xavier_internal/deserialize/
primitives.rs

1use std::str::FromStr;
2use quick_xml::events::{BytesStart, Event};
3use quick_xml::Reader;
4use crate::deserialize::error::PError;
5use crate::deserialize::macro_trait::XmlDeserializable;
6use crate::deserialize::decode::{decode_xml, strip_cdata};
7
8trait Number {}
9impl Number for i8 {}
10impl Number for i16 {}
11impl Number for i32 {}
12impl Number for i64 {}
13impl Number for i128 {}
14impl Number for u8 {}
15impl Number for u16 {}
16impl Number for u32 {}
17impl Number for u64 {}
18impl Number for u128 {}
19impl Number for isize {}
20impl Number for usize {}
21impl Number for f32 {}
22impl Number for f64  {}
23
24fn contains_malicious_characters(input: &str) -> bool {
25    for c in input.chars() {
26        match c as u32 {
27            0x00..=0x08 | 0x0B | 0x0C | 0x0E..=0x1F | 0x7F => {
28                return true;
29            }
30            _ => {}
31        }
32    }
33    false
34}
35
36fn contains_malicious_entities(input: &str) -> bool {
37    let malicious_patterns = [
38        "�", "", "", "", "", "", "", "", "",
39        "", "", "", "", "", "", "", "", "",
40        "", "", "", "", "", "", "", "", "",
41        "", "", ""
42    ];
43    
44    for pattern in &malicious_patterns {
45        if input.contains(pattern) {
46            return true;
47        }
48    }
49    
50    false
51}
52
53impl XmlDeserializable for String {
54    fn from_xml(reader: &mut Reader<&[u8]>, _: Option<&BytesStart>, _tag_name: Option<&str>) -> Result<Option<Self>, PError> {
55        let mut current_value = String::new();
56        loop {
57            match reader.read_event() {
58                Err(error) => { return Err(PError::new(&format!("Error at position {}: {:?}", reader.buffer_position(), error))) },
59                Ok(Event::Eof) => { },
60                Ok(Event::Start(_)) => {},
61                Ok(Event::End(_)) => { return Ok(Some(current_value)); },
62                Ok(Event::Empty(_)) => { return Ok(None); },
63                Ok(Event::Comment(_)) => {},
64                Ok(Event::Text(event)) => { 
65                    let raw_string = String::from_utf8(event.to_vec())?;
66                    if contains_malicious_entities(&raw_string) {
67                        return Err(PError::new("Malicious XML entities detected"));
68                    }
69                    let cdata_stripped = strip_cdata(&raw_string);
70                    let decoded = decode_xml(&cdata_stripped);
71                    
72                    if contains_malicious_characters(&decoded) {
73                        return Err(PError::new("Malicious characters detected in XML content"));
74                    }
75
76                    current_value.push_str(decoded.as_str());
77                },
78                Ok(Event::CData(event)) => { 
79                    let raw_string = String::from_utf8(event.to_vec())?;
80
81                    if contains_malicious_entities(&raw_string) {
82                        return Err(PError::new("Malicious XML entities detected"));
83                    }
84                    
85                    let decoded = decode_xml(&raw_string);
86                    
87                    if contains_malicious_characters(&decoded) {
88                        return Err(PError::new("Malicious characters detected in XML content"));
89                    }
90
91                    current_value.push_str(decoded.as_str());
92                },
93                Ok(Event::Decl(_)) => {},
94                Ok(Event::PI(_)) => {},
95                Ok(Event::DocType(_)) => {},
96            }
97        }
98    }
99}
100
101impl XmlDeserializable for char {
102    fn from_xml(reader: &mut Reader<&[u8]>, _: Option<&BytesStart>, _tag_name: Option<&str>) -> Result<Option<Self>, PError> {
103        loop {
104            match reader.read_event() {
105                Err(error) => { return Err(PError::new(&format!("Error at position {}: {:?}", reader.buffer_position(), error))) },
106                Ok(Event::Eof) => { },
107                Ok(Event::Start(_)) => {},
108                Ok(Event::End(_)) => { return Ok(None); },
109                Ok(Event::Empty(_)) => { return Ok(None); },
110                Ok(Event::Comment(_)) => {},
111                Ok(Event::Text(event)) => { 
112                    let raw_string = String::from_utf8(event.to_vec())?;
113                    let trimmed = raw_string.trim();
114                    if trimmed.is_empty() {
115                        return Ok(Some(' '));
116                    }
117                    if raw_string.chars().count()  > 1 {
118                        return Err(PError::new("It's supposed to be a char and string was found!"));
119                    }
120                    return Ok(Some(trimmed.chars().next().ok_or_else(|| PError::new("Empty string cannot be parsed as char"))?));
121                },
122                Ok(Event::CData(event)) => { 
123                    let raw_string = String::from_utf8(event.to_vec())?;
124                    let trimmed = raw_string.trim();
125                    if trimmed.is_empty() {
126                        return Ok(Some(' '));
127                    }
128                    return Ok(Some(trimmed.chars().next().ok_or_else(|| PError::new("Empty string cannot be parsed as char"))?));
129                },
130                Ok(Event::Decl(_)) => {},
131                Ok(Event::PI(_)) => {},
132                Ok(Event::DocType(_)) => {},
133            }
134        }
135    }
136}
137
138impl <T: FromStr + Number> XmlDeserializable for T
139    where PError: From<<T as FromStr>::Err> {
140    fn from_xml(reader: &mut Reader<&[u8]>, _: Option<&BytesStart>, _tag_name: Option<&str>)  -> Result<Option<Self>, PError> {
141
142        loop {
143              match reader.read_event() {
144                Err(error) =>  { return Err(PError::new(&format!("Error at position {}: {:?}", reader.buffer_position(), error))) },
145                Ok(Event::Eof) => {},
146                Ok(Event::Start(_)) => {},
147                Ok(Event::End(_)) => {  return Ok(Some("0".parse()?)); },
148                Ok(Event::Empty(_)) => { return Ok(Some("0".parse()?)); },
149                Ok(Event::Comment(_)) => {},
150                Ok(Event::Text(event)) => {
151                    let raw_string = String::from_utf8(event.to_vec())?;
152                    return if raw_string.is_empty() { Ok(Some("0".parse()?)) } else { Ok(Some(raw_string.parse()?)) };
153                },
154                Ok(Event::CData(event)) => {
155                    let raw_string = String::from_utf8(event.to_vec())?;
156                    return if raw_string.is_empty() { Ok(Some("0".parse()?)) } else { Ok(Some(raw_string.parse()?)) };
157                },
158                Ok(Event::Decl(_)) => {},
159                Ok(Event::PI(_)) => {},
160                Ok(Event::DocType(_)) => {},
161            }
162        }
163    }
164}
165
166
167impl XmlDeserializable for bool {
168    fn from_xml(reader: &mut Reader<&[u8]>, _: Option<&BytesStart>, _tag_name: Option<&str>)  -> Result<Option<Self>, PError> {
169        loop {
170            match reader.read_event() {
171                Err(error) =>  { return Err(PError::new(&format!("Error at position {}: {:?}", reader.buffer_position(), error))) },
172                Ok(Event::Eof) => {},
173                Ok(Event::Start(_)) => {},
174                Ok(Event::End(_)) => { return Ok(None); },
175                Ok(Event::Empty(_)) => { return Ok(None); },
176                Ok(Event::Comment(_)) => {},
177                Ok(Event::Text(event)) => {
178                    return Ok(Some(String::from_utf8(event.to_vec())?.parse()?))
179                },
180                Ok(Event::CData(event)) => {
181                    return Ok(Some(String::from_utf8(event.to_vec())?.parse()?))
182                },
183                Ok(Event::Decl(_)) => {},
184                Ok(Event::PI(_)) => {},
185                Ok(Event::DocType(_)) => {},
186            }
187        }
188    }
189}