Files
Stalwart/crates/dav-proto/src/schema/request.rs
2026-02-26 19:39:06 +01:00

296 lines
8.2 KiB
Rust

/*
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <hello@stalw.art>
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
*/
use super::{
Collation, MatchType,
property::{DavProperty, DavValue, LockScope, LockType},
response::Ace,
};
use crate::{Condition, Depth};
use calcard::{
icalendar::{ICalendarComponentType, ICalendarParameterName, ICalendarProperty},
vcard::{VCardParameterName, VCardProperty},
};
use types::{
TimeRange,
dead_property::{ArchivedDeadProperty, ArchivedDeadPropertyTag, DeadElementTag, DeadProperty},
};
#[derive(Debug, Clone, PartialEq, Eq, Default)]
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(test, serde(tag = "type", content = "data"))]
pub enum PropFind {
#[default]
PropName,
AllProp(Vec<DavProperty>),
Prop(Vec<DavProperty>),
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
pub struct PropertyUpdate {
pub set: Vec<DavPropertyValue>,
pub remove: Vec<DavProperty>,
pub set_first: bool,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
pub struct DavPropertyValue {
pub property: DavProperty,
pub value: DavValue,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
pub struct MkCol {
pub is_mkcalendar: bool,
pub props: Vec<DavPropertyValue>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
pub struct LockInfo {
pub lock_scope: LockScope,
pub lock_type: LockType,
pub owner: Option<DeadProperty>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(test, serde(tag = "type"))]
pub enum Report {
AddressbookQuery(AddressbookQuery),
AddressbookMultiGet(MultiGet),
CalendarQuery(CalendarQuery),
CalendarMultiGet(MultiGet),
FreeBusyQuery(FreeBusyQuery),
SyncCollection(SyncCollection),
ExpandProperty(ExpandProperty),
AclPrincipalPropSet(AclPrincipalPropSet),
PrincipalMatch(PrincipalMatch),
PrincipalPropertySearch(PrincipalPropertySearch),
PrincipalSearchPropertySet,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
pub struct ExpandProperty {
pub properties: Vec<ExpandPropertyItem>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
pub struct ExpandPropertyItem {
pub property: DavProperty,
pub depth: u32,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
pub struct AddressbookQuery {
pub properties: PropFind,
pub filters: Vec<Filter<(), VCardPropertyWithGroup, VCardParameterName>>,
pub limit: Option<u32>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
pub struct VCardPropertyWithGroup {
pub name: VCardProperty,
pub group: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
pub struct CalendarQuery {
pub properties: PropFind,
pub filters:
Vec<Filter<Vec<ICalendarComponentType>, ICalendarProperty, ICalendarParameterName>>,
pub timezone: Timezone,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(test, serde(tag = "type"))]
pub enum Timezone {
Name(String),
Id(String),
None,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
pub struct FreeBusyQuery {
pub range: Option<TimeRange>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
pub struct MultiGet {
pub properties: PropFind,
pub hrefs: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
pub struct SyncCollection {
pub sync_token: Option<String>,
pub properties: PropFind,
pub depth: Depth,
pub limit: Option<u32>,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(test, serde(tag = "type"))]
pub enum Filter<A, B, C> {
AnyOf,
AllOf,
Component {
comp: A,
op: FilterOp,
},
Property {
comp: A,
prop: B,
op: FilterOp,
},
Parameter {
comp: A,
prop: B,
param: C,
op: FilterOp,
},
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(test, serde(tag = "type", content = "data"))]
pub enum FilterOp {
Exists,
Undefined,
TimeRange(TimeRange),
TextMatch(TextMatch),
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(test, serde(tag = "type"))]
pub struct TextMatch {
pub match_type: MatchType,
pub value: String,
pub collation: Collation,
pub negate: bool,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
pub struct Acl {
pub aces: Vec<Ace>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
pub struct AclPrincipalPropSet {
pub properties: Vec<DavProperty>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
pub struct PrincipalMatch {
pub principal_properties: PrincipalMatchProperties,
pub properties: Vec<DavProperty>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
pub enum PrincipalMatchProperties {
Properties(Vec<DavProperty>),
Self_,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
pub struct PrincipalPropertySearch {
pub property_search: Vec<PropertySearch>,
pub properties: Vec<DavProperty>,
pub apply_to_principal_collection_set: bool,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
pub struct PropertySearch {
pub property: DavProperty,
pub match_: String,
}
impl PropertyUpdate {
pub fn has_changes(&self) -> bool {
!self.set.is_empty() || !self.remove.is_empty()
}
}
impl FreeBusyQuery {
pub fn new(start: i64, end: i64) -> Self {
FreeBusyQuery {
range: Some(TimeRange { start, end }),
}
}
}
pub trait DavDeadProperty {
fn to_dav_values(&self, output: &mut Vec<DavPropertyValue>);
}
impl DavDeadProperty for ArchivedDeadProperty {
fn to_dav_values(&self, output: &mut Vec<DavPropertyValue>) {
let mut depth: u32 = 0;
let mut tags = Vec::new();
let mut tag_start = None;
for tag in self.0.iter() {
match tag {
ArchivedDeadPropertyTag::ElementStart(start) => {
if depth == 0 {
tag_start = Some(DeadElementTag::from(start));
} else {
tags.push(tag.into());
}
depth += 1;
}
ArchivedDeadPropertyTag::ElementEnd => {
depth = depth.saturating_sub(1);
if depth > 0 {
tags.push(tag.into());
} else if let Some(tag_start) = tag_start.take() {
output.push(DavPropertyValue::new(
DavProperty::DeadProperty(tag_start),
DavValue::DeadProperty(DeadProperty(std::mem::take(&mut tags))),
));
}
}
ArchivedDeadPropertyTag::Text(_) => {
if tag_start.is_some() {
tags.push(tag.into());
}
}
}
}
}
}
impl Condition<'_> {
pub fn is_none_match(&self) -> bool {
match self {
Condition::ETag { is_not, .. } | Condition::Exists { is_not } => *is_not,
Condition::StateToken { .. } => false,
}
}
}