@zip.js/zip.js 2.8.52 → 2.8.54
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 +839 -528
- package/dist/zip-core-external.min.js +1 -1
- package/dist/zip-core.js +847 -527
- package/dist/zip-core.min.js +1 -1
- package/dist/zip-fs-core-external.js +880 -557
- package/dist/zip-fs-core-external.min.js +1 -1
- package/dist/zip-fs-core.js +829 -538
- package/dist/zip-fs-core.min.js +1 -1
- package/dist/zip-fs-external.js +880 -557
- package/dist/zip-fs-external.min.js +1 -1
- package/dist/zip-fs-native.js +895 -558
- package/dist/zip-fs-native.min.js +1 -1
- package/dist/zip-fs.js +894 -557
- package/dist/zip-fs.min.js +1 -1
- package/dist/zip-legacy.js +849 -529
- package/dist/zip-legacy.min.js +1 -1
- package/dist/zip-native.js +849 -529
- 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 +848 -528
- package/dist/zip.min.js +1 -1
- package/eslint.config.mjs +2 -1
- package/index-native.cjs +895 -558
- package/index-native.min.js +1 -1
- package/index.cjs +894 -557
- package/index.d.cts +672 -78
- package/index.d.ts +672 -78
- package/index.min.js +1 -1
- package/lib/core/codec-worker-web.js +13 -4
- package/lib/core/configuration.js +62 -21
- package/lib/core/constants.js +16 -1
- package/lib/core/io.js +44 -29
- package/lib/core/options.js +46 -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-entry.js +8 -0
- package/lib/core/zip-fs.js +38 -27
- package/lib/core/zip-reader.js +149 -60
- package/lib/core/zip-writer.js +329 -189
- 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 +11 -3
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,
|
|
@@ -90,7 +92,6 @@ import {
|
|
|
90
92
|
FILE_ATTR_UNIX_SETGID_MASK,
|
|
91
93
|
FILE_ATTR_UNIX_STICKY_MASK,
|
|
92
94
|
NUMBER_TYPE,
|
|
93
|
-
STRING_TYPE,
|
|
94
95
|
EMPTY_UINT8_ARRAY
|
|
95
96
|
} from "./constants.js";
|
|
96
97
|
import { getConfiguration } from "./configuration.js";
|
|
@@ -150,6 +151,7 @@ import {
|
|
|
150
151
|
OPTION_CHECK_OVERLAPPING_ENTRY_ONLY,
|
|
151
152
|
OPTION_CHECK_OVERLAPPING_ENTRY,
|
|
152
153
|
OPTION_CHECK_AMBIGUITY,
|
|
154
|
+
OPTION_CHECK_LOCAL_DIRECTORY,
|
|
153
155
|
OPTION_CHECK_SIGNATURE,
|
|
154
156
|
OPTION_CHECK_CRC32,
|
|
155
157
|
OPTION_CHECK_AUTHENTICATION_CODE,
|
|
@@ -166,7 +168,11 @@ import {
|
|
|
166
168
|
OPTION_USE_WEB_WORKERS,
|
|
167
169
|
OPTION_USE_COMPRESSION_STREAM,
|
|
168
170
|
OPTION_TRANSFER_STREAMS,
|
|
169
|
-
OPTION_PREVENT_CLOSE
|
|
171
|
+
OPTION_PREVENT_CLOSE,
|
|
172
|
+
checkFunctionOption,
|
|
173
|
+
checkSignalOption,
|
|
174
|
+
checkPasswordOption,
|
|
175
|
+
toNumber
|
|
170
176
|
} from "./options.js";
|
|
171
177
|
|
|
172
178
|
const ERR_BAD_FORMAT = "File format is not recognized";
|
|
@@ -180,6 +186,7 @@ const ERR_UNSUPPORTED_ENCRYPTION = "Encryption method not supported";
|
|
|
180
186
|
const ERR_UNSUPPORTED_COMPRESSION = "Compression method not supported";
|
|
181
187
|
const ERR_SPLIT_ZIP_FILE = "Split zip file";
|
|
182
188
|
const ERR_OVERLAPPING_ENTRY = "Overlapping entry found";
|
|
189
|
+
const ERR_ENTRY_DATA_OUT_OF_BOUNDS = "Entry data out of bounds";
|
|
183
190
|
const ERR_AMBIGUOUS_ARCHIVE = "Ambiguous archive";
|
|
184
191
|
const ERR_ENCRYPTED_CENTRAL_DIRECTORY = "Encrypted central directory is not supported";
|
|
185
192
|
const ERR_UNSAFE_FILENAME = "Unsafe filename";
|
|
@@ -209,6 +216,7 @@ const ZIP64_EXTRACTION = {
|
|
|
209
216
|
}
|
|
210
217
|
};
|
|
211
218
|
const MAX_END_OF_CENTRAL_DIR_PROBES = 64;
|
|
219
|
+
const MAX_DEFLATE_EXPANSION_RATIO = 1032;
|
|
212
220
|
const CENTRAL_DIRECTORY_UNREACHABLE = 0;
|
|
213
221
|
const CENTRAL_DIRECTORY_PLAUSIBLE = 1;
|
|
214
222
|
const CENTRAL_DIRECTORY_REACHABLE = 2;
|
|
@@ -219,7 +227,6 @@ class ZipReader {
|
|
|
219
227
|
Object.assign(this, {
|
|
220
228
|
reader: new GenericReader(reader),
|
|
221
229
|
options,
|
|
222
|
-
config: getConfiguration(),
|
|
223
230
|
readRanges: new Map()
|
|
224
231
|
});
|
|
225
232
|
}
|
|
@@ -227,7 +234,6 @@ class ZipReader {
|
|
|
227
234
|
async* getEntriesGenerator(options = {}) {
|
|
228
235
|
const zipReader = this;
|
|
229
236
|
let { reader } = zipReader;
|
|
230
|
-
const { config } = zipReader;
|
|
231
237
|
await initStream(reader);
|
|
232
238
|
if (reader.size === UNDEFINED_VALUE || !reader.readUint8Array) {
|
|
233
239
|
reader = new BlobReader(await streamToBlob(reader.readable));
|
|
@@ -236,7 +242,7 @@ class ZipReader {
|
|
|
236
242
|
if (reader.size < END_OF_CENTRAL_DIR_LENGTH) {
|
|
237
243
|
throw new Error(ERR_BAD_FORMAT);
|
|
238
244
|
}
|
|
239
|
-
const strictness = getStrictness(
|
|
245
|
+
const strictness = getStrictness(options, zipReader.options);
|
|
240
246
|
const checkAmbiguity = strictness == STRICTNESS_STRICT;
|
|
241
247
|
const rejectAmbiguousEndOfDirectory = strictness != STRICTNESS_TOLERANT;
|
|
242
248
|
const maxAppendedDataSize = getMaxAppendedDataSize(getOptionValue(zipReader, options, OPTION_MAX_APPENDED_DATA_SIZE), strictness);
|
|
@@ -244,9 +250,7 @@ class ZipReader {
|
|
|
244
250
|
const normalizeFilename = getOptionValue(zipReader, options, OPTION_NORMALIZE_FILENAME);
|
|
245
251
|
const { endOfDirectoryInfo, endOfDirectoryReachingEndCount } = await findEndOfCentralDirectory(reader, rejectAmbiguousEndOfDirectory, maxAppendedDataSize);
|
|
246
252
|
if (!endOfDirectoryInfo) {
|
|
247
|
-
|
|
248
|
-
const signatureView = getDataView(signatureArray);
|
|
249
|
-
if (getUint32(signatureView) == SPLIT_ZIP_FILE_SIGNATURE) {
|
|
253
|
+
if (await startsWithSplitZipSignature(reader)) {
|
|
250
254
|
throw new Error(ERR_SPLIT_ZIP_FILE);
|
|
251
255
|
} else {
|
|
252
256
|
throw new Error(ERR_EOCDR_NOT_FOUND);
|
|
@@ -385,7 +389,7 @@ class ZipReader {
|
|
|
385
389
|
}
|
|
386
390
|
zipReader.directoryOffset = directoryDataOffset;
|
|
387
391
|
zipReader.directoryLength = declaredDirectoryDataLength;
|
|
388
|
-
const decryptCentralDirectory =
|
|
392
|
+
const decryptCentralDirectory = getFunctionOptionValue(zipReader, options, OPTION_DECRYPT_CENTRAL_DIRECTORY);
|
|
389
393
|
let decryptedDirectory;
|
|
390
394
|
if (decryptCentralDirectory && filesLength && directoryArray.length >= 4 &&
|
|
391
395
|
getUint32(directoryView, 0) != CENTRAL_FILE_HEADER_SIGNATURE &&
|
|
@@ -401,7 +405,7 @@ class ZipReader {
|
|
|
401
405
|
const filenames = checkAmbiguity ? new Set() : UNDEFINED_VALUE;
|
|
402
406
|
let duplicateFilename;
|
|
403
407
|
for (let indexFile = 0; indexFile < filesLength; indexFile++) {
|
|
404
|
-
const fileEntry = new ZipEntry(reader,
|
|
408
|
+
const fileEntry = new ZipEntry(reader, zipReader.options);
|
|
405
409
|
if (offset + CENTRAL_FILE_HEADER_LENGTH > directoryArray.length || getUint32(directoryView, offset) != CENTRAL_FILE_HEADER_SIGNATURE) {
|
|
406
410
|
if (indexFile == 0 && !decryptedDirectory && (zip64EndOfDirectoryVersion2 || detectEncryptedCentralDirectory(directoryView))) {
|
|
407
411
|
throw new Error(ERR_ENCRYPTED_CENTRAL_DIRECTORY);
|
|
@@ -432,7 +436,7 @@ class ZipReader {
|
|
|
432
436
|
archive: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_ARCHIVE_MASK)
|
|
433
437
|
};
|
|
434
438
|
const offsetFileEntry = getUint32(directoryView, offset + 42);
|
|
435
|
-
const decode =
|
|
439
|
+
const decode = getFunctionOptionValue(zipReader, options, OPTION_DECODE_TEXT) || decodeText;
|
|
436
440
|
const rawFilenameEncoding = filenameUTF8 ? CHARSET_UTF8 : filenameEncoding || CHARSET_CP437;
|
|
437
441
|
const rawCommentEncoding = commentUTF8 ? CHARSET_UTF8 : commentEncoding || CHARSET_CP437;
|
|
438
442
|
let filename = decode(rawFilename, rawFilenameEncoding, TEXT_TYPE_FILENAME);
|
|
@@ -458,6 +462,7 @@ class ZipReader {
|
|
|
458
462
|
index: indexFile,
|
|
459
463
|
versionMadeBy,
|
|
460
464
|
msDosCompatible,
|
|
465
|
+
zip64: false,
|
|
461
466
|
compressedSize: 0,
|
|
462
467
|
uncompressedSize: 0,
|
|
463
468
|
commentLength,
|
|
@@ -544,13 +549,17 @@ class ZipReader {
|
|
|
544
549
|
if (duplicateFilename) {
|
|
545
550
|
throwAmbiguousArchive("duplicate filename");
|
|
546
551
|
}
|
|
547
|
-
if (checkAmbiguity && (prependedDataLength || (filesLength && startOffset > 0))) {
|
|
548
|
-
throwAmbiguousArchive("prepended data");
|
|
549
|
-
}
|
|
550
552
|
const extractPrependedData = getOptionValue(zipReader, options, OPTION_EXTRACT_PREPENDED_DATA);
|
|
551
553
|
const extractAppendedData = getOptionValue(zipReader, options, OPTION_EXTRACT_APPENDED_DATA);
|
|
554
|
+
const splitZipSignatureLength = (checkAmbiguity || extractPrependedData) && filesLength &&
|
|
555
|
+
startOffset == SPLIT_ZIP_FILE_SIGNATURE_LENGTH && await startsWithSplitZipMarker(reader) ? SPLIT_ZIP_FILE_SIGNATURE_LENGTH : 0;
|
|
556
|
+
if (checkAmbiguity && (prependedDataLength || (filesLength && startOffset > splitZipSignatureLength))) {
|
|
557
|
+
throwAmbiguousArchive("prepended data");
|
|
558
|
+
}
|
|
552
559
|
if (extractPrependedData) {
|
|
553
|
-
zipReader.prependedData = startOffset >
|
|
560
|
+
zipReader.prependedData = startOffset > splitZipSignatureLength ?
|
|
561
|
+
await readUint8Array(reader, splitZipSignatureLength, startOffset - splitZipSignatureLength) :
|
|
562
|
+
EMPTY_UINT8_ARRAY;
|
|
554
563
|
}
|
|
555
564
|
zipReader.comment = commentLength ? await readUint8Array(reader, commentOffset + END_OF_CENTRAL_DIR_LENGTH, commentLength) : EMPTY_UINT8_ARRAY;
|
|
556
565
|
if (extractAppendedData) {
|
|
@@ -635,6 +644,7 @@ export {
|
|
|
635
644
|
ERR_INVALID_COMPRESSED_DATA,
|
|
636
645
|
ERR_SPLIT_ZIP_FILE,
|
|
637
646
|
ERR_OVERLAPPING_ENTRY,
|
|
647
|
+
ERR_ENTRY_DATA_OUT_OF_BOUNDS,
|
|
638
648
|
ERR_AMBIGUOUS_ARCHIVE,
|
|
639
649
|
ERR_ENCRYPTED_CENTRAL_DIRECTORY,
|
|
640
650
|
ERR_UNSAFE_FILENAME,
|
|
@@ -646,16 +656,16 @@ export {
|
|
|
646
656
|
|
|
647
657
|
class ZipEntry {
|
|
648
658
|
|
|
649
|
-
constructor(reader,
|
|
659
|
+
constructor(reader, options) {
|
|
650
660
|
Object.assign(this, {
|
|
651
661
|
reader,
|
|
652
|
-
config,
|
|
653
662
|
options
|
|
654
663
|
});
|
|
655
664
|
}
|
|
656
665
|
|
|
657
666
|
async getData(writer, fileEntry, readRanges, options = {}) {
|
|
658
667
|
const zipEntry = this;
|
|
668
|
+
const config = getConfiguration();
|
|
659
669
|
const {
|
|
660
670
|
reader,
|
|
661
671
|
index,
|
|
@@ -664,7 +674,6 @@ class ZipEntry {
|
|
|
664
674
|
extraFieldAES,
|
|
665
675
|
extraFieldZip64,
|
|
666
676
|
compressionMethod,
|
|
667
|
-
config,
|
|
668
677
|
bitFlag,
|
|
669
678
|
rawBitFlag,
|
|
670
679
|
crc32,
|
|
@@ -682,6 +691,7 @@ class ZipEntry {
|
|
|
682
691
|
let password = getOptionValue(zipEntry, options, OPTION_PASSWORD);
|
|
683
692
|
let rawPassword = getOptionValue(zipEntry, options, OPTION_RAW_PASSWORD);
|
|
684
693
|
const passThrough = getOptionValue(zipEntry, options, OPTION_PASS_THROUGH);
|
|
694
|
+
checkPasswordOption(password, rawPassword);
|
|
685
695
|
password = password && password.length && password;
|
|
686
696
|
rawPassword = rawPassword && rawPassword.length && rawPassword;
|
|
687
697
|
if (extraFieldAES) {
|
|
@@ -697,9 +707,12 @@ class ZipEntry {
|
|
|
697
707
|
extraFieldLength,
|
|
698
708
|
filenameLength
|
|
699
709
|
} = localDirectory;
|
|
700
|
-
const
|
|
710
|
+
const checkLocalDirectoryOption = getOptionValue(zipEntry, options, OPTION_CHECK_LOCAL_DIRECTORY);
|
|
711
|
+
const entryStrictness = getStrictness(options, zipEntry.options);
|
|
712
|
+
const checkLocalDirectory = getCheckLocalDirectory(checkLocalDirectoryOption, entryStrictness);
|
|
713
|
+
const checkLocalFilename = getCheckLocalFilename(checkLocalDirectoryOption, entryStrictness);
|
|
701
714
|
let rawLocalFilename = EMPTY_UINT8_ARRAY;
|
|
702
|
-
if (
|
|
715
|
+
if (checkLocalFilename && (filenameLength || extraFieldLength)) {
|
|
703
716
|
const trailingDataArray = await readUint8Array(reader, localHeaderOffset + HEADER_SIZE, filenameLength + extraFieldLength);
|
|
704
717
|
rawLocalFilename = trailingDataArray.subarray(0, filenameLength);
|
|
705
718
|
localDirectory.rawExtraField = trailingDataArray.subarray(filenameLength);
|
|
@@ -708,17 +721,26 @@ class ZipEntry {
|
|
|
708
721
|
await readUint8Array(reader, localHeaderOffset + HEADER_SIZE + filenameLength, extraFieldLength) :
|
|
709
722
|
EMPTY_UINT8_ARRAY;
|
|
710
723
|
}
|
|
724
|
+
if (checkLocalFilename) {
|
|
725
|
+
localDirectory.rawFilename = rawLocalFilename;
|
|
726
|
+
}
|
|
711
727
|
readCommonFooter(zipEntry, localDirectory, dataView, 4, true);
|
|
712
|
-
if (
|
|
713
|
-
|
|
728
|
+
if (checkLocalDirectory) {
|
|
729
|
+
validateLocalDirectory(zipEntry, localDirectory, rawLocalFilename, checkLocalFilename);
|
|
714
730
|
}
|
|
715
|
-
const { lastAccessDate, creationDate } = localDirectory;
|
|
731
|
+
const { lastAccessDate, creationDate, uid, gid } = localDirectory;
|
|
716
732
|
if (lastAccessDate) {
|
|
717
733
|
fileEntry.lastAccessDate = lastAccessDate;
|
|
718
734
|
}
|
|
719
735
|
if (creationDate) {
|
|
720
736
|
fileEntry.creationDate = creationDate;
|
|
721
737
|
}
|
|
738
|
+
if (uid !== UNDEFINED_VALUE && fileEntry.uid === UNDEFINED_VALUE) {
|
|
739
|
+
fileEntry.uid = uid;
|
|
740
|
+
}
|
|
741
|
+
if (gid !== UNDEFINED_VALUE && fileEntry.gid === UNDEFINED_VALUE) {
|
|
742
|
+
fileEntry.gid = gid;
|
|
743
|
+
}
|
|
722
744
|
const encrypted = zipEntry.encrypted && localDirectory.encrypted && !passThrough;
|
|
723
745
|
const zipCrypto = encrypted && !extraFieldAES;
|
|
724
746
|
if (!passThrough) {
|
|
@@ -739,9 +761,12 @@ class ZipEntry {
|
|
|
739
761
|
}
|
|
740
762
|
}
|
|
741
763
|
const dataOffset = localHeaderOffset + HEADER_SIZE + filenameLength + extraFieldLength;
|
|
764
|
+
if (dataOffset + compressedSize > reader.size) {
|
|
765
|
+
throw new Error(ERR_ENTRY_DATA_OUT_OF_BOUNDS);
|
|
766
|
+
}
|
|
742
767
|
const size = compressedSize;
|
|
743
768
|
const readable = toCompatibleReadable(reader.createReadable({ offset: dataOffset, size }));
|
|
744
|
-
const signal = getOptionValue(zipEntry, options, OPTION_SIGNAL);
|
|
769
|
+
const signal = checkSignalOption(getOptionValue(zipEntry, options, OPTION_SIGNAL));
|
|
745
770
|
const checkPasswordOnly = getOptionValue(zipEntry, options, OPTION_CHECK_PASSWORD_ONLY);
|
|
746
771
|
let checkOverlappingEntry = getOptionValue(zipEntry, options, OPTION_CHECK_OVERLAPPING_ENTRY);
|
|
747
772
|
const checkOverlappingEntryOnly = getOptionValue(zipEntry, options, OPTION_CHECK_OVERLAPPING_ENTRY_ONLY);
|
|
@@ -749,6 +774,8 @@ class ZipEntry {
|
|
|
749
774
|
checkOverlappingEntry = true;
|
|
750
775
|
}
|
|
751
776
|
const { onstart, onprogress, onend } = options;
|
|
777
|
+
const compressed = compressionMethod != COMPRESSION_METHOD_STORE && !passThrough;
|
|
778
|
+
const outputSize = passThrough ? compressedSize : uncompressedSize;
|
|
752
779
|
const deflate64 = compressionMethod == COMPRESSION_METHOD_DEFLATE_64;
|
|
753
780
|
let useCompressionStream = getOptionValue(zipEntry, options, OPTION_USE_COMPRESSION_STREAM);
|
|
754
781
|
if (deflate64) {
|
|
@@ -769,9 +796,9 @@ class ZipEntry {
|
|
|
769
796
|
checkCrc32,
|
|
770
797
|
checkAuthenticationCode: getOptionValue(zipEntry, options, OPTION_CHECK_AUTHENTICATION_CODE),
|
|
771
798
|
passwordVerification: zipCrypto && (dataDescriptor ? ((rawLastModDate >>> 8) & MAX_8_BITS) : ((crc32 >>> 24) & MAX_8_BITS)),
|
|
772
|
-
outputSize
|
|
799
|
+
outputSize,
|
|
773
800
|
crc32,
|
|
774
|
-
compressed
|
|
801
|
+
compressed,
|
|
775
802
|
encrypted,
|
|
776
803
|
useWebWorkers: getOptionValue(zipEntry, options, OPTION_USE_WEB_WORKERS),
|
|
777
804
|
useCompressionStream,
|
|
@@ -808,11 +835,11 @@ class ZipEntry {
|
|
|
808
835
|
writer = new WritableStream();
|
|
809
836
|
}
|
|
810
837
|
writer = new GenericWriter(writer);
|
|
811
|
-
await initStream(writer,
|
|
838
|
+
await initStream(writer, getDecodableOutputSize(outputSize, compressedSize, compressed));
|
|
812
839
|
({ writable } = writer);
|
|
813
|
-
const { outputSize } = await runWorker({ readable, writable }, workerOptions);
|
|
814
|
-
writer.size +=
|
|
815
|
-
if (
|
|
840
|
+
const { outputSize: writtenSize } = await runWorker({ readable, writable }, workerOptions);
|
|
841
|
+
writer.size += writtenSize;
|
|
842
|
+
if (writtenSize != outputSize) {
|
|
816
843
|
throw new Error(ERR_INVALID_UNCOMPRESSED_SIZE);
|
|
817
844
|
}
|
|
818
845
|
}
|
|
@@ -954,10 +981,12 @@ function readCommonFooter(fileEntry, directory, dataView, offset, localDirectory
|
|
|
954
981
|
directory.extraFieldNTFS = extraFieldNTFS;
|
|
955
982
|
}
|
|
956
983
|
const extraFieldUnix = extraField.get(EXTRAFIELD_TYPE_UNIX);
|
|
984
|
+
let unixIdsRead;
|
|
957
985
|
if (extraFieldUnix) {
|
|
958
|
-
readExtraFieldUnix(extraFieldUnix, directory, false);
|
|
986
|
+
unixIdsRead = readExtraFieldUnix(extraFieldUnix, directory, false);
|
|
959
987
|
directory.extraFieldUnix = extraFieldUnix;
|
|
960
|
-
}
|
|
988
|
+
}
|
|
989
|
+
if (!unixIdsRead) {
|
|
961
990
|
const extraFieldInfoZip = extraField.get(EXTRAFIELD_TYPE_INFOZIP);
|
|
962
991
|
if (extraFieldInfoZip) {
|
|
963
992
|
readExtraFieldUnix(extraFieldInfoZip, directory, true);
|
|
@@ -1060,7 +1089,7 @@ function readExtraFieldNTFS(extraFieldNTFS, directory) {
|
|
|
1060
1089
|
const creationDate = getDateNTFS(rawCreationDate);
|
|
1061
1090
|
const extraFieldData = { lastModDate, lastAccessDate, creationDate };
|
|
1062
1091
|
Object.assign(extraFieldNTFS, extraFieldData);
|
|
1063
|
-
Object.assign(directory, extraFieldData);
|
|
1092
|
+
Object.assign(directory, extraFieldData, { rawLastAccessDate, rawCreationDate });
|
|
1064
1093
|
}
|
|
1065
1094
|
}
|
|
1066
1095
|
|
|
@@ -1104,6 +1133,7 @@ function readExtraFieldUnix(extraField, directory, isInfoZip) {
|
|
|
1104
1133
|
if (gid !== UNDEFINED_VALUE) {
|
|
1105
1134
|
directory.gid = gid;
|
|
1106
1135
|
}
|
|
1136
|
+
return uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE;
|
|
1107
1137
|
} catch {
|
|
1108
1138
|
// ignored
|
|
1109
1139
|
}
|
|
@@ -1176,26 +1206,25 @@ async function detectOverlappingEntry({
|
|
|
1176
1206
|
}
|
|
1177
1207
|
if (dataDescriptorLength) {
|
|
1178
1208
|
const dataDescriptorArray = await readUint8Array(reader, dataOffset + compressedSize, dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH);
|
|
1179
|
-
const
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
if (extraFieldZip64) {
|
|
1186
|
-
readCompressedSize = getBigUint64(getDataView(dataDescriptorArray), 8);
|
|
1187
|
-
readUncompressedSize = getBigUint64(getDataView(dataDescriptorArray), 16);
|
|
1188
|
-
} else {
|
|
1189
|
-
readCompressedSize = getUint32(getDataView(dataDescriptorArray), 8);
|
|
1190
|
-
readUncompressedSize = getUint32(getDataView(dataDescriptorArray), 12);
|
|
1191
|
-
}
|
|
1192
|
-
const matchCrc32 = (fileEntry.encrypted && !fileEntry.zipCrypto) || readCrc32 == crc32;
|
|
1209
|
+
const dataDescriptorView = getDataView(dataDescriptorArray);
|
|
1210
|
+
let signature = dataDescriptorArray.length == dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH &&
|
|
1211
|
+
getUint32(dataDescriptorView, 0) == DATA_DESCRIPTOR_RECORD_SIGNATURE;
|
|
1212
|
+
if (signature) {
|
|
1213
|
+
const signedDataDescriptor = readDataDescriptor(dataDescriptorView, DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH, extraFieldZip64);
|
|
1214
|
+
const matchCrc32 = (fileEntry.encrypted && !fileEntry.zipCrypto) || signedDataDescriptor.crc32 == crc32;
|
|
1193
1215
|
if (matchCrc32 &&
|
|
1194
|
-
|
|
1195
|
-
|
|
1216
|
+
signedDataDescriptor.compressedSize == compressedSize &&
|
|
1217
|
+
signedDataDescriptor.uncompressedSize == uncompressedSize) {
|
|
1196
1218
|
dataDescriptorLength += DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH;
|
|
1219
|
+
} else {
|
|
1220
|
+
signature = false;
|
|
1197
1221
|
}
|
|
1198
1222
|
}
|
|
1223
|
+
if (dataDescriptorArray.length >= dataDescriptorLength) {
|
|
1224
|
+
const localDataDescriptor = readDataDescriptor(dataDescriptorView, signature ? DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH : 0, extraFieldZip64);
|
|
1225
|
+
localDataDescriptor.signature = signature;
|
|
1226
|
+
fileEntry.localDirectory.dataDescriptor = localDataDescriptor;
|
|
1227
|
+
}
|
|
1199
1228
|
}
|
|
1200
1229
|
const range = {
|
|
1201
1230
|
start: offset,
|
|
@@ -1212,22 +1241,80 @@ async function detectOverlappingEntry({
|
|
|
1212
1241
|
readRanges.set(index, range);
|
|
1213
1242
|
}
|
|
1214
1243
|
|
|
1244
|
+
function readDataDescriptor(dataDescriptorView, offset, extraFieldZip64) {
|
|
1245
|
+
const crc32 = getUint32(dataDescriptorView, offset);
|
|
1246
|
+
let compressedSize;
|
|
1247
|
+
let uncompressedSize;
|
|
1248
|
+
if (extraFieldZip64) {
|
|
1249
|
+
compressedSize = getBigUint64(dataDescriptorView, offset + 4);
|
|
1250
|
+
uncompressedSize = getBigUint64(dataDescriptorView, offset + 12);
|
|
1251
|
+
} else {
|
|
1252
|
+
compressedSize = getUint32(dataDescriptorView, offset + 4);
|
|
1253
|
+
uncompressedSize = getUint32(dataDescriptorView, offset + 8);
|
|
1254
|
+
}
|
|
1255
|
+
return { crc32, compressedSize, uncompressedSize };
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1215
1258
|
function getDiskOffset(reader, diskNumber) {
|
|
1216
1259
|
return reader.getDiskOffset ? reader.getDiskOffset(diskNumber) : 0;
|
|
1217
1260
|
}
|
|
1218
1261
|
|
|
1262
|
+
async function startsWithSplitZipSignature(reader) {
|
|
1263
|
+
return await getFirstSignature(reader) == SPLIT_ZIP_FILE_SIGNATURE;
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
async function startsWithSplitZipMarker(reader) {
|
|
1267
|
+
const signature = await getFirstSignature(reader);
|
|
1268
|
+
return signature == SPLIT_ZIP_FILE_SIGNATURE || signature == TEMPORARY_SPLIT_ZIP_FILE_SIGNATURE;
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
async function getFirstSignature(reader) {
|
|
1272
|
+
const signatureArray = await readUint8Array(reader, 0, SPLIT_ZIP_FILE_SIGNATURE_LENGTH);
|
|
1273
|
+
return getUint32(getDataView(signatureArray));
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1219
1276
|
function isStrictnessValue(value) {
|
|
1220
1277
|
return value === STRICTNESS_STRICT || value === STRICTNESS_BALANCED || value === STRICTNESS_TOLERANT;
|
|
1221
1278
|
}
|
|
1222
1279
|
|
|
1223
|
-
function
|
|
1224
|
-
|
|
1225
|
-
|
|
1280
|
+
function getDecodableOutputSize(outputSize, compressedSize, compressed) {
|
|
1281
|
+
return Math.min(outputSize, compressed ? compressedSize * MAX_DEFLATE_EXPANSION_RATIO : compressedSize);
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
function getStrictness(options, inheritedOptions) {
|
|
1285
|
+
return resolveStrictness(options, resolveStrictness(inheritedOptions, STRICTNESS_BALANCED));
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
function resolveStrictness(options, inheritedStrictness) {
|
|
1289
|
+
const strictness = options[OPTION_STRICTNESS];
|
|
1290
|
+
if (strictness !== UNDEFINED_VALUE) {
|
|
1291
|
+
if (!isStrictnessValue(strictness)) {
|
|
1292
|
+
throw new Error(ERR_INVALID_STRICTNESS);
|
|
1293
|
+
}
|
|
1294
|
+
return strictness;
|
|
1295
|
+
}
|
|
1296
|
+
const checkAmbiguity = options[OPTION_CHECK_AMBIGUITY];
|
|
1297
|
+
if (checkAmbiguity === UNDEFINED_VALUE) {
|
|
1298
|
+
return inheritedStrictness;
|
|
1299
|
+
}
|
|
1300
|
+
if (checkAmbiguity) {
|
|
1301
|
+
return STRICTNESS_STRICT;
|
|
1302
|
+
}
|
|
1303
|
+
return inheritedStrictness == STRICTNESS_TOLERANT ? STRICTNESS_TOLERANT : STRICTNESS_BALANCED;
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
function getCheckLocalDirectory(checkLocalDirectory, strictness) {
|
|
1307
|
+
if (checkLocalDirectory === UNDEFINED_VALUE) {
|
|
1308
|
+
return strictness != STRICTNESS_TOLERANT;
|
|
1226
1309
|
}
|
|
1227
|
-
|
|
1228
|
-
|
|
1310
|
+
return Boolean(checkLocalDirectory);
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
function getCheckLocalFilename(checkLocalFilename, strictness) {
|
|
1314
|
+
if (checkLocalFilename === UNDEFINED_VALUE) {
|
|
1315
|
+
return strictness == STRICTNESS_STRICT;
|
|
1229
1316
|
}
|
|
1230
|
-
return
|
|
1317
|
+
return Boolean(checkLocalFilename);
|
|
1231
1318
|
}
|
|
1232
1319
|
|
|
1233
1320
|
function getFilenameValidation(filenameValidation, strictness) {
|
|
@@ -1375,10 +1462,11 @@ async function readSignature(reader, view, anchoredOffset, signatureOffset, size
|
|
|
1375
1462
|
return UNDEFINED_VALUE;
|
|
1376
1463
|
}
|
|
1377
1464
|
|
|
1378
|
-
function
|
|
1465
|
+
function validateLocalDirectory(zipEntry, localDirectory, rawLocalFilename, checkLocalFilename) {
|
|
1379
1466
|
const { rawFilename } = zipEntry;
|
|
1380
|
-
if (
|
|
1381
|
-
rawLocalFilename.
|
|
1467
|
+
if (checkLocalFilename &&
|
|
1468
|
+
(rawLocalFilename.length != rawFilename.length ||
|
|
1469
|
+
rawLocalFilename.some((byteValue, indexByte) => byteValue != rawFilename[indexByte]))) {
|
|
1382
1470
|
throwAmbiguousArchive("mismatched local file header (filename)");
|
|
1383
1471
|
}
|
|
1384
1472
|
if ((localDirectory.rawBitFlag & BITFLAG_AMBIGUITY_MASK) != (zipEntry.rawBitFlag & BITFLAG_AMBIGUITY_MASK)) {
|
|
@@ -1406,10 +1494,11 @@ function getOptionValue(zipReader, options, name) {
|
|
|
1406
1494
|
return options[name] === UNDEFINED_VALUE ? zipReader.options[name] : options[name];
|
|
1407
1495
|
}
|
|
1408
1496
|
|
|
1409
|
-
function
|
|
1410
|
-
return
|
|
1497
|
+
function getFunctionOptionValue(zipReader, options, name) {
|
|
1498
|
+
return checkFunctionOption(getOptionValue(zipReader, options, name));
|
|
1411
1499
|
}
|
|
1412
1500
|
|
|
1501
|
+
|
|
1413
1502
|
function getDate(timeRaw) {
|
|
1414
1503
|
const date = (timeRaw & 0xffff0000) >> 16, time = timeRaw & MAX_16_BITS;
|
|
1415
1504
|
return new Date(1980 + ((date & 0xFE00) >> 9), ((date & 0x01E0) >> 5) - 1, date & 0x001F, (time & 0xF800) >> 11, (time & 0x07E0) >> 5, (time & 0x001F) * 2, 0);
|