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
 21generate_element!(
 22    Query, "query", MAM,
 23    attributes: [
 24        queryid: Option<String> = "queryid" => optional,
 25        node: Option<String> = "node" => optional
 26    ],
 27    children: [
 28        form: Option<DataForm> = ("x", DATA_FORMS) => DataForm,
 29        set: Option<Set> = ("set", RSM) => Set
 30    ]
 31);
 32
 33impl IqGetPayload for Query {}
 34impl IqSetPayload for Query {}
 35impl IqResultPayload for Query {}
 36
 37generate_element!(
 38    Result_, "result", MAM,
 39    attributes: [
 40        id: String = "id" => required,
 41        queryid: String = "queryid" => required,
 42    ],
 43    children: [
 44        forwarded: Required<Forwarded> = ("forwarded", FORWARD) => Forwarded
 45    ]
 46);
 47
 48generate_attribute!(
 49    Complete, "complete", bool
 50);
 51
 52generate_element!(
 53    Fin, "fin", MAM,
 54    attributes: [
 55        complete: Complete = "complete" => default
 56    ],
 57    children: [
 58        set: Required<Set> = ("set", RSM) => Set
 59    ]
 60);
 61
 62impl IqResultPayload for Fin {}
 63
 64generate_attribute!(DefaultPrefs, "default", {
 65    Always => "always",
 66    Never => "never",
 67    Roster => "roster",
 68});
 69
 70#[derive(Debug, Clone)]
 71pub struct Prefs {
 72    pub default_: DefaultPrefs,
 73    pub always: Vec<Jid>,
 74    pub never: Vec<Jid>,
 75}
 76
 77impl IqGetPayload for Prefs {}
 78impl IqSetPayload for Prefs {}
 79impl IqResultPayload for Prefs {}
 80
 81impl TryFrom<Element> for Prefs {
 82    type Err = Error;
 83
 84    fn try_from(elem: Element) -> Result<Prefs, Error> {
 85        check_self!(elem, "prefs", MAM);
 86        check_no_unknown_attributes!(elem, "prefs", ["default"]);
 87        let mut always = vec!();
 88        let mut never = vec!();
 89        for child in elem.children() {
 90            if child.is("always", ns::MAM) {
 91                for jid_elem in child.children() {
 92                    if !jid_elem.is("jid", ns::MAM) {
 93                        return Err(Error::ParseError("Invalid jid element in always."));
 94                    }
 95                    always.push(jid_elem.text().parse()?);
 96                }
 97            } else if child.is("never", ns::MAM) {
 98                for jid_elem in child.children() {
 99                    if !jid_elem.is("jid", ns::MAM) {
100                        return Err(Error::ParseError("Invalid jid element in never."));
101                    }
102                    never.push(jid_elem.text().parse()?);
103                }
104            } else {
105                return Err(Error::ParseError("Unknown child in prefs element."));
106            }
107        }
108        let default_ = get_attr!(elem, "default", required);
109        Ok(Prefs { default_, always, never })
110    }
111}
112
113fn serialise_jid_list(name: &str, jids: Vec<Jid>) -> Option<Element> {
114    if jids.is_empty() {
115        None
116    } else {
117        Some(Element::builder(name)
118                     .ns(ns::MAM)
119                     .append(jids.into_iter()
120                                 .map(|jid| Element::builder("jid")
121                                                    .ns(ns::MAM)
122                                                    .append(jid)
123                                                    .build())
124                                 .collect::<Vec<_>>())
125                     .build())
126    }
127}
128
129impl From<Prefs> for Element {
130    fn from(prefs: Prefs) -> Element {
131        Element::builder("prefs")
132                .ns(ns::MAM)
133                .attr("default", prefs.default_)
134                .append(serialise_jid_list("always", prefs.always))
135                .append(serialise_jid_list("never", prefs.never))
136                .build()
137    }
138}
139
140#[cfg(test)]
141mod tests {
142    use super::*;
143    use std::str::FromStr;
144
145    #[test]
146    fn test_query() {
147        let elem: Element = "<query xmlns='urn:xmpp:mam:2'/>".parse().unwrap();
148        Query::try_from(elem).unwrap();
149    }
150
151    #[test]
152    fn test_result() {
153        #[cfg(not(feature = "component"))]
154        let elem: Element = r#"
155<result xmlns='urn:xmpp:mam:2' queryid='f27' id='28482-98726-73623'>
156  <forwarded xmlns='urn:xmpp:forward:0'>
157    <delay xmlns='urn:xmpp:delay' stamp='2010-07-10T23:08:25Z'/>
158    <message xmlns='jabber:client' from="witch@shakespeare.lit" to="macbeth@shakespeare.lit">
159      <body>Hail to thee</body>
160    </message>
161  </forwarded>
162</result>
163"#.parse().unwrap();
164        #[cfg(feature = "component")]
165        let elem: Element = r#"
166<result xmlns='urn:xmpp:mam:2' queryid='f27' id='28482-98726-73623'>
167  <forwarded xmlns='urn:xmpp:forward:0'>
168    <delay xmlns='urn:xmpp:delay' stamp='2010-07-10T23:08:25Z'/>
169    <message xmlns='jabber:component:accept' from="witch@shakespeare.lit" to="macbeth@shakespeare.lit">
170      <body>Hail to thee</body>
171    </message>
172  </forwarded>
173</result>
174"#.parse().unwrap();
175        Result_::try_from(elem).unwrap();
176    }
177
178    #[test]
179    fn test_fin() {
180        let elem: Element = r#"
181<fin xmlns='urn:xmpp:mam:2'>
182  <set xmlns='http://jabber.org/protocol/rsm'>
183    <first index='0'>28482-98726-73623</first>
184    <last>09af3-cc343-b409f</last>
185  </set>
186</fin>
187"#.parse().unwrap();
188        Fin::try_from(elem).unwrap();
189    }
190
191    #[test]
192    fn test_query_x() {
193        let elem: Element = r#"
194<query xmlns='urn:xmpp:mam:2'>
195  <x xmlns='jabber:x:data' type='submit'>
196    <field var='FORM_TYPE' type='hidden'>
197      <value>urn:xmpp:mam:2</value>
198    </field>
199    <field var='with'>
200      <value>juliet@capulet.lit</value>
201    </field>
202  </x>
203</query>
204"#.parse().unwrap();
205        Query::try_from(elem).unwrap();
206    }
207
208    #[test]
209    fn test_query_x_set() {
210        let elem: Element = r#"
211<query xmlns='urn:xmpp:mam:2'>
212  <x xmlns='jabber:x:data' type='submit'>
213    <field var='FORM_TYPE' type='hidden'>
214      <value>urn:xmpp:mam:2</value>
215    </field>
216    <field var='start'>
217      <value>2010-08-07T00:00:00Z</value>
218    </field>
219  </x>
220  <set xmlns='http://jabber.org/protocol/rsm'>
221    <max>10</max>
222  </set>
223</query>
224"#.parse().unwrap();
225        Query::try_from(elem).unwrap();
226    }
227
228    #[test]
229    fn test_prefs_get() {
230        let elem: Element = "<prefs xmlns='urn:xmpp:mam:2' default='always'/>".parse().unwrap();
231        let prefs = Prefs::try_from(elem).unwrap();
232        assert_eq!(prefs.always, vec!());
233        assert_eq!(prefs.never, vec!());
234
235        let elem: Element = r#"
236<prefs xmlns='urn:xmpp:mam:2' default='roster'>
237  <always/>
238  <never/>
239</prefs>
240"#.parse().unwrap();
241        let prefs = Prefs::try_from(elem).unwrap();
242        assert_eq!(prefs.always, vec!());
243        assert_eq!(prefs.never, vec!());
244    }
245
246    #[test]
247    fn test_prefs_result() {
248        let elem: Element = r#"
249<prefs xmlns='urn:xmpp:mam:2' default='roster'>
250  <always>
251    <jid>romeo@montague.lit</jid>
252  </always>
253  <never>
254    <jid>montague@montague.lit</jid>
255  </never>
256</prefs>
257"#.parse().unwrap();
258        let prefs = Prefs::try_from(elem).unwrap();
259        assert_eq!(prefs.always, vec!(Jid::from_str("romeo@montague.lit").unwrap()));
260        assert_eq!(prefs.never, vec!(Jid::from_str("montague@montague.lit").unwrap()));
261
262        let elem2 = Element::from(prefs.clone());
263        println!("{:?}", elem2);
264        let prefs2 = Prefs::try_from(elem2).unwrap();
265        assert_eq!(prefs.default_, prefs2.default_);
266        assert_eq!(prefs.always, prefs2.always);
267        assert_eq!(prefs.never, prefs2.never);
268    }
269
270    #[test]
271    fn test_invalid_child() {
272        let elem: Element = "<query xmlns='urn:xmpp:mam:2'><coucou/></query>".parse().unwrap();
273        let error = Query::try_from(elem).unwrap_err();
274        let message = match error {
275            Error::ParseError(string) => string,
276            _ => panic!(),
277        };
278        assert_eq!(message, "Unknown child in query element.");
279    }
280
281    #[test]
282    fn test_serialise() {
283        let elem: Element = "<query xmlns='urn:xmpp:mam:2'/>".parse().unwrap();
284        let replace = Query { queryid: None, node: None, form: None, set: None };
285        let elem2 = replace.into();
286        assert_eq!(elem, elem2);
287    }
288}