RFC 4791

Calendaring Extensions to WebDAV (CalDAV)

๐Ÿ“… published March 2007, from ietf

RFC 4791: Calendaring Extensions to WebDAV (CalDAV) ๐Ÿฆ‹

okay bestie, this one is the CalDAV spec, and it's giving calendar-sync main character energy โœจ. It's a Standards Track document from March 2007. The authors are C. Daboo (Apple), B. Desruisseaux (Oracle), and L. Dusseault (CommerceNet). The header doesn't list any RFCs it obsoletes or updates, so it's a fresh start ๐ŸŒธ.

Status of This Memo ๐Ÿ“œ

ok so this doc is an Internet standards track protocol for the Internet community ๐Ÿ’…. It's basically asking everyone to talk about it and send over ideas for making it better ๐Ÿซถ. For the current standardization state and status, check the latest version of the "Internet Official Protocol Standards" (STD 1) ๐Ÿ”. And distribution of this memo is totally unlimited ๐ŸŒˆ.

The IETF Trust holds the copyright, dated 2007 ๐Ÿ’œ.

Abstract ๐ŸŽ€

so the main idea is this ๐Ÿ’–: it takes WebDAV, which is the web-based authoring and versioning protocol, and adds extensions so you can access, manage, and share calendar and scheduling info in a standard way. The data is based on the iCalendar format ๐Ÿ“…. It also defines the "calendar-access" feature of CalDAV, which is the core of the whole thing ๐Ÿ‘‘.

Table of Contents ๐Ÿ—‚๏ธ

Table of Contents

   1.  Introduction . . . . . . . . . . . . . . . . . . . . . . . . .  5
     1.1.  Notational Conventions . . . . . . . . . . . . . . . . . .  5
     1.2.  XML Namespaces and Processing  . . . . . . . . . . . . . .  5
     1.3.  Method Preconditions and Postconditions  . . . . . . . . .  6
   2.  Requirements Overview  . . . . . . . . . . . . . . . . . . . .  6
   3.  Calendaring Data Model . . . . . . . . . . . . . . . . . . . .  7
     3.1.  Calendar Server  . . . . . . . . . . . . . . . . . . . . .  7
     3.2.  Recurrence and the Data Model  . . . . . . . . . . . . . .  8
   4.  Calendar Resources . . . . . . . . . . . . . . . . . . . . . .  9
     4.1.  Calendar Object Resources  . . . . . . . . . . . . . . . .  9
     4.2.  Calendar Collection  . . . . . . . . . . . . . . . . . . . 10
   5.  Calendar Access Feature  . . . . . . . . . . . . . . . . . . . 11
     5.1.  Calendar Access Support  . . . . . . . . . . . . . . . . . 11
       5.1.1.  Example: Using OPTIONS for the Discovery of
               Calendar Access Support  . . . . . . . . . . . . . . . 12
     5.2.  Calendar Collection Properties . . . . . . . . . . . . . . 12
       5.2.1.  CALDAV:calendar-description Property . . . . . . . . . 12
       5.2.2.  CALDAV:calendar-timezone Property  . . . . . . . . . . 13
       5.2.3.  CALDAV:supported-calendar-component-set Property . . . 14
       5.2.4.  CALDAV:supported-calendar-data Property  . . . . . . . 15
       5.2.5.  CALDAV:max-resource-size Property  . . . . . . . . . . 16
       5.2.6.  CALDAV:min-date-time Property  . . . . . . . . . . . . 17
       5.2.7.  CALDAV:max-date-time Property  . . . . . . . . . . . . 18
       5.2.8.  CALDAV:max-instances Property  . . . . . . . . . . . . 19
       5.2.9.  CALDAV:max-attendees-per-instance Property . . . . . . 19
       5.2.10. Additional Precondition for PROPPATCH  . . . . . . . . 20
     5.3.  Creating Resources . . . . . . . . . . . . . . . . . . . . 20
       5.3.1.  MKCALENDAR Method  . . . . . . . . . . . . . . . . . . 20
         5.3.1.1.  Status Codes . . . . . . . . . . . . . . . . . . . 22
         5.3.1.2.  Example: Successful MKCALENDAR Request . . . . . . 23
       5.3.2.  Creating Calendar Object Resources . . . . . . . . . . 25
         5.3.2.1.  Additional Preconditions for PUT, COPY, and
                   MOVE . . . . . . . . . . . . . . . . . . . . . . . 26
       5.3.3.  Non-Standard Components, Properties, and Parameters  . 28
       5.3.4.  Calendar Object Resource Entity Tag  . . . . . . . . . 28
   6.  Calendaring Access Control . . . . . . . . . . . . . . . . . . 29
     6.1.  Calendaring Privilege  . . . . . . . . . . . . . . . . . . 29
       6.1.1.  CALDAV:read-free-busy Privilege  . . . . . . . . . . . 29
     6.2.  Additional Principal Property  . . . . . . . . . . . . . . 30
       6.2.1.  CALDAV:calendar-home-set Property  . . . . . . . . . . 30
   7.  Calendaring Reports  . . . . . . . . . . . . . . . . . . . . . 31
     7.1.  REPORT Method  . . . . . . . . . . . . . . . . . . . . . . 31
     7.2.  Ordinary Collections . . . . . . . . . . . . . . . . . . . 31
     7.3.  Date and Floating Time . . . . . . . . . . . . . . . . . . 32
     7.4.  Time Range Filtering . . . . . . . . . . . . . . . . . . . 32
     7.5.  Searching Text: Collations . . . . . . . . . . . . . . . . 33

       7.5.1.  CALDAV:supported-collation-set Property  . . . . . . . 34
     7.6.  Partial Retrieval  . . . . . . . . . . . . . . . . . . . . 34
     7.7.  Non-Standard Components, Properties, and Parameters  . . . 35
     7.8.  CALDAV:calendar-query REPORT . . . . . . . . . . . . . . . 36
       7.8.1.  Example: Partial Retrieval of Events by Time Range . . 38
       7.8.2.  Example: Partial Retrieval of Recurring Events . . . . 42
       7.8.3.  Example: Expanded Retrieval of Recurring Events  . . . 45
       7.8.4.  Example: Partial Retrieval of Stored Free Busy
               Components . . . . . . . . . . . . . . . . . . . . . . 48
       7.8.5.  Example: Retrieval of To-Dos by Alarm Time Range . . . 50
       7.8.6.  Example: Retrieval of Event by UID . . . . . . . . . . 51
       7.8.7.  Example: Retrieval of Events by PARTSTAT . . . . . . . 53
       7.8.8.  Example: Retrieval of Events Only  . . . . . . . . . . 55
       7.8.9.  Example: Retrieval of All Pending To-Dos . . . . . . . 59
       7.8.10. Example: Attempt to Query Unsupported Property . . . . 62
     7.9.  CALDAV:calendar-multiget REPORT  . . . . . . . . . . . . . 63
       7.9.1.  Example: Successful CALDAV:calendar-multiget REPORT  . 64
     7.10. CALDAV:free-busy-query REPORT  . . . . . . . . . . . . . . 66
       7.10.1. Example: Successful CALDAV:free-busy-query REPORT  . . 68
   8.  Guidelines . . . . . . . . . . . . . . . . . . . . . . . . . . 69
     8.1.  Client-to-Client Interoperability  . . . . . . . . . . . . 69
     8.2.  Synchronization Operations . . . . . . . . . . . . . . . . 69
       8.2.1.  Use of Reports . . . . . . . . . . . . . . . . . . . . 69
         8.2.1.1.  Restrict the Time Range  . . . . . . . . . . . . . 69
         8.2.1.2.  Synchronize by Time Range  . . . . . . . . . . . . 70
         8.2.1.3.  Synchronization Process  . . . . . . . . . . . . . 70
       8.2.2.  Restrict the Properties Returned . . . . . . . . . . . 72
     8.3.  Use of Locking . . . . . . . . . . . . . . . . . . . . . . 72
     8.4.  Finding Calendars  . . . . . . . . . . . . . . . . . . . . 72
     8.5.  Storing and Using Attachments  . . . . . . . . . . . . . . 74
       8.5.1.  Inline Attachments . . . . . . . . . . . . . . . . . . 74
       8.5.2.  External Attachments . . . . . . . . . . . . . . . . . 75
     8.6.  Storing and Using Alarms . . . . . . . . . . . . . . . . . 76
   9.  XML Element Definitions  . . . . . . . . . . . . . . . . . . . 77
     9.1.  CALDAV:calendar XML Element  . . . . . . . . . . . . . . . 77
     9.2.  CALDAV:mkcalendar XML Element  . . . . . . . . . . . . . . 77
     9.3.  CALDAV:mkcalendar-response XML Element . . . . . . . . . . 78
     9.4.  CALDAV:supported-collation XML Element . . . . . . . . . . 78
     9.5.  CALDAV:calendar-query XML Element  . . . . . . . . . . . . 78
     9.6.  CALDAV:calendar-data XML Element . . . . . . . . . . . . . 79
       9.6.1.  CALDAV:comp XML Element  . . . . . . . . . . . . . . . 80
       9.6.2.  CALDAV:allcomp XML Element . . . . . . . . . . . . . . 81
       9.6.3.  CALDAV:allprop XML Element . . . . . . . . . . . . . . 81
       9.6.4.  CALDAV:prop XML Element  . . . . . . . . . . . . . . . 82
       9.6.5.  CALDAV:expand XML Element  . . . . . . . . . . . . . . 82
       9.6.6.  CALDAV:limit-recurrence-set XML Element  . . . . . . . 83
       9.6.7.  CALDAV:limit-freebusy-set XML Element  . . . . . . . . 84
     9.7.  CALDAV:filter XML Element  . . . . . . . . . . . . . . . . 85

       9.7.1.  CALDAV:comp-filter XML Element . . . . . . . . . . . . 85
       9.7.2.  CALDAV:prop-filter XML Element . . . . . . . . . . . . 86
       9.7.3.  CALDAV:param-filter XML Element  . . . . . . . . . . . 87
       9.7.4.  CALDAV:is-not-defined XML Element  . . . . . . . . . . 88
       9.7.5.  CALDAV:text-match XML Element  . . . . . . . . . . . . 88
     9.8.  CALDAV:timezone XML Element  . . . . . . . . . . . . . . . 89
     9.9.  CALDAV:time-range XML Element  . . . . . . . . . . . . . . 90
     9.10. CALDAV:calendar-multiget XML Element . . . . . . . . . . . 94
     9.11. CALDAV:free-busy-query XML Element . . . . . . . . . . . . 95
   10. Internationalization Considerations  . . . . . . . . . . . . . 95
   11. Security Considerations  . . . . . . . . . . . . . . . . . . . 95
   12. IANA Considerations  . . . . . . . . . . . . . . . . . . . . . 96
     12.1. Namespace Registration . . . . . . . . . . . . . . . . . . 96
   13. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . 96
   14. References . . . . . . . . . . . . . . . . . . . . . . . . . . 97
     14.1. Normative References . . . . . . . . . . . . . . . . . . . 97
     14.2. Informative References . . . . . . . . . . . . . . . . . . 98
   Appendix A.  CalDAV Method Privilege Table (Normative) . . . . . . 99
   Appendix B.  Calendar Collections Used in the Examples . . . . . . 99

1. Introduction ๐ŸŒธ

okay so using HTTP [RFC2616] and WebDAV [RFC2518] as the base for a calendar access protocol is not a new idea at all ๐Ÿ™ˆ. People were talking about it in the IETF CALSCH working group way back in 1997 or 1998. Lots of companies built calendar access protocols that used HTTP to upload and download iCalendar [RFC2445] objects and used WebDAV to list resources ๐Ÿ“…. The problem is they didn't play nicely with each other ๐Ÿ’€, because there are SO many small and big choices to make about how calendar data gets modeled as WebDAV resources, and how to build the features WebDAV doesn't already have. This document is the answer ๐Ÿ’–: it proposes a way to model calendar data in WebDAV and adds the extra features needed for a calendar access protocol that actually interoperates โœจ.

1.1. Notational Conventions ๐ŸŽ€

the key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be read as described in [RFC2119] ๐Ÿ”ฅ. These are the official BCP 14 vibes, so pay attention to them ๐Ÿซถ.

The term "protected" shows up in the Conformance field of property definitions, and it's defined in Section 1.4.2 of [RFC3253] ๐Ÿ’….

When XML element types from the namespaces "DAV:" and "urn:ietf:params:xml:ns:caldav" get mentioned outside of an XML fragment, the strings DAV: and CALDAV: get stuck on the front of the element type names, respectively ๐Ÿงš.


1.2. XML Namespaces and Processing โœจ

okay so the XML elements in this doc are defined with XML element type declarations (the kind you find in XML Document Type Declarations), described in Section 3.2 of [W3C.REC-xml-20060816] ๐Ÿงš

The namespace urn:ietf:params:xml:ns:caldav is reserved for the XML elements defined in this spec, its revisions, and related CalDAV specs ๐Ÿ’œ. XML elements defined by individual implementations MUST NOT use the urn:ietf:params:xml:ns:caldav namespace, and instead should use a namespace that they control ๐Ÿซถ.

heads up: the XML declarations in this doc don't include namespace info ๐Ÿ™ˆ. So implementers must not treat them as the only way to make valid CalDAV properties or to validate CalDAV XML element types. Some of the declarations point at XML elements from WebDAV [RFC2518], which use the DAV: namespace, so wherever those show up they get the DAV: prefix to avoid confusion ๐Ÿ’….

also, some CalDAV XML element names are identical to WebDAV element names, even though their namespaces are different. Be careful not to mix the two sets up ๐Ÿ˜ญ.

Processing of XML by CalDAV clients and servers MUST follow the rules described in [RFC2518]; in particular, Section 14 and Appendix 3 of that specification ๐ŸŽ€.

1.3. Method Preconditions and Postconditions ๐ŸŒธ

a "precondition" of a method describes the state of the server that must be true for that method to be performed ๐Ÿซง. a "postcondition" describes the state of the server that must be true after the method has been completed. If a method precondition or postcondition for a request isn't satisfied, the response status of the request MUST either be 403 (Forbidden), if the request shouldn't be repeated because it will always fail, or 409 (Conflict), if the user might be able to resolve the conflict and resubmit the request ๐Ÿ™…โ€โ™€๏ธ.

To help clients handle 403 and 409 responses better, every method precondition and postcondition gets its own distinct XML element type ๐ŸŽ€. When a particular precondition isn't satisfied or a particular postcondition can't be achieved, the appropriate XML element MUST be returned as the child of a top-level DAV:error element in the response body, unless otherwise negotiated by the request โœจ.

2. Requirements Overview โญ

this section lists what functionality is required of a CalDAV server ๐Ÿ“‹. To advertise support for CalDAV, a server:

  • MUST support iCalendar [RFC2445] as a media type for the calendar object resource format;
  • MUST support WebDAV Class 1 [RFC2518] (note that [rfc2518bis] describes clarifications to [RFC2518] that aid interoperability);
  • MUST support WebDAV ACL [RFC3744] with the additional privilege defined in Section 6.1 of this document;
  • MUST support transport over TLS [RFC2246] as defined in [RFC2818] (note that [RFC2246] has been obsoleted by [RFC4346]);
  • MUST support ETags [RFC2616] with additional requirements specified in Section 5.3.4 of this document;
  • MUST support all calendaring reports defined in Section 7 of this document; and
  • MUST advertise support on all calendar collections and calendar object resources for the calendaring reports in the DAV:supported-report-set property, as defined in Versioning Extensions to WebDAV [RFC3253].

In addition, a server:

  • SHOULD support the MKCALENDAR method defined in Section 5.3.1 of this document.

3. Calendaring Data Model ๐Ÿฆ‹

one of the features that has made WebDAV a successful protocol is its firm data model ๐Ÿ’Ž. That makes it a useful framework for other apps, like calendaring. This spec follows the same pattern: every feature is built on a well-described data model ๐Ÿง .

as a quick overview, a CalDAV calendar is modeled as a WebDAV collection with a defined structure. Each calendar collection holds a bunch of resources, each one representing a calendar object, as its direct child resources ๐Ÿ“…. Each resource that represents a calendar object (an event, a to-do, a journal entry, or other calendar components) is called a "calendar object resource" ๐ŸŽŸ๏ธ. Each calendar object resource and each calendar collection can be individually locked and can have individual WebDAV properties ๐Ÿ”’. The requirements that come from this model are in Section 4.1 and Section 4.2.

3.1. Calendar Server

a CalDAV server is a calendaring-aware engine combined with a WebDAV repository ๐Ÿ–ฅ๏ธ. A WebDAV repository is a set of WebDAV collections, containing other WebDAV resources, all inside one unified URL namespace. For example, the repository "http://www.example.com/webdav/" may contain WebDAV collections and resources, and all of them have URLs beginning with "http://www.example.com/webdav/" ๐ŸŒ. Note that the root URL, "http://www.example.com/", may not itself be a WebDAV repository (for example, if the WebDAV support is implemented through a servlet or other Web server extension) ๐Ÿค“.

A WebDAV repository MAY include calendar data in some parts of its URL namespace, and non-calendaring data in other parts ๐Ÿ—‚๏ธ.

A WebDAV repository can advertise itself as a CalDAV server if it supports the functionality defined in this specification at any point within the root of the repository ๐Ÿ“ฃ. That might mean calendar data is spread throughout the repository and mixed with non-calendar data in nearby collections (e.g., calendar data may be found in /home/lisa/calendars/ as well as in /home/bernard/calendars/, and non-calendar data in /home/lisa/contacts/) ๐Ÿ“. Or it might mean calendar data can only be found in certain sections of the repository (e.g., /calendar/) ๐ŸŽ€. Calendaring features are only required in the repository sections that are or contain calendar object resources ๐Ÿ’…. So a repository confining calendar data to the /calendar/ collection would only need to support the CalDAV required features within that collection ๐Ÿซถ.

The CalDAV server or repository is the canonical location for calendar data and state information ๐Ÿ‘‘. Clients may submit requests to change data or download data. Clients may store calendar objects offline and attempt to synchronize at a later time ๐Ÿ“ด. However, clients MUST be prepared for calendar data on the server to change between the time of last synchronization and when attempting an update, because calendar collections may be shared and accessible via multiple clients ๐Ÿ‘ฏโ€โ™€๏ธ. Entity tags and other features make this possible ๐Ÿท๏ธ.

3.2. Recurrence and the Data Model ๐Ÿ”

recurrence is a big part of the data model because it governs how many resources are expected to exist ๐Ÿงฎ. This spec models a recurring calendar component and its recurrence exceptions as a single resource ๐ŸŽ. In this model, recurrence rules, recurrence dates, exception rules, and exception dates are all part of the data in one single calendar object resource. This avoids problems like limiting how many recurrence instances to store in the repository, how to keep recurrence instances in sync with the recurring calendar component, and how to link recurrence exceptions with the recurring calendar component ๐Ÿ™Œ. It also means less data to synchronize between client and server, and it makes it easier to change all recurrence instances or a recurrence rule ๐Ÿช„. It's also easier to create a recurring calendar component and to delete all recurrence instances ๐Ÿ—‘๏ธ.

Clients aren't forced to retrieve info about all recurrence instances of a recurring component ๐Ÿฅฐ. The CALDAV:calendar-query and CALDAV:calendar-multiget reports defined in this document let clients retrieve only the recurrence instances that overlap a given time range โฐ.

4. Calendar Resources ๐Ÿ“

4.1. Calendar Object Resources

calendar object resources contained in calendar collections MUST NOT contain more than one type of calendar component (e.g., VEVENT, VTODO, VJOURNAL, VFREEBUSY, etc.) with the exception of VTIMEZONE components, which MUST be specified for each unique TZID parameter value specified in the iCalendar object ๐Ÿงฉ. For instance, a calendar object resource can contain one VEVENT component and one VTIMEZONE component, but it cannot contain one VEVENT component and one VTODO component. Instead, the VEVENT and VTODO components would have to be stored in separate calendar object resources in the same collection ๐Ÿ™…โ€โ™€๏ธ.

calendar object resources contained in calendar collections MUST NOT specify the iCalendar METHOD property ๐Ÿšซ.

The UID property value of the calendar components contained in a calendar object resource MUST be unique in the scope of the calendar collection they're stored in ๐Ÿ†”.

calendar components in a calendar collection that have different UID property values MUST be stored in separate calendar object resources ๐Ÿ“‚.

calendar components with the same UID property value, in a given calendar collection, MUST be contained in the same calendar object resource ๐Ÿ’ž. This makes sure all components in a recurrence "set" live in the same calendar object resource. It's possible for a calendar object resource to contain just components that represent "overridden" instances (ones that modify the behavior of a regular instance, and so include a RECURRENCE-ID property) without also including the "master" recurring component (the one that defines the recurrence "set" and does not contain any RECURRENCE-ID property) ๐Ÿฆ‹.

for example, given the following iCalendar object:

BEGIN:VCALENDAR
PRODID:-//Example Corp.//CalDAV Client//EN
VERSION:2.0
BEGIN:VEVENT
UID:1@example.com
SUMMARY:One-off Meeting
DTSTAMP:20041210T183904Z
DTSTART:20041207T120000Z
DTEND:20041207T130000Z
END:VEVENT
BEGIN:VEVENT
UID:2@example.com
SUMMARY:Weekly Meeting
DTSTAMP:20041210T183838Z
DTSTART:20041206T120000Z
DTEND:20041206T130000Z
RRULE:FREQ=WEEKLY
END:VEVENT
BEGIN:VEVENT
UID:2@example.com
SUMMARY:Weekly Meeting
RECURRENCE-ID:20041213T120000Z
DTSTAMP:20041210T183838Z
DTSTART:20041213T130000Z
DTEND:20041213T140000Z
END:VEVENT
END:VCALENDAR

the VEVENT component with the UID value "1@example.com" would be stored in its own calendar object resource ๐ŸŽ€. The two VEVENT components with the UID value "2@example.com", which represent a recurring event where one recurrence instance has been overridden, would be stored in the same calendar object resource ๐Ÿ’œโœจ.

4.2. Calendar Collection

okay so a calendar collection is basically the folder that holds your calendar object resources, which are the calendar components living inside a calendar ๐Ÿ“โœจ Clients see it as a WebDAV resource collection with its own URL. A calendar collection MUST report both the DAV:collection and CALDAV:calendar XML elements in the value of its DAV:resourcetype property. The element type declaration for CALDAV:calendar is:

<!ELEMENT calendar EMPTY>

bestie, there are two ways a calendar collection can show up ๐ŸŽ€ It can be created through provisioning, meaning it's made automatically when a user's account gets provisioned. Or it can be made with the MKCALENDAR method (see Section 5.3.1). This is super handy for making extra calendars like a soccer schedule, or for sharing one, like team events or conference rooms ๐ŸŒธ BUT (and this is important) this document does NOT define what extra calendar collections are actually for ๐Ÿ’€ So users have to rely on non-standard cues to figure it out, or use the CALDAV:calendar-description property from Section 5.2.1 to leave a little hint.

Now the rules for what lives inside a calendar collection, no cap, these are strict ๐Ÿ‘‘

a. Calendar collections MUST only contain calendar object resources and collections that are not calendar collections. So the only "top-level" non-collection resources allowed are calendar object resources. This keeps calendar clients from having to deal with non-calendar data ๐Ÿงš They still have to tell calendar object resources apart from collections when they use standard WebDAV techniques to look inside a collection, though.

b. Collections sitting inside calendar collections MUST NOT contain calendar collections at any depth. So no nesting calendar collections inside other calendar collections, no matter how deep ๐Ÿ™…โ€โ™€๏ธ This spec also doesn't say how those inner collections get used or how they connect to the calendar object resources in the calendar collection, so that's on the implementers ๐Ÿ’…

Multiple calendar collections MAY be children of the same collection. Mix and match, it's giving organized ๐ŸŒˆ


5. Calendar Access Feature ๐Ÿฆ‹

5.1. Calendar Access Support

A server that supports the features in this document MUST include calendar-access as a field in the DAV response header from an OPTIONS request on any resource that supports any calendar properties, reports, method, or privilege. A DAV response header value of calendar-access MUST indicate that the server supports all MUST level requirements in this document. So if you see that token, it's a promise that the server has the full MUST-level package ๐Ÿ”ฅ

5.1.1. Example: Using OPTIONS for the Discovery of Calendar Access Support

Here's the vibe check ๐Ÿ”

>> Request <<

OPTIONS /home/bernard/calendars/ HTTP/1.1
Host: cal.example.com

>> Response <<

HTTP/1.1 200 OK
Allow: OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, COPY, MOVE
Allow: PROPFIND, PROPPATCH, LOCK, UNLOCK, REPORT, ACL
DAV: 1, 2, access-control, calendar-access
Date: Sat, 11 Nov 2006 09:32:12 GMT
Content-Length: 0

In this example, the OPTIONS method comes back with calendar-access in the DAV response header, which tells us the collection /home/bernard/calendars/ supports the properties, reports, method, or privilege defined in this spec. Iconic discovery moment โœจ

5.2. Calendar Collection Properties

okay so this section defines the properties for calendar collections ๐ŸŽ€

5.2.1. CALDAV:calendar-description Property

Name: calendar-description

Namespace: urn:ietf:params:xml:ns:caldav

Purpose: Gives a human-readable description of the calendar collection ๐Ÿ“

Conformance: This property MAY be defined on any calendar collection. If it's defined, it MAY be protected, and it SHOULD NOT be returned by a PROPFIND DAV:allprop request (as defined in Section 12.14.1 of [RFC2518]). An xml:lang attribute that says what human language the description is in SHOULD be set for this property, either by clients or through server provisioning. Servers MUST return any xml:lang attribute that's set for the property. Language tags matter, periodt ๐ŸŒ

Description: If it's present, the property holds a description of the calendar collection that's fine to show to a user. If it's not present, the client should assume there's no description for the calendar collection ๐Ÿซถ

Definition:

<!ELEMENT calendar-description (#PCDATA)>
PCDATA value: string

Example:

<C:calendar-description xml:lang="fr-CA"
   xmlns:C="urn:ietf:params:xml:ns:caldav"
>Calendrier de Mathilde Desruisseaux</C:calendar-description>

5.2.2. CALDAV:calendar-timezone Property

Name: calendar-timezone

Namespace: urn:ietf:params:xml:ns:caldav

Purpose: Specifies a time zone on a calendar collection ๐ŸŒ

Conformance: This property SHOULD be defined on all calendar collections. If it's defined, it SHOULD NOT be returned by a PROPFIND DAV:allprop request (as defined in Section 12.14.1 of [RFC2518]).

Description: The CALDAV:calendar-timezone property tells the server which time zone to rely on when it resolves "date" values and "date with local time" values (aka floating time) into "date with UTC time" values. This matters SO much. The server needs this info to figure out whether a calendar component scheduled with "date" or "date with local time" values overlaps a CALDAV:time-range in a CALDAV:calendar-query REPORT. The server also needs it to work out the right FREEBUSY time period as "date with UTC time" in the VFREEBUSY component that comes back in a response to a CALDAV:free-busy-query REPORT request that includes calendar components scheduled with "date" or "date with local time" values ๐Ÿ’– If this property isn't there, the server MAY rely on whichever time zone it wants.

Note: The iCalendar data embedded inside the CALDAV:calendar-timezone XML element MUST follow the standard XML character data encoding rules. That includes using entity encoding like &lt;, &gt;, &amp; etc., or using a <![CDATA[ ... ]]> construct. If you go the CDATA route, the iCalendar data can't contain the character sequence ]]>, because that's the end delimiter for the CDATA section ๐Ÿ™ˆ

Definition:

<!ELEMENT calendar-timezone (#PCDATA)>
PCDATA value: an iCalendar object with exactly one VTIMEZONE
      component.

Example:

<C:calendar-timezone
    xmlns:C="urn:ietf:params:xml:ns:caldav">BEGIN:VCALENDAR
PRODID:-//Example Corp.//CalDAV Client//EN
VERSION:2.0
BEGIN:VTIMEZONE
TZID:US-Eastern
LAST-MODIFIED:19870101T000000Z
BEGIN:STANDARD
DTSTART:19671029T020000
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
TZNAME:Eastern Standard Time (US &amp; Canada)
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19870405T020000
RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
TZNAME:Eastern Daylight Time (US &amp; Canada)
END:DAYLIGHT
END:VTIMEZONE
END:VCALENDAR
</C:calendar-timezone>

5.2.3. CALDAV:supported-calendar-component-set Property

Name: supported-calendar-component-set

Namespace: urn:ietf:params:xml:ns:caldav

Purpose: Specifies which calendar component types (like VEVENT, VTODO, etc.) calendar object resources can hold in the calendar collection ๐Ÿ—“๏ธ

Conformance: This property MAY be defined on any calendar collection. If it's defined, it MUST be protected, and it SHOULD NOT be returned by a PROPFIND DAV:allprop request (as defined in Section 12.14.1 of [RFC2518]).

Description: The CALDAV:supported-calendar-component-set property puts restrictions on which calendar component types calendar object resources are allowed to contain in a calendar collection ๐Ÿšซ If a client tries to store a calendar object resource with a component type that isn't listed here (and the property exists), it MUST result in an error, with the CALDAV:supported-calendar-component precondition (Section 5.3.2.1) being violated. Since this property is protected, clients can't change it with a PROPPATCH request. BUT clients CAN set its initial value when they make a new calendar collection with MKCALENDAR ๐ŸŽ€ The empty-element tag <C:comp name="VTIMEZONE"/> MUST only be specified if support for calendar object resources that only contain VTIMEZONE components is provided or wanted. Support for VTIMEZONE components inside calendar object resources that contain VEVENT or VTODO components is always assumed, so you don't have to list it for those. If this property isn't there, the server MUST accept all component types, and the client can assume that every component type is accepted ๐ŸŒˆ

Definition:

<!ELEMENT supported-calendar-component-set (comp+)>

Example:

<C:supported-calendar-component-set
    xmlns:C="urn:ietf:params:xml:ns:caldav">
  <C:comp name="VEVENT"/>
  <C:comp name="VTODO"/>
</C:supported-calendar-component-set>

5.2.4. CALDAV:supported-calendar-data Property

Name: supported-calendar-data

Namespace: urn:ietf:params:xml:ns:caldav

Purpose: Specifies which media types are allowed for calendar object resources in a calendar collection ๐Ÿ“ฆ

Conformance: This property MAY be defined on any calendar collection. If it's defined, it MUST be protected, and it SHOULD NOT be returned by a PROPFIND DAV:allprop request (as defined in Section 12.14.1 of [RFC2518]).

Description: The CALDAV:supported-calendar-data property says which media type is supported for the calendar object resources in a given calendar collection (for example, iCalendar version 2.0) ๐Ÿ’œ If a client tries to store a calendar object resource with a media type that isn't listed here, it MUST result in an error, with the CALDAV:supported-calendar-data precondition (Section 5.3.2.1) being violated. If this property isn't there, the server MUST only accept data with the media type text/calendar and iCalendar version 2.0, and clients can assume the server will only accept that data. Clear rules, no drama ๐Ÿ’…

Definition:

<!ELEMENT supported-calendar-data (calendar-data+)>

Example:

<C:supported-calendar-data
   xmlns:C="urn:ietf:params:xml:ns:caldav">
  <C:calendar-data content-type="text/calendar" version="2.0"/>
</C:supported-calendar-data>

5.2.5. CALDAV:max-resource-size Property ๐Ÿ“ฆโœจ

Name: max-resource-size Namespace: urn:ietf:params:xml:ns:caldav

Purpose: okay so this one is the size limit ๐Ÿ’…. It gives a number in octets for the biggest calendar object resource the server will accept when you store one in a calendar collection ๐Ÿฆ‹

Conformance: this property MAY be defined on any calendar collection ๐ŸŽ€. If it's defined, it MUST be protected ๐Ÿ”’, and it SHOULD NOT show up in a PROPFIND DAV:allprop request (see Section 12.14.1 of [RFC2518]) ๐Ÿ™ˆ

Description: the CALDAV:max-resource-size is how the server says "this is the biggest thing I'll take" ๐Ÿ“. If you try to store a calendar object resource over that size, you MUST get an error, and the CALDAV:max-resource-size precondition (Section 5.3.2.1) gets violated ๐Ÿ’€. If this property isn't there at all, the client can just assume the server will take a resource of any reasonable size ๐ŸŒธ

Definition:

<!ELEMENT max-resource-size (#PCDATA)>
PCDATA value: a numeric value (positive integer)

Example:

<C:max-resource-size xmlns:C="urn:ietf:params:xml:ns:caldav"
>102400</C:max-resource-size>

5.2.6. CALDAV:min-date-time Property ๐Ÿ—“๏ธ๐Ÿ’œ

Name: min-date-time Namespace: urn:ietf:params:xml:ns:caldav

Purpose: this one gives a DATE-TIME value (in UTC โฐ) for the earliest date and time the server is willing to take for any DATE or DATE-TIME value in a calendar object resource stored in a calendar collection ๐Ÿงš

Conformance: this property MAY be defined on any calendar collection ๐ŸŽ€. If it's defined, it MUST be protected ๐Ÿ”’, and it SHOULD NOT show up in a PROPFIND DAV:allprop request (see Section 12.14.1 of [RFC2518]) ๐Ÿ™ˆ

Description: the CALDAV:min-date-time is an iCalendar DATE-TIME value in UTC that marks the earliest inclusive date the server accepts for any explicit DATE or DATE-TIME value in a calendar object resource stored in a calendar collection ๐Ÿ“…. Any attempt to store a resource using a DATE or DATE-TIME earlier than this MUST result in an error, and the CALDAV:min-date-time precondition (Section 5.3.2.1) gets violated ๐Ÿ˜ญ. Now the plot twist: servers MUST accept recurring components that have instances past this limit, as long as none of those instances have been overridden ๐ŸŒˆ. In that case the server MAY just ignore the instances outside the acceptable range when it processes reports on that calendar object resource ๐Ÿซถ. If this property isn't there, the client can assume any valid iCalendar date may be used at least up to the CALDAV:max-date-time value, if that one's defined โœจ

Definition:

<!ELEMENT min-date-time (#PCDATA)>
PCDATA value: an iCalendar format DATE-TIME value in UTC

Example:

<C:min-date-time xmlns:C="urn:ietf:params:xml:ns:caldav"
>19000101T000000Z</C:min-date-time>

5.2.7. CALDAV:max-date-time Property ๐ŸŒ™๐Ÿ”ฎ

Name: max-date-time Namespace: urn:ietf:params:xml:ns:caldav

Purpose: the mirror image of the last one ๐Ÿชž. It gives a DATE-TIME value (in UTC) for the latest date and time the server will accept for any DATE or DATE-TIME value in a calendar object resource stored in a calendar collection ๐Ÿ’–

Conformance: this property MAY be defined on any calendar collection ๐ŸŽ€. If it's defined, it MUST be protected ๐Ÿ”’, and it SHOULD NOT show up in a PROPFIND DAV:allprop request (see Section 12.14.1 of [RFC2518]) ๐Ÿ™ˆ

Description: the CALDAV:max-date-time is an iCalendar DATE-TIME value in UTC that marks the inclusive latest date the server will take for any date or time value in a calendar object resource stored in a calendar collection ๐Ÿ—“๏ธ. Storing a resource with a DATE or DATE-TIME later than this MUST result in an error, with the CALDAV:max-date-time precondition (Section 5.3.2.1) getting violated ๐Ÿ’€. Same deal as before: servers MUST accept recurring components that specify instances beyond this limit, as long as none of those instances have been overridden ๐ŸŒˆ. The server MAY simply ignore those out-of-range instances when processing reports on the calendar object resource ๐Ÿซถ. If this property isn't there, the client can assume any valid iCalendar date may be used at least down to the CALDAV:min-date-time value, if that one's defined ๐Ÿงš

Definition:

<!ELEMENT max-date-time (#PCDATA)>
PCDATA value: an iCalendar format DATE-TIME value in UTC

Example:

<C:max-date-time xmlns:C="urn:ietf:params:xml:ns:caldav"
>20491231T235959Z</C:max-date-time>

5.2.8. CALDAV:max-instances Property ๐Ÿ”๐Ÿ“

Name: max-instances Namespace: urn:ietf:params:xml:ns:caldav

Purpose: this is the cap on how many recurrence instances a calendar object resource stored in a calendar collection can generate ๐Ÿ”. It's a number, so no drama there ๐ŸŽ€

Conformance: this property MAY be defined on any calendar collection ๐ŸŽ€. If it's defined, it MUST be protected ๐Ÿ”’, and it SHOULD NOT show up in a PROPFIND DAV:allprop request (see Section 12.14.1 of [RFC2518]) ๐Ÿ™ˆ

Description: the CALDAV:max-instances is a numeric value for the maximum number of recurrence instances that a calendar object resource stored in a calendar collection can generate ๐ŸŒ€. If you try to store a resource with a recurrence pattern that makes more instances than this, you MUST get an error, and the CALDAV:max-instances precondition (Section 5.3.2.1) gets violated ๐Ÿ˜ญ. If the property isn't there, the client can assume the server has no limits on how many recurrence instances it can handle or expand ๐Ÿ‘‘

Definition:

<!ELEMENT max-instances (#PCDATA)>
PCDATA value: a numeric value (integer greater than zero)

Example:

<C:max-instances xmlns:C="urn:ietf:params:xml:ns:caldav"
>100</C:max-instances>

5.2.9. CALDAV:max-attendees-per-instance Property ๐Ÿ‘ฏโ€โ™€๏ธ๐Ÿ’…

Name: max-attendees-per-instance Namespace: urn:ietf:params:xml:ns:caldav

Purpose: this one gives the maximum number of ATTENDEE properties allowed in any single instance of a calendar object resource stored in a calendar collection ๐ŸŽŸ๏ธ

Conformance: this property MAY be defined on any calendar collection ๐ŸŽ€. If it's defined, it MUST be protected ๐Ÿ”’, and it SHOULD NOT show up in a PROPFIND DAV:allprop request (see Section 12.14.1 of [RFC2518]) ๐Ÿ™ˆ

Description: the CALDAV:max-attendees-per-instance is a numeric value for the maximum number of iCalendar ATTENDEE properties on any one instance of a calendar object resource stored in a calendar collection ๐Ÿฅณ. If you try to store a resource with more ATTENDEE properties per instance than this, you MUST get an error, and the CALDAV:max-attendees-per-instance precondition (Section 5.3.2.1) gets violated ๐Ÿ’€. If the property isn't there, the client can assume the server can handle any number of ATTENDEE properties in a calendar component ๐ŸŒˆ

Definition:

<!ELEMENT max-attendees-per-instance (#PCDATA)>
PCDATA value: a numeric value (integer greater than zero)

Example:

<C:max-attendees-per-instance
     xmlns:C="urn:ietf:params:xml:ns:caldav"
>25</C:max-attendees-per-instance>

5.2.10. Additional Precondition for PROPPATCH ๐Ÿงพโœจ

This specification adds an extra precondition for the PROPPATCH method ๐Ÿ’…. It's called:

CALDAV:valid-calendar-data: the time zone specified in the CALDAV:calendar-timezone property MUST be a valid iCalendar object containing a single valid VTIMEZONE component ๐ŸŒ


5.3. Creating Resources ๐ŸŽ€๐Ÿ—๏ธ

Calendar collections and calendar object resources can be created by either a CalDAV client or a CalDAV server ๐Ÿซถ. This specification defines the restrictions and the data model that both clients and servers MUST adhere to when they manipulate calendar data ๐Ÿ“š

5.3.1. MKCALENDAR Method ๐Ÿ“…๐Ÿ†•

An HTTP request using the MKCALENDAR method creates a new calendar collection resource ๐Ÿฆ‹. A server MAY restrict calendar collection creation to particular collections ๐Ÿšช

Supporting MKCALENDAR on the server is only RECOMMENDED, not REQUIRED ๐Ÿคทโ€โ™€๏ธ. Some calendar stores only support one calendar per user (or principal), and those are usually pre-created for each account ๐Ÿ’ผ. Still, servers and clients are strongly encouraged to support MKCALENDAR whenever possible so users can make multiple calendar collections and organize their stuff better ๐Ÿ—‚๏ธโœจ

Clients SHOULD use the DAV:displayname property for a human-readable name for the calendar ๐Ÿท๏ธ. They can either put the DAV:displayname value in the MKCALENDAR request body, or send a PROPPATCH request right after the MKCALENDAR request to change DAV:displayname to the right value ๐Ÿ’…. Clients SHOULD NOT set DAV:displayname to be the same as any other calendar collection at the same URI "level" ๐Ÿ™…โ€โ™€๏ธ. When they show calendar collections to users, clients SHOULD check DAV:displayname and use that value as the calendar's name ๐Ÿ‘€. If DAV:displayname is empty, the client MAY use the last part of the calendar collection URI as the name instead, but that path segment may be "opaque" and not mean anything human-readable ๐Ÿ™ˆ

If a MKCALENDAR request fails, the server state from before the request MUST be restored โช

Marshalling:

If there's a request body, it MUST be a CALDAV:mkcalendar XML element ๐Ÿงฉ. Instructions MUST get processed in the order they arrive (top to bottom) ๐Ÿ”. They MUST either all get executed or none get executed ๐Ÿซฃ. So if anything goes wrong mid-processing, every instruction that already ran MUST be undone, and you get a proper error result ๐Ÿ’€. The details for processing instructions are in the DAV:set instruction definition in Section 12.13.2 of [RFC2518] ๐Ÿ“–

<!ELEMENT mkcalendar (DAV:set)>

If a successful request has a response body, it MUST be a CALDAV:mkcalendar-response XML element ๐ŸŽ

<!ELEMENT mkcalendar-response ANY>

The response MUST include a Cache-Control:no-cache header ๐ŸงŠ

Preconditions:

  • DAV:resource-must-be-null: a resource MUST NOT exist at the Request-URI ๐Ÿšซ
  • CALDAV:calendar-collection-location-ok: the Request-URI MUST identify a location where a calendar collection can be created ๐Ÿ“
  • CALDAV:valid-calendar-data: the time zone specified in the CALDAV:calendar-timezone property MUST be a valid iCalendar object containing a single valid VTIMEZONE component ๐ŸŒ
  • DAV:needs-privilege: the DAV:bind privilege MUST be granted to the current user on the parent collection of the Request-URI ๐Ÿ”‘

Postconditions:

  • CALDAV:initialize-calendar-collection: a new calendar collection exists at the Request-URI ๐ŸŽ‰. The DAV:resourcetype of the calendar collection MUST contain both DAV:collection and CALDAV:calendar XML elements ๐Ÿ’–

Okay, we're getting closer to the good stuff, bestie ๐ŸŒˆโœจ

5.3.1.1. Status Codes

okay so these are the response codes you'd totally expect to see back from a MKCALENDAR request ๐Ÿ’… BUT this list is not the whole story, so don't treat it like the full menu ๐Ÿซถ

  • 201 (Created) - the calendar collection resource got created in its entirety ๐ŸŽ€
  • 207 (Multi-Status) - the calendar collection resource was NOT created because one or more DAV:set instructions in the request body couldn't be processed successfully ๐Ÿ˜ญ the ones you'd expect inside a 207 in this situation are:
    • 403 (Forbidden) - the client, for reasons the server chooses not to spell out, can't change one of the properties ๐Ÿ™ˆ
    • 409 (Conflict) - the client gave a value whose meaning doesn't fit the property. This includes trying to set read-only properties ๐Ÿ’€
    • 424 (Failed Dependency) - the DAV:set instruction on that resource would've worked if it weren't for another DAV:set instruction in the same request body failing ๐Ÿฅบ
    • 423 (Locked) - the resource is locked and the client either isn't a lock owner, or the lock type needs a lock token and the client didn't send one ๐Ÿ”’
    • 507 (Insufficient Storage) - the server didn't have enough space to record the property ๐Ÿซ 
  • 403 (Forbidden) - this covers at least one of two things: 1) the server doesn't allow calendar collections to be created at that location in its namespace, or 2) the parent collection of the Request-URI exists but can't accept members ๐Ÿšซ
  • 409 (Conflict) - a collection can't be made at the Request-URI until one or more intermediate collections have been created first ๐Ÿงฑ
  • 415 (Unsupported Media Type) - the server doesn't support the request body's type ๐Ÿ“ฆ
  • 507 (Insufficient Storage) - the resource doesn't have enough space to record its state after this method runs ๐Ÿ’พ

5.3.1.2. Example: Successful MKCALENDAR Request

ok this example makes a calendar collection called /home/lisa/calendars/events/ on the server cal.example.com ๐ŸŒธ it sets some specific values for DAV:displayname, CALDAV:calendar-description, CALDAV:supported-calendar-component-set, and CALDAV:calendar-timezone. so cute, Lisa is really organized ๐Ÿ—“๏ธโœจ

>> Request <<

MKCALENDAR /home/lisa/calendars/events/ HTTP/1.1
Host: cal.example.com
Content-Type: application/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<C:mkcalendar xmlns:D="DAV:"
              xmlns:C="urn:ietf:params:xml:ns:caldav">
  <D:set>
    <D:prop>
      <D:displayname>Lisa's Events</D:displayname>
      <C:calendar-description xml:lang="en"
>Calendar restricted to events.</C:calendar-description>
      <C:supported-calendar-component-set>
        <C:comp name="VEVENT"/>
      </C:supported-calendar-component-set>
      <C:calendar-timezone><![CDATA[BEGIN:VCALENDAR
PRODID:-//Example Corp.//CalDAV Client//EN
VERSION:2.0
BEGIN:VTIMEZONE
TZID:US-Eastern
LAST-MODIFIED:19870101T000000Z
BEGIN:STANDARD
DTSTART:19671029T020000
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
TZNAME:Eastern Standard Time (US & Canada)
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19870405T020000
RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
TZNAME:Eastern Daylight Time (US & Canada)
END:DAYLIGHT
END:VTIMEZONE
END:VCALENDAR
]]></C:calendar-timezone>
    </D:prop>
  </D:set>
</C:mkcalendar>

>> Response <<

HTTP/1.1 201 Created
Cache-Control: no-cache
Date: Sat, 11 Nov 2006 09:32:12 GMT
Content-Length: 0

5.3.2. Creating Calendar Object Resources

okay so clients fill calendar collections up with calendar object resources ๐Ÿฆ‹ the URL for each one is totally arbitrary and doesn't have to match anything in its iCalendar properties or other metadata, so no pressure on naming ๐Ÿ’– new calendar object resources MUST be created with a PUT request aimed at an unmapped URI ๐ŸŽฏ a PUT aimed at a mapped URI just updates a calendar object resource that already exists.

servers picking unmapped URIs for new resources? easy peasy ๐Ÿ˜Ž clients have it a bit harder, because a client might not want to scan every resource in the collection, and it might not want to lock the whole collection just to dodge a name collision ๐Ÿ˜ฉ BUT there's an HTTP feature that helps with this ๐Ÿ™Œ if the client wants to create a new non-collection resource, like a new VEVENT, it SHOULD send the HTTP request header "If-None-Match: *" on the PUT request. the Request-URI on that PUT MUST include the target collection where the resource is going, plus the name of the resource in the last path segment ๐Ÿ“ and that "If-None-Match: *" header means the client won't accidentally overwrite an existing resource if that last path segment already happens to be taken ๐Ÿ›ก๏ธ

>> Request <<

PUT /home/lisa/calendars/events/qwue23489.ics HTTP/1.1
If-None-Match: *
Host: cal.example.com
Content-Type: text/calendar
Content-Length: xxxx

BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp.//CalDAV Client//EN
BEGIN:VEVENT
UID:20010712T182145Z-123401@example.com
DTSTAMP:20060712T182145Z
DTSTART:20060714T170000Z
DTEND:20060715T040000Z
SUMMARY:Bastille Day Party
END:VEVENT
END:VCALENDAR

>> Response <<

HTTP/1.1 201 Created
Content-Length: 0
Date: Sat, 11 Nov 2006 09:32:12 GMT
ETag: "123456789-000-111"

changing an existing event works the same way, except you send a specific ETag in the "If-Match" header instead of "If-None-Match" ๐Ÿ”โœจ

as noted in Section 3.10 of [RFC2445], the URL of calendar object resources holding (an arbitrary set of) calendaring and scheduling information may end in ".ics", and the URL of calendar object resources holding free or busy time information may end in ".ifb" ๐Ÿ“

5.3.2.1. Additional Preconditions for PUT, COPY, and MOVE

this spec adds extra Preconditions for PUT, COPY, and MOVE ๐ŸŒˆ they kick in when a calendar object resource gets PUT into a calendar collection, when a calendar object resource gets COPYed or MOVEd into a calendar collection, or when a COPY or MOVE happens on a calendar collection itself ๐Ÿงš

the new preconditions are:

  • (CALDAV:supported-calendar-data): the resource submitted in the PUT request, or targeted by a COPY or MOVE request, MUST be a supported media type (i.e., iCalendar) for calendar object resources ๐Ÿ“
  • (CALDAV:valid-calendar-data): the resource submitted in the PUT request, or targeted by a COPY or MOVE request, MUST be valid data for the media type being specified (i.e., MUST contain valid iCalendar data) โœ…
  • (CALDAV:valid-calendar-object-resource): the resource submitted in the PUT request, or targeted by a COPY or MOVE request, MUST obey all restrictions specified in Section 4.1 (e.g., calendar object resources MUST NOT contain more than one type of calendar component, calendar object resources MUST NOT specify the iCalendar METHOD property, etc.) ๐Ÿ“
  • (CALDAV:supported-calendar-component): the resource submitted in the PUT request, or targeted by a COPY or MOVE request, MUST contain a type of calendar component that is supported in the targeted calendar collection ๐Ÿงฉ
  • (CALDAV:no-uid-conflict): the resource submitted in the PUT request, or targeted by a COPY or MOVE request, MUST NOT specify an iCalendar UID property value already in use in the targeted calendar collection, or overwrite an existing calendar object resource with one that has a different UID property value. Servers SHOULD report the URL of the resource that is already using the same UID property value in the DAV:href element ๐Ÿšจ
<!ELEMENT no-uid-conflict (DAV:href)>
  • (CALDAV:calendar-collection-location-ok): in a COPY or MOVE request, when the Request-URI is a calendar collection, the Destination-URI MUST identify a location where a calendar collection can be created ๐Ÿ“
  • (CALDAV:max-resource-size): the resource submitted in the PUT request, or targeted by a COPY or MOVE request, MUST have an octet size less than or equal to the value of the CALDAV:max-resource-size property value (Section 5.2.5) on the calendar collection where the resource will be stored โš–๏ธ
  • (CALDAV:min-date-time): the resource submitted in the PUT request, or targeted by a COPY or MOVE request, MUST have all of its iCalendar DATE or DATE-TIME property values (for each recurring instance) greater than or equal to the value of the CALDAV:min-date-time property value (Section 5.2.6) on the calendar collection where the resource will be stored ๐Ÿ“…
  • (CALDAV:max-date-time): the resource submitted in the PUT request, or targeted by a COPY or MOVE request, MUST have all of its iCalendar DATE or DATE-TIME property values (for each recurring instance) less than the value of the CALDAV:max-date-time property value (Section 5.2.7) on the calendar collection where the resource will be stored ๐Ÿ—“๏ธ
  • (CALDAV:max-instances): the resource submitted in the PUT request, or targeted by a COPY or MOVE request, MUST generate a number of recurring instances less than or equal to the value of the CALDAV:max-instances property value (Section 5.2.8) on the calendar collection where the resource will be stored ๐Ÿ”
  • (CALDAV:max-attendees-per-instance): the resource submitted in the PUT request, or targeted by a COPY or MOVE request, MUST have a number of ATTENDEE properties on any one instance less than or equal to the value of the CALDAV:max-attendees-per-instance property value (Section 5.2.9) on the calendar collection where the resource will be stored ๐Ÿ‘ฅ

5.3.3. Non-Standard Components, Properties, and Parameters

iCalendar has a "standard mechanism for doing non-standard things" ๐ŸŽจ this extension support lets implementers use non-standard components, properties, and parameters whose names start with the text "X-" ๐Ÿ’œ

servers MUST support non-standard components, properties, and parameters in calendar object resources stored via the PUT method ๐Ÿ™Œ

servers may need to enforce rules for their own "private" components, properties, or parameters, so servers MAY reject any attempt by the client to change those or to use values for those outside of any restrictions the server may have ๐Ÿ” servers SHOULD make sure any "private" components, properties, or parameters they use follow the convention of including a vendor id in the "X-" name, as described in Section 4.2 of [RFC2445], e.g., "X-ABC-PRIVATE" ๐Ÿท๏ธโœจ

5.3.4. Calendar Object Resource Entity Tag โœจ

okay so the DAV:getetag property MUST be defined and set to a strong entity tag on every single calendar object resource ๐Ÿ’… no exceptions bestie

when a GET request targets a calendar object resource, the response MUST include an ETag response header field that shows the current value of that strong entity tag ๐ŸŽ€

servers SHOULD send back a strong entity tag (the ETag header) in the PUT response when the stored calendar object resource is octet-for-octet identical to the body of the PUT request ๐Ÿซถ this is so clients can actually trust that tag for syncing. like, the client can do a PROPFIND on the resource, get the DAV:getetag back, and compare it to the tag from the PUT response. if they match, the resource on the server hasn't changed. iconic ๐Ÿงš

now if the server stores something from a PUT that is NOT octet-identical to what was sent, the spec doesn't say what the ETag header does, with one big catch: a strong entity tag MUST NOT be returned in that response ๐Ÿ˜ญ so clients might need to fetch the modified resource (and its ETag) and use that as the starting point for more changes, instead of the copy they sent with the PUT


6. Calendaring Access Control ๐Ÿ”

6.1. Calendaring Privilege ๐Ÿ‘‘

CalDAV servers MUST support and adhere to the requirements of WebDAV ACL [RFC3744]. basically WebDAV ACL gives you a framework for a whole extensible set of privileges that can be slapped onto WebDAV collections and ordinary resources ๐ŸŒธ on top of that, CalDAV servers MUST also support the calendaring privilege defined in this section

6.1.1. CALDAV:read-free-busy Privilege ๐Ÿฆ‹

okay this one is so relatable. calendar users often want to let other people see when they're busy, but NOT the juicy details like location, summary, or attendees ๐Ÿ™ˆ it keeps a lot of privacy while still letting people book meetings at times you're probably free. main character privacy energy

the CALDAV:read-free-busy privilege controls which calendar collections, regular collections, and calendar object resources get looked at when a CALDAV:free-busy-query REPORT request is processed (see Section 7.10). this privilege can be granted on calendar collections, regular collections, or calendar object resources ๐Ÿ’œ

servers MUST support this privilege on all calendar collections, regular collections, and calendar object resources โœจ

<!ELEMENT read-free-busy EMPTY>

the CALDAV:read-free-busy privilege MUST be aggregated in the DAV:read privilege ๐Ÿ“ servers MUST allow CALDAV:read-free-busy to be granted without DAV:read being granted too

heads up: if only CALDAV:read-free-busy has been granted on a resource, that does NOT imply access to GET, HEAD, OPTIONS, or PROPFIND on it. those are governed by the DAV:read privilege, so clients should keep that in mind ๐Ÿ™ˆ

6.2. Additional Principal Property ๐ŸŽ€

this section adds one more property for WebDAV principal resources, as defined in [RFC3744] ๐Ÿ’–

6.2.1. CALDAV:calendar-home-set Property ๐Ÿก

  • Name: calendar-home-set
  • Namespace: urn:ietf:params:xml:ns:caldav
  • Purpose: it tells you the URL of any WebDAV collections that hold calendar collections owned by the principal resource ๐Ÿง
  • Conformance: this property SHOULD be defined on a principal resource. if it's defined, it MAY be protected, and it SHOULD NOT be returned by a PROPFIND DAV:allprop request (as defined in Section 12.14.1 of [RFC2518]) ๐Ÿ’…
  • Description: the whole point of CALDAV:calendar-home-set is to help users find the calendar collections owned by the principal, super easily ๐Ÿ” usually people group all their calendar collections under one shared collection. this property gives the URL of collections that are either calendar collections or ordinary collections with child or descendant calendar collections owned by the principal โœจ
  • Definition:
<!ELEMENT calendar-home-set (DAV:href*)>
  • Example:
<C:calendar-home-set xmlns:D="DAV:"
                     xmlns:C="urn:ietf:params:xml:ns:caldav">
  <D:href>http://cal.example.com/home/bernard/calendars/</D:href>
</C:calendar-home-set>

7. Calendaring Reports ๐Ÿ“Š

this section defines the reports that CalDAV servers MUST support on calendar collections and calendar object resources ๐Ÿซถ

CalDAV servers MUST advertise support for these reports on all calendar collections and calendar object resources using the DAV:supported-report-set property, defined in Section 3.1.5 of [RFC3253]. CalDAV servers MAY also advertise support for these reports on ordinary collections ๐Ÿ’œ

some of these reports let calendar data (from possibly multiple resources) come back to you ๐Ÿฆ‹

7.1. REPORT Method ๐Ÿ“จ

the REPORT method (defined in Section 3.6 of [RFC3253]) is an extensible way to get info about one or more resources ๐Ÿงš unlike PROPFIND, which gives you the value of one or more named properties, REPORT can do way more complex processing. it's super useful when the server has everything it needs to handle a complex request (like a query), and the client would otherwise need a bunch of separate requests to get the same info ๐Ÿ”ฅ

CalDAV servers MUST support the DAV:expand-property REPORT defined in Section 3.8 of [RFC3253] ๐Ÿ‘‘

7.2. Ordinary Collections ๐Ÿ“

servers MAY support the reports defined in this document on ordinary collections (collections that aren't calendar collections), on top of calendar collections or calendar object resources ๐ŸŒˆ when computing responses to these reports on ordinary collections, servers MUST only consider calendar object resources contained in the calendar collections targeted by the REPORT request, based on the value of the Depth request header ๐Ÿ’…

7.3. Date and Floating Time ๐ŸŒ™

iCalendar lets you specify DATE and DATE-TIME values that aren't tied to any particular time zone ๐ŸŒ these are called "floating date" and "floating time". they mean the same day, hour, minute, and second no matter which time zone is being observed. for example, the DATE value "20051111" is November 11, 2005 in no specific time zone, and the DATE-TIME value "20051111T111100" is November 11, 2005 at 11:11 A.M. in no specific time zone โฐ

CalDAV servers may need to convert "floating date" and "floating time" values into date with UTC time values while processing calendaring REPORT requests ๐Ÿ”„

for the CALDAV:calendar-query REPORT, CalDAV servers MUST rely on the value of the CALDAV:timezone XML element, if it's in the request body, to do the proper conversion of "floating date" and "floating time" values into date with UTC time values ๐Ÿ’– if the CALDAV:timezone XML element isn't in the request body, CalDAV servers MUST rely on the value of the CALDAV:calendar-timezone property, if it's defined. if that's not defined either, CalDAV servers MAY rely on whatever time zone they choose ๐Ÿคทโ€โ™€๏ธ

for the CALDAV:free-busy-query REPORT, CalDAV servers MUST rely on the value of the CALDAV:calendar-timezone property, if it's defined, to work out the proper FREEBUSY time period value as date with UTC time for calendar components scheduled with "floating date" or "floating time" ๐Ÿฆ‹ if CALDAV:calendar-timezone isn't defined, CalDAV servers MAY rely on the time zone of their choice ๐Ÿ“

7.4. Time Range Filtering โณ

some reports in this section can include a time range filter, which limits the calendar object resources returned to only the ones that overlap the requested time range โœจ the filter can apply to a calendar component as a whole, or to specific calendar component properties with DATE or DATE-TIME value types ๐Ÿซง

to figure out if a calendar object resource matches the time range filter element, the start and end times of the targeted component or property are worked out and then compared to the requested time range. if there's any overlap, the resource matches the filter element ๐Ÿ’œ the rules in [RFC2445] for finding the actual start and end times of calendar components MUST be used, and they're fully listed in Section 9.9 of this document ๐Ÿ“–

when you're doing time range filtering, recurring calendar components like VEVENT and VTODO need special care ๐Ÿ” the server MUST expand recurring components to check whether any recurrence instances overlap the specified time range. if one or more recurrence instances overlap it, the calendar object resource matches the filter element ๐Ÿ’…

7.5. Searching Text: Collations ๐Ÿ”ค

some reports in this section do text matches on character strings the client gives you, and compare them against stored calendar data ๐Ÿ“ iCalendar data is UTF-8 by default and can include non-US-ASCII characters in some property and parameter values, so text matching needs well-defined rules, no cap ๐Ÿ˜ญ

to handle that, this spec uses the IANA Collation Registry defined in [RFC4790] to specify collations for text comparison with a well-defined rule ๐ŸŽ€

all the comparisons in CalDAV are "substring" matches, as per Section 4.2 of [RFC4790]. collations the server supports MUST support "substring" match operations ๐Ÿ’–

CalDAV servers are REQUIRED to support the "i;ascii-casemap" and "i;octet" collations, as described in [RFC4790], and they MAY support other collations too ๐ŸŒธ

servers MUST advertise the collations they support via the CALDAV:supported-collation-set property, defined on any resource that supports reports using collations ๐Ÿซถ

clients MUST only use collations from the list the server advertises ๐Ÿ™…โ€โ™€๏ธ

if the client doesn't explicitly specify a collation, or specifies the "default" collation identifier (as defined in Section 3.1 of [RFC4790]), the server MUST default to using "i;ascii-casemap" as the collation ๐Ÿงš

wildcards (as defined in Section 3.2 of [RFC4790]) MUST NOT be used in the collation identifier ๐Ÿšซ

and if the client picks a collation the server doesn't support, the server MUST respond with a CALDAV:supported-collation precondition error response ๐Ÿ’€

7.5.1. CALDAV:supported-collation-set Property ๐Ÿ’…

Name: supported-collation-set ๐ŸŽ€

Namespace: urn:ietf:params:xml:ns:caldav โœจ

Purpose: This is the server's little list of collations it can actually handle for text matching ๐Ÿ’– It identifies the set of collations the server supports for text matching operations.

Conformance: This one is not optional, bestie ๐Ÿ˜ญ This property MUST be defined on any resource that supports a report that does text matching. If it is defined, it MUST be protected, and it SHOULD NOT be returned by a PROPFIND DAV:allprop request (as defined in Section 12.14.1 of [RFC2518]) ๐Ÿ™ˆ

Description: The CALDAV:supported-collation-set property holds zero or more CALDAV:supported-collation elements. Each one names a collection identifier for a collation the server supports ๐Ÿ“

Definition:

<!ELEMENT supported-collation-set (supported-collation*)>

<!ELEMENT supported-collation (#PCDATA)>

Example:

<C:supported-collation-set
    xmlns:C="urn:ietf:params:xml:ns:caldav">
  <C:supported-collation>i;ascii-casemap</C:supported-collation>
  <C:supported-collation>i;octet</C:supported-collation>
</C:supported-collation-set>

7.6. Partial Retrieval ๐Ÿฆ‹

Okay so some calendaring reports in this document let you grab only part of a calendar object resource, which is honestly so smart ๐Ÿงš A CalDAV client can say exactly what it wants back in the body of a calendaring REPORT request.

A CalDAV client can ask for particular WebDAV property values, all of them, or just a list of the names of the resource's WebDAV properties. It can also ask for calendar data to come back, and it can pick whether it wants every component and property or only specific ones. Check out CALDAV:calendar-data in Section 9.6 for the details ๐Ÿ’œ

By default, the returned calendar data includes the component that defines the recurrence set, which is called the "master component," along with the components that define exceptions to that recurrence set, called the "overridden components" ๐ŸŒธ

A CalDAV client that only cares about recurrence instances overlapping a certain time range can ask for just the "master component," plus any "overridden components" that affect that time range. That way the server sends much less data (see CALDAV:limit-recurrence-set in Section 9.6.6) ๐Ÿ”ฅ An overridden component affects a time range if its current start and end times overlap it. It also counts if the original start and end times (the ones that would have been used if the instance weren't overridden) overlap it, or if it changes other instances that overlap it.

A CalDAV client with no support for recurrence properties (EXDATE, EXRULE, RDATE, and RRULE) and possibly VTIMEZONE components, or a client that isn't up for doing recurrence expansion because its processing power is limited, can ask for only the recurrence instances overlapping a time range. Each one comes back as its own separate calendar component that defines exactly one recurrence instance (see CALDAV:expand in Section 9.6.5) โญ

Last but not least, for VFREEBUSY components, a CalDAV client can ask to receive only the FREEBUSY property values that overlap a specified time range (see CALDAV:limit-freebusy-set in Section 9.6.7) ๐Ÿง


7.7. Non-Standard Components, Properties, and Parameters ๐ŸŒˆ

Servers MUST support non-standard component, property, or parameter names inside the CALDAV:calendar-data XML element in calendaring REPORT requests. This lets clients ask for non-standard components, properties, and parameters to be included in the calendar data in the response ๐Ÿซถ

Servers MAY also support non-standard component, property, or parameter names in the CALDAV:comp-filter, CALDAV:prop-filter, and CALDAV:param-filter XML elements that sit inside the CALDAV:filter XML element of calendaring REPORT requests ๐Ÿฆ‹

Servers MUST fail with the CALDAV:supported-filter precondition if a calendaring REPORT request uses a CALDAV:comp-filter, CALDAV:prop-filter, or CALDAV:param-filter XML element that points at a non-standard component, property, or parameter name the server doesn't support queries on. This one is serious ๐Ÿ’€

7.8. CALDAV:calendar-query REPORT ๐Ÿ‘‘

The CALDAV:calendar-query REPORT searches for every calendar object resource that matches a given filter ๐Ÿ” The response includes all the WebDAV properties and calendar object resource data that the request asked for. When it comes to CALDAV:calendar-data, you can explicitly say which calendar components and properties should come back in the data for matching resources ๐Ÿ’…

This report is modeled on the PROPFIND method, so it uses many of the same XML elements. The request can ask for WebDAV properties to be returned too. When it does, the response should behave the same way PROPFIND does with the DAV:multistatus response elements that return specific property results. For example, asking for the value of a property that doesn't exist is an error, and it MUST be noted with a response XML element containing a 404 (Not Found) status value ๐Ÿ™ˆ

Support for the CALDAV:calendar-query REPORT is REQUIRED. No cap, it's not a suggestion ๐Ÿ”ฅ

Marshalling:

The request body MUST be a CALDAV:calendar-query XML element, as defined in Section 9.5 ๐ŸŽ€

The request MAY include a Depth header. If there's no Depth header, Depth:0 is assumed โœจ

For a successful request, the response body MUST be a DAV:multistatus XML element. In other words, it uses the same format as a PROPFIND response. If there are no response elements, the returned DAV:multistatus XML element is empty ๐ŸŒธ

For a successful CALDAV:calendar-query REPORT request, the response body MUST contain a DAV:response element for each iCalendar object that matched the search filter. The calendar data comes back in the CALDAV:calendar-data XML element inside the DAV:propstat XML element ๐Ÿงš

Preconditions:

(CALDAV:supported-calendar-data): The "content-type" and "version" attributes of the CALDAV:calendar-data XML element (see Section 9.6) specify a media type the server supports for calendar object resources ๐Ÿ’–

(CALDAV:valid-filter): The CALDAV:filter XML element (see Section 9.7) in the REPORT request MUST be valid. For instance, a CALDAV:filter cannot nest a <C:comp name="VEVENT"> element inside a <C:comp name="VTODO"> element, and it cannot nest a <C:time-range start="..." end="..."> element inside a <C:prop name="SUMMARY"> element. Not me trying to nest a VEVENT inside a VTODO ๐Ÿ™ˆ

(CALDAV:supported-filter): The CALDAV:comp-filter (see Section 9.7.1), CALDAV:prop-filter (see Section 9.7.2), and CALDAV:param-filter (see Section 9.7.3) XML elements inside the CALDAV:filter XML element (see Section 9.7) of the REPORT request only reference components, properties, and parameters that the server supports querying. In other words, if the CALDAV:filter element tries to reference an unsupported component, property, or parameter, this precondition is violated. Servers SHOULD report the CALDAV:comp-filter, CALDAV:prop-filter, or CALDAV:param-filter that they don't support ๐Ÿ“

<!ELEMENT supported-filter (comp-filter*,
                            prop-filter*,
                            param-filter*)>

(CALDAV:valid-calendar-data): The time zone specified in the REPORT request MUST be a valid iCalendar object containing a single valid VTIMEZONE component ๐ŸŒ

(CALDAV:min-date-time): Any XML element that specifies a range of time MUST have its start or end DATE or DATE-TIME values greater than or equal to the CALDAV:min-date-time property value (Section 5.2.6) on the calendar collections the REPORT request targets. ๐Ÿ“…

(CALDAV:max-date-time): Any XML element that specifies a range of time MUST have its start or end DATE or DATE-TIME values less than or equal to the CALDAV:max-date-time property value (Section 5.2.7) on the calendar collections the REPORT request targets. ๐Ÿ“…

(CALDAV:supported-collation): Any XML attribute that specifies a collation MUST specify a collation the server supports, as described in Section 7.5 ๐Ÿซถ

Postconditions:

(DAV:number-of-matches-within-limits): The number of matching calendar object resources must fall within server-specific, predefined limits. For example, this condition might be triggered if a search would return an extremely large number of responses ๐Ÿ˜ญ

7.8.1. Example: Partial Retrieval of Events by Time Range โœจ

okay so this example is giving main character energy ๐Ÿ’… The client asks the server for certain components and properties of the VEVENT components that overlap the time range from January 4, 2006, at 00:00:00 UTC to January 5, 2006, at 00:00:00 UTC ๐ŸŒธ It also asks for DAV:getetag, and that comes back in the response too.

Here's the tea ๐Ÿซ– The first calendar object is a recurring event whose first instance sits outside the requested range, but its third instance does overlap. Because of the CALDAV:calendar-data element restrictions, the DTSTAMP property in the VEVENT components doesn't get returned, and the only property that shows up in the VCALENDAR object is VERSION ๐Ÿ™ˆ

See Appendix B for the calendar data this example is targeting ๐ŸŽ€

>> Request <<

REPORT /bernard/work/ HTTP/1.1
Host: cal.example.com
Depth: 1
Content-Type: application/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<C:calendar-query xmlns:D="DAV:"
              xmlns:C="urn:ietf:params:xml:ns:caldav">
  <D:prop>
    <D:getetag/>
    <C:calendar-data>
      <C:comp name="VCALENDAR">
        <C:prop name="VERSION"/>
        <C:comp name="VEVENT">
          <C:prop name="SUMMARY"/>
          <C:prop name="UID"/>
          <C:prop name="DTSTART"/>
          <C:prop name="DTEND"/>
          <C:prop name="DURATION"/>
          <C:prop name="RRULE"/>
          <C:prop name="RDATE"/>
          <C:prop name="EXRULE"/>
          <C:prop name="EXDATE"/>
          <C:prop name="RECURRENCE-ID"/>
        </C:comp>
        <C:comp name="VTIMEZONE"/>
      </C:comp>
    </C:calendar-data>
  </D:prop>
  <C:filter>
    <C:comp-filter name="VCALENDAR">
      <C:comp-filter name="VEVENT">
        <C:time-range start="20060104T000000Z"
                      end="20060105T000000Z"/>
      </C:comp-filter>
    </C:comp-filter>
  </C:filter>
</C:calendar-query>

>> Response <<

HTTP/1.1 207 Multi-Status
Date: Sat, 11 Nov 2006 09:32:12 GMT
Content-Type: application/xml; charset="utf-8"
Content-Length: xxxx
<?xml version="1.0" encoding="utf-8" ?>
<D:multistatus xmlns:D="DAV:"
           xmlns:C="urn:ietf:params:xml:ns:caldav">
  <D:response>
    <D:href>http://cal.example.com/bernard/work/abcd2.ics</D:href>
    <D:propstat>
      <D:prop>
        <D:getetag>"fffff-abcd2"</D:getetag>
        <C:calendar-data>BEGIN:VCALENDAR
VERSION:2.0
BEGIN:VTIMEZONE
LAST-MODIFIED:20040110T032845Z
TZID:US/Eastern
BEGIN:DAYLIGHT
DTSTART:20000404T020000
RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:20001026T020000
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
DTSTART;TZID=US/Eastern:20060102T120000
DURATION:PT1H
RRULE:FREQ=DAILY;COUNT=5
SUMMARY:Event #2
UID:00959BC664CA650E933C892C@example.com
END:VEVENT
BEGIN:VEVENT
DTSTART;TZID=US/Eastern:20060104T140000
DURATION:PT1H
RECURRENCE-ID;TZID=US/Eastern:20060104T120000
SUMMARY:Event #2 bis
UID:00959BC664CA650E933C892C@example.com
END:VEVENT
BEGIN:VEVENT
DTSTART;TZID=US/Eastern:20060106T140000
DURATION:PT1H
RECURRENCE-ID;TZID=US/Eastern:20060106T120000
SUMMARY:Event #2 bis bis
UID:00959BC664CA650E933C892C@example.com
END:VEVENT
END:VCALENDAR
</C:calendar-data>
      </D:prop>
      <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>
  </D:response>
  <D:response>
    <D:href>http://cal.example.com/bernard/work/abcd3.ics</D:href>
    <D:propstat>
      <D:prop>
        <D:getetag>"fffff-abcd3"</D:getetag>
        <C:calendar-data>BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp.//CalDAV Client//EN
BEGIN:VTIMEZONE
LAST-MODIFIED:20040110T032845Z
TZID:US/Eastern
BEGIN:DAYLIGHT
DTSTART:20000404T020000
RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:20001026T020000
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
DTSTART;TZID=US/Eastern:20060104T100000
DURATION:PT1H
SUMMARY:Event #3
UID:DC6C50A017428C5216A2F1CD@example.com
END:VEVENT
END:VCALENDAR
</C:calendar-data>
      </D:prop>
      <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>
  </D:response>
</D:multistatus>

7.8.2. Example: Partial Retrieval of Recurring Events ๐Ÿฆ‹

this one's all about asking for VEVENT components that overlap the time range from January 3, 2006, at 00:00:00 UTC to January 5, 2006, at 00:00:00 UTC ๐Ÿ’– The CALDAV:limit-recurrence-set element is the star here. It tells the server to only send back overridden recurrence components that overlap the range in that element, or that affect other instances overlapping the range (like with a THISANDFUTURE behavior) โœจ In this example, the first overridden component in the matching resource comes back, but the second one gets left out ๐Ÿซถ

See Appendix B for the calendar data this example is targeting ๐ŸŒˆ

>> Request <<

REPORT /bernard/work/ HTTP/1.1
Host: cal.example.com
Depth: 1
Content-Type: application/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<C:calendar-query xmlns:D="DAV:"
                  xmlns:C="urn:ietf:params:xml:ns:caldav">
  <D:prop>
    <C:calendar-data>
      <C:limit-recurrence-set start="20060103T000000Z"
                              end="20060105T000000Z"/>
    </C:calendar-data>
  </D:prop>
  <C:filter>
    <C:comp-filter name="VCALENDAR">
      <C:comp-filter name="VEVENT">
        <C:time-range start="20060103T000000Z"
                      end="20060105T000000Z"/>
      </C:comp-filter>
    </C:comp-filter>
  </C:filter>
</C:calendar-query>

>> Response <<

HTTP/1.1 207 Multi-Status
Date: Sat, 11 Nov 2006 09:32:12 GMT
Content-Type: application/xml; charset="utf-8"
Content-Length: xxxx
<?xml version="1.0" encoding="utf-8" ?>
<D:multistatus xmlns:D="DAV:"
           xmlns:C="urn:ietf:params:xml:ns:caldav">
  <D:response>
    <D:href>http://cal.example.com/bernard/work/abcd2.ics</D:href>
    <D:propstat>
      <D:prop>
        <D:getetag>"fffff-abcd2"</D:getetag>
        <C:calendar-data>BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp.//CalDAV Client//EN
BEGIN:VTIMEZONE
LAST-MODIFIED:20040110T032845Z
TZID:US/Eastern
BEGIN:DAYLIGHT
DTSTART:20000404T020000
RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:20001026T020000
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
DTSTAMP:20060206T001121Z
DTSTART;TZID=US/Eastern:20060102T120000
DURATION:PT1H
RRULE:FREQ=DAILY;COUNT=5
SUMMARY:Event #2
UID:00959BC664CA650E933C892C@example.com
END:VEVENT
BEGIN:VEVENT
DTSTAMP:20060206T001121Z
DTSTART;TZID=US/Eastern:20060104T140000
DURATION:PT1H
RECURRENCE-ID;TZID=US/Eastern:20060104T120000
SUMMARY:Event #2 bis
UID:00959BC664CA650E933C892C@example.com
END:VEVENT
END:VCALENDAR
</C:calendar-data>
      </D:prop>
      <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>
  </D:response>
  <D:response>
    <D:href>http://cal.example.com/bernard/work/abcd3.ics</D:href>
    <D:propstat>
      <D:prop>
        <D:getetag>"fffff-abcd3"</D:getetag>
        <C:calendar-data>BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp.//CalDAV Client//EN
BEGIN:VTIMEZONE
LAST-MODIFIED:20040110T032845Z
TZID:US/Eastern
BEGIN:DAYLIGHT
DTSTART:20000404T020000
RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:20001026T020000
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
ATTENDEE;PARTSTAT=ACCEPTED;ROLE=CHAIR:mailto:cyrus@example.com
ATTENDEE;PARTSTAT=NEEDS-ACTION:mailto:lisa@example.com
DTSTAMP:20060206T001220Z
DTSTART;TZID=US/Eastern:20060104T100000
DURATION:PT1H
LAST-MODIFIED:20060206T001330Z
ORGANIZER:mailto:cyrus@example.com
SEQUENCE:1
STATUS:TENTATIVE
SUMMARY:Event #3
UID:DC6C50A017428C5216A2F1CD@example.com
X-ABC-GUID:E1CX5Dr-0007ym-Hz@example.com
END:VEVENT
END:VCALENDAR
</C:calendar-data>
      </D:prop>
      <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>
  </D:response>
</D:multistatus>

7.8.3. Example: Expanded Retrieval of Recurring Events โœจ

okay so bestie, this one is giving "give me every single occurrence, but make it readable" ๐Ÿฆ‹ The client asks the server for VEVENTs that overlap the window from January 2, 2006, at 00:00:00 A.M. UTC to January 5, 2006, at 00:00:00 A.M. UTC. It also wants recurring components expanded into individual recurrence instance components, which is what CALDAV:expand does ๐Ÿ’… Also, the server only returns overridden recurrence instances that overlap the time range given in that expand element. Iconic restraint ๐Ÿ‘‘

See Appendix B for the calendar data being targeted by this example. ๐Ÿงš

Request <<
REPORT /bernard/work/ HTTP/1.1
Host: cal.example.com
Depth: 1
Content-Type: application/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<C:calendar-query xmlns:D="DAV:"
                  xmlns:C="urn:ietf:params:xml:ns:caldav">
  <D:prop>
    <C:calendar-data>
      <C:expand start="20060103T000000Z"
                end="20060105T000000Z"/>
    </C:calendar-data>
  </D:prop>
  <C:filter>
    <C:comp-filter name="VCALENDAR">
      <C:comp-filter name="VEVENT">
        <C:time-range start="20060103T000000Z"
                      end="20060105T000000Z"/>
      </C:comp-filter>
    </C:comp-filter>
  </C:filter>
</C:calendar-query>
Response <<
HTTP/1.1 207 Multi-Status
Date: Sat, 11 Nov 2006 09:32:12 GMT
Content-Type: application/xml; charset="utf-8"
Content-Length: xxxx
<?xml version="1.0" encoding="utf-8" ?>
<D:multistatus xmlns:D="DAV:"
           xmlns:C="urn:ietf:params:xml:ns:caldav">
  <D:response>
    <D:href>http://cal.example.com/bernard/work/abcd2.ics</D:href>
    <D:propstat>
      <D:prop>
        <D:getetag>"fffff-abcd2"</D:getetag>
        <C:calendar-data>BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp.//CalDAV Client//EN
BEGIN:VEVENT
DTSTAMP:20060206T001121Z
DTSTART:20060103T170000
DURATION:PT1H
RECURRENCE-ID:20060103T170000
SUMMARY:Event #2
UID:00959BC664CA650E933C892C@example.com
END:VEVENT
BEGIN:VEVENT
DTSTAMP:20060206T001121Z
DTSTART:20060104T190000
DURATION:PT1H
RECURRENCE-ID:20060104T170000
SUMMARY:Event #2 bis
UID:00959BC664CA650E933C892C@example.com
END:VEVENT
END:VCALENDAR
</C:calendar-data>
      </D:prop>
      <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>
  </D:response>
  <D:response>
    <D:href>http://cal.example.com/bernard/work/abcd3.ics</D:href>
    <D:propstat>
      <D:prop>
        <D:getetag>"fffff-abcd3"</D:getetag>
        <C:calendar-data>BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp.//CalDAV Client//EN
BEGIN:VEVENT
ATTENDEE;PARTSTAT=ACCEPTED;ROLE=CHAIR:mailto:cyrus@example.com
ATTENDEE;PARTSTAT=NEEDS-ACTION:mailto:lisa@example.com
DTSTAMP:20060206T001220Z
DTSTART:20060104T150000
DURATION:PT1H
LAST-MODIFIED:20060206T001330Z
ORGANIZER:mailto:cyrus@example.com
SEQUENCE:1
STATUS:TENTATIVE
SUMMARY:Event #3
UID:DC6C50A017428C5216A2F1CD@example.com
X-ABC-GUID:E1CX5Dr-0007ym-Hz@example.com
END:VEVENT
END:VCALENDAR
</C:calendar-data>
      </D:prop>
      <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>
  </D:response>
</D:multistatus>

7.8.4. Example: Partial Retrieval of Stored Free Busy Components ๐Ÿซถ

in this one the client wants the VFREEBUSY components with free busy info overlapping January 2, 2006, at 00:00:00 A.M. UTC (inclusive) up to January 3, 2006, at 00:00:00 A.M. UTC (exclusive) ๐Ÿ“… CALDAV:limit-freebusy-set tells the server to only send back the FREEBUSY property values that overlap that range. Also, and this matters ๐Ÿ™ˆ, this is not an example of figuring out when the calendar owner is busy. It's just retrieving what's stored.

See Appendix B for the calendar data being targeted by this example. ๐ŸŒธ

Request <<
REPORT /bernard/work/ HTTP/1.1
Host: cal.example.com
Depth: 1
Content-Type: application/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<C:calendar-query xmlns:D="DAV:"
              xmlns:C="urn:ietf:params:xml:ns:caldav">
  <D:prop>
    <C:calendar-data>
      <C:limit-freebusy-set start="20060102T000000Z"
                              end="20060103T000000Z"/>
    </C:calendar-data>
  </D:prop>
  <C:filter>
    <C:comp-filter name="VCALENDAR">
      <C:comp-filter name="VFREEBUSY">
        <C:time-range start="20060102T000000Z"
                        end="20060103T000000Z"/>
      </C:comp-filter>
    </C:comp-filter>
  </C:filter>
</C:calendar-query>
Response <<
HTTP/1.1 207 Multi-Status
Date: Sat, 11 Nov 2006 09:32:12 GMT
Content-Type: application/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<D:multistatus xmlns:D="DAV:"
               xmlns:C="urn:ietf:params:xml:ns:caldav">
  <D:response>
    <D:href>http://cal.example.com/bernard/work/abcd8.ics</D:href>
    <D:propstat>
      <D:prop>
        <D:getetag>"fffff-abcd8"</D:getetag>
        <C:calendar-data>BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp.//CalDAV Client//EN
BEGIN:VFREEBUSY
ORGANIZER;CN="Bernard Desruisseaux":mailto:bernard@example.com
UID:76ef34-54a3d2@example.com
DTSTAMP:20050530T123421Z
DTSTART:20060101T100000Z
DTEND:20060108T100000Z
FREEBUSY;FBTYPE=BUSY-TENTATIVE:20060102T100000Z/20060102T120000Z
END:VFREEBUSY
END:VCALENDAR
</C:calendar-data>
      </D:prop>
      <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>
  </D:response>
</D:multistatus>

7.8.5. Example: Retrieval of To-Dos by Alarm Time Range โฐ

here the client asks for VTODO components with an alarm trigger scheduled inside the given time range. Main character energy for your reminders ๐Ÿ’…

See Appendix B for the calendar data being targeted by this example. ๐Ÿ“

Request <<
REPORT /bernard/work/ HTTP/1.1
Host: cal.example.com
Depth: 1
Content-Type: application/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<C:calendar-query xmlns:C="urn:ietf:params:xml:ns:caldav">
  <D:prop xmlns:D="DAV:">
    <D:getetag/>
    <C:calendar-data/>
  </D:prop>
  <C:filter>
    <C:comp-filter name="VCALENDAR">
      <C:comp-filter name="VTODO">
        <C:comp-filter name="VALARM">
          <C:time-range start="20060106T100000Z"
                          end="20060107T100000Z"/>
        </C:comp-filter>
      </C:comp-filter>
    </C:comp-filter>
  </C:filter>
</C:calendar-query>
Response <<
HTTP/1.1 207 Multi-Status
Date: Sat, 11 Nov 2006 09:32:12 GMT
Content-Type: application/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<D:multistatus xmlns:D="DAV:"
               xmlns:C="urn:ietf:params:xml:ns:caldav">
  <D:response>
    <D:href>http://cal.example.com/bernard/work/abcd4.ics</D:href>
    <D:propstat>
      <D:prop>
        <D:getetag>"fffff-abcd4"</D:getetag>
        <C:calendar-data>BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp.//CalDAV Client//EN
BEGIN:VTODO
DTSTAMP:20060205T235300Z
DUE;TZID=US/Eastern:20060106T120000
LAST-MODIFIED:20060205T235308Z
SEQUENCE:1
STATUS:NEEDS-ACTION
SUMMARY:Task #2
UID:E10BA47467C5C69BB74E8720@example.com
BEGIN:VALARM
ACTION:AUDIO
TRIGGER;RELATED=START:-PT10M
END:VALARM
END:VTODO
END:VCALENDAR
</C:calendar-data>
      </D:prop>
      <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>
  </D:response>
</D:multistatus>

7.8.6. Example: Retrieval of Event by UID ๐Ÿ”

last one in this bunch, and it's so clean โœจ The client asks for the VEVENT whose UID property is set to "DC6C50A017428C5216A2F1CD@example.com". Just one event, no drama ๐Ÿ’–

See Appendix B for the calendar data being targeted by this example. ๐ŸŽ€

Request <<
REPORT /bernard/work/ HTTP/1.1
Host: cal.example.com
Depth: 1
Content-Type: application/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<C:calendar-query xmlns:C="urn:ietf:params:xml:ns:caldav">
  <D:prop xmlns:D="DAV:">
    <D:getetag/>
    <C:calendar-data/>
  </D:prop>
  <C:filter>
    <C:comp-filter name="VCALENDAR">
      <C:comp-filter name="VEVENT">
        <C:prop-filter name="UID">
          <C:text-match collation="i;octet"
          >DC6C50A017428C5216A2F1CD@example.com</C:text-match>
        </C:prop-filter>
      </C:comp-filter>
    </C:comp-filter>
  </C:filter>
</C:calendar-query>
Response <<
HTTP/1.1 207 Multi-Status
Date: Sat, 11 Nov 2006 09:32:12 GMT
Content-Type: application/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<D:multistatus xmlns:D="DAV:"
               xmlns:C="urn:ietf:params:xml:ns:caldav">
  <D:response>
    <D:href>http://cal.example.com/bernard/work/abcd3.ics</D:href>
    <D:propstat>
      <D:prop>
        <D:getetag>"fffff-abcd3"</D:getetag>
        <C:calendar-data>BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp.//CalDAV Client//EN
BEGIN:VTIMEZONE
LAST-MODIFIED:20040110T032845Z
TZID:US/Eastern
BEGIN:DAYLIGHT
DTSTART:20000404T020000
RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:20001026T020000
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
ATTENDEE;PARTSTAT=ACCEPTED;ROLE=CHAIR:mailto:cyrus@example.com
ATTENDEE;PARTSTAT=NEEDS-ACTION:mailto:lisa@example.com
DTSTAMP:20060206T001220Z
DTSTART;TZID=US/Eastern:20060104T100000
DURATION:PT1H
LAST-MODIFIED:20060206T001330Z
ORGANIZER:mailto:cyrus@example.com
SEQUENCE:1
STATUS:TENTATIVE
SUMMARY:Event #3
UID:DC6C50A017428C5216A2F1CD@example.com
X-ABC-GUID:E1CX5Dr-0007ym-Hz@example.com
END:VEVENT
END:VCALENDAR
</C:calendar-data>
      </D:prop>
      <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>
  </D:response>
</D:multistatus>

7.8.7. Example: Retrieval of Events by PARTSTAT โœจ

okay so in this example, the client asks the server for the VEVENT components where the ATTENDEE property is mailto:lisa@example.com and the PARTSTAT parameter is NEEDS-ACTION. lisa still needs to respond, so this is her to-do list ๐Ÿ’…๐ŸŽ€

See Appendix B for the calendar data being targeted by this example. ๐Ÿฆ‹

>> Request <<

REPORT /bernard/work/ HTTP/1.1
Host: cal.example.com
Depth: 1
Content-Type: application/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<C:calendar-query xmlns:C="urn:ietf:params:xml:ns:caldav">
  <D:prop xmlns:D="DAV:">
    <D:getetag/>
    <C:calendar-data/>
  </D:prop>
  <C:filter>
    <C:comp-filter name="VCALENDAR">
      <C:comp-filter name="VEVENT">
        <C:prop-filter name="ATTENDEE">
          <C:text-match collation="i;ascii-casemap"
           >mailto:lisa@example.com</C:text-match>
          <C:param-filter name="PARTSTAT">
            <C:text-match collation="i;ascii-casemap"
             >NEEDS-ACTION</C:text-match>
          </C:param-filter>
        </C:prop-filter>
      </C:comp-filter>
    </C:comp-filter>
  </C:filter>
</C:calendar-query>

>> Response <<

HTTP/1.1 207 Multi-Status
Date: Sat, 11 Nov 2006 09:32:12 GMT
Content-Type: application/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<D:multistatus xmlns:D="DAV:"
               xmlns:C="urn:ietf:params:xml:ns:caldav">
  <D:response>
    <D:href>http://cal.example.com/bernard/work/abcd3.ics</D:href>
    <D:propstat>
      <D:prop>
        <D:getetag>"fffff-abcd3"</D:getetag>
        <C:calendar-data>BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp.//CalDAV Client//EN
BEGIN:VTIMEZONE
LAST-MODIFIED:20040110T032845Z
TZID:US/Eastern
BEGIN:DAYLIGHT
DTSTART:20000404T020000
RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:20001026T020000
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
ATTENDEE;PARTSTAT=ACCEPTED;ROLE=CHAIR:mailto:cyrus@example.com
ATTENDEE;PARTSTAT=NEEDS-ACTION:mailto:lisa@example.com
DTSTAMP:20060206T001220Z
DTSTART;TZID=US/Eastern:20060104T100000
DURATION:PT1H
LAST-MODIFIED:20060206T001330Z
ORGANIZER:mailto:cyrus@example.com
SEQUENCE:1
STATUS:TENTATIVE
SUMMARY:Event #3
UID:DC6C50A017428C5216A2F1CD@example.com
X-ABC-GUID:E1CX5Dr-0007ym-Hz@example.com
END:VEVENT
END:VCALENDAR
</C:calendar-data>
      </D:prop>
      <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>
  </D:response>
</D:multistatus>

7.8.8. Example: Retrieval of Events Only ๐ŸŒธ

in this one, the client asks the server to hand back every single VEVENT component. no filtering drama, just all the events ๐Ÿฅฐ

See Appendix B for the calendar data being targeted by this example. ๐Ÿฆ‹

>> Request <<

REPORT /bernard/work/ HTTP/1.1
Host: cal.example.com
Depth: 1
Content-Type: application/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<C:calendar-query xmlns:C="urn:ietf:params:xml:ns:caldav">
  <D:prop xmlns:D="DAV:">
    <D:getetag/>
    <C:calendar-data/>
  </D:prop>
  <C:filter>
    <C:comp-filter name="VCALENDAR">
      <C:comp-filter name="VEVENT"/>
    </C:comp-filter>
  </C:filter>
</C:calendar-query>

>> Response <<

HTTP/1.1 207 Multi-Status
Date: Sat, 11 Nov 2006 09:32:12 GMT
Content-Type: application/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<D:multistatus xmlns:D="DAV:"
               xmlns:C="urn:ietf:params:xml:ns:caldav">
  <D:response>
    <D:href>http://cal.example.com/bernard/work/abcd1.ics</D:href>
    <D:propstat>
      <D:prop>
        <D:getetag>"fffff-abcd1"</D:getetag>
        <C:calendar-data>BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp.//CalDAV Client//EN
BEGIN:VTIMEZONE
LAST-MODIFIED:20040110T032845Z
TZID:US/Eastern
BEGIN:DAYLIGHT
DTSTART:20000404T020000
RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:20001026T020000
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
DTSTAMP:20060206T001102Z
DTSTART;TZID=US/Eastern:20060102T100000
DURATION:PT1H
SUMMARY:Event #1
Description:Go Steelers!
UID:74855313FA803DA593CD579A@example.com
END:VEVENT
END:VCALENDAR
</C:calendar-data>
      </D:prop>
      <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>
  </D:response>
  <D:response>
    <D:href>http://cal.example.com/bernard/work/abcd2.ics</D:href>
    <D:propstat>
      <D:prop>
        <D:getetag>"fffff-abcd2"</D:getetag>
        <C:calendar-data>BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp.//CalDAV Client//EN
BEGIN:VTIMEZONE
LAST-MODIFIED:20040110T032845Z
TZID:US/Eastern
BEGIN:DAYLIGHT
DTSTART:20000404T020000
RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:20001026T020000
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
DTSTAMP:20060206T001121Z
DTSTART;TZID=US/Eastern:20060102T120000
DURATION:PT1H
RRULE:FREQ=DAILY;COUNT=5
SUMMARY:Event #2
UID:00959BC664CA650E933C892C@example.com
END:VEVENT
BEGIN:VEVENT
DTSTAMP:20060206T001121Z
DTSTART;TZID=US/Eastern:20060104T140000
DURATION:PT1H
RECURRENCE-ID;TZID=US/Eastern:20060104T120000
SUMMARY:Event #2 bis
UID:00959BC664CA650E933C892C@example.com
END:VEVENT
BEGIN:VEVENT
DTSTAMP:20060206T001121Z
DTSTART;TZID=US/Eastern:20060106T140000
DURATION:PT1H
RECURRENCE-ID;TZID=US/Eastern:20060106T120000
SUMMARY:Event #2 bis bis
UID:00959BC664CA650E933C892C@example.com
END:VEVENT
END:VCALENDAR
</C:calendar-data>
      </D:prop>
      <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>
  </D:response>
  <D:response>
    <D:href>http://cal.example.com/bernard/work/abcd3.ics</D:href>
    <D:propstat>
      <D:prop>
        <D:getetag>"fffff-abcd3"</D:getetag>
        <C:calendar-data>BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp.//CalDAV Client//EN
BEGIN:VTIMEZONE
LAST-MODIFIED:20040110T032845Z
TZID:US/Eastern
BEGIN:DAYLIGHT
DTSTART:20000404T020000
RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:20001026T020000
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
ATTENDEE;PARTSTAT=ACCEPTED;ROLE=CHAIR:mailto:cyrus@example.com
ATTENDEE;PARTSTAT=NEEDS-ACTION:mailto:lisa@example.com
DTSTAMP:20060206T001220Z
DTSTART;TZID=US/Eastern:20060104T100000
DURATION:PT1H
LAST-MODIFIED:20060206T001330Z
ORGANIZER:mailto:cyrus@example.com
SEQUENCE:1
STATUS:TENTATIVE
SUMMARY:Event #3
UID:DC6C50A017428C5216A2F1CD@example.com
X-ABC-GUID:E1CX5Dr-0007ym-Hz@example.com
END:VEVENT
END:VCALENDAR
</C:calendar-data>
      </D:prop>
      <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>
  </D:response>
</D:multistatus>

7.8.9. Example: Retrieval of All Pending To-Dos ๐Ÿ“

so here the client wants every VTODO that has no COMPLETED property and whose STATUS value isn't CANCELLED. in other words, the tasks that are still waiting to get done. the not-finished-yet crew ๐Ÿ“๐Ÿ’œ

See Appendix B for the calendar data being targeted by this example. ๐Ÿฆ‹

>> Request <<

REPORT /bernard/work/ HTTP/1.1
Host: cal.example.com
Depth: 1
Content-Type: application/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<C:calendar-query xmlns:C="urn:ietf:params:xml:ns:caldav">
  <D:prop xmlns:D="DAV:">
    <D:getetag/>
    <C:calendar-data/>
  </D:prop>
  <C:filter>
    <C:comp-filter name="VCALENDAR">
      <C:comp-filter name="VTODO">
        <C:prop-filter name="COMPLETED">
          <C:is-not-defined/>
        </C:prop-filter>
        <C:prop-filter name="STATUS">
          <C:text-match
             negate-condition="yes">CANCELLED</C:text-match>
        </C:prop-filter>
      </C:comp-filter>
    </C:comp-filter>
  </C:filter>
</C:calendar-query>

>> Response <<

HTTP/1.1 207 Multi-Status
Date: Sat, 11 Nov 2006 09:32:12 GMT
Content-Type: application/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<D:multistatus xmlns:D="DAV:"
               xmlns:C="urn:ietf:params:xml:ns:caldav">
  <D:response>
    <D:href>http://cal.example.com/bernard/work/abcd4.ics</D:href>
    <D:propstat>
      <D:prop>
        <D:getetag>"fffff-abcd4"</D:getetag>
        <C:calendar-data>BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp.//CalDAV Client//EN
BEGIN:VTODO
DTSTAMP:20060205T235335Z
DUE;VALUE=DATE:20060104
STATUS:NEEDS-ACTION
SUMMARY:Task #1
UID:DDDEEB7915FA61233B861457@example.com
BEGIN:VALARM
ACTION:AUDIO
TRIGGER;RELATED=START:-PT10M
END:VALARM
END:VTODO
END:VCALENDAR
</C:calendar-data>
      </D:prop>
      <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>
  </D:response>

  <D:response>
    <D:href>http://cal.example.com/bernard/work/abcd5.ics</D:href>
    <D:propstat>
      <D:prop>
        <D:getetag>"fffff-abcd5"</D:getetag>
        <C:calendar-data>BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp.//CalDAV Client//EN
BEGIN:VTODO
DTSTAMP:20060205T235300Z
DUE;VALUE=DATE:20060106
LAST-MODIFIED:20060205T235308Z
SEQUENCE:1
STATUS:NEEDS-ACTION
SUMMARY:Task #2
UID:E10BA47467C5C69BB74E8720@example.com
BEGIN:VALARM
ACTION:AUDIO
TRIGGER;RELATED=START:-PT10M
END:VALARM
END:VTODO
END:VCALENDAR
</C:calendar-data>
      </D:prop>
      <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>
  </D:response>
</D:multistatus>

7.8.10. Example: Attempt to Query Unsupported Property

Okay bestie, this one is a little oops moment ๐Ÿ™ˆ. The client asks the server for every VEVENT that has an X-ABC-GUID property with a value matching "ABC" ๐Ÿ’…. Plot twist: the server doesn't support querying that non-standard property, so it sends back an error instead ๐Ÿ’€.

Peek at Appendix B for the calendar data this example is targeting ๐Ÿฆ‹.

Request <<
REPORT /bernard/work/ HTTP/1.1
Host: cal.example.com
Depth: 1
Content-Type: application/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<C:calendar-query xmlns:C="urn:ietf:params:xml:ns:caldav">
  <D:prop xmlns:D="DAV:">
    <D:getetag/>
    <C:calendar-data/>
  </D:prop>
  <C:filter>
    <C:comp-filter name="VCALENDAR">
      <C:comp-filter name="VEVENT">
        <C:prop-filter name="X-ABC-GUID">
          <C:text-match>ABC</C:text-match>
        </C:prop-filter>
      </C:comp-filter>
    </C:comp-filter>
  </C:filter>
</C:calendar-query>
Response <<
HTTP/1.1 403 Forbidden
Date: Sat, 11 Nov 2005 09:32:12 GMT
Content-Type: application/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<D:error>
  <C:supported-filter>
    <C:prop-filter name="X-ABC-GUID"/>
  </C:supported-filter>
</D:error>

7.9. CALDAV:calendar-multiget REPORT

The CALDAV:calendar-multiget REPORT is the "grab these exact ones" move ๐ŸŽ€. It pulls specific calendar object resources out of a collection (if the Request-URI is a collection), or fetches one specific calendar object resource (if the Request-URI is a calendar object resource). It's basically a cousin of the CALDAV:calendar-query REPORT (see Section 7.8), except instead of a CALDAV:filter element, it takes a list of DAV:href elements to decide what comes back ๐ŸŒธ.

Support for the CALDAV:calendar-multiget REPORT is REQUIRED. No skipping this one, periodt ๐Ÿ’….

Marshalling:

  • The request body MUST be a CALDAV:calendar-multiget XML element (see Section 9.10). If the Request-URI is a collection resource, the DAV:href elements MUST refer to calendar object resources within that collection, and they MAY refer to calendar object resources at any depth within the collection. Because of that, the "Depth" header MUST be ignored by the server and SHOULD NOT be sent by the client ๐Ÿ™ˆ. If the Request-URI refers to a non-collection resource, there MUST be a single DAV:href element that is equivalent to the Request-URI.
  • The response body for a successful request MUST be a DAV:multistatus XML element.
  • The response body for a successful CALDAV:calendar-multiget REPORT request MUST contain a DAV:response element for each calendar object resource referenced by the provided set of DAV:href elements. The calendar data comes back in the CALDAV:calendar-data element inside the DAV:prop element โœจ.
  • If there's an error accessing any of the provided DAV:href resources, the server MUST return the appropriate error status code in the DAV:status element of the corresponding DAV:response element.

Preconditions:

  • (CALDAV:supported-calendar-data): The "content-type" and "version" attributes of the CALDAV:calendar-data XML elements (see Section 9.6) have to specify a media type the server supports for calendar object resources ๐Ÿ“‹.
  • (CALDAV:min-date-time): Any XML element specifying a range of time MUST have its start or end DATE or DATE-TIME values greater than or equal to the CALDAV:min-date-time property value (Section 5.2.6) on the calendar collections being targeted by the REPORT request โฐ.
  • (CALDAV:max-date-time): Any XML element specifying a range of time MUST have its start or end DATE or DATE-TIME values less than or equal to the CALDAV:max-date-time property value (Section 5.2.7) on the calendar collections being targeted by the REPORT request โณ.

Postconditions:

None. Nothing extra to check after the fact ๐Ÿฆ‹.

7.9.1. Example: Successful CALDAV:calendar-multiget REPORT

In this one, the client asks for specific properties of the VEVENT components at two specific URIs ๐ŸŽ€. It also requests DAV:getetag, which comes back in the response too. Heads up: the resource at http://cal.example.com/bernard/work/mtg1.ics doesn't exist, so that one gets an error status ๐Ÿ˜ญ.

Check Appendix B for the calendar data being targeted here ๐Ÿ’œ.

Request <<
REPORT /bernard/work/ HTTP/1.1
Host: cal.example.com
Content-Type: application/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<C:calendar-multiget xmlns:D="DAV:"
                 xmlns:C="urn:ietf:params:xml:ns:caldav">
  <D:prop>
    <D:getetag/>
    <C:calendar-data/>
  </D:prop>
  <D:href>/bernard/work/abcd1.ics</D:href>
  <D:href>/bernard/work/mtg1.ics</D:href>
</C:calendar-multiget>
Response <<
HTTP/1.1 207 Multi-Status
Date: Sat, 11 Nov 2006 09:32:12 GMT
Content-Type: application/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<D:multistatus xmlns:D="DAV:"
               xmlns:C="urn:ietf:params:xml:ns:caldav">
  <D:response>
    <D:href>http://cal.example.com/bernard/work/abcd1.ics</D:href>
    <D:propstat>
      <D:prop>
        <D:getetag>"fffff-abcd1"</D:getetag>
        <C:calendar-data>BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp.//CalDAV Client//EN
BEGIN:VTIMEZONE
LAST-MODIFIED:20040110T032845Z
TZID:US/Eastern
BEGIN:DAYLIGHT
DTSTART:20000404T020000
RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:20001026T020000
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
DTSTAMP:20060206T001102Z
DTSTART;TZID=US/Eastern:20060102T100000
DURATION:PT1H
SUMMARY:Event #1
Description:Go Steelers!
UID:74855313FA803DA593CD579A@example.com
END:VEVENT
END:VCALENDAR
</C:calendar-data>
      </D:prop>
      <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>
  </D:response>
  <D:response>
    <D:href>http://cal.example.com/bernard/work/mtg1.ics</D:href>
    <D:status>HTTP/1.1 404 Not Found</D:status>

  </D:response>
</D:multistatus>

7.10. CALDAV:free-busy-query REPORT

The CALDAV:free-busy-query REPORT makes a VFREEBUSY component that shows the free/busy info for every calendar object resource the request targets, as long as the current user has the CALDAV:read-free-busy or DAV:read privilege on it ๐Ÿฆ‹. It's the "when is everyone actually free" query, and it's giving scheduling superpowers โœจ.

Only VEVENT components without a TRANSP property, or with TRANSP set to OPAQUE, count here. VFREEBUSY components SHOULD be considered too when generating the free busy time info ๐ŸŒธ.

For VEVENT components, the free or busy time type (FBTYPE) of the FREEBUSY properties in the returned VFREEBUSY component SHOULD be derived from the TRANSP and STATUS properties, following this table ๐Ÿ’œ:

      +---------------------------++------------------+
      |          VEVENT           ||    VFREEBUSY     |
      +-------------+-------------++------------------+
      | TRANSP      | STATUS      || FBTYPE           |
      +=============+=============++==================+
      |             | CONFIRMED   || BUSY             |
      |             | (default)   ||                  |
      | OPAQUE      +-------------++------------------+
      | (default)   | CANCELLED   || FREE             |
      |             +-------------++------------------+
      |             | TENTATIVE   || BUSY-TENTATIVE   |
      |             +-------------++------------------+
      |             | x-name      || BUSY or          |
      |             |             || x-name           |
      +-------------+-------------++------------------+
      |             | CONFIRMED   ||                  |
      | TRANSPARENT | CANCELLED   || FREE             |
      |             | TENTATIVE   ||                  |
      |             | x-name      ||                  |
      +-------------+-------------++------------------+

Duplicate busy time periods with the same FBTYPE parameter value SHOULD NOT be specified in the returned VFREEBUSY component. Servers SHOULD coalesce consecutive or overlapping busy time periods of the same type ๐Ÿงš. Busy time periods with different FBTYPE parameter values MAY overlap.

Support for the CALDAV:free-busy-query REPORT is REQUIRED. Non-negotiable ๐Ÿ‘‘.

Marshalling:

  • The request body MUST be a CALDAV:free-busy-query XML element (see Section 9.11), which MUST contain exactly one CALDAV:time-range XML element, as defined in Section 9.9 โฐ.
  • The request MAY include a Depth header. If no Depth header is included, Depth:0 is assumed.
  • The response body for a successful request MUST be an iCalendar object containing exactly one VFREEBUSY component. That component describes the busy time intervals for the calendar object resources containing VEVENT, or VFREEBUSY components, that satisfy the Depth value and for which the current user is at least granted the CALDAV:read-free-busy privilege. If no calendar object resources are found to satisfy these conditions, a VFREEBUSY component with no FREEBUSY property MUST be returned. This report only returns busy time information. Free time can be inferred from the busy time info returned ๐Ÿซถ.
  • If the current user isn't granted the CALDAV:read-free-busy or DAV:read privileges on the Request-URI, the CALDAV:free-busy-query REPORT request MUST fail and return a 404 (Not Found) status value. This restriction stops users from discovering URLs of resources they only have the CALDAV:read-free-busy privilege for ๐Ÿ™ˆ.
  • The CALDAV:free-busy-query REPORT request can only be run against a collection (either a regular collection or a calendar collection). An attempt to run the report on a calendar object resource MUST fail and return a 403 (Forbidden) status value ๐Ÿšซ.

Preconditions:

None.

Postconditions:

  • (DAV:number-of-matches-within-limits): The number of matching calendar object resources has to fall within server-specific, predefined limits. For example, this postcondition might fail if the specified CALDAV:time-range would cause an extremely large number of calendar object resources to be considered in computing the response ๐Ÿ“ˆ.

7.10.1. Example: Successful CALDAV:free-busy-query REPORT ๐ŸŽ€

okay so this example is giving free busy lookup done right ๐Ÿ’… Bernard's client wants to know when he's booked on his work calendar collection /bernard/work/. The window is 9:00 A.M. to 5:00 P.M. EST, which is 2:00 P.M. to 10:00 P.M. UTC, on January 4, 2006. The server comes back saying there are two one-hour busy blocks in there, and one of them is only tentative ๐Ÿฆ‹

Check Appendix B for the calendar data this example is hitting ๐Ÿงš

>> Request <<

REPORT /bernard/work/ HTTP/1.1
Host: cal.example.com
Depth: 1
Content-Type: application/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<C:free-busy-query xmlns:C="urn:ietf:params:xml:ns:caldav">
  <C:time-range start="20060104T140000Z"
                  end="20060105T220000Z"/>
</C:free-busy-query>

>> Response <<

HTTP/1.1 200 OK
Date: Sat, 11 Nov 2006 09:32:12 GMT
Content-Type: text/calendar
Content-Length: xxxx

BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp.//CalDAV Server//EN
BEGIN:VFREEBUSY
DTSTAMP:20050125T090000Z
DTSTART:20060104T140000Z
DTEND:20060105T220000Z
FREEBUSY;FBTYPE=BUSY-TENTATIVE:20060104T150000Z/PT1H
FREEBUSY:20060104T190000Z/PT1H
END:VFREEBUSY
END:VCALENDAR

8. Guidelines ๐ŸŒธ

8.1. Client-to-Client Interoperability ๐Ÿซถ

ngl there are a bunch of things clients can do that are still legal, meaning the server won't throw errors ๐Ÿ˜ญ But they can totally wreck interoperability with other client apps poking at the same data ๐Ÿ’€ Like, swapping a recurrence rule for a pile of recurrence dates, splitting one recurring event into a separate resource for every single occurrence, or translating start and end times from the original time zone into a different one. Honestly this is just iCalendar interoperability best practice, not a CalDAV-only thing, but the problems show up way more in CalDAV use cases ๐Ÿ“

8.2. Synchronization Operations ๐Ÿ’–

WebDAV already has what you need to sync a collection (or a bunch of them), make changes offline, and resolve conflicts neatly when you reconnect โœจ ETags are the secret sauce here, but not every WebDAV server has them, so it's not a free pass. Offline stuff matters way more for calendar apps than for a lot of other WebDAV apps, so CalDAV servers MUST support ETags, as specified in Section 5.3.4. no exceptions bestie ๐Ÿ‘‘

8.2.1. Use of Reports ๐Ÿ“š

8.2.1.1. Restrict the Time Range โฐ

The CalDAV reports are how clients save bandwidth and don't overwork the local machine ๐Ÿงš That's a huge deal on phones and handhelds with limited capacity, but it's still super relevant on desktops when a calendar collection is stuffed with tons of data ๐Ÿ˜ฉ

Clients usually show calendar data in views covering a finite stretch of time, so whenever possible they should only pull components from the server with a CALDAV:calendar-query REPORT plus a CALDAV:time-range element. That way only the stuff needed to fill the current view comes back ๐ŸŒˆ

8.2.1.2. Synchronize by Time Range ๐Ÿฆ‹

In a calendar, historical stuff (events, to-dos, etc. that finished before today) basically never changes, though it might get deleted ๐Ÿ™ˆ So a client can speed up sync by only caring about the present and the future up to some reasonable limit, like a week or a month. If the user then wanders off to look at a part of the calendar outside what's been synced, the client just runs another sync on that new interval. This "just-in-time" sync keeps bandwidth low for the stuff people actually do all day ๐Ÿ’…

8.2.1.3. Synchronization Process ๐Ÿ”ฅ

If a client wants to support calendar data sync (instead of downloading everything every time it's needed), it has to cache each calendar object resource's URI and ETag, along with the actual calendar data. The URI stays the same for the whole life of the resource, but the ETag changes with every single change to it ๐Ÿ’– So to sync the local cache with the server, the client can first fetch the URI/ETag pairs for the time interval it cares about, then compare those with what it cached. Any cached component whose ETag doesn't match the server's needs to be refreshed ๐Ÿซถ

To detect changes between the server and client data properly, the client needs to keep track of which calendar object resources have been created, changed, or deleted since the last sync operation so it can reconcile those changes with the server ๐Ÿง 

Here's an example of how to do that ๐Ÿ“

The client sends a CALDAV:calendar-query REPORT for a specific time range and only asks for the DAV:getetag property back:

REPORT /bernard/work/ HTTP/1.1
Host: cal.example.com
Depth: 1
Content-Type: application/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<C:calendar-query xmlns:D="DAV:"
                  xmlns:C="urn:ietf:params:xml:ns:caldav">
  <D:prop>
    <D:getetag/>
  </D:prop>
  <C:filter>
    <C:comp-filter name="VCALENDAR">
      <C:comp-filter name="VEVENT">
        <C:time-range start="20040902T000000Z"
                        end="20040903T000000Z"/>
      </C:comp-filter>
    </C:comp-filter>
  </C:filter>
</C:calendar-query>

The client then uses those results to figure out which calendar object resources changed, got created, or got deleted on the server, and how that lines up with the locally cached ones that might have changed, been created, or been deleted too ๐Ÿงš If there are calendar object resources on the server that need fetching, the client sends a CALDAV:calendar-multiget REPORT to grab its calendar data:

REPORT /bernard/work/ HTTP/1.1
Host: cal.example.com
Content-Type: application/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<C:calendar-multiget xmlns:D="DAV:"
                     xmlns:C="urn:ietf:params:xml:ns:caldav">
  <D:prop>
    <D:getetag/>
    <C:calendar-data/>
  </D:prop>
  <D:href>/bernard/work/abcd1.ics</D:href>
  <D:href>/bernard/work/mtg1.ics</D:href>
</C:calendar-multiget>

8.2.2. Restrict the Properties Returned โœ‚๏ธ

Clients don't always need every single property of a calendar object resource to show the user what's up ๐Ÿ’… Some property values can be huge (ATTACH and ATTENDEE, I'm looking at you ๐Ÿ‘€), so a client can limit the properties returned in a calendaring REPORT to just the ones it knows it'll use ๐ŸŒธ

BUT here's the catch ๐Ÿ™ˆ If a client needs to change a calendar object resource, the only way is to PUT the entire resource. There's currently no way to incrementally change a set of calendar properties. So the client has to fetch the whole calendar object resource being changed anyway ๐Ÿ˜ญ

8.3. Use of Locking ๐Ÿ”’

WebDAV locks keep two clients editing the same resource from overwriting each other's changes (ETags can also solve that one) or wasting time on changes that are going to conflict with someone else's ๐Ÿ’œ In a multi-user calendar system, an interactive client can lock an event while the user is editing it, then unlock it when they finish or cancel. Locks are also useful for stopping changes while data is being reorganized. For example, a calendar client might lock two calendar collections before moving a bunch of calendar resources from one to the other ๐Ÿงš

Clients are responsible for asking for a lock timeout that fits the use case ๐Ÿซถ When the user deliberately wants to reserve a resource and block other changes, a long timeout can make sense. But when the client locks something automatically, the timeout should be short, and the client can always refresh the lock if it needs to ๐Ÿฆ‹ A short timeout also means that if the client can't remove the lock, other calendar users aren't stuck locked out of making changes ๐ŸŒˆ

8.4. Finding Calendars โœจ

Most of the time, a calendar client (or agent) finds a new calendar by being handed the URL directly ๐Ÿ”—. Like, a user types their calendar location into the client config, or copies a URL out of an email and pastes it into the app. The client only needs to confirm that the URL points to a calendar collection. It might also be able to browse WebDAV collections to find calendar collections ๐Ÿงš

Calendar object resources use plain HTTP URLs, which keeps them backward compatible with existing software ๐Ÿ’–. The downside is that existing software doesn't usually know to check the OPTIONS response for that URL to see what it can do with it ๐Ÿ™ˆ. That's kind of a barrier for WebDAV usage and for CalDAV usage too. This specification doesn't really fix that, other than making the info available in the OPTIONS response if someone asks for it.

For calendar sharing and scheduling, you might want to find another user's calendar ๐Ÿ‘€. If that user has a calendar in the same repository, you can find it through the principal namespace that WebDAV ACL support requires. For everything else, the authors don't have a universal answer. Implementers can think about using vCard [RFC2426] or LDAP [RFC4511] together with calendar attributes [RFC2739] ๐Ÿ’…

Since CalDAV requires servers to support WebDAV ACL [RFC3744], principal namespaces included, plus the CALDAV:calendar-home-set property, CalDAV clients have a couple of ways to find your own calendar or someone else's ๐ŸŒธ

Here, a DAV:principal-match REPORT is used to look up a named property (CALDAV:calendar-home-set) on the current user's Principal-URL ๐ŸŽ€. With that, a WebDAV client can figure out "who am I" and "where are my calendars" ๐Ÿฆ‹ The REPORT request body looks like this:

<?xml version="1.0" encoding="utf-8" ?>
<D:principal-match xmlns:D="DAV:">
  <D:self/>
  <D:prop>
    <C:calendar-home-set
       xmlns:C="urn:ietf:params:xml:ns:caldav"/>
  </D:prop>
</D:principal-match>

To find other users' calendars, the DAV:principal-property-search REPORT can filter on some properties and return others ๐Ÿ”. Say you want a calendar owned by someone named "Laurie". The REPORT request body would look like this:

<?xml version="1.0" encoding="utf-8" ?>
<D:principal-property-search xmlns:D="DAV:">
  <D:property-search>
    <D:prop>
      <D:displayname/>
    </D:prop>
    <D:match>Laurie</D:match>
  </D:property-search>
  <D:prop>
    <C:calendar-home-set
       xmlns:C="urn:ietf:params:xml:ns:caldav"/>
    <D:displayname/>
  </D:prop>
</D:principal-property-search>

The server does a case-sensitive or caseless search for a matching string subset of "Laurie" inside the DAV:displayname property ๐Ÿซถ. So it might return "Laurie Dusseault", "Laurier Desruisseaux", or "Wilfrid Laurier" as matches, and then hand back the calendars for each of them ๐Ÿ˜ญ


8.5. Storing and Using Attachments ๐Ÿ“Ž

CalDAV clients MAY create attachments in calendar components, either inline or external ๐Ÿ’…. This section has some guidelines for making and managing attachments, so read on bestie ๐Ÿงš

8.5.1. Inline Attachments

CalDAV clients MUST support inline attachments as specified in iCalendar [RFC2445] ๐Ÿซถ. CalDAV servers MUST support inline attachments too, so clients can count on being able to attach stuff this way ๐Ÿ’–. BUT inline attachments come with some drawbacks, ngl ๐Ÿ™ˆ:

  • Servers MAY impose limits on the size of calendar object resources (for example, refusing PUT requests for very large iCalendar objects). Servers that impose these limits MUST use the CALDAV:max-resource-size property on a calendar collection to tell the client what the limit is (see Section 5.2.5) ๐Ÿ“
  • Servers MAY impose storage quota limitations on calendar collections (See [RFC4331]) ๐Ÿ’พ
  • Any change to a calendar object resource containing an inline attachment means the entire inline attachment has to be re-uploaded ๐Ÿ˜ฉ
  • Clients synchronizing a changed calendar object resource have to download the entire calendar object resource, even when the attachment hasn't changed ๐Ÿ’€

8.5.2. External Attachments

CalDAV clients SHOULD support downloading external attachments referenced by arbitrary URI schemes. They can either process them directly, or pass the attachment URI to a suitable "helper application" for processing, if one exists ๐Ÿงฉ CalDAV clients MUST support downloading external attachments referenced by the "http" or "https" URI schemes ๐ŸŒˆ An external attachment could be:

  • In a collection inside the calendar collection that contains the calendar object resource ๐Ÿ“
  • Somewhere else in the same repository that hosts the calendar collection ๐Ÿ 
  • On an HTTP or FTP server somewhere else ๐ŸŒ

CalDAV servers MAY provide support for child collections in calendar collections. CalDAV servers MAY allow the MKCOL method to create child collections in calendar collections. Child collections of calendar collections MAY contain any type of resource, EXCEPT calendar collections, which they MUST NOT contain ๐Ÿ™…โ€โ™€๏ธ Some CalDAV servers won't allow child collections in calendar collections. On those servers, it may be possible to discover other places where attachments can be stored ๐Ÿ”Ž

Clients are fully responsible for keeping references consistent with the calendar components that link to external attachments ๐Ÿ”—. So a client that deletes a calendar component with an external attachment might also delete the attachment, if that's appropriate. But appropriateness is super hard to figure out ๐Ÿ˜ตโ€๐Ÿ’ซ A new component could easily reference some existing Web resource that's meant to exist independently of the calendar component (the "attachment" might be a big proposal being discussed in a meeting, for example) ๐Ÿ“Š Best practices will probably emerge and should probably get documented, but for now, clients should be wary of aggressive "cleanup" of external attachments ๐Ÿงน A client could involve the user in deciding which unreferenced documents to remove, or it could be conservative and only delete attachments it created itself ๐Ÿซง

Clients are also responsible for keeping permissions consistent when using external attachments ๐Ÿ”. One reason servers should support storing attachments in child collections of calendar collections is that ACL inheritance might make it easier to grant the same permissions to attachments that are granted on the calendar collection. Otherwise, it gets really hard to keep permissions synced ๐Ÿ˜ค With attachments stored in separate repositories, it can be impossible to keep permissions consistent, because the two repositories may not support the same permissions or have the same set of principals ๐Ÿ’” Some systems have used tickets or other anonymous access control mechanisms to get partially working solutions to these kinds of problems ๐ŸŽŸ๏ธ


8.6. Storing and Using Alarms โฐ

Heads up, all CalDAV calendar collections (including the ones users treat as public or group calendars) can contain alarm info on events and to-dos ๐Ÿ“…. Users can sync a calendar across multiple devices and decide to have alarms go off on a different device than the one that made the alarm ๐Ÿ“ฑ๐Ÿ’ป. Not every alarm action type is fully interoperable (for example, the ones that name a sound file to play) ๐Ÿ”Š

When the action is AUDIO and the client is set up to execute the alarm, the client SHOULD play the suggested sound if it's available, or play another sound. It SHOULD NOT rewrite the alarm just to swap in a locally available sound ๐ŸŽต
When the action is DISPLAY and the client is set up to execute the alarm, the client SHOULD execute a display alarm by showing the suggested description or some reasonable replacement. It SHOULD NOT rewrite the alarm for its own convenience ๐Ÿ–ฅ๏ธ
When the action is EMAIL and the client is incapable of sending email, it SHOULD ignore the alarm, but it MUST continue to synchronize the alarm itself ๐Ÿ“ง
This specification makes no recommendations about executing alarms of type PROCEDURE, except to note that clients are advised to take care to avoid creating security holes by executing these โš ๏ธ

Non-interoperable alarm info (say somebody defines a color to use in a display alarm) should go in non-standard properties inside the VALARM component. That keeps the basic alarm usable on all devices ๐ŸŒŸ

Clients that allow changes to calendar object resources MUST synchronize the alarm data that already exists in those resources ๐Ÿซถ

Clients MAY execute alarms downloaded this way, maybe based on user preference ๐Ÿ™‹โ€โ™€๏ธ If a client is only doing read operations on a calendar, and there's no risk of losing alarm info, then the client MAY discard alarm info ๐Ÿ—‘๏ธ

This specification makes no attempt to provide multi-user alarms on group calendars, or to figure out who an alarm is intended for ๐Ÿคทโ€โ™€๏ธ Addressing those issues might need extensions to iCalendar. For example, to store alarms per user, or to indicate which user a VALARM was intended for ๐Ÿ’œ In the meantime, clients might maximize interoperability by generally not uploading alarm info to public, group, or resource calendars ๐Ÿง


9. XML Element Definitions ๐Ÿ“œ

9.1. CALDAV:calendar XML Element

Name: calendar

Namespace: urn:ietf:params:xml:ns:caldav

Purpose: Specifies the resource type of a calendar collection ๐Ÿ—‚๏ธ

Description: See Section 4.2.

Definition:

<!ELEMENT calendar EMPTY>

9.2. CALDAV:mkcalendar XML Element

Name: mkcalendar

Namespace: urn:ietf:params:xml:ns:caldav

Purpose: Specifies a request that includes the WebDAV property values to be set for a calendar collection resource when it's created ๐Ÿ› ๏ธ

Description: See Section 5.3.1.

Definition:

<!ELEMENT mkcalendar (DAV:set)>

9.3. CALDAV:mkcalendar-response XML Element

Name: mkcalendar-response

Namespace: urn:ietf:params:xml:ns:caldav

Purpose: Specifies a response body for a successful MKCALENDAR request ๐ŸŽ‰

Description: See Section 5.3.1.

Definition:

<!ELEMENT mkcalendar-response ANY>

9.4. CALDAV:supported-collation XML Element

Name: supported-collation

Namespace: urn:ietf:params:xml:ns:caldav

Purpose: Identifies a single collation via its collation identifier, as defined by [RFC4790] ๐Ÿ”ค

Description: The CALDAV:supported-collation contains the text of a collation identifier, as described in Section 7.5.1.

Definition:

<!ELEMENT supported-collation (#PCDATA)>
PCDATA value: collation identifier

9.5. CALDAV:calendar-query XML Element

Name: calendar-query

Namespace: urn:ietf:params:xml:ns:caldav

Purpose: Defines a report for querying calendar object resources ๐Ÿ”

Description: See Section 7.8.

Definition:

<!ELEMENT calendar-query ((DAV:allprop |
                           DAV:propname |
                           DAV:prop)?, filter, timezone?)>

9.6. CALDAV:calendar-data XML Element โœจ

Name: calendar-data ๐ŸŽ€

Namespace: urn:ietf:params:xml:ns:caldav ๐ŸŒธ

Purpose: okay, this element is a total multitasker ๐Ÿ’… It can do one of three jobs:

  1. It lists a supported media type for calendar object resources when it's nested inside the CALDAV:supported-calendar-data property ๐Ÿ“‹
  2. It says which parts of a calendar object resource should come back from a calendaring report ๐Ÿ”
  3. It carries the actual content of a calendar object resource in a calendaring report response ๐Ÿ’Œ

Description: when it's nested in CALDAV:supported-calendar-data, it's basically the server saying "hey, I speak this media type for calendar object resources" ๐Ÿฆ‹

When it shows up in a calendaring REPORT request, it tells the server which parts of the calendar object resources to send back ๐Ÿงš If there's no CALDAV:comp element inside it, the server just returns the whole calendar object resources, no edits, full send ๐Ÿ’โ€โ™€๏ธ

When it's in a calendaring REPORT response, it holds the content of a calendar object resource. Here's the fun part: XML parsers turn the two-character CRLF sequence (US-ASCII decimal 13 and US-ASCII decimal 10) into a single LF character (US-ASCII decimal 10). So the CR character (US-ASCII decimal 13) MAY be omitted in calendar object resources inside this element ๐Ÿ™ˆ Also, calendar object resources in this element MAY be invalid per their media type specification if the calendaring REPORT request's calendar-data part didn't ask for required properties (like UID, DTSTAMP, etc.), or if it had a CALDAV:prop element with the "novalue" attribute set to "yes". Not me being shady, that's just how it works ๐Ÿ˜ญ

Note: this one's a little bit of a trickster. It's written in requests and responses inside the DAV:prop element as if it were a WebDAV property. But it is NOT a WebDAV property ๐Ÿ™…โ€โ™€๏ธ so it doesn't show up in PROPFIND responses, and you can't use it in PROPPATCH requests. Bestie, don't be fooled ๐Ÿฅน

Note: the iCalendar data inside CALDAV:calendar-data MUST follow the standard XML character data encoding rules. That means using entity encoding like &lt;, &gt;, &amp; etc., or wrapping it in a <![CDATA[ ... ]]> construct. If you go the CDATA route, the iCalendar data can't contain the character sequence ]]>, because that's the CDATA section's end delimiter. Super important, so don't skip it ๐Ÿ”

Definition:

<!ELEMENT calendar-data EMPTY>

when nested in the CALDAV:supported-calendar-data property
to specify a supported media type for calendar object
resources;

<!ELEMENT calendar-data (comp?,
                         (expand | limit-recurrence-set)?,
                         limit-freebusy-set?)>

when nested in the DAV:prop XML element in a calendaring
REPORT request to specify which parts of calendar object
resources should be returned in the response;

<!ELEMENT calendar-data (#PCDATA)>
PCDATA value: iCalendar object

when nested in the DAV:prop XML element in a calendaring
REPORT response to specify the content of a returned
calendar object resource.

<!ATTLIST calendar-data content-type CDATA "text/calendar"
                        version CDATA "2.0">
content-type value: a MIME media type
version value: a version string

attributes can be used on all three variants of the
CALDAV:calendar-data XML element.

9.6.1. CALDAV:comp XML Element

Name: comp ๐Ÿง

Namespace: urn:ietf:params:xml:ns:caldav ๐ŸŒˆ

Purpose: this one picks which component types to return ๐ŸŽฏ

Description: the name value is a calendar component name, like VEVENT ๐Ÿ“…

Definition:

<!ELEMENT comp ((allprop | prop*), (allcomp | comp*))>

<!ATTLIST comp name CDATA #REQUIRED>
name value: a calendar component name

Note: the CALDAV:prop and CALDAV:allprop elements have the same names as the DAV:prop and DAV:allprop elements from [RFC2518]. The difference is that they live in the "urn:ietf:params:xml:ns:caldav" namespace instead of "DAV:" ๐Ÿ™ƒ


9.6.2. CALDAV:allcomp XML Element

Name: allcomp ๐Ÿฆ‹

Namespace: urn:ietf:params:xml:ns:caldav ๐ŸŒธ

Purpose: says that every component should be returned ๐ŸŒŸ

Description: the CALDAV:allcomp element is for when the client wants every type of component back from a calendaring REPORT request. Main character energy ๐Ÿ‘‘

Definition:

<!ELEMENT allcomp EMPTY>

9.6.3. CALDAV:allprop XML Element

Name: allprop ๐Ÿ’–

Namespace: urn:ietf:params:xml:ns:caldav โœจ

Purpose: says that every property should be returned ๐ŸŽ€

Description: the CALDAV:allprop element is for when the client wants all the properties of components back from a calendaring REPORT request. Give me everything ๐Ÿ’…

Definition:

<!ELEMENT allprop EMPTY>

Note: the CALDAV:allprop element has the same name as the DAV:allprop element from [RFC2518], but it's in the "urn:ietf:params:xml:ns:caldav" namespace instead of "DAV:" ๐Ÿงš


9.6.4. CALDAV:prop XML Element

Name: prop ๐Ÿ“

Namespace: urn:ietf:params:xml:ns:caldav ๐Ÿซถ

Purpose: defines which properties to send back in the response ๐Ÿ“ฆ

Description: the "name" attribute names the calendar property to return, like ATTENDEE ๐Ÿ‘€ The "novalue" attribute lets clients ask that the actual value NOT be returned, but only when "novalue" is set to "yes". In that case, the server returns just the iCalendar property name, any iCalendar parameters, and a trailing ":" with no value after it. Like a sneak peek without the spoiler ๐Ÿ™ˆ

Definition:

<!ELEMENT prop EMPTY>

<!ATTLIST prop name CDATA #REQUIRED
               novalue (yes | no) "no">
name value: a calendar property name
novalue value: "yes" or "no"

Note: the CALDAV:prop element has the same name as the DAV:prop element from [RFC2518], but it lives in the "urn:ietf:params:xml:ns:caldav" namespace instead of "DAV:" ๐ŸŒท


9.6.5. CALDAV:expand XML Element

Name: expand ๐Ÿ”ฅ

Namespace: urn:ietf:params:xml:ns:caldav ๐ŸŒˆ

Purpose: forces the server to break recurring components apart into individual recurrence instances ๐Ÿช„

Description: this is the element where the server gets told to expand. For a given calendaring REPORT request, the server MUST expand the recurrence set into calendar components that each define exactly one recurrence instance. It MUST return only the ones whose scheduled time intersects a specified time range. Serving precision ๐Ÿ’…

The "start" attribute is the inclusive start of that time range, and the "end" attribute is the non-inclusive end. Both are written as a date with UTC time value. The value of "end" MUST be greater than the value of "start". No cap, that's just basic logic ๐Ÿง 

The server MUST use the same logic as defined for CALDAV:time-range to figure out whether a recurrence instance intersects the specified time range ๐ŸŽฏ

Recurring components other than the initial instance MUST include a RECURRENCE-ID property, so everyone knows which instance they refer to ๐Ÿ”–

The returned calendar components MUST NOT use recurrence properties (that's EXDATE, EXRULE, RDATE, and RRULE) and MUST NOT have any reference to, or include, VTIMEZONE components. Date and local time that references time zone information MUST be converted into date with UTC time. Timezones are NOT the vibe here ๐ŸŒ๐Ÿšซ

Definition:

<!ELEMENT expand EMPTY>

<!ATTLIST expand start CDATA #REQUIRED
                 end   CDATA #REQUIRED>
start value: an iCalendar "date with UTC time"
end value: an iCalendar "date with UTC time"

9.6.6. CALDAV:limit-recurrence-set XML Element

Name: limit-recurrence-set ๐ŸŒ™

Namespace: urn:ietf:params:xml:ns:caldav ๐ŸŽ€

Purpose: sets a time range that limits which "overridden components" the server sends back ๐Ÿง

Description: for a given calendaring REPORT request, the server MUST return, in addition to the "master component", only the "overridden components" that actually affect a specified time range. An overridden component counts if its current start and end times overlap the time range, or if its original start and end times (the ones it would have had if it weren't overridden) overlap it. Sneaky overlaps count too ๐Ÿ‘€

The "start" attribute is the inclusive start of the time range, and "end" is the non-inclusive end. Both are written as a date with UTC time value. The value of "end" MUST be greater than the value of "start" ๐Ÿ’–

The server MUST use the same logic as defined for CALDAV:time-range to determine whether the current or original scheduled time of an "overridden" recurrence instance intersects the specified time range ๐Ÿ”

Here's the drama ๐ŸŽญ Overridden components with a RANGE parameter on their RECURRENCE-ID property can point at one or more instances in the recurrence set. Some of those instances might fall inside the time range, or might have originally fallen inside it before being overridden. If that's the case, the overridden component MUST be included in the results, because it changes how the instances in that time range get interpreted. Non-negotiable โœจ

Definition:

<!ELEMENT limit-recurrence-set EMPTY>

<!ATTLIST limit-recurrence-set start CDATA #REQUIRED
                               end   CDATA #REQUIRED>
start value: an iCalendar "date with UTC time"
end value: an iCalendar "date with UTC time"

9.6.7. CALDAV:limit-freebusy-set XML Element

Name: limit-freebusy-set ๐Ÿซง

Namespace: urn:ietf:params:xml:ns:caldav ๐ŸŒธ

Purpose: sets a time range that limits which FREEBUSY values the server returns ๐Ÿ•ฐ๏ธ

Description: for a given calendaring REPORT request, the server MUST only return the FREEBUSY property values of a VFREEBUSY component that intersect a specified time range. Only the tea that's relevant gets spilled โ˜•

The "start" attribute is the inclusive start of the time range, and "end" is the non-inclusive end. Both are written as a "date with UTC time" value. The value of "end" MUST be greater than the value of "start" ๐Ÿ’œ

The server MUST use the same logic as defined for CALDAV:time-range to determine whether a FREEBUSY property value intersects the specified time range ๐Ÿงšโ€โ™€๏ธ

Definition:

<!ELEMENT limit-freebusy-set EMPTY>

<!ATTLIST limit-freebusy-set start CDATA #REQUIRED
                             end   CDATA #REQUIRED>
start value: an iCalendar "date with UTC time"
end value: an iCalendar "date with UTC time"

9.7. CALDAV:filter XML Element โœจ

Name: filter

Namespace: urn:ietf:params:xml:ns:caldav

Purpose: Specifies a filter to limit the set of calendar components returned by the server. ๐Ÿ’…

Description: Okay so CALDAV:filter is the search filter that decides which calendar components come back from a calendaring REPORT request. It's the bouncer at the door, bestie ๐Ÿšชโœจ

Definition:

<!ELEMENT filter (comp-filter)>

9.7.1. CALDAV:comp-filter XML Element ๐Ÿฆ‹

Name: comp-filter

Namespace: urn:ietf:params:xml:ns:caldav

Purpose: Specifies search criteria on calendar components. ๐ŸŽ€

Description: The CALDAV:comp-filter element is aimed at either the calendar object (that's the VCALENDAR) or one specific component type, like VEVENT. Its scope is the whole calendar object when it sits under CALDAV:filter, and the enclosing calendar component when it sits under another CALDAV:comp-filter. A CALDAV:comp-filter counts as a match in any of these cases:

  • The CALDAV:comp-filter element is empty and the calendar object or calendar component type named in the "name" attribute exists in the current scope;

or:

  • The CALDAV:comp-filter element contains a CALDAV:is-not-defined element and the calendar object or calendar component type named in the "name" attribute does not exist in the current scope;

or:

  • The CALDAV:comp-filter element contains a CALDAV:time-range element, at least one recurrence instance in the targeted calendar component is scheduled to overlap that time range, and every specified CALDAV:prop-filter and CALDAV:comp-filter child element also matches the targeted calendar component;

or:

  • The CALDAV:comp-filter element only contains CALDAV:prop-filter and CALDAV:comp-filter child elements, and every one of them matches the targeted calendar component.

Definition:

<!ELEMENT comp-filter (is-not-defined | (time-range?,
                       prop-filter*, comp-filter*))>

<!ATTLIST comp-filter name CDATA #REQUIRED>
name value: a calendar object or calendar component
            type (e.g., VEVENT)

9.7.2. CALDAV:prop-filter XML Element ๐Ÿ’–

Name: prop-filter

Namespace: urn:ietf:params:xml:ns:caldav

Purpose: Specifies search criteria on calendar properties. ๐ŸŒธ

Description: The CALDAV:prop-filter element is a query aimed at one calendar property (like CATEGORIES) inside the enclosing calendar component. A calendar property counts as a match for a CALDAV:prop-filter in these cases:

  • The CALDAV:prop-filter element is empty and a property of the type named in the "name" attribute exists in the enclosing calendar component;

or:

  • The CALDAV:prop-filter element contains a CALDAV:is-not-defined element and no property of the type named in the "name" attribute exists in the enclosing calendar component;

or:

  • The CALDAV:prop-filter element contains a CALDAV:time-range element, the property value overlaps the specified time range, and every specified CALDAV:param-filter child element also matches the targeted property;

or:

  • The CALDAV:prop-filter element contains a CALDAV:text-match element, the property value matches it, and every specified CALDAV:param-filter child element also matches the targeted property.

Definition:

<!ELEMENT prop-filter (is-not-defined |
                       ((time-range | text-match)?,
                        param-filter*))>

<!ATTLIST prop-filter name CDATA #REQUIRED>
name value: a calendar property name (e.g., ATTENDEE)

9.7.3. CALDAV:param-filter XML Element ๐Ÿงš

Name: param-filter

Namespace: urn:ietf:params:xml:ns:caldav

Purpose: Limits the search to specific parameter values. ๐Ÿ“

Description: The CALDAV:param-filter element is a query aimed at one calendar property parameter (like PARTSTAT) inside the calendar property it's defined on. A calendar property parameter counts as a match for a CALDAV:param-filter in these cases:

  • The CALDAV:param-filter element is empty and a parameter of the type named in the "name" attribute exists on the calendar property being examined;

or:

  • The CALDAV:param-filter element contains a CALDAV:is-not-defined element and no parameter of the type named in the "name" attribute exists on the calendar property being examined.

Definition:

<!ELEMENT param-filter (is-not-defined | text-match?)>

<!ATTLIST param-filter name CDATA #REQUIRED>
name value: a property parameter name (e.g., PARTSTAT)

9.7.4. CALDAV:is-not-defined XML Element ๐Ÿ™ˆ

Name: is-not-defined

Namespace: urn:ietf:params:xml:ns:caldav

Purpose: Specifies that a match should occur if the enclosing component, property, or parameter does not exist. ๐Ÿซถ

Description: The CALDAV:is-not-defined element says there's a match when the enclosing component, property, or parameter value named in a calendaring REPORT request is not present in the calendar data being tested. It's the "ghost check" ๐Ÿ‘ป

Definition:

<!ELEMENT is-not-defined EMPTY>

9.7.5. CALDAV:text-match XML Element ๐Ÿ”ฅ

Name: text-match

Namespace: urn:ietf:params:xml:ns:caldav

Purpose: Specifies a substring match on a property or parameter value. ๐Ÿ’œ

Description: The CALDAV:text-match element carries the text used for a substring match against the property or parameter value named in a calendaring REPORT request.

The "collation" attribute picks the collation the server MUST use for character string matching. If that attribute isn't there, the server MUST use the "i;ascii-casemap" collation. The server really has to do this, no exceptions ๐Ÿ™…โ€โ™€๏ธ

The "negate-condition" attribute flips the result. Set it to "no" and you get a match when the text matches. Set it to "yes" and you get a match when the text does not match. For example, this can be used to match components with a STATUS property not set to CANCELLED. ๐Ÿ’…

Definition:

<!ELEMENT text-match (#PCDATA)>
PCDATA value: string

<!ATTLIST text-match collation        CDATA "i;ascii-casemap"
                     negate-condition (yes | no) "no">

9.8. CALDAV:timezone XML Element ๐ŸŒˆ

Name: timezone

Namespace: urn:ietf:params:xml:ns:caldav

Purpose: Specifies the time zone component to use when determining the results of a report. ๐Ÿ—บ๏ธ

Description: For a given calendaring REPORT request, the server MUST rely on the VTIMEZONE component you give in CALDAV:timezone instead of the CALDAV:calendar-timezone property on the calendar collection that holds the calendar object resource. It's used to turn "date" values and "date with local time" values (aka floating time) into "date with UTC time" values. The server needs that info to figure out whether a component scheduled with "date" or "date with local time" values overlaps a CALDAV:time-range in a CALDAV:calendar-query REPORT. Time zones matter, bestie โฐ

Note: The iCalendar data inside the CALDAV:timezone element MUST follow the standard XML character data encoding rules, including entity encoding such as &lt;, &gt;, &amp;, etc., or the use of a <![CDATA[ ... ]]> construct. If you go with the CDATA option, the iCalendar data cannot contain the character sequence "]]>", since that's the end delimiter for the CDATA section.

Definition:

<!ELEMENT timezone (#PCDATA)>
PCDATA value: an iCalendar object with exactly one VTIMEZONE

9.9. CALDAV:time-range XML Element โฐ

Name: time-range

Namespace: urn:ietf:params:xml:ns:caldav

Purpose: Specifies a time range to limit the set of calendar components returned by the server.

Description: okay so CALDAV:time-range is basically a date window ๐Ÿ—“๏ธ For a calendaring REPORT request, the server MUST only return the calendar object resources that, depending on the context, have a component or property whose value intersects the specified time range. Main character energy for the calendar data, fr fr ๐Ÿ’…

The start attribute is the inclusive start of the range, and the end attribute is the non-inclusive end. Both attributes MUST be specified as "date with UTC time" value. You can leave one end open by only including one attribute, but at least one attribute MUST always be present in the CALDAV:time-range element. If start or end is missing, it's treated as -infinity or +infinity respectively ๐ŸŒˆ And if both are there, the value of the end attribute MUST be greater than the value of the start attribute, no exceptions ๐Ÿ™…โ€โ™€๏ธ

Time range tests MUST consider every recurrence instance when testing the time range condition. If any one instance matches, the test returns true โœจ Checking recurrence instances means the server has to infer an effective value for DTSTART, DTEND, DURATION, and DUE properties for each instance, based on the recurrence patterns and any overrides. It's a lot, bestie, but the server is literally doing its best ๐Ÿซถ

Now the tables, which are the spicy part ๐Ÿ”ฅ A VEVENT overlaps a given time range if the condition for its component state (shown below) is satisfied. Note that, as specified in [RFC2445], the DTSTART property is REQUIRED in the VEVENT component. The conditions depend on whether DTEND and DURATION are present. Also, the value of the DTEND property MUST be later in time than the value of the DTSTART property ๐Ÿ’– A VEVENT with no DTEND and no DURATION lasts 1 day (+P1D) when DTSTART is a DATE value, and 0 seconds when DTSTART is a DATE-TIME value.

+---------------------------------------------------------------+
| VEVENT has the DTEND property?                                |
|   +-----------------------------------------------------------+
|   | VEVENT has the DURATION property?                         |
|   |   +-------------------------------------------------------+
|   |   | DURATION property value is greater than 0 seconds?    |
|   |   |   +---------------------------------------------------+
|   |   |   | DTSTART property is a DATE-TIME value?            |
|   |   |   |   +-----------------------------------------------+
|   |   |   |   | Condition to evaluate                         |
+---+---+---+---+-----------------------------------------------+
| Y | N | N | * | (start <  DTEND AND end > DTSTART)            |
+---+---+---+---+-----------------------------------------------+
| N | Y | Y | * | (start <  DTSTART+DURATION AND end > DTSTART) |
|   |   +---+---+-----------------------------------------------+
|   |   | N | * | (start <= DTSTART AND end > DTSTART)          |
+---+---+---+---+-----------------------------------------------+
| N | N | N | Y | (start <= DTSTART AND end > DTSTART)          |
+---+---+---+---+-----------------------------------------------+
| N | N | N | N | (start <  DTSTART+P1D AND end > DTSTART)      |
+---+---+---+---+-----------------------------------------------+

A VTODO overlaps a given time range if the condition for its component state (also below) is satisfied. This one depends on DTSTART, DURATION, DUE, COMPLETED, and CREATED being present or not ๐Ÿงฉ Note that, as specified in [RFC2445], the DUE value MUST be a DATE-TIME value equal to or after the DTSTART value, if DTSTART is specified.

+-------------------------------------------------------------------+
| VTODO has the DTSTART property?                                   |
|   +---------------------------------------------------------------+
|   |   VTODO has the DURATION property?                            |
|   |   +-----------------------------------------------------------+
|   |   | VTODO has the DUE property?                               |
|   |   |   +-------------------------------------------------------+
|   |   |   | VTODO has the COMPLETED property?                     |
|   |   |   |   +---------------------------------------------------+
|   |   |   |   | VTODO has the CREATED property?                   |
|   |   |   |   |   +-----------------------------------------------+
|   |   |   |   |   | Condition to evaluate                         |
+---+---+---+---+---+-----------------------------------------------+
| Y | Y | N | * | * | (start  <= DTSTART+DURATION)  AND             |
|   |   |   |   |   | ((end   >  DTSTART)  OR                       |
|   |   |   |   |   |  (end   >= DTSTART+DURATION))                 |
+---+---+---+---+---+-----------------------------------------------+
| Y | N | Y | * | * | ((start <  DUE)      OR  (start <= DTSTART))  |
|   |   |   |   |   | AND                                           |
|   |   |   |   |   | ((end   >  DTSTART)  OR  (end   >= DUE))      |
+---+---+---+---+---+-----------------------------------------------+
| Y | N | N | * | * | (start  <= DTSTART)  AND (end >  DTSTART)     |
+---+---+---+---+---+-----------------------------------------------+
| N | N | Y | * | * | (start  <  DUE)      AND (end >= DUE)         |
+---+---+---+---+---+-----------------------------------------------+
| N | N | N | Y | Y | ((start <= CREATED)  OR  (start <= COMPLETED))|
|   |   |   |   |   | AND                                           |
|   |   |   |   |   | ((end   >= CREATED)  OR  (end   >= COMPLETED))|
+---+---+---+---+---+-----------------------------------------------+
| N | N | N | Y | N | (start  <= COMPLETED) AND (end  >= COMPLETED) |
+---+---+---+---+---+-----------------------------------------------+
| N | N | N | N | Y | (end    >  CREATED)                           |
+---+---+---+---+---+-----------------------------------------------+
| N | N | N | N | N | TRUE                                          |
+---+---+---+---+---+-----------------------------------------------+

A VJOURNAL overlaps a given time range if the condition for its component state (see the table) is satisfied. It depends on whether DTSTART is there, and whether that DTSTART is a DATE-TIME or a DATE value ๐Ÿ““ The effective "duration" of a VJOURNAL is 1 day (+P1D) when DTSTART is a DATE value, and 0 seconds when DTSTART is a DATE-TIME value.

+----------------------------------------------------+
| VJOURNAL has the DTSTART property?                 |
|   +------------------------------------------------+
|   | DTSTART property is a DATE-TIME value?         |
|   |   +--------------------------------------------+
|   |   | Condition to evaluate                      |
+---+---+--------------------------------------------+
| Y | Y | (start <= DTSTART)     AND (end > DTSTART) |
+---+---+--------------------------------------------+
| Y | N | (start <  DTSTART+P1D) AND (end > DTSTART) |
+---+---+--------------------------------------------+
| N | * | FALSE                                      |
+---+---+--------------------------------------------+

A VFREEBUSY overlaps a given time range if the condition for its component state (table below) is satisfied. This one looks at whether DTSTART and DTEND are both there, and at any FREEBUSY properties when they're not ๐Ÿฆ‹ Any DURATION property is ignored, since it means something special inside a VFREEBUSY component. When only FREEBUSY properties are used, each period in each FREEBUSY property gets compared against the time range, no matter what kind of free busy information it represents (free, busy, busy-tentative, busy-unavailable).

+------------------------------------------------------+
| VFREEBUSY has both the DTSTART and DTEND properties? |
|   +--------------------------------------------------+
|   | VFREEBUSY has the FREEBUSY property?             |
|   |   +----------------------------------------------+
|   |   | Condition to evaluate                        |
+---+---+----------------------------------------------+
| Y | * | (start <= DTEND) AND (end > DTSTART)         |
+---+---+----------------------------------------------+
| N | Y | (start <  freebusy-period-end) AND           |
|   |   | (end   >  freebusy-period-start)             |
+---+---+----------------------------------------------+
| N | N | FALSE                                        |
+---+---+----------------------------------------------+

A VALARM overlaps a given time range if this holds: (start <= trigger-time) AND (end > trigger-time) โฐ

A VALARM can also be set up to trigger repeatedly ๐Ÿ” In that case, it overlaps the time range if at least one of its triggers overlaps the time range.

The calendar properties COMPLETED, CREATED, DTEND, DTSTAMP, DTSTART, DUE, and LAST-MODIFIED overlap a given time range if this holds: (start <= date-time) AND (end > date-time) ๐Ÿ’œ

Heads up, bestie: if DTEND is not present in a VEVENT but DURATION is, the test should instead use the 'effective' DTEND, which is DTSTART+DURATION. Same deal for a VTODO with no DUE but with DTSTART and DURATION: use the 'effective' DUE, which is DTSTART+DURATION ๐Ÿšจ

The semantic of CALDAV:time-range is not defined for any other calendar components and properties, so don't go there ๐Ÿ™ˆ

Definition:

<!ELEMENT time-range EMPTY>

<!ATTLIST time-range start CDATA #IMPLIED
                     end   CDATA #IMPLIED>
start value: an iCalendar "date with UTC time"
end value: an iCalendar "date with UTC time"

9.10. CALDAV:calendar-multiget XML Element ๐ŸŒธ

Name: calendar-multiget

Namespace: urn:ietf:params:xml:ns:caldav

Purpose: CalDAV report used to retrieve specific calendar object resources.

Description: Literally just see Section 7.9. It's the same story, babe ๐Ÿ’…

Definition:

<!ELEMENT calendar-multiget ((DAV:allprop |
                              DAV:propname |
                              DAV:prop)?, DAV:href+)>

9.11. CALDAV:free-busy-query XML Element ๐Ÿฆ‹

Name: free-busy-query

Namespace: urn:ietf:params:xml:ns:caldav

Purpose: CalDAV report used to generate a VFREEBUSY to determine busy time over a specific time range ๐Ÿซง

Description: See Section 7.10. Go check it out, it's giving full free-busy energy โœจ

Definition:

<!ELEMENT free-busy-query (time-range)>

10. Internationalization Considerations ๐ŸŒˆ

okay so CalDAV lets you store and fetch internationalized strings for the description of calendar collections ๐ŸŒโœจ (see Section 5.2.1). so your calendar can be named and described in whatever language or script you want, periodt ๐Ÿ’…

the CALDAV:calendar-query REPORT (Section 7.8) has a text searching option ๐Ÿ” that's controlled by the CALDAV:text-match element, and the nitty gritty of how characters get handled lives in that element's description (see Section 9.7.5). go read it, it's giving detail ๐Ÿง

11. Security Considerations ๐Ÿ”

okay this section is serious bestie, so listen up ๐Ÿซถ HTTP transactions travel in the clear over the network unless you've negotiated protection from snooping. you can fix that with TLS, as defined in [RFC2818]. and especially: HTTP Basic authentication MUST NOT be used unless TLS is in effect ๐Ÿšซ๐Ÿ”’ no plain Basic auth over open wifi, I'm begging you ๐Ÿ˜ญ

servers MUST take adequate precautions so that malicious clients can't eat up excessive server resources (CPU, memory, disk, etc.) through carefully crafted reports ๐Ÿ’€ like, imagine a client uploads an event with a recurrence rule saying it repeats every single second for the next 100 years. that's approximately 3 x 10^9 instances!!! ๐Ÿ˜ฑ a report that asks for those recurrences to be expanded over that whole range would likely count as a denial-of-service attack on the server. not it ๐Ÿ™…โ€โ™€๏ธ

when clients create new resources (including calendar collections), they MUST make sure the resource name (the last path segment of the resource URI) doesn't expose any data from inside the iCalendar resource itself, or info about what kind of calendar collection it is ๐Ÿคซ this is required so that nobody can guess whether a specific iCalendar component, or what types of components, live in a collection just by reading the resource name. privacy main character energy ๐Ÿ‘‘

when rolling up free-busy information, more info about a user's events gets exposed if busy periods overlap or are adjacent ๐Ÿ‘€ (this tells the client asking for the free-busy info that the calendar owner has at least two events, instead of only knowing that the owner has one or more events during the busy period). so a conservative approach to calendar data privacy would be for servers to always coalesce busy periods when they're the same type ๐Ÿซง

procedure alarms are a known security risk for clients or servers to handle, especially when the alarm was created by another agent ๐Ÿšจ clients and servers are not required to execute such procedure alarms. bye alarm ๐Ÿ‘‹

security considerations described in iCalendar [RFC2445] and iTIP [RFC2446] also apply to CalDAV ๐Ÿ“… and beyond those, CalDAV doesn't raise any security considerations that aren't already present in HTTP [RFC2616] and WebDAV [RFC2518], [RFC3253], [RFC3744]. so no surprise plot twists, it's giving continuity ๐ŸŽ€

12. IANA Considerations ๐Ÿ“‹

this document uses one new URN to identify a new XML namespace โœจ and the URN follows a registry mechanism described in [RFC3688]. very organized, very iconic ๐Ÿ’–

12.1. Namespace Registration

okay here's the registration request for the CalDAV namespace ๐Ÿฆ‹

  • URI: urn:ietf:params:xml:ns:caldav
  • Registrant Contact: See the "Authors' Addresses" section of this document.
  • XML: None. Namespace URIs do not represent an XML specification.

13. Acknowledgements ๐Ÿซถ๐ŸŒธ

the authors want to thank these lovely people for contributing their ideas and support while writing this spec ๐Ÿ’œ Michael Arick, Mario Bonin, Chris Bryant, Scott Carr, Andre Courtemanche, Mike Douglass, Ted Hardie, Marten den Haring, Jeffrey Harris, Sam Hartman, Helge Hess, Jeff McCullough, Alexey Melnikov, Dan Mosedale, Brian Moseley, Francois Perrault, Kervin L. Pierre, Julian F. Reschke, Wilfredo Sanchez Vega, Mike Shaver, Jari Urpalainen, Simon Vaillancourt, and Jim Whitehead. the big squad ๐Ÿฅน

the authors would also like to thank the Calendaring and Scheduling Consortium for advice on this spec, and for organizing interoperability testing events that helped refine it ๐ŸŽ‰๐Ÿงš

14. References ๐Ÿ“š

14.1. Normative References

  • [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997.
  • [RFC2246] Dierks, T. and C. Allen, "The TLS Protocol Version 1.0", RFC 2246, January 1999.
  • [RFC2445] Dawson, F. and Stenerson, D., "Internet Calendaring and Scheduling Core Object Specification (iCalendar)", RFC 2445, November 1998.
  • [RFC2446] Silverberg, S., Mansour, S., Dawson, F., and R. Hopson, "iCalendar Transport-Independent Interoperability Protocol (iTIP) Scheduling Events, BusyTime, To-dos and Journal Entries", RFC 2446, November 1998.
  • [RFC2518] Goland, Y., Whitehead, E., Faizi, A., Carter, S., and D. Jensen, "HTTP Extensions for Distributed Authoring -- WEBDAV", RFC 2518, February 1999.
  • [RFC2616] Fielding, R., Gettys, J., Mogul, J., Frystyk, H., Masinter, L., Leach, P., and T. Berners-Lee, "Hypertext Transfer Protocol -- HTTP/1.1", RFC 2616, June 1999.
  • [RFC2818] Rescorla, E., "HTTP Over TLS", RFC 2818, May 2000.
  • [RFC3253] Clemm, G., Amsden, J., Ellison, T., Kaler, C., and J. Whitehead, "Versioning Extensions to WebDAV (Web Distributed Authoring and Versioning)", RFC 3253, March 2002.
  • [RFC3688] Mealling, M., "The IETF XML Registry", BCP 81, RFC 3688, January 2004.
  • [RFC3744] Clemm, G., Reschke, J., Sedlar, E., and J. Whitehead, "Web Distributed Authoring and Versioning (WebDAV) Access Control Protocol", RFC 3744, May 2004.
  • [RFC4346] Dierks, T. and E. Rescorla, "The Transport Layer Security (TLS) Protocol Version 1.1", RFC 4346, April 2006.
  • [RFC4790] Newman, C., Duerst, M., and A. Gulbrandsen, "Internet Application Protocol Collation Registry", RFC 4790, March 2007.
  • [W3C.REC-xml-20060816] Paoli, J., Maler, E., Yergeau, F., Sperberg-McQueen, C., and T. Bray, "Extensible Markup Language (XML) 1.0 (Fourth Edition)", World Wide Web Consortium Recommendation REC-xml-20060816, August 2006, http://www.w3.org/TR/2006/REC-xml-20060816.

14.2. Informative References

  • [RFC2426] Dawson, F. and T. Howes, "vCard MIME Directory Profile", RFC 2426, September 1998.
  • [RFC2739] Small, T., Hennessy, D., and F. Dawson, "Calendar Attributes for vCard and LDAP", RFC 2739, January 2000.
  • [RFC4331] Korver, B. and L. Dusseault, "Quota and Size Properties for Distributed Authoring and Versioning (DAV) Collections", RFC 4331, February 2006.
  • [RFC4511] Sermersheim, J., "Lightweight Directory Access Protocol (LDAP): The Protocol", RFC 4511, June 2006.
  • [rfc2518bis] Dusseault, L., "HTTP Extensions for Distributed Authoring - WebDAV", Work in Progress, December 2006.

Appendix A. CalDAV Method Privilege Table (Normative) ๐Ÿ’…

the table below extends the WebDAV Method Privilege Table from Appendix B of [RFC3744] ๐ŸŒท it's normative, so it's not optional vibes ๐Ÿซก

+------------+------------------------------------------------------+
| METHOD     | PRIVILEGES                                           |
+------------+------------------------------------------------------+
| MKCALENDAR | DAV:bind                                             |
| REPORT     | DAV:read or CALDAV:read-free-busy (on all referenced |
|            | resources)                                           |
+------------+------------------------------------------------------+

Appendix B. Calendar Collections Used in the Examples โœจ

okay so this appendix is the big reveal ๐ŸŽ€ it shows the actual calendar object resources sitting inside the calendar collection that every example in this document has been querying. bestie, it's giving receipts ๐Ÿ’…

the collection is shown as if it came back from a CALDAV:calendar-query REPORT that asks for everything in the collection. so we get the request first, then the response, and the response is a whole pile of 207 Multi-Status goodness ๐Ÿฆ‹

Request <<
REPORT /bernard/work/ HTTP/1.1
Host: cal.example.com
Depth: 1
Content-Type: application/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<C:calendar-query xmlns:D="DAV:"
                 xmlns:C="urn:ietf:params:xml:ns:caldav">
 <D:prop>
   <D:getetag/>
   <C:calendar-data/>
 </D:prop>
 <C:filter>
   <C:comp-filter name="VCALENDAR"/>
 </C:filter>
</C:calendar-query>
Response <<
HTTP/1.1 207 Multi-Status
Content-Type: application/xml; charset="utf-8"
Content-Length: xxxx
<?xml version="1.0" encoding="utf-8" ?>
<D:multistatus xmlns:D="DAV:"
              xmlns:C="urn:ietf:params:xml:ns:caldav">

  <D:response>
    <D:href>http://cal.example.com/bernard/work/abcd1.ics</D:href>
    <D:propstat>
      <D:prop>
        <D:getetag>"fffff-abcd1"</D:getetag>
        <C:calendar-data>BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp.//CalDAV Client//EN
BEGIN:VTIMEZONE
LAST-MODIFIED:20040110T032845Z
TZID:US/Eastern
BEGIN:DAYLIGHT
DTSTART:20000404T020000
RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:20001026T020000
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
DTSTAMP:20060206T001102Z
DTSTART;TZID=US/Eastern:20060102T100000
DURATION:PT1H
SUMMARY:Event #1
Description:Go Steelers!
UID:74855313FA803DA593CD579A@example.com
END:VEVENT
END:VCALENDAR
</C:calendar-data>
      </D:prop>
      <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>
  </D:response>

  <D:response>
    <D:href>http://cal.example.com/bernard/work/abcd2.ics</D:href>
    <D:propstat>

      <D:prop>
        <D:getetag>"fffff-abcd2"</D:getetag>
        <C:calendar-data>BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp.//CalDAV Client//EN
BEGIN:VTIMEZONE
LAST-MODIFIED:20040110T032845Z
TZID:US/Eastern
BEGIN:DAYLIGHT
DTSTART:20000404T020000
RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:20001026T020000
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
DTSTAMP:20060206T001121Z
DTSTART;TZID=US/Eastern:20060102T120000
DURATION:PT1H
RRULE:FREQ=DAILY;COUNT=5
SUMMARY:Event #2
UID:00959BC664CA650E933C892C@example.com
END:VEVENT
BEGIN:VEVENT
DTSTAMP:20060206T001121Z
DTSTART;TZID=US/Eastern:20060104T140000
DURATION:PT1H
RECURRENCE-ID;TZID=US/Eastern:20060104T120000
SUMMARY:Event #2 bis
UID:00959BC664CA650E933C892C@example.com
END:VEVENT
END:VCALENDAR
</C:calendar-data>
      </D:prop>
      <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>
  </D:response>

  <D:response>
    <D:href>http://cal.example.com/bernard/work/abcd3.ics</D:href>
    <D:propstat>
      <D:prop>
        <D:getetag>"fffff-abcd3"</D:getetag>
        <C:calendar-data>BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp.//CalDAV Client//EN
BEGIN:VTIMEZONE
LAST-MODIFIED:20040110T032845Z
TZID:US/Eastern
BEGIN:DAYLIGHT
DTSTART:20000404T020000
RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:20001026T020000
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
ATTENDEE;PARTSTAT=ACCEPTED;ROLE=CHAIR:mailto:cyrus@example.com
ATTENDEE;PARTSTAT=NEEDS-ACTION:mailto:lisa@example.com
DTSTAMP:20060206T001220Z
DTSTART;TZID=US/Eastern:20060104T100000
DURATION:PT1H
LAST-MODIFIED:20060206T001330Z
ORGANIZER:mailto:cyrus@example.com
SEQUENCE:1
STATUS:TENTATIVE
SUMMARY:Event #3
UID:DC6C50A017428C5216A2F1CD@example.com
END:VEVENT
END:VCALENDAR
</C:calendar-data>
      </D:prop>
      <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>
  </D:response>

  <D:response>
    <D:href>http://cal.example.com/bernard/work/abcd4.ics</D:href>
    <D:propstat>
      <D:prop>

        <D:getetag>"fffff-abcd4"</D:getetag>
        <C:calendar-data>BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp.//CalDAV Client//EN
BEGIN:VTODO
DTSTAMP:20060205T235335Z
DUE;VALUE=DATE:20060104
STATUS:NEEDS-ACTION
SUMMARY:Task #1
UID:DDDEEB7915FA61233B861457@example.com
BEGIN:VALARM
ACTION:AUDIO
TRIGGER;RELATED=START:-PT10M
END:VALARM
END:VTODO
END:VCALENDAR
</C:calendar-data>
      </D:prop>
      <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>
  </D:response>

  <D:response>
    <D:href>http://cal.example.com/bernard/work/abcd5.ics</D:href>
    <D:propstat>
      <D:prop>
        <D:getetag>"fffff-abcd5"</D:getetag>
        <C:calendar-data>BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp.//CalDAV Client//EN
BEGIN:VTODO
DTSTAMP:20060205T235300Z
DUE;VALUE=DATE:20060106
LAST-MODIFIED:20060205T235308Z
SEQUENCE:1
STATUS:NEEDS-ACTION
SUMMARY:Task #2
UID:E10BA47467C5C69BB74E8720@example.com
BEGIN:VALARM
ACTION:AUDIO
TRIGGER;RELATED=START:-PT10M
END:VALARM
END:VTODO
END:VCALENDAR
</C:calendar-data>
      </D:prop>
      <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>

  </D:response>

  <D:response>
    <D:href>http://cal.example.com/bernard/work/abcd6.ics</D:href>
    <D:propstat>
      <D:prop>
        <D:getetag>"fffff-abcd6"</D:getetag>
        <C:calendar-data>BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp.//CalDAV Client//EN
BEGIN:VTODO
COMPLETED:20051223T122322Z
DTSTAMP:20060205T235400Z
DUE;VALUE=DATE:20051225
LAST-MODIFIED:20060205T235308Z
SEQUENCE:1
STATUS:COMPLETED
SUMMARY:Task #3
UID:E10BA47467C5C69BB74E8722@example.com
END:VTODO
END:VCALENDAR
</C:calendar-data>
      </D:prop>
      <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>
  </D:response>

  <D:response>
    <D:href>http://cal.example.com/bernard/work/abcd7.ics</D:href>
    <D:propstat>
      <D:prop>
        <D:getetag>"fffff-abcd7"</D:getetag>
        <C:calendar-data>BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp.//CalDAV Client//EN
BEGIN:VTODO
DTSTAMP:20060205T235600Z
DUE;VALUE=DATE:20060101
LAST-MODIFIED:20060205T235308Z
SEQUENCE:1
STATUS:CANCELLED
SUMMARY:Task #4
UID:E10BA47467C5C69BB74E8725@example.com
END:VTODO
END:VCALENDAR
</C:calendar-data>
      </D:prop>
      <D:status>HTTP/1.1 200 OK</D:status>

    </D:propstat>
  </D:response>

  <D:response>
    <D:href>http://cal.example.com/bernard/work/abcd8.ics</D:href>
    <D:propstat>
      <D:prop>
        <D:getetag>"fffff-abcd8"</D:getetag>
        <C:calendar-data>BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp.//CalDAV Client//EN
BEGIN:VFREEBUSY
ORGANIZER;CN="Bernard Desruisseaux":mailto:bernard@example.com
UID:76ef34-54a3d2@example.com
DTSTAMP:20050530T123421Z
DTSTART:20060101T000000Z
DTEND:20060108T000000Z
FREEBUSY:20050531T230000Z/20050601T010000Z
FREEBUSY;FBTYPE=BUSY-TENTATIVE:20060102T100000Z/20060102T120000Z
FREEBUSY:20060103T100000Z/20060103T120000Z
FREEBUSY:20060104T100000Z/20060104T120000Z
FREEBUSY;FBTYPE=BUSY-UNAVAILABLE:20060105T100000Z/20060105T120000Z
FREEBUSY:20060106T100000Z/20060106T120000Z
END:VFREEBUSY
END:VCALENDAR
</C:calendar-data>
      </D:prop>
      <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>
  </D:response>

</D:multistatus>

Authors' Addresses ๐Ÿงš

Cyrus Daboo ๐Ÿ’œ Apple Inc. 1 Infinite Loop Cupertino, CA 95014 USA

EMail: cyrus@daboo.name URI: http://www.apple.com/

Bernard Desruisseaux ๐ŸŒธ Oracle Corporation 600 Blvd. de Maisonneuve West Suite 1900 Montreal, QC H3A 3J2 CANADA

EMail: bernard.desruisseaux@oracle.com URI: http://www.oracle.com/

Lisa Dusseault ๐Ÿ“ CommerceNet 169 University Ave. Palo Alto, CA 94301 USA

EMail: ldusseault@commerce.net URI: http://commerce.net/


Copyright (C) The IETF Trust (2007).

This document is subject to the rights, licenses and restrictions contained in BCP 78, and except as set forth therein, the authors retain all their rights.

This document and the information contained herein are provided on an "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY, THE IETF TRUST AND THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.


Intellectual Property ๐Ÿ”ฅ

The IETF takes no position regarding the validity or scope of any Intellectual Property Rights or other rights that might be claimed to pertain to the implementation or use of the technology described in this document or the extent to which any license under such rights might or might not be available; nor does it represent that it has made any independent effort to identify any such rights. Information on the procedures with respect to rights in RFC documents can be found in BCP 78 and BCP 79.

Copies of IPR disclosures made to the IETF Secretariat and any assurances of licenses to be made available, or the result of an attempt made to obtain a general license or permission for the use of such proprietary rights by implementers or users of this specification can be obtained from the IETF on-line IPR repository at http://www.ietf.org/ipr.

The IETF invites any interested party to bring to its attention any copyrights, patents or patent applications, or other proprietary rights that may cover technology that may be required to implement this standard. Please address the information to the IETF at ietf-ipr@ietf.org.


Acknowledgement ๐Ÿ’–

Funding for the RFC Editor function is currently provided by the Internet Society.

๐Ÿ“ฆ where this page comes from