Fix multipart filename encoding (#363)
- Create a new encoding policy based on information from bug's comments and RFC documents - Update tests accordingly Closes #295
This commit is contained in:
committed by
Sean McArthur
parent
c4bf420021
commit
44c8ca392d
@@ -7,6 +7,7 @@ use std::path::Path;
|
||||
|
||||
use mime_guess::{self, Mime};
|
||||
use url::percent_encoding;
|
||||
use url::percent_encoding::EncodeSet;
|
||||
use uuid::Uuid;
|
||||
use http::HeaderMap;
|
||||
|
||||
@@ -311,6 +312,32 @@ impl Read for Reader {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct AttrCharEncodeSet;
|
||||
|
||||
impl EncodeSet for AttrCharEncodeSet {
|
||||
fn contains(&self, ch: u8) -> bool {
|
||||
match ch as char {
|
||||
'!' => false,
|
||||
'#' => false,
|
||||
'$' => false,
|
||||
'&' => false,
|
||||
'+' => false,
|
||||
'-' => false,
|
||||
'.' => false,
|
||||
'^' => false,
|
||||
'_' => false,
|
||||
'`' => false,
|
||||
'|' => false,
|
||||
'~' => false,
|
||||
_ => {
|
||||
let is_alpha_numeric = ch >= 0x41 && ch <= 0x5a || ch >= 0x61 && ch <= 0x7a || ch >= 0x30 && ch <= 0x39;
|
||||
!is_alpha_numeric
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn header(name: &str, field: &Part) -> Vec<u8> {
|
||||
let s = format!(
|
||||
@@ -325,7 +352,6 @@ fn header(name: &str, field: &Part) -> Vec<u8> {
|
||||
None => "".to_string(),
|
||||
},
|
||||
);
|
||||
|
||||
field.headers.iter().fold(s.into_bytes(), |mut header, (k,v)| {
|
||||
header.extend_from_slice(b"\r\n");
|
||||
header.extend_from_slice(k.as_str().as_bytes());
|
||||
@@ -337,7 +363,7 @@ fn header(name: &str, field: &Part) -> Vec<u8> {
|
||||
|
||||
fn format_parameter(name: &str, value: &str) -> String {
|
||||
let legal_value =
|
||||
percent_encoding::utf8_percent_encode(value, percent_encoding::PATH_SEGMENT_ENCODE_SET)
|
||||
percent_encoding::utf8_percent_encode(value, AttrCharEncodeSet)
|
||||
.to_string();
|
||||
if value.len() == legal_value.len() {
|
||||
// nothing has been percent encoded
|
||||
@@ -470,7 +496,7 @@ mod tests {
|
||||
fn header_percent_encoding() {
|
||||
let name = "start%'\"\r\nßend";
|
||||
let field = Part::text("");
|
||||
let expected = "Content-Disposition: form-data; name*=utf-8''start%25\'%22%0D%0A%C3%9Fend";
|
||||
let expected = "Content-Disposition: form-data; name*=utf-8''start%25%27%22%0D%0A%C3%9Fend";
|
||||
|
||||
assert_eq!(header(name, &field), expected.as_bytes());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user