@zip.js/zip.js 2.5.4 → 2.5.8

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 (53) 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 +343 -408
  5. package/dist/zip-fs-full.min.js +1 -1
  6. package/dist/zip-fs.js +343 -408
  7. package/dist/zip-fs.min.js +1 -1
  8. package/dist/zip-full.js +343 -408
  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 +343 -408
  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} +60 -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 +13 -24
  22. package/lib/core/{codecs → streams}/aes-crypto-stream.js +35 -33
  23. package/lib/core/{codecs → streams}/codec-stream.js +7 -7
  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 +185 -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 +30 -31
  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/tests/all/test-parallel-writes-ordered.js +1 -1
  51. package/tests/all/test-readable-stream.js +2 -2
  52. package/tests/all/test-zip64-auto.js +1 -1
  53. package/lib/core/codecs/codec.js +0 -246
@@ -26,9 +26,17 @@
26
26
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
27
  */
28
28
 
29
- /* global Worker, URL */
30
-
31
- import { createCodec, MESSAGE_EVENT_TYPE, MESSAGE_START, MESSAGE_PULL, MESSAGE_DATA, MESSAGE_ABORT } from "./codec.js";
29
+ /* global Worker, URL, TransformStream */
30
+
31
+ import {
32
+ createCodec,
33
+ MESSAGE_EVENT_TYPE,
34
+ MESSAGE_START,
35
+ MESSAGE_PULL,
36
+ MESSAGE_DATA,
37
+ MESSAGE_ABORT,
38
+ MESSAGE_CLOSE
39
+ } from "./codec-interface.js";
32
40
 
33
41
  let classicWorkersSupported = true;
34
42
 
@@ -36,10 +44,12 @@ export {
36
44
  getWorker
37
45
  };
38
46
 
39
- function getWorker(workerData, codecConstructor, options, config, onTaskFinished, webWorker, scripts) {
47
+ function getWorker(workerData, codecConstructor, readable, writable, options, config, streamOptions, onTaskFinished, webWorker, scripts) {
40
48
  Object.assign(workerData, {
41
49
  busy: true,
42
50
  codecConstructor,
51
+ readable,
52
+ writable,
43
53
  options: Object.assign({}, options),
44
54
  scripts,
45
55
  terminate() {
@@ -53,27 +63,50 @@ function getWorker(workerData, codecConstructor, options, config, onTaskFinished
53
63
  onTaskFinished(workerData);
54
64
  }
55
65
  });
66
+ const { signal, onprogress, size } = streamOptions;
67
+ if (signal || onprogress) {
68
+ let chunkOffset = 0;
69
+ const transformer = {};
70
+ if (onprogress) {
71
+ transformer.transform = (chunk, controller) => {
72
+ chunkOffset += chunk.length;
73
+ try {
74
+ onprogress(chunkOffset, size());
75
+ } catch (_error) {
76
+ // ignored
77
+ }
78
+ controller.enqueue(chunk);
79
+ };
80
+ }
81
+ workerData.readable = readable.pipeThrough(new TransformStream(transformer), { signal });
82
+ }
56
83
  return webWorker ? createWebWorkerInterface(workerData, config) : createWorkerInterface(workerData, config);
57
84
  }
58
85
 
59
86
  function createWorkerInterface(workerData, config) {
60
- const interfaceCodec = createCodec(workerData.codecConstructor, workerData.options, config);
87
+ const interfaceCodec = createCodec(workerData.codecConstructor, workerData.readable, workerData.writable, workerData.options, config);
61
88
  const codec = {
62
89
  abort() {
63
90
  interfaceCodec.abort();
64
91
  workerData.onTaskFinished();
65
92
  },
66
- start() {
67
- return interfaceCodec.start();
93
+ run() {
94
+ const result = interfaceCodec.run();
95
+ workerData.onTaskFinished();
96
+ return result;
68
97
  }
69
98
  };
70
- interfaceCodec.pull = () => codec.pull();
71
- interfaceCodec.ondata = data => ondata(workerData, codec, data);
72
99
  return codec;
73
100
  }
74
101
 
75
102
  function createWebWorkerInterface(workerData, { baseURL, chunkSize }) {
76
103
  const workerOptions = { type: "module" };
104
+ workerData.reader = workerData.readable.getReader();
105
+ workerData.writer = workerData.writable.getWriter();
106
+ workerData.result = new Promise((resolve, reject) => {
107
+ workerData.resolveResult = resolve;
108
+ workerData.rejectResult = reject;
109
+ });
77
110
  if (!workerData.interface) {
78
111
  if (!classicWorkersSupported) {
79
112
  workerData.worker = getWorker(workerOptions);
@@ -89,12 +122,14 @@ function createWebWorkerInterface(workerData, { baseURL, chunkSize }) {
89
122
  workerData.interface = {
90
123
  abort() {
91
124
  sendMessage({ type: MESSAGE_ABORT });
125
+ workerData.writer.releaseLock();
92
126
  workerData.onTaskFinished();
93
127
  },
94
- start() {
128
+ run() {
95
129
  const options = workerData.options;
96
130
  const scripts = workerData.scripts.slice(1);
97
131
  sendMessage({ type: MESSAGE_START, scripts, options, config: { chunkSize } });
132
+ return workerData.result;
98
133
  }
99
134
  };
100
135
  }
@@ -128,6 +163,7 @@ function createWebWorkerInterface(workerData, { baseURL, chunkSize }) {
128
163
  worker.postMessage(message);
129
164
  }
130
165
  } catch (error) {
166
+ workerData.writer.releaseLock();
131
167
  workerData.onTaskFinished();
132
168
  throw error;
133
169
  }
@@ -136,39 +172,34 @@ function createWebWorkerInterface(workerData, { baseURL, chunkSize }) {
136
172
  async function onMessage(event) {
137
173
  const message = event.data;
138
174
  const reponseError = message.error;
139
- const codec = workerData.interface;
140
175
  try {
141
176
  if (reponseError) {
142
177
  const error = new Error(reponseError.message);
143
178
  error.stack = reponseError.stack;
144
- codec.onerror(error);
179
+ workerData.rejectResult(error);
180
+ workerData.writer.releaseLock();
145
181
  workerData.onTaskFinished();
146
182
  } else {
147
183
  if (message.type == MESSAGE_PULL) {
148
- const { value, done } = await codec.pull();
184
+ const { value, done } = await workerData.reader.read();
149
185
  sendMessage({ type: MESSAGE_DATA, data: value, done, messageId: message.messageId });
150
186
  }
151
187
  if (message.type == MESSAGE_DATA) {
152
- const { value } = message.data;
153
- if (value && value.data) {
154
- value.data = new Uint8Array(value.data);
155
- }
156
- await ondata(workerData, codec, message.data);
188
+ let { data } = message;
189
+ data = new Uint8Array(data);
190
+ await workerData.writer.ready;
191
+ await workerData.writer.write(data);
192
+ }
193
+ if (message.type == MESSAGE_CLOSE) {
194
+ workerData.resolveResult(message.result);
195
+ workerData.writer.releaseLock();
196
+ workerData.onTaskFinished();
157
197
  }
158
198
  }
159
199
  } catch (error) {
160
- codec.onerror(error);
200
+ workerData.rejectResult(error);
201
+ workerData.writer.releaseLock();
161
202
  workerData.onTaskFinished();
162
203
  }
163
204
  }
164
- }
165
-
166
- async function ondata(workerData, codec, data) {
167
- let { value, done } = data;
168
- if (done) {
169
- await codec.ondata({ value: { data: value.data, signature: value.signature }, done });
170
- workerData.onTaskFinished();
171
- } else if (value.data) {
172
- await codec.ondata({ value: { data: value.data } });
173
- }
174
205
  }
@@ -28,47 +28,66 @@
28
28
 
29
29
  /* global setTimeout, clearTimeout */
30
30
 
31
- import { CODEC_INFLATE, CODEC_DEFLATE, ERR_INVALID_SIGNATURE, ERR_INVALID_PASSWORD } from "./codec.js";
31
+ import {
32
+ CODEC_INFLATE,
33
+ CODEC_DEFLATE,
34
+ ERR_INVALID_SIGNATURE,
35
+ ERR_INVALID_PASSWORD,
36
+ ERR_ABORT
37
+ } from "./codec-interface.js";
32
38
  import { getWorker } from "./codec-pool-worker.js";
33
39
 
34
40
  let pool = [];
35
41
  const pendingRequests = [];
36
42
 
37
43
  export {
38
- createCodec,
44
+ runCodec,
39
45
  terminateWorkers,
40
46
  CODEC_DEFLATE,
41
47
  CODEC_INFLATE,
42
48
  ERR_INVALID_SIGNATURE,
43
- ERR_INVALID_PASSWORD
49
+ ERR_INVALID_PASSWORD,
50
+ ERR_ABORT
44
51
  };
45
52
 
46
53
  let indexWorker = 0;
47
54
 
48
- function createCodec(codecConstructor, options, config) {
55
+ async function runCodec(codecConstructor, readable, writable, options, config, streamOptions) {
49
56
  const streamCopy = !options.compressed && !options.signed && !options.encrypted;
50
57
  const webWorker = !streamCopy && (options.useWebWorkers || (options.useWebWorkers === undefined && config.useWebWorkers));
51
58
  const scripts = webWorker && config.workerScripts ? config.workerScripts[options.codecType] : [];
52
59
  options.useCompressionStream = options.useCompressionStream === undefined ? config.useCompressionStream : options.useCompressionStream;
60
+ let codec;
53
61
  if (pool.length < config.maxWorkers) {
54
62
  const workerData = { indexWorker };
55
63
  indexWorker++;
56
64
  pool.push(workerData);
57
- return getWorker(workerData, codecConstructor, options, config, onTaskFinished, webWorker, scripts);
65
+ codec = getWorker(workerData, codecConstructor, readable, writable, options, config, streamOptions, onTaskFinished, webWorker, scripts);
58
66
  } else {
59
67
  const workerData = pool.find(workerData => !workerData.busy);
60
68
  if (workerData) {
61
69
  clearTerminateTimeout(workerData);
62
- return getWorker(workerData, codecConstructor, options, config, onTaskFinished, webWorker, scripts);
70
+ codec = getWorker(workerData, codecConstructor, readable, writable, options, config, streamOptions, onTaskFinished, webWorker, scripts);
71
+ } else {
72
+ codec = await new Promise(resolve => pendingRequests.push({ resolve, codecConstructor, readable, writable, options, webWorker, scripts }));
73
+ }
74
+ }
75
+ const { signal } = streamOptions;
76
+ try {
77
+ return await codec.run(signal);
78
+ } catch (error) {
79
+ if (signal && signal.aborted && (signal.reason == error || error.name == ERR_ABORT)) {
80
+ codec.abort();
81
+ throw new Error(ERR_ABORT);
63
82
  } else {
64
- return new Promise(resolve => pendingRequests.push({ resolve, codecConstructor, options, webWorker, scripts }));
83
+ throw error;
65
84
  }
66
85
  }
67
86
 
68
87
  function onTaskFinished(workerData) {
69
88
  if (pendingRequests.length) {
70
- const [{ resolve, codecConstructor, options, webWorker, scripts }] = pendingRequests.splice(0, 1);
71
- resolve(getWorker(workerData, codecConstructor, options, config, onTaskFinished, webWorker, scripts));
89
+ const [{ resolve, codecConstructor, readable, writable, options, webWorker, scripts }] = pendingRequests.splice(0, 1);
90
+ resolve(getWorker(workerData, codecConstructor, readable, writable, options, config, streamOptions, onTaskFinished, webWorker, scripts));
72
91
  } else if (workerData.worker) {
73
92
  clearTerminateTimeout(workerData);
74
93
  if (Number.isFinite(config.terminateWorkerTimeout) && config.terminateWorkerTimeout >= 0) {
@@ -66,6 +66,9 @@ function configure(configuration) {
66
66
  if (configuration.terminateWorkerTimeout !== undefined) {
67
67
  config.terminateWorkerTimeout = configuration.terminateWorkerTimeout;
68
68
  }
69
+ if (configuration.useCompressionStream !== undefined) {
70
+ config.useCompressionStream = configuration.useCompressionStream;
71
+ }
69
72
  if (configuration.useWebWorkers !== undefined) {
70
73
  config.useWebWorkers = configuration.useWebWorkers;
71
74
  }
package/lib/core/io.js CHANGED
@@ -75,24 +75,15 @@ class Reader extends Stream {
75
75
  }
76
76
 
77
77
  class WriterStream extends Stream {
78
+
78
79
  getStream() {
79
80
  const writer = this;
80
81
  return new WritableStream({
81
82
  write(chunk) {
82
- if (chunk && chunk.length) {
83
- return writer.writeUint8Array(chunk);
84
- }
83
+ return writer.writeUint8Array(chunk);
85
84
  }
86
85
  });
87
86
  }
88
-
89
- getStreamWriter() {
90
- const writer = this;
91
- if (!writer.streamWriter) {
92
- writer.streamWriter = writer.getStream().getWriter();
93
- }
94
- return writer.streamWriter;
95
- }
96
87
  }
97
88
 
98
89
  class Writer extends WriterStream {
@@ -275,13 +266,12 @@ function flushArrayBuffers(blobWriter) {
275
266
 
276
267
  class ReadableStreamReader {
277
268
 
278
- constructor(readableStream) {
269
+ constructor(readableStream, size = Infinity) {
279
270
  this.readableStream = readableStream;
280
- this.size = Infinity;
271
+ this.size = size;
281
272
  }
282
273
 
283
- init(size) {
284
- this.size = size;
274
+ init() {
285
275
  this.initialized = true;
286
276
  }
287
277
 
@@ -292,27 +282,26 @@ class ReadableStreamReader {
292
282
 
293
283
  class WritableStreamWriter extends Writer {
294
284
 
295
- constructor(writableStream) {
285
+ constructor(writable) {
296
286
  super();
297
287
  const writer = this;
298
- writer.writableStream = writableStream;
299
- writer.writer = writer.getStreamWriter();
288
+ writer.writable = writable;
300
289
  }
301
290
 
302
291
  async writeUint8Array(array) {
303
292
  await this.writer.ready;
304
- return this.writer.write(array);
293
+ const writer = this.writable.getWriter();
294
+ await writer.write(array);
295
+ writer.releaseLock();
305
296
  }
306
297
 
307
298
  getStream() {
308
- return this.writableStream;
299
+ return this.writable;
309
300
  }
310
301
 
311
302
  async getData() {
312
- const writer = this;
313
- await writer.writer.ready;
314
- await writer.writer.close();
315
- return writer.writableStream;
303
+ await this.writable.getWriter().close();
304
+ return this.writable;
316
305
  }
317
306
  }
318
307
 
@@ -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;
@@ -72,23 +78,21 @@ class AESDecryptionStream extends TransformStream {
72
78
  });
73
79
  },
74
80
  async transform(chunk, controller) {
75
- if (chunk && chunk.length) {
76
- const aesCrypto = this;
77
- if (aesCrypto.password) {
78
- const password = aesCrypto.password;
79
- aesCrypto.password = null;
80
- const preamble = subarray(chunk, 0, SALT_LENGTH[aesCrypto.strength] + 2);
81
- await createDecryptionKeys(aesCrypto, preamble, password);
82
- aesCrypto.ctr = new CtrGladman(new Aes(aesCrypto.keys.key), Array.from(COUNTER_DEFAULT_VALUE));
83
- aesCrypto.hmac = new HmacSha1(aesCrypto.keys.authentication);
84
- chunk = subarray(chunk, SALT_LENGTH[aesCrypto.strength] + 2);
85
- aesCrypto.resolveReady();
86
- } else {
87
- await aesCrypto.ready;
88
- }
89
- const output = new Uint8Array(chunk.length - SIGNATURE_LENGTH - ((chunk.length - SIGNATURE_LENGTH) % BLOCK_LENGTH));
90
- 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;
91
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));
92
96
  },
93
97
  async flush(controller) {
94
98
  const aesCrypto = this;
@@ -133,23 +137,21 @@ class AESEncryptionStream extends TransformStream {
133
137
  });
134
138
  },
135
139
  async transform(chunk, controller) {
136
- if (chunk && chunk.length) {
137
- const aesCrypto = this;
138
- let preamble = new Uint8Array(0);
139
- if (aesCrypto.password) {
140
- const password = aesCrypto.password;
141
- aesCrypto.password = null;
142
- preamble = await createEncryptionKeys(aesCrypto, password);
143
- aesCrypto.ctr = new CtrGladman(new Aes(aesCrypto.keys.key), Array.from(COUNTER_DEFAULT_VALUE));
144
- aesCrypto.hmac = new HmacSha1(aesCrypto.keys.authentication);
145
- aesCrypto.resolveReady();
146
- } else {
147
- await aesCrypto.ready;
148
- }
149
- const output = new Uint8Array(preamble.length + chunk.length - (chunk.length % BLOCK_LENGTH));
150
- output.set(preamble, 0);
151
- 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;
152
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));
153
155
  },
154
156
  async flush(controller) {
155
157
  const aesCrypto = this;
@@ -36,20 +36,20 @@
36
36
  /* global TransformStream */
37
37
 
38
38
  class CodecStream extends TransformStream {
39
+
39
40
  constructor(Codec, options) {
41
+ let codec;
40
42
  super({
41
43
  start() {
42
- this.codec = new Codec(options);
44
+ codec = new Codec(options);
43
45
  },
44
46
  transform(chunk, controller) {
45
- chunk = this.codec.append(chunk);
46
- if (chunk && chunk.length) {
47
- controller.enqueue(chunk);
48
- }
47
+ chunk = codec.append(chunk);
48
+ controller.enqueue(chunk);
49
49
  },
50
50
  flush(controller) {
51
- const chunk = this.codec.flush();
52
- if (chunk && chunk.length) {
51
+ const chunk = codec.flush();
52
+ if (chunk) {
53
53
  controller.enqueue(chunk);
54
54
  }
55
55
  }
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 && chunk.length) {
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,7 +29,7 @@
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;
@@ -47,18 +47,16 @@ class ZipCryptoDecryptionStream 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;
@@ -80,24 +78,22 @@ class ZipCryptoEncryptionStream 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
  }