@zip.js/zip.js 2.16.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/deno.json +1 -1
- package/dist/zip-core-external.js +284 -179
- package/dist/zip-core-external.min.js +1 -1
- package/dist/zip-core.js +108 -61
- package/dist/zip-core.min.js +1 -1
- package/dist/zip-fs-core-external.js +426 -189
- package/dist/zip-fs-core-external.min.js +1 -1
- package/dist/zip-fs-core.js +251 -70
- package/dist/zip-fs-core.min.js +1 -1
- package/dist/zip-fs-external.js +426 -189
- package/dist/zip-fs-external.min.js +1 -1
- package/dist/zip-fs-native.js +253 -72
- package/dist/zip-fs-native.min.js +1 -1
- package/dist/zip-fs.js +428 -189
- package/dist/zip-fs.min.js +1 -1
- package/dist/zip-legacy.js +110 -63
- package/dist/zip-legacy.min.js +1 -1
- package/dist/zip-native.js +110 -63
- 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 +285 -180
- package/dist/zip.min.js +1 -1
- package/eslint.config.mjs +1 -1
- package/index-native.cjs +253 -72
- package/index-native.min.js +1 -1
- package/index.cjs +428 -189
- package/index.d.cts +117 -16
- package/index.d.ts +117 -16
- package/index.min.js +1 -1
- 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 +22 -26
- 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
|
@@ -214,7 +214,7 @@ const ERR_INVALID_SIGNAL = "Invalid signal (must be an AbortSignal instance)";
|
|
|
214
214
|
const ERR_INVALID_PASSWORD_TYPE = "Invalid password (password must be a string, rawPassword must be a Uint8Array)";
|
|
215
215
|
const ERR_INVALID_PASS_THROUGH_VALUE = "Invalid passThrough option (must be a boolean or 'compressed')";
|
|
216
216
|
const ERR_ABORTED = "The operation was aborted";
|
|
217
|
-
const ABORT_ERROR_NAME = "AbortError";
|
|
217
|
+
const ABORT_ERROR_NAME$1 = "AbortError";
|
|
218
218
|
|
|
219
219
|
function checkFunctionOption(value) {
|
|
220
220
|
if (value && typeof value != FUNCTION_TYPE) {
|
|
@@ -232,7 +232,7 @@ function checkSignalOption(signal) {
|
|
|
232
232
|
|
|
233
233
|
function throwIfAborted(signal) {
|
|
234
234
|
if (signal && signal.aborted) {
|
|
235
|
-
throw signal.reason === UNDEFINED_VALUE ? new DOMException(ERR_ABORTED, ABORT_ERROR_NAME) : signal.reason;
|
|
235
|
+
throw signal.reason === UNDEFINED_VALUE ? new DOMException(ERR_ABORTED, ABORT_ERROR_NAME$1) : signal.reason;
|
|
236
236
|
}
|
|
237
237
|
}
|
|
238
238
|
|
|
@@ -1310,12 +1310,12 @@ let createEngine$1 = createEngine$2;
|
|
|
1310
1310
|
class AESDecryptionStream extends TransformStream {
|
|
1311
1311
|
|
|
1312
1312
|
constructor({ password, rawPassword, encryptionStrength, checkPasswordOnly, checkAuthenticationCode = true }) {
|
|
1313
|
+
const aesCrypto = {};
|
|
1313
1314
|
super({
|
|
1314
1315
|
start() {
|
|
1315
|
-
initAesCrypto(
|
|
1316
|
+
initAesCrypto(aesCrypto, password, rawPassword, encryptionStrength);
|
|
1316
1317
|
},
|
|
1317
1318
|
async transform(chunk, controller) {
|
|
1318
|
-
const aesCrypto = this;
|
|
1319
1319
|
const {
|
|
1320
1320
|
password,
|
|
1321
1321
|
strength,
|
|
@@ -1334,6 +1334,9 @@ class AESDecryptionStream extends TransformStream {
|
|
|
1334
1334
|
} else {
|
|
1335
1335
|
await ready;
|
|
1336
1336
|
}
|
|
1337
|
+
if (aesCrypto.discarded) {
|
|
1338
|
+
return;
|
|
1339
|
+
}
|
|
1337
1340
|
const output = new Uint8Array(chunk.length - AUTHENTICATION_CODE_LENGTH - ((chunk.length - AUTHENTICATION_CODE_LENGTH) % BLOCK_LENGTH));
|
|
1338
1341
|
controller.enqueue(append(aesCrypto, chunk, output, 0, AUTHENTICATION_CODE_LENGTH, true));
|
|
1339
1342
|
},
|
|
@@ -1342,9 +1345,12 @@ class AESDecryptionStream extends TransformStream {
|
|
|
1342
1345
|
engine,
|
|
1343
1346
|
pendingInput,
|
|
1344
1347
|
ready
|
|
1345
|
-
} =
|
|
1348
|
+
} = aesCrypto;
|
|
1346
1349
|
if (engine) {
|
|
1347
1350
|
await ready;
|
|
1351
|
+
if (aesCrypto.discarded) {
|
|
1352
|
+
return;
|
|
1353
|
+
}
|
|
1348
1354
|
const originalAuthenticationCode = subarray(pendingInput, pendingInput.length - AUTHENTICATION_CODE_LENGTH);
|
|
1349
1355
|
const decryptedChunkArray = new Uint8Array(subarray(pendingInput, 0, pendingInput.length - AUTHENTICATION_CODE_LENGTH));
|
|
1350
1356
|
engine.process(decryptedChunkArray, true);
|
|
@@ -1354,27 +1360,26 @@ class AESDecryptionStream extends TransformStream {
|
|
|
1354
1360
|
invalidAuthenticationCode |= authenticationCode[indexByte] ^ originalAuthenticationCode[indexByte];
|
|
1355
1361
|
}
|
|
1356
1362
|
if (invalidAuthenticationCode && checkAuthenticationCode) {
|
|
1357
|
-
|
|
1363
|
+
controller.error(new Error(ERR_INVALID_AUTHENTICATION_CODE));
|
|
1364
|
+
return;
|
|
1358
1365
|
}
|
|
1359
1366
|
controller.enqueue(decryptedChunkArray);
|
|
1360
1367
|
}
|
|
1361
|
-
},
|
|
1362
|
-
cancel() {
|
|
1363
|
-
disposeEngine(this);
|
|
1364
1368
|
}
|
|
1365
1369
|
});
|
|
1370
|
+
setDisposingReadable(this, aesCrypto);
|
|
1366
1371
|
}
|
|
1367
1372
|
}
|
|
1368
1373
|
|
|
1369
1374
|
class AESEncryptionStream extends TransformStream {
|
|
1370
1375
|
|
|
1371
1376
|
constructor({ password, rawPassword, encryptionStrength }) {
|
|
1377
|
+
const aesCrypto = {};
|
|
1372
1378
|
super({
|
|
1373
1379
|
start() {
|
|
1374
|
-
initAesCrypto(
|
|
1380
|
+
initAesCrypto(aesCrypto, password, rawPassword, encryptionStrength);
|
|
1375
1381
|
},
|
|
1376
1382
|
async transform(chunk, controller) {
|
|
1377
|
-
const aesCrypto = this;
|
|
1378
1383
|
const {
|
|
1379
1384
|
password,
|
|
1380
1385
|
strength,
|
|
@@ -1388,6 +1393,9 @@ class AESEncryptionStream extends TransformStream {
|
|
|
1388
1393
|
} else {
|
|
1389
1394
|
await ready;
|
|
1390
1395
|
}
|
|
1396
|
+
if (aesCrypto.discarded) {
|
|
1397
|
+
return;
|
|
1398
|
+
}
|
|
1391
1399
|
const output = new Uint8Array(preamble.length + chunk.length - (chunk.length % BLOCK_LENGTH));
|
|
1392
1400
|
output.set(preamble, 0);
|
|
1393
1401
|
controller.enqueue(append(aesCrypto, chunk, output, preamble.length, 0, false));
|
|
@@ -1397,19 +1405,20 @@ class AESEncryptionStream extends TransformStream {
|
|
|
1397
1405
|
engine,
|
|
1398
1406
|
pendingInput,
|
|
1399
1407
|
ready
|
|
1400
|
-
} =
|
|
1408
|
+
} = aesCrypto;
|
|
1401
1409
|
if (engine) {
|
|
1402
1410
|
await ready;
|
|
1411
|
+
if (aesCrypto.discarded) {
|
|
1412
|
+
return;
|
|
1413
|
+
}
|
|
1403
1414
|
const encryptedChunkArray = new Uint8Array(pendingInput);
|
|
1404
1415
|
engine.process(encryptedChunkArray, false);
|
|
1405
1416
|
const authenticationCode = subarray(engine.digest(), 0, AUTHENTICATION_CODE_LENGTH);
|
|
1406
1417
|
controller.enqueue(concat(encryptedChunkArray, authenticationCode));
|
|
1407
1418
|
}
|
|
1408
|
-
},
|
|
1409
|
-
cancel() {
|
|
1410
|
-
disposeEngine(this);
|
|
1411
1419
|
}
|
|
1412
1420
|
});
|
|
1421
|
+
setDisposingReadable(this, aesCrypto);
|
|
1413
1422
|
}
|
|
1414
1423
|
}
|
|
1415
1424
|
|
|
@@ -1422,7 +1431,37 @@ function initAesCrypto(aesCrypto, password, rawPassword, encryptionStrength) {
|
|
|
1422
1431
|
ready: new Promise(resolve => aesCrypto.resolveReady = resolve),
|
|
1423
1432
|
password: encodePassword(password, rawPassword),
|
|
1424
1433
|
strength: encryptionStrength - 1,
|
|
1425
|
-
pendingInput: EMPTY_UINT8_ARRAY
|
|
1434
|
+
pendingInput: EMPTY_UINT8_ARRAY,
|
|
1435
|
+
discarded: false
|
|
1436
|
+
});
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1439
|
+
function setDisposingReadable(stream, aesCrypto) {
|
|
1440
|
+
const reader = stream.readable.getReader();
|
|
1441
|
+
const readable = new ReadableStream({
|
|
1442
|
+
async pull(controller) {
|
|
1443
|
+
try {
|
|
1444
|
+
const { value, done } = await reader.read();
|
|
1445
|
+
if (done) {
|
|
1446
|
+
controller.close();
|
|
1447
|
+
} else {
|
|
1448
|
+
controller.enqueue(value);
|
|
1449
|
+
}
|
|
1450
|
+
} catch (error) {
|
|
1451
|
+
disposeEngine(aesCrypto);
|
|
1452
|
+
reader.cancel(error).catch(() => { });
|
|
1453
|
+
throw error;
|
|
1454
|
+
}
|
|
1455
|
+
},
|
|
1456
|
+
cancel(reason) {
|
|
1457
|
+
disposeEngine(aesCrypto);
|
|
1458
|
+
return reader.cancel(reason);
|
|
1459
|
+
}
|
|
1460
|
+
});
|
|
1461
|
+
Object.defineProperty(stream, "readable", {
|
|
1462
|
+
get() {
|
|
1463
|
+
return readable;
|
|
1464
|
+
}
|
|
1426
1465
|
});
|
|
1427
1466
|
}
|
|
1428
1467
|
|
|
@@ -1455,7 +1494,9 @@ async function createDecryptionKeys(decrypt, strength, password, preamble) {
|
|
|
1455
1494
|
}
|
|
1456
1495
|
}
|
|
1457
1496
|
|
|
1458
|
-
function disposeEngine(
|
|
1497
|
+
function disposeEngine(aesCrypto) {
|
|
1498
|
+
const { engine } = aesCrypto;
|
|
1499
|
+
aesCrypto.discarded = true;
|
|
1459
1500
|
if (engine && engine.dispose) {
|
|
1460
1501
|
engine.dispose();
|
|
1461
1502
|
}
|
|
@@ -1472,6 +1513,9 @@ async function createKeys$1(aesCrypto, strength, password, salt) {
|
|
|
1472
1513
|
const keyLength = KEY_LENGTH[strength];
|
|
1473
1514
|
const compositeKey = await deriveKey(password, salt, keyLength * 2 + PASSWORD_VERIFICATION_LENGTH);
|
|
1474
1515
|
aesCrypto.engine = createEngine$1(subarray(compositeKey, 0, keyLength), subarray(compositeKey, keyLength, keyLength * 2));
|
|
1516
|
+
if (aesCrypto.discarded) {
|
|
1517
|
+
disposeEngine(aesCrypto);
|
|
1518
|
+
}
|
|
1475
1519
|
return subarray(compositeKey, keyLength * 2);
|
|
1476
1520
|
}
|
|
1477
1521
|
|
|
@@ -1623,11 +1667,11 @@ function encrypt(target, input) {
|
|
|
1623
1667
|
}
|
|
1624
1668
|
|
|
1625
1669
|
function createKeys(target, password, rawPassword) {
|
|
1626
|
-
const
|
|
1670
|
+
const cryptoKeys = [0x12345678, 0x23456789, 0x34567890];
|
|
1627
1671
|
Object.assign(target, {
|
|
1628
|
-
|
|
1629
|
-
crcKey0: new Crc32(
|
|
1630
|
-
crcKey2: new Crc32(
|
|
1672
|
+
cryptoKeys,
|
|
1673
|
+
crcKey0: new Crc32(cryptoKeys[0]),
|
|
1674
|
+
crcKey2: new Crc32(cryptoKeys[2])
|
|
1631
1675
|
});
|
|
1632
1676
|
if (rawPassword) {
|
|
1633
1677
|
for (let index = 0; index < rawPassword.length; index++) {
|
|
@@ -1641,17 +1685,17 @@ function createKeys(target, password, rawPassword) {
|
|
|
1641
1685
|
}
|
|
1642
1686
|
|
|
1643
1687
|
function updateKeys(target, byte) {
|
|
1644
|
-
let [, key1] = target.
|
|
1688
|
+
let [, key1] = target.cryptoKeys;
|
|
1645
1689
|
target.crcKey0.append([byte]);
|
|
1646
1690
|
const key0 = ~target.crcKey0.get();
|
|
1647
1691
|
key1 = getInt32(Math.imul(getInt32(key1 + getInt8(key0)), 134775813) + 1);
|
|
1648
1692
|
target.crcKey2.append([key1 >>> 24]);
|
|
1649
1693
|
const key2 = ~target.crcKey2.get();
|
|
1650
|
-
target.
|
|
1694
|
+
target.cryptoKeys = [key0, key1, key2];
|
|
1651
1695
|
}
|
|
1652
1696
|
|
|
1653
1697
|
function getByte(target) {
|
|
1654
|
-
const temp = target.
|
|
1698
|
+
const temp = target.cryptoKeys[2] | 2;
|
|
1655
1699
|
return getInt8(Math.imul(temp, (temp ^ 1)) >>> 8);
|
|
1656
1700
|
}
|
|
1657
1701
|
|
|
@@ -1699,11 +1743,16 @@ function toCompatibleReadable(readable) {
|
|
|
1699
1743
|
const reader = readable.getReader();
|
|
1700
1744
|
return new ReadableStream({
|
|
1701
1745
|
async pull(controller) {
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1746
|
+
try {
|
|
1747
|
+
const { value, done } = await reader.read();
|
|
1748
|
+
if (done) {
|
|
1749
|
+
controller.close();
|
|
1750
|
+
} else {
|
|
1751
|
+
controller.enqueue(value);
|
|
1752
|
+
}
|
|
1753
|
+
} catch (error) {
|
|
1754
|
+
reader.cancel(error).catch(() => { });
|
|
1755
|
+
throw error;
|
|
1707
1756
|
}
|
|
1708
1757
|
},
|
|
1709
1758
|
cancel(reason) {
|
|
@@ -2006,28 +2055,25 @@ function pipeThroughGzipDecompressionStream(readable, gzipStream, outputSize, cr
|
|
|
2006
2055
|
pump();
|
|
2007
2056
|
return new ReadableStream({
|
|
2008
2057
|
async pull(controller) {
|
|
2009
|
-
let result;
|
|
2010
2058
|
try {
|
|
2011
|
-
|
|
2059
|
+
const { value, done } = await read();
|
|
2060
|
+
if (done) {
|
|
2061
|
+
controller.close();
|
|
2062
|
+
} else {
|
|
2063
|
+
outputLength += value.length;
|
|
2064
|
+
if (outputLength > outputSize) {
|
|
2065
|
+
throw new Error(ERR_INVALID_UNCOMPRESSED_SIZE);
|
|
2066
|
+
}
|
|
2067
|
+
if (outputCrc32) {
|
|
2068
|
+
outputCrc32.append(value);
|
|
2069
|
+
}
|
|
2070
|
+
controller.enqueue(value);
|
|
2071
|
+
}
|
|
2012
2072
|
} catch (error) {
|
|
2073
|
+
rejectTrailerReady(error);
|
|
2074
|
+
await cancel(reader, error);
|
|
2013
2075
|
throw trailerWritten ? getTrailerError(error) : error;
|
|
2014
2076
|
}
|
|
2015
|
-
const { value, done } = result;
|
|
2016
|
-
if (done) {
|
|
2017
|
-
controller.close();
|
|
2018
|
-
} else {
|
|
2019
|
-
outputLength += value.length;
|
|
2020
|
-
if (outputLength > outputSize) {
|
|
2021
|
-
const error = new Error(ERR_INVALID_UNCOMPRESSED_SIZE);
|
|
2022
|
-
rejectTrailerReady(error);
|
|
2023
|
-
await cancel(reader, error);
|
|
2024
|
-
throw error;
|
|
2025
|
-
}
|
|
2026
|
-
if (outputCrc32) {
|
|
2027
|
-
outputCrc32.append(value);
|
|
2028
|
-
}
|
|
2029
|
-
controller.enqueue(value);
|
|
2030
|
-
}
|
|
2031
2077
|
},
|
|
2032
2078
|
cancel(reason) {
|
|
2033
2079
|
rejectTrailerReady(reason);
|
|
@@ -2306,10 +2352,15 @@ function mapInflateStreamError(readable) {
|
|
|
2306
2352
|
const reader = readable.getReader();
|
|
2307
2353
|
return new ReadableStream({
|
|
2308
2354
|
async pull(controller) {
|
|
2309
|
-
let result;
|
|
2310
2355
|
try {
|
|
2311
|
-
|
|
2356
|
+
const { value, done } = await reader.read();
|
|
2357
|
+
if (done) {
|
|
2358
|
+
controller.close();
|
|
2359
|
+
} else {
|
|
2360
|
+
controller.enqueue(value);
|
|
2361
|
+
}
|
|
2312
2362
|
} catch (error) {
|
|
2363
|
+
await cancel(reader, error);
|
|
2313
2364
|
if (error && error.message) {
|
|
2314
2365
|
throw error;
|
|
2315
2366
|
}
|
|
@@ -2317,12 +2368,6 @@ function mapInflateStreamError(readable) {
|
|
|
2317
2368
|
mappedError.cause = error;
|
|
2318
2369
|
throw mappedError;
|
|
2319
2370
|
}
|
|
2320
|
-
const { value, done } = result;
|
|
2321
|
-
if (done) {
|
|
2322
|
-
controller.close();
|
|
2323
|
-
} else {
|
|
2324
|
-
controller.enqueue(value);
|
|
2325
|
-
}
|
|
2326
2371
|
},
|
|
2327
2372
|
cancel(reason) {
|
|
2328
2373
|
return reader.cancel(reason);
|
|
@@ -5401,8 +5446,8 @@ let ZipEntry$1 = class ZipEntry {
|
|
|
5401
5446
|
const passThroughCompression = Boolean(passThrough);
|
|
5402
5447
|
const passThroughEncryption = passThrough === true;
|
|
5403
5448
|
checkPasswordOption(password, rawPassword);
|
|
5404
|
-
password = password && password.length
|
|
5405
|
-
rawPassword = rawPassword && rawPassword.length
|
|
5449
|
+
password = password && password.length ? password : UNDEFINED_VALUE;
|
|
5450
|
+
rawPassword = rawPassword && rawPassword.length ? rawPassword : UNDEFINED_VALUE;
|
|
5406
5451
|
if (extraFieldAES) {
|
|
5407
5452
|
if (extraFieldAES.originalCompressionMethod != COMPRESSION_METHOD_AES) {
|
|
5408
5453
|
throw new Error(ERR_UNSUPPORTED_COMPRESSION);
|
|
@@ -6163,7 +6208,7 @@ function getMaxAppendedDataSize(maxAppendedDataSize, strictness) {
|
|
|
6163
6208
|
async function findEndOfCentralDirectory(reader, rejectAmbiguous, maxAppendedDataSize) {
|
|
6164
6209
|
const { size } = reader;
|
|
6165
6210
|
const anchoredLength = Math.min(size, END_OF_CENTRAL_DIR_LENGTH + MAX_16_BITS);
|
|
6166
|
-
const remoteProbeBudget = {
|
|
6211
|
+
const remoteProbeBudget = { remaining: MAX_END_OF_CENTRAL_DIR_PROBES };
|
|
6167
6212
|
let endOfDirectoryInfo;
|
|
6168
6213
|
let plausibleEndOfDirectoryInfo;
|
|
6169
6214
|
let endOfDirectoryReachingEndCount = 0;
|
|
@@ -6256,8 +6301,8 @@ async function readSignature(reader, view, anchoredOffset, signatureOffset, size
|
|
|
6256
6301
|
if (signatureOffset >= anchoredOffset) {
|
|
6257
6302
|
return getUint32$1(view, signatureOffset - anchoredOffset);
|
|
6258
6303
|
}
|
|
6259
|
-
if (remoteProbeBudget.
|
|
6260
|
-
remoteProbeBudget.
|
|
6304
|
+
if (remoteProbeBudget.remaining > 0) {
|
|
6305
|
+
remoteProbeBudget.remaining--;
|
|
6261
6306
|
const signatureArray = await readUint8Array(reader, signatureOffset, 4);
|
|
6262
6307
|
return getUint32$1(getDataView(signatureArray), 0);
|
|
6263
6308
|
}
|
|
@@ -7173,9 +7218,11 @@ function resolveMetadata(zipWriter, name, options) {
|
|
|
7173
7218
|
const passThrough = checkPassThroughOption(getOptionValue(zipWriter, options, OPTION_PASS_THROUGH));
|
|
7174
7219
|
const passThroughCompression = Boolean(passThrough);
|
|
7175
7220
|
const passThroughEncryption = passThrough === true;
|
|
7176
|
-
|
|
7177
|
-
|
|
7221
|
+
let password = getOptionValue(zipWriter, options, OPTION_PASSWORD);
|
|
7222
|
+
let rawPassword = getOptionValue(zipWriter, options, OPTION_RAW_PASSWORD);
|
|
7178
7223
|
checkPasswordOption(password, rawPassword);
|
|
7224
|
+
password = password && password.length ? password : UNDEFINED_VALUE;
|
|
7225
|
+
rawPassword = rawPassword && rawPassword.length ? rawPassword : UNDEFINED_VALUE;
|
|
7179
7226
|
const encryptionStrength = getNumberOptionValue(zipWriter, options, OPTION_ENCRYPTION_STRENGTH, 3);
|
|
7180
7227
|
const zipCrypto = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIPCRYPTO);
|
|
7181
7228
|
const extendedTimestamp = getOptionValue(zipWriter, options, OPTION_EXTENDED_TIMESTAMP, true);
|
|
@@ -8971,7 +9018,7 @@ function formatSupported(StreamClass, format) {
|
|
|
8971
9018
|
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
8972
9019
|
*/
|
|
8973
9020
|
|
|
8974
|
-
const VERSION = "2.16.
|
|
9021
|
+
const VERSION = "2.16.1";
|
|
8975
9022
|
|
|
8976
9023
|
/*
|
|
8977
9024
|
Copyright (c) 2025 Gildas Lormeau. All rights reserved.
|
|
@@ -9448,7 +9495,7 @@ try {
|
|
|
9448
9495
|
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
9449
9496
|
*/
|
|
9450
9497
|
|
|
9451
|
-
/* global
|
|
9498
|
+
/* global ReadableStream, WritableStream */
|
|
9452
9499
|
|
|
9453
9500
|
const FORMAT_DEFLATE = "deflate";
|
|
9454
9501
|
const FORMAT_DEFLATE_RAW = "deflate-raw";
|
|
@@ -9483,137 +9530,195 @@ function _make(isCompress, type, options = {}) {
|
|
|
9483
9530
|
const level = (typeof options.level === "number") ? options.level : -1;
|
|
9484
9531
|
const outBufferSize = (typeof options.outBuffer === "number") ? options.outBuffer : 64 * 1024;
|
|
9485
9532
|
const inBufferSize = (typeof options.inBufferSize === "number") ? options.inBufferSize : 64 * 1024;
|
|
9486
|
-
|
|
9487
|
-
|
|
9488
|
-
|
|
9533
|
+
const state = { out: 0, in: 0, inBufferSize: 0, streamHandle: 0 };
|
|
9534
|
+
let readableController, writableController, resolveWrite, cancelReason;
|
|
9535
|
+
let backpressure = true;
|
|
9536
|
+
let cancelled = false;
|
|
9537
|
+
initStream();
|
|
9538
|
+
const readable = new ReadableStream({
|
|
9539
|
+
start(controller) {
|
|
9540
|
+
readableController = controller;
|
|
9541
|
+
},
|
|
9542
|
+
pull() {
|
|
9543
|
+
backpressure = false;
|
|
9544
|
+
resumeWrite();
|
|
9545
|
+
},
|
|
9546
|
+
cancel(reason) {
|
|
9547
|
+
cancelled = true;
|
|
9548
|
+
cancelReason = reason;
|
|
9549
|
+
disposeStream(state);
|
|
9550
|
+
writableController.error(reason);
|
|
9551
|
+
resumeWrite();
|
|
9552
|
+
}
|
|
9553
|
+
}, { highWaterMark: 0 });
|
|
9554
|
+
const writable = new WritableStream({
|
|
9555
|
+
start(controller) {
|
|
9556
|
+
writableController = controller;
|
|
9557
|
+
},
|
|
9558
|
+
async write(chunk) {
|
|
9559
|
+
if (backpressure) {
|
|
9560
|
+
await new Promise(resolve => resolveWrite = resolve);
|
|
9561
|
+
}
|
|
9562
|
+
if (cancelled) {
|
|
9563
|
+
throw cancelReason;
|
|
9564
|
+
}
|
|
9489
9565
|
try {
|
|
9490
|
-
|
|
9491
|
-
this.out = malloc(outBufferSize);
|
|
9492
|
-
this.in = malloc(inBufferSize);
|
|
9493
|
-
this.inBufferSize = inBufferSize;
|
|
9494
|
-
if (!this.out || !this.in) {
|
|
9495
|
-
throw new Error("allocation failed");
|
|
9496
|
-
}
|
|
9497
|
-
if (isCompress) {
|
|
9498
|
-
this._process = wasm$1.deflate_process;
|
|
9499
|
-
this._last_consumed = wasm$1.deflate_last_consumed;
|
|
9500
|
-
this._end = wasm$1.deflate_end;
|
|
9501
|
-
this.streamHandle = wasm$1.deflate_new();
|
|
9502
|
-
if (type === FORMAT_GZIP) {
|
|
9503
|
-
result = wasm$1.deflate_init_gzip(this.streamHandle, level);
|
|
9504
|
-
} else if (type === FORMAT_DEFLATE_RAW) {
|
|
9505
|
-
result = wasm$1.deflate_init_raw(this.streamHandle, level);
|
|
9506
|
-
} else {
|
|
9507
|
-
result = wasm$1.deflate_init(this.streamHandle, level);
|
|
9508
|
-
}
|
|
9509
|
-
} else {
|
|
9510
|
-
if (type === FORMAT_DEFLATE64_RAW) {
|
|
9511
|
-
this._process = wasm$1.inflate9_process;
|
|
9512
|
-
this._last_consumed = wasm$1.inflate9_last_consumed;
|
|
9513
|
-
this._end = wasm$1.inflate9_end;
|
|
9514
|
-
this.streamHandle = wasm$1.inflate9_new();
|
|
9515
|
-
result = wasm$1.inflate9_init_raw(this.streamHandle);
|
|
9516
|
-
} else {
|
|
9517
|
-
this._process = wasm$1.inflate_process;
|
|
9518
|
-
this._last_consumed = wasm$1.inflate_last_consumed;
|
|
9519
|
-
this._end = wasm$1.inflate_end;
|
|
9520
|
-
this.streamHandle = wasm$1.inflate_new();
|
|
9521
|
-
if (type === FORMAT_DEFLATE_RAW) {
|
|
9522
|
-
result = wasm$1.inflate_init_raw(this.streamHandle);
|
|
9523
|
-
} else if (type === FORMAT_GZIP) {
|
|
9524
|
-
result = wasm$1.inflate_init_gzip(this.streamHandle);
|
|
9525
|
-
} else {
|
|
9526
|
-
result = wasm$1.inflate_init(this.streamHandle);
|
|
9527
|
-
}
|
|
9528
|
-
}
|
|
9529
|
-
}
|
|
9530
|
-
if (result !== 0) {
|
|
9531
|
-
throw new Error("init failed:" + result);
|
|
9532
|
-
}
|
|
9566
|
+
processChunk(chunk);
|
|
9533
9567
|
} catch (error) {
|
|
9534
|
-
disposeStream(
|
|
9568
|
+
disposeStream(state);
|
|
9569
|
+
readableController.error(error);
|
|
9535
9570
|
throw error;
|
|
9536
9571
|
}
|
|
9537
9572
|
},
|
|
9538
|
-
|
|
9573
|
+
close() {
|
|
9574
|
+
if (cancelled) {
|
|
9575
|
+
return;
|
|
9576
|
+
}
|
|
9539
9577
|
try {
|
|
9540
|
-
|
|
9541
|
-
const heap = new Uint8Array(memory.buffer);
|
|
9542
|
-
const process = this._process;
|
|
9543
|
-
const last_consumed = this._last_consumed;
|
|
9544
|
-
const out = this.out;
|
|
9545
|
-
let offset = 0;
|
|
9546
|
-
while (offset < buffer.length) {
|
|
9547
|
-
const toRead = Math.min(buffer.length - offset, 32 * 1024);
|
|
9548
|
-
if (!this.in || this.inBufferSize < toRead) {
|
|
9549
|
-
if (this.in && free) {
|
|
9550
|
-
free(this.in);
|
|
9551
|
-
this.in = 0;
|
|
9552
|
-
}
|
|
9553
|
-
this.in = malloc(toRead);
|
|
9554
|
-
this.inBufferSize = toRead;
|
|
9555
|
-
if (!this.in) {
|
|
9556
|
-
throw new Error("allocation failed");
|
|
9557
|
-
}
|
|
9558
|
-
}
|
|
9559
|
-
heap.set(buffer.subarray(offset, offset + toRead), this.in);
|
|
9560
|
-
const result = process(this.streamHandle, this.in, toRead, out, outBufferSize, 0);
|
|
9561
|
-
// checked before the byte count is used, so a status code can never be read as one
|
|
9562
|
-
const code = (result >> 24) & 0xff;
|
|
9563
|
-
const signedCode = (code & 0x80) ? code - 256 : code;
|
|
9564
|
-
if (signedCode < 0) {
|
|
9565
|
-
throw new Error("process error:" + signedCode);
|
|
9566
|
-
}
|
|
9567
|
-
const prod = result & 0x00ffffff;
|
|
9568
|
-
if (prod) {
|
|
9569
|
-
controller.enqueue(heap.slice(out, out + prod));
|
|
9570
|
-
}
|
|
9571
|
-
const consumed = last_consumed(this.streamHandle);
|
|
9572
|
-
if (consumed === 0 && prod === 0) {
|
|
9573
|
-
break;
|
|
9574
|
-
}
|
|
9575
|
-
offset += consumed;
|
|
9576
|
-
}
|
|
9578
|
+
flushStream();
|
|
9577
9579
|
} catch (error) {
|
|
9578
|
-
disposeStream(
|
|
9579
|
-
|
|
9580
|
+
disposeStream(state);
|
|
9581
|
+
readableController.error(error);
|
|
9582
|
+
throw error;
|
|
9583
|
+
}
|
|
9584
|
+
const result = disposeStream(state);
|
|
9585
|
+
if (result !== 0) {
|
|
9586
|
+
const error = new Error("end error:" + result);
|
|
9587
|
+
readableController.error(error);
|
|
9588
|
+
throw error;
|
|
9580
9589
|
}
|
|
9590
|
+
readableController.close();
|
|
9581
9591
|
},
|
|
9582
|
-
|
|
9583
|
-
|
|
9584
|
-
|
|
9585
|
-
|
|
9586
|
-
|
|
9587
|
-
|
|
9588
|
-
|
|
9589
|
-
|
|
9590
|
-
|
|
9591
|
-
|
|
9592
|
-
|
|
9593
|
-
|
|
9594
|
-
|
|
9595
|
-
|
|
9596
|
-
|
|
9597
|
-
|
|
9598
|
-
|
|
9599
|
-
|
|
9592
|
+
abort(reason) {
|
|
9593
|
+
disposeStream(state);
|
|
9594
|
+
readableController.error(reason);
|
|
9595
|
+
}
|
|
9596
|
+
}, { highWaterMark: 1 });
|
|
9597
|
+
return { readable, writable };
|
|
9598
|
+
|
|
9599
|
+
function initStream() {
|
|
9600
|
+
try {
|
|
9601
|
+
let result;
|
|
9602
|
+
state.out = malloc(outBufferSize);
|
|
9603
|
+
state.in = malloc(inBufferSize);
|
|
9604
|
+
state.inBufferSize = inBufferSize;
|
|
9605
|
+
if (!state.out || !state.in) {
|
|
9606
|
+
throw new Error("allocation failed");
|
|
9607
|
+
}
|
|
9608
|
+
if (isCompress) {
|
|
9609
|
+
state._process = wasm$1.deflate_process;
|
|
9610
|
+
state._last_consumed = wasm$1.deflate_last_consumed;
|
|
9611
|
+
state._end = wasm$1.deflate_end;
|
|
9612
|
+
state.streamHandle = wasm$1.deflate_new();
|
|
9613
|
+
if (type === FORMAT_GZIP) {
|
|
9614
|
+
result = wasm$1.deflate_init_gzip(state.streamHandle, level);
|
|
9615
|
+
} else if (type === FORMAT_DEFLATE_RAW) {
|
|
9616
|
+
result = wasm$1.deflate_init_raw(state.streamHandle, level);
|
|
9617
|
+
} else {
|
|
9618
|
+
result = wasm$1.deflate_init(state.streamHandle, level);
|
|
9619
|
+
}
|
|
9620
|
+
} else {
|
|
9621
|
+
if (type === FORMAT_DEFLATE64_RAW) {
|
|
9622
|
+
state._process = wasm$1.inflate9_process;
|
|
9623
|
+
state._last_consumed = wasm$1.inflate9_last_consumed;
|
|
9624
|
+
state._end = wasm$1.inflate9_end;
|
|
9625
|
+
state.streamHandle = wasm$1.inflate9_new();
|
|
9626
|
+
result = wasm$1.inflate9_init_raw(state.streamHandle);
|
|
9627
|
+
} else {
|
|
9628
|
+
state._process = wasm$1.inflate_process;
|
|
9629
|
+
state._last_consumed = wasm$1.inflate_last_consumed;
|
|
9630
|
+
state._end = wasm$1.inflate_end;
|
|
9631
|
+
state.streamHandle = wasm$1.inflate_new();
|
|
9632
|
+
if (type === FORMAT_DEFLATE_RAW) {
|
|
9633
|
+
result = wasm$1.inflate_init_raw(state.streamHandle);
|
|
9634
|
+
} else if (type === FORMAT_GZIP) {
|
|
9635
|
+
result = wasm$1.inflate_init_gzip(state.streamHandle);
|
|
9636
|
+
} else {
|
|
9637
|
+
result = wasm$1.inflate_init(state.streamHandle);
|
|
9600
9638
|
}
|
|
9601
9639
|
}
|
|
9602
|
-
}
|
|
9603
|
-
|
|
9604
|
-
|
|
9605
|
-
|
|
9606
|
-
|
|
9607
|
-
|
|
9640
|
+
}
|
|
9641
|
+
if (result !== 0) {
|
|
9642
|
+
throw new Error("init failed:" + result);
|
|
9643
|
+
}
|
|
9644
|
+
} catch (error) {
|
|
9645
|
+
disposeStream(state);
|
|
9646
|
+
throw error;
|
|
9647
|
+
}
|
|
9648
|
+
}
|
|
9649
|
+
|
|
9650
|
+
function processChunk(chunk) {
|
|
9651
|
+
const heap = new Uint8Array(memory.buffer);
|
|
9652
|
+
const process = state._process;
|
|
9653
|
+
const last_consumed = state._last_consumed;
|
|
9654
|
+
const out = state.out;
|
|
9655
|
+
let offset = 0;
|
|
9656
|
+
while (offset < chunk.length) {
|
|
9657
|
+
const toRead = Math.min(chunk.length - offset, 32 * 1024);
|
|
9658
|
+
if (!state.in || state.inBufferSize < toRead) {
|
|
9659
|
+
if (state.in && free) {
|
|
9660
|
+
free(state.in);
|
|
9661
|
+
state.in = 0;
|
|
9662
|
+
}
|
|
9663
|
+
state.in = malloc(toRead);
|
|
9664
|
+
state.inBufferSize = toRead;
|
|
9665
|
+
if (!state.in) {
|
|
9666
|
+
throw new Error("allocation failed");
|
|
9608
9667
|
}
|
|
9609
9668
|
}
|
|
9610
|
-
|
|
9611
|
-
|
|
9612
|
-
//
|
|
9613
|
-
|
|
9614
|
-
|
|
9669
|
+
heap.set(chunk.subarray(offset, offset + toRead), state.in);
|
|
9670
|
+
const result = process(state.streamHandle, state.in, toRead, out, outBufferSize, 0);
|
|
9671
|
+
// checked before the byte count is used, so a status code can never be read as one
|
|
9672
|
+
const code = (result >> 24) & 0xff;
|
|
9673
|
+
const signedCode = (code & 0x80) ? code - 256 : code;
|
|
9674
|
+
if (signedCode < 0) {
|
|
9675
|
+
throw new Error("process error:" + signedCode);
|
|
9676
|
+
}
|
|
9677
|
+
const prod = result & 0x00ffffff;
|
|
9678
|
+
if (prod) {
|
|
9679
|
+
enqueue(heap.slice(out, out + prod));
|
|
9680
|
+
}
|
|
9681
|
+
const consumed = last_consumed(state.streamHandle);
|
|
9682
|
+
if (consumed === 0 && prod === 0) {
|
|
9683
|
+
break;
|
|
9684
|
+
}
|
|
9685
|
+
offset += consumed;
|
|
9615
9686
|
}
|
|
9616
|
-
}
|
|
9687
|
+
}
|
|
9688
|
+
|
|
9689
|
+
function flushStream() {
|
|
9690
|
+
const heap = new Uint8Array(memory.buffer);
|
|
9691
|
+
const process = state._process;
|
|
9692
|
+
const out = state.out;
|
|
9693
|
+
while (true) {
|
|
9694
|
+
const result = process(state.streamHandle, 0, 0, out, outBufferSize, 4);
|
|
9695
|
+
const code = (result >> 24) & 0xff;
|
|
9696
|
+
const signedCode = (code & 0x80) ? code - 256 : code;
|
|
9697
|
+
if (signedCode < 0) {
|
|
9698
|
+
throw new Error("process error:" + signedCode);
|
|
9699
|
+
}
|
|
9700
|
+
const produced = result & 0x00ffffff;
|
|
9701
|
+
if (produced) {
|
|
9702
|
+
enqueue(heap.slice(out, out + produced));
|
|
9703
|
+
}
|
|
9704
|
+
if (code === 1 || produced === 0) {
|
|
9705
|
+
break;
|
|
9706
|
+
}
|
|
9707
|
+
}
|
|
9708
|
+
}
|
|
9709
|
+
|
|
9710
|
+
function enqueue(chunk) {
|
|
9711
|
+
backpressure = true;
|
|
9712
|
+
readableController.enqueue(chunk);
|
|
9713
|
+
}
|
|
9714
|
+
|
|
9715
|
+
function resumeWrite() {
|
|
9716
|
+
if (resolveWrite) {
|
|
9717
|
+
const resolve = resolveWrite;
|
|
9718
|
+
resolveWrite = null;
|
|
9719
|
+
resolve();
|
|
9720
|
+
}
|
|
9721
|
+
}
|
|
9617
9722
|
|
|
9618
9723
|
function disposeStream(state) {
|
|
9619
9724
|
let endResult = 0;
|
|
@@ -9943,7 +10048,11 @@ const DUPLICATES_VALUES = new Set([DUPLICATES_THROW, DUPLICATES_KEEP_FIRST, DUPL
|
|
|
9943
10048
|
const ERR_INVALID_PASS_THROUGH = "Invalid passThrough option (use readerOptions.passThrough or set uncompressedSize for each entry)";
|
|
9944
10049
|
const ERR_INVALID_READER_OPTIONS = "Invalid readerOptions (must be an object)";
|
|
9945
10050
|
const ERR_UNSUPPORTED_PASS_THROUGH_VALUE = "The 'compressed' passThrough option is only supported by Entry#getData() and ZipWriter#add()";
|
|
10051
|
+
const ERR_INVALID_PASSWORDS = "Invalid passwords option (must be an array of strings)";
|
|
10052
|
+
const ERR_INVALID_REQUEST_PASSWORD = "Invalid requestPassword option (must be a function returning a string or undefined)";
|
|
9946
10053
|
const ERR_ABORT_EXPORT = "zipjs-abort-export";
|
|
10054
|
+
const ABORT_ERROR_NAME = "AbortError";
|
|
10055
|
+
const EMPTY_RAW_PASSWORD = new Uint8Array(0);
|
|
9947
10056
|
|
|
9948
10057
|
class ZipEntry {
|
|
9949
10058
|
|
|
@@ -10316,8 +10425,10 @@ class ZipDirectoryEntry extends ZipEntry {
|
|
|
10316
10425
|
zipReader = new ZipReader(reader, options);
|
|
10317
10426
|
}
|
|
10318
10427
|
checkPassThroughValue(options.passThrough);
|
|
10428
|
+
checkPasswordCandidatesOptions(options);
|
|
10319
10429
|
const duplicates = checkDuplicatesOption(options.duplicates);
|
|
10320
10430
|
const importedEntries = [];
|
|
10431
|
+
const passwordState = { known: [] };
|
|
10321
10432
|
const entries = await zipReader.getEntries(options);
|
|
10322
10433
|
for (const entry of entries) {
|
|
10323
10434
|
let parent = this;
|
|
@@ -10362,7 +10473,7 @@ class ZipDirectoryEntry extends ZipEntry {
|
|
|
10362
10473
|
}
|
|
10363
10474
|
importedEntries.push(addChild(parent, name, {
|
|
10364
10475
|
data: entry,
|
|
10365
|
-
Reader: getZipBlobReader(Object.assign({}, options)),
|
|
10476
|
+
Reader: getZipBlobReader(Object.assign({}, options), passwordState),
|
|
10366
10477
|
uncompressedSize: options.passThrough ? entry.compressedSize : entry.uncompressedSize,
|
|
10367
10478
|
passThrough: options.passThrough
|
|
10368
10479
|
}));
|
|
@@ -10691,7 +10802,7 @@ function getReadableReader(readable) {
|
|
|
10691
10802
|
};
|
|
10692
10803
|
}
|
|
10693
10804
|
|
|
10694
|
-
function getZipBlobReader(options) {
|
|
10805
|
+
function getZipBlobReader(options, passwordState) {
|
|
10695
10806
|
return class extends Reader {
|
|
10696
10807
|
|
|
10697
10808
|
constructor(entry, options = {}) {
|
|
@@ -10704,12 +10815,12 @@ function getZipBlobReader(options) {
|
|
|
10704
10815
|
const zipBlobReader = this;
|
|
10705
10816
|
const readerOptions = Object.assign({}, options, zipBlobReader.options);
|
|
10706
10817
|
const { checkOverlappingEntry, checkOverlappingEntryOnly } = readerOptions;
|
|
10707
|
-
const data = await zipBlobReader.entry
|
|
10818
|
+
const data = await readEntryData(zipBlobReader.entry, Object.assign(readerOptions, {
|
|
10708
10819
|
checkPasswordOnly: false,
|
|
10709
10820
|
checkOverlappingEntry: checkOverlappingEntryOnly || checkOverlappingEntry,
|
|
10710
10821
|
checkOverlappingEntryOnly: false,
|
|
10711
10822
|
preventClose: false
|
|
10712
|
-
}));
|
|
10823
|
+
}), passwordState);
|
|
10713
10824
|
zipBlobReader.data = data;
|
|
10714
10825
|
zipBlobReader.blobReader = new BlobReader(data);
|
|
10715
10826
|
zipBlobReader.size = data.size;
|
|
@@ -10771,10 +10882,9 @@ async function initReaders(entry, options) {
|
|
|
10771
10882
|
await initStream(reader);
|
|
10772
10883
|
} catch (error) {
|
|
10773
10884
|
try {
|
|
10885
|
+
error.entry = child;
|
|
10774
10886
|
error.entryId = child.id;
|
|
10775
|
-
error.
|
|
10776
|
-
entry: child
|
|
10777
|
-
};
|
|
10887
|
+
error.entryName = child.getRelativeName(entry);
|
|
10778
10888
|
} catch {
|
|
10779
10889
|
// ignored
|
|
10780
10890
|
}
|
|
@@ -10866,10 +10976,136 @@ function checkReaderOptions(readerOptions) {
|
|
|
10866
10976
|
}
|
|
10867
10977
|
if (readerOptions) {
|
|
10868
10978
|
checkPassThroughValue(readerOptions.passThrough);
|
|
10979
|
+
checkPasswordCandidatesOptions(readerOptions);
|
|
10869
10980
|
}
|
|
10870
10981
|
return readerOptions;
|
|
10871
10982
|
}
|
|
10872
10983
|
|
|
10984
|
+
function checkPasswordCandidatesOptions(options) {
|
|
10985
|
+
const { passwords, requestPassword } = options;
|
|
10986
|
+
if (passwords && (!Array.isArray(passwords) || passwords.some(password => typeof password != STRING_TYPE))) {
|
|
10987
|
+
throw new Error(ERR_INVALID_PASSWORDS);
|
|
10988
|
+
}
|
|
10989
|
+
if (requestPassword && typeof requestPassword != FUNCTION_TYPE) {
|
|
10990
|
+
throw new Error(ERR_INVALID_REQUEST_PASSWORD);
|
|
10991
|
+
}
|
|
10992
|
+
}
|
|
10993
|
+
|
|
10994
|
+
async function readEntryData(entry, options, passwordState) {
|
|
10995
|
+
checkPasswordCandidatesOptions(options);
|
|
10996
|
+
const { passwords, requestPassword, signal } = options;
|
|
10997
|
+
options = Object.assign({}, options);
|
|
10998
|
+
delete options.passwords;
|
|
10999
|
+
delete options.requestPassword;
|
|
11000
|
+
if (!entry.encrypted || options.passThrough || (!passwords && !requestPassword)) {
|
|
11001
|
+
return entry.getData(new BlobWriter(), options);
|
|
11002
|
+
}
|
|
11003
|
+
const tried = new Set();
|
|
11004
|
+
let error;
|
|
11005
|
+
while (true) {
|
|
11006
|
+
for (const candidate of getPasswordCandidates(options, passwordState, passwords)) {
|
|
11007
|
+
if (!tried.has(candidate.key)) {
|
|
11008
|
+
const result = await tryPasswordCandidate(candidate);
|
|
11009
|
+
if (result.done) {
|
|
11010
|
+
return result.data;
|
|
11011
|
+
}
|
|
11012
|
+
error = result.error;
|
|
11013
|
+
}
|
|
11014
|
+
}
|
|
11015
|
+
if (!requestPassword) {
|
|
11016
|
+
break;
|
|
11017
|
+
}
|
|
11018
|
+
if (passwordState.pendingPrompt) {
|
|
11019
|
+
await passwordState.pendingPrompt;
|
|
11020
|
+
continue;
|
|
11021
|
+
}
|
|
11022
|
+
let release;
|
|
11023
|
+
passwordState.pendingPrompt = new Promise(resolve => release = resolve);
|
|
11024
|
+
try {
|
|
11025
|
+
const answer = await requestPassword(entry, error);
|
|
11026
|
+
if (answer === UNDEFINED_VALUE || answer === null) {
|
|
11027
|
+
break;
|
|
11028
|
+
}
|
|
11029
|
+
// deno-lint-ignore valid-typeof
|
|
11030
|
+
if (typeof answer != STRING_TYPE) {
|
|
11031
|
+
throw new Error(ERR_INVALID_REQUEST_PASSWORD);
|
|
11032
|
+
}
|
|
11033
|
+
const result = await tryPasswordCandidate(getPasswordCandidate(answer));
|
|
11034
|
+
if (result.done) {
|
|
11035
|
+
return result.data;
|
|
11036
|
+
}
|
|
11037
|
+
error = result.error;
|
|
11038
|
+
} finally {
|
|
11039
|
+
passwordState.pendingPrompt = UNDEFINED_VALUE;
|
|
11040
|
+
release();
|
|
11041
|
+
}
|
|
11042
|
+
}
|
|
11043
|
+
throw new Error(tried.size ? ERR_INVALID_PASSWORD : ERR_ENCRYPTED);
|
|
11044
|
+
|
|
11045
|
+
async function tryPasswordCandidate(candidate) {
|
|
11046
|
+
tried.add(candidate.key);
|
|
11047
|
+
const candidateOptions = Object.assign({}, options, candidate.options);
|
|
11048
|
+
if (entry.zipCrypto) {
|
|
11049
|
+
candidateOptions.checkCrc32 = true;
|
|
11050
|
+
try {
|
|
11051
|
+
await entry.getData(null, Object.assign({}, candidateOptions, { checkPasswordOnly: true }));
|
|
11052
|
+
} catch (probeError) {
|
|
11053
|
+
if (isInvalidPasswordError(probeError)) {
|
|
11054
|
+
return { done: false, error: probeError };
|
|
11055
|
+
}
|
|
11056
|
+
throw probeError;
|
|
11057
|
+
}
|
|
11058
|
+
}
|
|
11059
|
+
try {
|
|
11060
|
+
const data = await entry.getData(new BlobWriter(), candidateOptions);
|
|
11061
|
+
rememberPassword(passwordState, candidate);
|
|
11062
|
+
return { done: true, data };
|
|
11063
|
+
} catch (readError) {
|
|
11064
|
+
if (isAbortError(readError, signal) || (!entry.zipCrypto && !isInvalidPasswordError(readError))) {
|
|
11065
|
+
throw readError;
|
|
11066
|
+
}
|
|
11067
|
+
return { done: false, error: readError };
|
|
11068
|
+
}
|
|
11069
|
+
}
|
|
11070
|
+
}
|
|
11071
|
+
|
|
11072
|
+
function isInvalidPasswordError(error) {
|
|
11073
|
+
return isErrorObject(error) && error.message == ERR_INVALID_PASSWORD;
|
|
11074
|
+
}
|
|
11075
|
+
|
|
11076
|
+
function isAbortError(error, signal) {
|
|
11077
|
+
return Boolean(signal && signal.aborted) || (isErrorObject(error) && error.name == ABORT_ERROR_NAME);
|
|
11078
|
+
}
|
|
11079
|
+
|
|
11080
|
+
function getPasswordCandidates(options, passwordState, passwords) {
|
|
11081
|
+
const candidates = [];
|
|
11082
|
+
const { password, rawPassword } = options;
|
|
11083
|
+
if (rawPassword && rawPassword.length) {
|
|
11084
|
+
candidates.push({ key: rawPassword, options: { password: "", rawPassword } });
|
|
11085
|
+
}
|
|
11086
|
+
if (password) {
|
|
11087
|
+
candidates.push(getPasswordCandidate(password));
|
|
11088
|
+
}
|
|
11089
|
+
candidates.push(...passwordState.known);
|
|
11090
|
+
if (passwords) {
|
|
11091
|
+
candidates.push(...passwords.filter(password => password).map(getPasswordCandidate));
|
|
11092
|
+
}
|
|
11093
|
+
return candidates;
|
|
11094
|
+
}
|
|
11095
|
+
|
|
11096
|
+
function getPasswordCandidate(password) {
|
|
11097
|
+
return { key: password, options: { password, rawPassword: EMPTY_RAW_PASSWORD } };
|
|
11098
|
+
}
|
|
11099
|
+
|
|
11100
|
+
function rememberPassword(passwordState, candidate) {
|
|
11101
|
+
const { known } = passwordState;
|
|
11102
|
+
const index = known.findIndex(knownCandidate => knownCandidate.key === candidate.key);
|
|
11103
|
+
if (index != -1) {
|
|
11104
|
+
known.splice(index, 1);
|
|
11105
|
+
}
|
|
11106
|
+
known.unshift(candidate);
|
|
11107
|
+
}
|
|
11108
|
+
|
|
10873
11109
|
function checkPassThroughValue(passThrough) {
|
|
10874
11110
|
if (checkPassThroughOption(passThrough) === PASS_THROUGH_COMPRESSED) {
|
|
10875
11111
|
throw new Error(ERR_UNSUPPORTED_PASS_THROUGH_VALUE);
|
|
@@ -11007,6 +11243,7 @@ function addFileSystemHandle(zipEntry, handle, options) {
|
|
|
11007
11243
|
async function exportFileSystemHandle(zipEntry, directoryHandle, options) {
|
|
11008
11244
|
const { onstart, onprogress, onend } = options;
|
|
11009
11245
|
checkPassThroughValue(options.passThrough);
|
|
11246
|
+
checkPasswordCandidatesOptions(options);
|
|
11010
11247
|
const readerOptions = checkReaderOptions(options.readerOptions);
|
|
11011
11248
|
const abortController = new AbortController();
|
|
11012
11249
|
const { signal } = abortController;
|
|
@@ -11256,4 +11493,4 @@ function getPathParent(parent, path, movedEntry) {
|
|
|
11256
11493
|
return parent;
|
|
11257
11494
|
}
|
|
11258
11495
|
|
|
11259
|
-
export { BlobReader, BlobWriter, Data64URIReader, Data64URIWriter, ERR_ABORTED, ERR_AMBIGUOUS_ARCHIVE, ERR_ANCESTOR_ENTRY, ERR_BAD_FORMAT, ERR_CENTRAL_DIRECTORY_NOT_FOUND, ERR_DUPLICATED_NAME, ERR_DUPLICATE_IMPORTED_ENTRY, ERR_ENCRYPTED, ERR_ENCRYPTED_CENTRAL_DIRECTORY, ERR_ENTRY_DATA_OUT_OF_BOUNDS, ERR_ENTRY_EXISTS, ERR_EOCDR_LOCATOR_ZIP64_NOT_FOUND, ERR_EOCDR_NOT_FOUND, ERR_EXTRAFIELD_ZIP64_NOT_FOUND, ERR_HTTP_RANGE, ERR_HTTP_RESOURCE_CHANGED, ERR_HTTP_STATUS, ERR_INVALID_AUTHENTICATION_CODE, ERR_INVALID_BASE_URI, ERR_INVALID_CODEC_DEFINITION, ERR_INVALID_CODEC_MODULE, ERR_INVALID_COMMENT, ERR_INVALID_COMMENT_TYPE, ERR_INVALID_COMPRESSED_DATA, ERR_INVALID_CRC32, ERR_INVALID_DATE, ERR_INVALID_DUPLICATES, ERR_INVALID_ENCRYPTION_STRENGTH, ERR_INVALID_ENTRY, ERR_INVALID_ENTRY_COMMENT, ERR_INVALID_ENTRY_COMMENT_TYPE, ERR_INVALID_ENTRY_NAME, ERR_INVALID_EXTRAFIELD, ERR_INVALID_EXTRAFIELD_DATA, ERR_INVALID_EXTRAFIELD_DATA_TYPE, ERR_INVALID_EXTRAFIELD_TYPE, ERR_INVALID_FILENAME_VALIDATION, ERR_INVALID_FUNCTION_OPTION, ERR_INVALID_GID, ERR_INVALID_LEVEL, ERR_INVALID_MAX_APPENDED_DATA_SIZE, ERR_INVALID_MAX_WORKERS, ERR_INVALID_MSDOS_ATTRIBUTES, ERR_INVALID_MSDOS_DATA, ERR_INVALID_PASSWORD, ERR_INVALID_PASSWORD_TYPE, ERR_INVALID_PASS_THROUGH, ERR_INVALID_PASS_THROUGH_VALUE, ERR_INVALID_READER, ERR_INVALID_READER_OPTIONS, ERR_INVALID_SIGNAL, ERR_INVALID_SIGNATURE_DATA, ERR_INVALID_STRICTNESS, ERR_INVALID_UID, ERR_INVALID_UNCOMPRESSED_SIZE, ERR_INVALID_UNIX_EXTRA_FIELD_TYPE, ERR_INVALID_UNIX_ID_SIZE, ERR_INVALID_UNIX_MODE, ERR_INVALID_URI, ERR_INVALID_VERSION, ERR_ITERATOR_COMPLETED_TOO_SOON, ERR_LOCAL_FILE_HEADER_NOT_FOUND, ERR_OVERLAPPING_ENTRY, ERR_PARENT_NOT_DIRECTORY, ERR_READABLE_CONSUMED, ERR_RESERVED_COMPRESSION_METHOD, ERR_ROOT_DIRECTORY_NOT_MOVABLE, ERR_SPLIT_ZIP_FILE, ERR_TARGET_NOT_DIRECTORY, ERR_UNDEFINED_COMPRESSION_METHOD, ERR_UNDEFINED_CRC32, ERR_UNDEFINED_READER, ERR_UNDEFINED_UNCOMPRESSED_SIZE, ERR_UNDETERMINED_SIZE, ERR_UNSAFE_FILENAME, ERR_UNSUPPORTED_COMPRESSION, ERR_UNSUPPORTED_CONTEXT, ERR_UNSUPPORTED_CRYPTO_API, ERR_UNSUPPORTED_ENCRYPTION, ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH, ERR_UNSUPPORTED_ENCRYPTION_USDZ, ERR_UNSUPPORTED_FORMAT, ERR_UNSUPPORTED_PASS_THROUGH_VALUE, ERR_UNSUPPORTED_SPLIT_USDZ, ERR_UNSUPPORTED_UINT64, ERR_WORKER_STARTUP_TIMEOUT, ERR_WRITER_NOT_INITIALIZED, ERR_WRITER_SIZE_NOT_WRITABLE, ERR_ZIP_CRYPTO_LAST_MOD_DATE, ERR_ZIP_NOT_EMPTY, HttpRangeReader, HttpReader, Reader, SplitDataReader, SplitDataWriter, TextReader, TextWriter, Uint8ArrayReader, Uint8ArrayWriter, VERSION, WARNING_APPENDED_DATA, WARNING_CLAMPED_LAST_MODIFICATION_DATE, WARNING_COMPRESSED_PATCHED_DATA, WARNING_COMPRESSION_UNAVAILABLE, WARNING_DUPLICATE_FILENAME, WARNING_MALFORMED_EXTRA_FIELD, WARNING_MISMATCHED_LOCAL_FILE_HEADER_BIT_FLAG, WARNING_MISMATCHED_LOCAL_FILE_HEADER_COMPRESSION_METHOD, WARNING_MISMATCHED_LOCAL_FILE_HEADER_CRC32_OR_SIZES, WARNING_MISMATCHED_LOCAL_FILE_HEADER_FILENAME, WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY, WARNING_MULTIPLE_END_OF_CENTRAL_DIRECTORY, WARNING_PREPENDED_CENTRAL_DIRECTORY, WARNING_PREPENDED_DATA, WARNING_TRAILING_CENTRAL_DIRECTORY_DATA, WARNING_UNKNOWN_VERSION, WARNING_UNKNOWN_ZIP64_EXTENSIBLE_DATA, WARNING_UNSORTED_CENTRAL_DIRECTORY, WARNING_WRAPPED_ENTRIES_COUNT, Writer, ZipDirectoryEntry, ZipEntry, ZipFS, ZipFileEntry, ZipReader, ZipReaderStream, ZipWriter, ZipWriterStream, configure, createBlobTempStream, createOPFSTempStream, createSyncAccessHandleTempStream, fs, getMimeType, getRegisteredCodecs, getSupportedCompressionMethods, isZipFile, registerCodec, resetConfiguration, terminateWorkersAndModule as terminateWorkers, unregisterCodec };
|
|
11496
|
+
export { BlobReader, BlobWriter, Data64URIReader, Data64URIWriter, ERR_ABORTED, ERR_AMBIGUOUS_ARCHIVE, ERR_ANCESTOR_ENTRY, ERR_BAD_FORMAT, ERR_CENTRAL_DIRECTORY_NOT_FOUND, ERR_DUPLICATED_NAME, ERR_DUPLICATE_IMPORTED_ENTRY, ERR_ENCRYPTED, ERR_ENCRYPTED_CENTRAL_DIRECTORY, ERR_ENTRY_DATA_OUT_OF_BOUNDS, ERR_ENTRY_EXISTS, ERR_EOCDR_LOCATOR_ZIP64_NOT_FOUND, ERR_EOCDR_NOT_FOUND, ERR_EXTRAFIELD_ZIP64_NOT_FOUND, ERR_HTTP_RANGE, ERR_HTTP_RESOURCE_CHANGED, ERR_HTTP_STATUS, ERR_INVALID_AUTHENTICATION_CODE, ERR_INVALID_BASE_URI, ERR_INVALID_CODEC_DEFINITION, ERR_INVALID_CODEC_MODULE, ERR_INVALID_COMMENT, ERR_INVALID_COMMENT_TYPE, ERR_INVALID_COMPRESSED_DATA, ERR_INVALID_CRC32, ERR_INVALID_DATE, ERR_INVALID_DUPLICATES, ERR_INVALID_ENCRYPTION_STRENGTH, ERR_INVALID_ENTRY, ERR_INVALID_ENTRY_COMMENT, ERR_INVALID_ENTRY_COMMENT_TYPE, ERR_INVALID_ENTRY_NAME, ERR_INVALID_EXTRAFIELD, ERR_INVALID_EXTRAFIELD_DATA, ERR_INVALID_EXTRAFIELD_DATA_TYPE, ERR_INVALID_EXTRAFIELD_TYPE, ERR_INVALID_FILENAME_VALIDATION, ERR_INVALID_FUNCTION_OPTION, ERR_INVALID_GID, ERR_INVALID_LEVEL, ERR_INVALID_MAX_APPENDED_DATA_SIZE, ERR_INVALID_MAX_WORKERS, ERR_INVALID_MSDOS_ATTRIBUTES, ERR_INVALID_MSDOS_DATA, ERR_INVALID_PASSWORD, ERR_INVALID_PASSWORDS, ERR_INVALID_PASSWORD_TYPE, ERR_INVALID_PASS_THROUGH, ERR_INVALID_PASS_THROUGH_VALUE, ERR_INVALID_READER, ERR_INVALID_READER_OPTIONS, ERR_INVALID_REQUEST_PASSWORD, ERR_INVALID_SIGNAL, ERR_INVALID_SIGNATURE_DATA, ERR_INVALID_STRICTNESS, ERR_INVALID_UID, ERR_INVALID_UNCOMPRESSED_SIZE, ERR_INVALID_UNIX_EXTRA_FIELD_TYPE, ERR_INVALID_UNIX_ID_SIZE, ERR_INVALID_UNIX_MODE, ERR_INVALID_URI, ERR_INVALID_VERSION, ERR_ITERATOR_COMPLETED_TOO_SOON, ERR_LOCAL_FILE_HEADER_NOT_FOUND, ERR_OVERLAPPING_ENTRY, ERR_PARENT_NOT_DIRECTORY, ERR_READABLE_CONSUMED, ERR_RESERVED_COMPRESSION_METHOD, ERR_ROOT_DIRECTORY_NOT_MOVABLE, ERR_SPLIT_ZIP_FILE, ERR_TARGET_NOT_DIRECTORY, ERR_UNDEFINED_COMPRESSION_METHOD, ERR_UNDEFINED_CRC32, ERR_UNDEFINED_READER, ERR_UNDEFINED_UNCOMPRESSED_SIZE, ERR_UNDETERMINED_SIZE, ERR_UNSAFE_FILENAME, ERR_UNSUPPORTED_COMPRESSION, ERR_UNSUPPORTED_CONTEXT, ERR_UNSUPPORTED_CRYPTO_API, ERR_UNSUPPORTED_ENCRYPTION, ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH, ERR_UNSUPPORTED_ENCRYPTION_USDZ, ERR_UNSUPPORTED_FORMAT, ERR_UNSUPPORTED_PASS_THROUGH_VALUE, ERR_UNSUPPORTED_SPLIT_USDZ, ERR_UNSUPPORTED_UINT64, ERR_WORKER_STARTUP_TIMEOUT, ERR_WRITER_NOT_INITIALIZED, ERR_WRITER_SIZE_NOT_WRITABLE, ERR_ZIP_CRYPTO_LAST_MOD_DATE, ERR_ZIP_NOT_EMPTY, HttpRangeReader, HttpReader, Reader, SplitDataReader, SplitDataWriter, TextReader, TextWriter, Uint8ArrayReader, Uint8ArrayWriter, VERSION, WARNING_APPENDED_DATA, WARNING_CLAMPED_LAST_MODIFICATION_DATE, WARNING_COMPRESSED_PATCHED_DATA, WARNING_COMPRESSION_UNAVAILABLE, WARNING_DUPLICATE_FILENAME, WARNING_MALFORMED_EXTRA_FIELD, WARNING_MISMATCHED_LOCAL_FILE_HEADER_BIT_FLAG, WARNING_MISMATCHED_LOCAL_FILE_HEADER_COMPRESSION_METHOD, WARNING_MISMATCHED_LOCAL_FILE_HEADER_CRC32_OR_SIZES, WARNING_MISMATCHED_LOCAL_FILE_HEADER_FILENAME, WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY, WARNING_MULTIPLE_END_OF_CENTRAL_DIRECTORY, WARNING_PREPENDED_CENTRAL_DIRECTORY, WARNING_PREPENDED_DATA, WARNING_TRAILING_CENTRAL_DIRECTORY_DATA, WARNING_UNKNOWN_VERSION, WARNING_UNKNOWN_ZIP64_EXTENSIBLE_DATA, WARNING_UNSORTED_CENTRAL_DIRECTORY, WARNING_WRAPPED_ENTRIES_COUNT, Writer, ZipDirectoryEntry, ZipEntry, ZipFS, ZipFileEntry, ZipReader, ZipReaderStream, ZipWriter, ZipWriterStream, configure, createBlobTempStream, createOPFSTempStream, createSyncAccessHandleTempStream, fs, getMimeType, getRegisteredCodecs, getSupportedCompressionMethods, isZipFile, registerCodec, resetConfiguration, terminateWorkersAndModule as terminateWorkers, unregisterCodec };
|