single-file-core 1.6.19 → 1.6.21

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/vendor/zip/zip.js CHANGED
@@ -119,6 +119,10 @@ const MIN_DATE = new Date(1980, 0, 1);
119
119
 
120
120
  const UNDEFINED_VALUE = undefined;
121
121
  const INFINITY_VALUE = Infinity;
122
+ const ERR_LOCAL_FILE_HEADER_NOT_FOUND = "Local file header not found";
123
+ const ERR_OVERLAPPING_ENTRY = "Overlapping entry found";
124
+ const ERR_EXTRAFIELD_ZIP64_NOT_FOUND = "Zip64 extra field not found";
125
+
122
126
  const UNDEFINED_TYPE = "undefined";
123
127
  const FUNCTION_TYPE = "function";
124
128
  const OBJECT_TYPE = "object";
@@ -178,7 +182,6 @@ const OPTION_CHECK_CRC32 = "checkCrc32";
178
182
  const OPTION_CHECK_AUTHENTICATION_CODE = "checkAuthenticationCode";
179
183
  const OPTION_USE_WEB_WORKERS = "useWebWorkers";
180
184
  const OPTION_USE_COMPRESSION_STREAM = "useCompressionStream";
181
- const OPTION_TRANSFER_STREAMS = "transferStreams";
182
185
  const OPTION_PREVENT_CLOSE = "preventClose";
183
186
  const OPTION_ENCRYPTION_STRENGTH = "encryptionStrength";
184
187
  const OPTION_EXTENDED_TIMESTAMP = "extendedTimestamp";
@@ -215,6 +218,7 @@ const ERR_INVALID_FUNCTION_OPTION = "Invalid option (must be a function)";
215
218
  const ERR_INVALID_SIGNAL = "Invalid signal (must be an AbortSignal instance)";
216
219
  const ERR_INVALID_PASSWORD_TYPE = "Invalid password (password must be a string, rawPassword must be a Uint8Array)";
217
220
  const ERR_INVALID_PASS_THROUGH_VALUE = "Invalid passThrough option (must be a boolean or 'compressed')";
221
+ const ERR_INVALID_READER_OPTIONS = "Invalid readerOptions (must be an object)";
218
222
  const ERR_ABORTED = "The operation was aborted";
219
223
  const ABORT_ERROR_NAME = "AbortError";
220
224
 
@@ -225,6 +229,13 @@ function checkFunctionOption(value) {
225
229
  return value;
226
230
  }
227
231
 
232
+ function checkReaderOptionsObject(readerOptions) {
233
+ if (readerOptions && (typeof readerOptions != OBJECT_TYPE || Array.isArray(readerOptions))) {
234
+ throw new Error(ERR_INVALID_READER_OPTIONS);
235
+ }
236
+ return readerOptions;
237
+ }
238
+
228
239
  function checkSignalOption(signal) {
229
240
  if (signal && (typeof signal.addEventListener != FUNCTION_TYPE || typeof signal.aborted != BOOLEAN_TYPE)) {
230
241
  throw new Error(ERR_INVALID_SIGNAL);
@@ -296,7 +307,7 @@ function toNumber(value) {
296
307
  */
297
308
 
298
309
 
299
- const DEFAULT_CHUNK_SIZE$1 = 64 * 1024;
310
+ const DEFAULT_CHUNK_SIZE$1 = 256 * 1024;
300
311
  const MINIMUM_CHUNK_SIZE = 64;
301
312
  const MINIMUM_PROPERTY_VALUE = 1;
302
313
  const ERR_INVALID_MAX_WORKERS = "Invalid maxWorkers (must be an integer greater than 0)";
@@ -320,7 +331,6 @@ const DEFAULT_CONFIGURATION = {
320
331
  workerStartupTimeout: 5000,
321
332
  useWebWorkers: true,
322
333
  useCompressionStream: true,
323
- transferStreams: true,
324
334
  CompressionStream: typeof CompressionStream != UNDEFINED_TYPE && CompressionStream,
325
335
  DecompressionStream: typeof DecompressionStream != UNDEFINED_TYPE && DecompressionStream
326
336
  };
@@ -334,8 +344,7 @@ const URI_PROPERTY_NAMES = [
334
344
  ];
335
345
  const BOOLEAN_PROPERTY_NAMES = [
336
346
  "useCompressionStream",
337
- "useWebWorkers",
338
- "transferStreams"
347
+ "useWebWorkers"
339
348
  ];
340
349
  const NUMBER_PROPERTY_NAMES = [
341
350
  "chunkSize",
@@ -1276,12 +1285,12 @@ let createEngine = createEngine$1;
1276
1285
  class AESDecryptionStream extends TransformStream {
1277
1286
 
1278
1287
  constructor({ password, rawPassword, encryptionStrength, checkPasswordOnly, checkAuthenticationCode = true }) {
1288
+ const aesCrypto = {};
1279
1289
  super({
1280
1290
  start() {
1281
- initAesCrypto(this, password, rawPassword, encryptionStrength);
1291
+ initAesCrypto(aesCrypto, password, rawPassword, encryptionStrength);
1282
1292
  },
1283
1293
  async transform(chunk, controller) {
1284
- const aesCrypto = this;
1285
1294
  const {
1286
1295
  password,
1287
1296
  strength,
@@ -1300,6 +1309,9 @@ class AESDecryptionStream extends TransformStream {
1300
1309
  } else {
1301
1310
  await ready;
1302
1311
  }
1312
+ if (aesCrypto.discarded) {
1313
+ return;
1314
+ }
1303
1315
  const output = new Uint8Array(chunk.length - AUTHENTICATION_CODE_LENGTH - ((chunk.length - AUTHENTICATION_CODE_LENGTH) % BLOCK_LENGTH));
1304
1316
  controller.enqueue(append(aesCrypto, chunk, output, 0, AUTHENTICATION_CODE_LENGTH, true));
1305
1317
  },
@@ -1308,9 +1320,12 @@ class AESDecryptionStream extends TransformStream {
1308
1320
  engine,
1309
1321
  pendingInput,
1310
1322
  ready
1311
- } = this;
1323
+ } = aesCrypto;
1312
1324
  if (engine) {
1313
1325
  await ready;
1326
+ if (aesCrypto.discarded) {
1327
+ return;
1328
+ }
1314
1329
  const originalAuthenticationCode = subarray(pendingInput, pendingInput.length - AUTHENTICATION_CODE_LENGTH);
1315
1330
  const decryptedChunkArray = new Uint8Array(subarray(pendingInput, 0, pendingInput.length - AUTHENTICATION_CODE_LENGTH));
1316
1331
  engine.process(decryptedChunkArray, true);
@@ -1320,27 +1335,26 @@ class AESDecryptionStream extends TransformStream {
1320
1335
  invalidAuthenticationCode |= authenticationCode[indexByte] ^ originalAuthenticationCode[indexByte];
1321
1336
  }
1322
1337
  if (invalidAuthenticationCode && checkAuthenticationCode) {
1323
- throw new Error(ERR_INVALID_AUTHENTICATION_CODE);
1338
+ controller.error(new Error(ERR_INVALID_AUTHENTICATION_CODE));
1339
+ return;
1324
1340
  }
1325
1341
  controller.enqueue(decryptedChunkArray);
1326
1342
  }
1327
- },
1328
- cancel() {
1329
- disposeEngine(this);
1330
1343
  }
1331
1344
  });
1345
+ setDisposingReadable(this, aesCrypto);
1332
1346
  }
1333
1347
  }
1334
1348
 
1335
1349
  class AESEncryptionStream extends TransformStream {
1336
1350
 
1337
1351
  constructor({ password, rawPassword, encryptionStrength }) {
1352
+ const aesCrypto = {};
1338
1353
  super({
1339
1354
  start() {
1340
- initAesCrypto(this, password, rawPassword, encryptionStrength);
1355
+ initAesCrypto(aesCrypto, password, rawPassword, encryptionStrength);
1341
1356
  },
1342
1357
  async transform(chunk, controller) {
1343
- const aesCrypto = this;
1344
1358
  const {
1345
1359
  password,
1346
1360
  strength,
@@ -1354,6 +1368,9 @@ class AESEncryptionStream extends TransformStream {
1354
1368
  } else {
1355
1369
  await ready;
1356
1370
  }
1371
+ if (aesCrypto.discarded) {
1372
+ return;
1373
+ }
1357
1374
  const output = new Uint8Array(preamble.length + chunk.length - (chunk.length % BLOCK_LENGTH));
1358
1375
  output.set(preamble, 0);
1359
1376
  controller.enqueue(append(aesCrypto, chunk, output, preamble.length, 0, false));
@@ -1363,19 +1380,20 @@ class AESEncryptionStream extends TransformStream {
1363
1380
  engine,
1364
1381
  pendingInput,
1365
1382
  ready
1366
- } = this;
1383
+ } = aesCrypto;
1367
1384
  if (engine) {
1368
1385
  await ready;
1386
+ if (aesCrypto.discarded) {
1387
+ return;
1388
+ }
1369
1389
  const encryptedChunkArray = new Uint8Array(pendingInput);
1370
1390
  engine.process(encryptedChunkArray, false);
1371
1391
  const authenticationCode = subarray(engine.digest(), 0, AUTHENTICATION_CODE_LENGTH);
1372
1392
  controller.enqueue(concat(encryptedChunkArray, authenticationCode));
1373
1393
  }
1374
- },
1375
- cancel() {
1376
- disposeEngine(this);
1377
1394
  }
1378
1395
  });
1396
+ setDisposingReadable(this, aesCrypto);
1379
1397
  }
1380
1398
  }
1381
1399
 
@@ -1384,7 +1402,37 @@ function initAesCrypto(aesCrypto, password, rawPassword, encryptionStrength) {
1384
1402
  ready: new Promise(resolve => aesCrypto.resolveReady = resolve),
1385
1403
  password: encodePassword(password, rawPassword),
1386
1404
  strength: encryptionStrength - 1,
1387
- pendingInput: EMPTY_UINT8_ARRAY
1405
+ pendingInput: EMPTY_UINT8_ARRAY,
1406
+ discarded: false
1407
+ });
1408
+ }
1409
+
1410
+ function setDisposingReadable(stream, aesCrypto) {
1411
+ const reader = stream.readable.getReader();
1412
+ const readable = new ReadableStream({
1413
+ async pull(controller) {
1414
+ try {
1415
+ const { value, done } = await reader.read();
1416
+ if (done) {
1417
+ controller.close();
1418
+ } else {
1419
+ controller.enqueue(value);
1420
+ }
1421
+ } catch (error) {
1422
+ disposeEngine(aesCrypto);
1423
+ reader.cancel(error).catch(() => { });
1424
+ throw error;
1425
+ }
1426
+ },
1427
+ cancel(reason) {
1428
+ disposeEngine(aesCrypto);
1429
+ return reader.cancel(reason);
1430
+ }
1431
+ });
1432
+ Object.defineProperty(stream, "readable", {
1433
+ get() {
1434
+ return readable;
1435
+ }
1388
1436
  });
1389
1437
  }
1390
1438
 
@@ -1417,7 +1465,9 @@ async function createDecryptionKeys(decrypt, strength, password, preamble) {
1417
1465
  }
1418
1466
  }
1419
1467
 
1420
- function disposeEngine({ engine }) {
1468
+ function disposeEngine(aesCrypto) {
1469
+ const { engine } = aesCrypto;
1470
+ aesCrypto.discarded = true;
1421
1471
  if (engine && engine.dispose) {
1422
1472
  engine.dispose();
1423
1473
  }
@@ -1434,6 +1484,9 @@ async function createKeys$1(aesCrypto, strength, password, salt) {
1434
1484
  const keyLength = KEY_LENGTH[strength];
1435
1485
  const compositeKey = await deriveKey(password, salt, keyLength * 2 + PASSWORD_VERIFICATION_LENGTH);
1436
1486
  aesCrypto.engine = createEngine(subarray(compositeKey, 0, keyLength), subarray(compositeKey, keyLength, keyLength * 2));
1487
+ if (aesCrypto.discarded) {
1488
+ disposeEngine(aesCrypto);
1489
+ }
1437
1490
  return subarray(compositeKey, keyLength * 2);
1438
1491
  }
1439
1492
 
@@ -1585,11 +1638,11 @@ function encrypt(target, input) {
1585
1638
  }
1586
1639
 
1587
1640
  function createKeys(target, password, rawPassword) {
1588
- const keys = [0x12345678, 0x23456789, 0x34567890];
1641
+ const cryptoKeys = [0x12345678, 0x23456789, 0x34567890];
1589
1642
  Object.assign(target, {
1590
- keys,
1591
- crcKey0: new Crc32(keys[0]),
1592
- crcKey2: new Crc32(keys[2])
1643
+ cryptoKeys,
1644
+ crcKey0: new Crc32(cryptoKeys[0]),
1645
+ crcKey2: new Crc32(cryptoKeys[2])
1593
1646
  });
1594
1647
  if (rawPassword) {
1595
1648
  for (let index = 0; index < rawPassword.length; index++) {
@@ -1603,17 +1656,17 @@ function createKeys(target, password, rawPassword) {
1603
1656
  }
1604
1657
 
1605
1658
  function updateKeys(target, byte) {
1606
- let [, key1] = target.keys;
1659
+ let [, key1] = target.cryptoKeys;
1607
1660
  target.crcKey0.append([byte]);
1608
1661
  const key0 = ~target.crcKey0.get();
1609
1662
  key1 = getInt32(Math.imul(getInt32(key1 + getInt8(key0)), 134775813) + 1);
1610
1663
  target.crcKey2.append([key1 >>> 24]);
1611
1664
  const key2 = ~target.crcKey2.get();
1612
- target.keys = [key0, key1, key2];
1665
+ target.cryptoKeys = [key0, key1, key2];
1613
1666
  }
1614
1667
 
1615
1668
  function getByte(target) {
1616
- const temp = target.keys[2] | 2;
1669
+ const temp = target.cryptoKeys[2] | 2;
1617
1670
  return getInt8(Math.imul(temp, (temp ^ 1)) >>> 8);
1618
1671
  }
1619
1672
 
@@ -1661,11 +1714,16 @@ function toCompatibleReadable(readable) {
1661
1714
  const reader = readable.getReader();
1662
1715
  return new ReadableStream({
1663
1716
  async pull(controller) {
1664
- const { value, done } = await reader.read();
1665
- if (done) {
1666
- controller.close();
1667
- } else {
1668
- controller.enqueue(value);
1717
+ try {
1718
+ const { value, done } = await reader.read();
1719
+ if (done) {
1720
+ controller.close();
1721
+ } else {
1722
+ controller.enqueue(value);
1723
+ }
1724
+ } catch (error) {
1725
+ reader.cancel(error).catch(() => { });
1726
+ throw error;
1669
1727
  }
1670
1728
  },
1671
1729
  cancel(reason) {
@@ -1844,14 +1902,15 @@ async function ensureCodecStreams(format, codecURI) {
1844
1902
 
1845
1903
  const ERR_INVALID_UNCOMPRESSED_SIZE = "Invalid uncompressed size";
1846
1904
  const ERR_INVALID_COMPRESSED_DATA = "Invalid compressed data";
1905
+ const ERR_CODEC_OUT_OF_MEMORY = "Codec out of memory";
1847
1906
  const ERR_INVALID_CRC32 = "Invalid CRC32";
1907
+ const Z_MEM_ERROR_CODE = "Z_MEM_ERROR";
1848
1908
  const FORMAT_DEFLATE_RAW = "deflate-raw";
1849
1909
  const FORMAT_DEFLATE64_RAW = "deflate64-raw";
1850
1910
  const FORMAT_GZIP = "gzip";
1851
1911
  const GZIP_HEADER_LENGTH = 10;
1852
1912
  const GZIP_TRAILER_LENGTH = 8;
1853
1913
  const GZIP_HEADER_BYTES = [0x1f, 0x8b, 0x08];
1854
- const GZIP_OUTPUT_STALL_TIMEOUT = 5000;
1855
1914
 
1856
1915
  class DeflateStream extends TransformStream {
1857
1916
 
@@ -1862,7 +1921,7 @@ class DeflateStream extends TransformStream {
1862
1921
  let crc32Stream, encryptionStream, gzipCrc32Stream;
1863
1922
  let readable = super.readable;
1864
1923
  const codecStreams = format && getCodecStreams(format);
1865
- const GzipCompressionStream = getGzipCompressionStream(useCompressionStream, CompressionStream, CompressionStreamFallback);
1924
+ const GzipCompressionStream = getGzipCodecStream(useCompressionStream, CompressionStream, CompressionStreamFallback);
1866
1925
  const useGzipCrc32 = computeCrc32 && compressed && !deflate64 && !codecStreams && (!encrypted || zipCrypto) && Boolean(GzipCompressionStream);
1867
1926
  if ((!encrypted || zipCrypto) && computeCrc32 && !useGzipCrc32) {
1868
1927
  crc32Stream = new Crc32Stream();
@@ -1879,11 +1938,14 @@ class DeflateStream extends TransformStream {
1879
1938
  try {
1880
1939
  readable = pipeThroughCompressionStream(readable, useCompressionStream, { level, chunkSize }, CompressionStream, CompressionStreamFallback);
1881
1940
  } catch (error) {
1941
+ if (!useCompressionStream && CompressionStreamFallback) {
1942
+ throw mapMemoryError(error);
1943
+ }
1882
1944
  let gzipStream;
1883
1945
  try {
1884
1946
  gzipStream = new CompressionStream(FORMAT_GZIP);
1885
1947
  } catch {
1886
- throw error;
1948
+ throw mapMemoryError(error);
1887
1949
  }
1888
1950
  readable = pipeThroughBackpressured(readable, gzipStream);
1889
1951
  readable = pipeThrough(readable, new GzipToRawDeflateStream());
@@ -1947,72 +2009,123 @@ class GzipToRawDeflateStream extends TransformStream {
1947
2009
  }
1948
2010
  }
1949
2011
 
1950
- function pipeThroughGzipDecompressionStream(readable, gzipStream, outputSize, crc32) {
2012
+ function pipeThroughGzipDecompressionStream(readable, gzipStream, outputSize, crc32, sourceErrors) {
2013
+ const writer = gzipStream.writable.getWriter();
2014
+ const reader = gzipStream.readable.getReader();
2015
+ const outputCrc32 = crc32 === UNDEFINED_VALUE ? new Crc32() : UNDEFINED_VALUE;
1951
2016
  let outputLength = 0;
1952
- let inputDone = false;
1953
- let watchdogTimeout;
1954
- let resolveTrailerReady, rejectTrailerReady;
1955
- const trailerReady = new Promise((resolve, reject) => {
1956
- resolveTrailerReady = resolve;
1957
- rejectTrailerReady = reject;
2017
+ let trailerWritten = false;
2018
+ let settled = false;
2019
+ let resolvePull, controller;
2020
+ const output = new ReadableStream({
2021
+ start(streamController) {
2022
+ controller = streamController;
2023
+ },
2024
+ pull() {
2025
+ resumePump();
2026
+ },
2027
+ cancel(reason) {
2028
+ settled = true;
2029
+ resumePump();
2030
+ return reader.cancel(reason);
2031
+ }
1958
2032
  });
1959
- trailerReady.catch(() => { });
1960
- if (!outputSize) {
1961
- resolveTrailerReady();
1962
- }
1963
- const gzipWrapStream = new TransformStream({
1964
- start(controller) {
2033
+ pump();
2034
+ drain();
2035
+ return output;
2036
+
2037
+ async function pump() {
2038
+ const inputReader = readable.getReader();
2039
+ try {
1965
2040
  const header = new Uint8Array(GZIP_HEADER_LENGTH);
1966
2041
  header.set(GZIP_HEADER_BYTES);
1967
- controller.enqueue(header);
1968
- },
1969
- transform(chunk, controller) {
1970
- controller.enqueue(chunk);
1971
- },
1972
- async flush(controller) {
1973
- inputDone = true;
1974
- startWatchdog();
1975
- try {
1976
- await trailerReady;
1977
- } finally {
1978
- stopWatchdog();
2042
+ await writer.write(header);
2043
+ for (; ;) {
2044
+ await outputCapacity();
2045
+ await writer.ready;
2046
+ const { value, done } = await readSource(inputReader, sourceErrors);
2047
+ if (done) {
2048
+ break;
2049
+ }
2050
+ await writer.write(value);
2051
+ }
2052
+ if (outputCrc32) {
2053
+ await writer.write(new Uint8Array(0));
1979
2054
  }
1980
2055
  const trailer = new Uint8Array(GZIP_TRAILER_LENGTH);
1981
2056
  const dataView = getDataView(trailer);
1982
- dataView.setUint32(0, crc32.get(), true);
2057
+ dataView.setUint32(0, outputCrc32 ? outputCrc32.get() : crc32, true);
1983
2058
  dataView.setUint32(4, outputSize, true);
1984
- controller.enqueue(trailer);
1985
- },
1986
- cancel(reason) {
1987
- rejectTrailerReady(reason);
2059
+ trailerWritten = true;
2060
+ await writer.write(trailer);
2061
+ await writer.close();
2062
+ } catch (error) {
2063
+ await abort(writer, error);
2064
+ await cancel(inputReader, error);
1988
2065
  }
1989
- });
1990
- const outputStream = new TransformStream({
1991
- transform(chunk, controller) {
1992
- crc32.append(chunk);
1993
- outputLength += chunk.length;
1994
- if (outputLength >= outputSize) {
1995
- resolveTrailerReady();
1996
- } else if (inputDone) {
1997
- startWatchdog();
2066
+ }
2067
+
2068
+ async function drain() {
2069
+ try {
2070
+ for (; ;) {
2071
+ const { value, done } = await read();
2072
+ if (done) {
2073
+ break;
2074
+ }
2075
+ outputLength += value.length;
2076
+ if (outputLength > outputSize) {
2077
+ throw new Error(ERR_INVALID_UNCOMPRESSED_SIZE);
2078
+ }
2079
+ if (outputCrc32) {
2080
+ outputCrc32.append(value);
2081
+ }
2082
+ controller.enqueue(value);
1998
2083
  }
1999
- controller.enqueue(chunk);
2000
- },
2001
- cancel(reason) {
2002
- rejectTrailerReady(reason);
2084
+ if (!settled) {
2085
+ settled = true;
2086
+ controller.close();
2087
+ }
2088
+ } catch (error) {
2089
+ fail(error);
2090
+ await cancel(reader, error);
2003
2091
  }
2004
- });
2005
- readable = pipeThrough(readable, gzipWrapStream);
2006
- readable = pipeThroughBackpressured(readable, gzipStream);
2007
- return pipeThrough(readable, outputStream);
2092
+ }
2093
+
2094
+ function read() {
2095
+ return reader.read().catch(error => {
2096
+ if (trailerWritten) {
2097
+ if (!outputCrc32) {
2098
+ throw mapError(error, ERR_INVALID_CRC32);
2099
+ }
2100
+ if (outputLength != outputSize) {
2101
+ throw mapError(error, ERR_INVALID_UNCOMPRESSED_SIZE);
2102
+ }
2103
+ return { done: true };
2104
+ }
2105
+ throw mapCodecError(error, sourceErrors);
2106
+ });
2107
+ }
2008
2108
 
2009
- function startWatchdog() {
2010
- stopWatchdog();
2011
- watchdogTimeout = setTimeout(() => rejectTrailerReady(new Error(ERR_INVALID_UNCOMPRESSED_SIZE)), GZIP_OUTPUT_STALL_TIMEOUT);
2109
+ function outputCapacity() {
2110
+ if (!settled && controller.desiredSize <= 0) {
2111
+ return new Promise(resolve => resolvePull = resolve);
2112
+ }
2012
2113
  }
2013
2114
 
2014
- function stopWatchdog() {
2015
- clearTimeout(watchdogTimeout);
2115
+ function resumePump() {
2116
+ if (resolvePull) {
2117
+ const resolve = resolvePull;
2118
+ resolvePull = UNDEFINED_VALUE;
2119
+ resolve();
2120
+ }
2121
+ }
2122
+
2123
+ function fail(error) {
2124
+ if (!settled) {
2125
+ settled = true;
2126
+ controller.error(error);
2127
+ resumePump();
2128
+ }
2016
2129
  }
2017
2130
  }
2018
2131
 
@@ -2032,35 +2145,49 @@ class InflateStream extends TransformStream {
2032
2145
  }
2033
2146
  }
2034
2147
  if (compressed) {
2148
+ const sourceErrors = new Set();
2035
2149
  const codecStreams = format && getCodecStreams(format);
2150
+ let gzipStream;
2036
2151
  if (codecStreams) {
2037
- readable = pipeThroughBackpressured(readable, createCodecStream(codecStreams.DecompressionStream, format, { chunkSize, compressionMethod, rawBitFlag, uncompressedSize: outputSize }));
2152
+ readable = pipeThroughBackpressured(readable, createCodecStream(codecStreams.DecompressionStream, format, { chunkSize, compressionMethod, rawBitFlag, uncompressedSize: outputSize }), sourceErrors);
2038
2153
  } else {
2039
- try {
2040
- readable = pipeThroughCompressionStream(readable, useCompressionStream, { chunkSize, deflate64 }, DecompressionStream, DecompressionStreamFallback);
2041
- } catch (error) {
2042
- if (deflate64 || outputSize === UNDEFINED_VALUE) {
2043
- throw error;
2044
- }
2045
- let gzipStream;
2154
+ const GzipDecompressionStream = getGzipCodecStream(useCompressionStream, DecompressionStream, DecompressionStreamFallback);
2155
+ if (checkCrc32 && !deflate64 && crc32 !== UNDEFINED_VALUE && outputSize !== UNDEFINED_VALUE && GzipDecompressionStream) {
2046
2156
  try {
2047
- gzipStream = new DecompressionStream(FORMAT_GZIP);
2157
+ gzipStream = new GzipDecompressionStream(FORMAT_GZIP, { chunkSize });
2048
2158
  } catch {
2049
- throw error;
2159
+ gzipStream = UNDEFINED_VALUE;
2160
+ }
2161
+ }
2162
+ if (!gzipStream) {
2163
+ try {
2164
+ readable = pipeThroughCompressionStream(readable, useCompressionStream, { chunkSize, deflate64 }, DecompressionStream, DecompressionStreamFallback, sourceErrors);
2165
+ } catch (error) {
2166
+ if (deflate64 || outputSize === UNDEFINED_VALUE || (!useCompressionStream && DecompressionStreamFallback)) {
2167
+ throw mapMemoryError(error);
2168
+ }
2169
+ try {
2170
+ gzipStream = new DecompressionStream(FORMAT_GZIP);
2171
+ } catch {
2172
+ throw mapMemoryError(error);
2173
+ }
2050
2174
  }
2051
- gzipCrc32 = new Crc32();
2052
- readable = pipeThroughGzipDecompressionStream(readable, gzipStream, outputSize, gzipCrc32);
2053
2175
  }
2054
2176
  }
2055
- readable = mapInflateStreamError(readable);
2177
+ if (gzipStream) {
2178
+ gzipCrc32 = true;
2179
+ readable = pipeThroughGzipDecompressionStream(readable, gzipStream, outputSize, crc32, sourceErrors);
2180
+ } else {
2181
+ readable = mapInflateStreamError(readable, sourceErrors);
2182
+ }
2056
2183
  }
2057
2184
  if (checkCrc32 && !gzipCrc32) {
2058
2185
  crc32Stream = new Crc32Stream();
2059
2186
  readable = pipeThrough(readable, crc32Stream);
2060
2187
  }
2061
2188
  setReadable(this, readable, () => {
2062
- if (checkCrc32) {
2063
- const computedCrc32 = gzipCrc32 ? gzipCrc32.get() >>> 0 : new DataView(crc32Stream.value.buffer).getUint32(0, false);
2189
+ if (crc32Stream) {
2190
+ const computedCrc32 = new DataView(crc32Stream.value.buffer).getUint32(0, false);
2064
2191
  if (crc32 != computedCrc32) {
2065
2192
  throw new Error(ERR_INVALID_CRC32);
2066
2193
  }
@@ -2117,15 +2244,15 @@ function createCodecStream(CodecStreamClass, format, options) {
2117
2244
  return new CodecStreamClass(format, options);
2118
2245
  }
2119
2246
 
2120
- function getGzipCompressionStream(useCompressionStream, CompressionStreamNative, CompressionStreamFallback) {
2121
- if (useCompressionStream && CompressionStreamNative) {
2122
- return CompressionStreamNative;
2123
- } else if (CompressionStreamFallback && CompressionStreamFallback.requiresModule) {
2124
- return CompressionStreamFallback;
2247
+ function getGzipCodecStream(useCompressionStream, CodecStreamNative, CodecStreamFallback) {
2248
+ if (useCompressionStream && CodecStreamNative) {
2249
+ return CodecStreamNative;
2250
+ } else if (CodecStreamFallback && CodecStreamFallback.requiresModule) {
2251
+ return CodecStreamFallback;
2125
2252
  }
2126
2253
  }
2127
2254
 
2128
- function pipeThroughCompressionStream(readable, useCompressionStream, options, CompressionStreamNative, CompressionStreamFallback) {
2255
+ function pipeThroughCompressionStream(readable, useCompressionStream, options, CompressionStreamNative, CompressionStreamFallback, sourceErrors) {
2129
2256
  const Stream = useCompressionStream && CompressionStreamNative ?
2130
2257
  CompressionStreamNative :
2131
2258
  CompressionStreamFallback || CompressionStreamNative;
@@ -2140,14 +2267,14 @@ function pipeThroughCompressionStream(readable, useCompressionStream, options, C
2140
2267
  throw error;
2141
2268
  }
2142
2269
  }
2143
- return pipeThroughBackpressured(readable, codecStream);
2270
+ return pipeThroughBackpressured(readable, codecStream, sourceErrors);
2144
2271
  }
2145
2272
 
2146
2273
  function pipeThrough(readable, transformStream) {
2147
2274
  return toCompatibleReadable(readable).pipeThrough(transformStream);
2148
2275
  }
2149
2276
 
2150
- function pipeThroughBackpressured(readable, transformStream) {
2277
+ function pipeThroughBackpressured(readable, transformStream, sourceErrors) {
2151
2278
  const writer = transformStream.writable.getWriter();
2152
2279
  const reader = readable.getReader();
2153
2280
  pump();
@@ -2157,7 +2284,7 @@ function pipeThroughBackpressured(readable, transformStream) {
2157
2284
  try {
2158
2285
  for (; ;) {
2159
2286
  await writer.ready;
2160
- const result = await reader.read();
2287
+ const result = await readSource(reader, sourceErrors);
2161
2288
  if (result.done) {
2162
2289
  await writer.close();
2163
2290
  break;
@@ -2187,26 +2314,49 @@ async function cancel(reader, error) {
2187
2314
  }
2188
2315
  }
2189
2316
 
2190
- function mapInflateStreamError(readable) {
2317
+ function readSource(reader, sourceErrors) {
2318
+ const result = reader.read();
2319
+ return sourceErrors ? result.catch(error => {
2320
+ sourceErrors.add(error);
2321
+ throw error;
2322
+ }) : result;
2323
+ }
2324
+
2325
+ function mapCodecError(error, sourceErrors) {
2326
+ if (sourceErrors.has(error)) {
2327
+ return error;
2328
+ }
2329
+ return mapError(error, isMemoryError(error) ? ERR_CODEC_OUT_OF_MEMORY : ERR_INVALID_COMPRESSED_DATA);
2330
+ }
2331
+
2332
+ function mapMemoryError(error) {
2333
+ return isMemoryError(error) ? mapError(error, ERR_CODEC_OUT_OF_MEMORY) : error;
2334
+ }
2335
+
2336
+ function isMemoryError(error) {
2337
+ return isErrorObject(error) && error.code == Z_MEM_ERROR_CODE;
2338
+ }
2339
+
2340
+ function mapError(error, message) {
2341
+ const mappedError = new Error(message);
2342
+ mappedError.cause = error;
2343
+ return mappedError;
2344
+ }
2345
+
2346
+ function mapInflateStreamError(readable, sourceErrors) {
2191
2347
  const reader = readable.getReader();
2192
2348
  return new ReadableStream({
2193
2349
  async pull(controller) {
2194
- let result;
2195
2350
  try {
2196
- result = await reader.read();
2197
- } catch (error) {
2198
- if (error && error.message) {
2199
- throw error;
2351
+ const { value, done } = await reader.read();
2352
+ if (done) {
2353
+ controller.close();
2354
+ } else {
2355
+ controller.enqueue(value);
2200
2356
  }
2201
- const mappedError = new Error(ERR_INVALID_COMPRESSED_DATA);
2202
- mappedError.cause = error;
2203
- throw mappedError;
2204
- }
2205
- const { value, done } = result;
2206
- if (done) {
2207
- controller.close();
2208
- } else {
2209
- controller.enqueue(value);
2357
+ } catch (error) {
2358
+ await cancel(reader, error);
2359
+ throw mapCodecError(error, sourceErrors);
2210
2360
  }
2211
2361
  },
2212
2362
  cancel(reason) {
@@ -2244,7 +2394,7 @@ function mapInflateStreamError(readable) {
2244
2394
  */
2245
2395
 
2246
2396
 
2247
- const DEFAULT_CHUNK_SIZE = 64 * 1024;
2397
+ const DEFAULT_CHUNK_SIZE = 256 * 1024;
2248
2398
  const MESSAGE_EVENT_TYPE = "message";
2249
2399
  const MESSAGE_START = "start";
2250
2400
  const MESSAGE_PULL = "pull";
@@ -2450,7 +2600,7 @@ function disableWebWorker(workerData) {
2450
2600
  class CodecWorker {
2451
2601
 
2452
2602
  constructor(workerData, { readable, writable }, workerOptions, onTaskFinished) {
2453
- const { options, config, streamOptions, useWebWorkers, transferStreams, workerURI } = workerOptions;
2603
+ const { options, config, streamOptions, useWebWorkers, workerURI } = workerOptions;
2454
2604
  let { createWorker } = workerOptions;
2455
2605
  const { signal } = streamOptions;
2456
2606
  if (createWorkerFailed) {
@@ -2467,7 +2617,6 @@ class CodecWorker {
2467
2617
  workerOptions,
2468
2618
  workerURI,
2469
2619
  createWorker,
2470
- transferStreams,
2471
2620
  terminate() {
2472
2621
  return new Promise(resolve => {
2473
2622
  const { worker, busy } = workerData;
@@ -2570,10 +2719,11 @@ async function runWorker$1({ options, readable, writable, onTaskFinished, worker
2570
2719
  }
2571
2720
  codecStream = new CodecStream(options, config);
2572
2721
  chunkStream = new ChunkStream(getChunkSize(config));
2722
+ const { signal } = workerOptions.streamOptions;
2573
2723
  await readable
2574
2724
  .pipeThrough(codecStream)
2575
2725
  .pipeThrough(chunkStream)
2576
- .pipeTo(writable, { preventClose: true, preventAbort: true });
2726
+ .pipeTo(writable, { preventClose: true, preventAbort: true, signal });
2577
2727
  const {
2578
2728
  crc32,
2579
2729
  inputSize,
@@ -2641,14 +2791,9 @@ async function runWorker$1({ options, readable, writable, onTaskFinished, worker
2641
2791
  const MODULE_WORKER_OPTIONS = { type: "module" };
2642
2792
  const ERROR_EVENT_TYPE = "error";
2643
2793
  const MESSAGE_ERROR_EVENT_TYPE = "messageerror";
2794
+ const ABORT_EVENT_TYPE = "abort";
2644
2795
 
2645
2796
  let webWorkerSource, webWorkerURI, webWorkerOptions;
2646
- let transferStreamsSupported = true;
2647
- try {
2648
- transferStreamsSupported = typeof structuredClone == FUNCTION_TYPE && structuredClone(new DOMException("", "AbortError")).code !== UNDEFINED_VALUE;
2649
- } catch {
2650
- // ignored
2651
- }
2652
2797
 
2653
2798
  setWebWorkerBackend(createWebWorkerInterface);
2654
2799
 
@@ -2735,14 +2880,11 @@ async function runWebWorker(workerData, config) {
2735
2880
  });
2736
2881
  const { readable, options } = workerData;
2737
2882
  const { writable, closed, abortPipe } = watchClosedStream(workerData.writable, workerData);
2738
- let streamsTransferred;
2739
2883
  try {
2740
- streamsTransferred = sendMessage({
2884
+ sendMessage({
2741
2885
  type: MESSAGE_START,
2742
2886
  options,
2743
- config,
2744
- readable,
2745
- writable
2887
+ config
2746
2888
  }, workerData);
2747
2889
  } catch (error) {
2748
2890
  abortPipe();
@@ -2754,12 +2896,10 @@ async function runWebWorker(workerData, config) {
2754
2896
  workerData.onTaskFinished();
2755
2897
  throw error;
2756
2898
  }
2757
- if (!streamsTransferred) {
2758
- Object.assign(workerData, {
2759
- reader: readable.getReader(),
2760
- writer: writable.getWriter()
2761
- });
2762
- }
2899
+ Object.assign(workerData, {
2900
+ reader: readable.getReader(),
2901
+ writer: writable.getWriter()
2902
+ });
2763
2903
  const { workerStartupTimeout } = config;
2764
2904
  if (!workerData.workerAlive && Number.isFinite(workerStartupTimeout) && workerStartupTimeout >= 0) {
2765
2905
  workerData.startupTimeout = setTimeout(() => onStartupTimeout(workerData), workerStartupTimeout);
@@ -2792,7 +2932,7 @@ async function runWebWorker(workerData, config) {
2792
2932
  }
2793
2933
 
2794
2934
  async function closeWritable() {
2795
- if (!streamsTransferred && !writable.locked) {
2935
+ if (!writable.locked) {
2796
2936
  try {
2797
2937
  await writable.getWriter().close();
2798
2938
  } catch {
@@ -2817,6 +2957,13 @@ function watchClosedStream(writableSource, workerData) {
2817
2957
  Object.assign(workerData, { destinationFailed: true, destinationError: error });
2818
2958
  }
2819
2959
  });
2960
+ const { signal } = workerData.workerOptions.streamOptions;
2961
+ if (signal) {
2962
+ const onAbort = () => abortController.abort(signal.reason);
2963
+ const removeAbortListener = () => signal.removeEventListener(ABORT_EVENT_TYPE, onAbort);
2964
+ signal.addEventListener(ABORT_EVENT_TYPE, onAbort);
2965
+ closed.then(removeAbortListener, removeAbortListener);
2966
+ }
2820
2967
  return {
2821
2968
  writable, closed, abortPipe: () => {
2822
2969
  aborting = true;
@@ -2976,31 +3123,14 @@ function onWorkerError(event, workerData) {
2976
3123
  }
2977
3124
  }
2978
3125
 
2979
- function sendMessage(message, { worker, writer, transferStreams, workerAlive }) {
3126
+ function sendMessage(message, { worker, writer }) {
2980
3127
  try {
2981
- const { value, readable, writable } = message;
2982
- const transferables = [];
3128
+ const { value } = message;
2983
3129
  if (value) {
2984
3130
  message.value = toExactUint8Array(value);
2985
- transferables.push(message.value.buffer);
2986
- }
2987
- if (transferStreams && transferStreamsSupported && workerAlive) {
2988
- if (readable) {
2989
- transferables.push(readable);
2990
- }
2991
- if (writable) {
2992
- transferables.push(writable);
2993
- }
2994
- } else {
2995
- message.readable = message.writable = null;
2996
- }
2997
- if (transferables.length) {
2998
3131
  try {
2999
- worker.postMessage(message, transferables);
3000
- return true;
3132
+ worker.postMessage(message, [message.value.buffer]);
3001
3133
  } catch {
3002
- transferStreamsSupported = false;
3003
- message.readable = message.writable = null;
3004
3134
  worker.postMessage(message);
3005
3135
  }
3006
3136
  } else {
@@ -3079,9 +3209,6 @@ function getResponseError(errorData, errorValue) {
3079
3209
  responseError = errorValue.value;
3080
3210
  } else {
3081
3211
  responseError = Object.assign(new Error(message), { stack, code, name });
3082
- if (cause) {
3083
- responseError.cause = Object.assign(new Error(cause.message), { name: cause.name });
3084
- }
3085
3212
  }
3086
3213
  if (isErrorObject(responseError)) {
3087
3214
  try {
@@ -3091,6 +3218,14 @@ function getResponseError(errorData, errorValue) {
3091
3218
  if (codecImportFailed) {
3092
3219
  responseError.codecImportFailed = true;
3093
3220
  }
3221
+ if (cause) {
3222
+ if (!isErrorObject(responseError.cause)) {
3223
+ responseError.cause = Object.assign(new Error(cause.message), { name: cause.name });
3224
+ }
3225
+ if (cause.code !== UNDEFINED_VALUE && responseError.cause.code !== cause.code) {
3226
+ responseError.cause.code = cause.code;
3227
+ }
3228
+ }
3094
3229
  if (errorValue) {
3095
3230
  if (responseError.name !== name) {
3096
3231
  responseError.name = name;
@@ -3144,7 +3279,7 @@ let indexWorker = 0;
3144
3279
 
3145
3280
  async function runWorker(stream, workerOptions) {
3146
3281
  const { options, config } = workerOptions;
3147
- const { transferStreams, useWebWorkers, useCompressionStream, compressed, checkCrc32, computeCrc32, encrypted, format, codecURI } = options;
3282
+ const { useWebWorkers, useCompressionStream, compressed, checkCrc32, computeCrc32, encrypted, format, codecURI } = options;
3148
3283
  const { workerURI, createWorker, maxWorkers } = config;
3149
3284
  if (format) {
3150
3285
  if (codecURI) {
@@ -3152,7 +3287,6 @@ async function runWorker(stream, workerOptions) {
3152
3287
  }
3153
3288
  await ensureCodecStreams(format, options.codecURI);
3154
3289
  }
3155
- workerOptions.transferStreams = !format && (transferStreams || (transferStreams === UNDEFINED_VALUE && config.transferStreams));
3156
3290
  const streamCopy = !compressed && !checkCrc32 && !computeCrc32 && !encrypted;
3157
3291
  const workerSupported = format === UNDEFINED_VALUE || Boolean(options.codecURI);
3158
3292
  workerOptions.useWebWorkers = !streamCopy && workerSupported && (useWebWorkers || (useWebWorkers === UNDEFINED_VALUE && config.useWebWorkers));
@@ -3699,10 +3833,11 @@ class FetchReader extends Reader {
3699
3833
 
3700
3834
  createReadable(options) {
3701
3835
  const reader = this;
3702
- const { useRangeHeader, forceRangeRequests, size } = reader;
3836
+ const { useRangeHeader, forceRangeRequests, size, eocdCache } = reader;
3703
3837
  if ((useRangeHeader || forceRangeRequests) && size !== UNDEFINED_VALUE) {
3704
3838
  const { offset = 0, size: readSize = size - offset } = options || {};
3705
- if (readSize > 0 && offset < size) {
3839
+ const cached = eocdCache && offset >= size - eocdCache.length;
3840
+ if (readSize > 0 && offset < size && !cached) {
3706
3841
  return createRangeReadable(reader, offset, Math.min(readSize, size - offset));
3707
3842
  }
3708
3843
  }
@@ -4623,12 +4758,9 @@ const ERR_BAD_FORMAT = "File format is not recognized";
4623
4758
  const ERR_EOCDR_NOT_FOUND = "End of central directory not found";
4624
4759
  const ERR_EOCDR_LOCATOR_ZIP64_NOT_FOUND = "End of Zip64 central directory locator not found";
4625
4760
  const ERR_CENTRAL_DIRECTORY_NOT_FOUND = "Central directory header not found";
4626
- const ERR_LOCAL_FILE_HEADER_NOT_FOUND = "Local file header not found";
4627
- const ERR_EXTRAFIELD_ZIP64_NOT_FOUND = "Zip64 extra field not found";
4628
4761
  const ERR_ENCRYPTED = "File contains encrypted entry";
4629
4762
  const ERR_UNSUPPORTED_ENCRYPTION = "Encryption method not supported";
4630
4763
  const ERR_SPLIT_ZIP_FILE = "Split zip file";
4631
- const ERR_OVERLAPPING_ENTRY = "Overlapping entry found";
4632
4764
  const ERR_ENTRY_DATA_OUT_OF_BOUNDS = "Entry data out of bounds";
4633
4765
  const ERR_AMBIGUOUS_ARCHIVE = "Ambiguous archive";
4634
4766
  const ERR_ENCRYPTED_CENTRAL_DIRECTORY = "Encrypted central directory is not supported";
@@ -4647,6 +4779,8 @@ const WARNING_APPENDED_DATA = "appended data";
4647
4779
  const WARNING_PREPENDED_DATA = "prepended data";
4648
4780
  const WARNING_PREPENDED_CENTRAL_DIRECTORY = "prepended central directory";
4649
4781
  const WARNING_TRAILING_CENTRAL_DIRECTORY_DATA = "trailing central directory data";
4782
+ const WARNING_MISMATCHED_CENTRAL_DIRECTORY_OFFSET = "mismatched central directory offset";
4783
+ const WARNING_MISSING_ZIP64_EXTRA_FIELD = "missing zip64 extra field";
4650
4784
  const WARNING_DUPLICATE_FILENAME = "duplicate filename";
4651
4785
  const WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY = "mismatched zip64 end of central directory record";
4652
4786
  const WARNING_MULTIPLE_END_OF_CENTRAL_DIRECTORY = "multiple end of central directory records";
@@ -4660,7 +4794,7 @@ const PARENT_DIRECTORY_REGEXP = /(^|[\\/])\.\.([\\/]|$)/;
4660
4794
  const CHARSET_UTF8 = "utf-8";
4661
4795
  const PROPERTY_NAME_UTF8_SUFFIX = "UTF8";
4662
4796
  const CHARSET_CP437 = "cp437";
4663
- const BITFLAG_AMBIGUITY_MASK = BITFLAG_ENCRYPTED | BITFLAG_DATA_DESCRIPTOR | BITFLAG_LANG_ENCODING_FLAG;
4797
+ const BITFLAG_AMBIGUITY_MASK = BITFLAG_ENCRYPTED | BITFLAG_DATA_DESCRIPTOR | BITFLAG_STRONG_ENCRYPTION | BITFLAG_LANG_ENCODING_FLAG;
4664
4798
  const VENDOR_VERSION_AE_1$1 = 1;
4665
4799
  const ZIP64_PROPERTIES = [
4666
4800
  [PROPERTY_NAME_UNCOMPRESSED_SIZE, MAX_32_BITS],
@@ -4690,8 +4824,9 @@ class ZipReader {
4690
4824
  constructor(reader, options = {}) {
4691
4825
  Object.assign(this, {
4692
4826
  reader: new GenericReader(reader),
4693
- options,
4694
- readRanges: { indexes: new Set(), sortedRanges: [], pendingRanges: [] }
4827
+ options: options || {},
4828
+ readRanges: { indexes: new Set(), sortedRanges: [], pendingRanges: [] },
4829
+ entriesMissingZip64ExtraField: new WeakSet()
4695
4830
  });
4696
4831
  }
4697
4832
 
@@ -4762,16 +4897,22 @@ class ZipReader {
4762
4897
  directoryDataOffset = getDiskOffset$1(reader, getUint32$1(endOfDirectoryLocatorView, 4)) + getBigUint64(endOfDirectoryLocatorView, 8);
4763
4898
  let endOfDirectoryArray = await readUint8Array(reader, directoryDataOffset, ZIP64_END_OF_CENTRAL_DIR_LENGTH);
4764
4899
  let endOfDirectoryView = getDataView(endOfDirectoryArray);
4765
- const expectedDirectoryDataOffset = endOfDirectoryInfo.offset - ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH - ZIP64_END_OF_CENTRAL_DIR_LENGTH;
4766
- if ((endOfDirectoryArray.length < ZIP64_END_OF_CENTRAL_DIR_LENGTH || getUint32$1(endOfDirectoryView, 0) != ZIP64_END_OF_CENTRAL_DIR_SIGNATURE) &&
4767
- directoryDataOffset != expectedDirectoryDataOffset && expectedDirectoryDataOffset >= 0) {
4768
- const originalDirectoryDataOffset = directoryDataOffset;
4769
- directoryDataOffset = expectedDirectoryDataOffset;
4770
- if (directoryDataOffset > originalDirectoryDataOffset) {
4771
- prependedDataLength = directoryDataOffset - originalDirectoryDataOffset;
4900
+ if (endOfDirectoryArray.length < ZIP64_END_OF_CENTRAL_DIR_LENGTH || getUint32$1(endOfDirectoryView, 0) != ZIP64_END_OF_CENTRAL_DIR_SIGNATURE) {
4901
+ const locatorOffset = endOfDirectoryInfo.offset - ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH;
4902
+ let expectedDirectoryDataOffset = locatorOffset - ZIP64_END_OF_CENTRAL_DIR_LENGTH;
4903
+ if (!await startsWithSignature(reader, expectedDirectoryDataOffset, ZIP64_END_OF_CENTRAL_DIR_SIGNATURE)) {
4904
+ expectedDirectoryDataOffset = await findZip64EndOfDirectoryOffset(reader, locatorOffset);
4905
+ }
4906
+ if (expectedDirectoryDataOffset !== UNDEFINED_VALUE && expectedDirectoryDataOffset >= 0 &&
4907
+ directoryDataOffset != expectedDirectoryDataOffset) {
4908
+ const originalDirectoryDataOffset = directoryDataOffset;
4909
+ directoryDataOffset = expectedDirectoryDataOffset;
4910
+ if (directoryDataOffset > originalDirectoryDataOffset) {
4911
+ prependedDataLength = directoryDataOffset - originalDirectoryDataOffset;
4912
+ }
4913
+ endOfDirectoryArray = await readUint8Array(reader, directoryDataOffset, ZIP64_END_OF_CENTRAL_DIR_LENGTH);
4914
+ endOfDirectoryView = getDataView(endOfDirectoryArray);
4772
4915
  }
4773
- endOfDirectoryArray = await readUint8Array(reader, directoryDataOffset, ZIP64_END_OF_CENTRAL_DIR_LENGTH);
4774
- endOfDirectoryView = getDataView(endOfDirectoryArray);
4775
4916
  }
4776
4917
  if (endOfDirectoryArray.length < ZIP64_END_OF_CENTRAL_DIR_LENGTH || getUint32$1(endOfDirectoryView, 0) != ZIP64_END_OF_CENTRAL_DIR_SIGNATURE) {
4777
4918
  throw new Error(ERR_EOCDR_LOCATOR_ZIP64_NOT_FOUND);
@@ -4809,15 +4950,13 @@ class ZipReader {
4809
4950
  reportAmbiguity(checkAmbiguity, warnings, WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY);
4810
4951
  }
4811
4952
  directoryDataOffset = getDiskOffset$1(reader, diskNumber) + getBigUint64(endOfDirectoryView, 48) + prependedDataLength;
4953
+ } else if (directoryDataOffset == MAX_32_BITS || directoryDataLength == MAX_32_BITS || diskNumber == MAX_16_BITS) {
4954
+ throw new Error(ERR_EOCDR_LOCATOR_ZIP64_NOT_FOUND);
4812
4955
  }
4813
4956
  }
4814
4957
  let declaredDirectoryDataLength = directoryDataLength;
4815
4958
  const centralDirectoryEndOffset = endOfDirectoryInfo.offset -
4816
4959
  (zip64EndOfDirectory ? zip64EndOfDirectoryLength + ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH : 0);
4817
- if (directoryDataOffset >= reader.size) {
4818
- prependedDataLength = reader.size - directoryDataOffset - directoryDataLength - END_OF_CENTRAL_DIR_LENGTH;
4819
- directoryDataOffset = reader.size - directoryDataLength - END_OF_CENTRAL_DIR_LENGTH;
4820
- }
4821
4960
  if (expectedLastDiskNumber != lastDiskNumber) {
4822
4961
  throw new Error(ERR_SPLIT_ZIP_FILE);
4823
4962
  }
@@ -4825,33 +4964,64 @@ class ZipReader {
4825
4964
  throw new Error(ERR_BAD_FORMAT);
4826
4965
  }
4827
4966
  let offset = 0;
4828
- let directoryArray = await readUint8Array(reader, directoryDataOffset, directoryDataLength);
4967
+ let directoryArray = directoryDataOffset < reader.size ?
4968
+ await readUint8Array(reader, directoryDataOffset, directoryDataLength) :
4969
+ EMPTY_UINT8_ARRAY;
4829
4970
  let directoryView = getDataView(directoryArray);
4830
4971
  if (directoryDataLength) {
4831
- if (directoryArray.length < 4) {
4832
- throw new Error(ERR_BAD_FORMAT);
4833
- }
4834
- const expectedDirectoryDataOffset = centralDirectoryEndOffset - directoryDataLength;
4972
+ let expectedDirectoryDataOffset = centralDirectoryEndOffset - directoryDataLength;
4835
4973
  if (directoryDataOffset != expectedDirectoryDataOffset && diskNumber == lastDiskNumber) {
4836
- const storedPointsAtDirectory = getUint32$1(directoryView, offset) == CENTRAL_FILE_HEADER_SIGNATURE ||
4974
+ const storedPointsAtDirectory = directoryArray.length >= 4 && (
4975
+ getUint32$1(directoryView, offset) == CENTRAL_FILE_HEADER_SIGNATURE ||
4837
4976
  Boolean(directoryEncryptionInfo && directoryEncryptionInfo.compressedSize) ||
4838
- detectEncryptedCentralDirectory(directoryView);
4977
+ detectEncryptedCentralDirectory(directoryView));
4978
+ if (!storedPointsAtDirectory && expectedDirectoryDataOffset < 0) {
4979
+ throw new Error(ERR_BAD_FORMAT);
4980
+ }
4839
4981
  let reconcile = !storedPointsAtDirectory;
4840
- if (!reconcile && expectedDirectoryDataOffset >= 0 && expectedDirectoryDataOffset + 4 <= reader.size) {
4841
- const expectedSignatureArray = await readUint8Array(reader, expectedDirectoryDataOffset, 4);
4842
- reconcile = getUint32$1(getDataView(expectedSignatureArray), 0) == CENTRAL_FILE_HEADER_SIGNATURE;
4982
+ if (expectedDirectoryDataOffset >= 0 && expectedDirectoryDataOffset + 4 <= reader.size) {
4983
+ let expectedPointsAtDirectory = await pointsAtDirectory(reader, expectedDirectoryDataOffset);
4984
+ if (!expectedPointsAtDirectory) {
4985
+ const signatureRecordOffset = await findDigitalSignatureRecordOffset(reader, centralDirectoryEndOffset);
4986
+ const signedDirectoryDataOffset = signatureRecordOffset - directoryDataLength;
4987
+ if (signatureRecordOffset !== UNDEFINED_VALUE && signedDirectoryDataOffset >= 0 &&
4988
+ await pointsAtDirectory(reader, signedDirectoryDataOffset)) {
4989
+ expectedDirectoryDataOffset = signedDirectoryDataOffset;
4990
+ expectedPointsAtDirectory = true;
4991
+ }
4992
+ }
4993
+ if (storedPointsAtDirectory) {
4994
+ reconcile = expectedPointsAtDirectory;
4995
+ }
4843
4996
  }
4844
- if (reconcile) {
4997
+ if (reconcile && expectedDirectoryDataOffset != directoryDataOffset) {
4845
4998
  const originalDirectoryDataOffset = directoryDataOffset;
4846
4999
  directoryDataOffset = expectedDirectoryDataOffset;
4847
- if (directoryDataOffset > originalDirectoryDataOffset) {
4848
- prependedDataLength += directoryDataOffset - originalDirectoryDataOffset;
4849
- prependedCentralDirectory = storedPointsAtDirectory;
4850
- }
4851
5000
  directoryArray = await readUint8Array(reader, directoryDataOffset, directoryDataLength);
4852
5001
  directoryView = getDataView(directoryArray);
5002
+ const offsetDelta = directoryDataOffset - originalDirectoryDataOffset;
5003
+ const localHeaderOffset = getFirstLocalHeaderOffset(directoryArray, directoryView);
5004
+ const localHeaderFound = localHeaderOffset !== UNDEFINED_VALUE &&
5005
+ await startsWithSignature(reader, localHeaderOffset, LOCAL_FILE_HEADER_SIGNATURE);
5006
+ const shiftedLocalHeaderFound = localHeaderOffset !== UNDEFINED_VALUE &&
5007
+ await startsWithSignature(reader, localHeaderOffset + offsetDelta, LOCAL_FILE_HEADER_SIGNATURE);
5008
+ if (offsetDelta > 0 && !(localHeaderFound && !shiftedLocalHeaderFound)) {
5009
+ prependedDataLength += offsetDelta;
5010
+ prependedCentralDirectory = storedPointsAtDirectory;
5011
+ } else {
5012
+ reportAmbiguity(checkAmbiguity, warnings, WARNING_MISMATCHED_CENTRAL_DIRECTORY_OFFSET);
5013
+ if (offsetDelta < 0 && !localHeaderFound && shiftedLocalHeaderFound) {
5014
+ prependedDataLength += offsetDelta;
5015
+ }
5016
+ }
4853
5017
  }
4854
5018
  }
5019
+ if (directoryArray.length < 4) {
5020
+ throw new Error(ERR_BAD_FORMAT);
5021
+ }
5022
+ } else if (!filesLength && directoryDataOffset < centralDirectoryEndOffset && diskNumber == lastDiskNumber) {
5023
+ prependedDataLength += centralDirectoryEndOffset - directoryDataOffset;
5024
+ directoryDataOffset = centralDirectoryEndOffset;
4855
5025
  }
4856
5026
  const expectedDirectoryDataLength = centralDirectoryEndOffset - directoryDataOffset;
4857
5027
  if (directoryDataLength != expectedDirectoryDataLength && expectedDirectoryDataLength >= 0 && diskNumber == lastDiskNumber) {
@@ -4893,8 +5063,10 @@ class ZipReader {
4893
5063
  addWarning(warnings, WARNING_WRAPPED_ENTRIES_COUNT);
4894
5064
  }
4895
5065
  }
5066
+ const entryOptions = Object.assign({}, zipReader.options, options, { [OPTION_STRICTNESS]: strictness });
5067
+ delete entryOptions[OPTION_CHECK_AMBIGUITY];
4896
5068
  for (let indexFile = 0; indexFile < filesLength; indexFile++) {
4897
- const fileEntry = new ZipEntry(reader, zipReader.options);
5069
+ const fileEntry = new ZipEntry(reader, entryOptions);
4898
5070
  if (offset + CENTRAL_FILE_HEADER_LENGTH > directoryArray.length || getUint32$1(directoryView, offset) != CENTRAL_FILE_HEADER_SIGNATURE) {
4899
5071
  if (indexFile == 0 && !decryptedDirectory && (zip64EndOfDirectoryVersion2 || detectEncryptedCentralDirectory(directoryView))) {
4900
5072
  throw new Error(ERR_ENCRYPTED_CENTRAL_DIRECTORY);
@@ -4933,17 +5105,6 @@ class ZipReader {
4933
5105
  if (filename === UNDEFINED_VALUE) {
4934
5106
  filename = decodeText(rawFilename, rawFilenameEncoding);
4935
5107
  }
4936
- if (normalizeFilename) {
4937
- const normalizedFilename = normalizeFilename(filename);
4938
- if (normalizedFilename !== UNDEFINED_VALUE) {
4939
- filename = normalizedFilename;
4940
- }
4941
- }
4942
- if (isUnsafeFilename(filename, filenameValidation)) {
4943
- const error = new Error(ERR_UNSAFE_FILENAME);
4944
- error.filename = filename;
4945
- throw error;
4946
- }
4947
5108
  let comment = decode(rawComment, rawCommentEncoding, TEXT_TYPE_COMMENT);
4948
5109
  if (comment === UNDEFINED_VALUE) {
4949
5110
  comment = decodeText(rawComment, rawCommentEncoding);
@@ -4971,16 +5132,42 @@ class ZipReader {
4971
5132
  filename,
4972
5133
  comment
4973
5134
  });
4974
- if (readCommonFooter(fileEntry, fileEntry, directoryView, offset + 6)) {
5135
+ let malformedExtraField;
5136
+ try {
5137
+ malformedExtraField = readCommonFooter(fileEntry, fileEntry, directoryView, offset + 6);
5138
+ } catch (error) {
5139
+ if (checkAmbiguity || error.message != ERR_EXTRAFIELD_ZIP64_NOT_FOUND) {
5140
+ throw error;
5141
+ }
5142
+ fileEntry.zip64ExtraFieldMissing = true;
5143
+ addWarning(warnings, WARNING_MISSING_ZIP64_EXTRA_FIELD, fileEntry.filename);
5144
+ }
5145
+ filename = fileEntry.filename;
5146
+ if (normalizeFilename) {
5147
+ const normalizedFilename = normalizeFilename(filename);
5148
+ if (normalizedFilename !== UNDEFINED_VALUE) {
5149
+ filename = fileEntry.filename = normalizedFilename;
5150
+ }
5151
+ }
5152
+ if (isUnsafeFilename(filename, filenameValidation)) {
5153
+ const error = new Error(ERR_UNSAFE_FILENAME);
5154
+ error.filename = filename;
5155
+ throw error;
5156
+ }
5157
+ if (malformedExtraField) {
4975
5158
  addWarning(warnings, WARNING_MALFORMED_EXTRA_FIELD, filename);
4976
5159
  }
4977
- fileEntry.offset += prependedDataLength;
4978
- const entryPosition = getDiskOffset$1(reader, fileEntry.diskNumberStart) + fileEntry.offset;
4979
- startOffset = Math.min(entryPosition, startOffset);
4980
- if (entryPosition < previousEntryPosition) {
4981
- addWarning(warnings, WARNING_UNSORTED_CENTRAL_DIRECTORY, filename);
5160
+ if (fileEntry.zip64ExtraFieldMissing && fileEntry.offset == MAX_32_BITS) {
5161
+ startOffset = 0;
5162
+ } else {
5163
+ fileEntry.offset += prependedDataLength;
5164
+ const entryPosition = getDiskOffset$1(reader, fileEntry.diskNumberStart) + fileEntry.offset;
5165
+ startOffset = Math.min(entryPosition, startOffset);
5166
+ if (entryPosition < previousEntryPosition) {
5167
+ addWarning(warnings, WARNING_UNSORTED_CENTRAL_DIRECTORY, filename);
5168
+ }
5169
+ previousEntryPosition = entryPosition;
4982
5170
  }
4983
- previousEntryPosition = entryPosition;
4984
5171
  if ((fileEntry.version & MAX_8_BITS) > MAX_KNOWN_VERSION) {
4985
5172
  addWarning(warnings, WARNING_UNKNOWN_VERSION, filename);
4986
5173
  }
@@ -5000,11 +5187,12 @@ class ZipReader {
5000
5187
  const sticky = Boolean(fileEntry.unixMode & FILE_ATTR_UNIX_STICKY_MASK);
5001
5188
  const unixType = fileEntry.unixMode === UNDEFINED_VALUE ? unixExternalUpper : fileEntry.unixMode;
5002
5189
  const symlink = (unixType & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_SYMLINK;
5003
- const executable = !symlink && ((fileEntry.unixMode !== UNDEFINED_VALUE)
5004
- ? ((fileEntry.unixMode & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0)
5005
- : (unixCompatible && ((unixExternalUpper & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0)));
5006
5190
  const modeIsDir = fileEntry.unixMode !== UNDEFINED_VALUE && ((fileEntry.unixMode & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_DIR);
5007
5191
  const upperIsDir = ((unixExternalUpper & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_DIR);
5192
+ const directory = modeIsDir || upperIsDir || (msDosCompatible && msdosAttributes.directory) || fileEntry.filename.endsWith(DIRECTORY_SIGNATURE);
5193
+ const executable = !symlink && !directory && ((fileEntry.unixMode !== UNDEFINED_VALUE)
5194
+ ? ((fileEntry.unixMode & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0)
5195
+ : (unixCompatible && ((unixExternalUpper & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0)));
5008
5196
  Object.assign(fileEntry, {
5009
5197
  setuid,
5010
5198
  setgid,
@@ -5012,16 +5200,19 @@ class ZipReader {
5012
5200
  symlink,
5013
5201
  unixExternalUpper,
5014
5202
  executable,
5015
- directory: modeIsDir || upperIsDir || (msDosCompatible && msdosAttributes.directory) || fileEntry.filename.endsWith(DIRECTORY_SIGNATURE),
5203
+ directory,
5016
5204
  zipCrypto: fileEntry.encrypted && !fileEntry.extraFieldAES
5017
5205
  });
5018
5206
  const entry = new Entry(fileEntry);
5019
- entry.getData = (writer, options) => fileEntry.getData(writer, entry, zipReader.readRanges, options);
5207
+ if (fileEntry.zip64ExtraFieldMissing) {
5208
+ zipReader.entriesMissingZip64ExtraField.add(entry);
5209
+ }
5210
+ entry.getData = (writer, options) => fileEntry.getData(writer, entry, zipReader, options);
5020
5211
  entry.arrayBuffer = async options => {
5021
5212
  const writer = new TransformStream();
5022
5213
  const arrayBufferPromise = streamToBlob(writer.readable).then(blob => blob.arrayBuffer());
5023
5214
  arrayBufferPromise.catch(() => { });
5024
- await fileEntry.getData(writer, entry, zipReader.readRanges,
5215
+ await fileEntry.getData(writer, entry, zipReader,
5025
5216
  Object.assign({}, options, { preventClose: false }));
5026
5217
  return arrayBufferPromise;
5027
5218
  };
@@ -5068,10 +5259,10 @@ class ZipReader {
5068
5259
  const extractAppendedData = getOptionValue$1(zipReader, options, OPTION_EXTRACT_APPENDED_DATA);
5069
5260
  const splitZipSignatureLength = (checkAmbiguity || extractPrependedData) && filesLength &&
5070
5261
  startOffset == SPLIT_ZIP_FILE_SIGNATURE_LENGTH && await startsWithSplitZipMarker(reader) ? SPLIT_ZIP_FILE_SIGNATURE_LENGTH : 0;
5071
- if (checkAmbiguity && (prependedDataLength || (filesLength && startOffset > splitZipSignatureLength))) {
5262
+ if (checkAmbiguity && (prependedDataLength > 0 || (filesLength && startOffset > splitZipSignatureLength))) {
5072
5263
  throwAmbiguousArchive(WARNING_PREPENDED_DATA);
5073
5264
  }
5074
- if (prependedDataLength || (filesLength && startOffset > SPLIT_ZIP_FILE_SIGNATURE_LENGTH)) {
5265
+ if (prependedDataLength > 0 || (filesLength && startOffset > SPLIT_ZIP_FILE_SIGNATURE_LENGTH)) {
5075
5266
  addWarning(warnings, WARNING_PREPENDED_DATA);
5076
5267
  }
5077
5268
  if (prependedCentralDirectory) {
@@ -5229,8 +5420,12 @@ class ZipEntry {
5229
5420
  });
5230
5421
  }
5231
5422
 
5232
- async getData(writer, fileEntry, readRanges, options = {}) {
5423
+ async getData(writer, fileEntry, zipReader, options = {}) {
5233
5424
  const zipEntry = this;
5425
+ const { readRanges, directoryOffset } = zipReader;
5426
+ if (zipEntry.zip64ExtraFieldMissing) {
5427
+ throw new Error(ERR_EXTRAFIELD_ZIP64_NOT_FOUND);
5428
+ }
5234
5429
  const config = getConfiguration();
5235
5430
  const {
5236
5431
  reader,
@@ -5261,8 +5456,8 @@ class ZipEntry {
5261
5456
  const passThroughCompression = Boolean(passThrough);
5262
5457
  const passThroughEncryption = passThrough === true;
5263
5458
  checkPasswordOption(password, rawPassword);
5264
- password = password && password.length && password;
5265
- rawPassword = rawPassword && rawPassword.length && rawPassword;
5459
+ password = password && password.length ? password : UNDEFINED_VALUE;
5460
+ rawPassword = rawPassword && rawPassword.length ? rawPassword : UNDEFINED_VALUE;
5266
5461
  if (extraFieldAES) {
5267
5462
  if (extraFieldAES.originalCompressionMethod != COMPRESSION_METHOD_AES) {
5268
5463
  throw new Error(ERR_UNSUPPORTED_COMPRESSION);
@@ -5301,10 +5496,10 @@ class ZipEntry {
5301
5496
  }
5302
5497
  validateLocalDirectory(zipEntry, localDirectory, rawLocalFilename, checkLocalFilename, checkLocalDirectory ? UNDEFINED_VALUE : warnings);
5303
5498
  const { lastAccessDate, creationDate, uid, gid } = localDirectory;
5304
- if (lastAccessDate) {
5499
+ if (lastAccessDate && fileEntry.lastAccessDate === UNDEFINED_VALUE) {
5305
5500
  fileEntry.lastAccessDate = lastAccessDate;
5306
5501
  }
5307
- if (creationDate) {
5502
+ if (creationDate && fileEntry.creationDate === UNDEFINED_VALUE) {
5308
5503
  fileEntry.creationDate = creationDate;
5309
5504
  }
5310
5505
  if (uid !== UNDEFINED_VALUE && fileEntry.uid === UNDEFINED_VALUE) {
@@ -5314,12 +5509,12 @@ class ZipEntry {
5314
5509
  fileEntry.gid = gid;
5315
5510
  }
5316
5511
  const checkPasswordOnly = getOptionValue$1(zipEntry, options, OPTION_CHECK_PASSWORD_ONLY);
5317
- const encrypted = zipEntry.encrypted && localDirectory.encrypted && (!passThroughEncryption || checkPasswordOnly);
5512
+ const encrypted = zipEntry.encrypted && (!passThroughEncryption || checkPasswordOnly);
5318
5513
  const zipCrypto = encrypted && !extraFieldAES;
5319
5514
  if (!passThroughEncryption) {
5320
5515
  fileEntry.zipCrypto = zipCrypto;
5321
5516
  }
5322
- if (encrypted && (localDirectory.rawBitFlag & BITFLAG_STRONG_ENCRYPTION) == BITFLAG_STRONG_ENCRYPTION) {
5517
+ if (encrypted && (zipEntry.rawBitFlag & BITFLAG_STRONG_ENCRYPTION) == BITFLAG_STRONG_ENCRYPTION) {
5323
5518
  throw new Error(ERR_UNSUPPORTED_ENCRYPTION);
5324
5519
  }
5325
5520
  const registeredCodec = passThroughCompression ? UNDEFINED_VALUE : getRegisteredCodec(compressionMethod);
@@ -5333,7 +5528,7 @@ class ZipEntry {
5333
5528
  throw new Error(ERR_ENCRYPTED);
5334
5529
  }
5335
5530
  }
5336
- if (dataOffset + compressedSize > reader.size) {
5531
+ if (dataOffset + compressedSize > Math.min(reader.size, directoryOffset)) {
5337
5532
  throw new Error(ERR_ENTRY_DATA_OUT_OF_BOUNDS);
5338
5533
  }
5339
5534
  const size = compressedSize;
@@ -5375,7 +5570,6 @@ class ZipEntry {
5375
5570
  encrypted,
5376
5571
  useWebWorkers: getOptionValue$1(zipEntry, options, OPTION_USE_WEB_WORKERS),
5377
5572
  useCompressionStream,
5378
- transferStreams: getOptionValue$1(zipEntry, options, OPTION_TRANSFER_STREAMS),
5379
5573
  deflate64,
5380
5574
  format: registeredCodec ? registeredCodec.format : UNDEFINED_VALUE,
5381
5575
  codecURI: registeredCodec ? registeredCodec.codecURI : UNDEFINED_VALUE,
@@ -5400,6 +5594,7 @@ class ZipEntry {
5400
5594
  extraFieldZip64: extraFieldZip64 || localDirectory.extraFieldZip64,
5401
5595
  readRanges
5402
5596
  });
5597
+ validateDataDescriptor(zipEntry, localDirectory, checkLocalDirectory ? UNDEFINED_VALUE : warnings);
5403
5598
  }
5404
5599
  let writable, abortError, aborted;
5405
5600
  try {
@@ -5412,16 +5607,14 @@ class ZipEntry {
5412
5607
  ({ writable } = writer);
5413
5608
  const readable = toCompatibleReadable(reader.createReadable({ offset: dataOffset, size }));
5414
5609
  const { outputSize: writtenSize } = await runWorker({ readable, writable }, workerOptions);
5610
+ throwIfAborted(signal);
5415
5611
  if (writtenSize != outputSize) {
5416
5612
  throw Object.assign(new Error(ERR_INVALID_UNCOMPRESSED_SIZE), { outputSize: writtenSize });
5417
5613
  }
5418
5614
  writer.size += writtenSize;
5419
5615
  }
5420
5616
  } catch (error) {
5421
- const { outputSize: failedOutputSize } = workerOptions;
5422
- if (failedOutputSize !== UNDEFINED_VALUE) {
5423
- writer.size += failedOutputSize;
5424
- } else if (isErrorObject(error) && error.outputSize !== UNDEFINED_VALUE) {
5617
+ if (isErrorObject(error) && error.outputSize !== UNDEFINED_VALUE) {
5425
5618
  writer.size += error.outputSize;
5426
5619
  }
5427
5620
  if (!checkPasswordOnly || !isErrorObject(error) || error.message != ERR_ABORT_CHECK_PASSWORD) {
@@ -5449,13 +5642,7 @@ class ZipEntry {
5449
5642
  }
5450
5643
 
5451
5644
  function detectEncryptedCentralDirectory(directoryView) {
5452
- const maxOffset = Math.min(directoryView.byteLength, 1024) - 3;
5453
- for (let offset = 0; offset < maxOffset; offset++) {
5454
- if (getUint32$1(directoryView, offset) == ARCHIVE_EXTRA_DATA_SIGNATURE) {
5455
- return true;
5456
- }
5457
- }
5458
- return false;
5645
+ return directoryView.byteLength >= 4 && getUint32$1(directoryView, 0) == ARCHIVE_EXTRA_DATA_SIGNATURE;
5459
5646
  }
5460
5647
 
5461
5648
  function getWrappedFilesLength(directoryView, directoryArray, offset) {
@@ -5468,6 +5655,70 @@ function getWrappedFilesLength(directoryView, directoryArray, offset) {
5468
5655
  return wrappedFilesLength % (MAX_16_BITS + 1) ? 0 : wrappedFilesLength;
5469
5656
  }
5470
5657
 
5658
+ function pointsAtDirectory(reader, offset) {
5659
+ return startsWithSignature(reader, offset, CENTRAL_FILE_HEADER_SIGNATURE);
5660
+ }
5661
+
5662
+ async function startsWithSignature(reader, offset, signature) {
5663
+ if (offset < 0 || offset + 4 > reader.size) {
5664
+ return false;
5665
+ }
5666
+ const signatureArray = await readUint8Array(reader, offset, 4);
5667
+ return getUint32$1(getDataView(signatureArray), 0) == signature;
5668
+ }
5669
+
5670
+ async function findDigitalSignatureRecordOffset(reader, endOffset) {
5671
+ const startOffset = Math.max(0, endOffset - (6 + MAX_16_BITS));
5672
+ const tailArray = await readUint8Array(reader, startOffset, endOffset - startOffset);
5673
+ const tailView = getDataView(tailArray);
5674
+ for (let indexByte = tailArray.length - 6; indexByte >= 0; indexByte--) {
5675
+ if (getUint32$1(tailView, indexByte) == DIGITAL_SIGNATURE_RECORD_SIGNATURE &&
5676
+ indexByte + 6 + getUint16$1(tailView, indexByte + 4) == tailArray.length) {
5677
+ return startOffset + indexByte;
5678
+ }
5679
+ }
5680
+ }
5681
+
5682
+ async function findZip64EndOfDirectoryOffset(reader, endOffset) {
5683
+ const startOffset = Math.max(0, endOffset - (ZIP64_END_OF_CENTRAL_DIR_LENGTH + MAX_16_BITS));
5684
+ const tailArray = await readUint8Array(reader, startOffset, endOffset - startOffset);
5685
+ const tailView = getDataView(tailArray);
5686
+ for (let indexByte = tailArray.length - ZIP64_END_OF_CENTRAL_DIR_LENGTH; indexByte >= 0; indexByte--) {
5687
+ if (getUint32$1(tailView, indexByte) == ZIP64_END_OF_CENTRAL_DIR_SIGNATURE &&
5688
+ indexByte + 12 + Number(tailView.getBigUint64(indexByte + 4, true)) == tailArray.length) {
5689
+ return startOffset + indexByte;
5690
+ }
5691
+ }
5692
+ }
5693
+
5694
+ function getFirstLocalHeaderOffset(directoryArray, directoryView) {
5695
+ if (directoryArray.length < CENTRAL_FILE_HEADER_LENGTH) {
5696
+ return UNDEFINED_VALUE;
5697
+ }
5698
+ const localHeaderOffset = getUint32$1(directoryView, 42);
5699
+ if (localHeaderOffset != MAX_32_BITS) {
5700
+ return localHeaderOffset;
5701
+ }
5702
+ let offsetExtraField = CENTRAL_FILE_HEADER_LENGTH + getUint16$1(directoryView, 28);
5703
+ const endExtraField = Math.min(offsetExtraField + getUint16$1(directoryView, 30), directoryArray.length);
5704
+ while (offsetExtraField + 4 <= endExtraField) {
5705
+ const type = getUint16$1(directoryView, offsetExtraField);
5706
+ const size = getUint16$1(directoryView, offsetExtraField + 2);
5707
+ if (type == EXTRAFIELD_TYPE_ZIP64) {
5708
+ let offsetValue = offsetExtraField + 4;
5709
+ if (getUint32$1(directoryView, 24) == MAX_32_BITS) {
5710
+ offsetValue += 8;
5711
+ }
5712
+ if (getUint32$1(directoryView, 20) == MAX_32_BITS) {
5713
+ offsetValue += 8;
5714
+ }
5715
+ return offsetValue + 8 <= endExtraField ? getBigUint64(directoryView, offsetValue) : UNDEFINED_VALUE;
5716
+ }
5717
+ offsetExtraField += 4 + size;
5718
+ }
5719
+ return UNDEFINED_VALUE;
5720
+ }
5721
+
5471
5722
  function readDigitalSignature(signatureRecordArray) {
5472
5723
  if (signatureRecordArray.length >= 6) {
5473
5724
  const signatureRecordView = getDataView(signatureRecordArray);
@@ -5557,9 +5808,18 @@ function readCommonFooter(fileEntry, directory, dataView, offset, localDirectory
5557
5808
  uncompressedSize: getUint32$1(dataView, offset + HEADER_OFFSET_UNCOMPRESSED_SIZE)
5558
5809
  });
5559
5810
  const extraFieldZip64 = extraField.get(EXTRAFIELD_TYPE_ZIP64);
5811
+ let extraFieldZip64Missing;
5560
5812
  if (extraFieldZip64) {
5561
- readExtraFieldZip64(extraFieldZip64, directory);
5813
+ if (!readExtraFieldZip64(extraFieldZip64, directory, localDirectory)) {
5814
+ malformedExtraField = true;
5815
+ }
5562
5816
  directory.extraFieldZip64 = extraFieldZip64;
5817
+ } else if (ZIP64_PROPERTIES.some(([propertyName, max]) => directory[propertyName] == max)) {
5818
+ if (localDirectory) {
5819
+ malformedExtraField = true;
5820
+ } else {
5821
+ extraFieldZip64Missing = true;
5822
+ }
5563
5823
  }
5564
5824
  const extraFieldUnicodePath = extraField.get(EXTRAFIELD_TYPE_UNICODE_PATH);
5565
5825
  if (extraFieldUnicodePath) {
@@ -5572,10 +5832,13 @@ function readCommonFooter(fileEntry, directory, dataView, offset, localDirectory
5572
5832
  directory.extraFieldUnicodeComment = extraFieldUnicodeComment;
5573
5833
  }
5574
5834
  const extraFieldAES = extraField.get(EXTRAFIELD_TYPE_AES);
5575
- if (extraFieldAES && extraFieldAES.data.length >= 7) {
5835
+ if (extraFieldAES && (compressionMethod == COMPRESSION_METHOD_AES || directory.encrypted) && extraFieldAES.data.length >= 7) {
5576
5836
  readExtraFieldAES(extraFieldAES, directory, compressionMethod);
5577
5837
  directory.extraFieldAES = extraFieldAES;
5578
5838
  } else {
5839
+ if (extraFieldAES) {
5840
+ malformedExtraField = true;
5841
+ }
5579
5842
  directory.compressionMethod = compressionMethod;
5580
5843
  }
5581
5844
  const extraFieldPkwareUnix = extraField.get(EXTRAFIELD_TYPE_PKWARE_UNIX);
@@ -5588,50 +5851,66 @@ function readCommonFooter(fileEntry, directory, dataView, offset, localDirectory
5588
5851
  readExtraFieldUnixDates(extraFieldUnixType1, directory);
5589
5852
  directory.extraFieldUnixType1 = extraFieldUnixType1;
5590
5853
  }
5854
+ const extraFieldExtendedTimestamp = extraField.get(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
5855
+ if (extraFieldExtendedTimestamp) {
5856
+ readExtraFieldExtendedTimestamp(extraFieldExtendedTimestamp, directory, localDirectory);
5857
+ directory.extraFieldExtendedTimestamp = extraFieldExtendedTimestamp;
5858
+ }
5591
5859
  const extraFieldNTFS = extraField.get(EXTRAFIELD_TYPE_NTFS);
5592
5860
  if (extraFieldNTFS) {
5593
5861
  readExtraFieldNTFS(extraFieldNTFS, directory);
5594
5862
  directory.extraFieldNTFS = extraFieldNTFS;
5595
5863
  }
5596
- const extraFieldUnix = extraField.get(EXTRAFIELD_TYPE_UNIX);
5864
+ const extraFieldInfoZip = extraField.get(EXTRAFIELD_TYPE_INFOZIP);
5597
5865
  let unixIdsRead;
5866
+ if (extraFieldInfoZip) {
5867
+ unixIdsRead = readExtraFieldUnix(extraFieldInfoZip, directory, true);
5868
+ directory.extraFieldInfoZip = extraFieldInfoZip;
5869
+ }
5870
+ const extraFieldUnix = extraField.get(EXTRAFIELD_TYPE_UNIX);
5598
5871
  if (extraFieldUnix) {
5599
- unixIdsRead = readExtraFieldUnix(extraFieldUnix, directory, false);
5872
+ readExtraFieldUnix(extraFieldUnix, unixIdsRead ? {} : directory, false);
5600
5873
  directory.extraFieldUnix = extraFieldUnix;
5601
5874
  }
5602
- if (!unixIdsRead) {
5603
- const extraFieldInfoZip = extraField.get(EXTRAFIELD_TYPE_INFOZIP);
5604
- if (extraFieldInfoZip) {
5605
- readExtraFieldUnix(extraFieldInfoZip, directory, true);
5606
- directory.extraFieldInfoZip = extraFieldInfoZip;
5607
- }
5608
- }
5609
- const extraFieldExtendedTimestamp = extraField.get(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
5610
- if (extraFieldExtendedTimestamp) {
5611
- readExtraFieldExtendedTimestamp(extraFieldExtendedTimestamp, directory, localDirectory);
5612
- directory.extraFieldExtendedTimestamp = extraFieldExtendedTimestamp;
5613
- }
5614
5875
  const extraFieldUSDZ = extraField.get(EXTRAFIELD_TYPE_USDZ);
5615
5876
  if (extraFieldUSDZ) {
5616
5877
  directory.extraFieldUSDZ = extraFieldUSDZ;
5617
5878
  }
5879
+ if (extraFieldZip64Missing) {
5880
+ throw new Error(ERR_EXTRAFIELD_ZIP64_NOT_FOUND);
5881
+ }
5618
5882
  return malformedExtraField;
5619
5883
  }
5620
5884
 
5621
- function readExtraFieldZip64(extraFieldZip64, directory) {
5885
+ function readExtraFieldZip64(extraFieldZip64, directory, localDirectory) {
5622
5886
  directory.zip64 = true;
5623
5887
  const extraFieldView = getDataView(extraFieldZip64.data);
5624
5888
  const missingProperties = ZIP64_PROPERTIES.filter(([propertyName, max]) => directory[propertyName] == max);
5625
5889
  const requiredLength = missingProperties.reduce((length, [, max]) => length + ZIP64_EXTRACTION[max].bytes, 0);
5626
5890
  if (extraFieldZip64.data.length < requiredLength) {
5891
+ if (localDirectory) {
5892
+ return false;
5893
+ }
5627
5894
  throw new Error(ERR_EXTRAFIELD_ZIP64_NOT_FOUND);
5628
5895
  }
5629
- for (let indexMissingProperty = 0, offset = 0; indexMissingProperty < missingProperties.length; indexMissingProperty++) {
5630
- const [propertyName, max] = missingProperties[indexMissingProperty];
5631
- const extraction = ZIP64_EXTRACTION[max];
5632
- directory[propertyName] = extraFieldZip64[propertyName] = extraction.getValue(extraFieldView, offset);
5633
- offset += extraction.bytes;
5896
+ const values = [];
5897
+ try {
5898
+ for (let indexMissingProperty = 0, offset = 0; indexMissingProperty < missingProperties.length; indexMissingProperty++) {
5899
+ const [, max] = missingProperties[indexMissingProperty];
5900
+ const extraction = ZIP64_EXTRACTION[max];
5901
+ values.push(extraction.getValue(extraFieldView, offset));
5902
+ offset += extraction.bytes;
5903
+ }
5904
+ } catch (error) {
5905
+ if (localDirectory) {
5906
+ return false;
5907
+ }
5908
+ throw error;
5634
5909
  }
5910
+ missingProperties.forEach(([propertyName], indexMissingProperty) => {
5911
+ directory[propertyName] = extraFieldZip64[propertyName] = values[indexMissingProperty];
5912
+ });
5913
+ return true;
5635
5914
  }
5636
5915
 
5637
5916
  function readExtraFieldUnicode(extraFieldUnicode, propertyName, rawPropertyName, directory, fileEntry) {
@@ -5813,32 +6092,13 @@ async function detectOverlappingEntry({
5813
6092
  }) {
5814
6093
  let dataDescriptorLength = 0;
5815
6094
  if (dataDescriptor) {
5816
- if (extraFieldZip64) {
5817
- dataDescriptorLength = DATA_DESCRIPTOR_RECORD_ZIP_64_LENGTH;
5818
- } else {
5819
- dataDescriptorLength = DATA_DESCRIPTOR_RECORD_LENGTH;
5820
- }
5821
- }
5822
- if (dataDescriptorLength) {
5823
- const dataDescriptorArray = await readUint8Array(reader, dataOffset + compressedSize, dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH);
5824
- const dataDescriptorView = getDataView(dataDescriptorArray);
5825
- let signature = dataDescriptorArray.length == dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH &&
5826
- getUint32$1(dataDescriptorView, 0) == DATA_DESCRIPTOR_RECORD_SIGNATURE;
5827
- if (signature) {
5828
- const signedDataDescriptor = readDataDescriptor(dataDescriptorView, DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH, extraFieldZip64);
5829
- const matchCrc32 = (fileEntry.encrypted && !fileEntry.zipCrypto) || signedDataDescriptor.crc32 == crc32;
5830
- if (matchCrc32 &&
5831
- signedDataDescriptor.compressedSize == compressedSize &&
5832
- signedDataDescriptor.uncompressedSize == uncompressedSize) {
5833
- dataDescriptorLength += DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH;
5834
- } else {
5835
- signature = false;
5836
- }
5837
- }
5838
- if (dataDescriptorArray.length >= dataDescriptorLength) {
5839
- const localDataDescriptor = readDataDescriptor(dataDescriptorView, signature ? DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH : 0, extraFieldZip64);
5840
- localDataDescriptor.signature = signature;
6095
+ const zip64 = Boolean(extraFieldZip64);
6096
+ const localDataDescriptor = await readLocalDataDescriptor(reader, dataOffset + compressedSize, { crc32, compressedSize, uncompressedSize, zip64 });
6097
+ if (localDataDescriptor) {
5841
6098
  fileEntry.localDirectory.dataDescriptor = localDataDescriptor;
6099
+ dataDescriptorLength = getDataDescriptorLength(localDataDescriptor.zip64, localDataDescriptor.signature);
6100
+ } else {
6101
+ dataDescriptorLength = getDataDescriptorLength(zip64, false);
5842
6102
  }
5843
6103
  }
5844
6104
  const range = {
@@ -5903,18 +6163,50 @@ function mergeRanges(sortedRanges, pendingRanges) {
5903
6163
  return mergedRanges;
5904
6164
  }
5905
6165
 
5906
- function readDataDescriptor(dataDescriptorView, offset, extraFieldZip64) {
6166
+ async function readLocalDataDescriptor(reader, offset, { crc32, compressedSize, uncompressedSize, zip64 }) {
6167
+ const maxLength = DATA_DESCRIPTOR_RECORD_ZIP_64_LENGTH + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH;
6168
+ const length = Math.min(maxLength, Math.max(0, reader.size - offset));
6169
+ const dataDescriptorArray = length ? await readUint8Array(reader, offset, length) : EMPTY_UINT8_ARRAY;
6170
+ const dataDescriptorView = getDataView(dataDescriptorArray);
6171
+ const candidates = [[zip64, true], [zip64, false], [!zip64, true], [!zip64, false]]
6172
+ .map(([zip64Layout, signature]) => readDataDescriptor(dataDescriptorView, zip64Layout, signature))
6173
+ .filter(candidate => candidate && candidate.compressedSize == compressedSize && candidate.uncompressedSize == uncompressedSize);
6174
+ return candidates.find(candidate => candidate.crc32 == crc32) || candidates[0] ||
6175
+ readDataDescriptor(dataDescriptorView, zip64, true) || readDataDescriptor(dataDescriptorView, zip64, false);
6176
+ }
6177
+
6178
+ async function getEntryDataDescriptorLength(reader, offset, { crc32, compressedSize, uncompressedSize, extraFieldZip64 }) {
6179
+ const dataDescriptor = await readLocalDataDescriptor(reader, offset, { crc32, compressedSize, uncompressedSize, zip64: Boolean(extraFieldZip64) });
6180
+ if (dataDescriptor && dataDescriptor.compressedSize == compressedSize && dataDescriptor.uncompressedSize == uncompressedSize) {
6181
+ return getDataDescriptorLength(dataDescriptor.zip64, dataDescriptor.signature);
6182
+ }
6183
+ }
6184
+
6185
+ function readDataDescriptor(dataDescriptorView, zip64, signature) {
6186
+ const offset = signature ? DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH : 0;
6187
+ if (dataDescriptorView.byteLength < getDataDescriptorLength(zip64, signature) ||
6188
+ (signature && getUint32$1(dataDescriptorView, 0) != DATA_DESCRIPTOR_RECORD_SIGNATURE)) {
6189
+ return UNDEFINED_VALUE;
6190
+ }
5907
6191
  const crc32 = getUint32$1(dataDescriptorView, offset);
5908
6192
  let compressedSize;
5909
6193
  let uncompressedSize;
5910
- if (extraFieldZip64) {
5911
- compressedSize = getBigUint64(dataDescriptorView, offset + 4);
5912
- uncompressedSize = getBigUint64(dataDescriptorView, offset + 12);
5913
- } else {
5914
- compressedSize = getUint32$1(dataDescriptorView, offset + 4);
5915
- uncompressedSize = getUint32$1(dataDescriptorView, offset + 8);
6194
+ try {
6195
+ if (zip64) {
6196
+ compressedSize = getBigUint64(dataDescriptorView, offset + 4);
6197
+ uncompressedSize = getBigUint64(dataDescriptorView, offset + 12);
6198
+ } else {
6199
+ compressedSize = getUint32$1(dataDescriptorView, offset + 4);
6200
+ uncompressedSize = getUint32$1(dataDescriptorView, offset + 8);
6201
+ }
6202
+ } catch {
6203
+ return UNDEFINED_VALUE;
5916
6204
  }
5917
- return { crc32, compressedSize, uncompressedSize };
6205
+ return { signature, zip64, crc32, compressedSize, uncompressedSize };
6206
+ }
6207
+
6208
+ function getDataDescriptorLength(zip64, signature) {
6209
+ return (zip64 ? DATA_DESCRIPTOR_RECORD_ZIP_64_LENGTH : DATA_DESCRIPTOR_RECORD_LENGTH) + (signature ? DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH : 0);
5918
6210
  }
5919
6211
 
5920
6212
  function getDiskOffset$1(reader, diskNumber) {
@@ -6023,7 +6315,7 @@ function getMaxAppendedDataSize(maxAppendedDataSize, strictness) {
6023
6315
  async function findEndOfCentralDirectory(reader, rejectAmbiguous, maxAppendedDataSize) {
6024
6316
  const { size } = reader;
6025
6317
  const anchoredLength = Math.min(size, END_OF_CENTRAL_DIR_LENGTH + MAX_16_BITS);
6026
- const remoteProbeBudget = { count: MAX_END_OF_CENTRAL_DIR_PROBES };
6318
+ const remoteProbeBudget = { remaining: MAX_END_OF_CENTRAL_DIR_PROBES };
6027
6319
  let endOfDirectoryInfo;
6028
6320
  let plausibleEndOfDirectoryInfo;
6029
6321
  let endOfDirectoryReachingEndCount = 0;
@@ -6116,8 +6408,8 @@ async function readSignature(reader, view, anchoredOffset, signatureOffset, size
6116
6408
  if (signatureOffset >= anchoredOffset) {
6117
6409
  return getUint32$1(view, signatureOffset - anchoredOffset);
6118
6410
  }
6119
- if (remoteProbeBudget.count > 0) {
6120
- remoteProbeBudget.count--;
6411
+ if (remoteProbeBudget.remaining > 0) {
6412
+ remoteProbeBudget.remaining--;
6121
6413
  const signatureArray = await readUint8Array(reader, signatureOffset, 4);
6122
6414
  return getUint32$1(getDataView(signatureArray), 0);
6123
6415
  }
@@ -6149,6 +6441,18 @@ function validateLocalDirectory(zipEntry, localDirectory, rawLocalFilename, chec
6149
6441
  }
6150
6442
  }
6151
6443
 
6444
+ function validateDataDescriptor(zipEntry, localDirectory, warnings) {
6445
+ const { dataDescriptor } = localDirectory;
6446
+ const maskedLocalDirectory = zipEntry.decryptedDirectory &&
6447
+ (localDirectory.rawBitFlag & BITFLAG_MASKED_LOCAL_HEADERS) == BITFLAG_MASKED_LOCAL_HEADERS;
6448
+ if (dataDescriptor && !maskedLocalDirectory &&
6449
+ ((zipEntry.crc32 !== UNDEFINED_VALUE && dataDescriptor.crc32 != zipEntry.crc32) ||
6450
+ dataDescriptor.compressedSize != zipEntry.compressedSize ||
6451
+ dataDescriptor.uncompressedSize != zipEntry.uncompressedSize)) {
6452
+ reportAmbiguity(!warnings, warnings, WARNING_MISMATCHED_LOCAL_FILE_HEADER_CRC32_OR_SIZES);
6453
+ }
6454
+ }
6455
+
6152
6456
  function reportAmbiguity(reject, warnings, reason) {
6153
6457
  if (reject) {
6154
6458
  throwAmbiguousArchive(reason);
@@ -6207,6 +6511,7 @@ var zipReader = /*#__PURE__*/Object.freeze({
6207
6511
  ERR_AMBIGUOUS_ARCHIVE: ERR_AMBIGUOUS_ARCHIVE,
6208
6512
  ERR_BAD_FORMAT: ERR_BAD_FORMAT,
6209
6513
  ERR_CENTRAL_DIRECTORY_NOT_FOUND: ERR_CENTRAL_DIRECTORY_NOT_FOUND,
6514
+ ERR_CODEC_OUT_OF_MEMORY: ERR_CODEC_OUT_OF_MEMORY,
6210
6515
  ERR_ENCRYPTED: ERR_ENCRYPTED,
6211
6516
  ERR_ENCRYPTED_CENTRAL_DIRECTORY: ERR_ENCRYPTED_CENTRAL_DIRECTORY,
6212
6517
  ERR_ENTRY_DATA_OUT_OF_BOUNDS: ERR_ENTRY_DATA_OUT_OF_BOUNDS,
@@ -6233,11 +6538,13 @@ var zipReader = /*#__PURE__*/Object.freeze({
6233
6538
  WARNING_COMPRESSED_PATCHED_DATA: WARNING_COMPRESSED_PATCHED_DATA,
6234
6539
  WARNING_DUPLICATE_FILENAME: WARNING_DUPLICATE_FILENAME,
6235
6540
  WARNING_MALFORMED_EXTRA_FIELD: WARNING_MALFORMED_EXTRA_FIELD,
6541
+ WARNING_MISMATCHED_CENTRAL_DIRECTORY_OFFSET: WARNING_MISMATCHED_CENTRAL_DIRECTORY_OFFSET,
6236
6542
  WARNING_MISMATCHED_LOCAL_FILE_HEADER_BIT_FLAG: WARNING_MISMATCHED_LOCAL_FILE_HEADER_BIT_FLAG,
6237
6543
  WARNING_MISMATCHED_LOCAL_FILE_HEADER_COMPRESSION_METHOD: WARNING_MISMATCHED_LOCAL_FILE_HEADER_COMPRESSION_METHOD,
6238
6544
  WARNING_MISMATCHED_LOCAL_FILE_HEADER_CRC32_OR_SIZES: WARNING_MISMATCHED_LOCAL_FILE_HEADER_CRC32_OR_SIZES,
6239
6545
  WARNING_MISMATCHED_LOCAL_FILE_HEADER_FILENAME: WARNING_MISMATCHED_LOCAL_FILE_HEADER_FILENAME,
6240
6546
  WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY: WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY,
6547
+ WARNING_MISSING_ZIP64_EXTRA_FIELD: WARNING_MISSING_ZIP64_EXTRA_FIELD,
6241
6548
  WARNING_MULTIPLE_END_OF_CENTRAL_DIRECTORY: WARNING_MULTIPLE_END_OF_CENTRAL_DIRECTORY,
6242
6549
  WARNING_PREPENDED_CENTRAL_DIRECTORY: WARNING_PREPENDED_CENTRAL_DIRECTORY,
6243
6550
  WARNING_PREPENDED_DATA: WARNING_PREPENDED_DATA,
@@ -6248,6 +6555,7 @@ var zipReader = /*#__PURE__*/Object.freeze({
6248
6555
  WARNING_WRAPPED_ENTRIES_COUNT: WARNING_WRAPPED_ENTRIES_COUNT,
6249
6556
  ZipReader: ZipReader,
6250
6557
  ZipReaderStream: ZipReaderStream,
6558
+ getEntryDataDescriptorLength: getEntryDataDescriptorLength,
6251
6559
  isZipFile: isZipFile
6252
6560
  });
6253
6561
 
@@ -6370,129 +6678,8 @@ class ZipWriter {
6370
6678
  return watchPromiseError(this, prependZipEntries(this, reader));
6371
6679
  }
6372
6680
 
6373
- appendZip(reader) {
6374
- return watchPromiseError(this, this.appendZipEntries(reader));
6375
- }
6376
-
6377
- async appendZipEntries(reader) {
6378
- const zipWriter = this;
6379
- const { pendingAddFileCalls, filenames, fileEntries } = zipWriter;
6380
- while (pendingAddFileCalls.size) {
6381
- await Promise.allSettled(Array.from(pendingAddFileCalls));
6382
- }
6383
- let resolveAppendZip;
6384
- const promiseAppendZip = new Promise(resolve => resolveAppendZip = resolve);
6385
- pendingAddFileCalls.add(promiseAppendZip);
6386
- const appendedFilenames = [];
6387
- let releaseLockWriter;
6388
- try {
6389
- reader = new GenericReader(reader);
6390
- await initStream(reader);
6391
- if (reader.size === UNDEFINED_VALUE || !reader.readUint8Array) {
6392
- reader = new BlobReader(await streamToBlob(reader.readable));
6393
- await initStream(reader);
6394
- }
6395
- const { ZipReader } = await Promise.resolve().then(function () { return zipReader; });
6396
- const zipReader$1 = new ZipReader(reader);
6397
- const entries = await zipReader$1.getEntries();
6398
- await zipReader$1.close();
6399
- await initStream(zipWriter.writer);
6400
- const { directoryOffset } = zipReader$1;
6401
- entries.forEach(({ filename }) => {
6402
- if (filenames.has(filename)) {
6403
- throw new Error(ERR_DUPLICATED_NAME);
6404
- }
6405
- filenames.add(filename);
6406
- appendedFilenames.push(filename);
6407
- });
6408
- zipWriter.writerLocked = true;
6409
- const { lockWriter } = zipWriter;
6410
- zipWriter.lockWriter = new Promise(resolve => releaseLockWriter = () => {
6411
- zipWriter.writerLocked = false;
6412
- resolve();
6413
- });
6414
- await lockWriter;
6415
- if (zipWriter.addSplitZipSignature) {
6416
- delete zipWriter.addSplitZipSignature;
6417
- if (!await startsWithSplitZipSignature(reader)) {
6418
- await writeData(zipWriter.writer, getSplitZipSignatureArray());
6419
- zipWriter.offset += SPLIT_ZIP_FILE_SIGNATURE_LENGTH;
6420
- }
6421
- }
6422
- const entryPositions = await copyZipData(zipWriter, reader, entries, directoryOffset);
6423
- entries.forEach(entry => {
6424
- const {
6425
- version,
6426
- rawLastModDate,
6427
- rawFilename,
6428
- bitFlag,
6429
- encrypted,
6430
- uncompressedSize,
6431
- compressedSize,
6432
- extraFieldZip64
6433
- } = entry;
6434
- let {
6435
- compressionMethod,
6436
- rawExtraField,
6437
- } = entry;
6438
- const { level, languageEncodingFlag, dataDescriptor } = bitFlag;
6439
- rawExtraField = removeExtraFieldZip64(rawExtraField || EMPTY_UINT8_ARRAY);
6440
- if (entry.extraFieldAES) {
6441
- compressionMethod = COMPRESSION_METHOD_AES;
6442
- }
6443
- const extraFieldLength = getLength(rawExtraField);
6444
- const zip64UncompressedSize = Boolean(extraFieldZip64) && extraFieldZip64.uncompressedSize !== UNDEFINED_VALUE;
6445
- const zip64CompressedSize = Boolean(extraFieldZip64) && extraFieldZip64.compressedSize !== UNDEFINED_VALUE;
6446
- const bitFlagValue = (getBitFlag(level, languageEncodingFlag, dataDescriptor, encrypted, compressionMethod) & ~BITFLAG_LEVEL) | (level << 1);
6447
- const {
6448
- headerArray,
6449
- headerView
6450
- } = getHeaderArrayData({
6451
- version,
6452
- bitFlag: bitFlagValue,
6453
- compressionMethod,
6454
- uncompressedSize,
6455
- compressedSize,
6456
- rawLastModDate,
6457
- rawFilename,
6458
- zip64CompressedSize,
6459
- zip64UncompressedSize,
6460
- extraFieldLength
6461
- });
6462
- const { crc32 } = entry;
6463
- if (crc32 !== UNDEFINED_VALUE) {
6464
- setUint32(headerView, HEADER_OFFSET_SIGNATURE, crc32);
6465
- }
6466
- const { offset, diskNumberStart } = entryPositions.get(entry);
6467
- Object.assign(entry, {
6468
- zip64Enabled: true,
6469
- zip64UncompressedSize,
6470
- zip64CompressedSize,
6471
- offset,
6472
- diskNumberStart,
6473
- zip64DiskNumberStart: false,
6474
- rawExtraFieldZip64: EMPTY_UINT8_ARRAY,
6475
- rawExtraFieldAES: EMPTY_UINT8_ARRAY,
6476
- rawExtraFieldExtendedTimestamp: EMPTY_UINT8_ARRAY,
6477
- rawExtraFieldNTFS: EMPTY_UINT8_ARRAY,
6478
- rawExtraFieldUnix: EMPTY_UINT8_ARRAY,
6479
- rawExtraField,
6480
- rawCentralExtraField: EMPTY_UINT8_ARRAY,
6481
- headerArray,
6482
- headerView
6483
- });
6484
- fileEntries.set(entry.filename, entry);
6485
- });
6486
- } catch (error) {
6487
- appendedFilenames.forEach(filename => filenames.delete(filename));
6488
- throw error;
6489
- } finally {
6490
- resolveAppendZip();
6491
- pendingAddFileCalls.delete(promiseAppendZip);
6492
- if (releaseLockWriter) {
6493
- releaseLockWriter();
6494
- }
6495
- }
6681
+ appendZip(reader, options = {}) {
6682
+ return watchPromiseError(this, appendZipEntries(this, reader, options));
6496
6683
  }
6497
6684
 
6498
6685
  add(name = "", reader, options = {}) {
@@ -6654,11 +6841,149 @@ function watchPromiseError(zipWriter, promise) {
6654
6841
  return watchedPromise;
6655
6842
  }
6656
6843
 
6844
+ async function appendZipEntries(zipWriter, reader, options = {}) {
6845
+ const { pendingAddFileCalls, filenames, fileEntries } = zipWriter;
6846
+ const filter = checkFunctionOption(options.filter);
6847
+ const readerOptions = checkReaderOptionsObject(options.readerOptions);
6848
+ while (pendingAddFileCalls.size) {
6849
+ await Promise.allSettled(Array.from(pendingAddFileCalls));
6850
+ }
6851
+ let resolveAppendZip;
6852
+ const promiseAppendZip = new Promise(resolve => resolveAppendZip = resolve);
6853
+ pendingAddFileCalls.add(promiseAppendZip);
6854
+ const appendedFilenames = [];
6855
+ let releaseLockWriter;
6856
+ try {
6857
+ reader = new GenericReader(reader);
6858
+ await initStream(reader);
6859
+ if (reader.size === UNDEFINED_VALUE || !reader.readUint8Array) {
6860
+ reader = new BlobReader(await streamToBlob(reader.readable));
6861
+ await initStream(reader);
6862
+ }
6863
+ const { ZipReader, getEntryDataDescriptorLength } = await Promise.resolve().then(function () { return zipReader; });
6864
+ const zipReader$1 = new ZipReader(reader, readerOptions);
6865
+ const keptEntries = [];
6866
+ let entries;
6867
+ try {
6868
+ entries = await zipReader$1.getEntries();
6869
+ for (const entry of entries) {
6870
+ if (!filter || await filter(entry, getExistingEntry(fileEntries, entry.filename))) {
6871
+ keptEntries.push(entry);
6872
+ }
6873
+ }
6874
+ } finally {
6875
+ await zipReader$1.close();
6876
+ }
6877
+ await initStream(zipWriter.writer);
6878
+ const { directoryOffset, entriesMissingZip64ExtraField } = zipReader$1;
6879
+ keptEntries.forEach(entry => {
6880
+ const { filename } = entry;
6881
+ if (entriesMissingZip64ExtraField.has(entry)) {
6882
+ throw new Error(ERR_EXTRAFIELD_ZIP64_NOT_FOUND);
6883
+ }
6884
+ if (filenames.has(filename)) {
6885
+ throw new Error(ERR_DUPLICATED_NAME);
6886
+ }
6887
+ filenames.add(filename);
6888
+ appendedFilenames.push(filename);
6889
+ });
6890
+ zipWriter.writerLocked = true;
6891
+ const { lockWriter } = zipWriter;
6892
+ zipWriter.lockWriter = new Promise(resolve => releaseLockWriter = () => {
6893
+ zipWriter.writerLocked = false;
6894
+ resolve();
6895
+ });
6896
+ await lockWriter;
6897
+ if (zipWriter.addSplitZipSignature) {
6898
+ delete zipWriter.addSplitZipSignature;
6899
+ if (filter || !await startsWithSplitZipSignature(reader)) {
6900
+ await writeData(zipWriter.writer, getSplitZipSignatureArray());
6901
+ zipWriter.offset += SPLIT_ZIP_FILE_SIGNATURE_LENGTH;
6902
+ }
6903
+ }
6904
+ const entryPositions = await copyZipData(zipWriter, reader, entries, keptEntries, directoryOffset, Boolean(filter), getEntryDataDescriptorLength);
6905
+ keptEntries.forEach(entry => {
6906
+ const {
6907
+ version,
6908
+ rawLastModDate,
6909
+ rawFilename,
6910
+ rawBitFlag,
6911
+ uncompressedSize,
6912
+ compressedSize,
6913
+ extraFieldZip64
6914
+ } = entry;
6915
+ let {
6916
+ compressionMethod,
6917
+ rawExtraField,
6918
+ } = entry;
6919
+ rawExtraField = removeExtraFieldZip64(rawExtraField || EMPTY_UINT8_ARRAY);
6920
+ if (entry.extraFieldAES) {
6921
+ compressionMethod = COMPRESSION_METHOD_AES;
6922
+ }
6923
+ const extraFieldLength = getLength(rawExtraField);
6924
+ const zip64UncompressedSize = Boolean(extraFieldZip64) && extraFieldZip64.uncompressedSize !== UNDEFINED_VALUE;
6925
+ const zip64CompressedSize = Boolean(extraFieldZip64) && extraFieldZip64.compressedSize !== UNDEFINED_VALUE;
6926
+ const {
6927
+ headerArray,
6928
+ headerView
6929
+ } = getHeaderArrayData({
6930
+ version,
6931
+ bitFlag: rawBitFlag,
6932
+ compressionMethod,
6933
+ uncompressedSize,
6934
+ compressedSize,
6935
+ rawLastModDate,
6936
+ rawFilename,
6937
+ zip64CompressedSize,
6938
+ zip64UncompressedSize,
6939
+ extraFieldLength
6940
+ });
6941
+ const { crc32 } = entry;
6942
+ if (crc32 !== UNDEFINED_VALUE) {
6943
+ setUint32(headerView, HEADER_OFFSET_SIGNATURE, crc32);
6944
+ }
6945
+ const { offset, diskNumberStart } = entryPositions.get(entry);
6946
+ fileEntries.set(entry.filename, Object.assign({}, entry, {
6947
+ zip64Enabled: true,
6948
+ zip64UncompressedSize,
6949
+ zip64CompressedSize,
6950
+ offset,
6951
+ diskNumberStart,
6952
+ zip64DiskNumberStart: false,
6953
+ rawExtraFieldZip64: EMPTY_UINT8_ARRAY,
6954
+ rawExtraFieldAES: EMPTY_UINT8_ARRAY,
6955
+ rawExtraFieldExtendedTimestamp: EMPTY_UINT8_ARRAY,
6956
+ rawExtraFieldNTFS: EMPTY_UINT8_ARRAY,
6957
+ rawExtraFieldUnix: EMPTY_UINT8_ARRAY,
6958
+ rawCentralExtraFieldUnix: EMPTY_UINT8_ARRAY,
6959
+ rawExtraField,
6960
+ rawCentralExtraField: EMPTY_UINT8_ARRAY,
6961
+ headerArray,
6962
+ headerView
6963
+ }));
6964
+ });
6965
+ } catch (error) {
6966
+ appendedFilenames.forEach(filename => filenames.delete(filename));
6967
+ throw error;
6968
+ } finally {
6969
+ resolveAppendZip();
6970
+ pendingAddFileCalls.delete(promiseAppendZip);
6971
+ if (releaseLockWriter) {
6972
+ releaseLockWriter();
6973
+ }
6974
+ }
6975
+ }
6976
+
6977
+ function getExistingEntry(fileEntries, filename) {
6978
+ const fileEntry = fileEntries.get(filename);
6979
+ return fileEntry ? new Entry(fileEntry) : UNDEFINED_VALUE;
6980
+ }
6981
+
6657
6982
  async function prependZipEntries(zipWriter, reader) {
6658
6983
  if (zipWriter.filenames.size) {
6659
6984
  throw new Error(ERR_ZIP_NOT_EMPTY);
6660
6985
  }
6661
- await zipWriter.appendZipEntries(reader);
6986
+ await appendZipEntries(zipWriter, reader);
6662
6987
  }
6663
6988
 
6664
6989
  async function addFileEntry(zipWriter, name, reader, options) {
@@ -7033,16 +7358,17 @@ function resolveMetadata(zipWriter, name, options) {
7033
7358
  const passThrough = checkPassThroughOption(getOptionValue(zipWriter, options, OPTION_PASS_THROUGH));
7034
7359
  const passThroughCompression = Boolean(passThrough);
7035
7360
  const passThroughEncryption = passThrough === true;
7036
- const password = getOptionValue(zipWriter, options, OPTION_PASSWORD);
7037
- const rawPassword = getOptionValue(zipWriter, options, OPTION_RAW_PASSWORD);
7361
+ let password = getOptionValue(zipWriter, options, OPTION_PASSWORD);
7362
+ let rawPassword = getOptionValue(zipWriter, options, OPTION_RAW_PASSWORD);
7038
7363
  checkPasswordOption(password, rawPassword);
7364
+ password = password && password.length ? password : UNDEFINED_VALUE;
7365
+ rawPassword = rawPassword && rawPassword.length ? rawPassword : UNDEFINED_VALUE;
7039
7366
  const encryptionStrength = getNumberOptionValue(zipWriter, options, OPTION_ENCRYPTION_STRENGTH, 3);
7040
7367
  const zipCrypto = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIPCRYPTO);
7041
7368
  const extendedTimestamp = getOptionValue(zipWriter, options, OPTION_EXTENDED_TIMESTAMP, true);
7042
7369
  const ntfsTimestamp = getOptionValue(zipWriter, options, OPTION_NTFS_TIMESTAMP);
7043
7370
  const keepOrder = getOptionValue(zipWriter, options, OPTION_KEEP_ORDER, true);
7044
7371
  const useWebWorkers = getOptionValue(zipWriter, options, OPTION_USE_WEB_WORKERS);
7045
- const transferStreams = getOptionValue(zipWriter, options, OPTION_TRANSFER_STREAMS);
7046
7372
  const bufferedWrite = getOptionValue(zipWriter, options, OPTION_BUFFERED_WRITE);
7047
7373
  const createTempStream = getFunctionOptionValue(zipWriter, options, OPTION_CREATE_TEMP_STREAM);
7048
7374
  const dataDescriptorSignature = getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR_SIGNATURE, true);
@@ -7108,7 +7434,6 @@ function resolveMetadata(zipWriter, name, options) {
7108
7434
  ntfsTimestamp,
7109
7435
  keepOrder,
7110
7436
  useWebWorkers,
7111
- transferStreams,
7112
7437
  bufferedWrite,
7113
7438
  createTempStream,
7114
7439
  dataDescriptorSignature,
@@ -7167,7 +7492,7 @@ async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, op
7167
7492
  if (reader) {
7168
7493
  reader = new GenericReader(reader);
7169
7494
  await initStream(reader);
7170
- if (!reader.readable && !reader.readUint8Array) {
7495
+ if (!reader.readUint8Array && !reader.readable) {
7171
7496
  throw new Error(ERR_INVALID_READER);
7172
7497
  }
7173
7498
  ({ size: contentSize } = reader);
@@ -7430,6 +7755,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
7430
7755
  extraFieldExtendedTimestampTime,
7431
7756
  rawExtraFieldNTFS,
7432
7757
  rawExtraFieldUnix,
7758
+ rawCentralExtraFieldUnix,
7433
7759
  rawExtraFieldAES,
7434
7760
  } = headerInfo;
7435
7761
  const { dataDescriptorArray } = dataDescriptorInfo;
@@ -7454,7 +7780,6 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
7454
7780
  rawExtraField,
7455
7781
  rawCentralExtraField,
7456
7782
  useWebWorkers,
7457
- transferStreams,
7458
7783
  onstart,
7459
7784
  onprogress,
7460
7785
  onend,
@@ -7496,6 +7821,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
7496
7821
  rawExtraFieldExtendedTimestamp,
7497
7822
  rawExtraFieldNTFS,
7498
7823
  rawExtraFieldUnix,
7824
+ rawCentralExtraFieldUnix,
7499
7825
  rawExtraFieldAES,
7500
7826
  rawExtraField,
7501
7827
  rawCentralExtraField,
@@ -7542,7 +7868,6 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
7542
7868
  encrypted: encrypted && !passThroughEncryption,
7543
7869
  useWebWorkers,
7544
7870
  useCompressionStream,
7545
- transferStreams,
7546
7871
  format,
7547
7872
  codecURI,
7548
7873
  compressionMethod
@@ -7554,6 +7879,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
7554
7879
  const result = await runWorker({ readable, writable }, workerOptions);
7555
7880
  compressedSize = result.outputSize;
7556
7881
  writer.size += compressedSize;
7882
+ throwIfAborted(signal);
7557
7883
  if (!passThroughCompression) {
7558
7884
  uncompressedSize = result.inputSize;
7559
7885
  if (!encrypted || zipCrypto) {
@@ -7719,6 +8045,7 @@ function getHeaderInfo(options) {
7719
8045
  rawExtraFieldNTFS = rawExtraFieldExtendedTimestamp = EMPTY_UINT8_ARRAY;
7720
8046
  }
7721
8047
  let rawExtraFieldUnix;
8048
+ let rawCentralExtraFieldUnix;
7722
8049
  try {
7723
8050
  const { uid, gid, unixExtraFieldType } = options;
7724
8051
  if (unixExtraFieldType == INFOZIP_EXTRA_FIELD_TYPE && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
@@ -7733,7 +8060,7 @@ function getHeaderInfo(options) {
7733
8060
  extraFieldUnix.writeBytes(uidBytes);
7734
8061
  extraFieldUnix.writeUint8(gidBytes.length);
7735
8062
  extraFieldUnix.writeBytes(gidBytes);
7736
- rawExtraFieldUnix = extraFieldUnix.array;
8063
+ rawExtraFieldUnix = rawCentralExtraFieldUnix = extraFieldUnix.array;
7737
8064
  } else if (unixExtraFieldType == UNIX_EXTRA_FIELD_TYPE && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
7738
8065
  const extraFieldUnix = createRecordWriter(8);
7739
8066
  extraFieldUnix.writeUint16(EXTRAFIELD_TYPE_UNIX);
@@ -7741,11 +8068,15 @@ function getHeaderInfo(options) {
7741
8068
  extraFieldUnix.writeUint16((uid === UNDEFINED_VALUE ? 0 : uid) & MAX_16_BITS);
7742
8069
  extraFieldUnix.writeUint16((gid === UNDEFINED_VALUE ? 0 : gid) & MAX_16_BITS);
7743
8070
  rawExtraFieldUnix = extraFieldUnix.array;
8071
+ const centralExtraFieldUnix = createRecordWriter(4);
8072
+ centralExtraFieldUnix.writeUint16(EXTRAFIELD_TYPE_UNIX);
8073
+ centralExtraFieldUnix.writeUint16(0);
8074
+ rawCentralExtraFieldUnix = centralExtraFieldUnix.array;
7744
8075
  } else {
7745
- rawExtraFieldUnix = EMPTY_UINT8_ARRAY;
8076
+ rawExtraFieldUnix = rawCentralExtraFieldUnix = EMPTY_UINT8_ARRAY;
7746
8077
  }
7747
8078
  } catch {
7748
- rawExtraFieldUnix = EMPTY_UINT8_ARRAY;
8079
+ rawExtraFieldUnix = rawCentralExtraFieldUnix = EMPTY_UINT8_ARRAY;
7749
8080
  }
7750
8081
  if (compressionMethod === UNDEFINED_VALUE) {
7751
8082
  compressionMethod = compressed ? COMPRESSION_METHOD_DEFLATE : COMPRESSION_METHOD_STORE;
@@ -7837,6 +8168,7 @@ function getHeaderInfo(options) {
7837
8168
  rawExtraFieldExtendedTimestamp,
7838
8169
  rawExtraFieldNTFS,
7839
8170
  rawExtraFieldUnix,
8171
+ rawCentralExtraFieldUnix,
7840
8172
  rawExtraFieldAES,
7841
8173
  extraFieldLength
7842
8174
  };
@@ -8012,7 +8344,7 @@ function createDirectoryRecords(files) {
8012
8344
  rawExtraFieldAES,
8013
8345
  rawComment,
8014
8346
  rawExtraFieldNTFS,
8015
- rawExtraFieldUnix,
8347
+ rawCentralExtraFieldUnix,
8016
8348
  rawExtraField,
8017
8349
  rawCentralExtraField,
8018
8350
  extraFieldExtendedTimestampFlag,
@@ -8074,7 +8406,7 @@ function createDirectoryRecords(files) {
8074
8406
  rawExtraFieldZip64,
8075
8407
  rawExtraFieldAES,
8076
8408
  rawExtraFieldNTFS,
8077
- rawExtraFieldUnix,
8409
+ rawCentralExtraFieldUnix,
8078
8410
  rawExtraFieldTimestamp,
8079
8411
  rawExtraField,
8080
8412
  rawCentralExtraField);
@@ -8103,7 +8435,7 @@ async function writeDirectoryRecords(zipWriter, directoryDataLength, options) {
8103
8435
  rawExtraFieldAES,
8104
8436
  rawExtraFieldExtendedTimestamp,
8105
8437
  rawExtraFieldNTFS,
8106
- rawExtraFieldUnix,
8438
+ rawCentralExtraFieldUnix,
8107
8439
  rawExtraField,
8108
8440
  rawCentralExtraField,
8109
8441
  rawComment,
@@ -8120,7 +8452,7 @@ async function writeDirectoryRecords(zipWriter, directoryDataLength, options) {
8120
8452
  uncompressedSize,
8121
8453
  compressedSize
8122
8454
  } = fileEntry;
8123
- const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField, rawCentralExtraField);
8455
+ const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawCentralExtraFieldUnix, rawExtraField, rawCentralExtraField);
8124
8456
  const directoryRecordLength = CENTRAL_FILE_HEADER_LENGTH + getLength(rawFilename, rawComment) + extraFieldLength;
8125
8457
  if (exceedsAvailableSize(writer, offset + directoryRecordLength - directoryDiskOffset)) {
8126
8458
  await writeData(writer, directoryArray.slice(directoryDiskOffset, offset));
@@ -8156,7 +8488,7 @@ async function writeDirectoryRecords(zipWriter, directoryDataLength, options) {
8156
8488
  directoryRecord.writeBytes(rawExtraFieldAES);
8157
8489
  directoryRecord.writeBytes(rawExtraFieldExtendedTimestamp);
8158
8490
  directoryRecord.writeBytes(rawExtraFieldNTFS);
8159
- directoryRecord.writeBytes(rawExtraFieldUnix);
8491
+ directoryRecord.writeBytes(rawCentralExtraFieldUnix);
8160
8492
  directoryRecord.writeBytes(rawExtraField);
8161
8493
  directoryRecord.writeBytes(rawCentralExtraField);
8162
8494
  directoryRecord.writeBytes(rawComment);
@@ -8325,26 +8657,63 @@ function removeExtraFieldZip64(rawExtraField) {
8325
8657
  return rawExtraField;
8326
8658
  }
8327
8659
 
8328
- async function copyZipData(zipWriter, reader, entries, directoryOffset) {
8660
+ async function copyZipData(zipWriter, reader, entries, keptEntries, directoryOffset, compact, getEntryDataDescriptorLength) {
8329
8661
  const { writer } = zipWriter;
8330
8662
  const entryPositions = new Map();
8331
- if (writer.closeDisk) {
8663
+ if (writer.closeDisk || compact) {
8332
8664
  const sortedEntries = Array.from(entries).sort((firstEntry, secondEntry) =>
8333
8665
  getSourceOffset(reader, firstEntry) - getSourceOffset(reader, secondEntry));
8334
- let copiedLength = 0;
8335
- for (const entry of sortedEntries) {
8336
- const sourceOffset = getSourceOffset(reader, entry);
8337
- await copyData(zipWriter, reader, copiedLength, sourceOffset - copiedLength);
8338
- if (exceedsAvailableSize(writer, await getLocalHeaderLength(reader, sourceOffset))) {
8339
- await writer.closeDisk();
8340
- }
8341
- entryPositions.set(entry, {
8342
- offset: getSegmentOffset(zipWriter, writer),
8343
- diskNumberStart: getDiskNumber(writer)
8344
- });
8345
- copiedLength = sourceOffset;
8666
+ const regionEnds = getRegionEnds(reader, sortedEntries, directoryOffset);
8667
+ const keptEntrySet = new Set(keptEntries);
8668
+ const localHeaderLengths = new Map();
8669
+ for (let indexEntry = 0; indexEntry < sortedEntries.length; indexEntry++) {
8670
+ const entry = sortedEntries[indexEntry];
8671
+ if (keptEntrySet.has(entry)) {
8672
+ const sourceOffset = getSourceOffset(reader, entry);
8673
+ const localHeaderLength = await getLocalHeaderLength(reader, sourceOffset);
8674
+ if (localHeaderLength === UNDEFINED_VALUE) {
8675
+ throw new Error(ERR_LOCAL_FILE_HEADER_NOT_FOUND);
8676
+ }
8677
+ let entryEnd = sourceOffset + localHeaderLength + entry.compressedSize;
8678
+ if (entry.bitFlag.dataDescriptor) {
8679
+ const dataDescriptorLength = await getEntryDataDescriptorLength(reader, entryEnd, entry);
8680
+ entryEnd = dataDescriptorLength === UNDEFINED_VALUE ? Math.max(entryEnd, regionEnds[indexEntry]) : entryEnd + dataDescriptorLength;
8681
+ }
8682
+ if (entryEnd > regionEnds[indexEntry]) {
8683
+ throw new Error(ERR_OVERLAPPING_ENTRY);
8684
+ }
8685
+ regionEnds[indexEntry] = entryEnd;
8686
+ localHeaderLengths.set(entry, localHeaderLength);
8687
+ }
8688
+ }
8689
+ let copiedOffset = 0;
8690
+ let lastPosition;
8691
+ for (let indexEntry = 0; indexEntry < sortedEntries.length; indexEntry++) {
8692
+ const entry = sortedEntries[indexEntry];
8693
+ if (keptEntrySet.has(entry)) {
8694
+ const sourceOffset = getSourceOffset(reader, entry);
8695
+ if (sourceOffset < copiedOffset) {
8696
+ entryPositions.set(entry, lastPosition);
8697
+ } else {
8698
+ if (!compact) {
8699
+ await copyData(zipWriter, reader, copiedOffset, sourceOffset - copiedOffset);
8700
+ }
8701
+ if (writer.closeDisk && exceedsAvailableSize(writer, localHeaderLengths.get(entry))) {
8702
+ await writer.closeDisk();
8703
+ }
8704
+ lastPosition = {
8705
+ offset: getSegmentOffset(zipWriter, writer),
8706
+ diskNumberStart: getDiskNumber(writer)
8707
+ };
8708
+ entryPositions.set(entry, lastPosition);
8709
+ await copyData(zipWriter, reader, sourceOffset, regionEnds[indexEntry] - sourceOffset);
8710
+ copiedOffset = regionEnds[indexEntry];
8711
+ }
8712
+ }
8713
+ }
8714
+ if (!compact) {
8715
+ await copyData(zipWriter, reader, copiedOffset, directoryOffset - copiedOffset);
8346
8716
  }
8347
- await copyData(zipWriter, reader, copiedLength, directoryOffset - copiedLength);
8348
8717
  } else {
8349
8718
  const baseOffset = zipWriter.offset;
8350
8719
  await copyData(zipWriter, reader, 0, directoryOffset);
@@ -8356,6 +8725,20 @@ async function copyZipData(zipWriter, reader, entries, directoryOffset) {
8356
8725
  return entryPositions;
8357
8726
  }
8358
8727
 
8728
+ function getRegionEnds(reader, sortedEntries, directoryOffset) {
8729
+ const regionEnds = new Array(sortedEntries.length);
8730
+ let regionEnd = directoryOffset;
8731
+ for (let indexEntry = sortedEntries.length - 1; indexEntry >= 0; indexEntry--) {
8732
+ const sourceOffset = getSourceOffset(reader, sortedEntries[indexEntry]);
8733
+ const nextEntry = sortedEntries[indexEntry + 1];
8734
+ if (nextEntry && getSourceOffset(reader, nextEntry) > sourceOffset) {
8735
+ regionEnd = Math.min(getSourceOffset(reader, nextEntry), directoryOffset);
8736
+ }
8737
+ regionEnds[indexEntry] = regionEnd;
8738
+ }
8739
+ return regionEnds;
8740
+ }
8741
+
8359
8742
  async function copyData(zipWriter, reader, offset, size) {
8360
8743
  if (size > 0) {
8361
8744
  const { writer } = zipWriter;
@@ -8363,11 +8746,13 @@ async function copyData(zipWriter, reader, offset, size) {
8363
8746
  try {
8364
8747
  await flushBufferedData(createReadable(reader, { offset, size }), writer, UNDEFINED_VALUE, chunkLength => copiedLength += chunkLength);
8365
8748
  } catch (error) {
8366
- zipWriter.hasCorruptedEntries = true;
8367
- try {
8368
- error.corruptedEntry = true;
8369
- } catch {
8370
- // ignored
8749
+ if (copiedLength) {
8750
+ zipWriter.hasCorruptedEntries = true;
8751
+ try {
8752
+ error.corruptedEntry = true;
8753
+ } catch {
8754
+ // ignored
8755
+ }
8371
8756
  }
8372
8757
  throw error;
8373
8758
  } finally {
@@ -8378,11 +8763,16 @@ async function copyData(zipWriter, reader, offset, size) {
8378
8763
  }
8379
8764
 
8380
8765
  async function getLocalHeaderLength(reader, offset) {
8381
- const headerArray = await readUint8Array(reader, offset, HEADER_SIZE);
8766
+ const headerArray = offset >= 0 && offset + HEADER_SIZE <= reader.size ?
8767
+ await readUint8Array(reader, offset, HEADER_SIZE) :
8768
+ EMPTY_UINT8_ARRAY;
8382
8769
  if (getLength(headerArray) < HEADER_SIZE) {
8383
- return HEADER_SIZE;
8770
+ return UNDEFINED_VALUE;
8384
8771
  }
8385
8772
  const headerView = getDataView(headerArray);
8773
+ if (getUint32(headerView, 0) != LOCAL_FILE_HEADER_SIGNATURE) {
8774
+ return UNDEFINED_VALUE;
8775
+ }
8386
8776
  return HEADER_SIZE +
8387
8777
  getUint16(headerView, HEADER_OFFSET_FILENAME_LENGTH + LOCAL_HEADER_COMMON_OFFSET) +
8388
8778
  getUint16(headerView, HEADER_OFFSET_EXTRAFIELD_LENGTH + LOCAL_HEADER_COMMON_OFFSET);
@@ -8733,7 +9123,7 @@ function formatSupported(StreamClass, format) {
8733
9123
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
8734
9124
  */
8735
9125
 
8736
- const VERSION = "2.15.0";
9126
+ const VERSION = "2.22.0";
8737
9127
 
8738
9128
  /*
8739
9129
  Copyright (c) 2025 Gildas Lormeau. All rights reserved.
@@ -9931,4 +10321,4 @@ setDefaultConfiguration({
9931
10321
  workerURI: null
9932
10322
  });
9933
10323
 
9934
- export { BlobReader, BlobWriter, Data64URIReader, Data64URIWriter, ERR_ABORTED, ERR_AMBIGUOUS_ARCHIVE, ERR_BAD_FORMAT, ERR_CENTRAL_DIRECTORY_NOT_FOUND, ERR_DUPLICATED_NAME, ERR_ENCRYPTED, ERR_ENCRYPTED_CENTRAL_DIRECTORY, ERR_ENTRY_DATA_OUT_OF_BOUNDS, 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_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_VALUE, ERR_INVALID_READER, 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_RESERVED_COMPRESSION_METHOD, ERR_SPLIT_ZIP_FILE, 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_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, ZipReader, ZipReaderStream, ZipWriter, ZipWriterStream, configure, createBlobTempStream, createOPFSTempStream, createSyncAccessHandleTempStream, deflateSync as deflateRaw, getMimeType, getRegisteredCodecs, getSupportedCompressionMethods, inflateSync as inflateRaw, initStream, isZipFile, readUint8Array, registerCodec, resetConfiguration, terminateWorkers, unregisterCodec };
10324
+ export { BlobReader, BlobWriter, Data64URIReader, Data64URIWriter, ERR_ABORTED, ERR_AMBIGUOUS_ARCHIVE, ERR_BAD_FORMAT, ERR_CENTRAL_DIRECTORY_NOT_FOUND, ERR_CODEC_OUT_OF_MEMORY, ERR_DUPLICATED_NAME, ERR_ENCRYPTED, ERR_ENCRYPTED_CENTRAL_DIRECTORY, ERR_ENTRY_DATA_OUT_OF_BOUNDS, 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_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_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_RESERVED_COMPRESSION_METHOD, ERR_SPLIT_ZIP_FILE, 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_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_CENTRAL_DIRECTORY_OFFSET, 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_MISSING_ZIP64_EXTRA_FIELD, 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, ZipReader, ZipReaderStream, ZipWriter, ZipWriterStream, configure, createBlobTempStream, createOPFSTempStream, createSyncAccessHandleTempStream, deflateSync as deflateRaw, getMimeType, getRegisteredCodecs, getSupportedCompressionMethods, inflateSync as inflateRaw, initStream, isZipFile, readUint8Array, registerCodec, resetConfiguration, terminateWorkers, unregisterCodec };