@zip.js/zip.js 2.7.33 → 2.7.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 +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 +171 -87
- package/dist/zip-fs-full.min.js +1 -1
- package/dist/zip-fs.js +171 -87
- package/dist/zip-fs.min.js +1 -1
- package/dist/zip-full.js +168 -84
- 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 +168 -84
- package/dist/zip.min.js +1 -1
- package/index.cjs +171 -87
- package/index.d.ts +131 -9
- package/index.js +5 -3
- package/index.min.js +1 -1
- package/lib/core/codec-pool.js +36 -28
- package/lib/core/codec-worker.js +4 -4
- package/lib/core/io.js +16 -15
- package/lib/core/streams/aes-crypto-stream.js +14 -8
- package/lib/core/streams/common-crypto.js +2 -1
- package/lib/core/util/encode-text.js +3 -1
- package/lib/core/util/stream-codec-shim.js +4 -2
- package/lib/core/zip-fs-core.js +2 -1
- package/lib/core/zip-reader.js +39 -7
- package/lib/core/zip-writer.js +52 -16
- package/lib/z-worker-bootstrap-fflate.js +2 -1
- package/lib/z-worker-inline.js +1 -1
- package/lib/zip-fflate-shim.js +3 -1
- package/lib/zip-fs.js +3 -3
- package/package.json +1 -1
package/lib/core/codec-pool.js
CHANGED
|
@@ -56,26 +56,28 @@ let indexWorker = 0;
|
|
|
56
56
|
async function runWorker(stream, workerOptions) {
|
|
57
57
|
const { options, config } = workerOptions;
|
|
58
58
|
const { transferStreams, useWebWorkers, useCompressionStream, codecType, compressed, signed, encrypted } = options;
|
|
59
|
-
const { workerScripts, maxWorkers
|
|
59
|
+
const { workerScripts, maxWorkers } = config;
|
|
60
60
|
workerOptions.transferStreams = transferStreams || transferStreams === UNDEFINED_VALUE;
|
|
61
61
|
const streamCopy = !compressed && !signed && !encrypted && !workerOptions.transferStreams;
|
|
62
62
|
workerOptions.useWebWorkers = !streamCopy && (useWebWorkers || (useWebWorkers === UNDEFINED_VALUE && config.useWebWorkers));
|
|
63
63
|
workerOptions.scripts = workerOptions.useWebWorkers && workerScripts ? workerScripts[codecType] : [];
|
|
64
64
|
options.useCompressionStream = useCompressionStream || (useCompressionStream === UNDEFINED_VALUE && config.useCompressionStream);
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
65
|
+
return (await getWorker()).run();
|
|
66
|
+
|
|
67
|
+
async function getWorker() {
|
|
68
|
+
const workerData = pool.find(workerData => !workerData.busy);
|
|
69
|
+
if (workerData) {
|
|
70
|
+
clearTerminateTimeout(workerData);
|
|
71
|
+
return new CodecWorker(workerData, stream, workerOptions, onTaskFinished);
|
|
72
|
+
} else if (pool.length < maxWorkers) {
|
|
73
|
+
const workerData = { indexWorker };
|
|
74
|
+
indexWorker++;
|
|
75
|
+
pool.push(workerData);
|
|
76
|
+
return new CodecWorker(workerData, stream, workerOptions, onTaskFinished);
|
|
77
|
+
} else {
|
|
78
|
+
return new Promise(resolve => pendingRequests.push({ resolve, stream, workerOptions }));
|
|
79
|
+
}
|
|
77
80
|
}
|
|
78
|
-
return worker.run();
|
|
79
81
|
|
|
80
82
|
function onTaskFinished(workerData) {
|
|
81
83
|
if (pendingRequests.length) {
|
|
@@ -83,26 +85,32 @@ async function runWorker(stream, workerOptions) {
|
|
|
83
85
|
resolve(new CodecWorker(workerData, stream, workerOptions, onTaskFinished));
|
|
84
86
|
} else if (workerData.worker) {
|
|
85
87
|
clearTerminateTimeout(workerData);
|
|
86
|
-
|
|
87
|
-
if (workerData.terminated) {
|
|
88
|
-
workerData.terminated = false;
|
|
89
|
-
} else {
|
|
90
|
-
workerData.terminateTimeout = setTimeout(async () => {
|
|
91
|
-
pool = pool.filter(data => data != workerData);
|
|
92
|
-
try {
|
|
93
|
-
await workerData.terminate();
|
|
94
|
-
} catch (_error) {
|
|
95
|
-
// ignored
|
|
96
|
-
}
|
|
97
|
-
}, terminateWorkerTimeout);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
88
|
+
terminateWorker(workerData, workerOptions);
|
|
100
89
|
} else {
|
|
101
90
|
pool = pool.filter(data => data != workerData);
|
|
102
91
|
}
|
|
103
92
|
}
|
|
104
93
|
}
|
|
105
94
|
|
|
95
|
+
function terminateWorker(workerData, workerOptions) {
|
|
96
|
+
const { config } = workerOptions;
|
|
97
|
+
const { terminateWorkerTimeout } = config;
|
|
98
|
+
if (Number.isFinite(terminateWorkerTimeout) && terminateWorkerTimeout >= 0) {
|
|
99
|
+
if (workerData.terminated) {
|
|
100
|
+
workerData.terminated = false;
|
|
101
|
+
} else {
|
|
102
|
+
workerData.terminateTimeout = setTimeout(async () => {
|
|
103
|
+
pool = pool.filter(data => data != workerData);
|
|
104
|
+
try {
|
|
105
|
+
await workerData.terminate();
|
|
106
|
+
} catch (_error) {
|
|
107
|
+
// ignored
|
|
108
|
+
}
|
|
109
|
+
}, terminateWorkerTimeout);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
106
114
|
function clearTerminateTimeout(workerData) {
|
|
107
115
|
const { terminateTimeout } = workerData;
|
|
108
116
|
if (terminateTimeout) {
|
package/lib/core/codec-worker.js
CHANGED
|
@@ -100,9 +100,9 @@ class ProgressWatcherStream extends TransformStream {
|
|
|
100
100
|
constructor(readableSource, { onstart, onprogress, size, onend }) {
|
|
101
101
|
let chunkOffset = 0;
|
|
102
102
|
super({
|
|
103
|
-
start() {
|
|
103
|
+
async start() {
|
|
104
104
|
if (onstart) {
|
|
105
|
-
callHandler(onstart, size);
|
|
105
|
+
await callHandler(onstart, size);
|
|
106
106
|
}
|
|
107
107
|
},
|
|
108
108
|
async transform(chunk, controller) {
|
|
@@ -112,10 +112,10 @@ class ProgressWatcherStream extends TransformStream {
|
|
|
112
112
|
}
|
|
113
113
|
controller.enqueue(chunk);
|
|
114
114
|
},
|
|
115
|
-
flush() {
|
|
115
|
+
async flush() {
|
|
116
116
|
readableSource.size = chunkOffset;
|
|
117
117
|
if (onend) {
|
|
118
|
-
callHandler(onend, chunkOffset);
|
|
118
|
+
await callHandler(onend, chunkOffset);
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
121
|
});
|
package/lib/core/io.js
CHANGED
|
@@ -262,7 +262,7 @@ class FetchReader extends Reader {
|
|
|
262
262
|
|
|
263
263
|
constructor(url, options) {
|
|
264
264
|
super();
|
|
265
|
-
|
|
265
|
+
createHttpReader(this, url, options);
|
|
266
266
|
}
|
|
267
267
|
|
|
268
268
|
async init() {
|
|
@@ -279,7 +279,7 @@ class XHRReader extends Reader {
|
|
|
279
279
|
|
|
280
280
|
constructor(url, options) {
|
|
281
281
|
super();
|
|
282
|
-
|
|
282
|
+
createHttpReader(this, url, options);
|
|
283
283
|
}
|
|
284
284
|
|
|
285
285
|
async init() {
|
|
@@ -292,7 +292,7 @@ class XHRReader extends Reader {
|
|
|
292
292
|
}
|
|
293
293
|
}
|
|
294
294
|
|
|
295
|
-
function
|
|
295
|
+
function createHttpReader(httpReader, url, options) {
|
|
296
296
|
const {
|
|
297
297
|
preventHeadRequest,
|
|
298
298
|
useRangeHeader,
|
|
@@ -584,8 +584,8 @@ class SplitDataWriter extends Stream {
|
|
|
584
584
|
|
|
585
585
|
constructor(writerGenerator, maxSize = 4294967295) {
|
|
586
586
|
super();
|
|
587
|
-
const
|
|
588
|
-
Object.assign(
|
|
587
|
+
const writer = this;
|
|
588
|
+
Object.assign(writer, {
|
|
589
589
|
diskNumber: 0,
|
|
590
590
|
diskOffset: 0,
|
|
591
591
|
size: 0,
|
|
@@ -595,7 +595,7 @@ class SplitDataWriter extends Stream {
|
|
|
595
595
|
let diskSourceWriter, diskWritable, diskWriter;
|
|
596
596
|
const writable = new WritableStream({
|
|
597
597
|
async write(chunk) {
|
|
598
|
-
const { availableSize } =
|
|
598
|
+
const { availableSize } = writer;
|
|
599
599
|
if (!diskWriter) {
|
|
600
600
|
const { value, done } = await writerGenerator.next();
|
|
601
601
|
if (done && !value) {
|
|
@@ -604,9 +604,9 @@ class SplitDataWriter extends Stream {
|
|
|
604
604
|
diskSourceWriter = value;
|
|
605
605
|
diskSourceWriter.size = 0;
|
|
606
606
|
if (diskSourceWriter.maxSize) {
|
|
607
|
-
|
|
607
|
+
writer.maxSize = diskSourceWriter.maxSize;
|
|
608
608
|
}
|
|
609
|
-
|
|
609
|
+
writer.availableSize = writer.maxSize;
|
|
610
610
|
await initStream(diskSourceWriter);
|
|
611
611
|
diskWritable = value.writable;
|
|
612
612
|
diskWriter = diskWritable.getWriter();
|
|
@@ -615,8 +615,8 @@ class SplitDataWriter extends Stream {
|
|
|
615
615
|
} else if (chunk.length >= availableSize) {
|
|
616
616
|
await writeChunk(chunk.slice(0, availableSize));
|
|
617
617
|
await closeDisk();
|
|
618
|
-
|
|
619
|
-
|
|
618
|
+
writer.diskOffset += diskSourceWriter.size;
|
|
619
|
+
writer.diskNumber++;
|
|
620
620
|
diskWriter = null;
|
|
621
621
|
await this.write(chunk.slice(availableSize));
|
|
622
622
|
} else {
|
|
@@ -628,7 +628,7 @@ class SplitDataWriter extends Stream {
|
|
|
628
628
|
await closeDisk();
|
|
629
629
|
}
|
|
630
630
|
});
|
|
631
|
-
Object.defineProperty(
|
|
631
|
+
Object.defineProperty(writer, PROPERTY_NAME_WRITABLE, {
|
|
632
632
|
get() {
|
|
633
633
|
return writable;
|
|
634
634
|
}
|
|
@@ -640,8 +640,8 @@ class SplitDataWriter extends Stream {
|
|
|
640
640
|
await diskWriter.ready;
|
|
641
641
|
await diskWriter.write(chunk);
|
|
642
642
|
diskSourceWriter.size += chunkLength;
|
|
643
|
-
|
|
644
|
-
|
|
643
|
+
writer.size += chunkLength;
|
|
644
|
+
writer.availableSize -= chunkLength;
|
|
645
645
|
}
|
|
646
646
|
}
|
|
647
647
|
|
|
@@ -661,6 +661,8 @@ function isHttpFamily(url) {
|
|
|
661
661
|
async function initStream(stream, initSize) {
|
|
662
662
|
if (stream.init && !stream.initialized) {
|
|
663
663
|
await stream.init(initSize);
|
|
664
|
+
} else {
|
|
665
|
+
return Promise.resolve();
|
|
664
666
|
}
|
|
665
667
|
}
|
|
666
668
|
|
|
@@ -689,8 +691,7 @@ function initWriter(writer) {
|
|
|
689
691
|
if (writable.size === UNDEFINED_VALUE) {
|
|
690
692
|
writable.size = 0;
|
|
691
693
|
}
|
|
692
|
-
|
|
693
|
-
if (!splitZipFile) {
|
|
694
|
+
if (!(writer instanceof SplitDataWriter)) {
|
|
694
695
|
Object.assign(writer, {
|
|
695
696
|
diskNumber: 0,
|
|
696
697
|
diskOffset: 0,
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
/* global crypto, TransformStream */
|
|
30
30
|
// deno-lint-ignore-file no-this-alias
|
|
31
31
|
|
|
32
|
+
import { UNDEFINED_VALUE, UNDEFINED_TYPE, FUNCTION_TYPE } from "../constants.js";
|
|
32
33
|
import { encodeText } from "./../util/encode-text.js";
|
|
33
34
|
import {
|
|
34
35
|
cipher,
|
|
@@ -55,8 +56,6 @@ const SALT_LENGTH = [8, 12, 16];
|
|
|
55
56
|
const KEY_LENGTH = [16, 24, 32];
|
|
56
57
|
const SIGNATURE_LENGTH = 10;
|
|
57
58
|
const COUNTER_DEFAULT_VALUE = [0, 0, 0, 0];
|
|
58
|
-
const UNDEFINED_TYPE = "undefined";
|
|
59
|
-
const FUNCTION_TYPE = "function";
|
|
60
59
|
// deno-lint-ignore valid-typeof
|
|
61
60
|
const CRYPTO_API_SUPPORTED = typeof crypto != UNDEFINED_TYPE;
|
|
62
61
|
const subtle = CRYPTO_API_SUPPORTED && crypto.subtle;
|
|
@@ -71,12 +70,12 @@ let DERIVE_BITS_SUPPORTED = CRYPTO_API_SUPPORTED && SUBTLE_API_SUPPORTED && type
|
|
|
71
70
|
|
|
72
71
|
class AESDecryptionStream extends TransformStream {
|
|
73
72
|
|
|
74
|
-
constructor({ password, signed, encryptionStrength, checkPasswordOnly }) {
|
|
73
|
+
constructor({ password, rawPassword, signed, encryptionStrength, checkPasswordOnly }) {
|
|
75
74
|
super({
|
|
76
75
|
start() {
|
|
77
76
|
Object.assign(this, {
|
|
78
77
|
ready: new Promise(resolve => this.resolveReady = resolve),
|
|
79
|
-
password,
|
|
78
|
+
password: encodePassword(password, rawPassword),
|
|
80
79
|
signed,
|
|
81
80
|
strength: encryptionStrength - 1,
|
|
82
81
|
pending: new Uint8Array()
|
|
@@ -140,14 +139,14 @@ class AESDecryptionStream extends TransformStream {
|
|
|
140
139
|
|
|
141
140
|
class AESEncryptionStream extends TransformStream {
|
|
142
141
|
|
|
143
|
-
constructor({ password, encryptionStrength }) {
|
|
142
|
+
constructor({ password, rawPassword, encryptionStrength }) {
|
|
144
143
|
// deno-lint-ignore prefer-const
|
|
145
144
|
let stream;
|
|
146
145
|
super({
|
|
147
146
|
start() {
|
|
148
147
|
Object.assign(this, {
|
|
149
148
|
ready: new Promise(resolve => this.resolveReady = resolve),
|
|
150
|
-
password,
|
|
149
|
+
password: encodePassword(password, rawPassword),
|
|
151
150
|
strength: encryptionStrength - 1,
|
|
152
151
|
pending: new Uint8Array()
|
|
153
152
|
});
|
|
@@ -244,8 +243,7 @@ async function createEncryptionKeys(encrypt, strength, password) {
|
|
|
244
243
|
|
|
245
244
|
async function createKeys(aesCrypto, strength, password, salt) {
|
|
246
245
|
aesCrypto.password = null;
|
|
247
|
-
const
|
|
248
|
-
const baseKey = await importKey(RAW_FORMAT, encodedPassword, BASE_KEY_ALGORITHM, false, DERIVED_BITS_USAGE);
|
|
246
|
+
const baseKey = await importKey(RAW_FORMAT, password, BASE_KEY_ALGORITHM, false, DERIVED_BITS_USAGE);
|
|
249
247
|
const derivedBits = await deriveBits(Object.assign({ salt }, DERIVED_BITS_ALGORITHM), baseKey, 8 * ((KEY_LENGTH[strength] * 2) + 2));
|
|
250
248
|
const compositeKey = new Uint8Array(derivedBits);
|
|
251
249
|
const key = toBits(codecBytes, subarray(compositeKey, 0, KEY_LENGTH[strength]));
|
|
@@ -289,6 +287,14 @@ async function deriveBits(algorithm, baseKey, length) {
|
|
|
289
287
|
}
|
|
290
288
|
}
|
|
291
289
|
|
|
290
|
+
function encodePassword(password, rawPassword) {
|
|
291
|
+
if (rawPassword === UNDEFINED_VALUE) {
|
|
292
|
+
return encodeText(password);
|
|
293
|
+
} else {
|
|
294
|
+
return rawPassword;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
292
298
|
function concat(leftArray, rightArray) {
|
|
293
299
|
let array = leftArray;
|
|
294
300
|
if (leftArray.length + rightArray.length) {
|
|
@@ -28,11 +28,12 @@
|
|
|
28
28
|
|
|
29
29
|
/* global crypto */
|
|
30
30
|
|
|
31
|
+
import { FUNCTION_TYPE, UNDEFINED_TYPE } from "../constants.js";
|
|
31
32
|
import {
|
|
32
33
|
random
|
|
33
34
|
} from "./codecs/sjcl.js";
|
|
34
35
|
|
|
35
|
-
const GET_RANDOM_VALUES_SUPPORTED = typeof crypto !=
|
|
36
|
+
const GET_RANDOM_VALUES_SUPPORTED = typeof crypto != UNDEFINED_TYPE && typeof crypto.getRandomValues == FUNCTION_TYPE;
|
|
36
37
|
|
|
37
38
|
const ERR_INVALID_PASSWORD = "Invalid password";
|
|
38
39
|
const ERR_INVALID_SIGNATURE = "Invalid signature";
|
|
@@ -28,12 +28,14 @@
|
|
|
28
28
|
|
|
29
29
|
/* global TextEncoder */
|
|
30
30
|
|
|
31
|
+
import { UNDEFINED_TYPE } from "../constants.js";
|
|
32
|
+
|
|
31
33
|
export {
|
|
32
34
|
encodeText
|
|
33
35
|
};
|
|
34
36
|
|
|
35
37
|
function encodeText(value) {
|
|
36
|
-
if (typeof TextEncoder ==
|
|
38
|
+
if (typeof TextEncoder == UNDEFINED_TYPE) {
|
|
37
39
|
value = unescape(encodeURIComponent(value));
|
|
38
40
|
const result = new Uint8Array(value.length);
|
|
39
41
|
for (let i = 0; i < result.length; i++) {
|
|
@@ -29,6 +29,8 @@
|
|
|
29
29
|
|
|
30
30
|
// deno-lint-ignore-file no-this-alias
|
|
31
31
|
|
|
32
|
+
import { FUNCTION_TYPE, UNDEFINED_VALUE } from "../constants.js";
|
|
33
|
+
|
|
32
34
|
export {
|
|
33
35
|
initShimAsyncCodec
|
|
34
36
|
};
|
|
@@ -42,7 +44,7 @@ function initShimAsyncCodec(library, options = {}, registerDataHandler) {
|
|
|
42
44
|
|
|
43
45
|
function objectHasOwn(object, propertyName) {
|
|
44
46
|
// eslint-disable-next-line no-prototype-builtins
|
|
45
|
-
return typeof Object.hasOwn ===
|
|
47
|
+
return typeof Object.hasOwn === FUNCTION_TYPE ? Object.hasOwn(object, propertyName) : object.hasOwnProperty(propertyName);
|
|
46
48
|
}
|
|
47
49
|
|
|
48
50
|
function createCodecClass(constructor, constructorOptions, registerDataHandler) {
|
|
@@ -61,7 +63,7 @@ function createCodecClass(constructor, constructorOptions, registerDataHandler)
|
|
|
61
63
|
codecAdapter.pendingData = new Uint8Array(data);
|
|
62
64
|
}
|
|
63
65
|
};
|
|
64
|
-
if (objectHasOwn(options, "level") && options.level ===
|
|
66
|
+
if (objectHasOwn(options, "level") && options.level === UNDEFINED_VALUE) {
|
|
65
67
|
delete options.level;
|
|
66
68
|
}
|
|
67
69
|
codecAdapter.codec = new constructor(Object.assign({}, constructorOptions, options));
|
package/lib/core/zip-fs-core.js
CHANGED
|
@@ -52,6 +52,7 @@ import {
|
|
|
52
52
|
import {
|
|
53
53
|
Entry
|
|
54
54
|
} from "./zip-entry.js";
|
|
55
|
+
import { UNDEFINED_VALUE } from "./constants.js";
|
|
55
56
|
|
|
56
57
|
class ZipEntry {
|
|
57
58
|
|
|
@@ -433,7 +434,7 @@ class ZipDirectoryEntry extends ZipEntry {
|
|
|
433
434
|
|
|
434
435
|
async exportZip(writer, options) {
|
|
435
436
|
const zipEntry = this;
|
|
436
|
-
if (options.bufferedWrite ===
|
|
437
|
+
if (options.bufferedWrite === UNDEFINED_VALUE) {
|
|
437
438
|
options.bufferedWrite = true;
|
|
438
439
|
}
|
|
439
440
|
await Promise.all([initReaders(zipEntry, options.readerOptions), initStream(writer)]);
|
package/lib/core/zip-reader.js
CHANGED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
1. Redistributions of source code must retain the above copyright notice,
|
|
8
8
|
this list of conditions and the following disclaimer.
|
|
9
9
|
|
|
10
|
-
2. Redistributions in binary form must reproduce the above copyright
|
|
11
|
-
notice, this list of conditions and the following disclaimer in
|
|
10
|
+
2. Redistributions in binary form must reproduce the above copyright
|
|
11
|
+
notice, this list of conditions and the following disclaimer in
|
|
12
12
|
the documentation and/or other materials provided with the distribution.
|
|
13
13
|
|
|
14
14
|
3. The names of the authors may not be used to endorse or promote products
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
27
27
|
*/
|
|
28
28
|
|
|
29
|
-
/* global BigInt, Response, WritableStream */
|
|
29
|
+
/* global BigInt, Response, WritableStream, ReadableStream, TransformStream */
|
|
30
30
|
// deno-lint-ignore-file no-this-alias
|
|
31
31
|
|
|
32
32
|
import {
|
|
@@ -209,7 +209,7 @@ class ZipReader {
|
|
|
209
209
|
}
|
|
210
210
|
if (directoryDataOffset >= reader.size) {
|
|
211
211
|
prependedDataLength = reader.size - directoryDataOffset - directoryDataLength - END_OF_CENTRAL_DIR_LENGTH;
|
|
212
|
-
directoryDataOffset = reader.size - directoryDataLength - END_OF_CENTRAL_DIR_LENGTH;
|
|
212
|
+
directoryDataOffset = reader.size - directoryDataLength - END_OF_CENTRAL_DIR_LENGTH;
|
|
213
213
|
}
|
|
214
214
|
if (expectedLastDiskNumber != lastDiskNumber) {
|
|
215
215
|
throw new Error(ERR_SPLIT_ZIP_FILE);
|
|
@@ -326,8 +326,37 @@ class ZipReader {
|
|
|
326
326
|
}
|
|
327
327
|
}
|
|
328
328
|
|
|
329
|
+
class ZipReaderStream {
|
|
330
|
+
|
|
331
|
+
constructor(options = {}) {
|
|
332
|
+
const { readable, writable } = new TransformStream();
|
|
333
|
+
const gen = new ZipReader(readable, options).getEntriesGenerator();
|
|
334
|
+
this.readable = new ReadableStream({
|
|
335
|
+
async pull(controller) {
|
|
336
|
+
const { done, value } = await gen.next();
|
|
337
|
+
if (done)
|
|
338
|
+
return controller.close();
|
|
339
|
+
const chunk = {
|
|
340
|
+
...value,
|
|
341
|
+
readable: (function () {
|
|
342
|
+
const { readable, writable } = new TransformStream();
|
|
343
|
+
if (value.getData) {
|
|
344
|
+
value.getData(writable);
|
|
345
|
+
return readable;
|
|
346
|
+
}
|
|
347
|
+
})()
|
|
348
|
+
};
|
|
349
|
+
delete chunk.getData;
|
|
350
|
+
controller.enqueue(chunk);
|
|
351
|
+
}
|
|
352
|
+
});
|
|
353
|
+
this.writable = writable;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
329
357
|
export {
|
|
330
358
|
ZipReader,
|
|
359
|
+
ZipReaderStream,
|
|
331
360
|
ERR_BAD_FORMAT,
|
|
332
361
|
ERR_EOCDR_NOT_FOUND,
|
|
333
362
|
ERR_EOCDR_ZIP64_NOT_FOUND,
|
|
@@ -372,7 +401,9 @@ class ZipEntry {
|
|
|
372
401
|
const dataArray = await readUint8Array(reader, offset, 30, diskNumberStart);
|
|
373
402
|
const dataView = getDataView(dataArray);
|
|
374
403
|
let password = getOptionValue(zipEntry, options, "password");
|
|
404
|
+
let rawPassword = getOptionValue(zipEntry, options, "rawPassword");
|
|
375
405
|
password = password && password.length && password;
|
|
406
|
+
rawPassword = rawPassword && rawPassword.length && rawPassword;
|
|
376
407
|
if (extraFieldAES) {
|
|
377
408
|
if (extraFieldAES.originalCompressionMethod != COMPRESSION_METHOD_AES) {
|
|
378
409
|
throw new Error(ERR_UNSUPPORTED_COMPRESSION);
|
|
@@ -398,7 +429,7 @@ class ZipEntry {
|
|
|
398
429
|
if (encrypted) {
|
|
399
430
|
if (!zipCrypto && extraFieldAES.strength === UNDEFINED_VALUE) {
|
|
400
431
|
throw new Error(ERR_UNSUPPORTED_ENCRYPTION);
|
|
401
|
-
} else if (!password) {
|
|
432
|
+
} else if (!password && !rawPassword) {
|
|
402
433
|
throw new Error(ERR_ENCRYPTED);
|
|
403
434
|
}
|
|
404
435
|
}
|
|
@@ -423,6 +454,7 @@ class ZipEntry {
|
|
|
423
454
|
options: {
|
|
424
455
|
codecType: CODEC_INFLATE,
|
|
425
456
|
password,
|
|
457
|
+
rawPassword,
|
|
426
458
|
zipCrypto,
|
|
427
459
|
encryptionStrength: extraFieldAES && extraFieldAES.strength,
|
|
428
460
|
signed: getOptionValue(zipEntry, options, "checkSignature"),
|
|
@@ -452,7 +484,7 @@ class ZipEntry {
|
|
|
452
484
|
await writable.getWriter().close();
|
|
453
485
|
}
|
|
454
486
|
}
|
|
455
|
-
return checkPasswordOnly ?
|
|
487
|
+
return checkPasswordOnly ? UNDEFINED_VALUE : writer.getData ? writer.getData() : writable;
|
|
456
488
|
}
|
|
457
489
|
}
|
|
458
490
|
|
|
@@ -718,4 +750,4 @@ function setUint32(view, offset, value) {
|
|
|
718
750
|
|
|
719
751
|
function getDataView(array) {
|
|
720
752
|
return new DataView(array.buffer);
|
|
721
|
-
}
|
|
753
|
+
}
|
package/lib/core/zip-writer.js
CHANGED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
1. Redistributions of source code must retain the above copyright notice,
|
|
8
8
|
this list of conditions and the following disclaimer.
|
|
9
9
|
|
|
10
|
-
2. Redistributions in binary form must reproduce the above copyright
|
|
11
|
-
notice, this list of conditions and the following disclaimer in
|
|
10
|
+
2. Redistributions in binary form must reproduce the above copyright
|
|
11
|
+
notice, this list of conditions and the following disclaimer in
|
|
12
12
|
the documentation and/or other materials provided with the distribution.
|
|
13
13
|
|
|
14
14
|
3. The names of the authors may not be used to endorse or promote products
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
27
27
|
*/
|
|
28
28
|
|
|
29
|
-
/* global BigInt */
|
|
29
|
+
/* global BigInt, TransformStream, Response */
|
|
30
30
|
// deno-lint-ignore-file no-this-alias
|
|
31
31
|
|
|
32
32
|
import {
|
|
@@ -75,9 +75,7 @@ import {
|
|
|
75
75
|
import {
|
|
76
76
|
initStream,
|
|
77
77
|
initReader,
|
|
78
|
-
initWriter
|
|
79
|
-
BlobWriter,
|
|
80
|
-
SplitDataWriter
|
|
78
|
+
initWriter
|
|
81
79
|
} from "./io.js";
|
|
82
80
|
import { encodeText } from "./util/encode-text.js";
|
|
83
81
|
import {
|
|
@@ -110,9 +108,12 @@ class ZipWriter {
|
|
|
110
108
|
|
|
111
109
|
constructor(writer, options = {}) {
|
|
112
110
|
writer = initWriter(writer);
|
|
111
|
+
const addSplitZipSignature =
|
|
112
|
+
writer.availableSize !== UNDEFINED_VALUE && writer.availableSize > 0 && writer.availableSize !== Infinity &&
|
|
113
|
+
writer.maxSize !== UNDEFINED_VALUE && writer.maxSize > 0 && writer.maxSize !== Infinity;
|
|
113
114
|
Object.assign(this, {
|
|
114
115
|
writer,
|
|
115
|
-
addSplitZipSignature
|
|
116
|
+
addSplitZipSignature,
|
|
116
117
|
options,
|
|
117
118
|
config: getConfiguration(),
|
|
118
119
|
files: new Map(),
|
|
@@ -175,8 +176,36 @@ class ZipWriter {
|
|
|
175
176
|
}
|
|
176
177
|
}
|
|
177
178
|
|
|
179
|
+
class ZipWriterStream {
|
|
180
|
+
|
|
181
|
+
constructor(options = {}) {
|
|
182
|
+
const { readable, writable } = new TransformStream();
|
|
183
|
+
this.readable = readable;
|
|
184
|
+
this.zipWriter = new ZipWriter(writable, options);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
transform(path) {
|
|
188
|
+
const { readable, writable } = new TransformStream({
|
|
189
|
+
flush: () => { this.zipWriter.close(); }
|
|
190
|
+
});
|
|
191
|
+
this.zipWriter.add(path, readable);
|
|
192
|
+
return { readable: this.readable, writable };
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
writable(path) {
|
|
196
|
+
const { readable, writable } = new TransformStream();
|
|
197
|
+
this.zipWriter.add(path, readable);
|
|
198
|
+
return writable;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
close(comment = undefined, options = {}) {
|
|
202
|
+
return this.zipWriter.close(comment, options);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
178
206
|
export {
|
|
179
207
|
ZipWriter,
|
|
208
|
+
ZipWriterStream,
|
|
180
209
|
ERR_DUPLICATED_NAME,
|
|
181
210
|
ERR_INVALID_COMMENT,
|
|
182
211
|
ERR_INVALID_ENTRY_NAME,
|
|
@@ -219,6 +248,7 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
219
248
|
const internalFileAttribute = getOptionValue(zipWriter, options, PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTE, 0);
|
|
220
249
|
const externalFileAttribute = getOptionValue(zipWriter, options, PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTE, 0);
|
|
221
250
|
const password = getOptionValue(zipWriter, options, "password");
|
|
251
|
+
const rawPassword = getOptionValue(zipWriter, options, "rawPassword");
|
|
222
252
|
const encryptionStrength = getOptionValue(zipWriter, options, "encryptionStrength", 3);
|
|
223
253
|
const zipCrypto = getOptionValue(zipWriter, options, "zipCrypto");
|
|
224
254
|
const extendedTimestamp = getOptionValue(zipWriter, options, "extendedTimestamp", true);
|
|
@@ -301,6 +331,7 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
301
331
|
zip64Offset,
|
|
302
332
|
zip64DiskNumberStart,
|
|
303
333
|
password,
|
|
334
|
+
rawPassword,
|
|
304
335
|
level,
|
|
305
336
|
useWebWorkers,
|
|
306
337
|
encryptionStrength,
|
|
@@ -356,6 +387,7 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
|
356
387
|
let writingBufferedEntryData;
|
|
357
388
|
let writingEntryData;
|
|
358
389
|
let fileWriter;
|
|
390
|
+
let blobPromise;
|
|
359
391
|
files.set(name, fileEntry);
|
|
360
392
|
try {
|
|
361
393
|
let lockPreviousFileEntry;
|
|
@@ -364,7 +396,8 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
|
364
396
|
requestLockCurrentFileEntry();
|
|
365
397
|
}
|
|
366
398
|
if ((options.bufferedWrite || zipWriter.writerLocked || (zipWriter.bufferedWrites && keepOrder) || !dataDescriptor) && !usdz) {
|
|
367
|
-
fileWriter = new
|
|
399
|
+
fileWriter = new TransformStream();
|
|
400
|
+
blobPromise = new Response(fileWriter.readable).blob();
|
|
368
401
|
fileWriter.writable.size = 0;
|
|
369
402
|
bufferedWrite = true;
|
|
370
403
|
zipWriter.bufferedWrites++;
|
|
@@ -400,7 +433,7 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
|
400
433
|
fileEntry.filename = name;
|
|
401
434
|
if (bufferedWrite) {
|
|
402
435
|
await fileWriter.writable.getWriter().close();
|
|
403
|
-
let blob = await
|
|
436
|
+
let blob = await blobPromise;
|
|
404
437
|
await lockPreviousFileEntry;
|
|
405
438
|
await requestLockWriter();
|
|
406
439
|
writingBufferedEntryData = true;
|
|
@@ -467,7 +500,7 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
|
467
500
|
}
|
|
468
501
|
|
|
469
502
|
async function skipDiskIfNeeded(writable) {
|
|
470
|
-
if (headerInfo.localHeaderArray
|
|
503
|
+
if (getLength(headerInfo.localHeaderArray) > writer.availableSize) {
|
|
471
504
|
writer.availableSize = 0;
|
|
472
505
|
await writeData(writable, new Uint8Array());
|
|
473
506
|
}
|
|
@@ -500,6 +533,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
|
|
|
500
533
|
lastAccessDate,
|
|
501
534
|
creationDate,
|
|
502
535
|
password,
|
|
536
|
+
rawPassword,
|
|
503
537
|
level,
|
|
504
538
|
zip64,
|
|
505
539
|
zip64UncompressedSize,
|
|
@@ -556,6 +590,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
|
|
|
556
590
|
options: {
|
|
557
591
|
codecType: CODEC_DEFLATE,
|
|
558
592
|
level,
|
|
593
|
+
rawPassword,
|
|
559
594
|
password,
|
|
560
595
|
encryptionStrength,
|
|
561
596
|
zipCrypto: encrypted && zipCrypto,
|
|
@@ -637,6 +672,7 @@ function getHeaderInfo(options) {
|
|
|
637
672
|
lastModDate,
|
|
638
673
|
lastAccessDate,
|
|
639
674
|
creationDate,
|
|
675
|
+
rawPassword,
|
|
640
676
|
password,
|
|
641
677
|
level,
|
|
642
678
|
zip64,
|
|
@@ -648,7 +684,7 @@ function getHeaderInfo(options) {
|
|
|
648
684
|
extendedTimestamp
|
|
649
685
|
} = options;
|
|
650
686
|
const compressed = level !== 0 && !directory;
|
|
651
|
-
const encrypted = Boolean(password && getLength(password));
|
|
687
|
+
const encrypted = Boolean((password && getLength(password)) || (rawPassword && getLength(rawPassword)));
|
|
652
688
|
let version = options.version;
|
|
653
689
|
let rawExtraFieldAES;
|
|
654
690
|
if (encrypted && !zipCrypto) {
|
|
@@ -771,7 +807,7 @@ function appendExtraFieldUSDZ(entryInfo, zipWriterOffset) {
|
|
|
771
807
|
const { headerInfo } = entryInfo;
|
|
772
808
|
let { localHeaderArray, extraFieldLength } = headerInfo;
|
|
773
809
|
let localHeaderArrayView = getDataView(localHeaderArray);
|
|
774
|
-
let extraBytesLength = 64 - ((zipWriterOffset + localHeaderArray
|
|
810
|
+
let extraBytesLength = 64 - ((zipWriterOffset + getLength(localHeaderArray)) % 64);
|
|
775
811
|
if (extraBytesLength < 4) {
|
|
776
812
|
extraBytesLength += 64;
|
|
777
813
|
}
|
|
@@ -780,9 +816,9 @@ function appendExtraFieldUSDZ(entryInfo, zipWriterOffset) {
|
|
|
780
816
|
setUint16(extraFieldUSDZView, 0, EXTRAFIELD_TYPE_USDZ);
|
|
781
817
|
setUint16(extraFieldUSDZView, 2, extraBytesLength - 2);
|
|
782
818
|
const previousLocalHeaderArray = localHeaderArray;
|
|
783
|
-
headerInfo.localHeaderArray = localHeaderArray = new Uint8Array(previousLocalHeaderArray
|
|
819
|
+
headerInfo.localHeaderArray = localHeaderArray = new Uint8Array(getLength(previousLocalHeaderArray) + extraBytesLength);
|
|
784
820
|
arraySet(localHeaderArray, previousLocalHeaderArray);
|
|
785
|
-
arraySet(localHeaderArray, rawExtraFieldUSDZ, previousLocalHeaderArray
|
|
821
|
+
arraySet(localHeaderArray, rawExtraFieldUSDZ, getLength(previousLocalHeaderArray));
|
|
786
822
|
localHeaderArrayView = getDataView(localHeaderArray);
|
|
787
823
|
setUint16(localHeaderArrayView, 28, extraFieldLength + extraBytesLength);
|
|
788
824
|
entryInfo.metadataSize += extraBytesLength;
|
|
@@ -844,7 +880,7 @@ function setEntryInfo(entryInfo, options) {
|
|
|
844
880
|
if (zip64) {
|
|
845
881
|
const rawExtraFieldZip64View = getDataView(rawExtraFieldZip64);
|
|
846
882
|
setUint16(rawExtraFieldZip64View, 0, EXTRAFIELD_TYPE_ZIP64);
|
|
847
|
-
setUint16(rawExtraFieldZip64View, 2, rawExtraFieldZip64
|
|
883
|
+
setUint16(rawExtraFieldZip64View, 2, getLength(rawExtraFieldZip64) - 4);
|
|
848
884
|
let rawExtraFieldZip64Offset = 4;
|
|
849
885
|
if (zip64UncompressedSize) {
|
|
850
886
|
setUint32(headerView, 18, MAX_32_BITS);
|
|
@@ -1140,4 +1176,4 @@ function getLength(...arrayLikes) {
|
|
|
1140
1176
|
let result = 0;
|
|
1141
1177
|
arrayLikes.forEach(arrayLike => arrayLike && (result += arrayLike.length));
|
|
1142
1178
|
return result;
|
|
1143
|
-
}
|
|
1179
|
+
}
|
|
@@ -31,9 +31,10 @@
|
|
|
31
31
|
|
|
32
32
|
import "./core/z-worker-core.js";
|
|
33
33
|
import { initShimAsyncCodec } from "./core/util/stream-codec-shim.js";
|
|
34
|
+
import { UNDEFINED_VALUE } from "./core/constants.js";
|
|
34
35
|
|
|
35
36
|
self.initCodec = () => {
|
|
36
|
-
const { Deflate, Inflate } = initShimAsyncCodec(fflate,
|
|
37
|
+
const { Deflate, Inflate } = initShimAsyncCodec(fflate, UNDEFINED_VALUE, (codec, onData) => codec.ondata = onData);
|
|
37
38
|
self.Deflate = Deflate;
|
|
38
39
|
self.Inflate = Inflate;
|
|
39
40
|
};
|