From a680ab194ced4f7fd044ed45f42062581e4f26ca Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Fri, 21 Apr 2017 03:45:05 +0100 Subject: [PATCH] Add an Explicit Message Encryption parser. --- src/eme.rs | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 6 +++++ src/ns.rs | 3 +++ 3 files changed, 77 insertions(+) create mode 100644 src/eme.rs diff --git a/src/eme.rs b/src/eme.rs new file mode 100644 index 00000000..cf33de7f --- /dev/null +++ b/src/eme.rs @@ -0,0 +1,68 @@ +use minidom::Element; + +use error::Error; + +use ns; + +#[derive(Debug, Clone)] +pub struct ExplicitMessageEncryption { + pub namespace: String, + pub name: Option, +} + +pub fn parse_explicit_message_encryption(root: &Element) -> Result { + if !root.is("encryption", ns::EME) { + return Err(Error::ParseError("This is not an encryption element.")); + } + for _ in root.children() { + return Err(Error::ParseError("Unknown child in encryption element.")); + } + let namespace = root.attr("namespace").ok_or(Error::ParseError("Mandatory argument 'namespace' not present in encryption element."))?.to_owned(); + let name = root.attr("name").and_then(|value| value.parse().ok()); + Ok(ExplicitMessageEncryption { + namespace: namespace, + name: name, + }) +} + +#[cfg(test)] +mod tests { + use minidom::Element; + use error::Error; + use eme; + + #[test] + fn test_simple() { + let elem: Element = "".parse().unwrap(); + let encryption = eme::parse_explicit_message_encryption(&elem).unwrap(); + assert_eq!(encryption.namespace, "urn:xmpp:otr:0"); + assert_eq!(encryption.name, None); + + let elem: Element = "".parse().unwrap(); + let encryption = eme::parse_explicit_message_encryption(&elem).unwrap(); + assert_eq!(encryption.namespace, "some.unknown.mechanism"); + assert_eq!(encryption.name, Some(String::from("SuperMechanism"))); + } + + #[test] + fn test_unknown() { + let elem: Element = "".parse().unwrap(); + let error = eme::parse_explicit_message_encryption(&elem).unwrap_err(); + let message = match error { + Error::ParseError(string) => string, + _ => panic!(), + }; + assert_eq!(message, "This is not an encryption element."); + } + + #[test] + fn test_invalid_child() { + let elem: Element = "".parse().unwrap(); + let error = eme::parse_explicit_message_encryption(&elem).unwrap_err(); + let message = match error { + Error::ParseError(string) => string, + _ => panic!(), + }; + assert_eq!(message, "Unknown child in encryption element."); + } +} diff --git a/src/lib.rs b/src/lib.rs index 50679604..167f58ec 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -49,6 +49,9 @@ pub mod attention; /// XEP-0308: Last Message Correction pub mod message_correct; +/// XEP-0380: Explicit Message Encryption +pub mod eme; + /// XEP-0390: Entity Capabilities 2.0 pub mod ecaps2; @@ -60,6 +63,7 @@ pub enum MessagePayload { Receipt(receipts::Receipt), Attention(attention::Attention), MessageCorrect(message_correct::MessageCorrect), + ExplicitMessageEncryption(eme::ExplicitMessageEncryption), } /// Parse one of the payloads of a `` element, and return `Some` of a @@ -75,6 +79,8 @@ pub fn parse_message_payload(elem: &Element) -> Option { Some(MessagePayload::Attention(attention)) } else if let Ok(replace) = message_correct::parse_message_correct(elem) { Some(MessagePayload::MessageCorrect(replace)) + } else if let Ok(eme) = eme::parse_explicit_message_encryption(elem) { + Some(MessagePayload::ExplicitMessageEncryption(eme)) } else { None } diff --git a/src/ns.rs b/src/ns.rs index df708fbe..6aa1d3f7 100644 --- a/src/ns.rs +++ b/src/ns.rs @@ -31,6 +31,9 @@ pub const ATTENTION: &'static str = "urn:xmpp:attention:0"; /// XEP-0308: Last Message Correction pub const MESSAGE_CORRECT: &'static str = "urn:xmpp:message-correct:0"; +/// XEP-0380: Explicit Message Encryption +pub const EME: &'static str = "urn:xmpp:eme:0"; + /// XEP-0390: Entity Capabilities 2.0 pub const ECAPS2: &'static str = "urn:xmpp:caps"; /// XEP-0390: Entity Capabilities 2.0