@zip.js/zip.js 2.8.26 → 2.8.29
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/BENCHMARKS.md +168 -0
- package/README.md +2 -2
- package/deno.json +1 -1
- package/dist/zip-core.js +1113 -574
- package/dist/zip-core.min.js +1 -1
- package/dist/zip-fs-core.js +1209 -622
- package/dist/zip-fs-core.min.js +1 -1
- package/dist/zip-fs-native.js +1270 -632
- package/dist/zip-fs-native.min.js +1 -1
- package/dist/zip-fs.js +1347 -686
- package/dist/zip-fs.min.js +1 -1
- package/dist/zip-legacy.js +1114 -575
- package/dist/zip-legacy.min.js +1 -1
- package/dist/zip-module.wasm +0 -0
- package/dist/zip-native.js +1116 -577
- 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 +1193 -631
- package/dist/zip.min.js +1 -1
- package/eslint.config.mjs +6 -1
- package/index-native.cjs +1270 -632
- package/index-native.min.js +1 -1
- package/index.cjs +1347 -686
- 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 +130 -35
- 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 +89 -5
- package/lib/core/streams/zlib-js/zlib-streams.min.js +1 -1
- package/lib/core/streams/zlib-wasm/zlib-streams.js +79 -56
- 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/index.cjs
CHANGED
|
@@ -44,6 +44,7 @@ const CENTRAL_FILE_HEADER_SIGNATURE = 0x02014b50;
|
|
|
44
44
|
const END_OF_CENTRAL_DIR_SIGNATURE = 0x06054b50;
|
|
45
45
|
const ZIP64_END_OF_CENTRAL_DIR_SIGNATURE = 0x06064b50;
|
|
46
46
|
const ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIGNATURE = 0x07064b50;
|
|
47
|
+
const CENTRAL_FILE_HEADER_LENGTH = 46;
|
|
47
48
|
const END_OF_CENTRAL_DIR_LENGTH = 22;
|
|
48
49
|
const ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH = 20;
|
|
49
50
|
const ZIP64_END_OF_CENTRAL_DIR_LENGTH = 56;
|
|
@@ -91,9 +92,11 @@ const VERSION_AES = 0x33;
|
|
|
91
92
|
const DIRECTORY_SIGNATURE = "/";
|
|
92
93
|
|
|
93
94
|
const HEADER_SIZE = 30;
|
|
95
|
+
const HEADER_OFFSET_VERSION = 0;
|
|
94
96
|
const HEADER_OFFSET_SIGNATURE = 10;
|
|
95
97
|
const HEADER_OFFSET_COMPRESSED_SIZE = 14;
|
|
96
98
|
const HEADER_OFFSET_UNCOMPRESSED_SIZE = 18;
|
|
99
|
+
const LOCAL_HEADER_COMMON_OFFSET = 4;
|
|
97
100
|
|
|
98
101
|
const MAX_DATE = new Date(2107, 11, 31);
|
|
99
102
|
const MIN_DATE = new Date(1980, 0, 1);
|
|
@@ -148,6 +151,7 @@ const DEFAULT_CONFIGURATION = {
|
|
|
148
151
|
chunkSize: 64 * 1024,
|
|
149
152
|
maxWorkers,
|
|
150
153
|
terminateWorkerTimeout: 5000,
|
|
154
|
+
workerStarvationTimeout: 5000,
|
|
151
155
|
useWebWorkers: true,
|
|
152
156
|
useCompressionStream: true,
|
|
153
157
|
CompressionStream: typeof CompressionStream != UNDEFINED_TYPE && CompressionStream,
|
|
@@ -170,6 +174,7 @@ function configure(configuration) {
|
|
|
170
174
|
chunkSize,
|
|
171
175
|
maxWorkers,
|
|
172
176
|
terminateWorkerTimeout,
|
|
177
|
+
workerStarvationTimeout,
|
|
173
178
|
useCompressionStream,
|
|
174
179
|
useWebWorkers,
|
|
175
180
|
CompressionStream,
|
|
@@ -185,6 +190,7 @@ function configure(configuration) {
|
|
|
185
190
|
setIfDefined("chunkSize", chunkSize);
|
|
186
191
|
setIfDefined("maxWorkers", maxWorkers);
|
|
187
192
|
setIfDefined("terminateWorkerTimeout", terminateWorkerTimeout);
|
|
193
|
+
setIfDefined("workerStarvationTimeout", workerStarvationTimeout);
|
|
188
194
|
setIfDefined("useCompressionStream", useCompressionStream);
|
|
189
195
|
setIfDefined("useWebWorkers", useWebWorkers);
|
|
190
196
|
setIfDefined("CompressionStream", CompressionStream);
|
|
@@ -199,7 +205,7 @@ function setIfDefined(propertyName, propertyValue) {
|
|
|
199
205
|
}
|
|
200
206
|
}
|
|
201
207
|
|
|
202
|
-
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)}});}
|
|
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:a,Int32Array:c,Map:l,DataView:w,Promise:f,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 w(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],w=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)+w+o[t]+n.k[s.floor(t/20)]|0;w=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]+w|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,f;const h=new ArrayBuffer(o),u=new w(h);let p=0;const d=A;for(e=P.bytes.m(e),f=1;(o||1)>p;f++){for(i=a=t.encrypt(d.concat(e,[f])),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 w=i=0;!n[w];w^=a||1,i=o[i]||1){let o=i^i<<1^i<<2^i<<3^i<<4;o=o>>8^255&o^99,n[w]=o,s[o]=w,l=r[c=r[a=r[w]]];let f=16843009*l^65537*c^257*a^16843008*w,h=257*r[o]^16843008*o;for(let n=0;4>n;n++)t[n][w]=h=h<<24^h>>>8,e[n][o]=f=f<<24^f>>>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],w=i[3],f=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]^w[255&g]^n[S],u=a[y>>>24]^c[m>>16&255]^l[g>>8&255]^w[255&d]^n[S+1],p=a[m>>>24]^c[g>>16&255]^l[d>>8&255]^w[255&y]^n[S+2],g=a[g>>>24]^c[d>>16&255]^l[y>>8&255]^w[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]=f[d>>>24]<<24^f[y>>16&255]<<16^f[m>>8&255]<<8^f[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 f(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 w=new o(t.length-O-(t.length-O)%_);e.enqueue(et(n,t,w,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 w=ot(it(q,n.digest()),0,O);let f=s.length<O?1:0;for(let t=0;O>t;t++)f|=w[t]^c[t];if(f)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 f(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 w=e.length-r;let f;for(n=((t,e)=>{if(e&&e>t.length){const n=t;(t=new o(e)).set(n,0)}return t})(n,s+(w-w%_)),f=0;w-_>=f;f+=_){const t=at(q,ot(e,f,f+_));i&&c.update(t);const r=a.update(t);i||c.update(r),n.set(it(q,r),f+s)}return t.pending=ot(e,f),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),w=at(q,ot(l,0,L[s])),f=at(q,ot(l,L[s],2*L[s])),h=ot(l,2*L[s]);return e.assign(n,{keys:{key:w,$:f,passwordVerification:h},X:new J(new G(w),t.from(H)),Y:new Q(f)}),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=wt(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(wt(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(ft(n,e),0),r=12}else s=new o(t.length),r=0;s.set(ft(n,t),r),e.enqueue(s)}})}}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,n[s]);return n}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,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,f=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(f,p,()=>{let t;o&&!a&&(t=u.signature),o&&!a||!c||(t=new w(h.value.buffer).getUint32(0)),f.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:f,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,f,{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 w(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";let c;try{c=new i(a,n)}catch(t){if(!e)throw t;if(r)c=new r(a,n);else{if(!o)throw t;c=new o(a,n)}}return((t,e)=>{const n=e.writable.getWriter(),s=t.getReader();return(async()=>{try{for(;;){await n.ready;const t=await s.read();if(t.done){await n.close();break}await n.write(t.value)}}catch(t){await(async(t,e)=>{try{await t.abort(e)}catch{}})(n,t),await(async(t,e)=>{try{await t.cancel(e)}catch{}})(s,t)}})(),e.readable})(t,c)}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,w=new d({transform(t,e){t&&t.length&&(a+=t.length,e.enqueue(t))},flush(){e.assign(s,{inputSize:a})}}),f=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(w).pipeThrough(c).pipeThrough(f)})}}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 f(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 f(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:w,inputSize:h,outputSize:u}=e;Tt({type:zt,result:{signature:w,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.wt?n.wt:65536,c="number"==typeof n.ft?n.ft:65536;return new d({start(){try{let n;if(this.ht=Dt(a),this.in=Dt(c),this.ft=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,w=this.yt,f=this.ht,h=this.ut;let u=0;for(;u<i.length;){const e=s.min(i.length-u,32768);if((!this.in||this.ft<e)&&(this.in&&Mt&&(Mt(this.in),this.in=0),this.in=Dt(e),this.ft=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,f,a,0),p=16777215&o;if(p&&(h.set(c.subarray(f,f+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=w(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,w=o>>24&255;if(!t){const t=128&w?w-256:w;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===w||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)}}Et.bt=!0,Lt.bt=!0;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)}});}
|
|
203
209
|
|
|
204
210
|
/*
|
|
205
211
|
Copyright (c) 2022 Gildas Lormeau. All rights reserved.
|
|
@@ -948,37 +954,6 @@ cipher.aes = class {
|
|
|
948
954
|
}
|
|
949
955
|
};
|
|
950
956
|
|
|
951
|
-
/**
|
|
952
|
-
* Random values
|
|
953
|
-
* @namespace
|
|
954
|
-
*/
|
|
955
|
-
const random = {
|
|
956
|
-
/**
|
|
957
|
-
* Generate random words with pure js, cryptographically not as strong & safe as native implementation.
|
|
958
|
-
* @param {TypedArray} typedArray The array to fill.
|
|
959
|
-
* @return {TypedArray} The random values.
|
|
960
|
-
*/
|
|
961
|
-
getRandomValues(typedArray) {
|
|
962
|
-
const words = new Uint32Array(typedArray.buffer);
|
|
963
|
-
const r = (m_w) => {
|
|
964
|
-
let m_z = 0x3ade68b1;
|
|
965
|
-
const mask = 0xffffffff;
|
|
966
|
-
return function () {
|
|
967
|
-
m_z = (0x9069 * (m_z & 0xFFFF) + (m_z >> 0x10)) & mask;
|
|
968
|
-
m_w = (0x4650 * (m_w & 0xFFFF) + (m_w >> 0x10)) & mask;
|
|
969
|
-
const result = ((((m_z << 0x10) + m_w) & mask) / 0x100000000) + .5;
|
|
970
|
-
return result * (Math.random() > .5 ? 1 : -1);
|
|
971
|
-
};
|
|
972
|
-
};
|
|
973
|
-
for (let i = 0, rcache; i < typedArray.length; i += 4) {
|
|
974
|
-
const _r = r((rcache || Math.random()) * 0x100000000);
|
|
975
|
-
rcache = _r() * 0x3ade67b7;
|
|
976
|
-
words[i / 4] = (_r() * 0x100000000) | 0;
|
|
977
|
-
}
|
|
978
|
-
return typedArray;
|
|
979
|
-
}
|
|
980
|
-
};
|
|
981
|
-
|
|
982
957
|
/** @fileOverview CTR mode implementation.
|
|
983
958
|
*
|
|
984
959
|
* Special thanks to Roy Nicholson for pointing out a bug in our
|
|
@@ -1209,12 +1184,15 @@ const GET_RANDOM_VALUES_SUPPORTED = typeof crypto != UNDEFINED_TYPE && typeof cr
|
|
|
1209
1184
|
const ERR_INVALID_PASSWORD = "Invalid password";
|
|
1210
1185
|
const ERR_INVALID_SIGNATURE = "Invalid signature";
|
|
1211
1186
|
const ERR_ABORT_CHECK_PASSWORD = "zipjs-abort-check-password";
|
|
1187
|
+
const ERR_UNSUPPORTED_CRYPTO_API = "Crypto API not supported";
|
|
1212
1188
|
|
|
1213
1189
|
function getRandomValues(array) {
|
|
1214
1190
|
if (GET_RANDOM_VALUES_SUPPORTED) {
|
|
1215
1191
|
return crypto.getRandomValues(array);
|
|
1216
1192
|
} else {
|
|
1217
|
-
|
|
1193
|
+
// all supported runtimes expose crypto.getRandomValues; failing hard beats
|
|
1194
|
+
// silently generating predictable encryption salts
|
|
1195
|
+
throw new Error(ERR_UNSUPPORTED_CRYPTO_API);
|
|
1218
1196
|
}
|
|
1219
1197
|
}
|
|
1220
1198
|
|
|
@@ -1273,13 +1251,12 @@ let DERIVE_BITS_SUPPORTED = CRYPTO_API_SUPPORTED && SUBTLE_API_SUPPORTED && type
|
|
|
1273
1251
|
|
|
1274
1252
|
class AESDecryptionStream extends TransformStream {
|
|
1275
1253
|
|
|
1276
|
-
constructor({ password, rawPassword,
|
|
1254
|
+
constructor({ password, rawPassword, encryptionStrength, checkPasswordOnly }) {
|
|
1277
1255
|
super({
|
|
1278
1256
|
start() {
|
|
1279
1257
|
Object.assign(this, {
|
|
1280
1258
|
ready: new Promise(resolve => this.resolveReady = resolve),
|
|
1281
1259
|
password: encodePassword(password, rawPassword),
|
|
1282
|
-
signed,
|
|
1283
1260
|
strength: encryptionStrength - 1,
|
|
1284
1261
|
pending: new Uint8Array()
|
|
1285
1262
|
});
|
|
@@ -1308,7 +1285,6 @@ class AESDecryptionStream extends TransformStream {
|
|
|
1308
1285
|
},
|
|
1309
1286
|
async flush(controller) {
|
|
1310
1287
|
const {
|
|
1311
|
-
signed,
|
|
1312
1288
|
ctr,
|
|
1313
1289
|
hmac,
|
|
1314
1290
|
pending,
|
|
@@ -1325,13 +1301,15 @@ class AESDecryptionStream extends TransformStream {
|
|
|
1325
1301
|
const decryptedChunk = ctr.update(encryptedChunk);
|
|
1326
1302
|
decryptedChunkArray = fromBits(codecBytes, decryptedChunk);
|
|
1327
1303
|
}
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1304
|
+
const signature = subarray(fromBits(codecBytes, hmac.digest()), 0, SIGNATURE_LENGTH);
|
|
1305
|
+
// branch-free comparison: accumulate the differences instead of
|
|
1306
|
+
// short-circuiting on the first mismatching byte
|
|
1307
|
+
let invalidSignature = pending.length < SIGNATURE_LENGTH ? 1 : 0;
|
|
1308
|
+
for (let indexSignature = 0; indexSignature < SIGNATURE_LENGTH; indexSignature++) {
|
|
1309
|
+
invalidSignature |= signature[indexSignature] ^ originalSignature[indexSignature];
|
|
1310
|
+
}
|
|
1311
|
+
if (invalidSignature) {
|
|
1312
|
+
throw new Error(ERR_INVALID_SIGNATURE);
|
|
1335
1313
|
}
|
|
1336
1314
|
controller.enqueue(decryptedChunkArray);
|
|
1337
1315
|
}
|
|
@@ -1403,11 +1381,11 @@ function append(aesCrypto, input, output, paddingStart, paddingEnd, verifySignat
|
|
|
1403
1381
|
hmac,
|
|
1404
1382
|
pending
|
|
1405
1383
|
} = aesCrypto;
|
|
1406
|
-
const inputLength = input.length - paddingEnd;
|
|
1407
1384
|
if (pending.length) {
|
|
1408
1385
|
input = concat(pending, input);
|
|
1409
|
-
output = expand(output, inputLength - (inputLength % BLOCK_LENGTH));
|
|
1410
1386
|
}
|
|
1387
|
+
const inputLength = input.length - paddingEnd;
|
|
1388
|
+
output = expand(output, paddingStart + (inputLength - (inputLength % BLOCK_LENGTH)));
|
|
1411
1389
|
let offset;
|
|
1412
1390
|
for (offset = 0; offset <= inputLength - BLOCK_LENGTH; offset += BLOCK_LENGTH) {
|
|
1413
1391
|
const inputChunk = toBits(codecBytes, subarray(input, offset, offset + BLOCK_LENGTH));
|
|
@@ -1555,21 +1533,24 @@ const HEADER_LENGTH = 12;
|
|
|
1555
1533
|
|
|
1556
1534
|
class ZipCryptoDecryptionStream extends TransformStream {
|
|
1557
1535
|
|
|
1558
|
-
constructor({ password, passwordVerification, checkPasswordOnly }) {
|
|
1536
|
+
constructor({ password, rawPassword, passwordVerification, checkPasswordOnly }) {
|
|
1559
1537
|
super({
|
|
1560
1538
|
start() {
|
|
1561
1539
|
Object.assign(this, {
|
|
1562
1540
|
password,
|
|
1541
|
+
rawPassword,
|
|
1563
1542
|
passwordVerification
|
|
1564
1543
|
});
|
|
1565
|
-
createKeys(this, password);
|
|
1544
|
+
createKeys(this, password, rawPassword);
|
|
1566
1545
|
},
|
|
1567
1546
|
transform(chunk, controller) {
|
|
1568
1547
|
const zipCrypto = this;
|
|
1569
|
-
if (zipCrypto.password) {
|
|
1548
|
+
if (zipCrypto.password || zipCrypto.rawPassword) {
|
|
1570
1549
|
const decryptedHeader = decrypt(zipCrypto, chunk.subarray(0, HEADER_LENGTH));
|
|
1571
|
-
zipCrypto.password = null;
|
|
1572
|
-
|
|
1550
|
+
zipCrypto.password = zipCrypto.rawPassword = null;
|
|
1551
|
+
// verify the password with a branch-free comparison of the verification byte, mirroring
|
|
1552
|
+
// the constant-time AES HMAC signature check
|
|
1553
|
+
if ((decryptedHeader.at(-1) ^ zipCrypto.passwordVerification) != 0) {
|
|
1573
1554
|
throw new Error(ERR_INVALID_PASSWORD);
|
|
1574
1555
|
}
|
|
1575
1556
|
chunk = chunk.subarray(HEADER_LENGTH);
|
|
@@ -1586,21 +1567,22 @@ class ZipCryptoDecryptionStream extends TransformStream {
|
|
|
1586
1567
|
|
|
1587
1568
|
class ZipCryptoEncryptionStream extends TransformStream {
|
|
1588
1569
|
|
|
1589
|
-
constructor({ password, passwordVerification }) {
|
|
1570
|
+
constructor({ password, rawPassword, passwordVerification }) {
|
|
1590
1571
|
super({
|
|
1591
1572
|
start() {
|
|
1592
1573
|
Object.assign(this, {
|
|
1593
1574
|
password,
|
|
1575
|
+
rawPassword,
|
|
1594
1576
|
passwordVerification
|
|
1595
1577
|
});
|
|
1596
|
-
createKeys(this, password);
|
|
1578
|
+
createKeys(this, password, rawPassword);
|
|
1597
1579
|
},
|
|
1598
1580
|
transform(chunk, controller) {
|
|
1599
1581
|
const zipCrypto = this;
|
|
1600
1582
|
let output;
|
|
1601
1583
|
let offset;
|
|
1602
|
-
if (zipCrypto.password) {
|
|
1603
|
-
zipCrypto.password = null;
|
|
1584
|
+
if (zipCrypto.password || zipCrypto.rawPassword) {
|
|
1585
|
+
zipCrypto.password = zipCrypto.rawPassword = null;
|
|
1604
1586
|
const header = getRandomValues(new Uint8Array(HEADER_LENGTH));
|
|
1605
1587
|
header[HEADER_LENGTH - 1] = zipCrypto.passwordVerification;
|
|
1606
1588
|
output = new Uint8Array(chunk.length + header.length);
|
|
@@ -1635,25 +1617,31 @@ function encrypt(target, input) {
|
|
|
1635
1617
|
return output;
|
|
1636
1618
|
}
|
|
1637
1619
|
|
|
1638
|
-
function createKeys(target, password) {
|
|
1620
|
+
function createKeys(target, password, rawPassword) {
|
|
1639
1621
|
const keys = [0x12345678, 0x23456789, 0x34567890];
|
|
1640
1622
|
Object.assign(target, {
|
|
1641
1623
|
keys,
|
|
1642
1624
|
crcKey0: new Crc32(keys[0]),
|
|
1643
1625
|
crcKey2: new Crc32(keys[2])
|
|
1644
1626
|
});
|
|
1645
|
-
|
|
1646
|
-
|
|
1627
|
+
if (rawPassword) {
|
|
1628
|
+
for (let index = 0; index < rawPassword.length; index++) {
|
|
1629
|
+
updateKeys(target, rawPassword[index]);
|
|
1630
|
+
}
|
|
1631
|
+
} else {
|
|
1632
|
+
for (let index = 0; index < password.length; index++) {
|
|
1633
|
+
updateKeys(target, password.charCodeAt(index));
|
|
1634
|
+
}
|
|
1647
1635
|
}
|
|
1648
1636
|
}
|
|
1649
1637
|
|
|
1650
1638
|
function updateKeys(target, byte) {
|
|
1651
|
-
let [
|
|
1639
|
+
let [, key1] = target.keys;
|
|
1652
1640
|
target.crcKey0.append([byte]);
|
|
1653
|
-
key0 = ~target.crcKey0.get();
|
|
1641
|
+
const key0 = ~target.crcKey0.get();
|
|
1654
1642
|
key1 = getInt32(Math.imul(getInt32(key1 + getInt8(key0)), 134775813) + 1);
|
|
1655
1643
|
target.crcKey2.append([key1 >>> 24]);
|
|
1656
|
-
key2 = ~target.crcKey2.get();
|
|
1644
|
+
const key2 = ~target.crcKey2.get();
|
|
1657
1645
|
target.keys = [key0, key1, key2];
|
|
1658
1646
|
}
|
|
1659
1647
|
|
|
@@ -1700,6 +1688,7 @@ function getInt32(number) {
|
|
|
1700
1688
|
|
|
1701
1689
|
|
|
1702
1690
|
const ERR_INVALID_UNCOMPRESSED_SIZE = "Invalid uncompressed size";
|
|
1691
|
+
const ERR_INVALID_COMPRESSED_DATA = "Invalid compressed data";
|
|
1703
1692
|
const FORMAT_DEFLATE_RAW = "deflate-raw";
|
|
1704
1693
|
const FORMAT_DEFLATE64_RAW = "deflate64-raw";
|
|
1705
1694
|
|
|
@@ -1756,6 +1745,7 @@ class InflateStream extends TransformStream {
|
|
|
1756
1745
|
}
|
|
1757
1746
|
if (compressed) {
|
|
1758
1747
|
readable = pipeThroughCommpressionStream(readable, useCompressionStream, { chunkSize, deflate64 }, DecompressionStream, DecompressionStreamZlib, DecompressionStream);
|
|
1748
|
+
readable = mapInflateStreamError(readable);
|
|
1759
1749
|
}
|
|
1760
1750
|
if ((!encrypted || zipCrypto) && signed) {
|
|
1761
1751
|
crc32Stream = new Crc32Stream();
|
|
@@ -1784,14 +1774,15 @@ function setReadable(stream, readable, flush) {
|
|
|
1784
1774
|
function pipeThroughCommpressionStream(readable, useCompressionStream, options, CompressionStreamNative, CompressionStreamZlib, CompressionStream) {
|
|
1785
1775
|
const Stream = useCompressionStream && CompressionStreamNative ? CompressionStreamNative : CompressionStreamZlib || CompressionStream;
|
|
1786
1776
|
const format = options.deflate64 ? FORMAT_DEFLATE64_RAW : FORMAT_DEFLATE_RAW;
|
|
1777
|
+
let codecStream;
|
|
1787
1778
|
try {
|
|
1788
|
-
|
|
1779
|
+
codecStream = new Stream(format, options);
|
|
1789
1780
|
} catch (error) {
|
|
1790
1781
|
if (useCompressionStream) {
|
|
1791
1782
|
if (CompressionStreamZlib) {
|
|
1792
|
-
|
|
1783
|
+
codecStream = new CompressionStreamZlib(format, options);
|
|
1793
1784
|
} else if (CompressionStream) {
|
|
1794
|
-
|
|
1785
|
+
codecStream = new CompressionStream(format, options);
|
|
1795
1786
|
} else {
|
|
1796
1787
|
throw error;
|
|
1797
1788
|
}
|
|
@@ -1799,13 +1790,93 @@ function pipeThroughCommpressionStream(readable, useCompressionStream, options,
|
|
|
1799
1790
|
throw error;
|
|
1800
1791
|
}
|
|
1801
1792
|
}
|
|
1802
|
-
|
|
1793
|
+
// The native CompressionStream/DecompressionStream and the pure-JS zlib port do not signal
|
|
1794
|
+
// backpressure on their writable side (their `ready` never pends), so a plain pipeThrough drains
|
|
1795
|
+
// the whole source into them and peak memory grows with the entry size. Awaiting each write()
|
|
1796
|
+
// paces the source to the codec's consumption rate, keeping streaming memory bounded. The WASM
|
|
1797
|
+
// codec already backpressures, so this is a no-op cost for it.
|
|
1798
|
+
return pipeThroughBackpressured(readable, codecStream);
|
|
1803
1799
|
}
|
|
1804
1800
|
|
|
1805
1801
|
function pipeThrough(readable, transformStream) {
|
|
1806
1802
|
return readable.pipeThrough(transformStream);
|
|
1807
1803
|
}
|
|
1808
1804
|
|
|
1805
|
+
// Like readable.pipeThrough(transformStream), but drives the writable side manually and awaits each
|
|
1806
|
+
// write() so that a codec which under-reports backpressure cannot pull the whole source into memory.
|
|
1807
|
+
// Errors propagate in both directions: a source error aborts the codec; a downstream cancel/error
|
|
1808
|
+
// (surfaced through the codec's writable rejecting) cancels the source.
|
|
1809
|
+
function pipeThroughBackpressured(readable, transformStream) {
|
|
1810
|
+
const writer = transformStream.writable.getWriter();
|
|
1811
|
+
const reader = readable.getReader();
|
|
1812
|
+
pump();
|
|
1813
|
+
return transformStream.readable;
|
|
1814
|
+
|
|
1815
|
+
async function pump() {
|
|
1816
|
+
try {
|
|
1817
|
+
for (; ;) {
|
|
1818
|
+
await writer.ready;
|
|
1819
|
+
const result = await reader.read();
|
|
1820
|
+
if (result.done) {
|
|
1821
|
+
await writer.close();
|
|
1822
|
+
break;
|
|
1823
|
+
}
|
|
1824
|
+
await writer.write(result.value);
|
|
1825
|
+
}
|
|
1826
|
+
} catch (error) {
|
|
1827
|
+
await abort(writer, error);
|
|
1828
|
+
await cancel(reader, error);
|
|
1829
|
+
}
|
|
1830
|
+
}
|
|
1831
|
+
}
|
|
1832
|
+
|
|
1833
|
+
async function abort(writer, error) {
|
|
1834
|
+
try {
|
|
1835
|
+
await writer.abort(error);
|
|
1836
|
+
} catch {
|
|
1837
|
+
// the writable may already be errored/closed
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
|
|
1841
|
+
async function cancel(reader, error) {
|
|
1842
|
+
try {
|
|
1843
|
+
await reader.cancel(error);
|
|
1844
|
+
} catch {
|
|
1845
|
+
// the readable may already be errored/closed
|
|
1846
|
+
}
|
|
1847
|
+
}
|
|
1848
|
+
|
|
1849
|
+
// DecompressionStream implementations can fail with a message-less TypeError on malformed
|
|
1850
|
+
// input; give these errors an identifiable message (errors raised by the other stages of
|
|
1851
|
+
// the pipeline, e.g. ERR_INVALID_PASSWORD, always carry a message and pass through as-is)
|
|
1852
|
+
function mapInflateStreamError(readable) {
|
|
1853
|
+
const reader = readable.getReader();
|
|
1854
|
+
return new ReadableStream({
|
|
1855
|
+
async pull(controller) {
|
|
1856
|
+
let result;
|
|
1857
|
+
try {
|
|
1858
|
+
result = await reader.read();
|
|
1859
|
+
} catch (error) {
|
|
1860
|
+
if (error && error.message) {
|
|
1861
|
+
throw error;
|
|
1862
|
+
}
|
|
1863
|
+
const mappedError = new Error(ERR_INVALID_COMPRESSED_DATA);
|
|
1864
|
+
mappedError.cause = error;
|
|
1865
|
+
throw mappedError;
|
|
1866
|
+
}
|
|
1867
|
+
const { value, done } = result;
|
|
1868
|
+
if (done) {
|
|
1869
|
+
controller.close();
|
|
1870
|
+
} else {
|
|
1871
|
+
controller.enqueue(value);
|
|
1872
|
+
}
|
|
1873
|
+
},
|
|
1874
|
+
cancel(reason) {
|
|
1875
|
+
return reader.cancel(reason);
|
|
1876
|
+
}
|
|
1877
|
+
});
|
|
1878
|
+
}
|
|
1879
|
+
|
|
1809
1880
|
/*
|
|
1810
1881
|
Copyright (c) 2022 Gildas Lormeau. All rights reserved.
|
|
1811
1882
|
|
|
@@ -1835,6 +1906,7 @@ function pipeThrough(readable, transformStream) {
|
|
|
1835
1906
|
*/
|
|
1836
1907
|
|
|
1837
1908
|
|
|
1909
|
+
const DEFAULT_CHUNK_SIZE$1 = 64 * 1024;
|
|
1838
1910
|
const MESSAGE_EVENT_TYPE = "message";
|
|
1839
1911
|
const MESSAGE_START = "start";
|
|
1840
1912
|
const MESSAGE_PULL = "pull";
|
|
@@ -1903,6 +1975,9 @@ class ChunkStream extends TransformStream {
|
|
|
1903
1975
|
|
|
1904
1976
|
constructor(chunkSize) {
|
|
1905
1977
|
let pendingChunk;
|
|
1978
|
+
if (!(chunkSize >= 1)) {
|
|
1979
|
+
chunkSize = DEFAULT_CHUNK_SIZE$1;
|
|
1980
|
+
}
|
|
1906
1981
|
super({
|
|
1907
1982
|
transform,
|
|
1908
1983
|
flush(controller) {
|
|
@@ -1920,12 +1995,12 @@ class ChunkStream extends TransformStream {
|
|
|
1920
1995
|
chunk = newChunk;
|
|
1921
1996
|
pendingChunk = null;
|
|
1922
1997
|
}
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
pendingChunk = chunk;
|
|
1998
|
+
let offset = 0;
|
|
1999
|
+
while (chunk.length - offset > chunkSize) {
|
|
2000
|
+
controller.enqueue(chunk.slice(offset, offset + chunkSize));
|
|
2001
|
+
offset += chunkSize;
|
|
1928
2002
|
}
|
|
2003
|
+
pendingChunk = offset ? chunk.slice(offset) : chunk;
|
|
1929
2004
|
}
|
|
1930
2005
|
}
|
|
1931
2006
|
}
|
|
@@ -1960,8 +2035,10 @@ class ChunkStream extends TransformStream {
|
|
|
1960
2035
|
|
|
1961
2036
|
|
|
1962
2037
|
const MODULE_WORKER_OPTIONS = { type: "module" };
|
|
2038
|
+
const ERROR_EVENT_TYPE = "error";
|
|
2039
|
+
const MESSAGE_ERROR_EVENT_TYPE = "messageerror";
|
|
1963
2040
|
|
|
1964
|
-
let webWorkerSupported, webWorkerURI, webWorkerOptions;
|
|
2041
|
+
let webWorkerSupported, webWorkerSource, webWorkerURI, webWorkerOptions;
|
|
1965
2042
|
let transferStreamsSupported = true;
|
|
1966
2043
|
try {
|
|
1967
2044
|
transferStreamsSupported = typeof structuredClone == FUNCTION_TYPE && structuredClone(new DOMException("", "AbortError")).code !== UNDEFINED_VALUE;
|
|
@@ -1980,8 +2057,9 @@ class CodecWorker {
|
|
|
1980
2057
|
const { signal } = streamOptions;
|
|
1981
2058
|
Object.assign(workerData, {
|
|
1982
2059
|
busy: true,
|
|
2060
|
+
generation: (workerData.generation || 0) + 1,
|
|
1983
2061
|
readable: readable
|
|
1984
|
-
.pipeThrough(new ChunkStream(config
|
|
2062
|
+
.pipeThrough(new ChunkStream(getChunkSize(config)))
|
|
1985
2063
|
.pipeThrough(new ProgressWatcherStream(streamOptions), { signal }),
|
|
1986
2064
|
writable,
|
|
1987
2065
|
options: Object.assign({}, options),
|
|
@@ -2004,15 +2082,17 @@ class CodecWorker {
|
|
|
2004
2082
|
});
|
|
2005
2083
|
},
|
|
2006
2084
|
onTaskFinished() {
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2085
|
+
if (workerData.busy) {
|
|
2086
|
+
const { resolveTerminated } = workerData;
|
|
2087
|
+
if (resolveTerminated) {
|
|
2088
|
+
workerData.resolveTerminated = null;
|
|
2089
|
+
workerData.terminated = true;
|
|
2090
|
+
workerData.worker.terminate();
|
|
2091
|
+
resolveTerminated();
|
|
2092
|
+
}
|
|
2093
|
+
workerData.busy = false;
|
|
2094
|
+
onTaskFinished(workerData);
|
|
2013
2095
|
}
|
|
2014
|
-
workerData.busy = false;
|
|
2015
|
-
onTaskFinished(workerData);
|
|
2016
2096
|
}
|
|
2017
2097
|
});
|
|
2018
2098
|
if (webWorkerSupported === UNDEFINED_VALUE) {
|
|
@@ -2081,6 +2161,7 @@ function createWebWorkerInterface(workerData, config) {
|
|
|
2081
2161
|
}
|
|
2082
2162
|
Object.assign(workerData, {
|
|
2083
2163
|
worker,
|
|
2164
|
+
terminated: false,
|
|
2084
2165
|
interface: {
|
|
2085
2166
|
run: () => runWebWorker(workerData, { chunkSize, wasmURI, baseURI })
|
|
2086
2167
|
}
|
|
@@ -2096,7 +2177,15 @@ async function runWorker$1({ options, readable, writable, onTaskFinished }, conf
|
|
|
2096
2177
|
try {
|
|
2097
2178
|
await initModule$1(config);
|
|
2098
2179
|
} catch {
|
|
2099
|
-
|
|
2180
|
+
// The WASM module failed to load. Fall back to the native CompressionStream only if the
|
|
2181
|
+
// zlib codec that would otherwise run depends on that module; a self-contained codec
|
|
2182
|
+
// supplied through config (e.g. the pure-JS port) stays usable and is kept as requested.
|
|
2183
|
+
const ZlibStream = options.codecType.startsWith(CODEC_DEFLATE) ?
|
|
2184
|
+
config.CompressionStreamZlib :
|
|
2185
|
+
config.DecompressionStreamZlib;
|
|
2186
|
+
if (!ZlibStream || ZlibStream.requiresModule) {
|
|
2187
|
+
options.useCompressionStream = true;
|
|
2188
|
+
}
|
|
2100
2189
|
}
|
|
2101
2190
|
}
|
|
2102
2191
|
codecStream = new CodecStream(options, config);
|
|
@@ -2135,37 +2224,85 @@ async function runWebWorker(workerData, config) {
|
|
|
2135
2224
|
result
|
|
2136
2225
|
});
|
|
2137
2226
|
const { readable, options } = workerData;
|
|
2138
|
-
const { writable, closed } = watchClosedStream(workerData.writable);
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2227
|
+
const { writable, closed, abortPipe } = watchClosedStream(workerData.writable);
|
|
2228
|
+
let streamsTransferred;
|
|
2229
|
+
try {
|
|
2230
|
+
streamsTransferred = sendMessage({
|
|
2231
|
+
type: MESSAGE_START,
|
|
2232
|
+
options,
|
|
2233
|
+
config,
|
|
2234
|
+
readable,
|
|
2235
|
+
writable
|
|
2236
|
+
}, workerData);
|
|
2237
|
+
} catch (error) {
|
|
2238
|
+
abortPipe();
|
|
2239
|
+
try {
|
|
2240
|
+
await closed;
|
|
2241
|
+
} catch {
|
|
2242
|
+
// ignored
|
|
2243
|
+
}
|
|
2244
|
+
workerData.onTaskFinished();
|
|
2245
|
+
throw error;
|
|
2246
|
+
}
|
|
2146
2247
|
if (!streamsTransferred) {
|
|
2147
2248
|
Object.assign(workerData, {
|
|
2148
2249
|
reader: readable.getReader(),
|
|
2149
2250
|
writer: writable.getWriter()
|
|
2150
2251
|
});
|
|
2151
2252
|
}
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
await
|
|
2253
|
+
try {
|
|
2254
|
+
const resultValue = await result;
|
|
2255
|
+
await closeWritable();
|
|
2256
|
+
await closed;
|
|
2257
|
+
return resultValue;
|
|
2258
|
+
} catch (error) {
|
|
2259
|
+
await closeWritable();
|
|
2260
|
+
// unblock the pipe watcher if the worker died before closing its end of the stream
|
|
2261
|
+
abortPipe();
|
|
2262
|
+
try {
|
|
2263
|
+
await closed;
|
|
2264
|
+
} catch {
|
|
2265
|
+
// ignored
|
|
2266
|
+
}
|
|
2267
|
+
throw error;
|
|
2268
|
+
}
|
|
2269
|
+
|
|
2270
|
+
async function closeWritable() {
|
|
2271
|
+
if (!streamsTransferred && !writable.locked) {
|
|
2272
|
+
try {
|
|
2273
|
+
await writable.getWriter().close();
|
|
2274
|
+
} catch {
|
|
2275
|
+
// ignored
|
|
2276
|
+
}
|
|
2277
|
+
}
|
|
2155
2278
|
}
|
|
2156
|
-
await closed;
|
|
2157
|
-
return resultValue;
|
|
2158
2279
|
}
|
|
2159
2280
|
|
|
2160
2281
|
function watchClosedStream(writableSource) {
|
|
2282
|
+
const abortController = new AbortController();
|
|
2161
2283
|
const { writable, readable } = new TransformStream();
|
|
2162
|
-
const closed = readable.pipeTo(writableSource, { preventClose: true });
|
|
2163
|
-
|
|
2284
|
+
const closed = readable.pipeTo(writableSource, { preventClose: true, preventAbort: true, signal: abortController.signal });
|
|
2285
|
+
// the pipe can fail before `closed` is awaited (e.g. the destination write fails);
|
|
2286
|
+
// mark the rejection as handled so it cannot kill the process in the meantime
|
|
2287
|
+
closed.catch(() => { });
|
|
2288
|
+
return { writable, closed, abortPipe: () => abortController.abort() };
|
|
2289
|
+
}
|
|
2290
|
+
|
|
2291
|
+
function terminateWorker$1(workerData) {
|
|
2292
|
+
const { worker } = workerData;
|
|
2293
|
+
if (worker) {
|
|
2294
|
+
try {
|
|
2295
|
+
worker.terminate();
|
|
2296
|
+
} catch {
|
|
2297
|
+
// ignored
|
|
2298
|
+
}
|
|
2299
|
+
}
|
|
2300
|
+
workerData.interface = null;
|
|
2164
2301
|
}
|
|
2165
2302
|
|
|
2166
2303
|
function getWebWorker(url, baseURI, workerData, isModuleType, useBlobURI = true) {
|
|
2167
2304
|
let worker, resolvedURI, resolvedOptions;
|
|
2168
|
-
if (webWorkerURI === UNDEFINED_VALUE) {
|
|
2305
|
+
if (webWorkerURI === UNDEFINED_VALUE || webWorkerSource !== url) {
|
|
2169
2306
|
// deno-lint-ignore valid-typeof
|
|
2170
2307
|
const isFunctionURI = typeof url == FUNCTION_TYPE;
|
|
2171
2308
|
if (isFunctionURI) {
|
|
@@ -2222,16 +2359,36 @@ function getWebWorker(url, baseURI, workerData, isModuleType, useBlobURI = true)
|
|
|
2222
2359
|
}
|
|
2223
2360
|
}
|
|
2224
2361
|
}
|
|
2362
|
+
webWorkerSource = url;
|
|
2225
2363
|
webWorkerURI = resolvedURI;
|
|
2226
2364
|
webWorkerOptions = resolvedOptions;
|
|
2227
2365
|
} else {
|
|
2228
2366
|
worker = new Worker(webWorkerURI, webWorkerOptions);
|
|
2229
2367
|
}
|
|
2230
2368
|
worker.addEventListener(MESSAGE_EVENT_TYPE, event => onMessage(event, workerData));
|
|
2369
|
+
worker.addEventListener(ERROR_EVENT_TYPE, event => onWorkerError(event, workerData));
|
|
2370
|
+
worker.addEventListener(MESSAGE_ERROR_EVENT_TYPE, event => onWorkerError(event, workerData));
|
|
2231
2371
|
return worker;
|
|
2232
2372
|
}
|
|
2233
2373
|
|
|
2234
|
-
function
|
|
2374
|
+
function onWorkerError(event, workerData) {
|
|
2375
|
+
if (event.preventDefault) {
|
|
2376
|
+
event.preventDefault();
|
|
2377
|
+
}
|
|
2378
|
+
const { rejectResult, writer, onTaskFinished } = workerData;
|
|
2379
|
+
// the worker is unusable (e.g. its script failed to load); terminate it and
|
|
2380
|
+
// fail the current task instead of letting it hang forever
|
|
2381
|
+
terminateWorker$1(workerData);
|
|
2382
|
+
if (rejectResult) {
|
|
2383
|
+
rejectResult(event.error || new Error(event.message || ERROR_EVENT_TYPE));
|
|
2384
|
+
if (writer) {
|
|
2385
|
+
writer.releaseLock();
|
|
2386
|
+
}
|
|
2387
|
+
onTaskFinished();
|
|
2388
|
+
}
|
|
2389
|
+
}
|
|
2390
|
+
|
|
2391
|
+
function sendMessage(message, { worker, writer, transferStreams }) {
|
|
2235
2392
|
try {
|
|
2236
2393
|
const { value, readable, writable } = message;
|
|
2237
2394
|
const transferables = [];
|
|
@@ -2265,14 +2422,16 @@ function sendMessage(message, { worker, writer, onTaskFinished, transferStreams
|
|
|
2265
2422
|
if (writer) {
|
|
2266
2423
|
writer.releaseLock();
|
|
2267
2424
|
}
|
|
2268
|
-
onTaskFinished();
|
|
2269
2425
|
throw error;
|
|
2270
2426
|
}
|
|
2271
2427
|
}
|
|
2272
2428
|
|
|
2273
2429
|
async function onMessage({ data }, workerData) {
|
|
2274
2430
|
const { type, value, messageId, result, error } = data;
|
|
2275
|
-
const { reader, writer, resolveResult, rejectResult, onTaskFinished } = workerData;
|
|
2431
|
+
const { reader, writer, resolveResult, rejectResult, onTaskFinished, generation } = workerData;
|
|
2432
|
+
// continuations below can settle after the worker slot has been reassigned to a new
|
|
2433
|
+
// task (e.g. a pending pull read failing late); they must not touch the new task
|
|
2434
|
+
const stale = () => workerData.generation != generation;
|
|
2276
2435
|
try {
|
|
2277
2436
|
if (error) {
|
|
2278
2437
|
const { message, stack, code, name, outputSize } = error;
|
|
@@ -2282,23 +2441,32 @@ async function onMessage({ data }, workerData) {
|
|
|
2282
2441
|
} else {
|
|
2283
2442
|
if (type == MESSAGE_PULL) {
|
|
2284
2443
|
const { value, done } = await reader.read();
|
|
2285
|
-
|
|
2444
|
+
if (!stale()) {
|
|
2445
|
+
sendMessage({ type: MESSAGE_DATA, value, done, messageId }, workerData);
|
|
2446
|
+
}
|
|
2286
2447
|
}
|
|
2287
2448
|
if (type == MESSAGE_DATA) {
|
|
2288
2449
|
await writer.ready;
|
|
2289
2450
|
await writer.write(new Uint8Array(value));
|
|
2290
|
-
|
|
2451
|
+
if (!stale()) {
|
|
2452
|
+
sendMessage({ type: MESSAGE_ACK_DATA, messageId }, workerData);
|
|
2453
|
+
}
|
|
2291
2454
|
}
|
|
2292
2455
|
if (type == MESSAGE_CLOSE) {
|
|
2293
2456
|
close(null, result);
|
|
2294
2457
|
}
|
|
2295
2458
|
}
|
|
2296
2459
|
} catch (error) {
|
|
2297
|
-
|
|
2298
|
-
|
|
2460
|
+
if (!stale()) {
|
|
2461
|
+
terminateWorker$1(workerData);
|
|
2462
|
+
close(error);
|
|
2463
|
+
}
|
|
2299
2464
|
}
|
|
2300
2465
|
|
|
2301
2466
|
function close(error, result) {
|
|
2467
|
+
if (stale()) {
|
|
2468
|
+
return;
|
|
2469
|
+
}
|
|
2302
2470
|
if (error) {
|
|
2303
2471
|
rejectResult(error);
|
|
2304
2472
|
} else {
|
|
@@ -2342,6 +2510,8 @@ async function onMessage({ data }, workerData) {
|
|
|
2342
2510
|
|
|
2343
2511
|
let pool = [];
|
|
2344
2512
|
const pendingRequests = [];
|
|
2513
|
+
let starvationTimeout;
|
|
2514
|
+
let starvationDelay;
|
|
2345
2515
|
|
|
2346
2516
|
let indexWorker = 0;
|
|
2347
2517
|
|
|
@@ -2368,14 +2538,20 @@ async function runWorker(stream, workerOptions) {
|
|
|
2368
2538
|
pool.push(workerData);
|
|
2369
2539
|
return new CodecWorker(workerData, stream, workerOptions, onTaskFinished);
|
|
2370
2540
|
} else {
|
|
2371
|
-
return new Promise(resolve =>
|
|
2541
|
+
return new Promise(resolve => {
|
|
2542
|
+
pendingRequests.push({ resolve, stream, workerOptions });
|
|
2543
|
+
starvationDelay = config.workerStarvationTimeout;
|
|
2544
|
+
armStarvationTimeout();
|
|
2545
|
+
});
|
|
2372
2546
|
}
|
|
2373
2547
|
}
|
|
2374
2548
|
|
|
2375
2549
|
function onTaskFinished(workerData) {
|
|
2550
|
+
clearStarvationTimeout();
|
|
2376
2551
|
if (pendingRequests.length) {
|
|
2377
2552
|
const [{ resolve, stream, workerOptions }] = pendingRequests.splice(0, 1);
|
|
2378
2553
|
resolve(new CodecWorker(workerData, stream, workerOptions, onTaskFinished));
|
|
2554
|
+
armStarvationTimeout();
|
|
2379
2555
|
} else if (workerData.worker) {
|
|
2380
2556
|
clearTerminateTimeout(workerData);
|
|
2381
2557
|
terminateWorker(workerData, workerOptions);
|
|
@@ -2385,6 +2561,34 @@ async function runWorker(stream, workerOptions) {
|
|
|
2385
2561
|
}
|
|
2386
2562
|
}
|
|
2387
2563
|
|
|
2564
|
+
function armStarvationTimeout() {
|
|
2565
|
+
if (!starvationTimeout && pendingRequests.length && Number.isFinite(starvationDelay) && starvationDelay >= 0) {
|
|
2566
|
+
starvationTimeout = setTimeout(onWorkerStarvation, starvationDelay);
|
|
2567
|
+
}
|
|
2568
|
+
}
|
|
2569
|
+
|
|
2570
|
+
function clearStarvationTimeout() {
|
|
2571
|
+
if (starvationTimeout) {
|
|
2572
|
+
clearTimeout(starvationTimeout);
|
|
2573
|
+
starvationTimeout = null;
|
|
2574
|
+
}
|
|
2575
|
+
}
|
|
2576
|
+
|
|
2577
|
+
function onWorkerStarvation() {
|
|
2578
|
+
starvationTimeout = null;
|
|
2579
|
+
if (pendingRequests.length) {
|
|
2580
|
+
const [{ resolve, stream, workerOptions }] = pendingRequests.splice(0, 1);
|
|
2581
|
+
const inlineWorkerOptions = Object.assign({}, workerOptions, { useWebWorkers: false, workerURI: UNDEFINED_VALUE });
|
|
2582
|
+
resolve(new CodecWorker({}, stream, inlineWorkerOptions, onInlineTaskFinished));
|
|
2583
|
+
armStarvationTimeout();
|
|
2584
|
+
}
|
|
2585
|
+
}
|
|
2586
|
+
|
|
2587
|
+
function onInlineTaskFinished() {
|
|
2588
|
+
clearStarvationTimeout();
|
|
2589
|
+
armStarvationTimeout();
|
|
2590
|
+
}
|
|
2591
|
+
|
|
2388
2592
|
function terminateWorker(workerData, workerOptions) {
|
|
2389
2593
|
const { config } = workerOptions;
|
|
2390
2594
|
const { terminateWorkerTimeout } = config;
|
|
@@ -2455,6 +2659,7 @@ const ERR_WRITER_NOT_INITIALIZED = "Writer not initialized";
|
|
|
2455
2659
|
|
|
2456
2660
|
const CONTENT_TYPE_TEXT_PLAIN = "text/plain";
|
|
2457
2661
|
const HTTP_HEADER_CONTENT_LENGTH = "Content-Length";
|
|
2662
|
+
const HTTP_HEADER_CONTENT_ENCODING = "Content-Encoding";
|
|
2458
2663
|
const HTTP_HEADER_CONTENT_RANGE = "Content-Range";
|
|
2459
2664
|
const HTTP_HEADER_ACCEPT_RANGES = "Accept-Ranges";
|
|
2460
2665
|
const HTTP_HEADER_RANGE = "Range";
|
|
@@ -2579,7 +2784,7 @@ class Data64URIWriter extends Writer {
|
|
|
2579
2784
|
|
|
2580
2785
|
writeUint8Array(array) {
|
|
2581
2786
|
const writer = this;
|
|
2582
|
-
let indexArray
|
|
2787
|
+
let indexArray;
|
|
2583
2788
|
let dataString = writer.pending;
|
|
2584
2789
|
const delta = writer.pending.length;
|
|
2585
2790
|
writer.pending = "";
|
|
@@ -2589,12 +2794,10 @@ class Data64URIWriter extends Writer {
|
|
|
2589
2794
|
for (; indexArray < array.length; indexArray++) {
|
|
2590
2795
|
writer.pending += String.fromCharCode(array[indexArray]);
|
|
2591
2796
|
}
|
|
2592
|
-
if (dataString.length) {
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
writer.pending += dataString;
|
|
2597
|
-
}
|
|
2797
|
+
if (dataString.length > 2) {
|
|
2798
|
+
writer.data += btoa(dataString);
|
|
2799
|
+
} else {
|
|
2800
|
+
writer.pending = dataString + writer.pending;
|
|
2598
2801
|
}
|
|
2599
2802
|
}
|
|
2600
2803
|
|
|
@@ -2641,6 +2844,9 @@ class BlobWriter extends Stream {
|
|
|
2641
2844
|
}
|
|
2642
2845
|
});
|
|
2643
2846
|
writer.blob = new Response(transformStream.readable, { headers }).blob();
|
|
2847
|
+
// mark early rejections (e.g. aborted pipe) as handled; awaiting getData() still
|
|
2848
|
+
// surfaces them
|
|
2849
|
+
writer.blob.catch(() => { });
|
|
2644
2850
|
}
|
|
2645
2851
|
|
|
2646
2852
|
getData() {
|
|
@@ -2725,7 +2931,8 @@ function createHttpReader(httpReader, url, options) {
|
|
|
2725
2931
|
preventHeadRequest,
|
|
2726
2932
|
useRangeHeader,
|
|
2727
2933
|
forceRangeRequests,
|
|
2728
|
-
combineSizeEocd
|
|
2934
|
+
combineSizeEocd,
|
|
2935
|
+
fetch
|
|
2729
2936
|
} = options;
|
|
2730
2937
|
options = Object.assign({}, options);
|
|
2731
2938
|
delete options.preventHeadRequest;
|
|
@@ -2733,13 +2940,15 @@ function createHttpReader(httpReader, url, options) {
|
|
|
2733
2940
|
delete options.forceRangeRequests;
|
|
2734
2941
|
delete options.combineSizeEocd;
|
|
2735
2942
|
delete options.useXHR;
|
|
2943
|
+
delete options.fetch;
|
|
2736
2944
|
Object.assign(httpReader, {
|
|
2737
2945
|
url,
|
|
2738
2946
|
options,
|
|
2739
2947
|
preventHeadRequest,
|
|
2740
2948
|
useRangeHeader,
|
|
2741
2949
|
forceRangeRequests,
|
|
2742
|
-
combineSizeEocd
|
|
2950
|
+
combineSizeEocd,
|
|
2951
|
+
fetch
|
|
2743
2952
|
});
|
|
2744
2953
|
}
|
|
2745
2954
|
|
|
@@ -2758,7 +2967,10 @@ async function initHttpReader(httpReader, sendRequest, getRequestData) {
|
|
|
2758
2967
|
throw new Error(ERR_HTTP_RANGE);
|
|
2759
2968
|
} else {
|
|
2760
2969
|
if (combineSizeEocd) {
|
|
2761
|
-
|
|
2970
|
+
const eocdCache = new Uint8Array(await response.arrayBuffer());
|
|
2971
|
+
if (response.status == 206 && eocdCache.length == END_OF_CENTRAL_DIR_LENGTH) {
|
|
2972
|
+
httpReader.eocdCache = eocdCache;
|
|
2973
|
+
}
|
|
2762
2974
|
}
|
|
2763
2975
|
let contentSize;
|
|
2764
2976
|
const contentRangeHeader = response.headers.get(HTTP_HEADER_CONTENT_RANGE);
|
|
@@ -2804,7 +3016,18 @@ async function readUint8ArrayHttpReader(httpReader, index, length, sendRequest,
|
|
|
2804
3016
|
if (response.status != 206) {
|
|
2805
3017
|
throw new Error(ERR_HTTP_RANGE);
|
|
2806
3018
|
}
|
|
2807
|
-
|
|
3019
|
+
const contentRangeHeader = response.headers.get(HTTP_HEADER_CONTENT_RANGE);
|
|
3020
|
+
if (contentRangeHeader) {
|
|
3021
|
+
const rangeStart = Number(contentRangeHeader.trim().split(/[\s-]+/)[1]);
|
|
3022
|
+
if (!Number.isNaN(rangeStart) && rangeStart != index) {
|
|
3023
|
+
throw new Error(ERR_HTTP_RANGE);
|
|
3024
|
+
}
|
|
3025
|
+
}
|
|
3026
|
+
const data = new Uint8Array(await response.arrayBuffer());
|
|
3027
|
+
if (data.length != length) {
|
|
3028
|
+
throw new Error(ERR_HTTP_RANGE);
|
|
3029
|
+
}
|
|
3030
|
+
return data;
|
|
2808
3031
|
}
|
|
2809
3032
|
} else {
|
|
2810
3033
|
const { data } = httpReader;
|
|
@@ -2841,9 +3064,9 @@ async function getXMLHttpRequestData(httpReader) {
|
|
|
2841
3064
|
async function getRequestData(httpReader, sendRequest) {
|
|
2842
3065
|
const response = await sendRequest(HTTP_METHOD_GET, httpReader, getHeaders(httpReader));
|
|
2843
3066
|
httpReader.data = new Uint8Array(await response.arrayBuffer());
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
3067
|
+
// the downloaded content is authoritative, e.g. the Content-Length response header
|
|
3068
|
+
// of the HEAD request can be the encoded size when the content is compressed
|
|
3069
|
+
httpReader.size = httpReader.data.length;
|
|
2847
3070
|
}
|
|
2848
3071
|
|
|
2849
3072
|
async function getContentLength(httpReader, sendRequest, getRequestData) {
|
|
@@ -2852,7 +3075,7 @@ async function getContentLength(httpReader, sendRequest, getRequestData) {
|
|
|
2852
3075
|
} else {
|
|
2853
3076
|
const response = await sendRequest(HTTP_METHOD_HEAD, httpReader, getHeaders(httpReader));
|
|
2854
3077
|
const contentLength = response.headers.get(HTTP_HEADER_CONTENT_LENGTH);
|
|
2855
|
-
if (contentLength) {
|
|
3078
|
+
if (contentLength && !response.headers.get(HTTP_HEADER_CONTENT_ENCODING)) {
|
|
2856
3079
|
httpReader.size = Number(contentLength);
|
|
2857
3080
|
} else {
|
|
2858
3081
|
await getRequestData(httpReader, httpReader.options);
|
|
@@ -2860,8 +3083,8 @@ async function getContentLength(httpReader, sendRequest, getRequestData) {
|
|
|
2860
3083
|
}
|
|
2861
3084
|
}
|
|
2862
3085
|
|
|
2863
|
-
async function sendFetchRequest(method, { options, url }, headers) {
|
|
2864
|
-
const response = await
|
|
3086
|
+
async function sendFetchRequest(method, { fetch: fetchFunction = fetch, options, url }, headers) {
|
|
3087
|
+
const response = await fetchFunction(url, Object.assign({}, options, { method, headers }));
|
|
2865
3088
|
if (response.status < 400) {
|
|
2866
3089
|
return response;
|
|
2867
3090
|
} else {
|
|
@@ -2907,7 +3130,8 @@ class HttpReader extends Reader {
|
|
|
2907
3130
|
super();
|
|
2908
3131
|
Object.assign(this, {
|
|
2909
3132
|
url,
|
|
2910
|
-
|
|
3133
|
+
// an explicit fetch implementation takes precedence over useXHR
|
|
3134
|
+
reader: options.useXHR && !options.fetch ? new XHRReader(url, options) : new FetchReader(url, options)
|
|
2911
3135
|
});
|
|
2912
3136
|
}
|
|
2913
3137
|
|
|
@@ -2932,8 +3156,7 @@ class HttpReader extends Reader {
|
|
|
2932
3156
|
class HttpRangeReader extends HttpReader {
|
|
2933
3157
|
|
|
2934
3158
|
constructor(url, options = {}) {
|
|
2935
|
-
options
|
|
2936
|
-
super(url, options);
|
|
3159
|
+
super(url, Object.assign({}, options, { useRangeHeader: true }));
|
|
2937
3160
|
}
|
|
2938
3161
|
}
|
|
2939
3162
|
|
|
@@ -3007,7 +3230,7 @@ class SplitDataReader extends Reader {
|
|
|
3007
3230
|
reader.lastDiskNumber = 0;
|
|
3008
3231
|
reader.lastDiskOffset = 0;
|
|
3009
3232
|
await Promise.all(readers.map(async (diskReader, indexDiskReader) => {
|
|
3010
|
-
await diskReader
|
|
3233
|
+
await initStream(diskReader);
|
|
3011
3234
|
if (indexDiskReader != readers.length - 1) {
|
|
3012
3235
|
reader.lastDiskOffset += diskReader.size;
|
|
3013
3236
|
}
|
|
@@ -3091,14 +3314,26 @@ class SplitDataWriter extends Stream {
|
|
|
3091
3314
|
writer.diskOffset += diskSourceWriter.size;
|
|
3092
3315
|
writer.diskNumber++;
|
|
3093
3316
|
diskWriter = null;
|
|
3094
|
-
|
|
3317
|
+
// the next disk is not opened yet but its space is available; leaving a
|
|
3318
|
+
// stale value here would force a new disk for every subsequent write
|
|
3319
|
+
writer.availableSize = writer.maxSize;
|
|
3320
|
+
if (chunk.length > availableSize) {
|
|
3321
|
+
await this.write(chunk.subarray(availableSize));
|
|
3322
|
+
}
|
|
3095
3323
|
} else {
|
|
3096
3324
|
await writeChunk(chunk);
|
|
3097
3325
|
}
|
|
3098
3326
|
},
|
|
3099
3327
|
async close() {
|
|
3100
|
-
|
|
3101
|
-
|
|
3328
|
+
if (diskWriter) {
|
|
3329
|
+
await diskWriter.ready;
|
|
3330
|
+
await closeDisk();
|
|
3331
|
+
}
|
|
3332
|
+
},
|
|
3333
|
+
async abort(reason) {
|
|
3334
|
+
if (diskWriter) {
|
|
3335
|
+
await diskWriter.abort(reason);
|
|
3336
|
+
}
|
|
3102
3337
|
}
|
|
3103
3338
|
});
|
|
3104
3339
|
Object.defineProperty(writer, PROPERTY_NAME_WRITABLE, {
|
|
@@ -3113,7 +3348,6 @@ class SplitDataWriter extends Stream {
|
|
|
3113
3348
|
await diskWriter.ready;
|
|
3114
3349
|
await diskWriter.write(chunk);
|
|
3115
3350
|
diskSourceWriter.size += chunkLength;
|
|
3116
|
-
writer.size += chunkLength;
|
|
3117
3351
|
writer.availableSize -= chunkLength;
|
|
3118
3352
|
}
|
|
3119
3353
|
}
|
|
@@ -3213,7 +3447,7 @@ function readUint8Array(reader, offset, size, diskNumber) {
|
|
|
3213
3447
|
|
|
3214
3448
|
/* global TextDecoder */
|
|
3215
3449
|
|
|
3216
|
-
const CP437 = "\0☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼ !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~⌂ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■
|
|
3450
|
+
const CP437 = "\0☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼ !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~⌂ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ ".split("");
|
|
3217
3451
|
const VALID_CP437 = CP437.length == 256;
|
|
3218
3452
|
|
|
3219
3453
|
function decodeCP437(stringValue) {
|
|
@@ -3261,7 +3495,8 @@ function decodeText(value, encoding) {
|
|
|
3261
3495
|
if (encoding && encoding.trim().toLowerCase() == "cp437") {
|
|
3262
3496
|
return decodeCP437(value);
|
|
3263
3497
|
} else {
|
|
3264
|
-
|
|
3498
|
+
// ignoreBOM keeps a leading U+FEFF in filenames/comments instead of dropping it
|
|
3499
|
+
return new TextDecoder(encoding, { ignoreBOM: true }).decode(value);
|
|
3265
3500
|
}
|
|
3266
3501
|
}
|
|
3267
3502
|
|
|
@@ -3438,6 +3673,7 @@ const OPTION_SIGNAL = "signal";
|
|
|
3438
3673
|
const OPTION_CHECK_PASSWORD_ONLY = "checkPasswordOnly";
|
|
3439
3674
|
const OPTION_CHECK_OVERLAPPING_ENTRY_ONLY = "checkOverlappingEntryOnly";
|
|
3440
3675
|
const OPTION_CHECK_OVERLAPPING_ENTRY = "checkOverlappingEntry";
|
|
3676
|
+
const OPTION_CHECK_AMBIGUITY = "checkAmbiguity";
|
|
3441
3677
|
const OPTION_CHECK_SIGNATURE = "checkSignature";
|
|
3442
3678
|
const OPTION_USE_WEB_WORKERS = "useWebWorkers";
|
|
3443
3679
|
const OPTION_USE_COMPRESSION_STREAM = "useCompressionStream";
|
|
@@ -3495,12 +3731,16 @@ const ERR_LOCAL_FILE_HEADER_NOT_FOUND = "Local file header not found";
|
|
|
3495
3731
|
const ERR_EXTRAFIELD_ZIP64_NOT_FOUND = "Zip64 extra field not found";
|
|
3496
3732
|
const ERR_ENCRYPTED = "File contains encrypted entry";
|
|
3497
3733
|
const ERR_UNSUPPORTED_ENCRYPTION = "Encryption method not supported";
|
|
3498
|
-
const ERR_UNSUPPORTED_COMPRESSION = "Compression method not supported";
|
|
3734
|
+
const ERR_UNSUPPORTED_COMPRESSION$1 = "Compression method not supported";
|
|
3499
3735
|
const ERR_SPLIT_ZIP_FILE = "Split zip file";
|
|
3500
3736
|
const ERR_OVERLAPPING_ENTRY = "Overlapping entry found";
|
|
3737
|
+
const ERR_AMBIGUOUS_ARCHIVE = "Ambiguous archive";
|
|
3501
3738
|
const CHARSET_UTF8 = "utf-8";
|
|
3502
3739
|
const PROPERTY_NAME_UTF8_SUFFIX = "UTF8";
|
|
3503
3740
|
const CHARSET_CP437 = "cp437";
|
|
3741
|
+
// bits of the general purpose flag that change how an entry is interpreted; the level bits (1-2) are excluded
|
|
3742
|
+
// because they are informative only
|
|
3743
|
+
const BITFLAG_AMBIGUITY_MASK = BITFLAG_ENCRYPTED | BITFLAG_DATA_DESCRIPTOR | BITFLAG_LANG_ENCODING_FLAG;
|
|
3504
3744
|
const ZIP64_PROPERTIES = [
|
|
3505
3745
|
[PROPERTY_NAME_UNCOMPRESSED_SIZE, MAX_32_BITS],
|
|
3506
3746
|
[PROPERTY_NAME_COMPRESSED_SIZE, MAX_32_BITS],
|
|
@@ -3525,7 +3765,7 @@ class ZipReader {
|
|
|
3525
3765
|
reader: new GenericReader(reader),
|
|
3526
3766
|
options,
|
|
3527
3767
|
config: getConfiguration(),
|
|
3528
|
-
readRanges:
|
|
3768
|
+
readRanges: new Map()
|
|
3529
3769
|
});
|
|
3530
3770
|
}
|
|
3531
3771
|
|
|
@@ -3558,21 +3798,30 @@ class ZipReader {
|
|
|
3558
3798
|
const commentOffset = endOfDirectoryInfo.offset;
|
|
3559
3799
|
const commentLength = getUint16(endOfDirectoryView, 20);
|
|
3560
3800
|
const appendedDataOffset = commentOffset + END_OF_CENTRAL_DIR_LENGTH + commentLength;
|
|
3801
|
+
const checkAmbiguity = getOptionValue$1(zipReader, options, OPTION_CHECK_AMBIGUITY);
|
|
3802
|
+
if (checkAmbiguity && appendedDataOffset != reader.size) {
|
|
3803
|
+
throwAmbiguousArchive("appended data");
|
|
3804
|
+
}
|
|
3561
3805
|
let lastDiskNumber = getUint16(endOfDirectoryView, 4);
|
|
3562
3806
|
const expectedLastDiskNumber = reader.lastDiskNumber || 0;
|
|
3563
3807
|
let diskNumber = getUint16(endOfDirectoryView, 6);
|
|
3564
|
-
let filesLength = getUint16(endOfDirectoryView,
|
|
3808
|
+
let filesLength = getUint16(endOfDirectoryView, 10);
|
|
3565
3809
|
let prependedDataLength = 0;
|
|
3566
|
-
let startOffset
|
|
3810
|
+
let startOffset;
|
|
3811
|
+
let zip64EndOfDirectory;
|
|
3567
3812
|
if (directoryDataOffset == MAX_32_BITS || directoryDataLength == MAX_32_BITS || filesLength == MAX_16_BITS || diskNumber == MAX_16_BITS) {
|
|
3568
|
-
const endOfDirectoryLocatorArray =
|
|
3813
|
+
const endOfDirectoryLocatorArray = endOfDirectoryInfo.offset >= ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH ?
|
|
3814
|
+
await readUint8Array(reader, endOfDirectoryInfo.offset - ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH, ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH) :
|
|
3815
|
+
new Uint8Array();
|
|
3569
3816
|
const endOfDirectoryLocatorView = getDataView$1(endOfDirectoryLocatorArray);
|
|
3570
|
-
if (
|
|
3817
|
+
if (endOfDirectoryLocatorArray.length == ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH &&
|
|
3818
|
+
getUint32(endOfDirectoryLocatorView, 0) == ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIGNATURE) {
|
|
3571
3819
|
directoryDataOffset = getBigUint64(endOfDirectoryLocatorView, 8);
|
|
3572
3820
|
let endOfDirectoryArray = await readUint8Array(reader, directoryDataOffset, ZIP64_END_OF_CENTRAL_DIR_LENGTH, -1);
|
|
3573
3821
|
let endOfDirectoryView = getDataView$1(endOfDirectoryArray);
|
|
3574
|
-
const expectedDirectoryDataOffset = endOfDirectoryInfo.offset - ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH - ZIP64_END_OF_CENTRAL_DIR_LENGTH;
|
|
3575
|
-
if (getUint32(endOfDirectoryView, 0) != ZIP64_END_OF_CENTRAL_DIR_SIGNATURE &&
|
|
3822
|
+
const expectedDirectoryDataOffset = endOfDirectoryInfo.offset - ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH - ZIP64_END_OF_CENTRAL_DIR_LENGTH - (reader.lastDiskOffset || 0);
|
|
3823
|
+
if ((endOfDirectoryArray.length < ZIP64_END_OF_CENTRAL_DIR_LENGTH || getUint32(endOfDirectoryView, 0) != ZIP64_END_OF_CENTRAL_DIR_SIGNATURE) &&
|
|
3824
|
+
directoryDataOffset != expectedDirectoryDataOffset && expectedDirectoryDataOffset >= 0) {
|
|
3576
3825
|
const originalDirectoryDataOffset = directoryDataOffset;
|
|
3577
3826
|
directoryDataOffset = expectedDirectoryDataOffset;
|
|
3578
3827
|
if (directoryDataOffset > originalDirectoryDataOffset) {
|
|
@@ -3581,24 +3830,36 @@ class ZipReader {
|
|
|
3581
3830
|
endOfDirectoryArray = await readUint8Array(reader, directoryDataOffset, ZIP64_END_OF_CENTRAL_DIR_LENGTH, -1);
|
|
3582
3831
|
endOfDirectoryView = getDataView$1(endOfDirectoryArray);
|
|
3583
3832
|
}
|
|
3584
|
-
if (getUint32(endOfDirectoryView, 0) != ZIP64_END_OF_CENTRAL_DIR_SIGNATURE) {
|
|
3833
|
+
if (endOfDirectoryArray.length < ZIP64_END_OF_CENTRAL_DIR_LENGTH || getUint32(endOfDirectoryView, 0) != ZIP64_END_OF_CENTRAL_DIR_SIGNATURE) {
|
|
3585
3834
|
throw new Error(ERR_EOCDR_LOCATOR_ZIP64_NOT_FOUND);
|
|
3586
3835
|
}
|
|
3836
|
+
zip64EndOfDirectory = true;
|
|
3587
3837
|
if (lastDiskNumber == MAX_16_BITS) {
|
|
3588
3838
|
lastDiskNumber = getUint32(endOfDirectoryView, 16);
|
|
3839
|
+
} else if (checkAmbiguity && lastDiskNumber != getUint32(endOfDirectoryView, 16)) {
|
|
3840
|
+
throwAmbiguousArchive("mismatched zip64 end of central directory record");
|
|
3589
3841
|
}
|
|
3590
3842
|
if (diskNumber == MAX_16_BITS) {
|
|
3591
3843
|
diskNumber = getUint32(endOfDirectoryView, 20);
|
|
3844
|
+
} else if (checkAmbiguity && diskNumber != getUint32(endOfDirectoryView, 20)) {
|
|
3845
|
+
throwAmbiguousArchive("mismatched zip64 end of central directory record");
|
|
3592
3846
|
}
|
|
3593
3847
|
if (filesLength == MAX_16_BITS) {
|
|
3594
3848
|
filesLength = getBigUint64(endOfDirectoryView, 32);
|
|
3849
|
+
} else if (checkAmbiguity && filesLength != getBigUint64(endOfDirectoryView, 32)) {
|
|
3850
|
+
throwAmbiguousArchive("mismatched zip64 end of central directory record");
|
|
3595
3851
|
}
|
|
3596
3852
|
if (directoryDataLength == MAX_32_BITS) {
|
|
3597
3853
|
directoryDataLength = getBigUint64(endOfDirectoryView, 40);
|
|
3854
|
+
} else if (checkAmbiguity && directoryDataLength != getBigUint64(endOfDirectoryView, 40)) {
|
|
3855
|
+
throwAmbiguousArchive("mismatched zip64 end of central directory record");
|
|
3598
3856
|
}
|
|
3599
|
-
directoryDataOffset
|
|
3857
|
+
directoryDataOffset = getBigUint64(endOfDirectoryView, 48) + prependedDataLength;
|
|
3600
3858
|
}
|
|
3601
3859
|
}
|
|
3860
|
+
const declaredDirectoryDataLength = directoryDataLength;
|
|
3861
|
+
const centralDirectoryEndOffset = endOfDirectoryInfo.offset -
|
|
3862
|
+
(zip64EndOfDirectory ? ZIP64_END_OF_CENTRAL_DIR_LENGTH + ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH : 0);
|
|
3602
3863
|
if (directoryDataOffset >= reader.size) {
|
|
3603
3864
|
prependedDataLength = reader.size - directoryDataOffset - directoryDataLength - END_OF_CENTRAL_DIR_LENGTH;
|
|
3604
3865
|
directoryDataOffset = reader.size - directoryDataLength - END_OF_CENTRAL_DIR_LENGTH;
|
|
@@ -3613,8 +3874,11 @@ class ZipReader {
|
|
|
3613
3874
|
let directoryArray = await readUint8Array(reader, directoryDataOffset, directoryDataLength, diskNumber);
|
|
3614
3875
|
let directoryView = getDataView$1(directoryArray);
|
|
3615
3876
|
if (directoryDataLength) {
|
|
3616
|
-
|
|
3617
|
-
|
|
3877
|
+
if (directoryArray.length < 4) {
|
|
3878
|
+
throw new Error(ERR_BAD_FORMAT);
|
|
3879
|
+
}
|
|
3880
|
+
const expectedDirectoryDataOffset = centralDirectoryEndOffset - directoryDataLength - (reader.lastDiskOffset || 0);
|
|
3881
|
+
if (getUint32(directoryView, offset) != CENTRAL_FILE_HEADER_SIGNATURE && directoryDataOffset != expectedDirectoryDataOffset && diskNumber == lastDiskNumber) {
|
|
3618
3882
|
const originalDirectoryDataOffset = directoryDataOffset;
|
|
3619
3883
|
directoryDataOffset = expectedDirectoryDataOffset;
|
|
3620
3884
|
if (directoryDataOffset > originalDirectoryDataOffset) {
|
|
@@ -3624,8 +3888,8 @@ class ZipReader {
|
|
|
3624
3888
|
directoryView = getDataView$1(directoryArray);
|
|
3625
3889
|
}
|
|
3626
3890
|
}
|
|
3627
|
-
const expectedDirectoryDataLength =
|
|
3628
|
-
if (directoryDataLength != expectedDirectoryDataLength && expectedDirectoryDataLength >= 0) {
|
|
3891
|
+
const expectedDirectoryDataLength = centralDirectoryEndOffset - directoryDataOffset - (reader.lastDiskOffset || 0);
|
|
3892
|
+
if (directoryDataLength != expectedDirectoryDataLength && expectedDirectoryDataLength >= 0 && diskNumber == lastDiskNumber) {
|
|
3629
3893
|
directoryDataLength = expectedDirectoryDataLength;
|
|
3630
3894
|
directoryArray = await readUint8Array(reader, directoryDataOffset, directoryDataLength, diskNumber);
|
|
3631
3895
|
directoryView = getDataView$1(directoryArray);
|
|
@@ -3633,16 +3897,19 @@ class ZipReader {
|
|
|
3633
3897
|
if (directoryDataOffset < 0 || directoryDataOffset >= reader.size) {
|
|
3634
3898
|
throw new Error(ERR_BAD_FORMAT);
|
|
3635
3899
|
}
|
|
3900
|
+
startOffset = directoryDataOffset;
|
|
3636
3901
|
const filenameEncoding = getOptionValue$1(zipReader, options, OPTION_FILENAME_ENCODING);
|
|
3637
3902
|
const commentEncoding = getOptionValue$1(zipReader, options, OPTION_COMMENT_ENCODING);
|
|
3903
|
+
const filenames = checkAmbiguity ? new Set() : UNDEFINED_VALUE;
|
|
3904
|
+
let duplicateFilename;
|
|
3638
3905
|
for (let indexFile = 0; indexFile < filesLength; indexFile++) {
|
|
3639
3906
|
const fileEntry = new ZipEntry$1(reader, config, zipReader.options);
|
|
3640
|
-
if (getUint32(directoryView, offset) != CENTRAL_FILE_HEADER_SIGNATURE) {
|
|
3907
|
+
if (offset + CENTRAL_FILE_HEADER_LENGTH > directoryArray.length || getUint32(directoryView, offset) != CENTRAL_FILE_HEADER_SIGNATURE) {
|
|
3641
3908
|
throw new Error(ERR_CENTRAL_DIRECTORY_NOT_FOUND);
|
|
3642
3909
|
}
|
|
3643
3910
|
readCommonHeader(fileEntry, directoryView, offset + 6);
|
|
3644
3911
|
const languageEncodingFlag = Boolean(fileEntry.bitFlag.languageEncodingFlag);
|
|
3645
|
-
const filenameOffset = offset +
|
|
3912
|
+
const filenameOffset = offset + CENTRAL_FILE_HEADER_LENGTH;
|
|
3646
3913
|
const extraFieldOffset = filenameOffset + fileEntry.filenameLength;
|
|
3647
3914
|
const commentOffset = extraFieldOffset + fileEntry.extraFieldLength;
|
|
3648
3915
|
const versionMadeBy = getUint16(directoryView, offset + 4);
|
|
@@ -3663,7 +3930,7 @@ class ZipReader {
|
|
|
3663
3930
|
directory: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_DIR_MASK),
|
|
3664
3931
|
archive: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_ARCHIVE_MASK)
|
|
3665
3932
|
};
|
|
3666
|
-
const offsetFileEntry = getUint32(directoryView, offset + 42)
|
|
3933
|
+
const offsetFileEntry = getUint32(directoryView, offset + 42);
|
|
3667
3934
|
const decode = getOptionValue$1(zipReader, options, OPTION_DECODE_TEXT) || decodeText;
|
|
3668
3935
|
const rawFilenameEncoding = filenameUTF8 ? CHARSET_UTF8 : filenameEncoding || CHARSET_CP437;
|
|
3669
3936
|
const rawCommentEncoding = commentUTF8 ? CHARSET_UTF8 : commentEncoding || CHARSET_CP437;
|
|
@@ -3676,6 +3943,7 @@ class ZipReader {
|
|
|
3676
3943
|
comment = decodeText(rawComment, rawCommentEncoding);
|
|
3677
3944
|
}
|
|
3678
3945
|
Object.assign(fileEntry, {
|
|
3946
|
+
index: indexFile,
|
|
3679
3947
|
versionMadeBy,
|
|
3680
3948
|
msDosCompatible,
|
|
3681
3949
|
compressedSize: 0,
|
|
@@ -3695,8 +3963,15 @@ class ZipReader {
|
|
|
3695
3963
|
filename,
|
|
3696
3964
|
comment
|
|
3697
3965
|
});
|
|
3698
|
-
startOffset = Math.max(offsetFileEntry, startOffset);
|
|
3699
3966
|
readCommonFooter(fileEntry, fileEntry, directoryView, offset + 6);
|
|
3967
|
+
fileEntry.offset += prependedDataLength;
|
|
3968
|
+
startOffset = Math.min(fileEntry.offset, startOffset);
|
|
3969
|
+
if (checkAmbiguity) {
|
|
3970
|
+
if (filenames.has(fileEntry.filename)) {
|
|
3971
|
+
duplicateFilename = true;
|
|
3972
|
+
}
|
|
3973
|
+
filenames.add(fileEntry.filename);
|
|
3974
|
+
}
|
|
3700
3975
|
const unixExternalUpper = (fileEntry.externalFileAttributes >> 16) & MAX_16_BITS;
|
|
3701
3976
|
if (fileEntry.unixMode === UNDEFINED_VALUE && (unixExternalUpper & (FILE_ATTR_UNIX_DEFAULT_MASK | FILE_ATTR_UNIX_EXECUTABLE_MASK | FILE_ATTR_UNIX_TYPE_DIR)) != 0) {
|
|
3702
3977
|
fileEntry.unixMode = unixExternalUpper;
|
|
@@ -3717,7 +3992,7 @@ class ZipReader {
|
|
|
3717
3992
|
internalFileAttribute: fileEntry.internalFileAttributes,
|
|
3718
3993
|
externalFileAttribute: fileEntry.externalFileAttributes,
|
|
3719
3994
|
executable,
|
|
3720
|
-
directory: modeIsDir || upperIsDir || (msDosCompatible && msdosAttributes.directory) || (filename.endsWith(DIRECTORY_SIGNATURE) && !fileEntry.uncompressedSize),
|
|
3995
|
+
directory: modeIsDir || upperIsDir || (msDosCompatible && msdosAttributes.directory) || (fileEntry.filename.endsWith(DIRECTORY_SIGNATURE) && !fileEntry.uncompressedSize),
|
|
3721
3996
|
zipCrypto: fileEntry.encrypted && !fileEntry.extraFieldAES
|
|
3722
3997
|
});
|
|
3723
3998
|
const entry = new Entry(fileEntry);
|
|
@@ -3740,6 +4015,15 @@ class ZipReader {
|
|
|
3740
4015
|
}
|
|
3741
4016
|
yield entry;
|
|
3742
4017
|
}
|
|
4018
|
+
if (checkAmbiguity && offset != declaredDirectoryDataLength) {
|
|
4019
|
+
throwAmbiguousArchive("trailing central directory data");
|
|
4020
|
+
}
|
|
4021
|
+
if (duplicateFilename) {
|
|
4022
|
+
throwAmbiguousArchive("duplicate filename");
|
|
4023
|
+
}
|
|
4024
|
+
if (checkAmbiguity && (prependedDataLength || (filesLength && startOffset > 0))) {
|
|
4025
|
+
throwAmbiguousArchive("prepended data");
|
|
4026
|
+
}
|
|
3743
4027
|
const extractPrependedData = getOptionValue$1(zipReader, options, OPTION_EXTRACT_PREPENDED_DATA);
|
|
3744
4028
|
const extractAppendedData = getOptionValue$1(zipReader, options, OPTION_EXTRACT_APPENDED_DATA);
|
|
3745
4029
|
if (extractPrependedData) {
|
|
@@ -3779,9 +4063,21 @@ class ZipReaderStream {
|
|
|
3779
4063
|
readable: (function () {
|
|
3780
4064
|
const { readable, writable } = new TransformStream();
|
|
3781
4065
|
if (value.getData) {
|
|
3782
|
-
|
|
4066
|
+
getData();
|
|
3783
4067
|
return readable;
|
|
3784
4068
|
}
|
|
4069
|
+
|
|
4070
|
+
async function getData() {
|
|
4071
|
+
try {
|
|
4072
|
+
await value.getData(writable);
|
|
4073
|
+
} catch (error) {
|
|
4074
|
+
try {
|
|
4075
|
+
await writable.abort(error);
|
|
4076
|
+
} catch {
|
|
4077
|
+
// ignored
|
|
4078
|
+
}
|
|
4079
|
+
}
|
|
4080
|
+
}
|
|
3785
4081
|
})()
|
|
3786
4082
|
};
|
|
3787
4083
|
delete chunk.getData;
|
|
@@ -3806,6 +4102,7 @@ let ZipEntry$1 = class ZipEntry {
|
|
|
3806
4102
|
const zipEntry = this;
|
|
3807
4103
|
const {
|
|
3808
4104
|
reader,
|
|
4105
|
+
index,
|
|
3809
4106
|
offset,
|
|
3810
4107
|
diskNumberStart,
|
|
3811
4108
|
extraFieldAES,
|
|
@@ -3831,27 +4128,42 @@ let ZipEntry$1 = class ZipEntry {
|
|
|
3831
4128
|
rawPassword = rawPassword && rawPassword.length && rawPassword;
|
|
3832
4129
|
if (extraFieldAES) {
|
|
3833
4130
|
if (extraFieldAES.originalCompressionMethod != COMPRESSION_METHOD_AES) {
|
|
3834
|
-
throw new Error(ERR_UNSUPPORTED_COMPRESSION);
|
|
4131
|
+
throw new Error(ERR_UNSUPPORTED_COMPRESSION$1);
|
|
3835
4132
|
}
|
|
3836
4133
|
}
|
|
3837
4134
|
if ((compressionMethod != COMPRESSION_METHOD_STORE && compressionMethod != COMPRESSION_METHOD_DEFLATE && compressionMethod != COMPRESSION_METHOD_DEFLATE_64) && !passThrough) {
|
|
3838
|
-
throw new Error(ERR_UNSUPPORTED_COMPRESSION);
|
|
4135
|
+
throw new Error(ERR_UNSUPPORTED_COMPRESSION$1);
|
|
3839
4136
|
}
|
|
3840
|
-
if (getUint32(dataView, 0) != LOCAL_FILE_HEADER_SIGNATURE) {
|
|
4137
|
+
if (dataArray.length < HEADER_SIZE || getUint32(dataView, 0) != LOCAL_FILE_HEADER_SIGNATURE) {
|
|
3841
4138
|
throw new Error(ERR_LOCAL_FILE_HEADER_NOT_FOUND);
|
|
3842
4139
|
}
|
|
3843
4140
|
readCommonHeader(localDirectory, dataView, 4);
|
|
3844
4141
|
const {
|
|
3845
4142
|
extraFieldLength,
|
|
3846
|
-
filenameLength
|
|
3847
|
-
lastAccessDate,
|
|
3848
|
-
creationDate
|
|
4143
|
+
filenameLength
|
|
3849
4144
|
} = localDirectory;
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
4145
|
+
const checkAmbiguity = getOptionValue$1(zipEntry, options, OPTION_CHECK_AMBIGUITY);
|
|
4146
|
+
let rawLocalFilename = new Uint8Array();
|
|
4147
|
+
if (checkAmbiguity && (filenameLength || extraFieldLength)) {
|
|
4148
|
+
const trailingDataArray = await readUint8Array(reader, offset + HEADER_SIZE, filenameLength + extraFieldLength, diskNumberStart);
|
|
4149
|
+
rawLocalFilename = trailingDataArray.subarray(0, filenameLength);
|
|
4150
|
+
localDirectory.rawExtraField = trailingDataArray.subarray(filenameLength);
|
|
4151
|
+
} else {
|
|
4152
|
+
localDirectory.rawExtraField = extraFieldLength ?
|
|
4153
|
+
await readUint8Array(reader, offset + HEADER_SIZE + filenameLength, extraFieldLength, diskNumberStart) :
|
|
4154
|
+
new Uint8Array();
|
|
4155
|
+
}
|
|
3853
4156
|
readCommonFooter(zipEntry, localDirectory, dataView, 4, true);
|
|
3854
|
-
|
|
4157
|
+
if (checkAmbiguity) {
|
|
4158
|
+
checkLocalDirectory(zipEntry, localDirectory, rawLocalFilename);
|
|
4159
|
+
}
|
|
4160
|
+
const { lastAccessDate, creationDate } = localDirectory;
|
|
4161
|
+
if (lastAccessDate) {
|
|
4162
|
+
fileEntry.lastAccessDate = lastAccessDate;
|
|
4163
|
+
}
|
|
4164
|
+
if (creationDate) {
|
|
4165
|
+
fileEntry.creationDate = creationDate;
|
|
4166
|
+
}
|
|
3855
4167
|
const encrypted = zipEntry.encrypted && localDirectory.encrypted && !passThrough;
|
|
3856
4168
|
const zipCrypto = encrypted && !extraFieldAES;
|
|
3857
4169
|
if (!passThrough) {
|
|
@@ -3897,7 +4209,7 @@ let ZipEntry$1 = class ZipEntry {
|
|
|
3897
4209
|
outputSize: passThrough ? compressedSize : uncompressedSize,
|
|
3898
4210
|
signature,
|
|
3899
4211
|
compressed: compressionMethod != 0 && !passThrough,
|
|
3900
|
-
encrypted
|
|
4212
|
+
encrypted,
|
|
3901
4213
|
useWebWorkers: getOptionValue$1(zipEntry, options, OPTION_USE_WEB_WORKERS),
|
|
3902
4214
|
useCompressionStream,
|
|
3903
4215
|
transferStreams: getOptionValue$1(zipEntry, options, OPTION_TRANSFER_STREAMS),
|
|
@@ -3911,6 +4223,7 @@ let ZipEntry$1 = class ZipEntry {
|
|
|
3911
4223
|
await detectOverlappingEntry({
|
|
3912
4224
|
reader,
|
|
3913
4225
|
fileEntry,
|
|
4226
|
+
index,
|
|
3914
4227
|
offset,
|
|
3915
4228
|
diskNumberStart,
|
|
3916
4229
|
signature,
|
|
@@ -4013,7 +4326,7 @@ function readCommonFooter(fileEntry, directory, dataView, offset, localDirectory
|
|
|
4013
4326
|
directory.extraFieldUnicodeComment = extraFieldUnicodeComment;
|
|
4014
4327
|
}
|
|
4015
4328
|
const extraFieldAES = extraField.get(EXTRAFIELD_TYPE_AES);
|
|
4016
|
-
if (extraFieldAES) {
|
|
4329
|
+
if (extraFieldAES && extraFieldAES.data.length >= 7) {
|
|
4017
4330
|
readExtraFieldAES(extraFieldAES, directory, compressionMethod);
|
|
4018
4331
|
directory.extraFieldAES = extraFieldAES;
|
|
4019
4332
|
} else {
|
|
@@ -4050,19 +4363,23 @@ function readExtraFieldZip64(extraFieldZip64, directory) {
|
|
|
4050
4363
|
directory.zip64 = true;
|
|
4051
4364
|
const extraFieldView = getDataView$1(extraFieldZip64.data);
|
|
4052
4365
|
const missingProperties = ZIP64_PROPERTIES.filter(([propertyName, max]) => directory[propertyName] == max);
|
|
4366
|
+
const requiredLength = missingProperties.reduce((length, [, max]) => length + ZIP64_EXTRACTION[max].bytes, 0);
|
|
4367
|
+
if (extraFieldZip64.data.length < requiredLength) {
|
|
4368
|
+
throw new Error(ERR_EXTRAFIELD_ZIP64_NOT_FOUND);
|
|
4369
|
+
}
|
|
4053
4370
|
for (let indexMissingProperty = 0, offset = 0; indexMissingProperty < missingProperties.length; indexMissingProperty++) {
|
|
4054
4371
|
const [propertyName, max] = missingProperties[indexMissingProperty];
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
offset += extraction.bytes;
|
|
4059
|
-
} else if (extraFieldZip64[propertyName]) {
|
|
4060
|
-
throw new Error(ERR_EXTRAFIELD_ZIP64_NOT_FOUND);
|
|
4061
|
-
}
|
|
4372
|
+
const extraction = ZIP64_EXTRACTION[max];
|
|
4373
|
+
directory[propertyName] = extraFieldZip64[propertyName] = extraction.getValue(extraFieldView, offset);
|
|
4374
|
+
offset += extraction.bytes;
|
|
4062
4375
|
}
|
|
4063
4376
|
}
|
|
4064
4377
|
|
|
4065
4378
|
function readExtraFieldUnicode(extraFieldUnicode, propertyName, rawPropertyName, directory, fileEntry) {
|
|
4379
|
+
if (extraFieldUnicode.data.length < 5) {
|
|
4380
|
+
extraFieldUnicode.valid = false;
|
|
4381
|
+
return;
|
|
4382
|
+
}
|
|
4066
4383
|
const extraFieldView = getDataView$1(extraFieldUnicode.data);
|
|
4067
4384
|
const crc32 = new Crc32();
|
|
4068
4385
|
crc32.append(fileEntry[rawPropertyName]);
|
|
@@ -4135,32 +4452,30 @@ function readExtraFieldNTFS(extraFieldNTFS, directory) {
|
|
|
4135
4452
|
function readExtraFieldUnix(extraField, directory, isInfoZip) {
|
|
4136
4453
|
try {
|
|
4137
4454
|
const view = getDataView$1(new Uint8Array(extraField.data));
|
|
4138
|
-
let
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
if (
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4455
|
+
let uid, gid;
|
|
4456
|
+
if (isInfoZip) {
|
|
4457
|
+
// Info-ZIP New Unix "ux" field (0x7875): version + variable-length uid/gid
|
|
4458
|
+
let offset = 0;
|
|
4459
|
+
const version = getUint8(view, offset++);
|
|
4460
|
+
const uidSize = getUint8(view, offset++);
|
|
4461
|
+
uid = unpackUnixId(extraField.data.subarray(offset, offset + uidSize));
|
|
4462
|
+
offset += uidSize;
|
|
4463
|
+
const gidSize = getUint8(view, offset++);
|
|
4464
|
+
gid = unpackUnixId(extraField.data.subarray(offset, offset + gidSize));
|
|
4465
|
+
Object.assign(extraField, { version, uid, gid });
|
|
4466
|
+
} else if (extraField.data.length >= 4) {
|
|
4467
|
+
// Info-ZIP Unix "Ux" field (0x7855): fixed 2-byte uid + gid (the file mode, if any, is
|
|
4468
|
+
// carried in the external file attributes, not here)
|
|
4469
|
+
uid = getUint16(view, 0);
|
|
4470
|
+
gid = getUint16(view, 2);
|
|
4471
|
+
Object.assign(extraField, { uid, gid });
|
|
4472
|
+
}
|
|
4155
4473
|
if (uid !== UNDEFINED_VALUE) {
|
|
4156
4474
|
directory.uid = uid;
|
|
4157
4475
|
}
|
|
4158
4476
|
if (gid !== UNDEFINED_VALUE) {
|
|
4159
4477
|
directory.gid = gid;
|
|
4160
4478
|
}
|
|
4161
|
-
if (unixMode !== UNDEFINED_VALUE) {
|
|
4162
|
-
directory.unixMode = unixMode;
|
|
4163
|
-
}
|
|
4164
4479
|
} catch {
|
|
4165
4480
|
// ignored
|
|
4166
4481
|
}
|
|
@@ -4174,6 +4489,9 @@ function unpackUnixId(bytes) {
|
|
|
4174
4489
|
}
|
|
4175
4490
|
|
|
4176
4491
|
function readExtraFieldExtendedTimestamp(extraFieldExtendedTimestamp, directory, localDirectory) {
|
|
4492
|
+
if (!extraFieldExtendedTimestamp.data.length) {
|
|
4493
|
+
return;
|
|
4494
|
+
}
|
|
4177
4495
|
const extraFieldView = getDataView$1(extraFieldExtendedTimestamp.data);
|
|
4178
4496
|
const flags = getUint8(extraFieldView, 0);
|
|
4179
4497
|
const timeProperties = [];
|
|
@@ -4199,7 +4517,8 @@ function readExtraFieldExtendedTimestamp(extraFieldExtendedTimestamp, directory,
|
|
|
4199
4517
|
timeProperties.forEach((propertyName, indexProperty) => {
|
|
4200
4518
|
if (extraFieldExtendedTimestamp.data.length >= offset + 4) {
|
|
4201
4519
|
const time = getUint32(extraFieldView, offset);
|
|
4202
|
-
|
|
4520
|
+
// the extended timestamp is a signed 32-bit time_t value
|
|
4521
|
+
directory[propertyName] = extraFieldExtendedTimestamp[propertyName] = new Date((time | 0) * 1000);
|
|
4203
4522
|
const rawPropertyName = timeRawProperties[indexProperty];
|
|
4204
4523
|
extraFieldExtendedTimestamp[rawPropertyName] = time;
|
|
4205
4524
|
}
|
|
@@ -4210,6 +4529,7 @@ function readExtraFieldExtendedTimestamp(extraFieldExtendedTimestamp, directory,
|
|
|
4210
4529
|
async function detectOverlappingEntry({
|
|
4211
4530
|
reader,
|
|
4212
4531
|
fileEntry,
|
|
4532
|
+
index,
|
|
4213
4533
|
offset,
|
|
4214
4534
|
diskNumberStart,
|
|
4215
4535
|
signature,
|
|
@@ -4221,10 +4541,9 @@ async function detectOverlappingEntry({
|
|
|
4221
4541
|
readRanges
|
|
4222
4542
|
}) {
|
|
4223
4543
|
let diskOffset = 0;
|
|
4224
|
-
if (diskNumberStart) {
|
|
4225
|
-
for (let indexReader = 0; indexReader < diskNumberStart; indexReader++) {
|
|
4226
|
-
|
|
4227
|
-
diskOffset += diskReader.size;
|
|
4544
|
+
if (diskNumberStart && reader.readers) {
|
|
4545
|
+
for (let indexReader = 0; indexReader < Math.min(diskNumberStart, reader.readers.length); indexReader++) {
|
|
4546
|
+
diskOffset += reader.readers[indexReader].size;
|
|
4228
4547
|
}
|
|
4229
4548
|
}
|
|
4230
4549
|
let dataDescriptorLength = 0;
|
|
@@ -4237,7 +4556,8 @@ async function detectOverlappingEntry({
|
|
|
4237
4556
|
}
|
|
4238
4557
|
if (dataDescriptorLength) {
|
|
4239
4558
|
const dataDescriptorArray = await readUint8Array(reader, dataOffset + compressedSize, dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH, diskNumberStart);
|
|
4240
|
-
const dataDescriptorSignature =
|
|
4559
|
+
const dataDescriptorSignature = dataDescriptorArray.length == dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH &&
|
|
4560
|
+
getUint32(getDataView$1(dataDescriptorArray), 0) == DATA_DESCRIPTOR_RECORD_SIGNATURE;
|
|
4241
4561
|
if (dataDescriptorSignature) {
|
|
4242
4562
|
const readSignature = getUint32(getDataView$1(dataDescriptorArray), 4);
|
|
4243
4563
|
let readCompressedSize;
|
|
@@ -4262,14 +4582,14 @@ async function detectOverlappingEntry({
|
|
|
4262
4582
|
end: diskOffset + dataOffset + compressedSize + dataDescriptorLength,
|
|
4263
4583
|
fileEntry
|
|
4264
4584
|
};
|
|
4265
|
-
for (const otherRange of readRanges) {
|
|
4266
|
-
if (
|
|
4585
|
+
for (const [otherIndex, otherRange] of readRanges) {
|
|
4586
|
+
if (otherIndex != index && range.start < otherRange.end && otherRange.start < range.end) {
|
|
4267
4587
|
const error = new Error(ERR_OVERLAPPING_ENTRY);
|
|
4268
4588
|
error.overlappingEntry = otherRange.fileEntry;
|
|
4269
4589
|
throw error;
|
|
4270
4590
|
}
|
|
4271
4591
|
}
|
|
4272
|
-
readRanges.
|
|
4592
|
+
readRanges.set(index, range);
|
|
4273
4593
|
}
|
|
4274
4594
|
|
|
4275
4595
|
async function seekSignature(reader, signature, startOffset, minimumBytes, maximumLength) {
|
|
@@ -4294,6 +4614,35 @@ async function seekSignature(reader, signature, startOffset, minimumBytes, maxim
|
|
|
4294
4614
|
}
|
|
4295
4615
|
}
|
|
4296
4616
|
|
|
4617
|
+
function checkLocalDirectory(zipEntry, localDirectory, rawLocalFilename) {
|
|
4618
|
+
const { rawFilename } = zipEntry;
|
|
4619
|
+
if (rawLocalFilename.length != rawFilename.length ||
|
|
4620
|
+
rawLocalFilename.some((byteValue, indexByte) => byteValue != rawFilename[indexByte])) {
|
|
4621
|
+
throwAmbiguousArchive("mismatched local file header (filename)");
|
|
4622
|
+
}
|
|
4623
|
+
if ((localDirectory.rawBitFlag & BITFLAG_AMBIGUITY_MASK) != (zipEntry.rawBitFlag & BITFLAG_AMBIGUITY_MASK)) {
|
|
4624
|
+
throwAmbiguousArchive("mismatched local file header (general purpose bit flag)");
|
|
4625
|
+
}
|
|
4626
|
+
if (localDirectory.compressionMethod != zipEntry.compressionMethod) {
|
|
4627
|
+
throwAmbiguousArchive("mismatched local file header (compression method)");
|
|
4628
|
+
}
|
|
4629
|
+
// when the data descriptor flag is set, the local signature and sizes are zeroed out; all-zero values are
|
|
4630
|
+
// also tolerated when the flag is clear because some tools produce them (streaming writers predating bit 3)
|
|
4631
|
+
if (!localDirectory.bitFlag.dataDescriptor &&
|
|
4632
|
+
(localDirectory.signature || localDirectory.compressedSize || localDirectory.uncompressedSize) &&
|
|
4633
|
+
(localDirectory.signature != zipEntry.signature ||
|
|
4634
|
+
localDirectory.compressedSize != zipEntry.compressedSize ||
|
|
4635
|
+
localDirectory.uncompressedSize != zipEntry.uncompressedSize)) {
|
|
4636
|
+
throwAmbiguousArchive("mismatched local file header (signature or sizes)");
|
|
4637
|
+
}
|
|
4638
|
+
}
|
|
4639
|
+
|
|
4640
|
+
function throwAmbiguousArchive(reason) {
|
|
4641
|
+
const error = new Error(ERR_AMBIGUOUS_ARCHIVE);
|
|
4642
|
+
error.reason = reason;
|
|
4643
|
+
throw error;
|
|
4644
|
+
}
|
|
4645
|
+
|
|
4297
4646
|
function getOptionValue$1(zipReader, options, name) {
|
|
4298
4647
|
return options[name] === UNDEFINED_VALUE ? zipReader.options[name] : options[name];
|
|
4299
4648
|
}
|
|
@@ -4332,7 +4681,7 @@ function setUint32$1(view, offset, value) {
|
|
|
4332
4681
|
}
|
|
4333
4682
|
|
|
4334
4683
|
function getDataView$1(array) {
|
|
4335
|
-
return new DataView(array.buffer);
|
|
4684
|
+
return new DataView(array.buffer, array.byteOffset, array.byteLength);
|
|
4336
4685
|
}
|
|
4337
4686
|
|
|
4338
4687
|
/*
|
|
@@ -4372,13 +4721,19 @@ const ERR_INVALID_VERSION = "Version exceeds 65535";
|
|
|
4372
4721
|
const ERR_INVALID_ENCRYPTION_STRENGTH = "The strength must equal 1, 2, or 3";
|
|
4373
4722
|
const ERR_INVALID_EXTRAFIELD_TYPE = "Extra field type exceeds 65535";
|
|
4374
4723
|
const ERR_INVALID_EXTRAFIELD_DATA = "Extra field data exceeds 64KB";
|
|
4724
|
+
// same message as the constant exported by zip-reader.js
|
|
4725
|
+
const ERR_UNSUPPORTED_COMPRESSION = "Compression method not supported";
|
|
4726
|
+
const MIN_UNIX_TIME = -2147483648;
|
|
4727
|
+
const MAX_UNIX_TIME = 2147483647;
|
|
4375
4728
|
const ERR_UNSUPPORTED_FORMAT = "Zip64 is not supported (set the 'zip64' option to 'true')";
|
|
4376
4729
|
const ERR_UNDEFINED_UNCOMPRESSED_SIZE = "Undefined uncompressed size";
|
|
4730
|
+
const ERR_UNDEFINED_READER = "Undefined reader";
|
|
4377
4731
|
const ERR_ZIP_NOT_EMPTY = "Zip file not empty";
|
|
4378
4732
|
const ERR_INVALID_UID = "Invalid uid (must be integer 0..2^32-1)";
|
|
4379
4733
|
const ERR_INVALID_GID = "Invalid gid (must be integer 0..2^32-1)";
|
|
4380
4734
|
const ERR_INVALID_UNIX_MODE = "Invalid UNIX mode (must be integer 0..65535)";
|
|
4381
4735
|
const ERR_INVALID_UNIX_EXTRA_FIELD_TYPE = "Invalid unixExtraFieldType (must be 'infozip' or 'unix')";
|
|
4736
|
+
const ERR_INVALID_UNIX_ID_SIZE = "uid/gid must be 0..65535 for unixExtraFieldType 'unix' (use 'infozip' for larger ids)";
|
|
4382
4737
|
const ERR_INVALID_MSDOS_ATTRIBUTES = "Invalid msdosAttributesRaw (must be integer 0..255)";
|
|
4383
4738
|
const ERR_INVALID_MSDOS_DATA = "Invalid msdosAttributes (must be an object with boolean flags)";
|
|
4384
4739
|
|
|
@@ -4404,9 +4759,10 @@ class ZipWriter {
|
|
|
4404
4759
|
files: new Map(),
|
|
4405
4760
|
filenames: new Set(),
|
|
4406
4761
|
offset: options[OPTION_OFFSET] === UNDEFINED_VALUE ? writer.size || writer.writable.size || 0 : options[OPTION_OFFSET],
|
|
4407
|
-
|
|
4762
|
+
initialOffset: options[OPTION_OFFSET] === UNDEFINED_VALUE ? 0 : options[OPTION_OFFSET] - (writer.size || writer.writable.size || 0),
|
|
4408
4763
|
pendingAddFileCalls: new Set(),
|
|
4409
|
-
bufferedWrites: 0
|
|
4764
|
+
bufferedWrites: 0,
|
|
4765
|
+
lastFileEntry: UNDEFINED_VALUE
|
|
4410
4766
|
});
|
|
4411
4767
|
}
|
|
4412
4768
|
|
|
@@ -4415,17 +4771,18 @@ class ZipWriter {
|
|
|
4415
4771
|
throw new Error(ERR_ZIP_NOT_EMPTY);
|
|
4416
4772
|
}
|
|
4417
4773
|
reader = new GenericReader(reader);
|
|
4774
|
+
await initStream(reader);
|
|
4418
4775
|
const zipReader = new ZipReader(reader.readable);
|
|
4419
4776
|
const entries = await zipReader.getEntries();
|
|
4420
4777
|
await zipReader.close();
|
|
4778
|
+
await initStream(this.writer);
|
|
4421
4779
|
await reader.readable.pipeTo(this.writer.writable, { preventClose: true, preventAbort: true });
|
|
4422
4780
|
this.writer.size = this.offset = reader.size;
|
|
4423
4781
|
this.filenames = new Set(entries.map(entry => entry.filename));
|
|
4424
4782
|
this.files = new Map(entries.map(entry => {
|
|
4425
4783
|
const {
|
|
4426
4784
|
version,
|
|
4427
|
-
|
|
4428
|
-
lastModDate,
|
|
4785
|
+
rawLastModDate,
|
|
4429
4786
|
lastAccessDate,
|
|
4430
4787
|
creationDate,
|
|
4431
4788
|
rawFilename,
|
|
@@ -4438,6 +4795,7 @@ class ZipWriter {
|
|
|
4438
4795
|
zip64
|
|
4439
4796
|
} = entry;
|
|
4440
4797
|
let {
|
|
4798
|
+
compressionMethod,
|
|
4441
4799
|
rawExtraFieldZip64,
|
|
4442
4800
|
rawExtraFieldAES,
|
|
4443
4801
|
rawExtraFieldExtendedTimestamp,
|
|
@@ -4450,31 +4808,39 @@ class ZipWriter {
|
|
|
4450
4808
|
rawExtraFieldAES = rawExtraFieldAES || new Uint8Array();
|
|
4451
4809
|
rawExtraFieldExtendedTimestamp = rawExtraFieldExtendedTimestamp || new Uint8Array();
|
|
4452
4810
|
rawExtraFieldNTFS = rawExtraFieldNTFS || new Uint8Array();
|
|
4453
|
-
rawExtraFieldUnix =
|
|
4811
|
+
rawExtraFieldUnix = rawExtraFieldUnix || new Uint8Array();
|
|
4454
4812
|
rawExtraField = rawExtraField || new Uint8Array();
|
|
4813
|
+
if (entry.extraFieldAES) {
|
|
4814
|
+
compressionMethod = COMPRESSION_METHOD_AES;
|
|
4815
|
+
}
|
|
4455
4816
|
const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField);
|
|
4456
|
-
const zip64UncompressedSize = zip64 && uncompressedSize
|
|
4457
|
-
const zip64CompressedSize = zip64 && compressedSize
|
|
4817
|
+
const zip64UncompressedSize = zip64 && uncompressedSize >= MAX_32_BITS;
|
|
4818
|
+
const zip64CompressedSize = zip64 && compressedSize >= MAX_32_BITS;
|
|
4819
|
+
const bitFlagValue = (getBitFlag(level, languageEncodingFlag, dataDescriptor, encrypted, compressionMethod) & ~BITFLAG_LEVEL) | (level << 1);
|
|
4458
4820
|
const {
|
|
4459
4821
|
headerArray,
|
|
4460
4822
|
headerView
|
|
4461
4823
|
} = getHeaderArrayData({
|
|
4462
4824
|
version,
|
|
4463
|
-
bitFlag:
|
|
4825
|
+
bitFlag: bitFlagValue,
|
|
4464
4826
|
compressionMethod,
|
|
4465
4827
|
uncompressedSize,
|
|
4466
4828
|
compressedSize,
|
|
4467
|
-
|
|
4829
|
+
rawLastModDate,
|
|
4468
4830
|
rawFilename,
|
|
4469
4831
|
zip64CompressedSize,
|
|
4470
4832
|
zip64UncompressedSize,
|
|
4471
4833
|
extraFieldLength
|
|
4472
4834
|
});
|
|
4835
|
+
const { signature } = entry;
|
|
4836
|
+
if (signature !== UNDEFINED_VALUE) {
|
|
4837
|
+
setUint32(headerView, HEADER_OFFSET_SIGNATURE, signature);
|
|
4838
|
+
}
|
|
4473
4839
|
Object.assign(entry, {
|
|
4474
4840
|
zip64UncompressedSize,
|
|
4475
4841
|
zip64CompressedSize,
|
|
4476
|
-
zip64Offset: zip64 && this.offset - diskOffset
|
|
4477
|
-
zip64DiskNumberStart: zip64 && diskNumber
|
|
4842
|
+
zip64Offset: zip64 && this.offset - diskOffset >= MAX_32_BITS,
|
|
4843
|
+
zip64DiskNumberStart: zip64 && diskNumber >= MAX_16_BITS,
|
|
4478
4844
|
rawExtraFieldZip64,
|
|
4479
4845
|
rawExtraFieldAES,
|
|
4480
4846
|
rawExtraFieldExtendedTimestamp,
|
|
@@ -4492,6 +4858,7 @@ class ZipWriter {
|
|
|
4492
4858
|
|
|
4493
4859
|
async add(name = "", reader, options = {}) {
|
|
4494
4860
|
const zipWriter = this;
|
|
4861
|
+
options = Object.assign({}, options);
|
|
4495
4862
|
const {
|
|
4496
4863
|
pendingAddFileCalls,
|
|
4497
4864
|
config
|
|
@@ -4502,17 +4869,24 @@ class ZipWriter {
|
|
|
4502
4869
|
await new Promise(resolve => pendingEntries.push(resolve));
|
|
4503
4870
|
}
|
|
4504
4871
|
let promiseAddFile;
|
|
4872
|
+
let nameAdded;
|
|
4505
4873
|
try {
|
|
4506
4874
|
name = name.trim();
|
|
4875
|
+
if (getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY) && !name.endsWith(DIRECTORY_SIGNATURE)) {
|
|
4876
|
+
name += DIRECTORY_SIGNATURE;
|
|
4877
|
+
}
|
|
4507
4878
|
if (zipWriter.filenames.has(name)) {
|
|
4508
4879
|
throw new Error(ERR_DUPLICATED_NAME);
|
|
4509
4880
|
}
|
|
4510
4881
|
zipWriter.filenames.add(name);
|
|
4882
|
+
nameAdded = true;
|
|
4511
4883
|
promiseAddFile = addFile(zipWriter, name, reader, options);
|
|
4512
4884
|
pendingAddFileCalls.add(promiseAddFile);
|
|
4513
4885
|
return await promiseAddFile;
|
|
4514
4886
|
} catch (error) {
|
|
4515
|
-
|
|
4887
|
+
if (nameAdded) {
|
|
4888
|
+
zipWriter.filenames.delete(name);
|
|
4889
|
+
}
|
|
4516
4890
|
throw error;
|
|
4517
4891
|
} finally {
|
|
4518
4892
|
pendingAddFileCalls.delete(promiseAddFile);
|
|
@@ -4545,6 +4919,9 @@ class ZipWriter {
|
|
|
4545
4919
|
const zipWriter = this;
|
|
4546
4920
|
const { pendingAddFileCalls, writer } = this;
|
|
4547
4921
|
const { writable } = writer;
|
|
4922
|
+
if (getLength(comment) > MAX_16_BITS) {
|
|
4923
|
+
throw new Error(ERR_INVALID_COMMENT);
|
|
4924
|
+
}
|
|
4548
4925
|
while (pendingAddFileCalls.size) {
|
|
4549
4926
|
await Promise.allSettled(Array.from(pendingAddFileCalls));
|
|
4550
4927
|
}
|
|
@@ -4563,28 +4940,94 @@ class ZipWriterStream {
|
|
|
4563
4940
|
const { readable, writable } = new TransformStream();
|
|
4564
4941
|
this.readable = readable;
|
|
4565
4942
|
this.zipWriter = new ZipWriter(writable, options);
|
|
4943
|
+
this.pendingAddFileCalls = new Set();
|
|
4566
4944
|
}
|
|
4567
4945
|
|
|
4568
4946
|
transform(path) {
|
|
4947
|
+
const zipWriter = this.zipWriter;
|
|
4948
|
+
let streamController;
|
|
4569
4949
|
const { readable, writable } = new TransformStream({
|
|
4570
|
-
|
|
4950
|
+
start(controller) {
|
|
4951
|
+
streamController = controller;
|
|
4952
|
+
},
|
|
4953
|
+
flush: () => void closeArchive()
|
|
4571
4954
|
});
|
|
4572
|
-
this.zipWriter.add(path, readable);
|
|
4955
|
+
watchAddFileCall(this, this.zipWriter.add(path, readable), error => streamController.error(error));
|
|
4573
4956
|
return { readable: this.readable, writable };
|
|
4957
|
+
|
|
4958
|
+
async function closeArchive() {
|
|
4959
|
+
try {
|
|
4960
|
+
await zipWriter.close();
|
|
4961
|
+
} catch (error) {
|
|
4962
|
+
try {
|
|
4963
|
+
await zipWriter.writer.writable.abort(error);
|
|
4964
|
+
} catch {
|
|
4965
|
+
// ignored
|
|
4966
|
+
}
|
|
4967
|
+
}
|
|
4968
|
+
}
|
|
4574
4969
|
}
|
|
4575
4970
|
|
|
4576
4971
|
writable(path) {
|
|
4577
|
-
|
|
4578
|
-
|
|
4972
|
+
let streamController;
|
|
4973
|
+
const { readable, writable } = new TransformStream({
|
|
4974
|
+
start(controller) {
|
|
4975
|
+
streamController = controller;
|
|
4976
|
+
}
|
|
4977
|
+
});
|
|
4978
|
+
watchAddFileCall(this, this.zipWriter.add(path, readable), error => streamController.error(error));
|
|
4579
4979
|
return writable;
|
|
4580
4980
|
}
|
|
4581
4981
|
|
|
4582
|
-
close(comment = UNDEFINED_VALUE, options = {}) {
|
|
4982
|
+
async close(comment = UNDEFINED_VALUE, options = {}) {
|
|
4983
|
+
await Promise.all(Array.from(this.pendingAddFileCalls));
|
|
4583
4984
|
return this.zipWriter.close(comment, options);
|
|
4584
4985
|
}
|
|
4585
4986
|
}
|
|
4586
4987
|
|
|
4988
|
+
function watchAddFileCall(zipWriterStream, promiseAddFile, onerror) {
|
|
4989
|
+
zipWriterStream.pendingAddFileCalls.add(promiseAddFile);
|
|
4990
|
+
promiseAddFile.catch(error => {
|
|
4991
|
+
try {
|
|
4992
|
+
onerror(error);
|
|
4993
|
+
} catch {
|
|
4994
|
+
// ignored
|
|
4995
|
+
}
|
|
4996
|
+
});
|
|
4997
|
+
}
|
|
4998
|
+
|
|
4587
4999
|
async function addFile(zipWriter, name, reader, options) {
|
|
5000
|
+
const attributesInfo = resolveAttributes(zipWriter, name, options);
|
|
5001
|
+
({ name } = attributesInfo);
|
|
5002
|
+
const metadataInfo = resolveMetadata(zipWriter, name, options);
|
|
5003
|
+
const { comment } = metadataInfo;
|
|
5004
|
+
const extraField = options[PROPERTY_NAME_EXTRA_FIELD];
|
|
5005
|
+
zipWriter.files.set(name, UNDEFINED_VALUE);
|
|
5006
|
+
let fileEntry;
|
|
5007
|
+
try {
|
|
5008
|
+
const sizesInfo = await resolveSizes(zipWriter, reader, metadataInfo, options);
|
|
5009
|
+
({ reader } = sizesInfo);
|
|
5010
|
+
const { diskOffset, diskNumber } = zipWriter.writer;
|
|
5011
|
+
options = Object.assign({}, options, attributesInfo.resolvedOptions, metadataInfo.resolvedOptions, sizesInfo.resolvedOptions, {
|
|
5012
|
+
internalFileAttribute: metadataInfo.resolvedOptions.internalFileAttributes,
|
|
5013
|
+
externalFileAttribute: attributesInfo.resolvedOptions.externalFileAttributes,
|
|
5014
|
+
signature: options[PROPERTY_NAME_SIGNATURE],
|
|
5015
|
+
offset: zipWriter.offset - diskOffset,
|
|
5016
|
+
diskNumberStart: diskNumber
|
|
5017
|
+
});
|
|
5018
|
+
const headerInfo = getHeaderInfo(options);
|
|
5019
|
+
const dataDescriptorInfo = getDataDescriptorInfo(options);
|
|
5020
|
+
const metadataSize = getLength(headerInfo.localHeaderArray, dataDescriptorInfo.dataDescriptorArray);
|
|
5021
|
+
fileEntry = await getFileEntry(zipWriter, name, reader, { headerInfo, dataDescriptorInfo, metadataSize }, options);
|
|
5022
|
+
} catch (error) {
|
|
5023
|
+
zipWriter.files.delete(name);
|
|
5024
|
+
throw error;
|
|
5025
|
+
}
|
|
5026
|
+
Object.assign(fileEntry, { name, comment, extraField });
|
|
5027
|
+
return new Entry(fileEntry);
|
|
5028
|
+
}
|
|
5029
|
+
|
|
5030
|
+
function resolveAttributes(zipWriter, name, options) {
|
|
4588
5031
|
name = name.trim();
|
|
4589
5032
|
let msDosCompatible = getOptionValue(zipWriter, options, PROPERTY_NAME_MS_DOS_COMPATIBLE);
|
|
4590
5033
|
let versionMadeBy = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION_MADE_BY, msDosCompatible ? 20 : 768);
|
|
@@ -4592,7 +5035,7 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
4592
5035
|
const uid = getOptionValue(zipWriter, options, PROPERTY_NAME_UID);
|
|
4593
5036
|
const gid = getOptionValue(zipWriter, options, PROPERTY_NAME_GID);
|
|
4594
5037
|
let unixMode = getOptionValue(zipWriter, options, PROPERTY_NAME_UNIX_MODE);
|
|
4595
|
-
|
|
5038
|
+
let unixExtraFieldType = getOptionValue(zipWriter, options, OPTION_UNIX_EXTRA_FIELD_TYPE);
|
|
4596
5039
|
let setuid = getOptionValue(zipWriter, options, PROPERTY_NAME_SETUID);
|
|
4597
5040
|
let setgid = getOptionValue(zipWriter, options, PROPERTY_NAME_SETGID);
|
|
4598
5041
|
let sticky = getOptionValue(zipWriter, options, PROPERTY_NAME_STICKY);
|
|
@@ -4608,6 +5051,13 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
4608
5051
|
if (unixExtraFieldType !== UNDEFINED_VALUE && unixExtraFieldType !== INFOZIP_EXTRA_FIELD_TYPE && unixExtraFieldType !== UNIX_EXTRA_FIELD_TYPE) {
|
|
4609
5052
|
throw new Error(ERR_INVALID_UNIX_EXTRA_FIELD_TYPE);
|
|
4610
5053
|
}
|
|
5054
|
+
if (unixExtraFieldType === UNIX_EXTRA_FIELD_TYPE &&
|
|
5055
|
+
((uid !== UNDEFINED_VALUE && uid > MAX_16_BITS) || (gid !== UNDEFINED_VALUE && gid > MAX_16_BITS))) {
|
|
5056
|
+
throw new Error(ERR_INVALID_UNIX_ID_SIZE);
|
|
5057
|
+
}
|
|
5058
|
+
if (unixExtraFieldType === UNDEFINED_VALUE && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
|
|
5059
|
+
unixExtraFieldType = INFOZIP_EXTRA_FIELD_TYPE;
|
|
5060
|
+
}
|
|
4611
5061
|
let msdosAttributesRaw = getOptionValue(zipWriter, options, PROPERTY_NAME_MSDOS_ATTRIBUTES_RAW);
|
|
4612
5062
|
let msdosAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_MSDOS_ATTRIBUTES);
|
|
4613
5063
|
const hasUnixMetadata = uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE || unixMode !== UNDEFINED_VALUE || unixExtraFieldType;
|
|
@@ -4678,6 +5128,27 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
4678
5128
|
if (hasMsDosProvided) {
|
|
4679
5129
|
externalFileAttributes = (externalFileAttributes & MAX_32_BITS) | (msdosAttributesRaw & MAX_8_BITS);
|
|
4680
5130
|
}
|
|
5131
|
+
return {
|
|
5132
|
+
name,
|
|
5133
|
+
resolvedOptions: {
|
|
5134
|
+
versionMadeBy,
|
|
5135
|
+
msDosCompatible,
|
|
5136
|
+
externalFileAttributes,
|
|
5137
|
+
unixExternalUpper,
|
|
5138
|
+
uid,
|
|
5139
|
+
gid,
|
|
5140
|
+
unixMode,
|
|
5141
|
+
unixExtraFieldType,
|
|
5142
|
+
setuid,
|
|
5143
|
+
setgid,
|
|
5144
|
+
sticky,
|
|
5145
|
+
msdosAttributesRaw,
|
|
5146
|
+
msdosAttributes
|
|
5147
|
+
}
|
|
5148
|
+
};
|
|
5149
|
+
}
|
|
5150
|
+
|
|
5151
|
+
function resolveMetadata(zipWriter, name, options) {
|
|
4681
5152
|
const encode = getOptionValue(zipWriter, options, OPTION_ENCODE_TEXT, encodeText);
|
|
4682
5153
|
let rawFilename = encode(name);
|
|
4683
5154
|
if (rawFilename === UNDEFINED_VALUE) {
|
|
@@ -4716,10 +5187,14 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
4716
5187
|
const transferStreams = getOptionValue(zipWriter, options, OPTION_TRANSFER_STREAMS, true);
|
|
4717
5188
|
const bufferedWrite = getOptionValue(zipWriter, options, OPTION_BUFFERED_WRITE);
|
|
4718
5189
|
const createTempStream = getOptionValue(zipWriter, options, OPTION_CREATE_TEMP_STREAM);
|
|
4719
|
-
const dataDescriptorSignature = getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR_SIGNATURE,
|
|
5190
|
+
const dataDescriptorSignature = getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR_SIGNATURE, true);
|
|
4720
5191
|
const signal = getOptionValue(zipWriter, options, OPTION_SIGNAL);
|
|
4721
5192
|
const useUnicodeFileNames = getOptionValue(zipWriter, options, OPTION_USE_UNICODE_FILE_NAMES, true);
|
|
4722
5193
|
const compressionMethod = getOptionValue(zipWriter, options, PROPERTY_NAME_COMPRESSION_METHOD);
|
|
5194
|
+
if (!passThrough && compressionMethod !== UNDEFINED_VALUE &&
|
|
5195
|
+
compressionMethod !== COMPRESSION_METHOD_STORE && compressionMethod !== COMPRESSION_METHOD_DEFLATE) {
|
|
5196
|
+
throw new Error(ERR_UNSUPPORTED_COMPRESSION);
|
|
5197
|
+
}
|
|
4723
5198
|
let level = getOptionValue(zipWriter, options, OPTION_LEVEL);
|
|
4724
5199
|
let useCompressionStream = getOptionValue(zipWriter, options, OPTION_USE_COMPRESSION_STREAM);
|
|
4725
5200
|
let dataDescriptor = getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR);
|
|
@@ -4735,7 +5210,7 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
4735
5210
|
if (!useCompressionStream && (zipWriter.config.CompressionStream === UNDEFINED_VALUE && zipWriter.config.CompressionStreamZlib === UNDEFINED_VALUE)) {
|
|
4736
5211
|
level = 0;
|
|
4737
5212
|
}
|
|
4738
|
-
|
|
5213
|
+
const zip64 = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIP64);
|
|
4739
5214
|
if (!zipCrypto && (password !== UNDEFINED_VALUE || rawPassword !== UNDEFINED_VALUE) && !(encryptionStrength >= 1 && encryptionStrength <= 3)) {
|
|
4740
5215
|
throw new Error(ERR_INVALID_ENCRYPTION_STRENGTH);
|
|
4741
5216
|
}
|
|
@@ -4746,6 +5221,7 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
4746
5221
|
let offset = 0;
|
|
4747
5222
|
extraField.forEach(data => extraFieldSize += 4 + getLength(data));
|
|
4748
5223
|
rawExtraField = new Uint8Array(extraFieldSize);
|
|
5224
|
+
const rawExtraFieldView = getDataView(rawExtraField);
|
|
4749
5225
|
extraField.forEach((data, type) => {
|
|
4750
5226
|
if (type > MAX_16_BITS) {
|
|
4751
5227
|
throw new Error(ERR_INVALID_EXTRAFIELD_TYPE);
|
|
@@ -4753,22 +5229,72 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
4753
5229
|
if (getLength(data) > MAX_16_BITS) {
|
|
4754
5230
|
throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
|
|
4755
5231
|
}
|
|
4756
|
-
|
|
4757
|
-
|
|
5232
|
+
setUint16(rawExtraFieldView, offset, type);
|
|
5233
|
+
setUint16(rawExtraFieldView, offset + 2, getLength(data));
|
|
4758
5234
|
arraySet(rawExtraField, data, offset + 4);
|
|
4759
5235
|
offset += 4 + getLength(data);
|
|
4760
5236
|
});
|
|
4761
5237
|
}
|
|
5238
|
+
return {
|
|
5239
|
+
comment,
|
|
5240
|
+
resolvedOptions: {
|
|
5241
|
+
rawFilename,
|
|
5242
|
+
rawComment,
|
|
5243
|
+
version,
|
|
5244
|
+
lastModDate,
|
|
5245
|
+
lastAccessDate,
|
|
5246
|
+
creationDate,
|
|
5247
|
+
internalFileAttributes,
|
|
5248
|
+
passThrough,
|
|
5249
|
+
password,
|
|
5250
|
+
rawPassword,
|
|
5251
|
+
encryptionStrength,
|
|
5252
|
+
zipCrypto,
|
|
5253
|
+
extendedTimestamp,
|
|
5254
|
+
keepOrder,
|
|
5255
|
+
useWebWorkers,
|
|
5256
|
+
transferStreams,
|
|
5257
|
+
bufferedWrite,
|
|
5258
|
+
createTempStream,
|
|
5259
|
+
dataDescriptorSignature,
|
|
5260
|
+
signal,
|
|
5261
|
+
useUnicodeFileNames,
|
|
5262
|
+
compressionMethod,
|
|
5263
|
+
level,
|
|
5264
|
+
useCompressionStream,
|
|
5265
|
+
dataDescriptor,
|
|
5266
|
+
zip64,
|
|
5267
|
+
rawExtraField
|
|
5268
|
+
}
|
|
5269
|
+
};
|
|
5270
|
+
}
|
|
5271
|
+
|
|
5272
|
+
async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, options) {
|
|
5273
|
+
const { passThrough, zipCrypto, password, rawPassword, encryptionStrength } = metadata;
|
|
5274
|
+
let { dataDescriptor, zip64, level, compressionMethod } = metadata;
|
|
4762
5275
|
let maximumCompressedSize = 0;
|
|
4763
|
-
let maximumEntrySize = 0;
|
|
4764
5276
|
let uncompressedSize = 0;
|
|
4765
5277
|
if (passThrough) {
|
|
5278
|
+
// the headers of a passThrough entry describe the payload verbatim: without a
|
|
5279
|
+
// reader they would declare content that is not there
|
|
5280
|
+
if (!reader) {
|
|
5281
|
+
throw new Error(ERR_UNDEFINED_READER);
|
|
5282
|
+
}
|
|
4766
5283
|
uncompressedSize = options[PROPERTY_NAME_UNCOMPRESSED_SIZE];
|
|
4767
5284
|
if (uncompressedSize === UNDEFINED_VALUE) {
|
|
4768
5285
|
throw new Error(ERR_UNDEFINED_UNCOMPRESSED_SIZE);
|
|
4769
5286
|
}
|
|
4770
5287
|
}
|
|
4771
5288
|
const zip64Enabled = zip64 === true;
|
|
5289
|
+
const encrypted = getOptionValue(zipWriter, options, PROPERTY_NAME_ENCRYPTED);
|
|
5290
|
+
// entries without a reader have no payload: write them as empty stored files instead of
|
|
5291
|
+
// declaring a compressed or encrypted content that does not exist
|
|
5292
|
+
const encryptedEntry = Boolean(reader) && (Boolean((password && getLength(password)) || (rawPassword && getLength(rawPassword))) || (passThrough && encrypted));
|
|
5293
|
+
if (!reader) {
|
|
5294
|
+
level = 0;
|
|
5295
|
+
compressionMethod = COMPRESSION_METHOD_STORE;
|
|
5296
|
+
}
|
|
5297
|
+
const encryptionOverhead = encryptedEntry ? (zipCrypto ? 12 : 16 + encryptionStrength * 4) : 0;
|
|
4772
5298
|
if (reader) {
|
|
4773
5299
|
reader = new GenericReader(reader);
|
|
4774
5300
|
await initStream(reader);
|
|
@@ -4781,16 +5307,15 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
4781
5307
|
}
|
|
4782
5308
|
} else {
|
|
4783
5309
|
options.uncompressedSize = uncompressedSize = reader.size;
|
|
4784
|
-
maximumCompressedSize = getMaximumCompressedSize(uncompressedSize);
|
|
5310
|
+
maximumCompressedSize = getMaximumCompressedSize(uncompressedSize) + encryptionOverhead;
|
|
4785
5311
|
}
|
|
4786
5312
|
} else {
|
|
4787
5313
|
options.uncompressedSize = uncompressedSize;
|
|
4788
|
-
maximumCompressedSize = getMaximumCompressedSize(uncompressedSize);
|
|
5314
|
+
maximumCompressedSize = getMaximumCompressedSize(uncompressedSize) + encryptionOverhead;
|
|
4789
5315
|
}
|
|
4790
5316
|
}
|
|
4791
|
-
const
|
|
4792
|
-
const
|
|
4793
|
-
const zip64CompressedSize = zip64Enabled || maximumCompressedSize > MAX_32_BITS;
|
|
5317
|
+
const zip64UncompressedSize = zip64Enabled || uncompressedSize >= MAX_32_BITS;
|
|
5318
|
+
const zip64CompressedSize = zip64Enabled || maximumCompressedSize >= MAX_32_BITS;
|
|
4794
5319
|
if (zip64UncompressedSize || zip64CompressedSize) {
|
|
4795
5320
|
if (zip64 === false) {
|
|
4796
5321
|
throw new Error(ERR_UNSUPPORTED_FORMAT);
|
|
@@ -4799,73 +5324,19 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
4799
5324
|
}
|
|
4800
5325
|
}
|
|
4801
5326
|
zip64 = zip64 || false;
|
|
4802
|
-
|
|
4803
|
-
|
|
4804
|
-
|
|
4805
|
-
|
|
4806
|
-
|
|
4807
|
-
|
|
4808
|
-
|
|
4809
|
-
|
|
4810
|
-
|
|
4811
|
-
|
|
4812
|
-
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
password,
|
|
4816
|
-
rawPassword,
|
|
4817
|
-
level,
|
|
4818
|
-
useWebWorkers,
|
|
4819
|
-
transferStreams,
|
|
4820
|
-
encryptionStrength,
|
|
4821
|
-
extendedTimestamp,
|
|
4822
|
-
zipCrypto,
|
|
4823
|
-
bufferedWrite,
|
|
4824
|
-
createTempStream,
|
|
4825
|
-
keepOrder,
|
|
4826
|
-
useUnicodeFileNames,
|
|
4827
|
-
dataDescriptor,
|
|
4828
|
-
dataDescriptorSignature,
|
|
4829
|
-
signal,
|
|
4830
|
-
msDosCompatible,
|
|
4831
|
-
internalFileAttribute: internalFileAttributes,
|
|
4832
|
-
internalFileAttributes,
|
|
4833
|
-
externalFileAttribute: externalFileAttributes,
|
|
4834
|
-
externalFileAttributes,
|
|
4835
|
-
useCompressionStream,
|
|
4836
|
-
passThrough,
|
|
4837
|
-
encrypted: Boolean((password && getLength(password)) || (rawPassword && getLength(rawPassword))) || (passThrough && encrypted),
|
|
4838
|
-
signature: options[PROPERTY_NAME_SIGNATURE],
|
|
4839
|
-
compressionMethod,
|
|
4840
|
-
uncompressedSize,
|
|
4841
|
-
offset: zipWriter.offset - diskOffset,
|
|
4842
|
-
diskNumberStart: diskNumber,
|
|
4843
|
-
uid,
|
|
4844
|
-
gid,
|
|
4845
|
-
setuid,
|
|
4846
|
-
setgid,
|
|
4847
|
-
sticky,
|
|
4848
|
-
unixMode,
|
|
4849
|
-
msdosAttributesRaw,
|
|
4850
|
-
msdosAttributes,
|
|
4851
|
-
unixExternalUpper
|
|
4852
|
-
});
|
|
4853
|
-
const headerInfo = getHeaderInfo(options);
|
|
4854
|
-
const dataDescriptorInfo = getDataDescriptorInfo(options);
|
|
4855
|
-
const metadataSize = getLength(headerInfo.localHeaderArray, dataDescriptorInfo.dataDescriptorArray);
|
|
4856
|
-
maximumEntrySize = metadataSize + maximumCompressedSize;
|
|
4857
|
-
if (zipWriter.options[OPTION_USDZ]) {
|
|
4858
|
-
maximumEntrySize += maximumEntrySize + 64;
|
|
4859
|
-
}
|
|
4860
|
-
zipWriter.pendingEntriesSize += maximumEntrySize;
|
|
4861
|
-
let fileEntry;
|
|
4862
|
-
try {
|
|
4863
|
-
fileEntry = await getFileEntry(zipWriter, name, reader, { headerInfo, dataDescriptorInfo, metadataSize }, options);
|
|
4864
|
-
} finally {
|
|
4865
|
-
zipWriter.pendingEntriesSize -= maximumEntrySize;
|
|
4866
|
-
}
|
|
4867
|
-
Object.assign(fileEntry, { name, comment, extraField });
|
|
4868
|
-
return new Entry(fileEntry);
|
|
5327
|
+
return {
|
|
5328
|
+
reader,
|
|
5329
|
+
resolvedOptions: {
|
|
5330
|
+
dataDescriptor,
|
|
5331
|
+
zip64,
|
|
5332
|
+
zip64UncompressedSize,
|
|
5333
|
+
zip64CompressedSize,
|
|
5334
|
+
uncompressedSize,
|
|
5335
|
+
level,
|
|
5336
|
+
compressionMethod,
|
|
5337
|
+
encrypted: encryptedEntry
|
|
5338
|
+
}
|
|
5339
|
+
};
|
|
4869
5340
|
}
|
|
4870
5341
|
|
|
4871
5342
|
async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
@@ -4882,37 +5353,40 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
|
4882
5353
|
headerInfo
|
|
4883
5354
|
} = entryInfo;
|
|
4884
5355
|
const usdz = zipWriter.options[OPTION_USDZ];
|
|
4885
|
-
const previousFileEntry =
|
|
5356
|
+
const previousFileEntry = zipWriter.lastFileEntry;
|
|
4886
5357
|
let fileEntry = {};
|
|
4887
5358
|
let bufferedWrite;
|
|
4888
5359
|
let releaseLockWriter;
|
|
4889
5360
|
let releaseLockCurrentFileEntry;
|
|
4890
5361
|
let writingBufferedEntryData;
|
|
4891
5362
|
let writingEntryData;
|
|
5363
|
+
let writerSizeBeforeEntry;
|
|
5364
|
+
let flushedBufferedSize = 0;
|
|
4892
5365
|
let fileWriter;
|
|
4893
5366
|
files.set(name, fileEntry);
|
|
5367
|
+
zipWriter.lastFileEntry = fileEntry;
|
|
4894
5368
|
try {
|
|
4895
5369
|
let lockPreviousFileEntry;
|
|
4896
5370
|
if (keepOrder) {
|
|
4897
5371
|
lockPreviousFileEntry = previousFileEntry && previousFileEntry.lock;
|
|
4898
5372
|
requestLockCurrentFileEntry();
|
|
4899
5373
|
}
|
|
4900
|
-
if (
|
|
5374
|
+
if (options.bufferedWrite || !keepOrder || zipWriter.writerLocked || zipWriter.bufferedWrites || !dataDescriptor) {
|
|
5375
|
+
bufferedWrite = true;
|
|
5376
|
+
zipWriter.bufferedWrites++;
|
|
4901
5377
|
if (options.createTempStream) {
|
|
4902
5378
|
fileWriter = await options.createTempStream();
|
|
4903
5379
|
} else {
|
|
4904
5380
|
fileWriter = new TransformStream(UNDEFINED_VALUE, UNDEFINED_VALUE, { highWaterMark: INFINITY_VALUE });
|
|
4905
5381
|
}
|
|
4906
5382
|
fileWriter.size = 0;
|
|
4907
|
-
bufferedWrite = true;
|
|
4908
|
-
zipWriter.bufferedWrites++;
|
|
4909
5383
|
await initStream(writer);
|
|
4910
5384
|
} else {
|
|
4911
5385
|
fileWriter = writer;
|
|
4912
5386
|
await requestLockWriter();
|
|
4913
5387
|
}
|
|
4914
5388
|
await initStream(fileWriter);
|
|
4915
|
-
const {
|
|
5389
|
+
const { diskOffset } = writer;
|
|
4916
5390
|
if (zipWriter.addSplitZipSignature) {
|
|
4917
5391
|
delete zipWriter.addSplitZipSignature;
|
|
4918
5392
|
const signatureArray = new Uint8Array(4);
|
|
@@ -4921,21 +5395,20 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
|
4921
5395
|
await writeData(writer, signatureArray);
|
|
4922
5396
|
zipWriter.offset += 4;
|
|
4923
5397
|
}
|
|
4924
|
-
if (usdz) {
|
|
5398
|
+
if (usdz && !bufferedWrite) {
|
|
4925
5399
|
appendExtraFieldUSDZ(entryInfo, zipWriter.offset - diskOffset);
|
|
4926
5400
|
}
|
|
4927
|
-
const {
|
|
4928
|
-
localHeaderView,
|
|
4929
|
-
localHeaderArray
|
|
4930
|
-
} = headerInfo;
|
|
5401
|
+
const { localHeaderArray } = headerInfo;
|
|
4931
5402
|
if (!bufferedWrite) {
|
|
4932
5403
|
await lockPreviousFileEntry;
|
|
4933
|
-
await skipDiskIfNeeded(
|
|
5404
|
+
await skipDiskIfNeeded();
|
|
4934
5405
|
}
|
|
4935
|
-
const
|
|
4936
|
-
|
|
5406
|
+
const diskNumberStart = writer.diskNumber;
|
|
5407
|
+
const entryOffset = getSegmentOffset(zipWriter, writer);
|
|
5408
|
+
fileEntry.diskNumberStart = diskNumberStart;
|
|
4937
5409
|
if (!bufferedWrite) {
|
|
4938
5410
|
writingEntryData = true;
|
|
5411
|
+
writerSizeBeforeEntry = writer.size;
|
|
4939
5412
|
await writeData(fileWriter, localHeaderArray);
|
|
4940
5413
|
}
|
|
4941
5414
|
fileEntry = await createFileEntry(reader, fileWriter, fileEntry, entryInfo, zipWriter.config, options);
|
|
@@ -4948,16 +5421,24 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
|
4948
5421
|
await Promise.all([fileWriter.writable.getWriter().close(), lockPreviousFileEntry]);
|
|
4949
5422
|
await requestLockWriter();
|
|
4950
5423
|
writingBufferedEntryData = true;
|
|
5424
|
+
writerSizeBeforeEntry = writer.size;
|
|
5425
|
+
await skipDiskIfNeeded();
|
|
4951
5426
|
fileEntry.diskNumberStart = writer.diskNumber;
|
|
4952
|
-
fileEntry.offset = zipWriter
|
|
4953
|
-
|
|
4954
|
-
|
|
4955
|
-
|
|
4956
|
-
|
|
5427
|
+
fileEntry.offset = getSegmentOffset(zipWriter, writer);
|
|
5428
|
+
if (usdz) {
|
|
5429
|
+
// the padding depends on the entry offset, only known now that the writer is locked
|
|
5430
|
+
const previousMetadataSize = entryInfo.metadataSize;
|
|
5431
|
+
appendExtraFieldUSDZ(entryInfo, zipWriter.offset - writer.diskOffset);
|
|
5432
|
+
fileEntry.size += entryInfo.metadataSize - previousMetadataSize;
|
|
5433
|
+
}
|
|
5434
|
+
updateLocalHeader(fileEntry, headerInfo.localHeaderView, options);
|
|
5435
|
+
await writeData(writer, headerInfo.localHeaderArray);
|
|
5436
|
+
await flushBufferedData(fileWriter.readable, writer, signal, chunkLength => flushedBufferedSize += chunkLength);
|
|
4957
5437
|
writer.size += fileWriter.size;
|
|
4958
5438
|
writingBufferedEntryData = false;
|
|
4959
5439
|
} else {
|
|
4960
|
-
fileEntry.
|
|
5440
|
+
fileEntry.diskNumberStart = diskNumberStart;
|
|
5441
|
+
fileEntry.offset = entryOffset;
|
|
4961
5442
|
}
|
|
4962
5443
|
zipWriter.offset += fileEntry.size;
|
|
4963
5444
|
return fileEntry;
|
|
@@ -4971,10 +5452,9 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
|
4971
5452
|
// ignored
|
|
4972
5453
|
}
|
|
4973
5454
|
}
|
|
5455
|
+
zipWriter.offset += writer.size - writerSizeBeforeEntry;
|
|
4974
5456
|
if (bufferedWrite) {
|
|
4975
|
-
zipWriter.offset +=
|
|
4976
|
-
} else {
|
|
4977
|
-
zipWriter.offset = fileWriter.size;
|
|
5457
|
+
zipWriter.offset += flushedBufferedSize;
|
|
4978
5458
|
}
|
|
4979
5459
|
}
|
|
4980
5460
|
files.delete(name);
|
|
@@ -5005,10 +5485,10 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
|
5005
5485
|
await lockWriter;
|
|
5006
5486
|
}
|
|
5007
5487
|
|
|
5008
|
-
async function skipDiskIfNeeded(
|
|
5488
|
+
async function skipDiskIfNeeded() {
|
|
5009
5489
|
if (getLength(headerInfo.localHeaderArray) > writer.availableSize) {
|
|
5010
5490
|
writer.availableSize = 0;
|
|
5011
|
-
await writeData(
|
|
5491
|
+
await writeData(writer, new Uint8Array());
|
|
5012
5492
|
}
|
|
5013
5493
|
}
|
|
5014
5494
|
}
|
|
@@ -5149,6 +5629,10 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
|
|
|
5149
5629
|
uncompressedSize = result.inputSize;
|
|
5150
5630
|
signature = result.signature;
|
|
5151
5631
|
}
|
|
5632
|
+
if ((!zip64CompressedSize && compressedSize >= MAX_32_BITS) ||
|
|
5633
|
+
(!zip64UncompressedSize && uncompressedSize >= MAX_32_BITS)) {
|
|
5634
|
+
throw new Error(ERR_UNSUPPORTED_FORMAT);
|
|
5635
|
+
}
|
|
5152
5636
|
} catch (error) {
|
|
5153
5637
|
if (error.outputSize !== UNDEFINED_VALUE) {
|
|
5154
5638
|
writer.size += error.outputSize;
|
|
@@ -5211,35 +5695,28 @@ function getHeaderInfo(options) {
|
|
|
5211
5695
|
uncompressedSize
|
|
5212
5696
|
} = options;
|
|
5213
5697
|
let { version, compressionMethod } = options;
|
|
5214
|
-
const compressed = !directory && (
|
|
5698
|
+
const compressed = !directory && (compressionMethod === UNDEFINED_VALUE
|
|
5699
|
+
? (level === UNDEFINED_VALUE || level > 0)
|
|
5700
|
+
: compressionMethod !== COMPRESSION_METHOD_STORE);
|
|
5215
5701
|
let rawLocalExtraFieldZip64;
|
|
5216
5702
|
const uncompressedFile = passThrough || !compressed;
|
|
5217
|
-
|
|
5218
|
-
|
|
5219
|
-
|
|
5220
|
-
|
|
5221
|
-
|
|
5222
|
-
|
|
5223
|
-
|
|
5224
|
-
|
|
5225
|
-
|
|
5226
|
-
|
|
5227
|
-
|
|
5228
|
-
|
|
5229
|
-
setUint16(rawLocalExtraFieldZip64View, 2, getLength(rawLocalExtraFieldZip64) - 4);
|
|
5703
|
+
// entries without a data descriptor are always buffered (cf. getFileEntry), so the
|
|
5704
|
+
// zip64 extra field values can be patched into the local header before flushing it
|
|
5705
|
+
const zip64ExtraFieldComplete = zip64 && (options.bufferedWrite || !dataDescriptor || ((!zip64UncompressedSize && !zip64CompressedSize) || uncompressedFile));
|
|
5706
|
+
const writeLocalExtraFieldZip64 = zip64ExtraFieldComplete || (zip64 && dataDescriptor && (zip64UncompressedSize || zip64CompressedSize));
|
|
5707
|
+
if (zip64 && (zip64UncompressedSize || zip64CompressedSize)) {
|
|
5708
|
+
// APPNOTE 4.5.3: the zip64 extra field of a local header must include both the
|
|
5709
|
+
// uncompressed and compressed size fields
|
|
5710
|
+
const length = 4 + 16;
|
|
5711
|
+
const extraFieldZip64 = createRecordWriter(length);
|
|
5712
|
+
extraFieldZip64.uint16(EXTRAFIELD_TYPE_ZIP64);
|
|
5713
|
+
extraFieldZip64.uint16(length - 4);
|
|
5714
|
+
rawLocalExtraFieldZip64 = extraFieldZip64.array;
|
|
5230
5715
|
if (zip64ExtraFieldComplete) {
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
rawLocalExtraFieldZip64Offset += 8;
|
|
5236
|
-
}
|
|
5237
|
-
if (zip64CompressedSize && uncompressedFile) {
|
|
5238
|
-
setBigUint64(rawLocalExtraFieldZip64View, rawLocalExtraFieldZip64Offset, BigInt(uncompressedSize));
|
|
5239
|
-
rawLocalExtraFieldZip64Offset += 8;
|
|
5240
|
-
}
|
|
5241
|
-
if (rawLocalExtraFieldZip64Offset == 4) {
|
|
5242
|
-
rawLocalExtraFieldZip64 = new Uint8Array();
|
|
5716
|
+
extraFieldZip64.uint64(uncompressedSize);
|
|
5717
|
+
if (uncompressedFile) {
|
|
5718
|
+
const encryptionOverhead = encrypted ? (zipCrypto ? 12 : 16 + encryptionStrength * 4) : 0;
|
|
5719
|
+
extraFieldZip64.uint64(passThrough ? 0 : uncompressedSize + encryptionOverhead);
|
|
5243
5720
|
}
|
|
5244
5721
|
}
|
|
5245
5722
|
} else {
|
|
@@ -5247,11 +5724,11 @@ function getHeaderInfo(options) {
|
|
|
5247
5724
|
}
|
|
5248
5725
|
let rawExtraFieldAES;
|
|
5249
5726
|
if (encrypted && !zipCrypto) {
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
|
|
5727
|
+
const extraFieldAES = createRecordWriter(getLength(EXTRAFIELD_DATA_AES) + 2);
|
|
5728
|
+
extraFieldAES.uint16(EXTRAFIELD_TYPE_AES);
|
|
5729
|
+
extraFieldAES.bytes(EXTRAFIELD_DATA_AES);
|
|
5730
|
+
rawExtraFieldAES = extraFieldAES.array;
|
|
5731
|
+
rawExtraFieldAES[8] = encryptionStrength;
|
|
5255
5732
|
} else {
|
|
5256
5733
|
rawExtraFieldAES = new Uint8Array();
|
|
5257
5734
|
}
|
|
@@ -5259,33 +5736,38 @@ function getHeaderInfo(options) {
|
|
|
5259
5736
|
let rawExtraFieldExtendedTimestamp;
|
|
5260
5737
|
let extraFieldExtendedTimestampFlag;
|
|
5261
5738
|
if (extendedTimestamp) {
|
|
5262
|
-
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
|
|
5267
|
-
|
|
5268
|
-
|
|
5269
|
-
|
|
5270
|
-
|
|
5271
|
-
|
|
5272
|
-
|
|
5273
|
-
|
|
5274
|
-
|
|
5275
|
-
|
|
5276
|
-
|
|
5739
|
+
const lastModTimeUnix = getTimeUnix(lastModDate);
|
|
5740
|
+
if (inUnixTimeRange(lastModTimeUnix)) {
|
|
5741
|
+
const extraFieldTimestampLength = 9 + (lastAccessDate ? 4 : 0) + (creationDate ? 4 : 0);
|
|
5742
|
+
const extraFieldTimestamp = createRecordWriter(extraFieldTimestampLength);
|
|
5743
|
+
extraFieldExtendedTimestampFlag = 0x1 + (lastAccessDate ? 0x2 : 0) + (creationDate ? 0x4 : 0);
|
|
5744
|
+
extraFieldTimestamp.uint16(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
|
|
5745
|
+
extraFieldTimestamp.uint16(extraFieldTimestampLength - 4);
|
|
5746
|
+
extraFieldTimestamp.uint8(extraFieldExtendedTimestampFlag);
|
|
5747
|
+
extraFieldTimestamp.uint32(lastModTimeUnix);
|
|
5748
|
+
if (lastAccessDate) {
|
|
5749
|
+
extraFieldTimestamp.uint32(clampUnixTime(getTimeUnix(lastAccessDate)));
|
|
5750
|
+
}
|
|
5751
|
+
if (creationDate) {
|
|
5752
|
+
extraFieldTimestamp.uint32(clampUnixTime(getTimeUnix(creationDate)));
|
|
5753
|
+
}
|
|
5754
|
+
rawExtraFieldExtendedTimestamp = extraFieldTimestamp.array;
|
|
5755
|
+
} else {
|
|
5756
|
+
// the date cannot be stored as a 32-bit time_t; the NTFS field replaces it
|
|
5757
|
+
rawExtraFieldExtendedTimestamp = new Uint8Array();
|
|
5277
5758
|
}
|
|
5278
5759
|
try {
|
|
5279
|
-
rawExtraFieldNTFS = new Uint8Array(36);
|
|
5280
|
-
const extraFieldNTFSView = getDataView(rawExtraFieldNTFS);
|
|
5281
5760
|
const lastModTimeNTFS = getTimeNTFS(lastModDate);
|
|
5282
|
-
|
|
5283
|
-
|
|
5284
|
-
|
|
5285
|
-
|
|
5286
|
-
|
|
5287
|
-
|
|
5288
|
-
|
|
5761
|
+
const extraFieldNTFS = createRecordWriter(36);
|
|
5762
|
+
extraFieldNTFS.uint16(EXTRAFIELD_TYPE_NTFS);
|
|
5763
|
+
extraFieldNTFS.uint16(32);
|
|
5764
|
+
extraFieldNTFS.skip(4);
|
|
5765
|
+
extraFieldNTFS.uint16(EXTRAFIELD_TYPE_NTFS_TAG1);
|
|
5766
|
+
extraFieldNTFS.uint16(24);
|
|
5767
|
+
extraFieldNTFS.uint64(lastModTimeNTFS);
|
|
5768
|
+
extraFieldNTFS.uint64(getTimeNTFS(lastAccessDate) || lastModTimeNTFS);
|
|
5769
|
+
extraFieldNTFS.uint64(getTimeNTFS(creationDate) || lastModTimeNTFS);
|
|
5770
|
+
rawExtraFieldNTFS = extraFieldNTFS.array;
|
|
5289
5771
|
} catch {
|
|
5290
5772
|
rawExtraFieldNTFS = new Uint8Array();
|
|
5291
5773
|
}
|
|
@@ -5294,41 +5776,27 @@ function getHeaderInfo(options) {
|
|
|
5294
5776
|
}
|
|
5295
5777
|
let rawExtraFieldUnix;
|
|
5296
5778
|
try {
|
|
5297
|
-
const { uid, gid,
|
|
5298
|
-
if (unixExtraFieldType && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE
|
|
5779
|
+
const { uid, gid, unixExtraFieldType } = options;
|
|
5780
|
+
if (unixExtraFieldType == INFOZIP_EXTRA_FIELD_TYPE && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
|
|
5299
5781
|
const uidBytes = packUnixId(uid);
|
|
5300
5782
|
const gidBytes = packUnixId(gid);
|
|
5301
|
-
|
|
5302
|
-
|
|
5303
|
-
|
|
5304
|
-
|
|
5305
|
-
|
|
5306
|
-
|
|
5307
|
-
|
|
5308
|
-
|
|
5309
|
-
|
|
5310
|
-
|
|
5311
|
-
|
|
5312
|
-
|
|
5313
|
-
|
|
5314
|
-
|
|
5315
|
-
|
|
5316
|
-
|
|
5317
|
-
|
|
5318
|
-
rawExtraFieldUnix = new Uint8Array(4 + payloadLength);
|
|
5319
|
-
const rawExtraFieldUnixView = getDataView(rawExtraFieldUnix);
|
|
5320
|
-
setUint16(rawExtraFieldUnixView, 0, unixExtraFieldType == INFOZIP_EXTRA_FIELD_TYPE ? EXTRAFIELD_TYPE_INFOZIP : EXTRAFIELD_TYPE_UNIX);
|
|
5321
|
-
setUint16(rawExtraFieldUnixView, 2, payloadLength);
|
|
5322
|
-
setUint8(rawExtraFieldUnixView, 4, 1);
|
|
5323
|
-
setUint8(rawExtraFieldUnixView, 5, uidBytes.length);
|
|
5324
|
-
let offset = 6;
|
|
5325
|
-
arraySet(rawExtraFieldUnix, uidBytes, offset);
|
|
5326
|
-
offset += uidBytes.length;
|
|
5327
|
-
setUint8(rawExtraFieldUnixView, offset, gidBytes.length);
|
|
5328
|
-
offset++;
|
|
5329
|
-
arraySet(rawExtraFieldUnix, gidBytes, offset);
|
|
5330
|
-
offset += gidBytes.length;
|
|
5331
|
-
arraySet(rawExtraFieldUnix, modeArray, offset);
|
|
5783
|
+
const payloadLength = 3 + uidBytes.length + gidBytes.length;
|
|
5784
|
+
const extraFieldUnix = createRecordWriter(4 + payloadLength);
|
|
5785
|
+
extraFieldUnix.uint16(EXTRAFIELD_TYPE_INFOZIP);
|
|
5786
|
+
extraFieldUnix.uint16(payloadLength);
|
|
5787
|
+
extraFieldUnix.uint8(1);
|
|
5788
|
+
extraFieldUnix.uint8(uidBytes.length);
|
|
5789
|
+
extraFieldUnix.bytes(uidBytes);
|
|
5790
|
+
extraFieldUnix.uint8(gidBytes.length);
|
|
5791
|
+
extraFieldUnix.bytes(gidBytes);
|
|
5792
|
+
rawExtraFieldUnix = extraFieldUnix.array;
|
|
5793
|
+
} else if (unixExtraFieldType == UNIX_EXTRA_FIELD_TYPE && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
|
|
5794
|
+
const extraFieldUnix = createRecordWriter(8);
|
|
5795
|
+
extraFieldUnix.uint16(EXTRAFIELD_TYPE_UNIX);
|
|
5796
|
+
extraFieldUnix.uint16(4);
|
|
5797
|
+
extraFieldUnix.uint16((uid === UNDEFINED_VALUE ? 0 : uid) & MAX_16_BITS);
|
|
5798
|
+
extraFieldUnix.uint16((gid === UNDEFINED_VALUE ? 0 : gid) & MAX_16_BITS);
|
|
5799
|
+
rawExtraFieldUnix = extraFieldUnix.array;
|
|
5332
5800
|
} else {
|
|
5333
5801
|
rawExtraFieldUnix = new Uint8Array();
|
|
5334
5802
|
}
|
|
@@ -5346,8 +5814,11 @@ function getHeaderInfo(options) {
|
|
|
5346
5814
|
rawExtraFieldAES[9] = compressionMethod;
|
|
5347
5815
|
compressionMethod = COMPRESSION_METHOD_AES;
|
|
5348
5816
|
}
|
|
5349
|
-
const localExtraFieldZip64Length =
|
|
5817
|
+
const localExtraFieldZip64Length = writeLocalExtraFieldZip64 ? getLength(rawLocalExtraFieldZip64) : 0;
|
|
5350
5818
|
const extraFieldLength = localExtraFieldZip64Length + getLength(rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField);
|
|
5819
|
+
if (extraFieldLength > MAX_16_BITS) {
|
|
5820
|
+
throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
|
|
5821
|
+
}
|
|
5351
5822
|
const {
|
|
5352
5823
|
headerArray,
|
|
5353
5824
|
headerView,
|
|
@@ -5363,29 +5834,27 @@ function getHeaderInfo(options) {
|
|
|
5363
5834
|
zip64UncompressedSize,
|
|
5364
5835
|
extraFieldLength
|
|
5365
5836
|
});
|
|
5366
|
-
|
|
5367
|
-
const localHeaderArray =
|
|
5837
|
+
const localHeader = createRecordWriter(HEADER_SIZE + getLength(rawFilename) + extraFieldLength);
|
|
5838
|
+
const localHeaderArray = localHeader.array;
|
|
5368
5839
|
const localHeaderView = getDataView(localHeaderArray);
|
|
5369
|
-
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
|
-
|
|
5373
|
-
|
|
5374
|
-
|
|
5375
|
-
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
|
|
5380
|
-
localHeaderOffset += getLength(rawExtraFieldExtendedTimestamp);
|
|
5381
|
-
arraySet(localHeaderArray, rawExtraFieldNTFS, localHeaderOffset);
|
|
5382
|
-
localHeaderOffset += getLength(rawExtraFieldNTFS);
|
|
5383
|
-
arraySet(localHeaderArray, rawExtraFieldUnix, localHeaderOffset);
|
|
5384
|
-
localHeaderOffset += getLength(rawExtraFieldUnix);
|
|
5385
|
-
arraySet(localHeaderArray, rawExtraField, localHeaderOffset);
|
|
5840
|
+
localHeader.uint32(LOCAL_FILE_HEADER_SIGNATURE);
|
|
5841
|
+
localHeader.bytes(headerArray);
|
|
5842
|
+
localHeader.bytes(rawFilename);
|
|
5843
|
+
if (writeLocalExtraFieldZip64) {
|
|
5844
|
+
localHeader.bytes(rawLocalExtraFieldZip64);
|
|
5845
|
+
}
|
|
5846
|
+
localHeader.bytes(rawExtraFieldAES);
|
|
5847
|
+
localHeader.bytes(rawExtraFieldExtendedTimestamp);
|
|
5848
|
+
localHeader.bytes(rawExtraFieldNTFS);
|
|
5849
|
+
localHeader.bytes(rawExtraFieldUnix);
|
|
5850
|
+
localHeader.bytes(rawExtraField);
|
|
5386
5851
|
if (dataDescriptor) {
|
|
5387
|
-
|
|
5388
|
-
|
|
5852
|
+
if (!zip64CompressedSize) {
|
|
5853
|
+
setUint32(localHeaderView, HEADER_OFFSET_COMPRESSED_SIZE + LOCAL_HEADER_COMMON_OFFSET, 0);
|
|
5854
|
+
}
|
|
5855
|
+
if (!zip64UncompressedSize) {
|
|
5856
|
+
setUint32(localHeaderView, HEADER_OFFSET_UNCOMPRESSED_SIZE + LOCAL_HEADER_COMMON_OFFSET, 0);
|
|
5857
|
+
}
|
|
5389
5858
|
}
|
|
5390
5859
|
return {
|
|
5391
5860
|
localHeaderArray,
|
|
@@ -5412,7 +5881,7 @@ function getHeaderInfo(options) {
|
|
|
5412
5881
|
function appendExtraFieldUSDZ(entryInfo, zipWriterOffset) {
|
|
5413
5882
|
const { headerInfo } = entryInfo;
|
|
5414
5883
|
let { localHeaderArray, extraFieldLength } = headerInfo;
|
|
5415
|
-
let localHeaderArrayView
|
|
5884
|
+
let localHeaderArrayView;
|
|
5416
5885
|
let extraBytesLength = 64 - ((zipWriterOffset + getLength(localHeaderArray)) % 64);
|
|
5417
5886
|
if (extraBytesLength < 4) {
|
|
5418
5887
|
extraBytesLength += 64;
|
|
@@ -5420,13 +5889,14 @@ function appendExtraFieldUSDZ(entryInfo, zipWriterOffset) {
|
|
|
5420
5889
|
const rawExtraFieldUSDZ = new Uint8Array(extraBytesLength);
|
|
5421
5890
|
const extraFieldUSDZView = getDataView(rawExtraFieldUSDZ);
|
|
5422
5891
|
setUint16(extraFieldUSDZView, 0, EXTRAFIELD_TYPE_USDZ);
|
|
5423
|
-
setUint16(extraFieldUSDZView, 2, extraBytesLength -
|
|
5892
|
+
setUint16(extraFieldUSDZView, 2, extraBytesLength - 4);
|
|
5424
5893
|
const previousLocalHeaderArray = localHeaderArray;
|
|
5425
5894
|
headerInfo.localHeaderArray = localHeaderArray = new Uint8Array(getLength(previousLocalHeaderArray) + extraBytesLength);
|
|
5426
5895
|
arraySet(localHeaderArray, previousLocalHeaderArray);
|
|
5427
5896
|
arraySet(localHeaderArray, rawExtraFieldUSDZ, getLength(previousLocalHeaderArray));
|
|
5428
5897
|
localHeaderArrayView = getDataView(localHeaderArray);
|
|
5429
5898
|
setUint16(localHeaderArrayView, 28, extraFieldLength + extraBytesLength);
|
|
5899
|
+
headerInfo.localHeaderView = localHeaderArrayView;
|
|
5430
5900
|
entryInfo.metadataSize += extraBytesLength;
|
|
5431
5901
|
}
|
|
5432
5902
|
|
|
@@ -5549,37 +6019,32 @@ function updateLocalHeader({
|
|
|
5549
6019
|
}, localHeaderView, { dataDescriptor }) {
|
|
5550
6020
|
if (!dataDescriptor) {
|
|
5551
6021
|
if (!encrypted) {
|
|
5552
|
-
setUint32(localHeaderView, HEADER_OFFSET_SIGNATURE +
|
|
6022
|
+
setUint32(localHeaderView, HEADER_OFFSET_SIGNATURE + LOCAL_HEADER_COMMON_OFFSET, signature);
|
|
5553
6023
|
}
|
|
5554
6024
|
if (!zip64CompressedSize) {
|
|
5555
|
-
setUint32(localHeaderView, HEADER_OFFSET_COMPRESSED_SIZE +
|
|
6025
|
+
setUint32(localHeaderView, HEADER_OFFSET_COMPRESSED_SIZE + LOCAL_HEADER_COMMON_OFFSET, compressedSize);
|
|
5556
6026
|
}
|
|
5557
6027
|
if (!zip64UncompressedSize) {
|
|
5558
|
-
setUint32(localHeaderView, HEADER_OFFSET_UNCOMPRESSED_SIZE +
|
|
6028
|
+
setUint32(localHeaderView, HEADER_OFFSET_UNCOMPRESSED_SIZE + LOCAL_HEADER_COMMON_OFFSET, uncompressedSize);
|
|
5559
6029
|
}
|
|
5560
6030
|
}
|
|
5561
6031
|
if (zip64 && localExtraFieldZip64Length) {
|
|
5562
|
-
|
|
5563
|
-
|
|
5564
|
-
|
|
5565
|
-
|
|
5566
|
-
}
|
|
5567
|
-
if (zip64CompressedSize) {
|
|
5568
|
-
setBigUint64(localHeaderView, localHeaderOffset, BigInt(compressedSize));
|
|
5569
|
-
localHeaderOffset += 8;
|
|
5570
|
-
}
|
|
6032
|
+
// the local zip64 extra field always contains both size slots
|
|
6033
|
+
const localHeaderOffset = HEADER_SIZE + getLength(rawFilename) + 4;
|
|
6034
|
+
setBigUint64(localHeaderView, localHeaderOffset, BigInt(uncompressedSize));
|
|
6035
|
+
setBigUint64(localHeaderView, localHeaderOffset + 8, BigInt(compressedSize));
|
|
5571
6036
|
}
|
|
5572
6037
|
}
|
|
5573
6038
|
|
|
5574
6039
|
|
|
5575
6040
|
async function closeFile(zipWriter, comment, options) {
|
|
5576
|
-
const
|
|
5577
|
-
const {
|
|
5578
|
-
|
|
5579
|
-
|
|
6041
|
+
const directoryDataLength = createDirectoryRecords(zipWriter.files);
|
|
6042
|
+
const { cdStartDiskNumber, cdStartDiskOffset } = await writeDirectoryRecords(zipWriter, directoryDataLength, options);
|
|
6043
|
+
await writeEndOfDirectoryRecord(zipWriter, comment, options, { cdStartDiskNumber, cdStartDiskOffset, directoryDataLength });
|
|
6044
|
+
}
|
|
6045
|
+
|
|
6046
|
+
function createDirectoryRecords(files) {
|
|
5580
6047
|
let directoryDataLength = 0;
|
|
5581
|
-
let directoryOffset = zipWriter.offset - diskOffset;
|
|
5582
|
-
let filesLength = files.size;
|
|
5583
6048
|
for (const [, fileEntry] of files) {
|
|
5584
6049
|
const {
|
|
5585
6050
|
rawFilename,
|
|
@@ -5596,24 +6061,27 @@ async function closeFile(zipWriter, comment, options) {
|
|
|
5596
6061
|
uncompressedSize,
|
|
5597
6062
|
compressedSize
|
|
5598
6063
|
} = fileEntry;
|
|
5599
|
-
const zip64Offset = fileEntry.offset
|
|
5600
|
-
const zip64DiskNumberStart = fileEntry.diskNumberStart
|
|
6064
|
+
const zip64Offset = fileEntry.offset >= MAX_32_BITS;
|
|
6065
|
+
const zip64DiskNumberStart = fileEntry.diskNumberStart >= MAX_16_BITS;
|
|
5601
6066
|
let rawExtraFieldZip64;
|
|
5602
6067
|
if (zip64Offset || zip64DiskNumberStart || zip64UncompressedSize || zip64CompressedSize) {
|
|
5603
|
-
|
|
5604
|
-
|
|
5605
|
-
|
|
5606
|
-
|
|
5607
|
-
if (
|
|
5608
|
-
|
|
5609
|
-
|
|
5610
|
-
|
|
5611
|
-
|
|
5612
|
-
|
|
5613
|
-
if (
|
|
5614
|
-
|
|
5615
|
-
|
|
5616
|
-
if (zip64DiskNumberStart) {
|
|
6068
|
+
const length = 4 + (zip64UncompressedSize ? 8 : 0) + (zip64CompressedSize ? 8 : 0) + (zip64Offset ? 8 : 0) + (zip64DiskNumberStart ? 4 : 0);
|
|
6069
|
+
const extraFieldZip64 = createRecordWriter(length);
|
|
6070
|
+
extraFieldZip64.uint16(EXTRAFIELD_TYPE_ZIP64);
|
|
6071
|
+
extraFieldZip64.uint16(length - 4);
|
|
6072
|
+
if (zip64UncompressedSize) {
|
|
6073
|
+
extraFieldZip64.uint64(uncompressedSize);
|
|
6074
|
+
}
|
|
6075
|
+
if (zip64CompressedSize) {
|
|
6076
|
+
extraFieldZip64.uint64(compressedSize);
|
|
6077
|
+
}
|
|
6078
|
+
if (zip64Offset) {
|
|
6079
|
+
extraFieldZip64.uint64(fileEntry.offset);
|
|
6080
|
+
}
|
|
6081
|
+
if (zip64DiskNumberStart) {
|
|
6082
|
+
extraFieldZip64.uint32(fileEntry.diskNumberStart);
|
|
6083
|
+
}
|
|
6084
|
+
rawExtraFieldZip64 = extraFieldZip64.array;
|
|
5617
6085
|
} else {
|
|
5618
6086
|
rawExtraFieldZip64 = new Uint8Array();
|
|
5619
6087
|
}
|
|
@@ -5621,32 +6089,41 @@ async function closeFile(zipWriter, comment, options) {
|
|
|
5621
6089
|
fileEntry.zip64Offset = zip64Offset;
|
|
5622
6090
|
fileEntry.zip64DiskNumberStart = zip64DiskNumberStart;
|
|
5623
6091
|
let rawExtraFieldTimestamp;
|
|
5624
|
-
|
|
5625
|
-
|
|
5626
|
-
const
|
|
5627
|
-
|
|
5628
|
-
|
|
5629
|
-
|
|
5630
|
-
|
|
6092
|
+
const lastModTimeUnix = getTimeUnix(lastModDate);
|
|
6093
|
+
if (extendedTimestamp && inUnixTimeRange(lastModTimeUnix)) {
|
|
6094
|
+
const extraFieldTimestamp = createRecordWriter(9);
|
|
6095
|
+
extraFieldTimestamp.uint16(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
|
|
6096
|
+
extraFieldTimestamp.uint16(5);
|
|
6097
|
+
extraFieldTimestamp.uint8(extraFieldExtendedTimestampFlag);
|
|
6098
|
+
extraFieldTimestamp.uint32(lastModTimeUnix);
|
|
6099
|
+
rawExtraFieldTimestamp = extraFieldTimestamp.array;
|
|
5631
6100
|
} else {
|
|
5632
6101
|
rawExtraFieldTimestamp = new Uint8Array();
|
|
5633
6102
|
}
|
|
5634
6103
|
fileEntry.rawExtraFieldExtendedTimestamp = rawExtraFieldTimestamp;
|
|
5635
|
-
|
|
5636
|
-
|
|
5637
|
-
|
|
5638
|
-
|
|
5639
|
-
|
|
5640
|
-
|
|
5641
|
-
|
|
5642
|
-
|
|
5643
|
-
|
|
5644
|
-
|
|
6104
|
+
const extraFieldLength = getLength(
|
|
6105
|
+
rawExtraFieldZip64,
|
|
6106
|
+
rawExtraFieldAES,
|
|
6107
|
+
rawExtraFieldNTFS,
|
|
6108
|
+
rawExtraFieldUnix,
|
|
6109
|
+
rawExtraFieldTimestamp,
|
|
6110
|
+
rawExtraField);
|
|
6111
|
+
if (extraFieldLength > MAX_16_BITS) {
|
|
6112
|
+
throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
|
|
6113
|
+
}
|
|
6114
|
+
directoryDataLength += CENTRAL_FILE_HEADER_LENGTH + getLength(rawFilename, rawComment) + extraFieldLength;
|
|
5645
6115
|
}
|
|
6116
|
+
return directoryDataLength;
|
|
6117
|
+
}
|
|
6118
|
+
|
|
6119
|
+
async function writeDirectoryRecords(zipWriter, directoryDataLength, options) {
|
|
6120
|
+
const { files, writer } = zipWriter;
|
|
5646
6121
|
const directoryArray = new Uint8Array(directoryDataLength);
|
|
5647
|
-
const directoryView = getDataView(directoryArray);
|
|
5648
6122
|
await initStream(writer);
|
|
6123
|
+
let offset = 0;
|
|
5649
6124
|
let directoryDiskOffset = 0;
|
|
6125
|
+
let cdStartDiskNumber = writer.diskNumber;
|
|
6126
|
+
let cdStartDiskOffset = writer.diskOffset;
|
|
5650
6127
|
for (const [indexFileEntry, fileEntry] of Array.from(files.values()).entries()) {
|
|
5651
6128
|
const {
|
|
5652
6129
|
offset: fileEntryOffset,
|
|
@@ -5672,52 +6149,46 @@ async function closeFile(zipWriter, comment, options) {
|
|
|
5672
6149
|
compressedSize
|
|
5673
6150
|
} = fileEntry;
|
|
5674
6151
|
const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField);
|
|
5675
|
-
|
|
5676
|
-
|
|
6152
|
+
const directoryRecordLength = CENTRAL_FILE_HEADER_LENGTH + getLength(rawFilename, rawComment) + extraFieldLength;
|
|
6153
|
+
if (offset + directoryRecordLength - directoryDiskOffset > writer.availableSize) {
|
|
6154
|
+
await writeData(writer, directoryArray.slice(directoryDiskOffset, offset));
|
|
6155
|
+
directoryDiskOffset = offset;
|
|
6156
|
+
writer.availableSize = 0;
|
|
6157
|
+
await writeData(writer, new Uint8Array());
|
|
6158
|
+
}
|
|
6159
|
+
if (indexFileEntry == 0) {
|
|
6160
|
+
cdStartDiskNumber = writer.diskNumber;
|
|
6161
|
+
cdStartDiskOffset = writer.diskOffset;
|
|
6162
|
+
}
|
|
5677
6163
|
if (!zip64UncompressedSize) {
|
|
5678
6164
|
setUint32(headerView, HEADER_OFFSET_UNCOMPRESSED_SIZE, uncompressedSize);
|
|
5679
6165
|
}
|
|
5680
6166
|
if (!zip64CompressedSize) {
|
|
5681
6167
|
setUint32(headerView, HEADER_OFFSET_COMPRESSED_SIZE, compressedSize);
|
|
5682
6168
|
}
|
|
5683
|
-
|
|
5684
|
-
|
|
5685
|
-
|
|
5686
|
-
|
|
5687
|
-
|
|
5688
|
-
|
|
5689
|
-
|
|
5690
|
-
|
|
5691
|
-
|
|
5692
|
-
|
|
5693
|
-
|
|
5694
|
-
|
|
5695
|
-
|
|
5696
|
-
|
|
5697
|
-
|
|
5698
|
-
|
|
5699
|
-
|
|
5700
|
-
|
|
5701
|
-
|
|
5702
|
-
|
|
5703
|
-
|
|
5704
|
-
|
|
5705
|
-
|
|
5706
|
-
directoryOffset += getLength(rawExtraFieldExtendedTimestamp);
|
|
5707
|
-
arraySet(directoryArray, rawExtraFieldNTFS, directoryOffset);
|
|
5708
|
-
directoryOffset += getLength(rawExtraFieldNTFS);
|
|
5709
|
-
arraySet(directoryArray, rawExtraFieldUnix, directoryOffset);
|
|
5710
|
-
directoryOffset += getLength(rawExtraFieldUnix);
|
|
5711
|
-
arraySet(directoryArray, rawExtraField, directoryOffset);
|
|
5712
|
-
directoryOffset += getLength(rawExtraField);
|
|
5713
|
-
arraySet(directoryArray, rawComment, directoryOffset);
|
|
5714
|
-
directoryOffset += getLength(rawComment);
|
|
5715
|
-
if (offset - directoryDiskOffset > writer.availableSize) {
|
|
5716
|
-
writer.availableSize = 0;
|
|
5717
|
-
await writeData(writer, directoryArray.slice(directoryDiskOffset, offset));
|
|
5718
|
-
directoryDiskOffset = offset;
|
|
5719
|
-
}
|
|
5720
|
-
offset = directoryOffset;
|
|
6169
|
+
if ((zip64Offset || zip64DiskNumberStart) && fileEntry.version < VERSION_ZIP64) {
|
|
6170
|
+
setUint16(headerView, HEADER_OFFSET_VERSION, VERSION_ZIP64);
|
|
6171
|
+
}
|
|
6172
|
+
const directoryRecord = createRecordWriter(directoryRecordLength);
|
|
6173
|
+
directoryRecord.uint32(CENTRAL_FILE_HEADER_SIGNATURE);
|
|
6174
|
+
directoryRecord.uint16(versionMadeBy);
|
|
6175
|
+
directoryRecord.bytes(headerArray.subarray(0, HEADER_SIZE - 4 - 2));
|
|
6176
|
+
directoryRecord.uint16(extraFieldLength);
|
|
6177
|
+
directoryRecord.uint16(getLength(rawComment));
|
|
6178
|
+
directoryRecord.uint16(zip64DiskNumberStart ? MAX_16_BITS : diskNumberStart);
|
|
6179
|
+
directoryRecord.uint16(internalFileAttributes);
|
|
6180
|
+
directoryRecord.uint32(externalFileAttributes);
|
|
6181
|
+
directoryRecord.uint32(zip64Offset ? MAX_32_BITS : fileEntryOffset);
|
|
6182
|
+
directoryRecord.bytes(rawFilename);
|
|
6183
|
+
directoryRecord.bytes(rawExtraFieldZip64);
|
|
6184
|
+
directoryRecord.bytes(rawExtraFieldAES);
|
|
6185
|
+
directoryRecord.bytes(rawExtraFieldExtendedTimestamp);
|
|
6186
|
+
directoryRecord.bytes(rawExtraFieldNTFS);
|
|
6187
|
+
directoryRecord.bytes(rawExtraFieldUnix);
|
|
6188
|
+
directoryRecord.bytes(rawExtraField);
|
|
6189
|
+
directoryRecord.bytes(rawComment);
|
|
6190
|
+
arraySet(directoryArray, directoryRecord.array, offset);
|
|
6191
|
+
offset += directoryRecordLength;
|
|
5721
6192
|
if (options.onprogress) {
|
|
5722
6193
|
try {
|
|
5723
6194
|
await options.onprogress(indexFileEntry + 1, files.size, new Entry(fileEntry));
|
|
@@ -5727,36 +6198,53 @@ async function closeFile(zipWriter, comment, options) {
|
|
|
5727
6198
|
}
|
|
5728
6199
|
}
|
|
5729
6200
|
await writeData(writer, directoryDiskOffset ? directoryArray.slice(directoryDiskOffset) : directoryArray);
|
|
6201
|
+
return { cdStartDiskNumber, cdStartDiskOffset };
|
|
6202
|
+
}
|
|
6203
|
+
|
|
6204
|
+
async function writeEndOfDirectoryRecord(zipWriter, comment, options, cdInfo) {
|
|
6205
|
+
const { writer } = zipWriter;
|
|
6206
|
+
const { cdStartDiskNumber, cdStartDiskOffset } = cdInfo;
|
|
6207
|
+
let { directoryDataLength } = cdInfo;
|
|
6208
|
+
let filesLength = zipWriter.files.size;
|
|
6209
|
+
let diskNumber = cdStartDiskNumber;
|
|
6210
|
+
let directoryOffset = zipWriter.offset - cdStartDiskOffset - (cdStartDiskNumber ? zipWriter.initialOffset : 0);
|
|
5730
6211
|
let lastDiskNumber = writer.diskNumber;
|
|
5731
|
-
|
|
5732
|
-
if (availableSize < END_OF_CENTRAL_DIR_LENGTH) {
|
|
6212
|
+
if (writer.availableSize < END_OF_CENTRAL_DIR_LENGTH) {
|
|
5733
6213
|
lastDiskNumber++;
|
|
5734
6214
|
}
|
|
5735
6215
|
let zip64 = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIP64);
|
|
5736
|
-
if (directoryOffset
|
|
6216
|
+
if (directoryOffset >= MAX_32_BITS || directoryDataLength >= MAX_32_BITS || filesLength >= MAX_16_BITS || lastDiskNumber >= MAX_16_BITS) {
|
|
5737
6217
|
if (zip64 === false) {
|
|
5738
6218
|
throw new Error(ERR_UNSUPPORTED_FORMAT);
|
|
5739
6219
|
} else {
|
|
5740
6220
|
zip64 = true;
|
|
5741
6221
|
}
|
|
5742
6222
|
}
|
|
5743
|
-
const
|
|
5744
|
-
|
|
5745
|
-
|
|
6223
|
+
const commentLength = getLength(comment);
|
|
6224
|
+
if (commentLength > MAX_16_BITS) {
|
|
6225
|
+
throw new Error(ERR_INVALID_COMMENT);
|
|
6226
|
+
}
|
|
6227
|
+
const endOfdirectoryRecord = createRecordWriter(zip64 ? ZIP64_END_OF_CENTRAL_DIR_TOTAL_LENGTH : END_OF_CENTRAL_DIR_LENGTH);
|
|
6228
|
+
if (getLength(endOfdirectoryRecord.array) + commentLength > writer.availableSize) {
|
|
6229
|
+
writer.availableSize = 0;
|
|
6230
|
+
await writeData(writer, new Uint8Array());
|
|
6231
|
+
}
|
|
6232
|
+
lastDiskNumber = writer.diskNumber;
|
|
5746
6233
|
if (zip64) {
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
|
|
5755
|
-
|
|
5756
|
-
|
|
5757
|
-
|
|
5758
|
-
|
|
5759
|
-
|
|
6234
|
+
endOfdirectoryRecord.uint32(ZIP64_END_OF_CENTRAL_DIR_SIGNATURE);
|
|
6235
|
+
endOfdirectoryRecord.uint64(44);
|
|
6236
|
+
endOfdirectoryRecord.uint16(45);
|
|
6237
|
+
endOfdirectoryRecord.uint16(45);
|
|
6238
|
+
endOfdirectoryRecord.uint32(lastDiskNumber);
|
|
6239
|
+
endOfdirectoryRecord.uint32(diskNumber);
|
|
6240
|
+
endOfdirectoryRecord.uint64(filesLength);
|
|
6241
|
+
endOfdirectoryRecord.uint64(filesLength);
|
|
6242
|
+
endOfdirectoryRecord.uint64(directoryDataLength);
|
|
6243
|
+
endOfdirectoryRecord.uint64(directoryOffset);
|
|
6244
|
+
endOfdirectoryRecord.uint32(ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIGNATURE);
|
|
6245
|
+
endOfdirectoryRecord.uint32(lastDiskNumber);
|
|
6246
|
+
endOfdirectoryRecord.uint64(BigInt(zipWriter.offset) + BigInt(directoryDataLength) - BigInt(writer.diskOffset) - BigInt(writer.diskNumber ? zipWriter.initialOffset : 0));
|
|
6247
|
+
endOfdirectoryRecord.uint32(lastDiskNumber + 1);
|
|
5760
6248
|
const supportZip64SplitFile = getOptionValue(zipWriter, options, OPTION_SUPPORT_ZIP64_SPLIT_FILE, true);
|
|
5761
6249
|
if (supportZip64SplitFile) {
|
|
5762
6250
|
lastDiskNumber = MAX_16_BITS;
|
|
@@ -5765,29 +6253,40 @@ async function closeFile(zipWriter, comment, options) {
|
|
|
5765
6253
|
filesLength = MAX_16_BITS;
|
|
5766
6254
|
directoryOffset = MAX_32_BITS;
|
|
5767
6255
|
directoryDataLength = MAX_32_BITS;
|
|
5768
|
-
offset += ZIP64_END_OF_CENTRAL_DIR_LENGTH + ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH;
|
|
5769
|
-
}
|
|
5770
|
-
setUint32(endOfdirectoryView, offset, END_OF_CENTRAL_DIR_SIGNATURE);
|
|
5771
|
-
setUint16(endOfdirectoryView, offset + 4, lastDiskNumber);
|
|
5772
|
-
setUint16(endOfdirectoryView, offset + 6, diskNumber);
|
|
5773
|
-
setUint16(endOfdirectoryView, offset + 8, filesLength);
|
|
5774
|
-
setUint16(endOfdirectoryView, offset + 10, filesLength);
|
|
5775
|
-
setUint32(endOfdirectoryView, offset + 12, directoryDataLength);
|
|
5776
|
-
setUint32(endOfdirectoryView, offset + 16, directoryOffset);
|
|
5777
|
-
const commentLength = getLength(comment);
|
|
5778
|
-
if (commentLength) {
|
|
5779
|
-
if (commentLength <= MAX_16_BITS) {
|
|
5780
|
-
setUint16(endOfdirectoryView, offset + 20, commentLength);
|
|
5781
|
-
} else {
|
|
5782
|
-
throw new Error(ERR_INVALID_COMMENT);
|
|
5783
|
-
}
|
|
5784
6256
|
}
|
|
5785
|
-
|
|
6257
|
+
endOfdirectoryRecord.uint32(END_OF_CENTRAL_DIR_SIGNATURE);
|
|
6258
|
+
endOfdirectoryRecord.uint16(lastDiskNumber);
|
|
6259
|
+
endOfdirectoryRecord.uint16(diskNumber);
|
|
6260
|
+
endOfdirectoryRecord.uint16(filesLength);
|
|
6261
|
+
endOfdirectoryRecord.uint16(filesLength);
|
|
6262
|
+
endOfdirectoryRecord.uint32(directoryDataLength);
|
|
6263
|
+
endOfdirectoryRecord.uint32(directoryOffset);
|
|
6264
|
+
endOfdirectoryRecord.uint16(commentLength);
|
|
6265
|
+
await writeData(writer, endOfdirectoryRecord.array);
|
|
5786
6266
|
if (commentLength) {
|
|
5787
6267
|
await writeData(writer, comment);
|
|
5788
6268
|
}
|
|
5789
6269
|
}
|
|
5790
6270
|
|
|
6271
|
+
function createRecordWriter(length) {
|
|
6272
|
+
const array = new Uint8Array(length);
|
|
6273
|
+
const view = getDataView(array);
|
|
6274
|
+
let offset = 0;
|
|
6275
|
+
return {
|
|
6276
|
+
array,
|
|
6277
|
+
uint8: value => { setUint8(view, offset, value); offset += 1; },
|
|
6278
|
+
uint16: value => { setUint16(view, offset, value); offset += 2; },
|
|
6279
|
+
uint32: value => { setUint32(view, offset, value); offset += 4; },
|
|
6280
|
+
uint64: value => { setBigUint64(view, offset, BigInt(value)); offset += 8; },
|
|
6281
|
+
bytes: value => { arraySet(array, value, offset); offset += getLength(value); },
|
|
6282
|
+
skip: count => offset += count
|
|
6283
|
+
};
|
|
6284
|
+
}
|
|
6285
|
+
|
|
6286
|
+
function getSegmentOffset(zipWriter, writer) {
|
|
6287
|
+
return zipWriter.offset - writer.diskOffset - (writer.diskNumber ? zipWriter.initialOffset : 0);
|
|
6288
|
+
}
|
|
6289
|
+
|
|
5791
6290
|
async function writeData(writer, array) {
|
|
5792
6291
|
const { writable } = writer;
|
|
5793
6292
|
const streamWriter = writable.getWriter();
|
|
@@ -5800,12 +6299,40 @@ async function writeData(writer, array) {
|
|
|
5800
6299
|
}
|
|
5801
6300
|
}
|
|
5802
6301
|
|
|
6302
|
+
async function flushBufferedData(readable, writer, signal, onChunkWritten) {
|
|
6303
|
+
const streamWriter = writer.writable.getWriter();
|
|
6304
|
+
try {
|
|
6305
|
+
await readable.pipeTo(new WritableStream({
|
|
6306
|
+
async write(chunk) {
|
|
6307
|
+
await streamWriter.ready;
|
|
6308
|
+
await streamWriter.write(chunk);
|
|
6309
|
+
onChunkWritten(getLength(chunk));
|
|
6310
|
+
}
|
|
6311
|
+
}), { preventClose: true, preventAbort: true, signal });
|
|
6312
|
+
} finally {
|
|
6313
|
+
streamWriter.releaseLock();
|
|
6314
|
+
}
|
|
6315
|
+
}
|
|
6316
|
+
|
|
5803
6317
|
function getTimeNTFS(date) {
|
|
5804
6318
|
if (date) {
|
|
5805
6319
|
return ((BigInt(date.getTime()) + BigInt(11644473600000)) * BigInt(10000));
|
|
5806
6320
|
}
|
|
5807
6321
|
}
|
|
5808
6322
|
|
|
6323
|
+
function getTimeUnix(date) {
|
|
6324
|
+
return Math.floor(date.getTime() / 1000);
|
|
6325
|
+
}
|
|
6326
|
+
|
|
6327
|
+
// the extended timestamp extra field stores dates as signed 32-bit time_t values
|
|
6328
|
+
function inUnixTimeRange(timeUnix) {
|
|
6329
|
+
return timeUnix >= MIN_UNIX_TIME && timeUnix <= MAX_UNIX_TIME;
|
|
6330
|
+
}
|
|
6331
|
+
|
|
6332
|
+
function clampUnixTime(timeUnix) {
|
|
6333
|
+
return Math.min(MAX_UNIX_TIME, Math.max(MIN_UNIX_TIME, timeUnix));
|
|
6334
|
+
}
|
|
6335
|
+
|
|
5809
6336
|
function getOptionValue(zipWriter, options, name, defaultValue) {
|
|
5810
6337
|
const result = options[name] === UNDEFINED_VALUE ? zipWriter.options[name] : options[name];
|
|
5811
6338
|
return result === UNDEFINED_VALUE ? defaultValue : result;
|
|
@@ -5836,7 +6363,7 @@ function arraySet(array, typedArray, offset) {
|
|
|
5836
6363
|
}
|
|
5837
6364
|
|
|
5838
6365
|
function getDataView(array) {
|
|
5839
|
-
return new DataView(array.buffer);
|
|
6366
|
+
return new DataView(array.buffer, array.byteOffset, array.byteLength);
|
|
5840
6367
|
}
|
|
5841
6368
|
|
|
5842
6369
|
function getLength(...arrayLikes) {
|
|
@@ -5852,30 +6379,39 @@ function getHeaderArrayData({
|
|
|
5852
6379
|
uncompressedSize,
|
|
5853
6380
|
compressedSize,
|
|
5854
6381
|
lastModDate,
|
|
6382
|
+
rawLastModDate,
|
|
5855
6383
|
rawFilename,
|
|
5856
6384
|
zip64CompressedSize,
|
|
5857
6385
|
zip64UncompressedSize,
|
|
5858
6386
|
extraFieldLength
|
|
5859
6387
|
}) {
|
|
5860
|
-
const
|
|
6388
|
+
const headerRecord = createRecordWriter(HEADER_SIZE - 4);
|
|
6389
|
+
const headerArray = headerRecord.array;
|
|
5861
6390
|
const headerView = getDataView(headerArray);
|
|
5862
|
-
|
|
5863
|
-
|
|
5864
|
-
|
|
5865
|
-
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
|
|
6391
|
+
headerRecord.uint16(version);
|
|
6392
|
+
headerRecord.uint16(bitFlag);
|
|
6393
|
+
headerRecord.uint16(compressionMethod);
|
|
6394
|
+
if (rawLastModDate === UNDEFINED_VALUE) {
|
|
6395
|
+
const dateArray = new Uint32Array(1);
|
|
6396
|
+
const dateView = getDataView(dateArray);
|
|
6397
|
+
setUint16(dateView, 0, (((lastModDate.getHours() << 6) | lastModDate.getMinutes()) << 5) | lastModDate.getSeconds() / 2);
|
|
6398
|
+
setUint16(dateView, 2, ((((lastModDate.getFullYear() - 1980) << 4) | (lastModDate.getMonth() + 1)) << 5) | lastModDate.getDate());
|
|
6399
|
+
rawLastModDate = dateArray[0];
|
|
6400
|
+
}
|
|
6401
|
+
headerRecord.uint32(rawLastModDate);
|
|
6402
|
+
headerRecord.skip(4);
|
|
5871
6403
|
if (zip64CompressedSize || compressedSize !== UNDEFINED_VALUE) {
|
|
5872
|
-
|
|
6404
|
+
headerRecord.uint32(zip64CompressedSize ? MAX_32_BITS : compressedSize);
|
|
6405
|
+
} else {
|
|
6406
|
+
headerRecord.skip(4);
|
|
5873
6407
|
}
|
|
5874
6408
|
if (zip64UncompressedSize || uncompressedSize !== UNDEFINED_VALUE) {
|
|
5875
|
-
|
|
6409
|
+
headerRecord.uint32(zip64UncompressedSize ? MAX_32_BITS : uncompressedSize);
|
|
6410
|
+
} else {
|
|
6411
|
+
headerRecord.skip(4);
|
|
5876
6412
|
}
|
|
5877
|
-
|
|
5878
|
-
|
|
6413
|
+
headerRecord.uint16(getLength(rawFilename));
|
|
6414
|
+
headerRecord.uint16(extraFieldLength);
|
|
5879
6415
|
return {
|
|
5880
6416
|
headerArray,
|
|
5881
6417
|
headerView,
|
|
@@ -5976,7 +6512,7 @@ try {
|
|
|
5976
6512
|
// ignored
|
|
5977
6513
|
}
|
|
5978
6514
|
|
|
5979
|
-
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)});}
|
|
6515
|
+
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;}}})("FABhc20BAAAAAUULYAF/AX9gA39/gQAHBAJ/fwCBAAWAAAsBAYAACgEGgAAWgwAZgQAgAwBgAIAAA4AADQEEgQAVAwBgB4MAHoAAHxIDQ0IHAAQCAAQICAADAAUDCgCAAAeBAAMBBYEABwMBAwOBAAgQAgEABQYAAQEFBAkEBAkCBoAAAR4AAwQBAwQDAwIEBwEBBAUBcAENDQUGAQGCAoICBgiAAJkiQdDVBAsHigQcBm1lbW9yeQIADGluZmxhdGU5X25ldwAHDYYADwdpbml0AAgRigAQB19yYXcAChCGABQJcHJvY2VzcwALhwBGBmVuZAAOFoYADxBsYXN0X2NvbnN1bWVkABELhAAZgwBthQA2gwBsARKFAFiHAGsBFIUAf4MAEwdnemlwABUPhQAUhQB+ARaGAFaBAH0CGBWFAA6NAHwCZGWJAHyFAA6CAHwCGhCJAA+CAHwCHBGKABOCAHwCHQ+FABSFAHwBHoYAVoEAfAkgBGZyZWUAAhWFABWMAIMKBm1hbGxvYwABC4IAVQppYWxpemUAABlfgAAPFmRpcmVjdF9mdW5jdGlvbl90YWJsZQGAABwbZW1zY3JpcHRlbl9zdGFja19yZXN0b3JlAAUcjgAbAmdlgABvDnVycmVudAAGIl9fY3hhgABbBGNyZW2AABIGX2V4Y2VwggBdBnJlZmNvdYAAJR4+CRIBAEEBCwwAIiMMDxcZHz82OTwMAQsK9eYCQgOAAKkQwycBC38jAEEQayIKJAACQI8AAhIgAEH0AU0EQEGkJygCACIEQRCAABIGC2pB+ANxgQAJEEkbIgZBA3YiAHYiAUEDcQSBADIGAUF/c0EBgAAfBmoiAkEDdIAAGQzMJ2oiACABKALUJyKAAAYECCIFRoIAUgkgBEF+IAJ3cTaAAqoRAQsgBSAANgIMIAAgBTYCCAuAAEgDCGohgAA3ASCCAEaAAAUEcjYCBIEADwNqIgGBAE0DBEEBgQASBwwLCyAGQayCAJ8DCE0NgAAbgQCGBEECIACBADUFACACa3KAADUEAHRxaIEAowN0IgCCAI+AAB+CAI+AAAaLAI8FAXdxIgSGAJEBAoEAkQEChACRAQCAAGiDAIWAAAoDaiIHgACigQDfBSAGayIFgwCMgAAZAgFqgQAuCgAgCARAIAhBeHGBAG4EIQFBuIEAoAQhAgJ/gABlAQGAABkHA3Z0IgNxRYMAeAMDIASAAD6AADyBAHWBASEDCyEDgQDpgAB2gAAchACEAQGDAAcBA4MAi4IBHIAAVgIgB4AAOYAA/oIAdYABCwJBqIIBCQILRYABCQULaEECdIAA5gMpIgKBAS4CeHGAAKqAAFkEAiEBA4IBqAUoAhAiAIAAg4EACgEUgAAKAQ2AAH6AARCEACqAANmBAIUFA0kiARuAADaAAUkBIIAACYABOAEhgQCnAgsggABUAxghCYAAFoAACQQMIgBHgABIgAAKAQiAADeEAcaAALEDCAwKggApBRQiAQR/gAHIAhRqgAFTgQB3AwFFDYAAiQtBEGoLIQUDQCAFIYABTYABmgMUaiGAAgWCADACDQCAAOUBEIQAEIAAMQYNAAsgB0GAAFsIAAwJC0F/IQaAAB8Dv39LggAnAQuAAhKAALUCIQaEAP4IB0UNAEEfIQiAAf6CAPKAAsQD//8HgALGgAHBASaBAlgGdmciAGt2ggKlCkEBdGtBPmohCAuEAvEBCIUBNQEBgQGeAgAhgQIKgQAHgAA8ARmAAB0DAXZrgABXCAhBH0cbdCEChQFJhQE0BAQgA0+AAJMBAYAAtwMEIgOAAIYBAIEByoAARAEDgQI/ggFoAgQgggLFB0EddkEEcWqCANwCRhuAAB0CBBuAAGQBAoAAj4ABZIEA7oEAMQIFcoMAhAEFgALPAQiBAruAAO6AAs8CB3GBAa6AANiFAeEBIYABHYIBwIABTIgBwoACLgJJIYAAbIEByYMBxAEFgQAJhQFTgAGTAQGDAW8DCyIAggByAQWAATkCIAODA02AAEGBAMsBBYEB5wEIgAA5gAAJhAHngAAKjQHngAKTgAAWgwHnAQWCAeeAAA+EAecBBYIB54ABK4ACeoAA+4MB54IDgIgB54IAEIQB5wEEgwHnAQeHA9gBBYEEgoMDQ4AEpoAAjYECnwNBEE+AAI2CA4uAATKGA4ECBWqBAJOAAFeFA66BA1WAABeGA7sBBYsEQIABX4AEJwEhgAHlgANGgQA6gQNWgAN0gQCZgQNlgAJvgABKAbCCAIgCAkmAAIgBsIAAH4IAgYEALAK8J4AAA4EAG4MAiIEAN4kAjYYEMYUAS4QCSgkvaiIDAn9B/CqAADuAAFMChCuAAAiBAmgFiCtCfzeAAFcGgCtCgKCAgAABAQSBAA4R/CogCkEMakFwcUHYqtWqBXOBAHoCkCuCAScDQeAqgwAIBoAgCyIBaoAFooABkwJrIoACI4AEmQVNDQhB3IEAZAIiBYAAZgHUggAKAQiABKMFIgkgCE2AAUcFCUlyDQmAAvmAAEUDLQAAgAKQgAJvhQX6hADYgQA5BOQqIQCDAlqBAD+BAY2AADwBCIICagNqSQ2BAtuBAhKCAkMEQQAQBIAFdwJ/RoAB+QMBIQSAAMmCAR0BQYAAk4AD+4AGIYEC/AFrgQVTAWqCAs0EcWohBIAB8oEAqwEDhACrgQERgwCrgANFgQVnAgVNgAFKAQeAAKuBACqAAF+AAWMFRw0BDAWBADiAAEyAAOuBABaCAkKAAFOBAJUBRoAE/gECggMVgQCKgAEJBUEwaiAEgQC4gAHtAwwEC4MBcYEDIAMgBGuBAIkHAmtxIgIQBIMALgECgAB3gAKqgQArgADcgADNBEcNAguBAWgB4IEAlgFBggWsgAWohADpggDygQBoAXKBBSQDTXINgANTgABQgAPoCAZBKGpNDQULgADOgwDRgQDPggGsAdiCAA4BAIECTgLYKoEDSQEAgQGFgwFxAQOHAXGDANOBA2uAANUCIgWAANeCABKDAWuBAMcBtIMCe4EBSoAAewEbgQQtAbSDAr2CAmkEQegqIIEGzIAAUIIAFQVBxCdBf4EACALIJ4MCe4EADAHwgwJAgQHggwbPgwewgAZQAdSAAxCBBlgC2CeBBSeAALsDQSBHgAB5gQMBBARBKGuAABABeIAA6QFBgQJrgAHegwMOhAegggbOgAN0hQMIBAJqQSiBA2wEwCdBjIEBe4ED4IABzoABgQFNgQZkAktygwDaBAxBCHGBAAqAAdkCBWqBADCAAFEBA4AAZgEDggBmgAhRggN0ArAngwOPgQFPgAAtgACJgwBvgAClggBvgABWkABvAQOCARMCDAaDAAeFAT0DIAJLiAE1gwH7AQWCAYACAkCBBpmEAYKBBPeEAXoDAQwCgQWcAi0AgQCtgATgAQuEAa6BCSyDAa4BA4ECaYEHPIICjAMiBUmEB1kBCIIGTJQBQIIHyIwBQAEHmQFAgABiAgVBgAf4gQBBA2pBL4AAT4AAKAEDgAVMgAmUAwFBG4IJLAlB7CopAgA3AhCAAAsB5IMACwEIgAAUgglbgQBwjQIghAIMgAAgARiABK+CAhOAAJiEBL+AAWsBQYABHoEE4YAA04EDAgMgA0aBBu2DBU0BfoAJx4AG/4EAFoAGeoQAuoIIxQEAgAj2AwJB/4EKR4AACIQJE4AAFYQKVIAFLoEJ44AJEQEChQkRgAARggkRggmGgQE6AQuABseAAN6BCRGAAGCABnkCQQyABbYBCIEFMwEfggc3Af+EB+EBAoAH4YAAGZAH4YAAsYAHAgY2AhwgA0KCARMBAIAHPQNB1CmACZ6CBO+DCDuAArOBCjmCBQqAABOBAomDCZuBAHaCAI8BAoAIB4AAVYIIB4AIZoEIB4IH2oAHpoECMYEK4YIHgAECggOugAfngQdwgQfXgwMSgAf0AiIEgQbrAQWCBuuBAFcBEIEAmoAB8wMYQQiAAWUCAyKACDACQQyFCguAAdeBAPCDAIGBCg+AAMOACNmAACMBGIABAgEMgAA7hAbwgQL2gwRLhAatgAZoAU2ACIKAAm6BB8yxBq+AAyUEoCdBMIEAOYEDNIIIxIMHGoIC24ADLIIDb4UCxwFqgAYdhQBCgAmQgAaHggAVgAUJAiAIgAbwA2shB4UE5QIgBIELcoED3YoD0AEHgwUfgQDlhAvcgAHgggf3gwAxgAeZggAxAqwnhAijjgAxgQIlgwEGgQFAgAFogQWbBANxQQGAAD+AACSACiQBCYEAFoACPYIM24MClIAAEYEI0AECgwwGgwKWgAwKgAA5AXaDDJwBAoEC7IcLh4ECd4EANQMYIQaAAEaABDOBBB6CAEWCAR+BACaBAaWAACaAAB+AABiAC1yACRcBBIIJF4IB+4EJq4AAEIEJF4ALi4IKLoAGjYEJF4IENIAAMIADV4ELHoEJvYIAMYECLAEFgwkXggqOgACSAQaACayDAGABHIAA5AECgAW6gQoKggEpgAF+gALYgwGrAwINAYACyIMC3oEA1YUA0oEAOwIgBoAAXYEAMAEGgQAsARCBANeCAAoBFIAC5oIMDoAI6IACl4QAtYEDXoEA2YADOoEAJQEYggEEggw4gQJFgAAZARSGABkEByAJaoAL0wEEgAAHgQLtAQSBA32BAlaFBCSFBNmAAAoBaoIMwoAAEoMBjAEHkwQgAQetBCCDAymBAAeEAbGABCgBAoEAZoQEKAEHgAQoAQeSBCiAAVuCDXSGBCgBAoUEKIIPIYQEKIIEtQN0IgWFBCiAA9uDAJKGBCgBB4AEKIAFB4IEKAEChAwvggYigwH0gQ56ggQoAQeBBCiBDA+BAe2DC/+BBYGBBCiDC0SCAfyGBCiAANYBGIAAB4QA5IEA8oUBBIEGeoMLk4MEKoECL4EAK4gBCAELgAy5ggPaggIAAQiDAkKAAGYBHIAA0IAAzoACbIACQoEPDoAAioECQoIDXYAG84EA4gEHhA8dgQGvgwBAgAoEhAJAgAoMhAJAggAKgAJAhA5OAiAIgQCEgwDIggutgACGgAaNggDGhQwzgQJAggAZARSFABmAAFwDA0EPgwpnAQOBBKmAA4uHC72DBH2GBCGBDA6EAB+AAAqBBG8BA4YCXgIEaoIBj4AAEoMCXoAITJECXgEDogJegAcqgQJegAAHAQyBAs2DAAeHAl6CAGaEAl4BA4ACXgEDlQaGggA8AxwgBJEGhoEDGoIQuYUCWIACtIQGgIEHqYMAcQEYgQCYAQOWBoeDAl+FD/OAB6OEBoeCCSGBACaBBfKBAl8BB4cPWYEAXgEQgQtPgwPYhQDlgQDzggb0gwTdggAWgATwgQEJgg2lgAQbgwTyggDUgQ4FgwJfggT6AQmDAl+AADyEAl+AAe+AAl+BBWeAACiNAl8BC4MCX4YCXQMCIAmEAl0BCYYCXYIACogCXQEJgQCCgxBQjwJdgxB3mQJdgQv/igJdgAl6jQJdgAUChAAfgAAKgAOSiAJdgA5pggJdihHqgQ4+ggGFgAJhhRHogAFehQJbAQSEAc+IAluCEjWCAVKDEeOED1mCAfEBCIEG/4IR24EOnYEAboEIgIEBYwELgA4SAxBqJIAASgYL3gsBCH+BBs+CAOwEQQhrIoEHDwIEa4IM4oAAmIALOAIhBYEBUoACiYIGWIACXYAGgIAEPYIT0oAAL4MLC4AKp4EC5oQE6IAE6oMHegEDgQbegAArAQyAAkEBBIQDSIAAPoECEoANhwECiQcyAQSGBzKADZyAACIBGIER14YAQYAAMIUA4oES2oEMAIAAFgMUIgKABx0BA4IHHYAADwIQIoAGeoAAm4IHHQEEgALKAQSAEeoBAoACQIAHHYABIYIAMIEKdIEHHYIAEIAAMYECwgEGgwcdgAijgAJmgQ2ZgAf1AgNHgA5UgAE4ggJngA5+hgZ/hQgtghRxAgAPgQHmiQCZgA3tgRAQASCBEkeBAi6BAsEBBIcFIAEDhwUggwuoiwdiAQSIAsWABuCEAsWAAQmEAsWCAAqAAsWAApuBCeOBBv+ABaaCAMmDDx6BAsWCAJGAAsWDASGBAdmCABkBFIcAGQIgBYQRngEEgACcAQGAAdKGFb+AAYeDBD+DCWuCFN2OCWuADUyMCToBA4MB8AJHDYERdYMQUwG4gwAIAQ+ECYWBD4uSCYePAE2GCYeAAV2CBIeAAoSCAK6JAkaCEkiAANGMCXiKAkaOAjOEEpCAB3CGEouLACSDAgODAleIEouAAUWADLi0AleACBSACbuOAkCHCm2CDl2BBv+IB1OIAjOIB1OdAjOJB1WFAjOCAAqIAjOHB1WQAjODAP2SAjOOALiBAqGAD9OFAyWAAa2FCxSBCyyCBNGAFrOGF/yBBkKBBNEBAIUEz4AEL4IEzwEChQYlAQuCBl+CCICEDLiEFsCDDLiAAkoBH4IGiIUHKQEAgAcpgASzgAcpAQKDBymBCQKCBymBBuOBALmGCYeBBkOCBykCBAKABO6AAJaDCYkBBoAAlgEBigcxAQaCAJOCDVqBDSWADuyCBW2ABzCAB+yCBzABAYMHMIACioEFq4ICD4YHMAEAgQcwAQGBBzCBDMWABzCCEhCCBzCBCy4CIgSCAheCCY+BAF2BFNQBQYIA9wIDIoYBBoEIhIcXroAAJ4AA44AAiAIAC4ACdYAFEIASi4MBfIIBGoIBjYALZ4IRngHEggISgBAPgBJRAiAAgA/FgBNTBIwLAQeAAA2AE7eBBceDEGeBBOKKBc6CEHuAALmECEiBACaBEoWEBo+EEL8BDIEX/oUJC4MKNAEEjAXDgQ+JhgN9gAAigAzkgQCihhEAggDThAHWggOQggywAQSAA2yBFdeEFloBBIIWnYgV94AHAoAGZoIV94IE0oABRYIF44MAEIQBVYQX3pIFw4IDNocFw4EBw4UFw4EAG4EEZoUAmYIItIIFw4AASoQNJYAAlgEcgABRgAOQgAHygAOQAQCBA2ABBIIDkIMKIIsDkIQak4IDkIAPFYYNJYEB9YMNJYAACoADkAEDggOQgAhFgQOQggD6gQOQggEcgQOQgAAlgAN3ggEhggOQggAZgQOQggAZhgWvhADukQW0ggWGhgW0gBODhBbahg+ynwW0gBWwhAW0ggAfhgW0kABNgRq8hAFOgQg4ggJNgwW0hwI3ggVxgAFsjAW0igI3iwGLhQW0gAE1igW0iQJIhQW0gQJIiAW0gAJIhQW0rwJIggW0jwIxhgDmgwW0hwIkggW0iAIkggW0owIkgAx4owIkhgW0jAIkhwW0iwIkkQC4gQ1VhAW0hAGtAQGFCZaPBbSACq6BHKaABbSACCOFDN6BCtCKBbSBBOOBBZ+FCnyEEMeDCpiCBbSABYuGBbQBAYYbRI0FtIISIYAAuQMcIACDBbQBA4UFtIARb4YPO4EGSIAWaQEHhxNjgwsUggCEghbKhAzjAQGABbOAAMGCBbMBA4MFs4ABH4EFs4ICDoIQWoICqIEFswEDgQWzgQAHgAWzgAJ6gACVhgzjggfKAQeFELuAApWCAVmEAOqDBpeFEgSEDdaCAQ2AEvWCA9iDDPeDAQ0DCwtJgQvaAZCDDjuBFR8BaoELYgECggs1gAB0ggNQgheJAyAAP4AFAgF0gB6RhxNFAX+AAUwBkIQKkAMBCwaAAC0GJAALBAAjgBOzAgEBgAbVBEHEABCAEBmDC8gCBGuBGZOAHiSCAA6ABh4DAPwLgRjSggVrgAEjASSBB40FNgIgIACAEhkDCwsRgAAmgQFRAX6CB8ULEBAJC9kCAQN/QXqABzAEQEGUCIEATQExgQI4AX6BDHKEAFWEBLgBIIMCfIAACgEkhAAICihBAUHYNyACEQGABlaBAFcBfIEAV4MRF4AA5gM2AjiFAa8EAkG//oAACYAAZQQgABAkgxYPBkEfdSIDc4EWCIABj4AUBYAWLoMC0gEogw58AnZBghn+gAcSAU6AHl0BIoMQtoIAPYIAXAM0IAKBAj8BLIkAFIAA54EAB4ABloEAG4ANzYIN8YAAX4ADhgEwgALIgQAWATyDACsBJIAAB4AbOYIOHAFCgRtEAXCCEcYBQoAAqAE3gQ3IAkKBgwAUAcyAAOCAACsCtAqCCr4BcIMA0QFUgwAHAlBBggkNgAEJgxmFAiQRghwQgQ+5gAIsjAFtAXCAAW0BEoIB+oIOU4AGlQlBBBANC4YlASKEIV0CFCSBAXgBGYYBJIEHjAIiEoQBbAMEIROEG1uBAjcBE4AEZwMAIROCAH2BBJAB3IALOgEfgACnBfQFaiEVgAAIAdiAABABG4AACAHwgAAIARqDAL8CIRaBACCAABADEUGcgRgdBCEcQZiCAAgEHUGUK4AB+AIhHoEDNgNAIQqBAAcBPIENlAFBgBg2CAJJISBBfSENgAAOBgZHISEgE4ECGIEDLwMXIRCBGPyRIg6UAAKBCZCRIjyBCVSACaGAAXkXaw4TBAUGBwgJAwIMDQEaABwPIyMVIiOCBIEFTCEGDBqGAAqAFtKAAAoBbIEeUoEACAEigAlGAygCYIAO0wUDIAxJG4AAIQQGCyAggR/ggABWgAZUBQ4hDQwdgwTIAg0QgA8UAghygBXiAQiBBAKCF48DCkECgga2A0UNDoEajgFrgBVqAQOAARIDIAp0gBR6gAEKgAJBgAS3BCAJIQqDINSBEYCAAlIDCEHBgABegALUhgDLgAAYAXaCFkkCaw6AIzkBAoAE6gEegQ12gh+eBQgDQEGQgBztgA/vA5ABRoEBxQERgSApBnRqQQg7AYEgLIAAZIEKhIAfngNBgAKADL2AHRcBAoQAKIAFDYAAKAEJgQAogAALgArdhAAoAZiBHywBCIAAB4oAUAEHjQBQgAA1AaCLAEuCAHOHAEuAAJ8BBIACDgNBoCuBBIECoDyDAAkDIBRBgBE8AQyABYkBEYAAQIAAF4AAEQcMaiAVECUaggBUASCKAFMBBYwAUwGcgABPATyBArEBHIMAS4AQoAEMgCChAxFBIIoASoACfQNBATqABHcDoCshgQGjAiAdgANYgAN/AYmAA38B0IADiwFYgAATgABCgANyAkHHggRDAkEBgAKqASGACjsCCkGAGC0BCoIV9QIhB4EAHYEIPYEghYABFIEB8YASLQHEgQGggwvYAsILgRk7AdGBABGCG8GAAEqBER6IAEOFAD0CDBuBABmAGAUBBYAGDwEKgBidgAAcgRm0AkEfghgHggfwgAIkgAF5gQIkAQWEAiSDAXCDEtsDBQwCgAVugAFTgQIgAQaAAFQBCoIAkQEegAWagQh5BP//A3GAAqsBB4ElAgIQdoILNQJB3YMSpoEAoYIKsYACawQbC0HCggBAAQKBAAiEHLMDNgJEgABagAi9gABUgQOTgAQdgQBbgACzAwJBw4IAJoIC5wFEgR4hggRmgAAEgBvrAgMggAdnAiAQgQAKgQKOgAAqhAMWgAA5ARKADjoCAxCAGxGCADmABZCAAGSAAC0EEmohEoEANgJrIYEAO4AA1oESfIAADgMEDBmBAG2DBdABDIEKooIDQgINS4EYrowBHYUDQYQBHYADeQFqgwNEggEegQGegwCGgQBSgAEQAR+AARcDQYECgBowAWSCABACBXaAABOAADsDNgJoggAQBQp2QQ9xgBxeASKACScBYIAATgEOgwG9AQ6CAb0CQR6CIekCQaGKAUqAAKGAAAwBxYMCOgIAIYAEKIEFnwFsgAMVgAOvAwYgDIEKogETgAAJBwZBE00bIQmAAMsDBiAJghdsgAATgAr+gAFxAWyAAuOAAAwFdC8BsA6CAuoBAIEC6gEDgARlAQCBB2uYBE4BCqMEToADYoAWkYMAaYAADIYAaYAA2wIHcYEAbIsCpwEEgADGhQKrgwBBARaDBpKAAAeABqCBHYyBAzWAAA6ABqCAA3AFEyAaIBuBA2wCIg6CASEBv4IQGYYBIQEXgQEhAcaEAmGCAR2AASgBDoEOh4ICSgNkIg+BAAcEaGohDIAA3AELgAVfgAEygB2qBCgCWHSAAsEBIYIVWwNQISKAAQGAGzWAANgBCoIBBQEigAM8AhhxgAnZB2oiIy0AASKAAwaAH0OBCuiBGHSAARWAAQGJAz8BCYEBFQEJhQM/gADXgAGfBiMvAQIiCIUVhoAI/oYBJoAADIABH4IExYEj5oEBHAIgBoMBHAELgRZXAX+FBm2AAnoEEGsOAoAFjIERpoAJgYIPx4YAjAEdowCMigBlAwUgC4IJuQJBh4sDswEJgAGTAQOAAvmAJqaBBmyAAgaBADOAJZSBAJiAJFiADqeBJqiBALsDIBFqgAAeAi8Bgg7HgBY6jQCXgBDOpgCXhAIbgACagAszgwIggAI2gABUggxfgAp6jABcARupAFwBB4gAXAEHgwBcA/8AcYAnSoAnkYECIgMEIAyAACkCC2qAAhSWARGAA92BBT6CBiqDAbgBBIEBuIEBz4ACYoMDIYQCyIAFowFsgBfAhAA4ggAUBC8B9ASDAW8ClAqKArcBFoECt4AAcYUC64QDAIEGrQIgD4wC8gGjiwLyggA7gARDAVyDBPMBcIADPoEGmYIC7oIAoYEC8IAAQwEfiABDAfGNAEOEBnGGBpaAAzSEBZGAAAsBDYMAZAHIhQWRgQNXAtA3iQM3ggNVAVCAA8qLAzcBDIABboAE44EDNwELiwM3gAP0ogG4AQuAAzUCIQ+AAvqAAECAKeKBC1oF/wFxQQ6BAEcDBiEMgACdAQaBAhoDDCAPgQBmAiEYgACVAQaAAcKCAJWCAakCIBiAAIQBC4AoGgF2ggCHAQ+BAIcBDIAY1oEB5IAAiAENqQMzgQdCggOYgABGAQCAAe4BD4IAnYEB6wEPgQZlgAVkAiAMgAXeAtA3gAAvAQyDAmwBDIEALwELgQC0gA/ZghUQAc2DAXMBEoEWJAEggSYchQZ9gAAJgCSoAtA3gwAbAsAAgQAcAwBB1YEH6YcBqoAAHAMCQcmFB0ABBIEGZIAB+wFMhQJmgg/ZAQiMAYaAALyEAO6ACFKiAO6CAkmAAMcBBoMAzoQHS4AH4gIgBoEBWoAOZAEMgQDxiwSthQLpgCr+ARCDCiQBEIEA7YQHFIAL3QESggBHgAkdhgJMAiAQgQCPAxAgEoEAggMSDBGBEUeCB5sBCoEXEYAB0AEKggdagAXPhABGhgAiggAYgAcIhAAYgB4mhwAYggASghMekABMgAE8hAA0AQ6ABu+ACX4BDYILfgJB0IMAkYYJI4MJNAEKhCvMAkQhgiKckgBSgADLhABSgCk1AwJByoUBnYABIwLUN4ArtoEAQAFcgwKRgQALAVSSAyYBC4MDJoICn4cDJoIbeqABsIICiYEGZIECmQIiD4MqJYIBw4IHloAAYgELiAMfAQ+DAx8BD4YDHwEPhgMfggOmiAMfpQIxiwMfhQI9gAIcgQO3gAQeggPHgACIASGADMmBAycBCoUDJ4kCQQEPhgL1AfGKAvWGAlqAKx0DAkHLhQFgAQ+ACT6DAv2CBWsBSIcDBIgBXwMgBgSDJtOFAwOCHyq0AwMBSIkDA4EAcpIDAYEApQHMhAUrhgMJgAARhAIlAQaAB9CCAE2ACsYCFyCADygBCYAB7YIbNwEJgRzFgAAaATCAJMKBAAgCzDeDELIB/IsGKwEHhABBATSAKtEBA4EA1oAADIAQmgEogBA8gwBEAWuCBy2CABaAACIBa4EG3oETY4ELR4EUkAMGSRuBACABEoEK/oIumoAAF4EvfIEBmIcLWQEJggs4AwkhA4ABPgMSIAWAAS2BA7mDA6mBBueBB/2BAUqBLfGAAOiAAHmAA8iBAE2AAWKFA9+BFQeSAzOAAcSEAQ6BDLaFABuJA9uAA0aEACKACFSIB0OIBBCBABaEDIyBEacBEIMS6gESgxK4gQ0RgyGKgRGGgAFBgQl0gApLATyHD6YBLIABXQQQIBdGgAhXgAP9gCmOgRHFgBgbgSYSgAARgCsVhBCQgBVmATiDBb6CGECAEieBFXkCKHSBGhuAEkiBEi+AAG8COCCBFbqCHL4DLCIFggAugRGgATCBASaDADCBKi8CLAuDAfWAALuBA6QBBIEBXANrIAWADLCCIrsBNIMeogEsgBHggwRwgAANgAHoAWqBDNaAACeBAd+AC5yAAAIFCUsiCRuALAMDJiAJgQBqgQHsgQz5gB7ZAgRrgCwwgABPgQEDjABPggANATSBKkKBMCaAAVSBAKsCCUeAGXKAACmAAniAAJYBCYEdYYENaYEpLIASZIIRrQIIIIIRrYAddQFrgAAWgRrmAReDETaAEu2CLRIBFIAAF4EVwIABVgEgggA6gBK6ghF/gAPSgSQKgABDBBtqQYCAEeWDER+CEMkBRoEAE4AStoIUQYEOFIEwEoEIgIAAGYABKQcgDUF7IA0bginigAemgAGpARuAAAgDBCATgAAIgAGoBEYbIRmDKJoB0oMIsgJ8IYANdwEUgyAgBhkLlAkBDIAUNIYSsIABIYAI0oAAB4ATMIADNIADQgEOggePARCCMn8DAkFAgAGOhyf4ggt1gDP2AQKBM/aBKNeBM/WABMABDoEgaYAhowEEgAVkgAYeAQ2BBXKBFK6AAEoBC4AAyYEgTQELgA3RAiANgQvkAQmABBMEDSALa4MteIAJigFNgS1SghekAwkgDYAMgYEI1oMAK4EAJ4ABlAEQgQBBAQmAABUBD4ARZwJyQYEjkYAE/YAIz4AehYAhVoIADwMMIAyGIayABHkDCBADgSOKgxlCgg3/gxk3Aw1qIoAAVYAAcpMAUAEIgwBzhCaTgSkvhSuLgQMygQBSgyEIggBSgxk8gABSBQggC0kNgShFgAAJgQA9ggZnkgBgAQ2GJu6AAlOBADmCJvCAArmGKzWDItuBADkCIAiFADuCACwBB4EgP4cwp4EQHAENgiISAQ2EIhKCJYyBBtWBAYiAMrkBcYABNYEii4EAooALlIEBRIAABwFrgASngAAiAwwhCoINN4MYLYAAEQEIgABhAQqMGcmBIrKGKPWAAB+BBEOABdaEJAiAADUBGIEUHoAAEwEMgRDehQBFigAmgAAfgAAYAxQiB4AWqgEMghnNgAAPARCBM5UBAYAAEIEZzQENgAVJAQ2ABLMDByIKgRnNgAEiggAwgANvgSLVgAAQAQqCADGBBU6AA56EAYaAERiBBkWCGayAAFEBHIEA8IAYRoIZrIEBnIABZ4EZrIAAjIAAR4sZrAEIiBmsAwwgEIQZrIAUL4QZrIIACoAZrAEKghmsAQqBBUABGIQAtYAAKIIA2QEQgwENgBB0gwDcgQaPggAZARSGABkBEoMO0IQBygERhwIFARGLAcqDAe+SAooBEoQC2o4ANIACEAISEIIF/4AH+QIHC4IAmIAov4EG3oEESYAYNoElbgMaQXyAK3cBDoQj/IAQVQJxG4IpUYEATIEQ+AMHSxuCADoGCSAOIAf8gDp4gAPHARCAAxcCCyKBBAKHF+QBPIAABwEOgAXHgAQOgAAugAz+AiACgwAuggZNgQZbhChpgAAsgQZbgQRTgxm7gAgGAhEDgCEKgQAcggUogAc7gQXbgQUjgAyvgBpCgBmvBkEYdHILCIEE6gUFEBALT4EZUQF+gQAzAxAkBIAACoIeRIAmMoEGaoEAf40XhYAAHYEgHYIAF4IGdogXnIEZCYAfi4cE7AMgARGACXWCACcBOIAA6gEAgAAEAwELEIQAIoQX4wFAjBfPBQ8QEwvSgRk8hyVUmxkpgQkUoRkpAbSHGSkBJ4EOTYAtIYABDYAKcoAGDQNIIgSAE8IDQQ9LghsdA0GB/oAFSwFyiBk3ghkvghk5gDYphRkygABGjhkyhgAUjhkygBlunRk1gRt6ixk1gAC0ihk1AcS0GTUCQX6MAWYBcYABZosAEgEfgAASjBlHAQaAGUcEs0QBI4QZRwEQghlHAReFAUKDGUcBDIQBioQZQIECdYYIr4IHYgEDggdigg5eAcCDByCAAAeBHKyBGQcCIR2AABeBGWSAGSSjGWSDGUyAECCDGUyCCA0BHIUZPAMOIRKJGQKBFIyAGWSCIbelGTbDAAKAAeaAAbsDaw4fghl2GzM0NTYKCwwNDg8QEQMCFBUBJAAmFxgEPj9AQYQZeQMLDCSGAAqBLf+AGXuDDkyCGYWCGjqDGYUBCoEH/oAOMYEAEgEMgAwhATKDAAqCFn6GAWICDDOBEHEBBoMFEYAKDAE3ihY8AQaLFjwBBoEMaoEQu4Eq1YAhBoAEswSflgJHgTj7gQBbASiDAFmAEFcBKIEGBYAEyoAdDYAAAgIQKIEDBwEcgA84gAAuAjsBgTEbARCAAEoEQQIQKIIgsAG1iBdagAQZgABiATOCAKsBJIE204ACXIAQYYADBIAFRQN0QYCAA26CLg4FakEfcEWCAyGCCMkDAEG5iwxwgABCAQeBFqkBCIMX2wGHgA7YjQAeAgR2gDJEgA2OghcSgRjLAgdNggDGAiIJgAcPAQmADGWDA9GAAn8EA09xDYAWoYAFroI6zQGuiw3pgRRtATKLAUYBNqQBRoIL3oAGmIISH5MAq4ABtgQHQYDAgT2ygAAdAdiLEwODAdMBJIQYaYEBGIIEMoE2pIEANoAqzYEEZIE1AYMAC4ABdwM6AAiAB0aBACsCOgCEPBSBAZqDAY+CHTUDAkG2hRNPgQjIAQaDANuDGXkDRQ01pQDbiACYgQ5WgQy/Ay0AFYIlBYsAlIIIjooAigEEhgCKAbeQAIqFAWWADBSuAIqAAPeDIs2CAXOBICeZAJiBAqyTASIBuIsAmIEAJAEUgAS/AoAIgQGnAQeCESGFAKmBAASLAKiABLyAKDyKAKiDGqyCAksBNoIaooI+yoATnoEAvIENLYAP54EI+YIDV4AAaIEAo4AFvIUArgEogACugBv8kQCuAgwohQECgQAngg2wARCAABSKAdQBMqcCr4AIEoECWoADh4ADj4A84IECc4QDlQQYdnJygwPpggh2ATCAAScBvo8BJ4EQXYMItYEInoAC7I8O+YARH4UO+QRBAiEXgAEShgRKASmMAGGDFIUDCyAdgB8lAg0vhB5egRorjBoQgBh4hBoQAQ+KGhCFAOyGGhCHAOmkHl6BHlaABjsCpDyAAE+BDHeBHW+CD/b/HmubHmsFqDxBsDyCJrYBzYAABIEACoACN4kebIAAGIAAEoIeIwEqoR5tAayAAFEBzYIH34IpNQEQiR5uigBMgAEtgh5vgQHXAaiBATCPHm6AAEKHHm6DF9SAEgSBGWgBBo0eKgEynx5jkwA5ASqBABmEHmOAGaW3HmOAAE4DBgwwqR5ZAQaBAH2THlOAKniCGMICDC2eHk8BDoAACgEOgh5PAg0sgA0ukh5CAQyAD7OBACkBa4AQSYseQoEEGIUeQgEngwQQgg/XgAQQASuoBBCSHjCBOZ2PHjKAAZsBYIAAP4AeMoEBjIIeMgQFQR5JgSYRAU2FB8aLHjkBJ4oeOYAI3IgeOYAVp4MeOYAZcIIeOYMYNgELgx45ghyqhB45gRryjR45gEVqgR45mAQpgBtWoQQpAQqBAGmABLmBAGmAAAyPHjmLAn0BCIAAxqYeOQIhDYoePQMqIhSCASWMHj0BJpEePYMKGoceOYEB4YARuIE9Q4gbAgETgxsCARiGFn0BBoIBBYEXXwETgxfcARmBF1yAHUOEF9yAAL2kHjkBGYEeOQEEhR45AQ2IASaAAAyFHIEDBSAKggEcAiAKgwEcAQ2LHjmAOXmFHjmAHcuAAn2CAeIBCIQXFQElphfnhwBlAwUgDZ4eOYAU7oACBoEAM4weOQEEggC7ih45gCAWjQCXASSoAJeEAhuAAJqAESSDAiCHHjmACpGNAFwBI6kAXIAeOYYAXIIeOYASUYQeOYADTgELgADygRWsAQ2bHjmCCCqBBQ2FAbiCBkuBAc+AEf2DBCaEAsiAEuqmHjkBJaAeOYUC7oweOYIAO6AeOQEeiABDjB45ggBDhh4zgQ9whB4zAwUMK4keMwQEQQZJgBGkA4ICSYIM4qYItYAFjAIOaoAFFAFrgBpEgQV9AhJrgSgZgRaegQ7HghaWAxwiDYEXJIADkoEWzgQgaiEhgAOXgAAMgxtzASKDAA2DA6QBI4EACwFUgAOkgAAHA1AhGYEABwFAgQLIgQ7VAQOBAAeBFiSAAAcDMCEkgga/AQ6BA3KFBrSAMLGAAAuBPs4CCGqAGK6CReMBcoIKfoEDTwILIIArtwIgI4ID6oE9IoRBSQEGgQP0gAzsgRmBAgR2gQQWgRuhggHKgBtmAy0AAoEZVYEjMYAcYIADBIADpoEK9gEGgRsuAQmCSTeADVWCAC6CBO2CA9OBECSCAJiBIY+BAt2CBk0BCogAqIIAnAIIaoAAT4IAeYABAgEEghqzgTyggBoRgACJAQuCA4uCAN8BCoYC/4EAC4YA34EdAIAA2IEh8oEA5gELggTJASKEAN+HANsBCIMb9gEIgQMUggDbgBbFgUsRAX+AAJaBALuERTiBDhSCA4iJA2yBBe+CEPGBPyiAGvMBGoMAgQEDhAAfgS8Dgg5MAQKAA2aBDumCAM6AIbSCAUeAASKCG42DANoBaoAFWAMMIB+AGP2DG0yAGkuBRIwBJIEbSYAB0AHEgRtJgBtHgAZqgR0mgRd4gQFUAw4gIIFFCoAD2wEEgBQsgBj6gS1iggGXghrsgwGXgiU4ggZ1gUKwgUSDghmYAQuBBcYDDiAhhQBBgRcRAQSDPf6kAEiAGriAGsSBAKmAFQgCIgeAF6uiADaAFnSBBI2AADQDayEJgRawAQ6BBHyJAMaBOwueAEiIAEmAAVgBCYEEmwQJQQNJhgKZgwA8ggHlATqAAZWFAq2AFTiBBWkBCYAAV4ACaIEAV4AAB4MHwIAVjIAg/4YAPAIJQYBCDIAXBoMC3IAMsYIAcIEjvQEMgByGgACrhAAogAAMhABkggAKggBkggBWgC6TgwYqgQByASKAAE+ASveCAGaAAnuBACqAAD6ABb0CQQKBChiAEFCEAGaAAOMFLQAEOgCBRomADh0BDIExmwEIgx5YgB5WgQECgh4YAwgMH4Ee+4ECR4EC04ICS4ARFIACS4MC4oAA0oII1YIhiIEBFQEZhwAshwNRhgAsAQuBCf6CIdADDRwagCGzgAAVgCiKiAE/gQNMgCBngBtJAU+AJLOAIq6BREyCLAGBCGYByJEjTIAD0ooISoEeZ4QjTAENgQN7gAabqwhKAiANhSNMgABAAgAigAZ5iCNMAQuCHZqCAt0BCoQjTAETgACVgAA1gyAtgRi+AQWAHAeAGtMDcSALiCNMgAo8hSAtpQCIgApagwPLAQuGI0wBDY8jTIEAWYEBG4wI2gENgiNMghT2hiNMgCf0AQiRI0wCyDeDABuUI0yCKCuGI0yCBLGAACGII0yATlGBCtGJAYaAALyEAO6CCsGlIEmAAMeEAM6II0wBC4UEvIMjTIABFYEA5oIBFYUH/IACNAEOgQ9pgi4RiyM7gAsbgQyKhANhgAGqghSSgR55ggd/AQqLEJgBJKQMiIAfQQIgDoI9TYwd1gEDgh3WgUXLgBl2gQeKAUaCB8qAEgGBIQKBESuCIoGBEb6BAk+AAb8BA4MUlIIAloAAN4AEroACXYMAGQEpgRaKgxSlhBCBggPagBF1gRFzgBoEnBEcggBnAhtGgAAxAwBB54oJEIAFVgMSDB+BD5eBJs2AABKAAMGAEA6AKq6DACaTEPwCvf6CHpKCFB8CAHGBSEeBDkOALOKFIL+ABHKCIKQBBoEBaYMAFIAAZo8AHpEAMoApPo4AFIIS+gHOhSRzhA8zgw9EAQaCK+SBJHMBCoM30oMOy4AA2IEANAHPgwK7gQyUhyRqgAECAcyLJGqCAZIBVIADV4sCvoAcdQIgCogkaocERKQqx4MDp4EdU4wkagLIN4MniYAcx4gEPYokaoEEPYAZ+IQEPYEH7IEeo4UEPaUAgYsEPYUDW4ABIYEIXIAFPAEKggChgB1qggN7gSgMhARFiQNfniRqggFgiyRqggQbgQ6lgRCXkiRvgAFkAiALhCRvhQQmqidyjAQmgyRvhAQmgyRviQDFgQ1lgACEiSRvAQ6BNXmAKbuAAMCHJGWCA9GBAeiCJGUBBYwkZYIJHI8kZQEShiRlgApCjSRlgQBEiCRlgAAiiiRlgSJpgCEwgyZ5hyRlgBymgSRlgQAehRFviSRlgBAliwizjiRlAQ6BJGUBDoIATYAFE4YkZYcn6ocDYIcoSocAFIYoJIgAFIAAPIUB84IE/YE4sYEBA4EIKgENgQAOgTvthQymgRKsAgN2gCGpgx33gAWWAWuBEa8BIoQMzAETgCOjgAh0gROzgA4MgAAsgEzkgBO4gQN2gQgzAQWCAciBDNSLG0yAAAcBBIEEfQFHgQT/hAa2gEMDgRMNgyTiAQaBVOKDFfQCQbmHEsUBFIAJFIMXJYIBXoA/q4ItF4ASxIIB6oIWqYAf3IAfsoEbpAENhAAKARiAAZ6AAAcBFIEBxAEFgQIDgAz/gAzZgAGWgCSHgRrrgB1sAwtLG4ES/oAAJoAKGYFE1JAY/4QXHoETKYQXyYUTLYEA9AFEhBMahBMogABdgFFygAC/AbqIEVsBRIYYMIEAxYEGtIEGqIQPpQFqgQPNAQOFAMeBH+eBRRoBHIFV44ICtgFEgAh4gAARASCBJK6DEjmBAHWBCDMCIAOCFQ+AF56CAkGBARgCSRuAAj6WGJ2GAMoBBYQAyoEAf4IT3IAOYoAAwoAhH4Ip2YQX+YEeS4Id3YAAxgG7kgDPgQ0BhQDPghUHlQDPASSNAM8BKOQAz4M2Z4kAz4EdCAJBvIkCXQEFgQH1ggTNhxongS8xoAhFgwCchQCRgALiAy8BHIFPNAMAQZqLCYGCF/OHGNCEGlsBQYA6dIAnNoAA8AEJgxuEgBJGjBz/jBi1gQRqgBRnggRoARSAAAiKCPqBQsShCPqBCKSBI66CA5IBIIFTEwMAQdCKBRWCAKWABemEF/iCALmDB6OAABsBFIEWxIEAqYMsSYEsWoFATaUQ6YQTp4EFYYE1BIAJX4FTlIMk4oEonoconQEIgQr2gAAQiSidggsPliidgABuATiBQ6WFKJ2DKMuNKJ2AAJsBLIEBu4IGL4AG0YEH2QEIgAWWhShQkCifgihCBDQiBmqAACcBCYAAJ4NYDYAAPIBVZIEh2wEIgAA4gRLxgiifgAAjgAUhgBAygCa0gSifgACWkyifgBAPgVXQgij8iyifgg9diyifgATcgyfYAQSBAYWEKK6ASmiFKKmCAM6VKKSFAqaHCs+BIV2AAKaDCrgBHIFZ6oMHB4EK1IEROwMIECiDJMqBAAsCKQuBLH+BAo6AAAeCKSyBBdq5KPMBBYAo8wEFgyjzAQWCAJUBG4FFgwIgHIYo8wEXgwJkgyjzAQuAKPSADMQBEIMo9AEXgyReAQeLJF4BJ8EkXgEKg0EyCA8QQAvyBgEFgQBcgQTNjiQogUBVhSQoAUGBQ/aAXRaAALUBBYEWiIEDwwFIgQUZgEOigylzARCBNXuBVy+BJqWAHJ6BBUkCEGuAQPaAXb2CThcCCEaBXG+BKX4CCEmBBA4CS3KAJB2AAPSFAukDQcgtgCV6gALhh0rxARyBI/KCAAeCPvOAAA4BKoIa9oQ+fwRC//+BghsZAVSAAAwHgICCgPABN4AJ1gIBQYEfvwIHG4FSHAEwgUB9gU7mgAAMASyCWrQBAYAIpQE0gwEYgSSUggE4gQNYgQNWhAAWgAFaASyJABmEAWOAABcBTIcAF4Fa44EAnQLELYNGpQFEgAAPAoCAgAC1AZyBABGCANOAAA8BQYIjVYIDuIJdC4JUaQKcLYAaGgECgAzDgCo0gABdgQHJgkbsgAJvhAAIAUSCBfyCRyoCQZqAB4KBQycBgIIVrAMAECGAJyOCQTKAAH0BiIAAUIEfAAGEgQGdgCDCASSDJHmAAn4BmIEAhoBOFQFsgBFvBDYCpC2BAeWAAD0BNYIB5IIBDYslW4MCU4MNY4IApYAAboBGsYEIY4AELIAB64EAcYI/D4IoKQUBQTlBKoEi7ANGIgKCVaiCVSGBAhGDBdmCJ9WDDZ2ABiWAAYaBAGYCvC2BQq6BAEkDOwG4gACgB0GIETYCuBaCAloB/IED0QGwgAAMAkH0gCi7AayDABUCiBOAABUBpIEAFQHggAAVAaCDABUBlIEHTwGYgQAVAX6BIoYDARArgwC9ggKsASyAFuqCJ/2BAawCAXSAGJCDWHsBRIBA4IMa4oE/doImi4NAi4EA8gK0LYABBoEmMQQgNwJ0gwERAWiHABIBXIMAJQFIgwSPBYQBQQxsgAEpA5QgaoAY6gM2ApCBKCgDAUGQhAAPAYyDAA8BkoQADwGAgwAPAZaEAA8BfIAFFoUDfwFxgAN/hAALAR+AAAuMJjYBCIAmNgL2JIAs9YElZYFS9AIQNYEl7IAu1wIAGoICNYEE24QDoAEcg1GVgFlegwQNg05bgQRigwSsAQSAAkMBR4AvEIEA7gGHgQcDhS1EgSByggSCgAKtggvNgAK+gAKEhwa9ghglAhA3ggAsgwqagAWYgwS0gAraASiDRKCBAGmAYJ+BAW4Bd4Mn4wJLG4ETV4QAEAcDQQRKG2pKgAC5gBO9mCXtAwRBKoJUhIEArYNIDYAH7gELgjUigAKFgxIhAfGCCB+DM8QDMEEMgCT2AfCBHImBB7ODALEBiIAAhwFKgwmFAoQBgQNlAUiABGMBwIELfQEDgBizgAAMgAOSAcCBAxgBBoAEyYMfCIBS9YAAKQIgcoMM7wFsgSjCAh9wgERgBUEfcxA9ggATghuoBAAvATKBABCBAAkDMBA9ggI6gwLggwi7ggCbggEtgQE4hAfuglwYAkE5g1W5hAMaggAvgwmVgR0zgQNwggB6gBkEAR+CEhKTABwBi4EgGJUAHYAD+oZQp4MmxZMAKIINkOwAHIMGC4QBkAEJgAHjAUGASoqDB0eCAa6BOfMCAkiEAY6RAEYBIIAWAJYAYoELUI4BfoEJ+IQCooAC6YAIbAEkgQ55gQMpgA/AgSKGgA9ugAQrgQ4qgQhxgQL6hA2CggBdggCygAZDggB9gAoXAkdBgQQwAwgbcoIAuAEDgAAIgmGWgAAIARCBC8gCG3KCAISAAF+CCk+FAE2DH+mADZqEAEmDAKqeACaCJn+DACkDLwEGoABPAi0AgRcEnAAmvQF9ggC3gklEnACOgloYgVgqgQ5voQEMmQAmiAEMgAk4AQuAAbOCHG2ABBuAA0OBChqBADeCA1KCIQ6HDb4BIIJe9YMDgYIEWwHFgCpHBgUCCQkJA4IYBgHbgDQPgAVoAkHngQ+ngl3FggIugiv8gwNFgwTxAwMvAYAKZIAHwIERqIEAbYEEaIFHuIIqLoELIgFqgBmhgwCMgDIogwDSgjU4ASCAAL+BGg2GInmAFTaCCrGCACMCLEWBBHgBT4QdPYcA0IAARIAA6QFrhQDTggBJhBWrhgLcgRkggQ+OgE/XhR5OgwLrg0R2kACJAQaFAIQBFIFT/4FJ04cAh4AApQFNkQCHgQC9hgFagQFSghddhg03gAA9ARyDBhEBFIIkHIEAE4QBI4AL14EA74JKSoQA6gEHjwBjgByggAAYhQBjhgU3ggH7gABKhA2QgSSigQAQhAIjASCEAiOAARSAENmCD4WBBcKEAjeGALuBAjSBEmKEBRKBAIWDBhOAAt6AAIyCCl2KAIqAABaPAO0B24IA7YYARIIvLeMA8AEktADwsQDuAeeJAdOBA1+BAMyEANiAGuaCIQKFAK2BF0aDTy4BMJcAiYYAHpoD04kHDoEAh40FwIEs/YIC1YI6JIIACoITMYIACoFTU4MACoMAjoIvLIAAOAF0gQs8gU1vgQP6gAhHgTfzhAhfgg32gQUFgwcdAwEQNoIz5YUI6IAFDAEChSNQAQKBCmGBF1+FAB2BAFcDAhA6iABiggN7gwIrgAo7gg/JgQm6gAAhAVyBCy0BToFoKIEPJAIDaoFAiIEADAFsgWH/AwEQL4MAJgFsgiGlgAaJAxA3QYAFgIIAC4ADrwEbgwDagABWAWCDAECBACuGAfeAAA0CoC2BTHmAAVECoC2BTB4BKIAL5YkHgLAAH4MBtIEVloEXxYAPsoAKp4AAJIELKIIANIAQeIAMPgF0hAC3gRKygkLkggBOgQAGAqQtgAD7gxmelgD/gRQ8gAHrjwD8hQD4gmUIggEnAqAtghH3ngFKmQBOgAI9gwFIgQHHgicRgyU2ggDPgEnKAoMCghjkhgFnAWyDKSGBAeICAUWHACUCSXGAEyCAPG6LACqBJQCBEb2BAJWAGlKDEi6JAgqCMaTAAgqBAviDARCELou4ARABB4QU8YAAsoATQoIUzoIA84AEkYAZuYAB4oIh6oIZcoISkoIhuYYACoBZIYE21AGCgR7zgAkagBAqiQACgAUMgB+BgBTJgSHsAQiDVfOAAAyBWVaDAAqBUv6DAAqAAyaBNgSAAAqAC+GBZ3yAAAqAJF+AYVmBAAqAVcSAE8eBHE+BIkGAF3iBGWKBF0UFA0H6AUmAGvuBInYBDYIU7oJDmIAZcYEEE4AmiYEACoAB8YAXzYEACoFRq4EgPwEJglGRgSA1giFXgDOIgQAKgRRagSY9gQERgAnjgBfygADYgAL4hD1JgQcdggHrgAMsgRnrAQOAOH6AMz2CIW+CAziCAzaAB0aCK6aGA1eDBOaAAB+CBOeOA3aOAB+BAFqACBuCBbiBHwAELQCQIYADgYAWIAJBhIEjPooDh4AytYIyDIMChoEVfgKIE4IAHAGIgCikggKwgirTgQOkgwzCgwOkhA3YAqAtgRj8gQHqhQRIjwDMmwCtngDMgQAfgjL3qARChACchQRDgSZjuwRDgCF/gQDxghD0BQxsQZgggGyWAQCAN8cBC4AE9AF+gB0jgzU8ghFLgQoBAX2AOmaBOHaCADwBBoE1IIYKAIAFJIAE1IUGHYALJYAKOoByxQIBAoJdSoABfwK4LYMDqQG8gBHGBHRyIgaCEMyBFFkDA0EOgTaelAtJAQaXDMaBFLoCuS2DDMqAEzWFAF0Ca3aEAF0DA0ENghNlgAI3AWqAANEBNoAAHoIAcQMEQQq/AHGDEYyCAHMCQQmCAGeAR04BaoARtYEAZQIQLoMT3YMHroATQYFWzoIClYURXoQcJYFRDYIsQIEmIIENJoIRXoECAIU3zIAFIIIACIABu4MsrIYQWoIAIoIH0IMQt4ECEIIFY4ISewRMDQMagwhWgQHcgWs2lQDVggOUhAAqlQAjhQiAgA/OmAAmggAjAy0AM50AI4AAC7sAI4cAjwEKnwCPg1TllgAjggaOg14JgC9gixCsgwMqARiBa2cBSoQTAAEAgAOXhGBjAkULgji9AfqBKukCQXuAAYQBAYk/bAIQIY06fQK/AYFTloMWkgE1ixaSgQ7bgmfzmBaZgRTgnAAgAUCcACCwFvkBfYISjAHxgBecAQuBVLcFARACCwmCE3ICbBCBdF6AACcBbYEXiQcQQQu9CQEVgTmuAUCACECCBuICBkGBPW2DDfqAZOyDQCCADVmCat4BdIET24EAB4AGMoAmVYUE/YAAGoAamYINoIJbooAbd4AllAN/IQ6BJfyBRLiCAEKBLxiBAECBAFOBB4qETXaAIP+BAASBUiyAF1OBTfgBCYIAgwJBEIMGzoIAPIAQroIAPIFAZYMHEIEm5IFLxIEN9Icv04MoLIQAWAEJgQAEA0sbIYA9uYAMcgEBgin9gD/6gRN6gQDMgT7RggC5ggBBgR5JgABNgQBlAWuACRUCAE6EbDmAAAuAAiCBALECR3KAHL6CNXuAAnwBO4AnUoMAUoAA7YAAroMBL4EAW4cBKQEigQlTgQBChwExgVz/ggEzgWUFgjAggAANgTIxhQFBAkETgUSkBCIVIRaEBZUDAA4CgAusgUGjDCESQe4IIRZBrgghFYEWcwF/gAARAvANgAARBLANIRWBG7UBDoAh7oBDXYFkPwIBRoFkxAECgG7tAyACG4BtrYAEZAMPdCKAB0wDayEXgxIXgC1jgkSwgASOgScigWL9A3QhGIAKQwF/gRHogEKOhADEgEjigBRYARqANlsCEkyERhEB4IJAxAEVgUkCgApAgQAmgEVAAwYgFoEHd4Aq8IAgMYEIbgMiDnSALKiALZOASkmCI1gCGiCAYmCAASgBGoAcqAEZgD7jggdFAwYgEIABS4AAPgEOgylIgRPeASCBKeaAAJGAAeoCa3SDAWSAHEsCAXaCBzeAbnGAATGHAhWGAoqAAbaENQOAcK+AQZqBVrIBCIF1AYAAywFqgC3gAQaCIv6BAn0BCYJBRoEBsoIgbwEMgwongkkmAwIgF4BBjYEd8oMBJYEAGAUgDyIKIYA7QYcAy4EEW4EAtoAc7oEAtoEVdoET/QEBggLXhQCygWXtgl2NgEHmghd9gwCYAQCCcUiAAJiCAqWDY9UCIBOBAFaDXwaAKEOBAmUBDoEJ8YAY74YBiYQAB4MJzgEXgGfXgACngUC8gHDBgSpcgANFgAAEAUuCKaEEIAwbIoBLxAEIgACyARiCAXoBEYEBTYEBkwQGdCEQhDM3gUvwASKBMgqAAdqCAU6CL9mCAv6AMnABSoFxhYAg/oICVoECT4ICIAMgE2qAAkQD0wZLgwJdgAC3BNEES3GBcUKCZJuBQzqDAdQBD4gBzQEGgTA1gFa/AXaBATIBB4Ax3YAD1IEAbIECNIMDroEDywEAgwMRgjCPglHvgwMfhwOVgQALgQAIgQM+hSrjAw4LK4ABX4IBy4AE3oQjg4EElYFnW4EAB4MbBIJaUQELgwT4A2BB1IIE+ALKA4J1T4RAV4FZywHVgRhOgRdCAdWABn+BdcOAAAmDCvuACgiBIRiDACKDT8WAEHeBKnGAAziBCmmANDWGN7mBDCWAG/+BAmiAADiACNYHQaCG4u1+c4ABCIEASIF1zoM0PoMFL4ELC4AJqQLATYk3RIAAaoEgSoNzEAFzgCRjgRyDgDH+AX+DArSCAOsDIANzgisDgXZRgAA+gRBtgAAqiQD3hQJjgABDgBi5lAAzgAKnAgh2gQAegALHiQAehwAZgALnkwAZgBtjkwAZgBDdkwAZgAc7kwAZgAMnkwAZgD+wigAZggDigCD4gh1khADiAwvCBYAHo4ABK4ED4IEb+YAIEoAdm4BvloEBB4ELDYAANYAA/4EDtwTx/wNrgRIkBEHw/wOAJHCCcpOACEKBenoDgIA8gAosgABfggAbAyAAcoEceIJ5BoEiRIQBeoMBWIYAUYFqsoNieIAAk4QB0YAAYwFwgABSgQeAgQBtgWccggBSgABQgAIvAtsCgSZUA0GwK4IusIAApIIOVYECcoMAToMADYE2toQAC4ENs4QACwEDhwALgAC3hQALgA4/hQALgRTyhAALgA7uhQALgQ1mhAALgEakhQALgA7IhQALgETLhQALgAQUhQALgEaThQALAQ6HAAsBD4EAC4FBPoEw44IDG4AlNoN4BYEA+YIafYIACYEBqQKwK4MBqgKwK4UCjYBl5YICzYAfQYUCzaQBU4YAWoEnrIQBz4EBMIID+YF07YQAC4FqFIQAC4ABMIUAC4F1yYQAC4FskoQAC4FqTYQAC4FwmoQAC4ABMIUAC4ABMIUAC4FDQYQAC4ABMIUAC4ABMIUAC4ABMIUAC4ABMIUAC4UBMIJmqoEBDAEQhAELgADHgjM1AnRygAFEAQuBSfWHCYiAEcTJCYqDWBiFAD+FCYeAELWICYaEal6BdDKCKCMEQcACNoEM45IAF4ADXAEMgRB9kAm7ggdbgDCmxAm7gClQgwm7ggDEgAm9gSRcoQm9gAhBgF++gRLVgWWZhAnAAw0CGoM/PJAJwYUBaMAJwwEUgAbbBQUiFCEVjAnDAoECgAk9CaAPIRVB4A4hFIIgNoEAEQEQgQARAQ+AOayAB2QBDJQJwQIEGoEAHQJ0IoBOxQFrgDYFhAnCAQyPCcIBFoQJwoAAgoAHn4QAxYAvcAFqgDKDARqAI5iCIrqBWFaDCcUBFIEAE4ATpIUJyAEOgAF4ARWJCcgED2siF4UJyAEPhQnIARaRCcgBDoMJyAEX1gnIgRIKgDc4iwnIgXq3iADrigkmARiGCSYBDI0JJoEwlwQPGyIPgwkmARaICSaAAPGACSaADLqECSaAA8GCCSaANKyYCSaICSQCEmqAAaYB1IYJJAMSQdCCCSQCBxqNCSUBDKEJJYABkYgJJYADN6oJJoEFcYE5tYIz/ocKtoIBpIQKtoYKhAEShAqEgRKCgCfzgAAtAwsLq4ASC4EHWoEWX4E15AMBQZ6CEl4BAIEiroN9h4IAFgEegwAVgCLYiAAVAROCBLOBB1KAAFmEIpCHBdaAATEDOwGUgHAigQ6yAbCBIpWAIooBqIAACIEAEAKgLYEXGpIAOZYAGQMLrwKCAK2BEAmBEkiBDxSAEloBBIASt4BApIAAEoEjtgEEgxK3gg9AgRn2gxBagiS4gBBaAQWCCkCTAByABvyDEkaCZsKEAF2AEreKErWBNfeDEk4CABCAAASDAEqHEMCDAEqCOTmVAByFESWVAB+AAvwBc4MVTpQAqIYeSYMQNIQoQIEP/AEQgD4jgwA1gHE5gURHAaeAE+qCSzWCAMyAJkqIARuBAViEcYWFAP8BuIQA/5UAIIIBH4MS14ASyZkAKoIASoIiVoMBmYEAgIJsZ4AB+4EBPIIUioE9A4EAOgTALQumhQCpgQHghACtgk4TvACthQCCglE2gQpZAUiCcVOeAFSBAD+HALqAComCAfQDCwuBgWv6gAZWgEQLhQX7giVFghKIgQw9ASKALsCAJ26BGCeDA1UHCUH/gP+ff4IMVQEFgH2vgiQVgQxugUXrgQLmgQc5ghXGgAU3gSUsgRuvggZlgniFgALqAQGBdC8DLwG8hAAIAciAAAgCQSCDDKWBDJKAABaBDGSBFxiCDGCBB1iCEYWFFkaBGDaELM+AGFmAOzWCLLWBARsFmBZqEDCCAAoBpIYACoAAtIEAyQScFhAxggAQgAQHgQAQAaiFABABsIMAKgJB/oAECgMGQRKDHFuBGK+BBneACvuBAWiADQkDLQDwgEWsgwDegwpFhDJMggF9gAQGgAAygBfcAwZBEYABhIEEFQYoAqwtQQqAIwOAXQCABPqAKoyAAAqBey+BABuAHNIBBIAPs4FFhIAFj4IeyIEa3oFSzgIES4QenoImbgIQLIEAgIIEIIMT54ACd4AZp4QAIYAVcYAW4oA5IAJyIoBKoJIEMY0CFYkDy5cCZYEJyoUCuIQEMQEBjwQxAkGggEVwAxoQMoICi4EmSoQAjYJ6+4YAh4QAmrkAj4QDQQENgS5ZgQCagACUggqThDq1hFA2gQCTgQHpgTGrAf6BOyqDAeiAAWODARcBDIQAkIEykocBMrgAmIMH2IkBKoIqdgELgytzgwBngAASAQSAArGAPHSDAKGAAIoBB4cAioAKE8IAioBBIpkAioIAZ4J6nYEAioMBKwQFQf3/gwElggEdAQ3NAR2RAR8BIoAKeYICSwEMggCZhwBvgwAYgCT9iACfgj9ohQOYhH77gAk/gwMdgAtFigOUgAqChwBInwMGAQejAMKBGe6PAL2IAwiJAK2GBA+BBHOAAJADCRAzhQRxgCrlAQiCAA6BINyATPwBAIArFYEZi4AHcwYLC6ELARKBDUgEIGsiD4AuWoJ5YYBloIIXpoINEYEYBYEl3YMq8wLQx4AIdgHQgksSgQAEAUqCh20DQdgogw7jAtwWgVnUAX+CIq+CbMOCbmWFgjsC0CiBcdWBKYKCEGmCf5+AAEuBNQuDPZiBMvSAAFiACfABSIFY8oJ934FGvoAfdoCGHYAI/4EAwwEEhBx1hAT6ghxCgQUBgX2UARuBDN+Cci6DBQKCE7WAOCWAACMCrC2CCQ2CCqWDCd4BCYABuYUBpAHQgC5jgAuahACQggpxhH5ehgBwgG+dgjAPggoUgQYIgQnjggF1gnbjgR/pgAZzggD2gAfPgwbAAtAoggARggDvgACEgABdgAAVAuAWghTmhAD3gknIAuAWgAARgA1yAhA0gwCPAdSAAI+CNV0B1IUAMoIfMYIAl4FzSo8AJoUAHoQBNIIdcYYA6gEFgQrpgAuchgD3gg2PghE+gSamgR/igQxiAQSCAAqAGkWBHu6AAN+EIf6BCwOAMQWDCwqAHwSIAK2ER9eJAdyEBpODAJyAAI6CAJyDAeGCAMqDDxYBvIACKYAwNYEaE4B22IECaAEJhgJ0ARCDgBUBCINfQwEEg1KRgkfVgjg8gApNggOGgjluhkiahhQigjWOgVs4gwCFgwFihQr/gDT4ggn3AdSAAK6AAJUGvARMGyESggKfggHPgR8CgDONgDWxgTLvhAA8g3bngANGgVYngFZZhEAbgUeogQA1gQcpAUyALucBIoIXl4GH94EUsYEFeAIgDIIM74IX9ose/YMVBAIgC4EEI4BMF4FaOIMAbINwYYMH0oAAaYAAfIABpgMQamyDB9WAN9iHAtqAIPCAFl6AAIaAAcSBACCDAuCBCDyBJeKBSw+AAHaCSMABAYIChIF4DoE1HYEAtYFAV4IO54EI1YAASIE+X4IQUoNMo4EBHIEArAECggIngmOYgQ5ngg/DA0ECSoAA3IAAB4I564AAP4EAYYEAmIQAcoEOTIIDBIIUAoM76YIw0IMBS4EBFIIOWIEBVYAf7oEBRoAVbIJL8IQA+IAAFIEIXQIFa4QA9oASC4UDcYUTFYEK7oAMxIIW0wMAQbqAAkyBAVOBEJ+FAiGCEMaBPlwCAEiBAsqCBJGCDWWDELCBaoGGAICBBQsBD4MCTYEwJ4IFz4YBqIKGJIEAfAJxcoEPi4F+XoAAKgFLgj5ygQPvhTvzAQaDhO2BR+eCAKCFDbYBD4AOaAEkgBXIgwBhgIrAgRyTgHLqgQOFgQARgAbqiQK+gYlbgAO2gANbhwDvBQu2AgEJgBd7gTztg41agQLOgAbdAjsBgEMMAUGAAkqABPcEQQdBioAzCAEbgQhvgg5XAQmABYeAVASBHhSFAQWBQfaBAZyAHYeBIVODEzSBA2aBEBeDjw2DBZeFAuCAMCSBNzeBDzcBS4EQfoAG2YA8koEn94AEEIMEWgEgggRcAQaDBFGCIIeCFj+CdQiLACWDAVOCAuCAC34BFYIADwK8FYNG6YETagEJgnkvgQAdAcCDAB0BwIEbtYMAEgHEgwASAcSAG7aAEWmAI68BQYAtpYCECgMiAxuFAPeAJSKAAy0BG4QBD4IBOALZCIABOIMGe4AlLIEAXoIKyYQO6YRQboEADYAi6oEV6YAVDIJ+SIEHwQIDL4AFCwEHghZzgwVaASKAA7+BFouCAJCBDsKCEtqEB6CBB/2AAY+ADRmAEkeANx2BMxKVDm+YDq6SCwIBBIAH/IIAXIEsFgFqgBUPgQyGgQALgwr4gAiHApAhgCWpgASkgTdNAy8BhoFNloUApoAAEAKECIA8B4MASwEGgACngExBgwikgABhgBduAQaIAKuDI/2AG/mEAI+CLd6UAMeIAKsBC4YAqwEGgACrgwBggYB4gQCrgjfqAQaACKqABjgCvC2BB30FQRxrQWyCPzGDDN2CfA8CkB6CViOCAJWAAA8DoBsigTyigwCbgQ2CgSNLgwEEuQFWjAoSgBCMgjy2gwFVgibzggBqhAAVAQuBB1qCD12CANOBAyeCR1KAXtmATBiADiuBCLIEgQJJG4ABgQEjgwGBgRhEgQImgQffgABFgQIigADhhwC8ggDgAQaAYdyIAXWHKwWqAiCHAXUBBYYCIIGEHoQAy4EAC4UKHwMKQQSBXyiACNeAAWkBH4EzEoBVpIABZQEcgAGwhQKrgADxggrCvwFlgQYkigFnkgCgjQBygQiHhACwgQljgBiJgBLpgQO3gUc8gALnAy8BgoGKO4EAN4AADAGAgXbKiACvg2HAiwN4tAFYgBEohwt0gwtygYycgwC2gQkjgxC6BbMLAQp/gwV0gQWYAiIHgDEmggWMgAAJgRCrgQWCgCHRiQV+gSCAgAxGgQWEgxc7g0nagQV6gxfpgUj4gwV4gAGrAUaBK4aCBY2DBXqBC0yCQZyBb0yBFX2AAGaCBM6CAZ2ABM6BFi6GBKOEAn2ASJWMA/KAA1elA/KNAByIASWAYOWOA/KOAn2ACqiBJiWFHk+BV9+HEE2GBYSBDpGCIFWAC8CCJ4eDRFuEAOaBCroBAoQB+IEGRIE/E4UB94Aeg44B9bICsoIkJIEEEIEAwIISNIEFGoBMeoUB84gP44KAZYEGv4MAioEq8YEBDAQvAb4VgHothgNOvgNGiwCUgnwkjACUgAYFgAAnggFkAQaDD0yBHScBD4RfAoEpgo0PSI0B0YkPSIECa4Ivrp4Dz4B7E4MoFIFUkYAFE4EGjoYAcYQAGoArdoEAGoJOwgEGgwfZggE3AcCOATcBwvoBNwH+hQE3hA+t4gE3gA/AkAEzg1K8ggEmAcSOASYBxvoBJgH2hQEmgipQ5AEmgyptjQEmgCp7gRkwgUaAhACgAQuCCgyALh2BPGuBBY+AGvqABYiACgyAAA+ALlyBBY8BCIQKEAL/AYCcDYMQroEJuoEQroGVtIUMnYBRMoAMGIFOZ4MNOYMOFoCaxoEAnYAO4AEEgAy7gkdXAQSAHS6CG0WAAWKABV+FAECCBLKBBKWChb2HDkCALxmDABgBDYNBZwENgSqmgAtIgQ9ughChgAAIgkHkgAuYgw1tgT8LiQBCggBjggBagXxpgQDtgQYJgQA/hA+/gX2FgQEpgg9ng4N8hA0rhQAVgCm+AwALg4EanoANJoKQHIQ8IIF6a4EACIVj8IApqYQ+Z4AAD4ArbYM+g4FA1AHbgBvEBAFBFk2AK+6BhJIGQYGggAJxgCfigQBNgzdEAwECAoCf14ENlAIqRoAABYAzZYFj4gMAQTmBLTSBBvmAAl8DC9wJggGGgZUMgEaYggIUASyBLCmABt+AdsaBAA+AAAOBJCGBK+2DH4yBHniCABmDklmEAsACQSqAFtUCdSKAfX2BAbWAAkiBABcBbIMK7QFcgCXQgAGIgX9BgQ97gASOgQBrgABkgWYhg1pvAU+AEmEBS4EW+IAGbAFFgEB5gIQEAnJygWhggizPhD0igIIIgG54gCzcgQK6ggLOgF9ngB1nhBYYhQATgAtJhhqJhwAWgZgHgCRMhBp+hwAYgB2ohjTrgy6pgEk9hISBgQEYgQAIATiCAMaBHKqBALcBCIFH64A3qYMBBIKR4YI3+oKMw4E3zIEv5YGM34E5WoIAGoGQq4EAQoIADYFV9YA4FYEBf4UZWIIcxIA1zAIQOIItQIcAEYIAVoIADYEHXoEAVoIADYUbA4KCTYIBY4FdDYFFzoEXbYKD4YOCUYEBhIICfIIH1IIuBIIB4oIzWYJAXYEcvIEA4YEhcIKZK4EA2YQAJYM/b4ED2wFsgwBDgAAXgj+wAWyBbOwBA4KdDoEJGoBEfIE0a4EASIEDw4FIyoFEuYAAEAGwgARGAUGDh+KCCUGBAHCCALCAAEKBAAcCtC2BRFeCB88BtIMAGYAAioISnIEAA4ENE4IBaYIAMoABPYEAk4AAaIMFRYICBwG0gQ2TgUsqgJYlARuClCKCAEiBALQBXIEFP4AAIwLELYEfAYIAEwLELYEAxgIGBIM0ZgEBgAMkgaNohAFCgTaegSIcgQKhgQGtgBp9hgD0hQE6gQAlggCygQLVggrNgEXVgCphgQBfgTpEhACggToagQHphAESgQ4ggwFZmAESgEvfhBO+AWyDA1SFARyCAYeCBo6EA3SAQD6DAPCCES2CAUiANoGABm+CAj+tASyQASSEAQGAClCAC7mEA8uCAwiFA+eBAQ6BkH+BA7eCAICBBDSABYsCSxuDIaCADBgBRYUDtAEGgGVbhJlwggFjg4csgwCoATiABTGCRWiDS0ABCIIh/IMwVwEagzHzgwGWARqCO4QBC4CbNIAAyYMDSoFGSIIBYYIvMYAS9AFBgF7IAQOBTOmAJ32CHXeAJKIBi4Eu/oEAJYBnnAIQLoRBKYNCZoBvQ4EaqIGYvoQFbII5TIAaUIUCcYAVC4IDf4IvyIAAGIAADYFIUIEENoIADYQD1YEagoOFXYIAXYFpZ4MAHII1mIIAFoFDoAMLC4SBHgeBADKAaCSCBEiBBP+CBAOAATuBA92CRS6CA4cCECaHHYGAOe0BGIEy2oM484IAc4BDpIAAJIFAzoQRlIUAE4Q6s4QARoAApIQH9oAEuIAADYFKfQULkAkBD4EHd4EhAoEZU4Edx4CXKYWBgYEALgN0QYWCXkABAIE3aIIAEYACswKGAoI9BIMwt4M59oE1c4QAbgFUiAPUATiABwSCAe+AQ4eBVVoBc4CEsYJDlIAwLIMCrgE0gB8bgxaCgFRvgxTkgQdQgAlMggNHghK+hAGVASyAAHmBSOACA2uBB22BAAIDAxA7gjX8ggD7gjVyg5FkAQODn5+AABOANPyDA1qBNLaBABGBNPyCAxaAAAUBcIAErYYJDpIAKoCLYYcgxZIAIoI2FIIGdoGIqIY2FICFnYE2FIQVsIMlZoFzY4FV7oFhUYEOf4QQrIFIioAX1gKQI4EIMIINXIoANoIAe4BE34JpBoIEVoIADQKkLYEUUYEAlYFJIIABgIMD3QKAAYUeJ4IV4IARKQFgggGIgR0QggEkAUiDB7EBbIMEXwE0gBflgQGMgDepgQGCg0nFAVSAUcGBAa6BLWGBAEmCAPaDYHyBAZQBC4QJHwMQdHOAUkqBDk4BSIJyGwEMgwHKgiPngxXCghgBgAGwgwDHgylhgQCRgilmgjU2hABXgHBzgDhmggt+gzcxhwS6hAB3ggQhgAAPgVhzhAJDgwJsgVi4gwGOgQJegQAZggBNggsyggA1gQBJhDdGlgHGiBq4sAAfgwvcgVaKlAG9hDdMgwDVhwFMgjdLggHLgp/mhAe3hATVgaZBgTdQggDEAQKDN1CBBBuCN1CDAEqIBPWBAAeDO5OCniKDSO+BBjyAAWQBT4BH6YY65oIZhYQAYoJtl4QAYgEBhDqagZs6gTrnjQBigjrnhABmARuDRocCoC2DOpShAFOZALWBRveBSoKBht4CvgWAEb6CA+yAC7WAA+6DCneAiVeDFg8BPIMC5YAEXQFqgRjmggAdASyFoV+BB2CBEbKBmdiAEU+FBbsBcIAKYoFii4QCU4AKb4MIoYIAsYIAHAFcgwSKArQtgj83iAiAAUSBAAUBTIEeCYAMeIMLEIIAioABVYIKtYMWaYF1f4FEWQQgCE8bhCXIgAuPhAmMgk9KggA+AQOCGOelADuAEXWADduECHSAS1yCR1eBAlCDBYWDAWICBGqABzIBEIIC44EXB4ACZIMAMIEH3YGgiYAFlYQCg4EIeoIA/4EImIAed4IcWYcDRoENGYEDSIIEGwFYgBaOgAWogC+2gFTsgRAygR9igAB+g3FagkDRgACGgAAkgCj5gwAmggDogAAFgBkciAXOggE3ASKAVgqCBAeAGTyDAxGCGuuCAWSEHaqCHO+DXFmBL+MBhYEACoQCHIFAI4UJeIMJdQHEgAOAgiMsgyVAggEJgCNfgAQDgWQKAYKCLX2CAWGAAAyBDEiACHuADCqFTlaBApWBKoeCOOaBFD+DJS2BPE2AAA6CqcKBCd+BGXKCCeaECBWBMV+FAEGBSpCFSoWBAI+ACuSAAEOBFH2ACS0DC68EgB+0gQAZAXyBGVyAKQWBAAwBeIMBfQKMAYUNRwFshAt7AWuAAuOBGdWBAVgBA4Bl8YIFjAGQgJlBggDbgAGVgAxggAA0ggWcATiAHOaABQCBFtkBaoAFoAEHgj3agSsbgRbbgQTfg1v4gQAKggCaATSAHZ6BAZiDHUaBCuKAYcSBDAuDAC8CIAqBCJKEADICIAuCCJ+BAAqBXhGEAA2AA0qDPlGBPj+DEjyIajmGPkaAAICCAC2BBYmBPheAAA2AB7iCPkyAARyBMVyAAA2AOn+ADByBMVCAAA2ACdOAAFCBMUSAAA2APlWAAa6BMTiAAA2APliAAYGBMSyAAA2CFHaBBVaBB0iAEBiCD1aALtSBPl6AB5iBINiDPmWAPVGAAKGAir6CPmWBEIyDiayAY1eBAAqCQFaAHf0BBoNGMoARRQEGg6Vdgl81ghzAgADbghTdggKRgl7AgHHzgQJDgQ6jAQWDKAKAAuqASmABIIIjEIEZIoKdrYM9oIAC3IArXYMBe4AAG4FXcQESgAFwARGCAw2BA+oBAYELvoEsPAIiCYEC0oEZW4EABAVJGwu4C4EcQoMJg4EqQoEJg4RiuZIJgwFFgwIbgQmEgEDrgAFhgEM5ggtEkQmDggJIkAmDgAQqhAO1ggAZiQmDgx1tgQe8gwmDgAG2hRwcgQiBgAd6AXiEBVeAaSCCSXKCDjoBYIEcXoUAUAGAggDvgQLhggmxggR4iwm0gAP/AWCBJP+EA+qBSNSDKDCAAiiAPKyDFzuECaMDQYEggQDZiABsggLgAXiCDzWBCPiAAm6FZNCAABiAB6GDE1+DB1wBdIJZEYAACYUJ+IAQZYAABwFkgA/+gAHciQfXiENlhAAvhhALlgAigACAkQn9gBdwjgn9gR1ztAn9AXiBHfiCBTSEAXyAP5eAB6aAAIyANXGBCmqCWd6BAN2DBqWAChuCAOWAChsBCoMfJYIBE4MOBYAEAoQdz4QCJ4EJV4I1AokCIoAMppUF14JtpAIiCIQF14AEpIQCIIUF2AJ4IIKTC4QCF4IJ0IBPloEJHYKn2oAHgoEEfIECtYEABIR3xIZAP4QAkYIIOoFa0psI74KpJoAACgFohQWeggYOhAUHgRidjAIRhQIKiwnRrQAfgxJlgSBojwGwhwnUgwlthACFkgDghAMZkgDjhANygQouhgiuhgpIhgD+AQSCpeCDAWGUAC6ABKiCrdH/ASWHASWCAhSICqeBEEGOCqeGAhqQClSBB+WsCqeKAm2VAFOgCqeBBHaAk0wDAAs/gg/CgQAejxdIhkAhlAAfgAAcglJFBARAED+AAZ6AtXUCCxuAAA+HeJGACHGBLnwBSIB4CwQQGwtDgxYdh1XukRYdggogghO6ggfBgRIcgRPEgAcggXXxBQsL4x0LgVSNBAuhBGmAtDcFZmZpY2mAs7wBIIO1sBMAMS4zLjEuMS1tb3RsZXkAaW52gLREFWQgbGl0ZXJhbC9sZW5ndGhzIHNldIYAHAVjb2RlIIkAGQ91bmtub3duIGhlYWRlciCAtKoBZ4sAMgJkaYC0TgFugLTgigAWA2JpdIQARxAgcmVwZWF0AHRvbyBtYW55hQAXB3N5bWJvbHOOABgCb3KGAFOGACSFAFaCtMuAAF2AtRcBa4UApgIAYoAA+IAAmgxlcnJvcgBzdHJlYW2EAA2KANULLS0gbWlzc2luZyCAtX4ELW9mLYIAR4AAJQJjb4C1BAJjdIUA4wNjaGWKABeEAJiNABcEZGF0YYYAFYsBCwEggQDUBWZhciBigLVnAQCFAFcCcmOBAIEFbWF0Y2iGADIBd4C1ywRvdyBzgbXahgE7ggDeA3R5cIcAE4sBsoIA0I8AdYIAFoUBrwRjb21wgLX7AXOAtcCAAg4EdGhvZIAu/RMMC6UCAwAEAAUABgAHAAgACQAKgCXVDQ0ADwARABMAFwAbAB+Alj0VKwAzADsAQwBTAGMAcwCDAKMAwwDjgbhQggABAYCMAAIBgYQAAgGChAACAYOEAAIBhIQAAgGFhAACBZAASQDIghWNgK4cggCEAQeAAIABDYAAegEZgCX3ATGABD8BYYAARgHBgEXeAYGBReCAPP8EAQYBCIAl1gMQARiAAzcJMAFAAWABgAHAiQB4hQBwhQBoAYaAAAIBh4AAAgGIgAACAYmAAAIBioAAAgGLgAACAYyAAAIBjYAAAgGOgAACARCAAHIBEoAAiAEIggCAAQaAAQIBBYABBAMEAAyAAJaAGV0CAA6AAKIBD4CxBgQOC7cMtQEsgBmWggABARCMAAIBEYQAAgEShAACAROEAAIBFIQAAgEVhAACARDAASyJAICFAHSFAGyBAGQBFoAAAgEXgAACARiAAAIBGYAAAgEagAACARuAAAIBHIAAAgEdgAACAUCAAAIGoAgAAKANgACIgADQAR6AAAQBD4AAVAEggAAQAiAOgwDgAR6AAASBABSBAAEBoIQAFAETgAAEAQeEABQBDIABOAGMgAAEAUyAAAQBzIAABAEsgAAEAayAAAQBbIAABAHsgAAEARyAAAQBnIAABAFcgAAEAdyAAAQBPIAABAG8gAAEAXyAAAQB/IAABAECgAAEAYKAAAQBQoAABAHCgAAEASKAAAQBooAABAFigAAEAeKAAAQBEoAABAGSgAAEAVKAAAQB0oAABAEygAAEAbKAAAQBcoAABAHygAAEAQqAAAQBioAABAFKgAAEAcqAAAQBKoAABAGqgAAEAWqAAAQB6oAABAEagAAEAZqAAAQBWoAABAHagAAEgHp2AgC6gAAEAXqAAAQB+oAABAEGgAAEAYaAAAQBRoAABAHGgAAEASaAAAQBpoAABAFmgAAEAeaAAAQBFoAABAGWgAAEAVaAAAQB1oAABAE2gAAEAbaAAAQBdoAABAH2gAAEAQ6AAAQBjoAABAFOgAAEAc6AAAQBLoAABAGugAAEAW6AAAQB7oAABAEegAAEAZ6AAAQBXoAABAHegAAEAT6AAAQBvoAABAF+gAAEAf6AAAQBAYAABAGBgAAEAUGAAAQBwYAABAEhgAAEAaGAAAQBYYAABAHhgAAEARGAAAQBkYAABAFRgAAEAdGAAAQBMYAABAGxgAAEAXGAAAQB8YAABAEJgAAEAYmAAAQBSYAABAHJgAAEASmAAAQBqYAABAFpgAAEAemAAAQBGYAABAGZgAAEAVmAAAQB2YAABAE5gAAEAbmAAAQBeYAABAH5gAAEAQWAAAQBhYAABAFFgAAEAcWAAAQBJYAABAGlgAAEAWWAAAQB5YAABAEVgAAEAZWAAAQBVYAABAHVgAAEATWAAAQBtYAABAF1gAAEAfWAAAQBDYAABAGNgAAEAU2AAAQBzYAABIAN6AIArYAABAFtgAAEAe2AAAQBHYAABAGdgAAEAV2AAAQB3YAABAE9gAAEAb2AAAQBfYAABAH9gAAEAROAAMIFEwEJAJOAAAgBk4AACAFTgAAIAVOAAAgB04AACAHTgAAIATOAAAgBM4AACAGzgAAIAbOAAAgBc4AACAFzgAAIAfOAAAgB84AACAELgAAIgA2LgAQCgAAEgAAIAUuAAAgBS4AACAHLgAAIAcuAAAgBK4AACAErgAAIAauAAAgBq4AACAFrgAAIAWuAAAgB64AACAHrgAAIARuAAAgBG4AACAGbgAAIAZuAAAgBW4AACAFbgAAIAduAAAgB24AACAE7gAAIATuAAAgBu4AACAG7gAAIAXuAAAgBe4AACAH7gAAIAfuAAAiBA7YBB4AACAGHgAAIAYeAAAgBR4AACAFHgAAIAceAAAgBx4AACAEngAAIASeAAAgBp4AACAGngAAIAWeAAAgBZ4AACAHngAAIAeeAAAgBF4AACAEXgAAIAZeAAAgBl4AACAFXgAAIAVeAAAgB14AACAHXgAAIATeAAAgBN4AACAG3gAAIAbeAAAgBd4AACAF3gAAIAfeAAAgB94AACAEPgAAIAQ+AAAgBj4AACAGPgAAIAU+AAAgBT4AACAHPgAAIAc+AAAgBL4AACAEvgAAIAa+AAAgBr4AACAFvgAAIAW+AAAgB74AACAHvgAAIAR+AAAgBH4AACAGfgAAIAZ+AAAgBX4AACAFfgAAIAd+AAAgB34AACAE/gAAIAT+AAAgBv4AACAG/gAAIAX+AAAgBf4AACAH/gAAIAf+AAAiBBAoBQIAABAEggAAEAWCAAAQBEIAABAFQgAAEATCAAAQBcIIFVgMHAEiAAAQBKIAABAFogAAEARiAAAQBWIAABAE4gAAEAXiAAAQBBIAABAFEgAAEASSAAAQBZIAABAEUgAAEAVSAAAQBNIAABAF0gAAEAQOAAEIBg4AABAFDgAAEAcOAAAQBI4AABAGjgAAEAWOAAAQB44AABIC/A4AAdIECxgEFgABcAQWCBUoBFIAABAEMgAAEARyAAAQBAoAABAESgAAEgQYEARqCBeoBBYAD1AEFgAO4AQWAA5yATGqAAAQBEYAABAEJgAAEARmAAASBAAIBFYAABAENgAAEAR2AAASAv26AAqSBBkABBYACLIEFpgEFgAG0AQWAOroDGwtNgxx6hwAEAQKMAASBB1GJAAQBBIwABAEFigAEBEGwHAuAveGLAEuNADuFAC8BBoQABIEFiIEABIEBCoEABIEBkoEABICFfIIABAELhAAEAQyEAASABduBRGIE4B0LI4UAX4UFywIQEYAFbQYHCQYKBQuAN44EDQIOAYAHJQSUHgtphQCQhQCIhQCAhQB4gQBogQBcgQYfARCAAAQBFIAABAEYgAAEARyAAAQBIIAABAEogAAEATCAAAQBOIAABAFAgAAEAVCAAASBBr0BcIAABAGAgAAEAaCAAAQBwIAABAHggABvAx8Lco0Ab4EAa4EAZ4EAY4EAX4EAW4EAV4EAU4EAT4EAS4EAR4EAQ4EBPAGArwBBgE7BAgttgQDHAQSAAAIBCIAABIEBM4ECSwEQgAAOgwAMgZ97gKs6hAAkgQdzgQBPAQiAAAiBABiFAAyBCLeDAAwBIIEAlIAvUoEAawGAgQgvAQSDAAyAPCIKAQAQDABBkSEL/4Ah4AEDgpzlBQgJCQoKgEYggAABAQ2AAAEBDoAAAQEPgAABARCEAAEBEYQAAQEShAABAROEAAEBFIwAAQEVjAABARaMAAEBF4wAAQEYnAABARmcAAEBGpwAAQEbmwABARyBfrkEBAQFBYHCrAEHgAABAQiEAAGAWjqCAAEBCowAAYAkc4oAAYEBMJkAAYEBTJkAAYEBaLkAAYEBpLkAAYIDdYABzoUBvI0BqJ0BkLwBgAIbHLwAAQEdvAABgLyTgH3yA9AqAQ==")),B)});}
|
|
5980
6516
|
|
|
5981
6517
|
/*
|
|
5982
6518
|
Copyright (c) 2025 Gildas Lormeau. All rights reserved.
|
|
@@ -6026,46 +6562,54 @@ function _make(isCompress, type, options = {}) {
|
|
|
6026
6562
|
|
|
6027
6563
|
return new TransformStream({
|
|
6028
6564
|
start() {
|
|
6029
|
-
|
|
6030
|
-
|
|
6031
|
-
|
|
6032
|
-
|
|
6033
|
-
|
|
6034
|
-
|
|
6035
|
-
|
|
6036
|
-
this._last_consumed = wasm.deflate_last_consumed;
|
|
6037
|
-
this._end = wasm.deflate_end;
|
|
6038
|
-
this.streamHandle = wasm.deflate_new();
|
|
6039
|
-
if (type === "gzip") {
|
|
6040
|
-
result = wasm.deflate_init_gzip(this.streamHandle, level);
|
|
6041
|
-
} else if (type === "deflate-raw") {
|
|
6042
|
-
result = wasm.deflate_init_raw(this.streamHandle, level);
|
|
6043
|
-
} else {
|
|
6044
|
-
result = wasm.deflate_init(this.streamHandle, level);
|
|
6565
|
+
try {
|
|
6566
|
+
let result;
|
|
6567
|
+
this.out = malloc(outBufferSize);
|
|
6568
|
+
this.in = malloc(inBufferSize);
|
|
6569
|
+
this.inBufferSize = inBufferSize;
|
|
6570
|
+
if (!this.out || !this.in) {
|
|
6571
|
+
throw new Error("allocation failed");
|
|
6045
6572
|
}
|
|
6046
|
-
|
|
6047
|
-
if (
|
|
6048
|
-
this._process = wasm.
|
|
6049
|
-
this._last_consumed = wasm.
|
|
6050
|
-
this._end = wasm.
|
|
6051
|
-
this.streamHandle = wasm.
|
|
6052
|
-
|
|
6573
|
+
this._scratch = new Uint8Array(outBufferSize);
|
|
6574
|
+
if (isCompress) {
|
|
6575
|
+
this._process = wasm.deflate_process;
|
|
6576
|
+
this._last_consumed = wasm.deflate_last_consumed;
|
|
6577
|
+
this._end = wasm.deflate_end;
|
|
6578
|
+
this.streamHandle = wasm.deflate_new();
|
|
6579
|
+
if (type === "gzip") {
|
|
6580
|
+
result = wasm.deflate_init_gzip(this.streamHandle, level);
|
|
6581
|
+
} else if (type === "deflate-raw") {
|
|
6582
|
+
result = wasm.deflate_init_raw(this.streamHandle, level);
|
|
6583
|
+
} else {
|
|
6584
|
+
result = wasm.deflate_init(this.streamHandle, level);
|
|
6585
|
+
}
|
|
6053
6586
|
} else {
|
|
6054
|
-
|
|
6055
|
-
|
|
6056
|
-
|
|
6057
|
-
|
|
6058
|
-
|
|
6059
|
-
result = wasm.
|
|
6060
|
-
} else if (type === "gzip") {
|
|
6061
|
-
result = wasm.inflate_init_gzip(this.streamHandle);
|
|
6587
|
+
if (type === "deflate64-raw") {
|
|
6588
|
+
this._process = wasm.inflate9_process;
|
|
6589
|
+
this._last_consumed = wasm.inflate9_last_consumed;
|
|
6590
|
+
this._end = wasm.inflate9_end;
|
|
6591
|
+
this.streamHandle = wasm.inflate9_new();
|
|
6592
|
+
result = wasm.inflate9_init_raw(this.streamHandle);
|
|
6062
6593
|
} else {
|
|
6063
|
-
|
|
6594
|
+
this._process = wasm.inflate_process;
|
|
6595
|
+
this._last_consumed = wasm.inflate_last_consumed;
|
|
6596
|
+
this._end = wasm.inflate_end;
|
|
6597
|
+
this.streamHandle = wasm.inflate_new();
|
|
6598
|
+
if (type === "deflate-raw") {
|
|
6599
|
+
result = wasm.inflate_init_raw(this.streamHandle);
|
|
6600
|
+
} else if (type === "gzip") {
|
|
6601
|
+
result = wasm.inflate_init_gzip(this.streamHandle);
|
|
6602
|
+
} else {
|
|
6603
|
+
result = wasm.inflate_init(this.streamHandle);
|
|
6604
|
+
}
|
|
6064
6605
|
}
|
|
6065
6606
|
}
|
|
6066
|
-
|
|
6067
|
-
|
|
6068
|
-
|
|
6607
|
+
if (result !== 0) {
|
|
6608
|
+
throw new Error("init failed:" + result);
|
|
6609
|
+
}
|
|
6610
|
+
} catch (error) {
|
|
6611
|
+
disposeStream(this);
|
|
6612
|
+
throw error;
|
|
6069
6613
|
}
|
|
6070
6614
|
},
|
|
6071
6615
|
transform(chunk, controller) {
|
|
@@ -6082,9 +6626,13 @@ function _make(isCompress, type, options = {}) {
|
|
|
6082
6626
|
if (!this.in || this.inBufferSize < toRead) {
|
|
6083
6627
|
if (this.in && free) {
|
|
6084
6628
|
free(this.in);
|
|
6629
|
+
this.in = 0;
|
|
6085
6630
|
}
|
|
6086
6631
|
this.in = malloc(toRead);
|
|
6087
6632
|
this.inBufferSize = toRead;
|
|
6633
|
+
if (!this.in) {
|
|
6634
|
+
throw new Error("allocation failed");
|
|
6635
|
+
}
|
|
6088
6636
|
}
|
|
6089
6637
|
heap.set(buffer.subarray(offset, offset + toRead), this.in);
|
|
6090
6638
|
const result = process(this.streamHandle, this.in, toRead, out, outBufferSize, 0);
|
|
@@ -6107,15 +6655,7 @@ function _make(isCompress, type, options = {}) {
|
|
|
6107
6655
|
offset += consumed;
|
|
6108
6656
|
}
|
|
6109
6657
|
} catch (error) {
|
|
6110
|
-
|
|
6111
|
-
this._end(this.streamHandle);
|
|
6112
|
-
}
|
|
6113
|
-
if (this.in && free) {
|
|
6114
|
-
free(this.in);
|
|
6115
|
-
}
|
|
6116
|
-
if (this.out && free) {
|
|
6117
|
-
free(this.out);
|
|
6118
|
-
}
|
|
6658
|
+
disposeStream(this);
|
|
6119
6659
|
controller.error(error);
|
|
6120
6660
|
}
|
|
6121
6661
|
},
|
|
@@ -6146,21 +6686,35 @@ function _make(isCompress, type, options = {}) {
|
|
|
6146
6686
|
} catch (error) {
|
|
6147
6687
|
controller.error(error);
|
|
6148
6688
|
} finally {
|
|
6149
|
-
|
|
6150
|
-
|
|
6151
|
-
|
|
6152
|
-
controller.error(new Error("end error:" + result));
|
|
6153
|
-
}
|
|
6154
|
-
}
|
|
6155
|
-
if (this.in && free) {
|
|
6156
|
-
free(this.in);
|
|
6157
|
-
}
|
|
6158
|
-
if (this.out && free) {
|
|
6159
|
-
free(this.out);
|
|
6689
|
+
const result = disposeStream(this);
|
|
6690
|
+
if (result !== 0) {
|
|
6691
|
+
controller.error(new Error("end error:" + result));
|
|
6160
6692
|
}
|
|
6161
6693
|
}
|
|
6694
|
+
},
|
|
6695
|
+
cancel() {
|
|
6696
|
+
// release the stream handle and buffers when the pipeline is aborted,
|
|
6697
|
+
// they would be leaked in the process-lifetime wasm heap otherwise
|
|
6698
|
+
disposeStream(this);
|
|
6162
6699
|
}
|
|
6163
6700
|
});
|
|
6701
|
+
|
|
6702
|
+
function disposeStream(state) {
|
|
6703
|
+
let endResult = 0;
|
|
6704
|
+
if (state.streamHandle && state._end) {
|
|
6705
|
+
endResult = state._end(state.streamHandle);
|
|
6706
|
+
}
|
|
6707
|
+
state.streamHandle = 0;
|
|
6708
|
+
if (state.in && free) {
|
|
6709
|
+
free(state.in);
|
|
6710
|
+
}
|
|
6711
|
+
state.in = 0;
|
|
6712
|
+
if (state.out && free) {
|
|
6713
|
+
free(state.out);
|
|
6714
|
+
}
|
|
6715
|
+
state.out = 0;
|
|
6716
|
+
return endResult;
|
|
6717
|
+
}
|
|
6164
6718
|
}
|
|
6165
6719
|
|
|
6166
6720
|
class CompressionStreamZlib {
|
|
@@ -6173,6 +6727,11 @@ class DecompressionStreamZlib {
|
|
|
6173
6727
|
return _make(false, type, options);
|
|
6174
6728
|
}
|
|
6175
6729
|
}
|
|
6730
|
+
// These codecs are backed by the WASM module; they are unusable until setWasmExports() has run.
|
|
6731
|
+
// The worker uses this flag to know it must fall back to the native CompressionStream when the
|
|
6732
|
+
// module fails to load, rather than discarding a self-contained codec supplied through config.
|
|
6733
|
+
CompressionStreamZlib.requiresModule = true;
|
|
6734
|
+
DecompressionStreamZlib.requiresModule = true;
|
|
6176
6735
|
|
|
6177
6736
|
/*
|
|
6178
6737
|
Copyright (c) 2025 Gildas Lormeau. All rights reserved.
|
|
@@ -6330,12 +6889,15 @@ function terminateWorkersAndModule() {
|
|
|
6330
6889
|
*/
|
|
6331
6890
|
|
|
6332
6891
|
|
|
6892
|
+
const ERR_ENTRY_EXISTS = "Entry filename already exists";
|
|
6893
|
+
const ERR_READABLE_CONSUMED = "Readable stream already consumed";
|
|
6894
|
+
|
|
6333
6895
|
class ZipEntry {
|
|
6334
6896
|
|
|
6335
6897
|
constructor(fs, name, params, parent) {
|
|
6336
6898
|
const zipEntry = this;
|
|
6337
6899
|
if (fs.root && parent && parent.getChildByName(name)) {
|
|
6338
|
-
throw new Error(
|
|
6900
|
+
throw new Error(ERR_ENTRY_EXISTS);
|
|
6339
6901
|
}
|
|
6340
6902
|
if (!params) {
|
|
6341
6903
|
params = {};
|
|
@@ -6345,13 +6907,17 @@ class ZipEntry {
|
|
|
6345
6907
|
name,
|
|
6346
6908
|
data: params.data,
|
|
6347
6909
|
options: params.options,
|
|
6348
|
-
id: fs.
|
|
6910
|
+
id: fs.entryIdCounter++,
|
|
6349
6911
|
parent,
|
|
6350
6912
|
children: [],
|
|
6351
6913
|
uncompressedSize: params.uncompressedSize || 0,
|
|
6352
6914
|
passThrough: params.passThrough
|
|
6353
6915
|
});
|
|
6354
|
-
|
|
6916
|
+
// detached entries (e.g. clones) are not registered until they are attached,
|
|
6917
|
+
// otherwise they could never be garbage collected
|
|
6918
|
+
if (parent || !fs.root) {
|
|
6919
|
+
fs.entries[zipEntry.id] = zipEntry;
|
|
6920
|
+
}
|
|
6355
6921
|
if (parent) {
|
|
6356
6922
|
zipEntry.parent.children.push(zipEntry);
|
|
6357
6923
|
}
|
|
@@ -6389,7 +6955,7 @@ class ZipEntry {
|
|
|
6389
6955
|
rename(name) {
|
|
6390
6956
|
const parent = this.parent;
|
|
6391
6957
|
if (parent && parent.getChildByName(name)) {
|
|
6392
|
-
throw new Error(
|
|
6958
|
+
throw new Error(ERR_ENTRY_EXISTS);
|
|
6393
6959
|
} else {
|
|
6394
6960
|
this.name = name;
|
|
6395
6961
|
}
|
|
@@ -6428,16 +6994,17 @@ class ZipFileEntry extends ZipEntry {
|
|
|
6428
6994
|
}
|
|
6429
6995
|
|
|
6430
6996
|
isPasswordProtected() {
|
|
6431
|
-
return this.data.encrypted;
|
|
6997
|
+
return Boolean(this.data && this.data.encrypted);
|
|
6432
6998
|
}
|
|
6433
6999
|
|
|
6434
7000
|
async checkPassword(password, options = {}) {
|
|
6435
7001
|
const zipEntry = this;
|
|
6436
7002
|
if (zipEntry.isPasswordProtected()) {
|
|
6437
|
-
options.password = password;
|
|
6438
|
-
options.checkPasswordOnly = true;
|
|
6439
7003
|
try {
|
|
6440
|
-
await zipEntry.data.getData(null, options
|
|
7004
|
+
await zipEntry.data.getData(null, Object.assign({}, options, {
|
|
7005
|
+
password,
|
|
7006
|
+
checkPasswordOnly: true
|
|
7007
|
+
}));
|
|
6441
7008
|
return true;
|
|
6442
7009
|
} catch (error) {
|
|
6443
7010
|
if (error.message == ERR_INVALID_PASSWORD) {
|
|
@@ -6471,8 +7038,15 @@ class ZipFileEntry extends ZipEntry {
|
|
|
6471
7038
|
return this.getData({ writable }, options);
|
|
6472
7039
|
}
|
|
6473
7040
|
|
|
6474
|
-
getArrayBuffer(options) {
|
|
6475
|
-
|
|
7041
|
+
async getArrayBuffer(options) {
|
|
7042
|
+
// this.data may be a string, a Uint8Array, a data URI or a Blob depending on how the entry
|
|
7043
|
+
// was created, so retrieve the bytes through getUint8Array rather than assuming a Blob; this
|
|
7044
|
+
// also applies the options (password, signal, onprogress...) like the other getData() getters
|
|
7045
|
+
const array = await this.getUint8Array(options);
|
|
7046
|
+
// return the backing buffer directly when the array spans it, slicing the exact bytes otherwise
|
|
7047
|
+
return array.byteOffset || array.byteLength != array.buffer.byteLength
|
|
7048
|
+
? array.buffer.slice(array.byteOffset, array.byteOffset + array.byteLength)
|
|
7049
|
+
: array.buffer;
|
|
6476
7050
|
}
|
|
6477
7051
|
|
|
6478
7052
|
replaceBlob(blob) {
|
|
@@ -6514,7 +7088,7 @@ class ZipFileEntry extends ZipEntry {
|
|
|
6514
7088
|
replaceReadable(readable) {
|
|
6515
7089
|
Object.assign(this, {
|
|
6516
7090
|
data: null,
|
|
6517
|
-
Reader:
|
|
7091
|
+
Reader: getReadableReader(readable),
|
|
6518
7092
|
Writer: null,
|
|
6519
7093
|
reader: null
|
|
6520
7094
|
});
|
|
@@ -6530,7 +7104,7 @@ class ZipDirectoryEntry extends ZipEntry {
|
|
|
6530
7104
|
|
|
6531
7105
|
clone(deepClone) {
|
|
6532
7106
|
const zipEntry = this;
|
|
6533
|
-
const clonedEntry = new ZipDirectoryEntry(zipEntry.fs, zipEntry.name);
|
|
7107
|
+
const clonedEntry = new ZipDirectoryEntry(zipEntry.fs, zipEntry.name, zipEntry);
|
|
6534
7108
|
if (deepClone) {
|
|
6535
7109
|
clonedEntry.children = zipEntry.children.map(child => {
|
|
6536
7110
|
const childClone = child.clone(deepClone);
|
|
@@ -6604,7 +7178,7 @@ class ZipDirectoryEntry extends ZipEntry {
|
|
|
6604
7178
|
|
|
6605
7179
|
addReadable(name, readable, options = {}) {
|
|
6606
7180
|
return addChild(this, name, {
|
|
6607
|
-
Reader:
|
|
7181
|
+
Reader: getReadableReader(readable),
|
|
6608
7182
|
options
|
|
6609
7183
|
});
|
|
6610
7184
|
}
|
|
@@ -6618,6 +7192,7 @@ class ZipDirectoryEntry extends ZipEntry {
|
|
|
6618
7192
|
}
|
|
6619
7193
|
|
|
6620
7194
|
addFile(file, options = {}) {
|
|
7195
|
+
options = Object.assign({}, options);
|
|
6621
7196
|
if (!options.lastModDate) {
|
|
6622
7197
|
options.lastModDate = new Date(file.lastModified);
|
|
6623
7198
|
}
|
|
@@ -6684,11 +7259,15 @@ class ZipDirectoryEntry extends ZipEntry {
|
|
|
6684
7259
|
try {
|
|
6685
7260
|
const path = entry.filename.split("/");
|
|
6686
7261
|
const name = path.pop();
|
|
6687
|
-
path.forEach(
|
|
7262
|
+
path.forEach(pathPart => {
|
|
6688
7263
|
const previousParent = parent;
|
|
6689
7264
|
parent = parent.getChildByName(pathPart);
|
|
6690
|
-
if (
|
|
6691
|
-
|
|
7265
|
+
if (parent) {
|
|
7266
|
+
if (!parent.directory) {
|
|
7267
|
+
throw new Error(ERR_ENTRY_EXISTS);
|
|
7268
|
+
}
|
|
7269
|
+
} else {
|
|
7270
|
+
parent = new ZipDirectoryEntry(this.fs, pathPart, { data: null }, previousParent);
|
|
6692
7271
|
importedEntries.push(parent);
|
|
6693
7272
|
}
|
|
6694
7273
|
});
|
|
@@ -6699,6 +7278,22 @@ class ZipDirectoryEntry extends ZipEntry {
|
|
|
6699
7278
|
uncompressedSize: entry.uncompressedSize,
|
|
6700
7279
|
passThrough: options.passThrough
|
|
6701
7280
|
}));
|
|
7281
|
+
} else {
|
|
7282
|
+
let directoryEntry = parent;
|
|
7283
|
+
if (name) {
|
|
7284
|
+
directoryEntry = parent.getChildByName(name);
|
|
7285
|
+
if (directoryEntry) {
|
|
7286
|
+
if (!directoryEntry.directory) {
|
|
7287
|
+
throw new Error(ERR_ENTRY_EXISTS);
|
|
7288
|
+
}
|
|
7289
|
+
} else {
|
|
7290
|
+
directoryEntry = new ZipDirectoryEntry(this.fs, name, { data: null }, parent);
|
|
7291
|
+
importedEntries.push(directoryEntry);
|
|
7292
|
+
}
|
|
7293
|
+
}
|
|
7294
|
+
if (directoryEntry != this && !directoryEntry.data) {
|
|
7295
|
+
directoryEntry.data = entry;
|
|
7296
|
+
}
|
|
6702
7297
|
}
|
|
6703
7298
|
} catch (error) {
|
|
6704
7299
|
try {
|
|
@@ -6714,14 +7309,15 @@ class ZipDirectoryEntry extends ZipEntry {
|
|
|
6714
7309
|
return importedEntries;
|
|
6715
7310
|
}
|
|
6716
7311
|
|
|
6717
|
-
async exportZip(writer, options) {
|
|
7312
|
+
async exportZip(writer, options = {}) {
|
|
6718
7313
|
const zipEntry = this;
|
|
7314
|
+
options = Object.assign({}, options);
|
|
6719
7315
|
if (options.bufferedWrite === UNDEFINED_VALUE) {
|
|
6720
7316
|
options.bufferedWrite = true;
|
|
6721
7317
|
}
|
|
6722
|
-
await Promise.all([initReaders(zipEntry, options.readerOptions), initStream(writer)]);
|
|
7318
|
+
const [readers] = await Promise.all([initReaders(zipEntry, options.readerOptions), initStream(writer)]);
|
|
6723
7319
|
const zipWriter = new ZipWriter(writer, options);
|
|
6724
|
-
await exportZip(zipWriter, zipEntry, getTotalSize([zipEntry], "uncompressedSize"), options);
|
|
7320
|
+
await exportZip(zipWriter, zipEntry, getTotalSize([zipEntry], "uncompressedSize"), options, readers);
|
|
6725
7321
|
await zipWriter.close();
|
|
6726
7322
|
return writer.getData ? writer.getData() : writer.writable;
|
|
6727
7323
|
}
|
|
@@ -6767,7 +7363,15 @@ class FS {
|
|
|
6767
7363
|
|
|
6768
7364
|
remove(entry) {
|
|
6769
7365
|
detach(entry);
|
|
6770
|
-
|
|
7366
|
+
const removedEntries = [entry];
|
|
7367
|
+
while (removedEntries.length) {
|
|
7368
|
+
const removedEntry = removedEntries.pop();
|
|
7369
|
+
this.entries[removedEntry.id] = null;
|
|
7370
|
+
for (const child of removedEntry.children) {
|
|
7371
|
+
removedEntries.push(child);
|
|
7372
|
+
}
|
|
7373
|
+
}
|
|
7374
|
+
entry.parent = UNDEFINED_VALUE;
|
|
6771
7375
|
}
|
|
6772
7376
|
|
|
6773
7377
|
move(entry, destination) {
|
|
@@ -6777,12 +7381,17 @@ class FS {
|
|
|
6777
7381
|
if (destination.directory) {
|
|
6778
7382
|
if (!destination.isDescendantOf(entry)) {
|
|
6779
7383
|
if (entry != destination) {
|
|
6780
|
-
|
|
6781
|
-
|
|
7384
|
+
const existingChild = destination.getChildByName(entry.name);
|
|
7385
|
+
if (existingChild) {
|
|
7386
|
+
if (existingChild != entry) {
|
|
7387
|
+
throw new Error(ERR_ENTRY_EXISTS);
|
|
7388
|
+
}
|
|
7389
|
+
} else {
|
|
7390
|
+
detach(entry);
|
|
7391
|
+
entry.parent = destination;
|
|
7392
|
+
destination.children.push(entry);
|
|
7393
|
+
registerEntries(this, entry);
|
|
6782
7394
|
}
|
|
6783
|
-
detach(entry);
|
|
6784
|
-
entry.parent = destination;
|
|
6785
|
-
destination.children.push(entry);
|
|
6786
7395
|
}
|
|
6787
7396
|
} else {
|
|
6788
7397
|
throw new Error("Entry is a ancestor of target entry");
|
|
@@ -6799,6 +7408,11 @@ class FS {
|
|
|
6799
7408
|
for (let index = 0; node && index < path.length; index++) {
|
|
6800
7409
|
node = node.getChildByName(path[index]);
|
|
6801
7410
|
}
|
|
7411
|
+
if (!node) {
|
|
7412
|
+
// exclude detached entries, e.g. clones registered in `entries` but not attached
|
|
7413
|
+
node = this.entries.find(entry => entry && (entry == this.root || entry.isDescendantOf(this.root)) &&
|
|
7414
|
+
entry.getRelativeName() == fullname);
|
|
7415
|
+
}
|
|
6802
7416
|
return node;
|
|
6803
7417
|
}
|
|
6804
7418
|
|
|
@@ -6880,6 +7494,7 @@ class FS {
|
|
|
6880
7494
|
}
|
|
6881
7495
|
|
|
6882
7496
|
importZip(reader, options) {
|
|
7497
|
+
resetFS(this);
|
|
6883
7498
|
return this.root.importZip(reader, options);
|
|
6884
7499
|
}
|
|
6885
7500
|
|
|
@@ -6899,6 +7514,10 @@ class FS {
|
|
|
6899
7514
|
return this.root.exportWritable(writable, options);
|
|
6900
7515
|
}
|
|
6901
7516
|
|
|
7517
|
+
exportZip(writer, options) {
|
|
7518
|
+
return this.root.exportZip(writer, options);
|
|
7519
|
+
}
|
|
7520
|
+
|
|
6902
7521
|
isPasswordProtected() {
|
|
6903
7522
|
return this.root.isPasswordProtected();
|
|
6904
7523
|
}
|
|
@@ -6912,15 +7531,26 @@ const fs = { FS, ZipDirectoryEntry, ZipFileEntry };
|
|
|
6912
7531
|
|
|
6913
7532
|
function getTotalSize(entries, propertyName) {
|
|
6914
7533
|
let size = 0;
|
|
6915
|
-
|
|
7534
|
+
const pendingEntries = Array.from(entries);
|
|
7535
|
+
while (pendingEntries.length) {
|
|
7536
|
+
const entry = pendingEntries.pop();
|
|
7537
|
+
size += entry[propertyName] || 0;
|
|
7538
|
+
for (const child of entry.children) {
|
|
7539
|
+
pendingEntries.push(child);
|
|
7540
|
+
}
|
|
7541
|
+
}
|
|
6916
7542
|
return size;
|
|
7543
|
+
}
|
|
6917
7544
|
|
|
6918
|
-
|
|
6919
|
-
|
|
6920
|
-
|
|
6921
|
-
|
|
7545
|
+
function getReadableReader(readable) {
|
|
7546
|
+
let consumed;
|
|
7547
|
+
return function () {
|
|
7548
|
+
if (consumed) {
|
|
7549
|
+
throw new Error(ERR_READABLE_CONSUMED);
|
|
6922
7550
|
}
|
|
6923
|
-
|
|
7551
|
+
consumed = true;
|
|
7552
|
+
return { readable };
|
|
7553
|
+
};
|
|
6924
7554
|
}
|
|
6925
7555
|
|
|
6926
7556
|
function getZipBlobReader(options) {
|
|
@@ -6935,7 +7565,7 @@ function getZipBlobReader(options) {
|
|
|
6935
7565
|
async init() {
|
|
6936
7566
|
const zipBlobReader = this;
|
|
6937
7567
|
zipBlobReader.size = zipBlobReader.entry.uncompressedSize;
|
|
6938
|
-
const data = await zipBlobReader.entry.getData(new BlobWriter(), Object.assign({},
|
|
7568
|
+
const data = await zipBlobReader.entry.getData(new BlobWriter(), Object.assign({}, options, zipBlobReader.options));
|
|
6939
7569
|
zipBlobReader.data = data;
|
|
6940
7570
|
zipBlobReader.blobReader = new BlobReader(data);
|
|
6941
7571
|
super.init();
|
|
@@ -6948,29 +7578,41 @@ function getZipBlobReader(options) {
|
|
|
6948
7578
|
}
|
|
6949
7579
|
|
|
6950
7580
|
async function initReaders(entry, options) {
|
|
6951
|
-
|
|
6952
|
-
|
|
7581
|
+
const fileEntries = [];
|
|
7582
|
+
const pendingEntries = [entry];
|
|
7583
|
+
// per-export map so concurrent exports do not share (and lock) the same readers
|
|
7584
|
+
const readers = new Map();
|
|
7585
|
+
while (pendingEntries.length) {
|
|
7586
|
+
const pendingEntry = pendingEntries.pop();
|
|
7587
|
+
for (const child of pendingEntry.children) {
|
|
6953
7588
|
if (child.directory) {
|
|
6954
|
-
|
|
7589
|
+
pendingEntries.push(child);
|
|
6955
7590
|
} else {
|
|
6956
|
-
|
|
6957
|
-
try {
|
|
6958
|
-
await initStream(reader);
|
|
6959
|
-
} catch (error) {
|
|
6960
|
-
try {
|
|
6961
|
-
error.entryId = child.id;
|
|
6962
|
-
error.cause = {
|
|
6963
|
-
entry: child
|
|
6964
|
-
};
|
|
6965
|
-
} catch {
|
|
6966
|
-
// ignored
|
|
6967
|
-
}
|
|
6968
|
-
throw error;
|
|
6969
|
-
}
|
|
6970
|
-
child.uncompressedSize = reader.size;
|
|
7591
|
+
fileEntries.push(child);
|
|
6971
7592
|
}
|
|
6972
|
-
}
|
|
7593
|
+
}
|
|
6973
7594
|
}
|
|
7595
|
+
await Promise.all(fileEntries.map(async child => {
|
|
7596
|
+
const reader = child.reader = new child.Reader(child.data, options);
|
|
7597
|
+
readers.set(child, reader);
|
|
7598
|
+
try {
|
|
7599
|
+
await initStream(reader);
|
|
7600
|
+
} catch (error) {
|
|
7601
|
+
try {
|
|
7602
|
+
error.entryId = child.id;
|
|
7603
|
+
error.cause = {
|
|
7604
|
+
entry: child
|
|
7605
|
+
};
|
|
7606
|
+
} catch {
|
|
7607
|
+
// ignored
|
|
7608
|
+
}
|
|
7609
|
+
throw error;
|
|
7610
|
+
}
|
|
7611
|
+
if (reader.size !== UNDEFINED_VALUE) {
|
|
7612
|
+
child.uncompressedSize = reader.size;
|
|
7613
|
+
}
|
|
7614
|
+
}));
|
|
7615
|
+
return readers;
|
|
6974
7616
|
}
|
|
6975
7617
|
|
|
6976
7618
|
function detach(entry) {
|
|
@@ -6984,7 +7626,7 @@ function detach(entry) {
|
|
|
6984
7626
|
}
|
|
6985
7627
|
}
|
|
6986
7628
|
|
|
6987
|
-
async function exportZip(zipWriter, entry, totalSize, options) {
|
|
7629
|
+
async function exportZip(zipWriter, entry, totalSize, options, readers) {
|
|
6988
7630
|
const selectedEntry = entry;
|
|
6989
7631
|
const entryOffsets = new Map();
|
|
6990
7632
|
await process(zipWriter, entry);
|
|
@@ -6994,7 +7636,11 @@ async function exportZip(zipWriter, entry, totalSize, options) {
|
|
|
6994
7636
|
|
|
6995
7637
|
async function exportChild() {
|
|
6996
7638
|
if (options.bufferedWrite) {
|
|
6997
|
-
await Promise.allSettled(entry.children.map(processChild));
|
|
7639
|
+
const results = await Promise.allSettled(entry.children.map(processChild));
|
|
7640
|
+
const errorResult = results.find(result => result.status == "rejected");
|
|
7641
|
+
if (errorResult) {
|
|
7642
|
+
throw errorResult.reason;
|
|
7643
|
+
}
|
|
6998
7644
|
} else {
|
|
6999
7645
|
for (const child of entry.children) {
|
|
7000
7646
|
await processChild(child);
|
|
@@ -7049,7 +7695,7 @@ async function exportZip(zipWriter, entry, totalSize, options) {
|
|
|
7049
7695
|
});
|
|
7050
7696
|
}
|
|
7051
7697
|
}
|
|
7052
|
-
await zipWriter.add(name, child
|
|
7698
|
+
await zipWriter.add(name, readers.get(child), Object.assign({}, options, zipEntryOptions, childOptions, {
|
|
7053
7699
|
directory: child.directory,
|
|
7054
7700
|
onprogress: async indexProgress => {
|
|
7055
7701
|
if (options.onprogress) {
|
|
@@ -7098,7 +7744,7 @@ function addFileSystemHandle(zipEntry, handle, options) {
|
|
|
7098
7744
|
}
|
|
7099
7745
|
} catch (error) {
|
|
7100
7746
|
const message = error.message + (handle ? " (" + handle.name + ")" : "");
|
|
7101
|
-
throw new Error(message);
|
|
7747
|
+
throw new Error(message, { cause: error });
|
|
7102
7748
|
}
|
|
7103
7749
|
}
|
|
7104
7750
|
return addedEntries;
|
|
@@ -7158,9 +7804,21 @@ async function transformToFileSystemhandles(entry) {
|
|
|
7158
7804
|
|
|
7159
7805
|
function resetFS(fs) {
|
|
7160
7806
|
fs.entries = [];
|
|
7807
|
+
fs.entryIdCounter = 0;
|
|
7161
7808
|
fs.root = new ZipDirectoryEntry(fs);
|
|
7162
7809
|
}
|
|
7163
7810
|
|
|
7811
|
+
function registerEntries(fs, entry) {
|
|
7812
|
+
const pendingEntries = [entry];
|
|
7813
|
+
while (pendingEntries.length) {
|
|
7814
|
+
const pendingEntry = pendingEntries.pop();
|
|
7815
|
+
fs.entries[pendingEntry.id] = pendingEntry;
|
|
7816
|
+
for (const child of pendingEntry.children) {
|
|
7817
|
+
pendingEntries.push(child);
|
|
7818
|
+
}
|
|
7819
|
+
}
|
|
7820
|
+
}
|
|
7821
|
+
|
|
7164
7822
|
function addChild(parent, name, params, directory) {
|
|
7165
7823
|
if (parent.directory) {
|
|
7166
7824
|
return directory ? new ZipDirectoryEntry(parent.fs, name, params, parent) : new ZipFileEntry(parent.fs, name, params, parent);
|
|
@@ -8836,6 +9494,7 @@ exports.BlobReader = BlobReader;
|
|
|
8836
9494
|
exports.BlobWriter = BlobWriter;
|
|
8837
9495
|
exports.Data64URIReader = Data64URIReader;
|
|
8838
9496
|
exports.Data64URIWriter = Data64URIWriter;
|
|
9497
|
+
exports.ERR_AMBIGUOUS_ARCHIVE = ERR_AMBIGUOUS_ARCHIVE;
|
|
8839
9498
|
exports.ERR_BAD_FORMAT = ERR_BAD_FORMAT;
|
|
8840
9499
|
exports.ERR_CENTRAL_DIRECTORY_NOT_FOUND = ERR_CENTRAL_DIRECTORY_NOT_FOUND;
|
|
8841
9500
|
exports.ERR_DUPLICATED_NAME = ERR_DUPLICATED_NAME;
|
|
@@ -8845,6 +9504,7 @@ exports.ERR_EOCDR_NOT_FOUND = ERR_EOCDR_NOT_FOUND;
|
|
|
8845
9504
|
exports.ERR_EXTRAFIELD_ZIP64_NOT_FOUND = ERR_EXTRAFIELD_ZIP64_NOT_FOUND;
|
|
8846
9505
|
exports.ERR_HTTP_RANGE = ERR_HTTP_RANGE;
|
|
8847
9506
|
exports.ERR_INVALID_COMMENT = ERR_INVALID_COMMENT;
|
|
9507
|
+
exports.ERR_INVALID_COMPRESSED_DATA = ERR_INVALID_COMPRESSED_DATA;
|
|
8848
9508
|
exports.ERR_INVALID_ENCRYPTION_STRENGTH = ERR_INVALID_ENCRYPTION_STRENGTH;
|
|
8849
9509
|
exports.ERR_INVALID_ENTRY_COMMENT = ERR_INVALID_ENTRY_COMMENT;
|
|
8850
9510
|
exports.ERR_INVALID_ENTRY_NAME = ERR_INVALID_ENTRY_NAME;
|
|
@@ -8857,8 +9517,9 @@ exports.ERR_INVALID_VERSION = ERR_INVALID_VERSION;
|
|
|
8857
9517
|
exports.ERR_LOCAL_FILE_HEADER_NOT_FOUND = ERR_LOCAL_FILE_HEADER_NOT_FOUND;
|
|
8858
9518
|
exports.ERR_OVERLAPPING_ENTRY = ERR_OVERLAPPING_ENTRY;
|
|
8859
9519
|
exports.ERR_SPLIT_ZIP_FILE = ERR_SPLIT_ZIP_FILE;
|
|
9520
|
+
exports.ERR_UNDEFINED_READER = ERR_UNDEFINED_READER;
|
|
8860
9521
|
exports.ERR_UNDEFINED_UNCOMPRESSED_SIZE = ERR_UNDEFINED_UNCOMPRESSED_SIZE;
|
|
8861
|
-
exports.ERR_UNSUPPORTED_COMPRESSION = ERR_UNSUPPORTED_COMPRESSION;
|
|
9522
|
+
exports.ERR_UNSUPPORTED_COMPRESSION = ERR_UNSUPPORTED_COMPRESSION$1;
|
|
8862
9523
|
exports.ERR_UNSUPPORTED_ENCRYPTION = ERR_UNSUPPORTED_ENCRYPTION;
|
|
8863
9524
|
exports.ERR_UNSUPPORTED_FORMAT = ERR_UNSUPPORTED_FORMAT;
|
|
8864
9525
|
exports.ERR_ZIP_NOT_EMPTY = ERR_ZIP_NOT_EMPTY;
|