Merge branch 'o01eg/tokio-xmpp-accept-prefixes'

Astro created

Fixes Gitlab MR !1

Change summary

src/xmpp_codec.rs | 30 +++++++++++++++++++++++++++++-
1 file changed, 29 insertions(+), 1 deletion(-)

Detailed changes

src/xmpp_codec.rs 🔗

@@ -14,6 +14,7 @@ use std::io;
 use std::iter::FromIterator;
 use std::rc::Rc;
 use std::str::from_utf8;
+use std::borrow::Cow;
 use tokio_codec::{Decoder, Encoder};
 use xml5ever::interface::Attribute;
 use xml5ever::tokenizer::{Tag, TagKind, Token, TokenSink, XmlTokenizer};
@@ -104,7 +105,12 @@ impl ParserSink {
                     "xmlns" => (),
                     _ if is_prefix_xmlns(attr) => (),
                     _ => {
-                        el_builder = el_builder.attr(attr.name.local.as_ref(), attr.value.as_ref());
+                        let attr_name = if let Some(ref prefix) = attr.name.prefix {
+                            Cow::Owned(format!("{}:{}", prefix, attr.name.local))
+                        } else {
+                            Cow::Borrowed(attr.name.local.as_ref())
+                        };
+                        el_builder = el_builder.attr(attr_name, attr.value.as_ref());
                     }
                 }
             }
@@ -428,6 +434,28 @@ mod tests {
         });
     }
 
+    /// test case for https://gitlab.com/xmpp-rs/tokio-xmpp/issues/3
+    #[test]
+    fn test_atrribute_prefix() {
+        let mut c = XMPPCodec::new();
+        let mut b = BytesMut::with_capacity(1024);
+        b.put(r"<?xml version='1.0'?><stream:stream xmlns:stream='http://etherx.jabber.org/streams' version='1.0' xmlns='jabber:client'>");
+        let r = c.decode(&mut b);
+        assert!(match r {
+            Ok(Some(Packet::StreamStart(_))) => true,
+            _ => false,
+        });
+
+        b.clear();
+        b.put(r"<status xml:lang='en'>Test status</status>");
+        let r = c.decode(&mut b);
+        assert!(match r {
+            Ok(Some(Packet::Stanza(ref el))) if el.name() == "status" && el.text() == "Test status" && el.attr("xml:lang").map_or(false, |a| a == "en") => true,
+            _ => false,
+        });
+
+    }
+
     /// By default, encode() only get's a BytesMut that has 8kb space reserved.
     #[test]
     fn test_large_stanza() {