@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
@@ -70,6 +70,8 @@
70
70
  const EXTRAFIELD_TYPE_USDZ = 0x1986;
71
71
  const EXTRAFIELD_TYPE_INFOZIP = 0x7875;
72
72
  const EXTRAFIELD_TYPE_UNIX = 0x7855;
73
+ const EXTRAFIELD_TYPE_UNIX_TYPE1 = 0x5855;
74
+ const EXTRAFIELD_TYPE_PKWARE_UNIX = 0x000d;
73
75
 
74
76
  const BITFLAG_ENCRYPTED = 0b1;
75
77
  const BITFLAG_LEVEL = 0b0110;
@@ -2366,7 +2368,7 @@
2366
2368
  const DERIVED_BITS_USAGE = ["deriveBits"];
2367
2369
  const SALT_LENGTH = [8, 12, 16];
2368
2370
  const KEY_LENGTH = [16, 24, 32];
2369
- const SIGNATURE_LENGTH = 10;
2371
+ const AUTHENTICATION_CODE_LENGTH = 10;
2370
2372
  const COUNTER_DEFAULT_VALUE = [0, 0, 0, 0];
2371
2373
  // deno-lint-ignore valid-typeof
2372
2374
  const CRYPTO_API_SUPPORTED = typeof crypto != UNDEFINED_TYPE;
@@ -2406,8 +2408,8 @@
2406
2408
  } else {
2407
2409
  await ready;
2408
2410
  }
2409
- const output = new Uint8Array(chunk.length - SIGNATURE_LENGTH - ((chunk.length - SIGNATURE_LENGTH) % BLOCK_LENGTH));
2410
- controller.enqueue(append(aesCrypto, chunk, output, 0, SIGNATURE_LENGTH, true));
2411
+ const output = new Uint8Array(chunk.length - AUTHENTICATION_CODE_LENGTH - ((chunk.length - AUTHENTICATION_CODE_LENGTH) % BLOCK_LENGTH));
2412
+ controller.enqueue(append(aesCrypto, chunk, output, 0, AUTHENTICATION_CODE_LENGTH, true));
2411
2413
  },
2412
2414
  async flush(controller) {
2413
2415
  const {
@@ -2418,8 +2420,8 @@
2418
2420
  } = this;
2419
2421
  if (hmac && ctr) {
2420
2422
  await ready;
2421
- const chunkToDecrypt = subarray(pending, 0, pending.length - SIGNATURE_LENGTH);
2422
- const originalSignature = subarray(pending, pending.length - SIGNATURE_LENGTH);
2423
+ const chunkToDecrypt = subarray(pending, 0, pending.length - AUTHENTICATION_CODE_LENGTH);
2424
+ const originalAuthenticationCode = subarray(pending, pending.length - AUTHENTICATION_CODE_LENGTH);
2423
2425
  let decryptedChunkArray = EMPTY_UINT8_ARRAY;
2424
2426
  if (chunkToDecrypt.length) {
2425
2427
  const encryptedChunk = toBits(codecBytes, chunkToDecrypt);
@@ -2427,12 +2429,12 @@
2427
2429
  const decryptedChunk = ctr.update(encryptedChunk);
2428
2430
  decryptedChunkArray = fromBits(codecBytes, decryptedChunk);
2429
2431
  }
2430
- const signature = subarray(fromBits(codecBytes, hmac.digest()), 0, SIGNATURE_LENGTH);
2431
- let invalidSignature = pending.length < SIGNATURE_LENGTH ? 1 : 0;
2432
- for (let indexSignature = 0; indexSignature < SIGNATURE_LENGTH; indexSignature++) {
2433
- invalidSignature |= signature[indexSignature] ^ originalSignature[indexSignature];
2432
+ const authenticationCode = subarray(fromBits(codecBytes, hmac.digest()), 0, AUTHENTICATION_CODE_LENGTH);
2433
+ let invalidAuthenticationCode = pending.length < AUTHENTICATION_CODE_LENGTH ? 1 : 0;
2434
+ for (let indexByte = 0; indexByte < AUTHENTICATION_CODE_LENGTH; indexByte++) {
2435
+ invalidAuthenticationCode |= authenticationCode[indexByte] ^ originalAuthenticationCode[indexByte];
2434
2436
  }
2435
- if (invalidSignature && checkAuthenticationCode) {
2437
+ if (invalidAuthenticationCode && checkAuthenticationCode) {
2436
2438
  throw new Error(ERR_INVALID_AUTHENTICATION_CODE);
2437
2439
  }
2438
2440
  controller.enqueue(decryptedChunkArray);
@@ -2445,8 +2447,6 @@
2445
2447
  class AESEncryptionStream extends TransformStream {
2446
2448
 
2447
2449
  constructor({ password, rawPassword, encryptionStrength }) {
2448
- // deno-lint-ignore prefer-const
2449
- let stream;
2450
2450
  super({
2451
2451
  start() {
2452
2452
  initAesCrypto(this, password, rawPassword, encryptionStrength);
@@ -2485,12 +2485,11 @@
2485
2485
  hmac.update(encryptedChunk);
2486
2486
  encryptedChunkArray = fromBits(codecBytes, encryptedChunk);
2487
2487
  }
2488
- stream.signature = fromBits(codecBytes, hmac.digest()).slice(0, SIGNATURE_LENGTH);
2489
- controller.enqueue(concat(encryptedChunkArray, stream.signature));
2488
+ const authenticationCode = fromBits(codecBytes, hmac.digest()).slice(0, AUTHENTICATION_CODE_LENGTH);
2489
+ controller.enqueue(concat(encryptedChunkArray, authenticationCode));
2490
2490
  }
2491
2491
  }
2492
2492
  });
2493
- stream = this;
2494
2493
  }
2495
2494
  }
2496
2495
 
@@ -2503,7 +2502,7 @@
2503
2502
  });
2504
2503
  }
2505
2504
 
2506
- function append(aesCrypto, input, output, paddingStart, paddingEnd, verifySignature) {
2505
+ function append(aesCrypto, input, output, paddingStart, paddingEnd, verifyAuthenticationCode) {
2507
2506
  const {
2508
2507
  ctr,
2509
2508
  hmac,
@@ -2517,11 +2516,11 @@
2517
2516
  let offset;
2518
2517
  for (offset = 0; offset <= inputLength - BLOCK_LENGTH; offset += BLOCK_LENGTH) {
2519
2518
  const inputChunk = toBits(codecBytes, subarray(input, offset, offset + BLOCK_LENGTH));
2520
- if (verifySignature) {
2519
+ if (verifyAuthenticationCode) {
2521
2520
  hmac.update(inputChunk);
2522
2521
  }
2523
2522
  const outputChunk = ctr.update(inputChunk);
2524
- if (!verifySignature) {
2523
+ if (!verifyAuthenticationCode) {
2525
2524
  hmac.update(outputChunk);
2526
2525
  }
2527
2526
  output.set(fromBits(codecBytes, outputChunk), offset + paddingStart);
@@ -2816,7 +2815,7 @@
2816
2815
 
2817
2816
  class DeflateStream extends TransformStream {
2818
2817
 
2819
- constructor(options, { chunkSize, CompressionStreamZlib, CompressionStream }) {
2818
+ constructor(options, { chunkSize, CompressionStreamFallback, CompressionStream }) {
2820
2819
  super({});
2821
2820
  const { compressed, encrypted, useCompressionStream, zipCrypto, computeCrc32, level, deflate64, format, compressionMethod } = options;
2822
2821
  const stream = this;
@@ -2838,7 +2837,7 @@
2838
2837
  readable = pipeThrough(readable, gzipCrc32Stream);
2839
2838
  } else {
2840
2839
  try {
2841
- readable = pipeThroughCompressionStream(readable, useCompressionStream, { level, chunkSize }, CompressionStream, CompressionStreamZlib);
2840
+ readable = pipeThroughCompressionStream(readable, useCompressionStream, { level, chunkSize }, CompressionStream, CompressionStreamFallback);
2842
2841
  } catch (error) {
2843
2842
  let gzipStream;
2844
2843
  try {
@@ -2860,14 +2859,9 @@
2860
2859
  }
2861
2860
  }
2862
2861
  setReadable(stream, readable, () => {
2863
- let signature;
2864
- if (encrypted && !zipCrypto) {
2865
- signature = encryptionStream.signature;
2866
- }
2867
2862
  if ((!encrypted || zipCrypto) && computeCrc32) {
2868
- signature = useGzipCrc32 ? gzipCrc32Stream.signature : new DataView(crc32Stream.value.buffer).getUint32(0);
2863
+ stream.crc32 = useGzipCrc32 ? gzipCrc32Stream.crc32 : new DataView(crc32Stream.value.buffer).getUint32(0);
2869
2864
  }
2870
- stream.signature = signature;
2871
2865
  });
2872
2866
  }
2873
2867
  }
@@ -2905,7 +2899,7 @@
2905
2899
  },
2906
2900
  flush() {
2907
2901
  const dataView = getDataView(trailerCandidate);
2908
- stream.signature = dataView.getUint32(0, true);
2902
+ stream.crc32 = dataView.getUint32(0, true);
2909
2903
  stream.uncompressedSize = dataView.getUint32(4, true);
2910
2904
  }
2911
2905
  });
@@ -2985,9 +2979,9 @@
2985
2979
 
2986
2980
  class InflateStream extends TransformStream {
2987
2981
 
2988
- constructor(options, { chunkSize, DecompressionStreamZlib, DecompressionStream }) {
2982
+ constructor(options, { chunkSize, DecompressionStreamFallback, DecompressionStream }) {
2989
2983
  super({});
2990
- const { zipCrypto, encrypted, checkCrc32, signature, compressed, useCompressionStream, deflate64, format, compressionMethod, rawBitFlag, outputSize } = options;
2984
+ const { zipCrypto, encrypted, checkCrc32, crc32, compressed, useCompressionStream, deflate64, format, compressionMethod, rawBitFlag, outputSize } = options;
2991
2985
  let crc32Stream, decryptionStream;
2992
2986
  let readable = super.readable;
2993
2987
  if (encrypted) {
@@ -3004,7 +2998,7 @@
3004
2998
  readable = pipeThroughBackpressured(readable, createCodecStream(codecStreams.DecompressionStream, format, { chunkSize, compressionMethod, rawBitFlag, uncompressedSize: outputSize }));
3005
2999
  } else {
3006
3000
  try {
3007
- readable = pipeThroughCompressionStream(readable, useCompressionStream, { chunkSize, deflate64 }, DecompressionStream, DecompressionStreamZlib);
3001
+ readable = pipeThroughCompressionStream(readable, useCompressionStream, { chunkSize, deflate64 }, DecompressionStream, DecompressionStreamFallback);
3008
3002
  } catch (error) {
3009
3003
  if (deflate64 || outputSize === UNDEFINED_VALUE) {
3010
3004
  throw error;
@@ -3026,8 +3020,8 @@
3026
3020
  }
3027
3021
  setReadable(this, readable, () => {
3028
3022
  if (checkCrc32) {
3029
- const dataViewSignature = new DataView(crc32Stream.value.buffer);
3030
- if (signature != dataViewSignature.getUint32(0, false)) {
3023
+ const computedCrc32View = new DataView(crc32Stream.value.buffer);
3024
+ if (crc32 != computedCrc32View.getUint32(0, false)) {
3031
3025
  throw new Error(ERR_INVALID_CRC32);
3032
3026
  }
3033
3027
  }
@@ -3083,17 +3077,17 @@
3083
3077
  return new CodecStreamClass(format, options);
3084
3078
  }
3085
3079
 
3086
- function pipeThroughCompressionStream(readable, useCompressionStream, options, CompressionStreamNative, CompressionStreamZlib) {
3080
+ function pipeThroughCompressionStream(readable, useCompressionStream, options, CompressionStreamNative, CompressionStreamFallback) {
3087
3081
  const Stream = useCompressionStream && CompressionStreamNative ?
3088
3082
  CompressionStreamNative :
3089
- CompressionStreamZlib || CompressionStreamNative;
3083
+ CompressionStreamFallback || CompressionStreamNative;
3090
3084
  const format = options.deflate64 ? FORMAT_DEFLATE64_RAW : FORMAT_DEFLATE_RAW;
3091
3085
  let codecStream;
3092
3086
  try {
3093
3087
  codecStream = new Stream(format, options);
3094
3088
  } catch (error) {
3095
- if (useCompressionStream && CompressionStreamZlib && Stream != CompressionStreamZlib) {
3096
- codecStream = new CompressionStreamZlib(format, options);
3089
+ if (useCompressionStream && CompressionStreamFallback && Stream != CompressionStreamFallback) {
3090
+ codecStream = new CompressionStreamFallback(format, options);
3097
3091
  } else {
3098
3092
  throw error;
3099
3093
  }
@@ -3252,9 +3246,9 @@
3252
3246
  }
3253
3247
  },
3254
3248
  flush() {
3255
- const { signature } = stream;
3249
+ const { crc32 } = stream;
3256
3250
  Object.assign(codec, {
3257
- signature,
3251
+ crc32,
3258
3252
  inputSize
3259
3253
  });
3260
3254
  }
@@ -3356,7 +3350,7 @@
3356
3350
  const MESSAGE_ERROR_EVENT_TYPE = "messageerror";
3357
3351
  const ERR_WORKER_STARTUP_TIMEOUT = "Worker startup timeout";
3358
3352
 
3359
- let webWorkerSupported, webWorkerSource, webWorkerURI, webWorkerOptions;
3353
+ let webWorkerSupported, webWorkerSource, webWorkerURI, webWorkerOptions, createWorkerFailed;
3360
3354
  let transferStreamsSupported = true;
3361
3355
  try {
3362
3356
  transferStreamsSupported = typeof structuredClone == FUNCTION_TYPE && structuredClone(new DOMException("", "AbortError")).code !== UNDEFINED_VALUE;
@@ -3366,14 +3360,14 @@
3366
3360
  let initModule = () => { };
3367
3361
 
3368
3362
  async function supportsDeflate(config) {
3369
- const { CompressionStream: NativeStream, CompressionStreamZlib: ZlibStream } = config;
3370
- if (ZlibStream && !ZlibStream.requiresModule) {
3363
+ const { CompressionStream: NativeStream, CompressionStreamFallback: FallbackStream } = config;
3364
+ if (FallbackStream && !FallbackStream.requiresModule) {
3371
3365
  return true;
3372
3366
  }
3373
3367
  if (supportsDeflateRaw(NativeStream) || supportsGzip(NativeStream)) {
3374
3368
  return true;
3375
3369
  }
3376
- if (ZlibStream) {
3370
+ if (FallbackStream) {
3377
3371
  try {
3378
3372
  await initModule(config);
3379
3373
  return true;
@@ -3386,8 +3380,11 @@
3386
3380
 
3387
3381
  class CodecWorker {
3388
3382
 
3389
- constructor(workerData, { readable, writable }, { options, config, streamOptions, useWebWorkers, transferStreams, workerURI }, onTaskFinished) {
3383
+ constructor(workerData, { readable, writable }, { options, config, streamOptions, useWebWorkers, transferStreams, workerURI, createWorker }, onTaskFinished) {
3390
3384
  const { signal } = streamOptions;
3385
+ if (createWorkerFailed) {
3386
+ createWorker = UNDEFINED_VALUE;
3387
+ }
3391
3388
  Object.assign(workerData, {
3392
3389
  busy: true,
3393
3390
  generation: (workerData.generation || 0) + 1,
@@ -3397,6 +3394,7 @@
3397
3394
  writable,
3398
3395
  options: Object.assign({}, options),
3399
3396
  workerURI,
3397
+ createWorker,
3400
3398
  transferStreams,
3401
3399
  terminate() {
3402
3400
  return new Promise(resolve => {
@@ -3432,7 +3430,7 @@
3432
3430
  // deno-lint-ignore valid-typeof
3433
3431
  webWorkerSupported = typeof Worker != UNDEFINED_TYPE;
3434
3432
  }
3435
- return (useWebWorkers && webWorkerSupported ? createWebWorkerInterface : createWorkerInterface)(workerData, config);
3433
+ return (useWebWorkers && ((webWorkerSupported && workerURI) || createWorker) ? createWebWorkerInterface : createWorkerInterface)(workerData, config);
3436
3434
  }
3437
3435
  }
3438
3436
 
@@ -3489,7 +3487,11 @@
3489
3487
  try {
3490
3488
  worker = getWebWorker(workerData.workerURI, baseURI, workerData);
3491
3489
  } catch {
3492
- webWorkerSupported = false;
3490
+ if (workerData.createWorker) {
3491
+ createWorkerFailed = true;
3492
+ } else {
3493
+ webWorkerSupported = false;
3494
+ }
3493
3495
  return createWorkerInterface(workerData, config);
3494
3496
  }
3495
3497
  Object.assign(workerData, {
@@ -3502,7 +3504,11 @@
3502
3504
  return await runWebWorker(workerData, { chunkSize, wasmURI, baseURI, workerStartupTimeout });
3503
3505
  } catch (error) {
3504
3506
  if (error && error.workerStartupFailed) {
3505
- webWorkerSupported = false;
3507
+ if (workerData.createWorker) {
3508
+ createWorkerFailed = true;
3509
+ } else {
3510
+ webWorkerSupported = false;
3511
+ }
3506
3512
  const { reader } = workerData;
3507
3513
  if (reader) {
3508
3514
  reader.releaseLock();
@@ -3525,17 +3531,17 @@
3525
3531
  try {
3526
3532
  if (options.compressed && !options.format) {
3527
3533
  const deflate = options.codecType.startsWith(CODEC_DEFLATE);
3528
- const ZlibStream = deflate ? config.CompressionStreamZlib : config.DecompressionStreamZlib;
3534
+ const FallbackStream = deflate ? config.CompressionStreamFallback : config.DecompressionStreamFallback;
3529
3535
  const NativeStream = deflate ? config.CompressionStream : config.DecompressionStream;
3530
3536
  if (!options.useCompressionStream) {
3531
3537
  try {
3532
3538
  await initModule(config);
3533
3539
  } catch {
3534
- if (!ZlibStream || ZlibStream.requiresModule) {
3540
+ if (!FallbackStream || FallbackStream.requiresModule) {
3535
3541
  options.useCompressionStream = true;
3536
3542
  }
3537
3543
  }
3538
- } else if (ZlibStream && ZlibStream.requiresModule && !supportsDeflateRaw(NativeStream)) {
3544
+ } else if (FallbackStream && FallbackStream.requiresModule && !supportsDeflateRaw(NativeStream)) {
3539
3545
  try {
3540
3546
  await initModule(config);
3541
3547
  } catch {
@@ -3549,12 +3555,12 @@
3549
3555
  .pipeThrough(new ChunkStream(getChunkSize(config)))
3550
3556
  .pipeTo(writable, { preventClose: true, preventAbort: true });
3551
3557
  const {
3552
- signature,
3558
+ crc32,
3553
3559
  inputSize,
3554
3560
  outputSize
3555
3561
  } = codecStream;
3556
3562
  return {
3557
- signature,
3563
+ crc32,
3558
3564
  inputSize,
3559
3565
  outputSize
3560
3566
  };
@@ -3660,8 +3666,11 @@
3660
3666
  }
3661
3667
 
3662
3668
  function getWebWorker(url, baseURI, workerData, isModuleType, useBlobURI = true) {
3669
+ const { createWorker } = workerData;
3663
3670
  let worker, resolvedURI, resolvedOptions;
3664
- if (webWorkerURI === UNDEFINED_VALUE || webWorkerSource !== url) {
3671
+ if (createWorker) {
3672
+ worker = createWorker();
3673
+ } else if (webWorkerURI === UNDEFINED_VALUE || webWorkerSource !== url) {
3665
3674
  // deno-lint-ignore valid-typeof
3666
3675
  const isFunctionURI = typeof url == FUNCTION_TYPE;
3667
3676
  if (isFunctionURI) {
@@ -3916,7 +3925,7 @@
3916
3925
  async function runWorker(stream, workerOptions) {
3917
3926
  const { options, config } = workerOptions;
3918
3927
  const { transferStreams, useWebWorkers, useCompressionStream, compressed, checkCrc32, computeCrc32, encrypted, format, codecURI } = options;
3919
- const { workerURI, maxWorkers } = config;
3928
+ const { workerURI, createWorker, maxWorkers } = config;
3920
3929
  if (format) {
3921
3930
  if (codecURI) {
3922
3931
  options.codecURI = resolveCodecURI(codecURI, config.baseURI);
@@ -3928,6 +3937,7 @@
3928
3937
  const workerSupported = format === UNDEFINED_VALUE || Boolean(options.codecURI);
3929
3938
  workerOptions.useWebWorkers = !streamCopy && workerSupported && (useWebWorkers || (useWebWorkers === UNDEFINED_VALUE && config.useWebWorkers));
3930
3939
  workerOptions.workerURI = workerOptions.useWebWorkers && workerURI ? workerURI : UNDEFINED_VALUE;
3940
+ workerOptions.createWorker = workerOptions.useWebWorkers && createWorker ? createWorker : UNDEFINED_VALUE;
3931
3941
  options.useCompressionStream = useCompressionStream || (useCompressionStream === UNDEFINED_VALUE && config.useCompressionStream);
3932
3942
  return (await getWorker()).run();
3933
3943
 
@@ -3991,7 +4001,7 @@
3991
4001
  starvationTimeout = null;
3992
4002
  if (pendingRequests.length) {
3993
4003
  const [{ resolve, stream, workerOptions }] = pendingRequests.splice(0, 1);
3994
- const inlineWorkerOptions = Object.assign({}, workerOptions, { useWebWorkers: false, workerURI: UNDEFINED_VALUE });
4004
+ const inlineWorkerOptions = Object.assign({}, workerOptions, { useWebWorkers: false, workerURI: UNDEFINED_VALUE, createWorker: UNDEFINED_VALUE });
3995
4005
  resolve(new CodecWorker({}, stream, inlineWorkerOptions, onInlineTaskFinished));
3996
4006
  armStarvationTimeout();
3997
4007
  }
@@ -4171,6 +4181,8 @@
4171
4181
  const PROPERTY_NAME_EXTRA_FIELD = "extraField";
4172
4182
  const PROPERTY_NAME_EXTRA_FIELD_INFOZIP = "extraFieldInfoZip";
4173
4183
  const PROPERTY_NAME_EXTRA_FIELD_UNIX = "extraFieldUnix";
4184
+ const PROPERTY_NAME_EXTRA_FIELD_UNIX_TYPE1 = "extraFieldUnixType1";
4185
+ const PROPERTY_NAME_EXTRA_FIELD_PKWARE_UNIX = "extraFieldPkwareUnix";
4174
4186
  const PROPERTY_NAME_UID = "uid";
4175
4187
  const PROPERTY_NAME_GID = "gid";
4176
4188
  const PROPERTY_NAME_UNIX_MODE = "unixMode";
@@ -4187,6 +4199,7 @@
4187
4199
  const PROPERTY_NAME_EXTRA_FIELD_AES = "extraFieldAES";
4188
4200
  const PROPERTY_NAME_EXTRA_FIELD_NTFS = "extraFieldNTFS";
4189
4201
  const PROPERTY_NAME_EXTRA_FIELD_EXTENDED_TIMESTAMP = "extraFieldExtendedTimestamp";
4202
+ const PROPERTY_NAME_EXTRA_FIELD_USDZ = "extraFieldUSDZ";
4190
4203
 
4191
4204
  const PROPERTY_NAMES = [
4192
4205
  PROPERTY_NAME_FILENAME,
@@ -4198,6 +4211,7 @@
4198
4211
  PROPERTY_NAME_COMMENT,
4199
4212
  PROPERTY_NAME_RAW_COMMENT,
4200
4213
  PROPERTY_NAME_LAST_ACCESS_DATE,
4214
+ PROPERTY_NAME_RAW_LAST_ACCESS_DATE,
4201
4215
  PROPERTY_NAME_CREATION_DATE,
4202
4216
  PROPERTY_NAME_RAW_CREATION_DATE,
4203
4217
  PROPERTY_NAME_OFFSET,
@@ -4220,6 +4234,8 @@
4220
4234
  PROPERTY_NAME_EXTRA_FIELD,
4221
4235
  PROPERTY_NAME_EXTRA_FIELD_UNIX,
4222
4236
  PROPERTY_NAME_EXTRA_FIELD_INFOZIP,
4237
+ PROPERTY_NAME_EXTRA_FIELD_UNIX_TYPE1,
4238
+ PROPERTY_NAME_EXTRA_FIELD_PKWARE_UNIX,
4223
4239
  PROPERTY_NAME_UID,
4224
4240
  PROPERTY_NAME_GID,
4225
4241
  PROPERTY_NAME_UNIX_MODE,
@@ -4235,7 +4251,8 @@
4235
4251
  PROPERTY_NAME_EXTRA_FIELD_UNICODE_COMMENT,
4236
4252
  PROPERTY_NAME_EXTRA_FIELD_AES,
4237
4253
  PROPERTY_NAME_EXTRA_FIELD_NTFS,
4238
- PROPERTY_NAME_EXTRA_FIELD_EXTENDED_TIMESTAMP
4254
+ PROPERTY_NAME_EXTRA_FIELD_EXTENDED_TIMESTAMP,
4255
+ PROPERTY_NAME_EXTRA_FIELD_USDZ
4239
4256
  ];
4240
4257
 
4241
4258
  class Entry {
@@ -4309,6 +4326,7 @@
4309
4326
  const OPTION_OFFSET = "offset";
4310
4327
  const OPTION_USDZ = "usdz";
4311
4328
  const OPTION_UNIX_EXTRA_FIELD_TYPE = "unixExtraFieldType";
4329
+ const OPTION_LOCAL_EXTRA_FIELD = "localExtraField";
4312
4330
  const OPTION_STRICTNESS = "strictness";
4313
4331
  const OPTION_MAX_APPENDED_DATA_SIZE = "maxAppendedDataSize";
4314
4332
  const STRICTNESS_STRICT = "strict";
@@ -4361,7 +4379,7 @@
4361
4379
  const PROPERTY_NAME_UTF8_SUFFIX = "UTF8";
4362
4380
  const CHARSET_CP437 = "cp437";
4363
4381
  const BITFLAG_AMBIGUITY_MASK = BITFLAG_ENCRYPTED | BITFLAG_DATA_DESCRIPTOR | BITFLAG_LANG_ENCODING_FLAG;
4364
- const VENDOR_VERSION_AE_1 = 1;
4382
+ const VENDOR_VERSION_AE_1$1 = 1;
4365
4383
  const ZIP64_PROPERTIES = [
4366
4384
  [PROPERTY_NAME_UNCOMPRESSED_SIZE, MAX_32_BITS],
4367
4385
  [PROPERTY_NAME_COMPRESSED_SIZE, MAX_32_BITS],
@@ -4714,7 +4732,7 @@
4714
4732
  config,
4715
4733
  bitFlag,
4716
4734
  rawBitFlag,
4717
- signature,
4735
+ crc32,
4718
4736
  rawLastModDate,
4719
4737
  uncompressedSize,
4720
4738
  compressedSize
@@ -4805,7 +4823,7 @@
4805
4823
  const checkCrc32 = (checkCrc32Option === UNDEFINED_VALUE ?
4806
4824
  getOptionValue$1(zipEntry, options, OPTION_CHECK_SIGNATURE) :
4807
4825
  checkCrc32Option) && !passThrough &&
4808
- (!encrypted || zipCrypto || (extraFieldAES && extraFieldAES.vendorVersion == VENDOR_VERSION_AE_1));
4826
+ (!encrypted || zipCrypto || (extraFieldAES && extraFieldAES.vendorVersion == VENDOR_VERSION_AE_1$1));
4809
4827
  const workerOptions = {
4810
4828
  options: {
4811
4829
  codecType: CODEC_INFLATE,
@@ -4815,9 +4833,9 @@
4815
4833
  encryptionStrength: extraFieldAES && extraFieldAES.strength,
4816
4834
  checkCrc32,
4817
4835
  checkAuthenticationCode: getOptionValue$1(zipEntry, options, OPTION_CHECK_AUTHENTICATION_CODE),
4818
- passwordVerification: zipCrypto && (dataDescriptor ? ((rawLastModDate >>> 8) & MAX_8_BITS) : ((signature >>> 24) & MAX_8_BITS)),
4836
+ passwordVerification: zipCrypto && (dataDescriptor ? ((rawLastModDate >>> 8) & MAX_8_BITS) : ((crc32 >>> 24) & MAX_8_BITS)),
4819
4837
  outputSize: passThrough ? compressedSize : uncompressedSize,
4820
- signature,
4838
+ crc32,
4821
4839
  compressed: compressionMethod != 0 && !passThrough,
4822
4840
  encrypted,
4823
4841
  useWebWorkers: getOptionValue$1(zipEntry, options, OPTION_USE_WEB_WORKERS),
@@ -4839,7 +4857,7 @@
4839
4857
  fileEntry,
4840
4858
  index,
4841
4859
  offset: localHeaderOffset,
4842
- signature,
4860
+ crc32,
4843
4861
  compressedSize,
4844
4862
  uncompressedSize,
4845
4863
  dataOffset,
@@ -4956,6 +4974,16 @@
4956
4974
  } else {
4957
4975
  directory.compressionMethod = compressionMethod;
4958
4976
  }
4977
+ const extraFieldPkwareUnix = extraField.get(EXTRAFIELD_TYPE_PKWARE_UNIX);
4978
+ if (extraFieldPkwareUnix) {
4979
+ readExtraFieldUnixDates(extraFieldPkwareUnix, directory);
4980
+ directory.extraFieldPkwareUnix = extraFieldPkwareUnix;
4981
+ }
4982
+ const extraFieldUnixType1 = extraField.get(EXTRAFIELD_TYPE_UNIX_TYPE1);
4983
+ if (extraFieldUnixType1) {
4984
+ readExtraFieldUnixDates(extraFieldUnixType1, directory);
4985
+ directory.extraFieldUnixType1 = extraFieldUnixType1;
4986
+ }
4959
4987
  const extraFieldNTFS = extraField.get(EXTRAFIELD_TYPE_NTFS);
4960
4988
  if (extraFieldNTFS) {
4961
4989
  readExtraFieldNTFS(extraFieldNTFS, directory);
@@ -5005,15 +5033,15 @@
5005
5033
  return;
5006
5034
  }
5007
5035
  const extraFieldView = getDataView(extraFieldUnicode.data);
5008
- const crc32 = new Crc32();
5009
- crc32.append(fileEntry[rawPropertyName]);
5010
- const dataViewSignature = getDataView(new Uint8Array(4));
5011
- dataViewSignature.setUint32(0, crc32.get(), true);
5012
- const signature = getUint32(extraFieldView, 1);
5036
+ const computedCrc32 = new Crc32();
5037
+ computedCrc32.append(fileEntry[rawPropertyName]);
5038
+ const computedCrc32View = getDataView(new Uint8Array(4));
5039
+ computedCrc32View.setUint32(0, computedCrc32.get(), true);
5040
+ const nameCrc32 = getUint32(extraFieldView, 1);
5013
5041
  Object.assign(extraFieldUnicode, {
5014
5042
  version: getUint8(extraFieldView, 0),
5015
5043
  [propertyName]: decodeText(extraFieldUnicode.data.subarray(5)),
5016
- valid: !fileEntry.bitFlag.languageEncodingFlag && signature == getUint32(dataViewSignature, 0)
5044
+ valid: !fileEntry.bitFlag.languageEncodingFlag && nameCrc32 == getUint32(computedCrc32View, 0)
5017
5045
  });
5018
5046
  if (extraFieldUnicode.valid) {
5019
5047
  directory[propertyName] = extraFieldUnicode[propertyName];
@@ -5032,7 +5060,7 @@
5032
5060
  compressionMethod: getUint16(extraFieldView, 5)
5033
5061
  });
5034
5062
  directory.compressionMethod = extraFieldAES.compressionMethod;
5035
- if (extraFieldAES.vendorVersion != VENDOR_VERSION_AE_1) {
5063
+ if (extraFieldAES.vendorVersion != VENDOR_VERSION_AE_1$1) {
5036
5064
  directory.crc32 = UNDEFINED_VALUE;
5037
5065
  }
5038
5066
  }
@@ -5072,6 +5100,22 @@
5072
5100
  }
5073
5101
  }
5074
5102
 
5103
+ function readExtraFieldUnixDates(extraField, directory) {
5104
+ if (extraField.data.length < 8) {
5105
+ return;
5106
+ }
5107
+ const extraFieldView = getDataView(extraField.data);
5108
+ const lastAccessDate = new Date(getUint32(extraFieldView, 0) * 1000);
5109
+ const lastModDate = new Date(getUint32(extraFieldView, 4) * 1000);
5110
+ const extraFieldData = { lastAccessDate, lastModDate };
5111
+ if (extraField.data.length >= 12) {
5112
+ extraFieldData.uid = getUint16(extraFieldView, 8);
5113
+ extraFieldData.gid = getUint16(extraFieldView, 10);
5114
+ }
5115
+ Object.assign(extraField, extraFieldData);
5116
+ Object.assign(directory, extraFieldData);
5117
+ }
5118
+
5075
5119
  function readExtraFieldUnix(extraField, directory, isInfoZip) {
5076
5120
  try {
5077
5121
  const view = getDataView(extraField.data);
@@ -5150,7 +5194,7 @@
5150
5194
  fileEntry,
5151
5195
  index,
5152
5196
  offset,
5153
- signature,
5197
+ crc32,
5154
5198
  compressedSize,
5155
5199
  uncompressedSize,
5156
5200
  dataOffset,
@@ -5171,7 +5215,7 @@
5171
5215
  const dataDescriptorSignature = dataDescriptorArray.length == dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH &&
5172
5216
  getUint32(getDataView(dataDescriptorArray), 0) == DATA_DESCRIPTOR_RECORD_SIGNATURE;
5173
5217
  if (dataDescriptorSignature) {
5174
- const readSignature = getUint32(getDataView(dataDescriptorArray), 4);
5218
+ const readCrc32 = getUint32(getDataView(dataDescriptorArray), 4);
5175
5219
  let readCompressedSize;
5176
5220
  let readUncompressedSize;
5177
5221
  if (extraFieldZip64) {
@@ -5181,8 +5225,8 @@
5181
5225
  readCompressedSize = getUint32(getDataView(dataDescriptorArray), 8);
5182
5226
  readUncompressedSize = getUint32(getDataView(dataDescriptorArray), 12);
5183
5227
  }
5184
- const matchSignature = (fileEntry.encrypted && !fileEntry.zipCrypto) || readSignature == signature;
5185
- if (matchSignature &&
5228
+ const matchCrc32 = (fileEntry.encrypted && !fileEntry.zipCrypto) || readCrc32 == crc32;
5229
+ if (matchCrc32 &&
5186
5230
  readCompressedSize == compressedSize &&
5187
5231
  readUncompressedSize == uncompressedSize) {
5188
5232
  dataDescriptorLength += DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH;
@@ -5351,11 +5395,11 @@
5351
5395
  throwAmbiguousArchive("mismatched local file header (compression method)");
5352
5396
  }
5353
5397
  if (!localDirectory.bitFlag.dataDescriptor &&
5354
- (localDirectory.signature || localDirectory.compressedSize || localDirectory.uncompressedSize) &&
5355
- (localDirectory.signature != zipEntry.signature ||
5398
+ (localDirectory.crc32 || localDirectory.compressedSize || localDirectory.uncompressedSize) &&
5399
+ (localDirectory.crc32 != zipEntry.crc32 ||
5356
5400
  localDirectory.compressedSize != zipEntry.compressedSize ||
5357
5401
  localDirectory.uncompressedSize != zipEntry.uncompressedSize)) {
5358
- throwAmbiguousArchive("mismatched local file header (signature or sizes)");
5402
+ throwAmbiguousArchive("mismatched local file header (crc32 or sizes)");
5359
5403
  }
5360
5404
  }
5361
5405
 
@@ -5474,7 +5518,9 @@
5474
5518
  const ERR_INVALID_MSDOS_DATA = "Invalid msdosAttributes (must be an object with boolean flags)";
5475
5519
 
5476
5520
  const EXTRAFIELD_DATA_AES = new Uint8Array([0x07, 0x00, 0x02, 0x00, 0x41, 0x45, 0x03, 0x00, 0x00]);
5477
- const INFOZIP_EXTRA_FIELD_TYPE = "infozip";
5521
+ const EXTRAFIELD_OFFSET_AES_VENDOR_VERSION = 4;
5522
+ const VENDOR_VERSION_AE_1 = 1;
5523
+ const INFOZIP_EXTRA_FIELD_TYPE$1 = "infozip";
5478
5524
  const UNIX_EXTRA_FIELD_TYPE = "unix";
5479
5525
 
5480
5526
  let workers = 0;
@@ -5568,9 +5614,9 @@
5568
5614
  zip64UncompressedSize,
5569
5615
  extraFieldLength
5570
5616
  });
5571
- const { signature } = entry;
5572
- if (signature !== UNDEFINED_VALUE) {
5573
- setUint32(headerView, HEADER_OFFSET_SIGNATURE, signature);
5617
+ const { crc32 } = entry;
5618
+ if (crc32 !== UNDEFINED_VALUE) {
5619
+ setUint32(headerView, HEADER_OFFSET_SIGNATURE, crc32);
5574
5620
  }
5575
5621
  Object.assign(entry, {
5576
5622
  zip64UncompressedSize,
@@ -5693,6 +5739,7 @@
5693
5739
  internalFileAttribute: metadataInfo.resolvedOptions.internalFileAttributes,
5694
5740
  externalFileAttribute: attributesInfo.resolvedOptions.externalFileAttributes,
5695
5741
  signature: options[PROPERTY_NAME_SIGNATURE],
5742
+ crc32: options.crc32 === UNDEFINED_VALUE ? options[PROPERTY_NAME_SIGNATURE] : options.crc32,
5696
5743
  offset: zipWriter.offset - diskOffset,
5697
5744
  diskNumberStart: diskNumber
5698
5745
  });
@@ -5729,7 +5776,7 @@
5729
5776
  if (unixMode !== UNDEFINED_VALUE && (unixMode < 0 || unixMode > MAX_16_BITS)) {
5730
5777
  throw new Error(ERR_INVALID_UNIX_MODE);
5731
5778
  }
5732
- if (unixExtraFieldType !== UNDEFINED_VALUE && unixExtraFieldType !== INFOZIP_EXTRA_FIELD_TYPE && unixExtraFieldType !== UNIX_EXTRA_FIELD_TYPE) {
5779
+ if (unixExtraFieldType !== UNDEFINED_VALUE && unixExtraFieldType !== INFOZIP_EXTRA_FIELD_TYPE$1 && unixExtraFieldType !== UNIX_EXTRA_FIELD_TYPE) {
5733
5780
  throw new Error(ERR_INVALID_UNIX_EXTRA_FIELD_TYPE);
5734
5781
  }
5735
5782
  if (unixExtraFieldType === UNIX_EXTRA_FIELD_TYPE &&
@@ -5737,7 +5784,7 @@
5737
5784
  throw new Error(ERR_INVALID_UNIX_ID_SIZE);
5738
5785
  }
5739
5786
  if (unixExtraFieldType === UNDEFINED_VALUE && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
5740
- unixExtraFieldType = INFOZIP_EXTRA_FIELD_TYPE;
5787
+ unixExtraFieldType = INFOZIP_EXTRA_FIELD_TYPE$1;
5741
5788
  }
5742
5789
  let msdosAttributesRaw = getOptionValue(zipWriter, options, PROPERTY_NAME_MSDOS_ATTRIBUTES_RAW);
5743
5790
  let msdosAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_MSDOS_ATTRIBUTES);
@@ -5909,27 +5956,8 @@
5909
5956
  if (!zipCrypto && (password !== UNDEFINED_VALUE || rawPassword !== UNDEFINED_VALUE) && !(encryptionStrength >= 1 && encryptionStrength <= 3)) {
5910
5957
  throw new Error(ERR_INVALID_ENCRYPTION_STRENGTH);
5911
5958
  }
5912
- let rawExtraField = EMPTY_UINT8_ARRAY;
5913
- const extraField = options[PROPERTY_NAME_EXTRA_FIELD];
5914
- if (extraField) {
5915
- let extraFieldSize = 0;
5916
- let offset = 0;
5917
- extraField.forEach(data => extraFieldSize += 4 + getLength(data));
5918
- rawExtraField = new Uint8Array(extraFieldSize);
5919
- const rawExtraFieldView = getDataView(rawExtraField);
5920
- extraField.forEach((data, type) => {
5921
- if (type > MAX_16_BITS) {
5922
- throw new Error(ERR_INVALID_EXTRAFIELD_TYPE);
5923
- }
5924
- if (getLength(data) > MAX_16_BITS) {
5925
- throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
5926
- }
5927
- setUint16(rawExtraFieldView, offset, type);
5928
- setUint16(rawExtraFieldView, offset + 2, getLength(data));
5929
- arraySet(rawExtraField, data, offset + 4);
5930
- offset += 4 + getLength(data);
5931
- });
5932
- }
5959
+ const rawExtraField = serializeExtraField(options[PROPERTY_NAME_EXTRA_FIELD]);
5960
+ const rawLocalExtraField = serializeExtraField(options[OPTION_LOCAL_EXTRA_FIELD]);
5933
5961
  return {
5934
5962
  comment,
5935
5963
  resolvedOptions: {
@@ -5963,11 +5991,36 @@
5963
5991
  useCompressionStream,
5964
5992
  dataDescriptor,
5965
5993
  zip64,
5966
- rawExtraField
5994
+ rawExtraField,
5995
+ rawLocalExtraField
5967
5996
  }
5968
5997
  };
5969
5998
  }
5970
5999
 
6000
+ function serializeExtraField(extraField) {
6001
+ if (!extraField) {
6002
+ return EMPTY_UINT8_ARRAY;
6003
+ }
6004
+ let extraFieldSize = 0;
6005
+ let offset = 0;
6006
+ extraField.forEach(data => extraFieldSize += 4 + getLength(data));
6007
+ const rawExtraField = new Uint8Array(extraFieldSize);
6008
+ const rawExtraFieldView = getDataView(rawExtraField);
6009
+ extraField.forEach((data, type) => {
6010
+ if (type > MAX_16_BITS) {
6011
+ throw new Error(ERR_INVALID_EXTRAFIELD_TYPE);
6012
+ }
6013
+ if (getLength(data) > MAX_16_BITS) {
6014
+ throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
6015
+ }
6016
+ setUint16(rawExtraFieldView, offset, type);
6017
+ setUint16(rawExtraFieldView, offset + 2, getLength(data));
6018
+ arraySet(rawExtraField, data, offset + 4);
6019
+ offset += 4 + getLength(data);
6020
+ });
6021
+ return rawExtraField;
6022
+ }
6023
+
5971
6024
  async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, options) {
5972
6025
  const { passThrough, zipCrypto, password, rawPassword, encryptionStrength } = metadata;
5973
6026
  let { dataDescriptor, zip64, level, compressionMethod } = metadata;
@@ -6292,12 +6345,9 @@
6292
6345
  msdosAttributes
6293
6346
  };
6294
6347
  let {
6295
- crc32: signature,
6348
+ crc32,
6296
6349
  uncompressedSize
6297
6350
  } = options;
6298
- if (signature === UNDEFINED_VALUE) {
6299
- ({ signature } = options);
6300
- }
6301
6351
  let compressedSize = 0;
6302
6352
  if (!passThrough) {
6303
6353
  uncompressedSize = 0;
@@ -6335,7 +6385,7 @@
6335
6385
  if (!passThrough) {
6336
6386
  uncompressedSize = result.inputSize;
6337
6387
  if (!encrypted || zipCrypto) {
6338
- signature = result.signature;
6388
+ crc32 = result.crc32;
6339
6389
  }
6340
6390
  }
6341
6391
  if ((!zip64CompressedSize && compressedSize >= MAX_32_BITS) ||
@@ -6351,7 +6401,7 @@
6351
6401
 
6352
6402
  }
6353
6403
  setEntryInfo({
6354
- signature,
6404
+ crc32,
6355
6405
  compressedSize,
6356
6406
  uncompressedSize,
6357
6407
  headerInfo,
@@ -6374,8 +6424,8 @@
6374
6424
  version,
6375
6425
  headerArray,
6376
6426
  headerView,
6377
- signature,
6378
- crc32: encrypted && !zipCrypto ? UNDEFINED_VALUE : signature,
6427
+ signature: crc32,
6428
+ crc32: encrypted && !zipCrypto && !passThrough ? UNDEFINED_VALUE : crc32,
6379
6429
  extraFieldExtendedTimestampFlag,
6380
6430
  zip64UncompressedSize,
6381
6431
  zip64CompressedSize
@@ -6396,6 +6446,7 @@
6396
6446
  dataDescriptor,
6397
6447
  directory,
6398
6448
  rawExtraField,
6449
+ rawLocalExtraField,
6399
6450
  encryptionStrength,
6400
6451
  extendedTimestamp,
6401
6452
  ntfsTimestamp,
@@ -6403,7 +6454,8 @@
6403
6454
  encrypted,
6404
6455
  zip64UncompressedSize,
6405
6456
  zip64CompressedSize,
6406
- uncompressedSize
6457
+ uncompressedSize,
6458
+ crc32
6407
6459
  } = options;
6408
6460
  let { version, compressionMethod } = options;
6409
6461
  const compressed = !directory && (compressionMethod === UNDEFINED_VALUE
@@ -6491,7 +6543,7 @@
6491
6543
  let rawExtraFieldUnix;
6492
6544
  try {
6493
6545
  const { uid, gid, unixExtraFieldType } = options;
6494
- if (unixExtraFieldType == INFOZIP_EXTRA_FIELD_TYPE && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
6546
+ if (unixExtraFieldType == INFOZIP_EXTRA_FIELD_TYPE$1 && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
6495
6547
  const uidBytes = packUnixId(uid);
6496
6548
  const gidBytes = packUnixId(gid);
6497
6549
  const payloadLength = 3 + uidBytes.length + gidBytes.length;
@@ -6529,11 +6581,14 @@
6529
6581
  }
6530
6582
  if (encrypted && !zipCrypto) {
6531
6583
  version = version > VERSION_AES ? version : VERSION_AES;
6584
+ if (passThrough && crc32 !== UNDEFINED_VALUE) {
6585
+ rawExtraFieldAES[EXTRAFIELD_OFFSET_AES_VENDOR_VERSION] = VENDOR_VERSION_AE_1;
6586
+ }
6532
6587
  rawExtraFieldAES[9] = compressionMethod;
6533
6588
  compressionMethod = COMPRESSION_METHOD_AES;
6534
6589
  }
6535
6590
  const localExtraFieldZip64Length = writeLocalExtraFieldZip64 ? getLength(rawLocalExtraFieldZip64) : 0;
6536
- const extraFieldLength = localExtraFieldZip64Length + getLength(rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField);
6591
+ const extraFieldLength = localExtraFieldZip64Length + getLength(rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField, rawLocalExtraField);
6537
6592
  if (extraFieldLength > MAX_16_BITS) {
6538
6593
  throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
6539
6594
  }
@@ -6567,6 +6622,7 @@
6567
6622
  localHeader.bytes(rawExtraFieldNTFS);
6568
6623
  localHeader.bytes(rawExtraFieldUnix);
6569
6624
  localHeader.bytes(rawExtraField);
6625
+ localHeader.bytes(rawLocalExtraField);
6570
6626
  if (dataDescriptor) {
6571
6627
  if (!zip64CompressedSize) {
6572
6628
  setUint32(localHeaderView, HEADER_OFFSET_COMPRESSED_SIZE + LOCAL_HEADER_COMMON_OFFSET, 0);
@@ -6685,7 +6741,7 @@
6685
6741
  }
6686
6742
 
6687
6743
  function setEntryInfo({
6688
- signature,
6744
+ crc32,
6689
6745
  compressedSize,
6690
6746
  uncompressedSize,
6691
6747
  headerInfo,
@@ -6693,6 +6749,7 @@
6693
6749
  }, {
6694
6750
  zip64,
6695
6751
  zipCrypto,
6752
+ passThrough,
6696
6753
  dataDescriptor
6697
6754
  }) {
6698
6755
  const {
@@ -6703,10 +6760,10 @@
6703
6760
  dataDescriptorView,
6704
6761
  dataDescriptorOffset
6705
6762
  } = dataDescriptorInfo;
6706
- if ((!encrypted || zipCrypto) && signature !== UNDEFINED_VALUE) {
6707
- setUint32(headerView, HEADER_OFFSET_SIGNATURE, signature);
6763
+ if ((!encrypted || zipCrypto || passThrough) && crc32 !== UNDEFINED_VALUE) {
6764
+ setUint32(headerView, HEADER_OFFSET_SIGNATURE, crc32);
6708
6765
  if (dataDescriptor) {
6709
- setUint32(dataDescriptorView, dataDescriptorOffset, signature);
6766
+ setUint32(dataDescriptorView, dataDescriptorOffset, crc32);
6710
6767
  }
6711
6768
  }
6712
6769
  if (zip64) {
@@ -6729,15 +6786,15 @@
6729
6786
  encrypted,
6730
6787
  zip64,
6731
6788
  localExtraFieldZip64Length,
6732
- signature,
6789
+ crc32,
6733
6790
  compressedSize,
6734
6791
  uncompressedSize,
6735
6792
  zip64UncompressedSize,
6736
6793
  zip64CompressedSize
6737
- }, localHeaderView, { dataDescriptor }) {
6794
+ }, localHeaderView, { dataDescriptor, passThrough }) {
6738
6795
  if (!dataDescriptor) {
6739
- if (!encrypted) {
6740
- setUint32(localHeaderView, HEADER_OFFSET_SIGNATURE + LOCAL_HEADER_COMMON_OFFSET, signature);
6796
+ if (!encrypted || (passThrough && crc32 !== UNDEFINED_VALUE)) {
6797
+ setUint32(localHeaderView, HEADER_OFFSET_SIGNATURE + LOCAL_HEADER_COMMON_OFFSET, crc32);
6741
6798
  }
6742
6799
  if (!zip64CompressedSize) {
6743
6800
  setUint32(localHeaderView, HEADER_OFFSET_COMPRESSED_SIZE + LOCAL_HEADER_COMMON_OFFSET, compressedSize);
@@ -7202,6 +7259,20 @@
7202
7259
 
7203
7260
  const ERR_ENTRY_EXISTS = "Entry filename already exists";
7204
7261
  const ERR_READABLE_CONSUMED = "Readable stream already consumed";
7262
+ const INFOZIP_EXTRA_FIELD_TYPE = "infozip";
7263
+ const INTERPRETED_EXTRA_FIELD_TYPES = new Set([
7264
+ EXTRAFIELD_TYPE_ZIP64,
7265
+ EXTRAFIELD_TYPE_AES,
7266
+ EXTRAFIELD_TYPE_NTFS,
7267
+ EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP,
7268
+ EXTRAFIELD_TYPE_UNICODE_PATH,
7269
+ EXTRAFIELD_TYPE_UNICODE_COMMENT,
7270
+ EXTRAFIELD_TYPE_USDZ,
7271
+ EXTRAFIELD_TYPE_INFOZIP,
7272
+ EXTRAFIELD_TYPE_UNIX,
7273
+ EXTRAFIELD_TYPE_UNIX_TYPE1,
7274
+ EXTRAFIELD_TYPE_PKWARE_UNIX
7275
+ ]);
7205
7276
 
7206
7277
  class ZipEntry {
7207
7278
 
@@ -7939,6 +8010,20 @@
7939
8010
  }
7940
8011
  }
7941
8012
 
8013
+ function getUserExtraField(extraField) {
8014
+ if (extraField) {
8015
+ const userExtraField = new Map();
8016
+ extraField.forEach((field, type) => {
8017
+ if (!INTERPRETED_EXTRA_FIELD_TYPES.has(type)) {
8018
+ userExtraField.set(type, field.data);
8019
+ }
8020
+ });
8021
+ if (userExtraField.size) {
8022
+ return userExtraField;
8023
+ }
8024
+ }
8025
+ }
8026
+
7942
8027
  async function exportZip(zipWriter, entry, totalSize, options, readers) {
7943
8028
  const selectedEntry = entry;
7944
8029
  const entryOffsets = new Map();
@@ -7976,9 +8061,13 @@
7976
8061
  uncompressedSize,
7977
8062
  encrypted,
7978
8063
  zipCrypto,
7979
- signature,
8064
+ crc32,
7980
8065
  compressionMethod,
7981
- extraFieldAES
8066
+ extraFieldAES,
8067
+ internalFileAttributes,
8068
+ extraField,
8069
+ uid,
8070
+ gid
7982
8071
  } = child.data;
7983
8072
  zipEntryOptions = {
7984
8073
  externalFileAttributes,
@@ -7986,8 +8075,20 @@
7986
8075
  comment,
7987
8076
  lastModDate,
7988
8077
  creationDate,
7989
- lastAccessDate
8078
+ lastAccessDate,
8079
+ internalFileAttributes
7990
8080
  };
8081
+ const userExtraField = getUserExtraField(extraField);
8082
+ if (userExtraField) {
8083
+ zipEntryOptions.extraField = userExtraField;
8084
+ }
8085
+ if (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE) {
8086
+ Object.assign(zipEntryOptions, {
8087
+ uid,
8088
+ gid,
8089
+ unixExtraFieldType: options.unixExtraFieldType || INFOZIP_EXTRA_FIELD_TYPE
8090
+ });
8091
+ }
7991
8092
  if (child.passThrough) {
7992
8093
  let level, encryptionStrength;
7993
8094
  if (compressionMethod === 0) {
@@ -8000,7 +8101,7 @@
8000
8101
  passThrough: true,
8001
8102
  encrypted,
8002
8103
  zipCrypto,
8003
- signature,
8104
+ crc32,
8004
8105
  uncompressedSize,
8005
8106
  level,
8006
8107
  encryptionStrength,