unzipit 1.3.3 → 1.4.0
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/README.md +30 -5
- package/dist/unzipit-worker.js +1 -1
- package/dist/unzipit-worker.min.js +1 -1
- package/dist/unzipit-worker.module.js +1 -1
- package/dist/unzipit.d.ts +3 -1
- package/dist/unzipit.js +7 -4
- package/dist/unzipit.min.js +21 -21
- package/dist/unzipit.module.d.ts +3 -1
- package/dist/unzipit.module.js +7 -4
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@ async function readFiles(url) {
|
|
|
25
25
|
const {entries} = await unzip(url);
|
|
26
26
|
|
|
27
27
|
// print all entries and their sizes
|
|
28
|
-
for (const [name, entry]
|
|
28
|
+
for (const [name, entry] of Object.entries(entries)) {
|
|
29
29
|
console.log(name, entry.size);
|
|
30
30
|
}
|
|
31
31
|
|
|
@@ -255,10 +255,28 @@ Advantages over other libraries.
|
|
|
255
255
|
you still have to manually go through all the entries even if
|
|
256
256
|
you don't choose to read their contents. Further it's node only.
|
|
257
257
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
258
|
+
* fflate has 2 modes. One the entire contents of all
|
|
259
|
+
uncompressed files are provided therefore using lots
|
|
260
|
+
of memory. The other is like Yauzl where you're required
|
|
261
|
+
to handle every file but you can choose to ignore
|
|
262
|
+
certain ones. Further in this mode (maybe both modes) are
|
|
263
|
+
not standards compliant. It scans for files but that is not
|
|
264
|
+
a valid way to read a zip file. The only valid way to read a zip file
|
|
265
|
+
is to jump to the end of the file and find the table of
|
|
266
|
+
contents. So, fflate will fail on perfectly valid zip files.
|
|
267
|
+
|
|
268
|
+
Unzipit does not require all compressed content nor all uncompressed
|
|
269
|
+
content to be in memory. Only the entries you access use memory.
|
|
270
|
+
If you use a Blob as input the browser can effectively virtualize
|
|
271
|
+
access so it doesn't have to be in memory and unzipit will only
|
|
272
|
+
access the parts of the blob needed to read the content you request.
|
|
273
|
+
|
|
274
|
+
Further, if you use the `HTTPRangeReader` or similar, unzipit only
|
|
275
|
+
downloads/reads the parts of the zip file you actually use, saving you
|
|
276
|
+
bandwidth.
|
|
277
|
+
|
|
278
|
+
As well, if you only need the data for images or video or audio then you can do
|
|
279
|
+
things like
|
|
262
280
|
|
|
263
281
|
```js
|
|
264
282
|
const {entries} = await unzip(url);
|
|
@@ -343,6 +361,8 @@ class ZipEntry {
|
|
|
343
361
|
lastModDate: Date, // a Date
|
|
344
362
|
isDirectory: bool, // True if directory
|
|
345
363
|
encrypted: bool, // True if encrypted
|
|
364
|
+
externalFileAttributes: number, // platform specific file attributes
|
|
365
|
+
versionMadeBy: number, // platform that made this file
|
|
346
366
|
}
|
|
347
367
|
```
|
|
348
368
|
|
|
@@ -457,6 +477,11 @@ size before asking for their content.
|
|
|
457
477
|
unzipit does not currently support encrypted zip files and will throw if you try to get the data for one.
|
|
458
478
|
Put it on the TODO list 😅
|
|
459
479
|
|
|
480
|
+
## Other Limitations
|
|
481
|
+
|
|
482
|
+
unzipit only supports the uncompressed and deflate compression algorithms. Other algorithms are defined
|
|
483
|
+
in the zip spec but are uncommon.
|
|
484
|
+
|
|
460
485
|
# Testing
|
|
461
486
|
|
|
462
487
|
When writing tests serve the folder with your favorite web server (recommend [`servez`](https://www.npmjs.com/package/servez))
|
package/dist/unzipit-worker.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* unzipit@1.
|
|
1
|
+
/* unzipit@1.4.0, license MIT */
|
|
2
2
|
'use strict';(function(w){"function"===typeof define&&define.amd?define(w):w()})(function(){function w(a,b){var e=a.length;if(b<=e)return a;b=new Uint8Array(Math.max(e<<1,b));b.set(a,0);return b}function X(a,b,e,g){for(var f=0,c=0,m=g.length>>>1;c<e;){var p=a[c+b];g[c<<1]=0;g[(c<<1)+1]=p;p>f&&(f=p);c++}for(;c<m;)g[c<<1]=0,g[(c<<1)+1]=0,c++;return f}function z(a,b){var e=a.length,g,f;var c=d.bl_count;for(f=0;f<=b;f++)c[f]=0;for(f=1;f<e;f+=2)c[a[f]]++;f=d.next_code;var m=0;c[0]=0;for(g=1;g<=b;g++)m=
|
|
3
3
|
m+c[g-1]<<1,f[g]=m;for(b=0;b<e;b+=2)c=a[b+1],0!=c&&(a[b]=f[c],f[c]++)}function A(a,b,e){for(var g=a.length,f=d.rev15,c=0;c<g;c+=2)if(0!=a[c+1]){var m=a[c+1],p=c>>1<<4|m,t=b-m;m=a[c]<<t;for(t=m+(1<<t);m!=t;)e[f[m]>>>15-b]=p,m++}}function Y(a,b){for(var e=d.rev15,g=15-b,f=0;f<a.length;f+=2)a[f]=e[a[f]<<b-a[f+1]]>>>g}function x(a,b,e){return(a[b>>>3]|a[(b>>>3)+1]<<8)>>>(b&7)&(1<<e)-1}function K(a,b,e){return(a[b>>>3]|a[(b>>>3)+1]<<8|a[(b>>>3)+2]<<16)>>>(b&7)&(1<<e)-1}function L(a,b){return(a[b>>>3]|
|
|
4
4
|
a[(b>>>3)+1]<<8|a[(b>>>3)+2]<<16)>>>(b&7)}function fa(a){return a.arrayBuffer?a.arrayBuffer():new Promise((b,e)=>{const g=new FileReader;g.addEventListener("loadend",()=>{b(g.result)});g.addEventListener("error",e);g.readAsArrayBuffer(a)})}async function ha(a){a=await fa(a);return new Uint8Array(a)}const d=function(){var a=Uint16Array,b=Uint32Array;return{next_code:new a(16),bl_count:new a(16),ordr:[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],of0:[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,
|
package/dist/unzipit.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export type ZipInfo = {
|
|
|
5
5
|
|
|
6
6
|
export type ZipInfoRaw = {
|
|
7
7
|
zip: Zip,
|
|
8
|
-
entries: [
|
|
8
|
+
entries: ZipEntry[],
|
|
9
9
|
};
|
|
10
10
|
|
|
11
11
|
export type Zip = {
|
|
@@ -30,6 +30,8 @@ export type ZipEntry = {
|
|
|
30
30
|
lastModDate: Date, // a Date
|
|
31
31
|
isDirectory: boolean, // True if directory
|
|
32
32
|
encrypted: boolean, // True if encrypted
|
|
33
|
+
externalFileAttributes: number, // platform specific file attributes
|
|
34
|
+
versionMadeBy: number, // platform that made this file
|
|
33
35
|
};
|
|
34
36
|
|
|
35
37
|
export interface Reader {
|
package/dist/unzipit.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* unzipit@1.
|
|
1
|
+
/* unzipit@1.4.0, license MIT */
|
|
2
2
|
(function (global, factory) {
|
|
3
3
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
|
4
4
|
typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
|
@@ -695,6 +695,8 @@
|
|
|
695
695
|
this.lastModDate = dosDateTimeToDate(rawEntry.lastModFileDate, rawEntry.lastModFileTime);
|
|
696
696
|
this.isDirectory = rawEntry.uncompressedSize === 0 && rawEntry.name.endsWith('/');
|
|
697
697
|
this.encrypted = !!(rawEntry.generalPurposeBitFlag & 0x1);
|
|
698
|
+
this.externalFileAttributes = rawEntry.externalFileAttributes;
|
|
699
|
+
this.versionMadeBy = rawEntry.versionMadeBy;
|
|
698
700
|
}
|
|
699
701
|
// returns a promise that returns a Blob for this entry
|
|
700
702
|
async blob(type = 'application/octet-stream') {
|
|
@@ -719,6 +721,7 @@
|
|
|
719
721
|
const EOCDR_WITHOUT_COMMENT_SIZE = 22;
|
|
720
722
|
const MAX_COMMENT_SIZE = 0xffff; // 2-byte size
|
|
721
723
|
const EOCDR_SIGNATURE = 0x06054b50;
|
|
724
|
+
const ZIP64_EOCDR_SIGNATURE = 0x06064b50;
|
|
722
725
|
|
|
723
726
|
async function readAs(reader, offset, length) {
|
|
724
727
|
return await reader.read(offset, length);
|
|
@@ -864,10 +867,10 @@
|
|
|
864
867
|
// 16 - total number of disks
|
|
865
868
|
|
|
866
869
|
// ZIP64 end of central directory record
|
|
867
|
-
const zip64Eocdr = readAs(reader, zip64EocdrOffset, 56);
|
|
870
|
+
const zip64Eocdr = await readAs(reader, zip64EocdrOffset, 56);
|
|
868
871
|
|
|
869
872
|
// 0 - zip64 end of central dir signature 4 bytes (0x06064b50)
|
|
870
|
-
if (getUint32LE(zip64Eocdr, 0) !==
|
|
873
|
+
if (getUint32LE(zip64Eocdr, 0) !== ZIP64_EOCDR_SIGNATURE) {
|
|
871
874
|
throw new Error('invalid zip64 end of central directory record signature');
|
|
872
875
|
}
|
|
873
876
|
// 4 - size of zip64 end of central directory record 8 bytes
|
|
@@ -977,7 +980,7 @@
|
|
|
977
980
|
// find the Zip64 Extended Information Extra Field
|
|
978
981
|
const zip64ExtraField = rawEntry.extraFields.find(e => e.id === 0x0001);
|
|
979
982
|
if (!zip64ExtraField) {
|
|
980
|
-
|
|
983
|
+
throw new Error('expected zip64 extended information extra field');
|
|
981
984
|
}
|
|
982
985
|
const zip64EiefBuffer = zip64ExtraField.data;
|
|
983
986
|
let index = 0;
|
package/dist/unzipit.min.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* unzipit@1.
|
|
1
|
+
/* unzipit@1.4.0, license MIT */
|
|
2
2
|
'use strict';(function(z,G){"object"===typeof exports&&"undefined"!==typeof module?G(exports):"function"===typeof define&&define.amd?define(["exports"],G):(z="undefined"!==typeof globalThis?globalThis:z||self,G(z.unzipit={}))})(this,function(z){function G(a){return a.arrayBuffer?a.arrayBuffer():new Promise((b,c)=>{const e=new FileReader;e.addEventListener("loadend",()=>{b(e.result)});e.addEventListener("error",c);e.readAsArrayBuffer(a)})}async function na(a){a=await G(a);return new Uint8Array(a)}
|
|
3
3
|
function aa(a){return"undefined"!==typeof Blob&&a instanceof Blob}function I(a){return"undefined"!==typeof SharedArrayBuffer&&a instanceof SharedArrayBuffer}function R(a,b){var c=a.length;if(b<=c)return a;b=new Uint8Array(Math.max(c<<1,b));b.set(a,0);return b}function oa(a,b,c,e,d,h){for(var k=ba,f=ca,l=0;l<c;){var n=a[f(e,d)&b];d+=n&15;var u=n>>>4;if(15>=u)h[l]=u,l++;else{var x=n=0;16==u?(x=3+k(e,d,2),d+=2,n=h[l-1]):17==u?(x=3+k(e,d,3),d+=3):18==u&&(x=11+k(e,d,7),d+=7);for(u=l+x;l<u;)h[l]=n,l++}}return d}
|
|
4
4
|
function da(a,b,c,e){for(var d=0,h=0,k=e.length>>>1;h<c;){var f=a[h+b];e[h<<1]=0;e[(h<<1)+1]=f;f>d&&(d=f);h++}for(;h<k;)e[h<<1]=0,e[(h<<1)+1]=0,h++;return d}function J(a,b){var c=a.length,e,d;var h=g.bl_count;for(d=0;d<=b;d++)h[d]=0;for(d=1;d<c;d+=2)h[a[d]]++;d=g.next_code;var k=0;h[0]=0;for(e=1;e<=b;e++)k=k+h[e-1]<<1,d[e]=k;for(b=0;b<c;b+=2)h=a[b+1],0!=h&&(a[b]=d[h],d[h]++)}function K(a,b,c){for(var e=a.length,d=g.rev15,h=0;h<e;h+=2)if(0!=a[h+1]){var k=a[h+1],f=h>>1<<4|k,l=b-k;k=a[h]<<l;for(l=k+
|
|
@@ -9,23 +9,23 @@ resolve:L,reject:sa}=B.shift();N.set(E,{id:E,resolve:L,reject:sa});a.postMessage
|
|
|
9
9
|
0,q,g.ltree);t=(1<<p)-1;q=da(g.ttree,q,h,g.dtree);h=(1<<q)-1;J(g.ltree,p);K(g.ltree,p,d);J(g.dtree,q);K(g.dtree,q,e)}for(;;)if(q=d[x(b,m)&t],m+=q&15,p=q>>>4,0==p>>>8)k[r++]=p;else if(256==p)break;else{q=r+p-254;264<p&&(p=g.ldef[p-257],q=r+(p>>>3)+n(b,m,p&7),m+=p&7);p=e[x(b,m)&h];m+=p&15;p=g.ddef[p>>>4];var Q=(p>>>4)+l(b,m,p&15);m+=p&15;for(A&&(k=R(k,r+131072));r<q;)k[r]=k[r++-Q],k[r]=k[r++-Q],k[r]=k[r++-Q],k[r]=k[r++-Q];r=q}}}k.length==r||k.slice(0,r)}c(a?new Blob([L],{type:a}):L.buffer)}}}}function fa(a,
|
|
10
10
|
b,c){return new Promise((e,d)=>{B.push({src:a,uncompressedSize:b,type:c,resolve:e,reject:d,id:ta++});S()})}async function ua(){for(const a of O)await V.terminate(a);O.splice(0,O.length);D.splice(0,D.length);B.splice(0,B.length);N.clear();U=0;P=!0}async function H(a,b,c){return await a.read(b,c)}async function Z(a,b,c,e){return a.sliceAsBlob?await a.sliceAsBlob(b,c,e):await a.read(b,c)}function v(a,b){return a[b]+256*a[b+1]}function w(a,b){return a[b]+256*a[b+1]+65536*a[b+2]+16777216*a[b+3]}function F(a,
|
|
11
11
|
b){return w(a,b)+4294967296*w(a,b+4)}function M(a,b){I(a.buffer)&&(a=new Uint8Array(a));return va.decode(a)}async function wa(a,b){var c=Math.min(65557,b);b-=c;var e=await H(a,b,c);for(c-=22;0<=c;--c){if(101010256!==w(e,c))continue;var d=new Uint8Array(e.buffer,e.byteOffset+c,e.byteLength-c);e=v(d,4);if(0!==e)throw Error(`multi-volume zip files are not supported. This is volume: ${e}`);e=v(d,10);const k=w(d,12),f=w(d,16);var h=v(d,20);const l=d.length-22;if(h!==l)throw Error(`invalid comment length. expected: ${l}, actual: ${h}`);
|
|
12
|
-
d=new Uint8Array(d.buffer,d.byteOffset+22,h);h=M(d);return 65535===e||4294967295===f?await xa(a,b+c,h,d):await ha(a,f,k,e,h,d)}throw Error("could not find end of central directory. maybe not zip file");}async function xa(a,b,c,e){b=await H(a,b-20,20);if(117853008!==w(b,0))throw Error("invalid zip64 end of central directory locator signature");b=F(b,8);var d=H(a,b,56);if(
|
|
13
|
-
d,h,b,c,e)}async function ha(a,b,c,e,d,h){let k=0;b=await H(a,b,c);c=[];for(let A=0;A<e;++A){var f=b.subarray(k,k+46),l=w(f,0);if(33639248!==l)throw Error(`invalid central directory file header signature: 0x${l.toString(16)}`);f={versionMadeBy:v(f,4),versionNeededToExtract:v(f,6),generalPurposeBitFlag:v(f,8),compressionMethod:v(f,10),lastModFileTime:v(f,12),lastModFileDate:v(f,14),crc32:w(f,16),compressedSize:w(f,20),uncompressedSize:w(f,24),fileNameLength:v(f,28),extraFieldLength:v(f,
|
|
14
|
-
32),internalFileAttributes:v(f,36),externalFileAttributes:w(f,38),relativeOffsetOfLocalHeader:w(f,42)};if(f.generalPurposeBitFlag&64)throw Error("strong encryption is not supported");k+=46;l=b.subarray(k,k+f.fileNameLength+f.extraFieldLength+f.fileCommentLength);f.nameBytes=l.slice(0,f.fileNameLength);f.name=M(f.nameBytes);var n=f.fileNameLength+f.extraFieldLength;const C=l.slice(f.fileNameLength,n);f.extraFields=[];for(var u=0;u<C.length-3;){const t=v(C,u+0);var x=v(C,u+
|
|
15
|
-
f.extraFields.push({id:t,data:C.slice(u,x)});u=x}f.commentBytes=l.slice(n,n+f.fileCommentLength);f.comment=M(f.commentBytes);k+=l.length;if(4294967295===f.uncompressedSize||4294967295===f.compressedSize||4294967295===f.relativeOffsetOfLocalHeader){l=f.extraFields.find(t=>1===t.id);if(!l)
|
|
16
|
-
f.uncompressedSize=F(l,n);n+=8}if(4294967295===f.compressedSize){if(n+8>l.length)throw Error("zip64 extended information extra field does not include compressed size");f.compressedSize=F(l,n);n+=8}if(4294967295===f.relativeOffsetOfLocalHeader){if(n+8>l.length)throw Error("zip64 extended information extra field does not include relative header offset");f.relativeOffsetOfLocalHeader=F(l,n);n+=8}}if(l=f.extraFields.find(t=>
|
|
17
|
-
M(l.data.slice(5));if(0===f.compressionMethod&&(l=f.uncompressedSize,0!==(f.generalPurposeBitFlag&1)&&(l+=12),f.compressedSize!==l))throw Error(`compressed size mismatch for stored file: ${f.compressedSize} != ${l}`);c.push(f)}return{zip:{comment:d,commentBytes:h},entries:c.map(A=>new za(a,A))}}async function ia(a,b){if(b.generalPurposeBitFlag&1)throw Error("encrypted entries not supported");var c=await H(a,
|
|
18
|
-
e=v(c,26);var d=v(c,28);c=b.relativeOffsetOfLocalHeader+c.length+e+d;if(0===b.compressionMethod)e=!1;else if(8===b.compressionMethod)e=!0;else throw Error(`unsupported compression method: ${b.compressionMethod}`);d=c+b.compressedSize;if(0!==b.compressedSize&&d>a)throw Error(`file data overflows file bounds: ${c} + ${b.compressedSize} > ${a}`);
|
|
19
|
-
0===b.byteOffset&&b.byteLength===b.buffer.byteLength?b.buffer:b.slice().buffer;a=await Z(a,e,b.compressedSize);return await fa(a,b.uncompressedSize)}async function Ba(a,b,c){const {decompress:e,fileDataStart:d}=await ia(a,b);if(!e)return b=await Z(a,d,b.compressedSize,c),aa(b)?b:new Blob([I(b.buffer)?new Uint8Array(b):b],{type:c});a=await Z(a,
|
|
20
|
-
ArrayBuffer||a&&a.buffer&&a.buffer instanceof ArrayBuffer)a=new la(a);else if(I(a)||I(a.buffer))a=new la(a);else if("string"===typeof a){var b=await fetch(a);if(!b.ok)throw Error(`failed http request ${a}, status: ${b.status}: ${b.statusText}`);a=await b.blob();a=new ka(a)}else if("function"!==typeof a.getLength||"function"!==typeof a.read)throw Error("unsupported source type");
|
|
21
|
-
return await wa(a,b)}const Ca="undefined"!==typeof process&&process.versions&&"undefined"!==typeof process.versions.node&&"undefined"===typeof process.versions.electron;class la{constructor(a){this.typedArray=a instanceof ArrayBuffer||I(a)?new Uint8Array(a):new Uint8Array(a.buffer,a.byteOffset,a.byteLength)}async getLength(){return this.typedArray.byteLength}async read(a,
|
|
22
|
-
b){a=this.blob.slice(a,a+b);a=await G(a);return new Uint8Array(a)}async sliceAsBlob(a,b,c=""){return this.blob.slice(a,a+b,c)}}class Da{constructor(a){this.url=a}async getLength(){if(void 0===this.length){const a=await fetch(this.url,{method:"HEAD"});if(!a.ok)throw Error(`failed http request ${this.url}, status: ${a.status}: ${a.statusText}`);
|
|
23
|
-
b)return new Uint8Array(0);const c=await fetch(this.url,{headers:{Range:`bytes=${a}-${a+b-1}`}});if(!c.ok)throw Error(`failed http request ${this.url}, status: ${c.status} offset: ${a} size: ${b}: ${c.statusText}`);a=await c.arrayBuffer();return new Uint8Array(a)}}const g=function(){var a=Uint16Array,b=Uint32Array;return{next_code:new a(16),
|
|
24
|
-
258,999,999,999],exb:[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0],ldef:new a(32),df0:[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,65535,65535],dxb:[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0],ddef:new b(32),flmap:new a(512),
|
|
25
|
-
dhst:new b(30),ihst:new b(19),lits:new b(15E3),strt:new a(65536),prev:new a(32768)}}();(function(){function a(e,d,h){for(;0!=d--;)e.push(0,h)}for(var b=0;32768>b;b++){var c=b;c=(c&2863311530)>>>1|(c&1431655765)<<1;c=(c&3435973836)>>>2|(c&858993459)<<2;c=(c&4042322160)>>>4|(c&252645135)<<4;c=(c&4278255360)>>>8|(c&16711935)<<8;g.rev15[b]=(c>>>
|
|
26
|
-
8,8);J(g.fltree,9);K(g.fltree,9,g.flmap);ea(g.fltree,9);a(g.fdtree,32,5);J(g.fdtree,5);K(g.fdtree,5,g.fdmap);ea(g.fdtree,5);a(g.itree,19,0);a(g.ltree,286,0);a(g.dtree,30,0);a(g.ttree,320,0)})();const ma={table:function(){for(var a=new Uint32Array(256),b=0;256>b;b++){for(var c=b,e=0;8>e;e++)c=c&1?3988292384^c>>>1:c>>>1;a[b]=c}return a}(),update:function(a,
|
|
27
|
-
workerURL:"",useWorkers:!1};let ta=0,U=0,P=!0;const O=[],D=[],B=[],N=new Map,V=function(){if(Ca){const {Worker:a}=module.require("worker_threads");return{async createWorker(b){return new a(b)},addEventListener(b,c){b.on("message",e=>{c({target:b,data:e})})},async terminate(b){await b.terminate()}}}return{async createWorker(a){try{return await T(a)}catch(c){console.warn("could not load worker:",
|
|
28
|
-
a=URL.createObjectURL(new Blob([b],{type:"application/javascript"}));const e=await T(a);y.workerURL=a;return e}catch(c){console.warn("could not load worker via fetch:",a)}if(void 0!==b)try{a=`data:application/javascript;base64,${btoa(b)}`;const c=await T(a);y.workerURL=a;return c}catch(c){console.warn("could not load worker via dataURI")}console.warn("workers will not be used");throw Error("can not start workers");
|
|
29
|
-
class za{constructor(a,b){this._reader=a;this._rawEntry=b;this.name=b.name;this.nameBytes=b.nameBytes;this.size=b.uncompressedSize;this.compressedSize=b.compressedSize;this.comment=b.comment;this.commentBytes=b.commentBytes;this.compressionMethod=b.compressionMethod;a=b.lastModFileDate;var c=b.lastModFileTime;this.lastModDate=new Date((a>>9&127)+1980,(a>>5&15)-1,a&31,c>>11&31,c>>5&63,2*(c&31),0);this.isDirectory=
|
|
30
|
-
1)}async blob(a="application/octet-stream"){return await Ba(this._reader,this._rawEntry,a)}async arrayBuffer(){return await Aa(this._reader,this._rawEntry)}async text(){const a=await this.arrayBuffer();return M(new Uint8Array(a))}async json(){const a=await this.text();return JSON.parse(a)}}const ya={unsigned(){return 0}},va=
|
|
31
|
-
a.useWorkers?a.useWorkers:y.useWorkers;y.numWorkers=a.numWorkers||y.numWorkers};z.unzip=async function(a){const {zip:b,entries:c}=await ja(a);return{zip:b,entries:Object.fromEntries(c.map(e=>[e.name,e]))}};z.unzipRaw=ja;Object.defineProperty(z,"__esModule",{value:!0})});
|
|
12
|
+
d=new Uint8Array(d.buffer,d.byteOffset+22,h);h=M(d);return 65535===e||4294967295===f?await xa(a,b+c,h,d):await ha(a,f,k,e,h,d)}throw Error("could not find end of central directory. maybe not zip file");}async function xa(a,b,c,e){b=await H(a,b-20,20);if(117853008!==w(b,0))throw Error("invalid zip64 end of central directory locator signature");b=F(b,8);var d=await H(a,b,56);if(101075792!==w(d,0))throw Error("invalid zip64 end of central directory record signature");b=F(d,32);const h=F(d,40);d=F(d,
|
|
13
|
+
48);return ha(a,d,h,b,c,e)}async function ha(a,b,c,e,d,h){let k=0;b=await H(a,b,c);c=[];for(let A=0;A<e;++A){var f=b.subarray(k,k+46),l=w(f,0);if(33639248!==l)throw Error(`invalid central directory file header signature: 0x${l.toString(16)}`);f={versionMadeBy:v(f,4),versionNeededToExtract:v(f,6),generalPurposeBitFlag:v(f,8),compressionMethod:v(f,10),lastModFileTime:v(f,12),lastModFileDate:v(f,14),crc32:w(f,16),compressedSize:w(f,20),uncompressedSize:w(f,24),fileNameLength:v(f,28),extraFieldLength:v(f,
|
|
14
|
+
30),fileCommentLength:v(f,32),internalFileAttributes:v(f,36),externalFileAttributes:w(f,38),relativeOffsetOfLocalHeader:w(f,42)};if(f.generalPurposeBitFlag&64)throw Error("strong encryption is not supported");k+=46;l=b.subarray(k,k+f.fileNameLength+f.extraFieldLength+f.fileCommentLength);f.nameBytes=l.slice(0,f.fileNameLength);f.name=M(f.nameBytes);var n=f.fileNameLength+f.extraFieldLength;const C=l.slice(f.fileNameLength,n);f.extraFields=[];for(var u=0;u<C.length-3;){const t=v(C,u+0);var x=v(C,u+
|
|
15
|
+
2);u+=4;x=u+x;if(x>C.length)throw Error("extra field length exceeds extra field buffer size");f.extraFields.push({id:t,data:C.slice(u,x)});u=x}f.commentBytes=l.slice(n,n+f.fileCommentLength);f.comment=M(f.commentBytes);k+=l.length;if(4294967295===f.uncompressedSize||4294967295===f.compressedSize||4294967295===f.relativeOffsetOfLocalHeader){l=f.extraFields.find(t=>1===t.id);if(!l)throw Error("expected zip64 extended information extra field");l=l.data;n=0;if(4294967295===f.uncompressedSize){if(n+8>
|
|
16
|
+
l.length)throw Error("zip64 extended information extra field does not include uncompressed size");f.uncompressedSize=F(l,n);n+=8}if(4294967295===f.compressedSize){if(n+8>l.length)throw Error("zip64 extended information extra field does not include compressed size");f.compressedSize=F(l,n);n+=8}if(4294967295===f.relativeOffsetOfLocalHeader){if(n+8>l.length)throw Error("zip64 extended information extra field does not include relative header offset");f.relativeOffsetOfLocalHeader=F(l,n);n+=8}}if(l=f.extraFields.find(t=>
|
|
17
|
+
28789===t.id&&6<=t.data.length&&1===t.data[0]&&w(t.data,1),ya.unsigned(f.nameBytes)))f.fileName=M(l.data.slice(5));if(0===f.compressionMethod&&(l=f.uncompressedSize,0!==(f.generalPurposeBitFlag&1)&&(l+=12),f.compressedSize!==l))throw Error(`compressed size mismatch for stored file: ${f.compressedSize} != ${l}`);c.push(f)}return{zip:{comment:d,commentBytes:h},entries:c.map(A=>new za(a,A))}}async function ia(a,b){if(b.generalPurposeBitFlag&1)throw Error("encrypted entries not supported");var c=await H(a,
|
|
18
|
+
b.relativeOffsetOfLocalHeader,30);a=await a.getLength();var e=w(c,0);if(67324752!==e)throw Error(`invalid local file header signature: 0x${e.toString(16)}`);e=v(c,26);var d=v(c,28);c=b.relativeOffsetOfLocalHeader+c.length+e+d;if(0===b.compressionMethod)e=!1;else if(8===b.compressionMethod)e=!0;else throw Error(`unsupported compression method: ${b.compressionMethod}`);d=c+b.compressedSize;if(0!==b.compressedSize&&d>a)throw Error(`file data overflows file bounds: ${c} + ${b.compressedSize} > ${a}`);
|
|
19
|
+
return{decompress:e,fileDataStart:c}}async function Aa(a,b){const {decompress:c,fileDataStart:e}=await ia(a,b);if(!c)return b=await H(a,e,b.compressedSize),0===b.byteOffset&&b.byteLength===b.buffer.byteLength?b.buffer:b.slice().buffer;a=await Z(a,e,b.compressedSize);return await fa(a,b.uncompressedSize)}async function Ba(a,b,c){const {decompress:e,fileDataStart:d}=await ia(a,b);if(!e)return b=await Z(a,d,b.compressedSize,c),aa(b)?b:new Blob([I(b.buffer)?new Uint8Array(b):b],{type:c});a=await Z(a,
|
|
20
|
+
d,b.compressedSize);return await fa(a,b.uncompressedSize,c)}async function ja(a){if("undefined"!==typeof Blob&&a instanceof Blob)a=new ka(a);else if(a instanceof ArrayBuffer||a&&a.buffer&&a.buffer instanceof ArrayBuffer)a=new la(a);else if(I(a)||I(a.buffer))a=new la(a);else if("string"===typeof a){var b=await fetch(a);if(!b.ok)throw Error(`failed http request ${a}, status: ${b.status}: ${b.statusText}`);a=await b.blob();a=new ka(a)}else if("function"!==typeof a.getLength||"function"!==typeof a.read)throw Error("unsupported source type");
|
|
21
|
+
b=await a.getLength();if(b>Number.MAX_SAFE_INTEGER)throw Error(`file too large. size: ${b}. Only file sizes up 4503599627370496 bytes are supported`);return await wa(a,b)}const Ca="undefined"!==typeof process&&process.versions&&"undefined"!==typeof process.versions.node&&"undefined"===typeof process.versions.electron;class la{constructor(a){this.typedArray=a instanceof ArrayBuffer||I(a)?new Uint8Array(a):new Uint8Array(a.buffer,a.byteOffset,a.byteLength)}async getLength(){return this.typedArray.byteLength}async read(a,
|
|
22
|
+
b){return new Uint8Array(this.typedArray.buffer,this.typedArray.byteOffset+a,b)}}class ka{constructor(a){this.blob=a}async getLength(){return this.blob.size}async read(a,b){a=this.blob.slice(a,a+b);a=await G(a);return new Uint8Array(a)}async sliceAsBlob(a,b,c=""){return this.blob.slice(a,a+b,c)}}class Da{constructor(a){this.url=a}async getLength(){if(void 0===this.length){const a=await fetch(this.url,{method:"HEAD"});if(!a.ok)throw Error(`failed http request ${this.url}, status: ${a.status}: ${a.statusText}`);
|
|
23
|
+
this.length=parseInt(a.headers.get("content-length"));if(Number.isNaN(this.length))throw Error("could not get length");}return this.length}async read(a,b){if(0===b)return new Uint8Array(0);const c=await fetch(this.url,{headers:{Range:`bytes=${a}-${a+b-1}`}});if(!c.ok)throw Error(`failed http request ${this.url}, status: ${c.status} offset: ${a} size: ${b}: ${c.statusText}`);a=await c.arrayBuffer();return new Uint8Array(a)}}const g=function(){var a=Uint16Array,b=Uint32Array;return{next_code:new a(16),
|
|
24
|
+
bl_count:new a(16),ordr:[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],of0:[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,999,999,999],exb:[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0],ldef:new a(32),df0:[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,65535,65535],dxb:[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0],ddef:new b(32),flmap:new a(512),
|
|
25
|
+
fltree:[],fdmap:new a(32),fdtree:[],lmap:new a(32768),ltree:[],ttree:[],dmap:new a(32768),dtree:[],imap:new a(512),itree:[],rev15:new a(32768),lhst:new b(286),dhst:new b(30),ihst:new b(19),lits:new b(15E3),strt:new a(65536),prev:new a(32768)}}();(function(){function a(e,d,h){for(;0!=d--;)e.push(0,h)}for(var b=0;32768>b;b++){var c=b;c=(c&2863311530)>>>1|(c&1431655765)<<1;c=(c&3435973836)>>>2|(c&858993459)<<2;c=(c&4042322160)>>>4|(c&252645135)<<4;c=(c&4278255360)>>>8|(c&16711935)<<8;g.rev15[b]=(c>>>
|
|
26
|
+
16|c<<16)>>>17}for(b=0;32>b;b++)g.ldef[b]=g.of0[b]<<3|g.exb[b],g.ddef[b]=g.df0[b]<<4|g.dxb[b];a(g.fltree,144,8);a(g.fltree,112,9);a(g.fltree,24,7);a(g.fltree,8,8);J(g.fltree,9);K(g.fltree,9,g.flmap);ea(g.fltree,9);a(g.fdtree,32,5);J(g.fdtree,5);K(g.fdtree,5,g.fdmap);ea(g.fdtree,5);a(g.itree,19,0);a(g.ltree,286,0);a(g.dtree,30,0);a(g.ttree,320,0)})();const ma={table:function(){for(var a=new Uint32Array(256),b=0;256>b;b++){for(var c=b,e=0;8>e;e++)c=c&1?3988292384^c>>>1:c>>>1;a[b]=c}return a}(),update:function(a,
|
|
27
|
+
b,c,e){for(var d=0;d<e;d++)a=ma.table[(a^b[c+d])&255]^a>>>8;return a},crc:function(a,b,c){return ma.update(4294967295,a,b,c)^4294967295}},y={numWorkers:1,workerURL:"",useWorkers:!1};let ta=0,U=0,P=!0;const O=[],D=[],B=[],N=new Map,V=function(){if(Ca){const {Worker:a}=module.require("worker_threads");return{async createWorker(b){return new a(b)},addEventListener(b,c){b.on("message",e=>{c({target:b,data:e})})},async terminate(b){await b.terminate()}}}return{async createWorker(a){try{return await T(a)}catch(c){console.warn("could not load worker:",
|
|
28
|
+
a)}let b;try{const c=await fetch(a,{mode:"cors"});if(!c.ok)throw Error(`could not load: ${a}`);b=await c.text();a=URL.createObjectURL(new Blob([b],{type:"application/javascript"}));const e=await T(a);y.workerURL=a;return e}catch(c){console.warn("could not load worker via fetch:",a)}if(void 0!==b)try{a=`data:application/javascript;base64,${btoa(b)}`;const c=await T(a);y.workerURL=a;return c}catch(c){console.warn("could not load worker via dataURI")}console.warn("workers will not be used");throw Error("can not start workers");
|
|
29
|
+
},addEventListener(a,b){a.addEventListener("message",b)},async terminate(a){a.terminate()}}}();class za{constructor(a,b){this._reader=a;this._rawEntry=b;this.name=b.name;this.nameBytes=b.nameBytes;this.size=b.uncompressedSize;this.compressedSize=b.compressedSize;this.comment=b.comment;this.commentBytes=b.commentBytes;this.compressionMethod=b.compressionMethod;a=b.lastModFileDate;var c=b.lastModFileTime;this.lastModDate=new Date((a>>9&127)+1980,(a>>5&15)-1,a&31,c>>11&31,c>>5&63,2*(c&31),0);this.isDirectory=
|
|
30
|
+
0===b.uncompressedSize&&b.name.endsWith("/");this.encrypted=!!(b.generalPurposeBitFlag&1);this.externalFileAttributes=b.externalFileAttributes;this.versionMadeBy=b.versionMadeBy}async blob(a="application/octet-stream"){return await Ba(this._reader,this._rawEntry,a)}async arrayBuffer(){return await Aa(this._reader,this._rawEntry)}async text(){const a=await this.arrayBuffer();return M(new Uint8Array(a))}async json(){const a=await this.text();return JSON.parse(a)}}const ya={unsigned(){return 0}},va=
|
|
31
|
+
new TextDecoder;z.HTTPRangeReader=Da;z.cleanup=function(){ua()};z.setOptions=function(a){y.workerURL=a.workerURL||y.workerURL;a.workerURL&&(y.useWorkers=!0);y.useWorkers=void 0!==a.useWorkers?a.useWorkers:y.useWorkers;y.numWorkers=a.numWorkers||y.numWorkers};z.unzip=async function(a){const {zip:b,entries:c}=await ja(a);return{zip:b,entries:Object.fromEntries(c.map(e=>[e.name,e]))}};z.unzipRaw=ja;Object.defineProperty(z,"__esModule",{value:!0})});
|
package/dist/unzipit.module.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export type ZipInfo = {
|
|
|
5
5
|
|
|
6
6
|
export type ZipInfoRaw = {
|
|
7
7
|
zip: Zip,
|
|
8
|
-
entries: [
|
|
8
|
+
entries: ZipEntry[],
|
|
9
9
|
};
|
|
10
10
|
|
|
11
11
|
export type Zip = {
|
|
@@ -30,6 +30,8 @@ export type ZipEntry = {
|
|
|
30
30
|
lastModDate: Date, // a Date
|
|
31
31
|
isDirectory: boolean, // True if directory
|
|
32
32
|
encrypted: boolean, // True if encrypted
|
|
33
|
+
externalFileAttributes: number, // platform specific file attributes
|
|
34
|
+
versionMadeBy: number, // platform that made this file
|
|
33
35
|
};
|
|
34
36
|
|
|
35
37
|
export interface Reader {
|
package/dist/unzipit.module.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* unzipit@1.
|
|
1
|
+
/* unzipit@1.4.0, license MIT */
|
|
2
2
|
/* global SharedArrayBuffer, process */
|
|
3
3
|
|
|
4
4
|
function readBlobAsArrayBuffer(blob) {
|
|
@@ -689,6 +689,8 @@ class ZipEntry {
|
|
|
689
689
|
this.lastModDate = dosDateTimeToDate(rawEntry.lastModFileDate, rawEntry.lastModFileTime);
|
|
690
690
|
this.isDirectory = rawEntry.uncompressedSize === 0 && rawEntry.name.endsWith('/');
|
|
691
691
|
this.encrypted = !!(rawEntry.generalPurposeBitFlag & 0x1);
|
|
692
|
+
this.externalFileAttributes = rawEntry.externalFileAttributes;
|
|
693
|
+
this.versionMadeBy = rawEntry.versionMadeBy;
|
|
692
694
|
}
|
|
693
695
|
// returns a promise that returns a Blob for this entry
|
|
694
696
|
async blob(type = 'application/octet-stream') {
|
|
@@ -713,6 +715,7 @@ class ZipEntry {
|
|
|
713
715
|
const EOCDR_WITHOUT_COMMENT_SIZE = 22;
|
|
714
716
|
const MAX_COMMENT_SIZE = 0xffff; // 2-byte size
|
|
715
717
|
const EOCDR_SIGNATURE = 0x06054b50;
|
|
718
|
+
const ZIP64_EOCDR_SIGNATURE = 0x06064b50;
|
|
716
719
|
|
|
717
720
|
async function readAs(reader, offset, length) {
|
|
718
721
|
return await reader.read(offset, length);
|
|
@@ -858,10 +861,10 @@ async function readZip64CentralDirectory(reader, offset, comment, commentBytes)
|
|
|
858
861
|
// 16 - total number of disks
|
|
859
862
|
|
|
860
863
|
// ZIP64 end of central directory record
|
|
861
|
-
const zip64Eocdr = readAs(reader, zip64EocdrOffset, 56);
|
|
864
|
+
const zip64Eocdr = await readAs(reader, zip64EocdrOffset, 56);
|
|
862
865
|
|
|
863
866
|
// 0 - zip64 end of central dir signature 4 bytes (0x06064b50)
|
|
864
|
-
if (getUint32LE(zip64Eocdr, 0) !==
|
|
867
|
+
if (getUint32LE(zip64Eocdr, 0) !== ZIP64_EOCDR_SIGNATURE) {
|
|
865
868
|
throw new Error('invalid zip64 end of central directory record signature');
|
|
866
869
|
}
|
|
867
870
|
// 4 - size of zip64 end of central directory record 8 bytes
|
|
@@ -971,7 +974,7 @@ async function readEntries(reader, centralDirectoryOffset, centralDirectorySize,
|
|
|
971
974
|
// find the Zip64 Extended Information Extra Field
|
|
972
975
|
const zip64ExtraField = rawEntry.extraFields.find(e => e.id === 0x0001);
|
|
973
976
|
if (!zip64ExtraField) {
|
|
974
|
-
|
|
977
|
+
throw new Error('expected zip64 extended information extra field');
|
|
975
978
|
}
|
|
976
979
|
const zip64EiefBuffer = zip64ExtraField.data;
|
|
977
980
|
let index = 0;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "unzipit",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "random access unzip library for JavaScript",
|
|
5
5
|
"main": "dist/unzipit.js",
|
|
6
6
|
"module": "dist/unzipit.module.js",
|
|
@@ -14,7 +14,9 @@
|
|
|
14
14
|
"build-min": "rollup -c && google-closure-compiler --warning_level=VERBOSE --jscomp_off=globalThis --jscomp_off=checkTypes --externs build/externs.js --language_in=ECMASCRIPT_2019 --language_out=ECMASCRIPT_2019 --js dist/unzipit.js --js_output_file dist/unzipit.min.js && google-closure-compiler --warning_level=VERBOSE --jscomp_off=globalThis --jscomp_off=checkTypes --externs build/externs.js --language_in=ECMASCRIPT_2019 --language_out=ECMASCRIPT_2019 --js dist/unzipit-worker.js --js_output_file dist/unzipit-worker.min.js && node ./build/append-banner.js dist/unzipit.min.js dist/unzipit-worker.min.js",
|
|
15
15
|
"build-ts": "node ./build/copy.js dist/unzipit.d.ts dist/unzipit.module.d.ts && tsc --lib es2019,dom,dom.iterable --target es2019 test/ts/ts-test.ts",
|
|
16
16
|
"eslint": "eslint src/**/*.js test/tests/**/*.js",
|
|
17
|
-
"test": "
|
|
17
|
+
"test": "npm run test-node && npm run test-browser",
|
|
18
|
+
"test-node": "mocha test/node-test.js",
|
|
19
|
+
"test-browser": "node test/puppeteer.js"
|
|
18
20
|
},
|
|
19
21
|
"files": [
|
|
20
22
|
"dist/**"
|
|
@@ -45,7 +47,7 @@
|
|
|
45
47
|
"express": "^4.17.1",
|
|
46
48
|
"google-closure-compiler": "^20200830.0.0",
|
|
47
49
|
"mocha": "^8.1.3",
|
|
48
|
-
"puppeteer": "^
|
|
50
|
+
"puppeteer": "^13.0.1",
|
|
49
51
|
"rollup": "^2.27.1",
|
|
50
52
|
"rollup-plugin-node-resolve": "^5.2.0",
|
|
51
53
|
"typescript": "^4.0.2"
|