@zip.js/zip.js 2.5.2 → 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 (55) 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 +460 -482
  5. package/dist/zip-fs-full.min.js +1 -1
  6. package/dist/zip-fs.js +460 -482
  7. package/dist/zip-fs.min.js +1 -1
  8. package/dist/zip-full.js +460 -482
  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 +460 -482
  14. package/dist/zip.min.js +1 -1
  15. package/index-fflate.js +1 -1
  16. package/index.d.ts +1 -1
  17. package/index.js +3 -3
  18. package/lib/core/codec-interface.js +89 -0
  19. package/lib/core/{codecs/codec-pool-worker.js → codec-pool-worker.js} +55 -29
  20. package/lib/core/{codecs/codec-pool.js → codec-pool.js} +28 -9
  21. package/lib/core/configuration.js +10 -1
  22. package/lib/core/io.js +102 -100
  23. package/lib/core/{codecs → streams}/aes-crypto-stream.js +68 -54
  24. package/lib/core/{codecs → streams}/codec-stream.js +3 -6
  25. package/lib/core/{codecs → streams/codecs}/crc32.js +0 -0
  26. package/lib/core/{codecs → streams/codecs}/deflate.js +0 -0
  27. package/lib/core/{codecs → streams/codecs}/inflate.js +0 -0
  28. package/lib/core/{codecs → streams/codecs}/sjcl.js +0 -0
  29. package/lib/core/{codecs → streams}/crc32-stream.js +3 -4
  30. package/lib/core/{codecs → streams}/zip-crypto-stream.js +28 -32
  31. package/lib/core/streams/zip-entry-stream.js +178 -0
  32. package/lib/core/z-worker-core.js +30 -15
  33. package/lib/core/zip-fs-core.js +1 -1
  34. package/lib/core/zip-reader.js +21 -12
  35. package/lib/core/zip-writer.js +33 -22
  36. package/lib/z-worker-fflate.js +4 -1
  37. package/lib/z-worker-inline.js +1 -1
  38. package/lib/z-worker.js +2 -2
  39. package/lib/zip-fflate-shim.js +4 -1
  40. package/lib/zip-fs.js +6 -2
  41. package/lib/zip-full-fflate.js +6 -3
  42. package/lib/zip-full.js +8 -5
  43. package/lib/zip-no-worker-deflate.js +7 -3
  44. package/lib/zip-no-worker-fflate-deflate.js +6 -2
  45. package/lib/zip-no-worker-fflate-inflate.js +6 -3
  46. package/lib/zip-no-worker-fflate.js +6 -3
  47. package/lib/zip-no-worker-inflate.js +7 -4
  48. package/lib/zip-no-worker.js +8 -5
  49. package/lib/zip.js +6 -3
  50. package/package.json +2 -8
  51. package/tests/all/test-safe-closing.js +1 -1
  52. package/tests/node/package.json +2 -6
  53. package/tests/node/test-node.js +7 -11
  54. package/lib/core/codecs/codec.js +0 -230
  55. package/lib/core/engine.js +0 -89
@@ -30,7 +30,13 @@
30
30
  // deno-lint-ignore-file no-this-alias
31
31
 
32
32
  import encodeText from "./../util/encode-text.js";
33
- import { cipher, codec, misc, mode, random } from "./sjcl.js";
33
+ import {
34
+ cipher,
35
+ codec,
36
+ misc,
37
+ mode,
38
+ random
39
+ } from "./codecs/sjcl.js";
34
40
 
35
41
  const ERR_INVALID_PASSWORD = "Invalid pasword";
36
42
  const BLOCK_LENGTH = 16;
@@ -45,14 +51,19 @@ const SALT_LENGTH = [8, 12, 16];
45
51
  const KEY_LENGTH = [16, 24, 32];
46
52
  const SIGNATURE_LENGTH = 10;
47
53
  const COUNTER_DEFAULT_VALUE = [0, 0, 0, 0];
48
- const CRYPTO_API_SUPPORTED = typeof crypto != "undefined";
49
- const SUBTLE_API_SUPPORTED = CRYPTO_API_SUPPORTED && typeof crypto.subtle != "undefined";
54
+ const UNDEFINED_TYPE = "undefined";
55
+ const FUNCTION_TYPE = "function";
56
+ const CRYPTO_API_SUPPORTED = typeof crypto != UNDEFINED_TYPE;
57
+ const SUBTLE_API_SUPPORTED = CRYPTO_API_SUPPORTED && typeof crypto.subtle != UNDEFINED_TYPE;
58
+ const GET_RANDOM_VALUES_SUPPORTED = CRYPTO_API_SUPPORTED && typeof crypto.getRandomValues == FUNCTION_TYPE;
59
+ const IMPORT_KEY_SUPPORTED = CRYPTO_API_SUPPORTED && SUBTLE_API_SUPPORTED && typeof crypto.subtle.importKey == FUNCTION_TYPE;
60
+ const DERIVE_BITS_SUPPORTED = CRYPTO_API_SUPPORTED && SUBTLE_API_SUPPORTED && typeof crypto.subtle.deriveBits == FUNCTION_TYPE;
50
61
  const codecBytes = codec.bytes;
51
62
  const Aes = cipher.aes;
52
63
  const CtrGladman = mode.ctrGladman;
53
64
  const HmacSha1 = misc.hmacSha1;
54
65
 
55
- class AESDecryptStream extends TransformStream {
66
+ class AESDecryptionStream extends TransformStream {
56
67
 
57
68
  constructor(password, signed, strength) {
58
69
  let stream;
@@ -67,23 +78,21 @@ class AESDecryptStream extends TransformStream {
67
78
  });
68
79
  },
69
80
  async transform(chunk, controller) {
70
- if (chunk && chunk.length) {
71
- const aesCrypto = this;
72
- if (aesCrypto.password) {
73
- const password = aesCrypto.password;
74
- aesCrypto.password = null;
75
- const preamble = subarray(chunk, 0, SALT_LENGTH[aesCrypto.strength] + 2);
76
- await createDecryptionKeys(aesCrypto, preamble, password);
77
- aesCrypto.aesCtrGladman = new CtrGladman(new Aes(aesCrypto.keys.key), Array.from(COUNTER_DEFAULT_VALUE));
78
- aesCrypto.hmac = new HmacSha1(aesCrypto.keys.authentication);
79
- chunk = subarray(chunk, SALT_LENGTH[aesCrypto.strength] + 2);
80
- aesCrypto.resolveReady();
81
- } else {
82
- await aesCrypto.ready;
83
- }
84
- const output = new Uint8Array(chunk.length - SIGNATURE_LENGTH - ((chunk.length - SIGNATURE_LENGTH) % BLOCK_LENGTH));
85
- controller.enqueue(append(aesCrypto, chunk, output, 0, SIGNATURE_LENGTH, true));
81
+ const aesCrypto = this;
82
+ if (aesCrypto.password) {
83
+ const password = aesCrypto.password;
84
+ aesCrypto.password = null;
85
+ const preamble = subarray(chunk, 0, SALT_LENGTH[aesCrypto.strength] + 2);
86
+ await createDecryptionKeys(aesCrypto, preamble, password);
87
+ aesCrypto.ctr = new CtrGladman(new Aes(aesCrypto.keys.key), Array.from(COUNTER_DEFAULT_VALUE));
88
+ aesCrypto.hmac = new HmacSha1(aesCrypto.keys.authentication);
89
+ chunk = subarray(chunk, SALT_LENGTH[aesCrypto.strength] + 2);
90
+ aesCrypto.resolveReady();
91
+ } else {
92
+ await aesCrypto.ready;
86
93
  }
94
+ const output = new Uint8Array(chunk.length - SIGNATURE_LENGTH - ((chunk.length - SIGNATURE_LENGTH) % BLOCK_LENGTH));
95
+ controller.enqueue(append(aesCrypto, chunk, output, 0, SIGNATURE_LENGTH, true));
87
96
  },
88
97
  async flush(controller) {
89
98
  const aesCrypto = this;
@@ -93,14 +102,14 @@ class AESDecryptStream extends TransformStream {
93
102
  const originalSignature = subarray(pending, pending.length - SIGNATURE_LENGTH);
94
103
  let decryptedChunkArray = new Uint8Array(0);
95
104
  if (chunkToDecrypt.length) {
96
- const encryptedChunk = codecBytes.toBits(chunkToDecrypt);
105
+ const encryptedChunk = toBits(codecBytes, chunkToDecrypt);
97
106
  aesCrypto.hmac.update(encryptedChunk);
98
- const decryptedChunk = aesCrypto.aesCtrGladman.update(encryptedChunk);
99
- decryptedChunkArray = codecBytes.fromBits(decryptedChunk);
107
+ const decryptedChunk = aesCrypto.ctr.update(encryptedChunk);
108
+ decryptedChunkArray = fromBits(codecBytes, decryptedChunk);
100
109
  }
101
110
  stream.valid = true;
102
111
  if (aesCrypto.signed) {
103
- const signature = subarray(codecBytes.fromBits(aesCrypto.hmac.digest()), 0, SIGNATURE_LENGTH);
112
+ const signature = subarray(fromBits(codecBytes, aesCrypto.hmac.digest()), 0, SIGNATURE_LENGTH);
104
113
  for (let indexSignature = 0; indexSignature < SIGNATURE_LENGTH; indexSignature++) {
105
114
  if (signature[indexSignature] != originalSignature[indexSignature]) {
106
115
  stream.valid = false;
@@ -114,7 +123,7 @@ class AESDecryptStream extends TransformStream {
114
123
  }
115
124
  }
116
125
 
117
- class AESEncryptStream extends TransformStream {
126
+ class AESEncryptionStream extends TransformStream {
118
127
 
119
128
  constructor(password, strength) {
120
129
  let stream;
@@ -128,34 +137,32 @@ class AESEncryptStream extends TransformStream {
128
137
  });
129
138
  },
130
139
  async transform(chunk, controller) {
131
- if (chunk && chunk.length) {
132
- const aesCrypto = this;
133
- let preamble = new Uint8Array(0);
134
- if (aesCrypto.password) {
135
- const password = aesCrypto.password;
136
- aesCrypto.password = null;
137
- preamble = await createEncryptionKeys(aesCrypto, password);
138
- aesCrypto.aesCtrGladman = new CtrGladman(new Aes(aesCrypto.keys.key), Array.from(COUNTER_DEFAULT_VALUE));
139
- aesCrypto.hmac = new HmacSha1(aesCrypto.keys.authentication);
140
- aesCrypto.resolveReady();
141
- } else {
142
- await aesCrypto.ready;
143
- }
144
- const output = new Uint8Array(preamble.length + chunk.length - (chunk.length % BLOCK_LENGTH));
145
- output.set(preamble, 0);
146
- controller.enqueue(append(aesCrypto, chunk, output, preamble.length, 0));
140
+ const aesCrypto = this;
141
+ let preamble = new Uint8Array(0);
142
+ if (aesCrypto.password) {
143
+ const password = aesCrypto.password;
144
+ aesCrypto.password = null;
145
+ preamble = await createEncryptionKeys(aesCrypto, password);
146
+ aesCrypto.ctr = new CtrGladman(new Aes(aesCrypto.keys.key), Array.from(COUNTER_DEFAULT_VALUE));
147
+ aesCrypto.hmac = new HmacSha1(aesCrypto.keys.authentication);
148
+ aesCrypto.resolveReady();
149
+ } else {
150
+ await aesCrypto.ready;
147
151
  }
152
+ const output = new Uint8Array(preamble.length + chunk.length - (chunk.length % BLOCK_LENGTH));
153
+ output.set(preamble, 0);
154
+ controller.enqueue(append(aesCrypto, chunk, output, preamble.length, 0));
148
155
  },
149
156
  async flush(controller) {
150
157
  const aesCrypto = this;
151
158
  await aesCrypto.ready;
152
159
  let encryptedChunkArray = new Uint8Array(0);
153
160
  if (aesCrypto.pending.length) {
154
- const encryptedChunk = aesCrypto.aesCtrGladman.update(codecBytes.toBits(aesCrypto.pending));
161
+ const encryptedChunk = aesCrypto.ctr.update(toBits(codecBytes, aesCrypto.pending));
155
162
  aesCrypto.hmac.update(encryptedChunk);
156
- encryptedChunkArray = codecBytes.fromBits(encryptedChunk);
163
+ encryptedChunkArray = fromBits(codecBytes, encryptedChunk);
157
164
  }
158
- stream.signature = codecBytes.fromBits(aesCrypto.hmac.digest()).slice(0, SIGNATURE_LENGTH);
165
+ stream.signature = fromBits(codecBytes, aesCrypto.hmac.digest()).slice(0, SIGNATURE_LENGTH);
159
166
  controller.enqueue(concat(encryptedChunkArray, stream.signature));
160
167
  }
161
168
  });
@@ -164,8 +171,8 @@ class AESEncryptStream extends TransformStream {
164
171
  }
165
172
 
166
173
  export {
167
- AESDecryptStream,
168
- AESEncryptStream,
174
+ AESDecryptionStream,
175
+ AESEncryptionStream,
169
176
  ERR_INVALID_PASSWORD
170
177
  };
171
178
 
@@ -177,15 +184,15 @@ function append(aesCrypto, input, output, paddingStart, paddingEnd, verifySignat
177
184
  }
178
185
  let offset;
179
186
  for (offset = 0; offset <= inputLength - BLOCK_LENGTH; offset += BLOCK_LENGTH) {
180
- const inputChunk = codecBytes.toBits(subarray(input, offset, offset + BLOCK_LENGTH));
187
+ const inputChunk = toBits(codecBytes, subarray(input, offset, offset + BLOCK_LENGTH));
181
188
  if (verifySignature) {
182
189
  aesCrypto.hmac.update(inputChunk);
183
190
  }
184
- const outputChunk = aesCrypto.aesCtrGladman.update(inputChunk);
191
+ const outputChunk = aesCrypto.ctr.update(inputChunk);
185
192
  if (!verifySignature) {
186
193
  aesCrypto.hmac.update(outputChunk);
187
194
  }
188
- output.set(codecBytes.fromBits(outputChunk), offset + paddingStart);
195
+ output.set(fromBits(codecBytes, outputChunk), offset + paddingStart);
189
196
  }
190
197
  aesCrypto.pending = subarray(input, offset);
191
198
  return output;
@@ -212,14 +219,14 @@ async function createKeys(target, password, salt) {
212
219
  const derivedBits = await deriveBits(Object.assign({ salt }, DERIVED_BITS_ALGORITHM), basekey, 8 * ((KEY_LENGTH[target.strength] * 2) + 2));
213
220
  const compositeKey = new Uint8Array(derivedBits);
214
221
  target.keys = {
215
- key: codecBytes.toBits(subarray(compositeKey, 0, KEY_LENGTH[target.strength])),
216
- authentication: codecBytes.toBits(subarray(compositeKey, KEY_LENGTH[target.strength], KEY_LENGTH[target.strength] * 2)),
222
+ key: toBits(codecBytes, subarray(compositeKey, 0, KEY_LENGTH[target.strength])),
223
+ authentication: toBits(codecBytes, subarray(compositeKey, KEY_LENGTH[target.strength], KEY_LENGTH[target.strength] * 2)),
217
224
  passwordVerification: subarray(compositeKey, KEY_LENGTH[target.strength] * 2)
218
225
  };
219
226
  }
220
227
 
221
228
  function getRandomValues(array) {
222
- if (CRYPTO_API_SUPPORTED && typeof crypto.getRandomValues == "function") {
229
+ if (GET_RANDOM_VALUES_SUPPORTED) {
223
230
  return crypto.getRandomValues(array);
224
231
  } else {
225
232
  return random.getRandomValues(array);
@@ -227,7 +234,7 @@ function getRandomValues(array) {
227
234
  }
228
235
 
229
236
  function importKey(format, password, algorithm, extractable, keyUsages) {
230
- if (CRYPTO_API_SUPPORTED && SUBTLE_API_SUPPORTED && typeof crypto.subtle.importKey == "function") {
237
+ if (IMPORT_KEY_SUPPORTED) {
231
238
  return crypto.subtle.importKey(format, password, algorithm, extractable, keyUsages);
232
239
  } else {
233
240
  return misc.importKey(password);
@@ -235,7 +242,7 @@ function importKey(format, password, algorithm, extractable, keyUsages) {
235
242
  }
236
243
 
237
244
  async function deriveBits(algorithm, baseKey, length) {
238
- if (CRYPTO_API_SUPPORTED && SUBTLE_API_SUPPORTED && typeof crypto.subtle.deriveBits == "function") {
245
+ if (DERIVE_BITS_SUPPORTED) {
239
246
  return await crypto.subtle.deriveBits(algorithm, baseKey, length);
240
247
  } else {
241
248
  return misc.pbkdf2(baseKey, algorithm.salt, DERIVED_BITS_ALGORITHM.iterations, length);
@@ -263,4 +270,11 @@ function expand(inputArray, length) {
263
270
 
264
271
  function subarray(array, begin, end) {
265
272
  return array.subarray(begin, end);
273
+ }
274
+
275
+ function fromBits(codecBytes, chunk) {
276
+ return codecBytes.fromBits(chunk);
277
+ }
278
+ function toBits(codecBytes, chunk) {
279
+ return codecBytes.toBits(chunk);
266
280
  }
@@ -36,6 +36,7 @@
36
36
  /* global TransformStream */
37
37
 
38
38
  class CodecStream extends TransformStream {
39
+
39
40
  constructor(Codec, options) {
40
41
  super({
41
42
  start() {
@@ -43,15 +44,11 @@ class CodecStream extends TransformStream {
43
44
  },
44
45
  transform(chunk, controller) {
45
46
  chunk = this.codec.append(chunk);
46
- if (chunk) {
47
- controller.enqueue(chunk);
48
- }
47
+ controller.enqueue(chunk);
49
48
  },
50
49
  flush(controller) {
51
50
  const chunk = this.codec.flush();
52
- if (chunk) {
53
- controller.enqueue(chunk);
54
- }
51
+ controller.enqueue(chunk);
55
52
  }
56
53
  });
57
54
  }
File without changes
File without changes
File without changes
File without changes
@@ -28,18 +28,17 @@
28
28
 
29
29
  /* global TransformStream */
30
30
 
31
- import Crc32 from "./crc32.js";
31
+ import Crc32 from "./codecs/crc32.js";
32
32
 
33
33
  class Crc32Stream extends TransformStream {
34
+
34
35
  constructor() {
35
36
  super({
36
37
  start() {
37
38
  this.crc32 = new Crc32();
38
39
  },
39
40
  transform(chunk) {
40
- if (chunk) {
41
- this.crc32.append(chunk);
42
- }
41
+ this.crc32.append(chunk);
43
42
  },
44
43
  flush(controller) {
45
44
  const value = new Uint8Array(4);
@@ -29,12 +29,12 @@
29
29
  /* global crypto, TransformStream */
30
30
  // deno-lint-ignore-file no-this-alias
31
31
 
32
- import Crc32 from "./crc32.js";
32
+ import Crc32 from "./codecs/crc32.js";
33
33
  import { ERR_INVALID_PASSWORD } from "./aes-crypto-stream.js";
34
34
 
35
35
  const HEADER_LENGTH = 12;
36
36
 
37
- class ZipCryptoDecryptStream extends TransformStream {
37
+ class ZipCryptoDecryptionStream extends TransformStream {
38
38
 
39
39
  constructor(password, passwordVerification) {
40
40
  let stream;
@@ -47,18 +47,16 @@ class ZipCryptoDecryptStream extends TransformStream {
47
47
  createKeys(this, password);
48
48
  },
49
49
  transform(chunk, controller) {
50
- if (chunk && chunk.length) {
51
- const zipCrypto = this;
52
- if (zipCrypto.password) {
53
- const decryptedHeader = decrypt(zipCrypto, chunk.subarray(0, HEADER_LENGTH));
54
- zipCrypto.password = null;
55
- if (decryptedHeader[HEADER_LENGTH - 1] != zipCrypto.passwordVerification) {
56
- throw new Error(ERR_INVALID_PASSWORD);
57
- }
58
- chunk = chunk.subarray(HEADER_LENGTH);
50
+ const zipCrypto = this;
51
+ if (zipCrypto.password) {
52
+ const decryptedHeader = decrypt(zipCrypto, chunk.subarray(0, HEADER_LENGTH));
53
+ zipCrypto.password = null;
54
+ if (decryptedHeader[HEADER_LENGTH - 1] != zipCrypto.passwordVerification) {
55
+ throw new Error(ERR_INVALID_PASSWORD);
59
56
  }
60
- controller.enqueue(decrypt(zipCrypto, chunk));
57
+ chunk = chunk.subarray(HEADER_LENGTH);
61
58
  }
59
+ controller.enqueue(decrypt(zipCrypto, chunk));
62
60
  },
63
61
  flush() {
64
62
  stream.valid = true;
@@ -68,7 +66,7 @@ class ZipCryptoDecryptStream extends TransformStream {
68
66
  }
69
67
  }
70
68
 
71
- class ZipCryptoEncryptStream extends TransformStream {
69
+ class ZipCryptoEncryptionStream extends TransformStream {
72
70
 
73
71
  constructor(password, passwordVerification) {
74
72
  super({
@@ -80,24 +78,22 @@ class ZipCryptoEncryptStream extends TransformStream {
80
78
  createKeys(this, password);
81
79
  },
82
80
  transform(chunk, controller) {
83
- if (chunk && chunk.length) {
84
- const zipCrypto = this;
85
- let output;
86
- let offset;
87
- if (zipCrypto.password) {
88
- zipCrypto.password = null;
89
- const header = crypto.getRandomValues(new Uint8Array(HEADER_LENGTH));
90
- header[HEADER_LENGTH - 1] = zipCrypto.passwordVerification;
91
- output = new Uint8Array(chunk.length + header.length);
92
- output.set(encrypt(zipCrypto, header), 0);
93
- offset = HEADER_LENGTH;
94
- } else {
95
- output = new Uint8Array(chunk.length);
96
- offset = 0;
97
- }
98
- output.set(encrypt(zipCrypto, chunk), offset);
99
- controller.enqueue(output);
81
+ const zipCrypto = this;
82
+ let output;
83
+ let offset;
84
+ if (zipCrypto.password) {
85
+ zipCrypto.password = null;
86
+ const header = crypto.getRandomValues(new Uint8Array(HEADER_LENGTH));
87
+ header[HEADER_LENGTH - 1] = zipCrypto.passwordVerification;
88
+ output = new Uint8Array(chunk.length + header.length);
89
+ output.set(encrypt(zipCrypto, header), 0);
90
+ offset = HEADER_LENGTH;
91
+ } else {
92
+ output = new Uint8Array(chunk.length);
93
+ offset = 0;
100
94
  }
95
+ output.set(encrypt(zipCrypto, chunk), offset);
96
+ controller.enqueue(output);
101
97
  },
102
98
  flush() {
103
99
  }
@@ -106,8 +102,8 @@ class ZipCryptoEncryptStream extends TransformStream {
106
102
  }
107
103
 
108
104
  export {
109
- ZipCryptoDecryptStream,
110
- ZipCryptoEncryptStream,
105
+ ZipCryptoDecryptionStream,
106
+ ZipCryptoEncryptionStream,
111
107
  ERR_INVALID_PASSWORD
112
108
  };
113
109
 
@@ -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) {