@zip.js/zip.js 2.8.37 → 2.8.39
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/README.md +0 -12
- package/deno.json +3 -2
- package/dist/zip-core.js +161 -38
- package/dist/zip-core.min.js +1 -1
- package/dist/zip-fs-core.js +154 -38
- package/dist/zip-fs-core.min.js +1 -1
- package/dist/zip-fs-native.js +163 -40
- package/dist/zip-fs-native.min.js +1 -1
- package/dist/zip-fs.js +162 -39
- package/dist/zip-fs.min.js +1 -1
- package/dist/zip-legacy.js +163 -40
- package/dist/zip-legacy.min.js +1 -1
- package/dist/zip-native.js +163 -40
- 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 +162 -39
- package/dist/zip.min.js +1 -1
- package/index-native.cjs +163 -40
- package/index-native.min.js +1 -1
- package/index.cjs +162 -39
- package/index.d.cts +22 -2
- package/index.d.ts +22 -2
- package/index.min.js +1 -1
- package/lib/core/codec-pool.js +2 -1
- package/lib/core/codec-worker.js +94 -18
- package/lib/core/configuration.js +2 -0
- package/lib/core/constants.js +4 -0
- package/lib/core/io.js +1 -1
- package/lib/core/streams/codec-stream.js +6 -2
- package/lib/core/streams/zip-crypto-stream.js +1 -1
- package/lib/core/streams/zip-entry-stream.js +29 -12
- package/lib/core/web-worker-base.js +26 -8
- package/lib/core/web-worker-inline-native.js +1 -1
- package/lib/core/web-worker-inline-wasm.js +1 -1
- package/lib/core/zip-reader.js +23 -1
- package/lib/core/zip-writer.js +15 -7
- package/lib/zip-core-reader.js +2 -1
- package/package.json +1 -1
- package/worker-message-property-names.js +1 -1
package/README.md
CHANGED
|
@@ -14,18 +14,6 @@ See https://gildas-lormeau.github.io/zip-manager
|
|
|
14
14
|
|
|
15
15
|
See here for more info: https://gildas-lormeau.github.io/zip.js/
|
|
16
16
|
|
|
17
|
-
# Bundle size
|
|
18
|
-
|
|
19
|
-
zip.js is tree-shakeable: import named identifiers and your bundler removes what you do
|
|
20
|
-
not use, e.g. the whole write path if you only read zip files. `import * as zip from
|
|
21
|
-
"@zip.js/zip.js"` keeps everything.
|
|
22
|
-
|
|
23
|
-
Smaller entry points are also available, e.g. `@zip.js/zip.js/lib/zip-core.js` embeds
|
|
24
|
-
neither the Web Worker code nor the WASM module, pass `workerURI` and `wasmURI` to
|
|
25
|
-
`configure()` instead. The prebuilt bundles in
|
|
26
|
-
[`/dist`](https://github.com/gildas-lormeau/zip.js/tree/master/dist) are standalone files
|
|
27
|
-
for script tags and AMD loaders, they are not tree-shaken.
|
|
28
|
-
|
|
29
17
|
# Examples
|
|
30
18
|
|
|
31
19
|
## Hello world
|
package/deno.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zip-js/zip-js",
|
|
3
|
-
"version": "2.8.
|
|
3
|
+
"version": "2.8.39",
|
|
4
4
|
"exports": {
|
|
5
5
|
".": "./index.js"
|
|
6
6
|
},
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"benchmarks",
|
|
25
25
|
"docs",
|
|
26
26
|
".github",
|
|
27
|
-
"tests/corpus"
|
|
27
|
+
"tests/corpus",
|
|
28
|
+
"tests/fidelity/corpus"
|
|
28
29
|
]
|
|
29
30
|
}
|
package/dist/zip-core.js
CHANGED
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
const LOCAL_FILE_HEADER_SIGNATURE = 0x04034b50;
|
|
47
47
|
const SPLIT_ZIP_FILE_SIGNATURE = 0x08074b50;
|
|
48
48
|
const DATA_DESCRIPTOR_RECORD_SIGNATURE = SPLIT_ZIP_FILE_SIGNATURE;
|
|
49
|
+
const ARCHIVE_EXTRA_DATA_SIGNATURE = 0x08064b50;
|
|
49
50
|
const CENTRAL_FILE_HEADER_SIGNATURE = 0x02014b50;
|
|
50
51
|
const END_OF_CENTRAL_DIR_SIGNATURE = 0x06054b50;
|
|
51
52
|
const ZIP64_END_OF_CENTRAL_DIR_SIGNATURE = 0x06064b50;
|
|
@@ -77,6 +78,7 @@
|
|
|
77
78
|
const BITFLAG_LEVEL_FAST_MASK = 0b100;
|
|
78
79
|
const BITFLAG_LEVEL_SUPER_FAST_MASK = 0b110;
|
|
79
80
|
const BITFLAG_DATA_DESCRIPTOR = 0b1000;
|
|
81
|
+
const BITFLAG_STRONG_ENCRYPTION = 0b1000000;
|
|
80
82
|
const BITFLAG_LANG_ENCODING_FLAG = 0b100000000000;
|
|
81
83
|
const FILE_ATTR_MSDOS_DIR_MASK = 0b10000;
|
|
82
84
|
const FILE_ATTR_MSDOS_READONLY_MASK = 0x01;
|
|
@@ -160,6 +162,7 @@
|
|
|
160
162
|
maxWorkers,
|
|
161
163
|
terminateWorkerTimeout: 5000,
|
|
162
164
|
workerStarvationTimeout: 5000,
|
|
165
|
+
workerStartupTimeout: 5000,
|
|
163
166
|
useWebWorkers: true,
|
|
164
167
|
useCompressionStream: true,
|
|
165
168
|
transferStreams: true,
|
|
@@ -175,6 +178,7 @@
|
|
|
175
178
|
"maxWorkers",
|
|
176
179
|
"terminateWorkerTimeout",
|
|
177
180
|
"workerStarvationTimeout",
|
|
181
|
+
"workerStartupTimeout",
|
|
178
182
|
"useCompressionStream",
|
|
179
183
|
"useWebWorkers",
|
|
180
184
|
"transferStreams",
|
|
@@ -1710,7 +1714,7 @@
|
|
|
1710
1714
|
if (zipCrypto.password || zipCrypto.rawPassword) {
|
|
1711
1715
|
const decryptedHeader = decrypt(zipCrypto, chunk.subarray(0, HEADER_LENGTH));
|
|
1712
1716
|
zipCrypto.password = zipCrypto.rawPassword = null;
|
|
1713
|
-
if ((decryptedHeader
|
|
1717
|
+
if ((decryptedHeader[HEADER_LENGTH - 1] ^ zipCrypto.passwordVerification) != 0) {
|
|
1714
1718
|
throw new Error(ERR_INVALID_PASSWORD);
|
|
1715
1719
|
}
|
|
1716
1720
|
chunk = chunk.subarray(HEADER_LENGTH);
|
|
@@ -1883,7 +1887,7 @@
|
|
|
1883
1887
|
readable = pipeThroughBackpressured(readable, new CompressionStream(FORMAT_GZIP));
|
|
1884
1888
|
readable = pipeThrough(readable, gzipCrc32Stream);
|
|
1885
1889
|
} else {
|
|
1886
|
-
readable =
|
|
1890
|
+
readable = pipeThroughCompressionStream(readable, useCompressionStream, { level, chunkSize }, CompressionStream, CompressionStreamZlib);
|
|
1887
1891
|
}
|
|
1888
1892
|
}
|
|
1889
1893
|
if (encrypted) {
|
|
@@ -1968,7 +1972,7 @@
|
|
|
1968
1972
|
if (codecStreams) {
|
|
1969
1973
|
readable = pipeThroughBackpressured(readable, createCodecStream(codecStreams.DecompressionStream, format, { chunkSize }));
|
|
1970
1974
|
} else {
|
|
1971
|
-
readable =
|
|
1975
|
+
readable = pipeThroughCompressionStream(readable, useCompressionStream, { chunkSize, deflate64 }, DecompressionStream, DecompressionStreamZlib);
|
|
1972
1976
|
}
|
|
1973
1977
|
readable = mapInflateStreamError(readable);
|
|
1974
1978
|
}
|
|
@@ -1987,6 +1991,25 @@
|
|
|
1987
1991
|
}
|
|
1988
1992
|
}
|
|
1989
1993
|
|
|
1994
|
+
const deflateRawSupportByStream = new Map();
|
|
1995
|
+
|
|
1996
|
+
function supportsDeflateRaw(StreamClass) {
|
|
1997
|
+
if (!StreamClass) {
|
|
1998
|
+
return false;
|
|
1999
|
+
}
|
|
2000
|
+
let supported = deflateRawSupportByStream.get(StreamClass);
|
|
2001
|
+
if (supported === UNDEFINED_VALUE) {
|
|
2002
|
+
try {
|
|
2003
|
+
new StreamClass(FORMAT_DEFLATE_RAW);
|
|
2004
|
+
supported = true;
|
|
2005
|
+
} catch {
|
|
2006
|
+
supported = false;
|
|
2007
|
+
}
|
|
2008
|
+
deflateRawSupportByStream.set(StreamClass, supported);
|
|
2009
|
+
}
|
|
2010
|
+
return supported;
|
|
2011
|
+
}
|
|
2012
|
+
|
|
1990
2013
|
function setReadable(stream, readable, flush) {
|
|
1991
2014
|
readable = pipeThrough(readable, new TransformStream({ flush }));
|
|
1992
2015
|
Object.defineProperty(stream, "readable", {
|
|
@@ -2003,21 +2026,17 @@
|
|
|
2003
2026
|
return new CodecStreamClass(format, options);
|
|
2004
2027
|
}
|
|
2005
2028
|
|
|
2006
|
-
function
|
|
2007
|
-
const Stream = useCompressionStream && CompressionStreamNative ?
|
|
2029
|
+
function pipeThroughCompressionStream(readable, useCompressionStream, options, CompressionStreamNative, CompressionStreamZlib) {
|
|
2030
|
+
const Stream = useCompressionStream && CompressionStreamNative ?
|
|
2031
|
+
CompressionStreamNative :
|
|
2032
|
+
CompressionStreamZlib || CompressionStreamNative;
|
|
2008
2033
|
const format = options.deflate64 ? FORMAT_DEFLATE64_RAW : FORMAT_DEFLATE_RAW;
|
|
2009
2034
|
let codecStream;
|
|
2010
2035
|
try {
|
|
2011
2036
|
codecStream = new Stream(format, options);
|
|
2012
2037
|
} catch (error) {
|
|
2013
|
-
if (useCompressionStream) {
|
|
2014
|
-
|
|
2015
|
-
codecStream = new CompressionStreamZlib(format, options);
|
|
2016
|
-
} else if (CompressionStream) {
|
|
2017
|
-
codecStream = new CompressionStream(format, options);
|
|
2018
|
-
} else {
|
|
2019
|
-
throw error;
|
|
2020
|
-
}
|
|
2038
|
+
if (useCompressionStream && CompressionStreamZlib && Stream != CompressionStreamZlib) {
|
|
2039
|
+
codecStream = new CompressionStreamZlib(format, options);
|
|
2021
2040
|
} else {
|
|
2022
2041
|
throw error;
|
|
2023
2042
|
}
|
|
@@ -2278,6 +2297,7 @@
|
|
|
2278
2297
|
const MODULE_WORKER_OPTIONS = { type: "module" };
|
|
2279
2298
|
const ERROR_EVENT_TYPE = "error";
|
|
2280
2299
|
const MESSAGE_ERROR_EVENT_TYPE = "messageerror";
|
|
2300
|
+
const ERR_WORKER_STARTUP_TIMEOUT = "Worker startup timeout";
|
|
2281
2301
|
|
|
2282
2302
|
let webWorkerSupported, webWorkerSource, webWorkerURI, webWorkerOptions;
|
|
2283
2303
|
let transferStreamsSupported = true;
|
|
@@ -2288,6 +2308,10 @@
|
|
|
2288
2308
|
}
|
|
2289
2309
|
let initModule = () => { };
|
|
2290
2310
|
|
|
2311
|
+
function resetWebWorkerSupport() {
|
|
2312
|
+
webWorkerSupported = UNDEFINED_VALUE;
|
|
2313
|
+
}
|
|
2314
|
+
|
|
2291
2315
|
class CodecWorker {
|
|
2292
2316
|
|
|
2293
2317
|
constructor(workerData, { readable, writable }, { options, config, streamOptions, useWebWorkers, transferStreams, workerURI }, onTaskFinished) {
|
|
@@ -2381,7 +2405,7 @@
|
|
|
2381
2405
|
}
|
|
2382
2406
|
|
|
2383
2407
|
function createWebWorkerInterface(workerData, config) {
|
|
2384
|
-
const { baseURI, chunkSize } = config;
|
|
2408
|
+
const { baseURI, chunkSize, workerStartupTimeout } = config;
|
|
2385
2409
|
let { wasmURI } = config;
|
|
2386
2410
|
|
|
2387
2411
|
if (!workerData.interface) {
|
|
@@ -2398,9 +2422,26 @@
|
|
|
2398
2422
|
}
|
|
2399
2423
|
Object.assign(workerData, {
|
|
2400
2424
|
worker,
|
|
2425
|
+
workerAlive: false,
|
|
2401
2426
|
terminated: false,
|
|
2402
2427
|
interface: {
|
|
2403
|
-
run: () =>
|
|
2428
|
+
run: async () => {
|
|
2429
|
+
try {
|
|
2430
|
+
return await runWebWorker(workerData, { chunkSize, wasmURI, baseURI, workerStartupTimeout });
|
|
2431
|
+
} catch (error) {
|
|
2432
|
+
if (error && error.workerStartupFailed) {
|
|
2433
|
+
webWorkerSupported = false;
|
|
2434
|
+
const { reader } = workerData;
|
|
2435
|
+
if (reader) {
|
|
2436
|
+
reader.releaseLock();
|
|
2437
|
+
}
|
|
2438
|
+
workerData.reader = null;
|
|
2439
|
+
workerData.writer = null;
|
|
2440
|
+
return runWorker$1(workerData, config);
|
|
2441
|
+
}
|
|
2442
|
+
throw error;
|
|
2443
|
+
}
|
|
2444
|
+
}
|
|
2404
2445
|
}
|
|
2405
2446
|
});
|
|
2406
2447
|
}
|
|
@@ -2410,15 +2451,23 @@
|
|
|
2410
2451
|
async function runWorker$1({ options, readable, writable, onTaskFinished }, config) {
|
|
2411
2452
|
let codecStream;
|
|
2412
2453
|
try {
|
|
2413
|
-
if (!options.
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
config
|
|
2420
|
-
|
|
2421
|
-
|
|
2454
|
+
if (options.compressed && !options.format) {
|
|
2455
|
+
const deflate = options.codecType.startsWith(CODEC_DEFLATE);
|
|
2456
|
+
const ZlibStream = deflate ? config.CompressionStreamZlib : config.DecompressionStreamZlib;
|
|
2457
|
+
const NativeStream = deflate ? config.CompressionStream : config.DecompressionStream;
|
|
2458
|
+
if (!options.useCompressionStream) {
|
|
2459
|
+
try {
|
|
2460
|
+
await initModule(config);
|
|
2461
|
+
} catch {
|
|
2462
|
+
if (!ZlibStream || ZlibStream.requiresModule) {
|
|
2463
|
+
options.useCompressionStream = true;
|
|
2464
|
+
}
|
|
2465
|
+
}
|
|
2466
|
+
} else if (ZlibStream && ZlibStream.requiresModule && !supportsDeflateRaw(NativeStream)) {
|
|
2467
|
+
try {
|
|
2468
|
+
await initModule(config);
|
|
2469
|
+
} catch {
|
|
2470
|
+
// ignored
|
|
2422
2471
|
}
|
|
2423
2472
|
}
|
|
2424
2473
|
}
|
|
@@ -2487,6 +2536,10 @@
|
|
|
2487
2536
|
writer: writable.getWriter()
|
|
2488
2537
|
});
|
|
2489
2538
|
}
|
|
2539
|
+
const { workerStartupTimeout } = config;
|
|
2540
|
+
if (!workerData.workerAlive && Number.isFinite(workerStartupTimeout) && workerStartupTimeout >= 0) {
|
|
2541
|
+
workerData.startupTimeout = setTimeout(() => onStartupTimeout(workerData), workerStartupTimeout);
|
|
2542
|
+
}
|
|
2490
2543
|
try {
|
|
2491
2544
|
const resultValue = await result;
|
|
2492
2545
|
await closeWritable();
|
|
@@ -2599,28 +2652,68 @@
|
|
|
2599
2652
|
} else {
|
|
2600
2653
|
worker = new Worker(webWorkerURI, webWorkerOptions);
|
|
2601
2654
|
}
|
|
2602
|
-
worker.addEventListener(MESSAGE_EVENT_TYPE, event =>
|
|
2655
|
+
worker.addEventListener(MESSAGE_EVENT_TYPE, event => {
|
|
2656
|
+
workerData.workerAlive = true;
|
|
2657
|
+
clearStartupTimeout(workerData);
|
|
2658
|
+
onMessage(event, workerData);
|
|
2659
|
+
});
|
|
2603
2660
|
worker.addEventListener(ERROR_EVENT_TYPE, event => onWorkerError(event, workerData));
|
|
2604
2661
|
worker.addEventListener(MESSAGE_ERROR_EVENT_TYPE, event => onWorkerError(event, workerData));
|
|
2605
2662
|
return worker;
|
|
2606
2663
|
}
|
|
2607
2664
|
|
|
2665
|
+
function onStartupTimeout(workerData) {
|
|
2666
|
+
workerData.startupTimeout = null;
|
|
2667
|
+
if (workerData.workerAlive) {
|
|
2668
|
+
return;
|
|
2669
|
+
}
|
|
2670
|
+
const { rejectResult, writer } = workerData;
|
|
2671
|
+
terminateWorker$1(workerData);
|
|
2672
|
+
workerData.worker = null;
|
|
2673
|
+
if (rejectResult) {
|
|
2674
|
+
const error = new Error(ERR_WORKER_STARTUP_TIMEOUT);
|
|
2675
|
+
error.workerStartupFailed = true;
|
|
2676
|
+
rejectResult(error);
|
|
2677
|
+
if (writer) {
|
|
2678
|
+
writer.releaseLock();
|
|
2679
|
+
}
|
|
2680
|
+
}
|
|
2681
|
+
}
|
|
2682
|
+
|
|
2683
|
+
function clearStartupTimeout(workerData) {
|
|
2684
|
+
const { startupTimeout } = workerData;
|
|
2685
|
+
if (startupTimeout) {
|
|
2686
|
+
clearTimeout(startupTimeout);
|
|
2687
|
+
workerData.startupTimeout = null;
|
|
2688
|
+
}
|
|
2689
|
+
}
|
|
2690
|
+
|
|
2608
2691
|
function onWorkerError(event, workerData) {
|
|
2609
2692
|
if (event.preventDefault) {
|
|
2610
2693
|
event.preventDefault();
|
|
2611
2694
|
}
|
|
2612
|
-
|
|
2695
|
+
clearStartupTimeout(workerData);
|
|
2696
|
+
const { workerAlive, rejectResult, writer, onTaskFinished } = workerData;
|
|
2613
2697
|
terminateWorker$1(workerData);
|
|
2698
|
+
if (!workerAlive) {
|
|
2699
|
+
workerData.worker = null;
|
|
2700
|
+
}
|
|
2614
2701
|
if (rejectResult) {
|
|
2615
|
-
|
|
2702
|
+
let error = event.error || new Error(event.message || ERROR_EVENT_TYPE);
|
|
2703
|
+
if (!workerAlive) {
|
|
2704
|
+
error = Object.assign(new Error(error.message || ERROR_EVENT_TYPE), { workerStartupFailed: true });
|
|
2705
|
+
}
|
|
2706
|
+
rejectResult(error);
|
|
2616
2707
|
if (writer) {
|
|
2617
2708
|
writer.releaseLock();
|
|
2618
2709
|
}
|
|
2619
|
-
|
|
2710
|
+
if (workerAlive) {
|
|
2711
|
+
onTaskFinished();
|
|
2712
|
+
}
|
|
2620
2713
|
}
|
|
2621
2714
|
}
|
|
2622
2715
|
|
|
2623
|
-
function sendMessage(message, { worker, writer, transferStreams }) {
|
|
2716
|
+
function sendMessage(message, { worker, writer, transferStreams, workerAlive }) {
|
|
2624
2717
|
try {
|
|
2625
2718
|
const { value, readable, writable } = message;
|
|
2626
2719
|
const transferables = [];
|
|
@@ -2628,7 +2721,7 @@
|
|
|
2628
2721
|
message.value = toExactUint8Array(value);
|
|
2629
2722
|
transferables.push(message.value.buffer);
|
|
2630
2723
|
}
|
|
2631
|
-
if (transferStreams && transferStreamsSupported) {
|
|
2724
|
+
if (transferStreams && transferStreamsSupported && workerAlive) {
|
|
2632
2725
|
if (readable) {
|
|
2633
2726
|
transferables.push(readable);
|
|
2634
2727
|
}
|
|
@@ -2866,6 +2959,7 @@
|
|
|
2866
2959
|
clearTerminateTimeout(workerData);
|
|
2867
2960
|
return workerData.terminate();
|
|
2868
2961
|
}));
|
|
2962
|
+
resetWebWorkerSupport();
|
|
2869
2963
|
}
|
|
2870
2964
|
|
|
2871
2965
|
/*
|
|
@@ -3642,7 +3736,7 @@
|
|
|
3642
3736
|
|
|
3643
3737
|
getDiskOffset(diskNumber) {
|
|
3644
3738
|
const { diskOffsets, size } = this;
|
|
3645
|
-
const diskOffset = diskOffsets
|
|
3739
|
+
const diskOffset = diskOffsets[diskNumber];
|
|
3646
3740
|
return diskOffset === UNDEFINED_VALUE ? size : diskOffset;
|
|
3647
3741
|
}
|
|
3648
3742
|
|
|
@@ -4149,6 +4243,7 @@
|
|
|
4149
4243
|
const ERR_SPLIT_ZIP_FILE = "Split zip file";
|
|
4150
4244
|
const ERR_OVERLAPPING_ENTRY = "Overlapping entry found";
|
|
4151
4245
|
const ERR_AMBIGUOUS_ARCHIVE = "Ambiguous archive";
|
|
4246
|
+
const ERR_ENCRYPTED_CENTRAL_DIRECTORY = "Encrypted central directory is not supported";
|
|
4152
4247
|
const CHARSET_UTF8 = "utf-8";
|
|
4153
4248
|
const PROPERTY_NAME_UTF8_SUFFIX = "UTF8";
|
|
4154
4249
|
const CHARSET_CP437 = "cp437";
|
|
@@ -4226,6 +4321,7 @@
|
|
|
4226
4321
|
let prependedDataLength = 0;
|
|
4227
4322
|
let startOffset;
|
|
4228
4323
|
let zip64EndOfDirectory;
|
|
4324
|
+
let zip64EndOfDirectoryVersion2;
|
|
4229
4325
|
const requiresZip64 = directoryDataOffset == MAX_32_BITS || directoryDataLength == MAX_32_BITS || filesLength == MAX_16_BITS || diskNumber == MAX_16_BITS;
|
|
4230
4326
|
if (directoryDataOffset != MAX_32_BITS && diskNumber != MAX_16_BITS) {
|
|
4231
4327
|
directoryDataOffset += getDiskOffset$1(reader, diskNumber);
|
|
@@ -4255,6 +4351,7 @@
|
|
|
4255
4351
|
throw new Error(ERR_EOCDR_LOCATOR_ZIP64_NOT_FOUND);
|
|
4256
4352
|
}
|
|
4257
4353
|
zip64EndOfDirectory = true;
|
|
4354
|
+
zip64EndOfDirectoryVersion2 = getBigUint64(endOfDirectoryView, 4) > ZIP64_END_OF_CENTRAL_DIR_LENGTH - 12;
|
|
4258
4355
|
if (lastDiskNumber == MAX_16_BITS) {
|
|
4259
4356
|
lastDiskNumber = getUint32(endOfDirectoryView, 16);
|
|
4260
4357
|
} else if (checkAmbiguity && lastDiskNumber != getUint32(endOfDirectoryView, 16)) {
|
|
@@ -4334,6 +4431,9 @@
|
|
|
4334
4431
|
for (let indexFile = 0; indexFile < filesLength; indexFile++) {
|
|
4335
4432
|
const fileEntry = new ZipEntry(reader, config, zipReader.options);
|
|
4336
4433
|
if (offset + CENTRAL_FILE_HEADER_LENGTH > directoryArray.length || getUint32(directoryView, offset) != CENTRAL_FILE_HEADER_SIGNATURE) {
|
|
4434
|
+
if (indexFile == 0 && (zip64EndOfDirectoryVersion2 || detectEncryptedCentralDirectory(directoryView))) {
|
|
4435
|
+
throw new Error(ERR_ENCRYPTED_CENTRAL_DIRECTORY);
|
|
4436
|
+
}
|
|
4337
4437
|
throw new Error(ERR_CENTRAL_DIRECTORY_NOT_FOUND);
|
|
4338
4438
|
}
|
|
4339
4439
|
readCommonHeader(fileEntry, directoryView, offset + 6);
|
|
@@ -4601,6 +4701,9 @@
|
|
|
4601
4701
|
fileEntry.zipCrypto = zipCrypto;
|
|
4602
4702
|
}
|
|
4603
4703
|
if (encrypted) {
|
|
4704
|
+
if ((localDirectory.rawBitFlag & BITFLAG_STRONG_ENCRYPTION) == BITFLAG_STRONG_ENCRYPTION) {
|
|
4705
|
+
throw new Error(ERR_UNSUPPORTED_ENCRYPTION);
|
|
4706
|
+
}
|
|
4604
4707
|
if (!zipCrypto && (extraFieldAES.strength < 1 || extraFieldAES.strength > 3)) {
|
|
4605
4708
|
throw new Error(ERR_UNSUPPORTED_ENCRYPTION);
|
|
4606
4709
|
} else if (!password && !rawPassword) {
|
|
@@ -4694,6 +4797,16 @@
|
|
|
4694
4797
|
}
|
|
4695
4798
|
}
|
|
4696
4799
|
|
|
4800
|
+
function detectEncryptedCentralDirectory(directoryView) {
|
|
4801
|
+
const maxOffset = Math.min(directoryView.byteLength, 1024) - 3;
|
|
4802
|
+
for (let offset = 0; offset < maxOffset; offset++) {
|
|
4803
|
+
if (getUint32(directoryView, offset) == ARCHIVE_EXTRA_DATA_SIGNATURE) {
|
|
4804
|
+
return true;
|
|
4805
|
+
}
|
|
4806
|
+
}
|
|
4807
|
+
return false;
|
|
4808
|
+
}
|
|
4809
|
+
|
|
4697
4810
|
function readCommonHeader(directory, dataView, offset) {
|
|
4698
4811
|
const rawBitFlag = directory.rawBitFlag = getUint16(dataView, offset + 2);
|
|
4699
4812
|
const encrypted = (rawBitFlag & BITFLAG_ENCRYPTED) == BITFLAG_ENCRYPTED;
|
|
@@ -5208,6 +5321,7 @@
|
|
|
5208
5321
|
ERR_BAD_FORMAT: ERR_BAD_FORMAT,
|
|
5209
5322
|
ERR_CENTRAL_DIRECTORY_NOT_FOUND: ERR_CENTRAL_DIRECTORY_NOT_FOUND,
|
|
5210
5323
|
ERR_ENCRYPTED: ERR_ENCRYPTED,
|
|
5324
|
+
ERR_ENCRYPTED_CENTRAL_DIRECTORY: ERR_ENCRYPTED_CENTRAL_DIRECTORY,
|
|
5211
5325
|
ERR_EOCDR_LOCATOR_ZIP64_NOT_FOUND: ERR_EOCDR_LOCATOR_ZIP64_NOT_FOUND,
|
|
5212
5326
|
ERR_EOCDR_NOT_FOUND: ERR_EOCDR_NOT_FOUND,
|
|
5213
5327
|
ERR_EXTRAFIELD_ZIP64_NOT_FOUND: ERR_EXTRAFIELD_ZIP64_NOT_FOUND,
|
|
@@ -5620,7 +5734,11 @@
|
|
|
5620
5734
|
if (versionMadeBy > MAX_16_BITS) {
|
|
5621
5735
|
throw new Error(ERR_INVALID_VERSION);
|
|
5622
5736
|
}
|
|
5623
|
-
let externalFileAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTES
|
|
5737
|
+
let externalFileAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTES);
|
|
5738
|
+
const externalFileAttributesProvided = externalFileAttributes !== UNDEFINED_VALUE;
|
|
5739
|
+
if (!externalFileAttributesProvided) {
|
|
5740
|
+
externalFileAttributes = 0;
|
|
5741
|
+
}
|
|
5624
5742
|
if (!options[PROPERTY_NAME_DIRECTORY] && name.endsWith(DIRECTORY_SIGNATURE)) {
|
|
5625
5743
|
options[PROPERTY_NAME_DIRECTORY] = true;
|
|
5626
5744
|
}
|
|
@@ -5629,13 +5747,13 @@
|
|
|
5629
5747
|
if (!name.endsWith(DIRECTORY_SIGNATURE)) {
|
|
5630
5748
|
name += DIRECTORY_SIGNATURE;
|
|
5631
5749
|
}
|
|
5632
|
-
if (
|
|
5750
|
+
if (!externalFileAttributesProvided) {
|
|
5633
5751
|
externalFileAttributes = FILE_ATTR_MSDOS_DIR_MASK;
|
|
5634
5752
|
if (!msDosCompatible) {
|
|
5635
5753
|
externalFileAttributes |= (FILE_ATTR_UNIX_TYPE_DIR | FILE_ATTR_UNIX_EXECUTABLE_MASK | FILE_ATTR_UNIX_DEFAULT_MASK) << 16;
|
|
5636
5754
|
}
|
|
5637
5755
|
}
|
|
5638
|
-
} else if (!msDosCompatible &&
|
|
5756
|
+
} else if (!msDosCompatible && !externalFileAttributesProvided) {
|
|
5639
5757
|
if (executable) {
|
|
5640
5758
|
externalFileAttributes = (FILE_ATTR_UNIX_EXECUTABLE_MASK | FILE_ATTR_UNIX_DEFAULT_MASK) << 16;
|
|
5641
5759
|
} else {
|
|
@@ -5644,6 +5762,7 @@
|
|
|
5644
5762
|
}
|
|
5645
5763
|
let unixExternalUpper;
|
|
5646
5764
|
if (!msDosCompatible) {
|
|
5765
|
+
const unixModeProvided = unixMode !== UNDEFINED_VALUE || Boolean(setuid || setgid || sticky);
|
|
5647
5766
|
unixExternalUpper = (externalFileAttributes >> 16) & MAX_16_BITS;
|
|
5648
5767
|
unixMode = unixMode === UNDEFINED_VALUE ? unixExternalUpper : (unixMode & MAX_16_BITS);
|
|
5649
5768
|
if (setuid) {
|
|
@@ -5661,10 +5780,12 @@
|
|
|
5661
5780
|
} else {
|
|
5662
5781
|
sticky = Boolean(unixMode & FILE_ATTR_UNIX_STICKY_MASK);
|
|
5663
5782
|
}
|
|
5664
|
-
if (
|
|
5665
|
-
|
|
5783
|
+
if (!externalFileAttributesProvided || unixModeProvided) {
|
|
5784
|
+
if (directory) {
|
|
5785
|
+
unixMode |= FILE_ATTR_UNIX_TYPE_DIR;
|
|
5786
|
+
}
|
|
5787
|
+
externalFileAttributes = ((unixMode & MAX_16_BITS) << 16) | (externalFileAttributes & MAX_16_BITS);
|
|
5666
5788
|
}
|
|
5667
|
-
externalFileAttributes = ((unixMode & MAX_16_BITS) << 16) | (externalFileAttributes & MAX_8_BITS);
|
|
5668
5789
|
}
|
|
5669
5790
|
({ msdosAttributesRaw, msdosAttributes } = normalizeMsdosAttributes(msdosAttributesRaw, msdosAttributes));
|
|
5670
5791
|
if (hasMsDosProvided) {
|
|
@@ -6387,6 +6508,7 @@
|
|
|
6387
6508
|
if (extraFieldLength > MAX_16_BITS) {
|
|
6388
6509
|
throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
|
|
6389
6510
|
}
|
|
6511
|
+
const dosLastModDate = new Date(Math.ceil(lastModDate.getTime() / 2000) * 2000);
|
|
6390
6512
|
const {
|
|
6391
6513
|
headerArray,
|
|
6392
6514
|
headerView,
|
|
@@ -6396,7 +6518,7 @@
|
|
|
6396
6518
|
bitFlag: getBitFlag(level, useUnicodeFileNames, dataDescriptor, encrypted, compressionMethod),
|
|
6397
6519
|
compressionMethod,
|
|
6398
6520
|
uncompressedSize,
|
|
6399
|
-
lastModDate:
|
|
6521
|
+
lastModDate: dosLastModDate < MIN_DATE ? MIN_DATE : dosLastModDate > MAX_DATE ? MAX_DATE : dosLastModDate,
|
|
6400
6522
|
rawFilename,
|
|
6401
6523
|
zip64CompressedSize,
|
|
6402
6524
|
zip64UncompressedSize,
|
|
@@ -7494,6 +7616,7 @@
|
|
|
7494
7616
|
exports.ERR_CENTRAL_DIRECTORY_NOT_FOUND = ERR_CENTRAL_DIRECTORY_NOT_FOUND;
|
|
7495
7617
|
exports.ERR_DUPLICATED_NAME = ERR_DUPLICATED_NAME;
|
|
7496
7618
|
exports.ERR_ENCRYPTED = ERR_ENCRYPTED;
|
|
7619
|
+
exports.ERR_ENCRYPTED_CENTRAL_DIRECTORY = ERR_ENCRYPTED_CENTRAL_DIRECTORY;
|
|
7497
7620
|
exports.ERR_EOCDR_LOCATOR_ZIP64_NOT_FOUND = ERR_EOCDR_LOCATOR_ZIP64_NOT_FOUND;
|
|
7498
7621
|
exports.ERR_EOCDR_NOT_FOUND = ERR_EOCDR_NOT_FOUND;
|
|
7499
7622
|
exports.ERR_EXTRAFIELD_ZIP64_NOT_FOUND = ERR_EXTRAFIELD_ZIP64_NOT_FOUND;
|