mam.rs

  1// Copyright (c) 2017 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
  2//
  3// This Source Code Form is subject to the terms of the Mozilla Public
  4// License, v. 2.0. If a copy of the MPL was not distributed with this
  5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6
  7use try_from::TryFrom;
  8
  9use minidom::Element;
 10use jid::Jid;
 11
 12use error::Error;
 13
 14use iq::{IqGetPayload, IqSetPayload, IqResultPayload};
 15use data_forms::DataForm;
 16use rsm::Set;
 17use forwarding::Forwarded;
 18
 19use ns;
 20
 21#[derive(Debug, Clone)]
 22pub struct Query {
 23    pub queryid: Option<String>,
 24    pub node: Option<String>,
 25    pub form: Option<DataForm>,
 26    pub set: Option<Set>,
 27}
 28
 29impl IqGetPayload for Query {}
 30impl IqSetPayload for Query {}
 31impl IqResultPayload for Query {}
 32
 33generate_element_with_children!(
 34    Result_, "result", MAM,
 35    attributes: [
 36        id: String = "id" => required,
 37        queryid: String = "queryid" => required,
 38    ],
 39    child: (
 40        forwarded: Forwarded = ("forwarded", FORWARD) => Forwarded
 41    )
 42);
 43
 44#[derive(Debug, Clone)]
 45pub struct Fin {
 46    pub complete: bool,
 47    pub set: Set,
 48}
 49
 50impl IqResultPayload for Fin {}
 51
 52generate_attribute!(DefaultPrefs, "default", {
 53    Always => "always",
 54    Never => "never",
 55    Roster => "roster",
 56});
 57
 58#[derive(Debug, Clone)]
 59pub struct Prefs {
 60    pub default_: DefaultPrefs,
 61    pub always: Vec<Jid>,
 62    pub never: Vec<Jid>,
 63}
 64
 65impl IqGetPayload for Prefs {}
 66impl IqSetPayload for Prefs {}
 67impl IqResultPayload for Prefs {}
 68
 69impl TryFrom<Element> for Query {
 70    type Err = Error;
 71
 72    fn try_from(elem: Element) -> Result<Query, Error> {
 73        check_self!(elem, "query", MAM);
 74        check_no_unknown_attributes!(elem, "query", ["queryid", "node"]);
 75        let mut form = None;
 76        let mut set = None;
 77        for child in elem.children() {
 78            if child.is("x", ns::DATA_FORMS) {
 79                form = Some(DataForm::try_from(child.clone())?);
 80            } else if child.is("set", ns::RSM) {
 81                set = Some(Set::try_from(child.clone())?);
 82            } else {
 83                return Err(Error::ParseError("Unknown child in query element."));
 84            }
 85        }
 86        let queryid = get_attr!(elem, "queryid", optional);
 87        let node = get_attr!(elem, "node", optional);
 88        Ok(Query { queryid, node, form, set })
 89    }
 90}
 91
 92impl TryFrom<Element> for Fin {
 93    type Err = Error;
 94
 95    fn try_from(elem: Element) -> Result<Fin, Error> {
 96        check_self!(elem, "fin", MAM);
 97        check_no_unknown_attributes!(elem, "fin", ["complete"]);
 98        let mut set = None;
 99        for child in elem.children() {
100            if child.is("set", ns::RSM) {
101                set = Some(Set::try_from(child.clone())?);
102            } else {
103                return Err(Error::ParseError("Unknown child in fin element."));
104            }
105        }
106        let set = set.ok_or(Error::ParseError("Mandatory set element missing in fin."))?;
107        let complete = match elem.attr("complete") {
108            Some(complete) if complete == "true" => true,
109            Some(complete) if complete == "false" => false,
110            None => false,
111            Some(_) => return Err(Error::ParseError("Invalid value for 'complete' attribute.")),
112        };
113        Ok(Fin { complete, set })
114    }
115}
116
117impl TryFrom<Element> for Prefs {
118    type Err = Error;
119
120    fn try_from(elem: Element) -> Result<Prefs, Error> {
121        check_self!(elem, "prefs", MAM);
122        check_no_unknown_attributes!(elem, "prefs", ["default"]);
123        let mut always = vec!();
124        let mut never = vec!();
125        for child in elem.children() {
126            if child.is("always", ns::MAM) {
127                for jid_elem in child.children() {
128                    if !jid_elem.is("jid", ns::MAM) {
129                        return Err(Error::ParseError("Invalid jid element in always."));
130                    }
131                    always.push(jid_elem.text().parse()?);
132                }
133            } else if child.is("never", ns::MAM) {
134                for jid_elem in child.children() {
135                    if !jid_elem.is("jid", ns::MAM) {
136                        return Err(Error::ParseError("Invalid jid element in never."));
137                    }
138                    never.push(jid_elem.text().parse()?);
139                }
140            } else {
141                return Err(Error::ParseError("Unknown child in prefs element."));
142            }
143        }
144        let default_ = get_attr!(elem, "default", required);
145        Ok(Prefs { default_, always, never })
146    }
147}
148
149impl From<Query> for Element {
150    fn from(query: Query) -> Element {
151        Element::builder("query")
152                .ns(ns::MAM)
153                .attr("queryid", query.queryid)
154                .attr("node", query.node)
155                //.append(query.form)
156                .append(query.set)
157                .build()
158    }
159}
160
161impl From<Fin> for Element {
162    fn from(fin: Fin) -> Element {
163        Element::builder("fin")
164                .ns(ns::MAM)
165                .attr("complete", if fin.complete { Some("true") } else { None })
166                .append(fin.set)
167                .build()
168    }
169}
170
171fn serialise_jid_list(name: &str, jids: Vec<Jid>) -> Option<Element> {
172    if jids.is_empty() {
173        None
174    } else {
175        Some(Element::builder(name)
176                     .ns(ns::MAM)
177                     .append(jids.into_iter()
178                                 .map(|jid| Element::builder("jid")
179                                                    .ns(ns::MAM)
180                                                    .append(jid)
181                                                    .build())
182                                 .collect::<Vec<_>>())
183                     .build())
184    }
185}
186
187impl From<Prefs> for Element {
188    fn from(prefs: Prefs) -> Element {
189        Element::builder("prefs")
190                .ns(ns::MAM)
191                .attr("default", prefs.default_)
192                .append(serialise_jid_list("always", prefs.always))
193                .append(serialise_jid_list("never", prefs.never))
194                .build()
195    }
196}
197
198#[cfg(test)]
199mod tests {
200    use super::*;
201    use std::str::FromStr;
202
203    #[test]
204    fn test_query() {
205        let elem: Element = "<query xmlns='urn:xmpp:mam:2'/>".parse().unwrap();
206        Query::try_from(elem).unwrap();
207    }
208
209    #[test]
210    fn test_result() {
211        #[cfg(not(feature = "component"))]
212        let elem: Element = r#"
213<result xmlns='urn:xmpp:mam:2' queryid='f27' id='28482-98726-73623'>
214  <forwarded xmlns='urn:xmpp:forward:0'>
215    <delay xmlns='urn:xmpp:delay' stamp='2010-07-10T23:08:25Z'/>
216    <message xmlns='jabber:client' from="witch@shakespeare.lit" to="macbeth@shakespeare.lit">
217      <body>Hail to thee</body>
218    </message>
219  </forwarded>
220</result>
221"#.parse().unwrap();
222        #[cfg(feature = "component")]
223        let elem: Element = r#"
224<result xmlns='urn:xmpp:mam:2' queryid='f27' id='28482-98726-73623'>
225  <forwarded xmlns='urn:xmpp:forward:0'>
226    <delay xmlns='urn:xmpp:delay' stamp='2010-07-10T23:08:25Z'/>
227    <message xmlns='jabber:component:accept' from="witch@shakespeare.lit" to="macbeth@shakespeare.lit">
228      <body>Hail to thee</body>
229    </message>
230  </forwarded>
231</result>
232"#.parse().unwrap();
233        Result_::try_from(elem).unwrap();
234    }
235
236    #[test]
237    fn test_fin() {
238        let elem: Element = r#"
239<fin xmlns='urn:xmpp:mam:2'>
240  <set xmlns='http://jabber.org/protocol/rsm'>
241    <first index='0'>28482-98726-73623</first>
242    <last>09af3-cc343-b409f</last>
243  </set>
244</fin>
245"#.parse().unwrap();
246        Fin::try_from(elem).unwrap();
247    }
248
249    #[test]
250    fn test_query_x() {
251        let elem: Element = r#"
252<query xmlns='urn:xmpp:mam:2'>
253  <x xmlns='jabber:x:data' type='submit'>
254    <field var='FORM_TYPE' type='hidden'>
255      <value>urn:xmpp:mam:2</value>
256    </field>
257    <field var='with'>
258      <value>juliet@capulet.lit</value>
259    </field>
260  </x>
261</query>
262"#.parse().unwrap();
263        Query::try_from(elem).unwrap();
264    }
265
266    #[test]
267    fn test_query_x_set() {
268        let elem: Element = r#"
269<query xmlns='urn:xmpp:mam:2'>
270  <x xmlns='jabber:x:data' type='submit'>
271    <field var='FORM_TYPE' type='hidden'>
272      <value>urn:xmpp:mam:2</value>
273    </field>
274    <field var='start'>
275      <value>2010-08-07T00:00:00Z</value>
276    </field>
277  </x>
278  <set xmlns='http://jabber.org/protocol/rsm'>
279    <max>10</max>
280  </set>
281</query>
282"#.parse().unwrap();
283        Query::try_from(elem).unwrap();
284    }
285
286    #[test]
287    fn test_prefs_get() {
288        let elem: Element = "<prefs xmlns='urn:xmpp:mam:2' default='always'/>".parse().unwrap();
289        let prefs = Prefs::try_from(elem).unwrap();
290        assert_eq!(prefs.always, vec!());
291        assert_eq!(prefs.never, vec!());
292
293        let elem: Element = r#"
294<prefs xmlns='urn:xmpp:mam:2' default='roster'>
295  <always/>
296  <never/>
297</prefs>
298"#.parse().unwrap();
299        let prefs = Prefs::try_from(elem).unwrap();
300        assert_eq!(prefs.always, vec!());
301        assert_eq!(prefs.never, vec!());
302    }
303
304    #[test]
305    fn test_prefs_result() {
306        let elem: Element = r#"
307<prefs xmlns='urn:xmpp:mam:2' default='roster'>
308  <always>
309    <jid>romeo@montague.lit</jid>
310  </always>
311  <never>
312    <jid>montague@montague.lit</jid>
313  </never>
314</prefs>
315"#.parse().unwrap();
316        let prefs = Prefs::try_from(elem).unwrap();
317        assert_eq!(prefs.always, vec!(Jid::from_str("romeo@montague.lit").unwrap()));
318        assert_eq!(prefs.never, vec!(Jid::from_str("montague@montague.lit").unwrap()));
319
320        let elem2 = Element::from(prefs.clone());
321        println!("{:?}", elem2);
322        let prefs2 = Prefs::try_from(elem2).unwrap();
323        assert_eq!(prefs.default_, prefs2.default_);
324        assert_eq!(prefs.always, prefs2.always);
325        assert_eq!(prefs.never, prefs2.never);
326    }
327
328    #[test]
329    fn test_invalid_child() {
330        let elem: Element = "<query xmlns='urn:xmpp:mam:2'><coucou/></query>".parse().unwrap();
331        let error = Query::try_from(elem).unwrap_err();
332        let message = match error {
333            Error::ParseError(string) => string,
334            _ => panic!(),
335        };
336        assert_eq!(message, "Unknown child in query element.");
337    }
338
339    #[test]
340    fn test_serialise() {
341        let elem: Element = "<query xmlns='urn:xmpp:mam:2'/>".parse().unwrap();
342        let replace = Query { queryid: None, node: None, form: None, set: None };
343        let elem2 = replace.into();
344        assert_eq!(elem, elem2);
345    }
346}