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