// 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 try_from::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, } generate_attribute!(DefaultPrefs, "default", { Always => "always", Never => "never", Roster => "roster", }); #[derive(Debug, Clone)] pub struct Prefs { pub default_: DefaultPrefs, pub always: Vec, pub never: Vec, } impl TryFrom for Query { type Err = Error; fn try_from(elem: Element) -> Result { check_self!(elem, "query", MAM); check_no_unknown_attributes!(elem, "query", ["queryid", "node"]); 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.clone())?); } else if child.is("set", ns::RSM) { set = Some(Set::try_from(child.clone())?); } else { return Err(Error::ParseError("Unknown child in query element.")); } } let queryid = get_attr!(elem, "queryid", optional); let node = get_attr!(elem, "node", optional); Ok(Query { queryid, node, form, set }) } } impl TryFrom for Result_ { type Err = Error; fn try_from(elem: Element) -> Result { check_self!(elem, "result", MAM); check_no_unknown_attributes!(elem, "result", ["queryid", "id"]); let mut forwarded = None; for child in elem.children() { if child.is("forwarded", ns::FORWARD) { forwarded = Some(Forwarded::try_from(child.clone())?); } else { return Err(Error::ParseError("Unknown child in result element.")); } } let forwarded = forwarded.ok_or(Error::ParseError("Mandatory forwarded element missing in result."))?; let queryid = get_attr!(elem, "queryid", required); let id = get_attr!(elem, "id", required); Ok(Result_ { queryid, id, forwarded, }) } } impl TryFrom for Fin { type Err = Error; fn try_from(elem: Element) -> Result { check_self!(elem, "fin", MAM); check_no_unknown_attributes!(elem, "fin", ["complete"]); let mut set = None; for child in elem.children() { if child.is("set", ns::RSM) { set = Some(Set::try_from(child.clone())?); } else { return Err(Error::ParseError("Unknown child in fin element.")); } } let set = set.ok_or(Error::ParseError("Mandatory set element missing in fin."))?; let complete = match elem.attr("complete") { Some(complete) if complete == "true" => true, Some(complete) if complete == "false" => false, None => false, Some(_) => return Err(Error::ParseError("Invalid value for 'complete' attribute.")), }; Ok(Fin { complete, set }) } } impl TryFrom for Prefs { type Err = Error; fn try_from(elem: Element) -> Result { check_self!(elem, "prefs", MAM); check_no_unknown_attributes!(elem, "prefs", ["default"]); 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_ = get_attr!(elem, "default", required); Ok(Prefs { default_, always, never }) } } impl From for Element { fn from(query: Query) -> Element { Element::builder("query") .ns(ns::MAM) .attr("queryid", query.queryid) .attr("node", query.node) //.append(query.form) .append(query.set) .build() } } impl From for Element { fn from(result: Result_) -> Element { Element::builder("result") .ns(ns::MAM) .attr("queryid", result.queryid) .attr("id", result.id) .append(result.forwarded) .build() } } impl From for Element { fn from(fin: Fin) -> Element { Element::builder("fin") .ns(ns::MAM) .attr("complete", if fin.complete { Some("true") } else { None }) .append(fin.set) .build() } } fn serialise_jid_list(name: &str, jids: Vec) -> Option { if jids.is_empty() { None } else { Some(Element::builder(name) .ns(ns::MAM) .append(jids.into_iter() .map(|jid| Element::builder("jid") .ns(ns::MAM) .append(jid) .build()) .collect::>()) .build()) } } impl From for Element { fn from(prefs: Prefs) -> Element { Element::builder("prefs") .ns(ns::MAM) .attr("default", prefs.default_) .append(serialise_jid_list("always", prefs.always)) .append(serialise_jid_list("never", prefs.never)) .build() } } #[cfg(test)] mod tests { use super::*; use std::str::FromStr; #[test] fn test_query() { let elem: Element = "".parse().unwrap(); Query::try_from(elem).unwrap(); } #[test] fn test_result() { #[cfg(not(feature = "component"))] let elem: Element = r#" Hail to thee "#.parse().unwrap(); #[cfg(feature = "component")] 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(); let prefs = Prefs::try_from(elem).unwrap(); assert_eq!(prefs.always, vec!()); assert_eq!(prefs.never, vec!()); let elem: Element = r#" "#.parse().unwrap(); let prefs = Prefs::try_from(elem).unwrap(); assert_eq!(prefs.always, vec!()); assert_eq!(prefs.never, vec!()); } #[test] fn test_prefs_result() { let elem: Element = r#" romeo@montague.lit montague@montague.lit "#.parse().unwrap(); let prefs = Prefs::try_from(elem).unwrap(); assert_eq!(prefs.always, vec!(Jid::from_str("romeo@montague.lit").unwrap())); assert_eq!(prefs.never, vec!(Jid::from_str("montague@montague.lit").unwrap())); let elem2 = Element::from(prefs.clone()); println!("{:?}", elem2); let prefs2 = Prefs::try_from(elem2).unwrap(); assert_eq!(prefs.default_, prefs2.default_); assert_eq!(prefs.always, prefs2.always); assert_eq!(prefs.never, prefs2.never); } #[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); } }