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}