media_element.rs

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