@zip.js/zip.js 2.8.53 → 2.8.54
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 +1 -1
- package/deno.json +2 -1
- package/dist/zip-core-external.js +691 -482
- package/dist/zip-core-external.min.js +1 -1
- package/dist/zip-core.js +698 -481
- package/dist/zip-core.min.js +1 -1
- package/dist/zip-fs-core-external.js +729 -511
- package/dist/zip-fs-core-external.min.js +1 -1
- package/dist/zip-fs-core.js +691 -496
- package/dist/zip-fs-core.min.js +1 -1
- package/dist/zip-fs-external.js +729 -511
- package/dist/zip-fs-external.min.js +1 -1
- package/dist/zip-fs-native.js +743 -512
- package/dist/zip-fs-native.min.js +1 -1
- package/dist/zip-fs.js +742 -511
- package/dist/zip-fs.min.js +1 -1
- package/dist/zip-legacy.js +700 -483
- package/dist/zip-legacy.min.js +1 -1
- package/dist/zip-native.js +700 -483
- 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 +699 -482
- package/dist/zip.min.js +1 -1
- package/eslint.config.mjs +1 -0
- package/index-native.cjs +743 -512
- package/index-native.min.js +1 -1
- package/index.cjs +742 -511
- package/index.d.cts +398 -42
- package/index.d.ts +398 -42
- package/index.min.js +1 -1
- package/lib/core/configuration.js +62 -21
- package/lib/core/constants.js +11 -1
- package/lib/core/io.js +33 -27
- package/lib/core/options.js +44 -2
- package/lib/core/streams/aes-crypto-stream.js +12 -12
- package/lib/core/util/decode-text.js +11 -2
- package/lib/core/web-worker-base.js +3 -2
- package/lib/core/web-worker-inline-native.js +1 -1
- package/lib/core/web-worker-inline-wasm.js +1 -1
- package/lib/core/zip-fs.js +38 -27
- package/lib/core/zip-reader.js +58 -26
- package/lib/core/zip-writer.js +293 -177
- package/lib/zip-core-base.js +6 -1
- package/lib/zip-core-reader.js +1 -0
- package/lib/zip-core-writer.js +4 -0
- package/package.json +8 -2
package/lib/core/zip-writer.js
CHANGED
|
@@ -53,10 +53,10 @@
|
|
|
53
53
|
*
|
|
54
54
|
* Scheduling:
|
|
55
55
|
* - The central directory order (i.e. the order in which entries are listed by getEntries()) is
|
|
56
|
-
* the insertion order of the `
|
|
56
|
+
* the insertion order of the `fileEntries` map. addFile() reserves each entry's slot synchronously in
|
|
57
57
|
* add() call order, before initializing the reader, so concurrent entries whose readers
|
|
58
58
|
* initialize at different speeds are still listed in call order.
|
|
59
|
-
* - `fileEntry.
|
|
59
|
+
* - `fileEntry.lockFileEntry` chains every entry to the previous one to reach getFileEntry(); awaiting it
|
|
60
60
|
* serializes the physical writes when `keepOrder` is set. The physical layout therefore follows
|
|
61
61
|
* the order in which the readers finish initializing, not necessarily the central directory
|
|
62
62
|
* order; each entry records its own `offset`, so the archive stays consistent either way.
|
|
@@ -86,6 +86,7 @@ import {
|
|
|
86
86
|
COMPRESSION_METHOD_STORE,
|
|
87
87
|
COMPRESSION_METHOD_AES,
|
|
88
88
|
SPLIT_ZIP_FILE_SIGNATURE,
|
|
89
|
+
SPLIT_ZIP_FILE_SIGNATURE_LENGTH,
|
|
89
90
|
LOCAL_FILE_HEADER_SIGNATURE,
|
|
90
91
|
DATA_DESCRIPTOR_RECORD_SIGNATURE,
|
|
91
92
|
DIGITAL_SIGNATURE_RECORD_SIGNATURE,
|
|
@@ -139,6 +140,8 @@ import {
|
|
|
139
140
|
HEADER_OFFSET_SIGNATURE,
|
|
140
141
|
HEADER_OFFSET_COMPRESSED_SIZE,
|
|
141
142
|
HEADER_OFFSET_UNCOMPRESSED_SIZE,
|
|
143
|
+
HEADER_OFFSET_FILENAME_LENGTH,
|
|
144
|
+
HEADER_OFFSET_EXTRAFIELD_LENGTH,
|
|
142
145
|
LOCAL_HEADER_COMMON_OFFSET,
|
|
143
146
|
MIN_DATE,
|
|
144
147
|
MAX_DATE,
|
|
@@ -146,6 +149,7 @@ import {
|
|
|
146
149
|
INFINITY_VALUE,
|
|
147
150
|
OBJECT_TYPE,
|
|
148
151
|
STRING_TYPE,
|
|
152
|
+
FUNCTION_TYPE,
|
|
149
153
|
EMPTY_UINT8_ARRAY
|
|
150
154
|
} from "./constants.js";
|
|
151
155
|
import { getConfiguration } from "./configuration.js";
|
|
@@ -158,6 +162,8 @@ import {
|
|
|
158
162
|
} from "./codec-pool.js";
|
|
159
163
|
import {
|
|
160
164
|
initStream,
|
|
165
|
+
createReadable,
|
|
166
|
+
readUint8Array,
|
|
161
167
|
GenericWriter,
|
|
162
168
|
GenericReader,
|
|
163
169
|
BlobReader,
|
|
@@ -224,19 +230,28 @@ import {
|
|
|
224
230
|
OPTION_LOCAL_EXTRA_FIELD,
|
|
225
231
|
OPTION_SIGN_CENTRAL_DIRECTORY,
|
|
226
232
|
TEXT_TYPE_FILENAME,
|
|
227
|
-
TEXT_TYPE_COMMENT
|
|
233
|
+
TEXT_TYPE_COMMENT,
|
|
234
|
+
ERR_INVALID_PASSWORD_TYPE,
|
|
235
|
+
checkFunctionOption,
|
|
236
|
+
checkSignalOption,
|
|
237
|
+
checkPasswordOption,
|
|
238
|
+
toNumber
|
|
228
239
|
} from "./options.js";
|
|
229
240
|
|
|
230
241
|
const ERR_DUPLICATED_NAME = "File already exists";
|
|
231
242
|
const ERR_INVALID_COMMENT = "Zip file comment exceeds 64KB";
|
|
232
243
|
const ERR_INVALID_COMMENT_TYPE = "Invalid zip file comment (must be a Uint8Array)";
|
|
233
244
|
const ERR_INVALID_ENTRY_COMMENT = "File entry comment exceeds 64KB";
|
|
245
|
+
const ERR_INVALID_ENTRY_COMMENT_TYPE = "Invalid file entry comment (must be a string)";
|
|
246
|
+
const ERR_INVALID_DATE = "Invalid date (must be a valid Date instance)";
|
|
234
247
|
const ERR_INVALID_ENTRY_NAME = "File entry name exceeds 64KB";
|
|
235
248
|
const ERR_INVALID_VERSION = "Version exceeds 65535";
|
|
236
249
|
const ERR_INVALID_ENCRYPTION_STRENGTH = "The strength must equal 1, 2, or 3";
|
|
237
250
|
const ERR_UNSUPPORTED_ENCRYPTION_USDZ = "Encryption is not supported in USDZ files";
|
|
238
251
|
const ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH = "Encryption is not supported when the 'passThrough' option is set";
|
|
239
|
-
const
|
|
252
|
+
const ERR_INVALID_EXTRAFIELD = "Invalid extra field (must be a Map)";
|
|
253
|
+
const ERR_INVALID_EXTRAFIELD_TYPE = "Invalid extra field type (must be integer 0..65535)";
|
|
254
|
+
const ERR_INVALID_EXTRAFIELD_DATA_TYPE = "Invalid extra field data (must be a Uint8Array)";
|
|
240
255
|
const ERR_INVALID_EXTRAFIELD_DATA = "Extra field data exceeds 64KB";
|
|
241
256
|
const ERR_UNSUPPORTED_COMPRESSION = "Compression method not supported";
|
|
242
257
|
const MIN_UNIX_TIME = -2147483648;
|
|
@@ -256,7 +271,6 @@ const ERR_INVALID_UNIX_ID_SIZE = "uid/gid must be 0..65535 for unixExtraFieldTyp
|
|
|
256
271
|
const ERR_INVALID_MSDOS_ATTRIBUTES = "Invalid msdosAttributesRaw (must be integer 0..255)";
|
|
257
272
|
const ERR_INVALID_MSDOS_DATA = "Invalid msdosAttributes (must be an object with boolean flags)";
|
|
258
273
|
const ERR_INVALID_LEVEL = "Invalid level (must be integer 0..9)";
|
|
259
|
-
const ERR_INVALID_PASSWORD_TYPE = "Invalid password (password must be a string, rawPassword must be a Uint8Array)";
|
|
260
274
|
const ERR_INVALID_SIGNATURE_DATA = "Signature data exceeds 64KB";
|
|
261
275
|
|
|
262
276
|
const EXTRAFIELD_DATA_AES = new Uint8Array([0x07, 0x00, 0x02, 0x00, 0x41, 0x45, 0x03, 0x00, 0x00]);
|
|
@@ -281,8 +295,7 @@ class ZipWriter {
|
|
|
281
295
|
writer,
|
|
282
296
|
addSplitZipSignature,
|
|
283
297
|
options,
|
|
284
|
-
|
|
285
|
-
files: new Map(),
|
|
298
|
+
fileEntries: new Map(),
|
|
286
299
|
filenames: new Set(),
|
|
287
300
|
offset: options[OPTION_OFFSET] === UNDEFINED_VALUE ? writer.size || writer.writable.size || 0 : options[OPTION_OFFSET],
|
|
288
301
|
initialOffset: options[OPTION_OFFSET] === UNDEFINED_VALUE ? 0 : options[OPTION_OFFSET] - (writer.size || writer.writable.size || 0),
|
|
@@ -303,14 +316,23 @@ class ZipWriter {
|
|
|
303
316
|
await initStream(reader);
|
|
304
317
|
}
|
|
305
318
|
const { ZipReader } = await import("./zip-reader.js");
|
|
306
|
-
const zipReader = new ZipReader(reader
|
|
319
|
+
const zipReader = new ZipReader(reader);
|
|
307
320
|
const entries = await zipReader.getEntries();
|
|
308
321
|
await zipReader.close();
|
|
309
322
|
await initStream(this.writer);
|
|
310
|
-
|
|
311
|
-
|
|
323
|
+
const { directoryOffset } = zipReader;
|
|
324
|
+
let splitZipSignatureLength = 0;
|
|
325
|
+
if (this.addSplitZipSignature) {
|
|
326
|
+
delete this.addSplitZipSignature;
|
|
327
|
+
if (!await startsWithSplitZipSignature(reader)) {
|
|
328
|
+
await writeData(this.writer, getSplitZipSignatureArray());
|
|
329
|
+
splitZipSignatureLength = SPLIT_ZIP_FILE_SIGNATURE_LENGTH;
|
|
330
|
+
this.offset += splitZipSignatureLength;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
const entryPositions = await copyZipData(this, reader, entries, directoryOffset, splitZipSignatureLength);
|
|
312
334
|
this.filenames = new Set(entries.map(entry => entry.filename));
|
|
313
|
-
this.
|
|
335
|
+
this.fileEntries = new Map(entries.map(entry => {
|
|
314
336
|
const {
|
|
315
337
|
version,
|
|
316
338
|
rawLastModDate,
|
|
@@ -365,11 +387,12 @@ class ZipWriter {
|
|
|
365
387
|
if (crc32 !== UNDEFINED_VALUE) {
|
|
366
388
|
setUint32(headerView, HEADER_OFFSET_SIGNATURE, crc32);
|
|
367
389
|
}
|
|
390
|
+
const { offset, diskNumberStart } = entryPositions.get(entry);
|
|
368
391
|
Object.assign(entry, {
|
|
369
392
|
zip64UncompressedSize,
|
|
370
393
|
zip64CompressedSize,
|
|
371
|
-
|
|
372
|
-
diskNumberStart
|
|
394
|
+
offset,
|
|
395
|
+
diskNumberStart,
|
|
373
396
|
zip64DiskNumberStart: false,
|
|
374
397
|
rawExtraFieldZip64,
|
|
375
398
|
rawExtraFieldAES,
|
|
@@ -389,11 +412,8 @@ class ZipWriter {
|
|
|
389
412
|
async add(name = "", reader, options = {}) {
|
|
390
413
|
const zipWriter = this;
|
|
391
414
|
options = Object.assign({}, options);
|
|
392
|
-
const {
|
|
393
|
-
|
|
394
|
-
config
|
|
395
|
-
} = zipWriter;
|
|
396
|
-
if (workers < config.maxWorkers) {
|
|
415
|
+
const { pendingAddFileCalls } = zipWriter;
|
|
416
|
+
if (workers < getConfiguration().maxWorkers) {
|
|
397
417
|
workers++;
|
|
398
418
|
} else {
|
|
399
419
|
await new Promise(resolve => pendingEntries.push(resolve));
|
|
@@ -430,16 +450,16 @@ class ZipWriter {
|
|
|
430
450
|
}
|
|
431
451
|
|
|
432
452
|
remove(entry) {
|
|
433
|
-
const { filenames,
|
|
453
|
+
const { filenames, fileEntries } = this;
|
|
434
454
|
// deno-lint-ignore valid-typeof
|
|
435
455
|
if (typeof entry == STRING_TYPE) {
|
|
436
|
-
entry =
|
|
456
|
+
entry = fileEntries.get(entry);
|
|
437
457
|
}
|
|
438
458
|
if (entry && entry.filename !== UNDEFINED_VALUE) {
|
|
439
459
|
const { filename } = entry;
|
|
440
|
-
if (filenames.has(filename) &&
|
|
460
|
+
if (filenames.has(filename) && fileEntries.has(filename)) {
|
|
441
461
|
filenames.delete(filename);
|
|
442
|
-
|
|
462
|
+
fileEntries.delete(filename);
|
|
443
463
|
return true;
|
|
444
464
|
}
|
|
445
465
|
}
|
|
@@ -539,8 +559,12 @@ export {
|
|
|
539
559
|
ERR_INVALID_COMMENT_TYPE,
|
|
540
560
|
ERR_INVALID_ENTRY_NAME,
|
|
541
561
|
ERR_INVALID_ENTRY_COMMENT,
|
|
562
|
+
ERR_INVALID_ENTRY_COMMENT_TYPE,
|
|
563
|
+
ERR_INVALID_DATE,
|
|
542
564
|
ERR_INVALID_VERSION,
|
|
565
|
+
ERR_INVALID_EXTRAFIELD,
|
|
543
566
|
ERR_INVALID_EXTRAFIELD_TYPE,
|
|
567
|
+
ERR_INVALID_EXTRAFIELD_DATA_TYPE,
|
|
544
568
|
ERR_INVALID_EXTRAFIELD_DATA,
|
|
545
569
|
ERR_INVALID_ENCRYPTION_STRENGTH,
|
|
546
570
|
ERR_UNSUPPORTED_ENCRYPTION_USDZ,
|
|
@@ -569,12 +593,12 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
569
593
|
const metadataInfo = resolveMetadata(zipWriter, name, options);
|
|
570
594
|
const { comment } = metadataInfo;
|
|
571
595
|
const extraField = options[PROPERTY_NAME_EXTRA_FIELD];
|
|
572
|
-
zipWriter.
|
|
596
|
+
zipWriter.fileEntries.set(name, UNDEFINED_VALUE);
|
|
573
597
|
let fileEntry;
|
|
574
598
|
try {
|
|
575
599
|
const { resolvedOptions } = metadataInfo;
|
|
576
600
|
if (resolvedOptions.level != 0 && resolvedOptions.compressionMethod === UNDEFINED_VALUE &&
|
|
577
|
-
!resolvedOptions.passThrough && !(await supportsDeflate(
|
|
601
|
+
!resolvedOptions.passThrough && !(await supportsDeflate(getConfiguration()))) {
|
|
578
602
|
resolvedOptions.level = 0;
|
|
579
603
|
}
|
|
580
604
|
const sizesInfo = await resolveSizes(zipWriter, reader, metadataInfo, options);
|
|
@@ -592,7 +616,7 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
592
616
|
const metadataSize = getLength(headerInfo.localHeaderArray, dataDescriptorInfo.dataDescriptorArray);
|
|
593
617
|
fileEntry = await getFileEntry(zipWriter, name, reader, { headerInfo, dataDescriptorInfo, metadataSize }, options);
|
|
594
618
|
} catch (error) {
|
|
595
|
-
zipWriter.
|
|
619
|
+
zipWriter.fileEntries.delete(name);
|
|
596
620
|
throw error;
|
|
597
621
|
}
|
|
598
622
|
Object.assign(fileEntry, {
|
|
@@ -636,9 +660,9 @@ function resolveAttributes(zipWriter, name, options) {
|
|
|
636
660
|
if (unixExtraFieldType === UNDEFINED_VALUE && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
|
|
637
661
|
unixExtraFieldType = INFOZIP_EXTRA_FIELD_TYPE;
|
|
638
662
|
}
|
|
639
|
-
let msdosAttributesRaw =
|
|
663
|
+
let msdosAttributesRaw = getNumberOptionValue(zipWriter, options, PROPERTY_NAME_MSDOS_ATTRIBUTES_RAW);
|
|
640
664
|
let msdosAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_MSDOS_ATTRIBUTES);
|
|
641
|
-
const hasUnixMetadata = uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE || unixMode !== UNDEFINED_VALUE || unixExtraFieldType;
|
|
665
|
+
const hasUnixMetadata = uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE || unixMode !== UNDEFINED_VALUE || unixExtraFieldType || executable;
|
|
642
666
|
const hasMsDosProvided = msdosAttributesRaw !== UNDEFINED_VALUE || msdosAttributes !== UNDEFINED_VALUE;
|
|
643
667
|
if (hasUnixMetadata) {
|
|
644
668
|
msDosCompatible = false;
|
|
@@ -647,10 +671,10 @@ function resolveAttributes(zipWriter, name, options) {
|
|
|
647
671
|
msDosCompatible = true;
|
|
648
672
|
versionMadeBy = (versionMadeBy & MAX_8_BITS);
|
|
649
673
|
}
|
|
650
|
-
if (msdosAttributesRaw !== UNDEFINED_VALUE && (msdosAttributesRaw < 0 || msdosAttributesRaw > MAX_8_BITS)) {
|
|
674
|
+
if (msdosAttributesRaw !== UNDEFINED_VALUE && (!Number.isInteger(msdosAttributesRaw) || msdosAttributesRaw < 0 || msdosAttributesRaw > MAX_8_BITS)) {
|
|
651
675
|
throw new Error(ERR_INVALID_MSDOS_ATTRIBUTES);
|
|
652
676
|
}
|
|
653
|
-
if (msdosAttributes && typeof msdosAttributes !== OBJECT_TYPE) {
|
|
677
|
+
if (msdosAttributes && (typeof msdosAttributes !== OBJECT_TYPE || Array.isArray(msdosAttributes))) {
|
|
654
678
|
throw new Error(ERR_INVALID_MSDOS_DATA);
|
|
655
679
|
}
|
|
656
680
|
if (versionMadeBy > MAX_16_BITS) {
|
|
@@ -738,7 +762,7 @@ function resolveAttributes(zipWriter, name, options) {
|
|
|
738
762
|
}
|
|
739
763
|
|
|
740
764
|
function resolveMetadata(zipWriter, name, options) {
|
|
741
|
-
const encode =
|
|
765
|
+
const encode = getFunctionOptionValue(zipWriter, options, OPTION_ENCODE_TEXT) || encodeText;
|
|
742
766
|
let rawFilename = encode(name, TEXT_TYPE_FILENAME);
|
|
743
767
|
if (rawFilename === UNDEFINED_VALUE) {
|
|
744
768
|
rawFilename = encodeText(name);
|
|
@@ -747,6 +771,10 @@ function resolveMetadata(zipWriter, name, options) {
|
|
|
747
771
|
throw new Error(ERR_INVALID_ENTRY_NAME);
|
|
748
772
|
}
|
|
749
773
|
const comment = options[PROPERTY_NAME_COMMENT] || "";
|
|
774
|
+
// deno-lint-ignore valid-typeof
|
|
775
|
+
if (typeof comment != STRING_TYPE) {
|
|
776
|
+
throw new Error(ERR_INVALID_ENTRY_COMMENT_TYPE);
|
|
777
|
+
}
|
|
750
778
|
let rawComment = encode(comment, TEXT_TYPE_COMMENT);
|
|
751
779
|
if (rawComment === UNDEFINED_VALUE) {
|
|
752
780
|
rawComment = encodeText(comment);
|
|
@@ -758,16 +786,14 @@ function resolveMetadata(zipWriter, name, options) {
|
|
|
758
786
|
if (version > MAX_16_BITS) {
|
|
759
787
|
throw new Error(ERR_INVALID_VERSION);
|
|
760
788
|
}
|
|
761
|
-
const lastModDate =
|
|
762
|
-
const lastAccessDate =
|
|
763
|
-
const creationDate =
|
|
789
|
+
const lastModDate = getDateOptionValue(zipWriter, options, PROPERTY_NAME_LAST_MODIFICATION_DATE, new Date());
|
|
790
|
+
const lastAccessDate = getDateOptionValue(zipWriter, options, PROPERTY_NAME_LAST_ACCESS_DATE);
|
|
791
|
+
const creationDate = getDateOptionValue(zipWriter, options, PROPERTY_NAME_CREATION_DATE);
|
|
764
792
|
const internalFileAttributes = getAliasedOptionValue(zipWriter, options, PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES, PROPERTY_NAME_DEPRECATED_INTERNAL_FILE_ATTRIBUTES, 0);
|
|
765
793
|
const passThrough = getOptionValue(zipWriter, options, OPTION_PASS_THROUGH);
|
|
766
794
|
const password = getOptionValue(zipWriter, options, OPTION_PASSWORD);
|
|
767
795
|
const rawPassword = getOptionValue(zipWriter, options, OPTION_RAW_PASSWORD);
|
|
768
|
-
|
|
769
|
-
throw new Error(ERR_INVALID_PASSWORD_TYPE);
|
|
770
|
-
}
|
|
796
|
+
checkPasswordOption(password, rawPassword);
|
|
771
797
|
const encryptionStrength = getNumberOptionValue(zipWriter, options, OPTION_ENCRYPTION_STRENGTH, 3);
|
|
772
798
|
const zipCrypto = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIPCRYPTO);
|
|
773
799
|
const extendedTimestamp = getOptionValue(zipWriter, options, OPTION_EXTENDED_TIMESTAMP, true);
|
|
@@ -776,9 +802,9 @@ function resolveMetadata(zipWriter, name, options) {
|
|
|
776
802
|
const useWebWorkers = getOptionValue(zipWriter, options, OPTION_USE_WEB_WORKERS);
|
|
777
803
|
const transferStreams = getOptionValue(zipWriter, options, OPTION_TRANSFER_STREAMS);
|
|
778
804
|
const bufferedWrite = getOptionValue(zipWriter, options, OPTION_BUFFERED_WRITE);
|
|
779
|
-
const createTempStream =
|
|
805
|
+
const createTempStream = getFunctionOptionValue(zipWriter, options, OPTION_CREATE_TEMP_STREAM);
|
|
780
806
|
const dataDescriptorSignature = getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR_SIGNATURE, true);
|
|
781
|
-
const signal = getOptionValue(zipWriter, options, OPTION_SIGNAL);
|
|
807
|
+
const signal = checkSignalOption(getOptionValue(zipWriter, options, OPTION_SIGNAL));
|
|
782
808
|
const useUnicodeFileNames = getOptionValue(zipWriter, options, OPTION_USE_UNICODE_FILE_NAMES, true);
|
|
783
809
|
const compressionMethod = getOptionValue(zipWriter, options, PROPERTY_NAME_COMPRESSION_METHOD);
|
|
784
810
|
const registeredCodec = passThrough || compressionMethod === UNDEFINED_VALUE ? UNDEFINED_VALUE : getRegisteredCodec(compressionMethod);
|
|
@@ -858,18 +884,26 @@ function serializeExtraField(extraField) {
|
|
|
858
884
|
if (!extraField) {
|
|
859
885
|
return EMPTY_UINT8_ARRAY;
|
|
860
886
|
}
|
|
887
|
+
if (!(extraField instanceof Map)) {
|
|
888
|
+
throw new Error(ERR_INVALID_EXTRAFIELD);
|
|
889
|
+
}
|
|
861
890
|
let extraFieldSize = 0;
|
|
862
891
|
let offset = 0;
|
|
863
|
-
extraField.forEach(data => extraFieldSize += 4 + getLength(data));
|
|
864
|
-
const rawExtraField = new Uint8Array(extraFieldSize);
|
|
865
|
-
const rawExtraFieldView = getDataView(rawExtraField);
|
|
866
892
|
extraField.forEach((data, type) => {
|
|
867
|
-
if (type > MAX_16_BITS) {
|
|
893
|
+
if (!Number.isInteger(type) || type < 0 || type > MAX_16_BITS) {
|
|
868
894
|
throw new Error(ERR_INVALID_EXTRAFIELD_TYPE);
|
|
869
895
|
}
|
|
896
|
+
if (!(data instanceof Uint8Array)) {
|
|
897
|
+
throw new Error(ERR_INVALID_EXTRAFIELD_DATA_TYPE);
|
|
898
|
+
}
|
|
870
899
|
if (getLength(data) > MAX_16_BITS) {
|
|
871
900
|
throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
|
|
872
901
|
}
|
|
902
|
+
extraFieldSize += 4 + getLength(data);
|
|
903
|
+
});
|
|
904
|
+
const rawExtraField = new Uint8Array(extraFieldSize);
|
|
905
|
+
const rawExtraFieldView = getDataView(rawExtraField);
|
|
906
|
+
extraField.forEach((data, type) => {
|
|
873
907
|
setUint16(rawExtraFieldView, offset, type);
|
|
874
908
|
setUint16(rawExtraFieldView, offset + 2, getLength(data));
|
|
875
909
|
arraySet(rawExtraField, data, offset + 4);
|
|
@@ -956,8 +990,8 @@ function resolveEntrySizes(zipWriter, hasContent, contentSize, metadata, options
|
|
|
956
990
|
}
|
|
957
991
|
|
|
958
992
|
async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comment) {
|
|
959
|
-
const zipWriter = { options: writerOptions
|
|
960
|
-
if (writerOptions[OPTION_SIGN_CENTRAL_DIRECTORY]) {
|
|
993
|
+
const zipWriter = { options: writerOptions };
|
|
994
|
+
if (checkFunctionOption(writerOptions[OPTION_SIGN_CENTRAL_DIRECTORY])) {
|
|
961
995
|
throw new Error(ERR_UNDETERMINED_SIZE);
|
|
962
996
|
}
|
|
963
997
|
if (comment !== UNDEFINED_VALUE && !(comment instanceof Uint8Array)) {
|
|
@@ -983,7 +1017,7 @@ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comm
|
|
|
983
1017
|
({ name } = attributesInfo);
|
|
984
1018
|
const { resolvedOptions: metadata } = resolveMetadata(zipWriter, name, options);
|
|
985
1019
|
if (metadata.level != 0 && metadata.compressionMethod === UNDEFINED_VALUE &&
|
|
986
|
-
!metadata.passThrough && !(await supportsDeflate(
|
|
1020
|
+
!metadata.passThrough && !(await supportsDeflate(getConfiguration()))) {
|
|
987
1021
|
metadata.level = 0;
|
|
988
1022
|
}
|
|
989
1023
|
const hasContent = !getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY);
|
|
@@ -1032,7 +1066,7 @@ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comm
|
|
|
1032
1066
|
|
|
1033
1067
|
async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
1034
1068
|
const {
|
|
1035
|
-
|
|
1069
|
+
fileEntries,
|
|
1036
1070
|
writer
|
|
1037
1071
|
} = zipWriter;
|
|
1038
1072
|
const {
|
|
@@ -1054,12 +1088,12 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
|
1054
1088
|
let writerSizeBeforeEntry;
|
|
1055
1089
|
let flushedBufferedSize = 0;
|
|
1056
1090
|
let fileWriter;
|
|
1057
|
-
|
|
1091
|
+
fileEntries.set(name, fileEntry);
|
|
1058
1092
|
zipWriter.lastFileEntry = fileEntry;
|
|
1059
1093
|
try {
|
|
1060
1094
|
let lockPreviousFileEntry;
|
|
1061
1095
|
if (keepOrder) {
|
|
1062
|
-
lockPreviousFileEntry = previousFileEntry && previousFileEntry.
|
|
1096
|
+
lockPreviousFileEntry = previousFileEntry && previousFileEntry.lockFileEntry;
|
|
1063
1097
|
requestLockCurrentFileEntry();
|
|
1064
1098
|
}
|
|
1065
1099
|
if (options.bufferedWrite || !keepOrder || zipWriter.writerLocked || zipWriter.bufferedWrites || !dataDescriptor) {
|
|
@@ -1080,11 +1114,8 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
|
1080
1114
|
const diskOffset = getDiskOffset(writer);
|
|
1081
1115
|
if (zipWriter.addSplitZipSignature) {
|
|
1082
1116
|
delete zipWriter.addSplitZipSignature;
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
setUint32(signatureArrayView, 0, SPLIT_ZIP_FILE_SIGNATURE);
|
|
1086
|
-
await writeData(writer, signatureArray);
|
|
1087
|
-
zipWriter.offset += 4;
|
|
1117
|
+
await writeData(writer, getSplitZipSignatureArray());
|
|
1118
|
+
zipWriter.offset += SPLIT_ZIP_FILE_SIGNATURE_LENGTH;
|
|
1088
1119
|
}
|
|
1089
1120
|
if (usdz && !bufferedWrite) {
|
|
1090
1121
|
appendExtraFieldUSDZ(entryInfo, zipWriter.offset - diskOffset);
|
|
@@ -1102,11 +1133,11 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
|
1102
1133
|
writerSizeBeforeEntry = writer.size;
|
|
1103
1134
|
await writeData(fileWriter, localHeaderArray);
|
|
1104
1135
|
}
|
|
1105
|
-
fileEntry = await createFileEntry(reader, fileWriter, fileEntry, entryInfo,
|
|
1136
|
+
fileEntry = await createFileEntry(reader, fileWriter, fileEntry, entryInfo, getConfiguration(), options);
|
|
1106
1137
|
if (!bufferedWrite) {
|
|
1107
1138
|
writingEntryData = false;
|
|
1108
1139
|
}
|
|
1109
|
-
|
|
1140
|
+
fileEntries.set(name, fileEntry);
|
|
1110
1141
|
fileEntry.filename = name;
|
|
1111
1142
|
if (bufferedWrite) {
|
|
1112
1143
|
await Promise.all([fileWriter.writable.getWriter().close(), lockPreviousFileEntry]);
|
|
@@ -1147,7 +1178,7 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
|
1147
1178
|
zipWriter.offset += flushedBufferedSize;
|
|
1148
1179
|
}
|
|
1149
1180
|
}
|
|
1150
|
-
|
|
1181
|
+
fileEntries.delete(name);
|
|
1151
1182
|
throw error;
|
|
1152
1183
|
} finally {
|
|
1153
1184
|
if (bufferedWrite) {
|
|
@@ -1169,7 +1200,7 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
|
1169
1200
|
}
|
|
1170
1201
|
|
|
1171
1202
|
function requestLockCurrentFileEntry() {
|
|
1172
|
-
fileEntry.
|
|
1203
|
+
fileEntry.lockFileEntry = new Promise(resolve => releaseLockCurrentFileEntry = resolve);
|
|
1173
1204
|
}
|
|
1174
1205
|
|
|
1175
1206
|
async function requestLockWriter() {
|
|
@@ -1189,7 +1220,7 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
|
1189
1220
|
}
|
|
1190
1221
|
}
|
|
1191
1222
|
|
|
1192
|
-
async function createFileEntry(reader, writer, { diskNumberStart,
|
|
1223
|
+
async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry }, entryInfo, config, options) {
|
|
1193
1224
|
const {
|
|
1194
1225
|
headerInfo,
|
|
1195
1226
|
dataDescriptorInfo,
|
|
@@ -1257,7 +1288,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
|
|
|
1257
1288
|
codecURI
|
|
1258
1289
|
} = options;
|
|
1259
1290
|
const fileEntry = {
|
|
1260
|
-
|
|
1291
|
+
lockFileEntry,
|
|
1261
1292
|
versionMadeBy,
|
|
1262
1293
|
zip64,
|
|
1263
1294
|
directory: Boolean(directory),
|
|
@@ -1299,7 +1330,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
|
|
|
1299
1330
|
}
|
|
1300
1331
|
const { writable } = writer;
|
|
1301
1332
|
if (reader) {
|
|
1302
|
-
const readable = toCompatibleReadable(
|
|
1333
|
+
const readable = toCompatibleReadable(createReadable(reader));
|
|
1303
1334
|
const size = reader.size;
|
|
1304
1335
|
const workerOptions = {
|
|
1305
1336
|
options: {
|
|
@@ -1411,14 +1442,14 @@ function getHeaderInfo(options) {
|
|
|
1411
1442
|
if (zip64 && (zip64UncompressedSize || zip64CompressedSize)) {
|
|
1412
1443
|
const length = 4 + 16;
|
|
1413
1444
|
const extraFieldZip64 = createRecordWriter(length);
|
|
1414
|
-
extraFieldZip64.
|
|
1415
|
-
extraFieldZip64.
|
|
1445
|
+
extraFieldZip64.writeUint16(EXTRAFIELD_TYPE_ZIP64);
|
|
1446
|
+
extraFieldZip64.writeUint16(length - 4);
|
|
1416
1447
|
rawLocalExtraFieldZip64 = extraFieldZip64.array;
|
|
1417
1448
|
if (zip64ExtraFieldComplete) {
|
|
1418
|
-
extraFieldZip64.
|
|
1449
|
+
extraFieldZip64.writeUint64(uncompressedSize);
|
|
1419
1450
|
if (uncompressedFile) {
|
|
1420
1451
|
const encryptionOverhead = encrypted ? (zipCrypto ? 12 : 16 + encryptionStrength * 4) : 0;
|
|
1421
|
-
extraFieldZip64.
|
|
1452
|
+
extraFieldZip64.writeUint64(passThrough ? 0 : uncompressedSize + encryptionOverhead);
|
|
1422
1453
|
}
|
|
1423
1454
|
}
|
|
1424
1455
|
} else {
|
|
@@ -1427,8 +1458,8 @@ function getHeaderInfo(options) {
|
|
|
1427
1458
|
let rawExtraFieldAES;
|
|
1428
1459
|
if (encrypted && !zipCrypto) {
|
|
1429
1460
|
const extraFieldAES = createRecordWriter(getLength(EXTRAFIELD_DATA_AES) + 2);
|
|
1430
|
-
extraFieldAES.
|
|
1431
|
-
extraFieldAES.
|
|
1461
|
+
extraFieldAES.writeUint16(EXTRAFIELD_TYPE_AES);
|
|
1462
|
+
extraFieldAES.writeBytes(EXTRAFIELD_DATA_AES);
|
|
1432
1463
|
rawExtraFieldAES = extraFieldAES.array;
|
|
1433
1464
|
rawExtraFieldAES[8] = encryptionStrength;
|
|
1434
1465
|
} else {
|
|
@@ -1444,15 +1475,15 @@ function getHeaderInfo(options) {
|
|
|
1444
1475
|
const extraFieldTimestampLength = 9 + (lastAccessDate ? 4 : 0) + (creationDate ? 4 : 0);
|
|
1445
1476
|
const extraFieldTimestamp = createRecordWriter(extraFieldTimestampLength);
|
|
1446
1477
|
extraFieldExtendedTimestampFlag = 0x1 + (lastAccessDate ? 0x2 : 0) + (creationDate ? 0x4 : 0);
|
|
1447
|
-
extraFieldTimestamp.
|
|
1448
|
-
extraFieldTimestamp.
|
|
1449
|
-
extraFieldTimestamp.
|
|
1450
|
-
extraFieldTimestamp.
|
|
1478
|
+
extraFieldTimestamp.writeUint16(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
|
|
1479
|
+
extraFieldTimestamp.writeUint16(extraFieldTimestampLength - 4);
|
|
1480
|
+
extraFieldTimestamp.writeUint8(extraFieldExtendedTimestampFlag);
|
|
1481
|
+
extraFieldTimestamp.writeUint32(lastModTimeUnix);
|
|
1451
1482
|
if (lastAccessDate) {
|
|
1452
|
-
extraFieldTimestamp.
|
|
1483
|
+
extraFieldTimestamp.writeUint32(clampUnixTime(getTimeUnix(lastAccessDate)));
|
|
1453
1484
|
}
|
|
1454
1485
|
if (creationDate) {
|
|
1455
|
-
extraFieldTimestamp.
|
|
1486
|
+
extraFieldTimestamp.writeUint32(clampUnixTime(getTimeUnix(creationDate)));
|
|
1456
1487
|
}
|
|
1457
1488
|
rawExtraFieldExtendedTimestamp = extraFieldTimestamp.array;
|
|
1458
1489
|
} else {
|
|
@@ -1465,14 +1496,14 @@ function getHeaderInfo(options) {
|
|
|
1465
1496
|
try {
|
|
1466
1497
|
const lastModTimeNTFS = getTimeNTFS(lastModDate);
|
|
1467
1498
|
const extraFieldNTFS = createRecordWriter(36);
|
|
1468
|
-
extraFieldNTFS.
|
|
1469
|
-
extraFieldNTFS.
|
|
1499
|
+
extraFieldNTFS.writeUint16(EXTRAFIELD_TYPE_NTFS);
|
|
1500
|
+
extraFieldNTFS.writeUint16(32);
|
|
1470
1501
|
extraFieldNTFS.skip(4);
|
|
1471
|
-
extraFieldNTFS.
|
|
1472
|
-
extraFieldNTFS.
|
|
1473
|
-
extraFieldNTFS.
|
|
1474
|
-
extraFieldNTFS.
|
|
1475
|
-
extraFieldNTFS.
|
|
1502
|
+
extraFieldNTFS.writeUint16(EXTRAFIELD_TYPE_NTFS_TAG1);
|
|
1503
|
+
extraFieldNTFS.writeUint16(24);
|
|
1504
|
+
extraFieldNTFS.writeUint64(lastModTimeNTFS);
|
|
1505
|
+
extraFieldNTFS.writeUint64(lastAccessDate ? getTimeNTFS(lastAccessDate) : lastModTimeNTFS);
|
|
1506
|
+
extraFieldNTFS.writeUint64(creationDate ? getTimeNTFS(creationDate) : lastModTimeNTFS);
|
|
1476
1507
|
rawExtraFieldNTFS = extraFieldNTFS.array;
|
|
1477
1508
|
} catch {
|
|
1478
1509
|
rawExtraFieldNTFS = EMPTY_UINT8_ARRAY;
|
|
@@ -1491,20 +1522,20 @@ function getHeaderInfo(options) {
|
|
|
1491
1522
|
const gidBytes = packUnixId(gid);
|
|
1492
1523
|
const payloadLength = 3 + uidBytes.length + gidBytes.length;
|
|
1493
1524
|
const extraFieldUnix = createRecordWriter(4 + payloadLength);
|
|
1494
|
-
extraFieldUnix.
|
|
1495
|
-
extraFieldUnix.
|
|
1496
|
-
extraFieldUnix.
|
|
1497
|
-
extraFieldUnix.
|
|
1498
|
-
extraFieldUnix.
|
|
1499
|
-
extraFieldUnix.
|
|
1500
|
-
extraFieldUnix.
|
|
1525
|
+
extraFieldUnix.writeUint16(EXTRAFIELD_TYPE_INFOZIP);
|
|
1526
|
+
extraFieldUnix.writeUint16(payloadLength);
|
|
1527
|
+
extraFieldUnix.writeUint8(1);
|
|
1528
|
+
extraFieldUnix.writeUint8(uidBytes.length);
|
|
1529
|
+
extraFieldUnix.writeBytes(uidBytes);
|
|
1530
|
+
extraFieldUnix.writeUint8(gidBytes.length);
|
|
1531
|
+
extraFieldUnix.writeBytes(gidBytes);
|
|
1501
1532
|
rawExtraFieldUnix = extraFieldUnix.array;
|
|
1502
1533
|
} else if (unixExtraFieldType == UNIX_EXTRA_FIELD_TYPE && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
|
|
1503
1534
|
const extraFieldUnix = createRecordWriter(8);
|
|
1504
|
-
extraFieldUnix.
|
|
1505
|
-
extraFieldUnix.
|
|
1506
|
-
extraFieldUnix.
|
|
1507
|
-
extraFieldUnix.
|
|
1535
|
+
extraFieldUnix.writeUint16(EXTRAFIELD_TYPE_UNIX);
|
|
1536
|
+
extraFieldUnix.writeUint16(4);
|
|
1537
|
+
extraFieldUnix.writeUint16((uid === UNDEFINED_VALUE ? 0 : uid) & MAX_16_BITS);
|
|
1538
|
+
extraFieldUnix.writeUint16((gid === UNDEFINED_VALUE ? 0 : gid) & MAX_16_BITS);
|
|
1508
1539
|
rawExtraFieldUnix = extraFieldUnix.array;
|
|
1509
1540
|
} else {
|
|
1510
1541
|
rawExtraFieldUnix = EMPTY_UINT8_ARRAY;
|
|
@@ -1554,18 +1585,18 @@ function getHeaderInfo(options) {
|
|
|
1554
1585
|
const localHeader = createRecordWriter(HEADER_SIZE + getLength(rawFilename) + extraFieldLength);
|
|
1555
1586
|
const localHeaderArray = localHeader.array;
|
|
1556
1587
|
const localHeaderView = getDataView(localHeaderArray);
|
|
1557
|
-
localHeader.
|
|
1558
|
-
localHeader.
|
|
1559
|
-
localHeader.
|
|
1588
|
+
localHeader.writeUint32(LOCAL_FILE_HEADER_SIGNATURE);
|
|
1589
|
+
localHeader.writeBytes(headerArray);
|
|
1590
|
+
localHeader.writeBytes(rawFilename);
|
|
1560
1591
|
if (writeLocalExtraFieldZip64) {
|
|
1561
|
-
localHeader.
|
|
1562
|
-
}
|
|
1563
|
-
localHeader.
|
|
1564
|
-
localHeader.
|
|
1565
|
-
localHeader.
|
|
1566
|
-
localHeader.
|
|
1567
|
-
localHeader.
|
|
1568
|
-
localHeader.
|
|
1592
|
+
localHeader.writeBytes(rawLocalExtraFieldZip64);
|
|
1593
|
+
}
|
|
1594
|
+
localHeader.writeBytes(rawExtraFieldAES);
|
|
1595
|
+
localHeader.writeBytes(rawExtraFieldExtendedTimestamp);
|
|
1596
|
+
localHeader.writeBytes(rawExtraFieldNTFS);
|
|
1597
|
+
localHeader.writeBytes(rawExtraFieldUnix);
|
|
1598
|
+
localHeader.writeBytes(rawExtraField);
|
|
1599
|
+
localHeader.writeBytes(rawLocalExtraField);
|
|
1569
1600
|
if (dataDescriptor) {
|
|
1570
1601
|
if (!zip64CompressedSize) {
|
|
1571
1602
|
setUint32(localHeaderView, HEADER_OFFSET_COMPRESSED_SIZE + LOCAL_HEADER_COMMON_OFFSET, 0);
|
|
@@ -1755,7 +1786,7 @@ function updateLocalHeader({
|
|
|
1755
1786
|
|
|
1756
1787
|
|
|
1757
1788
|
async function closeFile(zipWriter, comment, options) {
|
|
1758
|
-
const directoryDataLength = createDirectoryRecords(zipWriter.
|
|
1789
|
+
const directoryDataLength = createDirectoryRecords(zipWriter.fileEntries);
|
|
1759
1790
|
const { directoryStart, directoryArray } = await writeDirectoryRecords(zipWriter, directoryDataLength, options);
|
|
1760
1791
|
const signatureLength = await writeDigitalSignatureRecord(zipWriter, directoryArray, options);
|
|
1761
1792
|
await writeEndOfDirectoryRecord(zipWriter, comment, options, { directoryStart, directoryDataLength, signatureLength });
|
|
@@ -1785,19 +1816,19 @@ function createDirectoryRecords(files) {
|
|
|
1785
1816
|
if (zip64Offset || zip64DiskNumberStart || zip64UncompressedSize || zip64CompressedSize) {
|
|
1786
1817
|
const length = 4 + (zip64UncompressedSize ? 8 : 0) + (zip64CompressedSize ? 8 : 0) + (zip64Offset ? 8 : 0) + (zip64DiskNumberStart ? 4 : 0);
|
|
1787
1818
|
const extraFieldZip64 = createRecordWriter(length);
|
|
1788
|
-
extraFieldZip64.
|
|
1789
|
-
extraFieldZip64.
|
|
1819
|
+
extraFieldZip64.writeUint16(EXTRAFIELD_TYPE_ZIP64);
|
|
1820
|
+
extraFieldZip64.writeUint16(length - 4);
|
|
1790
1821
|
if (zip64UncompressedSize) {
|
|
1791
|
-
extraFieldZip64.
|
|
1822
|
+
extraFieldZip64.writeUint64(uncompressedSize);
|
|
1792
1823
|
}
|
|
1793
1824
|
if (zip64CompressedSize) {
|
|
1794
|
-
extraFieldZip64.
|
|
1825
|
+
extraFieldZip64.writeUint64(compressedSize);
|
|
1795
1826
|
}
|
|
1796
1827
|
if (zip64Offset) {
|
|
1797
|
-
extraFieldZip64.
|
|
1828
|
+
extraFieldZip64.writeUint64(fileEntry.offset);
|
|
1798
1829
|
}
|
|
1799
1830
|
if (zip64DiskNumberStart) {
|
|
1800
|
-
extraFieldZip64.
|
|
1831
|
+
extraFieldZip64.writeUint32(fileEntry.diskNumberStart);
|
|
1801
1832
|
}
|
|
1802
1833
|
rawExtraFieldZip64 = extraFieldZip64.array;
|
|
1803
1834
|
} else {
|
|
@@ -1810,10 +1841,10 @@ function createDirectoryRecords(files) {
|
|
|
1810
1841
|
const lastModTimeUnix = getTimeUnix(lastModDate);
|
|
1811
1842
|
if (extendedTimestamp && inUnixTimeRange(lastModTimeUnix)) {
|
|
1812
1843
|
const extraFieldTimestamp = createRecordWriter(9);
|
|
1813
|
-
extraFieldTimestamp.
|
|
1814
|
-
extraFieldTimestamp.
|
|
1815
|
-
extraFieldTimestamp.
|
|
1816
|
-
extraFieldTimestamp.
|
|
1844
|
+
extraFieldTimestamp.writeUint16(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
|
|
1845
|
+
extraFieldTimestamp.writeUint16(5);
|
|
1846
|
+
extraFieldTimestamp.writeUint8(extraFieldExtendedTimestampFlag);
|
|
1847
|
+
extraFieldTimestamp.writeUint32(lastModTimeUnix);
|
|
1817
1848
|
rawExtraFieldTimestamp = extraFieldTimestamp.array;
|
|
1818
1849
|
} else {
|
|
1819
1850
|
rawExtraFieldTimestamp = EMPTY_UINT8_ARRAY;
|
|
@@ -1835,14 +1866,14 @@ function createDirectoryRecords(files) {
|
|
|
1835
1866
|
}
|
|
1836
1867
|
|
|
1837
1868
|
async function writeDirectoryRecords(zipWriter, directoryDataLength, options) {
|
|
1838
|
-
const {
|
|
1869
|
+
const { fileEntries, writer } = zipWriter;
|
|
1839
1870
|
const directoryArray = new Uint8Array(directoryDataLength);
|
|
1840
1871
|
await initStream(writer);
|
|
1841
1872
|
let offset = 0;
|
|
1842
1873
|
let directoryDiskOffset = 0;
|
|
1843
1874
|
let directoryStartDiskNumber = getDiskNumber(writer);
|
|
1844
1875
|
let directoryStartDiskOffset = getDiskOffset(writer);
|
|
1845
|
-
for (const [indexFileEntry, fileEntry] of Array.from(
|
|
1876
|
+
for (const [indexFileEntry, fileEntry] of Array.from(fileEntries.values()).entries()) {
|
|
1846
1877
|
const {
|
|
1847
1878
|
offset: fileEntryOffset,
|
|
1848
1879
|
rawFilename,
|
|
@@ -1887,28 +1918,28 @@ async function writeDirectoryRecords(zipWriter, directoryDataLength, options) {
|
|
|
1887
1918
|
setUint16(headerView, HEADER_OFFSET_VERSION, VERSION_ZIP64);
|
|
1888
1919
|
}
|
|
1889
1920
|
const directoryRecord = createRecordWriter(directoryRecordLength);
|
|
1890
|
-
directoryRecord.
|
|
1891
|
-
directoryRecord.
|
|
1892
|
-
directoryRecord.
|
|
1893
|
-
directoryRecord.
|
|
1894
|
-
directoryRecord.
|
|
1895
|
-
directoryRecord.
|
|
1896
|
-
directoryRecord.
|
|
1897
|
-
directoryRecord.
|
|
1898
|
-
directoryRecord.
|
|
1899
|
-
directoryRecord.
|
|
1900
|
-
directoryRecord.
|
|
1901
|
-
directoryRecord.
|
|
1902
|
-
directoryRecord.
|
|
1903
|
-
directoryRecord.
|
|
1904
|
-
directoryRecord.
|
|
1905
|
-
directoryRecord.
|
|
1906
|
-
directoryRecord.
|
|
1921
|
+
directoryRecord.writeUint32(CENTRAL_FILE_HEADER_SIGNATURE);
|
|
1922
|
+
directoryRecord.writeUint16(versionMadeBy);
|
|
1923
|
+
directoryRecord.writeBytes(headerArray.subarray(0, HEADER_SIZE - 4 - 2));
|
|
1924
|
+
directoryRecord.writeUint16(extraFieldLength);
|
|
1925
|
+
directoryRecord.writeUint16(getLength(rawComment));
|
|
1926
|
+
directoryRecord.writeUint16(zip64DiskNumberStart ? MAX_16_BITS : diskNumberStart);
|
|
1927
|
+
directoryRecord.writeUint16(internalFileAttributes);
|
|
1928
|
+
directoryRecord.writeUint32(externalFileAttributes);
|
|
1929
|
+
directoryRecord.writeUint32(zip64Offset ? MAX_32_BITS : fileEntryOffset);
|
|
1930
|
+
directoryRecord.writeBytes(rawFilename);
|
|
1931
|
+
directoryRecord.writeBytes(rawExtraFieldZip64);
|
|
1932
|
+
directoryRecord.writeBytes(rawExtraFieldAES);
|
|
1933
|
+
directoryRecord.writeBytes(rawExtraFieldExtendedTimestamp);
|
|
1934
|
+
directoryRecord.writeBytes(rawExtraFieldNTFS);
|
|
1935
|
+
directoryRecord.writeBytes(rawExtraFieldUnix);
|
|
1936
|
+
directoryRecord.writeBytes(rawExtraField);
|
|
1937
|
+
directoryRecord.writeBytes(rawComment);
|
|
1907
1938
|
arraySet(directoryArray, directoryRecord.array, offset);
|
|
1908
1939
|
offset += directoryRecordLength;
|
|
1909
1940
|
if (options.onprogress) {
|
|
1910
1941
|
try {
|
|
1911
|
-
await options.onprogress(indexFileEntry + 1,
|
|
1942
|
+
await options.onprogress(indexFileEntry + 1, fileEntries.size, new Entry(fileEntry));
|
|
1912
1943
|
} catch {
|
|
1913
1944
|
// ignored
|
|
1914
1945
|
}
|
|
@@ -1922,7 +1953,7 @@ async function writeDirectoryRecords(zipWriter, directoryDataLength, options) {
|
|
|
1922
1953
|
}
|
|
1923
1954
|
|
|
1924
1955
|
async function writeDigitalSignatureRecord(zipWriter, directoryArray, options) {
|
|
1925
|
-
const signCentralDirectory =
|
|
1956
|
+
const signCentralDirectory = getFunctionOptionValue(zipWriter, options, OPTION_SIGN_CENTRAL_DIRECTORY);
|
|
1926
1957
|
if (signCentralDirectory) {
|
|
1927
1958
|
const signatureData = await signCentralDirectory(directoryArray);
|
|
1928
1959
|
const signatureDataLength = getLength(signatureData);
|
|
@@ -1930,9 +1961,9 @@ async function writeDigitalSignatureRecord(zipWriter, directoryArray, options) {
|
|
|
1930
1961
|
throw new Error(ERR_INVALID_SIGNATURE_DATA);
|
|
1931
1962
|
}
|
|
1932
1963
|
const signatureRecord = createRecordWriter(6 + signatureDataLength);
|
|
1933
|
-
signatureRecord.
|
|
1934
|
-
signatureRecord.
|
|
1935
|
-
signatureRecord.
|
|
1964
|
+
signatureRecord.writeUint32(DIGITAL_SIGNATURE_RECORD_SIGNATURE);
|
|
1965
|
+
signatureRecord.writeUint16(signatureDataLength);
|
|
1966
|
+
signatureRecord.writeBytes(signatureData);
|
|
1936
1967
|
await writeData(zipWriter.writer, signatureRecord.array);
|
|
1937
1968
|
return 6 + signatureDataLength;
|
|
1938
1969
|
}
|
|
@@ -1943,7 +1974,7 @@ async function writeEndOfDirectoryRecord(zipWriter, comment, options, cdInfo) {
|
|
|
1943
1974
|
const { writer } = zipWriter;
|
|
1944
1975
|
const { directoryStart, signatureLength } = cdInfo;
|
|
1945
1976
|
let { directoryDataLength } = cdInfo;
|
|
1946
|
-
let
|
|
1977
|
+
let fileEntriesLength = zipWriter.fileEntries.size;
|
|
1947
1978
|
let diskNumber = directoryStart.diskNumber;
|
|
1948
1979
|
let directoryOffset = getSegmentOffset(zipWriter, directoryStart);
|
|
1949
1980
|
let lastDiskNumber = getDiskNumber(writer);
|
|
@@ -1951,7 +1982,7 @@ async function writeEndOfDirectoryRecord(zipWriter, comment, options, cdInfo) {
|
|
|
1951
1982
|
lastDiskNumber++;
|
|
1952
1983
|
}
|
|
1953
1984
|
let zip64 = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIP64);
|
|
1954
|
-
if (directoryOffset >= MAX_32_BITS || directoryDataLength >= MAX_32_BITS ||
|
|
1985
|
+
if (directoryOffset >= MAX_32_BITS || directoryDataLength >= MAX_32_BITS || fileEntriesLength >= MAX_16_BITS || lastDiskNumber >= MAX_16_BITS) {
|
|
1955
1986
|
if (zip64 === false) {
|
|
1956
1987
|
throw new Error(ERR_UNSUPPORTED_FORMAT);
|
|
1957
1988
|
} else {
|
|
@@ -1968,37 +1999,37 @@ async function writeEndOfDirectoryRecord(zipWriter, comment, options, cdInfo) {
|
|
|
1968
1999
|
}
|
|
1969
2000
|
lastDiskNumber = getDiskNumber(writer);
|
|
1970
2001
|
if (zip64) {
|
|
1971
|
-
endOfdirectoryRecord.
|
|
1972
|
-
endOfdirectoryRecord.
|
|
1973
|
-
endOfdirectoryRecord.
|
|
1974
|
-
endOfdirectoryRecord.
|
|
1975
|
-
endOfdirectoryRecord.
|
|
1976
|
-
endOfdirectoryRecord.
|
|
1977
|
-
endOfdirectoryRecord.
|
|
1978
|
-
endOfdirectoryRecord.
|
|
1979
|
-
endOfdirectoryRecord.
|
|
1980
|
-
endOfdirectoryRecord.
|
|
1981
|
-
endOfdirectoryRecord.
|
|
1982
|
-
endOfdirectoryRecord.
|
|
1983
|
-
endOfdirectoryRecord.
|
|
1984
|
-
endOfdirectoryRecord.
|
|
2002
|
+
endOfdirectoryRecord.writeUint32(ZIP64_END_OF_CENTRAL_DIR_SIGNATURE);
|
|
2003
|
+
endOfdirectoryRecord.writeUint64(44);
|
|
2004
|
+
endOfdirectoryRecord.writeUint16(45);
|
|
2005
|
+
endOfdirectoryRecord.writeUint16(45);
|
|
2006
|
+
endOfdirectoryRecord.writeUint32(lastDiskNumber);
|
|
2007
|
+
endOfdirectoryRecord.writeUint32(diskNumber);
|
|
2008
|
+
endOfdirectoryRecord.writeUint64(fileEntriesLength);
|
|
2009
|
+
endOfdirectoryRecord.writeUint64(fileEntriesLength);
|
|
2010
|
+
endOfdirectoryRecord.writeUint64(directoryDataLength);
|
|
2011
|
+
endOfdirectoryRecord.writeUint64(directoryOffset);
|
|
2012
|
+
endOfdirectoryRecord.writeUint32(ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIGNATURE);
|
|
2013
|
+
endOfdirectoryRecord.writeUint32(lastDiskNumber);
|
|
2014
|
+
endOfdirectoryRecord.writeUint64(BigInt(getSegmentOffset(zipWriter, writer)) + BigInt(directoryDataLength) + BigInt(signatureLength));
|
|
2015
|
+
endOfdirectoryRecord.writeUint32(lastDiskNumber + 1);
|
|
1985
2016
|
const supportZip64SplitFile = getOptionValue(zipWriter, options, OPTION_SUPPORT_ZIP64_SPLIT_FILE, true);
|
|
1986
2017
|
if (supportZip64SplitFile) {
|
|
1987
2018
|
lastDiskNumber = MAX_16_BITS;
|
|
1988
2019
|
diskNumber = MAX_16_BITS;
|
|
1989
2020
|
}
|
|
1990
|
-
|
|
2021
|
+
fileEntriesLength = MAX_16_BITS;
|
|
1991
2022
|
directoryOffset = MAX_32_BITS;
|
|
1992
2023
|
directoryDataLength = MAX_32_BITS;
|
|
1993
2024
|
}
|
|
1994
|
-
endOfdirectoryRecord.
|
|
1995
|
-
endOfdirectoryRecord.
|
|
1996
|
-
endOfdirectoryRecord.
|
|
1997
|
-
endOfdirectoryRecord.
|
|
1998
|
-
endOfdirectoryRecord.
|
|
1999
|
-
endOfdirectoryRecord.
|
|
2000
|
-
endOfdirectoryRecord.
|
|
2001
|
-
endOfdirectoryRecord.
|
|
2025
|
+
endOfdirectoryRecord.writeUint32(END_OF_CENTRAL_DIR_SIGNATURE);
|
|
2026
|
+
endOfdirectoryRecord.writeUint16(lastDiskNumber);
|
|
2027
|
+
endOfdirectoryRecord.writeUint16(diskNumber);
|
|
2028
|
+
endOfdirectoryRecord.writeUint16(fileEntriesLength);
|
|
2029
|
+
endOfdirectoryRecord.writeUint16(fileEntriesLength);
|
|
2030
|
+
endOfdirectoryRecord.writeUint32(directoryDataLength);
|
|
2031
|
+
endOfdirectoryRecord.writeUint32(directoryOffset);
|
|
2032
|
+
endOfdirectoryRecord.writeUint16(commentLength);
|
|
2002
2033
|
await writeData(writer, endOfdirectoryRecord.array);
|
|
2003
2034
|
if (commentLength) {
|
|
2004
2035
|
await writeData(writer, comment);
|
|
@@ -2011,11 +2042,11 @@ function createRecordWriter(length) {
|
|
|
2011
2042
|
let offset = 0;
|
|
2012
2043
|
return {
|
|
2013
2044
|
array,
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2045
|
+
writeUint8: value => { setUint8(view, offset, value); offset += 1; },
|
|
2046
|
+
writeUint16: value => { setUint16(view, offset, value); offset += 2; },
|
|
2047
|
+
writeUint32: value => { setUint32(view, offset, value); offset += 4; },
|
|
2048
|
+
writeUint64: value => { setBigUint64(view, offset, BigInt(value)); offset += 8; },
|
|
2049
|
+
writeBytes: value => { arraySet(array, value, offset); offset += getLength(value); },
|
|
2019
2050
|
skip: count => offset += count
|
|
2020
2051
|
};
|
|
2021
2052
|
}
|
|
@@ -2039,6 +2070,71 @@ function getSegmentOffset(zipWriter, { diskNumber = 0, diskOffset = 0 }) {
|
|
|
2039
2070
|
return zipWriter.offset - diskOffset - (diskNumber ? zipWriter.initialOffset : 0);
|
|
2040
2071
|
}
|
|
2041
2072
|
|
|
2073
|
+
async function startsWithSplitZipSignature(reader) {
|
|
2074
|
+
const signatureArray = await readUint8Array(reader, 0, SPLIT_ZIP_FILE_SIGNATURE_LENGTH);
|
|
2075
|
+
return getUint32(getDataView(signatureArray), 0) == SPLIT_ZIP_FILE_SIGNATURE;
|
|
2076
|
+
}
|
|
2077
|
+
|
|
2078
|
+
async function copyZipData(zipWriter, reader, entries, directoryOffset, splitZipSignatureLength) {
|
|
2079
|
+
const { writer } = zipWriter;
|
|
2080
|
+
const entryPositions = new Map();
|
|
2081
|
+
if (writer.closeDisk) {
|
|
2082
|
+
const sortedEntries = Array.from(entries).sort((firstEntry, secondEntry) =>
|
|
2083
|
+
getSourceOffset(reader, firstEntry) - getSourceOffset(reader, secondEntry));
|
|
2084
|
+
let copiedLength = 0;
|
|
2085
|
+
for (const entry of sortedEntries) {
|
|
2086
|
+
const sourceOffset = getSourceOffset(reader, entry);
|
|
2087
|
+
await copyData(zipWriter, reader, copiedLength, sourceOffset - copiedLength);
|
|
2088
|
+
if (exceedsAvailableSize(writer, await getLocalHeaderLength(reader, sourceOffset))) {
|
|
2089
|
+
await writer.closeDisk();
|
|
2090
|
+
}
|
|
2091
|
+
entryPositions.set(entry, {
|
|
2092
|
+
offset: getSegmentOffset(zipWriter, writer),
|
|
2093
|
+
diskNumberStart: getDiskNumber(writer)
|
|
2094
|
+
});
|
|
2095
|
+
copiedLength = sourceOffset;
|
|
2096
|
+
}
|
|
2097
|
+
await copyData(zipWriter, reader, copiedLength, directoryOffset - copiedLength);
|
|
2098
|
+
} else {
|
|
2099
|
+
await copyData(zipWriter, reader, 0, directoryOffset);
|
|
2100
|
+
entries.forEach(entry => entryPositions.set(entry, {
|
|
2101
|
+
offset: splitZipSignatureLength + getSourceOffset(reader, entry),
|
|
2102
|
+
diskNumberStart: 0
|
|
2103
|
+
}));
|
|
2104
|
+
}
|
|
2105
|
+
return entryPositions;
|
|
2106
|
+
}
|
|
2107
|
+
|
|
2108
|
+
async function copyData(zipWriter, reader, offset, size) {
|
|
2109
|
+
if (size > 0) {
|
|
2110
|
+
const { writer } = zipWriter;
|
|
2111
|
+
await createReadable(reader, { offset, size }).pipeTo(writer.writable, { preventClose: true, preventAbort: true });
|
|
2112
|
+
writer.size += size;
|
|
2113
|
+
zipWriter.offset += size;
|
|
2114
|
+
}
|
|
2115
|
+
}
|
|
2116
|
+
|
|
2117
|
+
async function getLocalHeaderLength(reader, offset) {
|
|
2118
|
+
const headerArray = await readUint8Array(reader, offset, HEADER_SIZE);
|
|
2119
|
+
if (getLength(headerArray) < HEADER_SIZE) {
|
|
2120
|
+
return HEADER_SIZE;
|
|
2121
|
+
}
|
|
2122
|
+
const headerView = getDataView(headerArray);
|
|
2123
|
+
return HEADER_SIZE +
|
|
2124
|
+
getUint16(headerView, HEADER_OFFSET_FILENAME_LENGTH + LOCAL_HEADER_COMMON_OFFSET) +
|
|
2125
|
+
getUint16(headerView, HEADER_OFFSET_EXTRAFIELD_LENGTH + LOCAL_HEADER_COMMON_OFFSET);
|
|
2126
|
+
}
|
|
2127
|
+
|
|
2128
|
+
function getSourceOffset(reader, { offset, diskNumberStart }) {
|
|
2129
|
+
return offset + (reader.getDiskOffset ? reader.getDiskOffset(diskNumberStart) : 0);
|
|
2130
|
+
}
|
|
2131
|
+
|
|
2132
|
+
function getSplitZipSignatureArray() {
|
|
2133
|
+
const signatureArray = new Uint8Array(SPLIT_ZIP_FILE_SIGNATURE_LENGTH);
|
|
2134
|
+
setUint32(getDataView(signatureArray), 0, SPLIT_ZIP_FILE_SIGNATURE);
|
|
2135
|
+
return signatureArray;
|
|
2136
|
+
}
|
|
2137
|
+
|
|
2042
2138
|
async function writeData(writer, array) {
|
|
2043
2139
|
const { writable } = writer;
|
|
2044
2140
|
const streamWriter = writable.getWriter();
|
|
@@ -2090,6 +2186,21 @@ function getOptionValue(zipWriter, options, name, defaultValue) {
|
|
|
2090
2186
|
return result === UNDEFINED_VALUE ? defaultValue : result;
|
|
2091
2187
|
}
|
|
2092
2188
|
|
|
2189
|
+
function getDateOptionValue(zipWriter, options, name, defaultValue) {
|
|
2190
|
+
const date = getOptionValue(zipWriter, options, name, defaultValue);
|
|
2191
|
+
if (date === null) {
|
|
2192
|
+
return defaultValue;
|
|
2193
|
+
}
|
|
2194
|
+
if (date !== UNDEFINED_VALUE && (typeof date.getTime != FUNCTION_TYPE || Number.isNaN(date.getTime()))) {
|
|
2195
|
+
throw new Error(ERR_INVALID_DATE);
|
|
2196
|
+
}
|
|
2197
|
+
return date;
|
|
2198
|
+
}
|
|
2199
|
+
|
|
2200
|
+
function getFunctionOptionValue(zipWriter, options, name) {
|
|
2201
|
+
return checkFunctionOption(getOptionValue(zipWriter, options, name));
|
|
2202
|
+
}
|
|
2203
|
+
|
|
2093
2204
|
function getAliasedOptionValue(zipWriter, options, name, deprecatedName, defaultValue) {
|
|
2094
2205
|
const value = getAliasedValue(options, name, deprecatedName);
|
|
2095
2206
|
const result = value === UNDEFINED_VALUE ? getAliasedValue(zipWriter.options, name, deprecatedName) : value;
|
|
@@ -2104,9 +2215,6 @@ function getNumberOptionValue(zipWriter, options, name, defaultValue) {
|
|
|
2104
2215
|
return toNumber(getOptionValue(zipWriter, options, name, defaultValue));
|
|
2105
2216
|
}
|
|
2106
2217
|
|
|
2107
|
-
function toNumber(value) {
|
|
2108
|
-
return typeof value == STRING_TYPE && value.trim() ? Number(value) : value;
|
|
2109
|
-
}
|
|
2110
2218
|
|
|
2111
2219
|
function getMaximumCompressedSize(uncompressedSize) {
|
|
2112
2220
|
return uncompressedSize + (5 * (Math.floor(uncompressedSize / 16383) + 1));
|
|
@@ -2118,6 +2226,14 @@ function isCompressed(compressionMethod, level) {
|
|
|
2118
2226
|
: compressionMethod !== COMPRESSION_METHOD_STORE;
|
|
2119
2227
|
}
|
|
2120
2228
|
|
|
2229
|
+
function getUint16(view, offset) {
|
|
2230
|
+
return view.getUint16(offset, true);
|
|
2231
|
+
}
|
|
2232
|
+
|
|
2233
|
+
function getUint32(view, offset) {
|
|
2234
|
+
return view.getUint32(offset, true);
|
|
2235
|
+
}
|
|
2236
|
+
|
|
2121
2237
|
function setUint8(view, offset, value) {
|
|
2122
2238
|
view.setUint8(offset, value);
|
|
2123
2239
|
}
|
|
@@ -2161,9 +2277,9 @@ function getHeaderArrayData({
|
|
|
2161
2277
|
const headerRecord = createRecordWriter(HEADER_SIZE - 4);
|
|
2162
2278
|
const headerArray = headerRecord.array;
|
|
2163
2279
|
const headerView = getDataView(headerArray);
|
|
2164
|
-
headerRecord.
|
|
2165
|
-
headerRecord.
|
|
2166
|
-
headerRecord.
|
|
2280
|
+
headerRecord.writeUint16(version);
|
|
2281
|
+
headerRecord.writeUint16(bitFlag);
|
|
2282
|
+
headerRecord.writeUint16(compressionMethod);
|
|
2167
2283
|
if (rawLastModDate === UNDEFINED_VALUE) {
|
|
2168
2284
|
const dateArray = new Uint32Array(1);
|
|
2169
2285
|
const dateView = getDataView(dateArray);
|
|
@@ -2171,20 +2287,20 @@ function getHeaderArrayData({
|
|
|
2171
2287
|
setUint16(dateView, 2, ((((lastModDate.getFullYear() - 1980) << 4) | (lastModDate.getMonth() + 1)) << 5) | lastModDate.getDate());
|
|
2172
2288
|
rawLastModDate = dateArray[0];
|
|
2173
2289
|
}
|
|
2174
|
-
headerRecord.
|
|
2290
|
+
headerRecord.writeUint32(rawLastModDate);
|
|
2175
2291
|
headerRecord.skip(4);
|
|
2176
2292
|
if (zip64CompressedSize || compressedSize !== UNDEFINED_VALUE) {
|
|
2177
|
-
headerRecord.
|
|
2293
|
+
headerRecord.writeUint32(zip64CompressedSize ? MAX_32_BITS : compressedSize);
|
|
2178
2294
|
} else {
|
|
2179
2295
|
headerRecord.skip(4);
|
|
2180
2296
|
}
|
|
2181
2297
|
if (zip64UncompressedSize || uncompressedSize !== UNDEFINED_VALUE) {
|
|
2182
|
-
headerRecord.
|
|
2298
|
+
headerRecord.writeUint32(zip64UncompressedSize ? MAX_32_BITS : uncompressedSize);
|
|
2183
2299
|
} else {
|
|
2184
2300
|
headerRecord.skip(4);
|
|
2185
2301
|
}
|
|
2186
|
-
headerRecord.
|
|
2187
|
-
headerRecord.
|
|
2302
|
+
headerRecord.writeUint16(getLength(rawFilename));
|
|
2303
|
+
headerRecord.writeUint16(extraFieldLength);
|
|
2188
2304
|
return {
|
|
2189
2305
|
headerArray,
|
|
2190
2306
|
headerView,
|