diff --git a/src/afterfact.rs b/src/afterfact.rs index 5aea8995..13e58316 100644 --- a/src/afterfact.rs +++ b/src/afterfact.rs @@ -546,7 +546,7 @@ fn emit_csv( } } if html_output_flag { - htmlreport::add_md_data("Results Summary".to_string(), html_output_stock); + htmlreport::add_md_data("Results Summary {#results_summary}".to_string(), html_output_stock); } Ok(()) } @@ -749,7 +749,8 @@ fn _print_detection_summary_by_computer( // html出力は各種すべてのコンピュータ名を表示するようにする if configs::CONFIG.read().unwrap().args.html_report.is_some() { html_output_stock.push(format!( - "### Computers with most unique {} detections:", + "### Computers with most unique {} detections: {{#computers_with_most_unique_{}_detections}}", + LEVEL_FULL.get(level.as_str()).unwrap(), LEVEL_FULL.get(level.as_str()).unwrap() )); for x in sorted_detections.iter() { @@ -804,7 +805,7 @@ fn _print_detection_summary_tables( let mut col_color = vec![]; for level in LEVEL_ABBR.values() { let mut col_output: Vec = vec![]; - let header_output = &format!("Top {} alerts:", LEVEL_FULL.get(level.as_str()).unwrap()); + let header_output = &format!("Top {} alerts: {{#top_{}_alerts}}", LEVEL_FULL.get(level.as_str()).unwrap(), LEVEL_FULL.get(level.as_str()).unwrap()); col_output.push(header_output.to_owned()); col_color.push(_get_table_color( diff --git a/src/detections/detection.rs b/src/detections/detection.rs index 9fea0f6c..b33fc109 100644 --- a/src/detections/detection.rs +++ b/src/detections/detection.rs @@ -696,7 +696,7 @@ impl Detection { html_report_stock.push(format!("- {}", tmp_total_detect_output)); } if !html_report_stock.is_empty() { - htmlreport::add_md_data("General Overview".to_string(), html_report_stock); + htmlreport::add_md_data("General Overview {#general_overview}".to_string(), html_report_stock); } } } diff --git a/src/main.rs b/src/main.rs index e423d6f9..489bdad4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -98,9 +98,8 @@ impl App { "- Start time: {}", analysis_start_time.format("%Y/%m/%d %H:%M") ), - "".to_string(), ]; - htmlreport::add_md_data("General Overview".to_string(), output_data); + htmlreport::add_md_data("General Overview {#general_overview}".to_string(), output_data); } // Show usage when no arguments. @@ -353,8 +352,8 @@ impl App { .ok(); println!(); if configs::CONFIG.read().unwrap().args.html_report.is_some() { - let output_data = vec![format!("- {}", elapsed_output_str), "".to_string()]; - htmlreport::add_md_data("General Overview".to_string(), output_data); + let output_data = vec![format!("- {}", elapsed_output_str)]; + htmlreport::add_md_data("General Overview {#general_overview}".to_string(), output_data); } // Qオプションを付けた場合もしくはパースのエラーがない場合はerrorのstackが0となるのでエラーログファイル自体が生成されない。 if ERROR_LOG_STACK.lock().unwrap().len() > 0 { @@ -575,9 +574,8 @@ impl App { let output_data = vec![ format!("- Analyzed event files: {}", evtx_files.len()), format!("- {}", total_size_output), - "".to_string(), ]; - htmlreport::add_md_data("General Overview".to_string(), output_data); + htmlreport::add_md_data("General Overview #{general_overview}".to_string(), output_data); } let rule_files = detection::Detection::parse_rule_files( diff --git a/src/options/htmlreport.rs b/src/options/htmlreport.rs index cf55a0de..db8e9ebc 100644 --- a/src/options/htmlreport.rs +++ b/src/options/htmlreport.rs @@ -32,6 +32,9 @@ impl HtmlReporter { pub fn create_html(self) -> String { let mut options = Options::empty(); options.insert(Options::ENABLE_TABLES); + options.insert(Options::ENABLE_HEADING_ATTRIBUTES); + options.insert(Options::ENABLE_FOOTNOTES); + let mut md_data = vec![]; for section_name in self.section_order { if let Some(v) = self.md_datas.get(§ion_name) { @@ -43,7 +46,7 @@ impl HtmlReporter { } } } - let md_str = md_data.join(""); + let md_str = md_data.join("\n"); let parser = Parser::new_ext(&md_str, options); let mut ret = String::new(); @@ -62,8 +65,8 @@ impl Default for HtmlReporter { fn get_init_md_data_map() -> (Vec, HashMap>) { let mut ret = HashMap::new(); let section_order = vec![ - "General Overview".to_string(), - "Results Summary".to_string(), + "General Overview {#general_overview}".to_string(), + "Results Summary {#results_summary}".to_string(), ]; for section in section_order.iter() { ret.insert(section.to_owned(), vec![]); @@ -132,7 +135,7 @@ mod tests { ]; html_reporter .md_datas - .insert("General Overview".to_string(), general_data.clone()); + .insert("General Overview {#general_overview}".to_string(), general_data.clone()); let general_overview_str = format!( "
    \n
  • {}
  • \n
", general_data[..general_data.len() - 1] @@ -140,7 +143,7 @@ mod tests { .replace("- ", "") ); let expect_str = format!( - "

General Overview

\n{}\n

Results Summary

\n

not found data.

\n", + "

General Overview

\n{}\n

Results Summary

\n

not found data.

\n", general_overview_str );