@zip.js/zip.js 2.8.49 → 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 +333 -203
- package/dist/zip-core-external.min.js +1 -1
- package/dist/zip-core.js +339 -203
- package/dist/zip-core.min.js +1 -1
- package/dist/zip-fs-core-external.js +420 -214
- package/dist/zip-fs-core-external.min.js +1 -1
- package/dist/zip-fs-core.js +212 -450
- package/dist/zip-fs-core.min.js +1 -1
- package/dist/zip-fs-external.js +420 -214
- package/dist/zip-fs-external.min.js +1 -1
- package/dist/zip-fs-native.js +426 -214
- package/dist/zip-fs-native.min.js +1 -1
- package/dist/zip-fs.js +426 -214
- package/dist/zip-fs.min.js +1 -1
- package/dist/zip-legacy.js +339 -203
- package/dist/zip-legacy.min.js +1 -1
- package/dist/zip-native.js +339 -203
- package/dist/zip-native.min.js +1 -1
- package/dist/zip.js +339 -203
- package/dist/zip.min.js +1 -1
- package/index-native.cjs +425 -213
- package/index-native.min.js +1 -1
- package/index.cjs +425 -213
- package/index.d.cts +124 -2
- package/index.d.ts +124 -2
- package/index.min.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 -404
- package/lib/core/constants.js +5 -1
- package/lib/core/io.js +2 -1
- package/lib/core/options.js +8 -0
- 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/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,60 +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
|
-
releaseWorkerStreams(workerData);
|
|
3519
|
-
return runWorker$1(workerData, config);
|
|
3520
|
-
}
|
|
3521
|
-
if (error && error.codecImportFailed) {
|
|
3522
|
-
if (workerData.reader) {
|
|
3523
|
-
releaseWorkerStreams(workerData);
|
|
3524
|
-
return runWorker$1(workerData, config);
|
|
3525
|
-
}
|
|
3526
|
-
workerData.onTaskFinished();
|
|
3527
|
-
}
|
|
3528
|
-
throw error;
|
|
3529
|
-
}
|
|
3530
|
-
}
|
|
3531
|
-
}
|
|
3532
|
-
});
|
|
3533
|
-
}
|
|
3534
|
-
return workerData.interface;
|
|
3535
|
-
}
|
|
3536
|
-
|
|
3537
3459
|
async function runWorker$1({ options, readable, writable, onTaskFinished }, config) {
|
|
3538
3460
|
let codecStream;
|
|
3539
3461
|
try {
|
|
@@ -3582,332 +3504,6 @@
|
|
|
3582
3504
|
}
|
|
3583
3505
|
}
|
|
3584
3506
|
|
|
3585
|
-
async function runWebWorker(workerData, config) {
|
|
3586
|
-
let resolveResult, rejectResult;
|
|
3587
|
-
const result = new Promise((resolve, reject) => {
|
|
3588
|
-
resolveResult = resolve;
|
|
3589
|
-
rejectResult = reject;
|
|
3590
|
-
});
|
|
3591
|
-
Object.assign(workerData, {
|
|
3592
|
-
reader: null,
|
|
3593
|
-
writer: null,
|
|
3594
|
-
resolveResult,
|
|
3595
|
-
rejectResult,
|
|
3596
|
-
result
|
|
3597
|
-
});
|
|
3598
|
-
const { readable, options } = workerData;
|
|
3599
|
-
const { writable, closed, abortPipe } = watchClosedStream(workerData.writable);
|
|
3600
|
-
let streamsTransferred;
|
|
3601
|
-
try {
|
|
3602
|
-
streamsTransferred = sendMessage({
|
|
3603
|
-
type: MESSAGE_START,
|
|
3604
|
-
options,
|
|
3605
|
-
config,
|
|
3606
|
-
readable,
|
|
3607
|
-
writable
|
|
3608
|
-
}, workerData);
|
|
3609
|
-
} catch (error) {
|
|
3610
|
-
abortPipe();
|
|
3611
|
-
try {
|
|
3612
|
-
await closed;
|
|
3613
|
-
} catch {
|
|
3614
|
-
// ignored
|
|
3615
|
-
}
|
|
3616
|
-
workerData.onTaskFinished();
|
|
3617
|
-
throw error;
|
|
3618
|
-
}
|
|
3619
|
-
if (!streamsTransferred) {
|
|
3620
|
-
Object.assign(workerData, {
|
|
3621
|
-
reader: readable.getReader(),
|
|
3622
|
-
writer: writable.getWriter()
|
|
3623
|
-
});
|
|
3624
|
-
}
|
|
3625
|
-
const { workerStartupTimeout } = config;
|
|
3626
|
-
if (!workerData.workerAlive && Number.isFinite(workerStartupTimeout) && workerStartupTimeout >= 0) {
|
|
3627
|
-
workerData.startupTimeout = setTimeout(() => onStartupTimeout(workerData), workerStartupTimeout);
|
|
3628
|
-
}
|
|
3629
|
-
try {
|
|
3630
|
-
const resultValue = await result;
|
|
3631
|
-
await closeWritable();
|
|
3632
|
-
await closed;
|
|
3633
|
-
return resultValue;
|
|
3634
|
-
} catch (error) {
|
|
3635
|
-
await closeWritable();
|
|
3636
|
-
abortPipe();
|
|
3637
|
-
try {
|
|
3638
|
-
await closed;
|
|
3639
|
-
} catch {
|
|
3640
|
-
// ignored
|
|
3641
|
-
}
|
|
3642
|
-
throw error;
|
|
3643
|
-
}
|
|
3644
|
-
|
|
3645
|
-
async function closeWritable() {
|
|
3646
|
-
if (!streamsTransferred && !writable.locked) {
|
|
3647
|
-
try {
|
|
3648
|
-
await writable.getWriter().close();
|
|
3649
|
-
} catch {
|
|
3650
|
-
// ignored
|
|
3651
|
-
}
|
|
3652
|
-
}
|
|
3653
|
-
}
|
|
3654
|
-
}
|
|
3655
|
-
|
|
3656
|
-
function watchClosedStream(writableSource) {
|
|
3657
|
-
const abortController = new AbortController();
|
|
3658
|
-
const { writable, readable } = new TransformStream();
|
|
3659
|
-
const closed = readable.pipeTo(writableSource, { preventClose: true, preventAbort: true, signal: abortController.signal });
|
|
3660
|
-
closed.catch(() => { });
|
|
3661
|
-
return { writable, closed, abortPipe: () => abortController.abort() };
|
|
3662
|
-
}
|
|
3663
|
-
|
|
3664
|
-
function releaseWorkerStreams(workerData) {
|
|
3665
|
-
const { reader } = workerData;
|
|
3666
|
-
if (reader) {
|
|
3667
|
-
reader.releaseLock();
|
|
3668
|
-
}
|
|
3669
|
-
workerData.reader = null;
|
|
3670
|
-
workerData.writer = null;
|
|
3671
|
-
}
|
|
3672
|
-
|
|
3673
|
-
function terminateWorker$1(workerData) {
|
|
3674
|
-
const { worker } = workerData;
|
|
3675
|
-
if (worker) {
|
|
3676
|
-
try {
|
|
3677
|
-
worker.terminate();
|
|
3678
|
-
} catch {
|
|
3679
|
-
// ignored
|
|
3680
|
-
}
|
|
3681
|
-
}
|
|
3682
|
-
workerData.interface = null;
|
|
3683
|
-
}
|
|
3684
|
-
|
|
3685
|
-
function getWebWorker(url, baseURI, workerData, isModuleType, useBlobURI = true) {
|
|
3686
|
-
const { createWorker } = workerData;
|
|
3687
|
-
let worker, resolvedURI, resolvedOptions;
|
|
3688
|
-
if (createWorker) {
|
|
3689
|
-
worker = createWorker();
|
|
3690
|
-
} else if (webWorkerURI === UNDEFINED_VALUE || webWorkerSource !== url) {
|
|
3691
|
-
// deno-lint-ignore valid-typeof
|
|
3692
|
-
const isFunctionURI = typeof url == FUNCTION_TYPE;
|
|
3693
|
-
if (isFunctionURI) {
|
|
3694
|
-
resolvedURI = url(useBlobURI);
|
|
3695
|
-
} else {
|
|
3696
|
-
resolvedURI = url;
|
|
3697
|
-
}
|
|
3698
|
-
const isDataURI = resolvedURI.startsWith("data:");
|
|
3699
|
-
const isBlobURI = resolvedURI.startsWith("blob:");
|
|
3700
|
-
if (isDataURI || isBlobURI) {
|
|
3701
|
-
if (isModuleType === UNDEFINED_VALUE) {
|
|
3702
|
-
isModuleType = false;
|
|
3703
|
-
}
|
|
3704
|
-
if (isModuleType) {
|
|
3705
|
-
resolvedOptions = MODULE_WORKER_OPTIONS;
|
|
3706
|
-
}
|
|
3707
|
-
try {
|
|
3708
|
-
worker = new Worker(resolvedURI, resolvedOptions);
|
|
3709
|
-
} catch (error) {
|
|
3710
|
-
if (isBlobURI) {
|
|
3711
|
-
try {
|
|
3712
|
-
URL.revokeObjectURL(resolvedURI);
|
|
3713
|
-
} catch {
|
|
3714
|
-
// ignored
|
|
3715
|
-
}
|
|
3716
|
-
}
|
|
3717
|
-
if (isFunctionURI && isBlobURI) {
|
|
3718
|
-
return getWebWorker(url, baseURI, workerData, isModuleType, false);
|
|
3719
|
-
} else if (!isModuleType) {
|
|
3720
|
-
return getWebWorker(url, baseURI, workerData, true, false);
|
|
3721
|
-
} else {
|
|
3722
|
-
throw error;
|
|
3723
|
-
}
|
|
3724
|
-
}
|
|
3725
|
-
} else {
|
|
3726
|
-
if (isModuleType === UNDEFINED_VALUE) {
|
|
3727
|
-
isModuleType = true;
|
|
3728
|
-
}
|
|
3729
|
-
if (isModuleType) {
|
|
3730
|
-
resolvedOptions = MODULE_WORKER_OPTIONS;
|
|
3731
|
-
}
|
|
3732
|
-
try {
|
|
3733
|
-
resolvedURI = new URL(resolvedURI, baseURI);
|
|
3734
|
-
} catch {
|
|
3735
|
-
// ignored
|
|
3736
|
-
}
|
|
3737
|
-
try {
|
|
3738
|
-
worker = new Worker(resolvedURI, resolvedOptions);
|
|
3739
|
-
} catch (error) {
|
|
3740
|
-
if (isModuleType) {
|
|
3741
|
-
return getWebWorker(url, baseURI, workerData, false, useBlobURI);
|
|
3742
|
-
} else {
|
|
3743
|
-
throw error;
|
|
3744
|
-
}
|
|
3745
|
-
}
|
|
3746
|
-
}
|
|
3747
|
-
webWorkerSource = url;
|
|
3748
|
-
webWorkerURI = resolvedURI;
|
|
3749
|
-
webWorkerOptions = resolvedOptions;
|
|
3750
|
-
} else {
|
|
3751
|
-
worker = new Worker(webWorkerURI, webWorkerOptions);
|
|
3752
|
-
}
|
|
3753
|
-
worker.addEventListener(MESSAGE_EVENT_TYPE, event => {
|
|
3754
|
-
workerData.workerAlive = true;
|
|
3755
|
-
clearStartupTimeout(workerData);
|
|
3756
|
-
onMessage(event, workerData);
|
|
3757
|
-
});
|
|
3758
|
-
worker.addEventListener(ERROR_EVENT_TYPE, event => onWorkerError(event, workerData));
|
|
3759
|
-
worker.addEventListener(MESSAGE_ERROR_EVENT_TYPE, event => onWorkerError(event, workerData));
|
|
3760
|
-
return worker;
|
|
3761
|
-
}
|
|
3762
|
-
|
|
3763
|
-
function onStartupTimeout(workerData) {
|
|
3764
|
-
workerData.startupTimeout = null;
|
|
3765
|
-
if (workerData.workerAlive) {
|
|
3766
|
-
return;
|
|
3767
|
-
}
|
|
3768
|
-
const { rejectResult, writer } = workerData;
|
|
3769
|
-
terminateWorker$1(workerData);
|
|
3770
|
-
workerData.worker = null;
|
|
3771
|
-
if (rejectResult) {
|
|
3772
|
-
const error = new Error(ERR_WORKER_STARTUP_TIMEOUT);
|
|
3773
|
-
error.workerStartupFailed = true;
|
|
3774
|
-
rejectResult(error);
|
|
3775
|
-
if (writer) {
|
|
3776
|
-
writer.releaseLock();
|
|
3777
|
-
}
|
|
3778
|
-
}
|
|
3779
|
-
}
|
|
3780
|
-
|
|
3781
|
-
function clearStartupTimeout(workerData) {
|
|
3782
|
-
const { startupTimeout } = workerData;
|
|
3783
|
-
if (startupTimeout) {
|
|
3784
|
-
clearTimeout(startupTimeout);
|
|
3785
|
-
workerData.startupTimeout = null;
|
|
3786
|
-
}
|
|
3787
|
-
}
|
|
3788
|
-
|
|
3789
|
-
function onWorkerError(event, workerData) {
|
|
3790
|
-
if (event.preventDefault) {
|
|
3791
|
-
event.preventDefault();
|
|
3792
|
-
}
|
|
3793
|
-
clearStartupTimeout(workerData);
|
|
3794
|
-
const { workerAlive, rejectResult, writer, onTaskFinished } = workerData;
|
|
3795
|
-
terminateWorker$1(workerData);
|
|
3796
|
-
if (!workerAlive) {
|
|
3797
|
-
workerData.worker = null;
|
|
3798
|
-
}
|
|
3799
|
-
if (rejectResult) {
|
|
3800
|
-
let error = event.error || new Error(event.message || ERROR_EVENT_TYPE);
|
|
3801
|
-
if (!workerAlive) {
|
|
3802
|
-
error = Object.assign(new Error(error.message || ERROR_EVENT_TYPE), { workerStartupFailed: true });
|
|
3803
|
-
}
|
|
3804
|
-
rejectResult(error);
|
|
3805
|
-
if (writer) {
|
|
3806
|
-
writer.releaseLock();
|
|
3807
|
-
}
|
|
3808
|
-
if (workerAlive) {
|
|
3809
|
-
onTaskFinished();
|
|
3810
|
-
}
|
|
3811
|
-
}
|
|
3812
|
-
}
|
|
3813
|
-
|
|
3814
|
-
function sendMessage(message, { worker, writer, transferStreams, workerAlive }) {
|
|
3815
|
-
try {
|
|
3816
|
-
const { value, readable, writable } = message;
|
|
3817
|
-
const transferables = [];
|
|
3818
|
-
if (value) {
|
|
3819
|
-
message.value = toExactUint8Array(value);
|
|
3820
|
-
transferables.push(message.value.buffer);
|
|
3821
|
-
}
|
|
3822
|
-
if (transferStreams && transferStreamsSupported && workerAlive) {
|
|
3823
|
-
if (readable) {
|
|
3824
|
-
transferables.push(readable);
|
|
3825
|
-
}
|
|
3826
|
-
if (writable) {
|
|
3827
|
-
transferables.push(writable);
|
|
3828
|
-
}
|
|
3829
|
-
} else {
|
|
3830
|
-
message.readable = message.writable = null;
|
|
3831
|
-
}
|
|
3832
|
-
if (transferables.length) {
|
|
3833
|
-
try {
|
|
3834
|
-
worker.postMessage(message, transferables);
|
|
3835
|
-
return true;
|
|
3836
|
-
} catch {
|
|
3837
|
-
transferStreamsSupported = false;
|
|
3838
|
-
message.readable = message.writable = null;
|
|
3839
|
-
worker.postMessage(message);
|
|
3840
|
-
}
|
|
3841
|
-
} else {
|
|
3842
|
-
worker.postMessage(message);
|
|
3843
|
-
}
|
|
3844
|
-
} catch (error) {
|
|
3845
|
-
if (writer) {
|
|
3846
|
-
writer.releaseLock();
|
|
3847
|
-
}
|
|
3848
|
-
throw error;
|
|
3849
|
-
}
|
|
3850
|
-
}
|
|
3851
|
-
|
|
3852
|
-
async function onMessage({ data }, workerData) {
|
|
3853
|
-
const { type, value, messageId, result, error } = data;
|
|
3854
|
-
const { reader, writer, resolveResult, rejectResult, onTaskFinished, generation } = workerData;
|
|
3855
|
-
const stale = () => workerData.generation != generation;
|
|
3856
|
-
try {
|
|
3857
|
-
if (error) {
|
|
3858
|
-
const { message, stack, code, name, outputSize, cause, codecImportFailed } = error;
|
|
3859
|
-
const responseError = new Error(message);
|
|
3860
|
-
Object.assign(responseError, { stack, code, name, outputSize });
|
|
3861
|
-
if (cause) {
|
|
3862
|
-
responseError.cause = Object.assign(new Error(cause.message), { name: cause.name });
|
|
3863
|
-
}
|
|
3864
|
-
if (codecImportFailed) {
|
|
3865
|
-
responseError.codecImportFailed = true;
|
|
3866
|
-
}
|
|
3867
|
-
close(responseError);
|
|
3868
|
-
} else {
|
|
3869
|
-
if (type == MESSAGE_PULL) {
|
|
3870
|
-
const { value, done } = await reader.read();
|
|
3871
|
-
if (!stale()) {
|
|
3872
|
-
sendMessage({ type: MESSAGE_DATA, value, done, messageId }, workerData);
|
|
3873
|
-
}
|
|
3874
|
-
}
|
|
3875
|
-
if (type == MESSAGE_DATA) {
|
|
3876
|
-
await writer.ready;
|
|
3877
|
-
await writer.write(new Uint8Array(value));
|
|
3878
|
-
if (!stale()) {
|
|
3879
|
-
sendMessage({ type: MESSAGE_ACK_DATA, messageId }, workerData);
|
|
3880
|
-
}
|
|
3881
|
-
}
|
|
3882
|
-
if (type == MESSAGE_CLOSE) {
|
|
3883
|
-
close(null, result);
|
|
3884
|
-
}
|
|
3885
|
-
}
|
|
3886
|
-
} catch (error) {
|
|
3887
|
-
if (!stale()) {
|
|
3888
|
-
terminateWorker$1(workerData);
|
|
3889
|
-
close(error);
|
|
3890
|
-
}
|
|
3891
|
-
}
|
|
3892
|
-
|
|
3893
|
-
function close(error, result) {
|
|
3894
|
-
if (stale()) {
|
|
3895
|
-
return;
|
|
3896
|
-
}
|
|
3897
|
-
if (error) {
|
|
3898
|
-
rejectResult(error);
|
|
3899
|
-
} else {
|
|
3900
|
-
resolveResult(result);
|
|
3901
|
-
}
|
|
3902
|
-
if (writer) {
|
|
3903
|
-
writer.releaseLock();
|
|
3904
|
-
}
|
|
3905
|
-
if (!(error && error.codecImportFailed)) {
|
|
3906
|
-
onTaskFinished();
|
|
3907
|
-
}
|
|
3908
|
-
}
|
|
3909
|
-
}
|
|
3910
|
-
|
|
3911
3507
|
/*
|
|
3912
3508
|
Copyright (c) 2025 Gildas Lormeau. All rights reserved.
|
|
3913
3509
|
|
|
@@ -4350,9 +3946,13 @@
|
|
|
4350
3946
|
const OPTION_UNIX_EXTRA_FIELD_TYPE = "unixExtraFieldType";
|
|
4351
3947
|
const OPTION_LOCAL_EXTRA_FIELD = "localExtraField";
|
|
4352
3948
|
const OPTION_STRICTNESS = "strictness";
|
|
3949
|
+
const OPTION_FILENAME_VALIDATION = "filenameValidation";
|
|
3950
|
+
const OPTION_NORMALIZE_FILENAME = "normalizeFilename";
|
|
4353
3951
|
const OPTION_MAX_APPENDED_DATA_SIZE = "maxAppendedDataSize";
|
|
4354
3952
|
const OPTION_DECRYPT_CENTRAL_DIRECTORY = "decryptCentralDirectory";
|
|
4355
3953
|
const OPTION_SIGN_CENTRAL_DIRECTORY = "signCentralDirectory";
|
|
3954
|
+
const TEXT_TYPE_FILENAME = "filename";
|
|
3955
|
+
const TEXT_TYPE_COMMENT = "comment";
|
|
4356
3956
|
const STRICTNESS_STRICT = "strict";
|
|
4357
3957
|
const STRICTNESS_BALANCED = "balanced";
|
|
4358
3958
|
const STRICTNESS_TOLERANT = "tolerant";
|
|
@@ -4399,6 +3999,11 @@
|
|
|
4399
3999
|
const ERR_OVERLAPPING_ENTRY = "Overlapping entry found";
|
|
4400
4000
|
const ERR_AMBIGUOUS_ARCHIVE = "Ambiguous archive";
|
|
4401
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]:/;
|
|
4402
4007
|
const CHARSET_UTF8 = "utf-8";
|
|
4403
4008
|
const PROPERTY_NAME_UTF8_SUFFIX = "UTF8";
|
|
4404
4009
|
const CHARSET_CP437 = "cp437";
|
|
@@ -4420,6 +4025,10 @@
|
|
|
4420
4025
|
bytes: 8
|
|
4421
4026
|
}
|
|
4422
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;
|
|
4423
4032
|
|
|
4424
4033
|
class ZipReader {
|
|
4425
4034
|
|
|
@@ -4448,6 +4057,8 @@
|
|
|
4448
4057
|
const checkAmbiguity = strictness == STRICTNESS_STRICT;
|
|
4449
4058
|
const rejectAmbiguousEndOfDirectory = strictness != STRICTNESS_TOLERANT;
|
|
4450
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);
|
|
4451
4062
|
const { endOfDirectoryInfo, endOfDirectoryReachingEndCount } = await findEndOfCentralDirectory(reader, rejectAmbiguousEndOfDirectory, maxAppendedDataSize);
|
|
4452
4063
|
if (!endOfDirectoryInfo) {
|
|
4453
4064
|
const signatureArray = await readUint8Array(reader, 0, 4);
|
|
@@ -4641,11 +4252,22 @@
|
|
|
4641
4252
|
const decode = getOptionValue$1(zipReader, options, OPTION_DECODE_TEXT) || decodeText;
|
|
4642
4253
|
const rawFilenameEncoding = filenameUTF8 ? CHARSET_UTF8 : filenameEncoding || CHARSET_CP437;
|
|
4643
4254
|
const rawCommentEncoding = commentUTF8 ? CHARSET_UTF8 : commentEncoding || CHARSET_CP437;
|
|
4644
|
-
let filename = decode(rawFilename, rawFilenameEncoding);
|
|
4255
|
+
let filename = decode(rawFilename, rawFilenameEncoding, TEXT_TYPE_FILENAME);
|
|
4645
4256
|
if (filename === UNDEFINED_VALUE) {
|
|
4646
4257
|
filename = decodeText(rawFilename, rawFilenameEncoding);
|
|
4647
4258
|
}
|
|
4648
|
-
|
|
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);
|
|
4649
4271
|
if (comment === UNDEFINED_VALUE) {
|
|
4650
4272
|
comment = decodeText(rawComment, rawCommentEncoding);
|
|
4651
4273
|
}
|
|
@@ -4706,10 +4328,10 @@
|
|
|
4706
4328
|
entry.getData = (writer, options) => fileEntry.getData(writer, entry, zipReader.readRanges, options);
|
|
4707
4329
|
entry.arrayBuffer = async options => {
|
|
4708
4330
|
const writer = new TransformStream();
|
|
4709
|
-
const
|
|
4710
|
-
|
|
4711
|
-
|
|
4712
|
-
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;
|
|
4713
4335
|
};
|
|
4714
4336
|
offset = endOffset;
|
|
4715
4337
|
const { onprogress } = options;
|
|
@@ -4920,7 +4542,7 @@
|
|
|
4920
4542
|
readRanges
|
|
4921
4543
|
});
|
|
4922
4544
|
}
|
|
4923
|
-
let writable;
|
|
4545
|
+
let writable, abortError;
|
|
4924
4546
|
try {
|
|
4925
4547
|
if (!checkOverlappingEntryOnly) {
|
|
4926
4548
|
if (checkPasswordOnly) {
|
|
@@ -4940,12 +4562,22 @@
|
|
|
4940
4562
|
writer.size += error.outputSize;
|
|
4941
4563
|
}
|
|
4942
4564
|
if (!checkPasswordOnly || error.message != ERR_ABORT_CHECK_PASSWORD) {
|
|
4565
|
+
abortError = error;
|
|
4943
4566
|
throw error;
|
|
4944
4567
|
}
|
|
4945
4568
|
} finally {
|
|
4946
4569
|
const preventClose = getOptionValue$1(zipEntry, options, OPTION_PREVENT_CLOSE);
|
|
4947
4570
|
if (!preventClose && writable && !writable.locked) {
|
|
4948
|
-
|
|
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
|
+
}
|
|
4949
4581
|
}
|
|
4950
4582
|
}
|
|
4951
4583
|
return checkPasswordOnly || checkOverlappingEntryOnly ? UNDEFINED_VALUE : writer.getData ? writer.getData() : writable;
|
|
@@ -5325,16 +4957,51 @@
|
|
|
5325
4957
|
return reader.getDiskOffset ? reader.getDiskOffset(diskNumber) : 0;
|
|
5326
4958
|
}
|
|
5327
4959
|
|
|
4960
|
+
function isStrictnessValue(value) {
|
|
4961
|
+
return value === STRICTNESS_STRICT || value === STRICTNESS_BALANCED || value === STRICTNESS_TOLERANT;
|
|
4962
|
+
}
|
|
4963
|
+
|
|
5328
4964
|
function getStrictness(strictness, checkAmbiguity) {
|
|
5329
4965
|
if (strictness === UNDEFINED_VALUE) {
|
|
5330
4966
|
return checkAmbiguity ? STRICTNESS_STRICT : STRICTNESS_BALANCED;
|
|
5331
4967
|
}
|
|
4968
|
+
if (!isStrictnessValue(strictness)) {
|
|
4969
|
+
throw new Error(ERR_INVALID_STRICTNESS);
|
|
4970
|
+
}
|
|
5332
4971
|
return strictness;
|
|
5333
4972
|
}
|
|
5334
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
|
+
|
|
5335
4998
|
function getMaxAppendedDataSize(maxAppendedDataSize, strictness) {
|
|
5336
4999
|
if (maxAppendedDataSize !== UNDEFINED_VALUE) {
|
|
5337
|
-
|
|
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;
|
|
5338
5005
|
}
|
|
5339
5006
|
if (strictness == STRICTNESS_STRICT) {
|
|
5340
5007
|
return 0;
|
|
@@ -5345,12 +5012,6 @@
|
|
|
5345
5012
|
return MAX_16_BITS;
|
|
5346
5013
|
}
|
|
5347
5014
|
|
|
5348
|
-
const MAX_END_OF_CENTRAL_DIR_PROBES = 64;
|
|
5349
|
-
|
|
5350
|
-
const CENTRAL_DIRECTORY_UNREACHABLE = 0;
|
|
5351
|
-
const CENTRAL_DIRECTORY_PLAUSIBLE = 1;
|
|
5352
|
-
const CENTRAL_DIRECTORY_REACHABLE = 2;
|
|
5353
|
-
|
|
5354
5015
|
async function findEndOfCentralDirectory(reader, rejectAmbiguous, maxAppendedDataSize) {
|
|
5355
5016
|
const { size } = reader;
|
|
5356
5017
|
const anchoredLength = Math.min(size, END_OF_CENTRAL_DIR_LENGTH + MAX_16_BITS);
|
|
@@ -5486,6 +5147,10 @@
|
|
|
5486
5147
|
return options[name] === UNDEFINED_VALUE ? zipReader.options[name] : options[name];
|
|
5487
5148
|
}
|
|
5488
5149
|
|
|
5150
|
+
function toNumber$1(value) {
|
|
5151
|
+
return typeof value == STRING_TYPE && value.trim() ? Number(value) : value;
|
|
5152
|
+
}
|
|
5153
|
+
|
|
5489
5154
|
function getDate(timeRaw) {
|
|
5490
5155
|
const date = (timeRaw & 0xffff0000) >> 16, time = timeRaw & MAX_16_BITS;
|
|
5491
5156
|
return new Date(1980 + ((date & 0xFE00) >> 9), ((date & 0x01E0) >> 5) - 1, date & 0x001F, (time & 0xF800) >> 11, (time & 0x07E0) >> 5, (time & 0x001F) * 2, 0);
|
|
@@ -5524,15 +5189,18 @@
|
|
|
5524
5189
|
ERR_INVALID_AUTHENTICATION_CODE: ERR_INVALID_AUTHENTICATION_CODE,
|
|
5525
5190
|
ERR_INVALID_COMPRESSED_DATA: ERR_INVALID_COMPRESSED_DATA,
|
|
5526
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,
|
|
5527
5194
|
ERR_INVALID_PASSWORD: ERR_INVALID_PASSWORD,
|
|
5528
5195
|
ERR_INVALID_SIGNATURE: ERR_INVALID_SIGNATURE,
|
|
5196
|
+
ERR_INVALID_STRICTNESS: ERR_INVALID_STRICTNESS,
|
|
5529
5197
|
ERR_INVALID_UNCOMPRESSED_SIZE: ERR_INVALID_UNCOMPRESSED_SIZE,
|
|
5530
5198
|
ERR_LOCAL_FILE_HEADER_NOT_FOUND: ERR_LOCAL_FILE_HEADER_NOT_FOUND,
|
|
5531
5199
|
ERR_OVERLAPPING_ENTRY: ERR_OVERLAPPING_ENTRY,
|
|
5532
5200
|
ERR_SPLIT_ZIP_FILE: ERR_SPLIT_ZIP_FILE,
|
|
5201
|
+
ERR_UNSAFE_FILENAME: ERR_UNSAFE_FILENAME,
|
|
5533
5202
|
ERR_UNSUPPORTED_COMPRESSION: ERR_UNSUPPORTED_COMPRESSION$1,
|
|
5534
5203
|
ERR_UNSUPPORTED_ENCRYPTION: ERR_UNSUPPORTED_ENCRYPTION,
|
|
5535
|
-
ERR_WORKER_STARTUP_TIMEOUT: ERR_WORKER_STARTUP_TIMEOUT,
|
|
5536
5204
|
ZipReader: ZipReader
|
|
5537
5205
|
});
|
|
5538
5206
|
|
|
@@ -5590,6 +5258,8 @@
|
|
|
5590
5258
|
const ERR_INVALID_UNIX_ID_SIZE = "uid/gid must be 0..65535 for unixExtraFieldType 'unix' (use 'infozip' for larger ids)";
|
|
5591
5259
|
const ERR_INVALID_MSDOS_ATTRIBUTES = "Invalid msdosAttributesRaw (must be integer 0..255)";
|
|
5592
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)";
|
|
5593
5263
|
const ERR_INVALID_SIGNATURE_DATA = "Signature data exceeds 64KB";
|
|
5594
5264
|
|
|
5595
5265
|
const EXTRAFIELD_DATA_AES = new Uint8Array([0x07, 0x00, 0x02, 0x00, 0x41, 0x45, 0x03, 0x00, 0x00]);
|
|
@@ -5597,6 +5267,7 @@
|
|
|
5597
5267
|
const VENDOR_VERSION_AE_1 = 1;
|
|
5598
5268
|
const INFOZIP_EXTRA_FIELD_TYPE$1 = "infozip";
|
|
5599
5269
|
const UNIX_EXTRA_FIELD_TYPE = "unix";
|
|
5270
|
+
const MAX_LEVEL = 9;
|
|
5600
5271
|
|
|
5601
5272
|
let workers = 0;
|
|
5602
5273
|
const pendingEntries = [];
|
|
@@ -5759,7 +5430,8 @@
|
|
|
5759
5430
|
|
|
5760
5431
|
remove(entry) {
|
|
5761
5432
|
const { filenames, files } = this;
|
|
5762
|
-
|
|
5433
|
+
// deno-lint-ignore valid-typeof
|
|
5434
|
+
if (typeof entry == STRING_TYPE) {
|
|
5763
5435
|
entry = files.get(entry);
|
|
5764
5436
|
}
|
|
5765
5437
|
if (entry && entry.filename !== UNDEFINED_VALUE) {
|
|
@@ -5835,20 +5507,20 @@
|
|
|
5835
5507
|
let msDosCompatible = getOptionValue(zipWriter, options, PROPERTY_NAME_MS_DOS_COMPATIBLE);
|
|
5836
5508
|
let versionMadeBy = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION_MADE_BY, msDosCompatible ? 20 : 768);
|
|
5837
5509
|
const executable = getOptionValue(zipWriter, options, PROPERTY_NAME_EXECUTABLE);
|
|
5838
|
-
const uid =
|
|
5839
|
-
const gid =
|
|
5840
|
-
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);
|
|
5841
5513
|
let unixExtraFieldType = getOptionValue(zipWriter, options, OPTION_UNIX_EXTRA_FIELD_TYPE);
|
|
5842
5514
|
let setuid = getOptionValue(zipWriter, options, PROPERTY_NAME_SETUID);
|
|
5843
5515
|
let setgid = getOptionValue(zipWriter, options, PROPERTY_NAME_SETGID);
|
|
5844
5516
|
let sticky = getOptionValue(zipWriter, options, PROPERTY_NAME_STICKY);
|
|
5845
|
-
if (uid !== UNDEFINED_VALUE && (uid < 0 || uid > MAX_32_BITS)) {
|
|
5517
|
+
if (uid !== UNDEFINED_VALUE && (!Number.isInteger(uid) || uid < 0 || uid > MAX_32_BITS)) {
|
|
5846
5518
|
throw new Error(ERR_INVALID_UID);
|
|
5847
5519
|
}
|
|
5848
|
-
if (gid !== UNDEFINED_VALUE && (gid < 0 || gid > MAX_32_BITS)) {
|
|
5520
|
+
if (gid !== UNDEFINED_VALUE && (!Number.isInteger(gid) || gid < 0 || gid > MAX_32_BITS)) {
|
|
5849
5521
|
throw new Error(ERR_INVALID_GID);
|
|
5850
5522
|
}
|
|
5851
|
-
if (unixMode !== UNDEFINED_VALUE && (unixMode < 0 || unixMode > MAX_16_BITS)) {
|
|
5523
|
+
if (unixMode !== UNDEFINED_VALUE && (!Number.isInteger(unixMode) || unixMode < 0 || unixMode > MAX_16_BITS)) {
|
|
5852
5524
|
throw new Error(ERR_INVALID_UNIX_MODE);
|
|
5853
5525
|
}
|
|
5854
5526
|
if (unixExtraFieldType !== UNDEFINED_VALUE && unixExtraFieldType !== INFOZIP_EXTRA_FIELD_TYPE$1 && unixExtraFieldType !== UNIX_EXTRA_FIELD_TYPE) {
|
|
@@ -5960,7 +5632,7 @@
|
|
|
5960
5632
|
|
|
5961
5633
|
function resolveMetadata(zipWriter, name, options) {
|
|
5962
5634
|
const encode = getOptionValue(zipWriter, options, OPTION_ENCODE_TEXT, encodeText);
|
|
5963
|
-
let rawFilename = encode(name);
|
|
5635
|
+
let rawFilename = encode(name, TEXT_TYPE_FILENAME);
|
|
5964
5636
|
if (rawFilename === UNDEFINED_VALUE) {
|
|
5965
5637
|
rawFilename = encodeText(name);
|
|
5966
5638
|
}
|
|
@@ -5968,7 +5640,7 @@
|
|
|
5968
5640
|
throw new Error(ERR_INVALID_ENTRY_NAME);
|
|
5969
5641
|
}
|
|
5970
5642
|
const comment = options[PROPERTY_NAME_COMMENT] || "";
|
|
5971
|
-
let rawComment = encode(comment);
|
|
5643
|
+
let rawComment = encode(comment, TEXT_TYPE_COMMENT);
|
|
5972
5644
|
if (rawComment === UNDEFINED_VALUE) {
|
|
5973
5645
|
rawComment = encodeText(comment);
|
|
5974
5646
|
}
|
|
@@ -5988,8 +5660,11 @@
|
|
|
5988
5660
|
if (!passThrough) {
|
|
5989
5661
|
password = getOptionValue(zipWriter, options, OPTION_PASSWORD);
|
|
5990
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
|
+
}
|
|
5991
5666
|
}
|
|
5992
|
-
const encryptionStrength =
|
|
5667
|
+
const encryptionStrength = getNumberOptionValue(zipWriter, options, OPTION_ENCRYPTION_STRENGTH, 3);
|
|
5993
5668
|
const zipCrypto = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIPCRYPTO);
|
|
5994
5669
|
const extendedTimestamp = getOptionValue(zipWriter, options, OPTION_EXTENDED_TIMESTAMP, true);
|
|
5995
5670
|
const ntfsTimestamp = getOptionValue(zipWriter, options, OPTION_NTFS_TIMESTAMP);
|
|
@@ -6007,7 +5682,10 @@
|
|
|
6007
5682
|
compressionMethod !== COMPRESSION_METHOD_STORE && compressionMethod !== COMPRESSION_METHOD_DEFLATE && !registeredCodec) {
|
|
6008
5683
|
throw new Error(ERR_UNSUPPORTED_COMPRESSION);
|
|
6009
5684
|
}
|
|
6010
|
-
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
|
+
}
|
|
6011
5689
|
if (zipWriter.options[OPTION_USDZ]) {
|
|
6012
5690
|
if (password !== UNDEFINED_VALUE || rawPassword !== UNDEFINED_VALUE) {
|
|
6013
5691
|
throw new Error(ERR_UNSUPPORTED_ENCRYPTION_USDZ);
|
|
@@ -6028,7 +5706,7 @@
|
|
|
6028
5706
|
useCompressionStream = false;
|
|
6029
5707
|
}
|
|
6030
5708
|
const zip64 = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIP64);
|
|
6031
|
-
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)) {
|
|
6032
5710
|
throw new Error(ERR_INVALID_ENCRYPTION_STRENGTH);
|
|
6033
5711
|
}
|
|
6034
5712
|
const rawExtraField = serializeExtraField(options[PROPERTY_NAME_EXTRA_FIELD]);
|
|
@@ -7222,6 +6900,14 @@
|
|
|
7222
6900
|
return result === UNDEFINED_VALUE ? defaultValue : result;
|
|
7223
6901
|
}
|
|
7224
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
|
+
|
|
7225
6911
|
function getMaximumCompressedSize(uncompressedSize) {
|
|
7226
6912
|
return uncompressedSize + (5 * (Math.floor(uncompressedSize / 16383) + 1));
|
|
7227
6913
|
}
|
|
@@ -7356,6 +7042,7 @@
|
|
|
7356
7042
|
|
|
7357
7043
|
const ERR_ENTRY_EXISTS = "Entry filename already exists";
|
|
7358
7044
|
const ERR_READABLE_CONSUMED = "Readable stream already consumed";
|
|
7045
|
+
const ERR_ABORT_EXPORT = "zipjs-abort-export";
|
|
7359
7046
|
const INFOZIP_EXTRA_FIELD_TYPE = "infozip";
|
|
7360
7047
|
const INTERPRETED_EXTRA_FIELD_TYPES = new Set([
|
|
7361
7048
|
EXTRAFIELD_TYPE_ZIP64,
|
|
@@ -7464,8 +7151,9 @@
|
|
|
7464
7151
|
const uncompressedSize = zipEntry.data ? zipEntry.data.uncompressedSize : reader.size;
|
|
7465
7152
|
await Promise.all([initStream(reader), initStream(writer, uncompressedSize)]);
|
|
7466
7153
|
const { readable } = reader;
|
|
7154
|
+
const { signal } = options;
|
|
7467
7155
|
zipEntry.uncompressedSize = reader.size;
|
|
7468
|
-
await toCompatibleReadable(readable).pipeTo(toCompatibleWritable(writer.writable));
|
|
7156
|
+
await toCompatibleReadable(readable).pipeTo(toCompatibleWritable(writer.writable), { signal });
|
|
7469
7157
|
return writer.getData ? writer.getData() : writer.writable;
|
|
7470
7158
|
}
|
|
7471
7159
|
}
|
|
@@ -7732,7 +7420,7 @@
|
|
|
7732
7420
|
for (const entry of entries) {
|
|
7733
7421
|
let parent = this;
|
|
7734
7422
|
try {
|
|
7735
|
-
const path = entry.filename.split("/");
|
|
7423
|
+
const path = entry.filename.split("/").filter(pathPart => pathPart != "" && pathPart != ".");
|
|
7736
7424
|
const name = path.pop();
|
|
7737
7425
|
path.forEach(pathPart => {
|
|
7738
7426
|
const previousParent = parent;
|
|
@@ -8107,6 +7795,39 @@
|
|
|
8107
7795
|
}
|
|
8108
7796
|
}
|
|
8109
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
|
+
|
|
8110
7831
|
function getUserExtraField(extraField) {
|
|
8111
7832
|
if (extraField) {
|
|
8112
7833
|
const userExtraField = new Map();
|
|
@@ -8227,8 +7948,9 @@
|
|
|
8227
7948
|
function addFileSystemHandle(zipEntry, handle, options) {
|
|
8228
7949
|
return addFile(zipEntry, handle, []);
|
|
8229
7950
|
|
|
8230
|
-
async function addFile(parentEntry, handle, addedEntries) {
|
|
7951
|
+
async function addFile(parentEntry, handle, addedEntries, parentName = "") {
|
|
8231
7952
|
if (handle) {
|
|
7953
|
+
const entryName = parentName ? parentName + "/" + handle.name : handle.name;
|
|
8232
7954
|
try {
|
|
8233
7955
|
if (handle.isFile || handle.isDirectory) {
|
|
8234
7956
|
handle = await transformToFileSystemhandle(handle);
|
|
@@ -8250,12 +7972,18 @@
|
|
|
8250
7972
|
const directoryEntry = parentEntry.addDirectory(handle.name);
|
|
8251
7973
|
addedEntries.push(directoryEntry);
|
|
8252
7974
|
for await (const childHandle of handle.values()) {
|
|
8253
|
-
await addFile(directoryEntry, childHandle, addedEntries);
|
|
7975
|
+
await addFile(directoryEntry, childHandle, addedEntries, entryName);
|
|
8254
7976
|
}
|
|
8255
7977
|
}
|
|
8256
7978
|
} catch (error) {
|
|
8257
|
-
|
|
8258
|
-
|
|
7979
|
+
try {
|
|
7980
|
+
if (error.entryName === UNDEFINED_VALUE) {
|
|
7981
|
+
error.entryName = entryName;
|
|
7982
|
+
}
|
|
7983
|
+
} catch {
|
|
7984
|
+
// ignored
|
|
7985
|
+
}
|
|
7986
|
+
throw error;
|
|
8259
7987
|
}
|
|
8260
7988
|
}
|
|
8261
7989
|
return addedEntries;
|
|
@@ -8265,15 +7993,32 @@
|
|
|
8265
7993
|
async function exportFileSystemHandle(zipEntry, directoryHandle, options) {
|
|
8266
7994
|
const totalSize = getTotalSize([zipEntry], "uncompressedSize");
|
|
8267
7995
|
const writtenSizes = new Map();
|
|
8268
|
-
|
|
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
|
+
}
|
|
8269
8012
|
return directoryHandle;
|
|
8270
8013
|
|
|
8271
8014
|
async function exportChildren(entry, parentHandle) {
|
|
8272
8015
|
if (options.concurrent) {
|
|
8273
8016
|
const results = await Promise.allSettled(entry.children.map(child => exportChild(child, parentHandle)));
|
|
8274
|
-
const
|
|
8275
|
-
if (
|
|
8276
|
-
|
|
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));
|
|
8277
8022
|
}
|
|
8278
8023
|
} else {
|
|
8279
8024
|
for (const child of entry.children) {
|
|
@@ -8283,6 +8028,12 @@
|
|
|
8283
8028
|
}
|
|
8284
8029
|
|
|
8285
8030
|
async function exportChild(child, parentHandle) {
|
|
8031
|
+
if (signal.aborted) {
|
|
8032
|
+
if (isExportAborted(signal.reason)) {
|
|
8033
|
+
return;
|
|
8034
|
+
}
|
|
8035
|
+
throw signal.reason;
|
|
8036
|
+
}
|
|
8286
8037
|
try {
|
|
8287
8038
|
if (child.directory) {
|
|
8288
8039
|
const childDirectoryHandle = await parentHandle.getDirectoryHandle(child.name, { create: true });
|
|
@@ -8291,6 +8042,7 @@
|
|
|
8291
8042
|
const fileHandle = await parentHandle.getFileHandle(child.name, { create: true });
|
|
8292
8043
|
const writable = await fileHandle.createWritable();
|
|
8293
8044
|
await child.getData({ writable }, Object.assign({}, options, {
|
|
8045
|
+
signal,
|
|
8294
8046
|
onprogress: async progress => {
|
|
8295
8047
|
if (options.onprogress) {
|
|
8296
8048
|
writtenSizes.set(child.id, progress);
|
|
@@ -8302,9 +8054,19 @@
|
|
|
8302
8054
|
}
|
|
8303
8055
|
}
|
|
8304
8056
|
}));
|
|
8057
|
+
exportedEntryNames.push(child.getRelativeName(zipEntry));
|
|
8305
8058
|
}
|
|
8306
8059
|
} catch (error) {
|
|
8307
|
-
|
|
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;
|
|
8308
8070
|
}
|
|
8309
8071
|
}
|
|
8310
8072
|
}
|