7z-iterator 0.1.0
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/LICENSE +42 -0
- package/README.md +142 -0
- package/dist/cjs/FileEntry.d.cts +12 -0
- package/dist/cjs/FileEntry.d.ts +12 -0
- package/dist/cjs/FileEntry.js +147 -0
- package/dist/cjs/FileEntry.js.map +1 -0
- package/dist/cjs/SevenZipIterator.d.cts +8 -0
- package/dist/cjs/SevenZipIterator.d.ts +8 -0
- package/dist/cjs/SevenZipIterator.js +204 -0
- package/dist/cjs/SevenZipIterator.js.map +1 -0
- package/dist/cjs/index.d.cts +4 -0
- package/dist/cjs/index.d.ts +4 -0
- package/dist/cjs/index.js +40 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/lib/Lock.d.cts +11 -0
- package/dist/cjs/lib/Lock.d.ts +11 -0
- package/dist/cjs/lib/Lock.js +65 -0
- package/dist/cjs/lib/Lock.js.map +1 -0
- package/dist/cjs/lib/streamToSource.d.cts +20 -0
- package/dist/cjs/lib/streamToSource.d.ts +20 -0
- package/dist/cjs/lib/streamToSource.js +116 -0
- package/dist/cjs/lib/streamToSource.js.map +1 -0
- package/dist/cjs/nextEntry.d.cts +4 -0
- package/dist/cjs/nextEntry.d.ts +4 -0
- package/dist/cjs/nextEntry.js +102 -0
- package/dist/cjs/nextEntry.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/sevenz/NumberCodec.d.cts +58 -0
- package/dist/cjs/sevenz/NumberCodec.d.ts +58 -0
- package/dist/cjs/sevenz/NumberCodec.js +133 -0
- package/dist/cjs/sevenz/NumberCodec.js.map +1 -0
- package/dist/cjs/sevenz/SevenZipParser.d.cts +96 -0
- package/dist/cjs/sevenz/SevenZipParser.d.ts +96 -0
- package/dist/cjs/sevenz/SevenZipParser.js +457 -0
- package/dist/cjs/sevenz/SevenZipParser.js.map +1 -0
- package/dist/cjs/sevenz/codecs/Aes.d.cts +22 -0
- package/dist/cjs/sevenz/codecs/Aes.d.ts +22 -0
- package/dist/cjs/sevenz/codecs/Aes.js +179 -0
- package/dist/cjs/sevenz/codecs/Aes.js.map +1 -0
- package/dist/cjs/sevenz/codecs/BZip2.d.cts +14 -0
- package/dist/cjs/sevenz/codecs/BZip2.d.ts +14 -0
- package/dist/cjs/sevenz/codecs/BZip2.js +37 -0
- package/dist/cjs/sevenz/codecs/BZip2.js.map +1 -0
- package/dist/cjs/sevenz/codecs/Bcj.d.cts +15 -0
- package/dist/cjs/sevenz/codecs/Bcj.d.ts +15 -0
- package/dist/cjs/sevenz/codecs/Bcj.js +89 -0
- package/dist/cjs/sevenz/codecs/Bcj.js.map +1 -0
- package/dist/cjs/sevenz/codecs/Copy.d.cts +14 -0
- package/dist/cjs/sevenz/codecs/Copy.d.ts +14 -0
- package/dist/cjs/sevenz/codecs/Copy.js +28 -0
- package/dist/cjs/sevenz/codecs/Copy.js.map +1 -0
- package/dist/cjs/sevenz/codecs/Deflate.d.cts +14 -0
- package/dist/cjs/sevenz/codecs/Deflate.d.ts +14 -0
- package/dist/cjs/sevenz/codecs/Deflate.js +39 -0
- package/dist/cjs/sevenz/codecs/Deflate.js.map +1 -0
- package/dist/cjs/sevenz/codecs/Delta.d.cts +15 -0
- package/dist/cjs/sevenz/codecs/Delta.d.ts +15 -0
- package/dist/cjs/sevenz/codecs/Delta.js +55 -0
- package/dist/cjs/sevenz/codecs/Delta.js.map +1 -0
- package/dist/cjs/sevenz/codecs/Lzma.d.cts +14 -0
- package/dist/cjs/sevenz/codecs/Lzma.d.ts +14 -0
- package/dist/cjs/sevenz/codecs/Lzma.js +53 -0
- package/dist/cjs/sevenz/codecs/Lzma.js.map +1 -0
- package/dist/cjs/sevenz/codecs/Lzma2.d.cts +14 -0
- package/dist/cjs/sevenz/codecs/Lzma2.d.ts +14 -0
- package/dist/cjs/sevenz/codecs/Lzma2.js +160 -0
- package/dist/cjs/sevenz/codecs/Lzma2.js.map +1 -0
- package/dist/cjs/sevenz/codecs/createBufferingDecoder.d.cts +7 -0
- package/dist/cjs/sevenz/codecs/createBufferingDecoder.d.ts +7 -0
- package/dist/cjs/sevenz/codecs/createBufferingDecoder.js +36 -0
- package/dist/cjs/sevenz/codecs/createBufferingDecoder.js.map +1 -0
- package/dist/cjs/sevenz/codecs/index.d.cts +24 -0
- package/dist/cjs/sevenz/codecs/index.d.ts +24 -0
- package/dist/cjs/sevenz/codecs/index.js +128 -0
- package/dist/cjs/sevenz/codecs/index.js.map +1 -0
- package/dist/cjs/sevenz/codecs/streams.d.cts +18 -0
- package/dist/cjs/sevenz/codecs/streams.d.ts +18 -0
- package/dist/cjs/sevenz/codecs/streams.js +79 -0
- package/dist/cjs/sevenz/codecs/streams.js.map +1 -0
- package/dist/cjs/sevenz/constants.d.cts +86 -0
- package/dist/cjs/sevenz/constants.d.ts +86 -0
- package/dist/cjs/sevenz/constants.js +162 -0
- package/dist/cjs/sevenz/constants.js.map +1 -0
- package/dist/cjs/sevenz/headers.d.cts +70 -0
- package/dist/cjs/sevenz/headers.d.ts +70 -0
- package/dist/cjs/sevenz/headers.js +661 -0
- package/dist/cjs/sevenz/headers.js.map +1 -0
- package/dist/cjs/sevenz/index.d.cts +4 -0
- package/dist/cjs/sevenz/index.d.ts +4 -0
- package/dist/cjs/sevenz/index.js +33 -0
- package/dist/cjs/sevenz/index.js.map +1 -0
- package/dist/cjs/types.d.cts +37 -0
- package/dist/cjs/types.d.ts +37 -0
- package/dist/cjs/types.js +32 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/esm/FileEntry.d.ts +12 -0
- package/dist/esm/FileEntry.js +63 -0
- package/dist/esm/FileEntry.js.map +1 -0
- package/dist/esm/SevenZipIterator.d.ts +8 -0
- package/dist/esm/SevenZipIterator.js +116 -0
- package/dist/esm/SevenZipIterator.js.map +1 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/lib/Lock.d.ts +11 -0
- package/dist/esm/lib/Lock.js +41 -0
- package/dist/esm/lib/Lock.js.map +1 -0
- package/dist/esm/lib/streamToSource.d.ts +20 -0
- package/dist/esm/lib/streamToSource.js +100 -0
- package/dist/esm/lib/streamToSource.js.map +1 -0
- package/dist/esm/nextEntry.d.ts +4 -0
- package/dist/esm/nextEntry.js +86 -0
- package/dist/esm/nextEntry.js.map +1 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/sevenz/NumberCodec.d.ts +58 -0
- package/dist/esm/sevenz/NumberCodec.js +138 -0
- package/dist/esm/sevenz/NumberCodec.js.map +1 -0
- package/dist/esm/sevenz/SevenZipParser.d.ts +96 -0
- package/dist/esm/sevenz/SevenZipParser.js +419 -0
- package/dist/esm/sevenz/SevenZipParser.js.map +1 -0
- package/dist/esm/sevenz/codecs/Aes.d.ts +22 -0
- package/dist/esm/sevenz/codecs/Aes.js +162 -0
- package/dist/esm/sevenz/codecs/Aes.js.map +1 -0
- package/dist/esm/sevenz/codecs/BZip2.d.ts +14 -0
- package/dist/esm/sevenz/codecs/BZip2.js +22 -0
- package/dist/esm/sevenz/codecs/BZip2.js.map +1 -0
- package/dist/esm/sevenz/codecs/Bcj.d.ts +15 -0
- package/dist/esm/sevenz/codecs/Bcj.js +75 -0
- package/dist/esm/sevenz/codecs/Bcj.js.map +1 -0
- package/dist/esm/sevenz/codecs/Copy.d.ts +14 -0
- package/dist/esm/sevenz/codecs/Copy.js +18 -0
- package/dist/esm/sevenz/codecs/Copy.js.map +1 -0
- package/dist/esm/sevenz/codecs/Deflate.d.ts +14 -0
- package/dist/esm/sevenz/codecs/Deflate.js +24 -0
- package/dist/esm/sevenz/codecs/Deflate.js.map +1 -0
- package/dist/esm/sevenz/codecs/Delta.d.ts +15 -0
- package/dist/esm/sevenz/codecs/Delta.js +41 -0
- package/dist/esm/sevenz/codecs/Delta.js.map +1 -0
- package/dist/esm/sevenz/codecs/Lzma.d.ts +14 -0
- package/dist/esm/sevenz/codecs/Lzma.js +38 -0
- package/dist/esm/sevenz/codecs/Lzma.js.map +1 -0
- package/dist/esm/sevenz/codecs/Lzma2.d.ts +14 -0
- package/dist/esm/sevenz/codecs/Lzma2.js +145 -0
- package/dist/esm/sevenz/codecs/Lzma2.js.map +1 -0
- package/dist/esm/sevenz/codecs/createBufferingDecoder.d.ts +7 -0
- package/dist/esm/sevenz/codecs/createBufferingDecoder.js +25 -0
- package/dist/esm/sevenz/codecs/createBufferingDecoder.js.map +1 -0
- package/dist/esm/sevenz/codecs/index.d.ts +24 -0
- package/dist/esm/sevenz/codecs/index.js +108 -0
- package/dist/esm/sevenz/codecs/index.js.map +1 -0
- package/dist/esm/sevenz/codecs/streams.d.ts +18 -0
- package/dist/esm/sevenz/codecs/streams.js +66 -0
- package/dist/esm/sevenz/codecs/streams.js.map +1 -0
- package/dist/esm/sevenz/constants.d.ts +86 -0
- package/dist/esm/sevenz/constants.js +131 -0
- package/dist/esm/sevenz/constants.js.map +1 -0
- package/dist/esm/sevenz/headers.d.ts +70 -0
- package/dist/esm/sevenz/headers.js +646 -0
- package/dist/esm/sevenz/headers.js.map +1 -0
- package/dist/esm/sevenz/index.d.ts +4 -0
- package/dist/esm/sevenz/index.js +5 -0
- package/dist/esm/sevenz/index.js.map +1 -0
- package/dist/esm/types.d.ts +37 -0
- package/dist/esm/types.js +2 -0
- package/dist/esm/types.js.map +1 -0
- package/package.json +77 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/iterators/7z-iterator/src/sevenz/NumberCodec.ts"],"sourcesContent":["// Variable-length integer encoding for 7z format\n// Reference: https://py7zr.readthedocs.io/en/latest/archive_format.html\n//\n// 7z uses a space-efficient encoding where the first byte determines length:\n// 0xxxxxxx -> 1 byte (0-127)\n// 10xxxxxx xxxxxxxx -> 2 bytes (0-16383)\n// 110xxxxx + 2 bytes -> 3 bytes\n// 1110xxxx + 3 bytes -> 4 bytes\n// 11110xxx + 4 bytes -> 5 bytes\n// 111110xx + 5 bytes -> 6 bytes\n// 1111110x + 6 bytes -> 7 bytes\n// 11111110 + 7 bytes -> 8 bytes\n// 11111111 + 8 bytes -> 9 bytes (full 64-bit)\n//\n// NOTE: Returns JavaScript number which is accurate up to 2^53 - 1 (~9 PB).\n// This covers all practical file sizes.\n\nimport { readUInt64LE } from 'extract-base-iterator';\n\nexport interface NumberReadResult {\n value: number;\n bytesRead: number;\n}\n\n/**\n * Read a variable-length encoded number from a buffer\n * @param buf - Buffer containing encoded number\n * @param offset - Offset to start reading from\n * @returns Object with value and number of bytes consumed\n */\nexport function readNumber(buf: Buffer, offset: number): NumberReadResult {\n var firstByte = buf[offset];\n\n // Count leading 1 bits to determine extra bytes\n var mask = 0x80;\n var extraBytes = 0;\n\n while ((firstByte & mask) !== 0 && extraBytes < 8) {\n extraBytes++;\n mask = mask >>> 1;\n }\n\n // Special case: all 8 bits set means 8 extra bytes\n if (extraBytes === 8) {\n // Full 64-bit value follows\n return {\n value: readUInt64LE(buf, offset + 1),\n bytesRead: 9,\n };\n }\n\n // Mask off the length bits from first byte\n var value = firstByte & ((mask - 1) | mask);\n\n // Add remaining bytes (big-endian order)\n for (var i = 0; i < extraBytes; i++) {\n value = value * 256 + buf[offset + 1 + i];\n }\n\n return {\n value: value,\n bytesRead: 1 + extraBytes,\n };\n}\n\n/**\n * Read a raw 64-bit little-endian number (used in some fixed-size fields)\n * @param buf - Buffer containing the number\n * @param offset - Offset to start reading from\n * @returns The number value\n */\nexport function readRawNumber(buf: Buffer, offset: number): number {\n return readUInt64LE(buf, offset);\n}\n\n/**\n * Calculate the encoded size of a number\n * @param value - The number to encode\n * @returns Number of bytes needed to encode the value\n */\nexport function encodedSize(value: number): number {\n if (value < 0x80) return 1; // 7 bits\n if (value < 0x4000) return 2; // 14 bits\n if (value < 0x200000) return 3; // 21 bits\n if (value < 0x10000000) return 4; // 28 bits\n if (value < 0x800000000) return 5; // 35 bits\n if (value < 0x40000000000) return 6; // 42 bits\n if (value < 0x2000000000000) return 7; // 49 bits\n // 2^56 = 72057594037927936 (use calculated value to avoid precision loss)\n if (value < 72057594037927936) return 8; // 56 bits\n return 9; // 64 bits\n}\n\n/**\n * Read a boolean encoded as a single byte\n * @param buf - Buffer to read from\n * @param offset - Offset to read from\n * @returns true if byte is non-zero\n */\nexport function readBoolean(buf: Buffer, offset: number): boolean {\n return buf[offset] !== 0;\n}\n\n/**\n * Read a \"defined\" bitmask for an array of items.\n * Used when some items in a list have optional values.\n *\n * Format: If \"allDefined\" byte is 0, a bitmask follows indicating which items have values.\n * If \"allDefined\" byte is non-zero, all items are defined.\n *\n * @param buf - Buffer to read from\n * @param offset - Offset to start reading\n * @param count - Number of items\n * @returns Object with defined array and bytes consumed\n */\nexport function readDefinedVector(buf: Buffer, offset: number, count: number): { defined: boolean[]; bytesRead: number } {\n var allDefined = buf[offset] !== 0;\n var bytesRead = 1;\n var defined: boolean[] = [];\n\n if (allDefined) {\n // All items are defined\n for (var i = 0; i < count; i++) {\n defined.push(true);\n }\n } else {\n // Read bitmask\n var bitsNeeded = count;\n var bytesNeeded = Math.ceil(bitsNeeded / 8);\n\n for (var byteIdx = 0; byteIdx < bytesNeeded; byteIdx++) {\n var byte = buf[offset + 1 + byteIdx];\n for (var bit = 7; bit >= 0 && defined.length < count; bit--) {\n defined.push((byte & (1 << bit)) !== 0);\n }\n }\n bytesRead += bytesNeeded;\n }\n\n return { defined: defined, bytesRead: bytesRead };\n}\n\n/**\n * Read an array of variable-length numbers\n * @param buf - Buffer to read from\n * @param offset - Offset to start reading\n * @param count - Number of items to read\n * @returns Object with values array and bytes consumed\n */\nexport function readNumberArray(buf: Buffer, offset: number, count: number): { values: number[]; bytesRead: number } {\n var values: number[] = [];\n var totalBytesRead = 0;\n\n for (var i = 0; i < count; i++) {\n var result = readNumber(buf, offset + totalBytesRead);\n values.push(result.value);\n totalBytesRead += result.bytesRead;\n }\n\n return { values: values, bytesRead: totalBytesRead };\n}\n"],"names":["encodedSize","readBoolean","readDefinedVector","readNumber","readNumberArray","readRawNumber","buf","offset","firstByte","mask","extraBytes","value","readUInt64LE","bytesRead","i","count","allDefined","defined","push","bitsNeeded","bytesNeeded","Math","ceil","byteIdx","byte","bit","length","values","totalBytesRead","result"],"mappings":"AAAA,iDAAiD;AACjD,wEAAwE;AACxE,EAAE;AACF,6EAA6E;AAC7E,iDAAiD;AACjD,mDAAmD;AACnD,yCAAyC;AACzC,yCAAyC;AACzC,yCAAyC;AACzC,yCAAyC;AACzC,yCAAyC;AACzC,yCAAyC;AACzC,uDAAuD;AACvD,EAAE;AACF,4EAA4E;AAC5E,wCAAwC;;;;;;;;;;;;QAiExBA;eAAAA;;QAmBAC;eAAAA;;QAgBAC;eAAAA;;QArFAC;eAAAA;;QAuHAC;eAAAA;;QA9EAC;eAAAA;;;mCAtDa;AAatB,SAASF,WAAWG,GAAW,EAAEC,MAAc;IACpD,IAAIC,YAAYF,GAAG,CAACC,OAAO;IAE3B,gDAAgD;IAChD,IAAIE,OAAO;IACX,IAAIC,aAAa;IAEjB,MAAO,AAACF,CAAAA,YAAYC,IAAG,MAAO,KAAKC,aAAa,EAAG;QACjDA;QACAD,OAAOA,SAAS;IAClB;IAEA,mDAAmD;IACnD,IAAIC,eAAe,GAAG;QACpB,4BAA4B;QAC5B,OAAO;YACLC,OAAOC,IAAAA,iCAAY,EAACN,KAAKC,SAAS;YAClCM,WAAW;QACb;IACF;IAEA,2CAA2C;IAC3C,IAAIF,QAAQH,YAAa,CAAA,AAACC,OAAO,IAAKA,IAAG;IAEzC,yCAAyC;IACzC,IAAK,IAAIK,IAAI,GAAGA,IAAIJ,YAAYI,IAAK;QACnCH,QAAQA,QAAQ,MAAML,GAAG,CAACC,SAAS,IAAIO,EAAE;IAC3C;IAEA,OAAO;QACLH,OAAOA;QACPE,WAAW,IAAIH;IACjB;AACF;AAQO,SAASL,cAAcC,GAAW,EAAEC,MAAc;IACvD,OAAOK,IAAAA,iCAAY,EAACN,KAAKC;AAC3B;AAOO,SAASP,YAAYW,KAAa;IACvC,IAAIA,QAAQ,MAAM,OAAO,GAAG,SAAS;IACrC,IAAIA,QAAQ,QAAQ,OAAO,GAAG,UAAU;IACxC,IAAIA,QAAQ,UAAU,OAAO,GAAG,UAAU;IAC1C,IAAIA,QAAQ,YAAY,OAAO,GAAG,UAAU;IAC5C,IAAIA,QAAQ,aAAa,OAAO,GAAG,UAAU;IAC7C,IAAIA,QAAQ,eAAe,OAAO,GAAG,UAAU;IAC/C,IAAIA,QAAQ,iBAAiB,OAAO,GAAG,UAAU;IACjD,0EAA0E;IAC1E,IAAIA,QAAQ,mBAAmB,OAAO,GAAG,UAAU;IACnD,OAAO,GAAG,UAAU;AACtB;AAQO,SAASV,YAAYK,GAAW,EAAEC,MAAc;IACrD,OAAOD,GAAG,CAACC,OAAO,KAAK;AACzB;AAcO,SAASL,kBAAkBI,GAAW,EAAEC,MAAc,EAAEQ,KAAa;IAC1E,IAAIC,aAAaV,GAAG,CAACC,OAAO,KAAK;IACjC,IAAIM,YAAY;IAChB,IAAII,UAAqB,EAAE;IAE3B,IAAID,YAAY;QACd,wBAAwB;QACxB,IAAK,IAAIF,IAAI,GAAGA,IAAIC,OAAOD,IAAK;YAC9BG,QAAQC,IAAI,CAAC;QACf;IACF,OAAO;QACL,eAAe;QACf,IAAIC,aAAaJ;QACjB,IAAIK,cAAcC,KAAKC,IAAI,CAACH,aAAa;QAEzC,IAAK,IAAII,UAAU,GAAGA,UAAUH,aAAaG,UAAW;YACtD,IAAIC,OAAOlB,GAAG,CAACC,SAAS,IAAIgB,QAAQ;YACpC,IAAK,IAAIE,MAAM,GAAGA,OAAO,KAAKR,QAAQS,MAAM,GAAGX,OAAOU,MAAO;gBAC3DR,QAAQC,IAAI,CAAC,AAACM,CAAAA,OAAQ,KAAKC,GAAG,MAAO;YACvC;QACF;QACAZ,aAAaO;IACf;IAEA,OAAO;QAAEH,SAASA;QAASJ,WAAWA;IAAU;AAClD;AASO,SAAST,gBAAgBE,GAAW,EAAEC,MAAc,EAAEQ,KAAa;IACxE,IAAIY,SAAmB,EAAE;IACzB,IAAIC,iBAAiB;IAErB,IAAK,IAAId,IAAI,GAAGA,IAAIC,OAAOD,IAAK;QAC9B,IAAIe,SAAS1B,WAAWG,KAAKC,SAASqB;QACtCD,OAAOT,IAAI,CAACW,OAAOlB,KAAK;QACxBiB,kBAAkBC,OAAOhB,SAAS;IACpC;IAEA,OAAO;QAAEc,QAAQA;QAAQd,WAAWe;IAAe;AACrD"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { type Readable } from 'readable-stream';
|
|
2
|
+
export interface SevenZipEntry {
|
|
3
|
+
name: string;
|
|
4
|
+
path: string;
|
|
5
|
+
type: 'file' | 'directory' | 'link';
|
|
6
|
+
size: number;
|
|
7
|
+
mtime?: Date;
|
|
8
|
+
atime?: Date;
|
|
9
|
+
ctime?: Date;
|
|
10
|
+
mode?: number;
|
|
11
|
+
isAntiFile: boolean;
|
|
12
|
+
_folderIndex: number;
|
|
13
|
+
_streamIndex: number;
|
|
14
|
+
_streamIndexInFolder: number;
|
|
15
|
+
_hasStream: boolean;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Archive source abstraction - allows reading from file descriptor or buffer
|
|
19
|
+
*/
|
|
20
|
+
export interface ArchiveSource {
|
|
21
|
+
read(position: number, length: number): Buffer;
|
|
22
|
+
getSize(): number;
|
|
23
|
+
close(): void;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Buffer-based archive source
|
|
27
|
+
*/
|
|
28
|
+
export declare class BufferSource implements ArchiveSource {
|
|
29
|
+
private buffer;
|
|
30
|
+
constructor(buffer: Buffer);
|
|
31
|
+
read(position: number, length: number): Buffer;
|
|
32
|
+
getSize(): number;
|
|
33
|
+
close(): void;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* File descriptor based archive source
|
|
37
|
+
*/
|
|
38
|
+
export declare class FileSource implements ArchiveSource {
|
|
39
|
+
private fd;
|
|
40
|
+
private size;
|
|
41
|
+
constructor(fd: number, size: number);
|
|
42
|
+
read(position: number, length: number): Buffer;
|
|
43
|
+
getSize(): number;
|
|
44
|
+
close(): void;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* SevenZipParser - parses 7z archives and provides entry iteration
|
|
48
|
+
*/
|
|
49
|
+
export declare class SevenZipParser {
|
|
50
|
+
private source;
|
|
51
|
+
private signature;
|
|
52
|
+
private streamsInfo;
|
|
53
|
+
private filesInfo;
|
|
54
|
+
private entries;
|
|
55
|
+
private parsed;
|
|
56
|
+
private decompressedCache;
|
|
57
|
+
constructor(source: ArchiveSource);
|
|
58
|
+
/**
|
|
59
|
+
* Parse the archive structure
|
|
60
|
+
* Must be called before iterating entries
|
|
61
|
+
*/
|
|
62
|
+
parse(): void;
|
|
63
|
+
/**
|
|
64
|
+
* Handle compressed header (kEncodedHeader)
|
|
65
|
+
*/
|
|
66
|
+
private handleCompressedHeader;
|
|
67
|
+
/**
|
|
68
|
+
* Parse streams info from encoded header block
|
|
69
|
+
* This is a simplified parser for the header's own compression info
|
|
70
|
+
*/
|
|
71
|
+
private parseEncodedHeaderStreams;
|
|
72
|
+
/**
|
|
73
|
+
* Build the entries list from parsed file info
|
|
74
|
+
*/
|
|
75
|
+
private buildEntries;
|
|
76
|
+
/**
|
|
77
|
+
* Create an entry from file info
|
|
78
|
+
*/
|
|
79
|
+
private createEntry;
|
|
80
|
+
/**
|
|
81
|
+
* Get the list of entries
|
|
82
|
+
*/
|
|
83
|
+
getEntries(): SevenZipEntry[];
|
|
84
|
+
/**
|
|
85
|
+
* Get a readable stream for an entry's content
|
|
86
|
+
*/
|
|
87
|
+
getEntryStream(entry: SevenZipEntry): Readable;
|
|
88
|
+
/**
|
|
89
|
+
* Get decompressed data for a folder, with caching for solid archives
|
|
90
|
+
*/
|
|
91
|
+
private getDecompressedFolder;
|
|
92
|
+
/**
|
|
93
|
+
* Close the parser and release resources
|
|
94
|
+
*/
|
|
95
|
+
close(): void;
|
|
96
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { type Readable } from 'readable-stream';
|
|
2
|
+
export interface SevenZipEntry {
|
|
3
|
+
name: string;
|
|
4
|
+
path: string;
|
|
5
|
+
type: 'file' | 'directory' | 'link';
|
|
6
|
+
size: number;
|
|
7
|
+
mtime?: Date;
|
|
8
|
+
atime?: Date;
|
|
9
|
+
ctime?: Date;
|
|
10
|
+
mode?: number;
|
|
11
|
+
isAntiFile: boolean;
|
|
12
|
+
_folderIndex: number;
|
|
13
|
+
_streamIndex: number;
|
|
14
|
+
_streamIndexInFolder: number;
|
|
15
|
+
_hasStream: boolean;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Archive source abstraction - allows reading from file descriptor or buffer
|
|
19
|
+
*/
|
|
20
|
+
export interface ArchiveSource {
|
|
21
|
+
read(position: number, length: number): Buffer;
|
|
22
|
+
getSize(): number;
|
|
23
|
+
close(): void;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Buffer-based archive source
|
|
27
|
+
*/
|
|
28
|
+
export declare class BufferSource implements ArchiveSource {
|
|
29
|
+
private buffer;
|
|
30
|
+
constructor(buffer: Buffer);
|
|
31
|
+
read(position: number, length: number): Buffer;
|
|
32
|
+
getSize(): number;
|
|
33
|
+
close(): void;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* File descriptor based archive source
|
|
37
|
+
*/
|
|
38
|
+
export declare class FileSource implements ArchiveSource {
|
|
39
|
+
private fd;
|
|
40
|
+
private size;
|
|
41
|
+
constructor(fd: number, size: number);
|
|
42
|
+
read(position: number, length: number): Buffer;
|
|
43
|
+
getSize(): number;
|
|
44
|
+
close(): void;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* SevenZipParser - parses 7z archives and provides entry iteration
|
|
48
|
+
*/
|
|
49
|
+
export declare class SevenZipParser {
|
|
50
|
+
private source;
|
|
51
|
+
private signature;
|
|
52
|
+
private streamsInfo;
|
|
53
|
+
private filesInfo;
|
|
54
|
+
private entries;
|
|
55
|
+
private parsed;
|
|
56
|
+
private decompressedCache;
|
|
57
|
+
constructor(source: ArchiveSource);
|
|
58
|
+
/**
|
|
59
|
+
* Parse the archive structure
|
|
60
|
+
* Must be called before iterating entries
|
|
61
|
+
*/
|
|
62
|
+
parse(): void;
|
|
63
|
+
/**
|
|
64
|
+
* Handle compressed header (kEncodedHeader)
|
|
65
|
+
*/
|
|
66
|
+
private handleCompressedHeader;
|
|
67
|
+
/**
|
|
68
|
+
* Parse streams info from encoded header block
|
|
69
|
+
* This is a simplified parser for the header's own compression info
|
|
70
|
+
*/
|
|
71
|
+
private parseEncodedHeaderStreams;
|
|
72
|
+
/**
|
|
73
|
+
* Build the entries list from parsed file info
|
|
74
|
+
*/
|
|
75
|
+
private buildEntries;
|
|
76
|
+
/**
|
|
77
|
+
* Create an entry from file info
|
|
78
|
+
*/
|
|
79
|
+
private createEntry;
|
|
80
|
+
/**
|
|
81
|
+
* Get the list of entries
|
|
82
|
+
*/
|
|
83
|
+
getEntries(): SevenZipEntry[];
|
|
84
|
+
/**
|
|
85
|
+
* Get a readable stream for an entry's content
|
|
86
|
+
*/
|
|
87
|
+
getEntryStream(entry: SevenZipEntry): Readable;
|
|
88
|
+
/**
|
|
89
|
+
* Get decompressed data for a folder, with caching for solid archives
|
|
90
|
+
*/
|
|
91
|
+
private getDecompressedFolder;
|
|
92
|
+
/**
|
|
93
|
+
* Close the parser and release resources
|
|
94
|
+
*/
|
|
95
|
+
close(): void;
|
|
96
|
+
}
|
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
// SevenZipParser - Main 7z archive parser
|
|
2
|
+
// Handles reading archive structure and providing file streams
|
|
3
|
+
"use strict";
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
function _export(target, all) {
|
|
8
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
9
|
+
enumerable: true,
|
|
10
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
_export(exports, {
|
|
14
|
+
get BufferSource () {
|
|
15
|
+
return BufferSource;
|
|
16
|
+
},
|
|
17
|
+
get FileSource () {
|
|
18
|
+
return FileSource;
|
|
19
|
+
},
|
|
20
|
+
get SevenZipParser () {
|
|
21
|
+
return SevenZipParser;
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
var _extractbaseiterator = require("extract-base-iterator");
|
|
25
|
+
var _fs = /*#__PURE__*/ _interop_require_default(require("fs"));
|
|
26
|
+
var _readablestream = require("readable-stream");
|
|
27
|
+
var _indexts = require("./codecs/index.js");
|
|
28
|
+
var _constantsts = require("./constants.js");
|
|
29
|
+
var _headersts = require("./headers.js");
|
|
30
|
+
var _NumberCodects = require("./NumberCodec.js");
|
|
31
|
+
function _class_call_check(instance, Constructor) {
|
|
32
|
+
if (!(instance instanceof Constructor)) {
|
|
33
|
+
throw new TypeError("Cannot call a class as a function");
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function _interop_require_default(obj) {
|
|
37
|
+
return obj && obj.__esModule ? obj : {
|
|
38
|
+
default: obj
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
var BufferSource = /*#__PURE__*/ function() {
|
|
42
|
+
"use strict";
|
|
43
|
+
function BufferSource(buffer) {
|
|
44
|
+
_class_call_check(this, BufferSource);
|
|
45
|
+
this.buffer = buffer;
|
|
46
|
+
}
|
|
47
|
+
var _proto = BufferSource.prototype;
|
|
48
|
+
_proto.read = function read(position, length) {
|
|
49
|
+
return this.buffer.slice(position, position + length);
|
|
50
|
+
};
|
|
51
|
+
_proto.getSize = function getSize() {
|
|
52
|
+
return this.buffer.length;
|
|
53
|
+
};
|
|
54
|
+
_proto.close = function close() {
|
|
55
|
+
// Nothing to close for buffer
|
|
56
|
+
};
|
|
57
|
+
return BufferSource;
|
|
58
|
+
}();
|
|
59
|
+
var FileSource = /*#__PURE__*/ function() {
|
|
60
|
+
"use strict";
|
|
61
|
+
function FileSource(fd, size) {
|
|
62
|
+
_class_call_check(this, FileSource);
|
|
63
|
+
this.fd = fd;
|
|
64
|
+
this.size = size;
|
|
65
|
+
}
|
|
66
|
+
var _proto = FileSource.prototype;
|
|
67
|
+
_proto.read = function read(position, length) {
|
|
68
|
+
var buf = (0, _extractbaseiterator.allocBuffer)(length);
|
|
69
|
+
var bytesRead = _fs.default.readSync(this.fd, buf, 0, length, position);
|
|
70
|
+
if (bytesRead < length) {
|
|
71
|
+
return buf.slice(0, bytesRead);
|
|
72
|
+
}
|
|
73
|
+
return buf;
|
|
74
|
+
};
|
|
75
|
+
_proto.getSize = function getSize() {
|
|
76
|
+
return this.size;
|
|
77
|
+
};
|
|
78
|
+
_proto.close = function close() {
|
|
79
|
+
try {
|
|
80
|
+
_fs.default.closeSync(this.fd);
|
|
81
|
+
} catch (_e) {
|
|
82
|
+
// Ignore close errors
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
return FileSource;
|
|
86
|
+
}();
|
|
87
|
+
var SevenZipParser = /*#__PURE__*/ function() {
|
|
88
|
+
"use strict";
|
|
89
|
+
function SevenZipParser(source) {
|
|
90
|
+
_class_call_check(this, SevenZipParser);
|
|
91
|
+
this.signature = null;
|
|
92
|
+
this.streamsInfo = null;
|
|
93
|
+
this.filesInfo = [];
|
|
94
|
+
this.entries = [];
|
|
95
|
+
this.parsed = false;
|
|
96
|
+
// Cache for decompressed solid blocks (folderIndex -> decompressed data)
|
|
97
|
+
this.decompressedCache = {};
|
|
98
|
+
this.source = source;
|
|
99
|
+
}
|
|
100
|
+
var _proto = SevenZipParser.prototype;
|
|
101
|
+
/**
|
|
102
|
+
* Parse the archive structure
|
|
103
|
+
* Must be called before iterating entries
|
|
104
|
+
*/ _proto.parse = function parse() {
|
|
105
|
+
if (this.parsed) return;
|
|
106
|
+
// Read signature header
|
|
107
|
+
var sigBuf = this.source.read(0, _constantsts.SIGNATURE_HEADER_SIZE);
|
|
108
|
+
if (sigBuf.length < _constantsts.SIGNATURE_HEADER_SIZE) {
|
|
109
|
+
throw (0, _constantsts.createCodedError)('Archive too small', _constantsts.ErrorCode.TRUNCATED_ARCHIVE);
|
|
110
|
+
}
|
|
111
|
+
this.signature = (0, _headersts.parseSignatureHeader)(sigBuf);
|
|
112
|
+
// Read encoded header
|
|
113
|
+
var headerOffset = _constantsts.SIGNATURE_HEADER_SIZE + this.signature.nextHeaderOffset;
|
|
114
|
+
var headerBuf = this.source.read(headerOffset, this.signature.nextHeaderSize);
|
|
115
|
+
if (headerBuf.length < this.signature.nextHeaderSize) {
|
|
116
|
+
throw (0, _constantsts.createCodedError)('Truncated header', _constantsts.ErrorCode.TRUNCATED_ARCHIVE);
|
|
117
|
+
}
|
|
118
|
+
// Parse encoded header (may need decompression)
|
|
119
|
+
try {
|
|
120
|
+
var headerResult = (0, _headersts.parseEncodedHeader)(headerBuf, this.signature.nextHeaderCRC);
|
|
121
|
+
this.streamsInfo = headerResult.streamsInfo || null;
|
|
122
|
+
this.filesInfo = headerResult.filesInfo;
|
|
123
|
+
} catch (err) {
|
|
124
|
+
var codedErr = err;
|
|
125
|
+
if (codedErr && codedErr.code === _constantsts.ErrorCode.COMPRESSED_HEADER) {
|
|
126
|
+
// Header is compressed - need to decompress first
|
|
127
|
+
this.handleCompressedHeader(headerBuf);
|
|
128
|
+
} else {
|
|
129
|
+
throw err;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// Build entries list
|
|
133
|
+
this.buildEntries();
|
|
134
|
+
this.parsed = true;
|
|
135
|
+
};
|
|
136
|
+
/**
|
|
137
|
+
* Handle compressed header (kEncodedHeader)
|
|
138
|
+
*/ _proto.handleCompressedHeader = function handleCompressedHeader(headerBuf) {
|
|
139
|
+
// Parse the encoded header info to get decompression parameters
|
|
140
|
+
var offset = 1; // Skip kEncodedHeader byte
|
|
141
|
+
// Should have StreamsInfo for the header itself
|
|
142
|
+
var propertyId = headerBuf[offset++];
|
|
143
|
+
if (propertyId !== _constantsts.PropertyId.kMainStreamsInfo && propertyId !== _constantsts.PropertyId.kPackInfo) {
|
|
144
|
+
throw (0, _constantsts.createCodedError)('Expected StreamsInfo in encoded header', _constantsts.ErrorCode.CORRUPT_HEADER);
|
|
145
|
+
}
|
|
146
|
+
// For now, we parse the streams info from the encoded header block
|
|
147
|
+
// This tells us how to decompress the actual header
|
|
148
|
+
// Read pack info from the encoded header structure
|
|
149
|
+
var packInfoResult = this.parseEncodedHeaderStreams(headerBuf, 1);
|
|
150
|
+
// Read the compressed header data
|
|
151
|
+
var compressedStart = _constantsts.SIGNATURE_HEADER_SIZE + packInfoResult.packPos;
|
|
152
|
+
var compressedData = this.source.read(compressedStart, packInfoResult.packSize);
|
|
153
|
+
// Decompress using the specified codec
|
|
154
|
+
var codec = (0, _indexts.getCodec)(packInfoResult.codecId);
|
|
155
|
+
var decompressedHeader = codec.decode(compressedData, packInfoResult.properties, packInfoResult.unpackSize);
|
|
156
|
+
// Verify CRC if present
|
|
157
|
+
if (packInfoResult.unpackCRC !== undefined) {
|
|
158
|
+
var actualCRC = (0, _extractbaseiterator.crc32)(decompressedHeader);
|
|
159
|
+
if (actualCRC !== packInfoResult.unpackCRC) {
|
|
160
|
+
throw (0, _constantsts.createCodedError)('Decompressed header CRC mismatch', _constantsts.ErrorCode.CRC_MISMATCH);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
// Now parse the decompressed header
|
|
164
|
+
// It should start with kHeader
|
|
165
|
+
var decompOffset = 0;
|
|
166
|
+
var headerId = decompressedHeader[decompOffset++];
|
|
167
|
+
if (headerId !== _constantsts.PropertyId.kHeader) {
|
|
168
|
+
throw (0, _constantsts.createCodedError)('Expected kHeader in decompressed header', _constantsts.ErrorCode.CORRUPT_HEADER);
|
|
169
|
+
}
|
|
170
|
+
// Parse the decompressed header using shared function from headers.ts
|
|
171
|
+
var result = (0, _headersts.parseHeaderContent)(decompressedHeader, decompOffset);
|
|
172
|
+
this.streamsInfo = result.streamsInfo || null;
|
|
173
|
+
this.filesInfo = result.filesInfo;
|
|
174
|
+
};
|
|
175
|
+
/**
|
|
176
|
+
* Parse streams info from encoded header block
|
|
177
|
+
* This is a simplified parser for the header's own compression info
|
|
178
|
+
*/ _proto.parseEncodedHeaderStreams = function parseEncodedHeaderStreams(buf, offset) {
|
|
179
|
+
// This is a simplified parser for the encoded header's own streams info
|
|
180
|
+
var packPos = 0;
|
|
181
|
+
var packSize = 0;
|
|
182
|
+
var unpackSize = 0;
|
|
183
|
+
var codecId = [];
|
|
184
|
+
var properties;
|
|
185
|
+
var unpackCRC;
|
|
186
|
+
while(offset < buf.length){
|
|
187
|
+
var propertyId = buf[offset++];
|
|
188
|
+
if (propertyId === _constantsts.PropertyId.kEnd) {
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
switch(propertyId){
|
|
192
|
+
case _constantsts.PropertyId.kPackInfo:
|
|
193
|
+
{
|
|
194
|
+
var packPosResult = (0, _NumberCodects.readNumber)(buf, offset);
|
|
195
|
+
packPos = packPosResult.value;
|
|
196
|
+
offset += packPosResult.bytesRead;
|
|
197
|
+
var numPackResult = (0, _NumberCodects.readNumber)(buf, offset);
|
|
198
|
+
offset += numPackResult.bytesRead;
|
|
199
|
+
// Read until kEnd
|
|
200
|
+
while(buf[offset] !== _constantsts.PropertyId.kEnd){
|
|
201
|
+
if (buf[offset] === _constantsts.PropertyId.kSize) {
|
|
202
|
+
offset++;
|
|
203
|
+
var sizeResult = (0, _NumberCodects.readNumber)(buf, offset);
|
|
204
|
+
packSize = sizeResult.value;
|
|
205
|
+
offset += sizeResult.bytesRead;
|
|
206
|
+
} else {
|
|
207
|
+
offset++;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
offset++; // Skip kEnd
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
case _constantsts.PropertyId.kUnpackInfo:
|
|
214
|
+
// Find folder/coder info
|
|
215
|
+
while(offset < buf.length && buf[offset] !== _constantsts.PropertyId.kEnd){
|
|
216
|
+
if (buf[offset] === _constantsts.PropertyId.kFolder) {
|
|
217
|
+
offset++;
|
|
218
|
+
var numFoldersResult = (0, _NumberCodects.readNumber)(buf, offset);
|
|
219
|
+
offset += numFoldersResult.bytesRead;
|
|
220
|
+
offset++; // external flag
|
|
221
|
+
// Parse coder
|
|
222
|
+
var numCodersResult = (0, _NumberCodects.readNumber)(buf, offset);
|
|
223
|
+
offset += numCodersResult.bytesRead;
|
|
224
|
+
var flags = buf[offset++];
|
|
225
|
+
var idSize = flags & 0x0f;
|
|
226
|
+
var hasAttributes = (flags & 0x20) !== 0;
|
|
227
|
+
codecId = [];
|
|
228
|
+
for(var i = 0; i < idSize; i++){
|
|
229
|
+
codecId.push(buf[offset++]);
|
|
230
|
+
}
|
|
231
|
+
if (hasAttributes) {
|
|
232
|
+
var propsLenResult = (0, _NumberCodects.readNumber)(buf, offset);
|
|
233
|
+
offset += propsLenResult.bytesRead;
|
|
234
|
+
properties = buf.slice(offset, offset + propsLenResult.value);
|
|
235
|
+
offset += propsLenResult.value;
|
|
236
|
+
}
|
|
237
|
+
} else if (buf[offset] === _constantsts.PropertyId.kCodersUnpackSize) {
|
|
238
|
+
offset++;
|
|
239
|
+
// Read unpack size - needed for LZMA decoder
|
|
240
|
+
var unpackSizeResult = (0, _NumberCodects.readNumber)(buf, offset);
|
|
241
|
+
unpackSize = unpackSizeResult.value;
|
|
242
|
+
offset += unpackSizeResult.bytesRead;
|
|
243
|
+
} else if (buf[offset] === _constantsts.PropertyId.kCRC) {
|
|
244
|
+
offset++;
|
|
245
|
+
var allDefined = buf[offset++];
|
|
246
|
+
if (allDefined) {
|
|
247
|
+
unpackCRC = buf.readUInt32LE(offset);
|
|
248
|
+
offset += 4;
|
|
249
|
+
}
|
|
250
|
+
} else {
|
|
251
|
+
offset++;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
if (buf[offset] === _constantsts.PropertyId.kEnd) offset++;
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
return {
|
|
259
|
+
packPos: packPos,
|
|
260
|
+
packSize: packSize,
|
|
261
|
+
unpackSize: unpackSize,
|
|
262
|
+
codecId: codecId,
|
|
263
|
+
properties: properties,
|
|
264
|
+
unpackCRC: unpackCRC
|
|
265
|
+
};
|
|
266
|
+
};
|
|
267
|
+
/**
|
|
268
|
+
* Build the entries list from parsed file info
|
|
269
|
+
*/ _proto.buildEntries = function buildEntries() {
|
|
270
|
+
this.entries = [];
|
|
271
|
+
if (!this.streamsInfo) {
|
|
272
|
+
// No streams info - just create entries from file info
|
|
273
|
+
for(var i = 0; i < this.filesInfo.length; i++){
|
|
274
|
+
var file = this.filesInfo[i];
|
|
275
|
+
this.entries.push(this.createEntry(file, 0, 0, 0));
|
|
276
|
+
}
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
// Use the properly parsed numUnpackStreamsPerFolder from the archive header
|
|
280
|
+
var streamsPerFolder = this.streamsInfo.numUnpackStreamsPerFolder;
|
|
281
|
+
// Now build entries with proper folder/stream tracking
|
|
282
|
+
var streamIndex = 0;
|
|
283
|
+
var folderIndex = 0;
|
|
284
|
+
var streamInFolder = 0;
|
|
285
|
+
var folderStreamCount = streamsPerFolder[0] || 0;
|
|
286
|
+
for(var j = 0; j < this.filesInfo.length; j++){
|
|
287
|
+
var fileInfo = this.filesInfo[j];
|
|
288
|
+
// Get size from unpackSizes for files with streams
|
|
289
|
+
var size = 0;
|
|
290
|
+
if (fileInfo.hasStream && streamIndex < this.streamsInfo.unpackSizes.length) {
|
|
291
|
+
size = this.streamsInfo.unpackSizes[streamIndex];
|
|
292
|
+
}
|
|
293
|
+
var entry = this.createEntry(fileInfo, size, folderIndex, streamInFolder);
|
|
294
|
+
entry._streamIndex = streamIndex;
|
|
295
|
+
this.entries.push(entry);
|
|
296
|
+
// Advance stream tracking for files with streams
|
|
297
|
+
if (fileInfo.hasStream) {
|
|
298
|
+
streamIndex++;
|
|
299
|
+
streamInFolder++;
|
|
300
|
+
// Check if we've exhausted streams in this folder
|
|
301
|
+
if (streamInFolder >= folderStreamCount) {
|
|
302
|
+
folderIndex++;
|
|
303
|
+
streamInFolder = 0;
|
|
304
|
+
folderStreamCount = streamsPerFolder[folderIndex] || 0;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
/**
|
|
310
|
+
* Create an entry from file info
|
|
311
|
+
*/ _proto.createEntry = function createEntry(file, size, folderIndex, streamInFolder) {
|
|
312
|
+
// Determine entry type
|
|
313
|
+
// Note: 7z format doesn't natively support symlinks. p7zip with -snl stores
|
|
314
|
+
// symlinks as regular files with the target path as content.
|
|
315
|
+
var type = 'file';
|
|
316
|
+
if (file.isDirectory) {
|
|
317
|
+
type = 'directory';
|
|
318
|
+
}
|
|
319
|
+
// Calculate mode from Windows attributes
|
|
320
|
+
var mode;
|
|
321
|
+
if (file.attributes !== undefined) {
|
|
322
|
+
// Check for Unix extension bit
|
|
323
|
+
if ((file.attributes & _constantsts.FileAttribute.UNIX_EXTENSION) !== 0) {
|
|
324
|
+
mode = file.attributes >>> 16 & 0xffff;
|
|
325
|
+
// Check for symlink (S_IFLNK = 0xA000)
|
|
326
|
+
// Note: Most 7z implementations don't preserve symlink mode bits
|
|
327
|
+
if ((mode & 0xf000) === 0xa000) {
|
|
328
|
+
type = 'link';
|
|
329
|
+
}
|
|
330
|
+
} else if (file.isDirectory) {
|
|
331
|
+
mode = 493; // 0o755
|
|
332
|
+
} else {
|
|
333
|
+
mode = 420; // 0o644
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
return {
|
|
337
|
+
name: getBaseName(file.name),
|
|
338
|
+
path: file.name,
|
|
339
|
+
type: type,
|
|
340
|
+
size: size,
|
|
341
|
+
mtime: file.mtime,
|
|
342
|
+
atime: file.atime,
|
|
343
|
+
ctime: file.ctime,
|
|
344
|
+
mode: mode,
|
|
345
|
+
isAntiFile: file.isAntiFile,
|
|
346
|
+
_folderIndex: folderIndex,
|
|
347
|
+
_streamIndex: 0,
|
|
348
|
+
_streamIndexInFolder: streamInFolder,
|
|
349
|
+
_hasStream: file.hasStream
|
|
350
|
+
};
|
|
351
|
+
};
|
|
352
|
+
/**
|
|
353
|
+
* Get the list of entries
|
|
354
|
+
*/ _proto.getEntries = function getEntries() {
|
|
355
|
+
if (!this.parsed) {
|
|
356
|
+
this.parse();
|
|
357
|
+
}
|
|
358
|
+
return this.entries;
|
|
359
|
+
};
|
|
360
|
+
/**
|
|
361
|
+
* Get a readable stream for an entry's content
|
|
362
|
+
*/ _proto.getEntryStream = function getEntryStream(entry) {
|
|
363
|
+
if (!entry._hasStream || entry.type === 'directory') {
|
|
364
|
+
// Return empty stream for directories and empty files
|
|
365
|
+
var emptyStream = new _readablestream.PassThrough();
|
|
366
|
+
emptyStream.end();
|
|
367
|
+
return emptyStream;
|
|
368
|
+
}
|
|
369
|
+
if (!this.streamsInfo) {
|
|
370
|
+
throw (0, _constantsts.createCodedError)('No streams info available', _constantsts.ErrorCode.CORRUPT_HEADER);
|
|
371
|
+
}
|
|
372
|
+
// Get folder info
|
|
373
|
+
var folder = this.streamsInfo.folders[entry._folderIndex];
|
|
374
|
+
if (!folder) {
|
|
375
|
+
throw (0, _constantsts.createCodedError)('Invalid folder index', _constantsts.ErrorCode.CORRUPT_HEADER);
|
|
376
|
+
}
|
|
377
|
+
// Check codec support
|
|
378
|
+
for(var i = 0; i < folder.coders.length; i++){
|
|
379
|
+
var coder = folder.coders[i];
|
|
380
|
+
if (!(0, _indexts.isCodecSupported)(coder.id)) {
|
|
381
|
+
var codecName = (0, _indexts.getCodecName)(coder.id);
|
|
382
|
+
throw (0, _constantsts.createCodedError)("Unsupported codec: ".concat(codecName), _constantsts.ErrorCode.UNSUPPORTED_CODEC);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
// Get decompressed data for this folder (with caching for solid archives)
|
|
386
|
+
var data = this.getDecompressedFolder(entry._folderIndex);
|
|
387
|
+
// Calculate file offset within the decompressed block
|
|
388
|
+
// For solid archives, multiple files are concatenated in the block
|
|
389
|
+
var fileStart = 0;
|
|
390
|
+
for(var m = 0; m < entry._streamIndexInFolder; m++){
|
|
391
|
+
// Sum sizes of all streams before this one in the folder
|
|
392
|
+
var prevStreamGlobalIndex = entry._streamIndex - entry._streamIndexInFolder + m;
|
|
393
|
+
fileStart += this.streamsInfo.unpackSizes[prevStreamGlobalIndex];
|
|
394
|
+
}
|
|
395
|
+
var fileSize = entry.size;
|
|
396
|
+
// Create a PassThrough stream with the file data
|
|
397
|
+
var outputStream = new _readablestream.PassThrough();
|
|
398
|
+
var fileData = data.slice(fileStart, fileStart + fileSize);
|
|
399
|
+
outputStream.end(fileData);
|
|
400
|
+
return outputStream;
|
|
401
|
+
};
|
|
402
|
+
/**
|
|
403
|
+
* Get decompressed data for a folder, with caching for solid archives
|
|
404
|
+
*/ _proto.getDecompressedFolder = function getDecompressedFolder(folderIndex) {
|
|
405
|
+
// Check cache first
|
|
406
|
+
if (this.decompressedCache[folderIndex]) {
|
|
407
|
+
return this.decompressedCache[folderIndex];
|
|
408
|
+
}
|
|
409
|
+
if (!this.streamsInfo) {
|
|
410
|
+
throw (0, _constantsts.createCodedError)('No streams info available', _constantsts.ErrorCode.CORRUPT_HEADER);
|
|
411
|
+
}
|
|
412
|
+
var folder = this.streamsInfo.folders[folderIndex];
|
|
413
|
+
// Calculate packed data position
|
|
414
|
+
var packPos = _constantsts.SIGNATURE_HEADER_SIZE + this.streamsInfo.packPos;
|
|
415
|
+
// Find which pack stream this folder uses
|
|
416
|
+
var packStreamIndex = 0;
|
|
417
|
+
for(var j = 0; j < folderIndex; j++){
|
|
418
|
+
packStreamIndex += this.streamsInfo.folders[j].packedStreams.length;
|
|
419
|
+
}
|
|
420
|
+
// Calculate position of this pack stream
|
|
421
|
+
for(var k = 0; k < packStreamIndex; k++){
|
|
422
|
+
packPos += this.streamsInfo.packSizes[k];
|
|
423
|
+
}
|
|
424
|
+
var packSize = this.streamsInfo.packSizes[packStreamIndex];
|
|
425
|
+
// Read packed data
|
|
426
|
+
var packedData = this.source.read(packPos, packSize);
|
|
427
|
+
// Decompress through codec chain
|
|
428
|
+
var data = packedData;
|
|
429
|
+
for(var l = 0; l < folder.coders.length; l++){
|
|
430
|
+
var coderInfo = folder.coders[l];
|
|
431
|
+
var codec = (0, _indexts.getCodec)(coderInfo.id);
|
|
432
|
+
// Get unpack size for this coder (needed by LZMA)
|
|
433
|
+
var unpackSize = folder.unpackSizes[l];
|
|
434
|
+
data = codec.decode(data, coderInfo.properties, unpackSize);
|
|
435
|
+
}
|
|
436
|
+
// Cache for solid archives (when multiple files share a folder)
|
|
437
|
+
this.decompressedCache[folderIndex] = data;
|
|
438
|
+
return data;
|
|
439
|
+
};
|
|
440
|
+
/**
|
|
441
|
+
* Close the parser and release resources
|
|
442
|
+
*/ _proto.close = function close() {
|
|
443
|
+
if (this.source) {
|
|
444
|
+
this.source.close();
|
|
445
|
+
}
|
|
446
|
+
};
|
|
447
|
+
return SevenZipParser;
|
|
448
|
+
}();
|
|
449
|
+
/**
|
|
450
|
+
* Get base name from a path
|
|
451
|
+
*/ function getBaseName(path) {
|
|
452
|
+
var lastSlash = path.lastIndexOf('/');
|
|
453
|
+
var lastBackslash = path.lastIndexOf('\\');
|
|
454
|
+
var lastSep = Math.max(lastSlash, lastBackslash);
|
|
455
|
+
return lastSep >= 0 ? path.slice(lastSep + 1) : path;
|
|
456
|
+
}
|
|
457
|
+
/* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
|