@zip.js/zip.js 2.8.25 → 2.8.28
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 +2 -2
- package/deno.json +1 -1
- package/dist/zip-core.js +1050 -569
- package/dist/zip-core.min.js +1 -1
- package/dist/zip-fs-core.js +1146 -617
- package/dist/zip-fs-core.min.js +1 -1
- package/dist/zip-fs-native.js +1207 -627
- package/dist/zip-fs-native.min.js +1 -1
- package/dist/zip-fs.js +1279 -681
- package/dist/zip-fs.min.js +1 -1
- package/dist/zip-legacy.js +1051 -570
- package/dist/zip-legacy.min.js +1 -1
- package/dist/zip-module.wasm +0 -0
- package/dist/zip-native.js +1053 -572
- package/dist/zip-native.min.js +1 -1
- package/dist/zip-web-worker-native.js +1 -1
- package/dist/zip-web-worker.js +1 -1
- package/dist/zip.js +1125 -626
- package/dist/zip.min.js +1 -1
- package/eslint.config.mjs +6 -1
- package/index-native.cjs +1207 -627
- package/index-native.min.js +1 -1
- package/index.cjs +1279 -681
- package/index.d.ts +2451 -2355
- package/index.min.js +1 -1
- package/lib/core/codec-pool.js +39 -1
- package/lib/core/codec-worker.js +120 -34
- package/lib/core/configuration.js +3 -0
- package/lib/core/constants.js +6 -0
- package/lib/core/io.js +55 -25
- package/lib/core/options.js +2 -0
- package/lib/core/streams/aes-crypto-stream.js +12 -12
- package/lib/core/streams/codec-stream.js +11 -5
- package/lib/core/streams/codecs/sjcl.js +1 -33
- package/lib/core/streams/common-crypto.js +4 -4
- package/lib/core/streams/zip-crypto-stream.js +25 -15
- package/lib/core/streams/zip-entry-stream.js +35 -1
- package/lib/core/streams/zlib-js/zlib-streams.min.js +1 -1
- package/lib/core/streams/zlib-wasm/zlib-streams.js +73 -55
- package/lib/core/streams/zlib-wasm/zlib-streams.wasm +0 -0
- package/lib/core/util/decode-cp437.js +1 -1
- package/lib/core/util/decode-text.js +2 -1
- package/lib/core/web-worker-base.js +12 -4
- package/lib/core/web-worker-inline-native.js +1 -1
- package/lib/core/web-worker-inline-wasm.js +1 -1
- package/lib/core/zip-fs.js +154 -55
- package/lib/core/zip-reader.js +185 -67
- package/lib/core/zip-writer.js +613 -376
- package/lib/core/zlib-streams-inline.js +1 -1
- package/lib/zip-core-reader.js +3 -1
- package/lib/zip-core-writer.js +1 -0
- package/package.json +20 -6
package/dist/zip.js
CHANGED
|
@@ -50,6 +50,7 @@
|
|
|
50
50
|
const END_OF_CENTRAL_DIR_SIGNATURE = 0x06054b50;
|
|
51
51
|
const ZIP64_END_OF_CENTRAL_DIR_SIGNATURE = 0x06064b50;
|
|
52
52
|
const ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIGNATURE = 0x07064b50;
|
|
53
|
+
const CENTRAL_FILE_HEADER_LENGTH = 46;
|
|
53
54
|
const END_OF_CENTRAL_DIR_LENGTH = 22;
|
|
54
55
|
const ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH = 20;
|
|
55
56
|
const ZIP64_END_OF_CENTRAL_DIR_LENGTH = 56;
|
|
@@ -97,9 +98,11 @@
|
|
|
97
98
|
const DIRECTORY_SIGNATURE = "/";
|
|
98
99
|
|
|
99
100
|
const HEADER_SIZE = 30;
|
|
101
|
+
const HEADER_OFFSET_VERSION = 0;
|
|
100
102
|
const HEADER_OFFSET_SIGNATURE = 10;
|
|
101
103
|
const HEADER_OFFSET_COMPRESSED_SIZE = 14;
|
|
102
104
|
const HEADER_OFFSET_UNCOMPRESSED_SIZE = 18;
|
|
105
|
+
const LOCAL_HEADER_COMMON_OFFSET = 4;
|
|
103
106
|
|
|
104
107
|
const MAX_DATE = new Date(2107, 11, 31);
|
|
105
108
|
const MIN_DATE = new Date(1980, 0, 1);
|
|
@@ -154,6 +157,7 @@
|
|
|
154
157
|
chunkSize: 64 * 1024,
|
|
155
158
|
maxWorkers,
|
|
156
159
|
terminateWorkerTimeout: 5000,
|
|
160
|
+
workerStarvationTimeout: 5000,
|
|
157
161
|
useWebWorkers: true,
|
|
158
162
|
useCompressionStream: true,
|
|
159
163
|
CompressionStream: typeof CompressionStream != UNDEFINED_TYPE && CompressionStream,
|
|
@@ -176,6 +180,7 @@
|
|
|
176
180
|
chunkSize,
|
|
177
181
|
maxWorkers,
|
|
178
182
|
terminateWorkerTimeout,
|
|
183
|
+
workerStarvationTimeout,
|
|
179
184
|
useCompressionStream,
|
|
180
185
|
useWebWorkers,
|
|
181
186
|
CompressionStream,
|
|
@@ -191,6 +196,7 @@
|
|
|
191
196
|
setIfDefined("chunkSize", chunkSize);
|
|
192
197
|
setIfDefined("maxWorkers", maxWorkers);
|
|
193
198
|
setIfDefined("terminateWorkerTimeout", terminateWorkerTimeout);
|
|
199
|
+
setIfDefined("workerStarvationTimeout", workerStarvationTimeout);
|
|
194
200
|
setIfDefined("useCompressionStream", useCompressionStream);
|
|
195
201
|
setIfDefined("useWebWorkers", useWebWorkers);
|
|
196
202
|
setIfDefined("CompressionStream", CompressionStream);
|
|
@@ -205,7 +211,7 @@
|
|
|
205
211
|
}
|
|
206
212
|
}
|
|
207
213
|
|
|
208
|
-
function t(t){const e='(t=>{"function"==typeof define&&define.amd?define(t):t()})(function(){"use strict";const{Array:t,Object:e,Number:n,Math:s,Error:r,Uint8Array:o,Uint16Array:i,Uint32Array:c,Int32Array:a,Map:h,DataView:f,Promise:l,TextEncoder:u,crypto:w,postMessage:p,TransformStream:d,ReadableStream:y,WritableStream:m,CompressionStream:g,DecompressionStream:S}=self,b=void 0,v="undefined",k="function",z=[];for(let t=0;256>t;t++){let e=t;for(let t=0;8>t;t++)1&e?e=e>>>1^3988292384:e>>>=1;z[t]=e}class C{constructor(t){this.t=t||-1}append(t){let e=0|this.t;for(let n=0,s=0|t.length;s>n;n++)e=e>>>8^z[255&(e^t[n])];this.t=e}get(){return~this.t}}class A extends d{constructor(){let t;const e=new C;super({transform(t,n){e.append(t),n.enqueue(t)},flush(){const n=new o(4);new f(n.buffer).setUint32(0,e.get()),t.value=n}}),t=this}}const x={concat(t,e){if(0===t.length||0===e.length)return t.concat(e);const n=t[t.length-1],s=x.o(n);return 32===s?t.concat(e):x.i(e,s,0|n,t.slice(0,t.length-1))},h(t){const e=t.length;if(0===e)return 0;const n=t[e-1];return 32*(e-1)+x.o(n)},l(t,e){if(32*t.length<e)return t;const n=(t=t.slice(0,s.ceil(e/32))).length;return e&=31,n>0&&e&&(t[n-1]=x.u(e,t[n-1]&2147483648>>e-1,1)),t},u:(t,e,n)=>32===t?e:(n?0|e:e<<32-t)+1099511627776*t,o:t=>s.round(t/1099511627776)||32,i(t,e,n,s){for(void 0===s&&(s=[]);e>=32;e-=32)s.push(n),n=0;if(0===e)return s.concat(t);for(let r=0;r<t.length;r++)s.push(n|t[r]>>>e),n=t[r]<<32-e;const r=t.length?t[t.length-1]:0,o=x.o(r);return s.push(x.u(e+o&31,e+o>32?n:s.pop(),1)),s}},I={bytes:{p(t){const e=x.h(t)/8,n=new o(e);let s;for(let r=0;e>r;r++)3&r||(s=t[r/4]),n[r]=s>>>24,s<<=8;return n},m(t){const e=[];let n,s=0;for(n=0;n<t.length;n++)s=s<<8|t[n],3&~n||(e.push(s),s=0);return 3&n&&e.push(x.u(8*(3&n),s)),e}}},R=class{constructor(t){const e=this;e.blockSize=512,e.S=[1732584193,4023233417,2562383102,271733878,3285377520],e.v=[1518500249,1859775393,2400959708,3395469782],t?(e.k=t.k.slice(0),e.C=t.C.slice(0),e.A=t.A):e.reset()}reset(){const t=this;return t.k=t.S.slice(0),t.C=[],t.A=0,t}update(t){const e=this;"string"==typeof t&&(t=I.I.m(t));const n=e.C=x.concat(e.C,t),s=e.A,o=e.A=s+x.h(t);if(o>9007199254740991)throw new r("Cannot hash more than 2^53 - 1 bits");const i=new c(n);let a=0;for(let t=e.blockSize+s-(e.blockSize+s&e.blockSize-1);o>=t;t+=e.blockSize)e.R(i.subarray(16*a,16*(a+1))),a+=1;return n.splice(0,16*a),e}P(){const t=this;let e=t.C;const n=t.k;e=x.concat(e,[x.u(1,1)]);for(let t=e.length+2;15&t;t++)e.push(0);for(e.push(s.floor(t.A/4294967296)),e.push(0|t.A);e.length;)t.R(e.splice(0,16));return t.reset(),n}U(t,e,n,s){return t>19?t>39?t>59?t>79?void 0:e^n^s:e&n|e&s|n&s:e^n^s:e&n|~e&s}V(t,e){return e<<t|e>>>32-t}R(e){const n=this,r=n.k,o=t(80);for(let t=0;16>t;t++)o[t]=e[t];let i=r[0],c=r[1],a=r[2],h=r[3],f=r[4];for(let t=0;79>=t;t++){16>t||(o[t]=n.V(1,o[t-3]^o[t-8]^o[t-14]^o[t-16]));const e=n.V(5,i)+n.U(t,c,a,h)+f+o[t]+n.v[s.floor(t/20)]|0;f=h,h=a,a=n.V(30,c),c=i,i=e}r[0]=r[0]+i|0,r[1]=r[1]+c|0,r[2]=r[2]+a|0,r[3]=r[3]+h|0,r[4]=r[4]+f|0}},P={getRandomValues(t){const e=new c(t.buffer),n=t=>{let e=987654321;const n=4294967295;return()=>(e=36969*(65535&e)+(e>>16)&n,(((e<<16)+(t=18e3*(65535&t)+(t>>16)&n)&n)/4294967296+.5)*(s.random()>.5?1:-1))};for(let r,o=0;o<t.length;o+=4){const t=n(4294967296*(r||s.random()));r=987654071*t(),e[o/4]=4294967296*t()|0}return t}},U={importKey:t=>new U.M(I.bytes.m(t)),_(t,e,n,s){if(n=n||1e4,0>s||0>n)throw new r("invalid params to pbkdf2");const o=1+(s>>5)<<2;let i,c,a,h,l;const u=new ArrayBuffer(o),w=new f(u);let p=0;const d=x;for(e=I.bytes.m(e),l=1;(o||1)>p;l++){for(i=c=t.encrypt(d.concat(e,[l])),a=1;n>a;a++)for(c=t.encrypt(c),h=0;h<c.length;h++)i[h]^=c[h];for(a=0;(o||1)>p&&a<i.length;a++)w.setInt32(p,i[a]),p+=4}return u.slice(0,s/8)},M:class{constructor(t){const e=this,n=e.B=R,s=[[],[]];e.D=[new n,new n];const r=e.D[0].blockSize/32;t.length>r&&(t=(new n).update(t).P());for(let e=0;r>e;e++)s[0][e]=909522486^t[e],s[1][e]=1549556828^t[e];e.D[0].update(s[0]),e.D[1].update(s[1]),e.W=new n(e.D[0])}reset(){const t=this;t.W=new t.B(t.D[0]),t.K=!1}update(t){this.K=!0,this.W.update(t)}digest(){const t=this,e=t.W.P(),n=new t.B(t.D[1]).update(e).P();return t.reset(),n}encrypt(t){if(this.K)throw new r("encrypt on already updated hmac called!");return this.update(t),this.digest(t)}}},V=typeof w!=v&&typeof w.getRandomValues==k,M="Invalid password",_="Invalid signature",B="zipjs-abort-check-password";function D(t){return V?w.getRandomValues(t):P.getRandomValues(t)}const W=16,K={name:"PBKDF2"},E=e.assign({hash:{name:"HMAC"}},K),L=e.assign({iterations:1e3,hash:{name:"SHA-1"}},K),O=["deriveBits"],T=[8,12,16],j=[16,24,32],H=10,Z=[0,0,0,0],F=typeof w!=v,N=F&&w.subtle,q=F&&typeof N!=v,G=I.bytes,J=class{constructor(t){const e=this;e.L=[[[],[],[],[],[]],[[],[],[],[],[]]],e.L[0][0][0]||e.O();const n=e.L[0][4],s=e.L[1],o=t.length;let i,c,a,h=1;if(4!==o&&6!==o&&8!==o)throw new r("invalid aes key size");for(e.v=[c=t.slice(0),a=[]],i=o;4*o+28>i;i++){let t=c[i-1];(i%o===0||8===o&&i%o===4)&&(t=n[t>>>24]<<24^n[t>>16&255]<<16^n[t>>8&255]<<8^n[255&t],i%o===0&&(t=t<<8^t>>>24^h<<24,h=h<<1^283*(h>>7))),c[i]=c[i-o]^t}for(let t=0;i;t++,i--){const e=c[3&t?i:i-4];a[t]=4>=i||4>t?e:s[0][n[e>>>24]]^s[1][n[e>>16&255]]^s[2][n[e>>8&255]]^s[3][n[255&e]]}}encrypt(t){return this.T(t,0)}decrypt(t){return this.T(t,1)}O(){const t=this.L[0],e=this.L[1],n=t[4],s=e[4],r=[],o=[];let i,c,a,h;for(let t=0;256>t;t++)o[(r[t]=t<<1^283*(t>>7))^t]=t;for(let f=i=0;!n[f];f^=c||1,i=o[i]||1){let o=i^i<<1^i<<2^i<<3^i<<4;o=o>>8^255&o^99,n[f]=o,s[o]=f,h=r[a=r[c=r[f]]];let l=16843009*h^65537*a^257*c^16843008*f,u=257*r[o]^16843008*o;for(let n=0;4>n;n++)t[n][f]=u=u<<24^u>>>8,e[n][o]=l=l<<24^l>>>8}for(let n=0;5>n;n++)t[n]=t[n].slice(0),e[n]=e[n].slice(0)}T(t,e){if(4!==t.length)throw new r("invalid aes block size");const n=this.v[e],s=n.length/4-2,o=[0,0,0,0],i=this.L[e],c=i[0],a=i[1],h=i[2],f=i[3],l=i[4];let u,w,p,d=t[0]^n[0],y=t[e?3:1]^n[1],m=t[2]^n[2],g=t[e?1:3]^n[3],S=4;for(let t=0;s>t;t++)u=c[d>>>24]^a[y>>16&255]^h[m>>8&255]^f[255&g]^n[S],w=c[y>>>24]^a[m>>16&255]^h[g>>8&255]^f[255&d]^n[S+1],p=c[m>>>24]^a[g>>16&255]^h[d>>8&255]^f[255&y]^n[S+2],g=c[g>>>24]^a[d>>16&255]^h[y>>8&255]^f[255&m]^n[S+3],S+=4,d=u,y=w,m=p;for(let t=0;4>t;t++)o[e?3&-t:t]=l[d>>>24]<<24^l[y>>16&255]<<16^l[m>>8&255]<<8^l[255&g]^n[S++],u=d,d=y,y=m,m=g,g=u;return o}},Q=class{constructor(t,e){this.j=t,this.H=e,this.Z=e}reset(){this.Z=this.H}update(t){return this.F(this.j,t,this.Z)}N(t){if(255&~(t>>24))t+=1<<24;else{let e=t>>16&255,n=t>>8&255,s=255&t;255===e?(e=0,255===n?(n=0,255===s?s=0:++s):++n):++e,t=0,t+=e<<16,t+=n<<8,t+=s}return t}q(t){0===(t[0]=this.N(t[0]))&&(t[1]=this.N(t[1]))}F(t,e,n){let s;if(!(s=e.length))return[];const r=x.h(e);for(let r=0;s>r;r+=4){this.q(n);const s=t.encrypt(n);e[r]^=s[0],e[r+1]^=s[1],e[r+2]^=s[2],e[r+3]^=s[3]}return x.l(e,r)}},X=U.M;let Y=F&&q&&typeof N.importKey==k,$=F&&q&&typeof N.deriveBits==k;class tt extends d{constructor({password:t,rawPassword:n,signed:s,encryptionStrength:i,checkPasswordOnly:c}){super({start(){e.assign(this,{ready:new l(t=>this.G=t),password:rt(t,n),signed:s,J:i-1,pending:new o})},async transform(t,e){const n=this,{password:s,J:i,G:a,ready:h}=n;s?(await(async(t,e,n,s)=>{const o=await st(t,e,n,it(s,0,T[e])),i=it(s,T[e]);if(o[0]!=i[0]||o[1]!=i[1])throw new r(M)})(n,i,s,it(t,0,T[i]+2)),t=it(t,T[i]+2),c?e.error(new r(B)):a()):await h;const f=new o(t.length-H-(t.length-H)%W);e.enqueue(nt(n,t,f,0,H,!0))},async flush(t){const{signed:e,X:n,Y:s,pending:i,ready:c}=this;if(s&&n){await c;const a=it(i,0,i.length-H),h=it(i,i.length-H);let f=new o;if(a.length){const t=at(G,a);s.update(t);const e=n.update(t);f=ct(G,e)}if(e){const t=it(ct(G,s.digest()),0,H);for(let e=0;H>e;e++)if(t[e]!=h[e])throw new r(_)}t.enqueue(f)}}})}}class et extends d{constructor({password:t,rawPassword:n,encryptionStrength:s}){let r;super({start(){e.assign(this,{ready:new l(t=>this.G=t),password:rt(t,n),J:s-1,pending:new o})},async transform(t,e){const n=this,{password:s,J:r,G:i,ready:c}=n;let a=new o;s?(a=await(async(t,e,n)=>{const s=D(new o(T[e]));return ot(s,await st(t,e,n,s))})(n,r,s),i()):await c;const h=new o(a.length+t.length-t.length%W);h.set(a,0),e.enqueue(nt(n,t,h,a.length,0))},async flush(t){const{X:e,Y:n,pending:s,ready:i}=this;if(n&&e){await i;let c=new o;if(s.length){const t=e.update(at(G,s));n.update(t),c=ct(G,t)}r.signature=ct(G,n.digest()).slice(0,H),t.enqueue(ot(c,r.signature))}}}),r=this}}function nt(t,e,n,s,r,i){const{X:c,Y:a,pending:h}=t,f=e.length-r;let l;for(h.length&&(e=ot(h,e),n=((t,e)=>{if(e&&e>t.length){const n=t;(t=new o(e)).set(n,0)}return t})(n,f-f%W)),l=0;f-W>=l;l+=W){const t=at(G,it(e,l,l+W));i&&a.update(t);const r=c.update(t);i||a.update(r),n.set(ct(G,r),l+s)}return t.pending=it(e,l),n}async function st(n,s,r,i){n.password=null;const c=await(async(t,e,n,s,r)=>{if(!Y)return U.importKey(e);try{return await N.importKey("raw",e,n,!1,r)}catch{return Y=!1,U.importKey(e)}})(0,r,E,0,O),a=await(async(t,e,n)=>{if(!$)return U._(e,t.salt,L.iterations,n);try{return await N.deriveBits(t,e,n)}catch{return $=!1,U._(e,t.salt,L.iterations,n)}})(e.assign({salt:i},L),c,8*(2*j[s]+2)),h=new o(a),f=at(G,it(h,0,j[s])),l=at(G,it(h,j[s],2*j[s])),u=it(h,2*j[s]);return e.assign(n,{keys:{key:f,$:l,passwordVerification:u},X:new Q(new J(f),t.from(Z)),Y:new X(l)}),u}function rt(t,e){return e===b?(t=>{if(typeof u==v){const e=new o((t=unescape(encodeURIComponent(t))).length);for(let n=0;n<e.length;n++)e[n]=t.charCodeAt(n);return e}return(new u).encode(t)})(t):e}function ot(t,e){let n=t;return t.length+e.length&&(n=new o(t.length+e.length),n.set(t,0),n.set(e,t.length)),n}function it(t,e,n){return t.subarray(e,n)}function ct(t,e){return t.p(e)}function at(t,e){return t.m(e)}class ht extends d{constructor({password:t,passwordVerification:n,checkPasswordOnly:s}){super({start(){e.assign(this,{password:t,passwordVerification:n}),wt(this,t)},transform(t,e){const n=this;if(n.password){const e=lt(n,t.subarray(0,12));if(n.password=null,e.at(-1)!=n.passwordVerification)throw new r(M);t=t.subarray(12)}s?e.error(new r(B)):e.enqueue(lt(n,t))}})}}class ft extends d{constructor({password:t,passwordVerification:n}){super({start(){e.assign(this,{password:t,passwordVerification:n}),wt(this,t)},transform(t,e){const n=this;let s,r;if(n.password){n.password=null;const e=D(new o(12));e[11]=n.passwordVerification,s=new o(t.length+e.length),s.set(ut(n,e),0),r=12}else s=new o(t.length),r=0;s.set(ut(n,t),r),e.enqueue(s)}})}}function lt(t,e){const n=new o(e.length);for(let s=0;s<e.length;s++)n[s]=dt(t)^e[s],pt(t,n[s]);return n}function ut(t,e){const n=new o(e.length);for(let s=0;s<e.length;s++)n[s]=dt(t)^e[s],pt(t,e[s]);return n}function wt(t,n){const s=[305419896,591751049,878082192];e.assign(t,{keys:s,tt:new C(s[0]),et:new C(s[2])});for(let e=0;e<n.length;e++)pt(t,n.charCodeAt(e))}function pt(t,e){let[n,r,o]=t.keys;t.tt.append([e]),n=~t.tt.get(),r=mt(s.imul(mt(r+yt(n)),134775813)+1),t.et.append([r>>>24]),o=~t.et.get(),t.keys=[n,r,o]}function dt(t){const e=2|t.keys[2];return yt(s.imul(e,1^e)>>>8)}function yt(t){return 255&t}function mt(t){return 4294967295&t}class gt extends d{constructor(t,{chunkSize:e,nt:n,CompressionStream:s}){super({});const{compressed:r,encrypted:o,useCompressionStream:i,zipCrypto:c,signed:a,level:h}=t,l=this;let u,w,p=super.readable;o&&!c||!a||(u=new A,p=kt(p,u)),r&&(p=vt(p,i,{level:h,chunkSize:e},s,n,s)),o&&(c?p=kt(p,new ft(t)):(w=new et(t),p=kt(p,w))),bt(l,p,()=>{let t;o&&!c&&(t=w.signature),o&&!c||!a||(t=new f(u.value.buffer).getUint32(0)),l.signature=t})}}class St extends d{constructor(t,{chunkSize:e,st:n,DecompressionStream:s}){super({});const{zipCrypto:o,encrypted:i,signed:c,signature:a,compressed:h,useCompressionStream:l,rt:u}=t;let w,p,d=super.readable;i&&(o?d=kt(d,new ht(t)):(p=new tt(t),d=kt(d,p))),h&&(d=vt(d,l,{chunkSize:e,rt:u},s,n,s)),i&&!o||!c||(w=new A,d=kt(d,w)),bt(this,d,()=>{if((!i||o)&&c){const t=new f(w.value.buffer);if(a!=t.getUint32(0,!1))throw new r(_)}})}}function bt(t,n,s){n=kt(n,new d({flush:s})),e.defineProperty(t,"readable",{get:()=>n})}function vt(t,e,n,s,r,o){const i=e&&s?s:r||o,c=n.rt?"deflate64-raw":"deflate-raw";try{t=kt(t,new i(c,n))}catch(s){if(!e)throw s;if(r)t=kt(t,new r(c,n));else{if(!o)throw s;t=kt(t,new o(c,n))}}return t}function kt(t,e){return t.pipeThrough(e)}const zt="data",Ct="close";class At extends d{constructor(t,n){super({});const s=this,{codecType:o}=t;let i;o.startsWith("deflate")?i=gt:o.startsWith("inflate")&&(i=St),s.outputSize=0;let c=0;const a=new i(t,n),h=super.readable,f=new d({transform(t,e){t&&t.length&&(c+=t.length,e.enqueue(t))},flush(){e.assign(s,{inputSize:c})}}),l=new d({transform(e,n){if(e&&e.length&&(n.enqueue(e),s.outputSize+=e.length,t.outputSize!==b&&s.outputSize>t.outputSize))throw new r("Invalid uncompressed size")},flush(){const{signature:t}=a;e.assign(s,{signature:t,inputSize:c})}});e.defineProperty(s,"readable",{get:()=>h.pipeThrough(f).pipeThrough(a).pipeThrough(l)})}}class xt extends d{constructor(t){let e;super({transform:function n(s,r){if(e){const t=new o(e.length+s.length);t.set(e),t.set(s,e.length),s=t,e=null}s.length>t?(r.enqueue(s.slice(0,t)),n(s.slice(t),r)):e=s},flush(t){e&&e.length&&t.enqueue(e)}})}}const It=new h,Rt=new h;let Pt,Ut,Vt,Mt,_t,Bt=0;async function Dt(t){try{const{options:e,config:s}=t;if(!e.useCompressionStream)try{await self.initModule(t.config)}catch{e.useCompressionStream=!0}s.CompressionStream=self.CompressionStream,s.DecompressionStream=self.DecompressionStream;const r={highWaterMark:1},o=t.readable||new y({async pull(t){const e=new l(t=>It.set(Bt,t));Wt({type:"pull",messageId:Bt}),Bt=(Bt+1)%n.MAX_SAFE_INTEGER;const{value:s,done:r}=await e;t.enqueue(s),r&&t.close()}},r),i=t.writable||new m({async write(t){let e;const s=new l(t=>e=t);Rt.set(Bt,e),Wt({type:zt,value:t,messageId:Bt}),Bt=(Bt+1)%n.MAX_SAFE_INTEGER,await s}},r),c=new At(e,s);Pt=new AbortController;const{signal:a}=Pt;await o.pipeThrough(c).pipeThrough(new xt(s.chunkSize)).pipeTo(i,{signal:a,preventClose:!0,preventAbort:!0}),await i.getWriter().close();const{signature:h,inputSize:f,outputSize:u}=c;Wt({type:Ct,result:{signature:h,inputSize:f,outputSize:u}})}catch(t){t.outputSize=0,Kt(t)}}function Wt(t){let{value:e}=t;if(e)if(e.length)try{e=new o(e),t.value=e.buffer,p(t,[t.value])}catch{p(t)}else p(t);else p(t)}function Kt(t=new r("Unknown error")){const{message:e,stack:n,code:s,name:o,outputSize:i}=t;p({error:{message:e,stack:n,code:s,name:o,outputSize:i}})}function Et(t,e,n={}){const i="number"==typeof n.level?n.level:-1,c="number"==typeof n.ot?n.ot:65536,a="number"==typeof n.it?n.it:65536;return new d({start(){let n;if(this.ct=Vt(c),this.in=Vt(a),this.it=a,this.ht=new o(c),t?(this.ft=Ut.deflate_process,this.lt=Ut.deflate_last_consumed,this.ut=Ut.deflate_end,this.wt=Ut.deflate_new(),n="gzip"===e?Ut.deflate_init_gzip(this.wt,i):"deflate-raw"===e?Ut.deflate_init_raw(this.wt,i):Ut.deflate_init(this.wt,i)):"deflate64-raw"===e?(this.ft=Ut.inflate9_process,this.lt=Ut.inflate9_last_consumed,this.ut=Ut.inflate9_end,this.wt=Ut.inflate9_new(),n=Ut.inflate9_init_raw(this.wt)):(this.ft=Ut.inflate_process,this.lt=Ut.inflate_last_consumed,this.ut=Ut.inflate_end,this.wt=Ut.inflate_new(),n="deflate-raw"===e?Ut.inflate_init_raw(this.wt):"gzip"===e?Ut.inflate_init_gzip(this.wt):Ut.inflate_init(this.wt)),0!==n)throw new r("init failed:"+n)},transform(e,n){try{const i=e,a=new o(_t.buffer),h=this.ft,f=this.lt,l=this.ct,u=this.ht;let w=0;for(;w<i.length;){const e=s.min(i.length-w,32768);this.in&&this.it>=e||(this.in&&Mt&&Mt(this.in),this.in=Vt(e),this.it=e),a.set(i.subarray(w,w+e),this.in);const o=h(this.wt,this.in,e,l,c,0),p=16777215&o;if(p&&(u.set(a.subarray(l,l+p),0),n.enqueue(u.slice(0,p))),!t){const t=o>>24&255,e=128&t?t-256:t;if(0>e)throw new r("process error:"+e)}const d=f(this.wt);if(0===d)break;w+=d}}catch(t){this.ut&&this.wt&&this.ut(this.wt),this.in&&Mt&&Mt(this.in),this.ct&&Mt&&Mt(this.ct),n.error(t)}},flush(e){try{const n=new o(_t.buffer),s=this.ft,i=this.ct,a=this.ht;for(;;){const o=s(this.wt,0,0,i,c,4),h=16777215&o,f=o>>24&255;if(!t){const t=128&f?f-256:f;if(0>t)throw new r("process error:"+t)}if(h&&(a.set(n.subarray(i,i+h),0),e.enqueue(a.slice(0,h))),1===f||0===h)break}}catch(t){e.error(t)}finally{if(this.ut&&this.wt){const t=this.ut(this.wt);0!==t&&e.error(new r("end error:"+t))}this.in&&Mt&&Mt(this.in),this.ct&&Mt&&Mt(this.ct)}}})}addEventListener("message",({data:t})=>{const{type:e,messageId:n,value:s,done:r}=t;try{if("start"==e&&Dt(t),e==zt){const t=It.get(n);It.delete(n),t({value:new o(s),done:r})}if("ack"==e){const t=Rt.get(n);Rt.delete(n),t()}e==Ct&&Pt.abort()}catch(t){Kt(t)}});class Lt{constructor(t="deflate",e){return Et(!0,t,e)}}class Ot{constructor(t="deflate",e){return Et(!1,t,e)}}let Tt=!1;self.initModule=async t=>{try{const e=await(async(t,{baseURI:e})=>{if(!Tt){let n,s;try{try{s=new URL(t,e)}catch{}const r=await fetch(s);n=await r.arrayBuffer()}catch(e){if(!t.startsWith("data:application/wasm;base64,"))throw e;n=(t=>{const e=t.split(",")[1],n=atob(e),s=n.length,r=new o(s);for(let t=0;s>t;++t)r[t]=n.charCodeAt(t);return r.buffer})(t)}(t=>{if(Ut=t,({malloc:Vt,free:Mt,memory:_t}=Ut),"function"!=typeof Vt||"function"!=typeof Mt||!_t)throw Ut=Vt=Mt=_t=null,new r("Invalid WASM module")})((await WebAssembly.instantiate(n)).instance.exports),Tt=!0}})(t.wasmURI,t);return t.nt=Lt,t.st=Ot,e}catch{}}});\n';t({workerURI:t=>{const n="text/javascript";if(t){const t=new Blob([e],{type:n});return URL.createObjectURL(t)}return "data:"+n+","+encodeURIComponent(e)}});}
|
|
214
|
+
function t(t){const e='(t=>{"function"==typeof define&&define.amd?define(t):t()})(function(){"use strict";const{Array:t,Object:e,Number:n,Math:s,Error:r,Uint8Array:o,Uint16Array:i,Uint32Array:a,Int32Array:c,Map:l,DataView:f,Promise:w,TextEncoder:h,crypto:u,postMessage:p,TransformStream:d,ReadableStream:y,WritableStream:m,CompressionStream:g,DecompressionStream:S}=self,b=void 0,k="undefined",v="function",z=[];for(let t=0;256>t;t++){let e=t;for(let t=0;8>t;t++)1&e?e=e>>>1^3988292384:e>>>=1;z[t]=e}class C{constructor(t){this.t=t||-1}append(t){let e=0|this.t;for(let n=0,s=0|t.length;s>n;n++)e=e>>>8^z[255&(e^t[n])];this.t=e}get(){return~this.t}}class I extends d{constructor(){let t;const e=new C;super({transform(t,n){e.append(t),n.enqueue(t)},flush(){const n=new o(4);new f(n.buffer).setUint32(0,e.get()),t.value=n}}),t=this}}const A={concat(t,e){if(0===t.length||0===e.length)return t.concat(e);const n=t[t.length-1],s=A.o(n);return 32===s?t.concat(e):A.i(e,s,0|n,t.slice(0,t.length-1))},l(t){const e=t.length;if(0===e)return 0;const n=t[e-1];return 32*(e-1)+A.o(n)},h(t,e){if(32*t.length<e)return t;const n=(t=t.slice(0,s.ceil(e/32))).length;return e&=31,n>0&&e&&(t[n-1]=A.u(e,t[n-1]&2147483648>>e-1,1)),t},u:(t,e,n)=>32===t?e:(n?0|e:e<<32-t)+1099511627776*t,o:t=>s.round(t/1099511627776)||32,i(t,e,n,s){for(void 0===s&&(s=[]);e>=32;e-=32)s.push(n),n=0;if(0===e)return s.concat(t);for(let r=0;r<t.length;r++)s.push(n|t[r]>>>e),n=t[r]<<32-e;const r=t.length?t[t.length-1]:0,o=A.o(r);return s.push(A.u(e+o&31,e+o>32?n:s.pop(),1)),s}},P={bytes:{p(t){const e=A.l(t)/8,n=new o(e);let s;for(let r=0;e>r;r++)3&r||(s=t[r/4]),n[r]=s>>>24,s<<=8;return n},m(t){const e=[];let n,s=0;for(n=0;n<t.length;n++)s=s<<8|t[n],3&~n||(e.push(s),s=0);return 3&n&&e.push(A.u(8*(3&n),s)),e}}},x=class{constructor(t){const e=this;e.blockSize=512,e.S=[1732584193,4023233417,2562383102,271733878,3285377520],e.k=[1518500249,1859775393,2400959708,3395469782],t?(e.v=t.v.slice(0),e.C=t.C.slice(0),e.I=t.I):e.reset()}reset(){const t=this;return t.v=t.S.slice(0),t.C=[],t.I=0,t}update(t){const e=this;"string"==typeof t&&(t=P.A.m(t));const n=e.C=A.concat(e.C,t),s=e.I,o=e.I=s+A.l(t);if(o>9007199254740991)throw new r("Cannot hash more than 2^53 - 1 bits");const i=new a(n);let c=0;for(let t=e.blockSize+s-(e.blockSize+s&e.blockSize-1);o>=t;t+=e.blockSize)e.P(i.subarray(16*c,16*(c+1))),c+=1;return n.splice(0,16*c),e}R(){const t=this;let e=t.C;const n=t.v;e=A.concat(e,[A.u(1,1)]);for(let t=e.length+2;15&t;t++)e.push(0);for(e.push(s.floor(t.I/4294967296)),e.push(0|t.I);e.length;)t.P(e.splice(0,16));return t.reset(),n}U(t,e,n,s){return t>19?t>39?t>59?t>79?void 0:e^n^s:e&n|e&s|n&s:e^n^s:e&n|~e&s}W(t,e){return e<<t|e>>>32-t}P(e){const n=this,r=n.v,o=t(80);for(let t=0;16>t;t++)o[t]=e[t];let i=r[0],a=r[1],c=r[2],l=r[3],f=r[4];for(let t=0;79>=t;t++){16>t||(o[t]=n.W(1,o[t-3]^o[t-8]^o[t-14]^o[t-16]));const e=n.W(5,i)+n.U(t,a,c,l)+f+o[t]+n.k[s.floor(t/20)]|0;f=l,l=c,c=n.W(30,a),a=i,i=e}r[0]=r[0]+i|0,r[1]=r[1]+a|0,r[2]=r[2]+c|0,r[3]=r[3]+l|0,r[4]=r[4]+f|0}},R={importKey:t=>new R.D(P.bytes.m(t)),M(t,e,n,s){if(n=n||1e4,0>s||0>n)throw new r("invalid params to pbkdf2");const o=1+(s>>5)<<2;let i,a,c,l,w;const h=new ArrayBuffer(o),u=new f(h);let p=0;const d=A;for(e=P.bytes.m(e),w=1;(o||1)>p;w++){for(i=a=t.encrypt(d.concat(e,[w])),c=1;n>c;c++)for(a=t.encrypt(a),l=0;l<a.length;l++)i[l]^=a[l];for(c=0;(o||1)>p&&c<i.length;c++)u.setInt32(p,i[c]),p+=4}return h.slice(0,s/8)},D:class{constructor(t){const e=this,n=e.V=x,s=[[],[]];e._=[new n,new n];const r=e._[0].blockSize/32;t.length>r&&(t=(new n).update(t).R());for(let e=0;r>e;e++)s[0][e]=909522486^t[e],s[1][e]=1549556828^t[e];e._[0].update(s[0]),e._[1].update(s[1]),e.B=new n(e._[0])}reset(){const t=this;t.B=new t.V(t._[0]),t.T=!1}update(t){this.T=!0,this.B.update(t)}digest(){const t=this,e=t.B.R(),n=new t.V(t._[1]).update(e).R();return t.reset(),n}encrypt(t){if(this.T)throw new r("encrypt on already updated hmac called!");return this.update(t),this.digest(t)}}},U=typeof u!=k&&typeof u.getRandomValues==v,W="Invalid password",D="Invalid signature",M="zipjs-abort-check-password";function V(t){if(U)return u.getRandomValues(t);throw new r("Crypto API not supported")}const _=16,B={name:"PBKDF2"},T=e.assign({hash:{name:"HMAC"}},B),K=e.assign({iterations:1e3,hash:{name:"SHA-1"}},B),j=["deriveBits"],E=[8,12,16],L=[16,24,32],O=10,H=[0,0,0,0],Z=typeof u!=k,F=Z&&u.subtle,N=Z&&typeof F!=k,q=P.bytes,G=class{constructor(t){const e=this;e.K=[[[],[],[],[],[]],[[],[],[],[],[]]],e.K[0][0][0]||e.j();const n=e.K[0][4],s=e.K[1],o=t.length;let i,a,c,l=1;if(4!==o&&6!==o&&8!==o)throw new r("invalid aes key size");for(e.k=[a=t.slice(0),c=[]],i=o;4*o+28>i;i++){let t=a[i-1];(i%o===0||8===o&&i%o===4)&&(t=n[t>>>24]<<24^n[t>>16&255]<<16^n[t>>8&255]<<8^n[255&t],i%o===0&&(t=t<<8^t>>>24^l<<24,l=l<<1^283*(l>>7))),a[i]=a[i-o]^t}for(let t=0;i;t++,i--){const e=a[3&t?i:i-4];c[t]=4>=i||4>t?e:s[0][n[e>>>24]]^s[1][n[e>>16&255]]^s[2][n[e>>8&255]]^s[3][n[255&e]]}}encrypt(t){return this.L(t,0)}decrypt(t){return this.L(t,1)}j(){const t=this.K[0],e=this.K[1],n=t[4],s=e[4],r=[],o=[];let i,a,c,l;for(let t=0;256>t;t++)o[(r[t]=t<<1^283*(t>>7))^t]=t;for(let f=i=0;!n[f];f^=a||1,i=o[i]||1){let o=i^i<<1^i<<2^i<<3^i<<4;o=o>>8^255&o^99,n[f]=o,s[o]=f,l=r[c=r[a=r[f]]];let w=16843009*l^65537*c^257*a^16843008*f,h=257*r[o]^16843008*o;for(let n=0;4>n;n++)t[n][f]=h=h<<24^h>>>8,e[n][o]=w=w<<24^w>>>8}for(let n=0;5>n;n++)t[n]=t[n].slice(0),e[n]=e[n].slice(0)}L(t,e){if(4!==t.length)throw new r("invalid aes block size");const n=this.k[e],s=n.length/4-2,o=[0,0,0,0],i=this.K[e],a=i[0],c=i[1],l=i[2],f=i[3],w=i[4];let h,u,p,d=t[0]^n[0],y=t[e?3:1]^n[1],m=t[2]^n[2],g=t[e?1:3]^n[3],S=4;for(let t=0;s>t;t++)h=a[d>>>24]^c[y>>16&255]^l[m>>8&255]^f[255&g]^n[S],u=a[y>>>24]^c[m>>16&255]^l[g>>8&255]^f[255&d]^n[S+1],p=a[m>>>24]^c[g>>16&255]^l[d>>8&255]^f[255&y]^n[S+2],g=a[g>>>24]^c[d>>16&255]^l[y>>8&255]^f[255&m]^n[S+3],S+=4,d=h,y=u,m=p;for(let t=0;4>t;t++)o[e?3&-t:t]=w[d>>>24]<<24^w[y>>16&255]<<16^w[m>>8&255]<<8^w[255&g]^n[S++],h=d,d=y,y=m,m=g,g=h;return o}},J=class{constructor(t,e){this.O=t,this.H=e,this.Z=e}reset(){this.Z=this.H}update(t){return this.F(this.O,t,this.Z)}N(t){if(255&~(t>>24))t+=1<<24;else{let e=t>>16&255,n=t>>8&255,s=255&t;255===e?(e=0,255===n?(n=0,255===s?s=0:++s):++n):++e,t=0,t+=e<<16,t+=n<<8,t+=s}return t}q(t){0===(t[0]=this.N(t[0]))&&(t[1]=this.N(t[1]))}F(t,e,n){let s;if(!(s=e.length))return[];const r=A.l(e);for(let r=0;s>r;r+=4){this.q(n);const s=t.encrypt(n);e[r]^=s[0],e[r+1]^=s[1],e[r+2]^=s[2],e[r+3]^=s[3]}return A.h(e,r)}},Q=R.D;let X=Z&&N&&typeof F.importKey==v,Y=Z&&N&&typeof F.deriveBits==v;class $ extends d{constructor({password:t,rawPassword:n,encryptionStrength:s,checkPasswordOnly:i}){super({start(){e.assign(this,{ready:new w(t=>this.G=t),password:st(t,n),J:s-1,pending:new o})},async transform(t,e){const n=this,{password:s,J:a,G:c,ready:l}=n;s?(await(async(t,e,n,s)=>{const o=await nt(t,e,n,ot(s,0,E[e])),i=ot(s,E[e]);if(o[0]!=i[0]||o[1]!=i[1])throw new r(W)})(n,a,s,ot(t,0,E[a]+2)),t=ot(t,E[a]+2),i?e.error(new r(M)):c()):await l;const f=new o(t.length-O-(t.length-O)%_);e.enqueue(et(n,t,f,0,O,!0))},async flush(t){const{X:e,Y:n,pending:s,ready:i}=this;if(n&&e){await i;const a=ot(s,0,s.length-O),c=ot(s,s.length-O);let l=new o;if(a.length){const t=at(q,a);n.update(t);const s=e.update(t);l=it(q,s)}const f=ot(it(q,n.digest()),0,O);let w=s.length<O?1:0;for(let t=0;O>t;t++)w|=f[t]^c[t];if(w)throw new r(D);t.enqueue(l)}}})}}class tt extends d{constructor({password:t,rawPassword:n,encryptionStrength:s}){let r;super({start(){e.assign(this,{ready:new w(t=>this.G=t),password:st(t,n),J:s-1,pending:new o})},async transform(t,e){const n=this,{password:s,J:r,G:i,ready:a}=n;let c=new o;s?(c=await(async(t,e,n)=>{const s=V(new o(E[e]));return rt(s,await nt(t,e,n,s))})(n,r,s),i()):await a;const l=new o(c.length+t.length-t.length%_);l.set(c,0),e.enqueue(et(n,t,l,c.length,0))},async flush(t){const{X:e,Y:n,pending:s,ready:i}=this;if(n&&e){await i;let a=new o;if(s.length){const t=e.update(at(q,s));n.update(t),a=it(q,t)}r.signature=it(q,n.digest()).slice(0,O),t.enqueue(rt(a,r.signature))}}}),r=this}}function et(t,e,n,s,r,i){const{X:a,Y:c,pending:l}=t;l.length&&(e=rt(l,e));const f=e.length-r;let w;for(n=((t,e)=>{if(e&&e>t.length){const n=t;(t=new o(e)).set(n,0)}return t})(n,s+(f-f%_)),w=0;f-_>=w;w+=_){const t=at(q,ot(e,w,w+_));i&&c.update(t);const r=a.update(t);i||c.update(r),n.set(it(q,r),w+s)}return t.pending=ot(e,w),n}async function nt(n,s,r,i){n.password=null;const a=await(async(t,e,n,s,r)=>{if(!X)return R.importKey(e);try{return await F.importKey("raw",e,n,!1,r)}catch{return X=!1,R.importKey(e)}})(0,r,T,0,j),c=await(async(t,e,n)=>{if(!Y)return R.M(e,t.salt,K.iterations,n);try{return await F.deriveBits(t,e,n)}catch{return Y=!1,R.M(e,t.salt,K.iterations,n)}})(e.assign({salt:i},K),a,8*(2*L[s]+2)),l=new o(c),f=at(q,ot(l,0,L[s])),w=at(q,ot(l,L[s],2*L[s])),h=ot(l,2*L[s]);return e.assign(n,{keys:{key:f,$:w,passwordVerification:h},X:new J(new G(f),t.from(H)),Y:new Q(w)}),h}function st(t,e){return e===b?(t=>{if(typeof h==k){const e=new o((t=unescape(encodeURIComponent(t))).length);for(let n=0;n<e.length;n++)e[n]=t.charCodeAt(n);return e}return(new h).encode(t)})(t):e}function rt(t,e){let n=t;return t.length+e.length&&(n=new o(t.length+e.length),n.set(t,0),n.set(e,t.length)),n}function ot(t,e,n){return t.subarray(e,n)}function it(t,e){return t.p(e)}function at(t,e){return t.m(e)}class ct extends d{constructor({password:t,rawPassword:n,passwordVerification:s,checkPasswordOnly:o}){super({start(){e.assign(this,{password:t,rawPassword:n,passwordVerification:s}),ht(this,t,n)},transform(t,e){const n=this;if(n.password||n.rawPassword){const e=ft(n,t.subarray(0,12));if(n.password=n.rawPassword=null,0!=(e.at(-1)^n.passwordVerification))throw new r(W);t=t.subarray(12)}o?e.error(new r(M)):e.enqueue(ft(n,t))}})}}class lt extends d{constructor({password:t,rawPassword:n,passwordVerification:s}){super({start(){e.assign(this,{password:t,rawPassword:n,passwordVerification:s}),ht(this,t,n)},transform(t,e){const n=this;let s,r;if(n.password||n.rawPassword){n.password=n.rawPassword=null;const e=V(new o(12));e[11]=n.passwordVerification,s=new o(t.length+e.length),s.set(wt(n,e),0),r=12}else s=new o(t.length),r=0;s.set(wt(n,t),r),e.enqueue(s)}})}}function ft(t,e){const n=new o(e.length);for(let s=0;s<e.length;s++)n[s]=pt(t)^e[s],ut(t,n[s]);return n}function wt(t,e){const n=new o(e.length);for(let s=0;s<e.length;s++)n[s]=pt(t)^e[s],ut(t,e[s]);return n}function ht(t,n,s){const r=[305419896,591751049,878082192];if(e.assign(t,{keys:r,tt:new C(r[0]),et:new C(r[2])}),s)for(let e=0;e<s.length;e++)ut(t,s[e]);else for(let e=0;e<n.length;e++)ut(t,n.charCodeAt(e))}function ut(t,e){let[,n]=t.keys;t.tt.append([e]);const r=~t.tt.get();n=yt(s.imul(yt(n+dt(r)),134775813)+1),t.et.append([n>>>24]);const o=~t.et.get();t.keys=[r,n,o]}function pt(t){const e=2|t.keys[2];return dt(s.imul(e,1^e)>>>8)}function dt(t){return 255&t}function yt(t){return 4294967295&t}class mt extends d{constructor(t,{chunkSize:e,nt:n,CompressionStream:s}){super({});const{compressed:r,encrypted:o,useCompressionStream:i,zipCrypto:a,signed:c,level:l}=t,w=this;let h,u,p=super.readable;o&&!a||!c||(h=new I,p=kt(p,h)),r&&(p=bt(p,i,{level:l,chunkSize:e},s,n,s)),o&&(a?p=kt(p,new lt(t)):(u=new tt(t),p=kt(p,u))),St(w,p,()=>{let t;o&&!a&&(t=u.signature),o&&!a||!c||(t=new f(h.value.buffer).getUint32(0)),w.signature=t})}}class gt extends d{constructor(t,{chunkSize:e,st:n,DecompressionStream:s}){super({});const{zipCrypto:o,encrypted:i,signed:a,signature:c,compressed:l,useCompressionStream:w,deflate64:h}=t;let u,p,d=super.readable;i&&(o?d=kt(d,new ct(t)):(p=new $(t),d=kt(d,p))),l&&(d=bt(d,w,{chunkSize:e,deflate64:h},s,n,s),d=(t=>{const e=t.getReader();return new y({async pull(t){let n;try{n=await e.read()}catch(t){if(t&&t.message)throw t;const e=new r("Invalid compressed data");throw e.cause=t,e}const{value:s,done:o}=n;o?t.close():t.enqueue(s)},cancel:t=>e.cancel(t)})})(d)),i&&!o||!a||(u=new I,d=kt(d,u)),St(this,d,()=>{if((!i||o)&&a){const t=new f(u.value.buffer);if(c!=t.getUint32(0,!1))throw new r(D)}})}}function St(t,n,s){n=kt(n,new d({flush:s})),e.defineProperty(t,"readable",{get:()=>n})}function bt(t,e,n,s,r,o){const i=e&&s?s:r||o,a=n.deflate64?"deflate64-raw":"deflate-raw";try{t=kt(t,new i(a,n))}catch(s){if(!e)throw s;if(r)t=kt(t,new r(a,n));else{if(!o)throw s;t=kt(t,new o(a,n))}}return t}function kt(t,e){return t.pipeThrough(e)}const vt="data",zt="close";class Ct extends d{constructor(t,n){super({});const s=this,{codecType:o}=t;let i;o.startsWith("deflate")?i=mt:o.startsWith("inflate")&&(i=gt),s.outputSize=0;let a=0;const c=new i(t,n),l=super.readable,f=new d({transform(t,e){t&&t.length&&(a+=t.length,e.enqueue(t))},flush(){e.assign(s,{inputSize:a})}}),w=new d({transform(e,n){if(e&&e.length&&(n.enqueue(e),s.outputSize+=e.length,t.outputSize!==b&&s.outputSize>t.outputSize))throw new r("Invalid uncompressed size")},flush(){const{signature:t}=c;e.assign(s,{signature:t,inputSize:a})}});e.defineProperty(s,"readable",{get:()=>l.pipeThrough(f).pipeThrough(c).pipeThrough(w)})}}class It extends d{constructor(t){let e;1>t&&(t=65536),super({transform:(n,s)=>{if(e){const t=new o(e.length+n.length);t.set(e),t.set(n,e.length),n=t,e=null}let r=0;for(;n.length-r>t;)s.enqueue(n.slice(r,r+t)),r+=t;e=r?n.slice(r):n},flush(t){e&&e.length&&t.enqueue(e)}})}}let At=2;try{typeof navigator!=k&&navigator.hardwareConcurrency&&(At=navigator.hardwareConcurrency)}catch{}const Pt={rt:"./core/web-worker-wasm.js",wasmURI:"./core/streams/zlib-wasm/zlib-streams.wasm",chunkSize:65536,ot:At,it:5e3,ct:5e3,lt:!0,useCompressionStream:!0,CompressionStream:typeof g!=k&&g,DecompressionStream:typeof S!=k&&S};e.assign({},Pt);const xt=new l,Rt=new l;let Ut,Wt,Dt,Mt,Vt,_t=0;async function Bt(t){let e,r;try{const{options:o,config:i}=t;if(!o.useCompressionStream)try{await self.initModule(t.config)}catch{o.useCompressionStream=!0}i.CompressionStream=self.CompressionStream,i.DecompressionStream=self.DecompressionStream;const a={highWaterMark:1},c=t.readable||new y({async pull(t){const e=new w(t=>xt.set(_t,t));Tt({type:"pull",messageId:_t}),_t=(_t+1)%n.MAX_SAFE_INTEGER;const{value:s,done:r}=await e;t.enqueue(s),r&&t.close()}},a);r=t.writable||new m({async write(t){let e;const s=new w(t=>e=t);Rt.set(_t,e),Tt({type:vt,value:t,messageId:_t}),_t=(_t+1)%n.MAX_SAFE_INTEGER,await s}},a),e=new Ct(o,i),Ut=new AbortController;const{signal:l}=Ut;await c.pipeThrough(e).pipeThrough(new It((t=>s.max(t.chunkSize,64))(i))).pipeTo(r,{signal:l,preventClose:!0,preventAbort:!0}),await r.getWriter().close();const{signature:f,inputSize:h,outputSize:u}=e;Tt({type:zt,result:{signature:f,inputSize:h,outputSize:u}})}catch(t){if(t.outputSize=e?e.outputSize:0,r&&!r.locked)try{await r.getWriter().close()}catch{}Kt(t)}}function Tt(t){let{value:e}=t;if(e)if(e.length)try{e=new o(e),t.value=e.buffer,p(t,[t.value])}catch{p(t)}else p(t);else p(t)}function Kt(t=new r("Unknown error")){const{message:e,stack:n,code:s,name:o,outputSize:i}=t;p({error:{message:e,stack:n,code:s,name:o,outputSize:i}})}function jt(t,e,n={}){const i="number"==typeof n.level?n.level:-1,a="number"==typeof n.ft?n.ft:65536,c="number"==typeof n.wt?n.wt:65536;return new d({start(){try{let n;if(this.ht=Dt(a),this.in=Dt(c),this.wt=c,!this.ht||!this.in)throw new r("allocation failed");if(this.ut=new o(a),t?(this.dt=Wt.deflate_process,this.yt=Wt.deflate_last_consumed,this.gt=Wt.deflate_end,this.St=Wt.deflate_new(),n="gzip"===e?Wt.deflate_init_gzip(this.St,i):"deflate-raw"===e?Wt.deflate_init_raw(this.St,i):Wt.deflate_init(this.St,i)):"deflate64-raw"===e?(this.dt=Wt.inflate9_process,this.yt=Wt.inflate9_last_consumed,this.gt=Wt.inflate9_end,this.St=Wt.inflate9_new(),n=Wt.inflate9_init_raw(this.St)):(this.dt=Wt.inflate_process,this.yt=Wt.inflate_last_consumed,this.gt=Wt.inflate_end,this.St=Wt.inflate_new(),n="deflate-raw"===e?Wt.inflate_init_raw(this.St):"gzip"===e?Wt.inflate_init_gzip(this.St):Wt.inflate_init(this.St)),0!==n)throw new r("init failed:"+n)}catch(t){throw l(this),t}},transform(e,n){try{const i=e,c=new o(Vt.buffer),l=this.dt,f=this.yt,w=this.ht,h=this.ut;let u=0;for(;u<i.length;){const e=s.min(i.length-u,32768);if((!this.in||this.wt<e)&&(this.in&&Mt&&(Mt(this.in),this.in=0),this.in=Dt(e),this.wt=e,!this.in))throw new r("allocation failed");c.set(i.subarray(u,u+e),this.in);const o=l(this.St,this.in,e,w,a,0),p=16777215&o;if(p&&(h.set(c.subarray(w,w+p),0),n.enqueue(h.slice(0,p))),!t){const t=o>>24&255,e=128&t?t-256:t;if(0>e)throw new r("process error:"+e)}const d=f(this.St);if(0===d)break;u+=d}}catch(t){l(this),n.error(t)}},flush(e){try{const n=new o(Vt.buffer),s=this.dt,i=this.ht,c=this.ut;for(;;){const o=s(this.St,0,0,i,a,4),l=16777215&o,f=o>>24&255;if(!t){const t=128&f?f-256:f;if(0>t)throw new r("process error:"+t)}if(l&&(c.set(n.subarray(i,i+l),0),e.enqueue(c.slice(0,l))),1===f||0===l)break}}catch(t){e.error(t)}finally{const t=l(this);0!==t&&e.error(new r("end error:"+t))}},cancel(){l(this)}});function l(t){let e=0;return t.St&&t.gt&&(e=t.gt(t.St)),t.St=0,t.in&&Mt&&Mt(t.in),t.in=0,t.ht&&Mt&&Mt(t.ht),t.ht=0,e}}addEventListener("message",({data:t})=>{const{type:e,messageId:n,value:s,done:r}=t;try{if("start"==e&&Bt(t),e==vt){const t=xt.get(n);xt.delete(n),t({value:new o(s),done:r})}if("ack"==e){const t=Rt.get(n);Rt.delete(n),t()}e==zt&&Ut.abort()}catch(t){Kt(t)}});class Et{constructor(t="deflate",e){return jt(!0,t,e)}}class Lt{constructor(t="deflate",e){return jt(!1,t,e)}}let Ot=!1;self.initModule=async t=>{try{const e=await(async(t,{baseURI:e})=>{if(!Ot){let n,s;try{try{s=new URL(t,e)}catch{}const r=await fetch(s);n=await r.arrayBuffer()}catch(e){if(!t.startsWith("data:application/wasm;base64,"))throw e;n=(t=>{const e=t.split(",")[1],n=atob(e),s=n.length,r=new o(s);for(let t=0;s>t;++t)r[t]=n.charCodeAt(t);return r.buffer})(t)}(t=>{if(Wt=t,({malloc:Dt,free:Mt,memory:Vt}=Wt),"function"!=typeof Dt||"function"!=typeof Mt||!Vt)throw Wt=Dt=Mt=Vt=null,new r("Invalid WASM module")})((await WebAssembly.instantiate(n)).instance.exports),Ot=!0}})(t.wasmURI,t);return t.nt=Et,t.st=Lt,e}catch{}}});\n';t({workerURI:t=>{const n="text/javascript";if(t){const t=new Blob([e],{type:n});return URL.createObjectURL(t)}return "data:"+n+","+encodeURIComponent(e)}});}
|
|
209
215
|
|
|
210
216
|
/*
|
|
211
217
|
Copyright (c) 2022 Gildas Lormeau. All rights reserved.
|
|
@@ -954,37 +960,6 @@
|
|
|
954
960
|
}
|
|
955
961
|
};
|
|
956
962
|
|
|
957
|
-
/**
|
|
958
|
-
* Random values
|
|
959
|
-
* @namespace
|
|
960
|
-
*/
|
|
961
|
-
const random = {
|
|
962
|
-
/**
|
|
963
|
-
* Generate random words with pure js, cryptographically not as strong & safe as native implementation.
|
|
964
|
-
* @param {TypedArray} typedArray The array to fill.
|
|
965
|
-
* @return {TypedArray} The random values.
|
|
966
|
-
*/
|
|
967
|
-
getRandomValues(typedArray) {
|
|
968
|
-
const words = new Uint32Array(typedArray.buffer);
|
|
969
|
-
const r = (m_w) => {
|
|
970
|
-
let m_z = 0x3ade68b1;
|
|
971
|
-
const mask = 0xffffffff;
|
|
972
|
-
return function () {
|
|
973
|
-
m_z = (0x9069 * (m_z & 0xFFFF) + (m_z >> 0x10)) & mask;
|
|
974
|
-
m_w = (0x4650 * (m_w & 0xFFFF) + (m_w >> 0x10)) & mask;
|
|
975
|
-
const result = ((((m_z << 0x10) + m_w) & mask) / 0x100000000) + .5;
|
|
976
|
-
return result * (Math.random() > .5 ? 1 : -1);
|
|
977
|
-
};
|
|
978
|
-
};
|
|
979
|
-
for (let i = 0, rcache; i < typedArray.length; i += 4) {
|
|
980
|
-
const _r = r((rcache || Math.random()) * 0x100000000);
|
|
981
|
-
rcache = _r() * 0x3ade67b7;
|
|
982
|
-
words[i / 4] = (_r() * 0x100000000) | 0;
|
|
983
|
-
}
|
|
984
|
-
return typedArray;
|
|
985
|
-
}
|
|
986
|
-
};
|
|
987
|
-
|
|
988
963
|
/** @fileOverview CTR mode implementation.
|
|
989
964
|
*
|
|
990
965
|
* Special thanks to Roy Nicholson for pointing out a bug in our
|
|
@@ -1215,12 +1190,15 @@
|
|
|
1215
1190
|
const ERR_INVALID_PASSWORD = "Invalid password";
|
|
1216
1191
|
const ERR_INVALID_SIGNATURE = "Invalid signature";
|
|
1217
1192
|
const ERR_ABORT_CHECK_PASSWORD = "zipjs-abort-check-password";
|
|
1193
|
+
const ERR_UNSUPPORTED_CRYPTO_API = "Crypto API not supported";
|
|
1218
1194
|
|
|
1219
1195
|
function getRandomValues(array) {
|
|
1220
1196
|
if (GET_RANDOM_VALUES_SUPPORTED) {
|
|
1221
1197
|
return crypto.getRandomValues(array);
|
|
1222
1198
|
} else {
|
|
1223
|
-
|
|
1199
|
+
// all supported runtimes expose crypto.getRandomValues; failing hard beats
|
|
1200
|
+
// silently generating predictable encryption salts
|
|
1201
|
+
throw new Error(ERR_UNSUPPORTED_CRYPTO_API);
|
|
1224
1202
|
}
|
|
1225
1203
|
}
|
|
1226
1204
|
|
|
@@ -1279,13 +1257,12 @@
|
|
|
1279
1257
|
|
|
1280
1258
|
class AESDecryptionStream extends TransformStream {
|
|
1281
1259
|
|
|
1282
|
-
constructor({ password, rawPassword,
|
|
1260
|
+
constructor({ password, rawPassword, encryptionStrength, checkPasswordOnly }) {
|
|
1283
1261
|
super({
|
|
1284
1262
|
start() {
|
|
1285
1263
|
Object.assign(this, {
|
|
1286
1264
|
ready: new Promise(resolve => this.resolveReady = resolve),
|
|
1287
1265
|
password: encodePassword(password, rawPassword),
|
|
1288
|
-
signed,
|
|
1289
1266
|
strength: encryptionStrength - 1,
|
|
1290
1267
|
pending: new Uint8Array()
|
|
1291
1268
|
});
|
|
@@ -1314,7 +1291,6 @@
|
|
|
1314
1291
|
},
|
|
1315
1292
|
async flush(controller) {
|
|
1316
1293
|
const {
|
|
1317
|
-
signed,
|
|
1318
1294
|
ctr,
|
|
1319
1295
|
hmac,
|
|
1320
1296
|
pending,
|
|
@@ -1331,13 +1307,15 @@
|
|
|
1331
1307
|
const decryptedChunk = ctr.update(encryptedChunk);
|
|
1332
1308
|
decryptedChunkArray = fromBits(codecBytes, decryptedChunk);
|
|
1333
1309
|
}
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1310
|
+
const signature = subarray(fromBits(codecBytes, hmac.digest()), 0, SIGNATURE_LENGTH);
|
|
1311
|
+
// branch-free comparison: accumulate the differences instead of
|
|
1312
|
+
// short-circuiting on the first mismatching byte
|
|
1313
|
+
let invalidSignature = pending.length < SIGNATURE_LENGTH ? 1 : 0;
|
|
1314
|
+
for (let indexSignature = 0; indexSignature < SIGNATURE_LENGTH; indexSignature++) {
|
|
1315
|
+
invalidSignature |= signature[indexSignature] ^ originalSignature[indexSignature];
|
|
1316
|
+
}
|
|
1317
|
+
if (invalidSignature) {
|
|
1318
|
+
throw new Error(ERR_INVALID_SIGNATURE);
|
|
1341
1319
|
}
|
|
1342
1320
|
controller.enqueue(decryptedChunkArray);
|
|
1343
1321
|
}
|
|
@@ -1409,11 +1387,11 @@
|
|
|
1409
1387
|
hmac,
|
|
1410
1388
|
pending
|
|
1411
1389
|
} = aesCrypto;
|
|
1412
|
-
const inputLength = input.length - paddingEnd;
|
|
1413
1390
|
if (pending.length) {
|
|
1414
1391
|
input = concat(pending, input);
|
|
1415
|
-
output = expand(output, inputLength - (inputLength % BLOCK_LENGTH));
|
|
1416
1392
|
}
|
|
1393
|
+
const inputLength = input.length - paddingEnd;
|
|
1394
|
+
output = expand(output, paddingStart + (inputLength - (inputLength % BLOCK_LENGTH)));
|
|
1417
1395
|
let offset;
|
|
1418
1396
|
for (offset = 0; offset <= inputLength - BLOCK_LENGTH; offset += BLOCK_LENGTH) {
|
|
1419
1397
|
const inputChunk = toBits(codecBytes, subarray(input, offset, offset + BLOCK_LENGTH));
|
|
@@ -1561,21 +1539,24 @@
|
|
|
1561
1539
|
|
|
1562
1540
|
class ZipCryptoDecryptionStream extends TransformStream {
|
|
1563
1541
|
|
|
1564
|
-
constructor({ password, passwordVerification, checkPasswordOnly }) {
|
|
1542
|
+
constructor({ password, rawPassword, passwordVerification, checkPasswordOnly }) {
|
|
1565
1543
|
super({
|
|
1566
1544
|
start() {
|
|
1567
1545
|
Object.assign(this, {
|
|
1568
1546
|
password,
|
|
1547
|
+
rawPassword,
|
|
1569
1548
|
passwordVerification
|
|
1570
1549
|
});
|
|
1571
|
-
createKeys(this, password);
|
|
1550
|
+
createKeys(this, password, rawPassword);
|
|
1572
1551
|
},
|
|
1573
1552
|
transform(chunk, controller) {
|
|
1574
1553
|
const zipCrypto = this;
|
|
1575
|
-
if (zipCrypto.password) {
|
|
1554
|
+
if (zipCrypto.password || zipCrypto.rawPassword) {
|
|
1576
1555
|
const decryptedHeader = decrypt(zipCrypto, chunk.subarray(0, HEADER_LENGTH));
|
|
1577
|
-
zipCrypto.password = null;
|
|
1578
|
-
|
|
1556
|
+
zipCrypto.password = zipCrypto.rawPassword = null;
|
|
1557
|
+
// verify the password with a branch-free comparison of the verification byte, mirroring
|
|
1558
|
+
// the constant-time AES HMAC signature check
|
|
1559
|
+
if ((decryptedHeader.at(-1) ^ zipCrypto.passwordVerification) != 0) {
|
|
1579
1560
|
throw new Error(ERR_INVALID_PASSWORD);
|
|
1580
1561
|
}
|
|
1581
1562
|
chunk = chunk.subarray(HEADER_LENGTH);
|
|
@@ -1592,21 +1573,22 @@
|
|
|
1592
1573
|
|
|
1593
1574
|
class ZipCryptoEncryptionStream extends TransformStream {
|
|
1594
1575
|
|
|
1595
|
-
constructor({ password, passwordVerification }) {
|
|
1576
|
+
constructor({ password, rawPassword, passwordVerification }) {
|
|
1596
1577
|
super({
|
|
1597
1578
|
start() {
|
|
1598
1579
|
Object.assign(this, {
|
|
1599
1580
|
password,
|
|
1581
|
+
rawPassword,
|
|
1600
1582
|
passwordVerification
|
|
1601
1583
|
});
|
|
1602
|
-
createKeys(this, password);
|
|
1584
|
+
createKeys(this, password, rawPassword);
|
|
1603
1585
|
},
|
|
1604
1586
|
transform(chunk, controller) {
|
|
1605
1587
|
const zipCrypto = this;
|
|
1606
1588
|
let output;
|
|
1607
1589
|
let offset;
|
|
1608
|
-
if (zipCrypto.password) {
|
|
1609
|
-
zipCrypto.password = null;
|
|
1590
|
+
if (zipCrypto.password || zipCrypto.rawPassword) {
|
|
1591
|
+
zipCrypto.password = zipCrypto.rawPassword = null;
|
|
1610
1592
|
const header = getRandomValues(new Uint8Array(HEADER_LENGTH));
|
|
1611
1593
|
header[HEADER_LENGTH - 1] = zipCrypto.passwordVerification;
|
|
1612
1594
|
output = new Uint8Array(chunk.length + header.length);
|
|
@@ -1641,25 +1623,31 @@
|
|
|
1641
1623
|
return output;
|
|
1642
1624
|
}
|
|
1643
1625
|
|
|
1644
|
-
function createKeys(target, password) {
|
|
1626
|
+
function createKeys(target, password, rawPassword) {
|
|
1645
1627
|
const keys = [0x12345678, 0x23456789, 0x34567890];
|
|
1646
1628
|
Object.assign(target, {
|
|
1647
1629
|
keys,
|
|
1648
1630
|
crcKey0: new Crc32(keys[0]),
|
|
1649
1631
|
crcKey2: new Crc32(keys[2])
|
|
1650
1632
|
});
|
|
1651
|
-
|
|
1652
|
-
|
|
1633
|
+
if (rawPassword) {
|
|
1634
|
+
for (let index = 0; index < rawPassword.length; index++) {
|
|
1635
|
+
updateKeys(target, rawPassword[index]);
|
|
1636
|
+
}
|
|
1637
|
+
} else {
|
|
1638
|
+
for (let index = 0; index < password.length; index++) {
|
|
1639
|
+
updateKeys(target, password.charCodeAt(index));
|
|
1640
|
+
}
|
|
1653
1641
|
}
|
|
1654
1642
|
}
|
|
1655
1643
|
|
|
1656
1644
|
function updateKeys(target, byte) {
|
|
1657
|
-
let [
|
|
1645
|
+
let [, key1] = target.keys;
|
|
1658
1646
|
target.crcKey0.append([byte]);
|
|
1659
|
-
key0 = ~target.crcKey0.get();
|
|
1647
|
+
const key0 = ~target.crcKey0.get();
|
|
1660
1648
|
key1 = getInt32(Math.imul(getInt32(key1 + getInt8(key0)), 134775813) + 1);
|
|
1661
1649
|
target.crcKey2.append([key1 >>> 24]);
|
|
1662
|
-
key2 = ~target.crcKey2.get();
|
|
1650
|
+
const key2 = ~target.crcKey2.get();
|
|
1663
1651
|
target.keys = [key0, key1, key2];
|
|
1664
1652
|
}
|
|
1665
1653
|
|
|
@@ -1706,6 +1694,7 @@
|
|
|
1706
1694
|
|
|
1707
1695
|
|
|
1708
1696
|
const ERR_INVALID_UNCOMPRESSED_SIZE = "Invalid uncompressed size";
|
|
1697
|
+
const ERR_INVALID_COMPRESSED_DATA = "Invalid compressed data";
|
|
1709
1698
|
const FORMAT_DEFLATE_RAW = "deflate-raw";
|
|
1710
1699
|
const FORMAT_DEFLATE64_RAW = "deflate64-raw";
|
|
1711
1700
|
|
|
@@ -1762,6 +1751,7 @@
|
|
|
1762
1751
|
}
|
|
1763
1752
|
if (compressed) {
|
|
1764
1753
|
readable = pipeThroughCommpressionStream(readable, useCompressionStream, { chunkSize, deflate64 }, DecompressionStream, DecompressionStreamZlib, DecompressionStream);
|
|
1754
|
+
readable = mapInflateStreamError(readable);
|
|
1765
1755
|
}
|
|
1766
1756
|
if ((!encrypted || zipCrypto) && signed) {
|
|
1767
1757
|
crc32Stream = new Crc32Stream();
|
|
@@ -1812,6 +1802,37 @@
|
|
|
1812
1802
|
return readable.pipeThrough(transformStream);
|
|
1813
1803
|
}
|
|
1814
1804
|
|
|
1805
|
+
// DecompressionStream implementations can fail with a message-less TypeError on malformed
|
|
1806
|
+
// input; give these errors an identifiable message (errors raised by the other stages of
|
|
1807
|
+
// the pipeline, e.g. ERR_INVALID_PASSWORD, always carry a message and pass through as-is)
|
|
1808
|
+
function mapInflateStreamError(readable) {
|
|
1809
|
+
const reader = readable.getReader();
|
|
1810
|
+
return new ReadableStream({
|
|
1811
|
+
async pull(controller) {
|
|
1812
|
+
let result;
|
|
1813
|
+
try {
|
|
1814
|
+
result = await reader.read();
|
|
1815
|
+
} catch (error) {
|
|
1816
|
+
if (error && error.message) {
|
|
1817
|
+
throw error;
|
|
1818
|
+
}
|
|
1819
|
+
const mappedError = new Error(ERR_INVALID_COMPRESSED_DATA);
|
|
1820
|
+
mappedError.cause = error;
|
|
1821
|
+
throw mappedError;
|
|
1822
|
+
}
|
|
1823
|
+
const { value, done } = result;
|
|
1824
|
+
if (done) {
|
|
1825
|
+
controller.close();
|
|
1826
|
+
} else {
|
|
1827
|
+
controller.enqueue(value);
|
|
1828
|
+
}
|
|
1829
|
+
},
|
|
1830
|
+
cancel(reason) {
|
|
1831
|
+
return reader.cancel(reason);
|
|
1832
|
+
}
|
|
1833
|
+
});
|
|
1834
|
+
}
|
|
1835
|
+
|
|
1815
1836
|
/*
|
|
1816
1837
|
Copyright (c) 2022 Gildas Lormeau. All rights reserved.
|
|
1817
1838
|
|
|
@@ -1841,6 +1862,7 @@
|
|
|
1841
1862
|
*/
|
|
1842
1863
|
|
|
1843
1864
|
|
|
1865
|
+
const DEFAULT_CHUNK_SIZE$1 = 64 * 1024;
|
|
1844
1866
|
const MESSAGE_EVENT_TYPE = "message";
|
|
1845
1867
|
const MESSAGE_START = "start";
|
|
1846
1868
|
const MESSAGE_PULL = "pull";
|
|
@@ -1909,6 +1931,9 @@
|
|
|
1909
1931
|
|
|
1910
1932
|
constructor(chunkSize) {
|
|
1911
1933
|
let pendingChunk;
|
|
1934
|
+
if (!(chunkSize >= 1)) {
|
|
1935
|
+
chunkSize = DEFAULT_CHUNK_SIZE$1;
|
|
1936
|
+
}
|
|
1912
1937
|
super({
|
|
1913
1938
|
transform,
|
|
1914
1939
|
flush(controller) {
|
|
@@ -1926,12 +1951,12 @@
|
|
|
1926
1951
|
chunk = newChunk;
|
|
1927
1952
|
pendingChunk = null;
|
|
1928
1953
|
}
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
pendingChunk = chunk;
|
|
1954
|
+
let offset = 0;
|
|
1955
|
+
while (chunk.length - offset > chunkSize) {
|
|
1956
|
+
controller.enqueue(chunk.slice(offset, offset + chunkSize));
|
|
1957
|
+
offset += chunkSize;
|
|
1934
1958
|
}
|
|
1959
|
+
pendingChunk = offset ? chunk.slice(offset) : chunk;
|
|
1935
1960
|
}
|
|
1936
1961
|
}
|
|
1937
1962
|
}
|
|
@@ -1966,8 +1991,10 @@
|
|
|
1966
1991
|
|
|
1967
1992
|
|
|
1968
1993
|
const MODULE_WORKER_OPTIONS = { type: "module" };
|
|
1994
|
+
const ERROR_EVENT_TYPE = "error";
|
|
1995
|
+
const MESSAGE_ERROR_EVENT_TYPE = "messageerror";
|
|
1969
1996
|
|
|
1970
|
-
let webWorkerSupported, webWorkerURI, webWorkerOptions;
|
|
1997
|
+
let webWorkerSupported, webWorkerSource, webWorkerURI, webWorkerOptions;
|
|
1971
1998
|
let transferStreamsSupported = true;
|
|
1972
1999
|
try {
|
|
1973
2000
|
transferStreamsSupported = typeof structuredClone == FUNCTION_TYPE && structuredClone(new DOMException("", "AbortError")).code !== UNDEFINED_VALUE;
|
|
@@ -1986,8 +2013,9 @@
|
|
|
1986
2013
|
const { signal } = streamOptions;
|
|
1987
2014
|
Object.assign(workerData, {
|
|
1988
2015
|
busy: true,
|
|
2016
|
+
generation: (workerData.generation || 0) + 1,
|
|
1989
2017
|
readable: readable
|
|
1990
|
-
.pipeThrough(new ChunkStream(config
|
|
2018
|
+
.pipeThrough(new ChunkStream(getChunkSize(config)))
|
|
1991
2019
|
.pipeThrough(new ProgressWatcherStream(streamOptions), { signal }),
|
|
1992
2020
|
writable,
|
|
1993
2021
|
options: Object.assign({}, options),
|
|
@@ -2010,15 +2038,17 @@
|
|
|
2010
2038
|
});
|
|
2011
2039
|
},
|
|
2012
2040
|
onTaskFinished() {
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2041
|
+
if (workerData.busy) {
|
|
2042
|
+
const { resolveTerminated } = workerData;
|
|
2043
|
+
if (resolveTerminated) {
|
|
2044
|
+
workerData.resolveTerminated = null;
|
|
2045
|
+
workerData.terminated = true;
|
|
2046
|
+
workerData.worker.terminate();
|
|
2047
|
+
resolveTerminated();
|
|
2048
|
+
}
|
|
2049
|
+
workerData.busy = false;
|
|
2050
|
+
onTaskFinished(workerData);
|
|
2019
2051
|
}
|
|
2020
|
-
workerData.busy = false;
|
|
2021
|
-
onTaskFinished(workerData);
|
|
2022
2052
|
}
|
|
2023
2053
|
});
|
|
2024
2054
|
if (webWorkerSupported === UNDEFINED_VALUE) {
|
|
@@ -2087,6 +2117,7 @@
|
|
|
2087
2117
|
}
|
|
2088
2118
|
Object.assign(workerData, {
|
|
2089
2119
|
worker,
|
|
2120
|
+
terminated: false,
|
|
2090
2121
|
interface: {
|
|
2091
2122
|
run: () => runWebWorker(workerData, { chunkSize, wasmURI, baseURI })
|
|
2092
2123
|
}
|
|
@@ -2141,37 +2172,85 @@
|
|
|
2141
2172
|
result
|
|
2142
2173
|
});
|
|
2143
2174
|
const { readable, options } = workerData;
|
|
2144
|
-
const { writable, closed } = watchClosedStream(workerData.writable);
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2175
|
+
const { writable, closed, abortPipe } = watchClosedStream(workerData.writable);
|
|
2176
|
+
let streamsTransferred;
|
|
2177
|
+
try {
|
|
2178
|
+
streamsTransferred = sendMessage({
|
|
2179
|
+
type: MESSAGE_START,
|
|
2180
|
+
options,
|
|
2181
|
+
config,
|
|
2182
|
+
readable,
|
|
2183
|
+
writable
|
|
2184
|
+
}, workerData);
|
|
2185
|
+
} catch (error) {
|
|
2186
|
+
abortPipe();
|
|
2187
|
+
try {
|
|
2188
|
+
await closed;
|
|
2189
|
+
} catch {
|
|
2190
|
+
// ignored
|
|
2191
|
+
}
|
|
2192
|
+
workerData.onTaskFinished();
|
|
2193
|
+
throw error;
|
|
2194
|
+
}
|
|
2152
2195
|
if (!streamsTransferred) {
|
|
2153
2196
|
Object.assign(workerData, {
|
|
2154
2197
|
reader: readable.getReader(),
|
|
2155
2198
|
writer: writable.getWriter()
|
|
2156
2199
|
});
|
|
2157
2200
|
}
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
await
|
|
2201
|
+
try {
|
|
2202
|
+
const resultValue = await result;
|
|
2203
|
+
await closeWritable();
|
|
2204
|
+
await closed;
|
|
2205
|
+
return resultValue;
|
|
2206
|
+
} catch (error) {
|
|
2207
|
+
await closeWritable();
|
|
2208
|
+
// unblock the pipe watcher if the worker died before closing its end of the stream
|
|
2209
|
+
abortPipe();
|
|
2210
|
+
try {
|
|
2211
|
+
await closed;
|
|
2212
|
+
} catch {
|
|
2213
|
+
// ignored
|
|
2214
|
+
}
|
|
2215
|
+
throw error;
|
|
2216
|
+
}
|
|
2217
|
+
|
|
2218
|
+
async function closeWritable() {
|
|
2219
|
+
if (!streamsTransferred && !writable.locked) {
|
|
2220
|
+
try {
|
|
2221
|
+
await writable.getWriter().close();
|
|
2222
|
+
} catch {
|
|
2223
|
+
// ignored
|
|
2224
|
+
}
|
|
2225
|
+
}
|
|
2161
2226
|
}
|
|
2162
|
-
await closed;
|
|
2163
|
-
return resultValue;
|
|
2164
2227
|
}
|
|
2165
2228
|
|
|
2166
2229
|
function watchClosedStream(writableSource) {
|
|
2230
|
+
const abortController = new AbortController();
|
|
2167
2231
|
const { writable, readable } = new TransformStream();
|
|
2168
|
-
const closed = readable.pipeTo(writableSource, { preventClose: true });
|
|
2169
|
-
|
|
2232
|
+
const closed = readable.pipeTo(writableSource, { preventClose: true, preventAbort: true, signal: abortController.signal });
|
|
2233
|
+
// the pipe can fail before `closed` is awaited (e.g. the destination write fails);
|
|
2234
|
+
// mark the rejection as handled so it cannot kill the process in the meantime
|
|
2235
|
+
closed.catch(() => { });
|
|
2236
|
+
return { writable, closed, abortPipe: () => abortController.abort() };
|
|
2237
|
+
}
|
|
2238
|
+
|
|
2239
|
+
function terminateWorker$1(workerData) {
|
|
2240
|
+
const { worker } = workerData;
|
|
2241
|
+
if (worker) {
|
|
2242
|
+
try {
|
|
2243
|
+
worker.terminate();
|
|
2244
|
+
} catch {
|
|
2245
|
+
// ignored
|
|
2246
|
+
}
|
|
2247
|
+
}
|
|
2248
|
+
workerData.interface = null;
|
|
2170
2249
|
}
|
|
2171
2250
|
|
|
2172
2251
|
function getWebWorker(url, baseURI, workerData, isModuleType, useBlobURI = true) {
|
|
2173
2252
|
let worker, resolvedURI, resolvedOptions;
|
|
2174
|
-
if (webWorkerURI === UNDEFINED_VALUE) {
|
|
2253
|
+
if (webWorkerURI === UNDEFINED_VALUE || webWorkerSource !== url) {
|
|
2175
2254
|
// deno-lint-ignore valid-typeof
|
|
2176
2255
|
const isFunctionURI = typeof url == FUNCTION_TYPE;
|
|
2177
2256
|
if (isFunctionURI) {
|
|
@@ -2228,16 +2307,36 @@
|
|
|
2228
2307
|
}
|
|
2229
2308
|
}
|
|
2230
2309
|
}
|
|
2310
|
+
webWorkerSource = url;
|
|
2231
2311
|
webWorkerURI = resolvedURI;
|
|
2232
2312
|
webWorkerOptions = resolvedOptions;
|
|
2233
2313
|
} else {
|
|
2234
2314
|
worker = new Worker(webWorkerURI, webWorkerOptions);
|
|
2235
2315
|
}
|
|
2236
2316
|
worker.addEventListener(MESSAGE_EVENT_TYPE, event => onMessage(event, workerData));
|
|
2317
|
+
worker.addEventListener(ERROR_EVENT_TYPE, event => onWorkerError(event, workerData));
|
|
2318
|
+
worker.addEventListener(MESSAGE_ERROR_EVENT_TYPE, event => onWorkerError(event, workerData));
|
|
2237
2319
|
return worker;
|
|
2238
2320
|
}
|
|
2239
2321
|
|
|
2240
|
-
function
|
|
2322
|
+
function onWorkerError(event, workerData) {
|
|
2323
|
+
if (event.preventDefault) {
|
|
2324
|
+
event.preventDefault();
|
|
2325
|
+
}
|
|
2326
|
+
const { rejectResult, writer, onTaskFinished } = workerData;
|
|
2327
|
+
// the worker is unusable (e.g. its script failed to load); terminate it and
|
|
2328
|
+
// fail the current task instead of letting it hang forever
|
|
2329
|
+
terminateWorker$1(workerData);
|
|
2330
|
+
if (rejectResult) {
|
|
2331
|
+
rejectResult(event.error || new Error(event.message || ERROR_EVENT_TYPE));
|
|
2332
|
+
if (writer) {
|
|
2333
|
+
writer.releaseLock();
|
|
2334
|
+
}
|
|
2335
|
+
onTaskFinished();
|
|
2336
|
+
}
|
|
2337
|
+
}
|
|
2338
|
+
|
|
2339
|
+
function sendMessage(message, { worker, writer, transferStreams }) {
|
|
2241
2340
|
try {
|
|
2242
2341
|
const { value, readable, writable } = message;
|
|
2243
2342
|
const transferables = [];
|
|
@@ -2271,14 +2370,16 @@
|
|
|
2271
2370
|
if (writer) {
|
|
2272
2371
|
writer.releaseLock();
|
|
2273
2372
|
}
|
|
2274
|
-
onTaskFinished();
|
|
2275
2373
|
throw error;
|
|
2276
2374
|
}
|
|
2277
2375
|
}
|
|
2278
2376
|
|
|
2279
2377
|
async function onMessage({ data }, workerData) {
|
|
2280
2378
|
const { type, value, messageId, result, error } = data;
|
|
2281
|
-
const { reader, writer, resolveResult, rejectResult, onTaskFinished } = workerData;
|
|
2379
|
+
const { reader, writer, resolveResult, rejectResult, onTaskFinished, generation } = workerData;
|
|
2380
|
+
// continuations below can settle after the worker slot has been reassigned to a new
|
|
2381
|
+
// task (e.g. a pending pull read failing late); they must not touch the new task
|
|
2382
|
+
const stale = () => workerData.generation != generation;
|
|
2282
2383
|
try {
|
|
2283
2384
|
if (error) {
|
|
2284
2385
|
const { message, stack, code, name, outputSize } = error;
|
|
@@ -2288,23 +2389,32 @@
|
|
|
2288
2389
|
} else {
|
|
2289
2390
|
if (type == MESSAGE_PULL) {
|
|
2290
2391
|
const { value, done } = await reader.read();
|
|
2291
|
-
|
|
2392
|
+
if (!stale()) {
|
|
2393
|
+
sendMessage({ type: MESSAGE_DATA, value, done, messageId }, workerData);
|
|
2394
|
+
}
|
|
2292
2395
|
}
|
|
2293
2396
|
if (type == MESSAGE_DATA) {
|
|
2294
2397
|
await writer.ready;
|
|
2295
2398
|
await writer.write(new Uint8Array(value));
|
|
2296
|
-
|
|
2399
|
+
if (!stale()) {
|
|
2400
|
+
sendMessage({ type: MESSAGE_ACK_DATA, messageId }, workerData);
|
|
2401
|
+
}
|
|
2297
2402
|
}
|
|
2298
2403
|
if (type == MESSAGE_CLOSE) {
|
|
2299
2404
|
close(null, result);
|
|
2300
2405
|
}
|
|
2301
2406
|
}
|
|
2302
2407
|
} catch (error) {
|
|
2303
|
-
|
|
2304
|
-
|
|
2408
|
+
if (!stale()) {
|
|
2409
|
+
terminateWorker$1(workerData);
|
|
2410
|
+
close(error);
|
|
2411
|
+
}
|
|
2305
2412
|
}
|
|
2306
2413
|
|
|
2307
2414
|
function close(error, result) {
|
|
2415
|
+
if (stale()) {
|
|
2416
|
+
return;
|
|
2417
|
+
}
|
|
2308
2418
|
if (error) {
|
|
2309
2419
|
rejectResult(error);
|
|
2310
2420
|
} else {
|
|
@@ -2348,6 +2458,8 @@
|
|
|
2348
2458
|
|
|
2349
2459
|
let pool = [];
|
|
2350
2460
|
const pendingRequests = [];
|
|
2461
|
+
let starvationTimeout;
|
|
2462
|
+
let starvationDelay;
|
|
2351
2463
|
|
|
2352
2464
|
let indexWorker = 0;
|
|
2353
2465
|
|
|
@@ -2374,14 +2486,20 @@
|
|
|
2374
2486
|
pool.push(workerData);
|
|
2375
2487
|
return new CodecWorker(workerData, stream, workerOptions, onTaskFinished);
|
|
2376
2488
|
} else {
|
|
2377
|
-
return new Promise(resolve =>
|
|
2489
|
+
return new Promise(resolve => {
|
|
2490
|
+
pendingRequests.push({ resolve, stream, workerOptions });
|
|
2491
|
+
starvationDelay = config.workerStarvationTimeout;
|
|
2492
|
+
armStarvationTimeout();
|
|
2493
|
+
});
|
|
2378
2494
|
}
|
|
2379
2495
|
}
|
|
2380
2496
|
|
|
2381
2497
|
function onTaskFinished(workerData) {
|
|
2498
|
+
clearStarvationTimeout();
|
|
2382
2499
|
if (pendingRequests.length) {
|
|
2383
2500
|
const [{ resolve, stream, workerOptions }] = pendingRequests.splice(0, 1);
|
|
2384
2501
|
resolve(new CodecWorker(workerData, stream, workerOptions, onTaskFinished));
|
|
2502
|
+
armStarvationTimeout();
|
|
2385
2503
|
} else if (workerData.worker) {
|
|
2386
2504
|
clearTerminateTimeout(workerData);
|
|
2387
2505
|
terminateWorker(workerData, workerOptions);
|
|
@@ -2391,6 +2509,34 @@
|
|
|
2391
2509
|
}
|
|
2392
2510
|
}
|
|
2393
2511
|
|
|
2512
|
+
function armStarvationTimeout() {
|
|
2513
|
+
if (!starvationTimeout && pendingRequests.length && Number.isFinite(starvationDelay) && starvationDelay >= 0) {
|
|
2514
|
+
starvationTimeout = setTimeout(onWorkerStarvation, starvationDelay);
|
|
2515
|
+
}
|
|
2516
|
+
}
|
|
2517
|
+
|
|
2518
|
+
function clearStarvationTimeout() {
|
|
2519
|
+
if (starvationTimeout) {
|
|
2520
|
+
clearTimeout(starvationTimeout);
|
|
2521
|
+
starvationTimeout = null;
|
|
2522
|
+
}
|
|
2523
|
+
}
|
|
2524
|
+
|
|
2525
|
+
function onWorkerStarvation() {
|
|
2526
|
+
starvationTimeout = null;
|
|
2527
|
+
if (pendingRequests.length) {
|
|
2528
|
+
const [{ resolve, stream, workerOptions }] = pendingRequests.splice(0, 1);
|
|
2529
|
+
const inlineWorkerOptions = Object.assign({}, workerOptions, { useWebWorkers: false, workerURI: UNDEFINED_VALUE });
|
|
2530
|
+
resolve(new CodecWorker({}, stream, inlineWorkerOptions, onInlineTaskFinished));
|
|
2531
|
+
armStarvationTimeout();
|
|
2532
|
+
}
|
|
2533
|
+
}
|
|
2534
|
+
|
|
2535
|
+
function onInlineTaskFinished() {
|
|
2536
|
+
clearStarvationTimeout();
|
|
2537
|
+
armStarvationTimeout();
|
|
2538
|
+
}
|
|
2539
|
+
|
|
2394
2540
|
function terminateWorker(workerData, workerOptions) {
|
|
2395
2541
|
const { config } = workerOptions;
|
|
2396
2542
|
const { terminateWorkerTimeout } = config;
|
|
@@ -2461,6 +2607,7 @@
|
|
|
2461
2607
|
|
|
2462
2608
|
const CONTENT_TYPE_TEXT_PLAIN = "text/plain";
|
|
2463
2609
|
const HTTP_HEADER_CONTENT_LENGTH = "Content-Length";
|
|
2610
|
+
const HTTP_HEADER_CONTENT_ENCODING = "Content-Encoding";
|
|
2464
2611
|
const HTTP_HEADER_CONTENT_RANGE = "Content-Range";
|
|
2465
2612
|
const HTTP_HEADER_ACCEPT_RANGES = "Accept-Ranges";
|
|
2466
2613
|
const HTTP_HEADER_RANGE = "Range";
|
|
@@ -2585,7 +2732,7 @@
|
|
|
2585
2732
|
|
|
2586
2733
|
writeUint8Array(array) {
|
|
2587
2734
|
const writer = this;
|
|
2588
|
-
let indexArray
|
|
2735
|
+
let indexArray;
|
|
2589
2736
|
let dataString = writer.pending;
|
|
2590
2737
|
const delta = writer.pending.length;
|
|
2591
2738
|
writer.pending = "";
|
|
@@ -2595,12 +2742,10 @@
|
|
|
2595
2742
|
for (; indexArray < array.length; indexArray++) {
|
|
2596
2743
|
writer.pending += String.fromCharCode(array[indexArray]);
|
|
2597
2744
|
}
|
|
2598
|
-
if (dataString.length) {
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
writer.pending += dataString;
|
|
2603
|
-
}
|
|
2745
|
+
if (dataString.length > 2) {
|
|
2746
|
+
writer.data += btoa(dataString);
|
|
2747
|
+
} else {
|
|
2748
|
+
writer.pending = dataString + writer.pending;
|
|
2604
2749
|
}
|
|
2605
2750
|
}
|
|
2606
2751
|
|
|
@@ -2647,6 +2792,9 @@
|
|
|
2647
2792
|
}
|
|
2648
2793
|
});
|
|
2649
2794
|
writer.blob = new Response(transformStream.readable, { headers }).blob();
|
|
2795
|
+
// mark early rejections (e.g. aborted pipe) as handled; awaiting getData() still
|
|
2796
|
+
// surfaces them
|
|
2797
|
+
writer.blob.catch(() => { });
|
|
2650
2798
|
}
|
|
2651
2799
|
|
|
2652
2800
|
getData() {
|
|
@@ -2731,7 +2879,8 @@
|
|
|
2731
2879
|
preventHeadRequest,
|
|
2732
2880
|
useRangeHeader,
|
|
2733
2881
|
forceRangeRequests,
|
|
2734
|
-
combineSizeEocd
|
|
2882
|
+
combineSizeEocd,
|
|
2883
|
+
fetch
|
|
2735
2884
|
} = options;
|
|
2736
2885
|
options = Object.assign({}, options);
|
|
2737
2886
|
delete options.preventHeadRequest;
|
|
@@ -2739,13 +2888,15 @@
|
|
|
2739
2888
|
delete options.forceRangeRequests;
|
|
2740
2889
|
delete options.combineSizeEocd;
|
|
2741
2890
|
delete options.useXHR;
|
|
2891
|
+
delete options.fetch;
|
|
2742
2892
|
Object.assign(httpReader, {
|
|
2743
2893
|
url,
|
|
2744
2894
|
options,
|
|
2745
2895
|
preventHeadRequest,
|
|
2746
2896
|
useRangeHeader,
|
|
2747
2897
|
forceRangeRequests,
|
|
2748
|
-
combineSizeEocd
|
|
2898
|
+
combineSizeEocd,
|
|
2899
|
+
fetch
|
|
2749
2900
|
});
|
|
2750
2901
|
}
|
|
2751
2902
|
|
|
@@ -2764,7 +2915,10 @@
|
|
|
2764
2915
|
throw new Error(ERR_HTTP_RANGE);
|
|
2765
2916
|
} else {
|
|
2766
2917
|
if (combineSizeEocd) {
|
|
2767
|
-
|
|
2918
|
+
const eocdCache = new Uint8Array(await response.arrayBuffer());
|
|
2919
|
+
if (response.status == 206 && eocdCache.length == END_OF_CENTRAL_DIR_LENGTH) {
|
|
2920
|
+
httpReader.eocdCache = eocdCache;
|
|
2921
|
+
}
|
|
2768
2922
|
}
|
|
2769
2923
|
let contentSize;
|
|
2770
2924
|
const contentRangeHeader = response.headers.get(HTTP_HEADER_CONTENT_RANGE);
|
|
@@ -2810,7 +2964,18 @@
|
|
|
2810
2964
|
if (response.status != 206) {
|
|
2811
2965
|
throw new Error(ERR_HTTP_RANGE);
|
|
2812
2966
|
}
|
|
2813
|
-
|
|
2967
|
+
const contentRangeHeader = response.headers.get(HTTP_HEADER_CONTENT_RANGE);
|
|
2968
|
+
if (contentRangeHeader) {
|
|
2969
|
+
const rangeStart = Number(contentRangeHeader.trim().split(/[\s-]+/)[1]);
|
|
2970
|
+
if (!Number.isNaN(rangeStart) && rangeStart != index) {
|
|
2971
|
+
throw new Error(ERR_HTTP_RANGE);
|
|
2972
|
+
}
|
|
2973
|
+
}
|
|
2974
|
+
const data = new Uint8Array(await response.arrayBuffer());
|
|
2975
|
+
if (data.length != length) {
|
|
2976
|
+
throw new Error(ERR_HTTP_RANGE);
|
|
2977
|
+
}
|
|
2978
|
+
return data;
|
|
2814
2979
|
}
|
|
2815
2980
|
} else {
|
|
2816
2981
|
const { data } = httpReader;
|
|
@@ -2847,9 +3012,9 @@
|
|
|
2847
3012
|
async function getRequestData(httpReader, sendRequest) {
|
|
2848
3013
|
const response = await sendRequest(HTTP_METHOD_GET, httpReader, getHeaders(httpReader));
|
|
2849
3014
|
httpReader.data = new Uint8Array(await response.arrayBuffer());
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
3015
|
+
// the downloaded content is authoritative, e.g. the Content-Length response header
|
|
3016
|
+
// of the HEAD request can be the encoded size when the content is compressed
|
|
3017
|
+
httpReader.size = httpReader.data.length;
|
|
2853
3018
|
}
|
|
2854
3019
|
|
|
2855
3020
|
async function getContentLength(httpReader, sendRequest, getRequestData) {
|
|
@@ -2858,7 +3023,7 @@
|
|
|
2858
3023
|
} else {
|
|
2859
3024
|
const response = await sendRequest(HTTP_METHOD_HEAD, httpReader, getHeaders(httpReader));
|
|
2860
3025
|
const contentLength = response.headers.get(HTTP_HEADER_CONTENT_LENGTH);
|
|
2861
|
-
if (contentLength) {
|
|
3026
|
+
if (contentLength && !response.headers.get(HTTP_HEADER_CONTENT_ENCODING)) {
|
|
2862
3027
|
httpReader.size = Number(contentLength);
|
|
2863
3028
|
} else {
|
|
2864
3029
|
await getRequestData(httpReader, httpReader.options);
|
|
@@ -2866,8 +3031,8 @@
|
|
|
2866
3031
|
}
|
|
2867
3032
|
}
|
|
2868
3033
|
|
|
2869
|
-
async function sendFetchRequest(method, { options, url }, headers) {
|
|
2870
|
-
const response = await
|
|
3034
|
+
async function sendFetchRequest(method, { fetch: fetchFunction = fetch, options, url }, headers) {
|
|
3035
|
+
const response = await fetchFunction(url, Object.assign({}, options, { method, headers }));
|
|
2871
3036
|
if (response.status < 400) {
|
|
2872
3037
|
return response;
|
|
2873
3038
|
} else {
|
|
@@ -2913,7 +3078,8 @@
|
|
|
2913
3078
|
super();
|
|
2914
3079
|
Object.assign(this, {
|
|
2915
3080
|
url,
|
|
2916
|
-
|
|
3081
|
+
// an explicit fetch implementation takes precedence over useXHR
|
|
3082
|
+
reader: options.useXHR && !options.fetch ? new XHRReader(url, options) : new FetchReader(url, options)
|
|
2917
3083
|
});
|
|
2918
3084
|
}
|
|
2919
3085
|
|
|
@@ -2938,8 +3104,7 @@
|
|
|
2938
3104
|
class HttpRangeReader extends HttpReader {
|
|
2939
3105
|
|
|
2940
3106
|
constructor(url, options = {}) {
|
|
2941
|
-
options
|
|
2942
|
-
super(url, options);
|
|
3107
|
+
super(url, Object.assign({}, options, { useRangeHeader: true }));
|
|
2943
3108
|
}
|
|
2944
3109
|
}
|
|
2945
3110
|
|
|
@@ -3013,7 +3178,7 @@
|
|
|
3013
3178
|
reader.lastDiskNumber = 0;
|
|
3014
3179
|
reader.lastDiskOffset = 0;
|
|
3015
3180
|
await Promise.all(readers.map(async (diskReader, indexDiskReader) => {
|
|
3016
|
-
await diskReader
|
|
3181
|
+
await initStream(diskReader);
|
|
3017
3182
|
if (indexDiskReader != readers.length - 1) {
|
|
3018
3183
|
reader.lastDiskOffset += diskReader.size;
|
|
3019
3184
|
}
|
|
@@ -3097,14 +3262,26 @@
|
|
|
3097
3262
|
writer.diskOffset += diskSourceWriter.size;
|
|
3098
3263
|
writer.diskNumber++;
|
|
3099
3264
|
diskWriter = null;
|
|
3100
|
-
|
|
3265
|
+
// the next disk is not opened yet but its space is available; leaving a
|
|
3266
|
+
// stale value here would force a new disk for every subsequent write
|
|
3267
|
+
writer.availableSize = writer.maxSize;
|
|
3268
|
+
if (chunk.length > availableSize) {
|
|
3269
|
+
await this.write(chunk.subarray(availableSize));
|
|
3270
|
+
}
|
|
3101
3271
|
} else {
|
|
3102
3272
|
await writeChunk(chunk);
|
|
3103
3273
|
}
|
|
3104
3274
|
},
|
|
3105
3275
|
async close() {
|
|
3106
|
-
|
|
3107
|
-
|
|
3276
|
+
if (diskWriter) {
|
|
3277
|
+
await diskWriter.ready;
|
|
3278
|
+
await closeDisk();
|
|
3279
|
+
}
|
|
3280
|
+
},
|
|
3281
|
+
async abort(reason) {
|
|
3282
|
+
if (diskWriter) {
|
|
3283
|
+
await diskWriter.abort(reason);
|
|
3284
|
+
}
|
|
3108
3285
|
}
|
|
3109
3286
|
});
|
|
3110
3287
|
Object.defineProperty(writer, PROPERTY_NAME_WRITABLE, {
|
|
@@ -3119,7 +3296,6 @@
|
|
|
3119
3296
|
await diskWriter.ready;
|
|
3120
3297
|
await diskWriter.write(chunk);
|
|
3121
3298
|
diskSourceWriter.size += chunkLength;
|
|
3122
|
-
writer.size += chunkLength;
|
|
3123
3299
|
writer.availableSize -= chunkLength;
|
|
3124
3300
|
}
|
|
3125
3301
|
}
|
|
@@ -3219,7 +3395,7 @@
|
|
|
3219
3395
|
|
|
3220
3396
|
/* global TextDecoder */
|
|
3221
3397
|
|
|
3222
|
-
const CP437 = "\0☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼ !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~⌂ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■
|
|
3398
|
+
const CP437 = "\0☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼ !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~⌂ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ ".split("");
|
|
3223
3399
|
const VALID_CP437 = CP437.length == 256;
|
|
3224
3400
|
|
|
3225
3401
|
function decodeCP437(stringValue) {
|
|
@@ -3267,7 +3443,8 @@
|
|
|
3267
3443
|
if (encoding && encoding.trim().toLowerCase() == "cp437") {
|
|
3268
3444
|
return decodeCP437(value);
|
|
3269
3445
|
} else {
|
|
3270
|
-
|
|
3446
|
+
// ignoreBOM keeps a leading U+FEFF in filenames/comments instead of dropping it
|
|
3447
|
+
return new TextDecoder(encoding, { ignoreBOM: true }).decode(value);
|
|
3271
3448
|
}
|
|
3272
3449
|
}
|
|
3273
3450
|
|
|
@@ -3444,6 +3621,7 @@
|
|
|
3444
3621
|
const OPTION_CHECK_PASSWORD_ONLY = "checkPasswordOnly";
|
|
3445
3622
|
const OPTION_CHECK_OVERLAPPING_ENTRY_ONLY = "checkOverlappingEntryOnly";
|
|
3446
3623
|
const OPTION_CHECK_OVERLAPPING_ENTRY = "checkOverlappingEntry";
|
|
3624
|
+
const OPTION_CHECK_AMBIGUITY = "checkAmbiguity";
|
|
3447
3625
|
const OPTION_CHECK_SIGNATURE = "checkSignature";
|
|
3448
3626
|
const OPTION_USE_WEB_WORKERS = "useWebWorkers";
|
|
3449
3627
|
const OPTION_USE_COMPRESSION_STREAM = "useCompressionStream";
|
|
@@ -3501,12 +3679,16 @@
|
|
|
3501
3679
|
const ERR_EXTRAFIELD_ZIP64_NOT_FOUND = "Zip64 extra field not found";
|
|
3502
3680
|
const ERR_ENCRYPTED = "File contains encrypted entry";
|
|
3503
3681
|
const ERR_UNSUPPORTED_ENCRYPTION = "Encryption method not supported";
|
|
3504
|
-
const ERR_UNSUPPORTED_COMPRESSION = "Compression method not supported";
|
|
3682
|
+
const ERR_UNSUPPORTED_COMPRESSION$1 = "Compression method not supported";
|
|
3505
3683
|
const ERR_SPLIT_ZIP_FILE = "Split zip file";
|
|
3506
3684
|
const ERR_OVERLAPPING_ENTRY = "Overlapping entry found";
|
|
3685
|
+
const ERR_AMBIGUOUS_ARCHIVE = "Ambiguous archive";
|
|
3507
3686
|
const CHARSET_UTF8 = "utf-8";
|
|
3508
3687
|
const PROPERTY_NAME_UTF8_SUFFIX = "UTF8";
|
|
3509
3688
|
const CHARSET_CP437 = "cp437";
|
|
3689
|
+
// bits of the general purpose flag that change how an entry is interpreted; the level bits (1-2) are excluded
|
|
3690
|
+
// because they are informative only
|
|
3691
|
+
const BITFLAG_AMBIGUITY_MASK = BITFLAG_ENCRYPTED | BITFLAG_DATA_DESCRIPTOR | BITFLAG_LANG_ENCODING_FLAG;
|
|
3510
3692
|
const ZIP64_PROPERTIES = [
|
|
3511
3693
|
[PROPERTY_NAME_UNCOMPRESSED_SIZE, MAX_32_BITS],
|
|
3512
3694
|
[PROPERTY_NAME_COMPRESSED_SIZE, MAX_32_BITS],
|
|
@@ -3531,7 +3713,7 @@
|
|
|
3531
3713
|
reader: new GenericReader(reader),
|
|
3532
3714
|
options,
|
|
3533
3715
|
config: getConfiguration(),
|
|
3534
|
-
readRanges:
|
|
3716
|
+
readRanges: new Map()
|
|
3535
3717
|
});
|
|
3536
3718
|
}
|
|
3537
3719
|
|
|
@@ -3564,21 +3746,30 @@
|
|
|
3564
3746
|
const commentOffset = endOfDirectoryInfo.offset;
|
|
3565
3747
|
const commentLength = getUint16(endOfDirectoryView, 20);
|
|
3566
3748
|
const appendedDataOffset = commentOffset + END_OF_CENTRAL_DIR_LENGTH + commentLength;
|
|
3749
|
+
const checkAmbiguity = getOptionValue$1(zipReader, options, OPTION_CHECK_AMBIGUITY);
|
|
3750
|
+
if (checkAmbiguity && appendedDataOffset != reader.size) {
|
|
3751
|
+
throwAmbiguousArchive("appended data");
|
|
3752
|
+
}
|
|
3567
3753
|
let lastDiskNumber = getUint16(endOfDirectoryView, 4);
|
|
3568
3754
|
const expectedLastDiskNumber = reader.lastDiskNumber || 0;
|
|
3569
3755
|
let diskNumber = getUint16(endOfDirectoryView, 6);
|
|
3570
|
-
let filesLength = getUint16(endOfDirectoryView,
|
|
3756
|
+
let filesLength = getUint16(endOfDirectoryView, 10);
|
|
3571
3757
|
let prependedDataLength = 0;
|
|
3572
|
-
let startOffset
|
|
3758
|
+
let startOffset;
|
|
3759
|
+
let zip64EndOfDirectory;
|
|
3573
3760
|
if (directoryDataOffset == MAX_32_BITS || directoryDataLength == MAX_32_BITS || filesLength == MAX_16_BITS || diskNumber == MAX_16_BITS) {
|
|
3574
|
-
const endOfDirectoryLocatorArray =
|
|
3761
|
+
const endOfDirectoryLocatorArray = endOfDirectoryInfo.offset >= ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH ?
|
|
3762
|
+
await readUint8Array(reader, endOfDirectoryInfo.offset - ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH, ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH) :
|
|
3763
|
+
new Uint8Array();
|
|
3575
3764
|
const endOfDirectoryLocatorView = getDataView$1(endOfDirectoryLocatorArray);
|
|
3576
|
-
if (
|
|
3765
|
+
if (endOfDirectoryLocatorArray.length == ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH &&
|
|
3766
|
+
getUint32(endOfDirectoryLocatorView, 0) == ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIGNATURE) {
|
|
3577
3767
|
directoryDataOffset = getBigUint64(endOfDirectoryLocatorView, 8);
|
|
3578
3768
|
let endOfDirectoryArray = await readUint8Array(reader, directoryDataOffset, ZIP64_END_OF_CENTRAL_DIR_LENGTH, -1);
|
|
3579
3769
|
let endOfDirectoryView = getDataView$1(endOfDirectoryArray);
|
|
3580
|
-
const expectedDirectoryDataOffset = endOfDirectoryInfo.offset - ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH - ZIP64_END_OF_CENTRAL_DIR_LENGTH;
|
|
3581
|
-
if (getUint32(endOfDirectoryView, 0) != ZIP64_END_OF_CENTRAL_DIR_SIGNATURE &&
|
|
3770
|
+
const expectedDirectoryDataOffset = endOfDirectoryInfo.offset - ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH - ZIP64_END_OF_CENTRAL_DIR_LENGTH - (reader.lastDiskOffset || 0);
|
|
3771
|
+
if ((endOfDirectoryArray.length < ZIP64_END_OF_CENTRAL_DIR_LENGTH || getUint32(endOfDirectoryView, 0) != ZIP64_END_OF_CENTRAL_DIR_SIGNATURE) &&
|
|
3772
|
+
directoryDataOffset != expectedDirectoryDataOffset && expectedDirectoryDataOffset >= 0) {
|
|
3582
3773
|
const originalDirectoryDataOffset = directoryDataOffset;
|
|
3583
3774
|
directoryDataOffset = expectedDirectoryDataOffset;
|
|
3584
3775
|
if (directoryDataOffset > originalDirectoryDataOffset) {
|
|
@@ -3587,24 +3778,36 @@
|
|
|
3587
3778
|
endOfDirectoryArray = await readUint8Array(reader, directoryDataOffset, ZIP64_END_OF_CENTRAL_DIR_LENGTH, -1);
|
|
3588
3779
|
endOfDirectoryView = getDataView$1(endOfDirectoryArray);
|
|
3589
3780
|
}
|
|
3590
|
-
if (getUint32(endOfDirectoryView, 0) != ZIP64_END_OF_CENTRAL_DIR_SIGNATURE) {
|
|
3781
|
+
if (endOfDirectoryArray.length < ZIP64_END_OF_CENTRAL_DIR_LENGTH || getUint32(endOfDirectoryView, 0) != ZIP64_END_OF_CENTRAL_DIR_SIGNATURE) {
|
|
3591
3782
|
throw new Error(ERR_EOCDR_LOCATOR_ZIP64_NOT_FOUND);
|
|
3592
3783
|
}
|
|
3784
|
+
zip64EndOfDirectory = true;
|
|
3593
3785
|
if (lastDiskNumber == MAX_16_BITS) {
|
|
3594
3786
|
lastDiskNumber = getUint32(endOfDirectoryView, 16);
|
|
3787
|
+
} else if (checkAmbiguity && lastDiskNumber != getUint32(endOfDirectoryView, 16)) {
|
|
3788
|
+
throwAmbiguousArchive("mismatched zip64 end of central directory record");
|
|
3595
3789
|
}
|
|
3596
3790
|
if (diskNumber == MAX_16_BITS) {
|
|
3597
3791
|
diskNumber = getUint32(endOfDirectoryView, 20);
|
|
3792
|
+
} else if (checkAmbiguity && diskNumber != getUint32(endOfDirectoryView, 20)) {
|
|
3793
|
+
throwAmbiguousArchive("mismatched zip64 end of central directory record");
|
|
3598
3794
|
}
|
|
3599
3795
|
if (filesLength == MAX_16_BITS) {
|
|
3600
3796
|
filesLength = getBigUint64(endOfDirectoryView, 32);
|
|
3797
|
+
} else if (checkAmbiguity && filesLength != getBigUint64(endOfDirectoryView, 32)) {
|
|
3798
|
+
throwAmbiguousArchive("mismatched zip64 end of central directory record");
|
|
3601
3799
|
}
|
|
3602
3800
|
if (directoryDataLength == MAX_32_BITS) {
|
|
3603
3801
|
directoryDataLength = getBigUint64(endOfDirectoryView, 40);
|
|
3802
|
+
} else if (checkAmbiguity && directoryDataLength != getBigUint64(endOfDirectoryView, 40)) {
|
|
3803
|
+
throwAmbiguousArchive("mismatched zip64 end of central directory record");
|
|
3604
3804
|
}
|
|
3605
|
-
directoryDataOffset
|
|
3805
|
+
directoryDataOffset = getBigUint64(endOfDirectoryView, 48) + prependedDataLength;
|
|
3606
3806
|
}
|
|
3607
3807
|
}
|
|
3808
|
+
const declaredDirectoryDataLength = directoryDataLength;
|
|
3809
|
+
const centralDirectoryEndOffset = endOfDirectoryInfo.offset -
|
|
3810
|
+
(zip64EndOfDirectory ? ZIP64_END_OF_CENTRAL_DIR_LENGTH + ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH : 0);
|
|
3608
3811
|
if (directoryDataOffset >= reader.size) {
|
|
3609
3812
|
prependedDataLength = reader.size - directoryDataOffset - directoryDataLength - END_OF_CENTRAL_DIR_LENGTH;
|
|
3610
3813
|
directoryDataOffset = reader.size - directoryDataLength - END_OF_CENTRAL_DIR_LENGTH;
|
|
@@ -3619,8 +3822,11 @@
|
|
|
3619
3822
|
let directoryArray = await readUint8Array(reader, directoryDataOffset, directoryDataLength, diskNumber);
|
|
3620
3823
|
let directoryView = getDataView$1(directoryArray);
|
|
3621
3824
|
if (directoryDataLength) {
|
|
3622
|
-
|
|
3623
|
-
|
|
3825
|
+
if (directoryArray.length < 4) {
|
|
3826
|
+
throw new Error(ERR_BAD_FORMAT);
|
|
3827
|
+
}
|
|
3828
|
+
const expectedDirectoryDataOffset = centralDirectoryEndOffset - directoryDataLength - (reader.lastDiskOffset || 0);
|
|
3829
|
+
if (getUint32(directoryView, offset) != CENTRAL_FILE_HEADER_SIGNATURE && directoryDataOffset != expectedDirectoryDataOffset && diskNumber == lastDiskNumber) {
|
|
3624
3830
|
const originalDirectoryDataOffset = directoryDataOffset;
|
|
3625
3831
|
directoryDataOffset = expectedDirectoryDataOffset;
|
|
3626
3832
|
if (directoryDataOffset > originalDirectoryDataOffset) {
|
|
@@ -3630,8 +3836,8 @@
|
|
|
3630
3836
|
directoryView = getDataView$1(directoryArray);
|
|
3631
3837
|
}
|
|
3632
3838
|
}
|
|
3633
|
-
const expectedDirectoryDataLength =
|
|
3634
|
-
if (directoryDataLength != expectedDirectoryDataLength && expectedDirectoryDataLength >= 0) {
|
|
3839
|
+
const expectedDirectoryDataLength = centralDirectoryEndOffset - directoryDataOffset - (reader.lastDiskOffset || 0);
|
|
3840
|
+
if (directoryDataLength != expectedDirectoryDataLength && expectedDirectoryDataLength >= 0 && diskNumber == lastDiskNumber) {
|
|
3635
3841
|
directoryDataLength = expectedDirectoryDataLength;
|
|
3636
3842
|
directoryArray = await readUint8Array(reader, directoryDataOffset, directoryDataLength, diskNumber);
|
|
3637
3843
|
directoryView = getDataView$1(directoryArray);
|
|
@@ -3639,16 +3845,19 @@
|
|
|
3639
3845
|
if (directoryDataOffset < 0 || directoryDataOffset >= reader.size) {
|
|
3640
3846
|
throw new Error(ERR_BAD_FORMAT);
|
|
3641
3847
|
}
|
|
3848
|
+
startOffset = directoryDataOffset;
|
|
3642
3849
|
const filenameEncoding = getOptionValue$1(zipReader, options, OPTION_FILENAME_ENCODING);
|
|
3643
3850
|
const commentEncoding = getOptionValue$1(zipReader, options, OPTION_COMMENT_ENCODING);
|
|
3851
|
+
const filenames = checkAmbiguity ? new Set() : UNDEFINED_VALUE;
|
|
3852
|
+
let duplicateFilename;
|
|
3644
3853
|
for (let indexFile = 0; indexFile < filesLength; indexFile++) {
|
|
3645
3854
|
const fileEntry = new ZipEntry(reader, config, zipReader.options);
|
|
3646
|
-
if (getUint32(directoryView, offset) != CENTRAL_FILE_HEADER_SIGNATURE) {
|
|
3855
|
+
if (offset + CENTRAL_FILE_HEADER_LENGTH > directoryArray.length || getUint32(directoryView, offset) != CENTRAL_FILE_HEADER_SIGNATURE) {
|
|
3647
3856
|
throw new Error(ERR_CENTRAL_DIRECTORY_NOT_FOUND);
|
|
3648
3857
|
}
|
|
3649
3858
|
readCommonHeader(fileEntry, directoryView, offset + 6);
|
|
3650
3859
|
const languageEncodingFlag = Boolean(fileEntry.bitFlag.languageEncodingFlag);
|
|
3651
|
-
const filenameOffset = offset +
|
|
3860
|
+
const filenameOffset = offset + CENTRAL_FILE_HEADER_LENGTH;
|
|
3652
3861
|
const extraFieldOffset = filenameOffset + fileEntry.filenameLength;
|
|
3653
3862
|
const commentOffset = extraFieldOffset + fileEntry.extraFieldLength;
|
|
3654
3863
|
const versionMadeBy = getUint16(directoryView, offset + 4);
|
|
@@ -3669,7 +3878,7 @@
|
|
|
3669
3878
|
directory: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_DIR_MASK),
|
|
3670
3879
|
archive: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_ARCHIVE_MASK)
|
|
3671
3880
|
};
|
|
3672
|
-
const offsetFileEntry = getUint32(directoryView, offset + 42)
|
|
3881
|
+
const offsetFileEntry = getUint32(directoryView, offset + 42);
|
|
3673
3882
|
const decode = getOptionValue$1(zipReader, options, OPTION_DECODE_TEXT) || decodeText;
|
|
3674
3883
|
const rawFilenameEncoding = filenameUTF8 ? CHARSET_UTF8 : filenameEncoding || CHARSET_CP437;
|
|
3675
3884
|
const rawCommentEncoding = commentUTF8 ? CHARSET_UTF8 : commentEncoding || CHARSET_CP437;
|
|
@@ -3682,6 +3891,7 @@
|
|
|
3682
3891
|
comment = decodeText(rawComment, rawCommentEncoding);
|
|
3683
3892
|
}
|
|
3684
3893
|
Object.assign(fileEntry, {
|
|
3894
|
+
index: indexFile,
|
|
3685
3895
|
versionMadeBy,
|
|
3686
3896
|
msDosCompatible,
|
|
3687
3897
|
compressedSize: 0,
|
|
@@ -3701,8 +3911,15 @@
|
|
|
3701
3911
|
filename,
|
|
3702
3912
|
comment
|
|
3703
3913
|
});
|
|
3704
|
-
startOffset = Math.max(offsetFileEntry, startOffset);
|
|
3705
3914
|
readCommonFooter(fileEntry, fileEntry, directoryView, offset + 6);
|
|
3915
|
+
fileEntry.offset += prependedDataLength;
|
|
3916
|
+
startOffset = Math.min(fileEntry.offset, startOffset);
|
|
3917
|
+
if (checkAmbiguity) {
|
|
3918
|
+
if (filenames.has(fileEntry.filename)) {
|
|
3919
|
+
duplicateFilename = true;
|
|
3920
|
+
}
|
|
3921
|
+
filenames.add(fileEntry.filename);
|
|
3922
|
+
}
|
|
3706
3923
|
const unixExternalUpper = (fileEntry.externalFileAttributes >> 16) & MAX_16_BITS;
|
|
3707
3924
|
if (fileEntry.unixMode === UNDEFINED_VALUE && (unixExternalUpper & (FILE_ATTR_UNIX_DEFAULT_MASK | FILE_ATTR_UNIX_EXECUTABLE_MASK | FILE_ATTR_UNIX_TYPE_DIR)) != 0) {
|
|
3708
3925
|
fileEntry.unixMode = unixExternalUpper;
|
|
@@ -3723,7 +3940,7 @@
|
|
|
3723
3940
|
internalFileAttribute: fileEntry.internalFileAttributes,
|
|
3724
3941
|
externalFileAttribute: fileEntry.externalFileAttributes,
|
|
3725
3942
|
executable,
|
|
3726
|
-
directory: modeIsDir || upperIsDir || (msDosCompatible && msdosAttributes.directory) || (filename.endsWith(DIRECTORY_SIGNATURE) && !fileEntry.uncompressedSize),
|
|
3943
|
+
directory: modeIsDir || upperIsDir || (msDosCompatible && msdosAttributes.directory) || (fileEntry.filename.endsWith(DIRECTORY_SIGNATURE) && !fileEntry.uncompressedSize),
|
|
3727
3944
|
zipCrypto: fileEntry.encrypted && !fileEntry.extraFieldAES
|
|
3728
3945
|
});
|
|
3729
3946
|
const entry = new Entry(fileEntry);
|
|
@@ -3746,6 +3963,15 @@
|
|
|
3746
3963
|
}
|
|
3747
3964
|
yield entry;
|
|
3748
3965
|
}
|
|
3966
|
+
if (checkAmbiguity && offset != declaredDirectoryDataLength) {
|
|
3967
|
+
throwAmbiguousArchive("trailing central directory data");
|
|
3968
|
+
}
|
|
3969
|
+
if (duplicateFilename) {
|
|
3970
|
+
throwAmbiguousArchive("duplicate filename");
|
|
3971
|
+
}
|
|
3972
|
+
if (checkAmbiguity && (prependedDataLength || (filesLength && startOffset > 0))) {
|
|
3973
|
+
throwAmbiguousArchive("prepended data");
|
|
3974
|
+
}
|
|
3749
3975
|
const extractPrependedData = getOptionValue$1(zipReader, options, OPTION_EXTRACT_PREPENDED_DATA);
|
|
3750
3976
|
const extractAppendedData = getOptionValue$1(zipReader, options, OPTION_EXTRACT_APPENDED_DATA);
|
|
3751
3977
|
if (extractPrependedData) {
|
|
@@ -3785,9 +4011,21 @@
|
|
|
3785
4011
|
readable: (function () {
|
|
3786
4012
|
const { readable, writable } = new TransformStream();
|
|
3787
4013
|
if (value.getData) {
|
|
3788
|
-
|
|
4014
|
+
getData();
|
|
3789
4015
|
return readable;
|
|
3790
4016
|
}
|
|
4017
|
+
|
|
4018
|
+
async function getData() {
|
|
4019
|
+
try {
|
|
4020
|
+
await value.getData(writable);
|
|
4021
|
+
} catch (error) {
|
|
4022
|
+
try {
|
|
4023
|
+
await writable.abort(error);
|
|
4024
|
+
} catch {
|
|
4025
|
+
// ignored
|
|
4026
|
+
}
|
|
4027
|
+
}
|
|
4028
|
+
}
|
|
3791
4029
|
})()
|
|
3792
4030
|
};
|
|
3793
4031
|
delete chunk.getData;
|
|
@@ -3812,6 +4050,7 @@
|
|
|
3812
4050
|
const zipEntry = this;
|
|
3813
4051
|
const {
|
|
3814
4052
|
reader,
|
|
4053
|
+
index,
|
|
3815
4054
|
offset,
|
|
3816
4055
|
diskNumberStart,
|
|
3817
4056
|
extraFieldAES,
|
|
@@ -3837,27 +4076,42 @@
|
|
|
3837
4076
|
rawPassword = rawPassword && rawPassword.length && rawPassword;
|
|
3838
4077
|
if (extraFieldAES) {
|
|
3839
4078
|
if (extraFieldAES.originalCompressionMethod != COMPRESSION_METHOD_AES) {
|
|
3840
|
-
throw new Error(ERR_UNSUPPORTED_COMPRESSION);
|
|
4079
|
+
throw new Error(ERR_UNSUPPORTED_COMPRESSION$1);
|
|
3841
4080
|
}
|
|
3842
4081
|
}
|
|
3843
4082
|
if ((compressionMethod != COMPRESSION_METHOD_STORE && compressionMethod != COMPRESSION_METHOD_DEFLATE && compressionMethod != COMPRESSION_METHOD_DEFLATE_64) && !passThrough) {
|
|
3844
|
-
throw new Error(ERR_UNSUPPORTED_COMPRESSION);
|
|
4083
|
+
throw new Error(ERR_UNSUPPORTED_COMPRESSION$1);
|
|
3845
4084
|
}
|
|
3846
|
-
if (getUint32(dataView, 0) != LOCAL_FILE_HEADER_SIGNATURE) {
|
|
4085
|
+
if (dataArray.length < HEADER_SIZE || getUint32(dataView, 0) != LOCAL_FILE_HEADER_SIGNATURE) {
|
|
3847
4086
|
throw new Error(ERR_LOCAL_FILE_HEADER_NOT_FOUND);
|
|
3848
4087
|
}
|
|
3849
4088
|
readCommonHeader(localDirectory, dataView, 4);
|
|
3850
4089
|
const {
|
|
3851
4090
|
extraFieldLength,
|
|
3852
|
-
filenameLength
|
|
3853
|
-
lastAccessDate,
|
|
3854
|
-
creationDate
|
|
4091
|
+
filenameLength
|
|
3855
4092
|
} = localDirectory;
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
4093
|
+
const checkAmbiguity = getOptionValue$1(zipEntry, options, OPTION_CHECK_AMBIGUITY);
|
|
4094
|
+
let rawLocalFilename = new Uint8Array();
|
|
4095
|
+
if (checkAmbiguity && (filenameLength || extraFieldLength)) {
|
|
4096
|
+
const trailingDataArray = await readUint8Array(reader, offset + HEADER_SIZE, filenameLength + extraFieldLength, diskNumberStart);
|
|
4097
|
+
rawLocalFilename = trailingDataArray.subarray(0, filenameLength);
|
|
4098
|
+
localDirectory.rawExtraField = trailingDataArray.subarray(filenameLength);
|
|
4099
|
+
} else {
|
|
4100
|
+
localDirectory.rawExtraField = extraFieldLength ?
|
|
4101
|
+
await readUint8Array(reader, offset + HEADER_SIZE + filenameLength, extraFieldLength, diskNumberStart) :
|
|
4102
|
+
new Uint8Array();
|
|
4103
|
+
}
|
|
3859
4104
|
readCommonFooter(zipEntry, localDirectory, dataView, 4, true);
|
|
3860
|
-
|
|
4105
|
+
if (checkAmbiguity) {
|
|
4106
|
+
checkLocalDirectory(zipEntry, localDirectory, rawLocalFilename);
|
|
4107
|
+
}
|
|
4108
|
+
const { lastAccessDate, creationDate } = localDirectory;
|
|
4109
|
+
if (lastAccessDate) {
|
|
4110
|
+
fileEntry.lastAccessDate = lastAccessDate;
|
|
4111
|
+
}
|
|
4112
|
+
if (creationDate) {
|
|
4113
|
+
fileEntry.creationDate = creationDate;
|
|
4114
|
+
}
|
|
3861
4115
|
const encrypted = zipEntry.encrypted && localDirectory.encrypted && !passThrough;
|
|
3862
4116
|
const zipCrypto = encrypted && !extraFieldAES;
|
|
3863
4117
|
if (!passThrough) {
|
|
@@ -3903,7 +4157,7 @@
|
|
|
3903
4157
|
outputSize: passThrough ? compressedSize : uncompressedSize,
|
|
3904
4158
|
signature,
|
|
3905
4159
|
compressed: compressionMethod != 0 && !passThrough,
|
|
3906
|
-
encrypted
|
|
4160
|
+
encrypted,
|
|
3907
4161
|
useWebWorkers: getOptionValue$1(zipEntry, options, OPTION_USE_WEB_WORKERS),
|
|
3908
4162
|
useCompressionStream,
|
|
3909
4163
|
transferStreams: getOptionValue$1(zipEntry, options, OPTION_TRANSFER_STREAMS),
|
|
@@ -3917,6 +4171,7 @@
|
|
|
3917
4171
|
await detectOverlappingEntry({
|
|
3918
4172
|
reader,
|
|
3919
4173
|
fileEntry,
|
|
4174
|
+
index,
|
|
3920
4175
|
offset,
|
|
3921
4176
|
diskNumberStart,
|
|
3922
4177
|
signature,
|
|
@@ -4019,7 +4274,7 @@
|
|
|
4019
4274
|
directory.extraFieldUnicodeComment = extraFieldUnicodeComment;
|
|
4020
4275
|
}
|
|
4021
4276
|
const extraFieldAES = extraField.get(EXTRAFIELD_TYPE_AES);
|
|
4022
|
-
if (extraFieldAES) {
|
|
4277
|
+
if (extraFieldAES && extraFieldAES.data.length >= 7) {
|
|
4023
4278
|
readExtraFieldAES(extraFieldAES, directory, compressionMethod);
|
|
4024
4279
|
directory.extraFieldAES = extraFieldAES;
|
|
4025
4280
|
} else {
|
|
@@ -4056,19 +4311,23 @@
|
|
|
4056
4311
|
directory.zip64 = true;
|
|
4057
4312
|
const extraFieldView = getDataView$1(extraFieldZip64.data);
|
|
4058
4313
|
const missingProperties = ZIP64_PROPERTIES.filter(([propertyName, max]) => directory[propertyName] == max);
|
|
4314
|
+
const requiredLength = missingProperties.reduce((length, [, max]) => length + ZIP64_EXTRACTION[max].bytes, 0);
|
|
4315
|
+
if (extraFieldZip64.data.length < requiredLength) {
|
|
4316
|
+
throw new Error(ERR_EXTRAFIELD_ZIP64_NOT_FOUND);
|
|
4317
|
+
}
|
|
4059
4318
|
for (let indexMissingProperty = 0, offset = 0; indexMissingProperty < missingProperties.length; indexMissingProperty++) {
|
|
4060
4319
|
const [propertyName, max] = missingProperties[indexMissingProperty];
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
offset += extraction.bytes;
|
|
4065
|
-
} else if (extraFieldZip64[propertyName]) {
|
|
4066
|
-
throw new Error(ERR_EXTRAFIELD_ZIP64_NOT_FOUND);
|
|
4067
|
-
}
|
|
4320
|
+
const extraction = ZIP64_EXTRACTION[max];
|
|
4321
|
+
directory[propertyName] = extraFieldZip64[propertyName] = extraction.getValue(extraFieldView, offset);
|
|
4322
|
+
offset += extraction.bytes;
|
|
4068
4323
|
}
|
|
4069
4324
|
}
|
|
4070
4325
|
|
|
4071
4326
|
function readExtraFieldUnicode(extraFieldUnicode, propertyName, rawPropertyName, directory, fileEntry) {
|
|
4327
|
+
if (extraFieldUnicode.data.length < 5) {
|
|
4328
|
+
extraFieldUnicode.valid = false;
|
|
4329
|
+
return;
|
|
4330
|
+
}
|
|
4072
4331
|
const extraFieldView = getDataView$1(extraFieldUnicode.data);
|
|
4073
4332
|
const crc32 = new Crc32();
|
|
4074
4333
|
crc32.append(fileEntry[rawPropertyName]);
|
|
@@ -4141,32 +4400,30 @@
|
|
|
4141
4400
|
function readExtraFieldUnix(extraField, directory, isInfoZip) {
|
|
4142
4401
|
try {
|
|
4143
4402
|
const view = getDataView$1(new Uint8Array(extraField.data));
|
|
4144
|
-
let
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
if (
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4403
|
+
let uid, gid;
|
|
4404
|
+
if (isInfoZip) {
|
|
4405
|
+
// Info-ZIP New Unix "ux" field (0x7875): version + variable-length uid/gid
|
|
4406
|
+
let offset = 0;
|
|
4407
|
+
const version = getUint8(view, offset++);
|
|
4408
|
+
const uidSize = getUint8(view, offset++);
|
|
4409
|
+
uid = unpackUnixId(extraField.data.subarray(offset, offset + uidSize));
|
|
4410
|
+
offset += uidSize;
|
|
4411
|
+
const gidSize = getUint8(view, offset++);
|
|
4412
|
+
gid = unpackUnixId(extraField.data.subarray(offset, offset + gidSize));
|
|
4413
|
+
Object.assign(extraField, { version, uid, gid });
|
|
4414
|
+
} else if (extraField.data.length >= 4) {
|
|
4415
|
+
// Info-ZIP Unix "Ux" field (0x7855): fixed 2-byte uid + gid (the file mode, if any, is
|
|
4416
|
+
// carried in the external file attributes, not here)
|
|
4417
|
+
uid = getUint16(view, 0);
|
|
4418
|
+
gid = getUint16(view, 2);
|
|
4419
|
+
Object.assign(extraField, { uid, gid });
|
|
4420
|
+
}
|
|
4161
4421
|
if (uid !== UNDEFINED_VALUE) {
|
|
4162
4422
|
directory.uid = uid;
|
|
4163
4423
|
}
|
|
4164
4424
|
if (gid !== UNDEFINED_VALUE) {
|
|
4165
4425
|
directory.gid = gid;
|
|
4166
4426
|
}
|
|
4167
|
-
if (unixMode !== UNDEFINED_VALUE) {
|
|
4168
|
-
directory.unixMode = unixMode;
|
|
4169
|
-
}
|
|
4170
4427
|
} catch {
|
|
4171
4428
|
// ignored
|
|
4172
4429
|
}
|
|
@@ -4180,6 +4437,9 @@
|
|
|
4180
4437
|
}
|
|
4181
4438
|
|
|
4182
4439
|
function readExtraFieldExtendedTimestamp(extraFieldExtendedTimestamp, directory, localDirectory) {
|
|
4440
|
+
if (!extraFieldExtendedTimestamp.data.length) {
|
|
4441
|
+
return;
|
|
4442
|
+
}
|
|
4183
4443
|
const extraFieldView = getDataView$1(extraFieldExtendedTimestamp.data);
|
|
4184
4444
|
const flags = getUint8(extraFieldView, 0);
|
|
4185
4445
|
const timeProperties = [];
|
|
@@ -4205,7 +4465,8 @@
|
|
|
4205
4465
|
timeProperties.forEach((propertyName, indexProperty) => {
|
|
4206
4466
|
if (extraFieldExtendedTimestamp.data.length >= offset + 4) {
|
|
4207
4467
|
const time = getUint32(extraFieldView, offset);
|
|
4208
|
-
|
|
4468
|
+
// the extended timestamp is a signed 32-bit time_t value
|
|
4469
|
+
directory[propertyName] = extraFieldExtendedTimestamp[propertyName] = new Date((time | 0) * 1000);
|
|
4209
4470
|
const rawPropertyName = timeRawProperties[indexProperty];
|
|
4210
4471
|
extraFieldExtendedTimestamp[rawPropertyName] = time;
|
|
4211
4472
|
}
|
|
@@ -4216,6 +4477,7 @@
|
|
|
4216
4477
|
async function detectOverlappingEntry({
|
|
4217
4478
|
reader,
|
|
4218
4479
|
fileEntry,
|
|
4480
|
+
index,
|
|
4219
4481
|
offset,
|
|
4220
4482
|
diskNumberStart,
|
|
4221
4483
|
signature,
|
|
@@ -4227,10 +4489,9 @@
|
|
|
4227
4489
|
readRanges
|
|
4228
4490
|
}) {
|
|
4229
4491
|
let diskOffset = 0;
|
|
4230
|
-
if (diskNumberStart) {
|
|
4231
|
-
for (let indexReader = 0; indexReader < diskNumberStart; indexReader++) {
|
|
4232
|
-
|
|
4233
|
-
diskOffset += diskReader.size;
|
|
4492
|
+
if (diskNumberStart && reader.readers) {
|
|
4493
|
+
for (let indexReader = 0; indexReader < Math.min(diskNumberStart, reader.readers.length); indexReader++) {
|
|
4494
|
+
diskOffset += reader.readers[indexReader].size;
|
|
4234
4495
|
}
|
|
4235
4496
|
}
|
|
4236
4497
|
let dataDescriptorLength = 0;
|
|
@@ -4243,7 +4504,8 @@
|
|
|
4243
4504
|
}
|
|
4244
4505
|
if (dataDescriptorLength) {
|
|
4245
4506
|
const dataDescriptorArray = await readUint8Array(reader, dataOffset + compressedSize, dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH, diskNumberStart);
|
|
4246
|
-
const dataDescriptorSignature =
|
|
4507
|
+
const dataDescriptorSignature = dataDescriptorArray.length == dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH &&
|
|
4508
|
+
getUint32(getDataView$1(dataDescriptorArray), 0) == DATA_DESCRIPTOR_RECORD_SIGNATURE;
|
|
4247
4509
|
if (dataDescriptorSignature) {
|
|
4248
4510
|
const readSignature = getUint32(getDataView$1(dataDescriptorArray), 4);
|
|
4249
4511
|
let readCompressedSize;
|
|
@@ -4268,14 +4530,14 @@
|
|
|
4268
4530
|
end: diskOffset + dataOffset + compressedSize + dataDescriptorLength,
|
|
4269
4531
|
fileEntry
|
|
4270
4532
|
};
|
|
4271
|
-
for (const otherRange of readRanges) {
|
|
4272
|
-
if (
|
|
4533
|
+
for (const [otherIndex, otherRange] of readRanges) {
|
|
4534
|
+
if (otherIndex != index && range.start < otherRange.end && otherRange.start < range.end) {
|
|
4273
4535
|
const error = new Error(ERR_OVERLAPPING_ENTRY);
|
|
4274
4536
|
error.overlappingEntry = otherRange.fileEntry;
|
|
4275
4537
|
throw error;
|
|
4276
4538
|
}
|
|
4277
4539
|
}
|
|
4278
|
-
readRanges.
|
|
4540
|
+
readRanges.set(index, range);
|
|
4279
4541
|
}
|
|
4280
4542
|
|
|
4281
4543
|
async function seekSignature(reader, signature, startOffset, minimumBytes, maximumLength) {
|
|
@@ -4300,6 +4562,35 @@
|
|
|
4300
4562
|
}
|
|
4301
4563
|
}
|
|
4302
4564
|
|
|
4565
|
+
function checkLocalDirectory(zipEntry, localDirectory, rawLocalFilename) {
|
|
4566
|
+
const { rawFilename } = zipEntry;
|
|
4567
|
+
if (rawLocalFilename.length != rawFilename.length ||
|
|
4568
|
+
rawLocalFilename.some((byteValue, indexByte) => byteValue != rawFilename[indexByte])) {
|
|
4569
|
+
throwAmbiguousArchive("mismatched local file header (filename)");
|
|
4570
|
+
}
|
|
4571
|
+
if ((localDirectory.rawBitFlag & BITFLAG_AMBIGUITY_MASK) != (zipEntry.rawBitFlag & BITFLAG_AMBIGUITY_MASK)) {
|
|
4572
|
+
throwAmbiguousArchive("mismatched local file header (general purpose bit flag)");
|
|
4573
|
+
}
|
|
4574
|
+
if (localDirectory.compressionMethod != zipEntry.compressionMethod) {
|
|
4575
|
+
throwAmbiguousArchive("mismatched local file header (compression method)");
|
|
4576
|
+
}
|
|
4577
|
+
// when the data descriptor flag is set, the local signature and sizes are zeroed out; all-zero values are
|
|
4578
|
+
// also tolerated when the flag is clear because some tools produce them (streaming writers predating bit 3)
|
|
4579
|
+
if (!localDirectory.bitFlag.dataDescriptor &&
|
|
4580
|
+
(localDirectory.signature || localDirectory.compressedSize || localDirectory.uncompressedSize) &&
|
|
4581
|
+
(localDirectory.signature != zipEntry.signature ||
|
|
4582
|
+
localDirectory.compressedSize != zipEntry.compressedSize ||
|
|
4583
|
+
localDirectory.uncompressedSize != zipEntry.uncompressedSize)) {
|
|
4584
|
+
throwAmbiguousArchive("mismatched local file header (signature or sizes)");
|
|
4585
|
+
}
|
|
4586
|
+
}
|
|
4587
|
+
|
|
4588
|
+
function throwAmbiguousArchive(reason) {
|
|
4589
|
+
const error = new Error(ERR_AMBIGUOUS_ARCHIVE);
|
|
4590
|
+
error.reason = reason;
|
|
4591
|
+
throw error;
|
|
4592
|
+
}
|
|
4593
|
+
|
|
4303
4594
|
function getOptionValue$1(zipReader, options, name) {
|
|
4304
4595
|
return options[name] === UNDEFINED_VALUE ? zipReader.options[name] : options[name];
|
|
4305
4596
|
}
|
|
@@ -4338,7 +4629,7 @@
|
|
|
4338
4629
|
}
|
|
4339
4630
|
|
|
4340
4631
|
function getDataView$1(array) {
|
|
4341
|
-
return new DataView(array.buffer);
|
|
4632
|
+
return new DataView(array.buffer, array.byteOffset, array.byteLength);
|
|
4342
4633
|
}
|
|
4343
4634
|
|
|
4344
4635
|
/*
|
|
@@ -4378,13 +4669,19 @@
|
|
|
4378
4669
|
const ERR_INVALID_ENCRYPTION_STRENGTH = "The strength must equal 1, 2, or 3";
|
|
4379
4670
|
const ERR_INVALID_EXTRAFIELD_TYPE = "Extra field type exceeds 65535";
|
|
4380
4671
|
const ERR_INVALID_EXTRAFIELD_DATA = "Extra field data exceeds 64KB";
|
|
4672
|
+
// same message as the constant exported by zip-reader.js
|
|
4673
|
+
const ERR_UNSUPPORTED_COMPRESSION = "Compression method not supported";
|
|
4674
|
+
const MIN_UNIX_TIME = -2147483648;
|
|
4675
|
+
const MAX_UNIX_TIME = 2147483647;
|
|
4381
4676
|
const ERR_UNSUPPORTED_FORMAT = "Zip64 is not supported (set the 'zip64' option to 'true')";
|
|
4382
4677
|
const ERR_UNDEFINED_UNCOMPRESSED_SIZE = "Undefined uncompressed size";
|
|
4678
|
+
const ERR_UNDEFINED_READER = "Undefined reader";
|
|
4383
4679
|
const ERR_ZIP_NOT_EMPTY = "Zip file not empty";
|
|
4384
4680
|
const ERR_INVALID_UID = "Invalid uid (must be integer 0..2^32-1)";
|
|
4385
4681
|
const ERR_INVALID_GID = "Invalid gid (must be integer 0..2^32-1)";
|
|
4386
4682
|
const ERR_INVALID_UNIX_MODE = "Invalid UNIX mode (must be integer 0..65535)";
|
|
4387
4683
|
const ERR_INVALID_UNIX_EXTRA_FIELD_TYPE = "Invalid unixExtraFieldType (must be 'infozip' or 'unix')";
|
|
4684
|
+
const ERR_INVALID_UNIX_ID_SIZE = "uid/gid must be 0..65535 for unixExtraFieldType 'unix' (use 'infozip' for larger ids)";
|
|
4388
4685
|
const ERR_INVALID_MSDOS_ATTRIBUTES = "Invalid msdosAttributesRaw (must be integer 0..255)";
|
|
4389
4686
|
const ERR_INVALID_MSDOS_DATA = "Invalid msdosAttributes (must be an object with boolean flags)";
|
|
4390
4687
|
|
|
@@ -4410,9 +4707,10 @@
|
|
|
4410
4707
|
files: new Map(),
|
|
4411
4708
|
filenames: new Set(),
|
|
4412
4709
|
offset: options[OPTION_OFFSET] === UNDEFINED_VALUE ? writer.size || writer.writable.size || 0 : options[OPTION_OFFSET],
|
|
4413
|
-
|
|
4710
|
+
initialOffset: options[OPTION_OFFSET] === UNDEFINED_VALUE ? 0 : options[OPTION_OFFSET] - (writer.size || writer.writable.size || 0),
|
|
4414
4711
|
pendingAddFileCalls: new Set(),
|
|
4415
|
-
bufferedWrites: 0
|
|
4712
|
+
bufferedWrites: 0,
|
|
4713
|
+
lastFileEntry: UNDEFINED_VALUE
|
|
4416
4714
|
});
|
|
4417
4715
|
}
|
|
4418
4716
|
|
|
@@ -4421,17 +4719,18 @@
|
|
|
4421
4719
|
throw new Error(ERR_ZIP_NOT_EMPTY);
|
|
4422
4720
|
}
|
|
4423
4721
|
reader = new GenericReader(reader);
|
|
4722
|
+
await initStream(reader);
|
|
4424
4723
|
const zipReader = new ZipReader(reader.readable);
|
|
4425
4724
|
const entries = await zipReader.getEntries();
|
|
4426
4725
|
await zipReader.close();
|
|
4726
|
+
await initStream(this.writer);
|
|
4427
4727
|
await reader.readable.pipeTo(this.writer.writable, { preventClose: true, preventAbort: true });
|
|
4428
4728
|
this.writer.size = this.offset = reader.size;
|
|
4429
4729
|
this.filenames = new Set(entries.map(entry => entry.filename));
|
|
4430
4730
|
this.files = new Map(entries.map(entry => {
|
|
4431
4731
|
const {
|
|
4432
4732
|
version,
|
|
4433
|
-
|
|
4434
|
-
lastModDate,
|
|
4733
|
+
rawLastModDate,
|
|
4435
4734
|
lastAccessDate,
|
|
4436
4735
|
creationDate,
|
|
4437
4736
|
rawFilename,
|
|
@@ -4444,6 +4743,7 @@
|
|
|
4444
4743
|
zip64
|
|
4445
4744
|
} = entry;
|
|
4446
4745
|
let {
|
|
4746
|
+
compressionMethod,
|
|
4447
4747
|
rawExtraFieldZip64,
|
|
4448
4748
|
rawExtraFieldAES,
|
|
4449
4749
|
rawExtraFieldExtendedTimestamp,
|
|
@@ -4456,31 +4756,39 @@
|
|
|
4456
4756
|
rawExtraFieldAES = rawExtraFieldAES || new Uint8Array();
|
|
4457
4757
|
rawExtraFieldExtendedTimestamp = rawExtraFieldExtendedTimestamp || new Uint8Array();
|
|
4458
4758
|
rawExtraFieldNTFS = rawExtraFieldNTFS || new Uint8Array();
|
|
4459
|
-
rawExtraFieldUnix =
|
|
4759
|
+
rawExtraFieldUnix = rawExtraFieldUnix || new Uint8Array();
|
|
4460
4760
|
rawExtraField = rawExtraField || new Uint8Array();
|
|
4761
|
+
if (entry.extraFieldAES) {
|
|
4762
|
+
compressionMethod = COMPRESSION_METHOD_AES;
|
|
4763
|
+
}
|
|
4461
4764
|
const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField);
|
|
4462
|
-
const zip64UncompressedSize = zip64 && uncompressedSize
|
|
4463
|
-
const zip64CompressedSize = zip64 && compressedSize
|
|
4765
|
+
const zip64UncompressedSize = zip64 && uncompressedSize >= MAX_32_BITS;
|
|
4766
|
+
const zip64CompressedSize = zip64 && compressedSize >= MAX_32_BITS;
|
|
4767
|
+
const bitFlagValue = (getBitFlag(level, languageEncodingFlag, dataDescriptor, encrypted, compressionMethod) & ~BITFLAG_LEVEL) | (level << 1);
|
|
4464
4768
|
const {
|
|
4465
4769
|
headerArray,
|
|
4466
4770
|
headerView
|
|
4467
4771
|
} = getHeaderArrayData({
|
|
4468
4772
|
version,
|
|
4469
|
-
bitFlag:
|
|
4773
|
+
bitFlag: bitFlagValue,
|
|
4470
4774
|
compressionMethod,
|
|
4471
4775
|
uncompressedSize,
|
|
4472
4776
|
compressedSize,
|
|
4473
|
-
|
|
4777
|
+
rawLastModDate,
|
|
4474
4778
|
rawFilename,
|
|
4475
4779
|
zip64CompressedSize,
|
|
4476
4780
|
zip64UncompressedSize,
|
|
4477
4781
|
extraFieldLength
|
|
4478
4782
|
});
|
|
4783
|
+
const { signature } = entry;
|
|
4784
|
+
if (signature !== UNDEFINED_VALUE) {
|
|
4785
|
+
setUint32(headerView, HEADER_OFFSET_SIGNATURE, signature);
|
|
4786
|
+
}
|
|
4479
4787
|
Object.assign(entry, {
|
|
4480
4788
|
zip64UncompressedSize,
|
|
4481
4789
|
zip64CompressedSize,
|
|
4482
|
-
zip64Offset: zip64 && this.offset - diskOffset
|
|
4483
|
-
zip64DiskNumberStart: zip64 && diskNumber
|
|
4790
|
+
zip64Offset: zip64 && this.offset - diskOffset >= MAX_32_BITS,
|
|
4791
|
+
zip64DiskNumberStart: zip64 && diskNumber >= MAX_16_BITS,
|
|
4484
4792
|
rawExtraFieldZip64,
|
|
4485
4793
|
rawExtraFieldAES,
|
|
4486
4794
|
rawExtraFieldExtendedTimestamp,
|
|
@@ -4498,6 +4806,7 @@
|
|
|
4498
4806
|
|
|
4499
4807
|
async add(name = "", reader, options = {}) {
|
|
4500
4808
|
const zipWriter = this;
|
|
4809
|
+
options = Object.assign({}, options);
|
|
4501
4810
|
const {
|
|
4502
4811
|
pendingAddFileCalls,
|
|
4503
4812
|
config
|
|
@@ -4508,17 +4817,24 @@
|
|
|
4508
4817
|
await new Promise(resolve => pendingEntries.push(resolve));
|
|
4509
4818
|
}
|
|
4510
4819
|
let promiseAddFile;
|
|
4820
|
+
let nameAdded;
|
|
4511
4821
|
try {
|
|
4512
4822
|
name = name.trim();
|
|
4823
|
+
if (getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY) && !name.endsWith(DIRECTORY_SIGNATURE)) {
|
|
4824
|
+
name += DIRECTORY_SIGNATURE;
|
|
4825
|
+
}
|
|
4513
4826
|
if (zipWriter.filenames.has(name)) {
|
|
4514
4827
|
throw new Error(ERR_DUPLICATED_NAME);
|
|
4515
4828
|
}
|
|
4516
4829
|
zipWriter.filenames.add(name);
|
|
4830
|
+
nameAdded = true;
|
|
4517
4831
|
promiseAddFile = addFile(zipWriter, name, reader, options);
|
|
4518
4832
|
pendingAddFileCalls.add(promiseAddFile);
|
|
4519
4833
|
return await promiseAddFile;
|
|
4520
4834
|
} catch (error) {
|
|
4521
|
-
|
|
4835
|
+
if (nameAdded) {
|
|
4836
|
+
zipWriter.filenames.delete(name);
|
|
4837
|
+
}
|
|
4522
4838
|
throw error;
|
|
4523
4839
|
} finally {
|
|
4524
4840
|
pendingAddFileCalls.delete(promiseAddFile);
|
|
@@ -4551,6 +4867,9 @@
|
|
|
4551
4867
|
const zipWriter = this;
|
|
4552
4868
|
const { pendingAddFileCalls, writer } = this;
|
|
4553
4869
|
const { writable } = writer;
|
|
4870
|
+
if (getLength(comment) > MAX_16_BITS) {
|
|
4871
|
+
throw new Error(ERR_INVALID_COMMENT);
|
|
4872
|
+
}
|
|
4554
4873
|
while (pendingAddFileCalls.size) {
|
|
4555
4874
|
await Promise.allSettled(Array.from(pendingAddFileCalls));
|
|
4556
4875
|
}
|
|
@@ -4569,28 +4888,94 @@
|
|
|
4569
4888
|
const { readable, writable } = new TransformStream();
|
|
4570
4889
|
this.readable = readable;
|
|
4571
4890
|
this.zipWriter = new ZipWriter(writable, options);
|
|
4891
|
+
this.pendingAddFileCalls = new Set();
|
|
4572
4892
|
}
|
|
4573
4893
|
|
|
4574
4894
|
transform(path) {
|
|
4895
|
+
const zipWriter = this.zipWriter;
|
|
4896
|
+
let streamController;
|
|
4575
4897
|
const { readable, writable } = new TransformStream({
|
|
4576
|
-
|
|
4898
|
+
start(controller) {
|
|
4899
|
+
streamController = controller;
|
|
4900
|
+
},
|
|
4901
|
+
flush: () => void closeArchive()
|
|
4577
4902
|
});
|
|
4578
|
-
this.zipWriter.add(path, readable);
|
|
4903
|
+
watchAddFileCall(this, this.zipWriter.add(path, readable), error => streamController.error(error));
|
|
4579
4904
|
return { readable: this.readable, writable };
|
|
4905
|
+
|
|
4906
|
+
async function closeArchive() {
|
|
4907
|
+
try {
|
|
4908
|
+
await zipWriter.close();
|
|
4909
|
+
} catch (error) {
|
|
4910
|
+
try {
|
|
4911
|
+
await zipWriter.writer.writable.abort(error);
|
|
4912
|
+
} catch {
|
|
4913
|
+
// ignored
|
|
4914
|
+
}
|
|
4915
|
+
}
|
|
4916
|
+
}
|
|
4580
4917
|
}
|
|
4581
4918
|
|
|
4582
4919
|
writable(path) {
|
|
4583
|
-
|
|
4584
|
-
|
|
4920
|
+
let streamController;
|
|
4921
|
+
const { readable, writable } = new TransformStream({
|
|
4922
|
+
start(controller) {
|
|
4923
|
+
streamController = controller;
|
|
4924
|
+
}
|
|
4925
|
+
});
|
|
4926
|
+
watchAddFileCall(this, this.zipWriter.add(path, readable), error => streamController.error(error));
|
|
4585
4927
|
return writable;
|
|
4586
4928
|
}
|
|
4587
4929
|
|
|
4588
|
-
close(comment = UNDEFINED_VALUE, options = {}) {
|
|
4930
|
+
async close(comment = UNDEFINED_VALUE, options = {}) {
|
|
4931
|
+
await Promise.all(Array.from(this.pendingAddFileCalls));
|
|
4589
4932
|
return this.zipWriter.close(comment, options);
|
|
4590
4933
|
}
|
|
4591
4934
|
}
|
|
4592
4935
|
|
|
4936
|
+
function watchAddFileCall(zipWriterStream, promiseAddFile, onerror) {
|
|
4937
|
+
zipWriterStream.pendingAddFileCalls.add(promiseAddFile);
|
|
4938
|
+
promiseAddFile.catch(error => {
|
|
4939
|
+
try {
|
|
4940
|
+
onerror(error);
|
|
4941
|
+
} catch {
|
|
4942
|
+
// ignored
|
|
4943
|
+
}
|
|
4944
|
+
});
|
|
4945
|
+
}
|
|
4946
|
+
|
|
4593
4947
|
async function addFile(zipWriter, name, reader, options) {
|
|
4948
|
+
const attributesInfo = resolveAttributes(zipWriter, name, options);
|
|
4949
|
+
({ name } = attributesInfo);
|
|
4950
|
+
const metadataInfo = resolveMetadata(zipWriter, name, options);
|
|
4951
|
+
const { comment } = metadataInfo;
|
|
4952
|
+
const extraField = options[PROPERTY_NAME_EXTRA_FIELD];
|
|
4953
|
+
zipWriter.files.set(name, UNDEFINED_VALUE);
|
|
4954
|
+
let fileEntry;
|
|
4955
|
+
try {
|
|
4956
|
+
const sizesInfo = await resolveSizes(zipWriter, reader, metadataInfo, options);
|
|
4957
|
+
({ reader } = sizesInfo);
|
|
4958
|
+
const { diskOffset, diskNumber } = zipWriter.writer;
|
|
4959
|
+
options = Object.assign({}, options, attributesInfo.resolvedOptions, metadataInfo.resolvedOptions, sizesInfo.resolvedOptions, {
|
|
4960
|
+
internalFileAttribute: metadataInfo.resolvedOptions.internalFileAttributes,
|
|
4961
|
+
externalFileAttribute: attributesInfo.resolvedOptions.externalFileAttributes,
|
|
4962
|
+
signature: options[PROPERTY_NAME_SIGNATURE],
|
|
4963
|
+
offset: zipWriter.offset - diskOffset,
|
|
4964
|
+
diskNumberStart: diskNumber
|
|
4965
|
+
});
|
|
4966
|
+
const headerInfo = getHeaderInfo(options);
|
|
4967
|
+
const dataDescriptorInfo = getDataDescriptorInfo(options);
|
|
4968
|
+
const metadataSize = getLength(headerInfo.localHeaderArray, dataDescriptorInfo.dataDescriptorArray);
|
|
4969
|
+
fileEntry = await getFileEntry(zipWriter, name, reader, { headerInfo, dataDescriptorInfo, metadataSize }, options);
|
|
4970
|
+
} catch (error) {
|
|
4971
|
+
zipWriter.files.delete(name);
|
|
4972
|
+
throw error;
|
|
4973
|
+
}
|
|
4974
|
+
Object.assign(fileEntry, { name, comment, extraField });
|
|
4975
|
+
return new Entry(fileEntry);
|
|
4976
|
+
}
|
|
4977
|
+
|
|
4978
|
+
function resolveAttributes(zipWriter, name, options) {
|
|
4594
4979
|
name = name.trim();
|
|
4595
4980
|
let msDosCompatible = getOptionValue(zipWriter, options, PROPERTY_NAME_MS_DOS_COMPATIBLE);
|
|
4596
4981
|
let versionMadeBy = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION_MADE_BY, msDosCompatible ? 20 : 768);
|
|
@@ -4598,7 +4983,7 @@
|
|
|
4598
4983
|
const uid = getOptionValue(zipWriter, options, PROPERTY_NAME_UID);
|
|
4599
4984
|
const gid = getOptionValue(zipWriter, options, PROPERTY_NAME_GID);
|
|
4600
4985
|
let unixMode = getOptionValue(zipWriter, options, PROPERTY_NAME_UNIX_MODE);
|
|
4601
|
-
|
|
4986
|
+
let unixExtraFieldType = getOptionValue(zipWriter, options, OPTION_UNIX_EXTRA_FIELD_TYPE);
|
|
4602
4987
|
let setuid = getOptionValue(zipWriter, options, PROPERTY_NAME_SETUID);
|
|
4603
4988
|
let setgid = getOptionValue(zipWriter, options, PROPERTY_NAME_SETGID);
|
|
4604
4989
|
let sticky = getOptionValue(zipWriter, options, PROPERTY_NAME_STICKY);
|
|
@@ -4614,6 +4999,13 @@
|
|
|
4614
4999
|
if (unixExtraFieldType !== UNDEFINED_VALUE && unixExtraFieldType !== INFOZIP_EXTRA_FIELD_TYPE && unixExtraFieldType !== UNIX_EXTRA_FIELD_TYPE) {
|
|
4615
5000
|
throw new Error(ERR_INVALID_UNIX_EXTRA_FIELD_TYPE);
|
|
4616
5001
|
}
|
|
5002
|
+
if (unixExtraFieldType === UNIX_EXTRA_FIELD_TYPE &&
|
|
5003
|
+
((uid !== UNDEFINED_VALUE && uid > MAX_16_BITS) || (gid !== UNDEFINED_VALUE && gid > MAX_16_BITS))) {
|
|
5004
|
+
throw new Error(ERR_INVALID_UNIX_ID_SIZE);
|
|
5005
|
+
}
|
|
5006
|
+
if (unixExtraFieldType === UNDEFINED_VALUE && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
|
|
5007
|
+
unixExtraFieldType = INFOZIP_EXTRA_FIELD_TYPE;
|
|
5008
|
+
}
|
|
4617
5009
|
let msdosAttributesRaw = getOptionValue(zipWriter, options, PROPERTY_NAME_MSDOS_ATTRIBUTES_RAW);
|
|
4618
5010
|
let msdosAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_MSDOS_ATTRIBUTES);
|
|
4619
5011
|
const hasUnixMetadata = uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE || unixMode !== UNDEFINED_VALUE || unixExtraFieldType;
|
|
@@ -4684,6 +5076,27 @@
|
|
|
4684
5076
|
if (hasMsDosProvided) {
|
|
4685
5077
|
externalFileAttributes = (externalFileAttributes & MAX_32_BITS) | (msdosAttributesRaw & MAX_8_BITS);
|
|
4686
5078
|
}
|
|
5079
|
+
return {
|
|
5080
|
+
name,
|
|
5081
|
+
resolvedOptions: {
|
|
5082
|
+
versionMadeBy,
|
|
5083
|
+
msDosCompatible,
|
|
5084
|
+
externalFileAttributes,
|
|
5085
|
+
unixExternalUpper,
|
|
5086
|
+
uid,
|
|
5087
|
+
gid,
|
|
5088
|
+
unixMode,
|
|
5089
|
+
unixExtraFieldType,
|
|
5090
|
+
setuid,
|
|
5091
|
+
setgid,
|
|
5092
|
+
sticky,
|
|
5093
|
+
msdosAttributesRaw,
|
|
5094
|
+
msdosAttributes
|
|
5095
|
+
}
|
|
5096
|
+
};
|
|
5097
|
+
}
|
|
5098
|
+
|
|
5099
|
+
function resolveMetadata(zipWriter, name, options) {
|
|
4687
5100
|
const encode = getOptionValue(zipWriter, options, OPTION_ENCODE_TEXT, encodeText);
|
|
4688
5101
|
let rawFilename = encode(name);
|
|
4689
5102
|
if (rawFilename === UNDEFINED_VALUE) {
|
|
@@ -4722,10 +5135,14 @@
|
|
|
4722
5135
|
const transferStreams = getOptionValue(zipWriter, options, OPTION_TRANSFER_STREAMS, true);
|
|
4723
5136
|
const bufferedWrite = getOptionValue(zipWriter, options, OPTION_BUFFERED_WRITE);
|
|
4724
5137
|
const createTempStream = getOptionValue(zipWriter, options, OPTION_CREATE_TEMP_STREAM);
|
|
4725
|
-
const dataDescriptorSignature = getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR_SIGNATURE,
|
|
5138
|
+
const dataDescriptorSignature = getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR_SIGNATURE, true);
|
|
4726
5139
|
const signal = getOptionValue(zipWriter, options, OPTION_SIGNAL);
|
|
4727
5140
|
const useUnicodeFileNames = getOptionValue(zipWriter, options, OPTION_USE_UNICODE_FILE_NAMES, true);
|
|
4728
5141
|
const compressionMethod = getOptionValue(zipWriter, options, PROPERTY_NAME_COMPRESSION_METHOD);
|
|
5142
|
+
if (!passThrough && compressionMethod !== UNDEFINED_VALUE &&
|
|
5143
|
+
compressionMethod !== COMPRESSION_METHOD_STORE && compressionMethod !== COMPRESSION_METHOD_DEFLATE) {
|
|
5144
|
+
throw new Error(ERR_UNSUPPORTED_COMPRESSION);
|
|
5145
|
+
}
|
|
4729
5146
|
let level = getOptionValue(zipWriter, options, OPTION_LEVEL);
|
|
4730
5147
|
let useCompressionStream = getOptionValue(zipWriter, options, OPTION_USE_COMPRESSION_STREAM);
|
|
4731
5148
|
let dataDescriptor = getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR);
|
|
@@ -4741,7 +5158,7 @@
|
|
|
4741
5158
|
if (!useCompressionStream && (zipWriter.config.CompressionStream === UNDEFINED_VALUE && zipWriter.config.CompressionStreamZlib === UNDEFINED_VALUE)) {
|
|
4742
5159
|
level = 0;
|
|
4743
5160
|
}
|
|
4744
|
-
|
|
5161
|
+
const zip64 = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIP64);
|
|
4745
5162
|
if (!zipCrypto && (password !== UNDEFINED_VALUE || rawPassword !== UNDEFINED_VALUE) && !(encryptionStrength >= 1 && encryptionStrength <= 3)) {
|
|
4746
5163
|
throw new Error(ERR_INVALID_ENCRYPTION_STRENGTH);
|
|
4747
5164
|
}
|
|
@@ -4752,6 +5169,7 @@
|
|
|
4752
5169
|
let offset = 0;
|
|
4753
5170
|
extraField.forEach(data => extraFieldSize += 4 + getLength(data));
|
|
4754
5171
|
rawExtraField = new Uint8Array(extraFieldSize);
|
|
5172
|
+
const rawExtraFieldView = getDataView(rawExtraField);
|
|
4755
5173
|
extraField.forEach((data, type) => {
|
|
4756
5174
|
if (type > MAX_16_BITS) {
|
|
4757
5175
|
throw new Error(ERR_INVALID_EXTRAFIELD_TYPE);
|
|
@@ -4759,22 +5177,72 @@
|
|
|
4759
5177
|
if (getLength(data) > MAX_16_BITS) {
|
|
4760
5178
|
throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
|
|
4761
5179
|
}
|
|
4762
|
-
|
|
4763
|
-
|
|
5180
|
+
setUint16(rawExtraFieldView, offset, type);
|
|
5181
|
+
setUint16(rawExtraFieldView, offset + 2, getLength(data));
|
|
4764
5182
|
arraySet(rawExtraField, data, offset + 4);
|
|
4765
5183
|
offset += 4 + getLength(data);
|
|
4766
5184
|
});
|
|
4767
5185
|
}
|
|
5186
|
+
return {
|
|
5187
|
+
comment,
|
|
5188
|
+
resolvedOptions: {
|
|
5189
|
+
rawFilename,
|
|
5190
|
+
rawComment,
|
|
5191
|
+
version,
|
|
5192
|
+
lastModDate,
|
|
5193
|
+
lastAccessDate,
|
|
5194
|
+
creationDate,
|
|
5195
|
+
internalFileAttributes,
|
|
5196
|
+
passThrough,
|
|
5197
|
+
password,
|
|
5198
|
+
rawPassword,
|
|
5199
|
+
encryptionStrength,
|
|
5200
|
+
zipCrypto,
|
|
5201
|
+
extendedTimestamp,
|
|
5202
|
+
keepOrder,
|
|
5203
|
+
useWebWorkers,
|
|
5204
|
+
transferStreams,
|
|
5205
|
+
bufferedWrite,
|
|
5206
|
+
createTempStream,
|
|
5207
|
+
dataDescriptorSignature,
|
|
5208
|
+
signal,
|
|
5209
|
+
useUnicodeFileNames,
|
|
5210
|
+
compressionMethod,
|
|
5211
|
+
level,
|
|
5212
|
+
useCompressionStream,
|
|
5213
|
+
dataDescriptor,
|
|
5214
|
+
zip64,
|
|
5215
|
+
rawExtraField
|
|
5216
|
+
}
|
|
5217
|
+
};
|
|
5218
|
+
}
|
|
5219
|
+
|
|
5220
|
+
async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, options) {
|
|
5221
|
+
const { passThrough, zipCrypto, password, rawPassword, encryptionStrength } = metadata;
|
|
5222
|
+
let { dataDescriptor, zip64, level, compressionMethod } = metadata;
|
|
4768
5223
|
let maximumCompressedSize = 0;
|
|
4769
|
-
let maximumEntrySize = 0;
|
|
4770
5224
|
let uncompressedSize = 0;
|
|
4771
5225
|
if (passThrough) {
|
|
5226
|
+
// the headers of a passThrough entry describe the payload verbatim: without a
|
|
5227
|
+
// reader they would declare content that is not there
|
|
5228
|
+
if (!reader) {
|
|
5229
|
+
throw new Error(ERR_UNDEFINED_READER);
|
|
5230
|
+
}
|
|
4772
5231
|
uncompressedSize = options[PROPERTY_NAME_UNCOMPRESSED_SIZE];
|
|
4773
5232
|
if (uncompressedSize === UNDEFINED_VALUE) {
|
|
4774
5233
|
throw new Error(ERR_UNDEFINED_UNCOMPRESSED_SIZE);
|
|
4775
5234
|
}
|
|
4776
5235
|
}
|
|
4777
5236
|
const zip64Enabled = zip64 === true;
|
|
5237
|
+
const encrypted = getOptionValue(zipWriter, options, PROPERTY_NAME_ENCRYPTED);
|
|
5238
|
+
// entries without a reader have no payload: write them as empty stored files instead of
|
|
5239
|
+
// declaring a compressed or encrypted content that does not exist
|
|
5240
|
+
const encryptedEntry = Boolean(reader) && (Boolean((password && getLength(password)) || (rawPassword && getLength(rawPassword))) || (passThrough && encrypted));
|
|
5241
|
+
if (!reader) {
|
|
5242
|
+
level = 0;
|
|
5243
|
+
compressionMethod = COMPRESSION_METHOD_STORE;
|
|
5244
|
+
}
|
|
5245
|
+
const encryptionOverhead = encryptedEntry ? (zipCrypto ? 12 : 16 + encryptionStrength * 4) : 0;
|
|
4778
5246
|
if (reader) {
|
|
4779
5247
|
reader = new GenericReader(reader);
|
|
4780
5248
|
await initStream(reader);
|
|
@@ -4787,16 +5255,15 @@
|
|
|
4787
5255
|
}
|
|
4788
5256
|
} else {
|
|
4789
5257
|
options.uncompressedSize = uncompressedSize = reader.size;
|
|
4790
|
-
maximumCompressedSize = getMaximumCompressedSize(uncompressedSize);
|
|
5258
|
+
maximumCompressedSize = getMaximumCompressedSize(uncompressedSize) + encryptionOverhead;
|
|
4791
5259
|
}
|
|
4792
5260
|
} else {
|
|
4793
5261
|
options.uncompressedSize = uncompressedSize;
|
|
4794
|
-
maximumCompressedSize = getMaximumCompressedSize(uncompressedSize);
|
|
5262
|
+
maximumCompressedSize = getMaximumCompressedSize(uncompressedSize) + encryptionOverhead;
|
|
4795
5263
|
}
|
|
4796
5264
|
}
|
|
4797
|
-
const
|
|
4798
|
-
const
|
|
4799
|
-
const zip64CompressedSize = zip64Enabled || maximumCompressedSize > MAX_32_BITS;
|
|
5265
|
+
const zip64UncompressedSize = zip64Enabled || uncompressedSize >= MAX_32_BITS;
|
|
5266
|
+
const zip64CompressedSize = zip64Enabled || maximumCompressedSize >= MAX_32_BITS;
|
|
4800
5267
|
if (zip64UncompressedSize || zip64CompressedSize) {
|
|
4801
5268
|
if (zip64 === false) {
|
|
4802
5269
|
throw new Error(ERR_UNSUPPORTED_FORMAT);
|
|
@@ -4805,73 +5272,19 @@
|
|
|
4805
5272
|
}
|
|
4806
5273
|
}
|
|
4807
5274
|
zip64 = zip64 || false;
|
|
4808
|
-
|
|
4809
|
-
|
|
4810
|
-
|
|
4811
|
-
|
|
4812
|
-
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
|
|
4820
|
-
|
|
4821
|
-
password,
|
|
4822
|
-
rawPassword,
|
|
4823
|
-
level,
|
|
4824
|
-
useWebWorkers,
|
|
4825
|
-
transferStreams,
|
|
4826
|
-
encryptionStrength,
|
|
4827
|
-
extendedTimestamp,
|
|
4828
|
-
zipCrypto,
|
|
4829
|
-
bufferedWrite,
|
|
4830
|
-
createTempStream,
|
|
4831
|
-
keepOrder,
|
|
4832
|
-
useUnicodeFileNames,
|
|
4833
|
-
dataDescriptor,
|
|
4834
|
-
dataDescriptorSignature,
|
|
4835
|
-
signal,
|
|
4836
|
-
msDosCompatible,
|
|
4837
|
-
internalFileAttribute: internalFileAttributes,
|
|
4838
|
-
internalFileAttributes,
|
|
4839
|
-
externalFileAttribute: externalFileAttributes,
|
|
4840
|
-
externalFileAttributes,
|
|
4841
|
-
useCompressionStream,
|
|
4842
|
-
passThrough,
|
|
4843
|
-
encrypted: Boolean((password && getLength(password)) || (rawPassword && getLength(rawPassword))) || (passThrough && encrypted),
|
|
4844
|
-
signature: options[PROPERTY_NAME_SIGNATURE],
|
|
4845
|
-
compressionMethod,
|
|
4846
|
-
uncompressedSize,
|
|
4847
|
-
offset: zipWriter.offset - diskOffset,
|
|
4848
|
-
diskNumberStart: diskNumber,
|
|
4849
|
-
uid,
|
|
4850
|
-
gid,
|
|
4851
|
-
setuid,
|
|
4852
|
-
setgid,
|
|
4853
|
-
sticky,
|
|
4854
|
-
unixMode,
|
|
4855
|
-
msdosAttributesRaw,
|
|
4856
|
-
msdosAttributes,
|
|
4857
|
-
unixExternalUpper
|
|
4858
|
-
});
|
|
4859
|
-
const headerInfo = getHeaderInfo(options);
|
|
4860
|
-
const dataDescriptorInfo = getDataDescriptorInfo(options);
|
|
4861
|
-
const metadataSize = getLength(headerInfo.localHeaderArray, dataDescriptorInfo.dataDescriptorArray);
|
|
4862
|
-
maximumEntrySize = metadataSize + maximumCompressedSize;
|
|
4863
|
-
if (zipWriter.options[OPTION_USDZ]) {
|
|
4864
|
-
maximumEntrySize += maximumEntrySize + 64;
|
|
4865
|
-
}
|
|
4866
|
-
zipWriter.pendingEntriesSize += maximumEntrySize;
|
|
4867
|
-
let fileEntry;
|
|
4868
|
-
try {
|
|
4869
|
-
fileEntry = await getFileEntry(zipWriter, name, reader, { headerInfo, dataDescriptorInfo, metadataSize }, options);
|
|
4870
|
-
} finally {
|
|
4871
|
-
zipWriter.pendingEntriesSize -= maximumEntrySize;
|
|
4872
|
-
}
|
|
4873
|
-
Object.assign(fileEntry, { name, comment, extraField });
|
|
4874
|
-
return new Entry(fileEntry);
|
|
5275
|
+
return {
|
|
5276
|
+
reader,
|
|
5277
|
+
resolvedOptions: {
|
|
5278
|
+
dataDescriptor,
|
|
5279
|
+
zip64,
|
|
5280
|
+
zip64UncompressedSize,
|
|
5281
|
+
zip64CompressedSize,
|
|
5282
|
+
uncompressedSize,
|
|
5283
|
+
level,
|
|
5284
|
+
compressionMethod,
|
|
5285
|
+
encrypted: encryptedEntry
|
|
5286
|
+
}
|
|
5287
|
+
};
|
|
4875
5288
|
}
|
|
4876
5289
|
|
|
4877
5290
|
async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
@@ -4888,37 +5301,40 @@
|
|
|
4888
5301
|
headerInfo
|
|
4889
5302
|
} = entryInfo;
|
|
4890
5303
|
const usdz = zipWriter.options[OPTION_USDZ];
|
|
4891
|
-
const previousFileEntry =
|
|
5304
|
+
const previousFileEntry = zipWriter.lastFileEntry;
|
|
4892
5305
|
let fileEntry = {};
|
|
4893
5306
|
let bufferedWrite;
|
|
4894
5307
|
let releaseLockWriter;
|
|
4895
5308
|
let releaseLockCurrentFileEntry;
|
|
4896
5309
|
let writingBufferedEntryData;
|
|
4897
5310
|
let writingEntryData;
|
|
5311
|
+
let writerSizeBeforeEntry;
|
|
5312
|
+
let flushedBufferedSize = 0;
|
|
4898
5313
|
let fileWriter;
|
|
4899
5314
|
files.set(name, fileEntry);
|
|
5315
|
+
zipWriter.lastFileEntry = fileEntry;
|
|
4900
5316
|
try {
|
|
4901
5317
|
let lockPreviousFileEntry;
|
|
4902
5318
|
if (keepOrder) {
|
|
4903
5319
|
lockPreviousFileEntry = previousFileEntry && previousFileEntry.lock;
|
|
4904
5320
|
requestLockCurrentFileEntry();
|
|
4905
5321
|
}
|
|
4906
|
-
if (
|
|
5322
|
+
if (options.bufferedWrite || !keepOrder || zipWriter.writerLocked || zipWriter.bufferedWrites || !dataDescriptor) {
|
|
5323
|
+
bufferedWrite = true;
|
|
5324
|
+
zipWriter.bufferedWrites++;
|
|
4907
5325
|
if (options.createTempStream) {
|
|
4908
5326
|
fileWriter = await options.createTempStream();
|
|
4909
5327
|
} else {
|
|
4910
5328
|
fileWriter = new TransformStream(UNDEFINED_VALUE, UNDEFINED_VALUE, { highWaterMark: INFINITY_VALUE });
|
|
4911
5329
|
}
|
|
4912
5330
|
fileWriter.size = 0;
|
|
4913
|
-
bufferedWrite = true;
|
|
4914
|
-
zipWriter.bufferedWrites++;
|
|
4915
5331
|
await initStream(writer);
|
|
4916
5332
|
} else {
|
|
4917
5333
|
fileWriter = writer;
|
|
4918
5334
|
await requestLockWriter();
|
|
4919
5335
|
}
|
|
4920
5336
|
await initStream(fileWriter);
|
|
4921
|
-
const {
|
|
5337
|
+
const { diskOffset } = writer;
|
|
4922
5338
|
if (zipWriter.addSplitZipSignature) {
|
|
4923
5339
|
delete zipWriter.addSplitZipSignature;
|
|
4924
5340
|
const signatureArray = new Uint8Array(4);
|
|
@@ -4927,21 +5343,20 @@
|
|
|
4927
5343
|
await writeData(writer, signatureArray);
|
|
4928
5344
|
zipWriter.offset += 4;
|
|
4929
5345
|
}
|
|
4930
|
-
if (usdz) {
|
|
5346
|
+
if (usdz && !bufferedWrite) {
|
|
4931
5347
|
appendExtraFieldUSDZ(entryInfo, zipWriter.offset - diskOffset);
|
|
4932
5348
|
}
|
|
4933
|
-
const {
|
|
4934
|
-
localHeaderView,
|
|
4935
|
-
localHeaderArray
|
|
4936
|
-
} = headerInfo;
|
|
5349
|
+
const { localHeaderArray } = headerInfo;
|
|
4937
5350
|
if (!bufferedWrite) {
|
|
4938
5351
|
await lockPreviousFileEntry;
|
|
4939
|
-
await skipDiskIfNeeded(
|
|
5352
|
+
await skipDiskIfNeeded();
|
|
4940
5353
|
}
|
|
4941
|
-
const
|
|
4942
|
-
|
|
5354
|
+
const diskNumberStart = writer.diskNumber;
|
|
5355
|
+
const entryOffset = getSegmentOffset(zipWriter, writer);
|
|
5356
|
+
fileEntry.diskNumberStart = diskNumberStart;
|
|
4943
5357
|
if (!bufferedWrite) {
|
|
4944
5358
|
writingEntryData = true;
|
|
5359
|
+
writerSizeBeforeEntry = writer.size;
|
|
4945
5360
|
await writeData(fileWriter, localHeaderArray);
|
|
4946
5361
|
}
|
|
4947
5362
|
fileEntry = await createFileEntry(reader, fileWriter, fileEntry, entryInfo, zipWriter.config, options);
|
|
@@ -4954,16 +5369,24 @@
|
|
|
4954
5369
|
await Promise.all([fileWriter.writable.getWriter().close(), lockPreviousFileEntry]);
|
|
4955
5370
|
await requestLockWriter();
|
|
4956
5371
|
writingBufferedEntryData = true;
|
|
5372
|
+
writerSizeBeforeEntry = writer.size;
|
|
5373
|
+
await skipDiskIfNeeded();
|
|
4957
5374
|
fileEntry.diskNumberStart = writer.diskNumber;
|
|
4958
|
-
fileEntry.offset = zipWriter
|
|
4959
|
-
|
|
4960
|
-
|
|
4961
|
-
|
|
4962
|
-
|
|
5375
|
+
fileEntry.offset = getSegmentOffset(zipWriter, writer);
|
|
5376
|
+
if (usdz) {
|
|
5377
|
+
// the padding depends on the entry offset, only known now that the writer is locked
|
|
5378
|
+
const previousMetadataSize = entryInfo.metadataSize;
|
|
5379
|
+
appendExtraFieldUSDZ(entryInfo, zipWriter.offset - writer.diskOffset);
|
|
5380
|
+
fileEntry.size += entryInfo.metadataSize - previousMetadataSize;
|
|
5381
|
+
}
|
|
5382
|
+
updateLocalHeader(fileEntry, headerInfo.localHeaderView, options);
|
|
5383
|
+
await writeData(writer, headerInfo.localHeaderArray);
|
|
5384
|
+
await flushBufferedData(fileWriter.readable, writer, signal, chunkLength => flushedBufferedSize += chunkLength);
|
|
4963
5385
|
writer.size += fileWriter.size;
|
|
4964
5386
|
writingBufferedEntryData = false;
|
|
4965
5387
|
} else {
|
|
4966
|
-
fileEntry.
|
|
5388
|
+
fileEntry.diskNumberStart = diskNumberStart;
|
|
5389
|
+
fileEntry.offset = entryOffset;
|
|
4967
5390
|
}
|
|
4968
5391
|
zipWriter.offset += fileEntry.size;
|
|
4969
5392
|
return fileEntry;
|
|
@@ -4977,10 +5400,9 @@
|
|
|
4977
5400
|
// ignored
|
|
4978
5401
|
}
|
|
4979
5402
|
}
|
|
5403
|
+
zipWriter.offset += writer.size - writerSizeBeforeEntry;
|
|
4980
5404
|
if (bufferedWrite) {
|
|
4981
|
-
zipWriter.offset +=
|
|
4982
|
-
} else {
|
|
4983
|
-
zipWriter.offset = fileWriter.size;
|
|
5405
|
+
zipWriter.offset += flushedBufferedSize;
|
|
4984
5406
|
}
|
|
4985
5407
|
}
|
|
4986
5408
|
files.delete(name);
|
|
@@ -5011,10 +5433,10 @@
|
|
|
5011
5433
|
await lockWriter;
|
|
5012
5434
|
}
|
|
5013
5435
|
|
|
5014
|
-
async function skipDiskIfNeeded(
|
|
5436
|
+
async function skipDiskIfNeeded() {
|
|
5015
5437
|
if (getLength(headerInfo.localHeaderArray) > writer.availableSize) {
|
|
5016
5438
|
writer.availableSize = 0;
|
|
5017
|
-
await writeData(
|
|
5439
|
+
await writeData(writer, new Uint8Array());
|
|
5018
5440
|
}
|
|
5019
5441
|
}
|
|
5020
5442
|
}
|
|
@@ -5155,6 +5577,10 @@
|
|
|
5155
5577
|
uncompressedSize = result.inputSize;
|
|
5156
5578
|
signature = result.signature;
|
|
5157
5579
|
}
|
|
5580
|
+
if ((!zip64CompressedSize && compressedSize >= MAX_32_BITS) ||
|
|
5581
|
+
(!zip64UncompressedSize && uncompressedSize >= MAX_32_BITS)) {
|
|
5582
|
+
throw new Error(ERR_UNSUPPORTED_FORMAT);
|
|
5583
|
+
}
|
|
5158
5584
|
} catch (error) {
|
|
5159
5585
|
if (error.outputSize !== UNDEFINED_VALUE) {
|
|
5160
5586
|
writer.size += error.outputSize;
|
|
@@ -5217,35 +5643,28 @@
|
|
|
5217
5643
|
uncompressedSize
|
|
5218
5644
|
} = options;
|
|
5219
5645
|
let { version, compressionMethod } = options;
|
|
5220
|
-
const compressed = !directory && (
|
|
5646
|
+
const compressed = !directory && (compressionMethod === UNDEFINED_VALUE
|
|
5647
|
+
? (level === UNDEFINED_VALUE || level > 0)
|
|
5648
|
+
: compressionMethod !== COMPRESSION_METHOD_STORE);
|
|
5221
5649
|
let rawLocalExtraFieldZip64;
|
|
5222
5650
|
const uncompressedFile = passThrough || !compressed;
|
|
5223
|
-
|
|
5224
|
-
|
|
5225
|
-
|
|
5226
|
-
|
|
5227
|
-
|
|
5228
|
-
|
|
5229
|
-
|
|
5230
|
-
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
setUint16(rawLocalExtraFieldZip64View, 2, getLength(rawLocalExtraFieldZip64) - 4);
|
|
5651
|
+
// entries without a data descriptor are always buffered (cf. getFileEntry), so the
|
|
5652
|
+
// zip64 extra field values can be patched into the local header before flushing it
|
|
5653
|
+
const zip64ExtraFieldComplete = zip64 && (options.bufferedWrite || !dataDescriptor || ((!zip64UncompressedSize && !zip64CompressedSize) || uncompressedFile));
|
|
5654
|
+
const writeLocalExtraFieldZip64 = zip64ExtraFieldComplete || (zip64 && dataDescriptor && (zip64UncompressedSize || zip64CompressedSize));
|
|
5655
|
+
if (zip64 && (zip64UncompressedSize || zip64CompressedSize)) {
|
|
5656
|
+
// APPNOTE 4.5.3: the zip64 extra field of a local header must include both the
|
|
5657
|
+
// uncompressed and compressed size fields
|
|
5658
|
+
const length = 4 + 16;
|
|
5659
|
+
const extraFieldZip64 = createRecordWriter(length);
|
|
5660
|
+
extraFieldZip64.uint16(EXTRAFIELD_TYPE_ZIP64);
|
|
5661
|
+
extraFieldZip64.uint16(length - 4);
|
|
5662
|
+
rawLocalExtraFieldZip64 = extraFieldZip64.array;
|
|
5236
5663
|
if (zip64ExtraFieldComplete) {
|
|
5237
|
-
|
|
5238
|
-
|
|
5239
|
-
|
|
5240
|
-
|
|
5241
|
-
rawLocalExtraFieldZip64Offset += 8;
|
|
5242
|
-
}
|
|
5243
|
-
if (zip64CompressedSize && uncompressedFile) {
|
|
5244
|
-
setBigUint64(rawLocalExtraFieldZip64View, rawLocalExtraFieldZip64Offset, BigInt(uncompressedSize));
|
|
5245
|
-
rawLocalExtraFieldZip64Offset += 8;
|
|
5246
|
-
}
|
|
5247
|
-
if (rawLocalExtraFieldZip64Offset == 4) {
|
|
5248
|
-
rawLocalExtraFieldZip64 = new Uint8Array();
|
|
5664
|
+
extraFieldZip64.uint64(uncompressedSize);
|
|
5665
|
+
if (uncompressedFile) {
|
|
5666
|
+
const encryptionOverhead = encrypted ? (zipCrypto ? 12 : 16 + encryptionStrength * 4) : 0;
|
|
5667
|
+
extraFieldZip64.uint64(passThrough ? 0 : uncompressedSize + encryptionOverhead);
|
|
5249
5668
|
}
|
|
5250
5669
|
}
|
|
5251
5670
|
} else {
|
|
@@ -5253,11 +5672,11 @@
|
|
|
5253
5672
|
}
|
|
5254
5673
|
let rawExtraFieldAES;
|
|
5255
5674
|
if (encrypted && !zipCrypto) {
|
|
5256
|
-
|
|
5257
|
-
|
|
5258
|
-
|
|
5259
|
-
|
|
5260
|
-
|
|
5675
|
+
const extraFieldAES = createRecordWriter(getLength(EXTRAFIELD_DATA_AES) + 2);
|
|
5676
|
+
extraFieldAES.uint16(EXTRAFIELD_TYPE_AES);
|
|
5677
|
+
extraFieldAES.bytes(EXTRAFIELD_DATA_AES);
|
|
5678
|
+
rawExtraFieldAES = extraFieldAES.array;
|
|
5679
|
+
rawExtraFieldAES[8] = encryptionStrength;
|
|
5261
5680
|
} else {
|
|
5262
5681
|
rawExtraFieldAES = new Uint8Array();
|
|
5263
5682
|
}
|
|
@@ -5265,33 +5684,38 @@
|
|
|
5265
5684
|
let rawExtraFieldExtendedTimestamp;
|
|
5266
5685
|
let extraFieldExtendedTimestampFlag;
|
|
5267
5686
|
if (extendedTimestamp) {
|
|
5268
|
-
|
|
5269
|
-
|
|
5270
|
-
|
|
5271
|
-
|
|
5272
|
-
|
|
5273
|
-
|
|
5274
|
-
|
|
5275
|
-
|
|
5276
|
-
|
|
5277
|
-
|
|
5278
|
-
|
|
5279
|
-
|
|
5280
|
-
|
|
5281
|
-
|
|
5282
|
-
|
|
5687
|
+
const lastModTimeUnix = getTimeUnix(lastModDate);
|
|
5688
|
+
if (inUnixTimeRange(lastModTimeUnix)) {
|
|
5689
|
+
const extraFieldTimestampLength = 9 + (lastAccessDate ? 4 : 0) + (creationDate ? 4 : 0);
|
|
5690
|
+
const extraFieldTimestamp = createRecordWriter(extraFieldTimestampLength);
|
|
5691
|
+
extraFieldExtendedTimestampFlag = 0x1 + (lastAccessDate ? 0x2 : 0) + (creationDate ? 0x4 : 0);
|
|
5692
|
+
extraFieldTimestamp.uint16(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
|
|
5693
|
+
extraFieldTimestamp.uint16(extraFieldTimestampLength - 4);
|
|
5694
|
+
extraFieldTimestamp.uint8(extraFieldExtendedTimestampFlag);
|
|
5695
|
+
extraFieldTimestamp.uint32(lastModTimeUnix);
|
|
5696
|
+
if (lastAccessDate) {
|
|
5697
|
+
extraFieldTimestamp.uint32(clampUnixTime(getTimeUnix(lastAccessDate)));
|
|
5698
|
+
}
|
|
5699
|
+
if (creationDate) {
|
|
5700
|
+
extraFieldTimestamp.uint32(clampUnixTime(getTimeUnix(creationDate)));
|
|
5701
|
+
}
|
|
5702
|
+
rawExtraFieldExtendedTimestamp = extraFieldTimestamp.array;
|
|
5703
|
+
} else {
|
|
5704
|
+
// the date cannot be stored as a 32-bit time_t; the NTFS field replaces it
|
|
5705
|
+
rawExtraFieldExtendedTimestamp = new Uint8Array();
|
|
5283
5706
|
}
|
|
5284
5707
|
try {
|
|
5285
|
-
rawExtraFieldNTFS = new Uint8Array(36);
|
|
5286
|
-
const extraFieldNTFSView = getDataView(rawExtraFieldNTFS);
|
|
5287
5708
|
const lastModTimeNTFS = getTimeNTFS(lastModDate);
|
|
5288
|
-
|
|
5289
|
-
|
|
5290
|
-
|
|
5291
|
-
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
|
|
5709
|
+
const extraFieldNTFS = createRecordWriter(36);
|
|
5710
|
+
extraFieldNTFS.uint16(EXTRAFIELD_TYPE_NTFS);
|
|
5711
|
+
extraFieldNTFS.uint16(32);
|
|
5712
|
+
extraFieldNTFS.skip(4);
|
|
5713
|
+
extraFieldNTFS.uint16(EXTRAFIELD_TYPE_NTFS_TAG1);
|
|
5714
|
+
extraFieldNTFS.uint16(24);
|
|
5715
|
+
extraFieldNTFS.uint64(lastModTimeNTFS);
|
|
5716
|
+
extraFieldNTFS.uint64(getTimeNTFS(lastAccessDate) || lastModTimeNTFS);
|
|
5717
|
+
extraFieldNTFS.uint64(getTimeNTFS(creationDate) || lastModTimeNTFS);
|
|
5718
|
+
rawExtraFieldNTFS = extraFieldNTFS.array;
|
|
5295
5719
|
} catch {
|
|
5296
5720
|
rawExtraFieldNTFS = new Uint8Array();
|
|
5297
5721
|
}
|
|
@@ -5300,41 +5724,27 @@
|
|
|
5300
5724
|
}
|
|
5301
5725
|
let rawExtraFieldUnix;
|
|
5302
5726
|
try {
|
|
5303
|
-
const { uid, gid,
|
|
5304
|
-
if (unixExtraFieldType && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE
|
|
5727
|
+
const { uid, gid, unixExtraFieldType } = options;
|
|
5728
|
+
if (unixExtraFieldType == INFOZIP_EXTRA_FIELD_TYPE && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
|
|
5305
5729
|
const uidBytes = packUnixId(uid);
|
|
5306
5730
|
const gidBytes = packUnixId(gid);
|
|
5307
|
-
|
|
5308
|
-
|
|
5309
|
-
|
|
5310
|
-
|
|
5311
|
-
|
|
5312
|
-
|
|
5313
|
-
|
|
5314
|
-
|
|
5315
|
-
|
|
5316
|
-
|
|
5317
|
-
|
|
5318
|
-
|
|
5319
|
-
|
|
5320
|
-
|
|
5321
|
-
|
|
5322
|
-
|
|
5323
|
-
|
|
5324
|
-
rawExtraFieldUnix = new Uint8Array(4 + payloadLength);
|
|
5325
|
-
const rawExtraFieldUnixView = getDataView(rawExtraFieldUnix);
|
|
5326
|
-
setUint16(rawExtraFieldUnixView, 0, unixExtraFieldType == INFOZIP_EXTRA_FIELD_TYPE ? EXTRAFIELD_TYPE_INFOZIP : EXTRAFIELD_TYPE_UNIX);
|
|
5327
|
-
setUint16(rawExtraFieldUnixView, 2, payloadLength);
|
|
5328
|
-
setUint8(rawExtraFieldUnixView, 4, 1);
|
|
5329
|
-
setUint8(rawExtraFieldUnixView, 5, uidBytes.length);
|
|
5330
|
-
let offset = 6;
|
|
5331
|
-
arraySet(rawExtraFieldUnix, uidBytes, offset);
|
|
5332
|
-
offset += uidBytes.length;
|
|
5333
|
-
setUint8(rawExtraFieldUnixView, offset, gidBytes.length);
|
|
5334
|
-
offset++;
|
|
5335
|
-
arraySet(rawExtraFieldUnix, gidBytes, offset);
|
|
5336
|
-
offset += gidBytes.length;
|
|
5337
|
-
arraySet(rawExtraFieldUnix, modeArray, offset);
|
|
5731
|
+
const payloadLength = 3 + uidBytes.length + gidBytes.length;
|
|
5732
|
+
const extraFieldUnix = createRecordWriter(4 + payloadLength);
|
|
5733
|
+
extraFieldUnix.uint16(EXTRAFIELD_TYPE_INFOZIP);
|
|
5734
|
+
extraFieldUnix.uint16(payloadLength);
|
|
5735
|
+
extraFieldUnix.uint8(1);
|
|
5736
|
+
extraFieldUnix.uint8(uidBytes.length);
|
|
5737
|
+
extraFieldUnix.bytes(uidBytes);
|
|
5738
|
+
extraFieldUnix.uint8(gidBytes.length);
|
|
5739
|
+
extraFieldUnix.bytes(gidBytes);
|
|
5740
|
+
rawExtraFieldUnix = extraFieldUnix.array;
|
|
5741
|
+
} else if (unixExtraFieldType == UNIX_EXTRA_FIELD_TYPE && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
|
|
5742
|
+
const extraFieldUnix = createRecordWriter(8);
|
|
5743
|
+
extraFieldUnix.uint16(EXTRAFIELD_TYPE_UNIX);
|
|
5744
|
+
extraFieldUnix.uint16(4);
|
|
5745
|
+
extraFieldUnix.uint16((uid === UNDEFINED_VALUE ? 0 : uid) & MAX_16_BITS);
|
|
5746
|
+
extraFieldUnix.uint16((gid === UNDEFINED_VALUE ? 0 : gid) & MAX_16_BITS);
|
|
5747
|
+
rawExtraFieldUnix = extraFieldUnix.array;
|
|
5338
5748
|
} else {
|
|
5339
5749
|
rawExtraFieldUnix = new Uint8Array();
|
|
5340
5750
|
}
|
|
@@ -5352,8 +5762,11 @@
|
|
|
5352
5762
|
rawExtraFieldAES[9] = compressionMethod;
|
|
5353
5763
|
compressionMethod = COMPRESSION_METHOD_AES;
|
|
5354
5764
|
}
|
|
5355
|
-
const localExtraFieldZip64Length =
|
|
5765
|
+
const localExtraFieldZip64Length = writeLocalExtraFieldZip64 ? getLength(rawLocalExtraFieldZip64) : 0;
|
|
5356
5766
|
const extraFieldLength = localExtraFieldZip64Length + getLength(rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField);
|
|
5767
|
+
if (extraFieldLength > MAX_16_BITS) {
|
|
5768
|
+
throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
|
|
5769
|
+
}
|
|
5357
5770
|
const {
|
|
5358
5771
|
headerArray,
|
|
5359
5772
|
headerView,
|
|
@@ -5369,29 +5782,27 @@
|
|
|
5369
5782
|
zip64UncompressedSize,
|
|
5370
5783
|
extraFieldLength
|
|
5371
5784
|
});
|
|
5372
|
-
|
|
5373
|
-
const localHeaderArray =
|
|
5785
|
+
const localHeader = createRecordWriter(HEADER_SIZE + getLength(rawFilename) + extraFieldLength);
|
|
5786
|
+
const localHeaderArray = localHeader.array;
|
|
5374
5787
|
const localHeaderView = getDataView(localHeaderArray);
|
|
5375
|
-
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
|
|
5380
|
-
|
|
5381
|
-
|
|
5382
|
-
|
|
5383
|
-
|
|
5384
|
-
|
|
5385
|
-
|
|
5386
|
-
localHeaderOffset += getLength(rawExtraFieldExtendedTimestamp);
|
|
5387
|
-
arraySet(localHeaderArray, rawExtraFieldNTFS, localHeaderOffset);
|
|
5388
|
-
localHeaderOffset += getLength(rawExtraFieldNTFS);
|
|
5389
|
-
arraySet(localHeaderArray, rawExtraFieldUnix, localHeaderOffset);
|
|
5390
|
-
localHeaderOffset += getLength(rawExtraFieldUnix);
|
|
5391
|
-
arraySet(localHeaderArray, rawExtraField, localHeaderOffset);
|
|
5788
|
+
localHeader.uint32(LOCAL_FILE_HEADER_SIGNATURE);
|
|
5789
|
+
localHeader.bytes(headerArray);
|
|
5790
|
+
localHeader.bytes(rawFilename);
|
|
5791
|
+
if (writeLocalExtraFieldZip64) {
|
|
5792
|
+
localHeader.bytes(rawLocalExtraFieldZip64);
|
|
5793
|
+
}
|
|
5794
|
+
localHeader.bytes(rawExtraFieldAES);
|
|
5795
|
+
localHeader.bytes(rawExtraFieldExtendedTimestamp);
|
|
5796
|
+
localHeader.bytes(rawExtraFieldNTFS);
|
|
5797
|
+
localHeader.bytes(rawExtraFieldUnix);
|
|
5798
|
+
localHeader.bytes(rawExtraField);
|
|
5392
5799
|
if (dataDescriptor) {
|
|
5393
|
-
|
|
5394
|
-
|
|
5800
|
+
if (!zip64CompressedSize) {
|
|
5801
|
+
setUint32(localHeaderView, HEADER_OFFSET_COMPRESSED_SIZE + LOCAL_HEADER_COMMON_OFFSET, 0);
|
|
5802
|
+
}
|
|
5803
|
+
if (!zip64UncompressedSize) {
|
|
5804
|
+
setUint32(localHeaderView, HEADER_OFFSET_UNCOMPRESSED_SIZE + LOCAL_HEADER_COMMON_OFFSET, 0);
|
|
5805
|
+
}
|
|
5395
5806
|
}
|
|
5396
5807
|
return {
|
|
5397
5808
|
localHeaderArray,
|
|
@@ -5418,7 +5829,7 @@
|
|
|
5418
5829
|
function appendExtraFieldUSDZ(entryInfo, zipWriterOffset) {
|
|
5419
5830
|
const { headerInfo } = entryInfo;
|
|
5420
5831
|
let { localHeaderArray, extraFieldLength } = headerInfo;
|
|
5421
|
-
let localHeaderArrayView
|
|
5832
|
+
let localHeaderArrayView;
|
|
5422
5833
|
let extraBytesLength = 64 - ((zipWriterOffset + getLength(localHeaderArray)) % 64);
|
|
5423
5834
|
if (extraBytesLength < 4) {
|
|
5424
5835
|
extraBytesLength += 64;
|
|
@@ -5426,13 +5837,14 @@
|
|
|
5426
5837
|
const rawExtraFieldUSDZ = new Uint8Array(extraBytesLength);
|
|
5427
5838
|
const extraFieldUSDZView = getDataView(rawExtraFieldUSDZ);
|
|
5428
5839
|
setUint16(extraFieldUSDZView, 0, EXTRAFIELD_TYPE_USDZ);
|
|
5429
|
-
setUint16(extraFieldUSDZView, 2, extraBytesLength -
|
|
5840
|
+
setUint16(extraFieldUSDZView, 2, extraBytesLength - 4);
|
|
5430
5841
|
const previousLocalHeaderArray = localHeaderArray;
|
|
5431
5842
|
headerInfo.localHeaderArray = localHeaderArray = new Uint8Array(getLength(previousLocalHeaderArray) + extraBytesLength);
|
|
5432
5843
|
arraySet(localHeaderArray, previousLocalHeaderArray);
|
|
5433
5844
|
arraySet(localHeaderArray, rawExtraFieldUSDZ, getLength(previousLocalHeaderArray));
|
|
5434
5845
|
localHeaderArrayView = getDataView(localHeaderArray);
|
|
5435
5846
|
setUint16(localHeaderArrayView, 28, extraFieldLength + extraBytesLength);
|
|
5847
|
+
headerInfo.localHeaderView = localHeaderArrayView;
|
|
5436
5848
|
entryInfo.metadataSize += extraBytesLength;
|
|
5437
5849
|
}
|
|
5438
5850
|
|
|
@@ -5555,37 +5967,32 @@
|
|
|
5555
5967
|
}, localHeaderView, { dataDescriptor }) {
|
|
5556
5968
|
if (!dataDescriptor) {
|
|
5557
5969
|
if (!encrypted) {
|
|
5558
|
-
setUint32(localHeaderView, HEADER_OFFSET_SIGNATURE +
|
|
5970
|
+
setUint32(localHeaderView, HEADER_OFFSET_SIGNATURE + LOCAL_HEADER_COMMON_OFFSET, signature);
|
|
5559
5971
|
}
|
|
5560
5972
|
if (!zip64CompressedSize) {
|
|
5561
|
-
setUint32(localHeaderView, HEADER_OFFSET_COMPRESSED_SIZE +
|
|
5973
|
+
setUint32(localHeaderView, HEADER_OFFSET_COMPRESSED_SIZE + LOCAL_HEADER_COMMON_OFFSET, compressedSize);
|
|
5562
5974
|
}
|
|
5563
5975
|
if (!zip64UncompressedSize) {
|
|
5564
|
-
setUint32(localHeaderView, HEADER_OFFSET_UNCOMPRESSED_SIZE +
|
|
5976
|
+
setUint32(localHeaderView, HEADER_OFFSET_UNCOMPRESSED_SIZE + LOCAL_HEADER_COMMON_OFFSET, uncompressedSize);
|
|
5565
5977
|
}
|
|
5566
5978
|
}
|
|
5567
5979
|
if (zip64 && localExtraFieldZip64Length) {
|
|
5568
|
-
|
|
5569
|
-
|
|
5570
|
-
|
|
5571
|
-
|
|
5572
|
-
}
|
|
5573
|
-
if (zip64CompressedSize) {
|
|
5574
|
-
setBigUint64(localHeaderView, localHeaderOffset, BigInt(compressedSize));
|
|
5575
|
-
localHeaderOffset += 8;
|
|
5576
|
-
}
|
|
5980
|
+
// the local zip64 extra field always contains both size slots
|
|
5981
|
+
const localHeaderOffset = HEADER_SIZE + getLength(rawFilename) + 4;
|
|
5982
|
+
setBigUint64(localHeaderView, localHeaderOffset, BigInt(uncompressedSize));
|
|
5983
|
+
setBigUint64(localHeaderView, localHeaderOffset + 8, BigInt(compressedSize));
|
|
5577
5984
|
}
|
|
5578
5985
|
}
|
|
5579
5986
|
|
|
5580
5987
|
|
|
5581
5988
|
async function closeFile(zipWriter, comment, options) {
|
|
5582
|
-
const
|
|
5583
|
-
const {
|
|
5584
|
-
|
|
5585
|
-
|
|
5989
|
+
const directoryDataLength = createDirectoryRecords(zipWriter.files);
|
|
5990
|
+
const { cdStartDiskNumber, cdStartDiskOffset } = await writeDirectoryRecords(zipWriter, directoryDataLength, options);
|
|
5991
|
+
await writeEndOfDirectoryRecord(zipWriter, comment, options, { cdStartDiskNumber, cdStartDiskOffset, directoryDataLength });
|
|
5992
|
+
}
|
|
5993
|
+
|
|
5994
|
+
function createDirectoryRecords(files) {
|
|
5586
5995
|
let directoryDataLength = 0;
|
|
5587
|
-
let directoryOffset = zipWriter.offset - diskOffset;
|
|
5588
|
-
let filesLength = files.size;
|
|
5589
5996
|
for (const [, fileEntry] of files) {
|
|
5590
5997
|
const {
|
|
5591
5998
|
rawFilename,
|
|
@@ -5602,24 +6009,27 @@
|
|
|
5602
6009
|
uncompressedSize,
|
|
5603
6010
|
compressedSize
|
|
5604
6011
|
} = fileEntry;
|
|
5605
|
-
const zip64Offset = fileEntry.offset
|
|
5606
|
-
const zip64DiskNumberStart = fileEntry.diskNumberStart
|
|
6012
|
+
const zip64Offset = fileEntry.offset >= MAX_32_BITS;
|
|
6013
|
+
const zip64DiskNumberStart = fileEntry.diskNumberStart >= MAX_16_BITS;
|
|
5607
6014
|
let rawExtraFieldZip64;
|
|
5608
6015
|
if (zip64Offset || zip64DiskNumberStart || zip64UncompressedSize || zip64CompressedSize) {
|
|
5609
|
-
|
|
5610
|
-
|
|
5611
|
-
|
|
5612
|
-
|
|
5613
|
-
if (
|
|
5614
|
-
|
|
5615
|
-
|
|
5616
|
-
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
if (
|
|
5620
|
-
|
|
5621
|
-
|
|
5622
|
-
if (zip64DiskNumberStart) {
|
|
6016
|
+
const length = 4 + (zip64UncompressedSize ? 8 : 0) + (zip64CompressedSize ? 8 : 0) + (zip64Offset ? 8 : 0) + (zip64DiskNumberStart ? 4 : 0);
|
|
6017
|
+
const extraFieldZip64 = createRecordWriter(length);
|
|
6018
|
+
extraFieldZip64.uint16(EXTRAFIELD_TYPE_ZIP64);
|
|
6019
|
+
extraFieldZip64.uint16(length - 4);
|
|
6020
|
+
if (zip64UncompressedSize) {
|
|
6021
|
+
extraFieldZip64.uint64(uncompressedSize);
|
|
6022
|
+
}
|
|
6023
|
+
if (zip64CompressedSize) {
|
|
6024
|
+
extraFieldZip64.uint64(compressedSize);
|
|
6025
|
+
}
|
|
6026
|
+
if (zip64Offset) {
|
|
6027
|
+
extraFieldZip64.uint64(fileEntry.offset);
|
|
6028
|
+
}
|
|
6029
|
+
if (zip64DiskNumberStart) {
|
|
6030
|
+
extraFieldZip64.uint32(fileEntry.diskNumberStart);
|
|
6031
|
+
}
|
|
6032
|
+
rawExtraFieldZip64 = extraFieldZip64.array;
|
|
5623
6033
|
} else {
|
|
5624
6034
|
rawExtraFieldZip64 = new Uint8Array();
|
|
5625
6035
|
}
|
|
@@ -5627,32 +6037,41 @@
|
|
|
5627
6037
|
fileEntry.zip64Offset = zip64Offset;
|
|
5628
6038
|
fileEntry.zip64DiskNumberStart = zip64DiskNumberStart;
|
|
5629
6039
|
let rawExtraFieldTimestamp;
|
|
5630
|
-
|
|
5631
|
-
|
|
5632
|
-
const
|
|
5633
|
-
|
|
5634
|
-
|
|
5635
|
-
|
|
5636
|
-
|
|
6040
|
+
const lastModTimeUnix = getTimeUnix(lastModDate);
|
|
6041
|
+
if (extendedTimestamp && inUnixTimeRange(lastModTimeUnix)) {
|
|
6042
|
+
const extraFieldTimestamp = createRecordWriter(9);
|
|
6043
|
+
extraFieldTimestamp.uint16(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
|
|
6044
|
+
extraFieldTimestamp.uint16(5);
|
|
6045
|
+
extraFieldTimestamp.uint8(extraFieldExtendedTimestampFlag);
|
|
6046
|
+
extraFieldTimestamp.uint32(lastModTimeUnix);
|
|
6047
|
+
rawExtraFieldTimestamp = extraFieldTimestamp.array;
|
|
5637
6048
|
} else {
|
|
5638
6049
|
rawExtraFieldTimestamp = new Uint8Array();
|
|
5639
6050
|
}
|
|
5640
6051
|
fileEntry.rawExtraFieldExtendedTimestamp = rawExtraFieldTimestamp;
|
|
5641
|
-
|
|
5642
|
-
|
|
5643
|
-
|
|
5644
|
-
|
|
5645
|
-
|
|
5646
|
-
|
|
5647
|
-
|
|
5648
|
-
|
|
5649
|
-
|
|
5650
|
-
|
|
6052
|
+
const extraFieldLength = getLength(
|
|
6053
|
+
rawExtraFieldZip64,
|
|
6054
|
+
rawExtraFieldAES,
|
|
6055
|
+
rawExtraFieldNTFS,
|
|
6056
|
+
rawExtraFieldUnix,
|
|
6057
|
+
rawExtraFieldTimestamp,
|
|
6058
|
+
rawExtraField);
|
|
6059
|
+
if (extraFieldLength > MAX_16_BITS) {
|
|
6060
|
+
throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
|
|
6061
|
+
}
|
|
6062
|
+
directoryDataLength += CENTRAL_FILE_HEADER_LENGTH + getLength(rawFilename, rawComment) + extraFieldLength;
|
|
5651
6063
|
}
|
|
6064
|
+
return directoryDataLength;
|
|
6065
|
+
}
|
|
6066
|
+
|
|
6067
|
+
async function writeDirectoryRecords(zipWriter, directoryDataLength, options) {
|
|
6068
|
+
const { files, writer } = zipWriter;
|
|
5652
6069
|
const directoryArray = new Uint8Array(directoryDataLength);
|
|
5653
|
-
const directoryView = getDataView(directoryArray);
|
|
5654
6070
|
await initStream(writer);
|
|
6071
|
+
let offset = 0;
|
|
5655
6072
|
let directoryDiskOffset = 0;
|
|
6073
|
+
let cdStartDiskNumber = writer.diskNumber;
|
|
6074
|
+
let cdStartDiskOffset = writer.diskOffset;
|
|
5656
6075
|
for (const [indexFileEntry, fileEntry] of Array.from(files.values()).entries()) {
|
|
5657
6076
|
const {
|
|
5658
6077
|
offset: fileEntryOffset,
|
|
@@ -5678,52 +6097,46 @@
|
|
|
5678
6097
|
compressedSize
|
|
5679
6098
|
} = fileEntry;
|
|
5680
6099
|
const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField);
|
|
5681
|
-
|
|
5682
|
-
|
|
6100
|
+
const directoryRecordLength = CENTRAL_FILE_HEADER_LENGTH + getLength(rawFilename, rawComment) + extraFieldLength;
|
|
6101
|
+
if (offset + directoryRecordLength - directoryDiskOffset > writer.availableSize) {
|
|
6102
|
+
await writeData(writer, directoryArray.slice(directoryDiskOffset, offset));
|
|
6103
|
+
directoryDiskOffset = offset;
|
|
6104
|
+
writer.availableSize = 0;
|
|
6105
|
+
await writeData(writer, new Uint8Array());
|
|
6106
|
+
}
|
|
6107
|
+
if (indexFileEntry == 0) {
|
|
6108
|
+
cdStartDiskNumber = writer.diskNumber;
|
|
6109
|
+
cdStartDiskOffset = writer.diskOffset;
|
|
6110
|
+
}
|
|
5683
6111
|
if (!zip64UncompressedSize) {
|
|
5684
6112
|
setUint32(headerView, HEADER_OFFSET_UNCOMPRESSED_SIZE, uncompressedSize);
|
|
5685
6113
|
}
|
|
5686
6114
|
if (!zip64CompressedSize) {
|
|
5687
6115
|
setUint32(headerView, HEADER_OFFSET_COMPRESSED_SIZE, compressedSize);
|
|
5688
6116
|
}
|
|
5689
|
-
|
|
5690
|
-
|
|
5691
|
-
|
|
5692
|
-
|
|
5693
|
-
|
|
5694
|
-
|
|
5695
|
-
|
|
5696
|
-
|
|
5697
|
-
|
|
5698
|
-
|
|
5699
|
-
|
|
5700
|
-
|
|
5701
|
-
|
|
5702
|
-
|
|
5703
|
-
|
|
5704
|
-
|
|
5705
|
-
|
|
5706
|
-
|
|
5707
|
-
|
|
5708
|
-
|
|
5709
|
-
|
|
5710
|
-
|
|
5711
|
-
|
|
5712
|
-
directoryOffset += getLength(rawExtraFieldExtendedTimestamp);
|
|
5713
|
-
arraySet(directoryArray, rawExtraFieldNTFS, directoryOffset);
|
|
5714
|
-
directoryOffset += getLength(rawExtraFieldNTFS);
|
|
5715
|
-
arraySet(directoryArray, rawExtraFieldUnix, directoryOffset);
|
|
5716
|
-
directoryOffset += getLength(rawExtraFieldUnix);
|
|
5717
|
-
arraySet(directoryArray, rawExtraField, directoryOffset);
|
|
5718
|
-
directoryOffset += getLength(rawExtraField);
|
|
5719
|
-
arraySet(directoryArray, rawComment, directoryOffset);
|
|
5720
|
-
directoryOffset += getLength(rawComment);
|
|
5721
|
-
if (offset - directoryDiskOffset > writer.availableSize) {
|
|
5722
|
-
writer.availableSize = 0;
|
|
5723
|
-
await writeData(writer, directoryArray.slice(directoryDiskOffset, offset));
|
|
5724
|
-
directoryDiskOffset = offset;
|
|
5725
|
-
}
|
|
5726
|
-
offset = directoryOffset;
|
|
6117
|
+
if ((zip64Offset || zip64DiskNumberStart) && fileEntry.version < VERSION_ZIP64) {
|
|
6118
|
+
setUint16(headerView, HEADER_OFFSET_VERSION, VERSION_ZIP64);
|
|
6119
|
+
}
|
|
6120
|
+
const directoryRecord = createRecordWriter(directoryRecordLength);
|
|
6121
|
+
directoryRecord.uint32(CENTRAL_FILE_HEADER_SIGNATURE);
|
|
6122
|
+
directoryRecord.uint16(versionMadeBy);
|
|
6123
|
+
directoryRecord.bytes(headerArray.subarray(0, HEADER_SIZE - 4 - 2));
|
|
6124
|
+
directoryRecord.uint16(extraFieldLength);
|
|
6125
|
+
directoryRecord.uint16(getLength(rawComment));
|
|
6126
|
+
directoryRecord.uint16(zip64DiskNumberStart ? MAX_16_BITS : diskNumberStart);
|
|
6127
|
+
directoryRecord.uint16(internalFileAttributes);
|
|
6128
|
+
directoryRecord.uint32(externalFileAttributes);
|
|
6129
|
+
directoryRecord.uint32(zip64Offset ? MAX_32_BITS : fileEntryOffset);
|
|
6130
|
+
directoryRecord.bytes(rawFilename);
|
|
6131
|
+
directoryRecord.bytes(rawExtraFieldZip64);
|
|
6132
|
+
directoryRecord.bytes(rawExtraFieldAES);
|
|
6133
|
+
directoryRecord.bytes(rawExtraFieldExtendedTimestamp);
|
|
6134
|
+
directoryRecord.bytes(rawExtraFieldNTFS);
|
|
6135
|
+
directoryRecord.bytes(rawExtraFieldUnix);
|
|
6136
|
+
directoryRecord.bytes(rawExtraField);
|
|
6137
|
+
directoryRecord.bytes(rawComment);
|
|
6138
|
+
arraySet(directoryArray, directoryRecord.array, offset);
|
|
6139
|
+
offset += directoryRecordLength;
|
|
5727
6140
|
if (options.onprogress) {
|
|
5728
6141
|
try {
|
|
5729
6142
|
await options.onprogress(indexFileEntry + 1, files.size, new Entry(fileEntry));
|
|
@@ -5733,36 +6146,53 @@
|
|
|
5733
6146
|
}
|
|
5734
6147
|
}
|
|
5735
6148
|
await writeData(writer, directoryDiskOffset ? directoryArray.slice(directoryDiskOffset) : directoryArray);
|
|
6149
|
+
return { cdStartDiskNumber, cdStartDiskOffset };
|
|
6150
|
+
}
|
|
6151
|
+
|
|
6152
|
+
async function writeEndOfDirectoryRecord(zipWriter, comment, options, cdInfo) {
|
|
6153
|
+
const { writer } = zipWriter;
|
|
6154
|
+
const { cdStartDiskNumber, cdStartDiskOffset } = cdInfo;
|
|
6155
|
+
let { directoryDataLength } = cdInfo;
|
|
6156
|
+
let filesLength = zipWriter.files.size;
|
|
6157
|
+
let diskNumber = cdStartDiskNumber;
|
|
6158
|
+
let directoryOffset = zipWriter.offset - cdStartDiskOffset - (cdStartDiskNumber ? zipWriter.initialOffset : 0);
|
|
5736
6159
|
let lastDiskNumber = writer.diskNumber;
|
|
5737
|
-
|
|
5738
|
-
if (availableSize < END_OF_CENTRAL_DIR_LENGTH) {
|
|
6160
|
+
if (writer.availableSize < END_OF_CENTRAL_DIR_LENGTH) {
|
|
5739
6161
|
lastDiskNumber++;
|
|
5740
6162
|
}
|
|
5741
6163
|
let zip64 = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIP64);
|
|
5742
|
-
if (directoryOffset
|
|
6164
|
+
if (directoryOffset >= MAX_32_BITS || directoryDataLength >= MAX_32_BITS || filesLength >= MAX_16_BITS || lastDiskNumber >= MAX_16_BITS) {
|
|
5743
6165
|
if (zip64 === false) {
|
|
5744
6166
|
throw new Error(ERR_UNSUPPORTED_FORMAT);
|
|
5745
6167
|
} else {
|
|
5746
6168
|
zip64 = true;
|
|
5747
6169
|
}
|
|
5748
6170
|
}
|
|
5749
|
-
const
|
|
5750
|
-
|
|
5751
|
-
|
|
6171
|
+
const commentLength = getLength(comment);
|
|
6172
|
+
if (commentLength > MAX_16_BITS) {
|
|
6173
|
+
throw new Error(ERR_INVALID_COMMENT);
|
|
6174
|
+
}
|
|
6175
|
+
const endOfdirectoryRecord = createRecordWriter(zip64 ? ZIP64_END_OF_CENTRAL_DIR_TOTAL_LENGTH : END_OF_CENTRAL_DIR_LENGTH);
|
|
6176
|
+
if (getLength(endOfdirectoryRecord.array) + commentLength > writer.availableSize) {
|
|
6177
|
+
writer.availableSize = 0;
|
|
6178
|
+
await writeData(writer, new Uint8Array());
|
|
6179
|
+
}
|
|
6180
|
+
lastDiskNumber = writer.diskNumber;
|
|
5752
6181
|
if (zip64) {
|
|
5753
|
-
|
|
5754
|
-
|
|
5755
|
-
|
|
5756
|
-
|
|
5757
|
-
|
|
5758
|
-
|
|
5759
|
-
|
|
5760
|
-
|
|
5761
|
-
|
|
5762
|
-
|
|
5763
|
-
|
|
5764
|
-
|
|
5765
|
-
|
|
6182
|
+
endOfdirectoryRecord.uint32(ZIP64_END_OF_CENTRAL_DIR_SIGNATURE);
|
|
6183
|
+
endOfdirectoryRecord.uint64(44);
|
|
6184
|
+
endOfdirectoryRecord.uint16(45);
|
|
6185
|
+
endOfdirectoryRecord.uint16(45);
|
|
6186
|
+
endOfdirectoryRecord.uint32(lastDiskNumber);
|
|
6187
|
+
endOfdirectoryRecord.uint32(diskNumber);
|
|
6188
|
+
endOfdirectoryRecord.uint64(filesLength);
|
|
6189
|
+
endOfdirectoryRecord.uint64(filesLength);
|
|
6190
|
+
endOfdirectoryRecord.uint64(directoryDataLength);
|
|
6191
|
+
endOfdirectoryRecord.uint64(directoryOffset);
|
|
6192
|
+
endOfdirectoryRecord.uint32(ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIGNATURE);
|
|
6193
|
+
endOfdirectoryRecord.uint32(lastDiskNumber);
|
|
6194
|
+
endOfdirectoryRecord.uint64(BigInt(zipWriter.offset) + BigInt(directoryDataLength) - BigInt(writer.diskOffset) - BigInt(writer.diskNumber ? zipWriter.initialOffset : 0));
|
|
6195
|
+
endOfdirectoryRecord.uint32(lastDiskNumber + 1);
|
|
5766
6196
|
const supportZip64SplitFile = getOptionValue(zipWriter, options, OPTION_SUPPORT_ZIP64_SPLIT_FILE, true);
|
|
5767
6197
|
if (supportZip64SplitFile) {
|
|
5768
6198
|
lastDiskNumber = MAX_16_BITS;
|
|
@@ -5771,29 +6201,40 @@
|
|
|
5771
6201
|
filesLength = MAX_16_BITS;
|
|
5772
6202
|
directoryOffset = MAX_32_BITS;
|
|
5773
6203
|
directoryDataLength = MAX_32_BITS;
|
|
5774
|
-
offset += ZIP64_END_OF_CENTRAL_DIR_LENGTH + ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH;
|
|
5775
|
-
}
|
|
5776
|
-
setUint32(endOfdirectoryView, offset, END_OF_CENTRAL_DIR_SIGNATURE);
|
|
5777
|
-
setUint16(endOfdirectoryView, offset + 4, lastDiskNumber);
|
|
5778
|
-
setUint16(endOfdirectoryView, offset + 6, diskNumber);
|
|
5779
|
-
setUint16(endOfdirectoryView, offset + 8, filesLength);
|
|
5780
|
-
setUint16(endOfdirectoryView, offset + 10, filesLength);
|
|
5781
|
-
setUint32(endOfdirectoryView, offset + 12, directoryDataLength);
|
|
5782
|
-
setUint32(endOfdirectoryView, offset + 16, directoryOffset);
|
|
5783
|
-
const commentLength = getLength(comment);
|
|
5784
|
-
if (commentLength) {
|
|
5785
|
-
if (commentLength <= MAX_16_BITS) {
|
|
5786
|
-
setUint16(endOfdirectoryView, offset + 20, commentLength);
|
|
5787
|
-
} else {
|
|
5788
|
-
throw new Error(ERR_INVALID_COMMENT);
|
|
5789
|
-
}
|
|
5790
6204
|
}
|
|
5791
|
-
|
|
6205
|
+
endOfdirectoryRecord.uint32(END_OF_CENTRAL_DIR_SIGNATURE);
|
|
6206
|
+
endOfdirectoryRecord.uint16(lastDiskNumber);
|
|
6207
|
+
endOfdirectoryRecord.uint16(diskNumber);
|
|
6208
|
+
endOfdirectoryRecord.uint16(filesLength);
|
|
6209
|
+
endOfdirectoryRecord.uint16(filesLength);
|
|
6210
|
+
endOfdirectoryRecord.uint32(directoryDataLength);
|
|
6211
|
+
endOfdirectoryRecord.uint32(directoryOffset);
|
|
6212
|
+
endOfdirectoryRecord.uint16(commentLength);
|
|
6213
|
+
await writeData(writer, endOfdirectoryRecord.array);
|
|
5792
6214
|
if (commentLength) {
|
|
5793
6215
|
await writeData(writer, comment);
|
|
5794
6216
|
}
|
|
5795
6217
|
}
|
|
5796
6218
|
|
|
6219
|
+
function createRecordWriter(length) {
|
|
6220
|
+
const array = new Uint8Array(length);
|
|
6221
|
+
const view = getDataView(array);
|
|
6222
|
+
let offset = 0;
|
|
6223
|
+
return {
|
|
6224
|
+
array,
|
|
6225
|
+
uint8: value => { setUint8(view, offset, value); offset += 1; },
|
|
6226
|
+
uint16: value => { setUint16(view, offset, value); offset += 2; },
|
|
6227
|
+
uint32: value => { setUint32(view, offset, value); offset += 4; },
|
|
6228
|
+
uint64: value => { setBigUint64(view, offset, BigInt(value)); offset += 8; },
|
|
6229
|
+
bytes: value => { arraySet(array, value, offset); offset += getLength(value); },
|
|
6230
|
+
skip: count => offset += count
|
|
6231
|
+
};
|
|
6232
|
+
}
|
|
6233
|
+
|
|
6234
|
+
function getSegmentOffset(zipWriter, writer) {
|
|
6235
|
+
return zipWriter.offset - writer.diskOffset - (writer.diskNumber ? zipWriter.initialOffset : 0);
|
|
6236
|
+
}
|
|
6237
|
+
|
|
5797
6238
|
async function writeData(writer, array) {
|
|
5798
6239
|
const { writable } = writer;
|
|
5799
6240
|
const streamWriter = writable.getWriter();
|
|
@@ -5806,12 +6247,40 @@
|
|
|
5806
6247
|
}
|
|
5807
6248
|
}
|
|
5808
6249
|
|
|
6250
|
+
async function flushBufferedData(readable, writer, signal, onChunkWritten) {
|
|
6251
|
+
const streamWriter = writer.writable.getWriter();
|
|
6252
|
+
try {
|
|
6253
|
+
await readable.pipeTo(new WritableStream({
|
|
6254
|
+
async write(chunk) {
|
|
6255
|
+
await streamWriter.ready;
|
|
6256
|
+
await streamWriter.write(chunk);
|
|
6257
|
+
onChunkWritten(getLength(chunk));
|
|
6258
|
+
}
|
|
6259
|
+
}), { preventClose: true, preventAbort: true, signal });
|
|
6260
|
+
} finally {
|
|
6261
|
+
streamWriter.releaseLock();
|
|
6262
|
+
}
|
|
6263
|
+
}
|
|
6264
|
+
|
|
5809
6265
|
function getTimeNTFS(date) {
|
|
5810
6266
|
if (date) {
|
|
5811
6267
|
return ((BigInt(date.getTime()) + BigInt(11644473600000)) * BigInt(10000));
|
|
5812
6268
|
}
|
|
5813
6269
|
}
|
|
5814
6270
|
|
|
6271
|
+
function getTimeUnix(date) {
|
|
6272
|
+
return Math.floor(date.getTime() / 1000);
|
|
6273
|
+
}
|
|
6274
|
+
|
|
6275
|
+
// the extended timestamp extra field stores dates as signed 32-bit time_t values
|
|
6276
|
+
function inUnixTimeRange(timeUnix) {
|
|
6277
|
+
return timeUnix >= MIN_UNIX_TIME && timeUnix <= MAX_UNIX_TIME;
|
|
6278
|
+
}
|
|
6279
|
+
|
|
6280
|
+
function clampUnixTime(timeUnix) {
|
|
6281
|
+
return Math.min(MAX_UNIX_TIME, Math.max(MIN_UNIX_TIME, timeUnix));
|
|
6282
|
+
}
|
|
6283
|
+
|
|
5815
6284
|
function getOptionValue(zipWriter, options, name, defaultValue) {
|
|
5816
6285
|
const result = options[name] === UNDEFINED_VALUE ? zipWriter.options[name] : options[name];
|
|
5817
6286
|
return result === UNDEFINED_VALUE ? defaultValue : result;
|
|
@@ -5842,7 +6311,7 @@
|
|
|
5842
6311
|
}
|
|
5843
6312
|
|
|
5844
6313
|
function getDataView(array) {
|
|
5845
|
-
return new DataView(array.buffer);
|
|
6314
|
+
return new DataView(array.buffer, array.byteOffset, array.byteLength);
|
|
5846
6315
|
}
|
|
5847
6316
|
|
|
5848
6317
|
function getLength(...arrayLikes) {
|
|
@@ -5858,30 +6327,39 @@
|
|
|
5858
6327
|
uncompressedSize,
|
|
5859
6328
|
compressedSize,
|
|
5860
6329
|
lastModDate,
|
|
6330
|
+
rawLastModDate,
|
|
5861
6331
|
rawFilename,
|
|
5862
6332
|
zip64CompressedSize,
|
|
5863
6333
|
zip64UncompressedSize,
|
|
5864
6334
|
extraFieldLength
|
|
5865
6335
|
}) {
|
|
5866
|
-
const
|
|
6336
|
+
const headerRecord = createRecordWriter(HEADER_SIZE - 4);
|
|
6337
|
+
const headerArray = headerRecord.array;
|
|
5867
6338
|
const headerView = getDataView(headerArray);
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
|
|
6339
|
+
headerRecord.uint16(version);
|
|
6340
|
+
headerRecord.uint16(bitFlag);
|
|
6341
|
+
headerRecord.uint16(compressionMethod);
|
|
6342
|
+
if (rawLastModDate === UNDEFINED_VALUE) {
|
|
6343
|
+
const dateArray = new Uint32Array(1);
|
|
6344
|
+
const dateView = getDataView(dateArray);
|
|
6345
|
+
setUint16(dateView, 0, (((lastModDate.getHours() << 6) | lastModDate.getMinutes()) << 5) | lastModDate.getSeconds() / 2);
|
|
6346
|
+
setUint16(dateView, 2, ((((lastModDate.getFullYear() - 1980) << 4) | (lastModDate.getMonth() + 1)) << 5) | lastModDate.getDate());
|
|
6347
|
+
rawLastModDate = dateArray[0];
|
|
6348
|
+
}
|
|
6349
|
+
headerRecord.uint32(rawLastModDate);
|
|
6350
|
+
headerRecord.skip(4);
|
|
5877
6351
|
if (zip64CompressedSize || compressedSize !== UNDEFINED_VALUE) {
|
|
5878
|
-
|
|
6352
|
+
headerRecord.uint32(zip64CompressedSize ? MAX_32_BITS : compressedSize);
|
|
6353
|
+
} else {
|
|
6354
|
+
headerRecord.skip(4);
|
|
5879
6355
|
}
|
|
5880
6356
|
if (zip64UncompressedSize || uncompressedSize !== UNDEFINED_VALUE) {
|
|
5881
|
-
|
|
6357
|
+
headerRecord.uint32(zip64UncompressedSize ? MAX_32_BITS : uncompressedSize);
|
|
6358
|
+
} else {
|
|
6359
|
+
headerRecord.skip(4);
|
|
5882
6360
|
}
|
|
5883
|
-
|
|
5884
|
-
|
|
6361
|
+
headerRecord.uint16(getLength(rawFilename));
|
|
6362
|
+
headerRecord.uint16(extraFieldLength);
|
|
5885
6363
|
return {
|
|
5886
6364
|
headerArray,
|
|
5887
6365
|
headerView,
|
|
@@ -5982,7 +6460,7 @@
|
|
|
5982
6460
|
// ignored
|
|
5983
6461
|
}
|
|
5984
6462
|
|
|
5985
|
-
const A="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";function g(g){let B;g({wasmURI:()=>(B||(B="data:application/wasm;base64,"+(g=>{g=(g=>{const B=(g=(g+"").replace(/[^A-Za-z0-9+/=]/g,"")).length,E=[];for(let I=0;B>I;I+=4){const B=A.indexOf(g[I])<<18|A.indexOf(g[I+1])<<12|(63&A.indexOf(g[I+2]))<<6|63&A.indexOf(g[I+3]);E.push(B>>16&255),"="!==g[I+2]&&E.push(B>>8&255),"="!==g[I+3]&&E.push(255&B);}return new Uint8Array(E)})(g);let B=new Uint8Array(1024),E=0;for(let A=0;A<g.length;){const C=g[A++];if(128&C){const Q=3+(127&C),D=g[A++]<<8|g[A++],o=E-D;I(E+Q);for(let A=0;Q>A;A++)B[E++]=B[o+A];}else {const Q=C;I(E+Q);for(let I=0;Q>I&&A<g.length;I++)B[E++]=g[A++];}}return (g=>{let B="";const E=g.length;let I=0;for(;E>I+2;I+=3){const E=g[I]<<16|g[I+1]<<8|g[I+2];B+=A[E>>18&63]+A[E>>12&63]+A[E>>6&63]+A[63&E];}const C=E-I;if(1===C){const E=g[I]<<16;B+=A[E>>18&63]+A[E>>12&63]+"==";}else if(2===C){const E=g[I]<<16|g[I+1]<<8;B+=A[E>>18&63]+A[E>>12&63]+A[E>>6&63]+"=";}return B})(new Uint8Array(B.buffer.slice(0,E)));function I(A){if(B.length<A){let g=2*B.length;for(;A>g;)g*=2;const I=new Uint8Array(g);I.set(B.subarray(0,E)),B=I;}}})("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BAGZgAAEAVmAAAQB2YAABAE5gAAEAbmAAAQBeYAABAH5gAAEAQWAAAQBhYAABAFFgAAEAcWAAAQBJYAABAGlgAAEAWWAAAQB5YAABAEVgAAEAZWAAAQBVYAABAHVgAAEATWAAAQBtYAABAF1gAAEAfWAAAQBDYAABAGNgAAEAU2AAAQBzYAABIARMwIArYAABAFtgAAEAe2AAAQBHYAABAGdgAAEAV2AAAQB3YAABAE9gAAEAb2AAAQBfYAABAH9gAAEAROAAMIFEwEJAJOAAAgBk4AACAFTgAAIAVOAAAgB04AACAHTgAAIATOAAAgBM4AACAGzgAAIAbOAAAgBc4AACAFzgAAIAfOAAAgB84AACAELgAAIgBDagAQCgAAEgAAIAUuAAAgBS4AACAHLgAAIAcuAAAgBK4AACAErgAAIAauAAAgBq4AACAFrgAAIAWuAAAgB64AACAHrgAAIARuAAAgBG4AACAGbgAAIAZuAAAgBW4AACAFbgAAIAduAAAgB24AACAE7gAAIATuAAAgBu4AACAG7gAAIAXuAAAgBe4AACAH7gAAIAfuAAAiBA7YBB4AACAGHgAAIAYeAAAgBR4AACAFHgAAIAceAAAgBx4AACAEngAAIASeAAAgBp4AACAGngAAIAWeAAAgBZ4AACAHngAAIAeeAAAgBF4AACAEXgAAIAZeAAAgBl4AACAFXgAAIAVeAAAgB14AACAHXgAAIATeAAAgBN4AACAG3gAAIAbeAAAgBd4AACAF3gAAIAfeAAAgB94AACAEPgAAIAQ+AAAgBj4AACAGPgAAIAU+AAAgBT4AACAHPgAAIAc+AAAgBL4AACAEvgAAIAa+AAAgBr4AACAFvgAAIAW+AAAgB74AACAHvgAAIAR+AAAgBH4AACAGfgAAIAZ+AAAgBX4AACAFfgAAIAd+AAAgB34AACAE/gAAIAT+AAAgBv4AACAG/gAAIAX+AAAgBf4AACAH/gAAIAf+AAAiBBAoBQIAABAEggAAEAWCAAAQBEIAABAFQgAAEATCAAAQBcIIFVgMHAEiAAAQBKIAABAFogAAEARiAAAQBWIAABAE4gAAEAXiAAAQBBIAABAFEgAAEASSAAAQBZIAABAEUgAAEAVSAAAQBNIAABAF0gAAEAQOAAEIBg4AABAFDgAAEAcOAAAQBI4AABAGjgAAEAWOAAAQB44AABIC+K4AAdIECxgEFgABcAQWCBUoBFIAABAEMgAAEARyAAASAvlaABEQBBYIGBAEaggXqAQWAA9QBBYADuAEFgAOcgE92gAAEARGAAAQBCYAABAEZgAAEgQACARWAAAQBDYAABAEdgAAEgL59gAKkgQZAAQWAAiyBBaYBBYABtAEFgD3fAxsLTYMfuYcABIC+rooABIEHUYkABAEEjAAEAQWKAAQEQbAcC4C9CosAS40AO4UALwEGhAAEgQWIgQAEgQEKgQAEgQGSgQAEgIS2ggAEAQuEAAQBDIQABIAF24FHeQTgHQsjhQBfhQXLAhARgAVtBgcJBgoFC4A6uAQNAg4BgAclBJQeC2mFAJCFAIiFAICFAHiBAGiBAFyBBh8BEIAABAEUgAAEARiAAAQBHIAABAEggAAEASiAAAQBMIAABAE4gAAEAUCAAAQBUIAABIEGvQFwgAAEAYCAAAQBoIAABAHAgAAEAeCAAG8DHwtyjQBvgQBrgQBngQBjgQBfgQBbgQBXgQBTgQBPgQBLgQBHgQBDgQE8AYCvAEGAUc0CC22BAMcBBIAAAgEIgAAEgQEzgQJLARCAAA6DAAyBnqyAqmuEACSBB3OBAE8BCIAACIEAGIUADIEIt4MADAEggQCUgDKEgQBrAYCBCC8BBIMADIA/SAoBABAMAEGRIQv/gCUfgMDAgIKxBQgJCQoKgEk3gAABAQ2AAAEBDoAAAQEPgAABARCEAAEBEYQAAQEShAABAROEAAEBFIwAAQEVjAABARaMAAEBF4wAAQEYnAABARmcAAEBGpwAAQEbmwABARyBffsEBAQFBYHB1QEHgAABAQiEAAGAXSqCAAEBCowAAYAnsooAAYEBMJkAAYEBTJkAAYEBaLkAAYEBpLkAAYIDdYABzoUBvI0BqJ0BkLwBgAIbHLwAAQEdvAABgA9PgH05A9AqAQ==")),B)});}
|
|
6463
|
+
const A="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";function g(g){let B;g({wasmURI:()=>(B||(B="data:application/wasm;base64,"+(g=>{g=(g=>{const B=(g=(g+"").replace(/[^A-Za-z0-9+/=]/g,"")).length,E=[];for(let I=0;B>I;I+=4){const B=A.indexOf(g[I])<<18|A.indexOf(g[I+1])<<12|(63&A.indexOf(g[I+2]))<<6|63&A.indexOf(g[I+3]);E.push(B>>16&255),"="!==g[I+2]&&E.push(B>>8&255),"="!==g[I+3]&&E.push(255&B);}return new Uint8Array(E)})(g);let B=new Uint8Array(1024),E=0;for(let A=0;A<g.length;){const C=g[A++];if(128&C){const Q=3+(127&C),Y=g[A++]<<8|g[A++],D=E-Y;I(E+Q);for(let A=0;Q>A;A++)B[E++]=B[D+A];}else {const Q=C;I(E+Q);for(let I=0;Q>I&&A<g.length;I++)B[E++]=g[A++];}}return (g=>{let B="";const E=g.length;let I=0;for(;E>I+2;I+=3){const E=g[I]<<16|g[I+1]<<8|g[I+2];B+=A[E>>18&63]+A[E>>12&63]+A[E>>6&63]+A[63&E];}const C=E-I;if(1===C){const E=g[I]<<16;B+=A[E>>18&63]+A[E>>12&63]+"==";}else if(2===C){const E=g[I]<<16|g[I+1]<<8;B+=A[E>>18&63]+A[E>>12&63]+A[E>>6&63]+"=";}return B})(new Uint8Array(B.buffer.slice(0,E)));function I(A){if(B.length<A){let g=2*B.length;for(;A>g;)g*=2;const I=new Uint8Array(g);I.set(B.subarray(0,E)),B=I;}}})("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BAEVgAAEAZWAAAQBVYAABAHVgAAEATWAAAQBtYAABAF1gAAEAfWAAAQBDYAABAGNgAAEAU2AAAQBzYAABIAN6AIArYAABAFtgAAEAe2AAAQBHYAABAGdgAAEAV2AAAQB3YAABAE9gAAEAb2AAAQBfYAABAH9gAAEAROAAMIFEwEJAJOAAAgBk4AACAFTgAAIAVOAAAgB04AACAHTgAAIATOAAAgBM4AACAGzgAAIAbOAAAgBc4AACAFzgAAIAfOAAAgB84AACAELgAAIgA2LgAQCgAAEgAAIAUuAAAgBS4AACAHLgAAIAcuAAAgBK4AACAErgAAIAauAAAgBq4AACAFrgAAIAWuAAAgB64AACAHrgAAIARuAAAgBG4AACAGbgAAIAZuAAAgBW4AACAFbgAAIAduAAAgB24AACAE7gAAIATuAAAgBu4AACAG7gAAIAXuAAAgBe4AACAH7gAAIAfuAAAiBA7YBB4AACAGHgAAIAYeAAAgBR4AACAFHgAAIAceAAAgBx4AACAEngAAIASeAAAgBp4AACAGngAAIAWeAAAgBZ4AACAHngAAIAeeAAAgBF4AACAEXgAAIAZeAAAgBl4AACAFXgAAIAVeAAAgB14AACAHXgAAIATeAAAgBN4AACAG3gAAIAbeAAAgBd4AACAF3gAAIAfeAAAgB94AACAEPgAAIAQ+AAAgBj4AACAGPgAAIAU+AAAgBT4AACAHPgAAIAc+AAAgBL4AACAEvgAAIAa+AAAgBr4AACAFvgAAIAW+AAAgB74AACAHvgAAIAR+AAAgBH4AACAGfgAAIAZ+AAAgBX4AACAFfgAAIAd+AAAgB34AACAE/gAAIAT+AAAgBv4AACAG/gAAIAX+AAAgBf4AACAH/gAAIAf+AAAiBBAoBQIAABAEggAAEAWCAAAQBEIAABAFQgAAEATCAAAQBcIIFVgMHAEiAAAQBKIAABAFogAAEARiAAAQBWIAABAE4gAAEAXiAAAQBBIAABAFEgAAEASSAAAQBZIAABAEUgAAEAVSAAAQBNIAABAF0gAAEAQOAAEIBg4AABAFDgAAEAcOAAAQBI4AABAGjgAAEAWOAAAQB44AABIC/A4AAdIECxgEFgABcAQWCBUoBFIAABAEMgAAEARyAAAQBAoAABAESgAAEgQYEARqCBeoBBYAD1AEFgAO4AQWAA5yATGqAAAQBEYAABAEJgAAEARmAAASBAAIBFYAABAENgAAEAR2AAASAv26AAqSBBkABBYACLIEFpgEFgAG0AQWAOroDGwtNgxx6hwAEAQKMAASBB1GJAAQBBIwABAEFigAEBEGwHAuAveGLAEuNADuFAC8BBoQABIEFiIEABIEBCoEABIEBkoEABICFfIIABAELhAAEAQyEAASABduBRGIE4B0LI4UAX4UFywIQEYAFbQYHCQYKBQuAN44EDQIOAYAHJQSUHgtphQCQhQCIhQCAhQB4gQBogQBcgQYfARCAAAQBFIAABAEYgAAEARyAAAQBIIAABAEogAAEATCAAAQBOIAABAFAgAAEAVCAAASBBr0BcIAABAGAgAAEAaCAAAQBwIAABAHggABvAx8Lco0Ab4EAa4EAZ4EAY4EAX4EAW4EAV4EAU4EAT4EAS4EAR4EAQ4EBPAGArwBBgE7BAgttgQDHAQSAAAIBCIAABIEBM4ECSwEQgAAOgwAMgZ97gKs6hAAkgQdzgQBPAQiAAAiBABiFAAyBCLeDAAwBIIEAlIAvUoEAawGAgQgvAQSDAAyAPCIKAQAQDABBkSEL/4Ah4AEDgpzlBQgJCQoKgEYggAABAQ2AAAEBDoAAAQEPgAABARCEAAEBEYQAAQEShAABAROEAAEBFIwAAQEVjAABARaMAAEBF4wAAQEYnAABARmcAAEBGpwAAQEbmwABARyBfrkEBAQFBYHCrAEHgAABAQiEAAGAWjqCAAEBCowAAYAkc4oAAYEBMJkAAYEBTJkAAYEBaLkAAYEBpLkAAYIDdYABzoUBvI0BqJ0BkLwBgAIbHLwAAQEdvAABgLyTgH3yA9AqAQ==")),B)});}
|
|
5986
6464
|
|
|
5987
6465
|
/*
|
|
5988
6466
|
Copyright (c) 2025 Gildas Lormeau. All rights reserved.
|
|
@@ -6032,46 +6510,54 @@
|
|
|
6032
6510
|
|
|
6033
6511
|
return new TransformStream({
|
|
6034
6512
|
start() {
|
|
6035
|
-
|
|
6036
|
-
|
|
6037
|
-
|
|
6038
|
-
|
|
6039
|
-
|
|
6040
|
-
|
|
6041
|
-
|
|
6042
|
-
this._last_consumed = wasm.deflate_last_consumed;
|
|
6043
|
-
this._end = wasm.deflate_end;
|
|
6044
|
-
this.streamHandle = wasm.deflate_new();
|
|
6045
|
-
if (type === "gzip") {
|
|
6046
|
-
result = wasm.deflate_init_gzip(this.streamHandle, level);
|
|
6047
|
-
} else if (type === "deflate-raw") {
|
|
6048
|
-
result = wasm.deflate_init_raw(this.streamHandle, level);
|
|
6049
|
-
} else {
|
|
6050
|
-
result = wasm.deflate_init(this.streamHandle, level);
|
|
6513
|
+
try {
|
|
6514
|
+
let result;
|
|
6515
|
+
this.out = malloc(outBufferSize);
|
|
6516
|
+
this.in = malloc(inBufferSize);
|
|
6517
|
+
this.inBufferSize = inBufferSize;
|
|
6518
|
+
if (!this.out || !this.in) {
|
|
6519
|
+
throw new Error("allocation failed");
|
|
6051
6520
|
}
|
|
6052
|
-
|
|
6053
|
-
if (
|
|
6054
|
-
this._process = wasm.
|
|
6055
|
-
this._last_consumed = wasm.
|
|
6056
|
-
this._end = wasm.
|
|
6057
|
-
this.streamHandle = wasm.
|
|
6058
|
-
|
|
6521
|
+
this._scratch = new Uint8Array(outBufferSize);
|
|
6522
|
+
if (isCompress) {
|
|
6523
|
+
this._process = wasm.deflate_process;
|
|
6524
|
+
this._last_consumed = wasm.deflate_last_consumed;
|
|
6525
|
+
this._end = wasm.deflate_end;
|
|
6526
|
+
this.streamHandle = wasm.deflate_new();
|
|
6527
|
+
if (type === "gzip") {
|
|
6528
|
+
result = wasm.deflate_init_gzip(this.streamHandle, level);
|
|
6529
|
+
} else if (type === "deflate-raw") {
|
|
6530
|
+
result = wasm.deflate_init_raw(this.streamHandle, level);
|
|
6531
|
+
} else {
|
|
6532
|
+
result = wasm.deflate_init(this.streamHandle, level);
|
|
6533
|
+
}
|
|
6059
6534
|
} else {
|
|
6060
|
-
|
|
6061
|
-
|
|
6062
|
-
|
|
6063
|
-
|
|
6064
|
-
|
|
6065
|
-
result = wasm.
|
|
6066
|
-
} else if (type === "gzip") {
|
|
6067
|
-
result = wasm.inflate_init_gzip(this.streamHandle);
|
|
6535
|
+
if (type === "deflate64-raw") {
|
|
6536
|
+
this._process = wasm.inflate9_process;
|
|
6537
|
+
this._last_consumed = wasm.inflate9_last_consumed;
|
|
6538
|
+
this._end = wasm.inflate9_end;
|
|
6539
|
+
this.streamHandle = wasm.inflate9_new();
|
|
6540
|
+
result = wasm.inflate9_init_raw(this.streamHandle);
|
|
6068
6541
|
} else {
|
|
6069
|
-
|
|
6542
|
+
this._process = wasm.inflate_process;
|
|
6543
|
+
this._last_consumed = wasm.inflate_last_consumed;
|
|
6544
|
+
this._end = wasm.inflate_end;
|
|
6545
|
+
this.streamHandle = wasm.inflate_new();
|
|
6546
|
+
if (type === "deflate-raw") {
|
|
6547
|
+
result = wasm.inflate_init_raw(this.streamHandle);
|
|
6548
|
+
} else if (type === "gzip") {
|
|
6549
|
+
result = wasm.inflate_init_gzip(this.streamHandle);
|
|
6550
|
+
} else {
|
|
6551
|
+
result = wasm.inflate_init(this.streamHandle);
|
|
6552
|
+
}
|
|
6070
6553
|
}
|
|
6071
6554
|
}
|
|
6072
|
-
|
|
6073
|
-
|
|
6074
|
-
|
|
6555
|
+
if (result !== 0) {
|
|
6556
|
+
throw new Error("init failed:" + result);
|
|
6557
|
+
}
|
|
6558
|
+
} catch (error) {
|
|
6559
|
+
disposeStream(this);
|
|
6560
|
+
throw error;
|
|
6075
6561
|
}
|
|
6076
6562
|
},
|
|
6077
6563
|
transform(chunk, controller) {
|
|
@@ -6088,9 +6574,13 @@
|
|
|
6088
6574
|
if (!this.in || this.inBufferSize < toRead) {
|
|
6089
6575
|
if (this.in && free) {
|
|
6090
6576
|
free(this.in);
|
|
6577
|
+
this.in = 0;
|
|
6091
6578
|
}
|
|
6092
6579
|
this.in = malloc(toRead);
|
|
6093
6580
|
this.inBufferSize = toRead;
|
|
6581
|
+
if (!this.in) {
|
|
6582
|
+
throw new Error("allocation failed");
|
|
6583
|
+
}
|
|
6094
6584
|
}
|
|
6095
6585
|
heap.set(buffer.subarray(offset, offset + toRead), this.in);
|
|
6096
6586
|
const result = process(this.streamHandle, this.in, toRead, out, outBufferSize, 0);
|
|
@@ -6113,15 +6603,7 @@
|
|
|
6113
6603
|
offset += consumed;
|
|
6114
6604
|
}
|
|
6115
6605
|
} catch (error) {
|
|
6116
|
-
|
|
6117
|
-
this._end(this.streamHandle);
|
|
6118
|
-
}
|
|
6119
|
-
if (this.in && free) {
|
|
6120
|
-
free(this.in);
|
|
6121
|
-
}
|
|
6122
|
-
if (this.out && free) {
|
|
6123
|
-
free(this.out);
|
|
6124
|
-
}
|
|
6606
|
+
disposeStream(this);
|
|
6125
6607
|
controller.error(error);
|
|
6126
6608
|
}
|
|
6127
6609
|
},
|
|
@@ -6152,21 +6634,35 @@
|
|
|
6152
6634
|
} catch (error) {
|
|
6153
6635
|
controller.error(error);
|
|
6154
6636
|
} finally {
|
|
6155
|
-
|
|
6156
|
-
|
|
6157
|
-
|
|
6158
|
-
controller.error(new Error("end error:" + result));
|
|
6159
|
-
}
|
|
6160
|
-
}
|
|
6161
|
-
if (this.in && free) {
|
|
6162
|
-
free(this.in);
|
|
6163
|
-
}
|
|
6164
|
-
if (this.out && free) {
|
|
6165
|
-
free(this.out);
|
|
6637
|
+
const result = disposeStream(this);
|
|
6638
|
+
if (result !== 0) {
|
|
6639
|
+
controller.error(new Error("end error:" + result));
|
|
6166
6640
|
}
|
|
6167
6641
|
}
|
|
6642
|
+
},
|
|
6643
|
+
cancel() {
|
|
6644
|
+
// release the stream handle and buffers when the pipeline is aborted,
|
|
6645
|
+
// they would be leaked in the process-lifetime wasm heap otherwise
|
|
6646
|
+
disposeStream(this);
|
|
6168
6647
|
}
|
|
6169
6648
|
});
|
|
6649
|
+
|
|
6650
|
+
function disposeStream(state) {
|
|
6651
|
+
let endResult = 0;
|
|
6652
|
+
if (state.streamHandle && state._end) {
|
|
6653
|
+
endResult = state._end(state.streamHandle);
|
|
6654
|
+
}
|
|
6655
|
+
state.streamHandle = 0;
|
|
6656
|
+
if (state.in && free) {
|
|
6657
|
+
free(state.in);
|
|
6658
|
+
}
|
|
6659
|
+
state.in = 0;
|
|
6660
|
+
if (state.out && free) {
|
|
6661
|
+
free(state.out);
|
|
6662
|
+
}
|
|
6663
|
+
state.out = 0;
|
|
6664
|
+
return endResult;
|
|
6665
|
+
}
|
|
6170
6666
|
}
|
|
6171
6667
|
|
|
6172
6668
|
class CompressionStreamZlib {
|
|
@@ -6342,6 +6838,7 @@
|
|
|
6342
6838
|
exports.BlobWriter = BlobWriter;
|
|
6343
6839
|
exports.Data64URIReader = Data64URIReader;
|
|
6344
6840
|
exports.Data64URIWriter = Data64URIWriter;
|
|
6841
|
+
exports.ERR_AMBIGUOUS_ARCHIVE = ERR_AMBIGUOUS_ARCHIVE;
|
|
6345
6842
|
exports.ERR_BAD_FORMAT = ERR_BAD_FORMAT;
|
|
6346
6843
|
exports.ERR_CENTRAL_DIRECTORY_NOT_FOUND = ERR_CENTRAL_DIRECTORY_NOT_FOUND;
|
|
6347
6844
|
exports.ERR_DUPLICATED_NAME = ERR_DUPLICATED_NAME;
|
|
@@ -6351,6 +6848,7 @@
|
|
|
6351
6848
|
exports.ERR_EXTRAFIELD_ZIP64_NOT_FOUND = ERR_EXTRAFIELD_ZIP64_NOT_FOUND;
|
|
6352
6849
|
exports.ERR_HTTP_RANGE = ERR_HTTP_RANGE;
|
|
6353
6850
|
exports.ERR_INVALID_COMMENT = ERR_INVALID_COMMENT;
|
|
6851
|
+
exports.ERR_INVALID_COMPRESSED_DATA = ERR_INVALID_COMPRESSED_DATA;
|
|
6354
6852
|
exports.ERR_INVALID_ENCRYPTION_STRENGTH = ERR_INVALID_ENCRYPTION_STRENGTH;
|
|
6355
6853
|
exports.ERR_INVALID_ENTRY_COMMENT = ERR_INVALID_ENTRY_COMMENT;
|
|
6356
6854
|
exports.ERR_INVALID_ENTRY_NAME = ERR_INVALID_ENTRY_NAME;
|
|
@@ -6363,8 +6861,9 @@
|
|
|
6363
6861
|
exports.ERR_LOCAL_FILE_HEADER_NOT_FOUND = ERR_LOCAL_FILE_HEADER_NOT_FOUND;
|
|
6364
6862
|
exports.ERR_OVERLAPPING_ENTRY = ERR_OVERLAPPING_ENTRY;
|
|
6365
6863
|
exports.ERR_SPLIT_ZIP_FILE = ERR_SPLIT_ZIP_FILE;
|
|
6864
|
+
exports.ERR_UNDEFINED_READER = ERR_UNDEFINED_READER;
|
|
6366
6865
|
exports.ERR_UNDEFINED_UNCOMPRESSED_SIZE = ERR_UNDEFINED_UNCOMPRESSED_SIZE;
|
|
6367
|
-
exports.ERR_UNSUPPORTED_COMPRESSION = ERR_UNSUPPORTED_COMPRESSION;
|
|
6866
|
+
exports.ERR_UNSUPPORTED_COMPRESSION = ERR_UNSUPPORTED_COMPRESSION$1;
|
|
6368
6867
|
exports.ERR_UNSUPPORTED_ENCRYPTION = ERR_UNSUPPORTED_ENCRYPTION;
|
|
6369
6868
|
exports.ERR_UNSUPPORTED_FORMAT = ERR_UNSUPPORTED_FORMAT;
|
|
6370
6869
|
exports.ERR_ZIP_NOT_EMPTY = ERR_ZIP_NOT_EMPTY;
|