@zip.js/zip.js 2.17.0 → 2.18.1

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.
package/deno.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zip-js/zip-js",
3
- "version": "2.17.0",
3
+ "version": "2.18.1",
4
4
  "exports": {
5
5
  ".": "./index.js",
6
6
  "./external": "./lib/zip-fs-external.js",
@@ -3280,8 +3280,13 @@ function getResponseError(errorData, errorValue) {
3280
3280
  if (codecImportFailed) {
3281
3281
  responseError.codecImportFailed = true;
3282
3282
  }
3283
- if (cause && !isErrorObject(responseError.cause)) {
3284
- responseError.cause = Object.assign(new Error(cause.message), { name: cause.name });
3283
+ if (cause) {
3284
+ if (!isErrorObject(responseError.cause)) {
3285
+ responseError.cause = Object.assign(new Error(cause.message), { name: cause.name });
3286
+ }
3287
+ if (cause.code !== UNDEFINED_VALUE && responseError.cause.code !== cause.code) {
3288
+ responseError.cause.code = cause.code;
3289
+ }
3285
3290
  }
3286
3291
  if (errorValue) {
3287
3292
  if (responseError.name !== name) {
@@ -4853,7 +4858,7 @@ const PARENT_DIRECTORY_REGEXP = /(^|[\\/])\.\.([\\/]|$)/;
4853
4858
  const CHARSET_UTF8 = "utf-8";
4854
4859
  const PROPERTY_NAME_UTF8_SUFFIX = "UTF8";
4855
4860
  const CHARSET_CP437 = "cp437";
4856
- const BITFLAG_AMBIGUITY_MASK = BITFLAG_ENCRYPTED | BITFLAG_DATA_DESCRIPTOR | BITFLAG_LANG_ENCODING_FLAG;
4861
+ const BITFLAG_AMBIGUITY_MASK = BITFLAG_ENCRYPTED | BITFLAG_DATA_DESCRIPTOR | BITFLAG_STRONG_ENCRYPTION | BITFLAG_LANG_ENCODING_FLAG;
4857
4862
  const VENDOR_VERSION_AE_1$1 = 1;
4858
4863
  const ZIP64_PROPERTIES = [
4859
4864
  [PROPERTY_NAME_UNCOMPRESSED_SIZE, MAX_32_BITS],
@@ -5507,12 +5512,12 @@ class ZipEntry {
5507
5512
  fileEntry.gid = gid;
5508
5513
  }
5509
5514
  const checkPasswordOnly = getOptionValue$1(zipEntry, options, OPTION_CHECK_PASSWORD_ONLY);
5510
- const encrypted = zipEntry.encrypted && localDirectory.encrypted && (!passThroughEncryption || checkPasswordOnly);
5515
+ const encrypted = zipEntry.encrypted && (!passThroughEncryption || checkPasswordOnly);
5511
5516
  const zipCrypto = encrypted && !extraFieldAES;
5512
5517
  if (!passThroughEncryption) {
5513
5518
  fileEntry.zipCrypto = zipCrypto;
5514
5519
  }
5515
- if (encrypted && (localDirectory.rawBitFlag & BITFLAG_STRONG_ENCRYPTION) == BITFLAG_STRONG_ENCRYPTION) {
5520
+ if (encrypted && (zipEntry.rawBitFlag & BITFLAG_STRONG_ENCRYPTION) == BITFLAG_STRONG_ENCRYPTION) {
5516
5521
  throw new Error(ERR_UNSUPPORTED_ENCRYPTION);
5517
5522
  }
5518
5523
  const registeredCodec = passThroughCompression ? UNDEFINED_VALUE : getRegisteredCodec(compressionMethod);
@@ -5752,8 +5757,16 @@ function readCommonFooter(fileEntry, directory, dataView, offset, localDirectory
5752
5757
  });
5753
5758
  const extraFieldZip64 = extraField.get(EXTRAFIELD_TYPE_ZIP64);
5754
5759
  if (extraFieldZip64) {
5755
- readExtraFieldZip64(extraFieldZip64, directory);
5760
+ if (!readExtraFieldZip64(extraFieldZip64, directory, localDirectory)) {
5761
+ malformedExtraField = true;
5762
+ }
5756
5763
  directory.extraFieldZip64 = extraFieldZip64;
5764
+ } else if (ZIP64_PROPERTIES.some(([propertyName, max]) => directory[propertyName] == max)) {
5765
+ if (localDirectory) {
5766
+ malformedExtraField = true;
5767
+ } else {
5768
+ throw new Error(ERR_EXTRAFIELD_ZIP64_NOT_FOUND);
5769
+ }
5757
5770
  }
5758
5771
  const extraFieldUnicodePath = extraField.get(EXTRAFIELD_TYPE_UNICODE_PATH);
5759
5772
  if (extraFieldUnicodePath) {
@@ -5766,10 +5779,13 @@ function readCommonFooter(fileEntry, directory, dataView, offset, localDirectory
5766
5779
  directory.extraFieldUnicodeComment = extraFieldUnicodeComment;
5767
5780
  }
5768
5781
  const extraFieldAES = extraField.get(EXTRAFIELD_TYPE_AES);
5769
- if (extraFieldAES && extraFieldAES.data.length >= 7) {
5782
+ if (extraFieldAES && (compressionMethod == COMPRESSION_METHOD_AES || directory.encrypted) && extraFieldAES.data.length >= 7) {
5770
5783
  readExtraFieldAES(extraFieldAES, directory, compressionMethod);
5771
5784
  directory.extraFieldAES = extraFieldAES;
5772
5785
  } else {
5786
+ if (extraFieldAES) {
5787
+ malformedExtraField = true;
5788
+ }
5773
5789
  directory.compressionMethod = compressionMethod;
5774
5790
  }
5775
5791
  const extraFieldPkwareUnix = extraField.get(EXTRAFIELD_TYPE_PKWARE_UNIX);
@@ -5812,20 +5828,35 @@ function readCommonFooter(fileEntry, directory, dataView, offset, localDirectory
5812
5828
  return malformedExtraField;
5813
5829
  }
5814
5830
 
5815
- function readExtraFieldZip64(extraFieldZip64, directory) {
5831
+ function readExtraFieldZip64(extraFieldZip64, directory, localDirectory) {
5816
5832
  directory.zip64 = true;
5817
5833
  const extraFieldView = getDataView(extraFieldZip64.data);
5818
5834
  const missingProperties = ZIP64_PROPERTIES.filter(([propertyName, max]) => directory[propertyName] == max);
5819
5835
  const requiredLength = missingProperties.reduce((length, [, max]) => length + ZIP64_EXTRACTION[max].bytes, 0);
5820
5836
  if (extraFieldZip64.data.length < requiredLength) {
5837
+ if (localDirectory) {
5838
+ return false;
5839
+ }
5821
5840
  throw new Error(ERR_EXTRAFIELD_ZIP64_NOT_FOUND);
5822
5841
  }
5823
- for (let indexMissingProperty = 0, offset = 0; indexMissingProperty < missingProperties.length; indexMissingProperty++) {
5824
- const [propertyName, max] = missingProperties[indexMissingProperty];
5825
- const extraction = ZIP64_EXTRACTION[max];
5826
- directory[propertyName] = extraFieldZip64[propertyName] = extraction.getValue(extraFieldView, offset);
5827
- offset += extraction.bytes;
5842
+ const values = [];
5843
+ try {
5844
+ for (let indexMissingProperty = 0, offset = 0; indexMissingProperty < missingProperties.length; indexMissingProperty++) {
5845
+ const [, max] = missingProperties[indexMissingProperty];
5846
+ const extraction = ZIP64_EXTRACTION[max];
5847
+ values.push(extraction.getValue(extraFieldView, offset));
5848
+ offset += extraction.bytes;
5849
+ }
5850
+ } catch (error) {
5851
+ if (localDirectory) {
5852
+ return false;
5853
+ }
5854
+ throw error;
5828
5855
  }
5856
+ missingProperties.forEach(([propertyName], indexMissingProperty) => {
5857
+ directory[propertyName] = extraFieldZip64[propertyName] = values[indexMissingProperty];
5858
+ });
5859
+ return true;
5829
5860
  }
5830
5861
 
5831
5862
  function readExtraFieldUnicode(extraFieldUnicode, propertyName, rawPropertyName, directory, fileEntry) {
@@ -6007,32 +6038,27 @@ async function detectOverlappingEntry({
6007
6038
  }) {
6008
6039
  let dataDescriptorLength = 0;
6009
6040
  if (dataDescriptor) {
6010
- if (extraFieldZip64) {
6011
- dataDescriptorLength = DATA_DESCRIPTOR_RECORD_ZIP_64_LENGTH;
6012
- } else {
6013
- dataDescriptorLength = DATA_DESCRIPTOR_RECORD_LENGTH;
6014
- }
6015
- }
6016
- if (dataDescriptorLength) {
6017
- const dataDescriptorArray = await readUint8Array(reader, dataOffset + compressedSize, dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH);
6041
+ const zip64 = Boolean(extraFieldZip64);
6042
+ const dataDescriptorArray = await readUint8Array(reader, dataOffset + compressedSize, DATA_DESCRIPTOR_RECORD_ZIP_64_LENGTH + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH);
6018
6043
  const dataDescriptorView = getDataView(dataDescriptorArray);
6019
- let signature = dataDescriptorArray.length == dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH &&
6020
- getUint32$1(dataDescriptorView, 0) == DATA_DESCRIPTOR_RECORD_SIGNATURE;
6021
- if (signature) {
6022
- const signedDataDescriptor = readDataDescriptor(dataDescriptorView, DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH, extraFieldZip64);
6023
- const matchCrc32 = (fileEntry.encrypted && !fileEntry.zipCrypto) || signedDataDescriptor.crc32 == crc32;
6024
- if (matchCrc32 &&
6025
- signedDataDescriptor.compressedSize == compressedSize &&
6026
- signedDataDescriptor.uncompressedSize == uncompressedSize) {
6027
- dataDescriptorLength += DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH;
6028
- } else {
6029
- signature = false;
6044
+ const ignoreCrc32 = fileEntry.encrypted && !fileEntry.zipCrypto;
6045
+ let localDataDescriptor;
6046
+ for (const [zip64Layout, signature] of [[zip64, true], [zip64, false], [!zip64, true], [!zip64, false]]) {
6047
+ const candidate = readDataDescriptor(dataDescriptorView, zip64Layout, signature);
6048
+ if (candidate && (ignoreCrc32 || candidate.crc32 == crc32) &&
6049
+ candidate.compressedSize == compressedSize && candidate.uncompressedSize == uncompressedSize) {
6050
+ localDataDescriptor = candidate;
6051
+ break;
6030
6052
  }
6031
6053
  }
6032
- if (dataDescriptorArray.length >= dataDescriptorLength) {
6033
- const localDataDescriptor = readDataDescriptor(dataDescriptorView, signature ? DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH : 0, extraFieldZip64);
6034
- localDataDescriptor.signature = signature;
6054
+ if (!localDataDescriptor) {
6055
+ localDataDescriptor = readDataDescriptor(dataDescriptorView, zip64, false);
6056
+ }
6057
+ if (localDataDescriptor) {
6035
6058
  fileEntry.localDirectory.dataDescriptor = localDataDescriptor;
6059
+ dataDescriptorLength = getDataDescriptorLength(localDataDescriptor.zip64, localDataDescriptor.signature);
6060
+ } else {
6061
+ dataDescriptorLength = getDataDescriptorLength(zip64, false);
6036
6062
  }
6037
6063
  }
6038
6064
  const range = {
@@ -6097,18 +6123,31 @@ function mergeRanges(sortedRanges, pendingRanges) {
6097
6123
  return mergedRanges;
6098
6124
  }
6099
6125
 
6100
- function readDataDescriptor(dataDescriptorView, offset, extraFieldZip64) {
6126
+ function readDataDescriptor(dataDescriptorView, zip64, signature) {
6127
+ const offset = signature ? DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH : 0;
6128
+ if (dataDescriptorView.byteLength < getDataDescriptorLength(zip64, signature) ||
6129
+ (signature && getUint32$1(dataDescriptorView, 0) != DATA_DESCRIPTOR_RECORD_SIGNATURE)) {
6130
+ return UNDEFINED_VALUE;
6131
+ }
6101
6132
  const crc32 = getUint32$1(dataDescriptorView, offset);
6102
6133
  let compressedSize;
6103
6134
  let uncompressedSize;
6104
- if (extraFieldZip64) {
6105
- compressedSize = getBigUint64(dataDescriptorView, offset + 4);
6106
- uncompressedSize = getBigUint64(dataDescriptorView, offset + 12);
6107
- } else {
6108
- compressedSize = getUint32$1(dataDescriptorView, offset + 4);
6109
- uncompressedSize = getUint32$1(dataDescriptorView, offset + 8);
6135
+ try {
6136
+ if (zip64) {
6137
+ compressedSize = getBigUint64(dataDescriptorView, offset + 4);
6138
+ uncompressedSize = getBigUint64(dataDescriptorView, offset + 12);
6139
+ } else {
6140
+ compressedSize = getUint32$1(dataDescriptorView, offset + 4);
6141
+ uncompressedSize = getUint32$1(dataDescriptorView, offset + 8);
6142
+ }
6143
+ } catch {
6144
+ return UNDEFINED_VALUE;
6110
6145
  }
6111
- return { crc32, compressedSize, uncompressedSize };
6146
+ return { signature, zip64, crc32, compressedSize, uncompressedSize };
6147
+ }
6148
+
6149
+ function getDataDescriptorLength(zip64, signature) {
6150
+ return (zip64 ? DATA_DESCRIPTOR_RECORD_ZIP_64_LENGTH : DATA_DESCRIPTOR_RECORD_LENGTH) + (signature ? DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH : 0);
6112
6151
  }
6113
6152
 
6114
6153
  function getDiskOffset$1(reader, diskNumber) {
@@ -8931,7 +8970,7 @@ function formatSupported(StreamClass, format) {
8931
8970
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
8932
8971
  */
8933
8972
 
8934
- const VERSION = "2.17.0";
8973
+ const VERSION = "2.18.1";
8935
8974
 
8936
8975
  /*
8937
8976
  Copyright (c) 2025 Gildas Lormeau. All rights reserved.