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