@zip.js/zip.js 2.8.58 → 2.8.59
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 +157 -39
- package/dist/zip-core-external.min.js +1 -1
- package/dist/zip-core.js +171 -38
- package/dist/zip-core.min.js +1 -1
- package/dist/zip-fs-core-external.js +157 -40
- package/dist/zip-fs-core-external.min.js +1 -1
- package/dist/zip-fs-core.js +156 -39
- package/dist/zip-fs-core.min.js +1 -1
- package/dist/zip-fs-external.js +157 -40
- package/dist/zip-fs-external.min.js +1 -1
- package/dist/zip-fs-native.js +171 -39
- package/dist/zip-fs-native.min.js +1 -1
- package/dist/zip-fs.js +171 -39
- package/dist/zip-fs.min.js +1 -1
- package/dist/zip-legacy.js +171 -38
- package/dist/zip-legacy.min.js +1 -1
- package/dist/zip-native.js +171 -38
- package/dist/zip-native.min.js +1 -1
- package/dist/zip.js +171 -38
- package/dist/zip.min.js +1 -1
- package/index-native.cjs +171 -39
- package/index-native.min.js +1 -1
- package/index.cjs +171 -39
- package/index.d.cts +184 -1
- package/index.d.ts +184 -1
- package/index.min.js +1 -1
- package/lib/core/constants.js +2 -0
- package/lib/core/options.js +2 -0
- package/lib/core/zip-reader.js +143 -33
- package/lib/core/zip-writer.js +13 -6
- package/lib/zip-core-reader.js +16 -1
- package/package.json +1 -1
package/lib/core/constants.js
CHANGED
|
@@ -74,6 +74,7 @@ const BITFLAG_LEVEL_MAX_MASK = 0b010;
|
|
|
74
74
|
const BITFLAG_LEVEL_FAST_MASK = 0b100;
|
|
75
75
|
const BITFLAG_LEVEL_SUPER_FAST_MASK = 0b110;
|
|
76
76
|
const BITFLAG_DATA_DESCRIPTOR = 0b1000;
|
|
77
|
+
const BITFLAG_COMPRESSED_PATCHED_DATA = 0b100000;
|
|
77
78
|
const BITFLAG_STRONG_ENCRYPTION = 0b1000000;
|
|
78
79
|
const BITFLAG_LANG_ENCODING_FLAG = 0b100000000000;
|
|
79
80
|
const BITFLAG_MASKED_LOCAL_HEADERS = 0b10000000000000;
|
|
@@ -171,6 +172,7 @@ export {
|
|
|
171
172
|
BITFLAG_LEVEL_FAST_MASK,
|
|
172
173
|
BITFLAG_LEVEL_SUPER_FAST_MASK,
|
|
173
174
|
BITFLAG_DATA_DESCRIPTOR,
|
|
175
|
+
BITFLAG_COMPRESSED_PATCHED_DATA,
|
|
174
176
|
BITFLAG_STRONG_ENCRYPTION,
|
|
175
177
|
BITFLAG_LANG_ENCODING_FLAG,
|
|
176
178
|
BITFLAG_MASKED_LOCAL_HEADERS,
|
package/lib/core/options.js
CHANGED
|
@@ -70,6 +70,7 @@ const OPTION_OFFSET = "offset";
|
|
|
70
70
|
const OPTION_USDZ = "usdz";
|
|
71
71
|
const OPTION_UNIX_EXTRA_FIELD_TYPE = "unixExtraFieldType";
|
|
72
72
|
const OPTION_LOCAL_EXTRA_FIELD = "localExtraField";
|
|
73
|
+
const OPTION_CENTRAL_EXTRA_FIELD = "centralExtraField";
|
|
73
74
|
const OPTION_STRICTNESS = "strictness";
|
|
74
75
|
const OPTION_FILENAME_VALIDATION = "filenameValidation";
|
|
75
76
|
const OPTION_NORMALIZE_FILENAME = "normalizeFilename";
|
|
@@ -124,6 +125,7 @@ export {
|
|
|
124
125
|
OPTION_USDZ,
|
|
125
126
|
OPTION_UNIX_EXTRA_FIELD_TYPE,
|
|
126
127
|
OPTION_LOCAL_EXTRA_FIELD,
|
|
128
|
+
OPTION_CENTRAL_EXTRA_FIELD,
|
|
127
129
|
OPTION_STRICTNESS,
|
|
128
130
|
OPTION_FILENAME_VALIDATION,
|
|
129
131
|
OPTION_NORMALIZE_FILENAME,
|
package/lib/core/zip-reader.js
CHANGED
|
@@ -68,6 +68,7 @@ import {
|
|
|
68
68
|
ZIP64_END_OF_CENTRAL_DIR_LENGTH,
|
|
69
69
|
BITFLAG_ENCRYPTED,
|
|
70
70
|
BITFLAG_STRONG_ENCRYPTION,
|
|
71
|
+
BITFLAG_COMPRESSED_PATCHED_DATA,
|
|
71
72
|
BITFLAG_MASKED_LOCAL_HEADERS,
|
|
72
73
|
BITFLAG_LEVEL,
|
|
73
74
|
BITFLAG_DATA_DESCRIPTOR,
|
|
@@ -196,6 +197,21 @@ const ERR_INVALID_STRICTNESS = "Invalid strictness (must be 'strict', 'balanced'
|
|
|
196
197
|
const ERR_INVALID_FILENAME_VALIDATION = "Invalid filenameValidation (must be 'strict', 'balanced' or 'tolerant')";
|
|
197
198
|
const ERR_INVALID_MAX_APPENDED_DATA_SIZE = "Invalid maxAppendedDataSize (must be a number greater than or equal to 0)";
|
|
198
199
|
const ERR_UNSUPPORTED_UINT64 = "64-bit value exceeds Number.MAX_SAFE_INTEGER";
|
|
200
|
+
const WARNING_UNSORTED_CENTRAL_DIRECTORY = "unsorted central directory";
|
|
201
|
+
const WARNING_UNKNOWN_VERSION = "unknown version needed to extract";
|
|
202
|
+
const WARNING_COMPRESSED_PATCHED_DATA = "compressed patched data";
|
|
203
|
+
const WARNING_MALFORMED_EXTRA_FIELD = "malformed extra field";
|
|
204
|
+
const WARNING_UNKNOWN_ZIP64_EXTENSIBLE_DATA = "unknown zip64 extensible data";
|
|
205
|
+
const WARNING_WRAPPED_ENTRIES_COUNT = "wrapped entries count";
|
|
206
|
+
const WARNING_APPENDED_DATA = "appended data";
|
|
207
|
+
const WARNING_PREPENDED_DATA = "prepended data";
|
|
208
|
+
const WARNING_TRAILING_CENTRAL_DIRECTORY_DATA = "trailing central directory data";
|
|
209
|
+
const WARNING_DUPLICATE_FILENAME = "duplicate filename";
|
|
210
|
+
const WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY = "mismatched zip64 end of central directory record";
|
|
211
|
+
const WARNING_MISMATCHED_LOCAL_FILE_HEADER_BIT_FLAG = "mismatched local file header (general purpose bit flag)";
|
|
212
|
+
const WARNING_MISMATCHED_LOCAL_FILE_HEADER_COMPRESSION_METHOD = "mismatched local file header (compression method)";
|
|
213
|
+
const WARNING_MISMATCHED_LOCAL_FILE_HEADER_CRC32_OR_SIZES = "mismatched local file header (crc32 or sizes)";
|
|
214
|
+
const MAX_KNOWN_VERSION = 63;
|
|
199
215
|
const DRIVE_LETTER_REGEXP = /^[a-zA-Z]:/;
|
|
200
216
|
const CHARSET_UTF8 = "utf-8";
|
|
201
217
|
const PROPERTY_NAME_UTF8_SUFFIX = "UTF8";
|
|
@@ -246,6 +262,7 @@ class ZipReader {
|
|
|
246
262
|
if (reader.size < END_OF_CENTRAL_DIR_LENGTH) {
|
|
247
263
|
throw new Error(ERR_BAD_FORMAT);
|
|
248
264
|
}
|
|
265
|
+
const warnings = zipReader.warnings = [];
|
|
249
266
|
const strictness = getStrictness(options, zipReader.options);
|
|
250
267
|
const checkAmbiguity = strictness == STRICTNESS_STRICT;
|
|
251
268
|
const rejectAmbiguousEndOfDirectory = strictness != STRICTNESS_TOLERANT;
|
|
@@ -269,8 +286,12 @@ class ZipReader {
|
|
|
269
286
|
const commentOffset = endOfDirectoryInfo.offset;
|
|
270
287
|
const commentLength = getUint16(endOfDirectoryView, 20);
|
|
271
288
|
const appendedDataOffset = commentOffset + END_OF_CENTRAL_DIR_LENGTH + commentLength;
|
|
272
|
-
|
|
273
|
-
|
|
289
|
+
const appendedDataLength = reader.size - appendedDataOffset;
|
|
290
|
+
if (appendedDataLength > maxAppendedDataSize) {
|
|
291
|
+
throwAmbiguousArchive(WARNING_APPENDED_DATA);
|
|
292
|
+
}
|
|
293
|
+
if (appendedDataLength > 0) {
|
|
294
|
+
addWarning(warnings, WARNING_APPENDED_DATA);
|
|
274
295
|
}
|
|
275
296
|
let lastDiskNumber = getUint16(endOfDirectoryView, 4);
|
|
276
297
|
const expectedLastDiskNumber = reader.lastDiskNumber || 0;
|
|
@@ -324,23 +345,23 @@ class ZipReader {
|
|
|
324
345
|
}
|
|
325
346
|
if (lastDiskNumber == MAX_16_BITS) {
|
|
326
347
|
lastDiskNumber = getUint32(endOfDirectoryView, 16);
|
|
327
|
-
} else if (
|
|
328
|
-
|
|
348
|
+
} else if (lastDiskNumber != getUint32(endOfDirectoryView, 16)) {
|
|
349
|
+
reportAmbiguity(checkAmbiguity, warnings, WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY);
|
|
329
350
|
}
|
|
330
351
|
if (diskNumber == MAX_16_BITS) {
|
|
331
352
|
diskNumber = getUint32(endOfDirectoryView, 20);
|
|
332
|
-
} else if (
|
|
333
|
-
|
|
353
|
+
} else if (diskNumber != getUint32(endOfDirectoryView, 20)) {
|
|
354
|
+
reportAmbiguity(checkAmbiguity, warnings, WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY);
|
|
334
355
|
}
|
|
335
356
|
if (filesLength == MAX_16_BITS) {
|
|
336
357
|
filesLength = getBigUint64(endOfDirectoryView, 32);
|
|
337
|
-
} else if (
|
|
338
|
-
|
|
358
|
+
} else if (filesLength != getBigUint64(endOfDirectoryView, 32)) {
|
|
359
|
+
reportAmbiguity(checkAmbiguity, warnings, WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY);
|
|
339
360
|
}
|
|
340
361
|
if (directoryDataLength == MAX_32_BITS) {
|
|
341
362
|
directoryDataLength = getBigUint64(endOfDirectoryView, 40);
|
|
342
|
-
} else if (
|
|
343
|
-
|
|
363
|
+
} else if (directoryDataLength != getBigUint64(endOfDirectoryView, 40)) {
|
|
364
|
+
reportAmbiguity(checkAmbiguity, warnings, WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY);
|
|
344
365
|
}
|
|
345
366
|
directoryDataOffset = getDiskOffset(reader, diskNumber) + getBigUint64(endOfDirectoryView, 48) + prependedDataLength;
|
|
346
367
|
}
|
|
@@ -409,14 +430,22 @@ class ZipReader {
|
|
|
409
430
|
declaredDirectoryDataLength = directoryArray.length;
|
|
410
431
|
decryptedDirectory = true;
|
|
411
432
|
}
|
|
433
|
+
if (directoryEncryptionInfo && !decryptedDirectory &&
|
|
434
|
+
(directoryArray.length < 4 || getUint32(directoryView, 0) == CENTRAL_FILE_HEADER_SIGNATURE)) {
|
|
435
|
+
addWarning(warnings, WARNING_UNKNOWN_ZIP64_EXTENSIBLE_DATA);
|
|
436
|
+
}
|
|
412
437
|
startOffset = directoryDataOffset;
|
|
413
438
|
const filenameEncoding = getOptionValue(zipReader, options, OPTION_FILENAME_ENCODING);
|
|
414
439
|
const commentEncoding = getOptionValue(zipReader, options, OPTION_COMMENT_ENCODING);
|
|
415
|
-
const filenames =
|
|
440
|
+
const filenames = new Set();
|
|
416
441
|
let duplicateFilename;
|
|
442
|
+
let previousEntryPosition = -1;
|
|
417
443
|
const recoverWrappedFilesLength = !checkAmbiguity && !zip64EndOfDirectory;
|
|
418
444
|
if (!filesLength && recoverWrappedFilesLength) {
|
|
419
445
|
filesLength = getWrappedFilesLength(directoryView, directoryArray, offset);
|
|
446
|
+
if (filesLength) {
|
|
447
|
+
addWarning(warnings, WARNING_WRAPPED_ENTRIES_COUNT);
|
|
448
|
+
}
|
|
420
449
|
}
|
|
421
450
|
for (let indexFile = 0; indexFile < filesLength; indexFile++) {
|
|
422
451
|
const fileEntry = new ZipEntry(reader, zipReader.options);
|
|
@@ -495,15 +524,26 @@ class ZipReader {
|
|
|
495
524
|
filename,
|
|
496
525
|
comment
|
|
497
526
|
});
|
|
498
|
-
readCommonFooter(fileEntry, fileEntry, directoryView, offset + 6)
|
|
527
|
+
if (readCommonFooter(fileEntry, fileEntry, directoryView, offset + 6)) {
|
|
528
|
+
addWarning(warnings, WARNING_MALFORMED_EXTRA_FIELD, filename);
|
|
529
|
+
}
|
|
499
530
|
fileEntry.offset += prependedDataLength;
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
531
|
+
const entryPosition = getDiskOffset(reader, fileEntry.diskNumberStart) + fileEntry.offset;
|
|
532
|
+
startOffset = Math.min(entryPosition, startOffset);
|
|
533
|
+
if (entryPosition < previousEntryPosition) {
|
|
534
|
+
addWarning(warnings, WARNING_UNSORTED_CENTRAL_DIRECTORY, filename);
|
|
535
|
+
}
|
|
536
|
+
previousEntryPosition = entryPosition;
|
|
537
|
+
if ((fileEntry.version & MAX_8_BITS) > MAX_KNOWN_VERSION) {
|
|
538
|
+
addWarning(warnings, WARNING_UNKNOWN_VERSION, filename);
|
|
539
|
+
}
|
|
540
|
+
if ((fileEntry.rawBitFlag & BITFLAG_COMPRESSED_PATCHED_DATA) == BITFLAG_COMPRESSED_PATCHED_DATA) {
|
|
541
|
+
addWarning(warnings, WARNING_COMPRESSED_PATCHED_DATA, filename);
|
|
542
|
+
}
|
|
543
|
+
if (filenames.has(fileEntry.filename)) {
|
|
544
|
+
duplicateFilename = true;
|
|
506
545
|
}
|
|
546
|
+
filenames.add(fileEntry.filename);
|
|
507
547
|
const unixExternalUpper = (fileEntry.externalFileAttributes >> 16) & MAX_16_BITS;
|
|
508
548
|
if (fileEntry.unixMode === UNDEFINED_VALUE && (unixExternalUpper & (FILE_ATTR_UNIX_DEFAULT_MASK | FILE_ATTR_UNIX_EXECUTABLE_MASK | FILE_ATTR_UNIX_TYPE_DIR)) != 0) {
|
|
509
549
|
fileEntry.unixMode = unixExternalUpper;
|
|
@@ -541,7 +581,11 @@ class ZipReader {
|
|
|
541
581
|
};
|
|
542
582
|
offset = endOffset;
|
|
543
583
|
if (indexFile == filesLength - 1 && recoverWrappedFilesLength) {
|
|
544
|
-
|
|
584
|
+
const wrappedFilesLength = getWrappedFilesLength(directoryView, directoryArray, offset);
|
|
585
|
+
if (wrappedFilesLength) {
|
|
586
|
+
filesLength += wrappedFilesLength;
|
|
587
|
+
addWarning(warnings, WARNING_WRAPPED_ENTRIES_COUNT);
|
|
588
|
+
}
|
|
545
589
|
}
|
|
546
590
|
const { onprogress } = options;
|
|
547
591
|
if (onprogress) {
|
|
@@ -567,18 +611,22 @@ class ZipReader {
|
|
|
567
611
|
zipReader.digitalSignature = digitalSignature;
|
|
568
612
|
offsetAfterSignature = offset + 6 + digitalSignature.length;
|
|
569
613
|
}
|
|
570
|
-
if (
|
|
571
|
-
|
|
614
|
+
if ((offset != declaredDirectoryDataLength && offsetAfterSignature != declaredDirectoryDataLength) ||
|
|
615
|
+
(!decryptedDirectory && offset != directoryDataLength && offsetAfterSignature != directoryDataLength)) {
|
|
616
|
+
reportAmbiguity(checkAmbiguity, warnings, WARNING_TRAILING_CENTRAL_DIRECTORY_DATA);
|
|
572
617
|
}
|
|
573
618
|
if (duplicateFilename) {
|
|
574
|
-
|
|
619
|
+
reportAmbiguity(checkAmbiguity, warnings, WARNING_DUPLICATE_FILENAME);
|
|
575
620
|
}
|
|
576
621
|
const extractPrependedData = getOptionValue(zipReader, options, OPTION_EXTRACT_PREPENDED_DATA);
|
|
577
622
|
const extractAppendedData = getOptionValue(zipReader, options, OPTION_EXTRACT_APPENDED_DATA);
|
|
578
623
|
const splitZipSignatureLength = (checkAmbiguity || extractPrependedData) && filesLength &&
|
|
579
624
|
startOffset == SPLIT_ZIP_FILE_SIGNATURE_LENGTH && await startsWithSplitZipMarker(reader) ? SPLIT_ZIP_FILE_SIGNATURE_LENGTH : 0;
|
|
580
625
|
if (checkAmbiguity && (prependedDataLength || (filesLength && startOffset > splitZipSignatureLength))) {
|
|
581
|
-
throwAmbiguousArchive(
|
|
626
|
+
throwAmbiguousArchive(WARNING_PREPENDED_DATA);
|
|
627
|
+
}
|
|
628
|
+
if (prependedDataLength || (filesLength && startOffset > SPLIT_ZIP_FILE_SIGNATURE_LENGTH)) {
|
|
629
|
+
addWarning(warnings, WARNING_PREPENDED_DATA);
|
|
582
630
|
}
|
|
583
631
|
if (extractPrependedData) {
|
|
584
632
|
zipReader.prependedData = startOffset > splitZipSignatureLength ?
|
|
@@ -648,8 +696,31 @@ class ZipReaderStream {
|
|
|
648
696
|
}
|
|
649
697
|
}
|
|
650
698
|
|
|
699
|
+
async function isZipFile(reader, options = {}) {
|
|
700
|
+
reader = new GenericReader(reader);
|
|
701
|
+
await initStream(reader);
|
|
702
|
+
if (reader.size === UNDEFINED_VALUE || !reader.readUint8Array) {
|
|
703
|
+
reader = new BlobReader(await streamToBlob(reader.readable));
|
|
704
|
+
await initStream(reader);
|
|
705
|
+
}
|
|
706
|
+
if (reader.size < END_OF_CENTRAL_DIR_LENGTH) {
|
|
707
|
+
return false;
|
|
708
|
+
}
|
|
709
|
+
const strictness = getStrictness(options, {});
|
|
710
|
+
const rejectAmbiguousEndOfDirectory = strictness != STRICTNESS_TOLERANT;
|
|
711
|
+
const maxAppendedDataSize = getMaxAppendedDataSize(options[OPTION_MAX_APPENDED_DATA_SIZE], strictness);
|
|
712
|
+
const { endOfDirectoryInfo, endOfDirectoryReachingEndCount } = await findEndOfCentralDirectory(reader, rejectAmbiguousEndOfDirectory, maxAppendedDataSize);
|
|
713
|
+
if (!endOfDirectoryInfo || (strictness == STRICTNESS_STRICT && endOfDirectoryReachingEndCount > 1)) {
|
|
714
|
+
return false;
|
|
715
|
+
}
|
|
716
|
+
const commentLength = getUint16(getDataView(endOfDirectoryInfo), 20);
|
|
717
|
+
const appendedDataOffset = endOfDirectoryInfo.offset + END_OF_CENTRAL_DIR_LENGTH + commentLength;
|
|
718
|
+
return reader.size - appendedDataOffset <= maxAppendedDataSize;
|
|
719
|
+
}
|
|
720
|
+
|
|
651
721
|
export {
|
|
652
722
|
ZipReader,
|
|
723
|
+
isZipFile,
|
|
653
724
|
ZipReaderStream,
|
|
654
725
|
ERR_BAD_FORMAT,
|
|
655
726
|
ERR_EOCDR_NOT_FOUND,
|
|
@@ -676,7 +747,21 @@ export {
|
|
|
676
747
|
ERR_INVALID_FILENAME_VALIDATION,
|
|
677
748
|
ERR_INVALID_MAX_APPENDED_DATA_SIZE,
|
|
678
749
|
ERR_UNSUPPORTED_UINT64,
|
|
679
|
-
ERR_WORKER_STARTUP_TIMEOUT
|
|
750
|
+
ERR_WORKER_STARTUP_TIMEOUT,
|
|
751
|
+
WARNING_UNSORTED_CENTRAL_DIRECTORY,
|
|
752
|
+
WARNING_UNKNOWN_VERSION,
|
|
753
|
+
WARNING_COMPRESSED_PATCHED_DATA,
|
|
754
|
+
WARNING_MALFORMED_EXTRA_FIELD,
|
|
755
|
+
WARNING_UNKNOWN_ZIP64_EXTENSIBLE_DATA,
|
|
756
|
+
WARNING_WRAPPED_ENTRIES_COUNT,
|
|
757
|
+
WARNING_APPENDED_DATA,
|
|
758
|
+
WARNING_PREPENDED_DATA,
|
|
759
|
+
WARNING_TRAILING_CENTRAL_DIRECTORY_DATA,
|
|
760
|
+
WARNING_DUPLICATE_FILENAME,
|
|
761
|
+
WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY,
|
|
762
|
+
WARNING_MISMATCHED_LOCAL_FILE_HEADER_BIT_FLAG,
|
|
763
|
+
WARNING_MISMATCHED_LOCAL_FILE_HEADER_COMPRESSION_METHOD,
|
|
764
|
+
WARNING_MISMATCHED_LOCAL_FILE_HEADER_CRC32_OR_SIZES
|
|
680
765
|
};
|
|
681
766
|
|
|
682
767
|
class ZipEntry {
|
|
@@ -710,6 +795,7 @@ class ZipEntry {
|
|
|
710
795
|
dataDescriptor
|
|
711
796
|
} = bitFlag;
|
|
712
797
|
const localDirectory = fileEntry.localDirectory = {};
|
|
798
|
+
const warnings = fileEntry.warnings = [];
|
|
713
799
|
const localHeaderOffset = getDiskOffset(reader, diskNumberStart) + offset;
|
|
714
800
|
const dataArray = await readUint8Array(reader, localHeaderOffset, HEADER_SIZE);
|
|
715
801
|
const dataView = getDataView(dataArray);
|
|
@@ -750,10 +836,10 @@ class ZipEntry {
|
|
|
750
836
|
if (checkLocalFilename) {
|
|
751
837
|
localDirectory.rawFilename = rawLocalFilename;
|
|
752
838
|
}
|
|
753
|
-
readCommonFooter(zipEntry, localDirectory, dataView, 4, true)
|
|
754
|
-
|
|
755
|
-
validateLocalDirectory(zipEntry, localDirectory, rawLocalFilename, checkLocalFilename);
|
|
839
|
+
if (readCommonFooter(zipEntry, localDirectory, dataView, 4, true)) {
|
|
840
|
+
addWarning(warnings, WARNING_MALFORMED_EXTRA_FIELD);
|
|
756
841
|
}
|
|
842
|
+
validateLocalDirectory(zipEntry, localDirectory, rawLocalFilename, checkLocalFilename, checkLocalDirectory ? UNDEFINED_VALUE : warnings);
|
|
757
843
|
const { lastAccessDate, creationDate, uid, gid } = localDirectory;
|
|
758
844
|
if (lastAccessDate) {
|
|
759
845
|
fileEntry.lastAccessDate = lastAccessDate;
|
|
@@ -979,6 +1065,7 @@ function readCommonFooter(fileEntry, directory, dataView, offset, localDirectory
|
|
|
979
1065
|
const extraField = directory.extraField = new Map();
|
|
980
1066
|
const rawExtraFieldView = getDataView(rawExtraField);
|
|
981
1067
|
let offsetExtraField = 0;
|
|
1068
|
+
let malformedExtraField = false;
|
|
982
1069
|
try {
|
|
983
1070
|
while (offsetExtraField < rawExtraField.length) {
|
|
984
1071
|
const type = getUint16(rawExtraFieldView, offsetExtraField);
|
|
@@ -990,7 +1077,10 @@ function readCommonFooter(fileEntry, directory, dataView, offset, localDirectory
|
|
|
990
1077
|
offsetExtraField += 4 + size;
|
|
991
1078
|
}
|
|
992
1079
|
} catch {
|
|
993
|
-
|
|
1080
|
+
malformedExtraField = true;
|
|
1081
|
+
}
|
|
1082
|
+
if (offsetExtraField > rawExtraField.length) {
|
|
1083
|
+
malformedExtraField = true;
|
|
994
1084
|
}
|
|
995
1085
|
const compressionMethod = getUint16(dataView, offset + 4);
|
|
996
1086
|
Object.assign(directory, {
|
|
@@ -1058,6 +1148,7 @@ function readCommonFooter(fileEntry, directory, dataView, offset, localDirectory
|
|
|
1058
1148
|
if (extraFieldUSDZ) {
|
|
1059
1149
|
directory.extraFieldUSDZ = extraFieldUSDZ;
|
|
1060
1150
|
}
|
|
1151
|
+
return malformedExtraField;
|
|
1061
1152
|
}
|
|
1062
1153
|
|
|
1063
1154
|
function readExtraFieldZip64(extraFieldZip64, directory) {
|
|
@@ -1519,27 +1610,46 @@ async function readSignature(reader, view, anchoredOffset, signatureOffset, size
|
|
|
1519
1610
|
return UNDEFINED_VALUE;
|
|
1520
1611
|
}
|
|
1521
1612
|
|
|
1522
|
-
function validateLocalDirectory(zipEntry, localDirectory, rawLocalFilename, checkLocalFilename) {
|
|
1613
|
+
function validateLocalDirectory(zipEntry, localDirectory, rawLocalFilename, checkLocalFilename, warnings) {
|
|
1523
1614
|
const { rawFilename } = zipEntry;
|
|
1615
|
+
const reject = !warnings;
|
|
1524
1616
|
const maskedLocalDirectory = zipEntry.decryptedDirectory &&
|
|
1525
1617
|
(localDirectory.rawBitFlag & BITFLAG_MASKED_LOCAL_HEADERS) == BITFLAG_MASKED_LOCAL_HEADERS;
|
|
1526
1618
|
if (checkLocalFilename && !maskedLocalDirectory &&
|
|
1527
1619
|
(rawLocalFilename.length != rawFilename.length ||
|
|
1528
1620
|
rawLocalFilename.some((byteValue, indexByte) => byteValue != rawFilename[indexByte]))) {
|
|
1529
|
-
|
|
1621
|
+
reportAmbiguity(reject, warnings, "mismatched local file header (filename)");
|
|
1530
1622
|
}
|
|
1531
1623
|
if ((localDirectory.rawBitFlag & BITFLAG_AMBIGUITY_MASK) != (zipEntry.rawBitFlag & BITFLAG_AMBIGUITY_MASK)) {
|
|
1532
|
-
|
|
1624
|
+
reportAmbiguity(reject, warnings, WARNING_MISMATCHED_LOCAL_FILE_HEADER_BIT_FLAG);
|
|
1533
1625
|
}
|
|
1534
1626
|
if (localDirectory.compressionMethod != zipEntry.compressionMethod) {
|
|
1535
|
-
|
|
1627
|
+
reportAmbiguity(reject, warnings, WARNING_MISMATCHED_LOCAL_FILE_HEADER_COMPRESSION_METHOD);
|
|
1536
1628
|
}
|
|
1537
1629
|
if (!localDirectory.bitFlag.dataDescriptor && !maskedLocalDirectory &&
|
|
1538
1630
|
(localDirectory.crc32 || localDirectory.compressedSize || localDirectory.uncompressedSize) &&
|
|
1539
1631
|
(localDirectory.crc32 != zipEntry.crc32 ||
|
|
1540
1632
|
localDirectory.compressedSize != zipEntry.compressedSize ||
|
|
1541
1633
|
localDirectory.uncompressedSize != zipEntry.uncompressedSize)) {
|
|
1542
|
-
|
|
1634
|
+
reportAmbiguity(reject, warnings, WARNING_MISMATCHED_LOCAL_FILE_HEADER_CRC32_OR_SIZES);
|
|
1635
|
+
}
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1638
|
+
function reportAmbiguity(reject, warnings, reason) {
|
|
1639
|
+
if (reject) {
|
|
1640
|
+
throwAmbiguousArchive(reason);
|
|
1641
|
+
} else {
|
|
1642
|
+
addWarning(warnings, reason);
|
|
1643
|
+
}
|
|
1644
|
+
}
|
|
1645
|
+
|
|
1646
|
+
function addWarning(warnings, reason, filename) {
|
|
1647
|
+
if (!warnings.some(warning => warning.reason == reason)) {
|
|
1648
|
+
const warning = { reason };
|
|
1649
|
+
if (filename !== UNDEFINED_VALUE) {
|
|
1650
|
+
warning.filename = filename;
|
|
1651
|
+
}
|
|
1652
|
+
warnings.push(warning);
|
|
1543
1653
|
}
|
|
1544
1654
|
}
|
|
1545
1655
|
|
package/lib/core/zip-writer.js
CHANGED
|
@@ -230,6 +230,7 @@ import {
|
|
|
230
230
|
OPTION_USDZ,
|
|
231
231
|
OPTION_UNIX_EXTRA_FIELD_TYPE,
|
|
232
232
|
OPTION_LOCAL_EXTRA_FIELD,
|
|
233
|
+
OPTION_CENTRAL_EXTRA_FIELD,
|
|
233
234
|
OPTION_SIGN_CENTRAL_DIRECTORY,
|
|
234
235
|
TEXT_TYPE_FILENAME,
|
|
235
236
|
TEXT_TYPE_COMMENT,
|
|
@@ -423,6 +424,7 @@ class ZipWriter {
|
|
|
423
424
|
rawExtraFieldNTFS: EMPTY_UINT8_ARRAY,
|
|
424
425
|
rawExtraFieldUnix: EMPTY_UINT8_ARRAY,
|
|
425
426
|
rawExtraField,
|
|
427
|
+
rawCentralExtraField: EMPTY_UINT8_ARRAY,
|
|
426
428
|
extendedTimestamp: false,
|
|
427
429
|
headerArray,
|
|
428
430
|
headerView
|
|
@@ -596,7 +598,6 @@ async function prependZipEntries(zipWriter, reader) {
|
|
|
596
598
|
|
|
597
599
|
async function addFileEntry(zipWriter, name, reader, options) {
|
|
598
600
|
options = Object.assign({}, options);
|
|
599
|
-
name = name.trim();
|
|
600
601
|
if (getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY) && !name.endsWith(DIRECTORY_SIGNATURE)) {
|
|
601
602
|
name += DIRECTORY_SIGNATURE;
|
|
602
603
|
}
|
|
@@ -725,7 +726,6 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
725
726
|
}
|
|
726
727
|
|
|
727
728
|
function resolveAttributes(zipWriter, name, options) {
|
|
728
|
-
name = name.trim();
|
|
729
729
|
let msDosCompatible = getOptionValue(zipWriter, options, PROPERTY_NAME_MS_DOS_COMPATIBLE);
|
|
730
730
|
let versionMadeBy = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION_MADE_BY, msDosCompatible ? VERSION_MADE_BY_MSDOS : VERSION_MADE_BY_UNIX);
|
|
731
731
|
const executable = getOptionValue(zipWriter, options, PROPERTY_NAME_EXECUTABLE);
|
|
@@ -930,6 +930,7 @@ function resolveMetadata(zipWriter, name, options) {
|
|
|
930
930
|
}
|
|
931
931
|
const rawExtraField = serializeExtraField(options[PROPERTY_NAME_EXTRA_FIELD]);
|
|
932
932
|
const rawLocalExtraField = serializeExtraField(options[OPTION_LOCAL_EXTRA_FIELD]);
|
|
933
|
+
const rawCentralExtraField = serializeExtraField(options[OPTION_CENTRAL_EXTRA_FIELD]);
|
|
933
934
|
return {
|
|
934
935
|
comment,
|
|
935
936
|
resolvedOptions: {
|
|
@@ -965,7 +966,8 @@ function resolveMetadata(zipWriter, name, options) {
|
|
|
965
966
|
dataDescriptor,
|
|
966
967
|
zip64,
|
|
967
968
|
rawExtraField,
|
|
968
|
-
rawLocalExtraField
|
|
969
|
+
rawLocalExtraField,
|
|
970
|
+
rawCentralExtraField
|
|
969
971
|
}
|
|
970
972
|
};
|
|
971
973
|
}
|
|
@@ -1107,7 +1109,6 @@ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comm
|
|
|
1107
1109
|
let { name } = entry;
|
|
1108
1110
|
const { size } = entry;
|
|
1109
1111
|
const options = Object.assign({}, entry.options);
|
|
1110
|
-
name = name.trim();
|
|
1111
1112
|
if (getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY) && !name.endsWith(DIRECTORY_SIGNATURE)) {
|
|
1112
1113
|
name += DIRECTORY_SIGNATURE;
|
|
1113
1114
|
}
|
|
@@ -1363,6 +1364,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
|
|
|
1363
1364
|
versionMadeBy,
|
|
1364
1365
|
rawComment,
|
|
1365
1366
|
rawExtraField,
|
|
1367
|
+
rawCentralExtraField,
|
|
1366
1368
|
useWebWorkers,
|
|
1367
1369
|
transferStreams,
|
|
1368
1370
|
onstart,
|
|
@@ -1406,6 +1408,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
|
|
|
1406
1408
|
rawExtraFieldUnix,
|
|
1407
1409
|
rawExtraFieldAES,
|
|
1408
1410
|
rawExtraField,
|
|
1411
|
+
rawCentralExtraField,
|
|
1409
1412
|
extendedTimestamp,
|
|
1410
1413
|
msDosCompatible,
|
|
1411
1414
|
internalFileAttributes,
|
|
@@ -1906,6 +1909,7 @@ function createDirectoryRecords(files) {
|
|
|
1906
1909
|
rawExtraFieldNTFS,
|
|
1907
1910
|
rawExtraFieldUnix,
|
|
1908
1911
|
rawExtraField,
|
|
1912
|
+
rawCentralExtraField,
|
|
1909
1913
|
extendedTimestamp,
|
|
1910
1914
|
extraFieldExtendedTimestampFlag,
|
|
1911
1915
|
lastModDate,
|
|
@@ -1960,7 +1964,8 @@ function createDirectoryRecords(files) {
|
|
|
1960
1964
|
rawExtraFieldNTFS,
|
|
1961
1965
|
rawExtraFieldUnix,
|
|
1962
1966
|
rawExtraFieldTimestamp,
|
|
1963
|
-
rawExtraField
|
|
1967
|
+
rawExtraField,
|
|
1968
|
+
rawCentralExtraField);
|
|
1964
1969
|
if (extraFieldLength > MAX_16_BITS) {
|
|
1965
1970
|
throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
|
|
1966
1971
|
}
|
|
@@ -1988,6 +1993,7 @@ async function writeDirectoryRecords(zipWriter, directoryDataLength, options) {
|
|
|
1988
1993
|
rawExtraFieldNTFS,
|
|
1989
1994
|
rawExtraFieldUnix,
|
|
1990
1995
|
rawExtraField,
|
|
1996
|
+
rawCentralExtraField,
|
|
1991
1997
|
rawComment,
|
|
1992
1998
|
versionMadeBy,
|
|
1993
1999
|
headerArray,
|
|
@@ -2002,7 +2008,7 @@ async function writeDirectoryRecords(zipWriter, directoryDataLength, options) {
|
|
|
2002
2008
|
uncompressedSize,
|
|
2003
2009
|
compressedSize
|
|
2004
2010
|
} = fileEntry;
|
|
2005
|
-
const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField);
|
|
2011
|
+
const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField, rawCentralExtraField);
|
|
2006
2012
|
const directoryRecordLength = CENTRAL_FILE_HEADER_LENGTH + getLength(rawFilename, rawComment) + extraFieldLength;
|
|
2007
2013
|
if (exceedsAvailableSize(writer, offset + directoryRecordLength - directoryDiskOffset)) {
|
|
2008
2014
|
await writeData(writer, directoryArray.slice(directoryDiskOffset, offset));
|
|
@@ -2040,6 +2046,7 @@ async function writeDirectoryRecords(zipWriter, directoryDataLength, options) {
|
|
|
2040
2046
|
directoryRecord.writeBytes(rawExtraFieldNTFS);
|
|
2041
2047
|
directoryRecord.writeBytes(rawExtraFieldUnix);
|
|
2042
2048
|
directoryRecord.writeBytes(rawExtraField);
|
|
2049
|
+
directoryRecord.writeBytes(rawCentralExtraField);
|
|
2043
2050
|
directoryRecord.writeBytes(rawComment);
|
|
2044
2051
|
arraySet(directoryArray, directoryRecord.array, offset);
|
|
2045
2052
|
offset += directoryRecordLength;
|
package/lib/zip-core-reader.js
CHANGED
|
@@ -31,6 +31,7 @@ import "./core/codec-worker-web.js";
|
|
|
31
31
|
export {
|
|
32
32
|
ZipReader,
|
|
33
33
|
ZipReaderStream,
|
|
34
|
+
isZipFile,
|
|
34
35
|
ERR_BAD_FORMAT,
|
|
35
36
|
ERR_EOCDR_NOT_FOUND,
|
|
36
37
|
ERR_EOCDR_LOCATOR_ZIP64_NOT_FOUND,
|
|
@@ -56,5 +57,19 @@ export {
|
|
|
56
57
|
ERR_INVALID_FILENAME_VALIDATION,
|
|
57
58
|
ERR_INVALID_MAX_APPENDED_DATA_SIZE,
|
|
58
59
|
ERR_UNSUPPORTED_UINT64,
|
|
59
|
-
ERR_WORKER_STARTUP_TIMEOUT
|
|
60
|
+
ERR_WORKER_STARTUP_TIMEOUT,
|
|
61
|
+
WARNING_UNSORTED_CENTRAL_DIRECTORY,
|
|
62
|
+
WARNING_UNKNOWN_VERSION,
|
|
63
|
+
WARNING_COMPRESSED_PATCHED_DATA,
|
|
64
|
+
WARNING_MALFORMED_EXTRA_FIELD,
|
|
65
|
+
WARNING_UNKNOWN_ZIP64_EXTENSIBLE_DATA,
|
|
66
|
+
WARNING_WRAPPED_ENTRIES_COUNT,
|
|
67
|
+
WARNING_APPENDED_DATA,
|
|
68
|
+
WARNING_PREPENDED_DATA,
|
|
69
|
+
WARNING_TRAILING_CENTRAL_DIRECTORY_DATA,
|
|
70
|
+
WARNING_DUPLICATE_FILENAME,
|
|
71
|
+
WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY,
|
|
72
|
+
WARNING_MISMATCHED_LOCAL_FILE_HEADER_BIT_FLAG,
|
|
73
|
+
WARNING_MISMATCHED_LOCAL_FILE_HEADER_COMPRESSION_METHOD,
|
|
74
|
+
WARNING_MISMATCHED_LOCAL_FILE_HEADER_CRC32_OR_SIZES
|
|
60
75
|
} from "./core/zip-reader.js";
|
package/package.json
CHANGED