Add consume newlines flag to phrase()

This commit is contained in:
Manos Pitsidianakis 2020-02-26 15:53:46 +02:00
parent 303c530488
commit 33c1bf6558
No known key found for this signature in database
GPG Key ID: 73627C2F690DF710
6 changed files with 33 additions and 25 deletions

View File

@ -957,7 +957,7 @@ named!(pub literal<&[u8]>,length_bytes!(delimited!(tag!("{"), map_res!(digit, |s
// Return a byte sequence surrounded by "s and decoded if necessary
pub fn quoted(input: &[u8]) -> IResult<&[u8], Vec<u8>> {
if let IResult::Done(r, o) = literal(input) {
return match crate::email::parser::phrase(o) {
return match crate::email::parser::phrase(o, false) {
IResult::Done(_, out) => IResult::Done(r, out),
e => e,
};
@ -969,7 +969,7 @@ pub fn quoted(input: &[u8]) -> IResult<&[u8], Vec<u8>> {
let mut i = 1;
while i < input.len() {
if input[i] == b'\"' && (i == 0 || (input[i - 1] != b'\\')) {
return match crate::email::parser::phrase(&input[1..i]) {
return match crate::email::parser::phrase(&input[1..i], false) {
IResult::Done(_, out) => IResult::Done(&input[i + 1..], out),
e => e,
};

View File

@ -246,7 +246,7 @@ impl Envelope {
self.set_from(value);
}
} else if name.eq_ignore_ascii_case(b"subject") {
let parse_result = parser::phrase(value.trim());
let parse_result = parser::phrase(value.trim(), false);
if parse_result.is_done() {
let value = parse_result.to_full_result().unwrap();
self.set_subject(value);
@ -267,7 +267,7 @@ impl Envelope {
self.set_in_reply_to(value);
in_reply_to = Some(value);
} else if name.eq_ignore_ascii_case(b"date") {
let parse_result = parser::phrase(value);
let parse_result = parser::phrase(value, false);
if parse_result.is_done() {
let value = parse_result.to_full_result().unwrap();
self.set_date(value.as_slice());
@ -302,7 +302,7 @@ impl Envelope {
self.other_headers.insert(
String::from_utf8(name.to_vec())
.unwrap_or_else(|err| String::from_utf8_lossy(&err.into_bytes()).into()),
parser::phrase(value)
parser::phrase(value, false)
.to_full_result()
.map(|value| {
String::from_utf8(value).unwrap_or_else(|err| {

View File

@ -185,7 +185,7 @@ impl AttachmentBuilder {
let mut name: Option<String> = None;
for (n, v) in params {
if n.eq_ignore_ascii_case(b"name") {
if let Ok(v) = crate::email::parser::phrase(v.trim())
if let Ok(v) = crate::email::parser::phrase(v.trim(), false)
.to_full_result()
.as_ref()
.and_then(|r| Ok(String::from_utf8_lossy(r).to_string()))

View File

@ -455,7 +455,7 @@ fn display_addr(input: &[u8]) -> IResult<&[u8], Address> {
}
}
if !flag {
let (rest, output) = match phrase(input) {
let (rest, output) = match phrase(input, false) {
IResult::Done(rest, raw) => (rest, raw),
_ => return IResult::Error(error_code!(ErrorKind::Custom(43))),
};
@ -480,7 +480,7 @@ fn display_addr(input: &[u8]) -> IResult<&[u8], Address> {
}
}
if flag {
match phrase(&input[0..end + display_name.length + 3]) {
match phrase(&input[0..end + display_name.length + 3], false) {
IResult::Error(e) => IResult::Error(e),
IResult::Incomplete(i) => IResult::Incomplete(i),
IResult::Done(_, raw) => {
@ -659,7 +659,7 @@ fn eat_comments(input: &[u8]) -> Vec<u8> {
*
* We should use a custom parser here*/
pub fn date(input: &[u8]) -> Result<UnixTimestamp> {
let mut parsed_result = phrase(&eat_comments(input)).to_full_result()?;
let mut parsed_result = phrase(&eat_comments(input), false).to_full_result()?;
if let Some(pos) = parsed_result.find(b"-0000") {
parsed_result[pos] = b'+';
}
@ -873,7 +873,7 @@ named!(
)
);
pub fn phrase(input: &[u8]) -> IResult<&[u8], Vec<u8>> {
pub fn phrase(input: &[u8], multiline: /* preserve newlines */ bool) -> IResult<&[u8], Vec<u8>> {
if input.is_empty() {
return IResult::Done(&[], Vec::with_capacity(0));
}
@ -907,16 +907,21 @@ pub fn phrase(input: &[u8]) -> IResult<&[u8], Vec<u8>> {
let end = end.unwrap_or_else(|| input.len() - ptr) + ptr;
let ascii_s = ptr;
let mut ascii_e;
let mut ascii_e = 0;
while ptr < end && !(is_whitespace!(input[ptr])) {
ptr += 1;
}
if !multiline {
ascii_e = ptr;
}
while ptr < input.len() && (is_whitespace!(input[ptr])) {
ptr += 1;
}
if multiline {
ascii_e = ptr;
}
if ptr >= input.len() {
acc.extend(
ascii_token(&input[ascii_s..ascii_e])
@ -1056,33 +1061,33 @@ mod tests {
let words = b"=?iso-8859-7?B?W215Y291cnNlcy5udHVhLmdyIC0gyvXs4fTp6t4g6uHpIMri4e306ere?=
=?iso-8859-7?B?INb18+nq3l0gzd3hIMHt4erv3+358+c6IMzF0c/TIMHQz9TFy8XTzMHU?=
=?iso-8859-7?B?2c0gwiDUzC4gysHNLiDFzsXUwdPH0yAyMDE3LTE4OiDTx8zFydnTxw==?=";
assert_eq!("[mycourses.ntua.gr - Κυματική και Κβαντική Φυσική] Νέα Ανακοίνωση: ΜΕΡΟΣ ΑΠΟΤΕΛΕΣΜΑΤΩΝ Β ΤΜ. ΚΑΝ. ΕΞΕΤΑΣΗΣ 2017-18: ΣΗΜΕΙΩΣΗ" , std::str::from_utf8(&phrase(words.trim()).to_full_result().unwrap()).unwrap());
assert_eq!("[mycourses.ntua.gr - Κυματική και Κβαντική Φυσική] Νέα Ανακοίνωση: ΜΕΡΟΣ ΑΠΟΤΕΛΕΣΜΑΤΩΝ Β ΤΜ. ΚΑΝ. ΕΞΕΤΑΣΗΣ 2017-18: ΣΗΜΕΙΩΣΗ" , std::str::from_utf8(&phrase(words.trim(), false).to_full_result().unwrap()).unwrap());
let words = b"=?UTF-8?Q?=CE=A0=CF=81=CF=8C=CF=83=CE=B8=CE=B5?= =?UTF-8?Q?=CF=84=CE=B7_=CE=B5=CE=BE=CE=B5=CF=84?= =?UTF-8?Q?=CE=B1=CF=83=CF=84=CE=B9=CE=BA=CE=AE?=";
assert_eq!(
"Πρόσθετη εξεταστική",
std::str::from_utf8(&phrase(words.trim()).to_full_result().unwrap()).unwrap()
std::str::from_utf8(&phrase(words.trim(), false).to_full_result().unwrap()).unwrap()
);
let words = b"[Advcomparch] =?utf-8?b?zqPPhc68z4DOtc+BzrnPhs6/z4HOrCDPg861IGZs?=\n\t=?utf-8?b?dXNoIM67z4zOs8+JIG1pc3ByZWRpY3Rpb24gzrrOsc+Ezqwgz4TOt869?=\n\t=?utf-8?b?IM61zrrPhM6tzrvOtc+Dzrcgc3RvcmU=?=";
assert_eq!(
"[Advcomparch] Συμπεριφορά σε flush λόγω misprediction κατά την εκτέλεση store",
std::str::from_utf8(&phrase(words.trim()).to_full_result().unwrap()).unwrap()
std::str::from_utf8(&phrase(words.trim(), false).to_full_result().unwrap()).unwrap()
);
let words = b"Re: [Advcomparch] =?utf-8?b?zqPPhc68z4DOtc+BzrnPhs6/z4HOrCDPg861IGZs?=
=?utf-8?b?dXNoIM67z4zOs8+JIG1pc3ByZWRpY3Rpb24gzrrOsc+Ezqwgz4TOt869?=
=?utf-8?b?IM61zrrPhM6tzrvOtc+Dzrcgc3RvcmU=?=";
assert_eq!(
"Re: [Advcomparch] Συμπεριφορά σε flush λόγω misprediction κατά την εκτέλεση store",
std::str::from_utf8(&phrase(words.trim()).to_full_result().unwrap()).unwrap()
std::str::from_utf8(&phrase(words.trim(), false).to_full_result().unwrap()).unwrap()
);
let words = b"sdf";
assert_eq!(
"sdf",
std::str::from_utf8(&phrase(words).to_full_result().unwrap()).unwrap()
std::str::from_utf8(&phrase(words, false).to_full_result().unwrap()).unwrap()
);
let words = b"=?iso-8859-7?b?U2VnIGZhdWx0IPP05+0g5er03evl8+cg9O/1?= =?iso-8859-7?q?_example_ru_n_=5Fsniper?=";
assert_eq!(
"Seg fault στην εκτέλεση του example ru n _sniper",
std::str::from_utf8(&phrase(words).to_full_result().unwrap()).unwrap()
std::str::from_utf8(&phrase(words, false).to_full_result().unwrap()).unwrap()
);
let words = b"Re: [Advcomparch]
=?iso-8859-7?b?U2VnIGZhdWx0IPP05+0g5er03evl8+cg9O/1?=
@ -1090,28 +1095,31 @@ mod tests {
assert_eq!(
"Re: [Advcomparch] Seg fault στην εκτέλεση του example ru n _sniper",
std::str::from_utf8(&phrase(words).to_full_result().unwrap()).unwrap()
std::str::from_utf8(&phrase(words, false).to_full_result().unwrap()).unwrap()
);
let words = r#"[internal] =?UTF-8?B?zp3Orc6/z4Igzp/OtM63zrPPjM+CIM6jz4XOs86zz4E=?=
=?UTF-8?B?zrHPhs6uz4I=?="#;
assert_eq!(
"[internal] Νέος Οδηγός Συγγραφής",
std::str::from_utf8(&phrase(words.as_bytes()).to_full_result().unwrap()).unwrap()
std::str::from_utf8(&phrase(words.as_bytes(), false).to_full_result().unwrap())
.unwrap()
);
let words = r#"=?UTF-8?Q?Re=3a_Climate_crisis_reality_check_=e2=80=93=c2=a0EcoHust?=
=?UTF-8?Q?ler?="#;
assert_eq!(
"Re: Climate crisis reality check \u{a0}EcoHustler",
std::str::from_utf8(&phrase(words.as_bytes()).to_full_result().unwrap()).unwrap()
std::str::from_utf8(&phrase(words.as_bytes(), false).to_full_result().unwrap())
.unwrap()
);
let words = r#"Re: Climate crisis reality check =?windows-1250?B?lqBFY29IdXN0?=
=?windows-1250?B?bGVy?="#;
assert_eq!(
"Re: Climate crisis reality check \u{a0}EcoHustler",
std::str::from_utf8(&phrase(words.as_bytes()).to_full_result().unwrap()).unwrap()
std::str::from_utf8(&phrase(words.as_bytes(), false).to_full_result().unwrap())
.unwrap()
);
}

View File

@ -689,7 +689,7 @@ impl Component for MailView {
Ok(headers
.into_iter()
.map(|(h, v)| {
melib::email::parser::phrase(v)
melib::email::parser::phrase(v, true)
.to_full_result()
.map(|v| {
let mut h = h.to_vec();
@ -1078,7 +1078,7 @@ impl Component for MailView {
let attachment_type = u.mime_type();
let binary = query_default_app(&attachment_type);
let mut name_opt = name.as_ref().and_then(|n| {
melib::email::parser::phrase(n.as_bytes())
melib::email::parser::phrase(n.as_bytes(), false)
.to_full_result()
.ok()
.and_then(|n| String::from_utf8(n).ok())

View File

@ -138,7 +138,7 @@ impl MailBackend for PluginBackend {
env.set_to(value);
}
let parse_result =
melib::email::parser::phrase(subject.as_bytes());
melib::email::parser::phrase(subject.as_bytes(), false);
if parse_result.is_done() {
let value = parse_result.to_full_result().unwrap();
env.set_subject(value);