Commitdfef7de6Recorded13 Mar 2026Repositorysigil-caldav
Fix CalDAV namespace, SXML whitespace, and JMAP dict key syntax
Message
CalDAV: Use correct namespace URI urn:ietf:params:xml:ns:caldav (was urn:ietf:params:caldav) which caused 403 on Fastmail REPORT requests. Add guard around calendar-home-set discovery with fallback deriving home from principal URL. Fix find-text-in-tree to skip whitespace-only strings. Guard find-elements against non-list SXML nodes.
JMAP: Fix broken (string->keyword "..."): syntax in email.sgl and send.sgl by using dict string key syntax and #{} literals.
Changed
src/sigil/caldav/calendar.sgl | 4 ++--
src/sigil/caldav/client.sgl | 42 ++++++++++++++++++++++++++----------------
src/sigil/caldav/event.sgl | 2 +-
3 files changed, 29 insertions(+), 19 deletions(-)Diff
src/sigil/caldav/calendar.sglmodified
@@ -35,7 +35,7 @@
35
(let* ((home (caldav-client-calendar-home client)) 36
(response (caldav-propfind client home 37
'(d:propfind (@ (xmlns:d "DAV:")−38
(xmlns:cal "urn:ietf:params:caldav")+38
(xmlns:cal "urn:ietf:params:xml:ns:caldav") 39
(xmlns:cs "http://calendarserver.org/ns/") 40
(xmlns:ic "http://apple.com/ns/ical/")) 41
(d:prop@@ -125,7 +125,7 @@
125
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" 126
(sxml->xml 127
`(cal:mkcalendar (@ (xmlns:d "DAV:")−128
(xmlns:cal "urn:ietf:params:caldav"))+128
(xmlns:cal "urn:ietf:params:xml:ns:caldav")) 129
(d:set 130
(d:prop 131
(d:displayname ,name)src/sigil/caldav/client.sglmodified
@@ -201,7 +201,7 @@
201
(define (find-elements sxml tag) 202
(let ((results '())) 203
(define (walk node)−204
(when (and (pair? node) (sxml-element? node))+204
(when (and (list? node) (pair? node) (sxml-element? node)) 205
(when (eq? (sxml-tag node) tag) 206
(set! results (cons node results))) 207
(for-each walk (sxml-content node))))@@ -277,19 +277,26 @@
277
(resolve-url url principal-href)) 278
279
;; Step 2: Find calendar-home-set−280
(let* ((home-response−281
(caldav-propfind client−282
(caldav-client-principal-url client)−283
'(d:propfind (@ (xmlns:d "DAV:")−284
(xmlns:cal "urn:ietf:params:caldav"))−285
(d:prop (cal:calendar-home-set)))))−286
(home-entries (parse-multistatus home-response))−287
(home-href−288
(and (pair? home-entries)−289
(let ((prop (dict-ref (car home-entries)−290
(string->keyword "cal:calendar-home-set") #f)))−291
(and prop (pair? prop)−292
(find-text-in-tree prop))))))+280
(let* ((home-href+281
(guard (e (else #f))+282
(let* ((home-response+283
(caldav-propfind client+284
(caldav-client-principal-url client)+285
'(d:propfind (@ (xmlns:d "DAV:")+286
(xmlns:cal "urn:ietf:params:xml:ns:caldav"))+287
(d:prop (cal:calendar-home-set)))))+288
(home-entries (parse-multistatus home-response)))+289
(and (pair? home-entries)+290
(let ((prop (dict-ref (car home-entries)+291
(string->keyword "cal:calendar-home-set") #f)))+292
(and prop (pair? prop)+293
(find-text-in-tree prop)))))))+294
;; Fallback: derive calendar home from principal URL+295
;; e.g. /dav/principals/user/X/ -> /dav/calendars/user/X/+296
(home-href (or home-href+297
(let ((principal (caldav-client-principal-url client)))+298
(and (string-contains? principal "/principals/")+299
(string-replace principal "/principals/" "/calendars/")))))) 300
(unless home-href 301
(error "caldav-connect: could not discover calendar home")) 302
(set-caldav-client-calendar-home! client@@ -297,12 +304,15 @@
304
305
client)))) 306
−300
;; Find the first text string in a nested SXML tree+307
;; Find the first non-whitespace text string in a nested SXML tree 308
;; Used to extract href text from nested elements like 309
;; (d:current-user-principal (d:href "/principal/")) 310
(define (find-text-in-tree tree) 311
(cond−305
((string? tree) tree)+312
((string? tree)+313
(if (string=? (string-trim tree) "")+314
#f+315
tree)) 316
((pair? tree) 317
(let loop ((items tree)) 318
(if (null? items)src/sigil/caldav/event.sglmodified
@@ -55,7 +55,7 @@
55
'())) 56
(body `(cal:calendar-query 57
(@ (xmlns:d "DAV:")−58
(xmlns:cal "urn:ietf:params:caldav"))+58
(xmlns:cal "urn:ietf:params:xml:ns:caldav")) 59
(d:prop 60
(d:getetag) 61
(cal:calendar-data))