arnaudq's blog
use of email addresses as calendar user addresses
The iCalendar standard defines the notion of organizer and attendees (users, groups, resources,...) for scheduling purpose. Those are identified by "calendar user addresses" which in practice are generally mailto: URIs:
ORGANIZER;CN=Ciy:mailto:ciny@example.com ATTENDEE;CN=Ciny;PARTSTAT=ACCEPTED:mailto:ciny@example.com ATTENDEE;CN=Arnaud;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:mailto:arnaudq@example.com
The CalDAV scheduling draft offers a way for a client to discover which calendar user addresses are associated with a particular user through the use of the CALDAV:calendar-user-address-set property.
This property can then be used in different ways, depending on the context:
- When creating a meeting invitation, it can be used to set the ORGANIZER property value.
- When fetching events from the server, it can be used to determine whether the owner of the calendar is the organizer or an attendee of the meeting by comparing the addresses returned in the calendar-user-address-set with the ORGANIZER and ATTENDEE values.
Client applications need to take into account a few points when doing this comparison though:
First of all, the calendar-user-address-set property is multivalued: a user may have both mailto:arnaudq@example.com and mailto:arnaud.quillaud@example.com defined as valid calendar addresses. So CUAs need to look for both values when comparing with the ORGANIZER/ATTENDEE values.
Then, when using mailto: URIs, there is no clear definition of how two such URIs should be compared for equality (as far as I know). For example, if one follows the SMTP definition, the local part of an email address is case sensitive. In the context of a calendar client though, I think it makes sense to:
- try to preserve the original case when storing calendar addresses.
- but do case insensitive comparison wherever a comparison is required.
Posted at 04:15PM Jan 18, 2010 by arnaudq in CalDAV | Comments[0]
Bundling iTIP REQUESTs
When conveying information about a recurring VEVENT or VTODO, iTIP REQUEST messages usually take one of two forms:
Either they contain a full calendar object, i.e. master + exceptions (from RFC2446-bis):
BEGIN:VCALENDAR
METHOD:REQUEST
PRODID:-//Example/ExampleCalendarClient//EN
VERSION:2.0
BEGIN:VEVENT
UID:123456789@example.com
SEQUENCE:2
RDATE:19980304T180000Z
RDATE:19980311T160000Z
RDATE:19980315T180000Z
ORGANIZER:mailto:a@example.com
ATTENDEE;ROLE=CHAIR;PARTSTAT=ACCEPTED:mailto:a@example.com
ATTENDEE;RSVP=TRUE:mailto:b@example.com
SUMMARY:Review Accounts
DTSTART:19980304T180000Z
DTEND:19980304T200000Z
DTSTAMP:19980303T193000Z
LOCATION:Conference Room A
STATUS:CONFIRMED
END:VEVENT
BEGIN:VEVENT
UID:123456789@example.com
SEQUENCE:2
RECURRENCE-ID:19980311T160000Z
ATTENDEE;ROLE=CHAIR;PARTSTAT=ACCEPTED:mailto:a@example.com
ATTENDEE;RSVP=TRUE:mailto:b@example.com
SUMMARY:Review Accounts
DTSTART:19980311T160000Z
DTEND:19980304T180000Z
DTSTAMP:19980306T193000Z
LOCATION:The Small conference room
STATUS:CONFIRMED
END:VEVENT
END:VCALENDAR
or they contain a single instance:
BEGIN:VCALENDAR
METHOD:REQUEST
PRODID:-//Example/ExampleCalendarClient//EN
VERSION:2.0
BEGIN:VEVENT
UID:123456789@example.com
SEQUENCE:1
RECURRENCE-ID:19980311T180000Z
ORGANIZER:mailto:a@example.com
ATTENDEE;ROLE=CHAIR;PARTSTAT=ACCEPTED:mailto:a@example.com
ATTENDEE;RSVP=TRUE:mailto:b@example.com
SUMMARY:Review Accounts
DTSTART:19980311T160000Z
DTEND:19980311T180000Z
DTSTAMP:19980306T193000Z
LOCATION:The Small conference room
STATUS:CONFIRMED
END:VEVENT
END:VCALENDAR
That is at least my observation. I'm having trouble finding out whether:
- this is just me making assumptions,
- this is mandated by iTIP/iTIP-bis (but where ?), or by some unwritten convention,
- this is an artifact of how calendar clients interaction usually works (typically the user can change either all instances or one single instance).
Sending only the master or the master + just a few exceptions could only be interpreted on the attendee side as meaning that the missing exceptions are no longer exceptions (?...). This does not make much sense.
But what about sending multiple instances with different RECURRENCE-ID in one single REQUEST ? For example, one could well change the description of one instance, and reschedule another instance by changing its DTSTART. Bundling those 2 instances into a single REQUEST could make sense. Another scenario is one where an attendee is added to only 3 instances of a recurring event. It seems natural to group those 3 instances into one REQUEST when sending the invitation to this attendee.
But is it legal to do so ? And, more importantly, are clients ready to consume this type of message ?
Posted at 03:24PM Dec 15, 2009 by arnaudq in CalDAV | Comments[0]
subcollections under calendar collections
To synchronize a calendar collection, clients typically issue a PROPFIND with Depth = 1 on the calendar collection, asking for the DAV:getetag property.
>> Request << PROPFIND /dav/home/arnaudq@example.com/calendar/ HTTP/1.1 host: localhost:8080 depth: 1 content-type: text/xml <?xml version="1.0" encoding="utf-8"?> <x0:propfind xmlns:x0="DAV:"> <x0:prop> <x0:getetag/> </x0:prop> </x0:propfind> >> Response << HTTP/1.1 207 Multi-Status Content-Type: application/xml; charset="utf-8" <?xml version="1.0" encoding="UTF-8"?><D:multistatus xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav"> <D:response> <D:href>/dav/home/arnaudq@example.com/calendar/</D:href> <D:propstat> <D:prop> <D:getetag/> </D:prop> <D:status>HTTP/1.1 404 Not Found</D:status> </D:propstat> </D:response> <D:response> <D:href>/dav/home/arnaudq@example.com/calendar/dd5b7d18-837b-2249-995e-765d5fc240e9.ics</D:href> <D:propstat> <D:prop> <D:getetag>"1259672377000.2"</D:getetag> </D:prop> <D:status>HTTP/1.1 200 OK</D:status> </D:propstat> </D:response> <D:response> <D:href>/dav/home/arnaudq@example.com/calendar/c14358f8-9b94-6e44-af3a-d728d336800b.ics</D:href> <D:propstat> <D:prop> <D:getetag>"1259672497000.2"</D:getetag> </D:prop> <D:status>HTTP/1.1 200 OK</D:status> </D:propstat> </D:response> </D:multistatus>
All resources directly under the calendar collection will be returned.
Among those, the client should be prepared to see WebDAV collections. While the CalDAV specification forbids calendar collections to contain other calendar collections (at any depth), having a basic WebDAV collection under a calendar collection is legal. To filter them out, a client can either rely on the DAV:href of each returned resource (collection URIs end with a "/" character), or ask for the DAV:resourcetype property:
In the example above, the calendar collection contains an "attachments" subcollection. CalDAV clients can simply ignore it, based on the value of its DAV:resourcetype property which is not empty.>> Request << PROPFIND /dav/home/arnaudq@example.com/calendar/ HTTP/1.1 host: localhost:8080 depth: 1 content-type: text/xml <?xml version="1.0" encoding="utf-8"?> <x0:propfind xmlns:x0="DAV:"> <x0:prop> <x0:getetag/> <x0:resourcetype/> </x0:prop> </x0:propfind> >> Response << HTTP/1.1 207 Multi-Status Content-Type: application/xml; charset="utf-8" <?xml version="1.0" encoding="UTF-8"?><D:multistatus xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav" xmlns:M="urn:ietf:params:xml:ns:carddav"> <D:response> <D:href>/dav/home/arnaudq@example.com/calendar/</D:href> <D:propstat> <D:prop> <D:resourcetype><C:calendar/><D:collection/></D:resourcetype> </D:prop> <D:status>HTTP/1.1 200 OK</D:status> </D:propstat> <D:propstat> <D:prop> <D:getetag/> </D:prop> <D:status>HTTP/1.1 404 Not Found</D:status> </D:propstat> </D:response> <D:response> <D:href>/dav/home/arnaudq@example.com/calendar/dd5b7d18-837b-2249-995e-765d5fc240e9.ics</D:href> <D:propstat> <D:prop> <D:getetag>"1259672377000.2"</D:getetag> <D:resourcetype></D:resourcetype> </D:prop> <D:status>HTTP/1.1 200 OK</D:status> </D:propstat> </D:response> <D:response> <D:href>/dav/home/arnaudq@example.com/calendar/attachments/</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:getetag/> </D:prop> <D:status>HTTP/1.1 404 Not Found</D:status> </D:propstat> </D:response> </D:multistatus>
Posted at 03:57PM Dec 01, 2009 by arnaudq in CalDAV | Comments[3]
DAV:current-user-privilege-set
The DAV:current-user-privilege-set WebDAV ACL property allows a client application to know what operations the currently authenticated user can issue on a WebDAV resource (read, read-write, etc...).
Until now, I was under the impression that servers should return only the top level privileges (aggregate or not).
For example, given a server with the following supported set (note that DAV:all is not abstract):
[DAV:, all] (aggregate)
|
+-- [DAV:, read] (aggregate)
|
+-- [DAV:, read-acl] (abstract)
+-- [DAV:, read-current-user-privilege-set] (abstract)
|
+-- [DAV:, write] (aggregate)
|
+-- [DAV:, write-acl] (abstract)
+-- [DAV:, write-properties]
+-- [DAV:, write-content]
and a user with all rights on a resource, I was expecting the following DAV:current-user-privilege-set:
<D:current-user-privilege-set>
<D:privilege><D:all/></D:privilege>
</D:current-user-privilege-set>
But the WebDAV ACL specification clearly states that "Aggregate privileges and their contained privileges are listed". So what the server should return is really the full set:
<D:current-user-privilege-set>
<D:privilege><D:all/></D:privilege>
<D:privilege><D:read/></D:privilege>
<D:privilege><D:write/></D:privilege>
<D:privilege><D:write-properties/></D:privilege>
<D:privilege><D:write-content/></D:privilege>
</D:current-user-privilege-set>
I guess this makes client implementers life easier.
Posted at 03:15PM Nov 02, 2009 by arnaudq in CalDAV | Comments[3]
More CalDAV enabled phones... starting with Symbian ?
The iPhone might be the first CalDAV enabled phone but hopefully, it won't be long before other start to appear.
My colleague Maximilian Odendahl has been working on a CalDAV provider for the native Symbian OS Calendar application for a few months now.
He started with a standalone application that syncs up one or more CalDAV accounts using the native Calendar database API (using WebDAV Sync when appropriate).
This is already working great. Here is a screenshot of the native Calendar application, showing events pulled from our hosted preview server:

Now that Sun Microsystems has joined the Symbian foundation, Max will be able to fully integrate his CalDAV provider into the native application, for example to allow direct configuration of an account (image below is still a mockup):

More info on his work at http://developer.symbian.org/wiki/index.php/CalDav.
(Can't resist to mention that after testing his client against 8 different servers, he found the next generation Sun Calendar Server to be the most standard compliant ...)
Posted at 10:49AM Aug 04, 2009 by arnaudq in CalDAV | Comments[4]