fix(webdav): achieve 100% litmus compliance (59/59 tests)
Complete RFC 4918 litmus test suite compliance (basic 16/16, copymove 13/13, props 30/30) by fixing six categories of failures: - PropPatchOp: parse PROPPATCH in document order (RFC 4918 §9.2) so that remove-then-set and set-then-remove yield different results - Null namespace: resolve_name now correctly maps xmlns="" to empty-ns QualifiedName instead of falling through to DAV: namespace - Unicode chars: handle quick-xml 0.39's Event::GeneralRef for character references (𐀀) — the parser emits these as GeneralRef, not Text - MOVE preserves dead props: call rename_resource on MOVE, clearing stale destination data even when source has no registered properties - Malformed PROPFIND: return 400 when body lacks a complete <propfind> element (test 2: bare <foo>, test 3: invalid xmlns:prefix="" binding) - PROPPATCH document order: process ops via Vec<PropPatchOp> instead of separate (sets, removes) to honour interleaved remove/set sequences
This commit is contained in:
@@ -850,11 +850,10 @@ async fn handle_proppatch(
|
||||
.await
|
||||
.map_err(|e| AppError::bad_request(format!("Failed to read request body: {}", e)))?;
|
||||
|
||||
let (props_to_set, props_to_remove) =
|
||||
crate::application::adapters::webdav_adapter::WebDavAdapter::parse_proppatch(
|
||||
body_bytes.reader(),
|
||||
)
|
||||
.map_err(|e| AppError::bad_request(format!("Failed to parse PROPPATCH: {}", e)))?;
|
||||
let ops = crate::application::adapters::webdav_adapter::WebDavAdapter::parse_proppatch(
|
||||
body_bytes.reader(),
|
||||
)
|
||||
.map_err(|e| AppError::bad_request(format!("Failed to parse PROPPATCH: {}", e)))?;
|
||||
|
||||
let effective_path = strip_username_prefix(path);
|
||||
let calendar_id = effective_path.split('/').next().unwrap_or(effective_path);
|
||||
@@ -870,12 +869,14 @@ async fn handle_proppatch(
|
||||
is_public: None,
|
||||
};
|
||||
|
||||
for prop in &props_to_set {
|
||||
match prop.name.name.as_str() {
|
||||
"displayname" => update.name = Some(prop.value.clone().unwrap_or_default()),
|
||||
"calendar-description" => update.description = prop.value.clone(),
|
||||
"calendar-color" => update.color = prop.value.clone(),
|
||||
_ => {}
|
||||
for op in &ops {
|
||||
if let crate::application::adapters::webdav_adapter::PropPatchOp::Set(prop) = op {
|
||||
match prop.name.name.as_str() {
|
||||
"displayname" => update.name = Some(prop.value.clone().unwrap_or_default()),
|
||||
"calendar-description" => update.description = prop.value.clone(),
|
||||
"calendar-color" => update.color = prop.value.clone(),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -887,11 +888,15 @@ async fn handle_proppatch(
|
||||
}
|
||||
|
||||
let mut results = Vec::new();
|
||||
for prop in &props_to_set {
|
||||
results.push((&prop.name, true));
|
||||
}
|
||||
for prop in &props_to_remove {
|
||||
results.push((prop, true));
|
||||
for op in &ops {
|
||||
match op {
|
||||
crate::application::adapters::webdav_adapter::PropPatchOp::Set(prop) => {
|
||||
results.push((&prop.name, true));
|
||||
}
|
||||
crate::application::adapters::webdav_adapter::PropPatchOp::Remove(name) => {
|
||||
results.push((name, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let href = format!("/caldav/{}", path);
|
||||
|
||||
Reference in New Issue
Block a user