}
pub fn mime_parse_value_delimited(input: &[u8]) -> IResult<&[u8], &[u8]> {
- let (i2, _) = tag!(input, "\"")?;
- let (i3, value) = take_until!(i2, "\"")?;
- let (i4, _) = tag!(i3, "\"")?;
- return Ok((i4, value));
+ let (input, _) = tag!(input, "\"")?;
+ let (input, value) = take_until!(input, "\"")?;
+ let (input, _) = tag!(input, "\"")?;
+ return Ok((input, value));
}
pub fn mime_parse_header_token(input: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> {
// from RFC2047 : like ch.is_ascii_whitespace but without 0x0c FORM-FEED
- let (i1, _) = take_while!(input, |ch: u8| ch == 0x20
+ let (input, _) = take_while!(input, |ch: u8| ch == 0x20
|| ch == 0x09
|| ch == 0x0a
|| ch == 0x0d)?;
- let (i2, name) = take_until!(i1, "=")?;
- let (i3, _) = tag!(i2, "=")?;
- let (i4, value) = alt!(
- i3,
+ let (input, name) = take_until!(input, "=")?;
+ let (input, _) = tag!(input, "=")?;
+ let (input, value) = alt!(
+ input,
mime_parse_value_delimited | complete!(take_until!(";")) | rest
)?;
- let (i5, _) = opt!(i4, complete!(tag!(";")))?;
- return Ok((i5, (name, value)));
+ let (input, _) = opt!(input, complete!(tag!(";")))?;
+ return Ok((input, (name, value)));
}
fn mime_parse_header_tokens(input: &[u8]) -> IResult<&[u8], MIMEHeaderTokens> {
- let (mut i2, _) = take_until_and_consume!(input, ";")?;
+ let (mut input, _) = take_until_and_consume!(input, ";")?;
let mut tokens = HashMap::new();
- while i2.len() > 0 {
- match mime_parse_header_token(i2) {
+ while input.len() > 0 {
+ match mime_parse_header_token(input) {
Ok((rem, t)) => {
tokens.insert(t.0, t.1);
// should never happen
- debug_validate_bug_on!(i2.len() == rem.len());
- if i2.len() == rem.len() {
+ debug_validate_bug_on!(input.len() == rem.len());
+ if input.len() == rem.len() {
//infinite loop
return Err(Err::Error((input, ErrorKind::Eof)));
}
- i2 = rem;
+ input = rem;
}
Err(_) => {
// keep first tokens is error in remaining buffer
}
}
}
- return Ok((i2, MIMEHeaderTokens { tokens }));
+ return Ok((input, MIMEHeaderTokens { tokens }));
}
-fn mime_find_header_token<'a>(header: &'a [u8], token: &[u8]) -> Result<&'a [u8], ()> {
+fn mime_find_header_token<'a>(
+ header: &'a [u8], token: &[u8], sections_values: &'a mut Vec<u8>,
+) -> Result<&'a [u8], ()> {
match mime_parse_header_tokens(header) {
Ok((_rem, t)) => {
+ // in case of multiple sections for the parameter cf RFC2231
+ let mut current_section_slice = Vec::new();
+
// look for the specific token
match t.tokens.get(token) {
// easy nominal case
Some(value) => return Ok(value),
- None => return Err(()),
+ None => {
+ // check for initial section of a parameter
+ current_section_slice.extend_from_slice(token);
+ current_section_slice.extend_from_slice(b"*0");
+ match t.tokens.get(¤t_section_slice[..]) {
+ Some(value) => {
+ sections_values.extend_from_slice(value);
+ let l = current_section_slice.len();
+ current_section_slice[l - 1] = b'1';
+ }
+ None => return Err(()),
+ }
+ }
+ }
+
+ let mut current_section_seen = 1;
+ // we have at least the initial section
+ // try looping until we do not find anymore a next section
+ loop {
+ match t.tokens.get(¤t_section_slice[..]) {
+ Some(value) => {
+ sections_values.extend_from_slice(value);
+ current_section_seen += 1;
+ let nbdigits = current_section_slice.len() - token.len() - 1;
+ current_section_slice.truncate(current_section_slice.len() - nbdigits);
+ current_section_slice
+ .extend_from_slice(current_section_seen.to_string().as_bytes());
+ }
+ None => return Ok(sections_values),
+ }
}
}
Err(_) => {
) -> bool {
let hbuf = build_slice!(hinput, hlen as usize);
let tbuf = build_slice!(tinput, tlen as usize);
- match mime_find_header_token(hbuf, tbuf) {
+ let mut sections_values = Vec::new();
+ match mime_find_header_token(hbuf, tbuf, &mut sections_values) {
Ok(value) => {
// limit the copy to the supplied buffer size
if value.len() <= RS_MIME_MAX_TOKEN_LEN {
#[test]
fn test_mime_find_header_token() {
+ let mut outvec = Vec::new();
let undelimok = mime_find_header_token(
"attachment; filename=test;".as_bytes(),
"filename".as_bytes(),
+ &mut outvec,
);
assert_eq!(undelimok, Ok("test".as_bytes()));
let delimok = mime_find_header_token(
"attachment; filename=\"test2\";".as_bytes(),
"filename".as_bytes(),
+ &mut outvec,
);
assert_eq!(delimok, Ok("test2".as_bytes()));
let evasion_othertoken = mime_find_header_token(
"attachment; dummy=\"filename=wrong\"; filename=real;".as_bytes(),
"filename".as_bytes(),
+ &mut outvec,
);
assert_eq!(evasion_othertoken, Ok("real".as_bytes()));
let badending = mime_find_header_token(
"attachment; filename=oksofar; badending".as_bytes(),
"filename".as_bytes(),
+ &mut outvec,
);
assert_eq!(badending, Ok("oksofar".as_bytes()));
let missend = mime_find_header_token(
"attachment; filename=test".as_bytes(),
"filename".as_bytes(),
+ &mut outvec,
);
assert_eq!(missend, Ok("test".as_bytes()));
+
+ let spaces = mime_find_header_token(
+ "attachment; filename=test me wrong".as_bytes(),
+ "filename".as_bytes(),
+ &mut outvec,
+ );
+ assert_eq!(spaces, Ok("test me wrong".as_bytes()));
+
+ assert_eq!(outvec.len(), 0);
+ let multi = mime_find_header_token(
+ "attachment; filename*0=abc; filename*1=\"def\";".as_bytes(),
+ "filename".as_bytes(),
+ &mut outvec,
+ );
+ assert_eq!(multi, Ok("abcdef".as_bytes()));
+ outvec.clear();
+
+ let multi = mime_find_header_token(
+ "attachment; filename*1=456; filename*0=\"123\"".as_bytes(),
+ "filename".as_bytes(),
+ &mut outvec,
+ );
+ assert_eq!(multi, Ok("123456".as_bytes()));
+ outvec.clear();
}
}