@intactfile/engines 0.1.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 (113) hide show
  1. package/dist/archive/index.d.ts +5 -13
  2. package/dist/archive/index.d.ts.map +1 -1
  3. package/dist/archive/index.js +4 -1
  4. package/dist/archive/index.js.map +1 -1
  5. package/dist/audio/index.d.ts +11 -0
  6. package/dist/audio/index.d.ts.map +1 -0
  7. package/dist/audio/index.js +11 -0
  8. package/dist/audio/index.js.map +1 -0
  9. package/dist/audio/mp3.d.ts +22 -0
  10. package/dist/audio/mp3.d.ts.map +1 -0
  11. package/dist/audio/mp3.js +141 -0
  12. package/dist/audio/mp3.js.map +1 -0
  13. package/dist/audio/wav.d.ts +23 -0
  14. package/dist/audio/wav.d.ts.map +1 -0
  15. package/dist/audio/wav.js +86 -0
  16. package/dist/audio/wav.js.map +1 -0
  17. package/dist/bytes-util.d.ts +17 -0
  18. package/dist/bytes-util.d.ts.map +1 -0
  19. package/dist/bytes-util.js +46 -0
  20. package/dist/bytes-util.js.map +1 -0
  21. package/dist/detect/index.d.ts +1 -1
  22. package/dist/detect/index.d.ts.map +1 -1
  23. package/dist/detect/index.js +77 -0
  24. package/dist/detect/index.js.map +1 -1
  25. package/dist/heic/format.d.ts +87 -0
  26. package/dist/heic/format.d.ts.map +1 -0
  27. package/dist/heic/format.js +241 -0
  28. package/dist/heic/format.js.map +1 -0
  29. package/dist/index.d.ts +14 -1
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +14 -1
  32. package/dist/index.js.map +1 -1
  33. package/dist/jpeg/index.d.ts +2 -8
  34. package/dist/jpeg/index.d.ts.map +1 -1
  35. package/dist/jpeg/index.js +4 -1
  36. package/dist/jpeg/index.js.map +1 -1
  37. package/dist/license.d.ts +63 -0
  38. package/dist/license.d.ts.map +1 -0
  39. package/dist/license.js +167 -0
  40. package/dist/license.js.map +1 -0
  41. package/dist/office-legacy/diagnose.d.ts +24 -0
  42. package/dist/office-legacy/diagnose.d.ts.map +1 -0
  43. package/dist/office-legacy/diagnose.js +111 -0
  44. package/dist/office-legacy/diagnose.js.map +1 -0
  45. package/dist/office-legacy/format.d.ts +89 -0
  46. package/dist/office-legacy/format.d.ts.map +1 -0
  47. package/dist/office-legacy/format.js +281 -0
  48. package/dist/office-legacy/format.js.map +1 -0
  49. package/dist/office-legacy/index.d.ts +9 -0
  50. package/dist/office-legacy/index.d.ts.map +1 -0
  51. package/dist/office-legacy/index.js +18 -0
  52. package/dist/office-legacy/index.js.map +1 -0
  53. package/dist/office-legacy/rebuild.d.ts +8 -0
  54. package/dist/office-legacy/rebuild.d.ts.map +1 -0
  55. package/dist/office-legacy/rebuild.js +234 -0
  56. package/dist/office-legacy/rebuild.js.map +1 -0
  57. package/dist/office-legacy/repair.d.ts +40 -0
  58. package/dist/office-legacy/repair.d.ts.map +1 -0
  59. package/dist/office-legacy/repair.js +161 -0
  60. package/dist/office-legacy/repair.js.map +1 -0
  61. package/dist/pdf/index.d.ts +5 -6
  62. package/dist/pdf/index.d.ts.map +1 -1
  63. package/dist/pdf/index.js +4 -1
  64. package/dist/pdf/index.js.map +1 -1
  65. package/dist/png/index.d.ts +1 -7
  66. package/dist/png/index.d.ts.map +1 -1
  67. package/dist/png/index.js +3 -1
  68. package/dist/png/index.js.map +1 -1
  69. package/dist/psd/diagnose.d.ts +33 -0
  70. package/dist/psd/diagnose.d.ts.map +1 -0
  71. package/dist/psd/diagnose.js +176 -0
  72. package/dist/psd/diagnose.js.map +1 -0
  73. package/dist/psd/format.d.ts +106 -0
  74. package/dist/psd/format.d.ts.map +1 -0
  75. package/dist/psd/format.js +238 -0
  76. package/dist/psd/format.js.map +1 -0
  77. package/dist/psd/index.d.ts +8 -0
  78. package/dist/psd/index.d.ts.map +1 -0
  79. package/dist/psd/index.js +13 -0
  80. package/dist/psd/index.js.map +1 -0
  81. package/dist/psd/repair.d.ts +36 -0
  82. package/dist/psd/repair.d.ts.map +1 -0
  83. package/dist/psd/repair.js +451 -0
  84. package/dist/psd/repair.js.map +1 -0
  85. package/dist/raw/diagnose.d.ts +29 -0
  86. package/dist/raw/diagnose.d.ts.map +1 -0
  87. package/dist/raw/diagnose.js +95 -0
  88. package/dist/raw/diagnose.js.map +1 -0
  89. package/dist/raw/format.d.ts +47 -0
  90. package/dist/raw/format.d.ts.map +1 -0
  91. package/dist/raw/format.js +213 -0
  92. package/dist/raw/format.js.map +1 -0
  93. package/dist/raw/index.d.ts +7 -0
  94. package/dist/raw/index.d.ts.map +1 -0
  95. package/dist/raw/index.js +13 -0
  96. package/dist/raw/index.js.map +1 -0
  97. package/dist/raw/repair.d.ts +46 -0
  98. package/dist/raw/repair.d.ts.map +1 -0
  99. package/dist/raw/repair.js +94 -0
  100. package/dist/raw/repair.js.map +1 -0
  101. package/dist/sqlite/index.d.ts +8 -1
  102. package/dist/sqlite/index.d.ts.map +1 -1
  103. package/dist/sqlite/index.js +4 -1
  104. package/dist/sqlite/index.js.map +1 -1
  105. package/dist/video/avi.d.ts +23 -0
  106. package/dist/video/avi.d.ts.map +1 -0
  107. package/dist/video/avi.js +122 -0
  108. package/dist/video/avi.js.map +1 -0
  109. package/dist/video/index.d.ts +15 -2
  110. package/dist/video/index.d.ts.map +1 -1
  111. package/dist/video/index.js +10 -2
  112. package/dist/video/index.js.map +1 -1
  113. package/package.json +18 -2
@@ -0,0 +1,167 @@
1
+ /**
2
+ * SDK/CLI license gate for the IntactFile repair engines.
3
+ *
4
+ * The repair engines are the paid product; diagnosis/detection stay free. On
5
+ * Node (CLI, MCP server, or the SDK imported directly) every repair entry
6
+ * point is gated behind a short-lived ES256 license minted by the API for
7
+ * ACTIVE Business subscribers and verified OFFLINE against the embedded PUBLIC
8
+ * key below — the API is the sole holder of the private key.
9
+ *
10
+ * In the BROWSER the gate is a no-op: the free in-browser widget calls these
11
+ * same functions and must stay free, so the gate only engages in a real Node
12
+ * runtime. DRM on a local library can't be unbreakable; this is a genuine,
13
+ * signed entitlement check plus the terms — not obfuscation. It never inspects
14
+ * file bytes and never phones home during a repair (verification is offline).
15
+ */
16
+ /** Embedded PUBLIC verification key (P-256). The private key never ships. */
17
+ const PUBLIC_JWK = {
18
+ kty: "EC",
19
+ crv: "P-256",
20
+ x: "W2edR_v1SXRWdNPE6s5KUoCbFlThQ48h325OtSzr71A",
21
+ y: "4BzLYg5mju7wf6Y_DJ4Df1eWjX6wyUxd9X_5LHgSmC4",
22
+ };
23
+ export class LicenseError extends Error {
24
+ code;
25
+ constructor(code, message) {
26
+ super(message);
27
+ this.code = code;
28
+ this.name = "LicenseError";
29
+ }
30
+ }
31
+ /* ------------------------------ module state ----------------------------- */
32
+ let currentToken;
33
+ /** Memoized claims for currentToken so repeated repairs don't re-verify. */
34
+ let verified;
35
+ /* ---------------------------- test-only hooks ---------------------------- */
36
+ // Undocumented, prefixed hooks used by the unit tests to drive the gate with
37
+ // an ephemeral keypair and to simulate a browser runtime. Not part of the API.
38
+ let testPublicJwk = null;
39
+ let testForceBrowser = false;
40
+ /** @internal test hook — override the embedded public key (null = restore). */
41
+ export function __setTestPublicKey(jwk) {
42
+ testPublicJwk = jwk;
43
+ verified = undefined;
44
+ }
45
+ /** @internal test hook — force the browser (no-op) code path. */
46
+ export function __setForceBrowser(on) {
47
+ testForceBrowser = on;
48
+ }
49
+ /* ------------------------------ runtime check ---------------------------- */
50
+ /** True only in a real Node runtime (never a browser tab or web worker). */
51
+ function isNodeRuntime() {
52
+ if (testForceBrowser)
53
+ return false;
54
+ return (typeof window === "undefined" &&
55
+ typeof globalThis.document === "undefined" &&
56
+ typeof process !== "undefined" &&
57
+ !!process.versions?.node);
58
+ }
59
+ /* ------------------------------ token decode ----------------------------- */
60
+ /** Decode a base64url segment to bytes (identical in Node and the browser). */
61
+ function b64urlToBytes(s) {
62
+ const b64 = s.replace(/-/g, "+").replace(/_/g, "/").padEnd(Math.ceil(s.length / 4) * 4, "=");
63
+ let bin;
64
+ try {
65
+ bin = atob(b64);
66
+ }
67
+ catch {
68
+ throw new LicenseError("invalid", "Malformed license token.");
69
+ }
70
+ const out = new Uint8Array(bin.length);
71
+ for (let i = 0; i < bin.length; i++)
72
+ out[i] = bin.charCodeAt(i);
73
+ return out;
74
+ }
75
+ function importVerifyKey(jwk) {
76
+ return globalThis.crypto.subtle.importKey("jwk", jwk, { name: "ECDSA", namedCurve: "P-256" }, false, ["verify"]);
77
+ }
78
+ /**
79
+ * Verify a compact ES256 license JWT offline and return its claims, or throw a
80
+ * LicenseError. Pure (no module state): the unit tests drive it with an
81
+ * ephemeral keypair via the `publicJwk` option.
82
+ */
83
+ export async function verifyLicense(token, opts = {}) {
84
+ const parts = token.split(".");
85
+ if (parts.length !== 3)
86
+ throw new LicenseError("invalid", "Malformed license token.");
87
+ const [h, p, sig] = parts;
88
+ let claims;
89
+ try {
90
+ claims = JSON.parse(new TextDecoder().decode(b64urlToBytes(p)));
91
+ }
92
+ catch {
93
+ throw new LicenseError("invalid", "Malformed license token.");
94
+ }
95
+ const key = await importVerifyKey(opts.publicJwk ?? testPublicJwk ?? PUBLIC_JWK);
96
+ // Re-wrap into plain ArrayBuffer-backed views so the WebCrypto BufferSource
97
+ // types line up (TextEncoder yields Uint8Array<ArrayBufferLike> under TS 5.7+).
98
+ const signature = b64urlToBytes(sig);
99
+ const data = new Uint8Array(new TextEncoder().encode(`${h}.${p}`));
100
+ let ok = false;
101
+ try {
102
+ ok = await globalThis.crypto.subtle.verify({ name: "ECDSA", hash: "SHA-256" }, key, signature, data);
103
+ }
104
+ catch {
105
+ ok = false;
106
+ }
107
+ if (!ok)
108
+ throw new LicenseError("invalid", "License signature is not valid.");
109
+ const now = opts.now ?? Math.floor(Date.now() / 1000);
110
+ if (typeof claims.exp !== "number" || claims.exp <= now) {
111
+ throw new LicenseError("expired", "License has expired — run `intactfile license --refresh`.");
112
+ }
113
+ if (claims.tier !== "business") {
114
+ throw new LicenseError("wrong-tier", "This license is not for the Business plan.");
115
+ }
116
+ return claims;
117
+ }
118
+ /* ------------------------------- public API ------------------------------ */
119
+ /** Apply a license token so Node-side repairs can run. No-op-safe to re-call. */
120
+ export function setLicense(token) {
121
+ currentToken = token.trim();
122
+ verified = undefined;
123
+ }
124
+ /** Forget any applied license. */
125
+ export function clearLicense() {
126
+ currentToken = undefined;
127
+ verified = undefined;
128
+ }
129
+ /** Report whether a valid license is currently applied (verifies offline). */
130
+ export async function getLicenseStatus() {
131
+ if (!currentToken)
132
+ return { licensed: false, reason: "missing" };
133
+ try {
134
+ const c = await verifyLicense(currentToken);
135
+ return { licensed: true, tier: c.tier, expiresAt: new Date(c.exp * 1000).toISOString() };
136
+ }
137
+ catch (e) {
138
+ return { licensed: false, reason: e instanceof LicenseError ? e.code : "invalid" };
139
+ }
140
+ }
141
+ /**
142
+ * The gate itself. In the browser it returns immediately (free widget). On
143
+ * Node it requires a valid, unexpired Business license, verified offline.
144
+ */
145
+ export async function assertLicensed() {
146
+ if (!isNodeRuntime())
147
+ return;
148
+ if (!currentToken) {
149
+ throw new LicenseError("missing", "An active IntactFile Business license is required to run repairs here. " +
150
+ "Run `intactfile login`, or call setLicense() with a license token.");
151
+ }
152
+ const now = Math.floor(Date.now() / 1000);
153
+ if (verified && verified.exp > now)
154
+ return;
155
+ verified = await verifyLicense(currentToken, { now });
156
+ }
157
+ /**
158
+ * Wrap a repair entry point so it is licensed on Node and free in the browser.
159
+ * Preserves the wrapped function's signature.
160
+ */
161
+ export function gate(fn) {
162
+ return async (...args) => {
163
+ await assertLicensed();
164
+ return fn(...args);
165
+ };
166
+ }
167
+ //# sourceMappingURL=license.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"license.js","sourceRoot":"","sources":["../src/license.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Read-only CFBF diagnosis: classify container damage without opening the
3
+ * document with a real Office parser. Pure byte scanning, browser-safe.
4
+ *
5
+ * Honesty rule: repairing the container recovers the STREAMS; whether Word/
6
+ * Excel/PowerPoint fully opens the file depends on the content inside those
7
+ * streams, which this engine never inspects or repairs (v1 scope).
8
+ */
9
+ import type { ByteSource } from "../byte-source.js";
10
+ import type { Confidence } from "../types.js";
11
+ export type OfficeDamageClass = "none" | "header-damage" | "fat-damage" | "directory-damage" | "truncated" | "content-damage" | "encrypted" | "not-cfbf" | "unknown";
12
+ export interface OfficeDiagnosis {
13
+ damageClass: OfficeDamageClass;
14
+ confidence: Confidence;
15
+ notes: string[];
16
+ majorVersion: number | null;
17
+ sectorSize: number | null;
18
+ container: "doc" | "xls" | "ppt" | "msg" | "ole" | null;
19
+ streamsFound: number;
20
+ prefixBytes: number;
21
+ }
22
+ export declare function diagnoseOfficeBytes(input: Uint8Array): OfficeDiagnosis;
23
+ export declare function diagnoseOffice(src: ByteSource): Promise<OfficeDiagnosis>;
24
+ //# sourceMappingURL=diagnose.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnose.d.ts","sourceRoot":"","sources":["../../src/office-legacy/diagnose.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAkB9C,MAAM,MAAM,iBAAiB,GACzB,MAAM,GACN,eAAe,GACf,YAAY,GACZ,kBAAkB,GAClB,WAAW,GACX,gBAAgB,GAChB,WAAW,GACX,UAAU,GACV,SAAS,CAAC;AAEd,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,iBAAiB,CAAC;IAC/B,UAAU,EAAE,UAAU,CAAC;IACvB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,IAAI,CAAC;IACxD,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAOD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,UAAU,GAAG,eAAe,CAiHtE;AAED,wBAAsB,cAAc,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,eAAe,CAAC,CAE9E"}
@@ -0,0 +1,111 @@
1
+ import { readAll } from "../bytes-util.js";
2
+ import { MAXREGSECT, buildFat, classifyContainer, findMagic, hasMagicAt, linearScanEntries, magicScore, parseHeader, readDifat, readDirectory, sectOffset, u16, } from "./format.js";
3
+ const SCAN_WINDOW = 64 * 1024;
4
+ const isEncrypted = (names) => names.some((n) => n === "EncryptedPackage" || n === "EncryptionInfo" || /encrypt/i.test(n));
5
+ export function diagnoseOfficeBytes(input) {
6
+ const notes = [];
7
+ const base = {
8
+ notes,
9
+ majorVersion: null,
10
+ sectorSize: null,
11
+ container: null,
12
+ streamsFound: 0,
13
+ prefixBytes: 0,
14
+ };
15
+ const done = (damageClass, confidence) => ({
16
+ damageClass,
17
+ confidence,
18
+ ...base,
19
+ });
20
+ if (input.length < 512) {
21
+ notes.push(`file is only ${input.length} bytes: too small to be a compound file`);
22
+ return done("not-cfbf", "high");
23
+ }
24
+ // Locate the header.
25
+ let work = input;
26
+ let headerDamaged = false;
27
+ if (!hasMagicAt(input, 0)) {
28
+ const score = magicScore(input, 0);
29
+ const at = findMagic(input, SCAN_WINDOW);
30
+ if (at > 0) {
31
+ base.prefixBytes = at;
32
+ work = input.subarray(at);
33
+ headerDamaged = true;
34
+ notes.push(`CFBF magic found at offset ${at} (garbage prefix)`);
35
+ }
36
+ else if (score >= 5) {
37
+ headerDamaged = true;
38
+ notes.push("CFBF signature is partially damaged but recognizable");
39
+ }
40
+ else {
41
+ notes.push("no CFBF signature (D0 CF 11 E0 …) found");
42
+ return done("not-cfbf", input.length > SCAN_WINDOW ? "medium" : "high");
43
+ }
44
+ }
45
+ const header = parseHeader(work);
46
+ if (!header) {
47
+ notes.push("compound-file header is unreadable");
48
+ return done("header-damage", "medium");
49
+ }
50
+ base.majorVersion = header.major;
51
+ base.sectorSize = header.sectorSize;
52
+ // Raw-header field sanity (before normalization): a garbled sector shift /
53
+ // byte order / mini shift that we can deterministically fix.
54
+ const rawShift = u16(work, 30);
55
+ const rawByteOrder = u16(work, 28);
56
+ const rawMiniShift = u16(work, 32);
57
+ if (rawByteOrder !== 0xfffe || (rawShift !== 9 && rawShift !== 12) || rawMiniShift !== 6) {
58
+ headerDamaged = true;
59
+ }
60
+ const fatSectors = readDifat(work, header);
61
+ const fat = fatSectors.length ? buildFat(work, header, fatSectors) : null;
62
+ // Directory via the chain; fall back to a linear scan.
63
+ let entries = fat ? readDirectory(work, header, fat) : [];
64
+ let usedScan = false;
65
+ const streamEntries = (e) => e.filter((x) => (x.type === 1 || x.type === 2) && x.name);
66
+ if (!entries.some((e) => e.type === 5) || streamEntries(entries).length === 0) {
67
+ const scanned = linearScanEntries(work, header);
68
+ if (streamEntries(scanned).length > streamEntries(entries).length) {
69
+ entries = scanned;
70
+ usedScan = true;
71
+ }
72
+ }
73
+ const names = streamEntries(entries).map((e) => e.name);
74
+ base.streamsFound = names.length;
75
+ base.container = classifyContainer(names);
76
+ if (isEncrypted(names)) {
77
+ notes.push("legacy Office encryption detected (EncryptedPackage/EncryptionInfo): recovery needs the password");
78
+ return done("encrypted", "high");
79
+ }
80
+ // Truncation: a real (non-sentinel) directory or FAT sector points past EOF.
81
+ const dirOff = sectOffset(header.firstDirSector, header.sectorSize);
82
+ const dirPastEof = header.firstDirSector <= MAXREGSECT && dirOff + header.sectorSize > work.length;
83
+ const fatPastEof = fatSectors.some((s) => sectOffset(s, header.sectorSize) + header.sectorSize > work.length);
84
+ if (dirPastEof || fatPastEof) {
85
+ notes.push("declared FAT/directory sectors extend past end-of-file: the file was cut short");
86
+ notes.push("data beyond the cut is physically gone; recovery is partial");
87
+ return done("truncated", "high");
88
+ }
89
+ if (!fat || fatSectors.length === 0) {
90
+ notes.push("FAT/DIFAT is unreadable: sector chains cannot be followed");
91
+ return done("fat-damage", "high");
92
+ }
93
+ if (usedScan) {
94
+ notes.push("the directory chain/tree is broken; streams are only reachable by a linear scan");
95
+ return done("directory-damage", "high");
96
+ }
97
+ if (headerDamaged) {
98
+ notes.push("header fields are damaged but the body is intact: deterministically fixable");
99
+ return done("header-damage", "high");
100
+ }
101
+ if (base.streamsFound === 0) {
102
+ notes.push("no streams could be located");
103
+ return done("directory-damage", "medium");
104
+ }
105
+ notes.push(`compound file OK: ${base.streamsFound} stream(s), container ${base.container}`);
106
+ return done("none", "high");
107
+ }
108
+ export async function diagnoseOffice(src) {
109
+ return diagnoseOfficeBytes(await readAll(src));
110
+ }
111
+ //# sourceMappingURL=diagnose.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnose.js","sourceRoot":"","sources":["../../src/office-legacy/diagnose.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EACL,UAAU,EACV,QAAQ,EACR,iBAAiB,EACjB,SAAS,EACT,UAAU,EACV,iBAAiB,EACjB,UAAU,EACV,WAAW,EACX,SAAS,EACT,aAAa,EACb,UAAU,EACV,GAAG,GAEJ,MAAM,aAAa,CAAC;AAwBrB,MAAM,WAAW,GAAG,EAAE,GAAG,IAAI,CAAC;AAE9B,MAAM,WAAW,GAAG,CAAC,KAAe,EAAW,EAAE,CAC/C,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,kBAAkB,IAAI,CAAC,KAAK,gBAAgB,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AAE9F,MAAM,UAAU,mBAAmB,CAAC,KAAiB;IACnD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,IAAI,GAAwD;QAChE,KAAK;QACL,YAAY,EAAE,IAAI;QAClB,UAAU,EAAE,IAAI;QAChB,SAAS,EAAE,IAAI;QACf,YAAY,EAAE,CAAC;QACf,WAAW,EAAE,CAAC;KACf,CAAC;IACF,MAAM,IAAI,GAAG,CAAC,WAA8B,EAAE,UAAsB,EAAmB,EAAE,CAAC,CAAC;QACzF,WAAW;QACX,UAAU;QACV,GAAG,IAAI;KACR,CAAC,CAAC;IAEH,IAAI,KAAK,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,gBAAgB,KAAK,CAAC,MAAM,yCAAyC,CAAC,CAAC;QAClF,OAAO,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAClC,CAAC;IAED,qBAAqB;IACrB,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,IAAI,aAAa,GAAG,KAAK,CAAC;IAC1B,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC;QAC1B,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QACnC,MAAM,EAAE,GAAG,SAAS,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;QACzC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;YACtB,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;YAC1B,aAAa,GAAG,IAAI,CAAC;YACrB,KAAK,CAAC,IAAI,CAAC,8BAA8B,EAAE,mBAAmB,CAAC,CAAC;QAClE,CAAC;aAAM,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;YACtB,aAAa,GAAG,IAAI,CAAC;YACrB,KAAK,CAAC,IAAI,CAAC,sDAAsD,CAAC,CAAC;QACrE,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAC;YACtD,OAAO,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,KAAK,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC;QACjD,OAAO,IAAI,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;IACzC,CAAC;IACD,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC;IACjC,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;IAEpC,2EAA2E;IAC3E,6DAA6D;IAC7D,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAC/B,MAAM,YAAY,GAAG,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACnC,MAAM,YAAY,GAAG,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACnC,IAAI,YAAY,KAAK,MAAM,IAAI,CAAC,QAAQ,KAAK,CAAC,IAAI,QAAQ,KAAK,EAAE,CAAC,IAAI,YAAY,KAAK,CAAC,EAAE,CAAC;QACzF,aAAa,GAAG,IAAI,CAAC;IACvB,CAAC;IAED,MAAM,UAAU,GAAG,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC3C,MAAM,GAAG,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAE1E,uDAAuD;IACvD,IAAI,OAAO,GAAe,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACtE,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,MAAM,aAAa,GAAG,CAAC,CAAa,EAAc,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;IAC/G,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,aAAa,CAAC,OAAO,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9E,MAAM,OAAO,GAAG,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAChD,IAAI,aAAa,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC;YAClE,OAAO,GAAG,OAAO,CAAC;YAClB,QAAQ,GAAG,IAAI,CAAC;QAClB,CAAC;IACH,CAAC;IACD,MAAM,KAAK,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACxD,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC,MAAM,CAAC;IACjC,IAAI,CAAC,SAAS,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;IAE1C,IAAI,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,kGAAkG,CAAC,CAAC;QAC/G,OAAO,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IACnC,CAAC;IAED,6EAA6E;IAC7E,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;IACpE,MAAM,UAAU,GAAG,MAAM,CAAC,cAAc,IAAI,UAAU,IAAI,MAAM,GAAG,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC;IACnG,MAAM,UAAU,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC,GAAG,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IAC9G,IAAI,UAAU,IAAI,UAAU,EAAE,CAAC;QAC7B,KAAK,CAAC,IAAI,CAAC,gFAAgF,CAAC,CAAC;QAC7F,KAAK,CAAC,IAAI,CAAC,6DAA6D,CAAC,CAAC;QAC1E,OAAO,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IACnC,CAAC;IAED,IAAI,CAAC,GAAG,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpC,KAAK,CAAC,IAAI,CAAC,2DAA2D,CAAC,CAAC;QACxE,OAAO,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IACpC,CAAC;IAED,IAAI,QAAQ,EAAE,CAAC;QACb,KAAK,CAAC,IAAI,CAAC,iFAAiF,CAAC,CAAC;QAC9F,OAAO,IAAI,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAC;IAC1C,CAAC;IAED,IAAI,aAAa,EAAE,CAAC;QAClB,KAAK,CAAC,IAAI,CAAC,6EAA6E,CAAC,CAAC;QAC1F,OAAO,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;IACvC,CAAC;IAED,IAAI,IAAI,CAAC,YAAY,KAAK,CAAC,EAAE,CAAC;QAC5B,KAAK,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;QAC1C,OAAO,IAAI,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,qBAAqB,IAAI,CAAC,YAAY,yBAAyB,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;IAC5F,OAAO,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,GAAe;IAClD,OAAO,mBAAmB,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;AACjD,CAAC"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Pure CFBF / OLE2 (Compound File Binary Format) primitives: header parse,
3
+ * FAT/DIFAT/MiniFAT walk, 128-byte directory entries, sector→offset math, and
4
+ * a pointer-free linear directory scan for salvage. No wasm, no compression —
5
+ * CFBF stores stream bytes raw, so this is all integer/offset arithmetic.
6
+ *
7
+ * Backs legacy binary Office: .doc/.xls/.ppt (97–2003), plus .msg/.msi. Repair
8
+ * scope is the CONTAINER + stream salvage — never the document content inside a
9
+ * stream. Reference: [MS-CFB]. All fields little-endian.
10
+ */
11
+ export declare const CFBF_MAGIC: Uint8Array<ArrayBuffer>;
12
+ export declare const MAXREGSECT = 4294967290;
13
+ export declare const DIFSECT = 4294967292;
14
+ export declare const FATSECT = 4294967293;
15
+ export declare const ENDOFCHAIN = 4294967294;
16
+ export declare const FREESECT = 4294967295;
17
+ export declare const NOSTREAM = 4294967295;
18
+ export declare const MINI_CUTOFF = 4096;
19
+ export declare const MINI_SECTOR = 64;
20
+ export declare const DIR_ENTRY = 128;
21
+ export declare const u16: (b: Uint8Array, o: number) => number;
22
+ export declare const u32: (b: Uint8Array, o: number) => number;
23
+ /** 64-bit little-endian as a JS number (v3 uses only the low 32 bits). */
24
+ export declare const u64: (b: Uint8Array, o: number) => number;
25
+ export interface CfbfHeader {
26
+ major: number;
27
+ sectorSize: number;
28
+ miniCutoff: number;
29
+ numFatSectors: number;
30
+ firstDirSector: number;
31
+ firstMiniFatSector: number;
32
+ numMiniFatSectors: number;
33
+ firstDifatSector: number;
34
+ numDifatSectors: number;
35
+ }
36
+ export declare function hasMagicAt(b: Uint8Array, off: number): boolean;
37
+ /** How many of the 8 magic bytes match at `off` (partial-magic heuristic). */
38
+ export declare function magicScore(b: Uint8Array, off: number): number;
39
+ /** First offset of an exact CFBF magic within `window`, or -1. */
40
+ export declare function findMagic(b: Uint8Array, window: number): number;
41
+ /** Parse the 512-byte header. Returns null if the sector shift is implausible. */
42
+ export declare function parseHeader(b: Uint8Array): CfbfHeader | null;
43
+ /** SECT number → absolute file offset. Sector 0 begins one sector past the header. */
44
+ export declare const sectOffset: (sect: number, sectorSize: number) => number;
45
+ /** Collect the FAT-sector numbers from the header DIFAT + any chained DIFAT sectors. */
46
+ export declare function readDifat(b: Uint8Array, header: CfbfHeader): number[];
47
+ /** Build the FAT array from its sectors. Out-of-range sectors read as FREESECT. */
48
+ export declare function buildFat(b: Uint8Array, header: CfbfHeader, fatSectors: number[]): Uint32Array;
49
+ /** Follow a FAT/MiniFAT chain from `start`, with cycle + bound guards. */
50
+ export declare function readChain(fat: Uint32Array, start: number, maxLen: number): number[];
51
+ export interface StreamRead {
52
+ bytes: Uint8Array;
53
+ complete: boolean;
54
+ brokenChain: boolean;
55
+ }
56
+ /** Read a normal (FAT-chained) stream of `size` bytes from `start`. */
57
+ export declare function readBigStream(b: Uint8Array, header: CfbfHeader, fat: Uint32Array, start: number, size: number): StreamRead;
58
+ /** Build the MiniFAT array by reading its sector chain from the FAT. */
59
+ export declare function buildMiniFat(b: Uint8Array, header: CfbfHeader, fat: Uint32Array): Uint32Array;
60
+ /** Read a small (MiniFAT-chained) stream from the mini stream. */
61
+ export declare function readMiniStream(miniStream: Uint8Array, miniFat: Uint32Array, start: number, size: number): StreamRead;
62
+ export interface DirEntry {
63
+ id: number;
64
+ name: string;
65
+ type: number;
66
+ color: number;
67
+ left: number;
68
+ right: number;
69
+ child: number;
70
+ startSector: number;
71
+ size: number;
72
+ /** byte offset of the raw 128-byte record (for the linear scanner). */
73
+ recordOffset: number;
74
+ }
75
+ /** Parse one 128-byte directory entry at absolute offset `off`. */
76
+ export declare function parseDirEntry(b: Uint8Array, off: number, id: number): DirEntry | null;
77
+ /** Read the directory entries by following the directory-sector chain. */
78
+ export declare function readDirectory(b: Uint8Array, header: CfbfHeader, fat: Uint32Array): DirEntry[];
79
+ /** True when a 128-byte record looks like a real directory entry. */
80
+ export declare function looksLikeEntry(b: Uint8Array, off: number): boolean;
81
+ /**
82
+ * Pointer-free salvage: scan the whole file at 128-byte alignment for records
83
+ * that look like directory entries. Recovers streams when the tree/chain is
84
+ * destroyed (the CFBF analog of the ZIP local-header scan).
85
+ */
86
+ export declare function linearScanEntries(b: Uint8Array, header: CfbfHeader): DirEntry[];
87
+ /** Detect the Office document type from the recovered stream names. */
88
+ export declare function classifyContainer(names: string[]): "doc" | "xls" | "ppt" | "msg" | "ole";
89
+ //# sourceMappingURL=format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/office-legacy/format.ts"],"names":[],"mappings":"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"}