1use std::io::{self, Cursor, Error, ErrorKind};
2
3use crate::{error::{HaProxErr, HaProxRes}, map_error, protocol_raw, return_error};
4
5#[allow(unused)]
6pub(crate)
7fn is_printable_utf8(u: &str, err_lbl: &str) -> HaProxRes<()>
8{
9 for p in u.chars()
10 {
11 if p.is_control() == true || p.is_ascii_whitespace() == true || p.is_ascii_control() == true
13 {
14 return_error!(ArgumentEinval,
15 "non-printable characters found in: '{}' for '{}'", sanitize_str_unicode(u), err_lbl);
16 }
17 }
18
19 return Ok(());
20}
21
22#[inline]
24pub(crate)
25fn is_printable_ascii_nowp(u: &str, err_lbl: &str) -> HaProxRes<()>
26{
27 return is_printable_ascii(u, err_lbl, false);
28}
29
30pub(crate)
32fn is_printable_ascii(u: &str, err_lbl: &str, whitesp: bool) -> HaProxRes<()>
33{
34 for p in u.chars()
35 {
36 if p.is_control() == true ||
38 (p.is_ascii_whitespace() == true && whitesp == false) ||
39 p.is_ascii_control() == true ||
40 p.is_ascii() == false
41 {
42 return_error!(ArgumentEinval,
43 "non-printable characters found in: '{}' for '{}'", sanitize_str_unicode(u), err_lbl);
44 }
45 }
46
47 return Ok(());
48}
49
50pub(crate)
52fn check_printable_ascii_single_wp<'a>(u: &'a str, err_lbl: &str) -> HaProxRes<Option<&'a str>>
53{
54 let mut wpi = 0;
55
56 if u.ends_with(protocol_raw::HEADER_V1_EOM) == false
57 {
58 return Ok(None);
59 }
60
61 let uw_end = &u[0..u.len()-protocol_raw::HEADER_V1_EOM.len()];
62
63 for p in uw_end.chars()
64 {
65 if p.is_control() == true ||
67 p.is_ascii() == false
68 {
69 return_error!(MalformedData,
70 "non-printable characters or non-ascii found in: '{}' for '{}'", sanitize_str_unicode(u), err_lbl);
71 }
72 else if p.is_ascii_whitespace() == true
73 {
74 if wpi > 0
75 {
76 return_error!(MalformedData,
77 "multiple spaces was found in '{}', for '{}'", sanitize_str_unicode(u), err_lbl);
78 }
79
80 wpi += 1;
81 }
82 else if p.is_ascii_control() == true
83 {
84 return_error!(MalformedData,
85 "control chars in sequence in '{}', for '{}'", sanitize_str_unicode(u), err_lbl);
86 }
87 else
88 {
89 wpi = 0;
90 }
91 }
92
93 return Ok(Some(uw_end));
94}
95
96pub(crate)
98fn sanitize_str_unicode(st: &str) -> String
99{
100 let mut out = String::with_capacity(st.len());
101
102 for c in st.chars()
103 {
104 if c.is_alphanumeric() == true ||
105 c.is_ascii_punctuation() == true ||
106 c == ' '
107 {
108 out.push(c);
109 }
110 else
111 {
112 let mut buf = [0_u8; 4];
113 c.encode_utf8(&mut buf);
114
115 let formatted: String =
116 buf[0..c.len_utf8()].into_iter()
117 .map(|c| format!("\\x{:02x}", c))
118 .collect();
119
120 out.push_str(&formatted);
121 }
122 }
123
124 return out;
125}
126
127pub
128fn map_io_err(err: Error) -> HaProxErr
129{
130 return map_error!(IoError, "{}", err)
131}
132
133pub trait ReadExtZeroCopy<'zc>
135{
136 fn borrow_exact(&mut self, len: usize) -> std::io::Result<&'zc [u8]>;
137}
138
139impl<'zc> ReadExtZeroCopy<'zc> for Cursor<&'zc [u8]>
140{
141 fn borrow_exact(&mut self, len: usize) -> std::io::Result<&'zc [u8]>
142 {
143 let start = self.position() as usize;
144
145 if self.get_ref().len() < start+len
146 {
147 return Err(
148 io::Error::new(ErrorKind::UnexpectedEof,
149 format!("len: {}, req: {}", self.get_ref().len(), start+len))
150 );
151 }
152 let out = &self.get_ref()[start..(start+len)];
153
154 self.set_position((start+len) as u64);
155
156 return Ok(out);
157 }
158}
159
160#[test]
161fn test_mult_wp()
162{
163 assert_eq!(
164 check_printable_ascii_single_wp("PROXY UNKNOWN ffff:f...f:ffff ffff:f...f:ffff 65535 65535\r\n", "test").is_err(),
165 true
166 );
167
168 assert_eq!(
169 check_printable_ascii_single_wp("PROXY UNKNOWN ffff:f...f:ffff ffff:f...f:ffff 65535 65535\r\n", "test"),
170 Ok(Some("PROXY UNKNOWN ffff:f...f:ffff ffff:f...f:ffff 65535 65535"))
171 );
172
173 assert_eq!(
174 check_printable_ascii_single_wp("PROXY UNKNOWN ffff:f...f:ffff ffff:f...f:ffff 65535 65535", "test"),
175 Ok(None)
176 );
177
178 assert_eq!(
179 check_printable_ascii_single_wp("PROXY UNKNOWN ffff:f...f:ffff ffff:f...f:ffff 65535 65535\r", "test"),
180 Ok(None)
181 );
182
183
184 assert_eq!(
185 check_printable_ascii_single_wp("PROXY UNKNOWN ffff:f...f:ffff ffff:f...f:ffff 65535 65535\r\n\r\n", "test").is_err(),
186 true
187 );
188}