Add the CalDAV client and a CLI to drive it
Discovery is the three PROPFINDs RFC 4791 describes rather than a walk through likely URLs. Queries use time-range, which v1 never did -- it fetched whole calendars and filtered in the browser on every view change. Every write states a precondition, so a stale ETag produces a Conflict a caller can act on instead of silently destroying somebody's edit. XML goes through quick-xml with namespace resolution. v1 matched prefixes with six regexes tried in sequence and recompiled inside the loop; there is a fixture here that is the same document under different prefixes, and it parses identically. Protocol parsing is split from transport so it can be tested against responses recorded from a real Baikal -- including the second propstat carrying 404s, which is what makes "this calendar has no colour" different from "this calendar has an empty colour". Live tests run against a real server, never a mock. tests/baikal/run.sh starts a container, walks Baikal's install wizard, and runs them; each test builds and destroys its own collection, so pointing it at a real server touches nothing that was already there. They cover discovery, round-trip, stale-ETag conflict, duplicate create, delete, time-range filtering, a series returned whole with its override, and writing every synthetic golden fixture to the server and reading it back. libdav was evaluated first, as planned. Not adopted: its HttpClient trait is defined over hyper::body::Incoming, so using it means replacing reqwest everywhere, plus a DNS resolver for service discovery we do not do and a second XML parser. Its precondition design is where Precondition's shape comes from. Reasons are recorded in the crate docs.
This commit is contained in:
@@ -0,0 +1,200 @@
|
||||
<?xml version="1.0" ?>
|
||||
<multistatus xmlns="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:CAL="urn:ietf:params:xml:ns:caldav" xmlns:cs="http://calendarserver.org/ns/" xmlns:card="urn:ietf:params:xml:ns:carddav">
|
||||
<response>
|
||||
<href>/dav.php/calendars/alex/</href>
|
||||
<propstat>
|
||||
<prop>
|
||||
<resourcetype>
|
||||
<collection/>
|
||||
</resourcetype>
|
||||
</prop>
|
||||
<status>HTTP/1.1 200 OK</status>
|
||||
</propstat>
|
||||
<propstat>
|
||||
<prop>
|
||||
<displayname/>
|
||||
<CAL:calendar-description/>
|
||||
<CAL:supported-calendar-component-set/>
|
||||
<x1:calendar-color xmlns:x1="http://apple.com/ns/ical/"/>
|
||||
<cs:getctag/>
|
||||
</prop>
|
||||
<status>HTTP/1.1 404 Not Found</status>
|
||||
</propstat>
|
||||
</response>
|
||||
<response>
|
||||
<href>/dav.php/calendars/alex/household-chores/</href>
|
||||
<propstat>
|
||||
<prop>
|
||||
<resourcetype>
|
||||
<collection/>
|
||||
<CAL:calendar/>
|
||||
</resourcetype>
|
||||
<displayname>Household Chores</displayname>
|
||||
<CAL:supported-calendar-component-set>
|
||||
<CAL:comp name="VEVENT"/>
|
||||
</CAL:supported-calendar-component-set>
|
||||
<x1:calendar-color xmlns:x1="http://apple.com/ns/ical/">#DC2626</x1:calendar-color>
|
||||
<cs:getctag>http://sabre.io/ns/sync/4</cs:getctag>
|
||||
</prop>
|
||||
<status>HTTP/1.1 200 OK</status>
|
||||
</propstat>
|
||||
<propstat>
|
||||
<prop>
|
||||
<CAL:calendar-description/>
|
||||
</prop>
|
||||
<status>HTTP/1.1 404 Not Found</status>
|
||||
</propstat>
|
||||
</response>
|
||||
<response>
|
||||
<href>/dav.php/calendars/alex/partner-chores/</href>
|
||||
<propstat>
|
||||
<prop>
|
||||
<resourcetype>
|
||||
<collection/>
|
||||
<CAL:calendar/>
|
||||
</resourcetype>
|
||||
<displayname>Partner Chores</displayname>
|
||||
<CAL:supported-calendar-component-set>
|
||||
<CAL:comp name="VEVENT"/>
|
||||
</CAL:supported-calendar-component-set>
|
||||
<x1:calendar-color xmlns:x1="http://apple.com/ns/ical/">#7C3AED</x1:calendar-color>
|
||||
<cs:getctag>http://sabre.io/ns/sync/6</cs:getctag>
|
||||
</prop>
|
||||
<status>HTTP/1.1 200 OK</status>
|
||||
</propstat>
|
||||
<propstat>
|
||||
<prop>
|
||||
<CAL:calendar-description/>
|
||||
</prop>
|
||||
<status>HTTP/1.1 404 Not Found</status>
|
||||
</propstat>
|
||||
</response>
|
||||
<response>
|
||||
<href>/dav.php/calendars/alex/trips/</href>
|
||||
<propstat>
|
||||
<prop>
|
||||
<resourcetype>
|
||||
<collection/>
|
||||
<CAL:calendar/>
|
||||
</resourcetype>
|
||||
<displayname>Trips</displayname>
|
||||
<CAL:supported-calendar-component-set>
|
||||
<CAL:comp name="VEVENT"/>
|
||||
</CAL:supported-calendar-component-set>
|
||||
<cs:getctag>http://sabre.io/ns/sync/23</cs:getctag>
|
||||
</prop>
|
||||
<status>HTTP/1.1 200 OK</status>
|
||||
</propstat>
|
||||
<propstat>
|
||||
<prop>
|
||||
<CAL:calendar-description/>
|
||||
<x1:calendar-color xmlns:x1="http://apple.com/ns/ical/"/>
|
||||
</prop>
|
||||
<status>HTTP/1.1 404 Not Found</status>
|
||||
</propstat>
|
||||
</response>
|
||||
<response>
|
||||
<href>/dav.php/calendars/alex/workouts/</href>
|
||||
<propstat>
|
||||
<prop>
|
||||
<resourcetype>
|
||||
<collection/>
|
||||
<CAL:calendar/>
|
||||
</resourcetype>
|
||||
<displayname>Workouts</displayname>
|
||||
<CAL:calendar-description>Calendar for logging workouts</CAL:calendar-description>
|
||||
<CAL:supported-calendar-component-set>
|
||||
<CAL:comp name="VEVENT"/>
|
||||
</CAL:supported-calendar-component-set>
|
||||
<x1:calendar-color xmlns:x1="http://apple.com/ns/ical/">#3B82F6</x1:calendar-color>
|
||||
<cs:getctag>http://sabre.io/ns/sync/64</cs:getctag>
|
||||
</prop>
|
||||
<status>HTTP/1.1 200 OK</status>
|
||||
</propstat>
|
||||
</response>
|
||||
<response>
|
||||
<href>/dav.php/calendars/alex/birthdays/</href>
|
||||
<propstat>
|
||||
<prop>
|
||||
<resourcetype>
|
||||
<collection/>
|
||||
<CAL:calendar/>
|
||||
<cs:shared-owner/>
|
||||
</resourcetype>
|
||||
<displayname>Birthdays</displayname>
|
||||
<CAL:calendar-description/>
|
||||
<CAL:supported-calendar-component-set>
|
||||
<CAL:comp name="VEVENT"/>
|
||||
</CAL:supported-calendar-component-set>
|
||||
<x1:calendar-color xmlns:x1="http://apple.com/ns/ical/">#DD403A</x1:calendar-color>
|
||||
<cs:getctag>http://sabre.io/ns/sync/36</cs:getctag>
|
||||
</prop>
|
||||
<status>HTTP/1.1 200 OK</status>
|
||||
</propstat>
|
||||
</response>
|
||||
<response>
|
||||
<href>/dav.php/calendars/alex/personal/</href>
|
||||
<propstat>
|
||||
<prop>
|
||||
<resourcetype>
|
||||
<collection/>
|
||||
<CAL:calendar/>
|
||||
</resourcetype>
|
||||
<displayname>Personal</displayname>
|
||||
<CAL:calendar-description/>
|
||||
<CAL:supported-calendar-component-set>
|
||||
<CAL:comp name="VEVENT"/>
|
||||
<CAL:comp name="VTODO"/>
|
||||
<CAL:comp name="VJOURNAL"/>
|
||||
</CAL:supported-calendar-component-set>
|
||||
<x1:calendar-color xmlns:x1="http://apple.com/ns/ical/">#0CCE6B</x1:calendar-color>
|
||||
<cs:getctag>http://sabre.io/ns/sync/930</cs:getctag>
|
||||
</prop>
|
||||
<status>HTTP/1.1 200 OK</status>
|
||||
</propstat>
|
||||
</response>
|
||||
<response>
|
||||
<href>/dav.php/calendars/alex/inbox/</href>
|
||||
<propstat>
|
||||
<prop>
|
||||
<resourcetype>
|
||||
<collection/>
|
||||
<CAL:schedule-inbox/>
|
||||
</resourcetype>
|
||||
</prop>
|
||||
<status>HTTP/1.1 200 OK</status>
|
||||
</propstat>
|
||||
<propstat>
|
||||
<prop>
|
||||
<displayname/>
|
||||
<CAL:calendar-description/>
|
||||
<CAL:supported-calendar-component-set/>
|
||||
<x1:calendar-color xmlns:x1="http://apple.com/ns/ical/"/>
|
||||
<cs:getctag/>
|
||||
</prop>
|
||||
<status>HTTP/1.1 404 Not Found</status>
|
||||
</propstat>
|
||||
</response>
|
||||
<response>
|
||||
<href>/dav.php/calendars/alex/outbox/</href>
|
||||
<propstat>
|
||||
<prop>
|
||||
<resourcetype>
|
||||
<collection/>
|
||||
<CAL:schedule-outbox/>
|
||||
</resourcetype>
|
||||
</prop>
|
||||
<status>HTTP/1.1 200 OK</status>
|
||||
</propstat>
|
||||
<propstat>
|
||||
<prop>
|
||||
<displayname/>
|
||||
<CAL:calendar-description/>
|
||||
<CAL:supported-calendar-component-set/>
|
||||
<x1:calendar-color xmlns:x1="http://apple.com/ns/ical/"/>
|
||||
<cs:getctag/>
|
||||
</prop>
|
||||
<status>HTTP/1.1 404 Not Found</status>
|
||||
</propstat>
|
||||
</response>
|
||||
</multistatus>
|
||||
@@ -0,0 +1,200 @@
|
||||
<?xml version="1.0" ?>
|
||||
<d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:cal="urn:ietf:params:xml:ns:caldav" xmlns:cs="http://calendarserver.org/ns/" xmlns:card="urn:ietf:params:xml:ns:carddav">
|
||||
<d:response>
|
||||
<d:href>/dav.php/calendars/alex/</d:href>
|
||||
<d:propstat>
|
||||
<d:prop>
|
||||
<d:resourcetype>
|
||||
<d:collection/>
|
||||
</d:resourcetype>
|
||||
</d:prop>
|
||||
<d:status>HTTP/1.1 200 OK</d:status>
|
||||
</d:propstat>
|
||||
<d:propstat>
|
||||
<d:prop>
|
||||
<d:displayname/>
|
||||
<cal:calendar-description/>
|
||||
<cal:supported-calendar-component-set/>
|
||||
<x1:calendar-color xmlns:x1="http://apple.com/ns/ical/"/>
|
||||
<cs:getctag/>
|
||||
</d:prop>
|
||||
<d:status>HTTP/1.1 404 Not Found</d:status>
|
||||
</d:propstat>
|
||||
</d:response>
|
||||
<d:response>
|
||||
<d:href>/dav.php/calendars/alex/household-chores/</d:href>
|
||||
<d:propstat>
|
||||
<d:prop>
|
||||
<d:resourcetype>
|
||||
<d:collection/>
|
||||
<cal:calendar/>
|
||||
</d:resourcetype>
|
||||
<d:displayname>Household Chores</d:displayname>
|
||||
<cal:supported-calendar-component-set>
|
||||
<cal:comp name="VEVENT"/>
|
||||
</cal:supported-calendar-component-set>
|
||||
<x1:calendar-color xmlns:x1="http://apple.com/ns/ical/">#DC2626</x1:calendar-color>
|
||||
<cs:getctag>http://sabre.io/ns/sync/4</cs:getctag>
|
||||
</d:prop>
|
||||
<d:status>HTTP/1.1 200 OK</d:status>
|
||||
</d:propstat>
|
||||
<d:propstat>
|
||||
<d:prop>
|
||||
<cal:calendar-description/>
|
||||
</d:prop>
|
||||
<d:status>HTTP/1.1 404 Not Found</d:status>
|
||||
</d:propstat>
|
||||
</d:response>
|
||||
<d:response>
|
||||
<d:href>/dav.php/calendars/alex/partner-chores/</d:href>
|
||||
<d:propstat>
|
||||
<d:prop>
|
||||
<d:resourcetype>
|
||||
<d:collection/>
|
||||
<cal:calendar/>
|
||||
</d:resourcetype>
|
||||
<d:displayname>Partner Chores</d:displayname>
|
||||
<cal:supported-calendar-component-set>
|
||||
<cal:comp name="VEVENT"/>
|
||||
</cal:supported-calendar-component-set>
|
||||
<x1:calendar-color xmlns:x1="http://apple.com/ns/ical/">#7C3AED</x1:calendar-color>
|
||||
<cs:getctag>http://sabre.io/ns/sync/6</cs:getctag>
|
||||
</d:prop>
|
||||
<d:status>HTTP/1.1 200 OK</d:status>
|
||||
</d:propstat>
|
||||
<d:propstat>
|
||||
<d:prop>
|
||||
<cal:calendar-description/>
|
||||
</d:prop>
|
||||
<d:status>HTTP/1.1 404 Not Found</d:status>
|
||||
</d:propstat>
|
||||
</d:response>
|
||||
<d:response>
|
||||
<d:href>/dav.php/calendars/alex/trips/</d:href>
|
||||
<d:propstat>
|
||||
<d:prop>
|
||||
<d:resourcetype>
|
||||
<d:collection/>
|
||||
<cal:calendar/>
|
||||
</d:resourcetype>
|
||||
<d:displayname>Trips</d:displayname>
|
||||
<cal:supported-calendar-component-set>
|
||||
<cal:comp name="VEVENT"/>
|
||||
</cal:supported-calendar-component-set>
|
||||
<cs:getctag>http://sabre.io/ns/sync/23</cs:getctag>
|
||||
</d:prop>
|
||||
<d:status>HTTP/1.1 200 OK</d:status>
|
||||
</d:propstat>
|
||||
<d:propstat>
|
||||
<d:prop>
|
||||
<cal:calendar-description/>
|
||||
<x1:calendar-color xmlns:x1="http://apple.com/ns/ical/"/>
|
||||
</d:prop>
|
||||
<d:status>HTTP/1.1 404 Not Found</d:status>
|
||||
</d:propstat>
|
||||
</d:response>
|
||||
<d:response>
|
||||
<d:href>/dav.php/calendars/alex/workouts/</d:href>
|
||||
<d:propstat>
|
||||
<d:prop>
|
||||
<d:resourcetype>
|
||||
<d:collection/>
|
||||
<cal:calendar/>
|
||||
</d:resourcetype>
|
||||
<d:displayname>Workouts</d:displayname>
|
||||
<cal:calendar-description>Calendar for logging workouts</cal:calendar-description>
|
||||
<cal:supported-calendar-component-set>
|
||||
<cal:comp name="VEVENT"/>
|
||||
</cal:supported-calendar-component-set>
|
||||
<x1:calendar-color xmlns:x1="http://apple.com/ns/ical/">#3B82F6</x1:calendar-color>
|
||||
<cs:getctag>http://sabre.io/ns/sync/64</cs:getctag>
|
||||
</d:prop>
|
||||
<d:status>HTTP/1.1 200 OK</d:status>
|
||||
</d:propstat>
|
||||
</d:response>
|
||||
<d:response>
|
||||
<d:href>/dav.php/calendars/alex/birthdays/</d:href>
|
||||
<d:propstat>
|
||||
<d:prop>
|
||||
<d:resourcetype>
|
||||
<d:collection/>
|
||||
<cal:calendar/>
|
||||
<cs:shared-owner/>
|
||||
</d:resourcetype>
|
||||
<d:displayname>Birthdays</d:displayname>
|
||||
<cal:calendar-description/>
|
||||
<cal:supported-calendar-component-set>
|
||||
<cal:comp name="VEVENT"/>
|
||||
</cal:supported-calendar-component-set>
|
||||
<x1:calendar-color xmlns:x1="http://apple.com/ns/ical/">#DD403A</x1:calendar-color>
|
||||
<cs:getctag>http://sabre.io/ns/sync/36</cs:getctag>
|
||||
</d:prop>
|
||||
<d:status>HTTP/1.1 200 OK</d:status>
|
||||
</d:propstat>
|
||||
</d:response>
|
||||
<d:response>
|
||||
<d:href>/dav.php/calendars/alex/personal/</d:href>
|
||||
<d:propstat>
|
||||
<d:prop>
|
||||
<d:resourcetype>
|
||||
<d:collection/>
|
||||
<cal:calendar/>
|
||||
</d:resourcetype>
|
||||
<d:displayname>Personal</d:displayname>
|
||||
<cal:calendar-description/>
|
||||
<cal:supported-calendar-component-set>
|
||||
<cal:comp name="VEVENT"/>
|
||||
<cal:comp name="VTODO"/>
|
||||
<cal:comp name="VJOURNAL"/>
|
||||
</cal:supported-calendar-component-set>
|
||||
<x1:calendar-color xmlns:x1="http://apple.com/ns/ical/">#0CCE6B</x1:calendar-color>
|
||||
<cs:getctag>http://sabre.io/ns/sync/930</cs:getctag>
|
||||
</d:prop>
|
||||
<d:status>HTTP/1.1 200 OK</d:status>
|
||||
</d:propstat>
|
||||
</d:response>
|
||||
<d:response>
|
||||
<d:href>/dav.php/calendars/alex/inbox/</d:href>
|
||||
<d:propstat>
|
||||
<d:prop>
|
||||
<d:resourcetype>
|
||||
<d:collection/>
|
||||
<cal:schedule-inbox/>
|
||||
</d:resourcetype>
|
||||
</d:prop>
|
||||
<d:status>HTTP/1.1 200 OK</d:status>
|
||||
</d:propstat>
|
||||
<d:propstat>
|
||||
<d:prop>
|
||||
<d:displayname/>
|
||||
<cal:calendar-description/>
|
||||
<cal:supported-calendar-component-set/>
|
||||
<x1:calendar-color xmlns:x1="http://apple.com/ns/ical/"/>
|
||||
<cs:getctag/>
|
||||
</d:prop>
|
||||
<d:status>HTTP/1.1 404 Not Found</d:status>
|
||||
</d:propstat>
|
||||
</d:response>
|
||||
<d:response>
|
||||
<d:href>/dav.php/calendars/alex/outbox/</d:href>
|
||||
<d:propstat>
|
||||
<d:prop>
|
||||
<d:resourcetype>
|
||||
<d:collection/>
|
||||
<cal:schedule-outbox/>
|
||||
</d:resourcetype>
|
||||
</d:prop>
|
||||
<d:status>HTTP/1.1 200 OK</d:status>
|
||||
</d:propstat>
|
||||
<d:propstat>
|
||||
<d:prop>
|
||||
<d:displayname/>
|
||||
<cal:calendar-description/>
|
||||
<cal:supported-calendar-component-set/>
|
||||
<x1:calendar-color xmlns:x1="http://apple.com/ns/ical/"/>
|
||||
<cs:getctag/>
|
||||
</d:prop>
|
||||
<d:status>HTTP/1.1 404 Not Found</d:status>
|
||||
</d:propstat>
|
||||
</d:response>
|
||||
</d:multistatus>
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" ?>
|
||||
<d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:cal="urn:ietf:params:xml:ns:caldav" xmlns:cs="http://calendarserver.org/ns/" xmlns:card="urn:ietf:params:xml:ns:carddav">
|
||||
<d:response>
|
||||
<d:href>/dav.php/</d:href>
|
||||
<d:propstat>
|
||||
<d:prop>
|
||||
<d:current-user-principal>
|
||||
<d:href>/dav.php/principals/alex/</d:href>
|
||||
</d:current-user-principal>
|
||||
</d:prop>
|
||||
<d:status>HTTP/1.1 200 OK</d:status>
|
||||
</d:propstat>
|
||||
<d:propstat>
|
||||
<d:prop>
|
||||
<d:displayname/>
|
||||
</d:prop>
|
||||
<d:status>HTTP/1.1 404 Not Found</d:status>
|
||||
</d:propstat>
|
||||
</d:response>
|
||||
</d:multistatus>
|
||||
@@ -0,0 +1,96 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:cal="urn:ietf:params:xml:ns:caldav">
|
||||
<d:response>
|
||||
<d:href>/dav.php/calendars/alex/personal/allday.ics</d:href>
|
||||
<d:propstat>
|
||||
<d:prop>
|
||||
<d:getetag>"7c9e8a1d2f3b4c5d6e7f8a9b0c1d2e3f"</d:getetag>
|
||||
<cal:calendar-data>BEGIN:VCALENDAR
|
||||
VERSION:2.0
|
||||
PRODID:DAVx5/4.4.8-gplay ical4j/3.2.19 (com.digibites.calendar)
|
||||
BEGIN:VEVENT
|
||||
UID:eee51914-187b-40d5-342c-dc80c118438a
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Check-in
|
||||
CLASS:PUBLIC
|
||||
TRANSP:OPAQUE
|
||||
DTSTART;VALUE=DATE:20250331
|
||||
DTEND;VALUE=DATE:20250401
|
||||
RRULE:FREQ=WEEKLY;BYDAY=MO
|
||||
CREATED:20250902T164854Z
|
||||
DTSTAMP:20250902T164854Z
|
||||
LAST-MODIFIED:20250902T164854Z
|
||||
SEQUENCE:2
|
||||
BEGIN:VALARM
|
||||
ACTION:DISPLAY
|
||||
DESCRIPTION:Retrospective demo retro
|
||||
TRIGGER:-PT4H
|
||||
END:VALARM
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
||||
</cal:calendar-data>
|
||||
</d:prop>
|
||||
<d:status>HTTP/1.1 200 OK</d:status>
|
||||
</d:propstat>
|
||||
</d:response>
|
||||
<d:response>
|
||||
<d:href>/dav.php/calendars/alex/personal/zoned.ics</d:href>
|
||||
<d:propstat>
|
||||
<d:prop>
|
||||
<d:getetag>"1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d"</d:getetag>
|
||||
<cal:calendar-data>BEGIN:VCALENDAR
|
||||
VERSION:2.0
|
||||
PRODID:DAVx5/4.5.19-gplay ical4j/4.3.0
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20260811T142404Z
|
||||
UID:3a21fd46-26c4-85b5-eee3-6d2d2256f8ef
|
||||
SUMMARY:Briefing
|
||||
DTSTART;TZID=America/New_York:20260818T083000
|
||||
DTEND;TZID=America/New_York:20260818T093000
|
||||
RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=TU
|
||||
STATUS:CONFIRMED
|
||||
BEGIN:VALARM
|
||||
TRIGGER:-PT1H
|
||||
ACTION:DISPLAY
|
||||
DESCRIPTION:Design
|
||||
END:VALARM
|
||||
BEGIN:VALARM
|
||||
TRIGGER:-PT12H
|
||||
ACTION:DISPLAY
|
||||
DESCRIPTION:Design
|
||||
END:VALARM
|
||||
END:VEVENT
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:America/New_York
|
||||
BEGIN:STANDARD
|
||||
TZNAME:EST
|
||||
TZOFFSETFROM:-0400
|
||||
TZOFFSETTO:-0500
|
||||
DTSTART:20071104T020000
|
||||
RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
|
||||
END:STANDARD
|
||||
BEGIN:DAYLIGHT
|
||||
TZNAME:EDT
|
||||
TZOFFSETFROM:-0500
|
||||
TZOFFSETTO:-0400
|
||||
DTSTART:20070311T020000
|
||||
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
|
||||
END:DAYLIGHT
|
||||
END:VTIMEZONE
|
||||
END:VCALENDAR
|
||||
</cal:calendar-data>
|
||||
</d:prop>
|
||||
<d:status>HTTP/1.1 200 OK</d:status>
|
||||
</d:propstat>
|
||||
</d:response>
|
||||
<d:response>
|
||||
<d:href>/dav.php/calendars/alex/personal/gone.ics</d:href>
|
||||
<d:propstat>
|
||||
<d:prop>
|
||||
<d:getetag/>
|
||||
<cal:calendar-data/>
|
||||
</d:prop>
|
||||
<d:status>HTTP/1.1 404 Not Found</d:status>
|
||||
</d:propstat>
|
||||
</d:response>
|
||||
</d:multistatus>
|
||||
Reference in New Issue
Block a user