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, 140);
41    }
42
43    #[cfg(target_pointer_width = "64")]
44    #[test]
45    fn test_size() {
46        assert_size!(Forwarded, 264);
47    }
48
49    #[test]
50    fn test_simple() {
51        let elem: Element =
52            "<forwarded xmlns='urn:xmpp:forward:0'><message xmlns='jabber:client'/></forwarded>"
53                .parse()
54                .unwrap();
55        Forwarded::try_from(elem).unwrap();
56    }
57
58    #[test]
59    #[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")]
60    fn test_invalid_child() {
61        let elem: Element = "<forwarded xmlns='urn:xmpp:forward:0'><message xmlns='jabber:client'/><coucou/></forwarded>"
62            .parse()
63            .unwrap();
64        let error = Forwarded::try_from(elem).unwrap_err();
65        let message = match error {
66            FromElementError::Invalid(Error::Other(string)) => string,
67            _ => panic!(),
68        };
69        assert_eq!(message, "Unknown child in Forwarded element.");
70    }
71
72    #[test]
73    fn test_serialise() {
74        let elem: Element = "<forwarded xmlns='urn:xmpp:forward:0'><message xmlns='jabber:client' type='chat'/></forwarded>".parse().unwrap();
75        let forwarded = Forwarded {
76            delay: None,
77            message: Message::new(None),
78        };
79        let elem2 = forwarded.into();
80        assert_eq!(elem, elem2);
81    }
82
83    #[test]
84    fn test_serialize_with_delay_and_stanza() {
85        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>"
86        .parse()
87        .unwrap();
88
89        let elem: Element = "<message xmlns='jabber:client' to='juliet@capulet.example/balcony' from='romeo@montague.example/home'/>"
90          .parse()
91          .unwrap();
92        let message = Message::try_from(elem).unwrap();
93
94        let elem: Element =
95            "<delay xmlns='urn:xmpp:delay' from='capulet.com' stamp='2002-09-10T23:08:25Z'/>"
96                .parse()
97                .unwrap();
98        let delay = Delay::try_from(elem).unwrap();
99
100        let forwarded = Forwarded {
101            delay: Some(delay),
102            message,
103        };
104
105        let serialized: Element = forwarded.into();
106        assert_eq!(serialized, reference);
107    }
108
109    #[test]
110    fn test_invalid_duplicate_delay() {
111        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>"
112            .parse()
113            .unwrap();
114        let error = Forwarded::try_from(elem).unwrap_err();
115        let message = match error {
116            FromElementError::Invalid(Error::Other(string)) => string,
117            _ => panic!(),
118        };
119        assert_eq!(
120            message,
121            "Forwarded element must not have more than one child in field 'delay'."
122        );
123    }
124
125    #[test]
126    fn test_invalid_duplicate_message() {
127        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>"
128            .parse()
129            .unwrap();
130        let error = Forwarded::try_from(elem).unwrap_err();
131        let message = match error {
132            FromElementError::Invalid(Error::Other(string)) => string,
133            _ => panic!(),
134        };
135        assert_eq!(
136            message,
137            "Forwarded element must not have more than one child in field 'message'."
138        );
139    }
140}