v5.0.2: нативный ZIP (unzip + buildZip) — 0 внешних зависимостей, страница грузится мгновенно
Deploy drhider / validate (push) Waiting to run
Deploy drhider / validate (push) Waiting to run
This commit is contained in:
+1
-1
@@ -20,7 +20,7 @@ if _sys_path_root not in sys.path:
|
|||||||
sys.path.insert(0, _sys_path_root)
|
sys.path.insert(0, _sys_path_root)
|
||||||
|
|
||||||
# Версия приложения (меняется при изменениях)
|
# Версия приложения (меняется при изменениях)
|
||||||
VERSION = "5.0.1"
|
VERSION = "5.0.2"
|
||||||
|
|
||||||
|
|
||||||
def create_app():
|
def create_app():
|
||||||
|
|||||||
Vendored
-13
File diff suppressed because one or more lines are too long
+47
-10
@@ -8,7 +8,6 @@
|
|||||||
<meta http-equiv="Expires" content="0">
|
<meta http-equiv="Expires" content="0">
|
||||||
<title>DrHider — обфускация документов</title>
|
<title>DrHider — обфускация документов</title>
|
||||||
<link rel="icon" type="image/svg+xml" href="/static/favicon.svg">
|
<link rel="icon" type="image/svg+xml" href="/static/favicon.svg">
|
||||||
<script src="/static/jszip.min.js"></script>
|
|
||||||
<style>
|
<style>
|
||||||
:root {
|
:root {
|
||||||
--brand-primary: #2563eb;
|
--brand-primary: #2563eb;
|
||||||
@@ -152,13 +151,53 @@ function ts() {
|
|||||||
|
|
||||||
function ss(idx, h) { const e = document.getElementById('st-' + idx); if (e) e.innerHTML = h; }
|
function ss(idx, h) { const e = document.getElementById('st-' + idx); if (e) e.innerHTML = h; }
|
||||||
|
|
||||||
|
// ═══════════ Нативный ZIP (без внешних библиотек) ═══════════
|
||||||
|
|
||||||
|
async function unzip(zb) {
|
||||||
|
const buf = await zb.arrayBuffer(); const dv = new DataView(buf);
|
||||||
|
const files = {}; let pos = 0;
|
||||||
|
while (pos < buf.byteLength - 4) {
|
||||||
|
const sig = dv.getUint32(pos, true);
|
||||||
|
if (sig === 0x04034b50) {
|
||||||
|
pos += 26; const nl = dv.getUint16(pos, true); pos += 2;
|
||||||
|
const el = dv.getUint16(pos, true); pos += 2;
|
||||||
|
const nm = new TextDecoder().decode(new Uint8Array(buf, pos, nl)); pos += nl + el;
|
||||||
|
const cs = dv.getUint32(pos - nl - el + 14, true);
|
||||||
|
files[nm] = new Blob([new Uint8Array(buf, pos, cs)]); pos += cs;
|
||||||
|
} else break;
|
||||||
|
}
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function buildZip(entries) {
|
||||||
|
const parts = []; const cd = []; let off = 0;
|
||||||
|
for (const e of entries) {
|
||||||
|
const d = new Uint8Array(await e.data.arrayBuffer());
|
||||||
|
const nm = new TextEncoder().encode(e.name);
|
||||||
|
const lh = new Uint8Array(30 + nm.length); const lv = new DataView(lh.buffer);
|
||||||
|
lv.setUint32(0, 0x04034b50, true); lv.setUint16(6, 0x800, true);
|
||||||
|
lv.setUint32(18, d.length, true); lv.setUint32(22, d.length, true);
|
||||||
|
lv.setUint16(26, nm.length, true); lh.set(nm, 30); parts.push(lh, d);
|
||||||
|
const ce = new Uint8Array(46 + nm.length); const cv = new DataView(ce.buffer);
|
||||||
|
cv.setUint32(0, 0x02014b50, true); cv.setUint16(8, 0x800, true);
|
||||||
|
cv.setUint32(20, d.length, true); cv.setUint32(24, d.length, true);
|
||||||
|
cv.setUint16(28, nm.length, true); cv.setUint32(42, off, true); ce.set(nm, 46); cd.push(ce);
|
||||||
|
off += 30 + nm.length + d.length;
|
||||||
|
}
|
||||||
|
const cs = cd.reduce((s, c) => s + c.length, 0);
|
||||||
|
const eo = new Uint8Array(22); const ev = new DataView(eo.buffer);
|
||||||
|
ev.setUint32(0, 0x06054b50, true); ev.setUint16(8, entries.length, true);
|
||||||
|
ev.setUint16(10, entries.length, true); ev.setUint32(12, cs, true); ev.setUint32(16, off, true);
|
||||||
|
return new Blob([...parts, ...cd, eo], { type: 'application/zip' });
|
||||||
|
}
|
||||||
|
|
||||||
async function uploadFiles() {
|
async function uploadFiles() {
|
||||||
if (sf.length === 0) return;
|
if (sf.length === 0) return;
|
||||||
ub.disabled = true;
|
ub.disabled = true;
|
||||||
const total = sf.length;
|
const total = sf.length;
|
||||||
const tstamp = ts();
|
const tstamp = ts();
|
||||||
const maps = [];
|
const maps = [];
|
||||||
const zip = new JSZip();
|
const zEntries = [];
|
||||||
let ok = 0, fail = 0;
|
let ok = 0, fail = 0;
|
||||||
|
|
||||||
for (let i = 0; i < total; i++) {
|
for (let i = 0; i < total; i++) {
|
||||||
@@ -186,15 +225,13 @@ async function uploadFiles() {
|
|||||||
});
|
});
|
||||||
clearInterval(timer);
|
clearInterval(timer);
|
||||||
const el = ((performance.now() - t0) / 1000).toFixed(1);
|
const el = ((performance.now() - t0) / 1000).toFixed(1);
|
||||||
const iz = await JSZip.loadAsync(blob);
|
const files = await unzip(blob);
|
||||||
const ks = Object.keys(iz.files).filter(k => !iz.files[k].dir);
|
for (const [name, data] of Object.entries(files)) {
|
||||||
for (const k of ks) {
|
if (name === 'mapping.csv') {
|
||||||
const d = await iz.files[k].async('blob');
|
const t = await data.text();
|
||||||
if (k === 'mapping.csv') {
|
|
||||||
const t = await iz.files[k].async('string');
|
|
||||||
const ls = t.split('\n');
|
const ls = t.split('\n');
|
||||||
maps.push(maps.length === 0 ? ls.join('\n') : ls.slice(1).join('\n'));
|
maps.push(maps.length === 0 ? ls.join('\n') : ls.slice(1).join('\n'));
|
||||||
} else { zip.file(k, d); }
|
} else { zEntries.push({ name, data }); }
|
||||||
}
|
}
|
||||||
ss(i, '<span style="color:#22c55e">✓ ' + el + 'с</span>');
|
ss(i, '<span style="color:#22c55e">✓ ' + el + 'с</span>');
|
||||||
ok++;
|
ok++;
|
||||||
@@ -208,7 +245,7 @@ async function uploadFiles() {
|
|||||||
|
|
||||||
if (ok > 0) {
|
if (ok > 0) {
|
||||||
st.className = 'status pack'; st.textContent = 'Упаковка...';
|
st.className = 'status pack'; st.textContent = 'Упаковка...';
|
||||||
const zb = await zip.generateAsync({ type: 'blob' });
|
const zb = await buildZip(zEntries);
|
||||||
const u = URL.createObjectURL(zb);
|
const u = URL.createObjectURL(zb);
|
||||||
const a = document.createElement('a'); a.href = u; a.download = 'drhider_' + tstamp + '.zip'; a.click();
|
const a = document.createElement('a'); a.href = u; a.download = 'drhider_' + tstamp + '.zip'; a.click();
|
||||||
URL.revokeObjectURL(u);
|
URL.revokeObjectURL(u);
|
||||||
|
|||||||
Reference in New Issue
Block a user