@zip.js/zip.js 2.8.42 → 2.8.44

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 (46) hide show
  1. package/README.md +0 -37
  2. package/deno.json +1 -1
  3. package/dist/zip-core-external.js +178 -77
  4. package/dist/zip-core-external.min.js +1 -1
  5. package/dist/zip-core.js +179 -76
  6. package/dist/zip-core.min.js +1 -1
  7. package/dist/zip-fs-core-external.js +178 -77
  8. package/dist/zip-fs-core-external.min.js +1 -1
  9. package/dist/zip-fs-core.js +177 -76
  10. package/dist/zip-fs-core.min.js +1 -1
  11. package/dist/zip-fs-external.js +178 -77
  12. package/dist/zip-fs-external.min.js +1 -1
  13. package/dist/zip-fs-native.js +180 -77
  14. package/dist/zip-fs-native.min.js +1 -1
  15. package/dist/zip-fs.js +180 -77
  16. package/dist/zip-fs.min.js +1 -1
  17. package/dist/zip-legacy.js +180 -77
  18. package/dist/zip-legacy.min.js +1 -1
  19. package/dist/zip-native.js +180 -77
  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 +180 -77
  24. package/dist/zip.min.js +1 -1
  25. package/index-native.cjs +180 -77
  26. package/index-native.min.js +1 -1
  27. package/index.cjs +180 -77
  28. package/index.d.cts +80 -7
  29. package/index.d.ts +80 -7
  30. package/index.min.js +1 -1
  31. package/lib/core/codec-pool.js +6 -2
  32. package/lib/core/codec-worker.js +23 -2
  33. package/lib/core/options.js +4 -0
  34. package/lib/core/streams/aes-crypto-stream.js +4 -4
  35. package/lib/core/streams/codec-stream.js +8 -2
  36. package/lib/core/streams/common-crypto.js +2 -0
  37. package/lib/core/streams/zip-entry-stream.js +102 -36
  38. package/lib/core/web-worker-inline-native.js +1 -1
  39. package/lib/core/web-worker-inline-wasm.js +1 -1
  40. package/lib/core/web-worker-wasm.js +4 -8
  41. package/lib/core/zip-entry.js +3 -0
  42. package/lib/core/zip-reader.js +35 -26
  43. package/lib/core/zip-writer.js +22 -10
  44. package/lib/zip-core-reader.js +2 -0
  45. package/package.json +1 -1
  46. package/worker-message-property-names.js +1 -1
@@ -2315,6 +2315,7 @@
2315
2315
 
2316
2316
  const ERR_INVALID_PASSWORD = "Invalid password";
2317
2317
  const ERR_INVALID_SIGNATURE = "Invalid signature";
2318
+ const ERR_INVALID_AUTHENTICATION_CODE = ERR_INVALID_SIGNATURE;
2318
2319
  const ERR_ABORT_CHECK_PASSWORD = "zipjs-abort-check-password";
2319
2320
  const ERR_UNSUPPORTED_CRYPTO_API = "Crypto API not supported";
2320
2321
 
@@ -2381,7 +2382,7 @@
2381
2382
 
2382
2383
  class AESDecryptionStream extends TransformStream {
2383
2384
 
2384
- constructor({ password, rawPassword, encryptionStrength, checkPasswordOnly }) {
2385
+ constructor({ password, rawPassword, encryptionStrength, checkPasswordOnly, checkAuthenticationCode = true }) {
2385
2386
  super({
2386
2387
  start() {
2387
2388
  initAesCrypto(this, password, rawPassword, encryptionStrength);
@@ -2431,8 +2432,8 @@
2431
2432
  for (let indexSignature = 0; indexSignature < SIGNATURE_LENGTH; indexSignature++) {
2432
2433
  invalidSignature |= signature[indexSignature] ^ originalSignature[indexSignature];
2433
2434
  }
2434
- if (invalidSignature) {
2435
- throw new Error(ERR_INVALID_SIGNATURE);
2435
+ if (invalidSignature && checkAuthenticationCode) {
2436
+ throw new Error(ERR_INVALID_AUTHENTICATION_CODE);
2436
2437
  }
2437
2438
  controller.enqueue(decryptedChunkArray);
2438
2439
  }
@@ -2803,6 +2804,7 @@
2803
2804
 
2804
2805
  const ERR_INVALID_UNCOMPRESSED_SIZE = "Invalid uncompressed size";
2805
2806
  const ERR_INVALID_COMPRESSED_DATA = "Invalid compressed data";
2807
+ const ERR_INVALID_CRC32 = ERR_INVALID_SIGNATURE;
2806
2808
  const ERR_UNSUPPORTED_COMPRESSION$2 = "Compression method not supported";
2807
2809
  const FORMAT_DEFLATE_RAW = "deflate-raw";
2808
2810
  const FORMAT_DEFLATE64_RAW = "deflate64-raw";
@@ -2810,19 +2812,20 @@
2810
2812
  const GZIP_HEADER_LENGTH = 10;
2811
2813
  const GZIP_TRAILER_LENGTH = 8;
2812
2814
  const GZIP_HEADER_BYTES = [0x1f, 0x8b, 0x08];
2815
+ const GZIP_OUTPUT_STALL_TIMEOUT = 5000;
2813
2816
 
2814
2817
  class DeflateStream extends TransformStream {
2815
2818
 
2816
2819
  constructor(options, { chunkSize, CompressionStreamZlib, CompressionStream }) {
2817
2820
  super({});
2818
- const { compressed, encrypted, useCompressionStream, zipCrypto, signed, level, deflate64, format, compressionMethod } = options;
2821
+ const { compressed, encrypted, useCompressionStream, zipCrypto, computeCrc32, level, deflate64, format, compressionMethod } = options;
2819
2822
  const stream = this;
2820
2823
  let crc32Stream, encryptionStream, gzipCrc32Stream;
2821
2824
  let readable = super.readable;
2822
2825
  const codecStreams = format && getCodecStreams(format);
2823
- const useGzipCrc32 = signed && compressed && !deflate64 && !codecStreams && (!encrypted || zipCrypto) &&
2826
+ const useGzipCrc32 = computeCrc32 && compressed && !deflate64 && !codecStreams && (!encrypted || zipCrypto) &&
2824
2827
  Boolean(useCompressionStream && CompressionStream);
2825
- if ((!encrypted || zipCrypto) && signed && !useGzipCrc32) {
2828
+ if ((!encrypted || zipCrypto) && computeCrc32 && !useGzipCrc32) {
2826
2829
  crc32Stream = new Crc32Stream();
2827
2830
  readable = pipeThrough(readable, crc32Stream);
2828
2831
  }
@@ -2861,7 +2864,7 @@
2861
2864
  if (encrypted && !zipCrypto) {
2862
2865
  signature = encryptionStream.signature;
2863
2866
  }
2864
- if ((!encrypted || zipCrypto) && signed) {
2867
+ if ((!encrypted || zipCrypto) && computeCrc32) {
2865
2868
  signature = useGzipCrc32 ? gzipCrc32Stream.signature : new DataView(crc32Stream.value.buffer).getUint32(0);
2866
2869
  }
2867
2870
  stream.signature = signature;
@@ -2910,26 +2913,73 @@
2910
2913
  }
2911
2914
  }
2912
2915
 
2913
- class RawDeflateToGzipStream extends TransformStream {
2916
+ function pipeThroughGzipDecompressionStream(readable, gzipStream, outputSize) {
2917
+ const crc32 = new Crc32();
2918
+ let outputLength = 0;
2919
+ let inputDone = false;
2920
+ let watchdogTimeout;
2921
+ let resolveTrailerReady, rejectTrailerReady;
2922
+ const trailerReady = new Promise((resolve, reject) => {
2923
+ resolveTrailerReady = resolve;
2924
+ rejectTrailerReady = reject;
2925
+ });
2926
+ trailerReady.catch(() => { });
2927
+ if (!outputSize) {
2928
+ resolveTrailerReady();
2929
+ }
2930
+ const gzipWrapStream = new TransformStream({
2931
+ start(controller) {
2932
+ const header = new Uint8Array(GZIP_HEADER_LENGTH);
2933
+ header.set(GZIP_HEADER_BYTES);
2934
+ controller.enqueue(header);
2935
+ },
2936
+ transform(chunk, controller) {
2937
+ controller.enqueue(chunk);
2938
+ },
2939
+ async flush(controller) {
2940
+ inputDone = true;
2941
+ startWatchdog();
2942
+ try {
2943
+ await trailerReady;
2944
+ } finally {
2945
+ stopWatchdog();
2946
+ }
2947
+ const trailer = new Uint8Array(GZIP_TRAILER_LENGTH);
2948
+ const dataView = getDataView(trailer);
2949
+ dataView.setUint32(0, crc32.get(), true);
2950
+ dataView.setUint32(4, outputSize, true);
2951
+ controller.enqueue(trailer);
2952
+ },
2953
+ cancel(reason) {
2954
+ rejectTrailerReady(reason);
2955
+ }
2956
+ });
2957
+ const outputStream = new TransformStream({
2958
+ transform(chunk, controller) {
2959
+ crc32.append(chunk);
2960
+ outputLength += chunk.length;
2961
+ if (outputLength >= outputSize) {
2962
+ resolveTrailerReady();
2963
+ } else if (inputDone) {
2964
+ startWatchdog();
2965
+ }
2966
+ controller.enqueue(chunk);
2967
+ },
2968
+ cancel(reason) {
2969
+ rejectTrailerReady(reason);
2970
+ }
2971
+ });
2972
+ readable = pipeThrough(readable, gzipWrapStream);
2973
+ readable = pipeThroughBackpressured(readable, gzipStream);
2974
+ return pipeThrough(readable, outputStream);
2914
2975
 
2915
- constructor(signature, uncompressedSize) {
2916
- super({
2917
- start(controller) {
2918
- const header = new Uint8Array(GZIP_HEADER_LENGTH);
2919
- header.set(GZIP_HEADER_BYTES);
2920
- controller.enqueue(header);
2921
- },
2922
- transform(chunk, controller) {
2923
- controller.enqueue(chunk);
2924
- },
2925
- flush(controller) {
2926
- const trailer = new Uint8Array(GZIP_TRAILER_LENGTH);
2927
- const dataView = getDataView(trailer);
2928
- dataView.setUint32(0, signature, true);
2929
- dataView.setUint32(4, uncompressedSize, true);
2930
- controller.enqueue(trailer);
2931
- }
2932
- });
2976
+ function startWatchdog() {
2977
+ stopWatchdog();
2978
+ watchdogTimeout = setTimeout(() => rejectTrailerReady(new Error(ERR_INVALID_UNCOMPRESSED_SIZE)), GZIP_OUTPUT_STALL_TIMEOUT);
2979
+ }
2980
+
2981
+ function stopWatchdog() {
2982
+ clearTimeout(watchdogTimeout);
2933
2983
  }
2934
2984
  }
2935
2985
 
@@ -2937,7 +2987,7 @@
2937
2987
 
2938
2988
  constructor(options, { chunkSize, DecompressionStreamZlib, DecompressionStream }) {
2939
2989
  super({});
2940
- const { zipCrypto, encrypted, signed, signature, compressed, useCompressionStream, deflate64, format, compressionMethod, rawBitFlag, outputSize } = options;
2990
+ const { zipCrypto, encrypted, checkCrc32, signature, compressed, useCompressionStream, deflate64, format, compressionMethod, rawBitFlag, outputSize } = options;
2941
2991
  let crc32Stream, decryptionStream;
2942
2992
  let readable = super.readable;
2943
2993
  if (encrypted) {
@@ -2956,7 +3006,7 @@
2956
3006
  try {
2957
3007
  readable = pipeThroughCompressionStream(readable, useCompressionStream, { chunkSize, deflate64 }, DecompressionStream, DecompressionStreamZlib);
2958
3008
  } catch (error) {
2959
- if (deflate64 || (encrypted && !zipCrypto) || signature === UNDEFINED_VALUE || outputSize === UNDEFINED_VALUE) {
3009
+ if (deflate64 || outputSize === UNDEFINED_VALUE) {
2960
3010
  throw error;
2961
3011
  }
2962
3012
  let gzipStream;
@@ -2965,46 +3015,58 @@
2965
3015
  } catch {
2966
3016
  throw error;
2967
3017
  }
2968
- readable = pipeThrough(readable, new RawDeflateToGzipStream(signature, outputSize));
2969
- readable = pipeThroughBackpressured(readable, gzipStream);
3018
+ readable = pipeThroughGzipDecompressionStream(readable, gzipStream, outputSize);
2970
3019
  }
2971
3020
  }
2972
3021
  readable = mapInflateStreamError(readable);
2973
3022
  }
2974
- if ((!encrypted || zipCrypto) && signed) {
3023
+ if (checkCrc32) {
2975
3024
  crc32Stream = new Crc32Stream();
2976
3025
  readable = pipeThrough(readable, crc32Stream);
2977
3026
  }
2978
3027
  setReadable(this, readable, () => {
2979
- if ((!encrypted || zipCrypto) && signed) {
3028
+ if (checkCrc32) {
2980
3029
  const dataViewSignature = new DataView(crc32Stream.value.buffer);
2981
3030
  if (signature != dataViewSignature.getUint32(0, false)) {
2982
- throw new Error(ERR_INVALID_SIGNATURE);
3031
+ throw new Error(ERR_INVALID_CRC32);
2983
3032
  }
2984
3033
  }
2985
3034
  });
2986
3035
  }
2987
3036
  }
2988
3037
 
2989
- const deflateRawSupportByStream = new Map();
3038
+ const formatSupportByStream = new Map();
2990
3039
 
2991
- function supportsDeflateRaw(StreamClass) {
3040
+ function supportsFormat(StreamClass, format) {
2992
3041
  if (!StreamClass) {
2993
3042
  return false;
2994
3043
  }
2995
- let supported = deflateRawSupportByStream.get(StreamClass);
3044
+ let supportByFormat = formatSupportByStream.get(StreamClass);
3045
+ if (!supportByFormat) {
3046
+ supportByFormat = new Map();
3047
+ formatSupportByStream.set(StreamClass, supportByFormat);
3048
+ }
3049
+ let supported = supportByFormat.get(format);
2996
3050
  if (supported === UNDEFINED_VALUE) {
2997
3051
  try {
2998
- new StreamClass(FORMAT_DEFLATE_RAW);
3052
+ new StreamClass(format);
2999
3053
  supported = true;
3000
3054
  } catch {
3001
3055
  supported = false;
3002
3056
  }
3003
- deflateRawSupportByStream.set(StreamClass, supported);
3057
+ supportByFormat.set(format, supported);
3004
3058
  }
3005
3059
  return supported;
3006
3060
  }
3007
3061
 
3062
+ function supportsDeflateRaw(StreamClass) {
3063
+ return supportsFormat(StreamClass, FORMAT_DEFLATE_RAW);
3064
+ }
3065
+
3066
+ function supportsGzip(StreamClass) {
3067
+ return supportsFormat(StreamClass, FORMAT_GZIP);
3068
+ }
3069
+
3008
3070
  function setReadable(stream, readable, flush) {
3009
3071
  readable = pipeThrough(readable, new TransformStream({ flush }));
3010
3072
  Object.defineProperty(stream, "readable", {
@@ -3303,6 +3365,25 @@
3303
3365
  }
3304
3366
  let initModule = () => { };
3305
3367
 
3368
+ async function supportsDeflate(config) {
3369
+ const { CompressionStream: NativeStream, CompressionStreamZlib: ZlibStream } = config;
3370
+ if (ZlibStream && !ZlibStream.requiresModule) {
3371
+ return true;
3372
+ }
3373
+ if (supportsDeflateRaw(NativeStream) || supportsGzip(NativeStream)) {
3374
+ return true;
3375
+ }
3376
+ if (ZlibStream) {
3377
+ try {
3378
+ await initModule(config);
3379
+ return true;
3380
+ } catch {
3381
+ return false;
3382
+ }
3383
+ }
3384
+ return false;
3385
+ }
3386
+
3306
3387
  class CodecWorker {
3307
3388
 
3308
3389
  constructor(workerData, { readable, writable }, { options, config, streamOptions, useWebWorkers, transferStreams, workerURI }, onTaskFinished) {
@@ -3834,7 +3915,7 @@
3834
3915
 
3835
3916
  async function runWorker(stream, workerOptions) {
3836
3917
  const { options, config } = workerOptions;
3837
- const { transferStreams, useWebWorkers, useCompressionStream, compressed, signed, encrypted, format, codecURI } = options;
3918
+ const { transferStreams, useWebWorkers, useCompressionStream, compressed, checkCrc32, computeCrc32, encrypted, format, codecURI } = options;
3838
3919
  const { workerURI, maxWorkers } = config;
3839
3920
  if (format) {
3840
3921
  if (codecURI) {
@@ -3843,7 +3924,7 @@
3843
3924
  await ensureCodecStreams(format, options.codecURI);
3844
3925
  }
3845
3926
  workerOptions.transferStreams = transferStreams || (transferStreams === UNDEFINED_VALUE && config.transferStreams);
3846
- const streamCopy = !compressed && !signed && !encrypted;
3927
+ const streamCopy = !compressed && !checkCrc32 && !computeCrc32 && !encrypted;
3847
3928
  const workerSupported = format === UNDEFINED_VALUE || Boolean(options.codecURI);
3848
3929
  workerOptions.useWebWorkers = !streamCopy && workerSupported && (useWebWorkers || (useWebWorkers === UNDEFINED_VALUE && config.useWebWorkers));
3849
3930
  workerOptions.workerURI = workerOptions.useWebWorkers && workerURI ? workerURI : UNDEFINED_VALUE;
@@ -4086,6 +4167,7 @@
4086
4167
  const PROPERTY_NAME_EXECUTABLE = "executable";
4087
4168
  const PROPERTY_NAME_COMPRESSION_METHOD = "compressionMethod";
4088
4169
  const PROPERTY_NAME_SIGNATURE = "signature";
4170
+ const PROPERTY_NAME_CRC32 = "crc32";
4089
4171
  const PROPERTY_NAME_EXTRA_FIELD = "extraField";
4090
4172
  const PROPERTY_NAME_EXTRA_FIELD_INFOZIP = "extraFieldInfoZip";
4091
4173
  const PROPERTY_NAME_EXTRA_FIELD_UNIX = "extraFieldUnix";
@@ -4134,6 +4216,7 @@
4134
4216
  PROPERTY_NAME_EXECUTABLE,
4135
4217
  PROPERTY_NAME_COMPRESSION_METHOD,
4136
4218
  PROPERTY_NAME_SIGNATURE,
4219
+ PROPERTY_NAME_CRC32,
4137
4220
  PROPERTY_NAME_EXTRA_FIELD,
4138
4221
  PROPERTY_NAME_EXTRA_FIELD_UNIX,
4139
4222
  PROPERTY_NAME_EXTRA_FIELD_INFOZIP,
@@ -4205,6 +4288,8 @@
4205
4288
  const OPTION_CHECK_OVERLAPPING_ENTRY = "checkOverlappingEntry";
4206
4289
  const OPTION_CHECK_AMBIGUITY = "checkAmbiguity";
4207
4290
  const OPTION_CHECK_SIGNATURE = "checkSignature";
4291
+ const OPTION_CHECK_CRC32 = "checkCrc32";
4292
+ const OPTION_CHECK_AUTHENTICATION_CODE = "checkAuthenticationCode";
4208
4293
  const OPTION_USE_WEB_WORKERS = "useWebWorkers";
4209
4294
  const OPTION_USE_COMPRESSION_STREAM = "useCompressionStream";
4210
4295
  const OPTION_TRANSFER_STREAMS = "transferStreams";
@@ -4276,6 +4361,7 @@
4276
4361
  const PROPERTY_NAME_UTF8_SUFFIX = "UTF8";
4277
4362
  const CHARSET_CP437 = "cp437";
4278
4363
  const BITFLAG_AMBIGUITY_MASK = BITFLAG_ENCRYPTED | BITFLAG_DATA_DESCRIPTOR | BITFLAG_LANG_ENCODING_FLAG;
4364
+ const VENDOR_VERSION_AE_1 = 1;
4279
4365
  const ZIP64_PROPERTIES = [
4280
4366
  [PROPERTY_NAME_UNCOMPRESSED_SIZE, MAX_32_BITS],
4281
4367
  [PROPERTY_NAME_COMPRESSED_SIZE, MAX_32_BITS],
@@ -4715,6 +4801,11 @@
4715
4801
  if (deflate64) {
4716
4802
  useCompressionStream = false;
4717
4803
  }
4804
+ const checkCrc32Option = getOptionValue$1(zipEntry, options, OPTION_CHECK_CRC32);
4805
+ const checkCrc32 = (checkCrc32Option === UNDEFINED_VALUE ?
4806
+ getOptionValue$1(zipEntry, options, OPTION_CHECK_SIGNATURE) :
4807
+ checkCrc32Option) && !passThrough &&
4808
+ (!encrypted || zipCrypto || (extraFieldAES && extraFieldAES.vendorVersion == VENDOR_VERSION_AE_1));
4718
4809
  const workerOptions = {
4719
4810
  options: {
4720
4811
  codecType: CODEC_INFLATE,
@@ -4722,7 +4813,8 @@
4722
4813
  rawPassword,
4723
4814
  zipCrypto,
4724
4815
  encryptionStrength: extraFieldAES && extraFieldAES.strength,
4725
- signed: getOptionValue$1(zipEntry, options, OPTION_CHECK_SIGNATURE) && !passThrough,
4816
+ checkCrc32,
4817
+ checkAuthenticationCode: getOptionValue$1(zipEntry, options, OPTION_CHECK_AUTHENTICATION_CODE),
4726
4818
  passwordVerification: zipCrypto && (dataDescriptor ? ((rawLastModDate >>> 8) & MAX_8_BITS) : ((signature >>> 24) & MAX_8_BITS)),
4727
4819
  outputSize: passThrough ? compressedSize : uncompressedSize,
4728
4820
  signature,
@@ -4838,6 +4930,7 @@
4838
4930
  const compressionMethod = getUint16(dataView, offset + 4);
4839
4931
  Object.assign(directory, {
4840
4932
  signature: getUint32(dataView, offset + HEADER_OFFSET_SIGNATURE),
4933
+ crc32: getUint32(dataView, offset + HEADER_OFFSET_SIGNATURE),
4841
4934
  compressedSize: getUint32(dataView, offset + HEADER_OFFSET_COMPRESSED_SIZE),
4842
4935
  uncompressedSize: getUint32(dataView, offset + HEADER_OFFSET_UNCOMPRESSED_SIZE)
4843
4936
  });
@@ -4939,6 +5032,9 @@
4939
5032
  compressionMethod: getUint16(extraFieldView, 5)
4940
5033
  });
4941
5034
  directory.compressionMethod = extraFieldAES.compressionMethod;
5035
+ if (extraFieldAES.vendorVersion != VENDOR_VERSION_AE_1) {
5036
+ directory.crc32 = UNDEFINED_VALUE;
5037
+ }
4942
5038
  }
4943
5039
 
4944
5040
  function readExtraFieldNTFS(extraFieldNTFS, directory) {
@@ -4957,26 +5053,22 @@
4957
5053
  } catch {
4958
5054
  // ignored
4959
5055
  }
4960
- try {
4961
- if (tag1Data && tag1Data.length == 24) {
4962
- const tag1View = getDataView(tag1Data);
4963
- const rawLastModDate = tag1View.getBigUint64(0, true);
4964
- const rawLastAccessDate = tag1View.getBigUint64(8, true);
4965
- const rawCreationDate = tag1View.getBigUint64(16, true);
4966
- Object.assign(extraFieldNTFS, {
4967
- rawLastModDate,
4968
- rawLastAccessDate,
4969
- rawCreationDate
4970
- });
4971
- const lastModDate = getDateNTFS(rawLastModDate);
4972
- const lastAccessDate = getDateNTFS(rawLastAccessDate);
4973
- const creationDate = getDateNTFS(rawCreationDate);
4974
- const extraFieldData = { lastModDate, lastAccessDate, creationDate };
4975
- Object.assign(extraFieldNTFS, extraFieldData);
4976
- Object.assign(directory, extraFieldData);
4977
- }
4978
- } catch {
4979
- // ignored
5056
+ if (tag1Data && tag1Data.length == 24) {
5057
+ const tag1View = getDataView(tag1Data);
5058
+ const rawLastModDate = tag1View.getBigUint64(0, true);
5059
+ const rawLastAccessDate = tag1View.getBigUint64(8, true);
5060
+ const rawCreationDate = tag1View.getBigUint64(16, true);
5061
+ Object.assign(extraFieldNTFS, {
5062
+ rawLastModDate,
5063
+ rawLastAccessDate,
5064
+ rawCreationDate
5065
+ });
5066
+ const lastModDate = getDateNTFS(rawLastModDate);
5067
+ const lastAccessDate = getDateNTFS(rawLastAccessDate);
5068
+ const creationDate = getDateNTFS(rawCreationDate);
5069
+ const extraFieldData = { lastModDate, lastAccessDate, creationDate };
5070
+ Object.assign(extraFieldNTFS, extraFieldData);
5071
+ Object.assign(directory, extraFieldData);
4980
5072
  }
4981
5073
  }
4982
5074
 
@@ -5279,11 +5371,7 @@
5279
5371
 
5280
5372
  function getDate(timeRaw) {
5281
5373
  const date = (timeRaw & 0xffff0000) >> 16, time = timeRaw & MAX_16_BITS;
5282
- try {
5283
- return new Date(1980 + ((date & 0xFE00) >> 9), ((date & 0x01E0) >> 5) - 1, date & 0x001F, (time & 0xF800) >> 11, (time & 0x07E0) >> 5, (time & 0x001F) * 2, 0);
5284
- } catch {
5285
- // ignored
5286
- }
5374
+ return new Date(1980 + ((date & 0xFE00) >> 9), ((date & 0x01E0) >> 5) - 1, date & 0x001F, (time & 0xF800) >> 11, (time & 0x07E0) >> 5, (time & 0x001F) * 2, 0);
5287
5375
  }
5288
5376
 
5289
5377
  function getDateNTFS(timeRaw) {
@@ -5316,7 +5404,9 @@
5316
5404
  ERR_EOCDR_LOCATOR_ZIP64_NOT_FOUND: ERR_EOCDR_LOCATOR_ZIP64_NOT_FOUND,
5317
5405
  ERR_EOCDR_NOT_FOUND: ERR_EOCDR_NOT_FOUND,
5318
5406
  ERR_EXTRAFIELD_ZIP64_NOT_FOUND: ERR_EXTRAFIELD_ZIP64_NOT_FOUND,
5407
+ ERR_INVALID_AUTHENTICATION_CODE: ERR_INVALID_AUTHENTICATION_CODE,
5319
5408
  ERR_INVALID_COMPRESSED_DATA: ERR_INVALID_COMPRESSED_DATA,
5409
+ ERR_INVALID_CRC32: ERR_INVALID_CRC32,
5320
5410
  ERR_INVALID_PASSWORD: ERR_INVALID_PASSWORD,
5321
5411
  ERR_INVALID_SIGNATURE: ERR_INVALID_SIGNATURE,
5322
5412
  ERR_INVALID_UNCOMPRESSED_SIZE: ERR_INVALID_UNCOMPRESSED_SIZE,
@@ -5369,6 +5459,8 @@
5369
5459
  const ERR_UNSUPPORTED_COMPRESSION = "Compression method not supported";
5370
5460
  const MIN_UNIX_TIME = -2147483648;
5371
5461
  const MAX_UNIX_TIME = 2147483647;
5462
+ const MIN_NTFS_TIME = BigInt(0);
5463
+ const MAX_NTFS_TIME = BigInt("0x7fffffffffffffff");
5372
5464
  const ERR_UNSUPPORTED_FORMAT = "Zip64 is not supported (set the 'zip64' option to 'true')";
5373
5465
  const ERR_UNDEFINED_UNCOMPRESSED_SIZE = "Undefined uncompressed size";
5374
5466
  const ERR_UNDEFINED_READER = "Undefined reader";
@@ -5588,6 +5680,11 @@
5588
5680
  zipWriter.files.set(name, UNDEFINED_VALUE);
5589
5681
  let fileEntry;
5590
5682
  try {
5683
+ const { resolvedOptions } = metadataInfo;
5684
+ if (resolvedOptions.level != 0 && resolvedOptions.compressionMethod === UNDEFINED_VALUE &&
5685
+ !resolvedOptions.passThrough && !(await supportsDeflate(zipWriter.config))) {
5686
+ resolvedOptions.level = 0;
5687
+ }
5591
5688
  const sizesInfo = await resolveSizes(zipWriter, reader, metadataInfo, options);
5592
5689
  ({ reader } = sizesInfo);
5593
5690
  const diskOffset = getDiskOffset(zipWriter.writer);
@@ -5808,9 +5905,6 @@
5808
5905
  if (level !== UNDEFINED_VALUE && level != 6) {
5809
5906
  useCompressionStream = false;
5810
5907
  }
5811
- if (!useCompressionStream && !registeredCodec && (zipWriter.config.CompressionStream === UNDEFINED_VALUE && zipWriter.config.CompressionStreamZlib === UNDEFINED_VALUE)) {
5812
- level = 0;
5813
- }
5814
5908
  const zip64 = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIP64);
5815
5909
  if (!zipCrypto && (password !== UNDEFINED_VALUE || rawPassword !== UNDEFINED_VALUE) && !(encryptionStrength >= 1 && encryptionStrength <= 3)) {
5816
5910
  throw new Error(ERR_INVALID_ENCRYPTION_STRENGTH);
@@ -6198,9 +6292,12 @@
6198
6292
  msdosAttributes
6199
6293
  };
6200
6294
  let {
6201
- signature,
6295
+ crc32: signature,
6202
6296
  uncompressedSize
6203
6297
  } = options;
6298
+ if (signature === UNDEFINED_VALUE) {
6299
+ ({ signature } = options);
6300
+ }
6204
6301
  let compressedSize = 0;
6205
6302
  if (!passThrough) {
6206
6303
  uncompressedSize = 0;
@@ -6218,7 +6315,7 @@
6218
6315
  encryptionStrength,
6219
6316
  zipCrypto: encrypted && zipCrypto,
6220
6317
  passwordVerification: encrypted && zipCrypto && (rawLastModDate >> 8) & MAX_8_BITS,
6221
- signed: !passThrough,
6318
+ computeCrc32: !passThrough,
6222
6319
  compressed: compressed && !passThrough,
6223
6320
  encrypted: encrypted && !passThrough,
6224
6321
  useWebWorkers,
@@ -6237,7 +6334,9 @@
6237
6334
  writer.size += compressedSize;
6238
6335
  if (!passThrough) {
6239
6336
  uncompressedSize = result.inputSize;
6240
- signature = result.signature;
6337
+ if (!encrypted || zipCrypto) {
6338
+ signature = result.signature;
6339
+ }
6241
6340
  }
6242
6341
  if ((!zip64CompressedSize && compressedSize >= MAX_32_BITS) ||
6243
6342
  (!zip64UncompressedSize && uncompressedSize >= MAX_32_BITS)) {
@@ -6276,6 +6375,7 @@
6276
6375
  headerArray,
6277
6376
  headerView,
6278
6377
  signature,
6378
+ crc32: encrypted && !zipCrypto ? UNDEFINED_VALUE : signature,
6279
6379
  extraFieldExtendedTimestampFlag,
6280
6380
  zip64UncompressedSize,
6281
6381
  zip64CompressedSize
@@ -6376,8 +6476,8 @@
6376
6476
  extraFieldNTFS.uint16(EXTRAFIELD_TYPE_NTFS_TAG1);
6377
6477
  extraFieldNTFS.uint16(24);
6378
6478
  extraFieldNTFS.uint64(lastModTimeNTFS);
6379
- extraFieldNTFS.uint64(getTimeNTFS(lastAccessDate) || lastModTimeNTFS);
6380
- extraFieldNTFS.uint64(getTimeNTFS(creationDate) || lastModTimeNTFS);
6479
+ extraFieldNTFS.uint64(lastAccessDate ? getTimeNTFS(lastAccessDate) : lastModTimeNTFS);
6480
+ extraFieldNTFS.uint64(creationDate ? getTimeNTFS(creationDate) : lastModTimeNTFS);
6381
6481
  rawExtraFieldNTFS = extraFieldNTFS.array;
6382
6482
  } catch {
6383
6483
  rawExtraFieldNTFS = EMPTY_UINT8_ARRAY;
@@ -6437,7 +6537,7 @@
6437
6537
  if (extraFieldLength > MAX_16_BITS) {
6438
6538
  throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
6439
6539
  }
6440
- const dosLastModDate = new Date(Math.ceil(lastModDate.getTime() / 2000) * 2000);
6540
+ const dosLastModDate = new Date(Math.ceil(Math.floor(lastModDate.getTime() / 1000) / 2) * 2000);
6441
6541
  const {
6442
6542
  headerArray,
6443
6543
  headerView,
@@ -6946,7 +7046,8 @@
6946
7046
 
6947
7047
  function getTimeNTFS(date) {
6948
7048
  if (date) {
6949
- return ((BigInt(date.getTime()) + BigInt(11644473600000)) * BigInt(10000));
7049
+ const timeNTFS = ((BigInt(date.getTime()) + BigInt(11644473600000)) * BigInt(10000));
7050
+ return timeNTFS < MIN_NTFS_TIME ? MIN_NTFS_TIME : timeNTFS > MAX_NTFS_TIME ? MAX_NTFS_TIME : timeNTFS;
6950
7051
  }
6951
7052
  }
6952
7053