ooxml-core 0.12.0 → 0.13.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/dist/crypto/index.cjs +118 -31
- package/dist/crypto/index.mjs +118 -31
- package/dist/docx/load/index.cjs +1273 -110
- package/dist/docx/load/index.mjs +1273 -110
- package/dist/docx/load/legacy-doc.d.ts.map +1 -1
- package/dist/pptx/automation/index.cjs +1479 -304
- package/dist/pptx/automation/index.d.ts +1 -1
- package/dist/pptx/automation/index.mjs +1479 -304
- package/dist/pptx/chunks/{index-LoCVDu8Z.d.ts → index-CT9y69AZ.d.ts} +22 -12
- package/dist/pptx/chunks/index-CT9y69AZ.d.ts.map +1 -0
- package/dist/pptx/cli/index.cjs +307 -152
- package/dist/pptx/cli/index.mjs +307 -152
- package/dist/pptx/index.cjs +1479 -304
- package/dist/pptx/index.d.ts +1 -1
- package/dist/pptx/index.mjs +1479 -304
- package/dist/visio/index.cjs +7498 -127
- package/dist/visio/index.d.ts +3 -1
- package/dist/visio/index.d.ts.map +1 -1
- package/dist/visio/index.mjs +7497 -128
- package/dist/visio/legacy.d.ts +10 -0
- package/dist/visio/legacy.d.ts.map +1 -0
- package/dist/visio/load.d.ts +5 -0
- package/dist/visio/load.d.ts.map +1 -0
- package/dist/visio/model.d.ts +1 -1
- package/dist/visio/model.d.ts.map +1 -1
- package/dist/xlsx/load/index.cjs +144 -52
- package/dist/xlsx/load/index.mjs +144 -52
- package/package.json +2 -2
- package/dist/pptx/chunks/index-LoCVDu8Z.d.ts.map +0 -1
package/dist/crypto/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
3
|
+
// node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/ole2-parser-types.js
|
|
4
4
|
var OLE_MAGIC = new Uint8Array([208, 207, 17, 224, 161, 177, 26, 225]);
|
|
5
5
|
var ENDOFCHAIN = 4294967294;
|
|
6
6
|
var FREESECT = 4294967295;
|
|
@@ -18,10 +18,13 @@ var Ole2ParseError = class extends Error {
|
|
|
18
18
|
}
|
|
19
19
|
};
|
|
20
20
|
|
|
21
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
21
|
+
// node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/ole2-parser-read.js
|
|
22
22
|
function parseOle2(buffer) {
|
|
23
23
|
const data = new Uint8Array(buffer);
|
|
24
24
|
const view = new DataView(buffer);
|
|
25
|
+
if (data.length < 512) {
|
|
26
|
+
throw new Ole2ParseError("Truncated OLE2 compound file header");
|
|
27
|
+
}
|
|
25
28
|
for (let i = 0; i < OLE_MAGIC.length; i++) {
|
|
26
29
|
if (data[i] !== OLE_MAGIC[i]) {
|
|
27
30
|
throw new Ole2ParseError("Not a valid OLE2 compound file");
|
|
@@ -35,8 +38,15 @@ function parseOle2(buffer) {
|
|
|
35
38
|
}
|
|
36
39
|
const sectorSizePower = view.getUint16(30, true);
|
|
37
40
|
const miniSectorSizePower = view.getUint16(32, true);
|
|
41
|
+
if (majorVersion !== 3 && majorVersion !== 4 || sectorSizePower !== (majorVersion === 3 ? 9 : 12) || miniSectorSizePower !== 6) {
|
|
42
|
+
throw new Ole2ParseError("Unsupported OLE2 version or sector size");
|
|
43
|
+
}
|
|
38
44
|
const sectorSize = 1 << sectorSizePower;
|
|
39
45
|
const miniSectorSize = 1 << miniSectorSizePower;
|
|
46
|
+
if (data.length < sectorSize || data.length % sectorSize !== 0) {
|
|
47
|
+
throw new Ole2ParseError("Truncated OLE2 sector");
|
|
48
|
+
}
|
|
49
|
+
const sectorCount = data.length / sectorSize - 1;
|
|
40
50
|
const totalFATSectors = view.getUint32(44, true);
|
|
41
51
|
const firstDirectorySector = view.getUint32(48, true);
|
|
42
52
|
const miniStreamCutoff = view.getUint32(56, true);
|
|
@@ -44,6 +54,9 @@ function parseOle2(buffer) {
|
|
|
44
54
|
const totalMiniFATSectors = view.getUint32(64, true);
|
|
45
55
|
const firstDIFATSector = view.getUint32(68, true);
|
|
46
56
|
const totalDIFATSectors = view.getUint32(72, true);
|
|
57
|
+
if (totalFATSectors > sectorCount || totalMiniFATSectors > sectorCount || totalDIFATSectors > sectorCount) {
|
|
58
|
+
throw new Ole2ParseError("Allocation table count exceeds file size");
|
|
59
|
+
}
|
|
47
60
|
function sectorOffset(sector) {
|
|
48
61
|
return (sector + 1) * sectorSize;
|
|
49
62
|
}
|
|
@@ -62,7 +75,11 @@ function parseOle2(buffer) {
|
|
|
62
75
|
}
|
|
63
76
|
}
|
|
64
77
|
let difatSector = firstDIFATSector;
|
|
78
|
+
const difatSeen = /* @__PURE__ */ new Set();
|
|
65
79
|
for (let d = 0; d < totalDIFATSectors && difatSector <= MAXREGSECT; d++) {
|
|
80
|
+
if (difatSeen.has(difatSector))
|
|
81
|
+
throw new Ole2ParseError("Circular DIFAT chain");
|
|
82
|
+
difatSeen.add(difatSector);
|
|
66
83
|
const difatData = readSector(difatSector);
|
|
67
84
|
const difatView = new DataView(difatData.buffer, difatData.byteOffset, difatData.byteLength);
|
|
68
85
|
const entriesPerSector = (sectorSize - 4) / 4;
|
|
@@ -74,11 +91,14 @@ function parseOle2(buffer) {
|
|
|
74
91
|
}
|
|
75
92
|
difatSector = difatView.getUint32(sectorSize - 4, true);
|
|
76
93
|
}
|
|
94
|
+
if (difatSeen.size !== totalDIFATSectors || fatSectors.length !== totalFATSectors || new Set(fatSectors).size !== fatSectors.length || fatSectors.some((id) => difatSeen.has(id))) {
|
|
95
|
+
throw new Ole2ParseError("Invalid DIFAT allocation table");
|
|
96
|
+
}
|
|
77
97
|
const fatEntries = [];
|
|
78
98
|
for (const fatSector of fatSectors) {
|
|
79
99
|
const fatData = readSector(fatSector);
|
|
80
100
|
const fatView = new DataView(fatData.buffer, fatData.byteOffset, fatData.byteLength);
|
|
81
|
-
for (let i = 0; i < sectorSize / 4; i++) {
|
|
101
|
+
for (let i = 0; i < sectorSize / 4 && fatEntries.length < sectorCount; i++) {
|
|
82
102
|
fatEntries.push(fatView.getUint32(i * 4, true));
|
|
83
103
|
}
|
|
84
104
|
}
|
|
@@ -92,8 +112,12 @@ function parseOle2(buffer) {
|
|
|
92
112
|
}
|
|
93
113
|
visited.add(current);
|
|
94
114
|
sectors.push(readSector(current));
|
|
95
|
-
|
|
115
|
+
if (fatEntries[current] === void 0)
|
|
116
|
+
throw new Ole2ParseError("Missing FAT chain entry");
|
|
117
|
+
current = fatEntries[current];
|
|
96
118
|
}
|
|
119
|
+
if (current !== ENDOFCHAIN)
|
|
120
|
+
throw new Ole2ParseError("Invalid FAT chain terminator");
|
|
97
121
|
const totalLength = sectors.length * sectorSize;
|
|
98
122
|
const result = new Uint8Array(totalLength);
|
|
99
123
|
let offset = 0;
|
|
@@ -104,16 +128,14 @@ function parseOle2(buffer) {
|
|
|
104
128
|
return result;
|
|
105
129
|
}
|
|
106
130
|
function readStream(startSector, size) {
|
|
131
|
+
if (size === 0)
|
|
132
|
+
return new Uint8Array(0);
|
|
133
|
+
if (size > sectorCount * sectorSize)
|
|
134
|
+
throw new Ole2ParseError("Stream size exceeds file size");
|
|
107
135
|
const raw = readSectorChain(startSector);
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
if (firstMiniFATSector <= MAXREGSECT && totalMiniFATSectors > 0) {
|
|
112
|
-
const miniFatRaw = readSectorChain(firstMiniFATSector);
|
|
113
|
-
const miniFatView = new DataView(miniFatRaw.buffer, miniFatRaw.byteOffset, miniFatRaw.byteLength);
|
|
114
|
-
for (let i = 0; i < miniFatRaw.length / 4; i++) {
|
|
115
|
-
miniFatEntries.push(miniFatView.getUint32(i * 4, true));
|
|
116
|
-
}
|
|
136
|
+
if (raw.length < size)
|
|
137
|
+
throw new Ole2ParseError("Truncated stream sector chain");
|
|
138
|
+
return raw.subarray(0, size);
|
|
117
139
|
}
|
|
118
140
|
const dirRaw = readSectorChain(firstDirectorySector);
|
|
119
141
|
const numEntries = Math.floor(dirRaw.length / DIR_ENTRY_SIZE);
|
|
@@ -126,6 +148,9 @@ function parseOle2(buffer) {
|
|
|
126
148
|
if (objectType === ENTRY_TYPE_EMPTY) {
|
|
127
149
|
continue;
|
|
128
150
|
}
|
|
151
|
+
if (nameLen < 2 || nameLen > 64 || nameLen % 2 !== 0 || entryView.getUint16(nameLen - 2, true) !== 0) {
|
|
152
|
+
throw new Ole2ParseError("Invalid directory entry name");
|
|
153
|
+
}
|
|
129
154
|
const nameBytes = Math.max(0, nameLen - 2);
|
|
130
155
|
let name = "";
|
|
131
156
|
for (let j = 0; j < nameBytes; j += 2) {
|
|
@@ -139,8 +164,11 @@ function parseOle2(buffer) {
|
|
|
139
164
|
const sizeLow = entryView.getUint32(120, true);
|
|
140
165
|
let size = sizeLow;
|
|
141
166
|
if (majorVersion === 4) {
|
|
142
|
-
entryView.getUint32(124, true);
|
|
143
|
-
size = sizeLow;
|
|
167
|
+
const sizeHigh = entryView.getUint32(124, true);
|
|
168
|
+
size = sizeLow + sizeHigh * 4294967296;
|
|
169
|
+
if (!Number.isSafeInteger(size) || size > sectorCount * sectorSize) {
|
|
170
|
+
throw new Ole2ParseError("Stream size exceeds supported file bounds");
|
|
171
|
+
}
|
|
144
172
|
}
|
|
145
173
|
entries.push({
|
|
146
174
|
name,
|
|
@@ -154,11 +182,28 @@ function parseOle2(buffer) {
|
|
|
154
182
|
});
|
|
155
183
|
}
|
|
156
184
|
const rootEntry = entries.find((e) => e.type === ENTRY_TYPE_ROOT);
|
|
185
|
+
if (!rootEntry || entries.filter((e) => e.type === ENTRY_TYPE_ROOT).length !== 1) {
|
|
186
|
+
throw new Ole2ParseError("Invalid root directory entry");
|
|
187
|
+
}
|
|
157
188
|
let miniStreamData;
|
|
158
189
|
if (rootEntry && rootEntry.startSector <= MAXREGSECT) {
|
|
159
|
-
miniStreamData =
|
|
190
|
+
miniStreamData = readStream(rootEntry.startSector, rootEntry.size);
|
|
191
|
+
}
|
|
192
|
+
const miniFatEntries = [];
|
|
193
|
+
if (firstMiniFATSector <= MAXREGSECT && totalMiniFATSectors > 0) {
|
|
194
|
+
const miniFatRaw = readSectorChain(firstMiniFATSector);
|
|
195
|
+
if (miniFatRaw.length !== totalMiniFATSectors * sectorSize) {
|
|
196
|
+
throw new Ole2ParseError("Unexpected mini FAT chain length");
|
|
197
|
+
}
|
|
198
|
+
const miniFatView = new DataView(miniFatRaw.buffer, miniFatRaw.byteOffset, miniFatRaw.byteLength);
|
|
199
|
+
const miniCapacity = Math.floor((miniStreamData?.length ?? 0) / miniSectorSize);
|
|
200
|
+
for (let i = 0; i < miniFatRaw.length / 4 && i < miniCapacity; i++) {
|
|
201
|
+
miniFatEntries.push(miniFatView.getUint32(i * 4, true));
|
|
202
|
+
}
|
|
160
203
|
}
|
|
161
204
|
function readMiniStream(startSector, size) {
|
|
205
|
+
if (size === 0)
|
|
206
|
+
return new Uint8Array(0);
|
|
162
207
|
if (!miniStreamData) {
|
|
163
208
|
throw new Ole2ParseError("Mini stream container not found");
|
|
164
209
|
}
|
|
@@ -171,17 +216,24 @@ function parseOle2(buffer) {
|
|
|
171
216
|
}
|
|
172
217
|
visited.add(current);
|
|
173
218
|
const offset2 = current * miniSectorSize;
|
|
219
|
+
if (offset2 + miniSectorSize > miniStreamData.length || miniFatEntries[current] === void 0) {
|
|
220
|
+
throw new Ole2ParseError("Mini stream sector exceeds allocation bounds");
|
|
221
|
+
}
|
|
174
222
|
sectors.push(miniStreamData.subarray(offset2, offset2 + miniSectorSize));
|
|
175
|
-
current = miniFatEntries[current]
|
|
223
|
+
current = miniFatEntries[current];
|
|
176
224
|
}
|
|
225
|
+
if (current !== ENDOFCHAIN)
|
|
226
|
+
throw new Ole2ParseError("Invalid mini FAT chain terminator");
|
|
177
227
|
const totalLength = sectors.length * miniSectorSize;
|
|
228
|
+
if (totalLength < size)
|
|
229
|
+
throw new Ole2ParseError("Truncated mini stream sector chain");
|
|
178
230
|
const result = new Uint8Array(totalLength);
|
|
179
231
|
let offset = 0;
|
|
180
232
|
for (const sector of sectors) {
|
|
181
233
|
result.set(sector, offset);
|
|
182
234
|
offset += miniSectorSize;
|
|
183
235
|
}
|
|
184
|
-
return result.subarray(0,
|
|
236
|
+
return result.subarray(0, size);
|
|
185
237
|
}
|
|
186
238
|
function getStream(name) {
|
|
187
239
|
const entry = entries.find((e) => (e.type === ENTRY_TYPE_STREAM || e.type === ENTRY_TYPE_ROOT) && e.name === name);
|
|
@@ -196,7 +248,7 @@ function parseOle2(buffer) {
|
|
|
196
248
|
return { entries, getStream };
|
|
197
249
|
}
|
|
198
250
|
|
|
199
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
251
|
+
// node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/utils/ooxml-crypto-primitives.js
|
|
200
252
|
function getSubtle() {
|
|
201
253
|
if (typeof globalThis.crypto !== "undefined" && globalThis.crypto.subtle) {
|
|
202
254
|
return globalThis.crypto.subtle;
|
|
@@ -1128,13 +1180,16 @@ var EncryptedFileError = class extends Error {
|
|
|
1128
1180
|
}
|
|
1129
1181
|
};
|
|
1130
1182
|
|
|
1131
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
1183
|
+
// node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/ole2-parser-write-helpers.js
|
|
1132
1184
|
function compareDirEntryNames(a, b) {
|
|
1185
|
+
const ua = a.toUpperCase();
|
|
1186
|
+
const ub = b.toUpperCase();
|
|
1187
|
+
if (ua.length !== a.length || ub.length !== b.length) {
|
|
1188
|
+
throw new Error("CFB stream names with expanding uppercase mappings are unsupported");
|
|
1189
|
+
}
|
|
1133
1190
|
if (a.length !== b.length) {
|
|
1134
1191
|
return a.length - b.length;
|
|
1135
1192
|
}
|
|
1136
|
-
const ua = a.toUpperCase();
|
|
1137
|
-
const ub = b.toUpperCase();
|
|
1138
1193
|
for (let i = 0; i < ua.length; i++) {
|
|
1139
1194
|
const diff = ua.charCodeAt(i) - ub.charCodeAt(i);
|
|
1140
1195
|
if (diff !== 0) {
|
|
@@ -1151,6 +1206,24 @@ function encodeName(name) {
|
|
|
1151
1206
|
}
|
|
1152
1207
|
return bytes;
|
|
1153
1208
|
}
|
|
1209
|
+
function buildDirectoryTree(entryCount) {
|
|
1210
|
+
const links = /* @__PURE__ */ new Map();
|
|
1211
|
+
let redLevel = 0;
|
|
1212
|
+
for (let remaining = entryCount - 2; remaining >= 0; remaining = Math.floor(remaining / 2) - 1)
|
|
1213
|
+
redLevel++;
|
|
1214
|
+
const build = (low, high, level) => {
|
|
1215
|
+
if (low > high)
|
|
1216
|
+
return 4294967295;
|
|
1217
|
+
const id = Math.floor((low + high) / 2);
|
|
1218
|
+
links.set(id, {
|
|
1219
|
+
left: build(low, id - 1, level + 1),
|
|
1220
|
+
right: build(id + 1, high, level + 1),
|
|
1221
|
+
color: level === redLevel ? 0 : 1
|
|
1222
|
+
});
|
|
1223
|
+
return id;
|
|
1224
|
+
};
|
|
1225
|
+
return { root: build(1, entryCount - 1, 0), links };
|
|
1226
|
+
}
|
|
1154
1227
|
function writeFatChain(fat, chain) {
|
|
1155
1228
|
for (let i = 0; i < chain.sectors.length; i++) {
|
|
1156
1229
|
fat[chain.sectors[i]] = i < chain.sectors.length - 1 ? chain.sectors[i + 1] : ENDOFCHAIN;
|
|
@@ -1174,7 +1247,7 @@ function writeInt32Sectors(outBytes, int32Data, firstSector, numSectors, sectorS
|
|
|
1174
1247
|
}
|
|
1175
1248
|
}
|
|
1176
1249
|
|
|
1177
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
1250
|
+
// node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/ole2-parser-write-serialize.js
|
|
1178
1251
|
function writeHeader(outView, outBytes, params) {
|
|
1179
1252
|
outBytes.set(OLE_MAGIC, 0);
|
|
1180
1253
|
outView.setUint16(24, 62, true);
|
|
@@ -1232,6 +1305,7 @@ function writeDifatSectors(outView, params) {
|
|
|
1232
1305
|
function serializeDirectoryEntries(dirEntries, numDirSectors, sectorSize) {
|
|
1233
1306
|
const dirData = new Uint8Array(numDirSectors * sectorSize);
|
|
1234
1307
|
const dirView = new DataView(dirData.buffer);
|
|
1308
|
+
const tree = buildDirectoryTree(dirEntries.length);
|
|
1235
1309
|
for (let i = 0; i < dirEntries.length; i++) {
|
|
1236
1310
|
const entry = dirEntries[i];
|
|
1237
1311
|
const entryOffset = i * DIR_ENTRY_SIZE;
|
|
@@ -1239,17 +1313,17 @@ function serializeDirectoryEntries(dirEntries, numDirSectors, sectorSize) {
|
|
|
1239
1313
|
dirData.set(nameBytes.subarray(0, Math.min(nameBytes.length, 64)), entryOffset);
|
|
1240
1314
|
dirView.setUint16(entryOffset + 64, Math.min((entry.name.length + 1) * 2, 64), true);
|
|
1241
1315
|
dirData[entryOffset + 66] = entry.type;
|
|
1242
|
-
dirData[entryOffset + 67] = 1;
|
|
1316
|
+
dirData[entryOffset + 67] = i === 0 ? 1 : tree.links.get(i).color;
|
|
1243
1317
|
if (entry.clsid) {
|
|
1244
1318
|
dirData.set(entry.clsid.subarray(0, 16), entryOffset + 80);
|
|
1245
1319
|
}
|
|
1246
1320
|
if (i === 0) {
|
|
1247
1321
|
dirView.setUint32(entryOffset + 68, 4294967295, true);
|
|
1248
1322
|
dirView.setUint32(entryOffset + 72, 4294967295, true);
|
|
1249
|
-
dirView.setUint32(entryOffset + 76,
|
|
1323
|
+
dirView.setUint32(entryOffset + 76, tree.root, true);
|
|
1250
1324
|
} else {
|
|
1251
|
-
dirView.setUint32(entryOffset + 68,
|
|
1252
|
-
dirView.setUint32(entryOffset + 72, i
|
|
1325
|
+
dirView.setUint32(entryOffset + 68, tree.links.get(i).left, true);
|
|
1326
|
+
dirView.setUint32(entryOffset + 72, tree.links.get(i).right, true);
|
|
1253
1327
|
dirView.setUint32(entryOffset + 76, 4294967295, true);
|
|
1254
1328
|
}
|
|
1255
1329
|
dirView.setUint32(entryOffset + 116, entry.startSector, true);
|
|
@@ -1266,10 +1340,23 @@ function writeStreamSectors(outBytes, streamData, chain, sectorSize) {
|
|
|
1266
1340
|
}
|
|
1267
1341
|
}
|
|
1268
1342
|
|
|
1269
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
1343
|
+
// node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/ole2-parser-write.js
|
|
1270
1344
|
function buildOle2(streams2, rootClsid, miniStreamCutoff = 4096) {
|
|
1271
1345
|
const sectorSize = 512;
|
|
1272
1346
|
const miniSectorSize = 64;
|
|
1347
|
+
const names = [...streams2.keys()].sort(compareDirEntryNames);
|
|
1348
|
+
for (let i = 0; i < names.length; i++) {
|
|
1349
|
+
const name = names[i];
|
|
1350
|
+
if (name.toUpperCase().length !== name.length) {
|
|
1351
|
+
throw new Error("CFB stream names with expanding uppercase mappings are unsupported");
|
|
1352
|
+
}
|
|
1353
|
+
if (!name.length || name.length > 31 || /[\x00\\/:!]/.test(name)) {
|
|
1354
|
+
throw new Error("CFB stream names must be 1-31 UTF-16 code units without NUL, \\, /, :, or !");
|
|
1355
|
+
}
|
|
1356
|
+
if (i > 0 && compareDirEntryNames(names[i - 1], name) === 0) {
|
|
1357
|
+
throw new Error("Duplicate CFB stream names");
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
1273
1360
|
const regularStreams = [];
|
|
1274
1361
|
const miniStreams = [];
|
|
1275
1362
|
for (const [name, data] of streams2) {
|
|
@@ -1287,7 +1374,7 @@ function buildOle2(streams2, rootClsid, miniStreamCutoff = 4096) {
|
|
|
1287
1374
|
for (let i = 0; i < numSectors; i++) {
|
|
1288
1375
|
sectors.push(nextSector++);
|
|
1289
1376
|
}
|
|
1290
|
-
fatChains.set(stream.name, { start: sectors[0] ??
|
|
1377
|
+
fatChains.set(stream.name, { start: sectors[0] ?? ENDOFCHAIN, sectors });
|
|
1291
1378
|
}
|
|
1292
1379
|
let miniStreamContainer = new Uint8Array(0);
|
|
1293
1380
|
const miniFatChains = /* @__PURE__ */ new Map();
|
|
@@ -1310,7 +1397,7 @@ function buildOle2(streams2, rootClsid, miniStreamCutoff = 4096) {
|
|
|
1310
1397
|
miniOffset += miniSectorSize;
|
|
1311
1398
|
}
|
|
1312
1399
|
miniFatChains.set(stream.name, {
|
|
1313
|
-
start: miniSectors[0] ??
|
|
1400
|
+
start: miniSectors[0] ?? ENDOFCHAIN,
|
|
1314
1401
|
sectors: miniSectors
|
|
1315
1402
|
});
|
|
1316
1403
|
}
|
|
@@ -1358,7 +1445,7 @@ function buildOle2(streams2, rootClsid, miniStreamCutoff = 4096) {
|
|
|
1358
1445
|
nextSector += numDirSectors;
|
|
1359
1446
|
let firstMiniFATSector = ENDOFCHAIN;
|
|
1360
1447
|
let numMiniFATSectors = 0;
|
|
1361
|
-
if (
|
|
1448
|
+
if (nextMiniSector > 0) {
|
|
1362
1449
|
numMiniFATSectors = Math.ceil(nextMiniSector * 4 / sectorSize);
|
|
1363
1450
|
firstMiniFATSector = nextSector;
|
|
1364
1451
|
nextSector += numMiniFATSectors;
|
package/dist/crypto/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
1
|
+
// node_modules/.bun/@christophervr+ole2@0.8.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;
|
|
@@ -16,10 +16,13 @@ var Ole2ParseError = class extends Error {
|
|
|
16
16
|
}
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
19
|
+
// node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/ole2-parser-read.js
|
|
20
20
|
function parseOle2(buffer) {
|
|
21
21
|
const data = new Uint8Array(buffer);
|
|
22
22
|
const view = new DataView(buffer);
|
|
23
|
+
if (data.length < 512) {
|
|
24
|
+
throw new Ole2ParseError("Truncated OLE2 compound file header");
|
|
25
|
+
}
|
|
23
26
|
for (let i = 0; i < OLE_MAGIC.length; i++) {
|
|
24
27
|
if (data[i] !== OLE_MAGIC[i]) {
|
|
25
28
|
throw new Ole2ParseError("Not a valid OLE2 compound file");
|
|
@@ -33,8 +36,15 @@ function parseOle2(buffer) {
|
|
|
33
36
|
}
|
|
34
37
|
const sectorSizePower = view.getUint16(30, true);
|
|
35
38
|
const miniSectorSizePower = view.getUint16(32, true);
|
|
39
|
+
if (majorVersion !== 3 && majorVersion !== 4 || sectorSizePower !== (majorVersion === 3 ? 9 : 12) || miniSectorSizePower !== 6) {
|
|
40
|
+
throw new Ole2ParseError("Unsupported OLE2 version or sector size");
|
|
41
|
+
}
|
|
36
42
|
const sectorSize = 1 << sectorSizePower;
|
|
37
43
|
const miniSectorSize = 1 << miniSectorSizePower;
|
|
44
|
+
if (data.length < sectorSize || data.length % sectorSize !== 0) {
|
|
45
|
+
throw new Ole2ParseError("Truncated OLE2 sector");
|
|
46
|
+
}
|
|
47
|
+
const sectorCount = data.length / sectorSize - 1;
|
|
38
48
|
const totalFATSectors = view.getUint32(44, true);
|
|
39
49
|
const firstDirectorySector = view.getUint32(48, true);
|
|
40
50
|
const miniStreamCutoff = view.getUint32(56, true);
|
|
@@ -42,6 +52,9 @@ function parseOle2(buffer) {
|
|
|
42
52
|
const totalMiniFATSectors = view.getUint32(64, true);
|
|
43
53
|
const firstDIFATSector = view.getUint32(68, true);
|
|
44
54
|
const totalDIFATSectors = view.getUint32(72, true);
|
|
55
|
+
if (totalFATSectors > sectorCount || totalMiniFATSectors > sectorCount || totalDIFATSectors > sectorCount) {
|
|
56
|
+
throw new Ole2ParseError("Allocation table count exceeds file size");
|
|
57
|
+
}
|
|
45
58
|
function sectorOffset(sector) {
|
|
46
59
|
return (sector + 1) * sectorSize;
|
|
47
60
|
}
|
|
@@ -60,7 +73,11 @@ function parseOle2(buffer) {
|
|
|
60
73
|
}
|
|
61
74
|
}
|
|
62
75
|
let difatSector = firstDIFATSector;
|
|
76
|
+
const difatSeen = /* @__PURE__ */ new Set();
|
|
63
77
|
for (let d = 0; d < totalDIFATSectors && difatSector <= MAXREGSECT; d++) {
|
|
78
|
+
if (difatSeen.has(difatSector))
|
|
79
|
+
throw new Ole2ParseError("Circular DIFAT chain");
|
|
80
|
+
difatSeen.add(difatSector);
|
|
64
81
|
const difatData = readSector(difatSector);
|
|
65
82
|
const difatView = new DataView(difatData.buffer, difatData.byteOffset, difatData.byteLength);
|
|
66
83
|
const entriesPerSector = (sectorSize - 4) / 4;
|
|
@@ -72,11 +89,14 @@ function parseOle2(buffer) {
|
|
|
72
89
|
}
|
|
73
90
|
difatSector = difatView.getUint32(sectorSize - 4, true);
|
|
74
91
|
}
|
|
92
|
+
if (difatSeen.size !== totalDIFATSectors || fatSectors.length !== totalFATSectors || new Set(fatSectors).size !== fatSectors.length || fatSectors.some((id) => difatSeen.has(id))) {
|
|
93
|
+
throw new Ole2ParseError("Invalid DIFAT allocation table");
|
|
94
|
+
}
|
|
75
95
|
const fatEntries = [];
|
|
76
96
|
for (const fatSector of fatSectors) {
|
|
77
97
|
const fatData = readSector(fatSector);
|
|
78
98
|
const fatView = new DataView(fatData.buffer, fatData.byteOffset, fatData.byteLength);
|
|
79
|
-
for (let i = 0; i < sectorSize / 4; i++) {
|
|
99
|
+
for (let i = 0; i < sectorSize / 4 && fatEntries.length < sectorCount; i++) {
|
|
80
100
|
fatEntries.push(fatView.getUint32(i * 4, true));
|
|
81
101
|
}
|
|
82
102
|
}
|
|
@@ -90,8 +110,12 @@ function parseOle2(buffer) {
|
|
|
90
110
|
}
|
|
91
111
|
visited.add(current);
|
|
92
112
|
sectors.push(readSector(current));
|
|
93
|
-
|
|
113
|
+
if (fatEntries[current] === void 0)
|
|
114
|
+
throw new Ole2ParseError("Missing FAT chain entry");
|
|
115
|
+
current = fatEntries[current];
|
|
94
116
|
}
|
|
117
|
+
if (current !== ENDOFCHAIN)
|
|
118
|
+
throw new Ole2ParseError("Invalid FAT chain terminator");
|
|
95
119
|
const totalLength = sectors.length * sectorSize;
|
|
96
120
|
const result = new Uint8Array(totalLength);
|
|
97
121
|
let offset = 0;
|
|
@@ -102,16 +126,14 @@ function parseOle2(buffer) {
|
|
|
102
126
|
return result;
|
|
103
127
|
}
|
|
104
128
|
function readStream(startSector, size) {
|
|
129
|
+
if (size === 0)
|
|
130
|
+
return new Uint8Array(0);
|
|
131
|
+
if (size > sectorCount * sectorSize)
|
|
132
|
+
throw new Ole2ParseError("Stream size exceeds file size");
|
|
105
133
|
const raw = readSectorChain(startSector);
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
if (firstMiniFATSector <= MAXREGSECT && totalMiniFATSectors > 0) {
|
|
110
|
-
const miniFatRaw = readSectorChain(firstMiniFATSector);
|
|
111
|
-
const miniFatView = new DataView(miniFatRaw.buffer, miniFatRaw.byteOffset, miniFatRaw.byteLength);
|
|
112
|
-
for (let i = 0; i < miniFatRaw.length / 4; i++) {
|
|
113
|
-
miniFatEntries.push(miniFatView.getUint32(i * 4, true));
|
|
114
|
-
}
|
|
134
|
+
if (raw.length < size)
|
|
135
|
+
throw new Ole2ParseError("Truncated stream sector chain");
|
|
136
|
+
return raw.subarray(0, size);
|
|
115
137
|
}
|
|
116
138
|
const dirRaw = readSectorChain(firstDirectorySector);
|
|
117
139
|
const numEntries = Math.floor(dirRaw.length / DIR_ENTRY_SIZE);
|
|
@@ -124,6 +146,9 @@ function parseOle2(buffer) {
|
|
|
124
146
|
if (objectType === ENTRY_TYPE_EMPTY) {
|
|
125
147
|
continue;
|
|
126
148
|
}
|
|
149
|
+
if (nameLen < 2 || nameLen > 64 || nameLen % 2 !== 0 || entryView.getUint16(nameLen - 2, true) !== 0) {
|
|
150
|
+
throw new Ole2ParseError("Invalid directory entry name");
|
|
151
|
+
}
|
|
127
152
|
const nameBytes = Math.max(0, nameLen - 2);
|
|
128
153
|
let name = "";
|
|
129
154
|
for (let j = 0; j < nameBytes; j += 2) {
|
|
@@ -137,8 +162,11 @@ function parseOle2(buffer) {
|
|
|
137
162
|
const sizeLow = entryView.getUint32(120, true);
|
|
138
163
|
let size = sizeLow;
|
|
139
164
|
if (majorVersion === 4) {
|
|
140
|
-
entryView.getUint32(124, true);
|
|
141
|
-
size = sizeLow;
|
|
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
|
+
}
|
|
142
170
|
}
|
|
143
171
|
entries.push({
|
|
144
172
|
name,
|
|
@@ -152,11 +180,28 @@ function parseOle2(buffer) {
|
|
|
152
180
|
});
|
|
153
181
|
}
|
|
154
182
|
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
|
+
}
|
|
155
186
|
let miniStreamData;
|
|
156
187
|
if (rootEntry && rootEntry.startSector <= MAXREGSECT) {
|
|
157
|
-
miniStreamData =
|
|
188
|
+
miniStreamData = readStream(rootEntry.startSector, rootEntry.size);
|
|
189
|
+
}
|
|
190
|
+
const miniFatEntries = [];
|
|
191
|
+
if (firstMiniFATSector <= MAXREGSECT && totalMiniFATSectors > 0) {
|
|
192
|
+
const miniFatRaw = readSectorChain(firstMiniFATSector);
|
|
193
|
+
if (miniFatRaw.length !== totalMiniFATSectors * sectorSize) {
|
|
194
|
+
throw new Ole2ParseError("Unexpected mini FAT chain length");
|
|
195
|
+
}
|
|
196
|
+
const miniFatView = new DataView(miniFatRaw.buffer, miniFatRaw.byteOffset, miniFatRaw.byteLength);
|
|
197
|
+
const miniCapacity = Math.floor((miniStreamData?.length ?? 0) / miniSectorSize);
|
|
198
|
+
for (let i = 0; i < miniFatRaw.length / 4 && i < miniCapacity; i++) {
|
|
199
|
+
miniFatEntries.push(miniFatView.getUint32(i * 4, true));
|
|
200
|
+
}
|
|
158
201
|
}
|
|
159
202
|
function readMiniStream(startSector, size) {
|
|
203
|
+
if (size === 0)
|
|
204
|
+
return new Uint8Array(0);
|
|
160
205
|
if (!miniStreamData) {
|
|
161
206
|
throw new Ole2ParseError("Mini stream container not found");
|
|
162
207
|
}
|
|
@@ -169,17 +214,24 @@ function parseOle2(buffer) {
|
|
|
169
214
|
}
|
|
170
215
|
visited.add(current);
|
|
171
216
|
const offset2 = current * miniSectorSize;
|
|
217
|
+
if (offset2 + miniSectorSize > miniStreamData.length || miniFatEntries[current] === void 0) {
|
|
218
|
+
throw new Ole2ParseError("Mini stream sector exceeds allocation bounds");
|
|
219
|
+
}
|
|
172
220
|
sectors.push(miniStreamData.subarray(offset2, offset2 + miniSectorSize));
|
|
173
|
-
current = miniFatEntries[current]
|
|
221
|
+
current = miniFatEntries[current];
|
|
174
222
|
}
|
|
223
|
+
if (current !== ENDOFCHAIN)
|
|
224
|
+
throw new Ole2ParseError("Invalid mini FAT chain terminator");
|
|
175
225
|
const totalLength = sectors.length * miniSectorSize;
|
|
226
|
+
if (totalLength < size)
|
|
227
|
+
throw new Ole2ParseError("Truncated mini stream sector chain");
|
|
176
228
|
const result = new Uint8Array(totalLength);
|
|
177
229
|
let offset = 0;
|
|
178
230
|
for (const sector of sectors) {
|
|
179
231
|
result.set(sector, offset);
|
|
180
232
|
offset += miniSectorSize;
|
|
181
233
|
}
|
|
182
|
-
return result.subarray(0,
|
|
234
|
+
return result.subarray(0, size);
|
|
183
235
|
}
|
|
184
236
|
function getStream(name) {
|
|
185
237
|
const entry = entries.find((e) => (e.type === ENTRY_TYPE_STREAM || e.type === ENTRY_TYPE_ROOT) && e.name === name);
|
|
@@ -194,7 +246,7 @@ function parseOle2(buffer) {
|
|
|
194
246
|
return { entries, getStream };
|
|
195
247
|
}
|
|
196
248
|
|
|
197
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
249
|
+
// node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/utils/ooxml-crypto-primitives.js
|
|
198
250
|
function getSubtle() {
|
|
199
251
|
if (typeof globalThis.crypto !== "undefined" && globalThis.crypto.subtle) {
|
|
200
252
|
return globalThis.crypto.subtle;
|
|
@@ -1126,13 +1178,16 @@ var EncryptedFileError = class extends Error {
|
|
|
1126
1178
|
}
|
|
1127
1179
|
};
|
|
1128
1180
|
|
|
1129
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
1181
|
+
// node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/ole2-parser-write-helpers.js
|
|
1130
1182
|
function compareDirEntryNames(a, b) {
|
|
1183
|
+
const ua = a.toUpperCase();
|
|
1184
|
+
const ub = b.toUpperCase();
|
|
1185
|
+
if (ua.length !== a.length || ub.length !== b.length) {
|
|
1186
|
+
throw new Error("CFB stream names with expanding uppercase mappings are unsupported");
|
|
1187
|
+
}
|
|
1131
1188
|
if (a.length !== b.length) {
|
|
1132
1189
|
return a.length - b.length;
|
|
1133
1190
|
}
|
|
1134
|
-
const ua = a.toUpperCase();
|
|
1135
|
-
const ub = b.toUpperCase();
|
|
1136
1191
|
for (let i = 0; i < ua.length; i++) {
|
|
1137
1192
|
const diff = ua.charCodeAt(i) - ub.charCodeAt(i);
|
|
1138
1193
|
if (diff !== 0) {
|
|
@@ -1149,6 +1204,24 @@ function encodeName(name) {
|
|
|
1149
1204
|
}
|
|
1150
1205
|
return bytes;
|
|
1151
1206
|
}
|
|
1207
|
+
function buildDirectoryTree(entryCount) {
|
|
1208
|
+
const links = /* @__PURE__ */ new Map();
|
|
1209
|
+
let redLevel = 0;
|
|
1210
|
+
for (let remaining = entryCount - 2; remaining >= 0; remaining = Math.floor(remaining / 2) - 1)
|
|
1211
|
+
redLevel++;
|
|
1212
|
+
const build = (low, high, level) => {
|
|
1213
|
+
if (low > high)
|
|
1214
|
+
return 4294967295;
|
|
1215
|
+
const id = Math.floor((low + high) / 2);
|
|
1216
|
+
links.set(id, {
|
|
1217
|
+
left: build(low, id - 1, level + 1),
|
|
1218
|
+
right: build(id + 1, high, level + 1),
|
|
1219
|
+
color: level === redLevel ? 0 : 1
|
|
1220
|
+
});
|
|
1221
|
+
return id;
|
|
1222
|
+
};
|
|
1223
|
+
return { root: build(1, entryCount - 1, 0), links };
|
|
1224
|
+
}
|
|
1152
1225
|
function writeFatChain(fat, chain) {
|
|
1153
1226
|
for (let i = 0; i < chain.sectors.length; i++) {
|
|
1154
1227
|
fat[chain.sectors[i]] = i < chain.sectors.length - 1 ? chain.sectors[i + 1] : ENDOFCHAIN;
|
|
@@ -1172,7 +1245,7 @@ function writeInt32Sectors(outBytes, int32Data, firstSector, numSectors, sectorS
|
|
|
1172
1245
|
}
|
|
1173
1246
|
}
|
|
1174
1247
|
|
|
1175
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
1248
|
+
// node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/ole2-parser-write-serialize.js
|
|
1176
1249
|
function writeHeader(outView, outBytes, params) {
|
|
1177
1250
|
outBytes.set(OLE_MAGIC, 0);
|
|
1178
1251
|
outView.setUint16(24, 62, true);
|
|
@@ -1230,6 +1303,7 @@ function writeDifatSectors(outView, params) {
|
|
|
1230
1303
|
function serializeDirectoryEntries(dirEntries, numDirSectors, sectorSize) {
|
|
1231
1304
|
const dirData = new Uint8Array(numDirSectors * sectorSize);
|
|
1232
1305
|
const dirView = new DataView(dirData.buffer);
|
|
1306
|
+
const tree = buildDirectoryTree(dirEntries.length);
|
|
1233
1307
|
for (let i = 0; i < dirEntries.length; i++) {
|
|
1234
1308
|
const entry = dirEntries[i];
|
|
1235
1309
|
const entryOffset = i * DIR_ENTRY_SIZE;
|
|
@@ -1237,17 +1311,17 @@ function serializeDirectoryEntries(dirEntries, numDirSectors, sectorSize) {
|
|
|
1237
1311
|
dirData.set(nameBytes.subarray(0, Math.min(nameBytes.length, 64)), entryOffset);
|
|
1238
1312
|
dirView.setUint16(entryOffset + 64, Math.min((entry.name.length + 1) * 2, 64), true);
|
|
1239
1313
|
dirData[entryOffset + 66] = entry.type;
|
|
1240
|
-
dirData[entryOffset + 67] = 1;
|
|
1314
|
+
dirData[entryOffset + 67] = i === 0 ? 1 : tree.links.get(i).color;
|
|
1241
1315
|
if (entry.clsid) {
|
|
1242
1316
|
dirData.set(entry.clsid.subarray(0, 16), entryOffset + 80);
|
|
1243
1317
|
}
|
|
1244
1318
|
if (i === 0) {
|
|
1245
1319
|
dirView.setUint32(entryOffset + 68, 4294967295, true);
|
|
1246
1320
|
dirView.setUint32(entryOffset + 72, 4294967295, true);
|
|
1247
|
-
dirView.setUint32(entryOffset + 76,
|
|
1321
|
+
dirView.setUint32(entryOffset + 76, tree.root, true);
|
|
1248
1322
|
} else {
|
|
1249
|
-
dirView.setUint32(entryOffset + 68,
|
|
1250
|
-
dirView.setUint32(entryOffset + 72, i
|
|
1323
|
+
dirView.setUint32(entryOffset + 68, tree.links.get(i).left, true);
|
|
1324
|
+
dirView.setUint32(entryOffset + 72, tree.links.get(i).right, true);
|
|
1251
1325
|
dirView.setUint32(entryOffset + 76, 4294967295, true);
|
|
1252
1326
|
}
|
|
1253
1327
|
dirView.setUint32(entryOffset + 116, entry.startSector, true);
|
|
@@ -1264,10 +1338,23 @@ function writeStreamSectors(outBytes, streamData, chain, sectorSize) {
|
|
|
1264
1338
|
}
|
|
1265
1339
|
}
|
|
1266
1340
|
|
|
1267
|
-
// node_modules/.bun/@christophervr+ole2@0.
|
|
1341
|
+
// node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/ole2-parser-write.js
|
|
1268
1342
|
function buildOle2(streams2, rootClsid, miniStreamCutoff = 4096) {
|
|
1269
1343
|
const sectorSize = 512;
|
|
1270
1344
|
const miniSectorSize = 64;
|
|
1345
|
+
const names = [...streams2.keys()].sort(compareDirEntryNames);
|
|
1346
|
+
for (let i = 0; i < names.length; i++) {
|
|
1347
|
+
const name = names[i];
|
|
1348
|
+
if (name.toUpperCase().length !== name.length) {
|
|
1349
|
+
throw new Error("CFB stream names with expanding uppercase mappings are unsupported");
|
|
1350
|
+
}
|
|
1351
|
+
if (!name.length || name.length > 31 || /[\x00\\/:!]/.test(name)) {
|
|
1352
|
+
throw new Error("CFB stream names must be 1-31 UTF-16 code units without NUL, \\, /, :, or !");
|
|
1353
|
+
}
|
|
1354
|
+
if (i > 0 && compareDirEntryNames(names[i - 1], name) === 0) {
|
|
1355
|
+
throw new Error("Duplicate CFB stream names");
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1271
1358
|
const regularStreams = [];
|
|
1272
1359
|
const miniStreams = [];
|
|
1273
1360
|
for (const [name, data] of streams2) {
|
|
@@ -1285,7 +1372,7 @@ function buildOle2(streams2, rootClsid, miniStreamCutoff = 4096) {
|
|
|
1285
1372
|
for (let i = 0; i < numSectors; i++) {
|
|
1286
1373
|
sectors.push(nextSector++);
|
|
1287
1374
|
}
|
|
1288
|
-
fatChains.set(stream.name, { start: sectors[0] ??
|
|
1375
|
+
fatChains.set(stream.name, { start: sectors[0] ?? ENDOFCHAIN, sectors });
|
|
1289
1376
|
}
|
|
1290
1377
|
let miniStreamContainer = new Uint8Array(0);
|
|
1291
1378
|
const miniFatChains = /* @__PURE__ */ new Map();
|
|
@@ -1308,7 +1395,7 @@ function buildOle2(streams2, rootClsid, miniStreamCutoff = 4096) {
|
|
|
1308
1395
|
miniOffset += miniSectorSize;
|
|
1309
1396
|
}
|
|
1310
1397
|
miniFatChains.set(stream.name, {
|
|
1311
|
-
start: miniSectors[0] ??
|
|
1398
|
+
start: miniSectors[0] ?? ENDOFCHAIN,
|
|
1312
1399
|
sectors: miniSectors
|
|
1313
1400
|
});
|
|
1314
1401
|
}
|
|
@@ -1356,7 +1443,7 @@ function buildOle2(streams2, rootClsid, miniStreamCutoff = 4096) {
|
|
|
1356
1443
|
nextSector += numDirSectors;
|
|
1357
1444
|
let firstMiniFATSector = ENDOFCHAIN;
|
|
1358
1445
|
let numMiniFATSectors = 0;
|
|
1359
|
-
if (
|
|
1446
|
+
if (nextMiniSector > 0) {
|
|
1360
1447
|
numMiniFATSectors = Math.ceil(nextMiniSector * 4 / sectorSize);
|
|
1361
1448
|
firstMiniFATSector = nextSector;
|
|
1362
1449
|
nextSector += numMiniFATSectors;
|