@loaders.gl/zip
Advanced tools
Comparing version 4.0.0-beta.2 to 4.0.0-beta.3
@@ -10,3 +10,3 @@ import { FileSystem } from '@loaders.gl/loader-utils'; | ||
/** FileProvider instance promise */ | ||
protected fileProvider: Promise<FileProvider | null>; | ||
protected fileProvider: FileProvider | null; | ||
fileName?: string; | ||
@@ -13,0 +13,0 @@ /** |
@@ -1,35 +0,14 @@ | ||
/// <reference types="node" /> | ||
import { FileProvider } from '@loaders.gl/loader-utils'; | ||
/** Element of hash array */ | ||
export type HashElement = { | ||
/** File name hash */ | ||
hash: Buffer; | ||
/** File offset in the archive */ | ||
offset: bigint; | ||
}; | ||
/** | ||
* Comparing md5 hashes according to https://github.com/Esri/i3s-spec/blob/master/docs/2.0/slpk_hashtable.pcsl.md step 5 | ||
* @param hash1 hash to compare | ||
* @param hash2 hash to compare | ||
* @returns -1 if hash1 < hash2, 0 of hash1 === hash2, 1 if hash1 > hash2 | ||
*/ | ||
export declare const compareHashes: (hash1: Buffer, hash2: Buffer) => number; | ||
/** | ||
* Reads hash file from buffer and returns it in ready-to-use form | ||
* @param hashFile - bufer containing hash file | ||
* @returns Array containing file info | ||
* @param arrayBuffer - buffer containing hash file | ||
* @returns Map containing hash and offset | ||
*/ | ||
export declare const parseHashFile: (hashFile: ArrayBuffer) => HashElement[]; | ||
export declare function parseHashTable(arrayBuffer: ArrayBuffer): Record<string, bigint>; | ||
/** | ||
* Binary search in the hash info | ||
* @param hashToSearch hash that we need to find | ||
* @returns required hash element or undefined if not found | ||
*/ | ||
export declare const findBin: (hashToSearch: Buffer, hashArray: HashElement[]) => HashElement | undefined; | ||
/** | ||
* generates hash info from central directory | ||
* generates hash info from zip files "central directory" | ||
* @param fileProvider - provider of the archive | ||
* @returns ready to use hash info | ||
*/ | ||
export declare const generateHashInfo: (fileProvider: FileProvider) => Promise<HashElement[]>; | ||
export declare function makeHashTableFromZipHeaders(fileProvider: FileProvider): Promise<Record<string, bigint>>; | ||
//# sourceMappingURL=hash-file-utility.d.ts.map |
export { ZipLoader } from './zip-loader'; | ||
export { ZipWriter } from './zip-writer'; | ||
export { TarBuilder } from './tar-builder'; | ||
export { parseZipCDFileHeader, zipCDFileHeaderGenerator, signature as cdSignature } from './parse-zip/cd-file-header'; | ||
export { parseZipCDFileHeader, makeZipCDHeaderIterator, signature as cdSignature } from './parse-zip/cd-file-header'; | ||
export { parseZipLocalFileHeader, signature as localHeaderSignature } from './parse-zip/local-file-header'; | ||
export { parseEoCDRecord } from './parse-zip/end-of-central-directory'; | ||
export { searchFromTheEnd } from './parse-zip/search-from-the-end'; | ||
export type { HashElement } from './hash-file-utility'; | ||
export { compareHashes, parseHashFile, findBin, generateHashInfo } from './hash-file-utility'; | ||
export { parseHashTable, makeHashTableFromZipHeaders } from './hash-file-utility'; | ||
export { ZipFileSystem } from './filesystems/zip-filesystem'; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -30,3 +30,3 @@ import { FileProvider } from '@loaders.gl/loader-utils'; | ||
*/ | ||
export declare const parseZipCDFileHeader: (headerOffset: bigint, buffer: FileProvider) => Promise<ZipCDFileHeader | null>; | ||
export declare const parseZipCDFileHeader: (headerOffset: bigint, file: FileProvider) => Promise<ZipCDFileHeader | null>; | ||
/** | ||
@@ -36,3 +36,3 @@ * Create iterator over files of zip archive | ||
*/ | ||
export declare function zipCDFileHeaderGenerator(fileProvider: FileProvider): AsyncGenerator<ZipCDFileHeader, void, unknown>; | ||
export declare function makeZipCDHeaderIterator(fileProvider: FileProvider): AsyncIterable<ZipCDFileHeader>; | ||
//# sourceMappingURL=cd-file-header.d.ts.map |
@@ -14,6 +14,6 @@ import { FileProvider } from '@loaders.gl/loader-utils'; | ||
* Parses end of central directory record of zip file | ||
* @param fileProvider - FileProvider instance | ||
* @param file - FileProvider instance | ||
* @returns Info from the header | ||
*/ | ||
export declare const parseEoCDRecord: (fileProvider: FileProvider) => Promise<ZipEoCDRecord>; | ||
export declare const parseEoCDRecord: (file: FileProvider) => Promise<ZipEoCDRecord>; | ||
//# sourceMappingURL=end-of-central-directory.d.ts.map |
import { FileProvider } from '@loaders.gl/loader-utils'; | ||
import { ZipSignature } from './search-from-the-end'; | ||
/** | ||
@@ -20,3 +21,3 @@ * zip local file header info | ||
}; | ||
export declare const signature: number[]; | ||
export declare const signature: ZipSignature; | ||
/** | ||
@@ -23,0 +24,0 @@ * Parses local file header of zip file |
import { FileProvider } from '@loaders.gl/loader-utils'; | ||
/** Description of zip signature type */ | ||
export type ZipSignature = [number, number, number, number]; | ||
export type ZipSignature = Uint8Array; | ||
/** | ||
@@ -5,0 +5,0 @@ * looking for the last occurrence of the provided |
{ | ||
"name": "@loaders.gl/zip", | ||
"version": "4.0.0-beta.2", | ||
"version": "4.0.0-beta.3", | ||
"description": "Zip Archive Loader", | ||
"license": "MIT", | ||
"type": "module", | ||
"publishConfig": { | ||
@@ -20,4 +21,11 @@ "access": "public" | ||
"types": "dist/index.d.ts", | ||
"main": "dist/es5/index.js", | ||
"module": "dist/esm/index.js", | ||
"main": "dist/index.cjs", | ||
"module": "dist/index.js", | ||
"exports": { | ||
".": { | ||
"import": "./dist/index.js", | ||
"require": "./dist/index.cjs", | ||
"types": "./dist/index.d.ts" | ||
} | ||
}, | ||
"sideEffects": false, | ||
@@ -30,12 +38,13 @@ "files": [ | ||
"scripts": { | ||
"pre-build": "npm run build-bundle", | ||
"build-bundle": "esbuild src/bundle.ts --bundle --outfile=dist/dist.min.js" | ||
"pre-build": "npm run build-bundle && npm run build-bundle -- --env=dev", | ||
"build-bundle": "ocular-bundle ./src/index.ts" | ||
}, | ||
"dependencies": { | ||
"@loaders.gl/compression": "4.0.0-beta.2", | ||
"@loaders.gl/loader-utils": "4.0.0-beta.2", | ||
"@loaders.gl/compression": "4.0.0-beta.3", | ||
"@loaders.gl/crypto": "4.0.0-beta.3", | ||
"@loaders.gl/loader-utils": "4.0.0-beta.3", | ||
"jszip": "^3.1.5", | ||
"md5": "^2.3.0" | ||
}, | ||
"gitHead": "79c2033f755e88e11bc30a04428e3666b177b8fc" | ||
"gitHead": "7ba9621cc51c7a26c407086ac86171f35b8712af" | ||
} |
import {FileSystem, isBrowser} from '@loaders.gl/loader-utils'; | ||
import {FileProvider, isFileProvider} from '@loaders.gl/loader-utils'; | ||
import {FileHandleFile} from '@loaders.gl/loader-utils'; | ||
import {ZipCDFileHeader, zipCDFileHeaderGenerator} from '../parse-zip/cd-file-header'; | ||
import {ZipCDFileHeader, makeZipCDHeaderIterator} from '../parse-zip/cd-file-header'; | ||
import {parseZipLocalFileHeader} from '../parse-zip/local-file-header'; | ||
@@ -27,3 +27,3 @@ import {DeflateCompression} from '@loaders.gl/compression'; | ||
/** FileProvider instance promise */ | ||
protected fileProvider: Promise<FileProvider | null> = Promise.resolve(null); | ||
protected fileProvider: FileProvider | null = null; | ||
public fileName?: string; | ||
@@ -40,3 +40,3 @@ | ||
if (!isBrowser) { | ||
this.fileProvider = FileHandleFile.from(file); | ||
this.fileProvider = new FileHandleFile(file); | ||
} else { | ||
@@ -46,3 +46,3 @@ throw new Error('Cannot open file for random access in a WEB browser'); | ||
} else if (isFileProvider(file)) { | ||
this.fileProvider = Promise.resolve(file); | ||
this.fileProvider = file; | ||
} | ||
@@ -53,5 +53,4 @@ } | ||
async destroy() { | ||
const fileProvider = await this.fileProvider; | ||
if (fileProvider) { | ||
await fileProvider.destroy(); | ||
if (this.fileProvider) { | ||
await this.fileProvider.destroy(); | ||
} | ||
@@ -65,8 +64,7 @@ } | ||
async readdir(): Promise<string[]> { | ||
const fileProvider = await this.fileProvider; | ||
if (!fileProvider) { | ||
if (!this.fileProvider) { | ||
throw new Error('No data detected in the zip archive'); | ||
} | ||
const fileNames: string[] = []; | ||
const zipCDIterator = zipCDFileHeaderGenerator(fileProvider); | ||
const zipCDIterator = makeZipCDHeaderIterator(this.fileProvider); | ||
for await (const cdHeader of zipCDIterator) { | ||
@@ -94,4 +92,3 @@ fileNames.push(cdHeader.fileName); | ||
async fetch(filename: string): Promise<Response> { | ||
const fileProvider = await this.fileProvider; | ||
if (!fileProvider) { | ||
if (!this.fileProvider) { | ||
throw new Error('No data detected in the zip archive'); | ||
@@ -102,3 +99,3 @@ } | ||
cdFileHeader.localHeaderOffset, | ||
fileProvider | ||
this.fileProvider | ||
); | ||
@@ -114,3 +111,3 @@ if (!localFileHeader) { | ||
const compressedFile = await fileProvider.slice( | ||
const compressedFile = await this.fileProvider.slice( | ||
localFileHeader.fileDataOffset, | ||
@@ -133,7 +130,6 @@ localFileHeader.fileDataOffset + localFileHeader.compressedSize | ||
private async getCDFileHeader(filename: string): Promise<ZipCDFileHeader> { | ||
const fileProvider = await this.fileProvider; | ||
if (!fileProvider) { | ||
if (!this.fileProvider) { | ||
throw new Error('No data detected in the zip archive'); | ||
} | ||
const zipCDIterator = zipCDFileHeaderGenerator(fileProvider); | ||
const zipCDIterator = makeZipCDHeaderIterator(this.fileProvider); | ||
let result: ZipCDFileHeader | null = null; | ||
@@ -140,0 +136,0 @@ for await (const cdHeader of zipCDIterator) { |
@@ -1,101 +0,53 @@ | ||
import md5 from 'md5'; | ||
import {MD5Hash} from '@loaders.gl/crypto'; | ||
import {FileProvider} from '@loaders.gl/loader-utils'; | ||
import {zipCDFileHeaderGenerator} from './parse-zip/cd-file-header'; | ||
import {makeZipCDHeaderIterator} from './parse-zip/cd-file-header'; | ||
/** Element of hash array */ | ||
export type HashElement = { | ||
/** File name hash */ | ||
hash: Buffer; | ||
/** File offset in the archive */ | ||
offset: bigint; | ||
}; | ||
/** | ||
* Comparing md5 hashes according to https://github.com/Esri/i3s-spec/blob/master/docs/2.0/slpk_hashtable.pcsl.md step 5 | ||
* @param hash1 hash to compare | ||
* @param hash2 hash to compare | ||
* @returns -1 if hash1 < hash2, 0 of hash1 === hash2, 1 if hash1 > hash2 | ||
* Reads hash file from buffer and returns it in ready-to-use form | ||
* @param arrayBuffer - buffer containing hash file | ||
* @returns Map containing hash and offset | ||
*/ | ||
export const compareHashes = (hash1: Buffer, hash2: Buffer): number => { | ||
const h1 = new BigUint64Array(hash1.buffer, hash1.byteOffset, 2); | ||
const h2 = new BigUint64Array(hash2.buffer, hash2.byteOffset, 2); | ||
export function parseHashTable(arrayBuffer: ArrayBuffer): Record<string, bigint> { | ||
const dataView = new DataView(arrayBuffer); | ||
const diff = h1[0] === h2[0] ? h1[1] - h2[1] : h1[0] - h2[0]; | ||
const hashMap: Record<string, bigint> = {}; | ||
if (diff < 0n) { | ||
return -1; | ||
} else if (diff === 0n) { | ||
return 0; | ||
for (let i = 0; i < arrayBuffer.byteLength; i = i + 24) { | ||
const offset = dataView.getBigUint64(i + 16, true); | ||
const hash = bufferToHex(arrayBuffer, i, 16); | ||
hashMap[hash] = offset; | ||
} | ||
return 1; | ||
}; | ||
/** | ||
* Reads hash file from buffer and returns it in ready-to-use form | ||
* @param hashFile - bufer containing hash file | ||
* @returns Array containing file info | ||
*/ | ||
export const parseHashFile = (hashFile: ArrayBuffer): HashElement[] => { | ||
const hashFileBuffer = Buffer.from(hashFile); | ||
const hashArray: HashElement[] = []; | ||
for (let i = 0; i < hashFileBuffer.buffer.byteLength; i = i + 24) { | ||
const offsetBuffer = new DataView( | ||
hashFileBuffer.buffer.slice( | ||
hashFileBuffer.byteOffset + i + 16, | ||
hashFileBuffer.byteOffset + i + 24 | ||
) | ||
); | ||
const offset = offsetBuffer.getBigUint64(offsetBuffer.byteOffset, true); | ||
hashArray.push({ | ||
hash: Buffer.from( | ||
hashFileBuffer.subarray(hashFileBuffer.byteOffset + i, hashFileBuffer.byteOffset + i + 16) | ||
), | ||
offset | ||
}); | ||
} | ||
return hashArray; | ||
}; | ||
return hashMap; | ||
} | ||
/** | ||
* Binary search in the hash info | ||
* @param hashToSearch hash that we need to find | ||
* @returns required hash element or undefined if not found | ||
*/ | ||
export const findBin = ( | ||
hashToSearch: Buffer, | ||
hashArray: HashElement[] | ||
): HashElement | undefined => { | ||
let lowerBorder = 0; | ||
let upperBorder = hashArray.length; | ||
function bufferToHex(buffer: ArrayBuffer, start: number, length: number): string { | ||
// buffer is an ArrayBuffer | ||
return [...new Uint8Array(buffer, start, length)] | ||
.map((x) => x.toString(16).padStart(2, '0')) | ||
.join(''); | ||
} | ||
while (upperBorder - lowerBorder > 1) { | ||
const middle = lowerBorder + Math.floor((upperBorder - lowerBorder) / 2); | ||
const value = compareHashes(hashArray[middle].hash, hashToSearch); | ||
if (value === 0) { | ||
return hashArray[middle]; | ||
} else if (value < 0) { | ||
lowerBorder = middle; | ||
} else { | ||
upperBorder = middle; | ||
} | ||
} | ||
return undefined; | ||
}; | ||
/** | ||
* generates hash info from central directory | ||
* generates hash info from zip files "central directory" | ||
* @param fileProvider - provider of the archive | ||
* @returns ready to use hash info | ||
*/ | ||
export const generateHashInfo = async (fileProvider: FileProvider): Promise<HashElement[]> => { | ||
const zipCDIterator = zipCDFileHeaderGenerator(fileProvider); | ||
const hashInfo: HashElement[] = []; | ||
export async function makeHashTableFromZipHeaders( | ||
fileProvider: FileProvider | ||
): Promise<Record<string, bigint>> { | ||
const zipCDIterator = makeZipCDHeaderIterator(fileProvider); | ||
const md5Hash = new MD5Hash(); | ||
const textEncoder = new TextEncoder(); | ||
const hashTable: Record<string, bigint> = {}; | ||
for await (const cdHeader of zipCDIterator) { | ||
hashInfo.push({ | ||
hash: Buffer.from(md5(cdHeader.fileName.split('\\').join('/').toLocaleLowerCase()), 'hex'), | ||
offset: cdHeader.localHeaderOffset | ||
}); | ||
const filename = cdHeader.fileName.split('\\').join('/').toLocaleLowerCase(); | ||
const arrayBuffer = textEncoder.encode(filename).buffer; | ||
const md5 = await md5Hash.hash(arrayBuffer, 'hex'); | ||
hashTable[md5] = cdHeader.localHeaderOffset; | ||
} | ||
hashInfo.sort((a, b) => compareHashes(a.hash, b.hash)); | ||
return hashInfo; | ||
}; | ||
return hashTable; | ||
} |
@@ -9,3 +9,3 @@ // loaders.gl, MIT license | ||
parseZipCDFileHeader, | ||
zipCDFileHeaderGenerator, | ||
makeZipCDHeaderIterator, | ||
signature as cdSignature | ||
@@ -20,5 +20,5 @@ } from './parse-zip/cd-file-header'; | ||
export type {HashElement} from './hash-file-utility'; | ||
export {compareHashes, parseHashFile, findBin, generateHashInfo} from './hash-file-utility'; | ||
// export type {HashElement} from './hash-file-utility'; | ||
export {parseHashTable, makeHashTableFromZipHeaders} from './hash-file-utility'; | ||
export {ZipFileSystem} from './filesystems/zip-filesystem'; |
@@ -1,2 +0,2 @@ | ||
import {FileProvider} from '@loaders.gl/loader-utils'; | ||
import {FileProvider, compareArrayBuffers} from '@loaders.gl/loader-utils'; | ||
import {parseEoCDRecord} from './end-of-central-directory'; | ||
@@ -34,3 +34,3 @@ import {ZipSignature} from './search-from-the-end'; | ||
export const signature: ZipSignature = [0x50, 0x4b, 0x01, 0x02]; | ||
export const signature: ZipSignature = new Uint8Array([0x50, 0x4b, 0x01, 0x02]); | ||
@@ -45,31 +45,22 @@ /** | ||
headerOffset: bigint, | ||
buffer: FileProvider | ||
file: FileProvider | ||
): Promise<ZipCDFileHeader | null> => { | ||
if ( | ||
Buffer.from(await buffer.slice(headerOffset, headerOffset + 4n)).compare( | ||
Buffer.from(signature) | ||
) !== 0 | ||
) { | ||
const magicBytes = await file.slice(headerOffset, headerOffset + 4n); | ||
if (!compareArrayBuffers(magicBytes, signature.buffer)) { | ||
return null; | ||
} | ||
let compressedSize = BigInt(await buffer.getUint32(headerOffset + CD_COMPRESSED_SIZE_OFFSET)); | ||
let uncompressedSize = BigInt(await buffer.getUint32(headerOffset + CD_UNCOMPRESSED_SIZE_OFFSET)); | ||
const extraFieldLength = await buffer.getUint16(headerOffset + CD_EXTRA_FIELD_LENGTH_OFFSET); | ||
const fileNameLength = await buffer.getUint16(headerOffset + CD_FILE_NAME_LENGTH_OFFSET); | ||
const fileName = new TextDecoder().decode( | ||
await buffer.slice( | ||
headerOffset + CD_FILE_NAME_OFFSET, | ||
headerOffset + CD_FILE_NAME_OFFSET + BigInt(fileNameLength) | ||
) | ||
let compressedSize = BigInt(await file.getUint32(headerOffset + CD_COMPRESSED_SIZE_OFFSET)); | ||
let uncompressedSize = BigInt(await file.getUint32(headerOffset + CD_UNCOMPRESSED_SIZE_OFFSET)); | ||
const extraFieldLength = await file.getUint16(headerOffset + CD_EXTRA_FIELD_LENGTH_OFFSET); | ||
const fileNameLength = await file.getUint16(headerOffset + CD_FILE_NAME_LENGTH_OFFSET); | ||
const filenameBytes = await file.slice( | ||
headerOffset + CD_FILE_NAME_OFFSET, | ||
headerOffset + CD_FILE_NAME_OFFSET + BigInt(fileNameLength) | ||
); | ||
const fileName = new TextDecoder().decode(filenameBytes); | ||
const extraOffset = headerOffset + CD_FILE_NAME_OFFSET + BigInt(fileNameLength); | ||
const oldFormatOffset = await file.getUint32(headerOffset + CD_LOCAL_HEADER_OFFSET_OFFSET); | ||
const oldFormatOffset = await buffer.getUint32(headerOffset + CD_LOCAL_HEADER_OFFSET_OFFSET); | ||
let fileDataOffset = BigInt(oldFormatOffset); | ||
@@ -79,11 +70,11 @@ let offsetInZip64Data = 4n; | ||
if (uncompressedSize === BigInt(0xffffffff)) { | ||
uncompressedSize = await buffer.getBigUint64(extraOffset + offsetInZip64Data); | ||
uncompressedSize = await file.getBigUint64(extraOffset + offsetInZip64Data); | ||
offsetInZip64Data += 8n; | ||
} | ||
if (compressedSize === BigInt(0xffffffff)) { | ||
compressedSize = await buffer.getBigUint64(extraOffset + offsetInZip64Data); | ||
compressedSize = await file.getBigUint64(extraOffset + offsetInZip64Data); | ||
offsetInZip64Data += 8n; | ||
} | ||
if (fileDataOffset === BigInt(0xffffffff)) { | ||
fileDataOffset = await buffer.getBigUint64(extraOffset + offsetInZip64Data); // setting it to the one from zip64 | ||
fileDataOffset = await file.getBigUint64(extraOffset + offsetInZip64Data); // setting it to the one from zip64 | ||
} | ||
@@ -107,3 +98,5 @@ const localHeaderOffset = fileDataOffset; | ||
*/ | ||
export async function* zipCDFileHeaderGenerator(fileProvider: FileProvider) { | ||
export async function* makeZipCDHeaderIterator( | ||
fileProvider: FileProvider | ||
): AsyncIterable<ZipCDFileHeader> { | ||
const {cdStartOffset} = await parseEoCDRecord(fileProvider); | ||
@@ -110,0 +103,0 @@ let cdHeader = await parseZipCDFileHeader(cdStartOffset, fileProvider); |
@@ -1,2 +0,2 @@ | ||
import {FileProvider} from '@loaders.gl/loader-utils'; | ||
import {FileProvider, compareArrayBuffers} from '@loaders.gl/loader-utils'; | ||
import {ZipSignature, searchFromTheEnd} from './search-from-the-end'; | ||
@@ -15,5 +15,5 @@ | ||
const eoCDSignature: ZipSignature = [0x50, 0x4b, 0x05, 0x06]; | ||
const zip64EoCDLocatorSignature = [0x50, 0x4b, 0x06, 0x07]; | ||
const zip64EoCDSignature = [0x50, 0x4b, 0x06, 0x06]; | ||
const eoCDSignature: ZipSignature = new Uint8Array([0x50, 0x4b, 0x05, 0x06]); | ||
const zip64EoCDLocatorSignature = new Uint8Array([0x50, 0x4b, 0x06, 0x07]); | ||
const zip64EoCDSignature = new Uint8Array([0x50, 0x4b, 0x06, 0x06]); | ||
@@ -29,12 +29,10 @@ // offsets accroding to https://en.wikipedia.org/wiki/ZIP_(file_format) | ||
* Parses end of central directory record of zip file | ||
* @param fileProvider - FileProvider instance | ||
* @param file - FileProvider instance | ||
* @returns Info from the header | ||
*/ | ||
export const parseEoCDRecord = async (fileProvider: FileProvider): Promise<ZipEoCDRecord> => { | ||
const zipEoCDOffset = await searchFromTheEnd(fileProvider, eoCDSignature); | ||
export const parseEoCDRecord = async (file: FileProvider): Promise<ZipEoCDRecord> => { | ||
const zipEoCDOffset = await searchFromTheEnd(file, eoCDSignature); | ||
let cdRecordsNumber = BigInt( | ||
await fileProvider.getUint16(zipEoCDOffset + CD_RECORDS_NUMBER_OFFSET) | ||
); | ||
let cdStartOffset = BigInt(await fileProvider.getUint32(zipEoCDOffset + CD_START_OFFSET_OFFSET)); | ||
let cdRecordsNumber = BigInt(await file.getUint16(zipEoCDOffset + CD_RECORDS_NUMBER_OFFSET)); | ||
let cdStartOffset = BigInt(await file.getUint32(zipEoCDOffset + CD_START_OFFSET_OFFSET)); | ||
@@ -44,25 +42,17 @@ if (cdStartOffset === BigInt(0xffffffff) || cdRecordsNumber === BigInt(0xffffffff)) { | ||
if ( | ||
Buffer.from( | ||
await fileProvider.slice(zip64EoCDLocatorOffset, zip64EoCDLocatorOffset + 4n) | ||
).compare(Buffer.from(zip64EoCDLocatorSignature)) !== 0 | ||
) { | ||
const magicBytes = await file.slice(zip64EoCDLocatorOffset, zip64EoCDLocatorOffset + 4n); | ||
if (!compareArrayBuffers(magicBytes, zip64EoCDLocatorSignature)) { | ||
throw new Error('zip64 EoCD locator not found'); | ||
} | ||
const zip64EoCDOffset = await fileProvider.getBigUint64( | ||
const zip64EoCDOffset = await file.getBigUint64( | ||
zip64EoCDLocatorOffset + ZIP64_EOCD_START_OFFSET_OFFSET | ||
); | ||
if ( | ||
Buffer.from(await fileProvider.slice(zip64EoCDOffset, zip64EoCDOffset + 4n)).compare( | ||
Buffer.from(zip64EoCDSignature) | ||
) !== 0 | ||
) { | ||
const endOfCDMagicBytes = await file.slice(zip64EoCDOffset, zip64EoCDOffset + 4n); | ||
if (!compareArrayBuffers(endOfCDMagicBytes, zip64EoCDSignature.buffer)) { | ||
throw new Error('zip64 EoCD not found'); | ||
} | ||
cdRecordsNumber = await fileProvider.getBigUint64( | ||
zip64EoCDOffset + ZIP64_CD_RECORDS_NUMBER_OFFSET | ||
); | ||
cdStartOffset = await fileProvider.getBigUint64(zip64EoCDOffset + ZIP64_CD_START_OFFSET_OFFSET); | ||
cdRecordsNumber = await file.getBigUint64(zip64EoCDOffset + ZIP64_CD_RECORDS_NUMBER_OFFSET); | ||
cdStartOffset = await file.getBigUint64(zip64EoCDOffset + ZIP64_CD_START_OFFSET_OFFSET); | ||
} | ||
@@ -69,0 +59,0 @@ |
@@ -1,2 +0,3 @@ | ||
import {FileProvider} from '@loaders.gl/loader-utils'; | ||
import {FileProvider, compareArrayBuffers} from '@loaders.gl/loader-utils'; | ||
import {ZipSignature} from './search-from-the-end'; | ||
@@ -30,3 +31,3 @@ /** | ||
export const signature = [0x50, 0x4b, 0x03, 0x04]; | ||
export const signature: ZipSignature = new Uint8Array([0x50, 0x4b, 0x03, 0x04]); | ||
@@ -43,7 +44,4 @@ /** | ||
): Promise<ZipLocalFileHeader | null> => { | ||
if ( | ||
Buffer.from(await buffer.slice(headerOffset, headerOffset + 4n)).compare( | ||
Buffer.from(signature) | ||
) !== 0 | ||
) { | ||
const magicBytes = await buffer.slice(headerOffset, headerOffset + 4n); | ||
if (!compareArrayBuffers(magicBytes, signature)) { | ||
return null; | ||
@@ -50,0 +48,0 @@ } |
import {FileProvider} from '@loaders.gl/loader-utils'; | ||
/** Description of zip signature type */ | ||
export type ZipSignature = [number, number, number, number]; | ||
export type ZipSignature = Uint8Array; | ||
@@ -6,0 +6,0 @@ /** |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Yes
513160
5
75
10889
4
+ Added@loaders.gl/compression@4.0.0-beta.3(transitive)
+ Added@loaders.gl/crypto@4.0.0-beta.3(transitive)
+ Added@loaders.gl/loader-utils@4.0.0-beta.3(transitive)
+ Added@loaders.gl/worker-utils@4.0.0-beta.3(transitive)
+ Added@types/crypto-js@4.2.2(transitive)
- Removed@loaders.gl/compression@4.0.0-beta.2(transitive)
- Removed@loaders.gl/loader-utils@4.0.0-beta.2(transitive)
- Removed@loaders.gl/worker-utils@4.0.0-beta.2(transitive)