local fs = require("@lune/fs") local stdio = require("@lune/stdio") local process = require("@lune/process") -- stylua: ignore local function createZip(version: number): buffer version = version or math.random(63, 100) print("Using version:", version) local data = buffer.create(98) local pos = 0 -- Local file header (30 bytes) buffer.writeu32(data, pos, 0x04034b50); pos += 4 print("Local header starts at:", 0) -- Track rest of local header position buffer.writeu16(data, pos, version); pos += 2 buffer.writeu16(data, pos, 0); pos += 2 -- flags buffer.writeu16(data, pos, 0); pos += 2 -- compression method buffer.writeu32(data, pos, 0); pos += 4 -- timestamp buffer.writeu32(data, pos, 0); pos += 4 -- crc32 buffer.writeu32(data, pos, 0); pos += 4 -- compressed size buffer.writeu32(data, pos, 0); pos += 4 -- uncompressed size buffer.writeu16(data, pos, 0); pos += 2 -- filename length buffer.writeu16(data, pos, 0); pos += 2 -- extra field length -- Central directory local cdOffset = pos print("CD fields:") buffer.writeu32(data, pos, 0x02014b50); pos += 4 -- signature print("- signature:", buffer.readu32(data, cdOffset)) buffer.writeu16(data, pos, 20); pos += 2 -- version made by print("- version made by:", buffer.readu16(data, cdOffset + 4)) buffer.writeu16(data, pos, version); pos += 2 -- version needed print("- version needed:", buffer.readu16(data, cdOffset + 6)) print("CD additional fields:") print("- flags:", buffer.readu16(data, cdOffset + 8)) print("- compression:", buffer.readu16(data, cdOffset + 10)) print("- local header offset:", buffer.readu32(data, cdOffset + 42)) buffer.writeu16(data, pos, 0); pos += 2 -- flags buffer.writeu16(data, pos, 0); pos += 2 -- compression buffer.writeu32(data, pos, 0); pos += 4 -- timestamp buffer.writeu32(data, pos, 0); pos += 4 -- crc32 buffer.writeu32(data, pos, 0); pos += 4 -- compressed size buffer.writeu32(data, pos, 0); pos += 4 -- uncompressed size buffer.writeu16(data, pos, 0); pos += 2 -- filename length buffer.writeu16(data, pos, 0); pos += 2 -- extra field length buffer.writeu16(data, pos, 0); pos += 2 -- comment length buffer.writeu16(data, pos, 0); pos += 2 -- disk number buffer.writeu16(data, pos, 0); pos += 2 -- internal attrs buffer.writeu32(data, pos, 0); pos += 4 -- external attrs buffer.writeu32(data, pos, 0); pos += 4 -- local header offset -- End of central directory print("EoCD fields:") buffer.writeu32(data, pos, 0x06054b50); pos += 4 -- signature buffer.writeu16(data, pos, 0); pos += 2 -- disk number buffer.writeu16(data, pos, 0); pos += 2 -- disk with cd buffer.writeu16(data, pos, 1); pos += 2 -- disk entries (1 file) print("- disk entries:", buffer.readu16(data, pos - 18)) buffer.writeu16(data, pos, 1); pos += 2 -- total entries (1 file) print("- total entries:", buffer.readu16(data, pos - 16)) buffer.writeu32(data, pos, 46); pos += 4 -- cd size (fixed size) print("- cd size:", buffer.readu32(data, pos - 14)) buffer.writeu32(data, pos, 30); pos += 4 -- cd offset (fixed offset) print("- cd offset:", buffer.readu32(data, pos - 10)) buffer.writeu16(data, pos, 0); pos += 2 -- comment length print("Final buffer size:", pos) local result = buffer.create(pos) buffer.copy(result, 0, data, 0, pos) return result end -- Write the invalid ZIP file local versionNum = assert(tonumber(process.args[1] or stdio.prompt("text", "Version number:"))) local zip = createZip(versionNum) fs.writeFile("tests/data/invalid_version.zip", zip) print(`Generated invalid_version.zip with version requirement {versionNum // 10}.{versionNum % 10}`)