@zip.js/zip.js 2.18.2 → 2.20.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/BENCHMARKS.md +172 -144
- package/deno.json +1 -1
- package/dist/zip-core-external.js +192 -120
- package/dist/zip-core-external.min.js +1 -1
- package/dist/zip-core.js +193 -119
- package/dist/zip-core.min.js +1 -1
- package/dist/zip-fs-core-external.js +192 -120
- package/dist/zip-fs-core-external.min.js +1 -1
- package/dist/zip-fs-core.js +193 -119
- package/dist/zip-fs-core.min.js +1 -1
- package/dist/zip-fs-external.js +192 -120
- package/dist/zip-fs-external.min.js +1 -1
- package/dist/zip-fs-native.js +195 -121
- package/dist/zip-fs-native.min.js +1 -1
- package/dist/zip-fs.js +194 -120
- package/dist/zip-fs.min.js +1 -1
- package/dist/zip-legacy.js +195 -121
- package/dist/zip-legacy.min.js +1 -1
- package/dist/zip-native.js +195 -121
- 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 +194 -120
- package/dist/zip.min.js +1 -1
- package/index-native.cjs +195 -121
- package/index-native.min.js +1 -1
- package/index.cjs +194 -120
- package/index.d.cts +95 -26
- package/index.d.ts +95 -26
- package/index.min.js +1 -1
- package/lib/core/codec-pool.js +1 -2
- package/lib/core/codec-worker-web.js +11 -39
- package/lib/core/codec-worker.js +1 -2
- package/lib/core/configuration.js +1 -1
- package/lib/core/options.js +0 -2
- package/lib/core/streams/codec-stream.js +1 -1
- package/lib/core/version.js +1 -1
- package/lib/core/web-worker-base.js +2 -3
- package/lib/core/web-worker-inline-native.js +1 -1
- package/lib/core/web-worker-inline-wasm.js +1 -1
- package/lib/core/zip-reader.js +100 -40
- package/lib/core/zip-writer.js +75 -34
- package/lib/zip-core-reader.js +2 -0
- package/package.json +1 -1
- package/worker-message-property-names.js +1 -1
package/lib/core/zip-reader.js
CHANGED
|
@@ -175,7 +175,6 @@ import {
|
|
|
175
175
|
STRICTNESS_TOLERANT,
|
|
176
176
|
OPTION_USE_WEB_WORKERS,
|
|
177
177
|
OPTION_USE_COMPRESSION_STREAM,
|
|
178
|
-
OPTION_TRANSFER_STREAMS,
|
|
179
178
|
OPTION_PREVENT_CLOSE,
|
|
180
179
|
checkFunctionOption,
|
|
181
180
|
checkSignalOption,
|
|
@@ -213,6 +212,8 @@ const WARNING_APPENDED_DATA = "appended data";
|
|
|
213
212
|
const WARNING_PREPENDED_DATA = "prepended data";
|
|
214
213
|
const WARNING_PREPENDED_CENTRAL_DIRECTORY = "prepended central directory";
|
|
215
214
|
const WARNING_TRAILING_CENTRAL_DIRECTORY_DATA = "trailing central directory data";
|
|
215
|
+
const WARNING_MISMATCHED_CENTRAL_DIRECTORY_OFFSET = "mismatched central directory offset";
|
|
216
|
+
const WARNING_MISSING_ZIP64_EXTRA_FIELD = "missing zip64 extra field";
|
|
216
217
|
const WARNING_DUPLICATE_FILENAME = "duplicate filename";
|
|
217
218
|
const WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY = "mismatched zip64 end of central directory record";
|
|
218
219
|
const WARNING_MULTIPLE_END_OF_CENTRAL_DIRECTORY = "multiple end of central directory records";
|
|
@@ -375,6 +376,8 @@ class ZipReader {
|
|
|
375
376
|
reportAmbiguity(checkAmbiguity, warnings, WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY);
|
|
376
377
|
}
|
|
377
378
|
directoryDataOffset = getDiskOffset(reader, diskNumber) + getBigUint64(endOfDirectoryView, 48) + prependedDataLength;
|
|
379
|
+
} else if (directoryDataOffset == MAX_32_BITS || directoryDataLength == MAX_32_BITS || diskNumber == MAX_16_BITS) {
|
|
380
|
+
throw new Error(ERR_EOCDR_LOCATOR_ZIP64_NOT_FOUND);
|
|
378
381
|
}
|
|
379
382
|
}
|
|
380
383
|
let declaredDirectoryDataLength = directoryDataLength;
|
|
@@ -397,25 +400,44 @@ class ZipReader {
|
|
|
397
400
|
if (directoryArray.length < 4) {
|
|
398
401
|
throw new Error(ERR_BAD_FORMAT);
|
|
399
402
|
}
|
|
400
|
-
|
|
403
|
+
let expectedDirectoryDataOffset = centralDirectoryEndOffset - directoryDataLength;
|
|
401
404
|
if (directoryDataOffset != expectedDirectoryDataOffset && diskNumber == lastDiskNumber) {
|
|
402
405
|
const storedPointsAtDirectory = getUint32(directoryView, offset) == CENTRAL_FILE_HEADER_SIGNATURE ||
|
|
403
406
|
Boolean(directoryEncryptionInfo && directoryEncryptionInfo.compressedSize) ||
|
|
404
407
|
detectEncryptedCentralDirectory(directoryView);
|
|
405
408
|
let reconcile = !storedPointsAtDirectory;
|
|
406
|
-
if (
|
|
407
|
-
const
|
|
408
|
-
|
|
409
|
+
if (expectedDirectoryDataOffset >= 0 && expectedDirectoryDataOffset + 4 <= reader.size) {
|
|
410
|
+
const expectedPointsAtDirectory = await pointsAtDirectory(reader, expectedDirectoryDataOffset);
|
|
411
|
+
if (storedPointsAtDirectory) {
|
|
412
|
+
reconcile = expectedPointsAtDirectory;
|
|
413
|
+
} else if (!expectedPointsAtDirectory) {
|
|
414
|
+
const signatureRecordOffset = await findDigitalSignatureRecordOffset(reader, centralDirectoryEndOffset);
|
|
415
|
+
const signedDirectoryDataOffset = signatureRecordOffset - directoryDataLength;
|
|
416
|
+
if (signatureRecordOffset !== UNDEFINED_VALUE && signedDirectoryDataOffset >= 0 &&
|
|
417
|
+
await pointsAtDirectory(reader, signedDirectoryDataOffset)) {
|
|
418
|
+
expectedDirectoryDataOffset = signedDirectoryDataOffset;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
409
421
|
}
|
|
410
422
|
if (reconcile) {
|
|
411
423
|
const originalDirectoryDataOffset = directoryDataOffset;
|
|
412
424
|
directoryDataOffset = expectedDirectoryDataOffset;
|
|
425
|
+
directoryArray = await readUint8Array(reader, directoryDataOffset, directoryDataLength);
|
|
426
|
+
directoryView = getDataView(directoryArray);
|
|
413
427
|
if (directoryDataOffset > originalDirectoryDataOffset) {
|
|
414
428
|
prependedDataLength += directoryDataOffset - originalDirectoryDataOffset;
|
|
415
429
|
prependedCentralDirectory = storedPointsAtDirectory;
|
|
430
|
+
} else {
|
|
431
|
+
reportAmbiguity(checkAmbiguity, warnings, WARNING_MISMATCHED_CENTRAL_DIRECTORY_OFFSET);
|
|
432
|
+
const offsetDelta = directoryDataOffset - originalDirectoryDataOffset;
|
|
433
|
+
if (directoryArray.length >= CENTRAL_FILE_HEADER_LENGTH) {
|
|
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
|
+
}
|
|
439
|
+
}
|
|
416
440
|
}
|
|
417
|
-
directoryArray = await readUint8Array(reader, directoryDataOffset, directoryDataLength);
|
|
418
|
-
directoryView = getDataView(directoryArray);
|
|
419
441
|
}
|
|
420
442
|
}
|
|
421
443
|
}
|
|
@@ -499,17 +521,6 @@ class ZipReader {
|
|
|
499
521
|
if (filename === UNDEFINED_VALUE) {
|
|
500
522
|
filename = decodeText(rawFilename, rawFilenameEncoding);
|
|
501
523
|
}
|
|
502
|
-
if (normalizeFilename) {
|
|
503
|
-
const normalizedFilename = normalizeFilename(filename);
|
|
504
|
-
if (normalizedFilename !== UNDEFINED_VALUE) {
|
|
505
|
-
filename = normalizedFilename;
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
if (isUnsafeFilename(filename, filenameValidation)) {
|
|
509
|
-
const error = new Error(ERR_UNSAFE_FILENAME);
|
|
510
|
-
error.filename = filename;
|
|
511
|
-
throw error;
|
|
512
|
-
}
|
|
513
524
|
let comment = decode(rawComment, rawCommentEncoding, TEXT_TYPE_COMMENT);
|
|
514
525
|
if (comment === UNDEFINED_VALUE) {
|
|
515
526
|
comment = decodeText(rawComment, rawCommentEncoding);
|
|
@@ -537,7 +548,29 @@ class ZipReader {
|
|
|
537
548
|
filename,
|
|
538
549
|
comment
|
|
539
550
|
});
|
|
540
|
-
|
|
551
|
+
let malformedExtraField;
|
|
552
|
+
try {
|
|
553
|
+
malformedExtraField = readCommonFooter(fileEntry, fileEntry, directoryView, offset + 6);
|
|
554
|
+
} catch (error) {
|
|
555
|
+
if (checkAmbiguity || error.message != ERR_EXTRAFIELD_ZIP64_NOT_FOUND) {
|
|
556
|
+
throw error;
|
|
557
|
+
}
|
|
558
|
+
fileEntry.zip64ExtraFieldMissing = true;
|
|
559
|
+
addWarning(warnings, WARNING_MISSING_ZIP64_EXTRA_FIELD, fileEntry.filename);
|
|
560
|
+
}
|
|
561
|
+
filename = fileEntry.filename;
|
|
562
|
+
if (normalizeFilename) {
|
|
563
|
+
const normalizedFilename = normalizeFilename(filename);
|
|
564
|
+
if (normalizedFilename !== UNDEFINED_VALUE) {
|
|
565
|
+
filename = fileEntry.filename = normalizedFilename;
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
if (isUnsafeFilename(filename, filenameValidation)) {
|
|
569
|
+
const error = new Error(ERR_UNSAFE_FILENAME);
|
|
570
|
+
error.filename = filename;
|
|
571
|
+
throw error;
|
|
572
|
+
}
|
|
573
|
+
if (malformedExtraField) {
|
|
541
574
|
addWarning(warnings, WARNING_MALFORMED_EXTRA_FIELD, filename);
|
|
542
575
|
}
|
|
543
576
|
fileEntry.offset += prependedDataLength;
|
|
@@ -566,11 +599,12 @@ class ZipReader {
|
|
|
566
599
|
const sticky = Boolean(fileEntry.unixMode & FILE_ATTR_UNIX_STICKY_MASK);
|
|
567
600
|
const unixType = fileEntry.unixMode === UNDEFINED_VALUE ? unixExternalUpper : fileEntry.unixMode;
|
|
568
601
|
const symlink = (unixType & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_SYMLINK;
|
|
569
|
-
const executable = !symlink && ((fileEntry.unixMode !== UNDEFINED_VALUE)
|
|
570
|
-
? ((fileEntry.unixMode & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0)
|
|
571
|
-
: (unixCompatible && ((unixExternalUpper & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0)));
|
|
572
602
|
const modeIsDir = fileEntry.unixMode !== UNDEFINED_VALUE && ((fileEntry.unixMode & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_DIR);
|
|
573
603
|
const upperIsDir = ((unixExternalUpper & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_DIR);
|
|
604
|
+
const directory = modeIsDir || upperIsDir || (msDosCompatible && msdosAttributes.directory) || fileEntry.filename.endsWith(DIRECTORY_SIGNATURE);
|
|
605
|
+
const executable = !symlink && !directory && ((fileEntry.unixMode !== UNDEFINED_VALUE)
|
|
606
|
+
? ((fileEntry.unixMode & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0)
|
|
607
|
+
: (unixCompatible && ((unixExternalUpper & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0)));
|
|
574
608
|
Object.assign(fileEntry, {
|
|
575
609
|
setuid,
|
|
576
610
|
setgid,
|
|
@@ -578,7 +612,7 @@ class ZipReader {
|
|
|
578
612
|
symlink,
|
|
579
613
|
unixExternalUpper,
|
|
580
614
|
executable,
|
|
581
|
-
directory
|
|
615
|
+
directory,
|
|
582
616
|
zipCrypto: fileEntry.encrypted && !fileEntry.extraFieldAES
|
|
583
617
|
});
|
|
584
618
|
const entry = new Entry(fileEntry);
|
|
@@ -634,10 +668,10 @@ class ZipReader {
|
|
|
634
668
|
const extractAppendedData = getOptionValue(zipReader, options, OPTION_EXTRACT_APPENDED_DATA);
|
|
635
669
|
const splitZipSignatureLength = (checkAmbiguity || extractPrependedData) && filesLength &&
|
|
636
670
|
startOffset == SPLIT_ZIP_FILE_SIGNATURE_LENGTH && await startsWithSplitZipMarker(reader) ? SPLIT_ZIP_FILE_SIGNATURE_LENGTH : 0;
|
|
637
|
-
if (checkAmbiguity && (prependedDataLength || (filesLength && startOffset > splitZipSignatureLength))) {
|
|
671
|
+
if (checkAmbiguity && (prependedDataLength > 0 || (filesLength && startOffset > splitZipSignatureLength))) {
|
|
638
672
|
throwAmbiguousArchive(WARNING_PREPENDED_DATA);
|
|
639
673
|
}
|
|
640
|
-
if (prependedDataLength || (filesLength && startOffset > SPLIT_ZIP_FILE_SIGNATURE_LENGTH)) {
|
|
674
|
+
if (prependedDataLength > 0 || (filesLength && startOffset > SPLIT_ZIP_FILE_SIGNATURE_LENGTH)) {
|
|
641
675
|
addWarning(warnings, WARNING_PREPENDED_DATA);
|
|
642
676
|
}
|
|
643
677
|
if (prependedCentralDirectory) {
|
|
@@ -826,6 +860,8 @@ export {
|
|
|
826
860
|
WARNING_PREPENDED_DATA,
|
|
827
861
|
WARNING_PREPENDED_CENTRAL_DIRECTORY,
|
|
828
862
|
WARNING_TRAILING_CENTRAL_DIRECTORY_DATA,
|
|
863
|
+
WARNING_MISMATCHED_CENTRAL_DIRECTORY_OFFSET,
|
|
864
|
+
WARNING_MISSING_ZIP64_EXTRA_FIELD,
|
|
829
865
|
WARNING_DUPLICATE_FILENAME,
|
|
830
866
|
WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY,
|
|
831
867
|
WARNING_MULTIPLE_END_OF_CENTRAL_DIRECTORY,
|
|
@@ -846,6 +882,9 @@ class ZipEntry {
|
|
|
846
882
|
|
|
847
883
|
async getData(writer, fileEntry, readRanges, options = {}) {
|
|
848
884
|
const zipEntry = this;
|
|
885
|
+
if (zipEntry.zip64ExtraFieldMissing) {
|
|
886
|
+
throw new Error(ERR_EXTRAFIELD_ZIP64_NOT_FOUND);
|
|
887
|
+
}
|
|
849
888
|
const config = getConfiguration();
|
|
850
889
|
const {
|
|
851
890
|
reader,
|
|
@@ -990,7 +1029,6 @@ class ZipEntry {
|
|
|
990
1029
|
encrypted,
|
|
991
1030
|
useWebWorkers: getOptionValue(zipEntry, options, OPTION_USE_WEB_WORKERS),
|
|
992
1031
|
useCompressionStream,
|
|
993
|
-
transferStreams: getOptionValue(zipEntry, options, OPTION_TRANSFER_STREAMS),
|
|
994
1032
|
deflate64,
|
|
995
1033
|
format: registeredCodec ? registeredCodec.format : UNDEFINED_VALUE,
|
|
996
1034
|
codecURI: registeredCodec ? registeredCodec.codecURI : UNDEFINED_VALUE,
|
|
@@ -1084,6 +1122,30 @@ function getWrappedFilesLength(directoryView, directoryArray, offset) {
|
|
|
1084
1122
|
return wrappedFilesLength % (MAX_16_BITS + 1) ? 0 : wrappedFilesLength;
|
|
1085
1123
|
}
|
|
1086
1124
|
|
|
1125
|
+
function pointsAtDirectory(reader, offset) {
|
|
1126
|
+
return startsWithSignature(reader, offset, CENTRAL_FILE_HEADER_SIGNATURE);
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
async function startsWithSignature(reader, offset, signature) {
|
|
1130
|
+
if (offset < 0 || offset + 4 > reader.size) {
|
|
1131
|
+
return false;
|
|
1132
|
+
}
|
|
1133
|
+
const signatureArray = await readUint8Array(reader, offset, 4);
|
|
1134
|
+
return getUint32(getDataView(signatureArray), 0) == signature;
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
async function findDigitalSignatureRecordOffset(reader, endOffset) {
|
|
1138
|
+
const startOffset = Math.max(0, endOffset - (6 + MAX_16_BITS));
|
|
1139
|
+
const tailArray = await readUint8Array(reader, startOffset, endOffset - startOffset);
|
|
1140
|
+
const tailView = getDataView(tailArray);
|
|
1141
|
+
for (let indexByte = tailArray.length - 6; indexByte >= 0; indexByte--) {
|
|
1142
|
+
if (getUint32(tailView, indexByte) == DIGITAL_SIGNATURE_RECORD_SIGNATURE &&
|
|
1143
|
+
indexByte + 6 + getUint16(tailView, indexByte + 4) == tailArray.length) {
|
|
1144
|
+
return startOffset + indexByte;
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1087
1149
|
function readDigitalSignature(signatureRecordArray) {
|
|
1088
1150
|
if (signatureRecordArray.length >= 6) {
|
|
1089
1151
|
const signatureRecordView = getDataView(signatureRecordArray);
|
|
@@ -1215,29 +1277,27 @@ function readCommonFooter(fileEntry, directory, dataView, offset, localDirectory
|
|
|
1215
1277
|
readExtraFieldUnixDates(extraFieldUnixType1, directory);
|
|
1216
1278
|
directory.extraFieldUnixType1 = extraFieldUnixType1;
|
|
1217
1279
|
}
|
|
1280
|
+
const extraFieldExtendedTimestamp = extraField.get(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
|
|
1281
|
+
if (extraFieldExtendedTimestamp) {
|
|
1282
|
+
readExtraFieldExtendedTimestamp(extraFieldExtendedTimestamp, directory, localDirectory);
|
|
1283
|
+
directory.extraFieldExtendedTimestamp = extraFieldExtendedTimestamp;
|
|
1284
|
+
}
|
|
1218
1285
|
const extraFieldNTFS = extraField.get(EXTRAFIELD_TYPE_NTFS);
|
|
1219
1286
|
if (extraFieldNTFS) {
|
|
1220
1287
|
readExtraFieldNTFS(extraFieldNTFS, directory);
|
|
1221
1288
|
directory.extraFieldNTFS = extraFieldNTFS;
|
|
1222
1289
|
}
|
|
1223
|
-
const
|
|
1290
|
+
const extraFieldInfoZip = extraField.get(EXTRAFIELD_TYPE_INFOZIP);
|
|
1224
1291
|
let unixIdsRead;
|
|
1292
|
+
if (extraFieldInfoZip) {
|
|
1293
|
+
unixIdsRead = readExtraFieldUnix(extraFieldInfoZip, directory, true);
|
|
1294
|
+
directory.extraFieldInfoZip = extraFieldInfoZip;
|
|
1295
|
+
}
|
|
1296
|
+
const extraFieldUnix = extraField.get(EXTRAFIELD_TYPE_UNIX);
|
|
1225
1297
|
if (extraFieldUnix) {
|
|
1226
|
-
|
|
1298
|
+
readExtraFieldUnix(extraFieldUnix, unixIdsRead ? {} : directory, false);
|
|
1227
1299
|
directory.extraFieldUnix = extraFieldUnix;
|
|
1228
1300
|
}
|
|
1229
|
-
if (!unixIdsRead) {
|
|
1230
|
-
const extraFieldInfoZip = extraField.get(EXTRAFIELD_TYPE_INFOZIP);
|
|
1231
|
-
if (extraFieldInfoZip) {
|
|
1232
|
-
readExtraFieldUnix(extraFieldInfoZip, directory, true);
|
|
1233
|
-
directory.extraFieldInfoZip = extraFieldInfoZip;
|
|
1234
|
-
}
|
|
1235
|
-
}
|
|
1236
|
-
const extraFieldExtendedTimestamp = extraField.get(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
|
|
1237
|
-
if (extraFieldExtendedTimestamp) {
|
|
1238
|
-
readExtraFieldExtendedTimestamp(extraFieldExtendedTimestamp, directory, localDirectory);
|
|
1239
|
-
directory.extraFieldExtendedTimestamp = extraFieldExtendedTimestamp;
|
|
1240
|
-
}
|
|
1241
1301
|
const extraFieldUSDZ = extraField.get(EXTRAFIELD_TYPE_USDZ);
|
|
1242
1302
|
if (extraFieldUSDZ) {
|
|
1243
1303
|
directory.extraFieldUSDZ = extraFieldUSDZ;
|
package/lib/core/zip-writer.js
CHANGED
|
@@ -218,7 +218,6 @@ import {
|
|
|
218
218
|
OPTION_SIGNAL,
|
|
219
219
|
OPTION_USE_WEB_WORKERS,
|
|
220
220
|
OPTION_USE_COMPRESSION_STREAM,
|
|
221
|
-
OPTION_TRANSFER_STREAMS,
|
|
222
221
|
OPTION_PREVENT_CLOSE,
|
|
223
222
|
OPTION_ENCRYPTION_STRENGTH,
|
|
224
223
|
OPTION_EXTENDED_TIMESTAMP,
|
|
@@ -343,13 +342,14 @@ class ZipWriter {
|
|
|
343
342
|
return watchPromiseError(this, prependZipEntries(this, reader));
|
|
344
343
|
}
|
|
345
344
|
|
|
346
|
-
appendZip(reader) {
|
|
347
|
-
return watchPromiseError(this, this.appendZipEntries(reader));
|
|
345
|
+
appendZip(reader, options = {}) {
|
|
346
|
+
return watchPromiseError(this, this.appendZipEntries(reader, options));
|
|
348
347
|
}
|
|
349
348
|
|
|
350
|
-
async appendZipEntries(reader) {
|
|
349
|
+
async appendZipEntries(reader, options = {}) {
|
|
351
350
|
const zipWriter = this;
|
|
352
351
|
const { pendingAddFileCalls, filenames, fileEntries } = zipWriter;
|
|
352
|
+
const filter = checkFunctionOption(options.filter);
|
|
353
353
|
while (pendingAddFileCalls.size) {
|
|
354
354
|
await Promise.allSettled(Array.from(pendingAddFileCalls));
|
|
355
355
|
}
|
|
@@ -368,10 +368,16 @@ class ZipWriter {
|
|
|
368
368
|
const { ZipReader } = await import("./zip-reader.js");
|
|
369
369
|
const zipReader = new ZipReader(reader);
|
|
370
370
|
const entries = await zipReader.getEntries();
|
|
371
|
+
const keptEntries = [];
|
|
372
|
+
for (const entry of entries) {
|
|
373
|
+
if (!filter || await filter(entry)) {
|
|
374
|
+
keptEntries.push(entry);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
371
377
|
await zipReader.close();
|
|
372
378
|
await initStream(zipWriter.writer);
|
|
373
379
|
const { directoryOffset } = zipReader;
|
|
374
|
-
|
|
380
|
+
keptEntries.forEach(({ filename }) => {
|
|
375
381
|
if (filenames.has(filename)) {
|
|
376
382
|
throw new Error(ERR_DUPLICATED_NAME);
|
|
377
383
|
}
|
|
@@ -392,8 +398,8 @@ class ZipWriter {
|
|
|
392
398
|
zipWriter.offset += SPLIT_ZIP_FILE_SIGNATURE_LENGTH;
|
|
393
399
|
}
|
|
394
400
|
}
|
|
395
|
-
const entryPositions = await copyZipData(zipWriter, reader, entries, directoryOffset);
|
|
396
|
-
|
|
401
|
+
const entryPositions = await copyZipData(zipWriter, reader, entries, keptEntries, directoryOffset, Boolean(filter));
|
|
402
|
+
keptEntries.forEach(entry => {
|
|
397
403
|
const {
|
|
398
404
|
version,
|
|
399
405
|
rawLastModDate,
|
|
@@ -449,6 +455,7 @@ class ZipWriter {
|
|
|
449
455
|
rawExtraFieldExtendedTimestamp: EMPTY_UINT8_ARRAY,
|
|
450
456
|
rawExtraFieldNTFS: EMPTY_UINT8_ARRAY,
|
|
451
457
|
rawExtraFieldUnix: EMPTY_UINT8_ARRAY,
|
|
458
|
+
rawCentralExtraFieldUnix: EMPTY_UINT8_ARRAY,
|
|
452
459
|
rawExtraField,
|
|
453
460
|
rawCentralExtraField: EMPTY_UINT8_ARRAY,
|
|
454
461
|
headerArray,
|
|
@@ -1063,7 +1070,6 @@ function resolveMetadata(zipWriter, name, options) {
|
|
|
1063
1070
|
const ntfsTimestamp = getOptionValue(zipWriter, options, OPTION_NTFS_TIMESTAMP);
|
|
1064
1071
|
const keepOrder = getOptionValue(zipWriter, options, OPTION_KEEP_ORDER, true);
|
|
1065
1072
|
const useWebWorkers = getOptionValue(zipWriter, options, OPTION_USE_WEB_WORKERS);
|
|
1066
|
-
const transferStreams = getOptionValue(zipWriter, options, OPTION_TRANSFER_STREAMS);
|
|
1067
1073
|
const bufferedWrite = getOptionValue(zipWriter, options, OPTION_BUFFERED_WRITE);
|
|
1068
1074
|
const createTempStream = getFunctionOptionValue(zipWriter, options, OPTION_CREATE_TEMP_STREAM);
|
|
1069
1075
|
const dataDescriptorSignature = getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR_SIGNATURE, true);
|
|
@@ -1129,7 +1135,6 @@ function resolveMetadata(zipWriter, name, options) {
|
|
|
1129
1135
|
ntfsTimestamp,
|
|
1130
1136
|
keepOrder,
|
|
1131
1137
|
useWebWorkers,
|
|
1132
|
-
transferStreams,
|
|
1133
1138
|
bufferedWrite,
|
|
1134
1139
|
createTempStream,
|
|
1135
1140
|
dataDescriptorSignature,
|
|
@@ -1188,7 +1193,7 @@ async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, op
|
|
|
1188
1193
|
if (reader) {
|
|
1189
1194
|
reader = new GenericReader(reader);
|
|
1190
1195
|
await initStream(reader);
|
|
1191
|
-
if (!reader.
|
|
1196
|
+
if (!reader.readUint8Array && !reader.readable) {
|
|
1192
1197
|
throw new Error(ERR_INVALID_READER);
|
|
1193
1198
|
}
|
|
1194
1199
|
({ size: contentSize } = reader);
|
|
@@ -1549,6 +1554,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
|
|
|
1549
1554
|
extraFieldExtendedTimestampTime,
|
|
1550
1555
|
rawExtraFieldNTFS,
|
|
1551
1556
|
rawExtraFieldUnix,
|
|
1557
|
+
rawCentralExtraFieldUnix,
|
|
1552
1558
|
rawExtraFieldAES,
|
|
1553
1559
|
} = headerInfo;
|
|
1554
1560
|
const { dataDescriptorArray } = dataDescriptorInfo;
|
|
@@ -1573,7 +1579,6 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
|
|
|
1573
1579
|
rawExtraField,
|
|
1574
1580
|
rawCentralExtraField,
|
|
1575
1581
|
useWebWorkers,
|
|
1576
|
-
transferStreams,
|
|
1577
1582
|
onstart,
|
|
1578
1583
|
onprogress,
|
|
1579
1584
|
onend,
|
|
@@ -1615,6 +1620,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
|
|
|
1615
1620
|
rawExtraFieldExtendedTimestamp,
|
|
1616
1621
|
rawExtraFieldNTFS,
|
|
1617
1622
|
rawExtraFieldUnix,
|
|
1623
|
+
rawCentralExtraFieldUnix,
|
|
1618
1624
|
rawExtraFieldAES,
|
|
1619
1625
|
rawExtraField,
|
|
1620
1626
|
rawCentralExtraField,
|
|
@@ -1661,7 +1667,6 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
|
|
|
1661
1667
|
encrypted: encrypted && !passThroughEncryption,
|
|
1662
1668
|
useWebWorkers,
|
|
1663
1669
|
useCompressionStream,
|
|
1664
|
-
transferStreams,
|
|
1665
1670
|
format,
|
|
1666
1671
|
codecURI,
|
|
1667
1672
|
compressionMethod
|
|
@@ -1839,6 +1844,7 @@ function getHeaderInfo(options) {
|
|
|
1839
1844
|
rawExtraFieldNTFS = rawExtraFieldExtendedTimestamp = EMPTY_UINT8_ARRAY;
|
|
1840
1845
|
}
|
|
1841
1846
|
let rawExtraFieldUnix;
|
|
1847
|
+
let rawCentralExtraFieldUnix;
|
|
1842
1848
|
try {
|
|
1843
1849
|
const { uid, gid, unixExtraFieldType } = options;
|
|
1844
1850
|
if (unixExtraFieldType == INFOZIP_EXTRA_FIELD_TYPE && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
|
|
@@ -1853,7 +1859,7 @@ function getHeaderInfo(options) {
|
|
|
1853
1859
|
extraFieldUnix.writeBytes(uidBytes);
|
|
1854
1860
|
extraFieldUnix.writeUint8(gidBytes.length);
|
|
1855
1861
|
extraFieldUnix.writeBytes(gidBytes);
|
|
1856
|
-
rawExtraFieldUnix = extraFieldUnix.array;
|
|
1862
|
+
rawExtraFieldUnix = rawCentralExtraFieldUnix = extraFieldUnix.array;
|
|
1857
1863
|
} else if (unixExtraFieldType == UNIX_EXTRA_FIELD_TYPE && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
|
|
1858
1864
|
const extraFieldUnix = createRecordWriter(8);
|
|
1859
1865
|
extraFieldUnix.writeUint16(EXTRAFIELD_TYPE_UNIX);
|
|
@@ -1861,11 +1867,15 @@ function getHeaderInfo(options) {
|
|
|
1861
1867
|
extraFieldUnix.writeUint16((uid === UNDEFINED_VALUE ? 0 : uid) & MAX_16_BITS);
|
|
1862
1868
|
extraFieldUnix.writeUint16((gid === UNDEFINED_VALUE ? 0 : gid) & MAX_16_BITS);
|
|
1863
1869
|
rawExtraFieldUnix = extraFieldUnix.array;
|
|
1870
|
+
const centralExtraFieldUnix = createRecordWriter(4);
|
|
1871
|
+
centralExtraFieldUnix.writeUint16(EXTRAFIELD_TYPE_UNIX);
|
|
1872
|
+
centralExtraFieldUnix.writeUint16(0);
|
|
1873
|
+
rawCentralExtraFieldUnix = centralExtraFieldUnix.array;
|
|
1864
1874
|
} else {
|
|
1865
|
-
rawExtraFieldUnix = EMPTY_UINT8_ARRAY;
|
|
1875
|
+
rawExtraFieldUnix = rawCentralExtraFieldUnix = EMPTY_UINT8_ARRAY;
|
|
1866
1876
|
}
|
|
1867
1877
|
} catch {
|
|
1868
|
-
rawExtraFieldUnix = EMPTY_UINT8_ARRAY;
|
|
1878
|
+
rawExtraFieldUnix = rawCentralExtraFieldUnix = EMPTY_UINT8_ARRAY;
|
|
1869
1879
|
}
|
|
1870
1880
|
if (compressionMethod === UNDEFINED_VALUE) {
|
|
1871
1881
|
compressionMethod = compressed ? COMPRESSION_METHOD_DEFLATE : COMPRESSION_METHOD_STORE;
|
|
@@ -1957,6 +1967,7 @@ function getHeaderInfo(options) {
|
|
|
1957
1967
|
rawExtraFieldExtendedTimestamp,
|
|
1958
1968
|
rawExtraFieldNTFS,
|
|
1959
1969
|
rawExtraFieldUnix,
|
|
1970
|
+
rawCentralExtraFieldUnix,
|
|
1960
1971
|
rawExtraFieldAES,
|
|
1961
1972
|
extraFieldLength
|
|
1962
1973
|
};
|
|
@@ -2132,7 +2143,7 @@ function createDirectoryRecords(files) {
|
|
|
2132
2143
|
rawExtraFieldAES,
|
|
2133
2144
|
rawComment,
|
|
2134
2145
|
rawExtraFieldNTFS,
|
|
2135
|
-
|
|
2146
|
+
rawCentralExtraFieldUnix,
|
|
2136
2147
|
rawExtraField,
|
|
2137
2148
|
rawCentralExtraField,
|
|
2138
2149
|
extraFieldExtendedTimestampFlag,
|
|
@@ -2194,7 +2205,7 @@ function createDirectoryRecords(files) {
|
|
|
2194
2205
|
rawExtraFieldZip64,
|
|
2195
2206
|
rawExtraFieldAES,
|
|
2196
2207
|
rawExtraFieldNTFS,
|
|
2197
|
-
|
|
2208
|
+
rawCentralExtraFieldUnix,
|
|
2198
2209
|
rawExtraFieldTimestamp,
|
|
2199
2210
|
rawExtraField,
|
|
2200
2211
|
rawCentralExtraField);
|
|
@@ -2223,7 +2234,7 @@ async function writeDirectoryRecords(zipWriter, directoryDataLength, options) {
|
|
|
2223
2234
|
rawExtraFieldAES,
|
|
2224
2235
|
rawExtraFieldExtendedTimestamp,
|
|
2225
2236
|
rawExtraFieldNTFS,
|
|
2226
|
-
|
|
2237
|
+
rawCentralExtraFieldUnix,
|
|
2227
2238
|
rawExtraField,
|
|
2228
2239
|
rawCentralExtraField,
|
|
2229
2240
|
rawComment,
|
|
@@ -2240,7 +2251,7 @@ async function writeDirectoryRecords(zipWriter, directoryDataLength, options) {
|
|
|
2240
2251
|
uncompressedSize,
|
|
2241
2252
|
compressedSize
|
|
2242
2253
|
} = fileEntry;
|
|
2243
|
-
const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS,
|
|
2254
|
+
const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawCentralExtraFieldUnix, rawExtraField, rawCentralExtraField);
|
|
2244
2255
|
const directoryRecordLength = CENTRAL_FILE_HEADER_LENGTH + getLength(rawFilename, rawComment) + extraFieldLength;
|
|
2245
2256
|
if (exceedsAvailableSize(writer, offset + directoryRecordLength - directoryDiskOffset)) {
|
|
2246
2257
|
await writeData(writer, directoryArray.slice(directoryDiskOffset, offset));
|
|
@@ -2276,7 +2287,7 @@ async function writeDirectoryRecords(zipWriter, directoryDataLength, options) {
|
|
|
2276
2287
|
directoryRecord.writeBytes(rawExtraFieldAES);
|
|
2277
2288
|
directoryRecord.writeBytes(rawExtraFieldExtendedTimestamp);
|
|
2278
2289
|
directoryRecord.writeBytes(rawExtraFieldNTFS);
|
|
2279
|
-
directoryRecord.writeBytes(
|
|
2290
|
+
directoryRecord.writeBytes(rawCentralExtraFieldUnix);
|
|
2280
2291
|
directoryRecord.writeBytes(rawExtraField);
|
|
2281
2292
|
directoryRecord.writeBytes(rawCentralExtraField);
|
|
2282
2293
|
directoryRecord.writeBytes(rawComment);
|
|
@@ -2445,26 +2456,42 @@ function removeExtraFieldZip64(rawExtraField) {
|
|
|
2445
2456
|
return rawExtraField;
|
|
2446
2457
|
}
|
|
2447
2458
|
|
|
2448
|
-
async function copyZipData(zipWriter, reader, entries, directoryOffset) {
|
|
2459
|
+
async function copyZipData(zipWriter, reader, entries, keptEntries, directoryOffset, compact) {
|
|
2449
2460
|
const { writer } = zipWriter;
|
|
2450
2461
|
const entryPositions = new Map();
|
|
2451
|
-
if (writer.closeDisk) {
|
|
2462
|
+
if (writer.closeDisk || compact) {
|
|
2452
2463
|
const sortedEntries = Array.from(entries).sort((firstEntry, secondEntry) =>
|
|
2453
2464
|
getSourceOffset(reader, firstEntry) - getSourceOffset(reader, secondEntry));
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2465
|
+
const regionEnds = getRegionEnds(reader, sortedEntries, directoryOffset);
|
|
2466
|
+
const keptEntrySet = new Set(keptEntries);
|
|
2467
|
+
let copiedOffset = 0;
|
|
2468
|
+
let lastPosition;
|
|
2469
|
+
for (let indexEntry = 0; indexEntry < sortedEntries.length; indexEntry++) {
|
|
2470
|
+
const entry = sortedEntries[indexEntry];
|
|
2471
|
+
if (keptEntrySet.has(entry)) {
|
|
2472
|
+
const sourceOffset = getSourceOffset(reader, entry);
|
|
2473
|
+
if (sourceOffset < copiedOffset) {
|
|
2474
|
+
entryPositions.set(entry, lastPosition);
|
|
2475
|
+
} else {
|
|
2476
|
+
if (!compact) {
|
|
2477
|
+
await copyData(zipWriter, reader, copiedOffset, sourceOffset - copiedOffset);
|
|
2478
|
+
}
|
|
2479
|
+
if (writer.closeDisk && exceedsAvailableSize(writer, await getLocalHeaderLength(reader, sourceOffset))) {
|
|
2480
|
+
await writer.closeDisk();
|
|
2481
|
+
}
|
|
2482
|
+
lastPosition = {
|
|
2483
|
+
offset: getSegmentOffset(zipWriter, writer),
|
|
2484
|
+
diskNumberStart: getDiskNumber(writer)
|
|
2485
|
+
};
|
|
2486
|
+
entryPositions.set(entry, lastPosition);
|
|
2487
|
+
await copyData(zipWriter, reader, sourceOffset, regionEnds[indexEntry] - sourceOffset);
|
|
2488
|
+
copiedOffset = regionEnds[indexEntry];
|
|
2489
|
+
}
|
|
2460
2490
|
}
|
|
2461
|
-
entryPositions.set(entry, {
|
|
2462
|
-
offset: getSegmentOffset(zipWriter, writer),
|
|
2463
|
-
diskNumberStart: getDiskNumber(writer)
|
|
2464
|
-
});
|
|
2465
|
-
copiedLength = sourceOffset;
|
|
2466
2491
|
}
|
|
2467
|
-
|
|
2492
|
+
if (!compact) {
|
|
2493
|
+
await copyData(zipWriter, reader, copiedOffset, directoryOffset - copiedOffset);
|
|
2494
|
+
}
|
|
2468
2495
|
} else {
|
|
2469
2496
|
const baseOffset = zipWriter.offset;
|
|
2470
2497
|
await copyData(zipWriter, reader, 0, directoryOffset);
|
|
@@ -2476,6 +2503,20 @@ async function copyZipData(zipWriter, reader, entries, directoryOffset) {
|
|
|
2476
2503
|
return entryPositions;
|
|
2477
2504
|
}
|
|
2478
2505
|
|
|
2506
|
+
function getRegionEnds(reader, sortedEntries, directoryOffset) {
|
|
2507
|
+
const regionEnds = new Array(sortedEntries.length);
|
|
2508
|
+
let regionEnd = directoryOffset;
|
|
2509
|
+
for (let indexEntry = sortedEntries.length - 1; indexEntry >= 0; indexEntry--) {
|
|
2510
|
+
const sourceOffset = getSourceOffset(reader, sortedEntries[indexEntry]);
|
|
2511
|
+
const nextEntry = sortedEntries[indexEntry + 1];
|
|
2512
|
+
if (nextEntry && getSourceOffset(reader, nextEntry) > sourceOffset) {
|
|
2513
|
+
regionEnd = getSourceOffset(reader, nextEntry);
|
|
2514
|
+
}
|
|
2515
|
+
regionEnds[indexEntry] = regionEnd;
|
|
2516
|
+
}
|
|
2517
|
+
return regionEnds;
|
|
2518
|
+
}
|
|
2519
|
+
|
|
2479
2520
|
async function copyData(zipWriter, reader, offset, size) {
|
|
2480
2521
|
if (size > 0) {
|
|
2481
2522
|
const { writer } = zipWriter;
|
package/lib/zip-core-reader.js
CHANGED
|
@@ -68,6 +68,8 @@ export {
|
|
|
68
68
|
WARNING_PREPENDED_DATA,
|
|
69
69
|
WARNING_PREPENDED_CENTRAL_DIRECTORY,
|
|
70
70
|
WARNING_TRAILING_CENTRAL_DIRECTORY_DATA,
|
|
71
|
+
WARNING_MISMATCHED_CENTRAL_DIRECTORY_OFFSET,
|
|
72
|
+
WARNING_MISSING_ZIP64_EXTRA_FIELD,
|
|
71
73
|
WARNING_DUPLICATE_FILENAME,
|
|
72
74
|
WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY,
|
|
73
75
|
WARNING_MULTIPLE_END_OF_CENTRAL_DIRECTORY,
|
package/package.json
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
const WORKER_MESSAGE_PROPERTY_NAMES = ["baseURI", "cause", "checkAuthenticationCode", "checkCrc32", "checkPasswordOnly", "chunkSize", "code", "codecImportFailed", "codecType", "codecURI", "compressed", "compressionMethod", "computeCrc32", "config", "crc32", "deflate64", "done", "encrypted", "encryptionStrength", "error", "errorValue", "format", "inputSize", "level", "message", "messageId", "name", "options", "outputSize", "password", "passwordVerification", "rawBitFlag", "rawPassword", "
|
|
1
|
+
const WORKER_MESSAGE_PROPERTY_NAMES = ["baseURI", "cause", "checkAuthenticationCode", "checkCrc32", "checkPasswordOnly", "chunkSize", "code", "codecImportFailed", "codecType", "codecURI", "compressed", "compressionMethod", "computeCrc32", "config", "crc32", "deflate64", "done", "encrypted", "encryptionStrength", "error", "errorValue", "format", "inputSize", "level", "message", "messageId", "name", "options", "outputSize", "password", "passwordVerification", "rawBitFlag", "rawPassword", "result", "stack", "type", "useCompressionStream", "useWebWorkers", "value", "wasmURI", "workerStartupTimeout", "zipCrypto"];
|
|
2
2
|
|
|
3
3
|
export { WORKER_MESSAGE_PROPERTY_NAMES };
|