* Builds a minimal but well-formed ZIP buffer with a single file entry. * entryName may contain path traversal sequences (e.g. "../evil.txt") — adm-zip * normalises these away, so we hand-craft the bytes here.
(entryName: string, content = Buffer.alloc(0))
| 42 | * normalises these away, so we hand-craft the bytes here. |
| 43 | */ |
| 44 | function buildZipWithFileEntry(entryName: string, content = Buffer.alloc(0)): Buffer { |
| 45 | const nameBytes = Buffer.from(entryName) |
| 46 | const dataCrc = crc32(content) |
| 47 | |
| 48 | // Local file header (30 bytes + name) |
| 49 | const lfh = Buffer.alloc(30 + nameBytes.length) |
| 50 | lfh.writeUInt32LE(0x04034b50, 0) // PK\x03\x04 signature |
| 51 | lfh.writeUInt16LE(20, 4) // version needed to extract (2.0) |
| 52 | lfh.writeUInt32LE(dataCrc, 14) // crc-32 |
| 53 | lfh.writeUInt32LE(content.length, 18) // compressed size |
| 54 | lfh.writeUInt32LE(content.length, 22) // uncompressed size |
| 55 | lfh.writeUInt16LE(nameBytes.length, 26) // file name length |
| 56 | nameBytes.copy(lfh, 30) |
| 57 | |
| 58 | const centralDirOffset = lfh.length + content.length |
| 59 | |
| 60 | // Central directory header (46 bytes + name) |
| 61 | const cdh = Buffer.alloc(46 + nameBytes.length) |
| 62 | cdh.writeUInt32LE(0x02014b50, 0) // PK\x01\x02 signature |
| 63 | cdh.writeUInt16LE(20, 4) // version made by |
| 64 | cdh.writeUInt16LE(20, 6) // version needed |
| 65 | cdh.writeUInt32LE(dataCrc, 16) // crc-32 |
| 66 | cdh.writeUInt32LE(content.length, 20) // compressed size |
| 67 | cdh.writeUInt32LE(content.length, 24) // uncompressed size |
| 68 | cdh.writeUInt16LE(nameBytes.length, 28) // file name length |
| 69 | cdh.writeUInt32LE(0 /* local header offset */, 42) |
| 70 | nameBytes.copy(cdh, 46) |
| 71 | |
| 72 | // End of central directory record (22 bytes) |
| 73 | const eocd = Buffer.alloc(22) |
| 74 | eocd.writeUInt32LE(0x06054b50, 0) // PK\x05\x06 signature |
| 75 | eocd.writeUInt16LE(1, 8) // total entries on this disk |
| 76 | eocd.writeUInt16LE(1, 10) // total entries |
| 77 | eocd.writeUInt32LE(cdh.length, 12) // size of central dir |
| 78 | eocd.writeUInt32LE(centralDirOffset, 16) // offset of central dir from start of disk |
| 79 | |
| 80 | return Buffer.concat([lfh, content, cdh, eocd]) |
| 81 | } |
| 82 | |
| 83 | /** |
| 84 | * Builds a ZIP with a single Unix symlink entry. The symlink target is stored as the |
no test coverage detected