@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/dist/zip.js
CHANGED
|
@@ -50,6 +50,7 @@
|
|
|
50
50
|
const END_OF_CENTRAL_DIR_SIGNATURE = 0x06054b50;
|
|
51
51
|
const ZIP64_END_OF_CENTRAL_DIR_SIGNATURE = 0x06064b50;
|
|
52
52
|
const ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIGNATURE = 0x07064b50;
|
|
53
|
+
const CENTRAL_FILE_HEADER_LENGTH = 46;
|
|
53
54
|
const END_OF_CENTRAL_DIR_LENGTH = 22;
|
|
54
55
|
const ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH = 20;
|
|
55
56
|
const ZIP64_END_OF_CENTRAL_DIR_LENGTH = 56;
|
|
@@ -97,9 +98,11 @@
|
|
|
97
98
|
const DIRECTORY_SIGNATURE = "/";
|
|
98
99
|
|
|
99
100
|
const HEADER_SIZE = 30;
|
|
101
|
+
const HEADER_OFFSET_VERSION = 0;
|
|
100
102
|
const HEADER_OFFSET_SIGNATURE = 10;
|
|
101
103
|
const HEADER_OFFSET_COMPRESSED_SIZE = 14;
|
|
102
104
|
const HEADER_OFFSET_UNCOMPRESSED_SIZE = 18;
|
|
105
|
+
const LOCAL_HEADER_COMMON_OFFSET = 4;
|
|
103
106
|
|
|
104
107
|
const MAX_DATE = new Date(2107, 11, 31);
|
|
105
108
|
const MIN_DATE = new Date(1980, 0, 1);
|
|
@@ -154,6 +157,7 @@
|
|
|
154
157
|
chunkSize: 64 * 1024,
|
|
155
158
|
maxWorkers,
|
|
156
159
|
terminateWorkerTimeout: 5000,
|
|
160
|
+
workerStarvationTimeout: 5000,
|
|
157
161
|
useWebWorkers: true,
|
|
158
162
|
useCompressionStream: true,
|
|
159
163
|
CompressionStream: typeof CompressionStream != UNDEFINED_TYPE && CompressionStream,
|
|
@@ -176,6 +180,7 @@
|
|
|
176
180
|
chunkSize,
|
|
177
181
|
maxWorkers,
|
|
178
182
|
terminateWorkerTimeout,
|
|
183
|
+
workerStarvationTimeout,
|
|
179
184
|
useCompressionStream,
|
|
180
185
|
useWebWorkers,
|
|
181
186
|
CompressionStream,
|
|
@@ -191,6 +196,7 @@
|
|
|
191
196
|
setIfDefined("chunkSize", chunkSize);
|
|
192
197
|
setIfDefined("maxWorkers", maxWorkers);
|
|
193
198
|
setIfDefined("terminateWorkerTimeout", terminateWorkerTimeout);
|
|
199
|
+
setIfDefined("workerStarvationTimeout", workerStarvationTimeout);
|
|
194
200
|
setIfDefined("useCompressionStream", useCompressionStream);
|
|
195
201
|
setIfDefined("useWebWorkers", useWebWorkers);
|
|
196
202
|
setIfDefined("CompressionStream", CompressionStream);
|
|
@@ -205,7 +211,7 @@
|
|
|
205
211
|
}
|
|
206
212
|
}
|
|
207
213
|
|
|
208
|
-
function t(t){const e='(t=>{"function"==typeof define&&define.amd?define(t):t()})(function(){"use strict";const{Array:t,Object:e,Number:n,Math:s,Error:r,Uint8Array:o,Uint16Array:i,Uint32Array:c,Int32Array:a,Map:h,DataView:f,Promise:l,TextEncoder:u,crypto:w,postMessage:p,TransformStream:d,ReadableStream:y,WritableStream:m,CompressionStream:g,DecompressionStream:S}=self,b=void 0,v="undefined",k="function",z=[];for(let t=0;256>t;t++){let e=t;for(let t=0;8>t;t++)1&e?e=e>>>1^3988292384:e>>>=1;z[t]=e}class C{constructor(t){this.t=t||-1}append(t){let e=0|this.t;for(let n=0,s=0|t.length;s>n;n++)e=e>>>8^z[255&(e^t[n])];this.t=e}get(){return~this.t}}class A extends d{constructor(){let t;const e=new C;super({transform(t,n){e.append(t),n.enqueue(t)},flush(){const n=new o(4);new f(n.buffer).setUint32(0,e.get()),t.value=n}}),t=this}}const x={concat(t,e){if(0===t.length||0===e.length)return t.concat(e);const n=t[t.length-1],s=x.o(n);return 32===s?t.concat(e):x.i(e,s,0|n,t.slice(0,t.length-1))},h(t){const e=t.length;if(0===e)return 0;const n=t[e-1];return 32*(e-1)+x.o(n)},l(t,e){if(32*t.length<e)return t;const n=(t=t.slice(0,s.ceil(e/32))).length;return e&=31,n>0&&e&&(t[n-1]=x.u(e,t[n-1]&2147483648>>e-1,1)),t},u:(t,e,n)=>32===t?e:(n?0|e:e<<32-t)+1099511627776*t,o:t=>s.round(t/1099511627776)||32,i(t,e,n,s){for(void 0===s&&(s=[]);e>=32;e-=32)s.push(n),n=0;if(0===e)return s.concat(t);for(let r=0;r<t.length;r++)s.push(n|t[r]>>>e),n=t[r]<<32-e;const r=t.length?t[t.length-1]:0,o=x.o(r);return s.push(x.u(e+o&31,e+o>32?n:s.pop(),1)),s}},I={bytes:{p(t){const e=x.h(t)/8,n=new o(e);let s;for(let r=0;e>r;r++)3&r||(s=t[r/4]),n[r]=s>>>24,s<<=8;return n},m(t){const e=[];let n,s=0;for(n=0;n<t.length;n++)s=s<<8|t[n],3&~n||(e.push(s),s=0);return 3&n&&e.push(x.u(8*(3&n),s)),e}}},R=class{constructor(t){const e=this;e.blockSize=512,e.S=[1732584193,4023233417,2562383102,271733878,3285377520],e.v=[1518500249,1859775393,2400959708,3395469782],t?(e.k=t.k.slice(0),e.C=t.C.slice(0),e.A=t.A):e.reset()}reset(){const t=this;return t.k=t.S.slice(0),t.C=[],t.A=0,t}update(t){const e=this;"string"==typeof t&&(t=I.I.m(t));const n=e.C=x.concat(e.C,t),s=e.A,o=e.A=s+x.h(t);if(o>9007199254740991)throw new r("Cannot hash more than 2^53 - 1 bits");const i=new c(n);let a=0;for(let t=e.blockSize+s-(e.blockSize+s&e.blockSize-1);o>=t;t+=e.blockSize)e.R(i.subarray(16*a,16*(a+1))),a+=1;return n.splice(0,16*a),e}P(){const t=this;let e=t.C;const n=t.k;e=x.concat(e,[x.u(1,1)]);for(let t=e.length+2;15&t;t++)e.push(0);for(e.push(s.floor(t.A/4294967296)),e.push(0|t.A);e.length;)t.R(e.splice(0,16));return t.reset(),n}U(t,e,n,s){return t>19?t>39?t>59?t>79?void 0:e^n^s:e&n|e&s|n&s:e^n^s:e&n|~e&s}V(t,e){return e<<t|e>>>32-t}R(e){const n=this,r=n.k,o=t(80);for(let t=0;16>t;t++)o[t]=e[t];let i=r[0],c=r[1],a=r[2],h=r[3],f=r[4];for(let t=0;79>=t;t++){16>t||(o[t]=n.V(1,o[t-3]^o[t-8]^o[t-14]^o[t-16]));const e=n.V(5,i)+n.U(t,c,a,h)+f+o[t]+n.v[s.floor(t/20)]|0;f=h,h=a,a=n.V(30,c),c=i,i=e}r[0]=r[0]+i|0,r[1]=r[1]+c|0,r[2]=r[2]+a|0,r[3]=r[3]+h|0,r[4]=r[4]+f|0}},P={getRandomValues(t){const e=new c(t.buffer),n=t=>{let e=987654321;const n=4294967295;return()=>(e=36969*(65535&e)+(e>>16)&n,(((e<<16)+(t=18e3*(65535&t)+(t>>16)&n)&n)/4294967296+.5)*(s.random()>.5?1:-1))};for(let r,o=0;o<t.length;o+=4){const t=n(4294967296*(r||s.random()));r=987654071*t(),e[o/4]=4294967296*t()|0}return t}},U={importKey:t=>new U.M(I.bytes.m(t)),_(t,e,n,s){if(n=n||1e4,0>s||0>n)throw new r("invalid params to pbkdf2");const o=1+(s>>5)<<2;let i,c,a,h,l;const u=new ArrayBuffer(o),w=new f(u);let p=0;const d=x;for(e=I.bytes.m(e),l=1;(o||1)>p;l++){for(i=c=t.encrypt(d.concat(e,[l])),a=1;n>a;a++)for(c=t.encrypt(c),h=0;h<c.length;h++)i[h]^=c[h];for(a=0;(o||1)>p&&a<i.length;a++)w.setInt32(p,i[a]),p+=4}return u.slice(0,s/8)},M:class{constructor(t){const e=this,n=e.B=R,s=[[],[]];e.D=[new n,new n];const r=e.D[0].blockSize/32;t.length>r&&(t=(new n).update(t).P());for(let e=0;r>e;e++)s[0][e]=909522486^t[e],s[1][e]=1549556828^t[e];e.D[0].update(s[0]),e.D[1].update(s[1]),e.W=new n(e.D[0])}reset(){const t=this;t.W=new t.B(t.D[0]),t.K=!1}update(t){this.K=!0,this.W.update(t)}digest(){const t=this,e=t.W.P(),n=new t.B(t.D[1]).update(e).P();return t.reset(),n}encrypt(t){if(this.K)throw new r("encrypt on already updated hmac called!");return this.update(t),this.digest(t)}}},V=typeof w!=v&&typeof w.getRandomValues==k,M="Invalid password",_="Invalid signature",B="zipjs-abort-check-password";function D(t){return V?w.getRandomValues(t):P.getRandomValues(t)}const W=16,K={name:"PBKDF2"},E=e.assign({hash:{name:"HMAC"}},K),L=e.assign({iterations:1e3,hash:{name:"SHA-1"}},K),O=["deriveBits"],T=[8,12,16],j=[16,24,32],H=10,Z=[0,0,0,0],F=typeof w!=v,N=F&&w.subtle,q=F&&typeof N!=v,G=I.bytes,J=class{constructor(t){const e=this;e.L=[[[],[],[],[],[]],[[],[],[],[],[]]],e.L[0][0][0]||e.O();const n=e.L[0][4],s=e.L[1],o=t.length;let i,c,a,h=1;if(4!==o&&6!==o&&8!==o)throw new r("invalid aes key size");for(e.v=[c=t.slice(0),a=[]],i=o;4*o+28>i;i++){let t=c[i-1];(i%o===0||8===o&&i%o===4)&&(t=n[t>>>24]<<24^n[t>>16&255]<<16^n[t>>8&255]<<8^n[255&t],i%o===0&&(t=t<<8^t>>>24^h<<24,h=h<<1^283*(h>>7))),c[i]=c[i-o]^t}for(let t=0;i;t++,i--){const e=c[3&t?i:i-4];a[t]=4>=i||4>t?e:s[0][n[e>>>24]]^s[1][n[e>>16&255]]^s[2][n[e>>8&255]]^s[3][n[255&e]]}}encrypt(t){return this.T(t,0)}decrypt(t){return this.T(t,1)}O(){const t=this.L[0],e=this.L[1],n=t[4],s=e[4],r=[],o=[];let i,c,a,h;for(let t=0;256>t;t++)o[(r[t]=t<<1^283*(t>>7))^t]=t;for(let f=i=0;!n[f];f^=c||1,i=o[i]||1){let o=i^i<<1^i<<2^i<<3^i<<4;o=o>>8^255&o^99,n[f]=o,s[o]=f,h=r[a=r[c=r[f]]];let l=16843009*h^65537*a^257*c^16843008*f,u=257*r[o]^16843008*o;for(let n=0;4>n;n++)t[n][f]=u=u<<24^u>>>8,e[n][o]=l=l<<24^l>>>8}for(let n=0;5>n;n++)t[n]=t[n].slice(0),e[n]=e[n].slice(0)}T(t,e){if(4!==t.length)throw new r("invalid aes block size");const n=this.v[e],s=n.length/4-2,o=[0,0,0,0],i=this.L[e],c=i[0],a=i[1],h=i[2],f=i[3],l=i[4];let u,w,p,d=t[0]^n[0],y=t[e?3:1]^n[1],m=t[2]^n[2],g=t[e?1:3]^n[3],S=4;for(let t=0;s>t;t++)u=c[d>>>24]^a[y>>16&255]^h[m>>8&255]^f[255&g]^n[S],w=c[y>>>24]^a[m>>16&255]^h[g>>8&255]^f[255&d]^n[S+1],p=c[m>>>24]^a[g>>16&255]^h[d>>8&255]^f[255&y]^n[S+2],g=c[g>>>24]^a[d>>16&255]^h[y>>8&255]^f[255&m]^n[S+3],S+=4,d=u,y=w,m=p;for(let t=0;4>t;t++)o[e?3&-t:t]=l[d>>>24]<<24^l[y>>16&255]<<16^l[m>>8&255]<<8^l[255&g]^n[S++],u=d,d=y,y=m,m=g,g=u;return o}},Q=class{constructor(t,e){this.j=t,this.H=e,this.Z=e}reset(){this.Z=this.H}update(t){return this.F(this.j,t,this.Z)}N(t){if(255&~(t>>24))t+=1<<24;else{let e=t>>16&255,n=t>>8&255,s=255&t;255===e?(e=0,255===n?(n=0,255===s?s=0:++s):++n):++e,t=0,t+=e<<16,t+=n<<8,t+=s}return t}q(t){0===(t[0]=this.N(t[0]))&&(t[1]=this.N(t[1]))}F(t,e,n){let s;if(!(s=e.length))return[];const r=x.h(e);for(let r=0;s>r;r+=4){this.q(n);const s=t.encrypt(n);e[r]^=s[0],e[r+1]^=s[1],e[r+2]^=s[2],e[r+3]^=s[3]}return x.l(e,r)}},X=U.M;let Y=F&&q&&typeof N.importKey==k,$=F&&q&&typeof N.deriveBits==k;class tt extends d{constructor({password:t,rawPassword:n,signed:s,encryptionStrength:i,checkPasswordOnly:c}){super({start(){e.assign(this,{ready:new l(t=>this.G=t),password:rt(t,n),signed:s,J:i-1,pending:new o})},async transform(t,e){const n=this,{password:s,J:i,G:a,ready:h}=n;s?(await(async(t,e,n,s)=>{const o=await st(t,e,n,it(s,0,T[e])),i=it(s,T[e]);if(o[0]!=i[0]||o[1]!=i[1])throw new r(M)})(n,i,s,it(t,0,T[i]+2)),t=it(t,T[i]+2),c?e.error(new r(B)):a()):await h;const f=new o(t.length-H-(t.length-H)%W);e.enqueue(nt(n,t,f,0,H,!0))},async flush(t){const{signed:e,X:n,Y:s,pending:i,ready:c}=this;if(s&&n){await c;const a=it(i,0,i.length-H),h=it(i,i.length-H);let f=new o;if(a.length){const t=at(G,a);s.update(t);const e=n.update(t);f=ct(G,e)}if(e){const t=it(ct(G,s.digest()),0,H);for(let e=0;H>e;e++)if(t[e]!=h[e])throw new r(_)}t.enqueue(f)}}})}}class et extends d{constructor({password:t,rawPassword:n,encryptionStrength:s}){let r;super({start(){e.assign(this,{ready:new l(t=>this.G=t),password:rt(t,n),J:s-1,pending:new o})},async transform(t,e){const n=this,{password:s,J:r,G:i,ready:c}=n;let a=new o;s?(a=await(async(t,e,n)=>{const s=D(new o(T[e]));return ot(s,await st(t,e,n,s))})(n,r,s),i()):await c;const h=new o(a.length+t.length-t.length%W);h.set(a,0),e.enqueue(nt(n,t,h,a.length,0))},async flush(t){const{X:e,Y:n,pending:s,ready:i}=this;if(n&&e){await i;let c=new o;if(s.length){const t=e.update(at(G,s));n.update(t),c=ct(G,t)}r.signature=ct(G,n.digest()).slice(0,H),t.enqueue(ot(c,r.signature))}}}),r=this}}function nt(t,e,n,s,r,i){const{X:c,Y:a,pending:h}=t,f=e.length-r;let l;for(h.length&&(e=ot(h,e),n=((t,e)=>{if(e&&e>t.length){const n=t;(t=new o(e)).set(n,0)}return t})(n,f-f%W)),l=0;f-W>=l;l+=W){const t=at(G,it(e,l,l+W));i&&a.update(t);const r=c.update(t);i||a.update(r),n.set(ct(G,r),l+s)}return t.pending=it(e,l),n}async function st(n,s,r,i){n.password=null;const c=await(async(t,e,n,s,r)=>{if(!Y)return U.importKey(e);try{return await N.importKey("raw",e,n,!1,r)}catch{return Y=!1,U.importKey(e)}})(0,r,E,0,O),a=await(async(t,e,n)=>{if(!$)return U._(e,t.salt,L.iterations,n);try{return await N.deriveBits(t,e,n)}catch{return $=!1,U._(e,t.salt,L.iterations,n)}})(e.assign({salt:i},L),c,8*(2*j[s]+2)),h=new o(a),f=at(G,it(h,0,j[s])),l=at(G,it(h,j[s],2*j[s])),u=it(h,2*j[s]);return e.assign(n,{keys:{key:f,$:l,passwordVerification:u},X:new Q(new J(f),t.from(Z)),Y:new X(l)}),u}function rt(t,e){return e===b?(t=>{if(typeof u==v){const e=new o((t=unescape(encodeURIComponent(t))).length);for(let n=0;n<e.length;n++)e[n]=t.charCodeAt(n);return e}return(new u).encode(t)})(t):e}function ot(t,e){let n=t;return t.length+e.length&&(n=new o(t.length+e.length),n.set(t,0),n.set(e,t.length)),n}function it(t,e,n){return t.subarray(e,n)}function ct(t,e){return t.p(e)}function at(t,e){return t.m(e)}class ht extends d{constructor({password:t,passwordVerification:n,checkPasswordOnly:s}){super({start(){e.assign(this,{password:t,passwordVerification:n}),wt(this,t)},transform(t,e){const n=this;if(n.password){const e=lt(n,t.subarray(0,12));if(n.password=null,e.at(-1)!=n.passwordVerification)throw new r(M);t=t.subarray(12)}s?e.error(new r(B)):e.enqueue(lt(n,t))}})}}class ft extends d{constructor({password:t,passwordVerification:n}){super({start(){e.assign(this,{password:t,passwordVerification:n}),wt(this,t)},transform(t,e){const n=this;let s,r;if(n.password){n.password=null;const e=D(new o(12));e[11]=n.passwordVerification,s=new o(t.length+e.length),s.set(ut(n,e),0),r=12}else s=new o(t.length),r=0;s.set(ut(n,t),r),e.enqueue(s)}})}}function lt(t,e){const n=new o(e.length);for(let s=0;s<e.length;s++)n[s]=dt(t)^e[s],pt(t,n[s]);return n}function ut(t,e){const n=new o(e.length);for(let s=0;s<e.length;s++)n[s]=dt(t)^e[s],pt(t,e[s]);return n}function wt(t,n){const s=[305419896,591751049,878082192];e.assign(t,{keys:s,tt:new C(s[0]),et:new C(s[2])});for(let e=0;e<n.length;e++)pt(t,n.charCodeAt(e))}function pt(t,e){let[n,r,o]=t.keys;t.tt.append([e]),n=~t.tt.get(),r=mt(s.imul(mt(r+yt(n)),134775813)+1),t.et.append([r>>>24]),o=~t.et.get(),t.keys=[n,r,o]}function dt(t){const e=2|t.keys[2];return yt(s.imul(e,1^e)>>>8)}function yt(t){return 255&t}function mt(t){return 4294967295&t}class gt extends d{constructor(t,{chunkSize:e,nt:n,CompressionStream:s}){super({});const{compressed:r,encrypted:o,useCompressionStream:i,zipCrypto:c,signed:a,level:h}=t,l=this;let u,w,p=super.readable;o&&!c||!a||(u=new A,p=kt(p,u)),r&&(p=vt(p,i,{level:h,chunkSize:e},s,n,s)),o&&(c?p=kt(p,new ft(t)):(w=new et(t),p=kt(p,w))),bt(l,p,()=>{let t;o&&!c&&(t=w.signature),o&&!c||!a||(t=new f(u.value.buffer).getUint32(0)),l.signature=t})}}class St extends d{constructor(t,{chunkSize:e,st:n,DecompressionStream:s}){super({});const{zipCrypto:o,encrypted:i,signed:c,signature:a,compressed:h,useCompressionStream:l,rt:u}=t;let w,p,d=super.readable;i&&(o?d=kt(d,new ht(t)):(p=new tt(t),d=kt(d,p))),h&&(d=vt(d,l,{chunkSize:e,rt:u},s,n,s)),i&&!o||!c||(w=new A,d=kt(d,w)),bt(this,d,()=>{if((!i||o)&&c){const t=new f(w.value.buffer);if(a!=t.getUint32(0,!1))throw new r(_)}})}}function bt(t,n,s){n=kt(n,new d({flush:s})),e.defineProperty(t,"readable",{get:()=>n})}function vt(t,e,n,s,r,o){const i=e&&s?s:r||o,c=n.rt?"deflate64-raw":"deflate-raw";try{t=kt(t,new i(c,n))}catch(s){if(!e)throw s;if(r)t=kt(t,new r(c,n));else{if(!o)throw s;t=kt(t,new o(c,n))}}return t}function kt(t,e){return t.pipeThrough(e)}const zt="data",Ct="close";class At extends d{constructor(t,n){super({});const s=this,{codecType:o}=t;let i;o.startsWith("deflate")?i=gt:o.startsWith("inflate")&&(i=St),s.outputSize=0;let c=0;const a=new i(t,n),h=super.readable,f=new d({transform(t,e){t&&t.length&&(c+=t.length,e.enqueue(t))},flush(){e.assign(s,{inputSize:c})}}),l=new d({transform(e,n){if(e&&e.length&&(n.enqueue(e),s.outputSize+=e.length,t.outputSize!==b&&s.outputSize>t.outputSize))throw new r("Invalid uncompressed size")},flush(){const{signature:t}=a;e.assign(s,{signature:t,inputSize:c})}});e.defineProperty(s,"readable",{get:()=>h.pipeThrough(f).pipeThrough(a).pipeThrough(l)})}}class xt extends d{constructor(t){let e;super({transform:function n(s,r){if(e){const t=new o(e.length+s.length);t.set(e),t.set(s,e.length),s=t,e=null}s.length>t?(r.enqueue(s.slice(0,t)),n(s.slice(t),r)):e=s},flush(t){e&&e.length&&t.enqueue(e)}})}}const It=new h,Rt=new h;let Pt,Ut,Vt,Mt,_t,Bt=0;async function Dt(t){try{const{options:e,config:s}=t;if(!e.useCompressionStream)try{await self.initModule(t.config)}catch{e.useCompressionStream=!0}s.CompressionStream=self.CompressionStream,s.DecompressionStream=self.DecompressionStream;const r={highWaterMark:1},o=t.readable||new y({async pull(t){const e=new l(t=>It.set(Bt,t));Wt({type:"pull",messageId:Bt}),Bt=(Bt+1)%n.MAX_SAFE_INTEGER;const{value:s,done:r}=await e;t.enqueue(s),r&&t.close()}},r),i=t.writable||new m({async write(t){let e;const s=new l(t=>e=t);Rt.set(Bt,e),Wt({type:zt,value:t,messageId:Bt}),Bt=(Bt+1)%n.MAX_SAFE_INTEGER,await s}},r),c=new At(e,s);Pt=new AbortController;const{signal:a}=Pt;await o.pipeThrough(c).pipeThrough(new xt(s.chunkSize)).pipeTo(i,{signal:a,preventClose:!0,preventAbort:!0}),await i.getWriter().close();const{signature:h,inputSize:f,outputSize:u}=c;Wt({type:Ct,result:{signature:h,inputSize:f,outputSize:u}})}catch(t){t.outputSize=0,Kt(t)}}function Wt(t){let{value:e}=t;if(e)if(e.length)try{e=new o(e),t.value=e.buffer,p(t,[t.value])}catch{p(t)}else p(t);else p(t)}function Kt(t=new r("Unknown error")){const{message:e,stack:n,code:s,name:o,outputSize:i}=t;p({error:{message:e,stack:n,code:s,name:o,outputSize:i}})}function Et(t,e,n={}){const i="number"==typeof n.level?n.level:-1,c="number"==typeof n.ot?n.ot:65536,a="number"==typeof n.it?n.it:65536;return new d({start(){let n;if(this.ct=Vt(c),this.in=Vt(a),this.it=a,this.ht=new o(c),t?(this.ft=Ut.deflate_process,this.lt=Ut.deflate_last_consumed,this.ut=Ut.deflate_end,this.wt=Ut.deflate_new(),n="gzip"===e?Ut.deflate_init_gzip(this.wt,i):"deflate-raw"===e?Ut.deflate_init_raw(this.wt,i):Ut.deflate_init(this.wt,i)):"deflate64-raw"===e?(this.ft=Ut.inflate9_process,this.lt=Ut.inflate9_last_consumed,this.ut=Ut.inflate9_end,this.wt=Ut.inflate9_new(),n=Ut.inflate9_init_raw(this.wt)):(this.ft=Ut.inflate_process,this.lt=Ut.inflate_last_consumed,this.ut=Ut.inflate_end,this.wt=Ut.inflate_new(),n="deflate-raw"===e?Ut.inflate_init_raw(this.wt):"gzip"===e?Ut.inflate_init_gzip(this.wt):Ut.inflate_init(this.wt)),0!==n)throw new r("init failed:"+n)},transform(e,n){try{const i=e,a=new o(_t.buffer),h=this.ft,f=this.lt,l=this.ct,u=this.ht;let w=0;for(;w<i.length;){const e=s.min(i.length-w,32768);this.in&&this.it>=e||(this.in&&Mt&&Mt(this.in),this.in=Vt(e),this.it=e),a.set(i.subarray(w,w+e),this.in);const o=h(this.wt,this.in,e,l,c,0),p=16777215&o;if(p&&(u.set(a.subarray(l,l+p),0),n.enqueue(u.slice(0,p))),!t){const t=o>>24&255,e=128&t?t-256:t;if(0>e)throw new r("process error:"+e)}const d=f(this.wt);if(0===d)break;w+=d}}catch(t){this.ut&&this.wt&&this.ut(this.wt),this.in&&Mt&&Mt(this.in),this.ct&&Mt&&Mt(this.ct),n.error(t)}},flush(e){try{const n=new o(_t.buffer),s=this.ft,i=this.ct,a=this.ht;for(;;){const o=s(this.wt,0,0,i,c,4),h=16777215&o,f=o>>24&255;if(!t){const t=128&f?f-256:f;if(0>t)throw new r("process error:"+t)}if(h&&(a.set(n.subarray(i,i+h),0),e.enqueue(a.slice(0,h))),1===f||0===h)break}}catch(t){e.error(t)}finally{if(this.ut&&this.wt){const t=this.ut(this.wt);0!==t&&e.error(new r("end error:"+t))}this.in&&Mt&&Mt(this.in),this.ct&&Mt&&Mt(this.ct)}}})}addEventListener("message",({data:t})=>{const{type:e,messageId:n,value:s,done:r}=t;try{if("start"==e&&Dt(t),e==zt){const t=It.get(n);It.delete(n),t({value:new o(s),done:r})}if("ack"==e){const t=Rt.get(n);Rt.delete(n),t()}e==Ct&&Pt.abort()}catch(t){Kt(t)}});class Lt{constructor(t="deflate",e){return Et(!0,t,e)}}class Ot{constructor(t="deflate",e){return Et(!1,t,e)}}let Tt=!1;self.initModule=async t=>{try{const e=await(async(t,{baseURI:e})=>{if(!Tt){let n,s;try{try{s=new URL(t,e)}catch{}const r=await fetch(s);n=await r.arrayBuffer()}catch(e){if(!t.startsWith("data:application/wasm;base64,"))throw e;n=(t=>{const e=t.split(",")[1],n=atob(e),s=n.length,r=new o(s);for(let t=0;s>t;++t)r[t]=n.charCodeAt(t);return r.buffer})(t)}(t=>{if(Ut=t,({malloc:Vt,free:Mt,memory:_t}=Ut),"function"!=typeof Vt||"function"!=typeof Mt||!_t)throw Ut=Vt=Mt=_t=null,new r("Invalid WASM module")})((await WebAssembly.instantiate(n)).instance.exports),Tt=!0}})(t.wasmURI,t);return t.nt=Lt,t.st=Ot,e}catch{}}});\n';t({workerURI:t=>{const n="text/javascript";if(t){const t=new Blob([e],{type:n});return URL.createObjectURL(t)}return "data:"+n+","+encodeURIComponent(e)}});}
|
|
214
|
+
function t(t){const e='(t=>{"function"==typeof define&&define.amd?define(t):t()})(function(){"use strict";const{Array:t,Object:e,Number:n,Math:s,Error:r,Uint8Array:o,Uint16Array:i,Uint32Array:a,Int32Array:c,Map:l,DataView: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)}});}
|
|
209
215
|
|
|
210
216
|
/*
|
|
211
217
|
Copyright (c) 2022 Gildas Lormeau. All rights reserved.
|
|
@@ -954,37 +960,6 @@
|
|
|
954
960
|
}
|
|
955
961
|
};
|
|
956
962
|
|
|
957
|
-
/**
|
|
958
|
-
* Random values
|
|
959
|
-
* @namespace
|
|
960
|
-
*/
|
|
961
|
-
const random = {
|
|
962
|
-
/**
|
|
963
|
-
* Generate random words with pure js, cryptographically not as strong & safe as native implementation.
|
|
964
|
-
* @param {TypedArray} typedArray The array to fill.
|
|
965
|
-
* @return {TypedArray} The random values.
|
|
966
|
-
*/
|
|
967
|
-
getRandomValues(typedArray) {
|
|
968
|
-
const words = new Uint32Array(typedArray.buffer);
|
|
969
|
-
const r = (m_w) => {
|
|
970
|
-
let m_z = 0x3ade68b1;
|
|
971
|
-
const mask = 0xffffffff;
|
|
972
|
-
return function () {
|
|
973
|
-
m_z = (0x9069 * (m_z & 0xFFFF) + (m_z >> 0x10)) & mask;
|
|
974
|
-
m_w = (0x4650 * (m_w & 0xFFFF) + (m_w >> 0x10)) & mask;
|
|
975
|
-
const result = ((((m_z << 0x10) + m_w) & mask) / 0x100000000) + .5;
|
|
976
|
-
return result * (Math.random() > .5 ? 1 : -1);
|
|
977
|
-
};
|
|
978
|
-
};
|
|
979
|
-
for (let i = 0, rcache; i < typedArray.length; i += 4) {
|
|
980
|
-
const _r = r((rcache || Math.random()) * 0x100000000);
|
|
981
|
-
rcache = _r() * 0x3ade67b7;
|
|
982
|
-
words[i / 4] = (_r() * 0x100000000) | 0;
|
|
983
|
-
}
|
|
984
|
-
return typedArray;
|
|
985
|
-
}
|
|
986
|
-
};
|
|
987
|
-
|
|
988
963
|
/** @fileOverview CTR mode implementation.
|
|
989
964
|
*
|
|
990
965
|
* Special thanks to Roy Nicholson for pointing out a bug in our
|
|
@@ -1215,12 +1190,15 @@
|
|
|
1215
1190
|
const ERR_INVALID_PASSWORD = "Invalid password";
|
|
1216
1191
|
const ERR_INVALID_SIGNATURE = "Invalid signature";
|
|
1217
1192
|
const ERR_ABORT_CHECK_PASSWORD = "zipjs-abort-check-password";
|
|
1193
|
+
const ERR_UNSUPPORTED_CRYPTO_API = "Crypto API not supported";
|
|
1218
1194
|
|
|
1219
1195
|
function getRandomValues(array) {
|
|
1220
1196
|
if (GET_RANDOM_VALUES_SUPPORTED) {
|
|
1221
1197
|
return crypto.getRandomValues(array);
|
|
1222
1198
|
} else {
|
|
1223
|
-
|
|
1199
|
+
// all supported runtimes expose crypto.getRandomValues; failing hard beats
|
|
1200
|
+
// silently generating predictable encryption salts
|
|
1201
|
+
throw new Error(ERR_UNSUPPORTED_CRYPTO_API);
|
|
1224
1202
|
}
|
|
1225
1203
|
}
|
|
1226
1204
|
|
|
@@ -1279,13 +1257,12 @@
|
|
|
1279
1257
|
|
|
1280
1258
|
class AESDecryptionStream extends TransformStream {
|
|
1281
1259
|
|
|
1282
|
-
constructor({ password, rawPassword,
|
|
1260
|
+
constructor({ password, rawPassword, encryptionStrength, checkPasswordOnly }) {
|
|
1283
1261
|
super({
|
|
1284
1262
|
start() {
|
|
1285
1263
|
Object.assign(this, {
|
|
1286
1264
|
ready: new Promise(resolve => this.resolveReady = resolve),
|
|
1287
1265
|
password: encodePassword(password, rawPassword),
|
|
1288
|
-
signed,
|
|
1289
1266
|
strength: encryptionStrength - 1,
|
|
1290
1267
|
pending: new Uint8Array()
|
|
1291
1268
|
});
|
|
@@ -1314,7 +1291,6 @@
|
|
|
1314
1291
|
},
|
|
1315
1292
|
async flush(controller) {
|
|
1316
1293
|
const {
|
|
1317
|
-
signed,
|
|
1318
1294
|
ctr,
|
|
1319
1295
|
hmac,
|
|
1320
1296
|
pending,
|
|
@@ -1331,13 +1307,15 @@
|
|
|
1331
1307
|
const decryptedChunk = ctr.update(encryptedChunk);
|
|
1332
1308
|
decryptedChunkArray = fromBits(codecBytes, decryptedChunk);
|
|
1333
1309
|
}
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1310
|
+
const signature = subarray(fromBits(codecBytes, hmac.digest()), 0, SIGNATURE_LENGTH);
|
|
1311
|
+
// branch-free comparison: accumulate the differences instead of
|
|
1312
|
+
// short-circuiting on the first mismatching byte
|
|
1313
|
+
let invalidSignature = pending.length < SIGNATURE_LENGTH ? 1 : 0;
|
|
1314
|
+
for (let indexSignature = 0; indexSignature < SIGNATURE_LENGTH; indexSignature++) {
|
|
1315
|
+
invalidSignature |= signature[indexSignature] ^ originalSignature[indexSignature];
|
|
1316
|
+
}
|
|
1317
|
+
if (invalidSignature) {
|
|
1318
|
+
throw new Error(ERR_INVALID_SIGNATURE);
|
|
1341
1319
|
}
|
|
1342
1320
|
controller.enqueue(decryptedChunkArray);
|
|
1343
1321
|
}
|
|
@@ -1409,11 +1387,11 @@
|
|
|
1409
1387
|
hmac,
|
|
1410
1388
|
pending
|
|
1411
1389
|
} = aesCrypto;
|
|
1412
|
-
const inputLength = input.length - paddingEnd;
|
|
1413
1390
|
if (pending.length) {
|
|
1414
1391
|
input = concat(pending, input);
|
|
1415
|
-
output = expand(output, inputLength - (inputLength % BLOCK_LENGTH));
|
|
1416
1392
|
}
|
|
1393
|
+
const inputLength = input.length - paddingEnd;
|
|
1394
|
+
output = expand(output, paddingStart + (inputLength - (inputLength % BLOCK_LENGTH)));
|
|
1417
1395
|
let offset;
|
|
1418
1396
|
for (offset = 0; offset <= inputLength - BLOCK_LENGTH; offset += BLOCK_LENGTH) {
|
|
1419
1397
|
const inputChunk = toBits(codecBytes, subarray(input, offset, offset + BLOCK_LENGTH));
|
|
@@ -1561,21 +1539,24 @@
|
|
|
1561
1539
|
|
|
1562
1540
|
class ZipCryptoDecryptionStream extends TransformStream {
|
|
1563
1541
|
|
|
1564
|
-
constructor({ password, passwordVerification, checkPasswordOnly }) {
|
|
1542
|
+
constructor({ password, rawPassword, passwordVerification, checkPasswordOnly }) {
|
|
1565
1543
|
super({
|
|
1566
1544
|
start() {
|
|
1567
1545
|
Object.assign(this, {
|
|
1568
1546
|
password,
|
|
1547
|
+
rawPassword,
|
|
1569
1548
|
passwordVerification
|
|
1570
1549
|
});
|
|
1571
|
-
createKeys(this, password);
|
|
1550
|
+
createKeys(this, password, rawPassword);
|
|
1572
1551
|
},
|
|
1573
1552
|
transform(chunk, controller) {
|
|
1574
1553
|
const zipCrypto = this;
|
|
1575
|
-
if (zipCrypto.password) {
|
|
1554
|
+
if (zipCrypto.password || zipCrypto.rawPassword) {
|
|
1576
1555
|
const decryptedHeader = decrypt(zipCrypto, chunk.subarray(0, HEADER_LENGTH));
|
|
1577
|
-
zipCrypto.password = null;
|
|
1578
|
-
|
|
1556
|
+
zipCrypto.password = zipCrypto.rawPassword = null;
|
|
1557
|
+
// verify the password with a branch-free comparison of the verification byte, mirroring
|
|
1558
|
+
// the constant-time AES HMAC signature check
|
|
1559
|
+
if ((decryptedHeader.at(-1) ^ zipCrypto.passwordVerification) != 0) {
|
|
1579
1560
|
throw new Error(ERR_INVALID_PASSWORD);
|
|
1580
1561
|
}
|
|
1581
1562
|
chunk = chunk.subarray(HEADER_LENGTH);
|
|
@@ -1592,21 +1573,22 @@
|
|
|
1592
1573
|
|
|
1593
1574
|
class ZipCryptoEncryptionStream extends TransformStream {
|
|
1594
1575
|
|
|
1595
|
-
constructor({ password, passwordVerification }) {
|
|
1576
|
+
constructor({ password, rawPassword, passwordVerification }) {
|
|
1596
1577
|
super({
|
|
1597
1578
|
start() {
|
|
1598
1579
|
Object.assign(this, {
|
|
1599
1580
|
password,
|
|
1581
|
+
rawPassword,
|
|
1600
1582
|
passwordVerification
|
|
1601
1583
|
});
|
|
1602
|
-
createKeys(this, password);
|
|
1584
|
+
createKeys(this, password, rawPassword);
|
|
1603
1585
|
},
|
|
1604
1586
|
transform(chunk, controller) {
|
|
1605
1587
|
const zipCrypto = this;
|
|
1606
1588
|
let output;
|
|
1607
1589
|
let offset;
|
|
1608
|
-
if (zipCrypto.password) {
|
|
1609
|
-
zipCrypto.password = null;
|
|
1590
|
+
if (zipCrypto.password || zipCrypto.rawPassword) {
|
|
1591
|
+
zipCrypto.password = zipCrypto.rawPassword = null;
|
|
1610
1592
|
const header = getRandomValues(new Uint8Array(HEADER_LENGTH));
|
|
1611
1593
|
header[HEADER_LENGTH - 1] = zipCrypto.passwordVerification;
|
|
1612
1594
|
output = new Uint8Array(chunk.length + header.length);
|
|
@@ -1641,25 +1623,31 @@
|
|
|
1641
1623
|
return output;
|
|
1642
1624
|
}
|
|
1643
1625
|
|
|
1644
|
-
function createKeys(target, password) {
|
|
1626
|
+
function createKeys(target, password, rawPassword) {
|
|
1645
1627
|
const keys = [0x12345678, 0x23456789, 0x34567890];
|
|
1646
1628
|
Object.assign(target, {
|
|
1647
1629
|
keys,
|
|
1648
1630
|
crcKey0: new Crc32(keys[0]),
|
|
1649
1631
|
crcKey2: new Crc32(keys[2])
|
|
1650
1632
|
});
|
|
1651
|
-
|
|
1652
|
-
|
|
1633
|
+
if (rawPassword) {
|
|
1634
|
+
for (let index = 0; index < rawPassword.length; index++) {
|
|
1635
|
+
updateKeys(target, rawPassword[index]);
|
|
1636
|
+
}
|
|
1637
|
+
} else {
|
|
1638
|
+
for (let index = 0; index < password.length; index++) {
|
|
1639
|
+
updateKeys(target, password.charCodeAt(index));
|
|
1640
|
+
}
|
|
1653
1641
|
}
|
|
1654
1642
|
}
|
|
1655
1643
|
|
|
1656
1644
|
function updateKeys(target, byte) {
|
|
1657
|
-
let [
|
|
1645
|
+
let [, key1] = target.keys;
|
|
1658
1646
|
target.crcKey0.append([byte]);
|
|
1659
|
-
key0 = ~target.crcKey0.get();
|
|
1647
|
+
const key0 = ~target.crcKey0.get();
|
|
1660
1648
|
key1 = getInt32(Math.imul(getInt32(key1 + getInt8(key0)), 134775813) + 1);
|
|
1661
1649
|
target.crcKey2.append([key1 >>> 24]);
|
|
1662
|
-
key2 = ~target.crcKey2.get();
|
|
1650
|
+
const key2 = ~target.crcKey2.get();
|
|
1663
1651
|
target.keys = [key0, key1, key2];
|
|
1664
1652
|
}
|
|
1665
1653
|
|
|
@@ -1706,6 +1694,7 @@
|
|
|
1706
1694
|
|
|
1707
1695
|
|
|
1708
1696
|
const ERR_INVALID_UNCOMPRESSED_SIZE = "Invalid uncompressed size";
|
|
1697
|
+
const ERR_INVALID_COMPRESSED_DATA = "Invalid compressed data";
|
|
1709
1698
|
const FORMAT_DEFLATE_RAW = "deflate-raw";
|
|
1710
1699
|
const FORMAT_DEFLATE64_RAW = "deflate64-raw";
|
|
1711
1700
|
|
|
@@ -1762,6 +1751,7 @@
|
|
|
1762
1751
|
}
|
|
1763
1752
|
if (compressed) {
|
|
1764
1753
|
readable = pipeThroughCommpressionStream(readable, useCompressionStream, { chunkSize, deflate64 }, DecompressionStream, DecompressionStreamZlib, DecompressionStream);
|
|
1754
|
+
readable = mapInflateStreamError(readable);
|
|
1765
1755
|
}
|
|
1766
1756
|
if ((!encrypted || zipCrypto) && signed) {
|
|
1767
1757
|
crc32Stream = new Crc32Stream();
|
|
@@ -1790,14 +1780,15 @@
|
|
|
1790
1780
|
function pipeThroughCommpressionStream(readable, useCompressionStream, options, CompressionStreamNative, CompressionStreamZlib, CompressionStream) {
|
|
1791
1781
|
const Stream = useCompressionStream && CompressionStreamNative ? CompressionStreamNative : CompressionStreamZlib || CompressionStream;
|
|
1792
1782
|
const format = options.deflate64 ? FORMAT_DEFLATE64_RAW : FORMAT_DEFLATE_RAW;
|
|
1783
|
+
let codecStream;
|
|
1793
1784
|
try {
|
|
1794
|
-
|
|
1785
|
+
codecStream = new Stream(format, options);
|
|
1795
1786
|
} catch (error) {
|
|
1796
1787
|
if (useCompressionStream) {
|
|
1797
1788
|
if (CompressionStreamZlib) {
|
|
1798
|
-
|
|
1789
|
+
codecStream = new CompressionStreamZlib(format, options);
|
|
1799
1790
|
} else if (CompressionStream) {
|
|
1800
|
-
|
|
1791
|
+
codecStream = new CompressionStream(format, options);
|
|
1801
1792
|
} else {
|
|
1802
1793
|
throw error;
|
|
1803
1794
|
}
|
|
@@ -1805,13 +1796,93 @@
|
|
|
1805
1796
|
throw error;
|
|
1806
1797
|
}
|
|
1807
1798
|
}
|
|
1808
|
-
|
|
1799
|
+
// The native CompressionStream/DecompressionStream and the pure-JS zlib port do not signal
|
|
1800
|
+
// backpressure on their writable side (their `ready` never pends), so a plain pipeThrough drains
|
|
1801
|
+
// the whole source into them and peak memory grows with the entry size. Awaiting each write()
|
|
1802
|
+
// paces the source to the codec's consumption rate, keeping streaming memory bounded. The WASM
|
|
1803
|
+
// codec already backpressures, so this is a no-op cost for it.
|
|
1804
|
+
return pipeThroughBackpressured(readable, codecStream);
|
|
1809
1805
|
}
|
|
1810
1806
|
|
|
1811
1807
|
function pipeThrough(readable, transformStream) {
|
|
1812
1808
|
return readable.pipeThrough(transformStream);
|
|
1813
1809
|
}
|
|
1814
1810
|
|
|
1811
|
+
// Like readable.pipeThrough(transformStream), but drives the writable side manually and awaits each
|
|
1812
|
+
// write() so that a codec which under-reports backpressure cannot pull the whole source into memory.
|
|
1813
|
+
// Errors propagate in both directions: a source error aborts the codec; a downstream cancel/error
|
|
1814
|
+
// (surfaced through the codec's writable rejecting) cancels the source.
|
|
1815
|
+
function pipeThroughBackpressured(readable, transformStream) {
|
|
1816
|
+
const writer = transformStream.writable.getWriter();
|
|
1817
|
+
const reader = readable.getReader();
|
|
1818
|
+
pump();
|
|
1819
|
+
return transformStream.readable;
|
|
1820
|
+
|
|
1821
|
+
async function pump() {
|
|
1822
|
+
try {
|
|
1823
|
+
for (; ;) {
|
|
1824
|
+
await writer.ready;
|
|
1825
|
+
const result = await reader.read();
|
|
1826
|
+
if (result.done) {
|
|
1827
|
+
await writer.close();
|
|
1828
|
+
break;
|
|
1829
|
+
}
|
|
1830
|
+
await writer.write(result.value);
|
|
1831
|
+
}
|
|
1832
|
+
} catch (error) {
|
|
1833
|
+
await abort(writer, error);
|
|
1834
|
+
await cancel(reader, error);
|
|
1835
|
+
}
|
|
1836
|
+
}
|
|
1837
|
+
}
|
|
1838
|
+
|
|
1839
|
+
async function abort(writer, error) {
|
|
1840
|
+
try {
|
|
1841
|
+
await writer.abort(error);
|
|
1842
|
+
} catch {
|
|
1843
|
+
// the writable may already be errored/closed
|
|
1844
|
+
}
|
|
1845
|
+
}
|
|
1846
|
+
|
|
1847
|
+
async function cancel(reader, error) {
|
|
1848
|
+
try {
|
|
1849
|
+
await reader.cancel(error);
|
|
1850
|
+
} catch {
|
|
1851
|
+
// the readable may already be errored/closed
|
|
1852
|
+
}
|
|
1853
|
+
}
|
|
1854
|
+
|
|
1855
|
+
// DecompressionStream implementations can fail with a message-less TypeError on malformed
|
|
1856
|
+
// input; give these errors an identifiable message (errors raised by the other stages of
|
|
1857
|
+
// the pipeline, e.g. ERR_INVALID_PASSWORD, always carry a message and pass through as-is)
|
|
1858
|
+
function mapInflateStreamError(readable) {
|
|
1859
|
+
const reader = readable.getReader();
|
|
1860
|
+
return new ReadableStream({
|
|
1861
|
+
async pull(controller) {
|
|
1862
|
+
let result;
|
|
1863
|
+
try {
|
|
1864
|
+
result = await reader.read();
|
|
1865
|
+
} catch (error) {
|
|
1866
|
+
if (error && error.message) {
|
|
1867
|
+
throw error;
|
|
1868
|
+
}
|
|
1869
|
+
const mappedError = new Error(ERR_INVALID_COMPRESSED_DATA);
|
|
1870
|
+
mappedError.cause = error;
|
|
1871
|
+
throw mappedError;
|
|
1872
|
+
}
|
|
1873
|
+
const { value, done } = result;
|
|
1874
|
+
if (done) {
|
|
1875
|
+
controller.close();
|
|
1876
|
+
} else {
|
|
1877
|
+
controller.enqueue(value);
|
|
1878
|
+
}
|
|
1879
|
+
},
|
|
1880
|
+
cancel(reason) {
|
|
1881
|
+
return reader.cancel(reason);
|
|
1882
|
+
}
|
|
1883
|
+
});
|
|
1884
|
+
}
|
|
1885
|
+
|
|
1815
1886
|
/*
|
|
1816
1887
|
Copyright (c) 2022 Gildas Lormeau. All rights reserved.
|
|
1817
1888
|
|
|
@@ -1841,6 +1912,7 @@
|
|
|
1841
1912
|
*/
|
|
1842
1913
|
|
|
1843
1914
|
|
|
1915
|
+
const DEFAULT_CHUNK_SIZE$1 = 64 * 1024;
|
|
1844
1916
|
const MESSAGE_EVENT_TYPE = "message";
|
|
1845
1917
|
const MESSAGE_START = "start";
|
|
1846
1918
|
const MESSAGE_PULL = "pull";
|
|
@@ -1909,6 +1981,9 @@
|
|
|
1909
1981
|
|
|
1910
1982
|
constructor(chunkSize) {
|
|
1911
1983
|
let pendingChunk;
|
|
1984
|
+
if (!(chunkSize >= 1)) {
|
|
1985
|
+
chunkSize = DEFAULT_CHUNK_SIZE$1;
|
|
1986
|
+
}
|
|
1912
1987
|
super({
|
|
1913
1988
|
transform,
|
|
1914
1989
|
flush(controller) {
|
|
@@ -1926,12 +2001,12 @@
|
|
|
1926
2001
|
chunk = newChunk;
|
|
1927
2002
|
pendingChunk = null;
|
|
1928
2003
|
}
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
pendingChunk = chunk;
|
|
2004
|
+
let offset = 0;
|
|
2005
|
+
while (chunk.length - offset > chunkSize) {
|
|
2006
|
+
controller.enqueue(chunk.slice(offset, offset + chunkSize));
|
|
2007
|
+
offset += chunkSize;
|
|
1934
2008
|
}
|
|
2009
|
+
pendingChunk = offset ? chunk.slice(offset) : chunk;
|
|
1935
2010
|
}
|
|
1936
2011
|
}
|
|
1937
2012
|
}
|
|
@@ -1966,8 +2041,10 @@
|
|
|
1966
2041
|
|
|
1967
2042
|
|
|
1968
2043
|
const MODULE_WORKER_OPTIONS = { type: "module" };
|
|
2044
|
+
const ERROR_EVENT_TYPE = "error";
|
|
2045
|
+
const MESSAGE_ERROR_EVENT_TYPE = "messageerror";
|
|
1969
2046
|
|
|
1970
|
-
let webWorkerSupported, webWorkerURI, webWorkerOptions;
|
|
2047
|
+
let webWorkerSupported, webWorkerSource, webWorkerURI, webWorkerOptions;
|
|
1971
2048
|
let transferStreamsSupported = true;
|
|
1972
2049
|
try {
|
|
1973
2050
|
transferStreamsSupported = typeof structuredClone == FUNCTION_TYPE && structuredClone(new DOMException("", "AbortError")).code !== UNDEFINED_VALUE;
|
|
@@ -1986,8 +2063,9 @@
|
|
|
1986
2063
|
const { signal } = streamOptions;
|
|
1987
2064
|
Object.assign(workerData, {
|
|
1988
2065
|
busy: true,
|
|
2066
|
+
generation: (workerData.generation || 0) + 1,
|
|
1989
2067
|
readable: readable
|
|
1990
|
-
.pipeThrough(new ChunkStream(config
|
|
2068
|
+
.pipeThrough(new ChunkStream(getChunkSize(config)))
|
|
1991
2069
|
.pipeThrough(new ProgressWatcherStream(streamOptions), { signal }),
|
|
1992
2070
|
writable,
|
|
1993
2071
|
options: Object.assign({}, options),
|
|
@@ -2010,15 +2088,17 @@
|
|
|
2010
2088
|
});
|
|
2011
2089
|
},
|
|
2012
2090
|
onTaskFinished() {
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2091
|
+
if (workerData.busy) {
|
|
2092
|
+
const { resolveTerminated } = workerData;
|
|
2093
|
+
if (resolveTerminated) {
|
|
2094
|
+
workerData.resolveTerminated = null;
|
|
2095
|
+
workerData.terminated = true;
|
|
2096
|
+
workerData.worker.terminate();
|
|
2097
|
+
resolveTerminated();
|
|
2098
|
+
}
|
|
2099
|
+
workerData.busy = false;
|
|
2100
|
+
onTaskFinished(workerData);
|
|
2019
2101
|
}
|
|
2020
|
-
workerData.busy = false;
|
|
2021
|
-
onTaskFinished(workerData);
|
|
2022
2102
|
}
|
|
2023
2103
|
});
|
|
2024
2104
|
if (webWorkerSupported === UNDEFINED_VALUE) {
|
|
@@ -2087,6 +2167,7 @@
|
|
|
2087
2167
|
}
|
|
2088
2168
|
Object.assign(workerData, {
|
|
2089
2169
|
worker,
|
|
2170
|
+
terminated: false,
|
|
2090
2171
|
interface: {
|
|
2091
2172
|
run: () => runWebWorker(workerData, { chunkSize, wasmURI, baseURI })
|
|
2092
2173
|
}
|
|
@@ -2102,7 +2183,15 @@
|
|
|
2102
2183
|
try {
|
|
2103
2184
|
await initModule$1(config);
|
|
2104
2185
|
} catch {
|
|
2105
|
-
|
|
2186
|
+
// The WASM module failed to load. Fall back to the native CompressionStream only if the
|
|
2187
|
+
// zlib codec that would otherwise run depends on that module; a self-contained codec
|
|
2188
|
+
// supplied through config (e.g. the pure-JS port) stays usable and is kept as requested.
|
|
2189
|
+
const ZlibStream = options.codecType.startsWith(CODEC_DEFLATE) ?
|
|
2190
|
+
config.CompressionStreamZlib :
|
|
2191
|
+
config.DecompressionStreamZlib;
|
|
2192
|
+
if (!ZlibStream || ZlibStream.requiresModule) {
|
|
2193
|
+
options.useCompressionStream = true;
|
|
2194
|
+
}
|
|
2106
2195
|
}
|
|
2107
2196
|
}
|
|
2108
2197
|
codecStream = new CodecStream(options, config);
|
|
@@ -2141,37 +2230,85 @@
|
|
|
2141
2230
|
result
|
|
2142
2231
|
});
|
|
2143
2232
|
const { readable, options } = workerData;
|
|
2144
|
-
const { writable, closed } = watchClosedStream(workerData.writable);
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2233
|
+
const { writable, closed, abortPipe } = watchClosedStream(workerData.writable);
|
|
2234
|
+
let streamsTransferred;
|
|
2235
|
+
try {
|
|
2236
|
+
streamsTransferred = sendMessage({
|
|
2237
|
+
type: MESSAGE_START,
|
|
2238
|
+
options,
|
|
2239
|
+
config,
|
|
2240
|
+
readable,
|
|
2241
|
+
writable
|
|
2242
|
+
}, workerData);
|
|
2243
|
+
} catch (error) {
|
|
2244
|
+
abortPipe();
|
|
2245
|
+
try {
|
|
2246
|
+
await closed;
|
|
2247
|
+
} catch {
|
|
2248
|
+
// ignored
|
|
2249
|
+
}
|
|
2250
|
+
workerData.onTaskFinished();
|
|
2251
|
+
throw error;
|
|
2252
|
+
}
|
|
2152
2253
|
if (!streamsTransferred) {
|
|
2153
2254
|
Object.assign(workerData, {
|
|
2154
2255
|
reader: readable.getReader(),
|
|
2155
2256
|
writer: writable.getWriter()
|
|
2156
2257
|
});
|
|
2157
2258
|
}
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
await
|
|
2259
|
+
try {
|
|
2260
|
+
const resultValue = await result;
|
|
2261
|
+
await closeWritable();
|
|
2262
|
+
await closed;
|
|
2263
|
+
return resultValue;
|
|
2264
|
+
} catch (error) {
|
|
2265
|
+
await closeWritable();
|
|
2266
|
+
// unblock the pipe watcher if the worker died before closing its end of the stream
|
|
2267
|
+
abortPipe();
|
|
2268
|
+
try {
|
|
2269
|
+
await closed;
|
|
2270
|
+
} catch {
|
|
2271
|
+
// ignored
|
|
2272
|
+
}
|
|
2273
|
+
throw error;
|
|
2274
|
+
}
|
|
2275
|
+
|
|
2276
|
+
async function closeWritable() {
|
|
2277
|
+
if (!streamsTransferred && !writable.locked) {
|
|
2278
|
+
try {
|
|
2279
|
+
await writable.getWriter().close();
|
|
2280
|
+
} catch {
|
|
2281
|
+
// ignored
|
|
2282
|
+
}
|
|
2283
|
+
}
|
|
2161
2284
|
}
|
|
2162
|
-
await closed;
|
|
2163
|
-
return resultValue;
|
|
2164
2285
|
}
|
|
2165
2286
|
|
|
2166
2287
|
function watchClosedStream(writableSource) {
|
|
2288
|
+
const abortController = new AbortController();
|
|
2167
2289
|
const { writable, readable } = new TransformStream();
|
|
2168
|
-
const closed = readable.pipeTo(writableSource, { preventClose: true });
|
|
2169
|
-
|
|
2290
|
+
const closed = readable.pipeTo(writableSource, { preventClose: true, preventAbort: true, signal: abortController.signal });
|
|
2291
|
+
// the pipe can fail before `closed` is awaited (e.g. the destination write fails);
|
|
2292
|
+
// mark the rejection as handled so it cannot kill the process in the meantime
|
|
2293
|
+
closed.catch(() => { });
|
|
2294
|
+
return { writable, closed, abortPipe: () => abortController.abort() };
|
|
2295
|
+
}
|
|
2296
|
+
|
|
2297
|
+
function terminateWorker$1(workerData) {
|
|
2298
|
+
const { worker } = workerData;
|
|
2299
|
+
if (worker) {
|
|
2300
|
+
try {
|
|
2301
|
+
worker.terminate();
|
|
2302
|
+
} catch {
|
|
2303
|
+
// ignored
|
|
2304
|
+
}
|
|
2305
|
+
}
|
|
2306
|
+
workerData.interface = null;
|
|
2170
2307
|
}
|
|
2171
2308
|
|
|
2172
2309
|
function getWebWorker(url, baseURI, workerData, isModuleType, useBlobURI = true) {
|
|
2173
2310
|
let worker, resolvedURI, resolvedOptions;
|
|
2174
|
-
if (webWorkerURI === UNDEFINED_VALUE) {
|
|
2311
|
+
if (webWorkerURI === UNDEFINED_VALUE || webWorkerSource !== url) {
|
|
2175
2312
|
// deno-lint-ignore valid-typeof
|
|
2176
2313
|
const isFunctionURI = typeof url == FUNCTION_TYPE;
|
|
2177
2314
|
if (isFunctionURI) {
|
|
@@ -2228,16 +2365,36 @@
|
|
|
2228
2365
|
}
|
|
2229
2366
|
}
|
|
2230
2367
|
}
|
|
2368
|
+
webWorkerSource = url;
|
|
2231
2369
|
webWorkerURI = resolvedURI;
|
|
2232
2370
|
webWorkerOptions = resolvedOptions;
|
|
2233
2371
|
} else {
|
|
2234
2372
|
worker = new Worker(webWorkerURI, webWorkerOptions);
|
|
2235
2373
|
}
|
|
2236
2374
|
worker.addEventListener(MESSAGE_EVENT_TYPE, event => onMessage(event, workerData));
|
|
2375
|
+
worker.addEventListener(ERROR_EVENT_TYPE, event => onWorkerError(event, workerData));
|
|
2376
|
+
worker.addEventListener(MESSAGE_ERROR_EVENT_TYPE, event => onWorkerError(event, workerData));
|
|
2237
2377
|
return worker;
|
|
2238
2378
|
}
|
|
2239
2379
|
|
|
2240
|
-
function
|
|
2380
|
+
function onWorkerError(event, workerData) {
|
|
2381
|
+
if (event.preventDefault) {
|
|
2382
|
+
event.preventDefault();
|
|
2383
|
+
}
|
|
2384
|
+
const { rejectResult, writer, onTaskFinished } = workerData;
|
|
2385
|
+
// the worker is unusable (e.g. its script failed to load); terminate it and
|
|
2386
|
+
// fail the current task instead of letting it hang forever
|
|
2387
|
+
terminateWorker$1(workerData);
|
|
2388
|
+
if (rejectResult) {
|
|
2389
|
+
rejectResult(event.error || new Error(event.message || ERROR_EVENT_TYPE));
|
|
2390
|
+
if (writer) {
|
|
2391
|
+
writer.releaseLock();
|
|
2392
|
+
}
|
|
2393
|
+
onTaskFinished();
|
|
2394
|
+
}
|
|
2395
|
+
}
|
|
2396
|
+
|
|
2397
|
+
function sendMessage(message, { worker, writer, transferStreams }) {
|
|
2241
2398
|
try {
|
|
2242
2399
|
const { value, readable, writable } = message;
|
|
2243
2400
|
const transferables = [];
|
|
@@ -2271,14 +2428,16 @@
|
|
|
2271
2428
|
if (writer) {
|
|
2272
2429
|
writer.releaseLock();
|
|
2273
2430
|
}
|
|
2274
|
-
onTaskFinished();
|
|
2275
2431
|
throw error;
|
|
2276
2432
|
}
|
|
2277
2433
|
}
|
|
2278
2434
|
|
|
2279
2435
|
async function onMessage({ data }, workerData) {
|
|
2280
2436
|
const { type, value, messageId, result, error } = data;
|
|
2281
|
-
const { reader, writer, resolveResult, rejectResult, onTaskFinished } = workerData;
|
|
2437
|
+
const { reader, writer, resolveResult, rejectResult, onTaskFinished, generation } = workerData;
|
|
2438
|
+
// continuations below can settle after the worker slot has been reassigned to a new
|
|
2439
|
+
// task (e.g. a pending pull read failing late); they must not touch the new task
|
|
2440
|
+
const stale = () => workerData.generation != generation;
|
|
2282
2441
|
try {
|
|
2283
2442
|
if (error) {
|
|
2284
2443
|
const { message, stack, code, name, outputSize } = error;
|
|
@@ -2288,23 +2447,32 @@
|
|
|
2288
2447
|
} else {
|
|
2289
2448
|
if (type == MESSAGE_PULL) {
|
|
2290
2449
|
const { value, done } = await reader.read();
|
|
2291
|
-
|
|
2450
|
+
if (!stale()) {
|
|
2451
|
+
sendMessage({ type: MESSAGE_DATA, value, done, messageId }, workerData);
|
|
2452
|
+
}
|
|
2292
2453
|
}
|
|
2293
2454
|
if (type == MESSAGE_DATA) {
|
|
2294
2455
|
await writer.ready;
|
|
2295
2456
|
await writer.write(new Uint8Array(value));
|
|
2296
|
-
|
|
2457
|
+
if (!stale()) {
|
|
2458
|
+
sendMessage({ type: MESSAGE_ACK_DATA, messageId }, workerData);
|
|
2459
|
+
}
|
|
2297
2460
|
}
|
|
2298
2461
|
if (type == MESSAGE_CLOSE) {
|
|
2299
2462
|
close(null, result);
|
|
2300
2463
|
}
|
|
2301
2464
|
}
|
|
2302
2465
|
} catch (error) {
|
|
2303
|
-
|
|
2304
|
-
|
|
2466
|
+
if (!stale()) {
|
|
2467
|
+
terminateWorker$1(workerData);
|
|
2468
|
+
close(error);
|
|
2469
|
+
}
|
|
2305
2470
|
}
|
|
2306
2471
|
|
|
2307
2472
|
function close(error, result) {
|
|
2473
|
+
if (stale()) {
|
|
2474
|
+
return;
|
|
2475
|
+
}
|
|
2308
2476
|
if (error) {
|
|
2309
2477
|
rejectResult(error);
|
|
2310
2478
|
} else {
|
|
@@ -2348,6 +2516,8 @@
|
|
|
2348
2516
|
|
|
2349
2517
|
let pool = [];
|
|
2350
2518
|
const pendingRequests = [];
|
|
2519
|
+
let starvationTimeout;
|
|
2520
|
+
let starvationDelay;
|
|
2351
2521
|
|
|
2352
2522
|
let indexWorker = 0;
|
|
2353
2523
|
|
|
@@ -2374,14 +2544,20 @@
|
|
|
2374
2544
|
pool.push(workerData);
|
|
2375
2545
|
return new CodecWorker(workerData, stream, workerOptions, onTaskFinished);
|
|
2376
2546
|
} else {
|
|
2377
|
-
return new Promise(resolve =>
|
|
2547
|
+
return new Promise(resolve => {
|
|
2548
|
+
pendingRequests.push({ resolve, stream, workerOptions });
|
|
2549
|
+
starvationDelay = config.workerStarvationTimeout;
|
|
2550
|
+
armStarvationTimeout();
|
|
2551
|
+
});
|
|
2378
2552
|
}
|
|
2379
2553
|
}
|
|
2380
2554
|
|
|
2381
2555
|
function onTaskFinished(workerData) {
|
|
2556
|
+
clearStarvationTimeout();
|
|
2382
2557
|
if (pendingRequests.length) {
|
|
2383
2558
|
const [{ resolve, stream, workerOptions }] = pendingRequests.splice(0, 1);
|
|
2384
2559
|
resolve(new CodecWorker(workerData, stream, workerOptions, onTaskFinished));
|
|
2560
|
+
armStarvationTimeout();
|
|
2385
2561
|
} else if (workerData.worker) {
|
|
2386
2562
|
clearTerminateTimeout(workerData);
|
|
2387
2563
|
terminateWorker(workerData, workerOptions);
|
|
@@ -2391,6 +2567,34 @@
|
|
|
2391
2567
|
}
|
|
2392
2568
|
}
|
|
2393
2569
|
|
|
2570
|
+
function armStarvationTimeout() {
|
|
2571
|
+
if (!starvationTimeout && pendingRequests.length && Number.isFinite(starvationDelay) && starvationDelay >= 0) {
|
|
2572
|
+
starvationTimeout = setTimeout(onWorkerStarvation, starvationDelay);
|
|
2573
|
+
}
|
|
2574
|
+
}
|
|
2575
|
+
|
|
2576
|
+
function clearStarvationTimeout() {
|
|
2577
|
+
if (starvationTimeout) {
|
|
2578
|
+
clearTimeout(starvationTimeout);
|
|
2579
|
+
starvationTimeout = null;
|
|
2580
|
+
}
|
|
2581
|
+
}
|
|
2582
|
+
|
|
2583
|
+
function onWorkerStarvation() {
|
|
2584
|
+
starvationTimeout = null;
|
|
2585
|
+
if (pendingRequests.length) {
|
|
2586
|
+
const [{ resolve, stream, workerOptions }] = pendingRequests.splice(0, 1);
|
|
2587
|
+
const inlineWorkerOptions = Object.assign({}, workerOptions, { useWebWorkers: false, workerURI: UNDEFINED_VALUE });
|
|
2588
|
+
resolve(new CodecWorker({}, stream, inlineWorkerOptions, onInlineTaskFinished));
|
|
2589
|
+
armStarvationTimeout();
|
|
2590
|
+
}
|
|
2591
|
+
}
|
|
2592
|
+
|
|
2593
|
+
function onInlineTaskFinished() {
|
|
2594
|
+
clearStarvationTimeout();
|
|
2595
|
+
armStarvationTimeout();
|
|
2596
|
+
}
|
|
2597
|
+
|
|
2394
2598
|
function terminateWorker(workerData, workerOptions) {
|
|
2395
2599
|
const { config } = workerOptions;
|
|
2396
2600
|
const { terminateWorkerTimeout } = config;
|
|
@@ -2461,6 +2665,7 @@
|
|
|
2461
2665
|
|
|
2462
2666
|
const CONTENT_TYPE_TEXT_PLAIN = "text/plain";
|
|
2463
2667
|
const HTTP_HEADER_CONTENT_LENGTH = "Content-Length";
|
|
2668
|
+
const HTTP_HEADER_CONTENT_ENCODING = "Content-Encoding";
|
|
2464
2669
|
const HTTP_HEADER_CONTENT_RANGE = "Content-Range";
|
|
2465
2670
|
const HTTP_HEADER_ACCEPT_RANGES = "Accept-Ranges";
|
|
2466
2671
|
const HTTP_HEADER_RANGE = "Range";
|
|
@@ -2585,7 +2790,7 @@
|
|
|
2585
2790
|
|
|
2586
2791
|
writeUint8Array(array) {
|
|
2587
2792
|
const writer = this;
|
|
2588
|
-
let indexArray
|
|
2793
|
+
let indexArray;
|
|
2589
2794
|
let dataString = writer.pending;
|
|
2590
2795
|
const delta = writer.pending.length;
|
|
2591
2796
|
writer.pending = "";
|
|
@@ -2595,12 +2800,10 @@
|
|
|
2595
2800
|
for (; indexArray < array.length; indexArray++) {
|
|
2596
2801
|
writer.pending += String.fromCharCode(array[indexArray]);
|
|
2597
2802
|
}
|
|
2598
|
-
if (dataString.length) {
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
writer.pending += dataString;
|
|
2603
|
-
}
|
|
2803
|
+
if (dataString.length > 2) {
|
|
2804
|
+
writer.data += btoa(dataString);
|
|
2805
|
+
} else {
|
|
2806
|
+
writer.pending = dataString + writer.pending;
|
|
2604
2807
|
}
|
|
2605
2808
|
}
|
|
2606
2809
|
|
|
@@ -2647,6 +2850,9 @@
|
|
|
2647
2850
|
}
|
|
2648
2851
|
});
|
|
2649
2852
|
writer.blob = new Response(transformStream.readable, { headers }).blob();
|
|
2853
|
+
// mark early rejections (e.g. aborted pipe) as handled; awaiting getData() still
|
|
2854
|
+
// surfaces them
|
|
2855
|
+
writer.blob.catch(() => { });
|
|
2650
2856
|
}
|
|
2651
2857
|
|
|
2652
2858
|
getData() {
|
|
@@ -2731,7 +2937,8 @@
|
|
|
2731
2937
|
preventHeadRequest,
|
|
2732
2938
|
useRangeHeader,
|
|
2733
2939
|
forceRangeRequests,
|
|
2734
|
-
combineSizeEocd
|
|
2940
|
+
combineSizeEocd,
|
|
2941
|
+
fetch
|
|
2735
2942
|
} = options;
|
|
2736
2943
|
options = Object.assign({}, options);
|
|
2737
2944
|
delete options.preventHeadRequest;
|
|
@@ -2739,13 +2946,15 @@
|
|
|
2739
2946
|
delete options.forceRangeRequests;
|
|
2740
2947
|
delete options.combineSizeEocd;
|
|
2741
2948
|
delete options.useXHR;
|
|
2949
|
+
delete options.fetch;
|
|
2742
2950
|
Object.assign(httpReader, {
|
|
2743
2951
|
url,
|
|
2744
2952
|
options,
|
|
2745
2953
|
preventHeadRequest,
|
|
2746
2954
|
useRangeHeader,
|
|
2747
2955
|
forceRangeRequests,
|
|
2748
|
-
combineSizeEocd
|
|
2956
|
+
combineSizeEocd,
|
|
2957
|
+
fetch
|
|
2749
2958
|
});
|
|
2750
2959
|
}
|
|
2751
2960
|
|
|
@@ -2764,7 +2973,10 @@
|
|
|
2764
2973
|
throw new Error(ERR_HTTP_RANGE);
|
|
2765
2974
|
} else {
|
|
2766
2975
|
if (combineSizeEocd) {
|
|
2767
|
-
|
|
2976
|
+
const eocdCache = new Uint8Array(await response.arrayBuffer());
|
|
2977
|
+
if (response.status == 206 && eocdCache.length == END_OF_CENTRAL_DIR_LENGTH) {
|
|
2978
|
+
httpReader.eocdCache = eocdCache;
|
|
2979
|
+
}
|
|
2768
2980
|
}
|
|
2769
2981
|
let contentSize;
|
|
2770
2982
|
const contentRangeHeader = response.headers.get(HTTP_HEADER_CONTENT_RANGE);
|
|
@@ -2810,7 +3022,18 @@
|
|
|
2810
3022
|
if (response.status != 206) {
|
|
2811
3023
|
throw new Error(ERR_HTTP_RANGE);
|
|
2812
3024
|
}
|
|
2813
|
-
|
|
3025
|
+
const contentRangeHeader = response.headers.get(HTTP_HEADER_CONTENT_RANGE);
|
|
3026
|
+
if (contentRangeHeader) {
|
|
3027
|
+
const rangeStart = Number(contentRangeHeader.trim().split(/[\s-]+/)[1]);
|
|
3028
|
+
if (!Number.isNaN(rangeStart) && rangeStart != index) {
|
|
3029
|
+
throw new Error(ERR_HTTP_RANGE);
|
|
3030
|
+
}
|
|
3031
|
+
}
|
|
3032
|
+
const data = new Uint8Array(await response.arrayBuffer());
|
|
3033
|
+
if (data.length != length) {
|
|
3034
|
+
throw new Error(ERR_HTTP_RANGE);
|
|
3035
|
+
}
|
|
3036
|
+
return data;
|
|
2814
3037
|
}
|
|
2815
3038
|
} else {
|
|
2816
3039
|
const { data } = httpReader;
|
|
@@ -2847,9 +3070,9 @@
|
|
|
2847
3070
|
async function getRequestData(httpReader, sendRequest) {
|
|
2848
3071
|
const response = await sendRequest(HTTP_METHOD_GET, httpReader, getHeaders(httpReader));
|
|
2849
3072
|
httpReader.data = new Uint8Array(await response.arrayBuffer());
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
3073
|
+
// the downloaded content is authoritative, e.g. the Content-Length response header
|
|
3074
|
+
// of the HEAD request can be the encoded size when the content is compressed
|
|
3075
|
+
httpReader.size = httpReader.data.length;
|
|
2853
3076
|
}
|
|
2854
3077
|
|
|
2855
3078
|
async function getContentLength(httpReader, sendRequest, getRequestData) {
|
|
@@ -2858,7 +3081,7 @@
|
|
|
2858
3081
|
} else {
|
|
2859
3082
|
const response = await sendRequest(HTTP_METHOD_HEAD, httpReader, getHeaders(httpReader));
|
|
2860
3083
|
const contentLength = response.headers.get(HTTP_HEADER_CONTENT_LENGTH);
|
|
2861
|
-
if (contentLength) {
|
|
3084
|
+
if (contentLength && !response.headers.get(HTTP_HEADER_CONTENT_ENCODING)) {
|
|
2862
3085
|
httpReader.size = Number(contentLength);
|
|
2863
3086
|
} else {
|
|
2864
3087
|
await getRequestData(httpReader, httpReader.options);
|
|
@@ -2866,8 +3089,8 @@
|
|
|
2866
3089
|
}
|
|
2867
3090
|
}
|
|
2868
3091
|
|
|
2869
|
-
async function sendFetchRequest(method, { options, url }, headers) {
|
|
2870
|
-
const response = await
|
|
3092
|
+
async function sendFetchRequest(method, { fetch: fetchFunction = fetch, options, url }, headers) {
|
|
3093
|
+
const response = await fetchFunction(url, Object.assign({}, options, { method, headers }));
|
|
2871
3094
|
if (response.status < 400) {
|
|
2872
3095
|
return response;
|
|
2873
3096
|
} else {
|
|
@@ -2913,7 +3136,8 @@
|
|
|
2913
3136
|
super();
|
|
2914
3137
|
Object.assign(this, {
|
|
2915
3138
|
url,
|
|
2916
|
-
|
|
3139
|
+
// an explicit fetch implementation takes precedence over useXHR
|
|
3140
|
+
reader: options.useXHR && !options.fetch ? new XHRReader(url, options) : new FetchReader(url, options)
|
|
2917
3141
|
});
|
|
2918
3142
|
}
|
|
2919
3143
|
|
|
@@ -2938,8 +3162,7 @@
|
|
|
2938
3162
|
class HttpRangeReader extends HttpReader {
|
|
2939
3163
|
|
|
2940
3164
|
constructor(url, options = {}) {
|
|
2941
|
-
options
|
|
2942
|
-
super(url, options);
|
|
3165
|
+
super(url, Object.assign({}, options, { useRangeHeader: true }));
|
|
2943
3166
|
}
|
|
2944
3167
|
}
|
|
2945
3168
|
|
|
@@ -3013,7 +3236,7 @@
|
|
|
3013
3236
|
reader.lastDiskNumber = 0;
|
|
3014
3237
|
reader.lastDiskOffset = 0;
|
|
3015
3238
|
await Promise.all(readers.map(async (diskReader, indexDiskReader) => {
|
|
3016
|
-
await diskReader
|
|
3239
|
+
await initStream(diskReader);
|
|
3017
3240
|
if (indexDiskReader != readers.length - 1) {
|
|
3018
3241
|
reader.lastDiskOffset += diskReader.size;
|
|
3019
3242
|
}
|
|
@@ -3097,14 +3320,26 @@
|
|
|
3097
3320
|
writer.diskOffset += diskSourceWriter.size;
|
|
3098
3321
|
writer.diskNumber++;
|
|
3099
3322
|
diskWriter = null;
|
|
3100
|
-
|
|
3323
|
+
// the next disk is not opened yet but its space is available; leaving a
|
|
3324
|
+
// stale value here would force a new disk for every subsequent write
|
|
3325
|
+
writer.availableSize = writer.maxSize;
|
|
3326
|
+
if (chunk.length > availableSize) {
|
|
3327
|
+
await this.write(chunk.subarray(availableSize));
|
|
3328
|
+
}
|
|
3101
3329
|
} else {
|
|
3102
3330
|
await writeChunk(chunk);
|
|
3103
3331
|
}
|
|
3104
3332
|
},
|
|
3105
3333
|
async close() {
|
|
3106
|
-
|
|
3107
|
-
|
|
3334
|
+
if (diskWriter) {
|
|
3335
|
+
await diskWriter.ready;
|
|
3336
|
+
await closeDisk();
|
|
3337
|
+
}
|
|
3338
|
+
},
|
|
3339
|
+
async abort(reason) {
|
|
3340
|
+
if (diskWriter) {
|
|
3341
|
+
await diskWriter.abort(reason);
|
|
3342
|
+
}
|
|
3108
3343
|
}
|
|
3109
3344
|
});
|
|
3110
3345
|
Object.defineProperty(writer, PROPERTY_NAME_WRITABLE, {
|
|
@@ -3119,7 +3354,6 @@
|
|
|
3119
3354
|
await diskWriter.ready;
|
|
3120
3355
|
await diskWriter.write(chunk);
|
|
3121
3356
|
diskSourceWriter.size += chunkLength;
|
|
3122
|
-
writer.size += chunkLength;
|
|
3123
3357
|
writer.availableSize -= chunkLength;
|
|
3124
3358
|
}
|
|
3125
3359
|
}
|
|
@@ -3219,7 +3453,7 @@
|
|
|
3219
3453
|
|
|
3220
3454
|
/* global TextDecoder */
|
|
3221
3455
|
|
|
3222
|
-
const CP437 = "\0☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼ !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~⌂ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■
|
|
3456
|
+
const CP437 = "\0☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼ !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~⌂ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ ".split("");
|
|
3223
3457
|
const VALID_CP437 = CP437.length == 256;
|
|
3224
3458
|
|
|
3225
3459
|
function decodeCP437(stringValue) {
|
|
@@ -3267,7 +3501,8 @@
|
|
|
3267
3501
|
if (encoding && encoding.trim().toLowerCase() == "cp437") {
|
|
3268
3502
|
return decodeCP437(value);
|
|
3269
3503
|
} else {
|
|
3270
|
-
|
|
3504
|
+
// ignoreBOM keeps a leading U+FEFF in filenames/comments instead of dropping it
|
|
3505
|
+
return new TextDecoder(encoding, { ignoreBOM: true }).decode(value);
|
|
3271
3506
|
}
|
|
3272
3507
|
}
|
|
3273
3508
|
|
|
@@ -3444,6 +3679,7 @@
|
|
|
3444
3679
|
const OPTION_CHECK_PASSWORD_ONLY = "checkPasswordOnly";
|
|
3445
3680
|
const OPTION_CHECK_OVERLAPPING_ENTRY_ONLY = "checkOverlappingEntryOnly";
|
|
3446
3681
|
const OPTION_CHECK_OVERLAPPING_ENTRY = "checkOverlappingEntry";
|
|
3682
|
+
const OPTION_CHECK_AMBIGUITY = "checkAmbiguity";
|
|
3447
3683
|
const OPTION_CHECK_SIGNATURE = "checkSignature";
|
|
3448
3684
|
const OPTION_USE_WEB_WORKERS = "useWebWorkers";
|
|
3449
3685
|
const OPTION_USE_COMPRESSION_STREAM = "useCompressionStream";
|
|
@@ -3501,12 +3737,16 @@
|
|
|
3501
3737
|
const ERR_EXTRAFIELD_ZIP64_NOT_FOUND = "Zip64 extra field not found";
|
|
3502
3738
|
const ERR_ENCRYPTED = "File contains encrypted entry";
|
|
3503
3739
|
const ERR_UNSUPPORTED_ENCRYPTION = "Encryption method not supported";
|
|
3504
|
-
const ERR_UNSUPPORTED_COMPRESSION = "Compression method not supported";
|
|
3740
|
+
const ERR_UNSUPPORTED_COMPRESSION$1 = "Compression method not supported";
|
|
3505
3741
|
const ERR_SPLIT_ZIP_FILE = "Split zip file";
|
|
3506
3742
|
const ERR_OVERLAPPING_ENTRY = "Overlapping entry found";
|
|
3743
|
+
const ERR_AMBIGUOUS_ARCHIVE = "Ambiguous archive";
|
|
3507
3744
|
const CHARSET_UTF8 = "utf-8";
|
|
3508
3745
|
const PROPERTY_NAME_UTF8_SUFFIX = "UTF8";
|
|
3509
3746
|
const CHARSET_CP437 = "cp437";
|
|
3747
|
+
// bits of the general purpose flag that change how an entry is interpreted; the level bits (1-2) are excluded
|
|
3748
|
+
// because they are informative only
|
|
3749
|
+
const BITFLAG_AMBIGUITY_MASK = BITFLAG_ENCRYPTED | BITFLAG_DATA_DESCRIPTOR | BITFLAG_LANG_ENCODING_FLAG;
|
|
3510
3750
|
const ZIP64_PROPERTIES = [
|
|
3511
3751
|
[PROPERTY_NAME_UNCOMPRESSED_SIZE, MAX_32_BITS],
|
|
3512
3752
|
[PROPERTY_NAME_COMPRESSED_SIZE, MAX_32_BITS],
|
|
@@ -3531,7 +3771,7 @@
|
|
|
3531
3771
|
reader: new GenericReader(reader),
|
|
3532
3772
|
options,
|
|
3533
3773
|
config: getConfiguration(),
|
|
3534
|
-
readRanges:
|
|
3774
|
+
readRanges: new Map()
|
|
3535
3775
|
});
|
|
3536
3776
|
}
|
|
3537
3777
|
|
|
@@ -3564,21 +3804,30 @@
|
|
|
3564
3804
|
const commentOffset = endOfDirectoryInfo.offset;
|
|
3565
3805
|
const commentLength = getUint16(endOfDirectoryView, 20);
|
|
3566
3806
|
const appendedDataOffset = commentOffset + END_OF_CENTRAL_DIR_LENGTH + commentLength;
|
|
3807
|
+
const checkAmbiguity = getOptionValue$1(zipReader, options, OPTION_CHECK_AMBIGUITY);
|
|
3808
|
+
if (checkAmbiguity && appendedDataOffset != reader.size) {
|
|
3809
|
+
throwAmbiguousArchive("appended data");
|
|
3810
|
+
}
|
|
3567
3811
|
let lastDiskNumber = getUint16(endOfDirectoryView, 4);
|
|
3568
3812
|
const expectedLastDiskNumber = reader.lastDiskNumber || 0;
|
|
3569
3813
|
let diskNumber = getUint16(endOfDirectoryView, 6);
|
|
3570
|
-
let filesLength = getUint16(endOfDirectoryView,
|
|
3814
|
+
let filesLength = getUint16(endOfDirectoryView, 10);
|
|
3571
3815
|
let prependedDataLength = 0;
|
|
3572
|
-
let startOffset
|
|
3816
|
+
let startOffset;
|
|
3817
|
+
let zip64EndOfDirectory;
|
|
3573
3818
|
if (directoryDataOffset == MAX_32_BITS || directoryDataLength == MAX_32_BITS || filesLength == MAX_16_BITS || diskNumber == MAX_16_BITS) {
|
|
3574
|
-
const endOfDirectoryLocatorArray =
|
|
3819
|
+
const endOfDirectoryLocatorArray = endOfDirectoryInfo.offset >= ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH ?
|
|
3820
|
+
await readUint8Array(reader, endOfDirectoryInfo.offset - ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH, ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH) :
|
|
3821
|
+
new Uint8Array();
|
|
3575
3822
|
const endOfDirectoryLocatorView = getDataView$1(endOfDirectoryLocatorArray);
|
|
3576
|
-
if (
|
|
3823
|
+
if (endOfDirectoryLocatorArray.length == ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH &&
|
|
3824
|
+
getUint32(endOfDirectoryLocatorView, 0) == ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIGNATURE) {
|
|
3577
3825
|
directoryDataOffset = getBigUint64(endOfDirectoryLocatorView, 8);
|
|
3578
3826
|
let endOfDirectoryArray = await readUint8Array(reader, directoryDataOffset, ZIP64_END_OF_CENTRAL_DIR_LENGTH, -1);
|
|
3579
3827
|
let endOfDirectoryView = getDataView$1(endOfDirectoryArray);
|
|
3580
|
-
const expectedDirectoryDataOffset = endOfDirectoryInfo.offset - ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH - ZIP64_END_OF_CENTRAL_DIR_LENGTH;
|
|
3581
|
-
if (getUint32(endOfDirectoryView, 0) != ZIP64_END_OF_CENTRAL_DIR_SIGNATURE &&
|
|
3828
|
+
const expectedDirectoryDataOffset = endOfDirectoryInfo.offset - ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH - ZIP64_END_OF_CENTRAL_DIR_LENGTH - (reader.lastDiskOffset || 0);
|
|
3829
|
+
if ((endOfDirectoryArray.length < ZIP64_END_OF_CENTRAL_DIR_LENGTH || getUint32(endOfDirectoryView, 0) != ZIP64_END_OF_CENTRAL_DIR_SIGNATURE) &&
|
|
3830
|
+
directoryDataOffset != expectedDirectoryDataOffset && expectedDirectoryDataOffset >= 0) {
|
|
3582
3831
|
const originalDirectoryDataOffset = directoryDataOffset;
|
|
3583
3832
|
directoryDataOffset = expectedDirectoryDataOffset;
|
|
3584
3833
|
if (directoryDataOffset > originalDirectoryDataOffset) {
|
|
@@ -3587,24 +3836,36 @@
|
|
|
3587
3836
|
endOfDirectoryArray = await readUint8Array(reader, directoryDataOffset, ZIP64_END_OF_CENTRAL_DIR_LENGTH, -1);
|
|
3588
3837
|
endOfDirectoryView = getDataView$1(endOfDirectoryArray);
|
|
3589
3838
|
}
|
|
3590
|
-
if (getUint32(endOfDirectoryView, 0) != ZIP64_END_OF_CENTRAL_DIR_SIGNATURE) {
|
|
3839
|
+
if (endOfDirectoryArray.length < ZIP64_END_OF_CENTRAL_DIR_LENGTH || getUint32(endOfDirectoryView, 0) != ZIP64_END_OF_CENTRAL_DIR_SIGNATURE) {
|
|
3591
3840
|
throw new Error(ERR_EOCDR_LOCATOR_ZIP64_NOT_FOUND);
|
|
3592
3841
|
}
|
|
3842
|
+
zip64EndOfDirectory = true;
|
|
3593
3843
|
if (lastDiskNumber == MAX_16_BITS) {
|
|
3594
3844
|
lastDiskNumber = getUint32(endOfDirectoryView, 16);
|
|
3845
|
+
} else if (checkAmbiguity && lastDiskNumber != getUint32(endOfDirectoryView, 16)) {
|
|
3846
|
+
throwAmbiguousArchive("mismatched zip64 end of central directory record");
|
|
3595
3847
|
}
|
|
3596
3848
|
if (diskNumber == MAX_16_BITS) {
|
|
3597
3849
|
diskNumber = getUint32(endOfDirectoryView, 20);
|
|
3850
|
+
} else if (checkAmbiguity && diskNumber != getUint32(endOfDirectoryView, 20)) {
|
|
3851
|
+
throwAmbiguousArchive("mismatched zip64 end of central directory record");
|
|
3598
3852
|
}
|
|
3599
3853
|
if (filesLength == MAX_16_BITS) {
|
|
3600
3854
|
filesLength = getBigUint64(endOfDirectoryView, 32);
|
|
3855
|
+
} else if (checkAmbiguity && filesLength != getBigUint64(endOfDirectoryView, 32)) {
|
|
3856
|
+
throwAmbiguousArchive("mismatched zip64 end of central directory record");
|
|
3601
3857
|
}
|
|
3602
3858
|
if (directoryDataLength == MAX_32_BITS) {
|
|
3603
3859
|
directoryDataLength = getBigUint64(endOfDirectoryView, 40);
|
|
3860
|
+
} else if (checkAmbiguity && directoryDataLength != getBigUint64(endOfDirectoryView, 40)) {
|
|
3861
|
+
throwAmbiguousArchive("mismatched zip64 end of central directory record");
|
|
3604
3862
|
}
|
|
3605
|
-
directoryDataOffset
|
|
3863
|
+
directoryDataOffset = getBigUint64(endOfDirectoryView, 48) + prependedDataLength;
|
|
3606
3864
|
}
|
|
3607
3865
|
}
|
|
3866
|
+
const declaredDirectoryDataLength = directoryDataLength;
|
|
3867
|
+
const centralDirectoryEndOffset = endOfDirectoryInfo.offset -
|
|
3868
|
+
(zip64EndOfDirectory ? ZIP64_END_OF_CENTRAL_DIR_LENGTH + ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH : 0);
|
|
3608
3869
|
if (directoryDataOffset >= reader.size) {
|
|
3609
3870
|
prependedDataLength = reader.size - directoryDataOffset - directoryDataLength - END_OF_CENTRAL_DIR_LENGTH;
|
|
3610
3871
|
directoryDataOffset = reader.size - directoryDataLength - END_OF_CENTRAL_DIR_LENGTH;
|
|
@@ -3619,8 +3880,11 @@
|
|
|
3619
3880
|
let directoryArray = await readUint8Array(reader, directoryDataOffset, directoryDataLength, diskNumber);
|
|
3620
3881
|
let directoryView = getDataView$1(directoryArray);
|
|
3621
3882
|
if (directoryDataLength) {
|
|
3622
|
-
|
|
3623
|
-
|
|
3883
|
+
if (directoryArray.length < 4) {
|
|
3884
|
+
throw new Error(ERR_BAD_FORMAT);
|
|
3885
|
+
}
|
|
3886
|
+
const expectedDirectoryDataOffset = centralDirectoryEndOffset - directoryDataLength - (reader.lastDiskOffset || 0);
|
|
3887
|
+
if (getUint32(directoryView, offset) != CENTRAL_FILE_HEADER_SIGNATURE && directoryDataOffset != expectedDirectoryDataOffset && diskNumber == lastDiskNumber) {
|
|
3624
3888
|
const originalDirectoryDataOffset = directoryDataOffset;
|
|
3625
3889
|
directoryDataOffset = expectedDirectoryDataOffset;
|
|
3626
3890
|
if (directoryDataOffset > originalDirectoryDataOffset) {
|
|
@@ -3630,8 +3894,8 @@
|
|
|
3630
3894
|
directoryView = getDataView$1(directoryArray);
|
|
3631
3895
|
}
|
|
3632
3896
|
}
|
|
3633
|
-
const expectedDirectoryDataLength =
|
|
3634
|
-
if (directoryDataLength != expectedDirectoryDataLength && expectedDirectoryDataLength >= 0) {
|
|
3897
|
+
const expectedDirectoryDataLength = centralDirectoryEndOffset - directoryDataOffset - (reader.lastDiskOffset || 0);
|
|
3898
|
+
if (directoryDataLength != expectedDirectoryDataLength && expectedDirectoryDataLength >= 0 && diskNumber == lastDiskNumber) {
|
|
3635
3899
|
directoryDataLength = expectedDirectoryDataLength;
|
|
3636
3900
|
directoryArray = await readUint8Array(reader, directoryDataOffset, directoryDataLength, diskNumber);
|
|
3637
3901
|
directoryView = getDataView$1(directoryArray);
|
|
@@ -3639,16 +3903,19 @@
|
|
|
3639
3903
|
if (directoryDataOffset < 0 || directoryDataOffset >= reader.size) {
|
|
3640
3904
|
throw new Error(ERR_BAD_FORMAT);
|
|
3641
3905
|
}
|
|
3906
|
+
startOffset = directoryDataOffset;
|
|
3642
3907
|
const filenameEncoding = getOptionValue$1(zipReader, options, OPTION_FILENAME_ENCODING);
|
|
3643
3908
|
const commentEncoding = getOptionValue$1(zipReader, options, OPTION_COMMENT_ENCODING);
|
|
3909
|
+
const filenames = checkAmbiguity ? new Set() : UNDEFINED_VALUE;
|
|
3910
|
+
let duplicateFilename;
|
|
3644
3911
|
for (let indexFile = 0; indexFile < filesLength; indexFile++) {
|
|
3645
3912
|
const fileEntry = new ZipEntry(reader, config, zipReader.options);
|
|
3646
|
-
if (getUint32(directoryView, offset) != CENTRAL_FILE_HEADER_SIGNATURE) {
|
|
3913
|
+
if (offset + CENTRAL_FILE_HEADER_LENGTH > directoryArray.length || getUint32(directoryView, offset) != CENTRAL_FILE_HEADER_SIGNATURE) {
|
|
3647
3914
|
throw new Error(ERR_CENTRAL_DIRECTORY_NOT_FOUND);
|
|
3648
3915
|
}
|
|
3649
3916
|
readCommonHeader(fileEntry, directoryView, offset + 6);
|
|
3650
3917
|
const languageEncodingFlag = Boolean(fileEntry.bitFlag.languageEncodingFlag);
|
|
3651
|
-
const filenameOffset = offset +
|
|
3918
|
+
const filenameOffset = offset + CENTRAL_FILE_HEADER_LENGTH;
|
|
3652
3919
|
const extraFieldOffset = filenameOffset + fileEntry.filenameLength;
|
|
3653
3920
|
const commentOffset = extraFieldOffset + fileEntry.extraFieldLength;
|
|
3654
3921
|
const versionMadeBy = getUint16(directoryView, offset + 4);
|
|
@@ -3669,7 +3936,7 @@
|
|
|
3669
3936
|
directory: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_DIR_MASK),
|
|
3670
3937
|
archive: Boolean(msdosAttributesRaw & FILE_ATTR_MSDOS_ARCHIVE_MASK)
|
|
3671
3938
|
};
|
|
3672
|
-
const offsetFileEntry = getUint32(directoryView, offset + 42)
|
|
3939
|
+
const offsetFileEntry = getUint32(directoryView, offset + 42);
|
|
3673
3940
|
const decode = getOptionValue$1(zipReader, options, OPTION_DECODE_TEXT) || decodeText;
|
|
3674
3941
|
const rawFilenameEncoding = filenameUTF8 ? CHARSET_UTF8 : filenameEncoding || CHARSET_CP437;
|
|
3675
3942
|
const rawCommentEncoding = commentUTF8 ? CHARSET_UTF8 : commentEncoding || CHARSET_CP437;
|
|
@@ -3682,6 +3949,7 @@
|
|
|
3682
3949
|
comment = decodeText(rawComment, rawCommentEncoding);
|
|
3683
3950
|
}
|
|
3684
3951
|
Object.assign(fileEntry, {
|
|
3952
|
+
index: indexFile,
|
|
3685
3953
|
versionMadeBy,
|
|
3686
3954
|
msDosCompatible,
|
|
3687
3955
|
compressedSize: 0,
|
|
@@ -3701,8 +3969,15 @@
|
|
|
3701
3969
|
filename,
|
|
3702
3970
|
comment
|
|
3703
3971
|
});
|
|
3704
|
-
startOffset = Math.max(offsetFileEntry, startOffset);
|
|
3705
3972
|
readCommonFooter(fileEntry, fileEntry, directoryView, offset + 6);
|
|
3973
|
+
fileEntry.offset += prependedDataLength;
|
|
3974
|
+
startOffset = Math.min(fileEntry.offset, startOffset);
|
|
3975
|
+
if (checkAmbiguity) {
|
|
3976
|
+
if (filenames.has(fileEntry.filename)) {
|
|
3977
|
+
duplicateFilename = true;
|
|
3978
|
+
}
|
|
3979
|
+
filenames.add(fileEntry.filename);
|
|
3980
|
+
}
|
|
3706
3981
|
const unixExternalUpper = (fileEntry.externalFileAttributes >> 16) & MAX_16_BITS;
|
|
3707
3982
|
if (fileEntry.unixMode === UNDEFINED_VALUE && (unixExternalUpper & (FILE_ATTR_UNIX_DEFAULT_MASK | FILE_ATTR_UNIX_EXECUTABLE_MASK | FILE_ATTR_UNIX_TYPE_DIR)) != 0) {
|
|
3708
3983
|
fileEntry.unixMode = unixExternalUpper;
|
|
@@ -3723,7 +3998,7 @@
|
|
|
3723
3998
|
internalFileAttribute: fileEntry.internalFileAttributes,
|
|
3724
3999
|
externalFileAttribute: fileEntry.externalFileAttributes,
|
|
3725
4000
|
executable,
|
|
3726
|
-
directory: modeIsDir || upperIsDir || (msDosCompatible && msdosAttributes.directory) || (filename.endsWith(DIRECTORY_SIGNATURE) && !fileEntry.uncompressedSize),
|
|
4001
|
+
directory: modeIsDir || upperIsDir || (msDosCompatible && msdosAttributes.directory) || (fileEntry.filename.endsWith(DIRECTORY_SIGNATURE) && !fileEntry.uncompressedSize),
|
|
3727
4002
|
zipCrypto: fileEntry.encrypted && !fileEntry.extraFieldAES
|
|
3728
4003
|
});
|
|
3729
4004
|
const entry = new Entry(fileEntry);
|
|
@@ -3746,6 +4021,15 @@
|
|
|
3746
4021
|
}
|
|
3747
4022
|
yield entry;
|
|
3748
4023
|
}
|
|
4024
|
+
if (checkAmbiguity && offset != declaredDirectoryDataLength) {
|
|
4025
|
+
throwAmbiguousArchive("trailing central directory data");
|
|
4026
|
+
}
|
|
4027
|
+
if (duplicateFilename) {
|
|
4028
|
+
throwAmbiguousArchive("duplicate filename");
|
|
4029
|
+
}
|
|
4030
|
+
if (checkAmbiguity && (prependedDataLength || (filesLength && startOffset > 0))) {
|
|
4031
|
+
throwAmbiguousArchive("prepended data");
|
|
4032
|
+
}
|
|
3749
4033
|
const extractPrependedData = getOptionValue$1(zipReader, options, OPTION_EXTRACT_PREPENDED_DATA);
|
|
3750
4034
|
const extractAppendedData = getOptionValue$1(zipReader, options, OPTION_EXTRACT_APPENDED_DATA);
|
|
3751
4035
|
if (extractPrependedData) {
|
|
@@ -3785,9 +4069,21 @@
|
|
|
3785
4069
|
readable: (function () {
|
|
3786
4070
|
const { readable, writable } = new TransformStream();
|
|
3787
4071
|
if (value.getData) {
|
|
3788
|
-
|
|
4072
|
+
getData();
|
|
3789
4073
|
return readable;
|
|
3790
4074
|
}
|
|
4075
|
+
|
|
4076
|
+
async function getData() {
|
|
4077
|
+
try {
|
|
4078
|
+
await value.getData(writable);
|
|
4079
|
+
} catch (error) {
|
|
4080
|
+
try {
|
|
4081
|
+
await writable.abort(error);
|
|
4082
|
+
} catch {
|
|
4083
|
+
// ignored
|
|
4084
|
+
}
|
|
4085
|
+
}
|
|
4086
|
+
}
|
|
3791
4087
|
})()
|
|
3792
4088
|
};
|
|
3793
4089
|
delete chunk.getData;
|
|
@@ -3812,6 +4108,7 @@
|
|
|
3812
4108
|
const zipEntry = this;
|
|
3813
4109
|
const {
|
|
3814
4110
|
reader,
|
|
4111
|
+
index,
|
|
3815
4112
|
offset,
|
|
3816
4113
|
diskNumberStart,
|
|
3817
4114
|
extraFieldAES,
|
|
@@ -3837,27 +4134,42 @@
|
|
|
3837
4134
|
rawPassword = rawPassword && rawPassword.length && rawPassword;
|
|
3838
4135
|
if (extraFieldAES) {
|
|
3839
4136
|
if (extraFieldAES.originalCompressionMethod != COMPRESSION_METHOD_AES) {
|
|
3840
|
-
throw new Error(ERR_UNSUPPORTED_COMPRESSION);
|
|
4137
|
+
throw new Error(ERR_UNSUPPORTED_COMPRESSION$1);
|
|
3841
4138
|
}
|
|
3842
4139
|
}
|
|
3843
4140
|
if ((compressionMethod != COMPRESSION_METHOD_STORE && compressionMethod != COMPRESSION_METHOD_DEFLATE && compressionMethod != COMPRESSION_METHOD_DEFLATE_64) && !passThrough) {
|
|
3844
|
-
throw new Error(ERR_UNSUPPORTED_COMPRESSION);
|
|
4141
|
+
throw new Error(ERR_UNSUPPORTED_COMPRESSION$1);
|
|
3845
4142
|
}
|
|
3846
|
-
if (getUint32(dataView, 0) != LOCAL_FILE_HEADER_SIGNATURE) {
|
|
4143
|
+
if (dataArray.length < HEADER_SIZE || getUint32(dataView, 0) != LOCAL_FILE_HEADER_SIGNATURE) {
|
|
3847
4144
|
throw new Error(ERR_LOCAL_FILE_HEADER_NOT_FOUND);
|
|
3848
4145
|
}
|
|
3849
4146
|
readCommonHeader(localDirectory, dataView, 4);
|
|
3850
4147
|
const {
|
|
3851
4148
|
extraFieldLength,
|
|
3852
|
-
filenameLength
|
|
3853
|
-
lastAccessDate,
|
|
3854
|
-
creationDate
|
|
4149
|
+
filenameLength
|
|
3855
4150
|
} = localDirectory;
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
4151
|
+
const checkAmbiguity = getOptionValue$1(zipEntry, options, OPTION_CHECK_AMBIGUITY);
|
|
4152
|
+
let rawLocalFilename = new Uint8Array();
|
|
4153
|
+
if (checkAmbiguity && (filenameLength || extraFieldLength)) {
|
|
4154
|
+
const trailingDataArray = await readUint8Array(reader, offset + HEADER_SIZE, filenameLength + extraFieldLength, diskNumberStart);
|
|
4155
|
+
rawLocalFilename = trailingDataArray.subarray(0, filenameLength);
|
|
4156
|
+
localDirectory.rawExtraField = trailingDataArray.subarray(filenameLength);
|
|
4157
|
+
} else {
|
|
4158
|
+
localDirectory.rawExtraField = extraFieldLength ?
|
|
4159
|
+
await readUint8Array(reader, offset + HEADER_SIZE + filenameLength, extraFieldLength, diskNumberStart) :
|
|
4160
|
+
new Uint8Array();
|
|
4161
|
+
}
|
|
3859
4162
|
readCommonFooter(zipEntry, localDirectory, dataView, 4, true);
|
|
3860
|
-
|
|
4163
|
+
if (checkAmbiguity) {
|
|
4164
|
+
checkLocalDirectory(zipEntry, localDirectory, rawLocalFilename);
|
|
4165
|
+
}
|
|
4166
|
+
const { lastAccessDate, creationDate } = localDirectory;
|
|
4167
|
+
if (lastAccessDate) {
|
|
4168
|
+
fileEntry.lastAccessDate = lastAccessDate;
|
|
4169
|
+
}
|
|
4170
|
+
if (creationDate) {
|
|
4171
|
+
fileEntry.creationDate = creationDate;
|
|
4172
|
+
}
|
|
3861
4173
|
const encrypted = zipEntry.encrypted && localDirectory.encrypted && !passThrough;
|
|
3862
4174
|
const zipCrypto = encrypted && !extraFieldAES;
|
|
3863
4175
|
if (!passThrough) {
|
|
@@ -3903,7 +4215,7 @@
|
|
|
3903
4215
|
outputSize: passThrough ? compressedSize : uncompressedSize,
|
|
3904
4216
|
signature,
|
|
3905
4217
|
compressed: compressionMethod != 0 && !passThrough,
|
|
3906
|
-
encrypted
|
|
4218
|
+
encrypted,
|
|
3907
4219
|
useWebWorkers: getOptionValue$1(zipEntry, options, OPTION_USE_WEB_WORKERS),
|
|
3908
4220
|
useCompressionStream,
|
|
3909
4221
|
transferStreams: getOptionValue$1(zipEntry, options, OPTION_TRANSFER_STREAMS),
|
|
@@ -3917,6 +4229,7 @@
|
|
|
3917
4229
|
await detectOverlappingEntry({
|
|
3918
4230
|
reader,
|
|
3919
4231
|
fileEntry,
|
|
4232
|
+
index,
|
|
3920
4233
|
offset,
|
|
3921
4234
|
diskNumberStart,
|
|
3922
4235
|
signature,
|
|
@@ -4019,7 +4332,7 @@
|
|
|
4019
4332
|
directory.extraFieldUnicodeComment = extraFieldUnicodeComment;
|
|
4020
4333
|
}
|
|
4021
4334
|
const extraFieldAES = extraField.get(EXTRAFIELD_TYPE_AES);
|
|
4022
|
-
if (extraFieldAES) {
|
|
4335
|
+
if (extraFieldAES && extraFieldAES.data.length >= 7) {
|
|
4023
4336
|
readExtraFieldAES(extraFieldAES, directory, compressionMethod);
|
|
4024
4337
|
directory.extraFieldAES = extraFieldAES;
|
|
4025
4338
|
} else {
|
|
@@ -4056,19 +4369,23 @@
|
|
|
4056
4369
|
directory.zip64 = true;
|
|
4057
4370
|
const extraFieldView = getDataView$1(extraFieldZip64.data);
|
|
4058
4371
|
const missingProperties = ZIP64_PROPERTIES.filter(([propertyName, max]) => directory[propertyName] == max);
|
|
4372
|
+
const requiredLength = missingProperties.reduce((length, [, max]) => length + ZIP64_EXTRACTION[max].bytes, 0);
|
|
4373
|
+
if (extraFieldZip64.data.length < requiredLength) {
|
|
4374
|
+
throw new Error(ERR_EXTRAFIELD_ZIP64_NOT_FOUND);
|
|
4375
|
+
}
|
|
4059
4376
|
for (let indexMissingProperty = 0, offset = 0; indexMissingProperty < missingProperties.length; indexMissingProperty++) {
|
|
4060
4377
|
const [propertyName, max] = missingProperties[indexMissingProperty];
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
offset += extraction.bytes;
|
|
4065
|
-
} else if (extraFieldZip64[propertyName]) {
|
|
4066
|
-
throw new Error(ERR_EXTRAFIELD_ZIP64_NOT_FOUND);
|
|
4067
|
-
}
|
|
4378
|
+
const extraction = ZIP64_EXTRACTION[max];
|
|
4379
|
+
directory[propertyName] = extraFieldZip64[propertyName] = extraction.getValue(extraFieldView, offset);
|
|
4380
|
+
offset += extraction.bytes;
|
|
4068
4381
|
}
|
|
4069
4382
|
}
|
|
4070
4383
|
|
|
4071
4384
|
function readExtraFieldUnicode(extraFieldUnicode, propertyName, rawPropertyName, directory, fileEntry) {
|
|
4385
|
+
if (extraFieldUnicode.data.length < 5) {
|
|
4386
|
+
extraFieldUnicode.valid = false;
|
|
4387
|
+
return;
|
|
4388
|
+
}
|
|
4072
4389
|
const extraFieldView = getDataView$1(extraFieldUnicode.data);
|
|
4073
4390
|
const crc32 = new Crc32();
|
|
4074
4391
|
crc32.append(fileEntry[rawPropertyName]);
|
|
@@ -4141,32 +4458,30 @@
|
|
|
4141
4458
|
function readExtraFieldUnix(extraField, directory, isInfoZip) {
|
|
4142
4459
|
try {
|
|
4143
4460
|
const view = getDataView$1(new Uint8Array(extraField.data));
|
|
4144
|
-
let
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
if (
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4461
|
+
let uid, gid;
|
|
4462
|
+
if (isInfoZip) {
|
|
4463
|
+
// Info-ZIP New Unix "ux" field (0x7875): version + variable-length uid/gid
|
|
4464
|
+
let offset = 0;
|
|
4465
|
+
const version = getUint8(view, offset++);
|
|
4466
|
+
const uidSize = getUint8(view, offset++);
|
|
4467
|
+
uid = unpackUnixId(extraField.data.subarray(offset, offset + uidSize));
|
|
4468
|
+
offset += uidSize;
|
|
4469
|
+
const gidSize = getUint8(view, offset++);
|
|
4470
|
+
gid = unpackUnixId(extraField.data.subarray(offset, offset + gidSize));
|
|
4471
|
+
Object.assign(extraField, { version, uid, gid });
|
|
4472
|
+
} else if (extraField.data.length >= 4) {
|
|
4473
|
+
// Info-ZIP Unix "Ux" field (0x7855): fixed 2-byte uid + gid (the file mode, if any, is
|
|
4474
|
+
// carried in the external file attributes, not here)
|
|
4475
|
+
uid = getUint16(view, 0);
|
|
4476
|
+
gid = getUint16(view, 2);
|
|
4477
|
+
Object.assign(extraField, { uid, gid });
|
|
4478
|
+
}
|
|
4161
4479
|
if (uid !== UNDEFINED_VALUE) {
|
|
4162
4480
|
directory.uid = uid;
|
|
4163
4481
|
}
|
|
4164
4482
|
if (gid !== UNDEFINED_VALUE) {
|
|
4165
4483
|
directory.gid = gid;
|
|
4166
4484
|
}
|
|
4167
|
-
if (unixMode !== UNDEFINED_VALUE) {
|
|
4168
|
-
directory.unixMode = unixMode;
|
|
4169
|
-
}
|
|
4170
4485
|
} catch {
|
|
4171
4486
|
// ignored
|
|
4172
4487
|
}
|
|
@@ -4180,6 +4495,9 @@
|
|
|
4180
4495
|
}
|
|
4181
4496
|
|
|
4182
4497
|
function readExtraFieldExtendedTimestamp(extraFieldExtendedTimestamp, directory, localDirectory) {
|
|
4498
|
+
if (!extraFieldExtendedTimestamp.data.length) {
|
|
4499
|
+
return;
|
|
4500
|
+
}
|
|
4183
4501
|
const extraFieldView = getDataView$1(extraFieldExtendedTimestamp.data);
|
|
4184
4502
|
const flags = getUint8(extraFieldView, 0);
|
|
4185
4503
|
const timeProperties = [];
|
|
@@ -4205,7 +4523,8 @@
|
|
|
4205
4523
|
timeProperties.forEach((propertyName, indexProperty) => {
|
|
4206
4524
|
if (extraFieldExtendedTimestamp.data.length >= offset + 4) {
|
|
4207
4525
|
const time = getUint32(extraFieldView, offset);
|
|
4208
|
-
|
|
4526
|
+
// the extended timestamp is a signed 32-bit time_t value
|
|
4527
|
+
directory[propertyName] = extraFieldExtendedTimestamp[propertyName] = new Date((time | 0) * 1000);
|
|
4209
4528
|
const rawPropertyName = timeRawProperties[indexProperty];
|
|
4210
4529
|
extraFieldExtendedTimestamp[rawPropertyName] = time;
|
|
4211
4530
|
}
|
|
@@ -4216,6 +4535,7 @@
|
|
|
4216
4535
|
async function detectOverlappingEntry({
|
|
4217
4536
|
reader,
|
|
4218
4537
|
fileEntry,
|
|
4538
|
+
index,
|
|
4219
4539
|
offset,
|
|
4220
4540
|
diskNumberStart,
|
|
4221
4541
|
signature,
|
|
@@ -4227,10 +4547,9 @@
|
|
|
4227
4547
|
readRanges
|
|
4228
4548
|
}) {
|
|
4229
4549
|
let diskOffset = 0;
|
|
4230
|
-
if (diskNumberStart) {
|
|
4231
|
-
for (let indexReader = 0; indexReader < diskNumberStart; indexReader++) {
|
|
4232
|
-
|
|
4233
|
-
diskOffset += diskReader.size;
|
|
4550
|
+
if (diskNumberStart && reader.readers) {
|
|
4551
|
+
for (let indexReader = 0; indexReader < Math.min(diskNumberStart, reader.readers.length); indexReader++) {
|
|
4552
|
+
diskOffset += reader.readers[indexReader].size;
|
|
4234
4553
|
}
|
|
4235
4554
|
}
|
|
4236
4555
|
let dataDescriptorLength = 0;
|
|
@@ -4243,7 +4562,8 @@
|
|
|
4243
4562
|
}
|
|
4244
4563
|
if (dataDescriptorLength) {
|
|
4245
4564
|
const dataDescriptorArray = await readUint8Array(reader, dataOffset + compressedSize, dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH, diskNumberStart);
|
|
4246
|
-
const dataDescriptorSignature =
|
|
4565
|
+
const dataDescriptorSignature = dataDescriptorArray.length == dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH &&
|
|
4566
|
+
getUint32(getDataView$1(dataDescriptorArray), 0) == DATA_DESCRIPTOR_RECORD_SIGNATURE;
|
|
4247
4567
|
if (dataDescriptorSignature) {
|
|
4248
4568
|
const readSignature = getUint32(getDataView$1(dataDescriptorArray), 4);
|
|
4249
4569
|
let readCompressedSize;
|
|
@@ -4268,14 +4588,14 @@
|
|
|
4268
4588
|
end: diskOffset + dataOffset + compressedSize + dataDescriptorLength,
|
|
4269
4589
|
fileEntry
|
|
4270
4590
|
};
|
|
4271
|
-
for (const otherRange of readRanges) {
|
|
4272
|
-
if (
|
|
4591
|
+
for (const [otherIndex, otherRange] of readRanges) {
|
|
4592
|
+
if (otherIndex != index && range.start < otherRange.end && otherRange.start < range.end) {
|
|
4273
4593
|
const error = new Error(ERR_OVERLAPPING_ENTRY);
|
|
4274
4594
|
error.overlappingEntry = otherRange.fileEntry;
|
|
4275
4595
|
throw error;
|
|
4276
4596
|
}
|
|
4277
4597
|
}
|
|
4278
|
-
readRanges.
|
|
4598
|
+
readRanges.set(index, range);
|
|
4279
4599
|
}
|
|
4280
4600
|
|
|
4281
4601
|
async function seekSignature(reader, signature, startOffset, minimumBytes, maximumLength) {
|
|
@@ -4300,6 +4620,35 @@
|
|
|
4300
4620
|
}
|
|
4301
4621
|
}
|
|
4302
4622
|
|
|
4623
|
+
function checkLocalDirectory(zipEntry, localDirectory, rawLocalFilename) {
|
|
4624
|
+
const { rawFilename } = zipEntry;
|
|
4625
|
+
if (rawLocalFilename.length != rawFilename.length ||
|
|
4626
|
+
rawLocalFilename.some((byteValue, indexByte) => byteValue != rawFilename[indexByte])) {
|
|
4627
|
+
throwAmbiguousArchive("mismatched local file header (filename)");
|
|
4628
|
+
}
|
|
4629
|
+
if ((localDirectory.rawBitFlag & BITFLAG_AMBIGUITY_MASK) != (zipEntry.rawBitFlag & BITFLAG_AMBIGUITY_MASK)) {
|
|
4630
|
+
throwAmbiguousArchive("mismatched local file header (general purpose bit flag)");
|
|
4631
|
+
}
|
|
4632
|
+
if (localDirectory.compressionMethod != zipEntry.compressionMethod) {
|
|
4633
|
+
throwAmbiguousArchive("mismatched local file header (compression method)");
|
|
4634
|
+
}
|
|
4635
|
+
// when the data descriptor flag is set, the local signature and sizes are zeroed out; all-zero values are
|
|
4636
|
+
// also tolerated when the flag is clear because some tools produce them (streaming writers predating bit 3)
|
|
4637
|
+
if (!localDirectory.bitFlag.dataDescriptor &&
|
|
4638
|
+
(localDirectory.signature || localDirectory.compressedSize || localDirectory.uncompressedSize) &&
|
|
4639
|
+
(localDirectory.signature != zipEntry.signature ||
|
|
4640
|
+
localDirectory.compressedSize != zipEntry.compressedSize ||
|
|
4641
|
+
localDirectory.uncompressedSize != zipEntry.uncompressedSize)) {
|
|
4642
|
+
throwAmbiguousArchive("mismatched local file header (signature or sizes)");
|
|
4643
|
+
}
|
|
4644
|
+
}
|
|
4645
|
+
|
|
4646
|
+
function throwAmbiguousArchive(reason) {
|
|
4647
|
+
const error = new Error(ERR_AMBIGUOUS_ARCHIVE);
|
|
4648
|
+
error.reason = reason;
|
|
4649
|
+
throw error;
|
|
4650
|
+
}
|
|
4651
|
+
|
|
4303
4652
|
function getOptionValue$1(zipReader, options, name) {
|
|
4304
4653
|
return options[name] === UNDEFINED_VALUE ? zipReader.options[name] : options[name];
|
|
4305
4654
|
}
|
|
@@ -4338,7 +4687,7 @@
|
|
|
4338
4687
|
}
|
|
4339
4688
|
|
|
4340
4689
|
function getDataView$1(array) {
|
|
4341
|
-
return new DataView(array.buffer);
|
|
4690
|
+
return new DataView(array.buffer, array.byteOffset, array.byteLength);
|
|
4342
4691
|
}
|
|
4343
4692
|
|
|
4344
4693
|
/*
|
|
@@ -4378,13 +4727,19 @@
|
|
|
4378
4727
|
const ERR_INVALID_ENCRYPTION_STRENGTH = "The strength must equal 1, 2, or 3";
|
|
4379
4728
|
const ERR_INVALID_EXTRAFIELD_TYPE = "Extra field type exceeds 65535";
|
|
4380
4729
|
const ERR_INVALID_EXTRAFIELD_DATA = "Extra field data exceeds 64KB";
|
|
4730
|
+
// same message as the constant exported by zip-reader.js
|
|
4731
|
+
const ERR_UNSUPPORTED_COMPRESSION = "Compression method not supported";
|
|
4732
|
+
const MIN_UNIX_TIME = -2147483648;
|
|
4733
|
+
const MAX_UNIX_TIME = 2147483647;
|
|
4381
4734
|
const ERR_UNSUPPORTED_FORMAT = "Zip64 is not supported (set the 'zip64' option to 'true')";
|
|
4382
4735
|
const ERR_UNDEFINED_UNCOMPRESSED_SIZE = "Undefined uncompressed size";
|
|
4736
|
+
const ERR_UNDEFINED_READER = "Undefined reader";
|
|
4383
4737
|
const ERR_ZIP_NOT_EMPTY = "Zip file not empty";
|
|
4384
4738
|
const ERR_INVALID_UID = "Invalid uid (must be integer 0..2^32-1)";
|
|
4385
4739
|
const ERR_INVALID_GID = "Invalid gid (must be integer 0..2^32-1)";
|
|
4386
4740
|
const ERR_INVALID_UNIX_MODE = "Invalid UNIX mode (must be integer 0..65535)";
|
|
4387
4741
|
const ERR_INVALID_UNIX_EXTRA_FIELD_TYPE = "Invalid unixExtraFieldType (must be 'infozip' or 'unix')";
|
|
4742
|
+
const ERR_INVALID_UNIX_ID_SIZE = "uid/gid must be 0..65535 for unixExtraFieldType 'unix' (use 'infozip' for larger ids)";
|
|
4388
4743
|
const ERR_INVALID_MSDOS_ATTRIBUTES = "Invalid msdosAttributesRaw (must be integer 0..255)";
|
|
4389
4744
|
const ERR_INVALID_MSDOS_DATA = "Invalid msdosAttributes (must be an object with boolean flags)";
|
|
4390
4745
|
|
|
@@ -4410,9 +4765,10 @@
|
|
|
4410
4765
|
files: new Map(),
|
|
4411
4766
|
filenames: new Set(),
|
|
4412
4767
|
offset: options[OPTION_OFFSET] === UNDEFINED_VALUE ? writer.size || writer.writable.size || 0 : options[OPTION_OFFSET],
|
|
4413
|
-
|
|
4768
|
+
initialOffset: options[OPTION_OFFSET] === UNDEFINED_VALUE ? 0 : options[OPTION_OFFSET] - (writer.size || writer.writable.size || 0),
|
|
4414
4769
|
pendingAddFileCalls: new Set(),
|
|
4415
|
-
bufferedWrites: 0
|
|
4770
|
+
bufferedWrites: 0,
|
|
4771
|
+
lastFileEntry: UNDEFINED_VALUE
|
|
4416
4772
|
});
|
|
4417
4773
|
}
|
|
4418
4774
|
|
|
@@ -4421,17 +4777,18 @@
|
|
|
4421
4777
|
throw new Error(ERR_ZIP_NOT_EMPTY);
|
|
4422
4778
|
}
|
|
4423
4779
|
reader = new GenericReader(reader);
|
|
4780
|
+
await initStream(reader);
|
|
4424
4781
|
const zipReader = new ZipReader(reader.readable);
|
|
4425
4782
|
const entries = await zipReader.getEntries();
|
|
4426
4783
|
await zipReader.close();
|
|
4784
|
+
await initStream(this.writer);
|
|
4427
4785
|
await reader.readable.pipeTo(this.writer.writable, { preventClose: true, preventAbort: true });
|
|
4428
4786
|
this.writer.size = this.offset = reader.size;
|
|
4429
4787
|
this.filenames = new Set(entries.map(entry => entry.filename));
|
|
4430
4788
|
this.files = new Map(entries.map(entry => {
|
|
4431
4789
|
const {
|
|
4432
4790
|
version,
|
|
4433
|
-
|
|
4434
|
-
lastModDate,
|
|
4791
|
+
rawLastModDate,
|
|
4435
4792
|
lastAccessDate,
|
|
4436
4793
|
creationDate,
|
|
4437
4794
|
rawFilename,
|
|
@@ -4444,6 +4801,7 @@
|
|
|
4444
4801
|
zip64
|
|
4445
4802
|
} = entry;
|
|
4446
4803
|
let {
|
|
4804
|
+
compressionMethod,
|
|
4447
4805
|
rawExtraFieldZip64,
|
|
4448
4806
|
rawExtraFieldAES,
|
|
4449
4807
|
rawExtraFieldExtendedTimestamp,
|
|
@@ -4456,31 +4814,39 @@
|
|
|
4456
4814
|
rawExtraFieldAES = rawExtraFieldAES || new Uint8Array();
|
|
4457
4815
|
rawExtraFieldExtendedTimestamp = rawExtraFieldExtendedTimestamp || new Uint8Array();
|
|
4458
4816
|
rawExtraFieldNTFS = rawExtraFieldNTFS || new Uint8Array();
|
|
4459
|
-
rawExtraFieldUnix =
|
|
4817
|
+
rawExtraFieldUnix = rawExtraFieldUnix || new Uint8Array();
|
|
4460
4818
|
rawExtraField = rawExtraField || new Uint8Array();
|
|
4819
|
+
if (entry.extraFieldAES) {
|
|
4820
|
+
compressionMethod = COMPRESSION_METHOD_AES;
|
|
4821
|
+
}
|
|
4461
4822
|
const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField);
|
|
4462
|
-
const zip64UncompressedSize = zip64 && uncompressedSize
|
|
4463
|
-
const zip64CompressedSize = zip64 && compressedSize
|
|
4823
|
+
const zip64UncompressedSize = zip64 && uncompressedSize >= MAX_32_BITS;
|
|
4824
|
+
const zip64CompressedSize = zip64 && compressedSize >= MAX_32_BITS;
|
|
4825
|
+
const bitFlagValue = (getBitFlag(level, languageEncodingFlag, dataDescriptor, encrypted, compressionMethod) & ~BITFLAG_LEVEL) | (level << 1);
|
|
4464
4826
|
const {
|
|
4465
4827
|
headerArray,
|
|
4466
4828
|
headerView
|
|
4467
4829
|
} = getHeaderArrayData({
|
|
4468
4830
|
version,
|
|
4469
|
-
bitFlag:
|
|
4831
|
+
bitFlag: bitFlagValue,
|
|
4470
4832
|
compressionMethod,
|
|
4471
4833
|
uncompressedSize,
|
|
4472
4834
|
compressedSize,
|
|
4473
|
-
|
|
4835
|
+
rawLastModDate,
|
|
4474
4836
|
rawFilename,
|
|
4475
4837
|
zip64CompressedSize,
|
|
4476
4838
|
zip64UncompressedSize,
|
|
4477
4839
|
extraFieldLength
|
|
4478
4840
|
});
|
|
4841
|
+
const { signature } = entry;
|
|
4842
|
+
if (signature !== UNDEFINED_VALUE) {
|
|
4843
|
+
setUint32(headerView, HEADER_OFFSET_SIGNATURE, signature);
|
|
4844
|
+
}
|
|
4479
4845
|
Object.assign(entry, {
|
|
4480
4846
|
zip64UncompressedSize,
|
|
4481
4847
|
zip64CompressedSize,
|
|
4482
|
-
zip64Offset: zip64 && this.offset - diskOffset
|
|
4483
|
-
zip64DiskNumberStart: zip64 && diskNumber
|
|
4848
|
+
zip64Offset: zip64 && this.offset - diskOffset >= MAX_32_BITS,
|
|
4849
|
+
zip64DiskNumberStart: zip64 && diskNumber >= MAX_16_BITS,
|
|
4484
4850
|
rawExtraFieldZip64,
|
|
4485
4851
|
rawExtraFieldAES,
|
|
4486
4852
|
rawExtraFieldExtendedTimestamp,
|
|
@@ -4498,6 +4864,7 @@
|
|
|
4498
4864
|
|
|
4499
4865
|
async add(name = "", reader, options = {}) {
|
|
4500
4866
|
const zipWriter = this;
|
|
4867
|
+
options = Object.assign({}, options);
|
|
4501
4868
|
const {
|
|
4502
4869
|
pendingAddFileCalls,
|
|
4503
4870
|
config
|
|
@@ -4508,17 +4875,24 @@
|
|
|
4508
4875
|
await new Promise(resolve => pendingEntries.push(resolve));
|
|
4509
4876
|
}
|
|
4510
4877
|
let promiseAddFile;
|
|
4878
|
+
let nameAdded;
|
|
4511
4879
|
try {
|
|
4512
4880
|
name = name.trim();
|
|
4881
|
+
if (getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY) && !name.endsWith(DIRECTORY_SIGNATURE)) {
|
|
4882
|
+
name += DIRECTORY_SIGNATURE;
|
|
4883
|
+
}
|
|
4513
4884
|
if (zipWriter.filenames.has(name)) {
|
|
4514
4885
|
throw new Error(ERR_DUPLICATED_NAME);
|
|
4515
4886
|
}
|
|
4516
4887
|
zipWriter.filenames.add(name);
|
|
4888
|
+
nameAdded = true;
|
|
4517
4889
|
promiseAddFile = addFile(zipWriter, name, reader, options);
|
|
4518
4890
|
pendingAddFileCalls.add(promiseAddFile);
|
|
4519
4891
|
return await promiseAddFile;
|
|
4520
4892
|
} catch (error) {
|
|
4521
|
-
|
|
4893
|
+
if (nameAdded) {
|
|
4894
|
+
zipWriter.filenames.delete(name);
|
|
4895
|
+
}
|
|
4522
4896
|
throw error;
|
|
4523
4897
|
} finally {
|
|
4524
4898
|
pendingAddFileCalls.delete(promiseAddFile);
|
|
@@ -4551,6 +4925,9 @@
|
|
|
4551
4925
|
const zipWriter = this;
|
|
4552
4926
|
const { pendingAddFileCalls, writer } = this;
|
|
4553
4927
|
const { writable } = writer;
|
|
4928
|
+
if (getLength(comment) > MAX_16_BITS) {
|
|
4929
|
+
throw new Error(ERR_INVALID_COMMENT);
|
|
4930
|
+
}
|
|
4554
4931
|
while (pendingAddFileCalls.size) {
|
|
4555
4932
|
await Promise.allSettled(Array.from(pendingAddFileCalls));
|
|
4556
4933
|
}
|
|
@@ -4569,28 +4946,94 @@
|
|
|
4569
4946
|
const { readable, writable } = new TransformStream();
|
|
4570
4947
|
this.readable = readable;
|
|
4571
4948
|
this.zipWriter = new ZipWriter(writable, options);
|
|
4949
|
+
this.pendingAddFileCalls = new Set();
|
|
4572
4950
|
}
|
|
4573
4951
|
|
|
4574
4952
|
transform(path) {
|
|
4953
|
+
const zipWriter = this.zipWriter;
|
|
4954
|
+
let streamController;
|
|
4575
4955
|
const { readable, writable } = new TransformStream({
|
|
4576
|
-
|
|
4956
|
+
start(controller) {
|
|
4957
|
+
streamController = controller;
|
|
4958
|
+
},
|
|
4959
|
+
flush: () => void closeArchive()
|
|
4577
4960
|
});
|
|
4578
|
-
this.zipWriter.add(path, readable);
|
|
4961
|
+
watchAddFileCall(this, this.zipWriter.add(path, readable), error => streamController.error(error));
|
|
4579
4962
|
return { readable: this.readable, writable };
|
|
4963
|
+
|
|
4964
|
+
async function closeArchive() {
|
|
4965
|
+
try {
|
|
4966
|
+
await zipWriter.close();
|
|
4967
|
+
} catch (error) {
|
|
4968
|
+
try {
|
|
4969
|
+
await zipWriter.writer.writable.abort(error);
|
|
4970
|
+
} catch {
|
|
4971
|
+
// ignored
|
|
4972
|
+
}
|
|
4973
|
+
}
|
|
4974
|
+
}
|
|
4580
4975
|
}
|
|
4581
4976
|
|
|
4582
4977
|
writable(path) {
|
|
4583
|
-
|
|
4584
|
-
|
|
4978
|
+
let streamController;
|
|
4979
|
+
const { readable, writable } = new TransformStream({
|
|
4980
|
+
start(controller) {
|
|
4981
|
+
streamController = controller;
|
|
4982
|
+
}
|
|
4983
|
+
});
|
|
4984
|
+
watchAddFileCall(this, this.zipWriter.add(path, readable), error => streamController.error(error));
|
|
4585
4985
|
return writable;
|
|
4586
4986
|
}
|
|
4587
4987
|
|
|
4588
|
-
close(comment = UNDEFINED_VALUE, options = {}) {
|
|
4988
|
+
async close(comment = UNDEFINED_VALUE, options = {}) {
|
|
4989
|
+
await Promise.all(Array.from(this.pendingAddFileCalls));
|
|
4589
4990
|
return this.zipWriter.close(comment, options);
|
|
4590
4991
|
}
|
|
4591
4992
|
}
|
|
4592
4993
|
|
|
4994
|
+
function watchAddFileCall(zipWriterStream, promiseAddFile, onerror) {
|
|
4995
|
+
zipWriterStream.pendingAddFileCalls.add(promiseAddFile);
|
|
4996
|
+
promiseAddFile.catch(error => {
|
|
4997
|
+
try {
|
|
4998
|
+
onerror(error);
|
|
4999
|
+
} catch {
|
|
5000
|
+
// ignored
|
|
5001
|
+
}
|
|
5002
|
+
});
|
|
5003
|
+
}
|
|
5004
|
+
|
|
4593
5005
|
async function addFile(zipWriter, name, reader, options) {
|
|
5006
|
+
const attributesInfo = resolveAttributes(zipWriter, name, options);
|
|
5007
|
+
({ name } = attributesInfo);
|
|
5008
|
+
const metadataInfo = resolveMetadata(zipWriter, name, options);
|
|
5009
|
+
const { comment } = metadataInfo;
|
|
5010
|
+
const extraField = options[PROPERTY_NAME_EXTRA_FIELD];
|
|
5011
|
+
zipWriter.files.set(name, UNDEFINED_VALUE);
|
|
5012
|
+
let fileEntry;
|
|
5013
|
+
try {
|
|
5014
|
+
const sizesInfo = await resolveSizes(zipWriter, reader, metadataInfo, options);
|
|
5015
|
+
({ reader } = sizesInfo);
|
|
5016
|
+
const { diskOffset, diskNumber } = zipWriter.writer;
|
|
5017
|
+
options = Object.assign({}, options, attributesInfo.resolvedOptions, metadataInfo.resolvedOptions, sizesInfo.resolvedOptions, {
|
|
5018
|
+
internalFileAttribute: metadataInfo.resolvedOptions.internalFileAttributes,
|
|
5019
|
+
externalFileAttribute: attributesInfo.resolvedOptions.externalFileAttributes,
|
|
5020
|
+
signature: options[PROPERTY_NAME_SIGNATURE],
|
|
5021
|
+
offset: zipWriter.offset - diskOffset,
|
|
5022
|
+
diskNumberStart: diskNumber
|
|
5023
|
+
});
|
|
5024
|
+
const headerInfo = getHeaderInfo(options);
|
|
5025
|
+
const dataDescriptorInfo = getDataDescriptorInfo(options);
|
|
5026
|
+
const metadataSize = getLength(headerInfo.localHeaderArray, dataDescriptorInfo.dataDescriptorArray);
|
|
5027
|
+
fileEntry = await getFileEntry(zipWriter, name, reader, { headerInfo, dataDescriptorInfo, metadataSize }, options);
|
|
5028
|
+
} catch (error) {
|
|
5029
|
+
zipWriter.files.delete(name);
|
|
5030
|
+
throw error;
|
|
5031
|
+
}
|
|
5032
|
+
Object.assign(fileEntry, { name, comment, extraField });
|
|
5033
|
+
return new Entry(fileEntry);
|
|
5034
|
+
}
|
|
5035
|
+
|
|
5036
|
+
function resolveAttributes(zipWriter, name, options) {
|
|
4594
5037
|
name = name.trim();
|
|
4595
5038
|
let msDosCompatible = getOptionValue(zipWriter, options, PROPERTY_NAME_MS_DOS_COMPATIBLE);
|
|
4596
5039
|
let versionMadeBy = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION_MADE_BY, msDosCompatible ? 20 : 768);
|
|
@@ -4598,7 +5041,7 @@
|
|
|
4598
5041
|
const uid = getOptionValue(zipWriter, options, PROPERTY_NAME_UID);
|
|
4599
5042
|
const gid = getOptionValue(zipWriter, options, PROPERTY_NAME_GID);
|
|
4600
5043
|
let unixMode = getOptionValue(zipWriter, options, PROPERTY_NAME_UNIX_MODE);
|
|
4601
|
-
|
|
5044
|
+
let unixExtraFieldType = getOptionValue(zipWriter, options, OPTION_UNIX_EXTRA_FIELD_TYPE);
|
|
4602
5045
|
let setuid = getOptionValue(zipWriter, options, PROPERTY_NAME_SETUID);
|
|
4603
5046
|
let setgid = getOptionValue(zipWriter, options, PROPERTY_NAME_SETGID);
|
|
4604
5047
|
let sticky = getOptionValue(zipWriter, options, PROPERTY_NAME_STICKY);
|
|
@@ -4614,6 +5057,13 @@
|
|
|
4614
5057
|
if (unixExtraFieldType !== UNDEFINED_VALUE && unixExtraFieldType !== INFOZIP_EXTRA_FIELD_TYPE && unixExtraFieldType !== UNIX_EXTRA_FIELD_TYPE) {
|
|
4615
5058
|
throw new Error(ERR_INVALID_UNIX_EXTRA_FIELD_TYPE);
|
|
4616
5059
|
}
|
|
5060
|
+
if (unixExtraFieldType === UNIX_EXTRA_FIELD_TYPE &&
|
|
5061
|
+
((uid !== UNDEFINED_VALUE && uid > MAX_16_BITS) || (gid !== UNDEFINED_VALUE && gid > MAX_16_BITS))) {
|
|
5062
|
+
throw new Error(ERR_INVALID_UNIX_ID_SIZE);
|
|
5063
|
+
}
|
|
5064
|
+
if (unixExtraFieldType === UNDEFINED_VALUE && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
|
|
5065
|
+
unixExtraFieldType = INFOZIP_EXTRA_FIELD_TYPE;
|
|
5066
|
+
}
|
|
4617
5067
|
let msdosAttributesRaw = getOptionValue(zipWriter, options, PROPERTY_NAME_MSDOS_ATTRIBUTES_RAW);
|
|
4618
5068
|
let msdosAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_MSDOS_ATTRIBUTES);
|
|
4619
5069
|
const hasUnixMetadata = uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE || unixMode !== UNDEFINED_VALUE || unixExtraFieldType;
|
|
@@ -4684,6 +5134,27 @@
|
|
|
4684
5134
|
if (hasMsDosProvided) {
|
|
4685
5135
|
externalFileAttributes = (externalFileAttributes & MAX_32_BITS) | (msdosAttributesRaw & MAX_8_BITS);
|
|
4686
5136
|
}
|
|
5137
|
+
return {
|
|
5138
|
+
name,
|
|
5139
|
+
resolvedOptions: {
|
|
5140
|
+
versionMadeBy,
|
|
5141
|
+
msDosCompatible,
|
|
5142
|
+
externalFileAttributes,
|
|
5143
|
+
unixExternalUpper,
|
|
5144
|
+
uid,
|
|
5145
|
+
gid,
|
|
5146
|
+
unixMode,
|
|
5147
|
+
unixExtraFieldType,
|
|
5148
|
+
setuid,
|
|
5149
|
+
setgid,
|
|
5150
|
+
sticky,
|
|
5151
|
+
msdosAttributesRaw,
|
|
5152
|
+
msdosAttributes
|
|
5153
|
+
}
|
|
5154
|
+
};
|
|
5155
|
+
}
|
|
5156
|
+
|
|
5157
|
+
function resolveMetadata(zipWriter, name, options) {
|
|
4687
5158
|
const encode = getOptionValue(zipWriter, options, OPTION_ENCODE_TEXT, encodeText);
|
|
4688
5159
|
let rawFilename = encode(name);
|
|
4689
5160
|
if (rawFilename === UNDEFINED_VALUE) {
|
|
@@ -4722,10 +5193,14 @@
|
|
|
4722
5193
|
const transferStreams = getOptionValue(zipWriter, options, OPTION_TRANSFER_STREAMS, true);
|
|
4723
5194
|
const bufferedWrite = getOptionValue(zipWriter, options, OPTION_BUFFERED_WRITE);
|
|
4724
5195
|
const createTempStream = getOptionValue(zipWriter, options, OPTION_CREATE_TEMP_STREAM);
|
|
4725
|
-
const dataDescriptorSignature = getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR_SIGNATURE,
|
|
5196
|
+
const dataDescriptorSignature = getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR_SIGNATURE, true);
|
|
4726
5197
|
const signal = getOptionValue(zipWriter, options, OPTION_SIGNAL);
|
|
4727
5198
|
const useUnicodeFileNames = getOptionValue(zipWriter, options, OPTION_USE_UNICODE_FILE_NAMES, true);
|
|
4728
5199
|
const compressionMethod = getOptionValue(zipWriter, options, PROPERTY_NAME_COMPRESSION_METHOD);
|
|
5200
|
+
if (!passThrough && compressionMethod !== UNDEFINED_VALUE &&
|
|
5201
|
+
compressionMethod !== COMPRESSION_METHOD_STORE && compressionMethod !== COMPRESSION_METHOD_DEFLATE) {
|
|
5202
|
+
throw new Error(ERR_UNSUPPORTED_COMPRESSION);
|
|
5203
|
+
}
|
|
4729
5204
|
let level = getOptionValue(zipWriter, options, OPTION_LEVEL);
|
|
4730
5205
|
let useCompressionStream = getOptionValue(zipWriter, options, OPTION_USE_COMPRESSION_STREAM);
|
|
4731
5206
|
let dataDescriptor = getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR);
|
|
@@ -4741,7 +5216,7 @@
|
|
|
4741
5216
|
if (!useCompressionStream && (zipWriter.config.CompressionStream === UNDEFINED_VALUE && zipWriter.config.CompressionStreamZlib === UNDEFINED_VALUE)) {
|
|
4742
5217
|
level = 0;
|
|
4743
5218
|
}
|
|
4744
|
-
|
|
5219
|
+
const zip64 = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIP64);
|
|
4745
5220
|
if (!zipCrypto && (password !== UNDEFINED_VALUE || rawPassword !== UNDEFINED_VALUE) && !(encryptionStrength >= 1 && encryptionStrength <= 3)) {
|
|
4746
5221
|
throw new Error(ERR_INVALID_ENCRYPTION_STRENGTH);
|
|
4747
5222
|
}
|
|
@@ -4752,6 +5227,7 @@
|
|
|
4752
5227
|
let offset = 0;
|
|
4753
5228
|
extraField.forEach(data => extraFieldSize += 4 + getLength(data));
|
|
4754
5229
|
rawExtraField = new Uint8Array(extraFieldSize);
|
|
5230
|
+
const rawExtraFieldView = getDataView(rawExtraField);
|
|
4755
5231
|
extraField.forEach((data, type) => {
|
|
4756
5232
|
if (type > MAX_16_BITS) {
|
|
4757
5233
|
throw new Error(ERR_INVALID_EXTRAFIELD_TYPE);
|
|
@@ -4759,22 +5235,72 @@
|
|
|
4759
5235
|
if (getLength(data) > MAX_16_BITS) {
|
|
4760
5236
|
throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
|
|
4761
5237
|
}
|
|
4762
|
-
|
|
4763
|
-
|
|
5238
|
+
setUint16(rawExtraFieldView, offset, type);
|
|
5239
|
+
setUint16(rawExtraFieldView, offset + 2, getLength(data));
|
|
4764
5240
|
arraySet(rawExtraField, data, offset + 4);
|
|
4765
5241
|
offset += 4 + getLength(data);
|
|
4766
5242
|
});
|
|
4767
5243
|
}
|
|
5244
|
+
return {
|
|
5245
|
+
comment,
|
|
5246
|
+
resolvedOptions: {
|
|
5247
|
+
rawFilename,
|
|
5248
|
+
rawComment,
|
|
5249
|
+
version,
|
|
5250
|
+
lastModDate,
|
|
5251
|
+
lastAccessDate,
|
|
5252
|
+
creationDate,
|
|
5253
|
+
internalFileAttributes,
|
|
5254
|
+
passThrough,
|
|
5255
|
+
password,
|
|
5256
|
+
rawPassword,
|
|
5257
|
+
encryptionStrength,
|
|
5258
|
+
zipCrypto,
|
|
5259
|
+
extendedTimestamp,
|
|
5260
|
+
keepOrder,
|
|
5261
|
+
useWebWorkers,
|
|
5262
|
+
transferStreams,
|
|
5263
|
+
bufferedWrite,
|
|
5264
|
+
createTempStream,
|
|
5265
|
+
dataDescriptorSignature,
|
|
5266
|
+
signal,
|
|
5267
|
+
useUnicodeFileNames,
|
|
5268
|
+
compressionMethod,
|
|
5269
|
+
level,
|
|
5270
|
+
useCompressionStream,
|
|
5271
|
+
dataDescriptor,
|
|
5272
|
+
zip64,
|
|
5273
|
+
rawExtraField
|
|
5274
|
+
}
|
|
5275
|
+
};
|
|
5276
|
+
}
|
|
5277
|
+
|
|
5278
|
+
async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, options) {
|
|
5279
|
+
const { passThrough, zipCrypto, password, rawPassword, encryptionStrength } = metadata;
|
|
5280
|
+
let { dataDescriptor, zip64, level, compressionMethod } = metadata;
|
|
4768
5281
|
let maximumCompressedSize = 0;
|
|
4769
|
-
let maximumEntrySize = 0;
|
|
4770
5282
|
let uncompressedSize = 0;
|
|
4771
5283
|
if (passThrough) {
|
|
5284
|
+
// the headers of a passThrough entry describe the payload verbatim: without a
|
|
5285
|
+
// reader they would declare content that is not there
|
|
5286
|
+
if (!reader) {
|
|
5287
|
+
throw new Error(ERR_UNDEFINED_READER);
|
|
5288
|
+
}
|
|
4772
5289
|
uncompressedSize = options[PROPERTY_NAME_UNCOMPRESSED_SIZE];
|
|
4773
5290
|
if (uncompressedSize === UNDEFINED_VALUE) {
|
|
4774
5291
|
throw new Error(ERR_UNDEFINED_UNCOMPRESSED_SIZE);
|
|
4775
5292
|
}
|
|
4776
5293
|
}
|
|
4777
5294
|
const zip64Enabled = zip64 === true;
|
|
5295
|
+
const encrypted = getOptionValue(zipWriter, options, PROPERTY_NAME_ENCRYPTED);
|
|
5296
|
+
// entries without a reader have no payload: write them as empty stored files instead of
|
|
5297
|
+
// declaring a compressed or encrypted content that does not exist
|
|
5298
|
+
const encryptedEntry = Boolean(reader) && (Boolean((password && getLength(password)) || (rawPassword && getLength(rawPassword))) || (passThrough && encrypted));
|
|
5299
|
+
if (!reader) {
|
|
5300
|
+
level = 0;
|
|
5301
|
+
compressionMethod = COMPRESSION_METHOD_STORE;
|
|
5302
|
+
}
|
|
5303
|
+
const encryptionOverhead = encryptedEntry ? (zipCrypto ? 12 : 16 + encryptionStrength * 4) : 0;
|
|
4778
5304
|
if (reader) {
|
|
4779
5305
|
reader = new GenericReader(reader);
|
|
4780
5306
|
await initStream(reader);
|
|
@@ -4787,16 +5313,15 @@
|
|
|
4787
5313
|
}
|
|
4788
5314
|
} else {
|
|
4789
5315
|
options.uncompressedSize = uncompressedSize = reader.size;
|
|
4790
|
-
maximumCompressedSize = getMaximumCompressedSize(uncompressedSize);
|
|
5316
|
+
maximumCompressedSize = getMaximumCompressedSize(uncompressedSize) + encryptionOverhead;
|
|
4791
5317
|
}
|
|
4792
5318
|
} else {
|
|
4793
5319
|
options.uncompressedSize = uncompressedSize;
|
|
4794
|
-
maximumCompressedSize = getMaximumCompressedSize(uncompressedSize);
|
|
5320
|
+
maximumCompressedSize = getMaximumCompressedSize(uncompressedSize) + encryptionOverhead;
|
|
4795
5321
|
}
|
|
4796
5322
|
}
|
|
4797
|
-
const
|
|
4798
|
-
const
|
|
4799
|
-
const zip64CompressedSize = zip64Enabled || maximumCompressedSize > MAX_32_BITS;
|
|
5323
|
+
const zip64UncompressedSize = zip64Enabled || uncompressedSize >= MAX_32_BITS;
|
|
5324
|
+
const zip64CompressedSize = zip64Enabled || maximumCompressedSize >= MAX_32_BITS;
|
|
4800
5325
|
if (zip64UncompressedSize || zip64CompressedSize) {
|
|
4801
5326
|
if (zip64 === false) {
|
|
4802
5327
|
throw new Error(ERR_UNSUPPORTED_FORMAT);
|
|
@@ -4805,73 +5330,19 @@
|
|
|
4805
5330
|
}
|
|
4806
5331
|
}
|
|
4807
5332
|
zip64 = zip64 || false;
|
|
4808
|
-
|
|
4809
|
-
|
|
4810
|
-
|
|
4811
|
-
|
|
4812
|
-
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
|
|
4820
|
-
|
|
4821
|
-
password,
|
|
4822
|
-
rawPassword,
|
|
4823
|
-
level,
|
|
4824
|
-
useWebWorkers,
|
|
4825
|
-
transferStreams,
|
|
4826
|
-
encryptionStrength,
|
|
4827
|
-
extendedTimestamp,
|
|
4828
|
-
zipCrypto,
|
|
4829
|
-
bufferedWrite,
|
|
4830
|
-
createTempStream,
|
|
4831
|
-
keepOrder,
|
|
4832
|
-
useUnicodeFileNames,
|
|
4833
|
-
dataDescriptor,
|
|
4834
|
-
dataDescriptorSignature,
|
|
4835
|
-
signal,
|
|
4836
|
-
msDosCompatible,
|
|
4837
|
-
internalFileAttribute: internalFileAttributes,
|
|
4838
|
-
internalFileAttributes,
|
|
4839
|
-
externalFileAttribute: externalFileAttributes,
|
|
4840
|
-
externalFileAttributes,
|
|
4841
|
-
useCompressionStream,
|
|
4842
|
-
passThrough,
|
|
4843
|
-
encrypted: Boolean((password && getLength(password)) || (rawPassword && getLength(rawPassword))) || (passThrough && encrypted),
|
|
4844
|
-
signature: options[PROPERTY_NAME_SIGNATURE],
|
|
4845
|
-
compressionMethod,
|
|
4846
|
-
uncompressedSize,
|
|
4847
|
-
offset: zipWriter.offset - diskOffset,
|
|
4848
|
-
diskNumberStart: diskNumber,
|
|
4849
|
-
uid,
|
|
4850
|
-
gid,
|
|
4851
|
-
setuid,
|
|
4852
|
-
setgid,
|
|
4853
|
-
sticky,
|
|
4854
|
-
unixMode,
|
|
4855
|
-
msdosAttributesRaw,
|
|
4856
|
-
msdosAttributes,
|
|
4857
|
-
unixExternalUpper
|
|
4858
|
-
});
|
|
4859
|
-
const headerInfo = getHeaderInfo(options);
|
|
4860
|
-
const dataDescriptorInfo = getDataDescriptorInfo(options);
|
|
4861
|
-
const metadataSize = getLength(headerInfo.localHeaderArray, dataDescriptorInfo.dataDescriptorArray);
|
|
4862
|
-
maximumEntrySize = metadataSize + maximumCompressedSize;
|
|
4863
|
-
if (zipWriter.options[OPTION_USDZ]) {
|
|
4864
|
-
maximumEntrySize += maximumEntrySize + 64;
|
|
4865
|
-
}
|
|
4866
|
-
zipWriter.pendingEntriesSize += maximumEntrySize;
|
|
4867
|
-
let fileEntry;
|
|
4868
|
-
try {
|
|
4869
|
-
fileEntry = await getFileEntry(zipWriter, name, reader, { headerInfo, dataDescriptorInfo, metadataSize }, options);
|
|
4870
|
-
} finally {
|
|
4871
|
-
zipWriter.pendingEntriesSize -= maximumEntrySize;
|
|
4872
|
-
}
|
|
4873
|
-
Object.assign(fileEntry, { name, comment, extraField });
|
|
4874
|
-
return new Entry(fileEntry);
|
|
5333
|
+
return {
|
|
5334
|
+
reader,
|
|
5335
|
+
resolvedOptions: {
|
|
5336
|
+
dataDescriptor,
|
|
5337
|
+
zip64,
|
|
5338
|
+
zip64UncompressedSize,
|
|
5339
|
+
zip64CompressedSize,
|
|
5340
|
+
uncompressedSize,
|
|
5341
|
+
level,
|
|
5342
|
+
compressionMethod,
|
|
5343
|
+
encrypted: encryptedEntry
|
|
5344
|
+
}
|
|
5345
|
+
};
|
|
4875
5346
|
}
|
|
4876
5347
|
|
|
4877
5348
|
async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
@@ -4888,37 +5359,40 @@
|
|
|
4888
5359
|
headerInfo
|
|
4889
5360
|
} = entryInfo;
|
|
4890
5361
|
const usdz = zipWriter.options[OPTION_USDZ];
|
|
4891
|
-
const previousFileEntry =
|
|
5362
|
+
const previousFileEntry = zipWriter.lastFileEntry;
|
|
4892
5363
|
let fileEntry = {};
|
|
4893
5364
|
let bufferedWrite;
|
|
4894
5365
|
let releaseLockWriter;
|
|
4895
5366
|
let releaseLockCurrentFileEntry;
|
|
4896
5367
|
let writingBufferedEntryData;
|
|
4897
5368
|
let writingEntryData;
|
|
5369
|
+
let writerSizeBeforeEntry;
|
|
5370
|
+
let flushedBufferedSize = 0;
|
|
4898
5371
|
let fileWriter;
|
|
4899
5372
|
files.set(name, fileEntry);
|
|
5373
|
+
zipWriter.lastFileEntry = fileEntry;
|
|
4900
5374
|
try {
|
|
4901
5375
|
let lockPreviousFileEntry;
|
|
4902
5376
|
if (keepOrder) {
|
|
4903
5377
|
lockPreviousFileEntry = previousFileEntry && previousFileEntry.lock;
|
|
4904
5378
|
requestLockCurrentFileEntry();
|
|
4905
5379
|
}
|
|
4906
|
-
if (
|
|
5380
|
+
if (options.bufferedWrite || !keepOrder || zipWriter.writerLocked || zipWriter.bufferedWrites || !dataDescriptor) {
|
|
5381
|
+
bufferedWrite = true;
|
|
5382
|
+
zipWriter.bufferedWrites++;
|
|
4907
5383
|
if (options.createTempStream) {
|
|
4908
5384
|
fileWriter = await options.createTempStream();
|
|
4909
5385
|
} else {
|
|
4910
5386
|
fileWriter = new TransformStream(UNDEFINED_VALUE, UNDEFINED_VALUE, { highWaterMark: INFINITY_VALUE });
|
|
4911
5387
|
}
|
|
4912
5388
|
fileWriter.size = 0;
|
|
4913
|
-
bufferedWrite = true;
|
|
4914
|
-
zipWriter.bufferedWrites++;
|
|
4915
5389
|
await initStream(writer);
|
|
4916
5390
|
} else {
|
|
4917
5391
|
fileWriter = writer;
|
|
4918
5392
|
await requestLockWriter();
|
|
4919
5393
|
}
|
|
4920
5394
|
await initStream(fileWriter);
|
|
4921
|
-
const {
|
|
5395
|
+
const { diskOffset } = writer;
|
|
4922
5396
|
if (zipWriter.addSplitZipSignature) {
|
|
4923
5397
|
delete zipWriter.addSplitZipSignature;
|
|
4924
5398
|
const signatureArray = new Uint8Array(4);
|
|
@@ -4927,21 +5401,20 @@
|
|
|
4927
5401
|
await writeData(writer, signatureArray);
|
|
4928
5402
|
zipWriter.offset += 4;
|
|
4929
5403
|
}
|
|
4930
|
-
if (usdz) {
|
|
5404
|
+
if (usdz && !bufferedWrite) {
|
|
4931
5405
|
appendExtraFieldUSDZ(entryInfo, zipWriter.offset - diskOffset);
|
|
4932
5406
|
}
|
|
4933
|
-
const {
|
|
4934
|
-
localHeaderView,
|
|
4935
|
-
localHeaderArray
|
|
4936
|
-
} = headerInfo;
|
|
5407
|
+
const { localHeaderArray } = headerInfo;
|
|
4937
5408
|
if (!bufferedWrite) {
|
|
4938
5409
|
await lockPreviousFileEntry;
|
|
4939
|
-
await skipDiskIfNeeded(
|
|
5410
|
+
await skipDiskIfNeeded();
|
|
4940
5411
|
}
|
|
4941
|
-
const
|
|
4942
|
-
|
|
5412
|
+
const diskNumberStart = writer.diskNumber;
|
|
5413
|
+
const entryOffset = getSegmentOffset(zipWriter, writer);
|
|
5414
|
+
fileEntry.diskNumberStart = diskNumberStart;
|
|
4943
5415
|
if (!bufferedWrite) {
|
|
4944
5416
|
writingEntryData = true;
|
|
5417
|
+
writerSizeBeforeEntry = writer.size;
|
|
4945
5418
|
await writeData(fileWriter, localHeaderArray);
|
|
4946
5419
|
}
|
|
4947
5420
|
fileEntry = await createFileEntry(reader, fileWriter, fileEntry, entryInfo, zipWriter.config, options);
|
|
@@ -4954,16 +5427,24 @@
|
|
|
4954
5427
|
await Promise.all([fileWriter.writable.getWriter().close(), lockPreviousFileEntry]);
|
|
4955
5428
|
await requestLockWriter();
|
|
4956
5429
|
writingBufferedEntryData = true;
|
|
5430
|
+
writerSizeBeforeEntry = writer.size;
|
|
5431
|
+
await skipDiskIfNeeded();
|
|
4957
5432
|
fileEntry.diskNumberStart = writer.diskNumber;
|
|
4958
|
-
fileEntry.offset = zipWriter
|
|
4959
|
-
|
|
4960
|
-
|
|
4961
|
-
|
|
4962
|
-
|
|
5433
|
+
fileEntry.offset = getSegmentOffset(zipWriter, writer);
|
|
5434
|
+
if (usdz) {
|
|
5435
|
+
// the padding depends on the entry offset, only known now that the writer is locked
|
|
5436
|
+
const previousMetadataSize = entryInfo.metadataSize;
|
|
5437
|
+
appendExtraFieldUSDZ(entryInfo, zipWriter.offset - writer.diskOffset);
|
|
5438
|
+
fileEntry.size += entryInfo.metadataSize - previousMetadataSize;
|
|
5439
|
+
}
|
|
5440
|
+
updateLocalHeader(fileEntry, headerInfo.localHeaderView, options);
|
|
5441
|
+
await writeData(writer, headerInfo.localHeaderArray);
|
|
5442
|
+
await flushBufferedData(fileWriter.readable, writer, signal, chunkLength => flushedBufferedSize += chunkLength);
|
|
4963
5443
|
writer.size += fileWriter.size;
|
|
4964
5444
|
writingBufferedEntryData = false;
|
|
4965
5445
|
} else {
|
|
4966
|
-
fileEntry.
|
|
5446
|
+
fileEntry.diskNumberStart = diskNumberStart;
|
|
5447
|
+
fileEntry.offset = entryOffset;
|
|
4967
5448
|
}
|
|
4968
5449
|
zipWriter.offset += fileEntry.size;
|
|
4969
5450
|
return fileEntry;
|
|
@@ -4977,10 +5458,9 @@
|
|
|
4977
5458
|
// ignored
|
|
4978
5459
|
}
|
|
4979
5460
|
}
|
|
5461
|
+
zipWriter.offset += writer.size - writerSizeBeforeEntry;
|
|
4980
5462
|
if (bufferedWrite) {
|
|
4981
|
-
zipWriter.offset +=
|
|
4982
|
-
} else {
|
|
4983
|
-
zipWriter.offset = fileWriter.size;
|
|
5463
|
+
zipWriter.offset += flushedBufferedSize;
|
|
4984
5464
|
}
|
|
4985
5465
|
}
|
|
4986
5466
|
files.delete(name);
|
|
@@ -5011,10 +5491,10 @@
|
|
|
5011
5491
|
await lockWriter;
|
|
5012
5492
|
}
|
|
5013
5493
|
|
|
5014
|
-
async function skipDiskIfNeeded(
|
|
5494
|
+
async function skipDiskIfNeeded() {
|
|
5015
5495
|
if (getLength(headerInfo.localHeaderArray) > writer.availableSize) {
|
|
5016
5496
|
writer.availableSize = 0;
|
|
5017
|
-
await writeData(
|
|
5497
|
+
await writeData(writer, new Uint8Array());
|
|
5018
5498
|
}
|
|
5019
5499
|
}
|
|
5020
5500
|
}
|
|
@@ -5155,6 +5635,10 @@
|
|
|
5155
5635
|
uncompressedSize = result.inputSize;
|
|
5156
5636
|
signature = result.signature;
|
|
5157
5637
|
}
|
|
5638
|
+
if ((!zip64CompressedSize && compressedSize >= MAX_32_BITS) ||
|
|
5639
|
+
(!zip64UncompressedSize && uncompressedSize >= MAX_32_BITS)) {
|
|
5640
|
+
throw new Error(ERR_UNSUPPORTED_FORMAT);
|
|
5641
|
+
}
|
|
5158
5642
|
} catch (error) {
|
|
5159
5643
|
if (error.outputSize !== UNDEFINED_VALUE) {
|
|
5160
5644
|
writer.size += error.outputSize;
|
|
@@ -5217,35 +5701,28 @@
|
|
|
5217
5701
|
uncompressedSize
|
|
5218
5702
|
} = options;
|
|
5219
5703
|
let { version, compressionMethod } = options;
|
|
5220
|
-
const compressed = !directory && (
|
|
5704
|
+
const compressed = !directory && (compressionMethod === UNDEFINED_VALUE
|
|
5705
|
+
? (level === UNDEFINED_VALUE || level > 0)
|
|
5706
|
+
: compressionMethod !== COMPRESSION_METHOD_STORE);
|
|
5221
5707
|
let rawLocalExtraFieldZip64;
|
|
5222
5708
|
const uncompressedFile = passThrough || !compressed;
|
|
5223
|
-
|
|
5224
|
-
|
|
5225
|
-
|
|
5226
|
-
|
|
5227
|
-
|
|
5228
|
-
|
|
5229
|
-
|
|
5230
|
-
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
setUint16(rawLocalExtraFieldZip64View, 2, getLength(rawLocalExtraFieldZip64) - 4);
|
|
5709
|
+
// entries without a data descriptor are always buffered (cf. getFileEntry), so the
|
|
5710
|
+
// zip64 extra field values can be patched into the local header before flushing it
|
|
5711
|
+
const zip64ExtraFieldComplete = zip64 && (options.bufferedWrite || !dataDescriptor || ((!zip64UncompressedSize && !zip64CompressedSize) || uncompressedFile));
|
|
5712
|
+
const writeLocalExtraFieldZip64 = zip64ExtraFieldComplete || (zip64 && dataDescriptor && (zip64UncompressedSize || zip64CompressedSize));
|
|
5713
|
+
if (zip64 && (zip64UncompressedSize || zip64CompressedSize)) {
|
|
5714
|
+
// APPNOTE 4.5.3: the zip64 extra field of a local header must include both the
|
|
5715
|
+
// uncompressed and compressed size fields
|
|
5716
|
+
const length = 4 + 16;
|
|
5717
|
+
const extraFieldZip64 = createRecordWriter(length);
|
|
5718
|
+
extraFieldZip64.uint16(EXTRAFIELD_TYPE_ZIP64);
|
|
5719
|
+
extraFieldZip64.uint16(length - 4);
|
|
5720
|
+
rawLocalExtraFieldZip64 = extraFieldZip64.array;
|
|
5236
5721
|
if (zip64ExtraFieldComplete) {
|
|
5237
|
-
|
|
5238
|
-
|
|
5239
|
-
|
|
5240
|
-
|
|
5241
|
-
rawLocalExtraFieldZip64Offset += 8;
|
|
5242
|
-
}
|
|
5243
|
-
if (zip64CompressedSize && uncompressedFile) {
|
|
5244
|
-
setBigUint64(rawLocalExtraFieldZip64View, rawLocalExtraFieldZip64Offset, BigInt(uncompressedSize));
|
|
5245
|
-
rawLocalExtraFieldZip64Offset += 8;
|
|
5246
|
-
}
|
|
5247
|
-
if (rawLocalExtraFieldZip64Offset == 4) {
|
|
5248
|
-
rawLocalExtraFieldZip64 = new Uint8Array();
|
|
5722
|
+
extraFieldZip64.uint64(uncompressedSize);
|
|
5723
|
+
if (uncompressedFile) {
|
|
5724
|
+
const encryptionOverhead = encrypted ? (zipCrypto ? 12 : 16 + encryptionStrength * 4) : 0;
|
|
5725
|
+
extraFieldZip64.uint64(passThrough ? 0 : uncompressedSize + encryptionOverhead);
|
|
5249
5726
|
}
|
|
5250
5727
|
}
|
|
5251
5728
|
} else {
|
|
@@ -5253,11 +5730,11 @@
|
|
|
5253
5730
|
}
|
|
5254
5731
|
let rawExtraFieldAES;
|
|
5255
5732
|
if (encrypted && !zipCrypto) {
|
|
5256
|
-
|
|
5257
|
-
|
|
5258
|
-
|
|
5259
|
-
|
|
5260
|
-
|
|
5733
|
+
const extraFieldAES = createRecordWriter(getLength(EXTRAFIELD_DATA_AES) + 2);
|
|
5734
|
+
extraFieldAES.uint16(EXTRAFIELD_TYPE_AES);
|
|
5735
|
+
extraFieldAES.bytes(EXTRAFIELD_DATA_AES);
|
|
5736
|
+
rawExtraFieldAES = extraFieldAES.array;
|
|
5737
|
+
rawExtraFieldAES[8] = encryptionStrength;
|
|
5261
5738
|
} else {
|
|
5262
5739
|
rawExtraFieldAES = new Uint8Array();
|
|
5263
5740
|
}
|
|
@@ -5265,33 +5742,38 @@
|
|
|
5265
5742
|
let rawExtraFieldExtendedTimestamp;
|
|
5266
5743
|
let extraFieldExtendedTimestampFlag;
|
|
5267
5744
|
if (extendedTimestamp) {
|
|
5268
|
-
|
|
5269
|
-
|
|
5270
|
-
|
|
5271
|
-
|
|
5272
|
-
|
|
5273
|
-
|
|
5274
|
-
|
|
5275
|
-
|
|
5276
|
-
|
|
5277
|
-
|
|
5278
|
-
|
|
5279
|
-
|
|
5280
|
-
|
|
5281
|
-
|
|
5282
|
-
|
|
5745
|
+
const lastModTimeUnix = getTimeUnix(lastModDate);
|
|
5746
|
+
if (inUnixTimeRange(lastModTimeUnix)) {
|
|
5747
|
+
const extraFieldTimestampLength = 9 + (lastAccessDate ? 4 : 0) + (creationDate ? 4 : 0);
|
|
5748
|
+
const extraFieldTimestamp = createRecordWriter(extraFieldTimestampLength);
|
|
5749
|
+
extraFieldExtendedTimestampFlag = 0x1 + (lastAccessDate ? 0x2 : 0) + (creationDate ? 0x4 : 0);
|
|
5750
|
+
extraFieldTimestamp.uint16(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
|
|
5751
|
+
extraFieldTimestamp.uint16(extraFieldTimestampLength - 4);
|
|
5752
|
+
extraFieldTimestamp.uint8(extraFieldExtendedTimestampFlag);
|
|
5753
|
+
extraFieldTimestamp.uint32(lastModTimeUnix);
|
|
5754
|
+
if (lastAccessDate) {
|
|
5755
|
+
extraFieldTimestamp.uint32(clampUnixTime(getTimeUnix(lastAccessDate)));
|
|
5756
|
+
}
|
|
5757
|
+
if (creationDate) {
|
|
5758
|
+
extraFieldTimestamp.uint32(clampUnixTime(getTimeUnix(creationDate)));
|
|
5759
|
+
}
|
|
5760
|
+
rawExtraFieldExtendedTimestamp = extraFieldTimestamp.array;
|
|
5761
|
+
} else {
|
|
5762
|
+
// the date cannot be stored as a 32-bit time_t; the NTFS field replaces it
|
|
5763
|
+
rawExtraFieldExtendedTimestamp = new Uint8Array();
|
|
5283
5764
|
}
|
|
5284
5765
|
try {
|
|
5285
|
-
rawExtraFieldNTFS = new Uint8Array(36);
|
|
5286
|
-
const extraFieldNTFSView = getDataView(rawExtraFieldNTFS);
|
|
5287
5766
|
const lastModTimeNTFS = getTimeNTFS(lastModDate);
|
|
5288
|
-
|
|
5289
|
-
|
|
5290
|
-
|
|
5291
|
-
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
|
|
5767
|
+
const extraFieldNTFS = createRecordWriter(36);
|
|
5768
|
+
extraFieldNTFS.uint16(EXTRAFIELD_TYPE_NTFS);
|
|
5769
|
+
extraFieldNTFS.uint16(32);
|
|
5770
|
+
extraFieldNTFS.skip(4);
|
|
5771
|
+
extraFieldNTFS.uint16(EXTRAFIELD_TYPE_NTFS_TAG1);
|
|
5772
|
+
extraFieldNTFS.uint16(24);
|
|
5773
|
+
extraFieldNTFS.uint64(lastModTimeNTFS);
|
|
5774
|
+
extraFieldNTFS.uint64(getTimeNTFS(lastAccessDate) || lastModTimeNTFS);
|
|
5775
|
+
extraFieldNTFS.uint64(getTimeNTFS(creationDate) || lastModTimeNTFS);
|
|
5776
|
+
rawExtraFieldNTFS = extraFieldNTFS.array;
|
|
5295
5777
|
} catch {
|
|
5296
5778
|
rawExtraFieldNTFS = new Uint8Array();
|
|
5297
5779
|
}
|
|
@@ -5300,41 +5782,27 @@
|
|
|
5300
5782
|
}
|
|
5301
5783
|
let rawExtraFieldUnix;
|
|
5302
5784
|
try {
|
|
5303
|
-
const { uid, gid,
|
|
5304
|
-
if (unixExtraFieldType && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE
|
|
5785
|
+
const { uid, gid, unixExtraFieldType } = options;
|
|
5786
|
+
if (unixExtraFieldType == INFOZIP_EXTRA_FIELD_TYPE && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
|
|
5305
5787
|
const uidBytes = packUnixId(uid);
|
|
5306
5788
|
const gidBytes = packUnixId(gid);
|
|
5307
|
-
|
|
5308
|
-
|
|
5309
|
-
|
|
5310
|
-
|
|
5311
|
-
|
|
5312
|
-
|
|
5313
|
-
|
|
5314
|
-
|
|
5315
|
-
|
|
5316
|
-
|
|
5317
|
-
|
|
5318
|
-
|
|
5319
|
-
|
|
5320
|
-
|
|
5321
|
-
|
|
5322
|
-
|
|
5323
|
-
|
|
5324
|
-
rawExtraFieldUnix = new Uint8Array(4 + payloadLength);
|
|
5325
|
-
const rawExtraFieldUnixView = getDataView(rawExtraFieldUnix);
|
|
5326
|
-
setUint16(rawExtraFieldUnixView, 0, unixExtraFieldType == INFOZIP_EXTRA_FIELD_TYPE ? EXTRAFIELD_TYPE_INFOZIP : EXTRAFIELD_TYPE_UNIX);
|
|
5327
|
-
setUint16(rawExtraFieldUnixView, 2, payloadLength);
|
|
5328
|
-
setUint8(rawExtraFieldUnixView, 4, 1);
|
|
5329
|
-
setUint8(rawExtraFieldUnixView, 5, uidBytes.length);
|
|
5330
|
-
let offset = 6;
|
|
5331
|
-
arraySet(rawExtraFieldUnix, uidBytes, offset);
|
|
5332
|
-
offset += uidBytes.length;
|
|
5333
|
-
setUint8(rawExtraFieldUnixView, offset, gidBytes.length);
|
|
5334
|
-
offset++;
|
|
5335
|
-
arraySet(rawExtraFieldUnix, gidBytes, offset);
|
|
5336
|
-
offset += gidBytes.length;
|
|
5337
|
-
arraySet(rawExtraFieldUnix, modeArray, offset);
|
|
5789
|
+
const payloadLength = 3 + uidBytes.length + gidBytes.length;
|
|
5790
|
+
const extraFieldUnix = createRecordWriter(4 + payloadLength);
|
|
5791
|
+
extraFieldUnix.uint16(EXTRAFIELD_TYPE_INFOZIP);
|
|
5792
|
+
extraFieldUnix.uint16(payloadLength);
|
|
5793
|
+
extraFieldUnix.uint8(1);
|
|
5794
|
+
extraFieldUnix.uint8(uidBytes.length);
|
|
5795
|
+
extraFieldUnix.bytes(uidBytes);
|
|
5796
|
+
extraFieldUnix.uint8(gidBytes.length);
|
|
5797
|
+
extraFieldUnix.bytes(gidBytes);
|
|
5798
|
+
rawExtraFieldUnix = extraFieldUnix.array;
|
|
5799
|
+
} else if (unixExtraFieldType == UNIX_EXTRA_FIELD_TYPE && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
|
|
5800
|
+
const extraFieldUnix = createRecordWriter(8);
|
|
5801
|
+
extraFieldUnix.uint16(EXTRAFIELD_TYPE_UNIX);
|
|
5802
|
+
extraFieldUnix.uint16(4);
|
|
5803
|
+
extraFieldUnix.uint16((uid === UNDEFINED_VALUE ? 0 : uid) & MAX_16_BITS);
|
|
5804
|
+
extraFieldUnix.uint16((gid === UNDEFINED_VALUE ? 0 : gid) & MAX_16_BITS);
|
|
5805
|
+
rawExtraFieldUnix = extraFieldUnix.array;
|
|
5338
5806
|
} else {
|
|
5339
5807
|
rawExtraFieldUnix = new Uint8Array();
|
|
5340
5808
|
}
|
|
@@ -5352,8 +5820,11 @@
|
|
|
5352
5820
|
rawExtraFieldAES[9] = compressionMethod;
|
|
5353
5821
|
compressionMethod = COMPRESSION_METHOD_AES;
|
|
5354
5822
|
}
|
|
5355
|
-
const localExtraFieldZip64Length =
|
|
5823
|
+
const localExtraFieldZip64Length = writeLocalExtraFieldZip64 ? getLength(rawLocalExtraFieldZip64) : 0;
|
|
5356
5824
|
const extraFieldLength = localExtraFieldZip64Length + getLength(rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField);
|
|
5825
|
+
if (extraFieldLength > MAX_16_BITS) {
|
|
5826
|
+
throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
|
|
5827
|
+
}
|
|
5357
5828
|
const {
|
|
5358
5829
|
headerArray,
|
|
5359
5830
|
headerView,
|
|
@@ -5369,29 +5840,27 @@
|
|
|
5369
5840
|
zip64UncompressedSize,
|
|
5370
5841
|
extraFieldLength
|
|
5371
5842
|
});
|
|
5372
|
-
|
|
5373
|
-
const localHeaderArray =
|
|
5843
|
+
const localHeader = createRecordWriter(HEADER_SIZE + getLength(rawFilename) + extraFieldLength);
|
|
5844
|
+
const localHeaderArray = localHeader.array;
|
|
5374
5845
|
const localHeaderView = getDataView(localHeaderArray);
|
|
5375
|
-
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
|
|
5380
|
-
|
|
5381
|
-
|
|
5382
|
-
|
|
5383
|
-
|
|
5384
|
-
|
|
5385
|
-
|
|
5386
|
-
localHeaderOffset += getLength(rawExtraFieldExtendedTimestamp);
|
|
5387
|
-
arraySet(localHeaderArray, rawExtraFieldNTFS, localHeaderOffset);
|
|
5388
|
-
localHeaderOffset += getLength(rawExtraFieldNTFS);
|
|
5389
|
-
arraySet(localHeaderArray, rawExtraFieldUnix, localHeaderOffset);
|
|
5390
|
-
localHeaderOffset += getLength(rawExtraFieldUnix);
|
|
5391
|
-
arraySet(localHeaderArray, rawExtraField, localHeaderOffset);
|
|
5846
|
+
localHeader.uint32(LOCAL_FILE_HEADER_SIGNATURE);
|
|
5847
|
+
localHeader.bytes(headerArray);
|
|
5848
|
+
localHeader.bytes(rawFilename);
|
|
5849
|
+
if (writeLocalExtraFieldZip64) {
|
|
5850
|
+
localHeader.bytes(rawLocalExtraFieldZip64);
|
|
5851
|
+
}
|
|
5852
|
+
localHeader.bytes(rawExtraFieldAES);
|
|
5853
|
+
localHeader.bytes(rawExtraFieldExtendedTimestamp);
|
|
5854
|
+
localHeader.bytes(rawExtraFieldNTFS);
|
|
5855
|
+
localHeader.bytes(rawExtraFieldUnix);
|
|
5856
|
+
localHeader.bytes(rawExtraField);
|
|
5392
5857
|
if (dataDescriptor) {
|
|
5393
|
-
|
|
5394
|
-
|
|
5858
|
+
if (!zip64CompressedSize) {
|
|
5859
|
+
setUint32(localHeaderView, HEADER_OFFSET_COMPRESSED_SIZE + LOCAL_HEADER_COMMON_OFFSET, 0);
|
|
5860
|
+
}
|
|
5861
|
+
if (!zip64UncompressedSize) {
|
|
5862
|
+
setUint32(localHeaderView, HEADER_OFFSET_UNCOMPRESSED_SIZE + LOCAL_HEADER_COMMON_OFFSET, 0);
|
|
5863
|
+
}
|
|
5395
5864
|
}
|
|
5396
5865
|
return {
|
|
5397
5866
|
localHeaderArray,
|
|
@@ -5418,7 +5887,7 @@
|
|
|
5418
5887
|
function appendExtraFieldUSDZ(entryInfo, zipWriterOffset) {
|
|
5419
5888
|
const { headerInfo } = entryInfo;
|
|
5420
5889
|
let { localHeaderArray, extraFieldLength } = headerInfo;
|
|
5421
|
-
let localHeaderArrayView
|
|
5890
|
+
let localHeaderArrayView;
|
|
5422
5891
|
let extraBytesLength = 64 - ((zipWriterOffset + getLength(localHeaderArray)) % 64);
|
|
5423
5892
|
if (extraBytesLength < 4) {
|
|
5424
5893
|
extraBytesLength += 64;
|
|
@@ -5426,13 +5895,14 @@
|
|
|
5426
5895
|
const rawExtraFieldUSDZ = new Uint8Array(extraBytesLength);
|
|
5427
5896
|
const extraFieldUSDZView = getDataView(rawExtraFieldUSDZ);
|
|
5428
5897
|
setUint16(extraFieldUSDZView, 0, EXTRAFIELD_TYPE_USDZ);
|
|
5429
|
-
setUint16(extraFieldUSDZView, 2, extraBytesLength -
|
|
5898
|
+
setUint16(extraFieldUSDZView, 2, extraBytesLength - 4);
|
|
5430
5899
|
const previousLocalHeaderArray = localHeaderArray;
|
|
5431
5900
|
headerInfo.localHeaderArray = localHeaderArray = new Uint8Array(getLength(previousLocalHeaderArray) + extraBytesLength);
|
|
5432
5901
|
arraySet(localHeaderArray, previousLocalHeaderArray);
|
|
5433
5902
|
arraySet(localHeaderArray, rawExtraFieldUSDZ, getLength(previousLocalHeaderArray));
|
|
5434
5903
|
localHeaderArrayView = getDataView(localHeaderArray);
|
|
5435
5904
|
setUint16(localHeaderArrayView, 28, extraFieldLength + extraBytesLength);
|
|
5905
|
+
headerInfo.localHeaderView = localHeaderArrayView;
|
|
5436
5906
|
entryInfo.metadataSize += extraBytesLength;
|
|
5437
5907
|
}
|
|
5438
5908
|
|
|
@@ -5555,37 +6025,32 @@
|
|
|
5555
6025
|
}, localHeaderView, { dataDescriptor }) {
|
|
5556
6026
|
if (!dataDescriptor) {
|
|
5557
6027
|
if (!encrypted) {
|
|
5558
|
-
setUint32(localHeaderView, HEADER_OFFSET_SIGNATURE +
|
|
6028
|
+
setUint32(localHeaderView, HEADER_OFFSET_SIGNATURE + LOCAL_HEADER_COMMON_OFFSET, signature);
|
|
5559
6029
|
}
|
|
5560
6030
|
if (!zip64CompressedSize) {
|
|
5561
|
-
setUint32(localHeaderView, HEADER_OFFSET_COMPRESSED_SIZE +
|
|
6031
|
+
setUint32(localHeaderView, HEADER_OFFSET_COMPRESSED_SIZE + LOCAL_HEADER_COMMON_OFFSET, compressedSize);
|
|
5562
6032
|
}
|
|
5563
6033
|
if (!zip64UncompressedSize) {
|
|
5564
|
-
setUint32(localHeaderView, HEADER_OFFSET_UNCOMPRESSED_SIZE +
|
|
6034
|
+
setUint32(localHeaderView, HEADER_OFFSET_UNCOMPRESSED_SIZE + LOCAL_HEADER_COMMON_OFFSET, uncompressedSize);
|
|
5565
6035
|
}
|
|
5566
6036
|
}
|
|
5567
6037
|
if (zip64 && localExtraFieldZip64Length) {
|
|
5568
|
-
|
|
5569
|
-
|
|
5570
|
-
|
|
5571
|
-
|
|
5572
|
-
}
|
|
5573
|
-
if (zip64CompressedSize) {
|
|
5574
|
-
setBigUint64(localHeaderView, localHeaderOffset, BigInt(compressedSize));
|
|
5575
|
-
localHeaderOffset += 8;
|
|
5576
|
-
}
|
|
6038
|
+
// the local zip64 extra field always contains both size slots
|
|
6039
|
+
const localHeaderOffset = HEADER_SIZE + getLength(rawFilename) + 4;
|
|
6040
|
+
setBigUint64(localHeaderView, localHeaderOffset, BigInt(uncompressedSize));
|
|
6041
|
+
setBigUint64(localHeaderView, localHeaderOffset + 8, BigInt(compressedSize));
|
|
5577
6042
|
}
|
|
5578
6043
|
}
|
|
5579
6044
|
|
|
5580
6045
|
|
|
5581
6046
|
async function closeFile(zipWriter, comment, options) {
|
|
5582
|
-
const
|
|
5583
|
-
const {
|
|
5584
|
-
|
|
5585
|
-
|
|
6047
|
+
const directoryDataLength = createDirectoryRecords(zipWriter.files);
|
|
6048
|
+
const { cdStartDiskNumber, cdStartDiskOffset } = await writeDirectoryRecords(zipWriter, directoryDataLength, options);
|
|
6049
|
+
await writeEndOfDirectoryRecord(zipWriter, comment, options, { cdStartDiskNumber, cdStartDiskOffset, directoryDataLength });
|
|
6050
|
+
}
|
|
6051
|
+
|
|
6052
|
+
function createDirectoryRecords(files) {
|
|
5586
6053
|
let directoryDataLength = 0;
|
|
5587
|
-
let directoryOffset = zipWriter.offset - diskOffset;
|
|
5588
|
-
let filesLength = files.size;
|
|
5589
6054
|
for (const [, fileEntry] of files) {
|
|
5590
6055
|
const {
|
|
5591
6056
|
rawFilename,
|
|
@@ -5602,24 +6067,27 @@
|
|
|
5602
6067
|
uncompressedSize,
|
|
5603
6068
|
compressedSize
|
|
5604
6069
|
} = fileEntry;
|
|
5605
|
-
const zip64Offset = fileEntry.offset
|
|
5606
|
-
const zip64DiskNumberStart = fileEntry.diskNumberStart
|
|
6070
|
+
const zip64Offset = fileEntry.offset >= MAX_32_BITS;
|
|
6071
|
+
const zip64DiskNumberStart = fileEntry.diskNumberStart >= MAX_16_BITS;
|
|
5607
6072
|
let rawExtraFieldZip64;
|
|
5608
6073
|
if (zip64Offset || zip64DiskNumberStart || zip64UncompressedSize || zip64CompressedSize) {
|
|
5609
|
-
|
|
5610
|
-
|
|
5611
|
-
|
|
5612
|
-
|
|
5613
|
-
if (
|
|
5614
|
-
|
|
5615
|
-
|
|
5616
|
-
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
if (
|
|
5620
|
-
|
|
5621
|
-
|
|
5622
|
-
if (zip64DiskNumberStart) {
|
|
6074
|
+
const length = 4 + (zip64UncompressedSize ? 8 : 0) + (zip64CompressedSize ? 8 : 0) + (zip64Offset ? 8 : 0) + (zip64DiskNumberStart ? 4 : 0);
|
|
6075
|
+
const extraFieldZip64 = createRecordWriter(length);
|
|
6076
|
+
extraFieldZip64.uint16(EXTRAFIELD_TYPE_ZIP64);
|
|
6077
|
+
extraFieldZip64.uint16(length - 4);
|
|
6078
|
+
if (zip64UncompressedSize) {
|
|
6079
|
+
extraFieldZip64.uint64(uncompressedSize);
|
|
6080
|
+
}
|
|
6081
|
+
if (zip64CompressedSize) {
|
|
6082
|
+
extraFieldZip64.uint64(compressedSize);
|
|
6083
|
+
}
|
|
6084
|
+
if (zip64Offset) {
|
|
6085
|
+
extraFieldZip64.uint64(fileEntry.offset);
|
|
6086
|
+
}
|
|
6087
|
+
if (zip64DiskNumberStart) {
|
|
6088
|
+
extraFieldZip64.uint32(fileEntry.diskNumberStart);
|
|
6089
|
+
}
|
|
6090
|
+
rawExtraFieldZip64 = extraFieldZip64.array;
|
|
5623
6091
|
} else {
|
|
5624
6092
|
rawExtraFieldZip64 = new Uint8Array();
|
|
5625
6093
|
}
|
|
@@ -5627,32 +6095,41 @@
|
|
|
5627
6095
|
fileEntry.zip64Offset = zip64Offset;
|
|
5628
6096
|
fileEntry.zip64DiskNumberStart = zip64DiskNumberStart;
|
|
5629
6097
|
let rawExtraFieldTimestamp;
|
|
5630
|
-
|
|
5631
|
-
|
|
5632
|
-
const
|
|
5633
|
-
|
|
5634
|
-
|
|
5635
|
-
|
|
5636
|
-
|
|
6098
|
+
const lastModTimeUnix = getTimeUnix(lastModDate);
|
|
6099
|
+
if (extendedTimestamp && inUnixTimeRange(lastModTimeUnix)) {
|
|
6100
|
+
const extraFieldTimestamp = createRecordWriter(9);
|
|
6101
|
+
extraFieldTimestamp.uint16(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
|
|
6102
|
+
extraFieldTimestamp.uint16(5);
|
|
6103
|
+
extraFieldTimestamp.uint8(extraFieldExtendedTimestampFlag);
|
|
6104
|
+
extraFieldTimestamp.uint32(lastModTimeUnix);
|
|
6105
|
+
rawExtraFieldTimestamp = extraFieldTimestamp.array;
|
|
5637
6106
|
} else {
|
|
5638
6107
|
rawExtraFieldTimestamp = new Uint8Array();
|
|
5639
6108
|
}
|
|
5640
6109
|
fileEntry.rawExtraFieldExtendedTimestamp = rawExtraFieldTimestamp;
|
|
5641
|
-
|
|
5642
|
-
|
|
5643
|
-
|
|
5644
|
-
|
|
5645
|
-
|
|
5646
|
-
|
|
5647
|
-
|
|
5648
|
-
|
|
5649
|
-
|
|
5650
|
-
|
|
6110
|
+
const extraFieldLength = getLength(
|
|
6111
|
+
rawExtraFieldZip64,
|
|
6112
|
+
rawExtraFieldAES,
|
|
6113
|
+
rawExtraFieldNTFS,
|
|
6114
|
+
rawExtraFieldUnix,
|
|
6115
|
+
rawExtraFieldTimestamp,
|
|
6116
|
+
rawExtraField);
|
|
6117
|
+
if (extraFieldLength > MAX_16_BITS) {
|
|
6118
|
+
throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
|
|
6119
|
+
}
|
|
6120
|
+
directoryDataLength += CENTRAL_FILE_HEADER_LENGTH + getLength(rawFilename, rawComment) + extraFieldLength;
|
|
5651
6121
|
}
|
|
6122
|
+
return directoryDataLength;
|
|
6123
|
+
}
|
|
6124
|
+
|
|
6125
|
+
async function writeDirectoryRecords(zipWriter, directoryDataLength, options) {
|
|
6126
|
+
const { files, writer } = zipWriter;
|
|
5652
6127
|
const directoryArray = new Uint8Array(directoryDataLength);
|
|
5653
|
-
const directoryView = getDataView(directoryArray);
|
|
5654
6128
|
await initStream(writer);
|
|
6129
|
+
let offset = 0;
|
|
5655
6130
|
let directoryDiskOffset = 0;
|
|
6131
|
+
let cdStartDiskNumber = writer.diskNumber;
|
|
6132
|
+
let cdStartDiskOffset = writer.diskOffset;
|
|
5656
6133
|
for (const [indexFileEntry, fileEntry] of Array.from(files.values()).entries()) {
|
|
5657
6134
|
const {
|
|
5658
6135
|
offset: fileEntryOffset,
|
|
@@ -5678,52 +6155,46 @@
|
|
|
5678
6155
|
compressedSize
|
|
5679
6156
|
} = fileEntry;
|
|
5680
6157
|
const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField);
|
|
5681
|
-
|
|
5682
|
-
|
|
6158
|
+
const directoryRecordLength = CENTRAL_FILE_HEADER_LENGTH + getLength(rawFilename, rawComment) + extraFieldLength;
|
|
6159
|
+
if (offset + directoryRecordLength - directoryDiskOffset > writer.availableSize) {
|
|
6160
|
+
await writeData(writer, directoryArray.slice(directoryDiskOffset, offset));
|
|
6161
|
+
directoryDiskOffset = offset;
|
|
6162
|
+
writer.availableSize = 0;
|
|
6163
|
+
await writeData(writer, new Uint8Array());
|
|
6164
|
+
}
|
|
6165
|
+
if (indexFileEntry == 0) {
|
|
6166
|
+
cdStartDiskNumber = writer.diskNumber;
|
|
6167
|
+
cdStartDiskOffset = writer.diskOffset;
|
|
6168
|
+
}
|
|
5683
6169
|
if (!zip64UncompressedSize) {
|
|
5684
6170
|
setUint32(headerView, HEADER_OFFSET_UNCOMPRESSED_SIZE, uncompressedSize);
|
|
5685
6171
|
}
|
|
5686
6172
|
if (!zip64CompressedSize) {
|
|
5687
6173
|
setUint32(headerView, HEADER_OFFSET_COMPRESSED_SIZE, compressedSize);
|
|
5688
6174
|
}
|
|
5689
|
-
|
|
5690
|
-
|
|
5691
|
-
|
|
5692
|
-
|
|
5693
|
-
|
|
5694
|
-
|
|
5695
|
-
|
|
5696
|
-
|
|
5697
|
-
|
|
5698
|
-
|
|
5699
|
-
|
|
5700
|
-
|
|
5701
|
-
|
|
5702
|
-
|
|
5703
|
-
|
|
5704
|
-
|
|
5705
|
-
|
|
5706
|
-
|
|
5707
|
-
|
|
5708
|
-
|
|
5709
|
-
|
|
5710
|
-
|
|
5711
|
-
|
|
5712
|
-
directoryOffset += getLength(rawExtraFieldExtendedTimestamp);
|
|
5713
|
-
arraySet(directoryArray, rawExtraFieldNTFS, directoryOffset);
|
|
5714
|
-
directoryOffset += getLength(rawExtraFieldNTFS);
|
|
5715
|
-
arraySet(directoryArray, rawExtraFieldUnix, directoryOffset);
|
|
5716
|
-
directoryOffset += getLength(rawExtraFieldUnix);
|
|
5717
|
-
arraySet(directoryArray, rawExtraField, directoryOffset);
|
|
5718
|
-
directoryOffset += getLength(rawExtraField);
|
|
5719
|
-
arraySet(directoryArray, rawComment, directoryOffset);
|
|
5720
|
-
directoryOffset += getLength(rawComment);
|
|
5721
|
-
if (offset - directoryDiskOffset > writer.availableSize) {
|
|
5722
|
-
writer.availableSize = 0;
|
|
5723
|
-
await writeData(writer, directoryArray.slice(directoryDiskOffset, offset));
|
|
5724
|
-
directoryDiskOffset = offset;
|
|
5725
|
-
}
|
|
5726
|
-
offset = directoryOffset;
|
|
6175
|
+
if ((zip64Offset || zip64DiskNumberStart) && fileEntry.version < VERSION_ZIP64) {
|
|
6176
|
+
setUint16(headerView, HEADER_OFFSET_VERSION, VERSION_ZIP64);
|
|
6177
|
+
}
|
|
6178
|
+
const directoryRecord = createRecordWriter(directoryRecordLength);
|
|
6179
|
+
directoryRecord.uint32(CENTRAL_FILE_HEADER_SIGNATURE);
|
|
6180
|
+
directoryRecord.uint16(versionMadeBy);
|
|
6181
|
+
directoryRecord.bytes(headerArray.subarray(0, HEADER_SIZE - 4 - 2));
|
|
6182
|
+
directoryRecord.uint16(extraFieldLength);
|
|
6183
|
+
directoryRecord.uint16(getLength(rawComment));
|
|
6184
|
+
directoryRecord.uint16(zip64DiskNumberStart ? MAX_16_BITS : diskNumberStart);
|
|
6185
|
+
directoryRecord.uint16(internalFileAttributes);
|
|
6186
|
+
directoryRecord.uint32(externalFileAttributes);
|
|
6187
|
+
directoryRecord.uint32(zip64Offset ? MAX_32_BITS : fileEntryOffset);
|
|
6188
|
+
directoryRecord.bytes(rawFilename);
|
|
6189
|
+
directoryRecord.bytes(rawExtraFieldZip64);
|
|
6190
|
+
directoryRecord.bytes(rawExtraFieldAES);
|
|
6191
|
+
directoryRecord.bytes(rawExtraFieldExtendedTimestamp);
|
|
6192
|
+
directoryRecord.bytes(rawExtraFieldNTFS);
|
|
6193
|
+
directoryRecord.bytes(rawExtraFieldUnix);
|
|
6194
|
+
directoryRecord.bytes(rawExtraField);
|
|
6195
|
+
directoryRecord.bytes(rawComment);
|
|
6196
|
+
arraySet(directoryArray, directoryRecord.array, offset);
|
|
6197
|
+
offset += directoryRecordLength;
|
|
5727
6198
|
if (options.onprogress) {
|
|
5728
6199
|
try {
|
|
5729
6200
|
await options.onprogress(indexFileEntry + 1, files.size, new Entry(fileEntry));
|
|
@@ -5733,36 +6204,53 @@
|
|
|
5733
6204
|
}
|
|
5734
6205
|
}
|
|
5735
6206
|
await writeData(writer, directoryDiskOffset ? directoryArray.slice(directoryDiskOffset) : directoryArray);
|
|
6207
|
+
return { cdStartDiskNumber, cdStartDiskOffset };
|
|
6208
|
+
}
|
|
6209
|
+
|
|
6210
|
+
async function writeEndOfDirectoryRecord(zipWriter, comment, options, cdInfo) {
|
|
6211
|
+
const { writer } = zipWriter;
|
|
6212
|
+
const { cdStartDiskNumber, cdStartDiskOffset } = cdInfo;
|
|
6213
|
+
let { directoryDataLength } = cdInfo;
|
|
6214
|
+
let filesLength = zipWriter.files.size;
|
|
6215
|
+
let diskNumber = cdStartDiskNumber;
|
|
6216
|
+
let directoryOffset = zipWriter.offset - cdStartDiskOffset - (cdStartDiskNumber ? zipWriter.initialOffset : 0);
|
|
5736
6217
|
let lastDiskNumber = writer.diskNumber;
|
|
5737
|
-
|
|
5738
|
-
if (availableSize < END_OF_CENTRAL_DIR_LENGTH) {
|
|
6218
|
+
if (writer.availableSize < END_OF_CENTRAL_DIR_LENGTH) {
|
|
5739
6219
|
lastDiskNumber++;
|
|
5740
6220
|
}
|
|
5741
6221
|
let zip64 = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIP64);
|
|
5742
|
-
if (directoryOffset
|
|
6222
|
+
if (directoryOffset >= MAX_32_BITS || directoryDataLength >= MAX_32_BITS || filesLength >= MAX_16_BITS || lastDiskNumber >= MAX_16_BITS) {
|
|
5743
6223
|
if (zip64 === false) {
|
|
5744
6224
|
throw new Error(ERR_UNSUPPORTED_FORMAT);
|
|
5745
6225
|
} else {
|
|
5746
6226
|
zip64 = true;
|
|
5747
6227
|
}
|
|
5748
6228
|
}
|
|
5749
|
-
const
|
|
5750
|
-
|
|
5751
|
-
|
|
6229
|
+
const commentLength = getLength(comment);
|
|
6230
|
+
if (commentLength > MAX_16_BITS) {
|
|
6231
|
+
throw new Error(ERR_INVALID_COMMENT);
|
|
6232
|
+
}
|
|
6233
|
+
const endOfdirectoryRecord = createRecordWriter(zip64 ? ZIP64_END_OF_CENTRAL_DIR_TOTAL_LENGTH : END_OF_CENTRAL_DIR_LENGTH);
|
|
6234
|
+
if (getLength(endOfdirectoryRecord.array) + commentLength > writer.availableSize) {
|
|
6235
|
+
writer.availableSize = 0;
|
|
6236
|
+
await writeData(writer, new Uint8Array());
|
|
6237
|
+
}
|
|
6238
|
+
lastDiskNumber = writer.diskNumber;
|
|
5752
6239
|
if (zip64) {
|
|
5753
|
-
|
|
5754
|
-
|
|
5755
|
-
|
|
5756
|
-
|
|
5757
|
-
|
|
5758
|
-
|
|
5759
|
-
|
|
5760
|
-
|
|
5761
|
-
|
|
5762
|
-
|
|
5763
|
-
|
|
5764
|
-
|
|
5765
|
-
|
|
6240
|
+
endOfdirectoryRecord.uint32(ZIP64_END_OF_CENTRAL_DIR_SIGNATURE);
|
|
6241
|
+
endOfdirectoryRecord.uint64(44);
|
|
6242
|
+
endOfdirectoryRecord.uint16(45);
|
|
6243
|
+
endOfdirectoryRecord.uint16(45);
|
|
6244
|
+
endOfdirectoryRecord.uint32(lastDiskNumber);
|
|
6245
|
+
endOfdirectoryRecord.uint32(diskNumber);
|
|
6246
|
+
endOfdirectoryRecord.uint64(filesLength);
|
|
6247
|
+
endOfdirectoryRecord.uint64(filesLength);
|
|
6248
|
+
endOfdirectoryRecord.uint64(directoryDataLength);
|
|
6249
|
+
endOfdirectoryRecord.uint64(directoryOffset);
|
|
6250
|
+
endOfdirectoryRecord.uint32(ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIGNATURE);
|
|
6251
|
+
endOfdirectoryRecord.uint32(lastDiskNumber);
|
|
6252
|
+
endOfdirectoryRecord.uint64(BigInt(zipWriter.offset) + BigInt(directoryDataLength) - BigInt(writer.diskOffset) - BigInt(writer.diskNumber ? zipWriter.initialOffset : 0));
|
|
6253
|
+
endOfdirectoryRecord.uint32(lastDiskNumber + 1);
|
|
5766
6254
|
const supportZip64SplitFile = getOptionValue(zipWriter, options, OPTION_SUPPORT_ZIP64_SPLIT_FILE, true);
|
|
5767
6255
|
if (supportZip64SplitFile) {
|
|
5768
6256
|
lastDiskNumber = MAX_16_BITS;
|
|
@@ -5771,29 +6259,40 @@
|
|
|
5771
6259
|
filesLength = MAX_16_BITS;
|
|
5772
6260
|
directoryOffset = MAX_32_BITS;
|
|
5773
6261
|
directoryDataLength = MAX_32_BITS;
|
|
5774
|
-
offset += ZIP64_END_OF_CENTRAL_DIR_LENGTH + ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH;
|
|
5775
|
-
}
|
|
5776
|
-
setUint32(endOfdirectoryView, offset, END_OF_CENTRAL_DIR_SIGNATURE);
|
|
5777
|
-
setUint16(endOfdirectoryView, offset + 4, lastDiskNumber);
|
|
5778
|
-
setUint16(endOfdirectoryView, offset + 6, diskNumber);
|
|
5779
|
-
setUint16(endOfdirectoryView, offset + 8, filesLength);
|
|
5780
|
-
setUint16(endOfdirectoryView, offset + 10, filesLength);
|
|
5781
|
-
setUint32(endOfdirectoryView, offset + 12, directoryDataLength);
|
|
5782
|
-
setUint32(endOfdirectoryView, offset + 16, directoryOffset);
|
|
5783
|
-
const commentLength = getLength(comment);
|
|
5784
|
-
if (commentLength) {
|
|
5785
|
-
if (commentLength <= MAX_16_BITS) {
|
|
5786
|
-
setUint16(endOfdirectoryView, offset + 20, commentLength);
|
|
5787
|
-
} else {
|
|
5788
|
-
throw new Error(ERR_INVALID_COMMENT);
|
|
5789
|
-
}
|
|
5790
6262
|
}
|
|
5791
|
-
|
|
6263
|
+
endOfdirectoryRecord.uint32(END_OF_CENTRAL_DIR_SIGNATURE);
|
|
6264
|
+
endOfdirectoryRecord.uint16(lastDiskNumber);
|
|
6265
|
+
endOfdirectoryRecord.uint16(diskNumber);
|
|
6266
|
+
endOfdirectoryRecord.uint16(filesLength);
|
|
6267
|
+
endOfdirectoryRecord.uint16(filesLength);
|
|
6268
|
+
endOfdirectoryRecord.uint32(directoryDataLength);
|
|
6269
|
+
endOfdirectoryRecord.uint32(directoryOffset);
|
|
6270
|
+
endOfdirectoryRecord.uint16(commentLength);
|
|
6271
|
+
await writeData(writer, endOfdirectoryRecord.array);
|
|
5792
6272
|
if (commentLength) {
|
|
5793
6273
|
await writeData(writer, comment);
|
|
5794
6274
|
}
|
|
5795
6275
|
}
|
|
5796
6276
|
|
|
6277
|
+
function createRecordWriter(length) {
|
|
6278
|
+
const array = new Uint8Array(length);
|
|
6279
|
+
const view = getDataView(array);
|
|
6280
|
+
let offset = 0;
|
|
6281
|
+
return {
|
|
6282
|
+
array,
|
|
6283
|
+
uint8: value => { setUint8(view, offset, value); offset += 1; },
|
|
6284
|
+
uint16: value => { setUint16(view, offset, value); offset += 2; },
|
|
6285
|
+
uint32: value => { setUint32(view, offset, value); offset += 4; },
|
|
6286
|
+
uint64: value => { setBigUint64(view, offset, BigInt(value)); offset += 8; },
|
|
6287
|
+
bytes: value => { arraySet(array, value, offset); offset += getLength(value); },
|
|
6288
|
+
skip: count => offset += count
|
|
6289
|
+
};
|
|
6290
|
+
}
|
|
6291
|
+
|
|
6292
|
+
function getSegmentOffset(zipWriter, writer) {
|
|
6293
|
+
return zipWriter.offset - writer.diskOffset - (writer.diskNumber ? zipWriter.initialOffset : 0);
|
|
6294
|
+
}
|
|
6295
|
+
|
|
5797
6296
|
async function writeData(writer, array) {
|
|
5798
6297
|
const { writable } = writer;
|
|
5799
6298
|
const streamWriter = writable.getWriter();
|
|
@@ -5806,12 +6305,40 @@
|
|
|
5806
6305
|
}
|
|
5807
6306
|
}
|
|
5808
6307
|
|
|
6308
|
+
async function flushBufferedData(readable, writer, signal, onChunkWritten) {
|
|
6309
|
+
const streamWriter = writer.writable.getWriter();
|
|
6310
|
+
try {
|
|
6311
|
+
await readable.pipeTo(new WritableStream({
|
|
6312
|
+
async write(chunk) {
|
|
6313
|
+
await streamWriter.ready;
|
|
6314
|
+
await streamWriter.write(chunk);
|
|
6315
|
+
onChunkWritten(getLength(chunk));
|
|
6316
|
+
}
|
|
6317
|
+
}), { preventClose: true, preventAbort: true, signal });
|
|
6318
|
+
} finally {
|
|
6319
|
+
streamWriter.releaseLock();
|
|
6320
|
+
}
|
|
6321
|
+
}
|
|
6322
|
+
|
|
5809
6323
|
function getTimeNTFS(date) {
|
|
5810
6324
|
if (date) {
|
|
5811
6325
|
return ((BigInt(date.getTime()) + BigInt(11644473600000)) * BigInt(10000));
|
|
5812
6326
|
}
|
|
5813
6327
|
}
|
|
5814
6328
|
|
|
6329
|
+
function getTimeUnix(date) {
|
|
6330
|
+
return Math.floor(date.getTime() / 1000);
|
|
6331
|
+
}
|
|
6332
|
+
|
|
6333
|
+
// the extended timestamp extra field stores dates as signed 32-bit time_t values
|
|
6334
|
+
function inUnixTimeRange(timeUnix) {
|
|
6335
|
+
return timeUnix >= MIN_UNIX_TIME && timeUnix <= MAX_UNIX_TIME;
|
|
6336
|
+
}
|
|
6337
|
+
|
|
6338
|
+
function clampUnixTime(timeUnix) {
|
|
6339
|
+
return Math.min(MAX_UNIX_TIME, Math.max(MIN_UNIX_TIME, timeUnix));
|
|
6340
|
+
}
|
|
6341
|
+
|
|
5815
6342
|
function getOptionValue(zipWriter, options, name, defaultValue) {
|
|
5816
6343
|
const result = options[name] === UNDEFINED_VALUE ? zipWriter.options[name] : options[name];
|
|
5817
6344
|
return result === UNDEFINED_VALUE ? defaultValue : result;
|
|
@@ -5842,7 +6369,7 @@
|
|
|
5842
6369
|
}
|
|
5843
6370
|
|
|
5844
6371
|
function getDataView(array) {
|
|
5845
|
-
return new DataView(array.buffer);
|
|
6372
|
+
return new DataView(array.buffer, array.byteOffset, array.byteLength);
|
|
5846
6373
|
}
|
|
5847
6374
|
|
|
5848
6375
|
function getLength(...arrayLikes) {
|
|
@@ -5858,30 +6385,39 @@
|
|
|
5858
6385
|
uncompressedSize,
|
|
5859
6386
|
compressedSize,
|
|
5860
6387
|
lastModDate,
|
|
6388
|
+
rawLastModDate,
|
|
5861
6389
|
rawFilename,
|
|
5862
6390
|
zip64CompressedSize,
|
|
5863
6391
|
zip64UncompressedSize,
|
|
5864
6392
|
extraFieldLength
|
|
5865
6393
|
}) {
|
|
5866
|
-
const
|
|
6394
|
+
const headerRecord = createRecordWriter(HEADER_SIZE - 4);
|
|
6395
|
+
const headerArray = headerRecord.array;
|
|
5867
6396
|
const headerView = getDataView(headerArray);
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
|
|
6397
|
+
headerRecord.uint16(version);
|
|
6398
|
+
headerRecord.uint16(bitFlag);
|
|
6399
|
+
headerRecord.uint16(compressionMethod);
|
|
6400
|
+
if (rawLastModDate === UNDEFINED_VALUE) {
|
|
6401
|
+
const dateArray = new Uint32Array(1);
|
|
6402
|
+
const dateView = getDataView(dateArray);
|
|
6403
|
+
setUint16(dateView, 0, (((lastModDate.getHours() << 6) | lastModDate.getMinutes()) << 5) | lastModDate.getSeconds() / 2);
|
|
6404
|
+
setUint16(dateView, 2, ((((lastModDate.getFullYear() - 1980) << 4) | (lastModDate.getMonth() + 1)) << 5) | lastModDate.getDate());
|
|
6405
|
+
rawLastModDate = dateArray[0];
|
|
6406
|
+
}
|
|
6407
|
+
headerRecord.uint32(rawLastModDate);
|
|
6408
|
+
headerRecord.skip(4);
|
|
5877
6409
|
if (zip64CompressedSize || compressedSize !== UNDEFINED_VALUE) {
|
|
5878
|
-
|
|
6410
|
+
headerRecord.uint32(zip64CompressedSize ? MAX_32_BITS : compressedSize);
|
|
6411
|
+
} else {
|
|
6412
|
+
headerRecord.skip(4);
|
|
5879
6413
|
}
|
|
5880
6414
|
if (zip64UncompressedSize || uncompressedSize !== UNDEFINED_VALUE) {
|
|
5881
|
-
|
|
6415
|
+
headerRecord.uint32(zip64UncompressedSize ? MAX_32_BITS : uncompressedSize);
|
|
6416
|
+
} else {
|
|
6417
|
+
headerRecord.skip(4);
|
|
5882
6418
|
}
|
|
5883
|
-
|
|
5884
|
-
|
|
6419
|
+
headerRecord.uint16(getLength(rawFilename));
|
|
6420
|
+
headerRecord.uint16(extraFieldLength);
|
|
5885
6421
|
return {
|
|
5886
6422
|
headerArray,
|
|
5887
6423
|
headerView,
|
|
@@ -5982,7 +6518,7 @@
|
|
|
5982
6518
|
// ignored
|
|
5983
6519
|
}
|
|
5984
6520
|
|
|
5985
|
-
const A="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";function g(g){let B;g({wasmURI:()=>(B||(B="data:application/wasm;base64,"+(g=>{g=(g=>{const B=(g=(g+"").replace(/[^A-Za-z0-9+/=]/g,"")).length,E=[];for(let I=0;B>I;I+=4){const B=A.indexOf(g[I])<<18|A.indexOf(g[I+1])<<12|(63&A.indexOf(g[I+2]))<<6|63&A.indexOf(g[I+3]);E.push(B>>16&255),"="!==g[I+2]&&E.push(B>>8&255),"="!==g[I+3]&&E.push(255&B);}return new Uint8Array(E)})(g);let B=new Uint8Array(1024),E=0;for(let A=0;A<g.length;){const C=g[A++];if(128&C){const Q=3+(127&C),D=g[A++]<<8|g[A++],o=E-D;I(E+Q);for(let A=0;Q>A;A++)B[E++]=B[o+A];}else {const Q=C;I(E+Q);for(let I=0;Q>I&&A<g.length;I++)B[E++]=g[A++];}}return (g=>{let B="";const E=g.length;let I=0;for(;E>I+2;I+=3){const E=g[I]<<16|g[I+1]<<8|g[I+2];B+=A[E>>18&63]+A[E>>12&63]+A[E>>6&63]+A[63&E];}const C=E-I;if(1===C){const E=g[I]<<16;B+=A[E>>18&63]+A[E>>12&63]+"==";}else if(2===C){const E=g[I]<<16|g[I+1]<<8;B+=A[E>>18&63]+A[E>>12&63]+A[E>>6&63]+"=";}return B})(new Uint8Array(B.buffer.slice(0,E)));function I(A){if(B.length<A){let g=2*B.length;for(;A>g;)g*=2;const I=new Uint8Array(g);I.set(B.subarray(0,E)),B=I;}}})("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BAGZgAAEAVmAAAQB2YAABAE5gAAEAbmAAAQBeYAABAH5gAAEAQWAAAQBhYAABAFFgAAEAcWAAAQBJYAABAGlgAAEAWWAAAQB5YAABAEVgAAEAZWAAAQBVYAABAHVgAAEATWAAAQBtYAABAF1gAAEAfWAAAQBDYAABAGNgAAEAU2AAAQBzYAABIARMwIArYAABAFtgAAEAe2AAAQBHYAABAGdgAAEAV2AAAQB3YAABAE9gAAEAb2AAAQBfYAABAH9gAAEAROAAMIFEwEJAJOAAAgBk4AACAFTgAAIAVOAAAgB04AACAHTgAAIATOAAAgBM4AACAGzgAAIAbOAAAgBc4AACAFzgAAIAfOAAAgB84AACAELgAAIgBDagAQCgAAEgAAIAUuAAAgBS4AACAHLgAAIAcuAAAgBK4AACAErgAAIAauAAAgBq4AACAFrgAAIAWuAAAgB64AACAHrgAAIARuAAAgBG4AACAGbgAAIAZuAAAgBW4AACAFbgAAIAduAAAgB24AACAE7gAAIATuAAAgBu4AACAG7gAAIAXuAAAgBe4AACAH7gAAIAfuAAAiBA7YBB4AACAGHgAAIAYeAAAgBR4AACAFHgAAIAceAAAgBx4AACAEngAAIASeAAAgBp4AACAGngAAIAWeAAAgBZ4AACAHngAAIAeeAAAgBF4AACAEXgAAIAZeAAAgBl4AACAFXgAAIAVeAAAgB14AACAHXgAAIATeAAAgBN4AACAG3gAAIAbeAAAgBd4AACAF3gAAIAfeAAAgB94AACAEPgAAIAQ+AAAgBj4AACAGPgAAIAU+AAAgBT4AACAHPgAAIAc+AAAgBL4AACAEvgAAIAa+AAAgBr4AACAFvgAAIAW+AAAgB74AACAHvgAAIAR+AAAgBH4AACAGfgAAIAZ+AAAgBX4AACAFfgAAIAd+AAAgB34AACAE/gAAIAT+AAAgBv4AACAG/gAAIAX+AAAgBf4AACAH/gAAIAf+AAAiBBAoBQIAABAEggAAEAWCAAAQBEIAABAFQgAAEATCAAAQBcIIFVgMHAEiAAAQBKIAABAFogAAEARiAAAQBWIAABAE4gAAEAXiAAAQBBIAABAFEgAAEASSAAAQBZIAABAEUgAAEAVSAAAQBNIAABAF0gAAEAQOAAEIBg4AABAFDgAAEAcOAAAQBI4AABAGjgAAEAWOAAAQB44AABIC+K4AAdIECxgEFgABcAQWCBUoBFIAABAEMgAAEARyAAASAvlaABEQBBYIGBAEaggXqAQWAA9QBBYADuAEFgAOcgE92gAAEARGAAAQBCYAABAEZgAAEgQACARWAAAQBDYAABAEdgAAEgL59gAKkgQZAAQWAAiyBBaYBBYABtAEFgD3fAxsLTYMfuYcABIC+rooABIEHUYkABAEEjAAEAQWKAAQEQbAcC4C9CosAS40AO4UALwEGhAAEgQWIgQAEgQEKgQAEgQGSgQAEgIS2ggAEAQuEAAQBDIQABIAF24FHeQTgHQsjhQBfhQXLAhARgAVtBgcJBgoFC4A6uAQNAg4BgAclBJQeC2mFAJCFAIiFAICFAHiBAGiBAFyBBh8BEIAABAEUgAAEARiAAAQBHIAABAEggAAEASiAAAQBMIAABAE4gAAEAUCAAAQBUIAABIEGvQFwgAAEAYCAAAQBoIAABAHAgAAEAeCAAG8DHwtyjQBvgQBrgQBngQBjgQBfgQBbgQBXgQBTgQBPgQBLgQBHgQBDgQE8AYCvAEGAUc0CC22BAMcBBIAAAgEIgAAEgQEzgQJLARCAAA6DAAyBnqyAqmuEACSBB3OBAE8BCIAACIEAGIUADIEIt4MADAEggQCUgDKEgQBrAYCBCC8BBIMADIA/SAoBABAMAEGRIQv/gCUfgMDAgIKxBQgJCQoKgEk3gAABAQ2AAAEBDoAAAQEPgAABARCEAAEBEYQAAQEShAABAROEAAEBFIwAAQEVjAABARaMAAEBF4wAAQEYnAABARmcAAEBGpwAAQEbmwABARyBffsEBAQFBYHB1QEHgAABAQiEAAGAXSqCAAEBCowAAYAnsooAAYEBMJkAAYEBTJkAAYEBaLkAAYEBpLkAAYIDdYABzoUBvI0BqJ0BkLwBgAIbHLwAAQEdvAABgA9PgH05A9AqAQ==")),B)});}
|
|
6521
|
+
const A="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";function g(g){let B;g({wasmURI:()=>(B||(B="data:application/wasm;base64,"+(g=>{g=(g=>{const B=(g=(g+"").replace(/[^A-Za-z0-9+/=]/g,"")).length,E=[];for(let I=0;B>I;I+=4){const B=A.indexOf(g[I])<<18|A.indexOf(g[I+1])<<12|(63&A.indexOf(g[I+2]))<<6|63&A.indexOf(g[I+3]);E.push(B>>16&255),"="!==g[I+2]&&E.push(B>>8&255),"="!==g[I+3]&&E.push(255&B);}return new Uint8Array(E)})(g);let B=new Uint8Array(1024),E=0;for(let A=0;A<g.length;){const C=g[A++];if(128&C){const Q=3+(127&C),Y=g[A++]<<8|g[A++],D=E-Y;I(E+Q);for(let A=0;Q>A;A++)B[E++]=B[D+A];}else {const Q=C;I(E+Q);for(let I=0;Q>I&&A<g.length;I++)B[E++]=g[A++];}}return (g=>{let B="";const E=g.length;let I=0;for(;E>I+2;I+=3){const E=g[I]<<16|g[I+1]<<8|g[I+2];B+=A[E>>18&63]+A[E>>12&63]+A[E>>6&63]+A[63&E];}const C=E-I;if(1===C){const E=g[I]<<16;B+=A[E>>18&63]+A[E>>12&63]+"==";}else if(2===C){const E=g[I]<<16|g[I+1]<<8;B+=A[E>>18&63]+A[E>>12&63]+A[E>>6&63]+"=";}return B})(new Uint8Array(B.buffer.slice(0,E)));function I(A){if(B.length<A){let g=2*B.length;for(;A>g;)g*=2;const I=new Uint8Array(g);I.set(B.subarray(0,E)),B=I;}}})("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BAEVgAAEAZWAAAQBVYAABAHVgAAEATWAAAQBtYAABAF1gAAEAfWAAAQBDYAABAGNgAAEAU2AAAQBzYAABIAN6AIArYAABAFtgAAEAe2AAAQBHYAABAGdgAAEAV2AAAQB3YAABAE9gAAEAb2AAAQBfYAABAH9gAAEAROAAMIFEwEJAJOAAAgBk4AACAFTgAAIAVOAAAgB04AACAHTgAAIATOAAAgBM4AACAGzgAAIAbOAAAgBc4AACAFzgAAIAfOAAAgB84AACAELgAAIgA2LgAQCgAAEgAAIAUuAAAgBS4AACAHLgAAIAcuAAAgBK4AACAErgAAIAauAAAgBq4AACAFrgAAIAWuAAAgB64AACAHrgAAIARuAAAgBG4AACAGbgAAIAZuAAAgBW4AACAFbgAAIAduAAAgB24AACAE7gAAIATuAAAgBu4AACAG7gAAIAXuAAAgBe4AACAH7gAAIAfuAAAiBA7YBB4AACAGHgAAIAYeAAAgBR4AACAFHgAAIAceAAAgBx4AACAEngAAIASeAAAgBp4AACAGngAAIAWeAAAgBZ4AACAHngAAIAeeAAAgBF4AACAEXgAAIAZeAAAgBl4AACAFXgAAIAVeAAAgB14AACAHXgAAIATeAAAgBN4AACAG3gAAIAbeAAAgBd4AACAF3gAAIAfeAAAgB94AACAEPgAAIAQ+AAAgBj4AACAGPgAAIAU+AAAgBT4AACAHPgAAIAc+AAAgBL4AACAEvgAAIAa+AAAgBr4AACAFvgAAIAW+AAAgB74AACAHvgAAIAR+AAAgBH4AACAGfgAAIAZ+AAAgBX4AACAFfgAAIAd+AAAgB34AACAE/gAAIAT+AAAgBv4AACAG/gAAIAX+AAAgBf4AACAH/gAAIAf+AAAiBBAoBQIAABAEggAAEAWCAAAQBEIAABAFQgAAEATCAAAQBcIIFVgMHAEiAAAQBKIAABAFogAAEARiAAAQBWIAABAE4gAAEAXiAAAQBBIAABAFEgAAEASSAAAQBZIAABAEUgAAEAVSAAAQBNIAABAF0gAAEAQOAAEIBg4AABAFDgAAEAcOAAAQBI4AABAGjgAAEAWOAAAQB44AABIC/A4AAdIECxgEFgABcAQWCBUoBFIAABAEMgAAEARyAAAQBAoAABAESgAAEgQYEARqCBeoBBYAD1AEFgAO4AQWAA5yATGqAAAQBEYAABAEJgAAEARmAAASBAAIBFYAABAENgAAEAR2AAASAv26AAqSBBkABBYACLIEFpgEFgAG0AQWAOroDGwtNgxx6hwAEAQKMAASBB1GJAAQBBIwABAEFigAEBEGwHAuAveGLAEuNADuFAC8BBoQABIEFiIEABIEBCoEABIEBkoEABICFfIIABAELhAAEAQyEAASABduBRGIE4B0LI4UAX4UFywIQEYAFbQYHCQYKBQuAN44EDQIOAYAHJQSUHgtphQCQhQCIhQCAhQB4gQBogQBcgQYfARCAAAQBFIAABAEYgAAEARyAAAQBIIAABAEogAAEATCAAAQBOIAABAFAgAAEAVCAAASBBr0BcIAABAGAgAAEAaCAAAQBwIAABAHggABvAx8Lco0Ab4EAa4EAZ4EAY4EAX4EAW4EAV4EAU4EAT4EAS4EAR4EAQ4EBPAGArwBBgE7BAgttgQDHAQSAAAIBCIAABIEBM4ECSwEQgAAOgwAMgZ97gKs6hAAkgQdzgQBPAQiAAAiBABiFAAyBCLeDAAwBIIEAlIAvUoEAawGAgQgvAQSDAAyAPCIKAQAQDABBkSEL/4Ah4AEDgpzlBQgJCQoKgEYggAABAQ2AAAEBDoAAAQEPgAABARCEAAEBEYQAAQEShAABAROEAAEBFIwAAQEVjAABARaMAAEBF4wAAQEYnAABARmcAAEBGpwAAQEbmwABARyBfrkEBAQFBYHCrAEHgAABAQiEAAGAWjqCAAEBCowAAYAkc4oAAYEBMJkAAYEBTJkAAYEBaLkAAYEBpLkAAYIDdYABzoUBvI0BqJ0BkLwBgAIbHLwAAQEdvAABgLyTgH3yA9AqAQ==")),B)});}
|
|
5986
6522
|
|
|
5987
6523
|
/*
|
|
5988
6524
|
Copyright (c) 2025 Gildas Lormeau. All rights reserved.
|
|
@@ -6032,46 +6568,54 @@
|
|
|
6032
6568
|
|
|
6033
6569
|
return new TransformStream({
|
|
6034
6570
|
start() {
|
|
6035
|
-
|
|
6036
|
-
|
|
6037
|
-
|
|
6038
|
-
|
|
6039
|
-
|
|
6040
|
-
|
|
6041
|
-
|
|
6042
|
-
this._last_consumed = wasm.deflate_last_consumed;
|
|
6043
|
-
this._end = wasm.deflate_end;
|
|
6044
|
-
this.streamHandle = wasm.deflate_new();
|
|
6045
|
-
if (type === "gzip") {
|
|
6046
|
-
result = wasm.deflate_init_gzip(this.streamHandle, level);
|
|
6047
|
-
} else if (type === "deflate-raw") {
|
|
6048
|
-
result = wasm.deflate_init_raw(this.streamHandle, level);
|
|
6049
|
-
} else {
|
|
6050
|
-
result = wasm.deflate_init(this.streamHandle, level);
|
|
6571
|
+
try {
|
|
6572
|
+
let result;
|
|
6573
|
+
this.out = malloc(outBufferSize);
|
|
6574
|
+
this.in = malloc(inBufferSize);
|
|
6575
|
+
this.inBufferSize = inBufferSize;
|
|
6576
|
+
if (!this.out || !this.in) {
|
|
6577
|
+
throw new Error("allocation failed");
|
|
6051
6578
|
}
|
|
6052
|
-
|
|
6053
|
-
if (
|
|
6054
|
-
this._process = wasm.
|
|
6055
|
-
this._last_consumed = wasm.
|
|
6056
|
-
this._end = wasm.
|
|
6057
|
-
this.streamHandle = wasm.
|
|
6058
|
-
|
|
6579
|
+
this._scratch = new Uint8Array(outBufferSize);
|
|
6580
|
+
if (isCompress) {
|
|
6581
|
+
this._process = wasm.deflate_process;
|
|
6582
|
+
this._last_consumed = wasm.deflate_last_consumed;
|
|
6583
|
+
this._end = wasm.deflate_end;
|
|
6584
|
+
this.streamHandle = wasm.deflate_new();
|
|
6585
|
+
if (type === "gzip") {
|
|
6586
|
+
result = wasm.deflate_init_gzip(this.streamHandle, level);
|
|
6587
|
+
} else if (type === "deflate-raw") {
|
|
6588
|
+
result = wasm.deflate_init_raw(this.streamHandle, level);
|
|
6589
|
+
} else {
|
|
6590
|
+
result = wasm.deflate_init(this.streamHandle, level);
|
|
6591
|
+
}
|
|
6059
6592
|
} else {
|
|
6060
|
-
|
|
6061
|
-
|
|
6062
|
-
|
|
6063
|
-
|
|
6064
|
-
|
|
6065
|
-
result = wasm.
|
|
6066
|
-
} else if (type === "gzip") {
|
|
6067
|
-
result = wasm.inflate_init_gzip(this.streamHandle);
|
|
6593
|
+
if (type === "deflate64-raw") {
|
|
6594
|
+
this._process = wasm.inflate9_process;
|
|
6595
|
+
this._last_consumed = wasm.inflate9_last_consumed;
|
|
6596
|
+
this._end = wasm.inflate9_end;
|
|
6597
|
+
this.streamHandle = wasm.inflate9_new();
|
|
6598
|
+
result = wasm.inflate9_init_raw(this.streamHandle);
|
|
6068
6599
|
} else {
|
|
6069
|
-
|
|
6600
|
+
this._process = wasm.inflate_process;
|
|
6601
|
+
this._last_consumed = wasm.inflate_last_consumed;
|
|
6602
|
+
this._end = wasm.inflate_end;
|
|
6603
|
+
this.streamHandle = wasm.inflate_new();
|
|
6604
|
+
if (type === "deflate-raw") {
|
|
6605
|
+
result = wasm.inflate_init_raw(this.streamHandle);
|
|
6606
|
+
} else if (type === "gzip") {
|
|
6607
|
+
result = wasm.inflate_init_gzip(this.streamHandle);
|
|
6608
|
+
} else {
|
|
6609
|
+
result = wasm.inflate_init(this.streamHandle);
|
|
6610
|
+
}
|
|
6070
6611
|
}
|
|
6071
6612
|
}
|
|
6072
|
-
|
|
6073
|
-
|
|
6074
|
-
|
|
6613
|
+
if (result !== 0) {
|
|
6614
|
+
throw new Error("init failed:" + result);
|
|
6615
|
+
}
|
|
6616
|
+
} catch (error) {
|
|
6617
|
+
disposeStream(this);
|
|
6618
|
+
throw error;
|
|
6075
6619
|
}
|
|
6076
6620
|
},
|
|
6077
6621
|
transform(chunk, controller) {
|
|
@@ -6088,9 +6632,13 @@
|
|
|
6088
6632
|
if (!this.in || this.inBufferSize < toRead) {
|
|
6089
6633
|
if (this.in && free) {
|
|
6090
6634
|
free(this.in);
|
|
6635
|
+
this.in = 0;
|
|
6091
6636
|
}
|
|
6092
6637
|
this.in = malloc(toRead);
|
|
6093
6638
|
this.inBufferSize = toRead;
|
|
6639
|
+
if (!this.in) {
|
|
6640
|
+
throw new Error("allocation failed");
|
|
6641
|
+
}
|
|
6094
6642
|
}
|
|
6095
6643
|
heap.set(buffer.subarray(offset, offset + toRead), this.in);
|
|
6096
6644
|
const result = process(this.streamHandle, this.in, toRead, out, outBufferSize, 0);
|
|
@@ -6113,15 +6661,7 @@
|
|
|
6113
6661
|
offset += consumed;
|
|
6114
6662
|
}
|
|
6115
6663
|
} catch (error) {
|
|
6116
|
-
|
|
6117
|
-
this._end(this.streamHandle);
|
|
6118
|
-
}
|
|
6119
|
-
if (this.in && free) {
|
|
6120
|
-
free(this.in);
|
|
6121
|
-
}
|
|
6122
|
-
if (this.out && free) {
|
|
6123
|
-
free(this.out);
|
|
6124
|
-
}
|
|
6664
|
+
disposeStream(this);
|
|
6125
6665
|
controller.error(error);
|
|
6126
6666
|
}
|
|
6127
6667
|
},
|
|
@@ -6152,21 +6692,35 @@
|
|
|
6152
6692
|
} catch (error) {
|
|
6153
6693
|
controller.error(error);
|
|
6154
6694
|
} finally {
|
|
6155
|
-
|
|
6156
|
-
|
|
6157
|
-
|
|
6158
|
-
controller.error(new Error("end error:" + result));
|
|
6159
|
-
}
|
|
6160
|
-
}
|
|
6161
|
-
if (this.in && free) {
|
|
6162
|
-
free(this.in);
|
|
6163
|
-
}
|
|
6164
|
-
if (this.out && free) {
|
|
6165
|
-
free(this.out);
|
|
6695
|
+
const result = disposeStream(this);
|
|
6696
|
+
if (result !== 0) {
|
|
6697
|
+
controller.error(new Error("end error:" + result));
|
|
6166
6698
|
}
|
|
6167
6699
|
}
|
|
6700
|
+
},
|
|
6701
|
+
cancel() {
|
|
6702
|
+
// release the stream handle and buffers when the pipeline is aborted,
|
|
6703
|
+
// they would be leaked in the process-lifetime wasm heap otherwise
|
|
6704
|
+
disposeStream(this);
|
|
6168
6705
|
}
|
|
6169
6706
|
});
|
|
6707
|
+
|
|
6708
|
+
function disposeStream(state) {
|
|
6709
|
+
let endResult = 0;
|
|
6710
|
+
if (state.streamHandle && state._end) {
|
|
6711
|
+
endResult = state._end(state.streamHandle);
|
|
6712
|
+
}
|
|
6713
|
+
state.streamHandle = 0;
|
|
6714
|
+
if (state.in && free) {
|
|
6715
|
+
free(state.in);
|
|
6716
|
+
}
|
|
6717
|
+
state.in = 0;
|
|
6718
|
+
if (state.out && free) {
|
|
6719
|
+
free(state.out);
|
|
6720
|
+
}
|
|
6721
|
+
state.out = 0;
|
|
6722
|
+
return endResult;
|
|
6723
|
+
}
|
|
6170
6724
|
}
|
|
6171
6725
|
|
|
6172
6726
|
class CompressionStreamZlib {
|
|
@@ -6179,6 +6733,11 @@
|
|
|
6179
6733
|
return _make(false, type, options);
|
|
6180
6734
|
}
|
|
6181
6735
|
}
|
|
6736
|
+
// These codecs are backed by the WASM module; they are unusable until setWasmExports() has run.
|
|
6737
|
+
// The worker uses this flag to know it must fall back to the native CompressionStream when the
|
|
6738
|
+
// module fails to load, rather than discarding a self-contained codec supplied through config.
|
|
6739
|
+
CompressionStreamZlib.requiresModule = true;
|
|
6740
|
+
DecompressionStreamZlib.requiresModule = true;
|
|
6182
6741
|
|
|
6183
6742
|
/*
|
|
6184
6743
|
Copyright (c) 2025 Gildas Lormeau. All rights reserved.
|
|
@@ -6342,6 +6901,7 @@
|
|
|
6342
6901
|
exports.BlobWriter = BlobWriter;
|
|
6343
6902
|
exports.Data64URIReader = Data64URIReader;
|
|
6344
6903
|
exports.Data64URIWriter = Data64URIWriter;
|
|
6904
|
+
exports.ERR_AMBIGUOUS_ARCHIVE = ERR_AMBIGUOUS_ARCHIVE;
|
|
6345
6905
|
exports.ERR_BAD_FORMAT = ERR_BAD_FORMAT;
|
|
6346
6906
|
exports.ERR_CENTRAL_DIRECTORY_NOT_FOUND = ERR_CENTRAL_DIRECTORY_NOT_FOUND;
|
|
6347
6907
|
exports.ERR_DUPLICATED_NAME = ERR_DUPLICATED_NAME;
|
|
@@ -6351,6 +6911,7 @@
|
|
|
6351
6911
|
exports.ERR_EXTRAFIELD_ZIP64_NOT_FOUND = ERR_EXTRAFIELD_ZIP64_NOT_FOUND;
|
|
6352
6912
|
exports.ERR_HTTP_RANGE = ERR_HTTP_RANGE;
|
|
6353
6913
|
exports.ERR_INVALID_COMMENT = ERR_INVALID_COMMENT;
|
|
6914
|
+
exports.ERR_INVALID_COMPRESSED_DATA = ERR_INVALID_COMPRESSED_DATA;
|
|
6354
6915
|
exports.ERR_INVALID_ENCRYPTION_STRENGTH = ERR_INVALID_ENCRYPTION_STRENGTH;
|
|
6355
6916
|
exports.ERR_INVALID_ENTRY_COMMENT = ERR_INVALID_ENTRY_COMMENT;
|
|
6356
6917
|
exports.ERR_INVALID_ENTRY_NAME = ERR_INVALID_ENTRY_NAME;
|
|
@@ -6363,8 +6924,9 @@
|
|
|
6363
6924
|
exports.ERR_LOCAL_FILE_HEADER_NOT_FOUND = ERR_LOCAL_FILE_HEADER_NOT_FOUND;
|
|
6364
6925
|
exports.ERR_OVERLAPPING_ENTRY = ERR_OVERLAPPING_ENTRY;
|
|
6365
6926
|
exports.ERR_SPLIT_ZIP_FILE = ERR_SPLIT_ZIP_FILE;
|
|
6927
|
+
exports.ERR_UNDEFINED_READER = ERR_UNDEFINED_READER;
|
|
6366
6928
|
exports.ERR_UNDEFINED_UNCOMPRESSED_SIZE = ERR_UNDEFINED_UNCOMPRESSED_SIZE;
|
|
6367
|
-
exports.ERR_UNSUPPORTED_COMPRESSION = ERR_UNSUPPORTED_COMPRESSION;
|
|
6929
|
+
exports.ERR_UNSUPPORTED_COMPRESSION = ERR_UNSUPPORTED_COMPRESSION$1;
|
|
6368
6930
|
exports.ERR_UNSUPPORTED_ENCRYPTION = ERR_UNSUPPORTED_ENCRYPTION;
|
|
6369
6931
|
exports.ERR_UNSUPPORTED_FORMAT = ERR_UNSUPPORTED_FORMAT;
|
|
6370
6932
|
exports.ERR_ZIP_NOT_EMPTY = ERR_ZIP_NOT_EMPTY;
|