@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.
Files changed (65) hide show
  1. package/dist/detect/index.d.ts +1 -1
  2. package/dist/detect/index.d.ts.map +1 -1
  3. package/dist/detect/index.js +77 -0
  4. package/dist/detect/index.js.map +1 -1
  5. package/dist/heic/format.d.ts +87 -0
  6. package/dist/heic/format.d.ts.map +1 -0
  7. package/dist/heic/format.js +241 -0
  8. package/dist/heic/format.js.map +1 -0
  9. package/dist/index.d.ts +8 -0
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +9 -0
  12. package/dist/index.js.map +1 -1
  13. package/dist/office-legacy/diagnose.d.ts +24 -0
  14. package/dist/office-legacy/diagnose.d.ts.map +1 -0
  15. package/dist/office-legacy/diagnose.js +111 -0
  16. package/dist/office-legacy/diagnose.js.map +1 -0
  17. package/dist/office-legacy/format.d.ts +89 -0
  18. package/dist/office-legacy/format.d.ts.map +1 -0
  19. package/dist/office-legacy/format.js +281 -0
  20. package/dist/office-legacy/format.js.map +1 -0
  21. package/dist/office-legacy/index.d.ts +9 -0
  22. package/dist/office-legacy/index.d.ts.map +1 -0
  23. package/dist/office-legacy/index.js +18 -0
  24. package/dist/office-legacy/index.js.map +1 -0
  25. package/dist/office-legacy/rebuild.d.ts +8 -0
  26. package/dist/office-legacy/rebuild.d.ts.map +1 -0
  27. package/dist/office-legacy/rebuild.js +234 -0
  28. package/dist/office-legacy/rebuild.js.map +1 -0
  29. package/dist/office-legacy/repair.d.ts +40 -0
  30. package/dist/office-legacy/repair.d.ts.map +1 -0
  31. package/dist/office-legacy/repair.js +161 -0
  32. package/dist/office-legacy/repair.js.map +1 -0
  33. package/dist/psd/diagnose.d.ts +33 -0
  34. package/dist/psd/diagnose.d.ts.map +1 -0
  35. package/dist/psd/diagnose.js +176 -0
  36. package/dist/psd/diagnose.js.map +1 -0
  37. package/dist/psd/format.d.ts +106 -0
  38. package/dist/psd/format.d.ts.map +1 -0
  39. package/dist/psd/format.js +238 -0
  40. package/dist/psd/format.js.map +1 -0
  41. package/dist/psd/index.d.ts +8 -0
  42. package/dist/psd/index.d.ts.map +1 -0
  43. package/dist/psd/index.js +13 -0
  44. package/dist/psd/index.js.map +1 -0
  45. package/dist/psd/repair.d.ts +36 -0
  46. package/dist/psd/repair.d.ts.map +1 -0
  47. package/dist/psd/repair.js +451 -0
  48. package/dist/psd/repair.js.map +1 -0
  49. package/dist/raw/diagnose.d.ts +29 -0
  50. package/dist/raw/diagnose.d.ts.map +1 -0
  51. package/dist/raw/diagnose.js +95 -0
  52. package/dist/raw/diagnose.js.map +1 -0
  53. package/dist/raw/format.d.ts +47 -0
  54. package/dist/raw/format.d.ts.map +1 -0
  55. package/dist/raw/format.js +213 -0
  56. package/dist/raw/format.js.map +1 -0
  57. package/dist/raw/index.d.ts +7 -0
  58. package/dist/raw/index.d.ts.map +1 -0
  59. package/dist/raw/index.js +13 -0
  60. package/dist/raw/index.js.map +1 -0
  61. package/dist/raw/repair.d.ts +46 -0
  62. package/dist/raw/repair.d.ts.map +1 -0
  63. package/dist/raw/repair.js +94 -0
  64. package/dist/raw/repair.js.map +1 -0
  65. 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"}