@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.
- package/README.md +1 -1
- package/deno.json +2 -1
- package/dist/zip-core-external.js +737 -491
- package/dist/zip-core-external.min.js +1 -1
- package/dist/zip-core.js +745 -490
- package/dist/zip-core.min.js +1 -1
- package/dist/zip-fs-core-external.js +776 -525
- package/dist/zip-fs-core-external.min.js +1 -1
- package/dist/zip-fs-core.js +738 -510
- package/dist/zip-fs-core.min.js +1 -1
- package/dist/zip-fs-external.js +776 -525
- package/dist/zip-fs-external.min.js +1 -1
- package/dist/zip-fs-native.js +790 -525
- package/dist/zip-fs-native.min.js +1 -1
- package/dist/zip-fs.js +791 -526
- package/dist/zip-fs.min.js +1 -1
- package/dist/zip-legacy.js +746 -491
- package/dist/zip-legacy.min.js +1 -1
- package/dist/zip-native.js +746 -491
- package/dist/zip-native.min.js +1 -1
- package/dist/zip-web-worker-native.js +1 -1
- package/dist/zip-web-worker.js +1 -1
- package/dist/zip.js +747 -492
- package/dist/zip.min.js +1 -1
- package/eslint.config.mjs +1 -0
- package/index-native.cjs +790 -525
- package/index-native.min.js +1 -1
- package/index.cjs +791 -526
- package/index.d.cts +422 -49
- package/index.d.ts +422 -49
- package/index.min.js +1 -1
- package/lib/core/configuration.js +62 -21
- package/lib/core/constants.js +13 -1
- package/lib/core/io.js +33 -27
- package/lib/core/options.js +44 -2
- package/lib/core/streams/aes-crypto-stream.js +12 -12
- package/lib/core/util/decode-text.js +11 -2
- package/lib/core/web-worker-base.js +3 -2
- package/lib/core/web-worker-inline-native.js +1 -1
- package/lib/core/web-worker-inline-wasm.js +1 -1
- package/lib/core/zip-fs.js +39 -32
- package/lib/core/zip-reader.js +100 -38
- package/lib/core/zip-writer.js +301 -177
- package/lib/core/zlib-streams-inline.js +1 -1
- package/lib/zip-core-base.js +6 -1
- package/lib/zip-core-reader.js +1 -0
- package/lib/zip-core-writer.js +5 -0
- package/package.json +8 -2
package/lib/core/zip-reader.js
CHANGED
|
@@ -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
|
-
|
|
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 ?
|
|
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 =
|
|
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
|
-
|
|
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,
|
|
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 =
|
|
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
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
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 >
|
|
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,
|
|
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
|
|
806
|
+
outputSize,
|
|
787
807
|
crc32,
|
|
788
|
-
compressed
|
|
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,
|
|
845
|
+
await initStream(writer, getDecodableOutputSize(outputSize, compressedSize, compressed));
|
|
826
846
|
({ writable } = writer);
|
|
827
|
-
const { outputSize } = await runWorker({ readable, writable }, workerOptions);
|
|
828
|
-
writer.size +=
|
|
829
|
-
if (
|
|
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
|
-
|
|
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
|
|
1467
|
-
return
|
|
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);
|