@loaders.gl/zip 4.0.0-beta.8 → 4.0.1

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/dist/dist.dev.js CHANGED
@@ -7478,6 +7478,7 @@ var __exports__ = (() => {
7478
7478
  var CD_UNCOMPRESSED_SIZE_OFFSET = 24n;
7479
7479
  var CD_FILE_NAME_LENGTH_OFFSET = 28n;
7480
7480
  var CD_EXTRA_FIELD_LENGTH_OFFSET = 30n;
7481
+ var CD_START_DISK_OFFSET = 32n;
7481
7482
  var CD_LOCAL_HEADER_OFFSET_OFFSET = 42n;
7482
7483
  var CD_FILE_NAME_OFFSET = 46n;
7483
7484
  var signature = new Uint8Array([80, 75, 1, 2]);
@@ -7486,36 +7487,31 @@ var __exports__ = (() => {
7486
7487
  if (!compareArrayBuffers(magicBytes, signature.buffer)) {
7487
7488
  return null;
7488
7489
  }
7489
- let compressedSize = BigInt(await file.getUint32(headerOffset + CD_COMPRESSED_SIZE_OFFSET));
7490
- let uncompressedSize = BigInt(await file.getUint32(headerOffset + CD_UNCOMPRESSED_SIZE_OFFSET));
7490
+ const compressedSize = BigInt(await file.getUint32(headerOffset + CD_COMPRESSED_SIZE_OFFSET));
7491
+ const uncompressedSize = BigInt(await file.getUint32(headerOffset + CD_UNCOMPRESSED_SIZE_OFFSET));
7491
7492
  const extraFieldLength = await file.getUint16(headerOffset + CD_EXTRA_FIELD_LENGTH_OFFSET);
7493
+ const startDisk = BigInt(await file.getUint16(headerOffset + CD_START_DISK_OFFSET));
7492
7494
  const fileNameLength = await file.getUint16(headerOffset + CD_FILE_NAME_LENGTH_OFFSET);
7493
7495
  const filenameBytes = await file.slice(headerOffset + CD_FILE_NAME_OFFSET, headerOffset + CD_FILE_NAME_OFFSET + BigInt(fileNameLength));
7494
7496
  const fileName = new TextDecoder().decode(filenameBytes);
7495
7497
  const extraOffset = headerOffset + CD_FILE_NAME_OFFSET + BigInt(fileNameLength);
7496
7498
  const oldFormatOffset = await file.getUint32(headerOffset + CD_LOCAL_HEADER_OFFSET_OFFSET);
7497
- let fileDataOffset = BigInt(oldFormatOffset);
7498
- let offsetInZip64Data = 4n;
7499
- if (uncompressedSize === BigInt(4294967295)) {
7500
- uncompressedSize = await file.getBigUint64(extraOffset + offsetInZip64Data);
7501
- offsetInZip64Data += 8n;
7502
- }
7503
- if (compressedSize === BigInt(4294967295)) {
7504
- compressedSize = await file.getBigUint64(extraOffset + offsetInZip64Data);
7505
- offsetInZip64Data += 8n;
7506
- }
7507
- if (fileDataOffset === BigInt(4294967295)) {
7508
- fileDataOffset = await file.getBigUint64(extraOffset + offsetInZip64Data);
7509
- }
7510
- const localHeaderOffset = fileDataOffset;
7511
- return {
7512
- compressedSize,
7499
+ const localHeaderOffset = BigInt(oldFormatOffset);
7500
+ const extraField = new DataView(await file.slice(extraOffset, extraOffset + BigInt(extraFieldLength)));
7501
+ const zip64data = {
7513
7502
  uncompressedSize,
7503
+ compressedSize,
7504
+ localHeaderOffset,
7505
+ startDisk
7506
+ };
7507
+ const res = findZip64DataInExtra(zip64data, extraField);
7508
+ return {
7509
+ ...zip64data,
7510
+ ...res,
7514
7511
  extraFieldLength,
7515
7512
  fileNameLength,
7516
7513
  fileName,
7517
- extraOffset,
7518
- localHeaderOffset
7514
+ extraOffset
7519
7515
  };
7520
7516
  };
7521
7517
  async function* makeZipCDHeaderIterator(fileProvider) {
@@ -7528,6 +7524,52 @@ var __exports__ = (() => {
7528
7524
  cdHeader = await parseZipCDFileHeader(cdHeader.extraOffset + BigInt(cdHeader.extraFieldLength), fileProvider);
7529
7525
  }
7530
7526
  }
7527
+ var getUint16 = (...bytes) => {
7528
+ return bytes[0] + bytes[1] * 16;
7529
+ };
7530
+ var findZip64DataInExtra = (zip64data, extraField) => {
7531
+ const zip64dataList = findExpectedData(zip64data);
7532
+ const zip64DataRes = {};
7533
+ if (zip64dataList.length > 0) {
7534
+ const zip64chunkSize = zip64dataList.reduce((sum, curr) => sum + curr.length, 0);
7535
+ const offsetInExtraData = new Uint8Array(extraField.buffer).findIndex((_val, i, arr) => getUint16(arr[i], arr[i + 1]) === 1 && getUint16(arr[i + 2], arr[i + 3]) === zip64chunkSize);
7536
+ let bytesRead = 0;
7537
+ for (const note of zip64dataList) {
7538
+ const offset = bytesRead;
7539
+ zip64DataRes[note.name] = extraField.getBigUint64(offsetInExtraData + 4 + offset, true);
7540
+ bytesRead = offset + note.length;
7541
+ }
7542
+ }
7543
+ return zip64DataRes;
7544
+ };
7545
+ var findExpectedData = (zip64data) => {
7546
+ const zip64dataList = [];
7547
+ if (zip64data.uncompressedSize === BigInt(4294967295)) {
7548
+ zip64dataList.push({
7549
+ name: "uncompressedSize",
7550
+ length: 8
7551
+ });
7552
+ }
7553
+ if (zip64data.compressedSize === BigInt(4294967295)) {
7554
+ zip64dataList.push({
7555
+ name: "compressedSize",
7556
+ length: 8
7557
+ });
7558
+ }
7559
+ if (zip64data.localHeaderOffset === BigInt(4294967295)) {
7560
+ zip64dataList.push({
7561
+ name: "localHeaderOffset",
7562
+ length: 8
7563
+ });
7564
+ }
7565
+ if (zip64data.startDisk === BigInt(4294967295)) {
7566
+ zip64dataList.push({
7567
+ name: "startDisk",
7568
+ length: 4
7569
+ });
7570
+ }
7571
+ return zip64dataList;
7572
+ };
7531
7573
 
7532
7574
  // src/parse-zip/local-file-header.ts
7533
7575
  var COMPRESSION_METHOD_OFFSET = 8n;
package/dist/index.cjs CHANGED
@@ -401,6 +401,7 @@ var CD_COMPRESSED_SIZE_OFFSET = 20n;
401
401
  var CD_UNCOMPRESSED_SIZE_OFFSET = 24n;
402
402
  var CD_FILE_NAME_LENGTH_OFFSET = 28n;
403
403
  var CD_EXTRA_FIELD_LENGTH_OFFSET = 30n;
404
+ var CD_START_DISK_OFFSET = 32n;
404
405
  var CD_LOCAL_HEADER_OFFSET_OFFSET = 42n;
405
406
  var CD_FILE_NAME_OFFSET = 46n;
406
407
  var signature = new Uint8Array([80, 75, 1, 2]);
@@ -409,9 +410,10 @@ var parseZipCDFileHeader = async (headerOffset, file) => {
409
410
  if (!(0, import_loader_utils2.compareArrayBuffers)(magicBytes, signature.buffer)) {
410
411
  return null;
411
412
  }
412
- let compressedSize = BigInt(await file.getUint32(headerOffset + CD_COMPRESSED_SIZE_OFFSET));
413
- let uncompressedSize = BigInt(await file.getUint32(headerOffset + CD_UNCOMPRESSED_SIZE_OFFSET));
413
+ const compressedSize = BigInt(await file.getUint32(headerOffset + CD_COMPRESSED_SIZE_OFFSET));
414
+ const uncompressedSize = BigInt(await file.getUint32(headerOffset + CD_UNCOMPRESSED_SIZE_OFFSET));
414
415
  const extraFieldLength = await file.getUint16(headerOffset + CD_EXTRA_FIELD_LENGTH_OFFSET);
416
+ const startDisk = BigInt(await file.getUint16(headerOffset + CD_START_DISK_OFFSET));
415
417
  const fileNameLength = await file.getUint16(headerOffset + CD_FILE_NAME_LENGTH_OFFSET);
416
418
  const filenameBytes = await file.slice(
417
419
  headerOffset + CD_FILE_NAME_OFFSET,
@@ -420,28 +422,24 @@ var parseZipCDFileHeader = async (headerOffset, file) => {
420
422
  const fileName = new TextDecoder().decode(filenameBytes);
421
423
  const extraOffset = headerOffset + CD_FILE_NAME_OFFSET + BigInt(fileNameLength);
422
424
  const oldFormatOffset = await file.getUint32(headerOffset + CD_LOCAL_HEADER_OFFSET_OFFSET);
423
- let fileDataOffset = BigInt(oldFormatOffset);
424
- let offsetInZip64Data = 4n;
425
- if (uncompressedSize === BigInt(4294967295)) {
426
- uncompressedSize = await file.getBigUint64(extraOffset + offsetInZip64Data);
427
- offsetInZip64Data += 8n;
428
- }
429
- if (compressedSize === BigInt(4294967295)) {
430
- compressedSize = await file.getBigUint64(extraOffset + offsetInZip64Data);
431
- offsetInZip64Data += 8n;
432
- }
433
- if (fileDataOffset === BigInt(4294967295)) {
434
- fileDataOffset = await file.getBigUint64(extraOffset + offsetInZip64Data);
435
- }
436
- const localHeaderOffset = fileDataOffset;
437
- return {
438
- compressedSize,
425
+ const localHeaderOffset = BigInt(oldFormatOffset);
426
+ const extraField = new DataView(
427
+ await file.slice(extraOffset, extraOffset + BigInt(extraFieldLength))
428
+ );
429
+ const zip64data = {
439
430
  uncompressedSize,
431
+ compressedSize,
432
+ localHeaderOffset,
433
+ startDisk
434
+ };
435
+ const res = findZip64DataInExtra(zip64data, extraField);
436
+ return {
437
+ ...zip64data,
438
+ ...res,
440
439
  extraFieldLength,
441
440
  fileNameLength,
442
441
  fileName,
443
- extraOffset,
444
- localHeaderOffset
442
+ extraOffset
445
443
  };
446
444
  };
447
445
  async function* makeZipCDHeaderIterator(fileProvider) {
@@ -455,6 +453,42 @@ async function* makeZipCDHeaderIterator(fileProvider) {
455
453
  );
456
454
  }
457
455
  }
456
+ var getUint16 = (...bytes) => {
457
+ return bytes[0] + bytes[1] * 16;
458
+ };
459
+ var findZip64DataInExtra = (zip64data, extraField) => {
460
+ const zip64dataList = findExpectedData(zip64data);
461
+ const zip64DataRes = {};
462
+ if (zip64dataList.length > 0) {
463
+ const zip64chunkSize = zip64dataList.reduce((sum, curr) => sum + curr.length, 0);
464
+ const offsetInExtraData = new Uint8Array(extraField.buffer).findIndex(
465
+ (_val, i, arr) => getUint16(arr[i], arr[i + 1]) === 1 && getUint16(arr[i + 2], arr[i + 3]) === zip64chunkSize
466
+ );
467
+ let bytesRead = 0;
468
+ for (const note of zip64dataList) {
469
+ const offset = bytesRead;
470
+ zip64DataRes[note.name] = extraField.getBigUint64(offsetInExtraData + 4 + offset, true);
471
+ bytesRead = offset + note.length;
472
+ }
473
+ }
474
+ return zip64DataRes;
475
+ };
476
+ var findExpectedData = (zip64data) => {
477
+ const zip64dataList = [];
478
+ if (zip64data.uncompressedSize === BigInt(4294967295)) {
479
+ zip64dataList.push({ name: "uncompressedSize", length: 8 });
480
+ }
481
+ if (zip64data.compressedSize === BigInt(4294967295)) {
482
+ zip64dataList.push({ name: "compressedSize", length: 8 });
483
+ }
484
+ if (zip64data.localHeaderOffset === BigInt(4294967295)) {
485
+ zip64dataList.push({ name: "localHeaderOffset", length: 8 });
486
+ }
487
+ if (zip64data.startDisk === BigInt(4294967295)) {
488
+ zip64dataList.push({ name: "startDisk", length: 4 });
489
+ }
490
+ return zip64dataList;
491
+ };
458
492
 
459
493
  // src/parse-zip/local-file-header.ts
460
494
  var import_loader_utils3 = require("@loaders.gl/loader-utils");
@@ -1 +1 @@
1
- {"version":3,"file":"cd-file-header.d.ts","sourceRoot":"","sources":["../../src/parse-zip/cd-file-header.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAsB,MAAM,0BAA0B,CAAC;AAE3E,OAAO,EAAC,YAAY,EAAC,MAAM,uBAAuB,CAAC;AAEnD;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,sBAAsB;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,wBAAwB;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,uBAAuB;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,uBAAuB;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,yBAAyB;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,2CAA2C;IAC3C,iBAAiB,EAAE,MAAM,CAAC;CAC3B,CAAC;AAUF,eAAO,MAAM,SAAS,EAAE,YAAuD,CAAC;AAEhF;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,iBACjB,MAAM,QACd,YAAY,KACjB,QAAQ,eAAe,GAAG,IAAI,CA4ChC,CAAC;AAEF;;;GAGG;AACH,wBAAuB,uBAAuB,CAC5C,YAAY,EAAE,YAAY,GACzB,aAAa,CAAC,eAAe,CAAC,CAUhC"}
1
+ {"version":3,"file":"cd-file-header.d.ts","sourceRoot":"","sources":["../../src/parse-zip/cd-file-header.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAsB,MAAM,0BAA0B,CAAC;AAE3E,OAAO,EAAC,YAAY,EAAC,MAAM,uBAAuB,CAAC;AAEnD;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,sBAAsB;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,wBAAwB;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,uBAAuB;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,uBAAuB;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,yBAAyB;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,2CAA2C;IAC3C,iBAAiB,EAAE,MAAM,CAAC;CAC3B,CAAC;AAyBF,eAAO,MAAM,SAAS,EAAE,YAAuD,CAAC;AAEhF;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,iBACjB,MAAM,QACd,YAAY,KACjB,QAAQ,eAAe,GAAG,IAAI,CA2ChC,CAAC;AAEF;;;GAGG;AACH,wBAAuB,uBAAuB,CAC5C,YAAY,EAAE,YAAY,GACzB,aAAa,CAAC,eAAe,CAAC,CAUhC"}
@@ -4,6 +4,7 @@ const CD_COMPRESSED_SIZE_OFFSET = 20n;
4
4
  const CD_UNCOMPRESSED_SIZE_OFFSET = 24n;
5
5
  const CD_FILE_NAME_LENGTH_OFFSET = 28n;
6
6
  const CD_EXTRA_FIELD_LENGTH_OFFSET = 30n;
7
+ const CD_START_DISK_OFFSET = 32n;
7
8
  const CD_LOCAL_HEADER_OFFSET_OFFSET = 42n;
8
9
  const CD_FILE_NAME_OFFSET = 46n;
9
10
  export const signature = new Uint8Array([0x50, 0x4b, 0x01, 0x02]);
@@ -12,36 +13,31 @@ export const parseZipCDFileHeader = async (headerOffset, file) => {
12
13
  if (!compareArrayBuffers(magicBytes, signature.buffer)) {
13
14
  return null;
14
15
  }
15
- let compressedSize = BigInt(await file.getUint32(headerOffset + CD_COMPRESSED_SIZE_OFFSET));
16
- let uncompressedSize = BigInt(await file.getUint32(headerOffset + CD_UNCOMPRESSED_SIZE_OFFSET));
16
+ const compressedSize = BigInt(await file.getUint32(headerOffset + CD_COMPRESSED_SIZE_OFFSET));
17
+ const uncompressedSize = BigInt(await file.getUint32(headerOffset + CD_UNCOMPRESSED_SIZE_OFFSET));
17
18
  const extraFieldLength = await file.getUint16(headerOffset + CD_EXTRA_FIELD_LENGTH_OFFSET);
19
+ const startDisk = BigInt(await file.getUint16(headerOffset + CD_START_DISK_OFFSET));
18
20
  const fileNameLength = await file.getUint16(headerOffset + CD_FILE_NAME_LENGTH_OFFSET);
19
21
  const filenameBytes = await file.slice(headerOffset + CD_FILE_NAME_OFFSET, headerOffset + CD_FILE_NAME_OFFSET + BigInt(fileNameLength));
20
22
  const fileName = new TextDecoder().decode(filenameBytes);
21
23
  const extraOffset = headerOffset + CD_FILE_NAME_OFFSET + BigInt(fileNameLength);
22
24
  const oldFormatOffset = await file.getUint32(headerOffset + CD_LOCAL_HEADER_OFFSET_OFFSET);
23
- let fileDataOffset = BigInt(oldFormatOffset);
24
- let offsetInZip64Data = 4n;
25
- if (uncompressedSize === BigInt(0xffffffff)) {
26
- uncompressedSize = await file.getBigUint64(extraOffset + offsetInZip64Data);
27
- offsetInZip64Data += 8n;
28
- }
29
- if (compressedSize === BigInt(0xffffffff)) {
30
- compressedSize = await file.getBigUint64(extraOffset + offsetInZip64Data);
31
- offsetInZip64Data += 8n;
32
- }
33
- if (fileDataOffset === BigInt(0xffffffff)) {
34
- fileDataOffset = await file.getBigUint64(extraOffset + offsetInZip64Data);
35
- }
36
- const localHeaderOffset = fileDataOffset;
37
- return {
38
- compressedSize,
25
+ const localHeaderOffset = BigInt(oldFormatOffset);
26
+ const extraField = new DataView(await file.slice(extraOffset, extraOffset + BigInt(extraFieldLength)));
27
+ const zip64data = {
39
28
  uncompressedSize,
29
+ compressedSize,
30
+ localHeaderOffset,
31
+ startDisk
32
+ };
33
+ const res = findZip64DataInExtra(zip64data, extraField);
34
+ return {
35
+ ...zip64data,
36
+ ...res,
40
37
  extraFieldLength,
41
38
  fileNameLength,
42
39
  fileName,
43
- extraOffset,
44
- localHeaderOffset
40
+ extraOffset
45
41
  };
46
42
  };
47
43
  export async function* makeZipCDHeaderIterator(fileProvider) {
@@ -54,4 +50,50 @@ export async function* makeZipCDHeaderIterator(fileProvider) {
54
50
  cdHeader = await parseZipCDFileHeader(cdHeader.extraOffset + BigInt(cdHeader.extraFieldLength), fileProvider);
55
51
  }
56
52
  }
53
+ const getUint16 = function () {
54
+ return (arguments.length <= 0 ? undefined : arguments[0]) + (arguments.length <= 1 ? undefined : arguments[1]) * 16;
55
+ };
56
+ const findZip64DataInExtra = (zip64data, extraField) => {
57
+ const zip64dataList = findExpectedData(zip64data);
58
+ const zip64DataRes = {};
59
+ if (zip64dataList.length > 0) {
60
+ const zip64chunkSize = zip64dataList.reduce((sum, curr) => sum + curr.length, 0);
61
+ const offsetInExtraData = new Uint8Array(extraField.buffer).findIndex((_val, i, arr) => getUint16(arr[i], arr[i + 1]) === 0x0001 && getUint16(arr[i + 2], arr[i + 3]) === zip64chunkSize);
62
+ let bytesRead = 0;
63
+ for (const note of zip64dataList) {
64
+ const offset = bytesRead;
65
+ zip64DataRes[note.name] = extraField.getBigUint64(offsetInExtraData + 4 + offset, true);
66
+ bytesRead = offset + note.length;
67
+ }
68
+ }
69
+ return zip64DataRes;
70
+ };
71
+ const findExpectedData = zip64data => {
72
+ const zip64dataList = [];
73
+ if (zip64data.uncompressedSize === BigInt(0xffffffff)) {
74
+ zip64dataList.push({
75
+ name: 'uncompressedSize',
76
+ length: 8
77
+ });
78
+ }
79
+ if (zip64data.compressedSize === BigInt(0xffffffff)) {
80
+ zip64dataList.push({
81
+ name: 'compressedSize',
82
+ length: 8
83
+ });
84
+ }
85
+ if (zip64data.localHeaderOffset === BigInt(0xffffffff)) {
86
+ zip64dataList.push({
87
+ name: 'localHeaderOffset',
88
+ length: 8
89
+ });
90
+ }
91
+ if (zip64data.startDisk === BigInt(0xffffffff)) {
92
+ zip64dataList.push({
93
+ name: 'startDisk',
94
+ length: 4
95
+ });
96
+ }
97
+ return zip64dataList;
98
+ };
57
99
  //# sourceMappingURL=cd-file-header.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cd-file-header.js","names":["compareArrayBuffers","parseEoCDRecord","CD_COMPRESSED_SIZE_OFFSET","CD_UNCOMPRESSED_SIZE_OFFSET","CD_FILE_NAME_LENGTH_OFFSET","CD_EXTRA_FIELD_LENGTH_OFFSET","CD_LOCAL_HEADER_OFFSET_OFFSET","CD_FILE_NAME_OFFSET","signature","Uint8Array","parseZipCDFileHeader","headerOffset","file","magicBytes","slice","buffer","compressedSize","BigInt","getUint32","uncompressedSize","extraFieldLength","getUint16","fileNameLength","filenameBytes","fileName","TextDecoder","decode","extraOffset","oldFormatOffset","fileDataOffset","offsetInZip64Data","getBigUint64","localHeaderOffset","makeZipCDHeaderIterator","fileProvider","cdStartOffset","cdHeader"],"sources":["../../src/parse-zip/cd-file-header.ts"],"sourcesContent":["import {FileProvider, compareArrayBuffers} from '@loaders.gl/loader-utils';\nimport {parseEoCDRecord} from './end-of-central-directory';\nimport {ZipSignature} from './search-from-the-end';\n\n/**\n * zip central directory file header info\n * according to https://en.wikipedia.org/wiki/ZIP_(file_format)\n */\nexport type ZipCDFileHeader = {\n /** Compressed size */\n compressedSize: bigint;\n /** Uncompressed size */\n uncompressedSize: bigint;\n /** Extra field size */\n extraFieldLength: number;\n /** File name length */\n fileNameLength: number;\n /** File name */\n fileName: string;\n /** Extra field offset */\n extraOffset: bigint;\n /** Relative offset of local file header */\n localHeaderOffset: bigint;\n};\n\n// offsets accroding to https://en.wikipedia.org/wiki/ZIP_(file_format)\nconst CD_COMPRESSED_SIZE_OFFSET = 20n;\nconst CD_UNCOMPRESSED_SIZE_OFFSET = 24n;\nconst CD_FILE_NAME_LENGTH_OFFSET = 28n;\nconst CD_EXTRA_FIELD_LENGTH_OFFSET = 30n;\nconst CD_LOCAL_HEADER_OFFSET_OFFSET = 42n;\nconst CD_FILE_NAME_OFFSET = 46n;\n\nexport const signature: ZipSignature = new Uint8Array([0x50, 0x4b, 0x01, 0x02]);\n\n/**\n * Parses central directory file header of zip file\n * @param headerOffset - offset in the archive where header starts\n * @param buffer - buffer containing whole array\n * @returns Info from the header\n */\nexport const parseZipCDFileHeader = async (\n headerOffset: bigint,\n file: FileProvider\n): Promise<ZipCDFileHeader | null> => {\n const magicBytes = await file.slice(headerOffset, headerOffset + 4n);\n if (!compareArrayBuffers(magicBytes, signature.buffer)) {\n return null;\n }\n\n let compressedSize = BigInt(await file.getUint32(headerOffset + CD_COMPRESSED_SIZE_OFFSET));\n let uncompressedSize = BigInt(await file.getUint32(headerOffset + CD_UNCOMPRESSED_SIZE_OFFSET));\n const extraFieldLength = await file.getUint16(headerOffset + CD_EXTRA_FIELD_LENGTH_OFFSET);\n const fileNameLength = await file.getUint16(headerOffset + CD_FILE_NAME_LENGTH_OFFSET);\n const filenameBytes = await file.slice(\n headerOffset + CD_FILE_NAME_OFFSET,\n headerOffset + CD_FILE_NAME_OFFSET + BigInt(fileNameLength)\n );\n const fileName = new TextDecoder().decode(filenameBytes);\n\n const extraOffset = headerOffset + CD_FILE_NAME_OFFSET + BigInt(fileNameLength);\n const oldFormatOffset = await file.getUint32(headerOffset + CD_LOCAL_HEADER_OFFSET_OFFSET);\n\n let fileDataOffset = BigInt(oldFormatOffset);\n let offsetInZip64Data = 4n;\n // looking for info that might be also be in zip64 extra field\n if (uncompressedSize === BigInt(0xffffffff)) {\n uncompressedSize = await file.getBigUint64(extraOffset + offsetInZip64Data);\n offsetInZip64Data += 8n;\n }\n if (compressedSize === BigInt(0xffffffff)) {\n compressedSize = await file.getBigUint64(extraOffset + offsetInZip64Data);\n offsetInZip64Data += 8n;\n }\n if (fileDataOffset === BigInt(0xffffffff)) {\n fileDataOffset = await file.getBigUint64(extraOffset + offsetInZip64Data); // setting it to the one from zip64\n }\n const localHeaderOffset = fileDataOffset;\n\n return {\n compressedSize,\n uncompressedSize,\n extraFieldLength,\n fileNameLength,\n fileName,\n extraOffset,\n localHeaderOffset\n };\n};\n\n/**\n * Create iterator over files of zip archive\n * @param fileProvider - file provider that provider random access to the file\n */\nexport async function* makeZipCDHeaderIterator(\n fileProvider: FileProvider\n): AsyncIterable<ZipCDFileHeader> {\n const {cdStartOffset} = await parseEoCDRecord(fileProvider);\n let cdHeader = await parseZipCDFileHeader(cdStartOffset, fileProvider);\n while (cdHeader) {\n yield cdHeader;\n cdHeader = await parseZipCDFileHeader(\n cdHeader.extraOffset + BigInt(cdHeader.extraFieldLength),\n fileProvider\n );\n }\n}\n"],"mappings":"AAAA,SAAsBA,mBAAmB,QAAO,0BAA0B;AAAC,SACnEC,eAAe;AAyBvB,MAAMC,yBAAyB,GAAG,GAAG;AACrC,MAAMC,2BAA2B,GAAG,GAAG;AACvC,MAAMC,0BAA0B,GAAG,GAAG;AACtC,MAAMC,4BAA4B,GAAG,GAAG;AACxC,MAAMC,6BAA6B,GAAG,GAAG;AACzC,MAAMC,mBAAmB,GAAG,GAAG;AAE/B,OAAO,MAAMC,SAAuB,GAAG,IAAIC,UAAU,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAQ/E,OAAO,MAAMC,oBAAoB,GAAG,MAAAA,CAClCC,YAAoB,EACpBC,IAAkB,KACkB;EACpC,MAAMC,UAAU,GAAG,MAAMD,IAAI,CAACE,KAAK,CAACH,YAAY,EAAEA,YAAY,GAAG,EAAE,CAAC;EACpE,IAAI,CAACX,mBAAmB,CAACa,UAAU,EAAEL,SAAS,CAACO,MAAM,CAAC,EAAE;IACtD,OAAO,IAAI;EACb;EAEA,IAAIC,cAAc,GAAGC,MAAM,CAAC,MAAML,IAAI,CAACM,SAAS,CAACP,YAAY,GAAGT,yBAAyB,CAAC,CAAC;EAC3F,IAAIiB,gBAAgB,GAAGF,MAAM,CAAC,MAAML,IAAI,CAACM,SAAS,CAACP,YAAY,GAAGR,2BAA2B,CAAC,CAAC;EAC/F,MAAMiB,gBAAgB,GAAG,MAAMR,IAAI,CAACS,SAAS,CAACV,YAAY,GAAGN,4BAA4B,CAAC;EAC1F,MAAMiB,cAAc,GAAG,MAAMV,IAAI,CAACS,SAAS,CAACV,YAAY,GAAGP,0BAA0B,CAAC;EACtF,MAAMmB,aAAa,GAAG,MAAMX,IAAI,CAACE,KAAK,CACpCH,YAAY,GAAGJ,mBAAmB,EAClCI,YAAY,GAAGJ,mBAAmB,GAAGU,MAAM,CAACK,cAAc,CAC5D,CAAC;EACD,MAAME,QAAQ,GAAG,IAAIC,WAAW,CAAC,CAAC,CAACC,MAAM,CAACH,aAAa,CAAC;EAExD,MAAMI,WAAW,GAAGhB,YAAY,GAAGJ,mBAAmB,GAAGU,MAAM,CAACK,cAAc,CAAC;EAC/E,MAAMM,eAAe,GAAG,MAAMhB,IAAI,CAACM,SAAS,CAACP,YAAY,GAAGL,6BAA6B,CAAC;EAE1F,IAAIuB,cAAc,GAAGZ,MAAM,CAACW,eAAe,CAAC;EAC5C,IAAIE,iBAAiB,GAAG,EAAE;EAE1B,IAAIX,gBAAgB,KAAKF,MAAM,CAAC,UAAU,CAAC,EAAE;IAC3CE,gBAAgB,GAAG,MAAMP,IAAI,CAACmB,YAAY,CAACJ,WAAW,GAAGG,iBAAiB,CAAC;IAC3EA,iBAAiB,IAAI,EAAE;EACzB;EACA,IAAId,cAAc,KAAKC,MAAM,CAAC,UAAU,CAAC,EAAE;IACzCD,cAAc,GAAG,MAAMJ,IAAI,CAACmB,YAAY,CAACJ,WAAW,GAAGG,iBAAiB,CAAC;IACzEA,iBAAiB,IAAI,EAAE;EACzB;EACA,IAAID,cAAc,KAAKZ,MAAM,CAAC,UAAU,CAAC,EAAE;IACzCY,cAAc,GAAG,MAAMjB,IAAI,CAACmB,YAAY,CAACJ,WAAW,GAAGG,iBAAiB,CAAC;EAC3E;EACA,MAAME,iBAAiB,GAAGH,cAAc;EAExC,OAAO;IACLb,cAAc;IACdG,gBAAgB;IAChBC,gBAAgB;IAChBE,cAAc;IACdE,QAAQ;IACRG,WAAW;IACXK;EACF,CAAC;AACH,CAAC;AAMD,OAAO,gBAAgBC,uBAAuBA,CAC5CC,YAA0B,EACM;EAChC,MAAM;IAACC;EAAa,CAAC,GAAG,MAAMlC,eAAe,CAACiC,YAAY,CAAC;EAC3D,IAAIE,QAAQ,GAAG,MAAM1B,oBAAoB,CAACyB,aAAa,EAAED,YAAY,CAAC;EACtE,OAAOE,QAAQ,EAAE;IACf,MAAMA,QAAQ;IACdA,QAAQ,GAAG,MAAM1B,oBAAoB,CACnC0B,QAAQ,CAACT,WAAW,GAAGV,MAAM,CAACmB,QAAQ,CAAChB,gBAAgB,CAAC,EACxDc,YACF,CAAC;EACH;AACF"}
1
+ {"version":3,"file":"cd-file-header.js","names":["compareArrayBuffers","parseEoCDRecord","CD_COMPRESSED_SIZE_OFFSET","CD_UNCOMPRESSED_SIZE_OFFSET","CD_FILE_NAME_LENGTH_OFFSET","CD_EXTRA_FIELD_LENGTH_OFFSET","CD_START_DISK_OFFSET","CD_LOCAL_HEADER_OFFSET_OFFSET","CD_FILE_NAME_OFFSET","signature","Uint8Array","parseZipCDFileHeader","headerOffset","file","magicBytes","slice","buffer","compressedSize","BigInt","getUint32","uncompressedSize","extraFieldLength","getUint16","startDisk","fileNameLength","filenameBytes","fileName","TextDecoder","decode","extraOffset","oldFormatOffset","localHeaderOffset","extraField","DataView","zip64data","res","findZip64DataInExtra","makeZipCDHeaderIterator","fileProvider","cdStartOffset","cdHeader","arguments","length","undefined","zip64dataList","findExpectedData","zip64DataRes","zip64chunkSize","reduce","sum","curr","offsetInExtraData","findIndex","_val","i","arr","bytesRead","note","offset","name","getBigUint64","push"],"sources":["../../src/parse-zip/cd-file-header.ts"],"sourcesContent":["import {FileProvider, compareArrayBuffers} from '@loaders.gl/loader-utils';\nimport {parseEoCDRecord} from './end-of-central-directory';\nimport {ZipSignature} from './search-from-the-end';\n\n/**\n * zip central directory file header info\n * according to https://en.wikipedia.org/wiki/ZIP_(file_format)\n */\nexport type ZipCDFileHeader = {\n /** Compressed size */\n compressedSize: bigint;\n /** Uncompressed size */\n uncompressedSize: bigint;\n /** Extra field size */\n extraFieldLength: number;\n /** File name length */\n fileNameLength: number;\n /** File name */\n fileName: string;\n /** Extra field offset */\n extraOffset: bigint;\n /** Relative offset of local file header */\n localHeaderOffset: bigint;\n};\n\n/**\n * Data that might be in Zip64 notation inside extra data\n */\ntype Zip64Data = {\n /** Uncompressed size */\n uncompressedSize: bigint;\n /** Compressed size */\n compressedSize: bigint;\n /** Relative offset of local file header */\n localHeaderOffset: bigint;\n /** Start disk */\n startDisk: bigint;\n};\n\n// offsets accroding to https://en.wikipedia.org/wiki/ZIP_(file_format)\nconst CD_COMPRESSED_SIZE_OFFSET = 20n;\nconst CD_UNCOMPRESSED_SIZE_OFFSET = 24n;\nconst CD_FILE_NAME_LENGTH_OFFSET = 28n;\nconst CD_EXTRA_FIELD_LENGTH_OFFSET = 30n;\nconst CD_START_DISK_OFFSET = 32n;\nconst CD_LOCAL_HEADER_OFFSET_OFFSET = 42n;\nconst CD_FILE_NAME_OFFSET = 46n;\n\nexport const signature: ZipSignature = new Uint8Array([0x50, 0x4b, 0x01, 0x02]);\n\n/**\n * Parses central directory file header of zip file\n * @param headerOffset - offset in the archive where header starts\n * @param buffer - buffer containing whole array\n * @returns Info from the header\n */\nexport const parseZipCDFileHeader = async (\n headerOffset: bigint,\n file: FileProvider\n): Promise<ZipCDFileHeader | null> => {\n const magicBytes = await file.slice(headerOffset, headerOffset + 4n);\n if (!compareArrayBuffers(magicBytes, signature.buffer)) {\n return null;\n }\n\n const compressedSize = BigInt(await file.getUint32(headerOffset + CD_COMPRESSED_SIZE_OFFSET));\n const uncompressedSize = BigInt(await file.getUint32(headerOffset + CD_UNCOMPRESSED_SIZE_OFFSET));\n const extraFieldLength = await file.getUint16(headerOffset + CD_EXTRA_FIELD_LENGTH_OFFSET);\n const startDisk = BigInt(await file.getUint16(headerOffset + CD_START_DISK_OFFSET));\n const fileNameLength = await file.getUint16(headerOffset + CD_FILE_NAME_LENGTH_OFFSET);\n const filenameBytes = await file.slice(\n headerOffset + CD_FILE_NAME_OFFSET,\n headerOffset + CD_FILE_NAME_OFFSET + BigInt(fileNameLength)\n );\n const fileName = new TextDecoder().decode(filenameBytes);\n\n const extraOffset = headerOffset + CD_FILE_NAME_OFFSET + BigInt(fileNameLength);\n const oldFormatOffset = await file.getUint32(headerOffset + CD_LOCAL_HEADER_OFFSET_OFFSET);\n\n const localHeaderOffset = BigInt(oldFormatOffset);\n const extraField = new DataView(\n await file.slice(extraOffset, extraOffset + BigInt(extraFieldLength))\n );\n // looking for info that might be also be in zip64 extra field\n\n const zip64data: Zip64Data = {\n uncompressedSize,\n compressedSize,\n localHeaderOffset,\n startDisk\n };\n\n const res = findZip64DataInExtra(zip64data, extraField);\n\n return {\n ...zip64data,\n ...res,\n extraFieldLength,\n fileNameLength,\n fileName,\n extraOffset\n };\n};\n\n/**\n * Create iterator over files of zip archive\n * @param fileProvider - file provider that provider random access to the file\n */\nexport async function* makeZipCDHeaderIterator(\n fileProvider: FileProvider\n): AsyncIterable<ZipCDFileHeader> {\n const {cdStartOffset} = await parseEoCDRecord(fileProvider);\n let cdHeader = await parseZipCDFileHeader(cdStartOffset, fileProvider);\n while (cdHeader) {\n yield cdHeader;\n cdHeader = await parseZipCDFileHeader(\n cdHeader.extraOffset + BigInt(cdHeader.extraFieldLength),\n fileProvider\n );\n }\n}\n/**\n * returns the number written in the provided bytes\n * @param bytes two bytes containing the number\n * @returns the number written in the provided bytes\n */\nconst getUint16 = (...bytes: [number, number]) => {\n return bytes[0] + bytes[1] * 16;\n};\n\n/**\n * reads all nesessary data from zip64 record in the extra data\n * @param zip64data values that might be in zip64 record\n * @param extraField full extra data\n * @returns data read from zip64\n */\n\nconst findZip64DataInExtra = (zip64data: Zip64Data, extraField: DataView): Partial<Zip64Data> => {\n const zip64dataList = findExpectedData(zip64data);\n\n const zip64DataRes: Partial<Zip64Data> = {};\n if (zip64dataList.length > 0) {\n // total length of data in zip64 notation in bytes\n const zip64chunkSize = zip64dataList.reduce((sum, curr) => sum + curr.length, 0);\n // we're looking for the zip64 nontation header (0x0001)\n // and a size field with a correct value next to it\n const offsetInExtraData = new Uint8Array(extraField.buffer).findIndex(\n (_val, i, arr) =>\n getUint16(arr[i], arr[i + 1]) === 0x0001 &&\n getUint16(arr[i + 2], arr[i + 3]) === zip64chunkSize\n );\n // then we read all the nesessary fields from the zip64 data\n let bytesRead = 0;\n for (const note of zip64dataList) {\n const offset = bytesRead;\n zip64DataRes[note.name] = extraField.getBigUint64(offsetInExtraData + 4 + offset, true);\n bytesRead = offset + note.length;\n }\n }\n\n return zip64DataRes;\n};\n\n/**\n * frind data that's expected to be in zip64\n * @param zip64data values that might be in zip64 record\n * @returns zip64 data description\n */\n\nconst findExpectedData = (zip64data: Zip64Data): {length: number; name: string}[] => {\n // We define fields that should be in zip64 data\n const zip64dataList: {length: number; name: string}[] = [];\n if (zip64data.uncompressedSize === BigInt(0xffffffff)) {\n zip64dataList.push({name: 'uncompressedSize', length: 8});\n }\n if (zip64data.compressedSize === BigInt(0xffffffff)) {\n zip64dataList.push({name: 'compressedSize', length: 8});\n }\n if (zip64data.localHeaderOffset === BigInt(0xffffffff)) {\n zip64dataList.push({name: 'localHeaderOffset', length: 8});\n }\n if (zip64data.startDisk === BigInt(0xffffffff)) {\n zip64dataList.push({name: 'startDisk', length: 4});\n }\n\n return zip64dataList;\n};\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loaders.gl/zip",
3
- "version": "4.0.0-beta.8",
3
+ "version": "4.0.1",
4
4
  "description": "Zip Archive Loader",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -38,11 +38,11 @@
38
38
  "build-bundle": "ocular-bundle ./src/index.ts"
39
39
  },
40
40
  "dependencies": {
41
- "@loaders.gl/compression": "4.0.0-beta.8",
42
- "@loaders.gl/crypto": "4.0.0-beta.8",
43
- "@loaders.gl/loader-utils": "4.0.0-beta.8",
41
+ "@loaders.gl/compression": "4.0.1",
42
+ "@loaders.gl/crypto": "4.0.1",
43
+ "@loaders.gl/loader-utils": "4.0.1",
44
44
  "jszip": "^3.1.5",
45
45
  "md5": "^2.3.0"
46
46
  },
47
- "gitHead": "ec3d1747b4c01c52a235455d6462680e711b4e19"
47
+ "gitHead": "765e5a26a6bf3f2cc02cabffc4a1e3665ec92a53"
48
48
  }
@@ -23,11 +23,26 @@ export type ZipCDFileHeader = {
23
23
  localHeaderOffset: bigint;
24
24
  };
25
25
 
26
+ /**
27
+ * Data that might be in Zip64 notation inside extra data
28
+ */
29
+ type Zip64Data = {
30
+ /** Uncompressed size */
31
+ uncompressedSize: bigint;
32
+ /** Compressed size */
33
+ compressedSize: bigint;
34
+ /** Relative offset of local file header */
35
+ localHeaderOffset: bigint;
36
+ /** Start disk */
37
+ startDisk: bigint;
38
+ };
39
+
26
40
  // offsets accroding to https://en.wikipedia.org/wiki/ZIP_(file_format)
27
41
  const CD_COMPRESSED_SIZE_OFFSET = 20n;
28
42
  const CD_UNCOMPRESSED_SIZE_OFFSET = 24n;
29
43
  const CD_FILE_NAME_LENGTH_OFFSET = 28n;
30
44
  const CD_EXTRA_FIELD_LENGTH_OFFSET = 30n;
45
+ const CD_START_DISK_OFFSET = 32n;
31
46
  const CD_LOCAL_HEADER_OFFSET_OFFSET = 42n;
32
47
  const CD_FILE_NAME_OFFSET = 46n;
33
48
 
@@ -48,9 +63,10 @@ export const parseZipCDFileHeader = async (
48
63
  return null;
49
64
  }
50
65
 
51
- let compressedSize = BigInt(await file.getUint32(headerOffset + CD_COMPRESSED_SIZE_OFFSET));
52
- let uncompressedSize = BigInt(await file.getUint32(headerOffset + CD_UNCOMPRESSED_SIZE_OFFSET));
66
+ const compressedSize = BigInt(await file.getUint32(headerOffset + CD_COMPRESSED_SIZE_OFFSET));
67
+ const uncompressedSize = BigInt(await file.getUint32(headerOffset + CD_UNCOMPRESSED_SIZE_OFFSET));
53
68
  const extraFieldLength = await file.getUint16(headerOffset + CD_EXTRA_FIELD_LENGTH_OFFSET);
69
+ const startDisk = BigInt(await file.getUint16(headerOffset + CD_START_DISK_OFFSET));
54
70
  const fileNameLength = await file.getUint16(headerOffset + CD_FILE_NAME_LENGTH_OFFSET);
55
71
  const filenameBytes = await file.slice(
56
72
  headerOffset + CD_FILE_NAME_OFFSET,
@@ -61,30 +77,28 @@ export const parseZipCDFileHeader = async (
61
77
  const extraOffset = headerOffset + CD_FILE_NAME_OFFSET + BigInt(fileNameLength);
62
78
  const oldFormatOffset = await file.getUint32(headerOffset + CD_LOCAL_HEADER_OFFSET_OFFSET);
63
79
 
64
- let fileDataOffset = BigInt(oldFormatOffset);
65
- let offsetInZip64Data = 4n;
80
+ const localHeaderOffset = BigInt(oldFormatOffset);
81
+ const extraField = new DataView(
82
+ await file.slice(extraOffset, extraOffset + BigInt(extraFieldLength))
83
+ );
66
84
  // looking for info that might be also be in zip64 extra field
67
- if (uncompressedSize === BigInt(0xffffffff)) {
68
- uncompressedSize = await file.getBigUint64(extraOffset + offsetInZip64Data);
69
- offsetInZip64Data += 8n;
70
- }
71
- if (compressedSize === BigInt(0xffffffff)) {
72
- compressedSize = await file.getBigUint64(extraOffset + offsetInZip64Data);
73
- offsetInZip64Data += 8n;
74
- }
75
- if (fileDataOffset === BigInt(0xffffffff)) {
76
- fileDataOffset = await file.getBigUint64(extraOffset + offsetInZip64Data); // setting it to the one from zip64
77
- }
78
- const localHeaderOffset = fileDataOffset;
79
85
 
80
- return {
81
- compressedSize,
86
+ const zip64data: Zip64Data = {
82
87
  uncompressedSize,
88
+ compressedSize,
89
+ localHeaderOffset,
90
+ startDisk
91
+ };
92
+
93
+ const res = findZip64DataInExtra(zip64data, extraField);
94
+
95
+ return {
96
+ ...zip64data,
97
+ ...res,
83
98
  extraFieldLength,
84
99
  fileNameLength,
85
100
  fileName,
86
- extraOffset,
87
- localHeaderOffset
101
+ extraOffset
88
102
  };
89
103
  };
90
104
 
@@ -105,3 +119,69 @@ export async function* makeZipCDHeaderIterator(
105
119
  );
106
120
  }
107
121
  }
122
+ /**
123
+ * returns the number written in the provided bytes
124
+ * @param bytes two bytes containing the number
125
+ * @returns the number written in the provided bytes
126
+ */
127
+ const getUint16 = (...bytes: [number, number]) => {
128
+ return bytes[0] + bytes[1] * 16;
129
+ };
130
+
131
+ /**
132
+ * reads all nesessary data from zip64 record in the extra data
133
+ * @param zip64data values that might be in zip64 record
134
+ * @param extraField full extra data
135
+ * @returns data read from zip64
136
+ */
137
+
138
+ const findZip64DataInExtra = (zip64data: Zip64Data, extraField: DataView): Partial<Zip64Data> => {
139
+ const zip64dataList = findExpectedData(zip64data);
140
+
141
+ const zip64DataRes: Partial<Zip64Data> = {};
142
+ if (zip64dataList.length > 0) {
143
+ // total length of data in zip64 notation in bytes
144
+ const zip64chunkSize = zip64dataList.reduce((sum, curr) => sum + curr.length, 0);
145
+ // we're looking for the zip64 nontation header (0x0001)
146
+ // and a size field with a correct value next to it
147
+ const offsetInExtraData = new Uint8Array(extraField.buffer).findIndex(
148
+ (_val, i, arr) =>
149
+ getUint16(arr[i], arr[i + 1]) === 0x0001 &&
150
+ getUint16(arr[i + 2], arr[i + 3]) === zip64chunkSize
151
+ );
152
+ // then we read all the nesessary fields from the zip64 data
153
+ let bytesRead = 0;
154
+ for (const note of zip64dataList) {
155
+ const offset = bytesRead;
156
+ zip64DataRes[note.name] = extraField.getBigUint64(offsetInExtraData + 4 + offset, true);
157
+ bytesRead = offset + note.length;
158
+ }
159
+ }
160
+
161
+ return zip64DataRes;
162
+ };
163
+
164
+ /**
165
+ * frind data that's expected to be in zip64
166
+ * @param zip64data values that might be in zip64 record
167
+ * @returns zip64 data description
168
+ */
169
+
170
+ const findExpectedData = (zip64data: Zip64Data): {length: number; name: string}[] => {
171
+ // We define fields that should be in zip64 data
172
+ const zip64dataList: {length: number; name: string}[] = [];
173
+ if (zip64data.uncompressedSize === BigInt(0xffffffff)) {
174
+ zip64dataList.push({name: 'uncompressedSize', length: 8});
175
+ }
176
+ if (zip64data.compressedSize === BigInt(0xffffffff)) {
177
+ zip64dataList.push({name: 'compressedSize', length: 8});
178
+ }
179
+ if (zip64data.localHeaderOffset === BigInt(0xffffffff)) {
180
+ zip64dataList.push({name: 'localHeaderOffset', length: 8});
181
+ }
182
+ if (zip64data.startDisk === BigInt(0xffffffff)) {
183
+ zip64dataList.push({name: 'startDisk', length: 4});
184
+ }
185
+
186
+ return zip64dataList;
187
+ };