diff --git a/CHANGELOG.md b/CHANGELOG.md index 49f7daa..ad2dbb1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +Version 0.5.0, released 2018-02-18: + * Updates + - Link Mauve has updated the optional `minidom` dependency. + - Link Mauve has added tests for invalid JIDs, which adds more error cases. + Version 0.4.0, released 2017-12-27: * Updates - Maxime Buquet has updated the optional `minidom` dependency. diff --git a/Cargo.toml b/Cargo.toml index a7ba1a0..cc9916d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "jid" -version = "0.4.0" +version = "0.5.0" authors = [ "lumi ", "Emmanuel Gil Peyrot ", @@ -18,4 +18,4 @@ license = "LGPL-3.0+" gitlab = { repository = "xmpp-rs/jid-rs" } [dependencies] -minidom = { version = "0.7", optional = true } +minidom = { version = "0.8.0", optional = true } diff --git a/src/lib.rs b/src/lib.rs index f0280d9..ebdfa80 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,8 +13,13 @@ use std::str::FromStr; /// An error that signifies that a `Jid` cannot be parsed from a string. #[derive(Debug, Clone, PartialEq, Eq)] pub enum JidParseError { - /// Happens when there is no domain. (really, only happens when the string is empty) + /// Happens when there is no domain, that is either the string is empty, + /// starts with a /, or contains the @/ sequence. NoDomain, + /// Happens when the node is empty, that is the string starts with a @. + EmptyNode, + /// Happens when the resource is empty, that is the string ends with a /. + EmptyResource, } /// A struct representing a Jabber ID. @@ -86,11 +91,17 @@ impl FromStr for Jid { ParserState::Node => { match c { '@' => { + if buf == "" { + return Err(JidParseError::EmptyNode); + } state = ParserState::Domain; node = Some(buf.clone()); // TODO: performance tweaks, do not need to copy it buf.clear(); }, '/' => { + if buf == "" { + return Err(JidParseError::NoDomain); + } state = ParserState::Resource; domain = Some(buf.clone()); // TODO: performance tweaks buf.clear(); @@ -103,6 +114,9 @@ impl FromStr for Jid { ParserState::Domain => { match c { '/' => { + if buf == "" { + return Err(JidParseError::NoDomain); + } state = ParserState::Resource; domain = Some(buf.clone()); // TODO: performance tweaks buf.clear(); @@ -129,6 +143,8 @@ impl FromStr for Jid { resource = Some(buf); }, } + } else if let ParserState::Resource = state { + return Err(JidParseError::EmptyResource); } Ok(Jid { node: node, @@ -401,6 +417,34 @@ mod tests { assert_eq!(String::from(Jid::full("a", "b", "c")), String::from("a@b/c")); } + #[test] + fn invalid() { + match Jid::from_str("") { + Err(JidParseError::NoDomain) => (), + err => panic!("Invalid error: {:?}", err) + } + + match Jid::from_str("a@/c") { + Err(JidParseError::NoDomain) => (), + err => panic!("Invalid error: {:?}", err) + } + + match Jid::from_str("/c") { + Err(JidParseError::NoDomain) => (), + err => panic!("Invalid error: {:?}", err) + } + + match Jid::from_str("@b") { + Err(JidParseError::EmptyNode) => (), + err => panic!("Invalid error: {:?}", err) + } + + match Jid::from_str("b/") { + Err(JidParseError::EmptyResource) => (), + err => panic!("Invalid error: {:?}", err) + } + } + #[cfg(feature = "minidom")] #[test] fn minidom() {