@loaders.gl/zip 4.1.0-alpha.4 → 4.1.0-alpha.5

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
@@ -6956,6 +6956,8 @@ var __exports__ = (() => {
6956
6956
  ZipFileSystem: () => ZipFileSystem,
6957
6957
  ZipLoader: () => ZipLoader,
6958
6958
  ZipWriter: () => ZipWriter,
6959
+ addOneFile: () => addOneFile,
6960
+ composeHashFile: () => composeHashFile,
6959
6961
  generateCDHeader: () => generateCDHeader,
6960
6962
  generateLocalHeader: () => generateLocalHeader,
6961
6963
  localHeaderSignature: () => signature3,
@@ -6970,7 +6972,7 @@ var __exports__ = (() => {
6970
6972
 
6971
6973
  // src/zip-loader.ts
6972
6974
  var import_jszip = __toESM(require_jszip_min(), 1);
6973
- var VERSION = true ? "4.1.0-alpha.4" : "latest";
6975
+ var VERSION = true ? "4.1.0-alpha.5" : "latest";
6974
6976
  var ZipLoader = {
6975
6977
  id: "zip",
6976
6978
  module: "zip",
@@ -7015,7 +7017,7 @@ var __exports__ = (() => {
7015
7017
 
7016
7018
  // src/zip-writer.ts
7017
7019
  var import_jszip2 = __toESM(require_jszip_min(), 1);
7018
- var VERSION2 = true ? "4.1.0-alpha.4" : "latest";
7020
+ var VERSION2 = true ? "4.1.0-alpha.5" : "latest";
7019
7021
  var ZipWriter = {
7020
7022
  name: "Zip Archive",
7021
7023
  id: "zip",
@@ -7521,9 +7523,13 @@ var __exports__ = (() => {
7521
7523
  var zip64EoCDLocatorSignature = new Uint8Array([80, 75, 6, 7]);
7522
7524
  var zip64EoCDSignature = new Uint8Array([80, 75, 6, 6]);
7523
7525
  var CD_RECORDS_NUMBER_OFFSET = 8n;
7526
+ var CD_RECORDS_NUMBER_ON_DISC_OFFSET = 10n;
7527
+ var CD_CD_BYTE_SIZE_OFFSET = 12n;
7524
7528
  var CD_START_OFFSET_OFFSET = 16n;
7525
7529
  var ZIP64_EOCD_START_OFFSET_OFFSET = 8n;
7526
7530
  var ZIP64_CD_RECORDS_NUMBER_OFFSET = 24n;
7531
+ var ZIP64_CD_RECORDS_NUMBER_ON_DISC_OFFSET = 32n;
7532
+ var ZIP64_CD_CD_BYTE_SIZE_OFFSET = 40n;
7527
7533
  var ZIP64_CD_START_OFFSET_OFFSET = 48n;
7528
7534
  var parseEoCDRecord = async (file) => {
7529
7535
  const zipEoCDOffset = await searchFromTheEnd(file, eoCDSignature);
@@ -7553,6 +7559,29 @@ var __exports__ = (() => {
7553
7559
  }
7554
7560
  };
7555
7561
  };
7562
+ async function updateEoCD(eocdBody, oldEoCDOffsets, newCDStartOffset, eocdStartOffset, newCDRecordsNumber) {
7563
+ const eocd = new DataView(eocdBody);
7564
+ const classicEoCDOffset = oldEoCDOffsets.zip64EoCDOffset ? oldEoCDOffsets.zipEoCDOffset - oldEoCDOffsets.zip64EoCDOffset : 0n;
7565
+ if (Number(newCDRecordsNumber) <= 65535) {
7566
+ setFieldToNumber(eocd, 2, classicEoCDOffset + CD_RECORDS_NUMBER_OFFSET, newCDRecordsNumber);
7567
+ setFieldToNumber(eocd, 2, classicEoCDOffset + CD_RECORDS_NUMBER_ON_DISC_OFFSET, newCDRecordsNumber);
7568
+ }
7569
+ if (eocdStartOffset - newCDStartOffset <= 4294967295) {
7570
+ setFieldToNumber(eocd, 4, classicEoCDOffset + CD_CD_BYTE_SIZE_OFFSET, eocdStartOffset - newCDStartOffset);
7571
+ }
7572
+ if (newCDStartOffset < 4294967295) {
7573
+ setFieldToNumber(eocd, 4, classicEoCDOffset + CD_START_OFFSET_OFFSET, newCDStartOffset);
7574
+ }
7575
+ if (oldEoCDOffsets.zip64EoCDLocatorOffset && oldEoCDOffsets.zip64EoCDOffset) {
7576
+ const locatorOffset = oldEoCDOffsets.zip64EoCDLocatorOffset - oldEoCDOffsets.zip64EoCDOffset;
7577
+ setFieldToNumber(eocd, 8, locatorOffset + ZIP64_EOCD_START_OFFSET_OFFSET, eocdStartOffset);
7578
+ setFieldToNumber(eocd, 8, ZIP64_CD_START_OFFSET_OFFSET, newCDStartOffset);
7579
+ setFieldToNumber(eocd, 8, ZIP64_CD_RECORDS_NUMBER_OFFSET, newCDRecordsNumber);
7580
+ setFieldToNumber(eocd, 8, ZIP64_CD_RECORDS_NUMBER_ON_DISC_OFFSET, newCDRecordsNumber);
7581
+ setFieldToNumber(eocd, 8, ZIP64_CD_CD_BYTE_SIZE_OFFSET, eocdStartOffset - newCDStartOffset);
7582
+ }
7583
+ return new Uint8Array(eocd.buffer);
7584
+ }
7556
7585
 
7557
7586
  // src/parse-zip/cd-file-header.ts
7558
7587
  var CD_COMPRESSED_SIZE_OFFSET = 20n;
@@ -7888,6 +7917,29 @@ var __exports__ = (() => {
7888
7917
  }
7889
7918
  };
7890
7919
 
7920
+ // ../crypto/src/lib/algorithms/crc32.ts
7921
+ var CRC32 = class {
7922
+ constructor() {
7923
+ this.crc = ~0;
7924
+ }
7925
+ update(arrayBuffer) {
7926
+ const CRC32_TABLE = getCRC32Table();
7927
+ const byteArray = new Uint8Array(arrayBuffer);
7928
+ for (let i = 0; i < byteArray.byteLength; i++) {
7929
+ this.crc = this.crc >>> 8 ^ CRC32_TABLE[(this.crc ^ byteArray[i]) & 255];
7930
+ }
7931
+ return this;
7932
+ }
7933
+ finalize() {
7934
+ this.crc = (this.crc ^ -1) >>> 0;
7935
+ return this.crc;
7936
+ }
7937
+ };
7938
+ var CRC32TAB = Uint32Array.of(0, 1996959894, 3993919788, 2567524794, 124634137, 1886057615, 3915621685, 2657392035, 249268274, 2044508324, 3772115230, 2547177864, 162941995, 2125561021, 3887607047, 2428444049, 498536548, 1789927666, 4089016648, 2227061214, 450548861, 1843258603, 4107580753, 2211677639, 325883990, 1684777152, 4251122042, 2321926636, 335633487, 1661365465, 4195302755, 2366115317, 997073096, 1281953886, 3579855332, 2724688242, 1006888145, 1258607687, 3524101629, 2768942443, 901097722, 1119000684, 3686517206, 2898065728, 853044451, 1172266101, 3705015759, 2882616665, 651767980, 1373503546, 3369554304, 3218104598, 565507253, 1454621731, 3485111705, 3099436303, 671266974, 1594198024, 3322730930, 2970347812, 795835527, 1483230225, 3244367275, 3060149565, 1994146192, 31158534, 2563907772, 4023717930, 1907459465, 112637215, 2680153253, 3904427059, 2013776290, 251722036, 2517215374, 3775830040, 2137656763, 141376813, 2439277719, 3865271297, 1802195444, 476864866, 2238001368, 4066508878, 1812370925, 453092731, 2181625025, 4111451223, 1706088902, 314042704, 2344532202, 4240017532, 1658658271, 366619977, 2362670323, 4224994405, 1303535960, 984961486, 2747007092, 3569037538, 1256170817, 1037604311, 2765210733, 3554079995, 1131014506, 879679996, 2909243462, 3663771856, 1141124467, 855842277, 2852801631, 3708648649, 1342533948, 654459306, 3188396048, 3373015174, 1466479909, 544179635, 3110523913, 3462522015, 1591671054, 702138776, 2966460450, 3352799412, 1504918807, 783551873, 3082640443, 3233442989, 3988292384, 2596254646, 62317068, 1957810842, 3939845945, 2647816111, 81470997, 1943803523, 3814918930, 2489596804, 225274430, 2053790376, 3826175755, 2466906013, 167816743, 2097651377, 4027552580, 2265490386, 503444072, 1762050814, 4150417245, 2154129355, 426522225, 1852507879, 4275313526, 2312317920, 282753626, 1742555852, 4189708143, 2394877945, 397917763, 1622183637, 3604390888, 2714866558, 953729732, 1340076626, 3518719985, 2797360999, 1068828381, 1219638859, 3624741850, 2936675148, 906185462, 1090812512, 3747672003, 2825379669, 829329135, 1181335161, 3412177804, 3160834842, 628085408, 1382605366, 3423369109, 3138078467, 570562233, 1426400815, 3317316542, 2998733608, 733239954, 1555261956, 3268935591, 3050360625, 752459403, 1541320221, 2607071920, 3965973030, 1969922972, 40735498, 2617837225, 3943577151, 1913087877, 83908371, 2512341634, 3803740692, 2075208622, 213261112, 2463272603, 3855990285, 2094854071, 198958881, 2262029012, 4057260610, 1759359992, 534414190, 2176718541, 4139329115, 1873836001, 414664567, 2282248934, 4279200368, 1711684554, 285281116, 2405801727, 4167216745, 1634467795, 376229701, 2685067896, 3608007406, 1308918612, 956543938, 2808555105, 3495958263, 1231636301, 1047427035, 2932959818, 3654703836, 1088359270, 936918e3, 2847714899, 3736837829, 1202900863, 817233897, 3183342108, 3401237130, 1404277552, 615818150, 3134207493, 3453421203, 1423857449, 601450431, 3009837614, 3294710456, 1567103746, 711928724, 3020668471, 3272380065, 1510334235, 755167117);
7939
+ function getCRC32Table() {
7940
+ return CRC32TAB;
7941
+ }
7942
+
7891
7943
  // ../crypto/src/lib/utils/base64-utils.ts
7892
7944
  function asciiToBase64(string) {
7893
7945
  string = `${string}`;
@@ -7939,6 +7991,16 @@ var __exports__ = (() => {
7939
7991
  }
7940
7992
 
7941
7993
  // ../crypto/src/lib/utils/digest-utils.ts
7994
+ function encodeNumber(number, encoding) {
7995
+ switch (encoding) {
7996
+ case "hex":
7997
+ return convertNumberToHex(number);
7998
+ case "base64":
7999
+ return convertHexToBase64(convertNumberToHex(number));
8000
+ default:
8001
+ throw new Error(encoding);
8002
+ }
8003
+ }
7942
8004
  function encodeHex(hex, encoding) {
7943
8005
  switch (encoding) {
7944
8006
  case "hex":
@@ -7957,6 +8019,43 @@ var __exports__ = (() => {
7957
8019
  const string = matches2.map((a) => String.fromCharCode(parseInt(a, 16))).join("");
7958
8020
  return asciiToBase64(string) || "";
7959
8021
  }
8022
+ function convertNumberToHex(cipher) {
8023
+ const hexString = cipher.toString(16);
8024
+ return hexString === "0" ? `0${hexString}` : hexString;
8025
+ }
8026
+
8027
+ // ../crypto/src/lib/crc32-hash.ts
8028
+ var CRC32Hash = class extends Hash {
8029
+ name = "crc32";
8030
+ constructor(options = {}) {
8031
+ super();
8032
+ this.options = {
8033
+ crypto: {},
8034
+ ...options
8035
+ };
8036
+ this.hashBatches = this.hashBatches.bind(this);
8037
+ }
8038
+ async hash(input, encoding) {
8039
+ return this.hashSync(input, encoding);
8040
+ }
8041
+ hashSync(input, encoding) {
8042
+ const hash = new CRC32();
8043
+ hash.update(input);
8044
+ const digest = hash.finalize();
8045
+ return encodeNumber(digest, encoding);
8046
+ }
8047
+ async *hashBatches(asyncIterator, encoding = "base64") {
8048
+ const hash = new CRC32();
8049
+ for await (const chunk of asyncIterator) {
8050
+ hash.update(chunk);
8051
+ yield chunk;
8052
+ }
8053
+ const digest = hash.finalize();
8054
+ this.options.crypto?.onEnd?.({
8055
+ hash: encodeNumber(digest, encoding)
8056
+ });
8057
+ }
8058
+ };
7960
8059
 
7961
8060
  // ../crypto/src/lib/algorithms/md5-wasm.ts
7962
8061
  var atb = typeof atob === "function" ? atob : typeof Buffer === "function" ? nodeATOB : identity;
@@ -8381,6 +8480,45 @@ var __exports__ = (() => {
8381
8480
  }
8382
8481
  };
8383
8482
 
8483
+ // src/parse-zip/zip-compozition.ts
8484
+ async function cutTheTailOff(provider) {
8485
+ const oldEoCDinfo = await parseEoCDRecord(provider);
8486
+ const oldCDStartOffset = oldEoCDinfo.cdStartOffset;
8487
+ const oldCDLength = Number(oldEoCDinfo.offsets.zip64EoCDOffset ? oldEoCDinfo.offsets.zip64EoCDOffset - oldCDStartOffset : oldEoCDinfo.offsets.zipEoCDOffset - oldCDStartOffset);
8488
+ const zipEnding = await provider.slice(oldCDStartOffset, provider.length);
8489
+ await provider.truncate(Number(oldCDStartOffset));
8490
+ const oldCDBody = zipEnding.slice(0, oldCDLength);
8491
+ const eocdBody = zipEnding.slice(oldCDLength, zipEnding.byteLength);
8492
+ return [oldCDBody, eocdBody, oldEoCDinfo];
8493
+ }
8494
+ async function generateFileHeaders(fileName, fileToAdd, localFileHeaderOffset) {
8495
+ const newFileCRC322 = parseInt(await new CRC32Hash().hash(fileToAdd, "hex"), 16);
8496
+ const newFileLocalHeader = generateLocalHeader({
8497
+ crc32: newFileCRC322,
8498
+ fileName,
8499
+ length: fileToAdd.byteLength
8500
+ });
8501
+ const newFileCDHeader = generateCDHeader({
8502
+ crc32: newFileCRC322,
8503
+ fileName,
8504
+ offset: localFileHeaderOffset,
8505
+ length: fileToAdd.byteLength
8506
+ });
8507
+ return [new Uint8Array(concatenateArrayBuffers(newFileLocalHeader, fileToAdd)), new Uint8Array(newFileCDHeader)];
8508
+ }
8509
+ async function addOneFile(zipUrl, fileToAdd, fileName) {
8510
+ const provider = new FileHandleFile(zipUrl, true);
8511
+ const [oldCDBody, eocdBody, oldEoCDinfo] = await cutTheTailOff(provider);
8512
+ const newFileOffset = provider.length;
8513
+ const [localPart, cdHeaderPart] = await generateFileHeaders(fileName, fileToAdd, newFileOffset);
8514
+ await provider.append(localPart);
8515
+ const newCDBody = concatenateArrayBuffers(oldCDBody, cdHeaderPart);
8516
+ const newCDStartOffset = provider.length;
8517
+ await provider.append(new Uint8Array(newCDBody));
8518
+ const eocdOffset = provider.length;
8519
+ await provider.append(await updateEoCD(eocdBody, oldEoCDinfo.offsets, newCDStartOffset, eocdOffset, oldEoCDinfo.cdRecordsNumber + 1n));
8520
+ }
8521
+
8384
8522
  // src/hash-file-utility.ts
8385
8523
  function parseHashTable(arrayBuffer) {
8386
8524
  const dataView = new DataView(arrayBuffer);
@@ -8408,6 +8546,23 @@ var __exports__ = (() => {
8408
8546
  }
8409
8547
  return hashTable;
8410
8548
  }
8549
+ async function composeHashFile(fileProvider) {
8550
+ const hashArray = await makeHashTableFromZipHeaders(fileProvider);
8551
+ const bufferArray = Object.entries(hashArray).map(([key, value]) => concatenateArrayBuffers(hexStringToBuffer(key), bigintToBuffer(value))).sort(compareHashes);
8552
+ return concatenateArrayBuffers(...bufferArray);
8553
+ }
8554
+ function compareHashes(arrA, arrB) {
8555
+ const a = new BigUint64Array(arrA);
8556
+ const b = new BigUint64Array(arrB);
8557
+ return Number(a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]);
8558
+ }
8559
+ function hexStringToBuffer(str) {
8560
+ const byteArray = str.match(/../g)?.map((h) => parseInt(h, 16));
8561
+ return new Uint8Array(byteArray ?? new Array(16)).buffer;
8562
+ }
8563
+ function bigintToBuffer(n) {
8564
+ return new BigUint64Array([n]).buffer;
8565
+ }
8411
8566
 
8412
8567
  // ../compression/src/lib/compression.ts
8413
8568
  var Compression = class {
@@ -11,4 +11,10 @@ export declare function parseHashTable(arrayBuffer: ArrayBuffer): Record<string,
11
11
  * @returns ready to use hash info
12
12
  */
13
13
  export declare function makeHashTableFromZipHeaders(fileProvider: FileProvider): Promise<Record<string, bigint>>;
14
+ /**
15
+ * creates hash file that later can be added to the SLPK archive
16
+ * @param fileProvider SLPK archive where we need to add hash file
17
+ * @returns ArrayBuffer containing hash file
18
+ */
19
+ export declare function composeHashFile(fileProvider: FileProvider): Promise<ArrayBuffer>;
14
20
  //# sourceMappingURL=hash-file-utility.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hash-file-utility.d.ts","sourceRoot":"","sources":["../src/hash-file-utility.ts"],"names":[],"mappings":"AAKA,OAAO,EAAC,YAAY,EAAC,MAAM,0BAA0B,CAAC;AAGtD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAY/E;AASD;;;;GAIG;AACH,wBAAsB,2BAA2B,CAC/C,YAAY,EAAE,YAAY,GACzB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAejC"}
1
+ {"version":3,"file":"hash-file-utility.d.ts","sourceRoot":"","sources":["../src/hash-file-utility.ts"],"names":[],"mappings":"AAKA,OAAO,EAAC,YAAY,EAA0B,MAAM,0BAA0B,CAAC;AAG/E;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAY/E;AASD;;;;GAIG;AACH,wBAAsB,2BAA2B,CAC/C,YAAY,EAAE,YAAY,GACzB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAejC;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,YAAY,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAMtF"}
@@ -1,4 +1,5 @@
1
1
  import { MD5Hash } from '@loaders.gl/crypto';
2
+ import { concatenateArrayBuffers } from '@loaders.gl/loader-utils';
2
3
  import { makeZipCDHeaderIterator } from "./parse-zip/cd-file-header.js";
3
4
  export function parseHashTable(arrayBuffer) {
4
5
  const dataView = new DataView(arrayBuffer);
@@ -26,4 +27,25 @@ export async function makeHashTableFromZipHeaders(fileProvider) {
26
27
  }
27
28
  return hashTable;
28
29
  }
30
+ export async function composeHashFile(fileProvider) {
31
+ const hashArray = await makeHashTableFromZipHeaders(fileProvider);
32
+ const bufferArray = Object.entries(hashArray).map(_ref => {
33
+ let [key, value] = _ref;
34
+ return concatenateArrayBuffers(hexStringToBuffer(key), bigintToBuffer(value));
35
+ }).sort(compareHashes);
36
+ return concatenateArrayBuffers(...bufferArray);
37
+ }
38
+ function compareHashes(arrA, arrB) {
39
+ const a = new BigUint64Array(arrA);
40
+ const b = new BigUint64Array(arrB);
41
+ return Number(a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]);
42
+ }
43
+ function hexStringToBuffer(str) {
44
+ var _str$match;
45
+ const byteArray = (_str$match = str.match(/../g)) === null || _str$match === void 0 ? void 0 : _str$match.map(h => parseInt(h, 16));
46
+ return new Uint8Array(byteArray !== null && byteArray !== void 0 ? byteArray : new Array(16)).buffer;
47
+ }
48
+ function bigintToBuffer(n) {
49
+ return new BigUint64Array([n]).buffer;
50
+ }
29
51
  //# sourceMappingURL=hash-file-utility.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"hash-file-utility.js","names":["MD5Hash","makeZipCDHeaderIterator","parseHashTable","arrayBuffer","dataView","DataView","hashMap","i","byteLength","offset","getBigUint64","hash","bufferToHex","buffer","start","length","Uint8Array","map","x","toString","padStart","join","makeHashTableFromZipHeaders","fileProvider","zipCDIterator","md5Hash","textEncoder","TextEncoder","hashTable","cdHeader","filename","fileName","split","toLocaleLowerCase","encode","md5","localHeaderOffset"],"sources":["../src/hash-file-utility.ts"],"sourcesContent":["// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport {MD5Hash} from '@loaders.gl/crypto';\nimport {FileProvider} from '@loaders.gl/loader-utils';\nimport {makeZipCDHeaderIterator} from './parse-zip/cd-file-header';\n\n/**\n * Reads hash file from buffer and returns it in ready-to-use form\n * @param arrayBuffer - buffer containing hash file\n * @returns Map containing hash and offset\n */\nexport function parseHashTable(arrayBuffer: ArrayBuffer): Record<string, bigint> {\n const dataView = new DataView(arrayBuffer);\n\n const hashMap: Record<string, bigint> = {};\n\n for (let i = 0; i < arrayBuffer.byteLength; i = i + 24) {\n const offset = dataView.getBigUint64(i + 16, true);\n const hash = bufferToHex(arrayBuffer, i, 16);\n hashMap[hash] = offset;\n }\n\n return hashMap;\n}\n\nfunction bufferToHex(buffer: ArrayBuffer, start: number, length: number): string {\n // buffer is an ArrayBuffer\n return [...new Uint8Array(buffer, start, length)]\n .map((x) => x.toString(16).padStart(2, '0'))\n .join('');\n}\n\n/**\n * generates hash info from zip files \"central directory\"\n * @param fileProvider - provider of the archive\n * @returns ready to use hash info\n */\nexport async function makeHashTableFromZipHeaders(\n fileProvider: FileProvider\n): Promise<Record<string, bigint>> {\n const zipCDIterator = makeZipCDHeaderIterator(fileProvider);\n const md5Hash = new MD5Hash();\n const textEncoder = new TextEncoder();\n\n const hashTable: Record<string, bigint> = {};\n\n for await (const cdHeader of zipCDIterator) {\n const filename = cdHeader.fileName.split('\\\\').join('/').toLocaleLowerCase();\n const arrayBuffer = textEncoder.encode(filename).buffer;\n const md5 = await md5Hash.hash(arrayBuffer, 'hex');\n hashTable[md5] = cdHeader.localHeaderOffset;\n }\n\n return hashTable;\n}\n"],"mappings":"AAIA,SAAQA,OAAO,QAAO,oBAAoB;AAAC,SAEnCC,uBAAuB;AAO/B,OAAO,SAASC,cAAcA,CAACC,WAAwB,EAA0B;EAC/E,MAAMC,QAAQ,GAAG,IAAIC,QAAQ,CAACF,WAAW,CAAC;EAE1C,MAAMG,OAA+B,GAAG,CAAC,CAAC;EAE1C,KAAK,IAAIC,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGJ,WAAW,CAACK,UAAU,EAAED,CAAC,GAAGA,CAAC,GAAG,EAAE,EAAE;IACtD,MAAME,MAAM,GAAGL,QAAQ,CAACM,YAAY,CAACH,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC;IAClD,MAAMI,IAAI,GAAGC,WAAW,CAACT,WAAW,EAAEI,CAAC,EAAE,EAAE,CAAC;IAC5CD,OAAO,CAACK,IAAI,CAAC,GAAGF,MAAM;EACxB;EAEA,OAAOH,OAAO;AAChB;AAEA,SAASM,WAAWA,CAACC,MAAmB,EAAEC,KAAa,EAAEC,MAAc,EAAU;EAE/E,OAAO,CAAC,GAAG,IAAIC,UAAU,CAACH,MAAM,EAAEC,KAAK,EAAEC,MAAM,CAAC,CAAC,CAC9CE,GAAG,CAAEC,CAAC,IAAKA,CAAC,CAACC,QAAQ,CAAC,EAAE,CAAC,CAACC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAC3CC,IAAI,CAAC,EAAE,CAAC;AACb;AAOA,OAAO,eAAeC,2BAA2BA,CAC/CC,YAA0B,EACO;EACjC,MAAMC,aAAa,GAAGvB,uBAAuB,CAACsB,YAAY,CAAC;EAC3D,MAAME,OAAO,GAAG,IAAIzB,OAAO,CAAC,CAAC;EAC7B,MAAM0B,WAAW,GAAG,IAAIC,WAAW,CAAC,CAAC;EAErC,MAAMC,SAAiC,GAAG,CAAC,CAAC;EAE5C,WAAW,MAAMC,QAAQ,IAAIL,aAAa,EAAE;IAC1C,MAAMM,QAAQ,GAAGD,QAAQ,CAACE,QAAQ,CAACC,KAAK,CAAC,IAAI,CAAC,CAACX,IAAI,CAAC,GAAG,CAAC,CAACY,iBAAiB,CAAC,CAAC;IAC5E,MAAM9B,WAAW,GAAGuB,WAAW,CAACQ,MAAM,CAACJ,QAAQ,CAAC,CAACjB,MAAM;IACvD,MAAMsB,GAAG,GAAG,MAAMV,OAAO,CAACd,IAAI,CAACR,WAAW,EAAE,KAAK,CAAC;IAClDyB,SAAS,CAACO,GAAG,CAAC,GAAGN,QAAQ,CAACO,iBAAiB;EAC7C;EAEA,OAAOR,SAAS;AAClB"}
1
+ {"version":3,"file":"hash-file-utility.js","names":["MD5Hash","concatenateArrayBuffers","makeZipCDHeaderIterator","parseHashTable","arrayBuffer","dataView","DataView","hashMap","i","byteLength","offset","getBigUint64","hash","bufferToHex","buffer","start","length","Uint8Array","map","x","toString","padStart","join","makeHashTableFromZipHeaders","fileProvider","zipCDIterator","md5Hash","textEncoder","TextEncoder","hashTable","cdHeader","filename","fileName","split","toLocaleLowerCase","encode","md5","localHeaderOffset","composeHashFile","hashArray","bufferArray","Object","entries","_ref","key","value","hexStringToBuffer","bigintToBuffer","sort","compareHashes","arrA","arrB","a","BigUint64Array","b","Number","str","_str$match","byteArray","match","h","parseInt","Array","n"],"sources":["../src/hash-file-utility.ts"],"sourcesContent":["// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport {MD5Hash} from '@loaders.gl/crypto';\nimport {FileProvider, concatenateArrayBuffers} from '@loaders.gl/loader-utils';\nimport {makeZipCDHeaderIterator} from './parse-zip/cd-file-header';\n\n/**\n * Reads hash file from buffer and returns it in ready-to-use form\n * @param arrayBuffer - buffer containing hash file\n * @returns Map containing hash and offset\n */\nexport function parseHashTable(arrayBuffer: ArrayBuffer): Record<string, bigint> {\n const dataView = new DataView(arrayBuffer);\n\n const hashMap: Record<string, bigint> = {};\n\n for (let i = 0; i < arrayBuffer.byteLength; i = i + 24) {\n const offset = dataView.getBigUint64(i + 16, true);\n const hash = bufferToHex(arrayBuffer, i, 16);\n hashMap[hash] = offset;\n }\n\n return hashMap;\n}\n\nfunction bufferToHex(buffer: ArrayBuffer, start: number, length: number): string {\n // buffer is an ArrayBuffer\n return [...new Uint8Array(buffer, start, length)]\n .map((x) => x.toString(16).padStart(2, '0'))\n .join('');\n}\n\n/**\n * generates hash info from zip files \"central directory\"\n * @param fileProvider - provider of the archive\n * @returns ready to use hash info\n */\nexport async function makeHashTableFromZipHeaders(\n fileProvider: FileProvider\n): Promise<Record<string, bigint>> {\n const zipCDIterator = makeZipCDHeaderIterator(fileProvider);\n const md5Hash = new MD5Hash();\n const textEncoder = new TextEncoder();\n\n const hashTable: Record<string, bigint> = {};\n\n for await (const cdHeader of zipCDIterator) {\n const filename = cdHeader.fileName.split('\\\\').join('/').toLocaleLowerCase();\n const arrayBuffer = textEncoder.encode(filename).buffer;\n const md5 = await md5Hash.hash(arrayBuffer, 'hex');\n hashTable[md5] = cdHeader.localHeaderOffset;\n }\n\n return hashTable;\n}\n\n/**\n * creates hash file that later can be added to the SLPK archive\n * @param fileProvider SLPK archive where we need to add hash file\n * @returns ArrayBuffer containing hash file\n */\nexport async function composeHashFile(fileProvider: FileProvider): Promise<ArrayBuffer> {\n const hashArray = await makeHashTableFromZipHeaders(fileProvider);\n const bufferArray = Object.entries(hashArray)\n .map(([key, value]) => concatenateArrayBuffers(hexStringToBuffer(key), bigintToBuffer(value)))\n .sort(compareHashes);\n return concatenateArrayBuffers(...bufferArray);\n}\n\n/**\n * Function to compare md5 hashes according to https://github.com/Esri/i3s-spec/blob/master/docs/2.0/slpk_hashtable.pcsl.md\n * @param arrA first hash to compare\n * @param arrB second hash to compare\n * @returns 0 if equal, negative number if a<b, pozitive if a>b\n */\nfunction compareHashes(arrA: ArrayBuffer, arrB: ArrayBuffer): number {\n const a = new BigUint64Array(arrA);\n const b = new BigUint64Array(arrB);\n\n return Number(a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]);\n}\n\n/**\n * converts hex string to buffer\n * @param str hex string to convert\n * @returns conversion result\n */\nfunction hexStringToBuffer(str: string): ArrayBuffer {\n const byteArray = str.match(/../g)?.map((h) => parseInt(h, 16));\n return new Uint8Array(byteArray ?? new Array(16)).buffer;\n}\n\n/**\n * converts bigint to buffer\n * @param n bigint to convert\n * @returns convertion result\n */\nfunction bigintToBuffer(n: bigint): ArrayBuffer {\n return new BigUint64Array([n]).buffer;\n}\n"],"mappings":"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"}
package/dist/index.cjs CHANGED
@@ -35,6 +35,8 @@ __export(src_exports, {
35
35
  ZipFileSystem: () => ZipFileSystem,
36
36
  ZipLoader: () => ZipLoader,
37
37
  ZipWriter: () => ZipWriter,
38
+ addOneFile: () => addOneFile,
39
+ composeHashFile: () => composeHashFile,
38
40
  generateCDHeader: () => generateCDHeader,
39
41
  generateLocalHeader: () => generateLocalHeader,
40
42
  localHeaderSignature: () => signature3,
@@ -443,9 +445,13 @@ var eoCDSignature = new Uint8Array([80, 75, 5, 6]);
443
445
  var zip64EoCDLocatorSignature = new Uint8Array([80, 75, 6, 7]);
444
446
  var zip64EoCDSignature = new Uint8Array([80, 75, 6, 6]);
445
447
  var CD_RECORDS_NUMBER_OFFSET = 8n;
448
+ var CD_RECORDS_NUMBER_ON_DISC_OFFSET = 10n;
449
+ var CD_CD_BYTE_SIZE_OFFSET = 12n;
446
450
  var CD_START_OFFSET_OFFSET = 16n;
447
451
  var ZIP64_EOCD_START_OFFSET_OFFSET = 8n;
448
452
  var ZIP64_CD_RECORDS_NUMBER_OFFSET = 24n;
453
+ var ZIP64_CD_RECORDS_NUMBER_ON_DISC_OFFSET = 32n;
454
+ var ZIP64_CD_CD_BYTE_SIZE_OFFSET = 40n;
449
455
  var ZIP64_CD_START_OFFSET_OFFSET = 48n;
450
456
  var parseEoCDRecord = async (file) => {
451
457
  const zipEoCDOffset = await searchFromTheEnd(file, eoCDSignature);
@@ -477,6 +483,39 @@ var parseEoCDRecord = async (file) => {
477
483
  }
478
484
  };
479
485
  };
486
+ async function updateEoCD(eocdBody, oldEoCDOffsets, newCDStartOffset, eocdStartOffset, newCDRecordsNumber) {
487
+ const eocd = new DataView(eocdBody);
488
+ const classicEoCDOffset = oldEoCDOffsets.zip64EoCDOffset ? oldEoCDOffsets.zipEoCDOffset - oldEoCDOffsets.zip64EoCDOffset : 0n;
489
+ if (Number(newCDRecordsNumber) <= 65535) {
490
+ setFieldToNumber(eocd, 2, classicEoCDOffset + CD_RECORDS_NUMBER_OFFSET, newCDRecordsNumber);
491
+ setFieldToNumber(
492
+ eocd,
493
+ 2,
494
+ classicEoCDOffset + CD_RECORDS_NUMBER_ON_DISC_OFFSET,
495
+ newCDRecordsNumber
496
+ );
497
+ }
498
+ if (eocdStartOffset - newCDStartOffset <= 4294967295) {
499
+ setFieldToNumber(
500
+ eocd,
501
+ 4,
502
+ classicEoCDOffset + CD_CD_BYTE_SIZE_OFFSET,
503
+ eocdStartOffset - newCDStartOffset
504
+ );
505
+ }
506
+ if (newCDStartOffset < 4294967295) {
507
+ setFieldToNumber(eocd, 4, classicEoCDOffset + CD_START_OFFSET_OFFSET, newCDStartOffset);
508
+ }
509
+ if (oldEoCDOffsets.zip64EoCDLocatorOffset && oldEoCDOffsets.zip64EoCDOffset) {
510
+ const locatorOffset = oldEoCDOffsets.zip64EoCDLocatorOffset - oldEoCDOffsets.zip64EoCDOffset;
511
+ setFieldToNumber(eocd, 8, locatorOffset + ZIP64_EOCD_START_OFFSET_OFFSET, eocdStartOffset);
512
+ setFieldToNumber(eocd, 8, ZIP64_CD_START_OFFSET_OFFSET, newCDStartOffset);
513
+ setFieldToNumber(eocd, 8, ZIP64_CD_RECORDS_NUMBER_OFFSET, newCDRecordsNumber);
514
+ setFieldToNumber(eocd, 8, ZIP64_CD_RECORDS_NUMBER_ON_DISC_OFFSET, newCDRecordsNumber);
515
+ setFieldToNumber(eocd, 8, ZIP64_CD_CD_BYTE_SIZE_OFFSET, eocdStartOffset - newCDStartOffset);
516
+ }
517
+ return new Uint8Array(eocd.buffer);
518
+ }
480
519
 
481
520
  // src/parse-zip/cd-file-header.ts
482
521
  var CD_COMPRESSED_SIZE_OFFSET = 20n;
@@ -857,8 +896,63 @@ var ZIP_HEADER_FIELDS2 = [
857
896
  }
858
897
  ];
859
898
 
860
- // src/hash-file-utility.ts
899
+ // src/parse-zip/zip-compozition.ts
900
+ var import_loader_utils5 = require("@loaders.gl/loader-utils");
861
901
  var import_crypto = require("@loaders.gl/crypto");
902
+ async function cutTheTailOff(provider) {
903
+ const oldEoCDinfo = await parseEoCDRecord(provider);
904
+ const oldCDStartOffset = oldEoCDinfo.cdStartOffset;
905
+ const oldCDLength = Number(
906
+ oldEoCDinfo.offsets.zip64EoCDOffset ? oldEoCDinfo.offsets.zip64EoCDOffset - oldCDStartOffset : oldEoCDinfo.offsets.zipEoCDOffset - oldCDStartOffset
907
+ );
908
+ const zipEnding = await provider.slice(oldCDStartOffset, provider.length);
909
+ await provider.truncate(Number(oldCDStartOffset));
910
+ const oldCDBody = zipEnding.slice(0, oldCDLength);
911
+ const eocdBody = zipEnding.slice(oldCDLength, zipEnding.byteLength);
912
+ return [oldCDBody, eocdBody, oldEoCDinfo];
913
+ }
914
+ async function generateFileHeaders(fileName, fileToAdd, localFileHeaderOffset) {
915
+ const newFileCRC322 = parseInt(await new import_crypto.CRC32Hash().hash(fileToAdd, "hex"), 16);
916
+ const newFileLocalHeader = generateLocalHeader({
917
+ crc32: newFileCRC322,
918
+ fileName,
919
+ length: fileToAdd.byteLength
920
+ });
921
+ const newFileCDHeader = generateCDHeader({
922
+ crc32: newFileCRC322,
923
+ fileName,
924
+ offset: localFileHeaderOffset,
925
+ length: fileToAdd.byteLength
926
+ });
927
+ return [
928
+ new Uint8Array((0, import_loader_utils5.concatenateArrayBuffers)(newFileLocalHeader, fileToAdd)),
929
+ new Uint8Array(newFileCDHeader)
930
+ ];
931
+ }
932
+ async function addOneFile(zipUrl, fileToAdd, fileName) {
933
+ const provider = new import_loader_utils5.FileHandleFile(zipUrl, true);
934
+ const [oldCDBody, eocdBody, oldEoCDinfo] = await cutTheTailOff(provider);
935
+ const newFileOffset = provider.length;
936
+ const [localPart, cdHeaderPart] = await generateFileHeaders(fileName, fileToAdd, newFileOffset);
937
+ await provider.append(localPart);
938
+ const newCDBody = (0, import_loader_utils5.concatenateArrayBuffers)(oldCDBody, cdHeaderPart);
939
+ const newCDStartOffset = provider.length;
940
+ await provider.append(new Uint8Array(newCDBody));
941
+ const eocdOffset = provider.length;
942
+ await provider.append(
943
+ await updateEoCD(
944
+ eocdBody,
945
+ oldEoCDinfo.offsets,
946
+ newCDStartOffset,
947
+ eocdOffset,
948
+ oldEoCDinfo.cdRecordsNumber + 1n
949
+ )
950
+ );
951
+ }
952
+
953
+ // src/hash-file-utility.ts
954
+ var import_crypto2 = require("@loaders.gl/crypto");
955
+ var import_loader_utils6 = require("@loaders.gl/loader-utils");
862
956
  function parseHashTable(arrayBuffer) {
863
957
  const dataView = new DataView(arrayBuffer);
864
958
  const hashMap = {};
@@ -874,7 +968,7 @@ function bufferToHex(buffer, start, length) {
874
968
  }
875
969
  async function makeHashTableFromZipHeaders(fileProvider) {
876
970
  const zipCDIterator = makeZipCDHeaderIterator(fileProvider);
877
- const md5Hash = new import_crypto.MD5Hash();
971
+ const md5Hash = new import_crypto2.MD5Hash();
878
972
  const textEncoder = new TextEncoder();
879
973
  const hashTable = {};
880
974
  for await (const cdHeader of zipCDIterator) {
@@ -885,11 +979,29 @@ async function makeHashTableFromZipHeaders(fileProvider) {
885
979
  }
886
980
  return hashTable;
887
981
  }
982
+ async function composeHashFile(fileProvider) {
983
+ const hashArray = await makeHashTableFromZipHeaders(fileProvider);
984
+ const bufferArray = Object.entries(hashArray).map(([key, value]) => (0, import_loader_utils6.concatenateArrayBuffers)(hexStringToBuffer(key), bigintToBuffer(value))).sort(compareHashes);
985
+ return (0, import_loader_utils6.concatenateArrayBuffers)(...bufferArray);
986
+ }
987
+ function compareHashes(arrA, arrB) {
988
+ const a = new BigUint64Array(arrA);
989
+ const b = new BigUint64Array(arrB);
990
+ return Number(a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]);
991
+ }
992
+ function hexStringToBuffer(str) {
993
+ var _a;
994
+ const byteArray = (_a = str.match(/../g)) == null ? void 0 : _a.map((h) => parseInt(h, 16));
995
+ return new Uint8Array(byteArray ?? new Array(16)).buffer;
996
+ }
997
+ function bigintToBuffer(n) {
998
+ return new BigUint64Array([n]).buffer;
999
+ }
888
1000
 
889
1001
  // src/filesystems/zip-filesystem.ts
890
- var import_loader_utils5 = require("@loaders.gl/loader-utils");
891
- var import_loader_utils6 = require("@loaders.gl/loader-utils");
892
1002
  var import_loader_utils7 = require("@loaders.gl/loader-utils");
1003
+ var import_loader_utils8 = require("@loaders.gl/loader-utils");
1004
+ var import_loader_utils9 = require("@loaders.gl/loader-utils");
893
1005
  var import_compression = require("@loaders.gl/compression");
894
1006
  var COMPRESSION_METHODS = {
895
1007
  /** No compression */
@@ -911,12 +1023,12 @@ var ZipFileSystem = class {
911
1023
  this.fileProvider = null;
912
1024
  if (typeof file === "string") {
913
1025
  this.fileName = file;
914
- if (!import_loader_utils5.isBrowser) {
915
- this.fileProvider = new import_loader_utils7.FileHandleFile(file);
1026
+ if (!import_loader_utils7.isBrowser) {
1027
+ this.fileProvider = new import_loader_utils9.FileHandleFile(file);
916
1028
  } else {
917
1029
  throw new Error("Cannot open file for random access in a WEB browser");
918
1030
  }
919
- } else if ((0, import_loader_utils6.isFileProvider)(file)) {
1031
+ } else if ((0, import_loader_utils8.isFileProvider)(file)) {
920
1032
  this.fileProvider = file;
921
1033
  }
922
1034
  }
package/dist/index.d.ts CHANGED
@@ -5,6 +5,7 @@ export { parseZipCDFileHeader, makeZipCDHeaderIterator, signature as CD_HEADER_S
5
5
  export { parseZipLocalFileHeader, signature as localHeaderSignature, generateLocalHeader } 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';
8
- export { parseHashTable, makeHashTableFromZipHeaders } from './hash-file-utility';
8
+ export { addOneFile } from './parse-zip/zip-compozition';
9
+ export { parseHashTable, makeHashTableFromZipHeaders, composeHashFile } from './hash-file-utility';
9
10
  export { ZipFileSystem } from './filesystems/zip-filesystem';
10
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,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,EACjC,mBAAmB,EACpB,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":"AAIA,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,EACjC,mBAAmB,EACpB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAC,eAAe,EAAC,MAAM,sCAAsC,CAAC;AACrE,OAAO,EAAC,gBAAgB,EAAC,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAC,UAAU,EAAC,MAAM,6BAA6B,CAAC;AAGvD,OAAO,EAAC,cAAc,EAAE,2BAA2B,EAAE,eAAe,EAAC,MAAM,qBAAqB,CAAC;AAEjG,OAAO,EAAC,aAAa,EAAC,MAAM,8BAA8B,CAAC"}
package/dist/index.js CHANGED
@@ -5,6 +5,7 @@ export { parseZipCDFileHeader, makeZipCDHeaderIterator, signature as CD_HEADER_S
5
5
  export { parseZipLocalFileHeader, signature as localHeaderSignature, generateLocalHeader } 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";
8
- export { parseHashTable, makeHashTableFromZipHeaders } from "./hash-file-utility.js";
8
+ export { addOneFile } from "./parse-zip/zip-compozition.js";
9
+ export { parseHashTable, makeHashTableFromZipHeaders, composeHashFile } from "./hash-file-utility.js";
9
10
  export { ZipFileSystem } from "./filesystems/zip-filesystem.js";
10
11
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["ZipLoader","ZipWriter","TarBuilder","parseZipCDFileHeader","makeZipCDHeaderIterator","signature","CD_HEADER_SIGNATURE","generateCDHeader","parseZipLocalFileHeader","localHeaderSignature","generateLocalHeader","parseEoCDRecord","searchFromTheEnd","parseHashTable","makeHashTableFromZipHeaders","ZipFileSystem"],"sources":["../src/index.ts"],"sourcesContent":["// loaders.gl\n// SPDX-License-Identifier: MIT\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 generateLocalHeader\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":"SAIQA,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,EACjCC,mBAAmB;AAAA,SAEbC,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","generateLocalHeader","parseEoCDRecord","searchFromTheEnd","addOneFile","parseHashTable","makeHashTableFromZipHeaders","composeHashFile","ZipFileSystem"],"sources":["../src/index.ts"],"sourcesContent":["// loaders.gl\n// SPDX-License-Identifier: MIT\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 generateLocalHeader\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';\nexport {addOneFile} from './parse-zip/zip-compozition';\n\n// export type {HashElement} from './hash-file-utility';\nexport {parseHashTable, makeHashTableFromZipHeaders, composeHashFile} from './hash-file-utility';\n\nexport {ZipFileSystem} from './filesystems/zip-filesystem';\n"],"mappings":"SAIQA,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,EACjCC,mBAAmB;AAAA,SAEbC,eAAe;AAAA,SACfC,gBAAgB;AAAA,SAChBC,UAAU;AAAA,SAGVC,cAAc,EAAEC,2BAA2B,EAAEC,eAAe;AAAA,SAE5DC,aAAa"}
@@ -1 +1 @@
1
- {"version":3,"file":"end-of-central-directory.d.ts","sourceRoot":"","sources":["../../src/parse-zip/end-of-central-directory.ts"],"names":[],"mappings":"AAIA,OAAO,EAAC,YAAY,EAAsB,MAAM,0BAA0B,CAAC;AAI3E;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,2CAA2C;IAC3C,aAAa,EAAE,MAAM,CAAC;IACtB,2CAA2C;IAC3C,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,oBAAoB,CAAC;CAC/B,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,aAAa,EAAE,MAAM,CAAC;IAEtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC,CAAC;AAiBF;;;;GAIG;AACH,eAAO,MAAM,eAAe,SAAgB,YAAY,KAAG,QAAQ,aAAa,CAmC/E,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,QAAQ,EAAE,WAAW,EACrB,cAAc,EAAE,oBAAoB,EACpC,gBAAgB,EAAE,MAAM,EACxB,eAAe,EAAE,MAAM,EACvB,kBAAkB,EAAE,MAAM,GACzB,OAAO,CAAC,UAAU,CAAC,CAiDrB"}
1
+ {"version":3,"file":"end-of-central-directory.d.ts","sourceRoot":"","sources":["../../src/parse-zip/end-of-central-directory.ts"],"names":[],"mappings":"AAIA,OAAO,EAAC,YAAY,EAAsB,MAAM,0BAA0B,CAAC;AAI3E;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,2CAA2C;IAC3C,aAAa,EAAE,MAAM,CAAC;IACtB,2CAA2C;IAC3C,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,oBAAoB,CAAC;CAC/B,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,aAAa,EAAE,MAAM,CAAC;IAEtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC,CAAC;AAiBF;;;;GAIG;AACH,eAAO,MAAM,eAAe,SAAgB,YAAY,KAAG,QAAQ,aAAa,CAmC/E,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,QAAQ,EAAE,WAAW,EACrB,cAAc,EAAE,oBAAoB,EACpC,gBAAgB,EAAE,MAAM,EACxB,eAAe,EAAE,MAAM,EACvB,kBAAkB,EAAE,MAAM,GACzB,OAAO,CAAC,UAAU,CAAC,CAmDrB"}
@@ -42,9 +42,8 @@ export const parseEoCDRecord = async file => {
42
42
  };
43
43
  };
44
44
  export async function updateEoCD(eocdBody, oldEoCDOffsets, newCDStartOffset, eocdStartOffset, newCDRecordsNumber) {
45
- var _oldEoCDOffsets$zip;
46
45
  const eocd = new DataView(eocdBody);
47
- const classicEoCDOffset = oldEoCDOffsets.zipEoCDOffset - ((_oldEoCDOffsets$zip = oldEoCDOffsets.zip64EoCDOffset) !== null && _oldEoCDOffsets$zip !== void 0 ? _oldEoCDOffsets$zip : 0n);
46
+ const classicEoCDOffset = oldEoCDOffsets.zip64EoCDOffset ? oldEoCDOffsets.zipEoCDOffset - oldEoCDOffsets.zip64EoCDOffset : 0n;
48
47
  if (Number(newCDRecordsNumber) <= 0xffff) {
49
48
  setFieldToNumber(eocd, 2, classicEoCDOffset + CD_RECORDS_NUMBER_OFFSET, newCDRecordsNumber);
50
49
  setFieldToNumber(eocd, 2, classicEoCDOffset + CD_RECORDS_NUMBER_ON_DISC_OFFSET, newCDRecordsNumber);
@@ -1 +1 @@
1
- {"version":3,"file":"end-of-central-directory.js","names":["compareArrayBuffers","searchFromTheEnd","setFieldToNumber","eoCDSignature","Uint8Array","zip64EoCDLocatorSignature","zip64EoCDSignature","CD_RECORDS_NUMBER_OFFSET","CD_RECORDS_NUMBER_ON_DISC_OFFSET","CD_CD_BYTE_SIZE_OFFSET","CD_START_OFFSET_OFFSET","ZIP64_EOCD_START_OFFSET_OFFSET","ZIP64_CD_RECORDS_NUMBER_OFFSET","ZIP64_CD_RECORDS_NUMBER_ON_DISC_OFFSET","ZIP64_CD_CD_BYTE_SIZE_OFFSET","ZIP64_CD_START_OFFSET_OFFSET","parseEoCDRecord","file","zipEoCDOffset","cdRecordsNumber","BigInt","getUint16","cdStartOffset","getUint32","zip64EoCDLocatorOffset","zip64EoCDOffset","magicBytes","slice","getBigUint64","endOfCDMagicBytes","buffer","Error","offsets","updateEoCD","eocdBody","oldEoCDOffsets","newCDStartOffset","eocdStartOffset","newCDRecordsNumber","_oldEoCDOffsets$zip","eocd","DataView","classicEoCDOffset","Number","locatorOffset"],"sources":["../../src/parse-zip/end-of-central-directory.ts"],"sourcesContent":["// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport {FileProvider, compareArrayBuffers} from '@loaders.gl/loader-utils';\nimport {ZipSignature, searchFromTheEnd} from './search-from-the-end';\nimport {setFieldToNumber} from './zip64-info-generation';\n\n/**\n * End of central directory info\n * according to https://en.wikipedia.org/wiki/ZIP_(file_format)\n */\nexport type ZipEoCDRecord = {\n /** Relative offset of local file header */\n cdStartOffset: bigint;\n /** Relative offset of local file header */\n cdRecordsNumber: bigint;\n offsets: ZipEoCDRecordOffsets;\n};\n\n/**\n * End of central directory offsets\n * according to https://en.wikipedia.org/wiki/ZIP_(file_format)\n */\nexport type ZipEoCDRecordOffsets = {\n zipEoCDOffset: bigint;\n\n zip64EoCDOffset?: bigint;\n zip64EoCDLocatorOffset?: bigint;\n};\n\nconst eoCDSignature: ZipSignature = new Uint8Array([0x50, 0x4b, 0x05, 0x06]);\nconst zip64EoCDLocatorSignature = new Uint8Array([0x50, 0x4b, 0x06, 0x07]);\nconst zip64EoCDSignature = new Uint8Array([0x50, 0x4b, 0x06, 0x06]);\n\n// offsets accroding to https://en.wikipedia.org/wiki/ZIP_(file_format)\nconst CD_RECORDS_NUMBER_OFFSET = 8n;\nconst CD_RECORDS_NUMBER_ON_DISC_OFFSET = 10n;\nconst CD_CD_BYTE_SIZE_OFFSET = 12n;\nconst CD_START_OFFSET_OFFSET = 16n;\nconst ZIP64_EOCD_START_OFFSET_OFFSET = 8n;\nconst ZIP64_CD_RECORDS_NUMBER_OFFSET = 24n;\nconst ZIP64_CD_RECORDS_NUMBER_ON_DISC_OFFSET = 32n;\nconst ZIP64_CD_CD_BYTE_SIZE_OFFSET = 40n;\nconst ZIP64_CD_START_OFFSET_OFFSET = 48n;\n\n/**\n * Parses end of central directory record of zip file\n * @param file - FileProvider instance\n * @returns Info from the header\n */\nexport const parseEoCDRecord = async (file: FileProvider): Promise<ZipEoCDRecord> => {\n const zipEoCDOffset = await searchFromTheEnd(file, eoCDSignature);\n\n let cdRecordsNumber = BigInt(await file.getUint16(zipEoCDOffset + CD_RECORDS_NUMBER_OFFSET));\n let cdStartOffset = BigInt(await file.getUint32(zipEoCDOffset + CD_START_OFFSET_OFFSET));\n\n let zip64EoCDLocatorOffset = zipEoCDOffset - 20n;\n let zip64EoCDOffset = 0n;\n\n const magicBytes = await file.slice(zip64EoCDLocatorOffset, zip64EoCDLocatorOffset + 4n);\n if (compareArrayBuffers(magicBytes, zip64EoCDLocatorSignature)) {\n zip64EoCDOffset = await file.getBigUint64(\n zip64EoCDLocatorOffset + ZIP64_EOCD_START_OFFSET_OFFSET\n );\n\n const endOfCDMagicBytes = await file.slice(zip64EoCDOffset, zip64EoCDOffset + 4n);\n if (!compareArrayBuffers(endOfCDMagicBytes, zip64EoCDSignature.buffer)) {\n throw new Error('zip64 EoCD not found');\n }\n\n cdRecordsNumber = await file.getBigUint64(zip64EoCDOffset + ZIP64_CD_RECORDS_NUMBER_OFFSET);\n cdStartOffset = await file.getBigUint64(zip64EoCDOffset + ZIP64_CD_START_OFFSET_OFFSET);\n } else {\n zip64EoCDLocatorOffset = 0n;\n }\n\n return {\n cdRecordsNumber,\n cdStartOffset,\n offsets: {\n zip64EoCDOffset,\n zip64EoCDLocatorOffset,\n zipEoCDOffset\n }\n };\n};\n\n/**\n * updates EoCD record to add more files to the archieve\n * @param eocdBody buffer containing header\n * @param oldEoCDOffsets info read from EoCD record befor updating\n * @param newCDStartOffset CD start offset to be updated\n * @param eocdStartOffset EoCD start offset to be updated\n * @returns new EoCD header\n */\nexport async function updateEoCD(\n eocdBody: ArrayBuffer,\n oldEoCDOffsets: ZipEoCDRecordOffsets,\n newCDStartOffset: bigint,\n eocdStartOffset: bigint,\n newCDRecordsNumber: bigint\n): Promise<Uint8Array> {\n const eocd = new DataView(eocdBody);\n\n const classicEoCDOffset = oldEoCDOffsets.zipEoCDOffset - (oldEoCDOffsets.zip64EoCDOffset ?? 0n);\n\n // updating classic EoCD record with new CD records number in general and on disc\n if (Number(newCDRecordsNumber) <= 0xffff) {\n setFieldToNumber(eocd, 2, classicEoCDOffset + CD_RECORDS_NUMBER_OFFSET, newCDRecordsNumber);\n setFieldToNumber(\n eocd,\n 2,\n classicEoCDOffset + CD_RECORDS_NUMBER_ON_DISC_OFFSET,\n newCDRecordsNumber\n );\n }\n\n // updating zip64 EoCD record with new size of CD\n if (eocdStartOffset - newCDStartOffset <= 0xffffffff) {\n setFieldToNumber(\n eocd,\n 4,\n classicEoCDOffset + CD_CD_BYTE_SIZE_OFFSET,\n eocdStartOffset - newCDStartOffset\n );\n }\n\n // updating classic EoCD record with new CD start offset\n if (newCDStartOffset < 0xffffffff) {\n setFieldToNumber(eocd, 4, classicEoCDOffset + CD_START_OFFSET_OFFSET, newCDStartOffset);\n }\n\n // updating zip64 EoCD locator and record with new EoCD record start offset and cd records number\n if (oldEoCDOffsets.zip64EoCDLocatorOffset && oldEoCDOffsets.zip64EoCDOffset) {\n // updating zip64 EoCD locator with new EoCD record start offset\n const locatorOffset = oldEoCDOffsets.zip64EoCDLocatorOffset - oldEoCDOffsets.zip64EoCDOffset;\n setFieldToNumber(eocd, 8, locatorOffset + ZIP64_EOCD_START_OFFSET_OFFSET, eocdStartOffset);\n\n // updating zip64 EoCD record with new cd start offset\n setFieldToNumber(eocd, 8, ZIP64_CD_START_OFFSET_OFFSET, newCDStartOffset);\n\n // updating zip64 EoCD record with new cd records number\n setFieldToNumber(eocd, 8, ZIP64_CD_RECORDS_NUMBER_OFFSET, newCDRecordsNumber);\n setFieldToNumber(eocd, 8, ZIP64_CD_RECORDS_NUMBER_ON_DISC_OFFSET, newCDRecordsNumber);\n\n // updating zip64 EoCD record with new size of CD\n setFieldToNumber(eocd, 8, ZIP64_CD_CD_BYTE_SIZE_OFFSET, eocdStartOffset - newCDStartOffset);\n }\n\n return new Uint8Array(eocd.buffer);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"end-of-central-directory.js","names":["compareArrayBuffers","searchFromTheEnd","setFieldToNumber","eoCDSignature","Uint8Array","zip64EoCDLocatorSignature","zip64EoCDSignature","CD_RECORDS_NUMBER_OFFSET","CD_RECORDS_NUMBER_ON_DISC_OFFSET","CD_CD_BYTE_SIZE_OFFSET","CD_START_OFFSET_OFFSET","ZIP64_EOCD_START_OFFSET_OFFSET","ZIP64_CD_RECORDS_NUMBER_OFFSET","ZIP64_CD_RECORDS_NUMBER_ON_DISC_OFFSET","ZIP64_CD_CD_BYTE_SIZE_OFFSET","ZIP64_CD_START_OFFSET_OFFSET","parseEoCDRecord","file","zipEoCDOffset","cdRecordsNumber","BigInt","getUint16","cdStartOffset","getUint32","zip64EoCDLocatorOffset","zip64EoCDOffset","magicBytes","slice","getBigUint64","endOfCDMagicBytes","buffer","Error","offsets","updateEoCD","eocdBody","oldEoCDOffsets","newCDStartOffset","eocdStartOffset","newCDRecordsNumber","eocd","DataView","classicEoCDOffset","Number","locatorOffset"],"sources":["../../src/parse-zip/end-of-central-directory.ts"],"sourcesContent":["// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport {FileProvider, compareArrayBuffers} from '@loaders.gl/loader-utils';\nimport {ZipSignature, searchFromTheEnd} from './search-from-the-end';\nimport {setFieldToNumber} from './zip64-info-generation';\n\n/**\n * End of central directory info\n * according to https://en.wikipedia.org/wiki/ZIP_(file_format)\n */\nexport type ZipEoCDRecord = {\n /** Relative offset of local file header */\n cdStartOffset: bigint;\n /** Relative offset of local file header */\n cdRecordsNumber: bigint;\n offsets: ZipEoCDRecordOffsets;\n};\n\n/**\n * End of central directory offsets\n * according to https://en.wikipedia.org/wiki/ZIP_(file_format)\n */\nexport type ZipEoCDRecordOffsets = {\n zipEoCDOffset: bigint;\n\n zip64EoCDOffset?: bigint;\n zip64EoCDLocatorOffset?: bigint;\n};\n\nconst eoCDSignature: ZipSignature = new Uint8Array([0x50, 0x4b, 0x05, 0x06]);\nconst zip64EoCDLocatorSignature = new Uint8Array([0x50, 0x4b, 0x06, 0x07]);\nconst zip64EoCDSignature = new Uint8Array([0x50, 0x4b, 0x06, 0x06]);\n\n// offsets accroding to https://en.wikipedia.org/wiki/ZIP_(file_format)\nconst CD_RECORDS_NUMBER_OFFSET = 8n;\nconst CD_RECORDS_NUMBER_ON_DISC_OFFSET = 10n;\nconst CD_CD_BYTE_SIZE_OFFSET = 12n;\nconst CD_START_OFFSET_OFFSET = 16n;\nconst ZIP64_EOCD_START_OFFSET_OFFSET = 8n;\nconst ZIP64_CD_RECORDS_NUMBER_OFFSET = 24n;\nconst ZIP64_CD_RECORDS_NUMBER_ON_DISC_OFFSET = 32n;\nconst ZIP64_CD_CD_BYTE_SIZE_OFFSET = 40n;\nconst ZIP64_CD_START_OFFSET_OFFSET = 48n;\n\n/**\n * Parses end of central directory record of zip file\n * @param file - FileProvider instance\n * @returns Info from the header\n */\nexport const parseEoCDRecord = async (file: FileProvider): Promise<ZipEoCDRecord> => {\n const zipEoCDOffset = await searchFromTheEnd(file, eoCDSignature);\n\n let cdRecordsNumber = BigInt(await file.getUint16(zipEoCDOffset + CD_RECORDS_NUMBER_OFFSET));\n let cdStartOffset = BigInt(await file.getUint32(zipEoCDOffset + CD_START_OFFSET_OFFSET));\n\n let zip64EoCDLocatorOffset = zipEoCDOffset - 20n;\n let zip64EoCDOffset = 0n;\n\n const magicBytes = await file.slice(zip64EoCDLocatorOffset, zip64EoCDLocatorOffset + 4n);\n if (compareArrayBuffers(magicBytes, zip64EoCDLocatorSignature)) {\n zip64EoCDOffset = await file.getBigUint64(\n zip64EoCDLocatorOffset + ZIP64_EOCD_START_OFFSET_OFFSET\n );\n\n const endOfCDMagicBytes = await file.slice(zip64EoCDOffset, zip64EoCDOffset + 4n);\n if (!compareArrayBuffers(endOfCDMagicBytes, zip64EoCDSignature.buffer)) {\n throw new Error('zip64 EoCD not found');\n }\n\n cdRecordsNumber = await file.getBigUint64(zip64EoCDOffset + ZIP64_CD_RECORDS_NUMBER_OFFSET);\n cdStartOffset = await file.getBigUint64(zip64EoCDOffset + ZIP64_CD_START_OFFSET_OFFSET);\n } else {\n zip64EoCDLocatorOffset = 0n;\n }\n\n return {\n cdRecordsNumber,\n cdStartOffset,\n offsets: {\n zip64EoCDOffset,\n zip64EoCDLocatorOffset,\n zipEoCDOffset\n }\n };\n};\n\n/**\n * updates EoCD record to add more files to the archieve\n * @param eocdBody buffer containing header\n * @param oldEoCDOffsets info read from EoCD record befor updating\n * @param newCDStartOffset CD start offset to be updated\n * @param eocdStartOffset EoCD start offset to be updated\n * @returns new EoCD header\n */\nexport async function updateEoCD(\n eocdBody: ArrayBuffer,\n oldEoCDOffsets: ZipEoCDRecordOffsets,\n newCDStartOffset: bigint,\n eocdStartOffset: bigint,\n newCDRecordsNumber: bigint\n): Promise<Uint8Array> {\n const eocd = new DataView(eocdBody);\n\n const classicEoCDOffset = oldEoCDOffsets.zip64EoCDOffset\n ? oldEoCDOffsets.zipEoCDOffset - oldEoCDOffsets.zip64EoCDOffset\n : 0n;\n\n // updating classic EoCD record with new CD records number in general and on disc\n if (Number(newCDRecordsNumber) <= 0xffff) {\n setFieldToNumber(eocd, 2, classicEoCDOffset + CD_RECORDS_NUMBER_OFFSET, newCDRecordsNumber);\n setFieldToNumber(\n eocd,\n 2,\n classicEoCDOffset + CD_RECORDS_NUMBER_ON_DISC_OFFSET,\n newCDRecordsNumber\n );\n }\n\n // updating zip64 EoCD record with new size of CD\n if (eocdStartOffset - newCDStartOffset <= 0xffffffff) {\n setFieldToNumber(\n eocd,\n 4,\n classicEoCDOffset + CD_CD_BYTE_SIZE_OFFSET,\n eocdStartOffset - newCDStartOffset\n );\n }\n\n // updating classic EoCD record with new CD start offset\n if (newCDStartOffset < 0xffffffff) {\n setFieldToNumber(eocd, 4, classicEoCDOffset + CD_START_OFFSET_OFFSET, newCDStartOffset);\n }\n\n // updating zip64 EoCD locator and record with new EoCD record start offset and cd records number\n if (oldEoCDOffsets.zip64EoCDLocatorOffset && oldEoCDOffsets.zip64EoCDOffset) {\n // updating zip64 EoCD locator with new EoCD record start offset\n const locatorOffset = oldEoCDOffsets.zip64EoCDLocatorOffset - oldEoCDOffsets.zip64EoCDOffset;\n setFieldToNumber(eocd, 8, locatorOffset + ZIP64_EOCD_START_OFFSET_OFFSET, eocdStartOffset);\n\n // updating zip64 EoCD record with new cd start offset\n setFieldToNumber(eocd, 8, ZIP64_CD_START_OFFSET_OFFSET, newCDStartOffset);\n\n // updating zip64 EoCD record with new cd records number\n setFieldToNumber(eocd, 8, ZIP64_CD_RECORDS_NUMBER_OFFSET, newCDRecordsNumber);\n setFieldToNumber(eocd, 8, ZIP64_CD_RECORDS_NUMBER_ON_DISC_OFFSET, newCDRecordsNumber);\n\n // updating zip64 EoCD record with new size of CD\n setFieldToNumber(eocd, 8, ZIP64_CD_CD_BYTE_SIZE_OFFSET, eocdStartOffset - newCDStartOffset);\n }\n\n return new Uint8Array(eocd.buffer);\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import JSZip from 'jszip';
2
- const VERSION = typeof "4.1.0-alpha.4" !== 'undefined' ? "4.1.0-alpha.4" : 'latest';
2
+ const VERSION = typeof "4.1.0-alpha.5" !== 'undefined' ? "4.1.0-alpha.5" : 'latest';
3
3
  export const ZipLoader = {
4
4
  id: 'zip',
5
5
  module: 'zip',
@@ -1,5 +1,5 @@
1
1
  import JSZip from 'jszip';
2
- const VERSION = typeof "4.1.0-alpha.4" !== 'undefined' ? "4.1.0-alpha.4" : 'latest';
2
+ const VERSION = typeof "4.1.0-alpha.5" !== 'undefined' ? "4.1.0-alpha.5" : 'latest';
3
3
  export const ZipWriter = {
4
4
  name: 'Zip Archive',
5
5
  id: 'zip',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loaders.gl/zip",
3
- "version": "4.1.0-alpha.4",
3
+ "version": "4.1.0-alpha.5",
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.1.0-alpha.4",
42
- "@loaders.gl/crypto": "4.1.0-alpha.4",
43
- "@loaders.gl/loader-utils": "4.1.0-alpha.4",
41
+ "@loaders.gl/compression": "4.1.0-alpha.5",
42
+ "@loaders.gl/crypto": "4.1.0-alpha.5",
43
+ "@loaders.gl/loader-utils": "4.1.0-alpha.5",
44
44
  "jszip": "^3.1.5",
45
45
  "md5": "^2.3.0"
46
46
  },
47
- "gitHead": "b18ba1d63be704fd021e4470e8ab84175621e62d"
47
+ "gitHead": "3250842d8cc0fc8b76a575168c1fd57e5a66b6ba"
48
48
  }
@@ -3,7 +3,7 @@
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
5
  import {MD5Hash} from '@loaders.gl/crypto';
6
- import {FileProvider} from '@loaders.gl/loader-utils';
6
+ import {FileProvider, concatenateArrayBuffers} from '@loaders.gl/loader-utils';
7
7
  import {makeZipCDHeaderIterator} from './parse-zip/cd-file-header';
8
8
 
9
9
  /**
@@ -55,3 +55,48 @@ export async function makeHashTableFromZipHeaders(
55
55
 
56
56
  return hashTable;
57
57
  }
58
+
59
+ /**
60
+ * creates hash file that later can be added to the SLPK archive
61
+ * @param fileProvider SLPK archive where we need to add hash file
62
+ * @returns ArrayBuffer containing hash file
63
+ */
64
+ export async function composeHashFile(fileProvider: FileProvider): Promise<ArrayBuffer> {
65
+ const hashArray = await makeHashTableFromZipHeaders(fileProvider);
66
+ const bufferArray = Object.entries(hashArray)
67
+ .map(([key, value]) => concatenateArrayBuffers(hexStringToBuffer(key), bigintToBuffer(value)))
68
+ .sort(compareHashes);
69
+ return concatenateArrayBuffers(...bufferArray);
70
+ }
71
+
72
+ /**
73
+ * Function to compare md5 hashes according to https://github.com/Esri/i3s-spec/blob/master/docs/2.0/slpk_hashtable.pcsl.md
74
+ * @param arrA first hash to compare
75
+ * @param arrB second hash to compare
76
+ * @returns 0 if equal, negative number if a<b, pozitive if a>b
77
+ */
78
+ function compareHashes(arrA: ArrayBuffer, arrB: ArrayBuffer): number {
79
+ const a = new BigUint64Array(arrA);
80
+ const b = new BigUint64Array(arrB);
81
+
82
+ return Number(a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]);
83
+ }
84
+
85
+ /**
86
+ * converts hex string to buffer
87
+ * @param str hex string to convert
88
+ * @returns conversion result
89
+ */
90
+ function hexStringToBuffer(str: string): ArrayBuffer {
91
+ const byteArray = str.match(/../g)?.map((h) => parseInt(h, 16));
92
+ return new Uint8Array(byteArray ?? new Array(16)).buffer;
93
+ }
94
+
95
+ /**
96
+ * converts bigint to buffer
97
+ * @param n bigint to convert
98
+ * @returns convertion result
99
+ */
100
+ function bigintToBuffer(n: bigint): ArrayBuffer {
101
+ return new BigUint64Array([n]).buffer;
102
+ }
package/src/index.ts CHANGED
@@ -19,8 +19,9 @@ export {
19
19
  } from './parse-zip/local-file-header';
20
20
  export {parseEoCDRecord} from './parse-zip/end-of-central-directory';
21
21
  export {searchFromTheEnd} from './parse-zip/search-from-the-end';
22
+ export {addOneFile} from './parse-zip/zip-compozition';
22
23
 
23
24
  // export type {HashElement} from './hash-file-utility';
24
- export {parseHashTable, makeHashTableFromZipHeaders} from './hash-file-utility';
25
+ export {parseHashTable, makeHashTableFromZipHeaders, composeHashFile} from './hash-file-utility';
25
26
 
26
27
  export {ZipFileSystem} from './filesystems/zip-filesystem';
@@ -103,7 +103,9 @@ export async function updateEoCD(
103
103
  ): Promise<Uint8Array> {
104
104
  const eocd = new DataView(eocdBody);
105
105
 
106
- const classicEoCDOffset = oldEoCDOffsets.zipEoCDOffset - (oldEoCDOffsets.zip64EoCDOffset ?? 0n);
106
+ const classicEoCDOffset = oldEoCDOffsets.zip64EoCDOffset
107
+ ? oldEoCDOffsets.zipEoCDOffset - oldEoCDOffsets.zip64EoCDOffset
108
+ : 0n;
107
109
 
108
110
  // updating classic EoCD record with new CD records number in general and on disc
109
111
  if (Number(newCDRecordsNumber) <= 0xffff) {