CalDAV REPORTメソッドを使ってスケジュール情報を取得する
CalDAV(RFC 4791)とは、iCalendar(RFC 2445)をWebDAV(RFC 4918)上でやり取りするための仕様です。
iCalendarは、スケジュールのカレンダー情報を記述するための仕様で、RSSのカレンダー版といったところでしょうか。そしてCalDAVはiCalendarをWebDAVプロトコルでやり取りするための仕組みです。
CalDAVに対応したクライアントは、MacのiCalが一番有名です。あと、SunbirdなどもCalDAVに対応しています。
Google CalendarにMacのiCalから接続できたりするのは、このCalDAVプロトコルに依るところです。
RFC 2445を始めとするiCalendar関連の仕様は、非常に幅が広くワーキングドラフトまで含めるとPIMに必要な機能がほぼすべて揃っています。
関連仕様の説明と各仕様へのリンクについてはCalDAV HomeのStarndardsにまとまっています。
早速、CalDAVで最も良く利用されるREPORTメソッドについて説明します。
REPORTメソッドは、CalDAV固有のメソッドで、iCalファイルを一度に取得するためのメソッドです。
(ちなみに、CalDAV固有のメソッドはもうひとつMKCALENDARメソッドのみです。)
WebDAVでファイルを取得するためのメソッドはGETですが、1月分のスケジュールを表示したいというような場合には、複数のiCalファイルを一度に取得する必要があります。
というのは、通常、CalDAVで扱う1つのファイルにはVCALENDARが1つ入っており、VCALENDARには一つVEVENTが入っています。(例外はあり、繰り返しイベントのようにVCALENDARには複数のVEVENTが入る場合もあります。)
つまり、CalDAVサーバー上には、各イベントが1つのiCalファイルとして扱われます。
REPORTメソッドは、「2010年4月のイベントを取得する」や「未承認のイベントを取得する」、「繰り返しイベントをある期間展開して取得する」など条件に合ったiCalファイルを取得するためのメソッドで、また、取得するデータに含めるプロパティも指定することができSQLのSELECT文と同じ働きをします。
以下は、2010年4月18日から4月24日のイベントを取得するクエリーです。Google Calendarに対して実行してみました。
(Google CalendarのCalDAVにアクセスする方法についてはこちらを参照ください)
REPORT /calendar/dav/hrendoh@gmail.com/events/ HTTP/1.1 Host: www.google.com Depth: 1 Content-Type: application/xml; charset="utf-8" Authorization: Basic XXXX Content-Length: 467 <?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:comp-filter name="VEVENT"> <C:time-range start="20060104T000000Z" end="20060105T000000Z"/> </C:comp-filter> </C:comp-filter> </C:filter> </C:calendar-query>
検索条件はfilter要素に指定します。
filter要素には以下の3種類の条件が指定できます。
- comp-filter要素: カレンダーのコンポーネントに対する条件文を指定します。comp-filter要素は、time-range要素または、comp-prop要素を指定できます。上記の例はcomp-filterにtime-range要素を指定しています。
- prop-filter要素: カレンダーのコンポーネントに対する条件文を指定します。子要素にパラメータを条件に指定するparam-filter要素を指定できます。ただし、prop-filterが実装されているサーバーは多くは無いようです。Google CalendarとBedeworkはフィルターが効きませんでした。
- param-filter要素: カレンダーのコンポーネントのプロパティのパラメータに対する条件文を指定します。
上記のクエリーは以下の結果を返します。
<?xml version="1.0" encoding="UTF-8"?> <D:multistatus xmlns:D="DAV:"> <D:response> <D:href>/calendar/dav/hrendoh%40gmail.com/events/pocjt9sjnctri32i1auaj8ojao%40google.com.ics</D:href> <D:propstat> <D:status>HTTP/1.1 200 OK</D:status> <D:prop> <D:getetag>"63407192760"</D:getetag> <C:calendar-data xmlns:C="urn:ietf:params:xml:ns:caldav">BEGIN:VCALENDAR PRODID:-//Google Inc//Google Calendar 70.9054//EN VERSION:2.0 CALSCALE:GREGORIAN X-WR-CALNAME:Hiroyuki Endoh X-WR-TIMEZONE:Asia/Tokyo BEGIN:VTIMEZONE TZID:Asia/Tokyo X-LIC-LOCATION:Asia/Tokyo BEGIN:STANDARD TZOFFSETFROM:+0900 TZOFFSETTO:+0900 TZNAME:JST DTSTART:19700101T000000 END:STANDARD END:VTIMEZONE BEGIN:VEVENT DTSTART;VALUE=DATE:20100420 DTEND;VALUE=DATE:20100421 DTSTAMP:20100417T130600Z UID:pocjt9sjnctri32i1auaj8ojao@google.com CREATED:20100417T130600Z DESCRIPTION: LAST-MODIFIED:20100417T130600Z LOCATION: SEQUENCE:0 STATUS:CONFIRMED SUMMARY:テスト TRANSP:TRANSPARENT BEGIN:VALARM ACTION:DISPLAY DESCRIPTION:This is an event reminder TRIGGER:-P0DT0H10M0S END:VALARM END:VEVENT END:VCALENDAR</C:calendar-data> </D:prop> </D:propstat> </D:response> </D:multistatus>
上記の例では、カレンダーのプロパティをすべて取得します。
必要なプロパティのみを結果に含める場合には、calendar-data要素にcomp要素を指定します。
また、RRULEプロパティを含む繰り返しイベントは展開して取得することもできます。expand要素に展開する開始日(start属性)と終了日(end属性)を指定します。
以下は、18日から3日間のみ繰り返しを展開するようにexpand要素を指定しています。また、結果が長くなるのでcomp要素により取得するプロパティも絞り込んでいます。
プロパティの指定と、繰り返しイベントの展開は、Google Calendarでは実装されていませんでしたので、以下はBedeworkに対して実行しています。
REPORT http://localhost:8080/ucaldav/user/test1/calendar HTTP/1.1 Host: localhost:8080 Depth: 1 Content-Type: application/xml; charset="utf-8" Authorization: Basic dGVzdDE6dGVzdA== Content-Length: 999 <?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: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="RECURRENCE-ID"/> </C:comp> <C:comp name="VTIMEZONE"/> </C:comp> <C:expand start="20100418T000000Z" end="20100421T000000Z"/> </C:calendar-data> </D:prop> <C:filter> <C:comp-filter name="VCALENDAR"> <C:comp-filter name="VEVENT"> <C:time-range start="20100418T000000Z" end="20100424T000000Z"/> </C:comp-filter> </C:comp-filter> </C:filter> </C:calendar-query>
CalDAVサーバーには4月中毎日繰り返すイベントが登録されています。
応答は以下の通り、正しく18日から3日間だけ展開されています。
<?xml version="1.0" encoding="UTF-8" ?> <multistatus xmlns="DAV:" xmlns:ns2="http://www.w3.org/2002/12/cal/ical#" xmlns:ns1="urn:ietf:params:xml:ns:caldav"> <response> <href>/ucaldav/user/test1/calendar/47a3b8e0-4a2d-11df-bae6-001c23f8c3c1.ics</href> <propstat> <prop> <ns1:calendar-data><![CDATA[BEGIN:VCALENDAR PRODID:BedeWork V3.5 VERSION:2.0 METHOD:REQUEST BEGIN:VEVENT DTSTAMP:20100417T143109Z SUMMARY:毎日 UID:47a3b8e0-4a2d-11df-bae6-001c23f8c3c1 DTSTART:20100418T020000Z DTEND:20100418T030000Z RECURRENCE-ID:20100418T110000Z END:VEVENT END:VCALENDAR ]]></ns1:calendar-data> </prop> <status>HTTP/1.1 200 ok</status> </propstat> </response> <response> <href>/ucaldav/user/test1/calendar/47a3b8e0-4a2d-11df-bae6-001c23f8c3c1.ics</href> <propstat> <prop> <ns1:calendar-data><![CDATA[BEGIN:VCALENDAR PRODID:BedeWork V3.5 VERSION:2.0 METHOD:REQUEST BEGIN:VEVENT DTSTAMP:20100417T143109Z SUMMARY:毎日 UID:47a3b8e0-4a2d-11df-bae6-001c23f8c3c1 DTSTART:20100419T020000Z DTEND:20100419T030000Z RECURRENCE-ID:20100419T110000Z END:VEVENT END:VCALENDAR ]]></ns1:calendar-data> </prop> <status>HTTP/1.1 200 ok</status> </propstat> </response> <response> <href>/ucaldav/user/test1/calendar/47a3b8e0-4a2d-11df-bae6-001c23f8c3c1.ics</href> <propstat> <prop> <ns1:calendar-data><![CDATA[BEGIN:VCALENDAR PRODID:BedeWork V3.5 VERSION:2.0 METHOD:REQUEST BEGIN:VEVENT DTSTAMP:20100417T143109Z SUMMARY:毎日 UID:47a3b8e0-4a2d-11df-bae6-001c23f8c3c1 DTSTART:20100420T020000Z DTEND:20100420T030000Z RECURRENCE-ID:20100420T110000Z END:VEVENT END:VCALENDAR ]]></ns1:calendar-data> </prop> <status>HTTP/1.1 200 ok</status> </propstat> </response> </multistatus>