diff options
author | Manos Pitsidianakis <el13635@mail.ntua.gr> | 2020-08-09 09:50:20 +0300 |
---|---|---|
committer | Manos Pitsidianakis <el13635@mail.ntua.gr> | 2020-08-09 09:50:20 +0300 |
commit | 560f9e539973028c43198b84e7d05e7105c21a1f (patch) | |
tree | e647fb3129e6a6f95fe054bbae9d32516f1018f7 /melib/src/email/parser.rs | |
parent | c0f8bc1aedb31c32e92348a07fe5f9532cc7de8c (diff) |
melib/email: parse empty attachments correctly
Diffstat (limited to 'melib/src/email/parser.rs')
-rw-r--r-- | melib/src/email/parser.rs | 57 |
1 files changed, 41 insertions, 16 deletions
diff --git a/melib/src/email/parser.rs b/melib/src/email/parser.rs index 27ab853d..b9edb174 100644 --- a/melib/src/email/parser.rs +++ b/melib/src/email/parser.rs @@ -28,7 +28,7 @@ use nom::{ error::ErrorKind, multi::{many0, many1, separated_list, separated_nonempty_list}, number::complete::le_u8, - sequence::{delimited, preceded, separated_pair, terminated}, + sequence::{delimited, pair, preceded, separated_pair, terminated}, }; use std::borrow::Cow; @@ -222,11 +222,14 @@ impl<'a, P: for<'r> FnMut(&'r u8) -> bool> BytesIterExt for std::slice::Split<'a //fn parser(input: I) -> IResult<I, O, E>; pub fn mail(input: &[u8]) -> Result<(Vec<(&[u8], &[u8])>, &[u8])> { - let (rest, result) = separated_pair( - headers::headers, - alt((tag(b"\n"), tag(b"\r\n"))), - take_while(|_| true), - )(input) + let (rest, result) = alt(( + separated_pair( + headers::headers, + alt((tag(b"\n"), tag(b"\r\n"))), + take_while(|_| true), + ), + pair(headers::headers, generic::eof), + ))(input) .chain_err_summary(|| "Could not parse mail")?; if !rest.is_empty() { @@ -378,6 +381,14 @@ pub mod generic { } } } + + pub fn eof(input: &[u8]) -> IResult<&[u8], &[u8]> { + if input.is_empty() { + Ok((input, input)) + } else { + Err(nom::Err::Error((input, "expected EOF").into())) + } + } } pub mod headers { @@ -645,11 +656,14 @@ pub mod attachments { use crate::email::address::*; use crate::email::attachment_types::{ContentDisposition, ContentDispositionKind}; pub fn attachment(input: &[u8]) -> IResult<&[u8], (std::vec::Vec<(&[u8], &[u8])>, &[u8])> { - separated_pair( - many0(headers::header), - alt((tag(b"\n"), tag(b"\r\n"))), - take_while(|_| true), - )(input) + alt(( + separated_pair( + many0(headers::header), + alt((tag(b"\n"), tag(b"\r\n"))), + take_while(|_| true), + ), + pair(headers::headers, generic::eof), + ))(input) } pub fn multipart_parts<'a>( @@ -703,10 +717,17 @@ pub mod attachments { (input, "multipart_parts(): malformed boundary").into(), )); } - ret.push(StrBuilder { - offset, - length: end - 2, - }); + if input[..end - 2].ends_with(b"\r\n") { + ret.push(StrBuilder { + offset, + length: end - 4, + }); + } else { + ret.push(StrBuilder { + offset, + length: end - 3, + }); + } offset += end + boundary.len(); input = &input[end + boundary.len()..]; if input.len() < 2 || input[0] != b'\n' || &input[0..2] == b"--" { @@ -769,7 +790,11 @@ pub mod attachments { if &input[end - 2..end] != b"--" { return Err(nom::Err::Error((input, "parts_f(): found EOF").into())); } - ret.push(&input[0..end - 2]); + if input[..end - 2].ends_with(b"\r\n") { + ret.push(&input[..end - 4]); + } else { + ret.push(&input[..end - 3]); + } input = &input[end + boundary.len()..]; if input.len() < 2 || (input[0] != b'\n' && &input[0..2] != b"\r\n") |