media_element.rs

  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}