@intactfile/engines 0.1.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 (207) hide show
  1. package/README.md +68 -0
  2. package/dist/archive/diagnose.d.ts +37 -0
  3. package/dist/archive/diagnose.d.ts.map +1 -0
  4. package/dist/archive/diagnose.js +165 -0
  5. package/dist/archive/diagnose.js.map +1 -0
  6. package/dist/archive/format.d.ts +52 -0
  7. package/dist/archive/format.d.ts.map +1 -0
  8. package/dist/archive/format.js +87 -0
  9. package/dist/archive/format.js.map +1 -0
  10. package/dist/archive/host.d.ts +83 -0
  11. package/dist/archive/host.d.ts.map +1 -0
  12. package/dist/archive/host.js +92 -0
  13. package/dist/archive/host.js.map +1 -0
  14. package/dist/archive/index.d.ts +22 -0
  15. package/dist/archive/index.d.ts.map +1 -0
  16. package/dist/archive/index.js +19 -0
  17. package/dist/archive/index.js.map +1 -0
  18. package/dist/archive/salvage.d.ts +73 -0
  19. package/dist/archive/salvage.d.ts.map +1 -0
  20. package/dist/archive/salvage.js +210 -0
  21. package/dist/archive/salvage.js.map +1 -0
  22. package/dist/byte-source.d.ts +19 -0
  23. package/dist/byte-source.d.ts.map +1 -0
  24. package/dist/byte-source.js +16 -0
  25. package/dist/byte-source.js.map +1 -0
  26. package/dist/bytesource/blob.d.ts +14 -0
  27. package/dist/bytesource/blob.d.ts.map +1 -0
  28. package/dist/bytesource/blob.js +23 -0
  29. package/dist/bytesource/blob.js.map +1 -0
  30. package/dist/crc32.d.ts +2 -0
  31. package/dist/crc32.d.ts.map +1 -0
  32. package/dist/crc32.js +18 -0
  33. package/dist/crc32.js.map +1 -0
  34. package/dist/detect/index.d.ts +16 -0
  35. package/dist/detect/index.d.ts.map +1 -0
  36. package/dist/detect/index.js +159 -0
  37. package/dist/detect/index.js.map +1 -0
  38. package/dist/index.d.ts +24 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +17 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/jpeg/browser-loader.d.ts +21 -0
  43. package/dist/jpeg/browser-loader.d.ts.map +1 -0
  44. package/dist/jpeg/browser-loader.js +28 -0
  45. package/dist/jpeg/browser-loader.js.map +1 -0
  46. package/dist/jpeg/diagnose.d.ts +50 -0
  47. package/dist/jpeg/diagnose.d.ts.map +1 -0
  48. package/dist/jpeg/diagnose.js +124 -0
  49. package/dist/jpeg/diagnose.js.map +1 -0
  50. package/dist/jpeg/exif.d.ts +11 -0
  51. package/dist/jpeg/exif.d.ts.map +1 -0
  52. package/dist/jpeg/exif.js +50 -0
  53. package/dist/jpeg/exif.js.map +1 -0
  54. package/dist/jpeg/format.d.ts +106 -0
  55. package/dist/jpeg/format.d.ts.map +1 -0
  56. package/dist/jpeg/format.js +248 -0
  57. package/dist/jpeg/format.js.map +1 -0
  58. package/dist/jpeg/index.d.ts +18 -0
  59. package/dist/jpeg/index.d.ts.map +1 -0
  60. package/dist/jpeg/index.js +14 -0
  61. package/dist/jpeg/index.js.map +1 -0
  62. package/dist/jpeg/mozjpeg-host.d.ts +60 -0
  63. package/dist/jpeg/mozjpeg-host.d.ts.map +1 -0
  64. package/dist/jpeg/mozjpeg-host.js +138 -0
  65. package/dist/jpeg/mozjpeg-host.js.map +1 -0
  66. package/dist/jpeg/repair.d.ts +89 -0
  67. package/dist/jpeg/repair.d.ts.map +1 -0
  68. package/dist/jpeg/repair.js +216 -0
  69. package/dist/jpeg/repair.js.map +1 -0
  70. package/dist/node.d.ts +11 -0
  71. package/dist/node.d.ts.map +1 -0
  72. package/dist/node.js +29 -0
  73. package/dist/node.js.map +1 -0
  74. package/dist/pdf/browser-loader.d.ts +30 -0
  75. package/dist/pdf/browser-loader.d.ts.map +1 -0
  76. package/dist/pdf/browser-loader.js +21 -0
  77. package/dist/pdf/browser-loader.js.map +1 -0
  78. package/dist/pdf/diagnose.d.ts +23 -0
  79. package/dist/pdf/diagnose.d.ts.map +1 -0
  80. package/dist/pdf/diagnose.js +113 -0
  81. package/dist/pdf/diagnose.js.map +1 -0
  82. package/dist/pdf/format.d.ts +61 -0
  83. package/dist/pdf/format.d.ts.map +1 -0
  84. package/dist/pdf/format.js +150 -0
  85. package/dist/pdf/format.js.map +1 -0
  86. package/dist/pdf/index.d.ts +17 -0
  87. package/dist/pdf/index.d.ts.map +1 -0
  88. package/dist/pdf/index.js +12 -0
  89. package/dist/pdf/index.js.map +1 -0
  90. package/dist/pdf/qpdf-host.d.ts +66 -0
  91. package/dist/pdf/qpdf-host.d.ts.map +1 -0
  92. package/dist/pdf/qpdf-host.js +149 -0
  93. package/dist/pdf/qpdf-host.js.map +1 -0
  94. package/dist/pdf/rebuild.d.ts +32 -0
  95. package/dist/pdf/rebuild.d.ts.map +1 -0
  96. package/dist/pdf/rebuild.js +90 -0
  97. package/dist/pdf/rebuild.js.map +1 -0
  98. package/dist/pdf/repair.d.ts +61 -0
  99. package/dist/pdf/repair.d.ts.map +1 -0
  100. package/dist/pdf/repair.js +167 -0
  101. package/dist/pdf/repair.js.map +1 -0
  102. package/dist/png/diagnose.d.ts +50 -0
  103. package/dist/png/diagnose.d.ts.map +1 -0
  104. package/dist/png/diagnose.js +261 -0
  105. package/dist/png/diagnose.js.map +1 -0
  106. package/dist/png/format.d.ts +133 -0
  107. package/dist/png/format.d.ts.map +1 -0
  108. package/dist/png/format.js +350 -0
  109. package/dist/png/format.js.map +1 -0
  110. package/dist/png/index.d.ts +13 -0
  111. package/dist/png/index.d.ts.map +1 -0
  112. package/dist/png/index.js +10 -0
  113. package/dist/png/index.js.map +1 -0
  114. package/dist/png/repair.d.ts +31 -0
  115. package/dist/png/repair.d.ts.map +1 -0
  116. package/dist/png/repair.js +335 -0
  117. package/dist/png/repair.js.map +1 -0
  118. package/dist/sqlite/diagnose.d.ts +31 -0
  119. package/dist/sqlite/diagnose.d.ts.map +1 -0
  120. package/dist/sqlite/diagnose.js +169 -0
  121. package/dist/sqlite/diagnose.js.map +1 -0
  122. package/dist/sqlite/format.d.ts +103 -0
  123. package/dist/sqlite/format.d.ts.map +1 -0
  124. package/dist/sqlite/format.js +237 -0
  125. package/dist/sqlite/format.js.map +1 -0
  126. package/dist/sqlite/index.d.ts +24 -0
  127. package/dist/sqlite/index.d.ts.map +1 -0
  128. package/dist/sqlite/index.js +19 -0
  129. package/dist/sqlite/index.js.map +1 -0
  130. package/dist/sqlite/recover.d.ts +66 -0
  131. package/dist/sqlite/recover.d.ts.map +1 -0
  132. package/dist/sqlite/recover.js +305 -0
  133. package/dist/sqlite/recover.js.map +1 -0
  134. package/dist/sqlite/scan.d.ts +94 -0
  135. package/dist/sqlite/scan.d.ts.map +1 -0
  136. package/dist/sqlite/scan.js +356 -0
  137. package/dist/sqlite/scan.js.map +1 -0
  138. package/dist/sqlite/sqlite-host.d.ts +37 -0
  139. package/dist/sqlite/sqlite-host.d.ts.map +1 -0
  140. package/dist/sqlite/sqlite-host.js +80 -0
  141. package/dist/sqlite/sqlite-host.js.map +1 -0
  142. package/dist/sqlite/wal.d.ts +14 -0
  143. package/dist/sqlite/wal.d.ts.map +1 -0
  144. package/dist/sqlite/wal.js +79 -0
  145. package/dist/sqlite/wal.js.map +1 -0
  146. package/dist/types.d.ts +2 -0
  147. package/dist/types.d.ts.map +1 -0
  148. package/dist/types.js +2 -0
  149. package/dist/types.js.map +1 -0
  150. package/dist/video/diagnose.d.ts +41 -0
  151. package/dist/video/diagnose.d.ts.map +1 -0
  152. package/dist/video/diagnose.js +188 -0
  153. package/dist/video/diagnose.js.map +1 -0
  154. package/dist/video/format.d.ts +87 -0
  155. package/dist/video/format.d.ts.map +1 -0
  156. package/dist/video/format.js +273 -0
  157. package/dist/video/format.js.map +1 -0
  158. package/dist/video/index.d.ts +21 -0
  159. package/dist/video/index.d.ts.map +1 -0
  160. package/dist/video/index.js +17 -0
  161. package/dist/video/index.js.map +1 -0
  162. package/dist/video/libav-host.d.ts +88 -0
  163. package/dist/video/libav-host.d.ts.map +1 -0
  164. package/dist/video/libav-host.js +66 -0
  165. package/dist/video/libav-host.js.map +1 -0
  166. package/dist/video/mp4-rebuild.d.ts +167 -0
  167. package/dist/video/mp4-rebuild.d.ts.map +1 -0
  168. package/dist/video/mp4-rebuild.js +270 -0
  169. package/dist/video/mp4-rebuild.js.map +1 -0
  170. package/dist/video/mp4box-host.d.ts +62 -0
  171. package/dist/video/mp4box-host.d.ts.map +1 -0
  172. package/dist/video/mp4box-host.js +209 -0
  173. package/dist/video/mp4box-host.js.map +1 -0
  174. package/dist/video/reconstruct.d.ts +97 -0
  175. package/dist/video/reconstruct.d.ts.map +1 -0
  176. package/dist/video/reconstruct.js +271 -0
  177. package/dist/video/reconstruct.js.map +1 -0
  178. package/dist/video/remux.d.ts +85 -0
  179. package/dist/video/remux.d.ts.map +1 -0
  180. package/dist/video/remux.js +350 -0
  181. package/dist/video/remux.js.map +1 -0
  182. package/dist/zip/diagnose.d.ts +22 -0
  183. package/dist/zip/diagnose.d.ts.map +1 -0
  184. package/dist/zip/diagnose.js +126 -0
  185. package/dist/zip/diagnose.js.map +1 -0
  186. package/dist/zip/format.d.ts +79 -0
  187. package/dist/zip/format.d.ts.map +1 -0
  188. package/dist/zip/format.js +129 -0
  189. package/dist/zip/format.js.map +1 -0
  190. package/dist/zip/repair.d.ts +32 -0
  191. package/dist/zip/repair.d.ts.map +1 -0
  192. package/dist/zip/repair.js +82 -0
  193. package/dist/zip/repair.js.map +1 -0
  194. package/dist/zip/salvage.d.ts +23 -0
  195. package/dist/zip/salvage.d.ts.map +1 -0
  196. package/dist/zip/salvage.js +140 -0
  197. package/dist/zip/salvage.js.map +1 -0
  198. package/dist/zip/scan.d.ts +64 -0
  199. package/dist/zip/scan.d.ts.map +1 -0
  200. package/dist/zip/scan.js +386 -0
  201. package/dist/zip/scan.js.map +1 -0
  202. package/dist/zip/writer.d.ts +14 -0
  203. package/dist/zip/writer.d.ts.map +1 -0
  204. package/dist/zip/writer.js +131 -0
  205. package/dist/zip/writer.js.map +1 -0
  206. package/package.json +71 -0
  207. package/src/archive/LICENSE-unrar.txt +53 -0
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Archive engine subpath export (`@intactfile/engines/archive`) — RAR/7z
3
+ * SALVAGE extraction (recover intact entries from a damaged archive), not deep
4
+ * repair. Kept out of the root export so browser bundles that never touch
5
+ * archives never pull in the 7z-wasm dependency; even here, the wasm only loads
6
+ * on the first salvageArchive call. diagnoseArchive is pure byte-sniffing and
7
+ * loads no wasm.
8
+ *
9
+ * License note: extraction (including RAR via 7-Zip's unRAR-derived decoder) is
10
+ * permitted; RAR CREATION is not and is never performed. The unRAR license text
11
+ * ships next to this module at ./LICENSE-unrar.txt.
12
+ */
13
+ export { diagnoseArchive } from './diagnose.js';
14
+ export type { ArchiveDiagnosis, ArchiveFormat, ArchiveDamageClass } from './diagnose.js';
15
+ export { salvageArchive, parseSltListing } from './salvage.js';
16
+ export type { SalvagedFile, SalvageStatus, SalvageOutcome, SalvageReport, SalvageEntrySummary, SalvageOptions, } from './salvage.js';
17
+ export { withSevenZip, ensureSevenZip, setSevenZipLoader, resetSevenZipHost, } from './host.js';
18
+ export type { SevenZipLoader, SevenZipFactory, SevenZipModule, SevenZipModuleOptions, SevenZipSession, SevenZipResult, SevenZipFS, } from './host.js';
19
+ export { SIG_7Z, SIG_RAR4, SIG_RAR5, matchAt, indexOfSig, } from './format.js';
20
+ /** Relative path (from this module) to the shipped unRAR license text. */
21
+ export declare const UNRAR_LICENSE_FILE = "LICENSE-unrar.txt";
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/archive/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAEzF,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/D,YAAY,EACV,YAAY,EACZ,aAAa,EACb,cAAc,EACd,aAAa,EACb,mBAAmB,EACnB,cAAc,GACf,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,WAAW,CAAC;AACnB,YAAY,EACV,cAAc,EACd,eAAe,EACf,cAAc,EACd,qBAAqB,EACrB,eAAe,EACf,cAAc,EACd,UAAU,GACX,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,UAAU,GACX,MAAM,aAAa,CAAC;AAErB,0EAA0E;AAC1E,eAAO,MAAM,kBAAkB,sBAAsB,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Archive engine subpath export (`@intactfile/engines/archive`) — RAR/7z
3
+ * SALVAGE extraction (recover intact entries from a damaged archive), not deep
4
+ * repair. Kept out of the root export so browser bundles that never touch
5
+ * archives never pull in the 7z-wasm dependency; even here, the wasm only loads
6
+ * on the first salvageArchive call. diagnoseArchive is pure byte-sniffing and
7
+ * loads no wasm.
8
+ *
9
+ * License note: extraction (including RAR via 7-Zip's unRAR-derived decoder) is
10
+ * permitted; RAR CREATION is not and is never performed. The unRAR license text
11
+ * ships next to this module at ./LICENSE-unrar.txt.
12
+ */
13
+ export { diagnoseArchive } from './diagnose.js';
14
+ export { salvageArchive, parseSltListing } from './salvage.js';
15
+ export { withSevenZip, ensureSevenZip, setSevenZipLoader, resetSevenZipHost, } from './host.js';
16
+ export { SIG_7Z, SIG_RAR4, SIG_RAR5, matchAt, indexOfSig, } from './format.js';
17
+ /** Relative path (from this module) to the shipped unRAR license text. */
18
+ export const UNRAR_LICENSE_FILE = 'LICENSE-unrar.txt';
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/archive/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAGhD,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAU/D,OAAO,EACL,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,WAAW,CAAC;AAWnB,OAAO,EACL,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,UAAU,GACX,MAAM,aAAa,CAAC;AAErB,0EAA0E;AAC1E,MAAM,CAAC,MAAM,kBAAkB,GAAG,mBAAmB,CAAC"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Salvage extraction of intact entries from a damaged 7z or RAR archive, via
3
+ * 7z-wasm. This is NOT deep repair: no recovery-record reconstruction, no
4
+ * re-deriving a lost 7z directory. It lists whatever the 7-Zip engine can still
5
+ * enumerate and extracts each entry on its own, keeping the ones that come out
6
+ * whole and honestly marking the rest.
7
+ *
8
+ * Honesty rules (docs/03):
9
+ * - a 7z file stores its directory at the END, so tail truncation removes the
10
+ * entry list entirely — there is then nothing to enumerate and salvage
11
+ * reports 'failed', never a fake success;
12
+ * - a solid 7z packs all entries into one stream, so a corruption point loses
13
+ * every entry after it — reported as a caveat and reflected in the counts;
14
+ * - encrypted entries without a password are marked 'encrypted', never
15
+ * silently skipped or reported as recovered;
16
+ * - an entry is only 'ok' when its extracted bytes match the listed size;
17
+ * - RAR recovery-record repair is out of scope, and RAR archives are NEVER
18
+ * created (unRAR license — see ./LICENSE-unrar.txt); only `l`/`x` run.
19
+ */
20
+ import type { ByteSource } from '../byte-source.js';
21
+ import { type ArchiveDiagnosis, type ArchiveFormat } from './diagnose.js';
22
+ export type SalvageStatus = 'ok' | 'corrupt' | 'encrypted';
23
+ export interface SalvagedFile {
24
+ name: string;
25
+ /** Recovered bytes for 'ok'; empty for 'corrupt'/'encrypted' (no trustworthy data). */
26
+ data: Uint8Array;
27
+ status: SalvageStatus;
28
+ }
29
+ export type SalvageOutcome = 'success' | 'partial' | 'failed';
30
+ export interface SalvageEntrySummary {
31
+ name: string;
32
+ status: SalvageStatus;
33
+ /** Listed uncompressed size, or null when the directory could not report it. */
34
+ size: number | null;
35
+ }
36
+ export interface SalvageReport {
37
+ outcome: SalvageOutcome;
38
+ format: ArchiveFormat;
39
+ /** Entries recovered whole (status 'ok'). */
40
+ filesRecovered: number;
41
+ /** Entries the directory listed (non-directory). */
42
+ filesTotal: number;
43
+ entries: SalvageEntrySummary[];
44
+ /** Any entry was encrypted (or the whole header was). */
45
+ encrypted: boolean;
46
+ /** Archive is solid (one shared stream). */
47
+ solid: boolean;
48
+ notes: string[];
49
+ }
50
+ export interface SalvageOptions {
51
+ /** Password for encrypted archives/entries. */
52
+ password?: string;
53
+ /** Reuse an existing diagnosis instead of re-sniffing. */
54
+ diagnosis?: ArchiveDiagnosis;
55
+ }
56
+ export declare function salvageArchive(src: ByteSource, opts?: SalvageOptions): Promise<{
57
+ files: SalvagedFile[];
58
+ report: SalvageReport;
59
+ }>;
60
+ interface ListedEntry {
61
+ path: string;
62
+ size: number | null;
63
+ isDir: boolean;
64
+ encrypted: boolean;
65
+ }
66
+ interface Listing {
67
+ entries: ListedEntry[];
68
+ solid: boolean;
69
+ }
70
+ /** Parse `7z l -slt` output into per-entry records (skips the archive block). */
71
+ export declare function parseSltListing(stdout: string, archiveName: string): Listing;
72
+ export {};
73
+ //# sourceMappingURL=salvage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"salvage.d.ts","sourceRoot":"","sources":["../../src/archive/salvage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAmB,KAAK,gBAAgB,EAAE,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AAG3F,MAAM,MAAM,aAAa,GAAG,IAAI,GAAG,SAAS,GAAG,WAAW,CAAC;AAE3D,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,uFAAuF;IACvF,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,aAAa,CAAC;CACvB;AAED,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE9D,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,aAAa,CAAC;IACtB,gFAAgF;IAChF,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,cAAc,CAAC;IACxB,MAAM,EAAE,aAAa,CAAC;IACtB,6CAA6C;IAC7C,cAAc,EAAE,MAAM,CAAC;IACvB,oDAAoD;IACpD,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,mBAAmB,EAAE,CAAC;IAC/B,yDAAyD;IACzD,SAAS,EAAE,OAAO,CAAC;IACnB,4CAA4C;IAC5C,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,gBAAgB,CAAC;CAC9B;AAKD,wBAAsB,cAAc,CAClC,GAAG,EAAE,UAAU,EACf,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC;IAAE,KAAK,EAAE,YAAY,EAAE,CAAC;IAAC,MAAM,EAAE,aAAa,CAAA;CAAE,CAAC,CA+D3D;AA6HD,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,UAAU,OAAO;IACf,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,iFAAiF;AACjF,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CA+B5E"}
@@ -0,0 +1,210 @@
1
+ import { diagnoseArchive } from './diagnose.js';
2
+ import { ensureSevenZip, withSevenZip } from './host.js';
3
+ const EMPTY = new Uint8Array(0);
4
+ const OUT_DIR = '/salvage-out';
5
+ export async function salvageArchive(src, opts = {}) {
6
+ const diagnosis = opts.diagnosis ?? (await diagnoseArchive(src));
7
+ const notes = [...diagnosis.notes];
8
+ const files = [];
9
+ const entries = [];
10
+ let encrypted = false;
11
+ let solid = false;
12
+ const finalize = (outcome) => {
13
+ if (diagnosis.format.startsWith('rar')) {
14
+ notes.push('RAR entries are extracted with 7-Zip\'s unRAR-derived decoder (extraction only; see ' +
15
+ 'LICENSE-unrar.txt). RAR recovery-record repair is out of scope and RAR archives are never created.');
16
+ }
17
+ return {
18
+ files,
19
+ report: {
20
+ outcome,
21
+ format: diagnosis.format,
22
+ filesRecovered: files.filter((f) => f.status === 'ok').length,
23
+ filesTotal: entries.length,
24
+ entries,
25
+ encrypted,
26
+ solid,
27
+ notes,
28
+ },
29
+ };
30
+ };
31
+ // ZIP and non-archives are out of scope for this engine.
32
+ if (diagnosis.format === 'zip') {
33
+ notes.push('this input is a ZIP — run the ZIP engine (repairZip); the RAR/7z salvage engine does not process ZIP');
34
+ return finalize('failed');
35
+ }
36
+ if (diagnosis.damageClass === 'not-archive' || diagnosis.format === 'unknown') {
37
+ notes.push('input is not a 7z or RAR archive; there is nothing to salvage');
38
+ return finalize('failed');
39
+ }
40
+ // Surface loader failures (no loader in the browser, wasm fetch failed) as an
41
+ // honest 'failed' with an engine note, not a thrown error at the caller.
42
+ try {
43
+ await ensureSevenZip();
44
+ }
45
+ catch (e) {
46
+ notes.push(`archive engine unavailable: ${e instanceof Error ? e.message : String(e)}`);
47
+ return finalize('failed');
48
+ }
49
+ try {
50
+ return await withSevenZip((z) => runSalvage(z, src, diagnosis, opts, notes, entries, files, {
51
+ setEncrypted: () => {
52
+ encrypted = true;
53
+ },
54
+ setSolid: () => {
55
+ solid = true;
56
+ },
57
+ finalize,
58
+ }));
59
+ }
60
+ catch (e) {
61
+ notes.push(`archive engine error during salvage: ${e instanceof Error ? e.message : String(e)}`);
62
+ return finalize('failed');
63
+ }
64
+ }
65
+ async function runSalvage(z, src, diagnosis, opts, notes, entries, files, state) {
66
+ const ext = diagnosis.format.startsWith('rar') ? 'rar' : '7z';
67
+ const name = `input.${ext}`;
68
+ const pw = opts.password;
69
+ const pwArgs = pw !== undefined ? [`-p${pw}`] : [];
70
+ z.fs.writeFile(name, await src.read(0, src.size));
71
+ const listRes = z.run(['l', '-slt', name, ...pwArgs]);
72
+ const listing = parseSltListing(listRes.stdout, name);
73
+ if (listing.entries.length === 0) {
74
+ const combined = `${listRes.stdout}\n${listRes.stderr}`;
75
+ if (looksEncrypted(combined) || (listRes.code !== 0 && diagnosis.damageClass === 'none' && pw === undefined)) {
76
+ state.setEncrypted();
77
+ notes.push('the archive header is encrypted; a password is required to list or extract any entry');
78
+ return state.finalize('failed');
79
+ }
80
+ if (diagnosis.damageClass === 'truncated') {
81
+ notes.push('the entry directory (stored at the end of a 7z file) was lost to truncation; no entries could be enumerated');
82
+ return state.finalize('failed');
83
+ }
84
+ if (diagnosis.damageClass === 'header-damage') {
85
+ notes.push('the archive directory is damaged; 7-Zip could not enumerate any entries');
86
+ return state.finalize('failed');
87
+ }
88
+ notes.push(`no entries could be listed (7-Zip exit ${listRes.code})`);
89
+ const err = firstLine(listRes.stderr);
90
+ if (err)
91
+ notes.push(`7-Zip: ${err}`);
92
+ return state.finalize('failed');
93
+ }
94
+ if (listing.solid) {
95
+ state.setSolid();
96
+ notes.push('archive is solid: all entries share one compressed stream, so a corruption point loses every ' +
97
+ 'entry after it in the same block');
98
+ }
99
+ for (const entry of listing.entries) {
100
+ if (entry.isDir)
101
+ continue;
102
+ let status;
103
+ let data = EMPTY;
104
+ if (entry.encrypted && pw === undefined) {
105
+ state.setEncrypted();
106
+ status = 'encrypted';
107
+ }
108
+ else {
109
+ const xRes = z.run(['x', name, `-o${OUT_DIR}`, '-y', entry.path, ...pwArgs]);
110
+ const got = readIfExists(z.fs, `${OUT_DIR}/${entry.path}`);
111
+ const combined = `${xRes.stdout}\n${xRes.stderr}`;
112
+ const sizeOk = entry.size === null ? true : got !== null && got.length === entry.size;
113
+ if (got !== null && sizeOk && !hasErrorMarker(combined)) {
114
+ status = 'ok';
115
+ data = got;
116
+ }
117
+ else if (entry.encrypted || looksEncrypted(combined)) {
118
+ state.setEncrypted();
119
+ status = 'encrypted';
120
+ }
121
+ else {
122
+ status = 'corrupt';
123
+ notes.push(`entry "${entry.path}" is damaged: ${got !== null ? `only ${got.length} of ${entry.size ?? '?'} bytes recovered` : 'no data recovered'}`);
124
+ }
125
+ }
126
+ files.push({ name: entry.path, data, status });
127
+ entries.push({ name: entry.path, status, size: entry.size });
128
+ }
129
+ const okCount = files.filter((f) => f.status === 'ok').length;
130
+ const encCount = files.filter((f) => f.status === 'encrypted').length;
131
+ const total = entries.length;
132
+ if (encCount > 0) {
133
+ notes.push(`${encCount} encrypted entr${encCount === 1 ? 'y' : 'ies'}: ${pw === undefined ? 'supply a password to recover' : 'the supplied password did not unlock'} ${encCount === 1 ? 'it' : 'them'}`);
134
+ }
135
+ let outcome;
136
+ if (total === 0) {
137
+ outcome = 'success';
138
+ notes.push('archive is empty (only directory entries); nothing to recover');
139
+ }
140
+ else if (okCount === total) {
141
+ outcome = 'success';
142
+ }
143
+ else if (okCount > 0) {
144
+ outcome = 'partial';
145
+ }
146
+ else {
147
+ outcome = 'failed';
148
+ }
149
+ notes.push(`recovered ${okCount} of ${total} entr${total === 1 ? 'y' : 'ies'}`);
150
+ return state.finalize(outcome);
151
+ }
152
+ /** Parse `7z l -slt` output into per-entry records (skips the archive block). */
153
+ export function parseSltListing(stdout, archiveName) {
154
+ const blocks = stdout.split(/\r?\n\r?\n/);
155
+ const entries = [];
156
+ let solid = false;
157
+ for (const block of blocks) {
158
+ const kv = {};
159
+ for (const line of block.split(/\r?\n/)) {
160
+ const m = /^(.+?) = (.*)$/.exec(line);
161
+ if (m)
162
+ kv[m[1].trim()] = m[2].trim();
163
+ }
164
+ if (kv['Path'] === undefined)
165
+ continue;
166
+ // Archive info block: has a "Type" key (e.g. Type = 7z). Not an entry.
167
+ if (kv['Type'] !== undefined || kv['Path'] === archiveName) {
168
+ if (kv['Solid'] === '+')
169
+ solid = true;
170
+ continue;
171
+ }
172
+ const attrs = kv['Attributes'] ?? '';
173
+ const isDir = kv['Folder'] === '+' || /(^|\s|^\.*)D/.test(attrs) || attrs.startsWith('D');
174
+ const sizeStr = kv['Size'];
175
+ const size = sizeStr !== undefined && /^\d+$/.test(sizeStr) ? Number(sizeStr) : null;
176
+ entries.push({
177
+ path: kv['Path'],
178
+ size,
179
+ isDir,
180
+ encrypted: kv['Encrypted'] === '+',
181
+ });
182
+ }
183
+ return { entries, solid };
184
+ }
185
+ function readIfExists(fs, path) {
186
+ try {
187
+ const st = fs.stat(path);
188
+ if (!fs.isFile(st.mode))
189
+ return null;
190
+ return fs.readFile(path, { encoding: 'binary' });
191
+ }
192
+ catch {
193
+ return null;
194
+ }
195
+ }
196
+ function hasErrorMarker(s) {
197
+ return /\bERROR\b|Data Error|CRC (?:Failed|error)|Unsupported Method|Unexpected end|Headers Error|Wrong password|Can ?not open/i.test(s);
198
+ }
199
+ function looksEncrypted(s) {
200
+ return /Wrong password|Enter password|Cannot open encrypted|password[- ]?protected/i.test(s);
201
+ }
202
+ function firstLine(s) {
203
+ for (const line of s.split(/\r?\n/)) {
204
+ const t = line.trim();
205
+ if (t)
206
+ return t;
207
+ }
208
+ return '';
209
+ }
210
+ //# sourceMappingURL=salvage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"salvage.js","sourceRoot":"","sources":["../../src/archive/salvage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Random-access byte source abstraction. Implementations exist for Node file
3
+ * handles and in-memory buffers; the app adds a BlobSource in the browser.
4
+ */
5
+ export interface ByteSource {
6
+ readonly size: number;
7
+ /**
8
+ * Read up to `length` bytes at `offset`. Reads past EOF are clamped: the
9
+ * returned array may be shorter than requested (possibly empty).
10
+ */
11
+ read(offset: number, length: number): Promise<Uint8Array>;
12
+ }
13
+ export declare class MemorySource implements ByteSource {
14
+ private readonly data;
15
+ readonly size: number;
16
+ constructor(data: Uint8Array);
17
+ read(offset: number, length: number): Promise<Uint8Array>;
18
+ }
19
+ //# sourceMappingURL=byte-source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"byte-source.d.ts","sourceRoot":"","sources":["../src/byte-source.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CAC3D;AAED,qBAAa,YAAa,YAAW,UAAU;IAGjC,OAAO,CAAC,QAAQ,CAAC,IAAI;IAFjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEO,IAAI,EAAE,UAAU;IAIvC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;CAKhE"}
@@ -0,0 +1,16 @@
1
+ export class MemorySource {
2
+ data;
3
+ size;
4
+ constructor(data) {
5
+ this.data = data;
6
+ this.size = data.length;
7
+ }
8
+ async read(offset, length) {
9
+ if (offset < 0 || length < 0)
10
+ throw new RangeError('negative offset/length');
11
+ if (offset >= this.size)
12
+ return new Uint8Array(0);
13
+ return this.data.subarray(offset, Math.min(offset + length, this.size));
14
+ }
15
+ }
16
+ //# sourceMappingURL=byte-source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"byte-source.js","sourceRoot":"","sources":["../src/byte-source.ts"],"names":[],"mappings":"AAaA,MAAM,OAAO,YAAY;IAGM;IAFpB,IAAI,CAAS;IAEtB,YAA6B,IAAgB;QAAhB,SAAI,GAAJ,IAAI,CAAY;QAC3C,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,MAAc,EAAE,MAAc;QACvC,IAAI,MAAM,GAAG,CAAC,IAAI,MAAM,GAAG,CAAC;YAAE,MAAM,IAAI,UAAU,CAAC,wBAAwB,CAAC,CAAC;QAC7E,IAAI,MAAM,IAAI,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;QAClD,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1E,CAAC;CACF"}
@@ -0,0 +1,14 @@
1
+ import type { ByteSource } from '../byte-source.js';
2
+ /**
3
+ * Browser-safe ByteSource over a File/Blob. Reads ranges lazily via
4
+ * slice().arrayBuffer(), so only the bytes the engine asks for are ever
5
+ * pulled into memory — never the whole file up front. Also works in Node
6
+ * (>= 18), where Blob is a global.
7
+ */
8
+ export declare class BlobSource implements ByteSource {
9
+ private readonly blob;
10
+ readonly size: number;
11
+ constructor(blob: Blob);
12
+ read(offset: number, length: number): Promise<Uint8Array>;
13
+ }
14
+ //# sourceMappingURL=blob.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blob.d.ts","sourceRoot":"","sources":["../../src/bytesource/blob.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD;;;;;GAKG;AACH,qBAAa,UAAW,YAAW,UAAU;IAG/B,OAAO,CAAC,QAAQ,CAAC,IAAI;IAFjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEO,IAAI,EAAE,IAAI;IAIjC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;CAMhE"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Browser-safe ByteSource over a File/Blob. Reads ranges lazily via
3
+ * slice().arrayBuffer(), so only the bytes the engine asks for are ever
4
+ * pulled into memory — never the whole file up front. Also works in Node
5
+ * (>= 18), where Blob is a global.
6
+ */
7
+ export class BlobSource {
8
+ blob;
9
+ size;
10
+ constructor(blob) {
11
+ this.blob = blob;
12
+ this.size = blob.size;
13
+ }
14
+ async read(offset, length) {
15
+ if (offset < 0 || length < 0)
16
+ throw new RangeError('negative offset/length');
17
+ if (offset >= this.size || length === 0)
18
+ return new Uint8Array(0);
19
+ const end = Math.min(offset + length, this.size);
20
+ return new Uint8Array(await this.blob.slice(offset, end).arrayBuffer());
21
+ }
22
+ }
23
+ //# sourceMappingURL=blob.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blob.js","sourceRoot":"","sources":["../../src/bytesource/blob.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,OAAO,UAAU;IAGQ;IAFpB,IAAI,CAAS;IAEtB,YAA6B,IAAU;QAAV,SAAI,GAAJ,IAAI,CAAM;QACrC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,MAAc,EAAE,MAAc;QACvC,IAAI,MAAM,GAAG,CAAC,IAAI,MAAM,GAAG,CAAC;YAAE,MAAM,IAAI,UAAU,CAAC,wBAAwB,CAAC,CAAC;QAC7E,IAAI,MAAM,IAAI,IAAI,CAAC,IAAI,IAAI,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;QAClE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACjD,OAAO,IAAI,UAAU,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IAC1E,CAAC;CACF"}
@@ -0,0 +1,2 @@
1
+ export declare function crc32(data: Uint8Array, seed?: number): number;
2
+ //# sourceMappingURL=crc32.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crc32.d.ts","sourceRoot":"","sources":["../src/crc32.ts"],"names":[],"mappings":"AAUA,wBAAgB,KAAK,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,SAAI,GAAG,MAAM,CAMxD"}
package/dist/crc32.js ADDED
@@ -0,0 +1,18 @@
1
+ const TABLE = (() => {
2
+ const t = new Uint32Array(256);
3
+ for (let i = 0; i < 256; i++) {
4
+ let c = i;
5
+ for (let k = 0; k < 8; k++)
6
+ c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
7
+ t[i] = c >>> 0;
8
+ }
9
+ return t;
10
+ })();
11
+ export function crc32(data, seed = 0) {
12
+ let c = ~seed >>> 0;
13
+ for (let i = 0; i < data.length; i++) {
14
+ c = TABLE[(c ^ data[i]) & 0xff] ^ (c >>> 8);
15
+ }
16
+ return ~c >>> 0;
17
+ }
18
+ //# sourceMappingURL=crc32.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crc32.js","sourceRoot":"","sources":["../src/crc32.ts"],"names":[],"mappings":"AAAA,MAAM,KAAK,GAAG,CAAC,GAAG,EAAE;IAClB,MAAM,CAAC,GAAG,IAAI,WAAW,CAAC,GAAG,CAAC,CAAC;IAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7B,IAAI,CAAC,GAAG,CAAC,CAAC;QACV,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;YAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACzE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACjB,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC,CAAC,EAAE,CAAC;AAEL,MAAM,UAAU,KAAK,CAAC,IAAgB,EAAE,IAAI,GAAG,CAAC;IAC9C,IAAI,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,CAAC;IACpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC,GAAG,IAAI,CAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IAChD,CAAC;IACD,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC;AAClB,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { ByteSource } from '../byte-source.js';
2
+ import type { Confidence } from '../types.js';
3
+ export type FileFormat = 'zip' | 'pdf' | 'mp4' | 'mov' | 'jpeg' | 'png' | 'wav' | 'avi' | 'riff' | 'mkv' | 'webm' | 'mp3' | 'unknown';
4
+ export interface FormatDetection {
5
+ format: FileFormat;
6
+ /** Sub-container when known: docx/xlsx/pptx/ooxml/zip for zips, ftyp brand for mp4/mov, riff type for riff. */
7
+ container?: string;
8
+ confidence: Confidence;
9
+ notes: string[];
10
+ }
11
+ /**
12
+ * Magic-byte format sniffing with garbage-prefix tolerance. Shared diagnosis
13
+ * entry point for the app UI.
14
+ */
15
+ export declare function detectFormat(src: ByteSource): Promise<FormatDetection>;
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/detect/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAW9C,MAAM,MAAM,UAAU,GAClB,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,MAAM,GACN,KAAK,GACL,KAAK,GACL,KAAK,GACL,MAAM,GACN,KAAK,GACL,MAAM,GACN,KAAK,GACL,SAAS,CAAC;AAEd,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,UAAU,CAAC;IACnB,+GAA+G;IAC/G,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,UAAU,CAAC;IACvB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAoDD;;;GAGG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,eAAe,CAAC,CA2G5E"}