/**
  * Parses the request.
  *
  * @return void
  */
 public function parse()
 {
     $filterNode = null;
     $filter = $this->xpath->query('/cal:calendar-query/cal:filter');
     if ($filter->length !== 1) {
         throw new Sabre_DAV_Exception_BadRequest('Only one filter element is allowed');
     }
     $compFilters = $this->parseCompFilters($filter->item(0));
     if (count($compFilters) !== 1) {
         throw new Sabre_DAV_Exception_BadRequest('There must be exactly 1 top-level comp-filter.');
     }
     $this->filters = $compFilters[0];
     $this->requestedProperties = array_keys(Sabre_DAV_XMLUtil::parseProperties($this->dom->firstChild));
     $expand = $this->xpath->query('/cal:calendar-query/dav:prop/cal:calendar-data/cal:expand');
     if ($expand->length > 0) {
         $this->expand = $this->parseExpand($expand->item(0));
     }
 }
Beispiel #2
0
 /**
  * This function handles the addressbook-multiget REPORT.
  *
  * This report is used by the client to fetch the content of a series
  * of urls. Effectively avoiding a lot of redundant requests.
  *
  * @param DOMNode $dom
  * @return void
  */
 public function addressbookMultiGetReport($dom)
 {
     $properties = array_keys(Sabre_DAV_XMLUtil::parseProperties($dom->firstChild));
     $hrefElems = $dom->getElementsByTagNameNS('urn:DAV', 'href');
     $propertyList = array();
     foreach ($hrefElems as $elem) {
         $uri = $this->server->calculateUri($elem->nodeValue);
         list($propertyList[]) = $this->server->getPropertiesForPath($uri, $properties);
     }
     $this->server->httpResponse->sendStatus(207);
     $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8');
     $this->server->httpResponse->sendBody($this->server->generateMultiStatus($propertyList));
 }
 /**
  * This method parses the PROPFIND request and returns its information
  *
  * This will either be a list of properties, or an empty array; in which case
  * an {DAV:}allprop was requested.
  *
  * @param string $body
  * @return array
  */
 public function parsePropFindRequest($body)
 {
     // If the propfind body was empty, it means IE is requesting 'all' properties
     if (!$body) {
         return array();
     }
     $dom = Sabre_DAV_XMLUtil::loadDOMDocument($body);
     $elem = $dom->getElementsByTagNameNS('urn:DAV', 'propfind')->item(0);
     return array_keys(Sabre_DAV_XMLUtil::parseProperties($elem));
 }
Beispiel #4
0
    function testParsePropertiesMapHref()
    {
        $xml = '<?xml version="1.0"?>
<root xmlns="DAV:">
  <prop>
    <displayname>Calendars</displayname>
  </prop>
  <prop>
    <someprop><href>http://sabredav.org/</href></someprop>
  </prop>
</root>';
        $dom = Sabre_DAV_XMLUtil::loadDOMDocument($xml);
        $properties = Sabre_DAV_XMLUtil::parseProperties($dom->firstChild, array('{DAV:}someprop' => 'Sabre_DAV_Property_Href'));
        $this->assertEquals(array('{DAV:}displayname' => 'Calendars', '{DAV:}someprop' => new Sabre_DAV_Property_Href('http://sabredav.org/', false)), $properties);
    }
Beispiel #5
0
 /**
  * This function handles the calendar-multiget REPORT.
  *
  * This report is used by the client to fetch the content of a series
  * of urls. Effectively avoiding a lot of redundant requests.
  *
  * @param DOMNode $dom
  * @return void
  */
 public function calendarMultiGetReport($dom)
 {
     $properties = array_keys(Sabre_DAV_XMLUtil::parseProperties($dom->firstChild));
     $hrefElems = $dom->getElementsByTagNameNS('urn:DAV', 'href');
     $xpath = new DOMXPath($dom);
     $xpath->registerNameSpace('cal', Sabre_CalDAV_Plugin::NS_CALDAV);
     $xpath->registerNameSpace('dav', 'urn:DAV');
     $expand = $xpath->query('/cal:calendar-multiget/dav:prop/cal:calendar-data/cal:expand');
     if ($expand->length > 0) {
         $expandElem = $expand->item(0);
         $start = $expandElem->getAttribute('start');
         $end = $expandElem->getAttribute('end');
         if (!$start || !$end) {
             throw new Sabre_DAV_Exception_BadRequest('The "start" and "end" attributes are required for the CALDAV:expand element');
         }
         $start = Sabre_VObject_DateTimeParser::parseDateTime($start);
         $end = Sabre_VObject_DateTimeParser::parseDateTime($end);
         if ($end <= $start) {
             throw new Sabre_DAV_Exception_BadRequest('The end-date must be larger than the start-date in the expand element.');
         }
         $expand = true;
     } else {
         $expand = false;
     }
     foreach ($hrefElems as $elem) {
         $uri = $this->server->calculateUri($elem->nodeValue);
         list($objProps) = $this->server->getPropertiesForPath($uri, $properties);
         if ($expand && isset($objProps[200]['{' . self::NS_CALDAV . '}calendar-data'])) {
             $vObject = Sabre_VObject_Reader::read($objProps[200]['{' . self::NS_CALDAV . '}calendar-data']);
             $vObject->expand($start, $end);
             $objProps[200]['{' . self::NS_CALDAV . '}calendar-data'] = $vObject->serialize();
         }
         $propertyList[] = $objProps;
     }
     $this->server->httpResponse->sendStatus(207);
     $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8');
     $this->server->httpResponse->sendBody($this->server->generateMultiStatus($propertyList));
 }
Beispiel #6
0
 /**
  * parsePrincipalPropertySearchReportRequest
  *
  * This method parses the request body from a
  * {DAV:}principal-property-search report.
  *
  * This method returns an array with two elements:
  *  1. an array with properties to search on, and their values
  *  2. a list of propertyvalues that should be returned for the request.
  * 
  * @param DOMDocument $dom 
  * @return array 
  */
 protected function parsePrincipalPropertySearchReportRequest($dom)
 {
     $httpDepth = $this->server->getHTTPDepth(0);
     if ($httpDepth !== 0) {
         throw new Sabre_DAV_Exception_BadRequest('This report is only defined when Depth: 0');
     }
     $searchProperties = array();
     $applyToPrincipalCollectionSet = false;
     // Parsing the search request
     foreach ($dom->firstChild->childNodes as $searchNode) {
         if (Sabre_DAV_XMLUtil::toClarkNotation($searchNode) == '{DAV:}apply-to-principal-collection-set') {
             $applyToPrincipalCollectionSet = true;
         }
         if (Sabre_DAV_XMLUtil::toClarkNotation($searchNode) !== '{DAV:}property-search') {
             continue;
         }
         $propertyName = null;
         $propertyValue = null;
         foreach ($searchNode->childNodes as $childNode) {
             switch (Sabre_DAV_XMLUtil::toClarkNotation($childNode)) {
                 case '{DAV:}prop':
                     $property = Sabre_DAV_XMLUtil::parseProperties($searchNode);
                     reset($property);
                     $propertyName = key($property);
                     break;
                 case '{DAV:}match':
                     $propertyValue = $childNode->textContent;
                     break;
             }
         }
         if (is_null($propertyName) || is_null($propertyValue)) {
             throw new Sabre_DAV_Exception_BadRequest('Invalid search request. propertyname: ' . $propertyName . '. propertvvalue: ' . $propertyValue);
         }
         $searchProperties[$propertyName] = $propertyValue;
     }
     return array($searchProperties, array_keys(Sabre_DAV_XMLUtil::parseProperties($dom->firstChild)), $applyToPrincipalCollectionSet);
 }
 /**
  * Parses the request.
  *
  * @return void
  */
 public function parse()
 {
     $filterNode = null;
     $limit = $this->xpath->evaluate('number(/card:addressbook-query/card:limit/card:nresults)');
     if (is_nan($limit)) {
         $limit = null;
     }
     $filter = $this->xpath->query('/card:addressbook-query/card:filter');
     if ($filter->length !== 1) {
         throw new Sabre_DAV_Exception_BadRequest('Only one filter element is allowed');
     }
     $filter = $filter->item(0);
     $test = $this->xpath->evaluate('string(@test)', $filter);
     if (!$test) {
         $test = self::TEST_ANYOF;
     }
     if ($test !== self::TEST_ANYOF && $test !== self::TEST_ALLOF) {
         throw new Sabre_DAV_Exception_BadRequest('The test attribute must either hold "anyof" or "allof"');
     }
     $propFilters = array();
     $propFilterNodes = $this->xpath->query('card:prop-filter', $filter);
     for ($ii = 0; $ii < $propFilterNodes->length; $ii++) {
         $propFilters[] = $this->parsePropFilterNode($propFilterNodes->item($ii));
     }
     $this->filters = $propFilters;
     $this->limit = $limit;
     $this->requestedProperties = array_keys(Sabre_DAV_XMLUtil::parseProperties($this->dom->firstChild));
     $this->test = $test;
 }
Beispiel #8
0
 /**
  * Parses a WebDAV multistatus response body
  *
  * This method returns an array with the following structure
  *
  * array(
  *   'url/to/resource' => array(
  *     '200' => array(
  *        '{DAV:}property1' => 'value1',
  *        '{DAV:}property2' => 'value2',
  *     ),
  *     '404' => array(
  *        '{DAV:}property1' => null,
  *        '{DAV:}property2' => null,
  *     ),
  *   )
  *   'url/to/resource2' => array(
  *      .. etc ..
  *   )
  * )
  *
  *
  * @param string $body xml body
  * @return array
  */
 public function parseMultiStatus($body)
 {
     $responseXML = simplexml_load_string($body, null, LIBXML_NOBLANKS | LIBXML_NOCDATA);
     if ($responseXML === false) {
         throw new InvalidArgumentException('The passed data is not valid XML');
     }
     $responseXML->registerXPathNamespace('d', 'DAV:');
     $propResult = array();
     foreach ($responseXML->xpath('d:response') as $response) {
         $response->registerXPathNamespace('d', 'DAV:');
         $href = $response->xpath('d:href');
         $href = (string) $href[0];
         $properties = array();
         foreach ($response->xpath('d:propstat') as $propStat) {
             $propStat->registerXPathNamespace('d', 'DAV:');
             $status = $propStat->xpath('d:status');
             list($httpVersion, $statusCode, $message) = explode(' ', (string) $status[0], 3);
             $properties[$statusCode] = Sabre_DAV_XMLUtil::parseProperties(dom_import_simplexml($propStat), $this->propertyMap);
         }
         $propResult[$href] = $properties;
     }
     return $propResult;
 }
Beispiel #9
0
 /**
  * This function handles the calendar-query REPORT
  *
  * This report is used by clients to request calendar objects based on
  * complex conditions.
  * 
  * @param DOMNode $dom 
  * @return void
  */
 public function calendarQueryReport($dom)
 {
     $requestedProperties = array_keys(Sabre_DAV_XMLUtil::parseProperties($dom->firstChild));
     $filterNode = $dom->getElementsByTagNameNS('urn:ietf:params:xml:ns:caldav', 'filter');
     if ($filterNode->length !== 1) {
         throw new Sabre_DAV_Exception_BadRequest('The calendar-query report must have a filter element');
     }
     $filters = Sabre_CalDAV_XMLUtil::parseCalendarQueryFilters($filterNode->item(0));
     $requestedCalendarData = true;
     if (!in_array('{urn:ietf:params:xml:ns:caldav}calendar-data', $requestedProperties)) {
         // We always retrieve calendar-data, as we need it for filtering.
         $requestedProperties[] = '{urn:ietf:params:xml:ns:caldav}calendar-data';
         // If calendar-data wasn't explicitly requested, we need to remove
         // it after processing.
         $requestedCalendarData = false;
     }
     // These are the list of nodes that potentially match the requirement
     $candidateNodes = $this->server->getPropertiesForPath($this->server->getRequestUri(), $requestedProperties, $this->server->getHTTPDepth(0));
     $verifiedNodes = array();
     foreach ($candidateNodes as $node) {
         // If the node didn't have a calendar-data property, it must not be a calendar object
         if (!isset($node[200]['{urn:ietf:params:xml:ns:caldav}calendar-data'])) {
             continue;
         }
         if ($this->validateFilters($node[200]['{urn:ietf:params:xml:ns:caldav}calendar-data'], $filters)) {
             if (!$requestedCalendarData) {
                 unset($node[200]['{urn:ietf:params:xml:ns:caldav}calendar-data']);
             }
             $verifiedNodes[] = $node;
         }
     }
     $this->server->httpResponse->sendStatus(207);
     $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8');
     $this->server->httpResponse->sendBody($this->server->generateMultiStatus($verifiedNodes));
 }
 /**
  * Parses the request.
  *
  * @return void
  */
 public function parse()
 {
     $filterNode = null;
     $limit = $this->xpath->evaluate('number(/card:addressbook-query/card:limit/card:nresults)');
     if (is_nan($limit)) {
         $limit = null;
     }
     $filter = $this->xpath->query('/card:addressbook-query/card:filter');
     // According to the CardDAV spec there needs to be exactly 1 filter
     // element. However, KDE 4.8.2 contains a bug that will encode 0 filter
     // elements, so this is a workaround for that.
     //
     // See: https://bugs.kde.org/show_bug.cgi?id=300047
     if ($filter->length === 0) {
         $test = null;
         $filter = null;
     } elseif ($filter->length === 1) {
         $filter = $filter->item(0);
         $test = $this->xpath->evaluate('string(@test)', $filter);
     } else {
         throw new Sabre_DAV_Exception_BadRequest('Only one filter element is allowed');
     }
     if (!$test) {
         $test = self::TEST_ANYOF;
     }
     if ($test !== self::TEST_ANYOF && $test !== self::TEST_ALLOF) {
         throw new Sabre_DAV_Exception_BadRequest('The test attribute must either hold "anyof" or "allof"');
     }
     $propFilters = array();
     $propFilterNodes = $this->xpath->query('card:prop-filter', $filter);
     for ($ii = 0; $ii < $propFilterNodes->length; $ii++) {
         $propFilters[] = $this->parsePropFilterNode($propFilterNodes->item($ii));
     }
     $this->filters = $propFilters;
     $this->limit = $limit;
     $this->requestedProperties = array_keys(Sabre_DAV_XMLUtil::parseProperties($this->dom->firstChild));
     $this->test = $test;
 }