diff --git a/core/http/src/handling/request.rs b/core/http/src/handling/request.rs index 760bd3c57c132306427742f4ca56224d93dce0ef..030188e9e83da5b2b29615f7268304bca71d4bfd 100644 --- a/core/http/src/handling/request.rs +++ b/core/http/src/handling/request.rs @@ -115,7 +115,7 @@ impl Request<'_> { &'a self, keys: &[&'a str], data: &Data, - ) -> Result<HashMap<&str, Result<Vec<u8>, ParseFormError>>, ParseFormError> { + ) -> Result<HashMap<String, Result<Vec<u8>, ParseFormError>>, ParseFormError> { let boundary; let post_type = if let Some(val) = self .headers @@ -145,13 +145,15 @@ impl Request<'_> { }; let data = data.buffer.as_slice(); - let mut keymap: HashMap<&str, Result<Vec<u8>, ParseFormError>> = + let mut keymap: HashMap<String, Result<Vec<u8>, ParseFormError>> = HashMap::with_capacity(keys.len()); + for key in keys { - keymap.entry(key).or_insert(Err(ParseFormError { + keymap.entry(key.to_string()).or_insert(Err(ParseFormError { error: ParseErrors::NoData, })); } + match post_type { Mime::ApplicationXWwwFormUrlencoded => { for kvp in data.split(|byte| *byte == b'&') { @@ -189,9 +191,63 @@ impl Request<'_> { } Mime::MultipartFormData => { let mut temp_bound = "--".to_string(); - temp_bound.push_str(boundary); + temp_bound.push_str(&format!("{boundary}")); let end_boundary = format!("{temp_bound}--").as_bytes().to_owned(); let boundary = temp_bound.as_bytes(); + let parts = data.split(|byte| byte == &b'\n').collect::<Vec<&[u8]>>(); + + let mut current_key: Option<String> = None; + let mut boundary_found = true; + for part in parts { + if part == [] { + continue; + } + if part == end_boundary { + break; + } + if !boundary_found && part == boundary { + boundary_found = true; + current_key = None; + continue; + } + if part.starts_with(b"Content-Disposition: form-data; name=") { + let headers = part + .split(|byte| byte == &b';') + .filter(|header| !header.is_empty()) + .collect::<Vec<_>>(); + if headers.len() < 2 { + continue; + } + let name = headers[1].split(|byte| byte == &b'=').collect::<Vec<_>>(); + if name.len() != 2 { + continue; + } + let mkey = String::from_utf8_lossy(name[1]) + .as_ref() + .trim_end() + .trim_matches('"') + .to_owned(); + + if keymap.contains_key::<str>(&mkey) { + current_key = Some(mkey.to_owned()); + } + boundary_found = false; + continue; + } else if let Some(key) = ¤t_key { + if let Some(val) = keymap.get::<str>(&key) { + if let Err(_) = val { + keymap.insert(key.to_string(), Ok(part.to_vec())); + continue; + } + keymap + .get_mut(key) + .unwrap() + .as_mut() + .unwrap() + .extend_from_slice(part); + } + } + } } _ => { return Err(ParseFormError { @@ -201,139 +257,6 @@ impl Request<'_> { }; Ok(keymap) } - - // pub fn get_post_text_form_key( - // &self, - // keys: &[&str], - // data: &Data, - // ) -> Result<HashMap<&str, Result<&str, ParseFormError>>, ParseFormError> { - // let mut post_type = self - // .headers - // .iter() - // .find(|header| header.contains("Content-Type: ")) - // .unwrap() - // .to_string(); - // - // post_type = post_type - // .strip_prefix("Content-Type: ") - // .unwrap() - // .to_string(); - // - // let post_type: Vec<&str> = post_type.trim().split(';').collect(); - // let mime_type = post_type[0].parse().unwrap(); - // - // // let data = String::from_utf8(vec) - // - // let mut result = HashMap::new(); - // match mime_type { - // Mime::ApplicationXWwwFormUrlencoded => { - // let data = String::from_utf8(data.buffer.clone()).unwrap(); - // let kvps = data - // .split("&") - // .map(|kvp| kvp.split_once("=").unwrap()) - // .collect::<HashMap<&str, &str>>(); - // - // for key in keys { - // let entry = if let Some(val) = kvps.get(key) { - // Ok(*val) - // } else { - // Err(ParseFormError { - // error: ParseErrors::NoData, - // }) - // }; - // result.insert(*key, entry); - // } - // Ok(result) - // } - // Mime::MultipartFormData => { - // let from_req = post_type[1..] - // .iter() - // .find(|val| val.contains("boundary=")) - // .unwrap() - // .strip_prefix("boundary=") - // .unwrap(); - // let mut boundary = b"--".to_vec(); - // boundary.extend_from_slice(from_req.trim_matches('"').as_bytes()); - // let mut end_boundary = boundary.clone(); - // end_boundary.extend_from_slice(b"--"); - // boundary.extend_from_slice(&[b'\r']); - // let parts = data - // .buffer - // .split(|byte| byte == &b'\n') - // .collect::<Vec<&[u8]>>(); - // - // let mut boundary_found = false; - // let mut current_key: Option<&str> = None; - // let mut result: HashMap<&str, Vec<u8>> = HashMap::new(); - // for part in parts { - // if part == [] { - // continue; - // } - // if part == end_boundary { - // break; - // } - // if !boundary_found && part == boundary { - // current_key = None; - // boundary_found = true; - // continue; - // } - // if part.starts_with(b"Content-Disposition: form-data; name=") { - // let headers = part - // .split(|byte| byte == &b';') - // .filter(|header| !header.is_empty()) - // .collect::<Vec<_>>(); - // if headers.len() < 2 { - // continue; - // } - // let name = headers[1].split(|byte| byte == &b'=').collect::<Vec<_>>(); - // if name.len() != 2 { - // continue; - // } - // let mkey = String::from_utf8_lossy(name[1]) - // .as_ref() - // .trim_end() - // .trim_matches('"') - // .to_owned(); - // for i in keys { - // if *i == mkey { - // current_key = Some(&mkey); - // } - // } - // boundary_found = false; - // } else if let Some(key) = current_key { - // if None == result.get(key) { - // result.insert(key, part.to_vec()); - // continue; - // } - // result.get_mut(key).unwrap().extend_from_slice(part); - // } - // } - // if result.len() == 0 { - // return Err(ParseFormError { - // error: ParseErrors::NoData, - // }); - // } - // let return_result: HashMap<&str, Result<&str, ParseErrors>> = - // HashMap::with_capacity(keys.len()); - // - // for key in keys { - // let val = result.get(key).ok_or(ParseFormError { - // error: ParseErrors::NoData, - // }).map(|value| String::from_utf8(value)) - // let val = if let Ok(str) = String::from_utf8(val) { - // Ok(str) - // } else { - // Err(ParseFormError { - // error: ParseErrors::BadData, - // }) - // }; - // } - // } - // _ => Err(ParseFormError { - // error: ParseErrors::BadData, - // }), - // } - // } } #[cfg(test)] @@ -375,19 +298,19 @@ value1 --boundary Content-Disposition: form-data; name=\"field2\"; filename=\"example.txt\" -value2 +value2\n --boundary-- " .to_vec(), is_complete: true, }; - let map = req.get_post_data(&["field1, field2"], &data).unwrap(); + let map = req.get_post_data(&["field1", "field2"], &data).unwrap(); assert_eq!( &b"value1".to_vec(), map.get("field1").unwrap().as_ref().unwrap() ); assert_eq!( - &b"value2".to_vec(), + &b"value2\n".to_vec(), map.get("field2").unwrap().as_ref().unwrap() ); }