@zip.js/zip.js 2.8.34 → 2.8.35
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 +13 -1
- package/deno.json +5 -2
- package/dist/README.md +3 -1
- package/dist/zip-core.js +472 -220
- package/dist/zip-core.min.js +1 -1
- package/dist/zip-fs-core.js +449 -220
- package/dist/zip-fs-core.min.js +1 -1
- package/dist/zip-fs-native.js +476 -226
- package/dist/zip-fs-native.min.js +1 -1
- package/dist/zip-fs.js +478 -228
- package/dist/zip-fs.min.js +1 -1
- package/dist/zip-legacy.js +474 -222
- package/dist/zip-legacy.min.js +1 -1
- package/dist/zip-native.js +475 -223
- 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 +477 -225
- package/dist/zip.min.js +1 -1
- package/index-native.cjs +476 -226
- package/index-native.min.js +1 -1
- package/index.cjs +478 -228
- package/index.d.cts +53 -0
- package/index.d.ts +53 -0
- package/index.min.js +1 -1
- package/lib/core/codec-pool.js +2 -2
- package/lib/core/codec-worker.js +6 -2
- package/lib/core/configuration.js +22 -1
- package/lib/core/io.js +209 -56
- package/lib/core/streams/aes-crypto-stream.js +1 -10
- package/lib/core/streams/codec-stream.js +36 -15
- package/lib/core/streams/zip-entry-stream.js +19 -28
- package/lib/core/util/array.js +48 -0
- package/lib/core/web-worker-base.js +3 -3
- package/lib/core/web-worker-inline-native.js +1 -1
- package/lib/core/web-worker-inline-wasm.js +1 -1
- package/lib/core/zip-fs.js +2 -3
- package/lib/core/zip-reader.js +37 -40
- package/lib/core/zip-writer.js +58 -51
- package/lib/core/zlib-streams-inline.js +1 -1
- package/lib/zip-core-base.js +5 -3
- package/lib/zip-fs-native.js +2 -2
- package/lib/zip-fs-wasm.js +2 -2
- package/lib/zip-legacy.js +2 -2
- package/lib/zip-module-native.js +2 -2
- package/lib/zip-module-wasm.js +3 -3
- package/lib/zip-native.js +2 -2
- package/lib/zip-wasm.js +2 -2
- package/package.json +3 -3
- package/worker-message-property-names.js +3 -0
- package/.github/workflows/publish.yml +0 -30
- package/reserved-property-names.js +0 -50
package/lib/core/zip-reader.js
CHANGED
|
@@ -85,10 +85,7 @@ import {
|
|
|
85
85
|
FILE_ATTR_UNIX_STICKY_MASK,
|
|
86
86
|
EMPTY_UINT8_ARRAY
|
|
87
87
|
} from "./constants.js";
|
|
88
|
-
import {
|
|
89
|
-
getConfiguration,
|
|
90
|
-
getChunkSize
|
|
91
|
-
} from "./configuration.js";
|
|
88
|
+
import { getConfiguration } from "./configuration.js";
|
|
92
89
|
import {
|
|
93
90
|
runWorker,
|
|
94
91
|
CODEC_INFLATE,
|
|
@@ -106,6 +103,7 @@ import {
|
|
|
106
103
|
GenericWriter
|
|
107
104
|
} from "./io.js";
|
|
108
105
|
import { decodeText } from "./util/decode-text.js";
|
|
106
|
+
import { getDataView } from "./util/array.js";
|
|
109
107
|
import { Crc32 } from "./streams/codecs/crc32.js";
|
|
110
108
|
import {
|
|
111
109
|
PROPERTY_NAME_RAW_FILENAME,
|
|
@@ -239,17 +237,21 @@ class ZipReader {
|
|
|
239
237
|
let prependedDataLength = 0;
|
|
240
238
|
let startOffset;
|
|
241
239
|
let zip64EndOfDirectory;
|
|
242
|
-
|
|
240
|
+
const requiresZip64 = directoryDataOffset == MAX_32_BITS || directoryDataLength == MAX_32_BITS || filesLength == MAX_16_BITS || diskNumber == MAX_16_BITS;
|
|
241
|
+
if (directoryDataOffset != MAX_32_BITS && diskNumber != MAX_16_BITS) {
|
|
242
|
+
directoryDataOffset += getDiskOffset(reader, diskNumber);
|
|
243
|
+
}
|
|
244
|
+
if (requiresZip64) {
|
|
243
245
|
const endOfDirectoryLocatorArray = endOfDirectoryInfo.offset >= ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH ?
|
|
244
246
|
await readUint8Array(reader, endOfDirectoryInfo.offset - ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH, ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH) :
|
|
245
247
|
EMPTY_UINT8_ARRAY;
|
|
246
248
|
const endOfDirectoryLocatorView = getDataView(endOfDirectoryLocatorArray);
|
|
247
249
|
if (endOfDirectoryLocatorArray.length == ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH &&
|
|
248
250
|
getUint32(endOfDirectoryLocatorView, 0) == ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIGNATURE) {
|
|
249
|
-
directoryDataOffset = getBigUint64(endOfDirectoryLocatorView, 8);
|
|
250
|
-
let endOfDirectoryArray = await readUint8Array(reader, directoryDataOffset, ZIP64_END_OF_CENTRAL_DIR_LENGTH
|
|
251
|
+
directoryDataOffset = getDiskOffset(reader, getUint32(endOfDirectoryLocatorView, 4)) + getBigUint64(endOfDirectoryLocatorView, 8);
|
|
252
|
+
let endOfDirectoryArray = await readUint8Array(reader, directoryDataOffset, ZIP64_END_OF_CENTRAL_DIR_LENGTH);
|
|
251
253
|
let endOfDirectoryView = getDataView(endOfDirectoryArray);
|
|
252
|
-
const expectedDirectoryDataOffset = endOfDirectoryInfo.offset - ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH - ZIP64_END_OF_CENTRAL_DIR_LENGTH
|
|
254
|
+
const expectedDirectoryDataOffset = endOfDirectoryInfo.offset - ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH - ZIP64_END_OF_CENTRAL_DIR_LENGTH;
|
|
253
255
|
if ((endOfDirectoryArray.length < ZIP64_END_OF_CENTRAL_DIR_LENGTH || getUint32(endOfDirectoryView, 0) != ZIP64_END_OF_CENTRAL_DIR_SIGNATURE) &&
|
|
254
256
|
directoryDataOffset != expectedDirectoryDataOffset && expectedDirectoryDataOffset >= 0) {
|
|
255
257
|
const originalDirectoryDataOffset = directoryDataOffset;
|
|
@@ -257,7 +259,7 @@ class ZipReader {
|
|
|
257
259
|
if (directoryDataOffset > originalDirectoryDataOffset) {
|
|
258
260
|
prependedDataLength = directoryDataOffset - originalDirectoryDataOffset;
|
|
259
261
|
}
|
|
260
|
-
endOfDirectoryArray = await readUint8Array(reader, directoryDataOffset, ZIP64_END_OF_CENTRAL_DIR_LENGTH
|
|
262
|
+
endOfDirectoryArray = await readUint8Array(reader, directoryDataOffset, ZIP64_END_OF_CENTRAL_DIR_LENGTH);
|
|
261
263
|
endOfDirectoryView = getDataView(endOfDirectoryArray);
|
|
262
264
|
}
|
|
263
265
|
if (endOfDirectoryArray.length < ZIP64_END_OF_CENTRAL_DIR_LENGTH || getUint32(endOfDirectoryView, 0) != ZIP64_END_OF_CENTRAL_DIR_SIGNATURE) {
|
|
@@ -284,7 +286,7 @@ class ZipReader {
|
|
|
284
286
|
} else if (checkAmbiguity && directoryDataLength != getBigUint64(endOfDirectoryView, 40)) {
|
|
285
287
|
throwAmbiguousArchive("mismatched zip64 end of central directory record");
|
|
286
288
|
}
|
|
287
|
-
directoryDataOffset = getBigUint64(endOfDirectoryView, 48) + prependedDataLength;
|
|
289
|
+
directoryDataOffset = getDiskOffset(reader, diskNumber) + getBigUint64(endOfDirectoryView, 48) + prependedDataLength;
|
|
288
290
|
}
|
|
289
291
|
}
|
|
290
292
|
const declaredDirectoryDataLength = directoryDataLength;
|
|
@@ -301,18 +303,18 @@ class ZipReader {
|
|
|
301
303
|
throw new Error(ERR_BAD_FORMAT);
|
|
302
304
|
}
|
|
303
305
|
let offset = 0;
|
|
304
|
-
let directoryArray = await readUint8Array(reader, directoryDataOffset, directoryDataLength
|
|
306
|
+
let directoryArray = await readUint8Array(reader, directoryDataOffset, directoryDataLength);
|
|
305
307
|
let directoryView = getDataView(directoryArray);
|
|
306
308
|
if (directoryDataLength) {
|
|
307
309
|
if (directoryArray.length < 4) {
|
|
308
310
|
throw new Error(ERR_BAD_FORMAT);
|
|
309
311
|
}
|
|
310
|
-
const expectedDirectoryDataOffset = centralDirectoryEndOffset - directoryDataLength
|
|
312
|
+
const expectedDirectoryDataOffset = centralDirectoryEndOffset - directoryDataLength;
|
|
311
313
|
if (directoryDataOffset != expectedDirectoryDataOffset && diskNumber == lastDiskNumber) {
|
|
312
314
|
const storedPointsAtDirectory = getUint32(directoryView, offset) == CENTRAL_FILE_HEADER_SIGNATURE;
|
|
313
315
|
let reconcile = !storedPointsAtDirectory;
|
|
314
316
|
if (!reconcile && expectedDirectoryDataOffset >= 0 && expectedDirectoryDataOffset + 4 <= reader.size) {
|
|
315
|
-
const expectedSignatureArray = await readUint8Array(reader, expectedDirectoryDataOffset, 4
|
|
317
|
+
const expectedSignatureArray = await readUint8Array(reader, expectedDirectoryDataOffset, 4);
|
|
316
318
|
reconcile = getUint32(getDataView(expectedSignatureArray), 0) == CENTRAL_FILE_HEADER_SIGNATURE;
|
|
317
319
|
}
|
|
318
320
|
if (reconcile) {
|
|
@@ -321,15 +323,15 @@ class ZipReader {
|
|
|
321
323
|
if (directoryDataOffset > originalDirectoryDataOffset) {
|
|
322
324
|
prependedDataLength += directoryDataOffset - originalDirectoryDataOffset;
|
|
323
325
|
}
|
|
324
|
-
directoryArray = await readUint8Array(reader, directoryDataOffset, directoryDataLength
|
|
326
|
+
directoryArray = await readUint8Array(reader, directoryDataOffset, directoryDataLength);
|
|
325
327
|
directoryView = getDataView(directoryArray);
|
|
326
328
|
}
|
|
327
329
|
}
|
|
328
330
|
}
|
|
329
|
-
const expectedDirectoryDataLength = centralDirectoryEndOffset - directoryDataOffset
|
|
331
|
+
const expectedDirectoryDataLength = centralDirectoryEndOffset - directoryDataOffset;
|
|
330
332
|
if (directoryDataLength != expectedDirectoryDataLength && expectedDirectoryDataLength >= 0 && diskNumber == lastDiskNumber) {
|
|
331
333
|
directoryDataLength = expectedDirectoryDataLength;
|
|
332
|
-
directoryArray = await readUint8Array(reader, directoryDataOffset, directoryDataLength
|
|
334
|
+
directoryArray = await readUint8Array(reader, directoryDataOffset, directoryDataLength);
|
|
333
335
|
directoryView = getDataView(directoryArray);
|
|
334
336
|
}
|
|
335
337
|
if (directoryDataOffset < 0 || directoryDataOffset >= reader.size) {
|
|
@@ -403,7 +405,7 @@ class ZipReader {
|
|
|
403
405
|
});
|
|
404
406
|
readCommonFooter(fileEntry, fileEntry, directoryView, offset + 6);
|
|
405
407
|
fileEntry.offset += prependedDataLength;
|
|
406
|
-
startOffset = Math.min(fileEntry.offset, startOffset);
|
|
408
|
+
startOffset = Math.min(getDiskOffset(reader, fileEntry.diskNumberStart) + fileEntry.offset, startOffset);
|
|
407
409
|
if (checkAmbiguity) {
|
|
408
410
|
if (filenames.has(fileEntry.filename)) {
|
|
409
411
|
duplicateFilename = true;
|
|
@@ -578,7 +580,8 @@ class ZipEntry {
|
|
|
578
580
|
dataDescriptor
|
|
579
581
|
} = bitFlag;
|
|
580
582
|
const localDirectory = fileEntry.localDirectory = {};
|
|
581
|
-
const
|
|
583
|
+
const localHeaderOffset = getDiskOffset(reader, diskNumberStart) + offset;
|
|
584
|
+
const dataArray = await readUint8Array(reader, localHeaderOffset, HEADER_SIZE);
|
|
582
585
|
const dataView = getDataView(dataArray);
|
|
583
586
|
let password = getOptionValue(zipEntry, options, OPTION_PASSWORD);
|
|
584
587
|
let rawPassword = getOptionValue(zipEntry, options, OPTION_RAW_PASSWORD);
|
|
@@ -604,12 +607,12 @@ class ZipEntry {
|
|
|
604
607
|
const checkAmbiguity = getStrictness(getOptionValue(zipEntry, options, OPTION_STRICTNESS), getOptionValue(zipEntry, options, OPTION_CHECK_AMBIGUITY)) == STRICTNESS_STRICT;
|
|
605
608
|
let rawLocalFilename = EMPTY_UINT8_ARRAY;
|
|
606
609
|
if (checkAmbiguity && (filenameLength || extraFieldLength)) {
|
|
607
|
-
const trailingDataArray = await readUint8Array(reader,
|
|
610
|
+
const trailingDataArray = await readUint8Array(reader, localHeaderOffset + HEADER_SIZE, filenameLength + extraFieldLength);
|
|
608
611
|
rawLocalFilename = trailingDataArray.subarray(0, filenameLength);
|
|
609
612
|
localDirectory.rawExtraField = trailingDataArray.subarray(filenameLength);
|
|
610
613
|
} else {
|
|
611
614
|
localDirectory.rawExtraField = extraFieldLength ?
|
|
612
|
-
await readUint8Array(reader,
|
|
615
|
+
await readUint8Array(reader, localHeaderOffset + HEADER_SIZE + filenameLength, extraFieldLength) :
|
|
613
616
|
EMPTY_UINT8_ARRAY;
|
|
614
617
|
}
|
|
615
618
|
readCommonFooter(zipEntry, localDirectory, dataView, 4, true);
|
|
@@ -635,9 +638,9 @@ class ZipEntry {
|
|
|
635
638
|
throw new Error(ERR_ENCRYPTED);
|
|
636
639
|
}
|
|
637
640
|
}
|
|
638
|
-
const dataOffset =
|
|
641
|
+
const dataOffset = localHeaderOffset + HEADER_SIZE + filenameLength + extraFieldLength;
|
|
639
642
|
const size = compressedSize;
|
|
640
|
-
const readable = reader.createReadable({ offset: dataOffset, size
|
|
643
|
+
const readable = reader.createReadable({ offset: dataOffset, size });
|
|
641
644
|
const signal = getOptionValue(zipEntry, options, OPTION_SIGNAL);
|
|
642
645
|
const checkPasswordOnly = getOptionValue(zipEntry, options, OPTION_CHECK_PASSWORD_ONLY);
|
|
643
646
|
let checkOverlappingEntry = getOptionValue(zipEntry, options, OPTION_CHECK_OVERLAPPING_ENTRY);
|
|
@@ -678,8 +681,7 @@ class ZipEntry {
|
|
|
678
681
|
reader,
|
|
679
682
|
fileEntry,
|
|
680
683
|
index,
|
|
681
|
-
offset,
|
|
682
|
-
diskNumberStart,
|
|
684
|
+
offset: localHeaderOffset,
|
|
683
685
|
signature,
|
|
684
686
|
compressedSize,
|
|
685
687
|
uncompressedSize,
|
|
@@ -743,7 +745,7 @@ function readCommonHeader(directory, dataView, offset) {
|
|
|
743
745
|
function readCommonFooter(fileEntry, directory, dataView, offset, localDirectory) {
|
|
744
746
|
const { rawExtraField } = directory;
|
|
745
747
|
const extraField = directory.extraField = new Map();
|
|
746
|
-
const rawExtraFieldView = getDataView(
|
|
748
|
+
const rawExtraFieldView = getDataView(rawExtraField);
|
|
747
749
|
let offsetExtraField = 0;
|
|
748
750
|
try {
|
|
749
751
|
while (offsetExtraField < rawExtraField.length) {
|
|
@@ -905,7 +907,7 @@ function readExtraFieldNTFS(extraFieldNTFS, directory) {
|
|
|
905
907
|
|
|
906
908
|
function readExtraFieldUnix(extraField, directory, isInfoZip) {
|
|
907
909
|
try {
|
|
908
|
-
const view = getDataView(
|
|
910
|
+
const view = getDataView(extraField.data);
|
|
909
911
|
let uid, gid;
|
|
910
912
|
if (isInfoZip) {
|
|
911
913
|
let offset = 0;
|
|
@@ -981,7 +983,6 @@ async function detectOverlappingEntry({
|
|
|
981
983
|
fileEntry,
|
|
982
984
|
index,
|
|
983
985
|
offset,
|
|
984
|
-
diskNumberStart,
|
|
985
986
|
signature,
|
|
986
987
|
compressedSize,
|
|
987
988
|
uncompressedSize,
|
|
@@ -990,12 +991,6 @@ async function detectOverlappingEntry({
|
|
|
990
991
|
extraFieldZip64,
|
|
991
992
|
readRanges
|
|
992
993
|
}) {
|
|
993
|
-
let diskOffset = 0;
|
|
994
|
-
if (diskNumberStart && reader.readers) {
|
|
995
|
-
for (let indexReader = 0; indexReader < Math.min(diskNumberStart, reader.readers.length); indexReader++) {
|
|
996
|
-
diskOffset += reader.readers[indexReader].size;
|
|
997
|
-
}
|
|
998
|
-
}
|
|
999
994
|
let dataDescriptorLength = 0;
|
|
1000
995
|
if (dataDescriptor) {
|
|
1001
996
|
if (extraFieldZip64) {
|
|
@@ -1005,7 +1000,7 @@ async function detectOverlappingEntry({
|
|
|
1005
1000
|
}
|
|
1006
1001
|
}
|
|
1007
1002
|
if (dataDescriptorLength) {
|
|
1008
|
-
const dataDescriptorArray = await readUint8Array(reader, dataOffset + compressedSize, dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH
|
|
1003
|
+
const dataDescriptorArray = await readUint8Array(reader, dataOffset + compressedSize, dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH);
|
|
1009
1004
|
const dataDescriptorSignature = dataDescriptorArray.length == dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH &&
|
|
1010
1005
|
getUint32(getDataView(dataDescriptorArray), 0) == DATA_DESCRIPTOR_RECORD_SIGNATURE;
|
|
1011
1006
|
if (dataDescriptorSignature) {
|
|
@@ -1028,8 +1023,8 @@ async function detectOverlappingEntry({
|
|
|
1028
1023
|
}
|
|
1029
1024
|
}
|
|
1030
1025
|
const range = {
|
|
1031
|
-
start:
|
|
1032
|
-
end:
|
|
1026
|
+
start: offset,
|
|
1027
|
+
end: dataOffset + compressedSize + dataDescriptorLength,
|
|
1033
1028
|
fileEntry
|
|
1034
1029
|
};
|
|
1035
1030
|
for (const [otherIndex, otherRange] of readRanges) {
|
|
@@ -1042,6 +1037,10 @@ async function detectOverlappingEntry({
|
|
|
1042
1037
|
readRanges.set(index, range);
|
|
1043
1038
|
}
|
|
1044
1039
|
|
|
1040
|
+
function getDiskOffset(reader, diskNumber) {
|
|
1041
|
+
return reader.getDiskOffset ? reader.getDiskOffset(diskNumber) : 0;
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1045
1044
|
function getStrictness(strictness, checkAmbiguity) {
|
|
1046
1045
|
if (strictness === UNDEFINED_VALUE) {
|
|
1047
1046
|
return checkAmbiguity ? STRICTNESS_STRICT : STRICTNESS_BALANCED;
|
|
@@ -1148,7 +1147,8 @@ async function getCentralDirectoryReachability(reader, view, anchoredOffset, ind
|
|
|
1148
1147
|
if (!filesLength && !directoryDataLength) {
|
|
1149
1148
|
return CENTRAL_DIRECTORY_PLAUSIBLE;
|
|
1150
1149
|
}
|
|
1151
|
-
|
|
1150
|
+
const directoryDiskNumber = getUint16(view, indexByte + 6);
|
|
1151
|
+
for (const centralDirectoryOffset of [offset - directoryDataLength, getDiskOffset(reader, directoryDiskNumber) + directoryDataOffset]) {
|
|
1152
1152
|
if (await readSignature(reader, view, anchoredOffset, centralDirectoryOffset, size, remoteProbeBudget) == CENTRAL_FILE_HEADER_SIGNATURE) {
|
|
1153
1153
|
return CENTRAL_DIRECTORY_REACHABLE;
|
|
1154
1154
|
}
|
|
@@ -1231,6 +1231,3 @@ function getBigUint64(view, offset) {
|
|
|
1231
1231
|
return Number(view.getBigUint64(offset, true));
|
|
1232
1232
|
}
|
|
1233
1233
|
|
|
1234
|
-
function getDataView(array) {
|
|
1235
|
-
return new DataView(array.buffer, array.byteOffset, array.byteLength);
|
|
1236
|
-
}
|
package/lib/core/zip-writer.js
CHANGED
|
@@ -44,9 +44,10 @@
|
|
|
44
44
|
* the other segments do not, see getSegmentOffset().
|
|
45
45
|
* - For split archives, `writer.diskOffset` is the total size of the closed segments and
|
|
46
46
|
* `writer.diskNumber` the index of the current segment. `writer.availableSize` is the remaining
|
|
47
|
-
* capacity of the current segment (
|
|
48
|
-
*
|
|
49
|
-
* required by APPNOTE section 8.5.2.
|
|
47
|
+
* capacity of the current segment; `writer.closeDisk()` ends it, the next segment being opened
|
|
48
|
+
* when more data is written. This is how header records are kept whole within a segment, as
|
|
49
|
+
* required by APPNOTE section 8.5.2. These properties only exist on split writers; the
|
|
50
|
+
* getDiskNumber(), getDiskOffset() and exceedsAvailableSize() accessors default them otherwise.
|
|
50
51
|
* - The segment coordinates of an entry (`diskNumberStart` and `offset`) must be read after
|
|
51
52
|
* calling skipDiskIfNeeded() and while holding the writer lock; they are unstable otherwise.
|
|
52
53
|
*
|
|
@@ -140,10 +141,7 @@ import {
|
|
|
140
141
|
OBJECT_TYPE,
|
|
141
142
|
EMPTY_UINT8_ARRAY
|
|
142
143
|
} from "./constants.js";
|
|
143
|
-
import {
|
|
144
|
-
getConfiguration,
|
|
145
|
-
getChunkSize
|
|
146
|
-
} from "./configuration.js";
|
|
144
|
+
import { getConfiguration } from "./configuration.js";
|
|
147
145
|
import {
|
|
148
146
|
CODEC_DEFLATE,
|
|
149
147
|
runWorker
|
|
@@ -154,6 +152,7 @@ import {
|
|
|
154
152
|
GenericReader
|
|
155
153
|
} from "./io.js";
|
|
156
154
|
import { encodeText } from "./util/encode-text.js";
|
|
155
|
+
import { getDataView } from "./util/array.js";
|
|
157
156
|
import {
|
|
158
157
|
PROPERTY_NAME_LAST_MODIFICATION_DATE,
|
|
159
158
|
PROPERTY_NAME_LAST_ACCESS_DATE,
|
|
@@ -207,9 +206,6 @@ import {
|
|
|
207
206
|
OPTION_USDZ,
|
|
208
207
|
OPTION_UNIX_EXTRA_FIELD_TYPE
|
|
209
208
|
} from "./options.js";
|
|
210
|
-
import {
|
|
211
|
-
ZipReader
|
|
212
|
-
} from "./zip-reader.js";
|
|
213
209
|
|
|
214
210
|
const ERR_DUPLICATED_NAME = "File already exists";
|
|
215
211
|
const ERR_INVALID_COMMENT = "Zip file comment exceeds 64KB";
|
|
@@ -245,9 +241,10 @@ class ZipWriter {
|
|
|
245
241
|
|
|
246
242
|
constructor(writer, options = {}) {
|
|
247
243
|
writer = new GenericWriter(writer);
|
|
244
|
+
const { availableSize = INFINITY_VALUE, maxSize = INFINITY_VALUE } = writer;
|
|
248
245
|
const addSplitZipSignature =
|
|
249
|
-
|
|
250
|
-
|
|
246
|
+
availableSize > 0 && availableSize !== INFINITY_VALUE &&
|
|
247
|
+
maxSize > 0 && maxSize !== INFINITY_VALUE;
|
|
251
248
|
Object.assign(this, {
|
|
252
249
|
writer,
|
|
253
250
|
addSplitZipSignature,
|
|
@@ -269,6 +266,7 @@ class ZipWriter {
|
|
|
269
266
|
}
|
|
270
267
|
reader = new GenericReader(reader);
|
|
271
268
|
await initStream(reader);
|
|
269
|
+
const { ZipReader } = await import("./zip-reader.js");
|
|
272
270
|
const zipReader = new ZipReader(reader.readable);
|
|
273
271
|
const entries = await zipReader.getEntries();
|
|
274
272
|
await zipReader.close();
|
|
@@ -287,8 +285,6 @@ class ZipWriter {
|
|
|
287
285
|
encrypted,
|
|
288
286
|
uncompressedSize,
|
|
289
287
|
compressedSize,
|
|
290
|
-
diskOffset,
|
|
291
|
-
diskNumber,
|
|
292
288
|
zip64
|
|
293
289
|
} = entry;
|
|
294
290
|
let {
|
|
@@ -336,8 +332,9 @@ class ZipWriter {
|
|
|
336
332
|
Object.assign(entry, {
|
|
337
333
|
zip64UncompressedSize,
|
|
338
334
|
zip64CompressedSize,
|
|
339
|
-
zip64Offset: zip64 &&
|
|
340
|
-
|
|
335
|
+
zip64Offset: zip64 && entry.offset >= MAX_32_BITS,
|
|
336
|
+
diskNumberStart: 0,
|
|
337
|
+
zip64DiskNumberStart: false,
|
|
341
338
|
rawExtraFieldZip64,
|
|
342
339
|
rawExtraFieldAES,
|
|
343
340
|
rawExtraFieldExtendedTimestamp,
|
|
@@ -521,7 +518,8 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
521
518
|
try {
|
|
522
519
|
const sizesInfo = await resolveSizes(zipWriter, reader, metadataInfo, options);
|
|
523
520
|
({ reader } = sizesInfo);
|
|
524
|
-
const
|
|
521
|
+
const diskOffset = getDiskOffset(zipWriter.writer);
|
|
522
|
+
const diskNumber = getDiskNumber(zipWriter.writer);
|
|
525
523
|
options = Object.assign({}, options, attributesInfo.resolvedOptions, metadataInfo.resolvedOptions, sizesInfo.resolvedOptions, {
|
|
526
524
|
internalFileAttribute: metadataInfo.resolvedOptions.internalFileAttributes,
|
|
527
525
|
externalFileAttribute: attributesInfo.resolvedOptions.externalFileAttributes,
|
|
@@ -698,7 +696,7 @@ function resolveMetadata(zipWriter, name, options) {
|
|
|
698
696
|
const extendedTimestamp = getOptionValue(zipWriter, options, OPTION_EXTENDED_TIMESTAMP, true);
|
|
699
697
|
const keepOrder = getOptionValue(zipWriter, options, OPTION_KEEP_ORDER, true);
|
|
700
698
|
const useWebWorkers = getOptionValue(zipWriter, options, OPTION_USE_WEB_WORKERS);
|
|
701
|
-
const transferStreams = getOptionValue(zipWriter, options, OPTION_TRANSFER_STREAMS
|
|
699
|
+
const transferStreams = getOptionValue(zipWriter, options, OPTION_TRANSFER_STREAMS);
|
|
702
700
|
const bufferedWrite = getOptionValue(zipWriter, options, OPTION_BUFFERED_WRITE);
|
|
703
701
|
const createTempStream = getOptionValue(zipWriter, options, OPTION_CREATE_TEMP_STREAM);
|
|
704
702
|
const dataDescriptorSignature = getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR_SIGNATURE, true);
|
|
@@ -896,7 +894,7 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
|
896
894
|
await requestLockWriter();
|
|
897
895
|
}
|
|
898
896
|
await initStream(fileWriter);
|
|
899
|
-
const
|
|
897
|
+
const diskOffset = getDiskOffset(writer);
|
|
900
898
|
if (zipWriter.addSplitZipSignature) {
|
|
901
899
|
delete zipWriter.addSplitZipSignature;
|
|
902
900
|
const signatureArray = new Uint8Array(4);
|
|
@@ -913,7 +911,7 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
|
913
911
|
await lockPreviousFileEntry;
|
|
914
912
|
await skipDiskIfNeeded();
|
|
915
913
|
}
|
|
916
|
-
const diskNumberStart = writer
|
|
914
|
+
const diskNumberStart = getDiskNumber(writer);
|
|
917
915
|
const entryOffset = getSegmentOffset(zipWriter, writer);
|
|
918
916
|
fileEntry.diskNumberStart = diskNumberStart;
|
|
919
917
|
if (!bufferedWrite) {
|
|
@@ -933,11 +931,11 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
|
933
931
|
writingBufferedEntryData = true;
|
|
934
932
|
writerSizeBeforeEntry = writer.size;
|
|
935
933
|
await skipDiskIfNeeded();
|
|
936
|
-
fileEntry.diskNumberStart = writer
|
|
934
|
+
fileEntry.diskNumberStart = getDiskNumber(writer);
|
|
937
935
|
fileEntry.offset = getSegmentOffset(zipWriter, writer);
|
|
938
936
|
if (usdz) {
|
|
939
937
|
const previousMetadataSize = entryInfo.metadataSize;
|
|
940
|
-
appendExtraFieldUSDZ(entryInfo, zipWriter.offset - writer
|
|
938
|
+
appendExtraFieldUSDZ(entryInfo, zipWriter.offset - getDiskOffset(writer));
|
|
941
939
|
fileEntry.size += entryInfo.metadataSize - previousMetadataSize;
|
|
942
940
|
}
|
|
943
941
|
updateLocalHeader(fileEntry, headerInfo.localHeaderView, options);
|
|
@@ -1002,9 +1000,8 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
|
1002
1000
|
}
|
|
1003
1001
|
|
|
1004
1002
|
async function skipDiskIfNeeded() {
|
|
1005
|
-
if (getLength(headerInfo.localHeaderArray)
|
|
1006
|
-
writer.
|
|
1007
|
-
await writeData(writer, EMPTY_UINT8_ARRAY);
|
|
1003
|
+
if (exceedsAvailableSize(writer, getLength(headerInfo.localHeaderArray))) {
|
|
1004
|
+
await writer.closeDisk();
|
|
1008
1005
|
}
|
|
1009
1006
|
}
|
|
1010
1007
|
}
|
|
@@ -1115,7 +1112,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
|
|
|
1115
1112
|
}
|
|
1116
1113
|
const { writable } = writer;
|
|
1117
1114
|
if (reader) {
|
|
1118
|
-
const readable = reader.createReadable ? reader.createReadable(
|
|
1115
|
+
const readable = reader.createReadable ? reader.createReadable() : reader.readable;
|
|
1119
1116
|
const size = reader.size;
|
|
1120
1117
|
const workerOptions = {
|
|
1121
1118
|
options: {
|
|
@@ -1547,8 +1544,8 @@ function updateLocalHeader({
|
|
|
1547
1544
|
|
|
1548
1545
|
async function closeFile(zipWriter, comment, options) {
|
|
1549
1546
|
const directoryDataLength = createDirectoryRecords(zipWriter.files);
|
|
1550
|
-
const
|
|
1551
|
-
await writeEndOfDirectoryRecord(zipWriter, comment, options, {
|
|
1547
|
+
const directoryStart = await writeDirectoryRecords(zipWriter, directoryDataLength, options);
|
|
1548
|
+
await writeEndOfDirectoryRecord(zipWriter, comment, options, { directoryStart, directoryDataLength });
|
|
1552
1549
|
}
|
|
1553
1550
|
|
|
1554
1551
|
function createDirectoryRecords(files) {
|
|
@@ -1630,8 +1627,8 @@ async function writeDirectoryRecords(zipWriter, directoryDataLength, options) {
|
|
|
1630
1627
|
await initStream(writer);
|
|
1631
1628
|
let offset = 0;
|
|
1632
1629
|
let directoryDiskOffset = 0;
|
|
1633
|
-
let
|
|
1634
|
-
let
|
|
1630
|
+
let directoryStartDiskNumber = getDiskNumber(writer);
|
|
1631
|
+
let directoryStartDiskOffset = getDiskOffset(writer);
|
|
1635
1632
|
for (const [indexFileEntry, fileEntry] of Array.from(files.values()).entries()) {
|
|
1636
1633
|
const {
|
|
1637
1634
|
offset: fileEntryOffset,
|
|
@@ -1658,15 +1655,14 @@ async function writeDirectoryRecords(zipWriter, directoryDataLength, options) {
|
|
|
1658
1655
|
} = fileEntry;
|
|
1659
1656
|
const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField);
|
|
1660
1657
|
const directoryRecordLength = CENTRAL_FILE_HEADER_LENGTH + getLength(rawFilename, rawComment) + extraFieldLength;
|
|
1661
|
-
if (offset + directoryRecordLength - directoryDiskOffset
|
|
1658
|
+
if (exceedsAvailableSize(writer, offset + directoryRecordLength - directoryDiskOffset)) {
|
|
1662
1659
|
await writeData(writer, directoryArray.slice(directoryDiskOffset, offset));
|
|
1663
1660
|
directoryDiskOffset = offset;
|
|
1664
|
-
writer.
|
|
1665
|
-
await writeData(writer, EMPTY_UINT8_ARRAY);
|
|
1661
|
+
await writer.closeDisk();
|
|
1666
1662
|
}
|
|
1667
1663
|
if (indexFileEntry == 0) {
|
|
1668
|
-
|
|
1669
|
-
|
|
1664
|
+
directoryStartDiskNumber = getDiskNumber(writer);
|
|
1665
|
+
directoryStartDiskOffset = getDiskOffset(writer);
|
|
1670
1666
|
}
|
|
1671
1667
|
if (!zip64UncompressedSize) {
|
|
1672
1668
|
setUint32(headerView, HEADER_OFFSET_UNCOMPRESSED_SIZE, uncompressedSize);
|
|
@@ -1706,18 +1702,18 @@ async function writeDirectoryRecords(zipWriter, directoryDataLength, options) {
|
|
|
1706
1702
|
}
|
|
1707
1703
|
}
|
|
1708
1704
|
await writeData(writer, directoryDiskOffset ? directoryArray.slice(directoryDiskOffset) : directoryArray);
|
|
1709
|
-
return {
|
|
1705
|
+
return { diskNumber: directoryStartDiskNumber, diskOffset: directoryStartDiskOffset };
|
|
1710
1706
|
}
|
|
1711
1707
|
|
|
1712
1708
|
async function writeEndOfDirectoryRecord(zipWriter, comment, options, cdInfo) {
|
|
1713
1709
|
const { writer } = zipWriter;
|
|
1714
|
-
const {
|
|
1710
|
+
const { directoryStart } = cdInfo;
|
|
1715
1711
|
let { directoryDataLength } = cdInfo;
|
|
1716
1712
|
let filesLength = zipWriter.files.size;
|
|
1717
|
-
let diskNumber =
|
|
1718
|
-
let directoryOffset =
|
|
1719
|
-
let lastDiskNumber = writer
|
|
1720
|
-
if (writer
|
|
1713
|
+
let diskNumber = directoryStart.diskNumber;
|
|
1714
|
+
let directoryOffset = getSegmentOffset(zipWriter, directoryStart);
|
|
1715
|
+
let lastDiskNumber = getDiskNumber(writer);
|
|
1716
|
+
if (exceedsAvailableSize(writer, END_OF_CENTRAL_DIR_LENGTH)) {
|
|
1721
1717
|
lastDiskNumber++;
|
|
1722
1718
|
}
|
|
1723
1719
|
let zip64 = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIP64);
|
|
@@ -1733,11 +1729,10 @@ async function writeEndOfDirectoryRecord(zipWriter, comment, options, cdInfo) {
|
|
|
1733
1729
|
throw new Error(ERR_INVALID_COMMENT);
|
|
1734
1730
|
}
|
|
1735
1731
|
const endOfdirectoryRecord = createRecordWriter(zip64 ? ZIP64_END_OF_CENTRAL_DIR_TOTAL_LENGTH : END_OF_CENTRAL_DIR_LENGTH);
|
|
1736
|
-
if (getLength(endOfdirectoryRecord.array) + commentLength
|
|
1737
|
-
writer.
|
|
1738
|
-
await writeData(writer, EMPTY_UINT8_ARRAY);
|
|
1732
|
+
if (exceedsAvailableSize(writer, getLength(endOfdirectoryRecord.array) + commentLength)) {
|
|
1733
|
+
await writer.closeDisk();
|
|
1739
1734
|
}
|
|
1740
|
-
lastDiskNumber = writer
|
|
1735
|
+
lastDiskNumber = getDiskNumber(writer);
|
|
1741
1736
|
if (zip64) {
|
|
1742
1737
|
endOfdirectoryRecord.uint32(ZIP64_END_OF_CENTRAL_DIR_SIGNATURE);
|
|
1743
1738
|
endOfdirectoryRecord.uint64(44);
|
|
@@ -1751,7 +1746,7 @@ async function writeEndOfDirectoryRecord(zipWriter, comment, options, cdInfo) {
|
|
|
1751
1746
|
endOfdirectoryRecord.uint64(directoryOffset);
|
|
1752
1747
|
endOfdirectoryRecord.uint32(ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIGNATURE);
|
|
1753
1748
|
endOfdirectoryRecord.uint32(lastDiskNumber);
|
|
1754
|
-
endOfdirectoryRecord.uint64(BigInt(zipWriter
|
|
1749
|
+
endOfdirectoryRecord.uint64(BigInt(getSegmentOffset(zipWriter, writer)) + BigInt(directoryDataLength));
|
|
1755
1750
|
endOfdirectoryRecord.uint32(lastDiskNumber + 1);
|
|
1756
1751
|
const supportZip64SplitFile = getOptionValue(zipWriter, options, OPTION_SUPPORT_ZIP64_SPLIT_FILE, true);
|
|
1757
1752
|
if (supportZip64SplitFile) {
|
|
@@ -1791,8 +1786,23 @@ function createRecordWriter(length) {
|
|
|
1791
1786
|
};
|
|
1792
1787
|
}
|
|
1793
1788
|
|
|
1794
|
-
function
|
|
1795
|
-
|
|
1789
|
+
function getDiskNumber(writer) {
|
|
1790
|
+
const { diskNumber = 0 } = writer;
|
|
1791
|
+
return diskNumber;
|
|
1792
|
+
}
|
|
1793
|
+
|
|
1794
|
+
function getDiskOffset(writer) {
|
|
1795
|
+
const { diskOffset = 0 } = writer;
|
|
1796
|
+
return diskOffset;
|
|
1797
|
+
}
|
|
1798
|
+
|
|
1799
|
+
function exceedsAvailableSize(writer, length) {
|
|
1800
|
+
const { availableSize = INFINITY_VALUE } = writer;
|
|
1801
|
+
return length > availableSize;
|
|
1802
|
+
}
|
|
1803
|
+
|
|
1804
|
+
function getSegmentOffset(zipWriter, { diskNumber = 0, diskOffset = 0 }) {
|
|
1805
|
+
return zipWriter.offset - diskOffset - (diskNumber ? zipWriter.initialOffset : 0);
|
|
1796
1806
|
}
|
|
1797
1807
|
|
|
1798
1808
|
async function writeData(writer, array) {
|
|
@@ -1869,9 +1879,6 @@ function arraySet(array, typedArray, offset) {
|
|
|
1869
1879
|
array.set(typedArray, offset);
|
|
1870
1880
|
}
|
|
1871
1881
|
|
|
1872
|
-
function getDataView(array) {
|
|
1873
|
-
return new DataView(array.buffer, array.byteOffset, array.byteLength);
|
|
1874
|
-
}
|
|
1875
1882
|
|
|
1876
1883
|
function getLength(...arrayLikes) {
|
|
1877
1884
|
let result = 0;
|