// Copyright (c) 2017 Emmanuel Gil Peyrot // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. use std::convert::TryFrom; use minidom::Element; use jid::Jid; use error::Error; use data_forms::DataForm; use rsm::Set; use forwarding::Forwarded; use ns; #[derive(Debug, Clone)] pub struct Query { pub queryid: Option, pub node: Option, pub form: Option, pub set: Option, } #[derive(Debug, Clone)] pub struct Result_ { pub queryid: String, pub id: String, pub forwarded: Forwarded, } #[derive(Debug, Clone)] pub struct Fin { pub complete: bool, pub set: Set, } #[derive(Debug, Clone)] pub enum DefaultPrefs { Always, Never, Roster, } #[derive(Debug, Clone)] pub struct Prefs { pub default_: Option, pub always: Vec, pub never: Vec, } impl<'a> TryFrom<&'a Element> for Query { type Error = Error; fn try_from(elem: &'a Element) -> Result { if !elem.is("query", ns::MAM) { return Err(Error::ParseError("This is not a query element.")); } let mut form = None; let mut set = None; for child in elem.children() { if child.is("x", ns::DATA_FORMS) { form = Some(DataForm::try_from(child)?); } else if child.is("set", ns::RSM) { set = Some(Set::try_from(child)?); } else { return Err(Error::ParseError("Unknown child in query element.")); } } let queryid = match elem.attr("queryid") { Some(queryid) => Some(queryid.to_owned()), None => None, }; let node = match elem.attr("node") { Some(node) => Some(node.to_owned()), None => None, }; Ok(Query { queryid, node, form, set }) } } impl<'a> TryFrom<&'a Element> for Result_ { type Error = Error; fn try_from(elem: &'a Element) -> Result { if !elem.is("result", ns::MAM) { return Err(Error::ParseError("This is not a result element.")); } let mut forwarded = None; for child in elem.children() { if child.is("forwarded", ns::FORWARD) { forwarded = Some(Forwarded::try_from(child)?); } else { return Err(Error::ParseError("Unknown child in result element.")); } } let queryid = match elem.attr("queryid") { Some(queryid) => queryid.to_owned(), None => return Err(Error::ParseError("No 'queryid' attribute present in result.")), }; let id = match elem.attr("id") { Some(id) => id.to_owned(), None => return Err(Error::ParseError("No 'id' attribute present in result.")), }; if forwarded.is_none() { return Err(Error::ParseError("Mandatory forwarded element missing in result.")); } let forwarded = forwarded.unwrap(); Ok(Result_ { queryid, id, forwarded, }) } } impl<'a> TryFrom<&'a Element> for Fin { type Error = Error; fn try_from(elem: &'a Element) -> Result { if !elem.is("fin", ns::MAM) { return Err(Error::ParseError("This is not a fin element.")); } let mut set = None; for child in elem.children() { if child.is("set", ns::RSM) { set = Some(Set::try_from(child)?); } else { return Err(Error::ParseError("Unknown child in fin element.")); } } let complete = match elem.attr("complete") { Some(complete) => complete == "true", None => false, }; if set.is_none() { return Err(Error::ParseError("Mandatory set element missing in fin.")); } let set = set.unwrap(); Ok(Fin { complete, set }) } } impl<'a> TryFrom<&'a Element> for Prefs { type Error = Error; fn try_from(elem: &'a Element) -> Result { if !elem.is("prefs", ns::MAM) { return Err(Error::ParseError("This is not a prefs element.")); } let mut always = vec!(); let mut never = vec!(); for child in elem.children() { if child.is("always", ns::MAM) { for jid_elem in child.children() { if !jid_elem.is("jid", ns::MAM) { return Err(Error::ParseError("Invalid jid element in always.")); } always.push(jid_elem.text().parse()?); } } else if child.is("never", ns::MAM) { for jid_elem in child.children() { if !jid_elem.is("jid", ns::MAM) { return Err(Error::ParseError("Invalid jid element in never.")); } never.push(jid_elem.text().parse()?); } } else { return Err(Error::ParseError("Unknown child in prefs element.")); } } let default_ = match elem.attr("default") { Some("always") => Some(DefaultPrefs::Always), Some("never") => Some(DefaultPrefs::Never), Some("roster") => Some(DefaultPrefs::Roster), None => None, _ => return Err(Error::ParseError("Invalid 'default' attribute present in prefs.")), }; Ok(Prefs { default_, always, never }) } } impl<'a> Into for &'a Query { fn into(self) -> Element { let mut elem = Element::builder("query") .ns(ns::MAM) .attr("queryid", self.queryid.clone()) .attr("node", self.node.clone()) .build(); //if let Some(form) = self.form { // elem.append_child((&form).into()); //} if let Some(ref set) = self.set { elem.append_child(set.into()); } elem } } impl<'a> Into for &'a Result_ { fn into(self) -> Element { let mut elem = Element::builder("result") .ns(ns::MAM) .attr("queryid", self.queryid.clone()) .attr("id", self.id.clone()) .build(); elem.append_child((&self.forwarded).into()); elem } } impl<'a> Into for &'a Fin { fn into(self) -> Element { let mut elem = Element::builder("fin") .ns(ns::MAM) .attr("complete", if self.complete { Some("true") } else { None }) .build(); elem.append_child((&self.set).into()); elem } } impl<'a> Into for &'a Prefs { fn into(self) -> Element { let mut elem = Element::builder("prefs") .ns(ns::MAM) .attr("default", match self.default_ { Some(DefaultPrefs::Always) => Some("always"), Some(DefaultPrefs::Never) => Some("never"), Some(DefaultPrefs::Roster) => Some("roster"), None => None, }) .build(); if !self.always.is_empty() { let mut always = Element::builder("always") .ns(ns::RSM) .build(); for jid in self.always.clone() { always.append_child(Element::builder("jid") .ns(ns::RSM) .append(String::from(jid)) .build()); } elem.append_child(always); } if !self.never.is_empty() { let mut never = Element::builder("never") .ns(ns::RSM) .build(); for jid in self.never.clone() { never.append_child(Element::builder("jid") .ns(ns::RSM) .append(String::from(jid)) .build()); } elem.append_child(never); } elem } } #[cfg(test)] mod tests { use super::*; #[test] fn test_query() { let elem: Element = "".parse().unwrap(); Query::try_from(&elem).unwrap(); } #[test] fn test_result() { let elem: Element = r#" Hail to thee "#.parse().unwrap(); Result_::try_from(&elem).unwrap(); } #[test] fn test_fin() { let elem: Element = r#" 28482-98726-73623 09af3-cc343-b409f "#.parse().unwrap(); Fin::try_from(&elem).unwrap(); } #[test] fn test_query_x() { let elem: Element = r#" urn:xmpp:mam:2 juliet@capulet.lit "#.parse().unwrap(); Query::try_from(&elem).unwrap(); } #[test] fn test_query_x_set() { let elem: Element = r#" urn:xmpp:mam:2 2010-08-07T00:00:00Z 10 "#.parse().unwrap(); Query::try_from(&elem).unwrap(); } #[test] fn test_prefs_get() { let elem: Element = "".parse().unwrap(); Prefs::try_from(&elem).unwrap(); let elem: Element = r#" "#.parse().unwrap(); Prefs::try_from(&elem).unwrap(); } #[test] fn test_prefs_result() { let elem: Element = r#" romeo@montague.lit montague@montague.lit "#.parse().unwrap(); Prefs::try_from(&elem).unwrap(); } #[test] fn test_invalid_child() { let elem: Element = "".parse().unwrap(); let error = Query::try_from(&elem).unwrap_err(); let message = match error { Error::ParseError(string) => string, _ => panic!(), }; assert_eq!(message, "Unknown child in query element."); } #[test] fn test_serialise() { let elem: Element = "".parse().unwrap(); let replace = Query { queryid: None, node: None, form: None, set: None }; let elem2 = (&replace).into(); assert_eq!(elem, elem2); } }