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 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}