ooxml-core 1.6.1 → 1.6.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/dist/{PptxHandler-BTXB54UC.mjs → PptxHandler-BL4B7CZO.mjs} +2 -2
- package/dist/automation/index.cjs +1 -1
- package/dist/automation/index.mjs +1 -1
- package/dist/{chunk-CS7HRNHL.mjs → chunk-GAGSCAR3.mjs} +43 -43
- package/dist/{chunk-5CJRDY7Q.mjs → chunk-NIHPA63A.mjs} +1 -1
- package/dist/{chunk-Q5LESLDA.mjs → chunk-TTPZITQN.mjs} +841 -614
- package/dist/{chunk-4L4UB3RQ.mjs → chunk-Z7IQR4S4.mjs} +3 -3
- package/dist/{chunk-RIFVZP2S.mjs → chunk-ZAP5WLEN.mjs} +1 -1
- package/dist/crypto/index.cjs +281 -109
- package/dist/crypto/index.mjs +281 -109
- package/dist/docx/load/index.cjs +481 -254
- package/dist/docx/load/index.mjs +481 -254
- package/dist/pptx/automation/index.cjs +1388 -1154
- package/dist/pptx/automation/index.d.ts +1 -1
- package/dist/pptx/automation/index.mjs +5 -5
- package/dist/pptx/chunks/{index-DkHgeV1p.d.ts → index-Cn-GzYGp.d.ts} +62 -13
- package/dist/pptx/chunks/{index-DkHgeV1p.d.ts.map → index-Cn-GzYGp.d.ts.map} +1 -1
- package/dist/pptx/cli/index.cjs +1267 -1088
- package/dist/pptx/cli/index.mjs +4 -4
- package/dist/pptx/converter/index.mjs +2 -2
- package/dist/pptx/index.cjs +1408 -1174
- package/dist/pptx/index.d.ts +1 -1
- package/dist/pptx/index.mjs +5 -5
- package/dist/visio/index.cjs +482 -232
- package/dist/visio/index.mjs +482 -232
- package/dist/xlsx/load/index.cjs +415 -188
- package/dist/xlsx/load/index.mjs +415 -188
- package/package.json +5 -5
package/dist/crypto/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// ../../node_modules/.bun/@christophervr+ole2@0.
|
|
1
|
+
// ../../node_modules/.bun/@christophervr+ole2@0.13.0/node_modules/@christophervr/ole2/dist/ole2-parser-types.js
|
|
2
2
|
var OLE_MAGIC = new Uint8Array([208, 207, 17, 224, 161, 177, 26, 225]);
|
|
3
3
|
var ENDOFCHAIN = 4294967294;
|
|
4
4
|
var FREESECT = 4294967295;
|
|
@@ -6,7 +6,9 @@ var FATSECT = 4294967293;
|
|
|
6
6
|
var DIFSECT = 4294967292;
|
|
7
7
|
var MAXREGSECT = 4294967290;
|
|
8
8
|
var ENTRY_TYPE_EMPTY = 0;
|
|
9
|
+
var ENTRY_TYPE_STORAGE = 1;
|
|
9
10
|
var ENTRY_TYPE_STREAM = 2;
|
|
11
|
+
var NOSTREAM = 4294967295;
|
|
10
12
|
var ENTRY_TYPE_ROOT = 5;
|
|
11
13
|
var DIR_ENTRY_SIZE = 128;
|
|
12
14
|
var Ole2ParseError = class extends Error {
|
|
@@ -16,10 +18,174 @@ var Ole2ParseError = class extends Error {
|
|
|
16
18
|
}
|
|
17
19
|
};
|
|
18
20
|
|
|
19
|
-
// ../../node_modules/.bun/@christophervr+ole2@0.
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const
|
|
21
|
+
// ../../node_modules/.bun/@christophervr+ole2@0.13.0/node_modules/@christophervr/ole2/dist/ole2-directory.js
|
|
22
|
+
var FILETIME_UNIX_EPOCH = 116444736000000000n;
|
|
23
|
+
function readFileTime(view, offset) {
|
|
24
|
+
const ticks = view.getBigUint64(offset, true);
|
|
25
|
+
if (ticks === 0n)
|
|
26
|
+
return void 0;
|
|
27
|
+
const ms = Number((ticks - FILETIME_UNIX_EPOCH) / 10000n);
|
|
28
|
+
const date = new Date(ms);
|
|
29
|
+
return Number.isNaN(date.getTime()) ? void 0 : date;
|
|
30
|
+
}
|
|
31
|
+
function decodeSlot(dir, id, majorVersion, warnings) {
|
|
32
|
+
const view = new DataView(dir.buffer, dir.byteOffset + id * DIR_ENTRY_SIZE, DIR_ENTRY_SIZE);
|
|
33
|
+
const nameLen = view.getUint16(64, true);
|
|
34
|
+
const type = view.getUint8(66);
|
|
35
|
+
const nameValid = nameLen >= 2 && nameLen <= 64 && nameLen % 2 === 0 && view.getUint16(nameLen - 2, true) === 0;
|
|
36
|
+
let name = "";
|
|
37
|
+
if (nameValid)
|
|
38
|
+
for (let j = 0; j < nameLen - 2; j += 2)
|
|
39
|
+
name += String.fromCharCode(view.getUint16(j, true));
|
|
40
|
+
const link = (offset) => {
|
|
41
|
+
const value = view.getUint32(offset, true);
|
|
42
|
+
return value === NOSTREAM ? -1 : value;
|
|
43
|
+
};
|
|
44
|
+
const sizeLow = view.getUint32(120, true);
|
|
45
|
+
const sizeHigh = view.getUint32(124, true);
|
|
46
|
+
let size = sizeLow;
|
|
47
|
+
if (majorVersion === 4)
|
|
48
|
+
size = sizeLow + sizeHigh * 4294967296;
|
|
49
|
+
else if (sizeHigh !== 0 && type !== ENTRY_TYPE_EMPTY) {
|
|
50
|
+
warnings.push({ code: "size-high-bits", message: `Ignored v3 stream-size high bits on directory entry ${id}` });
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
id,
|
|
54
|
+
type,
|
|
55
|
+
nameValid,
|
|
56
|
+
entry: {
|
|
57
|
+
id,
|
|
58
|
+
name,
|
|
59
|
+
type,
|
|
60
|
+
color: view.getUint8(67),
|
|
61
|
+
leftSiblingId: link(68),
|
|
62
|
+
rightSiblingId: link(72),
|
|
63
|
+
childId: link(76),
|
|
64
|
+
clsid: new Uint8Array(view.buffer.slice(view.byteOffset + 80, view.byteOffset + 96)),
|
|
65
|
+
stateBits: view.getUint32(96, true),
|
|
66
|
+
created: readFileTime(view, 100),
|
|
67
|
+
modified: readFileTime(view, 108),
|
|
68
|
+
startSector: view.getUint32(116, true),
|
|
69
|
+
size,
|
|
70
|
+
parentId: -1
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function readDirectory(dir, majorVersion, strict, warnings) {
|
|
75
|
+
const count = Math.floor(dir.length / DIR_ENTRY_SIZE);
|
|
76
|
+
const slots = [];
|
|
77
|
+
for (let id = 0; id < count; id++)
|
|
78
|
+
slots.push(decodeSlot(dir, id, majorVersion, warnings));
|
|
79
|
+
const roots = slots.filter((slot) => slot.type === ENTRY_TYPE_ROOT);
|
|
80
|
+
if (roots.length !== 1 || !roots[0].nameValid)
|
|
81
|
+
throw new Ole2ParseError("Invalid root directory entry");
|
|
82
|
+
const root = roots[0];
|
|
83
|
+
root.entry.path = [];
|
|
84
|
+
const reached = /* @__PURE__ */ new Set([root.id]);
|
|
85
|
+
const fail = (message) => {
|
|
86
|
+
if (strict)
|
|
87
|
+
throw new Ole2ParseError(message);
|
|
88
|
+
warnings.push({ code: "directory-link", message });
|
|
89
|
+
};
|
|
90
|
+
const pending = [];
|
|
91
|
+
const push = (id, parent, from) => {
|
|
92
|
+
if (id === -1)
|
|
93
|
+
return;
|
|
94
|
+
const target = slots[id];
|
|
95
|
+
if (!target || target.type === ENTRY_TYPE_EMPTY || target.type === ENTRY_TYPE_ROOT) {
|
|
96
|
+
fail(`Directory entry ${from} links to invalid entry ${id}`);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (reached.has(id)) {
|
|
100
|
+
fail(`Cyclic directory tree at entry ${id}`);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
reached.add(id);
|
|
104
|
+
pending.push({ id, parent });
|
|
105
|
+
};
|
|
106
|
+
push(root.entry.childId, root, root.id);
|
|
107
|
+
while (pending.length) {
|
|
108
|
+
const { id, parent } = pending.pop();
|
|
109
|
+
const slot = slots[id];
|
|
110
|
+
if (!slot.nameValid)
|
|
111
|
+
throw new Ole2ParseError("Invalid directory entry name");
|
|
112
|
+
slot.entry.parentId = parent.id;
|
|
113
|
+
slot.entry.path = [...parent.entry.path, slot.entry.name];
|
|
114
|
+
push(slot.entry.leftSiblingId, parent, id);
|
|
115
|
+
push(slot.entry.rightSiblingId, parent, id);
|
|
116
|
+
if (slot.type === ENTRY_TYPE_STORAGE)
|
|
117
|
+
push(slot.entry.childId, slot, id);
|
|
118
|
+
}
|
|
119
|
+
const entries = [];
|
|
120
|
+
for (const slot of slots) {
|
|
121
|
+
if (slot.type === ENTRY_TYPE_EMPTY)
|
|
122
|
+
continue;
|
|
123
|
+
if (!reached.has(slot.id)) {
|
|
124
|
+
if (!slot.nameValid) {
|
|
125
|
+
if (strict)
|
|
126
|
+
throw new Ole2ParseError("Invalid directory entry name");
|
|
127
|
+
warnings.push({ code: "invalid-unreachable-entry", message: `Skipped undecodable stale directory entry ${slot.id}` });
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
if (strict)
|
|
131
|
+
throw new Ole2ParseError(`Directory entry ${slot.id} is not reachable from the root`);
|
|
132
|
+
warnings.push({ code: "unreachable-entry", message: `Directory entry ${slot.id} (${slot.entry.name}) is not reachable from the root` });
|
|
133
|
+
}
|
|
134
|
+
entries.push(slot.entry);
|
|
135
|
+
}
|
|
136
|
+
return entries;
|
|
137
|
+
}
|
|
138
|
+
function sameName(a, b) {
|
|
139
|
+
return a.length === b.length && a.toUpperCase() === b.toUpperCase();
|
|
140
|
+
}
|
|
141
|
+
function bareName(name) {
|
|
142
|
+
return name.replace(/^[\u0001-\u0006]/, "");
|
|
143
|
+
}
|
|
144
|
+
function normalizePath(path, rootName) {
|
|
145
|
+
const parts = typeof path === "string" ? path.split("/").filter((part) => part !== "") : [...path];
|
|
146
|
+
if (parts.length && sameName(parts[0], rootName) && typeof path === "string")
|
|
147
|
+
parts.shift();
|
|
148
|
+
return parts;
|
|
149
|
+
}
|
|
150
|
+
function child(entries, parentId, name) {
|
|
151
|
+
const children = entries.filter((entry) => entry.parentId === parentId && entry.path !== void 0);
|
|
152
|
+
const pick = (matches) => matches.length === 1 ? matches[0] : void 0;
|
|
153
|
+
const exact = children.filter((entry) => entry.name === name);
|
|
154
|
+
if (exact.length)
|
|
155
|
+
return pick(exact);
|
|
156
|
+
const folded = children.filter((entry) => sameName(entry.name, name));
|
|
157
|
+
if (folded.length)
|
|
158
|
+
return pick(folded);
|
|
159
|
+
return pick(children.filter((entry) => sameName(bareName(entry.name), bareName(name))));
|
|
160
|
+
}
|
|
161
|
+
function findDirectoryEntry(entries, path) {
|
|
162
|
+
const root = entries.find((entry) => entry.type === ENTRY_TYPE_ROOT);
|
|
163
|
+
if (!root)
|
|
164
|
+
return void 0;
|
|
165
|
+
let current = root;
|
|
166
|
+
for (const name of normalizePath(path, root.name)) {
|
|
167
|
+
if (current.type !== ENTRY_TYPE_ROOT && current.type !== ENTRY_TYPE_STORAGE)
|
|
168
|
+
return void 0;
|
|
169
|
+
current = child(entries, current.id, name);
|
|
170
|
+
if (!current)
|
|
171
|
+
return void 0;
|
|
172
|
+
}
|
|
173
|
+
return current;
|
|
174
|
+
}
|
|
175
|
+
function findStreamByName(entries, name, isReadable) {
|
|
176
|
+
const root = entries.find((entry) => entry.type === ENTRY_TYPE_ROOT);
|
|
177
|
+
if (root && root.name === name)
|
|
178
|
+
return root;
|
|
179
|
+
const top = entries.filter((entry) => entry.parentId === root?.id && isReadable(entry));
|
|
180
|
+
return top.find((entry) => entry.name === name) ?? top.find((entry) => sameName(entry.name, name)) ?? entries.find((entry) => entry.name === name && isReadable(entry));
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// ../../node_modules/.bun/@christophervr+ole2@0.13.0/node_modules/@christophervr/ole2/dist/ole2-parser-read.js
|
|
184
|
+
function parseOle2(buffer, options = {}) {
|
|
185
|
+
const strict = options.strict === true;
|
|
186
|
+
const data = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
|
|
187
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
188
|
+
const warnings = [];
|
|
23
189
|
if (data.length < 512) {
|
|
24
190
|
throw new Ole2ParseError("Truncated OLE2 compound file header");
|
|
25
191
|
}
|
|
@@ -28,11 +194,12 @@ function parseOle2(buffer) {
|
|
|
28
194
|
throw new Ole2ParseError("Not a valid OLE2 compound file");
|
|
29
195
|
}
|
|
30
196
|
}
|
|
31
|
-
view.getUint16(24, true);
|
|
32
197
|
const majorVersion = view.getUint16(26, true);
|
|
33
198
|
const byteOrder = view.getUint16(28, true);
|
|
34
199
|
if (byteOrder !== 65534) {
|
|
35
|
-
|
|
200
|
+
if (strict)
|
|
201
|
+
throw new Ole2ParseError("Invalid byte order mark");
|
|
202
|
+
warnings.push({ code: "byte-order", message: `Ignored byte order mark 0x${byteOrder.toString(16)}` });
|
|
36
203
|
}
|
|
37
204
|
const sectorSizePower = view.getUint16(30, true);
|
|
38
205
|
const miniSectorSizePower = view.getUint16(32, true);
|
|
@@ -41,10 +208,14 @@ function parseOle2(buffer) {
|
|
|
41
208
|
}
|
|
42
209
|
const sectorSize = 1 << sectorSizePower;
|
|
43
210
|
const miniSectorSize = 1 << miniSectorSizePower;
|
|
44
|
-
if (data.length < sectorSize
|
|
211
|
+
if (data.length < sectorSize)
|
|
45
212
|
throw new Ole2ParseError("Truncated OLE2 sector");
|
|
213
|
+
if (data.length % sectorSize !== 0) {
|
|
214
|
+
if (strict)
|
|
215
|
+
throw new Ole2ParseError("Truncated OLE2 sector");
|
|
216
|
+
warnings.push({ code: "unaligned-length", message: `File length ${data.length} is not a multiple of ${sectorSize}` });
|
|
46
217
|
}
|
|
47
|
-
const sectorCount = data.length / sectorSize - 1;
|
|
218
|
+
const sectorCount = Math.ceil(data.length / sectorSize) - 1;
|
|
48
219
|
const totalFATSectors = view.getUint32(44, true);
|
|
49
220
|
const firstDirectorySector = view.getUint32(48, true);
|
|
50
221
|
const miniStreamCutoff = view.getUint32(56, true);
|
|
@@ -65,6 +236,13 @@ function parseOle2(buffer) {
|
|
|
65
236
|
}
|
|
66
237
|
return data.subarray(offset, offset + sectorSize);
|
|
67
238
|
}
|
|
239
|
+
function copySector(sector, target, at, want) {
|
|
240
|
+
const offset = sectorOffset(sector);
|
|
241
|
+
if (sector >= sectorCount || offset + want > data.length) {
|
|
242
|
+
throw new Ole2ParseError(`Sector ${sector} at offset ${offset} exceeds file size ${data.length}`);
|
|
243
|
+
}
|
|
244
|
+
target.set(data.subarray(offset, offset + want), at);
|
|
245
|
+
}
|
|
68
246
|
const fatSectors = [];
|
|
69
247
|
for (let i2 = 0; i2 < 109 && fatSectors.length < totalFATSectors; i2++) {
|
|
70
248
|
const sector = view.getUint32(76 + i2 * 4, true);
|
|
@@ -100,29 +278,36 @@ function parseOle2(buffer) {
|
|
|
100
278
|
fatEntries.push(fatView.getUint32(i2 * 4, true));
|
|
101
279
|
}
|
|
102
280
|
}
|
|
103
|
-
function
|
|
104
|
-
const
|
|
105
|
-
let current = startSector;
|
|
281
|
+
function followChain(table, start, label, needed) {
|
|
282
|
+
const ids = [];
|
|
106
283
|
const visited = /* @__PURE__ */ new Set();
|
|
284
|
+
let current = start;
|
|
107
285
|
while (current <= MAXREGSECT) {
|
|
286
|
+
if (!strict && needed !== void 0 && ids.length >= needed)
|
|
287
|
+
return ids;
|
|
108
288
|
if (visited.has(current)) {
|
|
109
|
-
throw new Ole2ParseError(`Circular reference in
|
|
289
|
+
throw new Ole2ParseError(`Circular reference in ${label} chain at sector ${current}`);
|
|
110
290
|
}
|
|
111
291
|
visited.add(current);
|
|
112
|
-
|
|
113
|
-
if (
|
|
114
|
-
throw new Ole2ParseError(
|
|
115
|
-
current =
|
|
292
|
+
ids.push(current);
|
|
293
|
+
if (table[current] === void 0)
|
|
294
|
+
throw new Ole2ParseError(`Missing ${label} chain entry`);
|
|
295
|
+
current = table[current];
|
|
116
296
|
}
|
|
117
|
-
if (current !== ENDOFCHAIN)
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
for (const sector of sectors) {
|
|
123
|
-
result.set(sector, offset);
|
|
124
|
-
offset += sectorSize;
|
|
297
|
+
if (current !== ENDOFCHAIN) {
|
|
298
|
+
if (strict || needed === void 0 || ids.length < needed) {
|
|
299
|
+
throw new Ole2ParseError(`Invalid ${label} chain terminator`);
|
|
300
|
+
}
|
|
301
|
+
warnings.push({ code: "chain-terminator", message: `Accepted ${label} chain ending in 0x${current.toString(16)}` });
|
|
125
302
|
}
|
|
303
|
+
return ids;
|
|
304
|
+
}
|
|
305
|
+
function readMetadataChain(startSector, label) {
|
|
306
|
+
if (startSector > MAXREGSECT)
|
|
307
|
+
return new Uint8Array(0);
|
|
308
|
+
const ids = followChain(fatEntries, startSector, label === "directory" ? "FAT" : label);
|
|
309
|
+
const result = new Uint8Array(ids.length * sectorSize);
|
|
310
|
+
ids.forEach((id, i2) => result.set(readSector(id), i2 * sectorSize));
|
|
126
311
|
return result;
|
|
127
312
|
}
|
|
128
313
|
function readStream(startSector, size) {
|
|
@@ -130,68 +315,44 @@ function parseOle2(buffer) {
|
|
|
130
315
|
return new Uint8Array(0);
|
|
131
316
|
if (size > sectorCount * sectorSize)
|
|
132
317
|
throw new Ole2ParseError("Stream size exceeds file size");
|
|
133
|
-
const
|
|
134
|
-
|
|
318
|
+
const needed = Math.ceil(size / sectorSize);
|
|
319
|
+
const ids = followChain(fatEntries, startSector, "FAT", needed);
|
|
320
|
+
if (ids.length < needed)
|
|
135
321
|
throw new Ole2ParseError("Truncated stream sector chain");
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
const numEntries = Math.floor(dirRaw.length / DIR_ENTRY_SIZE);
|
|
140
|
-
const entries = [];
|
|
141
|
-
for (let i2 = 0; i2 < numEntries; i2++) {
|
|
142
|
-
const entryOffset = i2 * DIR_ENTRY_SIZE;
|
|
143
|
-
const entryView = new DataView(dirRaw.buffer, dirRaw.byteOffset + entryOffset, DIR_ENTRY_SIZE);
|
|
144
|
-
const nameLen = entryView.getUint16(64, true);
|
|
145
|
-
const objectType = entryView.getUint8(66);
|
|
146
|
-
if (objectType === ENTRY_TYPE_EMPTY) {
|
|
147
|
-
continue;
|
|
322
|
+
const result = new Uint8Array(size);
|
|
323
|
+
for (let i2 = 0; i2 < needed; i2++) {
|
|
324
|
+
copySector(ids[i2], result, i2 * sectorSize, Math.min(sectorSize, size - i2 * sectorSize));
|
|
148
325
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
const leftSiblingId = entryView.getUint32(68, true);
|
|
158
|
-
const rightSiblingId = entryView.getUint32(72, true);
|
|
159
|
-
const childId = entryView.getUint32(76, true);
|
|
160
|
-
const clsid = new Uint8Array(entryView.buffer.slice(entryView.byteOffset + 80, entryView.byteOffset + 96));
|
|
161
|
-
const startSector = entryView.getUint32(116, true);
|
|
162
|
-
const sizeLow = entryView.getUint32(120, true);
|
|
163
|
-
let size = sizeLow;
|
|
164
|
-
if (majorVersion === 4) {
|
|
165
|
-
const sizeHigh = entryView.getUint32(124, true);
|
|
166
|
-
size = sizeLow + sizeHigh * 4294967296;
|
|
167
|
-
if (!Number.isSafeInteger(size) || size > sectorCount * sectorSize) {
|
|
168
|
-
throw new Ole2ParseError("Stream size exceeds supported file bounds");
|
|
169
|
-
}
|
|
326
|
+
return result;
|
|
327
|
+
}
|
|
328
|
+
if (firstDirectorySector > MAXREGSECT)
|
|
329
|
+
throw new Ole2ParseError("Missing directory chain");
|
|
330
|
+
const entries = readDirectory(readMetadataChain(firstDirectorySector, "directory"), majorVersion, strict, warnings);
|
|
331
|
+
for (const entry of entries) {
|
|
332
|
+
if (majorVersion === 4 && (!Number.isSafeInteger(entry.size) || entry.size > sectorCount * sectorSize)) {
|
|
333
|
+
throw new Ole2ParseError("Stream size exceeds supported file bounds");
|
|
170
334
|
}
|
|
171
|
-
entries.push({
|
|
172
|
-
name,
|
|
173
|
-
type: objectType,
|
|
174
|
-
startSector,
|
|
175
|
-
size,
|
|
176
|
-
childId: childId === 4294967295 ? -1 : childId,
|
|
177
|
-
leftSiblingId: leftSiblingId === 4294967295 ? -1 : leftSiblingId,
|
|
178
|
-
rightSiblingId: rightSiblingId === 4294967295 ? -1 : rightSiblingId,
|
|
179
|
-
clsid
|
|
180
|
-
});
|
|
181
335
|
}
|
|
182
336
|
const rootEntry = entries.find((e) => e.type === ENTRY_TYPE_ROOT);
|
|
183
|
-
if (!rootEntry || entries.filter((e) => e.type === ENTRY_TYPE_ROOT).length !== 1) {
|
|
184
|
-
throw new Ole2ParseError("Invalid root directory entry");
|
|
185
|
-
}
|
|
186
337
|
let miniStreamData;
|
|
187
|
-
if (rootEntry
|
|
338
|
+
if (rootEntry.startSector <= MAXREGSECT) {
|
|
188
339
|
miniStreamData = readStream(rootEntry.startSector, rootEntry.size);
|
|
189
340
|
}
|
|
190
341
|
const miniFatEntries = [];
|
|
191
|
-
if (firstMiniFATSector
|
|
192
|
-
|
|
193
|
-
if (miniFatRaw.length !== totalMiniFATSectors * sectorSize) {
|
|
342
|
+
if (firstMiniFATSector > MAXREGSECT && totalMiniFATSectors > 0) {
|
|
343
|
+
if (strict)
|
|
194
344
|
throw new Ole2ParseError("Unexpected mini FAT chain length");
|
|
345
|
+
warnings.push({ code: "mini-fat-count", message: `Header lists ${totalMiniFATSectors} mini FAT sectors but no chain` });
|
|
346
|
+
}
|
|
347
|
+
if (firstMiniFATSector <= MAXREGSECT && (totalMiniFATSectors > 0 || !strict)) {
|
|
348
|
+
const miniFatRaw = readMetadataChain(firstMiniFATSector, "mini FAT");
|
|
349
|
+
if (miniFatRaw.length !== totalMiniFATSectors * sectorSize) {
|
|
350
|
+
if (strict)
|
|
351
|
+
throw new Ole2ParseError("Unexpected mini FAT chain length");
|
|
352
|
+
warnings.push({
|
|
353
|
+
code: "mini-fat-count",
|
|
354
|
+
message: `Header lists ${totalMiniFATSectors} mini FAT sectors; chain has ${miniFatRaw.length / sectorSize}`
|
|
355
|
+
});
|
|
195
356
|
}
|
|
196
357
|
const miniFatView = new DataView(miniFatRaw.buffer, miniFatRaw.byteOffset, miniFatRaw.byteLength);
|
|
197
358
|
const miniCapacity = Math.floor((miniStreamData?.length ?? 0) / miniSectorSize);
|
|
@@ -205,45 +366,56 @@ function parseOle2(buffer) {
|
|
|
205
366
|
if (!miniStreamData) {
|
|
206
367
|
throw new Ole2ParseError("Mini stream container not found");
|
|
207
368
|
}
|
|
208
|
-
const
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
369
|
+
const needed = Math.ceil(size / miniSectorSize);
|
|
370
|
+
const capacity = miniStreamData.length / miniSectorSize;
|
|
371
|
+
let ids;
|
|
372
|
+
try {
|
|
373
|
+
ids = followChain(miniFatEntries, startSector, "mini FAT", needed);
|
|
374
|
+
} catch (error) {
|
|
375
|
+
if (error instanceof Ole2ParseError && /Missing mini FAT/.test(error.message)) {
|
|
376
|
+
throw new Ole2ParseError("Mini stream sector exceeds allocation bounds");
|
|
214
377
|
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
378
|
+
throw error;
|
|
379
|
+
}
|
|
380
|
+
const result = new Uint8Array(size);
|
|
381
|
+
for (let i2 = 0; i2 < ids.length && i2 < needed; i2++) {
|
|
382
|
+
const id = ids[i2];
|
|
383
|
+
if (id >= capacity || (id + 1) * miniSectorSize > miniStreamData.length) {
|
|
218
384
|
throw new Ole2ParseError("Mini stream sector exceeds allocation bounds");
|
|
219
385
|
}
|
|
220
|
-
|
|
221
|
-
|
|
386
|
+
const want = Math.min(miniSectorSize, size - i2 * miniSectorSize);
|
|
387
|
+
result.set(miniStreamData.subarray(id * miniSectorSize, id * miniSectorSize + want), i2 * miniSectorSize);
|
|
222
388
|
}
|
|
223
|
-
if (
|
|
224
|
-
throw new Ole2ParseError("Invalid mini FAT chain terminator");
|
|
225
|
-
const totalLength = sectors.length * miniSectorSize;
|
|
226
|
-
if (totalLength < size)
|
|
389
|
+
if (ids.length < needed)
|
|
227
390
|
throw new Ole2ParseError("Truncated mini stream sector chain");
|
|
228
|
-
|
|
229
|
-
let offset = 0;
|
|
230
|
-
for (const sector of sectors) {
|
|
231
|
-
result.set(sector, offset);
|
|
232
|
-
offset += miniSectorSize;
|
|
233
|
-
}
|
|
234
|
-
return result.subarray(0, size);
|
|
391
|
+
return result;
|
|
235
392
|
}
|
|
236
|
-
function
|
|
237
|
-
const entry = entries.find((e) => (e.type === ENTRY_TYPE_STREAM || e.type === ENTRY_TYPE_ROOT) && e.name === name);
|
|
238
|
-
if (!entry) {
|
|
239
|
-
return void 0;
|
|
240
|
-
}
|
|
393
|
+
function readEntry(entry) {
|
|
241
394
|
if (entry.size < miniStreamCutoff && entry.type !== ENTRY_TYPE_ROOT) {
|
|
242
395
|
return readMiniStream(entry.startSector, entry.size);
|
|
243
396
|
}
|
|
244
397
|
return readStream(entry.startSector, entry.size);
|
|
245
398
|
}
|
|
246
|
-
|
|
399
|
+
const readable = (entry) => entry.type === ENTRY_TYPE_STREAM || entry.type === ENTRY_TYPE_ROOT;
|
|
400
|
+
return {
|
|
401
|
+
entries,
|
|
402
|
+
warnings,
|
|
403
|
+
getStream(name) {
|
|
404
|
+
const entry = findStreamByName(entries, name, readable);
|
|
405
|
+
return entry ? readEntry(entry) : void 0;
|
|
406
|
+
},
|
|
407
|
+
getStreamByPath(path) {
|
|
408
|
+
const entry = findDirectoryEntry(entries, path);
|
|
409
|
+
return entry && entry.type === ENTRY_TYPE_STREAM ? readEntry(entry) : void 0;
|
|
410
|
+
},
|
|
411
|
+
getStreamById(id) {
|
|
412
|
+
const entry = entries.find((candidate) => candidate.id === id);
|
|
413
|
+
return entry && readable(entry) ? readEntry(entry) : void 0;
|
|
414
|
+
},
|
|
415
|
+
findEntry(path) {
|
|
416
|
+
return findDirectoryEntry(entries, path);
|
|
417
|
+
}
|
|
418
|
+
};
|
|
247
419
|
}
|
|
248
420
|
|
|
249
421
|
// crypto/uuid.ts
|
|
@@ -263,7 +435,7 @@ function createOfficeGuid() {
|
|
|
263
435
|
return `{${uuid.toUpperCase()}}`;
|
|
264
436
|
}
|
|
265
437
|
|
|
266
|
-
// ../../node_modules/.bun/@christophervr+ole2@0.
|
|
438
|
+
// ../../node_modules/.bun/@christophervr+ole2@0.13.0/node_modules/@christophervr/ole2/dist/utils/ooxml-crypto-primitives.js
|
|
267
439
|
function getSubtle() {
|
|
268
440
|
if (typeof globalThis.crypto !== "undefined" && globalThis.crypto.subtle) {
|
|
269
441
|
return globalThis.crypto.subtle;
|
|
@@ -2417,7 +2589,7 @@ var EncryptedFileError = class extends Error {
|
|
|
2417
2589
|
}
|
|
2418
2590
|
};
|
|
2419
2591
|
|
|
2420
|
-
// ../../node_modules/.bun/@christophervr+ole2@0.
|
|
2592
|
+
// ../../node_modules/.bun/@christophervr+ole2@0.13.0/node_modules/@christophervr/ole2/dist/ole2-parser-write-helpers.js
|
|
2421
2593
|
function compareDirEntryNames(a, b) {
|
|
2422
2594
|
const ua = a.toUpperCase();
|
|
2423
2595
|
const ub = b.toUpperCase();
|
|
@@ -2484,7 +2656,7 @@ function writeInt32Sectors(outBytes, int32Data, firstSector, numSectors, sectorS
|
|
|
2484
2656
|
}
|
|
2485
2657
|
}
|
|
2486
2658
|
|
|
2487
|
-
// ../../node_modules/.bun/@christophervr+ole2@0.
|
|
2659
|
+
// ../../node_modules/.bun/@christophervr+ole2@0.13.0/node_modules/@christophervr/ole2/dist/ole2-parser-write-serialize.js
|
|
2488
2660
|
function writeHeader(outView, outBytes, params) {
|
|
2489
2661
|
outBytes.set(OLE_MAGIC, 0);
|
|
2490
2662
|
outView.setUint16(24, 62, true);
|
|
@@ -2577,7 +2749,7 @@ function writeStreamSectors(outBytes, streamData, chain, sectorSize) {
|
|
|
2577
2749
|
}
|
|
2578
2750
|
}
|
|
2579
2751
|
|
|
2580
|
-
// ../../node_modules/.bun/@christophervr+ole2@0.
|
|
2752
|
+
// ../../node_modules/.bun/@christophervr+ole2@0.13.0/node_modules/@christophervr/ole2/dist/ole2-parser-write.js
|
|
2581
2753
|
function buildOle2(streams2, rootClsid, miniStreamCutoff = 4096) {
|
|
2582
2754
|
const sectorSize = 512;
|
|
2583
2755
|
const miniSectorSize = 64;
|