clear-excel 0.1.0 → 1.0.2
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/CHANGELOG.md +25 -0
- package/README.md +120 -72
- package/dist/api/sanitize-excel-file.d.ts +5 -0
- package/dist/api/sanitize-excel-file.d.ts.map +1 -0
- package/dist/api/sanitize-excel.d.ts +3 -0
- package/dist/api/sanitize-excel.d.ts.map +1 -0
- package/dist/biff/workbook.d.ts +4 -0
- package/dist/biff/workbook.d.ts.map +1 -0
- package/dist/constants.d.ts +6 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/errors.d.ts +20 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/formats.d.ts +5 -0
- package/dist/formats.d.ts.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2777 -0
- package/dist/index.js.map +1 -0
- package/dist/ooxml/cleanup.d.ts +3 -0
- package/dist/ooxml/cleanup.d.ts.map +1 -0
- package/dist/ooxml/constants.d.ts +4 -0
- package/dist/ooxml/constants.d.ts.map +1 -0
- package/dist/ooxml/parts.d.ts +5 -0
- package/dist/ooxml/parts.d.ts.map +1 -0
- package/dist/ooxml/relationships.d.ts +21 -0
- package/dist/ooxml/relationships.d.ts.map +1 -0
- package/dist/ooxml/styles.d.ts +7 -0
- package/dist/ooxml/styles.d.ts.map +1 -0
- package/dist/ooxml/workbook.d.ts +3 -0
- package/dist/ooxml/workbook.d.ts.map +1 -0
- package/dist/ooxml/xml.d.ts +12 -0
- package/dist/ooxml/xml.d.ts.map +1 -0
- package/dist/options.d.ts +5 -0
- package/dist/options.d.ts.map +1 -0
- package/dist/types.d.ts +28 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/zip/central-directory.d.ts +7 -0
- package/dist/zip/central-directory.d.ts.map +1 -0
- package/package.json +64 -44
- package/index.cjs +0 -3
- package/index.d.ts +0 -62
- package/index.js +0 -7
- package/src/index.cjs +0 -894
package/dist/index.js
ADDED
|
@@ -0,0 +1,2777 @@
|
|
|
1
|
+
import JSZip from "jszip";
|
|
2
|
+
import { posix, resolve } from "node:path";
|
|
3
|
+
import { randomUUID } from "node:crypto";
|
|
4
|
+
import { readFile, rename, unlink, writeFile } from "node:fs/promises";
|
|
5
|
+
//#region \0rolldown/runtime.js
|
|
6
|
+
var __create = Object.create;
|
|
7
|
+
var __defProp = Object.defineProperty;
|
|
8
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
9
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
10
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
11
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
12
|
+
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
15
|
+
key = keys[i];
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
17
|
+
get: ((k) => from[k]).bind(null, key),
|
|
18
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
return to;
|
|
22
|
+
};
|
|
23
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
|
|
24
|
+
value: mod,
|
|
25
|
+
enumerable: true
|
|
26
|
+
}) : target, mod));
|
|
27
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, { get: (a, b) => (typeof require !== "undefined" ? require : a)[b] }) : x)(function(x) {
|
|
28
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
29
|
+
throw Error("Calling `require` for \"" + x + "\" in an environment that doesn't expose the `require` function. See https://rolldown.rs/in-depth/bundling-cjs#require-external-modules for more details.");
|
|
30
|
+
});
|
|
31
|
+
//#endregion
|
|
32
|
+
//#region __vite-browser-external
|
|
33
|
+
var require___vite_browser_external = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
34
|
+
module.exports = {};
|
|
35
|
+
}));
|
|
36
|
+
/*! crc32.js (C) 2014-present SheetJS -- http://sheetjs.com */
|
|
37
|
+
//#endregion
|
|
38
|
+
//#region src/errors.ts
|
|
39
|
+
var import_cfb = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
40
|
+
var Base64_map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
|
41
|
+
function Base64_encode(input) {
|
|
42
|
+
var o = "";
|
|
43
|
+
var c1 = 0, c2 = 0, c3 = 0, e1 = 0, e2 = 0, e3 = 0, e4 = 0;
|
|
44
|
+
for (var i = 0; i < input.length;) {
|
|
45
|
+
c1 = input.charCodeAt(i++);
|
|
46
|
+
e1 = c1 >> 2;
|
|
47
|
+
c2 = input.charCodeAt(i++);
|
|
48
|
+
e2 = (c1 & 3) << 4 | c2 >> 4;
|
|
49
|
+
c3 = input.charCodeAt(i++);
|
|
50
|
+
e3 = (c2 & 15) << 2 | c3 >> 6;
|
|
51
|
+
e4 = c3 & 63;
|
|
52
|
+
if (isNaN(c2)) e3 = e4 = 64;
|
|
53
|
+
else if (isNaN(c3)) e4 = 64;
|
|
54
|
+
o += Base64_map.charAt(e1) + Base64_map.charAt(e2) + Base64_map.charAt(e3) + Base64_map.charAt(e4);
|
|
55
|
+
}
|
|
56
|
+
return o;
|
|
57
|
+
}
|
|
58
|
+
function Base64_decode(input) {
|
|
59
|
+
var o = "";
|
|
60
|
+
var c1 = 0, c2 = 0, c3 = 0, e1 = 0, e2 = 0, e3 = 0, e4 = 0;
|
|
61
|
+
input = input.replace(/[^\w\+\/\=]/g, "");
|
|
62
|
+
for (var i = 0; i < input.length;) {
|
|
63
|
+
e1 = Base64_map.indexOf(input.charAt(i++));
|
|
64
|
+
e2 = Base64_map.indexOf(input.charAt(i++));
|
|
65
|
+
c1 = e1 << 2 | e2 >> 4;
|
|
66
|
+
o += String.fromCharCode(c1);
|
|
67
|
+
e3 = Base64_map.indexOf(input.charAt(i++));
|
|
68
|
+
c2 = (e2 & 15) << 4 | e3 >> 2;
|
|
69
|
+
if (e3 !== 64) o += String.fromCharCode(c2);
|
|
70
|
+
e4 = Base64_map.indexOf(input.charAt(i++));
|
|
71
|
+
c3 = (e3 & 3) << 6 | e4;
|
|
72
|
+
if (e4 !== 64) o += String.fromCharCode(c3);
|
|
73
|
+
}
|
|
74
|
+
return o;
|
|
75
|
+
}
|
|
76
|
+
var has_buf = (function() {
|
|
77
|
+
return typeof Buffer !== "undefined" && typeof process !== "undefined" && typeof process.versions !== "undefined" && !!process.versions.node;
|
|
78
|
+
})();
|
|
79
|
+
var Buffer_from = (function() {
|
|
80
|
+
if (typeof Buffer !== "undefined") {
|
|
81
|
+
var nbfs = !Buffer.from;
|
|
82
|
+
if (!nbfs) try {
|
|
83
|
+
Buffer.from("foo", "utf8");
|
|
84
|
+
} catch (e) {
|
|
85
|
+
nbfs = true;
|
|
86
|
+
}
|
|
87
|
+
return nbfs ? function(buf, enc) {
|
|
88
|
+
return enc ? new Buffer(buf, enc) : new Buffer(buf);
|
|
89
|
+
} : Buffer.from.bind(Buffer);
|
|
90
|
+
}
|
|
91
|
+
return function() {};
|
|
92
|
+
})();
|
|
93
|
+
function new_raw_buf(len) {
|
|
94
|
+
if (has_buf) {
|
|
95
|
+
if (Buffer.alloc) return Buffer.alloc(len);
|
|
96
|
+
var b = new Buffer(len);
|
|
97
|
+
b.fill(0);
|
|
98
|
+
return b;
|
|
99
|
+
}
|
|
100
|
+
return typeof Uint8Array != "undefined" ? new Uint8Array(len) : new Array(len);
|
|
101
|
+
}
|
|
102
|
+
function new_unsafe_buf(len) {
|
|
103
|
+
if (has_buf) return Buffer.allocUnsafe ? Buffer.allocUnsafe(len) : new Buffer(len);
|
|
104
|
+
return typeof Uint8Array != "undefined" ? new Uint8Array(len) : new Array(len);
|
|
105
|
+
}
|
|
106
|
+
var s2a = function s2a(s) {
|
|
107
|
+
if (has_buf) return Buffer_from(s, "binary");
|
|
108
|
+
return s.split("").map(function(x) {
|
|
109
|
+
return x.charCodeAt(0) & 255;
|
|
110
|
+
});
|
|
111
|
+
};
|
|
112
|
+
var chr0 = /\u0000/g;
|
|
113
|
+
var chr1 = /[\u0001-\u0006]/g;
|
|
114
|
+
var __toBuffer = function(bufs) {
|
|
115
|
+
var x = [];
|
|
116
|
+
for (var i = 0; i < bufs[0].length; ++i) x.push.apply(x, bufs[0][i]);
|
|
117
|
+
return x;
|
|
118
|
+
};
|
|
119
|
+
var ___toBuffer = __toBuffer;
|
|
120
|
+
var __utf16le = function(b, s, e) {
|
|
121
|
+
var ss = [];
|
|
122
|
+
for (var i = s; i < e; i += 2) ss.push(String.fromCharCode(__readUInt16LE(b, i)));
|
|
123
|
+
return ss.join("").replace(chr0, "");
|
|
124
|
+
};
|
|
125
|
+
var ___utf16le = __utf16le;
|
|
126
|
+
var __hexlify = function(b, s, l) {
|
|
127
|
+
var ss = [];
|
|
128
|
+
for (var i = s; i < s + l; ++i) ss.push(("0" + b[i].toString(16)).slice(-2));
|
|
129
|
+
return ss.join("");
|
|
130
|
+
};
|
|
131
|
+
var ___hexlify = __hexlify;
|
|
132
|
+
var __bconcat = function(bufs) {
|
|
133
|
+
if (Array.isArray(bufs[0])) return [].concat.apply([], bufs);
|
|
134
|
+
var maxlen = 0, i = 0;
|
|
135
|
+
for (i = 0; i < bufs.length; ++i) maxlen += bufs[i].length;
|
|
136
|
+
var o = new Uint8Array(maxlen);
|
|
137
|
+
for (i = 0, maxlen = 0; i < bufs.length; maxlen += bufs[i].length, ++i) o.set(bufs[i], maxlen);
|
|
138
|
+
return o;
|
|
139
|
+
};
|
|
140
|
+
var bconcat = __bconcat;
|
|
141
|
+
if (has_buf) {
|
|
142
|
+
__utf16le = function(b, s, e) {
|
|
143
|
+
if (!Buffer.isBuffer(b)) return ___utf16le(b, s, e);
|
|
144
|
+
return b.toString("utf16le", s, e).replace(chr0, "");
|
|
145
|
+
};
|
|
146
|
+
__hexlify = function(b, s, l) {
|
|
147
|
+
return Buffer.isBuffer(b) ? b.toString("hex", s, s + l) : ___hexlify(b, s, l);
|
|
148
|
+
};
|
|
149
|
+
__toBuffer = function(bufs) {
|
|
150
|
+
return bufs[0].length > 0 && Buffer.isBuffer(bufs[0][0]) ? Buffer.concat(bufs[0]) : ___toBuffer(bufs);
|
|
151
|
+
};
|
|
152
|
+
s2a = function(s) {
|
|
153
|
+
return Buffer_from(s, "binary");
|
|
154
|
+
};
|
|
155
|
+
bconcat = function(bufs) {
|
|
156
|
+
return Buffer.isBuffer(bufs[0]) ? Buffer.concat(bufs) : __bconcat(bufs);
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
var __readUInt8 = function(b, idx) {
|
|
160
|
+
return b[idx];
|
|
161
|
+
};
|
|
162
|
+
var __readUInt16LE = function(b, idx) {
|
|
163
|
+
return b[idx + 1] * 256 + b[idx];
|
|
164
|
+
};
|
|
165
|
+
var __readInt16LE = function(b, idx) {
|
|
166
|
+
var u = b[idx + 1] * 256 + b[idx];
|
|
167
|
+
return u < 32768 ? u : (65535 - u + 1) * -1;
|
|
168
|
+
};
|
|
169
|
+
var __readUInt32LE = function(b, idx) {
|
|
170
|
+
return b[idx + 3] * (1 << 24) + (b[idx + 2] << 16) + (b[idx + 1] << 8) + b[idx];
|
|
171
|
+
};
|
|
172
|
+
var __readInt32LE = function(b, idx) {
|
|
173
|
+
return (b[idx + 3] << 24) + (b[idx + 2] << 16) + (b[idx + 1] << 8) + b[idx];
|
|
174
|
+
};
|
|
175
|
+
function ReadShift(size, t) {
|
|
176
|
+
var oI, oS, type = 0;
|
|
177
|
+
switch (size) {
|
|
178
|
+
case 1:
|
|
179
|
+
oI = __readUInt8(this, this.l);
|
|
180
|
+
break;
|
|
181
|
+
case 2:
|
|
182
|
+
oI = (t !== "i" ? __readUInt16LE : __readInt16LE)(this, this.l);
|
|
183
|
+
break;
|
|
184
|
+
case 4:
|
|
185
|
+
oI = __readInt32LE(this, this.l);
|
|
186
|
+
break;
|
|
187
|
+
case 16:
|
|
188
|
+
type = 2;
|
|
189
|
+
oS = __hexlify(this, this.l, size);
|
|
190
|
+
}
|
|
191
|
+
this.l += size;
|
|
192
|
+
if (type === 0) return oI;
|
|
193
|
+
return oS;
|
|
194
|
+
}
|
|
195
|
+
var __writeUInt32LE = function(b, val, idx) {
|
|
196
|
+
b[idx] = val & 255;
|
|
197
|
+
b[idx + 1] = val >>> 8 & 255;
|
|
198
|
+
b[idx + 2] = val >>> 16 & 255;
|
|
199
|
+
b[idx + 3] = val >>> 24 & 255;
|
|
200
|
+
};
|
|
201
|
+
var __writeInt32LE = function(b, val, idx) {
|
|
202
|
+
b[idx] = val & 255;
|
|
203
|
+
b[idx + 1] = val >> 8 & 255;
|
|
204
|
+
b[idx + 2] = val >> 16 & 255;
|
|
205
|
+
b[idx + 3] = val >> 24 & 255;
|
|
206
|
+
};
|
|
207
|
+
function WriteShift(t, val, f) {
|
|
208
|
+
var size = 0, i = 0;
|
|
209
|
+
switch (f) {
|
|
210
|
+
case "hex":
|
|
211
|
+
for (; i < t; ++i) this[this.l++] = parseInt(val.slice(2 * i, 2 * i + 2), 16) || 0;
|
|
212
|
+
return this;
|
|
213
|
+
case "utf16le":
|
|
214
|
+
var end = this.l + t;
|
|
215
|
+
for (i = 0; i < Math.min(val.length, t); ++i) {
|
|
216
|
+
var cc = val.charCodeAt(i);
|
|
217
|
+
this[this.l++] = cc & 255;
|
|
218
|
+
this[this.l++] = cc >> 8;
|
|
219
|
+
}
|
|
220
|
+
while (this.l < end) this[this.l++] = 0;
|
|
221
|
+
return this;
|
|
222
|
+
}
|
|
223
|
+
switch (t) {
|
|
224
|
+
case 1:
|
|
225
|
+
size = 1;
|
|
226
|
+
this[this.l] = val & 255;
|
|
227
|
+
break;
|
|
228
|
+
case 2:
|
|
229
|
+
size = 2;
|
|
230
|
+
this[this.l] = val & 255;
|
|
231
|
+
val >>>= 8;
|
|
232
|
+
this[this.l + 1] = val & 255;
|
|
233
|
+
break;
|
|
234
|
+
case 4:
|
|
235
|
+
size = 4;
|
|
236
|
+
__writeUInt32LE(this, val, this.l);
|
|
237
|
+
break;
|
|
238
|
+
case -4:
|
|
239
|
+
size = 4;
|
|
240
|
+
__writeInt32LE(this, val, this.l);
|
|
241
|
+
}
|
|
242
|
+
this.l += size;
|
|
243
|
+
return this;
|
|
244
|
+
}
|
|
245
|
+
function CheckField(hexstr, fld) {
|
|
246
|
+
var m = __hexlify(this, this.l, hexstr.length >> 1);
|
|
247
|
+
if (m !== hexstr) throw new Error(fld + "Expected " + hexstr + " saw " + m);
|
|
248
|
+
this.l += hexstr.length >> 1;
|
|
249
|
+
}
|
|
250
|
+
function prep_blob(blob, pos) {
|
|
251
|
+
blob.l = pos;
|
|
252
|
+
blob.read_shift = ReadShift;
|
|
253
|
+
blob.chk = CheckField;
|
|
254
|
+
blob.write_shift = WriteShift;
|
|
255
|
+
}
|
|
256
|
+
function new_buf(sz) {
|
|
257
|
+
var o = new_raw_buf(sz);
|
|
258
|
+
prep_blob(o, 0);
|
|
259
|
+
return o;
|
|
260
|
+
}
|
|
261
|
+
var CRC32 = (function() {
|
|
262
|
+
var CRC32 = {};
|
|
263
|
+
CRC32.version = "1.2.1";
|
|
264
|
+
function signed_crc_table() {
|
|
265
|
+
var c = 0, table = new Array(256);
|
|
266
|
+
for (var n = 0; n != 256; ++n) {
|
|
267
|
+
c = n;
|
|
268
|
+
c = c & 1 ? -306674912 ^ c >>> 1 : c >>> 1;
|
|
269
|
+
c = c & 1 ? -306674912 ^ c >>> 1 : c >>> 1;
|
|
270
|
+
c = c & 1 ? -306674912 ^ c >>> 1 : c >>> 1;
|
|
271
|
+
c = c & 1 ? -306674912 ^ c >>> 1 : c >>> 1;
|
|
272
|
+
c = c & 1 ? -306674912 ^ c >>> 1 : c >>> 1;
|
|
273
|
+
c = c & 1 ? -306674912 ^ c >>> 1 : c >>> 1;
|
|
274
|
+
c = c & 1 ? -306674912 ^ c >>> 1 : c >>> 1;
|
|
275
|
+
c = c & 1 ? -306674912 ^ c >>> 1 : c >>> 1;
|
|
276
|
+
table[n] = c;
|
|
277
|
+
}
|
|
278
|
+
return typeof Int32Array !== "undefined" ? new Int32Array(table) : table;
|
|
279
|
+
}
|
|
280
|
+
var T0 = signed_crc_table();
|
|
281
|
+
function slice_by_16_tables(T) {
|
|
282
|
+
var c = 0, v = 0, n = 0, table = typeof Int32Array !== "undefined" ? /* @__PURE__ */ new Int32Array(4096) : new Array(4096);
|
|
283
|
+
for (n = 0; n != 256; ++n) table[n] = T[n];
|
|
284
|
+
for (n = 0; n != 256; ++n) {
|
|
285
|
+
v = T[n];
|
|
286
|
+
for (c = 256 + n; c < 4096; c += 256) v = table[c] = v >>> 8 ^ T[v & 255];
|
|
287
|
+
}
|
|
288
|
+
var out = [];
|
|
289
|
+
for (n = 1; n != 16; ++n) out[n - 1] = typeof Int32Array !== "undefined" ? table.subarray(n * 256, n * 256 + 256) : table.slice(n * 256, n * 256 + 256);
|
|
290
|
+
return out;
|
|
291
|
+
}
|
|
292
|
+
var TT = slice_by_16_tables(T0);
|
|
293
|
+
var T1 = TT[0], T2 = TT[1], T3 = TT[2], T4 = TT[3], T5 = TT[4];
|
|
294
|
+
var T6 = TT[5], T7 = TT[6], T8 = TT[7], T9 = TT[8], Ta = TT[9];
|
|
295
|
+
var Tb = TT[10], Tc = TT[11], Td = TT[12], Te = TT[13], Tf = TT[14];
|
|
296
|
+
function crc32_bstr(bstr, seed) {
|
|
297
|
+
var C = seed ^ -1;
|
|
298
|
+
for (var i = 0, L = bstr.length; i < L;) C = C >>> 8 ^ T0[(C ^ bstr.charCodeAt(i++)) & 255];
|
|
299
|
+
return ~C;
|
|
300
|
+
}
|
|
301
|
+
function crc32_buf(B, seed) {
|
|
302
|
+
var C = seed ^ -1, L = B.length - 15, i = 0;
|
|
303
|
+
for (; i < L;) C = Tf[B[i++] ^ C & 255] ^ Te[B[i++] ^ C >> 8 & 255] ^ Td[B[i++] ^ C >> 16 & 255] ^ Tc[B[i++] ^ C >>> 24] ^ Tb[B[i++]] ^ Ta[B[i++]] ^ T9[B[i++]] ^ T8[B[i++]] ^ T7[B[i++]] ^ T6[B[i++]] ^ T5[B[i++]] ^ T4[B[i++]] ^ T3[B[i++]] ^ T2[B[i++]] ^ T1[B[i++]] ^ T0[B[i++]];
|
|
304
|
+
L += 15;
|
|
305
|
+
while (i < L) C = C >>> 8 ^ T0[(C ^ B[i++]) & 255];
|
|
306
|
+
return ~C;
|
|
307
|
+
}
|
|
308
|
+
function crc32_str(str, seed) {
|
|
309
|
+
var C = seed ^ -1;
|
|
310
|
+
for (var i = 0, L = str.length, c = 0, d = 0; i < L;) {
|
|
311
|
+
c = str.charCodeAt(i++);
|
|
312
|
+
if (c < 128) C = C >>> 8 ^ T0[(C ^ c) & 255];
|
|
313
|
+
else if (c < 2048) {
|
|
314
|
+
C = C >>> 8 ^ T0[(C ^ (192 | c >> 6 & 31)) & 255];
|
|
315
|
+
C = C >>> 8 ^ T0[(C ^ (128 | c & 63)) & 255];
|
|
316
|
+
} else if (c >= 55296 && c < 57344) {
|
|
317
|
+
c = (c & 1023) + 64;
|
|
318
|
+
d = str.charCodeAt(i++) & 1023;
|
|
319
|
+
C = C >>> 8 ^ T0[(C ^ (240 | c >> 8 & 7)) & 255];
|
|
320
|
+
C = C >>> 8 ^ T0[(C ^ (128 | c >> 2 & 63)) & 255];
|
|
321
|
+
C = C >>> 8 ^ T0[(C ^ (128 | d >> 6 & 15 | (c & 3) << 4)) & 255];
|
|
322
|
+
C = C >>> 8 ^ T0[(C ^ (128 | d & 63)) & 255];
|
|
323
|
+
} else {
|
|
324
|
+
C = C >>> 8 ^ T0[(C ^ (224 | c >> 12 & 15)) & 255];
|
|
325
|
+
C = C >>> 8 ^ T0[(C ^ (128 | c >> 6 & 63)) & 255];
|
|
326
|
+
C = C >>> 8 ^ T0[(C ^ (128 | c & 63)) & 255];
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
return ~C;
|
|
330
|
+
}
|
|
331
|
+
CRC32.table = T0;
|
|
332
|
+
CRC32.bstr = crc32_bstr;
|
|
333
|
+
CRC32.buf = crc32_buf;
|
|
334
|
+
CRC32.str = crc32_str;
|
|
335
|
+
return CRC32;
|
|
336
|
+
})();
|
|
337
|
+
var CFB = (function _CFB() {
|
|
338
|
+
var exports$1 = {};
|
|
339
|
+
exports$1.version = "1.2.2";
|
|
340
|
+
function namecmp(l, r) {
|
|
341
|
+
var L = l.split("/"), R = r.split("/");
|
|
342
|
+
for (var i = 0, c = 0, Z = Math.min(L.length, R.length); i < Z; ++i) {
|
|
343
|
+
if (c = L[i].length - R[i].length) return c;
|
|
344
|
+
if (L[i] != R[i]) return L[i] < R[i] ? -1 : 1;
|
|
345
|
+
}
|
|
346
|
+
return L.length - R.length;
|
|
347
|
+
}
|
|
348
|
+
function dirname(p) {
|
|
349
|
+
if (p.charAt(p.length - 1) == "/") return p.slice(0, -1).indexOf("/") === -1 ? p : dirname(p.slice(0, -1));
|
|
350
|
+
var c = p.lastIndexOf("/");
|
|
351
|
+
return c === -1 ? p : p.slice(0, c + 1);
|
|
352
|
+
}
|
|
353
|
+
function filename(p) {
|
|
354
|
+
if (p.charAt(p.length - 1) == "/") return filename(p.slice(0, -1));
|
|
355
|
+
var c = p.lastIndexOf("/");
|
|
356
|
+
return c === -1 ? p : p.slice(c + 1);
|
|
357
|
+
}
|
|
358
|
+
function write_dos_date(buf, date) {
|
|
359
|
+
if (typeof date === "string") date = new Date(date);
|
|
360
|
+
var hms = date.getHours();
|
|
361
|
+
hms = hms << 6 | date.getMinutes();
|
|
362
|
+
hms = hms << 5 | date.getSeconds() >>> 1;
|
|
363
|
+
buf.write_shift(2, hms);
|
|
364
|
+
var ymd = date.getFullYear() - 1980;
|
|
365
|
+
ymd = ymd << 4 | date.getMonth() + 1;
|
|
366
|
+
ymd = ymd << 5 | date.getDate();
|
|
367
|
+
buf.write_shift(2, ymd);
|
|
368
|
+
}
|
|
369
|
+
function parse_dos_date(buf) {
|
|
370
|
+
var hms = buf.read_shift(2) & 65535;
|
|
371
|
+
var ymd = buf.read_shift(2) & 65535;
|
|
372
|
+
var val = /* @__PURE__ */ new Date();
|
|
373
|
+
var d = ymd & 31;
|
|
374
|
+
ymd >>>= 5;
|
|
375
|
+
var m = ymd & 15;
|
|
376
|
+
ymd >>>= 4;
|
|
377
|
+
val.setMilliseconds(0);
|
|
378
|
+
val.setFullYear(ymd + 1980);
|
|
379
|
+
val.setMonth(m - 1);
|
|
380
|
+
val.setDate(d);
|
|
381
|
+
var S = hms & 31;
|
|
382
|
+
hms >>>= 5;
|
|
383
|
+
var M = hms & 63;
|
|
384
|
+
hms >>>= 6;
|
|
385
|
+
val.setHours(hms);
|
|
386
|
+
val.setMinutes(M);
|
|
387
|
+
val.setSeconds(S << 1);
|
|
388
|
+
return val;
|
|
389
|
+
}
|
|
390
|
+
function parse_extra_field(blob) {
|
|
391
|
+
prep_blob(blob, 0);
|
|
392
|
+
var o = {};
|
|
393
|
+
var flags = 0;
|
|
394
|
+
while (blob.l <= blob.length - 4) {
|
|
395
|
+
var type = blob.read_shift(2);
|
|
396
|
+
var sz = blob.read_shift(2), tgt = blob.l + sz;
|
|
397
|
+
var p = {};
|
|
398
|
+
switch (type) {
|
|
399
|
+
case 21589:
|
|
400
|
+
flags = blob.read_shift(1);
|
|
401
|
+
if (flags & 1) p.mtime = blob.read_shift(4);
|
|
402
|
+
if (sz > 5) {
|
|
403
|
+
if (flags & 2) p.atime = blob.read_shift(4);
|
|
404
|
+
if (flags & 4) p.ctime = blob.read_shift(4);
|
|
405
|
+
}
|
|
406
|
+
if (p.mtime) p.mt = /* @__PURE__ */ new Date(p.mtime * 1e3);
|
|
407
|
+
}
|
|
408
|
+
blob.l = tgt;
|
|
409
|
+
o[type] = p;
|
|
410
|
+
}
|
|
411
|
+
return o;
|
|
412
|
+
}
|
|
413
|
+
var fs;
|
|
414
|
+
function get_fs() {
|
|
415
|
+
return fs || (fs = require___vite_browser_external());
|
|
416
|
+
}
|
|
417
|
+
function parse(file, options) {
|
|
418
|
+
if (file[0] == 80 && file[1] == 75) return parse_zip(file, options);
|
|
419
|
+
if ((file[0] | 32) == 109 && (file[1] | 32) == 105) return parse_mad(file, options);
|
|
420
|
+
if (file.length < 512) throw new Error("CFB file size " + file.length + " < 512");
|
|
421
|
+
var mver = 3;
|
|
422
|
+
var ssz = 512;
|
|
423
|
+
var nmfs = 0;
|
|
424
|
+
var difat_sec_cnt = 0;
|
|
425
|
+
var dir_start = 0;
|
|
426
|
+
var minifat_start = 0;
|
|
427
|
+
var difat_start = 0;
|
|
428
|
+
var fat_addrs = [];
|
|
429
|
+
var blob = file.slice(0, 512);
|
|
430
|
+
prep_blob(blob, 0);
|
|
431
|
+
var mv = check_get_mver(blob);
|
|
432
|
+
mver = mv[0];
|
|
433
|
+
switch (mver) {
|
|
434
|
+
case 3:
|
|
435
|
+
ssz = 512;
|
|
436
|
+
break;
|
|
437
|
+
case 4:
|
|
438
|
+
ssz = 4096;
|
|
439
|
+
break;
|
|
440
|
+
case 0: if (mv[1] == 0) return parse_zip(file, options);
|
|
441
|
+
default: throw new Error("Major Version: Expected 3 or 4 saw " + mver);
|
|
442
|
+
}
|
|
443
|
+
if (ssz !== 512) {
|
|
444
|
+
blob = file.slice(0, ssz);
|
|
445
|
+
prep_blob(blob, 28);
|
|
446
|
+
}
|
|
447
|
+
var header = file.slice(0, ssz);
|
|
448
|
+
check_shifts(blob, mver);
|
|
449
|
+
var dir_cnt = blob.read_shift(4, "i");
|
|
450
|
+
if (mver === 3 && dir_cnt !== 0) throw new Error("# Directory Sectors: Expected 0 saw " + dir_cnt);
|
|
451
|
+
blob.l += 4;
|
|
452
|
+
dir_start = blob.read_shift(4, "i");
|
|
453
|
+
blob.l += 4;
|
|
454
|
+
blob.chk("00100000", "Mini Stream Cutoff Size: ");
|
|
455
|
+
minifat_start = blob.read_shift(4, "i");
|
|
456
|
+
nmfs = blob.read_shift(4, "i");
|
|
457
|
+
difat_start = blob.read_shift(4, "i");
|
|
458
|
+
difat_sec_cnt = blob.read_shift(4, "i");
|
|
459
|
+
for (var q = -1, j = 0; j < 109; ++j) {
|
|
460
|
+
q = blob.read_shift(4, "i");
|
|
461
|
+
if (q < 0) break;
|
|
462
|
+
fat_addrs[j] = q;
|
|
463
|
+
}
|
|
464
|
+
/** Break the file up into sectors */
|
|
465
|
+
var sectors = sectorify(file, ssz);
|
|
466
|
+
sleuth_fat(difat_start, difat_sec_cnt, sectors, ssz, fat_addrs);
|
|
467
|
+
/** Chains */
|
|
468
|
+
var sector_list = make_sector_list(sectors, dir_start, fat_addrs, ssz);
|
|
469
|
+
sector_list[dir_start].name = "!Directory";
|
|
470
|
+
if (nmfs > 0 && minifat_start !== ENDOFCHAIN) sector_list[minifat_start].name = "!MiniFAT";
|
|
471
|
+
sector_list[fat_addrs[0]].name = "!FAT";
|
|
472
|
+
sector_list.fat_addrs = fat_addrs;
|
|
473
|
+
sector_list.ssz = ssz;
|
|
474
|
+
var files = {}, Paths = [], FileIndex = [], FullPaths = [];
|
|
475
|
+
read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, FileIndex, minifat_start);
|
|
476
|
+
build_full_paths(FileIndex, FullPaths, Paths);
|
|
477
|
+
Paths.shift();
|
|
478
|
+
var o = {
|
|
479
|
+
FileIndex,
|
|
480
|
+
FullPaths
|
|
481
|
+
};
|
|
482
|
+
if (options && options.raw) o.raw = {
|
|
483
|
+
header,
|
|
484
|
+
sectors
|
|
485
|
+
};
|
|
486
|
+
return o;
|
|
487
|
+
}
|
|
488
|
+
function check_get_mver(blob) {
|
|
489
|
+
if (blob[blob.l] == 80 && blob[blob.l + 1] == 75) return [0, 0];
|
|
490
|
+
blob.chk(HEADER_SIGNATURE, "Header Signature: ");
|
|
491
|
+
blob.l += 16;
|
|
492
|
+
var mver = blob.read_shift(2, "u");
|
|
493
|
+
return [blob.read_shift(2, "u"), mver];
|
|
494
|
+
}
|
|
495
|
+
function check_shifts(blob, mver) {
|
|
496
|
+
var shift = 9;
|
|
497
|
+
blob.l += 2;
|
|
498
|
+
switch (shift = blob.read_shift(2)) {
|
|
499
|
+
case 9:
|
|
500
|
+
if (mver != 3) throw new Error("Sector Shift: Expected 9 saw " + shift);
|
|
501
|
+
break;
|
|
502
|
+
case 12:
|
|
503
|
+
if (mver != 4) throw new Error("Sector Shift: Expected 12 saw " + shift);
|
|
504
|
+
break;
|
|
505
|
+
default: throw new Error("Sector Shift: Expected 9 or 12 saw " + shift);
|
|
506
|
+
}
|
|
507
|
+
blob.chk("0600", "Mini Sector Shift: ");
|
|
508
|
+
blob.chk("000000000000", "Reserved: ");
|
|
509
|
+
}
|
|
510
|
+
/** Break the file up into sectors */
|
|
511
|
+
function sectorify(file, ssz) {
|
|
512
|
+
var nsectors = Math.ceil(file.length / ssz) - 1;
|
|
513
|
+
var sectors = [];
|
|
514
|
+
for (var i = 1; i < nsectors; ++i) sectors[i - 1] = file.slice(i * ssz, (i + 1) * ssz);
|
|
515
|
+
sectors[nsectors - 1] = file.slice(nsectors * ssz);
|
|
516
|
+
return sectors;
|
|
517
|
+
}
|
|
518
|
+
function build_full_paths(FI, FP, Paths) {
|
|
519
|
+
var i = 0, L = 0, R = 0, C = 0, j = 0, pl = Paths.length;
|
|
520
|
+
var dad = [], q = [];
|
|
521
|
+
for (; i < pl; ++i) {
|
|
522
|
+
dad[i] = q[i] = i;
|
|
523
|
+
FP[i] = Paths[i];
|
|
524
|
+
}
|
|
525
|
+
for (; j < q.length; ++j) {
|
|
526
|
+
i = q[j];
|
|
527
|
+
L = FI[i].L;
|
|
528
|
+
R = FI[i].R;
|
|
529
|
+
C = FI[i].C;
|
|
530
|
+
if (dad[i] === i) {
|
|
531
|
+
if (L !== -1 && dad[L] !== L) dad[i] = dad[L];
|
|
532
|
+
if (R !== -1 && dad[R] !== R) dad[i] = dad[R];
|
|
533
|
+
}
|
|
534
|
+
if (C !== -1) dad[C] = i;
|
|
535
|
+
if (L !== -1 && i != dad[i]) {
|
|
536
|
+
dad[L] = dad[i];
|
|
537
|
+
if (q.lastIndexOf(L) < j) q.push(L);
|
|
538
|
+
}
|
|
539
|
+
if (R !== -1 && i != dad[i]) {
|
|
540
|
+
dad[R] = dad[i];
|
|
541
|
+
if (q.lastIndexOf(R) < j) q.push(R);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
for (i = 1; i < pl; ++i) if (dad[i] === i) {
|
|
545
|
+
if (R !== -1 && dad[R] !== R) dad[i] = dad[R];
|
|
546
|
+
else if (L !== -1 && dad[L] !== L) dad[i] = dad[L];
|
|
547
|
+
}
|
|
548
|
+
for (i = 1; i < pl; ++i) {
|
|
549
|
+
if (FI[i].type === 0) continue;
|
|
550
|
+
j = i;
|
|
551
|
+
if (j != dad[j]) do {
|
|
552
|
+
j = dad[j];
|
|
553
|
+
FP[i] = FP[j] + "/" + FP[i];
|
|
554
|
+
} while (j !== 0 && -1 !== dad[j] && j != dad[j]);
|
|
555
|
+
dad[i] = -1;
|
|
556
|
+
}
|
|
557
|
+
FP[0] += "/";
|
|
558
|
+
for (i = 1; i < pl; ++i) if (FI[i].type !== 2) FP[i] += "/";
|
|
559
|
+
}
|
|
560
|
+
function get_mfat_entry(entry, payload, mini) {
|
|
561
|
+
var start = entry.start, size = entry.size;
|
|
562
|
+
var o = [];
|
|
563
|
+
var idx = start;
|
|
564
|
+
while (mini && size > 0 && idx >= 0) {
|
|
565
|
+
o.push(payload.slice(idx * MSSZ, idx * MSSZ + MSSZ));
|
|
566
|
+
size -= MSSZ;
|
|
567
|
+
idx = __readInt32LE(mini, idx * 4);
|
|
568
|
+
}
|
|
569
|
+
if (o.length === 0) return new_buf(0);
|
|
570
|
+
return bconcat(o).slice(0, entry.size);
|
|
571
|
+
}
|
|
572
|
+
/** Chase down the rest of the DIFAT chain to build a comprehensive list
|
|
573
|
+
DIFAT chains by storing the next sector number as the last 32 bits */
|
|
574
|
+
function sleuth_fat(idx, cnt, sectors, ssz, fat_addrs) {
|
|
575
|
+
var q = ENDOFCHAIN;
|
|
576
|
+
if (idx === ENDOFCHAIN) {
|
|
577
|
+
if (cnt !== 0) throw new Error("DIFAT chain shorter than expected");
|
|
578
|
+
} else if (idx !== -1) {
|
|
579
|
+
var sector = sectors[idx], m = (ssz >>> 2) - 1;
|
|
580
|
+
if (!sector) return;
|
|
581
|
+
for (var i = 0; i < m; ++i) {
|
|
582
|
+
if ((q = __readInt32LE(sector, i * 4)) === ENDOFCHAIN) break;
|
|
583
|
+
fat_addrs.push(q);
|
|
584
|
+
}
|
|
585
|
+
if (cnt >= 1) sleuth_fat(__readInt32LE(sector, ssz - 4), cnt - 1, sectors, ssz, fat_addrs);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
/** Follow the linked list of sectors for a given starting point */
|
|
589
|
+
function get_sector_list(sectors, start, fat_addrs, ssz, chkd) {
|
|
590
|
+
var buf = [], buf_chain = [];
|
|
591
|
+
if (!chkd) chkd = [];
|
|
592
|
+
var modulus = ssz - 1, j = 0, jj = 0;
|
|
593
|
+
for (j = start; j >= 0;) {
|
|
594
|
+
chkd[j] = true;
|
|
595
|
+
buf[buf.length] = j;
|
|
596
|
+
buf_chain.push(sectors[j]);
|
|
597
|
+
var addr = fat_addrs[Math.floor(j * 4 / ssz)];
|
|
598
|
+
jj = j * 4 & modulus;
|
|
599
|
+
if (ssz < 4 + jj) throw new Error("FAT boundary crossed: " + j + " 4 " + ssz);
|
|
600
|
+
if (!sectors[addr]) break;
|
|
601
|
+
j = __readInt32LE(sectors[addr], jj);
|
|
602
|
+
}
|
|
603
|
+
return {
|
|
604
|
+
nodes: buf,
|
|
605
|
+
data: __toBuffer([buf_chain])
|
|
606
|
+
};
|
|
607
|
+
}
|
|
608
|
+
/** Chase down the sector linked lists */
|
|
609
|
+
function make_sector_list(sectors, dir_start, fat_addrs, ssz) {
|
|
610
|
+
var sl = sectors.length, sector_list = [];
|
|
611
|
+
var chkd = [], buf = [], buf_chain = [];
|
|
612
|
+
var modulus = ssz - 1, i = 0, j = 0, k = 0, jj = 0;
|
|
613
|
+
for (i = 0; i < sl; ++i) {
|
|
614
|
+
buf = [];
|
|
615
|
+
k = i + dir_start;
|
|
616
|
+
if (k >= sl) k -= sl;
|
|
617
|
+
if (chkd[k]) continue;
|
|
618
|
+
buf_chain = [];
|
|
619
|
+
var seen = [];
|
|
620
|
+
for (j = k; j >= 0;) {
|
|
621
|
+
seen[j] = true;
|
|
622
|
+
chkd[j] = true;
|
|
623
|
+
buf[buf.length] = j;
|
|
624
|
+
buf_chain.push(sectors[j]);
|
|
625
|
+
var addr = fat_addrs[Math.floor(j * 4 / ssz)];
|
|
626
|
+
jj = j * 4 & modulus;
|
|
627
|
+
if (ssz < 4 + jj) throw new Error("FAT boundary crossed: " + j + " 4 " + ssz);
|
|
628
|
+
if (!sectors[addr]) break;
|
|
629
|
+
j = __readInt32LE(sectors[addr], jj);
|
|
630
|
+
if (seen[j]) break;
|
|
631
|
+
}
|
|
632
|
+
sector_list[k] = {
|
|
633
|
+
nodes: buf,
|
|
634
|
+
data: __toBuffer([buf_chain])
|
|
635
|
+
};
|
|
636
|
+
}
|
|
637
|
+
return sector_list;
|
|
638
|
+
}
|
|
639
|
+
function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, FileIndex, mini) {
|
|
640
|
+
var minifat_store = 0, pl = Paths.length ? 2 : 0;
|
|
641
|
+
var sector = sector_list[dir_start].data;
|
|
642
|
+
var i = 0, namelen = 0, name;
|
|
643
|
+
for (; i < sector.length; i += 128) {
|
|
644
|
+
var blob = sector.slice(i, i + 128);
|
|
645
|
+
prep_blob(blob, 64);
|
|
646
|
+
namelen = blob.read_shift(2);
|
|
647
|
+
name = __utf16le(blob, 0, namelen - pl);
|
|
648
|
+
Paths.push(name);
|
|
649
|
+
var o = {
|
|
650
|
+
name,
|
|
651
|
+
type: blob.read_shift(1),
|
|
652
|
+
color: blob.read_shift(1),
|
|
653
|
+
L: blob.read_shift(4, "i"),
|
|
654
|
+
R: blob.read_shift(4, "i"),
|
|
655
|
+
C: blob.read_shift(4, "i"),
|
|
656
|
+
clsid: blob.read_shift(16),
|
|
657
|
+
state: blob.read_shift(4, "i"),
|
|
658
|
+
start: 0,
|
|
659
|
+
size: 0
|
|
660
|
+
};
|
|
661
|
+
if (blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) !== 0) o.ct = read_date(blob, blob.l - 8);
|
|
662
|
+
if (blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) !== 0) o.mt = read_date(blob, blob.l - 8);
|
|
663
|
+
o.start = blob.read_shift(4, "i");
|
|
664
|
+
o.size = blob.read_shift(4, "i");
|
|
665
|
+
if (o.size < 0 && o.start < 0) {
|
|
666
|
+
o.size = o.type = 0;
|
|
667
|
+
o.start = ENDOFCHAIN;
|
|
668
|
+
o.name = "";
|
|
669
|
+
}
|
|
670
|
+
if (o.type === 5) {
|
|
671
|
+
minifat_store = o.start;
|
|
672
|
+
if (nmfs > 0 && minifat_store !== ENDOFCHAIN) sector_list[minifat_store].name = "!StreamData";
|
|
673
|
+
} else if (o.size >= 4096) {
|
|
674
|
+
o.storage = "fat";
|
|
675
|
+
if (sector_list[o.start] === void 0) sector_list[o.start] = get_sector_list(sectors, o.start, sector_list.fat_addrs, sector_list.ssz);
|
|
676
|
+
sector_list[o.start].name = o.name;
|
|
677
|
+
o.content = sector_list[o.start].data.slice(0, o.size);
|
|
678
|
+
} else {
|
|
679
|
+
o.storage = "minifat";
|
|
680
|
+
if (o.size < 0) o.size = 0;
|
|
681
|
+
else if (minifat_store !== ENDOFCHAIN && o.start !== ENDOFCHAIN && sector_list[minifat_store]) o.content = get_mfat_entry(o, sector_list[minifat_store].data, (sector_list[mini] || {}).data);
|
|
682
|
+
}
|
|
683
|
+
if (o.content) prep_blob(o.content, 0);
|
|
684
|
+
files[name] = o;
|
|
685
|
+
FileIndex.push(o);
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
function read_date(blob, offset) {
|
|
689
|
+
return /* @__PURE__ */ new Date((__readUInt32LE(blob, offset + 4) / 1e7 * Math.pow(2, 32) + __readUInt32LE(blob, offset) / 1e7 - 11644473600) * 1e3);
|
|
690
|
+
}
|
|
691
|
+
function read_file(filename, options) {
|
|
692
|
+
get_fs();
|
|
693
|
+
return parse(fs.readFileSync(filename), options);
|
|
694
|
+
}
|
|
695
|
+
function read(blob, options) {
|
|
696
|
+
var type = options && options.type;
|
|
697
|
+
if (!type) {
|
|
698
|
+
if (has_buf && Buffer.isBuffer(blob)) type = "buffer";
|
|
699
|
+
}
|
|
700
|
+
switch (type || "base64") {
|
|
701
|
+
case "file": return read_file(blob, options);
|
|
702
|
+
case "base64": return parse(s2a(Base64_decode(blob)), options);
|
|
703
|
+
case "binary": return parse(s2a(blob), options);
|
|
704
|
+
}
|
|
705
|
+
return parse(blob, options);
|
|
706
|
+
}
|
|
707
|
+
function init_cfb(cfb, opts) {
|
|
708
|
+
var o = opts || {}, root = o.root || "Root Entry";
|
|
709
|
+
if (!cfb.FullPaths) cfb.FullPaths = [];
|
|
710
|
+
if (!cfb.FileIndex) cfb.FileIndex = [];
|
|
711
|
+
if (cfb.FullPaths.length !== cfb.FileIndex.length) throw new Error("inconsistent CFB structure");
|
|
712
|
+
if (cfb.FullPaths.length === 0) {
|
|
713
|
+
cfb.FullPaths[0] = root + "/";
|
|
714
|
+
cfb.FileIndex[0] = {
|
|
715
|
+
name: root,
|
|
716
|
+
type: 5
|
|
717
|
+
};
|
|
718
|
+
}
|
|
719
|
+
if (o.CLSID) cfb.FileIndex[0].clsid = o.CLSID;
|
|
720
|
+
seed_cfb(cfb);
|
|
721
|
+
}
|
|
722
|
+
function seed_cfb(cfb) {
|
|
723
|
+
var nm = "Sh33tJ5";
|
|
724
|
+
if (CFB.find(cfb, "/" + nm)) return;
|
|
725
|
+
var p = new_buf(4);
|
|
726
|
+
p[0] = 55;
|
|
727
|
+
p[1] = p[3] = 50;
|
|
728
|
+
p[2] = 54;
|
|
729
|
+
cfb.FileIndex.push({
|
|
730
|
+
name: nm,
|
|
731
|
+
type: 2,
|
|
732
|
+
content: p,
|
|
733
|
+
size: 4,
|
|
734
|
+
L: 69,
|
|
735
|
+
R: 69,
|
|
736
|
+
C: 69
|
|
737
|
+
});
|
|
738
|
+
cfb.FullPaths.push(cfb.FullPaths[0] + nm);
|
|
739
|
+
rebuild_cfb(cfb);
|
|
740
|
+
}
|
|
741
|
+
function rebuild_cfb(cfb, f) {
|
|
742
|
+
init_cfb(cfb);
|
|
743
|
+
var gc = false, s = false;
|
|
744
|
+
for (var i = cfb.FullPaths.length - 1; i >= 0; --i) {
|
|
745
|
+
var _file = cfb.FileIndex[i];
|
|
746
|
+
switch (_file.type) {
|
|
747
|
+
case 0:
|
|
748
|
+
if (s) gc = true;
|
|
749
|
+
else {
|
|
750
|
+
cfb.FileIndex.pop();
|
|
751
|
+
cfb.FullPaths.pop();
|
|
752
|
+
}
|
|
753
|
+
break;
|
|
754
|
+
case 1:
|
|
755
|
+
case 2:
|
|
756
|
+
case 5:
|
|
757
|
+
s = true;
|
|
758
|
+
if (isNaN(_file.R * _file.L * _file.C)) gc = true;
|
|
759
|
+
if (_file.R > -1 && _file.L > -1 && _file.R == _file.L) gc = true;
|
|
760
|
+
break;
|
|
761
|
+
default: gc = true;
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
if (!gc && !f) return;
|
|
765
|
+
var now = new Date(1987, 1, 19), j = 0;
|
|
766
|
+
var fullPaths = Object.create ? Object.create(null) : {};
|
|
767
|
+
var data = [];
|
|
768
|
+
for (i = 0; i < cfb.FullPaths.length; ++i) {
|
|
769
|
+
fullPaths[cfb.FullPaths[i]] = true;
|
|
770
|
+
if (cfb.FileIndex[i].type === 0) continue;
|
|
771
|
+
data.push([cfb.FullPaths[i], cfb.FileIndex[i]]);
|
|
772
|
+
}
|
|
773
|
+
for (i = 0; i < data.length; ++i) {
|
|
774
|
+
var dad = dirname(data[i][0]);
|
|
775
|
+
s = fullPaths[dad];
|
|
776
|
+
while (!s) {
|
|
777
|
+
while (dirname(dad) && !fullPaths[dirname(dad)]) dad = dirname(dad);
|
|
778
|
+
data.push([dad, {
|
|
779
|
+
name: filename(dad).replace("/", ""),
|
|
780
|
+
type: 1,
|
|
781
|
+
clsid: HEADER_CLSID,
|
|
782
|
+
ct: now,
|
|
783
|
+
mt: now,
|
|
784
|
+
content: null
|
|
785
|
+
}]);
|
|
786
|
+
fullPaths[dad] = true;
|
|
787
|
+
dad = dirname(data[i][0]);
|
|
788
|
+
s = fullPaths[dad];
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
data.sort(function(x, y) {
|
|
792
|
+
return namecmp(x[0], y[0]);
|
|
793
|
+
});
|
|
794
|
+
cfb.FullPaths = [];
|
|
795
|
+
cfb.FileIndex = [];
|
|
796
|
+
for (i = 0; i < data.length; ++i) {
|
|
797
|
+
cfb.FullPaths[i] = data[i][0];
|
|
798
|
+
cfb.FileIndex[i] = data[i][1];
|
|
799
|
+
}
|
|
800
|
+
for (i = 0; i < data.length; ++i) {
|
|
801
|
+
var elt = cfb.FileIndex[i];
|
|
802
|
+
var nm = cfb.FullPaths[i];
|
|
803
|
+
elt.name = filename(nm).replace("/", "");
|
|
804
|
+
elt.L = elt.R = elt.C = -(elt.color = 1);
|
|
805
|
+
elt.size = elt.content ? elt.content.length : 0;
|
|
806
|
+
elt.start = 0;
|
|
807
|
+
elt.clsid = elt.clsid || HEADER_CLSID;
|
|
808
|
+
if (i === 0) {
|
|
809
|
+
elt.C = data.length > 1 ? 1 : -1;
|
|
810
|
+
elt.size = 0;
|
|
811
|
+
elt.type = 5;
|
|
812
|
+
} else if (nm.slice(-1) == "/") {
|
|
813
|
+
for (j = i + 1; j < data.length; ++j) if (dirname(cfb.FullPaths[j]) == nm) break;
|
|
814
|
+
elt.C = j >= data.length ? -1 : j;
|
|
815
|
+
for (j = i + 1; j < data.length; ++j) if (dirname(cfb.FullPaths[j]) == dirname(nm)) break;
|
|
816
|
+
elt.R = j >= data.length ? -1 : j;
|
|
817
|
+
elt.type = 1;
|
|
818
|
+
} else {
|
|
819
|
+
if (dirname(cfb.FullPaths[i + 1] || "") == dirname(nm)) elt.R = i + 1;
|
|
820
|
+
elt.type = 2;
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
function _write(cfb, options) {
|
|
825
|
+
var _opts = options || {};
|
|
826
|
+
if (_opts.fileType == "mad") return write_mad(cfb, _opts);
|
|
827
|
+
rebuild_cfb(cfb);
|
|
828
|
+
switch (_opts.fileType) {
|
|
829
|
+
case "zip": return write_zip(cfb, _opts);
|
|
830
|
+
}
|
|
831
|
+
var L = (function(cfb) {
|
|
832
|
+
var mini_size = 0, fat_size = 0;
|
|
833
|
+
for (var i = 0; i < cfb.FileIndex.length; ++i) {
|
|
834
|
+
var file = cfb.FileIndex[i];
|
|
835
|
+
if (!file.content) continue;
|
|
836
|
+
var flen = file.content.length;
|
|
837
|
+
if (flen > 0) {
|
|
838
|
+
if (flen < 4096) mini_size += flen + 63 >> 6;
|
|
839
|
+
else fat_size += flen + 511 >> 9;
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
var dir_cnt = cfb.FullPaths.length + 3 >> 2;
|
|
843
|
+
var mini_cnt = mini_size + 7 >> 3;
|
|
844
|
+
var mfat_cnt = mini_size + 127 >> 7;
|
|
845
|
+
var fat_base = mini_cnt + fat_size + dir_cnt + mfat_cnt;
|
|
846
|
+
var fat_cnt = fat_base + 127 >> 7;
|
|
847
|
+
var difat_cnt = fat_cnt <= 109 ? 0 : Math.ceil((fat_cnt - 109) / 127);
|
|
848
|
+
while (fat_base + fat_cnt + difat_cnt + 127 >> 7 > fat_cnt) difat_cnt = ++fat_cnt <= 109 ? 0 : Math.ceil((fat_cnt - 109) / 127);
|
|
849
|
+
var L = [
|
|
850
|
+
1,
|
|
851
|
+
difat_cnt,
|
|
852
|
+
fat_cnt,
|
|
853
|
+
mfat_cnt,
|
|
854
|
+
dir_cnt,
|
|
855
|
+
fat_size,
|
|
856
|
+
mini_size,
|
|
857
|
+
0
|
|
858
|
+
];
|
|
859
|
+
cfb.FileIndex[0].size = mini_size << 6;
|
|
860
|
+
L[7] = (cfb.FileIndex[0].start = L[0] + L[1] + L[2] + L[3] + L[4] + L[5]) + (L[6] + 7 >> 3);
|
|
861
|
+
return L;
|
|
862
|
+
})(cfb);
|
|
863
|
+
var o = new_buf(L[7] << 9);
|
|
864
|
+
var i = 0, T = 0;
|
|
865
|
+
for (i = 0; i < 8; ++i) o.write_shift(1, HEADER_SIG[i]);
|
|
866
|
+
for (i = 0; i < 8; ++i) o.write_shift(2, 0);
|
|
867
|
+
o.write_shift(2, 62);
|
|
868
|
+
o.write_shift(2, 3);
|
|
869
|
+
o.write_shift(2, 65534);
|
|
870
|
+
o.write_shift(2, 9);
|
|
871
|
+
o.write_shift(2, 6);
|
|
872
|
+
for (i = 0; i < 3; ++i) o.write_shift(2, 0);
|
|
873
|
+
o.write_shift(4, 0);
|
|
874
|
+
o.write_shift(4, L[2]);
|
|
875
|
+
o.write_shift(4, L[0] + L[1] + L[2] + L[3] - 1);
|
|
876
|
+
o.write_shift(4, 0);
|
|
877
|
+
o.write_shift(4, 4096);
|
|
878
|
+
o.write_shift(4, L[3] ? L[0] + L[1] + L[2] - 1 : ENDOFCHAIN);
|
|
879
|
+
o.write_shift(4, L[3]);
|
|
880
|
+
o.write_shift(-4, L[1] ? L[0] - 1 : ENDOFCHAIN);
|
|
881
|
+
o.write_shift(4, L[1]);
|
|
882
|
+
for (i = 0; i < 109; ++i) o.write_shift(-4, i < L[2] ? L[1] + i : -1);
|
|
883
|
+
if (L[1]) for (T = 0; T < L[1]; ++T) {
|
|
884
|
+
for (; i < 236 + T * 127; ++i) o.write_shift(-4, i < L[2] ? L[1] + i : -1);
|
|
885
|
+
o.write_shift(-4, T === L[1] - 1 ? ENDOFCHAIN : T + 1);
|
|
886
|
+
}
|
|
887
|
+
var chainit = function(w) {
|
|
888
|
+
for (T += w; i < T - 1; ++i) o.write_shift(-4, i + 1);
|
|
889
|
+
if (w) {
|
|
890
|
+
++i;
|
|
891
|
+
o.write_shift(-4, ENDOFCHAIN);
|
|
892
|
+
}
|
|
893
|
+
};
|
|
894
|
+
T = i = 0;
|
|
895
|
+
for (T += L[1]; i < T; ++i) o.write_shift(-4, consts.DIFSECT);
|
|
896
|
+
for (T += L[2]; i < T; ++i) o.write_shift(-4, consts.FATSECT);
|
|
897
|
+
chainit(L[3]);
|
|
898
|
+
chainit(L[4]);
|
|
899
|
+
var j = 0, flen = 0;
|
|
900
|
+
var file = cfb.FileIndex[0];
|
|
901
|
+
for (; j < cfb.FileIndex.length; ++j) {
|
|
902
|
+
file = cfb.FileIndex[j];
|
|
903
|
+
if (!file.content) continue;
|
|
904
|
+
flen = file.content.length;
|
|
905
|
+
if (flen < 4096) continue;
|
|
906
|
+
file.start = T;
|
|
907
|
+
chainit(flen + 511 >> 9);
|
|
908
|
+
}
|
|
909
|
+
chainit(L[6] + 7 >> 3);
|
|
910
|
+
while (o.l & 511) o.write_shift(-4, consts.ENDOFCHAIN);
|
|
911
|
+
T = i = 0;
|
|
912
|
+
for (j = 0; j < cfb.FileIndex.length; ++j) {
|
|
913
|
+
file = cfb.FileIndex[j];
|
|
914
|
+
if (!file.content) continue;
|
|
915
|
+
flen = file.content.length;
|
|
916
|
+
if (!flen || flen >= 4096) continue;
|
|
917
|
+
file.start = T;
|
|
918
|
+
chainit(flen + 63 >> 6);
|
|
919
|
+
}
|
|
920
|
+
while (o.l & 511) o.write_shift(-4, consts.ENDOFCHAIN);
|
|
921
|
+
for (i = 0; i < L[4] << 2; ++i) {
|
|
922
|
+
var nm = cfb.FullPaths[i];
|
|
923
|
+
if (!nm || nm.length === 0) {
|
|
924
|
+
for (j = 0; j < 17; ++j) o.write_shift(4, 0);
|
|
925
|
+
for (j = 0; j < 3; ++j) o.write_shift(4, -1);
|
|
926
|
+
for (j = 0; j < 12; ++j) o.write_shift(4, 0);
|
|
927
|
+
continue;
|
|
928
|
+
}
|
|
929
|
+
file = cfb.FileIndex[i];
|
|
930
|
+
if (i === 0) file.start = file.size ? file.start - 1 : ENDOFCHAIN;
|
|
931
|
+
var _nm = i === 0 && _opts.root || file.name;
|
|
932
|
+
if (_nm.length > 32) {
|
|
933
|
+
console.error("Name " + _nm + " will be truncated to " + _nm.slice(0, 32));
|
|
934
|
+
_nm = _nm.slice(0, 32);
|
|
935
|
+
}
|
|
936
|
+
flen = 2 * (_nm.length + 1);
|
|
937
|
+
o.write_shift(64, _nm, "utf16le");
|
|
938
|
+
o.write_shift(2, flen);
|
|
939
|
+
o.write_shift(1, file.type);
|
|
940
|
+
o.write_shift(1, file.color);
|
|
941
|
+
o.write_shift(-4, file.L);
|
|
942
|
+
o.write_shift(-4, file.R);
|
|
943
|
+
o.write_shift(-4, file.C);
|
|
944
|
+
if (!file.clsid) for (j = 0; j < 4; ++j) o.write_shift(4, 0);
|
|
945
|
+
else o.write_shift(16, file.clsid, "hex");
|
|
946
|
+
o.write_shift(4, file.state || 0);
|
|
947
|
+
o.write_shift(4, 0);
|
|
948
|
+
o.write_shift(4, 0);
|
|
949
|
+
o.write_shift(4, 0);
|
|
950
|
+
o.write_shift(4, 0);
|
|
951
|
+
o.write_shift(4, file.start);
|
|
952
|
+
o.write_shift(4, file.size);
|
|
953
|
+
o.write_shift(4, 0);
|
|
954
|
+
}
|
|
955
|
+
for (i = 1; i < cfb.FileIndex.length; ++i) {
|
|
956
|
+
file = cfb.FileIndex[i];
|
|
957
|
+
if (file.size >= 4096) {
|
|
958
|
+
o.l = file.start + 1 << 9;
|
|
959
|
+
if (has_buf && Buffer.isBuffer(file.content)) {
|
|
960
|
+
file.content.copy(o, o.l, 0, file.size);
|
|
961
|
+
o.l += file.size + 511 & -512;
|
|
962
|
+
} else {
|
|
963
|
+
for (j = 0; j < file.size; ++j) o.write_shift(1, file.content[j]);
|
|
964
|
+
for (; j & 511; ++j) o.write_shift(1, 0);
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
for (i = 1; i < cfb.FileIndex.length; ++i) {
|
|
969
|
+
file = cfb.FileIndex[i];
|
|
970
|
+
if (file.size > 0 && file.size < 4096) {
|
|
971
|
+
if (has_buf && Buffer.isBuffer(file.content)) {
|
|
972
|
+
file.content.copy(o, o.l, 0, file.size);
|
|
973
|
+
o.l += file.size + 63 & -64;
|
|
974
|
+
} else {
|
|
975
|
+
for (j = 0; j < file.size; ++j) o.write_shift(1, file.content[j]);
|
|
976
|
+
for (; j & 63; ++j) o.write_shift(1, 0);
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
if (has_buf) o.l = o.length;
|
|
981
|
+
else while (o.l < o.length) o.write_shift(1, 0);
|
|
982
|
+
return o;
|
|
983
|
+
}
|
|
984
|
+
function find(cfb, path) {
|
|
985
|
+
var UCFullPaths = cfb.FullPaths.map(function(x) {
|
|
986
|
+
return x.toUpperCase();
|
|
987
|
+
});
|
|
988
|
+
var UCPaths = UCFullPaths.map(function(x) {
|
|
989
|
+
var y = x.split("/");
|
|
990
|
+
return y[y.length - (x.slice(-1) == "/" ? 2 : 1)];
|
|
991
|
+
});
|
|
992
|
+
var k = false;
|
|
993
|
+
if (path.charCodeAt(0) === 47) {
|
|
994
|
+
k = true;
|
|
995
|
+
path = UCFullPaths[0].slice(0, -1) + path;
|
|
996
|
+
} else k = path.indexOf("/") !== -1;
|
|
997
|
+
var UCPath = path.toUpperCase();
|
|
998
|
+
var w = k === true ? UCFullPaths.indexOf(UCPath) : UCPaths.indexOf(UCPath);
|
|
999
|
+
if (w !== -1) return cfb.FileIndex[w];
|
|
1000
|
+
var m = !UCPath.match(chr1);
|
|
1001
|
+
UCPath = UCPath.replace(chr0, "");
|
|
1002
|
+
if (m) UCPath = UCPath.replace(chr1, "!");
|
|
1003
|
+
for (w = 0; w < UCFullPaths.length; ++w) {
|
|
1004
|
+
if ((m ? UCFullPaths[w].replace(chr1, "!") : UCFullPaths[w]).replace(chr0, "") == UCPath) return cfb.FileIndex[w];
|
|
1005
|
+
if ((m ? UCPaths[w].replace(chr1, "!") : UCPaths[w]).replace(chr0, "") == UCPath) return cfb.FileIndex[w];
|
|
1006
|
+
}
|
|
1007
|
+
return null;
|
|
1008
|
+
}
|
|
1009
|
+
/** CFB Constants */
|
|
1010
|
+
var MSSZ = 64;
|
|
1011
|
+
var ENDOFCHAIN = -2;
|
|
1012
|
+
var HEADER_SIGNATURE = "d0cf11e0a1b11ae1";
|
|
1013
|
+
var HEADER_SIG = [
|
|
1014
|
+
208,
|
|
1015
|
+
207,
|
|
1016
|
+
17,
|
|
1017
|
+
224,
|
|
1018
|
+
161,
|
|
1019
|
+
177,
|
|
1020
|
+
26,
|
|
1021
|
+
225
|
|
1022
|
+
];
|
|
1023
|
+
var HEADER_CLSID = "00000000000000000000000000000000";
|
|
1024
|
+
var consts = {
|
|
1025
|
+
MAXREGSECT: -6,
|
|
1026
|
+
DIFSECT: -4,
|
|
1027
|
+
FATSECT: -3,
|
|
1028
|
+
ENDOFCHAIN,
|
|
1029
|
+
FREESECT: -1,
|
|
1030
|
+
HEADER_SIGNATURE,
|
|
1031
|
+
HEADER_MINOR_VERSION: "3e00",
|
|
1032
|
+
MAXREGSID: -6,
|
|
1033
|
+
NOSTREAM: -1,
|
|
1034
|
+
HEADER_CLSID,
|
|
1035
|
+
EntryTypes: [
|
|
1036
|
+
"unknown",
|
|
1037
|
+
"storage",
|
|
1038
|
+
"stream",
|
|
1039
|
+
"lockbytes",
|
|
1040
|
+
"property",
|
|
1041
|
+
"root"
|
|
1042
|
+
]
|
|
1043
|
+
};
|
|
1044
|
+
function write_file(cfb, filename, options) {
|
|
1045
|
+
get_fs();
|
|
1046
|
+
var o = _write(cfb, options);
|
|
1047
|
+
fs.writeFileSync(filename, o);
|
|
1048
|
+
}
|
|
1049
|
+
function a2s(o) {
|
|
1050
|
+
var out = new Array(o.length);
|
|
1051
|
+
for (var i = 0; i < o.length; ++i) out[i] = String.fromCharCode(o[i]);
|
|
1052
|
+
return out.join("");
|
|
1053
|
+
}
|
|
1054
|
+
function write(cfb, options) {
|
|
1055
|
+
var o = _write(cfb, options);
|
|
1056
|
+
switch (options && options.type || "buffer") {
|
|
1057
|
+
case "file":
|
|
1058
|
+
get_fs();
|
|
1059
|
+
fs.writeFileSync(options.filename, o);
|
|
1060
|
+
return o;
|
|
1061
|
+
case "binary": return typeof o == "string" ? o : a2s(o);
|
|
1062
|
+
case "base64": return Base64_encode(typeof o == "string" ? o : a2s(o));
|
|
1063
|
+
case "buffer": if (has_buf) return Buffer.isBuffer(o) ? o : Buffer_from(o);
|
|
1064
|
+
case "array": return typeof o == "string" ? s2a(o) : o;
|
|
1065
|
+
}
|
|
1066
|
+
return o;
|
|
1067
|
+
}
|
|
1068
|
+
var _zlib;
|
|
1069
|
+
function use_zlib(zlib) {
|
|
1070
|
+
try {
|
|
1071
|
+
var InflateRaw = zlib.InflateRaw;
|
|
1072
|
+
var InflRaw = new InflateRaw();
|
|
1073
|
+
InflRaw._processChunk(new Uint8Array([3, 0]), InflRaw._finishFlushFlag);
|
|
1074
|
+
if (InflRaw.bytesRead) _zlib = zlib;
|
|
1075
|
+
else throw new Error("zlib does not expose bytesRead");
|
|
1076
|
+
} catch (e) {
|
|
1077
|
+
console.error("cannot use native zlib: " + (e.message || e));
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
function _inflateRawSync(payload, usz) {
|
|
1081
|
+
if (!_zlib) return _inflate(payload, usz);
|
|
1082
|
+
var InflateRaw = _zlib.InflateRaw;
|
|
1083
|
+
var InflRaw = new InflateRaw();
|
|
1084
|
+
var out = InflRaw._processChunk(payload.slice(payload.l), InflRaw._finishFlushFlag);
|
|
1085
|
+
payload.l += InflRaw.bytesRead;
|
|
1086
|
+
return out;
|
|
1087
|
+
}
|
|
1088
|
+
function _deflateRawSync(payload) {
|
|
1089
|
+
return _zlib ? _zlib.deflateRawSync(payload) : _deflate(payload);
|
|
1090
|
+
}
|
|
1091
|
+
var CLEN_ORDER = [
|
|
1092
|
+
16,
|
|
1093
|
+
17,
|
|
1094
|
+
18,
|
|
1095
|
+
0,
|
|
1096
|
+
8,
|
|
1097
|
+
7,
|
|
1098
|
+
9,
|
|
1099
|
+
6,
|
|
1100
|
+
10,
|
|
1101
|
+
5,
|
|
1102
|
+
11,
|
|
1103
|
+
4,
|
|
1104
|
+
12,
|
|
1105
|
+
3,
|
|
1106
|
+
13,
|
|
1107
|
+
2,
|
|
1108
|
+
14,
|
|
1109
|
+
1,
|
|
1110
|
+
15
|
|
1111
|
+
];
|
|
1112
|
+
var LEN_LN = [
|
|
1113
|
+
3,
|
|
1114
|
+
4,
|
|
1115
|
+
5,
|
|
1116
|
+
6,
|
|
1117
|
+
7,
|
|
1118
|
+
8,
|
|
1119
|
+
9,
|
|
1120
|
+
10,
|
|
1121
|
+
11,
|
|
1122
|
+
13,
|
|
1123
|
+
15,
|
|
1124
|
+
17,
|
|
1125
|
+
19,
|
|
1126
|
+
23,
|
|
1127
|
+
27,
|
|
1128
|
+
31,
|
|
1129
|
+
35,
|
|
1130
|
+
43,
|
|
1131
|
+
51,
|
|
1132
|
+
59,
|
|
1133
|
+
67,
|
|
1134
|
+
83,
|
|
1135
|
+
99,
|
|
1136
|
+
115,
|
|
1137
|
+
131,
|
|
1138
|
+
163,
|
|
1139
|
+
195,
|
|
1140
|
+
227,
|
|
1141
|
+
258
|
|
1142
|
+
];
|
|
1143
|
+
var DST_LN = [
|
|
1144
|
+
1,
|
|
1145
|
+
2,
|
|
1146
|
+
3,
|
|
1147
|
+
4,
|
|
1148
|
+
5,
|
|
1149
|
+
7,
|
|
1150
|
+
9,
|
|
1151
|
+
13,
|
|
1152
|
+
17,
|
|
1153
|
+
25,
|
|
1154
|
+
33,
|
|
1155
|
+
49,
|
|
1156
|
+
65,
|
|
1157
|
+
97,
|
|
1158
|
+
129,
|
|
1159
|
+
193,
|
|
1160
|
+
257,
|
|
1161
|
+
385,
|
|
1162
|
+
513,
|
|
1163
|
+
769,
|
|
1164
|
+
1025,
|
|
1165
|
+
1537,
|
|
1166
|
+
2049,
|
|
1167
|
+
3073,
|
|
1168
|
+
4097,
|
|
1169
|
+
6145,
|
|
1170
|
+
8193,
|
|
1171
|
+
12289,
|
|
1172
|
+
16385,
|
|
1173
|
+
24577
|
|
1174
|
+
];
|
|
1175
|
+
function bit_swap_8(n) {
|
|
1176
|
+
var t = (n << 1 | n << 11) & 139536 | (n << 5 | n << 15) & 558144;
|
|
1177
|
+
return (t >> 16 | t >> 8 | t) & 255;
|
|
1178
|
+
}
|
|
1179
|
+
var use_typed_arrays = typeof Uint8Array !== "undefined";
|
|
1180
|
+
var bitswap8 = use_typed_arrays ? /* @__PURE__ */ new Uint8Array(256) : [];
|
|
1181
|
+
for (var q = 0; q < 256; ++q) bitswap8[q] = bit_swap_8(q);
|
|
1182
|
+
function bit_swap_n(n, b) {
|
|
1183
|
+
var rev = bitswap8[n & 255];
|
|
1184
|
+
if (b <= 8) return rev >>> 8 - b;
|
|
1185
|
+
rev = rev << 8 | bitswap8[n >> 8 & 255];
|
|
1186
|
+
if (b <= 16) return rev >>> 16 - b;
|
|
1187
|
+
rev = rev << 8 | bitswap8[n >> 16 & 255];
|
|
1188
|
+
return rev >>> 24 - b;
|
|
1189
|
+
}
|
|
1190
|
+
function read_bits_2(buf, bl) {
|
|
1191
|
+
var w = bl & 7, h = bl >>> 3;
|
|
1192
|
+
return (buf[h] | (w <= 6 ? 0 : buf[h + 1] << 8)) >>> w & 3;
|
|
1193
|
+
}
|
|
1194
|
+
function read_bits_3(buf, bl) {
|
|
1195
|
+
var w = bl & 7, h = bl >>> 3;
|
|
1196
|
+
return (buf[h] | (w <= 5 ? 0 : buf[h + 1] << 8)) >>> w & 7;
|
|
1197
|
+
}
|
|
1198
|
+
function read_bits_4(buf, bl) {
|
|
1199
|
+
var w = bl & 7, h = bl >>> 3;
|
|
1200
|
+
return (buf[h] | (w <= 4 ? 0 : buf[h + 1] << 8)) >>> w & 15;
|
|
1201
|
+
}
|
|
1202
|
+
function read_bits_5(buf, bl) {
|
|
1203
|
+
var w = bl & 7, h = bl >>> 3;
|
|
1204
|
+
return (buf[h] | (w <= 3 ? 0 : buf[h + 1] << 8)) >>> w & 31;
|
|
1205
|
+
}
|
|
1206
|
+
function read_bits_7(buf, bl) {
|
|
1207
|
+
var w = bl & 7, h = bl >>> 3;
|
|
1208
|
+
return (buf[h] | (w <= 1 ? 0 : buf[h + 1] << 8)) >>> w & 127;
|
|
1209
|
+
}
|
|
1210
|
+
function read_bits_n(buf, bl, n) {
|
|
1211
|
+
var w = bl & 7, h = bl >>> 3, f = (1 << n) - 1;
|
|
1212
|
+
var v = buf[h] >>> w;
|
|
1213
|
+
if (n < 8 - w) return v & f;
|
|
1214
|
+
v |= buf[h + 1] << 8 - w;
|
|
1215
|
+
if (n < 16 - w) return v & f;
|
|
1216
|
+
v |= buf[h + 2] << 16 - w;
|
|
1217
|
+
if (n < 24 - w) return v & f;
|
|
1218
|
+
v |= buf[h + 3] << 24 - w;
|
|
1219
|
+
return v & f;
|
|
1220
|
+
}
|
|
1221
|
+
function write_bits_3(buf, bl, v) {
|
|
1222
|
+
var w = bl & 7, h = bl >>> 3;
|
|
1223
|
+
if (w <= 5) buf[h] |= (v & 7) << w;
|
|
1224
|
+
else {
|
|
1225
|
+
buf[h] |= v << w & 255;
|
|
1226
|
+
buf[h + 1] = (v & 7) >> 8 - w;
|
|
1227
|
+
}
|
|
1228
|
+
return bl + 3;
|
|
1229
|
+
}
|
|
1230
|
+
function write_bits_1(buf, bl, v) {
|
|
1231
|
+
var w = bl & 7, h = bl >>> 3;
|
|
1232
|
+
v = (v & 1) << w;
|
|
1233
|
+
buf[h] |= v;
|
|
1234
|
+
return bl + 1;
|
|
1235
|
+
}
|
|
1236
|
+
function write_bits_8(buf, bl, v) {
|
|
1237
|
+
var w = bl & 7, h = bl >>> 3;
|
|
1238
|
+
v <<= w;
|
|
1239
|
+
buf[h] |= v & 255;
|
|
1240
|
+
v >>>= 8;
|
|
1241
|
+
buf[h + 1] = v;
|
|
1242
|
+
return bl + 8;
|
|
1243
|
+
}
|
|
1244
|
+
function write_bits_16(buf, bl, v) {
|
|
1245
|
+
var w = bl & 7, h = bl >>> 3;
|
|
1246
|
+
v <<= w;
|
|
1247
|
+
buf[h] |= v & 255;
|
|
1248
|
+
v >>>= 8;
|
|
1249
|
+
buf[h + 1] = v & 255;
|
|
1250
|
+
buf[h + 2] = v >>> 8;
|
|
1251
|
+
return bl + 16;
|
|
1252
|
+
}
|
|
1253
|
+
function realloc(b, sz) {
|
|
1254
|
+
var L = b.length, M = 2 * L > sz ? 2 * L : sz + 5, i = 0;
|
|
1255
|
+
if (L >= sz) return b;
|
|
1256
|
+
if (has_buf) {
|
|
1257
|
+
var o = new_unsafe_buf(M);
|
|
1258
|
+
if (b.copy) b.copy(o);
|
|
1259
|
+
else for (; i < b.length; ++i) o[i] = b[i];
|
|
1260
|
+
return o;
|
|
1261
|
+
} else if (use_typed_arrays) {
|
|
1262
|
+
var a = new Uint8Array(M);
|
|
1263
|
+
if (a.set) a.set(b);
|
|
1264
|
+
else for (; i < L; ++i) a[i] = b[i];
|
|
1265
|
+
return a;
|
|
1266
|
+
}
|
|
1267
|
+
b.length = M;
|
|
1268
|
+
return b;
|
|
1269
|
+
}
|
|
1270
|
+
function zero_fill_array(n) {
|
|
1271
|
+
var o = new Array(n);
|
|
1272
|
+
for (var i = 0; i < n; ++i) o[i] = 0;
|
|
1273
|
+
return o;
|
|
1274
|
+
}
|
|
1275
|
+
function build_tree(clens, cmap, MAX) {
|
|
1276
|
+
var maxlen = 1, w = 0, i = 0, j = 0, ccode = 0, L = clens.length;
|
|
1277
|
+
var bl_count = use_typed_arrays ? /* @__PURE__ */ new Uint16Array(32) : zero_fill_array(32);
|
|
1278
|
+
for (i = 0; i < 32; ++i) bl_count[i] = 0;
|
|
1279
|
+
for (i = L; i < MAX; ++i) clens[i] = 0;
|
|
1280
|
+
L = clens.length;
|
|
1281
|
+
var ctree = use_typed_arrays ? new Uint16Array(L) : zero_fill_array(L);
|
|
1282
|
+
for (i = 0; i < L; ++i) {
|
|
1283
|
+
bl_count[w = clens[i]]++;
|
|
1284
|
+
if (maxlen < w) maxlen = w;
|
|
1285
|
+
ctree[i] = 0;
|
|
1286
|
+
}
|
|
1287
|
+
bl_count[0] = 0;
|
|
1288
|
+
for (i = 1; i <= maxlen; ++i) bl_count[i + 16] = ccode = ccode + bl_count[i - 1] << 1;
|
|
1289
|
+
for (i = 0; i < L; ++i) {
|
|
1290
|
+
ccode = clens[i];
|
|
1291
|
+
if (ccode != 0) ctree[i] = bl_count[ccode + 16]++;
|
|
1292
|
+
}
|
|
1293
|
+
var cleni = 0;
|
|
1294
|
+
for (i = 0; i < L; ++i) {
|
|
1295
|
+
cleni = clens[i];
|
|
1296
|
+
if (cleni != 0) {
|
|
1297
|
+
ccode = bit_swap_n(ctree[i], maxlen) >> maxlen - cleni;
|
|
1298
|
+
for (j = (1 << maxlen + 4 - cleni) - 1; j >= 0; --j) cmap[ccode | j << cleni] = cleni & 15 | i << 4;
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
return maxlen;
|
|
1302
|
+
}
|
|
1303
|
+
var fix_lmap = use_typed_arrays ? /* @__PURE__ */ new Uint16Array(512) : zero_fill_array(512);
|
|
1304
|
+
var fix_dmap = use_typed_arrays ? /* @__PURE__ */ new Uint16Array(32) : zero_fill_array(32);
|
|
1305
|
+
if (!use_typed_arrays) {
|
|
1306
|
+
for (var i = 0; i < 512; ++i) fix_lmap[i] = 0;
|
|
1307
|
+
for (i = 0; i < 32; ++i) fix_dmap[i] = 0;
|
|
1308
|
+
}
|
|
1309
|
+
(function() {
|
|
1310
|
+
var dlens = [];
|
|
1311
|
+
var i = 0;
|
|
1312
|
+
for (; i < 32; i++) dlens.push(5);
|
|
1313
|
+
build_tree(dlens, fix_dmap, 32);
|
|
1314
|
+
var clens = [];
|
|
1315
|
+
i = 0;
|
|
1316
|
+
for (; i <= 143; i++) clens.push(8);
|
|
1317
|
+
for (; i <= 255; i++) clens.push(9);
|
|
1318
|
+
for (; i <= 279; i++) clens.push(7);
|
|
1319
|
+
for (; i <= 287; i++) clens.push(8);
|
|
1320
|
+
build_tree(clens, fix_lmap, 288);
|
|
1321
|
+
})();
|
|
1322
|
+
var _deflateRaw = (function _deflateRawIIFE() {
|
|
1323
|
+
var DST_LN_RE = use_typed_arrays ? /* @__PURE__ */ new Uint8Array(32768) : [];
|
|
1324
|
+
var j = 0, k = 0;
|
|
1325
|
+
for (; j < DST_LN.length - 1; ++j) for (; k < DST_LN[j + 1]; ++k) DST_LN_RE[k] = j;
|
|
1326
|
+
for (; k < 32768; ++k) DST_LN_RE[k] = 29;
|
|
1327
|
+
var LEN_LN_RE = use_typed_arrays ? /* @__PURE__ */ new Uint8Array(259) : [];
|
|
1328
|
+
for (j = 0, k = 0; j < LEN_LN.length - 1; ++j) for (; k < LEN_LN[j + 1]; ++k) LEN_LN_RE[k] = j;
|
|
1329
|
+
function write_stored(data, out) {
|
|
1330
|
+
var boff = 0;
|
|
1331
|
+
while (boff < data.length) {
|
|
1332
|
+
var L = Math.min(65535, data.length - boff);
|
|
1333
|
+
var h = boff + L == data.length;
|
|
1334
|
+
out.write_shift(1, +h);
|
|
1335
|
+
out.write_shift(2, L);
|
|
1336
|
+
out.write_shift(2, ~L & 65535);
|
|
1337
|
+
while (L-- > 0) out[out.l++] = data[boff++];
|
|
1338
|
+
}
|
|
1339
|
+
return out.l;
|
|
1340
|
+
}
|
|
1341
|
+
function write_huff_fixed(data, out) {
|
|
1342
|
+
var bl = 0;
|
|
1343
|
+
var boff = 0;
|
|
1344
|
+
var addrs = use_typed_arrays ? /* @__PURE__ */ new Uint16Array(32768) : [];
|
|
1345
|
+
while (boff < data.length) {
|
|
1346
|
+
var L = Math.min(65535, data.length - boff);
|
|
1347
|
+
if (L < 10) {
|
|
1348
|
+
bl = write_bits_3(out, bl, +!!(boff + L == data.length));
|
|
1349
|
+
if (bl & 7) bl += 8 - (bl & 7);
|
|
1350
|
+
out.l = bl / 8 | 0;
|
|
1351
|
+
out.write_shift(2, L);
|
|
1352
|
+
out.write_shift(2, ~L & 65535);
|
|
1353
|
+
while (L-- > 0) out[out.l++] = data[boff++];
|
|
1354
|
+
bl = out.l * 8;
|
|
1355
|
+
continue;
|
|
1356
|
+
}
|
|
1357
|
+
bl = write_bits_3(out, bl, +!!(boff + L == data.length) + 2);
|
|
1358
|
+
var hash = 0;
|
|
1359
|
+
while (L-- > 0) {
|
|
1360
|
+
var d = data[boff];
|
|
1361
|
+
hash = (hash << 5 ^ d) & 32767;
|
|
1362
|
+
var match = -1, mlen = 0;
|
|
1363
|
+
if (match = addrs[hash]) {
|
|
1364
|
+
match |= boff & -32768;
|
|
1365
|
+
if (match > boff) match -= 32768;
|
|
1366
|
+
if (match < boff) while (data[match + mlen] == data[boff + mlen] && mlen < 250) ++mlen;
|
|
1367
|
+
}
|
|
1368
|
+
if (mlen > 2) {
|
|
1369
|
+
d = LEN_LN_RE[mlen];
|
|
1370
|
+
if (d <= 22) bl = write_bits_8(out, bl, bitswap8[d + 1] >> 1) - 1;
|
|
1371
|
+
else {
|
|
1372
|
+
write_bits_8(out, bl, 3);
|
|
1373
|
+
bl += 5;
|
|
1374
|
+
write_bits_8(out, bl, bitswap8[d - 23] >> 5);
|
|
1375
|
+
bl += 3;
|
|
1376
|
+
}
|
|
1377
|
+
var len_eb = d < 8 ? 0 : d - 4 >> 2;
|
|
1378
|
+
if (len_eb > 0) {
|
|
1379
|
+
write_bits_16(out, bl, mlen - LEN_LN[d]);
|
|
1380
|
+
bl += len_eb;
|
|
1381
|
+
}
|
|
1382
|
+
d = DST_LN_RE[boff - match];
|
|
1383
|
+
bl = write_bits_8(out, bl, bitswap8[d] >> 3);
|
|
1384
|
+
bl -= 3;
|
|
1385
|
+
var dst_eb = d < 4 ? 0 : d - 2 >> 1;
|
|
1386
|
+
if (dst_eb > 0) {
|
|
1387
|
+
write_bits_16(out, bl, boff - match - DST_LN[d]);
|
|
1388
|
+
bl += dst_eb;
|
|
1389
|
+
}
|
|
1390
|
+
for (var q = 0; q < mlen; ++q) {
|
|
1391
|
+
addrs[hash] = boff & 32767;
|
|
1392
|
+
hash = (hash << 5 ^ data[boff]) & 32767;
|
|
1393
|
+
++boff;
|
|
1394
|
+
}
|
|
1395
|
+
L -= mlen - 1;
|
|
1396
|
+
} else {
|
|
1397
|
+
if (d <= 143) d = d + 48;
|
|
1398
|
+
else bl = write_bits_1(out, bl, 1);
|
|
1399
|
+
bl = write_bits_8(out, bl, bitswap8[d]);
|
|
1400
|
+
addrs[hash] = boff & 32767;
|
|
1401
|
+
++boff;
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1404
|
+
bl = write_bits_8(out, bl, 0) - 1;
|
|
1405
|
+
}
|
|
1406
|
+
out.l = (bl + 7) / 8 | 0;
|
|
1407
|
+
return out.l;
|
|
1408
|
+
}
|
|
1409
|
+
return function _deflateRaw(data, out) {
|
|
1410
|
+
if (data.length < 8) return write_stored(data, out);
|
|
1411
|
+
return write_huff_fixed(data, out);
|
|
1412
|
+
};
|
|
1413
|
+
})();
|
|
1414
|
+
function _deflate(data) {
|
|
1415
|
+
var buf = new_buf(50 + Math.floor(data.length * 1.1));
|
|
1416
|
+
var off = _deflateRaw(data, buf);
|
|
1417
|
+
return buf.slice(0, off);
|
|
1418
|
+
}
|
|
1419
|
+
var dyn_lmap = use_typed_arrays ? /* @__PURE__ */ new Uint16Array(32768) : zero_fill_array(32768);
|
|
1420
|
+
var dyn_dmap = use_typed_arrays ? /* @__PURE__ */ new Uint16Array(32768) : zero_fill_array(32768);
|
|
1421
|
+
var dyn_cmap = use_typed_arrays ? /* @__PURE__ */ new Uint16Array(128) : zero_fill_array(128);
|
|
1422
|
+
var dyn_len_1 = 1, dyn_len_2 = 1;
|
|
1423
|
+
function dyn(data, boff) {
|
|
1424
|
+
var _HLIT = read_bits_5(data, boff) + 257;
|
|
1425
|
+
boff += 5;
|
|
1426
|
+
var _HDIST = read_bits_5(data, boff) + 1;
|
|
1427
|
+
boff += 5;
|
|
1428
|
+
var _HCLEN = read_bits_4(data, boff) + 4;
|
|
1429
|
+
boff += 4;
|
|
1430
|
+
var w = 0;
|
|
1431
|
+
var clens = use_typed_arrays ? /* @__PURE__ */ new Uint8Array(19) : zero_fill_array(19);
|
|
1432
|
+
var ctree = [
|
|
1433
|
+
0,
|
|
1434
|
+
0,
|
|
1435
|
+
0,
|
|
1436
|
+
0,
|
|
1437
|
+
0,
|
|
1438
|
+
0,
|
|
1439
|
+
0,
|
|
1440
|
+
0,
|
|
1441
|
+
0,
|
|
1442
|
+
0,
|
|
1443
|
+
0,
|
|
1444
|
+
0,
|
|
1445
|
+
0,
|
|
1446
|
+
0,
|
|
1447
|
+
0,
|
|
1448
|
+
0,
|
|
1449
|
+
0,
|
|
1450
|
+
0,
|
|
1451
|
+
0
|
|
1452
|
+
];
|
|
1453
|
+
var maxlen = 1;
|
|
1454
|
+
var bl_count = use_typed_arrays ? /* @__PURE__ */ new Uint8Array(8) : zero_fill_array(8);
|
|
1455
|
+
var next_code = use_typed_arrays ? /* @__PURE__ */ new Uint8Array(8) : zero_fill_array(8);
|
|
1456
|
+
var L = clens.length;
|
|
1457
|
+
for (var i = 0; i < _HCLEN; ++i) {
|
|
1458
|
+
clens[CLEN_ORDER[i]] = w = read_bits_3(data, boff);
|
|
1459
|
+
if (maxlen < w) maxlen = w;
|
|
1460
|
+
bl_count[w]++;
|
|
1461
|
+
boff += 3;
|
|
1462
|
+
}
|
|
1463
|
+
var ccode = 0;
|
|
1464
|
+
bl_count[0] = 0;
|
|
1465
|
+
for (i = 1; i <= maxlen; ++i) next_code[i] = ccode = ccode + bl_count[i - 1] << 1;
|
|
1466
|
+
for (i = 0; i < L; ++i) if ((ccode = clens[i]) != 0) ctree[i] = next_code[ccode]++;
|
|
1467
|
+
var cleni = 0;
|
|
1468
|
+
for (i = 0; i < L; ++i) {
|
|
1469
|
+
cleni = clens[i];
|
|
1470
|
+
if (cleni != 0) {
|
|
1471
|
+
ccode = bitswap8[ctree[i]] >> 8 - cleni;
|
|
1472
|
+
for (var j = (1 << 7 - cleni) - 1; j >= 0; --j) dyn_cmap[ccode | j << cleni] = cleni & 7 | i << 3;
|
|
1473
|
+
}
|
|
1474
|
+
}
|
|
1475
|
+
var hcodes = [];
|
|
1476
|
+
maxlen = 1;
|
|
1477
|
+
for (; hcodes.length < _HLIT + _HDIST;) {
|
|
1478
|
+
ccode = dyn_cmap[read_bits_7(data, boff)];
|
|
1479
|
+
boff += ccode & 7;
|
|
1480
|
+
switch (ccode >>>= 3) {
|
|
1481
|
+
case 16:
|
|
1482
|
+
w = 3 + read_bits_2(data, boff);
|
|
1483
|
+
boff += 2;
|
|
1484
|
+
ccode = hcodes[hcodes.length - 1];
|
|
1485
|
+
while (w-- > 0) hcodes.push(ccode);
|
|
1486
|
+
break;
|
|
1487
|
+
case 17:
|
|
1488
|
+
w = 3 + read_bits_3(data, boff);
|
|
1489
|
+
boff += 3;
|
|
1490
|
+
while (w-- > 0) hcodes.push(0);
|
|
1491
|
+
break;
|
|
1492
|
+
case 18:
|
|
1493
|
+
w = 11 + read_bits_7(data, boff);
|
|
1494
|
+
boff += 7;
|
|
1495
|
+
while (w-- > 0) hcodes.push(0);
|
|
1496
|
+
break;
|
|
1497
|
+
default:
|
|
1498
|
+
hcodes.push(ccode);
|
|
1499
|
+
if (maxlen < ccode) maxlen = ccode;
|
|
1500
|
+
}
|
|
1501
|
+
}
|
|
1502
|
+
var h1 = hcodes.slice(0, _HLIT), h2 = hcodes.slice(_HLIT);
|
|
1503
|
+
for (i = _HLIT; i < 286; ++i) h1[i] = 0;
|
|
1504
|
+
for (i = _HDIST; i < 30; ++i) h2[i] = 0;
|
|
1505
|
+
dyn_len_1 = build_tree(h1, dyn_lmap, 286);
|
|
1506
|
+
dyn_len_2 = build_tree(h2, dyn_dmap, 30);
|
|
1507
|
+
return boff;
|
|
1508
|
+
}
|
|
1509
|
+
function inflate(data, usz) {
|
|
1510
|
+
if (data[0] == 3 && !(data[1] & 3)) return [new_raw_buf(usz), 2];
|
|
1511
|
+
var boff = 0;
|
|
1512
|
+
var header = 0;
|
|
1513
|
+
var outbuf = new_unsafe_buf(usz ? usz : 1 << 18);
|
|
1514
|
+
var woff = 0;
|
|
1515
|
+
var OL = outbuf.length >>> 0;
|
|
1516
|
+
var max_len_1 = 0, max_len_2 = 0;
|
|
1517
|
+
while ((header & 1) == 0) {
|
|
1518
|
+
header = read_bits_3(data, boff);
|
|
1519
|
+
boff += 3;
|
|
1520
|
+
if (header >>> 1 == 0) {
|
|
1521
|
+
if (boff & 7) boff += 8 - (boff & 7);
|
|
1522
|
+
var sz = data[boff >>> 3] | data[(boff >>> 3) + 1] << 8;
|
|
1523
|
+
boff += 32;
|
|
1524
|
+
if (sz > 0) {
|
|
1525
|
+
if (!usz && OL < woff + sz) {
|
|
1526
|
+
outbuf = realloc(outbuf, woff + sz);
|
|
1527
|
+
OL = outbuf.length;
|
|
1528
|
+
}
|
|
1529
|
+
while (sz-- > 0) {
|
|
1530
|
+
outbuf[woff++] = data[boff >>> 3];
|
|
1531
|
+
boff += 8;
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
continue;
|
|
1535
|
+
} else if (header >> 1 == 1) {
|
|
1536
|
+
max_len_1 = 9;
|
|
1537
|
+
max_len_2 = 5;
|
|
1538
|
+
} else {
|
|
1539
|
+
boff = dyn(data, boff);
|
|
1540
|
+
max_len_1 = dyn_len_1;
|
|
1541
|
+
max_len_2 = dyn_len_2;
|
|
1542
|
+
}
|
|
1543
|
+
for (;;) {
|
|
1544
|
+
if (!usz && OL < woff + 32767) {
|
|
1545
|
+
outbuf = realloc(outbuf, woff + 32767);
|
|
1546
|
+
OL = outbuf.length;
|
|
1547
|
+
}
|
|
1548
|
+
var bits = read_bits_n(data, boff, max_len_1);
|
|
1549
|
+
var code = header >>> 1 == 1 ? fix_lmap[bits] : dyn_lmap[bits];
|
|
1550
|
+
boff += code & 15;
|
|
1551
|
+
code >>>= 4;
|
|
1552
|
+
if ((code >>> 8 & 255) === 0) outbuf[woff++] = code;
|
|
1553
|
+
else if (code == 256) break;
|
|
1554
|
+
else {
|
|
1555
|
+
code -= 257;
|
|
1556
|
+
var len_eb = code < 8 ? 0 : code - 4 >> 2;
|
|
1557
|
+
if (len_eb > 5) len_eb = 0;
|
|
1558
|
+
var tgt = woff + LEN_LN[code];
|
|
1559
|
+
if (len_eb > 0) {
|
|
1560
|
+
tgt += read_bits_n(data, boff, len_eb);
|
|
1561
|
+
boff += len_eb;
|
|
1562
|
+
}
|
|
1563
|
+
bits = read_bits_n(data, boff, max_len_2);
|
|
1564
|
+
code = header >>> 1 == 1 ? fix_dmap[bits] : dyn_dmap[bits];
|
|
1565
|
+
boff += code & 15;
|
|
1566
|
+
code >>>= 4;
|
|
1567
|
+
var dst_eb = code < 4 ? 0 : code - 2 >> 1;
|
|
1568
|
+
var dst = DST_LN[code];
|
|
1569
|
+
if (dst_eb > 0) {
|
|
1570
|
+
dst += read_bits_n(data, boff, dst_eb);
|
|
1571
|
+
boff += dst_eb;
|
|
1572
|
+
}
|
|
1573
|
+
if (!usz && OL < tgt) {
|
|
1574
|
+
outbuf = realloc(outbuf, tgt + 100);
|
|
1575
|
+
OL = outbuf.length;
|
|
1576
|
+
}
|
|
1577
|
+
while (woff < tgt) {
|
|
1578
|
+
outbuf[woff] = outbuf[woff - dst];
|
|
1579
|
+
++woff;
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
}
|
|
1584
|
+
if (usz) return [outbuf, boff + 7 >>> 3];
|
|
1585
|
+
return [outbuf.slice(0, woff), boff + 7 >>> 3];
|
|
1586
|
+
}
|
|
1587
|
+
function _inflate(payload, usz) {
|
|
1588
|
+
var out = inflate(payload.slice(payload.l || 0), usz);
|
|
1589
|
+
payload.l += out[1];
|
|
1590
|
+
return out[0];
|
|
1591
|
+
}
|
|
1592
|
+
function warn_or_throw(wrn, msg) {
|
|
1593
|
+
if (wrn) {
|
|
1594
|
+
if (typeof console !== "undefined") console.error(msg);
|
|
1595
|
+
} else throw new Error(msg);
|
|
1596
|
+
}
|
|
1597
|
+
function parse_zip(file, options) {
|
|
1598
|
+
var blob = file;
|
|
1599
|
+
prep_blob(blob, 0);
|
|
1600
|
+
var o = {
|
|
1601
|
+
FileIndex: [],
|
|
1602
|
+
FullPaths: []
|
|
1603
|
+
};
|
|
1604
|
+
init_cfb(o, { root: options.root });
|
|
1605
|
+
var i = blob.length - 4;
|
|
1606
|
+
while ((blob[i] != 80 || blob[i + 1] != 75 || blob[i + 2] != 5 || blob[i + 3] != 6) && i >= 0) --i;
|
|
1607
|
+
blob.l = i + 4;
|
|
1608
|
+
blob.l += 4;
|
|
1609
|
+
var fcnt = blob.read_shift(2);
|
|
1610
|
+
blob.l += 6;
|
|
1611
|
+
blob.l = blob.read_shift(4);
|
|
1612
|
+
for (i = 0; i < fcnt; ++i) {
|
|
1613
|
+
blob.l += 20;
|
|
1614
|
+
var csz = blob.read_shift(4);
|
|
1615
|
+
var usz = blob.read_shift(4);
|
|
1616
|
+
var namelen = blob.read_shift(2);
|
|
1617
|
+
var efsz = blob.read_shift(2);
|
|
1618
|
+
var fcsz = blob.read_shift(2);
|
|
1619
|
+
blob.l += 8;
|
|
1620
|
+
var offset = blob.read_shift(4);
|
|
1621
|
+
var EF = parse_extra_field(blob.slice(blob.l + namelen, blob.l + namelen + efsz));
|
|
1622
|
+
blob.l += namelen + efsz + fcsz;
|
|
1623
|
+
var L = blob.l;
|
|
1624
|
+
blob.l = offset + 4;
|
|
1625
|
+
parse_local_file(blob, csz, usz, o, EF);
|
|
1626
|
+
blob.l = L;
|
|
1627
|
+
}
|
|
1628
|
+
return o;
|
|
1629
|
+
}
|
|
1630
|
+
function parse_local_file(blob, csz, usz, o, EF) {
|
|
1631
|
+
blob.l += 2;
|
|
1632
|
+
var flags = blob.read_shift(2);
|
|
1633
|
+
var meth = blob.read_shift(2);
|
|
1634
|
+
var date = parse_dos_date(blob);
|
|
1635
|
+
if (flags & 8257) throw new Error("Unsupported ZIP encryption");
|
|
1636
|
+
var crc32 = blob.read_shift(4);
|
|
1637
|
+
var _csz = blob.read_shift(4);
|
|
1638
|
+
var _usz = blob.read_shift(4);
|
|
1639
|
+
var namelen = blob.read_shift(2);
|
|
1640
|
+
var efsz = blob.read_shift(2);
|
|
1641
|
+
var name = "";
|
|
1642
|
+
for (var i = 0; i < namelen; ++i) name += String.fromCharCode(blob[blob.l++]);
|
|
1643
|
+
if (efsz) {
|
|
1644
|
+
var ef = parse_extra_field(blob.slice(blob.l, blob.l + efsz));
|
|
1645
|
+
if ((ef[21589] || {}).mt) date = ef[21589].mt;
|
|
1646
|
+
if (((EF || {})[21589] || {}).mt) date = EF[21589].mt;
|
|
1647
|
+
}
|
|
1648
|
+
blob.l += efsz;
|
|
1649
|
+
var data = blob.slice(blob.l, blob.l + _csz);
|
|
1650
|
+
switch (meth) {
|
|
1651
|
+
case 8:
|
|
1652
|
+
data = _inflateRawSync(blob, _usz);
|
|
1653
|
+
break;
|
|
1654
|
+
case 0: break;
|
|
1655
|
+
default: throw new Error("Unsupported ZIP Compression method " + meth);
|
|
1656
|
+
}
|
|
1657
|
+
var wrn = false;
|
|
1658
|
+
if (flags & 8) {
|
|
1659
|
+
crc32 = blob.read_shift(4);
|
|
1660
|
+
if (crc32 == 134695760) {
|
|
1661
|
+
crc32 = blob.read_shift(4);
|
|
1662
|
+
wrn = true;
|
|
1663
|
+
}
|
|
1664
|
+
_csz = blob.read_shift(4);
|
|
1665
|
+
_usz = blob.read_shift(4);
|
|
1666
|
+
}
|
|
1667
|
+
if (_csz != csz) warn_or_throw(wrn, "Bad compressed size: " + csz + " != " + _csz);
|
|
1668
|
+
if (_usz != usz) warn_or_throw(wrn, "Bad uncompressed size: " + usz + " != " + _usz);
|
|
1669
|
+
var _crc32 = CRC32.buf(data, 0);
|
|
1670
|
+
if (crc32 >> 0 != _crc32 >> 0) warn_or_throw(wrn, "Bad CRC32 checksum: " + crc32 + " != " + _crc32);
|
|
1671
|
+
cfb_add(o, name, data, {
|
|
1672
|
+
unsafe: true,
|
|
1673
|
+
mt: date
|
|
1674
|
+
});
|
|
1675
|
+
}
|
|
1676
|
+
function write_zip(cfb, options) {
|
|
1677
|
+
var _opts = options || {};
|
|
1678
|
+
var out = [], cdirs = [];
|
|
1679
|
+
var o = new_buf(1);
|
|
1680
|
+
var method = _opts.compression ? 8 : 0, flags = 0;
|
|
1681
|
+
var i = 0, j = 0;
|
|
1682
|
+
var start_cd = 0, fcnt = 0;
|
|
1683
|
+
var root = cfb.FullPaths[0], fp = root, fi = cfb.FileIndex[0];
|
|
1684
|
+
var crcs = [];
|
|
1685
|
+
var sz_cd = 0;
|
|
1686
|
+
for (i = 1; i < cfb.FullPaths.length; ++i) {
|
|
1687
|
+
fp = cfb.FullPaths[i].slice(root.length);
|
|
1688
|
+
fi = cfb.FileIndex[i];
|
|
1689
|
+
if (!fi.size || !fi.content || fp == "Sh33tJ5") continue;
|
|
1690
|
+
var start = start_cd;
|
|
1691
|
+
var namebuf = new_buf(fp.length);
|
|
1692
|
+
for (j = 0; j < fp.length; ++j) namebuf.write_shift(1, fp.charCodeAt(j) & 127);
|
|
1693
|
+
namebuf = namebuf.slice(0, namebuf.l);
|
|
1694
|
+
crcs[fcnt] = CRC32.buf(fi.content, 0);
|
|
1695
|
+
var outbuf = fi.content;
|
|
1696
|
+
if (method == 8) outbuf = _deflateRawSync(outbuf);
|
|
1697
|
+
o = new_buf(30);
|
|
1698
|
+
o.write_shift(4, 67324752);
|
|
1699
|
+
o.write_shift(2, 20);
|
|
1700
|
+
o.write_shift(2, flags);
|
|
1701
|
+
o.write_shift(2, method);
|
|
1702
|
+
if (fi.mt) write_dos_date(o, fi.mt);
|
|
1703
|
+
else o.write_shift(4, 0);
|
|
1704
|
+
o.write_shift(-4, flags & 8 ? 0 : crcs[fcnt]);
|
|
1705
|
+
o.write_shift(4, flags & 8 ? 0 : outbuf.length);
|
|
1706
|
+
o.write_shift(4, flags & 8 ? 0 : fi.content.length);
|
|
1707
|
+
o.write_shift(2, namebuf.length);
|
|
1708
|
+
o.write_shift(2, 0);
|
|
1709
|
+
start_cd += o.length;
|
|
1710
|
+
out.push(o);
|
|
1711
|
+
start_cd += namebuf.length;
|
|
1712
|
+
out.push(namebuf);
|
|
1713
|
+
start_cd += outbuf.length;
|
|
1714
|
+
out.push(outbuf);
|
|
1715
|
+
if (flags & 8) {
|
|
1716
|
+
o = new_buf(12);
|
|
1717
|
+
o.write_shift(-4, crcs[fcnt]);
|
|
1718
|
+
o.write_shift(4, outbuf.length);
|
|
1719
|
+
o.write_shift(4, fi.content.length);
|
|
1720
|
+
start_cd += o.l;
|
|
1721
|
+
out.push(o);
|
|
1722
|
+
}
|
|
1723
|
+
o = new_buf(46);
|
|
1724
|
+
o.write_shift(4, 33639248);
|
|
1725
|
+
o.write_shift(2, 0);
|
|
1726
|
+
o.write_shift(2, 20);
|
|
1727
|
+
o.write_shift(2, flags);
|
|
1728
|
+
o.write_shift(2, method);
|
|
1729
|
+
o.write_shift(4, 0);
|
|
1730
|
+
o.write_shift(-4, crcs[fcnt]);
|
|
1731
|
+
o.write_shift(4, outbuf.length);
|
|
1732
|
+
o.write_shift(4, fi.content.length);
|
|
1733
|
+
o.write_shift(2, namebuf.length);
|
|
1734
|
+
o.write_shift(2, 0);
|
|
1735
|
+
o.write_shift(2, 0);
|
|
1736
|
+
o.write_shift(2, 0);
|
|
1737
|
+
o.write_shift(2, 0);
|
|
1738
|
+
o.write_shift(4, 0);
|
|
1739
|
+
o.write_shift(4, start);
|
|
1740
|
+
sz_cd += o.l;
|
|
1741
|
+
cdirs.push(o);
|
|
1742
|
+
sz_cd += namebuf.length;
|
|
1743
|
+
cdirs.push(namebuf);
|
|
1744
|
+
++fcnt;
|
|
1745
|
+
}
|
|
1746
|
+
o = new_buf(22);
|
|
1747
|
+
o.write_shift(4, 101010256);
|
|
1748
|
+
o.write_shift(2, 0);
|
|
1749
|
+
o.write_shift(2, 0);
|
|
1750
|
+
o.write_shift(2, fcnt);
|
|
1751
|
+
o.write_shift(2, fcnt);
|
|
1752
|
+
o.write_shift(4, sz_cd);
|
|
1753
|
+
o.write_shift(4, start_cd);
|
|
1754
|
+
o.write_shift(2, 0);
|
|
1755
|
+
return bconcat([
|
|
1756
|
+
bconcat(out),
|
|
1757
|
+
bconcat(cdirs),
|
|
1758
|
+
o
|
|
1759
|
+
]);
|
|
1760
|
+
}
|
|
1761
|
+
var ContentTypeMap = {
|
|
1762
|
+
"htm": "text/html",
|
|
1763
|
+
"xml": "text/xml",
|
|
1764
|
+
"gif": "image/gif",
|
|
1765
|
+
"jpg": "image/jpeg",
|
|
1766
|
+
"png": "image/png",
|
|
1767
|
+
"mso": "application/x-mso",
|
|
1768
|
+
"thmx": "application/vnd.ms-officetheme",
|
|
1769
|
+
"sh33tj5": "application/octet-stream"
|
|
1770
|
+
};
|
|
1771
|
+
function get_content_type(fi, fp) {
|
|
1772
|
+
if (fi.ctype) return fi.ctype;
|
|
1773
|
+
var ext = fi.name || "", m = ext.match(/\.([^\.]+)$/);
|
|
1774
|
+
if (m && ContentTypeMap[m[1]]) return ContentTypeMap[m[1]];
|
|
1775
|
+
if (fp) {
|
|
1776
|
+
m = (ext = fp).match(/[\.\\]([^\.\\])+$/);
|
|
1777
|
+
if (m && ContentTypeMap[m[1]]) return ContentTypeMap[m[1]];
|
|
1778
|
+
}
|
|
1779
|
+
return "application/octet-stream";
|
|
1780
|
+
}
|
|
1781
|
+
function write_base64_76(bstr) {
|
|
1782
|
+
var data = Base64_encode(bstr);
|
|
1783
|
+
var o = [];
|
|
1784
|
+
for (var i = 0; i < data.length; i += 76) o.push(data.slice(i, i + 76));
|
|
1785
|
+
return o.join("\r\n") + "\r\n";
|
|
1786
|
+
}
|
|
1787
|
+
function write_quoted_printable(text) {
|
|
1788
|
+
var encoded = text.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7E-\xFF=]/g, function(c) {
|
|
1789
|
+
var w = c.charCodeAt(0).toString(16).toUpperCase();
|
|
1790
|
+
return "=" + (w.length == 1 ? "0" + w : w);
|
|
1791
|
+
});
|
|
1792
|
+
encoded = encoded.replace(/ $/gm, "=20").replace(/\t$/gm, "=09");
|
|
1793
|
+
if (encoded.charAt(0) == "\n") encoded = "=0D" + encoded.slice(1);
|
|
1794
|
+
encoded = encoded.replace(/\r(?!\n)/gm, "=0D").replace(/\n\n/gm, "\n=0A").replace(/([^\r\n])\n/gm, "$1=0A");
|
|
1795
|
+
var o = [], split = encoded.split("\r\n");
|
|
1796
|
+
for (var si = 0; si < split.length; ++si) {
|
|
1797
|
+
var str = split[si];
|
|
1798
|
+
if (str.length == 0) {
|
|
1799
|
+
o.push("");
|
|
1800
|
+
continue;
|
|
1801
|
+
}
|
|
1802
|
+
for (var i = 0; i < str.length;) {
|
|
1803
|
+
var end = 76;
|
|
1804
|
+
var tmp = str.slice(i, i + end);
|
|
1805
|
+
if (tmp.charAt(end - 1) == "=") end--;
|
|
1806
|
+
else if (tmp.charAt(end - 2) == "=") end -= 2;
|
|
1807
|
+
else if (tmp.charAt(end - 3) == "=") end -= 3;
|
|
1808
|
+
tmp = str.slice(i, i + end);
|
|
1809
|
+
i += end;
|
|
1810
|
+
if (i < str.length) tmp += "=";
|
|
1811
|
+
o.push(tmp);
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
return o.join("\r\n");
|
|
1815
|
+
}
|
|
1816
|
+
function parse_quoted_printable(data) {
|
|
1817
|
+
var o = [];
|
|
1818
|
+
for (var di = 0; di < data.length; ++di) {
|
|
1819
|
+
var line = data[di];
|
|
1820
|
+
while (di <= data.length && line.charAt(line.length - 1) == "=") line = line.slice(0, line.length - 1) + data[++di];
|
|
1821
|
+
o.push(line);
|
|
1822
|
+
}
|
|
1823
|
+
for (var oi = 0; oi < o.length; ++oi) o[oi] = o[oi].replace(/[=][0-9A-Fa-f]{2}/g, function($$) {
|
|
1824
|
+
return String.fromCharCode(parseInt($$.slice(1), 16));
|
|
1825
|
+
});
|
|
1826
|
+
return s2a(o.join("\r\n"));
|
|
1827
|
+
}
|
|
1828
|
+
function parse_mime(cfb, data, root) {
|
|
1829
|
+
var fname = "", cte = "", ctype = "", fdata;
|
|
1830
|
+
var di = 0;
|
|
1831
|
+
for (; di < 10; ++di) {
|
|
1832
|
+
var line = data[di];
|
|
1833
|
+
if (!line || line.match(/^\s*$/)) break;
|
|
1834
|
+
var m = line.match(/^(.*?):\s*([^\s].*)$/);
|
|
1835
|
+
if (m) switch (m[1].toLowerCase()) {
|
|
1836
|
+
case "content-location":
|
|
1837
|
+
fname = m[2].trim();
|
|
1838
|
+
break;
|
|
1839
|
+
case "content-type":
|
|
1840
|
+
ctype = m[2].trim();
|
|
1841
|
+
break;
|
|
1842
|
+
case "content-transfer-encoding":
|
|
1843
|
+
cte = m[2].trim();
|
|
1844
|
+
break;
|
|
1845
|
+
}
|
|
1846
|
+
}
|
|
1847
|
+
++di;
|
|
1848
|
+
switch (cte.toLowerCase()) {
|
|
1849
|
+
case "base64":
|
|
1850
|
+
fdata = s2a(Base64_decode(data.slice(di).join("")));
|
|
1851
|
+
break;
|
|
1852
|
+
case "quoted-printable":
|
|
1853
|
+
fdata = parse_quoted_printable(data.slice(di));
|
|
1854
|
+
break;
|
|
1855
|
+
default: throw new Error("Unsupported Content-Transfer-Encoding " + cte);
|
|
1856
|
+
}
|
|
1857
|
+
var file = cfb_add(cfb, fname.slice(root.length), fdata, { unsafe: true });
|
|
1858
|
+
if (ctype) file.ctype = ctype;
|
|
1859
|
+
}
|
|
1860
|
+
function parse_mad(file, options) {
|
|
1861
|
+
if (a2s(file.slice(0, 13)).toLowerCase() != "mime-version:") throw new Error("Unsupported MAD header");
|
|
1862
|
+
var root = options && options.root || "";
|
|
1863
|
+
var data = (has_buf && Buffer.isBuffer(file) ? file.toString("binary") : a2s(file)).split("\r\n");
|
|
1864
|
+
var di = 0, row = "";
|
|
1865
|
+
for (di = 0; di < data.length; ++di) {
|
|
1866
|
+
row = data[di];
|
|
1867
|
+
if (!/^Content-Location:/i.test(row)) continue;
|
|
1868
|
+
row = row.slice(row.indexOf("file"));
|
|
1869
|
+
if (!root) root = row.slice(0, row.lastIndexOf("/") + 1);
|
|
1870
|
+
if (row.slice(0, root.length) == root) continue;
|
|
1871
|
+
while (root.length > 0) {
|
|
1872
|
+
root = root.slice(0, root.length - 1);
|
|
1873
|
+
root = root.slice(0, root.lastIndexOf("/") + 1);
|
|
1874
|
+
if (row.slice(0, root.length) == root) break;
|
|
1875
|
+
}
|
|
1876
|
+
}
|
|
1877
|
+
var mboundary = (data[1] || "").match(/boundary="(.*?)"/);
|
|
1878
|
+
if (!mboundary) throw new Error("MAD cannot find boundary");
|
|
1879
|
+
var boundary = "--" + (mboundary[1] || "");
|
|
1880
|
+
var o = {
|
|
1881
|
+
FileIndex: [],
|
|
1882
|
+
FullPaths: []
|
|
1883
|
+
};
|
|
1884
|
+
init_cfb(o);
|
|
1885
|
+
var start_di, fcnt = 0;
|
|
1886
|
+
for (di = 0; di < data.length; ++di) {
|
|
1887
|
+
var line = data[di];
|
|
1888
|
+
if (line !== boundary && line !== boundary + "--") continue;
|
|
1889
|
+
if (fcnt++) parse_mime(o, data.slice(start_di, di), root);
|
|
1890
|
+
start_di = di;
|
|
1891
|
+
}
|
|
1892
|
+
return o;
|
|
1893
|
+
}
|
|
1894
|
+
function write_mad(cfb, options) {
|
|
1895
|
+
var opts = options || {};
|
|
1896
|
+
var boundary = opts.boundary || "SheetJS";
|
|
1897
|
+
boundary = "------=" + boundary;
|
|
1898
|
+
var out = [
|
|
1899
|
+
"MIME-Version: 1.0",
|
|
1900
|
+
"Content-Type: multipart/related; boundary=\"" + boundary.slice(2) + "\"",
|
|
1901
|
+
"",
|
|
1902
|
+
"",
|
|
1903
|
+
""
|
|
1904
|
+
];
|
|
1905
|
+
var root = cfb.FullPaths[0], fp = root, fi = cfb.FileIndex[0];
|
|
1906
|
+
for (var i = 1; i < cfb.FullPaths.length; ++i) {
|
|
1907
|
+
fp = cfb.FullPaths[i].slice(root.length);
|
|
1908
|
+
fi = cfb.FileIndex[i];
|
|
1909
|
+
if (!fi.size || !fi.content || fp == "Sh33tJ5") continue;
|
|
1910
|
+
fp = fp.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7E-\xFF]/g, function(c) {
|
|
1911
|
+
return "_x" + c.charCodeAt(0).toString(16) + "_";
|
|
1912
|
+
}).replace(/[\u0080-\uFFFF]/g, function(u) {
|
|
1913
|
+
return "_u" + u.charCodeAt(0).toString(16) + "_";
|
|
1914
|
+
});
|
|
1915
|
+
var ca = fi.content;
|
|
1916
|
+
var cstr = has_buf && Buffer.isBuffer(ca) ? ca.toString("binary") : a2s(ca);
|
|
1917
|
+
var dispcnt = 0, L = Math.min(1024, cstr.length), cc = 0;
|
|
1918
|
+
for (var csl = 0; csl <= L; ++csl) if ((cc = cstr.charCodeAt(csl)) >= 32 && cc < 128) ++dispcnt;
|
|
1919
|
+
var qp = dispcnt >= L * 4 / 5;
|
|
1920
|
+
out.push(boundary);
|
|
1921
|
+
out.push("Content-Location: " + (opts.root || "file:///C:/SheetJS/") + fp);
|
|
1922
|
+
out.push("Content-Transfer-Encoding: " + (qp ? "quoted-printable" : "base64"));
|
|
1923
|
+
out.push("Content-Type: " + get_content_type(fi, fp));
|
|
1924
|
+
out.push("");
|
|
1925
|
+
out.push(qp ? write_quoted_printable(cstr) : write_base64_76(cstr));
|
|
1926
|
+
}
|
|
1927
|
+
out.push(boundary + "--\r\n");
|
|
1928
|
+
return out.join("\r\n");
|
|
1929
|
+
}
|
|
1930
|
+
function cfb_new(opts) {
|
|
1931
|
+
var o = {};
|
|
1932
|
+
init_cfb(o, opts);
|
|
1933
|
+
return o;
|
|
1934
|
+
}
|
|
1935
|
+
function cfb_add(cfb, name, content, opts) {
|
|
1936
|
+
var unsafe = opts && opts.unsafe;
|
|
1937
|
+
if (!unsafe) init_cfb(cfb);
|
|
1938
|
+
var file = !unsafe && CFB.find(cfb, name);
|
|
1939
|
+
if (!file) {
|
|
1940
|
+
var fpath = cfb.FullPaths[0];
|
|
1941
|
+
if (name.slice(0, fpath.length) == fpath) fpath = name;
|
|
1942
|
+
else {
|
|
1943
|
+
if (fpath.slice(-1) != "/") fpath += "/";
|
|
1944
|
+
fpath = (fpath + name).replace("//", "/");
|
|
1945
|
+
}
|
|
1946
|
+
file = {
|
|
1947
|
+
name: filename(name),
|
|
1948
|
+
type: 2
|
|
1949
|
+
};
|
|
1950
|
+
cfb.FileIndex.push(file);
|
|
1951
|
+
cfb.FullPaths.push(fpath);
|
|
1952
|
+
if (!unsafe) CFB.utils.cfb_gc(cfb);
|
|
1953
|
+
}
|
|
1954
|
+
file.content = content;
|
|
1955
|
+
file.size = content ? content.length : 0;
|
|
1956
|
+
if (opts) {
|
|
1957
|
+
if (opts.CLSID) file.clsid = opts.CLSID;
|
|
1958
|
+
if (opts.mt) file.mt = opts.mt;
|
|
1959
|
+
if (opts.ct) file.ct = opts.ct;
|
|
1960
|
+
}
|
|
1961
|
+
return file;
|
|
1962
|
+
}
|
|
1963
|
+
function cfb_del(cfb, name) {
|
|
1964
|
+
init_cfb(cfb);
|
|
1965
|
+
var file = CFB.find(cfb, name);
|
|
1966
|
+
if (file) {
|
|
1967
|
+
for (var j = 0; j < cfb.FileIndex.length; ++j) if (cfb.FileIndex[j] == file) {
|
|
1968
|
+
cfb.FileIndex.splice(j, 1);
|
|
1969
|
+
cfb.FullPaths.splice(j, 1);
|
|
1970
|
+
return true;
|
|
1971
|
+
}
|
|
1972
|
+
}
|
|
1973
|
+
return false;
|
|
1974
|
+
}
|
|
1975
|
+
function cfb_mov(cfb, old_name, new_name) {
|
|
1976
|
+
init_cfb(cfb);
|
|
1977
|
+
var file = CFB.find(cfb, old_name);
|
|
1978
|
+
if (file) {
|
|
1979
|
+
for (var j = 0; j < cfb.FileIndex.length; ++j) if (cfb.FileIndex[j] == file) {
|
|
1980
|
+
cfb.FileIndex[j].name = filename(new_name);
|
|
1981
|
+
cfb.FullPaths[j] = new_name;
|
|
1982
|
+
return true;
|
|
1983
|
+
}
|
|
1984
|
+
}
|
|
1985
|
+
return false;
|
|
1986
|
+
}
|
|
1987
|
+
function cfb_gc(cfb) {
|
|
1988
|
+
rebuild_cfb(cfb, true);
|
|
1989
|
+
}
|
|
1990
|
+
exports$1.find = find;
|
|
1991
|
+
exports$1.read = read;
|
|
1992
|
+
exports$1.parse = parse;
|
|
1993
|
+
exports$1.write = write;
|
|
1994
|
+
exports$1.writeFile = write_file;
|
|
1995
|
+
exports$1.utils = {
|
|
1996
|
+
cfb_new,
|
|
1997
|
+
cfb_add,
|
|
1998
|
+
cfb_del,
|
|
1999
|
+
cfb_mov,
|
|
2000
|
+
cfb_gc,
|
|
2001
|
+
ReadShift,
|
|
2002
|
+
CheckField,
|
|
2003
|
+
prep_blob,
|
|
2004
|
+
bconcat,
|
|
2005
|
+
use_zlib,
|
|
2006
|
+
_deflateRaw: _deflate,
|
|
2007
|
+
_inflateRaw: _inflate,
|
|
2008
|
+
consts
|
|
2009
|
+
};
|
|
2010
|
+
return exports$1;
|
|
2011
|
+
})();
|
|
2012
|
+
if (typeof __require !== "undefined" && typeof module !== "undefined" && typeof DO_NOT_EXPORT_CFB === "undefined") module.exports = CFB;
|
|
2013
|
+
})))(), 1);
|
|
2014
|
+
var ERROR_MESSAGES = Object.freeze({
|
|
2015
|
+
ERR_INVALID_ARGUMENT: "Invalid argument",
|
|
2016
|
+
ERR_UNSUPPORTED_EXTENSION: "Supported extensions are .xls, .xlsx, and .xlsm; input and output formats must match",
|
|
2017
|
+
ERR_INVALID_XLS: "Invalid or unsupported XLS workbook",
|
|
2018
|
+
ERR_INVALID_XLSX: "Invalid or unsupported OOXML workbook",
|
|
2019
|
+
ERR_LIMIT_EXCEEDED: "Excel workbook exceeds a configured safety limit",
|
|
2020
|
+
ERR_WORKSHEET_COUNT: "The workbook must contain exactly one worksheet",
|
|
2021
|
+
ERR_SAME_PATH: "Input and output paths must be different",
|
|
2022
|
+
ERR_OUTPUT_EXISTS: "The output file already exists",
|
|
2023
|
+
ERR_FILE_READ: "Unable to read the input Excel file",
|
|
2024
|
+
ERR_FILE_WRITE: "Unable to write the sanitized Excel file"
|
|
2025
|
+
});
|
|
2026
|
+
var ExcelSanitizationError = class extends Error {
|
|
2027
|
+
name = "ExcelSanitizationError";
|
|
2028
|
+
code;
|
|
2029
|
+
details;
|
|
2030
|
+
constructor(code, message, options = {}) {
|
|
2031
|
+
super(message, options.cause === void 0 ? void 0 : { cause: options.cause });
|
|
2032
|
+
this.code = code;
|
|
2033
|
+
if (options.details !== void 0) this.details = Object.freeze({ ...options.details });
|
|
2034
|
+
}
|
|
2035
|
+
};
|
|
2036
|
+
function createError(code, options = {}) {
|
|
2037
|
+
return new ExcelSanitizationError(code, options.message ?? ERROR_MESSAGES[code], options);
|
|
2038
|
+
}
|
|
2039
|
+
function limitExceeded(limit, configured, actual, partName) {
|
|
2040
|
+
return createError("ERR_LIMIT_EXCEEDED", { details: {
|
|
2041
|
+
limit,
|
|
2042
|
+
configured,
|
|
2043
|
+
actual,
|
|
2044
|
+
...partName === void 0 ? {} : { partName }
|
|
2045
|
+
} });
|
|
2046
|
+
}
|
|
2047
|
+
//#endregion
|
|
2048
|
+
//#region src/biff/workbook.ts
|
|
2049
|
+
var COMPOUND_FILE_SIGNATURE = Buffer.from([
|
|
2050
|
+
208,
|
|
2051
|
+
207,
|
|
2052
|
+
17,
|
|
2053
|
+
224,
|
|
2054
|
+
161,
|
|
2055
|
+
177,
|
|
2056
|
+
26,
|
|
2057
|
+
225
|
|
2058
|
+
]);
|
|
2059
|
+
var RECORD_HEADER_BYTES = 4;
|
|
2060
|
+
var CFB_STORAGE_ENTRY = 1;
|
|
2061
|
+
var CFB_STREAM_ENTRY = 2;
|
|
2062
|
+
var RECORD_CONTINUE = 60;
|
|
2063
|
+
var RECORD_BOUNDSHEET = 133;
|
|
2064
|
+
var RECORD_BOF_IDS = /* @__PURE__ */ new Set([
|
|
2065
|
+
9,
|
|
2066
|
+
521,
|
|
2067
|
+
1033,
|
|
2068
|
+
2057
|
|
2069
|
+
]);
|
|
2070
|
+
var OFFSET_CACHE_RECORD_IDS = /* @__PURE__ */ new Set([
|
|
2071
|
+
215,
|
|
2072
|
+
255,
|
|
2073
|
+
523
|
|
2074
|
+
]);
|
|
2075
|
+
var DRAWING_RECORD_IDS = /* @__PURE__ */ new Set([
|
|
2076
|
+
28,
|
|
2077
|
+
93,
|
|
2078
|
+
127,
|
|
2079
|
+
233,
|
|
2080
|
+
235,
|
|
2081
|
+
236,
|
|
2082
|
+
237,
|
|
2083
|
+
438,
|
|
2084
|
+
2150
|
|
2085
|
+
]);
|
|
2086
|
+
function hasCompoundFileSignature(buffer) {
|
|
2087
|
+
return buffer.length >= COMPOUND_FILE_SIGNATURE.length && buffer.subarray(0, COMPOUND_FILE_SIGNATURE.length).equals(COMPOUND_FILE_SIGNATURE);
|
|
2088
|
+
}
|
|
2089
|
+
async function sanitizeBiffWorkbook(buffer, options) {
|
|
2090
|
+
enforceInputSize(buffer, options);
|
|
2091
|
+
const cfb = import_cfb.read(buffer, { type: "buffer" });
|
|
2092
|
+
enforceContainerLimits(cfb, options);
|
|
2093
|
+
const workbookEntry = import_cfb.find(cfb, "Workbook") ?? import_cfb.find(cfb, "Book");
|
|
2094
|
+
if (!workbookEntry || workbookEntry.type !== CFB_STREAM_ENTRY) throw new Error("Compound file has no BIFF Workbook stream");
|
|
2095
|
+
const records = parseBiffRecords(Buffer.from(workbookEntry.content));
|
|
2096
|
+
rejectEncryptedWorkbook(records);
|
|
2097
|
+
enforceWorksheetCount$1(records, options.requireSingleWorksheet);
|
|
2098
|
+
const sanitizedStream = rebuildWorkbookStream(records);
|
|
2099
|
+
workbookEntry.content = sanitizedStream;
|
|
2100
|
+
workbookEntry.size = sanitizedStream.length;
|
|
2101
|
+
removeEmbeddedObjectEntries(cfb);
|
|
2102
|
+
return Buffer.from(import_cfb.write(cfb, {
|
|
2103
|
+
type: "buffer",
|
|
2104
|
+
fileType: "cfb"
|
|
2105
|
+
}));
|
|
2106
|
+
}
|
|
2107
|
+
function enforceInputSize(buffer, options) {
|
|
2108
|
+
const configured = options.limits.maxUncompressedBytes;
|
|
2109
|
+
if (buffer.length > configured) throw limitExceeded("maxUncompressedBytes", configured, buffer.length);
|
|
2110
|
+
}
|
|
2111
|
+
function enforceContainerLimits(cfb, options) {
|
|
2112
|
+
const entries = cfb.FileIndex.filter((entry) => entry.type === CFB_STORAGE_ENTRY || entry.type === CFB_STREAM_ENTRY);
|
|
2113
|
+
if (entries.length > options.limits.maxEntryCount) throw limitExceeded("maxEntryCount", options.limits.maxEntryCount, entries.length);
|
|
2114
|
+
const totalBytes = entries.reduce((total, entry) => entry.type === CFB_STREAM_ENTRY ? total + entry.content.length : total, 0);
|
|
2115
|
+
if (totalBytes > options.limits.maxUncompressedBytes) throw limitExceeded("maxUncompressedBytes", options.limits.maxUncompressedBytes, totalBytes);
|
|
2116
|
+
}
|
|
2117
|
+
function parseBiffRecords(stream) {
|
|
2118
|
+
const records = [];
|
|
2119
|
+
let offset = 0;
|
|
2120
|
+
let removeContinuation = false;
|
|
2121
|
+
while (offset < stream.length) {
|
|
2122
|
+
if (offset + RECORD_HEADER_BYTES > stream.length) throw new Error("Truncated BIFF record header");
|
|
2123
|
+
const id = stream.readUInt16LE(offset);
|
|
2124
|
+
const length = stream.readUInt16LE(offset + 2);
|
|
2125
|
+
const nextOffset = offset + RECORD_HEADER_BYTES + length;
|
|
2126
|
+
if (nextOffset > stream.length) throw new Error("Truncated BIFF record payload");
|
|
2127
|
+
const remove = id === RECORD_CONTINUE ? removeContinuation : DRAWING_RECORD_IDS.has(id) || OFFSET_CACHE_RECORD_IDS.has(id);
|
|
2128
|
+
records.push({
|
|
2129
|
+
id,
|
|
2130
|
+
originalOffset: offset,
|
|
2131
|
+
payload: stream.subarray(offset + RECORD_HEADER_BYTES, nextOffset),
|
|
2132
|
+
remove
|
|
2133
|
+
});
|
|
2134
|
+
if (id !== RECORD_CONTINUE) removeContinuation = remove;
|
|
2135
|
+
offset = nextOffset;
|
|
2136
|
+
}
|
|
2137
|
+
if (records.length === 0 || !RECORD_BOF_IDS.has(records[0]?.id ?? -1)) throw new Error("Workbook stream does not start with a BIFF BOF record");
|
|
2138
|
+
return records;
|
|
2139
|
+
}
|
|
2140
|
+
function rejectEncryptedWorkbook(records) {
|
|
2141
|
+
if (records.some((record) => record.id === 47)) throw createError("ERR_INVALID_XLS", { message: "Encrypted XLS workbooks are not supported" });
|
|
2142
|
+
}
|
|
2143
|
+
function enforceWorksheetCount$1(records, required) {
|
|
2144
|
+
const count = records.filter((record) => record.id === RECORD_BOUNDSHEET).length;
|
|
2145
|
+
if (count === 0) throw new Error("Workbook contains no sheets");
|
|
2146
|
+
if (required && count !== 1) throw createError("ERR_WORKSHEET_COUNT", { details: {
|
|
2147
|
+
expected: 1,
|
|
2148
|
+
actual: count
|
|
2149
|
+
} });
|
|
2150
|
+
}
|
|
2151
|
+
function rebuildWorkbookStream(records) {
|
|
2152
|
+
const newOffsets = /* @__PURE__ */ new Map();
|
|
2153
|
+
let outputLength = 0;
|
|
2154
|
+
for (const record of records) {
|
|
2155
|
+
if (record.remove) continue;
|
|
2156
|
+
newOffsets.set(record.originalOffset, outputLength);
|
|
2157
|
+
outputLength += RECORD_HEADER_BYTES + record.payload.length;
|
|
2158
|
+
}
|
|
2159
|
+
const output = Buffer.allocUnsafe(outputLength);
|
|
2160
|
+
let outputOffset = 0;
|
|
2161
|
+
for (const record of records) {
|
|
2162
|
+
if (record.remove) continue;
|
|
2163
|
+
const payload = patchBoundSheetOffset(record, newOffsets);
|
|
2164
|
+
output.writeUInt16LE(record.id, outputOffset);
|
|
2165
|
+
output.writeUInt16LE(payload.length, outputOffset + 2);
|
|
2166
|
+
payload.copy(output, outputOffset + RECORD_HEADER_BYTES);
|
|
2167
|
+
outputOffset += RECORD_HEADER_BYTES + payload.length;
|
|
2168
|
+
}
|
|
2169
|
+
return output;
|
|
2170
|
+
}
|
|
2171
|
+
function patchBoundSheetOffset(record, newOffsets) {
|
|
2172
|
+
if (record.id !== RECORD_BOUNDSHEET) return record.payload;
|
|
2173
|
+
if (record.payload.length < 4) throw new Error("Invalid BoundSheet record");
|
|
2174
|
+
const originalSheetOffset = record.payload.readUInt32LE(0);
|
|
2175
|
+
const newSheetOffset = newOffsets.get(originalSheetOffset);
|
|
2176
|
+
if (newSheetOffset === void 0) throw new Error("BoundSheet record points outside the Workbook stream");
|
|
2177
|
+
const payload = Buffer.from(record.payload);
|
|
2178
|
+
payload.writeUInt32LE(newSheetOffset, 0);
|
|
2179
|
+
return payload;
|
|
2180
|
+
}
|
|
2181
|
+
function removeEmbeddedObjectEntries(cfb) {
|
|
2182
|
+
const paths = cfb.FullPaths.filter((path) => path.split("/").filter(Boolean).some((segment) => segment.toLowerCase() === "objectpool" || segment.toLowerCase() === "ctls" || /^mbd[0-9a-f]{8}$/i.test(segment)));
|
|
2183
|
+
for (let index = paths.length - 1; index >= 0; index -= 1) import_cfb.utils.cfb_del(cfb, paths[index] ?? "");
|
|
2184
|
+
if (paths.length > 0) import_cfb.utils.cfb_gc(cfb);
|
|
2185
|
+
}
|
|
2186
|
+
//#endregion
|
|
2187
|
+
//#region src/zip/central-directory.ts
|
|
2188
|
+
var END_RECORD_MINIMUM_SIZE = 22;
|
|
2189
|
+
var CENTRAL_DIRECTORY_ENTRY_MINIMUM_SIZE = 46;
|
|
2190
|
+
var MAX_ZIP_COMMENT_SIZE = 65535;
|
|
2191
|
+
var END_RECORD_SIGNATURE = 101010256;
|
|
2192
|
+
var CENTRAL_DIRECTORY_ENTRY_SIGNATURE = 33639248;
|
|
2193
|
+
var ZIP64_END_LOCATOR_SIGNATURE = 117853008;
|
|
2194
|
+
function hasZipSignature(buffer) {
|
|
2195
|
+
return buffer.length >= 2 && buffer[0] === 80 && buffer[1] === 75;
|
|
2196
|
+
}
|
|
2197
|
+
function validateZipCentralDirectory(buffer, limits) {
|
|
2198
|
+
const endRecord = readEndRecord(buffer, limits);
|
|
2199
|
+
const centralDirectoryEnd = endRecord.centralDirectoryOffset + endRecord.centralDirectorySize;
|
|
2200
|
+
if (endRecord.centralDirectoryOffset > endRecord.offset || centralDirectoryEnd > endRecord.offset || centralDirectoryEnd > buffer.length) throw new Error("Invalid ZIP central-directory bounds");
|
|
2201
|
+
let entryOffset = endRecord.centralDirectoryOffset;
|
|
2202
|
+
let totalUncompressedSize = 0;
|
|
2203
|
+
for (let index = 0; index < endRecord.totalEntries; index += 1) {
|
|
2204
|
+
const entry = readCentralDirectoryEntry(buffer, entryOffset, centralDirectoryEnd, endRecord.centralDirectoryOffset);
|
|
2205
|
+
totalUncompressedSize += entry.uncompressedSize;
|
|
2206
|
+
if (totalUncompressedSize > limits.maxUncompressedBytes) throw limitExceeded("maxUncompressedBytes", limits.maxUncompressedBytes, totalUncompressedSize);
|
|
2207
|
+
entryOffset = entry.nextOffset;
|
|
2208
|
+
}
|
|
2209
|
+
if (entryOffset !== centralDirectoryEnd) throw new Error("ZIP central-directory entry count is inconsistent");
|
|
2210
|
+
}
|
|
2211
|
+
function readEndRecord(buffer, limits) {
|
|
2212
|
+
const offset = findEndOfCentralDirectory(buffer);
|
|
2213
|
+
if (offset === void 0 || offset + END_RECORD_MINIMUM_SIZE > buffer.length) throw new Error("ZIP end-of-central-directory record is missing");
|
|
2214
|
+
const diskNumber = buffer.readUInt16LE(offset + 4);
|
|
2215
|
+
const centralDirectoryDisk = buffer.readUInt16LE(offset + 6);
|
|
2216
|
+
const entriesOnDisk = buffer.readUInt16LE(offset + 8);
|
|
2217
|
+
const totalEntries = buffer.readUInt16LE(offset + 10);
|
|
2218
|
+
const centralDirectorySize = buffer.readUInt32LE(offset + 12);
|
|
2219
|
+
const centralDirectoryOffset = buffer.readUInt32LE(offset + 16);
|
|
2220
|
+
const commentLength = buffer.readUInt16LE(offset + 20);
|
|
2221
|
+
if (offset + END_RECORD_MINIMUM_SIZE + commentLength > buffer.length) throw new Error("Truncated ZIP comment");
|
|
2222
|
+
if (diskNumber !== 0 || centralDirectoryDisk !== 0 || entriesOnDisk !== totalEntries) throw new Error("Multi-disk ZIP files are not supported");
|
|
2223
|
+
if (totalEntries === 65535 || centralDirectorySize === 4294967295 || centralDirectoryOffset === 4294967295 || offset >= 20 && buffer.readUInt32LE(offset - 20) === ZIP64_END_LOCATOR_SIGNATURE) throw new Error("ZIP64 files are not supported");
|
|
2224
|
+
if (totalEntries > limits.maxEntryCount) throw limitExceeded("maxEntryCount", limits.maxEntryCount, totalEntries);
|
|
2225
|
+
return {
|
|
2226
|
+
offset,
|
|
2227
|
+
totalEntries,
|
|
2228
|
+
centralDirectoryOffset,
|
|
2229
|
+
centralDirectorySize
|
|
2230
|
+
};
|
|
2231
|
+
}
|
|
2232
|
+
function readCentralDirectoryEntry(buffer, entryOffset, centralDirectoryEnd, centralDirectoryOffset) {
|
|
2233
|
+
if (entryOffset + CENTRAL_DIRECTORY_ENTRY_MINIMUM_SIZE > centralDirectoryEnd || buffer.readUInt32LE(entryOffset) !== CENTRAL_DIRECTORY_ENTRY_SIGNATURE) throw new Error("Malformed ZIP central-directory entry");
|
|
2234
|
+
const compressedSize = buffer.readUInt32LE(entryOffset + 20);
|
|
2235
|
+
const uncompressedSize = buffer.readUInt32LE(entryOffset + 24);
|
|
2236
|
+
const fileNameLength = buffer.readUInt16LE(entryOffset + 28);
|
|
2237
|
+
const extraLength = buffer.readUInt16LE(entryOffset + 30);
|
|
2238
|
+
const fileCommentLength = buffer.readUInt16LE(entryOffset + 32);
|
|
2239
|
+
const entryDisk = buffer.readUInt16LE(entryOffset + 34);
|
|
2240
|
+
const localHeaderOffset = buffer.readUInt32LE(entryOffset + 42);
|
|
2241
|
+
if (compressedSize === 4294967295 || uncompressedSize === 4294967295 || localHeaderOffset === 4294967295 || entryDisk !== 0) throw new Error("ZIP64 or multi-disk entries are not supported");
|
|
2242
|
+
const fileNameOffset = entryOffset + CENTRAL_DIRECTORY_ENTRY_MINIMUM_SIZE;
|
|
2243
|
+
const extraOffset = fileNameOffset + fileNameLength;
|
|
2244
|
+
const nextOffset = extraOffset + extraLength + fileCommentLength;
|
|
2245
|
+
if (nextOffset > centralDirectoryEnd) throw new Error("Truncated ZIP central-directory entry");
|
|
2246
|
+
validatePackageEntryName(buffer.subarray(fileNameOffset, extraOffset).toString("utf8"));
|
|
2247
|
+
rejectZip64ExtraFields(buffer, extraOffset, extraLength);
|
|
2248
|
+
if (localHeaderOffset >= centralDirectoryOffset) throw new Error("Invalid ZIP local-header offset");
|
|
2249
|
+
return {
|
|
2250
|
+
nextOffset,
|
|
2251
|
+
uncompressedSize
|
|
2252
|
+
};
|
|
2253
|
+
}
|
|
2254
|
+
function validatePackageEntryName(name) {
|
|
2255
|
+
const normalized = name.replaceAll("\\", "/");
|
|
2256
|
+
if (normalized.includes("\0") || normalized.startsWith("/") || /^[A-Za-z]:\//.test(normalized) || normalized.split("/").includes("..")) throw new Error(`Unsafe ZIP entry name: ${name}`);
|
|
2257
|
+
}
|
|
2258
|
+
function findEndOfCentralDirectory(buffer) {
|
|
2259
|
+
const minimumOffset = Math.max(0, buffer.length - MAX_ZIP_COMMENT_SIZE - END_RECORD_MINIMUM_SIZE);
|
|
2260
|
+
for (let offset = buffer.length - END_RECORD_MINIMUM_SIZE; offset >= minimumOffset; offset -= 1) if (buffer.readUInt32LE(offset) === END_RECORD_SIGNATURE && offset + END_RECORD_MINIMUM_SIZE + buffer.readUInt16LE(offset + 20) === buffer.length) return offset;
|
|
2261
|
+
}
|
|
2262
|
+
function rejectZip64ExtraFields(buffer, extraOffset, extraLength) {
|
|
2263
|
+
const extraEnd = extraOffset + extraLength;
|
|
2264
|
+
let offset = extraOffset;
|
|
2265
|
+
while (offset < extraEnd) {
|
|
2266
|
+
if (offset + 4 > extraEnd) throw new Error("Malformed ZIP extra field");
|
|
2267
|
+
const headerId = buffer.readUInt16LE(offset);
|
|
2268
|
+
const fieldLength = buffer.readUInt16LE(offset + 2);
|
|
2269
|
+
offset += 4;
|
|
2270
|
+
if (offset + fieldLength > extraEnd) throw new Error("Truncated ZIP extra field");
|
|
2271
|
+
if (headerId === 1) throw new Error("ZIP64 files are not supported");
|
|
2272
|
+
offset += fieldLength;
|
|
2273
|
+
}
|
|
2274
|
+
}
|
|
2275
|
+
//#endregion
|
|
2276
|
+
//#region src/ooxml/constants.ts
|
|
2277
|
+
var DRAWING_RELATIONSHIP_SUFFIXES = [
|
|
2278
|
+
"/comments",
|
|
2279
|
+
"/control",
|
|
2280
|
+
"/drawing",
|
|
2281
|
+
"/image",
|
|
2282
|
+
"/oleObject",
|
|
2283
|
+
"/threadedComment",
|
|
2284
|
+
"/vmlDrawing"
|
|
2285
|
+
];
|
|
2286
|
+
var PERSON_RELATIONSHIP_SUFFIXES = ["/person"];
|
|
2287
|
+
var DRAWING_ELEMENTS = [
|
|
2288
|
+
"controls",
|
|
2289
|
+
"drawing",
|
|
2290
|
+
"legacyDrawing",
|
|
2291
|
+
"legacyDrawingHF",
|
|
2292
|
+
"oleObjects",
|
|
2293
|
+
"picture"
|
|
2294
|
+
];
|
|
2295
|
+
//#endregion
|
|
2296
|
+
//#region src/ooxml/cleanup.ts
|
|
2297
|
+
function removeWorksheetDrawingMarkup(xml) {
|
|
2298
|
+
return DRAWING_ELEMENTS.reduce((result, name) => {
|
|
2299
|
+
const element = new RegExp(`<(?:\\w+:)?${name}\\b[^>]*(?:\\/\\s*>|>[\\s\\S]*?<\\/(?:\\w+:)?${name}\\s*>)`, "gi");
|
|
2300
|
+
return result.replace(element, "");
|
|
2301
|
+
}, xml);
|
|
2302
|
+
}
|
|
2303
|
+
function removeThreadedCommentExtensions(xml) {
|
|
2304
|
+
return xml.replace(/<(?:\w+:)?ext\b[^>]*>[\s\S]*?<\/(?:\w+:)?ext\s*>/gi, (extension) => /<(?:\w+:)?threadedComments?\b/i.test(extension) ? "" : extension);
|
|
2305
|
+
}
|
|
2306
|
+
//#endregion
|
|
2307
|
+
//#region src/ooxml/parts.ts
|
|
2308
|
+
function getNodeBufferStream(file) {
|
|
2309
|
+
return file.internalStream("nodebuffer");
|
|
2310
|
+
}
|
|
2311
|
+
async function requireXml(zip, partName, budget, partLimitBytes) {
|
|
2312
|
+
const file = zip.file(partName);
|
|
2313
|
+
if (!file) throw new Error(`Required workbook part is missing: ${partName}`);
|
|
2314
|
+
return readXmlPart(file, partName, budget, partLimitBytes);
|
|
2315
|
+
}
|
|
2316
|
+
function readXmlPart(file, partName, budget, partLimitBytes) {
|
|
2317
|
+
return new Promise((resolve, reject) => {
|
|
2318
|
+
const chunks = [];
|
|
2319
|
+
const stream = getNodeBufferStream(file);
|
|
2320
|
+
let partBytes = 0;
|
|
2321
|
+
let settled = false;
|
|
2322
|
+
const fail = (error) => {
|
|
2323
|
+
if (settled) return;
|
|
2324
|
+
settled = true;
|
|
2325
|
+
stream.pause();
|
|
2326
|
+
reject(error);
|
|
2327
|
+
};
|
|
2328
|
+
stream.on("data", (chunk) => {
|
|
2329
|
+
if (settled) return;
|
|
2330
|
+
partBytes += chunk.length;
|
|
2331
|
+
budget.consumedBytes += chunk.length;
|
|
2332
|
+
if (partBytes > partLimitBytes) {
|
|
2333
|
+
fail(limitExceeded("partBytes", partLimitBytes, partBytes, partName));
|
|
2334
|
+
return;
|
|
2335
|
+
}
|
|
2336
|
+
if (budget.consumedBytes > budget.limitBytes) {
|
|
2337
|
+
fail(limitExceeded("maxXmlBytes", budget.limitBytes, budget.consumedBytes, partName));
|
|
2338
|
+
return;
|
|
2339
|
+
}
|
|
2340
|
+
chunks.push(Buffer.from(chunk));
|
|
2341
|
+
}).on("error", (error) => fail(error)).on("end", () => {
|
|
2342
|
+
if (settled) return;
|
|
2343
|
+
settled = true;
|
|
2344
|
+
resolve(Buffer.concat(chunks, partBytes).toString("utf8"));
|
|
2345
|
+
}).resume();
|
|
2346
|
+
});
|
|
2347
|
+
}
|
|
2348
|
+
//#endregion
|
|
2349
|
+
//#region src/ooxml/xml.ts
|
|
2350
|
+
function getAttribute(xml, name) {
|
|
2351
|
+
const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2352
|
+
const value = xml.match(new RegExp(`(?:^|\\s)${escaped}\\s*=\\s*(["'])(.*?)\\1`, "i"))?.[2];
|
|
2353
|
+
return value === void 0 ? void 0 : decodeXml(value);
|
|
2354
|
+
}
|
|
2355
|
+
function decodeXml(value) {
|
|
2356
|
+
return value.replaceAll("&", "&").replaceAll(""", "\"").replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
2357
|
+
}
|
|
2358
|
+
function findCollection(xml, name) {
|
|
2359
|
+
const match = xml.match(new RegExp(`<(?:\\w+:)?${name}\\b[^>]*>([\\s\\S]*?)<\\/(?:\\w+:)?${name}\\s*>`, "i"));
|
|
2360
|
+
if (!match) return;
|
|
2361
|
+
const full = match[0];
|
|
2362
|
+
if (full === void 0) return;
|
|
2363
|
+
return {
|
|
2364
|
+
body: match[1] ?? "",
|
|
2365
|
+
full,
|
|
2366
|
+
opening: full.slice(0, full.indexOf(">") + 1)
|
|
2367
|
+
};
|
|
2368
|
+
}
|
|
2369
|
+
function replaceCollection(xml, name, body, count) {
|
|
2370
|
+
const collection = findCollection(xml, name);
|
|
2371
|
+
if (!collection) return xml;
|
|
2372
|
+
const opening = /\bcount\s*=/.test(collection.opening) ? collection.opening.replace(/(\bcount\s*=\s*)(["'])\d+\2/i, `$1"${count}"`) : collection.opening.replace(/>$/, ` count="${count}">`);
|
|
2373
|
+
const prefix = collection.opening.match(/^<(\w+:)/)?.[1] ?? "";
|
|
2374
|
+
return xml.replace(collection.full, `${opening}${body}</${prefix}${name}>`);
|
|
2375
|
+
}
|
|
2376
|
+
function matchElements(xml, name) {
|
|
2377
|
+
return xml.match(new RegExp(`<(?:\\w+:)?${name}\\b[^>]*\\/\\s*>|<(?:\\w+:)?${name}\\b[^>]*>[\\s\\S]*?<\\/(?:\\w+:)?${name}\\s*>`, "gi")) ?? [];
|
|
2378
|
+
}
|
|
2379
|
+
//#endregion
|
|
2380
|
+
//#region src/ooxml/relationships.ts
|
|
2381
|
+
function removeRelationships(xml, source, relationshipSuffixes) {
|
|
2382
|
+
const targets = /* @__PURE__ */ new Set();
|
|
2383
|
+
return {
|
|
2384
|
+
xml: xml.replace(/<(?:\w+:)?Relationship\b[^>]*?(?:\/\s*>|>\s*<\/(?:\w+:)?Relationship\s*>)/gi, (tag) => {
|
|
2385
|
+
const type = getAttribute(tag, "Type") ?? "";
|
|
2386
|
+
const target = getAttribute(tag, "Target");
|
|
2387
|
+
const targetMode = getAttribute(tag, "TargetMode");
|
|
2388
|
+
if (!target || targetMode?.toLowerCase() === "external" || !relationshipSuffixes.some((suffix) => type.endsWith(suffix))) return tag;
|
|
2389
|
+
targets.add(resolveTarget(source, target));
|
|
2390
|
+
return "";
|
|
2391
|
+
}),
|
|
2392
|
+
targets
|
|
2393
|
+
};
|
|
2394
|
+
}
|
|
2395
|
+
function parseRelationships(xml, source) {
|
|
2396
|
+
return Array.from(xml.matchAll(/<(?:\w+:)?Relationship\b([^>]*?)(?:\/\s*>|>\s*<\/(?:\w+:)?Relationship\s*>)/gi)).flatMap((match) => {
|
|
2397
|
+
const attributes = match[1] ?? "";
|
|
2398
|
+
const id = getAttribute(attributes, "Id");
|
|
2399
|
+
const target = getAttribute(attributes, "Target");
|
|
2400
|
+
const type = getAttribute(attributes, "Type");
|
|
2401
|
+
if (!id || !target || !type) return [];
|
|
2402
|
+
const targetMode = getAttribute(attributes, "TargetMode");
|
|
2403
|
+
return [{
|
|
2404
|
+
id,
|
|
2405
|
+
target: targetMode?.toLowerCase() === "external" ? target : resolveTarget(source, target),
|
|
2406
|
+
targetMode,
|
|
2407
|
+
type
|
|
2408
|
+
}];
|
|
2409
|
+
});
|
|
2410
|
+
}
|
|
2411
|
+
function resolveTarget(source, target) {
|
|
2412
|
+
const resolved = target.startsWith("/") ? posix.normalize(target.slice(1)) : posix.normalize(posix.join(posix.dirname(source), target));
|
|
2413
|
+
if (resolved === ".." || resolved.startsWith("../")) throw new Error(`Relationship target escapes package: ${target}`);
|
|
2414
|
+
return resolved;
|
|
2415
|
+
}
|
|
2416
|
+
function relationshipFileForPart(partName) {
|
|
2417
|
+
return posix.join(posix.dirname(partName), "_rels", `${posix.basename(partName)}.rels`);
|
|
2418
|
+
}
|
|
2419
|
+
function sourcePartForRelationshipFile(fileName) {
|
|
2420
|
+
if (fileName === "_rels/.rels") return "";
|
|
2421
|
+
const match = fileName.match(/^(.*\/)_rels\/([^/]+)\.rels$/);
|
|
2422
|
+
return match ? `${match[1]}${match[2]}` : void 0;
|
|
2423
|
+
}
|
|
2424
|
+
async function removeUnreachableParts(zip, detachedRoots, readBudget, limits) {
|
|
2425
|
+
if (detachedRoots.size === 0) return;
|
|
2426
|
+
const graph = await buildRelationshipGraph(zip, readBudget, limits);
|
|
2427
|
+
const candidates = collectReachableParts(detachedRoots, graph);
|
|
2428
|
+
const packageReachable = collectReachableParts(/* @__PURE__ */ new Set([""]), graph);
|
|
2429
|
+
packageReachable.delete("");
|
|
2430
|
+
const deletedParts = new Set([...candidates].filter((partName) => !packageReachable.has(partName)));
|
|
2431
|
+
for (const partName of deletedParts) {
|
|
2432
|
+
zip.remove(partName);
|
|
2433
|
+
zip.remove(relationshipFileForPart(partName));
|
|
2434
|
+
}
|
|
2435
|
+
const contentTypes = await requireXml(zip, "[Content_Types].xml", readBudget, limits.maxMetadataXmlBytes);
|
|
2436
|
+
zip.file("[Content_Types].xml", contentTypes.replace(/<(?:\w+:)?Override\b[^>]*\/>/gi, (tag) => {
|
|
2437
|
+
const partName = getAttribute(tag, "PartName")?.replace(/^\//, "");
|
|
2438
|
+
return partName && deletedParts.has(partName) ? "" : tag;
|
|
2439
|
+
}));
|
|
2440
|
+
}
|
|
2441
|
+
async function buildRelationshipGraph(zip, readBudget, limits) {
|
|
2442
|
+
const graph = /* @__PURE__ */ new Map();
|
|
2443
|
+
for (const fileName of Object.keys(zip.files)) {
|
|
2444
|
+
if (!fileName.endsWith(".rels")) continue;
|
|
2445
|
+
const source = sourcePartForRelationshipFile(fileName);
|
|
2446
|
+
const file = zip.file(fileName);
|
|
2447
|
+
if (source !== void 0 && file) graph.set(source, parseRelationships(await readXmlPart(file, fileName, readBudget, limits.maxRelationshipsXmlBytes), source));
|
|
2448
|
+
}
|
|
2449
|
+
return graph;
|
|
2450
|
+
}
|
|
2451
|
+
function collectReachableParts(initial, graph) {
|
|
2452
|
+
const reachable = new Set(initial);
|
|
2453
|
+
const pending = [...initial];
|
|
2454
|
+
while (pending.length > 0) {
|
|
2455
|
+
const source = pending.pop();
|
|
2456
|
+
if (source === void 0) continue;
|
|
2457
|
+
for (const relationship of graph.get(source) ?? []) if (relationship.targetMode?.toLowerCase() !== "external" && !reachable.has(relationship.target)) {
|
|
2458
|
+
reachable.add(relationship.target);
|
|
2459
|
+
pending.push(relationship.target);
|
|
2460
|
+
}
|
|
2461
|
+
}
|
|
2462
|
+
return reachable;
|
|
2463
|
+
}
|
|
2464
|
+
//#endregion
|
|
2465
|
+
//#region src/ooxml/styles.ts
|
|
2466
|
+
async function removeUnusedCellStyles(zip, worksheets, readBudget, limits) {
|
|
2467
|
+
const stylesFile = zip.file("xl/styles.xml");
|
|
2468
|
+
if (!stylesFile) return;
|
|
2469
|
+
const usedStyles = /* @__PURE__ */ new Set([0]);
|
|
2470
|
+
for (const xml of worksheets.values()) collectStyleReferences(xml, usedStyles);
|
|
2471
|
+
const stylesXml = await readXmlPart(stylesFile, "xl/styles.xml", readBudget, limits.maxStylesXmlBytes);
|
|
2472
|
+
const cellXfs = findCollection(stylesXml, "cellXfs");
|
|
2473
|
+
if (!cellXfs) return;
|
|
2474
|
+
const xfs = matchElements(cellXfs.body, "xf");
|
|
2475
|
+
const retainedIndexes = [...usedStyles].sort((left, right) => left - right);
|
|
2476
|
+
validateStyleIndexes(retainedIndexes, xfs.length);
|
|
2477
|
+
const indexMap = new Map(retainedIndexes.map((oldIndex, newIndex) => [oldIndex, newIndex]));
|
|
2478
|
+
const retainedStyles = retainedIndexes.map((index) => {
|
|
2479
|
+
const style = xfs[index];
|
|
2480
|
+
if (style === void 0) throw new Error(`Worksheet references an invalid style index: ${index}`);
|
|
2481
|
+
return style;
|
|
2482
|
+
});
|
|
2483
|
+
zip.file("xl/styles.xml", replaceCollection(stylesXml, "cellXfs", retainedStyles.join(""), retainedIndexes.length));
|
|
2484
|
+
for (const [worksheetPath, xml] of worksheets) zip.file(worksheetPath, remapWorksheetStyles(xml, indexMap));
|
|
2485
|
+
}
|
|
2486
|
+
function validateStyleIndexes(indexes, styleCount) {
|
|
2487
|
+
if (indexes.some((index) => !Number.isInteger(index) || index < 0 || index >= styleCount)) throw new Error(`Worksheet references an invalid style index (${indexes.join(",")} of ${styleCount})`);
|
|
2488
|
+
}
|
|
2489
|
+
function collectStyleReferences(xml, references) {
|
|
2490
|
+
for (const tag of xml.match(/<(?:\w+:)?(?:c|row)\b[^>]*>/gi) ?? []) {
|
|
2491
|
+
const value = getAttribute(tag, "s");
|
|
2492
|
+
if (value !== void 0) references.add(Number(value));
|
|
2493
|
+
}
|
|
2494
|
+
for (const tag of xml.match(/<(?:\w+:)?col\b[^>]*>/gi) ?? []) {
|
|
2495
|
+
const value = getAttribute(tag, "style");
|
|
2496
|
+
if (value !== void 0) references.add(Number(value));
|
|
2497
|
+
}
|
|
2498
|
+
}
|
|
2499
|
+
function remapWorksheetStyles(xml, indexMap) {
|
|
2500
|
+
return xml.replace(/<(?:\w+:)?(?:c|row)\b[^>]*>/gi, (tag) => remapNumericAttribute(tag, "s", indexMap)).replace(/<(?:\w+:)?col\b[^>]*>/gi, (tag) => remapNumericAttribute(tag, "style", indexMap));
|
|
2501
|
+
}
|
|
2502
|
+
function remapNumericAttribute(tag, attributeName, indexMap) {
|
|
2503
|
+
const expression = new RegExp(`(\\s${attributeName}\\s*=\\s*)(["'])(\\d+)\\2`, "i");
|
|
2504
|
+
return tag.replace(expression, (match, prefix, quote, value) => {
|
|
2505
|
+
const remapped = indexMap.get(Number(value));
|
|
2506
|
+
return remapped === void 0 ? match : `${prefix}${quote}${remapped}${quote}`;
|
|
2507
|
+
});
|
|
2508
|
+
}
|
|
2509
|
+
//#endregion
|
|
2510
|
+
//#region src/ooxml/workbook.ts
|
|
2511
|
+
var WORKBOOK_PATH = "xl/workbook.xml";
|
|
2512
|
+
var WORKBOOK_RELATIONSHIPS_PATH = "xl/_rels/workbook.xml.rels";
|
|
2513
|
+
var CONTENT_TYPES_PATH = "[Content_Types].xml";
|
|
2514
|
+
async function sanitizeOoxmlWorkbook(buffer, options) {
|
|
2515
|
+
if (!hasZipSignature(buffer)) throw new Error("Invalid OOXML ZIP container");
|
|
2516
|
+
validateZipCentralDirectory(buffer, options.limits);
|
|
2517
|
+
const context = await loadWorkbookContext(buffer, options);
|
|
2518
|
+
const worksheetPaths = findWorksheetPaths(context.workbookXml, context.workbookRelationships, options.requireSingleWorksheet);
|
|
2519
|
+
const detachedRoots = cleanWorkbookRelationships(context);
|
|
2520
|
+
const worksheetXmlByPath = await cleanWorksheets(context, worksheetPaths, detachedRoots, options);
|
|
2521
|
+
await removeUnreachableParts(context.zip, detachedRoots, context.readBudget, options.limits);
|
|
2522
|
+
await removeUnusedCellStyles(context.zip, worksheetXmlByPath, context.readBudget, options.limits);
|
|
2523
|
+
return context.zip.generateAsync({
|
|
2524
|
+
type: "nodebuffer",
|
|
2525
|
+
compression: "DEFLATE",
|
|
2526
|
+
compressionOptions: { level: 6 }
|
|
2527
|
+
});
|
|
2528
|
+
}
|
|
2529
|
+
async function loadWorkbookContext(buffer, options) {
|
|
2530
|
+
const readBudget = {
|
|
2531
|
+
consumedBytes: 0,
|
|
2532
|
+
limitBytes: options.limits.maxXmlBytes
|
|
2533
|
+
};
|
|
2534
|
+
const zip = await JSZip.loadAsync(buffer);
|
|
2535
|
+
const workbookXml = await requireXml(zip, WORKBOOK_PATH, readBudget, options.limits.maxMetadataXmlBytes);
|
|
2536
|
+
const workbookRelationshipsXml = await requireXml(zip, WORKBOOK_RELATIONSHIPS_PATH, readBudget, options.limits.maxRelationshipsXmlBytes);
|
|
2537
|
+
await requireXml(zip, CONTENT_TYPES_PATH, readBudget, options.limits.maxMetadataXmlBytes);
|
|
2538
|
+
return {
|
|
2539
|
+
zip,
|
|
2540
|
+
readBudget,
|
|
2541
|
+
workbookXml,
|
|
2542
|
+
workbookRelationshipsXml,
|
|
2543
|
+
workbookRelationships: parseRelationships(workbookRelationshipsXml, WORKBOOK_PATH)
|
|
2544
|
+
};
|
|
2545
|
+
}
|
|
2546
|
+
function findWorksheetPaths(workbookXml, workbookRelationships, requireSingleWorksheet) {
|
|
2547
|
+
const sheetTags = workbookXml.match(/<(?:\w+:)?sheet\b[^>]*\/?>/gi) ?? [];
|
|
2548
|
+
enforceWorksheetCount(sheetTags.length, requireSingleWorksheet);
|
|
2549
|
+
if (sheetTags.length === 0) throw new Error("Workbook contains no sheets");
|
|
2550
|
+
const relationshipsById = new Map(workbookRelationships.map((relationship) => [relationship.id, relationship]));
|
|
2551
|
+
return sheetTags.flatMap((sheetTag) => {
|
|
2552
|
+
const id = getAttribute(sheetTag, "r:id");
|
|
2553
|
+
const relationship = id ? relationshipsById.get(id) : void 0;
|
|
2554
|
+
return relationship?.type.endsWith("/worksheet") ? [relationship.target] : [];
|
|
2555
|
+
});
|
|
2556
|
+
}
|
|
2557
|
+
function cleanWorkbookRelationships(context) {
|
|
2558
|
+
const cleaned = removeRelationships(context.workbookRelationshipsXml, WORKBOOK_PATH, PERSON_RELATIONSHIP_SUFFIXES);
|
|
2559
|
+
context.zip.file(WORKBOOK_RELATIONSHIPS_PATH, cleaned.xml);
|
|
2560
|
+
return cleaned.targets;
|
|
2561
|
+
}
|
|
2562
|
+
async function cleanWorksheets(context, worksheetPaths, detachedRoots, options) {
|
|
2563
|
+
const worksheetXmlByPath = /* @__PURE__ */ new Map();
|
|
2564
|
+
for (const worksheetPath of worksheetPaths) {
|
|
2565
|
+
const cleanedWorksheetXml = removeThreadedCommentExtensions(removeWorksheetDrawingMarkup(await requireXml(context.zip, worksheetPath, context.readBudget, options.limits.maxWorksheetXmlBytes)));
|
|
2566
|
+
worksheetXmlByPath.set(worksheetPath, cleanedWorksheetXml);
|
|
2567
|
+
context.zip.file(worksheetPath, cleanedWorksheetXml);
|
|
2568
|
+
await cleanWorksheetRelationships(context, worksheetPath, detachedRoots, options);
|
|
2569
|
+
}
|
|
2570
|
+
return worksheetXmlByPath;
|
|
2571
|
+
}
|
|
2572
|
+
async function cleanWorksheetRelationships(context, worksheetPath, detachedRoots, options) {
|
|
2573
|
+
const relationshipsPath = relationshipFileForPart(worksheetPath);
|
|
2574
|
+
const relationshipsFile = context.zip.file(relationshipsPath);
|
|
2575
|
+
if (!relationshipsFile) return;
|
|
2576
|
+
const cleaned = removeRelationships(await readXmlPart(relationshipsFile, relationshipsPath, context.readBudget, options.limits.maxRelationshipsXmlBytes), worksheetPath, DRAWING_RELATIONSHIP_SUFFIXES);
|
|
2577
|
+
context.zip.file(relationshipsPath, cleaned.xml);
|
|
2578
|
+
for (const target of cleaned.targets) detachedRoots.add(target);
|
|
2579
|
+
}
|
|
2580
|
+
function enforceWorksheetCount(count, required) {
|
|
2581
|
+
if (required && count !== 1) throw createError("ERR_WORKSHEET_COUNT", { details: {
|
|
2582
|
+
expected: 1,
|
|
2583
|
+
actual: count
|
|
2584
|
+
} });
|
|
2585
|
+
}
|
|
2586
|
+
//#endregion
|
|
2587
|
+
//#region src/constants.ts
|
|
2588
|
+
var DEFAULT_LIMITS = Object.freeze({
|
|
2589
|
+
maxEntryCount: 1e4,
|
|
2590
|
+
maxUncompressedBytes: 536870912,
|
|
2591
|
+
maxXmlBytes: 536870912,
|
|
2592
|
+
maxWorksheetXmlBytes: 268435456,
|
|
2593
|
+
maxStylesXmlBytes: 67108864,
|
|
2594
|
+
maxMetadataXmlBytes: 16777216,
|
|
2595
|
+
maxRelationshipsXmlBytes: 8388608
|
|
2596
|
+
});
|
|
2597
|
+
var SANITIZE_OPTION_NAMES = /* @__PURE__ */ new Set(["requireSingleWorksheet", "limits"]);
|
|
2598
|
+
var FILE_OPTION_NAMES = /* @__PURE__ */ new Set([
|
|
2599
|
+
"requireSingleWorksheet",
|
|
2600
|
+
"limits",
|
|
2601
|
+
"overwrite"
|
|
2602
|
+
]);
|
|
2603
|
+
var LIMIT_NAMES = /* @__PURE__ */ new Set([
|
|
2604
|
+
"maxEntryCount",
|
|
2605
|
+
"maxUncompressedBytes",
|
|
2606
|
+
"maxXmlBytes",
|
|
2607
|
+
"maxWorksheetXmlBytes",
|
|
2608
|
+
"maxStylesXmlBytes",
|
|
2609
|
+
"maxMetadataXmlBytes",
|
|
2610
|
+
"maxRelationshipsXmlBytes"
|
|
2611
|
+
]);
|
|
2612
|
+
//#endregion
|
|
2613
|
+
//#region src/options.ts
|
|
2614
|
+
function isRecord(value) {
|
|
2615
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
2616
|
+
}
|
|
2617
|
+
function validateKnownKeys(value, knownKeys, label) {
|
|
2618
|
+
for (const key of Object.keys(value)) if (!knownKeys.has(key)) throw createError("ERR_INVALID_ARGUMENT", {
|
|
2619
|
+
message: `Unknown ${label}: ${key}`,
|
|
2620
|
+
details: { key }
|
|
2621
|
+
});
|
|
2622
|
+
}
|
|
2623
|
+
function isLimitName(name) {
|
|
2624
|
+
return LIMIT_NAMES.has(name);
|
|
2625
|
+
}
|
|
2626
|
+
function normalizeLimits(overrides) {
|
|
2627
|
+
if (overrides === void 0) return DEFAULT_LIMITS;
|
|
2628
|
+
if (!isRecord(overrides)) throw createError("ERR_INVALID_ARGUMENT", { message: "options.limits must be an object" });
|
|
2629
|
+
validateKnownKeys(overrides, LIMIT_NAMES, "limit");
|
|
2630
|
+
const limits = { ...DEFAULT_LIMITS };
|
|
2631
|
+
for (const [name, value] of Object.entries(overrides)) {
|
|
2632
|
+
if (!isLimitName(name)) throw createError("ERR_INVALID_ARGUMENT", {
|
|
2633
|
+
message: `Unknown limit: ${name}`,
|
|
2634
|
+
details: { key: name }
|
|
2635
|
+
});
|
|
2636
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value <= 0) throw createError("ERR_INVALID_ARGUMENT", {
|
|
2637
|
+
message: `options.limits.${name} must be a positive safe integer`,
|
|
2638
|
+
details: {
|
|
2639
|
+
limit: name,
|
|
2640
|
+
value
|
|
2641
|
+
}
|
|
2642
|
+
});
|
|
2643
|
+
limits[name] = value;
|
|
2644
|
+
}
|
|
2645
|
+
return Object.freeze(limits);
|
|
2646
|
+
}
|
|
2647
|
+
function normalizeOptions(options, fileOptions = false) {
|
|
2648
|
+
if (options !== void 0 && !isRecord(options)) throw createError("ERR_INVALID_ARGUMENT", { message: "options must be an object" });
|
|
2649
|
+
const rawOptions = options ?? {};
|
|
2650
|
+
validateKnownKeys(rawOptions, fileOptions ? FILE_OPTION_NAMES : SANITIZE_OPTION_NAMES, "option");
|
|
2651
|
+
if (rawOptions.requireSingleWorksheet !== void 0 && typeof rawOptions.requireSingleWorksheet !== "boolean") throw createError("ERR_INVALID_ARGUMENT", { message: "options.requireSingleWorksheet must be a boolean" });
|
|
2652
|
+
let normalizedOverwrite = false;
|
|
2653
|
+
if (fileOptions) {
|
|
2654
|
+
const overwrite = rawOptions.overwrite;
|
|
2655
|
+
if (overwrite !== void 0 && typeof overwrite !== "boolean") throw createError("ERR_INVALID_ARGUMENT", { message: "options.overwrite must be a boolean" });
|
|
2656
|
+
normalizedOverwrite = overwrite ?? false;
|
|
2657
|
+
}
|
|
2658
|
+
const normalized = {
|
|
2659
|
+
requireSingleWorksheet: rawOptions.requireSingleWorksheet ?? false,
|
|
2660
|
+
limits: normalizeLimits(rawOptions.limits)
|
|
2661
|
+
};
|
|
2662
|
+
if (!fileOptions) return normalized;
|
|
2663
|
+
return {
|
|
2664
|
+
...normalized,
|
|
2665
|
+
overwrite: normalizedOverwrite
|
|
2666
|
+
};
|
|
2667
|
+
}
|
|
2668
|
+
//#endregion
|
|
2669
|
+
//#region src/api/sanitize-excel.ts
|
|
2670
|
+
async function sanitizeExcel(buffer, options) {
|
|
2671
|
+
if (!Buffer.isBuffer(buffer)) throw createError("ERR_INVALID_ARGUMENT", { message: "buffer must be a Node.js Buffer" });
|
|
2672
|
+
const normalized = normalizeOptions(options);
|
|
2673
|
+
const isBiff = hasCompoundFileSignature(buffer);
|
|
2674
|
+
try {
|
|
2675
|
+
return isBiff ? await sanitizeBiffWorkbook(buffer, normalized) : await sanitizeOoxmlWorkbook(buffer, normalized);
|
|
2676
|
+
} catch (error) {
|
|
2677
|
+
if (error instanceof ExcelSanitizationError) throw error;
|
|
2678
|
+
throw createError(isBiff ? "ERR_INVALID_XLS" : "ERR_INVALID_XLSX", { cause: error });
|
|
2679
|
+
}
|
|
2680
|
+
}
|
|
2681
|
+
//#endregion
|
|
2682
|
+
//#region src/formats.ts
|
|
2683
|
+
function excelFileFormat(name) {
|
|
2684
|
+
if (typeof name !== "string") return;
|
|
2685
|
+
const extension = /\.(xls|xlsx|xlsm)$/i.exec(name)?.[1]?.toLowerCase();
|
|
2686
|
+
return extension === "xls" || extension === "xlsx" || extension === "xlsm" ? extension : void 0;
|
|
2687
|
+
}
|
|
2688
|
+
function isExcelFilename(name) {
|
|
2689
|
+
return excelFileFormat(name) !== void 0;
|
|
2690
|
+
}
|
|
2691
|
+
function isXlsxFilename(name) {
|
|
2692
|
+
return excelFileFormat(name) === "xlsx";
|
|
2693
|
+
}
|
|
2694
|
+
//#endregion
|
|
2695
|
+
//#region src/api/sanitize-excel-file.ts
|
|
2696
|
+
async function sanitizeExcelFile(inputPath, outputPath, options) {
|
|
2697
|
+
const format = validateFilePaths(inputPath, outputPath);
|
|
2698
|
+
const normalized = normalizeOptions(options, true);
|
|
2699
|
+
const absoluteInputPath = resolve(inputPath);
|
|
2700
|
+
const absoluteOutputPath = resolve(outputPath);
|
|
2701
|
+
if (absoluteInputPath === absoluteOutputPath) throw createError("ERR_SAME_PATH", { details: {
|
|
2702
|
+
inputPath: absoluteInputPath,
|
|
2703
|
+
outputPath: absoluteOutputPath
|
|
2704
|
+
} });
|
|
2705
|
+
const input = await readInputFile(absoluteInputPath);
|
|
2706
|
+
validateInputFormat(input, format);
|
|
2707
|
+
const sanitized = await sanitizeExcel(input, {
|
|
2708
|
+
requireSingleWorksheet: normalized.requireSingleWorksheet,
|
|
2709
|
+
limits: normalized.limits
|
|
2710
|
+
});
|
|
2711
|
+
if (normalized.overwrite) await replaceFileAtomically(absoluteOutputPath, sanitized);
|
|
2712
|
+
else await writeNewFile(absoluteOutputPath, sanitized);
|
|
2713
|
+
}
|
|
2714
|
+
function validateFilePaths(inputPath, outputPath) {
|
|
2715
|
+
if (typeof inputPath !== "string" || inputPath.length === 0 || typeof outputPath !== "string" || outputPath.length === 0) throw createError("ERR_INVALID_ARGUMENT", { message: "inputPath and outputPath must be non-empty strings" });
|
|
2716
|
+
const inputFormat = excelFileFormat(inputPath);
|
|
2717
|
+
const outputFormat = excelFileFormat(outputPath);
|
|
2718
|
+
if (!inputFormat || !outputFormat || inputFormat !== outputFormat) throw createError("ERR_UNSUPPORTED_EXTENSION", { details: {
|
|
2719
|
+
inputPath,
|
|
2720
|
+
outputPath,
|
|
2721
|
+
inputFormat,
|
|
2722
|
+
outputFormat
|
|
2723
|
+
} });
|
|
2724
|
+
return inputFormat;
|
|
2725
|
+
}
|
|
2726
|
+
function validateInputFormat(input, format) {
|
|
2727
|
+
const isXls = hasCompoundFileSignature(input);
|
|
2728
|
+
if (format === "xls" !== isXls) throw createError(format === "xls" ? "ERR_INVALID_XLS" : "ERR_INVALID_XLSX", { details: { format } });
|
|
2729
|
+
}
|
|
2730
|
+
async function readInputFile(inputPath) {
|
|
2731
|
+
try {
|
|
2732
|
+
return await readFile(inputPath);
|
|
2733
|
+
} catch (error) {
|
|
2734
|
+
throw createError("ERR_FILE_READ", {
|
|
2735
|
+
cause: error,
|
|
2736
|
+
details: { inputPath }
|
|
2737
|
+
});
|
|
2738
|
+
}
|
|
2739
|
+
}
|
|
2740
|
+
async function writeNewFile(outputPath, contents) {
|
|
2741
|
+
try {
|
|
2742
|
+
await writeFile(outputPath, contents, { flag: "wx" });
|
|
2743
|
+
} catch (error) {
|
|
2744
|
+
if (hasErrorCode(error, "EEXIST")) throw createError("ERR_OUTPUT_EXISTS", {
|
|
2745
|
+
cause: error,
|
|
2746
|
+
details: { outputPath }
|
|
2747
|
+
});
|
|
2748
|
+
await removeIfPresent(outputPath);
|
|
2749
|
+
throw createError("ERR_FILE_WRITE", {
|
|
2750
|
+
cause: error,
|
|
2751
|
+
details: { outputPath }
|
|
2752
|
+
});
|
|
2753
|
+
}
|
|
2754
|
+
}
|
|
2755
|
+
async function replaceFileAtomically(outputPath, contents) {
|
|
2756
|
+
const temporaryPath = `${outputPath}.${process.pid}.${randomUUID()}.tmp`;
|
|
2757
|
+
try {
|
|
2758
|
+
await writeFile(temporaryPath, contents, { flag: "wx" });
|
|
2759
|
+
await rename(temporaryPath, outputPath);
|
|
2760
|
+
} catch (error) {
|
|
2761
|
+
await removeIfPresent(temporaryPath);
|
|
2762
|
+
throw createError("ERR_FILE_WRITE", {
|
|
2763
|
+
cause: error,
|
|
2764
|
+
details: { outputPath }
|
|
2765
|
+
});
|
|
2766
|
+
}
|
|
2767
|
+
}
|
|
2768
|
+
function hasErrorCode(error, expectedCode) {
|
|
2769
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === expectedCode;
|
|
2770
|
+
}
|
|
2771
|
+
async function removeIfPresent(path) {
|
|
2772
|
+
await unlink(path).catch(() => void 0);
|
|
2773
|
+
}
|
|
2774
|
+
//#endregion
|
|
2775
|
+
export { DEFAULT_LIMITS, ExcelSanitizationError, isExcelFilename, isXlsxFilename, sanitizeExcel, sanitizeExcelFile };
|
|
2776
|
+
|
|
2777
|
+
//# sourceMappingURL=index.js.map
|