@loaders.gl/zip 4.0.4 → 4.1.0-alpha.2

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
@@ -6951,12 +6951,13 @@ var __exports__ = (() => {
6951
6951
  // src/index.ts
6952
6952
  var src_exports = {};
6953
6953
  __export(src_exports, {
6954
+ CD_HEADER_SIGNATURE: () => signature2,
6954
6955
  TarBuilder: () => TarBuilder,
6955
6956
  ZipFileSystem: () => ZipFileSystem,
6956
6957
  ZipLoader: () => ZipLoader,
6957
6958
  ZipWriter: () => ZipWriter,
6958
- cdSignature: () => signature,
6959
- localHeaderSignature: () => signature2,
6959
+ generateCDHeader: () => generateCDHeader,
6960
+ localHeaderSignature: () => signature3,
6960
6961
  makeHashTableFromZipHeaders: () => makeHashTableFromZipHeaders,
6961
6962
  makeZipCDHeaderIterator: () => makeZipCDHeaderIterator,
6962
6963
  parseEoCDRecord: () => parseEoCDRecord,
@@ -7473,6 +7474,52 @@ var __exports__ = (() => {
7473
7474
  };
7474
7475
  };
7475
7476
 
7477
+ // src/parse-zip/zip64-info-generation.ts
7478
+ var signature = new Uint8Array([1, 0]);
7479
+ function createZip64Info(options) {
7480
+ const optionsToUse = {
7481
+ ...options,
7482
+ zip64Length: (options.offset ? 1 : 0) * 8 + (options.size ? 1 : 0) * 16
7483
+ };
7484
+ const arraysToConcat = [];
7485
+ for (const field of ZIP64_FIELDS) {
7486
+ if (!optionsToUse[field.name ?? ""] && !field.default) {
7487
+ continue;
7488
+ }
7489
+ const newValue = new DataView(new ArrayBuffer(field.size));
7490
+ NUMBER_SETTERS[field.size](newValue, 0, optionsToUse[field.name ?? ""] ?? field.default);
7491
+ arraysToConcat.push(newValue.buffer);
7492
+ }
7493
+ return concatenateArrayBuffers(...arraysToConcat);
7494
+ }
7495
+ var NUMBER_SETTERS = {
7496
+ 2: (header, offset, value) => {
7497
+ header.setUint16(offset, value, true);
7498
+ },
7499
+ 4: (header, offset, value) => {
7500
+ header.setUint32(offset, value, true);
7501
+ },
7502
+ 8: (header, offset, value) => {
7503
+ header.setBigUint64(offset, BigInt(value), true);
7504
+ }
7505
+ };
7506
+ var ZIP64_FIELDS = [{
7507
+ size: 2,
7508
+ default: new DataView(signature.buffer).getUint16(0, true)
7509
+ }, {
7510
+ size: 2,
7511
+ name: "zip64Length"
7512
+ }, {
7513
+ size: 8,
7514
+ name: "size"
7515
+ }, {
7516
+ size: 8,
7517
+ name: "size"
7518
+ }, {
7519
+ size: 8,
7520
+ name: "offset"
7521
+ }];
7522
+
7476
7523
  // src/parse-zip/cd-file-header.ts
7477
7524
  var CD_COMPRESSED_SIZE_OFFSET = 20n;
7478
7525
  var CD_UNCOMPRESSED_SIZE_OFFSET = 24n;
@@ -7481,10 +7528,10 @@ var __exports__ = (() => {
7481
7528
  var CD_START_DISK_OFFSET = 32n;
7482
7529
  var CD_LOCAL_HEADER_OFFSET_OFFSET = 42n;
7483
7530
  var CD_FILE_NAME_OFFSET = 46n;
7484
- var signature = new Uint8Array([80, 75, 1, 2]);
7531
+ var signature2 = new Uint8Array([80, 75, 1, 2]);
7485
7532
  var parseZipCDFileHeader = async (headerOffset, file) => {
7486
7533
  const magicBytes = await file.slice(headerOffset, headerOffset + 4n);
7487
- if (!compareArrayBuffers(magicBytes, signature.buffer)) {
7534
+ if (!compareArrayBuffers(magicBytes, signature2.buffer)) {
7488
7535
  return null;
7489
7536
  }
7490
7537
  const compressedSize = BigInt(await file.getUint32(headerOffset + CD_COMPRESSED_SIZE_OFFSET));
@@ -7570,6 +7617,104 @@ var __exports__ = (() => {
7570
7617
  }
7571
7618
  return zip64dataList;
7572
7619
  };
7620
+ function generateCDHeader(options) {
7621
+ const optionsToUse = {
7622
+ ...options,
7623
+ fnlength: options.fileName.length,
7624
+ extraLength: 0
7625
+ };
7626
+ let zip64header = new ArrayBuffer(0);
7627
+ const optionsToZip64 = {};
7628
+ if (optionsToUse.offset >= 4294967295) {
7629
+ optionsToZip64.offset = optionsToUse.offset;
7630
+ optionsToUse.offset = 4294967295;
7631
+ }
7632
+ if (optionsToUse.length >= 4294967295) {
7633
+ optionsToZip64.size = optionsToUse.length;
7634
+ optionsToUse.length = 4294967295;
7635
+ }
7636
+ if (Object.keys(optionsToZip64).length) {
7637
+ zip64header = createZip64Info(optionsToZip64);
7638
+ optionsToUse.extraLength = zip64header.byteLength;
7639
+ }
7640
+ const header = new DataView(new ArrayBuffer(46));
7641
+ for (const field of ZIP_HEADER_FIELDS) {
7642
+ NUMBER_SETTERS[field.size](header, field.offset, optionsToUse[field.name ?? ""] ?? field.default ?? 0);
7643
+ }
7644
+ const encodedName = new TextEncoder().encode(optionsToUse.fileName);
7645
+ const resHeader = concatenateArrayBuffers(header.buffer, encodedName, zip64header);
7646
+ return resHeader;
7647
+ }
7648
+ var ZIP_HEADER_FIELDS = [{
7649
+ offset: 0,
7650
+ size: 4,
7651
+ default: new DataView(signature2.buffer).getUint32(0, true)
7652
+ }, {
7653
+ offset: 4,
7654
+ size: 2,
7655
+ default: 45
7656
+ }, {
7657
+ offset: 6,
7658
+ size: 2,
7659
+ default: 45
7660
+ }, {
7661
+ offset: 8,
7662
+ size: 2,
7663
+ default: 0
7664
+ }, {
7665
+ offset: 10,
7666
+ size: 2,
7667
+ default: 0
7668
+ }, {
7669
+ offset: 12,
7670
+ size: 2,
7671
+ default: 0
7672
+ }, {
7673
+ offset: 14,
7674
+ size: 2,
7675
+ default: 0
7676
+ }, {
7677
+ offset: 16,
7678
+ size: 4,
7679
+ name: "crc32"
7680
+ }, {
7681
+ offset: 20,
7682
+ size: 4,
7683
+ name: "length"
7684
+ }, {
7685
+ offset: 24,
7686
+ size: 4,
7687
+ name: "length"
7688
+ }, {
7689
+ offset: 28,
7690
+ size: 2,
7691
+ name: "fnlength"
7692
+ }, {
7693
+ offset: 30,
7694
+ size: 2,
7695
+ default: 0,
7696
+ name: "extraLength"
7697
+ }, {
7698
+ offset: 32,
7699
+ size: 2,
7700
+ default: 0
7701
+ }, {
7702
+ offset: 34,
7703
+ size: 2,
7704
+ default: 0
7705
+ }, {
7706
+ offset: 36,
7707
+ size: 2,
7708
+ default: 0
7709
+ }, {
7710
+ offset: 38,
7711
+ size: 4,
7712
+ default: 0
7713
+ }, {
7714
+ offset: 42,
7715
+ size: 4,
7716
+ name: "offset"
7717
+ }];
7573
7718
 
7574
7719
  // src/parse-zip/local-file-header.ts
7575
7720
  var COMPRESSION_METHOD_OFFSET = 8n;
@@ -7578,10 +7723,10 @@ var __exports__ = (() => {
7578
7723
  var FILE_NAME_LENGTH_OFFSET = 26n;
7579
7724
  var EXTRA_FIELD_LENGTH_OFFSET = 28n;
7580
7725
  var FILE_NAME_OFFSET = 30n;
7581
- var signature2 = new Uint8Array([80, 75, 3, 4]);
7726
+ var signature3 = new Uint8Array([80, 75, 3, 4]);
7582
7727
  var parseZipLocalFileHeader = async (headerOffset, buffer) => {
7583
7728
  const magicBytes = await buffer.slice(headerOffset, headerOffset + 4n);
7584
- if (!compareArrayBuffers(magicBytes, signature2)) {
7729
+ if (!compareArrayBuffers(magicBytes, signature3)) {
7585
7730
  return null;
7586
7731
  }
7587
7732
  const fileNameLength = await buffer.getUint16(headerOffset + FILE_NAME_LENGTH_OFFSET);
package/dist/index.cjs CHANGED
@@ -30,12 +30,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var src_exports = {};
32
32
  __export(src_exports, {
33
+ CD_HEADER_SIGNATURE: () => signature2,
33
34
  TarBuilder: () => TarBuilder,
34
35
  ZipFileSystem: () => ZipFileSystem,
35
36
  ZipLoader: () => ZipLoader,
36
37
  ZipWriter: () => ZipWriter,
37
- cdSignature: () => signature,
38
- localHeaderSignature: () => signature2,
38
+ generateCDHeader: () => generateCDHeader,
39
+ localHeaderSignature: () => signature3,
39
40
  makeHashTableFromZipHeaders: () => makeHashTableFromZipHeaders,
40
41
  makeZipCDHeaderIterator: () => makeZipCDHeaderIterator,
41
42
  parseEoCDRecord: () => parseEoCDRecord,
@@ -334,7 +335,7 @@ var TarBuilder = class {
334
335
  };
335
336
 
336
337
  // src/parse-zip/cd-file-header.ts
337
- var import_loader_utils2 = require("@loaders.gl/loader-utils");
338
+ var import_loader_utils3 = require("@loaders.gl/loader-utils");
338
339
 
339
340
  // src/parse-zip/end-of-central-directory.ts
340
341
  var import_loader_utils = require("@loaders.gl/loader-utils");
@@ -396,6 +397,64 @@ var parseEoCDRecord = async (file) => {
396
397
  };
397
398
  };
398
399
 
400
+ // src/parse-zip/zip64-info-generation.ts
401
+ var import_loader_utils2 = require("@loaders.gl/loader-utils");
402
+ var signature = new Uint8Array([1, 0]);
403
+ function createZip64Info(options) {
404
+ const optionsToUse = {
405
+ ...options,
406
+ zip64Length: (options.offset ? 1 : 0) * 8 + (options.size ? 1 : 0) * 16
407
+ };
408
+ const arraysToConcat = [];
409
+ for (const field of ZIP64_FIELDS) {
410
+ if (!optionsToUse[field.name ?? ""] && !field.default) {
411
+ continue;
412
+ }
413
+ const newValue = new DataView(new ArrayBuffer(field.size));
414
+ NUMBER_SETTERS[field.size](newValue, 0, optionsToUse[field.name ?? ""] ?? field.default);
415
+ arraysToConcat.push(newValue.buffer);
416
+ }
417
+ return (0, import_loader_utils2.concatenateArrayBuffers)(...arraysToConcat);
418
+ }
419
+ var NUMBER_SETTERS = {
420
+ 2: (header, offset, value) => {
421
+ header.setUint16(offset, value, true);
422
+ },
423
+ 4: (header, offset, value) => {
424
+ header.setUint32(offset, value, true);
425
+ },
426
+ 8: (header, offset, value) => {
427
+ header.setBigUint64(offset, BigInt(value), true);
428
+ }
429
+ };
430
+ var ZIP64_FIELDS = [
431
+ // Header ID 0x0001
432
+ {
433
+ size: 2,
434
+ default: new DataView(signature.buffer).getUint16(0, true)
435
+ },
436
+ // Size of the extra field chunk (8, 16, 24 or 28)
437
+ {
438
+ size: 2,
439
+ name: "zip64Length"
440
+ },
441
+ // Original uncompressed file size
442
+ {
443
+ size: 8,
444
+ name: "size"
445
+ },
446
+ // Size of compressed data
447
+ {
448
+ size: 8,
449
+ name: "size"
450
+ },
451
+ // Offset of local header record
452
+ {
453
+ size: 8,
454
+ name: "offset"
455
+ }
456
+ ];
457
+
399
458
  // src/parse-zip/cd-file-header.ts
400
459
  var CD_COMPRESSED_SIZE_OFFSET = 20n;
401
460
  var CD_UNCOMPRESSED_SIZE_OFFSET = 24n;
@@ -404,10 +463,10 @@ var CD_EXTRA_FIELD_LENGTH_OFFSET = 30n;
404
463
  var CD_START_DISK_OFFSET = 32n;
405
464
  var CD_LOCAL_HEADER_OFFSET_OFFSET = 42n;
406
465
  var CD_FILE_NAME_OFFSET = 46n;
407
- var signature = new Uint8Array([80, 75, 1, 2]);
466
+ var signature2 = new Uint8Array([80, 75, 1, 2]);
408
467
  var parseZipCDFileHeader = async (headerOffset, file) => {
409
468
  const magicBytes = await file.slice(headerOffset, headerOffset + 4n);
410
- if (!(0, import_loader_utils2.compareArrayBuffers)(magicBytes, signature.buffer)) {
469
+ if (!(0, import_loader_utils3.compareArrayBuffers)(magicBytes, signature2.buffer)) {
411
470
  return null;
412
471
  }
413
472
  const compressedSize = BigInt(await file.getUint32(headerOffset + CD_COMPRESSED_SIZE_OFFSET));
@@ -489,19 +548,156 @@ var findExpectedData = (zip64data) => {
489
548
  }
490
549
  return zip64dataList;
491
550
  };
551
+ function generateCDHeader(options) {
552
+ const optionsToUse = {
553
+ ...options,
554
+ fnlength: options.fileName.length,
555
+ extraLength: 0
556
+ };
557
+ let zip64header = new ArrayBuffer(0);
558
+ const optionsToZip64 = {};
559
+ if (optionsToUse.offset >= 4294967295) {
560
+ optionsToZip64.offset = optionsToUse.offset;
561
+ optionsToUse.offset = 4294967295;
562
+ }
563
+ if (optionsToUse.length >= 4294967295) {
564
+ optionsToZip64.size = optionsToUse.length;
565
+ optionsToUse.length = 4294967295;
566
+ }
567
+ if (Object.keys(optionsToZip64).length) {
568
+ zip64header = createZip64Info(optionsToZip64);
569
+ optionsToUse.extraLength = zip64header.byteLength;
570
+ }
571
+ const header = new DataView(new ArrayBuffer(46));
572
+ for (const field of ZIP_HEADER_FIELDS) {
573
+ NUMBER_SETTERS[field.size](
574
+ header,
575
+ field.offset,
576
+ optionsToUse[field.name ?? ""] ?? field.default ?? 0
577
+ );
578
+ }
579
+ const encodedName = new TextEncoder().encode(optionsToUse.fileName);
580
+ const resHeader = (0, import_loader_utils3.concatenateArrayBuffers)(header.buffer, encodedName, zip64header);
581
+ return resHeader;
582
+ }
583
+ var ZIP_HEADER_FIELDS = [
584
+ // Central directory file header signature = 0x02014b50
585
+ {
586
+ offset: 0,
587
+ size: 4,
588
+ default: new DataView(signature2.buffer).getUint32(0, true)
589
+ },
590
+ // Version made by
591
+ {
592
+ offset: 4,
593
+ size: 2,
594
+ default: 45
595
+ },
596
+ // Version needed to extract (minimum)
597
+ {
598
+ offset: 6,
599
+ size: 2,
600
+ default: 45
601
+ },
602
+ // General purpose bit flag
603
+ {
604
+ offset: 8,
605
+ size: 2,
606
+ default: 0
607
+ },
608
+ // Compression method
609
+ {
610
+ offset: 10,
611
+ size: 2,
612
+ default: 0
613
+ },
614
+ // File last modification time
615
+ {
616
+ offset: 12,
617
+ size: 2,
618
+ default: 0
619
+ },
620
+ // File last modification date
621
+ {
622
+ offset: 14,
623
+ size: 2,
624
+ default: 0
625
+ },
626
+ // CRC-32 of uncompressed data
627
+ {
628
+ offset: 16,
629
+ size: 4,
630
+ name: "crc32"
631
+ },
632
+ // Compressed size (or 0xffffffff for ZIP64)
633
+ {
634
+ offset: 20,
635
+ size: 4,
636
+ name: "length"
637
+ },
638
+ // Uncompressed size (or 0xffffffff for ZIP64)
639
+ {
640
+ offset: 24,
641
+ size: 4,
642
+ name: "length"
643
+ },
644
+ // File name length (n)
645
+ {
646
+ offset: 28,
647
+ size: 2,
648
+ name: "fnlength"
649
+ },
650
+ // Extra field length (m)
651
+ {
652
+ offset: 30,
653
+ size: 2,
654
+ default: 0,
655
+ name: "extraLength"
656
+ },
657
+ // File comment length (k)
658
+ {
659
+ offset: 32,
660
+ size: 2,
661
+ default: 0
662
+ },
663
+ // Disk number where file starts (or 0xffff for ZIP64)
664
+ {
665
+ offset: 34,
666
+ size: 2,
667
+ default: 0
668
+ },
669
+ // Internal file attributes
670
+ {
671
+ offset: 36,
672
+ size: 2,
673
+ default: 0
674
+ },
675
+ // External file attributes
676
+ {
677
+ offset: 38,
678
+ size: 4,
679
+ default: 0
680
+ },
681
+ // Relative offset of local file header
682
+ {
683
+ offset: 42,
684
+ size: 4,
685
+ name: "offset"
686
+ }
687
+ ];
492
688
 
493
689
  // src/parse-zip/local-file-header.ts
494
- var import_loader_utils3 = require("@loaders.gl/loader-utils");
690
+ var import_loader_utils4 = require("@loaders.gl/loader-utils");
495
691
  var COMPRESSION_METHOD_OFFSET = 8n;
496
692
  var COMPRESSED_SIZE_OFFSET = 18n;
497
693
  var UNCOMPRESSED_SIZE_OFFSET = 22n;
498
694
  var FILE_NAME_LENGTH_OFFSET = 26n;
499
695
  var EXTRA_FIELD_LENGTH_OFFSET = 28n;
500
696
  var FILE_NAME_OFFSET = 30n;
501
- var signature2 = new Uint8Array([80, 75, 3, 4]);
697
+ var signature3 = new Uint8Array([80, 75, 3, 4]);
502
698
  var parseZipLocalFileHeader = async (headerOffset, buffer) => {
503
699
  const magicBytes = await buffer.slice(headerOffset, headerOffset + 4n);
504
- if (!(0, import_loader_utils3.compareArrayBuffers)(magicBytes, signature2)) {
700
+ if (!(0, import_loader_utils4.compareArrayBuffers)(magicBytes, signature3)) {
505
701
  return null;
506
702
  }
507
703
  const fileNameLength = await buffer.getUint16(headerOffset + FILE_NAME_LENGTH_OFFSET);
@@ -569,9 +765,9 @@ async function makeHashTableFromZipHeaders(fileProvider) {
569
765
  }
570
766
 
571
767
  // src/filesystems/zip-filesystem.ts
572
- var import_loader_utils4 = require("@loaders.gl/loader-utils");
573
768
  var import_loader_utils5 = require("@loaders.gl/loader-utils");
574
769
  var import_loader_utils6 = require("@loaders.gl/loader-utils");
770
+ var import_loader_utils7 = require("@loaders.gl/loader-utils");
575
771
  var import_compression = require("@loaders.gl/compression");
576
772
  var COMPRESSION_METHODS = {
577
773
  /** No compression */
@@ -593,12 +789,12 @@ var ZipFileSystem = class {
593
789
  this.fileProvider = null;
594
790
  if (typeof file === "string") {
595
791
  this.fileName = file;
596
- if (!import_loader_utils4.isBrowser) {
597
- this.fileProvider = new import_loader_utils6.FileHandleFile(file);
792
+ if (!import_loader_utils5.isBrowser) {
793
+ this.fileProvider = new import_loader_utils7.FileHandleFile(file);
598
794
  } else {
599
795
  throw new Error("Cannot open file for random access in a WEB browser");
600
796
  }
601
- } else if ((0, import_loader_utils5.isFileProvider)(file)) {
797
+ } else if ((0, import_loader_utils6.isFileProvider)(file)) {
602
798
  this.fileProvider = file;
603
799
  }
604
800
  }
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { ZipLoader } from './zip-loader';
2
2
  export { ZipWriter } from './zip-writer';
3
3
  export { TarBuilder } from './tar-builder';
4
- export { parseZipCDFileHeader, makeZipCDHeaderIterator, signature as cdSignature } from './parse-zip/cd-file-header';
4
+ export { parseZipCDFileHeader, makeZipCDHeaderIterator, signature as CD_HEADER_SIGNATURE, generateCDHeader } from './parse-zip/cd-file-header';
5
5
  export { parseZipLocalFileHeader, signature as localHeaderSignature } from './parse-zip/local-file-header';
6
6
  export { parseEoCDRecord } from './parse-zip/end-of-central-directory';
7
7
  export { searchFromTheEnd } from './parse-zip/search-from-the-end';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AACvC,OAAO,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AACvC,OAAO,EAAC,UAAU,EAAC,MAAM,eAAe,CAAC;AAEzC,OAAO,EACL,oBAAoB,EACpB,uBAAuB,EACvB,SAAS,IAAI,WAAW,EACzB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,uBAAuB,EACvB,SAAS,IAAI,oBAAoB,EAClC,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAC,eAAe,EAAC,MAAM,sCAAsC,CAAC;AACrE,OAAO,EAAC,gBAAgB,EAAC,MAAM,iCAAiC,CAAC;AAGjE,OAAO,EAAC,cAAc,EAAE,2BAA2B,EAAC,MAAM,qBAAqB,CAAC;AAEhF,OAAO,EAAC,aAAa,EAAC,MAAM,8BAA8B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AACvC,OAAO,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AACvC,OAAO,EAAC,UAAU,EAAC,MAAM,eAAe,CAAC;AAEzC,OAAO,EACL,oBAAoB,EACpB,uBAAuB,EACvB,SAAS,IAAI,mBAAmB,EAChC,gBAAgB,EACjB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,uBAAuB,EACvB,SAAS,IAAI,oBAAoB,EAClC,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAC,eAAe,EAAC,MAAM,sCAAsC,CAAC;AACrE,OAAO,EAAC,gBAAgB,EAAC,MAAM,iCAAiC,CAAC;AAGjE,OAAO,EAAC,cAAc,EAAE,2BAA2B,EAAC,MAAM,qBAAqB,CAAC;AAEhF,OAAO,EAAC,aAAa,EAAC,MAAM,8BAA8B,CAAC"}
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  export { ZipLoader } from "./zip-loader.js";
2
2
  export { ZipWriter } from "./zip-writer.js";
3
3
  export { TarBuilder } from "./tar-builder.js";
4
- export { parseZipCDFileHeader, makeZipCDHeaderIterator, signature as cdSignature } from "./parse-zip/cd-file-header.js";
4
+ export { parseZipCDFileHeader, makeZipCDHeaderIterator, signature as CD_HEADER_SIGNATURE, generateCDHeader } from "./parse-zip/cd-file-header.js";
5
5
  export { parseZipLocalFileHeader, signature as localHeaderSignature } from "./parse-zip/local-file-header.js";
6
6
  export { parseEoCDRecord } from "./parse-zip/end-of-central-directory.js";
7
7
  export { searchFromTheEnd } from "./parse-zip/search-from-the-end.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["ZipLoader","ZipWriter","TarBuilder","parseZipCDFileHeader","makeZipCDHeaderIterator","signature","cdSignature","parseZipLocalFileHeader","localHeaderSignature","parseEoCDRecord","searchFromTheEnd","parseHashTable","makeHashTableFromZipHeaders","ZipFileSystem"],"sources":["../src/index.ts"],"sourcesContent":["// loaders.gl, MIT license\n// Copyright (c) vis.gl contributors\n\nexport {ZipLoader} from './zip-loader';\nexport {ZipWriter} from './zip-writer';\nexport {TarBuilder} from './tar-builder';\n\nexport {\n parseZipCDFileHeader,\n makeZipCDHeaderIterator,\n signature as cdSignature\n} from './parse-zip/cd-file-header';\nexport {\n parseZipLocalFileHeader,\n signature as localHeaderSignature\n} from './parse-zip/local-file-header';\nexport {parseEoCDRecord} from './parse-zip/end-of-central-directory';\nexport {searchFromTheEnd} from './parse-zip/search-from-the-end';\n\n// export type {HashElement} from './hash-file-utility';\nexport {parseHashTable, makeHashTableFromZipHeaders} from './hash-file-utility';\n\nexport {ZipFileSystem} from './filesystems/zip-filesystem';\n"],"mappings":"SAGQA,SAAS;AAAA,SACTC,SAAS;AAAA,SACTC,UAAU;AAAA,SAGhBC,oBAAoB,EACpBC,uBAAuB,EACvBC,SAAS,IAAIC,WAAW;AAAA,SAGxBC,uBAAuB,EACvBF,SAAS,IAAIG,oBAAoB;AAAA,SAE3BC,eAAe;AAAA,SACfC,gBAAgB;AAAA,SAGhBC,cAAc,EAAEC,2BAA2B;AAAA,SAE3CC,aAAa"}
1
+ {"version":3,"file":"index.js","names":["ZipLoader","ZipWriter","TarBuilder","parseZipCDFileHeader","makeZipCDHeaderIterator","signature","CD_HEADER_SIGNATURE","generateCDHeader","parseZipLocalFileHeader","localHeaderSignature","parseEoCDRecord","searchFromTheEnd","parseHashTable","makeHashTableFromZipHeaders","ZipFileSystem"],"sources":["../src/index.ts"],"sourcesContent":["// loaders.gl, MIT license\n// Copyright (c) vis.gl contributors\n\nexport {ZipLoader} from './zip-loader';\nexport {ZipWriter} from './zip-writer';\nexport {TarBuilder} from './tar-builder';\n\nexport {\n parseZipCDFileHeader,\n makeZipCDHeaderIterator,\n signature as CD_HEADER_SIGNATURE,\n generateCDHeader\n} from './parse-zip/cd-file-header';\nexport {\n parseZipLocalFileHeader,\n signature as localHeaderSignature\n} from './parse-zip/local-file-header';\nexport {parseEoCDRecord} from './parse-zip/end-of-central-directory';\nexport {searchFromTheEnd} from './parse-zip/search-from-the-end';\n\n// export type {HashElement} from './hash-file-utility';\nexport {parseHashTable, makeHashTableFromZipHeaders} from './hash-file-utility';\n\nexport {ZipFileSystem} from './filesystems/zip-filesystem';\n"],"mappings":"SAGQA,SAAS;AAAA,SACTC,SAAS;AAAA,SACTC,UAAU;AAAA,SAGhBC,oBAAoB,EACpBC,uBAAuB,EACvBC,SAAS,IAAIC,mBAAmB,EAChCC,gBAAgB;AAAA,SAGhBC,uBAAuB,EACvBH,SAAS,IAAII,oBAAoB;AAAA,SAE3BC,eAAe;AAAA,SACfC,gBAAgB;AAAA,SAGhBC,cAAc,EAAEC,2BAA2B;AAAA,SAE3CC,aAAa"}
@@ -33,4 +33,22 @@ export declare const parseZipCDFileHeader: (headerOffset: bigint, file: FileProv
33
33
  * @param fileProvider - file provider that provider random access to the file
34
34
  */
35
35
  export declare function makeZipCDHeaderIterator(fileProvider: FileProvider): AsyncIterable<ZipCDFileHeader>;
36
+ /** info that can be placed into cd header */
37
+ type GenerateCDOptions = {
38
+ /** CRC-32 of uncompressed data */
39
+ crc32: number;
40
+ /** File name */
41
+ fileName: string;
42
+ /** File size */
43
+ length: number;
44
+ /** Relative offset of local file header */
45
+ offset: number;
46
+ };
47
+ /**
48
+ * generates cd header for the file
49
+ * @param options info that can be placed into cd header
50
+ * @returns buffer with header
51
+ */
52
+ export declare function generateCDHeader(options: GenerateCDOptions): ArrayBuffer;
53
+ export {};
36
54
  //# sourceMappingURL=cd-file-header.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cd-file-header.d.ts","sourceRoot":"","sources":["../../src/parse-zip/cd-file-header.ts"],"names":[],"mappings":"AAGA,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"}
1
+ {"version":3,"file":"cd-file-header.d.ts","sourceRoot":"","sources":["../../src/parse-zip/cd-file-header.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,YAAY,EAA+C,MAAM,0BAA0B,CAAC;AAEpG,OAAO,EAAC,YAAY,EAAC,MAAM,uBAAuB,CAAC;AAGnD;;;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;AAoED,6CAA6C;AAC7C,KAAK,iBAAiB,GAAG;IACvB,kCAAkC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,GAAG,WAAW,CAsCxE"}
@@ -1,5 +1,6 @@
1
- import { compareArrayBuffers } from '@loaders.gl/loader-utils';
1
+ import { compareArrayBuffers, concatenateArrayBuffers } from '@loaders.gl/loader-utils';
2
2
  import { parseEoCDRecord } from "./end-of-central-directory.js";
3
+ import { createZip64Info, NUMBER_SETTERS } from "./zip64-info-generation.js";
3
4
  const CD_COMPRESSED_SIZE_OFFSET = 20n;
4
5
  const CD_UNCOMPRESSED_SIZE_OFFSET = 24n;
5
6
  const CD_FILE_NAME_LENGTH_OFFSET = 28n;
@@ -96,4 +97,103 @@ const findExpectedData = zip64data => {
96
97
  }
97
98
  return zip64dataList;
98
99
  };
100
+ export function generateCDHeader(options) {
101
+ const optionsToUse = {
102
+ ...options,
103
+ fnlength: options.fileName.length,
104
+ extraLength: 0
105
+ };
106
+ let zip64header = new ArrayBuffer(0);
107
+ const optionsToZip64 = {};
108
+ if (optionsToUse.offset >= 0xffffffff) {
109
+ optionsToZip64.offset = optionsToUse.offset;
110
+ optionsToUse.offset = 0xffffffff;
111
+ }
112
+ if (optionsToUse.length >= 0xffffffff) {
113
+ optionsToZip64.size = optionsToUse.length;
114
+ optionsToUse.length = 0xffffffff;
115
+ }
116
+ if (Object.keys(optionsToZip64).length) {
117
+ zip64header = createZip64Info(optionsToZip64);
118
+ optionsToUse.extraLength = zip64header.byteLength;
119
+ }
120
+ const header = new DataView(new ArrayBuffer(46));
121
+ for (const field of ZIP_HEADER_FIELDS) {
122
+ var _ref, _optionsToUse, _field$name;
123
+ NUMBER_SETTERS[field.size](header, field.offset, (_ref = (_optionsToUse = optionsToUse[(_field$name = field.name) !== null && _field$name !== void 0 ? _field$name : '']) !== null && _optionsToUse !== void 0 ? _optionsToUse : field.default) !== null && _ref !== void 0 ? _ref : 0);
124
+ }
125
+ const encodedName = new TextEncoder().encode(optionsToUse.fileName);
126
+ const resHeader = concatenateArrayBuffers(header.buffer, encodedName, zip64header);
127
+ return resHeader;
128
+ }
129
+ const ZIP_HEADER_FIELDS = [{
130
+ offset: 0,
131
+ size: 4,
132
+ default: new DataView(signature.buffer).getUint32(0, true)
133
+ }, {
134
+ offset: 4,
135
+ size: 2,
136
+ default: 45
137
+ }, {
138
+ offset: 6,
139
+ size: 2,
140
+ default: 45
141
+ }, {
142
+ offset: 8,
143
+ size: 2,
144
+ default: 0
145
+ }, {
146
+ offset: 10,
147
+ size: 2,
148
+ default: 0
149
+ }, {
150
+ offset: 12,
151
+ size: 2,
152
+ default: 0
153
+ }, {
154
+ offset: 14,
155
+ size: 2,
156
+ default: 0
157
+ }, {
158
+ offset: 16,
159
+ size: 4,
160
+ name: 'crc32'
161
+ }, {
162
+ offset: 20,
163
+ size: 4,
164
+ name: 'length'
165
+ }, {
166
+ offset: 24,
167
+ size: 4,
168
+ name: 'length'
169
+ }, {
170
+ offset: 28,
171
+ size: 2,
172
+ name: 'fnlength'
173
+ }, {
174
+ offset: 30,
175
+ size: 2,
176
+ default: 0,
177
+ name: 'extraLength'
178
+ }, {
179
+ offset: 32,
180
+ size: 2,
181
+ default: 0
182
+ }, {
183
+ offset: 34,
184
+ size: 2,
185
+ default: 0
186
+ }, {
187
+ offset: 36,
188
+ size: 2,
189
+ default: 0
190
+ }, {
191
+ offset: 38,
192
+ size: 4,
193
+ default: 0
194
+ }, {
195
+ offset: 42,
196
+ size: 4,
197
+ name: 'offset'
198
+ }];
99
199
  //# 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_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":["// loaders.gl, MIT license\n// Copyright (c) vis.gl contributors\n\nimport {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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"}
1
+ {"version":3,"file":"cd-file-header.js","names":["compareArrayBuffers","concatenateArrayBuffers","parseEoCDRecord","createZip64Info","NUMBER_SETTERS","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","generateCDHeader","options","optionsToUse","fnlength","extraLength","zip64header","ArrayBuffer","optionsToZip64","size","Object","keys","byteLength","header","field","ZIP_HEADER_FIELDS","_ref","_optionsToUse","_field$name","default","encodedName","TextEncoder","encode","resHeader"],"sources":["../../src/parse-zip/cd-file-header.ts"],"sourcesContent":["// loaders.gl, MIT license\n// Copyright (c) vis.gl contributors\n\nimport {FileProvider, compareArrayBuffers, concatenateArrayBuffers} from '@loaders.gl/loader-utils';\nimport {parseEoCDRecord} from './end-of-central-directory';\nimport {ZipSignature} from './search-from-the-end';\nimport {createZip64Info, NUMBER_SETTERS} from './zip64-info-generation';\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\n/** info that can be placed into cd header */\ntype GenerateCDOptions = {\n /** CRC-32 of uncompressed data */\n crc32: number;\n /** File name */\n fileName: string;\n /** File size */\n length: number;\n /** Relative offset of local file header */\n offset: number;\n};\n\n/**\n * generates cd header for the file\n * @param options info that can be placed into cd header\n * @returns buffer with header\n */\nexport function generateCDHeader(options: GenerateCDOptions): ArrayBuffer {\n const optionsToUse = {\n ...options,\n fnlength: options.fileName.length,\n extraLength: 0\n };\n\n let zip64header: ArrayBuffer = new ArrayBuffer(0);\n\n const optionsToZip64: any = {};\n if (optionsToUse.offset >= 0xffffffff) {\n optionsToZip64.offset = optionsToUse.offset;\n optionsToUse.offset = 0xffffffff;\n }\n if (optionsToUse.length >= 0xffffffff) {\n optionsToZip64.size = optionsToUse.length;\n optionsToUse.length = 0xffffffff;\n }\n\n if (Object.keys(optionsToZip64).length) {\n zip64header = createZip64Info(optionsToZip64);\n optionsToUse.extraLength = zip64header.byteLength;\n }\n const header = new DataView(new ArrayBuffer(46));\n\n for (const field of ZIP_HEADER_FIELDS) {\n NUMBER_SETTERS[field.size](\n header,\n field.offset,\n optionsToUse[field.name ?? ''] ?? field.default ?? 0\n );\n }\n\n const encodedName = new TextEncoder().encode(optionsToUse.fileName);\n\n const resHeader = concatenateArrayBuffers(header.buffer, encodedName, zip64header);\n\n return resHeader;\n}\n\n/** Fields map */\nconst ZIP_HEADER_FIELDS = [\n // Central directory file header signature = 0x02014b50\n {\n offset: 0,\n size: 4,\n default: new DataView(signature.buffer).getUint32(0, true)\n },\n\n // Version made by\n {\n offset: 4,\n size: 2,\n default: 45\n },\n\n // Version needed to extract (minimum)\n {\n offset: 6,\n size: 2,\n default: 45\n },\n\n // General purpose bit flag\n {\n offset: 8,\n size: 2,\n default: 0\n },\n\n // Compression method\n {\n offset: 10,\n size: 2,\n default: 0\n },\n\n // File last modification time\n {\n offset: 12,\n size: 2,\n default: 0\n },\n\n // File last modification date\n {\n offset: 14,\n size: 2,\n default: 0\n },\n\n // CRC-32 of uncompressed data\n {\n offset: 16,\n size: 4,\n name: 'crc32'\n },\n\n // Compressed size (or 0xffffffff for ZIP64)\n {\n offset: 20,\n size: 4,\n name: 'length'\n },\n\n // Uncompressed size (or 0xffffffff for ZIP64)\n {\n offset: 24,\n size: 4,\n name: 'length'\n },\n\n // File name length (n)\n {\n offset: 28,\n size: 2,\n name: 'fnlength'\n },\n\n // Extra field length (m)\n {\n offset: 30,\n size: 2,\n default: 0,\n name: 'extraLength'\n },\n\n // File comment length (k)\n {\n offset: 32,\n size: 2,\n default: 0\n },\n\n // Disk number where file starts (or 0xffff for ZIP64)\n {\n offset: 34,\n size: 2,\n default: 0\n },\n\n // Internal file attributes\n {\n offset: 36,\n size: 2,\n default: 0\n },\n\n // External file attributes\n {\n offset: 38,\n size: 4,\n default: 0\n },\n\n // Relative offset of local file header\n {\n offset: 42,\n size: 4,\n name: 'offset'\n }\n];\n"],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ export declare const signature: Uint8Array;
2
+ /** info that can be placed into zip64 field, doc: https://en.wikipedia.org/wiki/ZIP_(file_format)#ZIP64 */
3
+ type Zip64Options = {
4
+ /** Original uncompressed file size and Size of compressed data */
5
+ size?: number;
6
+ /** Offset of local header record */
7
+ offset?: number;
8
+ };
9
+ /**
10
+ * creates zip64 extra field
11
+ * @param options info that can be placed into zip64 field
12
+ * @returns buffer with field
13
+ */
14
+ export declare function createZip64Info(options: Zip64Options): ArrayBuffer;
15
+ /**
16
+ * Function to write values into buffer
17
+ * @param header buffer where to write a value
18
+ * @param offset offset of the writing start
19
+ * @param value value to be written
20
+ */
21
+ type NumberSetter = (header: DataView, offset: number, value: number) => void;
22
+ /** functions to write values into buffer according to the bytes amount */
23
+ export declare const NUMBER_SETTERS: {
24
+ [key: number]: NumberSetter;
25
+ };
26
+ export {};
27
+ //# sourceMappingURL=zip64-info-generation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zip64-info-generation.d.ts","sourceRoot":"","sources":["../../src/parse-zip/zip64-info-generation.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,SAAS,YAA+B,CAAC;AAEtD,2GAA2G;AAC3G,KAAK,YAAY,GAAG;IAClB,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oCAAoC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,WAAW,CAkBlE;AAED;;;;;GAKG;AACH,KAAK,YAAY,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;AAE9E,0EAA0E;AAC1E,eAAO,MAAM,cAAc,EAAE;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAAA;CAUxD,CAAC"}
@@ -0,0 +1,47 @@
1
+ import { concatenateArrayBuffers } from '@loaders.gl/loader-utils';
2
+ export const signature = new Uint8Array([0x01, 0x00]);
3
+ export function createZip64Info(options) {
4
+ const optionsToUse = {
5
+ ...options,
6
+ zip64Length: (options.offset ? 1 : 0) * 8 + (options.size ? 1 : 0) * 16
7
+ };
8
+ const arraysToConcat = [];
9
+ for (const field of ZIP64_FIELDS) {
10
+ var _field$name, _optionsToUse, _field$name2;
11
+ if (!optionsToUse[(_field$name = field.name) !== null && _field$name !== void 0 ? _field$name : ''] && !field.default) {
12
+ continue;
13
+ }
14
+ const newValue = new DataView(new ArrayBuffer(field.size));
15
+ NUMBER_SETTERS[field.size](newValue, 0, (_optionsToUse = optionsToUse[(_field$name2 = field.name) !== null && _field$name2 !== void 0 ? _field$name2 : '']) !== null && _optionsToUse !== void 0 ? _optionsToUse : field.default);
16
+ arraysToConcat.push(newValue.buffer);
17
+ }
18
+ return concatenateArrayBuffers(...arraysToConcat);
19
+ }
20
+ export const NUMBER_SETTERS = {
21
+ 2: (header, offset, value) => {
22
+ header.setUint16(offset, value, true);
23
+ },
24
+ 4: (header, offset, value) => {
25
+ header.setUint32(offset, value, true);
26
+ },
27
+ 8: (header, offset, value) => {
28
+ header.setBigUint64(offset, BigInt(value), true);
29
+ }
30
+ };
31
+ const ZIP64_FIELDS = [{
32
+ size: 2,
33
+ default: new DataView(signature.buffer).getUint16(0, true)
34
+ }, {
35
+ size: 2,
36
+ name: 'zip64Length'
37
+ }, {
38
+ size: 8,
39
+ name: 'size'
40
+ }, {
41
+ size: 8,
42
+ name: 'size'
43
+ }, {
44
+ size: 8,
45
+ name: 'offset'
46
+ }];
47
+ //# sourceMappingURL=zip64-info-generation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zip64-info-generation.js","names":["concatenateArrayBuffers","signature","Uint8Array","createZip64Info","options","optionsToUse","zip64Length","offset","size","arraysToConcat","field","ZIP64_FIELDS","_field$name","_optionsToUse","_field$name2","name","default","newValue","DataView","ArrayBuffer","NUMBER_SETTERS","push","buffer","header","value","setUint16","setUint32","setBigUint64","BigInt","getUint16"],"sources":["../../src/parse-zip/zip64-info-generation.ts"],"sourcesContent":["import {concatenateArrayBuffers} from '@loaders.gl/loader-utils';\n\nexport const signature = new Uint8Array([0x01, 0x00]);\n\n/** info that can be placed into zip64 field, doc: https://en.wikipedia.org/wiki/ZIP_(file_format)#ZIP64 */\ntype Zip64Options = {\n /** Original uncompressed file size and Size of compressed data */\n size?: number;\n /** Offset of local header record */\n offset?: number;\n};\n\n/**\n * creates zip64 extra field\n * @param options info that can be placed into zip64 field\n * @returns buffer with field\n */\nexport function createZip64Info(options: Zip64Options): ArrayBuffer {\n const optionsToUse = {\n ...options,\n zip64Length: (options.offset ? 1 : 0) * 8 + (options.size ? 1 : 0) * 16\n };\n\n const arraysToConcat: ArrayBuffer[] = [];\n\n for (const field of ZIP64_FIELDS) {\n if (!optionsToUse[field.name ?? ''] && !field.default) {\n continue;\n }\n const newValue = new DataView(new ArrayBuffer(field.size));\n NUMBER_SETTERS[field.size](newValue, 0, optionsToUse[field.name ?? ''] ?? field.default);\n arraysToConcat.push(newValue.buffer);\n }\n\n return concatenateArrayBuffers(...arraysToConcat);\n}\n\n/**\n * Function to write values into buffer\n * @param header buffer where to write a value\n * @param offset offset of the writing start\n * @param value value to be written\n */\ntype NumberSetter = (header: DataView, offset: number, value: number) => void;\n\n/** functions to write values into buffer according to the bytes amount */\nexport const NUMBER_SETTERS: {[key: number]: NumberSetter} = {\n 2: (header, offset, value) => {\n header.setUint16(offset, value, true);\n },\n 4: (header, offset, value) => {\n header.setUint32(offset, value, true);\n },\n 8: (header, offset, value) => {\n header.setBigUint64(offset, BigInt(value), true);\n }\n};\n\n/** zip64 info fields description, we need it as a pattern to build a zip64 info */\nconst ZIP64_FIELDS = [\n // Header ID 0x0001\n {\n size: 2,\n default: new DataView(signature.buffer).getUint16(0, true)\n },\n\n // Size of the extra field chunk (8, 16, 24 or 28)\n {\n size: 2,\n name: 'zip64Length'\n },\n\n // Original uncompressed file size\n {\n size: 8,\n name: 'size'\n },\n\n // Size of compressed data\n {\n size: 8,\n name: 'size'\n },\n\n // Offset of local header record\n {\n size: 8,\n name: 'offset'\n }\n];\n"],"mappings":"AAAA,SAAQA,uBAAuB,QAAO,0BAA0B;AAEhE,OAAO,MAAMC,SAAS,GAAG,IAAIC,UAAU,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAerD,OAAO,SAASC,eAAeA,CAACC,OAAqB,EAAe;EAClE,MAAMC,YAAY,GAAG;IACnB,GAAGD,OAAO;IACVE,WAAW,EAAE,CAACF,OAAO,CAACG,MAAM,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAACH,OAAO,CAACI,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI;EACvE,CAAC;EAED,MAAMC,cAA6B,GAAG,EAAE;EAExC,KAAK,MAAMC,KAAK,IAAIC,YAAY,EAAE;IAAA,IAAAC,WAAA,EAAAC,aAAA,EAAAC,YAAA;IAChC,IAAI,CAACT,YAAY,EAAAO,WAAA,GAACF,KAAK,CAACK,IAAI,cAAAH,WAAA,cAAAA,WAAA,GAAI,EAAE,CAAC,IAAI,CAACF,KAAK,CAACM,OAAO,EAAE;MACrD;IACF;IACA,MAAMC,QAAQ,GAAG,IAAIC,QAAQ,CAAC,IAAIC,WAAW,CAACT,KAAK,CAACF,IAAI,CAAC,CAAC;IAC1DY,cAAc,CAACV,KAAK,CAACF,IAAI,CAAC,CAACS,QAAQ,EAAE,CAAC,GAAAJ,aAAA,GAAER,YAAY,EAAAS,YAAA,GAACJ,KAAK,CAACK,IAAI,cAAAD,YAAA,cAAAA,YAAA,GAAI,EAAE,CAAC,cAAAD,aAAA,cAAAA,aAAA,GAAIH,KAAK,CAACM,OAAO,CAAC;IACxFP,cAAc,CAACY,IAAI,CAACJ,QAAQ,CAACK,MAAM,CAAC;EACtC;EAEA,OAAOtB,uBAAuB,CAAC,GAAGS,cAAc,CAAC;AACnD;AAWA,OAAO,MAAMW,cAA6C,GAAG;EAC3D,CAAC,EAAE,CAACG,MAAM,EAAEhB,MAAM,EAAEiB,KAAK,KAAK;IAC5BD,MAAM,CAACE,SAAS,CAAClB,MAAM,EAAEiB,KAAK,EAAE,IAAI,CAAC;EACvC,CAAC;EACD,CAAC,EAAE,CAACD,MAAM,EAAEhB,MAAM,EAAEiB,KAAK,KAAK;IAC5BD,MAAM,CAACG,SAAS,CAACnB,MAAM,EAAEiB,KAAK,EAAE,IAAI,CAAC;EACvC,CAAC;EACD,CAAC,EAAE,CAACD,MAAM,EAAEhB,MAAM,EAAEiB,KAAK,KAAK;IAC5BD,MAAM,CAACI,YAAY,CAACpB,MAAM,EAAEqB,MAAM,CAACJ,KAAK,CAAC,EAAE,IAAI,CAAC;EAClD;AACF,CAAC;AAGD,MAAMb,YAAY,GAAG,CAEnB;EACEH,IAAI,EAAE,CAAC;EACPQ,OAAO,EAAE,IAAIE,QAAQ,CAACjB,SAAS,CAACqB,MAAM,CAAC,CAACO,SAAS,CAAC,CAAC,EAAE,IAAI;AAC3D,CAAC,EAGD;EACErB,IAAI,EAAE,CAAC;EACPO,IAAI,EAAE;AACR,CAAC,EAGD;EACEP,IAAI,EAAE,CAAC;EACPO,IAAI,EAAE;AACR,CAAC,EAGD;EACEP,IAAI,EAAE,CAAC;EACPO,IAAI,EAAE;AACR,CAAC,EAGD;EACEP,IAAI,EAAE,CAAC;EACPO,IAAI,EAAE;AACR,CAAC,CACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loaders.gl/zip",
3
- "version": "4.0.4",
3
+ "version": "4.1.0-alpha.2",
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.4",
42
- "@loaders.gl/crypto": "4.0.4",
43
- "@loaders.gl/loader-utils": "4.0.4",
41
+ "@loaders.gl/compression": "4.1.0-alpha.2",
42
+ "@loaders.gl/crypto": "4.1.0-alpha.2",
43
+ "@loaders.gl/loader-utils": "4.1.0-alpha.2",
44
44
  "jszip": "^3.1.5",
45
45
  "md5": "^2.3.0"
46
46
  },
47
- "gitHead": "4dc810fa04bb400f4aedfef98a83c7ef882ed3d7"
47
+ "gitHead": "a248382edd20e846c1ccb23c15d089fb9b368dbc"
48
48
  }
package/src/index.ts CHANGED
@@ -8,7 +8,8 @@ export {TarBuilder} from './tar-builder';
8
8
  export {
9
9
  parseZipCDFileHeader,
10
10
  makeZipCDHeaderIterator,
11
- signature as cdSignature
11
+ signature as CD_HEADER_SIGNATURE,
12
+ generateCDHeader
12
13
  } from './parse-zip/cd-file-header';
13
14
  export {
14
15
  parseZipLocalFileHeader,
@@ -1,9 +1,10 @@
1
1
  // loaders.gl, MIT license
2
2
  // Copyright (c) vis.gl contributors
3
3
 
4
- import {FileProvider, compareArrayBuffers} from '@loaders.gl/loader-utils';
4
+ import {FileProvider, compareArrayBuffers, concatenateArrayBuffers} from '@loaders.gl/loader-utils';
5
5
  import {parseEoCDRecord} from './end-of-central-directory';
6
6
  import {ZipSignature} from './search-from-the-end';
7
+ import {createZip64Info, NUMBER_SETTERS} from './zip64-info-generation';
7
8
 
8
9
  /**
9
10
  * zip central directory file header info
@@ -188,3 +189,183 @@ const findExpectedData = (zip64data: Zip64Data): {length: number; name: string}[
188
189
 
189
190
  return zip64dataList;
190
191
  };
192
+
193
+ /** info that can be placed into cd header */
194
+ type GenerateCDOptions = {
195
+ /** CRC-32 of uncompressed data */
196
+ crc32: number;
197
+ /** File name */
198
+ fileName: string;
199
+ /** File size */
200
+ length: number;
201
+ /** Relative offset of local file header */
202
+ offset: number;
203
+ };
204
+
205
+ /**
206
+ * generates cd header for the file
207
+ * @param options info that can be placed into cd header
208
+ * @returns buffer with header
209
+ */
210
+ export function generateCDHeader(options: GenerateCDOptions): ArrayBuffer {
211
+ const optionsToUse = {
212
+ ...options,
213
+ fnlength: options.fileName.length,
214
+ extraLength: 0
215
+ };
216
+
217
+ let zip64header: ArrayBuffer = new ArrayBuffer(0);
218
+
219
+ const optionsToZip64: any = {};
220
+ if (optionsToUse.offset >= 0xffffffff) {
221
+ optionsToZip64.offset = optionsToUse.offset;
222
+ optionsToUse.offset = 0xffffffff;
223
+ }
224
+ if (optionsToUse.length >= 0xffffffff) {
225
+ optionsToZip64.size = optionsToUse.length;
226
+ optionsToUse.length = 0xffffffff;
227
+ }
228
+
229
+ if (Object.keys(optionsToZip64).length) {
230
+ zip64header = createZip64Info(optionsToZip64);
231
+ optionsToUse.extraLength = zip64header.byteLength;
232
+ }
233
+ const header = new DataView(new ArrayBuffer(46));
234
+
235
+ for (const field of ZIP_HEADER_FIELDS) {
236
+ NUMBER_SETTERS[field.size](
237
+ header,
238
+ field.offset,
239
+ optionsToUse[field.name ?? ''] ?? field.default ?? 0
240
+ );
241
+ }
242
+
243
+ const encodedName = new TextEncoder().encode(optionsToUse.fileName);
244
+
245
+ const resHeader = concatenateArrayBuffers(header.buffer, encodedName, zip64header);
246
+
247
+ return resHeader;
248
+ }
249
+
250
+ /** Fields map */
251
+ const ZIP_HEADER_FIELDS = [
252
+ // Central directory file header signature = 0x02014b50
253
+ {
254
+ offset: 0,
255
+ size: 4,
256
+ default: new DataView(signature.buffer).getUint32(0, true)
257
+ },
258
+
259
+ // Version made by
260
+ {
261
+ offset: 4,
262
+ size: 2,
263
+ default: 45
264
+ },
265
+
266
+ // Version needed to extract (minimum)
267
+ {
268
+ offset: 6,
269
+ size: 2,
270
+ default: 45
271
+ },
272
+
273
+ // General purpose bit flag
274
+ {
275
+ offset: 8,
276
+ size: 2,
277
+ default: 0
278
+ },
279
+
280
+ // Compression method
281
+ {
282
+ offset: 10,
283
+ size: 2,
284
+ default: 0
285
+ },
286
+
287
+ // File last modification time
288
+ {
289
+ offset: 12,
290
+ size: 2,
291
+ default: 0
292
+ },
293
+
294
+ // File last modification date
295
+ {
296
+ offset: 14,
297
+ size: 2,
298
+ default: 0
299
+ },
300
+
301
+ // CRC-32 of uncompressed data
302
+ {
303
+ offset: 16,
304
+ size: 4,
305
+ name: 'crc32'
306
+ },
307
+
308
+ // Compressed size (or 0xffffffff for ZIP64)
309
+ {
310
+ offset: 20,
311
+ size: 4,
312
+ name: 'length'
313
+ },
314
+
315
+ // Uncompressed size (or 0xffffffff for ZIP64)
316
+ {
317
+ offset: 24,
318
+ size: 4,
319
+ name: 'length'
320
+ },
321
+
322
+ // File name length (n)
323
+ {
324
+ offset: 28,
325
+ size: 2,
326
+ name: 'fnlength'
327
+ },
328
+
329
+ // Extra field length (m)
330
+ {
331
+ offset: 30,
332
+ size: 2,
333
+ default: 0,
334
+ name: 'extraLength'
335
+ },
336
+
337
+ // File comment length (k)
338
+ {
339
+ offset: 32,
340
+ size: 2,
341
+ default: 0
342
+ },
343
+
344
+ // Disk number where file starts (or 0xffff for ZIP64)
345
+ {
346
+ offset: 34,
347
+ size: 2,
348
+ default: 0
349
+ },
350
+
351
+ // Internal file attributes
352
+ {
353
+ offset: 36,
354
+ size: 2,
355
+ default: 0
356
+ },
357
+
358
+ // External file attributes
359
+ {
360
+ offset: 38,
361
+ size: 4,
362
+ default: 0
363
+ },
364
+
365
+ // Relative offset of local file header
366
+ {
367
+ offset: 42,
368
+ size: 4,
369
+ name: 'offset'
370
+ }
371
+ ];
@@ -0,0 +1,90 @@
1
+ import {concatenateArrayBuffers} from '@loaders.gl/loader-utils';
2
+
3
+ export const signature = new Uint8Array([0x01, 0x00]);
4
+
5
+ /** info that can be placed into zip64 field, doc: https://en.wikipedia.org/wiki/ZIP_(file_format)#ZIP64 */
6
+ type Zip64Options = {
7
+ /** Original uncompressed file size and Size of compressed data */
8
+ size?: number;
9
+ /** Offset of local header record */
10
+ offset?: number;
11
+ };
12
+
13
+ /**
14
+ * creates zip64 extra field
15
+ * @param options info that can be placed into zip64 field
16
+ * @returns buffer with field
17
+ */
18
+ export function createZip64Info(options: Zip64Options): ArrayBuffer {
19
+ const optionsToUse = {
20
+ ...options,
21
+ zip64Length: (options.offset ? 1 : 0) * 8 + (options.size ? 1 : 0) * 16
22
+ };
23
+
24
+ const arraysToConcat: ArrayBuffer[] = [];
25
+
26
+ for (const field of ZIP64_FIELDS) {
27
+ if (!optionsToUse[field.name ?? ''] && !field.default) {
28
+ continue;
29
+ }
30
+ const newValue = new DataView(new ArrayBuffer(field.size));
31
+ NUMBER_SETTERS[field.size](newValue, 0, optionsToUse[field.name ?? ''] ?? field.default);
32
+ arraysToConcat.push(newValue.buffer);
33
+ }
34
+
35
+ return concatenateArrayBuffers(...arraysToConcat);
36
+ }
37
+
38
+ /**
39
+ * Function to write values into buffer
40
+ * @param header buffer where to write a value
41
+ * @param offset offset of the writing start
42
+ * @param value value to be written
43
+ */
44
+ type NumberSetter = (header: DataView, offset: number, value: number) => void;
45
+
46
+ /** functions to write values into buffer according to the bytes amount */
47
+ export const NUMBER_SETTERS: {[key: number]: NumberSetter} = {
48
+ 2: (header, offset, value) => {
49
+ header.setUint16(offset, value, true);
50
+ },
51
+ 4: (header, offset, value) => {
52
+ header.setUint32(offset, value, true);
53
+ },
54
+ 8: (header, offset, value) => {
55
+ header.setBigUint64(offset, BigInt(value), true);
56
+ }
57
+ };
58
+
59
+ /** zip64 info fields description, we need it as a pattern to build a zip64 info */
60
+ const ZIP64_FIELDS = [
61
+ // Header ID 0x0001
62
+ {
63
+ size: 2,
64
+ default: new DataView(signature.buffer).getUint16(0, true)
65
+ },
66
+
67
+ // Size of the extra field chunk (8, 16, 24 or 28)
68
+ {
69
+ size: 2,
70
+ name: 'zip64Length'
71
+ },
72
+
73
+ // Original uncompressed file size
74
+ {
75
+ size: 8,
76
+ name: 'size'
77
+ },
78
+
79
+ // Size of compressed data
80
+ {
81
+ size: 8,
82
+ name: 'size'
83
+ },
84
+
85
+ // Offset of local header record
86
+ {
87
+ size: 8,
88
+ name: 'offset'
89
+ }
90
+ ];