@zip.js/zip.js 2.8.43 → 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 (56) hide show
  1. package/README.md +0 -37
  2. package/deno.json +21 -1
  3. package/dist/zip-core-external.js +194 -159
  4. package/dist/zip-core-external.min.js +1 -1
  5. package/dist/zip-core.js +194 -131
  6. package/dist/zip-core.min.js +1 -1
  7. package/dist/zip-fs-core-external.js +246 -167
  8. package/dist/zip-fs-core-external.min.js +1 -1
  9. package/dist/zip-fs-core.js +244 -139
  10. package/dist/zip-fs-core.min.js +1 -1
  11. package/dist/zip-fs-external.js +267 -1761
  12. package/dist/zip-fs-external.min.js +1 -1
  13. package/dist/zip-fs-native.js +269 -1735
  14. package/dist/zip-fs-native.min.js +1 -1
  15. package/dist/zip-fs.js +268 -1734
  16. package/dist/zip-fs.min.js +1 -1
  17. package/dist/zip-legacy.js +196 -133
  18. package/dist/zip-legacy.min.js +1 -1
  19. package/dist/zip-native.js +196 -133
  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 +195 -132
  24. package/dist/zip.min.js +1 -1
  25. package/eslint.config.mjs +31 -2
  26. package/index-native.cjs +269 -1735
  27. package/index-native.min.js +1 -1
  28. package/index.cjs +268 -1734
  29. package/index.d.cts +129 -8
  30. package/index.d.ts +129 -8
  31. package/index.min.js +1 -1
  32. package/lib/core/codec-pool.js +6 -2
  33. package/lib/core/codec-worker.js +2 -2
  34. package/lib/core/constants.js +4 -0
  35. package/lib/core/options.js +6 -0
  36. package/lib/core/streams/aes-crypto-stream.js +18 -21
  37. package/lib/core/streams/codec-stream.js +6 -2
  38. package/lib/core/streams/common-crypto.js +2 -0
  39. package/lib/core/streams/zip-entry-stream.js +16 -17
  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 +2 -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-wasm.js +4 -8
  46. package/lib/core/zip-entry.js +11 -1
  47. package/lib/core/zip-fs.js +62 -5
  48. package/lib/core/zip-reader.js +80 -43
  49. package/lib/core/zip-writer.js +68 -45
  50. package/lib/zip-core-external.js +2 -0
  51. package/lib/zip-core-reader.js +2 -0
  52. package/lib/zip-fs-core-external.js +2 -0
  53. package/lib/zip-fs-external.js +2 -0
  54. package/lib/zip-mime-types.js +2 -0
  55. package/package.json +9 -3
  56. 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;
@@ -1369,6 +1371,7 @@
1369
1371
 
1370
1372
  const ERR_INVALID_PASSWORD = "Invalid password";
1371
1373
  const ERR_INVALID_SIGNATURE = "Invalid signature";
1374
+ const ERR_INVALID_AUTHENTICATION_CODE = ERR_INVALID_SIGNATURE;
1372
1375
  const ERR_ABORT_CHECK_PASSWORD = "zipjs-abort-check-password";
1373
1376
  const ERR_UNSUPPORTED_CRYPTO_API = "Crypto API not supported";
1374
1377
 
@@ -1419,7 +1422,7 @@
1419
1422
  const DERIVED_BITS_USAGE = ["deriveBits"];
1420
1423
  const SALT_LENGTH = [8, 12, 16];
1421
1424
  const KEY_LENGTH = [16, 24, 32];
1422
- const SIGNATURE_LENGTH = 10;
1425
+ const AUTHENTICATION_CODE_LENGTH = 10;
1423
1426
  const COUNTER_DEFAULT_VALUE = [0, 0, 0, 0];
1424
1427
  // deno-lint-ignore valid-typeof
1425
1428
  const CRYPTO_API_SUPPORTED = typeof crypto != UNDEFINED_TYPE;
@@ -1435,7 +1438,7 @@
1435
1438
 
1436
1439
  class AESDecryptionStream extends TransformStream {
1437
1440
 
1438
- constructor({ password, rawPassword, encryptionStrength, checkPasswordOnly }) {
1441
+ constructor({ password, rawPassword, encryptionStrength, checkPasswordOnly, checkAuthenticationCode = true }) {
1439
1442
  super({
1440
1443
  start() {
1441
1444
  initAesCrypto(this, password, rawPassword, encryptionStrength);
@@ -1459,8 +1462,8 @@
1459
1462
  } else {
1460
1463
  await ready;
1461
1464
  }
1462
- const output = new Uint8Array(chunk.length - SIGNATURE_LENGTH - ((chunk.length - SIGNATURE_LENGTH) % BLOCK_LENGTH));
1463
- 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));
1464
1467
  },
1465
1468
  async flush(controller) {
1466
1469
  const {
@@ -1471,8 +1474,8 @@
1471
1474
  } = this;
1472
1475
  if (hmac && ctr) {
1473
1476
  await ready;
1474
- const chunkToDecrypt = subarray(pending, 0, pending.length - SIGNATURE_LENGTH);
1475
- 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);
1476
1479
  let decryptedChunkArray = EMPTY_UINT8_ARRAY;
1477
1480
  if (chunkToDecrypt.length) {
1478
1481
  const encryptedChunk = toBits(codecBytes, chunkToDecrypt);
@@ -1480,13 +1483,13 @@
1480
1483
  const decryptedChunk = ctr.update(encryptedChunk);
1481
1484
  decryptedChunkArray = fromBits(codecBytes, decryptedChunk);
1482
1485
  }
1483
- const signature = subarray(fromBits(codecBytes, hmac.digest()), 0, SIGNATURE_LENGTH);
1484
- let invalidSignature = pending.length < SIGNATURE_LENGTH ? 1 : 0;
1485
- for (let indexSignature = 0; indexSignature < SIGNATURE_LENGTH; indexSignature++) {
1486
- 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];
1487
1490
  }
1488
- if (invalidSignature) {
1489
- throw new Error(ERR_INVALID_SIGNATURE);
1491
+ if (invalidAuthenticationCode && checkAuthenticationCode) {
1492
+ throw new Error(ERR_INVALID_AUTHENTICATION_CODE);
1490
1493
  }
1491
1494
  controller.enqueue(decryptedChunkArray);
1492
1495
  }
@@ -1498,8 +1501,6 @@
1498
1501
  class AESEncryptionStream extends TransformStream {
1499
1502
 
1500
1503
  constructor({ password, rawPassword, encryptionStrength }) {
1501
- // deno-lint-ignore prefer-const
1502
- let stream;
1503
1504
  super({
1504
1505
  start() {
1505
1506
  initAesCrypto(this, password, rawPassword, encryptionStrength);
@@ -1538,12 +1539,11 @@
1538
1539
  hmac.update(encryptedChunk);
1539
1540
  encryptedChunkArray = fromBits(codecBytes, encryptedChunk);
1540
1541
  }
1541
- stream.signature = fromBits(codecBytes, hmac.digest()).slice(0, SIGNATURE_LENGTH);
1542
- controller.enqueue(concat(encryptedChunkArray, stream.signature));
1542
+ const authenticationCode = fromBits(codecBytes, hmac.digest()).slice(0, AUTHENTICATION_CODE_LENGTH);
1543
+ controller.enqueue(concat(encryptedChunkArray, authenticationCode));
1543
1544
  }
1544
1545
  }
1545
1546
  });
1546
- stream = this;
1547
1547
  }
1548
1548
  }
1549
1549
 
@@ -1556,7 +1556,7 @@
1556
1556
  });
1557
1557
  }
1558
1558
 
1559
- function append(aesCrypto, input, output, paddingStart, paddingEnd, verifySignature) {
1559
+ function append(aesCrypto, input, output, paddingStart, paddingEnd, verifyAuthenticationCode) {
1560
1560
  const {
1561
1561
  ctr,
1562
1562
  hmac,
@@ -1570,11 +1570,11 @@
1570
1570
  let offset;
1571
1571
  for (offset = 0; offset <= inputLength - BLOCK_LENGTH; offset += BLOCK_LENGTH) {
1572
1572
  const inputChunk = toBits(codecBytes, subarray(input, offset, offset + BLOCK_LENGTH));
1573
- if (verifySignature) {
1573
+ if (verifyAuthenticationCode) {
1574
1574
  hmac.update(inputChunk);
1575
1575
  }
1576
1576
  const outputChunk = ctr.update(inputChunk);
1577
- if (!verifySignature) {
1577
+ if (!verifyAuthenticationCode) {
1578
1578
  hmac.update(outputChunk);
1579
1579
  }
1580
1580
  output.set(fromBits(codecBytes, outputChunk), offset + paddingStart);
@@ -1924,6 +1924,7 @@
1924
1924
 
1925
1925
  const ERR_INVALID_UNCOMPRESSED_SIZE = "Invalid uncompressed size";
1926
1926
  const ERR_INVALID_COMPRESSED_DATA = "Invalid compressed data";
1927
+ const ERR_INVALID_CRC32 = ERR_INVALID_SIGNATURE;
1927
1928
  const ERR_UNSUPPORTED_COMPRESSION$2 = "Compression method not supported";
1928
1929
  const FORMAT_DEFLATE_RAW = "deflate-raw";
1929
1930
  const FORMAT_DEFLATE64_RAW = "deflate64-raw";
@@ -1937,14 +1938,14 @@
1937
1938
 
1938
1939
  constructor(options, { chunkSize, CompressionStreamZlib, CompressionStream }) {
1939
1940
  super({});
1940
- const { compressed, encrypted, useCompressionStream, zipCrypto, signed, level, deflate64, format, compressionMethod } = options;
1941
+ const { compressed, encrypted, useCompressionStream, zipCrypto, computeCrc32, level, deflate64, format, compressionMethod } = options;
1941
1942
  const stream = this;
1942
1943
  let crc32Stream, encryptionStream, gzipCrc32Stream;
1943
1944
  let readable = super.readable;
1944
1945
  const codecStreams = format && getCodecStreams(format);
1945
- const useGzipCrc32 = signed && compressed && !deflate64 && !codecStreams && (!encrypted || zipCrypto) &&
1946
+ const useGzipCrc32 = computeCrc32 && compressed && !deflate64 && !codecStreams && (!encrypted || zipCrypto) &&
1946
1947
  Boolean(useCompressionStream && CompressionStream);
1947
- if ((!encrypted || zipCrypto) && signed && !useGzipCrc32) {
1948
+ if ((!encrypted || zipCrypto) && computeCrc32 && !useGzipCrc32) {
1948
1949
  crc32Stream = new Crc32Stream();
1949
1950
  readable = pipeThrough(readable, crc32Stream);
1950
1951
  }
@@ -1979,14 +1980,9 @@
1979
1980
  }
1980
1981
  }
1981
1982
  setReadable(stream, readable, () => {
1982
- let signature;
1983
- if (encrypted && !zipCrypto) {
1984
- signature = encryptionStream.signature;
1983
+ if ((!encrypted || zipCrypto) && computeCrc32) {
1984
+ stream.crc32 = useGzipCrc32 ? gzipCrc32Stream.crc32 : new DataView(crc32Stream.value.buffer).getUint32(0);
1985
1985
  }
1986
- if ((!encrypted || zipCrypto) && signed) {
1987
- signature = useGzipCrc32 ? gzipCrc32Stream.signature : new DataView(crc32Stream.value.buffer).getUint32(0);
1988
- }
1989
- stream.signature = signature;
1990
1986
  });
1991
1987
  }
1992
1988
  }
@@ -2024,7 +2020,7 @@
2024
2020
  },
2025
2021
  flush() {
2026
2022
  const dataView = getDataView(trailerCandidate);
2027
- stream.signature = dataView.getUint32(0, true);
2023
+ stream.crc32 = dataView.getUint32(0, true);
2028
2024
  stream.uncompressedSize = dataView.getUint32(4, true);
2029
2025
  }
2030
2026
  });
@@ -2106,7 +2102,7 @@
2106
2102
 
2107
2103
  constructor(options, { chunkSize, DecompressionStreamZlib, DecompressionStream }) {
2108
2104
  super({});
2109
- const { zipCrypto, encrypted, signed, signature, compressed, useCompressionStream, deflate64, format, compressionMethod, rawBitFlag, outputSize } = options;
2105
+ const { zipCrypto, encrypted, checkCrc32, crc32, compressed, useCompressionStream, deflate64, format, compressionMethod, rawBitFlag, outputSize } = options;
2110
2106
  let crc32Stream, decryptionStream;
2111
2107
  let readable = super.readable;
2112
2108
  if (encrypted) {
@@ -2139,15 +2135,15 @@
2139
2135
  }
2140
2136
  readable = mapInflateStreamError(readable);
2141
2137
  }
2142
- if ((!encrypted || zipCrypto) && signed) {
2138
+ if (checkCrc32) {
2143
2139
  crc32Stream = new Crc32Stream();
2144
2140
  readable = pipeThrough(readable, crc32Stream);
2145
2141
  }
2146
2142
  setReadable(this, readable, () => {
2147
- if ((!encrypted || zipCrypto) && signed) {
2148
- const dataViewSignature = new DataView(crc32Stream.value.buffer);
2149
- if (signature != dataViewSignature.getUint32(0, false)) {
2150
- throw new Error(ERR_INVALID_SIGNATURE);
2143
+ if (checkCrc32) {
2144
+ const computedCrc32View = new DataView(crc32Stream.value.buffer);
2145
+ if (crc32 != computedCrc32View.getUint32(0, false)) {
2146
+ throw new Error(ERR_INVALID_CRC32);
2151
2147
  }
2152
2148
  }
2153
2149
  });
@@ -2371,9 +2367,9 @@
2371
2367
  }
2372
2368
  },
2373
2369
  flush() {
2374
- const { signature } = stream;
2370
+ const { crc32 } = stream;
2375
2371
  Object.assign(codec, {
2376
- signature,
2372
+ crc32,
2377
2373
  inputSize
2378
2374
  });
2379
2375
  }
@@ -2672,12 +2668,12 @@
2672
2668
  .pipeThrough(new ChunkStream(getChunkSize(config)))
2673
2669
  .pipeTo(writable, { preventClose: true, preventAbort: true });
2674
2670
  const {
2675
- signature,
2671
+ crc32,
2676
2672
  inputSize,
2677
2673
  outputSize
2678
2674
  } = codecStream;
2679
2675
  return {
2680
- signature,
2676
+ crc32,
2681
2677
  inputSize,
2682
2678
  outputSize
2683
2679
  };
@@ -3038,7 +3034,7 @@
3038
3034
 
3039
3035
  async function runWorker(stream, workerOptions) {
3040
3036
  const { options, config } = workerOptions;
3041
- const { transferStreams, useWebWorkers, useCompressionStream, compressed, signed, encrypted, format, codecURI } = options;
3037
+ const { transferStreams, useWebWorkers, useCompressionStream, compressed, checkCrc32, computeCrc32, encrypted, format, codecURI } = options;
3042
3038
  const { workerURI, maxWorkers } = config;
3043
3039
  if (format) {
3044
3040
  if (codecURI) {
@@ -3047,7 +3043,7 @@
3047
3043
  await ensureCodecStreams(format, options.codecURI);
3048
3044
  }
3049
3045
  workerOptions.transferStreams = transferStreams || (transferStreams === UNDEFINED_VALUE && config.transferStreams);
3050
- const streamCopy = !compressed && !signed && !encrypted;
3046
+ const streamCopy = !compressed && !checkCrc32 && !computeCrc32 && !encrypted;
3051
3047
  const workerSupported = format === UNDEFINED_VALUE || Boolean(options.codecURI);
3052
3048
  workerOptions.useWebWorkers = !streamCopy && workerSupported && (useWebWorkers || (useWebWorkers === UNDEFINED_VALUE && config.useWebWorkers));
3053
3049
  workerOptions.workerURI = workerOptions.useWebWorkers && workerURI ? workerURI : UNDEFINED_VALUE;
@@ -4271,9 +4267,12 @@
4271
4267
  const PROPERTY_NAME_EXECUTABLE = "executable";
4272
4268
  const PROPERTY_NAME_COMPRESSION_METHOD = "compressionMethod";
4273
4269
  const PROPERTY_NAME_SIGNATURE = "signature";
4270
+ const PROPERTY_NAME_CRC32 = "crc32";
4274
4271
  const PROPERTY_NAME_EXTRA_FIELD = "extraField";
4275
4272
  const PROPERTY_NAME_EXTRA_FIELD_INFOZIP = "extraFieldInfoZip";
4276
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";
4277
4276
  const PROPERTY_NAME_UID = "uid";
4278
4277
  const PROPERTY_NAME_GID = "gid";
4279
4278
  const PROPERTY_NAME_UNIX_MODE = "unixMode";
@@ -4290,6 +4289,7 @@
4290
4289
  const PROPERTY_NAME_EXTRA_FIELD_AES = "extraFieldAES";
4291
4290
  const PROPERTY_NAME_EXTRA_FIELD_NTFS = "extraFieldNTFS";
4292
4291
  const PROPERTY_NAME_EXTRA_FIELD_EXTENDED_TIMESTAMP = "extraFieldExtendedTimestamp";
4292
+ const PROPERTY_NAME_EXTRA_FIELD_USDZ = "extraFieldUSDZ";
4293
4293
 
4294
4294
  const PROPERTY_NAMES = [
4295
4295
  PROPERTY_NAME_FILENAME,
@@ -4301,6 +4301,7 @@
4301
4301
  PROPERTY_NAME_COMMENT,
4302
4302
  PROPERTY_NAME_RAW_COMMENT,
4303
4303
  PROPERTY_NAME_LAST_ACCESS_DATE,
4304
+ PROPERTY_NAME_RAW_LAST_ACCESS_DATE,
4304
4305
  PROPERTY_NAME_CREATION_DATE,
4305
4306
  PROPERTY_NAME_RAW_CREATION_DATE,
4306
4307
  PROPERTY_NAME_OFFSET,
@@ -4319,9 +4320,12 @@
4319
4320
  PROPERTY_NAME_EXECUTABLE,
4320
4321
  PROPERTY_NAME_COMPRESSION_METHOD,
4321
4322
  PROPERTY_NAME_SIGNATURE,
4323
+ PROPERTY_NAME_CRC32,
4322
4324
  PROPERTY_NAME_EXTRA_FIELD,
4323
4325
  PROPERTY_NAME_EXTRA_FIELD_UNIX,
4324
4326
  PROPERTY_NAME_EXTRA_FIELD_INFOZIP,
4327
+ PROPERTY_NAME_EXTRA_FIELD_UNIX_TYPE1,
4328
+ PROPERTY_NAME_EXTRA_FIELD_PKWARE_UNIX,
4325
4329
  PROPERTY_NAME_UID,
4326
4330
  PROPERTY_NAME_GID,
4327
4331
  PROPERTY_NAME_UNIX_MODE,
@@ -4337,7 +4341,8 @@
4337
4341
  PROPERTY_NAME_EXTRA_FIELD_UNICODE_COMMENT,
4338
4342
  PROPERTY_NAME_EXTRA_FIELD_AES,
4339
4343
  PROPERTY_NAME_EXTRA_FIELD_NTFS,
4340
- PROPERTY_NAME_EXTRA_FIELD_EXTENDED_TIMESTAMP
4344
+ PROPERTY_NAME_EXTRA_FIELD_EXTENDED_TIMESTAMP,
4345
+ PROPERTY_NAME_EXTRA_FIELD_USDZ
4341
4346
  ];
4342
4347
 
4343
4348
  class Entry {
@@ -4390,6 +4395,8 @@
4390
4395
  const OPTION_CHECK_OVERLAPPING_ENTRY = "checkOverlappingEntry";
4391
4396
  const OPTION_CHECK_AMBIGUITY = "checkAmbiguity";
4392
4397
  const OPTION_CHECK_SIGNATURE = "checkSignature";
4398
+ const OPTION_CHECK_CRC32 = "checkCrc32";
4399
+ const OPTION_CHECK_AUTHENTICATION_CODE = "checkAuthenticationCode";
4393
4400
  const OPTION_USE_WEB_WORKERS = "useWebWorkers";
4394
4401
  const OPTION_USE_COMPRESSION_STREAM = "useCompressionStream";
4395
4402
  const OPTION_TRANSFER_STREAMS = "transferStreams";
@@ -4409,6 +4416,7 @@
4409
4416
  const OPTION_OFFSET = "offset";
4410
4417
  const OPTION_USDZ = "usdz";
4411
4418
  const OPTION_UNIX_EXTRA_FIELD_TYPE = "unixExtraFieldType";
4419
+ const OPTION_LOCAL_EXTRA_FIELD = "localExtraField";
4412
4420
  const OPTION_STRICTNESS = "strictness";
4413
4421
  const OPTION_MAX_APPENDED_DATA_SIZE = "maxAppendedDataSize";
4414
4422
  const STRICTNESS_STRICT = "strict";
@@ -4461,6 +4469,7 @@
4461
4469
  const PROPERTY_NAME_UTF8_SUFFIX = "UTF8";
4462
4470
  const CHARSET_CP437 = "cp437";
4463
4471
  const BITFLAG_AMBIGUITY_MASK = BITFLAG_ENCRYPTED | BITFLAG_DATA_DESCRIPTOR | BITFLAG_LANG_ENCODING_FLAG;
4472
+ const VENDOR_VERSION_AE_1$1 = 1;
4464
4473
  const ZIP64_PROPERTIES = [
4465
4474
  [PROPERTY_NAME_UNCOMPRESSED_SIZE, MAX_32_BITS],
4466
4475
  [PROPERTY_NAME_COMPRESSED_SIZE, MAX_32_BITS],
@@ -4853,7 +4862,7 @@
4853
4862
  config,
4854
4863
  bitFlag,
4855
4864
  rawBitFlag,
4856
- signature,
4865
+ crc32,
4857
4866
  rawLastModDate,
4858
4867
  uncompressedSize,
4859
4868
  compressedSize
@@ -4940,6 +4949,11 @@
4940
4949
  if (deflate64) {
4941
4950
  useCompressionStream = false;
4942
4951
  }
4952
+ const checkCrc32Option = getOptionValue$1(zipEntry, options, OPTION_CHECK_CRC32);
4953
+ const checkCrc32 = (checkCrc32Option === UNDEFINED_VALUE ?
4954
+ getOptionValue$1(zipEntry, options, OPTION_CHECK_SIGNATURE) :
4955
+ checkCrc32Option) && !passThrough &&
4956
+ (!encrypted || zipCrypto || (extraFieldAES && extraFieldAES.vendorVersion == VENDOR_VERSION_AE_1$1));
4943
4957
  const workerOptions = {
4944
4958
  options: {
4945
4959
  codecType: CODEC_INFLATE,
@@ -4947,10 +4961,11 @@
4947
4961
  rawPassword,
4948
4962
  zipCrypto,
4949
4963
  encryptionStrength: extraFieldAES && extraFieldAES.strength,
4950
- signed: getOptionValue$1(zipEntry, options, OPTION_CHECK_SIGNATURE) && !passThrough,
4951
- passwordVerification: zipCrypto && (dataDescriptor ? ((rawLastModDate >>> 8) & MAX_8_BITS) : ((signature >>> 24) & MAX_8_BITS)),
4964
+ checkCrc32,
4965
+ checkAuthenticationCode: getOptionValue$1(zipEntry, options, OPTION_CHECK_AUTHENTICATION_CODE),
4966
+ passwordVerification: zipCrypto && (dataDescriptor ? ((rawLastModDate >>> 8) & MAX_8_BITS) : ((crc32 >>> 24) & MAX_8_BITS)),
4952
4967
  outputSize: passThrough ? compressedSize : uncompressedSize,
4953
- signature,
4968
+ crc32,
4954
4969
  compressed: compressionMethod != 0 && !passThrough,
4955
4970
  encrypted,
4956
4971
  useWebWorkers: getOptionValue$1(zipEntry, options, OPTION_USE_WEB_WORKERS),
@@ -4972,7 +4987,7 @@
4972
4987
  fileEntry,
4973
4988
  index,
4974
4989
  offset: localHeaderOffset,
4975
- signature,
4990
+ crc32,
4976
4991
  compressedSize,
4977
4992
  uncompressedSize,
4978
4993
  dataOffset,
@@ -5063,6 +5078,7 @@
5063
5078
  const compressionMethod = getUint16(dataView, offset + 4);
5064
5079
  Object.assign(directory, {
5065
5080
  signature: getUint32(dataView, offset + HEADER_OFFSET_SIGNATURE),
5081
+ crc32: getUint32(dataView, offset + HEADER_OFFSET_SIGNATURE),
5066
5082
  compressedSize: getUint32(dataView, offset + HEADER_OFFSET_COMPRESSED_SIZE),
5067
5083
  uncompressedSize: getUint32(dataView, offset + HEADER_OFFSET_UNCOMPRESSED_SIZE)
5068
5084
  });
@@ -5088,6 +5104,16 @@
5088
5104
  } else {
5089
5105
  directory.compressionMethod = compressionMethod;
5090
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
+ }
5091
5117
  const extraFieldNTFS = extraField.get(EXTRAFIELD_TYPE_NTFS);
5092
5118
  if (extraFieldNTFS) {
5093
5119
  readExtraFieldNTFS(extraFieldNTFS, directory);
@@ -5137,15 +5163,15 @@
5137
5163
  return;
5138
5164
  }
5139
5165
  const extraFieldView = getDataView(extraFieldUnicode.data);
5140
- const crc32 = new Crc32();
5141
- crc32.append(fileEntry[rawPropertyName]);
5142
- const dataViewSignature = getDataView(new Uint8Array(4));
5143
- dataViewSignature.setUint32(0, crc32.get(), true);
5144
- 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);
5145
5171
  Object.assign(extraFieldUnicode, {
5146
5172
  version: getUint8(extraFieldView, 0),
5147
5173
  [propertyName]: decodeText(extraFieldUnicode.data.subarray(5)),
5148
- valid: !fileEntry.bitFlag.languageEncodingFlag && signature == getUint32(dataViewSignature, 0)
5174
+ valid: !fileEntry.bitFlag.languageEncodingFlag && nameCrc32 == getUint32(computedCrc32View, 0)
5149
5175
  });
5150
5176
  if (extraFieldUnicode.valid) {
5151
5177
  directory[propertyName] = extraFieldUnicode[propertyName];
@@ -5164,6 +5190,9 @@
5164
5190
  compressionMethod: getUint16(extraFieldView, 5)
5165
5191
  });
5166
5192
  directory.compressionMethod = extraFieldAES.compressionMethod;
5193
+ if (extraFieldAES.vendorVersion != VENDOR_VERSION_AE_1$1) {
5194
+ directory.crc32 = UNDEFINED_VALUE;
5195
+ }
5167
5196
  }
5168
5197
 
5169
5198
  function readExtraFieldNTFS(extraFieldNTFS, directory) {
@@ -5182,29 +5211,41 @@
5182
5211
  } catch {
5183
5212
  // ignored
5184
5213
  }
5185
- try {
5186
- if (tag1Data && tag1Data.length == 24) {
5187
- const tag1View = getDataView(tag1Data);
5188
- const rawLastModDate = tag1View.getBigUint64(0, true);
5189
- const rawLastAccessDate = tag1View.getBigUint64(8, true);
5190
- const rawCreationDate = tag1View.getBigUint64(16, true);
5191
- Object.assign(extraFieldNTFS, {
5192
- rawLastModDate,
5193
- rawLastAccessDate,
5194
- rawCreationDate
5195
- });
5196
- const lastModDate = getDateNTFS(rawLastModDate);
5197
- const lastAccessDate = getDateNTFS(rawLastAccessDate);
5198
- const creationDate = getDateNTFS(rawCreationDate);
5199
- const extraFieldData = { lastModDate, lastAccessDate, creationDate };
5200
- Object.assign(extraFieldNTFS, extraFieldData);
5201
- Object.assign(directory, extraFieldData);
5202
- }
5203
- } catch {
5204
- // ignored
5214
+ if (tag1Data && tag1Data.length == 24) {
5215
+ const tag1View = getDataView(tag1Data);
5216
+ const rawLastModDate = tag1View.getBigUint64(0, true);
5217
+ const rawLastAccessDate = tag1View.getBigUint64(8, true);
5218
+ const rawCreationDate = tag1View.getBigUint64(16, true);
5219
+ Object.assign(extraFieldNTFS, {
5220
+ rawLastModDate,
5221
+ rawLastAccessDate,
5222
+ rawCreationDate
5223
+ });
5224
+ const lastModDate = getDateNTFS(rawLastModDate);
5225
+ const lastAccessDate = getDateNTFS(rawLastAccessDate);
5226
+ const creationDate = getDateNTFS(rawCreationDate);
5227
+ const extraFieldData = { lastModDate, lastAccessDate, creationDate };
5228
+ Object.assign(extraFieldNTFS, extraFieldData);
5229
+ Object.assign(directory, extraFieldData);
5205
5230
  }
5206
5231
  }
5207
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
+
5208
5249
  function readExtraFieldUnix(extraField, directory, isInfoZip) {
5209
5250
  try {
5210
5251
  const view = getDataView(extraField.data);
@@ -5283,7 +5324,7 @@
5283
5324
  fileEntry,
5284
5325
  index,
5285
5326
  offset,
5286
- signature,
5327
+ crc32,
5287
5328
  compressedSize,
5288
5329
  uncompressedSize,
5289
5330
  dataOffset,
@@ -5304,7 +5345,7 @@
5304
5345
  const dataDescriptorSignature = dataDescriptorArray.length == dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH &&
5305
5346
  getUint32(getDataView(dataDescriptorArray), 0) == DATA_DESCRIPTOR_RECORD_SIGNATURE;
5306
5347
  if (dataDescriptorSignature) {
5307
- const readSignature = getUint32(getDataView(dataDescriptorArray), 4);
5348
+ const readCrc32 = getUint32(getDataView(dataDescriptorArray), 4);
5308
5349
  let readCompressedSize;
5309
5350
  let readUncompressedSize;
5310
5351
  if (extraFieldZip64) {
@@ -5314,8 +5355,8 @@
5314
5355
  readCompressedSize = getUint32(getDataView(dataDescriptorArray), 8);
5315
5356
  readUncompressedSize = getUint32(getDataView(dataDescriptorArray), 12);
5316
5357
  }
5317
- const matchSignature = (fileEntry.encrypted && !fileEntry.zipCrypto) || readSignature == signature;
5318
- if (matchSignature &&
5358
+ const matchCrc32 = (fileEntry.encrypted && !fileEntry.zipCrypto) || readCrc32 == crc32;
5359
+ if (matchCrc32 &&
5319
5360
  readCompressedSize == compressedSize &&
5320
5361
  readUncompressedSize == uncompressedSize) {
5321
5362
  dataDescriptorLength += DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH;
@@ -5484,11 +5525,11 @@
5484
5525
  throwAmbiguousArchive("mismatched local file header (compression method)");
5485
5526
  }
5486
5527
  if (!localDirectory.bitFlag.dataDescriptor &&
5487
- (localDirectory.signature || localDirectory.compressedSize || localDirectory.uncompressedSize) &&
5488
- (localDirectory.signature != zipEntry.signature ||
5528
+ (localDirectory.crc32 || localDirectory.compressedSize || localDirectory.uncompressedSize) &&
5529
+ (localDirectory.crc32 != zipEntry.crc32 ||
5489
5530
  localDirectory.compressedSize != zipEntry.compressedSize ||
5490
5531
  localDirectory.uncompressedSize != zipEntry.uncompressedSize)) {
5491
- throwAmbiguousArchive("mismatched local file header (signature or sizes)");
5532
+ throwAmbiguousArchive("mismatched local file header (crc32 or sizes)");
5492
5533
  }
5493
5534
  }
5494
5535
 
@@ -5504,11 +5545,7 @@
5504
5545
 
5505
5546
  function getDate(timeRaw) {
5506
5547
  const date = (timeRaw & 0xffff0000) >> 16, time = timeRaw & MAX_16_BITS;
5507
- try {
5508
- return new Date(1980 + ((date & 0xFE00) >> 9), ((date & 0x01E0) >> 5) - 1, date & 0x001F, (time & 0xF800) >> 11, (time & 0x07E0) >> 5, (time & 0x001F) * 2, 0);
5509
- } catch {
5510
- // ignored
5511
- }
5548
+ return new Date(1980 + ((date & 0xFE00) >> 9), ((date & 0x01E0) >> 5) - 1, date & 0x001F, (time & 0xF800) >> 11, (time & 0x07E0) >> 5, (time & 0x001F) * 2, 0);
5512
5549
  }
5513
5550
 
5514
5551
  function getDateNTFS(timeRaw) {
@@ -5541,7 +5578,9 @@
5541
5578
  ERR_EOCDR_LOCATOR_ZIP64_NOT_FOUND: ERR_EOCDR_LOCATOR_ZIP64_NOT_FOUND,
5542
5579
  ERR_EOCDR_NOT_FOUND: ERR_EOCDR_NOT_FOUND,
5543
5580
  ERR_EXTRAFIELD_ZIP64_NOT_FOUND: ERR_EXTRAFIELD_ZIP64_NOT_FOUND,
5581
+ ERR_INVALID_AUTHENTICATION_CODE: ERR_INVALID_AUTHENTICATION_CODE,
5544
5582
  ERR_INVALID_COMPRESSED_DATA: ERR_INVALID_COMPRESSED_DATA,
5583
+ ERR_INVALID_CRC32: ERR_INVALID_CRC32,
5545
5584
  ERR_INVALID_PASSWORD: ERR_INVALID_PASSWORD,
5546
5585
  ERR_INVALID_SIGNATURE: ERR_INVALID_SIGNATURE,
5547
5586
  ERR_INVALID_UNCOMPRESSED_SIZE: ERR_INVALID_UNCOMPRESSED_SIZE,
@@ -5595,6 +5634,8 @@
5595
5634
  const ERR_UNSUPPORTED_COMPRESSION = "Compression method not supported";
5596
5635
  const MIN_UNIX_TIME = -2147483648;
5597
5636
  const MAX_UNIX_TIME = 2147483647;
5637
+ const MIN_NTFS_TIME = BigInt(0);
5638
+ const MAX_NTFS_TIME = BigInt("0x7fffffffffffffff");
5598
5639
  const ERR_UNSUPPORTED_FORMAT = "Zip64 is not supported (set the 'zip64' option to 'true')";
5599
5640
  const ERR_UNDEFINED_UNCOMPRESSED_SIZE = "Undefined uncompressed size";
5600
5641
  const ERR_UNDEFINED_READER = "Undefined reader";
@@ -5608,6 +5649,8 @@
5608
5649
  const ERR_INVALID_MSDOS_DATA = "Invalid msdosAttributes (must be an object with boolean flags)";
5609
5650
 
5610
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;
5611
5654
  const INFOZIP_EXTRA_FIELD_TYPE = "infozip";
5612
5655
  const UNIX_EXTRA_FIELD_TYPE = "unix";
5613
5656
 
@@ -5702,9 +5745,9 @@
5702
5745
  zip64UncompressedSize,
5703
5746
  extraFieldLength
5704
5747
  });
5705
- const { signature } = entry;
5706
- if (signature !== UNDEFINED_VALUE) {
5707
- setUint32(headerView, HEADER_OFFSET_SIGNATURE, signature);
5748
+ const { crc32 } = entry;
5749
+ if (crc32 !== UNDEFINED_VALUE) {
5750
+ setUint32(headerView, HEADER_OFFSET_SIGNATURE, crc32);
5708
5751
  }
5709
5752
  Object.assign(entry, {
5710
5753
  zip64UncompressedSize,
@@ -5889,6 +5932,7 @@
5889
5932
  internalFileAttribute: metadataInfo.resolvedOptions.internalFileAttributes,
5890
5933
  externalFileAttribute: attributesInfo.resolvedOptions.externalFileAttributes,
5891
5934
  signature: options[PROPERTY_NAME_SIGNATURE],
5935
+ crc32: options.crc32 === UNDEFINED_VALUE ? options[PROPERTY_NAME_SIGNATURE] : options.crc32,
5892
5936
  offset: zipWriter.offset - diskOffset,
5893
5937
  diskNumberStart: diskNumber
5894
5938
  });
@@ -6105,27 +6149,8 @@
6105
6149
  if (!zipCrypto && (password !== UNDEFINED_VALUE || rawPassword !== UNDEFINED_VALUE) && !(encryptionStrength >= 1 && encryptionStrength <= 3)) {
6106
6150
  throw new Error(ERR_INVALID_ENCRYPTION_STRENGTH);
6107
6151
  }
6108
- let rawExtraField = EMPTY_UINT8_ARRAY;
6109
- const extraField = options[PROPERTY_NAME_EXTRA_FIELD];
6110
- if (extraField) {
6111
- let extraFieldSize = 0;
6112
- let offset = 0;
6113
- extraField.forEach(data => extraFieldSize += 4 + getLength(data));
6114
- rawExtraField = new Uint8Array(extraFieldSize);
6115
- const rawExtraFieldView = getDataView(rawExtraField);
6116
- extraField.forEach((data, type) => {
6117
- if (type > MAX_16_BITS) {
6118
- throw new Error(ERR_INVALID_EXTRAFIELD_TYPE);
6119
- }
6120
- if (getLength(data) > MAX_16_BITS) {
6121
- throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
6122
- }
6123
- setUint16(rawExtraFieldView, offset, type);
6124
- setUint16(rawExtraFieldView, offset + 2, getLength(data));
6125
- arraySet(rawExtraField, data, offset + 4);
6126
- offset += 4 + getLength(data);
6127
- });
6128
- }
6152
+ const rawExtraField = serializeExtraField(options[PROPERTY_NAME_EXTRA_FIELD]);
6153
+ const rawLocalExtraField = serializeExtraField(options[OPTION_LOCAL_EXTRA_FIELD]);
6129
6154
  return {
6130
6155
  comment,
6131
6156
  resolvedOptions: {
@@ -6159,11 +6184,36 @@
6159
6184
  useCompressionStream,
6160
6185
  dataDescriptor,
6161
6186
  zip64,
6162
- rawExtraField
6187
+ rawExtraField,
6188
+ rawLocalExtraField
6163
6189
  }
6164
6190
  };
6165
6191
  }
6166
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
+
6167
6217
  async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, options) {
6168
6218
  const { passThrough, zipCrypto, password, rawPassword, encryptionStrength } = metadata;
6169
6219
  let { dataDescriptor, zip64, level, compressionMethod } = metadata;
@@ -6488,7 +6538,7 @@
6488
6538
  msdosAttributes
6489
6539
  };
6490
6540
  let {
6491
- signature,
6541
+ crc32,
6492
6542
  uncompressedSize
6493
6543
  } = options;
6494
6544
  let compressedSize = 0;
@@ -6508,7 +6558,7 @@
6508
6558
  encryptionStrength,
6509
6559
  zipCrypto: encrypted && zipCrypto,
6510
6560
  passwordVerification: encrypted && zipCrypto && (rawLastModDate >> 8) & MAX_8_BITS,
6511
- signed: !passThrough,
6561
+ computeCrc32: !passThrough,
6512
6562
  compressed: compressed && !passThrough,
6513
6563
  encrypted: encrypted && !passThrough,
6514
6564
  useWebWorkers,
@@ -6527,7 +6577,9 @@
6527
6577
  writer.size += compressedSize;
6528
6578
  if (!passThrough) {
6529
6579
  uncompressedSize = result.inputSize;
6530
- signature = result.signature;
6580
+ if (!encrypted || zipCrypto) {
6581
+ crc32 = result.crc32;
6582
+ }
6531
6583
  }
6532
6584
  if ((!zip64CompressedSize && compressedSize >= MAX_32_BITS) ||
6533
6585
  (!zip64UncompressedSize && uncompressedSize >= MAX_32_BITS)) {
@@ -6542,7 +6594,7 @@
6542
6594
 
6543
6595
  }
6544
6596
  setEntryInfo({
6545
- signature,
6597
+ crc32,
6546
6598
  compressedSize,
6547
6599
  uncompressedSize,
6548
6600
  headerInfo,
@@ -6565,7 +6617,8 @@
6565
6617
  version,
6566
6618
  headerArray,
6567
6619
  headerView,
6568
- signature,
6620
+ signature: crc32,
6621
+ crc32: encrypted && !zipCrypto && !passThrough ? UNDEFINED_VALUE : crc32,
6569
6622
  extraFieldExtendedTimestampFlag,
6570
6623
  zip64UncompressedSize,
6571
6624
  zip64CompressedSize
@@ -6586,6 +6639,7 @@
6586
6639
  dataDescriptor,
6587
6640
  directory,
6588
6641
  rawExtraField,
6642
+ rawLocalExtraField,
6589
6643
  encryptionStrength,
6590
6644
  extendedTimestamp,
6591
6645
  ntfsTimestamp,
@@ -6593,7 +6647,8 @@
6593
6647
  encrypted,
6594
6648
  zip64UncompressedSize,
6595
6649
  zip64CompressedSize,
6596
- uncompressedSize
6650
+ uncompressedSize,
6651
+ crc32
6597
6652
  } = options;
6598
6653
  let { version, compressionMethod } = options;
6599
6654
  const compressed = !directory && (compressionMethod === UNDEFINED_VALUE
@@ -6666,8 +6721,8 @@
6666
6721
  extraFieldNTFS.uint16(EXTRAFIELD_TYPE_NTFS_TAG1);
6667
6722
  extraFieldNTFS.uint16(24);
6668
6723
  extraFieldNTFS.uint64(lastModTimeNTFS);
6669
- extraFieldNTFS.uint64(getTimeNTFS(lastAccessDate) || lastModTimeNTFS);
6670
- extraFieldNTFS.uint64(getTimeNTFS(creationDate) || lastModTimeNTFS);
6724
+ extraFieldNTFS.uint64(lastAccessDate ? getTimeNTFS(lastAccessDate) : lastModTimeNTFS);
6725
+ extraFieldNTFS.uint64(creationDate ? getTimeNTFS(creationDate) : lastModTimeNTFS);
6671
6726
  rawExtraFieldNTFS = extraFieldNTFS.array;
6672
6727
  } catch {
6673
6728
  rawExtraFieldNTFS = EMPTY_UINT8_ARRAY;
@@ -6719,15 +6774,18 @@
6719
6774
  }
6720
6775
  if (encrypted && !zipCrypto) {
6721
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
+ }
6722
6780
  rawExtraFieldAES[9] = compressionMethod;
6723
6781
  compressionMethod = COMPRESSION_METHOD_AES;
6724
6782
  }
6725
6783
  const localExtraFieldZip64Length = writeLocalExtraFieldZip64 ? getLength(rawLocalExtraFieldZip64) : 0;
6726
- const extraFieldLength = localExtraFieldZip64Length + getLength(rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField);
6784
+ const extraFieldLength = localExtraFieldZip64Length + getLength(rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField, rawLocalExtraField);
6727
6785
  if (extraFieldLength > MAX_16_BITS) {
6728
6786
  throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
6729
6787
  }
6730
- const dosLastModDate = new Date(Math.ceil(lastModDate.getTime() / 2000) * 2000);
6788
+ const dosLastModDate = new Date(Math.ceil(Math.floor(lastModDate.getTime() / 1000) / 2) * 2000);
6731
6789
  const {
6732
6790
  headerArray,
6733
6791
  headerView,
@@ -6757,6 +6815,7 @@
6757
6815
  localHeader.bytes(rawExtraFieldNTFS);
6758
6816
  localHeader.bytes(rawExtraFieldUnix);
6759
6817
  localHeader.bytes(rawExtraField);
6818
+ localHeader.bytes(rawLocalExtraField);
6760
6819
  if (dataDescriptor) {
6761
6820
  if (!zip64CompressedSize) {
6762
6821
  setUint32(localHeaderView, HEADER_OFFSET_COMPRESSED_SIZE + LOCAL_HEADER_COMMON_OFFSET, 0);
@@ -6875,7 +6934,7 @@
6875
6934
  }
6876
6935
 
6877
6936
  function setEntryInfo({
6878
- signature,
6937
+ crc32,
6879
6938
  compressedSize,
6880
6939
  uncompressedSize,
6881
6940
  headerInfo,
@@ -6883,6 +6942,7 @@
6883
6942
  }, {
6884
6943
  zip64,
6885
6944
  zipCrypto,
6945
+ passThrough,
6886
6946
  dataDescriptor
6887
6947
  }) {
6888
6948
  const {
@@ -6893,10 +6953,10 @@
6893
6953
  dataDescriptorView,
6894
6954
  dataDescriptorOffset
6895
6955
  } = dataDescriptorInfo;
6896
- if ((!encrypted || zipCrypto) && signature !== UNDEFINED_VALUE) {
6897
- setUint32(headerView, HEADER_OFFSET_SIGNATURE, signature);
6956
+ if ((!encrypted || zipCrypto || passThrough) && crc32 !== UNDEFINED_VALUE) {
6957
+ setUint32(headerView, HEADER_OFFSET_SIGNATURE, crc32);
6898
6958
  if (dataDescriptor) {
6899
- setUint32(dataDescriptorView, dataDescriptorOffset, signature);
6959
+ setUint32(dataDescriptorView, dataDescriptorOffset, crc32);
6900
6960
  }
6901
6961
  }
6902
6962
  if (zip64) {
@@ -6919,15 +6979,15 @@
6919
6979
  encrypted,
6920
6980
  zip64,
6921
6981
  localExtraFieldZip64Length,
6922
- signature,
6982
+ crc32,
6923
6983
  compressedSize,
6924
6984
  uncompressedSize,
6925
6985
  zip64UncompressedSize,
6926
6986
  zip64CompressedSize
6927
- }, localHeaderView, { dataDescriptor }) {
6987
+ }, localHeaderView, { dataDescriptor, passThrough }) {
6928
6988
  if (!dataDescriptor) {
6929
- if (!encrypted) {
6930
- 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);
6931
6991
  }
6932
6992
  if (!zip64CompressedSize) {
6933
6993
  setUint32(localHeaderView, HEADER_OFFSET_COMPRESSED_SIZE + LOCAL_HEADER_COMMON_OFFSET, compressedSize);
@@ -7236,7 +7296,8 @@
7236
7296
 
7237
7297
  function getTimeNTFS(date) {
7238
7298
  if (date) {
7239
- return ((BigInt(date.getTime()) + BigInt(11644473600000)) * BigInt(10000));
7299
+ const timeNTFS = ((BigInt(date.getTime()) + BigInt(11644473600000)) * BigInt(10000));
7300
+ return timeNTFS < MIN_NTFS_TIME ? MIN_NTFS_TIME : timeNTFS > MAX_NTFS_TIME ? MAX_NTFS_TIME : timeNTFS;
7240
7301
  }
7241
7302
  }
7242
7303
 
@@ -7841,10 +7902,12 @@
7841
7902
  exports.ERR_EXTRAFIELD_ZIP64_NOT_FOUND = ERR_EXTRAFIELD_ZIP64_NOT_FOUND;
7842
7903
  exports.ERR_HTTP_RANGE = ERR_HTTP_RANGE;
7843
7904
  exports.ERR_HTTP_RESOURCE_CHANGED = ERR_HTTP_RESOURCE_CHANGED;
7905
+ exports.ERR_INVALID_AUTHENTICATION_CODE = ERR_INVALID_AUTHENTICATION_CODE;
7844
7906
  exports.ERR_INVALID_CODEC_DEFINITION = ERR_INVALID_CODEC_DEFINITION;
7845
7907
  exports.ERR_INVALID_CODEC_MODULE = ERR_INVALID_CODEC_MODULE;
7846
7908
  exports.ERR_INVALID_COMMENT = ERR_INVALID_COMMENT;
7847
7909
  exports.ERR_INVALID_COMPRESSED_DATA = ERR_INVALID_COMPRESSED_DATA;
7910
+ exports.ERR_INVALID_CRC32 = ERR_INVALID_CRC32;
7848
7911
  exports.ERR_INVALID_ENCRYPTION_STRENGTH = ERR_INVALID_ENCRYPTION_STRENGTH;
7849
7912
  exports.ERR_INVALID_ENTRY_COMMENT = ERR_INVALID_ENTRY_COMMENT;
7850
7913
  exports.ERR_INVALID_ENTRY_NAME = ERR_INVALID_ENTRY_NAME;