fix: CalDAV Autodiscovery - XML war doppelt verschachtelt

Property-Elemente wurden unter einem Container mit demselben Tag
erzeugt, z.B.:
  <current-user-principal>
    <current-user-principal>    <!-- falsch, doppelt -->
      <href>/dav/adam/</href>
    </current-user-principal>
  </current-user-principal>

Clients wie DAVx5 und Thunderbird erkennen dadurch den Principal
nicht und melden "Kein CalDAV-Dienst gefunden". XML-Generierung
umgebaut - Response-Helfer bekommen jetzt eine populate_prop-
Callback, die die tatsaechlichen Property-Children direkt ins
<prop>-Element setzt.

Zusaetzlich:
* /.well-known/caldav und /carddav akzeptieren jetzt auch PROPFIND,
  OPTIONS, HEAD (einige Clients halten die Methode beim ersten
  Aufruf bei).
* Kalender-Response enthaelt current-user-privilege-set (leer, als
  Signal dass der Client nicht ACL-abhaengig pruefen muss).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Stefan Hacker
2026-04-12 13:44:44 +02:00
parent e85338761d
commit c4b381c5e9
2 changed files with 53 additions and 70 deletions
+5 -6
View File
@@ -92,15 +92,14 @@ def create_app(config_class=Config):
app.register_blueprint(dav_bp)
# Well-known URLs for CalDAV/CardDAV auto-discovery (iOS, DAVx5, etc.).
# RFC 6764 says we should do a 301 to the DAV root; clients then PROPFIND
# to walk principal/home-set/calendars. The path intentionally does NOT
# include a username - the user authenticates via HTTP Basic and the
# server routes them to their own principal.
@app.route('/.well-known/caldav')
# RFC 6764 requires 301; PROPFIND auf /.well-known/caldav gibt manche
# Clients direkt ab (Method-Preservation) - also auch dort akzeptieren
# und auf /dav/ weiterleiten. Alle HTTP-Methoden werden registriert.
@app.route('/.well-known/caldav', methods=['GET', 'PROPFIND', 'OPTIONS', 'HEAD'])
def wellknown_caldav():
return redirect('/dav/', code=301)
@app.route('/.well-known/carddav')
@app.route('/.well-known/carddav', methods=['GET', 'PROPFIND', 'OPTIONS', 'HEAD'])
def wellknown_carddav():
return redirect('/dav/', code=301)