@zip.js/zip.js 2.6.43 → 2.6.44

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.
@@ -75,7 +75,7 @@ import {
75
75
  import {
76
76
  initStream,
77
77
  BlobWriter,
78
- SplitZipWriter
78
+ SplitDataWriter
79
79
  } from "./io.js";
80
80
  import { encodeText } from "./util/encode-text.js";
81
81
  import {
@@ -109,7 +109,7 @@ class ZipWriter {
109
109
 
110
110
  constructor(writer, options = {}) {
111
111
  if (writer.writable === UNDEFINED_VALUE && typeof writer.next == FUNCTION_TYPE) {
112
- writer = new SplitZipWriter(writer);
112
+ writer = new SplitDataWriter(writer);
113
113
  }
114
114
  if (writer instanceof WritableStream) {
115
115
  writer = { writable: writer };
@@ -117,7 +117,7 @@ class ZipWriter {
117
117
  if (writer.writable.size === UNDEFINED_VALUE) {
118
118
  writer.writable.size = 0;
119
119
  }
120
- const splitZipFile = writer instanceof SplitZipWriter;
120
+ const splitZipFile = writer instanceof SplitDataWriter;
121
121
  if (!splitZipFile) {
122
122
  Object.assign(writer, {
123
123
  diskNumber: 0,
@@ -174,13 +174,15 @@ class ZipWriter {
174
174
  }
175
175
 
176
176
  async close(comment = new Uint8Array(), options = {}) {
177
+ const zipWriter = this;
177
178
  const { pendingAddFileCalls, writer } = this;
178
179
  const { writable } = writer;
179
180
  while (pendingAddFileCalls.size) {
180
181
  await Promise.all(Array.from(pendingAddFileCalls));
181
182
  }
182
183
  await closeFile(this, comment, options);
183
- if (!writer.preventClose && !options.preventClose) {
184
+ const preventClose = getOptionValue(zipWriter, options, "preventClose");
185
+ if (!preventClose) {
184
186
  await writable.close();
185
187
  }
186
188
  return writer.getData ? writer.getData() : writable;
@@ -216,20 +218,33 @@ async function addFile(zipWriter, name, reader, options) {
216
218
  if (getLength(rawComment) > MAX_16_BITS) {
217
219
  throw new Error(ERR_INVALID_ENTRY_COMMENT);
218
220
  }
219
- const version = zipWriter.options.version || options.version || 0;
221
+ const version = getOptionValue(zipWriter, options, "version", VERSION_DEFLATE);
220
222
  if (version > MAX_16_BITS) {
221
223
  throw new Error(ERR_INVALID_VERSION);
222
224
  }
223
- const versionMadeBy = zipWriter.options.versionMadeBy || options.versionMadeBy || 20;
225
+ const versionMadeBy = getOptionValue(zipWriter, options, "versionMadeBy", 20);
224
226
  if (versionMadeBy > MAX_16_BITS) {
225
227
  throw new Error(ERR_INVALID_VERSION);
226
228
  }
227
- const lastModDate = getOptionValue(zipWriter, options, PROPERTY_NAME_LAST_MODIFICATION_DATE) || new Date();
229
+ const lastModDate = getOptionValue(zipWriter, options, PROPERTY_NAME_LAST_MODIFICATION_DATE, new Date());
228
230
  const lastAccessDate = getOptionValue(zipWriter, options, PROPERTY_NAME_LAST_ACCESS_DATE);
229
231
  const creationDate = getOptionValue(zipWriter, options, PROPERTY_NAME_CREATION_DATE);
232
+ const msDosCompatible = getOptionValue(zipWriter, options, PROPERTY_NAME_MS_DOS_COMPATIBLE, true);
233
+ const internalFileAttribute = getOptionValue(zipWriter, options, PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTE, 0);
234
+ const externalFileAttribute = getOptionValue(zipWriter, options, PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTE, 0);
230
235
  const password = getOptionValue(zipWriter, options, "password");
231
- const encryptionStrength = getOptionValue(zipWriter, options, "encryptionStrength") || 3;
236
+ const encryptionStrength = getOptionValue(zipWriter, options, "encryptionStrength", 3);
232
237
  const zipCrypto = getOptionValue(zipWriter, options, "zipCrypto");
238
+ const extendedTimestamp = getOptionValue(zipWriter, options, "extendedTimestamp", true);
239
+ const keepOrder = getOptionValue(zipWriter, options, "keepOrder", true);
240
+ const level = getOptionValue(zipWriter, options, "level");
241
+ const useWebWorkers = getOptionValue(zipWriter, options, "useWebWorkers");
242
+ const bufferedWrite = getOptionValue(zipWriter, options, "bufferedWrite");
243
+ const dataDescriptorSignature = getOptionValue(zipWriter, options, "dataDescriptorSignature", false);
244
+ const signal = getOptionValue(zipWriter, options, "signal");
245
+ const useCompressionStream = getOptionValue(zipWriter, options, "useCompressionStream");
246
+ let dataDescriptor = getOptionValue(zipWriter, options, "dataDescriptor", true);
247
+ let zip64 = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIP64);
233
248
  if (password !== UNDEFINED_VALUE && encryptionStrength !== UNDEFINED_VALUE && (encryptionStrength < 1 || encryptionStrength > 3)) {
234
249
  throw new Error(ERR_INVALID_ENCRYPTION_STRENGTH);
235
250
  }
@@ -253,24 +268,9 @@ async function addFile(zipWriter, name, reader, options) {
253
268
  offset += 4 + getLength(data);
254
269
  });
255
270
  }
256
- let extendedTimestamp = getOptionValue(zipWriter, options, "extendedTimestamp");
257
- if (extendedTimestamp === UNDEFINED_VALUE) {
258
- extendedTimestamp = true;
259
- }
260
271
  let maximumCompressedSize = 0;
261
272
  let maximumEntrySize = 0;
262
- let keepOrder = getOptionValue(zipWriter, options, "keepOrder");
263
- if (keepOrder === UNDEFINED_VALUE) {
264
- keepOrder = true;
265
- }
266
273
  let uncompressedSize = 0;
267
- let msDosCompatible = getOptionValue(zipWriter, options, PROPERTY_NAME_MS_DOS_COMPATIBLE);
268
- if (msDosCompatible === UNDEFINED_VALUE) {
269
- msDosCompatible = true;
270
- }
271
- const internalFileAttribute = getOptionValue(zipWriter, options, PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTE) || 0;
272
- const externalFileAttribute = getOptionValue(zipWriter, options, PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTE) || 0;
273
- let zip64 = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIP64);
274
274
  if (reader) {
275
275
  if (reader instanceof ReadableStream) {
276
276
  reader = {
@@ -279,7 +279,7 @@ async function addFile(zipWriter, name, reader, options) {
279
279
  }
280
280
  await initStream(reader);
281
281
  if (reader.size === UNDEFINED_VALUE) {
282
- options.dataDescriptor = true;
282
+ dataDescriptor = true;
283
283
  if (zip64 || zip64 === UNDEFINED_VALUE) {
284
284
  zip64 = true;
285
285
  maximumCompressedSize = MAX_32_BITS;
@@ -289,10 +289,11 @@ async function addFile(zipWriter, name, reader, options) {
289
289
  maximumCompressedSize = getMaximumCompressedSize(uncompressedSize);
290
290
  }
291
291
  }
292
- const { diskOffset } = zipWriter.writer;
292
+ const { diskOffset, diskNumber } = zipWriter.writer;
293
293
  if (zipWriter.offset + zipWriter.pendingEntriesSize - diskOffset >= MAX_32_BITS ||
294
294
  uncompressedSize >= MAX_32_BITS ||
295
- maximumCompressedSize >= MAX_32_BITS) {
295
+ maximumCompressedSize >= MAX_32_BITS ||
296
+ diskNumber >= MAX_16_BITS) {
296
297
  if (zip64 === false || !keepOrder) {
297
298
  throw new Error(ERR_UNSUPPORTED_FORMAT);
298
299
  } else {
@@ -300,19 +301,6 @@ async function addFile(zipWriter, name, reader, options) {
300
301
  }
301
302
  }
302
303
  zip64 = zip64 || false;
303
- const level = getOptionValue(zipWriter, options, "level");
304
- const useWebWorkers = getOptionValue(zipWriter, options, "useWebWorkers");
305
- const bufferedWrite = getOptionValue(zipWriter, options, "bufferedWrite");
306
- let dataDescriptor = getOptionValue(zipWriter, options, "dataDescriptor");
307
- let dataDescriptorSignature = getOptionValue(zipWriter, options, "dataDescriptorSignature");
308
- const signal = getOptionValue(zipWriter, options, "signal");
309
- const useCompressionStream = getOptionValue(zipWriter, options, "useCompressionStream");
310
- if (dataDescriptor === UNDEFINED_VALUE) {
311
- dataDescriptor = true;
312
- }
313
- if (dataDescriptor && dataDescriptorSignature === UNDEFINED_VALUE) {
314
- dataDescriptorSignature = false;
315
- }
316
304
  options = Object.assign({}, options, {
317
305
  rawFilename,
318
306
  rawComment,
@@ -385,8 +373,7 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
385
373
  await initStream(writer);
386
374
  } else {
387
375
  fileWriter = writer;
388
- zipWriter.lockWriter = Promise.resolve();
389
- releaseLockWriter = () => delete zipWriter.lockWriter;
376
+ initLockWriter();
390
377
  }
391
378
  await initStream(fileWriter);
392
379
  const { writable, diskNumber } = writer;
@@ -415,7 +402,7 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
415
402
  await requestLockWriter();
416
403
  writingBufferedEntryData = true;
417
404
  if (!dataDescriptor) {
418
- blob = await setMissingInfo(fileEntry, blob, writable, options);
405
+ blob = await writeMissingHeaderInfo(fileEntry, blob, writable, options);
419
406
  }
420
407
  fileEntry.diskNumberStart = writer.diskNumber;
421
408
  diskOffset = writer.diskOffset;
@@ -425,7 +412,7 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
425
412
  }
426
413
  fileEntry.offset = zipWriter.offset - diskOffset;
427
414
  if (fileEntry.zip64) {
428
- setZip64Info(fileEntry);
415
+ setZip64OffsetInfo(fileEntry);
429
416
  } else if (fileEntry.offset >= MAX_32_BITS) {
430
417
  throw new Error(ERR_UNSUPPORTED_FORMAT);
431
418
  }
@@ -458,6 +445,11 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
458
445
  fileEntry.lock = new Promise(resolve => releaseLockCurrentFileEntry = resolve);
459
446
  }
460
447
 
448
+ function initLockWriter() {
449
+ zipWriter.lockWriter = Promise.resolve();
450
+ releaseLockWriter = () => delete zipWriter.lockWriter;
451
+ }
452
+
461
453
  async function requestLockWriter() {
462
454
  const { lockWriter } = zipWriter;
463
455
  if (lockWriter) {
@@ -616,6 +608,7 @@ function getHeaderInfo(options) {
616
608
  } = options;
617
609
  const compressed = level !== 0 && !directory;
618
610
  const encrypted = Boolean(password && getLength(password));
611
+ let version = options.version;
619
612
  let rawExtraFieldAES;
620
613
  if (encrypted && !zipCrypto) {
621
614
  rawExtraFieldAES = new Uint8Array(getLength(EXTRAFIELD_DATA_AES) + 2);
@@ -667,7 +660,6 @@ function getHeaderInfo(options) {
667
660
  if (compressed) {
668
661
  compressionMethod = COMPRESSION_METHOD_DEFLATE;
669
662
  }
670
- let version = options.version || VERSION_DEFLATE;
671
663
  if (zip64) {
672
664
  version = version > VERSION_ZIP64 ? version : VERSION_ZIP64;
673
665
  }
@@ -801,7 +793,7 @@ function setEntryInfo(entryInfo, options) {
801
793
  }
802
794
  }
803
795
 
804
- async function setMissingInfo(fileEntry, entryData, writable, { zipCrypto }) {
796
+ async function writeMissingHeaderInfo(fileEntry, entryData, writable, { zipCrypto }) {
805
797
  const arrayBuffer = await sliceAsArrayBuffer(entryData, 0, 26);
806
798
  const arrayBufferView = new DataView(arrayBuffer);
807
799
  if (!fileEntry.encrypted || zipCrypto) {
@@ -818,7 +810,7 @@ async function setMissingInfo(fileEntry, entryData, writable, { zipCrypto }) {
818
810
  return entryData.slice(arrayBuffer.byteLength);
819
811
  }
820
812
 
821
- function setZip64Info(fileEntry) {
813
+ function setZip64OffsetInfo(fileEntry) {
822
814
  const { rawExtraFieldZip64, offset, diskNumberStart } = fileEntry;
823
815
  const rawExtraFieldZip64View = getDataView(rawExtraFieldZip64);
824
816
  setBigUint64(rawExtraFieldZip64View, 20, BigInt(offset));
@@ -827,10 +819,10 @@ function setZip64Info(fileEntry) {
827
819
 
828
820
  async function closeFile(zipWriter, comment, options) {
829
821
  const { files, writer } = zipWriter;
830
- let offset = 0;
831
- let directoryDataLength = 0;
832
822
  const { diskOffset, writable } = writer;
833
823
  let { diskNumber } = writer;
824
+ let offset = 0;
825
+ let directoryDataLength = 0;
834
826
  let directoryOffset = zipWriter.offset - diskOffset;
835
827
  let filesLength = files.size;
836
828
  for (const [, {
@@ -852,14 +844,6 @@ async function closeFile(zipWriter, comment, options) {
852
844
  rawExtraFieldNTFS,
853
845
  rawExtraField);
854
846
  }
855
- let zip64 = options.zip64 || zipWriter.options.zip64 || false;
856
- if (directoryOffset >= MAX_32_BITS || directoryDataLength >= MAX_32_BITS || filesLength >= MAX_16_BITS) {
857
- if (options.zip64 === false || zipWriter.options.zip64 === false) {
858
- throw new Error(ERR_UNSUPPORTED_FORMAT);
859
- } else {
860
- zip64 = true;
861
- }
862
- }
863
847
  const directoryArray = new Uint8Array(directoryDataLength);
864
848
  const directoryView = getDataView(directoryArray);
865
849
  for (const [indexFileEntry, fileEntry] of Array.from(files.values()).entries()) {
@@ -925,13 +909,21 @@ async function closeFile(zipWriter, comment, options) {
925
909
  }
926
910
  await initStream(writer);
927
911
  await writeData(writable, directoryArray);
928
- const endOfdirectoryArray = new Uint8Array(zip64 ? ZIP64_END_OF_CENTRAL_DIR_TOTAL_LENGTH : END_OF_CENTRAL_DIR_LENGTH);
929
- const endOfdirectoryView = getDataView(endOfdirectoryArray);
930
912
  let lastDiskNumber = writer.diskNumber;
931
913
  const { availableSize } = writer;
932
- if (availableSize < getLength(endOfdirectoryArray)) {
914
+ if (availableSize < END_OF_CENTRAL_DIR_LENGTH) {
933
915
  lastDiskNumber++;
934
916
  }
917
+ let zip64 = getOptionValue(zipWriter, options, "zip64");
918
+ if (directoryOffset >= MAX_32_BITS || directoryDataLength >= MAX_32_BITS || filesLength >= MAX_16_BITS || lastDiskNumber >= MAX_16_BITS) {
919
+ if (zip64 === false) {
920
+ throw new Error(ERR_UNSUPPORTED_FORMAT);
921
+ } else {
922
+ zip64 = true;
923
+ }
924
+ }
925
+ const endOfdirectoryArray = new Uint8Array(zip64 ? ZIP64_END_OF_CENTRAL_DIR_TOTAL_LENGTH : END_OF_CENTRAL_DIR_LENGTH);
926
+ const endOfdirectoryView = getDataView(endOfdirectoryArray);
935
927
  offset = 0;
936
928
  if (zip64) {
937
929
  setUint32(endOfdirectoryView, 0, ZIP64_END_OF_CENTRAL_DIR_SIGNATURE);
@@ -996,8 +988,9 @@ function getTimeNTFS(date) {
996
988
  }
997
989
  }
998
990
 
999
- function getOptionValue(zipWriter, options, name) {
1000
- return options[name] === UNDEFINED_VALUE ? zipWriter.options[name] : options[name];
991
+ function getOptionValue(zipWriter, options, name, defaultValue) {
992
+ const result = options[name] === UNDEFINED_VALUE ? zipWriter.options[name] : options[name];
993
+ return result === UNDEFINED_VALUE ? defaultValue : result;
1001
994
  }
1002
995
 
1003
996
  function getMaximumCompressedSize(uncompressedSize) {
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "A JavaScript library to zip and unzip files in the browser, Deno and Node.js",
4
4
  "author": "Gildas Lormeau",
5
5
  "license": "BSD-3-Clause",
6
- "version": "2.6.43",
6
+ "version": "2.6.44",
7
7
  "type": "module",
8
8
  "keywords": [
9
9
  "zip",
@@ -24,7 +24,7 @@ export { test };
24
24
  async function test() {
25
25
  zip.configure({ chunkSize: 16 * 1024, useWebWorkers: true });
26
26
  const readers = PATHS.map(url => new zip.HttpReader(new URL(url, import.meta.url).href, { preventHeadRequest: true }));
27
- const zipReader = new zip.ZipReader(new zip.SplitZipReader(readers));
27
+ const zipReader = new zip.ZipReader(new zip.SplitDataReader(readers));
28
28
  const entries = await zipReader.getEntries();
29
29
  const results = await Promise.all(UNCOMPRESSED_SIZES.map(async (uncompressedSize, indexEntry) =>
30
30
  (await entries[indexEntry].getData(new zip.TextWriter())).length == uncompressedSize
@@ -0,0 +1,37 @@
1
+ /* global Blob, TextDecoder */
2
+
3
+ import * as zip from "../../index.js";
4
+
5
+ const TEXT_CONTENT = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.";
6
+ const BLOB_CONTENT = new Blob([TEXT_CONTENT]);
7
+
8
+ export { test };
9
+
10
+ const writers = [];
11
+
12
+ function* arrayWriterGenerator() {
13
+ while (true) {
14
+ const writer = new zip.Uint8ArrayWriter();
15
+ writers.push(writer);
16
+ yield writer;
17
+ }
18
+ }
19
+
20
+ async function test() {
21
+ zip.configure({ chunkSize: 1024, useWebWorkers: true });
22
+ const zipWriter = new zip.ZipWriter(new zip.BlobWriter());
23
+ const readers = [
24
+ new zip.TextReader(TEXT_CONTENT),
25
+ new zip.BlobReader(BLOB_CONTENT)
26
+ ];
27
+ await zipWriter.add("loremx2.txt", new zip.SplitDataReader(readers));
28
+ const blob = await zipWriter.close();
29
+ const zipReader = new zip.ZipReader(new zip.BlobReader(blob));
30
+ const firstEntry = (await zipReader.getEntries()).shift();
31
+ await firstEntry.getData(new zip.SplitDataWriter(arrayWriterGenerator(), 128));
32
+ const chunks = await Promise.all(writers.map(writer => writer.getData()));
33
+ const text = new TextDecoder().decode(new Uint8Array(chunks.map(data => Array.from(data)).flat()));
34
+ if (text != TEXT_CONTENT + TEXT_CONTENT) {
35
+ throw new Error();
36
+ }
37
+ }
@@ -20,7 +20,7 @@ function* blobWriterGenerator() {
20
20
 
21
21
  async function test() {
22
22
  zip.configure({ chunkSize: 1024, useWebWorkers: true });
23
- const splitZipWriter = new zip.SplitZipWriter(blobWriterGenerator(), 8192);
23
+ const splitZipWriter = new zip.SplitDataWriter(blobWriterGenerator(), 8192);
24
24
  const zipWriter = new zip.ZipWriter(splitZipWriter);
25
25
  await Promise.all([
26
26
  zipWriter.add("lorem1.txt", new zip.BlobReader(BLOB)),
@@ -29,7 +29,7 @@ async function test() {
29
29
  ]);
30
30
  await zipWriter.close();
31
31
  const readers = await Promise.all(writers.map(async writer => new zip.BlobReader(await writer.getData())));
32
- const zipReader = new zip.ZipReader(new zip.SplitZipReader(readers));
32
+ const zipReader = new zip.ZipReader(new zip.SplitDataReader(readers));
33
33
  const entries = await zipReader.getEntries();
34
34
  const results = await Promise.all(entries.map(async entry => (await entry.getData(new zip.TextWriter())).length == TEXT_CONTENT.length * TEXT_CONTENT_REPEAT));
35
35
  await zipReader.close();
@@ -41,7 +41,8 @@ export default ([
41
41
  { title: "Safe closing", script: "./test-safe-closing.js" },
42
42
  { title: "Service worker", script: "./test-sw.js", env: ["browser"] },
43
43
  { title: "Signature CRC32", script: "./test-crc.js" },
44
- { title: "Split file", script: "./test-split-zip.js" },
44
+ { title: "Split data", script: "./test-split-data.js" },
45
+ { title: "Split zip file", script: "./test-split-zip.js" },
45
46
  { title: "Store", script: "./test-store.js" },
46
47
  { title: "Streams", script: "./test-streams.js" },
47
48
  { title: "Worker timeout", script: "./test-worker-timeout.js" },