@zip.js/zip.js 2.6.26 → 2.6.28
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/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 +1709 -1684
- package/dist/zip-fs-full.min.js +1 -1
- package/dist/zip-fs.js +509 -484
- package/dist/zip-fs.min.js +1 -1
- package/dist/zip-full.js +509 -484
- 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 +509 -484
- package/dist/zip.min.js +1 -1
- package/index.d.ts +42 -19
- package/lib/core/codec-interface.js +17 -9
- package/lib/core/codec-pool-worker.js +2 -3
- package/lib/core/codec-pool.js +1 -1
- package/lib/core/configuration.js +29 -8
- package/lib/core/io.js +36 -46
- package/lib/core/streams/aes-crypto-stream.js +86 -61
- package/lib/core/streams/codec-stream.js +1 -2
- package/lib/core/streams/common-crypto.js +3 -1
- package/lib/core/streams/zip-crypto-stream.js +12 -13
- package/lib/core/streams/zip-entry-stream.js +41 -57
- package/lib/core/z-worker-core.js +9 -9
- package/lib/core/zip-reader.js +1 -2
- package/lib/core/zip-writer.js +49 -42
- package/lib/z-worker-inline.js +1 -1
- package/package.json +5 -2
- package/rollup-fflate.config.dev.js +2 -2
- package/rollup-fflate.config.js +2 -2
- package/rollup.config.dev.js +2 -2
- package/rollup.config.js +2 -2
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
27
27
|
*/
|
|
28
28
|
|
|
29
|
-
/* global
|
|
29
|
+
/* global TransformStream */
|
|
30
30
|
|
|
31
31
|
import { Crc32Stream } from "./crc32-stream.js";
|
|
32
32
|
import {
|
|
@@ -35,51 +35,36 @@ import {
|
|
|
35
35
|
} from "./aes-crypto-stream.js";
|
|
36
36
|
import {
|
|
37
37
|
ZipCryptoEncryptionStream,
|
|
38
|
-
ZipCryptoDecryptionStream
|
|
38
|
+
ZipCryptoDecryptionStream
|
|
39
39
|
} from "./zip-crypto-stream.js";
|
|
40
40
|
import {
|
|
41
|
-
ERR_INVALID_PASSWORD
|
|
41
|
+
ERR_INVALID_PASSWORD,
|
|
42
|
+
ERR_INVALID_SIGNATURE
|
|
42
43
|
} from "./common-crypto.js";
|
|
43
|
-
import { CodecStream } from "./codec-stream.js";
|
|
44
44
|
|
|
45
|
-
const ERR_INVALID_SIGNATURE = "Invalid signature";
|
|
46
45
|
const COMPRESSION_FORMAT = "deflate-raw";
|
|
47
|
-
const UNDEFINED_TYPE = "undefined";
|
|
48
|
-
const COMPRESSION_STREAM_API_SUPPORTED = typeof CompressionStream == UNDEFINED_TYPE;
|
|
49
|
-
const DECOMPRESSION_STREAM_API_SUPPORTED = typeof DecompressionStream == UNDEFINED_TYPE;
|
|
50
|
-
let INFLATE_RAW_SUPPORTED = true;
|
|
51
|
-
let DEFLATE_RAW_SUPPORTED = true;
|
|
52
46
|
|
|
53
47
|
class DeflateStream extends TransformStream {
|
|
54
48
|
|
|
55
|
-
constructor(
|
|
56
|
-
super({}
|
|
49
|
+
constructor(options, { chunkSize, CompressionStream, CompressionStreamNative }) {
|
|
50
|
+
super({});
|
|
57
51
|
const { compressed, encrypted, useCompressionStream, password, passwordVerification, encryptionStrength, zipCrypto, signed, level } = options;
|
|
58
52
|
const stream = this;
|
|
59
53
|
let crc32Stream, encryptionStream;
|
|
60
54
|
let readable = filterEmptyChunks(super.readable);
|
|
61
55
|
if ((!encrypted || zipCrypto) && signed) {
|
|
62
56
|
[readable, crc32Stream] = readable.tee();
|
|
63
|
-
crc32Stream =
|
|
57
|
+
crc32Stream = pipeThrough(crc32Stream, new Crc32Stream());
|
|
64
58
|
}
|
|
65
59
|
if (compressed) {
|
|
66
|
-
|
|
67
|
-
readable = pipeCodecStream(codecConstructor, readable, { chunkSize, level });
|
|
68
|
-
} else {
|
|
69
|
-
try {
|
|
70
|
-
readable = readable.pipeThrough(new CompressionStream(COMPRESSION_FORMAT));
|
|
71
|
-
} catch (_error) {
|
|
72
|
-
DEFLATE_RAW_SUPPORTED = false;
|
|
73
|
-
readable = pipeCodecStream(codecConstructor, readable, { chunkSize, level });
|
|
74
|
-
}
|
|
75
|
-
}
|
|
60
|
+
readable = pipeThroughCommpressionStream(readable, useCompressionStream, { level, chunkSize }, CompressionStreamNative, CompressionStream);
|
|
76
61
|
}
|
|
77
62
|
if (encrypted) {
|
|
78
63
|
if (zipCrypto) {
|
|
79
|
-
readable =
|
|
64
|
+
readable = pipeThrough(readable, new ZipCryptoEncryptionStream(password, passwordVerification));
|
|
80
65
|
} else {
|
|
81
66
|
encryptionStream = new AESEncryptionStream(password, encryptionStrength);
|
|
82
|
-
readable =
|
|
67
|
+
readable = pipeThrough(readable, encryptionStream);
|
|
83
68
|
}
|
|
84
69
|
}
|
|
85
70
|
setReadable(stream, readable, async () => {
|
|
@@ -98,46 +83,31 @@ class DeflateStream extends TransformStream {
|
|
|
98
83
|
|
|
99
84
|
class InflateStream extends TransformStream {
|
|
100
85
|
|
|
101
|
-
constructor(
|
|
102
|
-
super({}
|
|
103
|
-
const { zipCrypto, encrypted, password, passwordVerification, signed, encryptionStrength, compressed, useCompressionStream } = options;
|
|
104
|
-
const stream = this;
|
|
86
|
+
constructor(options, { chunkSize, DecompressionStream, DecompressionStreamNative }) {
|
|
87
|
+
super({});
|
|
88
|
+
const { zipCrypto, encrypted, password, passwordVerification, signed, signature, encryptionStrength, compressed, useCompressionStream } = options;
|
|
105
89
|
let crc32Stream, decryptionStream;
|
|
106
90
|
let readable = filterEmptyChunks(super.readable);
|
|
107
91
|
if (encrypted) {
|
|
108
92
|
if (zipCrypto) {
|
|
109
|
-
readable =
|
|
93
|
+
readable = pipeThrough(readable, new ZipCryptoDecryptionStream(password, passwordVerification));
|
|
110
94
|
} else {
|
|
111
95
|
decryptionStream = new AESDecryptionStream(password, signed, encryptionStrength);
|
|
112
|
-
readable =
|
|
96
|
+
readable = pipeThrough(readable, decryptionStream);
|
|
113
97
|
}
|
|
114
98
|
}
|
|
115
99
|
if (compressed) {
|
|
116
|
-
|
|
117
|
-
readable = pipeCodecStream(codecConstructor, readable, { chunkSize });
|
|
118
|
-
} else {
|
|
119
|
-
try {
|
|
120
|
-
readable = readable.pipeThrough(new DecompressionStream(COMPRESSION_FORMAT));
|
|
121
|
-
} catch (_error) {
|
|
122
|
-
INFLATE_RAW_SUPPORTED = false;
|
|
123
|
-
readable = pipeCodecStream(codecConstructor, readable, { chunkSize });
|
|
124
|
-
}
|
|
125
|
-
}
|
|
100
|
+
readable = pipeThroughCommpressionStream(readable, useCompressionStream, { chunkSize }, DecompressionStreamNative, DecompressionStream);
|
|
126
101
|
}
|
|
127
102
|
if ((!encrypted || zipCrypto) && signed) {
|
|
128
103
|
[readable, crc32Stream] = readable.tee();
|
|
129
|
-
crc32Stream =
|
|
104
|
+
crc32Stream = pipeThrough(crc32Stream, new Crc32Stream());
|
|
130
105
|
}
|
|
131
|
-
setReadable(
|
|
132
|
-
if (encrypted && !zipCrypto) {
|
|
133
|
-
if (!decryptionStream.valid) {
|
|
134
|
-
throw new Error(ERR_INVALID_SIGNATURE);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
106
|
+
setReadable(this, readable, async () => {
|
|
137
107
|
if ((!encrypted || zipCrypto) && signed) {
|
|
138
|
-
const
|
|
139
|
-
const dataViewSignature = new DataView(
|
|
140
|
-
if (
|
|
108
|
+
const streamSignature = await crc32Stream.getReader().read();
|
|
109
|
+
const dataViewSignature = new DataView(streamSignature.value.buffer);
|
|
110
|
+
if (signature != dataViewSignature.getUint32(0, false)) {
|
|
141
111
|
throw new Error(ERR_INVALID_SIGNATURE);
|
|
142
112
|
}
|
|
143
113
|
}
|
|
@@ -152,12 +122,8 @@ export {
|
|
|
152
122
|
ERR_INVALID_SIGNATURE
|
|
153
123
|
};
|
|
154
124
|
|
|
155
|
-
function pipeCodecStream(codecConstructor, readable, options) {
|
|
156
|
-
return readable.pipeThrough(new CodecStream(codecConstructor, options));
|
|
157
|
-
}
|
|
158
|
-
|
|
159
125
|
function filterEmptyChunks(readable) {
|
|
160
|
-
return
|
|
126
|
+
return pipeThrough(readable, new TransformStream({
|
|
161
127
|
transform(chunk, controller) {
|
|
162
128
|
if (chunk && chunk.length) {
|
|
163
129
|
controller.enqueue(chunk);
|
|
@@ -167,10 +133,28 @@ function filterEmptyChunks(readable) {
|
|
|
167
133
|
}
|
|
168
134
|
|
|
169
135
|
function setReadable(stream, readable, flush) {
|
|
170
|
-
readable =
|
|
136
|
+
readable = pipeThrough(readable, new TransformStream({ flush }));
|
|
171
137
|
Object.defineProperty(stream, "readable", {
|
|
172
138
|
get() {
|
|
173
139
|
return readable;
|
|
174
140
|
}
|
|
175
141
|
});
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function pipeThroughCommpressionStream(readable, useCompressionStream, options, CodecStreamNative, CodecStream) {
|
|
145
|
+
try {
|
|
146
|
+
const CompressionStream = useCompressionStream && CodecStreamNative ? CodecStreamNative : CodecStream;
|
|
147
|
+
readable = pipeThrough(readable, new CompressionStream(COMPRESSION_FORMAT, options));
|
|
148
|
+
} catch (error) {
|
|
149
|
+
if (useCompressionStream) {
|
|
150
|
+
readable = pipeThrough(readable, new CodecStream(COMPRESSION_FORMAT, options));
|
|
151
|
+
} else {
|
|
152
|
+
throw error;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return readable;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function pipeThrough(readable, transformStream) {
|
|
159
|
+
return readable.pipeThrough(transformStream);
|
|
176
160
|
}
|
|
@@ -30,8 +30,7 @@
|
|
|
30
30
|
|
|
31
31
|
import {
|
|
32
32
|
Codec,
|
|
33
|
-
|
|
34
|
-
CODEC_INFLATE,
|
|
33
|
+
getCodecStreamClass,
|
|
35
34
|
MESSAGE_EVENT_TYPE,
|
|
36
35
|
MESSAGE_START,
|
|
37
36
|
MESSAGE_PULL,
|
|
@@ -70,18 +69,19 @@ addEventListener(MESSAGE_EVENT_TYPE, async event => {
|
|
|
70
69
|
async function init(message) {
|
|
71
70
|
try {
|
|
72
71
|
const { options, scripts, config } = message;
|
|
73
|
-
const { codecType } = options;
|
|
74
72
|
if (scripts && scripts.length) {
|
|
75
73
|
importScripts.apply(undefined, scripts);
|
|
76
74
|
}
|
|
77
75
|
if (self.initCodec) {
|
|
78
76
|
self.initCodec();
|
|
79
77
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
78
|
+
config.CompressionStreamNative = self.CompressionStream;
|
|
79
|
+
config.DecompressionStreamNative = self.DecompressionStream;
|
|
80
|
+
if (self.Deflate) {
|
|
81
|
+
config.CompressionStream = getCodecStreamClass(self.Deflate);
|
|
82
|
+
}
|
|
83
|
+
if (self.Inflate) {
|
|
84
|
+
config.DecompressionStream = getCodecStreamClass(self.Inflate);
|
|
85
85
|
}
|
|
86
86
|
const strategy = { highWaterMark: 1, size: () => config.chunkSize };
|
|
87
87
|
const readable = message.readable || new ReadableStream({
|
|
@@ -106,7 +106,7 @@ async function init(message) {
|
|
|
106
106
|
await ackData;
|
|
107
107
|
}
|
|
108
108
|
}, strategy);
|
|
109
|
-
codec = new Codec(
|
|
109
|
+
codec = new Codec(readable, writable, options, config);
|
|
110
110
|
const result = await codec.run();
|
|
111
111
|
if (message.writable && !options.preventClose) {
|
|
112
112
|
await message.writable.close();
|
package/lib/core/zip-reader.js
CHANGED
|
@@ -355,8 +355,7 @@ class ZipEntry {
|
|
|
355
355
|
preventClose
|
|
356
356
|
},
|
|
357
357
|
config,
|
|
358
|
-
streamOptions: { signal, size, onstart, onprogress, onend }
|
|
359
|
-
codecConstructor: config.Inflate
|
|
358
|
+
streamOptions: { signal, size, onstart, onprogress, onend }
|
|
360
359
|
};
|
|
361
360
|
writable.size += (await runWorker({ readable, writable }, workerOptions)).size;
|
|
362
361
|
if (!preventClose) {
|
package/lib/core/zip-writer.js
CHANGED
|
@@ -181,12 +181,12 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
181
181
|
options.directory = name.endsWith(DIRECTORY_SIGNATURE);
|
|
182
182
|
}
|
|
183
183
|
const rawFilename = encodeText(name);
|
|
184
|
-
if (rawFilename
|
|
184
|
+
if (getLength(rawFilename) > MAX_16_BITS) {
|
|
185
185
|
throw new Error(ERR_INVALID_ENTRY_NAME);
|
|
186
186
|
}
|
|
187
187
|
const comment = options.comment || "";
|
|
188
188
|
const rawComment = encodeText(comment);
|
|
189
|
-
if (rawComment
|
|
189
|
+
if (getLength(rawComment) > MAX_16_BITS) {
|
|
190
190
|
throw new Error(ERR_INVALID_ENTRY_COMMENT);
|
|
191
191
|
}
|
|
192
192
|
const version = zipWriter.options.version || options.version || 0;
|
|
@@ -211,19 +211,19 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
211
211
|
if (extraField) {
|
|
212
212
|
let extraFieldSize = 0;
|
|
213
213
|
let offset = 0;
|
|
214
|
-
extraField.forEach(data => extraFieldSize += 4 + data
|
|
214
|
+
extraField.forEach(data => extraFieldSize += 4 + getLength(data));
|
|
215
215
|
rawExtraField = new Uint8Array(extraFieldSize);
|
|
216
216
|
extraField.forEach((data, type) => {
|
|
217
217
|
if (type > MAX_16_BITS) {
|
|
218
218
|
throw new Error(ERR_INVALID_EXTRAFIELD_TYPE);
|
|
219
219
|
}
|
|
220
|
-
if (data
|
|
220
|
+
if (getLength(data) > MAX_16_BITS) {
|
|
221
221
|
throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
|
|
222
222
|
}
|
|
223
223
|
arraySet(rawExtraField, new Uint16Array([type]), offset);
|
|
224
|
-
arraySet(rawExtraField, new Uint16Array([data
|
|
224
|
+
arraySet(rawExtraField, new Uint16Array([getLength(data)]), offset + 2);
|
|
225
225
|
arraySet(rawExtraField, data, offset + 4);
|
|
226
|
-
offset += 4 + data
|
|
226
|
+
offset += 4 + getLength(data);
|
|
227
227
|
});
|
|
228
228
|
}
|
|
229
229
|
let extendedTimestamp = getOptionValue(zipWriter, options, "extendedTimestamp");
|
|
@@ -312,7 +312,7 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
312
312
|
});
|
|
313
313
|
const headerInfo = getHeaderInfo(options);
|
|
314
314
|
const dataDescriptorInfo = getDataDescriptorInfo(options);
|
|
315
|
-
maximumEntrySize = headerInfo.localHeaderArray.
|
|
315
|
+
maximumEntrySize = getLength(headerInfo.localHeaderArray, dataDescriptorInfo.dataDescriptorArray) + maximumCompressedSize;
|
|
316
316
|
zipWriter.pendingEntriesSize += maximumEntrySize;
|
|
317
317
|
let fileEntry;
|
|
318
318
|
try {
|
|
@@ -530,8 +530,7 @@ async function createFileEntry(reader, writer, pendingFileEntry, entryInfo, conf
|
|
|
530
530
|
transferStreams: false
|
|
531
531
|
},
|
|
532
532
|
config,
|
|
533
|
-
streamOptions: { signal, size, onstart, onprogress, onend }
|
|
534
|
-
codecConstructor: config.Deflate
|
|
533
|
+
streamOptions: { signal, size, onstart, onprogress, onend }
|
|
535
534
|
};
|
|
536
535
|
const result = await runWorker({ readable, writable }, workerOptions);
|
|
537
536
|
writable.size += result.size;
|
|
@@ -562,7 +561,7 @@ async function createFileEntry(reader, writer, pendingFileEntry, entryInfo, conf
|
|
|
562
561
|
creationDate,
|
|
563
562
|
lastAccessDate,
|
|
564
563
|
encrypted,
|
|
565
|
-
length: localHeaderArray
|
|
564
|
+
length: getLength(localHeaderArray, dataDescriptorArray) + compressedSize,
|
|
566
565
|
compressionMethod,
|
|
567
566
|
version,
|
|
568
567
|
headerArray,
|
|
@@ -589,10 +588,10 @@ function getHeaderInfo(options) {
|
|
|
589
588
|
} = options;
|
|
590
589
|
let version = options.version || VERSION_DEFLATE;
|
|
591
590
|
const compressed = level !== 0 && !directory;
|
|
592
|
-
const encrypted = Boolean(password && password
|
|
591
|
+
const encrypted = Boolean(password && getLength(password));
|
|
593
592
|
let rawExtraFieldAES;
|
|
594
593
|
if (encrypted && !zipCrypto) {
|
|
595
|
-
rawExtraFieldAES = new Uint8Array(EXTRAFIELD_DATA_AES
|
|
594
|
+
rawExtraFieldAES = new Uint8Array(getLength(EXTRAFIELD_DATA_AES) + 2);
|
|
596
595
|
const extraFieldAESView = getDataView(rawExtraFieldAES);
|
|
597
596
|
setUint16(extraFieldAESView, 0, EXTRAFIELD_TYPE_AES);
|
|
598
597
|
arraySet(rawExtraFieldAES, EXTRAFIELD_DATA_AES, 2);
|
|
@@ -606,7 +605,7 @@ function getHeaderInfo(options) {
|
|
|
606
605
|
rawExtraFieldExtendedTimestamp = new Uint8Array(9 + (lastAccessDate ? 4 : 0) + (creationDate ? 4 : 0));
|
|
607
606
|
const extraFieldExtendedTimestampView = getDataView(rawExtraFieldExtendedTimestamp);
|
|
608
607
|
setUint16(extraFieldExtendedTimestampView, 0, EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
|
|
609
|
-
setUint16(extraFieldExtendedTimestampView, 2, rawExtraFieldExtendedTimestamp
|
|
608
|
+
setUint16(extraFieldExtendedTimestampView, 2, getLength(rawExtraFieldExtendedTimestamp) - 4);
|
|
610
609
|
const extraFieldExtendedTimestampFlag = 0x1 + (lastAccessDate ? 0x2 : 0) + (creationDate ? 0x4 : 0);
|
|
611
610
|
setUint8(extraFieldExtendedTimestampView, 4, extraFieldExtendedTimestampFlag);
|
|
612
611
|
setUint32(extraFieldExtendedTimestampView, 5, Math.floor(options.lastModDate.getTime() / 1000));
|
|
@@ -673,18 +672,18 @@ function getHeaderInfo(options) {
|
|
|
673
672
|
setUint16(dateView, 2, ((((lastModDate.getFullYear() - 1980) << 4) | (lastModDate.getMonth() + 1)) << 5) | lastModDate.getDate());
|
|
674
673
|
const rawLastModDate = dateArray[0];
|
|
675
674
|
setUint32(headerView, 6, rawLastModDate);
|
|
676
|
-
setUint16(headerView, 22, rawFilename
|
|
677
|
-
const extraFieldLength = rawExtraFieldAES
|
|
675
|
+
setUint16(headerView, 22, getLength(rawFilename));
|
|
676
|
+
const extraFieldLength = getLength(rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraField);
|
|
678
677
|
setUint16(headerView, 24, extraFieldLength);
|
|
679
|
-
const localHeaderArray = new Uint8Array(30 + rawFilename
|
|
678
|
+
const localHeaderArray = new Uint8Array(30 + getLength(rawFilename) + extraFieldLength);
|
|
680
679
|
const localHeaderView = getDataView(localHeaderArray);
|
|
681
680
|
setUint32(localHeaderView, 0, LOCAL_FILE_HEADER_SIGNATURE);
|
|
682
681
|
arraySet(localHeaderArray, headerArray, 4);
|
|
683
682
|
arraySet(localHeaderArray, rawFilename, 30);
|
|
684
|
-
arraySet(localHeaderArray, rawExtraFieldAES, 30 + rawFilename
|
|
685
|
-
arraySet(localHeaderArray, rawExtraFieldExtendedTimestamp, 30 + rawFilename
|
|
686
|
-
arraySet(localHeaderArray, rawExtraFieldNTFS, 30 + rawFilename
|
|
687
|
-
arraySet(localHeaderArray, rawExtraField, 30 + rawFilename
|
|
683
|
+
arraySet(localHeaderArray, rawExtraFieldAES, 30 + getLength(rawFilename));
|
|
684
|
+
arraySet(localHeaderArray, rawExtraFieldExtendedTimestamp, 30 + getLength(rawFilename, rawExtraFieldAES));
|
|
685
|
+
arraySet(localHeaderArray, rawExtraFieldNTFS, 30 + getLength(rawFilename, rawExtraFieldAES, rawExtraFieldExtendedTimestamp));
|
|
686
|
+
arraySet(localHeaderArray, rawExtraField, 30 + getLength(rawFilename, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS));
|
|
688
687
|
return {
|
|
689
688
|
localHeaderArray,
|
|
690
689
|
headerArray,
|
|
@@ -782,13 +781,14 @@ async function closeFile(zipWriter, comment, options) {
|
|
|
782
781
|
let filesLength = files.size;
|
|
783
782
|
for (const [, fileEntry] of files) {
|
|
784
783
|
directoryDataLength += 46 +
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
784
|
+
getLength(
|
|
785
|
+
fileEntry.rawFilename,
|
|
786
|
+
fileEntry.rawComment,
|
|
787
|
+
fileEntry.rawExtraFieldZip64,
|
|
788
|
+
fileEntry.rawExtraFieldAES,
|
|
789
|
+
fileEntry.rawExtraFieldExtendedTimestamp,
|
|
790
|
+
fileEntry.rawExtraFieldNTFS,
|
|
791
|
+
fileEntry.rawExtraField);
|
|
792
792
|
}
|
|
793
793
|
let zip64 = options.zip64 || zipWriter.options.zip64 || false;
|
|
794
794
|
if (directoryOffset >= MAX_32_BITS || directoryDataLength >= MAX_32_BITS || filesLength >= MAX_16_BITS) {
|
|
@@ -822,18 +822,18 @@ async function closeFile(zipWriter, comment, options) {
|
|
|
822
822
|
rawExtraFieldExtendedTimestamp = new Uint8Array(9);
|
|
823
823
|
const extraFieldExtendedTimestampView = getDataView(rawExtraFieldExtendedTimestamp);
|
|
824
824
|
setUint16(extraFieldExtendedTimestampView, 0, EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
|
|
825
|
-
setUint16(extraFieldExtendedTimestampView, 2, rawExtraFieldExtendedTimestamp
|
|
825
|
+
setUint16(extraFieldExtendedTimestampView, 2, getLength(rawExtraFieldExtendedTimestamp) - 4);
|
|
826
826
|
setUint8(extraFieldExtendedTimestampView, 4, 0x1);
|
|
827
827
|
setUint32(extraFieldExtendedTimestampView, 5, Math.floor(fileEntry.lastModDate.getTime() / 1000));
|
|
828
828
|
} else {
|
|
829
829
|
rawExtraFieldNTFS = rawExtraFieldExtendedTimestamp = new Uint8Array();
|
|
830
830
|
}
|
|
831
|
-
const extraFieldLength = rawExtraFieldZip64
|
|
831
|
+
const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraField);
|
|
832
832
|
setUint32(directoryView, offset, CENTRAL_FILE_HEADER_SIGNATURE);
|
|
833
833
|
setUint16(directoryView, offset + 4, versionMadeBy);
|
|
834
834
|
arraySet(directoryArray, headerArray, offset + 6);
|
|
835
835
|
setUint16(directoryView, offset + 30, extraFieldLength);
|
|
836
|
-
setUint16(directoryView, offset + 32, rawComment
|
|
836
|
+
setUint16(directoryView, offset + 32, getLength(rawComment));
|
|
837
837
|
setUint16(directoryView, offset + 36, internalFileAttribute);
|
|
838
838
|
if (externalFileAttribute) {
|
|
839
839
|
setUint32(directoryView, offset + 38, externalFileAttribute);
|
|
@@ -846,13 +846,13 @@ async function closeFile(zipWriter, comment, options) {
|
|
|
846
846
|
setUint32(directoryView, offset + 42, fileEntry.offset);
|
|
847
847
|
}
|
|
848
848
|
arraySet(directoryArray, rawFilename, offset + 46);
|
|
849
|
-
arraySet(directoryArray, rawExtraFieldZip64, offset + 46 + rawFilename
|
|
850
|
-
arraySet(directoryArray, rawExtraFieldAES, offset + 46 + rawFilename
|
|
851
|
-
arraySet(directoryArray, rawExtraFieldExtendedTimestamp, offset + 46 + rawFilename
|
|
852
|
-
arraySet(directoryArray, rawExtraFieldNTFS, offset + 46 + rawFilename
|
|
853
|
-
arraySet(directoryArray, rawExtraField, offset + 46 + rawFilename
|
|
854
|
-
arraySet(directoryArray, rawComment, offset + 46 + rawFilename
|
|
855
|
-
offset += 46 + rawFilename
|
|
849
|
+
arraySet(directoryArray, rawExtraFieldZip64, offset + 46 + getLength(rawFilename));
|
|
850
|
+
arraySet(directoryArray, rawExtraFieldAES, offset + 46 + getLength(rawFilename, rawExtraFieldZip64));
|
|
851
|
+
arraySet(directoryArray, rawExtraFieldExtendedTimestamp, offset + 46 + getLength(rawFilename, rawExtraFieldZip64, rawExtraFieldAES));
|
|
852
|
+
arraySet(directoryArray, rawExtraFieldNTFS, offset + 46 + getLength(rawFilename, rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp));
|
|
853
|
+
arraySet(directoryArray, rawExtraField, offset + 46 + getLength(rawFilename, rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS));
|
|
854
|
+
arraySet(directoryArray, rawComment, offset + 46 + getLength(rawFilename) + extraFieldLength);
|
|
855
|
+
offset += 46 + getLength(rawFilename, rawComment) + extraFieldLength;
|
|
856
856
|
if (options.onprogress) {
|
|
857
857
|
try {
|
|
858
858
|
await options.onprogress(indexFileEntry + 1, files.size, new Entry(fileEntry));
|
|
@@ -883,9 +883,10 @@ async function closeFile(zipWriter, comment, options) {
|
|
|
883
883
|
setUint16(directoryView, offset + 10, filesLength);
|
|
884
884
|
setUint32(directoryView, offset + 12, directoryDataLength);
|
|
885
885
|
setUint32(directoryView, offset + 16, directoryOffset);
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
886
|
+
const commentLength = getLength(comment);
|
|
887
|
+
if (commentLength) {
|
|
888
|
+
if (commentLength <= MAX_16_BITS) {
|
|
889
|
+
setUint16(directoryView, offset + 20, commentLength);
|
|
889
890
|
} else {
|
|
890
891
|
throw new Error(ERR_INVALID_COMMENT);
|
|
891
892
|
}
|
|
@@ -893,7 +894,7 @@ async function closeFile(zipWriter, comment, options) {
|
|
|
893
894
|
const { writable } = zipWriter.writer;
|
|
894
895
|
await initStream(zipWriter.writer);
|
|
895
896
|
await writeData(writable, directoryArray);
|
|
896
|
-
if (
|
|
897
|
+
if (commentLength) {
|
|
897
898
|
await writeData(writable, comment);
|
|
898
899
|
}
|
|
899
900
|
}
|
|
@@ -909,7 +910,7 @@ function sliceAsArrayBuffer(blob, start, end) {
|
|
|
909
910
|
async function writeData(writable, array) {
|
|
910
911
|
const streamWriter = writable.getWriter();
|
|
911
912
|
await streamWriter.ready;
|
|
912
|
-
writable.size += array
|
|
913
|
+
writable.size += getLength(array);
|
|
913
914
|
await streamWriter.write(array);
|
|
914
915
|
streamWriter.releaseLock();
|
|
915
916
|
}
|
|
@@ -950,4 +951,10 @@ function arraySet(array, typedArray, offset) {
|
|
|
950
951
|
|
|
951
952
|
function getDataView(array) {
|
|
952
953
|
return new DataView(array.buffer);
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
function getLength(...arrayLikes) {
|
|
957
|
+
let result = 0;
|
|
958
|
+
arrayLikes.forEach(arrayLike => arrayLike && (result += arrayLike.length));
|
|
959
|
+
return result;
|
|
953
960
|
}
|