@zip.js/zip.js 2.8.44 → 2.8.46

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.
Files changed (61) hide show
  1. package/README.md +28 -2
  2. package/deno.json +32 -2
  3. package/dist/zip-core-external.js +199 -149
  4. package/dist/zip-core-external.min.js +1 -1
  5. package/dist/zip-core.js +196 -120
  6. package/dist/zip-core.min.js +1 -1
  7. package/dist/zip-fs-core-external.js +251 -157
  8. package/dist/zip-fs-core-external.min.js +1 -1
  9. package/dist/zip-fs-core.js +227 -126
  10. package/dist/zip-fs-core.min.js +1 -1
  11. package/dist/zip-fs-external.js +272 -1751
  12. package/dist/zip-fs-external.min.js +1 -1
  13. package/dist/zip-fs-native.js +273 -1726
  14. package/dist/zip-fs-native.min.js +1 -1
  15. package/dist/zip-fs.js +273 -1726
  16. package/dist/zip-fs.min.js +1 -1
  17. package/dist/zip-legacy.js +198 -122
  18. package/dist/zip-legacy.min.js +1 -1
  19. package/dist/zip-native.js +200 -124
  20. package/dist/zip-native.min.js +1 -1
  21. package/dist/zip-web-worker-native.js +1 -1
  22. package/dist/zip-web-worker.js +1 -1
  23. package/dist/zip.js +200 -124
  24. package/dist/zip.min.js +1 -1
  25. package/eslint.config.mjs +31 -2
  26. package/index-native.cjs +273 -1726
  27. package/index-native.min.js +1 -1
  28. package/index.cjs +273 -1726
  29. package/index.d.cts +140 -2
  30. package/index.d.ts +140 -2
  31. package/index.min.js +1 -1
  32. package/lib/core/codec-pool.js +3 -2
  33. package/lib/core/codec-worker.js +30 -14
  34. package/lib/core/configuration.js +20 -2
  35. package/lib/core/constants.js +4 -0
  36. package/lib/core/options.js +2 -0
  37. package/lib/core/streams/aes-crypto-stream.js +15 -18
  38. package/lib/core/streams/codec-stream.js +2 -2
  39. package/lib/core/streams/zip-entry-stream.js +13 -18
  40. package/lib/core/util/mime-type-data.js +3 -0
  41. package/lib/core/util/mime-type.js +23 -1596
  42. package/lib/core/web-worker-base.js +29 -2
  43. package/lib/core/web-worker-inline-native.js +1 -1
  44. package/lib/core/web-worker-inline-wasm.js +1 -1
  45. package/lib/core/web-worker-native.js +7 -9
  46. package/lib/core/web-worker-wasm.js +9 -12
  47. package/lib/core/zip-entry.js +8 -1
  48. package/lib/core/zip-fs.js +62 -5
  49. package/lib/core/zip-reader.js +45 -17
  50. package/lib/core/zip-writer.js +58 -44
  51. package/lib/{core/web-worker-inline-template.js → zip-core-custom.js} +13 -20
  52. package/lib/zip-core-external.js +2 -0
  53. package/lib/zip-fs-core-external.js +2 -0
  54. package/lib/zip-fs-external.js +2 -0
  55. package/lib/zip-mime-types.js +2 -0
  56. package/lib/zip-module-native.js +3 -3
  57. package/lib/zip-module-wasm-base.js +3 -3
  58. package/package.json +28 -4
  59. package/worker-message-property-names.js +1 -1
  60. package/lib/core/web-worker-inline-template-native.js +0 -48
  61. package/lib/core/zlib-streams-inline-template.js +0 -45
package/dist/zip-core.js CHANGED
@@ -71,6 +71,8 @@
71
71
  const EXTRAFIELD_TYPE_USDZ = 0x1986;
72
72
  const EXTRAFIELD_TYPE_INFOZIP = 0x7875;
73
73
  const EXTRAFIELD_TYPE_UNIX = 0x7855;
74
+ const EXTRAFIELD_TYPE_UNIX_TYPE1 = 0x5855;
75
+ const EXTRAFIELD_TYPE_PKWARE_UNIX = 0x000d;
74
76
 
75
77
  const BITFLAG_ENCRYPTED = 0b1;
76
78
  const BITFLAG_LEVEL = 0b0110;
@@ -174,6 +176,7 @@
174
176
  "baseURI",
175
177
  "wasmURI",
176
178
  "workerURI",
179
+ "createWorker",
177
180
  "chunkSize",
178
181
  "maxWorkers",
179
182
  "terminateWorkerTimeout",
@@ -184,8 +187,8 @@
184
187
  "transferStreams",
185
188
  "CompressionStream",
186
189
  "DecompressionStream",
187
- "CompressionStreamZlib",
188
- "DecompressionStreamZlib"
190
+ "CompressionStreamFallback",
191
+ "DecompressionStreamFallback"
189
192
  ];
190
193
 
191
194
  const config = { ...DEFAULT_CONFIGURATION };
@@ -199,6 +202,7 @@
199
202
  }
200
203
 
201
204
  function configure(configuration) {
205
+ configuration = normalizeConfiguration(configuration);
202
206
  for (const propertyName of CONFIGURABLE_PROPERTY_NAMES) {
203
207
  const propertyValue = configuration[propertyName];
204
208
  if (propertyValue !== UNDEFINED_VALUE) {
@@ -207,7 +211,23 @@
207
211
  }
208
212
  }
209
213
 
214
+ function normalizeConfiguration(configuration) {
215
+ const { CompressionStreamZlib, DecompressionStreamZlib } = configuration;
216
+ if (CompressionStreamZlib === UNDEFINED_VALUE && DecompressionStreamZlib === UNDEFINED_VALUE) {
217
+ return configuration;
218
+ }
219
+ const normalizedConfiguration = Object.assign({}, configuration);
220
+ if (normalizedConfiguration.CompressionStreamFallback === UNDEFINED_VALUE) {
221
+ normalizedConfiguration.CompressionStreamFallback = CompressionStreamZlib;
222
+ }
223
+ if (normalizedConfiguration.DecompressionStreamFallback === UNDEFINED_VALUE) {
224
+ normalizedConfiguration.DecompressionStreamFallback = DecompressionStreamZlib;
225
+ }
226
+ return normalizedConfiguration;
227
+ }
228
+
210
229
  function setDefaultConfiguration(configuration) {
230
+ configuration = normalizeConfiguration(configuration);
211
231
  for (const propertyName of CONFIGURABLE_PROPERTY_NAMES) {
212
232
  const propertyValue = configuration[propertyName];
213
233
  if (propertyValue !== UNDEFINED_VALUE) {
@@ -1420,7 +1440,7 @@
1420
1440
  const DERIVED_BITS_USAGE = ["deriveBits"];
1421
1441
  const SALT_LENGTH = [8, 12, 16];
1422
1442
  const KEY_LENGTH = [16, 24, 32];
1423
- const SIGNATURE_LENGTH = 10;
1443
+ const AUTHENTICATION_CODE_LENGTH = 10;
1424
1444
  const COUNTER_DEFAULT_VALUE = [0, 0, 0, 0];
1425
1445
  // deno-lint-ignore valid-typeof
1426
1446
  const CRYPTO_API_SUPPORTED = typeof crypto != UNDEFINED_TYPE;
@@ -1460,8 +1480,8 @@
1460
1480
  } else {
1461
1481
  await ready;
1462
1482
  }
1463
- const output = new Uint8Array(chunk.length - SIGNATURE_LENGTH - ((chunk.length - SIGNATURE_LENGTH) % BLOCK_LENGTH));
1464
- controller.enqueue(append(aesCrypto, chunk, output, 0, SIGNATURE_LENGTH, true));
1483
+ const output = new Uint8Array(chunk.length - AUTHENTICATION_CODE_LENGTH - ((chunk.length - AUTHENTICATION_CODE_LENGTH) % BLOCK_LENGTH));
1484
+ controller.enqueue(append(aesCrypto, chunk, output, 0, AUTHENTICATION_CODE_LENGTH, true));
1465
1485
  },
1466
1486
  async flush(controller) {
1467
1487
  const {
@@ -1472,8 +1492,8 @@
1472
1492
  } = this;
1473
1493
  if (hmac && ctr) {
1474
1494
  await ready;
1475
- const chunkToDecrypt = subarray(pending, 0, pending.length - SIGNATURE_LENGTH);
1476
- const originalSignature = subarray(pending, pending.length - SIGNATURE_LENGTH);
1495
+ const chunkToDecrypt = subarray(pending, 0, pending.length - AUTHENTICATION_CODE_LENGTH);
1496
+ const originalAuthenticationCode = subarray(pending, pending.length - AUTHENTICATION_CODE_LENGTH);
1477
1497
  let decryptedChunkArray = EMPTY_UINT8_ARRAY;
1478
1498
  if (chunkToDecrypt.length) {
1479
1499
  const encryptedChunk = toBits(codecBytes, chunkToDecrypt);
@@ -1481,12 +1501,12 @@
1481
1501
  const decryptedChunk = ctr.update(encryptedChunk);
1482
1502
  decryptedChunkArray = fromBits(codecBytes, decryptedChunk);
1483
1503
  }
1484
- const signature = subarray(fromBits(codecBytes, hmac.digest()), 0, SIGNATURE_LENGTH);
1485
- let invalidSignature = pending.length < SIGNATURE_LENGTH ? 1 : 0;
1486
- for (let indexSignature = 0; indexSignature < SIGNATURE_LENGTH; indexSignature++) {
1487
- invalidSignature |= signature[indexSignature] ^ originalSignature[indexSignature];
1504
+ const authenticationCode = subarray(fromBits(codecBytes, hmac.digest()), 0, AUTHENTICATION_CODE_LENGTH);
1505
+ let invalidAuthenticationCode = pending.length < AUTHENTICATION_CODE_LENGTH ? 1 : 0;
1506
+ for (let indexByte = 0; indexByte < AUTHENTICATION_CODE_LENGTH; indexByte++) {
1507
+ invalidAuthenticationCode |= authenticationCode[indexByte] ^ originalAuthenticationCode[indexByte];
1488
1508
  }
1489
- if (invalidSignature && checkAuthenticationCode) {
1509
+ if (invalidAuthenticationCode && checkAuthenticationCode) {
1490
1510
  throw new Error(ERR_INVALID_AUTHENTICATION_CODE);
1491
1511
  }
1492
1512
  controller.enqueue(decryptedChunkArray);
@@ -1499,8 +1519,6 @@
1499
1519
  class AESEncryptionStream extends TransformStream {
1500
1520
 
1501
1521
  constructor({ password, rawPassword, encryptionStrength }) {
1502
- // deno-lint-ignore prefer-const
1503
- let stream;
1504
1522
  super({
1505
1523
  start() {
1506
1524
  initAesCrypto(this, password, rawPassword, encryptionStrength);
@@ -1539,12 +1557,11 @@
1539
1557
  hmac.update(encryptedChunk);
1540
1558
  encryptedChunkArray = fromBits(codecBytes, encryptedChunk);
1541
1559
  }
1542
- stream.signature = fromBits(codecBytes, hmac.digest()).slice(0, SIGNATURE_LENGTH);
1543
- controller.enqueue(concat(encryptedChunkArray, stream.signature));
1560
+ const authenticationCode = fromBits(codecBytes, hmac.digest()).slice(0, AUTHENTICATION_CODE_LENGTH);
1561
+ controller.enqueue(concat(encryptedChunkArray, authenticationCode));
1544
1562
  }
1545
1563
  }
1546
1564
  });
1547
- stream = this;
1548
1565
  }
1549
1566
  }
1550
1567
 
@@ -1557,7 +1574,7 @@
1557
1574
  });
1558
1575
  }
1559
1576
 
1560
- function append(aesCrypto, input, output, paddingStart, paddingEnd, verifySignature) {
1577
+ function append(aesCrypto, input, output, paddingStart, paddingEnd, verifyAuthenticationCode) {
1561
1578
  const {
1562
1579
  ctr,
1563
1580
  hmac,
@@ -1571,11 +1588,11 @@
1571
1588
  let offset;
1572
1589
  for (offset = 0; offset <= inputLength - BLOCK_LENGTH; offset += BLOCK_LENGTH) {
1573
1590
  const inputChunk = toBits(codecBytes, subarray(input, offset, offset + BLOCK_LENGTH));
1574
- if (verifySignature) {
1591
+ if (verifyAuthenticationCode) {
1575
1592
  hmac.update(inputChunk);
1576
1593
  }
1577
1594
  const outputChunk = ctr.update(inputChunk);
1578
- if (!verifySignature) {
1595
+ if (!verifyAuthenticationCode) {
1579
1596
  hmac.update(outputChunk);
1580
1597
  }
1581
1598
  output.set(fromBits(codecBytes, outputChunk), offset + paddingStart);
@@ -1937,7 +1954,7 @@
1937
1954
 
1938
1955
  class DeflateStream extends TransformStream {
1939
1956
 
1940
- constructor(options, { chunkSize, CompressionStreamZlib, CompressionStream }) {
1957
+ constructor(options, { chunkSize, CompressionStreamFallback, CompressionStream }) {
1941
1958
  super({});
1942
1959
  const { compressed, encrypted, useCompressionStream, zipCrypto, computeCrc32, level, deflate64, format, compressionMethod } = options;
1943
1960
  const stream = this;
@@ -1959,7 +1976,7 @@
1959
1976
  readable = pipeThrough(readable, gzipCrc32Stream);
1960
1977
  } else {
1961
1978
  try {
1962
- readable = pipeThroughCompressionStream(readable, useCompressionStream, { level, chunkSize }, CompressionStream, CompressionStreamZlib);
1979
+ readable = pipeThroughCompressionStream(readable, useCompressionStream, { level, chunkSize }, CompressionStream, CompressionStreamFallback);
1963
1980
  } catch (error) {
1964
1981
  let gzipStream;
1965
1982
  try {
@@ -1981,14 +1998,9 @@
1981
1998
  }
1982
1999
  }
1983
2000
  setReadable(stream, readable, () => {
1984
- let signature;
1985
- if (encrypted && !zipCrypto) {
1986
- signature = encryptionStream.signature;
1987
- }
1988
2001
  if ((!encrypted || zipCrypto) && computeCrc32) {
1989
- signature = useGzipCrc32 ? gzipCrc32Stream.signature : new DataView(crc32Stream.value.buffer).getUint32(0);
2002
+ stream.crc32 = useGzipCrc32 ? gzipCrc32Stream.crc32 : new DataView(crc32Stream.value.buffer).getUint32(0);
1990
2003
  }
1991
- stream.signature = signature;
1992
2004
  });
1993
2005
  }
1994
2006
  }
@@ -2026,7 +2038,7 @@
2026
2038
  },
2027
2039
  flush() {
2028
2040
  const dataView = getDataView(trailerCandidate);
2029
- stream.signature = dataView.getUint32(0, true);
2041
+ stream.crc32 = dataView.getUint32(0, true);
2030
2042
  stream.uncompressedSize = dataView.getUint32(4, true);
2031
2043
  }
2032
2044
  });
@@ -2106,9 +2118,9 @@
2106
2118
 
2107
2119
  class InflateStream extends TransformStream {
2108
2120
 
2109
- constructor(options, { chunkSize, DecompressionStreamZlib, DecompressionStream }) {
2121
+ constructor(options, { chunkSize, DecompressionStreamFallback, DecompressionStream }) {
2110
2122
  super({});
2111
- const { zipCrypto, encrypted, checkCrc32, signature, compressed, useCompressionStream, deflate64, format, compressionMethod, rawBitFlag, outputSize } = options;
2123
+ const { zipCrypto, encrypted, checkCrc32, crc32, compressed, useCompressionStream, deflate64, format, compressionMethod, rawBitFlag, outputSize } = options;
2112
2124
  let crc32Stream, decryptionStream;
2113
2125
  let readable = super.readable;
2114
2126
  if (encrypted) {
@@ -2125,7 +2137,7 @@
2125
2137
  readable = pipeThroughBackpressured(readable, createCodecStream(codecStreams.DecompressionStream, format, { chunkSize, compressionMethod, rawBitFlag, uncompressedSize: outputSize }));
2126
2138
  } else {
2127
2139
  try {
2128
- readable = pipeThroughCompressionStream(readable, useCompressionStream, { chunkSize, deflate64 }, DecompressionStream, DecompressionStreamZlib);
2140
+ readable = pipeThroughCompressionStream(readable, useCompressionStream, { chunkSize, deflate64 }, DecompressionStream, DecompressionStreamFallback);
2129
2141
  } catch (error) {
2130
2142
  if (deflate64 || outputSize === UNDEFINED_VALUE) {
2131
2143
  throw error;
@@ -2147,8 +2159,8 @@
2147
2159
  }
2148
2160
  setReadable(this, readable, () => {
2149
2161
  if (checkCrc32) {
2150
- const dataViewSignature = new DataView(crc32Stream.value.buffer);
2151
- if (signature != dataViewSignature.getUint32(0, false)) {
2162
+ const computedCrc32View = new DataView(crc32Stream.value.buffer);
2163
+ if (crc32 != computedCrc32View.getUint32(0, false)) {
2152
2164
  throw new Error(ERR_INVALID_CRC32);
2153
2165
  }
2154
2166
  }
@@ -2204,17 +2216,17 @@
2204
2216
  return new CodecStreamClass(format, options);
2205
2217
  }
2206
2218
 
2207
- function pipeThroughCompressionStream(readable, useCompressionStream, options, CompressionStreamNative, CompressionStreamZlib) {
2219
+ function pipeThroughCompressionStream(readable, useCompressionStream, options, CompressionStreamNative, CompressionStreamFallback) {
2208
2220
  const Stream = useCompressionStream && CompressionStreamNative ?
2209
2221
  CompressionStreamNative :
2210
- CompressionStreamZlib || CompressionStreamNative;
2222
+ CompressionStreamFallback || CompressionStreamNative;
2211
2223
  const format = options.deflate64 ? FORMAT_DEFLATE64_RAW : FORMAT_DEFLATE_RAW;
2212
2224
  let codecStream;
2213
2225
  try {
2214
2226
  codecStream = new Stream(format, options);
2215
2227
  } catch (error) {
2216
- if (useCompressionStream && CompressionStreamZlib && Stream != CompressionStreamZlib) {
2217
- codecStream = new CompressionStreamZlib(format, options);
2228
+ if (useCompressionStream && CompressionStreamFallback && Stream != CompressionStreamFallback) {
2229
+ codecStream = new CompressionStreamFallback(format, options);
2218
2230
  } else {
2219
2231
  throw error;
2220
2232
  }
@@ -2373,9 +2385,9 @@
2373
2385
  }
2374
2386
  },
2375
2387
  flush() {
2376
- const { signature } = stream;
2388
+ const { crc32 } = stream;
2377
2389
  Object.assign(codec, {
2378
- signature,
2390
+ crc32,
2379
2391
  inputSize
2380
2392
  });
2381
2393
  }
@@ -2477,7 +2489,7 @@
2477
2489
  const MESSAGE_ERROR_EVENT_TYPE = "messageerror";
2478
2490
  const ERR_WORKER_STARTUP_TIMEOUT = "Worker startup timeout";
2479
2491
 
2480
- let webWorkerSupported, webWorkerSource, webWorkerURI, webWorkerOptions;
2492
+ let webWorkerSupported, webWorkerSource, webWorkerURI, webWorkerOptions, createWorkerFailed;
2481
2493
  let transferStreamsSupported = true;
2482
2494
  try {
2483
2495
  transferStreamsSupported = typeof structuredClone == FUNCTION_TYPE && structuredClone(new DOMException("", "AbortError")).code !== UNDEFINED_VALUE;
@@ -2487,14 +2499,14 @@
2487
2499
  let initModule = () => { };
2488
2500
 
2489
2501
  async function supportsDeflate(config) {
2490
- const { CompressionStream: NativeStream, CompressionStreamZlib: ZlibStream } = config;
2491
- if (ZlibStream && !ZlibStream.requiresModule) {
2502
+ const { CompressionStream: NativeStream, CompressionStreamFallback: FallbackStream } = config;
2503
+ if (FallbackStream && !FallbackStream.requiresModule) {
2492
2504
  return true;
2493
2505
  }
2494
2506
  if (supportsDeflateRaw(NativeStream) || supportsGzip(NativeStream)) {
2495
2507
  return true;
2496
2508
  }
2497
- if (ZlibStream) {
2509
+ if (FallbackStream) {
2498
2510
  try {
2499
2511
  await initModule(config);
2500
2512
  return true;
@@ -2507,12 +2519,16 @@
2507
2519
 
2508
2520
  function resetWebWorkerSupport() {
2509
2521
  webWorkerSupported = UNDEFINED_VALUE;
2522
+ createWorkerFailed = false;
2510
2523
  }
2511
2524
 
2512
2525
  class CodecWorker {
2513
2526
 
2514
- constructor(workerData, { readable, writable }, { options, config, streamOptions, useWebWorkers, transferStreams, workerURI }, onTaskFinished) {
2527
+ constructor(workerData, { readable, writable }, { options, config, streamOptions, useWebWorkers, transferStreams, workerURI, createWorker }, onTaskFinished) {
2515
2528
  const { signal } = streamOptions;
2529
+ if (createWorkerFailed) {
2530
+ createWorker = UNDEFINED_VALUE;
2531
+ }
2516
2532
  Object.assign(workerData, {
2517
2533
  busy: true,
2518
2534
  generation: (workerData.generation || 0) + 1,
@@ -2522,6 +2538,7 @@
2522
2538
  writable,
2523
2539
  options: Object.assign({}, options),
2524
2540
  workerURI,
2541
+ createWorker,
2525
2542
  transferStreams,
2526
2543
  terminate() {
2527
2544
  return new Promise(resolve => {
@@ -2557,7 +2574,7 @@
2557
2574
  // deno-lint-ignore valid-typeof
2558
2575
  webWorkerSupported = typeof Worker != UNDEFINED_TYPE;
2559
2576
  }
2560
- return (useWebWorkers && webWorkerSupported ? createWebWorkerInterface : createWorkerInterface)(workerData, config);
2577
+ return (useWebWorkers && ((webWorkerSupported && workerURI) || createWorker) ? createWebWorkerInterface : createWorkerInterface)(workerData, config);
2561
2578
  }
2562
2579
  }
2563
2580
 
@@ -2614,7 +2631,11 @@
2614
2631
  try {
2615
2632
  worker = getWebWorker(workerData.workerURI, baseURI, workerData);
2616
2633
  } catch {
2617
- webWorkerSupported = false;
2634
+ if (workerData.createWorker) {
2635
+ createWorkerFailed = true;
2636
+ } else {
2637
+ webWorkerSupported = false;
2638
+ }
2618
2639
  return createWorkerInterface(workerData, config);
2619
2640
  }
2620
2641
  Object.assign(workerData, {
@@ -2627,7 +2648,11 @@
2627
2648
  return await runWebWorker(workerData, { chunkSize, wasmURI, baseURI, workerStartupTimeout });
2628
2649
  } catch (error) {
2629
2650
  if (error && error.workerStartupFailed) {
2630
- webWorkerSupported = false;
2651
+ if (workerData.createWorker) {
2652
+ createWorkerFailed = true;
2653
+ } else {
2654
+ webWorkerSupported = false;
2655
+ }
2631
2656
  const { reader } = workerData;
2632
2657
  if (reader) {
2633
2658
  reader.releaseLock();
@@ -2650,17 +2675,17 @@
2650
2675
  try {
2651
2676
  if (options.compressed && !options.format) {
2652
2677
  const deflate = options.codecType.startsWith(CODEC_DEFLATE);
2653
- const ZlibStream = deflate ? config.CompressionStreamZlib : config.DecompressionStreamZlib;
2678
+ const FallbackStream = deflate ? config.CompressionStreamFallback : config.DecompressionStreamFallback;
2654
2679
  const NativeStream = deflate ? config.CompressionStream : config.DecompressionStream;
2655
2680
  if (!options.useCompressionStream) {
2656
2681
  try {
2657
2682
  await initModule(config);
2658
2683
  } catch {
2659
- if (!ZlibStream || ZlibStream.requiresModule) {
2684
+ if (!FallbackStream || FallbackStream.requiresModule) {
2660
2685
  options.useCompressionStream = true;
2661
2686
  }
2662
2687
  }
2663
- } else if (ZlibStream && ZlibStream.requiresModule && !supportsDeflateRaw(NativeStream)) {
2688
+ } else if (FallbackStream && FallbackStream.requiresModule && !supportsDeflateRaw(NativeStream)) {
2664
2689
  try {
2665
2690
  await initModule(config);
2666
2691
  } catch {
@@ -2674,12 +2699,12 @@
2674
2699
  .pipeThrough(new ChunkStream(getChunkSize(config)))
2675
2700
  .pipeTo(writable, { preventClose: true, preventAbort: true });
2676
2701
  const {
2677
- signature,
2702
+ crc32,
2678
2703
  inputSize,
2679
2704
  outputSize
2680
2705
  } = codecStream;
2681
2706
  return {
2682
- signature,
2707
+ crc32,
2683
2708
  inputSize,
2684
2709
  outputSize
2685
2710
  };
@@ -2785,8 +2810,11 @@
2785
2810
  }
2786
2811
 
2787
2812
  function getWebWorker(url, baseURI, workerData, isModuleType, useBlobURI = true) {
2813
+ const { createWorker } = workerData;
2788
2814
  let worker, resolvedURI, resolvedOptions;
2789
- if (webWorkerURI === UNDEFINED_VALUE || webWorkerSource !== url) {
2815
+ if (createWorker) {
2816
+ worker = createWorker();
2817
+ } else if (webWorkerURI === UNDEFINED_VALUE || webWorkerSource !== url) {
2790
2818
  // deno-lint-ignore valid-typeof
2791
2819
  const isFunctionURI = typeof url == FUNCTION_TYPE;
2792
2820
  if (isFunctionURI) {
@@ -3041,7 +3069,7 @@
3041
3069
  async function runWorker(stream, workerOptions) {
3042
3070
  const { options, config } = workerOptions;
3043
3071
  const { transferStreams, useWebWorkers, useCompressionStream, compressed, checkCrc32, computeCrc32, encrypted, format, codecURI } = options;
3044
- const { workerURI, maxWorkers } = config;
3072
+ const { workerURI, createWorker, maxWorkers } = config;
3045
3073
  if (format) {
3046
3074
  if (codecURI) {
3047
3075
  options.codecURI = resolveCodecURI(codecURI, config.baseURI);
@@ -3053,6 +3081,7 @@
3053
3081
  const workerSupported = format === UNDEFINED_VALUE || Boolean(options.codecURI);
3054
3082
  workerOptions.useWebWorkers = !streamCopy && workerSupported && (useWebWorkers || (useWebWorkers === UNDEFINED_VALUE && config.useWebWorkers));
3055
3083
  workerOptions.workerURI = workerOptions.useWebWorkers && workerURI ? workerURI : UNDEFINED_VALUE;
3084
+ workerOptions.createWorker = workerOptions.useWebWorkers && createWorker ? createWorker : UNDEFINED_VALUE;
3056
3085
  options.useCompressionStream = useCompressionStream || (useCompressionStream === UNDEFINED_VALUE && config.useCompressionStream);
3057
3086
  return (await getWorker()).run();
3058
3087
 
@@ -3116,7 +3145,7 @@
3116
3145
  starvationTimeout = null;
3117
3146
  if (pendingRequests.length) {
3118
3147
  const [{ resolve, stream, workerOptions }] = pendingRequests.splice(0, 1);
3119
- const inlineWorkerOptions = Object.assign({}, workerOptions, { useWebWorkers: false, workerURI: UNDEFINED_VALUE });
3148
+ const inlineWorkerOptions = Object.assign({}, workerOptions, { useWebWorkers: false, workerURI: UNDEFINED_VALUE, createWorker: UNDEFINED_VALUE });
3120
3149
  resolve(new CodecWorker({}, stream, inlineWorkerOptions, onInlineTaskFinished));
3121
3150
  armStarvationTimeout();
3122
3151
  }
@@ -4277,6 +4306,8 @@
4277
4306
  const PROPERTY_NAME_EXTRA_FIELD = "extraField";
4278
4307
  const PROPERTY_NAME_EXTRA_FIELD_INFOZIP = "extraFieldInfoZip";
4279
4308
  const PROPERTY_NAME_EXTRA_FIELD_UNIX = "extraFieldUnix";
4309
+ const PROPERTY_NAME_EXTRA_FIELD_UNIX_TYPE1 = "extraFieldUnixType1";
4310
+ const PROPERTY_NAME_EXTRA_FIELD_PKWARE_UNIX = "extraFieldPkwareUnix";
4280
4311
  const PROPERTY_NAME_UID = "uid";
4281
4312
  const PROPERTY_NAME_GID = "gid";
4282
4313
  const PROPERTY_NAME_UNIX_MODE = "unixMode";
@@ -4293,6 +4324,7 @@
4293
4324
  const PROPERTY_NAME_EXTRA_FIELD_AES = "extraFieldAES";
4294
4325
  const PROPERTY_NAME_EXTRA_FIELD_NTFS = "extraFieldNTFS";
4295
4326
  const PROPERTY_NAME_EXTRA_FIELD_EXTENDED_TIMESTAMP = "extraFieldExtendedTimestamp";
4327
+ const PROPERTY_NAME_EXTRA_FIELD_USDZ = "extraFieldUSDZ";
4296
4328
 
4297
4329
  const PROPERTY_NAMES = [
4298
4330
  PROPERTY_NAME_FILENAME,
@@ -4304,6 +4336,7 @@
4304
4336
  PROPERTY_NAME_COMMENT,
4305
4337
  PROPERTY_NAME_RAW_COMMENT,
4306
4338
  PROPERTY_NAME_LAST_ACCESS_DATE,
4339
+ PROPERTY_NAME_RAW_LAST_ACCESS_DATE,
4307
4340
  PROPERTY_NAME_CREATION_DATE,
4308
4341
  PROPERTY_NAME_RAW_CREATION_DATE,
4309
4342
  PROPERTY_NAME_OFFSET,
@@ -4326,6 +4359,8 @@
4326
4359
  PROPERTY_NAME_EXTRA_FIELD,
4327
4360
  PROPERTY_NAME_EXTRA_FIELD_UNIX,
4328
4361
  PROPERTY_NAME_EXTRA_FIELD_INFOZIP,
4362
+ PROPERTY_NAME_EXTRA_FIELD_UNIX_TYPE1,
4363
+ PROPERTY_NAME_EXTRA_FIELD_PKWARE_UNIX,
4329
4364
  PROPERTY_NAME_UID,
4330
4365
  PROPERTY_NAME_GID,
4331
4366
  PROPERTY_NAME_UNIX_MODE,
@@ -4341,7 +4376,8 @@
4341
4376
  PROPERTY_NAME_EXTRA_FIELD_UNICODE_COMMENT,
4342
4377
  PROPERTY_NAME_EXTRA_FIELD_AES,
4343
4378
  PROPERTY_NAME_EXTRA_FIELD_NTFS,
4344
- PROPERTY_NAME_EXTRA_FIELD_EXTENDED_TIMESTAMP
4379
+ PROPERTY_NAME_EXTRA_FIELD_EXTENDED_TIMESTAMP,
4380
+ PROPERTY_NAME_EXTRA_FIELD_USDZ
4345
4381
  ];
4346
4382
 
4347
4383
  class Entry {
@@ -4415,6 +4451,7 @@
4415
4451
  const OPTION_OFFSET = "offset";
4416
4452
  const OPTION_USDZ = "usdz";
4417
4453
  const OPTION_UNIX_EXTRA_FIELD_TYPE = "unixExtraFieldType";
4454
+ const OPTION_LOCAL_EXTRA_FIELD = "localExtraField";
4418
4455
  const OPTION_STRICTNESS = "strictness";
4419
4456
  const OPTION_MAX_APPENDED_DATA_SIZE = "maxAppendedDataSize";
4420
4457
  const STRICTNESS_STRICT = "strict";
@@ -4467,7 +4504,7 @@
4467
4504
  const PROPERTY_NAME_UTF8_SUFFIX = "UTF8";
4468
4505
  const CHARSET_CP437 = "cp437";
4469
4506
  const BITFLAG_AMBIGUITY_MASK = BITFLAG_ENCRYPTED | BITFLAG_DATA_DESCRIPTOR | BITFLAG_LANG_ENCODING_FLAG;
4470
- const VENDOR_VERSION_AE_1 = 1;
4507
+ const VENDOR_VERSION_AE_1$1 = 1;
4471
4508
  const ZIP64_PROPERTIES = [
4472
4509
  [PROPERTY_NAME_UNCOMPRESSED_SIZE, MAX_32_BITS],
4473
4510
  [PROPERTY_NAME_COMPRESSED_SIZE, MAX_32_BITS],
@@ -4860,7 +4897,7 @@
4860
4897
  config,
4861
4898
  bitFlag,
4862
4899
  rawBitFlag,
4863
- signature,
4900
+ crc32,
4864
4901
  rawLastModDate,
4865
4902
  uncompressedSize,
4866
4903
  compressedSize
@@ -4951,7 +4988,7 @@
4951
4988
  const checkCrc32 = (checkCrc32Option === UNDEFINED_VALUE ?
4952
4989
  getOptionValue$1(zipEntry, options, OPTION_CHECK_SIGNATURE) :
4953
4990
  checkCrc32Option) && !passThrough &&
4954
- (!encrypted || zipCrypto || (extraFieldAES && extraFieldAES.vendorVersion == VENDOR_VERSION_AE_1));
4991
+ (!encrypted || zipCrypto || (extraFieldAES && extraFieldAES.vendorVersion == VENDOR_VERSION_AE_1$1));
4955
4992
  const workerOptions = {
4956
4993
  options: {
4957
4994
  codecType: CODEC_INFLATE,
@@ -4961,9 +4998,9 @@
4961
4998
  encryptionStrength: extraFieldAES && extraFieldAES.strength,
4962
4999
  checkCrc32,
4963
5000
  checkAuthenticationCode: getOptionValue$1(zipEntry, options, OPTION_CHECK_AUTHENTICATION_CODE),
4964
- passwordVerification: zipCrypto && (dataDescriptor ? ((rawLastModDate >>> 8) & MAX_8_BITS) : ((signature >>> 24) & MAX_8_BITS)),
5001
+ passwordVerification: zipCrypto && (dataDescriptor ? ((rawLastModDate >>> 8) & MAX_8_BITS) : ((crc32 >>> 24) & MAX_8_BITS)),
4965
5002
  outputSize: passThrough ? compressedSize : uncompressedSize,
4966
- signature,
5003
+ crc32,
4967
5004
  compressed: compressionMethod != 0 && !passThrough,
4968
5005
  encrypted,
4969
5006
  useWebWorkers: getOptionValue$1(zipEntry, options, OPTION_USE_WEB_WORKERS),
@@ -4985,7 +5022,7 @@
4985
5022
  fileEntry,
4986
5023
  index,
4987
5024
  offset: localHeaderOffset,
4988
- signature,
5025
+ crc32,
4989
5026
  compressedSize,
4990
5027
  uncompressedSize,
4991
5028
  dataOffset,
@@ -5102,6 +5139,16 @@
5102
5139
  } else {
5103
5140
  directory.compressionMethod = compressionMethod;
5104
5141
  }
5142
+ const extraFieldPkwareUnix = extraField.get(EXTRAFIELD_TYPE_PKWARE_UNIX);
5143
+ if (extraFieldPkwareUnix) {
5144
+ readExtraFieldUnixDates(extraFieldPkwareUnix, directory);
5145
+ directory.extraFieldPkwareUnix = extraFieldPkwareUnix;
5146
+ }
5147
+ const extraFieldUnixType1 = extraField.get(EXTRAFIELD_TYPE_UNIX_TYPE1);
5148
+ if (extraFieldUnixType1) {
5149
+ readExtraFieldUnixDates(extraFieldUnixType1, directory);
5150
+ directory.extraFieldUnixType1 = extraFieldUnixType1;
5151
+ }
5105
5152
  const extraFieldNTFS = extraField.get(EXTRAFIELD_TYPE_NTFS);
5106
5153
  if (extraFieldNTFS) {
5107
5154
  readExtraFieldNTFS(extraFieldNTFS, directory);
@@ -5151,15 +5198,15 @@
5151
5198
  return;
5152
5199
  }
5153
5200
  const extraFieldView = getDataView(extraFieldUnicode.data);
5154
- const crc32 = new Crc32();
5155
- crc32.append(fileEntry[rawPropertyName]);
5156
- const dataViewSignature = getDataView(new Uint8Array(4));
5157
- dataViewSignature.setUint32(0, crc32.get(), true);
5158
- const signature = getUint32(extraFieldView, 1);
5201
+ const computedCrc32 = new Crc32();
5202
+ computedCrc32.append(fileEntry[rawPropertyName]);
5203
+ const computedCrc32View = getDataView(new Uint8Array(4));
5204
+ computedCrc32View.setUint32(0, computedCrc32.get(), true);
5205
+ const nameCrc32 = getUint32(extraFieldView, 1);
5159
5206
  Object.assign(extraFieldUnicode, {
5160
5207
  version: getUint8(extraFieldView, 0),
5161
5208
  [propertyName]: decodeText(extraFieldUnicode.data.subarray(5)),
5162
- valid: !fileEntry.bitFlag.languageEncodingFlag && signature == getUint32(dataViewSignature, 0)
5209
+ valid: !fileEntry.bitFlag.languageEncodingFlag && nameCrc32 == getUint32(computedCrc32View, 0)
5163
5210
  });
5164
5211
  if (extraFieldUnicode.valid) {
5165
5212
  directory[propertyName] = extraFieldUnicode[propertyName];
@@ -5178,7 +5225,7 @@
5178
5225
  compressionMethod: getUint16(extraFieldView, 5)
5179
5226
  });
5180
5227
  directory.compressionMethod = extraFieldAES.compressionMethod;
5181
- if (extraFieldAES.vendorVersion != VENDOR_VERSION_AE_1) {
5228
+ if (extraFieldAES.vendorVersion != VENDOR_VERSION_AE_1$1) {
5182
5229
  directory.crc32 = UNDEFINED_VALUE;
5183
5230
  }
5184
5231
  }
@@ -5218,6 +5265,22 @@
5218
5265
  }
5219
5266
  }
5220
5267
 
5268
+ function readExtraFieldUnixDates(extraField, directory) {
5269
+ if (extraField.data.length < 8) {
5270
+ return;
5271
+ }
5272
+ const extraFieldView = getDataView(extraField.data);
5273
+ const lastAccessDate = new Date(getUint32(extraFieldView, 0) * 1000);
5274
+ const lastModDate = new Date(getUint32(extraFieldView, 4) * 1000);
5275
+ const extraFieldData = { lastAccessDate, lastModDate };
5276
+ if (extraField.data.length >= 12) {
5277
+ extraFieldData.uid = getUint16(extraFieldView, 8);
5278
+ extraFieldData.gid = getUint16(extraFieldView, 10);
5279
+ }
5280
+ Object.assign(extraField, extraFieldData);
5281
+ Object.assign(directory, extraFieldData);
5282
+ }
5283
+
5221
5284
  function readExtraFieldUnix(extraField, directory, isInfoZip) {
5222
5285
  try {
5223
5286
  const view = getDataView(extraField.data);
@@ -5296,7 +5359,7 @@
5296
5359
  fileEntry,
5297
5360
  index,
5298
5361
  offset,
5299
- signature,
5362
+ crc32,
5300
5363
  compressedSize,
5301
5364
  uncompressedSize,
5302
5365
  dataOffset,
@@ -5317,7 +5380,7 @@
5317
5380
  const dataDescriptorSignature = dataDescriptorArray.length == dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH &&
5318
5381
  getUint32(getDataView(dataDescriptorArray), 0) == DATA_DESCRIPTOR_RECORD_SIGNATURE;
5319
5382
  if (dataDescriptorSignature) {
5320
- const readSignature = getUint32(getDataView(dataDescriptorArray), 4);
5383
+ const readCrc32 = getUint32(getDataView(dataDescriptorArray), 4);
5321
5384
  let readCompressedSize;
5322
5385
  let readUncompressedSize;
5323
5386
  if (extraFieldZip64) {
@@ -5327,8 +5390,8 @@
5327
5390
  readCompressedSize = getUint32(getDataView(dataDescriptorArray), 8);
5328
5391
  readUncompressedSize = getUint32(getDataView(dataDescriptorArray), 12);
5329
5392
  }
5330
- const matchSignature = (fileEntry.encrypted && !fileEntry.zipCrypto) || readSignature == signature;
5331
- if (matchSignature &&
5393
+ const matchCrc32 = (fileEntry.encrypted && !fileEntry.zipCrypto) || readCrc32 == crc32;
5394
+ if (matchCrc32 &&
5332
5395
  readCompressedSize == compressedSize &&
5333
5396
  readUncompressedSize == uncompressedSize) {
5334
5397
  dataDescriptorLength += DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH;
@@ -5497,11 +5560,11 @@
5497
5560
  throwAmbiguousArchive("mismatched local file header (compression method)");
5498
5561
  }
5499
5562
  if (!localDirectory.bitFlag.dataDescriptor &&
5500
- (localDirectory.signature || localDirectory.compressedSize || localDirectory.uncompressedSize) &&
5501
- (localDirectory.signature != zipEntry.signature ||
5563
+ (localDirectory.crc32 || localDirectory.compressedSize || localDirectory.uncompressedSize) &&
5564
+ (localDirectory.crc32 != zipEntry.crc32 ||
5502
5565
  localDirectory.compressedSize != zipEntry.compressedSize ||
5503
5566
  localDirectory.uncompressedSize != zipEntry.uncompressedSize)) {
5504
- throwAmbiguousArchive("mismatched local file header (signature or sizes)");
5567
+ throwAmbiguousArchive("mismatched local file header (crc32 or sizes)");
5505
5568
  }
5506
5569
  }
5507
5570
 
@@ -5621,6 +5684,8 @@
5621
5684
  const ERR_INVALID_MSDOS_DATA = "Invalid msdosAttributes (must be an object with boolean flags)";
5622
5685
 
5623
5686
  const EXTRAFIELD_DATA_AES = new Uint8Array([0x07, 0x00, 0x02, 0x00, 0x41, 0x45, 0x03, 0x00, 0x00]);
5687
+ const EXTRAFIELD_OFFSET_AES_VENDOR_VERSION = 4;
5688
+ const VENDOR_VERSION_AE_1 = 1;
5624
5689
  const INFOZIP_EXTRA_FIELD_TYPE = "infozip";
5625
5690
  const UNIX_EXTRA_FIELD_TYPE = "unix";
5626
5691
 
@@ -5715,9 +5780,9 @@
5715
5780
  zip64UncompressedSize,
5716
5781
  extraFieldLength
5717
5782
  });
5718
- const { signature } = entry;
5719
- if (signature !== UNDEFINED_VALUE) {
5720
- setUint32(headerView, HEADER_OFFSET_SIGNATURE, signature);
5783
+ const { crc32 } = entry;
5784
+ if (crc32 !== UNDEFINED_VALUE) {
5785
+ setUint32(headerView, HEADER_OFFSET_SIGNATURE, crc32);
5721
5786
  }
5722
5787
  Object.assign(entry, {
5723
5788
  zip64UncompressedSize,
@@ -5902,6 +5967,7 @@
5902
5967
  internalFileAttribute: metadataInfo.resolvedOptions.internalFileAttributes,
5903
5968
  externalFileAttribute: attributesInfo.resolvedOptions.externalFileAttributes,
5904
5969
  signature: options[PROPERTY_NAME_SIGNATURE],
5970
+ crc32: options.crc32 === UNDEFINED_VALUE ? options[PROPERTY_NAME_SIGNATURE] : options.crc32,
5905
5971
  offset: zipWriter.offset - diskOffset,
5906
5972
  diskNumberStart: diskNumber
5907
5973
  });
@@ -6118,27 +6184,8 @@
6118
6184
  if (!zipCrypto && (password !== UNDEFINED_VALUE || rawPassword !== UNDEFINED_VALUE) && !(encryptionStrength >= 1 && encryptionStrength <= 3)) {
6119
6185
  throw new Error(ERR_INVALID_ENCRYPTION_STRENGTH);
6120
6186
  }
6121
- let rawExtraField = EMPTY_UINT8_ARRAY;
6122
- const extraField = options[PROPERTY_NAME_EXTRA_FIELD];
6123
- if (extraField) {
6124
- let extraFieldSize = 0;
6125
- let offset = 0;
6126
- extraField.forEach(data => extraFieldSize += 4 + getLength(data));
6127
- rawExtraField = new Uint8Array(extraFieldSize);
6128
- const rawExtraFieldView = getDataView(rawExtraField);
6129
- extraField.forEach((data, type) => {
6130
- if (type > MAX_16_BITS) {
6131
- throw new Error(ERR_INVALID_EXTRAFIELD_TYPE);
6132
- }
6133
- if (getLength(data) > MAX_16_BITS) {
6134
- throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
6135
- }
6136
- setUint16(rawExtraFieldView, offset, type);
6137
- setUint16(rawExtraFieldView, offset + 2, getLength(data));
6138
- arraySet(rawExtraField, data, offset + 4);
6139
- offset += 4 + getLength(data);
6140
- });
6141
- }
6187
+ const rawExtraField = serializeExtraField(options[PROPERTY_NAME_EXTRA_FIELD]);
6188
+ const rawLocalExtraField = serializeExtraField(options[OPTION_LOCAL_EXTRA_FIELD]);
6142
6189
  return {
6143
6190
  comment,
6144
6191
  resolvedOptions: {
@@ -6172,11 +6219,36 @@
6172
6219
  useCompressionStream,
6173
6220
  dataDescriptor,
6174
6221
  zip64,
6175
- rawExtraField
6222
+ rawExtraField,
6223
+ rawLocalExtraField
6176
6224
  }
6177
6225
  };
6178
6226
  }
6179
6227
 
6228
+ function serializeExtraField(extraField) {
6229
+ if (!extraField) {
6230
+ return EMPTY_UINT8_ARRAY;
6231
+ }
6232
+ let extraFieldSize = 0;
6233
+ let offset = 0;
6234
+ extraField.forEach(data => extraFieldSize += 4 + getLength(data));
6235
+ const rawExtraField = new Uint8Array(extraFieldSize);
6236
+ const rawExtraFieldView = getDataView(rawExtraField);
6237
+ extraField.forEach((data, type) => {
6238
+ if (type > MAX_16_BITS) {
6239
+ throw new Error(ERR_INVALID_EXTRAFIELD_TYPE);
6240
+ }
6241
+ if (getLength(data) > MAX_16_BITS) {
6242
+ throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
6243
+ }
6244
+ setUint16(rawExtraFieldView, offset, type);
6245
+ setUint16(rawExtraFieldView, offset + 2, getLength(data));
6246
+ arraySet(rawExtraField, data, offset + 4);
6247
+ offset += 4 + getLength(data);
6248
+ });
6249
+ return rawExtraField;
6250
+ }
6251
+
6180
6252
  async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, options) {
6181
6253
  const { passThrough, zipCrypto, password, rawPassword, encryptionStrength } = metadata;
6182
6254
  let { dataDescriptor, zip64, level, compressionMethod } = metadata;
@@ -6501,12 +6573,9 @@
6501
6573
  msdosAttributes
6502
6574
  };
6503
6575
  let {
6504
- crc32: signature,
6576
+ crc32,
6505
6577
  uncompressedSize
6506
6578
  } = options;
6507
- if (signature === UNDEFINED_VALUE) {
6508
- ({ signature } = options);
6509
- }
6510
6579
  let compressedSize = 0;
6511
6580
  if (!passThrough) {
6512
6581
  uncompressedSize = 0;
@@ -6544,7 +6613,7 @@
6544
6613
  if (!passThrough) {
6545
6614
  uncompressedSize = result.inputSize;
6546
6615
  if (!encrypted || zipCrypto) {
6547
- signature = result.signature;
6616
+ crc32 = result.crc32;
6548
6617
  }
6549
6618
  }
6550
6619
  if ((!zip64CompressedSize && compressedSize >= MAX_32_BITS) ||
@@ -6560,7 +6629,7 @@
6560
6629
 
6561
6630
  }
6562
6631
  setEntryInfo({
6563
- signature,
6632
+ crc32,
6564
6633
  compressedSize,
6565
6634
  uncompressedSize,
6566
6635
  headerInfo,
@@ -6583,8 +6652,8 @@
6583
6652
  version,
6584
6653
  headerArray,
6585
6654
  headerView,
6586
- signature,
6587
- crc32: encrypted && !zipCrypto ? UNDEFINED_VALUE : signature,
6655
+ signature: crc32,
6656
+ crc32: encrypted && !zipCrypto && !passThrough ? UNDEFINED_VALUE : crc32,
6588
6657
  extraFieldExtendedTimestampFlag,
6589
6658
  zip64UncompressedSize,
6590
6659
  zip64CompressedSize
@@ -6605,6 +6674,7 @@
6605
6674
  dataDescriptor,
6606
6675
  directory,
6607
6676
  rawExtraField,
6677
+ rawLocalExtraField,
6608
6678
  encryptionStrength,
6609
6679
  extendedTimestamp,
6610
6680
  ntfsTimestamp,
@@ -6612,7 +6682,8 @@
6612
6682
  encrypted,
6613
6683
  zip64UncompressedSize,
6614
6684
  zip64CompressedSize,
6615
- uncompressedSize
6685
+ uncompressedSize,
6686
+ crc32
6616
6687
  } = options;
6617
6688
  let { version, compressionMethod } = options;
6618
6689
  const compressed = !directory && (compressionMethod === UNDEFINED_VALUE
@@ -6738,11 +6809,14 @@
6738
6809
  }
6739
6810
  if (encrypted && !zipCrypto) {
6740
6811
  version = version > VERSION_AES ? version : VERSION_AES;
6812
+ if (passThrough && crc32 !== UNDEFINED_VALUE) {
6813
+ rawExtraFieldAES[EXTRAFIELD_OFFSET_AES_VENDOR_VERSION] = VENDOR_VERSION_AE_1;
6814
+ }
6741
6815
  rawExtraFieldAES[9] = compressionMethod;
6742
6816
  compressionMethod = COMPRESSION_METHOD_AES;
6743
6817
  }
6744
6818
  const localExtraFieldZip64Length = writeLocalExtraFieldZip64 ? getLength(rawLocalExtraFieldZip64) : 0;
6745
- const extraFieldLength = localExtraFieldZip64Length + getLength(rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField);
6819
+ const extraFieldLength = localExtraFieldZip64Length + getLength(rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField, rawLocalExtraField);
6746
6820
  if (extraFieldLength > MAX_16_BITS) {
6747
6821
  throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
6748
6822
  }
@@ -6776,6 +6850,7 @@
6776
6850
  localHeader.bytes(rawExtraFieldNTFS);
6777
6851
  localHeader.bytes(rawExtraFieldUnix);
6778
6852
  localHeader.bytes(rawExtraField);
6853
+ localHeader.bytes(rawLocalExtraField);
6779
6854
  if (dataDescriptor) {
6780
6855
  if (!zip64CompressedSize) {
6781
6856
  setUint32(localHeaderView, HEADER_OFFSET_COMPRESSED_SIZE + LOCAL_HEADER_COMMON_OFFSET, 0);
@@ -6894,7 +6969,7 @@
6894
6969
  }
6895
6970
 
6896
6971
  function setEntryInfo({
6897
- signature,
6972
+ crc32,
6898
6973
  compressedSize,
6899
6974
  uncompressedSize,
6900
6975
  headerInfo,
@@ -6902,6 +6977,7 @@
6902
6977
  }, {
6903
6978
  zip64,
6904
6979
  zipCrypto,
6980
+ passThrough,
6905
6981
  dataDescriptor
6906
6982
  }) {
6907
6983
  const {
@@ -6912,10 +6988,10 @@
6912
6988
  dataDescriptorView,
6913
6989
  dataDescriptorOffset
6914
6990
  } = dataDescriptorInfo;
6915
- if ((!encrypted || zipCrypto) && signature !== UNDEFINED_VALUE) {
6916
- setUint32(headerView, HEADER_OFFSET_SIGNATURE, signature);
6991
+ if ((!encrypted || zipCrypto || passThrough) && crc32 !== UNDEFINED_VALUE) {
6992
+ setUint32(headerView, HEADER_OFFSET_SIGNATURE, crc32);
6917
6993
  if (dataDescriptor) {
6918
- setUint32(dataDescriptorView, dataDescriptorOffset, signature);
6994
+ setUint32(dataDescriptorView, dataDescriptorOffset, crc32);
6919
6995
  }
6920
6996
  }
6921
6997
  if (zip64) {
@@ -6938,15 +7014,15 @@
6938
7014
  encrypted,
6939
7015
  zip64,
6940
7016
  localExtraFieldZip64Length,
6941
- signature,
7017
+ crc32,
6942
7018
  compressedSize,
6943
7019
  uncompressedSize,
6944
7020
  zip64UncompressedSize,
6945
7021
  zip64CompressedSize
6946
- }, localHeaderView, { dataDescriptor }) {
7022
+ }, localHeaderView, { dataDescriptor, passThrough }) {
6947
7023
  if (!dataDescriptor) {
6948
- if (!encrypted) {
6949
- setUint32(localHeaderView, HEADER_OFFSET_SIGNATURE + LOCAL_HEADER_COMMON_OFFSET, signature);
7024
+ if (!encrypted || (passThrough && crc32 !== UNDEFINED_VALUE)) {
7025
+ setUint32(localHeaderView, HEADER_OFFSET_SIGNATURE + LOCAL_HEADER_COMMON_OFFSET, crc32);
6950
7026
  }
6951
7027
  if (!zip64CompressedSize) {
6952
7028
  setUint32(localHeaderView, HEADER_OFFSET_COMPRESSED_SIZE + LOCAL_HEADER_COMMON_OFFSET, compressedSize);