@zip.js/zip.js 2.8.45 → 2.8.47

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 (56) hide show
  1. package/README.md +28 -2
  2. package/deno.json +13 -3
  3. package/dist/zip-core-external.js +146 -35
  4. package/dist/zip-core-external.min.js +1 -1
  5. package/dist/zip-core.js +154 -32
  6. package/dist/zip-core.min.js +1 -1
  7. package/dist/zip-fs-core-external.js +146 -35
  8. package/dist/zip-fs-core-external.min.js +1 -1
  9. package/dist/zip-fs-core.js +124 -30
  10. package/dist/zip-fs-core.min.js +1 -1
  11. package/dist/zip-fs-external.js +146 -35
  12. package/dist/zip-fs-external.min.js +1 -1
  13. package/dist/zip-fs-native.js +160 -36
  14. package/dist/zip-fs-native.min.js +1 -1
  15. package/dist/zip-fs.js +160 -36
  16. package/dist/zip-fs.min.js +1 -1
  17. package/dist/zip-legacy.js +156 -34
  18. package/dist/zip-legacy.min.js +1 -1
  19. package/dist/zip-native.js +158 -36
  20. package/dist/zip-native.min.js +1 -1
  21. package/dist/zip-web-worker-native.js +1 -1
  22. package/dist/zip-web-worker.js +1 -1
  23. package/dist/zip.js +158 -36
  24. package/dist/zip.min.js +1 -1
  25. package/index-native.cjs +160 -36
  26. package/index-native.min.js +1 -1
  27. package/index.cjs +160 -36
  28. package/index.d.cts +232 -1
  29. package/index.d.ts +232 -1
  30. package/index.min.js +1 -1
  31. package/lib/core/codec-pool.js +9 -5
  32. package/lib/core/codec-worker.js +30 -13
  33. package/lib/core/configuration.js +20 -2
  34. package/lib/core/constants.js +2 -0
  35. package/lib/core/options.js +4 -0
  36. package/lib/core/streams/codec-stream.js +2 -0
  37. package/lib/core/streams/common-crypto.js +2 -1
  38. package/lib/core/streams/zip-entry-stream.js +12 -10
  39. package/lib/core/util/sync-access-handle-temp-stream.js +2 -1
  40. package/lib/core/web-worker-base.js +27 -0
  41. package/lib/core/web-worker-inline-native.js +1 -1
  42. package/lib/core/web-worker-inline-wasm.js +1 -1
  43. package/lib/core/web-worker-native.js +7 -9
  44. package/lib/core/web-worker-wasm.js +9 -12
  45. package/lib/core/zip-fs.js +1 -1
  46. package/lib/core/zip-reader.js +58 -5
  47. package/lib/core/zip-writer.js +43 -8
  48. package/lib/zip-core-base.js +2 -1
  49. package/lib/{core/web-worker-inline-template.js → zip-core-custom.js} +13 -20
  50. package/lib/zip-core-reader.js +2 -1
  51. package/lib/zip-core-writer.js +10 -1
  52. package/lib/zip-module-native.js +3 -3
  53. package/lib/zip-module-wasm-base.js +3 -3
  54. package/package.json +20 -2
  55. package/lib/core/web-worker-inline-template-native.js +0 -48
  56. package/lib/core/zlib-streams-inline-template.js +0 -45
package/README.md CHANGED
@@ -3,8 +3,9 @@
3
3
  zip.js is a JavaScript open-source library (BSD-3-Clause license) for
4
4
  compressing and decompressing zip files. It has been designed to handle large amounts
5
5
  of data. It supports notably multi-core compression, native compression with
6
- compression streams, archives larger than 4GB with Zip64, split zip files, data
7
- encryption, incremental writing, and Deflate64 decompression.
6
+ compression streams, pluggable compression engines, archives larger than 4GB
7
+ with Zip64, split zip files, data encryption, incremental writing, and
8
+ Deflate64 decompression.
8
9
 
9
10
  # Demo
10
11
 
@@ -171,6 +172,31 @@ function downloadFile(blob) {
171
172
 
172
173
  Run the code on Plunker: https://plnkr.co/edit/4sVljNIpqSUE9HCA?preview
173
174
 
175
+ ## Custom web workers and compression engines
176
+
177
+ zip.js can create its web workers with the standard bundler pattern and
178
+ delegate compression/decompression to a custom engine, e.g.
179
+ [fflate](https://github.com/101arrowz/fflate):
180
+
181
+ ```js
182
+ import { configure } from "@zip.js/zip.js/lib/zip-core-custom.js";
183
+
184
+ configure({
185
+ createWorker: () => new Worker(new URL("./zip-worker.js", import.meta.url), { type: "module" })
186
+ });
187
+ ```
188
+
189
+ ```js
190
+ // zip-worker.js
191
+ import { initWorker } from "@zip.js/zip.js/worker";
192
+ import { CompressionStreamFallback, DecompressionStreamFallback } from "./fflate-streams.js";
193
+
194
+ initWorker({ CompressionStreamFallback, DecompressionStreamFallback });
195
+ ```
196
+
197
+ See https://gildas-lormeau.github.io/zip.js/#custom-workers for a complete
198
+ guide.
199
+
174
200
  ## Tests
175
201
 
176
202
  See https://github.com/gildas-lormeau/zip.js/tree/master/tests/all
package/deno.json CHANGED
@@ -1,12 +1,15 @@
1
1
  {
2
2
  "name": "@zip-js/zip-js",
3
- "version": "2.8.45",
3
+ "version": "2.8.47",
4
4
  "exports": {
5
5
  ".": "./index.js",
6
6
  "./external": "./lib/zip-fs-external.js",
7
7
  "./mime-types": "./lib/zip-mime-types.js",
8
8
  "./lib/zip-core-external.js": "./lib/zip-core-external.js",
9
- "./lib/zip-fs-core-external.js": "./lib/zip-fs-core-external.js"
9
+ "./lib/zip-fs-core-external.js": "./lib/zip-fs-core-external.js",
10
+ "./lib/zip-core-custom.js": "./lib/zip-core-custom.js",
11
+ "./worker": "./lib/core/web-worker-base.js",
12
+ "./lib/core/web-worker-base.js": "./lib/core/web-worker-base.js"
10
13
  },
11
14
  "publish": {
12
15
  "exclude": [
@@ -23,13 +26,20 @@
23
26
  "package-lock.json",
24
27
  ".npmignore",
25
28
  "eslint.config.mjs",
26
- "worker-message-property-names.js"
29
+ "worker-message-property-names.js",
30
+ "lib/core/web-worker-inline-template.js",
31
+ "lib/core/web-worker-inline-template-native.js",
32
+ "lib/core/zlib-streams-inline-template.js",
33
+ "lib/core/web-worker-inline-base.js"
27
34
  ]
28
35
  },
29
36
  "lint": {
30
37
  "exclude": [
31
38
  "dist/*.js",
32
39
  "*-inline.js",
40
+ "lib/core/web-worker-inline-wasm.js",
41
+ "lib/core/web-worker-inline-native.js",
42
+ "lib/core/zlib-streams-inline.js",
33
43
  "tests/",
34
44
  "benchmarks/",
35
45
  "**/*.cjs",
@@ -38,6 +38,7 @@ const LOCAL_FILE_HEADER_SIGNATURE = 0x04034b50;
38
38
  const SPLIT_ZIP_FILE_SIGNATURE = 0x08074b50;
39
39
  const DATA_DESCRIPTOR_RECORD_SIGNATURE = SPLIT_ZIP_FILE_SIGNATURE;
40
40
  const ARCHIVE_EXTRA_DATA_SIGNATURE = 0x08064b50;
41
+ const DIGITAL_SIGNATURE_RECORD_SIGNATURE = 0x05054b50;
41
42
  const CENTRAL_FILE_HEADER_SIGNATURE = 0x02014b50;
42
43
  const END_OF_CENTRAL_DIR_SIGNATURE = 0x06054b50;
43
44
  const ZIP64_END_OF_CENTRAL_DIR_SIGNATURE = 0x06064b50;
@@ -167,6 +168,7 @@ const CONFIGURABLE_PROPERTY_NAMES = [
167
168
  "baseURI",
168
169
  "wasmURI",
169
170
  "workerURI",
171
+ "createWorker",
170
172
  "chunkSize",
171
173
  "maxWorkers",
172
174
  "terminateWorkerTimeout",
@@ -177,8 +179,8 @@ const CONFIGURABLE_PROPERTY_NAMES = [
177
179
  "transferStreams",
178
180
  "CompressionStream",
179
181
  "DecompressionStream",
180
- "CompressionStreamZlib",
181
- "DecompressionStreamZlib"
182
+ "CompressionStreamFallback",
183
+ "DecompressionStreamFallback"
182
184
  ];
183
185
 
184
186
  const config = { ...DEFAULT_CONFIGURATION };
@@ -192,6 +194,7 @@ function getChunkSize(config) {
192
194
  }
193
195
 
194
196
  function configure(configuration) {
197
+ configuration = normalizeConfiguration(configuration);
195
198
  for (const propertyName of CONFIGURABLE_PROPERTY_NAMES) {
196
199
  const propertyValue = configuration[propertyName];
197
200
  if (propertyValue !== UNDEFINED_VALUE) {
@@ -200,7 +203,23 @@ function configure(configuration) {
200
203
  }
201
204
  }
202
205
 
206
+ function normalizeConfiguration(configuration) {
207
+ const { CompressionStreamZlib, DecompressionStreamZlib } = configuration;
208
+ if (CompressionStreamZlib === UNDEFINED_VALUE && DecompressionStreamZlib === UNDEFINED_VALUE) {
209
+ return configuration;
210
+ }
211
+ const normalizedConfiguration = Object.assign({}, configuration);
212
+ if (normalizedConfiguration.CompressionStreamFallback === UNDEFINED_VALUE) {
213
+ normalizedConfiguration.CompressionStreamFallback = CompressionStreamZlib;
214
+ }
215
+ if (normalizedConfiguration.DecompressionStreamFallback === UNDEFINED_VALUE) {
216
+ normalizedConfiguration.DecompressionStreamFallback = DecompressionStreamZlib;
217
+ }
218
+ return normalizedConfiguration;
219
+ }
220
+
203
221
  function setDefaultConfiguration(configuration) {
222
+ configuration = normalizeConfiguration(configuration);
204
223
  for (const propertyName of CONFIGURABLE_PROPERTY_NAMES) {
205
224
  const propertyValue = configuration[propertyName];
206
225
  if (propertyValue !== UNDEFINED_VALUE) {
@@ -1963,7 +1982,7 @@ const GZIP_OUTPUT_STALL_TIMEOUT = 5000;
1963
1982
 
1964
1983
  class DeflateStream extends TransformStream {
1965
1984
 
1966
- constructor(options, { chunkSize, CompressionStreamZlib, CompressionStream }) {
1985
+ constructor(options, { chunkSize, CompressionStreamFallback, CompressionStream }) {
1967
1986
  super({});
1968
1987
  const { compressed, encrypted, useCompressionStream, zipCrypto, computeCrc32, level, deflate64, format, compressionMethod } = options;
1969
1988
  const stream = this;
@@ -1985,7 +2004,7 @@ class DeflateStream extends TransformStream {
1985
2004
  readable = pipeThrough(readable, gzipCrc32Stream);
1986
2005
  } else {
1987
2006
  try {
1988
- readable = pipeThroughCompressionStream(readable, useCompressionStream, { level, chunkSize }, CompressionStream, CompressionStreamZlib);
2007
+ readable = pipeThroughCompressionStream(readable, useCompressionStream, { level, chunkSize }, CompressionStream, CompressionStreamFallback);
1989
2008
  } catch (error) {
1990
2009
  let gzipStream;
1991
2010
  try {
@@ -2127,7 +2146,7 @@ function pipeThroughGzipDecompressionStream(readable, gzipStream, outputSize) {
2127
2146
 
2128
2147
  class InflateStream extends TransformStream {
2129
2148
 
2130
- constructor(options, { chunkSize, DecompressionStreamZlib, DecompressionStream }) {
2149
+ constructor(options, { chunkSize, DecompressionStreamFallback, DecompressionStream }) {
2131
2150
  super({});
2132
2151
  const { zipCrypto, encrypted, checkCrc32, crc32, compressed, useCompressionStream, deflate64, format, compressionMethod, rawBitFlag, outputSize } = options;
2133
2152
  let crc32Stream, decryptionStream;
@@ -2146,7 +2165,7 @@ class InflateStream extends TransformStream {
2146
2165
  readable = pipeThroughBackpressured(readable, createCodecStream(codecStreams.DecompressionStream, format, { chunkSize, compressionMethod, rawBitFlag, uncompressedSize: outputSize }));
2147
2166
  } else {
2148
2167
  try {
2149
- readable = pipeThroughCompressionStream(readable, useCompressionStream, { chunkSize, deflate64 }, DecompressionStream, DecompressionStreamZlib);
2168
+ readable = pipeThroughCompressionStream(readable, useCompressionStream, { chunkSize, deflate64 }, DecompressionStream, DecompressionStreamFallback);
2150
2169
  } catch (error) {
2151
2170
  if (deflate64 || outputSize === UNDEFINED_VALUE) {
2152
2171
  throw error;
@@ -2225,17 +2244,17 @@ function createCodecStream(CodecStreamClass, format, options) {
2225
2244
  return new CodecStreamClass(format, options);
2226
2245
  }
2227
2246
 
2228
- function pipeThroughCompressionStream(readable, useCompressionStream, options, CompressionStreamNative, CompressionStreamZlib) {
2247
+ function pipeThroughCompressionStream(readable, useCompressionStream, options, CompressionStreamNative, CompressionStreamFallback) {
2229
2248
  const Stream = useCompressionStream && CompressionStreamNative ?
2230
2249
  CompressionStreamNative :
2231
- CompressionStreamZlib || CompressionStreamNative;
2250
+ CompressionStreamFallback || CompressionStreamNative;
2232
2251
  const format = options.deflate64 ? FORMAT_DEFLATE64_RAW : FORMAT_DEFLATE_RAW;
2233
2252
  let codecStream;
2234
2253
  try {
2235
2254
  codecStream = new Stream(format, options);
2236
2255
  } catch (error) {
2237
- if (useCompressionStream && CompressionStreamZlib && Stream != CompressionStreamZlib) {
2238
- codecStream = new CompressionStreamZlib(format, options);
2256
+ if (useCompressionStream && CompressionStreamFallback && Stream != CompressionStreamFallback) {
2257
+ codecStream = new CompressionStreamFallback(format, options);
2239
2258
  } else {
2240
2259
  throw error;
2241
2260
  }
@@ -2498,7 +2517,7 @@ const ERROR_EVENT_TYPE = "error";
2498
2517
  const MESSAGE_ERROR_EVENT_TYPE = "messageerror";
2499
2518
  const ERR_WORKER_STARTUP_TIMEOUT = "Worker startup timeout";
2500
2519
 
2501
- let webWorkerSupported, webWorkerSource, webWorkerURI, webWorkerOptions;
2520
+ let webWorkerSupported, webWorkerSource, webWorkerURI, webWorkerOptions, createWorkerFailed;
2502
2521
  let transferStreamsSupported = true;
2503
2522
  try {
2504
2523
  transferStreamsSupported = typeof structuredClone == FUNCTION_TYPE && structuredClone(new DOMException("", "AbortError")).code !== UNDEFINED_VALUE;
@@ -2512,14 +2531,14 @@ function configureWorker({ initModule: initModuleFunction }) {
2512
2531
  }
2513
2532
 
2514
2533
  async function supportsDeflate(config) {
2515
- const { CompressionStream: NativeStream, CompressionStreamZlib: ZlibStream } = config;
2516
- if (ZlibStream && !ZlibStream.requiresModule) {
2534
+ const { CompressionStream: NativeStream, CompressionStreamFallback: FallbackStream } = config;
2535
+ if (FallbackStream && !FallbackStream.requiresModule) {
2517
2536
  return true;
2518
2537
  }
2519
2538
  if (supportsDeflateRaw(NativeStream) || supportsGzip(NativeStream)) {
2520
2539
  return true;
2521
2540
  }
2522
- if (ZlibStream) {
2541
+ if (FallbackStream) {
2523
2542
  try {
2524
2543
  await initModule$1(config);
2525
2544
  return true;
@@ -2532,12 +2551,16 @@ async function supportsDeflate(config) {
2532
2551
 
2533
2552
  function resetWebWorkerSupport() {
2534
2553
  webWorkerSupported = UNDEFINED_VALUE;
2554
+ createWorkerFailed = false;
2535
2555
  }
2536
2556
 
2537
2557
  class CodecWorker {
2538
2558
 
2539
- constructor(workerData, { readable, writable }, { options, config, streamOptions, useWebWorkers, transferStreams, workerURI }, onTaskFinished) {
2559
+ constructor(workerData, { readable, writable }, { options, config, streamOptions, useWebWorkers, transferStreams, workerURI, createWorker }, onTaskFinished) {
2540
2560
  const { signal } = streamOptions;
2561
+ if (createWorkerFailed) {
2562
+ createWorker = UNDEFINED_VALUE;
2563
+ }
2541
2564
  Object.assign(workerData, {
2542
2565
  busy: true,
2543
2566
  generation: (workerData.generation || 0) + 1,
@@ -2547,6 +2570,7 @@ class CodecWorker {
2547
2570
  writable,
2548
2571
  options: Object.assign({}, options),
2549
2572
  workerURI,
2573
+ createWorker,
2550
2574
  transferStreams,
2551
2575
  terminate() {
2552
2576
  return new Promise(resolve => {
@@ -2582,7 +2606,7 @@ class CodecWorker {
2582
2606
  // deno-lint-ignore valid-typeof
2583
2607
  webWorkerSupported = typeof Worker != UNDEFINED_TYPE;
2584
2608
  }
2585
- return (useWebWorkers && webWorkerSupported ? createWebWorkerInterface : createWorkerInterface)(workerData, config);
2609
+ return (useWebWorkers && ((webWorkerSupported && workerURI) || createWorker) ? createWebWorkerInterface : createWorkerInterface)(workerData, config);
2586
2610
  }
2587
2611
  }
2588
2612
 
@@ -2639,7 +2663,11 @@ function createWebWorkerInterface(workerData, config) {
2639
2663
  try {
2640
2664
  worker = getWebWorker(workerData.workerURI, baseURI, workerData);
2641
2665
  } catch {
2642
- webWorkerSupported = false;
2666
+ if (workerData.createWorker) {
2667
+ createWorkerFailed = true;
2668
+ } else {
2669
+ webWorkerSupported = false;
2670
+ }
2643
2671
  return createWorkerInterface(workerData, config);
2644
2672
  }
2645
2673
  Object.assign(workerData, {
@@ -2652,7 +2680,11 @@ function createWebWorkerInterface(workerData, config) {
2652
2680
  return await runWebWorker(workerData, { chunkSize, wasmURI, baseURI, workerStartupTimeout });
2653
2681
  } catch (error) {
2654
2682
  if (error && error.workerStartupFailed) {
2655
- webWorkerSupported = false;
2683
+ if (workerData.createWorker) {
2684
+ createWorkerFailed = true;
2685
+ } else {
2686
+ webWorkerSupported = false;
2687
+ }
2656
2688
  const { reader } = workerData;
2657
2689
  if (reader) {
2658
2690
  reader.releaseLock();
@@ -2675,17 +2707,17 @@ async function runWorker$1({ options, readable, writable, onTaskFinished }, conf
2675
2707
  try {
2676
2708
  if (options.compressed && !options.format) {
2677
2709
  const deflate = options.codecType.startsWith(CODEC_DEFLATE);
2678
- const ZlibStream = deflate ? config.CompressionStreamZlib : config.DecompressionStreamZlib;
2710
+ const FallbackStream = deflate ? config.CompressionStreamFallback : config.DecompressionStreamFallback;
2679
2711
  const NativeStream = deflate ? config.CompressionStream : config.DecompressionStream;
2680
2712
  if (!options.useCompressionStream) {
2681
2713
  try {
2682
2714
  await initModule$1(config);
2683
2715
  } catch {
2684
- if (!ZlibStream || ZlibStream.requiresModule) {
2716
+ if (!FallbackStream || FallbackStream.requiresModule) {
2685
2717
  options.useCompressionStream = true;
2686
2718
  }
2687
2719
  }
2688
- } else if (ZlibStream && ZlibStream.requiresModule && !supportsDeflateRaw(NativeStream)) {
2720
+ } else if (FallbackStream && FallbackStream.requiresModule && !supportsDeflateRaw(NativeStream)) {
2689
2721
  try {
2690
2722
  await initModule$1(config);
2691
2723
  } catch {
@@ -2810,8 +2842,11 @@ function terminateWorker$1(workerData) {
2810
2842
  }
2811
2843
 
2812
2844
  function getWebWorker(url, baseURI, workerData, isModuleType, useBlobURI = true) {
2845
+ const { createWorker } = workerData;
2813
2846
  let worker, resolvedURI, resolvedOptions;
2814
- if (webWorkerURI === UNDEFINED_VALUE || webWorkerSource !== url) {
2847
+ if (createWorker) {
2848
+ worker = createWorker();
2849
+ } else if (webWorkerURI === UNDEFINED_VALUE || webWorkerSource !== url) {
2815
2850
  // deno-lint-ignore valid-typeof
2816
2851
  const isFunctionURI = typeof url == FUNCTION_TYPE;
2817
2852
  if (isFunctionURI) {
@@ -3066,7 +3101,7 @@ let indexWorker = 0;
3066
3101
  async function runWorker(stream, workerOptions) {
3067
3102
  const { options, config } = workerOptions;
3068
3103
  const { transferStreams, useWebWorkers, useCompressionStream, compressed, checkCrc32, computeCrc32, encrypted, format, codecURI } = options;
3069
- const { workerURI, maxWorkers } = config;
3104
+ const { workerURI, createWorker, maxWorkers } = config;
3070
3105
  if (format) {
3071
3106
  if (codecURI) {
3072
3107
  options.codecURI = resolveCodecURI(codecURI, config.baseURI);
@@ -3078,6 +3113,7 @@ async function runWorker(stream, workerOptions) {
3078
3113
  const workerSupported = format === UNDEFINED_VALUE || Boolean(options.codecURI);
3079
3114
  workerOptions.useWebWorkers = !streamCopy && workerSupported && (useWebWorkers || (useWebWorkers === UNDEFINED_VALUE && config.useWebWorkers));
3080
3115
  workerOptions.workerURI = workerOptions.useWebWorkers && workerURI ? workerURI : UNDEFINED_VALUE;
3116
+ workerOptions.createWorker = workerOptions.useWebWorkers && createWorker ? createWorker : UNDEFINED_VALUE;
3081
3117
  options.useCompressionStream = useCompressionStream || (useCompressionStream === UNDEFINED_VALUE && config.useCompressionStream);
3082
3118
  return (await getWorker()).run();
3083
3119
 
@@ -3141,7 +3177,7 @@ function onWorkerStarvation() {
3141
3177
  starvationTimeout = null;
3142
3178
  if (pendingRequests.length) {
3143
3179
  const [{ resolve, stream, workerOptions }] = pendingRequests.splice(0, 1);
3144
- const inlineWorkerOptions = Object.assign({}, workerOptions, { useWebWorkers: false, workerURI: UNDEFINED_VALUE });
3180
+ const inlineWorkerOptions = Object.assign({}, workerOptions, { useWebWorkers: false, workerURI: UNDEFINED_VALUE, createWorker: UNDEFINED_VALUE });
3145
3181
  resolve(new CodecWorker({}, stream, inlineWorkerOptions, onInlineTaskFinished));
3146
3182
  armStarvationTimeout();
3147
3183
  }
@@ -4450,6 +4486,8 @@ const OPTION_UNIX_EXTRA_FIELD_TYPE = "unixExtraFieldType";
4450
4486
  const OPTION_LOCAL_EXTRA_FIELD = "localExtraField";
4451
4487
  const OPTION_STRICTNESS = "strictness";
4452
4488
  const OPTION_MAX_APPENDED_DATA_SIZE = "maxAppendedDataSize";
4489
+ const OPTION_DECRYPT_CENTRAL_DIRECTORY = "decryptCentralDirectory";
4490
+ const OPTION_SIGN_CENTRAL_DIRECTORY = "signCentralDirectory";
4453
4491
  const STRICTNESS_STRICT = "strict";
4454
4492
  const STRICTNESS_BALANCED = "balanced";
4455
4493
  const STRICTNESS_TOLERANT = "tolerant";
@@ -4575,6 +4613,7 @@ class ZipReader {
4575
4613
  let startOffset;
4576
4614
  let zip64EndOfDirectory;
4577
4615
  let zip64EndOfDirectoryVersion2;
4616
+ let directoryEncryptionInfo;
4578
4617
  const requiresZip64 = directoryDataOffset == MAX_32_BITS || directoryDataLength == MAX_32_BITS || filesLength == MAX_16_BITS || diskNumber == MAX_16_BITS;
4579
4618
  if (directoryDataOffset != MAX_32_BITS && diskNumber != MAX_16_BITS) {
4580
4619
  directoryDataOffset += getDiskOffset$1(reader, diskNumber);
@@ -4605,6 +4644,15 @@ class ZipReader {
4605
4644
  }
4606
4645
  zip64EndOfDirectory = true;
4607
4646
  zip64EndOfDirectoryVersion2 = getBigUint64(endOfDirectoryView, 4) > ZIP64_END_OF_CENTRAL_DIR_LENGTH - 12;
4647
+ if (zip64EndOfDirectoryVersion2) {
4648
+ const extensibleDataLength = Math.min(
4649
+ Number(getBigUint64(endOfDirectoryView, 4)) - (ZIP64_END_OF_CENTRAL_DIR_LENGTH - 12),
4650
+ reader.size - directoryDataOffset - ZIP64_END_OF_CENTRAL_DIR_LENGTH);
4651
+ if (extensibleDataLength > 0) {
4652
+ const rawExtensibleData = await readUint8Array(reader, directoryDataOffset + ZIP64_END_OF_CENTRAL_DIR_LENGTH, extensibleDataLength);
4653
+ directoryEncryptionInfo = getDirectoryEncryptionInfo(rawExtensibleData);
4654
+ }
4655
+ }
4608
4656
  if (lastDiskNumber == MAX_16_BITS) {
4609
4657
  lastDiskNumber = getUint32(endOfDirectoryView, 16);
4610
4658
  } else if (checkAmbiguity && lastDiskNumber != getUint32(endOfDirectoryView, 16)) {
@@ -4628,7 +4676,7 @@ class ZipReader {
4628
4676
  directoryDataOffset = getDiskOffset$1(reader, diskNumber) + getBigUint64(endOfDirectoryView, 48) + prependedDataLength;
4629
4677
  }
4630
4678
  }
4631
- const declaredDirectoryDataLength = directoryDataLength;
4679
+ let declaredDirectoryDataLength = directoryDataLength;
4632
4680
  const centralDirectoryEndOffset = endOfDirectoryInfo.offset -
4633
4681
  (zip64EndOfDirectory ? ZIP64_END_OF_CENTRAL_DIR_LENGTH + ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH : 0);
4634
4682
  if (directoryDataOffset >= reader.size) {
@@ -4676,6 +4724,18 @@ class ZipReader {
4676
4724
  if (directoryDataOffset < 0 || directoryDataOffset >= reader.size) {
4677
4725
  throw new Error(ERR_BAD_FORMAT);
4678
4726
  }
4727
+ zipReader.directoryOffset = directoryDataOffset;
4728
+ zipReader.directoryLength = declaredDirectoryDataLength;
4729
+ const decryptCentralDirectory = getOptionValue$1(zipReader, options, OPTION_DECRYPT_CENTRAL_DIRECTORY);
4730
+ let decryptedDirectory;
4731
+ if (decryptCentralDirectory && filesLength && directoryArray.length >= 4 &&
4732
+ getUint32(directoryView, 0) != CENTRAL_FILE_HEADER_SIGNATURE &&
4733
+ (zip64EndOfDirectoryVersion2 || detectEncryptedCentralDirectory(directoryView))) {
4734
+ directoryArray = await decryptCentralDirectory(directoryArray, directoryEncryptionInfo);
4735
+ directoryView = getDataView(directoryArray);
4736
+ declaredDirectoryDataLength = directoryArray.length;
4737
+ decryptedDirectory = true;
4738
+ }
4679
4739
  startOffset = directoryDataOffset;
4680
4740
  const filenameEncoding = getOptionValue$1(zipReader, options, OPTION_FILENAME_ENCODING);
4681
4741
  const commentEncoding = getOptionValue$1(zipReader, options, OPTION_COMMENT_ENCODING);
@@ -4684,7 +4744,7 @@ class ZipReader {
4684
4744
  for (let indexFile = 0; indexFile < filesLength; indexFile++) {
4685
4745
  const fileEntry = new ZipEntry(reader, config, zipReader.options);
4686
4746
  if (offset + CENTRAL_FILE_HEADER_LENGTH > directoryArray.length || getUint32(directoryView, offset) != CENTRAL_FILE_HEADER_SIGNATURE) {
4687
- if (indexFile == 0 && (zip64EndOfDirectoryVersion2 || detectEncryptedCentralDirectory(directoryView))) {
4747
+ if (indexFile == 0 && !decryptedDirectory && (zip64EndOfDirectoryVersion2 || detectEncryptedCentralDirectory(directoryView))) {
4688
4748
  throw new Error(ERR_ENCRYPTED_CENTRAL_DIRECTORY);
4689
4749
  }
4690
4750
  throw new Error(ERR_CENTRAL_DIRECTORY_NOT_FOUND);
@@ -4797,7 +4857,15 @@ class ZipReader {
4797
4857
  }
4798
4858
  yield entry;
4799
4859
  }
4800
- if (checkAmbiguity && offset != declaredDirectoryDataLength) {
4860
+ let offsetAfterSignature = offset;
4861
+ if (offset + 6 <= directoryArray.length && getUint32(directoryView, offset) == DIGITAL_SIGNATURE_RECORD_SIGNATURE) {
4862
+ const signatureDataLength = getUint16(directoryView, offset + 4);
4863
+ if (offset + 6 + signatureDataLength <= directoryArray.length) {
4864
+ zipReader.digitalSignature = directoryArray.subarray(offset + 6, offset + 6 + signatureDataLength);
4865
+ offsetAfterSignature = offset + 6 + signatureDataLength;
4866
+ }
4867
+ }
4868
+ if (checkAmbiguity && offset != declaredDirectoryDataLength && offsetAfterSignature != declaredDirectoryDataLength) {
4801
4869
  throwAmbiguousArchive("trailing central directory data");
4802
4870
  }
4803
4871
  if (duplicateFilename) {
@@ -5069,6 +5137,25 @@ function detectEncryptedCentralDirectory(directoryView) {
5069
5137
  return false;
5070
5138
  }
5071
5139
 
5140
+ function getDirectoryEncryptionInfo(rawExtensibleData) {
5141
+ const directoryEncryptionInfo = { rawExtensibleData };
5142
+ if (rawExtensibleData.length >= 28) {
5143
+ const extensibleDataView = getDataView(rawExtensibleData);
5144
+ const hashDataLength = getUint16(extensibleDataView, 26);
5145
+ Object.assign(directoryEncryptionInfo, {
5146
+ compressionMethod: getUint16(extensibleDataView, 0),
5147
+ compressedSize: Number(getBigUint64(extensibleDataView, 2)),
5148
+ uncompressedSize: Number(getBigUint64(extensibleDataView, 10)),
5149
+ encryptionAlgorithm: getUint16(extensibleDataView, 18),
5150
+ bitLength: getUint16(extensibleDataView, 20),
5151
+ flags: getUint16(extensibleDataView, 22),
5152
+ hashAlgorithm: getUint16(extensibleDataView, 24),
5153
+ hashData: rawExtensibleData.subarray(28, 28 + hashDataLength)
5154
+ });
5155
+ }
5156
+ return directoryEncryptionInfo;
5157
+ }
5158
+
5072
5159
  function readCommonHeader(directory, dataView, offset) {
5073
5160
  const rawBitFlag = directory.rawBitFlag = getUint16(dataView, offset + 2);
5074
5161
  const encrypted = (rawBitFlag & BITFLAG_ENCRYPTED) == BITFLAG_ENCRYPTED;
@@ -5620,6 +5707,7 @@ var zipReader = /*#__PURE__*/Object.freeze({
5620
5707
  ERR_SPLIT_ZIP_FILE: ERR_SPLIT_ZIP_FILE,
5621
5708
  ERR_UNSUPPORTED_COMPRESSION: ERR_UNSUPPORTED_COMPRESSION$1,
5622
5709
  ERR_UNSUPPORTED_ENCRYPTION: ERR_UNSUPPORTED_ENCRYPTION,
5710
+ ERR_WORKER_STARTUP_TIMEOUT: ERR_WORKER_STARTUP_TIMEOUT,
5623
5711
  ZipReader: ZipReader,
5624
5712
  ZipReaderStream: ZipReaderStream
5625
5713
  });
@@ -5678,6 +5766,7 @@ const ERR_INVALID_UNIX_EXTRA_FIELD_TYPE = "Invalid unixExtraFieldType (must be '
5678
5766
  const ERR_INVALID_UNIX_ID_SIZE = "uid/gid must be 0..65535 for unixExtraFieldType 'unix' (use 'infozip' for larger ids)";
5679
5767
  const ERR_INVALID_MSDOS_ATTRIBUTES = "Invalid msdosAttributesRaw (must be integer 0..255)";
5680
5768
  const ERR_INVALID_MSDOS_DATA = "Invalid msdosAttributes (must be an object with boolean flags)";
5769
+ const ERR_INVALID_SIGNATURE_DATA = "Signature data exceeds 64KB";
5681
5770
 
5682
5771
  const EXTRAFIELD_DATA_AES = new Uint8Array([0x07, 0x00, 0x02, 0x00, 0x41, 0x45, 0x03, 0x00, 0x00]);
5683
5772
  const EXTRAFIELD_OFFSET_AES_VENDOR_VERSION = 4;
@@ -7037,8 +7126,9 @@ function updateLocalHeader({
7037
7126
 
7038
7127
  async function closeFile(zipWriter, comment, options) {
7039
7128
  const directoryDataLength = createDirectoryRecords(zipWriter.files);
7040
- const directoryStart = await writeDirectoryRecords(zipWriter, directoryDataLength, options);
7041
- await writeEndOfDirectoryRecord(zipWriter, comment, options, { directoryStart, directoryDataLength });
7129
+ const { directoryStart, directoryArray } = await writeDirectoryRecords(zipWriter, directoryDataLength, options);
7130
+ const signatureLength = await writeDigitalSignatureRecord(zipWriter, directoryArray, options);
7131
+ await writeEndOfDirectoryRecord(zipWriter, comment, options, { directoryStart, directoryDataLength, signatureLength });
7042
7132
  }
7043
7133
 
7044
7134
  function createDirectoryRecords(files) {
@@ -7195,12 +7285,33 @@ async function writeDirectoryRecords(zipWriter, directoryDataLength, options) {
7195
7285
  }
7196
7286
  }
7197
7287
  await writeData(writer, directoryDiskOffset ? directoryArray.slice(directoryDiskOffset) : directoryArray);
7198
- return { diskNumber: directoryStartDiskNumber, diskOffset: directoryStartDiskOffset };
7288
+ return {
7289
+ directoryStart: { diskNumber: directoryStartDiskNumber, diskOffset: directoryStartDiskOffset },
7290
+ directoryArray
7291
+ };
7292
+ }
7293
+
7294
+ async function writeDigitalSignatureRecord(zipWriter, directoryArray, options) {
7295
+ const signCentralDirectory = getOptionValue(zipWriter, options, OPTION_SIGN_CENTRAL_DIRECTORY);
7296
+ if (signCentralDirectory) {
7297
+ const signatureData = await signCentralDirectory(directoryArray);
7298
+ const signatureDataLength = getLength(signatureData);
7299
+ if (signatureDataLength > MAX_16_BITS) {
7300
+ throw new Error(ERR_INVALID_SIGNATURE_DATA);
7301
+ }
7302
+ const signatureRecord = createRecordWriter(6 + signatureDataLength);
7303
+ signatureRecord.uint32(DIGITAL_SIGNATURE_RECORD_SIGNATURE);
7304
+ signatureRecord.uint16(signatureDataLength);
7305
+ signatureRecord.bytes(signatureData);
7306
+ await writeData(zipWriter.writer, signatureRecord.array);
7307
+ return 6 + signatureDataLength;
7308
+ }
7309
+ return 0;
7199
7310
  }
7200
7311
 
7201
7312
  async function writeEndOfDirectoryRecord(zipWriter, comment, options, cdInfo) {
7202
7313
  const { writer } = zipWriter;
7203
- const { directoryStart } = cdInfo;
7314
+ const { directoryStart, signatureLength } = cdInfo;
7204
7315
  let { directoryDataLength } = cdInfo;
7205
7316
  let filesLength = zipWriter.files.size;
7206
7317
  let diskNumber = directoryStart.diskNumber;
@@ -7239,7 +7350,7 @@ async function writeEndOfDirectoryRecord(zipWriter, comment, options, cdInfo) {
7239
7350
  endOfdirectoryRecord.uint64(directoryOffset);
7240
7351
  endOfdirectoryRecord.uint32(ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIGNATURE);
7241
7352
  endOfdirectoryRecord.uint32(lastDiskNumber);
7242
- endOfdirectoryRecord.uint64(BigInt(getSegmentOffset(zipWriter, writer)) + BigInt(directoryDataLength));
7353
+ endOfdirectoryRecord.uint64(BigInt(getSegmentOffset(zipWriter, writer)) + BigInt(directoryDataLength) + BigInt(signatureLength));
7243
7354
  endOfdirectoryRecord.uint32(lastDiskNumber + 1);
7244
7355
  const supportZip64SplitFile = getOptionValue(zipWriter, options, OPTION_SUPPORT_ZIP64_SPLIT_FILE, true);
7245
7356
  if (supportZip64SplitFile) {
@@ -8278,8 +8389,8 @@ configureWorker({
8278
8389
  }
8279
8390
  });
8280
8391
  setDefaultConfiguration({
8281
- CompressionStreamZlib,
8282
- DecompressionStreamZlib
8392
+ CompressionStreamFallback: CompressionStreamZlib,
8393
+ DecompressionStreamFallback: DecompressionStreamZlib
8283
8394
  });
8284
8395
 
8285
8396
  function terminateWorkersAndModule() {
@@ -8293,4 +8404,4 @@ function terminateWorkersAndModule() {
8293
8404
 
8294
8405
  configureExternalAssets();
8295
8406
 
8296
- export { BlobReader, BlobWriter, Data64URIReader, Data64URIWriter, ERR_AMBIGUOUS_ARCHIVE, ERR_BAD_FORMAT, ERR_CENTRAL_DIRECTORY_NOT_FOUND, ERR_DUPLICATED_NAME, ERR_ENCRYPTED, ERR_ENCRYPTED_CENTRAL_DIRECTORY, ERR_EOCDR_LOCATOR_ZIP64_NOT_FOUND, ERR_EOCDR_NOT_FOUND, ERR_EXTRAFIELD_ZIP64_NOT_FOUND, ERR_HTTP_RANGE, ERR_HTTP_RESOURCE_CHANGED, ERR_INVALID_AUTHENTICATION_CODE, ERR_INVALID_CODEC_DEFINITION, ERR_INVALID_CODEC_MODULE, ERR_INVALID_COMMENT, ERR_INVALID_COMPRESSED_DATA, ERR_INVALID_CRC32, ERR_INVALID_ENCRYPTION_STRENGTH, ERR_INVALID_ENTRY_COMMENT, ERR_INVALID_ENTRY_NAME, ERR_INVALID_EXTRAFIELD_DATA, ERR_INVALID_EXTRAFIELD_TYPE, ERR_INVALID_PASSWORD, ERR_INVALID_SIGNATURE, ERR_INVALID_UNCOMPRESSED_SIZE, ERR_INVALID_VERSION, ERR_ITERATOR_COMPLETED_TOO_SOON, ERR_LOCAL_FILE_HEADER_NOT_FOUND, ERR_OVERLAPPING_ENTRY, ERR_RESERVED_COMPRESSION_METHOD, ERR_SPLIT_ZIP_FILE, ERR_UNDEFINED_READER, ERR_UNDEFINED_UNCOMPRESSED_SIZE, ERR_UNSUPPORTED_COMPRESSION$1 as ERR_UNSUPPORTED_COMPRESSION, ERR_UNSUPPORTED_ENCRYPTION, ERR_UNSUPPORTED_ENCRYPTION_USDZ, ERR_UNSUPPORTED_FORMAT, ERR_WRITER_NOT_INITIALIZED, ERR_ZIP_NOT_EMPTY, HttpRangeReader, HttpReader, Reader, SplitDataReader, SplitDataWriter, TextReader, TextWriter, Uint8ArrayReader, Uint8ArrayWriter, Writer, ZipReader, ZipReaderStream, ZipWriter, ZipWriterStream, configure, createBlobTempStream, createOPFSTempStream, createSyncAccessHandleTempStream, getMimeType, registerCodec, resetConfiguration, terminateWorkersAndModule as terminateWorkers, unregisterCodec };
8407
+ export { BlobReader, BlobWriter, Data64URIReader, Data64URIWriter, ERR_AMBIGUOUS_ARCHIVE, ERR_BAD_FORMAT, ERR_CENTRAL_DIRECTORY_NOT_FOUND, ERR_DUPLICATED_NAME, ERR_ENCRYPTED, ERR_ENCRYPTED_CENTRAL_DIRECTORY, ERR_EOCDR_LOCATOR_ZIP64_NOT_FOUND, ERR_EOCDR_NOT_FOUND, ERR_EXTRAFIELD_ZIP64_NOT_FOUND, ERR_HTTP_RANGE, ERR_HTTP_RESOURCE_CHANGED, ERR_INVALID_AUTHENTICATION_CODE, ERR_INVALID_CODEC_DEFINITION, ERR_INVALID_CODEC_MODULE, ERR_INVALID_COMMENT, ERR_INVALID_COMPRESSED_DATA, ERR_INVALID_CRC32, ERR_INVALID_ENCRYPTION_STRENGTH, ERR_INVALID_ENTRY_COMMENT, ERR_INVALID_ENTRY_NAME, ERR_INVALID_EXTRAFIELD_DATA, ERR_INVALID_EXTRAFIELD_TYPE, ERR_INVALID_GID, ERR_INVALID_MSDOS_ATTRIBUTES, ERR_INVALID_MSDOS_DATA, ERR_INVALID_PASSWORD, ERR_INVALID_SIGNATURE, ERR_INVALID_SIGNATURE_DATA, ERR_INVALID_UID, ERR_INVALID_UNCOMPRESSED_SIZE, ERR_INVALID_UNIX_EXTRA_FIELD_TYPE, ERR_INVALID_UNIX_ID_SIZE, ERR_INVALID_UNIX_MODE, ERR_INVALID_VERSION, ERR_ITERATOR_COMPLETED_TOO_SOON, ERR_LOCAL_FILE_HEADER_NOT_FOUND, ERR_OVERLAPPING_ENTRY, ERR_RESERVED_COMPRESSION_METHOD, ERR_SPLIT_ZIP_FILE, ERR_UNDEFINED_READER, ERR_UNDEFINED_UNCOMPRESSED_SIZE, ERR_UNSUPPORTED_COMPRESSION$1 as ERR_UNSUPPORTED_COMPRESSION, ERR_UNSUPPORTED_CONTEXT, ERR_UNSUPPORTED_CRYPTO_API, ERR_UNSUPPORTED_ENCRYPTION, ERR_UNSUPPORTED_ENCRYPTION_USDZ, ERR_UNSUPPORTED_FORMAT, ERR_WORKER_STARTUP_TIMEOUT, ERR_WRITER_NOT_INITIALIZED, ERR_ZIP_NOT_EMPTY, HttpRangeReader, HttpReader, Reader, SplitDataReader, SplitDataWriter, TextReader, TextWriter, Uint8ArrayReader, Uint8ArrayWriter, Writer, ZipReader, ZipReaderStream, ZipWriter, ZipWriterStream, configure, createBlobTempStream, createOPFSTempStream, createSyncAccessHandleTempStream, getMimeType, registerCodec, resetConfiguration, terminateWorkersAndModule as terminateWorkers, unregisterCodec };