aboutsummaryrefslogtreecommitdiff
path: root/aero-dav
diff options
context:
space:
mode:
authorQuentin Dufour <quentin@deuxfleurs.fr>2024-03-19 17:36:32 +0100
committerQuentin Dufour <quentin@deuxfleurs.fr>2024-03-19 17:36:32 +0100
commitfb6a379f43ff579dbc224fb52180ba3a6d6cde5c (patch)
tree0b570817fb7be8a30a2161b0782b54c710509f18 /aero-dav
parent5bf3517acfea3694fbe586e69a0e02b94c61eb1b (diff)
downloadaerogramme-fb6a379f43ff579dbc224fb52180ba3a6d6cde5c.tar.gz
aerogramme-fb6a379f43ff579dbc224fb52180ba3a6d6cde5c.zip
Working thunderbird autodetect
Diffstat (limited to 'aero-dav')
-rw-r--r--aero-dav/src/acldecoder.rs68
-rw-r--r--aero-dav/src/aclencoder.rs71
-rw-r--r--aero-dav/src/acltypes.rs38
-rw-r--r--aero-dav/src/caltypes.rs1
-rw-r--r--aero-dav/src/lib.rs8
-rw-r--r--aero-dav/src/realization.rs94
-rw-r--r--aero-dav/src/xml.rs2
7 files changed, 275 insertions, 7 deletions
diff --git a/aero-dav/src/acldecoder.rs b/aero-dav/src/acldecoder.rs
new file mode 100644
index 0000000..67dfb0b
--- /dev/null
+++ b/aero-dav/src/acldecoder.rs
@@ -0,0 +1,68 @@
+use super::acltypes::*;
+use super::types as dav;
+use super::xml::{QRead, Reader, IRead, DAV_URN};
+use super::error::ParsingError;
+
+impl QRead<Property> for Property {
+ async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
+ if xml.maybe_open_start(DAV_URN, "owner").await?.is_some() {
+ let href = xml.find().await?;
+ xml.close().await?;
+ return Ok(Self::Owner(href))
+ }
+ if xml.maybe_open_start(DAV_URN, "current-user-principal").await?.is_some() {
+ let user = xml.find().await?;
+ xml.close().await?;
+ return Ok(Self::CurrentUserPrincipal(user))
+ }
+ if xml.maybe_open_start(DAV_URN, "current-user-privilege-set").await?.is_some() {
+ xml.close().await?;
+ return Ok(Self::CurrentUserPrivilegeSet(vec![]))
+ }
+
+ Err(ParsingError::Recoverable)
+ }
+}
+
+impl QRead<PropertyRequest> for PropertyRequest {
+ async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
+ if xml.maybe_open(DAV_URN, "owner").await?.is_some() {
+ xml.close().await?;
+ return Ok(Self::Owner)
+ }
+
+ if xml.maybe_open(DAV_URN, "current-user-principal").await?.is_some() {
+ xml.close().await?;
+ return Ok(Self::CurrentUserPrincipal)
+ }
+
+ if xml.maybe_open(DAV_URN, "current-user-privilege-set").await?.is_some() {
+ xml.close().await?;
+ return Ok(Self::CurrentUserPrivilegeSet)
+ }
+
+ Err(ParsingError::Recoverable)
+ }
+}
+
+impl QRead<ResourceType> for ResourceType {
+ async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
+ if xml.maybe_open(DAV_URN, "principal").await?.is_some() {
+ xml.close().await?;
+ return Ok(Self::Principal)
+ }
+ Err(ParsingError::Recoverable)
+ }
+}
+
+// -----
+impl QRead<User> for User {
+ async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
+ if xml.maybe_open(DAV_URN, "unauthenticated").await?.is_some() {
+ xml.close().await?;
+ return Ok(Self::Unauthenticated)
+ }
+
+ dav::Href::qread(xml).await.map(Self::Authenticated)
+ }
+}
diff --git a/aero-dav/src/aclencoder.rs b/aero-dav/src/aclencoder.rs
new file mode 100644
index 0000000..2fa4707
--- /dev/null
+++ b/aero-dav/src/aclencoder.rs
@@ -0,0 +1,71 @@
+use quick_xml::Error as QError;
+use quick_xml::events::Event;
+
+use super::acltypes::*;
+use super::xml::{QWrite, Writer, IWrite};
+use super::error::ParsingError;
+
+impl QWrite for Property {
+ async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
+ match self {
+ Self::Owner(href) => {
+ let start = xml.create_dav_element("owner");
+ let end = start.to_end();
+ xml.q.write_event_async(Event::Start(start.clone())).await?;
+ href.qwrite(xml).await?;
+ xml.q.write_event_async(Event::End(end)).await
+ },
+ Self::CurrentUserPrincipal(user) => {
+ let start = xml.create_dav_element("current-user-principal");
+ let end = start.to_end();
+ xml.q.write_event_async(Event::Start(start.clone())).await?;
+ user.qwrite(xml).await?;
+ xml.q.write_event_async(Event::End(end)).await
+ },
+ Self::CurrentUserPrivilegeSet(_) => {
+ let empty_tag = xml.create_dav_element("current-user-privilege-set");
+ xml.q.write_event_async(Event::Empty(empty_tag)).await
+ },
+ }
+ }
+}
+
+impl QWrite for PropertyRequest {
+ async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
+ let mut atom = async |c| {
+ let empty_tag = xml.create_dav_element(c);
+ xml.q.write_event_async(Event::Empty(empty_tag)).await
+ };
+
+ match self {
+ Self::Owner => atom("owner").await,
+ Self::CurrentUserPrincipal => atom("current-user-principal").await,
+ Self::CurrentUserPrivilegeSet => atom("current-user-privilege-set").await,
+ }
+ }
+}
+
+impl QWrite for ResourceType {
+ async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
+ match self {
+ Self::Principal => {
+ let empty_tag = xml.create_dav_element("principal");
+ xml.q.write_event_async(Event::Empty(empty_tag)).await
+ }
+ }
+ }
+}
+
+// -----
+
+impl QWrite for User {
+ async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
+ match self {
+ Self::Unauthenticated => {
+ let tag = xml.create_dav_element("unauthenticated");
+ xml.q.write_event_async(Event::Empty(tag)).await
+ },
+ Self::Authenticated(href) => href.qwrite(xml).await,
+ }
+ }
+}
diff --git a/aero-dav/src/acltypes.rs b/aero-dav/src/acltypes.rs
index f356813..d5be413 100644
--- a/aero-dav/src/acltypes.rs
+++ b/aero-dav/src/acltypes.rs
@@ -1,4 +1,40 @@
-//@FIXME required for a full DAV implementation
+use super::types as dav;
+
+//RFC covered: RFC3744 (ACL core) + RFC5397 (ACL Current Principal Extension)
+
+
+//@FIXME required for a full CalDAV implementation
// See section 6. of the CalDAV RFC
// It seems mainly required for free-busy that I will not implement now.
// It can also be used for discovering main calendar, not sure it is used.
+// Note: it is used by Thunderbird
+
+
+#[derive(Debug, PartialEq, Clone)]
+pub enum PropertyRequest {
+ Owner,
+ CurrentUserPrincipal,
+ CurrentUserPrivilegeSet,
+}
+
+#[derive(Debug, PartialEq, Clone)]
+pub enum Property {
+ Owner(dav::Href),
+ CurrentUserPrincipal(User),
+ CurrentUserPrivilegeSet(Vec<Privilege>),
+}
+
+#[derive(Debug, PartialEq, Clone)]
+pub enum ResourceType {
+ Principal,
+}
+
+/// Not implemented, it's a placeholder
+#[derive(Debug, PartialEq, Clone)]
+pub struct Privilege(());
+
+#[derive(Debug, PartialEq, Clone)]
+pub enum User {
+ Unauthenticated,
+ Authenticated(dav::Href),
+}
diff --git a/aero-dav/src/caltypes.rs b/aero-dav/src/caltypes.rs
index aa056d4..602498c 100644
--- a/aero-dav/src/caltypes.rs
+++ b/aero-dav/src/caltypes.rs
@@ -2,7 +2,6 @@
use chrono::{DateTime,Utc};
use super::types as dav;
-use super::xml;
pub const ICAL_DATETIME_FMT: &str = "%Y%m%dT%H%M%SZ";
diff --git a/aero-dav/src/lib.rs b/aero-dav/src/lib.rs
index 0ca8243..009951a 100644
--- a/aero-dav/src/lib.rs
+++ b/aero-dav/src/lib.rs
@@ -16,8 +16,12 @@ pub mod caltypes;
pub mod calencoder;
pub mod caldecoder;
-// wip
-mod acltypes;
+// acl (wip)
+pub mod acltypes;
+pub mod aclencoder;
+pub mod acldecoder;
+
+// versioning (wip)
mod versioningtypes;
// final type
diff --git a/aero-dav/src/realization.rs b/aero-dav/src/realization.rs
index 7bec729..bfed4d7 100644
--- a/aero-dav/src/realization.rs
+++ b/aero-dav/src/realization.rs
@@ -1,5 +1,6 @@
use super::types as dav;
use super::caltypes as cal;
+use super::acltypes as acl;
use super::xml;
use super::error;
@@ -11,8 +12,8 @@ impl xml::QRead<Disabled> for Disabled {
}
}
impl xml::QWrite for Disabled {
- fn qwrite(&self, _xml: &mut xml::Writer<impl xml::IWrite>) -> impl futures::Future<Output = Result<(), quick_xml::Error>> + Send {
- async { unreachable!(); }
+ async fn qwrite(&self, _xml: &mut xml::Writer<impl xml::IWrite>) -> Result<(), quick_xml::Error> {
+ unreachable!()
}
}
@@ -40,3 +41,92 @@ impl dav::Extension for Calendar
type ResourceType = cal::ResourceType;
}
+// ACL
+#[derive(Debug, PartialEq, Clone)]
+pub struct Acl {}
+impl dav::Extension for Acl
+{
+ type Error = Disabled;
+ type Property = acl::Property;
+ type PropertyRequest = acl::PropertyRequest;
+ type ResourceType = acl::ResourceType;
+}
+
+// All merged
+#[derive(Debug, PartialEq, Clone)]
+pub struct All {}
+impl dav::Extension for All {
+ type Error = cal::Violation;
+ type Property = Property;
+ type PropertyRequest = PropertyRequest;
+ type ResourceType = ResourceType;
+}
+
+#[derive(Debug, PartialEq, Clone)]
+pub enum Property {
+ Cal(cal::Property),
+ Acl(acl::Property),
+}
+impl xml::QRead<Property> for Property {
+ async fn qread(xml: &mut xml::Reader<impl xml::IRead>) -> Result<Self, error::ParsingError> {
+ match cal::Property::qread(xml).await {
+ Err(error::ParsingError::Recoverable) => (),
+ otherwise => return otherwise.map(Property::Cal),
+ }
+ acl::Property::qread(xml).await.map(Property::Acl)
+ }
+}
+impl xml::QWrite for Property {
+ async fn qwrite(&self, xml: &mut xml::Writer<impl xml::IWrite>) -> Result<(), quick_xml::Error> {
+ match self {
+ Self::Cal(c) => c.qwrite(xml).await,
+ Self::Acl(a) => a.qwrite(xml).await,
+ }
+ }
+}
+
+#[derive(Debug, PartialEq, Clone)]
+pub enum PropertyRequest {
+ Cal(cal::PropertyRequest),
+ Acl(acl::PropertyRequest),
+}
+impl xml::QRead<PropertyRequest> for PropertyRequest {
+ async fn qread(xml: &mut xml::Reader<impl xml::IRead>) -> Result<Self, error::ParsingError> {
+ match cal::PropertyRequest::qread(xml).await {
+ Err(error::ParsingError::Recoverable) => (),
+ otherwise => return otherwise.map(PropertyRequest::Cal),
+ }
+ acl::PropertyRequest::qread(xml).await.map(PropertyRequest::Acl)
+ }
+}
+impl xml::QWrite for PropertyRequest {
+ async fn qwrite(&self, xml: &mut xml::Writer<impl xml::IWrite>) -> Result<(), quick_xml::Error> {
+ match self {
+ Self::Cal(c) => c.qwrite(xml).await,
+ Self::Acl(a) => a.qwrite(xml).await,
+ }
+ }
+}
+
+#[derive(Debug, PartialEq, Clone)]
+pub enum ResourceType {
+ Cal(cal::ResourceType),
+ Acl(acl::ResourceType),
+}
+impl xml::QRead<ResourceType> for ResourceType {
+ async fn qread(xml: &mut xml::Reader<impl xml::IRead>) -> Result<Self, error::ParsingError> {
+ match cal::ResourceType::qread(xml).await {
+ Err(error::ParsingError::Recoverable) => (),
+ otherwise => return otherwise.map(ResourceType::Cal),
+ }
+ acl::ResourceType::qread(xml).await.map(ResourceType::Acl)
+ }
+}
+impl xml::QWrite for ResourceType {
+ async fn qwrite(&self, xml: &mut xml::Writer<impl xml::IWrite>) -> Result<(), quick_xml::Error> {
+ match self {
+ Self::Cal(c) => c.qwrite(xml).await,
+ Self::Acl(a) => a.qwrite(xml).await,
+ }
+ }
+}
diff --git a/aero-dav/src/xml.rs b/aero-dav/src/xml.rs
index 26f54cc..020ee6c 100644
--- a/aero-dav/src/xml.rs
+++ b/aero-dav/src/xml.rs
@@ -264,7 +264,7 @@ impl<T: IRead> Reader<T> {
_ => return Err(ParsingError::Recoverable),
};
- //println!("open tag {:?}", evt);
+ //println!("open start tag {:?}", evt);
self.parents.push(evt.clone());
Ok(evt)
}