diff options
Diffstat (limited to 'src/dav/decoder.rs')
-rw-r--r-- | src/dav/decoder.rs | 948 |
1 files changed, 0 insertions, 948 deletions
diff --git a/src/dav/decoder.rs b/src/dav/decoder.rs deleted file mode 100644 index aa3c7e5..0000000 --- a/src/dav/decoder.rs +++ /dev/null @@ -1,948 +0,0 @@ -use std::borrow::Cow; -use std::future::Future; - -use quick_xml::events::{Event, BytesStart, BytesDecl, BytesText}; -use quick_xml::events::attributes::AttrError; -use quick_xml::name::{Namespace, QName, PrefixDeclaration, ResolveResult, ResolveResult::*}; -use quick_xml::reader::NsReader; -use tokio::io::AsyncBufRead; - -use super::types::*; -use super::error::ParsingError; -use super::xml::{Node, QRead, Reader, IRead, DAV_URN, CAL_URN}; - -//@TODO (1) Rewrite all objects as Href, -// where we return Ok(None) instead of trying to find the object at any cost. -// Add a xml.find<E: Qread>() -> Result<Option<E>, ParsingError> or similar for the cases we -// really need the object -// (2) Rewrite QRead and replace Result<Option<_>, _> with Result<_, _>, not found being a possible -// error. -// (3) Rewrite vectors with xml.collect<E: QRead>() -> Result<Vec<E>, _> -// (4) Something for alternatives would be great but no idea yet - -// ---- ROOT ---- - -/// Propfind request -impl<E: Extension> QRead<PropFind<E>> for PropFind<E> { - async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { - xml.open(DAV_URN, "propfind").await?; - let propfind: PropFind<E> = loop { - // allprop - if let Some(_) = xml.maybe_open(DAV_URN, "allprop").await? { - let includ = xml.maybe_find::<Include<E>>().await?; - xml.close().await?; - break PropFind::AllProp(includ) - } - - // propname - if let Some(_) = xml.maybe_open(DAV_URN, "propname").await? { - xml.close().await?; - break PropFind::PropName - } - - // prop - let (mut maybe_prop, mut dirty) = (None, false); - xml.maybe_read::<PropName<E>>(&mut maybe_prop, &mut dirty).await?; - if let Some(prop) = maybe_prop { - break PropFind::Prop(prop) - } - - // not found, skipping - xml.skip().await?; - }; - xml.close().await?; - - Ok(propfind) - } -} - -/// PROPPATCH request -impl<E: Extension> QRead<PropertyUpdate<E>> for PropertyUpdate<E> { - async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { - xml.open(DAV_URN, "propertyupdate").await?; - let collected_items = xml.collect::<PropertyUpdateItem<E>>().await?; - xml.close().await?; - Ok(PropertyUpdate(collected_items)) - } -} - -/// Generic response -impl<E: Extension, N: Node<N>> QRead<Multistatus<E,N>> for Multistatus<E,N> { - async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { - xml.open(DAV_URN, "multistatus").await?; - let mut responses = Vec::new(); - let mut responsedescription = None; - - loop { - let mut dirty = false; - xml.maybe_push(&mut responses, &mut dirty).await?; - xml.maybe_read(&mut responsedescription, &mut dirty).await?; - if !dirty { - match xml.peek() { - Event::End(_) => break, - _ => xml.skip().await?, - }; - } - } - - xml.close().await?; - Ok(Multistatus { responses, responsedescription }) - } -} - -// LOCK REQUEST -impl QRead<LockInfo> for LockInfo { - async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { - xml.open(DAV_URN, "lockinfo").await?; - let (mut m_scope, mut m_type, mut owner) = (None, None, None); - loop { - let mut dirty = false; - xml.maybe_read::<LockScope>(&mut m_scope, &mut dirty).await?; - xml.maybe_read::<LockType>(&mut m_type, &mut dirty).await?; - xml.maybe_read::<Owner>(&mut owner, &mut dirty).await?; - - if !dirty { - match xml.peek() { - Event::End(_) => break, - _ => xml.skip().await?, - }; - } - } - xml.close().await?; - match (m_scope, m_type) { - (Some(lockscope), Some(locktype)) => Ok(LockInfo { lockscope, locktype, owner }), - _ => Err(ParsingError::MissingChild), - } - } -} - -// LOCK RESPONSE -impl<E: Extension> QRead<PropValue<E>> for PropValue<E> { - async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { - xml.open(DAV_URN, "prop").await?; - let mut acc = xml.collect::<Property<E>>().await?; - xml.close().await?; - Ok(PropValue(acc)) - } -} - - -/// Error response -impl<E: Extension> QRead<Error<E>> for Error<E> { - async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { - xml.open(DAV_URN, "error").await?; - let violations = xml.collect::<Violation<E>>().await?; - xml.close().await?; - Ok(Error(violations)) - } -} - - - -// ---- INNER XML -impl<E: Extension, N: Node<N>> QRead<Response<E,N>> for Response<E,N> { - async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { - xml.open(DAV_URN, "response").await?; - let (mut status, mut error, mut responsedescription, mut location) = (None, None, None, None); - let mut href = Vec::new(); - let mut propstat = Vec::new(); - - loop { - let mut dirty = false; - xml.maybe_read::<Status>(&mut status, &mut dirty).await?; - xml.maybe_push::<Href>(&mut href, &mut dirty).await?; - xml.maybe_push::<PropStat<E,N>>(&mut propstat, &mut dirty).await?; - xml.maybe_read::<Error<E>>(&mut error, &mut dirty).await?; - xml.maybe_read::<ResponseDescription>(&mut responsedescription, &mut dirty).await?; - xml.maybe_read::<Location>(&mut location, &mut dirty).await?; - - if !dirty { - match xml.peek() { - Event::End(_) => break, - _ => { xml.skip().await? }, - }; - } - } - - xml.close().await?; - match (status, &propstat[..], &href[..]) { - (Some(status), &[], &[_, ..]) => Ok(Response { - status_or_propstat: StatusOrPropstat::Status(href, status), - error, responsedescription, location, - }), - (None, &[_, ..], &[_, ..]) => Ok(Response { - status_or_propstat: StatusOrPropstat::PropStat(href.into_iter().next().unwrap(), propstat), - error, responsedescription, location, - }), - (Some(_), &[_, ..], _) => Err(ParsingError::InvalidValue), - _ => Err(ParsingError::MissingChild), - } - } -} - -impl<E: Extension, N: Node<N>> QRead<PropStat<E,N>> for PropStat<E,N> { - async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { - xml.open(DAV_URN, "propstat").await?; - - let (mut m_prop, mut m_status, mut error, mut responsedescription) = (None, None, None, None); - - loop { - let mut dirty = false; - xml.maybe_read::<N>(&mut m_prop, &mut dirty).await?; - xml.maybe_read::<Status>(&mut m_status, &mut dirty).await?; - xml.maybe_read::<Error<E>>(&mut error, &mut dirty).await?; - xml.maybe_read::<ResponseDescription>(&mut responsedescription, &mut dirty).await?; - - if !dirty { - match xml.peek() { - Event::End(_) => break, - _ => xml.skip().await?, - }; - } - } - - xml.close().await?; - match (m_prop, m_status) { - (Some(prop), Some(status)) => Ok(PropStat { prop, status, error, responsedescription }), - _ => Err(ParsingError::MissingChild), - } - } -} - -impl QRead<Status> for Status { - async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { - xml.open(DAV_URN, "status").await?; - let fullcode = xml.tag_string().await?; - let txtcode = fullcode.splitn(3, ' ').nth(1).ok_or(ParsingError::InvalidValue)?; - let code = http::status::StatusCode::from_bytes(txtcode.as_bytes()).or(Err(ParsingError::InvalidValue))?; - xml.close().await?; - Ok(Status(code)) - } -} - -impl QRead<ResponseDescription> for ResponseDescription { - async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { - xml.open(DAV_URN, "responsedescription").await?; - let cnt = xml.tag_string().await?; - xml.close().await?; - Ok(ResponseDescription(cnt)) - } -} - -impl QRead<Location> for Location { - async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { - xml.open(DAV_URN, "location").await?; - let href = xml.find::<Href>().await?; - xml.close().await?; - Ok(Location(href)) - } -} - -impl<E: Extension> QRead<PropertyUpdateItem<E>> for PropertyUpdateItem<E> { - async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { - match Remove::qread(xml).await { - Err(ParsingError::Recoverable) => (), - otherwise => return otherwise.map(PropertyUpdateItem::Remove), - } - Set::qread(xml).await.map(PropertyUpdateItem::Set) - } -} - -impl<E: Extension> QRead<Remove<E>> for Remove<E> { - async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { - xml.open(DAV_URN, "remove").await?; - let propname = xml.find::<PropName<E>>().await?; - xml.close().await?; - Ok(Remove(propname)) - } -} - -impl<E: Extension> QRead<Set<E>> for Set<E> { - async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { - xml.open(DAV_URN, "set").await?; - let propvalue = xml.find::<PropValue<E>>().await?; - xml.close().await?; - Ok(Set(propvalue)) - } -} - -impl<E: Extension> QRead<Violation<E>> for Violation<E> { - async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { - if xml.maybe_open(DAV_URN, "lock-token-matches-request-uri").await?.is_some() { - xml.close().await?; - Ok(Violation::LockTokenMatchesRequestUri) - } else if xml.maybe_open(DAV_URN, "lock-token-submitted").await?.is_some() { - let links = xml.collect::<Href>().await?; - xml.close().await?; - Ok(Violation::LockTokenSubmitted(links)) - } else if xml.maybe_open(DAV_URN, "no-conflicting-lock").await?.is_some() { - let links = xml.collect::<Href>().await?; - xml.close().await?; - Ok(Violation::NoConflictingLock(links)) - } else if xml.maybe_open(DAV_URN, "no-external-entities").await?.is_some() { - xml.close().await?; - Ok(Violation::NoExternalEntities) - } else if xml.maybe_open(DAV_URN, "preserved-live-properties").await?.is_some() { - xml.close().await?; - Ok(Violation::PreservedLiveProperties) - } else if xml.maybe_open(DAV_URN, "propfind-finite-depth").await?.is_some() { - xml.close().await?; - Ok(Violation::PropfindFiniteDepth) - } else if xml.maybe_open(DAV_URN, "cannot-modify-protected-property").await?.is_some() { - xml.close().await?; - Ok(Violation::CannotModifyProtectedProperty) - } else { - E::Error::qread(xml).await.map(Violation::Extension) - } - } -} - -impl<E: Extension> QRead<Include<E>> for Include<E> { - async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { - xml.open(DAV_URN, "include").await?; - let acc = xml.collect::<PropertyRequest<E>>().await?; - xml.close().await?; - Ok(Include(acc)) - } -} - -impl<E: Extension> QRead<PropName<E>> for PropName<E> { - async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { - xml.open(DAV_URN, "prop").await?; - let acc = xml.collect::<PropertyRequest<E>>().await?; - xml.close().await?; - Ok(PropName(acc)) - } -} - -impl<E: Extension> QRead<PropertyRequest<E>> for PropertyRequest<E> { - async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { - let maybe = if xml.maybe_open(DAV_URN, "creationdate").await?.is_some() { - Some(PropertyRequest::CreationDate) - } else if xml.maybe_open(DAV_URN, "displayname").await?.is_some() { - Some(PropertyRequest::DisplayName) - } else if xml.maybe_open(DAV_URN, "getcontentlanguage").await?.is_some() { - Some(PropertyRequest::GetContentLanguage) - } else if xml.maybe_open(DAV_URN, "getcontentlength").await?.is_some() { - Some(PropertyRequest::GetContentLength) - } else if xml.maybe_open(DAV_URN, "getcontenttype").await?.is_some() { - Some(PropertyRequest::GetContentType) - } else if xml.maybe_open(DAV_URN, "getetag").await?.is_some() { - Some(PropertyRequest::GetEtag) - } else if xml.maybe_open(DAV_URN, "getlastmodified").await?.is_some() { - Some(PropertyRequest::GetLastModified) - } else if xml.maybe_open(DAV_URN, "lockdiscovery").await?.is_some() { - Some(PropertyRequest::LockDiscovery) - } else if xml.maybe_open(DAV_URN, "resourcetype").await?.is_some() { - Some(PropertyRequest::ResourceType) - } else if xml.maybe_open(DAV_URN, "supportedlock").await?.is_some() { - Some(PropertyRequest::SupportedLock) - } else { - None - }; - - match maybe { - Some(pr) => { - xml.close().await?; - Ok(pr) - }, - None => E::PropertyRequest::qread(xml).await.map(PropertyRequest::Extension), - } - } -} - -impl<E: Extension> QRead<Property<E>> for Property<E> { - async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { - use chrono::{DateTime, FixedOffset, TimeZone}; - - // Core WebDAV properties - if xml.maybe_open(DAV_URN, "creationdate").await?.is_some() { - let datestr = xml.tag_string().await?; - xml.close().await?; - return Ok(Property::CreationDate(DateTime::parse_from_rfc3339(datestr.as_str())?)) - } else if xml.maybe_open(DAV_URN, "displayname").await?.is_some() { - let name = xml.tag_string().await?; - xml.close().await?; - return Ok(Property::DisplayName(name)) - } else if xml.maybe_open(DAV_URN, "getcontentlanguage").await?.is_some() { - let lang = xml.tag_string().await?; - xml.close().await?; - return Ok(Property::GetContentLanguage(lang)) - } else if xml.maybe_open(DAV_URN, "getcontentlength").await?.is_some() { - let cl = xml.tag_string().await?.parse::<u64>()?; - xml.close().await?; - return Ok(Property::GetContentLength(cl)) - } else if xml.maybe_open(DAV_URN, "getcontenttype").await?.is_some() { - let ct = xml.tag_string().await?; - xml.close().await?; - return Ok(Property::GetContentType(ct)) - } else if xml.maybe_open(DAV_URN, "getetag").await?.is_some() { - let etag = xml.tag_string().await?; - xml.close().await?; - return Ok(Property::GetEtag(etag)) - } else if xml.maybe_open(DAV_URN, "getlastmodified").await?.is_some() { - let datestr = xml.tag_string().await?; - xml.close().await?; - return Ok(Property::GetLastModified(DateTime::parse_from_rfc2822(datestr.as_str())?)) - } else if xml.maybe_open(DAV_URN, "lockdiscovery").await?.is_some() { - let acc = xml.collect::<ActiveLock>().await?; - xml.close().await?; - return Ok(Property::LockDiscovery(acc)) - } else if xml.maybe_open(DAV_URN, "resourcetype").await?.is_some() { - let acc = xml.collect::<ResourceType<E>>().await?; - xml.close().await?; - return Ok(Property::ResourceType(acc)) - } else if xml.maybe_open(DAV_URN, "supportedlock").await?.is_some() { - let acc = xml.collect::<LockEntry>().await?; - xml.close().await?; - return Ok(Property::SupportedLock(acc)) - } - - // Option 2: an extension property, delegating - E::Property::qread(xml).await.map(Property::Extension) - } -} - -impl QRead<ActiveLock> for ActiveLock { - async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { - xml.open(DAV_URN, "activelock").await?; - let (mut m_scope, mut m_type, mut m_depth, mut owner, mut timeout, mut locktoken, mut m_root) = - (None, None, None, None, None, None, None); - - loop { - let mut dirty = false; - xml.maybe_read::<LockScope>(&mut m_scope, &mut dirty).await?; - xml.maybe_read::<LockType>(&mut m_type, &mut dirty).await?; - xml.maybe_read::<Depth>(&mut m_depth, &mut dirty).await?; - xml.maybe_read::<Owner>(&mut owner, &mut dirty).await?; - xml.maybe_read::<Timeout>(&mut timeout, &mut dirty).await?; - xml.maybe_read::<LockToken>(&mut locktoken, &mut dirty).await?; - xml.maybe_read::<LockRoot>(&mut m_root, &mut dirty).await?; - - if !dirty { - match xml.peek() { - Event::End(_) => break, - _ => { xml.skip().await?; }, - } - } - } - - xml.close().await?; - match (m_scope, m_type, m_depth, m_root) { - (Some(lockscope), Some(locktype), Some(depth), Some(lockroot)) => - Ok(ActiveLock { lockscope, locktype, depth, owner, timeout, locktoken, lockroot }), - _ => Err(ParsingError::MissingChild), - } - } -} - -impl QRead<Depth> for Depth { - async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { - xml.open(DAV_URN, "depth").await?; - let depth_str = xml.tag_string().await?; - xml.close().await?; - match depth_str.as_str() { - "0" => Ok(Depth::Zero), - "1" => Ok(Depth::One), - "infinity" => Ok(Depth::Infinity), - _ => Err(ParsingError::WrongToken), - } - } -} - -impl QRead<Owner> for Owner { - async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { - xml.open(DAV_URN, "owner").await?; - - let mut owner = Owner::Unknown; - loop { - match xml.peek() { - Event::Text(_) | Event::CData(_) => { - let txt = xml.tag_string().await?; - if matches!(owner, Owner::Unknown) { - owner = Owner::Txt(txt); - } - } - Event::Start(_) | Event::Empty(_) => { - match Href::qread(xml).await { - Ok(href) => { owner = Owner::Href(href); }, - Err(ParsingError::Recoverable) => { xml.skip().await?; }, - Err(e) => return Err(e), - } - } - Event::End(_) => break, - _ => { xml.skip().await?; }, - } - }; - xml.close().await?; - Ok(owner) - } -} - -impl QRead<Timeout> for Timeout { - async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { - const SEC_PFX: &str = "SEC_PFX"; - xml.open(DAV_URN, "timeout").await?; - - let timeout = match xml.tag_string().await?.as_str() { - "Infinite" => Timeout::Infinite, - seconds => match seconds.strip_prefix(SEC_PFX) { - Some(secs) => Timeout::Seconds(secs.parse::<u32>()?), - None => return Err(ParsingError::InvalidValue), - }, - }; - - xml.close().await?; - Ok(timeout) - } -} - -impl QRead<LockToken> for LockToken { - async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { - xml.open(DAV_URN, "locktoken").await?; - let href = Href::qread(xml).await?; - xml.close().await?; - Ok(LockToken(href)) - } -} - -impl QRead<LockRoot> for LockRoot { - async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { - xml.open(DAV_URN, "lockroot").await?; - let href = Href::qread(xml).await?; - xml.close().await?; - Ok(LockRoot(href)) - } -} - -impl<E: Extension> QRead<ResourceType<E>> for ResourceType<E> { - async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { - if xml.maybe_open(DAV_URN, "collection").await?.is_some() { - xml.close().await?; - return Ok(ResourceType::Collection) - } - - E::ResourceType::qread(xml).await.map(ResourceType::Extension) - } -} - -impl QRead<LockEntry> for LockEntry { - async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { - xml.open(DAV_URN, "lockentry").await?; - let (mut maybe_scope, mut maybe_type) = (None, None); - - loop { - let mut dirty = false; - xml.maybe_read::<LockScope>(&mut maybe_scope, &mut dirty).await?; - xml.maybe_read::<LockType>(&mut maybe_type, &mut dirty).await?; - if !dirty { - match xml.peek() { - Event::End(_) => break, - _ => xml.skip().await?, - }; - } - } - - xml.close().await?; - match (maybe_scope, maybe_type) { - (Some(lockscope), Some(locktype)) => Ok(LockEntry { lockscope, locktype }), - _ => Err(ParsingError::MissingChild), - } - } -} - -impl QRead<LockScope> for LockScope { - async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { - xml.open(DAV_URN, "lockscope").await?; - - let lockscope = loop { - if xml.maybe_open(DAV_URN, "exclusive").await?.is_some() { - xml.close().await?; - break LockScope::Exclusive - } else if xml.maybe_open(DAV_URN, "shared").await?.is_some() { - xml.close().await?; - break LockScope::Shared - } - - xml.skip().await?; - }; - - xml.close().await?; - Ok(lockscope) - } -} - -impl QRead<LockType> for LockType { - async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { - xml.open(DAV_URN, "locktype").await?; - - let locktype = loop { - if xml.maybe_open(DAV_URN, "write").await?.is_some() { - xml.close().await?; - break LockType::Write - } - - xml.skip().await?; - }; - - xml.close().await?; - Ok(locktype) - } -} - -impl QRead<Href> for Href { - async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { - xml.open(DAV_URN, "href").await?; - let mut url = xml.tag_string().await?; - xml.close().await?; - Ok(Href(url)) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use chrono::{FixedOffset, DateTime, TimeZone, Utc}; - use crate::dav::realization::Core; - - #[tokio::test] - async fn basic_propfind_propname() { - let src = r#"<?xml version="1.0" encoding="utf-8" ?> -<rando/> -<garbage><old/></garbage> -<D:propfind xmlns:D="DAV:"> - <D:propname/> -</D:propfind> -"#; - - let mut rdr = Reader::new(NsReader::from_reader(src.as_bytes())).await.unwrap(); - let got = rdr.find::<PropFind::<Core>>().await.unwrap(); - - assert_eq!(got, PropFind::<Core>::PropName); - } - - #[tokio::test] - async fn basic_propfind_prop() { - let src = r#"<?xml version="1.0" encoding="utf-8" ?> -<rando/> -<garbage><old/></garbage> -<D:propfind xmlns:D="DAV:"> - <D:prop> - <D:displayname/> - <D:getcontentlength/> - <D:getcontenttype/> - <D:getetag/> - <D:getlastmodified/> - <D:resourcetype/> - <D:supportedlock/> - </D:prop> -</D:propfind> -"#; - - let mut rdr = Reader::new(NsReader::from_reader(src.as_bytes())).await.unwrap(); - let got = rdr.find::<PropFind::<Core>>().await.unwrap(); - - assert_eq!(got, PropFind::Prop(PropName(vec![ - PropertyRequest::DisplayName, - PropertyRequest::GetContentLength, - PropertyRequest::GetContentType, - PropertyRequest::GetEtag, - PropertyRequest::GetLastModified, - PropertyRequest::ResourceType, - PropertyRequest::SupportedLock, - ]))); - } - - #[tokio::test] - async fn rfc_lock_error() { - let src = r#"<?xml version="1.0" encoding="utf-8" ?> - <D:error xmlns:D="DAV:"> - <D:lock-token-submitted> - <D:href>/locked/</D:href> - </D:lock-token-submitted> - </D:error>"#; - - let mut rdr = Reader::new(NsReader::from_reader(src.as_bytes())).await.unwrap(); - let got = rdr.find::<Error::<Core>>().await.unwrap(); - - assert_eq!(got, Error(vec![ - Violation::LockTokenSubmitted(vec![ - Href("/locked/".into()) - ]) - ])); - } - - - #[tokio::test] - async fn rfc_propertyupdate() { - let src = r#"<?xml version="1.0" encoding="utf-8" ?> - <D:propertyupdate xmlns:D="DAV:" - xmlns:Z="http://ns.example.com/standards/z39.50/"> - <D:set> - <D:prop> - <Z:Authors> - <Z:Author>Jim Whitehead</Z:Author> - <Z:Author>Roy Fielding</Z:Author> - </Z:Authors> - </D:prop> - </D:set> - <D:remove> - <D:prop><Z:Copyright-Owner/></D:prop> - </D:remove> - </D:propertyupdate>"#; - - let mut rdr = Reader::new(NsReader::from_reader(src.as_bytes())).await.unwrap(); - let got = rdr.find::<PropertyUpdate::<Core>>().await.unwrap(); - - assert_eq!(got, PropertyUpdate(vec![ - PropertyUpdateItem::Set(Set(PropValue(vec![]))), - PropertyUpdateItem::Remove(Remove(PropName(vec![]))), - ])); - } - - #[tokio::test] - async fn rfc_lockinfo() { - let src = r#" -<?xml version="1.0" encoding="utf-8" ?> -<D:lockinfo xmlns:D='DAV:'> - <D:lockscope><D:exclusive/></D:lockscope> - <D:locktype><D:write/></D:locktype> - <D:owner> - <D:href>http://example.org/~ejw/contact.html</D:href> - </D:owner> -</D:lockinfo> -"#; - - let mut rdr = Reader::new(NsReader::from_reader(src.as_bytes())).await.unwrap(); - let got = rdr.find::<LockInfo>().await.unwrap(); - - assert_eq!(got, LockInfo { - lockscope: LockScope::Exclusive, - locktype: LockType::Write, - owner: Some(Owner::Href(Href("http://example.org/~ejw/contact.html".into()))), - }); - } - - #[tokio::test] - async fn rfc_multistatus_name() { - let src = r#" -<?xml version="1.0" encoding="utf-8" ?> - <multistatus xmlns="DAV:"> - <response> - <href>http://www.example.com/container/</href> - <propstat> - <prop xmlns:R="http://ns.example.com/boxschema/"> - <R:bigbox/> - <R:author/> - <creationdate/> - <displayname/> - <resourcetype/> - <supportedlock/> - </prop> - <status>HTTP/1.1 200 OK</status> - </propstat> - </response> - <response> - <href>http://www.example.com/container/front.html</href> - <propstat> - <prop xmlns:R="http://ns.example.com/boxschema/"> - <R:bigbox/> - <creationdate/> - <displayname/> - <getcontentlength/> - <getcontenttype/> - <getetag/> - <getlastmodified/> - <resourcetype/> - <supportedlock/> - </prop> - <status>HTTP/1.1 200 OK</status> - </propstat> - </response> - </multistatus> -"#; - - let mut rdr = Reader::new(NsReader::from_reader(src.as_bytes())).await.unwrap(); - let got = rdr.find::<Multistatus::<Core, PropName<Core>>>().await.unwrap(); - - assert_eq!(got, Multistatus { - responses: vec![ - Response { - status_or_propstat: StatusOrPropstat::PropStat( - Href("http://www.example.com/container/".into()), - vec![PropStat { - prop: PropName(vec![ - PropertyRequest::CreationDate, - PropertyRequest::DisplayName, - PropertyRequest::ResourceType, - PropertyRequest::SupportedLock, - ]), - status: Status(http::status::StatusCode::OK), - error: None, - responsedescription: None, - }], - ), - error: None, - responsedescription: None, - location: None, - }, - Response { - status_or_propstat: StatusOrPropstat::PropStat( - Href("http://www.example.com/container/front.html".into()), - vec![PropStat { - prop: PropName(vec![ - PropertyRequest::CreationDate, - PropertyRequest::DisplayName, - PropertyRequest::GetContentLength, - PropertyRequest::GetContentType, - PropertyRequest::GetEtag, - PropertyRequest::GetLastModified, - PropertyRequest::ResourceType, - PropertyRequest::SupportedLock, - ]), - status: Status(http::status::StatusCode::OK), - error: None, - responsedescription: None, - }], - ), - error: None, - responsedescription: None, - location: None, - }, - ], - responsedescription: None, - }); - } - - - #[tokio::test] - async fn rfc_multistatus_value() { - let src = r#" - <?xml version="1.0" encoding="utf-8" ?> - <D:multistatus xmlns:D="DAV:"> - <D:response> - <D:href>/container/</D:href> - <D:propstat> - <D:prop xmlns:R="http://ns.example.com/boxschema/"> - <R:bigbox><R:BoxType>Box type A</R:BoxType></R:bigbox> - <R:author><R:Name>Hadrian</R:Name></R:author> - <D:creationdate>1997-12-01T17:42:21-08:00</D:creationdate> - <D:displayname>Example collection</D:displayname> - <D:resourcetype><D:collection/></D:resourcetype> - <D:supportedlock> - <D:lockentry> - <D:lockscope><D:exclusive/></D:lockscope> - <D:locktype><D:write/></D:locktype> - </D:lockentry> - <D:lockentry> - <D:lockscope><D:shared/></D:lockscope> - <D:locktype><D:write/></D:locktype> - </D:lockentry> - </D:supportedlock> - </D:prop> - <D:status>HTTP/1.1 200 OK</D:status> - </D:propstat> - </D:response> - <D:response> - <D:href>/container/front.html</D:href> - <D:propstat> - <D:prop xmlns:R="http://ns.example.com/boxschema/"> - <R:bigbox><R:BoxType>Box type B</R:BoxType> - </R:bigbox> - <D:creationdate>1997-12-01T18:27:21-08:00</D:creationdate> - <D:displayname>Example HTML resource</D:displayname> - <D:getcontentlength>4525</D:getcontentlength> - <D:getcontenttype>text/html</D:getcontenttype> - <D:getetag>"zzyzx"</D:getetag> - <D:getlastmodified - >Mon, 12 Jan 1998 09:25:56 GMT</D:getlastmodified> - <D:resourcetype/> - <D:supportedlock> - <D:lockentry> - <D:lockscope><D:exclusive/></D:lockscope> - <D:locktype><D:write/></D:locktype> - </D:lockentry> - <D:lockentry> - <D:lockscope><D:shared/></D:lockscope> - <D:locktype><D:write/></D:locktype> - </D:lockentry> - </D:supportedlock> - </D:prop> - <D:status>HTTP/1.1 200 OK</D:status> - </D:propstat> - </D:response> - </D:multistatus>"#; - - let mut rdr = Reader::new(NsReader::from_reader(src.as_bytes())).await.unwrap(); - let got = rdr.find::<Multistatus::<Core, PropValue<Core>>>().await.unwrap(); - - assert_eq!(got, Multistatus { - responses: vec![ - Response { - status_or_propstat: StatusOrPropstat::PropStat( - Href("/container/".into()), - vec![PropStat { - prop: PropValue(vec![ - Property::CreationDate(FixedOffset::west_opt(8 * 3600).unwrap().with_ymd_and_hms(1997, 12, 01, 17, 42, 21).unwrap()), - Property::DisplayName("Example collection".into()), - Property::ResourceType(vec![ResourceType::Collection]), - Property::SupportedLock(vec![ - LockEntry { - lockscope: LockScope::Exclusive, - locktype: LockType::Write, - }, - LockEntry { - lockscope: LockScope::Shared, - locktype: LockType::Write, - }, - ]), - ]), - status: Status(http::status::StatusCode::OK), - error: None, - responsedescription: None, - }], - ), - error: None, - responsedescription: None, - location: None, - - }, - Response { - status_or_propstat: StatusOrPropstat::PropStat( - Href("/container/front.html".into()), - vec![PropStat { - prop: PropValue(vec![ - Property::CreationDate(FixedOffset::west_opt(8 * 3600).unwrap().with_ymd_and_hms(1997, 12, 01, 18, 27, 21).unwrap()), - Property::DisplayName("Example HTML resource".into()), - Property::GetContentLength(4525), - Property::GetContentType("text/html".into()), - Property::GetEtag(r#""zzyzx""#.into()), - Property::GetLastModified(FixedOffset::west_opt(0).unwrap().with_ymd_and_hms(1998, 01, 12, 09, 25, 56).unwrap()), - //Property::ResourceType(vec![]), - Property::SupportedLock(vec![ - LockEntry { - lockscope: LockScope::Exclusive, - locktype: LockType::Write, - }, - LockEntry { - lockscope: LockScope::Shared, - locktype: LockType::Write, - }, - ]), - ]), - status: Status(http::status::StatusCode::OK), - error: None, - responsedescription: None, - }], - ), - error: None, - responsedescription: None, - location: None, - - }, - ], - responsedescription: None, - }); - } - -} |