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;
10
11use error::Error;
12
13use ns;
14use helpers::TrimmedPlainText;
15
16generate_element_with_text!(URI, "uri", ns::MEDIA_ELEMENT,
17 [
18 type_: String = "type" => required
19 ],
20 uri: TrimmedPlainText<String>
21);
22
23generate_element_with_children!(MediaElement, "media", ns::MEDIA_ELEMENT,
24 attributes: [
25 width: Option<usize> = "width" => optional,
26 height: Option<usize> = "height" => optional
27 ],
28 children: [
29 uris: Vec<URI> = ("uri", ns::MEDIA_ELEMENT) => URI
30 ]
31);
32
33#[cfg(test)]
34mod tests {
35 use super::*;
36 use data_forms::DataForm;
37 use std::error::Error as StdError;
38
39 #[test]
40 fn test_simple() {
41 let elem: Element = "<media xmlns='urn:xmpp:media-element'/>".parse().unwrap();
42 let media = MediaElement::try_from(elem).unwrap();
43 assert!(media.width.is_none());
44 assert!(media.height.is_none());
45 assert!(media.uris.is_empty());
46 }
47
48 #[test]
49 fn test_width_height() {
50 let elem: Element = "<media xmlns='urn:xmpp:media-element' width='32' height='32'/>".parse().unwrap();
51 let media = MediaElement::try_from(elem).unwrap();
52 assert_eq!(media.width.unwrap(), 32);
53 assert_eq!(media.height.unwrap(), 32);
54 }
55
56 #[test]
57 fn test_uri() {
58 let elem: Element = "<media xmlns='urn:xmpp:media-element'><uri type='text/html'>https://example.org/</uri></media>".parse().unwrap();
59 let media = MediaElement::try_from(elem).unwrap();
60 assert_eq!(media.uris.len(), 1);
61 assert_eq!(media.uris[0].type_, "text/html");
62 assert_eq!(media.uris[0].uri, "https://example.org/");
63 }
64
65 #[test]
66 fn test_invalid_width_height() {
67 let elem: Element = "<media xmlns='urn:xmpp:media-element' width=''/>".parse().unwrap();
68 let error = MediaElement::try_from(elem).unwrap_err();
69 let error = match error {
70 Error::ParseIntError(error) => error,
71 _ => panic!(),
72 };
73 assert_eq!(error.description(), "cannot parse integer from empty string");
74
75 let elem: Element = "<media xmlns='urn:xmpp:media-element' width='coucou'/>".parse().unwrap();
76 let error = MediaElement::try_from(elem).unwrap_err();
77 let error = match error {
78 Error::ParseIntError(error) => error,
79 _ => panic!(),
80 };
81 assert_eq!(error.description(), "invalid digit found in string");
82
83 let elem: Element = "<media xmlns='urn:xmpp:media-element' height=''/>".parse().unwrap();
84 let error = MediaElement::try_from(elem).unwrap_err();
85 let error = match error {
86 Error::ParseIntError(error) => error,
87 _ => panic!(),
88 };
89 assert_eq!(error.description(), "cannot parse integer from empty string");
90
91 let elem: Element = "<media xmlns='urn:xmpp:media-element' height='-10'/>".parse().unwrap();
92 let error = MediaElement::try_from(elem).unwrap_err();
93 let error = match error {
94 Error::ParseIntError(error) => error,
95 _ => panic!(),
96 };
97 assert_eq!(error.description(), "invalid digit found in string");
98 }
99
100 #[test]
101 fn test_unknown_child() {
102 let elem: Element = "<media xmlns='urn:xmpp:media-element'><coucou/></media>".parse().unwrap();
103 let error = MediaElement::try_from(elem).unwrap_err();
104 let message = match error {
105 Error::ParseError(string) => string,
106 _ => panic!(),
107 };
108 assert_eq!(message, "Unknown child in media element.");
109 }
110
111 #[test]
112 fn test_bad_uri() {
113 let elem: Element = "<media xmlns='urn:xmpp:media-element'><uri>https://example.org/</uri></media>".parse().unwrap();
114 let error = MediaElement::try_from(elem).unwrap_err();
115 let message = match error {
116 Error::ParseError(string) => string,
117 _ => panic!(),
118 };
119 assert_eq!(message, "Required attribute 'type' missing.");
120
121 let elem: Element = "<media xmlns='urn:xmpp:media-element'><uri type='text/html'/></media>".parse().unwrap();
122 let error = MediaElement::try_from(elem).unwrap_err();
123 let message = match error {
124 Error::ParseError(string) => string,
125 _ => panic!(),
126 };
127 assert_eq!(message, "URI missing in uri.");
128 }
129
130 #[test]
131 fn test_xep_ex1() {
132 let elem: Element = r#"
133<media xmlns='urn:xmpp:media-element'>
134 <uri type='audio/x-wav'>
135 http://victim.example.com/challenges/speech.wav?F3A6292C
136 </uri>
137 <uri type='audio/ogg; codecs=speex'>
138 cid:sha1+a15a505e360702b79c75a5f67773072ed392f52a@bob.xmpp.org
139 </uri>
140 <uri type='audio/mpeg'>
141 http://victim.example.com/challenges/speech.mp3?F3A6292C
142 </uri>
143</media>"#.parse().unwrap();
144 let media = MediaElement::try_from(elem).unwrap();
145 assert!(media.width.is_none());
146 assert!(media.height.is_none());
147 assert_eq!(media.uris.len(), 3);
148 assert_eq!(media.uris[0].type_, "audio/x-wav");
149 assert_eq!(media.uris[0].uri, "http://victim.example.com/challenges/speech.wav?F3A6292C");
150 assert_eq!(media.uris[1].type_, "audio/ogg; codecs=speex");
151 assert_eq!(media.uris[1].uri, "cid:sha1+a15a505e360702b79c75a5f67773072ed392f52a@bob.xmpp.org");
152 assert_eq!(media.uris[2].type_, "audio/mpeg");
153 assert_eq!(media.uris[2].uri, "http://victim.example.com/challenges/speech.mp3?F3A6292C");
154 }
155
156 #[test]
157 fn test_xep_ex2() {
158 let elem: Element = r#"
159<x xmlns='jabber:x:data' type='form'>
160 [ ... ]
161 <field var='ocr'>
162 <media xmlns='urn:xmpp:media-element'
163 height='80'
164 width='290'>
165 <uri type='image/jpeg'>
166 http://www.victim.com/challenges/ocr.jpeg?F3A6292C
167 </uri>
168 <uri type='image/jpeg'>
169 cid:sha1+f24030b8d91d233bac14777be5ab531ca3b9f102@bob.xmpp.org
170 </uri>
171 </media>
172 </field>
173 [ ... ]
174</x>"#.parse().unwrap();
175 let form = DataForm::try_from(elem).unwrap();
176 assert_eq!(form.fields.len(), 1);
177 assert_eq!(form.fields[0].var, "ocr");
178 assert_eq!(form.fields[0].media[0].width, Some(290));
179 assert_eq!(form.fields[0].media[0].height, Some(80));
180 assert_eq!(form.fields[0].media[0].uris[0].type_, "image/jpeg");
181 assert_eq!(form.fields[0].media[0].uris[0].uri, "http://www.victim.com/challenges/ocr.jpeg?F3A6292C");
182 assert_eq!(form.fields[0].media[0].uris[1].type_, "image/jpeg");
183 assert_eq!(form.fields[0].media[0].uris[1].uri, "cid:sha1+f24030b8d91d233bac14777be5ab531ca3b9f102@bob.xmpp.org");
184 }
185}