Search code examples
phpeventsdomcurlcaldav

Get events from CalDAV server using curl


I am trying to get all events from a certain CalDAV server (Baikal in this case) with curl. Base tutorial for this task is this.

According to this tutorial, the request should look something like this:

PROPFIND /calendars/johndoe/home/ HTTP/1.1
Depth: 0
Prefer: return-minimal
Content-Type: application/xml; charset=utf-8

<d:propfind xmlns:d="DAV:" xmlns:cs="http://calendarserver.org/ns/">
  <d:prop>
     <d:displayname />
     <cs:getctag />
  </d:prop>
</d:propfind>

This is my implementation:

$headers = array(

        'Content-Type: application/xml; charset=utf-8',
        'Depth: 0',
        'Prefer: return-minimal'
    );

$fp = fopen(dirname(__FILE__).'/getEventCURLError.txt', 'w');
$url = "http://xxx.ch/dav/cal.php/calendars/john/john-cal/";
$userpwd = "john:12345";

// prepare request body
$doc  = new DOMDocument('1.0', 'utf-8');
$doc->formatOutput = true;

$query = $doc->createElement('c:calendar-query');
$query->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:c', 'urn:ietf:params:xml:ns:caldav');
$query->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:d', 'DAV:');

$prop = $doc->createElement('d:prop');
$prop->appendChild($doc->createElement('d:getetag'));
$prop->appendChild($doc->createElement('c:calendar-data'));
$query->appendChild($prop);
$doc->appendChild($query);
$body = $doc->saveXML();

echo "Body: " . $body . "<br>";

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_USERPWD, $userpwd);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_STDERR, $fp);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PROPFIND');
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);

$response = curl_exec($ch);
curl_close($ch);

print_r($response);    

$xml = simplexml_load_string($response);
print_r($xml)

The output is this:

Body: 

/dav/cal.php/calendars/john/john-cal/HTTP/1.1 200 OK 

SimpleXMLElement Object ( )

Even though I have a lot of events in the calendar, they don't seem to be returned. What am I doing wrong here? Any input is appreciated.


Solution

  • Presumably your code doesn't work because you are using a calendar-query REPORT entity with a PROPFIND request.

    $query = $doc->createElement('c:calendar-query');
    

    ...

    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PROPFIND');
    

    A PROPFIND request expects a propfind entity in the request, not a calendar-query one, as shown in the original example:

    PROPFIND /calendars/johndoe/home/ HTTP/1.1
    Depth: 0
    Prefer: return-minimal
    Content-Type: application/xml; charset=utf-8
    
    <d:propfind xmlns:d="DAV:" xmlns:cs="http://calendarserver.org/ns/">
      <d:prop>
         <d:displayname />
         <cs:getctag />
      </d:prop>
    </d:propfind>
    

    You have two choices, either create a proper calendar-query REPORT (i.e. do curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'REPORT')) or emit a proper PROPFIND request entity. I'd say the latter is the better choice.