@intactfile/engines 0.2.0 → 0.3.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/detect/index.d.ts +1 -1
- package/dist/detect/index.d.ts.map +1 -1
- package/dist/detect/index.js +77 -0
- package/dist/detect/index.js.map +1 -1
- package/dist/heic/format.d.ts +87 -0
- package/dist/heic/format.d.ts.map +1 -0
- package/dist/heic/format.js +241 -0
- package/dist/heic/format.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/office-legacy/diagnose.d.ts +24 -0
- package/dist/office-legacy/diagnose.d.ts.map +1 -0
- package/dist/office-legacy/diagnose.js +111 -0
- package/dist/office-legacy/diagnose.js.map +1 -0
- package/dist/office-legacy/format.d.ts +89 -0
- package/dist/office-legacy/format.d.ts.map +1 -0
- package/dist/office-legacy/format.js +281 -0
- package/dist/office-legacy/format.js.map +1 -0
- package/dist/office-legacy/index.d.ts +9 -0
- package/dist/office-legacy/index.d.ts.map +1 -0
- package/dist/office-legacy/index.js +18 -0
- package/dist/office-legacy/index.js.map +1 -0
- package/dist/office-legacy/rebuild.d.ts +8 -0
- package/dist/office-legacy/rebuild.d.ts.map +1 -0
- package/dist/office-legacy/rebuild.js +234 -0
- package/dist/office-legacy/rebuild.js.map +1 -0
- package/dist/office-legacy/repair.d.ts +40 -0
- package/dist/office-legacy/repair.d.ts.map +1 -0
- package/dist/office-legacy/repair.js +161 -0
- package/dist/office-legacy/repair.js.map +1 -0
- package/dist/psd/diagnose.d.ts +33 -0
- package/dist/psd/diagnose.d.ts.map +1 -0
- package/dist/psd/diagnose.js +176 -0
- package/dist/psd/diagnose.js.map +1 -0
- package/dist/psd/format.d.ts +106 -0
- package/dist/psd/format.d.ts.map +1 -0
- package/dist/psd/format.js +238 -0
- package/dist/psd/format.js.map +1 -0
- package/dist/psd/index.d.ts +8 -0
- package/dist/psd/index.d.ts.map +1 -0
- package/dist/psd/index.js +13 -0
- package/dist/psd/index.js.map +1 -0
- package/dist/psd/repair.d.ts +36 -0
- package/dist/psd/repair.d.ts.map +1 -0
- package/dist/psd/repair.js +451 -0
- package/dist/psd/repair.js.map +1 -0
- package/dist/raw/diagnose.d.ts +29 -0
- package/dist/raw/diagnose.d.ts.map +1 -0
- package/dist/raw/diagnose.js +95 -0
- package/dist/raw/diagnose.js.map +1 -0
- package/dist/raw/format.d.ts +47 -0
- package/dist/raw/format.d.ts.map +1 -0
- package/dist/raw/format.js +213 -0
- package/dist/raw/format.js.map +1 -0
- package/dist/raw/index.d.ts +7 -0
- package/dist/raw/index.d.ts.map +1 -0
- package/dist/raw/index.js +13 -0
- package/dist/raw/index.js.map +1 -0
- package/dist/raw/repair.d.ts +46 -0
- package/dist/raw/repair.d.ts.map +1 -0
- package/dist/raw/repair.js +94 -0
- package/dist/raw/repair.js.map +1 -0
- package/package.json +14 -2
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure-TS canonical CFBF (v3, 512-byte sectors) writer. Given a flat set of
|
|
3
|
+
* recovered streams it emits a fresh, structurally-valid compound file:
|
|
4
|
+
* header + FAT + DIFAT(inline) + directory + MiniFAT + mini stream + big
|
|
5
|
+
* streams. Deterministic output. No wasm.
|
|
6
|
+
*
|
|
7
|
+
* v1 limit: ≤ 109 FAT sectors (~7 MB of addressable sectors), which covers
|
|
8
|
+
* legacy Office files comfortably; larger inputs are reported without a rebuild.
|
|
9
|
+
*/
|
|
10
|
+
import { CFBF_MAGIC, DIR_ENTRY, ENDOFCHAIN, FATSECT, FREESECT, MINI_CUTOFF, MINI_SECTOR, NOSTREAM, } from "./format.js";
|
|
11
|
+
const SS = 512; // sector size (v3)
|
|
12
|
+
const PER_FAT = SS / 4; // 128 entries per FAT sector
|
|
13
|
+
const PER_DIR = SS / DIR_ENTRY; // 4 entries per directory sector
|
|
14
|
+
const wU16 = (b, o, v) => { b[o] = v & 0xff; b[o + 1] = (v >>> 8) & 0xff; };
|
|
15
|
+
const wU32 = (b, o, v) => {
|
|
16
|
+
b[o] = v & 0xff;
|
|
17
|
+
b[o + 1] = (v >>> 8) & 0xff;
|
|
18
|
+
b[o + 2] = (v >>> 16) & 0xff;
|
|
19
|
+
b[o + 3] = (v >>> 24) & 0xff;
|
|
20
|
+
};
|
|
21
|
+
/** CFBF sibling collation: shorter names first, then by uppercased UTF-16. */
|
|
22
|
+
function compareNames(a, b) {
|
|
23
|
+
if (a.length !== b.length)
|
|
24
|
+
return a.length - b.length;
|
|
25
|
+
const ua = a.toUpperCase();
|
|
26
|
+
const ub = b.toUpperCase();
|
|
27
|
+
return ua < ub ? -1 : ua > ub ? 1 : 0;
|
|
28
|
+
}
|
|
29
|
+
/** True if a rebuild would need more than the 109 inline DIFAT slots. */
|
|
30
|
+
export function rebuildExceedsLimit(streams) {
|
|
31
|
+
let dataSectors = 0;
|
|
32
|
+
let miniBytes = 0;
|
|
33
|
+
for (const s of streams) {
|
|
34
|
+
if (s.bytes.length === 0)
|
|
35
|
+
continue;
|
|
36
|
+
if (s.bytes.length < MINI_CUTOFF)
|
|
37
|
+
miniBytes += Math.ceil(s.bytes.length / MINI_SECTOR) * MINI_SECTOR;
|
|
38
|
+
else
|
|
39
|
+
dataSectors += Math.ceil(s.bytes.length / SS);
|
|
40
|
+
}
|
|
41
|
+
const S = Math.ceil(miniBytes / SS);
|
|
42
|
+
const M = Math.ceil(Math.ceil(miniBytes / MINI_SECTOR) * 4 / SS);
|
|
43
|
+
const D = Math.ceil((1 + streams.length) * DIR_ENTRY / SS);
|
|
44
|
+
const base = D + M + S + dataSectors;
|
|
45
|
+
let F = 1;
|
|
46
|
+
for (let i = 0; i < 8; i++) {
|
|
47
|
+
const n = base + F;
|
|
48
|
+
const f2 = Math.max(1, Math.ceil(n / PER_FAT));
|
|
49
|
+
if (f2 === F)
|
|
50
|
+
break;
|
|
51
|
+
F = f2;
|
|
52
|
+
}
|
|
53
|
+
return F > 109;
|
|
54
|
+
}
|
|
55
|
+
export function writeCfbf(streams) {
|
|
56
|
+
// 1. Mini stream: pack small streams (< 4096 B), each padded to 64 B.
|
|
57
|
+
const small = streams.filter((s) => s.bytes.length > 0 && s.bytes.length < MINI_CUTOFF);
|
|
58
|
+
const big = streams.filter((s) => s.bytes.length >= MINI_CUTOFF);
|
|
59
|
+
const empty = streams.filter((s) => s.bytes.length === 0);
|
|
60
|
+
const miniStartOf = new Map();
|
|
61
|
+
let miniSectors = 0;
|
|
62
|
+
for (const s of small) {
|
|
63
|
+
miniStartOf.set(s, miniSectors);
|
|
64
|
+
miniSectors += Math.ceil(s.bytes.length / MINI_SECTOR);
|
|
65
|
+
}
|
|
66
|
+
const miniStreamLen = miniSectors * MINI_SECTOR;
|
|
67
|
+
const miniStream = new Uint8Array(miniStreamLen);
|
|
68
|
+
for (const s of small) {
|
|
69
|
+
miniStream.set(s.bytes, miniStartOf.get(s) * MINI_SECTOR);
|
|
70
|
+
}
|
|
71
|
+
// 2. Sector counts.
|
|
72
|
+
const D = Math.max(1, Math.ceil((1 + streams.length) * DIR_ENTRY / SS));
|
|
73
|
+
const miniFatEntries = miniSectors;
|
|
74
|
+
const M = Math.ceil((miniFatEntries * 4) / SS);
|
|
75
|
+
const S = Math.ceil(miniStreamLen / SS);
|
|
76
|
+
const bigRun = new Map();
|
|
77
|
+
let bigTotal = 0;
|
|
78
|
+
for (const s of big)
|
|
79
|
+
bigTotal += Math.ceil(s.bytes.length / SS);
|
|
80
|
+
const dataSectors = D + M + S + bigTotal;
|
|
81
|
+
let F = 1;
|
|
82
|
+
for (let i = 0; i < 16; i++) {
|
|
83
|
+
const n = dataSectors + F;
|
|
84
|
+
const f2 = Math.max(1, Math.ceil(n / PER_FAT));
|
|
85
|
+
if (f2 === F)
|
|
86
|
+
break;
|
|
87
|
+
F = f2;
|
|
88
|
+
}
|
|
89
|
+
const total = dataSectors + F;
|
|
90
|
+
// 3. Sector index assignment.
|
|
91
|
+
const dirStart = 0;
|
|
92
|
+
const miniFatStart = D;
|
|
93
|
+
const miniStreamStart = D + M;
|
|
94
|
+
let cursor = D + M + S;
|
|
95
|
+
for (const s of big) {
|
|
96
|
+
const sectors = Math.ceil(s.bytes.length / SS);
|
|
97
|
+
bigRun.set(s, { start: cursor, sectors });
|
|
98
|
+
cursor += sectors;
|
|
99
|
+
}
|
|
100
|
+
const fatStart = dataSectors;
|
|
101
|
+
// 4. FAT.
|
|
102
|
+
const fat = new Uint32Array(total).fill(FREESECT);
|
|
103
|
+
const chainRange = (a, count) => {
|
|
104
|
+
for (let i = 0; i < count; i++)
|
|
105
|
+
fat[a + i] = i === count - 1 ? ENDOFCHAIN : a + i + 1;
|
|
106
|
+
};
|
|
107
|
+
if (D > 0)
|
|
108
|
+
chainRange(dirStart, D);
|
|
109
|
+
if (M > 0)
|
|
110
|
+
chainRange(miniFatStart, M);
|
|
111
|
+
if (S > 0)
|
|
112
|
+
chainRange(miniStreamStart, S);
|
|
113
|
+
for (const s of big) {
|
|
114
|
+
const r = bigRun.get(s);
|
|
115
|
+
chainRange(r.start, r.sectors);
|
|
116
|
+
}
|
|
117
|
+
for (let i = fatStart; i < total; i++)
|
|
118
|
+
fat[i] = FATSECT;
|
|
119
|
+
// 5. MiniFAT (chain each small stream's mini-sectors).
|
|
120
|
+
const miniFat = new Uint32Array(M * PER_FAT).fill(FREESECT);
|
|
121
|
+
for (const s of small) {
|
|
122
|
+
const start = miniStartOf.get(s);
|
|
123
|
+
const n = Math.ceil(s.bytes.length / MINI_SECTOR);
|
|
124
|
+
for (let i = 0; i < n; i++)
|
|
125
|
+
miniFat[start + i] = i === n - 1 ? ENDOFCHAIN : start + i + 1;
|
|
126
|
+
}
|
|
127
|
+
// 6. Directory entries (Root + one per stream, siblings in a balanced BST).
|
|
128
|
+
const sorted = [...streams].sort((a, z) => compareNames(a.name, z.name));
|
|
129
|
+
const idOf = new Map();
|
|
130
|
+
sorted.forEach((s, i) => idOf.set(s, i + 1)); // 0 = Root
|
|
131
|
+
const left = new Array(streams.length + 1).fill(NOSTREAM);
|
|
132
|
+
const right = new Array(streams.length + 1).fill(NOSTREAM);
|
|
133
|
+
const buildTree = (lo, hi) => {
|
|
134
|
+
if (lo > hi)
|
|
135
|
+
return NOSTREAM;
|
|
136
|
+
const mid = (lo + hi) >> 1;
|
|
137
|
+
const id = mid + 1;
|
|
138
|
+
left[id] = buildTree(lo, mid - 1);
|
|
139
|
+
right[id] = buildTree(mid + 1, hi);
|
|
140
|
+
return id;
|
|
141
|
+
};
|
|
142
|
+
const rootChild = buildTree(0, sorted.length - 1);
|
|
143
|
+
const dir = new Uint8Array(D * SS);
|
|
144
|
+
// fill unused slots as free entries
|
|
145
|
+
for (let i = 0; i < D * PER_DIR; i++) {
|
|
146
|
+
const o = i * DIR_ENTRY;
|
|
147
|
+
wU32(dir, o + 68, NOSTREAM);
|
|
148
|
+
wU32(dir, o + 72, NOSTREAM);
|
|
149
|
+
wU32(dir, o + 76, NOSTREAM);
|
|
150
|
+
}
|
|
151
|
+
const writeEntry = (id, name, type, startSector, size, child) => {
|
|
152
|
+
const o = id * DIR_ENTRY;
|
|
153
|
+
const nm = name.length > 31 ? name.slice(0, 31) : name;
|
|
154
|
+
for (let i = 0; i < nm.length; i++)
|
|
155
|
+
wU16(dir, o + i * 2, nm.charCodeAt(i));
|
|
156
|
+
const nameLen = (nm.length + 1) * 2; // incl. NUL terminator
|
|
157
|
+
wU16(dir, o + 64, nameLen);
|
|
158
|
+
dir[o + 66] = type;
|
|
159
|
+
dir[o + 67] = 1; // black
|
|
160
|
+
wU32(dir, o + 68, left[id] ?? NOSTREAM);
|
|
161
|
+
wU32(dir, o + 72, right[id] ?? NOSTREAM);
|
|
162
|
+
wU32(dir, o + 76, child);
|
|
163
|
+
wU32(dir, o + 116, startSector);
|
|
164
|
+
wU32(dir, o + 120, size >>> 0);
|
|
165
|
+
wU32(dir, o + 124, Math.floor(size / 0x1_0000_0000));
|
|
166
|
+
};
|
|
167
|
+
// Root Entry
|
|
168
|
+
writeEntry(0, "Root Entry", 5, S > 0 ? miniStreamStart : ENDOFCHAIN, miniStreamLen, rootChild);
|
|
169
|
+
left[0] = NOSTREAM;
|
|
170
|
+
right[0] = NOSTREAM;
|
|
171
|
+
wU32(dir, 68, NOSTREAM);
|
|
172
|
+
wU32(dir, 72, NOSTREAM);
|
|
173
|
+
wU32(dir, 76, rootChild);
|
|
174
|
+
for (const s of streams) {
|
|
175
|
+
const id = idOf.get(s);
|
|
176
|
+
let start;
|
|
177
|
+
if (s.bytes.length === 0)
|
|
178
|
+
start = ENDOFCHAIN;
|
|
179
|
+
else if (s.bytes.length < MINI_CUTOFF)
|
|
180
|
+
start = miniStartOf.get(s);
|
|
181
|
+
else
|
|
182
|
+
start = bigRun.get(s).start;
|
|
183
|
+
writeEntry(id, s.name, 2, start, s.bytes.length, NOSTREAM);
|
|
184
|
+
}
|
|
185
|
+
void empty;
|
|
186
|
+
// 7. Assemble the file.
|
|
187
|
+
const file = new Uint8Array(SS + total * SS);
|
|
188
|
+
// header
|
|
189
|
+
file.set(CFBF_MAGIC, 0);
|
|
190
|
+
wU16(file, 24, 0x3e); // minor version
|
|
191
|
+
wU16(file, 26, 3); // major version (v3)
|
|
192
|
+
wU16(file, 28, 0xfffe); // byte order
|
|
193
|
+
wU16(file, 30, 9); // sector shift
|
|
194
|
+
wU16(file, 32, 6); // mini sector shift
|
|
195
|
+
wU32(file, 40, 0); // # dir sectors (0 for v3)
|
|
196
|
+
wU32(file, 44, F); // # FAT sectors
|
|
197
|
+
wU32(file, 48, dirStart); // first dir sector
|
|
198
|
+
wU32(file, 56, MINI_CUTOFF); // mini stream cutoff
|
|
199
|
+
wU32(file, 60, M > 0 ? miniFatStart : ENDOFCHAIN); // first MiniFAT sector
|
|
200
|
+
wU32(file, 64, M); // # MiniFAT sectors
|
|
201
|
+
wU32(file, 68, ENDOFCHAIN); // first DIFAT sector (≤109 FAT sectors → none)
|
|
202
|
+
wU32(file, 72, 0); // # DIFAT sectors
|
|
203
|
+
for (let i = 0; i < 109; i++)
|
|
204
|
+
wU32(file, 76 + i * 4, i < F ? fatStart + i : FREESECT);
|
|
205
|
+
const put = (sect, bytes) => { file.set(bytes, (sect + 1) * SS); };
|
|
206
|
+
put(dirStart, dir);
|
|
207
|
+
// MiniFAT
|
|
208
|
+
if (M > 0) {
|
|
209
|
+
const mf = new Uint8Array(M * SS);
|
|
210
|
+
for (let i = 0; i < miniFat.length; i++)
|
|
211
|
+
wU32(mf, i * 4, miniFat[i]);
|
|
212
|
+
put(miniFatStart, mf);
|
|
213
|
+
}
|
|
214
|
+
// mini stream
|
|
215
|
+
if (S > 0) {
|
|
216
|
+
const ms = new Uint8Array(S * SS);
|
|
217
|
+
ms.set(miniStream, 0);
|
|
218
|
+
put(miniStreamStart, ms);
|
|
219
|
+
}
|
|
220
|
+
// big streams
|
|
221
|
+
for (const s of big) {
|
|
222
|
+
const r = bigRun.get(s);
|
|
223
|
+
const buf = new Uint8Array(r.sectors * SS);
|
|
224
|
+
buf.set(s.bytes, 0);
|
|
225
|
+
put(r.start, buf);
|
|
226
|
+
}
|
|
227
|
+
// FAT sectors
|
|
228
|
+
const fatBuf = new Uint8Array(F * SS).fill(0xff); // FREESECT padding
|
|
229
|
+
for (let i = 0; i < fat.length; i++)
|
|
230
|
+
wU32(fatBuf, i * 4, fat[i]);
|
|
231
|
+
put(fatStart, fatBuf);
|
|
232
|
+
return file;
|
|
233
|
+
}
|
|
234
|
+
//# sourceMappingURL=rebuild.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rebuild.js","sourceRoot":"","sources":["../../src/office-legacy/rebuild.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Legacy Office (CFBF/OLE2) repair: header normalization → FAT/DIFAT build →
|
|
3
|
+
* directory walk (with a pointer-free linear-scan fallback) → stream extraction
|
|
4
|
+
* (FAT + MiniFAT chains, with a contiguity fallback) → pure-TS rebuild of a
|
|
5
|
+
* canonical v3 compound file. No wasm.
|
|
6
|
+
*
|
|
7
|
+
* Honesty rule (docs/03): we rebuild the CONTAINER and recover its streams. If
|
|
8
|
+
* the damage is inside a stream's document content (BIFF/FIB), the file may
|
|
9
|
+
* still not fully open — the caveats say so. `outcome` is never "success" when a
|
|
10
|
+
* stream came back partial.
|
|
11
|
+
*/
|
|
12
|
+
import type { ByteSource } from "../byte-source.js";
|
|
13
|
+
import { type OfficeDamageClass } from "./diagnose.js";
|
|
14
|
+
export type OfficeRepairOutcome = "success" | "partial" | "failed";
|
|
15
|
+
export type OfficeRepairStrategy = "tree-walk" | "linear-scan" | "contiguity-fallback" | null;
|
|
16
|
+
export interface RecoveredStream {
|
|
17
|
+
name: string;
|
|
18
|
+
size: number;
|
|
19
|
+
bytesRecovered: number;
|
|
20
|
+
complete: boolean;
|
|
21
|
+
viaLinearScan: boolean;
|
|
22
|
+
}
|
|
23
|
+
export interface OfficeRepairReport {
|
|
24
|
+
outcome: OfficeRepairOutcome;
|
|
25
|
+
damageClass: OfficeDamageClass;
|
|
26
|
+
container: "doc" | "xls" | "ppt" | "msg" | "ole" | null;
|
|
27
|
+
strategy: OfficeRepairStrategy;
|
|
28
|
+
streams: RecoveredStream[];
|
|
29
|
+
caveats: string[];
|
|
30
|
+
notes: string[];
|
|
31
|
+
bytesIn: number;
|
|
32
|
+
bytesOut: number;
|
|
33
|
+
}
|
|
34
|
+
export interface OfficeRepairResult {
|
|
35
|
+
file?: Uint8Array;
|
|
36
|
+
report: OfficeRepairReport;
|
|
37
|
+
}
|
|
38
|
+
export declare function repairOfficeBytes(input: Uint8Array): OfficeRepairResult;
|
|
39
|
+
export declare function repairOffice(src: ByteSource): Promise<OfficeRepairResult>;
|
|
40
|
+
//# sourceMappingURL=repair.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repair.d.ts","sourceRoot":"","sources":["../../src/office-legacy/repair.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAuB,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAoB5E,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;AACnE,MAAM,MAAM,oBAAoB,GAAG,WAAW,GAAG,aAAa,GAAG,qBAAqB,GAAG,IAAI,CAAC;AAE9F,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,mBAAmB,CAAC;IAC7B,WAAW,EAAE,iBAAiB,CAAC;IAC/B,SAAS,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,IAAI,CAAC;IACxD,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,MAAM,EAAE,kBAAkB,CAAC;CAC5B;AAYD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,GAAG,kBAAkB,CAqJvE;AAED,wBAAsB,YAAY,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAE/E"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { readAll } from "../bytes-util.js";
|
|
2
|
+
import { diagnoseOfficeBytes } from "./diagnose.js";
|
|
3
|
+
import { MAXREGSECT, buildFat, buildMiniFat, classifyContainer, findMagic, hasMagicAt, linearScanEntries, parseHeader, readBigStream, readDifat, readDirectory, readMiniStream, sectOffset, } from "./format.js";
|
|
4
|
+
import { rebuildExceedsLimit, writeCfbf } from "./rebuild.js";
|
|
5
|
+
const CONTAINER_CAVEAT = "Container repaired; recovered streams do not guarantee the document opens — content inside a stream may still be damaged.";
|
|
6
|
+
/** Read `size` bytes sequentially from a start sector, ignoring the FAT chain. */
|
|
7
|
+
function contiguousRead(work, header, start, size) {
|
|
8
|
+
if (start > MAXREGSECT)
|
|
9
|
+
return new Uint8Array(0);
|
|
10
|
+
const off = sectOffset(start, header.sectorSize);
|
|
11
|
+
return work.subarray(off, Math.min(off + size, work.length));
|
|
12
|
+
}
|
|
13
|
+
export function repairOfficeBytes(input) {
|
|
14
|
+
const diag = diagnoseOfficeBytes(input);
|
|
15
|
+
const notes = [...diag.notes];
|
|
16
|
+
const caveats = [];
|
|
17
|
+
const fail = () => ({
|
|
18
|
+
report: {
|
|
19
|
+
outcome: "failed",
|
|
20
|
+
damageClass: diag.damageClass,
|
|
21
|
+
container: diag.container,
|
|
22
|
+
strategy: null,
|
|
23
|
+
streams: [],
|
|
24
|
+
caveats,
|
|
25
|
+
notes,
|
|
26
|
+
bytesIn: input.length,
|
|
27
|
+
bytesOut: 0,
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
if (diag.damageClass === "not-cfbf") {
|
|
31
|
+
notes.push("input is not a compound file; nothing to repair");
|
|
32
|
+
return fail();
|
|
33
|
+
}
|
|
34
|
+
if (diag.damageClass === "encrypted") {
|
|
35
|
+
notes.push("the file is encrypted; recovery requires the password and is declined");
|
|
36
|
+
return fail();
|
|
37
|
+
}
|
|
38
|
+
// Strip a garbage prefix so the header sits at offset 0.
|
|
39
|
+
let work = input;
|
|
40
|
+
if (!hasMagicAt(input, 0)) {
|
|
41
|
+
const at = findMagic(input, 64 * 1024);
|
|
42
|
+
if (at > 0) {
|
|
43
|
+
work = input.slice(at);
|
|
44
|
+
notes.push(`stripped ${at} garbage byte(s) before the CFBF signature`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const header = parseHeader(work);
|
|
48
|
+
if (!header)
|
|
49
|
+
return fail();
|
|
50
|
+
const fatSectors = readDifat(work, header);
|
|
51
|
+
const fat = fatSectors.length ? buildFat(work, header, fatSectors) : new Uint32Array(0);
|
|
52
|
+
// Directory: chain walk, else pointer-free linear scan.
|
|
53
|
+
let entries = fat.length ? readDirectory(work, header, fat) : [];
|
|
54
|
+
let strategy = "tree-walk";
|
|
55
|
+
const streamsOf = (e) => e.filter((x) => x.type === 2 && x.name && x.name !== "Root Entry");
|
|
56
|
+
let root = entries.find((e) => e.type === 5);
|
|
57
|
+
if (!root || streamsOf(entries).length === 0) {
|
|
58
|
+
const scanned = linearScanEntries(work, header);
|
|
59
|
+
if (streamsOf(scanned).length > streamsOf(entries).length) {
|
|
60
|
+
entries = scanned;
|
|
61
|
+
strategy = "linear-scan";
|
|
62
|
+
root = scanned.find((e) => e.type === 5) ?? root;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const streamEntries = streamsOf(entries);
|
|
66
|
+
if (streamEntries.length === 0) {
|
|
67
|
+
notes.push("no streams could be recovered from the directory or a linear scan");
|
|
68
|
+
return fail();
|
|
69
|
+
}
|
|
70
|
+
// Mini stream (from Root) + MiniFAT for small streams.
|
|
71
|
+
let miniStream = new Uint8Array(0);
|
|
72
|
+
let miniFat = new Uint32Array(0);
|
|
73
|
+
if (root && root.size > 0 && fat.length) {
|
|
74
|
+
miniStream = readBigStream(work, header, fat, root.startSector, root.size).bytes;
|
|
75
|
+
miniFat = buildMiniFat(work, header, fat);
|
|
76
|
+
}
|
|
77
|
+
const recovered = [];
|
|
78
|
+
const out = [];
|
|
79
|
+
let anyPartial = false;
|
|
80
|
+
let usedContiguity = false;
|
|
81
|
+
for (const e of streamEntries) {
|
|
82
|
+
let bytes;
|
|
83
|
+
let complete;
|
|
84
|
+
if (e.size === 0) {
|
|
85
|
+
bytes = new Uint8Array(0);
|
|
86
|
+
complete = true;
|
|
87
|
+
}
|
|
88
|
+
else if (e.size < header.miniCutoff) {
|
|
89
|
+
const r = readMiniStream(miniStream, miniFat, e.startSector, e.size);
|
|
90
|
+
bytes = r.bytes;
|
|
91
|
+
complete = r.complete;
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
const r = fat.length
|
|
95
|
+
? readBigStream(work, header, fat, e.startSector, e.size)
|
|
96
|
+
: { bytes: new Uint8Array(0), complete: false, brokenChain: true };
|
|
97
|
+
bytes = r.bytes;
|
|
98
|
+
complete = r.complete;
|
|
99
|
+
if (!complete) {
|
|
100
|
+
// contiguity fallback: assume the stream was laid out sequentially.
|
|
101
|
+
const cont = contiguousRead(work, header, e.startSector, e.size);
|
|
102
|
+
if (cont.length > bytes.length) {
|
|
103
|
+
bytes = cont;
|
|
104
|
+
complete = cont.length >= e.size;
|
|
105
|
+
usedContiguity = true;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (!complete)
|
|
110
|
+
anyPartial = true;
|
|
111
|
+
recovered.push({
|
|
112
|
+
name: e.name,
|
|
113
|
+
size: e.size,
|
|
114
|
+
bytesRecovered: bytes.length,
|
|
115
|
+
complete,
|
|
116
|
+
viaLinearScan: strategy === "linear-scan",
|
|
117
|
+
});
|
|
118
|
+
out.push({ name: e.name, bytes });
|
|
119
|
+
}
|
|
120
|
+
// Rebuild a canonical container from the recovered streams.
|
|
121
|
+
let file;
|
|
122
|
+
if (rebuildExceedsLimit(out)) {
|
|
123
|
+
notes.push("recovered data exceeds the v1 rebuild limit (109 FAT sectors); streams recovered but not repackaged");
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
file = writeCfbf(out);
|
|
127
|
+
}
|
|
128
|
+
const container = classifyContainer(streamEntries.map((e) => e.name));
|
|
129
|
+
let outcome;
|
|
130
|
+
if (!file)
|
|
131
|
+
outcome = "partial";
|
|
132
|
+
else if (anyPartial)
|
|
133
|
+
outcome = "partial";
|
|
134
|
+
else
|
|
135
|
+
outcome = "success";
|
|
136
|
+
caveats.push(CONTAINER_CAVEAT);
|
|
137
|
+
if (diag.damageClass === "truncated")
|
|
138
|
+
caveats.push("The file was cut short; data beyond the cut is physically gone.");
|
|
139
|
+
if (usedContiguity) {
|
|
140
|
+
strategy = "contiguity-fallback";
|
|
141
|
+
caveats.push("Some stream data was reassembled by assuming original on-disk order; verify against a known-good copy.");
|
|
142
|
+
}
|
|
143
|
+
return {
|
|
144
|
+
file,
|
|
145
|
+
report: {
|
|
146
|
+
outcome,
|
|
147
|
+
damageClass: diag.damageClass,
|
|
148
|
+
container,
|
|
149
|
+
strategy,
|
|
150
|
+
streams: recovered,
|
|
151
|
+
caveats,
|
|
152
|
+
notes,
|
|
153
|
+
bytesIn: input.length,
|
|
154
|
+
bytesOut: file?.length ?? 0,
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
export async function repairOffice(src) {
|
|
159
|
+
return repairOfficeBytes(await readAll(src));
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=repair.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repair.js","sourceRoot":"","sources":["../../src/office-legacy/repair.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PSD/PSB structural diagnosis via pure own parsing — no wasm, no pixel decode
|
|
3
|
+
* in this chain, so it is safe in the browser-facing root export.
|
|
4
|
+
*
|
|
5
|
+
* It validates the signature (incl. garbage prefix), the 26-byte header, then
|
|
6
|
+
* the four length-prefixed sections by BOUNDARY MATH only (never decoding the
|
|
7
|
+
* composite). Honesty rule: name the on-disk problem; never claim the layer
|
|
8
|
+
* stack is recoverable — a repaired PSD is the flattened composite.
|
|
9
|
+
*/
|
|
10
|
+
import type { ByteSource } from "../byte-source.js";
|
|
11
|
+
import type { Confidence } from "../types.js";
|
|
12
|
+
import { type PsdSafetyCaps } from "./format.js";
|
|
13
|
+
export type PsdDamageClass = "none" | "signature-damage" | "header-damage" | "bad-section-length" | "truncated" | "composite-corruption" | "layers-damaged" | "thumbnail-only" | "garbage-prefix" | "not-psd" | "unknown";
|
|
14
|
+
export interface PsdDiagnosis {
|
|
15
|
+
damageClass: PsdDamageClass;
|
|
16
|
+
confidence: Confidence;
|
|
17
|
+
notes: string[];
|
|
18
|
+
/** Offset of a valid 8BPS signature (0 normally, >0 = garbage prefix, null = none). */
|
|
19
|
+
signatureOffset: number | null;
|
|
20
|
+
version: 1 | 2 | null;
|
|
21
|
+
width: number | null;
|
|
22
|
+
height: number | null;
|
|
23
|
+
channels: number | null;
|
|
24
|
+
depth: number | null;
|
|
25
|
+
colorMode: number | null;
|
|
26
|
+
/** Compression flag of the image-data (composite) section, when readable. */
|
|
27
|
+
compression: number | null;
|
|
28
|
+
hasThumbnail: boolean;
|
|
29
|
+
prefixBytes: number;
|
|
30
|
+
}
|
|
31
|
+
export declare function diagnosePsdBytes(b: Uint8Array, caps?: PsdSafetyCaps): PsdDiagnosis;
|
|
32
|
+
export declare function diagnosePsd(src: ByteSource, caps?: PsdSafetyCaps): Promise<PsdDiagnosis>;
|
|
33
|
+
//# sourceMappingURL=diagnose.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnose.d.ts","sourceRoot":"","sources":["../../src/psd/diagnose.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,OAAO,EAGL,KAAK,aAAa,EAWnB,MAAM,aAAa,CAAC;AAErB,MAAM,MAAM,cAAc,GACtB,MAAM,GACN,kBAAkB,GAClB,eAAe,GACf,oBAAoB,GACpB,WAAW,GACX,sBAAsB,GACtB,gBAAgB,GAChB,gBAAgB,GAChB,gBAAgB,GAChB,SAAS,GACT,SAAS,CAAC;AAEd,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,cAAc,CAAC;IAC5B,UAAU,EAAE,UAAU,CAAC;IACvB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,uFAAuF;IACvF,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,OAAO,EAAE,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,6EAA6E;IAC7E,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;CACrB;AAID,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,GAAE,aAAgC,GAAG,YAAY,CAuKpG;AAaD,wBAAsB,WAAW,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,GAAE,aAAgC,GAAG,OAAO,CAAC,YAAY,CAAC,CAEhH"}
|