@zip.js/zip.js 2.8.48 → 2.8.50
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 +351 -205
- package/dist/zip-core-external.min.js +1 -1
- package/dist/zip-core.js +357 -205
- package/dist/zip-core.min.js +1 -1
- package/dist/zip-fs-core-external.js +438 -216
- package/dist/zip-fs-core-external.min.js +1 -1
- package/dist/zip-fs-core.js +213 -435
- package/dist/zip-fs-core.min.js +1 -1
- package/dist/zip-fs-external.js +438 -216
- package/dist/zip-fs-external.min.js +1 -1
- package/dist/zip-fs-native.js +447 -219
- package/dist/zip-fs-native.min.js +1 -1
- package/dist/zip-fs.js +445 -217
- package/dist/zip-fs.min.js +1 -1
- package/dist/zip-legacy.js +359 -207
- package/dist/zip-legacy.min.js +1 -1
- package/dist/zip-native.js +360 -208
- 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 +358 -206
- package/dist/zip.min.js +1 -1
- package/index-native.cjs +446 -218
- package/index-native.min.js +1 -1
- package/index.cjs +444 -216
- package/index.d.cts +124 -2
- package/index.d.ts +124 -2
- package/index.min.js +1 -1
- package/lib/core/codec-pool.js +1 -1
- package/lib/core/codec-registry.js +2 -2
- package/lib/core/codec-worker-web.js +436 -0
- package/lib/core/codec-worker.js +23 -388
- package/lib/core/constants.js +5 -1
- package/lib/core/io.js +2 -1
- package/lib/core/options.js +8 -0
- package/lib/core/streams/zlib-js/zlib-streams.min.js +1 -1
- package/lib/core/web-worker-base.js +10 -2
- package/lib/core/web-worker-inline-native.js +1 -1
- package/lib/core/web-worker-inline-wasm.js +1 -1
- package/lib/core/zip-fs.js +88 -12
- package/lib/core/zip-reader.js +90 -16
- package/lib/core/zip-writer.js +36 -13
- package/lib/zip-core-reader.js +6 -0
- package/lib/zip-core-writer.js +4 -0
- package/package.json +1 -1
- package/worker-message-property-names.js +1 -1
package/dist/zip-fs-core.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.zip = {}));
|
|
5
5
|
})(this, (function (exports) { 'use strict';
|
|
6
6
|
|
|
7
|
-
const { Array, Object, String, Number, BigInt, Math, Date, Map, Set, Response, URL, Error, Uint8Array, Uint16Array, Uint32Array, DataView, Blob, Promise, TextEncoder, TextDecoder, document, crypto, btoa, TransformStream, ReadableStream, WritableStream, CompressionStream, DecompressionStream, navigator, Worker } = typeof globalThis !== 'undefined' ? globalThis : this || self;
|
|
7
|
+
const { Array, Object, String, Number, BigInt, Math, Date, Map, Set, Response, URL, Error, Uint8Array, Uint16Array, Uint32Array, DataView, Blob, Promise, TextEncoder, TextDecoder, document, crypto, btoa, TransformStream, ReadableStream, WritableStream, CompressionStream, DecompressionStream, navigator, Worker, Symbol, setTimeout, clearTimeout, structuredClone } = typeof globalThis !== 'undefined' ? globalThis : this || self;
|
|
8
8
|
|
|
9
9
|
/*
|
|
10
10
|
Copyright (c) 2022 Gildas Lormeau. All rights reserved.
|
|
@@ -116,6 +116,8 @@
|
|
|
116
116
|
const UNDEFINED_TYPE = "undefined";
|
|
117
117
|
const FUNCTION_TYPE = "function";
|
|
118
118
|
const OBJECT_TYPE = "object";
|
|
119
|
+
const STRING_TYPE = "string";
|
|
120
|
+
const NUMBER_TYPE = "number";
|
|
119
121
|
|
|
120
122
|
const EMPTY_UINT8_ARRAY = new Uint8Array();
|
|
121
123
|
|
|
@@ -707,7 +709,7 @@
|
|
|
707
709
|
forceRangeRequests,
|
|
708
710
|
combineSizeEocd
|
|
709
711
|
} = httpReader;
|
|
710
|
-
if (isHttpFamily(url) && (useRangeHeader || forceRangeRequests) && (typeof preventHeadRequest ==
|
|
712
|
+
if (isHttpFamily(url) && (useRangeHeader || forceRangeRequests) && (typeof preventHeadRequest == UNDEFINED_TYPE || preventHeadRequest)) {
|
|
711
713
|
const response = await sendRequest(HTTP_METHOD_GET, httpReader, getRangeHeaders(httpReader, combineSizeEocd ? -END_OF_CENTRAL_DIR_LENGTH : undefined));
|
|
712
714
|
const acceptRanges = response.headers.get(HTTP_HEADER_ACCEPT_RANGES);
|
|
713
715
|
if (!forceRangeRequests && (!acceptRanges || acceptRanges.toLowerCase() != HTTP_RANGE_UNIT)) {
|
|
@@ -3203,12 +3205,6 @@
|
|
|
3203
3205
|
|
|
3204
3206
|
|
|
3205
3207
|
const DEFAULT_CHUNK_SIZE = 64 * 1024;
|
|
3206
|
-
const MESSAGE_EVENT_TYPE = "message";
|
|
3207
|
-
const MESSAGE_START = "start";
|
|
3208
|
-
const MESSAGE_PULL = "pull";
|
|
3209
|
-
const MESSAGE_DATA = "data";
|
|
3210
|
-
const MESSAGE_ACK_DATA = "ack";
|
|
3211
|
-
const MESSAGE_CLOSE = "close";
|
|
3212
3208
|
const CODEC_DEFLATE = "deflate";
|
|
3213
3209
|
const CODEC_INFLATE = "inflate";
|
|
3214
3210
|
|
|
@@ -3331,8 +3327,8 @@
|
|
|
3331
3327
|
1. Redistributions of source code must retain the above copyright notice,
|
|
3332
3328
|
this list of conditions and the following disclaimer.
|
|
3333
3329
|
|
|
3334
|
-
2. Redistributions in binary form must reproduce the above copyright
|
|
3335
|
-
notice, this list of conditions and the following disclaimer in
|
|
3330
|
+
2. Redistributions in binary form must reproduce the above copyright
|
|
3331
|
+
notice, this list of conditions and the following disclaimer in
|
|
3336
3332
|
the documentation and/or other materials provided with the distribution.
|
|
3337
3333
|
|
|
3338
3334
|
3. The names of the authors may not be used to endorse or promote products
|
|
@@ -3350,19 +3346,6 @@
|
|
|
3350
3346
|
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
3351
3347
|
*/
|
|
3352
3348
|
|
|
3353
|
-
|
|
3354
|
-
const MODULE_WORKER_OPTIONS = { type: "module" };
|
|
3355
|
-
const ERROR_EVENT_TYPE = "error";
|
|
3356
|
-
const MESSAGE_ERROR_EVENT_TYPE = "messageerror";
|
|
3357
|
-
const ERR_WORKER_STARTUP_TIMEOUT = "Worker startup timeout";
|
|
3358
|
-
|
|
3359
|
-
let webWorkerSupported, webWorkerSource, webWorkerURI, webWorkerOptions, createWorkerFailed;
|
|
3360
|
-
let transferStreamsSupported = true;
|
|
3361
|
-
try {
|
|
3362
|
-
transferStreamsSupported = typeof structuredClone == FUNCTION_TYPE && structuredClone(new DOMException("", "AbortError")).code !== UNDEFINED_VALUE;
|
|
3363
|
-
} catch {
|
|
3364
|
-
// ignored
|
|
3365
|
-
}
|
|
3366
3349
|
let initModule = () => { };
|
|
3367
3350
|
|
|
3368
3351
|
async function supportsDeflate(config) {
|
|
@@ -3388,9 +3371,6 @@
|
|
|
3388
3371
|
|
|
3389
3372
|
constructor(workerData, { readable, writable }, { options, config, streamOptions, useWebWorkers, transferStreams, workerURI, createWorker }, onTaskFinished) {
|
|
3390
3373
|
const { signal } = streamOptions;
|
|
3391
|
-
if (createWorkerFailed) {
|
|
3392
|
-
createWorker = UNDEFINED_VALUE;
|
|
3393
|
-
}
|
|
3394
3374
|
Object.assign(workerData, {
|
|
3395
3375
|
busy: true,
|
|
3396
3376
|
generation: (workerData.generation || 0) + 1,
|
|
@@ -3432,11 +3412,7 @@
|
|
|
3432
3412
|
}
|
|
3433
3413
|
}
|
|
3434
3414
|
});
|
|
3435
|
-
|
|
3436
|
-
// deno-lint-ignore valid-typeof
|
|
3437
|
-
webWorkerSupported = typeof Worker != UNDEFINED_TYPE;
|
|
3438
|
-
}
|
|
3439
|
-
return (useWebWorkers && ((webWorkerSupported && workerURI) || createWorker) ? createWebWorkerInterface : createWorkerInterface)(workerData, config);
|
|
3415
|
+
return (createWorkerInterface)(workerData, config);
|
|
3440
3416
|
}
|
|
3441
3417
|
}
|
|
3442
3418
|
|
|
@@ -3480,58 +3456,6 @@
|
|
|
3480
3456
|
};
|
|
3481
3457
|
}
|
|
3482
3458
|
|
|
3483
|
-
function createWebWorkerInterface(workerData, config) {
|
|
3484
|
-
const { baseURI, chunkSize, workerStartupTimeout } = config;
|
|
3485
|
-
let { wasmURI } = config;
|
|
3486
|
-
|
|
3487
|
-
if (!workerData.interface) {
|
|
3488
|
-
// deno-lint-ignore valid-typeof
|
|
3489
|
-
if (typeof wasmURI == FUNCTION_TYPE) {
|
|
3490
|
-
wasmURI = wasmURI();
|
|
3491
|
-
}
|
|
3492
|
-
let worker;
|
|
3493
|
-
try {
|
|
3494
|
-
worker = getWebWorker(workerData.workerURI, baseURI, workerData);
|
|
3495
|
-
} catch {
|
|
3496
|
-
if (workerData.createWorker) {
|
|
3497
|
-
createWorkerFailed = true;
|
|
3498
|
-
} else {
|
|
3499
|
-
webWorkerSupported = false;
|
|
3500
|
-
}
|
|
3501
|
-
return createWorkerInterface(workerData, config);
|
|
3502
|
-
}
|
|
3503
|
-
Object.assign(workerData, {
|
|
3504
|
-
worker,
|
|
3505
|
-
workerAlive: false,
|
|
3506
|
-
terminated: false,
|
|
3507
|
-
interface: {
|
|
3508
|
-
run: async () => {
|
|
3509
|
-
try {
|
|
3510
|
-
return await runWebWorker(workerData, { chunkSize, wasmURI, baseURI, workerStartupTimeout });
|
|
3511
|
-
} catch (error) {
|
|
3512
|
-
if (error && error.workerStartupFailed) {
|
|
3513
|
-
if (workerData.createWorker) {
|
|
3514
|
-
createWorkerFailed = true;
|
|
3515
|
-
} else {
|
|
3516
|
-
webWorkerSupported = false;
|
|
3517
|
-
}
|
|
3518
|
-
const { reader } = workerData;
|
|
3519
|
-
if (reader) {
|
|
3520
|
-
reader.releaseLock();
|
|
3521
|
-
}
|
|
3522
|
-
workerData.reader = null;
|
|
3523
|
-
workerData.writer = null;
|
|
3524
|
-
return runWorker$1(workerData, config);
|
|
3525
|
-
}
|
|
3526
|
-
throw error;
|
|
3527
|
-
}
|
|
3528
|
-
}
|
|
3529
|
-
}
|
|
3530
|
-
});
|
|
3531
|
-
}
|
|
3532
|
-
return workerData.interface;
|
|
3533
|
-
}
|
|
3534
|
-
|
|
3535
3459
|
async function runWorker$1({ options, readable, writable, onTaskFinished }, config) {
|
|
3536
3460
|
let codecStream;
|
|
3537
3461
|
try {
|
|
@@ -3580,318 +3504,6 @@
|
|
|
3580
3504
|
}
|
|
3581
3505
|
}
|
|
3582
3506
|
|
|
3583
|
-
async function runWebWorker(workerData, config) {
|
|
3584
|
-
let resolveResult, rejectResult;
|
|
3585
|
-
const result = new Promise((resolve, reject) => {
|
|
3586
|
-
resolveResult = resolve;
|
|
3587
|
-
rejectResult = reject;
|
|
3588
|
-
});
|
|
3589
|
-
Object.assign(workerData, {
|
|
3590
|
-
reader: null,
|
|
3591
|
-
writer: null,
|
|
3592
|
-
resolveResult,
|
|
3593
|
-
rejectResult,
|
|
3594
|
-
result
|
|
3595
|
-
});
|
|
3596
|
-
const { readable, options } = workerData;
|
|
3597
|
-
const { writable, closed, abortPipe } = watchClosedStream(workerData.writable);
|
|
3598
|
-
let streamsTransferred;
|
|
3599
|
-
try {
|
|
3600
|
-
streamsTransferred = sendMessage({
|
|
3601
|
-
type: MESSAGE_START,
|
|
3602
|
-
options,
|
|
3603
|
-
config,
|
|
3604
|
-
readable,
|
|
3605
|
-
writable
|
|
3606
|
-
}, workerData);
|
|
3607
|
-
} catch (error) {
|
|
3608
|
-
abortPipe();
|
|
3609
|
-
try {
|
|
3610
|
-
await closed;
|
|
3611
|
-
} catch {
|
|
3612
|
-
// ignored
|
|
3613
|
-
}
|
|
3614
|
-
workerData.onTaskFinished();
|
|
3615
|
-
throw error;
|
|
3616
|
-
}
|
|
3617
|
-
if (!streamsTransferred) {
|
|
3618
|
-
Object.assign(workerData, {
|
|
3619
|
-
reader: readable.getReader(),
|
|
3620
|
-
writer: writable.getWriter()
|
|
3621
|
-
});
|
|
3622
|
-
}
|
|
3623
|
-
const { workerStartupTimeout } = config;
|
|
3624
|
-
if (!workerData.workerAlive && Number.isFinite(workerStartupTimeout) && workerStartupTimeout >= 0) {
|
|
3625
|
-
workerData.startupTimeout = setTimeout(() => onStartupTimeout(workerData), workerStartupTimeout);
|
|
3626
|
-
}
|
|
3627
|
-
try {
|
|
3628
|
-
const resultValue = await result;
|
|
3629
|
-
await closeWritable();
|
|
3630
|
-
await closed;
|
|
3631
|
-
return resultValue;
|
|
3632
|
-
} catch (error) {
|
|
3633
|
-
await closeWritable();
|
|
3634
|
-
abortPipe();
|
|
3635
|
-
try {
|
|
3636
|
-
await closed;
|
|
3637
|
-
} catch {
|
|
3638
|
-
// ignored
|
|
3639
|
-
}
|
|
3640
|
-
throw error;
|
|
3641
|
-
}
|
|
3642
|
-
|
|
3643
|
-
async function closeWritable() {
|
|
3644
|
-
if (!streamsTransferred && !writable.locked) {
|
|
3645
|
-
try {
|
|
3646
|
-
await writable.getWriter().close();
|
|
3647
|
-
} catch {
|
|
3648
|
-
// ignored
|
|
3649
|
-
}
|
|
3650
|
-
}
|
|
3651
|
-
}
|
|
3652
|
-
}
|
|
3653
|
-
|
|
3654
|
-
function watchClosedStream(writableSource) {
|
|
3655
|
-
const abortController = new AbortController();
|
|
3656
|
-
const { writable, readable } = new TransformStream();
|
|
3657
|
-
const closed = readable.pipeTo(writableSource, { preventClose: true, preventAbort: true, signal: abortController.signal });
|
|
3658
|
-
closed.catch(() => { });
|
|
3659
|
-
return { writable, closed, abortPipe: () => abortController.abort() };
|
|
3660
|
-
}
|
|
3661
|
-
|
|
3662
|
-
function terminateWorker$1(workerData) {
|
|
3663
|
-
const { worker } = workerData;
|
|
3664
|
-
if (worker) {
|
|
3665
|
-
try {
|
|
3666
|
-
worker.terminate();
|
|
3667
|
-
} catch {
|
|
3668
|
-
// ignored
|
|
3669
|
-
}
|
|
3670
|
-
}
|
|
3671
|
-
workerData.interface = null;
|
|
3672
|
-
}
|
|
3673
|
-
|
|
3674
|
-
function getWebWorker(url, baseURI, workerData, isModuleType, useBlobURI = true) {
|
|
3675
|
-
const { createWorker } = workerData;
|
|
3676
|
-
let worker, resolvedURI, resolvedOptions;
|
|
3677
|
-
if (createWorker) {
|
|
3678
|
-
worker = createWorker();
|
|
3679
|
-
} else if (webWorkerURI === UNDEFINED_VALUE || webWorkerSource !== url) {
|
|
3680
|
-
// deno-lint-ignore valid-typeof
|
|
3681
|
-
const isFunctionURI = typeof url == FUNCTION_TYPE;
|
|
3682
|
-
if (isFunctionURI) {
|
|
3683
|
-
resolvedURI = url(useBlobURI);
|
|
3684
|
-
} else {
|
|
3685
|
-
resolvedURI = url;
|
|
3686
|
-
}
|
|
3687
|
-
const isDataURI = resolvedURI.startsWith("data:");
|
|
3688
|
-
const isBlobURI = resolvedURI.startsWith("blob:");
|
|
3689
|
-
if (isDataURI || isBlobURI) {
|
|
3690
|
-
if (isModuleType === UNDEFINED_VALUE) {
|
|
3691
|
-
isModuleType = false;
|
|
3692
|
-
}
|
|
3693
|
-
if (isModuleType) {
|
|
3694
|
-
resolvedOptions = MODULE_WORKER_OPTIONS;
|
|
3695
|
-
}
|
|
3696
|
-
try {
|
|
3697
|
-
worker = new Worker(resolvedURI, resolvedOptions);
|
|
3698
|
-
} catch (error) {
|
|
3699
|
-
if (isBlobURI) {
|
|
3700
|
-
try {
|
|
3701
|
-
URL.revokeObjectURL(resolvedURI);
|
|
3702
|
-
} catch {
|
|
3703
|
-
// ignored
|
|
3704
|
-
}
|
|
3705
|
-
}
|
|
3706
|
-
if (isFunctionURI && isBlobURI) {
|
|
3707
|
-
return getWebWorker(url, baseURI, workerData, isModuleType, false);
|
|
3708
|
-
} else if (!isModuleType) {
|
|
3709
|
-
return getWebWorker(url, baseURI, workerData, true, false);
|
|
3710
|
-
} else {
|
|
3711
|
-
throw error;
|
|
3712
|
-
}
|
|
3713
|
-
}
|
|
3714
|
-
} else {
|
|
3715
|
-
if (isModuleType === UNDEFINED_VALUE) {
|
|
3716
|
-
isModuleType = true;
|
|
3717
|
-
}
|
|
3718
|
-
if (isModuleType) {
|
|
3719
|
-
resolvedOptions = MODULE_WORKER_OPTIONS;
|
|
3720
|
-
}
|
|
3721
|
-
try {
|
|
3722
|
-
resolvedURI = new URL(resolvedURI, baseURI);
|
|
3723
|
-
} catch {
|
|
3724
|
-
// ignored
|
|
3725
|
-
}
|
|
3726
|
-
try {
|
|
3727
|
-
worker = new Worker(resolvedURI, resolvedOptions);
|
|
3728
|
-
} catch (error) {
|
|
3729
|
-
if (!isModuleType) {
|
|
3730
|
-
return getWebWorker(url, baseURI, workerData, false, useBlobURI);
|
|
3731
|
-
} else {
|
|
3732
|
-
throw error;
|
|
3733
|
-
}
|
|
3734
|
-
}
|
|
3735
|
-
}
|
|
3736
|
-
webWorkerSource = url;
|
|
3737
|
-
webWorkerURI = resolvedURI;
|
|
3738
|
-
webWorkerOptions = resolvedOptions;
|
|
3739
|
-
} else {
|
|
3740
|
-
worker = new Worker(webWorkerURI, webWorkerOptions);
|
|
3741
|
-
}
|
|
3742
|
-
worker.addEventListener(MESSAGE_EVENT_TYPE, event => {
|
|
3743
|
-
workerData.workerAlive = true;
|
|
3744
|
-
clearStartupTimeout(workerData);
|
|
3745
|
-
onMessage(event, workerData);
|
|
3746
|
-
});
|
|
3747
|
-
worker.addEventListener(ERROR_EVENT_TYPE, event => onWorkerError(event, workerData));
|
|
3748
|
-
worker.addEventListener(MESSAGE_ERROR_EVENT_TYPE, event => onWorkerError(event, workerData));
|
|
3749
|
-
return worker;
|
|
3750
|
-
}
|
|
3751
|
-
|
|
3752
|
-
function onStartupTimeout(workerData) {
|
|
3753
|
-
workerData.startupTimeout = null;
|
|
3754
|
-
if (workerData.workerAlive) {
|
|
3755
|
-
return;
|
|
3756
|
-
}
|
|
3757
|
-
const { rejectResult, writer } = workerData;
|
|
3758
|
-
terminateWorker$1(workerData);
|
|
3759
|
-
workerData.worker = null;
|
|
3760
|
-
if (rejectResult) {
|
|
3761
|
-
const error = new Error(ERR_WORKER_STARTUP_TIMEOUT);
|
|
3762
|
-
error.workerStartupFailed = true;
|
|
3763
|
-
rejectResult(error);
|
|
3764
|
-
if (writer) {
|
|
3765
|
-
writer.releaseLock();
|
|
3766
|
-
}
|
|
3767
|
-
}
|
|
3768
|
-
}
|
|
3769
|
-
|
|
3770
|
-
function clearStartupTimeout(workerData) {
|
|
3771
|
-
const { startupTimeout } = workerData;
|
|
3772
|
-
if (startupTimeout) {
|
|
3773
|
-
clearTimeout(startupTimeout);
|
|
3774
|
-
workerData.startupTimeout = null;
|
|
3775
|
-
}
|
|
3776
|
-
}
|
|
3777
|
-
|
|
3778
|
-
function onWorkerError(event, workerData) {
|
|
3779
|
-
if (event.preventDefault) {
|
|
3780
|
-
event.preventDefault();
|
|
3781
|
-
}
|
|
3782
|
-
clearStartupTimeout(workerData);
|
|
3783
|
-
const { workerAlive, rejectResult, writer, onTaskFinished } = workerData;
|
|
3784
|
-
terminateWorker$1(workerData);
|
|
3785
|
-
if (!workerAlive) {
|
|
3786
|
-
workerData.worker = null;
|
|
3787
|
-
}
|
|
3788
|
-
if (rejectResult) {
|
|
3789
|
-
let error = event.error || new Error(event.message || ERROR_EVENT_TYPE);
|
|
3790
|
-
if (!workerAlive) {
|
|
3791
|
-
error = Object.assign(new Error(error.message || ERROR_EVENT_TYPE), { workerStartupFailed: true });
|
|
3792
|
-
}
|
|
3793
|
-
rejectResult(error);
|
|
3794
|
-
if (writer) {
|
|
3795
|
-
writer.releaseLock();
|
|
3796
|
-
}
|
|
3797
|
-
if (workerAlive) {
|
|
3798
|
-
onTaskFinished();
|
|
3799
|
-
}
|
|
3800
|
-
}
|
|
3801
|
-
}
|
|
3802
|
-
|
|
3803
|
-
function sendMessage(message, { worker, writer, transferStreams, workerAlive }) {
|
|
3804
|
-
try {
|
|
3805
|
-
const { value, readable, writable } = message;
|
|
3806
|
-
const transferables = [];
|
|
3807
|
-
if (value) {
|
|
3808
|
-
message.value = toExactUint8Array(value);
|
|
3809
|
-
transferables.push(message.value.buffer);
|
|
3810
|
-
}
|
|
3811
|
-
if (transferStreams && transferStreamsSupported && workerAlive) {
|
|
3812
|
-
if (readable) {
|
|
3813
|
-
transferables.push(readable);
|
|
3814
|
-
}
|
|
3815
|
-
if (writable) {
|
|
3816
|
-
transferables.push(writable);
|
|
3817
|
-
}
|
|
3818
|
-
} else {
|
|
3819
|
-
message.readable = message.writable = null;
|
|
3820
|
-
}
|
|
3821
|
-
if (transferables.length) {
|
|
3822
|
-
try {
|
|
3823
|
-
worker.postMessage(message, transferables);
|
|
3824
|
-
return true;
|
|
3825
|
-
} catch {
|
|
3826
|
-
transferStreamsSupported = false;
|
|
3827
|
-
message.readable = message.writable = null;
|
|
3828
|
-
worker.postMessage(message);
|
|
3829
|
-
}
|
|
3830
|
-
} else {
|
|
3831
|
-
worker.postMessage(message);
|
|
3832
|
-
}
|
|
3833
|
-
} catch (error) {
|
|
3834
|
-
if (writer) {
|
|
3835
|
-
writer.releaseLock();
|
|
3836
|
-
}
|
|
3837
|
-
throw error;
|
|
3838
|
-
}
|
|
3839
|
-
}
|
|
3840
|
-
|
|
3841
|
-
async function onMessage({ data }, workerData) {
|
|
3842
|
-
const { type, value, messageId, result, error } = data;
|
|
3843
|
-
const { reader, writer, resolveResult, rejectResult, onTaskFinished, generation } = workerData;
|
|
3844
|
-
const stale = () => workerData.generation != generation;
|
|
3845
|
-
try {
|
|
3846
|
-
if (error) {
|
|
3847
|
-
const { message, stack, code, name, outputSize, cause } = error;
|
|
3848
|
-
const responseError = new Error(message);
|
|
3849
|
-
Object.assign(responseError, { stack, code, name, outputSize });
|
|
3850
|
-
if (cause) {
|
|
3851
|
-
responseError.cause = Object.assign(new Error(cause.message), { name: cause.name });
|
|
3852
|
-
}
|
|
3853
|
-
close(responseError);
|
|
3854
|
-
} else {
|
|
3855
|
-
if (type == MESSAGE_PULL) {
|
|
3856
|
-
const { value, done } = await reader.read();
|
|
3857
|
-
if (!stale()) {
|
|
3858
|
-
sendMessage({ type: MESSAGE_DATA, value, done, messageId }, workerData);
|
|
3859
|
-
}
|
|
3860
|
-
}
|
|
3861
|
-
if (type == MESSAGE_DATA) {
|
|
3862
|
-
await writer.ready;
|
|
3863
|
-
await writer.write(new Uint8Array(value));
|
|
3864
|
-
if (!stale()) {
|
|
3865
|
-
sendMessage({ type: MESSAGE_ACK_DATA, messageId }, workerData);
|
|
3866
|
-
}
|
|
3867
|
-
}
|
|
3868
|
-
if (type == MESSAGE_CLOSE) {
|
|
3869
|
-
close(null, result);
|
|
3870
|
-
}
|
|
3871
|
-
}
|
|
3872
|
-
} catch (error) {
|
|
3873
|
-
if (!stale()) {
|
|
3874
|
-
terminateWorker$1(workerData);
|
|
3875
|
-
close(error);
|
|
3876
|
-
}
|
|
3877
|
-
}
|
|
3878
|
-
|
|
3879
|
-
function close(error, result) {
|
|
3880
|
-
if (stale()) {
|
|
3881
|
-
return;
|
|
3882
|
-
}
|
|
3883
|
-
if (error) {
|
|
3884
|
-
rejectResult(error);
|
|
3885
|
-
} else {
|
|
3886
|
-
resolveResult(result);
|
|
3887
|
-
}
|
|
3888
|
-
if (writer) {
|
|
3889
|
-
writer.releaseLock();
|
|
3890
|
-
}
|
|
3891
|
-
onTaskFinished();
|
|
3892
|
-
}
|
|
3893
|
-
}
|
|
3894
|
-
|
|
3895
3507
|
/*
|
|
3896
3508
|
Copyright (c) 2025 Gildas Lormeau. All rights reserved.
|
|
3897
3509
|
|
|
@@ -3938,7 +3550,7 @@
|
|
|
3938
3550
|
}
|
|
3939
3551
|
await ensureCodecStreams(format, options.codecURI);
|
|
3940
3552
|
}
|
|
3941
|
-
workerOptions.transferStreams = transferStreams || (transferStreams === UNDEFINED_VALUE && config.transferStreams);
|
|
3553
|
+
workerOptions.transferStreams = !format && (transferStreams || (transferStreams === UNDEFINED_VALUE && config.transferStreams));
|
|
3942
3554
|
const streamCopy = !compressed && !checkCrc32 && !computeCrc32 && !encrypted;
|
|
3943
3555
|
const workerSupported = format === UNDEFINED_VALUE || Boolean(options.codecURI);
|
|
3944
3556
|
workerOptions.useWebWorkers = !streamCopy && workerSupported && (useWebWorkers || (useWebWorkers === UNDEFINED_VALUE && config.useWebWorkers));
|
|
@@ -4334,9 +3946,13 @@
|
|
|
4334
3946
|
const OPTION_UNIX_EXTRA_FIELD_TYPE = "unixExtraFieldType";
|
|
4335
3947
|
const OPTION_LOCAL_EXTRA_FIELD = "localExtraField";
|
|
4336
3948
|
const OPTION_STRICTNESS = "strictness";
|
|
3949
|
+
const OPTION_FILENAME_VALIDATION = "filenameValidation";
|
|
3950
|
+
const OPTION_NORMALIZE_FILENAME = "normalizeFilename";
|
|
4337
3951
|
const OPTION_MAX_APPENDED_DATA_SIZE = "maxAppendedDataSize";
|
|
4338
3952
|
const OPTION_DECRYPT_CENTRAL_DIRECTORY = "decryptCentralDirectory";
|
|
4339
3953
|
const OPTION_SIGN_CENTRAL_DIRECTORY = "signCentralDirectory";
|
|
3954
|
+
const TEXT_TYPE_FILENAME = "filename";
|
|
3955
|
+
const TEXT_TYPE_COMMENT = "comment";
|
|
4340
3956
|
const STRICTNESS_STRICT = "strict";
|
|
4341
3957
|
const STRICTNESS_BALANCED = "balanced";
|
|
4342
3958
|
const STRICTNESS_TOLERANT = "tolerant";
|
|
@@ -4383,6 +3999,11 @@
|
|
|
4383
3999
|
const ERR_OVERLAPPING_ENTRY = "Overlapping entry found";
|
|
4384
4000
|
const ERR_AMBIGUOUS_ARCHIVE = "Ambiguous archive";
|
|
4385
4001
|
const ERR_ENCRYPTED_CENTRAL_DIRECTORY = "Encrypted central directory is not supported";
|
|
4002
|
+
const ERR_UNSAFE_FILENAME = "Unsafe filename";
|
|
4003
|
+
const ERR_INVALID_STRICTNESS = "Invalid strictness (must be 'strict', 'balanced' or 'tolerant')";
|
|
4004
|
+
const ERR_INVALID_FILENAME_VALIDATION = "Invalid filenameValidation (must be 'strict', 'balanced' or 'tolerant')";
|
|
4005
|
+
const ERR_INVALID_MAX_APPENDED_DATA_SIZE = "Invalid maxAppendedDataSize (must be a number greater than or equal to 0)";
|
|
4006
|
+
const DRIVE_LETTER_REGEXP = /^[a-zA-Z]:/;
|
|
4386
4007
|
const CHARSET_UTF8 = "utf-8";
|
|
4387
4008
|
const PROPERTY_NAME_UTF8_SUFFIX = "UTF8";
|
|
4388
4009
|
const CHARSET_CP437 = "cp437";
|
|
@@ -4404,6 +4025,10 @@
|
|
|
4404
4025
|
bytes: 8
|
|
4405
4026
|
}
|
|
4406
4027
|
};
|
|
4028
|
+
const MAX_END_OF_CENTRAL_DIR_PROBES = 64;
|
|
4029
|
+
const CENTRAL_DIRECTORY_UNREACHABLE = 0;
|
|
4030
|
+
const CENTRAL_DIRECTORY_PLAUSIBLE = 1;
|
|
4031
|
+
const CENTRAL_DIRECTORY_REACHABLE = 2;
|
|
4407
4032
|
|
|
4408
4033
|
class ZipReader {
|
|
4409
4034
|
|
|
@@ -4432,6 +4057,8 @@
|
|
|
4432
4057
|
const checkAmbiguity = strictness == STRICTNESS_STRICT;
|
|
4433
4058
|
const rejectAmbiguousEndOfDirectory = strictness != STRICTNESS_TOLERANT;
|
|
4434
4059
|
const maxAppendedDataSize = getMaxAppendedDataSize(getOptionValue$1(zipReader, options, OPTION_MAX_APPENDED_DATA_SIZE), strictness);
|
|
4060
|
+
const filenameValidation = getFilenameValidation(getOptionValue$1(zipReader, options, OPTION_FILENAME_VALIDATION), strictness);
|
|
4061
|
+
const normalizeFilename = getOptionValue$1(zipReader, options, OPTION_NORMALIZE_FILENAME);
|
|
4435
4062
|
const { endOfDirectoryInfo, endOfDirectoryReachingEndCount } = await findEndOfCentralDirectory(reader, rejectAmbiguousEndOfDirectory, maxAppendedDataSize);
|
|
4436
4063
|
if (!endOfDirectoryInfo) {
|
|
4437
4064
|
const signatureArray = await readUint8Array(reader, 0, 4);
|
|
@@ -4625,11 +4252,22 @@
|
|
|
4625
4252
|
const decode = getOptionValue$1(zipReader, options, OPTION_DECODE_TEXT) || decodeText;
|
|
4626
4253
|
const rawFilenameEncoding = filenameUTF8 ? CHARSET_UTF8 : filenameEncoding || CHARSET_CP437;
|
|
4627
4254
|
const rawCommentEncoding = commentUTF8 ? CHARSET_UTF8 : commentEncoding || CHARSET_CP437;
|
|
4628
|
-
let filename = decode(rawFilename, rawFilenameEncoding);
|
|
4255
|
+
let filename = decode(rawFilename, rawFilenameEncoding, TEXT_TYPE_FILENAME);
|
|
4629
4256
|
if (filename === UNDEFINED_VALUE) {
|
|
4630
4257
|
filename = decodeText(rawFilename, rawFilenameEncoding);
|
|
4631
4258
|
}
|
|
4632
|
-
|
|
4259
|
+
if (normalizeFilename) {
|
|
4260
|
+
const normalizedFilename = normalizeFilename(filename);
|
|
4261
|
+
if (normalizedFilename !== UNDEFINED_VALUE) {
|
|
4262
|
+
filename = normalizedFilename;
|
|
4263
|
+
}
|
|
4264
|
+
}
|
|
4265
|
+
if (isUnsafeFilename(filename, filenameValidation)) {
|
|
4266
|
+
const error = new Error(ERR_UNSAFE_FILENAME);
|
|
4267
|
+
error.filename = filename;
|
|
4268
|
+
throw error;
|
|
4269
|
+
}
|
|
4270
|
+
let comment = decode(rawComment, rawCommentEncoding, TEXT_TYPE_COMMENT);
|
|
4633
4271
|
if (comment === UNDEFINED_VALUE) {
|
|
4634
4272
|
comment = decodeText(rawComment, rawCommentEncoding);
|
|
4635
4273
|
}
|
|
@@ -4690,10 +4328,10 @@
|
|
|
4690
4328
|
entry.getData = (writer, options) => fileEntry.getData(writer, entry, zipReader.readRanges, options);
|
|
4691
4329
|
entry.arrayBuffer = async options => {
|
|
4692
4330
|
const writer = new TransformStream();
|
|
4693
|
-
const
|
|
4694
|
-
|
|
4695
|
-
|
|
4696
|
-
return
|
|
4331
|
+
const arrayBufferPromise = streamToBlob(writer.readable).then(blob => blob.arrayBuffer());
|
|
4332
|
+
arrayBufferPromise.catch(() => { });
|
|
4333
|
+
await fileEntry.getData(writer, entry, zipReader.readRanges, options);
|
|
4334
|
+
return arrayBufferPromise;
|
|
4697
4335
|
};
|
|
4698
4336
|
offset = endOffset;
|
|
4699
4337
|
const { onprogress } = options;
|
|
@@ -4904,7 +4542,7 @@
|
|
|
4904
4542
|
readRanges
|
|
4905
4543
|
});
|
|
4906
4544
|
}
|
|
4907
|
-
let writable;
|
|
4545
|
+
let writable, abortError;
|
|
4908
4546
|
try {
|
|
4909
4547
|
if (!checkOverlappingEntryOnly) {
|
|
4910
4548
|
if (checkPasswordOnly) {
|
|
@@ -4924,12 +4562,22 @@
|
|
|
4924
4562
|
writer.size += error.outputSize;
|
|
4925
4563
|
}
|
|
4926
4564
|
if (!checkPasswordOnly || error.message != ERR_ABORT_CHECK_PASSWORD) {
|
|
4565
|
+
abortError = error;
|
|
4927
4566
|
throw error;
|
|
4928
4567
|
}
|
|
4929
4568
|
} finally {
|
|
4930
4569
|
const preventClose = getOptionValue$1(zipEntry, options, OPTION_PREVENT_CLOSE);
|
|
4931
4570
|
if (!preventClose && writable && !writable.locked) {
|
|
4932
|
-
|
|
4571
|
+
const writableWriter = writable.getWriter();
|
|
4572
|
+
if (abortError) {
|
|
4573
|
+
try {
|
|
4574
|
+
await writableWriter.abort(abortError);
|
|
4575
|
+
} catch {
|
|
4576
|
+
// the error being propagated is more relevant; ignored
|
|
4577
|
+
}
|
|
4578
|
+
} else {
|
|
4579
|
+
await writableWriter.close();
|
|
4580
|
+
}
|
|
4933
4581
|
}
|
|
4934
4582
|
}
|
|
4935
4583
|
return checkPasswordOnly || checkOverlappingEntryOnly ? UNDEFINED_VALUE : writer.getData ? writer.getData() : writable;
|
|
@@ -5309,16 +4957,51 @@
|
|
|
5309
4957
|
return reader.getDiskOffset ? reader.getDiskOffset(diskNumber) : 0;
|
|
5310
4958
|
}
|
|
5311
4959
|
|
|
4960
|
+
function isStrictnessValue(value) {
|
|
4961
|
+
return value === STRICTNESS_STRICT || value === STRICTNESS_BALANCED || value === STRICTNESS_TOLERANT;
|
|
4962
|
+
}
|
|
4963
|
+
|
|
5312
4964
|
function getStrictness(strictness, checkAmbiguity) {
|
|
5313
4965
|
if (strictness === UNDEFINED_VALUE) {
|
|
5314
4966
|
return checkAmbiguity ? STRICTNESS_STRICT : STRICTNESS_BALANCED;
|
|
5315
4967
|
}
|
|
4968
|
+
if (!isStrictnessValue(strictness)) {
|
|
4969
|
+
throw new Error(ERR_INVALID_STRICTNESS);
|
|
4970
|
+
}
|
|
5316
4971
|
return strictness;
|
|
5317
4972
|
}
|
|
5318
4973
|
|
|
4974
|
+
function getFilenameValidation(filenameValidation, strictness) {
|
|
4975
|
+
if (filenameValidation === UNDEFINED_VALUE) {
|
|
4976
|
+
return strictness;
|
|
4977
|
+
}
|
|
4978
|
+
if (!isStrictnessValue(filenameValidation)) {
|
|
4979
|
+
throw new Error(ERR_INVALID_FILENAME_VALIDATION);
|
|
4980
|
+
}
|
|
4981
|
+
return filenameValidation;
|
|
4982
|
+
}
|
|
4983
|
+
|
|
4984
|
+
function isUnsafeFilename(filename, filenameValidation) {
|
|
4985
|
+
if (filenameValidation == STRICTNESS_TOLERANT) {
|
|
4986
|
+
return false;
|
|
4987
|
+
}
|
|
4988
|
+
const pathParts = filename.split("/");
|
|
4989
|
+
if (pathParts.length > 1 && pathParts[pathParts.length - 1] === "") {
|
|
4990
|
+
pathParts.pop();
|
|
4991
|
+
}
|
|
4992
|
+
if (pathParts.includes("..") || filename.startsWith("/") || filename.startsWith("\\\\") || DRIVE_LETTER_REGEXP.test(filename)) {
|
|
4993
|
+
return true;
|
|
4994
|
+
}
|
|
4995
|
+
return filenameValidation == STRICTNESS_STRICT && (pathParts.includes(".") || pathParts.includes(""));
|
|
4996
|
+
}
|
|
4997
|
+
|
|
5319
4998
|
function getMaxAppendedDataSize(maxAppendedDataSize, strictness) {
|
|
5320
4999
|
if (maxAppendedDataSize !== UNDEFINED_VALUE) {
|
|
5321
|
-
|
|
5000
|
+
const size = toNumber$1(maxAppendedDataSize);
|
|
5001
|
+
if (typeof size != NUMBER_TYPE || Number.isNaN(size) || size < 0) {
|
|
5002
|
+
throw new Error(ERR_INVALID_MAX_APPENDED_DATA_SIZE);
|
|
5003
|
+
}
|
|
5004
|
+
return size;
|
|
5322
5005
|
}
|
|
5323
5006
|
if (strictness == STRICTNESS_STRICT) {
|
|
5324
5007
|
return 0;
|
|
@@ -5329,12 +5012,6 @@
|
|
|
5329
5012
|
return MAX_16_BITS;
|
|
5330
5013
|
}
|
|
5331
5014
|
|
|
5332
|
-
const MAX_END_OF_CENTRAL_DIR_PROBES = 64;
|
|
5333
|
-
|
|
5334
|
-
const CENTRAL_DIRECTORY_UNREACHABLE = 0;
|
|
5335
|
-
const CENTRAL_DIRECTORY_PLAUSIBLE = 1;
|
|
5336
|
-
const CENTRAL_DIRECTORY_REACHABLE = 2;
|
|
5337
|
-
|
|
5338
5015
|
async function findEndOfCentralDirectory(reader, rejectAmbiguous, maxAppendedDataSize) {
|
|
5339
5016
|
const { size } = reader;
|
|
5340
5017
|
const anchoredLength = Math.min(size, END_OF_CENTRAL_DIR_LENGTH + MAX_16_BITS);
|
|
@@ -5470,6 +5147,10 @@
|
|
|
5470
5147
|
return options[name] === UNDEFINED_VALUE ? zipReader.options[name] : options[name];
|
|
5471
5148
|
}
|
|
5472
5149
|
|
|
5150
|
+
function toNumber$1(value) {
|
|
5151
|
+
return typeof value == STRING_TYPE && value.trim() ? Number(value) : value;
|
|
5152
|
+
}
|
|
5153
|
+
|
|
5473
5154
|
function getDate(timeRaw) {
|
|
5474
5155
|
const date = (timeRaw & 0xffff0000) >> 16, time = timeRaw & MAX_16_BITS;
|
|
5475
5156
|
return new Date(1980 + ((date & 0xFE00) >> 9), ((date & 0x01E0) >> 5) - 1, date & 0x001F, (time & 0xF800) >> 11, (time & 0x07E0) >> 5, (time & 0x001F) * 2, 0);
|
|
@@ -5508,15 +5189,18 @@
|
|
|
5508
5189
|
ERR_INVALID_AUTHENTICATION_CODE: ERR_INVALID_AUTHENTICATION_CODE,
|
|
5509
5190
|
ERR_INVALID_COMPRESSED_DATA: ERR_INVALID_COMPRESSED_DATA,
|
|
5510
5191
|
ERR_INVALID_CRC32: ERR_INVALID_CRC32,
|
|
5192
|
+
ERR_INVALID_FILENAME_VALIDATION: ERR_INVALID_FILENAME_VALIDATION,
|
|
5193
|
+
ERR_INVALID_MAX_APPENDED_DATA_SIZE: ERR_INVALID_MAX_APPENDED_DATA_SIZE,
|
|
5511
5194
|
ERR_INVALID_PASSWORD: ERR_INVALID_PASSWORD,
|
|
5512
5195
|
ERR_INVALID_SIGNATURE: ERR_INVALID_SIGNATURE,
|
|
5196
|
+
ERR_INVALID_STRICTNESS: ERR_INVALID_STRICTNESS,
|
|
5513
5197
|
ERR_INVALID_UNCOMPRESSED_SIZE: ERR_INVALID_UNCOMPRESSED_SIZE,
|
|
5514
5198
|
ERR_LOCAL_FILE_HEADER_NOT_FOUND: ERR_LOCAL_FILE_HEADER_NOT_FOUND,
|
|
5515
5199
|
ERR_OVERLAPPING_ENTRY: ERR_OVERLAPPING_ENTRY,
|
|
5516
5200
|
ERR_SPLIT_ZIP_FILE: ERR_SPLIT_ZIP_FILE,
|
|
5201
|
+
ERR_UNSAFE_FILENAME: ERR_UNSAFE_FILENAME,
|
|
5517
5202
|
ERR_UNSUPPORTED_COMPRESSION: ERR_UNSUPPORTED_COMPRESSION$1,
|
|
5518
5203
|
ERR_UNSUPPORTED_ENCRYPTION: ERR_UNSUPPORTED_ENCRYPTION,
|
|
5519
|
-
ERR_WORKER_STARTUP_TIMEOUT: ERR_WORKER_STARTUP_TIMEOUT,
|
|
5520
5204
|
ZipReader: ZipReader
|
|
5521
5205
|
});
|
|
5522
5206
|
|
|
@@ -5574,6 +5258,8 @@
|
|
|
5574
5258
|
const ERR_INVALID_UNIX_ID_SIZE = "uid/gid must be 0..65535 for unixExtraFieldType 'unix' (use 'infozip' for larger ids)";
|
|
5575
5259
|
const ERR_INVALID_MSDOS_ATTRIBUTES = "Invalid msdosAttributesRaw (must be integer 0..255)";
|
|
5576
5260
|
const ERR_INVALID_MSDOS_DATA = "Invalid msdosAttributes (must be an object with boolean flags)";
|
|
5261
|
+
const ERR_INVALID_LEVEL = "Invalid level (must be integer 0..9)";
|
|
5262
|
+
const ERR_INVALID_PASSWORD_TYPE = "Invalid password (password must be a string, rawPassword must be a Uint8Array)";
|
|
5577
5263
|
const ERR_INVALID_SIGNATURE_DATA = "Signature data exceeds 64KB";
|
|
5578
5264
|
|
|
5579
5265
|
const EXTRAFIELD_DATA_AES = new Uint8Array([0x07, 0x00, 0x02, 0x00, 0x41, 0x45, 0x03, 0x00, 0x00]);
|
|
@@ -5581,6 +5267,7 @@
|
|
|
5581
5267
|
const VENDOR_VERSION_AE_1 = 1;
|
|
5582
5268
|
const INFOZIP_EXTRA_FIELD_TYPE$1 = "infozip";
|
|
5583
5269
|
const UNIX_EXTRA_FIELD_TYPE = "unix";
|
|
5270
|
+
const MAX_LEVEL = 9;
|
|
5584
5271
|
|
|
5585
5272
|
let workers = 0;
|
|
5586
5273
|
const pendingEntries = [];
|
|
@@ -5743,7 +5430,8 @@
|
|
|
5743
5430
|
|
|
5744
5431
|
remove(entry) {
|
|
5745
5432
|
const { filenames, files } = this;
|
|
5746
|
-
|
|
5433
|
+
// deno-lint-ignore valid-typeof
|
|
5434
|
+
if (typeof entry == STRING_TYPE) {
|
|
5747
5435
|
entry = files.get(entry);
|
|
5748
5436
|
}
|
|
5749
5437
|
if (entry && entry.filename !== UNDEFINED_VALUE) {
|
|
@@ -5819,20 +5507,20 @@
|
|
|
5819
5507
|
let msDosCompatible = getOptionValue(zipWriter, options, PROPERTY_NAME_MS_DOS_COMPATIBLE);
|
|
5820
5508
|
let versionMadeBy = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION_MADE_BY, msDosCompatible ? 20 : 768);
|
|
5821
5509
|
const executable = getOptionValue(zipWriter, options, PROPERTY_NAME_EXECUTABLE);
|
|
5822
|
-
const uid =
|
|
5823
|
-
const gid =
|
|
5824
|
-
let unixMode =
|
|
5510
|
+
const uid = getNumberOptionValue(zipWriter, options, PROPERTY_NAME_UID);
|
|
5511
|
+
const gid = getNumberOptionValue(zipWriter, options, PROPERTY_NAME_GID);
|
|
5512
|
+
let unixMode = getNumberOptionValue(zipWriter, options, PROPERTY_NAME_UNIX_MODE);
|
|
5825
5513
|
let unixExtraFieldType = getOptionValue(zipWriter, options, OPTION_UNIX_EXTRA_FIELD_TYPE);
|
|
5826
5514
|
let setuid = getOptionValue(zipWriter, options, PROPERTY_NAME_SETUID);
|
|
5827
5515
|
let setgid = getOptionValue(zipWriter, options, PROPERTY_NAME_SETGID);
|
|
5828
5516
|
let sticky = getOptionValue(zipWriter, options, PROPERTY_NAME_STICKY);
|
|
5829
|
-
if (uid !== UNDEFINED_VALUE && (uid < 0 || uid > MAX_32_BITS)) {
|
|
5517
|
+
if (uid !== UNDEFINED_VALUE && (!Number.isInteger(uid) || uid < 0 || uid > MAX_32_BITS)) {
|
|
5830
5518
|
throw new Error(ERR_INVALID_UID);
|
|
5831
5519
|
}
|
|
5832
|
-
if (gid !== UNDEFINED_VALUE && (gid < 0 || gid > MAX_32_BITS)) {
|
|
5520
|
+
if (gid !== UNDEFINED_VALUE && (!Number.isInteger(gid) || gid < 0 || gid > MAX_32_BITS)) {
|
|
5833
5521
|
throw new Error(ERR_INVALID_GID);
|
|
5834
5522
|
}
|
|
5835
|
-
if (unixMode !== UNDEFINED_VALUE && (unixMode < 0 || unixMode > MAX_16_BITS)) {
|
|
5523
|
+
if (unixMode !== UNDEFINED_VALUE && (!Number.isInteger(unixMode) || unixMode < 0 || unixMode > MAX_16_BITS)) {
|
|
5836
5524
|
throw new Error(ERR_INVALID_UNIX_MODE);
|
|
5837
5525
|
}
|
|
5838
5526
|
if (unixExtraFieldType !== UNDEFINED_VALUE && unixExtraFieldType !== INFOZIP_EXTRA_FIELD_TYPE$1 && unixExtraFieldType !== UNIX_EXTRA_FIELD_TYPE) {
|
|
@@ -5944,7 +5632,7 @@
|
|
|
5944
5632
|
|
|
5945
5633
|
function resolveMetadata(zipWriter, name, options) {
|
|
5946
5634
|
const encode = getOptionValue(zipWriter, options, OPTION_ENCODE_TEXT, encodeText);
|
|
5947
|
-
let rawFilename = encode(name);
|
|
5635
|
+
let rawFilename = encode(name, TEXT_TYPE_FILENAME);
|
|
5948
5636
|
if (rawFilename === UNDEFINED_VALUE) {
|
|
5949
5637
|
rawFilename = encodeText(name);
|
|
5950
5638
|
}
|
|
@@ -5952,7 +5640,7 @@
|
|
|
5952
5640
|
throw new Error(ERR_INVALID_ENTRY_NAME);
|
|
5953
5641
|
}
|
|
5954
5642
|
const comment = options[PROPERTY_NAME_COMMENT] || "";
|
|
5955
|
-
let rawComment = encode(comment);
|
|
5643
|
+
let rawComment = encode(comment, TEXT_TYPE_COMMENT);
|
|
5956
5644
|
if (rawComment === UNDEFINED_VALUE) {
|
|
5957
5645
|
rawComment = encodeText(comment);
|
|
5958
5646
|
}
|
|
@@ -5972,8 +5660,11 @@
|
|
|
5972
5660
|
if (!passThrough) {
|
|
5973
5661
|
password = getOptionValue(zipWriter, options, OPTION_PASSWORD);
|
|
5974
5662
|
rawPassword = getOptionValue(zipWriter, options, OPTION_RAW_PASSWORD);
|
|
5663
|
+
if ((password && typeof password != STRING_TYPE) || (rawPassword && !(rawPassword instanceof Uint8Array))) {
|
|
5664
|
+
throw new Error(ERR_INVALID_PASSWORD_TYPE);
|
|
5665
|
+
}
|
|
5975
5666
|
}
|
|
5976
|
-
const encryptionStrength =
|
|
5667
|
+
const encryptionStrength = getNumberOptionValue(zipWriter, options, OPTION_ENCRYPTION_STRENGTH, 3);
|
|
5977
5668
|
const zipCrypto = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIPCRYPTO);
|
|
5978
5669
|
const extendedTimestamp = getOptionValue(zipWriter, options, OPTION_EXTENDED_TIMESTAMP, true);
|
|
5979
5670
|
const ntfsTimestamp = getOptionValue(zipWriter, options, OPTION_NTFS_TIMESTAMP);
|
|
@@ -5991,7 +5682,10 @@
|
|
|
5991
5682
|
compressionMethod !== COMPRESSION_METHOD_STORE && compressionMethod !== COMPRESSION_METHOD_DEFLATE && !registeredCodec) {
|
|
5992
5683
|
throw new Error(ERR_UNSUPPORTED_COMPRESSION);
|
|
5993
5684
|
}
|
|
5994
|
-
let level =
|
|
5685
|
+
let level = getNumberOptionValue(zipWriter, options, OPTION_LEVEL);
|
|
5686
|
+
if (level !== UNDEFINED_VALUE && (!Number.isInteger(level) || level < 0 || level > MAX_LEVEL)) {
|
|
5687
|
+
throw new Error(ERR_INVALID_LEVEL);
|
|
5688
|
+
}
|
|
5995
5689
|
if (zipWriter.options[OPTION_USDZ]) {
|
|
5996
5690
|
if (password !== UNDEFINED_VALUE || rawPassword !== UNDEFINED_VALUE) {
|
|
5997
5691
|
throw new Error(ERR_UNSUPPORTED_ENCRYPTION_USDZ);
|
|
@@ -6012,7 +5706,7 @@
|
|
|
6012
5706
|
useCompressionStream = false;
|
|
6013
5707
|
}
|
|
6014
5708
|
const zip64 = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIP64);
|
|
6015
|
-
if (!zipCrypto && (password !== UNDEFINED_VALUE || rawPassword !== UNDEFINED_VALUE) && !(encryptionStrength >= 1 && encryptionStrength <= 3)) {
|
|
5709
|
+
if (!zipCrypto && (password !== UNDEFINED_VALUE || rawPassword !== UNDEFINED_VALUE) && !(Number.isInteger(encryptionStrength) && encryptionStrength >= 1 && encryptionStrength <= 3)) {
|
|
6016
5710
|
throw new Error(ERR_INVALID_ENCRYPTION_STRENGTH);
|
|
6017
5711
|
}
|
|
6018
5712
|
const rawExtraField = serializeExtraField(options[PROPERTY_NAME_EXTRA_FIELD]);
|
|
@@ -7206,6 +6900,14 @@
|
|
|
7206
6900
|
return result === UNDEFINED_VALUE ? defaultValue : result;
|
|
7207
6901
|
}
|
|
7208
6902
|
|
|
6903
|
+
function getNumberOptionValue(zipWriter, options, name, defaultValue) {
|
|
6904
|
+
return toNumber(getOptionValue(zipWriter, options, name, defaultValue));
|
|
6905
|
+
}
|
|
6906
|
+
|
|
6907
|
+
function toNumber(value) {
|
|
6908
|
+
return typeof value == STRING_TYPE && value.trim() ? Number(value) : value;
|
|
6909
|
+
}
|
|
6910
|
+
|
|
7209
6911
|
function getMaximumCompressedSize(uncompressedSize) {
|
|
7210
6912
|
return uncompressedSize + (5 * (Math.floor(uncompressedSize / 16383) + 1));
|
|
7211
6913
|
}
|
|
@@ -7340,6 +7042,7 @@
|
|
|
7340
7042
|
|
|
7341
7043
|
const ERR_ENTRY_EXISTS = "Entry filename already exists";
|
|
7342
7044
|
const ERR_READABLE_CONSUMED = "Readable stream already consumed";
|
|
7045
|
+
const ERR_ABORT_EXPORT = "zipjs-abort-export";
|
|
7343
7046
|
const INFOZIP_EXTRA_FIELD_TYPE = "infozip";
|
|
7344
7047
|
const INTERPRETED_EXTRA_FIELD_TYPES = new Set([
|
|
7345
7048
|
EXTRAFIELD_TYPE_ZIP64,
|
|
@@ -7448,8 +7151,9 @@
|
|
|
7448
7151
|
const uncompressedSize = zipEntry.data ? zipEntry.data.uncompressedSize : reader.size;
|
|
7449
7152
|
await Promise.all([initStream(reader), initStream(writer, uncompressedSize)]);
|
|
7450
7153
|
const { readable } = reader;
|
|
7154
|
+
const { signal } = options;
|
|
7451
7155
|
zipEntry.uncompressedSize = reader.size;
|
|
7452
|
-
await toCompatibleReadable(readable).pipeTo(toCompatibleWritable(writer.writable));
|
|
7156
|
+
await toCompatibleReadable(readable).pipeTo(toCompatibleWritable(writer.writable), { signal });
|
|
7453
7157
|
return writer.getData ? writer.getData() : writer.writable;
|
|
7454
7158
|
}
|
|
7455
7159
|
}
|
|
@@ -7716,7 +7420,7 @@
|
|
|
7716
7420
|
for (const entry of entries) {
|
|
7717
7421
|
let parent = this;
|
|
7718
7422
|
try {
|
|
7719
|
-
const path = entry.filename.split("/");
|
|
7423
|
+
const path = entry.filename.split("/").filter(pathPart => pathPart != "" && pathPart != ".");
|
|
7720
7424
|
const name = path.pop();
|
|
7721
7425
|
path.forEach(pathPart => {
|
|
7722
7426
|
const previousParent = parent;
|
|
@@ -8091,6 +7795,39 @@
|
|
|
8091
7795
|
}
|
|
8092
7796
|
}
|
|
8093
7797
|
|
|
7798
|
+
function forwardAbort(signal, abortController) {
|
|
7799
|
+
if (!signal) {
|
|
7800
|
+
return () => { };
|
|
7801
|
+
}
|
|
7802
|
+
if (signal.aborted) {
|
|
7803
|
+
abortController.abort(signal.reason);
|
|
7804
|
+
return () => { };
|
|
7805
|
+
}
|
|
7806
|
+
const abort = () => abortController.abort(signal.reason);
|
|
7807
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
7808
|
+
return () => signal.removeEventListener("abort", abort);
|
|
7809
|
+
}
|
|
7810
|
+
|
|
7811
|
+
function isExportAborted(error) {
|
|
7812
|
+
return Boolean(error) && error.message == ERR_ABORT_EXPORT;
|
|
7813
|
+
}
|
|
7814
|
+
|
|
7815
|
+
function aggregateEntryErrors(errors) {
|
|
7816
|
+
const [error] = errors;
|
|
7817
|
+
const otherErrors = errors
|
|
7818
|
+
.slice(1)
|
|
7819
|
+
.flatMap(otherError => [otherError, ...(otherError && otherError.entryErrors || [])])
|
|
7820
|
+
.filter(otherError => otherError !== error);
|
|
7821
|
+
if (otherErrors.length) {
|
|
7822
|
+
try {
|
|
7823
|
+
error.entryErrors = [...(error.entryErrors || []), ...otherErrors];
|
|
7824
|
+
} catch {
|
|
7825
|
+
// ignored
|
|
7826
|
+
}
|
|
7827
|
+
}
|
|
7828
|
+
return error;
|
|
7829
|
+
}
|
|
7830
|
+
|
|
8094
7831
|
function getUserExtraField(extraField) {
|
|
8095
7832
|
if (extraField) {
|
|
8096
7833
|
const userExtraField = new Map();
|
|
@@ -8211,8 +7948,9 @@
|
|
|
8211
7948
|
function addFileSystemHandle(zipEntry, handle, options) {
|
|
8212
7949
|
return addFile(zipEntry, handle, []);
|
|
8213
7950
|
|
|
8214
|
-
async function addFile(parentEntry, handle, addedEntries) {
|
|
7951
|
+
async function addFile(parentEntry, handle, addedEntries, parentName = "") {
|
|
8215
7952
|
if (handle) {
|
|
7953
|
+
const entryName = parentName ? parentName + "/" + handle.name : handle.name;
|
|
8216
7954
|
try {
|
|
8217
7955
|
if (handle.isFile || handle.isDirectory) {
|
|
8218
7956
|
handle = await transformToFileSystemhandle(handle);
|
|
@@ -8234,12 +7972,18 @@
|
|
|
8234
7972
|
const directoryEntry = parentEntry.addDirectory(handle.name);
|
|
8235
7973
|
addedEntries.push(directoryEntry);
|
|
8236
7974
|
for await (const childHandle of handle.values()) {
|
|
8237
|
-
await addFile(directoryEntry, childHandle, addedEntries);
|
|
7975
|
+
await addFile(directoryEntry, childHandle, addedEntries, entryName);
|
|
8238
7976
|
}
|
|
8239
7977
|
}
|
|
8240
7978
|
} catch (error) {
|
|
8241
|
-
|
|
8242
|
-
|
|
7979
|
+
try {
|
|
7980
|
+
if (error.entryName === UNDEFINED_VALUE) {
|
|
7981
|
+
error.entryName = entryName;
|
|
7982
|
+
}
|
|
7983
|
+
} catch {
|
|
7984
|
+
// ignored
|
|
7985
|
+
}
|
|
7986
|
+
throw error;
|
|
8243
7987
|
}
|
|
8244
7988
|
}
|
|
8245
7989
|
return addedEntries;
|
|
@@ -8249,15 +7993,32 @@
|
|
|
8249
7993
|
async function exportFileSystemHandle(zipEntry, directoryHandle, options) {
|
|
8250
7994
|
const totalSize = getTotalSize([zipEntry], "uncompressedSize");
|
|
8251
7995
|
const writtenSizes = new Map();
|
|
8252
|
-
|
|
7996
|
+
const abortController = new AbortController();
|
|
7997
|
+
const { signal } = abortController;
|
|
7998
|
+
const releaseSignal = forwardAbort(options.signal, abortController);
|
|
7999
|
+
const exportedEntryNames = [];
|
|
8000
|
+
try {
|
|
8001
|
+
await exportChildren(zipEntry, directoryHandle);
|
|
8002
|
+
} catch (error) {
|
|
8003
|
+
try {
|
|
8004
|
+
error.exportedEntryNames = exportedEntryNames;
|
|
8005
|
+
} catch {
|
|
8006
|
+
// ignored
|
|
8007
|
+
}
|
|
8008
|
+
throw error;
|
|
8009
|
+
} finally {
|
|
8010
|
+
releaseSignal();
|
|
8011
|
+
}
|
|
8253
8012
|
return directoryHandle;
|
|
8254
8013
|
|
|
8255
8014
|
async function exportChildren(entry, parentHandle) {
|
|
8256
8015
|
if (options.concurrent) {
|
|
8257
8016
|
const results = await Promise.allSettled(entry.children.map(child => exportChild(child, parentHandle)));
|
|
8258
|
-
const
|
|
8259
|
-
if (
|
|
8260
|
-
|
|
8017
|
+
const rejectedResults = results.filter(result => result.status == "rejected");
|
|
8018
|
+
if (rejectedResults.length) {
|
|
8019
|
+
const failedResults = rejectedResults.filter(result => !isExportAborted(result.reason));
|
|
8020
|
+
const reportedResults = failedResults.length ? failedResults : rejectedResults;
|
|
8021
|
+
throw aggregateEntryErrors(reportedResults.map(result => result.reason));
|
|
8261
8022
|
}
|
|
8262
8023
|
} else {
|
|
8263
8024
|
for (const child of entry.children) {
|
|
@@ -8267,6 +8028,12 @@
|
|
|
8267
8028
|
}
|
|
8268
8029
|
|
|
8269
8030
|
async function exportChild(child, parentHandle) {
|
|
8031
|
+
if (signal.aborted) {
|
|
8032
|
+
if (isExportAborted(signal.reason)) {
|
|
8033
|
+
return;
|
|
8034
|
+
}
|
|
8035
|
+
throw signal.reason;
|
|
8036
|
+
}
|
|
8270
8037
|
try {
|
|
8271
8038
|
if (child.directory) {
|
|
8272
8039
|
const childDirectoryHandle = await parentHandle.getDirectoryHandle(child.name, { create: true });
|
|
@@ -8275,6 +8042,7 @@
|
|
|
8275
8042
|
const fileHandle = await parentHandle.getFileHandle(child.name, { create: true });
|
|
8276
8043
|
const writable = await fileHandle.createWritable();
|
|
8277
8044
|
await child.getData({ writable }, Object.assign({}, options, {
|
|
8045
|
+
signal,
|
|
8278
8046
|
onprogress: async progress => {
|
|
8279
8047
|
if (options.onprogress) {
|
|
8280
8048
|
writtenSizes.set(child.id, progress);
|
|
@@ -8286,9 +8054,19 @@
|
|
|
8286
8054
|
}
|
|
8287
8055
|
}
|
|
8288
8056
|
}));
|
|
8057
|
+
exportedEntryNames.push(child.getRelativeName(zipEntry));
|
|
8289
8058
|
}
|
|
8290
8059
|
} catch (error) {
|
|
8291
|
-
|
|
8060
|
+
abortController.abort(new Error(ERR_ABORT_EXPORT));
|
|
8061
|
+
try {
|
|
8062
|
+
if (error.entryName === UNDEFINED_VALUE) {
|
|
8063
|
+
error.entryName = child.getRelativeName(zipEntry);
|
|
8064
|
+
error.entryId = child.id;
|
|
8065
|
+
}
|
|
8066
|
+
} catch {
|
|
8067
|
+
// ignored
|
|
8068
|
+
}
|
|
8069
|
+
throw error;
|
|
8292
8070
|
}
|
|
8293
8071
|
}
|
|
8294
8072
|
}
|