@push.rocks/smartarchive 5.2.3 → 5.3.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/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/classes.smartarchive.d.ts +1 -1
- package/dist_ts/classes.smartarchive.js +2 -2
- package/dist_ts/classes.ziptools.d.ts +18 -0
- package/dist_ts/classes.ziptools.js +70 -0
- package/dist_ts/index.d.ts +1 -0
- package/dist_ts/index.js +3 -1
- package/dist_ts_shared/bzip2/index.js +2 -2
- package/dist_ts_shared/classes.ziptools.d.ts +6 -13
- package/dist_ts_shared/classes.ziptools.js +511 -54
- package/dist_ts_shared/errors.d.ts +25 -0
- package/dist_ts_shared/errors.js +28 -1
- package/dist_ts_shared/index.d.ts +1 -1
- package/dist_ts_shared/index.js +2 -2
- package/dist_ts_shared/interfaces.d.ts +35 -0
- package/dist_ts_shared/plugins.ziptools.d.ts +3 -0
- package/dist_ts_shared/plugins.ziptools.js +4 -0
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/index.d.ts +1 -1
- package/dist_ts_web/index.js +1 -1
- package/dist_ts_web/plugins.d.ts +1 -1
- package/dist_ts_web/plugins.js +1 -1
- package/dist_ts_web/zip.d.ts +3 -0
- package/dist_ts_web/zip.js +3 -0
- package/package.json +5 -3
- package/readme.hints.md +15 -1
- package/readme.md +43 -54
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.smartarchive.ts +1 -1
- package/ts/classes.ziptools.ts +75 -0
- package/ts/index.ts +3 -0
- package/ts_shared/classes.ziptools.ts +690 -51
- package/ts_shared/errors.ts +31 -0
- package/ts_shared/index.ts +1 -1
- package/ts_shared/interfaces.ts +38 -0
- package/ts_shared/plugins.ziptools.ts +4 -0
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/zip.ts +7 -0
|
@@ -1,57 +1,521 @@
|
|
|
1
|
-
import * as plugins from './plugins.js';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
1
|
+
import * as plugins from './plugins.ziptools.js';
|
|
2
|
+
import { ZIP_ERROR_CODES, ZipError } from './errors.js';
|
|
3
|
+
const ZIP_LOCAL_FILE_HEADER_SIGNATURE = 0x04034b50;
|
|
4
|
+
const ZIP_CENTRAL_DIRECTORY_SIGNATURE = 0x02014b50;
|
|
5
|
+
const ZIP_END_OF_CENTRAL_DIRECTORY_SIGNATURE = 0x06054b50;
|
|
6
|
+
const ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_SIGNATURE = 0x07064b50;
|
|
7
|
+
const ZIP_DATA_DESCRIPTOR_SIGNATURE = 0x08074b50;
|
|
8
|
+
const ZIP64_EXTRA_FIELD_ID = 0x0001;
|
|
9
|
+
const ZIP_UNICODE_PATH_EXTRA_FIELD_ID = 0x7075;
|
|
10
|
+
const ZIP_ALLOWED_GENERAL_PURPOSE_FLAGS = 0x080e;
|
|
11
|
+
const PAKO_INPUT_CHUNK_BYTES = 16 * 1024;
|
|
12
|
+
const PAKO_OUTPUT_CHUNK_BYTES = 16 * 1024;
|
|
13
|
+
const crc32Table = (() => {
|
|
14
|
+
const table = new Uint32Array(256);
|
|
15
|
+
for (let index = 0; index < table.length; index++) {
|
|
16
|
+
let value = index;
|
|
17
|
+
for (let bit = 0; bit < 8; bit++) {
|
|
18
|
+
value = value & 1 ? 0xedb88320 ^ (value >>> 1) : value >>> 1;
|
|
19
|
+
}
|
|
20
|
+
table[index] = value >>> 0;
|
|
21
|
+
}
|
|
22
|
+
return table;
|
|
23
|
+
})();
|
|
24
|
+
function throwInvalidZip(message) {
|
|
25
|
+
throw new ZipError(message, ZIP_ERROR_CODES.INVALID_ARCHIVE);
|
|
26
|
+
}
|
|
27
|
+
function throwUnsupportedZip(message) {
|
|
28
|
+
throw new ZipError(message, ZIP_ERROR_CODES.UNSUPPORTED_FEATURE);
|
|
29
|
+
}
|
|
30
|
+
function checkedEnd(data, offset, length) {
|
|
31
|
+
const end = offset + length;
|
|
32
|
+
if (!Number.isSafeInteger(offset) ||
|
|
33
|
+
!Number.isSafeInteger(length) ||
|
|
34
|
+
offset < 0 ||
|
|
35
|
+
length < 0 ||
|
|
36
|
+
!Number.isSafeInteger(end) ||
|
|
37
|
+
end > data.length) {
|
|
38
|
+
throwInvalidZip('ZIP record extends beyond the archive');
|
|
39
|
+
}
|
|
40
|
+
return end;
|
|
41
|
+
}
|
|
42
|
+
function readUint16(data, offset) {
|
|
43
|
+
checkedEnd(data, offset, 2);
|
|
44
|
+
return data[offset] | (data[offset + 1] << 8);
|
|
45
|
+
}
|
|
46
|
+
function readUint32(data, offset) {
|
|
47
|
+
checkedEnd(data, offset, 4);
|
|
48
|
+
return (data[offset] |
|
|
49
|
+
(data[offset + 1] << 8) |
|
|
50
|
+
(data[offset + 2] << 16) |
|
|
51
|
+
(data[offset + 3] << 24)) >>> 0;
|
|
52
|
+
}
|
|
53
|
+
function equalBytes(first, second) {
|
|
54
|
+
if (first.length !== second.length)
|
|
55
|
+
return false;
|
|
56
|
+
for (let index = 0; index < first.length; index++) {
|
|
57
|
+
if (first[index] !== second[index])
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
function validateExtraFields(data, offset, length) {
|
|
63
|
+
const end = checkedEnd(data, offset, length);
|
|
64
|
+
let cursor = offset;
|
|
65
|
+
while (cursor < end) {
|
|
66
|
+
if (cursor + 4 > end) {
|
|
67
|
+
throwInvalidZip('ZIP extra field header is truncated');
|
|
68
|
+
}
|
|
69
|
+
const fieldId = readUint16(data, cursor);
|
|
70
|
+
const fieldLength = readUint16(data, cursor + 2);
|
|
71
|
+
cursor += 4;
|
|
72
|
+
if (cursor + fieldLength > end) {
|
|
73
|
+
throwInvalidZip('ZIP extra field data is truncated');
|
|
74
|
+
}
|
|
75
|
+
if (fieldId === ZIP64_EXTRA_FIELD_ID) {
|
|
76
|
+
throwUnsupportedZip('ZIP64 entries are not supported by bounded extraction');
|
|
77
|
+
}
|
|
78
|
+
if (fieldId === ZIP_UNICODE_PATH_EXTRA_FIELD_ID) {
|
|
79
|
+
throwUnsupportedZip('ZIP Unicode path extra fields are not supported by bounded extraction');
|
|
80
|
+
}
|
|
81
|
+
cursor += fieldLength;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function decodeZipPath(rawPath, flags) {
|
|
85
|
+
if (!rawPath.length) {
|
|
86
|
+
throwInvalidZip('ZIP entry path is empty');
|
|
87
|
+
}
|
|
88
|
+
let path;
|
|
89
|
+
if (flags & 0x0800) {
|
|
90
|
+
try {
|
|
91
|
+
path = new TextDecoder('utf-8', { fatal: true }).decode(rawPath);
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
throwInvalidZip('ZIP entry path is not valid UTF-8');
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
if (rawPath.some(byte => byte > 0x7f)) {
|
|
99
|
+
throwUnsupportedZip('ZIP entry paths without the UTF-8 flag must be ASCII');
|
|
100
|
+
}
|
|
101
|
+
path = new TextDecoder().decode(rawPath);
|
|
102
|
+
}
|
|
103
|
+
if (path.includes('\0')) {
|
|
104
|
+
throwInvalidZip('ZIP entry path contains a NUL byte');
|
|
105
|
+
}
|
|
106
|
+
if (path.includes('\\') || path.startsWith('/') || /^[A-Za-z]:/.test(path)) {
|
|
107
|
+
throwInvalidZip('ZIP entry path is not relative');
|
|
108
|
+
}
|
|
109
|
+
const isDirectory = path.endsWith('/');
|
|
110
|
+
const pathSegments = path.split('/');
|
|
111
|
+
if (isDirectory)
|
|
112
|
+
pathSegments.pop();
|
|
113
|
+
if (!pathSegments.length ||
|
|
114
|
+
pathSegments.some(segment => !segment || segment === '.' || segment === '..')) {
|
|
115
|
+
throwInvalidZip('ZIP entry path contains an invalid segment');
|
|
116
|
+
}
|
|
117
|
+
return path;
|
|
118
|
+
}
|
|
119
|
+
function findZipEndRecord(data, maxEntries) {
|
|
120
|
+
if (data.length < 22) {
|
|
121
|
+
throwInvalidZip('ZIP end record is missing');
|
|
122
|
+
}
|
|
123
|
+
const candidates = [];
|
|
124
|
+
const earliestOffset = Math.max(0, data.length - 22 - 0xffff);
|
|
125
|
+
for (let offset = data.length - 22; offset >= earliestOffset; offset--) {
|
|
126
|
+
if (readUint32(data, offset) !== ZIP_END_OF_CENTRAL_DIRECTORY_SIGNATURE)
|
|
127
|
+
continue;
|
|
128
|
+
const commentLength = readUint16(data, offset + 20);
|
|
129
|
+
if (offset + 22 + commentLength === data.length) {
|
|
130
|
+
candidates.push(offset);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (candidates.length !== 1) {
|
|
134
|
+
throwInvalidZip(candidates.length ? 'ZIP end record is ambiguous' : 'ZIP end record is missing');
|
|
135
|
+
}
|
|
136
|
+
const offset = candidates[0];
|
|
137
|
+
const diskNumber = readUint16(data, offset + 4);
|
|
138
|
+
const centralDirectoryDisk = readUint16(data, offset + 6);
|
|
139
|
+
const entriesOnDisk = readUint16(data, offset + 8);
|
|
140
|
+
const entryCount = readUint16(data, offset + 10);
|
|
141
|
+
const centralDirectorySize = readUint32(data, offset + 12);
|
|
142
|
+
const centralDirectoryOffset = readUint32(data, offset + 16);
|
|
143
|
+
if (diskNumber === 0xffff ||
|
|
144
|
+
centralDirectoryDisk === 0xffff ||
|
|
145
|
+
entriesOnDisk === 0xffff ||
|
|
146
|
+
entryCount === 0xffff ||
|
|
147
|
+
centralDirectorySize === 0xffffffff ||
|
|
148
|
+
centralDirectoryOffset === 0xffffffff) {
|
|
149
|
+
throwUnsupportedZip('ZIP64 archives are not supported by bounded extraction');
|
|
150
|
+
}
|
|
151
|
+
if (diskNumber !== 0 || centralDirectoryDisk !== 0 || entriesOnDisk !== entryCount) {
|
|
152
|
+
throwUnsupportedZip('Split ZIP archives are not supported by bounded extraction');
|
|
153
|
+
}
|
|
154
|
+
if (offset >= 20 &&
|
|
155
|
+
readUint32(data, offset - 20) === ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_SIGNATURE) {
|
|
156
|
+
throwUnsupportedZip('ZIP64 archives are not supported by bounded extraction');
|
|
157
|
+
}
|
|
158
|
+
if (entryCount > maxEntries) {
|
|
159
|
+
throw new ZipError(`ZIP contains ${entryCount} entries, exceeding the configured limit`, ZIP_ERROR_CODES.ENTRY_COUNT_LIMIT);
|
|
160
|
+
}
|
|
161
|
+
const centralDirectoryEnd = checkedEnd(data, centralDirectoryOffset, centralDirectorySize);
|
|
162
|
+
if (centralDirectoryEnd !== offset) {
|
|
163
|
+
throwInvalidZip('ZIP central directory range is inconsistent');
|
|
164
|
+
}
|
|
165
|
+
return {
|
|
166
|
+
offset,
|
|
167
|
+
entryCount,
|
|
168
|
+
centralDirectoryOffset,
|
|
169
|
+
centralDirectorySize,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
function validateGeneralPurposeFlags(flags, compressionMethod) {
|
|
173
|
+
if (flags & ~ZIP_ALLOWED_GENERAL_PURPOSE_FLAGS) {
|
|
174
|
+
throwUnsupportedZip('ZIP entry uses unsupported general-purpose flags');
|
|
175
|
+
}
|
|
176
|
+
if (compressionMethod !== 8 && flags & 0x0006) {
|
|
177
|
+
throwUnsupportedZip('ZIP compression flags are only supported for DEFLATE entries');
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
function parseDataDescriptor(data, dataEnd, centralDirectoryOffset, entry) {
|
|
181
|
+
const candidates = [];
|
|
182
|
+
const matchesDescriptorAt = (offset) => {
|
|
183
|
+
if (offset + 12 > centralDirectoryOffset)
|
|
184
|
+
return null;
|
|
185
|
+
if (readUint32(data, offset) !== entry.crc32 ||
|
|
186
|
+
readUint32(data, offset + 4) !== entry.compressedSize ||
|
|
187
|
+
readUint32(data, offset + 8) !== entry.uncompressedSize) {
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
return offset + 12;
|
|
191
|
+
};
|
|
192
|
+
const unsignedEnd = matchesDescriptorAt(dataEnd);
|
|
193
|
+
if (unsignedEnd !== null)
|
|
194
|
+
candidates.push(unsignedEnd);
|
|
195
|
+
if (dataEnd + 4 <= centralDirectoryOffset &&
|
|
196
|
+
readUint32(data, dataEnd) === ZIP_DATA_DESCRIPTOR_SIGNATURE) {
|
|
197
|
+
const signedEnd = matchesDescriptorAt(dataEnd + 4);
|
|
198
|
+
if (signedEnd !== null)
|
|
199
|
+
candidates.push(signedEnd);
|
|
200
|
+
}
|
|
201
|
+
if (candidates.length !== 1) {
|
|
202
|
+
throwInvalidZip(candidates.length
|
|
203
|
+
? 'ZIP data descriptor is ambiguous'
|
|
204
|
+
: 'ZIP data descriptor does not match the central directory');
|
|
205
|
+
}
|
|
206
|
+
return candidates[0];
|
|
207
|
+
}
|
|
208
|
+
function parseZipEntries(data, maxEntries) {
|
|
209
|
+
const endRecord = findZipEndRecord(data, maxEntries);
|
|
210
|
+
const centralDirectoryEnd = endRecord.centralDirectoryOffset + endRecord.centralDirectorySize;
|
|
211
|
+
const entries = [];
|
|
212
|
+
const localOffsets = new Set();
|
|
213
|
+
let cursor = endRecord.centralDirectoryOffset;
|
|
214
|
+
for (let entryIndex = 0; entryIndex < endRecord.entryCount; entryIndex++) {
|
|
215
|
+
if (readUint32(data, cursor) !== ZIP_CENTRAL_DIRECTORY_SIGNATURE) {
|
|
216
|
+
throwInvalidZip('ZIP central directory entry signature is invalid');
|
|
217
|
+
}
|
|
218
|
+
checkedEnd(data, cursor, 46);
|
|
219
|
+
const versionNeeded = readUint16(data, cursor + 6);
|
|
220
|
+
const flags = readUint16(data, cursor + 8);
|
|
221
|
+
const compressionMethod = readUint16(data, cursor + 10);
|
|
222
|
+
const modificationTime = readUint16(data, cursor + 12);
|
|
223
|
+
const modificationDate = readUint16(data, cursor + 14);
|
|
224
|
+
const crc32 = readUint32(data, cursor + 16);
|
|
225
|
+
const compressedSize = readUint32(data, cursor + 20);
|
|
226
|
+
const uncompressedSize = readUint32(data, cursor + 24);
|
|
227
|
+
const pathLength = readUint16(data, cursor + 28);
|
|
228
|
+
const extraLength = readUint16(data, cursor + 30);
|
|
229
|
+
const commentLength = readUint16(data, cursor + 32);
|
|
230
|
+
const diskNumberStart = readUint16(data, cursor + 34);
|
|
231
|
+
const localHeaderOffset = readUint32(data, cursor + 42);
|
|
232
|
+
if (compressedSize === 0xffffffff ||
|
|
233
|
+
uncompressedSize === 0xffffffff ||
|
|
234
|
+
diskNumberStart === 0xffff ||
|
|
235
|
+
localHeaderOffset === 0xffffffff) {
|
|
236
|
+
throwUnsupportedZip('ZIP64 entries are not supported by bounded extraction');
|
|
237
|
+
}
|
|
238
|
+
if (diskNumberStart !== 0) {
|
|
239
|
+
throwUnsupportedZip('Split ZIP entries are not supported by bounded extraction');
|
|
240
|
+
}
|
|
241
|
+
validateGeneralPurposeFlags(flags, compressionMethod);
|
|
242
|
+
if (compressionMethod === 0 || compressionMethod === 8) {
|
|
243
|
+
const minimumVersion = compressionMethod === 8 || (flags & 0x0008) !== 0 ? 20 : 10;
|
|
244
|
+
if (versionNeeded < minimumVersion) {
|
|
245
|
+
throwInvalidZip('ZIP entry declares an insufficient extraction version');
|
|
246
|
+
}
|
|
247
|
+
if (versionNeeded > 20) {
|
|
248
|
+
throwUnsupportedZip('ZIP entry requires features outside the bounded subset');
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
if (compressionMethod === 0 && compressedSize !== uncompressedSize) {
|
|
252
|
+
throwInvalidZip('ZIP stored entry has inconsistent sizes');
|
|
253
|
+
}
|
|
254
|
+
const pathOffset = cursor + 46;
|
|
255
|
+
const extraOffset = checkedEnd(data, pathOffset, pathLength);
|
|
256
|
+
const commentOffset = checkedEnd(data, extraOffset, extraLength);
|
|
257
|
+
const nextCursor = checkedEnd(data, commentOffset, commentLength);
|
|
258
|
+
if (nextCursor > centralDirectoryEnd) {
|
|
259
|
+
throwInvalidZip('ZIP central directory entry exceeds the central directory');
|
|
260
|
+
}
|
|
261
|
+
const rawPath = data.subarray(pathOffset, extraOffset);
|
|
262
|
+
const path = decodeZipPath(rawPath, flags);
|
|
263
|
+
validateExtraFields(data, extraOffset, extraLength);
|
|
264
|
+
if (localOffsets.has(localHeaderOffset)) {
|
|
265
|
+
throwInvalidZip('ZIP entries reference the same local header');
|
|
266
|
+
}
|
|
267
|
+
localOffsets.add(localHeaderOffset);
|
|
268
|
+
if (localHeaderOffset >= endRecord.centralDirectoryOffset) {
|
|
269
|
+
throwInvalidZip('ZIP local header intersects the central directory');
|
|
270
|
+
}
|
|
271
|
+
if (readUint32(data, localHeaderOffset) !== ZIP_LOCAL_FILE_HEADER_SIGNATURE) {
|
|
272
|
+
throwInvalidZip('ZIP local file header signature is invalid');
|
|
273
|
+
}
|
|
274
|
+
checkedEnd(data, localHeaderOffset, 30);
|
|
275
|
+
const localVersionNeeded = readUint16(data, localHeaderOffset + 4);
|
|
276
|
+
const localFlags = readUint16(data, localHeaderOffset + 6);
|
|
277
|
+
const localCompressionMethod = readUint16(data, localHeaderOffset + 8);
|
|
278
|
+
const localModificationTime = readUint16(data, localHeaderOffset + 10);
|
|
279
|
+
const localModificationDate = readUint16(data, localHeaderOffset + 12);
|
|
280
|
+
const localCrc32 = readUint32(data, localHeaderOffset + 14);
|
|
281
|
+
const localCompressedSize = readUint32(data, localHeaderOffset + 18);
|
|
282
|
+
const localUncompressedSize = readUint32(data, localHeaderOffset + 22);
|
|
283
|
+
const localPathLength = readUint16(data, localHeaderOffset + 26);
|
|
284
|
+
const localExtraLength = readUint16(data, localHeaderOffset + 28);
|
|
285
|
+
const localPathOffset = localHeaderOffset + 30;
|
|
286
|
+
const localExtraOffset = checkedEnd(data, localPathOffset, localPathLength);
|
|
287
|
+
const dataStart = checkedEnd(data, localExtraOffset, localExtraLength);
|
|
288
|
+
const dataEnd = checkedEnd(data, dataStart, compressedSize);
|
|
289
|
+
if (dataEnd > endRecord.centralDirectoryOffset) {
|
|
290
|
+
throwInvalidZip('ZIP local file data intersects the central directory');
|
|
291
|
+
}
|
|
292
|
+
if (localVersionNeeded !== versionNeeded ||
|
|
293
|
+
localFlags !== flags ||
|
|
294
|
+
localCompressionMethod !== compressionMethod ||
|
|
295
|
+
localModificationTime !== modificationTime ||
|
|
296
|
+
localModificationDate !== modificationDate) {
|
|
297
|
+
throwInvalidZip('ZIP local and central entry metadata differ');
|
|
298
|
+
}
|
|
299
|
+
const localRawPath = data.subarray(localPathOffset, localExtraOffset);
|
|
300
|
+
if (!equalBytes(localRawPath, rawPath)) {
|
|
301
|
+
throwInvalidZip('ZIP local and central entry paths differ');
|
|
302
|
+
}
|
|
303
|
+
validateExtraFields(data, localExtraOffset, localExtraLength);
|
|
304
|
+
let localRecordEnd = dataEnd;
|
|
305
|
+
if (flags & 0x0008) {
|
|
306
|
+
if (localCrc32 !== 0 || localCompressedSize !== 0 || localUncompressedSize !== 0) {
|
|
307
|
+
throwInvalidZip('ZIP data-descriptor entry has non-zero local size metadata');
|
|
308
|
+
}
|
|
309
|
+
localRecordEnd = parseDataDescriptor(data, dataEnd, endRecord.centralDirectoryOffset, {
|
|
310
|
+
crc32,
|
|
311
|
+
compressedSize,
|
|
312
|
+
uncompressedSize,
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
else if (localCrc32 !== crc32 ||
|
|
316
|
+
localCompressedSize !== compressedSize ||
|
|
317
|
+
localUncompressedSize !== uncompressedSize) {
|
|
318
|
+
throwInvalidZip('ZIP local sizes or CRC differ from the central directory');
|
|
319
|
+
}
|
|
320
|
+
entries.push({
|
|
321
|
+
path,
|
|
322
|
+
rawPath,
|
|
323
|
+
flags,
|
|
324
|
+
compressionMethod,
|
|
325
|
+
crc32,
|
|
326
|
+
compressedSize,
|
|
327
|
+
uncompressedSize,
|
|
328
|
+
localHeaderOffset,
|
|
329
|
+
dataStart,
|
|
330
|
+
dataEnd,
|
|
331
|
+
localRecordEnd,
|
|
332
|
+
isDirectory: path.endsWith('/'),
|
|
42
333
|
});
|
|
43
|
-
|
|
334
|
+
cursor = nextCursor;
|
|
335
|
+
}
|
|
336
|
+
if (cursor !== centralDirectoryEnd) {
|
|
337
|
+
throwUnsupportedZip('ZIP central directory signatures are not supported by bounded extraction');
|
|
338
|
+
}
|
|
339
|
+
const entriesByLocalOffset = [...entries].sort((first, second) => first.localHeaderOffset - second.localHeaderOffset);
|
|
340
|
+
for (let index = 1; index < entriesByLocalOffset.length; index++) {
|
|
341
|
+
if (entriesByLocalOffset[index - 1].localRecordEnd >
|
|
342
|
+
entriesByLocalOffset[index].localHeaderOffset) {
|
|
343
|
+
throwInvalidZip('ZIP local file records overlap');
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
return entries;
|
|
347
|
+
}
|
|
348
|
+
function validateSelectiveOptions(options) {
|
|
349
|
+
if (!options || typeof options.filter !== 'function') {
|
|
350
|
+
throw new ZipError('ZIP extraction filter must be a function', ZIP_ERROR_CODES.INVALID_LIMIT);
|
|
351
|
+
}
|
|
352
|
+
const limits = [
|
|
353
|
+
options.maxArchiveBytes,
|
|
354
|
+
options.maxEntries,
|
|
355
|
+
options.maxSelectedEntries,
|
|
356
|
+
options.maxCompressedEntryBytes,
|
|
357
|
+
options.maxUncompressedEntryBytes,
|
|
358
|
+
options.maxTotalUncompressedBytes,
|
|
359
|
+
];
|
|
360
|
+
if (limits.some(limit => !Number.isSafeInteger(limit) || limit < 1)) {
|
|
361
|
+
throw new ZipError('ZIP extraction limits must be positive safe integers', ZIP_ERROR_CODES.INVALID_LIMIT);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
function updateCrc32(crc, data) {
|
|
365
|
+
let nextCrc = crc;
|
|
366
|
+
for (const byte of data) {
|
|
367
|
+
nextCrc = crc32Table[(nextCrc ^ byte) & 0xff] ^ (nextCrc >>> 8);
|
|
368
|
+
}
|
|
369
|
+
return nextCrc >>> 0;
|
|
370
|
+
}
|
|
371
|
+
function combineChunks(chunks, byteLength) {
|
|
372
|
+
const result = new Uint8Array(byteLength);
|
|
373
|
+
let offset = 0;
|
|
374
|
+
for (const chunk of chunks) {
|
|
375
|
+
result.set(chunk, offset);
|
|
376
|
+
offset += chunk.length;
|
|
44
377
|
}
|
|
378
|
+
return result;
|
|
45
379
|
}
|
|
46
380
|
/**
|
|
47
381
|
* ZIP compression and decompression utilities
|
|
48
382
|
*/
|
|
49
383
|
export class ZipTools {
|
|
50
384
|
/**
|
|
51
|
-
*
|
|
385
|
+
* Extract selected entries from a strict, bounded ZIP subset.
|
|
386
|
+
*
|
|
387
|
+
* This security-focused API accepts single-disk, non-ZIP64 archives and
|
|
388
|
+
* decompresses only entries selected from validated central-directory metadata.
|
|
52
389
|
*/
|
|
53
|
-
|
|
54
|
-
|
|
390
|
+
async extractSelectedZipEntries(data, options) {
|
|
391
|
+
validateSelectiveOptions(options);
|
|
392
|
+
if (!(data instanceof Uint8Array)) {
|
|
393
|
+
throw new ZipError('ZIP archive must be a Uint8Array', ZIP_ERROR_CODES.INVALID_ARCHIVE);
|
|
394
|
+
}
|
|
395
|
+
if (data.length > options.maxArchiveBytes) {
|
|
396
|
+
throw new ZipError(`ZIP archive has ${data.length} bytes, exceeding the configured limit`, ZIP_ERROR_CODES.ARCHIVE_SIZE_LIMIT);
|
|
397
|
+
}
|
|
398
|
+
const entries = parseZipEntries(data, options.maxEntries);
|
|
399
|
+
const selectedEntries = [];
|
|
400
|
+
const selectedPaths = new Set();
|
|
401
|
+
let declaredTotalUncompressedBytes = 0;
|
|
402
|
+
for (const entry of entries) {
|
|
403
|
+
const entryInfo = {
|
|
404
|
+
path: entry.path,
|
|
405
|
+
size: entry.uncompressedSize,
|
|
406
|
+
compressedSize: entry.compressedSize,
|
|
407
|
+
compressionMethod: entry.compressionMethod,
|
|
408
|
+
isDirectory: entry.isDirectory,
|
|
409
|
+
isFile: !entry.isDirectory,
|
|
410
|
+
};
|
|
411
|
+
if (!options.filter(entryInfo))
|
|
412
|
+
continue;
|
|
413
|
+
if (selectedPaths.has(entry.path)) {
|
|
414
|
+
throw new ZipError(`ZIP contains duplicate selected path: ${entry.path}`, ZIP_ERROR_CODES.DUPLICATE_SELECTED_PATH);
|
|
415
|
+
}
|
|
416
|
+
selectedPaths.add(entry.path);
|
|
417
|
+
if (selectedEntries.length >= options.maxSelectedEntries) {
|
|
418
|
+
throw new ZipError('ZIP selected entry count exceeds the configured limit', ZIP_ERROR_CODES.SELECTED_ENTRY_COUNT_LIMIT);
|
|
419
|
+
}
|
|
420
|
+
if (entry.compressedSize > options.maxCompressedEntryBytes) {
|
|
421
|
+
throw new ZipError(`ZIP selected entry ${entry.path} exceeds the compressed-size limit`, ZIP_ERROR_CODES.COMPRESSED_SIZE_LIMIT);
|
|
422
|
+
}
|
|
423
|
+
if (entry.uncompressedSize > options.maxUncompressedEntryBytes) {
|
|
424
|
+
throw new ZipError(`ZIP selected entry ${entry.path} exceeds the uncompressed-size limit`, ZIP_ERROR_CODES.UNCOMPRESSED_SIZE_LIMIT);
|
|
425
|
+
}
|
|
426
|
+
if (entry.uncompressedSize >
|
|
427
|
+
options.maxTotalUncompressedBytes - declaredTotalUncompressedBytes) {
|
|
428
|
+
throw new ZipError('ZIP selected entries exceed the total uncompressed-size limit', ZIP_ERROR_CODES.TOTAL_UNCOMPRESSED_SIZE_LIMIT);
|
|
429
|
+
}
|
|
430
|
+
if (entry.compressionMethod !== 0 && entry.compressionMethod !== 8) {
|
|
431
|
+
throw new ZipError(`ZIP selected entry ${entry.path} uses unsupported compression method ${entry.compressionMethod}`, ZIP_ERROR_CODES.UNSUPPORTED_FEATURE);
|
|
432
|
+
}
|
|
433
|
+
declaredTotalUncompressedBytes += entry.uncompressedSize;
|
|
434
|
+
selectedEntries.push(entry);
|
|
435
|
+
}
|
|
436
|
+
const extractedEntries = [];
|
|
437
|
+
let actualTotalUncompressedBytes = 0;
|
|
438
|
+
for (const entry of selectedEntries) {
|
|
439
|
+
const compressedData = data.subarray(entry.dataStart, entry.dataEnd);
|
|
440
|
+
let content;
|
|
441
|
+
let crcState = 0xffffffff;
|
|
442
|
+
if (entry.compressionMethod === 0) {
|
|
443
|
+
if (entry.compressedSize !== entry.uncompressedSize) {
|
|
444
|
+
throw new ZipError(`ZIP stored entry ${entry.path} has inconsistent sizes`, ZIP_ERROR_CODES.UNCOMPRESSED_SIZE_MISMATCH);
|
|
445
|
+
}
|
|
446
|
+
if (entry.uncompressedSize >
|
|
447
|
+
options.maxTotalUncompressedBytes - actualTotalUncompressedBytes) {
|
|
448
|
+
throw new ZipError('ZIP selected entries exceed the total uncompressed-size limit', ZIP_ERROR_CODES.TOTAL_UNCOMPRESSED_SIZE_LIMIT);
|
|
449
|
+
}
|
|
450
|
+
content = new Uint8Array(compressedData);
|
|
451
|
+
crcState = updateCrc32(crcState, content);
|
|
452
|
+
actualTotalUncompressedBytes += content.length;
|
|
453
|
+
}
|
|
454
|
+
else {
|
|
455
|
+
const chunks = [];
|
|
456
|
+
let actualEntryBytes = 0;
|
|
457
|
+
let zstream;
|
|
458
|
+
const inflater = new plugins.pako.Inflate({
|
|
459
|
+
raw: true,
|
|
460
|
+
chunkSize: PAKO_OUTPUT_CHUNK_BYTES,
|
|
461
|
+
});
|
|
462
|
+
inflater.onStart = (stream) => {
|
|
463
|
+
zstream = stream;
|
|
464
|
+
};
|
|
465
|
+
inflater.onData = (chunk) => {
|
|
466
|
+
if (chunk.length > entry.uncompressedSize - actualEntryBytes) {
|
|
467
|
+
throw new ZipError(`ZIP selected entry ${entry.path} expands beyond its declared size`, ZIP_ERROR_CODES.UNCOMPRESSED_SIZE_MISMATCH);
|
|
468
|
+
}
|
|
469
|
+
if (chunk.length > options.maxUncompressedEntryBytes - actualEntryBytes) {
|
|
470
|
+
throw new ZipError(`ZIP selected entry ${entry.path} exceeds the uncompressed-size limit`, ZIP_ERROR_CODES.UNCOMPRESSED_SIZE_LIMIT);
|
|
471
|
+
}
|
|
472
|
+
if (chunk.length >
|
|
473
|
+
options.maxTotalUncompressedBytes - actualTotalUncompressedBytes) {
|
|
474
|
+
throw new ZipError('ZIP selected entries exceed the total uncompressed-size limit', ZIP_ERROR_CODES.TOTAL_UNCOMPRESSED_SIZE_LIMIT);
|
|
475
|
+
}
|
|
476
|
+
const retainedChunk = chunk.slice();
|
|
477
|
+
chunks.push(retainedChunk);
|
|
478
|
+
crcState = updateCrc32(crcState, retainedChunk);
|
|
479
|
+
actualEntryBytes += retainedChunk.length;
|
|
480
|
+
actualTotalUncompressedBytes += retainedChunk.length;
|
|
481
|
+
};
|
|
482
|
+
let pushSucceeded = true;
|
|
483
|
+
let inputOffset = 0;
|
|
484
|
+
try {
|
|
485
|
+
do {
|
|
486
|
+
const inputEnd = Math.min(inputOffset + PAKO_INPUT_CHUNK_BYTES, compressedData.length);
|
|
487
|
+
pushSucceeded = inflater.push(compressedData.subarray(inputOffset, inputEnd), inputEnd === compressedData.length);
|
|
488
|
+
inputOffset = inputEnd;
|
|
489
|
+
if (!pushSucceeded)
|
|
490
|
+
break;
|
|
491
|
+
if (inflater.ended && inputOffset < compressedData.length) {
|
|
492
|
+
throw new ZipError(`ZIP selected entry ${entry.path} ended before consuming its compressed data`, ZIP_ERROR_CODES.COMPRESSED_SIZE_MISMATCH);
|
|
493
|
+
}
|
|
494
|
+
} while (inputOffset < compressedData.length);
|
|
495
|
+
}
|
|
496
|
+
catch (error) {
|
|
497
|
+
if (error instanceof ZipError)
|
|
498
|
+
throw error;
|
|
499
|
+
throw new ZipError(`ZIP selected entry ${entry.path} contains invalid DEFLATE data`, ZIP_ERROR_CODES.INVALID_ARCHIVE);
|
|
500
|
+
}
|
|
501
|
+
if (!pushSucceeded || inflater.err || !inflater.ended || !zstream) {
|
|
502
|
+
throw new ZipError(`ZIP selected entry ${entry.path} contains invalid or truncated DEFLATE data`, ZIP_ERROR_CODES.INVALID_ARCHIVE);
|
|
503
|
+
}
|
|
504
|
+
if (zstream.avail_in !== 0 || zstream.total_in !== compressedData.length) {
|
|
505
|
+
throw new ZipError(`ZIP selected entry ${entry.path} did not consume its exact compressed data`, ZIP_ERROR_CODES.COMPRESSED_SIZE_MISMATCH);
|
|
506
|
+
}
|
|
507
|
+
if (actualEntryBytes !== entry.uncompressedSize) {
|
|
508
|
+
throw new ZipError(`ZIP selected entry ${entry.path} did not produce its declared size`, ZIP_ERROR_CODES.UNCOMPRESSED_SIZE_MISMATCH);
|
|
509
|
+
}
|
|
510
|
+
content = combineChunks(chunks, actualEntryBytes);
|
|
511
|
+
}
|
|
512
|
+
const actualCrc32 = (crcState ^ 0xffffffff) >>> 0;
|
|
513
|
+
if (actualCrc32 !== entry.crc32) {
|
|
514
|
+
throw new ZipError(`ZIP selected entry ${entry.path} failed its CRC check`, ZIP_ERROR_CODES.CRC_MISMATCH);
|
|
515
|
+
}
|
|
516
|
+
extractedEntries.push({ path: entry.path, content });
|
|
517
|
+
}
|
|
518
|
+
return extractedEntries;
|
|
55
519
|
}
|
|
56
520
|
/**
|
|
57
521
|
* Create a ZIP archive from an array of entries
|
|
@@ -66,15 +530,8 @@ export class ZipTools {
|
|
|
66
530
|
else if (entry.content instanceof Uint8Array) {
|
|
67
531
|
data = entry.content;
|
|
68
532
|
}
|
|
69
|
-
else if (entry.content instanceof plugins.smartfile.SmartFile) {
|
|
70
|
-
data = new Uint8Array(entry.content.contents);
|
|
71
|
-
}
|
|
72
|
-
else if (entry.content instanceof plugins.smartfile.StreamFile) {
|
|
73
|
-
const buffer = await entry.content.getContentAsBuffer();
|
|
74
|
-
data = new Uint8Array(buffer);
|
|
75
|
-
}
|
|
76
533
|
else {
|
|
77
|
-
throw new Error('
|
|
534
|
+
throw new Error('Shared ZIP creation accepts string or Uint8Array content');
|
|
78
535
|
}
|
|
79
536
|
if (compressionLevel !== undefined) {
|
|
80
537
|
filesObj[entry.archivePath] = [data, { level: compressionLevel }];
|
|
@@ -100,4 +557,4 @@ export class ZipTools {
|
|
|
100
557
|
return entries;
|
|
101
558
|
}
|
|
102
559
|
}
|
|
103
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy56aXB0b29scy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzX3NoYXJlZC9jbGFzc2VzLnppcHRvb2xzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBR3hDOzs7R0FHRztBQUNILE1BQU0sT0FBTyx5QkFBMEIsU0FBUSxPQUFPLENBQUMsV0FBVyxDQUFDLFdBQXFEO0lBc0J0SDtRQUNFLEtBQUssQ0FBQztZQUNKLFVBQVUsRUFBRSxJQUFJO1lBQ2hCLGFBQWEsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLGNBQWMsRUFBRSxFQUFFO2dCQUNoRCxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxjQUFjLENBQUMsQ0FBQztnQkFDOUQsTUFBTSxLQUFLLEdBQUcsUUFBUSxZQUFZLFVBQVUsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxJQUFJLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQztnQkFDbkYsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO2dCQUNqQyxPQUFPLElBQUksQ0FBQztZQUNkLENBQUM7WUFDRCxhQUFhLEVBQUUsS0FBSyxJQUFJLEVBQUU7Z0JBQ3hCLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksVUFBVSxDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO2dCQUM1QyxNQUFNLE9BQU8sQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUNyQyxNQUFNLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUNsQyxPQUFPLElBQUksQ0FBQztZQUNkLENBQUM7U0FDRixDQUFDLENBQUM7UUFuQ0csYUFBUSxH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
|
|
560
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy56aXB0b29scy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzX3NoYXJlZC9jbGFzc2VzLnppcHRvb2xzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sdUJBQXVCLENBQUM7QUFDakQsT0FBTyxFQUFFLGVBQWUsRUFBRSxRQUFRLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFTeEQsTUFBTSwrQkFBK0IsR0FBRyxVQUFVLENBQUM7QUFDbkQsTUFBTSwrQkFBK0IsR0FBRyxVQUFVLENBQUM7QUFDbkQsTUFBTSxzQ0FBc0MsR0FBRyxVQUFVLENBQUM7QUFDMUQsTUFBTSxnREFBZ0QsR0FBRyxVQUFVLENBQUM7QUFDcEUsTUFBTSw2QkFBNkIsR0FBRyxVQUFVLENBQUM7QUFDakQsTUFBTSxvQkFBb0IsR0FBRyxNQUFNLENBQUM7QUFDcEMsTUFBTSwrQkFBK0IsR0FBRyxNQUFNLENBQUM7QUFDL0MsTUFBTSxpQ0FBaUMsR0FBRyxNQUFNLENBQUM7QUFDakQsTUFBTSxzQkFBc0IsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDO0FBQ3pDLE1BQU0sdUJBQXVCLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQztBQXdCMUMsTUFBTSxVQUFVLEdBQUcsQ0FBQyxHQUFHLEVBQUU7SUFDdkIsTUFBTSxLQUFLLEdBQUcsSUFBSSxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDbkMsS0FBSyxJQUFJLEtBQUssR0FBRyxDQUFDLEVBQUUsS0FBSyxHQUFHLEtBQUssQ0FBQyxNQUFNLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQztRQUNsRCxJQUFJLEtBQUssR0FBRyxLQUFLLENBQUM7UUFDbEIsS0FBSyxJQUFJLEdBQUcsR0FBRyxDQUFDLEVBQUUsR0FBRyxHQUFHLENBQUMsRUFBRSxHQUFHLEVBQUUsRUFBRSxDQUFDO1lBQ2pDLEtBQUssR0FBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLEdB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
|