@pixerate/editor 0.73.0 → 0.74.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/THIRD_PARTY_NOTICES.md +1 -0
- package/dist/animation-editor/index.cjs +708 -298
- package/dist/animation-editor/index.cjs.map +1 -1
- package/dist/animation-editor/index.d.cts +36 -2
- package/dist/animation-editor/index.d.ts +36 -2
- package/dist/animation-editor/index.js +693 -283
- package/dist/animation-editor/index.js.map +1 -1
- package/dist/chart/index.cjs +11 -9
- package/dist/chart/index.cjs.map +1 -1
- package/dist/chart/index.js +5 -3
- package/dist/chart/index.js.map +1 -1
- package/dist/{chunk-3S72F46R.js → chunk-2GFUA4X5.js} +2 -322
- package/dist/chunk-2GFUA4X5.js.map +1 -0
- package/dist/chunk-33AHNSEB.js +323 -0
- package/dist/chunk-33AHNSEB.js.map +1 -0
- package/dist/{chunk-NN3JGUSX.cjs → chunk-5PTR7HTL.cjs} +3 -323
- package/dist/chunk-5PTR7HTL.cjs.map +1 -0
- package/dist/{chunk-4YFMSPBU.js → chunk-EIXXBKUB.js} +6 -4
- package/dist/{chunk-4YFMSPBU.js.map → chunk-EIXXBKUB.js.map} +1 -1
- package/dist/chunk-EMQWJA3G.cjs +323 -0
- package/dist/chunk-EMQWJA3G.cjs.map +1 -0
- package/dist/{chunk-BQQZ6MOI.js → chunk-FGW5OWJ4.js} +6 -4
- package/dist/{chunk-BQQZ6MOI.js.map → chunk-FGW5OWJ4.js.map} +1 -1
- package/dist/{chunk-YZZMX6V7.cjs → chunk-FV5AXTSF.cjs} +11 -9
- package/dist/chunk-FV5AXTSF.cjs.map +1 -0
- package/dist/{chunk-7ZSU4MQZ.cjs → chunk-PL3MPFPA.cjs} +10 -8
- package/dist/chunk-PL3MPFPA.cjs.map +1 -0
- package/dist/export/index.cjs +4 -3
- package/dist/export/index.cjs.map +1 -1
- package/dist/export/index.js +3 -2
- package/dist/extensions/index.cjs +4 -3
- package/dist/extensions/index.cjs.map +1 -1
- package/dist/extensions/index.js +3 -2
- package/dist/index.cjs +19 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +12 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-3S72F46R.js.map +0 -1
- package/dist/chunk-7ZSU4MQZ.cjs.map +0 -1
- package/dist/chunk-NN3JGUSX.cjs.map +0 -1
- package/dist/chunk-YZZMX6V7.cjs.map +0 -1
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
// src/import/zip.ts
|
|
2
|
+
var ZipError = class extends Error {
|
|
3
|
+
code;
|
|
4
|
+
entryName;
|
|
5
|
+
constructor(code, message, details = {}) {
|
|
6
|
+
super(message, details.cause !== void 0 ? { cause: details.cause } : void 0);
|
|
7
|
+
this.name = "ZipError";
|
|
8
|
+
this.code = code;
|
|
9
|
+
this.entryName = details.entryName;
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
var DEFAULT_ZIP_MAX_ENTRIES = 1e4;
|
|
13
|
+
var DEFAULT_ZIP_MAX_TOTAL_SIZE = 256 * 1024 * 1024;
|
|
14
|
+
var SIG_EOCD = 101010256;
|
|
15
|
+
var SIG_ZIP64_EOCD = 101075792;
|
|
16
|
+
var SIG_ZIP64_LOCATOR = 117853008;
|
|
17
|
+
var SIG_CENTRAL = 33639248;
|
|
18
|
+
var SIG_LOCAL = 67324752;
|
|
19
|
+
var EOCD_SIZE = 22;
|
|
20
|
+
var MAX_COMMENT = 65535;
|
|
21
|
+
var crcTable = null;
|
|
22
|
+
function zipCrc32(data) {
|
|
23
|
+
if (!crcTable) {
|
|
24
|
+
crcTable = new Uint32Array(256);
|
|
25
|
+
for (let n = 0; n < 256; n++) {
|
|
26
|
+
let c = n;
|
|
27
|
+
for (let k = 0; k < 8; k++) c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
|
|
28
|
+
crcTable[n] = c >>> 0;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
let crc = 4294967295;
|
|
32
|
+
for (let i = 0; i < data.length; i++) crc = crcTable[(crc ^ data[i]) & 255] ^ crc >>> 8;
|
|
33
|
+
return (crc ^ 4294967295) >>> 0;
|
|
34
|
+
}
|
|
35
|
+
function toBytes(data) {
|
|
36
|
+
if (ArrayBuffer.isView(data)) return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
37
|
+
return new Uint8Array(data);
|
|
38
|
+
}
|
|
39
|
+
function isUnsafeZipPath(name) {
|
|
40
|
+
if (!name || name.includes("\0")) return true;
|
|
41
|
+
const normalized = name.replace(/\\/g, "/");
|
|
42
|
+
if (normalized.startsWith("/") || /^[a-zA-Z]:/.test(normalized)) return true;
|
|
43
|
+
return normalized.split("/").some((segment) => segment === "..");
|
|
44
|
+
}
|
|
45
|
+
var utf8 = new TextDecoder("utf-8");
|
|
46
|
+
var CP437_HIGH = "\xC7\xFC\xE9\xE2\xE4\xE0\xE5\xE7\xEA\xEB\xE8\xEF\xEE\xEC\xC4\xC5\xC9\xE6\xC6\xF4\xF6\xF2\xFB\xF9\xFF\xD6\xDC\xA2\xA3\xA5\u20A7\u0192\xE1\xED\xF3\xFA\xF1\xD1\xAA\xBA\xBF\u2310\xAC\xBD\xBC\xA1\xAB\xBB\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255D\u255C\u255B\u2510\u2514\u2534\u252C\u251C\u2500\u253C\u255E\u255F\u255A\u2554\u2569\u2566\u2560\u2550\u256C\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256B\u256A\u2518\u250C\u2588\u2584\u258C\u2590\u2580\u03B1\xDF\u0393\u03C0\u03A3\u03C3\xB5\u03C4\u03A6\u0398\u03A9\u03B4\u221E\u03C6\u03B5\u2229\u2261\xB1\u2265\u2264\u2320\u2321\xF7\u2248\xB0\u2219\xB7\u221A\u207F\xB2\u25A0\xA0";
|
|
47
|
+
function decodeName(bytes, isUtf8) {
|
|
48
|
+
if (isUtf8 || bytes.every((b) => b < 128)) return utf8.decode(bytes);
|
|
49
|
+
let out = "";
|
|
50
|
+
for (const b of bytes) out += b < 128 ? String.fromCharCode(b) : CP437_HIGH[b - 128];
|
|
51
|
+
return out;
|
|
52
|
+
}
|
|
53
|
+
var ZipArchive = class {
|
|
54
|
+
constructor(bytes, entries, maxTotalSize) {
|
|
55
|
+
this.bytes = bytes;
|
|
56
|
+
this.maxTotalSize = maxTotalSize;
|
|
57
|
+
this.entries = entries;
|
|
58
|
+
entries.forEach((entry) => {
|
|
59
|
+
if (!this.byName.has(entry.name)) this.byName.set(entry.name, entry);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
bytes;
|
|
63
|
+
maxTotalSize;
|
|
64
|
+
/** Entries in central-directory order. */
|
|
65
|
+
entries;
|
|
66
|
+
byName = /* @__PURE__ */ new Map();
|
|
67
|
+
extracted = 0;
|
|
68
|
+
/** Looks up an entry by exact name (a leading `/` is ignored). */
|
|
69
|
+
get(name) {
|
|
70
|
+
return this.byName.get(name.replace(/^\/+/, ""));
|
|
71
|
+
}
|
|
72
|
+
has(name) {
|
|
73
|
+
return !!this.get(name);
|
|
74
|
+
}
|
|
75
|
+
/** Uncompressed bytes extracted so far (counted against `maxTotalSize`). */
|
|
76
|
+
get extractedSize() {
|
|
77
|
+
return this.extracted;
|
|
78
|
+
}
|
|
79
|
+
/** Extracts an entry's data, verifying its size and CRC-32. */
|
|
80
|
+
async read(entryOrName) {
|
|
81
|
+
const entry = typeof entryOrName === "string" ? this.get(entryOrName) : entryOrName;
|
|
82
|
+
if (!entry) {
|
|
83
|
+
throw new ZipError("entry_not_found", `ZIP entry "${String(entryOrName)}" not found.`, {
|
|
84
|
+
entryName: String(entryOrName)
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
const name = entry.name;
|
|
88
|
+
if (entry.encrypted) {
|
|
89
|
+
throw new ZipError("encrypted", `ZIP entry "${name}" is encrypted; encrypted archives are not supported.`, {
|
|
90
|
+
entryName: name
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
if (entry.isDirectory) return new Uint8Array(0);
|
|
94
|
+
const remaining = this.maxTotalSize - this.extracted;
|
|
95
|
+
if (entry.size > remaining) {
|
|
96
|
+
throw new ZipError(
|
|
97
|
+
"too_large",
|
|
98
|
+
`Extracting "${name}" (${entry.size} bytes) would exceed the ${this.maxTotalSize}-byte limit.`,
|
|
99
|
+
{ entryName: name }
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
const { bytes } = this;
|
|
103
|
+
const offset = entry.localHeaderOffset;
|
|
104
|
+
if (offset + 30 > bytes.length || readU32(bytes, offset) !== SIG_LOCAL) {
|
|
105
|
+
throw new ZipError("corrupt_entry", `ZIP entry "${name}" has no valid local header.`, { entryName: name });
|
|
106
|
+
}
|
|
107
|
+
const dataStart = offset + 30 + readU16(bytes, offset + 26) + readU16(bytes, offset + 28);
|
|
108
|
+
const dataEnd = dataStart + entry.compressedSize;
|
|
109
|
+
if (dataEnd > bytes.length) {
|
|
110
|
+
throw new ZipError("corrupt_entry", `ZIP entry "${name}" is truncated.`, { entryName: name });
|
|
111
|
+
}
|
|
112
|
+
const raw = bytes.subarray(dataStart, dataEnd);
|
|
113
|
+
let data;
|
|
114
|
+
if (entry.method === 0) {
|
|
115
|
+
if (entry.compressedSize !== entry.size) {
|
|
116
|
+
throw new ZipError("corrupt_entry", `Stored ZIP entry "${name}" has inconsistent sizes.`, { entryName: name });
|
|
117
|
+
}
|
|
118
|
+
data = raw.slice();
|
|
119
|
+
} else if (entry.method === 8) {
|
|
120
|
+
data = await inflateRaw(raw, entry.size, name);
|
|
121
|
+
} else {
|
|
122
|
+
throw new ZipError(
|
|
123
|
+
"unsupported_feature",
|
|
124
|
+
`ZIP entry "${name}" uses unsupported compression method ${entry.method}; only stored and deflate are supported.`,
|
|
125
|
+
{ entryName: name }
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
if (data.length !== entry.size) {
|
|
129
|
+
throw new ZipError("corrupt_entry", `ZIP entry "${name}" size does not match the directory.`, { entryName: name });
|
|
130
|
+
}
|
|
131
|
+
this.extracted += data.length;
|
|
132
|
+
if (zipCrc32(data) !== entry.crc32) {
|
|
133
|
+
throw new ZipError("corrupt_entry", `ZIP entry "${name}" failed its CRC-32 check.`, { entryName: name });
|
|
134
|
+
}
|
|
135
|
+
return data;
|
|
136
|
+
}
|
|
137
|
+
/** Extracts an entry and decodes it as UTF-8 (a leading BOM is removed). */
|
|
138
|
+
async readText(entryOrName) {
|
|
139
|
+
const text = utf8.decode(await this.read(entryOrName));
|
|
140
|
+
return text.charCodeAt(0) === 65279 ? text.slice(1) : text;
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
function readU16(bytes, offset) {
|
|
144
|
+
return bytes[offset] | bytes[offset + 1] << 8;
|
|
145
|
+
}
|
|
146
|
+
function readU32(bytes, offset) {
|
|
147
|
+
return (bytes[offset] | bytes[offset + 1] << 8 | bytes[offset + 2] << 16 | bytes[offset + 3] << 24) >>> 0;
|
|
148
|
+
}
|
|
149
|
+
function readU64(bytes, offset) {
|
|
150
|
+
const value = readU32(bytes, offset) + readU32(bytes, offset + 4) * 4294967296;
|
|
151
|
+
if (!Number.isSafeInteger(value)) {
|
|
152
|
+
throw new ZipError("unsupported_feature", "ZIP64 value exceeds the supported range.");
|
|
153
|
+
}
|
|
154
|
+
return value;
|
|
155
|
+
}
|
|
156
|
+
async function inflateRaw(raw, limit, entryName) {
|
|
157
|
+
const Stream = globalThis.DecompressionStream;
|
|
158
|
+
if (typeof Stream !== "function") {
|
|
159
|
+
throw new ZipError(
|
|
160
|
+
"unsupported_environment",
|
|
161
|
+
"Inflating ZIP entries needs DecompressionStream (modern browsers, Node 18+).",
|
|
162
|
+
{ entryName }
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
const stream = new Stream("deflate-raw");
|
|
166
|
+
const writer = stream.writable.getWriter();
|
|
167
|
+
const reader = stream.readable.getReader();
|
|
168
|
+
const CHUNK = 64 * 1024;
|
|
169
|
+
const feeding = (async () => {
|
|
170
|
+
for (let i = 0; i < raw.length; i += CHUNK) await writer.write(raw.subarray(i, i + CHUNK));
|
|
171
|
+
await writer.close();
|
|
172
|
+
})();
|
|
173
|
+
feeding.catch(() => {
|
|
174
|
+
});
|
|
175
|
+
const chunks = [];
|
|
176
|
+
let total = 0;
|
|
177
|
+
try {
|
|
178
|
+
for (; ; ) {
|
|
179
|
+
const { done, value } = await reader.read();
|
|
180
|
+
if (done) break;
|
|
181
|
+
total += value.length;
|
|
182
|
+
if (total > limit) {
|
|
183
|
+
throw new ZipError(
|
|
184
|
+
"corrupt_entry",
|
|
185
|
+
`ZIP entry "${entryName}" inflates beyond its declared size of ${limit} bytes.`,
|
|
186
|
+
{ entryName }
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
chunks.push(value);
|
|
190
|
+
}
|
|
191
|
+
} catch (error) {
|
|
192
|
+
reader.cancel().catch(() => {
|
|
193
|
+
});
|
|
194
|
+
writer.abort().catch(() => {
|
|
195
|
+
});
|
|
196
|
+
if (error instanceof ZipError) throw error;
|
|
197
|
+
throw new ZipError("corrupt_entry", `ZIP entry "${entryName}" has an invalid deflate stream.`, {
|
|
198
|
+
entryName,
|
|
199
|
+
cause: error
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
await feeding.catch(() => {
|
|
203
|
+
});
|
|
204
|
+
const out = new Uint8Array(total);
|
|
205
|
+
let pos = 0;
|
|
206
|
+
for (const chunk of chunks) {
|
|
207
|
+
out.set(chunk, pos);
|
|
208
|
+
pos += chunk.length;
|
|
209
|
+
}
|
|
210
|
+
return out;
|
|
211
|
+
}
|
|
212
|
+
function findEndOfCentralDirectory(bytes) {
|
|
213
|
+
const min = Math.max(0, bytes.length - EOCD_SIZE - MAX_COMMENT);
|
|
214
|
+
for (let i = bytes.length - EOCD_SIZE; i >= min; i--) {
|
|
215
|
+
if (readU32(bytes, i) === SIG_EOCD && i + EOCD_SIZE + readU16(bytes, i + 20) <= bytes.length) return i;
|
|
216
|
+
}
|
|
217
|
+
return -1;
|
|
218
|
+
}
|
|
219
|
+
async function readZip(data, options = {}) {
|
|
220
|
+
const bytes = toBytes(data);
|
|
221
|
+
const maxEntries = options.maxEntries ?? DEFAULT_ZIP_MAX_ENTRIES;
|
|
222
|
+
const maxTotalSize = options.maxTotalSize ?? DEFAULT_ZIP_MAX_TOTAL_SIZE;
|
|
223
|
+
const eocd = findEndOfCentralDirectory(bytes);
|
|
224
|
+
if (eocd < 0) throw new ZipError("invalid_archive", "Not a ZIP archive (no end of central directory record).");
|
|
225
|
+
let diskNumber = readU16(bytes, eocd + 4);
|
|
226
|
+
let cdDisk = readU16(bytes, eocd + 6);
|
|
227
|
+
let count = readU16(bytes, eocd + 10);
|
|
228
|
+
let cdSize = readU32(bytes, eocd + 12);
|
|
229
|
+
let cdOffset = readU32(bytes, eocd + 16);
|
|
230
|
+
if (count === 65535 || cdSize === 4294967295 || cdOffset === 4294967295) {
|
|
231
|
+
const locator = eocd - 20;
|
|
232
|
+
if (locator < 0 || readU32(bytes, locator) !== SIG_ZIP64_LOCATOR) {
|
|
233
|
+
throw new ZipError("invalid_archive", "ZIP64 archive is missing its end of central directory locator.");
|
|
234
|
+
}
|
|
235
|
+
const record = readU64(bytes, locator + 8);
|
|
236
|
+
if (record + 56 > bytes.length || readU32(bytes, record) !== SIG_ZIP64_EOCD) {
|
|
237
|
+
throw new ZipError("invalid_archive", "ZIP64 end of central directory record not found.");
|
|
238
|
+
}
|
|
239
|
+
diskNumber = readU32(bytes, record + 16);
|
|
240
|
+
cdDisk = readU32(bytes, record + 20);
|
|
241
|
+
count = readU64(bytes, record + 32);
|
|
242
|
+
cdSize = readU64(bytes, record + 40);
|
|
243
|
+
cdOffset = readU64(bytes, record + 48);
|
|
244
|
+
}
|
|
245
|
+
if (diskNumber !== 0 || cdDisk !== 0) {
|
|
246
|
+
throw new ZipError("unsupported_feature", "Multi-disk (spanned) ZIP archives are not supported.");
|
|
247
|
+
}
|
|
248
|
+
if (count > maxEntries) {
|
|
249
|
+
throw new ZipError("too_many_entries", `ZIP archive has ${count} entries; the limit is ${maxEntries}.`);
|
|
250
|
+
}
|
|
251
|
+
if (cdOffset + cdSize > bytes.length) {
|
|
252
|
+
throw new ZipError("invalid_archive", "ZIP central directory lies outside the file.");
|
|
253
|
+
}
|
|
254
|
+
const entries = [];
|
|
255
|
+
let p = cdOffset;
|
|
256
|
+
for (let i = 0; i < count; i++) {
|
|
257
|
+
if (p + 46 > bytes.length || readU32(bytes, p) !== SIG_CENTRAL) {
|
|
258
|
+
throw new ZipError("invalid_archive", "ZIP central directory is corrupt.");
|
|
259
|
+
}
|
|
260
|
+
const flags = readU16(bytes, p + 8);
|
|
261
|
+
const method = readU16(bytes, p + 10);
|
|
262
|
+
const crc32 = readU32(bytes, p + 16);
|
|
263
|
+
let compressedSize = readU32(bytes, p + 20);
|
|
264
|
+
let size = readU32(bytes, p + 24);
|
|
265
|
+
const nameLength = readU16(bytes, p + 28);
|
|
266
|
+
const extraLength = readU16(bytes, p + 30);
|
|
267
|
+
const commentLength = readU16(bytes, p + 32);
|
|
268
|
+
let localHeaderOffset = readU32(bytes, p + 42);
|
|
269
|
+
const nameStart = p + 46;
|
|
270
|
+
const extraStart = nameStart + nameLength;
|
|
271
|
+
const next = extraStart + extraLength + commentLength;
|
|
272
|
+
if (next > bytes.length) throw new ZipError("invalid_archive", "ZIP central directory is truncated.");
|
|
273
|
+
for (let e = extraStart; e + 4 <= extraStart + extraLength; ) {
|
|
274
|
+
const id = readU16(bytes, e);
|
|
275
|
+
const len = readU16(bytes, e + 2);
|
|
276
|
+
if (id === 1) {
|
|
277
|
+
let f = e + 4;
|
|
278
|
+
const end = f + len;
|
|
279
|
+
if (size === 4294967295 && f + 8 <= end) {
|
|
280
|
+
size = readU64(bytes, f);
|
|
281
|
+
f += 8;
|
|
282
|
+
}
|
|
283
|
+
if (compressedSize === 4294967295 && f + 8 <= end) {
|
|
284
|
+
compressedSize = readU64(bytes, f);
|
|
285
|
+
f += 8;
|
|
286
|
+
}
|
|
287
|
+
if (localHeaderOffset === 4294967295 && f + 8 <= end) localHeaderOffset = readU64(bytes, f);
|
|
288
|
+
}
|
|
289
|
+
e += 4 + len;
|
|
290
|
+
}
|
|
291
|
+
const rawName = decodeName(bytes.subarray(nameStart, extraStart), (flags & 2048) !== 0);
|
|
292
|
+
const name = rawName.replace(/\\/g, "/");
|
|
293
|
+
p = next;
|
|
294
|
+
if (isUnsafeZipPath(rawName)) {
|
|
295
|
+
if (options.unsafePaths === "skip") continue;
|
|
296
|
+
throw new ZipError("unsafe_path", `ZIP entry name "${rawName}" is absolute or escapes the archive root.`, {
|
|
297
|
+
entryName: rawName
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
entries.push({
|
|
301
|
+
name,
|
|
302
|
+
isDirectory: name.endsWith("/"),
|
|
303
|
+
encrypted: (flags & 1) !== 0,
|
|
304
|
+
method,
|
|
305
|
+
compressedSize,
|
|
306
|
+
size,
|
|
307
|
+
crc32,
|
|
308
|
+
localHeaderOffset
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
return new ZipArchive(bytes, entries, maxTotalSize);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
export {
|
|
315
|
+
ZipError,
|
|
316
|
+
DEFAULT_ZIP_MAX_ENTRIES,
|
|
317
|
+
DEFAULT_ZIP_MAX_TOTAL_SIZE,
|
|
318
|
+
zipCrc32,
|
|
319
|
+
isUnsafeZipPath,
|
|
320
|
+
ZipArchive,
|
|
321
|
+
readZip
|
|
322
|
+
};
|
|
323
|
+
//# sourceMappingURL=chunk-33AHNSEB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/import/zip.ts"],"sourcesContent":["/**\n * Minimal, dependency-free ZIP reader used by the DOCX and zipped-export\n * import adapters.\n *\n * - Reads the central directory (including ZIP64 end records and extra\n * fields), so sizes come from the authoritative directory rather than local\n * headers or data descriptors.\n * - Supports stored (method 0) and deflate (method 8) entries; deflate is\n * inflated with the platform `DecompressionStream(\"deflate-raw\")` (modern\n * browsers, Node ≥ 18).\n * - Guards against zip bombs (entry-count and total-uncompressed-size caps,\n * enforced on the bytes actually inflated, not only the declared sizes),\n * path traversal in entry names and encrypted entries.\n * - Verifies CRC-32 checksums of extracted entries.\n */\n\nexport type ZipErrorCode =\n /** Not a ZIP archive, or its directory is truncated / inconsistent. */\n | \"invalid_archive\"\n /** Compression method other than stored/deflate, multi-disk archives, … */\n | \"unsupported_feature\"\n /** The entry is encrypted (general-purpose flag bit 0). */\n | \"encrypted\"\n /** An entry name is absolute or contains `..` segments. */\n | \"unsafe_path\"\n /** More entries than `maxEntries`. */\n | \"too_many_entries\"\n /** Extracting would exceed `maxTotalSize` uncompressed bytes. */\n | \"too_large\"\n /** The entry data is corrupt (bad header, size or CRC mismatch, bad deflate stream). */\n | \"corrupt_entry\"\n /** No entry with the requested name. */\n | \"entry_not_found\"\n /** `DecompressionStream` is unavailable in this environment. */\n | \"unsupported_environment\";\n\nexport class ZipError extends Error {\n readonly code: ZipErrorCode;\n readonly entryName?: string;\n\n constructor(code: ZipErrorCode, message: string, details: { entryName?: string; cause?: unknown } = {}) {\n super(message, details.cause !== undefined ? { cause: details.cause } : undefined);\n this.name = \"ZipError\";\n this.code = code;\n this.entryName = details.entryName;\n }\n}\n\nexport interface ZipEntry {\n /** Entry path with `/` separators (backslashes are normalized). */\n name: string;\n /** Whether the entry is a directory (name ends with `/`). */\n isDirectory: boolean;\n /** Whether the entry is encrypted; reading it throws `ZipError(\"encrypted\")`. */\n encrypted: boolean;\n /** Compression method (0 = stored, 8 = deflate). */\n method: number;\n /** Declared compressed size in bytes. */\n compressedSize: number;\n /** Declared uncompressed size in bytes. */\n size: number;\n /** CRC-32 of the uncompressed data. */\n crc32: number;\n /** Offset of the entry's local file header. */\n localHeaderOffset: number;\n}\n\nexport interface ZipReadOptions {\n /** Maximum number of entries in the central directory (default 10 000). */\n maxEntries?: number;\n /**\n * Maximum number of uncompressed bytes extracted from the archive, summed\n * over every `read` call (default 256 MiB). Enforced while inflating.\n */\n maxTotalSize?: number;\n /**\n * What to do with entries whose names are absolute or contain `..`\n * segments: `\"error\"` (default) rejects the archive, `\"skip\"` leaves them\n * out of `entries`.\n */\n unsafePaths?: \"error\" | \"skip\";\n}\n\nexport const DEFAULT_ZIP_MAX_ENTRIES = 10_000;\nexport const DEFAULT_ZIP_MAX_TOTAL_SIZE = 256 * 1024 * 1024;\n\nconst SIG_EOCD = 0x06054b50;\nconst SIG_ZIP64_EOCD = 0x06064b50;\nconst SIG_ZIP64_LOCATOR = 0x07064b50;\nconst SIG_CENTRAL = 0x02014b50;\nconst SIG_LOCAL = 0x04034b50;\nconst EOCD_SIZE = 22;\nconst MAX_COMMENT = 0xffff;\n\nlet crcTable: Uint32Array | null = null;\n\n/** CRC-32 (IEEE 802.3), as used by ZIP. */\nexport function zipCrc32(data: Uint8Array): number {\n if (!crcTable) {\n crcTable = new Uint32Array(256);\n for (let n = 0; n < 256; n++) {\n let c = n;\n for (let k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;\n crcTable[n] = c >>> 0;\n }\n }\n let crc = 0xffffffff;\n for (let i = 0; i < data.length; i++) crc = crcTable[(crc ^ data[i]) & 0xff] ^ (crc >>> 8);\n return (crc ^ 0xffffffff) >>> 0;\n}\n\nfunction toBytes(data: ArrayBuffer | ArrayBufferView): Uint8Array {\n // Duck-typed so ArrayBuffers from other realms (iframes, jsdom) work too.\n if (ArrayBuffer.isView(data)) return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);\n return new Uint8Array(data as ArrayBuffer);\n}\n\n/** Whether `name` is absolute, has a drive letter, or contains `..` / NUL. */\nexport function isUnsafeZipPath(name: string): boolean {\n if (!name || name.includes(\"\\0\")) return true;\n const normalized = name.replace(/\\\\/g, \"/\");\n if (normalized.startsWith(\"/\") || /^[a-zA-Z]:/.test(normalized)) return true;\n return normalized.split(\"/\").some((segment) => segment === \"..\");\n}\n\nconst utf8 = new TextDecoder(\"utf-8\");\n\n/** CP437 high half, used for names without the UTF-8 flag. */\nconst CP437_HIGH =\n \"ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ \";\n\nfunction decodeName(bytes: Uint8Array, isUtf8: boolean): string {\n if (isUtf8 || bytes.every((b) => b < 0x80)) return utf8.decode(bytes);\n let out = \"\";\n for (const b of bytes) out += b < 0x80 ? String.fromCharCode(b) : CP437_HIGH[b - 0x80];\n return out;\n}\n\n/**\n * A parsed ZIP archive. Entry data is extracted lazily with {@link read}.\n * Create it with {@link readZip}.\n */\nexport class ZipArchive {\n /** Entries in central-directory order. */\n readonly entries: readonly ZipEntry[];\n private readonly byName = new Map<string, ZipEntry>();\n private extracted = 0;\n\n constructor(\n private readonly bytes: Uint8Array,\n entries: ZipEntry[],\n private readonly maxTotalSize: number,\n ) {\n this.entries = entries;\n entries.forEach((entry) => {\n if (!this.byName.has(entry.name)) this.byName.set(entry.name, entry);\n });\n }\n\n /** Looks up an entry by exact name (a leading `/` is ignored). */\n get(name: string): ZipEntry | undefined {\n return this.byName.get(name.replace(/^\\/+/, \"\"));\n }\n\n has(name: string): boolean {\n return !!this.get(name);\n }\n\n /** Uncompressed bytes extracted so far (counted against `maxTotalSize`). */\n get extractedSize(): number {\n return this.extracted;\n }\n\n /** Extracts an entry's data, verifying its size and CRC-32. */\n async read(entryOrName: ZipEntry | string): Promise<Uint8Array> {\n const entry = typeof entryOrName === \"string\" ? this.get(entryOrName) : entryOrName;\n if (!entry) {\n throw new ZipError(\"entry_not_found\", `ZIP entry \"${String(entryOrName)}\" not found.`, {\n entryName: String(entryOrName),\n });\n }\n const name = entry.name;\n if (entry.encrypted) {\n throw new ZipError(\"encrypted\", `ZIP entry \"${name}\" is encrypted; encrypted archives are not supported.`, {\n entryName: name,\n });\n }\n if (entry.isDirectory) return new Uint8Array(0);\n const remaining = this.maxTotalSize - this.extracted;\n if (entry.size > remaining) {\n throw new ZipError(\n \"too_large\",\n `Extracting \"${name}\" (${entry.size} bytes) would exceed the ${this.maxTotalSize}-byte limit.`,\n { entryName: name },\n );\n }\n\n const { bytes } = this;\n const offset = entry.localHeaderOffset;\n if (offset + 30 > bytes.length || readU32(bytes, offset) !== SIG_LOCAL) {\n throw new ZipError(\"corrupt_entry\", `ZIP entry \"${name}\" has no valid local header.`, { entryName: name });\n }\n const dataStart = offset + 30 + readU16(bytes, offset + 26) + readU16(bytes, offset + 28);\n const dataEnd = dataStart + entry.compressedSize;\n if (dataEnd > bytes.length) {\n throw new ZipError(\"corrupt_entry\", `ZIP entry \"${name}\" is truncated.`, { entryName: name });\n }\n const raw = bytes.subarray(dataStart, dataEnd);\n\n let data: Uint8Array;\n if (entry.method === 0) {\n if (entry.compressedSize !== entry.size) {\n throw new ZipError(\"corrupt_entry\", `Stored ZIP entry \"${name}\" has inconsistent sizes.`, { entryName: name });\n }\n data = raw.slice();\n } else if (entry.method === 8) {\n // Cap at the declared size: more output means a lying header (or a bomb).\n data = await inflateRaw(raw, entry.size, name);\n } else {\n throw new ZipError(\n \"unsupported_feature\",\n `ZIP entry \"${name}\" uses unsupported compression method ${entry.method}; only stored and deflate are supported.`,\n { entryName: name },\n );\n }\n if (data.length !== entry.size) {\n throw new ZipError(\"corrupt_entry\", `ZIP entry \"${name}\" size does not match the directory.`, { entryName: name });\n }\n this.extracted += data.length;\n if (zipCrc32(data) !== entry.crc32) {\n throw new ZipError(\"corrupt_entry\", `ZIP entry \"${name}\" failed its CRC-32 check.`, { entryName: name });\n }\n return data;\n }\n\n /** Extracts an entry and decodes it as UTF-8 (a leading BOM is removed). */\n async readText(entryOrName: ZipEntry | string): Promise<string> {\n const text = utf8.decode(await this.read(entryOrName));\n return text.charCodeAt(0) === 0xfeff ? text.slice(1) : text;\n }\n}\n\nfunction readU16(bytes: Uint8Array, offset: number): number {\n return bytes[offset] | (bytes[offset + 1] << 8);\n}\n\nfunction readU32(bytes: Uint8Array, offset: number): number {\n return (bytes[offset] | (bytes[offset + 1] << 8) | (bytes[offset + 2] << 16) | (bytes[offset + 3] << 24)) >>> 0;\n}\n\nfunction readU64(bytes: Uint8Array, offset: number): number {\n const value = readU32(bytes, offset) + readU32(bytes, offset + 4) * 0x100000000;\n if (!Number.isSafeInteger(value)) {\n throw new ZipError(\"unsupported_feature\", \"ZIP64 value exceeds the supported range.\");\n }\n return value;\n}\n\n/** Inflates a raw deflate stream, failing as soon as output exceeds `limit` bytes. */\nasync function inflateRaw(raw: Uint8Array, limit: number, entryName: string): Promise<Uint8Array> {\n const Stream: typeof DecompressionStream | undefined = (globalThis as any).DecompressionStream;\n if (typeof Stream !== \"function\") {\n throw new ZipError(\n \"unsupported_environment\",\n \"Inflating ZIP entries needs DecompressionStream (modern browsers, Node 18+).\",\n { entryName },\n );\n }\n const stream = new Stream(\"deflate-raw\");\n const writer = stream.writable.getWriter();\n const reader = stream.readable.getReader();\n // Feed the input in slices so output is pulled (and checked) incrementally.\n const CHUNK = 64 * 1024;\n const feeding = (async () => {\n for (let i = 0; i < raw.length; i += CHUNK) await writer.write(raw.subarray(i, i + CHUNK) as unknown as BufferSource);\n await writer.close();\n })();\n feeding.catch(() => {});\n\n const chunks: Uint8Array[] = [];\n let total = 0;\n try {\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n total += value.length;\n if (total > limit) {\n throw new ZipError(\n \"corrupt_entry\",\n `ZIP entry \"${entryName}\" inflates beyond its declared size of ${limit} bytes.`,\n { entryName },\n );\n }\n chunks.push(value);\n }\n } catch (error) {\n reader.cancel().catch(() => {});\n writer.abort().catch(() => {});\n if (error instanceof ZipError) throw error;\n throw new ZipError(\"corrupt_entry\", `ZIP entry \"${entryName}\" has an invalid deflate stream.`, {\n entryName,\n cause: error,\n });\n }\n await feeding.catch(() => {});\n const out = new Uint8Array(total);\n let pos = 0;\n for (const chunk of chunks) {\n out.set(chunk, pos);\n pos += chunk.length;\n }\n return out;\n}\n\nfunction findEndOfCentralDirectory(bytes: Uint8Array): number {\n const min = Math.max(0, bytes.length - EOCD_SIZE - MAX_COMMENT);\n for (let i = bytes.length - EOCD_SIZE; i >= min; i--) {\n if (readU32(bytes, i) === SIG_EOCD && i + EOCD_SIZE + readU16(bytes, i + 20) <= bytes.length) return i;\n }\n return -1;\n}\n\n/**\n * Parses a ZIP archive's central directory. Entry data is not extracted until\n * {@link ZipArchive.read} is called. Throws {@link ZipError}.\n */\nexport async function readZip(data: ArrayBuffer | ArrayBufferView, options: ZipReadOptions = {}): Promise<ZipArchive> {\n const bytes = toBytes(data);\n const maxEntries = options.maxEntries ?? DEFAULT_ZIP_MAX_ENTRIES;\n const maxTotalSize = options.maxTotalSize ?? DEFAULT_ZIP_MAX_TOTAL_SIZE;\n\n const eocd = findEndOfCentralDirectory(bytes);\n if (eocd < 0) throw new ZipError(\"invalid_archive\", \"Not a ZIP archive (no end of central directory record).\");\n\n let diskNumber = readU16(bytes, eocd + 4);\n let cdDisk = readU16(bytes, eocd + 6);\n let count = readU16(bytes, eocd + 10);\n let cdSize = readU32(bytes, eocd + 12);\n let cdOffset = readU32(bytes, eocd + 16);\n\n if (count === 0xffff || cdSize === 0xffffffff || cdOffset === 0xffffffff) {\n const locator = eocd - 20;\n if (locator < 0 || readU32(bytes, locator) !== SIG_ZIP64_LOCATOR) {\n throw new ZipError(\"invalid_archive\", \"ZIP64 archive is missing its end of central directory locator.\");\n }\n const record = readU64(bytes, locator + 8);\n if (record + 56 > bytes.length || readU32(bytes, record) !== SIG_ZIP64_EOCD) {\n throw new ZipError(\"invalid_archive\", \"ZIP64 end of central directory record not found.\");\n }\n diskNumber = readU32(bytes, record + 16);\n cdDisk = readU32(bytes, record + 20);\n count = readU64(bytes, record + 32);\n cdSize = readU64(bytes, record + 40);\n cdOffset = readU64(bytes, record + 48);\n }\n if (diskNumber !== 0 || cdDisk !== 0) {\n throw new ZipError(\"unsupported_feature\", \"Multi-disk (spanned) ZIP archives are not supported.\");\n }\n if (count > maxEntries) {\n throw new ZipError(\"too_many_entries\", `ZIP archive has ${count} entries; the limit is ${maxEntries}.`);\n }\n if (cdOffset + cdSize > bytes.length) {\n throw new ZipError(\"invalid_archive\", \"ZIP central directory lies outside the file.\");\n }\n\n const entries: ZipEntry[] = [];\n let p = cdOffset;\n for (let i = 0; i < count; i++) {\n if (p + 46 > bytes.length || readU32(bytes, p) !== SIG_CENTRAL) {\n throw new ZipError(\"invalid_archive\", \"ZIP central directory is corrupt.\");\n }\n const flags = readU16(bytes, p + 8);\n const method = readU16(bytes, p + 10);\n const crc32 = readU32(bytes, p + 16);\n let compressedSize = readU32(bytes, p + 20);\n let size = readU32(bytes, p + 24);\n const nameLength = readU16(bytes, p + 28);\n const extraLength = readU16(bytes, p + 30);\n const commentLength = readU16(bytes, p + 32);\n let localHeaderOffset = readU32(bytes, p + 42);\n const nameStart = p + 46;\n const extraStart = nameStart + nameLength;\n const next = extraStart + extraLength + commentLength;\n if (next > bytes.length) throw new ZipError(\"invalid_archive\", \"ZIP central directory is truncated.\");\n\n // ZIP64 extended information: only the fields that overflowed are present, in order.\n for (let e = extraStart; e + 4 <= extraStart + extraLength; ) {\n const id = readU16(bytes, e);\n const len = readU16(bytes, e + 2);\n if (id === 0x0001) {\n let f = e + 4;\n const end = f + len;\n if (size === 0xffffffff && f + 8 <= end) {\n size = readU64(bytes, f);\n f += 8;\n }\n if (compressedSize === 0xffffffff && f + 8 <= end) {\n compressedSize = readU64(bytes, f);\n f += 8;\n }\n if (localHeaderOffset === 0xffffffff && f + 8 <= end) localHeaderOffset = readU64(bytes, f);\n }\n e += 4 + len;\n }\n\n const rawName = decodeName(bytes.subarray(nameStart, extraStart), (flags & 0x0800) !== 0);\n const name = rawName.replace(/\\\\/g, \"/\");\n p = next;\n if (isUnsafeZipPath(rawName)) {\n if (options.unsafePaths === \"skip\") continue;\n throw new ZipError(\"unsafe_path\", `ZIP entry name \"${rawName}\" is absolute or escapes the archive root.`, {\n entryName: rawName,\n });\n }\n entries.push({\n name,\n isDirectory: name.endsWith(\"/\"),\n encrypted: (flags & 0x0001) !== 0,\n method,\n compressedSize,\n size,\n crc32,\n localHeaderOffset,\n });\n }\n return new ZipArchive(bytes, entries, maxTotalSize);\n}\n"],"mappings":"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","names":[]}
|