media_element.rs

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