@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
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;
@@ -1420,7 +1422,7 @@
1420
1422
  const DERIVED_BITS_USAGE = ["deriveBits"];
1421
1423
  const SALT_LENGTH = [8, 12, 16];
1422
1424
  const KEY_LENGTH = [16, 24, 32];
1423
- const SIGNATURE_LENGTH = 10;
1425
+ const AUTHENTICATION_CODE_LENGTH = 10;
1424
1426
  const COUNTER_DEFAULT_VALUE = [0, 0, 0, 0];
1425
1427
  // deno-lint-ignore valid-typeof
1426
1428
  const CRYPTO_API_SUPPORTED = typeof crypto != UNDEFINED_TYPE;
@@ -1460,8 +1462,8 @@
1460
1462
  } else {
1461
1463
  await ready;
1462
1464
  }
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));
1465
+ const output = new Uint8Array(chunk.length - AUTHENTICATION_CODE_LENGTH - ((chunk.length - AUTHENTICATION_CODE_LENGTH) % BLOCK_LENGTH));
1466
+ controller.enqueue(append(aesCrypto, chunk, output, 0, AUTHENTICATION_CODE_LENGTH, true));
1465
1467
  },
1466
1468
  async flush(controller) {
1467
1469
  const {
@@ -1472,8 +1474,8 @@
1472
1474
  } = this;
1473
1475
  if (hmac && ctr) {
1474
1476
  await ready;
1475
- const chunkToDecrypt = subarray(pending, 0, pending.length - SIGNATURE_LENGTH);
1476
- const originalSignature = subarray(pending, pending.length - SIGNATURE_LENGTH);
1477
+ const chunkToDecrypt = subarray(pending, 0, pending.length - AUTHENTICATION_CODE_LENGTH);
1478
+ const originalAuthenticationCode = subarray(pending, pending.length - AUTHENTICATION_CODE_LENGTH);
1477
1479
  let decryptedChunkArray = EMPTY_UINT8_ARRAY;
1478
1480
  if (chunkToDecrypt.length) {
1479
1481
  const encryptedChunk = toBits(codecBytes, chunkToDecrypt);
@@ -1481,12 +1483,12 @@
1481
1483
  const decryptedChunk = ctr.update(encryptedChunk);
1482
1484
  decryptedChunkArray = fromBits(codecBytes, decryptedChunk);
1483
1485
  }
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];
1486
+ const authenticationCode = subarray(fromBits(codecBytes, hmac.digest()), 0, AUTHENTICATION_CODE_LENGTH);
1487
+ let invalidAuthenticationCode = pending.length < AUTHENTICATION_CODE_LENGTH ? 1 : 0;
1488
+ for (let indexByte = 0; indexByte < AUTHENTICATION_CODE_LENGTH; indexByte++) {
1489
+ invalidAuthenticationCode |= authenticationCode[indexByte] ^ originalAuthenticationCode[indexByte];
1488
1490
  }
1489
- if (invalidSignature && checkAuthenticationCode) {
1491
+ if (invalidAuthenticationCode && checkAuthenticationCode) {
1490
1492
  throw new Error(ERR_INVALID_AUTHENTICATION_CODE);
1491
1493
  }
1492
1494
  controller.enqueue(decryptedChunkArray);
@@ -1499,8 +1501,6 @@
1499
1501
  class AESEncryptionStream extends TransformStream {
1500
1502
 
1501
1503
  constructor({ password, rawPassword, encryptionStrength }) {
1502
- // deno-lint-ignore prefer-const
1503
- let stream;
1504
1504
  super({
1505
1505
  start() {
1506
1506
  initAesCrypto(this, password, rawPassword, encryptionStrength);
@@ -1539,12 +1539,11 @@
1539
1539
  hmac.update(encryptedChunk);
1540
1540
  encryptedChunkArray = fromBits(codecBytes, encryptedChunk);
1541
1541
  }
1542
- stream.signature = fromBits(codecBytes, hmac.digest()).slice(0, SIGNATURE_LENGTH);
1543
- controller.enqueue(concat(encryptedChunkArray, stream.signature));
1542
+ const authenticationCode = fromBits(codecBytes, hmac.digest()).slice(0, AUTHENTICATION_CODE_LENGTH);
1543
+ controller.enqueue(concat(encryptedChunkArray, authenticationCode));
1544
1544
  }
1545
1545
  }
1546
1546
  });
1547
- stream = this;
1548
1547
  }
1549
1548
  }
1550
1549
 
@@ -1557,7 +1556,7 @@
1557
1556
  });
1558
1557
  }
1559
1558
 
1560
- function append(aesCrypto, input, output, paddingStart, paddingEnd, verifySignature) {
1559
+ function append(aesCrypto, input, output, paddingStart, paddingEnd, verifyAuthenticationCode) {
1561
1560
  const {
1562
1561
  ctr,
1563
1562
  hmac,
@@ -1571,11 +1570,11 @@
1571
1570
  let offset;
1572
1571
  for (offset = 0; offset <= inputLength - BLOCK_LENGTH; offset += BLOCK_LENGTH) {
1573
1572
  const inputChunk = toBits(codecBytes, subarray(input, offset, offset + BLOCK_LENGTH));
1574
- if (verifySignature) {
1573
+ if (verifyAuthenticationCode) {
1575
1574
  hmac.update(inputChunk);
1576
1575
  }
1577
1576
  const outputChunk = ctr.update(inputChunk);
1578
- if (!verifySignature) {
1577
+ if (!verifyAuthenticationCode) {
1579
1578
  hmac.update(outputChunk);
1580
1579
  }
1581
1580
  output.set(fromBits(codecBytes, outputChunk), offset + paddingStart);
@@ -1981,14 +1980,9 @@
1981
1980
  }
1982
1981
  }
1983
1982
  setReadable(stream, readable, () => {
1984
- let signature;
1985
- if (encrypted && !zipCrypto) {
1986
- signature = encryptionStream.signature;
1987
- }
1988
1983
  if ((!encrypted || zipCrypto) && computeCrc32) {
1989
- signature = useGzipCrc32 ? gzipCrc32Stream.signature : new DataView(crc32Stream.value.buffer).getUint32(0);
1984
+ stream.crc32 = useGzipCrc32 ? gzipCrc32Stream.crc32 : new DataView(crc32Stream.value.buffer).getUint32(0);
1990
1985
  }
1991
- stream.signature = signature;
1992
1986
  });
1993
1987
  }
1994
1988
  }
@@ -2026,7 +2020,7 @@
2026
2020
  },
2027
2021
  flush() {
2028
2022
  const dataView = getDataView(trailerCandidate);
2029
- stream.signature = dataView.getUint32(0, true);
2023
+ stream.crc32 = dataView.getUint32(0, true);
2030
2024
  stream.uncompressedSize = dataView.getUint32(4, true);
2031
2025
  }
2032
2026
  });
@@ -2108,7 +2102,7 @@
2108
2102
 
2109
2103
  constructor(options, { chunkSize, DecompressionStreamZlib, DecompressionStream }) {
2110
2104
  super({});
2111
- const { zipCrypto, encrypted, checkCrc32, signature, compressed, useCompressionStream, deflate64, format, compressionMethod, rawBitFlag, outputSize } = options;
2105
+ const { zipCrypto, encrypted, checkCrc32, crc32, compressed, useCompressionStream, deflate64, format, compressionMethod, rawBitFlag, outputSize } = options;
2112
2106
  let crc32Stream, decryptionStream;
2113
2107
  let readable = super.readable;
2114
2108
  if (encrypted) {
@@ -2147,8 +2141,8 @@
2147
2141
  }
2148
2142
  setReadable(this, readable, () => {
2149
2143
  if (checkCrc32) {
2150
- const dataViewSignature = new DataView(crc32Stream.value.buffer);
2151
- if (signature != dataViewSignature.getUint32(0, false)) {
2144
+ const computedCrc32View = new DataView(crc32Stream.value.buffer);
2145
+ if (crc32 != computedCrc32View.getUint32(0, false)) {
2152
2146
  throw new Error(ERR_INVALID_CRC32);
2153
2147
  }
2154
2148
  }
@@ -2373,9 +2367,9 @@
2373
2367
  }
2374
2368
  },
2375
2369
  flush() {
2376
- const { signature } = stream;
2370
+ const { crc32 } = stream;
2377
2371
  Object.assign(codec, {
2378
- signature,
2372
+ crc32,
2379
2373
  inputSize
2380
2374
  });
2381
2375
  }
@@ -2674,12 +2668,12 @@
2674
2668
  .pipeThrough(new ChunkStream(getChunkSize(config)))
2675
2669
  .pipeTo(writable, { preventClose: true, preventAbort: true });
2676
2670
  const {
2677
- signature,
2671
+ crc32,
2678
2672
  inputSize,
2679
2673
  outputSize
2680
2674
  } = codecStream;
2681
2675
  return {
2682
- signature,
2676
+ crc32,
2683
2677
  inputSize,
2684
2678
  outputSize
2685
2679
  };
@@ -4277,6 +4271,8 @@
4277
4271
  const PROPERTY_NAME_EXTRA_FIELD = "extraField";
4278
4272
  const PROPERTY_NAME_EXTRA_FIELD_INFOZIP = "extraFieldInfoZip";
4279
4273
  const PROPERTY_NAME_EXTRA_FIELD_UNIX = "extraFieldUnix";
4274
+ const PROPERTY_NAME_EXTRA_FIELD_UNIX_TYPE1 = "extraFieldUnixType1";
4275
+ const PROPERTY_NAME_EXTRA_FIELD_PKWARE_UNIX = "extraFieldPkwareUnix";
4280
4276
  const PROPERTY_NAME_UID = "uid";
4281
4277
  const PROPERTY_NAME_GID = "gid";
4282
4278
  const PROPERTY_NAME_UNIX_MODE = "unixMode";
@@ -4293,6 +4289,7 @@
4293
4289
  const PROPERTY_NAME_EXTRA_FIELD_AES = "extraFieldAES";
4294
4290
  const PROPERTY_NAME_EXTRA_FIELD_NTFS = "extraFieldNTFS";
4295
4291
  const PROPERTY_NAME_EXTRA_FIELD_EXTENDED_TIMESTAMP = "extraFieldExtendedTimestamp";
4292
+ const PROPERTY_NAME_EXTRA_FIELD_USDZ = "extraFieldUSDZ";
4296
4293
 
4297
4294
  const PROPERTY_NAMES = [
4298
4295
  PROPERTY_NAME_FILENAME,
@@ -4304,6 +4301,7 @@
4304
4301
  PROPERTY_NAME_COMMENT,
4305
4302
  PROPERTY_NAME_RAW_COMMENT,
4306
4303
  PROPERTY_NAME_LAST_ACCESS_DATE,
4304
+ PROPERTY_NAME_RAW_LAST_ACCESS_DATE,
4307
4305
  PROPERTY_NAME_CREATION_DATE,
4308
4306
  PROPERTY_NAME_RAW_CREATION_DATE,
4309
4307
  PROPERTY_NAME_OFFSET,
@@ -4326,6 +4324,8 @@
4326
4324
  PROPERTY_NAME_EXTRA_FIELD,
4327
4325
  PROPERTY_NAME_EXTRA_FIELD_UNIX,
4328
4326
  PROPERTY_NAME_EXTRA_FIELD_INFOZIP,
4327
+ PROPERTY_NAME_EXTRA_FIELD_UNIX_TYPE1,
4328
+ PROPERTY_NAME_EXTRA_FIELD_PKWARE_UNIX,
4329
4329
  PROPERTY_NAME_UID,
4330
4330
  PROPERTY_NAME_GID,
4331
4331
  PROPERTY_NAME_UNIX_MODE,
@@ -4341,7 +4341,8 @@
4341
4341
  PROPERTY_NAME_EXTRA_FIELD_UNICODE_COMMENT,
4342
4342
  PROPERTY_NAME_EXTRA_FIELD_AES,
4343
4343
  PROPERTY_NAME_EXTRA_FIELD_NTFS,
4344
- PROPERTY_NAME_EXTRA_FIELD_EXTENDED_TIMESTAMP
4344
+ PROPERTY_NAME_EXTRA_FIELD_EXTENDED_TIMESTAMP,
4345
+ PROPERTY_NAME_EXTRA_FIELD_USDZ
4345
4346
  ];
4346
4347
 
4347
4348
  class Entry {
@@ -4415,6 +4416,7 @@
4415
4416
  const OPTION_OFFSET = "offset";
4416
4417
  const OPTION_USDZ = "usdz";
4417
4418
  const OPTION_UNIX_EXTRA_FIELD_TYPE = "unixExtraFieldType";
4419
+ const OPTION_LOCAL_EXTRA_FIELD = "localExtraField";
4418
4420
  const OPTION_STRICTNESS = "strictness";
4419
4421
  const OPTION_MAX_APPENDED_DATA_SIZE = "maxAppendedDataSize";
4420
4422
  const STRICTNESS_STRICT = "strict";
@@ -4467,7 +4469,7 @@
4467
4469
  const PROPERTY_NAME_UTF8_SUFFIX = "UTF8";
4468
4470
  const CHARSET_CP437 = "cp437";
4469
4471
  const BITFLAG_AMBIGUITY_MASK = BITFLAG_ENCRYPTED | BITFLAG_DATA_DESCRIPTOR | BITFLAG_LANG_ENCODING_FLAG;
4470
- const VENDOR_VERSION_AE_1 = 1;
4472
+ const VENDOR_VERSION_AE_1$1 = 1;
4471
4473
  const ZIP64_PROPERTIES = [
4472
4474
  [PROPERTY_NAME_UNCOMPRESSED_SIZE, MAX_32_BITS],
4473
4475
  [PROPERTY_NAME_COMPRESSED_SIZE, MAX_32_BITS],
@@ -4860,7 +4862,7 @@
4860
4862
  config,
4861
4863
  bitFlag,
4862
4864
  rawBitFlag,
4863
- signature,
4865
+ crc32,
4864
4866
  rawLastModDate,
4865
4867
  uncompressedSize,
4866
4868
  compressedSize
@@ -4951,7 +4953,7 @@
4951
4953
  const checkCrc32 = (checkCrc32Option === UNDEFINED_VALUE ?
4952
4954
  getOptionValue$1(zipEntry, options, OPTION_CHECK_SIGNATURE) :
4953
4955
  checkCrc32Option) && !passThrough &&
4954
- (!encrypted || zipCrypto || (extraFieldAES && extraFieldAES.vendorVersion == VENDOR_VERSION_AE_1));
4956
+ (!encrypted || zipCrypto || (extraFieldAES && extraFieldAES.vendorVersion == VENDOR_VERSION_AE_1$1));
4955
4957
  const workerOptions = {
4956
4958
  options: {
4957
4959
  codecType: CODEC_INFLATE,
@@ -4961,9 +4963,9 @@
4961
4963
  encryptionStrength: extraFieldAES && extraFieldAES.strength,
4962
4964
  checkCrc32,
4963
4965
  checkAuthenticationCode: getOptionValue$1(zipEntry, options, OPTION_CHECK_AUTHENTICATION_CODE),
4964
- passwordVerification: zipCrypto && (dataDescriptor ? ((rawLastModDate >>> 8) & MAX_8_BITS) : ((signature >>> 24) & MAX_8_BITS)),
4966
+ passwordVerification: zipCrypto && (dataDescriptor ? ((rawLastModDate >>> 8) & MAX_8_BITS) : ((crc32 >>> 24) & MAX_8_BITS)),
4965
4967
  outputSize: passThrough ? compressedSize : uncompressedSize,
4966
- signature,
4968
+ crc32,
4967
4969
  compressed: compressionMethod != 0 && !passThrough,
4968
4970
  encrypted,
4969
4971
  useWebWorkers: getOptionValue$1(zipEntry, options, OPTION_USE_WEB_WORKERS),
@@ -4985,7 +4987,7 @@
4985
4987
  fileEntry,
4986
4988
  index,
4987
4989
  offset: localHeaderOffset,
4988
- signature,
4990
+ crc32,
4989
4991
  compressedSize,
4990
4992
  uncompressedSize,
4991
4993
  dataOffset,
@@ -5102,6 +5104,16 @@
5102
5104
  } else {
5103
5105
  directory.compressionMethod = compressionMethod;
5104
5106
  }
5107
+ const extraFieldPkwareUnix = extraField.get(EXTRAFIELD_TYPE_PKWARE_UNIX);
5108
+ if (extraFieldPkwareUnix) {
5109
+ readExtraFieldUnixDates(extraFieldPkwareUnix, directory);
5110
+ directory.extraFieldPkwareUnix = extraFieldPkwareUnix;
5111
+ }
5112
+ const extraFieldUnixType1 = extraField.get(EXTRAFIELD_TYPE_UNIX_TYPE1);
5113
+ if (extraFieldUnixType1) {
5114
+ readExtraFieldUnixDates(extraFieldUnixType1, directory);
5115
+ directory.extraFieldUnixType1 = extraFieldUnixType1;
5116
+ }
5105
5117
  const extraFieldNTFS = extraField.get(EXTRAFIELD_TYPE_NTFS);
5106
5118
  if (extraFieldNTFS) {
5107
5119
  readExtraFieldNTFS(extraFieldNTFS, directory);
@@ -5151,15 +5163,15 @@
5151
5163
  return;
5152
5164
  }
5153
5165
  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);
5166
+ const computedCrc32 = new Crc32();
5167
+ computedCrc32.append(fileEntry[rawPropertyName]);
5168
+ const computedCrc32View = getDataView(new Uint8Array(4));
5169
+ computedCrc32View.setUint32(0, computedCrc32.get(), true);
5170
+ const nameCrc32 = getUint32(extraFieldView, 1);
5159
5171
  Object.assign(extraFieldUnicode, {
5160
5172
  version: getUint8(extraFieldView, 0),
5161
5173
  [propertyName]: decodeText(extraFieldUnicode.data.subarray(5)),
5162
- valid: !fileEntry.bitFlag.languageEncodingFlag && signature == getUint32(dataViewSignature, 0)
5174
+ valid: !fileEntry.bitFlag.languageEncodingFlag && nameCrc32 == getUint32(computedCrc32View, 0)
5163
5175
  });
5164
5176
  if (extraFieldUnicode.valid) {
5165
5177
  directory[propertyName] = extraFieldUnicode[propertyName];
@@ -5178,7 +5190,7 @@
5178
5190
  compressionMethod: getUint16(extraFieldView, 5)
5179
5191
  });
5180
5192
  directory.compressionMethod = extraFieldAES.compressionMethod;
5181
- if (extraFieldAES.vendorVersion != VENDOR_VERSION_AE_1) {
5193
+ if (extraFieldAES.vendorVersion != VENDOR_VERSION_AE_1$1) {
5182
5194
  directory.crc32 = UNDEFINED_VALUE;
5183
5195
  }
5184
5196
  }
@@ -5218,6 +5230,22 @@
5218
5230
  }
5219
5231
  }
5220
5232
 
5233
+ function readExtraFieldUnixDates(extraField, directory) {
5234
+ if (extraField.data.length < 8) {
5235
+ return;
5236
+ }
5237
+ const extraFieldView = getDataView(extraField.data);
5238
+ const lastAccessDate = new Date(getUint32(extraFieldView, 0) * 1000);
5239
+ const lastModDate = new Date(getUint32(extraFieldView, 4) * 1000);
5240
+ const extraFieldData = { lastAccessDate, lastModDate };
5241
+ if (extraField.data.length >= 12) {
5242
+ extraFieldData.uid = getUint16(extraFieldView, 8);
5243
+ extraFieldData.gid = getUint16(extraFieldView, 10);
5244
+ }
5245
+ Object.assign(extraField, extraFieldData);
5246
+ Object.assign(directory, extraFieldData);
5247
+ }
5248
+
5221
5249
  function readExtraFieldUnix(extraField, directory, isInfoZip) {
5222
5250
  try {
5223
5251
  const view = getDataView(extraField.data);
@@ -5296,7 +5324,7 @@
5296
5324
  fileEntry,
5297
5325
  index,
5298
5326
  offset,
5299
- signature,
5327
+ crc32,
5300
5328
  compressedSize,
5301
5329
  uncompressedSize,
5302
5330
  dataOffset,
@@ -5317,7 +5345,7 @@
5317
5345
  const dataDescriptorSignature = dataDescriptorArray.length == dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH &&
5318
5346
  getUint32(getDataView(dataDescriptorArray), 0) == DATA_DESCRIPTOR_RECORD_SIGNATURE;
5319
5347
  if (dataDescriptorSignature) {
5320
- const readSignature = getUint32(getDataView(dataDescriptorArray), 4);
5348
+ const readCrc32 = getUint32(getDataView(dataDescriptorArray), 4);
5321
5349
  let readCompressedSize;
5322
5350
  let readUncompressedSize;
5323
5351
  if (extraFieldZip64) {
@@ -5327,8 +5355,8 @@
5327
5355
  readCompressedSize = getUint32(getDataView(dataDescriptorArray), 8);
5328
5356
  readUncompressedSize = getUint32(getDataView(dataDescriptorArray), 12);
5329
5357
  }
5330
- const matchSignature = (fileEntry.encrypted && !fileEntry.zipCrypto) || readSignature == signature;
5331
- if (matchSignature &&
5358
+ const matchCrc32 = (fileEntry.encrypted && !fileEntry.zipCrypto) || readCrc32 == crc32;
5359
+ if (matchCrc32 &&
5332
5360
  readCompressedSize == compressedSize &&
5333
5361
  readUncompressedSize == uncompressedSize) {
5334
5362
  dataDescriptorLength += DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH;
@@ -5497,11 +5525,11 @@
5497
5525
  throwAmbiguousArchive("mismatched local file header (compression method)");
5498
5526
  }
5499
5527
  if (!localDirectory.bitFlag.dataDescriptor &&
5500
- (localDirectory.signature || localDirectory.compressedSize || localDirectory.uncompressedSize) &&
5501
- (localDirectory.signature != zipEntry.signature ||
5528
+ (localDirectory.crc32 || localDirectory.compressedSize || localDirectory.uncompressedSize) &&
5529
+ (localDirectory.crc32 != zipEntry.crc32 ||
5502
5530
  localDirectory.compressedSize != zipEntry.compressedSize ||
5503
5531
  localDirectory.uncompressedSize != zipEntry.uncompressedSize)) {
5504
- throwAmbiguousArchive("mismatched local file header (signature or sizes)");
5532
+ throwAmbiguousArchive("mismatched local file header (crc32 or sizes)");
5505
5533
  }
5506
5534
  }
5507
5535
 
@@ -5621,6 +5649,8 @@
5621
5649
  const ERR_INVALID_MSDOS_DATA = "Invalid msdosAttributes (must be an object with boolean flags)";
5622
5650
 
5623
5651
  const EXTRAFIELD_DATA_AES = new Uint8Array([0x07, 0x00, 0x02, 0x00, 0x41, 0x45, 0x03, 0x00, 0x00]);
5652
+ const EXTRAFIELD_OFFSET_AES_VENDOR_VERSION = 4;
5653
+ const VENDOR_VERSION_AE_1 = 1;
5624
5654
  const INFOZIP_EXTRA_FIELD_TYPE = "infozip";
5625
5655
  const UNIX_EXTRA_FIELD_TYPE = "unix";
5626
5656
 
@@ -5715,9 +5745,9 @@
5715
5745
  zip64UncompressedSize,
5716
5746
  extraFieldLength
5717
5747
  });
5718
- const { signature } = entry;
5719
- if (signature !== UNDEFINED_VALUE) {
5720
- setUint32(headerView, HEADER_OFFSET_SIGNATURE, signature);
5748
+ const { crc32 } = entry;
5749
+ if (crc32 !== UNDEFINED_VALUE) {
5750
+ setUint32(headerView, HEADER_OFFSET_SIGNATURE, crc32);
5721
5751
  }
5722
5752
  Object.assign(entry, {
5723
5753
  zip64UncompressedSize,
@@ -5902,6 +5932,7 @@
5902
5932
  internalFileAttribute: metadataInfo.resolvedOptions.internalFileAttributes,
5903
5933
  externalFileAttribute: attributesInfo.resolvedOptions.externalFileAttributes,
5904
5934
  signature: options[PROPERTY_NAME_SIGNATURE],
5935
+ crc32: options.crc32 === UNDEFINED_VALUE ? options[PROPERTY_NAME_SIGNATURE] : options.crc32,
5905
5936
  offset: zipWriter.offset - diskOffset,
5906
5937
  diskNumberStart: diskNumber
5907
5938
  });
@@ -6118,27 +6149,8 @@
6118
6149
  if (!zipCrypto && (password !== UNDEFINED_VALUE || rawPassword !== UNDEFINED_VALUE) && !(encryptionStrength >= 1 && encryptionStrength <= 3)) {
6119
6150
  throw new Error(ERR_INVALID_ENCRYPTION_STRENGTH);
6120
6151
  }
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
- }
6152
+ const rawExtraField = serializeExtraField(options[PROPERTY_NAME_EXTRA_FIELD]);
6153
+ const rawLocalExtraField = serializeExtraField(options[OPTION_LOCAL_EXTRA_FIELD]);
6142
6154
  return {
6143
6155
  comment,
6144
6156
  resolvedOptions: {
@@ -6172,11 +6184,36 @@
6172
6184
  useCompressionStream,
6173
6185
  dataDescriptor,
6174
6186
  zip64,
6175
- rawExtraField
6187
+ rawExtraField,
6188
+ rawLocalExtraField
6176
6189
  }
6177
6190
  };
6178
6191
  }
6179
6192
 
6193
+ function serializeExtraField(extraField) {
6194
+ if (!extraField) {
6195
+ return EMPTY_UINT8_ARRAY;
6196
+ }
6197
+ let extraFieldSize = 0;
6198
+ let offset = 0;
6199
+ extraField.forEach(data => extraFieldSize += 4 + getLength(data));
6200
+ const rawExtraField = new Uint8Array(extraFieldSize);
6201
+ const rawExtraFieldView = getDataView(rawExtraField);
6202
+ extraField.forEach((data, type) => {
6203
+ if (type > MAX_16_BITS) {
6204
+ throw new Error(ERR_INVALID_EXTRAFIELD_TYPE);
6205
+ }
6206
+ if (getLength(data) > MAX_16_BITS) {
6207
+ throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
6208
+ }
6209
+ setUint16(rawExtraFieldView, offset, type);
6210
+ setUint16(rawExtraFieldView, offset + 2, getLength(data));
6211
+ arraySet(rawExtraField, data, offset + 4);
6212
+ offset += 4 + getLength(data);
6213
+ });
6214
+ return rawExtraField;
6215
+ }
6216
+
6180
6217
  async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, options) {
6181
6218
  const { passThrough, zipCrypto, password, rawPassword, encryptionStrength } = metadata;
6182
6219
  let { dataDescriptor, zip64, level, compressionMethod } = metadata;
@@ -6501,12 +6538,9 @@
6501
6538
  msdosAttributes
6502
6539
  };
6503
6540
  let {
6504
- crc32: signature,
6541
+ crc32,
6505
6542
  uncompressedSize
6506
6543
  } = options;
6507
- if (signature === UNDEFINED_VALUE) {
6508
- ({ signature } = options);
6509
- }
6510
6544
  let compressedSize = 0;
6511
6545
  if (!passThrough) {
6512
6546
  uncompressedSize = 0;
@@ -6544,7 +6578,7 @@
6544
6578
  if (!passThrough) {
6545
6579
  uncompressedSize = result.inputSize;
6546
6580
  if (!encrypted || zipCrypto) {
6547
- signature = result.signature;
6581
+ crc32 = result.crc32;
6548
6582
  }
6549
6583
  }
6550
6584
  if ((!zip64CompressedSize && compressedSize >= MAX_32_BITS) ||
@@ -6560,7 +6594,7 @@
6560
6594
 
6561
6595
  }
6562
6596
  setEntryInfo({
6563
- signature,
6597
+ crc32,
6564
6598
  compressedSize,
6565
6599
  uncompressedSize,
6566
6600
  headerInfo,
@@ -6583,8 +6617,8 @@
6583
6617
  version,
6584
6618
  headerArray,
6585
6619
  headerView,
6586
- signature,
6587
- crc32: encrypted && !zipCrypto ? UNDEFINED_VALUE : signature,
6620
+ signature: crc32,
6621
+ crc32: encrypted && !zipCrypto && !passThrough ? UNDEFINED_VALUE : crc32,
6588
6622
  extraFieldExtendedTimestampFlag,
6589
6623
  zip64UncompressedSize,
6590
6624
  zip64CompressedSize
@@ -6605,6 +6639,7 @@
6605
6639
  dataDescriptor,
6606
6640
  directory,
6607
6641
  rawExtraField,
6642
+ rawLocalExtraField,
6608
6643
  encryptionStrength,
6609
6644
  extendedTimestamp,
6610
6645
  ntfsTimestamp,
@@ -6612,7 +6647,8 @@
6612
6647
  encrypted,
6613
6648
  zip64UncompressedSize,
6614
6649
  zip64CompressedSize,
6615
- uncompressedSize
6650
+ uncompressedSize,
6651
+ crc32
6616
6652
  } = options;
6617
6653
  let { version, compressionMethod } = options;
6618
6654
  const compressed = !directory && (compressionMethod === UNDEFINED_VALUE
@@ -6738,11 +6774,14 @@
6738
6774
  }
6739
6775
  if (encrypted && !zipCrypto) {
6740
6776
  version = version > VERSION_AES ? version : VERSION_AES;
6777
+ if (passThrough && crc32 !== UNDEFINED_VALUE) {
6778
+ rawExtraFieldAES[EXTRAFIELD_OFFSET_AES_VENDOR_VERSION] = VENDOR_VERSION_AE_1;
6779
+ }
6741
6780
  rawExtraFieldAES[9] = compressionMethod;
6742
6781
  compressionMethod = COMPRESSION_METHOD_AES;
6743
6782
  }
6744
6783
  const localExtraFieldZip64Length = writeLocalExtraFieldZip64 ? getLength(rawLocalExtraFieldZip64) : 0;
6745
- const extraFieldLength = localExtraFieldZip64Length + getLength(rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField);
6784
+ const extraFieldLength = localExtraFieldZip64Length + getLength(rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField, rawLocalExtraField);
6746
6785
  if (extraFieldLength > MAX_16_BITS) {
6747
6786
  throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
6748
6787
  }
@@ -6776,6 +6815,7 @@
6776
6815
  localHeader.bytes(rawExtraFieldNTFS);
6777
6816
  localHeader.bytes(rawExtraFieldUnix);
6778
6817
  localHeader.bytes(rawExtraField);
6818
+ localHeader.bytes(rawLocalExtraField);
6779
6819
  if (dataDescriptor) {
6780
6820
  if (!zip64CompressedSize) {
6781
6821
  setUint32(localHeaderView, HEADER_OFFSET_COMPRESSED_SIZE + LOCAL_HEADER_COMMON_OFFSET, 0);
@@ -6894,7 +6934,7 @@
6894
6934
  }
6895
6935
 
6896
6936
  function setEntryInfo({
6897
- signature,
6937
+ crc32,
6898
6938
  compressedSize,
6899
6939
  uncompressedSize,
6900
6940
  headerInfo,
@@ -6902,6 +6942,7 @@
6902
6942
  }, {
6903
6943
  zip64,
6904
6944
  zipCrypto,
6945
+ passThrough,
6905
6946
  dataDescriptor
6906
6947
  }) {
6907
6948
  const {
@@ -6912,10 +6953,10 @@
6912
6953
  dataDescriptorView,
6913
6954
  dataDescriptorOffset
6914
6955
  } = dataDescriptorInfo;
6915
- if ((!encrypted || zipCrypto) && signature !== UNDEFINED_VALUE) {
6916
- setUint32(headerView, HEADER_OFFSET_SIGNATURE, signature);
6956
+ if ((!encrypted || zipCrypto || passThrough) && crc32 !== UNDEFINED_VALUE) {
6957
+ setUint32(headerView, HEADER_OFFSET_SIGNATURE, crc32);
6917
6958
  if (dataDescriptor) {
6918
- setUint32(dataDescriptorView, dataDescriptorOffset, signature);
6959
+ setUint32(dataDescriptorView, dataDescriptorOffset, crc32);
6919
6960
  }
6920
6961
  }
6921
6962
  if (zip64) {
@@ -6938,15 +6979,15 @@
6938
6979
  encrypted,
6939
6980
  zip64,
6940
6981
  localExtraFieldZip64Length,
6941
- signature,
6982
+ crc32,
6942
6983
  compressedSize,
6943
6984
  uncompressedSize,
6944
6985
  zip64UncompressedSize,
6945
6986
  zip64CompressedSize
6946
- }, localHeaderView, { dataDescriptor }) {
6987
+ }, localHeaderView, { dataDescriptor, passThrough }) {
6947
6988
  if (!dataDescriptor) {
6948
- if (!encrypted) {
6949
- setUint32(localHeaderView, HEADER_OFFSET_SIGNATURE + LOCAL_HEADER_COMMON_OFFSET, signature);
6989
+ if (!encrypted || (passThrough && crc32 !== UNDEFINED_VALUE)) {
6990
+ setUint32(localHeaderView, HEADER_OFFSET_SIGNATURE + LOCAL_HEADER_COMMON_OFFSET, crc32);
6950
6991
  }
6951
6992
  if (!zip64CompressedSize) {
6952
6993
  setUint32(localHeaderView, HEADER_OFFSET_COMPRESSED_SIZE + LOCAL_HEADER_COMMON_OFFSET, compressedSize);