* docs: prepare Vendoo 1.41.2 git-ignore boundary hotfix * fix: track native source modules with root-anchored runtime ignores
90 lines
2.9 KiB
JavaScript
90 lines
2.9 KiB
JavaScript
import { deflateRawSync } from 'zlib';
|
|
|
|
const CRC_TABLE = (() => {
|
|
const table = new Uint32Array(256);
|
|
for (let n = 0; n < 256; n++) {
|
|
let c = n;
|
|
for (let k = 0; k < 8; k++) c = (c & 1) ? (0xedb88320 ^ (c >>> 1)) : (c >>> 1);
|
|
table[n] = c >>> 0;
|
|
}
|
|
return table;
|
|
})();
|
|
|
|
function crc32(buffer) {
|
|
let crc = 0xffffffff;
|
|
for (const byte of buffer) crc = CRC_TABLE[(crc ^ byte) & 0xff] ^ (crc >>> 8);
|
|
return (crc ^ 0xffffffff) >>> 0;
|
|
}
|
|
|
|
function dosDateTime(date = new Date()) {
|
|
const year = Math.max(1980, date.getFullYear());
|
|
const time = (date.getHours() << 11) | (date.getMinutes() << 5) | Math.floor(date.getSeconds() / 2);
|
|
const day = date.getDate();
|
|
const month = date.getMonth() + 1;
|
|
const dosDate = ((year - 1980) << 9) | (month << 5) | day;
|
|
return { time, date: dosDate };
|
|
}
|
|
|
|
export function createZip(files) {
|
|
const localParts = [];
|
|
const centralParts = [];
|
|
let offset = 0;
|
|
const stamp = dosDateTime();
|
|
|
|
for (const file of files) {
|
|
const name = Buffer.from(String(file.name || 'file.bin').replace(/\\/g, '/'), 'utf8');
|
|
const data = Buffer.isBuffer(file.data) ? file.data : Buffer.from(file.data || '');
|
|
const compressed = deflateRawSync(data, { level: 6 });
|
|
const crc = crc32(data);
|
|
|
|
const local = Buffer.alloc(30);
|
|
local.writeUInt32LE(0x04034b50, 0);
|
|
local.writeUInt16LE(20, 4);
|
|
local.writeUInt16LE(0x0800, 6);
|
|
local.writeUInt16LE(8, 8);
|
|
local.writeUInt16LE(stamp.time, 10);
|
|
local.writeUInt16LE(stamp.date, 12);
|
|
local.writeUInt32LE(crc, 14);
|
|
local.writeUInt32LE(compressed.length, 18);
|
|
local.writeUInt32LE(data.length, 22);
|
|
local.writeUInt16LE(name.length, 26);
|
|
local.writeUInt16LE(0, 28);
|
|
localParts.push(local, name, compressed);
|
|
|
|
const central = Buffer.alloc(46);
|
|
central.writeUInt32LE(0x02014b50, 0);
|
|
central.writeUInt16LE(20, 4);
|
|
central.writeUInt16LE(20, 6);
|
|
central.writeUInt16LE(0x0800, 8);
|
|
central.writeUInt16LE(8, 10);
|
|
central.writeUInt16LE(stamp.time, 12);
|
|
central.writeUInt16LE(stamp.date, 14);
|
|
central.writeUInt32LE(crc, 16);
|
|
central.writeUInt32LE(compressed.length, 20);
|
|
central.writeUInt32LE(data.length, 24);
|
|
central.writeUInt16LE(name.length, 28);
|
|
central.writeUInt16LE(0, 30);
|
|
central.writeUInt16LE(0, 32);
|
|
central.writeUInt16LE(0, 34);
|
|
central.writeUInt16LE(0, 36);
|
|
central.writeUInt32LE(0, 38);
|
|
central.writeUInt32LE(offset, 42);
|
|
centralParts.push(central, name);
|
|
|
|
offset += local.length + name.length + compressed.length;
|
|
}
|
|
|
|
const centralDirectory = Buffer.concat(centralParts);
|
|
const end = Buffer.alloc(22);
|
|
end.writeUInt32LE(0x06054b50, 0);
|
|
end.writeUInt16LE(0, 4);
|
|
end.writeUInt16LE(0, 6);
|
|
end.writeUInt16LE(files.length, 8);
|
|
end.writeUInt16LE(files.length, 10);
|
|
end.writeUInt32LE(centralDirectory.length, 12);
|
|
end.writeUInt32LE(offset, 16);
|
|
end.writeUInt16LE(0, 20);
|
|
|
|
return Buffer.concat([...localParts, centralDirectory, end]);
|
|
}
|