@oh-my-pi/pi-utils 17.4.0 → 17.4.2

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.
Files changed (82) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/LICENSE +22 -0
  3. package/THIRD-PARTY-NOTICES.txt +22909 -0
  4. package/dist/types/ar/arj.d.ts +5 -0
  5. package/dist/types/ar/asar.d.ts +7 -0
  6. package/dist/types/ar/bytes.d.ts +20 -0
  7. package/dist/types/ar/cab.d.ts +5 -0
  8. package/dist/types/ar/checksums.d.ts +10 -0
  9. package/dist/types/ar/codecs/bzip2.d.ts +4 -0
  10. package/dist/types/ar/codecs/gzip.d.ts +6 -0
  11. package/dist/types/ar/codecs/lzma.d.ts +6 -0
  12. package/dist/types/ar/codecs/lzw.d.ts +4 -0
  13. package/dist/types/ar/codecs/lzx.d.ts +7 -0
  14. package/dist/types/ar/codecs/xz.d.ts +4 -0
  15. package/dist/types/ar/codecs/zstd.d.ts +6 -0
  16. package/dist/types/ar/cpio.d.ts +7 -0
  17. package/dist/types/ar/deb.d.ts +5 -0
  18. package/dist/types/ar/entries.d.ts +22 -0
  19. package/dist/types/ar/error.d.ts +8 -0
  20. package/dist/types/ar/index.d.ts +11 -0
  21. package/dist/types/ar/iso.d.ts +5 -0
  22. package/dist/types/ar/limits.d.ts +33 -0
  23. package/dist/types/ar/lzh.d.ts +7 -0
  24. package/dist/types/ar/open.d.ts +45 -0
  25. package/dist/types/ar/paths.d.ts +18 -0
  26. package/dist/types/ar/rar/rar4-decoder.d.ts +6 -0
  27. package/dist/types/ar/rar/rar5-decoder.d.ts +6 -0
  28. package/dist/types/ar/rar.d.ts +5 -0
  29. package/dist/types/ar/reader.d.ts +28 -0
  30. package/dist/types/ar/registry.d.ts +17 -0
  31. package/dist/types/ar/rpm.d.ts +5 -0
  32. package/dist/types/ar/sevenzip/decode.d.ts +33 -0
  33. package/dist/types/ar/sevenzip.d.ts +5 -0
  34. package/dist/types/ar/source.d.ts +54 -0
  35. package/dist/types/ar/tar.d.ts +9 -0
  36. package/dist/types/ar/types.d.ts +99 -0
  37. package/dist/types/ar/unix-ar.d.ts +7 -0
  38. package/dist/types/ar/write.d.ts +10 -0
  39. package/dist/types/ar/zip.d.ts +10 -0
  40. package/dist/types/postmortem.d.ts +33 -0
  41. package/package.json +9 -3
  42. package/src/ar/arj.ts +314 -0
  43. package/src/ar/asar.ts +480 -0
  44. package/src/ar/bytes.ts +78 -0
  45. package/src/ar/cab.ts +377 -0
  46. package/src/ar/checksums.ts +62 -0
  47. package/src/ar/codecs/bzip2.ts +489 -0
  48. package/src/ar/codecs/gzip.ts +25 -0
  49. package/src/ar/codecs/lzma.ts +437 -0
  50. package/src/ar/codecs/lzw.ts +191 -0
  51. package/src/ar/codecs/lzx.ts +366 -0
  52. package/src/ar/codecs/xz.ts +522 -0
  53. package/src/ar/codecs/zstd.ts +25 -0
  54. package/src/ar/cpio.ts +389 -0
  55. package/src/ar/deb.ts +160 -0
  56. package/src/ar/entries.ts +97 -0
  57. package/src/ar/error.ts +11 -0
  58. package/src/ar/index.ts +16 -0
  59. package/src/ar/iso.ts +712 -0
  60. package/src/ar/limits.ts +80 -0
  61. package/src/ar/lzh.ts +659 -0
  62. package/src/ar/open.ts +225 -0
  63. package/src/ar/paths.ts +70 -0
  64. package/src/ar/rar/rar4-decoder.ts +459 -0
  65. package/src/ar/rar/rar5-decoder.ts +400 -0
  66. package/src/ar/rar.ts +735 -0
  67. package/src/ar/reader.ts +162 -0
  68. package/src/ar/registry.ts +208 -0
  69. package/src/ar/rpm.ts +320 -0
  70. package/src/ar/sevenzip/decode.ts +239 -0
  71. package/src/ar/sevenzip.ts +634 -0
  72. package/src/ar/source.ts +190 -0
  73. package/src/ar/tar.ts +771 -0
  74. package/src/ar/types.ts +131 -0
  75. package/src/ar/unix-ar.ts +312 -0
  76. package/src/ar/write.ts +55 -0
  77. package/src/ar/zip.ts +719 -0
  78. package/src/browsers.ts +2 -149
  79. package/src/docx/converter.ts +9 -9
  80. package/src/postmortem.ts +74 -0
  81. package/dist/types/docx/zip.d.ts +0 -6
  82. package/src/docx/zip.ts +0 -87
@@ -0,0 +1,239 @@
1
+ import { crc32 } from "../checksums";
2
+ import { lzma2Decompress, lzmaDecompress } from "../codecs/lzma";
3
+ import { ArchiveError } from "../error";
4
+ import type { ArchiveLimits } from "../limits";
5
+ import { assertInMemorySize } from "../limits";
6
+ import type { ByteSource } from "../source";
7
+
8
+ /** One 7z coder and its global folder-stream coordinates. */
9
+ export interface SevenZipCoder {
10
+ id: bigint;
11
+ properties: Uint8Array;
12
+ inputStart: number;
13
+ outputStart: number;
14
+ numInputs: number;
15
+ numOutputs: number;
16
+ }
17
+
18
+ /** One binding from a coder output stream to another coder input stream. */
19
+ export interface SevenZipBindPair {
20
+ input: number;
21
+ output: number;
22
+ }
23
+
24
+ /** Parsed folder graph and its lazy packed-data coordinates. */
25
+ export interface SevenZipFolderRecord {
26
+ coders: SevenZipCoder[];
27
+ bindPairs: SevenZipBindPair[];
28
+ packedIndices: number[];
29
+ unpackSizes: number[];
30
+ packOffsets: number[];
31
+ packSizes: number[];
32
+ packCrcs: Array<number | undefined>;
33
+ crc?: number;
34
+ }
35
+
36
+ function methodName(id: bigint): string {
37
+ switch (id) {
38
+ case 0n:
39
+ return "Copy";
40
+ case 3n:
41
+ return "Delta";
42
+ case 0x21n:
43
+ return "LZMA2";
44
+ case 0x30101n:
45
+ return "LZMA";
46
+ case 0x30401n:
47
+ return "PPMd";
48
+ case 0x3030103n:
49
+ return "BCJ x86";
50
+ case 0x303011bn:
51
+ return "BCJ2";
52
+ case 0x6f10701n:
53
+ return "7zAES";
54
+ case 0x40108n:
55
+ return "Deflate";
56
+ case 0x40109n:
57
+ return "Deflate64";
58
+ case 0x40202n:
59
+ return "BZip2";
60
+ case 0x3030205n:
61
+ return "BCJ PowerPC";
62
+ case 0x3030401n:
63
+ return "BCJ IA64";
64
+ case 0x3030501n:
65
+ return "BCJ ARM";
66
+ case 0x3030701n:
67
+ return "BCJ ARM Thumb";
68
+ case 0x3030805n:
69
+ return "BCJ SPARC";
70
+ case 0xan:
71
+ return "BCJ ARM64";
72
+ case 0xbn:
73
+ return "BCJ RISC-V";
74
+ default:
75
+ return `method 0x${id.toString(16)}`;
76
+ }
77
+ }
78
+
79
+ function read32LE(bytes: Uint8Array, offset: number): number {
80
+ if (offset + 4 > bytes.byteLength) throw new ArchiveError("Invalid 7z BCJ properties");
81
+ return (bytes[offset]! | (bytes[offset + 1]! << 8) | (bytes[offset + 2]! << 16) | (bytes[offset + 3]! << 24)) >>> 0;
82
+ }
83
+
84
+ function deltaDecode(bytes: Uint8Array, distance: number): void {
85
+ const history = new Uint8Array(256);
86
+ let position = 0;
87
+ for (let index = 0; index < bytes.byteLength; index++) {
88
+ const value = (bytes[index]! + history[(distance + position) & 0xff]!) & 0xff;
89
+ history[position] = value;
90
+ bytes[index] = value;
91
+ position = (position - 1) & 0xff;
92
+ }
93
+ }
94
+
95
+ function x86Decode(bytes: Uint8Array, startOffset: number): void {
96
+ const maskToBitNumber = [0, 1, 2, 2, 3] as const;
97
+ let previousMask = 0;
98
+ let previousPosition = 0xfffffffb;
99
+ if (bytes.byteLength < 5) return;
100
+ let position = 0;
101
+ const limit = bytes.byteLength - 5;
102
+ while (position <= limit) {
103
+ let byte = bytes[position]!;
104
+ if (byte !== 0xe8 && byte !== 0xe9) {
105
+ position++;
106
+ continue;
107
+ }
108
+ const absolutePosition = (startOffset + position) >>> 0;
109
+ const offset = (absolutePosition - previousPosition) >>> 0;
110
+ previousPosition = absolutePosition;
111
+ if (offset > 5) previousMask = 0;
112
+ else for (let index = 0; index < offset; index++) previousMask = ((previousMask & 0x77) << 1) >>> 0;
113
+ byte = bytes[position + 4]!;
114
+ if ((byte === 0 || byte === 0xff) && previousMask >>> 1 <= 4 && previousMask >>> 1 !== 3) {
115
+ let source = read32LE(bytes, position + 1);
116
+ let destination = 0;
117
+ for (;;) {
118
+ destination = (source - absolutePosition - 5) >>> 0;
119
+ if (previousMask === 0) break;
120
+ const bitIndex = maskToBitNumber[previousMask >>> 1]! * 8;
121
+ const testByte = (destination >>> (24 - bitIndex)) & 0xff;
122
+ if (testByte !== 0 && testByte !== 0xff) break;
123
+ const lowMask = bitIndex === 0 ? 0xffffffff : 2 ** (32 - bitIndex) - 1;
124
+ source = (destination ^ lowMask) >>> 0;
125
+ }
126
+ bytes[position + 4] = ~(((destination >>> 24) & 1) - 1) & 0xff;
127
+ bytes[position + 3] = destination >>> 16;
128
+ bytes[position + 2] = destination >>> 8;
129
+ bytes[position + 1] = destination;
130
+ position += 5;
131
+ previousMask = 0;
132
+ } else {
133
+ position++;
134
+ previousMask |= 1;
135
+ if (byte === 0 || byte === 0xff) previousMask |= 0x10;
136
+ }
137
+ }
138
+ }
139
+
140
+ /** Shared lazy decoder/cache for a single 7z folder (solid block). */
141
+ export class SevenZipFolderSource {
142
+ readonly #source: ByteSource;
143
+ readonly #folder: SevenZipFolderRecord;
144
+ readonly #limits: ArchiveLimits;
145
+ #cached?: Promise<Uint8Array>;
146
+
147
+ constructor(source: ByteSource, folder: SevenZipFolderRecord, limits: ArchiveLimits) {
148
+ this.#source = source;
149
+ this.#folder = folder;
150
+ this.#limits = limits;
151
+ }
152
+
153
+ read(): Promise<Uint8Array> {
154
+ this.#cached ??= this.#decode();
155
+ return this.#cached;
156
+ }
157
+
158
+ async #decode(): Promise<Uint8Array> {
159
+ const folder = this.#folder;
160
+ if (folder.packedIndices.length !== 1 || folder.packOffsets.length !== 1 || folder.packSizes.length !== 1) {
161
+ const bcj2 = folder.coders.find(coder => coder.id === 0x303011bn);
162
+ if (bcj2) throw new ArchiveError("Unsupported 7z coder BCJ2 (multi-input folder)");
163
+ throw new ArchiveError("Unsupported 7z folder graph with multiple packed input streams");
164
+ }
165
+ const packOffset = folder.packOffsets[0]!;
166
+ const packSize = folder.packSizes[0]!;
167
+ if (
168
+ !Number.isSafeInteger(packOffset) ||
169
+ !Number.isSafeInteger(packSize) ||
170
+ packOffset < 0 ||
171
+ packSize < 0 ||
172
+ packOffset + packSize > this.#source.size
173
+ ) {
174
+ throw new ArchiveError("Invalid 7z packed-stream range");
175
+ }
176
+ let bytes = await this.#source.read(packOffset, packOffset + packSize);
177
+ if (folder.packCrcs[0] !== undefined && crc32(bytes) !== folder.packCrcs[0]) {
178
+ throw new ArchiveError("Invalid 7z packed-stream CRC32 mismatch");
179
+ }
180
+ let inputIndex = folder.packedIndices[0]!;
181
+ const visited = new Set<number>();
182
+ for (;;) {
183
+ const coderIndex = folder.coders.findIndex(
184
+ coder => inputIndex >= coder.inputStart && inputIndex < coder.inputStart + coder.numInputs,
185
+ );
186
+ if (coderIndex < 0 || visited.has(coderIndex)) throw new ArchiveError("Invalid 7z folder binding graph");
187
+ visited.add(coderIndex);
188
+ const coder = folder.coders[coderIndex]!;
189
+ if (coder.numInputs !== 1 || coder.numOutputs !== 1)
190
+ throw new ArchiveError(`Unsupported 7z coder ${methodName(coder.id)} stream topology`);
191
+ const outputSize = folder.unpackSizes[coder.outputStart];
192
+ if (outputSize === undefined) throw new ArchiveError("Invalid 7z coder unpack size");
193
+ assertInMemorySize(outputSize, this.#limits);
194
+ switch (coder.id) {
195
+ case 0n:
196
+ if (coder.properties.byteLength !== 0 || bytes.byteLength !== outputSize)
197
+ throw new ArchiveError("Invalid 7z Copy coder size or properties");
198
+ break;
199
+ case 0x30101n:
200
+ bytes = await lzmaDecompress(coder.properties, bytes, outputSize);
201
+ break;
202
+ case 0x21n:
203
+ if (coder.properties.byteLength !== 1) throw new ArchiveError("Invalid 7z LZMA2 coder properties");
204
+ bytes = await lzma2Decompress(coder.properties[0]!, bytes, outputSize);
205
+ if (bytes.byteLength !== outputSize) throw new ArchiveError("7z LZMA2 coder output size mismatch");
206
+ break;
207
+ case 3n:
208
+ if (coder.properties.byteLength !== 1 || bytes.byteLength !== outputSize)
209
+ throw new ArchiveError("Invalid 7z Delta coder properties or size");
210
+ bytes = bytes.slice();
211
+ deltaDecode(bytes, coder.properties[0]! + 1);
212
+ break;
213
+ case 0x3030103n: {
214
+ if (coder.properties.byteLength !== 0 && coder.properties.byteLength !== 4)
215
+ throw new ArchiveError("Invalid 7z BCJ x86 coder properties");
216
+ if (bytes.byteLength !== outputSize) throw new ArchiveError("7z BCJ x86 coder output size mismatch");
217
+ const startOffset = coder.properties.byteLength === 4 ? read32LE(coder.properties, 0) : 0;
218
+ bytes = bytes.slice();
219
+ x86Decode(bytes, startOffset);
220
+ break;
221
+ }
222
+ case 0x30401n:
223
+ throw new ArchiveError("Unsupported 7z coder PPMd");
224
+ case 0x6f10701n:
225
+ throw new ArchiveError("Encrypted 7z archives use unsupported coder 7zAES");
226
+ default:
227
+ throw new ArchiveError(`Unsupported 7z coder ${methodName(coder.id)}`);
228
+ }
229
+ const binding = folder.bindPairs.find(pair => pair.output === coder.outputStart);
230
+ if (!binding) break;
231
+ inputIndex = binding.input;
232
+ }
233
+ if (visited.size !== folder.coders.length)
234
+ throw new ArchiveError("Unsupported 7z folder graph with disconnected coders");
235
+ if (folder.crc !== undefined && crc32(bytes) !== folder.crc)
236
+ throw new ArchiveError("Invalid 7z folder CRC32 mismatch");
237
+ return bytes;
238
+ }
239
+ }