@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
package/dist/zip-core.js
CHANGED
|
@@ -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) {
|
|
@@ -1975,28 +2024,25 @@
|
|
|
1975
2024
|
pump();
|
|
1976
2025
|
return new ReadableStream({
|
|
1977
2026
|
async pull(controller) {
|
|
1978
|
-
let result;
|
|
1979
2027
|
try {
|
|
1980
|
-
|
|
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
|
+
}
|
|
1981
2041
|
} catch (error) {
|
|
2042
|
+
rejectTrailerReady(error);
|
|
2043
|
+
await cancel(reader, error);
|
|
1982
2044
|
throw trailerWritten ? getTrailerError(error) : error;
|
|
1983
2045
|
}
|
|
1984
|
-
const { value, done } = result;
|
|
1985
|
-
if (done) {
|
|
1986
|
-
controller.close();
|
|
1987
|
-
} else {
|
|
1988
|
-
outputLength += value.length;
|
|
1989
|
-
if (outputLength > outputSize) {
|
|
1990
|
-
const error = new Error(ERR_INVALID_UNCOMPRESSED_SIZE);
|
|
1991
|
-
rejectTrailerReady(error);
|
|
1992
|
-
await cancel(reader, error);
|
|
1993
|
-
throw error;
|
|
1994
|
-
}
|
|
1995
|
-
if (outputCrc32) {
|
|
1996
|
-
outputCrc32.append(value);
|
|
1997
|
-
}
|
|
1998
|
-
controller.enqueue(value);
|
|
1999
|
-
}
|
|
2000
2046
|
},
|
|
2001
2047
|
cancel(reason) {
|
|
2002
2048
|
rejectTrailerReady(reason);
|
|
@@ -2275,10 +2321,15 @@
|
|
|
2275
2321
|
const reader = readable.getReader();
|
|
2276
2322
|
return new ReadableStream({
|
|
2277
2323
|
async pull(controller) {
|
|
2278
|
-
let result;
|
|
2279
2324
|
try {
|
|
2280
|
-
|
|
2325
|
+
const { value, done } = await reader.read();
|
|
2326
|
+
if (done) {
|
|
2327
|
+
controller.close();
|
|
2328
|
+
} else {
|
|
2329
|
+
controller.enqueue(value);
|
|
2330
|
+
}
|
|
2281
2331
|
} catch (error) {
|
|
2332
|
+
await cancel(reader, error);
|
|
2282
2333
|
if (error && error.message) {
|
|
2283
2334
|
throw error;
|
|
2284
2335
|
}
|
|
@@ -2286,12 +2337,6 @@
|
|
|
2286
2337
|
mappedError.cause = error;
|
|
2287
2338
|
throw mappedError;
|
|
2288
2339
|
}
|
|
2289
|
-
const { value, done } = result;
|
|
2290
|
-
if (done) {
|
|
2291
|
-
controller.close();
|
|
2292
|
-
} else {
|
|
2293
|
-
controller.enqueue(value);
|
|
2294
|
-
}
|
|
2295
2340
|
},
|
|
2296
2341
|
cancel(reason) {
|
|
2297
2342
|
return reader.cancel(reason);
|
|
@@ -5346,8 +5391,8 @@
|
|
|
5346
5391
|
const passThroughCompression = Boolean(passThrough);
|
|
5347
5392
|
const passThroughEncryption = passThrough === true;
|
|
5348
5393
|
checkPasswordOption(password, rawPassword);
|
|
5349
|
-
password = password && password.length
|
|
5350
|
-
rawPassword = rawPassword && rawPassword.length
|
|
5394
|
+
password = password && password.length ? password : UNDEFINED_VALUE;
|
|
5395
|
+
rawPassword = rawPassword && rawPassword.length ? rawPassword : UNDEFINED_VALUE;
|
|
5351
5396
|
if (extraFieldAES) {
|
|
5352
5397
|
if (extraFieldAES.originalCompressionMethod != COMPRESSION_METHOD_AES) {
|
|
5353
5398
|
throw new Error(ERR_UNSUPPORTED_COMPRESSION);
|
|
@@ -6108,7 +6153,7 @@
|
|
|
6108
6153
|
async function findEndOfCentralDirectory(reader, rejectAmbiguous, maxAppendedDataSize) {
|
|
6109
6154
|
const { size } = reader;
|
|
6110
6155
|
const anchoredLength = Math.min(size, END_OF_CENTRAL_DIR_LENGTH + MAX_16_BITS);
|
|
6111
|
-
const remoteProbeBudget = {
|
|
6156
|
+
const remoteProbeBudget = { remaining: MAX_END_OF_CENTRAL_DIR_PROBES };
|
|
6112
6157
|
let endOfDirectoryInfo;
|
|
6113
6158
|
let plausibleEndOfDirectoryInfo;
|
|
6114
6159
|
let endOfDirectoryReachingEndCount = 0;
|
|
@@ -6201,8 +6246,8 @@
|
|
|
6201
6246
|
if (signatureOffset >= anchoredOffset) {
|
|
6202
6247
|
return getUint32$1(view, signatureOffset - anchoredOffset);
|
|
6203
6248
|
}
|
|
6204
|
-
if (remoteProbeBudget.
|
|
6205
|
-
remoteProbeBudget.
|
|
6249
|
+
if (remoteProbeBudget.remaining > 0) {
|
|
6250
|
+
remoteProbeBudget.remaining--;
|
|
6206
6251
|
const signatureArray = await readUint8Array(reader, signatureOffset, 4);
|
|
6207
6252
|
return getUint32$1(getDataView(signatureArray), 0);
|
|
6208
6253
|
}
|
|
@@ -7118,9 +7163,11 @@
|
|
|
7118
7163
|
const passThrough = checkPassThroughOption(getOptionValue(zipWriter, options, OPTION_PASS_THROUGH));
|
|
7119
7164
|
const passThroughCompression = Boolean(passThrough);
|
|
7120
7165
|
const passThroughEncryption = passThrough === true;
|
|
7121
|
-
|
|
7122
|
-
|
|
7166
|
+
let password = getOptionValue(zipWriter, options, OPTION_PASSWORD);
|
|
7167
|
+
let rawPassword = getOptionValue(zipWriter, options, OPTION_RAW_PASSWORD);
|
|
7123
7168
|
checkPasswordOption(password, rawPassword);
|
|
7169
|
+
password = password && password.length ? password : UNDEFINED_VALUE;
|
|
7170
|
+
rawPassword = rawPassword && rawPassword.length ? rawPassword : UNDEFINED_VALUE;
|
|
7124
7171
|
const encryptionStrength = getNumberOptionValue(zipWriter, options, OPTION_ENCRYPTION_STRENGTH, 3);
|
|
7125
7172
|
const zipCrypto = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIPCRYPTO);
|
|
7126
7173
|
const extendedTimestamp = getOptionValue(zipWriter, options, OPTION_EXTENDED_TIMESTAMP, true);
|
|
@@ -8818,7 +8865,7 @@
|
|
|
8818
8865
|
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
8819
8866
|
*/
|
|
8820
8867
|
|
|
8821
|
-
const VERSION = "2.16.
|
|
8868
|
+
const VERSION = "2.16.1";
|
|
8822
8869
|
|
|
8823
8870
|
/*
|
|
8824
8871
|
Copyright (c) 2025 Gildas Lormeau. All rights reserved.
|