@zip.js/zip.js 2.6.33 → 2.6.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/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 +2483 -2364
- package/dist/zip-fs-full.min.js +1 -1
- package/dist/zip-fs.js +1241 -1122
- package/dist/zip-fs.min.js +1 -1
- package/dist/zip-full.js +1238 -1119
- 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 +1242 -1123
- package/dist/zip.min.js +1 -1
- package/index-fflate.js +3 -1
- package/index.cjs +2483 -2364
- package/index.d.ts +51 -6
- package/index.js +3 -1
- package/lib/core/codec-pool.js +2 -2
- package/lib/core/codec-worker.js +321 -0
- package/lib/core/configuration.js +3 -3
- package/lib/core/constants.js +6 -5
- package/lib/core/io.js +68 -1
- package/lib/core/streams/aes-crypto-stream.js +2 -0
- package/lib/core/streams/codec-stream.js +60 -13
- package/lib/core/streams/codecs/sjcl.js +1 -1
- package/lib/core/streams/stream-adapter.js +55 -0
- package/lib/core/streams/zip-crypto-stream.js +1 -0
- package/lib/core/streams/zip-entry-stream.js +1 -0
- package/lib/core/util/stream-codec-shim.js +2 -0
- package/lib/core/z-worker-core.js +21 -11
- package/lib/core/zip-entry.js +2 -1
- package/lib/core/zip-fs-core.js +1 -0
- package/lib/core/zip-reader.js +7 -5
- package/lib/core/zip-writer.js +88 -42
- package/lib/z-worker-inline.js +1 -1
- package/lib/zip.js +1 -1
- package/package.json +5 -5
- package/tests/all/test-http-split-zip.js +37 -0
- package/tests/all/test-split-zip.js +25 -22
- package/tests/tests-data.js +2 -1
- package/lib/core/codec-interface.js +0 -115
- package/lib/core/codec-pool-worker.js +0 -293
|
@@ -34,25 +34,72 @@
|
|
|
34
34
|
*/
|
|
35
35
|
|
|
36
36
|
/* global TransformStream */
|
|
37
|
+
// deno-lint-ignore-file no-this-alias
|
|
38
|
+
|
|
39
|
+
import {
|
|
40
|
+
ERR_INVALID_PASSWORD,
|
|
41
|
+
ERR_INVALID_SIGNATURE,
|
|
42
|
+
InflateStream,
|
|
43
|
+
DeflateStream
|
|
44
|
+
} from "./zip-entry-stream.js";
|
|
45
|
+
|
|
46
|
+
const MESSAGE_EVENT_TYPE = "message";
|
|
47
|
+
const MESSAGE_START = "start";
|
|
48
|
+
const MESSAGE_PULL = "pull";
|
|
49
|
+
const MESSAGE_DATA = "data";
|
|
50
|
+
const MESSAGE_ACK_DATA = "ack";
|
|
51
|
+
const MESSAGE_CLOSE = "close";
|
|
52
|
+
const CODEC_DEFLATE = "deflate";
|
|
53
|
+
const CODEC_INFLATE = "inflate";
|
|
54
|
+
|
|
55
|
+
export {
|
|
56
|
+
CODEC_DEFLATE,
|
|
57
|
+
CODEC_INFLATE,
|
|
58
|
+
MESSAGE_EVENT_TYPE,
|
|
59
|
+
MESSAGE_START,
|
|
60
|
+
MESSAGE_PULL,
|
|
61
|
+
MESSAGE_DATA,
|
|
62
|
+
MESSAGE_ACK_DATA,
|
|
63
|
+
MESSAGE_CLOSE,
|
|
64
|
+
ERR_INVALID_PASSWORD,
|
|
65
|
+
ERR_INVALID_SIGNATURE,
|
|
66
|
+
CodecStream
|
|
67
|
+
};
|
|
37
68
|
|
|
38
69
|
class CodecStream extends TransformStream {
|
|
39
70
|
|
|
40
|
-
constructor(
|
|
41
|
-
|
|
42
|
-
|
|
71
|
+
constructor(options, config) {
|
|
72
|
+
super({});
|
|
73
|
+
const codec = this;
|
|
74
|
+
const { codecType } = options;
|
|
75
|
+
let Stream;
|
|
76
|
+
if (codecType.startsWith(CODEC_DEFLATE)) {
|
|
77
|
+
Stream = DeflateStream;
|
|
78
|
+
} else if (codecType.startsWith(CODEC_INFLATE)) {
|
|
79
|
+
Stream = InflateStream;
|
|
80
|
+
}
|
|
81
|
+
let size = 0;
|
|
82
|
+
const stream = new Stream(options, config);
|
|
83
|
+
const readable = super.readable;
|
|
84
|
+
const transformStream = new TransformStream({
|
|
43
85
|
transform(chunk, controller) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
flush(controller) {
|
|
47
|
-
const chunk = codec.flush();
|
|
48
|
-
if (chunk) {
|
|
86
|
+
if (chunk && chunk.length) {
|
|
87
|
+
size += chunk.length;
|
|
49
88
|
controller.enqueue(chunk);
|
|
50
89
|
}
|
|
90
|
+
},
|
|
91
|
+
flush() {
|
|
92
|
+
const { signature } = stream;
|
|
93
|
+
Object.assign(codec, {
|
|
94
|
+
signature,
|
|
95
|
+
size
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
Object.defineProperty(codec, "readable", {
|
|
100
|
+
get() {
|
|
101
|
+
return readable.pipeThrough(stream).pipeThrough(transformStream);
|
|
51
102
|
}
|
|
52
103
|
});
|
|
53
104
|
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export {
|
|
57
|
-
CodecStream
|
|
58
|
-
};
|
|
105
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Derived from https://github.com/xqdoo00o/jszip/blob/master/lib/sjcl.js and https://github.com/bitwiseshiftleft/sjcl
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
// deno-lint-ignore-file no-this-alias
|
|
4
4
|
|
|
5
5
|
/*
|
|
6
6
|
* SJCL is open. You can use, modify and redistribute it under a BSD
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright (c) 2022 Gildas Lormeau. All rights reserved.
|
|
3
|
+
|
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
|
6
|
+
|
|
7
|
+
1. Redistributions of source code must retain the above copyright notice,
|
|
8
|
+
this list of conditions and the following disclaimer.
|
|
9
|
+
|
|
10
|
+
2. Redistributions in binary form must reproduce the above copyright
|
|
11
|
+
notice, this list of conditions and the following disclaimer in
|
|
12
|
+
the documentation and/or other materials provided with the distribution.
|
|
13
|
+
|
|
14
|
+
3. The names of the authors may not be used to endorse or promote products
|
|
15
|
+
derived from this software without specific prior written permission.
|
|
16
|
+
|
|
17
|
+
THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
|
18
|
+
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
19
|
+
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
|
20
|
+
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
21
|
+
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
22
|
+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
|
23
|
+
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
24
|
+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
25
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
|
26
|
+
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/* global TransformStream */
|
|
30
|
+
|
|
31
|
+
export {
|
|
32
|
+
StreamAdapter
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
class StreamAdapter {
|
|
36
|
+
|
|
37
|
+
constructor(Codec) {
|
|
38
|
+
return class extends TransformStream {
|
|
39
|
+
constructor(options) {
|
|
40
|
+
const codec = new Codec(options);
|
|
41
|
+
super({
|
|
42
|
+
transform(chunk, controller) {
|
|
43
|
+
controller.enqueue(codec.append(chunk));
|
|
44
|
+
},
|
|
45
|
+
flush(controller) {
|
|
46
|
+
const chunk = codec.flush();
|
|
47
|
+
if (chunk) {
|
|
48
|
+
controller.enqueue(chunk);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -29,23 +29,23 @@
|
|
|
29
29
|
/* global self, importScripts, addEventListener, postMessage, ReadableStream, WritableStream */
|
|
30
30
|
|
|
31
31
|
import { UNDEFINED_VALUE } from "./constants.js";
|
|
32
|
+
import { StreamAdapter } from "./streams/stream-adapter.js";
|
|
32
33
|
import {
|
|
33
|
-
|
|
34
|
-
getCodecStreamClass,
|
|
34
|
+
CodecStream,
|
|
35
35
|
MESSAGE_EVENT_TYPE,
|
|
36
36
|
MESSAGE_START,
|
|
37
37
|
MESSAGE_PULL,
|
|
38
38
|
MESSAGE_DATA,
|
|
39
39
|
MESSAGE_ACK_DATA,
|
|
40
40
|
MESSAGE_CLOSE
|
|
41
|
-
} from "./codec-
|
|
41
|
+
} from "./streams/codec-stream.js";
|
|
42
42
|
|
|
43
43
|
const pendingPullMessages = new Map();
|
|
44
44
|
const pendingDataMessages = new Map();
|
|
45
|
-
|
|
45
|
+
|
|
46
46
|
let messageId = 0;
|
|
47
47
|
|
|
48
|
-
addEventListener(MESSAGE_EVENT_TYPE,
|
|
48
|
+
addEventListener(MESSAGE_EVENT_TYPE, event => {
|
|
49
49
|
const message = event.data;
|
|
50
50
|
const { type, messageId, data, done } = message;
|
|
51
51
|
try {
|
|
@@ -79,15 +79,15 @@ async function init(message) {
|
|
|
79
79
|
config.CompressionStreamNative = self.CompressionStream;
|
|
80
80
|
config.DecompressionStreamNative = self.DecompressionStream;
|
|
81
81
|
if (self.Deflate) {
|
|
82
|
-
config.CompressionStream =
|
|
82
|
+
config.CompressionStream = new StreamAdapter(self.Deflate);
|
|
83
83
|
}
|
|
84
84
|
if (self.Inflate) {
|
|
85
|
-
config.DecompressionStream =
|
|
85
|
+
config.DecompressionStream = new StreamAdapter(self.Inflate);
|
|
86
86
|
}
|
|
87
87
|
const strategy = { highWaterMark: 1, size: () => config.chunkSize };
|
|
88
88
|
const readable = message.readable || new ReadableStream({
|
|
89
89
|
async pull(controller) {
|
|
90
|
-
|
|
90
|
+
const result = new Promise(resolve => pendingPullMessages.set(messageId, resolve));
|
|
91
91
|
sendMessage({ type: MESSAGE_PULL, messageId });
|
|
92
92
|
messageId = (messageId + 1) % Number.MAX_SAFE_INTEGER;
|
|
93
93
|
const { value, done } = await result;
|
|
@@ -107,14 +107,24 @@ async function init(message) {
|
|
|
107
107
|
await ackData;
|
|
108
108
|
}
|
|
109
109
|
}, strategy);
|
|
110
|
-
|
|
111
|
-
|
|
110
|
+
const codecStream = new CodecStream(options, config);
|
|
111
|
+
await readable.pipeThrough(codecStream).pipeTo(writable, { preventAbort: true });
|
|
112
112
|
try {
|
|
113
113
|
await writable.close();
|
|
114
114
|
} catch (_error) {
|
|
115
115
|
// ignored
|
|
116
116
|
}
|
|
117
|
-
|
|
117
|
+
const {
|
|
118
|
+
signature,
|
|
119
|
+
size
|
|
120
|
+
} = codecStream;
|
|
121
|
+
sendMessage({
|
|
122
|
+
type: MESSAGE_CLOSE,
|
|
123
|
+
result: {
|
|
124
|
+
signature,
|
|
125
|
+
size
|
|
126
|
+
}
|
|
127
|
+
});
|
|
118
128
|
} catch (error) {
|
|
119
129
|
sendErrorMessage(error);
|
|
120
130
|
}
|
package/lib/core/zip-entry.js
CHANGED
|
@@ -32,7 +32,8 @@ const PROPERTY_NAMES = [
|
|
|
32
32
|
"rawExtraField", "bitFlag", "extraFieldZip64", "extraFieldUnicodePath", "extraFieldUnicodeComment",
|
|
33
33
|
"extraFieldAES", "filenameUTF8", "commentUTF8", "offset", "zip64", "compressionMethod",
|
|
34
34
|
"extraFieldNTFS", "lastAccessDate", "creationDate", "extraFieldExtendedTimestamp",
|
|
35
|
-
"version", "versionMadeBy", "msDosCompatible", "internalFileAttribute", "externalFileAttribute"
|
|
35
|
+
"version", "versionMadeBy", "msDosCompatible", "internalFileAttribute", "externalFileAttribute",
|
|
36
|
+
"diskNumberStart"];
|
|
36
37
|
|
|
37
38
|
class Entry {
|
|
38
39
|
|
package/lib/core/zip-fs-core.js
CHANGED
package/lib/core/zip-reader.js
CHANGED
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
*/
|
|
28
28
|
|
|
29
29
|
/* global BigInt, Response, ReadableStream, WritableStream */
|
|
30
|
+
// deno-lint-ignore-file no-this-alias
|
|
30
31
|
|
|
31
32
|
import {
|
|
32
33
|
MAX_32_BITS,
|
|
@@ -34,6 +35,7 @@ import {
|
|
|
34
35
|
COMPRESSION_METHOD_DEFLATE,
|
|
35
36
|
COMPRESSION_METHOD_STORE,
|
|
36
37
|
COMPRESSION_METHOD_AES,
|
|
38
|
+
SPLIT_ZIP_FILE_SIGNATURE,
|
|
37
39
|
LOCAL_FILE_HEADER_SIGNATURE,
|
|
38
40
|
CENTRAL_FILE_HEADER_SIGNATURE,
|
|
39
41
|
END_OF_CENTRAL_DIR_SIGNATURE,
|
|
@@ -77,7 +79,6 @@ import { decodeText } from "./util/decode-text.js";
|
|
|
77
79
|
import { Crc32 } from "./streams/codecs/crc32.js";
|
|
78
80
|
import { Entry } from "./zip-entry.js";
|
|
79
81
|
|
|
80
|
-
const SPLIT_ZIP_FILE_SIGNATURE = 0x08074b50;
|
|
81
82
|
const ERR_BAD_FORMAT = "File format is not recognized";
|
|
82
83
|
const ERR_EOCDR_NOT_FOUND = "End of central directory not found";
|
|
83
84
|
const ERR_EOCDR_ZIP64_NOT_FOUND = "End of Zip64 central directory not found";
|
|
@@ -150,15 +151,16 @@ class ZipReader {
|
|
|
150
151
|
throw new Error(ERR_EOCDR_NOT_FOUND);
|
|
151
152
|
}
|
|
152
153
|
}
|
|
153
|
-
const { lastDiskNumber } = reader;
|
|
154
154
|
const endOfDirectoryView = getDataView(endOfDirectoryInfo);
|
|
155
155
|
let directoryDataLength = getUint32(endOfDirectoryView, 12);
|
|
156
156
|
let directoryDataOffset = getUint32(endOfDirectoryView, 16);
|
|
157
157
|
const commentOffset = endOfDirectoryInfo.offset;
|
|
158
158
|
const commentLength = getUint16(endOfDirectoryView, 20);
|
|
159
159
|
const appendedDataOffset = commentOffset + END_OF_CENTRAL_DIR_LENGTH + commentLength;
|
|
160
|
-
|
|
161
|
-
|
|
160
|
+
const lastDiskNumber = getUint16(endOfDirectoryView, 4);
|
|
161
|
+
const expectedLastDiskNumber = reader.lastDiskNumber || 0;
|
|
162
|
+
let diskNumber = getUint16(endOfDirectoryView, 6);
|
|
163
|
+
if (expectedLastDiskNumber != lastDiskNumber) {
|
|
162
164
|
throw new Error(ERR_SPLIT_ZIP_FILE);
|
|
163
165
|
}
|
|
164
166
|
let filesLength = getUint16(endOfDirectoryView, 8);
|
|
@@ -344,7 +346,7 @@ class ZipEntry {
|
|
|
344
346
|
compressedSize
|
|
345
347
|
} = zipEntry;
|
|
346
348
|
const localDirectory = zipEntry.localDirectory = {};
|
|
347
|
-
|
|
349
|
+
const dataArray = await readUint8Array(reader, offset, 30, diskNumberStart);
|
|
348
350
|
const dataView = getDataView(dataArray);
|
|
349
351
|
let password = getOptionValue(zipEntry, options, "password");
|
|
350
352
|
password = password && password.length && password;
|
package/lib/core/zip-writer.js
CHANGED
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
*/
|
|
28
28
|
|
|
29
29
|
/* global BigInt, ReadableStream, WritableStream */
|
|
30
|
+
// deno-lint-ignore-file no-this-alias
|
|
30
31
|
|
|
31
32
|
import {
|
|
32
33
|
MAX_32_BITS,
|
|
@@ -34,19 +35,21 @@ import {
|
|
|
34
35
|
COMPRESSION_METHOD_DEFLATE,
|
|
35
36
|
COMPRESSION_METHOD_STORE,
|
|
36
37
|
COMPRESSION_METHOD_AES,
|
|
38
|
+
SPLIT_ZIP_FILE_SIGNATURE,
|
|
37
39
|
LOCAL_FILE_HEADER_SIGNATURE,
|
|
38
40
|
DATA_DESCRIPTOR_RECORD_SIGNATURE,
|
|
39
41
|
CENTRAL_FILE_HEADER_SIGNATURE,
|
|
40
42
|
END_OF_CENTRAL_DIR_SIGNATURE,
|
|
41
43
|
ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIGNATURE,
|
|
42
44
|
ZIP64_END_OF_CENTRAL_DIR_SIGNATURE,
|
|
43
|
-
ZIP64_TOTAL_NUMBER_OF_DISKS,
|
|
44
45
|
EXTRAFIELD_TYPE_AES,
|
|
45
46
|
EXTRAFIELD_TYPE_ZIP64,
|
|
46
47
|
EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP,
|
|
47
48
|
EXTRAFIELD_TYPE_NTFS,
|
|
48
49
|
EXTRAFIELD_TYPE_NTFS_TAG1,
|
|
49
50
|
END_OF_CENTRAL_DIR_LENGTH,
|
|
51
|
+
ZIP64_END_OF_CENTRAL_DIR_LENGTH,
|
|
52
|
+
ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH,
|
|
50
53
|
ZIP64_END_OF_CENTRAL_DIR_TOTAL_LENGTH,
|
|
51
54
|
BITFLAG_ENCRYPTED,
|
|
52
55
|
BITFLAG_DATA_DESCRIPTOR,
|
|
@@ -58,7 +61,8 @@ import {
|
|
|
58
61
|
DIRECTORY_SIGNATURE,
|
|
59
62
|
MIN_DATE,
|
|
60
63
|
MAX_DATE,
|
|
61
|
-
UNDEFINED_VALUE
|
|
64
|
+
UNDEFINED_VALUE,
|
|
65
|
+
FUNCTION_TYPE
|
|
62
66
|
} from "./constants.js";
|
|
63
67
|
import {
|
|
64
68
|
getConfiguration,
|
|
@@ -70,7 +74,8 @@ import {
|
|
|
70
74
|
} from "./codec-pool.js";
|
|
71
75
|
import {
|
|
72
76
|
initStream,
|
|
73
|
-
BlobWriter
|
|
77
|
+
BlobWriter,
|
|
78
|
+
SplitZipWriter
|
|
74
79
|
} from "./io.js";
|
|
75
80
|
import { encodeText } from "./util/encode-text.js";
|
|
76
81
|
import { Entry } from "./zip-entry.js";
|
|
@@ -86,7 +91,7 @@ const ERR_INVALID_EXTRAFIELD_DATA = "Extra field data exceeds 64KB";
|
|
|
86
91
|
const ERR_UNSUPPORTED_FORMAT = "Zip64 is not supported (make sure 'keepOrder' is set to 'true')";
|
|
87
92
|
|
|
88
93
|
const EXTRAFIELD_DATA_AES = new Uint8Array([0x07, 0x00, 0x02, 0x00, 0x41, 0x45, 0x03, 0x00, 0x00]);
|
|
89
|
-
const EXTRAFIELD_LENGTH_ZIP64 =
|
|
94
|
+
const EXTRAFIELD_LENGTH_ZIP64 = 28;
|
|
90
95
|
|
|
91
96
|
let workers = 0;
|
|
92
97
|
const pendingEntries = [];
|
|
@@ -94,14 +99,26 @@ const pendingEntries = [];
|
|
|
94
99
|
class ZipWriter {
|
|
95
100
|
|
|
96
101
|
constructor(writer, options = {}) {
|
|
102
|
+
if (writer.writable === UNDEFINED_VALUE && typeof writer.next == FUNCTION_TYPE) {
|
|
103
|
+
writer = new SplitZipWriter(writer);
|
|
104
|
+
}
|
|
97
105
|
if (writer instanceof WritableStream) {
|
|
98
106
|
writer = { writable: writer };
|
|
99
107
|
}
|
|
100
108
|
if (writer.writable.size === UNDEFINED_VALUE) {
|
|
101
109
|
writer.writable.size = 0;
|
|
102
110
|
}
|
|
111
|
+
const splitZipFile = writer instanceof SplitZipWriter;
|
|
112
|
+
if (!splitZipFile) {
|
|
113
|
+
Object.assign(writer, {
|
|
114
|
+
diskNumber: 0,
|
|
115
|
+
diskOffset: 0,
|
|
116
|
+
availableSize: Infinity
|
|
117
|
+
});
|
|
118
|
+
}
|
|
103
119
|
Object.assign(this, {
|
|
104
120
|
writer,
|
|
121
|
+
addSplitZipSignature: splitZipFile,
|
|
105
122
|
options,
|
|
106
123
|
config: getConfiguration(),
|
|
107
124
|
files: new Map(),
|
|
@@ -366,10 +383,21 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
|
366
383
|
releaseLockWriter = () => delete zipWriter.lockWriter;
|
|
367
384
|
}
|
|
368
385
|
await initStream(fileWriter);
|
|
386
|
+
const { writable, diskNumber } = writer;
|
|
387
|
+
let { diskOffset } = writer;
|
|
388
|
+
if (zipWriter.addSplitZipSignature) {
|
|
389
|
+
delete zipWriter.addSplitZipSignature;
|
|
390
|
+
const signatureArray = new Uint8Array(4);
|
|
391
|
+
const signatureArrayView = new DataView(signatureArray.buffer);
|
|
392
|
+
setUint32(signatureArrayView, 0, SPLIT_ZIP_FILE_SIGNATURE);
|
|
393
|
+
await writeData(writable, signatureArray);
|
|
394
|
+
zipWriter.offset += 4;
|
|
395
|
+
}
|
|
369
396
|
if (!bufferedWrite) {
|
|
370
397
|
await lockPreviousFileEntry;
|
|
371
398
|
}
|
|
372
399
|
writingEntryData = true;
|
|
400
|
+
fileEntry.diskNumberStart = diskNumber;
|
|
373
401
|
fileEntry = await createFileEntry(reader, fileWriter, fileEntry, entryInfo, zipWriter.config, options);
|
|
374
402
|
writingEntryData = false;
|
|
375
403
|
files.set(name, fileEntry);
|
|
@@ -380,7 +408,6 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
|
380
408
|
await lockPreviousFileEntry;
|
|
381
409
|
await requestLockWriter();
|
|
382
410
|
writingBufferedEntryData = true;
|
|
383
|
-
const { writable } = writer;
|
|
384
411
|
if (!dataDescriptor) {
|
|
385
412
|
const arrayBuffer = await sliceAsArrayBuffer(blob, 0, 26);
|
|
386
413
|
const arrayBufferView = new DataView(arrayBuffer);
|
|
@@ -397,13 +424,18 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
|
397
424
|
await writeData(writable, new Uint8Array(arrayBuffer));
|
|
398
425
|
blob = blob.slice(arrayBuffer.byteLength);
|
|
399
426
|
}
|
|
427
|
+
fileEntry.diskNumberStart = writer.diskNumber;
|
|
428
|
+
diskOffset = writer.diskOffset;
|
|
400
429
|
await blob.stream().pipeTo(writable, { preventClose: true, signal });
|
|
430
|
+
writable.size += blob.size;
|
|
401
431
|
writingBufferedEntryData = false;
|
|
402
432
|
}
|
|
403
|
-
fileEntry.offset = zipWriter.offset;
|
|
433
|
+
fileEntry.offset = zipWriter.offset - diskOffset;
|
|
404
434
|
if (fileEntry.zip64) {
|
|
405
|
-
const
|
|
406
|
-
|
|
435
|
+
const { rawExtraFieldZip64, offset, diskNumberStart } = fileEntry;
|
|
436
|
+
const rawExtraFieldZip64View = getDataView(rawExtraFieldZip64);
|
|
437
|
+
setBigUint64(rawExtraFieldZip64View, 20, BigInt(offset));
|
|
438
|
+
setUint32(rawExtraFieldZip64View, 28, diskNumberStart);
|
|
407
439
|
} else if (fileEntry.offset >= MAX_32_BITS) {
|
|
408
440
|
throw new Error(ERR_UNSUPPORTED_FORMAT);
|
|
409
441
|
}
|
|
@@ -447,7 +479,7 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
|
447
479
|
}
|
|
448
480
|
}
|
|
449
481
|
|
|
450
|
-
async function createFileEntry(reader, writer,
|
|
482
|
+
async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryInfo, config, options) {
|
|
451
483
|
const {
|
|
452
484
|
headerInfo,
|
|
453
485
|
dataDescriptorInfo
|
|
@@ -492,7 +524,7 @@ async function createFileEntry(reader, writer, pendingFileEntry, entryInfo, conf
|
|
|
492
524
|
useCompressionStream
|
|
493
525
|
} = options;
|
|
494
526
|
const fileEntry = {
|
|
495
|
-
lock
|
|
527
|
+
lock,
|
|
496
528
|
versionMadeBy,
|
|
497
529
|
zip64,
|
|
498
530
|
directory: Boolean(directory),
|
|
@@ -507,7 +539,8 @@ async function createFileEntry(reader, writer, pendingFileEntry, entryInfo, conf
|
|
|
507
539
|
extendedTimestamp,
|
|
508
540
|
msDosCompatible,
|
|
509
541
|
internalFileAttribute,
|
|
510
|
-
externalFileAttribute
|
|
542
|
+
externalFileAttribute,
|
|
543
|
+
diskNumberStart
|
|
511
544
|
};
|
|
512
545
|
let uncompressedSize = 0;
|
|
513
546
|
let signature;
|
|
@@ -779,10 +812,12 @@ function setEntryInfo(entryInfo, options) {
|
|
|
779
812
|
}
|
|
780
813
|
|
|
781
814
|
async function closeFile(zipWriter, comment, options) {
|
|
782
|
-
const { files } = zipWriter;
|
|
815
|
+
const { files, writer } = zipWriter;
|
|
783
816
|
let offset = 0;
|
|
784
817
|
let directoryDataLength = 0;
|
|
785
|
-
|
|
818
|
+
const { diskOffset, writable } = writer;
|
|
819
|
+
let { diskNumber } = writer;
|
|
820
|
+
let directoryOffset = zipWriter.offset - diskOffset;
|
|
786
821
|
let filesLength = files.size;
|
|
787
822
|
for (const [, {
|
|
788
823
|
rawFilename,
|
|
@@ -811,7 +846,7 @@ async function closeFile(zipWriter, comment, options) {
|
|
|
811
846
|
zip64 = true;
|
|
812
847
|
}
|
|
813
848
|
}
|
|
814
|
-
const directoryArray = new Uint8Array(directoryDataLength
|
|
849
|
+
const directoryArray = new Uint8Array(directoryDataLength);
|
|
815
850
|
const directoryView = getDataView(directoryArray);
|
|
816
851
|
for (const [indexFileEntry, fileEntry] of Array.from(files.values()).entries()) {
|
|
817
852
|
const {
|
|
@@ -830,7 +865,8 @@ async function closeFile(zipWriter, comment, options) {
|
|
|
830
865
|
internalFileAttribute,
|
|
831
866
|
externalFileAttribute,
|
|
832
867
|
extendedTimestamp,
|
|
833
|
-
lastModDate
|
|
868
|
+
lastModDate,
|
|
869
|
+
diskNumberStart
|
|
834
870
|
} = fileEntry;
|
|
835
871
|
let rawExtraFieldExtendedTimestamp;
|
|
836
872
|
if (extendedTimestamp) {
|
|
@@ -849,17 +885,14 @@ async function closeFile(zipWriter, comment, options) {
|
|
|
849
885
|
arraySet(directoryArray, headerArray, offset + 6);
|
|
850
886
|
setUint16(directoryView, offset + 30, extraFieldLength);
|
|
851
887
|
setUint16(directoryView, offset + 32, getLength(rawComment));
|
|
888
|
+
setUint16(directoryView, offset + 34, zip64 ? MAX_16_BITS : diskNumberStart);
|
|
852
889
|
setUint16(directoryView, offset + 36, internalFileAttribute);
|
|
853
890
|
if (externalFileAttribute) {
|
|
854
891
|
setUint32(directoryView, offset + 38, externalFileAttribute);
|
|
855
892
|
} else if (directory && msDosCompatible) {
|
|
856
893
|
setUint8(directoryView, offset + 38, FILE_ATTR_MSDOS_DIR_MASK);
|
|
857
894
|
}
|
|
858
|
-
|
|
859
|
-
setUint32(directoryView, offset + 42, MAX_32_BITS);
|
|
860
|
-
} else {
|
|
861
|
-
setUint32(directoryView, offset + 42, fileEntryOffset);
|
|
862
|
-
}
|
|
895
|
+
setUint32(directoryView, offset + 42, zip64 ? MAX_32_BITS : fileEntryOffset);
|
|
863
896
|
arraySet(directoryArray, rawFilename, offset + 46);
|
|
864
897
|
arraySet(directoryArray, rawExtraFieldZip64, offset + 46 + getLength(rawFilename));
|
|
865
898
|
arraySet(directoryArray, rawExtraFieldAES, offset + 46 + getLength(rawFilename, rawExtraFieldZip64));
|
|
@@ -876,39 +909,52 @@ async function closeFile(zipWriter, comment, options) {
|
|
|
876
909
|
}
|
|
877
910
|
}
|
|
878
911
|
}
|
|
912
|
+
await initStream(writer);
|
|
913
|
+
await writeData(writable, directoryArray);
|
|
914
|
+
const endOfdirectoryArray = new Uint8Array(zip64 ? ZIP64_END_OF_CENTRAL_DIR_TOTAL_LENGTH : END_OF_CENTRAL_DIR_LENGTH);
|
|
915
|
+
const endOfdirectoryView = getDataView(endOfdirectoryArray);
|
|
916
|
+
let lastDiskNumber = writer.diskNumber;
|
|
917
|
+
const { availableSize } = writer;
|
|
918
|
+
if (availableSize < endOfdirectoryArray.length) {
|
|
919
|
+
lastDiskNumber++;
|
|
920
|
+
}
|
|
921
|
+
offset = 0;
|
|
879
922
|
if (zip64) {
|
|
880
|
-
setUint32(
|
|
881
|
-
setBigUint64(
|
|
882
|
-
setUint16(
|
|
883
|
-
setUint16(
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
setBigUint64(
|
|
887
|
-
setBigUint64(
|
|
888
|
-
|
|
889
|
-
setBigUint64(
|
|
890
|
-
setUint32(
|
|
923
|
+
setUint32(endOfdirectoryView, 0, ZIP64_END_OF_CENTRAL_DIR_SIGNATURE);
|
|
924
|
+
setBigUint64(endOfdirectoryView, 4, BigInt(44));
|
|
925
|
+
setUint16(endOfdirectoryView, 12, 45);
|
|
926
|
+
setUint16(endOfdirectoryView, 14, 45);
|
|
927
|
+
setUint32(endOfdirectoryView, 16, lastDiskNumber);
|
|
928
|
+
setUint32(endOfdirectoryView, 20, diskNumber);
|
|
929
|
+
setBigUint64(endOfdirectoryView, 24, BigInt(filesLength));
|
|
930
|
+
setBigUint64(endOfdirectoryView, 32, BigInt(filesLength));
|
|
931
|
+
setBigUint64(endOfdirectoryView, 40, BigInt(directoryDataLength));
|
|
932
|
+
setBigUint64(endOfdirectoryView, 48, BigInt(directoryOffset));
|
|
933
|
+
setUint32(endOfdirectoryView, 56, ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIGNATURE);
|
|
934
|
+
setBigUint64(endOfdirectoryView, 64, BigInt(directoryOffset) + BigInt(directoryDataLength));
|
|
935
|
+
setUint32(endOfdirectoryView, 72, lastDiskNumber + 1);
|
|
936
|
+
diskNumber = MAX_16_BITS;
|
|
891
937
|
filesLength = MAX_16_BITS;
|
|
892
938
|
directoryOffset = MAX_32_BITS;
|
|
893
939
|
directoryDataLength = MAX_32_BITS;
|
|
894
|
-
offset +=
|
|
895
|
-
}
|
|
896
|
-
setUint32(
|
|
897
|
-
setUint16(
|
|
898
|
-
setUint16(
|
|
899
|
-
|
|
900
|
-
|
|
940
|
+
offset += ZIP64_END_OF_CENTRAL_DIR_LENGTH + ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH;
|
|
941
|
+
}
|
|
942
|
+
setUint32(endOfdirectoryView, offset, END_OF_CENTRAL_DIR_SIGNATURE);
|
|
943
|
+
setUint16(endOfdirectoryView, offset + 4, lastDiskNumber);
|
|
944
|
+
setUint16(endOfdirectoryView, offset + 6, diskNumber);
|
|
945
|
+
setUint16(endOfdirectoryView, offset + 8, filesLength);
|
|
946
|
+
setUint16(endOfdirectoryView, offset + 10, filesLength);
|
|
947
|
+
setUint32(endOfdirectoryView, offset + 12, directoryDataLength);
|
|
948
|
+
setUint32(endOfdirectoryView, offset + 16, directoryOffset);
|
|
901
949
|
const commentLength = getLength(comment);
|
|
902
950
|
if (commentLength) {
|
|
903
951
|
if (commentLength <= MAX_16_BITS) {
|
|
904
|
-
setUint16(
|
|
952
|
+
setUint16(endOfdirectoryView, offset + 20, commentLength);
|
|
905
953
|
} else {
|
|
906
954
|
throw new Error(ERR_INVALID_COMMENT);
|
|
907
955
|
}
|
|
908
956
|
}
|
|
909
|
-
|
|
910
|
-
await initStream(zipWriter.writer);
|
|
911
|
-
await writeData(writable, directoryArray);
|
|
957
|
+
await writeData(writable, endOfdirectoryArray);
|
|
912
958
|
if (commentLength) {
|
|
913
959
|
await writeData(writable, comment);
|
|
914
960
|
}
|