@zip.js/zip.js 2.15.0 → 2.16.1
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/BENCHMARKS.md +4 -2
- package/deno.json +1 -1
- package/dist/zip-core-external.js +410 -227
- package/dist/zip-core-external.min.js +1 -1
- package/dist/zip-core.js +234 -109
- package/dist/zip-core.min.js +1 -1
- package/dist/zip-fs-core-external.js +552 -237
- package/dist/zip-fs-core-external.min.js +1 -1
- package/dist/zip-fs-core.js +377 -118
- package/dist/zip-fs-core.min.js +1 -1
- package/dist/zip-fs-external.js +552 -237
- package/dist/zip-fs-external.min.js +1 -1
- package/dist/zip-fs-native.js +379 -120
- package/dist/zip-fs-native.min.js +1 -1
- package/dist/zip-fs.js +554 -237
- package/dist/zip-fs.min.js +1 -1
- package/dist/zip-legacy.js +236 -111
- package/dist/zip-legacy.min.js +1 -1
- package/dist/zip-native.js +236 -111
- 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 +411 -228
- package/dist/zip.min.js +1 -1
- package/eslint.config.mjs +1 -1
- package/index-native.cjs +379 -120
- package/index-native.min.js +1 -1
- package/index.cjs +554 -237
- package/index.d.cts +143 -16
- package/index.d.ts +143 -16
- package/index.min.js +1 -1
- package/lib/core/io.js +3 -2
- package/lib/core/streams/aes-crypto-stream.js +60 -17
- package/lib/core/streams/zip-crypto-stream.js +7 -7
- package/lib/core/streams/zip-entry-stream.js +146 -73
- package/lib/core/streams/zlib-wasm/zlib-streams.js +176 -118
- package/lib/core/util/compatible-streams.js +10 -5
- package/lib/core/version.js +1 -1
- 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 +144 -10
- package/lib/core/zip-reader.js +5 -5
- package/lib/core/zip-writer.js +4 -2
- package/package.json +3 -2
package/dist/zip-fs-core.js
CHANGED
|
@@ -223,7 +223,7 @@
|
|
|
223
223
|
const ERR_INVALID_PASSWORD_TYPE = "Invalid password (password must be a string, rawPassword must be a Uint8Array)";
|
|
224
224
|
const ERR_INVALID_PASS_THROUGH_VALUE = "Invalid passThrough option (must be a boolean or 'compressed')";
|
|
225
225
|
const ERR_ABORTED = "The operation was aborted";
|
|
226
|
-
const ABORT_ERROR_NAME = "AbortError";
|
|
226
|
+
const ABORT_ERROR_NAME$1 = "AbortError";
|
|
227
227
|
|
|
228
228
|
function checkFunctionOption(value) {
|
|
229
229
|
if (value && typeof value != FUNCTION_TYPE) {
|
|
@@ -241,7 +241,7 @@
|
|
|
241
241
|
|
|
242
242
|
function throwIfAborted(signal) {
|
|
243
243
|
if (signal && signal.aborted) {
|
|
244
|
-
throw signal.reason === UNDEFINED_VALUE ? new DOMException(ERR_ABORTED, ABORT_ERROR_NAME) : signal.reason;
|
|
244
|
+
throw signal.reason === UNDEFINED_VALUE ? new DOMException(ERR_ABORTED, ABORT_ERROR_NAME$1) : signal.reason;
|
|
245
245
|
}
|
|
246
246
|
}
|
|
247
247
|
|
|
@@ -1283,12 +1283,12 @@
|
|
|
1283
1283
|
class AESDecryptionStream extends TransformStream {
|
|
1284
1284
|
|
|
1285
1285
|
constructor({ password, rawPassword, encryptionStrength, checkPasswordOnly, checkAuthenticationCode = true }) {
|
|
1286
|
+
const aesCrypto = {};
|
|
1286
1287
|
super({
|
|
1287
1288
|
start() {
|
|
1288
|
-
initAesCrypto(
|
|
1289
|
+
initAesCrypto(aesCrypto, password, rawPassword, encryptionStrength);
|
|
1289
1290
|
},
|
|
1290
1291
|
async transform(chunk, controller) {
|
|
1291
|
-
const aesCrypto = this;
|
|
1292
1292
|
const {
|
|
1293
1293
|
password,
|
|
1294
1294
|
strength,
|
|
@@ -1307,6 +1307,9 @@
|
|
|
1307
1307
|
} else {
|
|
1308
1308
|
await ready;
|
|
1309
1309
|
}
|
|
1310
|
+
if (aesCrypto.discarded) {
|
|
1311
|
+
return;
|
|
1312
|
+
}
|
|
1310
1313
|
const output = new Uint8Array(chunk.length - AUTHENTICATION_CODE_LENGTH - ((chunk.length - AUTHENTICATION_CODE_LENGTH) % BLOCK_LENGTH));
|
|
1311
1314
|
controller.enqueue(append(aesCrypto, chunk, output, 0, AUTHENTICATION_CODE_LENGTH, true));
|
|
1312
1315
|
},
|
|
@@ -1315,9 +1318,12 @@
|
|
|
1315
1318
|
engine,
|
|
1316
1319
|
pendingInput,
|
|
1317
1320
|
ready
|
|
1318
|
-
} =
|
|
1321
|
+
} = aesCrypto;
|
|
1319
1322
|
if (engine) {
|
|
1320
1323
|
await ready;
|
|
1324
|
+
if (aesCrypto.discarded) {
|
|
1325
|
+
return;
|
|
1326
|
+
}
|
|
1321
1327
|
const originalAuthenticationCode = subarray(pendingInput, pendingInput.length - AUTHENTICATION_CODE_LENGTH);
|
|
1322
1328
|
const decryptedChunkArray = new Uint8Array(subarray(pendingInput, 0, pendingInput.length - AUTHENTICATION_CODE_LENGTH));
|
|
1323
1329
|
engine.process(decryptedChunkArray, true);
|
|
@@ -1327,27 +1333,26 @@
|
|
|
1327
1333
|
invalidAuthenticationCode |= authenticationCode[indexByte] ^ originalAuthenticationCode[indexByte];
|
|
1328
1334
|
}
|
|
1329
1335
|
if (invalidAuthenticationCode && checkAuthenticationCode) {
|
|
1330
|
-
|
|
1336
|
+
controller.error(new Error(ERR_INVALID_AUTHENTICATION_CODE));
|
|
1337
|
+
return;
|
|
1331
1338
|
}
|
|
1332
1339
|
controller.enqueue(decryptedChunkArray);
|
|
1333
1340
|
}
|
|
1334
|
-
},
|
|
1335
|
-
cancel() {
|
|
1336
|
-
disposeEngine(this);
|
|
1337
1341
|
}
|
|
1338
1342
|
});
|
|
1343
|
+
setDisposingReadable(this, aesCrypto);
|
|
1339
1344
|
}
|
|
1340
1345
|
}
|
|
1341
1346
|
|
|
1342
1347
|
class AESEncryptionStream extends TransformStream {
|
|
1343
1348
|
|
|
1344
1349
|
constructor({ password, rawPassword, encryptionStrength }) {
|
|
1350
|
+
const aesCrypto = {};
|
|
1345
1351
|
super({
|
|
1346
1352
|
start() {
|
|
1347
|
-
initAesCrypto(
|
|
1353
|
+
initAesCrypto(aesCrypto, password, rawPassword, encryptionStrength);
|
|
1348
1354
|
},
|
|
1349
1355
|
async transform(chunk, controller) {
|
|
1350
|
-
const aesCrypto = this;
|
|
1351
1356
|
const {
|
|
1352
1357
|
password,
|
|
1353
1358
|
strength,
|
|
@@ -1361,6 +1366,9 @@
|
|
|
1361
1366
|
} else {
|
|
1362
1367
|
await ready;
|
|
1363
1368
|
}
|
|
1369
|
+
if (aesCrypto.discarded) {
|
|
1370
|
+
return;
|
|
1371
|
+
}
|
|
1364
1372
|
const output = new Uint8Array(preamble.length + chunk.length - (chunk.length % BLOCK_LENGTH));
|
|
1365
1373
|
output.set(preamble, 0);
|
|
1366
1374
|
controller.enqueue(append(aesCrypto, chunk, output, preamble.length, 0, false));
|
|
@@ -1370,19 +1378,20 @@
|
|
|
1370
1378
|
engine,
|
|
1371
1379
|
pendingInput,
|
|
1372
1380
|
ready
|
|
1373
|
-
} =
|
|
1381
|
+
} = aesCrypto;
|
|
1374
1382
|
if (engine) {
|
|
1375
1383
|
await ready;
|
|
1384
|
+
if (aesCrypto.discarded) {
|
|
1385
|
+
return;
|
|
1386
|
+
}
|
|
1376
1387
|
const encryptedChunkArray = new Uint8Array(pendingInput);
|
|
1377
1388
|
engine.process(encryptedChunkArray, false);
|
|
1378
1389
|
const authenticationCode = subarray(engine.digest(), 0, AUTHENTICATION_CODE_LENGTH);
|
|
1379
1390
|
controller.enqueue(concat(encryptedChunkArray, authenticationCode));
|
|
1380
1391
|
}
|
|
1381
|
-
},
|
|
1382
|
-
cancel() {
|
|
1383
|
-
disposeEngine(this);
|
|
1384
1392
|
}
|
|
1385
1393
|
});
|
|
1394
|
+
setDisposingReadable(this, aesCrypto);
|
|
1386
1395
|
}
|
|
1387
1396
|
}
|
|
1388
1397
|
|
|
@@ -1391,7 +1400,37 @@
|
|
|
1391
1400
|
ready: new Promise(resolve => aesCrypto.resolveReady = resolve),
|
|
1392
1401
|
password: encodePassword(password, rawPassword),
|
|
1393
1402
|
strength: encryptionStrength - 1,
|
|
1394
|
-
pendingInput: EMPTY_UINT8_ARRAY
|
|
1403
|
+
pendingInput: EMPTY_UINT8_ARRAY,
|
|
1404
|
+
discarded: false
|
|
1405
|
+
});
|
|
1406
|
+
}
|
|
1407
|
+
|
|
1408
|
+
function setDisposingReadable(stream, aesCrypto) {
|
|
1409
|
+
const reader = stream.readable.getReader();
|
|
1410
|
+
const readable = new ReadableStream({
|
|
1411
|
+
async pull(controller) {
|
|
1412
|
+
try {
|
|
1413
|
+
const { value, done } = await reader.read();
|
|
1414
|
+
if (done) {
|
|
1415
|
+
controller.close();
|
|
1416
|
+
} else {
|
|
1417
|
+
controller.enqueue(value);
|
|
1418
|
+
}
|
|
1419
|
+
} catch (error) {
|
|
1420
|
+
disposeEngine(aesCrypto);
|
|
1421
|
+
reader.cancel(error).catch(() => { });
|
|
1422
|
+
throw error;
|
|
1423
|
+
}
|
|
1424
|
+
},
|
|
1425
|
+
cancel(reason) {
|
|
1426
|
+
disposeEngine(aesCrypto);
|
|
1427
|
+
return reader.cancel(reason);
|
|
1428
|
+
}
|
|
1429
|
+
});
|
|
1430
|
+
Object.defineProperty(stream, "readable", {
|
|
1431
|
+
get() {
|
|
1432
|
+
return readable;
|
|
1433
|
+
}
|
|
1395
1434
|
});
|
|
1396
1435
|
}
|
|
1397
1436
|
|
|
@@ -1424,7 +1463,9 @@
|
|
|
1424
1463
|
}
|
|
1425
1464
|
}
|
|
1426
1465
|
|
|
1427
|
-
function disposeEngine(
|
|
1466
|
+
function disposeEngine(aesCrypto) {
|
|
1467
|
+
const { engine } = aesCrypto;
|
|
1468
|
+
aesCrypto.discarded = true;
|
|
1428
1469
|
if (engine && engine.dispose) {
|
|
1429
1470
|
engine.dispose();
|
|
1430
1471
|
}
|
|
@@ -1441,6 +1482,9 @@
|
|
|
1441
1482
|
const keyLength = KEY_LENGTH[strength];
|
|
1442
1483
|
const compositeKey = await deriveKey(password, salt, keyLength * 2 + PASSWORD_VERIFICATION_LENGTH);
|
|
1443
1484
|
aesCrypto.engine = createEngine(subarray(compositeKey, 0, keyLength), subarray(compositeKey, keyLength, keyLength * 2));
|
|
1485
|
+
if (aesCrypto.discarded) {
|
|
1486
|
+
disposeEngine(aesCrypto);
|
|
1487
|
+
}
|
|
1444
1488
|
return subarray(compositeKey, keyLength * 2);
|
|
1445
1489
|
}
|
|
1446
1490
|
|
|
@@ -1592,11 +1636,11 @@
|
|
|
1592
1636
|
}
|
|
1593
1637
|
|
|
1594
1638
|
function createKeys(target, password, rawPassword) {
|
|
1595
|
-
const
|
|
1639
|
+
const cryptoKeys = [0x12345678, 0x23456789, 0x34567890];
|
|
1596
1640
|
Object.assign(target, {
|
|
1597
|
-
|
|
1598
|
-
crcKey0: new Crc32(
|
|
1599
|
-
crcKey2: new Crc32(
|
|
1641
|
+
cryptoKeys,
|
|
1642
|
+
crcKey0: new Crc32(cryptoKeys[0]),
|
|
1643
|
+
crcKey2: new Crc32(cryptoKeys[2])
|
|
1600
1644
|
});
|
|
1601
1645
|
if (rawPassword) {
|
|
1602
1646
|
for (let index = 0; index < rawPassword.length; index++) {
|
|
@@ -1610,17 +1654,17 @@
|
|
|
1610
1654
|
}
|
|
1611
1655
|
|
|
1612
1656
|
function updateKeys(target, byte) {
|
|
1613
|
-
let [, key1] = target.
|
|
1657
|
+
let [, key1] = target.cryptoKeys;
|
|
1614
1658
|
target.crcKey0.append([byte]);
|
|
1615
1659
|
const key0 = ~target.crcKey0.get();
|
|
1616
1660
|
key1 = getInt32(Math.imul(getInt32(key1 + getInt8(key0)), 134775813) + 1);
|
|
1617
1661
|
target.crcKey2.append([key1 >>> 24]);
|
|
1618
1662
|
const key2 = ~target.crcKey2.get();
|
|
1619
|
-
target.
|
|
1663
|
+
target.cryptoKeys = [key0, key1, key2];
|
|
1620
1664
|
}
|
|
1621
1665
|
|
|
1622
1666
|
function getByte(target) {
|
|
1623
|
-
const temp = target.
|
|
1667
|
+
const temp = target.cryptoKeys[2] | 2;
|
|
1624
1668
|
return getInt8(Math.imul(temp, (temp ^ 1)) >>> 8);
|
|
1625
1669
|
}
|
|
1626
1670
|
|
|
@@ -1668,11 +1712,16 @@
|
|
|
1668
1712
|
const reader = readable.getReader();
|
|
1669
1713
|
return new ReadableStream({
|
|
1670
1714
|
async pull(controller) {
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1715
|
+
try {
|
|
1716
|
+
const { value, done } = await reader.read();
|
|
1717
|
+
if (done) {
|
|
1718
|
+
controller.close();
|
|
1719
|
+
} else {
|
|
1720
|
+
controller.enqueue(value);
|
|
1721
|
+
}
|
|
1722
|
+
} catch (error) {
|
|
1723
|
+
reader.cancel(error).catch(() => { });
|
|
1724
|
+
throw error;
|
|
1676
1725
|
}
|
|
1677
1726
|
},
|
|
1678
1727
|
cancel(reason) {
|
|
@@ -1858,7 +1907,6 @@
|
|
|
1858
1907
|
const GZIP_HEADER_LENGTH = 10;
|
|
1859
1908
|
const GZIP_TRAILER_LENGTH = 8;
|
|
1860
1909
|
const GZIP_HEADER_BYTES = [0x1f, 0x8b, 0x08];
|
|
1861
|
-
const GZIP_OUTPUT_STALL_TIMEOUT = 5000;
|
|
1862
1910
|
|
|
1863
1911
|
class DeflateStream extends TransformStream {
|
|
1864
1912
|
|
|
@@ -1869,7 +1917,7 @@
|
|
|
1869
1917
|
let crc32Stream, encryptionStream, gzipCrc32Stream;
|
|
1870
1918
|
let readable = super.readable;
|
|
1871
1919
|
const codecStreams = format && getCodecStreams(format);
|
|
1872
|
-
const GzipCompressionStream =
|
|
1920
|
+
const GzipCompressionStream = getGzipCodecStream(useCompressionStream, CompressionStream, CompressionStreamFallback);
|
|
1873
1921
|
const useGzipCrc32 = computeCrc32 && compressed && !deflate64 && !codecStreams && (!encrypted || zipCrypto) && Boolean(GzipCompressionStream);
|
|
1874
1922
|
if ((!encrypted || zipCrypto) && computeCrc32 && !useGzipCrc32) {
|
|
1875
1923
|
crc32Stream = new Crc32Stream();
|
|
@@ -1886,6 +1934,9 @@
|
|
|
1886
1934
|
try {
|
|
1887
1935
|
readable = pipeThroughCompressionStream(readable, useCompressionStream, { level, chunkSize }, CompressionStream, CompressionStreamFallback);
|
|
1888
1936
|
} catch (error) {
|
|
1937
|
+
if (!useCompressionStream && CompressionStreamFallback) {
|
|
1938
|
+
throw error;
|
|
1939
|
+
}
|
|
1889
1940
|
let gzipStream;
|
|
1890
1941
|
try {
|
|
1891
1942
|
gzipStream = new CompressionStream(FORMAT_GZIP);
|
|
@@ -1955,74 +2006,134 @@
|
|
|
1955
2006
|
}
|
|
1956
2007
|
|
|
1957
2008
|
function pipeThroughGzipDecompressionStream(readable, gzipStream, outputSize, crc32) {
|
|
2009
|
+
const writer = gzipStream.writable.getWriter();
|
|
2010
|
+
const reader = gzipStream.readable.getReader();
|
|
2011
|
+
const outputCrc32 = crc32 === UNDEFINED_VALUE ? new Crc32() : UNDEFINED_VALUE;
|
|
1958
2012
|
let outputLength = 0;
|
|
1959
2013
|
let inputDone = false;
|
|
1960
|
-
let
|
|
2014
|
+
let trailerWritten = false;
|
|
2015
|
+
let idleCheckArmed = false;
|
|
2016
|
+
let readCount = 0;
|
|
2017
|
+
let readPending = false;
|
|
1961
2018
|
let resolveTrailerReady, rejectTrailerReady;
|
|
1962
2019
|
const trailerReady = new Promise((resolve, reject) => {
|
|
1963
2020
|
resolveTrailerReady = resolve;
|
|
1964
2021
|
rejectTrailerReady = reject;
|
|
1965
2022
|
});
|
|
1966
2023
|
trailerReady.catch(() => { });
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
2024
|
+
pump();
|
|
2025
|
+
return new ReadableStream({
|
|
2026
|
+
async pull(controller) {
|
|
2027
|
+
try {
|
|
2028
|
+
const { value, done } = await read();
|
|
2029
|
+
if (done) {
|
|
2030
|
+
controller.close();
|
|
2031
|
+
} else {
|
|
2032
|
+
outputLength += value.length;
|
|
2033
|
+
if (outputLength > outputSize) {
|
|
2034
|
+
throw new Error(ERR_INVALID_UNCOMPRESSED_SIZE);
|
|
2035
|
+
}
|
|
2036
|
+
if (outputCrc32) {
|
|
2037
|
+
outputCrc32.append(value);
|
|
2038
|
+
}
|
|
2039
|
+
controller.enqueue(value);
|
|
2040
|
+
}
|
|
2041
|
+
} catch (error) {
|
|
2042
|
+
rejectTrailerReady(error);
|
|
2043
|
+
await cancel(reader, error);
|
|
2044
|
+
throw trailerWritten ? getTrailerError(error) : error;
|
|
2045
|
+
}
|
|
2046
|
+
},
|
|
2047
|
+
cancel(reason) {
|
|
2048
|
+
rejectTrailerReady(reason);
|
|
2049
|
+
return reader.cancel(reason);
|
|
2050
|
+
}
|
|
2051
|
+
});
|
|
2052
|
+
|
|
2053
|
+
async function pump() {
|
|
2054
|
+
const inputReader = readable.getReader();
|
|
2055
|
+
try {
|
|
1972
2056
|
const header = new Uint8Array(GZIP_HEADER_LENGTH);
|
|
1973
2057
|
header.set(GZIP_HEADER_BYTES);
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
2058
|
+
await writer.write(header);
|
|
2059
|
+
for (; ;) {
|
|
2060
|
+
await writer.ready;
|
|
2061
|
+
const { value, done } = await inputReader.read();
|
|
2062
|
+
if (done) {
|
|
2063
|
+
break;
|
|
2064
|
+
}
|
|
2065
|
+
await writer.write(value);
|
|
2066
|
+
}
|
|
1980
2067
|
inputDone = true;
|
|
1981
|
-
|
|
1982
|
-
|
|
2068
|
+
if (outputCrc32) {
|
|
2069
|
+
if (readPending) {
|
|
2070
|
+
armIdleCheck();
|
|
2071
|
+
}
|
|
1983
2072
|
await trailerReady;
|
|
1984
|
-
} finally {
|
|
1985
|
-
stopWatchdog();
|
|
1986
2073
|
}
|
|
1987
2074
|
const trailer = new Uint8Array(GZIP_TRAILER_LENGTH);
|
|
1988
2075
|
const dataView = getDataView(trailer);
|
|
1989
|
-
dataView.setUint32(0,
|
|
2076
|
+
dataView.setUint32(0, outputCrc32 ? outputCrc32.get() : crc32, true);
|
|
1990
2077
|
dataView.setUint32(4, outputSize, true);
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
2078
|
+
trailerWritten = true;
|
|
2079
|
+
await writer.write(trailer);
|
|
2080
|
+
await writer.close();
|
|
2081
|
+
} catch (error) {
|
|
2082
|
+
await abort(writer, error);
|
|
2083
|
+
await cancel(inputReader, error);
|
|
1995
2084
|
}
|
|
1996
|
-
}
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
}
|
|
2006
|
-
controller.enqueue(chunk);
|
|
2007
|
-
},
|
|
2008
|
-
cancel(reason) {
|
|
2009
|
-
rejectTrailerReady(reason);
|
|
2085
|
+
}
|
|
2086
|
+
|
|
2087
|
+
function read() {
|
|
2088
|
+
readCount++;
|
|
2089
|
+
readPending = true;
|
|
2090
|
+
const result = reader.read();
|
|
2091
|
+
result.then(onReadSettled, onReadSettled);
|
|
2092
|
+
if (inputDone && outputCrc32) {
|
|
2093
|
+
armIdleCheck();
|
|
2010
2094
|
}
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
readable = pipeThroughBackpressured(readable, gzipStream);
|
|
2014
|
-
return pipeThrough(readable, outputStream);
|
|
2095
|
+
return result;
|
|
2096
|
+
}
|
|
2015
2097
|
|
|
2016
|
-
function
|
|
2017
|
-
|
|
2018
|
-
watchdogTimeout = setTimeout(() => rejectTrailerReady(new Error(ERR_INVALID_UNCOMPRESSED_SIZE)), GZIP_OUTPUT_STALL_TIMEOUT);
|
|
2098
|
+
function onReadSettled() {
|
|
2099
|
+
readPending = false;
|
|
2019
2100
|
}
|
|
2020
2101
|
|
|
2021
|
-
function
|
|
2022
|
-
|
|
2102
|
+
async function armIdleCheck() {
|
|
2103
|
+
if (!idleCheckArmed) {
|
|
2104
|
+
idleCheckArmed = true;
|
|
2105
|
+
const count = readCount;
|
|
2106
|
+
await nextTask();
|
|
2107
|
+
idleCheckArmed = false;
|
|
2108
|
+
if (readPending) {
|
|
2109
|
+
if (readCount == count) {
|
|
2110
|
+
resolveTrailerReady();
|
|
2111
|
+
} else {
|
|
2112
|
+
armIdleCheck();
|
|
2113
|
+
}
|
|
2114
|
+
}
|
|
2115
|
+
}
|
|
2116
|
+
}
|
|
2117
|
+
|
|
2118
|
+
function getTrailerError(error) {
|
|
2119
|
+
const trailerError = new Error(outputLength == outputSize ? ERR_INVALID_CRC32 : ERR_INVALID_UNCOMPRESSED_SIZE);
|
|
2120
|
+
trailerError.cause = error;
|
|
2121
|
+
return trailerError;
|
|
2023
2122
|
}
|
|
2024
2123
|
}
|
|
2025
2124
|
|
|
2125
|
+
function nextTask() {
|
|
2126
|
+
return new Promise(resolve => {
|
|
2127
|
+
const { port1, port2 } = new MessageChannel();
|
|
2128
|
+
port2.onmessage = () => {
|
|
2129
|
+
port1.close();
|
|
2130
|
+
port2.close();
|
|
2131
|
+
resolve();
|
|
2132
|
+
};
|
|
2133
|
+
port1.postMessage(UNDEFINED_VALUE);
|
|
2134
|
+
});
|
|
2135
|
+
}
|
|
2136
|
+
|
|
2026
2137
|
class InflateStream extends TransformStream {
|
|
2027
2138
|
|
|
2028
2139
|
constructor(options, { chunkSize, DecompressionStreamFallback, DecompressionStream }) {
|
|
@@ -2043,20 +2154,32 @@
|
|
|
2043
2154
|
if (codecStreams) {
|
|
2044
2155
|
readable = pipeThroughBackpressured(readable, createCodecStream(codecStreams.DecompressionStream, format, { chunkSize, compressionMethod, rawBitFlag, uncompressedSize: outputSize }));
|
|
2045
2156
|
} else {
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
if (deflate64 || outputSize === UNDEFINED_VALUE) {
|
|
2050
|
-
throw error;
|
|
2051
|
-
}
|
|
2052
|
-
let gzipStream;
|
|
2157
|
+
let gzipStream;
|
|
2158
|
+
const GzipDecompressionStream = getGzipCodecStream(useCompressionStream, DecompressionStream, DecompressionStreamFallback);
|
|
2159
|
+
if (checkCrc32 && !deflate64 && crc32 !== UNDEFINED_VALUE && outputSize !== UNDEFINED_VALUE && GzipDecompressionStream) {
|
|
2053
2160
|
try {
|
|
2054
|
-
gzipStream = new
|
|
2161
|
+
gzipStream = new GzipDecompressionStream(FORMAT_GZIP, { chunkSize });
|
|
2055
2162
|
} catch {
|
|
2056
|
-
|
|
2163
|
+
gzipStream = UNDEFINED_VALUE;
|
|
2057
2164
|
}
|
|
2058
|
-
|
|
2059
|
-
|
|
2165
|
+
}
|
|
2166
|
+
if (!gzipStream) {
|
|
2167
|
+
try {
|
|
2168
|
+
readable = pipeThroughCompressionStream(readable, useCompressionStream, { chunkSize, deflate64 }, DecompressionStream, DecompressionStreamFallback);
|
|
2169
|
+
} catch (error) {
|
|
2170
|
+
if (deflate64 || outputSize === UNDEFINED_VALUE || (!useCompressionStream && DecompressionStreamFallback)) {
|
|
2171
|
+
throw error;
|
|
2172
|
+
}
|
|
2173
|
+
try {
|
|
2174
|
+
gzipStream = new DecompressionStream(FORMAT_GZIP);
|
|
2175
|
+
} catch {
|
|
2176
|
+
throw error;
|
|
2177
|
+
}
|
|
2178
|
+
}
|
|
2179
|
+
}
|
|
2180
|
+
if (gzipStream) {
|
|
2181
|
+
gzipCrc32 = true;
|
|
2182
|
+
readable = pipeThroughGzipDecompressionStream(readable, gzipStream, outputSize, crc32);
|
|
2060
2183
|
}
|
|
2061
2184
|
}
|
|
2062
2185
|
readable = mapInflateStreamError(readable);
|
|
@@ -2066,8 +2189,8 @@
|
|
|
2066
2189
|
readable = pipeThrough(readable, crc32Stream);
|
|
2067
2190
|
}
|
|
2068
2191
|
setReadable(this, readable, () => {
|
|
2069
|
-
if (
|
|
2070
|
-
const computedCrc32 =
|
|
2192
|
+
if (crc32Stream) {
|
|
2193
|
+
const computedCrc32 = new DataView(crc32Stream.value.buffer).getUint32(0, false);
|
|
2071
2194
|
if (crc32 != computedCrc32) {
|
|
2072
2195
|
throw new Error(ERR_INVALID_CRC32);
|
|
2073
2196
|
}
|
|
@@ -2124,11 +2247,11 @@
|
|
|
2124
2247
|
return new CodecStreamClass(format, options);
|
|
2125
2248
|
}
|
|
2126
2249
|
|
|
2127
|
-
function
|
|
2128
|
-
if (useCompressionStream &&
|
|
2129
|
-
return
|
|
2130
|
-
} else if (
|
|
2131
|
-
return
|
|
2250
|
+
function getGzipCodecStream(useCompressionStream, CodecStreamNative, CodecStreamFallback) {
|
|
2251
|
+
if (useCompressionStream && CodecStreamNative) {
|
|
2252
|
+
return CodecStreamNative;
|
|
2253
|
+
} else if (CodecStreamFallback && CodecStreamFallback.requiresModule) {
|
|
2254
|
+
return CodecStreamFallback;
|
|
2132
2255
|
}
|
|
2133
2256
|
}
|
|
2134
2257
|
|
|
@@ -2198,10 +2321,15 @@
|
|
|
2198
2321
|
const reader = readable.getReader();
|
|
2199
2322
|
return new ReadableStream({
|
|
2200
2323
|
async pull(controller) {
|
|
2201
|
-
let result;
|
|
2202
2324
|
try {
|
|
2203
|
-
|
|
2325
|
+
const { value, done } = await reader.read();
|
|
2326
|
+
if (done) {
|
|
2327
|
+
controller.close();
|
|
2328
|
+
} else {
|
|
2329
|
+
controller.enqueue(value);
|
|
2330
|
+
}
|
|
2204
2331
|
} catch (error) {
|
|
2332
|
+
await cancel(reader, error);
|
|
2205
2333
|
if (error && error.message) {
|
|
2206
2334
|
throw error;
|
|
2207
2335
|
}
|
|
@@ -2209,12 +2337,6 @@
|
|
|
2209
2337
|
mappedError.cause = error;
|
|
2210
2338
|
throw mappedError;
|
|
2211
2339
|
}
|
|
2212
|
-
const { value, done } = result;
|
|
2213
|
-
if (done) {
|
|
2214
|
-
controller.close();
|
|
2215
|
-
} else {
|
|
2216
|
-
controller.enqueue(value);
|
|
2217
|
-
}
|
|
2218
2340
|
},
|
|
2219
2341
|
cancel(reason) {
|
|
2220
2342
|
return reader.cancel(reason);
|
|
@@ -3726,10 +3848,11 @@
|
|
|
3726
3848
|
|
|
3727
3849
|
createReadable(options) {
|
|
3728
3850
|
const reader = this;
|
|
3729
|
-
const { useRangeHeader, forceRangeRequests, size } = reader;
|
|
3851
|
+
const { useRangeHeader, forceRangeRequests, size, eocdCache } = reader;
|
|
3730
3852
|
if ((useRangeHeader || forceRangeRequests) && size !== UNDEFINED_VALUE) {
|
|
3731
3853
|
const { offset = 0, size: readSize = size - offset } = options || {};
|
|
3732
|
-
|
|
3854
|
+
const cached = eocdCache && offset >= size - eocdCache.length;
|
|
3855
|
+
if (readSize > 0 && offset < size && !cached) {
|
|
3733
3856
|
return createRangeReadable(reader, offset, Math.min(readSize, size - offset));
|
|
3734
3857
|
}
|
|
3735
3858
|
}
|
|
@@ -5288,8 +5411,8 @@
|
|
|
5288
5411
|
const passThroughCompression = Boolean(passThrough);
|
|
5289
5412
|
const passThroughEncryption = passThrough === true;
|
|
5290
5413
|
checkPasswordOption(password, rawPassword);
|
|
5291
|
-
password = password && password.length
|
|
5292
|
-
rawPassword = rawPassword && rawPassword.length
|
|
5414
|
+
password = password && password.length ? password : UNDEFINED_VALUE;
|
|
5415
|
+
rawPassword = rawPassword && rawPassword.length ? rawPassword : UNDEFINED_VALUE;
|
|
5293
5416
|
if (extraFieldAES) {
|
|
5294
5417
|
if (extraFieldAES.originalCompressionMethod != COMPRESSION_METHOD_AES) {
|
|
5295
5418
|
throw new Error(ERR_UNSUPPORTED_COMPRESSION);
|
|
@@ -6050,7 +6173,7 @@
|
|
|
6050
6173
|
async function findEndOfCentralDirectory(reader, rejectAmbiguous, maxAppendedDataSize) {
|
|
6051
6174
|
const { size } = reader;
|
|
6052
6175
|
const anchoredLength = Math.min(size, END_OF_CENTRAL_DIR_LENGTH + MAX_16_BITS);
|
|
6053
|
-
const remoteProbeBudget = {
|
|
6176
|
+
const remoteProbeBudget = { remaining: MAX_END_OF_CENTRAL_DIR_PROBES };
|
|
6054
6177
|
let endOfDirectoryInfo;
|
|
6055
6178
|
let plausibleEndOfDirectoryInfo;
|
|
6056
6179
|
let endOfDirectoryReachingEndCount = 0;
|
|
@@ -6143,8 +6266,8 @@
|
|
|
6143
6266
|
if (signatureOffset >= anchoredOffset) {
|
|
6144
6267
|
return getUint32$1(view, signatureOffset - anchoredOffset);
|
|
6145
6268
|
}
|
|
6146
|
-
if (remoteProbeBudget.
|
|
6147
|
-
remoteProbeBudget.
|
|
6269
|
+
if (remoteProbeBudget.remaining > 0) {
|
|
6270
|
+
remoteProbeBudget.remaining--;
|
|
6148
6271
|
const signatureArray = await readUint8Array(reader, signatureOffset, 4);
|
|
6149
6272
|
return getUint32$1(getDataView(signatureArray), 0);
|
|
6150
6273
|
}
|
|
@@ -7060,9 +7183,11 @@
|
|
|
7060
7183
|
const passThrough = checkPassThroughOption(getOptionValue(zipWriter, options, OPTION_PASS_THROUGH));
|
|
7061
7184
|
const passThroughCompression = Boolean(passThrough);
|
|
7062
7185
|
const passThroughEncryption = passThrough === true;
|
|
7063
|
-
|
|
7064
|
-
|
|
7186
|
+
let password = getOptionValue(zipWriter, options, OPTION_PASSWORD);
|
|
7187
|
+
let rawPassword = getOptionValue(zipWriter, options, OPTION_RAW_PASSWORD);
|
|
7065
7188
|
checkPasswordOption(password, rawPassword);
|
|
7189
|
+
password = password && password.length ? password : UNDEFINED_VALUE;
|
|
7190
|
+
rawPassword = rawPassword && rawPassword.length ? rawPassword : UNDEFINED_VALUE;
|
|
7066
7191
|
const encryptionStrength = getNumberOptionValue(zipWriter, options, OPTION_ENCRYPTION_STRENGTH, 3);
|
|
7067
7192
|
const zipCrypto = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIPCRYPTO);
|
|
7068
7193
|
const extendedTimestamp = getOptionValue(zipWriter, options, OPTION_EXTENDED_TIMESTAMP, true);
|
|
@@ -8858,7 +8983,7 @@
|
|
|
8858
8983
|
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
8859
8984
|
*/
|
|
8860
8985
|
|
|
8861
|
-
const VERSION = "2.
|
|
8986
|
+
const VERSION = "2.16.1";
|
|
8862
8987
|
|
|
8863
8988
|
/*
|
|
8864
8989
|
Copyright (c) 2025 Gildas Lormeau. All rights reserved.
|
|
@@ -9351,7 +9476,11 @@
|
|
|
9351
9476
|
const ERR_INVALID_PASS_THROUGH = "Invalid passThrough option (use readerOptions.passThrough or set uncompressedSize for each entry)";
|
|
9352
9477
|
const ERR_INVALID_READER_OPTIONS = "Invalid readerOptions (must be an object)";
|
|
9353
9478
|
const ERR_UNSUPPORTED_PASS_THROUGH_VALUE = "The 'compressed' passThrough option is only supported by Entry#getData() and ZipWriter#add()";
|
|
9479
|
+
const ERR_INVALID_PASSWORDS = "Invalid passwords option (must be an array of strings)";
|
|
9480
|
+
const ERR_INVALID_REQUEST_PASSWORD = "Invalid requestPassword option (must be a function returning a string or undefined)";
|
|
9354
9481
|
const ERR_ABORT_EXPORT = "zipjs-abort-export";
|
|
9482
|
+
const ABORT_ERROR_NAME = "AbortError";
|
|
9483
|
+
const EMPTY_RAW_PASSWORD = new Uint8Array(0);
|
|
9355
9484
|
|
|
9356
9485
|
class ZipEntry {
|
|
9357
9486
|
|
|
@@ -9724,8 +9853,10 @@
|
|
|
9724
9853
|
zipReader = new ZipReader(reader, options);
|
|
9725
9854
|
}
|
|
9726
9855
|
checkPassThroughValue(options.passThrough);
|
|
9856
|
+
checkPasswordCandidatesOptions(options);
|
|
9727
9857
|
const duplicates = checkDuplicatesOption(options.duplicates);
|
|
9728
9858
|
const importedEntries = [];
|
|
9859
|
+
const passwordState = { known: [] };
|
|
9729
9860
|
const entries = await zipReader.getEntries(options);
|
|
9730
9861
|
for (const entry of entries) {
|
|
9731
9862
|
let parent = this;
|
|
@@ -9770,7 +9901,7 @@
|
|
|
9770
9901
|
}
|
|
9771
9902
|
importedEntries.push(addChild(parent, name, {
|
|
9772
9903
|
data: entry,
|
|
9773
|
-
Reader: getZipBlobReader(Object.assign({}, options)),
|
|
9904
|
+
Reader: getZipBlobReader(Object.assign({}, options), passwordState),
|
|
9774
9905
|
uncompressedSize: options.passThrough ? entry.compressedSize : entry.uncompressedSize,
|
|
9775
9906
|
passThrough: options.passThrough
|
|
9776
9907
|
}));
|
|
@@ -10099,7 +10230,7 @@
|
|
|
10099
10230
|
};
|
|
10100
10231
|
}
|
|
10101
10232
|
|
|
10102
|
-
function getZipBlobReader(options) {
|
|
10233
|
+
function getZipBlobReader(options, passwordState) {
|
|
10103
10234
|
return class extends Reader {
|
|
10104
10235
|
|
|
10105
10236
|
constructor(entry, options = {}) {
|
|
@@ -10112,12 +10243,12 @@
|
|
|
10112
10243
|
const zipBlobReader = this;
|
|
10113
10244
|
const readerOptions = Object.assign({}, options, zipBlobReader.options);
|
|
10114
10245
|
const { checkOverlappingEntry, checkOverlappingEntryOnly } = readerOptions;
|
|
10115
|
-
const data = await zipBlobReader.entry
|
|
10246
|
+
const data = await readEntryData(zipBlobReader.entry, Object.assign(readerOptions, {
|
|
10116
10247
|
checkPasswordOnly: false,
|
|
10117
10248
|
checkOverlappingEntry: checkOverlappingEntryOnly || checkOverlappingEntry,
|
|
10118
10249
|
checkOverlappingEntryOnly: false,
|
|
10119
10250
|
preventClose: false
|
|
10120
|
-
}));
|
|
10251
|
+
}), passwordState);
|
|
10121
10252
|
zipBlobReader.data = data;
|
|
10122
10253
|
zipBlobReader.blobReader = new BlobReader(data);
|
|
10123
10254
|
zipBlobReader.size = data.size;
|
|
@@ -10179,10 +10310,9 @@
|
|
|
10179
10310
|
await initStream(reader);
|
|
10180
10311
|
} catch (error) {
|
|
10181
10312
|
try {
|
|
10313
|
+
error.entry = child;
|
|
10182
10314
|
error.entryId = child.id;
|
|
10183
|
-
error.
|
|
10184
|
-
entry: child
|
|
10185
|
-
};
|
|
10315
|
+
error.entryName = child.getRelativeName(entry);
|
|
10186
10316
|
} catch {
|
|
10187
10317
|
// ignored
|
|
10188
10318
|
}
|
|
@@ -10274,10 +10404,136 @@
|
|
|
10274
10404
|
}
|
|
10275
10405
|
if (readerOptions) {
|
|
10276
10406
|
checkPassThroughValue(readerOptions.passThrough);
|
|
10407
|
+
checkPasswordCandidatesOptions(readerOptions);
|
|
10277
10408
|
}
|
|
10278
10409
|
return readerOptions;
|
|
10279
10410
|
}
|
|
10280
10411
|
|
|
10412
|
+
function checkPasswordCandidatesOptions(options) {
|
|
10413
|
+
const { passwords, requestPassword } = options;
|
|
10414
|
+
if (passwords && (!Array.isArray(passwords) || passwords.some(password => typeof password != STRING_TYPE))) {
|
|
10415
|
+
throw new Error(ERR_INVALID_PASSWORDS);
|
|
10416
|
+
}
|
|
10417
|
+
if (requestPassword && typeof requestPassword != FUNCTION_TYPE) {
|
|
10418
|
+
throw new Error(ERR_INVALID_REQUEST_PASSWORD);
|
|
10419
|
+
}
|
|
10420
|
+
}
|
|
10421
|
+
|
|
10422
|
+
async function readEntryData(entry, options, passwordState) {
|
|
10423
|
+
checkPasswordCandidatesOptions(options);
|
|
10424
|
+
const { passwords, requestPassword, signal } = options;
|
|
10425
|
+
options = Object.assign({}, options);
|
|
10426
|
+
delete options.passwords;
|
|
10427
|
+
delete options.requestPassword;
|
|
10428
|
+
if (!entry.encrypted || options.passThrough || (!passwords && !requestPassword)) {
|
|
10429
|
+
return entry.getData(new BlobWriter(), options);
|
|
10430
|
+
}
|
|
10431
|
+
const tried = new Set();
|
|
10432
|
+
let error;
|
|
10433
|
+
while (true) {
|
|
10434
|
+
for (const candidate of getPasswordCandidates(options, passwordState, passwords)) {
|
|
10435
|
+
if (!tried.has(candidate.key)) {
|
|
10436
|
+
const result = await tryPasswordCandidate(candidate);
|
|
10437
|
+
if (result.done) {
|
|
10438
|
+
return result.data;
|
|
10439
|
+
}
|
|
10440
|
+
error = result.error;
|
|
10441
|
+
}
|
|
10442
|
+
}
|
|
10443
|
+
if (!requestPassword) {
|
|
10444
|
+
break;
|
|
10445
|
+
}
|
|
10446
|
+
if (passwordState.pendingPrompt) {
|
|
10447
|
+
await passwordState.pendingPrompt;
|
|
10448
|
+
continue;
|
|
10449
|
+
}
|
|
10450
|
+
let release;
|
|
10451
|
+
passwordState.pendingPrompt = new Promise(resolve => release = resolve);
|
|
10452
|
+
try {
|
|
10453
|
+
const answer = await requestPassword(entry, error);
|
|
10454
|
+
if (answer === UNDEFINED_VALUE || answer === null) {
|
|
10455
|
+
break;
|
|
10456
|
+
}
|
|
10457
|
+
// deno-lint-ignore valid-typeof
|
|
10458
|
+
if (typeof answer != STRING_TYPE) {
|
|
10459
|
+
throw new Error(ERR_INVALID_REQUEST_PASSWORD);
|
|
10460
|
+
}
|
|
10461
|
+
const result = await tryPasswordCandidate(getPasswordCandidate(answer));
|
|
10462
|
+
if (result.done) {
|
|
10463
|
+
return result.data;
|
|
10464
|
+
}
|
|
10465
|
+
error = result.error;
|
|
10466
|
+
} finally {
|
|
10467
|
+
passwordState.pendingPrompt = UNDEFINED_VALUE;
|
|
10468
|
+
release();
|
|
10469
|
+
}
|
|
10470
|
+
}
|
|
10471
|
+
throw new Error(tried.size ? ERR_INVALID_PASSWORD : ERR_ENCRYPTED);
|
|
10472
|
+
|
|
10473
|
+
async function tryPasswordCandidate(candidate) {
|
|
10474
|
+
tried.add(candidate.key);
|
|
10475
|
+
const candidateOptions = Object.assign({}, options, candidate.options);
|
|
10476
|
+
if (entry.zipCrypto) {
|
|
10477
|
+
candidateOptions.checkCrc32 = true;
|
|
10478
|
+
try {
|
|
10479
|
+
await entry.getData(null, Object.assign({}, candidateOptions, { checkPasswordOnly: true }));
|
|
10480
|
+
} catch (probeError) {
|
|
10481
|
+
if (isInvalidPasswordError(probeError)) {
|
|
10482
|
+
return { done: false, error: probeError };
|
|
10483
|
+
}
|
|
10484
|
+
throw probeError;
|
|
10485
|
+
}
|
|
10486
|
+
}
|
|
10487
|
+
try {
|
|
10488
|
+
const data = await entry.getData(new BlobWriter(), candidateOptions);
|
|
10489
|
+
rememberPassword(passwordState, candidate);
|
|
10490
|
+
return { done: true, data };
|
|
10491
|
+
} catch (readError) {
|
|
10492
|
+
if (isAbortError(readError, signal) || (!entry.zipCrypto && !isInvalidPasswordError(readError))) {
|
|
10493
|
+
throw readError;
|
|
10494
|
+
}
|
|
10495
|
+
return { done: false, error: readError };
|
|
10496
|
+
}
|
|
10497
|
+
}
|
|
10498
|
+
}
|
|
10499
|
+
|
|
10500
|
+
function isInvalidPasswordError(error) {
|
|
10501
|
+
return isErrorObject(error) && error.message == ERR_INVALID_PASSWORD;
|
|
10502
|
+
}
|
|
10503
|
+
|
|
10504
|
+
function isAbortError(error, signal) {
|
|
10505
|
+
return Boolean(signal && signal.aborted) || (isErrorObject(error) && error.name == ABORT_ERROR_NAME);
|
|
10506
|
+
}
|
|
10507
|
+
|
|
10508
|
+
function getPasswordCandidates(options, passwordState, passwords) {
|
|
10509
|
+
const candidates = [];
|
|
10510
|
+
const { password, rawPassword } = options;
|
|
10511
|
+
if (rawPassword && rawPassword.length) {
|
|
10512
|
+
candidates.push({ key: rawPassword, options: { password: "", rawPassword } });
|
|
10513
|
+
}
|
|
10514
|
+
if (password) {
|
|
10515
|
+
candidates.push(getPasswordCandidate(password));
|
|
10516
|
+
}
|
|
10517
|
+
candidates.push(...passwordState.known);
|
|
10518
|
+
if (passwords) {
|
|
10519
|
+
candidates.push(...passwords.filter(password => password).map(getPasswordCandidate));
|
|
10520
|
+
}
|
|
10521
|
+
return candidates;
|
|
10522
|
+
}
|
|
10523
|
+
|
|
10524
|
+
function getPasswordCandidate(password) {
|
|
10525
|
+
return { key: password, options: { password, rawPassword: EMPTY_RAW_PASSWORD } };
|
|
10526
|
+
}
|
|
10527
|
+
|
|
10528
|
+
function rememberPassword(passwordState, candidate) {
|
|
10529
|
+
const { known } = passwordState;
|
|
10530
|
+
const index = known.findIndex(knownCandidate => knownCandidate.key === candidate.key);
|
|
10531
|
+
if (index != -1) {
|
|
10532
|
+
known.splice(index, 1);
|
|
10533
|
+
}
|
|
10534
|
+
known.unshift(candidate);
|
|
10535
|
+
}
|
|
10536
|
+
|
|
10281
10537
|
function checkPassThroughValue(passThrough) {
|
|
10282
10538
|
if (checkPassThroughOption(passThrough) === PASS_THROUGH_COMPRESSED) {
|
|
10283
10539
|
throw new Error(ERR_UNSUPPORTED_PASS_THROUGH_VALUE);
|
|
@@ -10415,6 +10671,7 @@
|
|
|
10415
10671
|
async function exportFileSystemHandle(zipEntry, directoryHandle, options) {
|
|
10416
10672
|
const { onstart, onprogress, onend } = options;
|
|
10417
10673
|
checkPassThroughValue(options.passThrough);
|
|
10674
|
+
checkPasswordCandidatesOptions(options);
|
|
10418
10675
|
const readerOptions = checkReaderOptions(options.readerOptions);
|
|
10419
10676
|
const abortController = new AbortController();
|
|
10420
10677
|
const { signal } = abortController;
|
|
@@ -10713,11 +10970,13 @@
|
|
|
10713
10970
|
exports.ERR_INVALID_MSDOS_ATTRIBUTES = ERR_INVALID_MSDOS_ATTRIBUTES;
|
|
10714
10971
|
exports.ERR_INVALID_MSDOS_DATA = ERR_INVALID_MSDOS_DATA;
|
|
10715
10972
|
exports.ERR_INVALID_PASSWORD = ERR_INVALID_PASSWORD;
|
|
10973
|
+
exports.ERR_INVALID_PASSWORDS = ERR_INVALID_PASSWORDS;
|
|
10716
10974
|
exports.ERR_INVALID_PASSWORD_TYPE = ERR_INVALID_PASSWORD_TYPE;
|
|
10717
10975
|
exports.ERR_INVALID_PASS_THROUGH = ERR_INVALID_PASS_THROUGH;
|
|
10718
10976
|
exports.ERR_INVALID_PASS_THROUGH_VALUE = ERR_INVALID_PASS_THROUGH_VALUE;
|
|
10719
10977
|
exports.ERR_INVALID_READER = ERR_INVALID_READER;
|
|
10720
10978
|
exports.ERR_INVALID_READER_OPTIONS = ERR_INVALID_READER_OPTIONS;
|
|
10979
|
+
exports.ERR_INVALID_REQUEST_PASSWORD = ERR_INVALID_REQUEST_PASSWORD;
|
|
10721
10980
|
exports.ERR_INVALID_SIGNAL = ERR_INVALID_SIGNAL;
|
|
10722
10981
|
exports.ERR_INVALID_SIGNATURE_DATA = ERR_INVALID_SIGNATURE_DATA;
|
|
10723
10982
|
exports.ERR_INVALID_STRICTNESS = ERR_INVALID_STRICTNESS;
|