From f372a95b017587bd964ef80fdfdef7c2128bca15 Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Sun, 17 Mar 2024 10:31:05 +0100 Subject: [PATCH] basic propfind --- aero-dav/src/caltypes.rs | 72 ++++++++++++++-------------- aero-dav/src/realization.rs | 6 +-- aero-dav/src/types.rs | 66 +++++++++++++------------- aero-dav/src/xml.rs | 2 +- aero-proto/src/dav.rs | 95 +++++++++++++++++++++++++++++++------ 5 files changed, 153 insertions(+), 88 deletions(-) diff --git a/aero-dav/src/caltypes.rs b/aero-dav/src/caltypes.rs index 628ec4b..cb0a98c 100644 --- a/aero-dav/src/caltypes.rs +++ b/aero-dav/src/caltypes.rs @@ -108,13 +108,13 @@ pub struct CalendarMultiget { pub struct FreeBusyQuery(pub TimeRange); // ----- Hooks ----- -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum ResourceType { Calendar, } /// Check the matching Property object for documentation -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum PropertyRequest { CalendarDescription, CalendarTimezone, @@ -129,7 +129,7 @@ pub enum PropertyRequest { CalendarData(CalendarDataRequest), } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum Property { /// Name: calendar-description /// @@ -609,7 +609,7 @@ pub enum Property { CalendarData(CalendarDataPayload), } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum Violation { /// (DAV:resource-must-be-null): A resource MUST NOT exist at the /// Request-URI; @@ -780,7 +780,7 @@ pub enum Violation { /// If the client chooses a collation not supported by the server, the /// server MUST respond with a CALDAV:supported-collation precondition /// error response. -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct SupportedCollation(pub Collation); /// @@ -789,7 +789,7 @@ pub struct SupportedCollation(pub Collation); /// when nested in the DAV:prop XML element in a calendaring /// REPORT response to specify the content of a returned /// calendar object resource. -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct CalendarDataPayload { pub mime: Option, pub payload: String, @@ -802,7 +802,7 @@ pub struct CalendarDataPayload { /// when nested in the DAV:prop XML element in a calendaring /// REPORT request to specify which parts of calendar object /// resources should be returned in the response; -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct CalendarDataRequest { pub mime: Option, pub comp: Option, @@ -817,7 +817,7 @@ pub struct CalendarDataRequest { /// when nested in the CALDAV:supported-calendar-data property /// to specify a supported media type for calendar object /// resources; -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct CalendarDataEmpty(pub Option); /// ); /// version value: a version string /// attributes can be used on all three variants of the /// CALDAV:calendar-data XML element. -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct CalendarDataSupport { pub content_type: String, pub version: String, @@ -852,7 +852,7 @@ pub struct CalendarDataSupport { /// However, the CALDAV:prop and CALDAV:allprop elements are defined /// in the "urn:ietf:params:xml:ns:caldav" namespace instead of the /// "DAV:" namespace. -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct Comp { pub name: Component, pub prop_kind: Option, @@ -872,7 +872,7 @@ pub struct Comp { /// /// /// -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct CompSupport(pub Component); /// Name: allcomp @@ -888,7 +888,7 @@ pub struct CompSupport(pub Component); /// Definition: /// /// -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum CompKind { AllComp, Comp(Vec), @@ -912,7 +912,7 @@ pub enum CompKind { /// allprop element defined in [RFC2518]. However, the CALDAV:allprop /// element is defined in the "urn:ietf:params:xml:ns:caldav" /// namespace instead of the "DAV:" namespace. -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum PropKind { AllProp, Prop(Vec), @@ -942,13 +942,13 @@ pub enum PropKind { /// element defined in [RFC2518]. However, the CALDAV:prop element is /// defined in the "urn:ietf:params:xml:ns:caldav" namespace instead /// of the "DAV:" namespace. -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct CalProp { pub name: ComponentProperty, pub novalue: Option, } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum RecurrenceModifier { Expand(Expand), LimitRecurrenceSet(LimitRecurrenceSet), @@ -994,7 +994,7 @@ pub enum RecurrenceModifier { /// end CDATA #REQUIRED> /// start value: an iCalendar "date with UTC time" /// end value: an iCalendar "date with UTC time" -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct Expand(pub DateTime, pub DateTime); /// CALDAV:limit-recurrence-set XML Element @@ -1042,7 +1042,7 @@ pub struct Expand(pub DateTime, pub DateTime); /// end CDATA #REQUIRED> /// start value: an iCalendar "date with UTC time" /// end value: an iCalendar "date with UTC time" -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct LimitRecurrenceSet(pub DateTime, pub DateTime); /// Name: limit-freebusy-set @@ -1073,11 +1073,11 @@ pub struct LimitRecurrenceSet(pub DateTime, pub DateTime); /// end CDATA #REQUIRED> /// start value: an iCalendar "date with UTC time" /// end value: an iCalendar "date with UTC time" -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct LimitFreebusySet(pub DateTime, pub DateTime); /// Used by CalendarQuery & CalendarMultiget -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum CalendarSelector { AllProp, PropName, @@ -1135,20 +1135,20 @@ pub enum CalendarSelector { /// name value: a calendar object or calendar component /// type (e.g., VEVENT) /// ``` -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct CompFilter { pub name: Component, // Option 1 = None, Option 2, 3, 4 = Some pub additional_rules: Option, } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum CompFilterRules { // Option 2 IsNotDefined, // Options 3 & 4 Matches(CompFilterMatch), } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct CompFilterMatch { pub time_range: Option, pub prop_filter: Vec, @@ -1201,26 +1201,26 @@ pub struct CompFilterMatch { /// /// name value: a calendar property name (e.g., ATTENDEE) /// ``` -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct PropFilter { pub name: ComponentProperty, // None = Option 1, Some() = Option 2, 3 & 4 pub additional_rules: Option, } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum PropFilterRules { // Option 2 IsNotDefined, // Options 3 & 4 Match(PropFilterMatch), } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct PropFilterMatch { pub time_range: Option, pub time_or_text: Option, pub param_filter: Vec, } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum TimeOrText { Time(TimeRange), Text(TextMatch), @@ -1254,7 +1254,7 @@ pub enum TimeOrText { /// PCDATA value: string /// -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct TextMatch { pub collation: Option, pub negate_condition: Option, @@ -1292,12 +1292,12 @@ pub struct TextMatch { /// /// name value: a property parameter name (e.g., PARTSTAT) /// ``` -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct ParamFilter { pub name: PropertyParameter, pub additional_rules: Option, } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum ParamFilterMatch { IsNotDefined, Match(TextMatch), @@ -1353,7 +1353,7 @@ pub enum ParamFilterMatch { /// /// /// PCDATA value: an iCalendar object with exactly one VTIMEZONE -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct TimeZone(pub String); /// Name: filter @@ -1369,7 +1369,7 @@ pub struct TimeZone(pub String); /// /// Definition: /// -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct Filter(pub CompFilter); /// Name: time-range @@ -1381,7 +1381,7 @@ pub struct Filter(pub CompFilter); /// end CDATA #IMPLIED> /// start value: an iCalendar "date with UTC time" /// end value: an iCalendar "date with UTC time" -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum TimeRange { OnlyStart(DateTime), OnlyEnd(DateTime), @@ -1391,7 +1391,7 @@ pub enum TimeRange { // ----------------------- ENUM ATTRIBUTES --------------------- /// Known components -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum Component { VCalendar, VJournal, @@ -1432,11 +1432,11 @@ impl Component { /// name="VERSION", name="SUMMARY", etc. /// Can be set on different objects: VCalendar, VEvent, etc. /// Might be replaced by an enum later -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct ComponentProperty(pub String); /// like PARSTAT -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct PropertyParameter(pub String); impl PropertyParameter { pub fn as_str<'a>(&'a self) -> &'a str { @@ -1444,7 +1444,7 @@ impl PropertyParameter { } } -#[derive(Default,Debug,PartialEq)] +#[derive(Default,Debug,PartialEq,Clone)] pub enum Collation { #[default] AsciiCaseMap, diff --git a/aero-dav/src/realization.rs b/aero-dav/src/realization.rs index a7bbb16..8c47fad 100644 --- a/aero-dav/src/realization.rs +++ b/aero-dav/src/realization.rs @@ -3,7 +3,7 @@ use super::caltypes as cal; use super::xml; use super::error; -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct Disabled(()); impl xml::QRead for Disabled { async fn qread(_xml: &mut xml::Reader) -> Result { @@ -20,7 +20,7 @@ impl xml::QWrite for Disabled { /// /// Any extension is kooh is disabled through an object we can't build /// due to a private inner element. -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct Core {} impl dav::Extension for Core { type Error = Disabled; @@ -30,7 +30,7 @@ impl dav::Extension for Core { } // WebDAV with the base Calendar implementation (RFC4791) -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct Calendar {} impl dav::Extension for Calendar { diff --git a/aero-dav/src/types.rs b/aero-dav/src/types.rs index 2489c0a..79e98fd 100644 --- a/aero-dav/src/types.rs +++ b/aero-dav/src/types.rs @@ -6,7 +6,7 @@ use super::xml; /// It's how we implement a DAV extension /// (That's the dark magic part...) -pub trait Extension: std::fmt::Debug + PartialEq { +pub trait Extension: std::fmt::Debug + PartialEq + Clone { type Error: xml::Node; type Property: xml::Node; type PropertyRequest: xml::Node; @@ -20,7 +20,7 @@ pub trait Extension: std::fmt::Debug + PartialEq { /// Purpose: Describes a lock on a resource. /// -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct ActiveLock { pub lockscope: LockScope, pub locktype: LockType, @@ -54,7 +54,7 @@ pub struct Collection{} /// Value: "0" | "1" | "infinity" /// /// -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum Depth { Zero, One, @@ -77,9 +77,9 @@ pub enum Depth { /// postcondition code. Unrecognized elements MUST be ignored. /// /// -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct Error(pub Vec>); -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum Violation { /// Name: lock-token-matches-request-uri /// @@ -190,7 +190,7 @@ pub struct Exclusive {} /// Value: Simple-ref /// /// -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct Href(pub String); @@ -206,7 +206,7 @@ pub struct Href(pub String); /// standards. This element MUST NOT contain text or mixed content. /// /// -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct Include(pub Vec>); /// 14.9. location XML Element @@ -223,7 +223,7 @@ pub struct Include(pub Vec>); /// that would be used in a Location header. /// /// -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct Location(pub Href); /// 14.10. lockentry XML Element @@ -234,7 +234,7 @@ pub struct Location(pub Href); /// resource. /// /// -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct LockEntry { pub lockscope: LockScope, pub locktype: LockType, @@ -248,7 +248,7 @@ pub struct LockEntry { /// specify the type of lock the client wishes to have created. /// /// -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct LockInfo { pub lockscope: LockScope, pub locktype: LockType, @@ -267,7 +267,7 @@ pub struct LockInfo { /// values and the response to LOCK requests. /// /// -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct LockRoot(pub Href); /// 14.13. lockscope XML Element @@ -277,7 +277,7 @@ pub struct LockRoot(pub Href); /// Purpose: Specifies whether a lock is an exclusive lock, or a shared /// lock. /// -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum LockScope { Exclusive, Shared @@ -293,7 +293,7 @@ pub enum LockScope { /// refers to the lock. /// /// -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct LockToken(pub Href); /// 14.15. locktype XML Element @@ -304,7 +304,7 @@ pub struct LockToken(pub Href); /// specification only defines one lock type, the write lock. /// /// -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum LockType { /// 14.30. write XML Element /// @@ -330,7 +330,7 @@ pub enum LockType { /// response descriptions contained within the responses. /// /// -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct Multistatus> { pub responses: Vec>, pub responsedescription: Option, @@ -360,7 +360,7 @@ pub struct Multistatus> { /// /// //@FIXME might need support for an extension -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum Owner { Txt(String), Href(Href), @@ -381,10 +381,10 @@ pub enum Owner { /// text or mixed content. /// /// -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct PropName(pub Vec>); -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct PropValue(pub Vec>); /// 14.19. propertyupdate XML Element @@ -397,10 +397,10 @@ pub struct PropValue(pub Vec>); /// required to modify the properties on the resource. /// /// -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct PropertyUpdate(pub Vec>); -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum PropertyUpdateItem { Remove(Remove), Set(Set), @@ -440,7 +440,7 @@ pub enum PropertyUpdateItem { /// values. /// /// -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum PropFind { PropName, AllProp(Option>), @@ -462,7 +462,7 @@ pub enum PropFind { /// the properties named in 'prop'. /// /// -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct PropStat> { pub prop: N, pub status: Status, @@ -483,7 +483,7 @@ pub struct PropStat> { /// the names of properties to be removed are required. /// /// -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct Remove(pub PropName); /// 14.24. response XML Element @@ -511,7 +511,7 @@ pub struct Remove(pub PropName); /// /// --- rewritten as --- /// -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum StatusOrPropstat> { // One status, multiple hrefs... Status(Vec, Status), @@ -519,7 +519,7 @@ pub enum StatusOrPropstat> { PropStat(Href, Vec>), } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct Response> { pub status_or_propstat: StatusOrPropstat, pub error: Option>, @@ -538,7 +538,7 @@ pub struct Response> { /// user. /// /// -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct ResponseDescription(pub String); /// 14.26. set XML Element @@ -557,7 +557,7 @@ pub struct ResponseDescription(pub String); /// property, and MUST be subsequently retrievable using PROPFIND. /// /// -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct Set(pub PropValue); /// 14.27. shared XML Element @@ -568,7 +568,7 @@ pub struct Set(pub PropValue); /// /// /// -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct Shared {} @@ -582,7 +582,7 @@ pub struct Shared {} /// /// //@FIXME: Better typing is possible with an enum for example -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct Status(pub http::status::StatusCode); /// 14.29. timeout XML Element @@ -610,7 +610,7 @@ pub struct Status(pub http::status::StatusCode); /// elapse between granting of the lock at the server, and the automatic /// removal of the lock. The timeout value for TimeType "Second" MUST /// NOT be greater than 2^32-1. -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum Timeout { Seconds(u32), Infinite, @@ -644,7 +644,7 @@ pub enum Timeout { /// the header value could include LWS as defined in [RFC2616], Section /// 4.2. Server implementors SHOULD strip LWS from these values before /// using as WebDAV property values. -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum PropertyRequest { CreationDate, DisplayName, @@ -659,7 +659,7 @@ pub enum PropertyRequest { Extension(E::PropertyRequest), } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum Property { /// 15.1. creationdate Property /// @@ -942,7 +942,7 @@ pub enum Property { Extension(E::Property), } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum ResourceType { Collection, Extension(E::ResourceType), diff --git a/aero-dav/src/xml.rs b/aero-dav/src/xml.rs index e078c6f..827e9d0 100644 --- a/aero-dav/src/xml.rs +++ b/aero-dav/src/xml.rs @@ -24,7 +24,7 @@ pub trait QRead { } // The representation of an XML node in Rust -pub trait Node = QRead + QWrite + std::fmt::Debug + PartialEq + Sync; +pub trait Node = QRead + QWrite + std::fmt::Debug + PartialEq + Clone + Sync; // --------------- diff --git a/aero-proto/src/dav.rs b/aero-proto/src/dav.rs index 3981b61..0bbb7f7 100644 --- a/aero-proto/src/dav.rs +++ b/aero-proto/src/dav.rs @@ -22,9 +22,9 @@ use rustls_pemfile::{certs, private_key}; use aero_user::config::{DavConfig, DavUnsecureConfig}; use aero_user::login::ArcLoginProvider; use aero_collections::user::User; -use aero_dav::types::{PropFind, Multistatus, PropValue, ResponseDescription}; -use aero_dav::realization::{Core, Calendar}; -use aero_dav::xml as dav; +use aero_dav::types as dav; +use aero_dav::realization::Calendar; +use aero_dav::xml as dxml; pub struct Server { bind_addr: SocketAddr, @@ -196,7 +196,13 @@ async fn router(user: std::sync::Arc, req: Request) -> Result = path.split("/").filter(|s| *s != "").collect(); let method = req.method().as_str().to_uppercase(); + //@FIXME check depth, handle it + match (method.as_str(), path_segments.as_slice()) { + ("OPTIONS", _) => return Ok(Response::builder() + .status(200) + .header("DAV", "1") + .body(text_body(""))?), ("PROPFIND", []) => propfind_root(user, req).await, (_, [ username, ..]) if *username != user.username => return Ok(Response::builder() .status(403) @@ -216,14 +222,73 @@ async fn router(user: std::sync::Arc, req: Request) -> Result async fn propfind_root(user: std::sync::Arc, req: Request) -> Result>> { - tracing::info!("root"); + let supported_propname = vec![ + dav::PropertyRequest::DisplayName, + dav::PropertyRequest::ResourceType, + ]; - let r = deserialize::>(req).await?; - println!("r: {:?}", r); - serialize(Multistatus::> { - responses: vec![], - responsedescription: Some(ResponseDescription("hello world".to_string())), - }) + // A client may choose not to submit a request body. An empty PROPFIND + // request body MUST be treated as if it were an 'allprop' request. + // @FIXME here we handle any invalid data as an allprop, an empty request is thus correctly + // handled, but corrupted requests are also silently handled as allprop. + let propfind = deserialize::>(req).await.unwrap_or_else(|_| dav::PropFind::::AllProp(None)); + tracing::debug!(recv=?propfind, "inferred propfind request"); + + if matches!(propfind, dav::PropFind::PropName) { + return serialize(dav::Multistatus::> { + responses: vec![dav::Response { + status_or_propstat: dav::StatusOrPropstat::PropStat( + dav::Href(format!("./{}/", user.username)), + vec![dav::PropStat { + prop: dav::PropName(supported_propname), + status: dav::Status(hyper::StatusCode::OK), + error: None, + responsedescription: None, + }], + ), + error: None, + location: None, + responsedescription: Some(dav::ResponseDescription("user home directory".into())), + }], + responsedescription: Some(dav::ResponseDescription("propname response".to_string())), + }); + } + + let propname = match propfind { + dav::PropFind::PropName => unreachable!(), + dav::PropFind::AllProp(None) => supported_propname.clone(), + dav::PropFind::AllProp(Some(dav::Include(mut include))) => { + include.extend_from_slice(supported_propname.as_slice()); + include + }, + dav::PropFind::Prop(dav::PropName(inner)) => inner, + }; + + let values = propname.iter().filter_map(|n| match n { + dav::PropertyRequest::DisplayName => Some(dav::Property::DisplayName(format!("{} home", user.username))), + dav::PropertyRequest::ResourceType => Some(dav::Property::ResourceType(vec![dav::ResourceType::Collection])), + _ => None, + }).collect(); + + let multistatus = dav::Multistatus::> { + responses: vec![ dav::Response { + status_or_propstat: dav::StatusOrPropstat::PropStat( + dav::Href(format!("./{}/", user.username)), + vec![dav::PropStat { + prop: dav::PropValue(values), + status: dav::Status(hyper::StatusCode::OK), + error: None, + responsedescription: None, + }], + ), + error: None, + location: None, + responsedescription: Some(dav::ResponseDescription("Root node".into())), + } ], + responsedescription: Some(dav::ResponseDescription("hello world".to_string())), + }; + + serialize(multistatus) } async fn propfind_home(user: std::sync::Arc, req: &Request) -> Result>> { @@ -263,7 +328,7 @@ async fn collections(_user: std::sync::Arc, _req: Request BoxBody { BoxBody::new(Full::new(Bytes::from(txt)).map_err(|e| match e {})) } -fn serialize(elem: T) -> Result>> { +fn serialize(elem: T) -> Result>> { let (tx, rx) = tokio::sync::mpsc::channel::(1); // Build the writer @@ -286,7 +351,7 @@ fn serialize(elem: T) -> Result tracing::debug!("fully serialized object"), Err(e) => tracing::error!(err=?e, "failed to serialize object"), @@ -308,14 +373,14 @@ fn serialize(elem: T) -> Result>(req: Request) -> Result { +async fn deserialize>(req: Request) -> Result { let stream_of_frames = BodyStream::new(req.into_body()); let stream_of_bytes = stream_of_frames .try_filter_map(|frame| async move { Ok(frame.into_data().ok()) }) .map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err)); let async_read = tokio_util::io::StreamReader::new(stream_of_bytes); let async_read = std::pin::pin!(async_read); - let mut rdr = dav::Reader::new(quick_xml::reader::NsReader::from_reader(async_read)).await?; + let mut rdr = dxml::Reader::new(quick_xml::reader::NsReader::from_reader(async_read)).await?; let parsed = rdr.find::().await?; Ok(parsed) }