server: much improved xmls pretty printer
This commit is contained in:
@@ -54,7 +54,7 @@ urlencoding = "2.1.3"
|
||||
#xtracing = { path = "../../xtracing" }
|
||||
xtracing = { version = "0.3.2", registry = "xinu" }
|
||||
zip = "4.3.0"
|
||||
xmlem = "0.1.0"
|
||||
|
||||
|
||||
[build-dependencies]
|
||||
build-info-build = "0.0.41"
|
||||
|
||||
@@ -43,4 +43,6 @@ pub enum ServerError {
|
||||
AskamaError(#[from] askama::Error),
|
||||
#[error("xml error: {0}")]
|
||||
XmlError(#[from] quick_xml::Error),
|
||||
#[error("xml encoding error: {0}")]
|
||||
XmlEncodingError(#[from] quick_xml::encoding::EncodingError),
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
fs::File,
|
||||
io::{Cursor, Read},
|
||||
str::FromStr,
|
||||
|
||||
};
|
||||
|
||||
use askama::Template;
|
||||
@@ -14,7 +14,7 @@ use memmap::MmapOptions;
|
||||
use quick_xml::de::from_str as xml_from_str;
|
||||
use sqlx::{types::Json, PgPool};
|
||||
use tracing::{error, info, info_span, instrument, warn};
|
||||
use xmlem::{display, Document};
|
||||
|
||||
use zip::ZipArchive;
|
||||
|
||||
use crate::{
|
||||
@@ -407,15 +407,12 @@ pub async fn thread(
|
||||
} else {
|
||||
// DMARC reports are XML
|
||||
// Pretty print XML
|
||||
let doc_result = Document::from_str(&raw_content);
|
||||
if let Ok(doc) = doc_result {
|
||||
doc.to_string_pretty_with_config(&display::Config::default_pretty())
|
||||
} else {
|
||||
error!(
|
||||
"Failed to parse XML for pretty printing: {:?}",
|
||||
doc_result.unwrap_err()
|
||||
);
|
||||
raw_content
|
||||
match pretty_print_xml_with_trimming(&raw_content) {
|
||||
Ok(pretty_xml) => pretty_xml,
|
||||
Err(e) => {
|
||||
error!("Failed to pretty print XML: {:?}", e);
|
||||
raw_content
|
||||
}
|
||||
}
|
||||
};
|
||||
current_html.push_str(&format!(
|
||||
@@ -897,15 +894,12 @@ fn extract_mixed(m: &ParsedMail, part_addr: &mut Vec<String>) -> Result<Body, Se
|
||||
} else {
|
||||
// DMARC reports are XML
|
||||
// Pretty print XML
|
||||
let doc_result = Document::from_str(&xml);
|
||||
if let Ok(doc) = doc_result {
|
||||
doc.to_string_pretty_with_config(&display::Config::default_pretty())
|
||||
} else {
|
||||
error!(
|
||||
"Failed to parse XML for pretty printing: {:?}",
|
||||
doc_result.unwrap_err()
|
||||
);
|
||||
xml
|
||||
match pretty_print_xml_with_trimming(&xml) {
|
||||
Ok(pretty_xml) => pretty_xml,
|
||||
Err(e) => {
|
||||
error!("Failed to pretty print XML: {:?}", e);
|
||||
xml
|
||||
}
|
||||
}
|
||||
};
|
||||
parts.push(Body::html(format!("\n<pre>{}</pre>", html_escape::encode_text(&pretty_printed_content))));
|
||||
@@ -1864,6 +1858,37 @@ pub fn parse_dmarc_report(xml: &str) -> Result<String, ServerError> {
|
||||
Ok(html)
|
||||
}
|
||||
|
||||
fn pretty_print_xml_with_trimming(xml_input: &str) -> Result<String, ServerError> {
|
||||
use quick_xml::events::{Event, BytesText};
|
||||
use quick_xml::reader::Reader;
|
||||
use quick_xml::writer::Writer;
|
||||
use std::io::Cursor;
|
||||
|
||||
let mut reader = Reader::from_str(xml_input);
|
||||
reader.config_mut().trim_text(true);
|
||||
|
||||
let mut writer = Writer::new_with_indent(Cursor::new(Vec::new()), b' ', 4);
|
||||
|
||||
let mut buf = Vec::new();
|
||||
loop {
|
||||
match reader.read_event_into(&mut buf) {
|
||||
Ok(Event::Eof) => break,
|
||||
Ok(Event::Text(e)) => {
|
||||
let trimmed_text = e.decode()?.trim().to_string();
|
||||
writer.write_event(Event::Text(BytesText::new(&trimmed_text)))?;
|
||||
},
|
||||
Ok(event) => {
|
||||
writer.write_event(event)?;
|
||||
},
|
||||
Err(e) => return Err(ServerError::StringError(format!("XML parsing error: {}", e))),
|
||||
}
|
||||
buf.clear();
|
||||
}
|
||||
|
||||
let result = writer.into_inner().into_inner();
|
||||
Ok(String::from_utf8(result)?)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
Reference in New Issue
Block a user