@node-projects/excelforge 2.3.0 → 3.0.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/.github/FUNDING.yml +4 -0
- package/MISSING.md +326 -0
- package/README.md +484 -12
- package/dist/core/SharedStrings.js +6 -2
- package/dist/core/SharedStrings.js.map +1 -1
- package/dist/core/Workbook.d.ts +41 -1
- package/dist/core/Workbook.js +773 -57
- package/dist/core/Workbook.js.map +1 -1
- package/dist/core/WorkbookReader.d.ts +18 -4
- package/dist/core/WorkbookReader.js +1386 -20
- package/dist/core/WorkbookReader.js.map +1 -1
- package/dist/core/Worksheet.d.ts +130 -2
- package/dist/core/Worksheet.js +792 -66
- package/dist/core/Worksheet.js.map +1 -1
- package/dist/core/types.d.ts +287 -5
- package/dist/core/types.js +12 -1
- package/dist/core/types.js.map +1 -1
- package/dist/features/ChartBuilder.d.ts +9 -1
- package/dist/features/ChartBuilder.js +140 -14
- package/dist/features/ChartBuilder.js.map +1 -1
- package/dist/features/CsvModule.d.ts +11 -0
- package/dist/features/CsvModule.js +137 -0
- package/dist/features/CsvModule.js.map +1 -0
- package/dist/features/Encryption.d.ts +6 -0
- package/dist/features/Encryption.js +806 -0
- package/dist/features/Encryption.js.map +1 -0
- package/dist/features/FormControlBuilder.d.ts +6 -0
- package/dist/features/FormControlBuilder.js +135 -0
- package/dist/features/FormControlBuilder.js.map +1 -0
- package/dist/features/FormulaEngine.d.ts +22 -0
- package/dist/features/FormulaEngine.js +498 -0
- package/dist/features/FormulaEngine.js.map +1 -0
- package/dist/features/HtmlModule.d.ts +21 -0
- package/dist/features/HtmlModule.js +1417 -0
- package/dist/features/HtmlModule.js.map +1 -0
- package/dist/features/JsonModule.d.ts +10 -0
- package/dist/features/JsonModule.js +76 -0
- package/dist/features/JsonModule.js.map +1 -0
- package/dist/features/PivotTableBuilder.d.ts +7 -0
- package/dist/features/PivotTableBuilder.js +170 -0
- package/dist/features/PivotTableBuilder.js.map +1 -0
- package/dist/features/Signing.d.ts +12 -0
- package/dist/features/Signing.js +318 -0
- package/dist/features/Signing.js.map +1 -0
- package/dist/features/TableBuilder.js +2 -2
- package/dist/features/TableBuilder.js.map +1 -1
- package/dist/index-min.js +579 -144
- package/dist/index.d.ts +17 -1
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -1
- package/dist/styles/StyleRegistry.d.ts +14 -0
- package/dist/styles/StyleRegistry.js +95 -30
- package/dist/styles/StyleRegistry.js.map +1 -1
- package/dist/utils/helpers.d.ts +4 -0
- package/dist/utils/helpers.js +64 -14
- package/dist/utils/helpers.js.map +1 -1
- package/dist/utils/zip.js +145 -73
- package/dist/utils/zip.js.map +1 -1
- package/dist/vba/VbaProject.d.ts +19 -0
- package/dist/vba/VbaProject.js +281 -0
- package/dist/vba/VbaProject.js.map +1 -0
- package/dist/vba/cfb.d.ts +7 -0
- package/dist/vba/cfb.js +352 -0
- package/dist/vba/cfb.js.map +1 -0
- package/dist/vba/ovba.d.ts +2 -0
- package/dist/vba/ovba.js +137 -0
- package/dist/vba/ovba.js.map +1 -0
- package/package.json +4 -3
- package/validator.cs +0 -155
- package/validatorEpplus.cs +0 -27
- package/validatorReadData.cs +0 -111
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import { compressOvba, decompressOvba } from './ovba.js';
|
|
2
|
+
import { buildCfb, readCfb } from './cfb.js';
|
|
3
|
+
const enc = new TextEncoder();
|
|
4
|
+
const dec = new TextDecoder('utf-8');
|
|
5
|
+
function u16le(v) { return [v & 0xFF, (v >> 8) & 0xFF]; }
|
|
6
|
+
function u32le(v) { return [v & 0xFF, (v >> 8) & 0xFF, (v >> 16) & 0xFF, (v >> 24) & 0xFF]; }
|
|
7
|
+
function readU16(buf, off) { return buf[off] | (buf[off + 1] << 8); }
|
|
8
|
+
function readU32(buf, off) { return (buf[off] | (buf[off + 1] << 8) | (buf[off + 2] << 16) | (buf[off + 3] << 24)) >>> 0; }
|
|
9
|
+
function rec(id, data) {
|
|
10
|
+
const d = data instanceof Uint8Array ? Array.from(data) : data;
|
|
11
|
+
return [...u16le(id), ...u32le(d.length), ...d];
|
|
12
|
+
}
|
|
13
|
+
function toUtf16le(s) {
|
|
14
|
+
const out = [];
|
|
15
|
+
for (const ch of s) {
|
|
16
|
+
const c = ch.charCodeAt(0);
|
|
17
|
+
out.push(c & 0xFF, (c >> 8) & 0xFF);
|
|
18
|
+
}
|
|
19
|
+
return out;
|
|
20
|
+
}
|
|
21
|
+
function moduleAttributes(m) {
|
|
22
|
+
const lines = [
|
|
23
|
+
`Attribute VB_Name = "${m.name}"`,
|
|
24
|
+
];
|
|
25
|
+
if (m.type === 'document') {
|
|
26
|
+
const baseClsid = m.name === 'ThisWorkbook'
|
|
27
|
+
? '0{00020819-0000-0000-C000-000000000046}'
|
|
28
|
+
: '0{00020820-0000-0000-C000-000000000046}';
|
|
29
|
+
lines.push(`Attribute VB_Base = "${baseClsid}"`, 'Attribute VB_GlobalNameSpace = False', 'Attribute VB_Creatable = False', 'Attribute VB_PredeclaredId = True', 'Attribute VB_Exposed = True', 'Attribute VB_TemplateDerived = False', 'Attribute VB_Customizable = True');
|
|
30
|
+
}
|
|
31
|
+
else if (m.type === 'class') {
|
|
32
|
+
lines.push('Attribute VB_GlobalNameSpace = False', 'Attribute VB_Creatable = False', 'Attribute VB_PredeclaredId = False', 'Attribute VB_Exposed = False');
|
|
33
|
+
}
|
|
34
|
+
return lines.join('\r\n') + '\r\n';
|
|
35
|
+
}
|
|
36
|
+
export class VbaProject {
|
|
37
|
+
constructor() {
|
|
38
|
+
this.modules = [];
|
|
39
|
+
this._dirty = false;
|
|
40
|
+
}
|
|
41
|
+
addModule(m) {
|
|
42
|
+
this.modules.push(m);
|
|
43
|
+
this._dirty = true;
|
|
44
|
+
return this;
|
|
45
|
+
}
|
|
46
|
+
removeModule(name) {
|
|
47
|
+
this.modules = this.modules.filter(m => m.name !== name);
|
|
48
|
+
this._dirty = true;
|
|
49
|
+
return this;
|
|
50
|
+
}
|
|
51
|
+
getModule(name) {
|
|
52
|
+
return this.modules.find(m => m.name === name);
|
|
53
|
+
}
|
|
54
|
+
build() {
|
|
55
|
+
if (this._raw && !this._dirty)
|
|
56
|
+
return this._raw;
|
|
57
|
+
const hasThisWorkbook = this.modules.some(m => m.name === 'ThisWorkbook' && m.type === 'document');
|
|
58
|
+
const unsorted = hasThisWorkbook
|
|
59
|
+
? this.modules
|
|
60
|
+
: [{ name: 'ThisWorkbook', type: 'document', code: '' }, ...this.modules];
|
|
61
|
+
const allModules = [
|
|
62
|
+
...unsorted.filter(m => m.type === 'document'),
|
|
63
|
+
...unsorted.filter(m => m.type !== 'document'),
|
|
64
|
+
];
|
|
65
|
+
const moduleStreams = [];
|
|
66
|
+
for (const m of allModules) {
|
|
67
|
+
const src = moduleAttributes(m) + m.code;
|
|
68
|
+
const compressed = compressOvba(enc.encode(src));
|
|
69
|
+
moduleStreams.push({ name: m.name, data: compressed, storage: 'VBA' });
|
|
70
|
+
}
|
|
71
|
+
const vbaProjectStream = {
|
|
72
|
+
name: '_VBA_PROJECT',
|
|
73
|
+
data: new Uint8Array([0xCC, 0x61, 0xFF, 0xFF, 0x00, 0x00, 0x00]),
|
|
74
|
+
storage: 'VBA',
|
|
75
|
+
};
|
|
76
|
+
const dirBytes = this._buildDirStream(allModules);
|
|
77
|
+
const dirCompressed = compressOvba(dirBytes);
|
|
78
|
+
const dirStream = { name: 'dir', data: dirCompressed, storage: 'VBA' };
|
|
79
|
+
const projectText = this._buildProjectText(allModules);
|
|
80
|
+
const projectStream = { name: 'PROJECT', data: enc.encode(projectText) };
|
|
81
|
+
const wmData = this._buildProjectWm(allModules);
|
|
82
|
+
const wmStream = { name: 'PROJECTwm', data: new Uint8Array(wmData) };
|
|
83
|
+
const allStreams = [
|
|
84
|
+
vbaProjectStream, dirStream, ...moduleStreams,
|
|
85
|
+
projectStream, wmStream,
|
|
86
|
+
];
|
|
87
|
+
return buildCfb(allStreams);
|
|
88
|
+
}
|
|
89
|
+
_buildDirStream(modules) {
|
|
90
|
+
const b = [];
|
|
91
|
+
const projectName = 'VBAProject';
|
|
92
|
+
const nameBytes = enc.encode(projectName);
|
|
93
|
+
b.push(...rec(0x0001, u32le(0x00000001)));
|
|
94
|
+
b.push(...rec(0x0002, u32le(0x0409)));
|
|
95
|
+
b.push(...rec(0x0014, u32le(0x0409)));
|
|
96
|
+
b.push(...rec(0x0003, u16le(0x04E4)));
|
|
97
|
+
b.push(...rec(0x0004, Array.from(nameBytes)));
|
|
98
|
+
b.push(...rec(0x0005, []));
|
|
99
|
+
b.push(...rec(0x0040, []));
|
|
100
|
+
b.push(...rec(0x0006, []));
|
|
101
|
+
b.push(...rec(0x003D, []));
|
|
102
|
+
b.push(...rec(0x0007, u32le(0)));
|
|
103
|
+
b.push(...rec(0x0008, u32le(0)));
|
|
104
|
+
b.push(...u16le(0x0009), ...u32le(0x00000004), ...u32le(0x05A3), ...u16le(0x0002));
|
|
105
|
+
b.push(...rec(0x000C, []));
|
|
106
|
+
b.push(...rec(0x003C, []));
|
|
107
|
+
b.push(...rec(0x000F, u16le(modules.length)));
|
|
108
|
+
b.push(...rec(0x0013, u16le(0xFFFF)));
|
|
109
|
+
for (const m of modules) {
|
|
110
|
+
const nameB = enc.encode(m.name);
|
|
111
|
+
const nameU = toUtf16le(m.name);
|
|
112
|
+
b.push(...rec(0x0019, Array.from(nameB)));
|
|
113
|
+
b.push(...rec(0x0047, nameU));
|
|
114
|
+
b.push(...rec(0x001A, Array.from(nameB)));
|
|
115
|
+
b.push(...rec(0x0032, nameU));
|
|
116
|
+
b.push(...rec(0x001C, []));
|
|
117
|
+
b.push(...rec(0x0048, []));
|
|
118
|
+
b.push(...rec(0x0031, u32le(0)));
|
|
119
|
+
b.push(...rec(0x001E, u32le(0)));
|
|
120
|
+
b.push(...rec(0x002C, u16le(0xFFFF)));
|
|
121
|
+
if (m.type === 'document') {
|
|
122
|
+
b.push(...rec(0x0022, []));
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
b.push(...rec(0x0021, []));
|
|
126
|
+
}
|
|
127
|
+
b.push(...rec(0x002B, []));
|
|
128
|
+
}
|
|
129
|
+
b.push(...rec(0x0010, []));
|
|
130
|
+
return new Uint8Array(b);
|
|
131
|
+
}
|
|
132
|
+
_buildProjectText(modules) {
|
|
133
|
+
const lines = [
|
|
134
|
+
'ID="{00000000-0000-0000-0000-000000000000}"',
|
|
135
|
+
];
|
|
136
|
+
const docs = modules.filter(m => m.type === 'document');
|
|
137
|
+
const others = modules.filter(m => m.type !== 'document');
|
|
138
|
+
for (const m of docs) {
|
|
139
|
+
lines.push(`Document=${m.name}/&H00000000`);
|
|
140
|
+
}
|
|
141
|
+
for (const m of others) {
|
|
142
|
+
if (m.type === 'class') {
|
|
143
|
+
lines.push(`Class=${m.name}`);
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
lines.push(`Module=${m.name}`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
lines.push('Name="VBAProject"', 'HelpContextID=0', 'VersionCompatible32="393222000"', '', '[Host Extender Info]', '&H00000001={3832D640-CF90-11CF-8E43-00A0C911005A};VBE;&H00000000', '', '[Workspace]');
|
|
150
|
+
for (const m of [...docs, ...others]) {
|
|
151
|
+
lines.push(`${m.name}=0, 0, 0, 0, C `);
|
|
152
|
+
}
|
|
153
|
+
return lines.join('\r\n') + '\r\n';
|
|
154
|
+
}
|
|
155
|
+
_buildProjectWm(modules) {
|
|
156
|
+
const out = [];
|
|
157
|
+
for (const m of modules) {
|
|
158
|
+
for (const ch of m.name)
|
|
159
|
+
out.push(ch.charCodeAt(0));
|
|
160
|
+
out.push(0);
|
|
161
|
+
for (const ch of m.name) {
|
|
162
|
+
const c = ch.charCodeAt(0);
|
|
163
|
+
out.push(c & 0xFF, (c >> 8) & 0xFF);
|
|
164
|
+
}
|
|
165
|
+
out.push(0, 0);
|
|
166
|
+
}
|
|
167
|
+
out.push(0);
|
|
168
|
+
return out;
|
|
169
|
+
}
|
|
170
|
+
static fromBytes(data) {
|
|
171
|
+
const vba = new VbaProject();
|
|
172
|
+
vba._raw = data;
|
|
173
|
+
const streams = readCfb(data);
|
|
174
|
+
const streamMap = new Map();
|
|
175
|
+
for (const s of streams) {
|
|
176
|
+
const key = s.storage ? `${s.storage}/${s.name}` : s.name;
|
|
177
|
+
streamMap.set(key, s.data);
|
|
178
|
+
}
|
|
179
|
+
const dirCompressed = streamMap.get('VBA/dir');
|
|
180
|
+
if (!dirCompressed)
|
|
181
|
+
return vba;
|
|
182
|
+
let dirData;
|
|
183
|
+
try {
|
|
184
|
+
dirData = decompressOvba(dirCompressed);
|
|
185
|
+
}
|
|
186
|
+
catch {
|
|
187
|
+
return vba;
|
|
188
|
+
}
|
|
189
|
+
const classNames = new Set();
|
|
190
|
+
const projectData = streamMap.get('PROJECT');
|
|
191
|
+
if (projectData) {
|
|
192
|
+
const projectText = dec.decode(projectData);
|
|
193
|
+
for (const line of projectText.split(/\r?\n/)) {
|
|
194
|
+
const m = line.match(/^Class=(.+)$/);
|
|
195
|
+
if (m)
|
|
196
|
+
classNames.add(m[1]);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
const moduleInfos = parseDirStream(dirData);
|
|
200
|
+
for (const info of moduleInfos) {
|
|
201
|
+
const streamKey = `VBA/${info.name}`;
|
|
202
|
+
const streamData = streamMap.get(streamKey);
|
|
203
|
+
if (!streamData)
|
|
204
|
+
continue;
|
|
205
|
+
let code = '';
|
|
206
|
+
try {
|
|
207
|
+
const compressedSource = streamData.subarray(info.offset);
|
|
208
|
+
const decompressed = decompressOvba(compressedSource);
|
|
209
|
+
code = dec.decode(decompressed);
|
|
210
|
+
}
|
|
211
|
+
catch {
|
|
212
|
+
code = dec.decode(streamData.subarray(info.offset));
|
|
213
|
+
}
|
|
214
|
+
const stripped = stripAttributes(code);
|
|
215
|
+
const type = classNames.has(info.name) ? 'class' : info.type;
|
|
216
|
+
vba.modules.push({
|
|
217
|
+
name: info.name,
|
|
218
|
+
type,
|
|
219
|
+
code: stripped,
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
vba._dirty = false;
|
|
223
|
+
return vba;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
function parseDirStream(data) {
|
|
227
|
+
const modules = [];
|
|
228
|
+
let pos = 0;
|
|
229
|
+
let currentModule = null;
|
|
230
|
+
while (pos + 6 <= data.length) {
|
|
231
|
+
const id = readU16(data, pos);
|
|
232
|
+
const size = readU32(data, pos + 2);
|
|
233
|
+
pos += 6;
|
|
234
|
+
if (id === 0x0009) {
|
|
235
|
+
pos += 6;
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
if (pos + size > data.length)
|
|
239
|
+
break;
|
|
240
|
+
const body = data.subarray(pos, pos + size);
|
|
241
|
+
pos += size;
|
|
242
|
+
switch (id) {
|
|
243
|
+
case 0x0019:
|
|
244
|
+
currentModule = {
|
|
245
|
+
name: dec.decode(body),
|
|
246
|
+
type: 'standard',
|
|
247
|
+
offset: 0,
|
|
248
|
+
};
|
|
249
|
+
break;
|
|
250
|
+
case 0x0031:
|
|
251
|
+
if (currentModule && body.length >= 4) {
|
|
252
|
+
currentModule.offset = readU32(body, 0);
|
|
253
|
+
}
|
|
254
|
+
break;
|
|
255
|
+
case 0x0021:
|
|
256
|
+
if (currentModule)
|
|
257
|
+
currentModule.type = 'standard';
|
|
258
|
+
break;
|
|
259
|
+
case 0x0022:
|
|
260
|
+
if (currentModule)
|
|
261
|
+
currentModule.type = 'document';
|
|
262
|
+
break;
|
|
263
|
+
case 0x002B:
|
|
264
|
+
if (currentModule?.name) {
|
|
265
|
+
modules.push(currentModule);
|
|
266
|
+
}
|
|
267
|
+
currentModule = null;
|
|
268
|
+
break;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return modules;
|
|
272
|
+
}
|
|
273
|
+
function stripAttributes(code) {
|
|
274
|
+
const lines = code.split(/\r?\n/);
|
|
275
|
+
const start = lines.findIndex(l => !l.startsWith('Attribute '));
|
|
276
|
+
if (start < 0)
|
|
277
|
+
return code;
|
|
278
|
+
const trimmed = lines.slice(start).join('\n');
|
|
279
|
+
return trimmed;
|
|
280
|
+
}
|
|
281
|
+
//# sourceMappingURL=VbaProject.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VbaProject.js","sourceRoot":"","sources":["../../src/vba/VbaProject.ts"],"names":[],"mappings":"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"}
|
package/dist/vba/cfb.js
ADDED
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
const SIGNATURE = new Uint8Array([0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1]);
|
|
2
|
+
const ENDOFCHAIN = 0xFFFFFFFE;
|
|
3
|
+
const FREESECT = 0xFFFFFFFF;
|
|
4
|
+
const FATSECT = 0xFFFFFFFD;
|
|
5
|
+
const NOSTREAM = 0xFFFFFFFF;
|
|
6
|
+
const SECTOR_SIZE = 512;
|
|
7
|
+
const MINI_SIZE = 64;
|
|
8
|
+
const MINI_CUTOFF = 0x1000;
|
|
9
|
+
const DIR_ENTRY_SZ = 128;
|
|
10
|
+
function u16(buf, off) {
|
|
11
|
+
return buf[off] | (buf[off + 1] << 8);
|
|
12
|
+
}
|
|
13
|
+
function u32(buf, off) {
|
|
14
|
+
return (buf[off] | (buf[off + 1] << 8) | (buf[off + 2] << 16) | (buf[off + 3] << 24)) >>> 0;
|
|
15
|
+
}
|
|
16
|
+
function setU16(buf, off, v) {
|
|
17
|
+
buf[off] = v & 0xFF;
|
|
18
|
+
buf[off + 1] = (v >> 8) & 0xFF;
|
|
19
|
+
}
|
|
20
|
+
function setU32(buf, off, v) {
|
|
21
|
+
buf[off] = v & 0xFF;
|
|
22
|
+
buf[off + 1] = (v >> 8) & 0xFF;
|
|
23
|
+
buf[off + 2] = (v >> 16) & 0xFF;
|
|
24
|
+
buf[off + 3] = (v >> 24) & 0xFF;
|
|
25
|
+
}
|
|
26
|
+
function encodeName(name) {
|
|
27
|
+
if (name.length > 31)
|
|
28
|
+
throw new Error(`CFB entry name too long (${name.length} chars, max 31): "${name}"`);
|
|
29
|
+
const bytes = new Uint8Array(64);
|
|
30
|
+
let i = 0;
|
|
31
|
+
for (const ch of name) {
|
|
32
|
+
const code = ch.charCodeAt(0);
|
|
33
|
+
bytes[i++] = code & 0xFF;
|
|
34
|
+
bytes[i++] = (code >> 8) & 0xFF;
|
|
35
|
+
}
|
|
36
|
+
bytes[i++] = 0;
|
|
37
|
+
bytes[i++] = 0;
|
|
38
|
+
return { bytes, size: i };
|
|
39
|
+
}
|
|
40
|
+
function decodeName(buf, off, nameSize) {
|
|
41
|
+
let s = '';
|
|
42
|
+
const len = Math.max(0, nameSize - 2);
|
|
43
|
+
for (let i = 0; i < len; i += 2) {
|
|
44
|
+
const code = buf[off + i] | (buf[off + i + 1] << 8);
|
|
45
|
+
if (code === 0)
|
|
46
|
+
break;
|
|
47
|
+
s += String.fromCharCode(code);
|
|
48
|
+
}
|
|
49
|
+
return s;
|
|
50
|
+
}
|
|
51
|
+
function followChain(fat, start) {
|
|
52
|
+
const chain = [];
|
|
53
|
+
let sid = start;
|
|
54
|
+
while (sid !== ENDOFCHAIN && sid < fat.length) {
|
|
55
|
+
chain.push(sid);
|
|
56
|
+
sid = fat[sid];
|
|
57
|
+
}
|
|
58
|
+
return chain;
|
|
59
|
+
}
|
|
60
|
+
function ceilDiv(a, b) { return Math.ceil(a / b); }
|
|
61
|
+
export function readCfb(data) {
|
|
62
|
+
for (let i = 0; i < 8; i++)
|
|
63
|
+
if (data[i] !== SIGNATURE[i])
|
|
64
|
+
throw new Error('Not a CFB file');
|
|
65
|
+
const sectorPow = u16(data, 30);
|
|
66
|
+
const sectorSize = 1 << sectorPow;
|
|
67
|
+
const miniPow = u16(data, 32);
|
|
68
|
+
const miniSize = 1 << miniPow;
|
|
69
|
+
const fatSectors = u32(data, 44);
|
|
70
|
+
const dirStart = u32(data, 48);
|
|
71
|
+
const miniFatStart = u32(data, 60);
|
|
72
|
+
const sectorOff = (sid) => 512 + sid * sectorSize;
|
|
73
|
+
const difat = [];
|
|
74
|
+
for (let i = 0; i < 109 && i < fatSectors; i++) {
|
|
75
|
+
const sid = u32(data, 76 + i * 4);
|
|
76
|
+
if (sid !== FREESECT)
|
|
77
|
+
difat.push(sid);
|
|
78
|
+
}
|
|
79
|
+
const totalSectors = Math.floor((data.length - 512) / sectorSize);
|
|
80
|
+
const fat = new Uint32Array(totalSectors);
|
|
81
|
+
fat.fill(FREESECT);
|
|
82
|
+
for (let fi = 0; fi < difat.length; fi++) {
|
|
83
|
+
const off = sectorOff(difat[fi]);
|
|
84
|
+
const entriesPerSector = sectorSize / 4;
|
|
85
|
+
for (let j = 0; j < entriesPerSector && fi * entriesPerSector + j < totalSectors; j++) {
|
|
86
|
+
fat[fi * entriesPerSector + j] = u32(data, off + j * 4);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const dirChain = followChain(fat, dirStart);
|
|
90
|
+
const dirBuf = new Uint8Array(dirChain.length * sectorSize);
|
|
91
|
+
for (let i = 0; i < dirChain.length; i++) {
|
|
92
|
+
dirBuf.set(data.subarray(sectorOff(dirChain[i]), sectorOff(dirChain[i]) + sectorSize), i * sectorSize);
|
|
93
|
+
}
|
|
94
|
+
const numEntries = dirBuf.length / DIR_ENTRY_SZ;
|
|
95
|
+
const entries = [];
|
|
96
|
+
for (let i = 0; i < numEntries; i++) {
|
|
97
|
+
const off = i * DIR_ENTRY_SZ;
|
|
98
|
+
const nameSize = u16(dirBuf, off + 64);
|
|
99
|
+
if (nameSize === 0)
|
|
100
|
+
continue;
|
|
101
|
+
entries.push({
|
|
102
|
+
name: decodeName(dirBuf, off, nameSize),
|
|
103
|
+
type: dirBuf[off + 66],
|
|
104
|
+
child: u32(dirBuf, off + 76),
|
|
105
|
+
left: u32(dirBuf, off + 68),
|
|
106
|
+
right: u32(dirBuf, off + 72),
|
|
107
|
+
startSector: u32(dirBuf, off + 116),
|
|
108
|
+
size: u32(dirBuf, off + 120),
|
|
109
|
+
index: i,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
const root = entries.find(e => e.type === 5);
|
|
113
|
+
if (!root)
|
|
114
|
+
throw new Error('No root entry in CFB');
|
|
115
|
+
const miniContainerChain = followChain(fat, root.startSector);
|
|
116
|
+
const miniContainer = new Uint8Array(miniContainerChain.length * sectorSize);
|
|
117
|
+
for (let i = 0; i < miniContainerChain.length; i++) {
|
|
118
|
+
miniContainer.set(data.subarray(sectorOff(miniContainerChain[i]), sectorOff(miniContainerChain[i]) + sectorSize), i * sectorSize);
|
|
119
|
+
}
|
|
120
|
+
const miniFatChain = followChain(fat, miniFatStart);
|
|
121
|
+
const numMiniEntries = miniFatChain.length * (sectorSize / 4);
|
|
122
|
+
const miniFat = new Uint32Array(numMiniEntries);
|
|
123
|
+
miniFat.fill(FREESECT);
|
|
124
|
+
for (let i = 0; i < miniFatChain.length; i++) {
|
|
125
|
+
const off = sectorOff(miniFatChain[i]);
|
|
126
|
+
const count = sectorSize / 4;
|
|
127
|
+
for (let j = 0; j < count; j++) {
|
|
128
|
+
miniFat[i * count + j] = u32(data, off + j * 4);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
const parentMap = new Map();
|
|
132
|
+
function collectChildren(parentIdx, parentName) {
|
|
133
|
+
const parent = entries.find(e => e.index === parentIdx);
|
|
134
|
+
if (!parent || parent.child === NOSTREAM)
|
|
135
|
+
return;
|
|
136
|
+
const visit = (idx) => {
|
|
137
|
+
if (idx === NOSTREAM || idx >= numEntries)
|
|
138
|
+
return;
|
|
139
|
+
const e = entries.find(en => en.index === idx);
|
|
140
|
+
if (!e)
|
|
141
|
+
return;
|
|
142
|
+
parentMap.set(idx, parentName);
|
|
143
|
+
if (e.type === 1)
|
|
144
|
+
collectChildren(idx, e.name);
|
|
145
|
+
visit(e.left);
|
|
146
|
+
visit(e.right);
|
|
147
|
+
};
|
|
148
|
+
visit(parent.child);
|
|
149
|
+
}
|
|
150
|
+
collectChildren(root.index, '');
|
|
151
|
+
const streams = [];
|
|
152
|
+
for (const entry of entries) {
|
|
153
|
+
if (entry.type !== 2)
|
|
154
|
+
continue;
|
|
155
|
+
let streamData;
|
|
156
|
+
if (entry.size < MINI_CUTOFF) {
|
|
157
|
+
const chain = followChain(miniFat, entry.startSector);
|
|
158
|
+
const buf = new Uint8Array(chain.length * miniSize);
|
|
159
|
+
for (let i = 0; i < chain.length; i++) {
|
|
160
|
+
const off = chain[i] * miniSize;
|
|
161
|
+
buf.set(miniContainer.subarray(off, off + miniSize), i * miniSize);
|
|
162
|
+
}
|
|
163
|
+
streamData = buf.subarray(0, entry.size);
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
const chain = followChain(fat, entry.startSector);
|
|
167
|
+
const buf = new Uint8Array(chain.length * sectorSize);
|
|
168
|
+
for (let i = 0; i < chain.length; i++) {
|
|
169
|
+
buf.set(data.subarray(sectorOff(chain[i]), sectorOff(chain[i]) + sectorSize), i * sectorSize);
|
|
170
|
+
}
|
|
171
|
+
streamData = buf.subarray(0, entry.size);
|
|
172
|
+
}
|
|
173
|
+
streams.push({
|
|
174
|
+
name: entry.name,
|
|
175
|
+
data: streamData,
|
|
176
|
+
storage: parentMap.get(entry.index) || undefined,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
return streams;
|
|
180
|
+
}
|
|
181
|
+
export function buildCfb(streams) {
|
|
182
|
+
const root = { name: 'Root Entry', type: 5, children: [] };
|
|
183
|
+
const storages = new Map();
|
|
184
|
+
storages.set('', root);
|
|
185
|
+
for (const s of streams) {
|
|
186
|
+
const parentName = s.storage ?? '';
|
|
187
|
+
let parent = storages.get(parentName);
|
|
188
|
+
if (!parent) {
|
|
189
|
+
parent = { name: parentName, type: 1, children: [] };
|
|
190
|
+
storages.set(parentName, parent);
|
|
191
|
+
root.children.push(parent);
|
|
192
|
+
}
|
|
193
|
+
const node = { name: s.name, type: 2, data: s.data };
|
|
194
|
+
parent.children.push(node);
|
|
195
|
+
}
|
|
196
|
+
const flat = [];
|
|
197
|
+
const queue = [root];
|
|
198
|
+
while (queue.length) {
|
|
199
|
+
const n = queue.shift();
|
|
200
|
+
flat.push({
|
|
201
|
+
node: n, parentIdx: -1, childIdx: NOSTREAM,
|
|
202
|
+
leftIdx: NOSTREAM, rightIdx: NOSTREAM,
|
|
203
|
+
miniStart: 0, size: n.data?.length ?? 0,
|
|
204
|
+
});
|
|
205
|
+
if (n.children) {
|
|
206
|
+
for (const c of n.children)
|
|
207
|
+
queue.push(c);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
for (let i = 0; i < flat.length; i++) {
|
|
211
|
+
const n = flat[i].node;
|
|
212
|
+
if (!n.children?.length)
|
|
213
|
+
continue;
|
|
214
|
+
const childIdxs = flat
|
|
215
|
+
.map((e, idx) => ({ e, idx }))
|
|
216
|
+
.filter(({ e }) => n.children.includes(e.node))
|
|
217
|
+
.map(({ idx }) => idx);
|
|
218
|
+
if (childIdxs.length === 0)
|
|
219
|
+
continue;
|
|
220
|
+
const sorted = childIdxs.sort((a, b) => {
|
|
221
|
+
const na = flat[a].node.name, nb = flat[b].node.name;
|
|
222
|
+
if (na.length !== nb.length)
|
|
223
|
+
return na.length - nb.length;
|
|
224
|
+
return na.toUpperCase() < nb.toUpperCase() ? -1 : na.toUpperCase() > nb.toUpperCase() ? 1 : 0;
|
|
225
|
+
});
|
|
226
|
+
const buildTree = (arr) => {
|
|
227
|
+
if (arr.length === 0)
|
|
228
|
+
return NOSTREAM;
|
|
229
|
+
const mid = arr.length >> 1;
|
|
230
|
+
flat[arr[mid]].leftIdx = buildTree(arr.slice(0, mid));
|
|
231
|
+
flat[arr[mid]].rightIdx = buildTree(arr.slice(mid + 1));
|
|
232
|
+
return arr[mid];
|
|
233
|
+
};
|
|
234
|
+
flat[i].childIdx = buildTree(sorted);
|
|
235
|
+
}
|
|
236
|
+
const miniSectorData = [];
|
|
237
|
+
const miniChains = new Map();
|
|
238
|
+
let nextMiniSector = 0;
|
|
239
|
+
for (let i = 0; i < flat.length; i++) {
|
|
240
|
+
const d = flat[i].node.data;
|
|
241
|
+
if (!d || d.length === 0)
|
|
242
|
+
continue;
|
|
243
|
+
const numMiniSectors = ceilDiv(d.length, MINI_SIZE);
|
|
244
|
+
const chain = [];
|
|
245
|
+
for (let m = 0; m < numMiniSectors; m++) {
|
|
246
|
+
chain.push(nextMiniSector++);
|
|
247
|
+
const chunk = d.subarray(m * MINI_SIZE, Math.min((m + 1) * MINI_SIZE, d.length));
|
|
248
|
+
for (const b of chunk)
|
|
249
|
+
miniSectorData.push(b);
|
|
250
|
+
for (let p = chunk.length; p < MINI_SIZE; p++)
|
|
251
|
+
miniSectorData.push(0);
|
|
252
|
+
}
|
|
253
|
+
flat[i].miniStart = chain[0];
|
|
254
|
+
miniChains.set(i, chain);
|
|
255
|
+
}
|
|
256
|
+
const totalMiniSectors = nextMiniSector;
|
|
257
|
+
const miniFatEntries = Math.max(totalMiniSectors, 1);
|
|
258
|
+
const miniFatSectors = ceilDiv(miniFatEntries * 4, SECTOR_SIZE);
|
|
259
|
+
const miniFat = new Uint32Array(miniFatSectors * (SECTOR_SIZE / 4));
|
|
260
|
+
miniFat.fill(FREESECT);
|
|
261
|
+
for (const chain of miniChains.values()) {
|
|
262
|
+
for (let j = 0; j < chain.length; j++) {
|
|
263
|
+
miniFat[chain[j]] = j + 1 < chain.length ? chain[j + 1] : ENDOFCHAIN;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
const containerData = new Uint8Array(miniSectorData);
|
|
267
|
+
const containerSectors = ceilDiv(containerData.length || 1, SECTOR_SIZE);
|
|
268
|
+
const numDirEntries = flat.length;
|
|
269
|
+
const dirSectors = ceilDiv(numDirEntries * DIR_ENTRY_SZ, SECTOR_SIZE);
|
|
270
|
+
const fatSectorIdx = 0;
|
|
271
|
+
const dirStartSector = 1;
|
|
272
|
+
const miniFatStartSector = dirStartSector + dirSectors;
|
|
273
|
+
const containerStartSector = miniFatStartSector + miniFatSectors;
|
|
274
|
+
const totalSectors = 1 + dirSectors + miniFatSectors + containerSectors;
|
|
275
|
+
const fat = new Uint32Array(SECTOR_SIZE / 4);
|
|
276
|
+
fat.fill(FREESECT);
|
|
277
|
+
fat[fatSectorIdx] = FATSECT;
|
|
278
|
+
for (let i = 0; i < dirSectors; i++) {
|
|
279
|
+
fat[dirStartSector + i] = i + 1 < dirSectors ? dirStartSector + i + 1 : ENDOFCHAIN;
|
|
280
|
+
}
|
|
281
|
+
for (let i = 0; i < miniFatSectors; i++) {
|
|
282
|
+
fat[miniFatStartSector + i] = i + 1 < miniFatSectors ? miniFatStartSector + i + 1 : ENDOFCHAIN;
|
|
283
|
+
}
|
|
284
|
+
for (let i = 0; i < containerSectors; i++) {
|
|
285
|
+
fat[containerStartSector + i] = i + 1 < containerSectors ? containerStartSector + i + 1 : ENDOFCHAIN;
|
|
286
|
+
}
|
|
287
|
+
flat[0].miniStart = containerStartSector;
|
|
288
|
+
flat[0].size = containerData.length;
|
|
289
|
+
const dirBuf = new Uint8Array(dirSectors * SECTOR_SIZE);
|
|
290
|
+
for (let i = 0; i < flat.length; i++) {
|
|
291
|
+
const off = i * DIR_ENTRY_SZ;
|
|
292
|
+
const e = flat[i];
|
|
293
|
+
const { bytes, size: nameSize } = encodeName(e.node.name);
|
|
294
|
+
dirBuf.set(bytes, off);
|
|
295
|
+
setU16(dirBuf, off + 64, nameSize);
|
|
296
|
+
dirBuf[off + 66] = e.node.type;
|
|
297
|
+
dirBuf[off + 67] = 1;
|
|
298
|
+
setU32(dirBuf, off + 68, e.leftIdx);
|
|
299
|
+
setU32(dirBuf, off + 72, e.rightIdx);
|
|
300
|
+
setU32(dirBuf, off + 76, e.childIdx);
|
|
301
|
+
if (e.node.type === 5) {
|
|
302
|
+
setU32(dirBuf, off + 116, containerStartSector);
|
|
303
|
+
setU32(dirBuf, off + 120, containerData.length);
|
|
304
|
+
}
|
|
305
|
+
else if (e.node.type === 2 && e.node.data && e.node.data.length > 0) {
|
|
306
|
+
setU32(dirBuf, off + 116, e.miniStart);
|
|
307
|
+
setU32(dirBuf, off + 120, e.node.data.length);
|
|
308
|
+
}
|
|
309
|
+
else if (e.node.type === 1) {
|
|
310
|
+
setU32(dirBuf, off + 116, 0);
|
|
311
|
+
setU32(dirBuf, off + 120, 0);
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
setU32(dirBuf, off + 116, ENDOFCHAIN);
|
|
315
|
+
setU32(dirBuf, off + 120, 0);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
const header = new Uint8Array(512);
|
|
319
|
+
header.set(SIGNATURE, 0);
|
|
320
|
+
setU16(header, 24, 0x003E);
|
|
321
|
+
setU16(header, 26, 0x0003);
|
|
322
|
+
setU16(header, 28, 0xFFFE);
|
|
323
|
+
setU16(header, 30, 9);
|
|
324
|
+
setU16(header, 32, 6);
|
|
325
|
+
setU32(header, 44, 1);
|
|
326
|
+
setU32(header, 48, dirStartSector);
|
|
327
|
+
setU32(header, 56, MINI_CUTOFF);
|
|
328
|
+
setU32(header, 60, miniFatStartSector);
|
|
329
|
+
setU32(header, 64, miniFatSectors);
|
|
330
|
+
setU32(header, 68, ENDOFCHAIN);
|
|
331
|
+
setU32(header, 72, 0);
|
|
332
|
+
setU32(header, 76, fatSectorIdx);
|
|
333
|
+
for (let i = 1; i < 109; i++)
|
|
334
|
+
setU32(header, 76 + i * 4, FREESECT);
|
|
335
|
+
const fileSize = 512 + totalSectors * SECTOR_SIZE;
|
|
336
|
+
const file = new Uint8Array(fileSize);
|
|
337
|
+
file.set(header, 0);
|
|
338
|
+
const fatBuf = new Uint8Array(SECTOR_SIZE);
|
|
339
|
+
for (let i = 0; i < fat.length; i++)
|
|
340
|
+
setU32(fatBuf, i * 4, fat[i]);
|
|
341
|
+
file.set(fatBuf, 512 + fatSectorIdx * SECTOR_SIZE);
|
|
342
|
+
file.set(dirBuf, 512 + dirStartSector * SECTOR_SIZE);
|
|
343
|
+
const miniFatBuf = new Uint8Array(miniFatSectors * SECTOR_SIZE);
|
|
344
|
+
for (let i = 0; i < miniFat.length; i++)
|
|
345
|
+
setU32(miniFatBuf, i * 4, miniFat[i]);
|
|
346
|
+
file.set(miniFatBuf, 512 + miniFatStartSector * SECTOR_SIZE);
|
|
347
|
+
const containerBuf = new Uint8Array(containerSectors * SECTOR_SIZE);
|
|
348
|
+
containerBuf.set(containerData);
|
|
349
|
+
file.set(containerBuf, 512 + containerStartSector * SECTOR_SIZE);
|
|
350
|
+
return file;
|
|
351
|
+
}
|
|
352
|
+
//# sourceMappingURL=cfb.js.map
|