diff --git a/crates/guara-core/src/report.rs b/crates/guara-core/src/report.rs index 804fffb..569d6f8 100644 --- a/crates/guara-core/src/report.rs +++ b/crates/guara-core/src/report.rs @@ -101,6 +101,37 @@ pub fn csv(found: &[&Found]) -> String { out } +/// The Guará logo, embedded so the report renders identically as a +/// standalone, offline HTML/PDF export (same reasoning as +/// `Sabiá/crates/sabia-core/src/report.rs`, which this mirrors): a +/// `src="/logo.png"` reference would 404 once the file is saved outside the +/// app's own server, and a forensic report that only half-renders without +/// network access defeats its purpose as a portable piece of evidence. +const LOGO_PNG: &[u8] = include_bytes!("../../../logo.png"); +const B64: &[u8; 64] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +/// Encodes the embedded logo as a `data:image/png;base64,...` URI. +fn logo_data_uri() -> String { + let mut out = String::with_capacity(LOGO_PNG.len().div_ceil(3) * 4 + 22); + out.push_str("data:image/png;base64,"); + for chunk in LOGO_PNG.chunks(3) { + let b0 = chunk[0]; + let b1 = chunk.get(1).copied(); + let b2 = chunk.get(2).copied(); + out.push(B64[(b0 >> 2) as usize] as char); + out.push(B64[(((b0 & 0b11) << 4) | (b1.unwrap_or(0) >> 4)) as usize] as char); + out.push(match b1 { + Some(b1) => B64[(((b1 & 0b1111) << 2) | (b2.unwrap_or(0) >> 6)) as usize] as char, + None => '=', + }); + out.push(match b2 { + Some(b2) => B64[(b2 & 0b111111) as usize] as char, + None => '=', + }); + } + out +} + fn esc(s: &str) -> String { s.replace('&', "&") .replace('<', "<") @@ -135,6 +166,9 @@ pub fn html(r: &ReportInput) -> String { r#"Guará: relatório de recuperação
"#, ); - o.push_str("

Relatório de recuperação de arquivos

Gerado pelo Guará "); + o.push_str("
\"\"

Relatório de recuperação de arquivos

TLP:AMBERUso autorizado
Gerado pelo Guará "); o.push_str(env!("CARGO_PKG_VERSION")); o.push_str(&format!(" em {}
", fmt_unix(now)));