@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 +157 -2
- package/dist/hash-file-utility.d.ts +6 -0
- package/dist/hash-file-utility.d.ts.map +1 -1
- package/dist/hash-file-utility.js +22 -0
- package/dist/hash-file-utility.js.map +1 -1
- package/dist/index.cjs +119 -7
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/parse-zip/end-of-central-directory.d.ts.map +1 -1
- package/dist/parse-zip/end-of-central-directory.js +1 -2
- package/dist/parse-zip/end-of-central-directory.js.map +1 -1
- package/dist/zip-loader.js +1 -1
- package/dist/zip-writer.js +1 -1
- package/package.json +5 -5
- package/src/hash-file-utility.ts +46 -1
- package/src/index.ts +2 -1
- package/src/parse-zip/end-of-central-directory.ts +3 -1
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.
|
|
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.
|
|
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,
|
|
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,
|
|
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/
|
|
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
|
|
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 (!
|
|
915
|
-
this.fileProvider = new
|
|
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,
|
|
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 {
|
|
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
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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;
|
|
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 {
|
|
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,
|
|
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,
|
|
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 -
|
|
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","
|
|
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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"}
|
package/dist/zip-loader.js
CHANGED
package/dist/zip-writer.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loaders.gl/zip",
|
|
3
|
-
"version": "4.1.0-alpha.
|
|
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.
|
|
42
|
-
"@loaders.gl/crypto": "4.1.0-alpha.
|
|
43
|
-
"@loaders.gl/loader-utils": "4.1.0-alpha.
|
|
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": "
|
|
47
|
+
"gitHead": "3250842d8cc0fc8b76a575168c1fd57e5a66b6ba"
|
|
48
48
|
}
|
package/src/hash-file-utility.ts
CHANGED
|
@@ -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.
|
|
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) {
|