v5.0.2: нативный ZIP (unzip + buildZip) — 0 внешних зависимостей, страница грузится мгновенно
Deploy drhider / validate (push) Waiting to run

This commit is contained in:
2026-07-12 14:48:59 +04:00
parent 75b8476703
commit 1a84770e82
3 changed files with 48 additions and 24 deletions
+1 -1
View File
@@ -20,7 +20,7 @@ if _sys_path_root not in sys.path:
sys.path.insert(0, _sys_path_root)
# Версия приложения (меняется при изменениях)
VERSION = "5.0.1"
VERSION = "5.0.2"
def create_app():
-13
View File
File diff suppressed because one or more lines are too long
+47 -10
View File
@@ -8,7 +8,6 @@
<meta http-equiv="Expires" content="0">
<title>DrHider — обфускация документов</title>
<link rel="icon" type="image/svg+xml" href="/static/favicon.svg">
<script src="/static/jszip.min.js"></script>
<style>
:root {
--brand-primary: #2563eb;
@@ -152,13 +151,53 @@ function ts() {
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() {
if (sf.length === 0) return;
ub.disabled = true;
const total = sf.length;
const tstamp = ts();
const maps = [];
const zip = new JSZip();
const zEntries = [];
let ok = 0, fail = 0;
for (let i = 0; i < total; i++) {
@@ -186,15 +225,13 @@ async function uploadFiles() {
});
clearInterval(timer);
const el = ((performance.now() - t0) / 1000).toFixed(1);
const iz = await JSZip.loadAsync(blob);
const ks = Object.keys(iz.files).filter(k => !iz.files[k].dir);
for (const k of ks) {
const d = await iz.files[k].async('blob');
if (k === 'mapping.csv') {
const t = await iz.files[k].async('string');
const files = await unzip(blob);
for (const [name, data] of Object.entries(files)) {
if (name === 'mapping.csv') {
const t = await data.text();
const ls = t.split('\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>');
ok++;
@@ -208,7 +245,7 @@ async function uploadFiles() {
if (ok > 0) {
st.className = 'status pack'; st.textContent = 'Упаковка...';
const zb = await zip.generateAsync({ type: 'blob' });
const zb = await buildZip(zEntries);
const u = URL.createObjectURL(zb);
const a = document.createElement('a'); a.href = u; a.download = 'drhider_' + tstamp + '.zip'; a.click();
URL.revokeObjectURL(u);