diff options
author | Neal H. Walfield <neal@pep.foundation> | 2019-07-08 14:47:44 +0200 |
---|---|---|
committer | Neal H. Walfield <neal@pep.foundation> | 2019-07-08 14:49:16 +0200 |
commit | 9ff5fbcf805c0d1237cc8f5fd0325f805e145ddd (patch) | |
tree | 844f2fd1ef46b179545dc9dd1cd0d748807d6bcc /rfc2822 | |
parent | b2f4b977f9278e6f3074ce6e671b71099cc09316 (diff) |
rfc2822: Support unquoted @s in the display name
- Some OpenPGP implementations generate user ids that look like:
foo@bar.com <foo@bar.com>
foo@bar.com is not a valid display-name, because the '@' needs to
be quoted.
Support this variant anyway.
Diffstat (limited to 'rfc2822')
-rw-r--r-- | rfc2822/src/grammar.lalrpop | 16 | ||||
-rw-r--r-- | rfc2822/src/lib.rs | 23 |
2 files changed, 31 insertions, 8 deletions
diff --git a/rfc2822/src/grammar.lalrpop b/rfc2822/src/grammar.lalrpop index 4f664c5c..208d3da2 100644 --- a/rfc2822/src/grammar.lalrpop +++ b/rfc2822/src/grammar.lalrpop @@ -247,13 +247,19 @@ atext_plus : String = { // The display-name in a name-addr production often includes a ., but // is not quoted. The RFC even recommends supporting this variant. -other_or_dot : String = { +// Also some OpenPGP implementations create User IDs that look like: +// +// foo@bar.com <foo@bar.com> +// +// That is, with an unquoted at! Support that too. +other_or_dot_or_at : String = { <a:OTHER> => a.to_string(), <d:DOT> => d.to_string(), + <a:AT> => a.to_string(), } -atext_dot_plus : String = { - <a:other_or_dot+> => strings_flatten(a.into_iter(), ""), +atext_dot_at_plus : String = { + <a:other_or_dot_or_at+> => strings_flatten(a.into_iter(), ""), } // atom = [CFWS] 1*atext [CFWS] @@ -267,7 +273,7 @@ pub(crate) Atom : Vec<Component> = { } atom : Vec<Component> = { - <c1:CFWS?> <a:atext_dot_plus> <c2:CFWS?> => + <c1:CFWS?> <a:atext_dot_at_plus> <c2:CFWS?> => components_concat!( c1, Component::Text(a), @@ -277,7 +283,7 @@ atom : Vec<Component> = { // See the phrase production for why this variant of the 'atom' // production exists, and why the 'CFWS?'es are not included. atom_prime : Component = { - <a:atext_dot_plus> => Component::Text(a), + <a:atext_dot_at_plus> => Component::Text(a), } // dot-atom = [CFWS] dot-atom-text [CFWS] diff --git a/rfc2822/src/lib.rs b/rfc2822/src/lib.rs index d956afb7..2edb8090 100644 --- a/rfc2822/src/lib.rs +++ b/rfc2822/src/lib.rs @@ -805,7 +805,7 @@ mod tests { // atom = [CFWS] 1*atext [CFWS] // - // Note: our atom parser also allows for dots. + // Note: our atom parser also allows for dots and ats. // // An atom is a sequence of characters. // @@ -825,7 +825,7 @@ mod tests { "!", "#", "$", "%", "&", "'", "*", "+", "-", "/", "=", "?", "^", "_", "`", "{", "|", "}", "~", // Extension: - "."] + ".", "@"] .into_iter() { c(s, Some(vec![Component::Text(s.to_string())])) @@ -833,7 +833,7 @@ mod tests { for &s in ["\x02", " ", "(", ")", "<", ">", "[", "]", ":", ";", - "@", "\\", ",", "\""] + "\\", ",", "\""] .into_iter() { c(s, None) @@ -1518,6 +1518,22 @@ mod tests { } #[test] + fn display_name_parser() { + c!(grammar::DisplayNameParser::new(), Vec<Component>); + + c("Willi Wonka", + Some(vec![ Component::Text("Willi Wonka".into()) ])); + + // As an extention we unquoted dots. + c("Willi A. Wonka", + Some(vec![ Component::Text("Willi A. Wonka".into()) ])); + + // As an extention we unquoted ats. + c("foo@example.org", + Some(vec![ Component::Text("foo@example.org".into()) ])); + } + + #[test] fn name_addr_api() { fn c_(name: Option<&str>, comment: Option<&str>, email: Option<&str>) { @@ -1545,6 +1561,7 @@ mod tests { c("Harold Hutchins", "(artist)", "harold.hutchins@captain-underpants.com"); c("Mr. Meaner", "(Gym Teacher)", "kenny@jerome-horwitz.k12.us"); + c("foo@bar.com", "display name with at", "foo@bar.com"); } #[test] |