Files
Simon James b54a3139c7 Initial commit: Qortal Web Builder monorepo.
Includes QWB, Qortal Web, and Q-Shops Q-Apps with shared packages and build scripts.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-09 12:17:29 +00:00

145 lines
4.4 KiB
JavaScript

/**
* Minimal ZIP (STORE / no compression) for browser — one dependency-free helper
* so PUBLISH_QDN_RESOURCE can ship WEBSITE/APP archives from this Q-App.
*/
(function (global) {
'use strict';
const crcTable = (function makeTable() {
const t = new Uint32Array(256);
for (let i = 0; i < 256; i++) {
let c = i;
for (let k = 0; k < 8; k++) c = (c & 1) ? (0xedb88320 ^ (c >>> 1)) : (c >>> 1);
t[i] = c >>> 0;
}
return t;
})();
function crc32(buf) {
let c = 0xffffffff;
for (let i = 0; i < buf.length; i++) c = crcTable[(c ^ buf[i]) & 0xff] ^ (c >>> 8);
return (c ^ 0xffffffff) >>> 0;
}
function strToUtf8(s) {
return new TextEncoder().encode(String(s));
}
/** @param {Record<string, Uint8Array|string>} files map path -> bytes or utf8 string */
function buildZipStore(files) {
const entries = Object.keys(files).map((name) => {
const raw = files[name];
const data = raw instanceof Uint8Array ? raw : strToUtf8(raw);
return { name, data };
});
let offset = 0;
const parts = [];
const central = [];
for (const e of entries) {
const nameBytes = strToUtf8(e.name);
const nameLen = nameBytes.length;
const data = e.data;
const size = data.length;
const crc = crc32(data);
const sig = 0x04034b50;
const ver = 20;
const flags = 0;
const method = 0;
const time = 0;
const date = 0;
const csize = size;
const hlen = 30 + nameLen;
const local = new DataView(new ArrayBuffer(hlen + size));
let p = 0;
local.setUint32(p, sig, true); p += 4;
local.setUint16(p, ver, true); p += 2;
local.setUint16(p, flags, true); p += 2;
local.setUint16(p, method, true); p += 2;
local.setUint16(p, time, true); p += 2;
local.setUint16(p, date, true); p += 2;
local.setUint32(p, crc, true); p += 4;
local.setUint32(p, csize, true); p += 4;
local.setUint32(p, size, true); p += 4;
local.setUint16(p, nameLen, true); p += 2;
local.setUint16(p, 0, true); p += 2;
new Uint8Array(local.buffer).set(nameBytes, p);
p += nameLen;
new Uint8Array(local.buffer).set(data, p);
parts.push(new Uint8Array(local.buffer));
central.push({
nameBytes,
crc,
size,
csize,
localOffset: offset,
});
offset += local.buffer.byteLength;
}
const cdParts = [];
let cdSize = 0;
let cdOffset = offset;
for (let i = 0; i < central.length; i++) {
const c = central[i];
const nameLen = c.nameBytes.length;
const hlen = 46 + nameLen;
const buf = new DataView(new ArrayBuffer(46));
let q = 0;
buf.setUint32(q, 0x02014b50, true); q += 4;
buf.setUint16(q, 20, true); q += 2;
buf.setUint16(q, 20, true); q += 2;
buf.setUint16(q, 0, true); q += 2;
buf.setUint16(q, 0, true); q += 2;
buf.setUint16(q, 0, true); q += 2;
buf.setUint16(q, 0, true); q += 2;
buf.setUint32(q, c.crc, true); q += 4;
buf.setUint32(q, c.csize, true); q += 4;
buf.setUint32(q, c.size, true); q += 4;
buf.setUint16(q, nameLen, true); q += 2;
buf.setUint16(q, 0, true); q += 2;
buf.setUint16(q, 0, true); q += 2;
buf.setUint16(q, 0, true); q += 2;
buf.setUint16(q, 0, true); q += 2;
buf.setUint32(q, 0, true); q += 4;
buf.setUint32(q, c.localOffset, true); q += 4;
const header = new Uint8Array(buf.buffer);
const merged = new Uint8Array(hlen);
merged.set(header, 0);
merged.set(c.nameBytes, 46);
cdParts.push(merged);
cdSize += merged.length;
}
const eoc = new DataView(new ArrayBuffer(22));
eoc.setUint32(0, 0x06054b50, true);
eoc.setUint16(4, 0, true);
eoc.setUint16(6, 0, true);
eoc.setUint16(8, entries.length, true);
eoc.setUint16(10, entries.length, true);
eoc.setUint32(12, cdSize, true);
eoc.setUint32(16, cdOffset, true);
eoc.setUint16(20, 0, true);
const totalLen = offset + cdSize + 22;
const out = new Uint8Array(totalLen);
let o = 0;
for (const part of parts) {
out.set(part, o);
o += part.length;
}
for (const part of cdParts) {
out.set(part, o);
o += part.length;
}
out.set(new Uint8Array(eoc.buffer), o);
return out;
}
global.buildZipStore = buildZipStore;
})(typeof window !== 'undefined' ? window : globalThis);