@zip.js/zip.js 2.8.53 → 2.8.55

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 (48) hide show
  1. package/README.md +1 -1
  2. package/deno.json +2 -1
  3. package/dist/zip-core-external.js +737 -491
  4. package/dist/zip-core-external.min.js +1 -1
  5. package/dist/zip-core.js +745 -490
  6. package/dist/zip-core.min.js +1 -1
  7. package/dist/zip-fs-core-external.js +776 -525
  8. package/dist/zip-fs-core-external.min.js +1 -1
  9. package/dist/zip-fs-core.js +738 -510
  10. package/dist/zip-fs-core.min.js +1 -1
  11. package/dist/zip-fs-external.js +776 -525
  12. package/dist/zip-fs-external.min.js +1 -1
  13. package/dist/zip-fs-native.js +790 -525
  14. package/dist/zip-fs-native.min.js +1 -1
  15. package/dist/zip-fs.js +791 -526
  16. package/dist/zip-fs.min.js +1 -1
  17. package/dist/zip-legacy.js +746 -491
  18. package/dist/zip-legacy.min.js +1 -1
  19. package/dist/zip-native.js +746 -491
  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 +747 -492
  24. package/dist/zip.min.js +1 -1
  25. package/eslint.config.mjs +1 -0
  26. package/index-native.cjs +790 -525
  27. package/index-native.min.js +1 -1
  28. package/index.cjs +791 -526
  29. package/index.d.cts +422 -49
  30. package/index.d.ts +422 -49
  31. package/index.min.js +1 -1
  32. package/lib/core/configuration.js +62 -21
  33. package/lib/core/constants.js +13 -1
  34. package/lib/core/io.js +33 -27
  35. package/lib/core/options.js +44 -2
  36. package/lib/core/streams/aes-crypto-stream.js +12 -12
  37. package/lib/core/util/decode-text.js +11 -2
  38. package/lib/core/web-worker-base.js +3 -2
  39. package/lib/core/web-worker-inline-native.js +1 -1
  40. package/lib/core/web-worker-inline-wasm.js +1 -1
  41. package/lib/core/zip-fs.js +39 -32
  42. package/lib/core/zip-reader.js +100 -38
  43. package/lib/core/zip-writer.js +301 -177
  44. package/lib/core/zlib-streams-inline.js +1 -1
  45. package/lib/zip-core-base.js +6 -1
  46. package/lib/zip-core-reader.js +1 -0
  47. package/lib/zip-core-writer.js +5 -0
  48. package/package.json +8 -2
@@ -37,6 +37,8 @@ import {
37
37
  COMPRESSION_METHOD_STORE,
38
38
  COMPRESSION_METHOD_AES,
39
39
  SPLIT_ZIP_FILE_SIGNATURE,
40
+ TEMPORARY_SPLIT_ZIP_FILE_SIGNATURE,
41
+ SPLIT_ZIP_FILE_SIGNATURE_LENGTH,
40
42
  DATA_DESCRIPTOR_RECORD_SIGNATURE,
41
43
  DATA_DESCRIPTOR_RECORD_LENGTH,
42
44
  DATA_DESCRIPTOR_RECORD_ZIP_64_LENGTH,
@@ -66,6 +68,7 @@ import {
66
68
  ZIP64_END_OF_CENTRAL_DIR_LENGTH,
67
69
  BITFLAG_ENCRYPTED,
68
70
  BITFLAG_STRONG_ENCRYPTION,
71
+ BITFLAG_MASKED_LOCAL_HEADERS,
69
72
  BITFLAG_LEVEL,
70
73
  BITFLAG_DATA_DESCRIPTOR,
71
74
  BITFLAG_LANG_ENCODING_FLAG,
@@ -90,7 +93,6 @@ import {
90
93
  FILE_ATTR_UNIX_SETGID_MASK,
91
94
  FILE_ATTR_UNIX_STICKY_MASK,
92
95
  NUMBER_TYPE,
93
- STRING_TYPE,
94
96
  EMPTY_UINT8_ARRAY
95
97
  } from "./constants.js";
96
98
  import { getConfiguration } from "./configuration.js";
@@ -167,7 +169,11 @@ import {
167
169
  OPTION_USE_WEB_WORKERS,
168
170
  OPTION_USE_COMPRESSION_STREAM,
169
171
  OPTION_TRANSFER_STREAMS,
170
- OPTION_PREVENT_CLOSE
172
+ OPTION_PREVENT_CLOSE,
173
+ checkFunctionOption,
174
+ checkSignalOption,
175
+ checkPasswordOption,
176
+ toNumber
171
177
  } from "./options.js";
172
178
 
173
179
  const ERR_BAD_FORMAT = "File format is not recognized";
@@ -181,6 +187,7 @@ const ERR_UNSUPPORTED_ENCRYPTION = "Encryption method not supported";
181
187
  const ERR_UNSUPPORTED_COMPRESSION = "Compression method not supported";
182
188
  const ERR_SPLIT_ZIP_FILE = "Split zip file";
183
189
  const ERR_OVERLAPPING_ENTRY = "Overlapping entry found";
190
+ const ERR_ENTRY_DATA_OUT_OF_BOUNDS = "Entry data out of bounds";
184
191
  const ERR_AMBIGUOUS_ARCHIVE = "Ambiguous archive";
185
192
  const ERR_ENCRYPTED_CENTRAL_DIRECTORY = "Encrypted central directory is not supported";
186
193
  const ERR_UNSAFE_FILENAME = "Unsafe filename";
@@ -210,6 +217,7 @@ const ZIP64_EXTRACTION = {
210
217
  }
211
218
  };
212
219
  const MAX_END_OF_CENTRAL_DIR_PROBES = 64;
220
+ const MAX_DEFLATE_EXPANSION_RATIO = 1032;
213
221
  const CENTRAL_DIRECTORY_UNREACHABLE = 0;
214
222
  const CENTRAL_DIRECTORY_PLAUSIBLE = 1;
215
223
  const CENTRAL_DIRECTORY_REACHABLE = 2;
@@ -220,7 +228,6 @@ class ZipReader {
220
228
  Object.assign(this, {
221
229
  reader: new GenericReader(reader),
222
230
  options,
223
- config: getConfiguration(),
224
231
  readRanges: new Map()
225
232
  });
226
233
  }
@@ -228,7 +235,6 @@ class ZipReader {
228
235
  async* getEntriesGenerator(options = {}) {
229
236
  const zipReader = this;
230
237
  let { reader } = zipReader;
231
- const { config } = zipReader;
232
238
  await initStream(reader);
233
239
  if (reader.size === UNDEFINED_VALUE || !reader.readUint8Array) {
234
240
  reader = new BlobReader(await streamToBlob(reader.readable));
@@ -245,9 +251,7 @@ class ZipReader {
245
251
  const normalizeFilename = getOptionValue(zipReader, options, OPTION_NORMALIZE_FILENAME);
246
252
  const { endOfDirectoryInfo, endOfDirectoryReachingEndCount } = await findEndOfCentralDirectory(reader, rejectAmbiguousEndOfDirectory, maxAppendedDataSize);
247
253
  if (!endOfDirectoryInfo) {
248
- const signatureArray = await readUint8Array(reader, 0, 4);
249
- const signatureView = getDataView(signatureArray);
250
- if (getUint32(signatureView) == SPLIT_ZIP_FILE_SIGNATURE) {
254
+ if (await startsWithSplitZipSignature(reader)) {
251
255
  throw new Error(ERR_SPLIT_ZIP_FILE);
252
256
  } else {
253
257
  throw new Error(ERR_EOCDR_NOT_FOUND);
@@ -273,6 +277,7 @@ class ZipReader {
273
277
  let startOffset;
274
278
  let zip64EndOfDirectory;
275
279
  let zip64EndOfDirectoryVersion2;
280
+ let zip64EndOfDirectoryLength = ZIP64_END_OF_CENTRAL_DIR_LENGTH;
276
281
  let directoryEncryptionInfo;
277
282
  const requiresZip64 = directoryDataOffset == MAX_32_BITS || directoryDataLength == MAX_32_BITS || filesLength == MAX_16_BITS || diskNumber == MAX_16_BITS;
278
283
  if (directoryDataOffset != MAX_32_BITS && diskNumber != MAX_16_BITS) {
@@ -309,6 +314,7 @@ class ZipReader {
309
314
  Number(getBigUint64(endOfDirectoryView, 4)) - (ZIP64_END_OF_CENTRAL_DIR_LENGTH - 12),
310
315
  reader.size - directoryDataOffset - ZIP64_END_OF_CENTRAL_DIR_LENGTH);
311
316
  if (extensibleDataLength > 0) {
317
+ zip64EndOfDirectoryLength += extensibleDataLength;
312
318
  const rawExtensibleData = await readUint8Array(reader, directoryDataOffset + ZIP64_END_OF_CENTRAL_DIR_LENGTH, extensibleDataLength);
313
319
  directoryEncryptionInfo = getDirectoryEncryptionInfo(rawExtensibleData);
314
320
  }
@@ -338,7 +344,7 @@ class ZipReader {
338
344
  }
339
345
  let declaredDirectoryDataLength = directoryDataLength;
340
346
  const centralDirectoryEndOffset = endOfDirectoryInfo.offset -
341
- (zip64EndOfDirectory ? ZIP64_END_OF_CENTRAL_DIR_LENGTH + ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH : 0);
347
+ (zip64EndOfDirectory ? zip64EndOfDirectoryLength + ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH : 0);
342
348
  if (directoryDataOffset >= reader.size) {
343
349
  prependedDataLength = reader.size - directoryDataOffset - directoryDataLength - END_OF_CENTRAL_DIR_LENGTH;
344
350
  directoryDataOffset = reader.size - directoryDataLength - END_OF_CENTRAL_DIR_LENGTH;
@@ -358,7 +364,9 @@ class ZipReader {
358
364
  }
359
365
  const expectedDirectoryDataOffset = centralDirectoryEndOffset - directoryDataLength;
360
366
  if (directoryDataOffset != expectedDirectoryDataOffset && diskNumber == lastDiskNumber) {
361
- const storedPointsAtDirectory = getUint32(directoryView, offset) == CENTRAL_FILE_HEADER_SIGNATURE;
367
+ const storedPointsAtDirectory = getUint32(directoryView, offset) == CENTRAL_FILE_HEADER_SIGNATURE ||
368
+ Boolean(directoryEncryptionInfo && directoryEncryptionInfo.compressedSize) ||
369
+ detectEncryptedCentralDirectory(directoryView);
362
370
  let reconcile = !storedPointsAtDirectory;
363
371
  if (!reconcile && expectedDirectoryDataOffset >= 0 && expectedDirectoryDataOffset + 4 <= reader.size) {
364
372
  const expectedSignatureArray = await readUint8Array(reader, expectedDirectoryDataOffset, 4);
@@ -386,12 +394,14 @@ class ZipReader {
386
394
  }
387
395
  zipReader.directoryOffset = directoryDataOffset;
388
396
  zipReader.directoryLength = declaredDirectoryDataLength;
389
- const decryptCentralDirectory = getOptionValue(zipReader, options, OPTION_DECRYPT_CENTRAL_DIRECTORY);
390
- let decryptedDirectory;
397
+ const decryptCentralDirectory = getFunctionOptionValue(zipReader, options, OPTION_DECRYPT_CENTRAL_DIRECTORY);
398
+ let decryptedDirectory, dataAfterEncryptedDirectory;
391
399
  if (decryptCentralDirectory && filesLength && directoryArray.length >= 4 &&
392
400
  getUint32(directoryView, 0) != CENTRAL_FILE_HEADER_SIGNATURE &&
393
401
  (zip64EndOfDirectoryVersion2 || detectEncryptedCentralDirectory(directoryView))) {
394
- directoryArray = await decryptCentralDirectory(directoryArray, directoryEncryptionInfo);
402
+ const encryptedDirectoryDataLength = getEncryptedDirectoryDataLength(directoryEncryptionInfo, declaredDirectoryDataLength, directoryArray.length);
403
+ dataAfterEncryptedDirectory = directoryArray.subarray(encryptedDirectoryDataLength);
404
+ directoryArray = await decryptCentralDirectory(directoryArray.subarray(0, encryptedDirectoryDataLength), directoryEncryptionInfo);
395
405
  directoryView = getDataView(directoryArray);
396
406
  declaredDirectoryDataLength = directoryArray.length;
397
407
  decryptedDirectory = true;
@@ -402,7 +412,7 @@ class ZipReader {
402
412
  const filenames = checkAmbiguity ? new Set() : UNDEFINED_VALUE;
403
413
  let duplicateFilename;
404
414
  for (let indexFile = 0; indexFile < filesLength; indexFile++) {
405
- const fileEntry = new ZipEntry(reader, config, zipReader.options);
415
+ const fileEntry = new ZipEntry(reader, zipReader.options);
406
416
  if (offset + CENTRAL_FILE_HEADER_LENGTH > directoryArray.length || getUint32(directoryView, offset) != CENTRAL_FILE_HEADER_SIGNATURE) {
407
417
  if (indexFile == 0 && !decryptedDirectory && (zip64EndOfDirectoryVersion2 || detectEncryptedCentralDirectory(directoryView))) {
408
418
  throw new Error(ERR_ENCRYPTED_CENTRAL_DIRECTORY);
@@ -433,7 +443,7 @@ class ZipReader {
433
443
  archive: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_ARCHIVE_MASK)
434
444
  };
435
445
  const offsetFileEntry = getUint32(directoryView, offset + 42);
436
- const decode = getOptionValue(zipReader, options, OPTION_DECODE_TEXT) || decodeText;
446
+ const decode = getFunctionOptionValue(zipReader, options, OPTION_DECODE_TEXT) || decodeText;
437
447
  const rawFilenameEncoding = filenameUTF8 ? CHARSET_UTF8 : filenameEncoding || CHARSET_CP437;
438
448
  const rawCommentEncoding = commentUTF8 ? CHARSET_UTF8 : commentEncoding || CHARSET_CP437;
439
449
  let filename = decode(rawFilename, rawFilenameEncoding, TEXT_TYPE_FILENAME);
@@ -457,6 +467,7 @@ class ZipReader {
457
467
  }
458
468
  Object.assign(fileEntry, {
459
469
  index: indexFile,
470
+ decryptedDirectory,
460
471
  versionMadeBy,
461
472
  msDosCompatible,
462
473
  zip64: false,
@@ -533,12 +544,11 @@ class ZipReader {
533
544
  yield entry;
534
545
  }
535
546
  let offsetAfterSignature = offset;
536
- if (offset + 6 <= directoryArray.length && getUint32(directoryView, offset) == DIGITAL_SIGNATURE_RECORD_SIGNATURE) {
537
- const signatureDataLength = getUint16(directoryView, offset + 4);
538
- if (offset + 6 + signatureDataLength <= directoryArray.length) {
539
- zipReader.digitalSignature = directoryArray.subarray(offset + 6, offset + 6 + signatureDataLength);
540
- offsetAfterSignature = offset + 6 + signatureDataLength;
541
- }
547
+ const digitalSignature = readDigitalSignature(directoryArray.subarray(offset)) ||
548
+ (decryptedDirectory ? readDigitalSignature(dataAfterEncryptedDirectory) : UNDEFINED_VALUE);
549
+ if (digitalSignature) {
550
+ zipReader.digitalSignature = digitalSignature;
551
+ offsetAfterSignature = offset + 6 + digitalSignature.length;
542
552
  }
543
553
  if (checkAmbiguity && offset != declaredDirectoryDataLength && offsetAfterSignature != declaredDirectoryDataLength) {
544
554
  throwAmbiguousArchive("trailing central directory data");
@@ -546,13 +556,17 @@ class ZipReader {
546
556
  if (duplicateFilename) {
547
557
  throwAmbiguousArchive("duplicate filename");
548
558
  }
549
- if (checkAmbiguity && (prependedDataLength || (filesLength && startOffset > 0))) {
550
- throwAmbiguousArchive("prepended data");
551
- }
552
559
  const extractPrependedData = getOptionValue(zipReader, options, OPTION_EXTRACT_PREPENDED_DATA);
553
560
  const extractAppendedData = getOptionValue(zipReader, options, OPTION_EXTRACT_APPENDED_DATA);
561
+ const splitZipSignatureLength = (checkAmbiguity || extractPrependedData) && filesLength &&
562
+ startOffset == SPLIT_ZIP_FILE_SIGNATURE_LENGTH && await startsWithSplitZipMarker(reader) ? SPLIT_ZIP_FILE_SIGNATURE_LENGTH : 0;
563
+ if (checkAmbiguity && (prependedDataLength || (filesLength && startOffset > splitZipSignatureLength))) {
564
+ throwAmbiguousArchive("prepended data");
565
+ }
554
566
  if (extractPrependedData) {
555
- zipReader.prependedData = startOffset > 0 ? await readUint8Array(reader, 0, startOffset) : EMPTY_UINT8_ARRAY;
567
+ zipReader.prependedData = startOffset > splitZipSignatureLength ?
568
+ await readUint8Array(reader, splitZipSignatureLength, startOffset - splitZipSignatureLength) :
569
+ EMPTY_UINT8_ARRAY;
556
570
  }
557
571
  zipReader.comment = commentLength ? await readUint8Array(reader, commentOffset + END_OF_CENTRAL_DIR_LENGTH, commentLength) : EMPTY_UINT8_ARRAY;
558
572
  if (extractAppendedData) {
@@ -637,6 +651,7 @@ export {
637
651
  ERR_INVALID_COMPRESSED_DATA,
638
652
  ERR_SPLIT_ZIP_FILE,
639
653
  ERR_OVERLAPPING_ENTRY,
654
+ ERR_ENTRY_DATA_OUT_OF_BOUNDS,
640
655
  ERR_AMBIGUOUS_ARCHIVE,
641
656
  ERR_ENCRYPTED_CENTRAL_DIRECTORY,
642
657
  ERR_UNSAFE_FILENAME,
@@ -648,16 +663,16 @@ export {
648
663
 
649
664
  class ZipEntry {
650
665
 
651
- constructor(reader, config, options) {
666
+ constructor(reader, options) {
652
667
  Object.assign(this, {
653
668
  reader,
654
- config,
655
669
  options
656
670
  });
657
671
  }
658
672
 
659
673
  async getData(writer, fileEntry, readRanges, options = {}) {
660
674
  const zipEntry = this;
675
+ const config = getConfiguration();
661
676
  const {
662
677
  reader,
663
678
  index,
@@ -666,7 +681,6 @@ class ZipEntry {
666
681
  extraFieldAES,
667
682
  extraFieldZip64,
668
683
  compressionMethod,
669
- config,
670
684
  bitFlag,
671
685
  rawBitFlag,
672
686
  crc32,
@@ -684,6 +698,7 @@ class ZipEntry {
684
698
  let password = getOptionValue(zipEntry, options, OPTION_PASSWORD);
685
699
  let rawPassword = getOptionValue(zipEntry, options, OPTION_RAW_PASSWORD);
686
700
  const passThrough = getOptionValue(zipEntry, options, OPTION_PASS_THROUGH);
701
+ checkPasswordOption(password, rawPassword);
687
702
  password = password && password.length && password;
688
703
  rawPassword = rawPassword && rawPassword.length && rawPassword;
689
704
  if (extraFieldAES) {
@@ -753,9 +768,12 @@ class ZipEntry {
753
768
  }
754
769
  }
755
770
  const dataOffset = localHeaderOffset + HEADER_SIZE + filenameLength + extraFieldLength;
771
+ if (dataOffset + compressedSize > reader.size) {
772
+ throw new Error(ERR_ENTRY_DATA_OUT_OF_BOUNDS);
773
+ }
756
774
  const size = compressedSize;
757
775
  const readable = toCompatibleReadable(reader.createReadable({ offset: dataOffset, size }));
758
- const signal = getOptionValue(zipEntry, options, OPTION_SIGNAL);
776
+ const signal = checkSignalOption(getOptionValue(zipEntry, options, OPTION_SIGNAL));
759
777
  const checkPasswordOnly = getOptionValue(zipEntry, options, OPTION_CHECK_PASSWORD_ONLY);
760
778
  let checkOverlappingEntry = getOptionValue(zipEntry, options, OPTION_CHECK_OVERLAPPING_ENTRY);
761
779
  const checkOverlappingEntryOnly = getOptionValue(zipEntry, options, OPTION_CHECK_OVERLAPPING_ENTRY_ONLY);
@@ -763,6 +781,8 @@ class ZipEntry {
763
781
  checkOverlappingEntry = true;
764
782
  }
765
783
  const { onstart, onprogress, onend } = options;
784
+ const compressed = compressionMethod != COMPRESSION_METHOD_STORE && !passThrough;
785
+ const outputSize = passThrough ? compressedSize : uncompressedSize;
766
786
  const deflate64 = compressionMethod == COMPRESSION_METHOD_DEFLATE_64;
767
787
  let useCompressionStream = getOptionValue(zipEntry, options, OPTION_USE_COMPRESSION_STREAM);
768
788
  if (deflate64) {
@@ -783,9 +803,9 @@ class ZipEntry {
783
803
  checkCrc32,
784
804
  checkAuthenticationCode: getOptionValue(zipEntry, options, OPTION_CHECK_AUTHENTICATION_CODE),
785
805
  passwordVerification: zipCrypto && (dataDescriptor ? ((rawLastModDate >>> 8) & MAX_8_BITS) : ((crc32 >>> 24) & MAX_8_BITS)),
786
- outputSize: passThrough ? compressedSize : uncompressedSize,
806
+ outputSize,
787
807
  crc32,
788
- compressed: compressionMethod != 0 && !passThrough,
808
+ compressed,
789
809
  encrypted,
790
810
  useWebWorkers: getOptionValue(zipEntry, options, OPTION_USE_WEB_WORKERS),
791
811
  useCompressionStream,
@@ -822,11 +842,11 @@ class ZipEntry {
822
842
  writer = new WritableStream();
823
843
  }
824
844
  writer = new GenericWriter(writer);
825
- await initStream(writer, passThrough ? compressedSize : uncompressedSize);
845
+ await initStream(writer, getDecodableOutputSize(outputSize, compressedSize, compressed));
826
846
  ({ writable } = writer);
827
- const { outputSize } = await runWorker({ readable, writable }, workerOptions);
828
- writer.size += outputSize;
829
- if (outputSize != (passThrough ? compressedSize : uncompressedSize)) {
847
+ const { outputSize: writtenSize } = await runWorker({ readable, writable }, workerOptions);
848
+ writer.size += writtenSize;
849
+ if (writtenSize != outputSize) {
830
850
  throw new Error(ERR_INVALID_UNCOMPRESSED_SIZE);
831
851
  }
832
852
  }
@@ -867,6 +887,27 @@ function detectEncryptedCentralDirectory(directoryView) {
867
887
  return false;
868
888
  }
869
889
 
890
+ function readDigitalSignature(signatureRecordArray) {
891
+ if (signatureRecordArray.length >= 6) {
892
+ const signatureRecordView = getDataView(signatureRecordArray);
893
+ if (getUint32(signatureRecordView, 0) == DIGITAL_SIGNATURE_RECORD_SIGNATURE) {
894
+ const signatureDataLength = getUint16(signatureRecordView, 4);
895
+ if (6 + signatureDataLength <= signatureRecordArray.length) {
896
+ return signatureRecordArray.subarray(6, 6 + signatureDataLength);
897
+ }
898
+ }
899
+ }
900
+ }
901
+
902
+ function getEncryptedDirectoryDataLength(directoryEncryptionInfo, declaredDirectoryDataLength, directoryDataLength) {
903
+ const encryptedDirectoryDataLength = directoryEncryptionInfo && directoryEncryptionInfo.compressedSize ?
904
+ directoryEncryptionInfo.compressedSize :
905
+ declaredDirectoryDataLength;
906
+ return encryptedDirectoryDataLength > 0 && encryptedDirectoryDataLength <= directoryDataLength ?
907
+ encryptedDirectoryDataLength :
908
+ directoryDataLength;
909
+ }
910
+
870
911
  function getDirectoryEncryptionInfo(rawExtensibleData) {
871
912
  const directoryEncryptionInfo = { rawExtensibleData };
872
913
  if (rawExtensibleData.length >= 28) {
@@ -1246,10 +1287,28 @@ function getDiskOffset(reader, diskNumber) {
1246
1287
  return reader.getDiskOffset ? reader.getDiskOffset(diskNumber) : 0;
1247
1288
  }
1248
1289
 
1290
+ async function startsWithSplitZipSignature(reader) {
1291
+ return await getFirstSignature(reader) == SPLIT_ZIP_FILE_SIGNATURE;
1292
+ }
1293
+
1294
+ async function startsWithSplitZipMarker(reader) {
1295
+ const signature = await getFirstSignature(reader);
1296
+ return signature == SPLIT_ZIP_FILE_SIGNATURE || signature == TEMPORARY_SPLIT_ZIP_FILE_SIGNATURE;
1297
+ }
1298
+
1299
+ async function getFirstSignature(reader) {
1300
+ const signatureArray = await readUint8Array(reader, 0, SPLIT_ZIP_FILE_SIGNATURE_LENGTH);
1301
+ return getUint32(getDataView(signatureArray));
1302
+ }
1303
+
1249
1304
  function isStrictnessValue(value) {
1250
1305
  return value === STRICTNESS_STRICT || value === STRICTNESS_BALANCED || value === STRICTNESS_TOLERANT;
1251
1306
  }
1252
1307
 
1308
+ function getDecodableOutputSize(outputSize, compressedSize, compressed) {
1309
+ return Math.min(outputSize, compressed ? compressedSize * MAX_DEFLATE_EXPANSION_RATIO : compressedSize);
1310
+ }
1311
+
1253
1312
  function getStrictness(options, inheritedOptions) {
1254
1313
  return resolveStrictness(options, resolveStrictness(inheritedOptions, STRICTNESS_BALANCED));
1255
1314
  }
@@ -1433,7 +1492,9 @@ async function readSignature(reader, view, anchoredOffset, signatureOffset, size
1433
1492
 
1434
1493
  function validateLocalDirectory(zipEntry, localDirectory, rawLocalFilename, checkLocalFilename) {
1435
1494
  const { rawFilename } = zipEntry;
1436
- if (checkLocalFilename &&
1495
+ const maskedLocalDirectory = zipEntry.decryptedDirectory &&
1496
+ (localDirectory.rawBitFlag & BITFLAG_MASKED_LOCAL_HEADERS) == BITFLAG_MASKED_LOCAL_HEADERS;
1497
+ if (checkLocalFilename && !maskedLocalDirectory &&
1437
1498
  (rawLocalFilename.length != rawFilename.length ||
1438
1499
  rawLocalFilename.some((byteValue, indexByte) => byteValue != rawFilename[indexByte]))) {
1439
1500
  throwAmbiguousArchive("mismatched local file header (filename)");
@@ -1444,7 +1505,7 @@ function validateLocalDirectory(zipEntry, localDirectory, rawLocalFilename, chec
1444
1505
  if (localDirectory.compressionMethod != zipEntry.compressionMethod) {
1445
1506
  throwAmbiguousArchive("mismatched local file header (compression method)");
1446
1507
  }
1447
- if (!localDirectory.bitFlag.dataDescriptor &&
1508
+ if (!localDirectory.bitFlag.dataDescriptor && !maskedLocalDirectory &&
1448
1509
  (localDirectory.crc32 || localDirectory.compressedSize || localDirectory.uncompressedSize) &&
1449
1510
  (localDirectory.crc32 != zipEntry.crc32 ||
1450
1511
  localDirectory.compressedSize != zipEntry.compressedSize ||
@@ -1463,10 +1524,11 @@ function getOptionValue(zipReader, options, name) {
1463
1524
  return options[name] === UNDEFINED_VALUE ? zipReader.options[name] : options[name];
1464
1525
  }
1465
1526
 
1466
- function toNumber(value) {
1467
- return typeof value == STRING_TYPE && value.trim() ? Number(value) : value;
1527
+ function getFunctionOptionValue(zipReader, options, name) {
1528
+ return checkFunctionOption(getOptionValue(zipReader, options, name));
1468
1529
  }
1469
1530
 
1531
+
1470
1532
  function getDate(timeRaw) {
1471
1533
  const date = (timeRaw & 0xffff0000) >> 16, time = timeRaw & MAX_16_BITS;
1472
1534
  return new Date(1980 + ((date & 0xFE00) >> 9), ((date & 0x01E0) >> 5) - 1, date & 0x001F, (time & 0xF800) >> 11, (time & 0x07E0) >> 5, (time & 0x001F) * 2, 0);