Import upstream v0.16.22, stripped
Upstream commit: 474dd0229cb20cf513036619781ed97bd8073c3f Enterprise-only files removed or emptied: 63 Enterprise-only snippets removed: 117 in 50 files Dangling module declarations removed: 5 Cargo edits turning enterprise off: 14 Verification: clean Enterprise feature gates left for rebuilt features: 19 in 18 files Produced by tools/fork/strip.py. The full report is in docs/fork/strip-reports/ on main.
This commit is contained in:
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <[email protected]>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
#![warn(clippy::large_futures)]
|
||||
|
||||
pub mod calendar;
|
||||
pub mod card;
|
||||
pub mod common;
|
||||
pub mod file;
|
||||
pub mod principal;
|
||||
pub mod request;
|
||||
|
||||
use dav_proto::schema::{
|
||||
request::DavPropertyValue,
|
||||
response::{Condition, List, Prop, PropStat, ResponseDescription, Status},
|
||||
};
|
||||
use groupware::{DavResourceName, RFC_3986, is_uri_segment};
|
||||
use hyper::{Method, StatusCode};
|
||||
use std::borrow::Cow;
|
||||
use store::ahash::AHashMap;
|
||||
pub(crate) type Result<T> = std::result::Result<T, DavError>;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum DavMethod {
|
||||
GET,
|
||||
PUT,
|
||||
POST,
|
||||
DELETE,
|
||||
HEAD,
|
||||
PATCH,
|
||||
PROPFIND,
|
||||
PROPPATCH,
|
||||
REPORT,
|
||||
MKCOL,
|
||||
MKCALENDAR,
|
||||
COPY,
|
||||
MOVE,
|
||||
LOCK,
|
||||
UNLOCK,
|
||||
OPTIONS,
|
||||
ACL,
|
||||
}
|
||||
|
||||
impl From<DavMethod> for trc::WebDavEvent {
|
||||
fn from(value: DavMethod) -> Self {
|
||||
match value {
|
||||
DavMethod::GET => trc::WebDavEvent::Get,
|
||||
DavMethod::PUT => trc::WebDavEvent::Put,
|
||||
DavMethod::POST => trc::WebDavEvent::Post,
|
||||
DavMethod::DELETE => trc::WebDavEvent::Delete,
|
||||
DavMethod::HEAD => trc::WebDavEvent::Head,
|
||||
DavMethod::PATCH => trc::WebDavEvent::Patch,
|
||||
DavMethod::PROPFIND => trc::WebDavEvent::Propfind,
|
||||
DavMethod::PROPPATCH => trc::WebDavEvent::Proppatch,
|
||||
DavMethod::REPORT => trc::WebDavEvent::Report,
|
||||
DavMethod::MKCOL => trc::WebDavEvent::Mkcol,
|
||||
DavMethod::MKCALENDAR => trc::WebDavEvent::Mkcalendar,
|
||||
DavMethod::COPY => trc::WebDavEvent::Copy,
|
||||
DavMethod::MOVE => trc::WebDavEvent::Move,
|
||||
DavMethod::LOCK => trc::WebDavEvent::Lock,
|
||||
DavMethod::UNLOCK => trc::WebDavEvent::Unlock,
|
||||
DavMethod::OPTIONS => trc::WebDavEvent::Options,
|
||||
DavMethod::ACL => trc::WebDavEvent::Acl,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) enum DavError {
|
||||
Parse(dav_proto::parser::Error),
|
||||
Internal(trc::Error),
|
||||
Condition(DavErrorCondition),
|
||||
Code(StatusCode),
|
||||
}
|
||||
|
||||
struct DavErrorCondition {
|
||||
pub code: StatusCode,
|
||||
pub condition: Condition,
|
||||
pub details: Option<String>,
|
||||
}
|
||||
|
||||
impl From<DavErrorCondition> for DavError {
|
||||
fn from(value: DavErrorCondition) -> Self {
|
||||
DavError::Condition(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Condition> for DavErrorCondition {
|
||||
fn from(value: Condition) -> Self {
|
||||
DavErrorCondition {
|
||||
code: StatusCode::CONFLICT,
|
||||
condition: value,
|
||||
details: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DavErrorCondition {
|
||||
pub fn new(code: StatusCode, condition: impl Into<Condition>) -> Self {
|
||||
DavErrorCondition {
|
||||
code,
|
||||
condition: condition.into(),
|
||||
details: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_details(mut self, details: impl Into<String>) -> Self {
|
||||
self.details = Some(details.into());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl DavMethod {
|
||||
pub fn parse(method: &Method) -> Option<Self> {
|
||||
match *method {
|
||||
Method::GET => Some(DavMethod::GET),
|
||||
Method::PUT => Some(DavMethod::PUT),
|
||||
Method::DELETE => Some(DavMethod::DELETE),
|
||||
Method::OPTIONS => Some(DavMethod::OPTIONS),
|
||||
Method::POST => Some(DavMethod::POST),
|
||||
Method::PATCH => Some(DavMethod::PATCH),
|
||||
Method::HEAD => Some(DavMethod::HEAD),
|
||||
_ => {
|
||||
hashify::tiny_map!(method.as_str().as_bytes(),
|
||||
"PROPFIND" => DavMethod::PROPFIND,
|
||||
"PROPPATCH" => DavMethod::PROPPATCH,
|
||||
"REPORT" => DavMethod::REPORT,
|
||||
"MKCOL" => DavMethod::MKCOL,
|
||||
"MKCALENDAR" => DavMethod::MKCALENDAR,
|
||||
"COPY" => DavMethod::COPY,
|
||||
"MOVE" => DavMethod::MOVE,
|
||||
"LOCK" => DavMethod::LOCK,
|
||||
"UNLOCK" => DavMethod::UNLOCK,
|
||||
"ACL" => DavMethod::ACL
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn has_body(self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
DavMethod::PUT
|
||||
| DavMethod::POST
|
||||
| DavMethod::PATCH
|
||||
| DavMethod::PROPPATCH
|
||||
| DavMethod::PROPFIND
|
||||
| DavMethod::REPORT
|
||||
| DavMethod::LOCK
|
||||
| DavMethod::ACL
|
||||
| DavMethod::MKCALENDAR
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct PropStatBuilder {
|
||||
propstats: AHashMap<(StatusCode, Option<Condition>, Option<String>), Vec<DavPropertyValue>>,
|
||||
}
|
||||
|
||||
impl PropStatBuilder {
|
||||
pub fn insert_ok(&mut self, prop: impl Into<DavPropertyValue>) -> &mut Self {
|
||||
self.propstats
|
||||
.entry((StatusCode::OK, None, None))
|
||||
.or_default()
|
||||
.push(prop.into());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn insert_with_status(
|
||||
&mut self,
|
||||
prop: impl Into<DavPropertyValue>,
|
||||
status: StatusCode,
|
||||
) -> &mut Self {
|
||||
self.propstats
|
||||
.entry((status, None, None))
|
||||
.or_default()
|
||||
.push(prop.into());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn insert_error_with_description(
|
||||
&mut self,
|
||||
prop: impl Into<DavPropertyValue>,
|
||||
status: StatusCode,
|
||||
description: impl Into<String>,
|
||||
) -> &mut Self {
|
||||
self.propstats
|
||||
.entry((status, None, Some(description.into())))
|
||||
.or_default()
|
||||
.push(prop.into());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn insert_precondition_failed(
|
||||
&mut self,
|
||||
prop: impl Into<DavPropertyValue>,
|
||||
status: StatusCode,
|
||||
condition: impl Into<Condition>,
|
||||
) -> &mut Self {
|
||||
self.propstats
|
||||
.entry((status, Some(condition.into()), None))
|
||||
.or_default()
|
||||
.push(prop.into());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn insert_precondition_failed_with_description(
|
||||
&mut self,
|
||||
prop: impl Into<DavPropertyValue>,
|
||||
status: StatusCode,
|
||||
condition: impl Into<Condition>,
|
||||
description: impl Into<String>,
|
||||
) -> &mut Self {
|
||||
self.propstats
|
||||
.entry((status, Some(condition.into()), Some(description.into())))
|
||||
.or_default()
|
||||
.push(prop.into());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> Vec<PropStat> {
|
||||
self.propstats
|
||||
.into_iter()
|
||||
.map(|((status, condition, description), props)| PropStat {
|
||||
prop: Prop(List(props)),
|
||||
status: Status(status),
|
||||
error: condition,
|
||||
response_description: description.map(ResponseDescription),
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
// Workaround for Apple bug with missing percent encoding in paths
|
||||
pub(crate) fn fix_percent_encoding(path: &'_ str) -> Cow<'_, str> {
|
||||
let (parent, name) = if let Some((parent, name)) = path.rsplit_once('/') {
|
||||
(Some(parent), name)
|
||||
} else {
|
||||
(None, path)
|
||||
};
|
||||
|
||||
if is_uri_segment(name) {
|
||||
path.into()
|
||||
} else {
|
||||
let name = percent_encoding::utf8_percent_encode(name, RFC_3986);
|
||||
|
||||
if let Some(parent) = parent {
|
||||
Cow::Owned(format!("{parent}/{name}"))
|
||||
} else {
|
||||
Cow::Owned(name.to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user