@zip.js/zip.js 2.8.44 → 2.8.45

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 (51) hide show
  1. package/deno.json +21 -1
  2. package/dist/zip-core-external.js +138 -123
  3. package/dist/zip-core-external.min.js +1 -1
  4. package/dist/zip-core.js +137 -96
  5. package/dist/zip-core.min.js +1 -1
  6. package/dist/zip-fs-core-external.js +190 -131
  7. package/dist/zip-fs-core-external.min.js +1 -1
  8. package/dist/zip-fs-core.js +189 -104
  9. package/dist/zip-fs-core.min.js +1 -1
  10. package/dist/zip-fs-external.js +211 -1725
  11. package/dist/zip-fs-external.min.js +1 -1
  12. package/dist/zip-fs-native.js +212 -1700
  13. package/dist/zip-fs-native.min.js +1 -1
  14. package/dist/zip-fs.js +211 -1699
  15. package/dist/zip-fs.min.js +1 -1
  16. package/dist/zip-legacy.js +139 -98
  17. package/dist/zip-legacy.min.js +1 -1
  18. package/dist/zip-native.js +139 -98
  19. package/dist/zip-native.min.js +1 -1
  20. package/dist/zip-web-worker-native.js +1 -1
  21. package/dist/zip-web-worker.js +1 -1
  22. package/dist/zip.js +138 -97
  23. package/dist/zip.min.js +1 -1
  24. package/eslint.config.mjs +31 -2
  25. package/index-native.cjs +212 -1700
  26. package/index-native.min.js +1 -1
  27. package/index.cjs +211 -1699
  28. package/index.d.cts +49 -1
  29. package/index.d.ts +49 -1
  30. package/index.min.js +1 -1
  31. package/lib/core/codec-worker.js +2 -2
  32. package/lib/core/constants.js +4 -0
  33. package/lib/core/options.js +2 -0
  34. package/lib/core/streams/aes-crypto-stream.js +15 -18
  35. package/lib/core/streams/codec-stream.js +2 -2
  36. package/lib/core/streams/zip-entry-stream.js +5 -10
  37. package/lib/core/util/mime-type-data.js +3 -0
  38. package/lib/core/util/mime-type.js +23 -1596
  39. package/lib/core/web-worker-base.js +2 -2
  40. package/lib/core/web-worker-inline-native.js +1 -1
  41. package/lib/core/web-worker-inline-wasm.js +1 -1
  42. package/lib/core/zip-entry.js +8 -1
  43. package/lib/core/zip-fs.js +62 -5
  44. package/lib/core/zip-reader.js +45 -17
  45. package/lib/core/zip-writer.js +58 -44
  46. package/lib/zip-core-external.js +2 -0
  47. package/lib/zip-fs-core-external.js +2 -0
  48. package/lib/zip-fs-external.js +2 -0
  49. package/lib/zip-mime-types.js +2 -0
  50. package/package.json +9 -3
  51. package/worker-message-property-names.js +1 -1
@@ -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);
@@ -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
  });
@@ -2987,7 +2981,7 @@
2987
2981
 
2988
2982
  constructor(options, { chunkSize, DecompressionStreamZlib, 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) {
@@ -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
  }
@@ -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
  }
@@ -3549,12 +3543,12 @@
3549
3543
  .pipeThrough(new ChunkStream(getChunkSize(config)))
3550
3544
  .pipeTo(writable, { preventClose: true, preventAbort: true });
3551
3545
  const {
3552
- signature,
3546
+ crc32,
3553
3547
  inputSize,
3554
3548
  outputSize
3555
3549
  } = codecStream;
3556
3550
  return {
3557
- signature,
3551
+ crc32,
3558
3552
  inputSize,
3559
3553
  outputSize
3560
3554
  };
@@ -4171,6 +4165,8 @@
4171
4165
  const PROPERTY_NAME_EXTRA_FIELD = "extraField";
4172
4166
  const PROPERTY_NAME_EXTRA_FIELD_INFOZIP = "extraFieldInfoZip";
4173
4167
  const PROPERTY_NAME_EXTRA_FIELD_UNIX = "extraFieldUnix";
4168
+ const PROPERTY_NAME_EXTRA_FIELD_UNIX_TYPE1 = "extraFieldUnixType1";
4169
+ const PROPERTY_NAME_EXTRA_FIELD_PKWARE_UNIX = "extraFieldPkwareUnix";
4174
4170
  const PROPERTY_NAME_UID = "uid";
4175
4171
  const PROPERTY_NAME_GID = "gid";
4176
4172
  const PROPERTY_NAME_UNIX_MODE = "unixMode";
@@ -4187,6 +4183,7 @@
4187
4183
  const PROPERTY_NAME_EXTRA_FIELD_AES = "extraFieldAES";
4188
4184
  const PROPERTY_NAME_EXTRA_FIELD_NTFS = "extraFieldNTFS";
4189
4185
  const PROPERTY_NAME_EXTRA_FIELD_EXTENDED_TIMESTAMP = "extraFieldExtendedTimestamp";
4186
+ const PROPERTY_NAME_EXTRA_FIELD_USDZ = "extraFieldUSDZ";
4190
4187
 
4191
4188
  const PROPERTY_NAMES = [
4192
4189
  PROPERTY_NAME_FILENAME,
@@ -4198,6 +4195,7 @@
4198
4195
  PROPERTY_NAME_COMMENT,
4199
4196
  PROPERTY_NAME_RAW_COMMENT,
4200
4197
  PROPERTY_NAME_LAST_ACCESS_DATE,
4198
+ PROPERTY_NAME_RAW_LAST_ACCESS_DATE,
4201
4199
  PROPERTY_NAME_CREATION_DATE,
4202
4200
  PROPERTY_NAME_RAW_CREATION_DATE,
4203
4201
  PROPERTY_NAME_OFFSET,
@@ -4220,6 +4218,8 @@
4220
4218
  PROPERTY_NAME_EXTRA_FIELD,
4221
4219
  PROPERTY_NAME_EXTRA_FIELD_UNIX,
4222
4220
  PROPERTY_NAME_EXTRA_FIELD_INFOZIP,
4221
+ PROPERTY_NAME_EXTRA_FIELD_UNIX_TYPE1,
4222
+ PROPERTY_NAME_EXTRA_FIELD_PKWARE_UNIX,
4223
4223
  PROPERTY_NAME_UID,
4224
4224
  PROPERTY_NAME_GID,
4225
4225
  PROPERTY_NAME_UNIX_MODE,
@@ -4235,7 +4235,8 @@
4235
4235
  PROPERTY_NAME_EXTRA_FIELD_UNICODE_COMMENT,
4236
4236
  PROPERTY_NAME_EXTRA_FIELD_AES,
4237
4237
  PROPERTY_NAME_EXTRA_FIELD_NTFS,
4238
- PROPERTY_NAME_EXTRA_FIELD_EXTENDED_TIMESTAMP
4238
+ PROPERTY_NAME_EXTRA_FIELD_EXTENDED_TIMESTAMP,
4239
+ PROPERTY_NAME_EXTRA_FIELD_USDZ
4239
4240
  ];
4240
4241
 
4241
4242
  class Entry {
@@ -4309,6 +4310,7 @@
4309
4310
  const OPTION_OFFSET = "offset";
4310
4311
  const OPTION_USDZ = "usdz";
4311
4312
  const OPTION_UNIX_EXTRA_FIELD_TYPE = "unixExtraFieldType";
4313
+ const OPTION_LOCAL_EXTRA_FIELD = "localExtraField";
4312
4314
  const OPTION_STRICTNESS = "strictness";
4313
4315
  const OPTION_MAX_APPENDED_DATA_SIZE = "maxAppendedDataSize";
4314
4316
  const STRICTNESS_STRICT = "strict";
@@ -4361,7 +4363,7 @@
4361
4363
  const PROPERTY_NAME_UTF8_SUFFIX = "UTF8";
4362
4364
  const CHARSET_CP437 = "cp437";
4363
4365
  const BITFLAG_AMBIGUITY_MASK = BITFLAG_ENCRYPTED | BITFLAG_DATA_DESCRIPTOR | BITFLAG_LANG_ENCODING_FLAG;
4364
- const VENDOR_VERSION_AE_1 = 1;
4366
+ const VENDOR_VERSION_AE_1$1 = 1;
4365
4367
  const ZIP64_PROPERTIES = [
4366
4368
  [PROPERTY_NAME_UNCOMPRESSED_SIZE, MAX_32_BITS],
4367
4369
  [PROPERTY_NAME_COMPRESSED_SIZE, MAX_32_BITS],
@@ -4714,7 +4716,7 @@
4714
4716
  config,
4715
4717
  bitFlag,
4716
4718
  rawBitFlag,
4717
- signature,
4719
+ crc32,
4718
4720
  rawLastModDate,
4719
4721
  uncompressedSize,
4720
4722
  compressedSize
@@ -4805,7 +4807,7 @@
4805
4807
  const checkCrc32 = (checkCrc32Option === UNDEFINED_VALUE ?
4806
4808
  getOptionValue$1(zipEntry, options, OPTION_CHECK_SIGNATURE) :
4807
4809
  checkCrc32Option) && !passThrough &&
4808
- (!encrypted || zipCrypto || (extraFieldAES && extraFieldAES.vendorVersion == VENDOR_VERSION_AE_1));
4810
+ (!encrypted || zipCrypto || (extraFieldAES && extraFieldAES.vendorVersion == VENDOR_VERSION_AE_1$1));
4809
4811
  const workerOptions = {
4810
4812
  options: {
4811
4813
  codecType: CODEC_INFLATE,
@@ -4815,9 +4817,9 @@
4815
4817
  encryptionStrength: extraFieldAES && extraFieldAES.strength,
4816
4818
  checkCrc32,
4817
4819
  checkAuthenticationCode: getOptionValue$1(zipEntry, options, OPTION_CHECK_AUTHENTICATION_CODE),
4818
- passwordVerification: zipCrypto && (dataDescriptor ? ((rawLastModDate >>> 8) & MAX_8_BITS) : ((signature >>> 24) & MAX_8_BITS)),
4820
+ passwordVerification: zipCrypto && (dataDescriptor ? ((rawLastModDate >>> 8) & MAX_8_BITS) : ((crc32 >>> 24) & MAX_8_BITS)),
4819
4821
  outputSize: passThrough ? compressedSize : uncompressedSize,
4820
- signature,
4822
+ crc32,
4821
4823
  compressed: compressionMethod != 0 && !passThrough,
4822
4824
  encrypted,
4823
4825
  useWebWorkers: getOptionValue$1(zipEntry, options, OPTION_USE_WEB_WORKERS),
@@ -4839,7 +4841,7 @@
4839
4841
  fileEntry,
4840
4842
  index,
4841
4843
  offset: localHeaderOffset,
4842
- signature,
4844
+ crc32,
4843
4845
  compressedSize,
4844
4846
  uncompressedSize,
4845
4847
  dataOffset,
@@ -4956,6 +4958,16 @@
4956
4958
  } else {
4957
4959
  directory.compressionMethod = compressionMethod;
4958
4960
  }
4961
+ const extraFieldPkwareUnix = extraField.get(EXTRAFIELD_TYPE_PKWARE_UNIX);
4962
+ if (extraFieldPkwareUnix) {
4963
+ readExtraFieldUnixDates(extraFieldPkwareUnix, directory);
4964
+ directory.extraFieldPkwareUnix = extraFieldPkwareUnix;
4965
+ }
4966
+ const extraFieldUnixType1 = extraField.get(EXTRAFIELD_TYPE_UNIX_TYPE1);
4967
+ if (extraFieldUnixType1) {
4968
+ readExtraFieldUnixDates(extraFieldUnixType1, directory);
4969
+ directory.extraFieldUnixType1 = extraFieldUnixType1;
4970
+ }
4959
4971
  const extraFieldNTFS = extraField.get(EXTRAFIELD_TYPE_NTFS);
4960
4972
  if (extraFieldNTFS) {
4961
4973
  readExtraFieldNTFS(extraFieldNTFS, directory);
@@ -5005,15 +5017,15 @@
5005
5017
  return;
5006
5018
  }
5007
5019
  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);
5020
+ const computedCrc32 = new Crc32();
5021
+ computedCrc32.append(fileEntry[rawPropertyName]);
5022
+ const computedCrc32View = getDataView(new Uint8Array(4));
5023
+ computedCrc32View.setUint32(0, computedCrc32.get(), true);
5024
+ const nameCrc32 = getUint32(extraFieldView, 1);
5013
5025
  Object.assign(extraFieldUnicode, {
5014
5026
  version: getUint8(extraFieldView, 0),
5015
5027
  [propertyName]: decodeText(extraFieldUnicode.data.subarray(5)),
5016
- valid: !fileEntry.bitFlag.languageEncodingFlag && signature == getUint32(dataViewSignature, 0)
5028
+ valid: !fileEntry.bitFlag.languageEncodingFlag && nameCrc32 == getUint32(computedCrc32View, 0)
5017
5029
  });
5018
5030
  if (extraFieldUnicode.valid) {
5019
5031
  directory[propertyName] = extraFieldUnicode[propertyName];
@@ -5032,7 +5044,7 @@
5032
5044
  compressionMethod: getUint16(extraFieldView, 5)
5033
5045
  });
5034
5046
  directory.compressionMethod = extraFieldAES.compressionMethod;
5035
- if (extraFieldAES.vendorVersion != VENDOR_VERSION_AE_1) {
5047
+ if (extraFieldAES.vendorVersion != VENDOR_VERSION_AE_1$1) {
5036
5048
  directory.crc32 = UNDEFINED_VALUE;
5037
5049
  }
5038
5050
  }
@@ -5072,6 +5084,22 @@
5072
5084
  }
5073
5085
  }
5074
5086
 
5087
+ function readExtraFieldUnixDates(extraField, directory) {
5088
+ if (extraField.data.length < 8) {
5089
+ return;
5090
+ }
5091
+ const extraFieldView = getDataView(extraField.data);
5092
+ const lastAccessDate = new Date(getUint32(extraFieldView, 0) * 1000);
5093
+ const lastModDate = new Date(getUint32(extraFieldView, 4) * 1000);
5094
+ const extraFieldData = { lastAccessDate, lastModDate };
5095
+ if (extraField.data.length >= 12) {
5096
+ extraFieldData.uid = getUint16(extraFieldView, 8);
5097
+ extraFieldData.gid = getUint16(extraFieldView, 10);
5098
+ }
5099
+ Object.assign(extraField, extraFieldData);
5100
+ Object.assign(directory, extraFieldData);
5101
+ }
5102
+
5075
5103
  function readExtraFieldUnix(extraField, directory, isInfoZip) {
5076
5104
  try {
5077
5105
  const view = getDataView(extraField.data);
@@ -5150,7 +5178,7 @@
5150
5178
  fileEntry,
5151
5179
  index,
5152
5180
  offset,
5153
- signature,
5181
+ crc32,
5154
5182
  compressedSize,
5155
5183
  uncompressedSize,
5156
5184
  dataOffset,
@@ -5171,7 +5199,7 @@
5171
5199
  const dataDescriptorSignature = dataDescriptorArray.length == dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH &&
5172
5200
  getUint32(getDataView(dataDescriptorArray), 0) == DATA_DESCRIPTOR_RECORD_SIGNATURE;
5173
5201
  if (dataDescriptorSignature) {
5174
- const readSignature = getUint32(getDataView(dataDescriptorArray), 4);
5202
+ const readCrc32 = getUint32(getDataView(dataDescriptorArray), 4);
5175
5203
  let readCompressedSize;
5176
5204
  let readUncompressedSize;
5177
5205
  if (extraFieldZip64) {
@@ -5181,8 +5209,8 @@
5181
5209
  readCompressedSize = getUint32(getDataView(dataDescriptorArray), 8);
5182
5210
  readUncompressedSize = getUint32(getDataView(dataDescriptorArray), 12);
5183
5211
  }
5184
- const matchSignature = (fileEntry.encrypted && !fileEntry.zipCrypto) || readSignature == signature;
5185
- if (matchSignature &&
5212
+ const matchCrc32 = (fileEntry.encrypted && !fileEntry.zipCrypto) || readCrc32 == crc32;
5213
+ if (matchCrc32 &&
5186
5214
  readCompressedSize == compressedSize &&
5187
5215
  readUncompressedSize == uncompressedSize) {
5188
5216
  dataDescriptorLength += DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH;
@@ -5351,11 +5379,11 @@
5351
5379
  throwAmbiguousArchive("mismatched local file header (compression method)");
5352
5380
  }
5353
5381
  if (!localDirectory.bitFlag.dataDescriptor &&
5354
- (localDirectory.signature || localDirectory.compressedSize || localDirectory.uncompressedSize) &&
5355
- (localDirectory.signature != zipEntry.signature ||
5382
+ (localDirectory.crc32 || localDirectory.compressedSize || localDirectory.uncompressedSize) &&
5383
+ (localDirectory.crc32 != zipEntry.crc32 ||
5356
5384
  localDirectory.compressedSize != zipEntry.compressedSize ||
5357
5385
  localDirectory.uncompressedSize != zipEntry.uncompressedSize)) {
5358
- throwAmbiguousArchive("mismatched local file header (signature or sizes)");
5386
+ throwAmbiguousArchive("mismatched local file header (crc32 or sizes)");
5359
5387
  }
5360
5388
  }
5361
5389
 
@@ -5474,7 +5502,9 @@
5474
5502
  const ERR_INVALID_MSDOS_DATA = "Invalid msdosAttributes (must be an object with boolean flags)";
5475
5503
 
5476
5504
  const EXTRAFIELD_DATA_AES = new Uint8Array([0x07, 0x00, 0x02, 0x00, 0x41, 0x45, 0x03, 0x00, 0x00]);
5477
- const INFOZIP_EXTRA_FIELD_TYPE = "infozip";
5505
+ const EXTRAFIELD_OFFSET_AES_VENDOR_VERSION = 4;
5506
+ const VENDOR_VERSION_AE_1 = 1;
5507
+ const INFOZIP_EXTRA_FIELD_TYPE$1 = "infozip";
5478
5508
  const UNIX_EXTRA_FIELD_TYPE = "unix";
5479
5509
 
5480
5510
  let workers = 0;
@@ -5568,9 +5598,9 @@
5568
5598
  zip64UncompressedSize,
5569
5599
  extraFieldLength
5570
5600
  });
5571
- const { signature } = entry;
5572
- if (signature !== UNDEFINED_VALUE) {
5573
- setUint32(headerView, HEADER_OFFSET_SIGNATURE, signature);
5601
+ const { crc32 } = entry;
5602
+ if (crc32 !== UNDEFINED_VALUE) {
5603
+ setUint32(headerView, HEADER_OFFSET_SIGNATURE, crc32);
5574
5604
  }
5575
5605
  Object.assign(entry, {
5576
5606
  zip64UncompressedSize,
@@ -5693,6 +5723,7 @@
5693
5723
  internalFileAttribute: metadataInfo.resolvedOptions.internalFileAttributes,
5694
5724
  externalFileAttribute: attributesInfo.resolvedOptions.externalFileAttributes,
5695
5725
  signature: options[PROPERTY_NAME_SIGNATURE],
5726
+ crc32: options.crc32 === UNDEFINED_VALUE ? options[PROPERTY_NAME_SIGNATURE] : options.crc32,
5696
5727
  offset: zipWriter.offset - diskOffset,
5697
5728
  diskNumberStart: diskNumber
5698
5729
  });
@@ -5729,7 +5760,7 @@
5729
5760
  if (unixMode !== UNDEFINED_VALUE && (unixMode < 0 || unixMode > MAX_16_BITS)) {
5730
5761
  throw new Error(ERR_INVALID_UNIX_MODE);
5731
5762
  }
5732
- if (unixExtraFieldType !== UNDEFINED_VALUE && unixExtraFieldType !== INFOZIP_EXTRA_FIELD_TYPE && unixExtraFieldType !== UNIX_EXTRA_FIELD_TYPE) {
5763
+ if (unixExtraFieldType !== UNDEFINED_VALUE && unixExtraFieldType !== INFOZIP_EXTRA_FIELD_TYPE$1 && unixExtraFieldType !== UNIX_EXTRA_FIELD_TYPE) {
5733
5764
  throw new Error(ERR_INVALID_UNIX_EXTRA_FIELD_TYPE);
5734
5765
  }
5735
5766
  if (unixExtraFieldType === UNIX_EXTRA_FIELD_TYPE &&
@@ -5737,7 +5768,7 @@
5737
5768
  throw new Error(ERR_INVALID_UNIX_ID_SIZE);
5738
5769
  }
5739
5770
  if (unixExtraFieldType === UNDEFINED_VALUE && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
5740
- unixExtraFieldType = INFOZIP_EXTRA_FIELD_TYPE;
5771
+ unixExtraFieldType = INFOZIP_EXTRA_FIELD_TYPE$1;
5741
5772
  }
5742
5773
  let msdosAttributesRaw = getOptionValue(zipWriter, options, PROPERTY_NAME_MSDOS_ATTRIBUTES_RAW);
5743
5774
  let msdosAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_MSDOS_ATTRIBUTES);
@@ -5909,27 +5940,8 @@
5909
5940
  if (!zipCrypto && (password !== UNDEFINED_VALUE || rawPassword !== UNDEFINED_VALUE) && !(encryptionStrength >= 1 && encryptionStrength <= 3)) {
5910
5941
  throw new Error(ERR_INVALID_ENCRYPTION_STRENGTH);
5911
5942
  }
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
- }
5943
+ const rawExtraField = serializeExtraField(options[PROPERTY_NAME_EXTRA_FIELD]);
5944
+ const rawLocalExtraField = serializeExtraField(options[OPTION_LOCAL_EXTRA_FIELD]);
5933
5945
  return {
5934
5946
  comment,
5935
5947
  resolvedOptions: {
@@ -5963,11 +5975,36 @@
5963
5975
  useCompressionStream,
5964
5976
  dataDescriptor,
5965
5977
  zip64,
5966
- rawExtraField
5978
+ rawExtraField,
5979
+ rawLocalExtraField
5967
5980
  }
5968
5981
  };
5969
5982
  }
5970
5983
 
5984
+ function serializeExtraField(extraField) {
5985
+ if (!extraField) {
5986
+ return EMPTY_UINT8_ARRAY;
5987
+ }
5988
+ let extraFieldSize = 0;
5989
+ let offset = 0;
5990
+ extraField.forEach(data => extraFieldSize += 4 + getLength(data));
5991
+ const rawExtraField = new Uint8Array(extraFieldSize);
5992
+ const rawExtraFieldView = getDataView(rawExtraField);
5993
+ extraField.forEach((data, type) => {
5994
+ if (type > MAX_16_BITS) {
5995
+ throw new Error(ERR_INVALID_EXTRAFIELD_TYPE);
5996
+ }
5997
+ if (getLength(data) > MAX_16_BITS) {
5998
+ throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
5999
+ }
6000
+ setUint16(rawExtraFieldView, offset, type);
6001
+ setUint16(rawExtraFieldView, offset + 2, getLength(data));
6002
+ arraySet(rawExtraField, data, offset + 4);
6003
+ offset += 4 + getLength(data);
6004
+ });
6005
+ return rawExtraField;
6006
+ }
6007
+
5971
6008
  async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, options) {
5972
6009
  const { passThrough, zipCrypto, password, rawPassword, encryptionStrength } = metadata;
5973
6010
  let { dataDescriptor, zip64, level, compressionMethod } = metadata;
@@ -6292,12 +6329,9 @@
6292
6329
  msdosAttributes
6293
6330
  };
6294
6331
  let {
6295
- crc32: signature,
6332
+ crc32,
6296
6333
  uncompressedSize
6297
6334
  } = options;
6298
- if (signature === UNDEFINED_VALUE) {
6299
- ({ signature } = options);
6300
- }
6301
6335
  let compressedSize = 0;
6302
6336
  if (!passThrough) {
6303
6337
  uncompressedSize = 0;
@@ -6335,7 +6369,7 @@
6335
6369
  if (!passThrough) {
6336
6370
  uncompressedSize = result.inputSize;
6337
6371
  if (!encrypted || zipCrypto) {
6338
- signature = result.signature;
6372
+ crc32 = result.crc32;
6339
6373
  }
6340
6374
  }
6341
6375
  if ((!zip64CompressedSize && compressedSize >= MAX_32_BITS) ||
@@ -6351,7 +6385,7 @@
6351
6385
 
6352
6386
  }
6353
6387
  setEntryInfo({
6354
- signature,
6388
+ crc32,
6355
6389
  compressedSize,
6356
6390
  uncompressedSize,
6357
6391
  headerInfo,
@@ -6374,8 +6408,8 @@
6374
6408
  version,
6375
6409
  headerArray,
6376
6410
  headerView,
6377
- signature,
6378
- crc32: encrypted && !zipCrypto ? UNDEFINED_VALUE : signature,
6411
+ signature: crc32,
6412
+ crc32: encrypted && !zipCrypto && !passThrough ? UNDEFINED_VALUE : crc32,
6379
6413
  extraFieldExtendedTimestampFlag,
6380
6414
  zip64UncompressedSize,
6381
6415
  zip64CompressedSize
@@ -6396,6 +6430,7 @@
6396
6430
  dataDescriptor,
6397
6431
  directory,
6398
6432
  rawExtraField,
6433
+ rawLocalExtraField,
6399
6434
  encryptionStrength,
6400
6435
  extendedTimestamp,
6401
6436
  ntfsTimestamp,
@@ -6403,7 +6438,8 @@
6403
6438
  encrypted,
6404
6439
  zip64UncompressedSize,
6405
6440
  zip64CompressedSize,
6406
- uncompressedSize
6441
+ uncompressedSize,
6442
+ crc32
6407
6443
  } = options;
6408
6444
  let { version, compressionMethod } = options;
6409
6445
  const compressed = !directory && (compressionMethod === UNDEFINED_VALUE
@@ -6491,7 +6527,7 @@
6491
6527
  let rawExtraFieldUnix;
6492
6528
  try {
6493
6529
  const { uid, gid, unixExtraFieldType } = options;
6494
- if (unixExtraFieldType == INFOZIP_EXTRA_FIELD_TYPE && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
6530
+ if (unixExtraFieldType == INFOZIP_EXTRA_FIELD_TYPE$1 && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
6495
6531
  const uidBytes = packUnixId(uid);
6496
6532
  const gidBytes = packUnixId(gid);
6497
6533
  const payloadLength = 3 + uidBytes.length + gidBytes.length;
@@ -6529,11 +6565,14 @@
6529
6565
  }
6530
6566
  if (encrypted && !zipCrypto) {
6531
6567
  version = version > VERSION_AES ? version : VERSION_AES;
6568
+ if (passThrough && crc32 !== UNDEFINED_VALUE) {
6569
+ rawExtraFieldAES[EXTRAFIELD_OFFSET_AES_VENDOR_VERSION] = VENDOR_VERSION_AE_1;
6570
+ }
6532
6571
  rawExtraFieldAES[9] = compressionMethod;
6533
6572
  compressionMethod = COMPRESSION_METHOD_AES;
6534
6573
  }
6535
6574
  const localExtraFieldZip64Length = writeLocalExtraFieldZip64 ? getLength(rawLocalExtraFieldZip64) : 0;
6536
- const extraFieldLength = localExtraFieldZip64Length + getLength(rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField);
6575
+ const extraFieldLength = localExtraFieldZip64Length + getLength(rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField, rawLocalExtraField);
6537
6576
  if (extraFieldLength > MAX_16_BITS) {
6538
6577
  throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
6539
6578
  }
@@ -6567,6 +6606,7 @@
6567
6606
  localHeader.bytes(rawExtraFieldNTFS);
6568
6607
  localHeader.bytes(rawExtraFieldUnix);
6569
6608
  localHeader.bytes(rawExtraField);
6609
+ localHeader.bytes(rawLocalExtraField);
6570
6610
  if (dataDescriptor) {
6571
6611
  if (!zip64CompressedSize) {
6572
6612
  setUint32(localHeaderView, HEADER_OFFSET_COMPRESSED_SIZE + LOCAL_HEADER_COMMON_OFFSET, 0);
@@ -6685,7 +6725,7 @@
6685
6725
  }
6686
6726
 
6687
6727
  function setEntryInfo({
6688
- signature,
6728
+ crc32,
6689
6729
  compressedSize,
6690
6730
  uncompressedSize,
6691
6731
  headerInfo,
@@ -6693,6 +6733,7 @@
6693
6733
  }, {
6694
6734
  zip64,
6695
6735
  zipCrypto,
6736
+ passThrough,
6696
6737
  dataDescriptor
6697
6738
  }) {
6698
6739
  const {
@@ -6703,10 +6744,10 @@
6703
6744
  dataDescriptorView,
6704
6745
  dataDescriptorOffset
6705
6746
  } = dataDescriptorInfo;
6706
- if ((!encrypted || zipCrypto) && signature !== UNDEFINED_VALUE) {
6707
- setUint32(headerView, HEADER_OFFSET_SIGNATURE, signature);
6747
+ if ((!encrypted || zipCrypto || passThrough) && crc32 !== UNDEFINED_VALUE) {
6748
+ setUint32(headerView, HEADER_OFFSET_SIGNATURE, crc32);
6708
6749
  if (dataDescriptor) {
6709
- setUint32(dataDescriptorView, dataDescriptorOffset, signature);
6750
+ setUint32(dataDescriptorView, dataDescriptorOffset, crc32);
6710
6751
  }
6711
6752
  }
6712
6753
  if (zip64) {
@@ -6729,15 +6770,15 @@
6729
6770
  encrypted,
6730
6771
  zip64,
6731
6772
  localExtraFieldZip64Length,
6732
- signature,
6773
+ crc32,
6733
6774
  compressedSize,
6734
6775
  uncompressedSize,
6735
6776
  zip64UncompressedSize,
6736
6777
  zip64CompressedSize
6737
- }, localHeaderView, { dataDescriptor }) {
6778
+ }, localHeaderView, { dataDescriptor, passThrough }) {
6738
6779
  if (!dataDescriptor) {
6739
- if (!encrypted) {
6740
- setUint32(localHeaderView, HEADER_OFFSET_SIGNATURE + LOCAL_HEADER_COMMON_OFFSET, signature);
6780
+ if (!encrypted || (passThrough && crc32 !== UNDEFINED_VALUE)) {
6781
+ setUint32(localHeaderView, HEADER_OFFSET_SIGNATURE + LOCAL_HEADER_COMMON_OFFSET, crc32);
6741
6782
  }
6742
6783
  if (!zip64CompressedSize) {
6743
6784
  setUint32(localHeaderView, HEADER_OFFSET_COMPRESSED_SIZE + LOCAL_HEADER_COMMON_OFFSET, compressedSize);
@@ -7202,6 +7243,20 @@
7202
7243
 
7203
7244
  const ERR_ENTRY_EXISTS = "Entry filename already exists";
7204
7245
  const ERR_READABLE_CONSUMED = "Readable stream already consumed";
7246
+ const INFOZIP_EXTRA_FIELD_TYPE = "infozip";
7247
+ const INTERPRETED_EXTRA_FIELD_TYPES = new Set([
7248
+ EXTRAFIELD_TYPE_ZIP64,
7249
+ EXTRAFIELD_TYPE_AES,
7250
+ EXTRAFIELD_TYPE_NTFS,
7251
+ EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP,
7252
+ EXTRAFIELD_TYPE_UNICODE_PATH,
7253
+ EXTRAFIELD_TYPE_UNICODE_COMMENT,
7254
+ EXTRAFIELD_TYPE_USDZ,
7255
+ EXTRAFIELD_TYPE_INFOZIP,
7256
+ EXTRAFIELD_TYPE_UNIX,
7257
+ EXTRAFIELD_TYPE_UNIX_TYPE1,
7258
+ EXTRAFIELD_TYPE_PKWARE_UNIX
7259
+ ]);
7205
7260
 
7206
7261
  class ZipEntry {
7207
7262
 
@@ -7939,6 +7994,20 @@
7939
7994
  }
7940
7995
  }
7941
7996
 
7997
+ function getUserExtraField(extraField) {
7998
+ if (extraField) {
7999
+ const userExtraField = new Map();
8000
+ extraField.forEach((field, type) => {
8001
+ if (!INTERPRETED_EXTRA_FIELD_TYPES.has(type)) {
8002
+ userExtraField.set(type, field.data);
8003
+ }
8004
+ });
8005
+ if (userExtraField.size) {
8006
+ return userExtraField;
8007
+ }
8008
+ }
8009
+ }
8010
+
7942
8011
  async function exportZip(zipWriter, entry, totalSize, options, readers) {
7943
8012
  const selectedEntry = entry;
7944
8013
  const entryOffsets = new Map();
@@ -7976,9 +8045,13 @@
7976
8045
  uncompressedSize,
7977
8046
  encrypted,
7978
8047
  zipCrypto,
7979
- signature,
8048
+ crc32,
7980
8049
  compressionMethod,
7981
- extraFieldAES
8050
+ extraFieldAES,
8051
+ internalFileAttributes,
8052
+ extraField,
8053
+ uid,
8054
+ gid
7982
8055
  } = child.data;
7983
8056
  zipEntryOptions = {
7984
8057
  externalFileAttributes,
@@ -7986,8 +8059,20 @@
7986
8059
  comment,
7987
8060
  lastModDate,
7988
8061
  creationDate,
7989
- lastAccessDate
8062
+ lastAccessDate,
8063
+ internalFileAttributes
7990
8064
  };
8065
+ const userExtraField = getUserExtraField(extraField);
8066
+ if (userExtraField) {
8067
+ zipEntryOptions.extraField = userExtraField;
8068
+ }
8069
+ if (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE) {
8070
+ Object.assign(zipEntryOptions, {
8071
+ uid,
8072
+ gid,
8073
+ unixExtraFieldType: options.unixExtraFieldType || INFOZIP_EXTRA_FIELD_TYPE
8074
+ });
8075
+ }
7991
8076
  if (child.passThrough) {
7992
8077
  let level, encryptionStrength;
7993
8078
  if (compressionMethod === 0) {
@@ -8000,7 +8085,7 @@
8000
8085
  passThrough: true,
8001
8086
  encrypted,
8002
8087
  zipCrypto,
8003
- signature,
8088
+ crc32,
8004
8089
  uncompressedSize,
8005
8090
  level,
8006
8091
  encryptionStrength,