single-file-core 1.5.88 → 1.5.89

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/vendor/zip/zip.js CHANGED
@@ -38,6 +38,7 @@ const COMPRESSION_METHOD_AES = 0x63;
38
38
 
39
39
  const LOCAL_FILE_HEADER_SIGNATURE = 0x04034b50;
40
40
  const SPLIT_ZIP_FILE_SIGNATURE = 0x08074b50;
41
+ const TEMPORARY_SPLIT_ZIP_FILE_SIGNATURE = 0x30304b50;
41
42
  const DATA_DESCRIPTOR_RECORD_SIGNATURE = SPLIT_ZIP_FILE_SIGNATURE;
42
43
  const ARCHIVE_EXTRA_DATA_SIGNATURE = 0x08064b50;
43
44
  const DIGITAL_SIGNATURE_RECORD_SIGNATURE = 0x05054b50;
@@ -54,6 +55,7 @@ const ZIP64_END_OF_CENTRAL_DIR_TOTAL_LENGTH = END_OF_CENTRAL_DIR_LENGTH + ZIP64_
54
55
  const DATA_DESCRIPTOR_RECORD_LENGTH = 12;
55
56
  const DATA_DESCRIPTOR_RECORD_ZIP_64_LENGTH = 20;
56
57
  const DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH = 4;
58
+ const SPLIT_ZIP_FILE_SIGNATURE_LENGTH = 4;
57
59
 
58
60
  const EXTRAFIELD_TYPE_ZIP64 = 0x0001;
59
61
  const EXTRAFIELD_TYPE_AES = 0x9901;
@@ -74,8 +76,10 @@ const BITFLAG_LEVEL_MAX_MASK = 0b010;
74
76
  const BITFLAG_LEVEL_FAST_MASK = 0b100;
75
77
  const BITFLAG_LEVEL_SUPER_FAST_MASK = 0b110;
76
78
  const BITFLAG_DATA_DESCRIPTOR = 0b1000;
79
+ const BITFLAG_COMPRESSED_PATCHED_DATA = 0b100000;
77
80
  const BITFLAG_STRONG_ENCRYPTION = 0b1000000;
78
81
  const BITFLAG_LANG_ENCODING_FLAG = 0b100000000000;
82
+ const BITFLAG_MASKED_LOCAL_HEADERS = 0b10000000000000;
79
83
  const FILE_ATTR_MSDOS_DIR_MASK = 0b10000;
80
84
  const FILE_ATTR_MSDOS_READONLY_MASK = 0x01;
81
85
  const FILE_ATTR_MSDOS_HIDDEN_MASK = 0x02;
@@ -83,16 +87,22 @@ const FILE_ATTR_MSDOS_SYSTEM_MASK = 0x04;
83
87
  const FILE_ATTR_MSDOS_ARCHIVE_MASK = 0x20;
84
88
  const FILE_ATTR_UNIX_TYPE_MASK = 0o170000;
85
89
  const FILE_ATTR_UNIX_TYPE_DIR = 0o040000;
90
+ const FILE_ATTR_UNIX_TYPE_SYMLINK = 0o120000;
91
+ const FILE_ATTR_UNIX_TYPE_FILE = 0o100000;
86
92
  const FILE_ATTR_UNIX_EXECUTABLE_MASK = 0o111;
87
93
  const FILE_ATTR_UNIX_DEFAULT_MASK = 0o644;
88
94
  const FILE_ATTR_UNIX_SETUID_MASK = 0o4000;
89
95
  const FILE_ATTR_UNIX_SETGID_MASK = 0o2000;
90
96
  const FILE_ATTR_UNIX_STICKY_MASK = 0o1000;
91
97
 
98
+ const VERSION_STORE = 0x0A;
92
99
  const VERSION_DEFLATE = 0x14;
93
100
  const VERSION_ZIP64 = 0x2D;
94
101
  const VERSION_AES = 0x33;
95
102
 
103
+ const VERSION_MADE_BY_MSDOS = 0x0014;
104
+ const VERSION_MADE_BY_UNIX = 0x0300;
105
+
96
106
  const DIRECTORY_SIGNATURE = "/";
97
107
 
98
108
  const HEADER_SIZE = 30;
@@ -100,6 +110,8 @@ const HEADER_OFFSET_VERSION = 0;
100
110
  const HEADER_OFFSET_SIGNATURE = 10;
101
111
  const HEADER_OFFSET_COMPRESSED_SIZE = 14;
102
112
  const HEADER_OFFSET_UNCOMPRESSED_SIZE = 18;
113
+ const HEADER_OFFSET_FILENAME_LENGTH = 22;
114
+ const HEADER_OFFSET_EXTRAFIELD_LENGTH = 24;
103
115
  const LOCAL_HEADER_COMMON_OFFSET = 4;
104
116
 
105
117
  const MAX_DATE = new Date(2107, 11, 31, 23, 59, 58);
@@ -112,9 +124,129 @@ const FUNCTION_TYPE = "function";
112
124
  const OBJECT_TYPE = "object";
113
125
  const STRING_TYPE = "string";
114
126
  const NUMBER_TYPE = "number";
127
+ const BOOLEAN_TYPE = "boolean";
115
128
 
116
129
  const EMPTY_UINT8_ARRAY = new Uint8Array();
117
130
 
131
+ /*
132
+ Copyright (c) 2022 Gildas Lormeau. All rights reserved.
133
+
134
+ Redistribution and use in source and binary forms, with or without
135
+ modification, are permitted provided that the following conditions are met:
136
+
137
+ 1. Redistributions of source code must retain the above copyright notice,
138
+ this list of conditions and the following disclaimer.
139
+
140
+ 2. Redistributions in binary form must reproduce the above copyright
141
+ notice, this list of conditions and the following disclaimer in
142
+ the documentation and/or other materials provided with the distribution.
143
+
144
+ 3. The names of the authors may not be used to endorse or promote products
145
+ derived from this software without specific prior written permission.
146
+
147
+ THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
148
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
149
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
150
+ INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
151
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
152
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
153
+ OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
154
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
155
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
156
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
157
+ */
158
+
159
+
160
+ const OPTION_FILENAME_ENCODING = "filenameEncoding";
161
+ const OPTION_COMMENT_ENCODING = "commentEncoding";
162
+ const OPTION_DECODE_TEXT = "decodeText";
163
+ const OPTION_EXTRACT_PREPENDED_DATA = "extractPrependedData";
164
+ const OPTION_EXTRACT_APPENDED_DATA = "extractAppendedData";
165
+ const OPTION_PASSWORD = "password";
166
+ const OPTION_RAW_PASSWORD = "rawPassword";
167
+ const OPTION_PASS_THROUGH = "passThrough";
168
+ const OPTION_SIGNAL = "signal";
169
+ const OPTION_CHECK_PASSWORD_ONLY = "checkPasswordOnly";
170
+ const OPTION_CHECK_OVERLAPPING_ENTRY_ONLY = "checkOverlappingEntryOnly";
171
+ const OPTION_CHECK_OVERLAPPING_ENTRY = "checkOverlappingEntry";
172
+ const OPTION_CHECK_AMBIGUITY = "checkAmbiguity";
173
+ const OPTION_CHECK_LOCAL_DIRECTORY = "checkLocalDirectory";
174
+ const OPTION_CHECK_SIGNATURE = "checkSignature";
175
+ const OPTION_CHECK_CRC32 = "checkCrc32";
176
+ const OPTION_CHECK_AUTHENTICATION_CODE = "checkAuthenticationCode";
177
+ const OPTION_USE_WEB_WORKERS = "useWebWorkers";
178
+ const OPTION_USE_COMPRESSION_STREAM = "useCompressionStream";
179
+ const OPTION_TRANSFER_STREAMS = "transferStreams";
180
+ const OPTION_PREVENT_CLOSE = "preventClose";
181
+ const OPTION_ENCRYPTION_STRENGTH = "encryptionStrength";
182
+ const OPTION_EXTENDED_TIMESTAMP = "extendedTimestamp";
183
+ const OPTION_NTFS_TIMESTAMP = "ntfsTimestamp";
184
+ const OPTION_KEEP_ORDER = "keepOrder";
185
+ const OPTION_LEVEL = "level";
186
+ const OPTION_BUFFERED_WRITE = "bufferedWrite";
187
+ const OPTION_CREATE_TEMP_STREAM = "createTempStream";
188
+ const OPTION_DATA_DESCRIPTOR_SIGNATURE = "dataDescriptorSignature";
189
+ const OPTION_USE_UNICODE_FILE_NAMES = "useUnicodeFileNames";
190
+ const OPTION_DATA_DESCRIPTOR = "dataDescriptor";
191
+ const OPTION_SUPPORT_ZIP64_SPLIT_FILE = "supportZip64SplitFile";
192
+ const OPTION_ENCODE_TEXT = "encodeText";
193
+ const OPTION_OFFSET = "offset";
194
+ const OPTION_USDZ = "usdz";
195
+ const OPTION_UNIX_EXTRA_FIELD_TYPE = "unixExtraFieldType";
196
+ const OPTION_LOCAL_EXTRA_FIELD = "localExtraField";
197
+ const OPTION_CENTRAL_EXTRA_FIELD = "centralExtraField";
198
+ const OPTION_STRICTNESS = "strictness";
199
+ const OPTION_FILENAME_VALIDATION = "filenameValidation";
200
+ const OPTION_NORMALIZE_FILENAME = "normalizeFilename";
201
+ const OPTION_MAX_APPENDED_DATA_SIZE = "maxAppendedDataSize";
202
+ const OPTION_DECRYPT_CENTRAL_DIRECTORY = "decryptCentralDirectory";
203
+ const OPTION_SIGN_CENTRAL_DIRECTORY = "signCentralDirectory";
204
+ const TEXT_TYPE_FILENAME = "filename";
205
+ const TEXT_TYPE_COMMENT = "comment";
206
+ const STRICTNESS_STRICT = "strict";
207
+ const STRICTNESS_BALANCED = "balanced";
208
+ const STRICTNESS_TOLERANT = "tolerant";
209
+
210
+ const ERR_INVALID_FUNCTION_OPTION = "Invalid option (must be a function)";
211
+ const ERR_INVALID_SIGNAL = "Invalid signal (must be an AbortSignal instance)";
212
+ const ERR_INVALID_PASSWORD_TYPE = "Invalid password (password must be a string, rawPassword must be a Uint8Array)";
213
+
214
+ function checkFunctionOption(value) {
215
+ if (value && typeof value != FUNCTION_TYPE) {
216
+ throw new Error(ERR_INVALID_FUNCTION_OPTION);
217
+ }
218
+ return value;
219
+ }
220
+
221
+ function checkSignalOption(signal) {
222
+ if (signal && (typeof signal.addEventListener != FUNCTION_TYPE || typeof signal.aborted != BOOLEAN_TYPE)) {
223
+ throw new Error(ERR_INVALID_SIGNAL);
224
+ }
225
+ return signal || UNDEFINED_VALUE;
226
+ }
227
+
228
+ function checkPasswordOption(password, rawPassword) {
229
+ if ((password && typeof password != STRING_TYPE) || (rawPassword && !(rawPassword instanceof Uint8Array))) {
230
+ throw new Error(ERR_INVALID_PASSWORD_TYPE);
231
+ }
232
+ }
233
+
234
+ function checkInteger(value, maxValue, errorMessage) {
235
+ if (!Number.isInteger(value) || value < 0 || value > maxValue) {
236
+ throw new Error(errorMessage);
237
+ }
238
+ }
239
+
240
+ function checkIntegerOption(value, maxValue, errorMessage) {
241
+ if (value !== UNDEFINED_VALUE) {
242
+ checkInteger(value, maxValue, errorMessage);
243
+ }
244
+ }
245
+
246
+ function toNumber(value) {
247
+ return typeof value == STRING_TYPE && value.trim() ? Number(value) : value;
248
+ }
249
+
118
250
  /*
119
251
  Copyright (c) 2025 Gildas Lormeau. All rights reserved.
120
252
 
@@ -144,7 +276,10 @@ const EMPTY_UINT8_ARRAY = new Uint8Array();
144
276
  */
145
277
 
146
278
 
279
+ const DEFAULT_CHUNK_SIZE$1 = 64 * 1024;
147
280
  const MINIMUM_CHUNK_SIZE = 64;
281
+ const MINIMUM_PROPERTY_VALUE = 1;
282
+ const ERR_INVALID_MAX_WORKERS = "Invalid maxWorkers (must be an integer greater than 0)";
148
283
  let maxWorkers = 2;
149
284
  try {
150
285
  if (typeof navigator != UNDEFINED_TYPE && navigator.hardwareConcurrency) {
@@ -156,7 +291,7 @@ try {
156
291
  const DEFAULT_CONFIGURATION = {
157
292
  workerURI: "./core/web-worker-wasm.js",
158
293
  wasmURI: "./core/streams/zlib-wasm/zlib-streams.wasm",
159
- chunkSize: 64 * 1024,
294
+ chunkSize: DEFAULT_CHUNK_SIZE$1,
160
295
  maxWorkers,
161
296
  terminateWorkerTimeout: 5000,
162
297
  workerStarvationTimeout: 5000,
@@ -168,24 +303,38 @@ const DEFAULT_CONFIGURATION = {
168
303
  DecompressionStream: typeof DecompressionStream != UNDEFINED_TYPE && DecompressionStream
169
304
  };
170
305
 
171
- const CONFIGURABLE_PROPERTY_NAMES = [
306
+ const PROPERTY_NAME_MAX_WORKERS = "maxWorkers";
307
+
308
+ const STRING_PROPERTY_NAMES = [
172
309
  "baseURI",
173
310
  "wasmURI",
174
- "workerURI",
175
- "createWorker",
311
+ "workerURI"
312
+ ];
313
+ const BOOLEAN_PROPERTY_NAMES = [
314
+ "useCompressionStream",
315
+ "useWebWorkers",
316
+ "transferStreams"
317
+ ];
318
+ const NUMBER_PROPERTY_NAMES = [
176
319
  "chunkSize",
177
- "maxWorkers",
320
+ PROPERTY_NAME_MAX_WORKERS,
178
321
  "terminateWorkerTimeout",
179
322
  "workerStarvationTimeout",
180
- "workerStartupTimeout",
181
- "useCompressionStream",
182
- "useWebWorkers",
183
- "transferStreams",
323
+ "workerStartupTimeout"
324
+ ];
325
+ const FUNCTION_PROPERTY_NAMES = [
326
+ "createWorker",
184
327
  "CompressionStream",
185
328
  "DecompressionStream",
186
329
  "CompressionStreamFallback",
187
330
  "DecompressionStreamFallback"
188
331
  ];
332
+ const CONFIGURABLE_PROPERTY_NAMES = [
333
+ ...STRING_PROPERTY_NAMES,
334
+ ...BOOLEAN_PROPERTY_NAMES,
335
+ ...NUMBER_PROPERTY_NAMES,
336
+ ...FUNCTION_PROPERTY_NAMES
337
+ ];
189
338
 
190
339
  const config = { ...DEFAULT_CONFIGURATION };
191
340
 
@@ -194,20 +343,43 @@ function getConfiguration() {
194
343
  }
195
344
 
196
345
  function getChunkSize(config) {
197
- return Math.max(config.chunkSize, MINIMUM_CHUNK_SIZE);
346
+ return normalizeChunkSize(config.chunkSize);
347
+ }
348
+
349
+ function normalizeChunkSize(chunkSize) {
350
+ chunkSize = toNumber(chunkSize);
351
+ return Number.isInteger(chunkSize) && chunkSize >= MINIMUM_PROPERTY_VALUE ? Math.max(chunkSize, MINIMUM_CHUNK_SIZE) : DEFAULT_CHUNK_SIZE$1;
198
352
  }
199
353
 
200
354
  function configure(configuration) {
201
- configuration = normalizeConfiguration(configuration);
355
+ Object.assign(config, checkConfiguration(normalizeConfiguration(configuration)));
356
+ }
357
+
358
+ function checkConfiguration(configuration) {
359
+ const checkedConfiguration = {};
202
360
  for (const propertyName of CONFIGURABLE_PROPERTY_NAMES) {
203
361
  const propertyValue = configuration[propertyName];
204
362
  if (propertyValue !== UNDEFINED_VALUE) {
205
- config[propertyName] = propertyValue;
363
+ checkedConfiguration[propertyName] = checkPropertyValue(propertyName, propertyValue);
364
+ }
365
+ }
366
+ return checkedConfiguration;
367
+ }
368
+
369
+ function checkPropertyValue(propertyName, propertyValue) {
370
+ if (NUMBER_PROPERTY_NAMES.includes(propertyName)) {
371
+ propertyValue = toNumber(propertyValue);
372
+ if (propertyName == PROPERTY_NAME_MAX_WORKERS && (!Number.isInteger(propertyValue) || propertyValue < MINIMUM_PROPERTY_VALUE)) {
373
+ throw new Error(ERR_INVALID_MAX_WORKERS);
206
374
  }
375
+ } else if (FUNCTION_PROPERTY_NAMES.includes(propertyName)) {
376
+ checkFunctionOption(propertyValue);
207
377
  }
378
+ return propertyValue;
208
379
  }
209
380
 
210
381
  function normalizeConfiguration(configuration) {
382
+ configuration = configuration || {};
211
383
  const { CompressionStreamZlib, DecompressionStreamZlib } = configuration;
212
384
  if (CompressionStreamZlib === UNDEFINED_VALUE && DecompressionStreamZlib === UNDEFINED_VALUE) {
213
385
  return configuration;
@@ -223,14 +395,9 @@ function normalizeConfiguration(configuration) {
223
395
  }
224
396
 
225
397
  function setDefaultConfiguration(configuration) {
226
- configuration = normalizeConfiguration(configuration);
227
- for (const propertyName of CONFIGURABLE_PROPERTY_NAMES) {
228
- const propertyValue = configuration[propertyName];
229
- if (propertyValue !== UNDEFINED_VALUE) {
230
- DEFAULT_CONFIGURATION[propertyName] = propertyValue;
231
- }
232
- }
233
- configure(configuration);
398
+ const checkedConfiguration = checkConfiguration(normalizeConfiguration(configuration));
399
+ Object.assign(DEFAULT_CONFIGURATION, checkedConfiguration);
400
+ Object.assign(config, checkedConfiguration);
234
401
  }
235
402
 
236
403
  function resetConfiguration() {
@@ -1386,13 +1553,13 @@ class AESDecryptionStream extends TransformStream {
1386
1553
  const {
1387
1554
  ctr,
1388
1555
  hmac,
1389
- pending,
1556
+ pendingInput,
1390
1557
  ready
1391
1558
  } = this;
1392
1559
  if (hmac && ctr) {
1393
1560
  await ready;
1394
- const chunkToDecrypt = subarray(pending, 0, pending.length - AUTHENTICATION_CODE_LENGTH);
1395
- const originalAuthenticationCode = subarray(pending, pending.length - AUTHENTICATION_CODE_LENGTH);
1561
+ const chunkToDecrypt = subarray(pendingInput, 0, pendingInput.length - AUTHENTICATION_CODE_LENGTH);
1562
+ const originalAuthenticationCode = subarray(pendingInput, pendingInput.length - AUTHENTICATION_CODE_LENGTH);
1396
1563
  let decryptedChunkArray = EMPTY_UINT8_ARRAY;
1397
1564
  if (chunkToDecrypt.length) {
1398
1565
  const encryptedChunk = toBits(codecBytes, chunkToDecrypt);
@@ -1401,7 +1568,7 @@ class AESDecryptionStream extends TransformStream {
1401
1568
  decryptedChunkArray = fromBits(codecBytes, decryptedChunk);
1402
1569
  }
1403
1570
  const authenticationCode = subarray(fromBits(codecBytes, hmac.digest()), 0, AUTHENTICATION_CODE_LENGTH);
1404
- let invalidAuthenticationCode = pending.length < AUTHENTICATION_CODE_LENGTH ? 1 : 0;
1571
+ let invalidAuthenticationCode = pendingInput.length < AUTHENTICATION_CODE_LENGTH ? 1 : 0;
1405
1572
  for (let indexByte = 0; indexByte < AUTHENTICATION_CODE_LENGTH; indexByte++) {
1406
1573
  invalidAuthenticationCode |= authenticationCode[indexByte] ^ originalAuthenticationCode[indexByte];
1407
1574
  }
@@ -1445,14 +1612,14 @@ class AESEncryptionStream extends TransformStream {
1445
1612
  const {
1446
1613
  ctr,
1447
1614
  hmac,
1448
- pending,
1615
+ pendingInput,
1449
1616
  ready
1450
1617
  } = this;
1451
1618
  if (hmac && ctr) {
1452
1619
  await ready;
1453
1620
  let encryptedChunkArray = EMPTY_UINT8_ARRAY;
1454
- if (pending.length) {
1455
- const encryptedChunk = ctr.update(toBits(codecBytes, pending));
1621
+ if (pendingInput.length) {
1622
+ const encryptedChunk = ctr.update(toBits(codecBytes, pendingInput));
1456
1623
  hmac.update(encryptedChunk);
1457
1624
  encryptedChunkArray = fromBits(codecBytes, encryptedChunk);
1458
1625
  }
@@ -1469,7 +1636,7 @@ function initAesCrypto(aesCrypto, password, rawPassword, encryptionStrength) {
1469
1636
  ready: new Promise(resolve => aesCrypto.resolveReady = resolve),
1470
1637
  password: encodePassword(password, rawPassword),
1471
1638
  strength: encryptionStrength - 1,
1472
- pending: EMPTY_UINT8_ARRAY
1639
+ pendingInput: EMPTY_UINT8_ARRAY
1473
1640
  });
1474
1641
  }
1475
1642
 
@@ -1477,10 +1644,10 @@ function append(aesCrypto, input, output, paddingStart, paddingEnd, verifyAuthen
1477
1644
  const {
1478
1645
  ctr,
1479
1646
  hmac,
1480
- pending
1647
+ pendingInput
1481
1648
  } = aesCrypto;
1482
- if (pending.length) {
1483
- input = concat(pending, input);
1649
+ if (pendingInput.length) {
1650
+ input = concat(pendingInput, input);
1484
1651
  }
1485
1652
  const inputLength = input.length - paddingEnd;
1486
1653
  output = expand(output, paddingStart + (inputLength - (inputLength % BLOCK_LENGTH)));
@@ -1496,7 +1663,7 @@ function append(aesCrypto, input, output, paddingStart, paddingEnd, verifyAuthen
1496
1663
  }
1497
1664
  output.set(fromBits(codecBytes, outputChunk), offset + paddingStart);
1498
1665
  }
1499
- aesCrypto.pending = subarray(input, offset);
1666
+ aesCrypto.pendingInput = subarray(input, offset);
1500
1667
  return output;
1501
1668
  }
1502
1669
 
@@ -1772,8 +1939,6 @@ function getInt32(number) {
1772
1939
  */
1773
1940
 
1774
1941
 
1775
- const HTTP_HEADER_CONTENT_TYPE = "Content-Type";
1776
-
1777
1942
  function toCompatibleReadable(readable) {
1778
1943
  if (readable instanceof ReadableStream) {
1779
1944
  return readable;
@@ -1796,12 +1961,9 @@ function toCompatibleReadable(readable) {
1796
1961
 
1797
1962
  function streamToBlob(readable, contentType) {
1798
1963
  readable = toCompatibleReadable(readable);
1964
+ const blobOptions = contentType ? { type: contentType } : {};
1799
1965
  if (responseSupportsGlobalReadable()) {
1800
- const options = {};
1801
- if (contentType) {
1802
- options.headers = [[HTTP_HEADER_CONTENT_TYPE, contentType]];
1803
- }
1804
- return new Response(readable, options).blob();
1966
+ return new Response(readable).blob().then(blob => contentType ? new Blob([blob], blobOptions) : blob);
1805
1967
  }
1806
1968
  const chunks = [];
1807
1969
  return readable
@@ -1810,7 +1972,7 @@ function streamToBlob(readable, contentType) {
1810
1972
  chunks.push(chunk);
1811
1973
  }
1812
1974
  }))
1813
- .then(() => new Blob(chunks, contentType ? { type: contentType } : {}));
1975
+ .then(() => new Blob(chunks, blobOptions));
1814
1976
  }
1815
1977
 
1816
1978
  function responseSupportsGlobalReadable() {
@@ -2752,6 +2914,7 @@ function createWebWorkerInterface(workerData, config) {
2752
2914
  worker,
2753
2915
  workerAlive: false,
2754
2916
  terminated: false,
2917
+ startupError: null,
2755
2918
  interface: {
2756
2919
  run: async () => {
2757
2920
  try {
@@ -2779,6 +2942,13 @@ function createWebWorkerInterface(workerData, config) {
2779
2942
  }
2780
2943
 
2781
2944
  async function runWebWorker(workerData, config) {
2945
+ if (!workerData.worker) {
2946
+ const { startupError } = workerData;
2947
+ workerData.startupError = null;
2948
+ const error = startupError || new Error(ERR_WORKER_STARTUP_TIMEOUT);
2949
+ error.workerStartupFailed = true;
2950
+ throw error;
2951
+ }
2782
2952
  let resolveResult, rejectResult;
2783
2953
  const result = new Promise((resolve, reject) => {
2784
2954
  resolveResult = resolve;
@@ -2992,11 +3162,12 @@ function onWorkerError(event, workerData) {
2992
3162
  if (!workerAlive) {
2993
3163
  workerData.worker = null;
2994
3164
  }
3165
+ let error = event.error || new Error(event.message || ERROR_EVENT_TYPE);
3166
+ if (!workerAlive) {
3167
+ error = Object.assign(new Error(error.message || ERROR_EVENT_TYPE), { workerStartupFailed: true });
3168
+ workerData.startupError = error;
3169
+ }
2995
3170
  if (rejectResult) {
2996
- let error = event.error || new Error(event.message || ERROR_EVENT_TYPE);
2997
- if (!workerAlive) {
2998
- error = Object.assign(new Error(error.message || ERROR_EVENT_TYPE), { workerStartupFailed: true });
2999
- }
3000
3171
  rejectResult(error);
3001
3172
  if (writer) {
3002
3173
  writer.releaseLock();
@@ -3265,6 +3436,96 @@ async function terminateWorkers() {
3265
3436
  resetWebWorkerSupport();
3266
3437
  }
3267
3438
 
3439
+ /*
3440
+ Copyright (c) 2022 Gildas Lormeau. All rights reserved.
3441
+
3442
+ Redistribution and use in source and binary forms, with or without
3443
+ modification, are permitted provided that the following conditions are met:
3444
+
3445
+ 1. Redistributions of source code must retain the above copyright notice,
3446
+ this list of conditions and the following disclaimer.
3447
+
3448
+ 2. Redistributions in binary form must reproduce the above copyright
3449
+ notice, this list of conditions and the following disclaimer in
3450
+ the documentation and/or other materials provided with the distribution.
3451
+
3452
+ 3. The names of the authors may not be used to endorse or promote products
3453
+ derived from this software without specific prior written permission.
3454
+
3455
+ THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
3456
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
3457
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
3458
+ INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
3459
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3460
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
3461
+ OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
3462
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
3463
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
3464
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3465
+ */
3466
+
3467
+ /* global TextDecoder */
3468
+
3469
+ const CP437 = "\0☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼ !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~⌂ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ ".split("");
3470
+ const VALID_CP437 = CP437.length == 256;
3471
+
3472
+ function decodeCP437(stringValue) {
3473
+ if (VALID_CP437) {
3474
+ let result = "";
3475
+ for (let indexCharacter = 0; indexCharacter < stringValue.length; indexCharacter++) {
3476
+ result += CP437[stringValue[indexCharacter]];
3477
+ }
3478
+ return result;
3479
+ } else {
3480
+ return new TextDecoder().decode(stringValue);
3481
+ }
3482
+ }
3483
+
3484
+ /*
3485
+ Copyright (c) 2022 Gildas Lormeau. All rights reserved.
3486
+
3487
+ Redistribution and use in source and binary forms, with or without
3488
+ modification, are permitted provided that the following conditions are met:
3489
+
3490
+ 1. Redistributions of source code must retain the above copyright notice,
3491
+ this list of conditions and the following disclaimer.
3492
+
3493
+ 2. Redistributions in binary form must reproduce the above copyright
3494
+ notice, this list of conditions and the following disclaimer in
3495
+ the documentation and/or other materials provided with the distribution.
3496
+
3497
+ 3. The names of the authors may not be used to endorse or promote products
3498
+ derived from this software without specific prior written permission.
3499
+
3500
+ THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
3501
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
3502
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
3503
+ INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
3504
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3505
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
3506
+ OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
3507
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
3508
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
3509
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3510
+ */
3511
+
3512
+
3513
+ function decodeText(value, encoding) {
3514
+ return decode(value, encoding, true);
3515
+ }
3516
+
3517
+ function decodeTextRemovingBOM(value, encoding) {
3518
+ return decode(value, encoding, false);
3519
+ }
3520
+
3521
+ function decode(value, encoding, ignoreBOM) {
3522
+ if (encoding && encoding.trim().toLowerCase() == "cp437") {
3523
+ return decodeCP437(value);
3524
+ } else {
3525
+ return new TextDecoder(encoding, { ignoreBOM }).decode(value);
3526
+ }
3527
+ }
3528
+
3268
3529
  /*
3269
3530
  Copyright (c) 2025 Gildas Lormeau. All rights reserved.
3270
3531
 
@@ -3337,12 +3598,15 @@ class Reader extends Stream {
3337
3598
  createReadable({ offset = 0, size, chunkSize = getChunkSize(getConfiguration()) } = {}) {
3338
3599
  const reader = this;
3339
3600
  let chunkOffset = 0;
3601
+ chunkSize = normalizeChunkSize(chunkSize);
3340
3602
  return new ReadableStream({
3341
3603
  async pull(controller) {
3342
3604
  const dataSize = size === UNDEFINED_VALUE ? chunkSize : Math.min(chunkSize, size - chunkOffset);
3343
3605
  const data = await readUint8Array(reader, offset + chunkOffset, dataSize);
3344
- controller.enqueue(data);
3345
- if ((chunkOffset + chunkSize > size) || (size === UNDEFINED_VALUE && !data.length && dataSize)) {
3606
+ if (data.length) {
3607
+ controller.enqueue(data);
3608
+ }
3609
+ if ((chunkOffset + chunkSize >= size) || (!data.length && dataSize)) {
3346
3610
  controller.close();
3347
3611
  } else {
3348
3612
  chunkOffset += chunkSize;
@@ -3420,32 +3684,33 @@ class Data64URIWriter extends Writer {
3420
3684
  constructor(contentType) {
3421
3685
  super();
3422
3686
  Object.assign(this, {
3687
+ contentType,
3423
3688
  data: "data:" + (contentType || "") + ";base64,",
3424
- pending: []
3689
+ pendingCharacters: ""
3425
3690
  });
3426
3691
  }
3427
3692
 
3428
3693
  writeUint8Array(array) {
3429
3694
  const writer = this;
3430
3695
  let indexArray;
3431
- let dataString = writer.pending;
3432
- const delta = writer.pending.length;
3433
- writer.pending = "";
3696
+ let dataString = writer.pendingCharacters;
3697
+ const delta = writer.pendingCharacters.length;
3698
+ writer.pendingCharacters = "";
3434
3699
  for (indexArray = 0; indexArray < (Math.floor((delta + array.length) / 3) * 3) - delta; indexArray++) {
3435
3700
  dataString += String.fromCharCode(array[indexArray]);
3436
3701
  }
3437
3702
  for (; indexArray < array.length; indexArray++) {
3438
- writer.pending += String.fromCharCode(array[indexArray]);
3703
+ writer.pendingCharacters += String.fromCharCode(array[indexArray]);
3439
3704
  }
3440
3705
  if (dataString.length > 2) {
3441
3706
  writer.data += btoa(dataString);
3442
3707
  } else {
3443
- writer.pending = dataString + writer.pending;
3708
+ writer.pendingCharacters = dataString + writer.pendingCharacters;
3444
3709
  }
3445
3710
  }
3446
3711
 
3447
3712
  getData() {
3448
- return this.data + btoa(this.pending);
3713
+ return this.data + btoa(this.pendingCharacters);
3449
3714
  }
3450
3715
  }
3451
3716
 
@@ -3475,7 +3740,7 @@ class BlobReader extends Reader {
3475
3740
  constructor(blob) {
3476
3741
  super();
3477
3742
  Object.assign(this, {
3478
- blob,
3743
+ sourceBlob: blob,
3479
3744
  size: blob.size
3480
3745
  });
3481
3746
  if (!blobSliceProbe) {
@@ -3485,13 +3750,13 @@ class BlobReader extends Reader {
3485
3750
 
3486
3751
  createReadable(options) {
3487
3752
  const reader = this;
3488
- const { blob, size } = reader;
3753
+ const { sourceBlob, size } = reader;
3489
3754
  const { offset = 0, size: readSize = size - offset } = options || {};
3490
3755
  if (!offset && readSize >= size) {
3491
- return toCompatibleReadable(blob.stream());
3756
+ return toCompatibleReadable(sourceBlob.stream());
3492
3757
  }
3493
3758
  if (blobSliceReliable) {
3494
- return toCompatibleReadable(blob.slice(offset, offset + readSize).stream());
3759
+ return toCompatibleReadable(sourceBlob.slice(offset, offset + readSize).stream());
3495
3760
  }
3496
3761
  return super.createReadable(options);
3497
3762
  }
@@ -3500,7 +3765,7 @@ class BlobReader extends Reader {
3500
3765
  const reader = this;
3501
3766
  const offsetEnd = offset + length;
3502
3767
  const readsWholeBlob = !offset && offsetEnd >= reader.size;
3503
- const blob = readsWholeBlob ? reader.blob : reader.blob.slice(offset, offsetEnd);
3768
+ const blob = readsWholeBlob ? reader.sourceBlob : reader.sourceBlob.slice(offset, offsetEnd);
3504
3769
  let arrayBuffer = await blob.arrayBuffer();
3505
3770
  const sliceIgnoredByBuggyImplementation = arrayBuffer.byteLength > length;
3506
3771
  if (sliceIgnoredByBuggyImplementation) {
@@ -3521,12 +3786,13 @@ class BlobWriter extends Stream {
3521
3786
  return transformStream.writable;
3522
3787
  }
3523
3788
  });
3524
- writer.blob = streamToBlob(transformStream.readable, contentType);
3525
- writer.blob.catch(() => { });
3789
+ writer.contentType = contentType;
3790
+ writer.blobPromise = streamToBlob(transformStream.readable, contentType);
3791
+ writer.blobPromise.catch(() => { });
3526
3792
  }
3527
3793
 
3528
3794
  getData() {
3529
- return this.blob;
3795
+ return this.blobPromise;
3530
3796
  }
3531
3797
  }
3532
3798
 
@@ -3540,7 +3806,7 @@ class TextReader extends BlobReader {
3540
3806
  class TextWriter extends BlobWriter {
3541
3807
 
3542
3808
  constructor(encoding) {
3543
- super(encoding);
3809
+ super();
3544
3810
  Object.assign(this, {
3545
3811
  encoding,
3546
3812
  utf8: !encoding || encoding.toLowerCase() == "utf-8"
@@ -3556,14 +3822,7 @@ class TextWriter extends BlobWriter {
3556
3822
  if (blob.text && utf8) {
3557
3823
  return blob.text();
3558
3824
  } else {
3559
- const reader = new FileReader();
3560
- return new Promise((resolve, reject) => {
3561
- Object.assign(reader, {
3562
- onload: ({ target }) => resolve(target.result),
3563
- onerror: () => reject(reader.error)
3564
- });
3565
- reader.readAsText(blob, encoding);
3566
- });
3825
+ return decodeTextRemovingBOM(new Uint8Array(await blob.arrayBuffer()), encoding);
3567
3826
  }
3568
3827
  }
3569
3828
  }
@@ -4021,9 +4280,8 @@ class SplitDataReader extends Reader {
4021
4280
 
4022
4281
  async init() {
4023
4282
  const reader = this;
4024
- const { readers } = reader;
4025
4283
  reader.lastDiskNumber = 0;
4026
- await Promise.all(readers.map(diskReader => initStream(diskReader)));
4284
+ const readers = reader.readers = await Promise.all(reader.readers.map(initDiskReader));
4027
4285
  reader.diskOffsets = readers.map(diskReader => {
4028
4286
  const diskOffset = reader.size;
4029
4287
  reader.size += diskReader.size;
@@ -4200,6 +4458,10 @@ class GenericWriter {
4200
4458
  }
4201
4459
  }
4202
4460
 
4461
+ function ownsWritable(writer) {
4462
+ return Boolean(writer && writer.getData);
4463
+ }
4464
+
4203
4465
  function isHttpFamily(url) {
4204
4466
  const { baseURI } = getConfiguration();
4205
4467
  const { protocol } = new URL(url, baseURI);
@@ -4214,94 +4476,32 @@ async function initStream(stream, initSize) {
4214
4476
  }
4215
4477
  }
4216
4478
 
4479
+ async function initDiskReader(diskReader) {
4480
+ diskReader = new GenericReader(diskReader);
4481
+ await initStream(diskReader);
4482
+ if (diskReader.size === UNDEFINED_VALUE || !diskReader.readUint8Array) {
4483
+ diskReader = new BlobReader(await streamToBlob(diskReader.readable));
4484
+ await initStream(diskReader);
4485
+ }
4486
+ return diskReader;
4487
+ }
4488
+
4217
4489
  function readUint8Array(reader, offset, size) {
4218
4490
  return reader.readUint8Array(offset, size);
4219
4491
  }
4220
4492
 
4493
+ function createReadable(reader, options) {
4494
+ if (reader.createReadable) {
4495
+ return reader.createReadable(options);
4496
+ } else if (reader.readUint8Array) {
4497
+ return Reader.prototype.createReadable.call(reader, options);
4498
+ } else {
4499
+ return reader.readable;
4500
+ }
4501
+ }
4502
+
4221
4503
  /*
4222
- Copyright (c) 2022 Gildas Lormeau. All rights reserved.
4223
-
4224
- Redistribution and use in source and binary forms, with or without
4225
- modification, are permitted provided that the following conditions are met:
4226
-
4227
- 1. Redistributions of source code must retain the above copyright notice,
4228
- this list of conditions and the following disclaimer.
4229
-
4230
- 2. Redistributions in binary form must reproduce the above copyright
4231
- notice, this list of conditions and the following disclaimer in
4232
- the documentation and/or other materials provided with the distribution.
4233
-
4234
- 3. The names of the authors may not be used to endorse or promote products
4235
- derived from this software without specific prior written permission.
4236
-
4237
- THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
4238
- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
4239
- FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
4240
- INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
4241
- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
4242
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
4243
- OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
4244
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
4245
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
4246
- EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4247
- */
4248
-
4249
- /* global TextDecoder */
4250
-
4251
- const CP437 = "\0☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼ !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~⌂ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ ".split("");
4252
- const VALID_CP437 = CP437.length == 256;
4253
-
4254
- function decodeCP437(stringValue) {
4255
- if (VALID_CP437) {
4256
- let result = "";
4257
- for (let indexCharacter = 0; indexCharacter < stringValue.length; indexCharacter++) {
4258
- result += CP437[stringValue[indexCharacter]];
4259
- }
4260
- return result;
4261
- } else {
4262
- return new TextDecoder().decode(stringValue);
4263
- }
4264
- }
4265
-
4266
- /*
4267
- Copyright (c) 2022 Gildas Lormeau. All rights reserved.
4268
-
4269
- Redistribution and use in source and binary forms, with or without
4270
- modification, are permitted provided that the following conditions are met:
4271
-
4272
- 1. Redistributions of source code must retain the above copyright notice,
4273
- this list of conditions and the following disclaimer.
4274
-
4275
- 2. Redistributions in binary form must reproduce the above copyright
4276
- notice, this list of conditions and the following disclaimer in
4277
- the documentation and/or other materials provided with the distribution.
4278
-
4279
- 3. The names of the authors may not be used to endorse or promote products
4280
- derived from this software without specific prior written permission.
4281
-
4282
- THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
4283
- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
4284
- FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
4285
- INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
4286
- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
4287
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
4288
- OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
4289
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
4290
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
4291
- EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4292
- */
4293
-
4294
-
4295
- function decodeText(value, encoding) {
4296
- if (encoding && encoding.trim().toLowerCase() == "cp437") {
4297
- return decodeCP437(value);
4298
- } else {
4299
- return new TextDecoder(encoding, { ignoreBOM: true }).decode(value);
4300
- }
4301
- }
4302
-
4303
- /*
4304
- Copyright (c) 2025 Gildas Lormeau. All rights reserved.
4504
+ Copyright (c) 2025 Gildas Lormeau. All rights reserved.
4305
4505
 
4306
4506
  Redistribution and use in source and binary forms, with or without
4307
4507
  modification, are permitted provided that the following conditions are met:
@@ -4344,6 +4544,8 @@ const PROPERTY_NAME_CREATION_DATE = "creationDate";
4344
4544
  const PROPERTY_NAME_RAW_CREATION_DATE = "rawCreationDate";
4345
4545
  const PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES = "internalFileAttributes";
4346
4546
  const PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTES = "externalFileAttributes";
4547
+ const PROPERTY_NAME_DEPRECATED_INTERNAL_FILE_ATTRIBUTES = "internalFileAttribute";
4548
+ const PROPERTY_NAME_DEPRECATED_EXTERNAL_FILE_ATTRIBUTES = "externalFileAttribute";
4347
4549
  const PROPERTY_NAME_MSDOS_ATTRIBUTES_RAW = "msdosAttributesRaw";
4348
4550
  const PROPERTY_NAME_MSDOS_ATTRIBUTES = "msdosAttributes";
4349
4551
  const PROPERTY_NAME_MS_DOS_COMPATIBLE = "msDosCompatible";
@@ -4354,6 +4556,7 @@ const PROPERTY_NAME_VERSION_MADE_BY = "versionMadeBy";
4354
4556
  const PROPERTY_NAME_ZIPCRYPTO = "zipCrypto";
4355
4557
  const PROPERTY_NAME_DIRECTORY = "directory";
4356
4558
  const PROPERTY_NAME_EXECUTABLE = "executable";
4559
+ const PROPERTY_NAME_SYMLINK = "symlink";
4357
4560
  const PROPERTY_NAME_COMPRESSION_METHOD = "compressionMethod";
4358
4561
  const PROPERTY_NAME_SIGNATURE = "signature";
4359
4562
  const PROPERTY_NAME_CRC32 = "crc32";
@@ -4369,6 +4572,10 @@ const PROPERTY_NAME_SETUID = "setuid";
4369
4572
  const PROPERTY_NAME_SETGID = "setgid";
4370
4573
  const PROPERTY_NAME_STICKY = "sticky";
4371
4574
  const PROPERTY_NAME_BITFLAG = "bitFlag";
4575
+ const PROPERTY_NAME_RAW_BITFLAG = "rawBitFlag";
4576
+ const PROPERTY_NAME_FILENAME_LENGTH = "filenameLength";
4577
+ const PROPERTY_NAME_EXTRA_FIELD_LENGTH = "extraFieldLength";
4578
+ const PROPERTY_NAME_UNIX_EXTERNAL_UPPER = "unixExternalUpper";
4372
4579
  const PROPERTY_NAME_FILENAME_UTF8 = "filenameUTF8";
4373
4580
  const PROPERTY_NAME_COMMENT_UTF8 = "commentUTF8";
4374
4581
  const PROPERTY_NAME_RAW_EXTRA_FIELD = "rawExtraField";
@@ -4397,6 +4604,8 @@ const PROPERTY_NAMES = [
4397
4604
  PROPERTY_NAME_DISK_NUMBER_START,
4398
4605
  PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES,
4399
4606
  PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTES,
4607
+ PROPERTY_NAME_DEPRECATED_INTERNAL_FILE_ATTRIBUTES,
4608
+ PROPERTY_NAME_DEPRECATED_EXTERNAL_FILE_ATTRIBUTES,
4400
4609
  PROPERTY_NAME_MSDOS_ATTRIBUTES_RAW,
4401
4610
  PROPERTY_NAME_MSDOS_ATTRIBUTES,
4402
4611
  PROPERTY_NAME_MS_DOS_COMPATIBLE,
@@ -4407,6 +4616,7 @@ const PROPERTY_NAMES = [
4407
4616
  PROPERTY_NAME_ZIPCRYPTO,
4408
4617
  PROPERTY_NAME_DIRECTORY,
4409
4618
  PROPERTY_NAME_EXECUTABLE,
4619
+ PROPERTY_NAME_SYMLINK,
4410
4620
  PROPERTY_NAME_COMPRESSION_METHOD,
4411
4621
  PROPERTY_NAME_SIGNATURE,
4412
4622
  PROPERTY_NAME_CRC32,
@@ -4418,10 +4628,14 @@ const PROPERTY_NAMES = [
4418
4628
  PROPERTY_NAME_UID,
4419
4629
  PROPERTY_NAME_GID,
4420
4630
  PROPERTY_NAME_UNIX_MODE,
4631
+ PROPERTY_NAME_UNIX_EXTERNAL_UPPER,
4421
4632
  PROPERTY_NAME_SETUID,
4422
4633
  PROPERTY_NAME_SETGID,
4423
4634
  PROPERTY_NAME_STICKY,
4424
4635
  PROPERTY_NAME_BITFLAG,
4636
+ PROPERTY_NAME_RAW_BITFLAG,
4637
+ PROPERTY_NAME_FILENAME_LENGTH,
4638
+ PROPERTY_NAME_EXTRA_FIELD_LENGTH,
4425
4639
  PROPERTY_NAME_FILENAME_UTF8,
4426
4640
  PROPERTY_NAME_COMMENT_UTF8,
4427
4641
  PROPERTY_NAME_RAW_EXTRA_FIELD,
@@ -4442,82 +4656,6 @@ class Entry {
4442
4656
 
4443
4657
  }
4444
4658
 
4445
- /*
4446
- Copyright (c) 2022 Gildas Lormeau. All rights reserved.
4447
-
4448
- Redistribution and use in source and binary forms, with or without
4449
- modification, are permitted provided that the following conditions are met:
4450
-
4451
- 1. Redistributions of source code must retain the above copyright notice,
4452
- this list of conditions and the following disclaimer.
4453
-
4454
- 2. Redistributions in binary form must reproduce the above copyright
4455
- notice, this list of conditions and the following disclaimer in
4456
- the documentation and/or other materials provided with the distribution.
4457
-
4458
- 3. The names of the authors may not be used to endorse or promote products
4459
- derived from this software without specific prior written permission.
4460
-
4461
- THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
4462
- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
4463
- FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
4464
- INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
4465
- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
4466
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
4467
- OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
4468
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
4469
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
4470
- EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4471
- */
4472
-
4473
- const OPTION_FILENAME_ENCODING = "filenameEncoding";
4474
- const OPTION_COMMENT_ENCODING = "commentEncoding";
4475
- const OPTION_DECODE_TEXT = "decodeText";
4476
- const OPTION_EXTRACT_PREPENDED_DATA = "extractPrependedData";
4477
- const OPTION_EXTRACT_APPENDED_DATA = "extractAppendedData";
4478
- const OPTION_PASSWORD = "password";
4479
- const OPTION_RAW_PASSWORD = "rawPassword";
4480
- const OPTION_PASS_THROUGH = "passThrough";
4481
- const OPTION_SIGNAL = "signal";
4482
- const OPTION_CHECK_PASSWORD_ONLY = "checkPasswordOnly";
4483
- const OPTION_CHECK_OVERLAPPING_ENTRY_ONLY = "checkOverlappingEntryOnly";
4484
- const OPTION_CHECK_OVERLAPPING_ENTRY = "checkOverlappingEntry";
4485
- const OPTION_CHECK_AMBIGUITY = "checkAmbiguity";
4486
- const OPTION_CHECK_SIGNATURE = "checkSignature";
4487
- const OPTION_CHECK_CRC32 = "checkCrc32";
4488
- const OPTION_CHECK_AUTHENTICATION_CODE = "checkAuthenticationCode";
4489
- const OPTION_USE_WEB_WORKERS = "useWebWorkers";
4490
- const OPTION_USE_COMPRESSION_STREAM = "useCompressionStream";
4491
- const OPTION_TRANSFER_STREAMS = "transferStreams";
4492
- const OPTION_PREVENT_CLOSE = "preventClose";
4493
- const OPTION_ENCRYPTION_STRENGTH = "encryptionStrength";
4494
- const OPTION_EXTENDED_TIMESTAMP = "extendedTimestamp";
4495
- const OPTION_NTFS_TIMESTAMP = "ntfsTimestamp";
4496
- const OPTION_KEEP_ORDER = "keepOrder";
4497
- const OPTION_LEVEL = "level";
4498
- const OPTION_BUFFERED_WRITE = "bufferedWrite";
4499
- const OPTION_CREATE_TEMP_STREAM = "createTempStream";
4500
- const OPTION_DATA_DESCRIPTOR_SIGNATURE = "dataDescriptorSignature";
4501
- const OPTION_USE_UNICODE_FILE_NAMES = "useUnicodeFileNames";
4502
- const OPTION_DATA_DESCRIPTOR = "dataDescriptor";
4503
- const OPTION_SUPPORT_ZIP64_SPLIT_FILE = "supportZip64SplitFile";
4504
- const OPTION_ENCODE_TEXT = "encodeText";
4505
- const OPTION_OFFSET = "offset";
4506
- const OPTION_USDZ = "usdz";
4507
- const OPTION_UNIX_EXTRA_FIELD_TYPE = "unixExtraFieldType";
4508
- const OPTION_LOCAL_EXTRA_FIELD = "localExtraField";
4509
- const OPTION_STRICTNESS = "strictness";
4510
- const OPTION_FILENAME_VALIDATION = "filenameValidation";
4511
- const OPTION_NORMALIZE_FILENAME = "normalizeFilename";
4512
- const OPTION_MAX_APPENDED_DATA_SIZE = "maxAppendedDataSize";
4513
- const OPTION_DECRYPT_CENTRAL_DIRECTORY = "decryptCentralDirectory";
4514
- const OPTION_SIGN_CENTRAL_DIRECTORY = "signCentralDirectory";
4515
- const TEXT_TYPE_FILENAME = "filename";
4516
- const TEXT_TYPE_COMMENT = "comment";
4517
- const STRICTNESS_STRICT = "strict";
4518
- const STRICTNESS_BALANCED = "balanced";
4519
- const STRICTNESS_TOLERANT = "tolerant";
4520
-
4521
4659
  /*
4522
4660
  Copyright (c) 2025 Gildas Lormeau. All rights reserved.
4523
4661
 
@@ -4558,12 +4696,29 @@ const ERR_UNSUPPORTED_ENCRYPTION = "Encryption method not supported";
4558
4696
  const ERR_UNSUPPORTED_COMPRESSION$1 = "Compression method not supported";
4559
4697
  const ERR_SPLIT_ZIP_FILE = "Split zip file";
4560
4698
  const ERR_OVERLAPPING_ENTRY = "Overlapping entry found";
4699
+ const ERR_ENTRY_DATA_OUT_OF_BOUNDS = "Entry data out of bounds";
4561
4700
  const ERR_AMBIGUOUS_ARCHIVE = "Ambiguous archive";
4562
4701
  const ERR_ENCRYPTED_CENTRAL_DIRECTORY = "Encrypted central directory is not supported";
4563
4702
  const ERR_UNSAFE_FILENAME = "Unsafe filename";
4564
4703
  const ERR_INVALID_STRICTNESS = "Invalid strictness (must be 'strict', 'balanced' or 'tolerant')";
4565
4704
  const ERR_INVALID_FILENAME_VALIDATION = "Invalid filenameValidation (must be 'strict', 'balanced' or 'tolerant')";
4566
4705
  const ERR_INVALID_MAX_APPENDED_DATA_SIZE = "Invalid maxAppendedDataSize (must be a number greater than or equal to 0)";
4706
+ const ERR_UNSUPPORTED_UINT64 = "64-bit value exceeds Number.MAX_SAFE_INTEGER";
4707
+ const WARNING_UNSORTED_CENTRAL_DIRECTORY = "unsorted central directory";
4708
+ const WARNING_UNKNOWN_VERSION = "unknown version needed to extract";
4709
+ const WARNING_COMPRESSED_PATCHED_DATA = "compressed patched data";
4710
+ const WARNING_MALFORMED_EXTRA_FIELD = "malformed extra field";
4711
+ const WARNING_UNKNOWN_ZIP64_EXTENSIBLE_DATA = "unknown zip64 extensible data";
4712
+ const WARNING_WRAPPED_ENTRIES_COUNT = "wrapped entries count";
4713
+ const WARNING_APPENDED_DATA = "appended data";
4714
+ const WARNING_PREPENDED_DATA = "prepended data";
4715
+ const WARNING_TRAILING_CENTRAL_DIRECTORY_DATA = "trailing central directory data";
4716
+ const WARNING_DUPLICATE_FILENAME = "duplicate filename";
4717
+ const WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY = "mismatched zip64 end of central directory record";
4718
+ const WARNING_MISMATCHED_LOCAL_FILE_HEADER_BIT_FLAG = "mismatched local file header (general purpose bit flag)";
4719
+ const WARNING_MISMATCHED_LOCAL_FILE_HEADER_COMPRESSION_METHOD = "mismatched local file header (compression method)";
4720
+ const WARNING_MISMATCHED_LOCAL_FILE_HEADER_CRC32_OR_SIZES = "mismatched local file header (crc32 or sizes)";
4721
+ const MAX_KNOWN_VERSION = 63;
4567
4722
  const DRIVE_LETTER_REGEXP = /^[a-zA-Z]:/;
4568
4723
  const CHARSET_UTF8 = "utf-8";
4569
4724
  const PROPERTY_NAME_UTF8_SUFFIX = "UTF8";
@@ -4578,7 +4733,7 @@ const ZIP64_PROPERTIES = [
4578
4733
  ];
4579
4734
  const ZIP64_EXTRACTION = {
4580
4735
  [MAX_16_BITS]: {
4581
- getValue: getUint32,
4736
+ getValue: getUint32$1,
4582
4737
  bytes: 4
4583
4738
  },
4584
4739
  [MAX_32_BITS]: {
@@ -4586,7 +4741,9 @@ const ZIP64_EXTRACTION = {
4586
4741
  bytes: 8
4587
4742
  }
4588
4743
  };
4744
+ const MAX_SAFE_UINT64 = BigInt(Number.MAX_SAFE_INTEGER);
4589
4745
  const MAX_END_OF_CENTRAL_DIR_PROBES = 64;
4746
+ const MAX_DEFLATE_EXPANSION_RATIO = 1032;
4590
4747
  const CENTRAL_DIRECTORY_UNREACHABLE = 0;
4591
4748
  const CENTRAL_DIRECTORY_PLAUSIBLE = 1;
4592
4749
  const CENTRAL_DIRECTORY_REACHABLE = 2;
@@ -4597,7 +4754,6 @@ class ZipReader {
4597
4754
  Object.assign(this, {
4598
4755
  reader: new GenericReader(reader),
4599
4756
  options,
4600
- config: getConfiguration(),
4601
4757
  readRanges: new Map()
4602
4758
  });
4603
4759
  }
@@ -4605,7 +4761,6 @@ class ZipReader {
4605
4761
  async* getEntriesGenerator(options = {}) {
4606
4762
  const zipReader = this;
4607
4763
  let { reader } = zipReader;
4608
- const { config } = zipReader;
4609
4764
  await initStream(reader);
4610
4765
  if (reader.size === UNDEFINED_VALUE || !reader.readUint8Array) {
4611
4766
  reader = new BlobReader(await streamToBlob(reader.readable));
@@ -4614,7 +4769,8 @@ class ZipReader {
4614
4769
  if (reader.size < END_OF_CENTRAL_DIR_LENGTH) {
4615
4770
  throw new Error(ERR_BAD_FORMAT);
4616
4771
  }
4617
- const strictness = getStrictness(getOptionValue$1(zipReader, options, OPTION_STRICTNESS), getOptionValue$1(zipReader, options, OPTION_CHECK_AMBIGUITY));
4772
+ const warnings = zipReader.warnings = [];
4773
+ const strictness = getStrictness(options, zipReader.options);
4618
4774
  const checkAmbiguity = strictness == STRICTNESS_STRICT;
4619
4775
  const rejectAmbiguousEndOfDirectory = strictness != STRICTNESS_TOLERANT;
4620
4776
  const maxAppendedDataSize = getMaxAppendedDataSize(getOptionValue$1(zipReader, options, OPTION_MAX_APPENDED_DATA_SIZE), strictness);
@@ -4622,9 +4778,7 @@ class ZipReader {
4622
4778
  const normalizeFilename = getOptionValue$1(zipReader, options, OPTION_NORMALIZE_FILENAME);
4623
4779
  const { endOfDirectoryInfo, endOfDirectoryReachingEndCount } = await findEndOfCentralDirectory(reader, rejectAmbiguousEndOfDirectory, maxAppendedDataSize);
4624
4780
  if (!endOfDirectoryInfo) {
4625
- const signatureArray = await readUint8Array(reader, 0, 4);
4626
- const signatureView = getDataView(signatureArray);
4627
- if (getUint32(signatureView) == SPLIT_ZIP_FILE_SIGNATURE) {
4781
+ if (await startsWithSplitZipSignature$1(reader)) {
4628
4782
  throw new Error(ERR_SPLIT_ZIP_FILE);
4629
4783
  } else {
4630
4784
  throw new Error(ERR_EOCDR_NOT_FOUND);
@@ -4634,22 +4788,27 @@ class ZipReader {
4634
4788
  throwAmbiguousArchive("multiple end of central directory records");
4635
4789
  }
4636
4790
  const endOfDirectoryView = getDataView(endOfDirectoryInfo);
4637
- let directoryDataLength = getUint32(endOfDirectoryView, 12);
4638
- let directoryDataOffset = getUint32(endOfDirectoryView, 16);
4791
+ let directoryDataLength = getUint32$1(endOfDirectoryView, 12);
4792
+ let directoryDataOffset = getUint32$1(endOfDirectoryView, 16);
4639
4793
  const commentOffset = endOfDirectoryInfo.offset;
4640
- const commentLength = getUint16(endOfDirectoryView, 20);
4794
+ const commentLength = getUint16$1(endOfDirectoryView, 20);
4641
4795
  const appendedDataOffset = commentOffset + END_OF_CENTRAL_DIR_LENGTH + commentLength;
4642
- if (reader.size - appendedDataOffset > maxAppendedDataSize) {
4643
- throwAmbiguousArchive("appended data");
4796
+ const appendedDataLength = reader.size - appendedDataOffset;
4797
+ if (appendedDataLength > maxAppendedDataSize) {
4798
+ throwAmbiguousArchive(WARNING_APPENDED_DATA);
4644
4799
  }
4645
- let lastDiskNumber = getUint16(endOfDirectoryView, 4);
4800
+ if (appendedDataLength > 0) {
4801
+ addWarning(warnings, WARNING_APPENDED_DATA);
4802
+ }
4803
+ let lastDiskNumber = getUint16$1(endOfDirectoryView, 4);
4646
4804
  const expectedLastDiskNumber = reader.lastDiskNumber || 0;
4647
- let diskNumber = getUint16(endOfDirectoryView, 6);
4648
- let filesLength = getUint16(endOfDirectoryView, 10);
4805
+ let diskNumber = getUint16$1(endOfDirectoryView, 6);
4806
+ let filesLength = getUint16$1(endOfDirectoryView, 10);
4649
4807
  let prependedDataLength = 0;
4650
4808
  let startOffset;
4651
4809
  let zip64EndOfDirectory;
4652
4810
  let zip64EndOfDirectoryVersion2;
4811
+ let zip64EndOfDirectoryLength = ZIP64_END_OF_CENTRAL_DIR_LENGTH;
4653
4812
  let directoryEncryptionInfo;
4654
4813
  const requiresZip64 = directoryDataOffset == MAX_32_BITS || directoryDataLength == MAX_32_BITS || filesLength == MAX_16_BITS || diskNumber == MAX_16_BITS;
4655
4814
  if (directoryDataOffset != MAX_32_BITS && diskNumber != MAX_16_BITS) {
@@ -4661,12 +4820,12 @@ class ZipReader {
4661
4820
  EMPTY_UINT8_ARRAY;
4662
4821
  const endOfDirectoryLocatorView = getDataView(endOfDirectoryLocatorArray);
4663
4822
  if (endOfDirectoryLocatorArray.length == ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH &&
4664
- getUint32(endOfDirectoryLocatorView, 0) == ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIGNATURE) {
4665
- directoryDataOffset = getDiskOffset$1(reader, getUint32(endOfDirectoryLocatorView, 4)) + getBigUint64(endOfDirectoryLocatorView, 8);
4823
+ getUint32$1(endOfDirectoryLocatorView, 0) == ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIGNATURE) {
4824
+ directoryDataOffset = getDiskOffset$1(reader, getUint32$1(endOfDirectoryLocatorView, 4)) + getBigUint64(endOfDirectoryLocatorView, 8);
4666
4825
  let endOfDirectoryArray = await readUint8Array(reader, directoryDataOffset, ZIP64_END_OF_CENTRAL_DIR_LENGTH);
4667
4826
  let endOfDirectoryView = getDataView(endOfDirectoryArray);
4668
4827
  const expectedDirectoryDataOffset = endOfDirectoryInfo.offset - ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH - ZIP64_END_OF_CENTRAL_DIR_LENGTH;
4669
- if ((endOfDirectoryArray.length < ZIP64_END_OF_CENTRAL_DIR_LENGTH || getUint32(endOfDirectoryView, 0) != ZIP64_END_OF_CENTRAL_DIR_SIGNATURE) &&
4828
+ if ((endOfDirectoryArray.length < ZIP64_END_OF_CENTRAL_DIR_LENGTH || getUint32$1(endOfDirectoryView, 0) != ZIP64_END_OF_CENTRAL_DIR_SIGNATURE) &&
4670
4829
  directoryDataOffset != expectedDirectoryDataOffset && expectedDirectoryDataOffset >= 0) {
4671
4830
  const originalDirectoryDataOffset = directoryDataOffset;
4672
4831
  directoryDataOffset = expectedDirectoryDataOffset;
@@ -4676,46 +4835,47 @@ class ZipReader {
4676
4835
  endOfDirectoryArray = await readUint8Array(reader, directoryDataOffset, ZIP64_END_OF_CENTRAL_DIR_LENGTH);
4677
4836
  endOfDirectoryView = getDataView(endOfDirectoryArray);
4678
4837
  }
4679
- if (endOfDirectoryArray.length < ZIP64_END_OF_CENTRAL_DIR_LENGTH || getUint32(endOfDirectoryView, 0) != ZIP64_END_OF_CENTRAL_DIR_SIGNATURE) {
4838
+ if (endOfDirectoryArray.length < ZIP64_END_OF_CENTRAL_DIR_LENGTH || getUint32$1(endOfDirectoryView, 0) != ZIP64_END_OF_CENTRAL_DIR_SIGNATURE) {
4680
4839
  throw new Error(ERR_EOCDR_LOCATOR_ZIP64_NOT_FOUND);
4681
4840
  }
4682
4841
  zip64EndOfDirectory = true;
4683
4842
  zip64EndOfDirectoryVersion2 = getBigUint64(endOfDirectoryView, 4) > ZIP64_END_OF_CENTRAL_DIR_LENGTH - 12;
4684
4843
  if (zip64EndOfDirectoryVersion2) {
4685
4844
  const extensibleDataLength = Math.min(
4686
- Number(getBigUint64(endOfDirectoryView, 4)) - (ZIP64_END_OF_CENTRAL_DIR_LENGTH - 12),
4845
+ getBigUint64(endOfDirectoryView, 4) - (ZIP64_END_OF_CENTRAL_DIR_LENGTH - 12),
4687
4846
  reader.size - directoryDataOffset - ZIP64_END_OF_CENTRAL_DIR_LENGTH);
4688
4847
  if (extensibleDataLength > 0) {
4848
+ zip64EndOfDirectoryLength += extensibleDataLength;
4689
4849
  const rawExtensibleData = await readUint8Array(reader, directoryDataOffset + ZIP64_END_OF_CENTRAL_DIR_LENGTH, extensibleDataLength);
4690
4850
  directoryEncryptionInfo = getDirectoryEncryptionInfo(rawExtensibleData);
4691
4851
  }
4692
4852
  }
4693
4853
  if (lastDiskNumber == MAX_16_BITS) {
4694
- lastDiskNumber = getUint32(endOfDirectoryView, 16);
4695
- } else if (checkAmbiguity && lastDiskNumber != getUint32(endOfDirectoryView, 16)) {
4696
- throwAmbiguousArchive("mismatched zip64 end of central directory record");
4854
+ lastDiskNumber = getUint32$1(endOfDirectoryView, 16);
4855
+ } else if (lastDiskNumber != getUint32$1(endOfDirectoryView, 16)) {
4856
+ reportAmbiguity(checkAmbiguity, warnings, WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY);
4697
4857
  }
4698
4858
  if (diskNumber == MAX_16_BITS) {
4699
- diskNumber = getUint32(endOfDirectoryView, 20);
4700
- } else if (checkAmbiguity && diskNumber != getUint32(endOfDirectoryView, 20)) {
4701
- throwAmbiguousArchive("mismatched zip64 end of central directory record");
4859
+ diskNumber = getUint32$1(endOfDirectoryView, 20);
4860
+ } else if (diskNumber != getUint32$1(endOfDirectoryView, 20)) {
4861
+ reportAmbiguity(checkAmbiguity, warnings, WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY);
4702
4862
  }
4703
4863
  if (filesLength == MAX_16_BITS) {
4704
4864
  filesLength = getBigUint64(endOfDirectoryView, 32);
4705
- } else if (checkAmbiguity && filesLength != getBigUint64(endOfDirectoryView, 32)) {
4706
- throwAmbiguousArchive("mismatched zip64 end of central directory record");
4865
+ } else if (filesLength != getBigUint64(endOfDirectoryView, 32)) {
4866
+ reportAmbiguity(checkAmbiguity, warnings, WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY);
4707
4867
  }
4708
4868
  if (directoryDataLength == MAX_32_BITS) {
4709
4869
  directoryDataLength = getBigUint64(endOfDirectoryView, 40);
4710
- } else if (checkAmbiguity && directoryDataLength != getBigUint64(endOfDirectoryView, 40)) {
4711
- throwAmbiguousArchive("mismatched zip64 end of central directory record");
4870
+ } else if (directoryDataLength != getBigUint64(endOfDirectoryView, 40)) {
4871
+ reportAmbiguity(checkAmbiguity, warnings, WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY);
4712
4872
  }
4713
4873
  directoryDataOffset = getDiskOffset$1(reader, diskNumber) + getBigUint64(endOfDirectoryView, 48) + prependedDataLength;
4714
4874
  }
4715
4875
  }
4716
4876
  let declaredDirectoryDataLength = directoryDataLength;
4717
4877
  const centralDirectoryEndOffset = endOfDirectoryInfo.offset -
4718
- (zip64EndOfDirectory ? ZIP64_END_OF_CENTRAL_DIR_LENGTH + ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH : 0);
4878
+ (zip64EndOfDirectory ? zip64EndOfDirectoryLength + ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH : 0);
4719
4879
  if (directoryDataOffset >= reader.size) {
4720
4880
  prependedDataLength = reader.size - directoryDataOffset - directoryDataLength - END_OF_CENTRAL_DIR_LENGTH;
4721
4881
  directoryDataOffset = reader.size - directoryDataLength - END_OF_CENTRAL_DIR_LENGTH;
@@ -4735,11 +4895,13 @@ class ZipReader {
4735
4895
  }
4736
4896
  const expectedDirectoryDataOffset = centralDirectoryEndOffset - directoryDataLength;
4737
4897
  if (directoryDataOffset != expectedDirectoryDataOffset && diskNumber == lastDiskNumber) {
4738
- const storedPointsAtDirectory = getUint32(directoryView, offset) == CENTRAL_FILE_HEADER_SIGNATURE;
4898
+ const storedPointsAtDirectory = getUint32$1(directoryView, offset) == CENTRAL_FILE_HEADER_SIGNATURE ||
4899
+ Boolean(directoryEncryptionInfo && directoryEncryptionInfo.compressedSize) ||
4900
+ detectEncryptedCentralDirectory(directoryView);
4739
4901
  let reconcile = !storedPointsAtDirectory;
4740
4902
  if (!reconcile && expectedDirectoryDataOffset >= 0 && expectedDirectoryDataOffset + 4 <= reader.size) {
4741
4903
  const expectedSignatureArray = await readUint8Array(reader, expectedDirectoryDataOffset, 4);
4742
- reconcile = getUint32(getDataView(expectedSignatureArray), 0) == CENTRAL_FILE_HEADER_SIGNATURE;
4904
+ reconcile = getUint32$1(getDataView(expectedSignatureArray), 0) == CENTRAL_FILE_HEADER_SIGNATURE;
4743
4905
  }
4744
4906
  if (reconcile) {
4745
4907
  const originalDirectoryDataOffset = directoryDataOffset;
@@ -4763,24 +4925,38 @@ class ZipReader {
4763
4925
  }
4764
4926
  zipReader.directoryOffset = directoryDataOffset;
4765
4927
  zipReader.directoryLength = declaredDirectoryDataLength;
4766
- const decryptCentralDirectory = getOptionValue$1(zipReader, options, OPTION_DECRYPT_CENTRAL_DIRECTORY);
4767
- let decryptedDirectory;
4928
+ const decryptCentralDirectory = getFunctionOptionValue$1(zipReader, options, OPTION_DECRYPT_CENTRAL_DIRECTORY);
4929
+ let decryptedDirectory, dataAfterEncryptedDirectory;
4768
4930
  if (decryptCentralDirectory && filesLength && directoryArray.length >= 4 &&
4769
- getUint32(directoryView, 0) != CENTRAL_FILE_HEADER_SIGNATURE &&
4931
+ getUint32$1(directoryView, 0) != CENTRAL_FILE_HEADER_SIGNATURE &&
4770
4932
  (zip64EndOfDirectoryVersion2 || detectEncryptedCentralDirectory(directoryView))) {
4771
- directoryArray = await decryptCentralDirectory(directoryArray, directoryEncryptionInfo);
4933
+ const encryptedDirectoryDataLength = getEncryptedDirectoryDataLength(directoryEncryptionInfo, declaredDirectoryDataLength, directoryArray.length);
4934
+ dataAfterEncryptedDirectory = directoryArray.subarray(encryptedDirectoryDataLength);
4935
+ directoryArray = await decryptCentralDirectory(directoryArray.subarray(0, encryptedDirectoryDataLength), directoryEncryptionInfo);
4772
4936
  directoryView = getDataView(directoryArray);
4773
4937
  declaredDirectoryDataLength = directoryArray.length;
4774
4938
  decryptedDirectory = true;
4775
4939
  }
4940
+ if (directoryEncryptionInfo && !decryptedDirectory &&
4941
+ (directoryArray.length < 4 || getUint32$1(directoryView, 0) == CENTRAL_FILE_HEADER_SIGNATURE)) {
4942
+ addWarning(warnings, WARNING_UNKNOWN_ZIP64_EXTENSIBLE_DATA);
4943
+ }
4776
4944
  startOffset = directoryDataOffset;
4777
4945
  const filenameEncoding = getOptionValue$1(zipReader, options, OPTION_FILENAME_ENCODING);
4778
4946
  const commentEncoding = getOptionValue$1(zipReader, options, OPTION_COMMENT_ENCODING);
4779
- const filenames = checkAmbiguity ? new Set() : UNDEFINED_VALUE;
4947
+ const filenames = new Set();
4780
4948
  let duplicateFilename;
4949
+ let previousEntryPosition = -1;
4950
+ const recoverWrappedFilesLength = !checkAmbiguity && !zip64EndOfDirectory;
4951
+ if (!filesLength && recoverWrappedFilesLength) {
4952
+ filesLength = getWrappedFilesLength(directoryView, directoryArray, offset);
4953
+ if (filesLength) {
4954
+ addWarning(warnings, WARNING_WRAPPED_ENTRIES_COUNT);
4955
+ }
4956
+ }
4781
4957
  for (let indexFile = 0; indexFile < filesLength; indexFile++) {
4782
- const fileEntry = new ZipEntry(reader, config, zipReader.options);
4783
- if (offset + CENTRAL_FILE_HEADER_LENGTH > directoryArray.length || getUint32(directoryView, offset) != CENTRAL_FILE_HEADER_SIGNATURE) {
4958
+ const fileEntry = new ZipEntry(reader, zipReader.options);
4959
+ if (offset + CENTRAL_FILE_HEADER_LENGTH > directoryArray.length || getUint32$1(directoryView, offset) != CENTRAL_FILE_HEADER_SIGNATURE) {
4784
4960
  if (indexFile == 0 && !decryptedDirectory && (zip64EndOfDirectoryVersion2 || detectEncryptedCentralDirectory(directoryView))) {
4785
4961
  throw new Error(ERR_ENCRYPTED_CENTRAL_DIRECTORY);
4786
4962
  }
@@ -4791,16 +4967,16 @@ class ZipReader {
4791
4967
  const filenameOffset = offset + CENTRAL_FILE_HEADER_LENGTH;
4792
4968
  const extraFieldOffset = filenameOffset + fileEntry.filenameLength;
4793
4969
  const commentOffset = extraFieldOffset + fileEntry.extraFieldLength;
4794
- const versionMadeBy = getUint16(directoryView, offset + 4);
4970
+ const versionMadeBy = getUint16$1(directoryView, offset + 4);
4795
4971
  const msDosCompatible = versionMadeBy >> 8 == 0;
4796
4972
  const unixCompatible = versionMadeBy >> 8 == 3;
4797
4973
  const rawFilename = directoryArray.subarray(filenameOffset, extraFieldOffset);
4798
- const commentLength = getUint16(directoryView, offset + 32);
4974
+ const commentLength = getUint16$1(directoryView, offset + 32);
4799
4975
  const endOffset = commentOffset + commentLength;
4800
4976
  const rawComment = directoryArray.subarray(commentOffset, endOffset);
4801
4977
  const filenameUTF8 = languageEncodingFlag;
4802
4978
  const commentUTF8 = languageEncodingFlag;
4803
- const externalFileAttributes = getUint32(directoryView, offset + 38);
4979
+ const externalFileAttributes = getUint32$1(directoryView, offset + 38);
4804
4980
  const msdosAttributesRaw = externalFileAttributes & MAX_8_BITS;
4805
4981
  const msdosAttributes = {
4806
4982
  readOnly: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_READONLY_MASK),
@@ -4809,8 +4985,8 @@ class ZipReader {
4809
4985
  directory: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_DIR_MASK),
4810
4986
  archive: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_ARCHIVE_MASK)
4811
4987
  };
4812
- const offsetFileEntry = getUint32(directoryView, offset + 42);
4813
- const decode = getOptionValue$1(zipReader, options, OPTION_DECODE_TEXT) || decodeText;
4988
+ const offsetFileEntry = getUint32$1(directoryView, offset + 42);
4989
+ const decode = getFunctionOptionValue$1(zipReader, options, OPTION_DECODE_TEXT) || decodeText;
4814
4990
  const rawFilenameEncoding = filenameUTF8 ? CHARSET_UTF8 : filenameEncoding || CHARSET_CP437;
4815
4991
  const rawCommentEncoding = commentUTF8 ? CHARSET_UTF8 : commentEncoding || CHARSET_CP437;
4816
4992
  let filename = decode(rawFilename, rawFilenameEncoding, TEXT_TYPE_FILENAME);
@@ -4834,14 +5010,16 @@ class ZipReader {
4834
5010
  }
4835
5011
  Object.assign(fileEntry, {
4836
5012
  index: indexFile,
5013
+ decryptedDirectory,
4837
5014
  versionMadeBy,
4838
5015
  msDosCompatible,
5016
+ zip64: false,
4839
5017
  compressedSize: 0,
4840
5018
  uncompressedSize: 0,
4841
5019
  commentLength,
4842
5020
  offset: offsetFileEntry,
4843
- diskNumberStart: getUint16(directoryView, offset + 34),
4844
- internalFileAttributes: getUint16(directoryView, offset + 36),
5021
+ diskNumberStart: getUint16$1(directoryView, offset + 34),
5022
+ internalFileAttributes: getUint16$1(directoryView, offset + 36),
4845
5023
  externalFileAttributes,
4846
5024
  msdosAttributesRaw,
4847
5025
  msdosAttributes,
@@ -4853,15 +5031,26 @@ class ZipReader {
4853
5031
  filename,
4854
5032
  comment
4855
5033
  });
4856
- readCommonFooter(fileEntry, fileEntry, directoryView, offset + 6);
5034
+ if (readCommonFooter(fileEntry, fileEntry, directoryView, offset + 6)) {
5035
+ addWarning(warnings, WARNING_MALFORMED_EXTRA_FIELD, filename);
5036
+ }
4857
5037
  fileEntry.offset += prependedDataLength;
4858
- startOffset = Math.min(getDiskOffset$1(reader, fileEntry.diskNumberStart) + fileEntry.offset, startOffset);
4859
- if (checkAmbiguity) {
4860
- if (filenames.has(fileEntry.filename)) {
4861
- duplicateFilename = true;
4862
- }
4863
- filenames.add(fileEntry.filename);
5038
+ const entryPosition = getDiskOffset$1(reader, fileEntry.diskNumberStart) + fileEntry.offset;
5039
+ startOffset = Math.min(entryPosition, startOffset);
5040
+ if (entryPosition < previousEntryPosition) {
5041
+ addWarning(warnings, WARNING_UNSORTED_CENTRAL_DIRECTORY, filename);
5042
+ }
5043
+ previousEntryPosition = entryPosition;
5044
+ if ((fileEntry.version & MAX_8_BITS) > MAX_KNOWN_VERSION) {
5045
+ addWarning(warnings, WARNING_UNKNOWN_VERSION, filename);
5046
+ }
5047
+ if ((fileEntry.rawBitFlag & BITFLAG_COMPRESSED_PATCHED_DATA) == BITFLAG_COMPRESSED_PATCHED_DATA) {
5048
+ addWarning(warnings, WARNING_COMPRESSED_PATCHED_DATA, filename);
5049
+ }
5050
+ if (filenames.has(fileEntry.filename)) {
5051
+ duplicateFilename = true;
4864
5052
  }
5053
+ filenames.add(fileEntry.filename);
4865
5054
  const unixExternalUpper = (fileEntry.externalFileAttributes >> 16) & MAX_16_BITS;
4866
5055
  if (fileEntry.unixMode === UNDEFINED_VALUE && (unixExternalUpper & (FILE_ATTR_UNIX_DEFAULT_MASK | FILE_ATTR_UNIX_EXECUTABLE_MASK | FILE_ATTR_UNIX_TYPE_DIR)) != 0) {
4867
5056
  fileEntry.unixMode = unixExternalUpper;
@@ -4869,20 +5058,23 @@ class ZipReader {
4869
5058
  const setuid = Boolean(fileEntry.unixMode & FILE_ATTR_UNIX_SETUID_MASK);
4870
5059
  const setgid = Boolean(fileEntry.unixMode & FILE_ATTR_UNIX_SETGID_MASK);
4871
5060
  const sticky = Boolean(fileEntry.unixMode & FILE_ATTR_UNIX_STICKY_MASK);
4872
- const executable = (fileEntry.unixMode !== UNDEFINED_VALUE)
5061
+ const unixType = fileEntry.unixMode === UNDEFINED_VALUE ? unixExternalUpper : fileEntry.unixMode;
5062
+ const symlink = (unixType & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_SYMLINK;
5063
+ const executable = !symlink && ((fileEntry.unixMode !== UNDEFINED_VALUE)
4873
5064
  ? ((fileEntry.unixMode & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0)
4874
- : (unixCompatible && ((unixExternalUpper & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0));
5065
+ : (unixCompatible && ((unixExternalUpper & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0)));
4875
5066
  const modeIsDir = fileEntry.unixMode !== UNDEFINED_VALUE && ((fileEntry.unixMode & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_DIR);
4876
5067
  const upperIsDir = ((unixExternalUpper & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_DIR);
4877
5068
  Object.assign(fileEntry, {
4878
5069
  setuid,
4879
5070
  setgid,
4880
5071
  sticky,
5072
+ symlink,
4881
5073
  unixExternalUpper,
4882
5074
  internalFileAttribute: fileEntry.internalFileAttributes,
4883
5075
  externalFileAttribute: fileEntry.externalFileAttributes,
4884
5076
  executable,
4885
- directory: modeIsDir || upperIsDir || (msDosCompatible && msdosAttributes.directory) || (fileEntry.filename.endsWith(DIRECTORY_SIGNATURE) && !fileEntry.uncompressedSize),
5077
+ directory: modeIsDir || upperIsDir || (msDosCompatible && msdosAttributes.directory) || fileEntry.filename.endsWith(DIRECTORY_SIGNATURE),
4886
5078
  zipCrypto: fileEntry.encrypted && !fileEntry.extraFieldAES
4887
5079
  });
4888
5080
  const entry = new Entry(fileEntry);
@@ -4895,6 +5087,13 @@ class ZipReader {
4895
5087
  return arrayBufferPromise;
4896
5088
  };
4897
5089
  offset = endOffset;
5090
+ if (indexFile == filesLength - 1 && recoverWrappedFilesLength) {
5091
+ const wrappedFilesLength = getWrappedFilesLength(directoryView, directoryArray, offset);
5092
+ if (wrappedFilesLength) {
5093
+ filesLength += wrappedFilesLength;
5094
+ addWarning(warnings, WARNING_WRAPPED_ENTRIES_COUNT);
5095
+ }
5096
+ }
4898
5097
  const { onprogress } = options;
4899
5098
  if (onprogress) {
4900
5099
  try {
@@ -4906,26 +5105,40 @@ class ZipReader {
4906
5105
  yield entry;
4907
5106
  }
4908
5107
  let offsetAfterSignature = offset;
4909
- if (offset + 6 <= directoryArray.length && getUint32(directoryView, offset) == DIGITAL_SIGNATURE_RECORD_SIGNATURE) {
4910
- const signatureDataLength = getUint16(directoryView, offset + 4);
4911
- if (offset + 6 + signatureDataLength <= directoryArray.length) {
4912
- zipReader.digitalSignature = directoryArray.subarray(offset + 6, offset + 6 + signatureDataLength);
4913
- offsetAfterSignature = offset + 6 + signatureDataLength;
5108
+ let digitalSignature = readDigitalSignature(directoryArray.subarray(offset)) ||
5109
+ (decryptedDirectory ? readDigitalSignature(dataAfterEncryptedDirectory) : UNDEFINED_VALUE);
5110
+ if (!digitalSignature && !decryptedDirectory) {
5111
+ const signatureRecordOffset = directoryDataOffset + offset;
5112
+ const signatureRecordLength = Math.min(centralDirectoryEndOffset - signatureRecordOffset, 6 + MAX_16_BITS);
5113
+ if (signatureRecordLength >= 6) {
5114
+ digitalSignature = readDigitalSignature(await readUint8Array(reader, signatureRecordOffset, signatureRecordLength));
4914
5115
  }
4915
5116
  }
4916
- if (checkAmbiguity && offset != declaredDirectoryDataLength && offsetAfterSignature != declaredDirectoryDataLength) {
4917
- throwAmbiguousArchive("trailing central directory data");
5117
+ if (digitalSignature) {
5118
+ zipReader.digitalSignature = digitalSignature;
5119
+ offsetAfterSignature = offset + 6 + digitalSignature.length;
4918
5120
  }
4919
- if (duplicateFilename) {
4920
- throwAmbiguousArchive("duplicate filename");
5121
+ if ((offset != declaredDirectoryDataLength && offsetAfterSignature != declaredDirectoryDataLength) ||
5122
+ (!decryptedDirectory && offset != directoryDataLength && offsetAfterSignature != directoryDataLength)) {
5123
+ reportAmbiguity(checkAmbiguity, warnings, WARNING_TRAILING_CENTRAL_DIRECTORY_DATA);
4921
5124
  }
4922
- if (checkAmbiguity && (prependedDataLength || (filesLength && startOffset > 0))) {
4923
- throwAmbiguousArchive("prepended data");
5125
+ if (duplicateFilename) {
5126
+ reportAmbiguity(checkAmbiguity, warnings, WARNING_DUPLICATE_FILENAME);
4924
5127
  }
4925
5128
  const extractPrependedData = getOptionValue$1(zipReader, options, OPTION_EXTRACT_PREPENDED_DATA);
4926
5129
  const extractAppendedData = getOptionValue$1(zipReader, options, OPTION_EXTRACT_APPENDED_DATA);
5130
+ const splitZipSignatureLength = (checkAmbiguity || extractPrependedData) && filesLength &&
5131
+ startOffset == SPLIT_ZIP_FILE_SIGNATURE_LENGTH && await startsWithSplitZipMarker(reader) ? SPLIT_ZIP_FILE_SIGNATURE_LENGTH : 0;
5132
+ if (checkAmbiguity && (prependedDataLength || (filesLength && startOffset > splitZipSignatureLength))) {
5133
+ throwAmbiguousArchive(WARNING_PREPENDED_DATA);
5134
+ }
5135
+ if (prependedDataLength || (filesLength && startOffset > SPLIT_ZIP_FILE_SIGNATURE_LENGTH)) {
5136
+ addWarning(warnings, WARNING_PREPENDED_DATA);
5137
+ }
4927
5138
  if (extractPrependedData) {
4928
- zipReader.prependedData = startOffset > 0 ? await readUint8Array(reader, 0, startOffset) : EMPTY_UINT8_ARRAY;
5139
+ zipReader.prependedData = startOffset > splitZipSignatureLength ?
5140
+ await readUint8Array(reader, splitZipSignatureLength, startOffset - splitZipSignatureLength) :
5141
+ EMPTY_UINT8_ARRAY;
4929
5142
  }
4930
5143
  zipReader.comment = commentLength ? await readUint8Array(reader, commentOffset + END_OF_CENTRAL_DIR_LENGTH, commentLength) : EMPTY_UINT8_ARRAY;
4931
5144
  if (extractAppendedData) {
@@ -4943,6 +5156,10 @@ class ZipReader {
4943
5156
  }
4944
5157
 
4945
5158
  async close() {
5159
+ const { reader } = this;
5160
+ if (!reader.readUint8Array && reader.readable && !reader.readable.locked) {
5161
+ await reader.readable.cancel();
5162
+ }
4946
5163
  }
4947
5164
  }
4948
5165
 
@@ -4986,18 +5203,40 @@ class ZipReaderStream {
4986
5203
  }
4987
5204
  }
4988
5205
 
5206
+ async function isZipFile(reader, options = {}) {
5207
+ reader = new GenericReader(reader);
5208
+ await initStream(reader);
5209
+ if (reader.size === UNDEFINED_VALUE || !reader.readUint8Array) {
5210
+ reader = new BlobReader(await streamToBlob(reader.readable));
5211
+ await initStream(reader);
5212
+ }
5213
+ if (reader.size < END_OF_CENTRAL_DIR_LENGTH) {
5214
+ return false;
5215
+ }
5216
+ const strictness = getStrictness(options, {});
5217
+ const rejectAmbiguousEndOfDirectory = strictness != STRICTNESS_TOLERANT;
5218
+ const maxAppendedDataSize = getMaxAppendedDataSize(options[OPTION_MAX_APPENDED_DATA_SIZE], strictness);
5219
+ const { endOfDirectoryInfo, endOfDirectoryReachingEndCount } = await findEndOfCentralDirectory(reader, rejectAmbiguousEndOfDirectory, maxAppendedDataSize);
5220
+ if (!endOfDirectoryInfo || (strictness == STRICTNESS_STRICT && endOfDirectoryReachingEndCount > 1)) {
5221
+ return false;
5222
+ }
5223
+ const commentLength = getUint16$1(getDataView(endOfDirectoryInfo), 20);
5224
+ const appendedDataOffset = endOfDirectoryInfo.offset + END_OF_CENTRAL_DIR_LENGTH + commentLength;
5225
+ return reader.size - appendedDataOffset <= maxAppendedDataSize;
5226
+ }
5227
+
4989
5228
  class ZipEntry {
4990
5229
 
4991
- constructor(reader, config, options) {
5230
+ constructor(reader, options) {
4992
5231
  Object.assign(this, {
4993
5232
  reader,
4994
- config,
4995
5233
  options
4996
5234
  });
4997
5235
  }
4998
5236
 
4999
5237
  async getData(writer, fileEntry, readRanges, options = {}) {
5000
5238
  const zipEntry = this;
5239
+ const config = getConfiguration();
5001
5240
  const {
5002
5241
  reader,
5003
5242
  index,
@@ -5006,7 +5245,6 @@ class ZipEntry {
5006
5245
  extraFieldAES,
5007
5246
  extraFieldZip64,
5008
5247
  compressionMethod,
5009
- config,
5010
5248
  bitFlag,
5011
5249
  rawBitFlag,
5012
5250
  crc32,
@@ -5018,12 +5256,14 @@ class ZipEntry {
5018
5256
  dataDescriptor
5019
5257
  } = bitFlag;
5020
5258
  const localDirectory = fileEntry.localDirectory = {};
5259
+ const warnings = fileEntry.warnings = [];
5021
5260
  const localHeaderOffset = getDiskOffset$1(reader, diskNumberStart) + offset;
5022
5261
  const dataArray = await readUint8Array(reader, localHeaderOffset, HEADER_SIZE);
5023
5262
  const dataView = getDataView(dataArray);
5024
5263
  let password = getOptionValue$1(zipEntry, options, OPTION_PASSWORD);
5025
5264
  let rawPassword = getOptionValue$1(zipEntry, options, OPTION_RAW_PASSWORD);
5026
5265
  const passThrough = getOptionValue$1(zipEntry, options, OPTION_PASS_THROUGH);
5266
+ checkPasswordOption(password, rawPassword);
5027
5267
  password = password && password.length && password;
5028
5268
  rawPassword = rawPassword && rawPassword.length && rawPassword;
5029
5269
  if (extraFieldAES) {
@@ -5031,7 +5271,7 @@ class ZipEntry {
5031
5271
  throw new Error(ERR_UNSUPPORTED_COMPRESSION$1);
5032
5272
  }
5033
5273
  }
5034
- if (dataArray.length < HEADER_SIZE || getUint32(dataView, 0) != LOCAL_FILE_HEADER_SIGNATURE) {
5274
+ if (dataArray.length < HEADER_SIZE || getUint32$1(dataView, 0) != LOCAL_FILE_HEADER_SIGNATURE) {
5035
5275
  throw new Error(ERR_LOCAL_FILE_HEADER_NOT_FOUND);
5036
5276
  }
5037
5277
  readCommonHeader(localDirectory, dataView, 4);
@@ -5039,9 +5279,13 @@ class ZipEntry {
5039
5279
  extraFieldLength,
5040
5280
  filenameLength
5041
5281
  } = localDirectory;
5042
- const checkAmbiguity = getStrictness(getOptionValue$1(zipEntry, options, OPTION_STRICTNESS), getOptionValue$1(zipEntry, options, OPTION_CHECK_AMBIGUITY)) == STRICTNESS_STRICT;
5282
+ const dataOffset = localDirectory.dataOffset = localHeaderOffset + HEADER_SIZE + filenameLength + extraFieldLength;
5283
+ const checkLocalDirectoryOption = getOptionValue$1(zipEntry, options, OPTION_CHECK_LOCAL_DIRECTORY);
5284
+ const entryStrictness = getStrictness(options, zipEntry.options);
5285
+ const checkLocalDirectory = getCheckLocalDirectory(checkLocalDirectoryOption, entryStrictness);
5286
+ const checkLocalFilename = getCheckLocalFilename(checkLocalDirectoryOption, entryStrictness);
5043
5287
  let rawLocalFilename = EMPTY_UINT8_ARRAY;
5044
- if (checkAmbiguity && (filenameLength || extraFieldLength)) {
5288
+ if (checkLocalFilename && (filenameLength || extraFieldLength)) {
5045
5289
  const trailingDataArray = await readUint8Array(reader, localHeaderOffset + HEADER_SIZE, filenameLength + extraFieldLength);
5046
5290
  rawLocalFilename = trailingDataArray.subarray(0, filenameLength);
5047
5291
  localDirectory.rawExtraField = trailingDataArray.subarray(filenameLength);
@@ -5050,17 +5294,26 @@ class ZipEntry {
5050
5294
  await readUint8Array(reader, localHeaderOffset + HEADER_SIZE + filenameLength, extraFieldLength) :
5051
5295
  EMPTY_UINT8_ARRAY;
5052
5296
  }
5053
- readCommonFooter(zipEntry, localDirectory, dataView, 4, true);
5054
- if (checkAmbiguity) {
5055
- checkLocalDirectory(zipEntry, localDirectory, rawLocalFilename);
5297
+ if (checkLocalFilename) {
5298
+ localDirectory.rawFilename = rawLocalFilename;
5299
+ }
5300
+ if (readCommonFooter(zipEntry, localDirectory, dataView, 4, true)) {
5301
+ addWarning(warnings, WARNING_MALFORMED_EXTRA_FIELD);
5056
5302
  }
5057
- const { lastAccessDate, creationDate } = localDirectory;
5303
+ validateLocalDirectory(zipEntry, localDirectory, rawLocalFilename, checkLocalFilename, checkLocalDirectory ? UNDEFINED_VALUE : warnings);
5304
+ const { lastAccessDate, creationDate, uid, gid } = localDirectory;
5058
5305
  if (lastAccessDate) {
5059
5306
  fileEntry.lastAccessDate = lastAccessDate;
5060
5307
  }
5061
5308
  if (creationDate) {
5062
5309
  fileEntry.creationDate = creationDate;
5063
5310
  }
5311
+ if (uid !== UNDEFINED_VALUE && fileEntry.uid === UNDEFINED_VALUE) {
5312
+ fileEntry.uid = uid;
5313
+ }
5314
+ if (gid !== UNDEFINED_VALUE && fileEntry.gid === UNDEFINED_VALUE) {
5315
+ fileEntry.gid = gid;
5316
+ }
5064
5317
  const encrypted = zipEntry.encrypted && localDirectory.encrypted && !passThrough;
5065
5318
  const zipCrypto = encrypted && !extraFieldAES;
5066
5319
  if (!passThrough) {
@@ -5080,10 +5333,12 @@ class ZipEntry {
5080
5333
  throw new Error(ERR_ENCRYPTED);
5081
5334
  }
5082
5335
  }
5083
- const dataOffset = localHeaderOffset + HEADER_SIZE + filenameLength + extraFieldLength;
5336
+ if (dataOffset + compressedSize > reader.size) {
5337
+ throw new Error(ERR_ENTRY_DATA_OUT_OF_BOUNDS);
5338
+ }
5084
5339
  const size = compressedSize;
5085
5340
  const readable = toCompatibleReadable(reader.createReadable({ offset: dataOffset, size }));
5086
- const signal = getOptionValue$1(zipEntry, options, OPTION_SIGNAL);
5341
+ const signal = checkSignalOption(getOptionValue$1(zipEntry, options, OPTION_SIGNAL));
5087
5342
  const checkPasswordOnly = getOptionValue$1(zipEntry, options, OPTION_CHECK_PASSWORD_ONLY);
5088
5343
  let checkOverlappingEntry = getOptionValue$1(zipEntry, options, OPTION_CHECK_OVERLAPPING_ENTRY);
5089
5344
  const checkOverlappingEntryOnly = getOptionValue$1(zipEntry, options, OPTION_CHECK_OVERLAPPING_ENTRY_ONLY);
@@ -5091,6 +5346,8 @@ class ZipEntry {
5091
5346
  checkOverlappingEntry = true;
5092
5347
  }
5093
5348
  const { onstart, onprogress, onend } = options;
5349
+ const compressed = compressionMethod != COMPRESSION_METHOD_STORE && !passThrough;
5350
+ const outputSize = passThrough ? compressedSize : uncompressedSize;
5094
5351
  const deflate64 = compressionMethod == COMPRESSION_METHOD_DEFLATE_64;
5095
5352
  let useCompressionStream = getOptionValue$1(zipEntry, options, OPTION_USE_COMPRESSION_STREAM);
5096
5353
  if (deflate64) {
@@ -5111,9 +5368,9 @@ class ZipEntry {
5111
5368
  checkCrc32,
5112
5369
  checkAuthenticationCode: getOptionValue$1(zipEntry, options, OPTION_CHECK_AUTHENTICATION_CODE),
5113
5370
  passwordVerification: zipCrypto && (dataDescriptor ? ((rawLastModDate >>> 8) & MAX_8_BITS) : ((crc32 >>> 24) & MAX_8_BITS)),
5114
- outputSize: passThrough ? compressedSize : uncompressedSize,
5371
+ outputSize,
5115
5372
  crc32,
5116
- compressed: compressionMethod != 0 && !passThrough,
5373
+ compressed,
5117
5374
  encrypted,
5118
5375
  useWebWorkers: getOptionValue$1(zipEntry, options, OPTION_USE_WEB_WORKERS),
5119
5376
  useCompressionStream,
@@ -5150,11 +5407,11 @@ class ZipEntry {
5150
5407
  writer = new WritableStream();
5151
5408
  }
5152
5409
  writer = new GenericWriter(writer);
5153
- await initStream(writer, passThrough ? compressedSize : uncompressedSize);
5410
+ await initStream(writer, getDecodableOutputSize(outputSize, compressedSize, compressed));
5154
5411
  ({ writable } = writer);
5155
- const { outputSize } = await runWorker({ readable, writable }, workerOptions);
5156
- writer.size += outputSize;
5157
- if (outputSize != (passThrough ? compressedSize : uncompressedSize)) {
5412
+ const { outputSize: writtenSize } = await runWorker({ readable, writable }, workerOptions);
5413
+ writer.size += writtenSize;
5414
+ if (writtenSize != outputSize) {
5158
5415
  throw new Error(ERR_INVALID_UNCOMPRESSED_SIZE);
5159
5416
  }
5160
5417
  }
@@ -5167,7 +5424,7 @@ class ZipEntry {
5167
5424
  throw error;
5168
5425
  }
5169
5426
  } finally {
5170
- const preventClose = getOptionValue$1(zipEntry, options, OPTION_PREVENT_CLOSE);
5427
+ const preventClose = !ownsWritable(writer) && getOptionValue$1(zipEntry, options, OPTION_PREVENT_CLOSE);
5171
5428
  if (!preventClose && writable && !writable.locked) {
5172
5429
  const writableWriter = writable.getWriter();
5173
5430
  if (abortError) {
@@ -5188,26 +5445,57 @@ class ZipEntry {
5188
5445
  function detectEncryptedCentralDirectory(directoryView) {
5189
5446
  const maxOffset = Math.min(directoryView.byteLength, 1024) - 3;
5190
5447
  for (let offset = 0; offset < maxOffset; offset++) {
5191
- if (getUint32(directoryView, offset) == ARCHIVE_EXTRA_DATA_SIGNATURE) {
5448
+ if (getUint32$1(directoryView, offset) == ARCHIVE_EXTRA_DATA_SIGNATURE) {
5192
5449
  return true;
5193
5450
  }
5194
5451
  }
5195
5452
  return false;
5196
5453
  }
5197
5454
 
5455
+ function getWrappedFilesLength(directoryView, directoryArray, offset) {
5456
+ let wrappedFilesLength = 0;
5457
+ while (offset + CENTRAL_FILE_HEADER_LENGTH <= directoryArray.length && getUint32$1(directoryView, offset) == CENTRAL_FILE_HEADER_SIGNATURE) {
5458
+ offset += CENTRAL_FILE_HEADER_LENGTH +
5459
+ getUint16$1(directoryView, offset + 28) + getUint16$1(directoryView, offset + 30) + getUint16$1(directoryView, offset + 32);
5460
+ wrappedFilesLength++;
5461
+ }
5462
+ return wrappedFilesLength % (MAX_16_BITS + 1) ? 0 : wrappedFilesLength;
5463
+ }
5464
+
5465
+ function readDigitalSignature(signatureRecordArray) {
5466
+ if (signatureRecordArray.length >= 6) {
5467
+ const signatureRecordView = getDataView(signatureRecordArray);
5468
+ if (getUint32$1(signatureRecordView, 0) == DIGITAL_SIGNATURE_RECORD_SIGNATURE) {
5469
+ const signatureDataLength = getUint16$1(signatureRecordView, 4);
5470
+ if (6 + signatureDataLength <= signatureRecordArray.length) {
5471
+ return signatureRecordArray.subarray(6, 6 + signatureDataLength);
5472
+ }
5473
+ }
5474
+ }
5475
+ }
5476
+
5477
+ function getEncryptedDirectoryDataLength(directoryEncryptionInfo, declaredDirectoryDataLength, directoryDataLength) {
5478
+ const encryptedDirectoryDataLength = directoryEncryptionInfo && directoryEncryptionInfo.compressedSize ?
5479
+ directoryEncryptionInfo.compressedSize :
5480
+ declaredDirectoryDataLength;
5481
+ return encryptedDirectoryDataLength > 0 && encryptedDirectoryDataLength <= directoryDataLength ?
5482
+ encryptedDirectoryDataLength :
5483
+ directoryDataLength;
5484
+ }
5485
+
5198
5486
  function getDirectoryEncryptionInfo(rawExtensibleData) {
5199
5487
  const directoryEncryptionInfo = { rawExtensibleData };
5200
5488
  if (rawExtensibleData.length >= 28) {
5201
5489
  const extensibleDataView = getDataView(rawExtensibleData);
5202
- const hashDataLength = getUint16(extensibleDataView, 26);
5490
+ const hashDataLength = getUint16$1(extensibleDataView, 26);
5203
5491
  Object.assign(directoryEncryptionInfo, {
5204
- compressionMethod: getUint16(extensibleDataView, 0),
5205
- compressedSize: Number(getBigUint64(extensibleDataView, 2)),
5206
- uncompressedSize: Number(getBigUint64(extensibleDataView, 10)),
5207
- encryptionAlgorithm: getUint16(extensibleDataView, 18),
5208
- bitLength: getUint16(extensibleDataView, 20),
5209
- flags: getUint16(extensibleDataView, 22),
5210
- hashAlgorithm: getUint16(extensibleDataView, 24),
5492
+ compressionMethod: getUint16$1(extensibleDataView, 0),
5493
+ compressedSize: getBigUint64(extensibleDataView, 2),
5494
+ uncompressedSize: getBigUint64(extensibleDataView, 10),
5495
+ encryptionAlgorithm: getUint16$1(extensibleDataView, 18),
5496
+ bitLength: getUint16$1(extensibleDataView, 20),
5497
+ flags: getUint16$1(extensibleDataView, 22),
5498
+ hashAlgorithm: getUint16$1(extensibleDataView, 24),
5211
5499
  hashData: rawExtensibleData.subarray(28, 28 + hashDataLength)
5212
5500
  });
5213
5501
  }
@@ -5215,12 +5503,12 @@ function getDirectoryEncryptionInfo(rawExtensibleData) {
5215
5503
  }
5216
5504
 
5217
5505
  function readCommonHeader(directory, dataView, offset) {
5218
- const rawBitFlag = directory.rawBitFlag = getUint16(dataView, offset + 2);
5506
+ const rawBitFlag = directory.rawBitFlag = getUint16$1(dataView, offset + 2);
5219
5507
  const encrypted = (rawBitFlag & BITFLAG_ENCRYPTED) == BITFLAG_ENCRYPTED;
5220
- const rawLastModDate = getUint32(dataView, offset + 6);
5508
+ const rawLastModDate = getUint32$1(dataView, offset + 6);
5221
5509
  Object.assign(directory, {
5222
5510
  encrypted,
5223
- version: getUint16(dataView, offset),
5511
+ version: getUint16$1(dataView, offset),
5224
5512
  bitFlag: {
5225
5513
  level: (rawBitFlag & BITFLAG_LEVEL) >> 1,
5226
5514
  dataDescriptor: (rawBitFlag & BITFLAG_DATA_DESCRIPTOR) == BITFLAG_DATA_DESCRIPTOR,
@@ -5228,8 +5516,8 @@ function readCommonHeader(directory, dataView, offset) {
5228
5516
  },
5229
5517
  rawLastModDate,
5230
5518
  lastModDate: getDate(rawLastModDate),
5231
- filenameLength: getUint16(dataView, offset + 22),
5232
- extraFieldLength: getUint16(dataView, offset + 24)
5519
+ filenameLength: getUint16$1(dataView, offset + 22),
5520
+ extraFieldLength: getUint16$1(dataView, offset + 24)
5233
5521
  });
5234
5522
  }
5235
5523
 
@@ -5238,10 +5526,11 @@ function readCommonFooter(fileEntry, directory, dataView, offset, localDirectory
5238
5526
  const extraField = directory.extraField = new Map();
5239
5527
  const rawExtraFieldView = getDataView(rawExtraField);
5240
5528
  let offsetExtraField = 0;
5529
+ let malformedExtraField = false;
5241
5530
  try {
5242
5531
  while (offsetExtraField < rawExtraField.length) {
5243
- const type = getUint16(rawExtraFieldView, offsetExtraField);
5244
- const size = getUint16(rawExtraFieldView, offsetExtraField + 2);
5532
+ const type = getUint16$1(rawExtraFieldView, offsetExtraField);
5533
+ const size = getUint16$1(rawExtraFieldView, offsetExtraField + 2);
5245
5534
  extraField.set(type, {
5246
5535
  type,
5247
5536
  data: rawExtraField.slice(offsetExtraField + 4, offsetExtraField + 4 + size)
@@ -5249,14 +5538,17 @@ function readCommonFooter(fileEntry, directory, dataView, offset, localDirectory
5249
5538
  offsetExtraField += 4 + size;
5250
5539
  }
5251
5540
  } catch {
5252
- // ignored
5541
+ malformedExtraField = true;
5542
+ }
5543
+ if (offsetExtraField > rawExtraField.length) {
5544
+ malformedExtraField = true;
5253
5545
  }
5254
- const compressionMethod = getUint16(dataView, offset + 4);
5546
+ const compressionMethod = getUint16$1(dataView, offset + 4);
5255
5547
  Object.assign(directory, {
5256
- signature: getUint32(dataView, offset + HEADER_OFFSET_SIGNATURE),
5257
- crc32: getUint32(dataView, offset + HEADER_OFFSET_SIGNATURE),
5258
- compressedSize: getUint32(dataView, offset + HEADER_OFFSET_COMPRESSED_SIZE),
5259
- uncompressedSize: getUint32(dataView, offset + HEADER_OFFSET_UNCOMPRESSED_SIZE)
5548
+ signature: getUint32$1(dataView, offset + HEADER_OFFSET_SIGNATURE),
5549
+ crc32: getUint32$1(dataView, offset + HEADER_OFFSET_SIGNATURE),
5550
+ compressedSize: getUint32$1(dataView, offset + HEADER_OFFSET_COMPRESSED_SIZE),
5551
+ uncompressedSize: getUint32$1(dataView, offset + HEADER_OFFSET_UNCOMPRESSED_SIZE)
5260
5552
  });
5261
5553
  const extraFieldZip64 = extraField.get(EXTRAFIELD_TYPE_ZIP64);
5262
5554
  if (extraFieldZip64) {
@@ -5296,10 +5588,12 @@ function readCommonFooter(fileEntry, directory, dataView, offset, localDirectory
5296
5588
  directory.extraFieldNTFS = extraFieldNTFS;
5297
5589
  }
5298
5590
  const extraFieldUnix = extraField.get(EXTRAFIELD_TYPE_UNIX);
5591
+ let unixIdsRead;
5299
5592
  if (extraFieldUnix) {
5300
- readExtraFieldUnix(extraFieldUnix, directory, false);
5593
+ unixIdsRead = readExtraFieldUnix(extraFieldUnix, directory, false);
5301
5594
  directory.extraFieldUnix = extraFieldUnix;
5302
- } else {
5595
+ }
5596
+ if (!unixIdsRead) {
5303
5597
  const extraFieldInfoZip = extraField.get(EXTRAFIELD_TYPE_INFOZIP);
5304
5598
  if (extraFieldInfoZip) {
5305
5599
  readExtraFieldUnix(extraFieldInfoZip, directory, true);
@@ -5315,6 +5609,7 @@ function readCommonFooter(fileEntry, directory, dataView, offset, localDirectory
5315
5609
  if (extraFieldUSDZ) {
5316
5610
  directory.extraFieldUSDZ = extraFieldUSDZ;
5317
5611
  }
5612
+ return malformedExtraField;
5318
5613
  }
5319
5614
 
5320
5615
  function readExtraFieldZip64(extraFieldZip64, directory) {
@@ -5343,11 +5638,12 @@ function readExtraFieldUnicode(extraFieldUnicode, propertyName, rawPropertyName,
5343
5638
  computedCrc32.append(fileEntry[rawPropertyName]);
5344
5639
  const computedCrc32View = getDataView(new Uint8Array(4));
5345
5640
  computedCrc32View.setUint32(0, computedCrc32.get(), true);
5346
- const nameCrc32 = getUint32(extraFieldView, 1);
5641
+ const nameCrc32 = getUint32$1(extraFieldView, 1);
5642
+ const version = getUint8(extraFieldView, 0);
5347
5643
  Object.assign(extraFieldUnicode, {
5348
- version: getUint8(extraFieldView, 0),
5644
+ version,
5349
5645
  [propertyName]: decodeText(extraFieldUnicode.data.subarray(5)),
5350
- valid: !fileEntry.bitFlag.languageEncodingFlag && nameCrc32 == getUint32(computedCrc32View, 0)
5646
+ valid: version == 1 && !fileEntry.bitFlag.languageEncodingFlag && nameCrc32 == getUint32$1(computedCrc32View, 0)
5351
5647
  });
5352
5648
  if (extraFieldUnicode.valid) {
5353
5649
  directory[propertyName] = extraFieldUnicode[propertyName];
@@ -5363,7 +5659,7 @@ function readExtraFieldAES(extraFieldAES, directory, compressionMethod) {
5363
5659
  vendorId: getUint8(extraFieldView, 2),
5364
5660
  strength,
5365
5661
  originalCompressionMethod: compressionMethod,
5366
- compressionMethod: getUint16(extraFieldView, 5)
5662
+ compressionMethod: getUint16$1(extraFieldView, 5)
5367
5663
  });
5368
5664
  directory.compressionMethod = extraFieldAES.compressionMethod;
5369
5665
  if (extraFieldAES.vendorVersion != VENDOR_VERSION_AE_1$1) {
@@ -5377,8 +5673,8 @@ function readExtraFieldNTFS(extraFieldNTFS, directory) {
5377
5673
  let tag1Data;
5378
5674
  try {
5379
5675
  while (offsetExtraField < extraFieldNTFS.data.length && !tag1Data) {
5380
- const tagValue = getUint16(extraFieldView, offsetExtraField);
5381
- const attributeSize = getUint16(extraFieldView, offsetExtraField + 2);
5676
+ const tagValue = getUint16$1(extraFieldView, offsetExtraField);
5677
+ const attributeSize = getUint16$1(extraFieldView, offsetExtraField + 2);
5382
5678
  if (tagValue == EXTRAFIELD_TYPE_NTFS_TAG1) {
5383
5679
  tag1Data = extraFieldNTFS.data.slice(offsetExtraField + 4, offsetExtraField + 4 + attributeSize);
5384
5680
  }
@@ -5402,7 +5698,7 @@ function readExtraFieldNTFS(extraFieldNTFS, directory) {
5402
5698
  const creationDate = getDateNTFS(rawCreationDate);
5403
5699
  const extraFieldData = { lastModDate, lastAccessDate, creationDate };
5404
5700
  Object.assign(extraFieldNTFS, extraFieldData);
5405
- Object.assign(directory, extraFieldData);
5701
+ Object.assign(directory, extraFieldData, { rawLastAccessDate, rawCreationDate });
5406
5702
  }
5407
5703
  }
5408
5704
 
@@ -5411,12 +5707,12 @@ function readExtraFieldUnixDates(extraField, directory) {
5411
5707
  return;
5412
5708
  }
5413
5709
  const extraFieldView = getDataView(extraField.data);
5414
- const lastAccessDate = new Date(getUint32(extraFieldView, 0) * 1000);
5415
- const lastModDate = new Date(getUint32(extraFieldView, 4) * 1000);
5710
+ const lastAccessDate = new Date((getUint32$1(extraFieldView, 0) | 0) * 1000);
5711
+ const lastModDate = new Date((getUint32$1(extraFieldView, 4) | 0) * 1000);
5416
5712
  const extraFieldData = { lastAccessDate, lastModDate };
5417
5713
  if (extraField.data.length >= 12) {
5418
- extraFieldData.uid = getUint16(extraFieldView, 8);
5419
- extraFieldData.gid = getUint16(extraFieldView, 10);
5714
+ extraFieldData.uid = getUint16$1(extraFieldView, 8);
5715
+ extraFieldData.gid = getUint16$1(extraFieldView, 10);
5420
5716
  }
5421
5717
  Object.assign(extraField, extraFieldData);
5422
5718
  Object.assign(directory, extraFieldData);
@@ -5436,8 +5732,8 @@ function readExtraFieldUnix(extraField, directory, isInfoZip) {
5436
5732
  gid = unpackUnixId(extraField.data.subarray(offset, offset + gidSize));
5437
5733
  Object.assign(extraField, { version, uid, gid });
5438
5734
  } else if (extraField.data.length >= 4) {
5439
- uid = getUint16(view, 0);
5440
- gid = getUint16(view, 2);
5735
+ uid = getUint16$1(view, 0);
5736
+ gid = getUint16$1(view, 2);
5441
5737
  Object.assign(extraField, { uid, gid });
5442
5738
  }
5443
5739
  if (uid !== UNDEFINED_VALUE) {
@@ -5446,6 +5742,7 @@ function readExtraFieldUnix(extraField, directory, isInfoZip) {
5446
5742
  if (gid !== UNDEFINED_VALUE) {
5447
5743
  directory.gid = gid;
5448
5744
  }
5745
+ return uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE;
5449
5746
  } catch {
5450
5747
  // ignored
5451
5748
  }
@@ -5486,7 +5783,7 @@ function readExtraFieldExtendedTimestamp(extraFieldExtendedTimestamp, directory,
5486
5783
  let offset = 1;
5487
5784
  timeProperties.forEach((propertyName, indexProperty) => {
5488
5785
  if (extraFieldExtendedTimestamp.data.length >= offset + 4) {
5489
- const time = getUint32(extraFieldView, offset);
5786
+ const time = getUint32$1(extraFieldView, offset);
5490
5787
  directory[propertyName] = extraFieldExtendedTimestamp[propertyName] = new Date((time | 0) * 1000);
5491
5788
  const rawPropertyName = timeRawProperties[indexProperty];
5492
5789
  extraFieldExtendedTimestamp[rawPropertyName] = time;
@@ -5518,26 +5815,25 @@ async function detectOverlappingEntry({
5518
5815
  }
5519
5816
  if (dataDescriptorLength) {
5520
5817
  const dataDescriptorArray = await readUint8Array(reader, dataOffset + compressedSize, dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH);
5521
- const dataDescriptorSignature = dataDescriptorArray.length == dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH &&
5522
- getUint32(getDataView(dataDescriptorArray), 0) == DATA_DESCRIPTOR_RECORD_SIGNATURE;
5523
- if (dataDescriptorSignature) {
5524
- const readCrc32 = getUint32(getDataView(dataDescriptorArray), 4);
5525
- let readCompressedSize;
5526
- let readUncompressedSize;
5527
- if (extraFieldZip64) {
5528
- readCompressedSize = getBigUint64(getDataView(dataDescriptorArray), 8);
5529
- readUncompressedSize = getBigUint64(getDataView(dataDescriptorArray), 16);
5530
- } else {
5531
- readCompressedSize = getUint32(getDataView(dataDescriptorArray), 8);
5532
- readUncompressedSize = getUint32(getDataView(dataDescriptorArray), 12);
5533
- }
5534
- const matchCrc32 = (fileEntry.encrypted && !fileEntry.zipCrypto) || readCrc32 == crc32;
5818
+ const dataDescriptorView = getDataView(dataDescriptorArray);
5819
+ let signature = dataDescriptorArray.length == dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH &&
5820
+ getUint32$1(dataDescriptorView, 0) == DATA_DESCRIPTOR_RECORD_SIGNATURE;
5821
+ if (signature) {
5822
+ const signedDataDescriptor = readDataDescriptor(dataDescriptorView, DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH, extraFieldZip64);
5823
+ const matchCrc32 = (fileEntry.encrypted && !fileEntry.zipCrypto) || signedDataDescriptor.crc32 == crc32;
5535
5824
  if (matchCrc32 &&
5536
- readCompressedSize == compressedSize &&
5537
- readUncompressedSize == uncompressedSize) {
5825
+ signedDataDescriptor.compressedSize == compressedSize &&
5826
+ signedDataDescriptor.uncompressedSize == uncompressedSize) {
5538
5827
  dataDescriptorLength += DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH;
5828
+ } else {
5829
+ signature = false;
5539
5830
  }
5540
5831
  }
5832
+ if (dataDescriptorArray.length >= dataDescriptorLength) {
5833
+ const localDataDescriptor = readDataDescriptor(dataDescriptorView, signature ? DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH : 0, extraFieldZip64);
5834
+ localDataDescriptor.signature = signature;
5835
+ fileEntry.localDirectory.dataDescriptor = localDataDescriptor;
5836
+ }
5541
5837
  }
5542
5838
  const range = {
5543
5839
  start: offset,
@@ -5554,22 +5850,80 @@ async function detectOverlappingEntry({
5554
5850
  readRanges.set(index, range);
5555
5851
  }
5556
5852
 
5853
+ function readDataDescriptor(dataDescriptorView, offset, extraFieldZip64) {
5854
+ const crc32 = getUint32$1(dataDescriptorView, offset);
5855
+ let compressedSize;
5856
+ let uncompressedSize;
5857
+ if (extraFieldZip64) {
5858
+ compressedSize = getBigUint64(dataDescriptorView, offset + 4);
5859
+ uncompressedSize = getBigUint64(dataDescriptorView, offset + 12);
5860
+ } else {
5861
+ compressedSize = getUint32$1(dataDescriptorView, offset + 4);
5862
+ uncompressedSize = getUint32$1(dataDescriptorView, offset + 8);
5863
+ }
5864
+ return { crc32, compressedSize, uncompressedSize };
5865
+ }
5866
+
5557
5867
  function getDiskOffset$1(reader, diskNumber) {
5558
5868
  return reader.getDiskOffset ? reader.getDiskOffset(diskNumber) : 0;
5559
5869
  }
5560
5870
 
5871
+ async function startsWithSplitZipSignature$1(reader) {
5872
+ return await getFirstSignature(reader) == SPLIT_ZIP_FILE_SIGNATURE;
5873
+ }
5874
+
5875
+ async function startsWithSplitZipMarker(reader) {
5876
+ const signature = await getFirstSignature(reader);
5877
+ return signature == SPLIT_ZIP_FILE_SIGNATURE || signature == TEMPORARY_SPLIT_ZIP_FILE_SIGNATURE;
5878
+ }
5879
+
5880
+ async function getFirstSignature(reader) {
5881
+ const signatureArray = await readUint8Array(reader, 0, SPLIT_ZIP_FILE_SIGNATURE_LENGTH);
5882
+ return getUint32$1(getDataView(signatureArray));
5883
+ }
5884
+
5561
5885
  function isStrictnessValue(value) {
5562
5886
  return value === STRICTNESS_STRICT || value === STRICTNESS_BALANCED || value === STRICTNESS_TOLERANT;
5563
5887
  }
5564
5888
 
5565
- function getStrictness(strictness, checkAmbiguity) {
5566
- if (strictness === UNDEFINED_VALUE) {
5567
- return checkAmbiguity ? STRICTNESS_STRICT : STRICTNESS_BALANCED;
5889
+ function getDecodableOutputSize(outputSize, compressedSize, compressed) {
5890
+ return Math.min(outputSize, compressed ? compressedSize * MAX_DEFLATE_EXPANSION_RATIO : compressedSize);
5891
+ }
5892
+
5893
+ function getStrictness(options, inheritedOptions) {
5894
+ return resolveStrictness(options, resolveStrictness(inheritedOptions, STRICTNESS_BALANCED));
5895
+ }
5896
+
5897
+ function resolveStrictness(options, inheritedStrictness) {
5898
+ const strictness = options[OPTION_STRICTNESS];
5899
+ if (strictness !== UNDEFINED_VALUE) {
5900
+ if (!isStrictnessValue(strictness)) {
5901
+ throw new Error(ERR_INVALID_STRICTNESS);
5902
+ }
5903
+ return strictness;
5904
+ }
5905
+ const checkAmbiguity = options[OPTION_CHECK_AMBIGUITY];
5906
+ if (checkAmbiguity === UNDEFINED_VALUE) {
5907
+ return inheritedStrictness;
5568
5908
  }
5569
- if (!isStrictnessValue(strictness)) {
5570
- throw new Error(ERR_INVALID_STRICTNESS);
5909
+ if (checkAmbiguity) {
5910
+ return STRICTNESS_STRICT;
5571
5911
  }
5572
- return strictness;
5912
+ return inheritedStrictness == STRICTNESS_TOLERANT ? STRICTNESS_TOLERANT : STRICTNESS_BALANCED;
5913
+ }
5914
+
5915
+ function getCheckLocalDirectory(checkLocalDirectory, strictness) {
5916
+ if (checkLocalDirectory === UNDEFINED_VALUE) {
5917
+ return strictness != STRICTNESS_TOLERANT;
5918
+ }
5919
+ return Boolean(checkLocalDirectory);
5920
+ }
5921
+
5922
+ function getCheckLocalFilename(checkLocalFilename, strictness) {
5923
+ if (checkLocalFilename === UNDEFINED_VALUE) {
5924
+ return strictness == STRICTNESS_STRICT;
5925
+ }
5926
+ return Boolean(checkLocalFilename);
5573
5927
  }
5574
5928
 
5575
5929
  function getFilenameValidation(filenameValidation, strictness) {
@@ -5598,7 +5952,7 @@ function isUnsafeFilename(filename, filenameValidation) {
5598
5952
 
5599
5953
  function getMaxAppendedDataSize(maxAppendedDataSize, strictness) {
5600
5954
  if (maxAppendedDataSize !== UNDEFINED_VALUE) {
5601
- const size = toNumber$1(maxAppendedDataSize);
5955
+ const size = toNumber(maxAppendedDataSize);
5602
5956
  if (typeof size != NUMBER_TYPE || Number.isNaN(size) || size < 0) {
5603
5957
  throw new Error(ERR_INVALID_MAX_APPENDED_DATA_SIZE);
5604
5958
  }
@@ -5621,7 +5975,7 @@ async function findEndOfCentralDirectory(reader, rejectAmbiguous, maxAppendedDat
5621
5975
  let plausibleEndOfDirectoryInfo;
5622
5976
  let endOfDirectoryReachingEndCount = 0;
5623
5977
  for await (const [anchoredView, anchoredOffset, anchoredArray, indexByte, offset] of scanEndOfCentralDirectory(reader, anchoredLength)) {
5624
- const commentLength = getUint16(anchoredView, indexByte + 20);
5978
+ const commentLength = getUint16$1(anchoredView, indexByte + 20);
5625
5979
  if (offset + END_OF_CENTRAL_DIR_LENGTH + commentLength == size) {
5626
5980
  const reachability = await getCentralDirectoryReachability(reader, anchoredView, anchoredOffset, indexByte, offset, size, remoteProbeBudget);
5627
5981
  if (reachability == CENTRAL_DIRECTORY_REACHABLE) {
@@ -5672,7 +6026,7 @@ async function* scanEndOfCentralDirectory(reader, scanLength) {
5672
6026
  const scanArray = await readUint8Array(reader, scanOffset, scanLength);
5673
6027
  const scanView = getDataView(scanArray);
5674
6028
  for (let indexByte = scanArray.length - END_OF_CENTRAL_DIR_LENGTH; indexByte >= 0; indexByte--) {
5675
- if (getUint32(scanView, indexByte) == END_OF_CENTRAL_DIR_SIGNATURE) {
6029
+ if (getUint32$1(scanView, indexByte) == END_OF_CENTRAL_DIR_SIGNATURE) {
5676
6030
  yield [scanView, scanOffset, scanArray, indexByte, scanOffset + indexByte];
5677
6031
  }
5678
6032
  }
@@ -5683,9 +6037,9 @@ function getEndOfCentralDirectoryInfo(scanArray, indexByte, offset) {
5683
6037
  }
5684
6038
 
5685
6039
  async function getCentralDirectoryReachability(reader, view, anchoredOffset, indexByte, offset, size, remoteProbeBudget) {
5686
- const filesLength = getUint16(view, indexByte + 10);
5687
- const directoryDataLength = getUint32(view, indexByte + 12);
5688
- const directoryDataOffset = getUint32(view, indexByte + 16);
6040
+ const filesLength = getUint16$1(view, indexByte + 10);
6041
+ const directoryDataLength = getUint32$1(view, indexByte + 12);
6042
+ const directoryDataOffset = getUint32$1(view, indexByte + 16);
5689
6043
  if (filesLength == MAX_16_BITS || directoryDataLength == MAX_32_BITS || directoryDataOffset == MAX_32_BITS) {
5690
6044
  const locatorSignature = await readSignature(reader, view, anchoredOffset, offset - ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH, size, remoteProbeBudget);
5691
6045
  return locatorSignature == ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIGNATURE ? CENTRAL_DIRECTORY_REACHABLE : CENTRAL_DIRECTORY_UNREACHABLE;
@@ -5693,7 +6047,7 @@ async function getCentralDirectoryReachability(reader, view, anchoredOffset, ind
5693
6047
  if (!filesLength && !directoryDataLength) {
5694
6048
  return CENTRAL_DIRECTORY_PLAUSIBLE;
5695
6049
  }
5696
- const directoryDiskNumber = getUint16(view, indexByte + 6);
6050
+ const directoryDiskNumber = getUint16$1(view, indexByte + 6);
5697
6051
  for (const centralDirectoryOffset of [offset - directoryDataLength, getDiskOffset$1(reader, directoryDiskNumber) + directoryDataOffset]) {
5698
6052
  if (await readSignature(reader, view, anchoredOffset, centralDirectoryOffset, size, remoteProbeBudget) == CENTRAL_FILE_HEADER_SIGNATURE) {
5699
6053
  return CENTRAL_DIRECTORY_REACHABLE;
@@ -5707,34 +6061,56 @@ async function readSignature(reader, view, anchoredOffset, signatureOffset, size
5707
6061
  return UNDEFINED_VALUE;
5708
6062
  }
5709
6063
  if (signatureOffset >= anchoredOffset) {
5710
- return getUint32(view, signatureOffset - anchoredOffset);
6064
+ return getUint32$1(view, signatureOffset - anchoredOffset);
5711
6065
  }
5712
6066
  if (remoteProbeBudget.count > 0) {
5713
6067
  remoteProbeBudget.count--;
5714
6068
  const signatureArray = await readUint8Array(reader, signatureOffset, 4);
5715
- return getUint32(getDataView(signatureArray), 0);
6069
+ return getUint32$1(getDataView(signatureArray), 0);
5716
6070
  }
5717
6071
  return UNDEFINED_VALUE;
5718
6072
  }
5719
6073
 
5720
- function checkLocalDirectory(zipEntry, localDirectory, rawLocalFilename) {
6074
+ function validateLocalDirectory(zipEntry, localDirectory, rawLocalFilename, checkLocalFilename, warnings) {
5721
6075
  const { rawFilename } = zipEntry;
5722
- if (rawLocalFilename.length != rawFilename.length ||
5723
- rawLocalFilename.some((byteValue, indexByte) => byteValue != rawFilename[indexByte])) {
5724
- throwAmbiguousArchive("mismatched local file header (filename)");
6076
+ const reject = !warnings;
6077
+ const maskedLocalDirectory = zipEntry.decryptedDirectory &&
6078
+ (localDirectory.rawBitFlag & BITFLAG_MASKED_LOCAL_HEADERS) == BITFLAG_MASKED_LOCAL_HEADERS;
6079
+ if (checkLocalFilename && !maskedLocalDirectory &&
6080
+ (rawLocalFilename.length != rawFilename.length ||
6081
+ rawLocalFilename.some((byteValue, indexByte) => byteValue != rawFilename[indexByte]))) {
6082
+ reportAmbiguity(reject, warnings, "mismatched local file header (filename)");
5725
6083
  }
5726
6084
  if ((localDirectory.rawBitFlag & BITFLAG_AMBIGUITY_MASK) != (zipEntry.rawBitFlag & BITFLAG_AMBIGUITY_MASK)) {
5727
- throwAmbiguousArchive("mismatched local file header (general purpose bit flag)");
6085
+ reportAmbiguity(reject, warnings, WARNING_MISMATCHED_LOCAL_FILE_HEADER_BIT_FLAG);
5728
6086
  }
5729
6087
  if (localDirectory.compressionMethod != zipEntry.compressionMethod) {
5730
- throwAmbiguousArchive("mismatched local file header (compression method)");
6088
+ reportAmbiguity(reject, warnings, WARNING_MISMATCHED_LOCAL_FILE_HEADER_COMPRESSION_METHOD);
5731
6089
  }
5732
- if (!localDirectory.bitFlag.dataDescriptor &&
6090
+ if (!localDirectory.bitFlag.dataDescriptor && !maskedLocalDirectory &&
5733
6091
  (localDirectory.crc32 || localDirectory.compressedSize || localDirectory.uncompressedSize) &&
5734
6092
  (localDirectory.crc32 != zipEntry.crc32 ||
5735
6093
  localDirectory.compressedSize != zipEntry.compressedSize ||
5736
6094
  localDirectory.uncompressedSize != zipEntry.uncompressedSize)) {
5737
- throwAmbiguousArchive("mismatched local file header (crc32 or sizes)");
6095
+ reportAmbiguity(reject, warnings, WARNING_MISMATCHED_LOCAL_FILE_HEADER_CRC32_OR_SIZES);
6096
+ }
6097
+ }
6098
+
6099
+ function reportAmbiguity(reject, warnings, reason) {
6100
+ if (reject) {
6101
+ throwAmbiguousArchive(reason);
6102
+ } else {
6103
+ addWarning(warnings, reason);
6104
+ }
6105
+ }
6106
+
6107
+ function addWarning(warnings, reason, filename) {
6108
+ if (!warnings.some(warning => warning.reason == reason)) {
6109
+ const warning = { reason };
6110
+ if (filename !== UNDEFINED_VALUE) {
6111
+ warning.filename = filename;
6112
+ }
6113
+ warnings.push(warning);
5738
6114
  }
5739
6115
  }
5740
6116
 
@@ -5748,13 +6124,15 @@ function getOptionValue$1(zipReader, options, name) {
5748
6124
  return options[name] === UNDEFINED_VALUE ? zipReader.options[name] : options[name];
5749
6125
  }
5750
6126
 
5751
- function toNumber$1(value) {
5752
- return typeof value == STRING_TYPE && value.trim() ? Number(value) : value;
6127
+ function getFunctionOptionValue$1(zipReader, options, name) {
6128
+ return checkFunctionOption(getOptionValue$1(zipReader, options, name));
5753
6129
  }
5754
6130
 
6131
+
5755
6132
  function getDate(timeRaw) {
5756
6133
  const date = (timeRaw & 0xffff0000) >> 16, time = timeRaw & MAX_16_BITS;
5757
- return new Date(1980 + ((date & 0xFE00) >> 9), ((date & 0x01E0) >> 5) - 1, date & 0x001F, (time & 0xF800) >> 11, (time & 0x07E0) >> 5, (time & 0x001F) * 2, 0);
6134
+ const result = new Date(1980 + ((date & 0xFE00) >> 9), ((date & 0x01E0) >> 5) - 1, date & 0x001F, (time & 0xF800) >> 11, (time & 0x07E0) >> 5, (time & 0x001F) * 2, 0);
6135
+ return result < MIN_DATE ? MIN_DATE : result;
5758
6136
  }
5759
6137
 
5760
6138
  function getDateNTFS(timeRaw) {
@@ -5765,16 +6143,20 @@ function getUint8(view, offset) {
5765
6143
  return view.getUint8(offset);
5766
6144
  }
5767
6145
 
5768
- function getUint16(view, offset) {
6146
+ function getUint16$1(view, offset) {
5769
6147
  return view.getUint16(offset, true);
5770
6148
  }
5771
6149
 
5772
- function getUint32(view, offset) {
6150
+ function getUint32$1(view, offset) {
5773
6151
  return view.getUint32(offset, true);
5774
6152
  }
5775
6153
 
5776
6154
  function getBigUint64(view, offset) {
5777
- return Number(view.getBigUint64(offset, true));
6155
+ const value = view.getBigUint64(offset, true);
6156
+ if (value > MAX_SAFE_UINT64) {
6157
+ throw new Error(ERR_UNSUPPORTED_UINT64);
6158
+ }
6159
+ return Number(value);
5778
6160
  }
5779
6161
 
5780
6162
  var zipReader = /*#__PURE__*/Object.freeze({
@@ -5784,6 +6166,7 @@ var zipReader = /*#__PURE__*/Object.freeze({
5784
6166
  ERR_CENTRAL_DIRECTORY_NOT_FOUND: ERR_CENTRAL_DIRECTORY_NOT_FOUND,
5785
6167
  ERR_ENCRYPTED: ERR_ENCRYPTED,
5786
6168
  ERR_ENCRYPTED_CENTRAL_DIRECTORY: ERR_ENCRYPTED_CENTRAL_DIRECTORY,
6169
+ ERR_ENTRY_DATA_OUT_OF_BOUNDS: ERR_ENTRY_DATA_OUT_OF_BOUNDS,
5787
6170
  ERR_EOCDR_LOCATOR_ZIP64_NOT_FOUND: ERR_EOCDR_LOCATOR_ZIP64_NOT_FOUND,
5788
6171
  ERR_EOCDR_NOT_FOUND: ERR_EOCDR_NOT_FOUND,
5789
6172
  ERR_EXTRAFIELD_ZIP64_NOT_FOUND: ERR_EXTRAFIELD_ZIP64_NOT_FOUND,
@@ -5802,9 +6185,25 @@ var zipReader = /*#__PURE__*/Object.freeze({
5802
6185
  ERR_UNSAFE_FILENAME: ERR_UNSAFE_FILENAME,
5803
6186
  ERR_UNSUPPORTED_COMPRESSION: ERR_UNSUPPORTED_COMPRESSION$1,
5804
6187
  ERR_UNSUPPORTED_ENCRYPTION: ERR_UNSUPPORTED_ENCRYPTION,
6188
+ ERR_UNSUPPORTED_UINT64: ERR_UNSUPPORTED_UINT64,
5805
6189
  ERR_WORKER_STARTUP_TIMEOUT: ERR_WORKER_STARTUP_TIMEOUT,
6190
+ WARNING_APPENDED_DATA: WARNING_APPENDED_DATA,
6191
+ WARNING_COMPRESSED_PATCHED_DATA: WARNING_COMPRESSED_PATCHED_DATA,
6192
+ WARNING_DUPLICATE_FILENAME: WARNING_DUPLICATE_FILENAME,
6193
+ WARNING_MALFORMED_EXTRA_FIELD: WARNING_MALFORMED_EXTRA_FIELD,
6194
+ WARNING_MISMATCHED_LOCAL_FILE_HEADER_BIT_FLAG: WARNING_MISMATCHED_LOCAL_FILE_HEADER_BIT_FLAG,
6195
+ WARNING_MISMATCHED_LOCAL_FILE_HEADER_COMPRESSION_METHOD: WARNING_MISMATCHED_LOCAL_FILE_HEADER_COMPRESSION_METHOD,
6196
+ WARNING_MISMATCHED_LOCAL_FILE_HEADER_CRC32_OR_SIZES: WARNING_MISMATCHED_LOCAL_FILE_HEADER_CRC32_OR_SIZES,
6197
+ WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY: WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY,
6198
+ WARNING_PREPENDED_DATA: WARNING_PREPENDED_DATA,
6199
+ WARNING_TRAILING_CENTRAL_DIRECTORY_DATA: WARNING_TRAILING_CENTRAL_DIRECTORY_DATA,
6200
+ WARNING_UNKNOWN_VERSION: WARNING_UNKNOWN_VERSION,
6201
+ WARNING_UNKNOWN_ZIP64_EXTENSIBLE_DATA: WARNING_UNKNOWN_ZIP64_EXTENSIBLE_DATA,
6202
+ WARNING_UNSORTED_CENTRAL_DIRECTORY: WARNING_UNSORTED_CENTRAL_DIRECTORY,
6203
+ WARNING_WRAPPED_ENTRIES_COUNT: WARNING_WRAPPED_ENTRIES_COUNT,
5806
6204
  ZipReader: ZipReader,
5807
- ZipReaderStream: ZipReaderStream
6205
+ ZipReaderStream: ZipReaderStream,
6206
+ isZipFile: isZipFile
5808
6207
  });
5809
6208
 
5810
6209
  /*
@@ -5838,12 +6237,18 @@ var zipReader = /*#__PURE__*/Object.freeze({
5838
6237
 
5839
6238
  const ERR_DUPLICATED_NAME = "File already exists";
5840
6239
  const ERR_INVALID_COMMENT = "Zip file comment exceeds 64KB";
6240
+ const ERR_INVALID_COMMENT_TYPE = "Invalid zip file comment (must be a Uint8Array)";
5841
6241
  const ERR_INVALID_ENTRY_COMMENT = "File entry comment exceeds 64KB";
6242
+ const ERR_INVALID_ENTRY_COMMENT_TYPE = "Invalid file entry comment (must be a string)";
6243
+ const ERR_INVALID_DATE = "Invalid date (must be a valid Date instance)";
5842
6244
  const ERR_INVALID_ENTRY_NAME = "File entry name exceeds 64KB";
5843
6245
  const ERR_INVALID_VERSION = "Version exceeds 65535";
5844
6246
  const ERR_INVALID_ENCRYPTION_STRENGTH = "The strength must equal 1, 2, or 3";
5845
6247
  const ERR_UNSUPPORTED_ENCRYPTION_USDZ = "Encryption is not supported in USDZ files";
5846
- const ERR_INVALID_EXTRAFIELD_TYPE = "Extra field type exceeds 65535";
6248
+ const ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH = "Encryption is not supported when the 'passThrough' option is set";
6249
+ const ERR_INVALID_EXTRAFIELD = "Invalid extra field (must be a Map)";
6250
+ const ERR_INVALID_EXTRAFIELD_TYPE = "Invalid extra field type (must be integer 0..65535)";
6251
+ const ERR_INVALID_EXTRAFIELD_DATA_TYPE = "Invalid extra field data (must be a Uint8Array)";
5847
6252
  const ERR_INVALID_EXTRAFIELD_DATA = "Extra field data exceeds 64KB";
5848
6253
  const ERR_UNSUPPORTED_COMPRESSION = "Compression method not supported";
5849
6254
  const MIN_UNIX_TIME = -2147483648;
@@ -5852,6 +6257,8 @@ const MIN_NTFS_TIME = BigInt(0);
5852
6257
  const MAX_NTFS_TIME = BigInt("0x7fffffffffffffff");
5853
6258
  const ERR_UNSUPPORTED_FORMAT = "Zip64 is not supported (set the 'zip64' option to 'true')";
5854
6259
  const ERR_UNDEFINED_UNCOMPRESSED_SIZE = "Undefined uncompressed size";
6260
+ const ERR_UNDEFINED_COMPRESSION_METHOD = "Undefined compression method";
6261
+ const ERR_UNDETERMINED_SIZE = "Undetermined size";
5855
6262
  const ERR_UNDEFINED_READER = "Undefined reader";
5856
6263
  const ERR_ZIP_NOT_EMPTY = "Zip file not empty";
5857
6264
  const ERR_INVALID_UID = "Invalid uid (must be integer 0..2^32-1)";
@@ -5862,11 +6269,12 @@ const ERR_INVALID_UNIX_ID_SIZE = "uid/gid must be 0..65535 for unixExtraFieldTyp
5862
6269
  const ERR_INVALID_MSDOS_ATTRIBUTES = "Invalid msdosAttributesRaw (must be integer 0..255)";
5863
6270
  const ERR_INVALID_MSDOS_DATA = "Invalid msdosAttributes (must be an object with boolean flags)";
5864
6271
  const ERR_INVALID_LEVEL = "Invalid level (must be integer 0..9)";
5865
- const ERR_INVALID_PASSWORD_TYPE = "Invalid password (password must be a string, rawPassword must be a Uint8Array)";
5866
6272
  const ERR_INVALID_SIGNATURE_DATA = "Signature data exceeds 64KB";
5867
6273
 
5868
6274
  const EXTRAFIELD_DATA_AES = new Uint8Array([0x07, 0x00, 0x02, 0x00, 0x41, 0x45, 0x03, 0x00, 0x00]);
5869
6275
  const EXTRAFIELD_OFFSET_AES_VENDOR_VERSION = 4;
6276
+ const EXTRAFIELD_OFFSET_AES_COMPRESSION_METHOD = 9;
6277
+ const EXTRAFIELD_USDZ_MAX_LENGTH = 67;
5870
6278
  const VENDOR_VERSION_AE_1 = 1;
5871
6279
  const INFOZIP_EXTRA_FIELD_TYPE = "infozip";
5872
6280
  const UNIX_EXTRA_FIELD_TYPE = "unix";
@@ -5887,161 +6295,167 @@ class ZipWriter {
5887
6295
  writer,
5888
6296
  addSplitZipSignature,
5889
6297
  options,
5890
- config: getConfiguration(),
5891
- files: new Map(),
6298
+ fileEntries: new Map(),
5892
6299
  filenames: new Set(),
5893
6300
  offset: options[OPTION_OFFSET] === UNDEFINED_VALUE ? writer.size || writer.writable.size || 0 : options[OPTION_OFFSET],
5894
6301
  initialOffset: options[OPTION_OFFSET] === UNDEFINED_VALUE ? 0 : options[OPTION_OFFSET] - (writer.size || writer.writable.size || 0),
5895
6302
  pendingAddFileCalls: new Set(),
6303
+ pendingErrors: [],
5896
6304
  bufferedWrites: 0,
5897
6305
  lastFileEntry: UNDEFINED_VALUE
5898
6306
  });
5899
6307
  }
5900
6308
 
5901
- async prependZip(reader) {
5902
- if (this.filenames.size) {
5903
- throw new Error(ERR_ZIP_NOT_EMPTY);
5904
- }
5905
- reader = new GenericReader(reader);
5906
- await initStream(reader);
5907
- const { ZipReader } = await Promise.resolve().then(function () { return zipReader; });
5908
- const zipReader$1 = new ZipReader(reader.readable);
5909
- const entries = await zipReader$1.getEntries();
5910
- await zipReader$1.close();
5911
- await initStream(this.writer);
5912
- await reader.readable.pipeTo(this.writer.writable, { preventClose: true, preventAbort: true });
5913
- this.writer.size = this.offset = reader.size;
5914
- this.filenames = new Set(entries.map(entry => entry.filename));
5915
- this.files = new Map(entries.map(entry => {
5916
- const {
5917
- version,
5918
- rawLastModDate,
5919
- lastAccessDate,
5920
- creationDate,
5921
- rawFilename,
5922
- bitFlag,
5923
- encrypted,
5924
- uncompressedSize,
5925
- compressedSize,
5926
- zip64
5927
- } = entry;
5928
- let {
5929
- compressionMethod,
5930
- rawExtraFieldZip64,
5931
- rawExtraFieldAES,
5932
- rawExtraFieldExtendedTimestamp,
5933
- rawExtraFieldNTFS,
5934
- rawExtraFieldUnix,
5935
- rawExtraField,
5936
- } = entry;
5937
- const { level, languageEncodingFlag, dataDescriptor } = bitFlag;
5938
- rawExtraFieldZip64 = rawExtraFieldZip64 || EMPTY_UINT8_ARRAY;
5939
- rawExtraFieldAES = rawExtraFieldAES || EMPTY_UINT8_ARRAY;
5940
- rawExtraFieldExtendedTimestamp = rawExtraFieldExtendedTimestamp || EMPTY_UINT8_ARRAY;
5941
- rawExtraFieldNTFS = rawExtraFieldNTFS || EMPTY_UINT8_ARRAY;
5942
- rawExtraFieldUnix = rawExtraFieldUnix || EMPTY_UINT8_ARRAY;
5943
- rawExtraField = rawExtraField || EMPTY_UINT8_ARRAY;
5944
- if (entry.extraFieldAES) {
5945
- compressionMethod = COMPRESSION_METHOD_AES;
5946
- }
5947
- const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField);
5948
- const zip64UncompressedSize = zip64 && uncompressedSize >= MAX_32_BITS;
5949
- const zip64CompressedSize = zip64 && compressedSize >= MAX_32_BITS;
5950
- const bitFlagValue = (getBitFlag(level, languageEncodingFlag, dataDescriptor, encrypted, compressionMethod) & ~BITFLAG_LEVEL) | (level << 1);
5951
- const {
5952
- headerArray,
5953
- headerView
5954
- } = getHeaderArrayData({
5955
- version,
5956
- bitFlag: bitFlagValue,
5957
- compressionMethod,
5958
- uncompressedSize,
5959
- compressedSize,
5960
- rawLastModDate,
5961
- rawFilename,
5962
- zip64CompressedSize,
5963
- zip64UncompressedSize,
5964
- extraFieldLength
5965
- });
5966
- const { crc32 } = entry;
5967
- if (crc32 !== UNDEFINED_VALUE) {
5968
- setUint32(headerView, HEADER_OFFSET_SIGNATURE, crc32);
5969
- }
5970
- Object.assign(entry, {
5971
- zip64UncompressedSize,
5972
- zip64CompressedSize,
5973
- zip64Offset: zip64 && entry.offset >= MAX_32_BITS,
5974
- diskNumberStart: 0,
5975
- zip64DiskNumberStart: false,
5976
- rawExtraFieldZip64,
5977
- rawExtraFieldAES,
5978
- rawExtraFieldExtendedTimestamp,
5979
- rawExtraFieldNTFS,
5980
- rawExtraFieldUnix,
5981
- rawExtraField,
5982
- extendedTimestamp: rawExtraFieldExtendedTimestamp.length > 0 || rawExtraFieldNTFS.length > 0,
5983
- extraFieldExtendedTimestampFlag: 0x1 + (lastAccessDate ? 0x2 : 0) + (creationDate ? 0x4 : 0),
5984
- headerArray,
5985
- headerView
5986
- });
5987
- return [entry.filename, entry];
5988
- }));
6309
+ prependZip(reader) {
6310
+ return watchPromiseError(this, prependZipEntries(this, reader));
5989
6311
  }
5990
6312
 
5991
- async add(name = "", reader, options = {}) {
6313
+ appendZip(reader) {
6314
+ return watchPromiseError(this, this.appendZipEntries(reader));
6315
+ }
6316
+
6317
+ async appendZipEntries(reader) {
5992
6318
  const zipWriter = this;
5993
- options = Object.assign({}, options);
5994
- const {
5995
- pendingAddFileCalls,
5996
- config
5997
- } = zipWriter;
5998
- if (workers < config.maxWorkers) {
5999
- workers++;
6000
- } else {
6001
- await new Promise(resolve => pendingEntries.push(resolve));
6319
+ const { pendingAddFileCalls, filenames, fileEntries } = zipWriter;
6320
+ while (pendingAddFileCalls.size) {
6321
+ await Promise.allSettled(Array.from(pendingAddFileCalls));
6002
6322
  }
6003
- let promiseAddFile;
6004
- let nameAdded;
6323
+ let resolveAppendZip;
6324
+ const promiseAppendZip = new Promise(resolve => resolveAppendZip = resolve);
6325
+ pendingAddFileCalls.add(promiseAppendZip);
6326
+ const appendedFilenames = [];
6327
+ let releaseLockWriter;
6005
6328
  try {
6006
- name = name.trim();
6007
- if (getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY) && !name.endsWith(DIRECTORY_SIGNATURE)) {
6008
- name += DIRECTORY_SIGNATURE;
6009
- }
6010
- if (zipWriter.filenames.has(name)) {
6011
- throw new Error(ERR_DUPLICATED_NAME);
6012
- }
6013
- zipWriter.filenames.add(name);
6014
- nameAdded = true;
6015
- promiseAddFile = addFile(zipWriter, name, reader, options);
6016
- pendingAddFileCalls.add(promiseAddFile);
6017
- return await promiseAddFile;
6018
- } catch (error) {
6019
- if (nameAdded) {
6020
- zipWriter.filenames.delete(name);
6329
+ reader = new GenericReader(reader);
6330
+ await initStream(reader);
6331
+ if (reader.size === UNDEFINED_VALUE || !reader.readUint8Array) {
6332
+ reader = new BlobReader(await streamToBlob(reader.readable));
6333
+ await initStream(reader);
6334
+ }
6335
+ const { ZipReader } = await Promise.resolve().then(function () { return zipReader; });
6336
+ const zipReader$1 = new ZipReader(reader);
6337
+ const entries = await zipReader$1.getEntries();
6338
+ await zipReader$1.close();
6339
+ await initStream(zipWriter.writer);
6340
+ const { directoryOffset } = zipReader$1;
6341
+ entries.forEach(({ filename }) => {
6342
+ if (filenames.has(filename)) {
6343
+ throw new Error(ERR_DUPLICATED_NAME);
6344
+ }
6345
+ filenames.add(filename);
6346
+ appendedFilenames.push(filename);
6347
+ });
6348
+ zipWriter.writerLocked = true;
6349
+ const { lockWriter } = zipWriter;
6350
+ zipWriter.lockWriter = new Promise(resolve => releaseLockWriter = () => {
6351
+ zipWriter.writerLocked = false;
6352
+ resolve();
6353
+ });
6354
+ await lockWriter;
6355
+ if (zipWriter.addSplitZipSignature) {
6356
+ delete zipWriter.addSplitZipSignature;
6357
+ if (!await startsWithSplitZipSignature(reader)) {
6358
+ await writeData(zipWriter.writer, getSplitZipSignatureArray());
6359
+ zipWriter.offset += SPLIT_ZIP_FILE_SIGNATURE_LENGTH;
6360
+ }
6021
6361
  }
6362
+ const entryPositions = await copyZipData(zipWriter, reader, entries, directoryOffset);
6363
+ entries.forEach(entry => {
6364
+ const {
6365
+ version,
6366
+ rawLastModDate,
6367
+ rawFilename,
6368
+ bitFlag,
6369
+ encrypted,
6370
+ uncompressedSize,
6371
+ compressedSize,
6372
+ extraFieldZip64
6373
+ } = entry;
6374
+ let {
6375
+ compressionMethod,
6376
+ rawExtraField,
6377
+ } = entry;
6378
+ const { level, languageEncodingFlag, dataDescriptor } = bitFlag;
6379
+ rawExtraField = removeExtraFieldZip64(rawExtraField || EMPTY_UINT8_ARRAY);
6380
+ if (entry.extraFieldAES) {
6381
+ compressionMethod = COMPRESSION_METHOD_AES;
6382
+ }
6383
+ const extraFieldLength = getLength(rawExtraField);
6384
+ const zip64UncompressedSize = Boolean(extraFieldZip64) && extraFieldZip64.uncompressedSize !== UNDEFINED_VALUE;
6385
+ const zip64CompressedSize = Boolean(extraFieldZip64) && extraFieldZip64.compressedSize !== UNDEFINED_VALUE;
6386
+ const bitFlagValue = (getBitFlag(level, languageEncodingFlag, dataDescriptor, encrypted, compressionMethod) & ~BITFLAG_LEVEL) | (level << 1);
6387
+ const {
6388
+ headerArray,
6389
+ headerView
6390
+ } = getHeaderArrayData({
6391
+ version,
6392
+ bitFlag: bitFlagValue,
6393
+ compressionMethod,
6394
+ uncompressedSize,
6395
+ compressedSize,
6396
+ rawLastModDate,
6397
+ rawFilename,
6398
+ zip64CompressedSize,
6399
+ zip64UncompressedSize,
6400
+ extraFieldLength
6401
+ });
6402
+ const { crc32 } = entry;
6403
+ if (crc32 !== UNDEFINED_VALUE) {
6404
+ setUint32(headerView, HEADER_OFFSET_SIGNATURE, crc32);
6405
+ }
6406
+ const { offset, diskNumberStart } = entryPositions.get(entry);
6407
+ Object.assign(entry, {
6408
+ zip64UncompressedSize,
6409
+ zip64CompressedSize,
6410
+ offset,
6411
+ diskNumberStart,
6412
+ zip64DiskNumberStart: false,
6413
+ rawExtraFieldZip64: EMPTY_UINT8_ARRAY,
6414
+ rawExtraFieldAES: EMPTY_UINT8_ARRAY,
6415
+ rawExtraFieldExtendedTimestamp: EMPTY_UINT8_ARRAY,
6416
+ rawExtraFieldNTFS: EMPTY_UINT8_ARRAY,
6417
+ rawExtraFieldUnix: EMPTY_UINT8_ARRAY,
6418
+ rawExtraField,
6419
+ rawCentralExtraField: EMPTY_UINT8_ARRAY,
6420
+ extendedTimestamp: false,
6421
+ headerArray,
6422
+ headerView
6423
+ });
6424
+ fileEntries.set(entry.filename, entry);
6425
+ });
6426
+ } catch (error) {
6427
+ appendedFilenames.forEach(filename => filenames.delete(filename));
6022
6428
  throw error;
6023
6429
  } finally {
6024
- pendingAddFileCalls.delete(promiseAddFile);
6025
- const pendingEntry = pendingEntries.shift();
6026
- if (pendingEntry) {
6027
- pendingEntry();
6028
- } else {
6029
- workers--;
6430
+ resolveAppendZip();
6431
+ pendingAddFileCalls.delete(promiseAppendZip);
6432
+ if (releaseLockWriter) {
6433
+ releaseLockWriter();
6030
6434
  }
6031
6435
  }
6032
6436
  }
6033
6437
 
6438
+ add(name = "", reader, options = {}) {
6439
+ const zipWriter = this;
6440
+ const { pendingAddFileCalls } = zipWriter;
6441
+ const promiseAddFile = addFileEntry(zipWriter, name, reader, options);
6442
+ pendingAddFileCalls.add(promiseAddFile);
6443
+ const deletePendingAddFileCall = () => pendingAddFileCalls.delete(promiseAddFile);
6444
+ Promise.prototype.then.call(promiseAddFile, deletePendingAddFileCall, deletePendingAddFileCall);
6445
+ return watchPromiseError(zipWriter, promiseAddFile);
6446
+ }
6447
+
6034
6448
  remove(entry) {
6035
- const { filenames, files } = this;
6449
+ const { filenames, fileEntries } = this;
6036
6450
  // deno-lint-ignore valid-typeof
6037
6451
  if (typeof entry == STRING_TYPE) {
6038
- entry = files.get(entry);
6452
+ entry = fileEntries.get(entry);
6039
6453
  }
6040
6454
  if (entry && entry.filename !== UNDEFINED_VALUE) {
6041
6455
  const { filename } = entry;
6042
- if (filenames.has(filename) && files.has(filename)) {
6456
+ if (filenames.has(filename) && fileEntries.has(filename)) {
6043
6457
  filenames.delete(filename);
6044
- files.delete(filename);
6458
+ fileEntries.delete(filename);
6045
6459
  return true;
6046
6460
  }
6047
6461
  }
@@ -6052,14 +6466,30 @@ class ZipWriter {
6052
6466
  const zipWriter = this;
6053
6467
  const { pendingAddFileCalls, writer } = this;
6054
6468
  const { writable } = writer;
6469
+ if (!(comment instanceof Uint8Array)) {
6470
+ throw new Error(ERR_INVALID_COMMENT_TYPE);
6471
+ }
6055
6472
  if (getLength(comment) > MAX_16_BITS) {
6056
6473
  throw new Error(ERR_INVALID_COMMENT);
6057
6474
  }
6058
6475
  while (pendingAddFileCalls.size) {
6059
6476
  await Promise.allSettled(Array.from(pendingAddFileCalls));
6060
6477
  }
6478
+ await Promise.allSettled(zipWriter.pendingErrors.map(watcher => watcher.recorded));
6479
+ const unobservedWatchers = zipWriter.pendingErrors.filter(watcher => watcher.error && !watcher.observed);
6480
+ if (unobservedWatchers.length) {
6481
+ const unobservedErrors = unobservedWatchers.map(watcher => watcher.error);
6482
+ unobservedWatchers.forEach(watcher => watcher.observed = true);
6483
+ const [error] = unobservedErrors;
6484
+ try {
6485
+ error.entryErrors = unobservedErrors;
6486
+ } catch {
6487
+ // ignored
6488
+ }
6489
+ throw error;
6490
+ }
6061
6491
  await closeFile(zipWriter, comment, options);
6062
- const preventClose = getOptionValue(zipWriter, options, OPTION_PREVENT_CLOSE);
6492
+ const preventClose = !ownsWritable(writer) && getOptionValue(zipWriter, options, OPTION_PREVENT_CLOSE);
6063
6493
  if (!preventClose) {
6064
6494
  await writable.getWriter().close();
6065
6495
  }
@@ -6092,11 +6522,7 @@ class ZipWriterStream {
6092
6522
  try {
6093
6523
  await zipWriter.close();
6094
6524
  } catch (error) {
6095
- try {
6096
- await zipWriter.writer.writable.abort(error);
6097
- } catch {
6098
- // ignored
6099
- }
6525
+ await abortWritable(zipWriter, error);
6100
6526
  }
6101
6527
  }
6102
6528
  }
@@ -6113,8 +6539,89 @@ class ZipWriterStream {
6113
6539
  }
6114
6540
 
6115
6541
  async close(comment = UNDEFINED_VALUE, options = {}) {
6116
- await Promise.all(Array.from(this.pendingAddFileCalls));
6117
- return this.zipWriter.close(comment, options);
6542
+ const { zipWriter } = this;
6543
+ const results = await Promise.allSettled(Array.from(this.pendingAddFileCalls));
6544
+ const entryErrors = results.filter(result => result.status == "rejected").map(result => result.reason);
6545
+ if (entryErrors.length) {
6546
+ const [error] = entryErrors;
6547
+ try {
6548
+ error.entryErrors = entryErrors;
6549
+ } catch {
6550
+ // ignored
6551
+ }
6552
+ await abortWritable(zipWriter, error);
6553
+ throw error;
6554
+ }
6555
+ try {
6556
+ return await zipWriter.close(comment, options);
6557
+ } catch (error) {
6558
+ await abortWritable(zipWriter, error);
6559
+ throw error;
6560
+ }
6561
+ }
6562
+ }
6563
+
6564
+ class WatchedPromise extends Promise {
6565
+
6566
+ then(onFulfilled, onRejected) {
6567
+ const { watcher } = this;
6568
+ if (watcher) {
6569
+ watcher.observed = true;
6570
+ }
6571
+ return super.then(onFulfilled, onRejected);
6572
+ }
6573
+ }
6574
+
6575
+ function watchPromiseError(zipWriter, promise) {
6576
+ const watchedPromise = new WatchedPromise((resolve, reject) => Promise.prototype.then.call(promise, resolve, reject));
6577
+ const watcher = {};
6578
+ watchedPromise.watcher = watcher;
6579
+ watcher.recorded = Promise.prototype.then.call(watchedPromise, UNDEFINED_VALUE, error => watcher.error = error);
6580
+ zipWriter.pendingErrors.push(watcher);
6581
+ return watchedPromise;
6582
+ }
6583
+
6584
+ async function prependZipEntries(zipWriter, reader) {
6585
+ if (zipWriter.filenames.size) {
6586
+ throw new Error(ERR_ZIP_NOT_EMPTY);
6587
+ }
6588
+ await zipWriter.appendZipEntries(reader);
6589
+ }
6590
+
6591
+ async function addFileEntry(zipWriter, name, reader, options) {
6592
+ options = Object.assign({}, options);
6593
+ if (getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY) && !name.endsWith(DIRECTORY_SIGNATURE)) {
6594
+ name += DIRECTORY_SIGNATURE;
6595
+ }
6596
+ if (zipWriter.filenames.has(name)) {
6597
+ throw new Error(ERR_DUPLICATED_NAME);
6598
+ }
6599
+ zipWriter.filenames.add(name);
6600
+ if (workers < getConfiguration().maxWorkers) {
6601
+ workers++;
6602
+ } else {
6603
+ await new Promise(resolve => pendingEntries.push(resolve));
6604
+ }
6605
+ try {
6606
+ return await addFile(zipWriter, name, reader, options);
6607
+ } catch (error) {
6608
+ zipWriter.filenames.delete(name);
6609
+ throw error;
6610
+ } finally {
6611
+ const pendingEntry = pendingEntries.shift();
6612
+ if (pendingEntry) {
6613
+ pendingEntry();
6614
+ } else {
6615
+ workers--;
6616
+ }
6617
+ }
6618
+ }
6619
+
6620
+ async function abortWritable(zipWriter, error) {
6621
+ try {
6622
+ await zipWriter.writer.writable.abort(error);
6623
+ } catch {
6624
+ // ignored
6118
6625
  }
6119
6626
  }
6120
6627
 
@@ -6135,12 +6642,12 @@ async function addFile(zipWriter, name, reader, options) {
6135
6642
  const metadataInfo = resolveMetadata(zipWriter, name, options);
6136
6643
  const { comment } = metadataInfo;
6137
6644
  const extraField = options[PROPERTY_NAME_EXTRA_FIELD];
6138
- zipWriter.files.set(name, UNDEFINED_VALUE);
6645
+ zipWriter.fileEntries.set(name, UNDEFINED_VALUE);
6139
6646
  let fileEntry;
6140
6647
  try {
6141
6648
  const { resolvedOptions } = metadataInfo;
6142
6649
  if (resolvedOptions.level != 0 && resolvedOptions.compressionMethod === UNDEFINED_VALUE &&
6143
- !resolvedOptions.passThrough && !(await supportsDeflate(zipWriter.config))) {
6650
+ !resolvedOptions.passThrough && !(await supportsDeflate(getConfiguration()))) {
6144
6651
  resolvedOptions.level = 0;
6145
6652
  }
6146
6653
  const sizesInfo = await resolveSizes(zipWriter, reader, metadataInfo, options);
@@ -6148,29 +6655,33 @@ async function addFile(zipWriter, name, reader, options) {
6148
6655
  const diskOffset = getDiskOffset(zipWriter.writer);
6149
6656
  const diskNumber = getDiskNumber(zipWriter.writer);
6150
6657
  options = Object.assign({}, options, attributesInfo.resolvedOptions, metadataInfo.resolvedOptions, sizesInfo.resolvedOptions, {
6151
- internalFileAttribute: metadataInfo.resolvedOptions.internalFileAttributes,
6152
- externalFileAttribute: attributesInfo.resolvedOptions.externalFileAttributes,
6153
6658
  signature: options[PROPERTY_NAME_SIGNATURE],
6154
6659
  crc32: options.crc32 === UNDEFINED_VALUE ? options[PROPERTY_NAME_SIGNATURE] : options.crc32,
6155
6660
  offset: zipWriter.offset - diskOffset,
6156
- diskNumberStart: diskNumber
6661
+ diskNumberStart: diskNumber,
6662
+ [OPTION_USDZ]: zipWriter.options[OPTION_USDZ]
6157
6663
  });
6158
6664
  const headerInfo = getHeaderInfo(options);
6159
6665
  const dataDescriptorInfo = getDataDescriptorInfo(options);
6160
6666
  const metadataSize = getLength(headerInfo.localHeaderArray, dataDescriptorInfo.dataDescriptorArray);
6161
6667
  fileEntry = await getFileEntry(zipWriter, name, reader, { headerInfo, dataDescriptorInfo, metadataSize }, options);
6162
6668
  } catch (error) {
6163
- zipWriter.files.delete(name);
6669
+ zipWriter.fileEntries.delete(name);
6164
6670
  throw error;
6165
6671
  }
6166
- Object.assign(fileEntry, { name, comment, extraField });
6672
+ Object.assign(fileEntry, {
6673
+ name,
6674
+ comment,
6675
+ extraField,
6676
+ [PROPERTY_NAME_DEPRECATED_INTERNAL_FILE_ATTRIBUTES]: fileEntry.internalFileAttributes,
6677
+ [PROPERTY_NAME_DEPRECATED_EXTERNAL_FILE_ATTRIBUTES]: fileEntry.externalFileAttributes
6678
+ });
6167
6679
  return new Entry(fileEntry);
6168
6680
  }
6169
6681
 
6170
6682
  function resolveAttributes(zipWriter, name, options) {
6171
- name = name.trim();
6172
6683
  let msDosCompatible = getOptionValue(zipWriter, options, PROPERTY_NAME_MS_DOS_COMPATIBLE);
6173
- let versionMadeBy = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION_MADE_BY, msDosCompatible ? 20 : 768);
6684
+ let versionMadeBy = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION_MADE_BY, msDosCompatible ? VERSION_MADE_BY_MSDOS : VERSION_MADE_BY_UNIX);
6174
6685
  const executable = getOptionValue(zipWriter, options, PROPERTY_NAME_EXECUTABLE);
6175
6686
  const uid = getNumberOptionValue(zipWriter, options, PROPERTY_NAME_UID);
6176
6687
  const gid = getNumberOptionValue(zipWriter, options, PROPERTY_NAME_GID);
@@ -6179,15 +6690,9 @@ function resolveAttributes(zipWriter, name, options) {
6179
6690
  let setuid = getOptionValue(zipWriter, options, PROPERTY_NAME_SETUID);
6180
6691
  let setgid = getOptionValue(zipWriter, options, PROPERTY_NAME_SETGID);
6181
6692
  let sticky = getOptionValue(zipWriter, options, PROPERTY_NAME_STICKY);
6182
- if (uid !== UNDEFINED_VALUE && (!Number.isInteger(uid) || uid < 0 || uid > MAX_32_BITS)) {
6183
- throw new Error(ERR_INVALID_UID);
6184
- }
6185
- if (gid !== UNDEFINED_VALUE && (!Number.isInteger(gid) || gid < 0 || gid > MAX_32_BITS)) {
6186
- throw new Error(ERR_INVALID_GID);
6187
- }
6188
- if (unixMode !== UNDEFINED_VALUE && (!Number.isInteger(unixMode) || unixMode < 0 || unixMode > MAX_16_BITS)) {
6189
- throw new Error(ERR_INVALID_UNIX_MODE);
6190
- }
6693
+ checkIntegerOption(uid, MAX_32_BITS, ERR_INVALID_UID);
6694
+ checkIntegerOption(gid, MAX_32_BITS, ERR_INVALID_GID);
6695
+ checkIntegerOption(unixMode, MAX_16_BITS, ERR_INVALID_UNIX_MODE);
6191
6696
  if (unixExtraFieldType !== UNDEFINED_VALUE && unixExtraFieldType !== INFOZIP_EXTRA_FIELD_TYPE && unixExtraFieldType !== UNIX_EXTRA_FIELD_TYPE) {
6192
6697
  throw new Error(ERR_INVALID_UNIX_EXTRA_FIELD_TYPE);
6193
6698
  }
@@ -6198,27 +6703,25 @@ function resolveAttributes(zipWriter, name, options) {
6198
6703
  if (unixExtraFieldType === UNDEFINED_VALUE && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
6199
6704
  unixExtraFieldType = INFOZIP_EXTRA_FIELD_TYPE;
6200
6705
  }
6201
- let msdosAttributesRaw = getOptionValue(zipWriter, options, PROPERTY_NAME_MSDOS_ATTRIBUTES_RAW);
6706
+ let msdosAttributesRaw = getNumberOptionValue(zipWriter, options, PROPERTY_NAME_MSDOS_ATTRIBUTES_RAW);
6202
6707
  let msdosAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_MSDOS_ATTRIBUTES);
6203
- const hasUnixMetadata = uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE || unixMode !== UNDEFINED_VALUE || unixExtraFieldType;
6708
+ const hasUnixMetadata = uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE || unixMode !== UNDEFINED_VALUE || unixExtraFieldType || executable;
6204
6709
  const hasMsDosProvided = msdosAttributesRaw !== UNDEFINED_VALUE || msdosAttributes !== UNDEFINED_VALUE;
6205
6710
  if (hasUnixMetadata) {
6206
6711
  msDosCompatible = false;
6207
- versionMadeBy = (versionMadeBy & MAX_16_BITS) | (3 << 8);
6712
+ versionMadeBy = (versionMadeBy & MAX_8_BITS) | VERSION_MADE_BY_UNIX;
6208
6713
  } else if (hasMsDosProvided) {
6209
6714
  msDosCompatible = true;
6210
6715
  versionMadeBy = (versionMadeBy & MAX_8_BITS);
6211
6716
  }
6212
- if (msdosAttributesRaw !== UNDEFINED_VALUE && (msdosAttributesRaw < 0 || msdosAttributesRaw > MAX_8_BITS)) {
6213
- throw new Error(ERR_INVALID_MSDOS_ATTRIBUTES);
6214
- }
6215
- if (msdosAttributes && typeof msdosAttributes !== OBJECT_TYPE) {
6717
+ checkIntegerOption(msdosAttributesRaw, MAX_8_BITS, ERR_INVALID_MSDOS_ATTRIBUTES);
6718
+ if (msdosAttributes && (typeof msdosAttributes !== OBJECT_TYPE || Array.isArray(msdosAttributes))) {
6216
6719
  throw new Error(ERR_INVALID_MSDOS_DATA);
6217
6720
  }
6218
6721
  if (versionMadeBy > MAX_16_BITS) {
6219
6722
  throw new Error(ERR_INVALID_VERSION);
6220
6723
  }
6221
- let externalFileAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTES);
6724
+ let externalFileAttributes = getAliasedOptionValue(zipWriter, options, PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTES, PROPERTY_NAME_DEPRECATED_EXTERNAL_FILE_ATTRIBUTES);
6222
6725
  const externalFileAttributesProvided = externalFileAttributes !== UNDEFINED_VALUE;
6223
6726
  if (!externalFileAttributesProvided) {
6224
6727
  externalFileAttributes = 0;
@@ -6244,11 +6747,10 @@ function resolveAttributes(zipWriter, name, options) {
6244
6747
  externalFileAttributes = FILE_ATTR_UNIX_DEFAULT_MASK << 16;
6245
6748
  }
6246
6749
  }
6247
- let unixExternalUpper;
6248
6750
  if (!msDosCompatible) {
6249
6751
  const unixModeProvided = unixMode !== UNDEFINED_VALUE || Boolean(setuid || setgid || sticky);
6250
- unixExternalUpper = (externalFileAttributes >> 16) & MAX_16_BITS;
6251
- unixMode = unixMode === UNDEFINED_VALUE ? unixExternalUpper : (unixMode & MAX_16_BITS);
6752
+ const defaultUnixMode = (externalFileAttributes >> 16) & MAX_16_BITS;
6753
+ unixMode = unixMode === UNDEFINED_VALUE ? defaultUnixMode : (unixMode & MAX_16_BITS);
6252
6754
  if (setuid) {
6253
6755
  unixMode |= FILE_ATTR_UNIX_SETUID_MASK;
6254
6756
  } else {
@@ -6266,7 +6768,9 @@ function resolveAttributes(zipWriter, name, options) {
6266
6768
  }
6267
6769
  if (!externalFileAttributesProvided || unixModeProvided) {
6268
6770
  if (directory) {
6269
- unixMode |= FILE_ATTR_UNIX_TYPE_DIR;
6771
+ unixMode = (unixMode & ~FILE_ATTR_UNIX_TYPE_MASK) | FILE_ATTR_UNIX_TYPE_DIR;
6772
+ } else if (!(unixMode & FILE_ATTR_UNIX_TYPE_MASK)) {
6773
+ unixMode |= FILE_ATTR_UNIX_TYPE_FILE;
6270
6774
  }
6271
6775
  externalFileAttributes = ((unixMode & MAX_16_BITS) << 16) | (externalFileAttributes & MAX_16_BITS);
6272
6776
  }
@@ -6275,17 +6779,20 @@ function resolveAttributes(zipWriter, name, options) {
6275
6779
  if (hasMsDosProvided) {
6276
6780
  externalFileAttributes = (externalFileAttributes & MAX_32_BITS) | (msdosAttributesRaw & MAX_8_BITS);
6277
6781
  }
6782
+ const unixExternalUpper = (externalFileAttributes >> 16) & MAX_16_BITS;
6783
+ const symlink = unixMode !== UNDEFINED_VALUE && ((unixMode & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_SYMLINK);
6278
6784
  return {
6279
6785
  name,
6280
6786
  resolvedOptions: {
6281
6787
  versionMadeBy,
6282
- msDosCompatible,
6788
+ msDosCompatible: Boolean(msDosCompatible),
6283
6789
  externalFileAttributes,
6284
6790
  unixExternalUpper,
6285
6791
  uid,
6286
6792
  gid,
6287
6793
  unixMode,
6288
6794
  unixExtraFieldType,
6795
+ symlink,
6289
6796
  setuid,
6290
6797
  setgid,
6291
6798
  sticky,
@@ -6296,7 +6803,7 @@ function resolveAttributes(zipWriter, name, options) {
6296
6803
  }
6297
6804
 
6298
6805
  function resolveMetadata(zipWriter, name, options) {
6299
- const encode = getOptionValue(zipWriter, options, OPTION_ENCODE_TEXT, encodeText);
6806
+ const encode = getFunctionOptionValue(zipWriter, options, OPTION_ENCODE_TEXT) || encodeText;
6300
6807
  let rawFilename = encode(name, TEXT_TYPE_FILENAME);
6301
6808
  if (rawFilename === UNDEFINED_VALUE) {
6302
6809
  rawFilename = encodeText(name);
@@ -6305,6 +6812,10 @@ function resolveMetadata(zipWriter, name, options) {
6305
6812
  throw new Error(ERR_INVALID_ENTRY_NAME);
6306
6813
  }
6307
6814
  const comment = options[PROPERTY_NAME_COMMENT] || "";
6815
+ // deno-lint-ignore valid-typeof
6816
+ if (typeof comment != STRING_TYPE) {
6817
+ throw new Error(ERR_INVALID_ENTRY_COMMENT_TYPE);
6818
+ }
6308
6819
  let rawComment = encode(comment, TEXT_TYPE_COMMENT);
6309
6820
  if (rawComment === UNDEFINED_VALUE) {
6310
6821
  rawComment = encodeText(comment);
@@ -6312,23 +6823,19 @@ function resolveMetadata(zipWriter, name, options) {
6312
6823
  if (getLength(rawComment) > MAX_16_BITS) {
6313
6824
  throw new Error(ERR_INVALID_ENTRY_COMMENT);
6314
6825
  }
6315
- const version = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION, VERSION_DEFLATE);
6316
- if (version > MAX_16_BITS) {
6826
+ const version = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION);
6827
+ if (version !== UNDEFINED_VALUE && version > MAX_16_BITS) {
6317
6828
  throw new Error(ERR_INVALID_VERSION);
6318
6829
  }
6319
- const lastModDate = getOptionValue(zipWriter, options, PROPERTY_NAME_LAST_MODIFICATION_DATE, new Date());
6320
- const lastAccessDate = getOptionValue(zipWriter, options, PROPERTY_NAME_LAST_ACCESS_DATE);
6321
- const creationDate = getOptionValue(zipWriter, options, PROPERTY_NAME_CREATION_DATE);
6322
- const internalFileAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES, 0);
6830
+ const lastModDate = getDateOptionValue(zipWriter, options, PROPERTY_NAME_LAST_MODIFICATION_DATE, new Date());
6831
+ const rawLastModDate = getOptionValue(zipWriter, options, PROPERTY_NAME_RAW_LAST_MODIFICATION_DATE);
6832
+ const lastAccessDate = getDateOptionValue(zipWriter, options, PROPERTY_NAME_LAST_ACCESS_DATE);
6833
+ const creationDate = getDateOptionValue(zipWriter, options, PROPERTY_NAME_CREATION_DATE);
6834
+ const internalFileAttributes = getAliasedOptionValue(zipWriter, options, PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES, PROPERTY_NAME_DEPRECATED_INTERNAL_FILE_ATTRIBUTES, 0);
6323
6835
  const passThrough = getOptionValue(zipWriter, options, OPTION_PASS_THROUGH);
6324
- let password, rawPassword;
6325
- if (!passThrough) {
6326
- password = getOptionValue(zipWriter, options, OPTION_PASSWORD);
6327
- rawPassword = getOptionValue(zipWriter, options, OPTION_RAW_PASSWORD);
6328
- if ((password && typeof password != STRING_TYPE) || (rawPassword && !(rawPassword instanceof Uint8Array))) {
6329
- throw new Error(ERR_INVALID_PASSWORD_TYPE);
6330
- }
6331
- }
6836
+ const password = getOptionValue(zipWriter, options, OPTION_PASSWORD);
6837
+ const rawPassword = getOptionValue(zipWriter, options, OPTION_RAW_PASSWORD);
6838
+ checkPasswordOption(password, rawPassword);
6332
6839
  const encryptionStrength = getNumberOptionValue(zipWriter, options, OPTION_ENCRYPTION_STRENGTH, 3);
6333
6840
  const zipCrypto = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIPCRYPTO);
6334
6841
  const extendedTimestamp = getOptionValue(zipWriter, options, OPTION_EXTENDED_TIMESTAMP, true);
@@ -6337,9 +6844,9 @@ function resolveMetadata(zipWriter, name, options) {
6337
6844
  const useWebWorkers = getOptionValue(zipWriter, options, OPTION_USE_WEB_WORKERS);
6338
6845
  const transferStreams = getOptionValue(zipWriter, options, OPTION_TRANSFER_STREAMS);
6339
6846
  const bufferedWrite = getOptionValue(zipWriter, options, OPTION_BUFFERED_WRITE);
6340
- const createTempStream = getOptionValue(zipWriter, options, OPTION_CREATE_TEMP_STREAM);
6847
+ const createTempStream = getFunctionOptionValue(zipWriter, options, OPTION_CREATE_TEMP_STREAM);
6341
6848
  const dataDescriptorSignature = getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR_SIGNATURE, true);
6342
- const signal = getOptionValue(zipWriter, options, OPTION_SIGNAL);
6849
+ const signal = checkSignalOption(getOptionValue(zipWriter, options, OPTION_SIGNAL));
6343
6850
  const useUnicodeFileNames = getOptionValue(zipWriter, options, OPTION_USE_UNICODE_FILE_NAMES, true);
6344
6851
  const compressionMethod = getOptionValue(zipWriter, options, PROPERTY_NAME_COMPRESSION_METHOD);
6345
6852
  const registeredCodec = passThrough || compressionMethod === UNDEFINED_VALUE ? UNDEFINED_VALUE : getRegisteredCodec(compressionMethod);
@@ -6348,9 +6855,7 @@ function resolveMetadata(zipWriter, name, options) {
6348
6855
  throw new Error(ERR_UNSUPPORTED_COMPRESSION);
6349
6856
  }
6350
6857
  let level = getNumberOptionValue(zipWriter, options, OPTION_LEVEL);
6351
- if (level !== UNDEFINED_VALUE && (!Number.isInteger(level) || level < 0 || level > MAX_LEVEL)) {
6352
- throw new Error(ERR_INVALID_LEVEL);
6353
- }
6858
+ checkIntegerOption(level, MAX_LEVEL, ERR_INVALID_LEVEL);
6354
6859
  if (zipWriter.options[OPTION_USDZ]) {
6355
6860
  if (password !== UNDEFINED_VALUE || rawPassword !== UNDEFINED_VALUE) {
6356
6861
  throw new Error(ERR_UNSUPPORTED_ENCRYPTION_USDZ);
@@ -6359,12 +6864,15 @@ function resolveMetadata(zipWriter, name, options) {
6359
6864
  level = 0;
6360
6865
  }
6361
6866
  }
6867
+ if (passThrough) {
6868
+ level = UNDEFINED_VALUE;
6869
+ }
6362
6870
  let useCompressionStream = getOptionValue(zipWriter, options, OPTION_USE_COMPRESSION_STREAM);
6363
6871
  let dataDescriptor = getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR);
6364
6872
  if (bufferedWrite && dataDescriptor === UNDEFINED_VALUE) {
6365
6873
  dataDescriptor = false;
6366
6874
  }
6367
- if (dataDescriptor === UNDEFINED_VALUE || zipCrypto) {
6875
+ if (dataDescriptor === UNDEFINED_VALUE || (zipCrypto && !passThrough)) {
6368
6876
  dataDescriptor = true;
6369
6877
  }
6370
6878
  if (level !== UNDEFINED_VALUE && level != 6) {
@@ -6376,6 +6884,7 @@ function resolveMetadata(zipWriter, name, options) {
6376
6884
  }
6377
6885
  const rawExtraField = serializeExtraField(options[PROPERTY_NAME_EXTRA_FIELD]);
6378
6886
  const rawLocalExtraField = serializeExtraField(options[OPTION_LOCAL_EXTRA_FIELD]);
6887
+ const rawCentralExtraField = serializeExtraField(options[OPTION_CENTRAL_EXTRA_FIELD]);
6379
6888
  return {
6380
6889
  comment,
6381
6890
  resolvedOptions: {
@@ -6383,6 +6892,7 @@ function resolveMetadata(zipWriter, name, options) {
6383
6892
  rawComment,
6384
6893
  version,
6385
6894
  lastModDate,
6895
+ rawLastModDate,
6386
6896
  lastAccessDate,
6387
6897
  creationDate,
6388
6898
  internalFileAttributes,
@@ -6410,7 +6920,8 @@ function resolveMetadata(zipWriter, name, options) {
6410
6920
  dataDescriptor,
6411
6921
  zip64,
6412
6922
  rawExtraField,
6413
- rawLocalExtraField
6923
+ rawLocalExtraField,
6924
+ rawCentralExtraField
6414
6925
  }
6415
6926
  };
6416
6927
  }
@@ -6419,18 +6930,24 @@ function serializeExtraField(extraField) {
6419
6930
  if (!extraField) {
6420
6931
  return EMPTY_UINT8_ARRAY;
6421
6932
  }
6933
+ if (!(extraField instanceof Map)) {
6934
+ throw new Error(ERR_INVALID_EXTRAFIELD);
6935
+ }
6422
6936
  let extraFieldSize = 0;
6423
6937
  let offset = 0;
6424
- extraField.forEach(data => extraFieldSize += 4 + getLength(data));
6425
- const rawExtraField = new Uint8Array(extraFieldSize);
6426
- const rawExtraFieldView = getDataView(rawExtraField);
6427
6938
  extraField.forEach((data, type) => {
6428
- if (type > MAX_16_BITS) {
6429
- throw new Error(ERR_INVALID_EXTRAFIELD_TYPE);
6939
+ checkInteger(type, MAX_16_BITS, ERR_INVALID_EXTRAFIELD_TYPE);
6940
+ if (!(data instanceof Uint8Array)) {
6941
+ throw new Error(ERR_INVALID_EXTRAFIELD_DATA_TYPE);
6430
6942
  }
6431
6943
  if (getLength(data) > MAX_16_BITS) {
6432
6944
  throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
6433
6945
  }
6946
+ extraFieldSize += 4 + getLength(data);
6947
+ });
6948
+ const rawExtraField = new Uint8Array(extraFieldSize);
6949
+ const rawExtraFieldView = getDataView(rawExtraField);
6950
+ extraField.forEach((data, type) => {
6434
6951
  setUint16(rawExtraFieldView, offset, type);
6435
6952
  setUint16(rawExtraFieldView, offset + 2, getLength(data));
6436
6953
  arraySet(rawExtraField, data, offset + 4);
@@ -6440,46 +6957,64 @@ function serializeExtraField(extraField) {
6440
6957
  }
6441
6958
 
6442
6959
  async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, options) {
6960
+ if (metadata.passThrough && !reader && !getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY)) {
6961
+ throw new Error(ERR_UNDEFINED_READER);
6962
+ }
6963
+ let contentSize;
6964
+ if (reader) {
6965
+ reader = new GenericReader(reader);
6966
+ await initStream(reader);
6967
+ ({ size: contentSize } = reader);
6968
+ }
6969
+ return Object.assign({ reader }, resolveEntrySizes(zipWriter, Boolean(reader), contentSize, metadata, options));
6970
+ }
6971
+
6972
+ function resolveEntrySizes(zipWriter, hasContent, contentSize, metadata, options) {
6443
6973
  const { passThrough, zipCrypto, password, rawPassword, encryptionStrength } = metadata;
6444
6974
  let { dataDescriptor, zip64, level, compressionMethod } = metadata;
6445
6975
  let maximumCompressedSize = 0;
6446
6976
  let uncompressedSize = 0;
6447
- if (passThrough) {
6448
- if (!reader) {
6449
- throw new Error(ERR_UNDEFINED_READER);
6450
- }
6977
+ if (passThrough && hasContent) {
6451
6978
  uncompressedSize = options[PROPERTY_NAME_UNCOMPRESSED_SIZE];
6452
6979
  if (uncompressedSize === UNDEFINED_VALUE) {
6453
6980
  throw new Error(ERR_UNDEFINED_UNCOMPRESSED_SIZE);
6454
6981
  }
6982
+ if (compressionMethod === UNDEFINED_VALUE) {
6983
+ throw new Error(ERR_UNDEFINED_COMPRESSION_METHOD);
6984
+ }
6455
6985
  }
6456
6986
  const zip64Enabled = zip64 === true;
6457
6987
  const encrypted = getOptionValue(zipWriter, options, PROPERTY_NAME_ENCRYPTED);
6458
- const encryptedEntry = Boolean(reader) && (Boolean((password && getLength(password)) || (rawPassword && getLength(rawPassword))) || (passThrough && encrypted));
6459
- if (!reader) {
6988
+ if (hasContent && passThrough && !encrypted && getLength(password, rawPassword)) {
6989
+ throw new Error(ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH);
6990
+ }
6991
+ const encryptedEntry = hasContent && (Boolean((password && getLength(password)) || (rawPassword && getLength(rawPassword))) || (passThrough && encrypted));
6992
+ if (!hasContent) {
6460
6993
  level = 0;
6461
6994
  compressionMethod = COMPRESSION_METHOD_STORE;
6462
6995
  }
6463
6996
  const encryptionOverhead = encryptedEntry ? (zipCrypto ? 12 : 16 + encryptionStrength * 4) : 0;
6464
- if (reader) {
6465
- reader = new GenericReader(reader);
6466
- await initStream(reader);
6997
+ if (hasContent) {
6467
6998
  if (!passThrough) {
6468
- if (reader.size === UNDEFINED_VALUE) {
6999
+ if (contentSize === UNDEFINED_VALUE) {
6469
7000
  dataDescriptor = true;
6470
7001
  if (zip64 || zip64 === UNDEFINED_VALUE) {
6471
7002
  zip64 = true;
6472
7003
  uncompressedSize = maximumCompressedSize = MAX_32_BITS + 1;
6473
7004
  }
6474
7005
  } else {
6475
- options.uncompressedSize = uncompressedSize = reader.size;
6476
- maximumCompressedSize = getMaximumCompressedSize(uncompressedSize) + encryptionOverhead;
7006
+ options.uncompressedSize = uncompressedSize = contentSize;
7007
+ maximumCompressedSize = (isCompressed(compressionMethod, level) ? getMaximumCompressedSize(uncompressedSize) : uncompressedSize) + encryptionOverhead;
6477
7008
  }
6478
7009
  } else {
6479
7010
  options.uncompressedSize = uncompressedSize;
6480
- maximumCompressedSize = getMaximumCompressedSize(uncompressedSize) + encryptionOverhead;
7011
+ maximumCompressedSize = contentSize === UNDEFINED_VALUE ? getMaximumCompressedSize(uncompressedSize) + encryptionOverhead : contentSize;
6481
7012
  }
6482
7013
  }
7014
+ const emptyEntry = !encryptedEntry && (!hasContent || (contentSize === 0 && !passThrough)) && !isCompressed(compressionMethod, level);
7015
+ if (emptyEntry && !zipCrypto && getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR) === UNDEFINED_VALUE) {
7016
+ dataDescriptor = false;
7017
+ }
6483
7018
  const zip64UncompressedSize = zip64Enabled || uncompressedSize >= MAX_32_BITS;
6484
7019
  const zip64CompressedSize = zip64Enabled || maximumCompressedSize >= MAX_32_BITS;
6485
7020
  if (zip64UncompressedSize || zip64CompressedSize) {
@@ -6491,9 +7026,10 @@ async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, op
6491
7026
  }
6492
7027
  zip64 = zip64 || false;
6493
7028
  return {
6494
- reader,
7029
+ maximumCompressedSize,
6495
7030
  resolvedOptions: {
6496
7031
  dataDescriptor,
7032
+ emptyEntry,
6497
7033
  zip64,
6498
7034
  zip64UncompressedSize,
6499
7035
  zip64CompressedSize,
@@ -6507,12 +7043,13 @@ async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, op
6507
7043
 
6508
7044
  async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
6509
7045
  const {
6510
- files,
7046
+ fileEntries,
6511
7047
  writer
6512
7048
  } = zipWriter;
6513
7049
  const {
6514
7050
  keepOrder,
6515
7051
  dataDescriptor,
7052
+ emptyEntry,
6516
7053
  signal
6517
7054
  } = options;
6518
7055
  const {
@@ -6529,15 +7066,15 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
6529
7066
  let writerSizeBeforeEntry;
6530
7067
  let flushedBufferedSize = 0;
6531
7068
  let fileWriter;
6532
- files.set(name, fileEntry);
7069
+ fileEntries.set(name, fileEntry);
6533
7070
  zipWriter.lastFileEntry = fileEntry;
6534
7071
  try {
6535
7072
  let lockPreviousFileEntry;
6536
7073
  if (keepOrder) {
6537
- lockPreviousFileEntry = previousFileEntry && previousFileEntry.lock;
7074
+ lockPreviousFileEntry = previousFileEntry && previousFileEntry.lockFileEntry;
6538
7075
  requestLockCurrentFileEntry();
6539
7076
  }
6540
- if (options.bufferedWrite || !keepOrder || zipWriter.writerLocked || zipWriter.bufferedWrites || !dataDescriptor) {
7077
+ if (options.bufferedWrite || !keepOrder || zipWriter.writerLocked || zipWriter.bufferedWrites || (!dataDescriptor && !emptyEntry)) {
6541
7078
  bufferedWrite = true;
6542
7079
  zipWriter.bufferedWrites++;
6543
7080
  if (options.createTempStream) {
@@ -6553,13 +7090,8 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
6553
7090
  }
6554
7091
  await initStream(fileWriter);
6555
7092
  const diskOffset = getDiskOffset(writer);
6556
- if (zipWriter.addSplitZipSignature) {
6557
- delete zipWriter.addSplitZipSignature;
6558
- const signatureArray = new Uint8Array(4);
6559
- const signatureArrayView = getDataView(signatureArray);
6560
- setUint32(signatureArrayView, 0, SPLIT_ZIP_FILE_SIGNATURE);
6561
- await writeData(writer, signatureArray);
6562
- zipWriter.offset += 4;
7093
+ if (zipWriter.addSplitZipSignature && !bufferedWrite) {
7094
+ await writeSplitZipSignature(zipWriter, writer);
6563
7095
  }
6564
7096
  if (usdz && !bufferedWrite) {
6565
7097
  appendExtraFieldUSDZ(entryInfo, zipWriter.offset - diskOffset);
@@ -6577,15 +7109,18 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
6577
7109
  writerSizeBeforeEntry = writer.size;
6578
7110
  await writeData(fileWriter, localHeaderArray);
6579
7111
  }
6580
- fileEntry = await createFileEntry(reader, fileWriter, fileEntry, entryInfo, zipWriter.config, options);
7112
+ fileEntry = await createFileEntry(reader, fileWriter, fileEntry, entryInfo, getConfiguration(), options);
6581
7113
  if (!bufferedWrite) {
6582
7114
  writingEntryData = false;
6583
7115
  }
6584
- files.set(name, fileEntry);
7116
+ fileEntries.set(name, fileEntry);
6585
7117
  fileEntry.filename = name;
6586
7118
  if (bufferedWrite) {
6587
7119
  await Promise.all([fileWriter.writable.getWriter().close(), lockPreviousFileEntry]);
6588
7120
  await requestLockWriter();
7121
+ if (zipWriter.addSplitZipSignature) {
7122
+ await writeSplitZipSignature(zipWriter, writer);
7123
+ }
6589
7124
  writingBufferedEntryData = true;
6590
7125
  writerSizeBeforeEntry = writer.size;
6591
7126
  await skipDiskIfNeeded();
@@ -6622,7 +7157,7 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
6622
7157
  zipWriter.offset += flushedBufferedSize;
6623
7158
  }
6624
7159
  }
6625
- files.delete(name);
7160
+ fileEntries.delete(name);
6626
7161
  throw error;
6627
7162
  } finally {
6628
7163
  if (bufferedWrite) {
@@ -6644,7 +7179,7 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
6644
7179
  }
6645
7180
 
6646
7181
  function requestLockCurrentFileEntry() {
6647
- fileEntry.lock = new Promise(resolve => releaseLockCurrentFileEntry = resolve);
7182
+ fileEntry.lockFileEntry = new Promise(resolve => releaseLockCurrentFileEntry = resolve);
6648
7183
  }
6649
7184
 
6650
7185
  async function requestLockWriter() {
@@ -6664,7 +7199,7 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
6664
7199
  }
6665
7200
  }
6666
7201
 
6667
- async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryInfo, config, options) {
7202
+ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry }, entryInfo, config, options) {
6668
7203
  const {
6669
7204
  headerInfo,
6670
7205
  dataDescriptorInfo,
@@ -6705,6 +7240,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
6705
7240
  versionMadeBy,
6706
7241
  rawComment,
6707
7242
  rawExtraField,
7243
+ rawCentralExtraField,
6708
7244
  useWebWorkers,
6709
7245
  transferStreams,
6710
7246
  onstart,
@@ -6719,6 +7255,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
6719
7255
  uid,
6720
7256
  gid,
6721
7257
  unixMode,
7258
+ symlink,
6722
7259
  setuid,
6723
7260
  setgid,
6724
7261
  sticky,
@@ -6731,7 +7268,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
6731
7268
  codecURI
6732
7269
  } = options;
6733
7270
  const fileEntry = {
6734
- lock,
7271
+ lockFileEntry,
6735
7272
  versionMadeBy,
6736
7273
  zip64,
6737
7274
  directory: Boolean(directory),
@@ -6747,6 +7284,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
6747
7284
  rawExtraFieldUnix,
6748
7285
  rawExtraFieldAES,
6749
7286
  rawExtraField,
7287
+ rawCentralExtraField,
6750
7288
  extendedTimestamp,
6751
7289
  msDosCompatible,
6752
7290
  internalFileAttributes,
@@ -6755,6 +7293,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
6755
7293
  uid,
6756
7294
  gid,
6757
7295
  unixMode,
7296
+ symlink: Boolean(symlink),
6758
7297
  setuid,
6759
7298
  setgid,
6760
7299
  sticky,
@@ -6772,7 +7311,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
6772
7311
  }
6773
7312
  const { writable } = writer;
6774
7313
  if (reader) {
6775
- const readable = toCompatibleReadable(reader.createReadable ? reader.createReadable() : reader.readable);
7314
+ const readable = toCompatibleReadable(createReadable(reader));
6776
7315
  const size = reader.size;
6777
7316
  const workerOptions = {
6778
7317
  options: {
@@ -6835,8 +7374,8 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
6835
7374
  rawLastModDate,
6836
7375
  creationDate,
6837
7376
  lastAccessDate,
6838
- encrypted,
6839
- zipCrypto,
7377
+ encrypted: Boolean(encrypted),
7378
+ zipCrypto: Boolean(zipCrypto),
6840
7379
  size: metadataSize + compressedSize,
6841
7380
  compressionMethod,
6842
7381
  version,
@@ -6855,6 +7394,7 @@ function getHeaderInfo(options) {
6855
7394
  const {
6856
7395
  rawFilename,
6857
7396
  lastModDate,
7397
+ rawLastModDate: rawLastModDateOption,
6858
7398
  lastAccessDate,
6859
7399
  creationDate,
6860
7400
  level,
@@ -6876,9 +7416,7 @@ function getHeaderInfo(options) {
6876
7416
  crc32
6877
7417
  } = options;
6878
7418
  let { version, compressionMethod } = options;
6879
- const compressed = !directory && (compressionMethod === UNDEFINED_VALUE
6880
- ? (level === UNDEFINED_VALUE || level > 0)
6881
- : compressionMethod !== COMPRESSION_METHOD_STORE);
7419
+ const compressed = !directory && isCompressed(compressionMethod, level);
6882
7420
  let rawLocalExtraFieldZip64;
6883
7421
  const uncompressedFile = passThrough || !compressed;
6884
7422
  const zip64ExtraFieldComplete = zip64 && (options.bufferedWrite || !dataDescriptor || ((!zip64UncompressedSize && !zip64CompressedSize) || uncompressedFile));
@@ -6886,14 +7424,14 @@ function getHeaderInfo(options) {
6886
7424
  if (zip64 && (zip64UncompressedSize || zip64CompressedSize)) {
6887
7425
  const length = 4 + 16;
6888
7426
  const extraFieldZip64 = createRecordWriter(length);
6889
- extraFieldZip64.uint16(EXTRAFIELD_TYPE_ZIP64);
6890
- extraFieldZip64.uint16(length - 4);
7427
+ extraFieldZip64.writeUint16(EXTRAFIELD_TYPE_ZIP64);
7428
+ extraFieldZip64.writeUint16(length - 4);
6891
7429
  rawLocalExtraFieldZip64 = extraFieldZip64.array;
6892
7430
  if (zip64ExtraFieldComplete) {
6893
- extraFieldZip64.uint64(uncompressedSize);
7431
+ extraFieldZip64.writeUint64(uncompressedSize);
6894
7432
  if (uncompressedFile) {
6895
7433
  const encryptionOverhead = encrypted ? (zipCrypto ? 12 : 16 + encryptionStrength * 4) : 0;
6896
- extraFieldZip64.uint64(passThrough ? 0 : uncompressedSize + encryptionOverhead);
7434
+ extraFieldZip64.writeUint64(passThrough ? 0 : uncompressedSize + encryptionOverhead);
6897
7435
  }
6898
7436
  }
6899
7437
  } else {
@@ -6902,8 +7440,8 @@ function getHeaderInfo(options) {
6902
7440
  let rawExtraFieldAES;
6903
7441
  if (encrypted && !zipCrypto) {
6904
7442
  const extraFieldAES = createRecordWriter(getLength(EXTRAFIELD_DATA_AES) + 2);
6905
- extraFieldAES.uint16(EXTRAFIELD_TYPE_AES);
6906
- extraFieldAES.bytes(EXTRAFIELD_DATA_AES);
7443
+ extraFieldAES.writeUint16(EXTRAFIELD_TYPE_AES);
7444
+ extraFieldAES.writeBytes(EXTRAFIELD_DATA_AES);
6907
7445
  rawExtraFieldAES = extraFieldAES.array;
6908
7446
  rawExtraFieldAES[8] = encryptionStrength;
6909
7447
  } else {
@@ -6919,15 +7457,15 @@ function getHeaderInfo(options) {
6919
7457
  const extraFieldTimestampLength = 9 + (lastAccessDate ? 4 : 0) + (creationDate ? 4 : 0);
6920
7458
  const extraFieldTimestamp = createRecordWriter(extraFieldTimestampLength);
6921
7459
  extraFieldExtendedTimestampFlag = 0x1 + (lastAccessDate ? 0x2 : 0) + (creationDate ? 0x4 : 0);
6922
- extraFieldTimestamp.uint16(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
6923
- extraFieldTimestamp.uint16(extraFieldTimestampLength - 4);
6924
- extraFieldTimestamp.uint8(extraFieldExtendedTimestampFlag);
6925
- extraFieldTimestamp.uint32(lastModTimeUnix);
7460
+ extraFieldTimestamp.writeUint16(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
7461
+ extraFieldTimestamp.writeUint16(extraFieldTimestampLength - 4);
7462
+ extraFieldTimestamp.writeUint8(extraFieldExtendedTimestampFlag);
7463
+ extraFieldTimestamp.writeUint32(lastModTimeUnix);
6926
7464
  if (lastAccessDate) {
6927
- extraFieldTimestamp.uint32(clampUnixTime(getTimeUnix(lastAccessDate)));
7465
+ extraFieldTimestamp.writeUint32(clampUnixTime(getTimeUnix(lastAccessDate)));
6928
7466
  }
6929
7467
  if (creationDate) {
6930
- extraFieldTimestamp.uint32(clampUnixTime(getTimeUnix(creationDate)));
7468
+ extraFieldTimestamp.writeUint32(clampUnixTime(getTimeUnix(creationDate)));
6931
7469
  }
6932
7470
  rawExtraFieldExtendedTimestamp = extraFieldTimestamp.array;
6933
7471
  } else {
@@ -6940,14 +7478,14 @@ function getHeaderInfo(options) {
6940
7478
  try {
6941
7479
  const lastModTimeNTFS = getTimeNTFS(lastModDate);
6942
7480
  const extraFieldNTFS = createRecordWriter(36);
6943
- extraFieldNTFS.uint16(EXTRAFIELD_TYPE_NTFS);
6944
- extraFieldNTFS.uint16(32);
7481
+ extraFieldNTFS.writeUint16(EXTRAFIELD_TYPE_NTFS);
7482
+ extraFieldNTFS.writeUint16(32);
6945
7483
  extraFieldNTFS.skip(4);
6946
- extraFieldNTFS.uint16(EXTRAFIELD_TYPE_NTFS_TAG1);
6947
- extraFieldNTFS.uint16(24);
6948
- extraFieldNTFS.uint64(lastModTimeNTFS);
6949
- extraFieldNTFS.uint64(lastAccessDate ? getTimeNTFS(lastAccessDate) : lastModTimeNTFS);
6950
- extraFieldNTFS.uint64(creationDate ? getTimeNTFS(creationDate) : lastModTimeNTFS);
7484
+ extraFieldNTFS.writeUint16(EXTRAFIELD_TYPE_NTFS_TAG1);
7485
+ extraFieldNTFS.writeUint16(24);
7486
+ extraFieldNTFS.writeUint64(lastModTimeNTFS);
7487
+ extraFieldNTFS.writeUint64(lastAccessDate ? getTimeNTFS(lastAccessDate) : lastModTimeNTFS);
7488
+ extraFieldNTFS.writeUint64(creationDate ? getTimeNTFS(creationDate) : lastModTimeNTFS);
6951
7489
  rawExtraFieldNTFS = extraFieldNTFS.array;
6952
7490
  } catch {
6953
7491
  rawExtraFieldNTFS = EMPTY_UINT8_ARRAY;
@@ -6962,24 +7500,24 @@ function getHeaderInfo(options) {
6962
7500
  try {
6963
7501
  const { uid, gid, unixExtraFieldType } = options;
6964
7502
  if (unixExtraFieldType == INFOZIP_EXTRA_FIELD_TYPE && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
6965
- const uidBytes = packUnixId(uid);
6966
- const gidBytes = packUnixId(gid);
7503
+ const uidBytes = packUnixId(uid === UNDEFINED_VALUE ? 0 : uid);
7504
+ const gidBytes = packUnixId(gid === UNDEFINED_VALUE ? 0 : gid);
6967
7505
  const payloadLength = 3 + uidBytes.length + gidBytes.length;
6968
7506
  const extraFieldUnix = createRecordWriter(4 + payloadLength);
6969
- extraFieldUnix.uint16(EXTRAFIELD_TYPE_INFOZIP);
6970
- extraFieldUnix.uint16(payloadLength);
6971
- extraFieldUnix.uint8(1);
6972
- extraFieldUnix.uint8(uidBytes.length);
6973
- extraFieldUnix.bytes(uidBytes);
6974
- extraFieldUnix.uint8(gidBytes.length);
6975
- extraFieldUnix.bytes(gidBytes);
7507
+ extraFieldUnix.writeUint16(EXTRAFIELD_TYPE_INFOZIP);
7508
+ extraFieldUnix.writeUint16(payloadLength);
7509
+ extraFieldUnix.writeUint8(1);
7510
+ extraFieldUnix.writeUint8(uidBytes.length);
7511
+ extraFieldUnix.writeBytes(uidBytes);
7512
+ extraFieldUnix.writeUint8(gidBytes.length);
7513
+ extraFieldUnix.writeBytes(gidBytes);
6976
7514
  rawExtraFieldUnix = extraFieldUnix.array;
6977
7515
  } else if (unixExtraFieldType == UNIX_EXTRA_FIELD_TYPE && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
6978
7516
  const extraFieldUnix = createRecordWriter(8);
6979
- extraFieldUnix.uint16(EXTRAFIELD_TYPE_UNIX);
6980
- extraFieldUnix.uint16(4);
6981
- extraFieldUnix.uint16((uid === UNDEFINED_VALUE ? 0 : uid) & MAX_16_BITS);
6982
- extraFieldUnix.uint16((gid === UNDEFINED_VALUE ? 0 : gid) & MAX_16_BITS);
7517
+ extraFieldUnix.writeUint16(EXTRAFIELD_TYPE_UNIX);
7518
+ extraFieldUnix.writeUint16(4);
7519
+ extraFieldUnix.writeUint16((uid === UNDEFINED_VALUE ? 0 : uid) & MAX_16_BITS);
7520
+ extraFieldUnix.writeUint16((gid === UNDEFINED_VALUE ? 0 : gid) & MAX_16_BITS);
6983
7521
  rawExtraFieldUnix = extraFieldUnix.array;
6984
7522
  } else {
6985
7523
  rawExtraFieldUnix = EMPTY_UINT8_ARRAY;
@@ -6990,6 +7528,9 @@ function getHeaderInfo(options) {
6990
7528
  if (compressionMethod === UNDEFINED_VALUE) {
6991
7529
  compressionMethod = compressed ? COMPRESSION_METHOD_DEFLATE : COMPRESSION_METHOD_STORE;
6992
7530
  }
7531
+ if (version === UNDEFINED_VALUE) {
7532
+ version = compressionMethod == COMPRESSION_METHOD_STORE && !directory && !encrypted ? VERSION_STORE : VERSION_DEFLATE;
7533
+ }
6993
7534
  const { codecVersionNeeded } = options;
6994
7535
  if (compressed && codecVersionNeeded !== UNDEFINED_VALUE) {
6995
7536
  version = version > codecVersionNeeded ? version : codecVersionNeeded;
@@ -7002,12 +7543,13 @@ function getHeaderInfo(options) {
7002
7543
  if (passThrough && crc32 !== UNDEFINED_VALUE) {
7003
7544
  rawExtraFieldAES[EXTRAFIELD_OFFSET_AES_VENDOR_VERSION] = VENDOR_VERSION_AE_1;
7004
7545
  }
7005
- rawExtraFieldAES[9] = compressionMethod;
7546
+ setUint16(getDataView(rawExtraFieldAES), EXTRAFIELD_OFFSET_AES_COMPRESSION_METHOD, compressionMethod);
7006
7547
  compressionMethod = COMPRESSION_METHOD_AES;
7007
7548
  }
7008
7549
  const localExtraFieldZip64Length = writeLocalExtraFieldZip64 ? getLength(rawLocalExtraFieldZip64) : 0;
7009
7550
  const extraFieldLength = localExtraFieldZip64Length + getLength(rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField, rawLocalExtraField);
7010
- if (extraFieldLength > MAX_16_BITS) {
7551
+ const maximumUsdzExtraFieldLength = options[OPTION_USDZ] ? EXTRAFIELD_USDZ_MAX_LENGTH : 0;
7552
+ if (extraFieldLength + maximumUsdzExtraFieldLength > MAX_16_BITS) {
7011
7553
  throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
7012
7554
  }
7013
7555
  const dosLastModDate = new Date(Math.ceil(Math.floor(lastModDate.getTime() / 1000) / 2) * 2000);
@@ -7021,6 +7563,7 @@ function getHeaderInfo(options) {
7021
7563
  compressionMethod,
7022
7564
  uncompressedSize,
7023
7565
  lastModDate: dosLastModDate < MIN_DATE ? MIN_DATE : dosLastModDate > MAX_DATE ? MAX_DATE : dosLastModDate,
7566
+ rawLastModDate: rawLastModDateOption,
7024
7567
  rawFilename,
7025
7568
  zip64CompressedSize,
7026
7569
  zip64UncompressedSize,
@@ -7029,18 +7572,18 @@ function getHeaderInfo(options) {
7029
7572
  const localHeader = createRecordWriter(HEADER_SIZE + getLength(rawFilename) + extraFieldLength);
7030
7573
  const localHeaderArray = localHeader.array;
7031
7574
  const localHeaderView = getDataView(localHeaderArray);
7032
- localHeader.uint32(LOCAL_FILE_HEADER_SIGNATURE);
7033
- localHeader.bytes(headerArray);
7034
- localHeader.bytes(rawFilename);
7575
+ localHeader.writeUint32(LOCAL_FILE_HEADER_SIGNATURE);
7576
+ localHeader.writeBytes(headerArray);
7577
+ localHeader.writeBytes(rawFilename);
7035
7578
  if (writeLocalExtraFieldZip64) {
7036
- localHeader.bytes(rawLocalExtraFieldZip64);
7037
- }
7038
- localHeader.bytes(rawExtraFieldAES);
7039
- localHeader.bytes(rawExtraFieldExtendedTimestamp);
7040
- localHeader.bytes(rawExtraFieldNTFS);
7041
- localHeader.bytes(rawExtraFieldUnix);
7042
- localHeader.bytes(rawExtraField);
7043
- localHeader.bytes(rawLocalExtraField);
7579
+ localHeader.writeBytes(rawLocalExtraFieldZip64);
7580
+ }
7581
+ localHeader.writeBytes(rawExtraFieldAES);
7582
+ localHeader.writeBytes(rawExtraFieldExtendedTimestamp);
7583
+ localHeader.writeBytes(rawExtraFieldNTFS);
7584
+ localHeader.writeBytes(rawExtraFieldUnix);
7585
+ localHeader.writeBytes(rawExtraField);
7586
+ localHeader.writeBytes(rawLocalExtraField);
7044
7587
  if (dataDescriptor) {
7045
7588
  if (!zip64CompressedSize) {
7046
7589
  setUint32(localHeaderView, HEADER_OFFSET_COMPRESSED_SIZE + LOCAL_HEADER_COMMON_OFFSET, 0);
@@ -7093,18 +7636,14 @@ function appendExtraFieldUSDZ(entryInfo, zipWriterOffset) {
7093
7636
  }
7094
7637
 
7095
7638
  function packUnixId(id) {
7096
- if (id === UNDEFINED_VALUE) {
7097
- return EMPTY_UINT8_ARRAY;
7098
- } else {
7099
- const dataArray = new Uint8Array(4);
7100
- const dataView = getDataView(dataArray);
7101
- dataView.setUint32(0, id, true);
7102
- let length = 4;
7103
- while (length > 1 && dataArray[length - 1] === 0) {
7104
- length--;
7105
- }
7106
- return dataArray.subarray(0, length);
7639
+ const dataArray = new Uint8Array(4);
7640
+ const dataView = getDataView(dataArray);
7641
+ dataView.setUint32(0, id, true);
7642
+ let length = 4;
7643
+ while (length > 1 && dataArray[length - 1] === 0) {
7644
+ length--;
7107
7645
  }
7646
+ return dataArray.subarray(0, length);
7108
7647
  }
7109
7648
 
7110
7649
  function normalizeMsdosAttributes(msdosAttributesRaw, msdosAttributes) {
@@ -7230,10 +7769,10 @@ function updateLocalHeader({
7230
7769
 
7231
7770
 
7232
7771
  async function closeFile(zipWriter, comment, options) {
7233
- const directoryDataLength = createDirectoryRecords(zipWriter.files);
7234
- const { directoryStart, directoryArray } = await writeDirectoryRecords(zipWriter, directoryDataLength, options);
7772
+ const directoryDataLength = createDirectoryRecords(zipWriter.fileEntries);
7773
+ const { directoryStart, directoryEnd, directoryArray } = await writeDirectoryRecords(zipWriter, directoryDataLength, options);
7235
7774
  const signatureLength = await writeDigitalSignatureRecord(zipWriter, directoryArray, options);
7236
- await writeEndOfDirectoryRecord(zipWriter, comment, options, { directoryStart, directoryDataLength, signatureLength });
7775
+ await writeEndOfDirectoryRecord(zipWriter, comment, options, { directoryStart, directoryEnd, directoryDataLength, signatureLength });
7237
7776
  }
7238
7777
 
7239
7778
  function createDirectoryRecords(files) {
@@ -7246,6 +7785,7 @@ function createDirectoryRecords(files) {
7246
7785
  rawExtraFieldNTFS,
7247
7786
  rawExtraFieldUnix,
7248
7787
  rawExtraField,
7788
+ rawCentralExtraField,
7249
7789
  extendedTimestamp,
7250
7790
  extraFieldExtendedTimestampFlag,
7251
7791
  lastModDate,
@@ -7260,19 +7800,19 @@ function createDirectoryRecords(files) {
7260
7800
  if (zip64Offset || zip64DiskNumberStart || zip64UncompressedSize || zip64CompressedSize) {
7261
7801
  const length = 4 + (zip64UncompressedSize ? 8 : 0) + (zip64CompressedSize ? 8 : 0) + (zip64Offset ? 8 : 0) + (zip64DiskNumberStart ? 4 : 0);
7262
7802
  const extraFieldZip64 = createRecordWriter(length);
7263
- extraFieldZip64.uint16(EXTRAFIELD_TYPE_ZIP64);
7264
- extraFieldZip64.uint16(length - 4);
7803
+ extraFieldZip64.writeUint16(EXTRAFIELD_TYPE_ZIP64);
7804
+ extraFieldZip64.writeUint16(length - 4);
7265
7805
  if (zip64UncompressedSize) {
7266
- extraFieldZip64.uint64(uncompressedSize);
7806
+ extraFieldZip64.writeUint64(uncompressedSize);
7267
7807
  }
7268
7808
  if (zip64CompressedSize) {
7269
- extraFieldZip64.uint64(compressedSize);
7809
+ extraFieldZip64.writeUint64(compressedSize);
7270
7810
  }
7271
7811
  if (zip64Offset) {
7272
- extraFieldZip64.uint64(fileEntry.offset);
7812
+ extraFieldZip64.writeUint64(fileEntry.offset);
7273
7813
  }
7274
7814
  if (zip64DiskNumberStart) {
7275
- extraFieldZip64.uint32(fileEntry.diskNumberStart);
7815
+ extraFieldZip64.writeUint32(fileEntry.diskNumberStart);
7276
7816
  }
7277
7817
  rawExtraFieldZip64 = extraFieldZip64.array;
7278
7818
  } else {
@@ -7285,10 +7825,10 @@ function createDirectoryRecords(files) {
7285
7825
  const lastModTimeUnix = getTimeUnix(lastModDate);
7286
7826
  if (extendedTimestamp && inUnixTimeRange(lastModTimeUnix)) {
7287
7827
  const extraFieldTimestamp = createRecordWriter(9);
7288
- extraFieldTimestamp.uint16(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
7289
- extraFieldTimestamp.uint16(5);
7290
- extraFieldTimestamp.uint8(extraFieldExtendedTimestampFlag);
7291
- extraFieldTimestamp.uint32(lastModTimeUnix);
7828
+ extraFieldTimestamp.writeUint16(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
7829
+ extraFieldTimestamp.writeUint16(5);
7830
+ extraFieldTimestamp.writeUint8(extraFieldExtendedTimestampFlag);
7831
+ extraFieldTimestamp.writeUint32(lastModTimeUnix);
7292
7832
  rawExtraFieldTimestamp = extraFieldTimestamp.array;
7293
7833
  } else {
7294
7834
  rawExtraFieldTimestamp = EMPTY_UINT8_ARRAY;
@@ -7300,7 +7840,8 @@ function createDirectoryRecords(files) {
7300
7840
  rawExtraFieldNTFS,
7301
7841
  rawExtraFieldUnix,
7302
7842
  rawExtraFieldTimestamp,
7303
- rawExtraField);
7843
+ rawExtraField,
7844
+ rawCentralExtraField);
7304
7845
  if (extraFieldLength > MAX_16_BITS) {
7305
7846
  throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
7306
7847
  }
@@ -7310,14 +7851,15 @@ function createDirectoryRecords(files) {
7310
7851
  }
7311
7852
 
7312
7853
  async function writeDirectoryRecords(zipWriter, directoryDataLength, options) {
7313
- const { files, writer } = zipWriter;
7854
+ const { fileEntries, writer } = zipWriter;
7314
7855
  const directoryArray = new Uint8Array(directoryDataLength);
7315
7856
  await initStream(writer);
7316
7857
  let offset = 0;
7317
7858
  let directoryDiskOffset = 0;
7318
7859
  let directoryStartDiskNumber = getDiskNumber(writer);
7319
7860
  let directoryStartDiskOffset = getDiskOffset(writer);
7320
- for (const [indexFileEntry, fileEntry] of Array.from(files.values()).entries()) {
7861
+ let directoryEndDiskEntriesLength = 0;
7862
+ for (const [indexFileEntry, fileEntry] of Array.from(fileEntries.values()).entries()) {
7321
7863
  const {
7322
7864
  offset: fileEntryOffset,
7323
7865
  rawFilename,
@@ -7327,6 +7869,7 @@ async function writeDirectoryRecords(zipWriter, directoryDataLength, options) {
7327
7869
  rawExtraFieldNTFS,
7328
7870
  rawExtraFieldUnix,
7329
7871
  rawExtraField,
7872
+ rawCentralExtraField,
7330
7873
  rawComment,
7331
7874
  versionMadeBy,
7332
7875
  headerArray,
@@ -7341,11 +7884,12 @@ async function writeDirectoryRecords(zipWriter, directoryDataLength, options) {
7341
7884
  uncompressedSize,
7342
7885
  compressedSize
7343
7886
  } = fileEntry;
7344
- const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField);
7887
+ const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField, rawCentralExtraField);
7345
7888
  const directoryRecordLength = CENTRAL_FILE_HEADER_LENGTH + getLength(rawFilename, rawComment) + extraFieldLength;
7346
7889
  if (exceedsAvailableSize(writer, offset + directoryRecordLength - directoryDiskOffset)) {
7347
7890
  await writeData(writer, directoryArray.slice(directoryDiskOffset, offset));
7348
7891
  directoryDiskOffset = offset;
7892
+ directoryEndDiskEntriesLength = 0;
7349
7893
  await writer.closeDisk();
7350
7894
  }
7351
7895
  if (indexFileEntry == 0) {
@@ -7362,28 +7906,30 @@ async function writeDirectoryRecords(zipWriter, directoryDataLength, options) {
7362
7906
  setUint16(headerView, HEADER_OFFSET_VERSION, VERSION_ZIP64);
7363
7907
  }
7364
7908
  const directoryRecord = createRecordWriter(directoryRecordLength);
7365
- directoryRecord.uint32(CENTRAL_FILE_HEADER_SIGNATURE);
7366
- directoryRecord.uint16(versionMadeBy);
7367
- directoryRecord.bytes(headerArray.subarray(0, HEADER_SIZE - 4 - 2));
7368
- directoryRecord.uint16(extraFieldLength);
7369
- directoryRecord.uint16(getLength(rawComment));
7370
- directoryRecord.uint16(zip64DiskNumberStart ? MAX_16_BITS : diskNumberStart);
7371
- directoryRecord.uint16(internalFileAttributes);
7372
- directoryRecord.uint32(externalFileAttributes);
7373
- directoryRecord.uint32(zip64Offset ? MAX_32_BITS : fileEntryOffset);
7374
- directoryRecord.bytes(rawFilename);
7375
- directoryRecord.bytes(rawExtraFieldZip64);
7376
- directoryRecord.bytes(rawExtraFieldAES);
7377
- directoryRecord.bytes(rawExtraFieldExtendedTimestamp);
7378
- directoryRecord.bytes(rawExtraFieldNTFS);
7379
- directoryRecord.bytes(rawExtraFieldUnix);
7380
- directoryRecord.bytes(rawExtraField);
7381
- directoryRecord.bytes(rawComment);
7909
+ directoryRecord.writeUint32(CENTRAL_FILE_HEADER_SIGNATURE);
7910
+ directoryRecord.writeUint16(versionMadeBy);
7911
+ directoryRecord.writeBytes(headerArray.subarray(0, HEADER_SIZE - 4 - 2));
7912
+ directoryRecord.writeUint16(extraFieldLength);
7913
+ directoryRecord.writeUint16(getLength(rawComment));
7914
+ directoryRecord.writeUint16(zip64DiskNumberStart ? MAX_16_BITS : diskNumberStart);
7915
+ directoryRecord.writeUint16(internalFileAttributes);
7916
+ directoryRecord.writeUint32(externalFileAttributes);
7917
+ directoryRecord.writeUint32(zip64Offset ? MAX_32_BITS : fileEntryOffset);
7918
+ directoryRecord.writeBytes(rawFilename);
7919
+ directoryRecord.writeBytes(rawExtraFieldZip64);
7920
+ directoryRecord.writeBytes(rawExtraFieldAES);
7921
+ directoryRecord.writeBytes(rawExtraFieldExtendedTimestamp);
7922
+ directoryRecord.writeBytes(rawExtraFieldNTFS);
7923
+ directoryRecord.writeBytes(rawExtraFieldUnix);
7924
+ directoryRecord.writeBytes(rawExtraField);
7925
+ directoryRecord.writeBytes(rawCentralExtraField);
7926
+ directoryRecord.writeBytes(rawComment);
7382
7927
  arraySet(directoryArray, directoryRecord.array, offset);
7383
7928
  offset += directoryRecordLength;
7929
+ directoryEndDiskEntriesLength++;
7384
7930
  if (options.onprogress) {
7385
7931
  try {
7386
- await options.onprogress(indexFileEntry + 1, files.size, new Entry(fileEntry));
7932
+ await options.onprogress(indexFileEntry + 1, fileEntries.size, new Entry(fileEntry));
7387
7933
  } catch {
7388
7934
  // ignored
7389
7935
  }
@@ -7392,12 +7938,13 @@ async function writeDirectoryRecords(zipWriter, directoryDataLength, options) {
7392
7938
  await writeData(writer, directoryDiskOffset ? directoryArray.slice(directoryDiskOffset) : directoryArray);
7393
7939
  return {
7394
7940
  directoryStart: { diskNumber: directoryStartDiskNumber, diskOffset: directoryStartDiskOffset },
7941
+ directoryEnd: { diskNumber: getDiskNumber(writer), entriesLength: directoryEndDiskEntriesLength },
7395
7942
  directoryArray
7396
7943
  };
7397
7944
  }
7398
7945
 
7399
7946
  async function writeDigitalSignatureRecord(zipWriter, directoryArray, options) {
7400
- const signCentralDirectory = getOptionValue(zipWriter, options, OPTION_SIGN_CENTRAL_DIRECTORY);
7947
+ const signCentralDirectory = getFunctionOptionValue(zipWriter, options, OPTION_SIGN_CENTRAL_DIRECTORY);
7401
7948
  if (signCentralDirectory) {
7402
7949
  const signatureData = await signCentralDirectory(directoryArray);
7403
7950
  const signatureDataLength = getLength(signatureData);
@@ -7405,10 +7952,14 @@ async function writeDigitalSignatureRecord(zipWriter, directoryArray, options) {
7405
7952
  throw new Error(ERR_INVALID_SIGNATURE_DATA);
7406
7953
  }
7407
7954
  const signatureRecord = createRecordWriter(6 + signatureDataLength);
7408
- signatureRecord.uint32(DIGITAL_SIGNATURE_RECORD_SIGNATURE);
7409
- signatureRecord.uint16(signatureDataLength);
7410
- signatureRecord.bytes(signatureData);
7411
- await writeData(zipWriter.writer, signatureRecord.array);
7955
+ signatureRecord.writeUint32(DIGITAL_SIGNATURE_RECORD_SIGNATURE);
7956
+ signatureRecord.writeUint16(signatureDataLength);
7957
+ signatureRecord.writeBytes(signatureData);
7958
+ const { writer } = zipWriter;
7959
+ if (exceedsAvailableSize(writer, getLength(signatureRecord.array))) {
7960
+ await writer.closeDisk();
7961
+ }
7962
+ await writeData(writer, signatureRecord.array);
7412
7963
  return 6 + signatureDataLength;
7413
7964
  }
7414
7965
  return 0;
@@ -7416,64 +7967,66 @@ async function writeDigitalSignatureRecord(zipWriter, directoryArray, options) {
7416
7967
 
7417
7968
  async function writeEndOfDirectoryRecord(zipWriter, comment, options, cdInfo) {
7418
7969
  const { writer } = zipWriter;
7419
- const { directoryStart, signatureLength } = cdInfo;
7970
+ const { directoryStart, directoryEnd, signatureLength } = cdInfo;
7420
7971
  let { directoryDataLength } = cdInfo;
7421
- let filesLength = zipWriter.files.size;
7972
+ let fileEntriesLength = zipWriter.fileEntries.size;
7422
7973
  let diskNumber = directoryStart.diskNumber;
7423
7974
  let directoryOffset = getSegmentOffset(zipWriter, directoryStart);
7975
+ const commentLength = getLength(comment);
7976
+ if (commentLength > MAX_16_BITS) {
7977
+ throw new Error(ERR_INVALID_COMMENT);
7978
+ }
7979
+ let zip64 = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIP64);
7424
7980
  let lastDiskNumber = getDiskNumber(writer);
7425
- if (exceedsAvailableSize(writer, END_OF_CENTRAL_DIR_LENGTH)) {
7981
+ if (exceedsAvailableSize(writer, (zip64 ? ZIP64_END_OF_CENTRAL_DIR_TOTAL_LENGTH : END_OF_CENTRAL_DIR_LENGTH) + commentLength)) {
7426
7982
  lastDiskNumber++;
7427
7983
  }
7428
- let zip64 = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIP64);
7429
- if (directoryOffset >= MAX_32_BITS || directoryDataLength >= MAX_32_BITS || filesLength >= MAX_16_BITS || lastDiskNumber >= MAX_16_BITS) {
7984
+ if (directoryOffset >= MAX_32_BITS || directoryDataLength >= MAX_32_BITS || fileEntriesLength >= MAX_16_BITS || lastDiskNumber >= MAX_16_BITS) {
7430
7985
  if (zip64 === false) {
7431
7986
  throw new Error(ERR_UNSUPPORTED_FORMAT);
7432
7987
  } else {
7433
7988
  zip64 = true;
7434
7989
  }
7435
7990
  }
7436
- const commentLength = getLength(comment);
7437
- if (commentLength > MAX_16_BITS) {
7438
- throw new Error(ERR_INVALID_COMMENT);
7439
- }
7440
7991
  const endOfdirectoryRecord = createRecordWriter(zip64 ? ZIP64_END_OF_CENTRAL_DIR_TOTAL_LENGTH : END_OF_CENTRAL_DIR_LENGTH);
7441
7992
  if (exceedsAvailableSize(writer, getLength(endOfdirectoryRecord.array) + commentLength)) {
7442
7993
  await writer.closeDisk();
7443
7994
  }
7444
7995
  lastDiskNumber = getDiskNumber(writer);
7996
+ let diskFileEntriesLength = lastDiskNumber == directoryEnd.diskNumber ? directoryEnd.entriesLength : 0;
7445
7997
  if (zip64) {
7446
- endOfdirectoryRecord.uint32(ZIP64_END_OF_CENTRAL_DIR_SIGNATURE);
7447
- endOfdirectoryRecord.uint64(44);
7448
- endOfdirectoryRecord.uint16(45);
7449
- endOfdirectoryRecord.uint16(45);
7450
- endOfdirectoryRecord.uint32(lastDiskNumber);
7451
- endOfdirectoryRecord.uint32(diskNumber);
7452
- endOfdirectoryRecord.uint64(filesLength);
7453
- endOfdirectoryRecord.uint64(filesLength);
7454
- endOfdirectoryRecord.uint64(directoryDataLength);
7455
- endOfdirectoryRecord.uint64(directoryOffset);
7456
- endOfdirectoryRecord.uint32(ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIGNATURE);
7457
- endOfdirectoryRecord.uint32(lastDiskNumber);
7458
- endOfdirectoryRecord.uint64(BigInt(getSegmentOffset(zipWriter, writer)) + BigInt(directoryDataLength) + BigInt(signatureLength));
7459
- endOfdirectoryRecord.uint32(lastDiskNumber + 1);
7998
+ endOfdirectoryRecord.writeUint32(ZIP64_END_OF_CENTRAL_DIR_SIGNATURE);
7999
+ endOfdirectoryRecord.writeUint64(44);
8000
+ endOfdirectoryRecord.writeUint16(45);
8001
+ endOfdirectoryRecord.writeUint16(45);
8002
+ endOfdirectoryRecord.writeUint32(lastDiskNumber);
8003
+ endOfdirectoryRecord.writeUint32(diskNumber);
8004
+ endOfdirectoryRecord.writeUint64(diskFileEntriesLength);
8005
+ endOfdirectoryRecord.writeUint64(fileEntriesLength);
8006
+ endOfdirectoryRecord.writeUint64(directoryDataLength);
8007
+ endOfdirectoryRecord.writeUint64(directoryOffset);
8008
+ endOfdirectoryRecord.writeUint32(ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIGNATURE);
8009
+ endOfdirectoryRecord.writeUint32(lastDiskNumber);
8010
+ endOfdirectoryRecord.writeUint64(BigInt(getSegmentOffset(zipWriter, writer)) + BigInt(directoryDataLength) + BigInt(signatureLength));
8011
+ endOfdirectoryRecord.writeUint32(lastDiskNumber + 1);
7460
8012
  const supportZip64SplitFile = getOptionValue(zipWriter, options, OPTION_SUPPORT_ZIP64_SPLIT_FILE, true);
7461
8013
  if (supportZip64SplitFile) {
7462
8014
  lastDiskNumber = MAX_16_BITS;
7463
8015
  diskNumber = MAX_16_BITS;
7464
8016
  }
7465
- filesLength = MAX_16_BITS;
8017
+ diskFileEntriesLength = MAX_16_BITS;
8018
+ fileEntriesLength = MAX_16_BITS;
7466
8019
  directoryOffset = MAX_32_BITS;
7467
8020
  directoryDataLength = MAX_32_BITS;
7468
8021
  }
7469
- endOfdirectoryRecord.uint32(END_OF_CENTRAL_DIR_SIGNATURE);
7470
- endOfdirectoryRecord.uint16(lastDiskNumber);
7471
- endOfdirectoryRecord.uint16(diskNumber);
7472
- endOfdirectoryRecord.uint16(filesLength);
7473
- endOfdirectoryRecord.uint16(filesLength);
7474
- endOfdirectoryRecord.uint32(directoryDataLength);
7475
- endOfdirectoryRecord.uint32(directoryOffset);
7476
- endOfdirectoryRecord.uint16(commentLength);
8022
+ endOfdirectoryRecord.writeUint32(END_OF_CENTRAL_DIR_SIGNATURE);
8023
+ endOfdirectoryRecord.writeUint16(lastDiskNumber);
8024
+ endOfdirectoryRecord.writeUint16(diskNumber);
8025
+ endOfdirectoryRecord.writeUint16(diskFileEntriesLength);
8026
+ endOfdirectoryRecord.writeUint16(fileEntriesLength);
8027
+ endOfdirectoryRecord.writeUint32(directoryDataLength);
8028
+ endOfdirectoryRecord.writeUint32(directoryOffset);
8029
+ endOfdirectoryRecord.writeUint16(commentLength);
7477
8030
  await writeData(writer, endOfdirectoryRecord.array);
7478
8031
  if (commentLength) {
7479
8032
  await writeData(writer, comment);
@@ -7486,11 +8039,11 @@ function createRecordWriter(length) {
7486
8039
  let offset = 0;
7487
8040
  return {
7488
8041
  array,
7489
- uint8: value => { setUint8(view, offset, value); offset += 1; },
7490
- uint16: value => { setUint16(view, offset, value); offset += 2; },
7491
- uint32: value => { setUint32(view, offset, value); offset += 4; },
7492
- uint64: value => { setBigUint64(view, offset, BigInt(value)); offset += 8; },
7493
- bytes: value => { arraySet(array, value, offset); offset += getLength(value); },
8042
+ writeUint8: value => { setUint8(view, offset, value); offset += 1; },
8043
+ writeUint16: value => { setUint16(view, offset, value); offset += 2; },
8044
+ writeUint32: value => { setUint32(view, offset, value); offset += 4; },
8045
+ writeUint64: value => { setBigUint64(view, offset, BigInt(value)); offset += 8; },
8046
+ writeBytes: value => { arraySet(array, value, offset); offset += getLength(value); },
7494
8047
  skip: count => offset += count
7495
8048
  };
7496
8049
  }
@@ -7514,6 +8067,105 @@ function getSegmentOffset(zipWriter, { diskNumber = 0, diskOffset = 0 }) {
7514
8067
  return zipWriter.offset - diskOffset - (diskNumber ? zipWriter.initialOffset : 0);
7515
8068
  }
7516
8069
 
8070
+ async function startsWithSplitZipSignature(reader) {
8071
+ const signatureArray = await readUint8Array(reader, 0, SPLIT_ZIP_FILE_SIGNATURE_LENGTH);
8072
+ return getUint32(getDataView(signatureArray), 0) == SPLIT_ZIP_FILE_SIGNATURE;
8073
+ }
8074
+
8075
+ function removeExtraFieldZip64(rawExtraField) {
8076
+ const rawExtraFieldView = getDataView(rawExtraField);
8077
+ let offsetExtraField = 0;
8078
+ while (offsetExtraField + 4 <= getLength(rawExtraField)) {
8079
+ const size = 4 + getUint16(rawExtraFieldView, offsetExtraField + 2);
8080
+ if (getUint16(rawExtraFieldView, offsetExtraField) == EXTRAFIELD_TYPE_ZIP64) {
8081
+ return removeExtraFieldZip64(concat(
8082
+ rawExtraField.subarray(0, offsetExtraField),
8083
+ rawExtraField.subarray(Math.min(offsetExtraField + size, getLength(rawExtraField)))));
8084
+ }
8085
+ offsetExtraField += size;
8086
+ }
8087
+ return rawExtraField;
8088
+ }
8089
+
8090
+ async function copyZipData(zipWriter, reader, entries, directoryOffset) {
8091
+ const { writer } = zipWriter;
8092
+ const entryPositions = new Map();
8093
+ if (writer.closeDisk) {
8094
+ const sortedEntries = Array.from(entries).sort((firstEntry, secondEntry) =>
8095
+ getSourceOffset(reader, firstEntry) - getSourceOffset(reader, secondEntry));
8096
+ let copiedLength = 0;
8097
+ for (const entry of sortedEntries) {
8098
+ const sourceOffset = getSourceOffset(reader, entry);
8099
+ await copyData(zipWriter, reader, copiedLength, sourceOffset - copiedLength);
8100
+ if (exceedsAvailableSize(writer, await getLocalHeaderLength(reader, sourceOffset))) {
8101
+ await writer.closeDisk();
8102
+ }
8103
+ entryPositions.set(entry, {
8104
+ offset: getSegmentOffset(zipWriter, writer),
8105
+ diskNumberStart: getDiskNumber(writer)
8106
+ });
8107
+ copiedLength = sourceOffset;
8108
+ }
8109
+ await copyData(zipWriter, reader, copiedLength, directoryOffset - copiedLength);
8110
+ } else {
8111
+ const baseOffset = zipWriter.offset;
8112
+ await copyData(zipWriter, reader, 0, directoryOffset);
8113
+ entries.forEach(entry => entryPositions.set(entry, {
8114
+ offset: baseOffset + getSourceOffset(reader, entry),
8115
+ diskNumberStart: 0
8116
+ }));
8117
+ }
8118
+ return entryPositions;
8119
+ }
8120
+
8121
+ async function copyData(zipWriter, reader, offset, size) {
8122
+ if (size > 0) {
8123
+ const { writer } = zipWriter;
8124
+ let copiedLength = 0;
8125
+ try {
8126
+ await flushBufferedData(createReadable(reader, { offset, size }), writer, UNDEFINED_VALUE, chunkLength => copiedLength += chunkLength);
8127
+ } catch (error) {
8128
+ zipWriter.hasCorruptedEntries = true;
8129
+ try {
8130
+ error.corruptedEntry = true;
8131
+ } catch {
8132
+ // ignored
8133
+ }
8134
+ throw error;
8135
+ } finally {
8136
+ writer.size += copiedLength;
8137
+ zipWriter.offset += copiedLength;
8138
+ }
8139
+ }
8140
+ }
8141
+
8142
+ async function getLocalHeaderLength(reader, offset) {
8143
+ const headerArray = await readUint8Array(reader, offset, HEADER_SIZE);
8144
+ if (getLength(headerArray) < HEADER_SIZE) {
8145
+ return HEADER_SIZE;
8146
+ }
8147
+ const headerView = getDataView(headerArray);
8148
+ return HEADER_SIZE +
8149
+ getUint16(headerView, HEADER_OFFSET_FILENAME_LENGTH + LOCAL_HEADER_COMMON_OFFSET) +
8150
+ getUint16(headerView, HEADER_OFFSET_EXTRAFIELD_LENGTH + LOCAL_HEADER_COMMON_OFFSET);
8151
+ }
8152
+
8153
+ function getSourceOffset(reader, { offset, diskNumberStart }) {
8154
+ return offset + (reader.getDiskOffset ? reader.getDiskOffset(diskNumberStart) : 0);
8155
+ }
8156
+
8157
+ function getSplitZipSignatureArray() {
8158
+ const signatureArray = new Uint8Array(SPLIT_ZIP_FILE_SIGNATURE_LENGTH);
8159
+ setUint32(getDataView(signatureArray), 0, SPLIT_ZIP_FILE_SIGNATURE);
8160
+ return signatureArray;
8161
+ }
8162
+
8163
+ async function writeSplitZipSignature(zipWriter, writer) {
8164
+ delete zipWriter.addSplitZipSignature;
8165
+ await writeData(writer, getSplitZipSignatureArray());
8166
+ zipWriter.offset += SPLIT_ZIP_FILE_SIGNATURE_LENGTH;
8167
+ }
8168
+
7517
8169
  async function writeData(writer, array) {
7518
8170
  const { writable } = writer;
7519
8171
  const streamWriter = writable.getWriter();
@@ -7565,18 +8217,54 @@ function getOptionValue(zipWriter, options, name, defaultValue) {
7565
8217
  return result === UNDEFINED_VALUE ? defaultValue : result;
7566
8218
  }
7567
8219
 
8220
+ function getDateOptionValue(zipWriter, options, name, defaultValue) {
8221
+ const date = getOptionValue(zipWriter, options, name, defaultValue);
8222
+ if (date === null) {
8223
+ return defaultValue;
8224
+ }
8225
+ if (date !== UNDEFINED_VALUE && (typeof date.getTime != FUNCTION_TYPE || Number.isNaN(date.getTime()))) {
8226
+ throw new Error(ERR_INVALID_DATE);
8227
+ }
8228
+ return date;
8229
+ }
8230
+
8231
+ function getFunctionOptionValue(zipWriter, options, name) {
8232
+ return checkFunctionOption(getOptionValue(zipWriter, options, name));
8233
+ }
8234
+
8235
+ function getAliasedOptionValue(zipWriter, options, name, deprecatedName, defaultValue) {
8236
+ const value = getAliasedValue(options, name, deprecatedName);
8237
+ const result = value === UNDEFINED_VALUE ? getAliasedValue(zipWriter.options, name, deprecatedName) : value;
8238
+ return result === UNDEFINED_VALUE ? defaultValue : result;
8239
+ }
8240
+
8241
+ function getAliasedValue(options, name, deprecatedName) {
8242
+ return options[name] === UNDEFINED_VALUE ? options[deprecatedName] : options[name];
8243
+ }
8244
+
7568
8245
  function getNumberOptionValue(zipWriter, options, name, defaultValue) {
7569
8246
  return toNumber(getOptionValue(zipWriter, options, name, defaultValue));
7570
8247
  }
7571
8248
 
7572
- function toNumber(value) {
7573
- return typeof value == STRING_TYPE && value.trim() ? Number(value) : value;
7574
- }
7575
8249
 
7576
8250
  function getMaximumCompressedSize(uncompressedSize) {
7577
8251
  return uncompressedSize + (5 * (Math.floor(uncompressedSize / 16383) + 1));
7578
8252
  }
7579
8253
 
8254
+ function isCompressed(compressionMethod, level) {
8255
+ return compressionMethod === UNDEFINED_VALUE
8256
+ ? (level === UNDEFINED_VALUE || level > 0)
8257
+ : compressionMethod !== COMPRESSION_METHOD_STORE;
8258
+ }
8259
+
8260
+ function getUint16(view, offset) {
8261
+ return view.getUint16(offset, true);
8262
+ }
8263
+
8264
+ function getUint32(view, offset) {
8265
+ return view.getUint32(offset, true);
8266
+ }
8267
+
7580
8268
  function setUint8(view, offset, value) {
7581
8269
  view.setUint8(offset, value);
7582
8270
  }
@@ -7620,9 +8308,9 @@ function getHeaderArrayData({
7620
8308
  const headerRecord = createRecordWriter(HEADER_SIZE - 4);
7621
8309
  const headerArray = headerRecord.array;
7622
8310
  const headerView = getDataView(headerArray);
7623
- headerRecord.uint16(version);
7624
- headerRecord.uint16(bitFlag);
7625
- headerRecord.uint16(compressionMethod);
8311
+ headerRecord.writeUint16(version);
8312
+ headerRecord.writeUint16(bitFlag);
8313
+ headerRecord.writeUint16(compressionMethod);
7626
8314
  if (rawLastModDate === UNDEFINED_VALUE) {
7627
8315
  const dateArray = new Uint32Array(1);
7628
8316
  const dateView = getDataView(dateArray);
@@ -7630,20 +8318,20 @@ function getHeaderArrayData({
7630
8318
  setUint16(dateView, 2, ((((lastModDate.getFullYear() - 1980) << 4) | (lastModDate.getMonth() + 1)) << 5) | lastModDate.getDate());
7631
8319
  rawLastModDate = dateArray[0];
7632
8320
  }
7633
- headerRecord.uint32(rawLastModDate);
8321
+ headerRecord.writeUint32(rawLastModDate);
7634
8322
  headerRecord.skip(4);
7635
8323
  if (zip64CompressedSize || compressedSize !== UNDEFINED_VALUE) {
7636
- headerRecord.uint32(zip64CompressedSize ? MAX_32_BITS : compressedSize);
8324
+ headerRecord.writeUint32(zip64CompressedSize ? MAX_32_BITS : compressedSize);
7637
8325
  } else {
7638
8326
  headerRecord.skip(4);
7639
8327
  }
7640
8328
  if (zip64UncompressedSize || uncompressedSize !== UNDEFINED_VALUE) {
7641
- headerRecord.uint32(zip64UncompressedSize ? MAX_32_BITS : uncompressedSize);
8329
+ headerRecord.writeUint32(zip64UncompressedSize ? MAX_32_BITS : uncompressedSize);
7642
8330
  } else {
7643
8331
  headerRecord.skip(4);
7644
8332
  }
7645
- headerRecord.uint16(getLength(rawFilename));
7646
- headerRecord.uint16(extraFieldLength);
8333
+ headerRecord.writeUint16(getLength(rawFilename));
8334
+ headerRecord.writeUint16(extraFieldLength);
7647
8335
  return {
7648
8336
  headerArray,
7649
8337
  headerView,
@@ -8901,4 +9589,4 @@ try {
8901
9589
  }
8902
9590
  catch (e) { }
8903
9591
 
8904
- 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_FILENAME_VALIDATION, ERR_INVALID_GID, ERR_INVALID_LEVEL, ERR_INVALID_MAX_APPENDED_DATA_SIZE, ERR_INVALID_MSDOS_ATTRIBUTES, ERR_INVALID_MSDOS_DATA, ERR_INVALID_PASSWORD, ERR_INVALID_PASSWORD_TYPE, ERR_INVALID_SIGNATURE, ERR_INVALID_SIGNATURE_DATA, ERR_INVALID_STRICTNESS, 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_UNSAFE_FILENAME, 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, deflateSync as deflateRaw, getMimeType, inflateSync as inflateRaw, initStream, readUint8Array, registerCodec, resetConfiguration, terminateWorkers, unregisterCodec };
9592
+ 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_ENTRY_DATA_OUT_OF_BOUNDS, 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_COMMENT_TYPE, ERR_INVALID_COMPRESSED_DATA, ERR_INVALID_CRC32, ERR_INVALID_DATE, ERR_INVALID_ENCRYPTION_STRENGTH, ERR_INVALID_ENTRY_COMMENT, ERR_INVALID_ENTRY_COMMENT_TYPE, ERR_INVALID_ENTRY_NAME, ERR_INVALID_EXTRAFIELD, ERR_INVALID_EXTRAFIELD_DATA, ERR_INVALID_EXTRAFIELD_DATA_TYPE, ERR_INVALID_EXTRAFIELD_TYPE, ERR_INVALID_FILENAME_VALIDATION, ERR_INVALID_FUNCTION_OPTION, ERR_INVALID_GID, ERR_INVALID_LEVEL, ERR_INVALID_MAX_APPENDED_DATA_SIZE, ERR_INVALID_MAX_WORKERS, ERR_INVALID_MSDOS_ATTRIBUTES, ERR_INVALID_MSDOS_DATA, ERR_INVALID_PASSWORD, ERR_INVALID_PASSWORD_TYPE, ERR_INVALID_SIGNAL, ERR_INVALID_SIGNATURE, ERR_INVALID_SIGNATURE_DATA, ERR_INVALID_STRICTNESS, 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_COMPRESSION_METHOD, ERR_UNDEFINED_READER, ERR_UNDEFINED_UNCOMPRESSED_SIZE, ERR_UNDETERMINED_SIZE, ERR_UNSAFE_FILENAME, ERR_UNSUPPORTED_COMPRESSION$1 as ERR_UNSUPPORTED_COMPRESSION, ERR_UNSUPPORTED_CONTEXT, ERR_UNSUPPORTED_CRYPTO_API, ERR_UNSUPPORTED_ENCRYPTION, ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH, ERR_UNSUPPORTED_ENCRYPTION_USDZ, ERR_UNSUPPORTED_FORMAT, ERR_UNSUPPORTED_UINT64, ERR_WORKER_STARTUP_TIMEOUT, ERR_WRITER_NOT_INITIALIZED, ERR_ZIP_NOT_EMPTY, HttpRangeReader, HttpReader, Reader, SplitDataReader, SplitDataWriter, TextReader, TextWriter, Uint8ArrayReader, Uint8ArrayWriter, WARNING_APPENDED_DATA, WARNING_COMPRESSED_PATCHED_DATA, WARNING_DUPLICATE_FILENAME, WARNING_MALFORMED_EXTRA_FIELD, WARNING_MISMATCHED_LOCAL_FILE_HEADER_BIT_FLAG, WARNING_MISMATCHED_LOCAL_FILE_HEADER_COMPRESSION_METHOD, WARNING_MISMATCHED_LOCAL_FILE_HEADER_CRC32_OR_SIZES, WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY, WARNING_PREPENDED_DATA, WARNING_TRAILING_CENTRAL_DIRECTORY_DATA, WARNING_UNKNOWN_VERSION, WARNING_UNKNOWN_ZIP64_EXTENSIBLE_DATA, WARNING_UNSORTED_CENTRAL_DIRECTORY, WARNING_WRAPPED_ENTRIES_COUNT, Writer, ZipReader, ZipReaderStream, ZipWriter, ZipWriterStream, configure, createBlobTempStream, createOPFSTempStream, createSyncAccessHandleTempStream, deflateSync as deflateRaw, getMimeType, inflateSync as inflateRaw, initStream, isZipFile, readUint8Array, registerCodec, resetConfiguration, terminateWorkers, unregisterCodec };