Skip to main content

xmpp_parsers/
forwarding.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 xso::{AsXml, FromXml};
8
9use crate::delay::Delay;
10use crate::message::Message;
11use crate::ns;
12
13/// Contains a forwarded stanza, either standalone or part of another
14/// extension (such as carbons).
15#[derive(FromXml, AsXml, Debug, Clone, PartialEq)]
16#[xml(namespace = ns::FORWARD, name = "forwarded")]
17pub struct Forwarded {
18    /// When the stanza originally got sent.
19    #[xml(child(default))]
20    pub delay: Option<Delay>,
21
22    /// The stanza being forwarded.
23    // The schema says that we should allow either a Message, Presence or Iq, in either
24    // jabber:client or jabber:server, but in the wild so far we’ve only seen Message being
25    // transmitted, so let’s hardcode that for now.  The schema also makes it optional, but so far
26    // it’s always present (or this wrapper is useless).
27    #[xml(child)]
28    pub message: Message,
29}
30
31#[cfg(test)]
32mod tests {
33    use super::*;
34    use minidom::Element;
35    use xso::error::{Error, FromElementError};
36
37    #[cfg(target_pointer_width = "32")]
38    #[test]
39    fn test_size() {
40        assert_size!(Forwarded, 152);
41    }
42
43    #[cfg(target_pointer_width = "64")]
44    #[test]
45    fn test_size() {
46        assert_size!(Forwarded, 288);
47    }
48
49    #[test]
50    #[cfg(not(feature = "component"))] // feature = "component" changes <message/> namespace
51    fn test_simple() {
52        let elem: Element =
53            "<forwarded xmlns='urn:xmpp:forward:0'><message xmlns='jabber:client'/></forwarded>"
54                .parse()
55                .unwrap();
56        Forwarded::try_from(elem).unwrap();
57    }
58
59    #[test]
60    #[cfg(not(feature = "component"))] // feature = "component" changes <message/> namespace
61    #[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")]
62    fn test_invalid_child() {
63        let elem: Element = "<forwarded xmlns='urn:xmpp:forward:0'><message xmlns='jabber:client'/><coucou/></forwarded>"
64            .parse()
65            .unwrap();
66        let error = Forwarded::try_from(elem).unwrap_err();
67        let message = match error {
68            FromElementError::Invalid(Error::Other(string)) => string,
69            _ => panic!(),
70        };
71        assert_eq!(message, "Unknown child in Forwarded element.");
72    }
73
74    #[test]
75    #[cfg(not(feature = "component"))] // feature = "component" changes <message/> namespace
76    fn test_serialise() {
77        let elem: Element = "<forwarded xmlns='urn:xmpp:forward:0'><message xmlns='jabber:client' type='chat'/></forwarded>".parse().unwrap();
78        let forwarded = Forwarded {
79            delay: None,
80            message: Message::new(None),
81        };
82        let elem2 = forwarded.into();
83        assert_eq!(elem, elem2);
84    }
85
86    #[test]
87    #[cfg(not(feature = "component"))] // feature = "component" changes <message/> namespace
88    fn test_serialize_with_delay_and_stanza() {
89        let reference: Element = "<forwarded xmlns='urn:xmpp:forward:0'><delay xmlns='urn:xmpp:delay' from='capulet.com' stamp='2002-09-10T23:08:25+00:00'/><message xmlns='jabber:client' to='juliet@capulet.example/balcony' from='romeo@montague.example/home'/></forwarded>"
90        .parse()
91        .unwrap();
92
93        let elem: Element = "<message xmlns='jabber:client' to='juliet@capulet.example/balcony' from='romeo@montague.example/home'/>"
94          .parse()
95          .unwrap();
96        let message = Message::try_from(elem).unwrap();
97
98        let elem: Element =
99            "<delay xmlns='urn:xmpp:delay' from='capulet.com' stamp='2002-09-10T23:08:25Z'/>"
100                .parse()
101                .unwrap();
102        let delay = Delay::try_from(elem).unwrap();
103
104        let forwarded = Forwarded {
105            delay: Some(delay),
106            message,
107        };
108
109        let serialized: Element = forwarded.into();
110        assert_eq!(serialized, reference);
111    }
112
113    #[test]
114    fn test_invalid_duplicate_delay() {
115        let elem: Element = "<forwarded xmlns='urn:xmpp:forward:0'><delay xmlns='urn:xmpp:delay' from='capulet.com' stamp='2002-09-10T23:08:25+00:00'/><delay xmlns='urn:xmpp:delay' from='capulet.com' stamp='2002-09-10T23:08:25+00:00'/><message xmlns='jabber:client' to='juliet@capulet.example/balcony' from='romeo@montague.example/home'/></forwarded>"
116            .parse()
117            .unwrap();
118        let error = Forwarded::try_from(elem).unwrap_err();
119        let message = match error {
120            FromElementError::Invalid(Error::Other(string)) => string,
121            _ => panic!(),
122        };
123        assert_eq!(
124            message,
125            "Forwarded element must not have more than one child in field 'delay'."
126        );
127    }
128
129    #[test]
130    #[cfg(not(feature = "component"))] // feature = "component" changes <message/> namespace
131    fn test_invalid_duplicate_message() {
132        let elem: Element = "<forwarded xmlns='urn:xmpp:forward:0'><delay xmlns='urn:xmpp:delay' from='capulet.com' stamp='2002-09-10T23:08:25+00:00'/><message xmlns='jabber:client' to='juliet@capulet.example/balcony' from='romeo@montague.example/home'/><message xmlns='jabber:client' to='juliet@capulet.example/balcony' from='romeo@montague.example/home'/></forwarded>"
133            .parse()
134            .unwrap();
135        let error = Forwarded::try_from(elem).unwrap_err();
136        let message = match error {
137            FromElementError::Invalid(Error::Other(string)) => string,
138            _ => panic!(),
139        };
140        assert_eq!(
141            message,
142            "Forwarded element must not have more than one child in field 'message'."
143        );
144    }
145}