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