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