@zip.js/zip.js 2.8.51 → 2.8.52
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 +8 -3
- package/deno.json +1 -1
- package/dist/zip-core-external.js +88 -44
- package/dist/zip-core-external.min.js +1 -1
- package/dist/zip-core.js +89 -43
- package/dist/zip-core.min.js +1 -1
- package/dist/zip-fs-core-external.js +408 -148
- package/dist/zip-fs-core-external.min.js +1 -1
- package/dist/zip-fs-core.js +408 -147
- package/dist/zip-fs-core.min.js +1 -1
- package/dist/zip-fs-external.js +408 -148
- package/dist/zip-fs-external.min.js +1 -1
- package/dist/zip-fs-native.js +410 -147
- package/dist/zip-fs-native.min.js +1 -1
- package/dist/zip-fs.js +410 -147
- package/dist/zip-fs.min.js +1 -1
- package/dist/zip-legacy.js +89 -43
- package/dist/zip-legacy.min.js +1 -1
- package/dist/zip-native.js +89 -43
- package/dist/zip-native.min.js +1 -1
- package/dist/zip.js +89 -43
- package/dist/zip.min.js +1 -1
- package/index-native.cjs +410 -147
- package/index-native.min.js +1 -1
- package/index.cjs +410 -147
- package/index.d.cts +278 -10
- package/index.d.ts +278 -10
- package/index.min.js +1 -1
- package/lib/core/codec-worker.js +2 -0
- package/lib/core/constants.js +4 -0
- package/lib/core/io.js +32 -2
- package/lib/core/util/compatible-streams.js +3 -8
- package/lib/core/zip-entry.js +8 -0
- package/lib/core/zip-fs.js +236 -107
- package/lib/core/zip-reader.js +15 -6
- package/lib/core/zip-writer.js +135 -29
- package/lib/zip-core-writer.js +2 -0
- package/package.json +5 -5
package/lib/core/zip-fs.js
CHANGED
|
@@ -34,26 +34,31 @@ import {
|
|
|
34
34
|
Reader,
|
|
35
35
|
TextReader,
|
|
36
36
|
TextWriter,
|
|
37
|
+
getTextSize,
|
|
37
38
|
Data64URIReader,
|
|
38
39
|
Data64URIWriter,
|
|
39
40
|
Uint8ArrayReader,
|
|
40
41
|
Uint8ArrayWriter,
|
|
41
42
|
BlobReader,
|
|
42
43
|
BlobWriter,
|
|
43
|
-
HttpReader
|
|
44
|
+
HttpReader,
|
|
45
|
+
ownsWritable
|
|
44
46
|
} from "./io.js";
|
|
45
47
|
import {
|
|
46
48
|
ZipReader,
|
|
47
49
|
ERR_INVALID_PASSWORD
|
|
48
50
|
} from "./zip-reader.js";
|
|
49
51
|
import {
|
|
50
|
-
ZipWriter
|
|
52
|
+
ZipWriter,
|
|
53
|
+
getEntriesSize
|
|
51
54
|
} from "./zip-writer.js";
|
|
52
55
|
import {
|
|
53
56
|
Entry
|
|
54
57
|
} from "./zip-entry.js";
|
|
58
|
+
import { ProgressWatcherStream, callHandler } from "./codec-worker.js";
|
|
55
59
|
import {
|
|
56
60
|
UNDEFINED_VALUE,
|
|
61
|
+
FUNCTION_TYPE,
|
|
57
62
|
EXTRAFIELD_TYPE_ZIP64,
|
|
58
63
|
EXTRAFIELD_TYPE_AES,
|
|
59
64
|
EXTRAFIELD_TYPE_NTFS,
|
|
@@ -71,6 +76,7 @@ import { toCompatibleReadable, toCompatibleWritable } from "./util/compatible-st
|
|
|
71
76
|
|
|
72
77
|
const ERR_ENTRY_EXISTS = "Entry filename already exists";
|
|
73
78
|
const ERR_READABLE_CONSUMED = "Readable stream already consumed";
|
|
79
|
+
const ERR_INVALID_PASS_THROUGH = "Invalid passThrough option (use readerOptions.passThrough or set uncompressedSize for each entry)";
|
|
74
80
|
const ERR_ABORT_EXPORT = "zipjs-abort-export";
|
|
75
81
|
const ERR_ABORTED = "The operation was aborted";
|
|
76
82
|
const ABORT_ERROR_NAME = "AbortError";
|
|
@@ -108,6 +114,7 @@ class ZipEntry {
|
|
|
108
114
|
parent,
|
|
109
115
|
children: [],
|
|
110
116
|
uncompressedSize: params.uncompressedSize || 0,
|
|
117
|
+
undeterminedSize: params.undeterminedSize || params.uncompressedSize === UNDEFINED_VALUE,
|
|
111
118
|
passThrough: params.passThrough
|
|
112
119
|
});
|
|
113
120
|
if (parent || !fs.root) {
|
|
@@ -175,16 +182,17 @@ class ZipFileEntry extends ZipEntry {
|
|
|
175
182
|
|
|
176
183
|
async getData(writer, options = {}) {
|
|
177
184
|
const zipEntry = this;
|
|
178
|
-
if (!writer || (writer.constructor == zipEntry.Writer && zipEntry.data)) {
|
|
185
|
+
if (!writer || (writer.constructor == zipEntry.Writer && zipEntry.data && keepsContentType(writer, zipEntry.data))) {
|
|
179
186
|
return zipEntry.data;
|
|
180
187
|
} else {
|
|
181
188
|
const reader = zipEntry.reader = createReader(zipEntry.Reader, zipEntry.data, options);
|
|
182
|
-
const
|
|
183
|
-
await Promise.all([initStream(reader), initStream(writer,
|
|
184
|
-
const { readable } = reader;
|
|
189
|
+
const dataSize = zipEntry.uncompressedSize || reader.size;
|
|
190
|
+
await Promise.all([initStream(reader), initStream(writer, dataSize)]);
|
|
185
191
|
const { signal } = options;
|
|
192
|
+
const readable = createProgressReadable(zipEntry, reader, options, signal);
|
|
193
|
+
const preventClose = !ownsWritable(writer) && Boolean(options.preventClose);
|
|
186
194
|
zipEntry.uncompressedSize = reader.size;
|
|
187
|
-
await toCompatibleReadable(readable).pipeTo(toCompatibleWritable(writer.writable), { signal });
|
|
195
|
+
await toCompatibleReadable(readable).pipeTo(toCompatibleWritable(writer.writable), { signal, preventClose, preventAbort: preventClose });
|
|
188
196
|
return writer.getData ? writer.getData() : writer.writable;
|
|
189
197
|
}
|
|
190
198
|
}
|
|
@@ -315,7 +323,7 @@ class ZipDirectoryEntry extends ZipEntry {
|
|
|
315
323
|
Reader: TextReader,
|
|
316
324
|
Writer: TextWriter,
|
|
317
325
|
options,
|
|
318
|
-
uncompressedSize: text
|
|
326
|
+
uncompressedSize: getTextSize(text)
|
|
319
327
|
});
|
|
320
328
|
}
|
|
321
329
|
|
|
@@ -444,10 +452,16 @@ class ZipDirectoryEntry extends ZipEntry {
|
|
|
444
452
|
}
|
|
445
453
|
|
|
446
454
|
async importZip(reader, options = {}) {
|
|
447
|
-
|
|
448
|
-
|
|
455
|
+
let zipReader;
|
|
456
|
+
if (reader && typeof reader.getEntries == FUNCTION_TYPE) {
|
|
457
|
+
zipReader = reader;
|
|
458
|
+
options = Object.assign({}, zipReader.options, options);
|
|
459
|
+
} else {
|
|
460
|
+
await initStream(reader);
|
|
461
|
+
zipReader = new ZipReader(reader, options);
|
|
462
|
+
}
|
|
449
463
|
const importedEntries = [];
|
|
450
|
-
const entries = await zipReader.getEntries();
|
|
464
|
+
const entries = await zipReader.getEntries(options);
|
|
451
465
|
for (const entry of entries) {
|
|
452
466
|
let parent = this;
|
|
453
467
|
try {
|
|
@@ -469,7 +483,7 @@ class ZipDirectoryEntry extends ZipEntry {
|
|
|
469
483
|
importedEntries.push(addChild(parent, name, {
|
|
470
484
|
data: entry,
|
|
471
485
|
Reader: getZipBlobReader(Object.assign({}, options)),
|
|
472
|
-
uncompressedSize: entry.uncompressedSize,
|
|
486
|
+
uncompressedSize: options.passThrough ? entry.compressedSize : entry.uncompressedSize,
|
|
473
487
|
passThrough: options.passThrough
|
|
474
488
|
}));
|
|
475
489
|
} else {
|
|
@@ -511,11 +525,25 @@ class ZipDirectoryEntry extends ZipEntry {
|
|
|
511
525
|
}
|
|
512
526
|
const [readers] = await Promise.all([initReaders(zipEntry, options.readerOptions), initStream(writer)]);
|
|
513
527
|
const zipWriter = new ZipWriter(writer, options);
|
|
514
|
-
await exportZip(zipWriter, zipEntry, getTotalSize([zipEntry],
|
|
515
|
-
await zipWriter.close();
|
|
528
|
+
await exportZip(zipWriter, zipEntry, getTotalSize([zipEntry], getUncompressedSize), options, readers);
|
|
529
|
+
await zipWriter.close(options.globalComment);
|
|
516
530
|
return writer.getData ? writer.getData() : writer.writable;
|
|
517
531
|
}
|
|
518
532
|
|
|
533
|
+
getExportedSize(options = {}) {
|
|
534
|
+
const zipEntry = this;
|
|
535
|
+
options = Object.assign({}, options);
|
|
536
|
+
if (options.bufferedWrite === UNDEFINED_VALUE) {
|
|
537
|
+
options.bufferedWrite = true;
|
|
538
|
+
}
|
|
539
|
+
const writeOrderGuaranteed = !options.bufferedWrite ||
|
|
540
|
+
(options.keepOrder !== false && zipEntry.children.every(child => !child.children.length));
|
|
541
|
+
return getEntriesSize(options, Array.from(zipEntry.getChildren({ recursive: true }), child => {
|
|
542
|
+
const { name, entryOptions } = getChildEntryOptions(child, zipEntry, options);
|
|
543
|
+
return { name, size: child.directory ? 0 : getDeterminedSize(child, isPassThrough(child, options)), options: entryOptions };
|
|
544
|
+
}), writeOrderGuaranteed, options.globalComment);
|
|
545
|
+
}
|
|
546
|
+
|
|
519
547
|
getChildByName(name) {
|
|
520
548
|
const children = this.children;
|
|
521
549
|
for (let childIndex = 0; childIndex < children.length; childIndex++) {
|
|
@@ -723,6 +751,10 @@ class FS {
|
|
|
723
751
|
return this.root.exportZip(writer, options);
|
|
724
752
|
}
|
|
725
753
|
|
|
754
|
+
getExportedSize(options) {
|
|
755
|
+
return this.root.getExportedSize(options);
|
|
756
|
+
}
|
|
757
|
+
|
|
726
758
|
isPasswordProtected() {
|
|
727
759
|
return this.root.isPasswordProtected();
|
|
728
760
|
}
|
|
@@ -733,14 +765,14 @@ class FS {
|
|
|
733
765
|
}
|
|
734
766
|
|
|
735
767
|
const fs = { FS, ZipDirectoryEntry, ZipFileEntry };
|
|
736
|
-
export { fs, ERR_ENTRY_EXISTS, ERR_READABLE_CONSUMED, ERR_ABORTED };
|
|
768
|
+
export { fs, ERR_ENTRY_EXISTS, ERR_READABLE_CONSUMED, ERR_INVALID_PASS_THROUGH, ERR_ABORTED };
|
|
737
769
|
|
|
738
|
-
function getTotalSize(entries,
|
|
770
|
+
function getTotalSize(entries, getEntrySize) {
|
|
739
771
|
let size = 0;
|
|
740
772
|
const pendingEntries = Array.from(entries);
|
|
741
773
|
while (pendingEntries.length) {
|
|
742
774
|
const entry = pendingEntries.pop();
|
|
743
|
-
size += entry
|
|
775
|
+
size += getEntrySize(entry) || 0;
|
|
744
776
|
for (const child of entry.children) {
|
|
745
777
|
pendingEntries.push(child);
|
|
746
778
|
}
|
|
@@ -748,6 +780,15 @@ function getTotalSize(entries, propertyName) {
|
|
|
748
780
|
return size;
|
|
749
781
|
}
|
|
750
782
|
|
|
783
|
+
function getUncompressedSize(entry) {
|
|
784
|
+
return entry.uncompressedSize;
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
function getExtractedSize(entry, passThrough) {
|
|
788
|
+
const { data } = entry;
|
|
789
|
+
return passThrough && data instanceof Entry ? data.compressedSize : entry.uncompressedSize;
|
|
790
|
+
}
|
|
791
|
+
|
|
751
792
|
function getReadableReader(readable) {
|
|
752
793
|
let consumed;
|
|
753
794
|
return function () {
|
|
@@ -770,10 +811,17 @@ function getZipBlobReader(options) {
|
|
|
770
811
|
|
|
771
812
|
async init() {
|
|
772
813
|
const zipBlobReader = this;
|
|
773
|
-
|
|
774
|
-
const
|
|
814
|
+
const readerOptions = Object.assign({}, options, zipBlobReader.options);
|
|
815
|
+
const { checkOverlappingEntry, checkOverlappingEntryOnly } = readerOptions;
|
|
816
|
+
const data = await zipBlobReader.entry.getData(new BlobWriter(), Object.assign(readerOptions, {
|
|
817
|
+
checkPasswordOnly: false,
|
|
818
|
+
checkOverlappingEntry: checkOverlappingEntryOnly || checkOverlappingEntry,
|
|
819
|
+
checkOverlappingEntryOnly: false,
|
|
820
|
+
preventClose: false
|
|
821
|
+
}));
|
|
775
822
|
zipBlobReader.data = data;
|
|
776
823
|
zipBlobReader.blobReader = new BlobReader(data);
|
|
824
|
+
zipBlobReader.size = data.size;
|
|
777
825
|
super.init();
|
|
778
826
|
}
|
|
779
827
|
|
|
@@ -787,6 +835,30 @@ function createReader(Reader, data, options) {
|
|
|
787
835
|
return Reader.prototype ? new Reader(data, options) : Reader(data, options);
|
|
788
836
|
}
|
|
789
837
|
|
|
838
|
+
function keepsContentType(writer, data) {
|
|
839
|
+
const { contentType } = writer;
|
|
840
|
+
if (contentType === UNDEFINED_VALUE) {
|
|
841
|
+
return true;
|
|
842
|
+
} else if (writer.constructor == BlobWriter) {
|
|
843
|
+
return data.type == contentType;
|
|
844
|
+
} else if (writer.constructor == Data64URIWriter) {
|
|
845
|
+
return data.startsWith(writer.data);
|
|
846
|
+
} else {
|
|
847
|
+
return true;
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
function createProgressReadable(zipEntry, reader, options, signal) {
|
|
852
|
+
const { onstart, onprogress, onend } = options;
|
|
853
|
+
const { readable } = reader;
|
|
854
|
+
const coreReaderReportsProgress = zipEntry.data instanceof Entry;
|
|
855
|
+
if (coreReaderReportsProgress || (!onstart && !onprogress && !onend)) {
|
|
856
|
+
return readable;
|
|
857
|
+
} else {
|
|
858
|
+
return toCompatibleReadable(readable).pipeThrough(new ProgressWatcherStream({ onstart, onprogress, onend, size: reader.size }), { signal });
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
|
|
790
862
|
async function initReaders(entry, options) {
|
|
791
863
|
const fileEntries = [];
|
|
792
864
|
const pendingEntries = [entry];
|
|
@@ -819,6 +891,7 @@ async function initReaders(entry, options) {
|
|
|
819
891
|
}
|
|
820
892
|
if (reader.size !== UNDEFINED_VALUE) {
|
|
821
893
|
child.uncompressedSize = reader.size;
|
|
894
|
+
child.undeterminedSize = false;
|
|
822
895
|
}
|
|
823
896
|
}));
|
|
824
897
|
return readers;
|
|
@@ -868,6 +941,90 @@ function aggregateEntryErrors(errors) {
|
|
|
868
941
|
return error;
|
|
869
942
|
}
|
|
870
943
|
|
|
944
|
+
function getChildEntryOptions(child, selectedEntry, options) {
|
|
945
|
+
const name = options.relativePath ? child.getRelativeName(selectedEntry) : child.getFullname();
|
|
946
|
+
const childOptions = child.options || {};
|
|
947
|
+
let zipEntryMetadata = {};
|
|
948
|
+
let passThroughOptions = {};
|
|
949
|
+
if (child.data instanceof Entry) {
|
|
950
|
+
const {
|
|
951
|
+
externalFileAttributes,
|
|
952
|
+
versionMadeBy,
|
|
953
|
+
comment,
|
|
954
|
+
lastModDate,
|
|
955
|
+
creationDate,
|
|
956
|
+
lastAccessDate,
|
|
957
|
+
uncompressedSize,
|
|
958
|
+
encrypted,
|
|
959
|
+
zipCrypto,
|
|
960
|
+
crc32,
|
|
961
|
+
compressionMethod,
|
|
962
|
+
extraFieldAES,
|
|
963
|
+
internalFileAttributes,
|
|
964
|
+
extraField,
|
|
965
|
+
uid,
|
|
966
|
+
gid
|
|
967
|
+
} = child.data;
|
|
968
|
+
zipEntryMetadata = {
|
|
969
|
+
externalFileAttributes,
|
|
970
|
+
versionMadeBy,
|
|
971
|
+
comment,
|
|
972
|
+
lastModDate,
|
|
973
|
+
creationDate,
|
|
974
|
+
lastAccessDate,
|
|
975
|
+
internalFileAttributes
|
|
976
|
+
};
|
|
977
|
+
const userExtraField = getUserExtraField(extraField);
|
|
978
|
+
if (userExtraField) {
|
|
979
|
+
zipEntryMetadata.extraField = userExtraField;
|
|
980
|
+
}
|
|
981
|
+
if (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE) {
|
|
982
|
+
Object.assign(zipEntryMetadata, {
|
|
983
|
+
uid,
|
|
984
|
+
gid,
|
|
985
|
+
unixExtraFieldType: INFOZIP_EXTRA_FIELD_TYPE
|
|
986
|
+
});
|
|
987
|
+
}
|
|
988
|
+
if (isPassThrough(child, options)) {
|
|
989
|
+
let level, encryptionStrength;
|
|
990
|
+
if (compressionMethod === 0) {
|
|
991
|
+
level = 0;
|
|
992
|
+
}
|
|
993
|
+
if (extraFieldAES) {
|
|
994
|
+
encryptionStrength = extraFieldAES.strength;
|
|
995
|
+
}
|
|
996
|
+
passThroughOptions = {
|
|
997
|
+
passThrough: true,
|
|
998
|
+
encrypted,
|
|
999
|
+
zipCrypto,
|
|
1000
|
+
crc32,
|
|
1001
|
+
uncompressedSize,
|
|
1002
|
+
level,
|
|
1003
|
+
encryptionStrength,
|
|
1004
|
+
compressionMethod
|
|
1005
|
+
};
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
const entryOptions = Object.assign({}, zipEntryMetadata, options, passThroughOptions, childOptions, { directory: child.directory });
|
|
1009
|
+
if (!child.directory && entryOptions.passThrough && entryOptions.uncompressedSize === UNDEFINED_VALUE) {
|
|
1010
|
+
throw new Error(ERR_INVALID_PASS_THROUGH);
|
|
1011
|
+
}
|
|
1012
|
+
return { name, entryOptions };
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
function getDeterminedSize(child, passThrough) {
|
|
1016
|
+
const { reader } = child;
|
|
1017
|
+
if (reader && reader.size !== UNDEFINED_VALUE) {
|
|
1018
|
+
return reader.size;
|
|
1019
|
+
}
|
|
1020
|
+
return child.undeterminedSize ? UNDEFINED_VALUE : getExtractedSize(child, passThrough);
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
function isPassThrough(child, options) {
|
|
1024
|
+
const { readerOptions } = options;
|
|
1025
|
+
return Boolean(!child.directory && (child.passThrough || (readerOptions && readerOptions.passThrough)));
|
|
1026
|
+
}
|
|
1027
|
+
|
|
871
1028
|
function getUserExtraField(extraField) {
|
|
872
1029
|
if (extraField) {
|
|
873
1030
|
const userExtraField = new Map();
|
|
@@ -883,8 +1040,14 @@ function getUserExtraField(extraField) {
|
|
|
883
1040
|
}
|
|
884
1041
|
|
|
885
1042
|
async function exportZip(zipWriter, entry, totalSize, options, readers) {
|
|
1043
|
+
const { onstart, onprogress, onend, onentryprogress } = options;
|
|
886
1044
|
const selectedEntry = entry;
|
|
887
|
-
const
|
|
1045
|
+
const totalEntries = getTotalSize(entry.children, () => 1);
|
|
1046
|
+
let writtenSize = 0;
|
|
1047
|
+
let writtenEntries = 0;
|
|
1048
|
+
if (onstart) {
|
|
1049
|
+
await callHandler(onstart, totalSize);
|
|
1050
|
+
}
|
|
888
1051
|
if (options.bufferedWrite) {
|
|
889
1052
|
await processChildren(entry);
|
|
890
1053
|
} else {
|
|
@@ -892,6 +1055,9 @@ async function exportZip(zipWriter, entry, totalSize, options, readers) {
|
|
|
892
1055
|
await addChild(child);
|
|
893
1056
|
}
|
|
894
1057
|
}
|
|
1058
|
+
if (onend) {
|
|
1059
|
+
await callHandler(onend, writtenSize);
|
|
1060
|
+
}
|
|
895
1061
|
|
|
896
1062
|
async function processChildren(entry) {
|
|
897
1063
|
const results = await Promise.allSettled(entry.children.map(async child => {
|
|
@@ -905,81 +1071,23 @@ async function exportZip(zipWriter, entry, totalSize, options, readers) {
|
|
|
905
1071
|
}
|
|
906
1072
|
|
|
907
1073
|
async function addChild(child) {
|
|
908
|
-
const name
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
externalFileAttributes,
|
|
914
|
-
versionMadeBy,
|
|
915
|
-
comment,
|
|
916
|
-
lastModDate,
|
|
917
|
-
creationDate,
|
|
918
|
-
lastAccessDate,
|
|
919
|
-
uncompressedSize,
|
|
920
|
-
encrypted,
|
|
921
|
-
zipCrypto,
|
|
922
|
-
crc32,
|
|
923
|
-
compressionMethod,
|
|
924
|
-
extraFieldAES,
|
|
925
|
-
internalFileAttributes,
|
|
926
|
-
extraField,
|
|
927
|
-
uid,
|
|
928
|
-
gid
|
|
929
|
-
} = child.data;
|
|
930
|
-
zipEntryOptions = {
|
|
931
|
-
externalFileAttributes,
|
|
932
|
-
versionMadeBy,
|
|
933
|
-
comment,
|
|
934
|
-
lastModDate,
|
|
935
|
-
creationDate,
|
|
936
|
-
lastAccessDate,
|
|
937
|
-
internalFileAttributes
|
|
938
|
-
};
|
|
939
|
-
const userExtraField = getUserExtraField(extraField);
|
|
940
|
-
if (userExtraField) {
|
|
941
|
-
zipEntryOptions.extraField = userExtraField;
|
|
942
|
-
}
|
|
943
|
-
if (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE) {
|
|
944
|
-
Object.assign(zipEntryOptions, {
|
|
945
|
-
uid,
|
|
946
|
-
gid,
|
|
947
|
-
unixExtraFieldType: options.unixExtraFieldType || INFOZIP_EXTRA_FIELD_TYPE
|
|
948
|
-
});
|
|
949
|
-
}
|
|
950
|
-
if (child.passThrough) {
|
|
951
|
-
let level, encryptionStrength;
|
|
952
|
-
if (compressionMethod === 0) {
|
|
953
|
-
level = 0;
|
|
954
|
-
}
|
|
955
|
-
if (extraFieldAES) {
|
|
956
|
-
encryptionStrength = extraFieldAES.strength;
|
|
957
|
-
}
|
|
958
|
-
zipEntryOptions = Object.assign(zipEntryOptions, {
|
|
959
|
-
passThrough: true,
|
|
960
|
-
encrypted,
|
|
961
|
-
zipCrypto,
|
|
962
|
-
crc32,
|
|
963
|
-
uncompressedSize,
|
|
964
|
-
level,
|
|
965
|
-
encryptionStrength,
|
|
966
|
-
compressionMethod
|
|
967
|
-
});
|
|
968
|
-
}
|
|
969
|
-
}
|
|
970
|
-
await zipWriter.add(name, readers.get(child), Object.assign({}, options, zipEntryOptions, childOptions, {
|
|
971
|
-
directory: child.directory,
|
|
1074
|
+
const { name, entryOptions } = getChildEntryOptions(child, selectedEntry, options);
|
|
1075
|
+
let entryWrittenSize = 0;
|
|
1076
|
+
const entryMetadata = await zipWriter.add(name, readers.get(child), Object.assign(entryOptions, {
|
|
1077
|
+
onstart: UNDEFINED_VALUE,
|
|
1078
|
+
onend: UNDEFINED_VALUE,
|
|
972
1079
|
onprogress: async indexProgress => {
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
} catch {
|
|
978
|
-
// ignored
|
|
979
|
-
}
|
|
1080
|
+
writtenSize += indexProgress - entryWrittenSize;
|
|
1081
|
+
entryWrittenSize = indexProgress;
|
|
1082
|
+
if (onprogress) {
|
|
1083
|
+
await callHandler(onprogress, writtenSize, totalSize);
|
|
980
1084
|
}
|
|
981
1085
|
}
|
|
982
1086
|
}));
|
|
1087
|
+
writtenEntries++;
|
|
1088
|
+
if (onentryprogress) {
|
|
1089
|
+
await callHandler(onentryprogress, writtenEntries, totalEntries, entryMetadata);
|
|
1090
|
+
}
|
|
983
1091
|
}
|
|
984
1092
|
}
|
|
985
1093
|
|
|
@@ -1007,7 +1115,7 @@ function addFileSystemHandle(zipEntry, handle, options) {
|
|
|
1007
1115
|
})
|
|
1008
1116
|
);
|
|
1009
1117
|
} else if (handle.kind == "directory") {
|
|
1010
|
-
const directoryEntry = parentEntry.addDirectory(handle.name);
|
|
1118
|
+
const directoryEntry = parentEntry.addDirectory(handle.name, options);
|
|
1011
1119
|
addedEntries.push(directoryEntry);
|
|
1012
1120
|
for await (const childHandle of handle.values()) {
|
|
1013
1121
|
await addFile(directoryEntry, childHandle, addedEntries, entryName);
|
|
@@ -1029,15 +1137,29 @@ function addFileSystemHandle(zipEntry, handle, options) {
|
|
|
1029
1137
|
}
|
|
1030
1138
|
|
|
1031
1139
|
async function exportFileSystemHandle(zipEntry, directoryHandle, options) {
|
|
1032
|
-
const
|
|
1033
|
-
const writtenSizes = new Map();
|
|
1140
|
+
const { onstart, onprogress, onend } = options;
|
|
1034
1141
|
const abortController = new AbortController();
|
|
1035
1142
|
const { signal } = abortController;
|
|
1036
1143
|
const releaseSignal = forwardAbort(options.signal, abortController);
|
|
1144
|
+
const getDataOptions = Object.assign({}, options, options.readerOptions, {
|
|
1145
|
+
signal,
|
|
1146
|
+
onstart: UNDEFINED_VALUE,
|
|
1147
|
+
onprogress: UNDEFINED_VALUE,
|
|
1148
|
+
onend: UNDEFINED_VALUE,
|
|
1149
|
+
preventClose: false
|
|
1150
|
+
});
|
|
1151
|
+
const totalSize = getTotalSize([zipEntry], entry => getExtractedSize(entry, getDataOptions.passThrough));
|
|
1037
1152
|
const exportedEntryNames = [];
|
|
1038
1153
|
let exportAborted = false;
|
|
1154
|
+
let writtenSize = 0;
|
|
1039
1155
|
try {
|
|
1156
|
+
if (onstart) {
|
|
1157
|
+
await callHandler(onstart, totalSize);
|
|
1158
|
+
}
|
|
1040
1159
|
await exportChildren(zipEntry, directoryHandle);
|
|
1160
|
+
if (onend) {
|
|
1161
|
+
await callHandler(onend, writtenSize);
|
|
1162
|
+
}
|
|
1041
1163
|
} catch (error) {
|
|
1042
1164
|
try {
|
|
1043
1165
|
error.exportedEntryNames = exportedEntryNames;
|
|
@@ -1050,6 +1172,25 @@ async function exportFileSystemHandle(zipEntry, directoryHandle, options) {
|
|
|
1050
1172
|
}
|
|
1051
1173
|
return directoryHandle;
|
|
1052
1174
|
|
|
1175
|
+
function createProgressWritable(writable) {
|
|
1176
|
+
const writer = writable.getWriter();
|
|
1177
|
+
return new WritableStream({
|
|
1178
|
+
async write(chunk) {
|
|
1179
|
+
await writer.write(chunk);
|
|
1180
|
+
writtenSize += chunk.length;
|
|
1181
|
+
if (onprogress) {
|
|
1182
|
+
await callHandler(onprogress, writtenSize, totalSize);
|
|
1183
|
+
}
|
|
1184
|
+
},
|
|
1185
|
+
close() {
|
|
1186
|
+
return writer.close();
|
|
1187
|
+
},
|
|
1188
|
+
abort(reason) {
|
|
1189
|
+
return writer.abort(reason);
|
|
1190
|
+
}
|
|
1191
|
+
});
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1053
1194
|
async function exportChildren(entry, parentHandle) {
|
|
1054
1195
|
if (options.concurrent) {
|
|
1055
1196
|
const results = await Promise.allSettled(entry.children.map(child => exportChild(child, parentHandle)));
|
|
@@ -1081,19 +1222,7 @@ async function exportFileSystemHandle(zipEntry, directoryHandle, options) {
|
|
|
1081
1222
|
const fileHandle = await parentHandle.getFileHandle(child.name, { create: true });
|
|
1082
1223
|
const writable = await fileHandle.createWritable();
|
|
1083
1224
|
try {
|
|
1084
|
-
await child.getData({ writable
|
|
1085
|
-
signal,
|
|
1086
|
-
onprogress: async progress => {
|
|
1087
|
-
if (options.onprogress) {
|
|
1088
|
-
writtenSizes.set(child.id, progress);
|
|
1089
|
-
try {
|
|
1090
|
-
await options.onprogress(Array.from(writtenSizes.values()).reduce((previousValue, currentValue) => previousValue + currentValue, 0), totalSize);
|
|
1091
|
-
} catch {
|
|
1092
|
-
// ignored
|
|
1093
|
-
}
|
|
1094
|
-
}
|
|
1095
|
-
}
|
|
1096
|
-
}));
|
|
1225
|
+
await child.getData({ writable: createProgressWritable(writable) }, getDataOptions);
|
|
1097
1226
|
} catch (error) {
|
|
1098
1227
|
throw exportAborted ? new Error(ERR_ABORT_EXPORT) : error;
|
|
1099
1228
|
}
|
package/lib/core/zip-reader.js
CHANGED
|
@@ -76,6 +76,7 @@ import {
|
|
|
76
76
|
FILE_ATTR_MSDOS_ARCHIVE_MASK,
|
|
77
77
|
FILE_ATTR_UNIX_TYPE_MASK,
|
|
78
78
|
FILE_ATTR_UNIX_TYPE_DIR,
|
|
79
|
+
FILE_ATTR_UNIX_TYPE_SYMLINK,
|
|
79
80
|
FILE_ATTR_UNIX_EXECUTABLE_MASK,
|
|
80
81
|
FILE_ATTR_UNIX_DEFAULT_MASK,
|
|
81
82
|
DIRECTORY_SIGNATURE,
|
|
@@ -111,7 +112,8 @@ import {
|
|
|
111
112
|
readUint8Array,
|
|
112
113
|
BlobReader,
|
|
113
114
|
GenericReader,
|
|
114
|
-
GenericWriter
|
|
115
|
+
GenericWriter,
|
|
116
|
+
ownsWritable
|
|
115
117
|
} from "./io.js";
|
|
116
118
|
import { decodeText } from "./util/decode-text.js";
|
|
117
119
|
import { getDataView } from "./util/array.js";
|
|
@@ -489,15 +491,18 @@ class ZipReader {
|
|
|
489
491
|
const setuid = Boolean(fileEntry.unixMode & FILE_ATTR_UNIX_SETUID_MASK);
|
|
490
492
|
const setgid = Boolean(fileEntry.unixMode & FILE_ATTR_UNIX_SETGID_MASK);
|
|
491
493
|
const sticky = Boolean(fileEntry.unixMode & FILE_ATTR_UNIX_STICKY_MASK);
|
|
492
|
-
const
|
|
494
|
+
const unixType = fileEntry.unixMode === UNDEFINED_VALUE ? unixExternalUpper : fileEntry.unixMode;
|
|
495
|
+
const symlink = (unixType & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_SYMLINK;
|
|
496
|
+
const executable = !symlink && ((fileEntry.unixMode !== UNDEFINED_VALUE)
|
|
493
497
|
? ((fileEntry.unixMode & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0)
|
|
494
|
-
: (unixCompatible && ((unixExternalUpper & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0));
|
|
498
|
+
: (unixCompatible && ((unixExternalUpper & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0)));
|
|
495
499
|
const modeIsDir = fileEntry.unixMode !== UNDEFINED_VALUE && ((fileEntry.unixMode & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_DIR);
|
|
496
500
|
const upperIsDir = ((unixExternalUpper & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_DIR);
|
|
497
501
|
Object.assign(fileEntry, {
|
|
498
502
|
setuid,
|
|
499
503
|
setgid,
|
|
500
504
|
sticky,
|
|
505
|
+
symlink,
|
|
501
506
|
unixExternalUpper,
|
|
502
507
|
internalFileAttribute: fileEntry.internalFileAttributes,
|
|
503
508
|
externalFileAttribute: fileEntry.externalFileAttributes,
|
|
@@ -563,6 +568,10 @@ class ZipReader {
|
|
|
563
568
|
}
|
|
564
569
|
|
|
565
570
|
async close() {
|
|
571
|
+
const { reader } = this;
|
|
572
|
+
if (!reader.readUint8Array && reader.readable && !reader.readable.locked) {
|
|
573
|
+
await reader.readable.cancel();
|
|
574
|
+
}
|
|
566
575
|
}
|
|
567
576
|
}
|
|
568
577
|
|
|
@@ -816,7 +825,7 @@ class ZipEntry {
|
|
|
816
825
|
throw error;
|
|
817
826
|
}
|
|
818
827
|
} finally {
|
|
819
|
-
const preventClose = getOptionValue(zipEntry, options, OPTION_PREVENT_CLOSE);
|
|
828
|
+
const preventClose = !ownsWritable(writer) && getOptionValue(zipEntry, options, OPTION_PREVENT_CLOSE);
|
|
820
829
|
if (!preventClose && writable && !writable.locked) {
|
|
821
830
|
const writableWriter = writable.getWriter();
|
|
822
831
|
if (abortError) {
|
|
@@ -1060,8 +1069,8 @@ function readExtraFieldUnixDates(extraField, directory) {
|
|
|
1060
1069
|
return;
|
|
1061
1070
|
}
|
|
1062
1071
|
const extraFieldView = getDataView(extraField.data);
|
|
1063
|
-
const lastAccessDate = new Date(getUint32(extraFieldView, 0) * 1000);
|
|
1064
|
-
const lastModDate = new Date(getUint32(extraFieldView, 4) * 1000);
|
|
1072
|
+
const lastAccessDate = new Date((getUint32(extraFieldView, 0) | 0) * 1000);
|
|
1073
|
+
const lastModDate = new Date((getUint32(extraFieldView, 4) | 0) * 1000);
|
|
1065
1074
|
const extraFieldData = { lastAccessDate, lastModDate };
|
|
1066
1075
|
if (extraField.data.length >= 12) {
|
|
1067
1076
|
extraFieldData.uid = getUint16(extraFieldView, 8);
|