// use quick_xml::events::BytesDecl; pub mod bind; pub mod iq; pub mod sasl; pub mod stream; use std::collections::BTreeMap; use std::str; // const DECLARATION: BytesDecl<'_> = BytesDecl::new("1.0", None, None); use async_recursion::async_recursion; use quick_xml::events::{BytesEnd, BytesStart, BytesText, Event}; use quick_xml::name::PrefixDeclaration; use quick_xml::{Reader, Writer}; use tokio::io::{AsyncBufRead, AsyncWrite}; use crate::{JabberError, Result}; #[derive(Clone, Debug)] /// represents an xml element as a tree of nodes pub struct Element { /// element prefix /// e.g. `foo` in ``. prefix: Option, /// element name /// e.g. `bar` in ``. localname: String, /// qualifying namespace /// an element must be qualified by a namespace /// e.g. for `` in /// ``` /// /// /// /// /// zlib /// lzw /// /// /// /// ``` /// would be `"http://etherx.jabber.org/streams"` but for /// ``` /// /// /// /// /// zlib /// lzw /// /// /// /// ``` /// would be `"jabber:client"` namespace: String, /// all namespaces applied to element /// e.g. for `` in /// ``` /// /// /// /// zlib /// lzw /// /// /// ``` /// would be `[(None, "urn:ietf:params:xml:ns:xmpp-bind")]` despite /// `(Some("stream"), "http://etherx.jabber.org/streams")` also being available // TODO: maybe not even needed, as can calculate when writing which namespaces need to be declared // but then can't have unused namespace on element, confusing. namespace_declarations: Box, String>>, /// element attributes attributes: Box>, // children elements namespaces contain their parents' namespaces children: Box>, } #[derive(Clone, Debug)] pub enum Node { Element(Element), Text(String), Unknown, } impl From for Node { fn from(element: Element) -> Self { Self::Element(element) } } impl From for Node { fn from(text: S) -> Self { Self::Text(text.to_string()) } } impl<'s> From<&Node> for Vec> { fn from(node: &Node) -> Self { match node { Node::Element(e) => e.into(), Node::Text(t) => vec![Event::Text(BytesText::new(t))], Unknown => vec![], } } } impl Element { /// returns the fully qualified name /// e.g. `foo:bar` in /// ``. pub fn name(&self) -> &str { if let Some(prefix) = self.prefix { format!("{}:{}", prefix, self.localname).as_str() } else { &self.localname } } /// returns the localname. /// e.g. `bar` in `` pub fn localname(&self) -> &str { &self.localname } /// returns the prefix. /// e.g. `foo` in ``. returns None if there is /// no prefix. pub fn prefix(&self) -> Option<&str> { self.prefix } /// returns the namespace which applies to the current element, e.g. for /// `` /// it will be `foo` but for /// `` /// it will be `bar`. pub fn namespace(&self) -> &str { &self.namespace } } impl<'s> From<&Element> for Vec> { fn from(element: &Element) -> Self { let name = element.name(); let event = BytesStart::new(name); // namespace declarations let namespace_declarations = element.namespace_declarations.iter().map(|declaration| { let (prefix, namespace) = declaration; match prefix { Some(prefix) => return (format!("xmlns:{}", prefix).as_str(), *namespace), None => return ("xmlns", *namespace), } }); let event = event.with_attributes(namespace_declarations); // attributes let event = event.with_attributes(element.attributes.into_iter()); match element.children.is_empty() { true => return vec![Event::Empty(event)], false => { return { let start: Vec> = vec![Event::Start(event)]; let start_and_content: Vec> = start .into_iter() .chain({ let u = element.children.iter().fold( Vec::new(), |acc: Vec>, child: &Node<'s>| { acc.into_iter() .chain(Into::>>::into(child).into_iter()) .collect() }, ); u }) .collect(); let full: Vec> = start_and_content .into_iter() .chain(vec![Event::End(BytesEnd::new(name))]) .collect(); full } } } } } impl Element { /// if there is only one child in the vec of children, will return that element pub fn child(&self) -> Result<&Node> { if self.children.len() == 1 { Ok(&self.children[0]) } else if self.children.len() > 1 { Err(ElementError::MultipleChildren.into()) } else { Err(ElementError::NoChildren.into()) } } /// returns reference to children pub fn children(&self) -> Result<&Vec> { if !self.children.is_empty() { Ok(&self.children) } else { Err(ElementError::NoChildren.into()) } } /// returns text content, error if there is none pub fn text_content(&self) -> Result> { let mut text = Vec::new(); for node in *self.children { match node { Node::Text(t) => text.push(t), _ => {} } } if text.is_empty() { return Err(ElementError::NotText.into()); } Ok(text) } /// returns whether or not the element is qualified by a namespace, either declared /// by a parent, or itself. fn namespace_qualified>( &self, namespace_context: &BTreeMap, S>, ) -> bool { // create a new local_namespaces combining that in the context and those declared within the element let mut local_namespaces = *namespace_context.clone(); self.namespace_declarations.iter().for_each(|prefix, declaration| local_namespaces.insert(prefix, declaration)); if let Some(namespace) = local_namespaces.get(self.prefix) { if namespace != self.namespace { return false; } } else { return false; }; for child in *self.children { if child.namespace_qualified(&local_namespaces) == false { return false; } } true } /// writes an element to a writer. the element's namespace must be qualified by the /// context given in `local_namespaces` or the element's internal namespace declarations pub async fn write, W: AsyncWrite + Unpin + Send>( &self, writer: &mut Writer, local_namespaces: &BTreeMap, S>, ) -> Result<()> { // TODO: instead of having a check if namespace qualified function, have the namespace declarations be added if needed given the context when converting from `Element` to `Event`s if self.namespace_qualified(local_namespaces) { let events: Vec = self.into(); for event in events { writer.write_event_async(event).await? } Ok(()) } else { Err(ElementError::NamespaceNotQualified.into()) } } pub async fn write_start, W: AsyncWrite + Unpin + Send>( &self, writer: &mut Writer, local_namespaces: &BTreeMap, S>, ) -> Result<()> { if self.namespace_qualified(local_namespaces) { let mut event = BytesStart::new(self.name()); // namespace declarations self.namespace_declarations.iter().for_each(|declaration| { let (prefix, namespace) = declaration; match prefix { Some(prefix) => { event.push_attribute((format!("xmlns:{}", prefix).as_str(), *namespace)) } None => event.push_attribute(("xmlns", *namespace)), } }); // attributes let event = event.with_attributes(self.attributes.iter().map(|(attr, value)| (*attr, *value))); writer.write_event_async(Event::Start(event)).await?; Ok(()) } else { Err(ElementError::NamespaceNotQualified.into()) } } pub async fn write_end( &self, writer: &mut Writer, ) -> Result<()> { let event = BytesEnd::new(self.name()); writer.write_event_async(Event::End(event)).await?; Ok(()) } #[async_recursion] pub async fn read, R: AsyncBufRead + Unpin + Send>( reader: &mut Reader, local_namespaces: &BTreeMap, S>, ) -> Result { let node = Node::read_recursive(reader, local_namespaces) .await? .ok_or(JabberError::UnexpectedEnd)?; match node { Node::Element(e) => Ok(e), Node::Text(_) => Err(JabberError::UnexpectedText), Node::Unknown => Err(JabberError::UnexpectedElement), } } pub async fn read_start, R: AsyncBufRead + Unpin + Send>( reader: &mut Reader, local_namespaces: &BTreeMap, S>, ) -> Result { let buf = Vec::new(); let event = reader.read_event_into_async(&mut buf).await?; match event { Event::Start(e) => { let prefix = e.name().prefix().map(|prefix| prefix.into_inner()); let converted_prefix; if let Some(raw_prefix) = prefix { converted_prefix = Some(str::from_utf8(raw_prefix)?) } let prefix = converted_prefix; let localname = str::from_utf8(e.local_name().into_inner())?.to_owned(); let mut local_namespaces = local_namespaces.clone(); let mut namespace_declarations = BTreeMap::new(); let attributes = BTreeMap::new(); for attribute in e.attributes() { let attribute = attribute?; if let Some(prefix_declaration) = attribute.key.as_namespace_binding() { match prefix_declaration { PrefixDeclaration::Default => { let value = str::from_utf8(attribute.value.as_ref())?; if let Some(_) = namespace_declarations.insert(None, value) { return Err(ElementParseError::DuplicateAttribute.into()); }; local_namespaces.insert(None, value); } PrefixDeclaration::Named(prefix) => { let key = str::from_utf8(prefix)?; let value = str::from_utf8(attribute.value.as_ref())?; if let Some(_) = namespace_declarations.insert(Some(key), value) { return Err(ElementParseError::DuplicateAttribute.into()); }; local_namespaces.insert(Some(key), value); } } } else { if let Some(_) = attributes.insert( str::from_utf8(attribute.key.into_inner())?, str::from_utf8(attribute.value.as_ref())?, ) { return Err(ElementParseError::DuplicateAttribute.into()); }; } } let namespace = *local_namespaces .get(&prefix) .ok_or(ElementParseError::NoNamespace)?; let mut children = Vec::new(); Ok(Self { prefix, localname, namespace, namespace_declarations: Box::new(namespace_declarations), attributes: Box::new(attributes), children: Box::new(children), }) } e => Err(ElementError::NotAStart(e).into()), } } } impl Node { #[async_recursion] async fn read_recursive, R: AsyncBufRead + Unpin + Send>( reader: &mut Reader, local_namespaces: &BTreeMap, S>, ) -> Result> { let mut buf = Vec::new(); let event = reader.read_event_into_async(&mut buf).await?; match event { Event::Empty(e) => { let prefix = e.name().prefix().map(|prefix| prefix.into_inner()); let converted_prefix; if let Some(raw_prefix) = prefix { converted_prefix = Some(str::from_utf8(raw_prefix)?) } let prefix = converted_prefix; let localname = str::from_utf8(e.local_name().into_inner())?.to_owned(); let mut local_namespaces = local_namespaces.clone(); let mut namespace_declarations = BTreeMap::new(); let attributes = BTreeMap::new(); for attribute in e.attributes() { let attribute = attribute?; if let Some(prefix_declaration) = attribute.key.as_namespace_binding() { match prefix_declaration { PrefixDeclaration::Default => { let value = str::from_utf8(attribute.value.as_ref())?; if let Some(_) = namespace_declarations.insert(None, value) { return Err(ElementParseError::DuplicateAttribute.into()); }; local_namespaces.insert(None, value); } PrefixDeclaration::Named(prefix) => { let key = str::from_utf8(prefix)?; let value = str::from_utf8(attribute.value.as_ref())?; if let Some(_) = namespace_declarations.insert(Some(key), value) { return Err(ElementParseError::DuplicateAttribute.into()); }; local_namespaces.insert(Some(key), value); } } } else { if let Some(_) = attributes.insert( str::from_utf8(attribute.key.into_inner())?, str::from_utf8(attribute.value.as_ref())?, ) { return Err(ElementParseError::DuplicateAttribute.into()); }; } } let namespace = *local_namespaces .get(&prefix) .ok_or(ElementParseError::NoNamespace)?; let mut children = Vec::new(); Ok(Some(Self::Element(Element { prefix, localname, namespace, namespace_declarations: Box::new(namespace_declarations), attributes: Box::new(attributes), children: Box::new(children), }))) } Event::Start(e) => { let prefix = e.name().prefix().map(|prefix| prefix.into_inner()); let converted_prefix; if let Some(raw_prefix) = prefix { converted_prefix = Some(str::from_utf8(raw_prefix)?) } let prefix = converted_prefix; let localname = str::from_utf8(e.local_name().into_inner())?.to_owned(); let mut local_namespaces = local_namespaces.clone(); let mut namespace_declarations = BTreeMap::new(); let attributes = BTreeMap::new(); for attribute in e.attributes() { let attribute = attribute?; if let Some(prefix_declaration) = attribute.key.as_namespace_binding() { match prefix_declaration { PrefixDeclaration::Default => { let value = str::from_utf8(attribute.value.as_ref())?; if let Some(_) = namespace_declarations.insert(None, value) { return Err(ElementParseError::DuplicateAttribute.into()); }; local_namespaces.insert(None, value); } PrefixDeclaration::Named(prefix) => { let key = str::from_utf8(prefix)?; let value = str::from_utf8(attribute.value.as_ref())?; if let Some(_) = namespace_declarations.insert(Some(key), value) { return Err(ElementParseError::DuplicateAttribute.into()); }; local_namespaces.insert(Some(key), value); } } } else { if let Some(_) = attributes.insert( str::from_utf8(attribute.key.into_inner())?, str::from_utf8(attribute.value.as_ref())?, ) { return Err(ElementParseError::DuplicateAttribute.into()); }; } } let namespace = *local_namespaces .get(&prefix) .ok_or(ElementParseError::NoNamespace)?; let mut children = Vec::new(); while let Some(child_node) = Node::read_recursive(reader, &local_namespaces).await? { children.push(child_node) } let mut children = Vec::new(); Ok(Some(Self::Element(Element { prefix, localname, namespace, namespace_declarations: Box::new(namespace_declarations), attributes: Box::new(attributes), children: Box::new(children), }))) } Event::End(_) => Ok(None), Event::Text(e) => Ok(Some(Self::Text(e.unescape()?.as_ref().to_string()))), e => Ok(Some(Self::Unknown)), } } fn namespace_qualified>( &self, namespace_context: &BTreeMap, S>, ) -> bool { match self { Self::Element(e) => e.namespace_qualified(namespace_context), _ => true, } } } pub enum NodeBuilder { Text(String), Element(ElementBuilder), } pub struct ElementBuilder { localname: String, prefix: Option, namespace: String, namespace_declarations: BTreeMap, String>, attributes: BTreeMap, children: Vec, } impl ElementBuilder { pub fn new(localname: S, prefix: Option, namespace: S) -> Self { Self { prefix, localname, namespace, namespace_declarations: Box::new(BTreeMap::new()), attributes: Box::new(BTreeMap::new()), children: Box::new(Vec::new()), } } pub fn push_namespace_declaration( &mut self, (prefix, namespace): (Option, S), ) -> Option { self.namespace_declarations.insert(prefix, namespace) } pub fn push_attribute(&mut self, (key, value): (S, S)) -> Option { self.attributes.insert(key, value) } pub fn push_child(&mut self, child: Node) { self.children.push(child) } /// checks if there is a namespace conflict within the element being built pub fn namespace_conflict>( &self ) -> bool { self.namespace_conflict_recursive(&BTreeMap::new()) } fn namespace_conflict_recursive>( &self, parent_namespaces: &BTreeMap, S>, ) -> bool { // create a new local_namespaces combining that in the context and those declared within the element let mut local_namespaces = *parent_namespaces.clone(); self.namespace_declarations.iter().for_each(|prefix, declaration| local_namespaces.insert(prefix, declaration)); if let Some(namespace) = local_namespaces.get(self.prefix) { if namespace != self.namespace { return false; } } else { return false; }; for child in *self.children { if child.namespace_conflict(&local_namespaces) == false { return false; } } true } // check for possible conflicts in namespace pub fn build(self) -> Result { for child in self.children { match child { Node::Element(e) => { if !e.namespace_conflict() } } } Element { prefix: self.prefix, localname: self.localname, namespace: self.namespace, namespace_declarations: self.namespace_declarations, attributes: self.attributes, children: self.children, } } } #[derive(Debug)] pub enum ElementError<'e> { NotAStart(Event<'e>), NotText, NoChildren, NamespaceNotQualified, MultipleChildren, } #[derive(Debug)] pub enum ElementParseError { DuplicateAttribute, NoNamespace, }