3bb690e5bb
CI / Format (push) Successful in 4s
CI / Clippy (push) Successful in 4m19s
CI / Security Audit (push) Successful in 1m44s
CI / Tests (push) Successful in 5m15s
CI / Detect Changes (push) Successful in 5s
CI / Deploy Agent (push) Successful in 2s
CI / Deploy Dashboard (push) Successful in 2s
CI / Deploy Docs (push) Has been skipped
CI / Deploy MCP (push) Successful in 2s
44 lines
1.2 KiB
Rust
44 lines
1.2 KiB
Rust
use std::io::{Cursor, Write};
|
|
|
|
use zip::write::SimpleFileOptions;
|
|
use zip::AesMode;
|
|
|
|
use super::ReportContext;
|
|
|
|
pub(super) fn build_zip(
|
|
ctx: &ReportContext,
|
|
password: &str,
|
|
html: &str,
|
|
pdf: &[u8],
|
|
) -> Result<Vec<u8>, zip::result::ZipError> {
|
|
let buf = Cursor::new(Vec::new());
|
|
let mut zip = zip::ZipWriter::new(buf);
|
|
|
|
let options = SimpleFileOptions::default()
|
|
.compression_method(zip::CompressionMethod::Deflated)
|
|
.with_aes_encryption(AesMode::Aes256, password);
|
|
|
|
// report.pdf (primary)
|
|
zip.start_file("report.pdf", options)?;
|
|
zip.write_all(pdf)?;
|
|
|
|
// report.html (fallback)
|
|
zip.start_file("report.html", options)?;
|
|
zip.write_all(html.as_bytes())?;
|
|
|
|
// findings.json
|
|
let findings_json =
|
|
serde_json::to_string_pretty(&ctx.findings).unwrap_or_else(|_| "[]".to_string());
|
|
zip.start_file("findings.json", options)?;
|
|
zip.write_all(findings_json.as_bytes())?;
|
|
|
|
// attack-chain.json
|
|
let chain_json =
|
|
serde_json::to_string_pretty(&ctx.attack_chain).unwrap_or_else(|_| "[]".to_string());
|
|
zip.start_file("attack-chain.json", options)?;
|
|
zip.write_all(chain_json.as_bytes())?;
|
|
|
|
let cursor = zip.finish()?;
|
|
Ok(cursor.into_inner())
|
|
}
|