//! Handles export of results in HTML format use crate::output::ResultsFormatter; pub struct HtmlFormatter; fn escape_html(s: &str) -> String { let mut result = String::with_capacity(s.len()); for c in s.chars() { match c { '&' => result.push_str("&"), '<' => result.push_str("<"), '>' => result.push_str(">"), '"' => result.push_str("""), _ => result.push(c), } } result } impl ResultsFormatter for HtmlFormatter { fn header(&mut self, raw_query: &str, col_count: usize) -> Option { let escaped = escape_html(raw_query); Some(format!("{}", escaped, col_count, escaped)) } fn row_started(&mut self) -> Option { Some("".to_owned()) } fn format_element(&mut self, _: &str, record: &str, _is_last: bool) -> Option { Some(format!("", escape_html(record))) } fn row_ended(&mut self) -> Option { Some("".to_owned()) } fn footer(&mut self) -> Option { Some("
{}
{}
".to_owned()) } } #[cfg(test)] mod test { use super::*; use crate::output::html::HtmlFormatter; use crate::output::test::write_test_items; #[test] fn test() { let result = write_test_items(&mut HtmlFormatter); assert_eq!("select key, value
select key, value
foo_valueBAR value
123
", result); } #[test] fn test_escape_html() { assert_eq!(escape_html(""), "<script>alert(1)</script>"); assert_eq!(escape_html("a&b"), "a&b"); assert_eq!(escape_html("\"hello\""), ""hello""); } }