summaryrefslogblamecommitdiffstats
path: root/src/stanza/sasl.rs
blob: bbf3f4196ef4ea5e9789bb8950ee53129828c449 (plain) (tree)

































                                                            

 









                                         
                      


















































































































                                                                                             
 
use quick_xml::{
    events::{BytesStart, BytesText, Event},
    name::QName,
};

use crate::error::SASLError;
use crate::JabberError;

use super::Element;

const XMLNS: &str = "urn:ietf:params:xml:ns:xmpp-sasl";

#[derive(Debug)]
pub struct Auth<'e> {
    pub mechanism: &'e str,
    pub sasl_data: &'e str,
}

impl<'e> Auth<'e> {
    fn event(&self) -> Event<'e> {
        let mut start = BytesStart::new("auth");
        start.push_attribute(("xmlns", XMLNS));
        start.push_attribute(("mechanism", self.mechanism));
        Event::Start(start)
    }

    fn children(&self) -> Option<Vec<Element<'e>>> {
        let sasl = BytesText::from_escaped(self.sasl_data);
        let sasl = Element {
            event: Event::Text(sasl),
            children: None,
        };
        Some(vec![sasl])
    }
}

impl<'e> Into<Element<'e>> for Auth<'e> {
    fn into(self) -> Element<'e> {
        Element {
            event: self.event(),
            children: self.children(),
        }
    }
}

#[derive(Debug)]
pub struct Challenge {
    pub sasl_data: Vec<u8>,
}

impl<'e> TryFrom<&Element<'e>> for Challenge {
    type Error = JabberError;

    fn try_from(element: &Element<'e>) -> Result<Challenge, Self::Error> {
        if let Event::Start(start) = &element.event {
            if start.name() == QName(b"challenge") {
                let sasl_data: &Element<'_> = super::child(element)?;
                if let Event::Text(sasl_data) = &sasl_data.event {
                    let s = sasl_data.clone();
                    let s = s.into_inner();
                    let s = s.to_vec();
                    return Ok(Challenge { sasl_data: s });
                }
            }
        }
        Err(SASLError::NoChallenge.into())
    }
}

// impl<'e> TryFrom<Element<'e>> for Challenge {
//     type Error = JabberError;

//     fn try_from(element: Element<'e>) -> Result<Challenge, Self::Error> {
//         if let Event::Start(start) = &element.event {
//             if start.name() == QName(b"challenge") {
//                 println!("one");
//                 if let Some(children) = element.children.as_deref() {
//                     if children.len() == 1 {
//                         let sasl_data = children.first().unwrap();
//                         if let Event::Text(sasl_data) = &sasl_data.event {
//                             return Ok(Challenge {
//                                 sasl_data: sasl_data.clone().into_inner().to_vec(),
//                             });
//                         } else {
//                             return Err(SASLError::NoChallenge.into());
//                         }
//                     } else {
//                         return Err(SASLError::NoChallenge.into());
//                     }
//                 } else {
//                     return Err(SASLError::NoChallenge.into());
//                 }
//             }
//         }
//         Err(SASLError::NoChallenge.into())
//     }
// }

#[derive(Debug)]
pub struct Response<'e> {
    pub sasl_data: &'e str,
}

impl<'e> Response<'e> {
    fn event(&self) -> Event<'e> {
        let mut start = BytesStart::new("response");
        start.push_attribute(("xmlns", XMLNS));
        Event::Start(start)
    }

    fn children(&self) -> Option<Vec<Element<'e>>> {
        let sasl = BytesText::from_escaped(self.sasl_data);
        let sasl = Element {
            event: Event::Text(sasl),
            children: None,
        };
        Some(vec![sasl])
    }
}

impl<'e> Into<Element<'e>> for Response<'e> {
    fn into(self) -> Element<'e> {
        Element {
            event: self.event(),
            children: self.children(),
        }
    }
}

#[derive(Debug)]
pub struct Success {
    pub sasl_data: Option<Vec<u8>>,
}

impl<'e> TryFrom<&Element<'e>> for Success {
    type Error = JabberError;

    fn try_from(element: &Element<'e>) -> Result<Success, Self::Error> {
        match &element.event {
            Event::Start(start) => {
                if start.name() == QName(b"success") {
                    match super::child(element) {
                        Ok(sasl_data) => {
                            if let Event::Text(sasl_data) = &sasl_data.event {
                                return Ok(Success {
                                    sasl_data: Some(sasl_data.clone().into_inner().to_vec()),
                                });
                            }
                        }
                        Err(_) => return Ok(Success { sasl_data: None }),
                    };
                }
            }
            Event::Empty(empty) => {
                if empty.name() == QName(b"success") {
                    return Ok(Success { sasl_data: None });
                }
            }
            _ => {}
        }
        Err(SASLError::NoSuccess.into())
    }
}