@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,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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"}
@@ -1,11 +1,10 @@
1
- /**
2
- * PDF engine subpath export (`@intactfile/engines/pdf`). Kept out of the root
3
- * export so browser bundles that never repair PDFs never see the qpdf wasm
4
- * dependency; even here, the wasm is only loaded on the first repairPdf call.
5
- */
6
1
  export { diagnosePdf } from './diagnose.js';
7
2
  export type { PdfDiagnosis, PdfDamageClass } from './diagnose.js';
8
- export { repairPdf, qpdfArgLadder, buildRepairCandidates } from './repair.js';
3
+ export declare const repairPdf: (src: import("../byte-source.js").ByteSource) => Promise<{
4
+ pdf: Uint8Array;
5
+ report: import("./repair.js").PdfRepairReport;
6
+ }>;
7
+ export { qpdfArgLadder, buildRepairCandidates } from './repair.js';
9
8
  export type { PdfRepairReport, PdfRepairAttempt, PdfRepairOutcome, PdfVerification, RepairCandidate, } from './repair.js';
10
9
  export { rebuildXrefSkeleton } from './rebuild.js';
11
10
  export type { XrefRebuildResult } from './rebuild.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/pdf/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAC9E,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,eAAe,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACvE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC1F,OAAO,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACrF,OAAO,EACL,aAAa,EACb,WAAW,EACX,mBAAmB,EACnB,QAAQ,EACR,UAAU,GACX,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/pdf/index.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAClE,eAAO,MAAM,SAAS;;;EAAmB,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACnE,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,eAAe,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACvE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC1F,OAAO,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACrF,OAAO,EACL,aAAa,EACb,WAAW,EACX,mBAAmB,EACnB,QAAQ,EACR,UAAU,GACX,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC"}
package/dist/pdf/index.js CHANGED
@@ -3,8 +3,11 @@
3
3
  * export so browser bundles that never repair PDFs never see the qpdf wasm
4
4
  * dependency; even here, the wasm is only loaded on the first repairPdf call.
5
5
  */
6
+ import { gate } from '../license.js';
7
+ import { repairPdf as _repairPdf } from './repair.js';
6
8
  export { diagnosePdf } from './diagnose.js';
7
- export { repairPdf, qpdfArgLadder, buildRepairCandidates } from './repair.js';
9
+ export const repairPdf = gate(_repairPdf);
10
+ export { qpdfArgLadder, buildRepairCandidates } from './repair.js';
8
11
  export { rebuildXrefSkeleton } from './rebuild.js';
9
12
  export { runQpdf, setQpdfLoader, resetQpdfHost } from './qpdf-host.js';
10
13
  export { createBrowserQpdfLoader, DEFAULT_QPDF_BASE_URL } from './browser-loader.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/pdf/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAQ9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEnD,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEvE,OAAO,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACrF,OAAO,EACL,aAAa,EACb,WAAW,EACX,mBAAmB,EACnB,QAAQ,EACR,UAAU,GACX,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/pdf/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,SAAS,IAAI,UAAU,EAAE,MAAM,aAAa,CAAC;AAEtD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAQnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEnD,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEvE,OAAO,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACrF,OAAO,EACL,aAAa,EACb,WAAW,EACX,mBAAmB,EACnB,QAAQ,EACR,UAAU,GACX,MAAM,aAAa,CAAC"}
@@ -1,12 +1,6 @@
1
- /**
2
- * PNG engine subpath export (`@intactfile/engines/png`). Pure TypeScript —
3
- * pako (MIT) + fast-png (MIT), no wasm — so it is browser-safe. Kept on its own
4
- * key (not the root barrel) purely to avoid touching src/index.ts; the parent
5
- * integration can promote diagnosePng to the root if desired since it is pure.
6
- */
7
1
  export { diagnosePng } from './diagnose.js';
8
2
  export type { PngDiagnosis, PngDamageClass, PngChunkInfo } from './diagnose.js';
9
- export { repairPng } from './repair.js';
3
+ export declare const repairPng: (src: import("../byte-source.js").ByteSource, opts?: import("./repair.js").PngRepairOptions | undefined) => Promise<import("./repair.js").PngRepairResult>;
10
4
  export type { PngRepairReport, PngRepairOutcome, PngRepairOptions, PngRepairResult, } from './repair.js';
11
5
  export { PNG_SIGNATURE, DEFAULT_PNG_CAPS, walkChunksInMemory, factorizeDimensions, reconstructDimensions, channelsForColorType, isValidColorConfig, bytesPerRow, scanlineStride, unfilterScanlines8, unmangleNewlines, looksNewlineMangled, findSignature, hasSignatureAt, parseIhdr, serializeIhdr, ihdrCrc, } from './format.js';
12
6
  export type { PngChunk, ChunkWalk, IhdrFields, PngSafetyCaps, DimensionCandidate, ReconstructedDimensions, } from './format.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/png/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,oBAAoB,EACpB,kBAAkB,EAClB,WAAW,EACX,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,aAAa,EACb,cAAc,EACd,SAAS,EACT,aAAa,EACb,OAAO,GACR,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,QAAQ,EACR,SAAS,EACT,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/png/index.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAChF,eAAO,MAAM,SAAS,4JAAmB,CAAC;AAC1C,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,oBAAoB,EACpB,kBAAkB,EAClB,WAAW,EACX,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,aAAa,EACb,cAAc,EACd,SAAS,EACT,aAAa,EACb,OAAO,GACR,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,QAAQ,EACR,SAAS,EACT,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,aAAa,CAAC"}
package/dist/png/index.js CHANGED
@@ -4,7 +4,9 @@
4
4
  * key (not the root barrel) purely to avoid touching src/index.ts; the parent
5
5
  * integration can promote diagnosePng to the root if desired since it is pure.
6
6
  */
7
+ import { gate } from '../license.js';
8
+ import { repairPng as _repairPng } from './repair.js';
7
9
  export { diagnosePng } from './diagnose.js';
8
- export { repairPng } from './repair.js';
10
+ export const repairPng = gate(_repairPng);
9
11
  export { PNG_SIGNATURE, DEFAULT_PNG_CAPS, walkChunksInMemory, factorizeDimensions, reconstructDimensions, channelsForColorType, isValidColorConfig, bytesPerRow, scanlineStride, unfilterScanlines8, unmangleNewlines, looksNewlineMangled, findSignature, hasSignatureAt, parseIhdr, serializeIhdr, ihdrCrc, } from './format.js';
10
12
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/png/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAOxC,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,oBAAoB,EACpB,kBAAkB,EAClB,WAAW,EACX,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,aAAa,EACb,cAAc,EACd,SAAS,EACT,aAAa,EACb,OAAO,GACR,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/png/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,SAAS,IAAI,UAAU,EAAE,MAAM,aAAa,CAAC;AAEtD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC;AAO1C,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,oBAAoB,EACpB,kBAAkB,EAClB,WAAW,EACX,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,aAAa,EACb,cAAc,EACd,SAAS,EACT,aAAa,EACb,OAAO,GACR,MAAM,aAAa,CAAC"}
@@ -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"}
@@ -0,0 +1,176 @@
1
+ import { readAll } from "../bytes-util.js";
2
+ import { DEFAULT_PSD_CAPS, findSignature, hasSignatureAt, looksLikePsdAt, mapSections, parseHeader, rowBytes, u16be, u32be, u64be, walkImageResources, } from "./format.js";
3
+ const SCAN_WINDOW = 64 * 1024;
4
+ export function diagnosePsdBytes(b, caps = DEFAULT_PSD_CAPS) {
5
+ const notes = [];
6
+ const base = {
7
+ notes,
8
+ signatureOffset: null,
9
+ version: null,
10
+ width: null,
11
+ height: null,
12
+ channels: null,
13
+ depth: null,
14
+ colorMode: null,
15
+ compression: null,
16
+ hasThumbnail: false,
17
+ prefixBytes: 0,
18
+ };
19
+ const done = (damageClass, confidence) => ({
20
+ damageClass,
21
+ confidence,
22
+ ...base,
23
+ });
24
+ if (b.length < 26) {
25
+ notes.push(`file is only ${b.length} bytes: too small to be a PSD`);
26
+ return done("not-psd", "high");
27
+ }
28
+ // Signature location.
29
+ let sigOff = -1;
30
+ if (hasSignatureAt(b, 0))
31
+ sigOff = 0;
32
+ else {
33
+ const at = findSignature(b, SCAN_WINDOW);
34
+ if (at > 0) {
35
+ base.signatureOffset = at;
36
+ base.prefixBytes = at;
37
+ notes.push(`valid 8BPS signature found at offset ${at} (garbage prefix)`);
38
+ // fall through to header validation against the found offset for a richer note
39
+ const h = parseHeader(b, at);
40
+ if (h)
41
+ fillHeader(base, h, notes);
42
+ return done("garbage-prefix", "high");
43
+ }
44
+ if (looksLikePsdAt(b, 0)) {
45
+ base.signatureOffset = 0;
46
+ notes.push('the "8B" marker is present but the full 8BPS signature is damaged');
47
+ return done("signature-damage", "high");
48
+ }
49
+ notes.push("no 8BPS signature at the start and none found within the scan window");
50
+ return done("not-psd", b.length > SCAN_WINDOW ? "medium" : "high");
51
+ }
52
+ base.signatureOffset = sigOff;
53
+ const header = parseHeader(b, sigOff);
54
+ if (!header) {
55
+ notes.push("8BPS signature present but the 26-byte header is invalid (geometry / depth / mode / version)");
56
+ return done("header-damage", "high");
57
+ }
58
+ fillHeader(base, header, notes);
59
+ // Bomb guard.
60
+ if (header.width * header.height > caps.maxPixels) {
61
+ notes.push(`declared ${header.width}x${header.height} exceeds the safety cap: possible decompression bomb`);
62
+ return done("unknown", "high");
63
+ }
64
+ const sec = mapSections(b, header);
65
+ // Color-mode length must match the color mode.
66
+ const cmLen = sec.colorMode.length;
67
+ if (header.colorMode === 3 || header.colorMode === 1 || header.colorMode === 9) {
68
+ if (cmLen !== 0) {
69
+ notes.push(`color-mode data length is ${cmLen} but must be 0 for this color mode: corrupt length field`);
70
+ return done("bad-section-length", "high");
71
+ }
72
+ }
73
+ else if (header.colorMode === 2 && cmLen !== 768) {
74
+ notes.push(`indexed color needs a 768-byte palette but the length is ${cmLen}: corrupt length field`);
75
+ return done("bad-section-length", "high");
76
+ }
77
+ // Any declared length larger than the whole file = a corrupt length field, not truncation.
78
+ for (const [name, span] of [
79
+ ["colorMode", sec.colorMode],
80
+ ["imageResources", sec.imageResources],
81
+ ["layerAndMask", sec.layerAndMask],
82
+ ]) {
83
+ if (span.length > b.length) {
84
+ notes.push(`${name} declares ${span.length} bytes, larger than the whole file: corrupt length field`);
85
+ return done("bad-section-length", "high");
86
+ }
87
+ }
88
+ // Image resources: declared non-empty but doesn't start with an 8BIM block.
89
+ if (sec.imageResources.length > 0) {
90
+ const r = sec.imageResources.dataOffset;
91
+ const startsWith8bim = b[r] === 0x38 && b[r + 1] === 0x42 && b[r + 2] === 0x49 && b[r + 3] === 0x4d;
92
+ if (!startsWith8bim) {
93
+ notes.push("image-resources section does not begin with an 8BIM block: corrupt length/offset");
94
+ return done("bad-section-length", "high");
95
+ }
96
+ }
97
+ const resWalk = walkImageResources(b, sec.imageResources.dataOffset, sec.imageResources.length);
98
+ base.hasThumbnail = !!resWalk.thumbnail;
99
+ // Truncation: a section that fits in magnitude but runs past EOF.
100
+ if (sec.danglingSections.length > 0) {
101
+ notes.push(`section(s) run past end-of-file: ${sec.danglingSections.join(", ")} — file is truncated`);
102
+ return done("truncated", base.hasThumbnail ? "high" : "medium");
103
+ }
104
+ // Image-data (composite) boundary checks — magnitude only, no pixel decode.
105
+ const idOff = sec.imageDataOffset;
106
+ if (idOff + 2 > b.length) {
107
+ notes.push("file ends before the image-data section: the composite is missing");
108
+ return done(base.hasThumbnail ? "thumbnail-only" : "truncated", base.hasThumbnail ? "high" : "medium");
109
+ }
110
+ const compression = u16be(b, idOff);
111
+ base.compression = compression;
112
+ if (compression > 3) {
113
+ notes.push(`image-data compression flag is ${compression} (must be 0..3): composite header corrupt`);
114
+ return done("composite-corruption", "high");
115
+ }
116
+ const rb = rowBytes(header.width, header.depth);
117
+ const avail = b.length - (idOff + 2);
118
+ if (compression === 0) {
119
+ const need = rb * header.height * header.channels;
120
+ if (need > avail) {
121
+ notes.push(`raw composite needs ${need} bytes but only ${avail} remain: truncated`);
122
+ return done(base.hasThumbnail ? "thumbnail-only" : "truncated", "high");
123
+ }
124
+ }
125
+ else if (compression === 1) {
126
+ const entries = header.height * header.channels;
127
+ const entryW = header.version === 2 ? 4 : 2;
128
+ const tableSize = entries * entryW;
129
+ if (2 + tableSize > avail + 2) {
130
+ notes.push("RLE scanline byte-count table is truncated");
131
+ return done(base.hasThumbnail ? "thumbnail-only" : "truncated", "high");
132
+ }
133
+ let sum = 0;
134
+ let p = idOff + 2;
135
+ for (let i = 0; i < entries; i++) {
136
+ sum += entryW === 4 ? u32be(b, p) : u16be(b, p);
137
+ p += entryW;
138
+ }
139
+ if (tableSize + sum > avail) {
140
+ notes.push(`RLE data needs ${tableSize + sum} bytes but only ${avail} remain: truncated`);
141
+ return done(base.hasThumbnail ? "thumbnail-only" : "truncated", "high");
142
+ }
143
+ }
144
+ // compression 2/3 (ZIP) boundary can't be checked without inflating; trust presence.
145
+ // Light layer-section sanity (no full parse): a corrupt layer-info length /
146
+ // absurd layer count = the classic "won't open, but the composite is fine".
147
+ if (sec.layerAndMask.length > 0) {
148
+ const lmData = sec.layerAndMask.dataOffset;
149
+ const lenW = header.version === 2 ? 8 : 4;
150
+ if (lmData + lenW + 2 <= b.length) {
151
+ const layerInfoLen = lenW === 8 ? u64be(b, lmData) : u32be(b, lmData);
152
+ const bodyMax = sec.layerAndMask.length - lenW;
153
+ const layerCount = int16(u16be(b, lmData + lenW));
154
+ if (layerInfoLen > bodyMax || Math.abs(layerCount) > 8000) {
155
+ notes.push("layer section is damaged (implausible layer-info length / count); the composite is intact");
156
+ notes.push("layers cannot be reconstructed — repair will hand back the flattened composite");
157
+ return done("layers-damaged", "high");
158
+ }
159
+ }
160
+ }
161
+ notes.push(`PSD OK: ${header.width}x${header.height}, ${header.channels}ch, ${header.depth}-bit, mode ${header.colorMode}`);
162
+ return done("none", "high");
163
+ }
164
+ const int16 = (v) => (v >= 0x8000 ? v - 0x10000 : v);
165
+ function fillHeader(base, h, _notes) {
166
+ base.version = h.version;
167
+ base.width = h.width;
168
+ base.height = h.height;
169
+ base.channels = h.channels;
170
+ base.depth = h.depth;
171
+ base.colorMode = h.colorMode;
172
+ }
173
+ export async function diagnosePsd(src, caps = DEFAULT_PSD_CAPS) {
174
+ return diagnosePsdBytes(await readAll(src), caps);
175
+ }
176
+ //# sourceMappingURL=diagnose.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnose.js","sourceRoot":"","sources":["../../src/psd/diagnose.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Pure PSD/PSB byte primitives: header parse/serialize, the four length-prefixed
3
+ * sections, image-resource (8BIM) walking, the embedded thumbnail, and the
4
+ * composite codec (raw / RLE-PackBits / ZIP). No wasm, no I/O — everything here
5
+ * is plain byte arithmetic, safe in the browser root export and unit-testable.
6
+ *
7
+ * A "repaired PSD" here means the FLATTENED composite is recovered — never the
8
+ * layer stack. See docs/engineering/engine-psd.md. All fields are big-endian.
9
+ */
10
+ /** "8BPS" */
11
+ export declare const PSD_SIGNATURE: Uint8Array<ArrayBuffer>;
12
+ export type PsdColorMode = number;
13
+ export type PsdCompression = 0 | 1 | 2 | 3;
14
+ export interface PsdHeader {
15
+ version: 1 | 2;
16
+ channels: number;
17
+ height: number;
18
+ width: number;
19
+ depth: number;
20
+ colorMode: PsdColorMode;
21
+ }
22
+ export interface PsdSafetyCaps {
23
+ maxWidth: number;
24
+ maxHeight: number;
25
+ maxPixels: number;
26
+ /** Hard ceiling on the decoded composite (all planes). */
27
+ maxCompositeBytes: number;
28
+ }
29
+ /** PSB tops out at 300000²; cap pixels/bytes well below a memory bomb. */
30
+ export declare const DEFAULT_PSD_CAPS: PsdSafetyCaps;
31
+ export declare const u16be: (b: Uint8Array, o: number) => number;
32
+ export declare const u32be: (b: Uint8Array, o: number) => number;
33
+ /** 64-bit big-endian as a JS number (safe for our bounded offsets). */
34
+ export declare const u64be: (b: Uint8Array, o: number) => number;
35
+ export declare function writeU16be(b: Uint8Array, o: number, v: number): void;
36
+ export declare function writeU32be(b: Uint8Array, o: number, v: number): void;
37
+ export declare function hasSignatureAt(b: Uint8Array, off: number): boolean;
38
+ /** The "8B" fingerprint is present but the full "8BPS" magic is not exact. */
39
+ export declare function looksLikePsdAt(b: Uint8Array, off: number): boolean;
40
+ /** First offset of a valid 8BPS signature within `window`, or -1. */
41
+ export declare function findSignature(b: Uint8Array, window: number): number;
42
+ /** Parse and validate the 26-byte header at `off`. Returns null if implausible. */
43
+ export declare function parseHeader(b: Uint8Array, off?: number): PsdHeader | null;
44
+ export declare function serializeHeader(h: PsdHeader): Uint8Array;
45
+ /** Bytes per scanline for one channel at this width/depth. */
46
+ export declare const rowBytes: (width: number, depth: number) => number;
47
+ /** Length of the color-mode data section forced by color mode (0 unless Indexed/Duotone). */
48
+ export declare function expectedColorModeLen(actualLen: number, colorMode: PsdColorMode): number;
49
+ export interface SectionSpan {
50
+ offset: number;
51
+ dataOffset: number;
52
+ length: number;
53
+ end: number;
54
+ }
55
+ export interface PsdSections {
56
+ header: PsdHeader;
57
+ colorMode: SectionSpan;
58
+ imageResources: SectionSpan;
59
+ layerAndMask: SectionSpan;
60
+ /** Offset of the image-data section (2-byte compression flag lives here). */
61
+ imageDataOffset: number;
62
+ /** Any section whose declared length runs past EOF. */
63
+ danglingSections: string[];
64
+ }
65
+ /**
66
+ * Walk the section chain from offset 26, trusting declared lengths. Records
67
+ * sections that dangle past EOF (the truncation / bad-length signal). Never
68
+ * decodes pixels.
69
+ */
70
+ export declare function mapSections(b: Uint8Array, header: PsdHeader): PsdSections;
71
+ export interface ResourceBlock {
72
+ id: number;
73
+ offset: number;
74
+ dataOffset: number;
75
+ dataLength: number;
76
+ totalLength: number;
77
+ }
78
+ export interface ResourceWalk {
79
+ blocks: ResourceBlock[];
80
+ /** True byte length of a well-formed resources section (may differ from declared). */
81
+ trueLength: number;
82
+ /** Embedded thumbnail JPEG (resource 1036/1033), if a full FFD8..FFD9 is present. */
83
+ thumbnail?: {
84
+ offset: number;
85
+ length: number;
86
+ resourceId: number;
87
+ };
88
+ }
89
+ /** Re-walk the self-delimiting 8BIM resource blocks; recompute the true length. */
90
+ export declare function walkImageResources(b: Uint8Array, start: number, declaredLen: number): ResourceWalk;
91
+ /** Largest complete FFD8..FFD9 JPEG within [from,to). */
92
+ export declare function findJpeg(b: Uint8Array, from: number, to: number): {
93
+ offset: number;
94
+ length: number;
95
+ } | null;
96
+ /**
97
+ * Decode one PackBits scanline from b[pos..end) into up to `outLen` bytes.
98
+ * Returns the row and how many output bytes were produced (short if damaged).
99
+ */
100
+ export declare function unpackBitsRow(b: Uint8Array, pos: number, end: number, outLen: number): {
101
+ row: Uint8Array;
102
+ produced: number;
103
+ };
104
+ /** Encode one scanline with PackBits (Adobe/TIFF variant). */
105
+ export declare function packBitsRow(row: Uint8Array): Uint8Array;
106
+ //# sourceMappingURL=format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/psd/format.ts"],"names":[],"mappings":"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"}