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