@zip.js/zip.js 2.5.4 → 2.5.5

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.
Files changed (50) hide show
  1. package/dist/z-worker-fflate.js +1 -1
  2. package/dist/z-worker-pako.js +1 -1
  3. package/dist/z-worker.js +1 -1
  4. package/dist/zip-fs-full.js +307 -388
  5. package/dist/zip-fs-full.min.js +1 -1
  6. package/dist/zip-fs.js +307 -388
  7. package/dist/zip-fs.min.js +1 -1
  8. package/dist/zip-full.js +307 -388
  9. package/dist/zip-full.min.js +1 -1
  10. package/dist/zip-no-worker-deflate.min.js +1 -1
  11. package/dist/zip-no-worker-inflate.min.js +1 -1
  12. package/dist/zip-no-worker.min.js +1 -1
  13. package/dist/zip.js +307 -388
  14. package/dist/zip.min.js +1 -1
  15. package/index-fflate.js +1 -1
  16. package/index.js +3 -3
  17. package/lib/core/{engine.js → codec-interface.js} +52 -46
  18. package/lib/core/{codecs/codec-pool-worker.js → codec-pool-worker.js} +55 -29
  19. package/lib/core/{codecs/codec-pool.js → codec-pool.js} +28 -9
  20. package/lib/core/configuration.js +3 -0
  21. package/lib/core/io.js +7 -20
  22. package/lib/core/{codecs → streams}/aes-crypto-stream.js +35 -33
  23. package/lib/core/{codecs → streams}/codec-stream.js +3 -6
  24. package/lib/core/{codecs → streams/codecs}/crc32.js +0 -0
  25. package/lib/core/{codecs → streams/codecs}/deflate.js +0 -0
  26. package/lib/core/{codecs → streams/codecs}/inflate.js +0 -0
  27. package/lib/core/{codecs → streams/codecs}/sjcl.js +0 -0
  28. package/lib/core/{codecs → streams}/crc32-stream.js +3 -4
  29. package/lib/core/{codecs → streams}/zip-crypto-stream.js +24 -28
  30. package/lib/core/streams/zip-entry-stream.js +178 -0
  31. package/lib/core/z-worker-core.js +30 -15
  32. package/lib/core/zip-fs-core.js +1 -1
  33. package/lib/core/zip-reader.js +21 -18
  34. package/lib/core/zip-writer.js +18 -18
  35. package/lib/z-worker-fflate.js +4 -1
  36. package/lib/z-worker-inline.js +1 -1
  37. package/lib/z-worker.js +2 -2
  38. package/lib/zip-fflate-shim.js +4 -1
  39. package/lib/zip-fs.js +6 -2
  40. package/lib/zip-full-fflate.js +6 -3
  41. package/lib/zip-full.js +8 -5
  42. package/lib/zip-no-worker-deflate.js +7 -3
  43. package/lib/zip-no-worker-fflate-deflate.js +6 -2
  44. package/lib/zip-no-worker-fflate-inflate.js +6 -3
  45. package/lib/zip-no-worker-fflate.js +6 -3
  46. package/lib/zip-no-worker-inflate.js +7 -4
  47. package/lib/zip-no-worker.js +8 -5
  48. package/lib/zip.js +6 -3
  49. package/package.json +2 -8
  50. package/lib/core/codecs/codec.js +0 -246
@@ -0,0 +1,178 @@
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 CompressionStream, DecompressionStream, TransformStream */
30
+
31
+ import Crc32Stream from "./crc32-stream.js";
32
+ import {
33
+ AESEncryptionStream,
34
+ AESDecryptionStream
35
+ } from "./aes-crypto-stream.js";
36
+ import {
37
+ ZipCryptoEncryptionStream,
38
+ ZipCryptoDecryptionStream,
39
+ ERR_INVALID_PASSWORD
40
+ } from "./zip-crypto-stream.js";
41
+ import CodecStream from "./codec-stream.js";
42
+
43
+ const ERR_INVALID_SIGNATURE = "Invalid signature";
44
+ const COMPRESSION_FORMAT = "deflate-raw";
45
+ const UNDEFINED_TYPE = "undefined";
46
+
47
+ class DeflateStream extends TransformStream {
48
+
49
+ constructor(codecConstructor, { compressed, useCompressionStream, password, passwordVerification, encryptionStrength, zipCrypto, signed }, { chunkSize }, ...strategies) {
50
+ super({}, ...strategies);
51
+ const stream = this;
52
+ let crc32Stream, encryptionStream;
53
+ let readable = filterEmptyChunks(super.readable);
54
+ const encrypted = Boolean(password);
55
+ if ((!encrypted || zipCrypto) && signed) {
56
+ [readable, crc32Stream] = readable.tee();
57
+ crc32Stream = crc32Stream.pipeThrough(new Crc32Stream());
58
+ }
59
+ if (compressed) {
60
+ if ((useCompressionStream !== undefined && !useCompressionStream) || typeof CompressionStream == UNDEFINED_TYPE) {
61
+ readable = pipeCodecStream(codecConstructor, readable, chunkSize);
62
+ } else {
63
+ try {
64
+ const compressionStream = new CompressionStream(COMPRESSION_FORMAT);
65
+ readable = readable.pipeThrough(compressionStream);
66
+ } catch (_error) {
67
+ readable = pipeCodecStream(codecConstructor, readable, chunkSize);
68
+ }
69
+ }
70
+ }
71
+ if (encrypted) {
72
+ if (zipCrypto) {
73
+ readable = readable.pipeThrough(new ZipCryptoEncryptionStream(password, passwordVerification));
74
+ } else {
75
+ encryptionStream = new AESEncryptionStream(password, encryptionStrength);
76
+ readable = readable.pipeThrough(encryptionStream);
77
+ }
78
+ }
79
+ setReadable(stream, readable, async () => {
80
+ let signature;
81
+ if (encrypted && !zipCrypto) {
82
+ signature = encryptionStream.signature;
83
+ }
84
+ if ((!encrypted || zipCrypto) && signed) {
85
+ signature = await crc32Stream.getReader().read();
86
+ signature = new DataView(signature.value.buffer).getUint32(0);
87
+ }
88
+ stream.signature = signature;
89
+ });
90
+ }
91
+ }
92
+
93
+ class InflateStream extends TransformStream {
94
+
95
+ constructor(codecConstructor, { zipCrypto, password, passwordVerification, signed, encryptionStrength, compressed, useCompressionStream }, { chunkSize }, ...strategies) {
96
+ super({}, ...strategies);
97
+ const stream = this;
98
+ let crc32Stream, decryptionStream;
99
+ let readable = filterEmptyChunks(super.readable);
100
+ const encrypted = Boolean(password);
101
+ if (encrypted) {
102
+ if (zipCrypto) {
103
+ readable = readable.pipeThrough(new ZipCryptoDecryptionStream(password, passwordVerification));
104
+ } else {
105
+ decryptionStream = new AESDecryptionStream(password, signed, encryptionStrength);
106
+ readable = readable.pipeThrough(decryptionStream);
107
+ }
108
+ }
109
+ if (compressed) {
110
+ if ((useCompressionStream !== undefined && !useCompressionStream) || typeof DecompressionStream == UNDEFINED_TYPE) {
111
+ readable = pipeCodecStream(codecConstructor, readable, chunkSize);
112
+ } else {
113
+ try {
114
+ readable = readable.pipeThrough(new DecompressionStream(COMPRESSION_FORMAT));
115
+ } catch (_error) {
116
+ readable = pipeCodecStream(codecConstructor, readable, chunkSize);
117
+ }
118
+ }
119
+ }
120
+ if ((!encrypted || zipCrypto) && signed) {
121
+ [readable, crc32Stream] = readable.tee();
122
+ crc32Stream = crc32Stream.pipeThrough(new Crc32Stream());
123
+ }
124
+ setReadable(stream, readable, async () => {
125
+ let signature;
126
+ if (encrypted && !zipCrypto) {
127
+ if (!decryptionStream.valid) {
128
+ throw new Error(ERR_INVALID_SIGNATURE);
129
+ }
130
+ }
131
+ if ((!encrypted || zipCrypto) && signed) {
132
+ signature = await crc32Stream.getReader().read();
133
+ const dataViewSignature = new DataView(signature.value.buffer);
134
+ if (signature != dataViewSignature.getUint32(0, false)) {
135
+ throw new Error(ERR_INVALID_SIGNATURE);
136
+ }
137
+ }
138
+ });
139
+ }
140
+ }
141
+
142
+ export {
143
+ DeflateStream,
144
+ InflateStream,
145
+ ERR_INVALID_PASSWORD,
146
+ ERR_INVALID_SIGNATURE
147
+ };
148
+
149
+ function pipeCodecStream(codecConstructor, stream, chunkSize) {
150
+ return stream.pipeThrough(new CodecStream(codecConstructor, { chunkSize }));
151
+ }
152
+
153
+ function filterEmptyChunks(readable) {
154
+ return readable.pipeThrough(new TransformStream({
155
+ transform(chunk, controller) {
156
+ if (chunk && chunk.length) {
157
+ controller.enqueue(chunk);
158
+ }
159
+ }
160
+ }));
161
+ }
162
+
163
+ function setReadable(stream, readable, flush) {
164
+ stream.length = 0;
165
+ readable = readable.pipeThrough(new TransformStream({
166
+ transform(chunk, controller) {
167
+ if (chunk && chunk.length) {
168
+ stream.length += chunk.length;
169
+ controller.enqueue(chunk);
170
+ }
171
+ }, flush
172
+ }));
173
+ Object.defineProperty(stream, "readable", {
174
+ get() {
175
+ return readable;
176
+ }
177
+ });
178
+ }
@@ -26,7 +26,7 @@
26
26
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
27
  */
28
28
 
29
- /* global self, importScripts, addEventListener, postMessage */
29
+ /* global self, importScripts, addEventListener, postMessage, ReadableStream, WritableStream */
30
30
 
31
31
  import {
32
32
  createCodec,
@@ -37,7 +37,8 @@ import {
37
37
  MESSAGE_PULL,
38
38
  MESSAGE_DATA,
39
39
  MESSAGE_ABORT,
40
- } from "./codecs/codec.js";
40
+ MESSAGE_CLOSE
41
+ } from "./codec-interface.js";
41
42
 
42
43
  const pendingMessages = new Map();
43
44
  let codec;
@@ -78,16 +79,30 @@ async function init(message) {
78
79
  } else if (options.codecType.startsWith(CODEC_INFLATE)) {
79
80
  codecConstructor = self.Inflate;
80
81
  }
81
- codec = createCodec(codecConstructor, options, message.config);
82
- codec.ondata = data => sendMessage({ type: MESSAGE_DATA, data });
83
- codec.onerror = error => postMessage({ error: { message: error.message, stack: error.stack } });
84
- codec.pull = () => {
85
- const result = new Promise((resolve, reject) => pendingMessages.set(messageId, { resolve, reject }));
86
- sendMessage({ type: MESSAGE_PULL, messageId });
87
- messageId++;
88
- return result;
89
- };
90
- await codec.start();
82
+ const readable = new ReadableStream({
83
+ async pull(controller) {
84
+ let result = new Promise((resolve, reject) => pendingMessages.set(messageId, { resolve, reject }));
85
+ sendMessage({ type: MESSAGE_PULL, messageId });
86
+ messageId++;
87
+ const { value, done } = await result;
88
+ // debugger;
89
+ controller.enqueue(value);
90
+ if (done) {
91
+ controller.close();
92
+ }
93
+ }
94
+ }, {
95
+ highWaterMark: 1
96
+ });
97
+ const writable = new WritableStream({
98
+ write(data) {
99
+ sendMessage({ type: MESSAGE_DATA, data });
100
+ }
101
+ });
102
+ codec = createCodec(codecConstructor, readable, writable, options, message.config);
103
+ const result = await codec.run();
104
+ sendMessage({ type: MESSAGE_CLOSE, result });
105
+
91
106
  } catch (error) {
92
107
  postMessage({ error: { message: error.message, stack: error.stack } });
93
108
  }
@@ -95,11 +110,11 @@ async function init(message) {
95
110
 
96
111
  function sendMessage(message) {
97
112
  if (message.data) {
98
- const data = message.data.value.data;
113
+ const data = message.data;
99
114
  if (data && data.length) {
100
115
  try {
101
- message.data.value.data = data.buffer;
102
- postMessage(message, [message.data.value.data]);
116
+ message.data = data.buffer;
117
+ postMessage(message, [message.data]);
103
118
  } catch (_error) {
104
119
  postMessage(message);
105
120
  }
@@ -26,7 +26,6 @@
26
26
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
27
  */
28
28
 
29
- export { ERR_ABORT } from "./engine.js";
30
29
  import {
31
30
  Reader,
32
31
  TextReader,
@@ -419,6 +418,7 @@ class FS {
419
418
  }
420
419
 
421
420
  const fs = { FS, ZipDirectoryEntry, ZipFileEntry };
421
+ export { ERR_ABORT } from "./codec-pool.js";
422
422
  export { fs };
423
423
 
424
424
  function getTotalSize(entries, propertyName) {
@@ -56,11 +56,18 @@ import {
56
56
  FILE_ATTR_MSDOS_DIR_MASK,
57
57
  DIRECTORY_SIGNATURE
58
58
  } from "./constants.js";
59
- import { getConfiguration, getChunkSize } from "./configuration.js";
60
- import { createCodec, CODEC_INFLATE, ERR_INVALID_SIGNATURE, ERR_INVALID_PASSWORD } from "./codecs/codec-pool.js";
59
+ import {
60
+ getConfiguration,
61
+ getChunkSize
62
+ } from "./configuration.js";
63
+ import {
64
+ runCodec,
65
+ CODEC_INFLATE,
66
+ ERR_INVALID_SIGNATURE,
67
+ ERR_INVALID_PASSWORD
68
+ } from "./codec-pool.js";
61
69
  import decodeText from "./util/decode-text.js";
62
- import Crc32 from "./codecs/crc32.js";
63
- import { processData } from "./engine.js";
70
+ import Crc32 from "./streams/codecs/crc32.js";
64
71
  import Entry from "./zip-entry.js";
65
72
 
66
73
  const ERR_BAD_FORMAT = "File format is not recognized";
@@ -292,7 +299,15 @@ class ZipEntry {
292
299
  throw new Error(ERR_ENCRYPTED);
293
300
  }
294
301
  }
295
- const codec = await createCodec(config.Inflate, {
302
+ const dataOffset = offset + 30 + localDirectory.filenameLength + localDirectory.extraFieldLength;
303
+ const size = () => compressedSize;
304
+ const readable = reader.getStream({ offset: dataOffset, size, chunkSize: getChunkSize(config) });
305
+ const writable = writer.getStream();
306
+ const signal = getOptionValue(zipEntry, options, "signal");
307
+ if (!writer.initialized) {
308
+ await writer.init();
309
+ }
310
+ await runCodec(config.Inflate, readable, writable, {
296
311
  codecType: CODEC_INFLATE,
297
312
  password,
298
313
  zipCrypto,
@@ -304,19 +319,7 @@ class ZipEntry {
304
319
  encrypted,
305
320
  useWebWorkers: getOptionValue(zipEntry, options, "useWebWorkers"),
306
321
  useCompressionStream: getOptionValue(zipEntry, options, "useCompressionStream")
307
- }, config);
308
- if (!writer.initialized) {
309
- await writer.init();
310
- }
311
- const signal = getOptionValue(zipEntry, options, "signal");
312
- const dataOffset = offset + 30 + localDirectory.filenameLength + localDirectory.extraFieldLength;
313
- const size = () => compressedSize;
314
- await processData(
315
- codec,
316
- reader.getStream({ offset: dataOffset, size, chunkSize: getChunkSize(config) }).getReader(),
317
- writer.getStreamWriter(),
318
- size,
319
- { onprogress: options.onprogress, signal });
322
+ }, config, { signal, onprogress: options.onprogress, size });
320
323
  return writer.getData();
321
324
  }
322
325
  }
@@ -59,11 +59,16 @@ import {
59
59
  MIN_DATE,
60
60
  MAX_DATE
61
61
  } from "./constants.js";
62
- import { getConfiguration, getChunkSize } from "./configuration.js";
63
- import { CODEC_DEFLATE, createCodec } from "./codecs/codec-pool.js";
62
+ import {
63
+ getConfiguration,
64
+ getChunkSize
65
+ } from "./configuration.js";
66
+ import {
67
+ CODEC_DEFLATE,
68
+ runCodec
69
+ } from "./codec-pool.js";
64
70
  import encodeText from "./util/encode-text.js";
65
71
  import { BlobWriter } from "./io.js";
66
- import { processData } from "./engine.js";
67
72
  import Entry from "./zip-entry.js";
68
73
 
69
74
  const ERR_DUPLICATED_NAME = "File already exists";
@@ -281,7 +286,7 @@ async function addFile(zipWriter, name, reader, options) {
281
286
 
282
287
  async function getFileEntry(zipWriter, name, reader, options) {
283
288
  const { files, writer } = zipWriter;
284
- const streamWriter = writer.getStreamWriter();
289
+ const streamWriter = writer.getStream().getWriter();
285
290
  const previousFileEntry = Array.from(files.values()).pop();
286
291
  let fileEntry = {};
287
292
  let bufferedWrite;
@@ -307,7 +312,7 @@ async function getFileEntry(zipWriter, name, reader, options) {
307
312
  }
308
313
  fileWriter = writer;
309
314
  }
310
- fileEntry = await createFileEntry(reader, fileWriter.getStreamWriter(), zipWriter.config, options);
315
+ fileEntry = await createFileEntry(reader, fileWriter.getStream(), fileWriter.getStream().getWriter(), zipWriter.config, options);
311
316
  fileEntry.lock = lockCurrentFileEntry;
312
317
  files.set(name, fileEntry);
313
318
  fileEntry.filename = name;
@@ -369,7 +374,7 @@ async function getFileEntry(zipWriter, name, reader, options) {
369
374
  }
370
375
  }
371
376
 
372
- async function createFileEntry(reader, streamWriter, config, options) {
377
+ async function createFileEntry(reader, writable, streamWriter, config, options) {
373
378
  const {
374
379
  rawFilename,
375
380
  lastAccessDate,
@@ -516,7 +521,11 @@ async function createFileEntry(reader, streamWriter, config, options) {
516
521
  let result;
517
522
  let compressedSize = 0;
518
523
  if (reader) {
519
- const codec = await createCodec(config.Deflate, {
524
+ await writeUint8Array(streamWriter, localHeaderArray);
525
+ fileEntry.dataWritten = true;
526
+ const size = () => reader.size;
527
+ const readable = reader.getStream({ offset: 0, size, chunkSize: getChunkSize(config) });
528
+ result = await runCodec(config.Deflate, readable, writable, {
520
529
  codecType: CODEC_DEFLATE,
521
530
  level,
522
531
  password,
@@ -528,16 +537,7 @@ async function createFileEntry(reader, streamWriter, config, options) {
528
537
  encrypted,
529
538
  useWebWorkers,
530
539
  useCompressionStream
531
- }, config);
532
- await writeUint8Array(streamWriter, localHeaderArray);
533
- fileEntry.dataWritten = true;
534
- const size = () => reader.size;
535
- result = await processData(
536
- codec,
537
- reader.getStream({ offset: 0, size, chunkSize: getChunkSize(config) }).getReader(),
538
- streamWriter,
539
- () => reader.size,
540
- { onprogress, signal });
540
+ }, config, { signal, onprogress, size });
541
541
  uncompressedSize = fileEntry.uncompressedSize = reader.size;
542
542
  compressedSize = result.length;
543
543
  } else {
@@ -594,7 +594,7 @@ async function createFileEntry(reader, streamWriter, config, options) {
594
594
 
595
595
  async function closeFile(zipWriter, comment, options) {
596
596
  const { files } = zipWriter;
597
- const streamWriter = zipWriter.writer.getStreamWriter();
597
+ const streamWriter = zipWriter.writer.getStream().getWriter();
598
598
  let offset = 0;
599
599
  let directoryDataLength = 0;
600
600
  let directoryOffset = zipWriter.offset;
@@ -29,7 +29,10 @@
29
29
  /* global self */
30
30
 
31
31
  import "./core/z-worker-core.js";
32
- import { Deflate, Inflate } from "./zip-fflate-shim.js";
32
+ import {
33
+ Deflate,
34
+ Inflate
35
+ } from "./zip-fflate-shim.js";
33
36
 
34
37
  self.initCodec = () => {
35
38
  self.Deflate = Deflate;