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}