Digital Sovereignty for everyone

Architecture

LH DAV is a data plugin: it owns the DAV protocol and the sync change log, and DAV itself (vCard and iCalendar, readable by any standard client) is the portability mechanism. It registers no MCP abilities; tooling plugins use its plain PHP service API (see Provider API).

URL layout

Everything is under /wp-json/lh-dav/v1/ on each site:

  • (root): answers current-user-principal
  • principals/{user ID}/: the signed-in user only; any other ID is a 403
  • addressbooks/{user ID}/{collection}/{name}.vcf and calendars/{user ID}/{collection}/{name}.ics
  • setup-profile: the Apple .mobileconfig (normal REST authentication, so a cookie with a wp_rest nonce works)

/.well-known/carddav and /.well-known/caldav are matched on parse_request (no rewrite rules, so nothing to flush across the network) and 301 to the root, only while a provider serves that component.

Serving DAV through REST

Taken from LH Vcard 1.11.0’s CardDAV handler. The REST server only carries the request: LH_DAV_Server builds the full response, returns a WP_REST_Response whose data is a short summary (what REST logs record), and sends the real XML, vCard or iCalendar body on rest_pre_serve_request. OPTIONS on any DAV path, and every method on the namespace root, are answered on rest_pre_dispatch (priority 5) before core’s own handling.

Authentication

Core’s application password check does the login. On DAV paths rest_authentication_errors (priority 99) skips core’s errors so the server can send its own WWW-Authenticate: Basic challenge, which contacts apps need. The server then refuses any request not authenticated by an application password (rest_get_authenticated_app_password()), so a browser cookie alone gets a 401. Users also need the access capability (read by default).

Making and changing collections

Since 0.3.0, MKCALENDAR and extended MKCOL on a free name in a home make a collection, PROPPATCH on a collection renames, recolours or reorders it, and DELETE on a collection removes it, all through a provider implementing LH_DAV_Collection_Manager (see Provider API). The DAV header then includes extended-mkcol. LH Calendars is the first such provider.

Change log and sync tokens

Table {base_prefix}lh_dav_changes (network-wide): id (the sync sequence), site_id, collection (key {component}/{owner user ID, 0 if shared}/{collection id}), resource, operation (modified or deleted), user_id, changed_gmt. Created and upgraded on schema_version() (stored in site option lh_dav-schema_version), never on plugin_version(). Since 0.3.0 changes are recorded and read against the collection’s site_id, which defaults to the current site.

Sync tokens are {base}sync/{sequence}/{state hash}. A token whose state hash no longer matches the collection’s state gets a full resend; one below the pruned-through marker gets 403 valid-sync-token, telling the client to resync. A daily cron on the main site prunes rows older than the retention (90 days) and records the highest pruned ID in site option lh_dav-pruned_through.

Known limits

  • addressbook-query and calendar-query ignore filters and return the whole collection; large calendars may later want time-range filtering.
  • MOVE and COPY get 403. Collections whose provider does not manage them cannot be made, renamed or deleted over DAV.
  • No CalDAV scheduling (RFC 6638) yet, so invitations and replies are not sent from devices.
  • PROPFIND returns every known property rather than only those requested.

If you like this plugin please consider making a donation to further development

Install LHero.org

lhero.org

Open it straight from your home screen, full screen and quicker to load.

  1. Tap the Share button . If you cannot see it, tap ••• first.
  2. Scroll down and tap Add to Home Screen.
  3. Tap Add.
  1. Tap the browser menu â‹®.
  2. Tap Install app or Add to Home screen.
  1. In the menu bar, choose File, then Add to Dock.

Use your browser's menu to install this site or add it to your home screen.