7z-iterator 2.0.0 → 2.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/lib/defer.d.cts +1 -0
- package/dist/cjs/lib/defer.d.ts +1 -0
- package/dist/cjs/lib/defer.js +18 -0
- package/dist/cjs/lib/defer.js.map +1 -0
- package/dist/cjs/sevenz/ArchiveSource.d.cts +1 -0
- package/dist/cjs/sevenz/ArchiveSource.d.ts +1 -0
- package/dist/cjs/sevenz/ArchiveSource.js +23 -0
- package/dist/cjs/sevenz/ArchiveSource.js.map +1 -1
- package/dist/cjs/sevenz/SevenZipParser.js +27 -7
- package/dist/cjs/sevenz/SevenZipParser.js.map +1 -1
- package/dist/cjs/sevenz/constants.d.cts +1 -0
- package/dist/cjs/sevenz/constants.d.ts +1 -0
- package/dist/cjs/sevenz/constants.js +1 -0
- package/dist/cjs/sevenz/constants.js.map +1 -1
- package/dist/esm/lib/defer.d.ts +1 -0
- package/dist/esm/lib/defer.js +5 -0
- package/dist/esm/lib/defer.js.map +1 -0
- package/dist/esm/sevenz/ArchiveSource.d.ts +1 -0
- package/dist/esm/sevenz/ArchiveSource.js +23 -0
- package/dist/esm/sevenz/ArchiveSource.js.map +1 -1
- package/dist/esm/sevenz/SevenZipParser.js +27 -7
- package/dist/esm/sevenz/SevenZipParser.js.map +1 -1
- package/dist/esm/sevenz/constants.d.ts +1 -0
- package/dist/esm/sevenz/constants.js +1 -0
- package/dist/esm/sevenz/constants.js.map +1 -1
- package/package.json +1 -1
|
@@ -197,6 +197,7 @@ var ErrorCode = {
|
|
|
197
197
|
UNSUPPORTED_VERSION: 'UNSUPPORTED_VERSION',
|
|
198
198
|
UNSUPPORTED_FEATURE: 'UNSUPPORTED_FEATURE',
|
|
199
199
|
TRUNCATED_ARCHIVE: 'TRUNCATED_ARCHIVE',
|
|
200
|
+
CORRUPT_ARCHIVE: 'CORRUPT_ARCHIVE',
|
|
200
201
|
CORRUPT_HEADER: 'CORRUPT_HEADER',
|
|
201
202
|
ENCRYPTED_ARCHIVE: 'ENCRYPTED_ARCHIVE',
|
|
202
203
|
COMPRESSED_HEADER: 'COMPRESSED_HEADER',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/iterators/7z-iterator/src/sevenz/constants.ts"],"sourcesContent":["// 7z format constants\n// Reference: https://py7zr.readthedocs.io/en/latest/archive_format.html\n\n// 7z signature: '7z' + magic bytes\nexport const SEVENZ_MAGIC = [0x37, 0x7a, 0xbc, 0xaf, 0x27, 0x1c];\n\n// Header sizes\nexport const SIGNATURE_HEADER_SIZE = 32;\nexport const START_HEADER_SIZE = 20; // Part of signature header after magic + version\n\n// Property IDs for encoded header\nexport const PropertyId = {\n kEnd: 0x00,\n kHeader: 0x01,\n kArchiveProperties: 0x02,\n kAdditionalStreamsInfo: 0x03,\n kMainStreamsInfo: 0x04,\n kFilesInfo: 0x05,\n kPackInfo: 0x06,\n kUnpackInfo: 0x07,\n kSubStreamsInfo: 0x08,\n kSize: 0x09,\n kCRC: 0x0a,\n kFolder: 0x0b,\n kCodersUnpackSize: 0x0c,\n kNumUnpackStream: 0x0d,\n kEmptyStream: 0x0e,\n kEmptyFile: 0x0f,\n kAnti: 0x10,\n kName: 0x11,\n kCTime: 0x12,\n kATime: 0x13,\n kMTime: 0x14,\n kWinAttributes: 0x15,\n kComment: 0x16,\n kEncodedHeader: 0x17,\n kStartPos: 0x18,\n kDummy: 0x19,\n};\n\n// Codec IDs\n// 7z uses variable-length codec IDs\n// Reference: 7za i output shows hex codec IDs (e.g., 3030501 = ARM)\nexport const CodecId = {\n COPY: [0x00],\n DELTA: [0x03],\n LZMA: [0x03, 0x01, 0x01],\n LZMA2: [0x21],\n BCJ_X86: [0x03, 0x03, 0x01, 0x03],\n BCJ_PPC: [0x03, 0x03, 0x02, 0x05],\n BCJ_IA64: [0x03, 0x03, 0x04, 0x01],\n BCJ_ARM: [0x03, 0x03, 0x05, 0x01],\n BCJ_ARMT: [0x03, 0x03, 0x07, 0x01],\n BCJ_SPARC: [0x03, 0x03, 0x08, 0x05],\n BCJ_ARM64: [0x03, 0x03, 0x0a, 0x01],\n BCJ2: [0x03, 0x03, 0x01, 0x1b],\n PPMD: [0x03, 0x04, 0x01],\n DEFLATE: [0x04, 0x01, 0x08],\n BZIP2: [0x04, 0x02, 0x02],\n AES: [0x06, 0xf1, 0x07, 0x01],\n};\n\n// File attribute flags (Windows style, stored in FilesInfo)\nexport const FileAttribute = {\n READONLY: 0x01,\n HIDDEN: 0x02,\n SYSTEM: 0x04,\n DIRECTORY: 0x10,\n ARCHIVE: 0x20,\n DEVICE: 0x40,\n NORMAL: 0x80,\n TEMPORARY: 0x100,\n SPARSE_FILE: 0x200,\n REPARSE_POINT: 0x400,\n COMPRESSED: 0x800,\n OFFLINE: 0x1000,\n NOT_CONTENT_INDEXED: 0x2000,\n ENCRYPTED: 0x4000,\n UNIX_EXTENSION: 0x8000,\n};\n\n// Unix permission modes (decimal values for Node 0.8 compatibility)\nexport const UnixMode = {\n DIR: 16384, // 0o40000 - directory\n FILE: 32768, // 0o100000 - regular file\n SYMLINK: 40960, // 0o120000 - symbolic link\n RWXRWXRWX: 511, // 0o777\n RWXRXRX: 493, // 0o755\n RWRR: 420, // 0o644\n DEFAULT_DIR: 493, // 0o755 - rwxr-xr-x\n DEFAULT_FILE: 420, // 0o644 - rw-r--r--\n};\n\n// Error codes\nexport const ErrorCode = {\n INVALID_SIGNATURE: 'INVALID_SIGNATURE',\n CRC_MISMATCH: 'CRC_MISMATCH',\n UNSUPPORTED_CODEC: 'UNSUPPORTED_CODEC',\n UNSUPPORTED_VERSION: 'UNSUPPORTED_VERSION',\n UNSUPPORTED_FEATURE: 'UNSUPPORTED_FEATURE',\n TRUNCATED_ARCHIVE: 'TRUNCATED_ARCHIVE',\n CORRUPT_HEADER: 'CORRUPT_HEADER',\n ENCRYPTED_ARCHIVE: 'ENCRYPTED_ARCHIVE',\n COMPRESSED_HEADER: 'COMPRESSED_HEADER',\n DECOMPRESSION_FAILED: 'DECOMPRESSION_FAILED',\n};\n\n// Error with code property\nexport interface CodedError extends Error {\n code: string;\n}\n\n/**\n * Create an error with a code property\n */\nexport function createCodedError(message: string, code: string): CodedError {\n const err = new Error(message) as CodedError;\n err.code = code;\n return err;\n}\n"],"names":["CodecId","ErrorCode","FileAttribute","PropertyId","SEVENZ_MAGIC","SIGNATURE_HEADER_SIZE","START_HEADER_SIZE","UnixMode","createCodedError","kEnd","kHeader","kArchiveProperties","kAdditionalStreamsInfo","kMainStreamsInfo","kFilesInfo","kPackInfo","kUnpackInfo","kSubStreamsInfo","kSize","kCRC","kFolder","kCodersUnpackSize","kNumUnpackStream","kEmptyStream","kEmptyFile","kAnti","kName","kCTime","kATime","kMTime","kWinAttributes","kComment","kEncodedHeader","kStartPos","kDummy","COPY","DELTA","LZMA","LZMA2","BCJ_X86","BCJ_PPC","BCJ_IA64","BCJ_ARM","BCJ_ARMT","BCJ_SPARC","BCJ_ARM64","BCJ2","PPMD","DEFLATE","BZIP2","AES","READONLY","HIDDEN","SYSTEM","DIRECTORY","ARCHIVE","DEVICE","NORMAL","TEMPORARY","SPARSE_FILE","REPARSE_POINT","COMPRESSED","OFFLINE","NOT_CONTENT_INDEXED","ENCRYPTED","UNIX_EXTENSION","DIR","FILE","SYMLINK","RWXRWXRWX","RWXRXRX","RWRR","DEFAULT_DIR","DEFAULT_FILE","INVALID_SIGNATURE","CRC_MISMATCH","UNSUPPORTED_CODEC","UNSUPPORTED_VERSION","UNSUPPORTED_FEATURE","TRUNCATED_ARCHIVE","CORRUPT_HEADER","ENCRYPTED_ARCHIVE","COMPRESSED_HEADER","DECOMPRESSION_FAILED","message","code","err","Error"],"mappings":"AAAA,sBAAsB;AACtB,wEAAwE;AAExE,mCAAmC;;;;;;;;;;;;QAwCtBA;eAAAA;;QAmDAC;eAAAA;;QA/BAC;eAAAA;;QApDAC;eAAAA;;QAPAC;eAAAA;;QAGAC;eAAAA;;QACAC;eAAAA;;QA0EAC;eAAAA;;
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/iterators/7z-iterator/src/sevenz/constants.ts"],"sourcesContent":["// 7z format constants\n// Reference: https://py7zr.readthedocs.io/en/latest/archive_format.html\n\n// 7z signature: '7z' + magic bytes\nexport const SEVENZ_MAGIC = [0x37, 0x7a, 0xbc, 0xaf, 0x27, 0x1c];\n\n// Header sizes\nexport const SIGNATURE_HEADER_SIZE = 32;\nexport const START_HEADER_SIZE = 20; // Part of signature header after magic + version\n\n// Property IDs for encoded header\nexport const PropertyId = {\n kEnd: 0x00,\n kHeader: 0x01,\n kArchiveProperties: 0x02,\n kAdditionalStreamsInfo: 0x03,\n kMainStreamsInfo: 0x04,\n kFilesInfo: 0x05,\n kPackInfo: 0x06,\n kUnpackInfo: 0x07,\n kSubStreamsInfo: 0x08,\n kSize: 0x09,\n kCRC: 0x0a,\n kFolder: 0x0b,\n kCodersUnpackSize: 0x0c,\n kNumUnpackStream: 0x0d,\n kEmptyStream: 0x0e,\n kEmptyFile: 0x0f,\n kAnti: 0x10,\n kName: 0x11,\n kCTime: 0x12,\n kATime: 0x13,\n kMTime: 0x14,\n kWinAttributes: 0x15,\n kComment: 0x16,\n kEncodedHeader: 0x17,\n kStartPos: 0x18,\n kDummy: 0x19,\n};\n\n// Codec IDs\n// 7z uses variable-length codec IDs\n// Reference: 7za i output shows hex codec IDs (e.g., 3030501 = ARM)\nexport const CodecId = {\n COPY: [0x00],\n DELTA: [0x03],\n LZMA: [0x03, 0x01, 0x01],\n LZMA2: [0x21],\n BCJ_X86: [0x03, 0x03, 0x01, 0x03],\n BCJ_PPC: [0x03, 0x03, 0x02, 0x05],\n BCJ_IA64: [0x03, 0x03, 0x04, 0x01],\n BCJ_ARM: [0x03, 0x03, 0x05, 0x01],\n BCJ_ARMT: [0x03, 0x03, 0x07, 0x01],\n BCJ_SPARC: [0x03, 0x03, 0x08, 0x05],\n BCJ_ARM64: [0x03, 0x03, 0x0a, 0x01],\n BCJ2: [0x03, 0x03, 0x01, 0x1b],\n PPMD: [0x03, 0x04, 0x01],\n DEFLATE: [0x04, 0x01, 0x08],\n BZIP2: [0x04, 0x02, 0x02],\n AES: [0x06, 0xf1, 0x07, 0x01],\n};\n\n// File attribute flags (Windows style, stored in FilesInfo)\nexport const FileAttribute = {\n READONLY: 0x01,\n HIDDEN: 0x02,\n SYSTEM: 0x04,\n DIRECTORY: 0x10,\n ARCHIVE: 0x20,\n DEVICE: 0x40,\n NORMAL: 0x80,\n TEMPORARY: 0x100,\n SPARSE_FILE: 0x200,\n REPARSE_POINT: 0x400,\n COMPRESSED: 0x800,\n OFFLINE: 0x1000,\n NOT_CONTENT_INDEXED: 0x2000,\n ENCRYPTED: 0x4000,\n UNIX_EXTENSION: 0x8000,\n};\n\n// Unix permission modes (decimal values for Node 0.8 compatibility)\nexport const UnixMode = {\n DIR: 16384, // 0o40000 - directory\n FILE: 32768, // 0o100000 - regular file\n SYMLINK: 40960, // 0o120000 - symbolic link\n RWXRWXRWX: 511, // 0o777\n RWXRXRX: 493, // 0o755\n RWRR: 420, // 0o644\n DEFAULT_DIR: 493, // 0o755 - rwxr-xr-x\n DEFAULT_FILE: 420, // 0o644 - rw-r--r--\n};\n\n// Error codes\nexport const ErrorCode = {\n INVALID_SIGNATURE: 'INVALID_SIGNATURE',\n CRC_MISMATCH: 'CRC_MISMATCH',\n UNSUPPORTED_CODEC: 'UNSUPPORTED_CODEC',\n UNSUPPORTED_VERSION: 'UNSUPPORTED_VERSION',\n UNSUPPORTED_FEATURE: 'UNSUPPORTED_FEATURE',\n TRUNCATED_ARCHIVE: 'TRUNCATED_ARCHIVE',\n CORRUPT_ARCHIVE: 'CORRUPT_ARCHIVE',\n CORRUPT_HEADER: 'CORRUPT_HEADER',\n ENCRYPTED_ARCHIVE: 'ENCRYPTED_ARCHIVE',\n COMPRESSED_HEADER: 'COMPRESSED_HEADER',\n DECOMPRESSION_FAILED: 'DECOMPRESSION_FAILED',\n};\n\n// Error with code property\nexport interface CodedError extends Error {\n code: string;\n}\n\n/**\n * Create an error with a code property\n */\nexport function createCodedError(message: string, code: string): CodedError {\n const err = new Error(message) as CodedError;\n err.code = code;\n return err;\n}\n"],"names":["CodecId","ErrorCode","FileAttribute","PropertyId","SEVENZ_MAGIC","SIGNATURE_HEADER_SIZE","START_HEADER_SIZE","UnixMode","createCodedError","kEnd","kHeader","kArchiveProperties","kAdditionalStreamsInfo","kMainStreamsInfo","kFilesInfo","kPackInfo","kUnpackInfo","kSubStreamsInfo","kSize","kCRC","kFolder","kCodersUnpackSize","kNumUnpackStream","kEmptyStream","kEmptyFile","kAnti","kName","kCTime","kATime","kMTime","kWinAttributes","kComment","kEncodedHeader","kStartPos","kDummy","COPY","DELTA","LZMA","LZMA2","BCJ_X86","BCJ_PPC","BCJ_IA64","BCJ_ARM","BCJ_ARMT","BCJ_SPARC","BCJ_ARM64","BCJ2","PPMD","DEFLATE","BZIP2","AES","READONLY","HIDDEN","SYSTEM","DIRECTORY","ARCHIVE","DEVICE","NORMAL","TEMPORARY","SPARSE_FILE","REPARSE_POINT","COMPRESSED","OFFLINE","NOT_CONTENT_INDEXED","ENCRYPTED","UNIX_EXTENSION","DIR","FILE","SYMLINK","RWXRWXRWX","RWXRXRX","RWRR","DEFAULT_DIR","DEFAULT_FILE","INVALID_SIGNATURE","CRC_MISMATCH","UNSUPPORTED_CODEC","UNSUPPORTED_VERSION","UNSUPPORTED_FEATURE","TRUNCATED_ARCHIVE","CORRUPT_ARCHIVE","CORRUPT_HEADER","ENCRYPTED_ARCHIVE","COMPRESSED_HEADER","DECOMPRESSION_FAILED","message","code","err","Error"],"mappings":"AAAA,sBAAsB;AACtB,wEAAwE;AAExE,mCAAmC;;;;;;;;;;;;QAwCtBA;eAAAA;;QAmDAC;eAAAA;;QA/BAC;eAAAA;;QApDAC;eAAAA;;QAPAC;eAAAA;;QAGAC;eAAAA;;QACAC;eAAAA;;QA0EAC;eAAAA;;QAkCGC;eAAAA;;;AAhHT,IAAMJ,eAAe;IAAC;IAAM;IAAM;IAAM;IAAM;IAAM;CAAK;AAGzD,IAAMC,wBAAwB;AAC9B,IAAMC,oBAAoB,IAAI,iDAAiD;AAG/E,IAAMH,aAAa;IACxBM,MAAM;IACNC,SAAS;IACTC,oBAAoB;IACpBC,wBAAwB;IACxBC,kBAAkB;IAClBC,YAAY;IACZC,WAAW;IACXC,aAAa;IACbC,iBAAiB;IACjBC,OAAO;IACPC,MAAM;IACNC,SAAS;IACTC,mBAAmB;IACnBC,kBAAkB;IAClBC,cAAc;IACdC,YAAY;IACZC,OAAO;IACPC,OAAO;IACPC,QAAQ;IACRC,QAAQ;IACRC,QAAQ;IACRC,gBAAgB;IAChBC,UAAU;IACVC,gBAAgB;IAChBC,WAAW;IACXC,QAAQ;AACV;AAKO,IAAMlC,UAAU;IACrBmC,MAAM;QAAC;KAAK;IACZC,OAAO;QAAC;KAAK;IACbC,MAAM;QAAC;QAAM;QAAM;KAAK;IACxBC,OAAO;QAAC;KAAK;IACbC,SAAS;QAAC;QAAM;QAAM;QAAM;KAAK;IACjCC,SAAS;QAAC;QAAM;QAAM;QAAM;KAAK;IACjCC,UAAU;QAAC;QAAM;QAAM;QAAM;KAAK;IAClCC,SAAS;QAAC;QAAM;QAAM;QAAM;KAAK;IACjCC,UAAU;QAAC;QAAM;QAAM;QAAM;KAAK;IAClCC,WAAW;QAAC;QAAM;QAAM;QAAM;KAAK;IACnCC,WAAW;QAAC;QAAM;QAAM;QAAM;KAAK;IACnCC,MAAM;QAAC;QAAM;QAAM;QAAM;KAAK;IAC9BC,MAAM;QAAC;QAAM;QAAM;KAAK;IACxBC,SAAS;QAAC;QAAM;QAAM;KAAK;IAC3BC,OAAO;QAAC;QAAM;QAAM;KAAK;IACzBC,KAAK;QAAC;QAAM;QAAM;QAAM;KAAK;AAC/B;AAGO,IAAMhD,gBAAgB;IAC3BiD,UAAU;IACVC,QAAQ;IACRC,QAAQ;IACRC,WAAW;IACXC,SAAS;IACTC,QAAQ;IACRC,QAAQ;IACRC,WAAW;IACXC,aAAa;IACbC,eAAe;IACfC,YAAY;IACZC,SAAS;IACTC,qBAAqB;IACrBC,WAAW;IACXC,gBAAgB;AAClB;AAGO,IAAM1D,WAAW;IACtB2D,KAAK;IACLC,MAAM;IACNC,SAAS;IACTC,WAAW;IACXC,SAAS;IACTC,MAAM;IACNC,aAAa;IACbC,cAAc;AAChB;AAGO,IAAMxE,YAAY;IACvByE,mBAAmB;IACnBC,cAAc;IACdC,mBAAmB;IACnBC,qBAAqB;IACrBC,qBAAqB;IACrBC,mBAAmB;IACnBC,iBAAiB;IACjBC,gBAAgB;IAChBC,mBAAmB;IACnBC,mBAAmB;IACnBC,sBAAsB;AACxB;AAUO,SAAS5E,iBAAiB6E,OAAe,EAAEC,IAAY;IAC5D,IAAMC,MAAM,IAAIC,MAAMH;IACtBE,IAAID,IAAI,GAAGA;IACX,OAAOC;AACT"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const defer: (fn: () => void) => void;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// Yield to I/O: runs after pending I/O callbacks complete
|
|
2
|
+
// setImmediate (Node 0.10+) or setTimeout fallback (Node 0.8)
|
|
3
|
+
// Use this when other code may have scheduled I/O that must run first
|
|
4
|
+
// For "avoid Zalgo" (just need async), use process.nextTick instead
|
|
5
|
+
export const defer = typeof setImmediate !== 'undefined' ? setImmediate : (fn)=>setTimeout(fn, 0);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/iterators/7z-iterator/src/lib/defer.ts"],"sourcesContent":["// Yield to I/O: runs after pending I/O callbacks complete\n// setImmediate (Node 0.10+) or setTimeout fallback (Node 0.8)\n// Use this when other code may have scheduled I/O that must run first\n// For \"avoid Zalgo\" (just need async), use process.nextTick instead\nexport const defer: (fn: () => void) => void = typeof setImmediate !== 'undefined' ? setImmediate : (fn) => setTimeout(fn, 0);\n"],"names":["defer","setImmediate","fn","setTimeout"],"mappings":"AAAA,0DAA0D;AAC1D,8DAA8D;AAC9D,sEAAsE;AACtE,oEAAoE;AACpE,OAAO,MAAMA,QAAkC,OAAOC,iBAAiB,cAAcA,eAAe,CAACC,KAAOC,WAAWD,IAAI,GAAG"}
|
|
@@ -57,6 +57,29 @@ function createReadableStream(readFn) {
|
|
|
57
57
|
* More memory efficient for large archives.
|
|
58
58
|
*/ export class FileSource {
|
|
59
59
|
read(position, length) {
|
|
60
|
+
// Handle large reads by chunking to fit 32-bit signed int limit
|
|
61
|
+
const MAX_INT32 = 0x7fffffff; // 2,147,483,647 bytes (~2GB)
|
|
62
|
+
if (length <= MAX_INT32) {
|
|
63
|
+
return this.readChunk(position, length);
|
|
64
|
+
}
|
|
65
|
+
// For large reads, split into multiple chunks
|
|
66
|
+
const chunks = [];
|
|
67
|
+
let totalBytesRead = 0;
|
|
68
|
+
let currentPos = position;
|
|
69
|
+
while(totalBytesRead < length){
|
|
70
|
+
const remaining = length - totalBytesRead;
|
|
71
|
+
const chunkSize = Math.min(remaining, MAX_INT32);
|
|
72
|
+
const chunk = this.readChunk(currentPos, chunkSize);
|
|
73
|
+
chunks.push(chunk);
|
|
74
|
+
totalBytesRead += chunk.length;
|
|
75
|
+
currentPos += chunk.length;
|
|
76
|
+
if (chunk.length < chunkSize) {
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return Buffer.concat(chunks);
|
|
81
|
+
}
|
|
82
|
+
readChunk(position, length) {
|
|
60
83
|
const buf = allocBuffer(length);
|
|
61
84
|
const bytesRead = fs.readSync(this.fd, buf, 0, length, position);
|
|
62
85
|
if (bytesRead < length) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/iterators/7z-iterator/src/sevenz/ArchiveSource.ts"],"sourcesContent":["/**\n * ArchiveSource - Abstraction for reading 7z archive data\n *\n * Provides a common interface for reading archive data from either\n * a file descriptor or an in-memory buffer.\n */\n\nimport { allocBuffer, Readable } from 'extract-base-iterator';\nimport fs from 'fs';\nimport type Stream from 'stream';\n\n// Helper to create a Readable stream compatible with Node 0.8\nfunction createReadableStream(readFn: (stream: Stream.Readable) => void): Stream.Readable {\n const stream = new Readable();\n stream._read = function () {\n readFn(this);\n };\n return stream;\n}\n\n/**\n * Archive source abstraction - allows reading from file descriptor or buffer\n */\nexport interface ArchiveSource {\n read(position: number, length: number): Buffer;\n getSize(): number;\n close(): void;\n /**\n * Create a readable stream for a portion of the archive.\n * Used for streaming decompression.\n */\n createReadStream(offset: number, length: number): Stream.Readable;\n}\n\n/**\n * Buffer-based archive source\n *\n * Used when the entire archive is already in memory.\n */\nexport class BufferSource implements ArchiveSource {\n private buffer: Buffer;\n\n constructor(buffer: Buffer) {\n this.buffer = buffer;\n }\n\n read(position: number, length: number): Buffer {\n return this.buffer.slice(position, position + length);\n }\n\n getSize(): number {\n return this.buffer.length;\n }\n\n close(): void {\n // Nothing to close for buffer\n }\n\n /**\n * Create a readable stream for a portion of the buffer.\n * Streams the data in chunks to avoid blocking.\n */\n createReadStream(offset: number, length: number): Stream.Readable {\n const buffer = this.buffer;\n const end = Math.min(offset + length, buffer.length);\n let currentPos = offset;\n const chunkSize = 65536; // 64KB chunks\n\n return createReadableStream((stream) => {\n if (currentPos >= end) {\n stream.push(null);\n return;\n }\n\n const toRead = Math.min(chunkSize, end - currentPos);\n const chunk = buffer.slice(currentPos, currentPos + toRead);\n currentPos += toRead;\n stream.push(chunk);\n });\n }\n}\n\n/**\n * File descriptor based archive source\n *\n * Used for reading directly from a file on disk.\n * More memory efficient for large archives.\n */\nexport class FileSource implements ArchiveSource {\n private fd: number;\n private size: number;\n\n constructor(fd: number, size: number) {\n this.fd = fd;\n this.size = size;\n }\n\n read(position: number, length: number): Buffer {\n const buf = allocBuffer(length);\n const bytesRead = fs.readSync(this.fd, buf, 0, length, position);\n if (bytesRead < length) {\n return buf.slice(0, bytesRead);\n }\n return buf;\n }\n\n getSize(): number {\n return this.size;\n }\n\n close(): void {\n try {\n fs.closeSync(this.fd);\n } catch (_e) {\n // Ignore close errors\n }\n }\n\n /**\n * Create a readable stream for a portion of the file.\n * Uses async fs.read() to avoid blocking the event loop.\n */\n createReadStream(offset: number, length: number): Stream.Readable {\n const fd = this.fd;\n let bytesRead = 0;\n let reading = false;\n let finished = false;\n const chunkSize = 65536; // 64KB chunks\n let _streamRef: Stream.Readable | null = null;\n\n const stream = createReadableStream((s) => {\n _streamRef = s;\n if (reading || finished) return; // Prevent re-entrant reads\n\n const toRead = Math.min(chunkSize, length - bytesRead);\n if (toRead <= 0) {\n finished = true;\n s.push(null);\n return;\n }\n\n reading = true;\n const buffer = allocBuffer(toRead);\n const currentOffset = offset + bytesRead;\n\n fs.read(fd, buffer, 0, toRead, currentOffset, (err, n) => {\n reading = false;\n\n if (err) {\n // Emit error for Node 0.8 compatibility (no destroy method)\n s.emit('error', err);\n finished = true;\n s.push(null);\n return;\n }\n\n if (n === 0) {\n finished = true;\n s.push(null);\n } else {\n bytesRead += n;\n s.push(buffer.slice(0, n));\n }\n });\n });\n\n return stream;\n }\n}\n"],"names":["allocBuffer","Readable","fs","createReadableStream","readFn","stream","_read","BufferSource","read","position","length","buffer","slice","getSize","close","createReadStream","offset","end","Math","min","currentPos","chunkSize","push","toRead","chunk","FileSource","buf","bytesRead","readSync","fd","size","closeSync","_e","reading","finished","_streamRef","s","currentOffset","err","n","emit"],"mappings":"AAAA;;;;;CAKC,GAED,SAASA,WAAW,EAAEC,QAAQ,QAAQ,wBAAwB;AAC9D,OAAOC,QAAQ,KAAK;AAGpB,8DAA8D;AAC9D,SAASC,qBAAqBC,MAAyC;IACrE,MAAMC,SAAS,IAAIJ;IACnBI,OAAOC,KAAK,GAAG;QACbF,OAAO,IAAI;IACb;IACA,OAAOC;AACT;AAgBA;;;;CAIC,GACD,OAAO,MAAME;IAOXC,KAAKC,QAAgB,EAAEC,MAAc,EAAU;QAC7C,OAAO,IAAI,CAACC,MAAM,CAACC,KAAK,CAACH,UAAUA,WAAWC;IAChD;IAEAG,UAAkB;QAChB,OAAO,IAAI,CAACF,MAAM,CAACD,MAAM;IAC3B;IAEAI,QAAc;IACZ,8BAA8B;IAChC;IAEA;;;GAGC,GACDC,iBAAiBC,MAAc,EAAEN,MAAc,EAAmB;QAChE,MAAMC,SAAS,IAAI,CAACA,MAAM;QAC1B,MAAMM,MAAMC,KAAKC,GAAG,CAACH,SAASN,QAAQC,OAAOD,MAAM;QACnD,IAAIU,aAAaJ;QACjB,MAAMK,YAAY,OAAO,cAAc;QAEvC,OAAOlB,qBAAqB,CAACE;YAC3B,IAAIe,cAAcH,KAAK;gBACrBZ,OAAOiB,IAAI,CAAC;gBACZ;YACF;YAEA,MAAMC,SAASL,KAAKC,GAAG,CAACE,WAAWJ,MAAMG;YACzC,MAAMI,QAAQb,OAAOC,KAAK,CAACQ,YAAYA,aAAaG;YACpDH,cAAcG;YACdlB,OAAOiB,IAAI,CAACE;QACd;IACF;IArCA,YAAYb,MAAc,CAAE;QAC1B,IAAI,CAACA,MAAM,GAAGA;IAChB;AAoCF;AAEA;;;;;CAKC,GACD,OAAO,MAAMc;IASXjB,KAAKC,QAAgB,EAAEC,MAAc,EAAU;QAC7C,MAAMgB,
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/iterators/7z-iterator/src/sevenz/ArchiveSource.ts"],"sourcesContent":["/**\n * ArchiveSource - Abstraction for reading 7z archive data\n *\n * Provides a common interface for reading archive data from either\n * a file descriptor or an in-memory buffer.\n */\n\nimport { allocBuffer, Readable } from 'extract-base-iterator';\nimport fs from 'fs';\nimport type Stream from 'stream';\n\n// Helper to create a Readable stream compatible with Node 0.8\nfunction createReadableStream(readFn: (stream: Stream.Readable) => void): Stream.Readable {\n const stream = new Readable();\n stream._read = function () {\n readFn(this);\n };\n return stream;\n}\n\n/**\n * Archive source abstraction - allows reading from file descriptor or buffer\n */\nexport interface ArchiveSource {\n read(position: number, length: number): Buffer;\n getSize(): number;\n close(): void;\n /**\n * Create a readable stream for a portion of the archive.\n * Used for streaming decompression.\n */\n createReadStream(offset: number, length: number): Stream.Readable;\n}\n\n/**\n * Buffer-based archive source\n *\n * Used when the entire archive is already in memory.\n */\nexport class BufferSource implements ArchiveSource {\n private buffer: Buffer;\n\n constructor(buffer: Buffer) {\n this.buffer = buffer;\n }\n\n read(position: number, length: number): Buffer {\n return this.buffer.slice(position, position + length);\n }\n\n getSize(): number {\n return this.buffer.length;\n }\n\n close(): void {\n // Nothing to close for buffer\n }\n\n /**\n * Create a readable stream for a portion of the buffer.\n * Streams the data in chunks to avoid blocking.\n */\n createReadStream(offset: number, length: number): Stream.Readable {\n const buffer = this.buffer;\n const end = Math.min(offset + length, buffer.length);\n let currentPos = offset;\n const chunkSize = 65536; // 64KB chunks\n\n return createReadableStream((stream) => {\n if (currentPos >= end) {\n stream.push(null);\n return;\n }\n\n const toRead = Math.min(chunkSize, end - currentPos);\n const chunk = buffer.slice(currentPos, currentPos + toRead);\n currentPos += toRead;\n stream.push(chunk);\n });\n }\n}\n\n/**\n * File descriptor based archive source\n *\n * Used for reading directly from a file on disk.\n * More memory efficient for large archives.\n */\nexport class FileSource implements ArchiveSource {\n private fd: number;\n private size: number;\n\n constructor(fd: number, size: number) {\n this.fd = fd;\n this.size = size;\n }\n\n read(position: number, length: number): Buffer {\n // Handle large reads by chunking to fit 32-bit signed int limit\n const MAX_INT32 = 0x7fffffff; // 2,147,483,647 bytes (~2GB)\n\n if (length <= MAX_INT32) {\n return this.readChunk(position, length);\n }\n\n // For large reads, split into multiple chunks\n const chunks: Buffer[] = [];\n let totalBytesRead = 0;\n let currentPos = position;\n\n while (totalBytesRead < length) {\n const remaining = length - totalBytesRead;\n const chunkSize = Math.min(remaining, MAX_INT32);\n const chunk = this.readChunk(currentPos, chunkSize);\n\n chunks.push(chunk);\n totalBytesRead += chunk.length;\n currentPos += chunk.length;\n\n if (chunk.length < chunkSize) {\n // EOF reached\n break;\n }\n }\n\n return Buffer.concat(chunks);\n }\n\n private readChunk(position: number, length: number): Buffer {\n const buf = allocBuffer(length);\n const bytesRead = fs.readSync(this.fd, buf, 0, length, position);\n if (bytesRead < length) {\n return buf.slice(0, bytesRead);\n }\n return buf;\n }\n\n getSize(): number {\n return this.size;\n }\n\n close(): void {\n try {\n fs.closeSync(this.fd);\n } catch (_e) {\n // Ignore close errors\n }\n }\n\n /**\n * Create a readable stream for a portion of the file.\n * Uses async fs.read() to avoid blocking the event loop.\n */\n createReadStream(offset: number, length: number): Stream.Readable {\n const fd = this.fd;\n let bytesRead = 0;\n let reading = false;\n let finished = false;\n const chunkSize = 65536; // 64KB chunks\n let _streamRef: Stream.Readable | null = null;\n\n const stream = createReadableStream((s) => {\n _streamRef = s;\n if (reading || finished) return; // Prevent re-entrant reads\n\n const toRead = Math.min(chunkSize, length - bytesRead);\n if (toRead <= 0) {\n finished = true;\n s.push(null);\n return;\n }\n\n reading = true;\n const buffer = allocBuffer(toRead);\n const currentOffset = offset + bytesRead;\n\n fs.read(fd, buffer, 0, toRead, currentOffset, (err, n) => {\n reading = false;\n\n if (err) {\n // Emit error for Node 0.8 compatibility (no destroy method)\n s.emit('error', err);\n finished = true;\n s.push(null);\n return;\n }\n\n if (n === 0) {\n finished = true;\n s.push(null);\n } else {\n bytesRead += n;\n s.push(buffer.slice(0, n));\n }\n });\n });\n\n return stream;\n }\n}\n"],"names":["allocBuffer","Readable","fs","createReadableStream","readFn","stream","_read","BufferSource","read","position","length","buffer","slice","getSize","close","createReadStream","offset","end","Math","min","currentPos","chunkSize","push","toRead","chunk","FileSource","MAX_INT32","readChunk","chunks","totalBytesRead","remaining","Buffer","concat","buf","bytesRead","readSync","fd","size","closeSync","_e","reading","finished","_streamRef","s","currentOffset","err","n","emit"],"mappings":"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"}
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
* - Non-solid: one file per folder
|
|
18
18
|
* - Supports LZMA, LZMA2, COPY, BCJ2, and other codecs
|
|
19
19
|
*/ import { crc32, PassThrough } from 'extract-base-iterator';
|
|
20
|
+
import { defer } from '../lib/defer.js';
|
|
20
21
|
import { decodeBcj2Multi, getCodec, getCodecName, isBcj2Codec, isCodecSupported } from './codecs/index.js';
|
|
21
22
|
import { FolderStreamSplitter } from './FolderStreamSplitter.js';
|
|
22
23
|
import { createCodedError, ErrorCode, FileAttribute, PropertyId, SIGNATURE_HEADER_SIZE } from './constants.js';
|
|
@@ -400,7 +401,7 @@ export { BufferSource, FileSource } from './ArchiveSource.js';
|
|
|
400
401
|
stream._read = (size)=>{
|
|
401
402
|
if (!started && !destroyed) {
|
|
402
403
|
started = true;
|
|
403
|
-
|
|
404
|
+
defer(()=>{
|
|
404
405
|
if (destroyed) return;
|
|
405
406
|
try {
|
|
406
407
|
let crcValue = 0;
|
|
@@ -434,7 +435,7 @@ export { BufferSource, FileSource } from './ArchiveSource.js';
|
|
|
434
435
|
stream.destroy(err);
|
|
435
436
|
}
|
|
436
437
|
}
|
|
437
|
-
}
|
|
438
|
+
});
|
|
438
439
|
}
|
|
439
440
|
return originalRead(size);
|
|
440
441
|
};
|
|
@@ -469,7 +470,7 @@ export { BufferSource, FileSource } from './ArchiveSource.js';
|
|
|
469
470
|
stream._read = (size)=>{
|
|
470
471
|
if (!started && !destroyed) {
|
|
471
472
|
started = true;
|
|
472
|
-
|
|
473
|
+
defer(()=>{
|
|
473
474
|
if (destroyed) return;
|
|
474
475
|
try {
|
|
475
476
|
const data = this.getDecompressedFolder(folderIdx);
|
|
@@ -504,7 +505,7 @@ export { BufferSource, FileSource } from './ArchiveSource.js';
|
|
|
504
505
|
stream.destroy(err);
|
|
505
506
|
}
|
|
506
507
|
}
|
|
507
|
-
}
|
|
508
|
+
});
|
|
508
509
|
}
|
|
509
510
|
return originalRead(size);
|
|
510
511
|
};
|
|
@@ -559,17 +560,32 @@ export { BufferSource, FileSource } from './ArchiveSource.js';
|
|
|
559
560
|
return data;
|
|
560
561
|
}
|
|
561
562
|
// Calculate packed data position
|
|
562
|
-
|
|
563
|
+
// Use Math.max to prevent 32-bit signed overflow
|
|
564
|
+
const signedHeaderSize = SIGNATURE_HEADER_SIZE;
|
|
565
|
+
const signedPackPos = this.streamsInfo.packPos;
|
|
566
|
+
let packPos = Math.max(signedHeaderSize, 0) + Math.max(signedPackPos, 0);
|
|
563
567
|
// Find which pack stream this folder uses
|
|
564
568
|
let packStreamIndex = 0;
|
|
565
569
|
for(let j = 0; j < folderIndex; j++){
|
|
566
570
|
packStreamIndex += this.streamsInfo.folders[j].packedStreams.length;
|
|
567
571
|
}
|
|
568
|
-
// Calculate position of this pack stream
|
|
572
|
+
// Calculate position of this pack stream - PREVENT OVERFLOW
|
|
569
573
|
for(let k = 0; k < packStreamIndex; k++){
|
|
570
|
-
|
|
574
|
+
const size = this.streamsInfo.packSizes[k];
|
|
575
|
+
if (packPos + size < packPos) {
|
|
576
|
+
throw createCodedError(`Pack position overflow at index ${k}`, ErrorCode.CORRUPT_ARCHIVE);
|
|
577
|
+
}
|
|
578
|
+
packPos += size;
|
|
571
579
|
}
|
|
572
580
|
const packSize = this.streamsInfo.packSizes[packStreamIndex];
|
|
581
|
+
// Validate pack size to prevent overflow
|
|
582
|
+
// Upper bound is Number.MAX_SAFE_INTEGER (2^53-1 = 9PB) - safe for all realistic archives
|
|
583
|
+
if (packSize < 0 || packSize > Number.MAX_SAFE_INTEGER) {
|
|
584
|
+
throw createCodedError(`Invalid pack size: ${packSize}`, ErrorCode.CORRUPT_ARCHIVE);
|
|
585
|
+
}
|
|
586
|
+
if (packPos < 0 || packPos > Number.MAX_SAFE_INTEGER) {
|
|
587
|
+
throw createCodedError(`Invalid pack position: ${packPos}`, ErrorCode.CORRUPT_ARCHIVE);
|
|
588
|
+
}
|
|
573
589
|
// Read packed data
|
|
574
590
|
const packedData = this.source.read(packPos, packSize);
|
|
575
591
|
// Decompress through codec chain
|
|
@@ -579,6 +595,10 @@ export { BufferSource, FileSource } from './ArchiveSource.js';
|
|
|
579
595
|
const codec = getCodec(coderInfo.id);
|
|
580
596
|
// Get unpack size for this coder (needed by LZMA)
|
|
581
597
|
const unpackSize = folder.unpackSizes[l];
|
|
598
|
+
// Validate unpack size to prevent overflow
|
|
599
|
+
if (unpackSize < 0 || unpackSize > Number.MAX_SAFE_INTEGER) {
|
|
600
|
+
throw createCodedError(`Invalid unpack size: ${unpackSize}`, ErrorCode.CORRUPT_ARCHIVE);
|
|
601
|
+
}
|
|
582
602
|
data2 = codec.decode(data2, coderInfo.properties, unpackSize);
|
|
583
603
|
}
|
|
584
604
|
// Cache only if more files remain in this folder
|