function testSerialize()
    {
        $dt = new DateTime('2010-03-14 16:35', new DateTimeZone('UTC'));
        $lastMod = new Sabre_DAV_Property_GetLastModified($dt);
        $doc = new DOMDocument();
        $root = $doc->createElement('d:getlastmodified');
        $root->setAttribute('xmlns:d', 'DAV:');
        $doc->appendChild($root);
        $objectTree = new Sabre_DAV_ObjectTree(new Sabre_DAV_SimpleDirectory('rootdir'));
        $server = new Sabre_DAV_Server($objectTree);
        $lastMod->serialize($server, $root);
        $xml = $doc->saveXML();
        $this->assertEquals('<?xml version="1.0"?>
<d:getlastmodified xmlns:d="DAV:" xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">' . Sabre_HTTP_Util::toHTTPDate($dt) . '</d:getlastmodified>
', $xml);
        $ok = false;
        try {
            Sabre_DAV_Property_GetLastModified::unserialize(Sabre_DAV_XMLUtil::loadDOMDocument($xml)->firstChild);
        } catch (Sabre_DAV_Exception $e) {
            $ok = true;
        }
        if (!$ok) {
            $this->markTestFailed('Unserialize should not be supported');
        }
    }
 function parse($xml)
 {
     $xml = implode("\n", $xml);
     $dom = Sabre_DAV_XMLUtil::loadDOMDocument($xml);
     $q = new Sabre_CardDAV_AddressBookQueryParser($dom);
     $q->parse();
     return $q;
 }
    /**
     * @depends testSimple
     */
    function testUnserializer()
    {
        $xml = '<?xml version="1.0"?>
<d:root xmlns:d="DAV:" xmlns:cal="' . Sabre_CalDAV_Plugin::NS_CALDAV . '">' . '<cal:comp name="VEVENT"/>' . '<cal:comp name="VJOURNAL"/>' . '</d:root>';
        $dom = Sabre_DAV_XMLUtil::loadDOMDocument($xml);
        $property = Sabre_CalDAV_Property_SupportedCalendarComponentSet::unserialize($dom->firstChild);
        $this->assertTrue($property instanceof Sabre_CalDAV_Property_SupportedCalendarComponentSet);
        $this->assertEquals(array('VEVENT', 'VJOURNAL'), $property->getValue());
    }
    /**
     * @depends testConstruct
     */
    function testUnserialize()
    {
        $xml = '<?xml version="1.0"?>
<d:anything xmlns:d="DAV:"><d:collection/><d:principal/></d:anything>
';
        $dom = Sabre_DAV_XMLUtil::loadDOMDocument($xml);
        $resourceType = Sabre_DAV_Property_ResourceType::unserialize($dom->firstChild);
        $this->assertEquals(array('{DAV:}collection', '{DAV:}principal'), $resourceType->getValue());
    }
Пример #5
0
 /**
  * Unserializes this property from a DOM Element
  *
  * This method returns an instance of this class.
  * It will only decode {DAV:}href values.
  *
  * @param DOMElement $dom
  * @return Sabre_DAV_Property_Href
  */
 static function unserialize(DOMElement $dom)
 {
     $hrefs = array();
     foreach ($dom->childNodes as $child) {
         if (Sabre_DAV_XMLUtil::toClarkNotation($child) === '{DAV:}href') {
             $hrefs[] = $child->textContent;
         }
     }
     return new self($hrefs, false);
 }
 /**
  * Unserializes the DOMElement back into a Property class.
  * 
  * @param DOMElement $node 
  * @return void
  */
 static function unserialize(DOMElement $node)
 {
     $components = array();
     foreach ($node->childNodes as $childNode) {
         if (Sabre_DAV_XMLUtil::toClarkNotation($childNode) === '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}comp') {
             $components[] = $childNode->getAttribute('name');
         }
     }
     return new self($components);
 }
 /**
  * This function parses the calendar-query report request body
  *
  * The body is quite complicated, so we're turning it into a PHP
  * array.
  *
  * The resulting associative array has xpath expressions as keys.
  * By default the xpath expressions should simply be checked for existance
  * The xpath expressions can point to elements or attributes.
  * 
  * The array values can contain a number of items, which alters the query
  * filter. 
  *
  * * time-range. Must also check if the todo or event falls within the
  *               specified timerange. How this is interpreted depends on
  *               the type of object (VTODO, VEVENT, VJOURNAL, etc)
  * * is-not-defined
  *               Instead of checking if the attribute or element exist,
  *               we must check if it doesn't.
  * * text-match
  *               Checks if the value of the attribute or element matches
  *               the specified value. This is actually another array with
  *               the 'collation', 'value' and 'negate-condition' items.
  *
  * Refer to the CalDAV spec for more information.
  * 
  * @param DOMNode $domNode 
  * @param string $basePath used for recursive calls.
  * @param array $filters used for recursive calls.
  * @return array 
  */
 public static function parseCalendarQueryFilters($domNode, $basePath = '/c:iCalendar', &$filters = array())
 {
     foreach ($domNode->childNodes as $child) {
         switch (Sabre_DAV_XMLUtil::toClarkNotation($child)) {
             case '{urn:ietf:params:xml:ns:caldav}comp-filter':
             case '{urn:ietf:params:xml:ns:caldav}prop-filter':
                 $filterName = $basePath . '/' . 'c:' . strtolower($child->getAttribute('name'));
                 $filters[$filterName] = array();
                 self::parseCalendarQueryFilters($child, $filterName, $filters);
                 break;
             case '{urn:ietf:params:xml:ns:caldav}time-range':
                 if ($start = $child->getAttribute('start')) {
                     $start = self::parseICalendarDateTime($start);
                 } else {
                     $start = null;
                 }
                 if ($end = $child->getAttribute('end')) {
                     $end = self::parseICalendarDateTime($end);
                 } else {
                     $end = null;
                 }
                 if (!is_null($start) && !is_null($end) && $end <= $start) {
                     throw new Sabre_DAV_Exception_BadRequest('The end-date must be larger than the start-date in the time-range filter');
                 }
                 $filters[$basePath]['time-range'] = array('start' => $start, 'end' => $end);
                 break;
             case '{urn:ietf:params:xml:ns:caldav}is-not-defined':
                 $filters[$basePath]['is-not-defined'] = true;
                 break;
             case '{urn:ietf:params:xml:ns:caldav}param-filter':
                 $filterName = $basePath . '/@' . strtolower($child->getAttribute('name'));
                 $filters[$filterName] = array();
                 self::parseCalendarQueryFilters($child, $filterName, $filters);
                 break;
             case '{urn:ietf:params:xml:ns:caldav}text-match':
                 $collation = $child->getAttribute('collation');
                 if (!$collation) {
                     $collation = 'i;ascii-casemap';
                 }
                 $filters[$basePath]['text-match'] = array('collation' => $collation == 'default' ? 'i;ascii-casemap' : $collation, 'negate-condition' => $child->getAttribute('negate-condition') === 'yes', 'value' => $child->nodeValue);
                 break;
         }
     }
     return $filters;
 }
 /**
  * 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));
     }
 }
 /**
  * Unserializes the DOMElement back into a Property class.
  *
  * @param DOMElement $node
  * @return Sabre_CalDAV_Property_ScheduleCalendarTransp
  */
 static function unserialize(DOMElement $node)
 {
     $value = null;
     foreach ($node->childNodes as $childNode) {
         switch (Sabre_DAV_XMLUtil::toClarkNotation($childNode)) {
             case '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}opaque':
                 $value = self::OPAQUE;
                 break;
             case '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}transparent':
                 $value = self::TRANSPARENT;
                 break;
         }
     }
     if (is_null($value)) {
         return null;
     }
     return new self($value);
 }
Пример #10
0
 /**
  * Unserializes this property from a DOM Element 
  *
  * This method returns an instance of this class.
  * It will only decode {DAV:}href values. For non-compatible elements null will be returned.
  *
  * @param DOMElement $dom 
  * @return Sabre_DAV_Property_Href 
  */
 static function unserialize(DOMElement $dom)
 {
     if (Sabre_DAV_XMLUtil::toClarkNotation($dom->firstChild) === '{DAV:}href') {
         return new self($dom->firstChild->textContent, false);
     }
 }
Пример #11
0
 /**
  * Unserializes a DOM element into a ResourceType property.
  *
  * @param DOMElement $dom
  * @return Sabre_DAV_Property_ResourceType
  */
 public static function unserialize(DOMElement $dom)
 {
     $value = array();
     foreach ($dom->childNodes as $child) {
         $value[] = Sabre_DAV_XMLUtil::toClarkNotation($child);
     }
     return new self($value);
 }
Пример #12
0
 /**
  * This method is responsible for parsing the request and generating the
  * response for the CALDAV:free-busy-query REPORT.
  *
  * @param DOMNode $dom
  * @return void
  */
 protected function freeBusyQueryReport(DOMNode $dom)
 {
     $start = null;
     $end = null;
     foreach ($dom->firstChild->childNodes as $childNode) {
         $clark = Sabre_DAV_XMLUtil::toClarkNotation($childNode);
         if ($clark == '{' . self::NS_CALDAV . '}time-range') {
             $start = $childNode->getAttribute('start');
             $end = $childNode->getAttribute('end');
             break;
         }
     }
     if ($start) {
         $start = Sabre_VObject_DateTimeParser::parseDateTime($start);
     }
     if ($end) {
         $end = Sabre_VObject_DateTimeParser::parseDateTime($end);
     }
     if (!$start && !$end) {
         throw new Sabre_DAV_Exception_BadRequest('The freebusy report must have a time-range filter');
     }
     $acl = $this->server->getPlugin('acl');
     if (!$acl) {
         throw new Sabre_DAV_Exception('The ACL plugin must be loaded for free-busy queries to work');
     }
     $uri = $this->server->getRequestUri();
     $acl->checkPrivileges($uri, '{' . self::NS_CALDAV . '}read-free-busy');
     $calendar = $this->server->tree->getNodeForPath($uri);
     if (!$calendar instanceof Sabre_CalDAV_ICalendar) {
         throw new Sabre_DAV_Exception_NotImplemented('The free-busy-query REPORT is only implemented on calendars');
     }
     $objects = array_map(function ($child) {
         $obj = $child->get();
         if (is_resource($obj)) {
             $obj = stream_get_contents($obj);
         }
         return $obj;
     }, $calendar->getChildren());
     $generator = new Sabre_VObject_FreeBusyGenerator();
     $generator->setObjects($objects);
     $generator->setTimeRange($start, $end);
     $result = $generator->getResult();
     $result = $result->serialize();
     $this->server->httpResponse->sendStatus(200);
     $this->server->httpResponse->setHeader('Content-Type', 'text/calendar');
     $this->server->httpResponse->setHeader('Content-Length', strlen($result));
     $this->server->httpResponse->sendBody($result);
 }
Пример #13
0
    /**
     * @expectedException Sabre_DAV_Exception_BadRequest
     */
    function testUnserializeUnknown()
    {
        $xml = '<?xml version="1.0"?>
<d:principal xmlns:d="DAV:">' . '  <d:foo />' . '</d:principal>';
        $dom = Sabre_DAV_XMLUtil::loadDOMDocument($xml);
        Sabre_DAVACL_Property_Principal::unserialize($dom->firstChild);
    }
Пример #14
0
    /**
     * @depends testParamFilter
     */
    function testUndefinedNegation()
    {
        $xml = <<<XML
<?xml version="1.0"?>
<C:filter xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav">
  <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>
XML;
        $dom = Sabre_DAV_XMLUtil::loadDOMDocument($xml);
        $expected = array('/c:iCalendar/c:vcalendar' => array(), '/c:iCalendar/c:vcalendar/c:vtodo' => array(), '/c:iCalendar/c:vcalendar/c:vtodo/c:completed' => array('is-not-defined' => true), '/c:iCalendar/c:vcalendar/c:vtodo/c:status' => array('text-match' => array('collation' => 'i;ascii-casemap', 'negate-condition' => true, 'value' => 'CANCELLED')));
        $result = Sabre_CalDAV_XMLUtil::parseCalendarQueryFilters($dom->firstChild);
        $this->assertEquals($expected, $result);
    }
Пример #15
0
 /**
  * Parses a webdav lock xml body, and returns a new Sabre_DAV_Locks_LockInfo object
  *
  * @param string $body
  * @return Sabre_DAV_Locks_LockInfo
  */
 protected function parseLockRequest($body)
 {
     $xml = simplexml_load_string(Sabre_DAV_XMLUtil::convertDAVNamespace($body), null, LIBXML_NOWARNING);
     $xml->registerXPathNamespace('d', 'urn:DAV');
     $lockInfo = new Sabre_DAV_Locks_LockInfo();
     $children = $xml->children("urn:DAV");
     $lockInfo->owner = (string) $children->owner;
     $lockInfo->token = Sabre_DAV_UUIDUtil::getUUID();
     $lockInfo->scope = count($xml->xpath('d:lockscope/d:exclusive')) > 0 ? Sabre_DAV_Locks_LockInfo::EXCLUSIVE : Sabre_DAV_Locks_LockInfo::SHARED;
     return $lockInfo;
 }
Пример #16
0
 /**
  * @depends testSupportedReportSetProperty
  * @depends testCalendarMultiGetReport
  */
 function testCalendarQueryReport1ObjectNoCalData()
 {
     $body = '<?xml version="1.0"?>' . '<c:calendar-query xmlns:c="urn:ietf:params:xml:ns:caldav" xmlns:d="DAV:">' . '<d:prop>' . '  <d:getetag />' . '</d:prop>' . '<c:filter>' . '  <c:comp-filter name="VCALENDAR">' . '    <c:comp-filter name="VEVENT" />' . '  </c:comp-filter>' . '</c:filter>' . '</c:calendar-query>';
     $request = new Sabre_HTTP_Request(array('REQUEST_METHOD' => 'REPORT', 'REQUEST_URI' => '/calendars/user1/UUID-123467/UUID-2345', 'HTTP_DEPTH' => '0'));
     $request->setBody($body);
     $this->server->httpRequest = $request;
     $this->server->exec();
     $this->assertEquals('HTTP/1.1 207 Multi-Status', $this->response->status, 'Received an unexpected status. Full response body: ' . $this->response->body);
     $xml = simplexml_load_string(Sabre_DAV_XMLUtil::convertDAVNamespace($this->response->body));
     $xml->registerXPathNamespace('d', 'urn:DAV');
     $xml->registerXPathNamespace('c', 'urn:ietf:params:xml:ns:caldav');
     $check = array('/d:multistatus', '/d:multistatus/d:response', '/d:multistatus/d:response/d:href', '/d:multistatus/d:response/d:propstat', '/d:multistatus/d:response/d:propstat/d:prop', '/d:multistatus/d:response/d:propstat/d:prop/d:getetag', '/d:multistatus/d:response/d:propstat/d:status' => 'HTTP/1.1 200 OK');
     foreach ($check as $v1 => $v2) {
         $xpath = is_int($v1) ? $v2 : $v1;
         $result = $xml->xpath($xpath);
         $this->assertEquals(1, count($result), 'We expected 1 ' . $xpath . ' elements. We\'ve found ' . count($result) . '. Full result: ' . $this->response->body);
         if (!is_int($v1)) {
             $this->assertEquals($v2, (string) $result[0]);
         }
     }
 }
Пример #17
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);
 }
Пример #18
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));
 }
 /**
  * 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;
 }
Пример #20
0
 /**
  * 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));
 }
Пример #21
0
 /**
  * @expectedException InvalidArgumentException
  */
 function testParseClarkNotationFail()
 {
     Sabre_DAV_XMLUtil::parseClarkNotation('}foo');
 }
Пример #22
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);
    }
Пример #23
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));
 }
 /**
  * Unserializes the {DAV:}acl xml element. 
  * 
  * @param DOMElement $dom 
  * @return Sabre_DAVACL_Property_Acl 
  */
 public static function unserialize(DOMElement $dom)
 {
     $privileges = array();
     $xaces = $dom->getElementsByTagNameNS('urn:DAV', 'ace');
     for ($ii = 0; $ii < $xaces->length; $ii++) {
         $xace = $xaces->item($ii);
         $principal = $xace->getElementsByTagNameNS('urn:DAV', 'principal');
         if ($principal->length !== 1) {
             throw new Sabre_DAV_Exception_BadRequest('Each {DAV:}ace element must have one {DAV:}principal element');
         }
         $principal = Sabre_DAVACL_Property_Principal::unserialize($principal->item(0));
         if ($principal->getType() !== Sabre_DAVACL_Property_Principal::HREF) {
             throw new Sabre_DAV_Exception_NotImplemented('Currently only uri based principals are support, {DAV:}all, {DAV:}unauthenticated and {DAV:}authenticated are not implemented yet');
         }
         $principal = $principal->getHref();
         $protected = false;
         if ($xace->getElementsByTagNameNS('urn:DAV', 'protected')->length > 0) {
             $protected = true;
         }
         $grants = $xace->getElementsByTagNameNS('urn:DAV', 'grant');
         if ($grants->length < 1) {
             throw new Sabre_DAV_Exception_NotImplemented('Every {DAV:}ace element must have a {DAV:}grant element. {DAV:}deny is not yet supported');
         }
         $grant = $grants->item(0);
         $xprivs = $grant->getElementsByTagNameNS('urn:DAV', 'privilege');
         for ($jj = 0; $jj < $xprivs->length; $jj++) {
             $xpriv = $xprivs->item($jj);
             $privilegeName = null;
             for ($kk = 0; $kk < $xpriv->childNodes->length; $kk++) {
                 $childNode = $xpriv->childNodes->item($kk);
                 if ($t = Sabre_DAV_XMLUtil::toClarkNotation($childNode)) {
                     $privilegeName = $t;
                     break;
                 }
             }
             if (is_null($privilegeName)) {
                 throw new Sabre_DAV_Exception_BadRequest('{DAV:}privilege elements must have a privilege element contained within them.');
             }
             $privileges[] = array('principal' => $principal, 'protected' => $protected, 'privilege' => $privilegeName);
         }
     }
     return new self($privileges);
 }
Пример #25
0
 /**
  * Parses all WebDAV properties out of a DOM Element
  *
  * Generally WebDAV properties are enclosed in {DAV:}prop elements. This
  * method helps by going through all these and pulling out the actual
  * propertynames, making them array keys and making the property values,
  * well.. the array values.
  *
  * If no value was given (self-closing element) null will be used as the
  * value. This is used in for example PROPFIND requests.
  *
  * Complex values are supported through the propertyMap argument. The
  * propertyMap should have the clark-notation properties as it's keys, and
  * classnames as values.
  *
  * When any of these properties are found, the unserialize() method will be
  * (statically) called. The result of this method is used as the value.
  *
  * @param DOMElement $parentNode
  * @param array $propertyMap
  * @return array
  */
 static function parseProperties(DOMElement $parentNode, array $propertyMap = array())
 {
     $propList = array();
     foreach ($parentNode->childNodes as $propNode) {
         if (Sabre_DAV_XMLUtil::toClarkNotation($propNode) !== '{DAV:}prop') {
             continue;
         }
         foreach ($propNode->childNodes as $propNodeData) {
             /* If there are no elements in here, we actually get 1 text node, this special case is dedicated to netdrive */
             if ($propNodeData->nodeType != XML_ELEMENT_NODE) {
                 continue;
             }
             $propertyName = Sabre_DAV_XMLUtil::toClarkNotation($propNodeData);
             if (isset($propertyMap[$propertyName])) {
                 $propList[$propertyName] = call_user_func(array($propertyMap[$propertyName], 'unserialize'), $propNodeData);
             } else {
                 $propList[$propertyName] = $propNodeData->textContent;
             }
         }
     }
     return $propList;
 }
Пример #26
0
    /**
     * @expectedException Sabre_DAV_Exception_BadRequest
     */
    function testUnserializeMissingPriv()
    {
        $source = '<?xml version="1.0"?>
<d:root xmlns:d="DAV:">
  <d:ace>
    <d:grant>
      <d:privilege />
    </d:grant>
    <d:principal><d:href>/principals/evert</d:href></d:principal>
  </d:ace>
</d:root>
';
        $dom = Sabre_DAV_XMLUtil::loadDOMDocument($source);
        Sabre_DAVACL_Property_Acl::unserialize($dom->firstChild);
    }
Пример #27
0
 /**
  * This event is triggered when the server didn't know how to handle a
  * certain request.
  *
  * We intercept this to handle POST requests on calendars.
  *
  * @param string $method
  * @param string $uri
  * @return null|bool
  */
 public function unknownMethod($method, $uri)
 {
     if ($method !== 'POST') {
         return;
     }
     // Only handling xml
     $contentType = $this->server->httpRequest->getHeader('Content-Type');
     if (strpos($contentType, 'application/xml') === false && strpos($contentType, 'text/xml') === false) {
         return;
     }
     // Making sure the node exists
     try {
         $node = $this->server->tree->getNodeForPath($uri);
     } catch (Sabre_DAV_Exception_NotFound $e) {
         return;
     }
     $requestBody = $this->server->httpRequest->getBody(true);
     // If this request handler could not deal with this POST request, it
     // will return 'null' and other plugins get a chance to handle the
     // request.
     //
     // However, we already requested the full body. This is a problem,
     // because a body can only be read once. This is why we preemptively
     // re-populated the request body with the existing data.
     $this->server->httpRequest->setBody($requestBody);
     $dom = Sabre_DAV_XMLUtil::loadDOMDocument($requestBody);
     $documentType = Sabre_DAV_XMLUtil::toClarkNotation($dom->firstChild);
     switch ($documentType) {
         // Dealing with the 'share' document, which modified invitees on a
         // calendar.
         case '{' . Sabre_CalDAV_Plugin::NS_CALENDARSERVER . '}share':
             // We can only deal with IShareableCalendar objects
             if (!$node instanceof Sabre_CalDAV_IShareableCalendar) {
                 return;
             }
             // Getting ACL info
             $acl = $this->server->getPlugin('acl');
             // If there's no ACL support, we allow everything
             if ($acl) {
                 $acl->checkPrivileges($uri, '{DAV:}write');
             }
             $mutations = $this->parseShareRequest($dom);
             $node->updateShares($mutations[0], $mutations[1]);
             $this->server->httpResponse->sendStatus(200);
             // Adding this because sending a response body may cause issues,
             // and I wanted some type of indicator the response was handled.
             $this->server->httpResponse->setHeader('X-Sabre-Status', 'everything-went-well');
             // Breaking the event chain
             return false;
             // The invite-reply document is sent when the user replies to an
             // invitation of a calendar share.
         // The invite-reply document is sent when the user replies to an
         // invitation of a calendar share.
         case '{' . Sabre_CalDAV_Plugin::NS_CALENDARSERVER . '}invite-reply':
             // This only works on the calendar-home-root node.
             if (!$node instanceof Sabre_CalDAV_UserCalendars) {
                 return;
             }
             // Getting ACL info
             $acl = $this->server->getPlugin('acl');
             // If there's no ACL support, we allow everything
             if ($acl) {
                 $acl->checkPrivileges($uri, '{DAV:}write');
             }
             $message = $this->parseInviteReplyRequest($dom);
             $url = $node->shareReply($message['href'], $message['status'], $message['calendarUri'], $message['inReplyTo'], $message['summary']);
             $this->server->httpResponse->sendStatus(200);
             // Adding this because sending a response body may cause issues,
             // and I wanted some type of indicator the response was handled.
             $this->server->httpResponse->setHeader('X-Sabre-Status', 'everything-went-well');
             if ($url) {
                 $dom = new DOMDocument('1.0', 'UTF-8');
                 $dom->formatOutput = true;
                 $root = $dom->createElement('cs:shared-as');
                 foreach ($this->server->xmlNamespaces as $namespace => $prefix) {
                     $root->setAttribute('xmlns:' . $prefix, $namespace);
                 }
                 $dom->appendChild($root);
                 $href = new Sabre_DAV_Property_Href($url);
                 $href->serialize($this->server, $root);
                 $this->server->httpResponse->setHeader('Content-Type', 'application/xml');
                 $this->server->httpResponse->sendBody($dom->saveXML());
             }
             // Breaking the event chain
             return false;
         case '{' . Sabre_CalDAV_Plugin::NS_CALENDARSERVER . '}publish-calendar':
             // We can only deal with IShareableCalendar objects
             if (!$node instanceof Sabre_CalDAV_IShareableCalendar) {
                 return;
             }
             // Getting ACL info
             $acl = $this->server->getPlugin('acl');
             // If there's no ACL support, we allow everything
             if ($acl) {
                 $acl->checkPrivileges($uri, '{DAV:}write');
             }
             $node->setPublishStatus(true);
             // iCloud sends back the 202, so we will too.
             $this->server->httpResponse->sendStatus(202);
             // Adding this because sending a response body may cause issues,
             // and I wanted some type of indicator the response was handled.
             $this->server->httpResponse->setHeader('X-Sabre-Status', 'everything-went-well');
             // Breaking the event chain
             return false;
         case '{' . Sabre_CalDAV_Plugin::NS_CALENDARSERVER . '}unpublish-calendar':
             // We can only deal with IShareableCalendar objects
             if (!$node instanceof Sabre_CalDAV_IShareableCalendar) {
                 return;
             }
             // Getting ACL info
             $acl = $this->server->getPlugin('acl');
             // If there's no ACL support, we allow everything
             if ($acl) {
                 $acl->checkPrivileges($uri, '{DAV:}write');
             }
             $node->setPublishStatus(false);
             $this->server->httpResponse->sendStatus(200);
             // Adding this because sending a response body may cause issues,
             // and I wanted some type of indicator the response was handled.
             $this->server->httpResponse->setHeader('X-Sabre-Status', 'everything-went-well');
             // Breaking the event chain
             return false;
     }
 }
Пример #28
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;
 }
Пример #29
0
    /**
     * @expectedException Sabre_DAV_Exception
     */
    function testUnserializeNoStatus()
    {
        $xml = '<?xml version="1.0"?>
<d:root xmlns:d="DAV:" xmlns:cal="' . Sabre_CalDAV_Plugin::NS_CALDAV . '" xmlns:cs="' . Sabre_CalDAV_Plugin::NS_CALENDARSERVER . '">
  <cs:user>
    <d:href>mailto:user1@example.org</d:href>
    <!-- <cs:invite-accepted/> -->
    <cs:access>
      <cs:read-write/>
    </cs:access>
  </cs:user>
</d:root>';
        $doc2 = Sabre_DAV_XMLUtil::loadDOMDocument($xml);
        $outputProperty = Sabre_CalDAV_Property_Invite::unserialize($doc2->firstChild);
    }
 /**
  * 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;
 }