When you set the account type to Automatic, as explained in my previous blog post, iCal will do a DNS query to find out what is the host name of the CalDAV server. If a SRV DNS entry have been found, iCal will get the hostname and TCP port from the SRV entry, and will do the following (here, I'm assuming that the CalDAV server found in the SRV entry is "server.macti.lan" and the TCP port is 8008):
- Do a PROPFIND (WebDAV method) request on http://server.macti.lan:80/.well-known/caldav with the following body:
<?xml version="1.0" encoding="UTF-8"?>
<A:propfind xmlns:A="DAV:">
<A:prop>
<A:current-user-principal/>
<A:principal-URL/>
<A:resourcetype/>
</A:prop>
</A:propfind> - If iCal didn't get a valid response on port 80, it will try the same request, but on port 8080 instead.
- If iCal didn't get a valid response on port 80 or 8080, it will try on the port it found in the SRV entry, in our case, port 8008.
The response from /.well-known/caldav might be a redirect (HTTP status code 301 or 302). In fact, that's what iCal Server 10.8 does, it redirect the request to http://server.macti.lan:8008/. So again, iCal will do the same request as before until it gets a 207 status code instead of a redirect. The response will look like this:
The value we need is the value of current-user-principal, which indicates the location of the user's "principals". With this value, iCal will make a OPTIONS request to /principals/__uids__/C0F07FAF-A20A-4A88-A518-D27E5D3074CA/. I don't know why iCal is making the request, but my guess it's doing it so that it can find which CalDAV features are supported by the CalDAV server. That list is available in the response's DAV header:
<?xml version='1.0' encoding='UTF-8'?>
<multistatus xmlns='DAV:'>
<response>
<href>/</href>
<propstat>
<prop>
<current-user-principal>
<href>/principals/__uids__/C0F07FAF-A20A-4A88-A518-D27E5D3074CA/</href>
</current-user-principal>
<resourcetype>
<collection/>
</resourcetype>
</prop>
<status>HTTP/1.1 200 OK</status>
</propstat>
</response>
</multistatus>
DAV: 1, access-control, calendar-access, calendar-schedule, calendar-auto-schedule, calendar-availability, inbox-availability, calendar-proxy, calendarserver-private-events, calendarserver-private-comments, calendarserver-sharing, calendarserver-sharing-no-scheduling, calendar-query-extended, calendar-default-alarms, addressbook, extended-mkcol, calendarserver-principal-property-searchThis is a response from iCal Server 10.8, which supports all CalDAV features and extensions. Doing the same request to a Google Calendar server will return a lot less features/extensions.
Following the OPTIONS request, iCal will make a PROPFIND request on the same URL as the OPTIONS request, with the following body:
<?xml version="1.0" encoding="UTF-8"?>The value that we need back from this request is the value of the calendar-home-set property. This property is the URL to calendar collections. So iCal can finally found where the calendars are, and it will do a PROPFIND request to the URL found with the value of calendar-home-set. The body of that PROPFIND request is quite large so I'm not going to past it here, but in short, that PROPFIND will find the request properties for each sub-collections in the main calendar collection. For example, if the main collection is located at:
<A:propfind xmlns:A="DAV:">
<A:prop>
<C:calendar-home-set xmlns:C="urn:ietf:params:xml:ns:caldav"/>
<C:calendar-user-address-set xmlns:C="urn:ietf:params:xml:ns:caldav"/>
<A:current-user-principal/>
<A:displayname/>
<B:dropbox-home-URL xmlns:B="http://calendarserver.org/ns/"/>
<B:email-address-set xmlns:B="http://calendarserver.org/ns/"/>
<B:notification-URL xmlns:B="http://calendarserver.org/ns/"/>
<A:principal-collection-set/>
<A:principal-URL/>
<A:resource-id/>
<C:schedule-inbox-URL xmlns:C="urn:ietf:params:xml:ns:caldav"/>
<C:schedule-outbox-URL xmlns:C="urn:ietf:params:xml:ns:caldav"/> <A:supported-report-set/>
</A:prop>
</A:propfind>
/calendars/__uids__/0B9B4FA7-8ADC-4984-8258-D04A4939A574/The "calendar" collection will be located at:
/calendars/__uids__/0B9B4FA7-8ADC-4984-8258-D04A4939A574/calendar/And the "tasks" collection:
/calendars/__uids__/0B9B4FA7-8ADC-4984-8258-D04A4939A574/tasksSo, for each sub-collection, iCal will do the following:
- A PROPFIND request to find the value of the checksum-versions property;
- A PROPFIND request to find the value of the getctag and sync-token properties;
- A PROPFIND request to find the value of the getcontenttype and getetag properties;
The third request, who fetches the content type and etag, is the one that will return a link to all iCalendar objects from the calendar collection. The response will return a <response> XML attribute for each iCalendar objects, with the following structure:
<response>From there, iCal will simply fetch all valid iCalendar objects and display them in the calendar window. This is done by doing a REPORT request on the calendar collection, with the calendar-multiget attribute, with the list of calendar objects that the previous PROPFIND response have returned.
<href>/calendars/__uids__/C0F07FAF-A20A-4A88-A518-D27E5D3074CA/calendar/20111210T013923Z-uidGen%40mbp-pascal-robert-4.local.ics</href>
<propstat>
<prop>
<getcontenttype>text/calendar;charset=utf-8</getcontenttype>
<getetag>"9b6b2d11f86891f748ef09ab0993b75c"</getetag>
</prop>
<status>HTTP/1.1 200 OK</status>
</propstat>
</response>
<?xml version="1.0" encoding="UTF-8"?><B:calendar-multiget xmlns:B="urn:ietf:params:xml:ns:caldav"> <A:prop xmlns:A="DAV:"> <A:getetag/> <B:calendar-data/> <C:updated-by xmlns:C="http://calendarserver.org/ns/"/> <C:created-by xmlns:C="http://calendarserver.org/ns/"/> </A:prop> <A:href xmlns:A="DAV:">/calendars/__uids__/C0F07FAF-A20A-4A88-A518-D27E5D3074CA/calendar/20111210T013923Z-uidGen%40mbp-pascal-robert-4.local.ics</A:href></B:calendar-multiget>This is the response:
<D:multistatus xmlns:D="DAV:"> <D:response> <D:href>/calendars/__uids__/C0F07FAF-A20A-4A88-A518-D27E5D3074CA/calendar/20111210T013923Z-uidGen%40mbp-pascal-robert-4.local.ics</D:href> <D:propstat> <D:status>HTTP/1.1 200 OK</D:status> <D:prop> <D:getetag>"63459166486"</D:getetag> <C:calendar-data xmlns:C="urn:ietf:params:xml:ns:caldav"> BEGIN:VCALENDAR PRODID:-//Google Inc//Google Calendar 70.9054//EN VERSION:2.0 CALSCALE:GREGORIAN X-WR-CALNAME:Pascal Robert X-WR-TIMEZONE:America/New_York BEGIN:VEVENT DTSTART:20111209T140000Z DTEND:20111209T180000Z DTSTAMP:20111210T021446Z ORGANIZER;CN=probert@macti.lan:mailto:probert@macti.lan UID:20111210T021447Z-uidGen@mbp-pascal-robert-4.local ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;CN=Pascal Robert;X-NUM-GUESTS=0:mailto:pascal.probert@gmail.com CLASS:CONFIDENTIAL CREATED:20111210T021446Z DESCRIPTION:Un plus long texte LAST-MODIFIED:20111210T021446Z LOCATION:Un endroit SEQUENCE:0 STATUS:CONFIRMED SUMMARY:Événement test TRANSP:OPAQUE BEGIN:VALARM ACTION:DISPLAY DESCRIPTION:This is an event reminder TRIGGER:-P0DT0H30M0S END:VALARM BEGIN:VALARM ACTION:AUDIO TRIGGER;VALUE=DATE-TIME:20111209T134500Z END:VALARM END:VEVENT END:VCALENDAR </C:calendar-data> </D:prop> </D:propstat> <D:propstat> <D:status>HTTP/1.1 404 Not Found</D:status> <D:prop> <C:updated-by xmlns:C="http://calendarserver.org/ns/" /> <C:created-by xmlns:C="http://calendarserver.org/ns/" /> </D:prop> </D:propstat> </D:response> </D:multistatus>
No comments:
Post a Comment