fix: resolve CalDAV PROPFIND returning empty property values (#153)
Root cause: XML namespace prefixes (e.g. "D", "C") were not being
resolved to their actual namespace URIs (e.g. "DAV:",
"urn:ietf:params:xml:ns:caldav") during PROPFIND parsing. This caused
all property match arms to fall through to the catch-all, producing
empty XML elements.
Changes:
- Add namespace-aware XML parsing (collect_ns_decls + resolve_name) to
WebDavAdapter, used by all DAV protocol parsers (WebDAV, CalDAV,
CardDAV)
- Add /.well-known/caldav -> /caldav/ redirect (RFC 6764)
- Add root /caldav/ PROPFIND response with current-user-principal and
calendar-home-set discovery properties
- Add /caldav/principals/{username}/ PROPFIND handler (was 500 error)
- Add /caldav/{username}/ user calendar home handler (calendar-home-set
target)
- Respect Depth header at root: depth 0 returns only root entry, depth
1+ includes calendar children
- Fix pre-existing TRANSCODE_POOL_THREADS test compilation error
- Add 8 new tests covering namespace resolution, discovery properties,
and principal responses
https://claude.ai/code/session_01T49VBJSimgo28APxbucHzq
This commit is contained in:
@@ -53,10 +53,12 @@ impl CardDavAdapter {
|
||||
let mut sync_token = String::new();
|
||||
let mut in_href = false;
|
||||
let mut in_sync_token = false;
|
||||
let mut ns_map = std::collections::HashMap::<String, String>::new();
|
||||
|
||||
loop {
|
||||
match xml_reader.read_event_into(&mut buffer) {
|
||||
Ok(Event::Start(ref e)) => {
|
||||
WebDavAdapter::collect_ns_decls(e, &mut ns_map);
|
||||
let name = e.name();
|
||||
let name_str = std::str::from_utf8(name.as_ref()).unwrap_or("");
|
||||
|
||||
@@ -78,9 +80,8 @@ impl CardDavAdapter {
|
||||
in_sync_token = true
|
||||
}
|
||||
_ if in_prop => {
|
||||
let namespace = WebDavAdapter::extract_namespace(name_str);
|
||||
let prop_name = WebDavAdapter::extract_local_name(name_str);
|
||||
props.push(QualifiedName::new(namespace, prop_name));
|
||||
let qname = WebDavAdapter::resolve_name(name_str, &ns_map);
|
||||
props.push(qname);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@@ -107,11 +108,11 @@ impl CardDavAdapter {
|
||||
}
|
||||
}
|
||||
Ok(Event::Empty(ref e)) if in_prop => {
|
||||
WebDavAdapter::collect_ns_decls(e, &mut ns_map);
|
||||
let name = e.name();
|
||||
let name_str = std::str::from_utf8(name.as_ref()).unwrap_or("");
|
||||
let namespace = WebDavAdapter::extract_namespace(name_str);
|
||||
let prop_name = WebDavAdapter::extract_local_name(name_str);
|
||||
props.push(QualifiedName::new(namespace, prop_name));
|
||||
let qname = WebDavAdapter::resolve_name(name_str, &ns_map);
|
||||
props.push(qname);
|
||||
}
|
||||
Ok(Event::Eof) => break,
|
||||
Err(e) => return Err(WebDavError::XmlError(e)),
|
||||
|
||||
Reference in New Issue
Block a user