44 * SPDX-License-Identifier: Apache-2.0 OR MIT
55 */
66
7- use std:: io:: { BufRead , Cursor , Read } ;
8- use std:: net:: IpAddr ;
9- use std:: str:: FromStr ;
10-
11- use flate2:: read:: GzDecoder ;
12- use mail_parser:: { MessageParser , MimeHeaders , PartType } ;
13- use quick_xml:: events:: { BytesStart , Event } ;
14- use quick_xml:: reader:: Reader ;
15-
167use crate :: report:: {
178 ActionDisposition , Alignment , AuthResult , DKIMAuthResult , DateRange , Disposition , DkimResult ,
189 DmarcResult , Error , Extension , Identifier , PolicyEvaluated , PolicyOverride ,
1910 PolicyOverrideReason , PolicyPublished , Record , Report , ReportMetadata , Row , SPFAuthResult ,
2011 SPFDomainScope , SpfResult ,
2112} ;
13+ use flate2:: read:: GzDecoder ;
14+ use mail_parser:: { MessageParser , MimeHeaders , PartType } ;
15+ use quick_xml:: events:: { BytesStart , Event } ;
16+ use quick_xml:: reader:: Reader ;
17+ use std:: borrow:: Cow ;
18+ use std:: io:: { BufRead , Cursor , Read } ;
19+ use std:: net:: IpAddr ;
20+ use std:: str:: FromStr ;
2221
2322impl Report {
2423 pub fn parse_rfc5322 ( report : & [ u8 ] ) -> Result < Self , Error > {
@@ -707,11 +706,46 @@ impl<R: BufRead> ReaderHelper for Reader<R> {
707706 }
708707
709708 fn next_value < T : FromStr > ( & mut self , buf : & mut Vec < u8 > ) -> Result < Option < T > , String > {
710- let mut value = None ;
709+ let mut value: Option < String > = None ;
710+
711711 loop {
712712 match self . read_event_into ( buf) {
713713 Ok ( Event :: Text ( e) ) => {
714- value = e. unescape ( ) . ok ( ) . and_then ( |v| T :: from_str ( v. as_ref ( ) ) . ok ( ) ) ;
714+ let v = e. xml_content ( ) . map_err ( |e| {
715+ format ! (
716+ "Failed to decode text value at position {}: {}" ,
717+ self . buffer_position( ) ,
718+ e
719+ )
720+ } ) ?;
721+ if let Some ( value) = & mut value {
722+ value. push_str ( & v) ;
723+ } else {
724+ value = Some ( v. into_owned ( ) ) ;
725+ }
726+ }
727+ Ok ( Event :: GeneralRef ( e) ) => {
728+ let v = hashify:: tiny_map!( e. as_ref( ) ,
729+ b"lt" => "<" ,
730+ b"gt" => ">" ,
731+ b"amp" => "&" ,
732+ b"apos" => "'" ,
733+ b"quot" => "\" " ,
734+ )
735+ . map ( Cow :: Borrowed )
736+ . or_else ( || {
737+ e. resolve_char_ref ( )
738+ . ok ( )
739+ . flatten ( )
740+ . map ( |v| Cow :: Owned ( v. to_string ( ) ) )
741+ } )
742+ . unwrap_or_else ( || e. xml_content ( ) . unwrap_or_default ( ) ) ;
743+
744+ if let Some ( value) = & mut value {
745+ value. push_str ( & v) ;
746+ } else {
747+ value = Some ( v. into_owned ( ) ) ;
748+ }
715749 }
716750 Ok ( Event :: End ( _) ) => {
717751 break ;
@@ -733,7 +767,7 @@ impl<R: BufRead> ReaderHelper for Reader<R> {
733767 }
734768 }
735769
736- Ok ( value)
770+ Ok ( value. and_then ( |v| T :: from_str ( & v ) . ok ( ) ) )
737771 }
738772
739773 fn skip_tag ( & mut self , buf : & mut Vec < u8 > ) -> Result < ( ) , String > {
0 commit comments