@zip.js/zip.js 2.20.0 → 2.21.0
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 +1 -1
- package/dist/zip-core-external.js +327 -211
- package/dist/zip-core-external.min.js +1 -1
- package/dist/zip-core.js +327 -211
- package/dist/zip-core.min.js +1 -1
- package/dist/zip-fs-core-external.js +327 -211
- package/dist/zip-fs-core-external.min.js +1 -1
- package/dist/zip-fs-core.js +327 -211
- package/dist/zip-fs-core.min.js +1 -1
- package/dist/zip-fs-external.js +327 -211
- package/dist/zip-fs-external.min.js +1 -1
- package/dist/zip-fs-native.js +327 -211
- package/dist/zip-fs-native.min.js +1 -1
- package/dist/zip-fs.js +327 -211
- package/dist/zip-fs.min.js +1 -1
- package/dist/zip-legacy.js +327 -211
- package/dist/zip-legacy.min.js +1 -1
- package/dist/zip-native.js +327 -211
- package/dist/zip-native.min.js +1 -1
- package/dist/zip.js +327 -211
- package/dist/zip.min.js +1 -1
- package/index-native.cjs +327 -211
- package/index-native.min.js +1 -1
- package/index.cjs +327 -211
- package/index.d.cts +62 -29
- package/index.d.ts +62 -29
- package/index.min.js +1 -1
- package/lib/core/constants.js +7 -0
- package/lib/core/version.js +1 -1
- package/lib/core/zip-reader.js +156 -69
- package/lib/core/zip-writer.js +172 -142
- package/package.json +1 -1
package/lib/core/constants.js
CHANGED
|
@@ -117,6 +117,10 @@ const MIN_DATE = new Date(1980, 0, 1);
|
|
|
117
117
|
|
|
118
118
|
const UNDEFINED_VALUE = undefined;
|
|
119
119
|
const INFINITY_VALUE = Infinity;
|
|
120
|
+
const ERR_LOCAL_FILE_HEADER_NOT_FOUND = "Local file header not found";
|
|
121
|
+
const ERR_OVERLAPPING_ENTRY = "Overlapping entry found";
|
|
122
|
+
const ERR_EXTRAFIELD_ZIP64_NOT_FOUND = "Zip64 extra field not found";
|
|
123
|
+
|
|
120
124
|
const UNDEFINED_TYPE = "undefined";
|
|
121
125
|
const FUNCTION_TYPE = "function";
|
|
122
126
|
const OBJECT_TYPE = "object";
|
|
@@ -211,6 +215,9 @@ export {
|
|
|
211
215
|
MAX_DATE,
|
|
212
216
|
UNDEFINED_VALUE,
|
|
213
217
|
INFINITY_VALUE,
|
|
218
|
+
ERR_LOCAL_FILE_HEADER_NOT_FOUND,
|
|
219
|
+
ERR_OVERLAPPING_ENTRY,
|
|
220
|
+
ERR_EXTRAFIELD_ZIP64_NOT_FOUND,
|
|
214
221
|
UNDEFINED_TYPE,
|
|
215
222
|
FUNCTION_TYPE,
|
|
216
223
|
OBJECT_TYPE,
|
package/lib/core/version.js
CHANGED
package/lib/core/zip-reader.js
CHANGED
|
@@ -68,6 +68,9 @@ import {
|
|
|
68
68
|
ZIP64_END_OF_CENTRAL_DIR_LENGTH,
|
|
69
69
|
BITFLAG_ENCRYPTED,
|
|
70
70
|
BITFLAG_STRONG_ENCRYPTION,
|
|
71
|
+
ERR_LOCAL_FILE_HEADER_NOT_FOUND,
|
|
72
|
+
ERR_OVERLAPPING_ENTRY,
|
|
73
|
+
ERR_EXTRAFIELD_ZIP64_NOT_FOUND,
|
|
71
74
|
BITFLAG_COMPRESSED_PATCHED_DATA,
|
|
72
75
|
BITFLAG_MASKED_LOCAL_HEADERS,
|
|
73
76
|
BITFLAG_LEVEL,
|
|
@@ -188,12 +191,9 @@ const ERR_BAD_FORMAT = "File format is not recognized";
|
|
|
188
191
|
const ERR_EOCDR_NOT_FOUND = "End of central directory not found";
|
|
189
192
|
const ERR_EOCDR_LOCATOR_ZIP64_NOT_FOUND = "End of Zip64 central directory locator not found";
|
|
190
193
|
const ERR_CENTRAL_DIRECTORY_NOT_FOUND = "Central directory header not found";
|
|
191
|
-
const ERR_LOCAL_FILE_HEADER_NOT_FOUND = "Local file header not found";
|
|
192
|
-
const ERR_EXTRAFIELD_ZIP64_NOT_FOUND = "Zip64 extra field not found";
|
|
193
194
|
const ERR_ENCRYPTED = "File contains encrypted entry";
|
|
194
195
|
const ERR_UNSUPPORTED_ENCRYPTION = "Encryption method not supported";
|
|
195
196
|
const ERR_SPLIT_ZIP_FILE = "Split zip file";
|
|
196
|
-
const ERR_OVERLAPPING_ENTRY = "Overlapping entry found";
|
|
197
197
|
const ERR_ENTRY_DATA_OUT_OF_BOUNDS = "Entry data out of bounds";
|
|
198
198
|
const ERR_AMBIGUOUS_ARCHIVE = "Ambiguous archive";
|
|
199
199
|
const ERR_ENCRYPTED_CENTRAL_DIRECTORY = "Encrypted central directory is not supported";
|
|
@@ -258,7 +258,8 @@ class ZipReader {
|
|
|
258
258
|
Object.assign(this, {
|
|
259
259
|
reader: new GenericReader(reader),
|
|
260
260
|
options,
|
|
261
|
-
readRanges: { indexes: new Set(), sortedRanges: [], pendingRanges: [] }
|
|
261
|
+
readRanges: { indexes: new Set(), sortedRanges: [], pendingRanges: [] },
|
|
262
|
+
entriesMissingZip64ExtraField: new WeakSet()
|
|
262
263
|
});
|
|
263
264
|
}
|
|
264
265
|
|
|
@@ -329,16 +330,22 @@ class ZipReader {
|
|
|
329
330
|
directoryDataOffset = getDiskOffset(reader, getUint32(endOfDirectoryLocatorView, 4)) + getBigUint64(endOfDirectoryLocatorView, 8);
|
|
330
331
|
let endOfDirectoryArray = await readUint8Array(reader, directoryDataOffset, ZIP64_END_OF_CENTRAL_DIR_LENGTH);
|
|
331
332
|
let endOfDirectoryView = getDataView(endOfDirectoryArray);
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
333
|
+
if (endOfDirectoryArray.length < ZIP64_END_OF_CENTRAL_DIR_LENGTH || getUint32(endOfDirectoryView, 0) != ZIP64_END_OF_CENTRAL_DIR_SIGNATURE) {
|
|
334
|
+
const locatorOffset = endOfDirectoryInfo.offset - ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH;
|
|
335
|
+
let expectedDirectoryDataOffset = locatorOffset - ZIP64_END_OF_CENTRAL_DIR_LENGTH;
|
|
336
|
+
if (!await startsWithSignature(reader, expectedDirectoryDataOffset, ZIP64_END_OF_CENTRAL_DIR_SIGNATURE)) {
|
|
337
|
+
expectedDirectoryDataOffset = await findZip64EndOfDirectoryOffset(reader, locatorOffset);
|
|
338
|
+
}
|
|
339
|
+
if (expectedDirectoryDataOffset !== UNDEFINED_VALUE && expectedDirectoryDataOffset >= 0 &&
|
|
340
|
+
directoryDataOffset != expectedDirectoryDataOffset) {
|
|
341
|
+
const originalDirectoryDataOffset = directoryDataOffset;
|
|
342
|
+
directoryDataOffset = expectedDirectoryDataOffset;
|
|
343
|
+
if (directoryDataOffset > originalDirectoryDataOffset) {
|
|
344
|
+
prependedDataLength = directoryDataOffset - originalDirectoryDataOffset;
|
|
345
|
+
}
|
|
346
|
+
endOfDirectoryArray = await readUint8Array(reader, directoryDataOffset, ZIP64_END_OF_CENTRAL_DIR_LENGTH);
|
|
347
|
+
endOfDirectoryView = getDataView(endOfDirectoryArray);
|
|
339
348
|
}
|
|
340
|
-
endOfDirectoryArray = await readUint8Array(reader, directoryDataOffset, ZIP64_END_OF_CENTRAL_DIR_LENGTH);
|
|
341
|
-
endOfDirectoryView = getDataView(endOfDirectoryArray);
|
|
342
349
|
}
|
|
343
350
|
if (endOfDirectoryArray.length < ZIP64_END_OF_CENTRAL_DIR_LENGTH || getUint32(endOfDirectoryView, 0) != ZIP64_END_OF_CENTRAL_DIR_SIGNATURE) {
|
|
344
351
|
throw new Error(ERR_EOCDR_LOCATOR_ZIP64_NOT_FOUND);
|
|
@@ -383,10 +390,6 @@ class ZipReader {
|
|
|
383
390
|
let declaredDirectoryDataLength = directoryDataLength;
|
|
384
391
|
const centralDirectoryEndOffset = endOfDirectoryInfo.offset -
|
|
385
392
|
(zip64EndOfDirectory ? zip64EndOfDirectoryLength + ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH : 0);
|
|
386
|
-
if (directoryDataOffset >= reader.size) {
|
|
387
|
-
prependedDataLength = reader.size - directoryDataOffset - directoryDataLength - END_OF_CENTRAL_DIR_LENGTH;
|
|
388
|
-
directoryDataOffset = reader.size - directoryDataLength - END_OF_CENTRAL_DIR_LENGTH;
|
|
389
|
-
}
|
|
390
393
|
if (expectedLastDiskNumber != lastDiskNumber) {
|
|
391
394
|
throw new Error(ERR_SPLIT_ZIP_FILE);
|
|
392
395
|
}
|
|
@@ -394,52 +397,64 @@ class ZipReader {
|
|
|
394
397
|
throw new Error(ERR_BAD_FORMAT);
|
|
395
398
|
}
|
|
396
399
|
let offset = 0;
|
|
397
|
-
let directoryArray =
|
|
400
|
+
let directoryArray = directoryDataOffset < reader.size ?
|
|
401
|
+
await readUint8Array(reader, directoryDataOffset, directoryDataLength) :
|
|
402
|
+
EMPTY_UINT8_ARRAY;
|
|
398
403
|
let directoryView = getDataView(directoryArray);
|
|
399
404
|
if (directoryDataLength) {
|
|
400
|
-
if (directoryArray.length < 4) {
|
|
401
|
-
throw new Error(ERR_BAD_FORMAT);
|
|
402
|
-
}
|
|
403
405
|
let expectedDirectoryDataOffset = centralDirectoryEndOffset - directoryDataLength;
|
|
404
406
|
if (directoryDataOffset != expectedDirectoryDataOffset && diskNumber == lastDiskNumber) {
|
|
405
|
-
const storedPointsAtDirectory =
|
|
407
|
+
const storedPointsAtDirectory = directoryArray.length >= 4 && (
|
|
408
|
+
getUint32(directoryView, offset) == CENTRAL_FILE_HEADER_SIGNATURE ||
|
|
406
409
|
Boolean(directoryEncryptionInfo && directoryEncryptionInfo.compressedSize) ||
|
|
407
|
-
detectEncryptedCentralDirectory(directoryView);
|
|
410
|
+
detectEncryptedCentralDirectory(directoryView));
|
|
411
|
+
if (!storedPointsAtDirectory && expectedDirectoryDataOffset < 0) {
|
|
412
|
+
throw new Error(ERR_BAD_FORMAT);
|
|
413
|
+
}
|
|
408
414
|
let reconcile = !storedPointsAtDirectory;
|
|
409
415
|
if (expectedDirectoryDataOffset >= 0 && expectedDirectoryDataOffset + 4 <= reader.size) {
|
|
410
|
-
|
|
411
|
-
if (
|
|
412
|
-
reconcile = expectedPointsAtDirectory;
|
|
413
|
-
} else if (!expectedPointsAtDirectory) {
|
|
416
|
+
let expectedPointsAtDirectory = await pointsAtDirectory(reader, expectedDirectoryDataOffset);
|
|
417
|
+
if (!expectedPointsAtDirectory) {
|
|
414
418
|
const signatureRecordOffset = await findDigitalSignatureRecordOffset(reader, centralDirectoryEndOffset);
|
|
415
419
|
const signedDirectoryDataOffset = signatureRecordOffset - directoryDataLength;
|
|
416
420
|
if (signatureRecordOffset !== UNDEFINED_VALUE && signedDirectoryDataOffset >= 0 &&
|
|
417
421
|
await pointsAtDirectory(reader, signedDirectoryDataOffset)) {
|
|
418
422
|
expectedDirectoryDataOffset = signedDirectoryDataOffset;
|
|
423
|
+
expectedPointsAtDirectory = true;
|
|
419
424
|
}
|
|
420
425
|
}
|
|
426
|
+
if (storedPointsAtDirectory) {
|
|
427
|
+
reconcile = expectedPointsAtDirectory;
|
|
428
|
+
}
|
|
421
429
|
}
|
|
422
|
-
if (reconcile) {
|
|
430
|
+
if (reconcile && expectedDirectoryDataOffset != directoryDataOffset) {
|
|
423
431
|
const originalDirectoryDataOffset = directoryDataOffset;
|
|
424
432
|
directoryDataOffset = expectedDirectoryDataOffset;
|
|
425
433
|
directoryArray = await readUint8Array(reader, directoryDataOffset, directoryDataLength);
|
|
426
434
|
directoryView = getDataView(directoryArray);
|
|
427
|
-
|
|
428
|
-
|
|
435
|
+
const offsetDelta = directoryDataOffset - originalDirectoryDataOffset;
|
|
436
|
+
const localHeaderOffset = getFirstLocalHeaderOffset(directoryArray, directoryView);
|
|
437
|
+
const localHeaderFound = localHeaderOffset !== UNDEFINED_VALUE &&
|
|
438
|
+
await startsWithSignature(reader, localHeaderOffset, LOCAL_FILE_HEADER_SIGNATURE);
|
|
439
|
+
const shiftedLocalHeaderFound = localHeaderOffset !== UNDEFINED_VALUE &&
|
|
440
|
+
await startsWithSignature(reader, localHeaderOffset + offsetDelta, LOCAL_FILE_HEADER_SIGNATURE);
|
|
441
|
+
if (offsetDelta > 0 && !(localHeaderFound && !shiftedLocalHeaderFound)) {
|
|
442
|
+
prependedDataLength += offsetDelta;
|
|
429
443
|
prependedCentralDirectory = storedPointsAtDirectory;
|
|
430
444
|
} else {
|
|
431
445
|
reportAmbiguity(checkAmbiguity, warnings, WARNING_MISMATCHED_CENTRAL_DIRECTORY_OFFSET);
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
const localHeaderOffset = getUint32(directoryView, 42);
|
|
435
|
-
if (!await startsWithSignature(reader, localHeaderOffset, LOCAL_FILE_HEADER_SIGNATURE) &&
|
|
436
|
-
await startsWithSignature(reader, localHeaderOffset + offsetDelta, LOCAL_FILE_HEADER_SIGNATURE)) {
|
|
437
|
-
prependedDataLength += offsetDelta;
|
|
438
|
-
}
|
|
446
|
+
if (offsetDelta < 0 && !localHeaderFound && shiftedLocalHeaderFound) {
|
|
447
|
+
prependedDataLength += offsetDelta;
|
|
439
448
|
}
|
|
440
449
|
}
|
|
441
450
|
}
|
|
442
451
|
}
|
|
452
|
+
if (directoryArray.length < 4) {
|
|
453
|
+
throw new Error(ERR_BAD_FORMAT);
|
|
454
|
+
}
|
|
455
|
+
} else if (!filesLength && directoryDataOffset < centralDirectoryEndOffset && diskNumber == lastDiskNumber) {
|
|
456
|
+
prependedDataLength += centralDirectoryEndOffset - directoryDataOffset;
|
|
457
|
+
directoryDataOffset = centralDirectoryEndOffset;
|
|
443
458
|
}
|
|
444
459
|
const expectedDirectoryDataLength = centralDirectoryEndOffset - directoryDataOffset;
|
|
445
460
|
if (directoryDataLength != expectedDirectoryDataLength && expectedDirectoryDataLength >= 0 && diskNumber == lastDiskNumber) {
|
|
@@ -481,8 +496,10 @@ class ZipReader {
|
|
|
481
496
|
addWarning(warnings, WARNING_WRAPPED_ENTRIES_COUNT);
|
|
482
497
|
}
|
|
483
498
|
}
|
|
499
|
+
const entryOptions = Object.assign({}, zipReader.options, options, { [OPTION_STRICTNESS]: strictness });
|
|
500
|
+
delete entryOptions[OPTION_CHECK_AMBIGUITY];
|
|
484
501
|
for (let indexFile = 0; indexFile < filesLength; indexFile++) {
|
|
485
|
-
const fileEntry = new ZipEntry(reader,
|
|
502
|
+
const fileEntry = new ZipEntry(reader, entryOptions);
|
|
486
503
|
if (offset + CENTRAL_FILE_HEADER_LENGTH > directoryArray.length || getUint32(directoryView, offset) != CENTRAL_FILE_HEADER_SIGNATURE) {
|
|
487
504
|
if (indexFile == 0 && !decryptedDirectory && (zip64EndOfDirectoryVersion2 || detectEncryptedCentralDirectory(directoryView))) {
|
|
488
505
|
throw new Error(ERR_ENCRYPTED_CENTRAL_DIRECTORY);
|
|
@@ -573,13 +590,17 @@ class ZipReader {
|
|
|
573
590
|
if (malformedExtraField) {
|
|
574
591
|
addWarning(warnings, WARNING_MALFORMED_EXTRA_FIELD, filename);
|
|
575
592
|
}
|
|
576
|
-
fileEntry.offset
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
593
|
+
if (fileEntry.zip64ExtraFieldMissing && fileEntry.offset == MAX_32_BITS) {
|
|
594
|
+
startOffset = 0;
|
|
595
|
+
} else {
|
|
596
|
+
fileEntry.offset += prependedDataLength;
|
|
597
|
+
const entryPosition = getDiskOffset(reader, fileEntry.diskNumberStart) + fileEntry.offset;
|
|
598
|
+
startOffset = Math.min(entryPosition, startOffset);
|
|
599
|
+
if (entryPosition < previousEntryPosition) {
|
|
600
|
+
addWarning(warnings, WARNING_UNSORTED_CENTRAL_DIRECTORY, filename);
|
|
601
|
+
}
|
|
602
|
+
previousEntryPosition = entryPosition;
|
|
581
603
|
}
|
|
582
|
-
previousEntryPosition = entryPosition;
|
|
583
604
|
if ((fileEntry.version & MAX_8_BITS) > MAX_KNOWN_VERSION) {
|
|
584
605
|
addWarning(warnings, WARNING_UNKNOWN_VERSION, filename);
|
|
585
606
|
}
|
|
@@ -616,12 +637,15 @@ class ZipReader {
|
|
|
616
637
|
zipCrypto: fileEntry.encrypted && !fileEntry.extraFieldAES
|
|
617
638
|
});
|
|
618
639
|
const entry = new Entry(fileEntry);
|
|
619
|
-
|
|
640
|
+
if (fileEntry.zip64ExtraFieldMissing) {
|
|
641
|
+
zipReader.entriesMissingZip64ExtraField.add(entry);
|
|
642
|
+
}
|
|
643
|
+
entry.getData = (writer, options) => fileEntry.getData(writer, entry, zipReader, options);
|
|
620
644
|
entry.arrayBuffer = async options => {
|
|
621
645
|
const writer = new TransformStream();
|
|
622
646
|
const arrayBufferPromise = streamToBlob(writer.readable).then(blob => blob.arrayBuffer());
|
|
623
647
|
arrayBufferPromise.catch(() => { });
|
|
624
|
-
await fileEntry.getData(writer, entry, zipReader
|
|
648
|
+
await fileEntry.getData(writer, entry, zipReader,
|
|
625
649
|
Object.assign({}, options, { preventClose: false }));
|
|
626
650
|
return arrayBufferPromise;
|
|
627
651
|
};
|
|
@@ -824,6 +848,7 @@ export {
|
|
|
824
848
|
ZipReader,
|
|
825
849
|
isZipFile,
|
|
826
850
|
ZipReaderStream,
|
|
851
|
+
getEntryDataDescriptorLength,
|
|
827
852
|
ERR_BAD_FORMAT,
|
|
828
853
|
ERR_EOCDR_NOT_FOUND,
|
|
829
854
|
ERR_EOCDR_LOCATOR_ZIP64_NOT_FOUND,
|
|
@@ -880,8 +905,9 @@ class ZipEntry {
|
|
|
880
905
|
});
|
|
881
906
|
}
|
|
882
907
|
|
|
883
|
-
async getData(writer, fileEntry,
|
|
908
|
+
async getData(writer, fileEntry, zipReader, options = {}) {
|
|
884
909
|
const zipEntry = this;
|
|
910
|
+
const { readRanges, directoryOffset } = zipReader;
|
|
885
911
|
if (zipEntry.zip64ExtraFieldMissing) {
|
|
886
912
|
throw new Error(ERR_EXTRAFIELD_ZIP64_NOT_FOUND);
|
|
887
913
|
}
|
|
@@ -955,10 +981,10 @@ class ZipEntry {
|
|
|
955
981
|
}
|
|
956
982
|
validateLocalDirectory(zipEntry, localDirectory, rawLocalFilename, checkLocalFilename, checkLocalDirectory ? UNDEFINED_VALUE : warnings);
|
|
957
983
|
const { lastAccessDate, creationDate, uid, gid } = localDirectory;
|
|
958
|
-
if (lastAccessDate) {
|
|
984
|
+
if (lastAccessDate && fileEntry.lastAccessDate === UNDEFINED_VALUE) {
|
|
959
985
|
fileEntry.lastAccessDate = lastAccessDate;
|
|
960
986
|
}
|
|
961
|
-
if (creationDate) {
|
|
987
|
+
if (creationDate && fileEntry.creationDate === UNDEFINED_VALUE) {
|
|
962
988
|
fileEntry.creationDate = creationDate;
|
|
963
989
|
}
|
|
964
990
|
if (uid !== UNDEFINED_VALUE && fileEntry.uid === UNDEFINED_VALUE) {
|
|
@@ -987,7 +1013,7 @@ class ZipEntry {
|
|
|
987
1013
|
throw new Error(ERR_ENCRYPTED);
|
|
988
1014
|
}
|
|
989
1015
|
}
|
|
990
|
-
if (dataOffset + compressedSize > reader.size) {
|
|
1016
|
+
if (dataOffset + compressedSize > Math.min(reader.size, directoryOffset)) {
|
|
991
1017
|
throw new Error(ERR_ENTRY_DATA_OUT_OF_BOUNDS);
|
|
992
1018
|
}
|
|
993
1019
|
const size = compressedSize;
|
|
@@ -1053,6 +1079,7 @@ class ZipEntry {
|
|
|
1053
1079
|
extraFieldZip64: extraFieldZip64 || localDirectory.extraFieldZip64,
|
|
1054
1080
|
readRanges
|
|
1055
1081
|
});
|
|
1082
|
+
validateDataDescriptor(zipEntry, localDirectory, checkLocalDirectory ? UNDEFINED_VALUE : warnings);
|
|
1056
1083
|
}
|
|
1057
1084
|
let writable, abortError, aborted;
|
|
1058
1085
|
try {
|
|
@@ -1072,10 +1099,7 @@ class ZipEntry {
|
|
|
1072
1099
|
writer.size += writtenSize;
|
|
1073
1100
|
}
|
|
1074
1101
|
} catch (error) {
|
|
1075
|
-
|
|
1076
|
-
if (failedOutputSize !== UNDEFINED_VALUE) {
|
|
1077
|
-
writer.size += failedOutputSize;
|
|
1078
|
-
} else if (isErrorObject(error) && error.outputSize !== UNDEFINED_VALUE) {
|
|
1102
|
+
if (isErrorObject(error) && error.outputSize !== UNDEFINED_VALUE) {
|
|
1079
1103
|
writer.size += error.outputSize;
|
|
1080
1104
|
}
|
|
1081
1105
|
if (!checkPasswordOnly || !isErrorObject(error) || error.message != ERR_ABORT_CHECK_PASSWORD) {
|
|
@@ -1103,13 +1127,7 @@ class ZipEntry {
|
|
|
1103
1127
|
}
|
|
1104
1128
|
|
|
1105
1129
|
function detectEncryptedCentralDirectory(directoryView) {
|
|
1106
|
-
|
|
1107
|
-
for (let offset = 0; offset < maxOffset; offset++) {
|
|
1108
|
-
if (getUint32(directoryView, offset) == ARCHIVE_EXTRA_DATA_SIGNATURE) {
|
|
1109
|
-
return true;
|
|
1110
|
-
}
|
|
1111
|
-
}
|
|
1112
|
-
return false;
|
|
1130
|
+
return directoryView.byteLength >= 4 && getUint32(directoryView, 0) == ARCHIVE_EXTRA_DATA_SIGNATURE;
|
|
1113
1131
|
}
|
|
1114
1132
|
|
|
1115
1133
|
function getWrappedFilesLength(directoryView, directoryArray, offset) {
|
|
@@ -1146,6 +1164,46 @@ async function findDigitalSignatureRecordOffset(reader, endOffset) {
|
|
|
1146
1164
|
}
|
|
1147
1165
|
}
|
|
1148
1166
|
|
|
1167
|
+
async function findZip64EndOfDirectoryOffset(reader, endOffset) {
|
|
1168
|
+
const startOffset = Math.max(0, endOffset - (ZIP64_END_OF_CENTRAL_DIR_LENGTH + MAX_16_BITS));
|
|
1169
|
+
const tailArray = await readUint8Array(reader, startOffset, endOffset - startOffset);
|
|
1170
|
+
const tailView = getDataView(tailArray);
|
|
1171
|
+
for (let indexByte = tailArray.length - ZIP64_END_OF_CENTRAL_DIR_LENGTH; indexByte >= 0; indexByte--) {
|
|
1172
|
+
if (getUint32(tailView, indexByte) == ZIP64_END_OF_CENTRAL_DIR_SIGNATURE &&
|
|
1173
|
+
indexByte + 12 + Number(tailView.getBigUint64(indexByte + 4, true)) == tailArray.length) {
|
|
1174
|
+
return startOffset + indexByte;
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
function getFirstLocalHeaderOffset(directoryArray, directoryView) {
|
|
1180
|
+
if (directoryArray.length < CENTRAL_FILE_HEADER_LENGTH) {
|
|
1181
|
+
return UNDEFINED_VALUE;
|
|
1182
|
+
}
|
|
1183
|
+
const localHeaderOffset = getUint32(directoryView, 42);
|
|
1184
|
+
if (localHeaderOffset != MAX_32_BITS) {
|
|
1185
|
+
return localHeaderOffset;
|
|
1186
|
+
}
|
|
1187
|
+
let offsetExtraField = CENTRAL_FILE_HEADER_LENGTH + getUint16(directoryView, 28);
|
|
1188
|
+
const endExtraField = Math.min(offsetExtraField + getUint16(directoryView, 30), directoryArray.length);
|
|
1189
|
+
while (offsetExtraField + 4 <= endExtraField) {
|
|
1190
|
+
const type = getUint16(directoryView, offsetExtraField);
|
|
1191
|
+
const size = getUint16(directoryView, offsetExtraField + 2);
|
|
1192
|
+
if (type == EXTRAFIELD_TYPE_ZIP64) {
|
|
1193
|
+
let offsetValue = offsetExtraField + 4;
|
|
1194
|
+
if (getUint32(directoryView, 24) == MAX_32_BITS) {
|
|
1195
|
+
offsetValue += 8;
|
|
1196
|
+
}
|
|
1197
|
+
if (getUint32(directoryView, 20) == MAX_32_BITS) {
|
|
1198
|
+
offsetValue += 8;
|
|
1199
|
+
}
|
|
1200
|
+
return offsetValue + 8 <= endExtraField ? getBigUint64(directoryView, offsetValue) : UNDEFINED_VALUE;
|
|
1201
|
+
}
|
|
1202
|
+
offsetExtraField += 4 + size;
|
|
1203
|
+
}
|
|
1204
|
+
return UNDEFINED_VALUE;
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1149
1207
|
function readDigitalSignature(signatureRecordArray) {
|
|
1150
1208
|
if (signatureRecordArray.length >= 6) {
|
|
1151
1209
|
const signatureRecordView = getDataView(signatureRecordArray);
|
|
@@ -1235,6 +1293,7 @@ function readCommonFooter(fileEntry, directory, dataView, offset, localDirectory
|
|
|
1235
1293
|
uncompressedSize: getUint32(dataView, offset + HEADER_OFFSET_UNCOMPRESSED_SIZE)
|
|
1236
1294
|
});
|
|
1237
1295
|
const extraFieldZip64 = extraField.get(EXTRAFIELD_TYPE_ZIP64);
|
|
1296
|
+
let extraFieldZip64Missing;
|
|
1238
1297
|
if (extraFieldZip64) {
|
|
1239
1298
|
if (!readExtraFieldZip64(extraFieldZip64, directory, localDirectory)) {
|
|
1240
1299
|
malformedExtraField = true;
|
|
@@ -1244,7 +1303,7 @@ function readCommonFooter(fileEntry, directory, dataView, offset, localDirectory
|
|
|
1244
1303
|
if (localDirectory) {
|
|
1245
1304
|
malformedExtraField = true;
|
|
1246
1305
|
} else {
|
|
1247
|
-
|
|
1306
|
+
extraFieldZip64Missing = true;
|
|
1248
1307
|
}
|
|
1249
1308
|
}
|
|
1250
1309
|
const extraFieldUnicodePath = extraField.get(EXTRAFIELD_TYPE_UNICODE_PATH);
|
|
@@ -1302,6 +1361,9 @@ function readCommonFooter(fileEntry, directory, dataView, offset, localDirectory
|
|
|
1302
1361
|
if (extraFieldUSDZ) {
|
|
1303
1362
|
directory.extraFieldUSDZ = extraFieldUSDZ;
|
|
1304
1363
|
}
|
|
1364
|
+
if (extraFieldZip64Missing) {
|
|
1365
|
+
throw new Error(ERR_EXTRAFIELD_ZIP64_NOT_FOUND);
|
|
1366
|
+
}
|
|
1305
1367
|
return malformedExtraField;
|
|
1306
1368
|
}
|
|
1307
1369
|
|
|
@@ -1516,13 +1578,7 @@ async function detectOverlappingEntry({
|
|
|
1516
1578
|
let dataDescriptorLength = 0;
|
|
1517
1579
|
if (dataDescriptor) {
|
|
1518
1580
|
const zip64 = Boolean(extraFieldZip64);
|
|
1519
|
-
const
|
|
1520
|
-
const dataDescriptorView = getDataView(dataDescriptorArray);
|
|
1521
|
-
const candidates = [[zip64, true], [zip64, false], [!zip64, true], [!zip64, false]]
|
|
1522
|
-
.map(([zip64Layout, signature]) => readDataDescriptor(dataDescriptorView, zip64Layout, signature))
|
|
1523
|
-
.filter(candidate => candidate && candidate.compressedSize == compressedSize && candidate.uncompressedSize == uncompressedSize);
|
|
1524
|
-
const localDataDescriptor = candidates.find(candidate => candidate.crc32 == crc32) || candidates[0] ||
|
|
1525
|
-
readDataDescriptor(dataDescriptorView, zip64, true) || readDataDescriptor(dataDescriptorView, zip64, false);
|
|
1581
|
+
const localDataDescriptor = await readLocalDataDescriptor(reader, dataOffset + compressedSize, { crc32, compressedSize, uncompressedSize, zip64 });
|
|
1526
1582
|
if (localDataDescriptor) {
|
|
1527
1583
|
fileEntry.localDirectory.dataDescriptor = localDataDescriptor;
|
|
1528
1584
|
dataDescriptorLength = getDataDescriptorLength(localDataDescriptor.zip64, localDataDescriptor.signature);
|
|
@@ -1592,6 +1648,25 @@ function mergeRanges(sortedRanges, pendingRanges) {
|
|
|
1592
1648
|
return mergedRanges;
|
|
1593
1649
|
}
|
|
1594
1650
|
|
|
1651
|
+
async function readLocalDataDescriptor(reader, offset, { crc32, compressedSize, uncompressedSize, zip64 }) {
|
|
1652
|
+
const maxLength = DATA_DESCRIPTOR_RECORD_ZIP_64_LENGTH + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH;
|
|
1653
|
+
const length = Math.min(maxLength, Math.max(0, reader.size - offset));
|
|
1654
|
+
const dataDescriptorArray = length ? await readUint8Array(reader, offset, length) : EMPTY_UINT8_ARRAY;
|
|
1655
|
+
const dataDescriptorView = getDataView(dataDescriptorArray);
|
|
1656
|
+
const candidates = [[zip64, true], [zip64, false], [!zip64, true], [!zip64, false]]
|
|
1657
|
+
.map(([zip64Layout, signature]) => readDataDescriptor(dataDescriptorView, zip64Layout, signature))
|
|
1658
|
+
.filter(candidate => candidate && candidate.compressedSize == compressedSize && candidate.uncompressedSize == uncompressedSize);
|
|
1659
|
+
return candidates.find(candidate => candidate.crc32 == crc32) || candidates[0] ||
|
|
1660
|
+
readDataDescriptor(dataDescriptorView, zip64, true) || readDataDescriptor(dataDescriptorView, zip64, false);
|
|
1661
|
+
}
|
|
1662
|
+
|
|
1663
|
+
async function getEntryDataDescriptorLength(reader, offset, { crc32, compressedSize, uncompressedSize, extraFieldZip64 }) {
|
|
1664
|
+
const dataDescriptor = await readLocalDataDescriptor(reader, offset, { crc32, compressedSize, uncompressedSize, zip64: Boolean(extraFieldZip64) });
|
|
1665
|
+
if (dataDescriptor && dataDescriptor.compressedSize == compressedSize && dataDescriptor.uncompressedSize == uncompressedSize) {
|
|
1666
|
+
return getDataDescriptorLength(dataDescriptor.zip64, dataDescriptor.signature);
|
|
1667
|
+
}
|
|
1668
|
+
}
|
|
1669
|
+
|
|
1595
1670
|
function readDataDescriptor(dataDescriptorView, zip64, signature) {
|
|
1596
1671
|
const offset = signature ? DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH : 0;
|
|
1597
1672
|
if (dataDescriptorView.byteLength < getDataDescriptorLength(zip64, signature) ||
|
|
@@ -1851,6 +1926,18 @@ function validateLocalDirectory(zipEntry, localDirectory, rawLocalFilename, chec
|
|
|
1851
1926
|
}
|
|
1852
1927
|
}
|
|
1853
1928
|
|
|
1929
|
+
function validateDataDescriptor(zipEntry, localDirectory, warnings) {
|
|
1930
|
+
const { dataDescriptor } = localDirectory;
|
|
1931
|
+
const maskedLocalDirectory = zipEntry.decryptedDirectory &&
|
|
1932
|
+
(localDirectory.rawBitFlag & BITFLAG_MASKED_LOCAL_HEADERS) == BITFLAG_MASKED_LOCAL_HEADERS;
|
|
1933
|
+
if (dataDescriptor && !maskedLocalDirectory &&
|
|
1934
|
+
((zipEntry.crc32 !== UNDEFINED_VALUE && dataDescriptor.crc32 != zipEntry.crc32) ||
|
|
1935
|
+
dataDescriptor.compressedSize != zipEntry.compressedSize ||
|
|
1936
|
+
dataDescriptor.uncompressedSize != zipEntry.uncompressedSize)) {
|
|
1937
|
+
reportAmbiguity(!warnings, warnings, WARNING_MISMATCHED_LOCAL_FILE_HEADER_CRC32_OR_SIZES);
|
|
1938
|
+
}
|
|
1939
|
+
}
|
|
1940
|
+
|
|
1854
1941
|
function reportAmbiguity(reject, warnings, reason) {
|
|
1855
1942
|
if (reject) {
|
|
1856
1943
|
throwAmbiguousArchive(reason);
|