summaryrefslogtreecommitdiffstats
path: root/melib/src/email/parser.rs
diff options
context:
space:
mode:
authorManos Pitsidianakis <el13635@mail.ntua.gr>2020-08-09 09:50:20 +0300
committerManos Pitsidianakis <el13635@mail.ntua.gr>2020-08-09 09:50:20 +0300
commit560f9e539973028c43198b84e7d05e7105c21a1f (patch)
treee647fb3129e6a6f95fe054bbae9d32516f1018f7 /melib/src/email/parser.rs
parentc0f8bc1aedb31c32e92348a07fe5f9532cc7de8c (diff)
melib/email: parse empty attachments correctly
Diffstat (limited to 'melib/src/email/parser.rs')
-rw-r--r--melib/src/email/parser.rs57
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")