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