diff --git a/parsers/ChangeLog b/parsers/ChangeLog index 2b558bffb605b6bcdb5e02457b1db9ba43e86c5d..155b76a847ff65d67bb8a90192eddde0ffdd577f 100644 --- a/parsers/ChangeLog +++ b/parsers/ChangeLog @@ -48,6 +48,9 @@ XXXX-YY-ZZ RELEASER ssm::StreamManagement::optional and starttls::StartTls::required are now proper bools, instead of Option (!518) - vCard-temp queries have been split into vcard::VCardQuery (!522) + - http_upload’s Header type has been split into HeaderName, an enum + containing only the name of the header, and the Header struct with + both a name and a value(!530) * New parsers/serialisers: - Stream Features (RFC 6120) (!400) - Spam Reporting (XEP-0377) (!506) diff --git a/parsers/src/http_upload.rs b/parsers/src/http_upload.rs index e6507b8128194ec4fcec86b22abfd56f1c931f7f..fb276fd58f197b6c92a160be151d3560e792abd0 100644 --- a/parsers/src/http_upload.rs +++ b/parsers/src/http_upload.rs @@ -4,15 +4,11 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. -use xso::{ - error::{Error, FromElementError, FromEventsError}, - exports::rxml, - minidom_compat, AsXml, FromXml, -}; +use xso::{error::Error, AsXml, AsXmlText, FromXml, FromXmlText}; use crate::iq::{IqGetPayload, IqResultPayload}; use crate::ns; -use minidom::Element; +use alloc::borrow::Cow; /// Requesting a slot #[derive(FromXml, AsXml, Debug, Clone, PartialEq)] @@ -33,32 +29,37 @@ pub struct SlotRequest { impl IqGetPayload for SlotRequest {} -/// Slot header +/// All three possible header names. #[derive(Debug, Clone, PartialEq)] -pub enum Header { +pub enum HeaderName { /// Authorization header - Authorization(String), + Authorization, /// Cookie header - Cookie(String), + Cookie, /// Expires header - Expires(String), + Expires, +} + +impl HeaderName { + /// Returns the string version of this enum value. + pub fn as_str(&self) -> &'static str { + match self { + HeaderName::Authorization => "Authorization", + HeaderName::Cookie => "Cookie", + HeaderName::Expires => "Expires", + } + } } -impl TryFrom for Header { - type Error = FromElementError; - fn try_from(elem: Element) -> Result { - check_self!(elem, "header", HTTP_UPLOAD); - check_no_children!(elem, "header"); - check_no_unknown_attributes!(elem, "header", ["name"]); - let name: String = get_attr!(elem, "name", Required); - let text = elem.text(); - - Ok(match name.to_lowercase().as_str() { - "authorization" => Header::Authorization(text), - "cookie" => Header::Cookie(text), - "expires" => Header::Expires(text), +impl FromXmlText for HeaderName { + fn from_xml_text(mut s: String) -> Result { + s.make_ascii_lowercase(); + Ok(match s.as_str() { + "authorization" => HeaderName::Authorization, + "cookie" => HeaderName::Cookie, + "expires" => HeaderName::Expires, _ => { return Err(Error::Other( "Header name must be either 'Authorization', 'Cookie', or 'Expires'.", @@ -69,41 +70,23 @@ impl TryFrom for Header { } } -impl FromXml for Header { - type Builder = minidom_compat::FromEventsViaElement
; - - fn from_events( - qname: rxml::QName, - attrs: rxml::AttrMap, - ) -> Result { - if qname.0 != ns::HTTP_UPLOAD || qname.1 != "header" { - return Err(FromEventsError::Mismatch { name: qname, attrs }); - } - Self::Builder::new(qname, attrs) - } -} - -impl From
for Element { - fn from(elem: Header) -> Element { - let (attr, val) = match elem { - Header::Authorization(val) => ("Authorization", val), - Header::Cookie(val) => ("Cookie", val), - Header::Expires(val) => ("Expires", val), - }; - - Element::builder("header", ns::HTTP_UPLOAD) - .attr("name", attr) - .append(val) - .build() +impl AsXmlText for HeaderName { + fn as_xml_text(&self) -> Result, Error> { + Ok(Cow::Borrowed(self.as_str())) } } -impl AsXml for Header { - type ItemIter<'x> = minidom_compat::AsItemsViaElement<'x>; +/// Slot header +#[derive(FromXml, AsXml, Debug, Clone, PartialEq)] +#[xml(namespace = ns::HTTP_UPLOAD, name = "header")] +pub struct Header { + /// Name of the header + #[xml(attribute)] + pub name: HeaderName, - fn as_xml_iter(&self) -> Result, Error> { - minidom_compat::AsItemsViaElement::new(self.clone()) - } + /// Value of the header + #[xml(text)] + pub value: String, } /// Put URL @@ -146,11 +129,13 @@ impl IqResultPayload for SlotResult {} #[cfg(test)] mod tests { use super::*; + use minidom::Element; #[cfg(target_pointer_width = "32")] #[test] fn test_size() { assert_size!(SlotRequest, 32); + assert_size!(HeaderName, 1); assert_size!(Header, 16); assert_size!(Put, 24); assert_size!(Get, 12); @@ -161,6 +146,7 @@ mod tests { #[test] fn test_size() { assert_size!(SlotRequest, 56); + assert_size!(HeaderName, 1); assert_size!(Header, 32); assert_size!(Put, 48); assert_size!(Get, 24); @@ -196,11 +182,17 @@ mod tests { assert_eq!(slot.put.url, String::from("https://upload.montague.tld/4a771ac1-f0b2-4a4a-9700-f2a26fa2bb67/tr%C3%A8s%20cool.jpg")); assert_eq!( slot.put.headers[0], - Header::Authorization(String::from("Basic Base64String==")) + Header { + name: HeaderName::Authorization, + value: String::from("Basic Base64String==") + } ); assert_eq!( slot.put.headers[1], - Header::Cookie(String::from("foo=bar; user=romeo")) + Header { + name: HeaderName::Cookie, + value: String::from("foo=bar; user=romeo") + } ); assert_eq!(slot.get.url, String::from("https://download.montague.tld/4a771ac1-f0b2-4a4a-9700-f2a26fa2bb67/tr%C3%A8s%20cool.jpg")); } diff --git a/xmpp/src/upload/receive.rs b/xmpp/src/upload/receive.rs index 2c9fb66d9d08be3a62e7910849ae153a0ab50a00..38cee635178c4da351a07faddb3da90c4b13458e 100644 --- a/xmpp/src/upload/receive.rs +++ b/xmpp/src/upload/receive.rs @@ -10,11 +10,7 @@ use reqwest::{ use std::path::PathBuf; use tokio::fs::File; use tokio_util::codec::{BytesCodec, FramedRead}; -use tokio_xmpp::{ - jid::Jid, - minidom::Element, - parsers::http_upload::{Header as HttpUploadHeader, SlotResult}, -}; +use tokio_xmpp::{jid::Jid, minidom::Element, parsers::http_upload::SlotResult}; use crate::{Agent, Event}; @@ -39,12 +35,8 @@ pub async fn handle_upload_result( let mut headers = ReqwestHeaderMap::new(); for header in slot.put.headers { - let (attr, val) = match header { - HttpUploadHeader::Authorization(val) => ("Authorization", val), - HttpUploadHeader::Cookie(val) => ("Cookie", val), - HttpUploadHeader::Expires(val) => ("Expires", val), - }; - headers.insert(attr, val.parse().unwrap()); + let attr = header.name.as_str(); + headers.insert(attr, header.value.parse().unwrap()); } let web = ReqwestClient::new();