@zip.js/zip.js 2.11.3 → 2.12.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/deno.json +1 -1
- package/dist/zip-core-external.js +444 -114
- package/dist/zip-core-external.min.js +1 -1
- package/dist/zip-core.js +454 -111
- package/dist/zip-core.min.js +1 -1
- package/dist/zip-fs-core-external.js +509 -236
- package/dist/zip-fs-core-external.min.js +1 -1
- package/dist/zip-fs-core.js +522 -233
- package/dist/zip-fs-core.min.js +1 -1
- package/dist/zip-fs-external.js +509 -236
- package/dist/zip-fs-external.min.js +1 -1
- package/dist/zip-fs-native.js +524 -235
- package/dist/zip-fs-native.min.js +1 -1
- package/dist/zip-fs.js +525 -236
- package/dist/zip-fs.min.js +1 -1
- package/dist/zip-legacy.js +456 -113
- package/dist/zip-legacy.min.js +1 -1
- package/dist/zip-native.js +456 -113
- package/dist/zip-native.min.js +1 -1
- package/dist/zip-web-worker-native.js +1 -1
- package/dist/zip-web-worker.js +1 -1
- package/dist/zip.js +457 -114
- package/dist/zip.min.js +1 -1
- package/index-native.cjs +524 -235
- package/index-native.min.js +1 -1
- package/index.cjs +525 -236
- package/index.d.cts +480 -59
- package/index.d.ts +480 -59
- package/index.min.js +1 -1
- package/lib/core/codec-worker-web.js +10 -2
- package/lib/core/codec-worker.js +4 -3
- package/lib/core/configuration.js +20 -5
- package/lib/core/constants.js +2 -0
- package/lib/core/io.js +20 -10
- package/lib/core/options.js +29 -0
- package/lib/core/streams/codec-stream.js +6 -0
- package/lib/core/util/warnings.js +42 -0
- package/lib/core/version.js +1 -1
- package/lib/core/web-worker-base.js +4 -3
- package/lib/core/web-worker-inline-native.js +1 -1
- package/lib/core/web-worker-inline-wasm.js +1 -1
- package/lib/core/zip-entry.js +49 -1
- package/lib/core/zip-fs.js +43 -134
- package/lib/core/zip-reader.js +108 -47
- package/lib/core/zip-writer.js +238 -54
- package/lib/zip-core-base.js +9 -3
- package/lib/zip-core-reader.js +2 -0
- package/lib/zip-core-writer.js +6 -1
- package/lib/zip-module-wasm-base.js +2 -2
- package/package.json +5 -3
package/dist/zip-core.js
CHANGED
|
@@ -134,6 +134,7 @@
|
|
|
134
134
|
const BOOLEAN_TYPE = "boolean";
|
|
135
135
|
|
|
136
136
|
const EMPTY_UINT8_ARRAY = new Uint8Array();
|
|
137
|
+
const SYMBOL_ASYNC_DISPOSE = Symbol.asyncDispose || Symbol();
|
|
137
138
|
|
|
138
139
|
/*
|
|
139
140
|
Copyright (c) 2022 Gildas Lormeau. All rights reserved.
|
|
@@ -178,6 +179,7 @@
|
|
|
178
179
|
const OPTION_CHECK_OVERLAPPING_ENTRY = "checkOverlappingEntry";
|
|
179
180
|
const OPTION_CHECK_AMBIGUITY = "checkAmbiguity";
|
|
180
181
|
const OPTION_CHECK_LOCAL_DIRECTORY = "checkLocalDirectory";
|
|
182
|
+
const OPTION_CHECK_LOCAL_FILENAME = "checkLocalFilename";
|
|
181
183
|
const OPTION_CHECK_SIGNATURE = "checkSignature";
|
|
182
184
|
const OPTION_CHECK_CRC32 = "checkCrc32";
|
|
183
185
|
const OPTION_CHECK_AUTHENTICATION_CODE = "checkAuthenticationCode";
|
|
@@ -208,15 +210,20 @@
|
|
|
208
210
|
const OPTION_MAX_APPENDED_DATA_SIZE = "maxAppendedDataSize";
|
|
209
211
|
const OPTION_DECRYPT_CENTRAL_DIRECTORY = "decryptCentralDirectory";
|
|
210
212
|
const OPTION_SIGN_CENTRAL_DIRECTORY = "signCentralDirectory";
|
|
213
|
+
const OPTION_ENTRY = "entry";
|
|
211
214
|
const TEXT_TYPE_FILENAME = "filename";
|
|
212
215
|
const TEXT_TYPE_COMMENT = "comment";
|
|
213
216
|
const STRICTNESS_STRICT = "strict";
|
|
214
217
|
const STRICTNESS_BALANCED = "balanced";
|
|
215
218
|
const STRICTNESS_TOLERANT = "tolerant";
|
|
219
|
+
const PASS_THROUGH_COMPRESSED = "compressed";
|
|
216
220
|
|
|
217
221
|
const ERR_INVALID_FUNCTION_OPTION = "Invalid option (must be a function)";
|
|
218
222
|
const ERR_INVALID_SIGNAL = "Invalid signal (must be an AbortSignal instance)";
|
|
219
223
|
const ERR_INVALID_PASSWORD_TYPE = "Invalid password (password must be a string, rawPassword must be a Uint8Array)";
|
|
224
|
+
const ERR_INVALID_PASS_THROUGH_VALUE = "Invalid passThrough option (must be a boolean or 'compressed')";
|
|
225
|
+
const ERR_ABORTED = "The operation was aborted";
|
|
226
|
+
const ABORT_ERROR_NAME = "AbortError";
|
|
220
227
|
|
|
221
228
|
function checkFunctionOption(value) {
|
|
222
229
|
if (value && typeof value != FUNCTION_TYPE) {
|
|
@@ -232,12 +239,25 @@
|
|
|
232
239
|
return signal || UNDEFINED_VALUE;
|
|
233
240
|
}
|
|
234
241
|
|
|
242
|
+
function throwIfAborted(signal) {
|
|
243
|
+
if (signal && signal.aborted) {
|
|
244
|
+
throw signal.reason === UNDEFINED_VALUE ? new DOMException(ERR_ABORTED, ABORT_ERROR_NAME) : signal.reason;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
235
248
|
function checkPasswordOption(password, rawPassword) {
|
|
236
249
|
if ((password && typeof password != STRING_TYPE) || (rawPassword && !(rawPassword instanceof Uint8Array))) {
|
|
237
250
|
throw new Error(ERR_INVALID_PASSWORD_TYPE);
|
|
238
251
|
}
|
|
239
252
|
}
|
|
240
253
|
|
|
254
|
+
function checkPassThroughOption(passThrough) {
|
|
255
|
+
if (passThrough !== UNDEFINED_VALUE && typeof passThrough != BOOLEAN_TYPE && passThrough !== PASS_THROUGH_COMPRESSED) {
|
|
256
|
+
throw new Error(ERR_INVALID_PASS_THROUGH_VALUE);
|
|
257
|
+
}
|
|
258
|
+
return passThrough;
|
|
259
|
+
}
|
|
260
|
+
|
|
241
261
|
function checkInteger(value, maxValue, errorMessage) {
|
|
242
262
|
if (!Number.isInteger(value) || value < 0 || value > maxValue) {
|
|
243
263
|
throw new Error(errorMessage);
|
|
@@ -287,6 +307,8 @@
|
|
|
287
307
|
const MINIMUM_CHUNK_SIZE = 64;
|
|
288
308
|
const MINIMUM_PROPERTY_VALUE = 1;
|
|
289
309
|
const ERR_INVALID_MAX_WORKERS = "Invalid maxWorkers (must be an integer greater than 0)";
|
|
310
|
+
const ERR_INVALID_BASE_URI = "Invalid baseURI (must be a string)";
|
|
311
|
+
const ERR_INVALID_URI = "Invalid URI (must be a string or a function returning a string)";
|
|
290
312
|
let maxWorkers = 2;
|
|
291
313
|
try {
|
|
292
314
|
if (typeof navigator != UNDEFINED_TYPE && navigator.hardwareConcurrency) {
|
|
@@ -311,9 +333,9 @@
|
|
|
311
333
|
};
|
|
312
334
|
|
|
313
335
|
const PROPERTY_NAME_MAX_WORKERS = "maxWorkers";
|
|
336
|
+
const PROPERTY_NAME_BASE_URI = "baseURI";
|
|
314
337
|
|
|
315
|
-
const
|
|
316
|
-
"baseURI",
|
|
338
|
+
const URI_PROPERTY_NAMES = [
|
|
317
339
|
"wasmURI",
|
|
318
340
|
"workerURI"
|
|
319
341
|
];
|
|
@@ -337,7 +359,8 @@
|
|
|
337
359
|
"DecompressionStreamFallback"
|
|
338
360
|
];
|
|
339
361
|
const CONFIGURABLE_PROPERTY_NAMES = [
|
|
340
|
-
|
|
362
|
+
PROPERTY_NAME_BASE_URI,
|
|
363
|
+
...URI_PROPERTY_NAMES,
|
|
341
364
|
...BOOLEAN_PROPERTY_NAMES,
|
|
342
365
|
...NUMBER_PROPERTY_NAMES,
|
|
343
366
|
...FUNCTION_PROPERTY_NAMES
|
|
@@ -381,6 +404,14 @@
|
|
|
381
404
|
}
|
|
382
405
|
} else if (FUNCTION_PROPERTY_NAMES.includes(propertyName)) {
|
|
383
406
|
checkFunctionOption(propertyValue);
|
|
407
|
+
} else if (propertyName == PROPERTY_NAME_BASE_URI) {
|
|
408
|
+
if (propertyValue && typeof propertyValue != STRING_TYPE) {
|
|
409
|
+
throw new Error(ERR_INVALID_BASE_URI);
|
|
410
|
+
}
|
|
411
|
+
} else if (URI_PROPERTY_NAMES.includes(propertyName)) {
|
|
412
|
+
if (propertyValue && typeof propertyValue != STRING_TYPE && typeof propertyValue != FUNCTION_TYPE) {
|
|
413
|
+
throw new Error(ERR_INVALID_URI);
|
|
414
|
+
}
|
|
384
415
|
}
|
|
385
416
|
return propertyValue;
|
|
386
417
|
}
|
|
@@ -2597,6 +2628,7 @@
|
|
|
2597
2628
|
constructor(chunkSize) {
|
|
2598
2629
|
const pendingChunks = [];
|
|
2599
2630
|
let pendingLength = 0;
|
|
2631
|
+
let outputSize = 0;
|
|
2600
2632
|
if (!Number.isFinite(chunkSize) || chunkSize < 1) {
|
|
2601
2633
|
chunkSize = DEFAULT_CHUNK_SIZE;
|
|
2602
2634
|
}
|
|
@@ -2605,15 +2637,20 @@
|
|
|
2605
2637
|
pendingChunks.push(chunk);
|
|
2606
2638
|
pendingLength += chunk.length;
|
|
2607
2639
|
while (pendingLength > chunkSize) {
|
|
2640
|
+
outputSize += chunkSize;
|
|
2608
2641
|
controller.enqueue(shiftChunk());
|
|
2609
2642
|
}
|
|
2610
2643
|
},
|
|
2611
2644
|
flush(controller) {
|
|
2612
2645
|
if (pendingLength) {
|
|
2646
|
+
outputSize += pendingLength;
|
|
2613
2647
|
controller.enqueue(concatChunks(pendingChunks, pendingLength));
|
|
2614
2648
|
}
|
|
2615
2649
|
}
|
|
2616
2650
|
});
|
|
2651
|
+
Object.defineProperty(this, "outputSize", {
|
|
2652
|
+
get: () => outputSize
|
|
2653
|
+
});
|
|
2617
2654
|
|
|
2618
2655
|
function shiftChunk() {
|
|
2619
2656
|
const result = new Uint8Array(chunkSize);
|
|
@@ -2814,7 +2851,7 @@
|
|
|
2814
2851
|
}
|
|
2815
2852
|
|
|
2816
2853
|
async function runWorker$1({ options, readable, writable, onTaskFinished }, config) {
|
|
2817
|
-
let codecStream;
|
|
2854
|
+
let codecStream, chunkStream;
|
|
2818
2855
|
try {
|
|
2819
2856
|
if (options.compressed && !options.format) {
|
|
2820
2857
|
const deflate = options.codecType.startsWith(CODEC_DEFLATE);
|
|
@@ -2837,9 +2874,10 @@
|
|
|
2837
2874
|
}
|
|
2838
2875
|
}
|
|
2839
2876
|
codecStream = new CodecStream(options, config);
|
|
2877
|
+
chunkStream = new ChunkStream(getChunkSize(config));
|
|
2840
2878
|
await readable
|
|
2841
2879
|
.pipeThrough(codecStream)
|
|
2842
|
-
.pipeThrough(
|
|
2880
|
+
.pipeThrough(chunkStream)
|
|
2843
2881
|
.pipeTo(writable, { preventClose: true, preventAbort: true });
|
|
2844
2882
|
const {
|
|
2845
2883
|
crc32,
|
|
@@ -2853,7 +2891,7 @@
|
|
|
2853
2891
|
};
|
|
2854
2892
|
} catch (error) {
|
|
2855
2893
|
if (codecStream) {
|
|
2856
|
-
error.outputSize =
|
|
2894
|
+
error.outputSize = chunkStream ? chunkStream.outputSize : 0;
|
|
2857
2895
|
}
|
|
2858
2896
|
throw error;
|
|
2859
2897
|
} finally {
|
|
@@ -2962,11 +3000,17 @@
|
|
|
2962
3000
|
let resolveResult, rejectResult;
|
|
2963
3001
|
const result = new Promise((resolve, reject) => {
|
|
2964
3002
|
resolveResult = resolve;
|
|
2965
|
-
rejectResult =
|
|
3003
|
+
rejectResult = error => {
|
|
3004
|
+
if (error && error.outputSize === UNDEFINED_VALUE) {
|
|
3005
|
+
error.outputSize = workerData.outputSize;
|
|
3006
|
+
}
|
|
3007
|
+
reject(error);
|
|
3008
|
+
};
|
|
2966
3009
|
});
|
|
2967
3010
|
Object.assign(workerData, {
|
|
2968
3011
|
reader: null,
|
|
2969
3012
|
writer: null,
|
|
3013
|
+
outputSize: 0,
|
|
2970
3014
|
resolveResult,
|
|
2971
3015
|
rejectResult,
|
|
2972
3016
|
result
|
|
@@ -3250,8 +3294,10 @@
|
|
|
3250
3294
|
}
|
|
3251
3295
|
}
|
|
3252
3296
|
if (type == MESSAGE_DATA) {
|
|
3297
|
+
const chunk = new Uint8Array(value);
|
|
3253
3298
|
await writer.ready;
|
|
3254
|
-
await writer.write(
|
|
3299
|
+
await writer.write(chunk);
|
|
3300
|
+
workerData.outputSize += chunk.length;
|
|
3255
3301
|
if (!stale()) {
|
|
3256
3302
|
sendMessage({ type: MESSAGE_ACK_DATA, messageId }, workerData);
|
|
3257
3303
|
}
|
|
@@ -3559,10 +3605,13 @@
|
|
|
3559
3605
|
|
|
3560
3606
|
|
|
3561
3607
|
const ERR_HTTP_STATUS = "HTTP error ";
|
|
3608
|
+
const MIN_SUCCESS_HTTP_STATUS = 200;
|
|
3609
|
+
const MAX_SUCCESS_HTTP_STATUS = 299;
|
|
3562
3610
|
const ERR_HTTP_RANGE = "HTTP Range not supported";
|
|
3563
3611
|
const ERR_HTTP_RESOURCE_CHANGED = "HTTP resource changed";
|
|
3564
3612
|
const ERR_ITERATOR_COMPLETED_TOO_SOON = "Writer iterator completed too soon";
|
|
3565
3613
|
const ERR_WRITER_NOT_INITIALIZED = "Writer not initialized";
|
|
3614
|
+
const ERR_WRITER_SIZE_NOT_WRITABLE = "Invalid writer (size must be writable)";
|
|
3566
3615
|
|
|
3567
3616
|
const CONTENT_TYPE_TEXT_PLAIN = "text/plain";
|
|
3568
3617
|
const HTTP_HEADER_CONTENT_LENGTH = "Content-Length";
|
|
@@ -3754,11 +3803,14 @@
|
|
|
3754
3803
|
const reader = this;
|
|
3755
3804
|
const { sourceBlob, size } = reader;
|
|
3756
3805
|
const { offset = 0, size: readSize = size - offset } = options || {};
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3806
|
+
// deno-lint-ignore valid-typeof
|
|
3807
|
+
if (typeof sourceBlob.stream == FUNCTION_TYPE) {
|
|
3808
|
+
if (!offset && readSize >= size) {
|
|
3809
|
+
return toCompatibleReadable(sourceBlob.stream());
|
|
3810
|
+
}
|
|
3811
|
+
if (blobSliceReliable) {
|
|
3812
|
+
return toCompatibleReadable(sourceBlob.slice(offset, offset + readSize).stream());
|
|
3813
|
+
}
|
|
3762
3814
|
}
|
|
3763
3815
|
return super.createReadable(options);
|
|
3764
3816
|
}
|
|
@@ -4138,7 +4190,7 @@
|
|
|
4138
4190
|
|
|
4139
4191
|
async function sendFetchRequest(method, { fetch: fetchFunction = fetch, options, url }, headers) {
|
|
4140
4192
|
const response = await fetchFunction(url, Object.assign({}, options, { method, headers }));
|
|
4141
|
-
if (response.status
|
|
4193
|
+
if (response.status >= MIN_SUCCESS_HTTP_STATUS && response.status <= MAX_SUCCESS_HTTP_STATUS) {
|
|
4142
4194
|
return response;
|
|
4143
4195
|
} else {
|
|
4144
4196
|
throw response.status == 416 ? new Error(ERR_HTTP_RANGE) : new Error(ERR_HTTP_STATUS + (response.statusText || response.status));
|
|
@@ -4149,7 +4201,7 @@
|
|
|
4149
4201
|
return new Promise((resolve, reject) => {
|
|
4150
4202
|
const request = new XMLHttpRequest();
|
|
4151
4203
|
request.addEventListener("load", () => {
|
|
4152
|
-
if (request.status
|
|
4204
|
+
if (request.status >= MIN_SUCCESS_HTTP_STATUS && request.status <= MAX_SUCCESS_HTTP_STATUS) {
|
|
4153
4205
|
const headers = [];
|
|
4154
4206
|
request.getAllResponseHeaders().trim().split(/[\r\n]+/).forEach(header => {
|
|
4155
4207
|
const splitHeader = header.trim().split(/\s*:\s*/);
|
|
@@ -4453,8 +4505,10 @@
|
|
|
4453
4505
|
writable: toCompatibleWritable(writer)
|
|
4454
4506
|
};
|
|
4455
4507
|
}
|
|
4456
|
-
|
|
4457
|
-
writer.size = 0;
|
|
4508
|
+
try {
|
|
4509
|
+
writer.size = writer.size === UNDEFINED_VALUE ? 0 : writer.size;
|
|
4510
|
+
} catch {
|
|
4511
|
+
throw new Error(ERR_WRITER_SIZE_NOT_WRITABLE);
|
|
4458
4512
|
}
|
|
4459
4513
|
return writer;
|
|
4460
4514
|
}
|
|
@@ -4502,6 +4556,45 @@
|
|
|
4502
4556
|
}
|
|
4503
4557
|
}
|
|
4504
4558
|
|
|
4559
|
+
/*
|
|
4560
|
+
Copyright (c) 2026 Gildas Lormeau. All rights reserved.
|
|
4561
|
+
|
|
4562
|
+
Redistribution and use in source and binary forms, with or without
|
|
4563
|
+
modification, are permitted provided that the following conditions are met:
|
|
4564
|
+
|
|
4565
|
+
1. Redistributions of source code must retain the above copyright notice,
|
|
4566
|
+
this list of conditions and the following disclaimer.
|
|
4567
|
+
|
|
4568
|
+
2. Redistributions in binary form must reproduce the above copyright
|
|
4569
|
+
notice, this list of conditions and the following disclaimer in
|
|
4570
|
+
the documentation and/or other materials provided with the distribution.
|
|
4571
|
+
|
|
4572
|
+
3. The names of the authors may not be used to endorse or promote products
|
|
4573
|
+
derived from this software without specific prior written permission.
|
|
4574
|
+
|
|
4575
|
+
THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
|
4576
|
+
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
4577
|
+
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
|
4578
|
+
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
4579
|
+
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
4580
|
+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
|
4581
|
+
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
4582
|
+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
4583
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
|
4584
|
+
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
4585
|
+
*/
|
|
4586
|
+
|
|
4587
|
+
|
|
4588
|
+
function addWarning(warnings, reason, filename) {
|
|
4589
|
+
if (!warnings.some(warning => warning.reason == reason)) {
|
|
4590
|
+
const warning = { reason };
|
|
4591
|
+
if (filename !== UNDEFINED_VALUE) {
|
|
4592
|
+
warning.filename = filename;
|
|
4593
|
+
}
|
|
4594
|
+
warnings.push(warning);
|
|
4595
|
+
}
|
|
4596
|
+
}
|
|
4597
|
+
|
|
4505
4598
|
/*
|
|
4506
4599
|
Copyright (c) 2025 Gildas Lormeau. All rights reserved.
|
|
4507
4600
|
|
|
@@ -4530,6 +4623,7 @@
|
|
|
4530
4623
|
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
4531
4624
|
*/
|
|
4532
4625
|
|
|
4626
|
+
|
|
4533
4627
|
const PROPERTY_NAME_FILENAME = "filename";
|
|
4534
4628
|
const PROPERTY_NAME_RAW_FILENAME = "rawFilename";
|
|
4535
4629
|
const PROPERTY_NAME_COMMENT = "comment";
|
|
@@ -4654,6 +4748,38 @@
|
|
|
4654
4748
|
|
|
4655
4749
|
}
|
|
4656
4750
|
|
|
4751
|
+
const INTERPRETED_EXTRA_FIELD_TYPES = new Set([
|
|
4752
|
+
EXTRAFIELD_TYPE_ZIP64,
|
|
4753
|
+
EXTRAFIELD_TYPE_AES,
|
|
4754
|
+
EXTRAFIELD_TYPE_NTFS,
|
|
4755
|
+
EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP,
|
|
4756
|
+
EXTRAFIELD_TYPE_UNICODE_PATH,
|
|
4757
|
+
EXTRAFIELD_TYPE_UNICODE_COMMENT,
|
|
4758
|
+
EXTRAFIELD_TYPE_USDZ,
|
|
4759
|
+
EXTRAFIELD_TYPE_INFOZIP,
|
|
4760
|
+
EXTRAFIELD_TYPE_UNIX,
|
|
4761
|
+
EXTRAFIELD_TYPE_UNIX_TYPE1,
|
|
4762
|
+
EXTRAFIELD_TYPE_PKWARE_UNIX
|
|
4763
|
+
]);
|
|
4764
|
+
|
|
4765
|
+
function getUserExtraField(extraField) {
|
|
4766
|
+
if (extraField) {
|
|
4767
|
+
const userExtraField = new Map();
|
|
4768
|
+
extraField.forEach((field, type) => {
|
|
4769
|
+
if (!INTERPRETED_EXTRA_FIELD_TYPES.has(type)) {
|
|
4770
|
+
userExtraField.set(type, field.data);
|
|
4771
|
+
}
|
|
4772
|
+
});
|
|
4773
|
+
if (userExtraField.size) {
|
|
4774
|
+
return userExtraField;
|
|
4775
|
+
}
|
|
4776
|
+
}
|
|
4777
|
+
}
|
|
4778
|
+
|
|
4779
|
+
function getEncryptionOverhead(encrypted, zipCrypto, encryptionStrength) {
|
|
4780
|
+
return encrypted ? (zipCrypto ? 12 : 16 + encryptionStrength * 4) : 0;
|
|
4781
|
+
}
|
|
4782
|
+
|
|
4657
4783
|
/*
|
|
4658
4784
|
Copyright (c) 2025 Gildas Lormeau. All rights reserved.
|
|
4659
4785
|
|
|
@@ -4713,6 +4839,8 @@
|
|
|
4713
4839
|
const WARNING_TRAILING_CENTRAL_DIRECTORY_DATA = "trailing central directory data";
|
|
4714
4840
|
const WARNING_DUPLICATE_FILENAME = "duplicate filename";
|
|
4715
4841
|
const WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY = "mismatched zip64 end of central directory record";
|
|
4842
|
+
const WARNING_MULTIPLE_END_OF_CENTRAL_DIRECTORY = "multiple end of central directory records";
|
|
4843
|
+
const WARNING_MISMATCHED_LOCAL_FILE_HEADER_FILENAME = "mismatched local file header (filename)";
|
|
4716
4844
|
const WARNING_MISMATCHED_LOCAL_FILE_HEADER_BIT_FLAG = "mismatched local file header (general purpose bit flag)";
|
|
4717
4845
|
const WARNING_MISMATCHED_LOCAL_FILE_HEADER_COMPRESSION_METHOD = "mismatched local file header (compression method)";
|
|
4718
4846
|
const WARNING_MISMATCHED_LOCAL_FILE_HEADER_CRC32_OR_SIZES = "mismatched local file header (crc32 or sizes)";
|
|
@@ -4783,7 +4911,7 @@
|
|
|
4783
4911
|
}
|
|
4784
4912
|
}
|
|
4785
4913
|
if (rejectAmbiguousEndOfDirectory && endOfDirectoryReachingEndCount > 1) {
|
|
4786
|
-
throwAmbiguousArchive(
|
|
4914
|
+
throwAmbiguousArchive(WARNING_MULTIPLE_END_OF_CENTRAL_DIRECTORY);
|
|
4787
4915
|
}
|
|
4788
4916
|
const endOfDirectoryView = getDataView(endOfDirectoryInfo);
|
|
4789
4917
|
let directoryDataLength = getUint32$1(endOfDirectoryView, 12);
|
|
@@ -5081,7 +5209,8 @@
|
|
|
5081
5209
|
const writer = new TransformStream();
|
|
5082
5210
|
const arrayBufferPromise = streamToBlob(writer.readable).then(blob => blob.arrayBuffer());
|
|
5083
5211
|
arrayBufferPromise.catch(() => { });
|
|
5084
|
-
await fileEntry.getData(writer, entry, zipReader.readRanges,
|
|
5212
|
+
await fileEntry.getData(writer, entry, zipReader.readRanges,
|
|
5213
|
+
Object.assign({}, options, { preventClose: false }));
|
|
5085
5214
|
return arrayBufferPromise;
|
|
5086
5215
|
};
|
|
5087
5216
|
offset = endOffset;
|
|
@@ -5162,48 +5291,101 @@
|
|
|
5162
5291
|
await reader.readable.cancel();
|
|
5163
5292
|
}
|
|
5164
5293
|
}
|
|
5294
|
+
|
|
5295
|
+
[SYMBOL_ASYNC_DISPOSE]() {
|
|
5296
|
+
return this.close();
|
|
5297
|
+
}
|
|
5165
5298
|
}
|
|
5166
5299
|
|
|
5167
5300
|
class ZipReaderStream {
|
|
5168
5301
|
|
|
5169
5302
|
constructor(options = {}) {
|
|
5170
|
-
|
|
5171
|
-
const
|
|
5303
|
+
let sourceController;
|
|
5304
|
+
const { readable, writable } = new TransformStream({
|
|
5305
|
+
start(controller) {
|
|
5306
|
+
sourceController = controller;
|
|
5307
|
+
}
|
|
5308
|
+
});
|
|
5309
|
+
const zipReader = new ZipReader(readable, options);
|
|
5310
|
+
const gen = zipReader.getEntriesGenerator();
|
|
5311
|
+
const pendingEntries = new Set();
|
|
5172
5312
|
this.readable = new ReadableStream({
|
|
5173
5313
|
async pull(controller) {
|
|
5174
5314
|
const { done, value } = await gen.next();
|
|
5175
5315
|
if (done)
|
|
5176
5316
|
return controller.close();
|
|
5317
|
+
const entryStream = createEntryStream(value, pendingEntries);
|
|
5177
5318
|
const chunk = {
|
|
5178
5319
|
...value,
|
|
5179
|
-
readable:
|
|
5180
|
-
const { readable, writable } = new TransformStream();
|
|
5181
|
-
if (value.getData) {
|
|
5182
|
-
getData();
|
|
5183
|
-
return readable;
|
|
5184
|
-
}
|
|
5185
|
-
|
|
5186
|
-
async function getData() {
|
|
5187
|
-
try {
|
|
5188
|
-
await value.getData(writable);
|
|
5189
|
-
} catch (error) {
|
|
5190
|
-
try {
|
|
5191
|
-
await writable.abort(error);
|
|
5192
|
-
} catch {
|
|
5193
|
-
// ignored
|
|
5194
|
-
}
|
|
5195
|
-
}
|
|
5196
|
-
}
|
|
5197
|
-
})()
|
|
5320
|
+
readable: entryStream.readable
|
|
5198
5321
|
};
|
|
5199
5322
|
delete chunk.getData;
|
|
5323
|
+
Object.defineProperties(chunk, {
|
|
5324
|
+
localDirectory: {
|
|
5325
|
+
get: () => value.localDirectory,
|
|
5326
|
+
enumerable: true
|
|
5327
|
+
},
|
|
5328
|
+
warnings: {
|
|
5329
|
+
get: () => value.warnings,
|
|
5330
|
+
enumerable: true
|
|
5331
|
+
}
|
|
5332
|
+
});
|
|
5200
5333
|
controller.enqueue(chunk);
|
|
5334
|
+
},
|
|
5335
|
+
async cancel(reason) {
|
|
5336
|
+
const entryStreams = Array.from(pendingEntries);
|
|
5337
|
+
pendingEntries.clear();
|
|
5338
|
+
sourceController.error(reason);
|
|
5339
|
+
await Promise.allSettled(entryStreams.map(entryStream => entryStream.cancel(reason)));
|
|
5340
|
+
await Promise.allSettled([gen.return(), zipReader.close()]);
|
|
5201
5341
|
}
|
|
5202
5342
|
});
|
|
5203
5343
|
this.writable = writable;
|
|
5204
5344
|
}
|
|
5205
5345
|
}
|
|
5206
5346
|
|
|
5347
|
+
function createEntryStream(entry, pendingEntries) {
|
|
5348
|
+
const { readable, writable } = new TransformStream();
|
|
5349
|
+
let dataReader;
|
|
5350
|
+
const entryStream = {
|
|
5351
|
+
cancel: async reason => {
|
|
5352
|
+
pendingEntries.delete(entryStream);
|
|
5353
|
+
await (dataReader ? dataReader.cancel(reason) : readable.cancel(reason));
|
|
5354
|
+
}
|
|
5355
|
+
};
|
|
5356
|
+
entryStream.readable = new ReadableStream({
|
|
5357
|
+
async pull(controller) {
|
|
5358
|
+
if (!dataReader) {
|
|
5359
|
+
dataReader = readable.getReader();
|
|
5360
|
+
pendingEntries.add(entryStream);
|
|
5361
|
+
getData();
|
|
5362
|
+
}
|
|
5363
|
+
const { done, value } = await dataReader.read();
|
|
5364
|
+
if (done) {
|
|
5365
|
+
controller.close();
|
|
5366
|
+
} else {
|
|
5367
|
+
controller.enqueue(value);
|
|
5368
|
+
}
|
|
5369
|
+
},
|
|
5370
|
+
cancel: reason => entryStream.cancel(reason)
|
|
5371
|
+
}, { highWaterMark: 0 });
|
|
5372
|
+
return entryStream;
|
|
5373
|
+
|
|
5374
|
+
async function getData() {
|
|
5375
|
+
try {
|
|
5376
|
+
await entry.getData(writable, { preventClose: false });
|
|
5377
|
+
} catch (error) {
|
|
5378
|
+
try {
|
|
5379
|
+
await writable.abort(error);
|
|
5380
|
+
} catch {
|
|
5381
|
+
// ignored
|
|
5382
|
+
}
|
|
5383
|
+
} finally {
|
|
5384
|
+
pendingEntries.delete(entryStream);
|
|
5385
|
+
}
|
|
5386
|
+
}
|
|
5387
|
+
}
|
|
5388
|
+
|
|
5207
5389
|
async function isZipFile(reader, options = {}) {
|
|
5208
5390
|
reader = new GenericReader(reader);
|
|
5209
5391
|
await initStream(reader);
|
|
@@ -5263,7 +5445,9 @@
|
|
|
5263
5445
|
const dataView = getDataView(dataArray);
|
|
5264
5446
|
let password = getOptionValue$1(zipEntry, options, OPTION_PASSWORD);
|
|
5265
5447
|
let rawPassword = getOptionValue$1(zipEntry, options, OPTION_RAW_PASSWORD);
|
|
5266
|
-
const passThrough = getOptionValue$1(zipEntry, options, OPTION_PASS_THROUGH);
|
|
5448
|
+
const passThrough = checkPassThroughOption(getOptionValue$1(zipEntry, options, OPTION_PASS_THROUGH));
|
|
5449
|
+
const passThroughCompression = Boolean(passThrough);
|
|
5450
|
+
const passThroughEncryption = passThrough === true;
|
|
5267
5451
|
checkPasswordOption(password, rawPassword);
|
|
5268
5452
|
password = password && password.length && password;
|
|
5269
5453
|
rawPassword = rawPassword && rawPassword.length && rawPassword;
|
|
@@ -5284,7 +5468,9 @@
|
|
|
5284
5468
|
const checkLocalDirectoryOption = getOptionValue$1(zipEntry, options, OPTION_CHECK_LOCAL_DIRECTORY);
|
|
5285
5469
|
const entryStrictness = getStrictness(options, zipEntry.options);
|
|
5286
5470
|
const checkLocalDirectory = getCheckLocalDirectory(checkLocalDirectoryOption, entryStrictness);
|
|
5287
|
-
const
|
|
5471
|
+
const checkLocalFilenameOption = getOptionValue$1(zipEntry, options, OPTION_CHECK_LOCAL_FILENAME);
|
|
5472
|
+
const checkLocalFilename = getCheckLocalFilename(
|
|
5473
|
+
checkLocalFilenameOption === UNDEFINED_VALUE ? checkLocalDirectoryOption : checkLocalFilenameOption, entryStrictness);
|
|
5288
5474
|
let rawLocalFilename = EMPTY_UINT8_ARRAY;
|
|
5289
5475
|
if (checkLocalFilename && (filenameLength || extraFieldLength)) {
|
|
5290
5476
|
const trailingDataArray = await readUint8Array(reader, localHeaderOffset + HEADER_SIZE, filenameLength + extraFieldLength);
|
|
@@ -5315,16 +5501,17 @@
|
|
|
5315
5501
|
if (gid !== UNDEFINED_VALUE && fileEntry.gid === UNDEFINED_VALUE) {
|
|
5316
5502
|
fileEntry.gid = gid;
|
|
5317
5503
|
}
|
|
5318
|
-
const
|
|
5504
|
+
const checkPasswordOnly = getOptionValue$1(zipEntry, options, OPTION_CHECK_PASSWORD_ONLY);
|
|
5505
|
+
const encrypted = zipEntry.encrypted && localDirectory.encrypted && (!passThroughEncryption || checkPasswordOnly);
|
|
5319
5506
|
const zipCrypto = encrypted && !extraFieldAES;
|
|
5320
|
-
if (!
|
|
5507
|
+
if (!passThroughEncryption) {
|
|
5321
5508
|
fileEntry.zipCrypto = zipCrypto;
|
|
5322
5509
|
}
|
|
5323
5510
|
if (encrypted && (localDirectory.rawBitFlag & BITFLAG_STRONG_ENCRYPTION) == BITFLAG_STRONG_ENCRYPTION) {
|
|
5324
5511
|
throw new Error(ERR_UNSUPPORTED_ENCRYPTION);
|
|
5325
5512
|
}
|
|
5326
|
-
const registeredCodec =
|
|
5327
|
-
if (compressionMethod != COMPRESSION_METHOD_STORE && compressionMethod != COMPRESSION_METHOD_DEFLATE && compressionMethod != COMPRESSION_METHOD_DEFLATE_64 && !registeredCodec && !
|
|
5513
|
+
const registeredCodec = passThroughCompression ? UNDEFINED_VALUE : getRegisteredCodec(compressionMethod);
|
|
5514
|
+
if (compressionMethod != COMPRESSION_METHOD_STORE && compressionMethod != COMPRESSION_METHOD_DEFLATE && compressionMethod != COMPRESSION_METHOD_DEFLATE_64 && !registeredCodec && !passThroughCompression) {
|
|
5328
5515
|
throw new Error(ERR_UNSUPPORTED_COMPRESSION);
|
|
5329
5516
|
}
|
|
5330
5517
|
if (encrypted) {
|
|
@@ -5340,15 +5527,17 @@
|
|
|
5340
5527
|
const size = compressedSize;
|
|
5341
5528
|
const readable = toCompatibleReadable(reader.createReadable({ offset: dataOffset, size }));
|
|
5342
5529
|
const signal = checkSignalOption(getOptionValue$1(zipEntry, options, OPTION_SIGNAL));
|
|
5343
|
-
|
|
5530
|
+
throwIfAborted(signal);
|
|
5344
5531
|
let checkOverlappingEntry = getOptionValue$1(zipEntry, options, OPTION_CHECK_OVERLAPPING_ENTRY);
|
|
5345
5532
|
const checkOverlappingEntryOnly = getOptionValue$1(zipEntry, options, OPTION_CHECK_OVERLAPPING_ENTRY_ONLY);
|
|
5346
5533
|
if (checkOverlappingEntryOnly) {
|
|
5347
5534
|
checkOverlappingEntry = true;
|
|
5348
5535
|
}
|
|
5349
5536
|
const { onstart, onprogress, onend } = options;
|
|
5350
|
-
const compressed = compressionMethod != COMPRESSION_METHOD_STORE && !
|
|
5351
|
-
const outputSize =
|
|
5537
|
+
const compressed = compressionMethod != COMPRESSION_METHOD_STORE && !passThroughCompression;
|
|
5538
|
+
const outputSize = passThroughCompression ?
|
|
5539
|
+
compressedSize - getEncryptionOverhead(encrypted, zipCrypto, extraFieldAES && extraFieldAES.strength) :
|
|
5540
|
+
uncompressedSize;
|
|
5352
5541
|
const deflate64 = compressionMethod == COMPRESSION_METHOD_DEFLATE_64;
|
|
5353
5542
|
let useCompressionStream = getOptionValue$1(zipEntry, options, OPTION_USE_COMPRESSION_STREAM);
|
|
5354
5543
|
if (deflate64) {
|
|
@@ -5357,7 +5546,7 @@
|
|
|
5357
5546
|
const checkCrc32Option = getOptionValue$1(zipEntry, options, OPTION_CHECK_CRC32);
|
|
5358
5547
|
const checkCrc32 = (checkCrc32Option === UNDEFINED_VALUE ?
|
|
5359
5548
|
getOptionValue$1(zipEntry, options, OPTION_CHECK_SIGNATURE) :
|
|
5360
|
-
checkCrc32Option) && !
|
|
5549
|
+
checkCrc32Option) && !passThroughCompression &&
|
|
5361
5550
|
(!encrypted || zipCrypto || (extraFieldAES && extraFieldAES.vendorVersion == VENDOR_VERSION_AE_1$1));
|
|
5362
5551
|
const workerOptions = {
|
|
5363
5552
|
options: {
|
|
@@ -5411,10 +5600,10 @@
|
|
|
5411
5600
|
await initStream(writer, getDecodableOutputSize(outputSize, compressedSize, compressed));
|
|
5412
5601
|
({ writable } = writer);
|
|
5413
5602
|
const { outputSize: writtenSize } = await runWorker({ readable, writable }, workerOptions);
|
|
5414
|
-
writer.size += writtenSize;
|
|
5415
5603
|
if (writtenSize != outputSize) {
|
|
5416
|
-
throw new Error(ERR_INVALID_UNCOMPRESSED_SIZE);
|
|
5604
|
+
throw Object.assign(new Error(ERR_INVALID_UNCOMPRESSED_SIZE), { outputSize: writtenSize });
|
|
5417
5605
|
}
|
|
5606
|
+
writer.size += writtenSize;
|
|
5418
5607
|
}
|
|
5419
5608
|
} catch (error) {
|
|
5420
5609
|
if (error.outputSize !== UNDEFINED_VALUE) {
|
|
@@ -6080,7 +6269,7 @@
|
|
|
6080
6269
|
if (checkLocalFilename && !maskedLocalDirectory &&
|
|
6081
6270
|
(rawLocalFilename.length != rawFilename.length ||
|
|
6082
6271
|
rawLocalFilename.some((byteValue, indexByte) => byteValue != rawFilename[indexByte]))) {
|
|
6083
|
-
reportAmbiguity(reject, warnings,
|
|
6272
|
+
reportAmbiguity(reject, warnings, WARNING_MISMATCHED_LOCAL_FILE_HEADER_FILENAME);
|
|
6084
6273
|
}
|
|
6085
6274
|
if ((localDirectory.rawBitFlag & BITFLAG_AMBIGUITY_MASK) != (zipEntry.rawBitFlag & BITFLAG_AMBIGUITY_MASK)) {
|
|
6086
6275
|
reportAmbiguity(reject, warnings, WARNING_MISMATCHED_LOCAL_FILE_HEADER_BIT_FLAG);
|
|
@@ -6105,16 +6294,6 @@
|
|
|
6105
6294
|
}
|
|
6106
6295
|
}
|
|
6107
6296
|
|
|
6108
|
-
function addWarning(warnings, reason, filename) {
|
|
6109
|
-
if (!warnings.some(warning => warning.reason == reason)) {
|
|
6110
|
-
const warning = { reason };
|
|
6111
|
-
if (filename !== UNDEFINED_VALUE) {
|
|
6112
|
-
warning.filename = filename;
|
|
6113
|
-
}
|
|
6114
|
-
warnings.push(warning);
|
|
6115
|
-
}
|
|
6116
|
-
}
|
|
6117
|
-
|
|
6118
6297
|
function throwAmbiguousArchive(reason) {
|
|
6119
6298
|
const error = new Error(ERR_AMBIGUOUS_ARCHIVE);
|
|
6120
6299
|
error.reason = reason;
|
|
@@ -6194,7 +6373,9 @@
|
|
|
6194
6373
|
WARNING_MISMATCHED_LOCAL_FILE_HEADER_BIT_FLAG: WARNING_MISMATCHED_LOCAL_FILE_HEADER_BIT_FLAG,
|
|
6195
6374
|
WARNING_MISMATCHED_LOCAL_FILE_HEADER_COMPRESSION_METHOD: WARNING_MISMATCHED_LOCAL_FILE_HEADER_COMPRESSION_METHOD,
|
|
6196
6375
|
WARNING_MISMATCHED_LOCAL_FILE_HEADER_CRC32_OR_SIZES: WARNING_MISMATCHED_LOCAL_FILE_HEADER_CRC32_OR_SIZES,
|
|
6376
|
+
WARNING_MISMATCHED_LOCAL_FILE_HEADER_FILENAME: WARNING_MISMATCHED_LOCAL_FILE_HEADER_FILENAME,
|
|
6197
6377
|
WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY: WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY,
|
|
6378
|
+
WARNING_MULTIPLE_END_OF_CENTRAL_DIRECTORY: WARNING_MULTIPLE_END_OF_CENTRAL_DIRECTORY,
|
|
6198
6379
|
WARNING_PREPENDED_CENTRAL_DIRECTORY: WARNING_PREPENDED_CENTRAL_DIRECTORY,
|
|
6199
6380
|
WARNING_PREPENDED_DATA: WARNING_PREPENDED_DATA,
|
|
6200
6381
|
WARNING_TRAILING_CENTRAL_DIRECTORY_DATA: WARNING_TRAILING_CENTRAL_DIRECTORY_DATA,
|
|
@@ -6247,7 +6428,7 @@
|
|
|
6247
6428
|
const ERR_INVALID_ENCRYPTION_STRENGTH = "The strength must equal 1, 2, or 3";
|
|
6248
6429
|
const ERR_UNSUPPORTED_ENCRYPTION_USDZ = "Encryption is not supported in USDZ files";
|
|
6249
6430
|
const ERR_UNSUPPORTED_SPLIT_USDZ = "Split zip files are not supported in USDZ files";
|
|
6250
|
-
const ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH = "Encryption is not supported when the 'passThrough' option is set";
|
|
6431
|
+
const ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH = "Encryption is not supported when the 'passThrough' option is set to true (use 'compressed' instead)";
|
|
6251
6432
|
const ERR_INVALID_EXTRAFIELD = "Invalid extra field (must be a Map)";
|
|
6252
6433
|
const ERR_INVALID_EXTRAFIELD_TYPE = "Invalid extra field type (must be integer 0..65535)";
|
|
6253
6434
|
const ERR_INVALID_EXTRAFIELD_DATA_TYPE = "Invalid extra field data (must be a Uint8Array)";
|
|
@@ -6259,6 +6440,7 @@
|
|
|
6259
6440
|
const ERR_UNSUPPORTED_FORMAT = "Zip64 is not supported (set the 'zip64' option to 'true')";
|
|
6260
6441
|
const ERR_UNDEFINED_UNCOMPRESSED_SIZE = "Undefined uncompressed size";
|
|
6261
6442
|
const ERR_UNDEFINED_COMPRESSION_METHOD = "Undefined compression method";
|
|
6443
|
+
const ERR_UNDEFINED_CRC32 = "Undefined CRC32";
|
|
6262
6444
|
const ERR_UNDETERMINED_SIZE = "Undetermined size";
|
|
6263
6445
|
const ERR_UNDEFINED_READER = "Undefined reader";
|
|
6264
6446
|
const ERR_INVALID_READER = "Invalid reader (must be a Reader instance, a ReadableStream instance, or an object with a 'readable' property)";
|
|
@@ -6272,14 +6454,21 @@
|
|
|
6272
6454
|
const ERR_INVALID_MSDOS_DATA = "Invalid msdosAttributes (must be an object with boolean flags)";
|
|
6273
6455
|
const ERR_INVALID_LEVEL = "Invalid level (must be integer 0..9)";
|
|
6274
6456
|
const ERR_INVALID_SIGNATURE_DATA = "Signature data exceeds 64KB";
|
|
6457
|
+
const ERR_INVALID_ENTRY = "Invalid entry option (must be an entry returned by ZipReader#getEntries())";
|
|
6458
|
+
const ERR_ZIP_CRYPTO_LAST_MOD_DATE = "The last modification date of an entry encrypted with ZipCrypto cannot be changed when passThrough is set";
|
|
6459
|
+
const WARNING_COMPRESSION_UNAVAILABLE = "compression unavailable";
|
|
6460
|
+
const WARNING_CLAMPED_LAST_MODIFICATION_DATE = "clamped last modification date";
|
|
6275
6461
|
|
|
6276
6462
|
const EXTRAFIELD_DATA_AES = new Uint8Array([0x07, 0x00, 0x02, 0x00, 0x41, 0x45, 0x03, 0x00, 0x00]);
|
|
6277
6463
|
const EXTRAFIELD_OFFSET_AES_VENDOR_VERSION = 4;
|
|
6278
6464
|
const EXTRAFIELD_OFFSET_AES_COMPRESSION_METHOD = 9;
|
|
6279
6465
|
const EXTRAFIELD_USDZ_MAX_LENGTH = 67;
|
|
6466
|
+
const MIN_PRINTABLE_ASCII_CHARACTER_CODE = 0x20;
|
|
6467
|
+
const MAX_PRINTABLE_ASCII_CHARACTER_CODE = 0x7e;
|
|
6280
6468
|
const VENDOR_VERSION_AE_1 = 1;
|
|
6281
6469
|
const INFOZIP_EXTRA_FIELD_TYPE = "infozip";
|
|
6282
6470
|
const UNIX_EXTRA_FIELD_TYPE = "unix";
|
|
6471
|
+
const LEVEL_BY_BITFLAG_LEVEL = [8, 9, 5, 3];
|
|
6283
6472
|
const MAX_LEVEL = 9;
|
|
6284
6473
|
|
|
6285
6474
|
let workers = 0;
|
|
@@ -6306,9 +6495,11 @@
|
|
|
6306
6495
|
initialOffset: options[OPTION_OFFSET] === UNDEFINED_VALUE ? 0 : options[OPTION_OFFSET] - (writer.size || writer.writable.size || 0),
|
|
6307
6496
|
pendingAddFileCalls: new Set(),
|
|
6308
6497
|
pendingErrors: [],
|
|
6498
|
+
warnings: [],
|
|
6309
6499
|
bufferedWrites: 0,
|
|
6310
6500
|
directWrites: 0,
|
|
6311
|
-
lastFileEntry: UNDEFINED_VALUE
|
|
6501
|
+
lastFileEntry: UNDEFINED_VALUE,
|
|
6502
|
+
archiveClosed: false
|
|
6312
6503
|
});
|
|
6313
6504
|
}
|
|
6314
6505
|
|
|
@@ -6473,6 +6664,9 @@
|
|
|
6473
6664
|
const zipWriter = this;
|
|
6474
6665
|
const { pendingAddFileCalls, writer } = this;
|
|
6475
6666
|
const { writable } = writer;
|
|
6667
|
+
if (zipWriter.archiveClosed) {
|
|
6668
|
+
return getWriterData(writer);
|
|
6669
|
+
}
|
|
6476
6670
|
if (!(comment instanceof Uint8Array)) {
|
|
6477
6671
|
throw new Error(ERR_INVALID_COMMENT_TYPE);
|
|
6478
6672
|
}
|
|
@@ -6496,11 +6690,16 @@
|
|
|
6496
6690
|
throw error;
|
|
6497
6691
|
}
|
|
6498
6692
|
await closeFile(zipWriter, comment, options);
|
|
6693
|
+
zipWriter.archiveClosed = true;
|
|
6499
6694
|
const preventClose = !ownsWritable(writer) && getOptionValue(zipWriter, options, OPTION_PREVENT_CLOSE);
|
|
6500
6695
|
if (!preventClose) {
|
|
6501
6696
|
await writable.getWriter().close();
|
|
6502
6697
|
}
|
|
6503
|
-
return writer
|
|
6698
|
+
return getWriterData(writer);
|
|
6699
|
+
}
|
|
6700
|
+
|
|
6701
|
+
[SYMBOL_ASYNC_DISPOSE]() {
|
|
6702
|
+
return this.close();
|
|
6504
6703
|
}
|
|
6505
6704
|
}
|
|
6506
6705
|
|
|
@@ -6579,6 +6778,10 @@
|
|
|
6579
6778
|
}
|
|
6580
6779
|
}
|
|
6581
6780
|
|
|
6781
|
+
function getWriterData(writer) {
|
|
6782
|
+
return writer.getData ? writer.getData() : writer.writable;
|
|
6783
|
+
}
|
|
6784
|
+
|
|
6582
6785
|
function watchPromiseError(zipWriter, promise) {
|
|
6583
6786
|
const watchedPromise = new WatchedPromise((resolve, reject) => Promise.prototype.then.call(promise, resolve, reject));
|
|
6584
6787
|
const watcher = {};
|
|
@@ -6597,6 +6800,14 @@
|
|
|
6597
6800
|
|
|
6598
6801
|
async function addFileEntry(zipWriter, name, reader, options) {
|
|
6599
6802
|
options = Object.assign({}, options);
|
|
6803
|
+
const entry = options[OPTION_ENTRY];
|
|
6804
|
+
if (entry !== UNDEFINED_VALUE) {
|
|
6805
|
+
const { entryOptions, passThroughOptions } = getSourceEntryOptions(entry,
|
|
6806
|
+
checkPassThroughOption(getOptionValue(zipWriter, options, OPTION_PASS_THROUGH)),
|
|
6807
|
+
getOptionValue(zipWriter, options, PROPERTY_NAME_LAST_MODIFICATION_DATE));
|
|
6808
|
+
delete options[OPTION_ENTRY];
|
|
6809
|
+
options = Object.assign(entryOptions, passThroughOptions, options);
|
|
6810
|
+
}
|
|
6600
6811
|
if (getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY) && !name.endsWith(DIRECTORY_SIGNATURE)) {
|
|
6601
6812
|
name += DIRECTORY_SIGNATURE;
|
|
6602
6813
|
}
|
|
@@ -6661,21 +6872,33 @@
|
|
|
6661
6872
|
try {
|
|
6662
6873
|
const { resolvedOptions } = metadataInfo;
|
|
6663
6874
|
if (resolvedOptions.level != 0 && resolvedOptions.compressionMethod === UNDEFINED_VALUE &&
|
|
6664
|
-
!resolvedOptions.
|
|
6875
|
+
!resolvedOptions.passThroughCompression && !(await supportsDeflate(getConfiguration()))) {
|
|
6665
6876
|
resolvedOptions.level = 0;
|
|
6877
|
+
addWarning(zipWriter.warnings, WARNING_COMPRESSION_UNAVAILABLE, name);
|
|
6666
6878
|
}
|
|
6667
6879
|
const sizesInfo = await resolveSizes(zipWriter, reader, metadataInfo, options);
|
|
6668
6880
|
({ reader } = sizesInfo);
|
|
6669
6881
|
const diskOffset = getDiskOffset(zipWriter.writer);
|
|
6670
6882
|
const diskNumber = getDiskNumber(zipWriter.writer);
|
|
6883
|
+
let crc32 = options.crc32 === UNDEFINED_VALUE ? options[PROPERTY_NAME_SIGNATURE] : options.crc32;
|
|
6884
|
+
const storesAE2 = sizesInfo.resolvedOptions.encrypted && !resolvedOptions.zipCrypto;
|
|
6885
|
+
if (resolvedOptions.passThroughCompression && !resolvedOptions.passThroughEncryption && storesAE2) {
|
|
6886
|
+
crc32 = UNDEFINED_VALUE;
|
|
6887
|
+
}
|
|
6888
|
+
if (resolvedOptions.passThroughCompression && reader && !storesAE2 && crc32 === UNDEFINED_VALUE) {
|
|
6889
|
+
throw new Error(ERR_UNDEFINED_CRC32);
|
|
6890
|
+
}
|
|
6671
6891
|
options = Object.assign({}, options, attributesInfo.resolvedOptions, metadataInfo.resolvedOptions, sizesInfo.resolvedOptions, {
|
|
6672
6892
|
signature: options[PROPERTY_NAME_SIGNATURE],
|
|
6673
|
-
crc32
|
|
6893
|
+
crc32,
|
|
6674
6894
|
offset: zipWriter.offset - diskOffset,
|
|
6675
6895
|
diskNumberStart: diskNumber,
|
|
6676
6896
|
[OPTION_USDZ]: zipWriter.options[OPTION_USDZ]
|
|
6677
6897
|
});
|
|
6678
6898
|
const headerInfo = getHeaderInfo(options);
|
|
6899
|
+
if (headerInfo.lastModDateClamped) {
|
|
6900
|
+
addWarning(zipWriter.warnings, WARNING_CLAMPED_LAST_MODIFICATION_DATE, name);
|
|
6901
|
+
}
|
|
6679
6902
|
const dataDescriptorInfo = getDataDescriptorInfo(options);
|
|
6680
6903
|
const metadataSize = getLength(headerInfo.localHeaderArray, dataDescriptorInfo.dataDescriptorArray);
|
|
6681
6904
|
fileEntry = await getFileEntry(zipWriter, name, reader, {
|
|
@@ -6702,6 +6925,95 @@
|
|
|
6702
6925
|
return new Entry(fileEntry);
|
|
6703
6926
|
}
|
|
6704
6927
|
|
|
6928
|
+
function getSourceEntryOptions(entry, passThrough, lastModDateOverride) {
|
|
6929
|
+
if (entry === null || typeof entry != OBJECT_TYPE || Array.isArray(entry)) {
|
|
6930
|
+
throw new Error(ERR_INVALID_ENTRY);
|
|
6931
|
+
}
|
|
6932
|
+
const {
|
|
6933
|
+
externalFileAttributes,
|
|
6934
|
+
versionMadeBy,
|
|
6935
|
+
comment,
|
|
6936
|
+
lastModDate,
|
|
6937
|
+
rawLastModDate,
|
|
6938
|
+
creationDate,
|
|
6939
|
+
lastAccessDate,
|
|
6940
|
+
uncompressedSize,
|
|
6941
|
+
encrypted,
|
|
6942
|
+
zipCrypto,
|
|
6943
|
+
crc32,
|
|
6944
|
+
compressionMethod,
|
|
6945
|
+
extraFieldAES,
|
|
6946
|
+
extraFieldUnix,
|
|
6947
|
+
internalFileAttributes,
|
|
6948
|
+
extraField,
|
|
6949
|
+
bitFlag,
|
|
6950
|
+
directory,
|
|
6951
|
+
uid,
|
|
6952
|
+
gid
|
|
6953
|
+
} = entry;
|
|
6954
|
+
const entryOptions = {
|
|
6955
|
+
externalFileAttributes,
|
|
6956
|
+
versionMadeBy,
|
|
6957
|
+
comment,
|
|
6958
|
+
lastModDate,
|
|
6959
|
+
creationDate,
|
|
6960
|
+
lastAccessDate,
|
|
6961
|
+
internalFileAttributes,
|
|
6962
|
+
directory
|
|
6963
|
+
};
|
|
6964
|
+
if (bitFlag && bitFlag.languageEncodingFlag) {
|
|
6965
|
+
entryOptions[OPTION_USE_UNICODE_FILE_NAMES] = true;
|
|
6966
|
+
}
|
|
6967
|
+
const userExtraField = getUserExtraField(extraField);
|
|
6968
|
+
if (userExtraField) {
|
|
6969
|
+
entryOptions[PROPERTY_NAME_EXTRA_FIELD] = userExtraField;
|
|
6970
|
+
}
|
|
6971
|
+
if (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE) {
|
|
6972
|
+
Object.assign(entryOptions, {
|
|
6973
|
+
uid,
|
|
6974
|
+
gid,
|
|
6975
|
+
unixExtraFieldType: extraFieldUnix ? UNIX_EXTRA_FIELD_TYPE : INFOZIP_EXTRA_FIELD_TYPE
|
|
6976
|
+
});
|
|
6977
|
+
}
|
|
6978
|
+
const passThroughOptions = {};
|
|
6979
|
+
if (passThrough && !directory) {
|
|
6980
|
+
Object.assign(passThroughOptions, {
|
|
6981
|
+
uncompressedSize,
|
|
6982
|
+
crc32,
|
|
6983
|
+
compressionMethod
|
|
6984
|
+
});
|
|
6985
|
+
if (passThrough !== PASS_THROUGH_COMPRESSED) {
|
|
6986
|
+
Object.assign(passThroughOptions, {
|
|
6987
|
+
encrypted,
|
|
6988
|
+
zipCrypto,
|
|
6989
|
+
encryptionStrength: extraFieldAES ? extraFieldAES.strength : UNDEFINED_VALUE
|
|
6990
|
+
});
|
|
6991
|
+
}
|
|
6992
|
+
if (bitFlag) {
|
|
6993
|
+
passThroughOptions.dataDescriptor = bitFlag.dataDescriptor;
|
|
6994
|
+
passThroughOptions[OPTION_LEVEL] = LEVEL_BY_BITFLAG_LEVEL[bitFlag.level];
|
|
6995
|
+
}
|
|
6996
|
+
if (lastModDateOverride === UNDEFINED_VALUE) {
|
|
6997
|
+
passThroughOptions.rawLastModDate = rawLastModDate;
|
|
6998
|
+
} else if (passThrough !== PASS_THROUGH_COMPRESSED && zipCrypto && (!bitFlag || bitFlag.dataDescriptor) &&
|
|
6999
|
+
lastModDateOverride instanceof Date &&
|
|
7000
|
+
getDosTimeHighByte(lastModDateOverride) != ((rawLastModDate >>> 8) & MAX_8_BITS)) {
|
|
7001
|
+
throw new Error(ERR_ZIP_CRYPTO_LAST_MOD_DATE);
|
|
7002
|
+
}
|
|
7003
|
+
}
|
|
7004
|
+
return { entryOptions, passThroughOptions };
|
|
7005
|
+
}
|
|
7006
|
+
|
|
7007
|
+
function getDosTimeHighByte(lastModDate) {
|
|
7008
|
+
let dosLastModDate = new Date(Math.ceil(Math.floor(lastModDate.getTime() / 1000) / 2) * 2000);
|
|
7009
|
+
if (dosLastModDate < MIN_DATE) {
|
|
7010
|
+
dosLastModDate = MIN_DATE;
|
|
7011
|
+
} else if (dosLastModDate > MAX_DATE) {
|
|
7012
|
+
dosLastModDate = MAX_DATE;
|
|
7013
|
+
}
|
|
7014
|
+
return ((dosLastModDate.getHours() << 3) | (dosLastModDate.getMinutes() >> 3)) & MAX_8_BITS;
|
|
7015
|
+
}
|
|
7016
|
+
|
|
6705
7017
|
function resolveAttributes(zipWriter, name, options) {
|
|
6706
7018
|
let msDosCompatible = getOptionValue(zipWriter, options, PROPERTY_NAME_MS_DOS_COMPATIBLE);
|
|
6707
7019
|
let versionMadeBy = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION_MADE_BY, msDosCompatible ? VERSION_MADE_BY_MSDOS : VERSION_MADE_BY_UNIX);
|
|
@@ -6855,7 +7167,9 @@
|
|
|
6855
7167
|
const lastAccessDate = getDateOptionValue(zipWriter, options, PROPERTY_NAME_LAST_ACCESS_DATE);
|
|
6856
7168
|
const creationDate = getDateOptionValue(zipWriter, options, PROPERTY_NAME_CREATION_DATE);
|
|
6857
7169
|
const internalFileAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES, 0);
|
|
6858
|
-
const passThrough = getOptionValue(zipWriter, options, OPTION_PASS_THROUGH);
|
|
7170
|
+
const passThrough = checkPassThroughOption(getOptionValue(zipWriter, options, OPTION_PASS_THROUGH));
|
|
7171
|
+
const passThroughCompression = Boolean(passThrough);
|
|
7172
|
+
const passThroughEncryption = passThrough === true;
|
|
6859
7173
|
const password = getOptionValue(zipWriter, options, OPTION_PASSWORD);
|
|
6860
7174
|
const rawPassword = getOptionValue(zipWriter, options, OPTION_RAW_PASSWORD);
|
|
6861
7175
|
checkPasswordOption(password, rawPassword);
|
|
@@ -6870,10 +7184,12 @@
|
|
|
6870
7184
|
const createTempStream = getFunctionOptionValue(zipWriter, options, OPTION_CREATE_TEMP_STREAM);
|
|
6871
7185
|
const dataDescriptorSignature = getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR_SIGNATURE, true);
|
|
6872
7186
|
const signal = checkSignalOption(getOptionValue(zipWriter, options, OPTION_SIGNAL));
|
|
6873
|
-
|
|
7187
|
+
throwIfAborted(signal);
|
|
7188
|
+
const useUnicodeFileNames = getOptionValue(zipWriter, options, OPTION_USE_UNICODE_FILE_NAMES,
|
|
7189
|
+
!isPrintableASCIIText(rawFilename) || !isPrintableASCIIText(rawComment));
|
|
6874
7190
|
const compressionMethod = getOptionValue(zipWriter, options, PROPERTY_NAME_COMPRESSION_METHOD);
|
|
6875
|
-
const registeredCodec =
|
|
6876
|
-
if (!
|
|
7191
|
+
const registeredCodec = passThroughCompression || compressionMethod === UNDEFINED_VALUE ? UNDEFINED_VALUE : getRegisteredCodec(compressionMethod);
|
|
7192
|
+
if (!passThroughCompression && compressionMethod !== UNDEFINED_VALUE &&
|
|
6877
7193
|
compressionMethod !== COMPRESSION_METHOD_STORE && compressionMethod !== COMPRESSION_METHOD_DEFLATE && !registeredCodec) {
|
|
6878
7194
|
throw new Error(ERR_UNSUPPORTED_COMPRESSION);
|
|
6879
7195
|
}
|
|
@@ -6887,15 +7203,15 @@
|
|
|
6887
7203
|
level = 0;
|
|
6888
7204
|
}
|
|
6889
7205
|
}
|
|
6890
|
-
if (
|
|
6891
|
-
level =
|
|
7206
|
+
if (passThroughCompression) {
|
|
7207
|
+
level = toNumber(options[OPTION_LEVEL]);
|
|
6892
7208
|
}
|
|
6893
7209
|
let useCompressionStream = getOptionValue(zipWriter, options, OPTION_USE_COMPRESSION_STREAM);
|
|
6894
7210
|
let dataDescriptor = getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR);
|
|
6895
7211
|
if (bufferedWrite && dataDescriptor === UNDEFINED_VALUE) {
|
|
6896
7212
|
dataDescriptor = false;
|
|
6897
7213
|
}
|
|
6898
|
-
if (dataDescriptor === UNDEFINED_VALUE || (zipCrypto && !
|
|
7214
|
+
if (dataDescriptor === UNDEFINED_VALUE || (zipCrypto && !passThroughEncryption)) {
|
|
6899
7215
|
dataDescriptor = true;
|
|
6900
7216
|
}
|
|
6901
7217
|
if (level !== UNDEFINED_VALUE && level != 6) {
|
|
@@ -6919,7 +7235,8 @@
|
|
|
6919
7235
|
lastAccessDate,
|
|
6920
7236
|
creationDate,
|
|
6921
7237
|
internalFileAttributes,
|
|
6922
|
-
|
|
7238
|
+
passThroughCompression,
|
|
7239
|
+
passThroughEncryption,
|
|
6923
7240
|
password,
|
|
6924
7241
|
rawPassword,
|
|
6925
7242
|
encryptionStrength,
|
|
@@ -6980,7 +7297,7 @@
|
|
|
6980
7297
|
}
|
|
6981
7298
|
|
|
6982
7299
|
async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, options) {
|
|
6983
|
-
if (metadata.
|
|
7300
|
+
if (metadata.passThroughCompression && !reader && !getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY)) {
|
|
6984
7301
|
throw new Error(ERR_UNDEFINED_READER);
|
|
6985
7302
|
}
|
|
6986
7303
|
let contentSize;
|
|
@@ -6996,12 +7313,12 @@
|
|
|
6996
7313
|
}
|
|
6997
7314
|
|
|
6998
7315
|
function resolveEntrySizes(zipWriter, hasContent, contentSize, metadata, options) {
|
|
6999
|
-
const {
|
|
7316
|
+
const { passThroughCompression, passThroughEncryption, zipCrypto, password, rawPassword, encryptionStrength } = metadata;
|
|
7000
7317
|
let { dataDescriptor, zip64, level, compressionMethod } = metadata;
|
|
7001
7318
|
let maximumCompressedSize = 0;
|
|
7002
7319
|
let uncompressedSize = 0;
|
|
7003
7320
|
let unknownSize = false;
|
|
7004
|
-
if (
|
|
7321
|
+
if (passThroughCompression && hasContent) {
|
|
7005
7322
|
uncompressedSize = options[PROPERTY_NAME_UNCOMPRESSED_SIZE];
|
|
7006
7323
|
if (uncompressedSize === UNDEFINED_VALUE) {
|
|
7007
7324
|
throw new Error(ERR_UNDEFINED_UNCOMPRESSED_SIZE);
|
|
@@ -7012,17 +7329,17 @@
|
|
|
7012
7329
|
}
|
|
7013
7330
|
const zip64Enabled = zip64 === true;
|
|
7014
7331
|
const encrypted = getOptionValue(zipWriter, options, PROPERTY_NAME_ENCRYPTED);
|
|
7015
|
-
if (hasContent &&
|
|
7332
|
+
if (hasContent && passThroughEncryption && !encrypted && getLength(password, rawPassword)) {
|
|
7016
7333
|
throw new Error(ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH);
|
|
7017
7334
|
}
|
|
7018
|
-
const encryptedEntry = hasContent && (Boolean((password && getLength(password)) || (rawPassword && getLength(rawPassword))) || (
|
|
7335
|
+
const encryptedEntry = hasContent && (Boolean((password && getLength(password)) || (rawPassword && getLength(rawPassword))) || (passThroughEncryption && encrypted));
|
|
7019
7336
|
if (!hasContent) {
|
|
7020
7337
|
level = 0;
|
|
7021
7338
|
compressionMethod = COMPRESSION_METHOD_STORE;
|
|
7022
7339
|
}
|
|
7023
|
-
const encryptionOverhead = encryptedEntry
|
|
7340
|
+
const encryptionOverhead = getEncryptionOverhead(encryptedEntry, zipCrypto, encryptionStrength);
|
|
7024
7341
|
if (hasContent) {
|
|
7025
|
-
if (!
|
|
7342
|
+
if (!passThroughCompression) {
|
|
7026
7343
|
if (contentSize === UNDEFINED_VALUE) {
|
|
7027
7344
|
dataDescriptor = true;
|
|
7028
7345
|
if (zip64 || zip64 === UNDEFINED_VALUE) {
|
|
@@ -7035,10 +7352,12 @@
|
|
|
7035
7352
|
}
|
|
7036
7353
|
} else {
|
|
7037
7354
|
options.uncompressedSize = uncompressedSize;
|
|
7038
|
-
maximumCompressedSize = contentSize === UNDEFINED_VALUE ?
|
|
7355
|
+
maximumCompressedSize = contentSize === UNDEFINED_VALUE ?
|
|
7356
|
+
getMaximumCompressedSize(uncompressedSize) + encryptionOverhead :
|
|
7357
|
+
contentSize + (passThroughEncryption ? 0 : encryptionOverhead);
|
|
7039
7358
|
}
|
|
7040
7359
|
}
|
|
7041
|
-
const emptyEntry = !encryptedEntry && (!hasContent || (contentSize === 0 && !
|
|
7360
|
+
const emptyEntry = !encryptedEntry && (!hasContent || (contentSize === 0 && !passThroughCompression)) && !isCompressed(compressionMethod, level);
|
|
7042
7361
|
if (emptyEntry && !zipCrypto && getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR) === UNDEFINED_VALUE) {
|
|
7043
7362
|
dataDescriptor = false;
|
|
7044
7363
|
}
|
|
@@ -7245,6 +7564,7 @@
|
|
|
7245
7564
|
localExtraFieldZip64Length,
|
|
7246
7565
|
rawExtraFieldExtendedTimestamp,
|
|
7247
7566
|
extraFieldExtendedTimestampFlag,
|
|
7567
|
+
extraFieldExtendedTimestampTime,
|
|
7248
7568
|
rawExtraFieldNTFS,
|
|
7249
7569
|
rawExtraFieldUnix,
|
|
7250
7570
|
rawExtraFieldAES,
|
|
@@ -7257,6 +7577,7 @@
|
|
|
7257
7577
|
password,
|
|
7258
7578
|
rawPassword,
|
|
7259
7579
|
level,
|
|
7580
|
+
useUnicodeFileNames,
|
|
7260
7581
|
zip64,
|
|
7261
7582
|
zip64Enabled,
|
|
7262
7583
|
zip64UncompressedSize,
|
|
@@ -7291,7 +7612,8 @@
|
|
|
7291
7612
|
msdosAttributesRaw,
|
|
7292
7613
|
msdosAttributes,
|
|
7293
7614
|
useCompressionStream,
|
|
7294
|
-
|
|
7615
|
+
passThroughCompression,
|
|
7616
|
+
passThroughEncryption,
|
|
7295
7617
|
format,
|
|
7296
7618
|
codecURI
|
|
7297
7619
|
} = options;
|
|
@@ -7302,9 +7624,9 @@
|
|
|
7302
7624
|
zip64Enabled,
|
|
7303
7625
|
directory: Boolean(directory),
|
|
7304
7626
|
executable: Boolean(executable),
|
|
7305
|
-
filenameUTF8:
|
|
7627
|
+
filenameUTF8: Boolean(useUnicodeFileNames),
|
|
7306
7628
|
rawFilename,
|
|
7307
|
-
commentUTF8:
|
|
7629
|
+
commentUTF8: Boolean(useUnicodeFileNames),
|
|
7308
7630
|
rawComment,
|
|
7309
7631
|
rawExtraFieldZip64,
|
|
7310
7632
|
localExtraFieldZip64Length,
|
|
@@ -7335,7 +7657,7 @@
|
|
|
7335
7657
|
uncompressedSize
|
|
7336
7658
|
} = options;
|
|
7337
7659
|
let compressedSize = 0;
|
|
7338
|
-
if (!
|
|
7660
|
+
if (!passThroughCompression) {
|
|
7339
7661
|
uncompressedSize = 0;
|
|
7340
7662
|
}
|
|
7341
7663
|
const { writable } = writer;
|
|
@@ -7352,9 +7674,9 @@
|
|
|
7352
7674
|
encryptionStrength,
|
|
7353
7675
|
zipCrypto: encrypted && zipCrypto,
|
|
7354
7676
|
passwordVerification: encrypted && zipCrypto && (rawLastModDate >> 8) & MAX_8_BITS,
|
|
7355
|
-
computeCrc32: !
|
|
7356
|
-
compressed: compressed && !
|
|
7357
|
-
encrypted: encrypted && !
|
|
7677
|
+
computeCrc32: !passThroughCompression,
|
|
7678
|
+
compressed: compressed && !passThroughCompression,
|
|
7679
|
+
encrypted: encrypted && !passThroughEncryption,
|
|
7358
7680
|
useWebWorkers,
|
|
7359
7681
|
useCompressionStream,
|
|
7360
7682
|
transferStreams,
|
|
@@ -7369,7 +7691,7 @@
|
|
|
7369
7691
|
const result = await runWorker({ readable, writable }, workerOptions);
|
|
7370
7692
|
compressedSize = result.outputSize;
|
|
7371
7693
|
writer.size += compressedSize;
|
|
7372
|
-
if (!
|
|
7694
|
+
if (!passThroughCompression) {
|
|
7373
7695
|
uncompressedSize = result.inputSize;
|
|
7374
7696
|
if (!encrypted || zipCrypto) {
|
|
7375
7697
|
crc32 = result.crc32;
|
|
@@ -7412,8 +7734,9 @@
|
|
|
7412
7734
|
headerArray,
|
|
7413
7735
|
headerView,
|
|
7414
7736
|
signature: crc32,
|
|
7415
|
-
crc32: encrypted && !zipCrypto && !
|
|
7737
|
+
crc32: encrypted && !zipCrypto && !passThroughCompression ? UNDEFINED_VALUE : crc32,
|
|
7416
7738
|
extraFieldExtendedTimestampFlag,
|
|
7739
|
+
extraFieldExtendedTimestampTime,
|
|
7417
7740
|
zip64UncompressedSize,
|
|
7418
7741
|
zip64CompressedSize
|
|
7419
7742
|
});
|
|
@@ -7438,7 +7761,7 @@
|
|
|
7438
7761
|
encryptionStrength,
|
|
7439
7762
|
extendedTimestamp,
|
|
7440
7763
|
ntfsTimestamp,
|
|
7441
|
-
|
|
7764
|
+
passThroughCompression,
|
|
7442
7765
|
encrypted,
|
|
7443
7766
|
zip64UncompressedSize,
|
|
7444
7767
|
zip64CompressedSize,
|
|
@@ -7449,7 +7772,7 @@
|
|
|
7449
7772
|
let { version, compressionMethod } = options;
|
|
7450
7773
|
const compressed = !directory && isCompressed(compressionMethod, level);
|
|
7451
7774
|
let rawLocalExtraFieldZip64;
|
|
7452
|
-
const uncompressedFile =
|
|
7775
|
+
const uncompressedFile = passThroughCompression || !compressed;
|
|
7453
7776
|
const zip64ExtraFieldComplete = zip64 && (options.bufferedWrite || !dataDescriptor || ((!zip64UncompressedSize && !zip64CompressedSize) || (uncompressedFile && !unknownSize)));
|
|
7454
7777
|
const writeLocalExtraFieldZip64 = zip64ExtraFieldComplete || (zip64 && dataDescriptor && (zip64UncompressedSize || zip64CompressedSize));
|
|
7455
7778
|
if (zip64 && (zip64UncompressedSize || zip64CompressedSize)) {
|
|
@@ -7461,8 +7784,8 @@
|
|
|
7461
7784
|
if (zip64ExtraFieldComplete) {
|
|
7462
7785
|
extraFieldZip64.writeUint64(uncompressedSize);
|
|
7463
7786
|
if (uncompressedFile) {
|
|
7464
|
-
const encryptionOverhead = encrypted
|
|
7465
|
-
extraFieldZip64.writeUint64(
|
|
7787
|
+
const encryptionOverhead = getEncryptionOverhead(encrypted, zipCrypto, encryptionStrength);
|
|
7788
|
+
extraFieldZip64.writeUint64(passThroughCompression ? 0 : uncompressedSize + encryptionOverhead);
|
|
7466
7789
|
}
|
|
7467
7790
|
}
|
|
7468
7791
|
} else {
|
|
@@ -7481,6 +7804,7 @@
|
|
|
7481
7804
|
let rawExtraFieldNTFS;
|
|
7482
7805
|
let rawExtraFieldExtendedTimestamp;
|
|
7483
7806
|
let extraFieldExtendedTimestampFlag;
|
|
7807
|
+
let extraFieldExtendedTimestampTime;
|
|
7484
7808
|
if (extendedTimestamp) {
|
|
7485
7809
|
const lastModTimeUnix = getTimeUnix(lastModDate);
|
|
7486
7810
|
const lastModTimeUnixInRange = inUnixTimeRange(lastModTimeUnix);
|
|
@@ -7488,6 +7812,7 @@
|
|
|
7488
7812
|
const extraFieldTimestampLength = 9 + (lastAccessDate ? 4 : 0) + (creationDate ? 4 : 0);
|
|
7489
7813
|
const extraFieldTimestamp = createRecordWriter(extraFieldTimestampLength);
|
|
7490
7814
|
extraFieldExtendedTimestampFlag = 0x1 + (lastAccessDate ? 0x2 : 0) + (creationDate ? 0x4 : 0);
|
|
7815
|
+
extraFieldExtendedTimestampTime = lastModTimeUnix;
|
|
7491
7816
|
extraFieldTimestamp.writeUint16(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
|
|
7492
7817
|
extraFieldTimestamp.writeUint16(extraFieldTimestampLength - 4);
|
|
7493
7818
|
extraFieldTimestamp.writeUint8(extraFieldExtendedTimestampFlag);
|
|
@@ -7571,7 +7896,7 @@
|
|
|
7571
7896
|
}
|
|
7572
7897
|
if (encrypted && !zipCrypto) {
|
|
7573
7898
|
version = version > VERSION_AES ? version : VERSION_AES;
|
|
7574
|
-
if (
|
|
7899
|
+
if (passThroughCompression && crc32 !== UNDEFINED_VALUE) {
|
|
7575
7900
|
rawExtraFieldAES[EXTRAFIELD_OFFSET_AES_VENDOR_VERSION] = VENDOR_VERSION_AE_1;
|
|
7576
7901
|
}
|
|
7577
7902
|
setUint16(getDataView(rawExtraFieldAES), EXTRAFIELD_OFFSET_AES_COMPRESSION_METHOD, compressionMethod);
|
|
@@ -7633,12 +7958,14 @@
|
|
|
7633
7958
|
headerArray,
|
|
7634
7959
|
headerView,
|
|
7635
7960
|
lastModDate: storedLastModDate,
|
|
7961
|
+
lastModDateClamped: storedLastModDate === clampedLastModDate && dosLastModDate.getTime() != clampedLastModDate.getTime(),
|
|
7636
7962
|
rawLastModDate,
|
|
7637
7963
|
encrypted,
|
|
7638
7964
|
compressed,
|
|
7639
7965
|
version,
|
|
7640
7966
|
compressionMethod,
|
|
7641
7967
|
extraFieldExtendedTimestampFlag,
|
|
7968
|
+
extraFieldExtendedTimestampTime,
|
|
7642
7969
|
rawExtraFieldZip64: EMPTY_UINT8_ARRAY,
|
|
7643
7970
|
localExtraFieldZip64Length,
|
|
7644
7971
|
rawExtraFieldExtendedTimestamp,
|
|
@@ -7741,7 +8068,7 @@
|
|
|
7741
8068
|
}, {
|
|
7742
8069
|
zip64,
|
|
7743
8070
|
zipCrypto,
|
|
7744
|
-
|
|
8071
|
+
passThroughCompression,
|
|
7745
8072
|
dataDescriptor
|
|
7746
8073
|
}) {
|
|
7747
8074
|
const {
|
|
@@ -7752,7 +8079,7 @@
|
|
|
7752
8079
|
dataDescriptorView,
|
|
7753
8080
|
dataDescriptorOffset
|
|
7754
8081
|
} = dataDescriptorInfo;
|
|
7755
|
-
if ((!encrypted || zipCrypto ||
|
|
8082
|
+
if ((!encrypted || zipCrypto || passThroughCompression) && crc32 !== UNDEFINED_VALUE) {
|
|
7756
8083
|
setUint32(headerView, HEADER_OFFSET_SIGNATURE, crc32);
|
|
7757
8084
|
if (dataDescriptor) {
|
|
7758
8085
|
setUint32(dataDescriptorView, dataDescriptorOffset, crc32);
|
|
@@ -7783,9 +8110,9 @@
|
|
|
7783
8110
|
uncompressedSize,
|
|
7784
8111
|
zip64UncompressedSize,
|
|
7785
8112
|
zip64CompressedSize
|
|
7786
|
-
}, localHeaderView, { dataDescriptor,
|
|
8113
|
+
}, localHeaderView, { dataDescriptor, passThroughCompression }) {
|
|
7787
8114
|
if (!dataDescriptor) {
|
|
7788
|
-
if (!encrypted || (
|
|
8115
|
+
if (!encrypted || (passThroughCompression && crc32 !== UNDEFINED_VALUE)) {
|
|
7789
8116
|
setUint32(localHeaderView, HEADER_OFFSET_SIGNATURE + LOCAL_HEADER_COMMON_OFFSET, crc32);
|
|
7790
8117
|
}
|
|
7791
8118
|
if (!zip64CompressedSize) {
|
|
@@ -7822,9 +8149,8 @@
|
|
|
7822
8149
|
rawExtraFieldUnix,
|
|
7823
8150
|
rawExtraField,
|
|
7824
8151
|
rawCentralExtraField,
|
|
7825
|
-
extendedTimestamp,
|
|
7826
8152
|
extraFieldExtendedTimestampFlag,
|
|
7827
|
-
|
|
8153
|
+
extraFieldExtendedTimestampTime,
|
|
7828
8154
|
zip64Enabled,
|
|
7829
8155
|
uncompressedSize,
|
|
7830
8156
|
compressedSize
|
|
@@ -7867,16 +8193,15 @@
|
|
|
7867
8193
|
fileEntry.zip64Offset = zip64Offset;
|
|
7868
8194
|
fileEntry.zip64DiskNumberStart = zip64DiskNumberStart;
|
|
7869
8195
|
let rawExtraFieldTimestamp;
|
|
7870
|
-
|
|
7871
|
-
|
|
8196
|
+
if (extraFieldExtendedTimestampTime === UNDEFINED_VALUE) {
|
|
8197
|
+
rawExtraFieldTimestamp = EMPTY_UINT8_ARRAY;
|
|
8198
|
+
} else {
|
|
7872
8199
|
const extraFieldTimestamp = createRecordWriter(9);
|
|
7873
8200
|
extraFieldTimestamp.writeUint16(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
|
|
7874
8201
|
extraFieldTimestamp.writeUint16(5);
|
|
7875
8202
|
extraFieldTimestamp.writeUint8(extraFieldExtendedTimestampFlag);
|
|
7876
|
-
extraFieldTimestamp.writeUint32(
|
|
8203
|
+
extraFieldTimestamp.writeUint32(extraFieldExtendedTimestampTime);
|
|
7877
8204
|
rawExtraFieldTimestamp = extraFieldTimestamp.array;
|
|
7878
|
-
} else {
|
|
7879
|
-
rawExtraFieldTimestamp = EMPTY_UINT8_ARRAY;
|
|
7880
8205
|
}
|
|
7881
8206
|
fileEntry.rawExtraFieldExtendedTimestamp = rawExtraFieldTimestamp;
|
|
7882
8207
|
const extraFieldLength = getLength(
|
|
@@ -8376,6 +8701,11 @@
|
|
|
8376
8701
|
};
|
|
8377
8702
|
}
|
|
8378
8703
|
|
|
8704
|
+
function isPrintableASCIIText(rawText) {
|
|
8705
|
+
return rawText.every(characterCode =>
|
|
8706
|
+
characterCode >= MIN_PRINTABLE_ASCII_CHARACTER_CODE && characterCode <= MAX_PRINTABLE_ASCII_CHARACTER_CODE);
|
|
8707
|
+
}
|
|
8708
|
+
|
|
8379
8709
|
function getBitFlag(level, useUnicodeFileNames, dataDescriptor, encrypted, compressionMethod) {
|
|
8380
8710
|
let bitFlag = 0;
|
|
8381
8711
|
if (useUnicodeFileNames) {
|
|
@@ -8537,7 +8867,7 @@
|
|
|
8537
8867
|
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
8538
8868
|
*/
|
|
8539
8869
|
|
|
8540
|
-
const VERSION = "2.
|
|
8870
|
+
const VERSION = "2.12.0";
|
|
8541
8871
|
|
|
8542
8872
|
/*
|
|
8543
8873
|
Copyright (c) 2025 Gildas Lormeau. All rights reserved.
|
|
@@ -8990,6 +9320,7 @@
|
|
|
8990
9320
|
exports.BlobWriter = BlobWriter;
|
|
8991
9321
|
exports.Data64URIReader = Data64URIReader;
|
|
8992
9322
|
exports.Data64URIWriter = Data64URIWriter;
|
|
9323
|
+
exports.ERR_ABORTED = ERR_ABORTED;
|
|
8993
9324
|
exports.ERR_AMBIGUOUS_ARCHIVE = ERR_AMBIGUOUS_ARCHIVE;
|
|
8994
9325
|
exports.ERR_BAD_FORMAT = ERR_BAD_FORMAT;
|
|
8995
9326
|
exports.ERR_CENTRAL_DIRECTORY_NOT_FOUND = ERR_CENTRAL_DIRECTORY_NOT_FOUND;
|
|
@@ -9002,7 +9333,9 @@
|
|
|
9002
9333
|
exports.ERR_EXTRAFIELD_ZIP64_NOT_FOUND = ERR_EXTRAFIELD_ZIP64_NOT_FOUND;
|
|
9003
9334
|
exports.ERR_HTTP_RANGE = ERR_HTTP_RANGE;
|
|
9004
9335
|
exports.ERR_HTTP_RESOURCE_CHANGED = ERR_HTTP_RESOURCE_CHANGED;
|
|
9336
|
+
exports.ERR_HTTP_STATUS = ERR_HTTP_STATUS;
|
|
9005
9337
|
exports.ERR_INVALID_AUTHENTICATION_CODE = ERR_INVALID_AUTHENTICATION_CODE;
|
|
9338
|
+
exports.ERR_INVALID_BASE_URI = ERR_INVALID_BASE_URI;
|
|
9006
9339
|
exports.ERR_INVALID_CODEC_DEFINITION = ERR_INVALID_CODEC_DEFINITION;
|
|
9007
9340
|
exports.ERR_INVALID_CODEC_MODULE = ERR_INVALID_CODEC_MODULE;
|
|
9008
9341
|
exports.ERR_INVALID_COMMENT = ERR_INVALID_COMMENT;
|
|
@@ -9011,6 +9344,7 @@
|
|
|
9011
9344
|
exports.ERR_INVALID_CRC32 = ERR_INVALID_CRC32;
|
|
9012
9345
|
exports.ERR_INVALID_DATE = ERR_INVALID_DATE;
|
|
9013
9346
|
exports.ERR_INVALID_ENCRYPTION_STRENGTH = ERR_INVALID_ENCRYPTION_STRENGTH;
|
|
9347
|
+
exports.ERR_INVALID_ENTRY = ERR_INVALID_ENTRY;
|
|
9014
9348
|
exports.ERR_INVALID_ENTRY_COMMENT = ERR_INVALID_ENTRY_COMMENT;
|
|
9015
9349
|
exports.ERR_INVALID_ENTRY_COMMENT_TYPE = ERR_INVALID_ENTRY_COMMENT_TYPE;
|
|
9016
9350
|
exports.ERR_INVALID_ENTRY_NAME = ERR_INVALID_ENTRY_NAME;
|
|
@@ -9028,6 +9362,7 @@
|
|
|
9028
9362
|
exports.ERR_INVALID_MSDOS_DATA = ERR_INVALID_MSDOS_DATA;
|
|
9029
9363
|
exports.ERR_INVALID_PASSWORD = ERR_INVALID_PASSWORD;
|
|
9030
9364
|
exports.ERR_INVALID_PASSWORD_TYPE = ERR_INVALID_PASSWORD_TYPE;
|
|
9365
|
+
exports.ERR_INVALID_PASS_THROUGH_VALUE = ERR_INVALID_PASS_THROUGH_VALUE;
|
|
9031
9366
|
exports.ERR_INVALID_READER = ERR_INVALID_READER;
|
|
9032
9367
|
exports.ERR_INVALID_SIGNAL = ERR_INVALID_SIGNAL;
|
|
9033
9368
|
exports.ERR_INVALID_SIGNATURE_DATA = ERR_INVALID_SIGNATURE_DATA;
|
|
@@ -9037,6 +9372,7 @@
|
|
|
9037
9372
|
exports.ERR_INVALID_UNIX_EXTRA_FIELD_TYPE = ERR_INVALID_UNIX_EXTRA_FIELD_TYPE;
|
|
9038
9373
|
exports.ERR_INVALID_UNIX_ID_SIZE = ERR_INVALID_UNIX_ID_SIZE;
|
|
9039
9374
|
exports.ERR_INVALID_UNIX_MODE = ERR_INVALID_UNIX_MODE;
|
|
9375
|
+
exports.ERR_INVALID_URI = ERR_INVALID_URI;
|
|
9040
9376
|
exports.ERR_INVALID_VERSION = ERR_INVALID_VERSION;
|
|
9041
9377
|
exports.ERR_ITERATOR_COMPLETED_TOO_SOON = ERR_ITERATOR_COMPLETED_TOO_SOON;
|
|
9042
9378
|
exports.ERR_LOCAL_FILE_HEADER_NOT_FOUND = ERR_LOCAL_FILE_HEADER_NOT_FOUND;
|
|
@@ -9044,6 +9380,7 @@
|
|
|
9044
9380
|
exports.ERR_RESERVED_COMPRESSION_METHOD = ERR_RESERVED_COMPRESSION_METHOD;
|
|
9045
9381
|
exports.ERR_SPLIT_ZIP_FILE = ERR_SPLIT_ZIP_FILE;
|
|
9046
9382
|
exports.ERR_UNDEFINED_COMPRESSION_METHOD = ERR_UNDEFINED_COMPRESSION_METHOD;
|
|
9383
|
+
exports.ERR_UNDEFINED_CRC32 = ERR_UNDEFINED_CRC32;
|
|
9047
9384
|
exports.ERR_UNDEFINED_READER = ERR_UNDEFINED_READER;
|
|
9048
9385
|
exports.ERR_UNDEFINED_UNCOMPRESSED_SIZE = ERR_UNDEFINED_UNCOMPRESSED_SIZE;
|
|
9049
9386
|
exports.ERR_UNDETERMINED_SIZE = ERR_UNDETERMINED_SIZE;
|
|
@@ -9059,6 +9396,8 @@
|
|
|
9059
9396
|
exports.ERR_UNSUPPORTED_UINT64 = ERR_UNSUPPORTED_UINT64;
|
|
9060
9397
|
exports.ERR_WORKER_STARTUP_TIMEOUT = ERR_WORKER_STARTUP_TIMEOUT;
|
|
9061
9398
|
exports.ERR_WRITER_NOT_INITIALIZED = ERR_WRITER_NOT_INITIALIZED;
|
|
9399
|
+
exports.ERR_WRITER_SIZE_NOT_WRITABLE = ERR_WRITER_SIZE_NOT_WRITABLE;
|
|
9400
|
+
exports.ERR_ZIP_CRYPTO_LAST_MOD_DATE = ERR_ZIP_CRYPTO_LAST_MOD_DATE;
|
|
9062
9401
|
exports.ERR_ZIP_NOT_EMPTY = ERR_ZIP_NOT_EMPTY;
|
|
9063
9402
|
exports.HttpRangeReader = HttpRangeReader;
|
|
9064
9403
|
exports.HttpReader = HttpReader;
|
|
@@ -9071,13 +9410,17 @@
|
|
|
9071
9410
|
exports.Uint8ArrayWriter = Uint8ArrayWriter;
|
|
9072
9411
|
exports.VERSION = VERSION;
|
|
9073
9412
|
exports.WARNING_APPENDED_DATA = WARNING_APPENDED_DATA;
|
|
9413
|
+
exports.WARNING_CLAMPED_LAST_MODIFICATION_DATE = WARNING_CLAMPED_LAST_MODIFICATION_DATE;
|
|
9074
9414
|
exports.WARNING_COMPRESSED_PATCHED_DATA = WARNING_COMPRESSED_PATCHED_DATA;
|
|
9415
|
+
exports.WARNING_COMPRESSION_UNAVAILABLE = WARNING_COMPRESSION_UNAVAILABLE;
|
|
9075
9416
|
exports.WARNING_DUPLICATE_FILENAME = WARNING_DUPLICATE_FILENAME;
|
|
9076
9417
|
exports.WARNING_MALFORMED_EXTRA_FIELD = WARNING_MALFORMED_EXTRA_FIELD;
|
|
9077
9418
|
exports.WARNING_MISMATCHED_LOCAL_FILE_HEADER_BIT_FLAG = WARNING_MISMATCHED_LOCAL_FILE_HEADER_BIT_FLAG;
|
|
9078
9419
|
exports.WARNING_MISMATCHED_LOCAL_FILE_HEADER_COMPRESSION_METHOD = WARNING_MISMATCHED_LOCAL_FILE_HEADER_COMPRESSION_METHOD;
|
|
9079
9420
|
exports.WARNING_MISMATCHED_LOCAL_FILE_HEADER_CRC32_OR_SIZES = WARNING_MISMATCHED_LOCAL_FILE_HEADER_CRC32_OR_SIZES;
|
|
9421
|
+
exports.WARNING_MISMATCHED_LOCAL_FILE_HEADER_FILENAME = WARNING_MISMATCHED_LOCAL_FILE_HEADER_FILENAME;
|
|
9080
9422
|
exports.WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY = WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY;
|
|
9423
|
+
exports.WARNING_MULTIPLE_END_OF_CENTRAL_DIRECTORY = WARNING_MULTIPLE_END_OF_CENTRAL_DIRECTORY;
|
|
9081
9424
|
exports.WARNING_PREPENDED_CENTRAL_DIRECTORY = WARNING_PREPENDED_CENTRAL_DIRECTORY;
|
|
9082
9425
|
exports.WARNING_PREPENDED_DATA = WARNING_PREPENDED_DATA;
|
|
9083
9426
|
exports.WARNING_TRAILING_CENTRAL_DIRECTORY_DATA = WARNING_TRAILING_CENTRAL_DIRECTORY_DATA;
|