diff --git a/network-poc/static/index.html b/network-poc/static/index.html index ee83c0d..a91819d 100644 --- a/network-poc/static/index.html +++ b/network-poc/static/index.html @@ -1989,7 +1989,18 @@ if (!card) return; const files = projectFiles[cardId]; - // Luodaan ZIP ilman ulkoisia kirjastoja (yksinkertainen uncompressed ZIP) + // CRC-32 laskenta ZIP-tiedostoille + function crc32(bytes) { + let crc = 0xFFFFFFFF; + for (let i = 0; i < bytes.length; i++) { + crc ^= bytes[i]; + for (let j = 0; j < 8; j++) { + crc = (crc >>> 1) ^ (crc & 1 ? 0xEDB88320 : 0); + } + } + return (crc ^ 0xFFFFFFFF) >>> 0; + } + const entries = Object.entries(files); const parts = []; const centralDir = []; @@ -1998,6 +2009,7 @@ for (const [name, content] of entries) { const nameBytes = new TextEncoder().encode(name); const contentBytes = new TextEncoder().encode(content); + const crc = crc32(contentBytes); // Local file header const header = new Uint8Array(30 + nameBytes.length); @@ -2005,8 +2017,9 @@ view.setUint32(0, 0x04034b50, true); // Signature view.setUint16(4, 20, true); // Version needed view.setUint16(8, 0, true); // Method: store - view.setUint32(18, contentBytes.length, true); // Compressed size - view.setUint32(22, contentBytes.length, true); // Uncompressed size + view.setUint32(14, crc, true); // CRC-32 + view.setUint32(18, contentBytes.length, true); + view.setUint32(22, contentBytes.length, true); view.setUint16(26, nameBytes.length, true); header.set(nameBytes, 30); @@ -2016,6 +2029,7 @@ cdView.setUint32(0, 0x02014b50, true); cdView.setUint16(4, 20, true); cdView.setUint16(6, 20, true); + cdView.setUint32(16, crc, true); // CRC-32 cdView.setUint32(20, contentBytes.length, true); cdView.setUint32(24, contentBytes.length, true); cdView.setUint16(28, nameBytes.length, true);