@zip.js/zip.js 2.8.61 → 2.10.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/README.md +40 -0
- package/deno.json +1 -1
- package/dist/zip-core-external.js +15 -15
- package/dist/zip-core-external.min.js +1 -1
- package/dist/zip-core.js +15 -14
- package/dist/zip-core.min.js +1 -1
- package/dist/zip-fs-core-external.js +168 -57
- package/dist/zip-fs-core-external.min.js +1 -1
- package/dist/zip-fs-core.js +170 -56
- package/dist/zip-fs-core.min.js +1 -1
- package/dist/zip-fs-external.js +168 -57
- package/dist/zip-fs-external.min.js +1 -1
- package/dist/zip-fs-native.js +170 -56
- package/dist/zip-fs-native.min.js +1 -1
- package/dist/zip-fs.js +170 -56
- package/dist/zip-fs.min.js +1 -1
- package/dist/zip-legacy.js +15 -14
- package/dist/zip-legacy.min.js +1 -1
- package/dist/zip-native.js +15 -14
- package/dist/zip-native.min.js +1 -1
- package/dist/zip.js +15 -14
- package/dist/zip.min.js +1 -1
- package/index-native.cjs +170 -56
- package/index-native.min.js +1 -1
- package/index.cjs +170 -56
- package/index.d.cts +104 -9
- package/index.d.ts +104 -9
- package/index.min.js +1 -1
- package/lib/core/streams/codecs/crc32.js +1 -1
- package/lib/core/util/decode-cp437.js +5 -12
- package/lib/core/version.js +1 -1
- package/lib/core/zip-fs.js +155 -44
- package/lib/core/zip-reader.js +7 -0
- package/lib/zip-core-reader.js +1 -0
- package/package.json +1 -1
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
// Every table MUST stay a PACKED_SMI array: build with array literals (not `new Array(n)`,
|
|
34
34
|
// which is HOLEY) and store the signed int32 XOR result (no `>>> 0`). An unsigned or holey
|
|
35
35
|
// table becomes a V8 FixedDoubleArray whose every hot-loop lookup unboxes a double (~1.6x
|
|
36
|
-
// slower). Signedness is irrelevant to the result
|
|
36
|
+
// slower). Signedness is irrelevant to the result: the reads mask/shift it and the final
|
|
37
37
|
// `~crc` normalizes it. Do NOT reintroduce `>>> 0` here or switch to `new Array(256)`.
|
|
38
38
|
const T = [[], [], [], [], [], [], [], []];
|
|
39
39
|
for (let n = 0; n < 256; n++) {
|
|
@@ -26,23 +26,16 @@
|
|
|
26
26
|
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
27
27
|
*/
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const CP437 = "\0☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼ !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~⌂ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ ".split("");
|
|
32
|
-
const VALID_CP437 = CP437.length == 256;
|
|
29
|
+
const CP437 = "\0\u263A\u263B\u2665\u2666\u2663\u2660\u2022\u25D8\u25CB\u25D9\u2642\u2640\u266A\u266B\u263C\u25BA\u25C4\u2195\u203C\u00B6\u00A7\u25AC\u21A8\u2191\u2193\u2192\u2190\u221F\u2194\u25B2\u25BC !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u2302\u00C7\u00FC\u00E9\u00E2\u00E4\u00E0\u00E5\u00E7\u00EA\u00EB\u00E8\u00EF\u00EE\u00EC\u00C4\u00C5\u00C9\u00E6\u00C6\u00F4\u00F6\u00F2\u00FB\u00F9\u00FF\u00D6\u00DC\u00A2\u00A3\u00A5\u20A7\u0192\u00E1\u00ED\u00F3\u00FA\u00F1\u00D1\u00AA\u00BA\u00BF\u2310\u00AC\u00BD\u00BC\u00A1\u00AB\u00BB\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255D\u255C\u255B\u2510\u2514\u2534\u252C\u251C\u2500\u253C\u255E\u255F\u255A\u2554\u2569\u2566\u2560\u2550\u256C\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256B\u256A\u2518\u250C\u2588\u2584\u258C\u2590\u2580\u03B1\u00DF\u0393\u03C0\u03A3\u03C3\u00B5\u03C4\u03A6\u0398\u03A9\u03B4\u221E\u03C6\u03B5\u2229\u2261\u00B1\u2265\u2264\u2320\u2321\u00F7\u2248\u00B0\u2219\u00B7\u221A\u207F\u00B2\u25A0\u00A0".split("");
|
|
33
30
|
|
|
34
31
|
export {
|
|
35
32
|
decodeCP437
|
|
36
33
|
};
|
|
37
34
|
|
|
38
35
|
function decodeCP437(stringValue) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
result += CP437[stringValue[indexCharacter]];
|
|
43
|
-
}
|
|
44
|
-
return result;
|
|
45
|
-
} else {
|
|
46
|
-
return new TextDecoder().decode(stringValue);
|
|
36
|
+
let result = "";
|
|
37
|
+
for (let indexCharacter = 0; indexCharacter < stringValue.length; indexCharacter++) {
|
|
38
|
+
result += CP437[stringValue[indexCharacter]];
|
|
47
39
|
}
|
|
40
|
+
return result;
|
|
48
41
|
}
|
package/lib/core/version.js
CHANGED
package/lib/core/zip-fs.js
CHANGED
|
@@ -80,7 +80,14 @@ import { toExactUint8Array } from "./util/array.js";
|
|
|
80
80
|
import { toCompatibleReadable, toCompatibleWritable } from "./util/compatible-streams.js";
|
|
81
81
|
|
|
82
82
|
const ERR_ENTRY_EXISTS = "Entry filename already exists";
|
|
83
|
+
const ERR_DUPLICATE_IMPORTED_ENTRY = "Duplicate entry filename in the imported zip file";
|
|
84
|
+
const ERR_INVALID_DUPLICATES = "Invalid duplicates option (must be \"throw\", \"keep-first\" or \"keep-last\")";
|
|
85
|
+
const ERR_ANCESTOR_ENTRY = "Entry is a ancestor of target entry";
|
|
83
86
|
const ERR_READABLE_CONSUMED = "Readable stream already consumed";
|
|
87
|
+
const DUPLICATES_THROW = "throw";
|
|
88
|
+
const DUPLICATES_KEEP_FIRST = "keep-first";
|
|
89
|
+
const DUPLICATES_KEEP_LAST = "keep-last";
|
|
90
|
+
const DUPLICATES_VALUES = new Set([DUPLICATES_THROW, DUPLICATES_KEEP_FIRST, DUPLICATES_KEEP_LAST]);
|
|
84
91
|
const ERR_INVALID_PASS_THROUGH = "Invalid passThrough option (use readerOptions.passThrough or set uncompressedSize for each entry)";
|
|
85
92
|
const ERR_INVALID_READER_OPTIONS = "Invalid readerOptions (must be an object)";
|
|
86
93
|
const ERR_ZIP_CRYPTO_LAST_MOD_DATE = "The last modification date of an entry encrypted with ZipCrypto cannot be changed when passThrough is set";
|
|
@@ -157,12 +164,26 @@ class ZipEntry {
|
|
|
157
164
|
}
|
|
158
165
|
|
|
159
166
|
rename(name) {
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
167
|
+
const zipEntry = this;
|
|
168
|
+
let parent = zipEntry.parent;
|
|
169
|
+
if (parent) {
|
|
170
|
+
const path = splitPath(name);
|
|
171
|
+
if (path) {
|
|
172
|
+
name = path.pop();
|
|
173
|
+
parent = getPathParent(parent, path, zipEntry);
|
|
174
|
+
}
|
|
175
|
+
const existingChild = parent.getChildByName(name);
|
|
176
|
+
if (existingChild && existingChild != zipEntry) {
|
|
177
|
+
throw new Error(ERR_ENTRY_EXISTS);
|
|
178
|
+
}
|
|
179
|
+
if (parent != zipEntry.parent) {
|
|
180
|
+
detach(zipEntry);
|
|
181
|
+
zipEntry.parent = parent;
|
|
182
|
+
parent.children.push(zipEntry);
|
|
183
|
+
registerEntries(zipEntry.fs, zipEntry);
|
|
184
|
+
}
|
|
165
185
|
}
|
|
186
|
+
zipEntry.name = name;
|
|
166
187
|
}
|
|
167
188
|
|
|
168
189
|
setOptions(options) {
|
|
@@ -255,47 +276,47 @@ class ZipFileEntry extends ZipEntry {
|
|
|
255
276
|
}
|
|
256
277
|
|
|
257
278
|
replaceBlob(blob) {
|
|
258
|
-
|
|
279
|
+
replaceContent(this, {
|
|
259
280
|
data: blob,
|
|
260
281
|
Reader: BlobReader,
|
|
261
282
|
Writer: BlobWriter,
|
|
262
|
-
|
|
283
|
+
uncompressedSize: blob.size
|
|
263
284
|
});
|
|
264
285
|
}
|
|
265
286
|
|
|
266
287
|
replaceText(text) {
|
|
267
|
-
|
|
288
|
+
replaceContent(this, {
|
|
268
289
|
data: text,
|
|
269
290
|
Reader: TextReader,
|
|
270
291
|
Writer: TextWriter,
|
|
271
|
-
|
|
292
|
+
uncompressedSize: getTextSize(text)
|
|
272
293
|
});
|
|
273
294
|
}
|
|
274
295
|
|
|
275
296
|
replaceData64URI(dataURI) {
|
|
276
|
-
|
|
297
|
+
replaceContent(this, {
|
|
277
298
|
data: dataURI,
|
|
278
299
|
Reader: Data64URIReader,
|
|
279
300
|
Writer: Data64URIWriter,
|
|
280
|
-
|
|
301
|
+
uncompressedSize: getData64URISize(dataURI)
|
|
281
302
|
});
|
|
282
303
|
}
|
|
283
304
|
|
|
284
305
|
replaceUint8Array(array) {
|
|
285
|
-
|
|
306
|
+
replaceContent(this, {
|
|
286
307
|
data: array,
|
|
287
308
|
Reader: Uint8ArrayReader,
|
|
288
309
|
Writer: Uint8ArrayWriter,
|
|
289
|
-
|
|
310
|
+
uncompressedSize: array.length
|
|
290
311
|
});
|
|
291
312
|
}
|
|
292
313
|
|
|
293
314
|
replaceReadable(readable) {
|
|
294
|
-
|
|
315
|
+
replaceContent(this, {
|
|
295
316
|
data: null,
|
|
296
317
|
Reader: getReadableReader(readable),
|
|
297
318
|
Writer: null,
|
|
298
|
-
|
|
319
|
+
uncompressedSize: UNDEFINED_VALUE
|
|
299
320
|
});
|
|
300
321
|
}
|
|
301
322
|
}
|
|
@@ -345,17 +366,12 @@ class ZipDirectoryEntry extends ZipEntry {
|
|
|
345
366
|
}
|
|
346
367
|
|
|
347
368
|
addData64URI(name, dataURI, options = {}) {
|
|
348
|
-
let dataEnd = dataURI.length;
|
|
349
|
-
while (dataURI.charAt(dataEnd - 1) == "=") {
|
|
350
|
-
dataEnd--;
|
|
351
|
-
}
|
|
352
|
-
const dataStart = dataURI.indexOf(",") + 1;
|
|
353
369
|
return addChild(this, name, {
|
|
354
370
|
data: dataURI,
|
|
355
371
|
Reader: Data64URIReader,
|
|
356
372
|
Writer: Data64URIWriter,
|
|
357
373
|
options,
|
|
358
|
-
uncompressedSize:
|
|
374
|
+
uncompressedSize: getData64URISize(dataURI)
|
|
359
375
|
});
|
|
360
376
|
}
|
|
361
377
|
|
|
@@ -463,6 +479,7 @@ class ZipDirectoryEntry extends ZipEntry {
|
|
|
463
479
|
await initStream(reader);
|
|
464
480
|
zipReader = new ZipReader(reader, options);
|
|
465
481
|
}
|
|
482
|
+
const duplicates = checkDuplicatesOption(options.duplicates);
|
|
466
483
|
const importedEntries = [];
|
|
467
484
|
const entries = await zipReader.getEntries(options);
|
|
468
485
|
for (const entry of entries) {
|
|
@@ -470,19 +487,42 @@ class ZipDirectoryEntry extends ZipEntry {
|
|
|
470
487
|
try {
|
|
471
488
|
const path = entry.filename.split("/").filter(pathPart => pathPart != "" && pathPart != ".");
|
|
472
489
|
const name = path.pop();
|
|
473
|
-
|
|
490
|
+
let skippedEntry = false;
|
|
491
|
+
for (const pathPart of path) {
|
|
474
492
|
const previousParent = parent;
|
|
475
493
|
parent = parent.getChildByName(pathPart);
|
|
476
494
|
if (parent) {
|
|
477
495
|
if (!parent.directory) {
|
|
478
|
-
|
|
496
|
+
if (duplicates == DUPLICATES_KEEP_FIRST) {
|
|
497
|
+
skippedEntry = true;
|
|
498
|
+
break;
|
|
499
|
+
} else if (duplicates == DUPLICATES_KEEP_LAST) {
|
|
500
|
+
this.fs.remove(parent);
|
|
501
|
+
parent = new ZipDirectoryEntry(this.fs, pathPart, { data: null }, previousParent);
|
|
502
|
+
importedEntries.push(parent);
|
|
503
|
+
} else {
|
|
504
|
+
throw new Error(ERR_DUPLICATE_IMPORTED_ENTRY);
|
|
505
|
+
}
|
|
479
506
|
}
|
|
480
507
|
} else {
|
|
481
508
|
parent = new ZipDirectoryEntry(this.fs, pathPart, { data: null }, previousParent);
|
|
482
509
|
importedEntries.push(parent);
|
|
483
510
|
}
|
|
484
|
-
}
|
|
511
|
+
}
|
|
512
|
+
if (skippedEntry) {
|
|
513
|
+
continue;
|
|
514
|
+
}
|
|
485
515
|
if (!entry.directory) {
|
|
516
|
+
const existingChild = parent.getChildByName(name);
|
|
517
|
+
if (existingChild) {
|
|
518
|
+
if (duplicates == DUPLICATES_KEEP_FIRST) {
|
|
519
|
+
continue;
|
|
520
|
+
} else if (duplicates == DUPLICATES_KEEP_LAST) {
|
|
521
|
+
this.fs.remove(existingChild);
|
|
522
|
+
} else {
|
|
523
|
+
throw new Error(ERR_DUPLICATE_IMPORTED_ENTRY);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
486
526
|
importedEntries.push(addChild(parent, name, {
|
|
487
527
|
data: entry,
|
|
488
528
|
Reader: getZipBlobReader(Object.assign({}, options)),
|
|
@@ -493,11 +533,17 @@ class ZipDirectoryEntry extends ZipEntry {
|
|
|
493
533
|
let directoryEntry = parent;
|
|
494
534
|
if (name) {
|
|
495
535
|
directoryEntry = parent.getChildByName(name);
|
|
496
|
-
if (directoryEntry) {
|
|
497
|
-
if (
|
|
498
|
-
|
|
536
|
+
if (directoryEntry && !directoryEntry.directory) {
|
|
537
|
+
if (duplicates == DUPLICATES_KEEP_FIRST) {
|
|
538
|
+
continue;
|
|
539
|
+
} else if (duplicates == DUPLICATES_KEEP_LAST) {
|
|
540
|
+
this.fs.remove(directoryEntry);
|
|
541
|
+
directoryEntry = UNDEFINED_VALUE;
|
|
542
|
+
} else {
|
|
543
|
+
throw new Error(ERR_DUPLICATE_IMPORTED_ENTRY);
|
|
499
544
|
}
|
|
500
|
-
}
|
|
545
|
+
}
|
|
546
|
+
if (!directoryEntry) {
|
|
501
547
|
directoryEntry = new ZipDirectoryEntry(this.fs, name, { data: null }, parent);
|
|
502
548
|
importedEntries.push(directoryEntry);
|
|
503
549
|
}
|
|
@@ -507,6 +553,7 @@ class ZipDirectoryEntry extends ZipEntry {
|
|
|
507
553
|
}
|
|
508
554
|
}
|
|
509
555
|
} catch (error) {
|
|
556
|
+
importedEntries.reverse().forEach(importedEntry => this.fs.remove(importedEntry));
|
|
510
557
|
try {
|
|
511
558
|
error.cause = {
|
|
512
559
|
entry
|
|
@@ -625,7 +672,7 @@ class ZipFS {
|
|
|
625
672
|
}
|
|
626
673
|
}
|
|
627
674
|
} else {
|
|
628
|
-
throw new Error(
|
|
675
|
+
throw new Error(ERR_ANCESTOR_ENTRY);
|
|
629
676
|
}
|
|
630
677
|
} else {
|
|
631
678
|
throw new Error("Target entry is not a directory");
|
|
@@ -637,7 +684,7 @@ class ZipFS {
|
|
|
637
684
|
const path = fullname.split("/");
|
|
638
685
|
let node = this.root;
|
|
639
686
|
for (let index = 0; node && index < path.length; index++) {
|
|
640
|
-
node = node.getChildByName(path[index]);
|
|
687
|
+
node = node.directory ? node.getChildByName(path[index]) : UNDEFINED_VALUE;
|
|
641
688
|
}
|
|
642
689
|
if (!node) {
|
|
643
690
|
node = this.entries.find(entry => entry && (entry == this.root || entry.isDescendantOf(this.root)) &&
|
|
@@ -699,33 +746,27 @@ class ZipFS {
|
|
|
699
746
|
}
|
|
700
747
|
|
|
701
748
|
importBlob(blob, options) {
|
|
702
|
-
|
|
703
|
-
return this.root.importBlob(blob, options);
|
|
749
|
+
return resetAndImport(this, root => root.importBlob(blob, options));
|
|
704
750
|
}
|
|
705
751
|
|
|
706
752
|
importData64URI(dataURI, options) {
|
|
707
|
-
|
|
708
|
-
return this.root.importData64URI(dataURI, options);
|
|
753
|
+
return resetAndImport(this, root => root.importData64URI(dataURI, options));
|
|
709
754
|
}
|
|
710
755
|
|
|
711
756
|
importUint8Array(array, options) {
|
|
712
|
-
|
|
713
|
-
return this.root.importUint8Array(array, options);
|
|
757
|
+
return resetAndImport(this, root => root.importUint8Array(array, options));
|
|
714
758
|
}
|
|
715
759
|
|
|
716
760
|
importHttpContent(url, options) {
|
|
717
|
-
|
|
718
|
-
return this.root.importHttpContent(url, options);
|
|
761
|
+
return resetAndImport(this, root => root.importHttpContent(url, options));
|
|
719
762
|
}
|
|
720
763
|
|
|
721
764
|
importReadable(readable, options) {
|
|
722
|
-
|
|
723
|
-
return this.root.importReadable(readable, options);
|
|
765
|
+
return resetAndImport(this, root => root.importReadable(readable, options));
|
|
724
766
|
}
|
|
725
767
|
|
|
726
768
|
importZip(reader, options) {
|
|
727
|
-
|
|
728
|
-
return this.root.importZip(reader, options);
|
|
769
|
+
return resetAndImport(this, root => root.importZip(reader, options));
|
|
729
770
|
}
|
|
730
771
|
|
|
731
772
|
exportBlob(options) {
|
|
@@ -766,7 +807,7 @@ class ZipFS {
|
|
|
766
807
|
}
|
|
767
808
|
|
|
768
809
|
const fs = { FS: ZipFS, ZipDirectoryEntry, ZipFileEntry };
|
|
769
|
-
export { ZipFS, ZipEntry, ZipFileEntry, ZipDirectoryEntry, fs, ERR_ENTRY_EXISTS, ERR_READABLE_CONSUMED, ERR_INVALID_PASS_THROUGH, ERR_INVALID_READER_OPTIONS, ERR_ZIP_CRYPTO_LAST_MOD_DATE, ERR_ABORTED };
|
|
810
|
+
export { ZipFS, ZipEntry, ZipFileEntry, ZipDirectoryEntry, fs, ERR_ENTRY_EXISTS, ERR_DUPLICATE_IMPORTED_ENTRY, ERR_INVALID_DUPLICATES, ERR_READABLE_CONSUMED, ERR_INVALID_PASS_THROUGH, ERR_INVALID_READER_OPTIONS, ERR_ZIP_CRYPTO_LAST_MOD_DATE, ERR_ABORTED };
|
|
770
811
|
|
|
771
812
|
function getTotalSize(entries, getEntrySize) {
|
|
772
813
|
let size = 0;
|
|
@@ -1046,6 +1087,25 @@ function checkReaderOptions(readerOptions) {
|
|
|
1046
1087
|
return readerOptions;
|
|
1047
1088
|
}
|
|
1048
1089
|
|
|
1090
|
+
function replaceContent(zipEntry, params) {
|
|
1091
|
+
const { uncompressedSize } = params;
|
|
1092
|
+
Object.assign(zipEntry, params, {
|
|
1093
|
+
reader: null,
|
|
1094
|
+
passThrough: UNDEFINED_VALUE,
|
|
1095
|
+
uncompressedSize: uncompressedSize === UNDEFINED_VALUE ? 0 : uncompressedSize,
|
|
1096
|
+
undeterminedSize: uncompressedSize === UNDEFINED_VALUE
|
|
1097
|
+
});
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
function getData64URISize(dataURI) {
|
|
1101
|
+
let dataEnd = dataURI.length;
|
|
1102
|
+
while (dataURI.charAt(dataEnd - 1) == "=") {
|
|
1103
|
+
dataEnd--;
|
|
1104
|
+
}
|
|
1105
|
+
const dataStart = dataURI.indexOf(",") + 1;
|
|
1106
|
+
return Math.floor((dataEnd - dataStart) * 0.75);
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1049
1109
|
function isPassThrough(child, options) {
|
|
1050
1110
|
const { readerOptions } = options;
|
|
1051
1111
|
return Boolean(!child.directory && (child.passThrough || (readerOptions && readerOptions.passThrough)));
|
|
@@ -1335,6 +1395,15 @@ function resetFS(fs) {
|
|
|
1335
1395
|
fs.root = new ZipDirectoryEntry(fs);
|
|
1336
1396
|
}
|
|
1337
1397
|
|
|
1398
|
+
function resetAndImport(fs, importFunction) {
|
|
1399
|
+
const { entries, entryIdCounter, root } = fs;
|
|
1400
|
+
resetFS(fs);
|
|
1401
|
+
return importFunction(fs.root).catch(error => {
|
|
1402
|
+
Object.assign(fs, { entries, entryIdCounter, root });
|
|
1403
|
+
throw error;
|
|
1404
|
+
});
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1338
1407
|
function collectChildren(directory, recursive) {
|
|
1339
1408
|
const children = [];
|
|
1340
1409
|
const pendingDirectories = [directory];
|
|
@@ -1363,8 +1432,50 @@ function registerEntries(fs, entry) {
|
|
|
1363
1432
|
|
|
1364
1433
|
function addChild(parent, name, params, directory) {
|
|
1365
1434
|
if (parent.directory) {
|
|
1435
|
+
const path = splitPath(name);
|
|
1436
|
+
if (path) {
|
|
1437
|
+
name = path.pop();
|
|
1438
|
+
parent = getPathParent(parent, path);
|
|
1439
|
+
}
|
|
1366
1440
|
return directory ? new ZipDirectoryEntry(parent.fs, name, params, parent) : new ZipFileEntry(parent.fs, name, params, parent);
|
|
1367
1441
|
} else {
|
|
1368
1442
|
throw new Error("Parent entry is not a directory");
|
|
1369
1443
|
}
|
|
1370
|
-
}
|
|
1444
|
+
}
|
|
1445
|
+
|
|
1446
|
+
function checkDuplicatesOption(duplicates) {
|
|
1447
|
+
if (duplicates === UNDEFINED_VALUE) {
|
|
1448
|
+
return DUPLICATES_THROW;
|
|
1449
|
+
} else if (DUPLICATES_VALUES.has(duplicates)) {
|
|
1450
|
+
return duplicates;
|
|
1451
|
+
} else {
|
|
1452
|
+
throw new Error(ERR_INVALID_DUPLICATES);
|
|
1453
|
+
}
|
|
1454
|
+
}
|
|
1455
|
+
|
|
1456
|
+
function splitPath(name) {
|
|
1457
|
+
if (name.includes("/")) {
|
|
1458
|
+
const path = name.split("/").filter(pathPart => pathPart != "" && pathPart != ".");
|
|
1459
|
+
if (path.length) {
|
|
1460
|
+
return path;
|
|
1461
|
+
}
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1465
|
+
function getPathParent(parent, path, movedEntry) {
|
|
1466
|
+
path.forEach(pathPart => {
|
|
1467
|
+
const previousParent = parent;
|
|
1468
|
+
parent = parent.getChildByName(pathPart);
|
|
1469
|
+
if (parent) {
|
|
1470
|
+
if (!parent.directory) {
|
|
1471
|
+
throw new Error(ERR_ENTRY_EXISTS);
|
|
1472
|
+
}
|
|
1473
|
+
if (movedEntry && (parent == movedEntry || parent.isDescendantOf(movedEntry))) {
|
|
1474
|
+
throw new Error(ERR_ANCESTOR_ENTRY);
|
|
1475
|
+
}
|
|
1476
|
+
} else {
|
|
1477
|
+
parent = new ZipDirectoryEntry(previousParent.fs, pathPart, { data: null }, previousParent);
|
|
1478
|
+
}
|
|
1479
|
+
});
|
|
1480
|
+
return parent;
|
|
1481
|
+
}
|
package/lib/core/zip-reader.js
CHANGED
|
@@ -205,6 +205,7 @@ const WARNING_UNKNOWN_ZIP64_EXTENSIBLE_DATA = "unknown zip64 extensible data";
|
|
|
205
205
|
const WARNING_WRAPPED_ENTRIES_COUNT = "wrapped entries count";
|
|
206
206
|
const WARNING_APPENDED_DATA = "appended data";
|
|
207
207
|
const WARNING_PREPENDED_DATA = "prepended data";
|
|
208
|
+
const WARNING_PREPENDED_CENTRAL_DIRECTORY = "prepended central directory";
|
|
208
209
|
const WARNING_TRAILING_CENTRAL_DIRECTORY_DATA = "trailing central directory data";
|
|
209
210
|
const WARNING_DUPLICATE_FILENAME = "duplicate filename";
|
|
210
211
|
const WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY = "mismatched zip64 end of central directory record";
|
|
@@ -298,6 +299,7 @@ class ZipReader {
|
|
|
298
299
|
let diskNumber = getUint16(endOfDirectoryView, 6);
|
|
299
300
|
let filesLength = getUint16(endOfDirectoryView, 10);
|
|
300
301
|
let prependedDataLength = 0;
|
|
302
|
+
let prependedCentralDirectory;
|
|
301
303
|
let startOffset;
|
|
302
304
|
let zip64EndOfDirectory;
|
|
303
305
|
let zip64EndOfDirectoryVersion2;
|
|
@@ -401,6 +403,7 @@ class ZipReader {
|
|
|
401
403
|
directoryDataOffset = expectedDirectoryDataOffset;
|
|
402
404
|
if (directoryDataOffset > originalDirectoryDataOffset) {
|
|
403
405
|
prependedDataLength += directoryDataOffset - originalDirectoryDataOffset;
|
|
406
|
+
prependedCentralDirectory = storedPointsAtDirectory;
|
|
404
407
|
}
|
|
405
408
|
directoryArray = await readUint8Array(reader, directoryDataOffset, directoryDataLength);
|
|
406
409
|
directoryView = getDataView(directoryArray);
|
|
@@ -628,6 +631,9 @@ class ZipReader {
|
|
|
628
631
|
if (prependedDataLength || (filesLength && startOffset > SPLIT_ZIP_FILE_SIGNATURE_LENGTH)) {
|
|
629
632
|
addWarning(warnings, WARNING_PREPENDED_DATA);
|
|
630
633
|
}
|
|
634
|
+
if (prependedCentralDirectory) {
|
|
635
|
+
addWarning(warnings, WARNING_PREPENDED_CENTRAL_DIRECTORY);
|
|
636
|
+
}
|
|
631
637
|
if (extractPrependedData) {
|
|
632
638
|
zipReader.prependedData = startOffset > splitZipSignatureLength ?
|
|
633
639
|
await readUint8Array(reader, splitZipSignatureLength, startOffset - splitZipSignatureLength) :
|
|
@@ -756,6 +762,7 @@ export {
|
|
|
756
762
|
WARNING_WRAPPED_ENTRIES_COUNT,
|
|
757
763
|
WARNING_APPENDED_DATA,
|
|
758
764
|
WARNING_PREPENDED_DATA,
|
|
765
|
+
WARNING_PREPENDED_CENTRAL_DIRECTORY,
|
|
759
766
|
WARNING_TRAILING_CENTRAL_DIRECTORY_DATA,
|
|
760
767
|
WARNING_DUPLICATE_FILENAME,
|
|
761
768
|
WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY,
|
package/lib/zip-core-reader.js
CHANGED
|
@@ -66,6 +66,7 @@ export {
|
|
|
66
66
|
WARNING_WRAPPED_ENTRIES_COUNT,
|
|
67
67
|
WARNING_APPENDED_DATA,
|
|
68
68
|
WARNING_PREPENDED_DATA,
|
|
69
|
+
WARNING_PREPENDED_CENTRAL_DIRECTORY,
|
|
69
70
|
WARNING_TRAILING_CENTRAL_DIRECTORY_DATA,
|
|
70
71
|
WARNING_DUPLICATE_FILENAME,
|
|
71
72
|
WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY,
|
package/package.json
CHANGED