@zip.js/zip.js 2.7.69 → 2.7.71
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/deno.json +1 -1
- package/dist/z-worker-fflate.js +1 -1
- package/dist/z-worker-pako.js +1 -1
- package/dist/z-worker.js +1 -1
- package/dist/zip-fs-full.js +281 -121
- package/dist/zip-fs-full.min.js +1 -1
- package/dist/zip-fs.js +281 -121
- package/dist/zip-fs.min.js +1 -1
- package/dist/zip-full.js +280 -120
- package/dist/zip-full.min.js +1 -1
- package/dist/zip-no-worker-deflate.min.js +1 -1
- package/dist/zip-no-worker-inflate.min.js +1 -1
- package/dist/zip-no-worker.min.js +1 -1
- package/dist/zip.js +280 -120
- package/dist/zip.min.js +1 -1
- package/eslint.config.mjs +1 -1
- package/index-fflate.js +2 -0
- package/index.cjs +281 -121
- package/index.d.ts +26 -1
- package/index.js +2 -0
- package/index.min.js +1 -1
- package/lib/core/codec-pool.js +2 -0
- package/lib/core/constants.js +8 -1
- package/lib/core/io.js +6 -4
- package/lib/core/options.js +89 -0
- package/lib/core/streams/codec-stream.js +5 -0
- package/lib/core/streams/zip-crypto-stream.js +1 -1
- package/lib/core/streams/zip-entry-stream.js +7 -30
- package/lib/core/zip-entry.js +17 -6
- package/lib/core/zip-fs-core.js +1 -1
- package/lib/core/zip-reader.js +176 -46
- package/lib/core/zip-writer.js +69 -37
- package/lib/z-worker-inline.js +1 -1
- package/package.json +4 -4
package/lib/core/zip-reader.js
CHANGED
|
@@ -36,6 +36,10 @@ import {
|
|
|
36
36
|
COMPRESSION_METHOD_STORE,
|
|
37
37
|
COMPRESSION_METHOD_AES,
|
|
38
38
|
SPLIT_ZIP_FILE_SIGNATURE,
|
|
39
|
+
DATA_DESCRIPTOR_RECORD_SIGNATURE,
|
|
40
|
+
DATA_DESCRIPTOR_RECORD_LENGTH,
|
|
41
|
+
DATA_DESCRIPTOR_RECORD_ZIP_64_LENGTH,
|
|
42
|
+
DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH,
|
|
39
43
|
LOCAL_FILE_HEADER_SIGNATURE,
|
|
40
44
|
CENTRAL_FILE_HEADER_SIGNATURE,
|
|
41
45
|
END_OF_CENTRAL_DIR_SIGNATURE,
|
|
@@ -76,6 +80,7 @@ import {
|
|
|
76
80
|
CODEC_INFLATE,
|
|
77
81
|
ERR_INVALID_SIGNATURE,
|
|
78
82
|
ERR_INVALID_PASSWORD,
|
|
83
|
+
ERR_INVALID_UNCOMPRESSED_SIZE,
|
|
79
84
|
ERR_ABORT_CHECK_PASSWORD
|
|
80
85
|
} from "./codec-pool.js";
|
|
81
86
|
import {
|
|
@@ -92,8 +97,8 @@ import {
|
|
|
92
97
|
PROPERTY_NAME_FILENAME,
|
|
93
98
|
PROPERTY_NAME_RAW_COMMENT,
|
|
94
99
|
PROPERTY_NAME_COMMENT,
|
|
95
|
-
|
|
96
|
-
|
|
100
|
+
PROPERTY_NAME_UNCOMPRESSED_SIZE,
|
|
101
|
+
PROPERTY_NAME_COMPRESSED_SIZE,
|
|
97
102
|
PROPERTY_NAME_OFFSET,
|
|
98
103
|
PROPERTY_NAME_DISK_NUMBER_START,
|
|
99
104
|
PROPERTY_NAME_LAST_MODIFICATION_DATE,
|
|
@@ -104,6 +109,25 @@ import {
|
|
|
104
109
|
PROPERTY_NAME_RAW_CREATION_DATE,
|
|
105
110
|
Entry
|
|
106
111
|
} from "./zip-entry.js";
|
|
112
|
+
import {
|
|
113
|
+
OPTION_FILENAME_ENCODING,
|
|
114
|
+
OPTION_COMMENT_ENCODING,
|
|
115
|
+
OPTION_DECODE_TEXT,
|
|
116
|
+
OPTION_EXTRACT_PREPENDED_DATA,
|
|
117
|
+
OPTION_EXTRACT_APPENDED_DATA,
|
|
118
|
+
OPTION_PASSWORD,
|
|
119
|
+
OPTION_RAW_PASSWORD,
|
|
120
|
+
OPTION_PASS_THROUGH,
|
|
121
|
+
OPTION_SIGNAL,
|
|
122
|
+
OPTION_CHECK_PASSWORD_ONLY,
|
|
123
|
+
OPTION_CHECK_OVERLAPPING_ENTRY_ONLY,
|
|
124
|
+
OPTION_CHECK_OVERLAPPING_ENTRY,
|
|
125
|
+
OPTION_CHECK_SIGNATURE,
|
|
126
|
+
OPTION_USE_WEB_WORKERS,
|
|
127
|
+
OPTION_USE_COMPRESSION_STREAM,
|
|
128
|
+
OPTION_TRANSFER_STREAMS,
|
|
129
|
+
OPTION_PREVENT_CLOSE
|
|
130
|
+
} from "./options.js";
|
|
107
131
|
|
|
108
132
|
const ERR_BAD_FORMAT = "File format is not recognized";
|
|
109
133
|
const ERR_EOCDR_NOT_FOUND = "End of central directory not found";
|
|
@@ -115,11 +139,12 @@ const ERR_ENCRYPTED = "File contains encrypted entry";
|
|
|
115
139
|
const ERR_UNSUPPORTED_ENCRYPTION = "Encryption method not supported";
|
|
116
140
|
const ERR_UNSUPPORTED_COMPRESSION = "Compression method not supported";
|
|
117
141
|
const ERR_SPLIT_ZIP_FILE = "Split zip file";
|
|
142
|
+
const ERR_OVERLAPPING_ENTRY = "Overlapping entry found";
|
|
118
143
|
const CHARSET_UTF8 = "utf-8";
|
|
119
144
|
const CHARSET_CP437 = "cp437";
|
|
120
145
|
const ZIP64_PROPERTIES = [
|
|
121
|
-
[
|
|
122
|
-
[
|
|
146
|
+
[PROPERTY_NAME_UNCOMPRESSED_SIZE, MAX_32_BITS],
|
|
147
|
+
[PROPERTY_NAME_COMPRESSED_SIZE, MAX_32_BITS],
|
|
123
148
|
[PROPERTY_NAME_OFFSET, MAX_32_BITS],
|
|
124
149
|
[PROPERTY_NAME_DISK_NUMBER_START, MAX_16_BITS]
|
|
125
150
|
];
|
|
@@ -140,7 +165,8 @@ class ZipReader {
|
|
|
140
165
|
Object.assign(this, {
|
|
141
166
|
reader: new GenericReader(reader),
|
|
142
167
|
options,
|
|
143
|
-
config: getConfiguration()
|
|
168
|
+
config: getConfiguration(),
|
|
169
|
+
readRanges: []
|
|
144
170
|
});
|
|
145
171
|
}
|
|
146
172
|
|
|
@@ -190,7 +216,9 @@ class ZipReader {
|
|
|
190
216
|
if (getUint32(endOfDirectoryView, 0) != ZIP64_END_OF_CENTRAL_DIR_SIGNATURE && directoryDataOffset != expectedDirectoryDataOffset) {
|
|
191
217
|
const originalDirectoryDataOffset = directoryDataOffset;
|
|
192
218
|
directoryDataOffset = expectedDirectoryDataOffset;
|
|
193
|
-
|
|
219
|
+
if (directoryDataOffset > originalDirectoryDataOffset) {
|
|
220
|
+
prependedDataLength = directoryDataOffset - originalDirectoryDataOffset;
|
|
221
|
+
}
|
|
194
222
|
endOfDirectoryArray = await readUint8Array(reader, directoryDataOffset, ZIP64_END_OF_CENTRAL_DIR_LENGTH, -1);
|
|
195
223
|
endOfDirectoryView = getDataView(endOfDirectoryArray);
|
|
196
224
|
}
|
|
@@ -230,7 +258,9 @@ class ZipReader {
|
|
|
230
258
|
if (getUint32(directoryView, offset) != CENTRAL_FILE_HEADER_SIGNATURE && directoryDataOffset != expectedDirectoryDataOffset) {
|
|
231
259
|
const originalDirectoryDataOffset = directoryDataOffset;
|
|
232
260
|
directoryDataOffset = expectedDirectoryDataOffset;
|
|
233
|
-
|
|
261
|
+
if (directoryDataOffset > originalDirectoryDataOffset) {
|
|
262
|
+
prependedDataLength += directoryDataOffset - originalDirectoryDataOffset;
|
|
263
|
+
}
|
|
234
264
|
directoryArray = await readUint8Array(reader, directoryDataOffset, directoryDataLength, diskNumber);
|
|
235
265
|
directoryView = getDataView(directoryArray);
|
|
236
266
|
}
|
|
@@ -244,8 +274,8 @@ class ZipReader {
|
|
|
244
274
|
if (directoryDataOffset < 0 || directoryDataOffset >= reader.size) {
|
|
245
275
|
throw new Error(ERR_BAD_FORMAT);
|
|
246
276
|
}
|
|
247
|
-
const filenameEncoding = getOptionValue(zipReader, options,
|
|
248
|
-
const commentEncoding = getOptionValue(zipReader, options,
|
|
277
|
+
const filenameEncoding = getOptionValue(zipReader, options, OPTION_FILENAME_ENCODING);
|
|
278
|
+
const commentEncoding = getOptionValue(zipReader, options, OPTION_COMMENT_ENCODING);
|
|
249
279
|
for (let indexFile = 0; indexFile < filesLength; indexFile++) {
|
|
250
280
|
const fileEntry = new ZipEntry(reader, config, zipReader.options);
|
|
251
281
|
if (getUint32(directoryView, offset) != CENTRAL_FILE_HEADER_SIGNATURE) {
|
|
@@ -291,7 +321,7 @@ class ZipReader {
|
|
|
291
321
|
});
|
|
292
322
|
fileEntry.internalFileAttribute = fileEntry.internalFileAttributes;
|
|
293
323
|
fileEntry.externalFileAttribute = fileEntry.externalFileAttributes;
|
|
294
|
-
const decode = getOptionValue(zipReader, options,
|
|
324
|
+
const decode = getOptionValue(zipReader, options, OPTION_DECODE_TEXT) || decodeText;
|
|
295
325
|
const rawFilenameEncoding = filenameUTF8 ? CHARSET_UTF8 : filenameEncoding || CHARSET_CP437;
|
|
296
326
|
const rawCommentEncoding = commentUTF8 ? CHARSET_UTF8 : commentEncoding || CHARSET_CP437;
|
|
297
327
|
let filename = decode(rawFilename, rawFilenameEncoding);
|
|
@@ -312,12 +342,12 @@ class ZipReader {
|
|
|
312
342
|
readCommonFooter(fileEntry, fileEntry, directoryView, offset + 6);
|
|
313
343
|
fileEntry.zipCrypto = fileEntry.encrypted && !fileEntry.extraFieldAES;
|
|
314
344
|
const entry = new Entry(fileEntry);
|
|
315
|
-
entry.getData = (writer, options) => fileEntry.getData(writer, entry, options);
|
|
345
|
+
entry.getData = (writer, options) => fileEntry.getData(writer, entry, zipReader.readRanges, options);
|
|
316
346
|
entry.arrayBuffer = async options => {
|
|
317
347
|
const writer = new TransformStream();
|
|
318
348
|
const [arrayBuffer] = await Promise.all([
|
|
319
349
|
new Response(writer.readable).arrayBuffer(),
|
|
320
|
-
fileEntry.getData(writer, entry, options)]);
|
|
350
|
+
fileEntry.getData(writer, entry, zipReader.readRanges, options)]);
|
|
321
351
|
return arrayBuffer;
|
|
322
352
|
};
|
|
323
353
|
offset = endOffset;
|
|
@@ -332,8 +362,8 @@ class ZipReader {
|
|
|
332
362
|
}
|
|
333
363
|
yield entry;
|
|
334
364
|
}
|
|
335
|
-
const extractPrependedData = getOptionValue(zipReader, options,
|
|
336
|
-
const extractAppendedData = getOptionValue(zipReader, options,
|
|
365
|
+
const extractPrependedData = getOptionValue(zipReader, options, OPTION_EXTRACT_PREPENDED_DATA);
|
|
366
|
+
const extractAppendedData = getOptionValue(zipReader, options, OPTION_EXTRACT_APPENDED_DATA);
|
|
337
367
|
if (extractPrependedData) {
|
|
338
368
|
zipReader.prependedData = startOffset > 0 ? await readUint8Array(reader, 0, startOffset) : new Uint8Array();
|
|
339
369
|
}
|
|
@@ -398,7 +428,9 @@ export {
|
|
|
398
428
|
ERR_UNSUPPORTED_COMPRESSION,
|
|
399
429
|
ERR_INVALID_SIGNATURE,
|
|
400
430
|
ERR_INVALID_PASSWORD,
|
|
401
|
-
|
|
431
|
+
ERR_INVALID_UNCOMPRESSED_SIZE,
|
|
432
|
+
ERR_SPLIT_ZIP_FILE,
|
|
433
|
+
ERR_OVERLAPPING_ENTRY
|
|
402
434
|
};
|
|
403
435
|
|
|
404
436
|
class ZipEntry {
|
|
@@ -411,13 +443,14 @@ class ZipEntry {
|
|
|
411
443
|
});
|
|
412
444
|
}
|
|
413
445
|
|
|
414
|
-
async getData(writer, fileEntry, options = {}) {
|
|
446
|
+
async getData(writer, fileEntry, readRanges, options = {}) {
|
|
415
447
|
const zipEntry = this;
|
|
416
448
|
const {
|
|
417
449
|
reader,
|
|
418
450
|
offset,
|
|
419
451
|
diskNumberStart,
|
|
420
452
|
extraFieldAES,
|
|
453
|
+
extraFieldZip64,
|
|
421
454
|
compressionMethod,
|
|
422
455
|
config,
|
|
423
456
|
bitFlag,
|
|
@@ -426,13 +459,15 @@ class ZipEntry {
|
|
|
426
459
|
uncompressedSize,
|
|
427
460
|
compressedSize
|
|
428
461
|
} = zipEntry;
|
|
462
|
+
const {
|
|
463
|
+
dataDescriptor
|
|
464
|
+
} = bitFlag;
|
|
429
465
|
const localDirectory = fileEntry.localDirectory = {};
|
|
430
|
-
const
|
|
431
|
-
const dataArray = await readUint8Array(reader, offset, dataArraySize + 4, diskNumberStart);
|
|
466
|
+
const dataArray = await readUint8Array(reader, offset, HEADER_SIZE, diskNumberStart);
|
|
432
467
|
const dataView = getDataView(dataArray);
|
|
433
|
-
let password = getOptionValue(zipEntry, options,
|
|
434
|
-
let rawPassword = getOptionValue(zipEntry, options,
|
|
435
|
-
const passThrough = getOptionValue(zipEntry, options,
|
|
468
|
+
let password = getOptionValue(zipEntry, options, OPTION_PASSWORD);
|
|
469
|
+
let rawPassword = getOptionValue(zipEntry, options, OPTION_RAW_PASSWORD);
|
|
470
|
+
const passThrough = getOptionValue(zipEntry, options, OPTION_PASS_THROUGH);
|
|
436
471
|
password = password && password.length && password;
|
|
437
472
|
rawPassword = rawPassword && rawPassword.length && rawPassword;
|
|
438
473
|
if (extraFieldAES) {
|
|
@@ -447,14 +482,17 @@ class ZipEntry {
|
|
|
447
482
|
throw new Error(ERR_LOCAL_FILE_HEADER_NOT_FOUND);
|
|
448
483
|
}
|
|
449
484
|
readCommonHeader(localDirectory, dataView, 4);
|
|
450
|
-
|
|
451
|
-
|
|
485
|
+
const {
|
|
486
|
+
extraFieldLength,
|
|
487
|
+
filenameLength,
|
|
488
|
+
lastAccessDate,
|
|
489
|
+
creationDate
|
|
490
|
+
} = localDirectory;
|
|
491
|
+
localDirectory.rawExtraField = extraFieldLength ?
|
|
492
|
+
await readUint8Array(reader, offset + HEADER_SIZE + filenameLength, extraFieldLength, diskNumberStart) :
|
|
452
493
|
new Uint8Array();
|
|
453
494
|
readCommonFooter(zipEntry, localDirectory, dataView, 4, true);
|
|
454
|
-
Object.assign(fileEntry, {
|
|
455
|
-
lastAccessDate: localDirectory.lastAccessDate,
|
|
456
|
-
creationDate: localDirectory.creationDate
|
|
457
|
-
});
|
|
495
|
+
Object.assign(fileEntry, { lastAccessDate, creationDate });
|
|
458
496
|
const encrypted = zipEntry.encrypted && localDirectory.encrypted && !passThrough;
|
|
459
497
|
const zipCrypto = encrypted && !extraFieldAES;
|
|
460
498
|
if (!passThrough) {
|
|
@@ -467,7 +505,7 @@ class ZipEntry {
|
|
|
467
505
|
throw new Error(ERR_ENCRYPTED);
|
|
468
506
|
}
|
|
469
507
|
}
|
|
470
|
-
const dataOffset = offset +
|
|
508
|
+
const dataOffset = offset + HEADER_SIZE + filenameLength + extraFieldLength;
|
|
471
509
|
const size = compressedSize;
|
|
472
510
|
const readable = reader.readable;
|
|
473
511
|
Object.assign(readable, {
|
|
@@ -475,14 +513,13 @@ class ZipEntry {
|
|
|
475
513
|
offset: dataOffset,
|
|
476
514
|
size
|
|
477
515
|
});
|
|
478
|
-
const signal = getOptionValue(zipEntry, options,
|
|
479
|
-
const checkPasswordOnly = getOptionValue(zipEntry, options,
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
const { writable } = writer;
|
|
516
|
+
const signal = getOptionValue(zipEntry, options, OPTION_SIGNAL);
|
|
517
|
+
const checkPasswordOnly = getOptionValue(zipEntry, options, OPTION_CHECK_PASSWORD_ONLY);
|
|
518
|
+
let checkOverlappingEntry = getOptionValue(zipEntry, options, OPTION_CHECK_OVERLAPPING_ENTRY);
|
|
519
|
+
const checkOverlappingEntryOnly = getOptionValue(zipEntry, options, OPTION_CHECK_OVERLAPPING_ENTRY_ONLY);
|
|
520
|
+
if (checkOverlappingEntryOnly) {
|
|
521
|
+
checkOverlappingEntry = true;
|
|
522
|
+
}
|
|
486
523
|
const { onstart, onprogress, onend } = options;
|
|
487
524
|
const workerOptions = {
|
|
488
525
|
options: {
|
|
@@ -491,22 +528,50 @@ class ZipEntry {
|
|
|
491
528
|
rawPassword,
|
|
492
529
|
zipCrypto,
|
|
493
530
|
encryptionStrength: extraFieldAES && extraFieldAES.strength,
|
|
494
|
-
signed: getOptionValue(zipEntry, options,
|
|
495
|
-
passwordVerification: zipCrypto && (
|
|
531
|
+
signed: getOptionValue(zipEntry, options, OPTION_CHECK_SIGNATURE) && !passThrough,
|
|
532
|
+
passwordVerification: zipCrypto && (dataDescriptor ? ((rawLastModDate >>> 8) & 0xFF) : ((signature >>> 24) & 0xFF)),
|
|
533
|
+
outputSize: uncompressedSize,
|
|
496
534
|
signature,
|
|
497
535
|
compressed: compressionMethod != 0 && !passThrough,
|
|
498
536
|
encrypted: zipEntry.encrypted && !passThrough,
|
|
499
|
-
useWebWorkers: getOptionValue(zipEntry, options,
|
|
500
|
-
useCompressionStream: getOptionValue(zipEntry, options,
|
|
501
|
-
transferStreams: getOptionValue(zipEntry, options,
|
|
537
|
+
useWebWorkers: getOptionValue(zipEntry, options, OPTION_USE_WEB_WORKERS),
|
|
538
|
+
useCompressionStream: getOptionValue(zipEntry, options, OPTION_USE_COMPRESSION_STREAM),
|
|
539
|
+
transferStreams: getOptionValue(zipEntry, options, OPTION_TRANSFER_STREAMS),
|
|
502
540
|
checkPasswordOnly
|
|
503
541
|
},
|
|
504
542
|
config,
|
|
505
543
|
streamOptions: { signal, size, onstart, onprogress, onend }
|
|
506
544
|
};
|
|
545
|
+
if (checkOverlappingEntry) {
|
|
546
|
+
await detectOverlappingEntry({
|
|
547
|
+
reader,
|
|
548
|
+
fileEntry,
|
|
549
|
+
offset,
|
|
550
|
+
diskNumberStart,
|
|
551
|
+
signature,
|
|
552
|
+
compressedSize,
|
|
553
|
+
uncompressedSize,
|
|
554
|
+
dataOffset,
|
|
555
|
+
dataDescriptor: dataDescriptor || localDirectory.bitFlag.dataDescriptor,
|
|
556
|
+
extraFieldZip64: extraFieldZip64 || localDirectory.extraFieldZip64,
|
|
557
|
+
readRanges
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
let writable;
|
|
507
561
|
try {
|
|
508
|
-
|
|
509
|
-
|
|
562
|
+
if (!checkOverlappingEntryOnly) {
|
|
563
|
+
if (checkPasswordOnly) {
|
|
564
|
+
writer = new WritableStream();
|
|
565
|
+
}
|
|
566
|
+
writer = new GenericWriter(writer);
|
|
567
|
+
await initStream(writer, passThrough ? compressedSize : uncompressedSize);
|
|
568
|
+
({ writable } = writer);
|
|
569
|
+
const { outputSize } = await runWorker({ readable, writable }, workerOptions);
|
|
570
|
+
writer.size += outputSize;
|
|
571
|
+
if (outputSize != (passThrough ? compressedSize : uncompressedSize)) {
|
|
572
|
+
throw new Error(ERR_INVALID_UNCOMPRESSED_SIZE);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
510
575
|
} catch (error) {
|
|
511
576
|
if (error.outputSize !== UNDEFINED_VALUE) {
|
|
512
577
|
writer.size += error.outputSize;
|
|
@@ -515,12 +580,12 @@ class ZipEntry {
|
|
|
515
580
|
throw error;
|
|
516
581
|
}
|
|
517
582
|
} finally {
|
|
518
|
-
const preventClose = getOptionValue(zipEntry, options,
|
|
519
|
-
if (!preventClose && !writable.locked) {
|
|
583
|
+
const preventClose = getOptionValue(zipEntry, options, OPTION_PREVENT_CLOSE);
|
|
584
|
+
if (!preventClose && writable && !writable.locked) {
|
|
520
585
|
await writable.getWriter().close();
|
|
521
586
|
}
|
|
522
587
|
}
|
|
523
|
-
return checkPasswordOnly ? UNDEFINED_VALUE : writer.getData ? writer.getData() : writable;
|
|
588
|
+
return checkPasswordOnly || checkOverlappingEntryOnly ? UNDEFINED_VALUE : writer.getData ? writer.getData() : writable;
|
|
524
589
|
}
|
|
525
590
|
}
|
|
526
591
|
|
|
@@ -728,6 +793,71 @@ function readExtraFieldExtendedTimestamp(extraFieldExtendedTimestamp, directory,
|
|
|
728
793
|
});
|
|
729
794
|
}
|
|
730
795
|
|
|
796
|
+
async function detectOverlappingEntry({
|
|
797
|
+
reader,
|
|
798
|
+
fileEntry,
|
|
799
|
+
offset,
|
|
800
|
+
diskNumberStart,
|
|
801
|
+
signature,
|
|
802
|
+
compressedSize,
|
|
803
|
+
uncompressedSize,
|
|
804
|
+
dataOffset,
|
|
805
|
+
dataDescriptor,
|
|
806
|
+
extraFieldZip64,
|
|
807
|
+
readRanges
|
|
808
|
+
}) {
|
|
809
|
+
let diskOffset = 0;
|
|
810
|
+
if (diskNumberStart) {
|
|
811
|
+
for (let indexReader = 0; indexReader < diskNumberStart; indexReader++) {
|
|
812
|
+
const diskReader = reader.readers[indexReader];
|
|
813
|
+
diskOffset += diskReader.size;
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
let dataDescriptorLength = 0;
|
|
817
|
+
if (dataDescriptor) {
|
|
818
|
+
if (extraFieldZip64) {
|
|
819
|
+
dataDescriptorLength = DATA_DESCRIPTOR_RECORD_ZIP_64_LENGTH;
|
|
820
|
+
} else {
|
|
821
|
+
dataDescriptorLength = DATA_DESCRIPTOR_RECORD_LENGTH;
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
if (dataDescriptorLength) {
|
|
825
|
+
const dataDescriptorArray = await readUint8Array(reader, dataOffset + compressedSize, dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH, diskNumberStart);
|
|
826
|
+
const dataDescriptorSignature = getUint32(getDataView(dataDescriptorArray), 0) == DATA_DESCRIPTOR_RECORD_SIGNATURE;
|
|
827
|
+
if (dataDescriptorSignature) {
|
|
828
|
+
const readSignature = getUint32(getDataView(dataDescriptorArray), 4);
|
|
829
|
+
let readCompressedSize;
|
|
830
|
+
let readUncompressedSize;
|
|
831
|
+
if (extraFieldZip64) {
|
|
832
|
+
readCompressedSize = getBigUint64(getDataView(dataDescriptorArray), 8);
|
|
833
|
+
readUncompressedSize = getBigUint64(getDataView(dataDescriptorArray), 16);
|
|
834
|
+
} else {
|
|
835
|
+
readCompressedSize = getUint32(getDataView(dataDescriptorArray), 8);
|
|
836
|
+
readUncompressedSize = getUint32(getDataView(dataDescriptorArray), 12);
|
|
837
|
+
}
|
|
838
|
+
const matchSignature = (fileEntry.encrypted && !fileEntry.zipCrypto) || readSignature == signature;
|
|
839
|
+
if (matchSignature &&
|
|
840
|
+
readCompressedSize == compressedSize &&
|
|
841
|
+
readUncompressedSize == uncompressedSize) {
|
|
842
|
+
dataDescriptorLength += DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH;
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
const range = {
|
|
847
|
+
start: diskOffset + offset,
|
|
848
|
+
end: diskOffset + dataOffset + compressedSize + dataDescriptorLength,
|
|
849
|
+
fileEntry
|
|
850
|
+
};
|
|
851
|
+
for (const otherRange of readRanges) {
|
|
852
|
+
if (otherRange.fileEntry != fileEntry && range.start >= otherRange.start && range.start < otherRange.end) {
|
|
853
|
+
const error = new Error(ERR_OVERLAPPING_ENTRY);
|
|
854
|
+
error.overlappingEntry = otherRange.fileEntry;
|
|
855
|
+
throw error;
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
readRanges.push(range);
|
|
859
|
+
}
|
|
860
|
+
|
|
731
861
|
async function seekSignature(reader, signature, startOffset, minimumBytes, maximumLength) {
|
|
732
862
|
const signatureArray = new Uint8Array(4);
|
|
733
863
|
const signatureView = getDataView(signatureArray);
|
package/lib/core/zip-writer.js
CHANGED
|
@@ -43,6 +43,9 @@ import {
|
|
|
43
43
|
END_OF_CENTRAL_DIR_SIGNATURE,
|
|
44
44
|
ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIGNATURE,
|
|
45
45
|
ZIP64_END_OF_CENTRAL_DIR_SIGNATURE,
|
|
46
|
+
DATA_DESCRIPTOR_RECORD_LENGTH,
|
|
47
|
+
DATA_DESCRIPTOR_RECORD_ZIP_64_LENGTH,
|
|
48
|
+
DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH,
|
|
46
49
|
EXTRAFIELD_TYPE_AES,
|
|
47
50
|
EXTRAFIELD_TYPE_ZIP64,
|
|
48
51
|
EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP,
|
|
@@ -105,8 +108,34 @@ import {
|
|
|
105
108
|
PROPERTY_NAME_ZIPCRYPTO,
|
|
106
109
|
PROPERTY_NAME_DIRECTORY,
|
|
107
110
|
PROPERTY_NAME_EXECUTABLE,
|
|
111
|
+
PROPERTY_NAME_COMPRESSION_METHOD,
|
|
112
|
+
PROPERTY_NAME_SIGNATURE,
|
|
113
|
+
PROPERTY_NAME_COMMENT,
|
|
114
|
+
PROPERTY_NAME_UNCOMPRESSED_SIZE,
|
|
115
|
+
PROPERTY_NAME_EXTRA_FIELD,
|
|
108
116
|
Entry
|
|
109
117
|
} from "./zip-entry.js";
|
|
118
|
+
import {
|
|
119
|
+
OPTION_PASSWORD,
|
|
120
|
+
OPTION_RAW_PASSWORD,
|
|
121
|
+
OPTION_PASS_THROUGH,
|
|
122
|
+
OPTION_SIGNAL,
|
|
123
|
+
OPTION_USE_WEB_WORKERS,
|
|
124
|
+
OPTION_USE_COMPRESSION_STREAM,
|
|
125
|
+
OPTION_PREVENT_CLOSE,
|
|
126
|
+
OPTION_ENCRYPTION_STRENGTH,
|
|
127
|
+
OPTION_EXTENDED_TIMESTAMP,
|
|
128
|
+
OPTION_KEEP_ORDER,
|
|
129
|
+
OPTION_LEVEL,
|
|
130
|
+
OPTION_BUFFERED_WRITE,
|
|
131
|
+
OPTION_DATA_DESCRIPTOR_SIGNATURE,
|
|
132
|
+
OPTION_USE_UNICODE_FILE_NAMES,
|
|
133
|
+
OPTION_DATA_DESCRIPTOR,
|
|
134
|
+
OPTION_SUPPORT_ZIP64_SPLIT_FILE,
|
|
135
|
+
OPTION_ENCODE_TEXT,
|
|
136
|
+
OPTION_OFFSET,
|
|
137
|
+
OPTION_USDZ
|
|
138
|
+
} from "./options.js";
|
|
110
139
|
import {
|
|
111
140
|
ZipReader
|
|
112
141
|
} from "./zip-reader.js";
|
|
@@ -142,7 +171,7 @@ class ZipWriter {
|
|
|
142
171
|
config: getConfiguration(),
|
|
143
172
|
files: new Map(),
|
|
144
173
|
filenames: new Set(),
|
|
145
|
-
offset: options
|
|
174
|
+
offset: options[OPTION_OFFSET] === UNDEFINED_VALUE ? writer.size || writer.writable.size || 0 : options[OPTION_OFFSET],
|
|
146
175
|
pendingEntriesSize: 0,
|
|
147
176
|
pendingAddFileCalls: new Set(),
|
|
148
177
|
bufferedWrites: 0
|
|
@@ -181,7 +210,7 @@ class ZipWriter {
|
|
|
181
210
|
rawExtraFieldAES,
|
|
182
211
|
rawExtraFieldExtendedTimestamp,
|
|
183
212
|
rawExtraFieldNTFS,
|
|
184
|
-
rawExtraField
|
|
213
|
+
rawExtraField
|
|
185
214
|
} = entry;
|
|
186
215
|
const { level, languageEncodingFlag, dataDescriptor } = bitFlag;
|
|
187
216
|
rawExtraFieldZip64 = rawExtraFieldZip64 || new Uint8Array();
|
|
@@ -285,7 +314,7 @@ class ZipWriter {
|
|
|
285
314
|
await Promise.allSettled(Array.from(pendingAddFileCalls));
|
|
286
315
|
}
|
|
287
316
|
await closeFile(this, comment, options);
|
|
288
|
-
const preventClose = getOptionValue(zipWriter, options,
|
|
317
|
+
const preventClose = getOptionValue(zipWriter, options, OPTION_PREVENT_CLOSE);
|
|
289
318
|
if (!preventClose) {
|
|
290
319
|
await writable.getWriter().close();
|
|
291
320
|
}
|
|
@@ -348,8 +377,8 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
348
377
|
if (externalFileAttributes === 0) {
|
|
349
378
|
externalFileAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTE, 0);
|
|
350
379
|
}
|
|
351
|
-
if (!options
|
|
352
|
-
options
|
|
380
|
+
if (!options[PROPERTY_NAME_DIRECTORY] && name.endsWith(DIRECTORY_SIGNATURE)) {
|
|
381
|
+
options[PROPERTY_NAME_DIRECTORY] = true;
|
|
353
382
|
}
|
|
354
383
|
const directory = getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY);
|
|
355
384
|
if (directory) {
|
|
@@ -369,7 +398,7 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
369
398
|
externalFileAttributes = FILE_ATTR_UNIX_DEFAULT_MASK << 16;
|
|
370
399
|
}
|
|
371
400
|
}
|
|
372
|
-
const encode = getOptionValue(zipWriter, options,
|
|
401
|
+
const encode = getOptionValue(zipWriter, options, OPTION_ENCODE_TEXT, encodeText);
|
|
373
402
|
let rawFilename = encode(name);
|
|
374
403
|
if (rawFilename === UNDEFINED_VALUE) {
|
|
375
404
|
rawFilename = encodeText(name);
|
|
@@ -377,7 +406,7 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
377
406
|
if (getLength(rawFilename) > MAX_16_BITS) {
|
|
378
407
|
throw new Error(ERR_INVALID_ENTRY_NAME);
|
|
379
408
|
}
|
|
380
|
-
const comment = options
|
|
409
|
+
const comment = options[PROPERTY_NAME_COMMENT] || "";
|
|
381
410
|
let rawComment = encode(comment);
|
|
382
411
|
if (rawComment === UNDEFINED_VALUE) {
|
|
383
412
|
rawComment = encodeText(comment);
|
|
@@ -396,25 +425,25 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
396
425
|
if (internalFileAttributes === 0) {
|
|
397
426
|
internalFileAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTE, 0);
|
|
398
427
|
}
|
|
399
|
-
const passThrough = getOptionValue(zipWriter, options,
|
|
428
|
+
const passThrough = getOptionValue(zipWriter, options, OPTION_PASS_THROUGH);
|
|
400
429
|
let password, rawPassword;
|
|
401
430
|
if (!passThrough) {
|
|
402
|
-
password = getOptionValue(zipWriter, options,
|
|
403
|
-
rawPassword = getOptionValue(zipWriter, options,
|
|
431
|
+
password = getOptionValue(zipWriter, options, OPTION_PASSWORD);
|
|
432
|
+
rawPassword = getOptionValue(zipWriter, options, OPTION_RAW_PASSWORD);
|
|
404
433
|
}
|
|
405
|
-
const encryptionStrength = getOptionValue(zipWriter, options,
|
|
434
|
+
const encryptionStrength = getOptionValue(zipWriter, options, OPTION_ENCRYPTION_STRENGTH, 3);
|
|
406
435
|
const zipCrypto = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIPCRYPTO);
|
|
407
|
-
const extendedTimestamp = getOptionValue(zipWriter, options,
|
|
408
|
-
const keepOrder = getOptionValue(zipWriter, options,
|
|
409
|
-
const level = getOptionValue(zipWriter, options,
|
|
410
|
-
const useWebWorkers = getOptionValue(zipWriter, options,
|
|
411
|
-
const bufferedWrite = getOptionValue(zipWriter, options,
|
|
412
|
-
const dataDescriptorSignature = getOptionValue(zipWriter, options,
|
|
413
|
-
const signal = getOptionValue(zipWriter, options,
|
|
414
|
-
const useUnicodeFileNames = getOptionValue(zipWriter, options,
|
|
415
|
-
const useCompressionStream = getOptionValue(zipWriter, options,
|
|
416
|
-
const compressionMethod = getOptionValue(zipWriter, options,
|
|
417
|
-
let dataDescriptor = getOptionValue(zipWriter, options,
|
|
436
|
+
const extendedTimestamp = getOptionValue(zipWriter, options, OPTION_EXTENDED_TIMESTAMP, true);
|
|
437
|
+
const keepOrder = getOptionValue(zipWriter, options, OPTION_KEEP_ORDER, true);
|
|
438
|
+
const level = getOptionValue(zipWriter, options, OPTION_LEVEL);
|
|
439
|
+
const useWebWorkers = getOptionValue(zipWriter, options, OPTION_USE_WEB_WORKERS);
|
|
440
|
+
const bufferedWrite = getOptionValue(zipWriter, options, OPTION_BUFFERED_WRITE);
|
|
441
|
+
const dataDescriptorSignature = getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR_SIGNATURE, false);
|
|
442
|
+
const signal = getOptionValue(zipWriter, options, OPTION_SIGNAL);
|
|
443
|
+
const useUnicodeFileNames = getOptionValue(zipWriter, options, OPTION_USE_UNICODE_FILE_NAMES, true);
|
|
444
|
+
const useCompressionStream = getOptionValue(zipWriter, options, OPTION_USE_COMPRESSION_STREAM);
|
|
445
|
+
const compressionMethod = getOptionValue(zipWriter, options, PROPERTY_NAME_COMPRESSION_METHOD);
|
|
446
|
+
let dataDescriptor = getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR);
|
|
418
447
|
if (bufferedWrite && dataDescriptor === UNDEFINED_VALUE) {
|
|
419
448
|
dataDescriptor = false;
|
|
420
449
|
}
|
|
@@ -426,7 +455,7 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
426
455
|
throw new Error(ERR_INVALID_ENCRYPTION_STRENGTH);
|
|
427
456
|
}
|
|
428
457
|
let rawExtraField = new Uint8Array();
|
|
429
|
-
const
|
|
458
|
+
const extraField = options[PROPERTY_NAME_EXTRA_FIELD];
|
|
430
459
|
if (extraField) {
|
|
431
460
|
let extraFieldSize = 0;
|
|
432
461
|
let offset = 0;
|
|
@@ -449,7 +478,7 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
449
478
|
let maximumEntrySize = 0;
|
|
450
479
|
let uncompressedSize = 0;
|
|
451
480
|
if (passThrough) {
|
|
452
|
-
|
|
481
|
+
uncompressedSize = options[PROPERTY_NAME_UNCOMPRESSED_SIZE];
|
|
453
482
|
if (uncompressedSize === UNDEFINED_VALUE) {
|
|
454
483
|
throw new Error(ERR_UNDEFINED_UNCOMPRESSED_SIZE);
|
|
455
484
|
}
|
|
@@ -478,7 +507,7 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
478
507
|
const zip64UncompressedSize = zip64Enabled || uncompressedSize > MAX_32_BITS;
|
|
479
508
|
const zip64CompressedSize = zip64Enabled || maximumCompressedSize > MAX_32_BITS;
|
|
480
509
|
const zip64Offset = zip64Enabled || zipWriter.offset + zipWriter.pendingEntriesSize - diskOffset > MAX_32_BITS;
|
|
481
|
-
const supportZip64SplitFile = getOptionValue(zipWriter, options,
|
|
510
|
+
const supportZip64SplitFile = getOptionValue(zipWriter, options, OPTION_SUPPORT_ZIP64_SPLIT_FILE, true);
|
|
482
511
|
const zip64DiskNumberStart = (supportZip64SplitFile && zip64Enabled) || diskNumber + Math.ceil(zipWriter.pendingEntriesSize / maxSize) > MAX_16_BITS;
|
|
483
512
|
if (zip64Offset || zip64UncompressedSize || zip64CompressedSize || zip64DiskNumberStart) {
|
|
484
513
|
if (zip64 === false || !keepOrder) {
|
|
@@ -489,7 +518,6 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
489
518
|
}
|
|
490
519
|
zip64 = zip64 || false;
|
|
491
520
|
const encrypted = getOptionValue(zipWriter, options, PROPERTY_NAME_ENCRYPTED);
|
|
492
|
-
const { signature } = options;
|
|
493
521
|
options = Object.assign({}, options, {
|
|
494
522
|
rawFilename,
|
|
495
523
|
rawComment,
|
|
@@ -525,17 +553,17 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
525
553
|
useCompressionStream,
|
|
526
554
|
passThrough,
|
|
527
555
|
encrypted: Boolean((password && getLength(password)) || (rawPassword && getLength(rawPassword))) || (passThrough && encrypted),
|
|
528
|
-
signature,
|
|
556
|
+
signature: options[PROPERTY_NAME_SIGNATURE],
|
|
529
557
|
compressionMethod,
|
|
530
558
|
uncompressedSize,
|
|
531
559
|
offset: zipWriter.offset - diskOffset,
|
|
532
|
-
diskNumberStart: diskNumber
|
|
560
|
+
diskNumberStart: diskNumber
|
|
533
561
|
});
|
|
534
562
|
const headerInfo = getHeaderInfo(options);
|
|
535
563
|
const dataDescriptorInfo = getDataDescriptorInfo(options);
|
|
536
564
|
const metadataSize = getLength(headerInfo.localHeaderArray, dataDescriptorInfo.dataDescriptorArray);
|
|
537
565
|
maximumEntrySize = metadataSize + maximumCompressedSize;
|
|
538
|
-
if (zipWriter.options
|
|
566
|
+
if (zipWriter.options[OPTION_USDZ]) {
|
|
539
567
|
maximumEntrySize += maximumEntrySize + 64;
|
|
540
568
|
}
|
|
541
569
|
zipWriter.pendingEntriesSize += maximumEntrySize;
|
|
@@ -562,7 +590,7 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
|
562
590
|
const {
|
|
563
591
|
headerInfo
|
|
564
592
|
} = entryInfo;
|
|
565
|
-
const
|
|
593
|
+
const usdz = zipWriter.options[OPTION_USDZ];
|
|
566
594
|
const previousFileEntry = Array.from(files.values()).pop();
|
|
567
595
|
let fileEntry = {};
|
|
568
596
|
let bufferedWrite;
|
|
@@ -1008,7 +1036,7 @@ function getHeaderInfo(options) {
|
|
|
1008
1036
|
zip64UncompressedSize,
|
|
1009
1037
|
extraFieldLength
|
|
1010
1038
|
});
|
|
1011
|
-
let localHeaderOffset = HEADER_SIZE
|
|
1039
|
+
let localHeaderOffset = HEADER_SIZE;
|
|
1012
1040
|
const localHeaderArray = new Uint8Array(localHeaderOffset + getLength(rawFilename) + extraFieldLength);
|
|
1013
1041
|
const localHeaderView = getDataView(localHeaderArray);
|
|
1014
1042
|
setUint32(localHeaderView, 0, LOCAL_FILE_HEADER_SIGNATURE);
|
|
@@ -1079,11 +1107,15 @@ function getDataDescriptorInfo({
|
|
|
1079
1107
|
}) {
|
|
1080
1108
|
let dataDescriptorArray = new Uint8Array();
|
|
1081
1109
|
let dataDescriptorView, dataDescriptorOffset = 0;
|
|
1110
|
+
let dataDescriptorLength = zip64 ? DATA_DESCRIPTOR_RECORD_ZIP_64_LENGTH : DATA_DESCRIPTOR_RECORD_LENGTH;
|
|
1111
|
+
if (dataDescriptorSignature) {
|
|
1112
|
+
dataDescriptorLength += DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH;
|
|
1113
|
+
}
|
|
1082
1114
|
if (dataDescriptor) {
|
|
1083
|
-
dataDescriptorArray = new Uint8Array(
|
|
1115
|
+
dataDescriptorArray = new Uint8Array(dataDescriptorLength);
|
|
1084
1116
|
dataDescriptorView = getDataView(dataDescriptorArray);
|
|
1085
1117
|
if (dataDescriptorSignature) {
|
|
1086
|
-
dataDescriptorOffset =
|
|
1118
|
+
dataDescriptorOffset = DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH;
|
|
1087
1119
|
setUint32(dataDescriptorView, 0, DATA_DESCRIPTOR_RECORD_SIGNATURE);
|
|
1088
1120
|
}
|
|
1089
1121
|
}
|
|
@@ -1160,7 +1192,7 @@ function updateLocalHeader({
|
|
|
1160
1192
|
}
|
|
1161
1193
|
if (zip64) {
|
|
1162
1194
|
if (localExtraFieldZip64Length) {
|
|
1163
|
-
let localHeaderOffset = HEADER_SIZE +
|
|
1195
|
+
let localHeaderOffset = HEADER_SIZE + getLength(rawFilename) + 4;
|
|
1164
1196
|
if (zip64UncompressedSize) {
|
|
1165
1197
|
setBigUint64(localHeaderView, localHeaderOffset, BigInt(uncompressedSize));
|
|
1166
1198
|
localHeaderOffset += 8;
|
|
@@ -1290,7 +1322,7 @@ async function closeFile(zipWriter, comment, options) {
|
|
|
1290
1322
|
setUint32(headerView, HEADER_OFFSET_COMPRESSED_SIZE, compressedSize);
|
|
1291
1323
|
}
|
|
1292
1324
|
arraySet(directoryArray, headerArray, offset + 6);
|
|
1293
|
-
let directoryOffset = offset + HEADER_SIZE
|
|
1325
|
+
let directoryOffset = offset + HEADER_SIZE;
|
|
1294
1326
|
setUint16(directoryView, directoryOffset, extraFieldLength);
|
|
1295
1327
|
directoryOffset += 2;
|
|
1296
1328
|
setUint16(directoryView, directoryOffset, getLength(rawComment));
|
|
@@ -1364,7 +1396,7 @@ async function closeFile(zipWriter, comment, options) {
|
|
|
1364
1396
|
setUint32(endOfdirectoryView, 56, ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIGNATURE);
|
|
1365
1397
|
setBigUint64(endOfdirectoryView, 64, BigInt(directoryOffset) + BigInt(directoryDataLength));
|
|
1366
1398
|
setUint32(endOfdirectoryView, 72, lastDiskNumber + 1);
|
|
1367
|
-
const supportZip64SplitFile = getOptionValue(zipWriter, options,
|
|
1399
|
+
const supportZip64SplitFile = getOptionValue(zipWriter, options, OPTION_SUPPORT_ZIP64_SPLIT_FILE, true);
|
|
1368
1400
|
if (supportZip64SplitFile) {
|
|
1369
1401
|
lastDiskNumber = MAX_16_BITS;
|
|
1370
1402
|
diskNumber = MAX_16_BITS;
|
|
@@ -1464,7 +1496,7 @@ function getHeaderArrayData({
|
|
|
1464
1496
|
zip64UncompressedSize,
|
|
1465
1497
|
extraFieldLength
|
|
1466
1498
|
}) {
|
|
1467
|
-
const headerArray = new Uint8Array(HEADER_SIZE);
|
|
1499
|
+
const headerArray = new Uint8Array(HEADER_SIZE - 4);
|
|
1468
1500
|
const headerView = getDataView(headerArray);
|
|
1469
1501
|
setUint16(headerView, 0, version);
|
|
1470
1502
|
setUint16(headerView, 2, bitFlag);
|