Ejemplo n.º 1
0
 /**
  * This function handles the addressbook-query REPORT
  *
  * This report is used by the client to filter an addressbook based on a
  * complex query.
  *
  * @param \DOMNode $dom
  * @return void
  */
 protected function addressbookQueryReport($dom)
 {
     $query = new AddressBookQueryParser($dom);
     $query->parse();
     $depth = $this->server->getHTTPDepth(0);
     if ($depth == 0) {
         $candidateNodes = [$this->server->tree->getNodeForPath($this->server->getRequestUri())];
         if (!$candidateNodes[0] instanceof ICard) {
             throw new ReportNotSupported('The addressbook-query report is not supported on this url with Depth: 0');
         }
     } else {
         $candidateNodes = $this->server->tree->getChildren($this->server->getRequestUri());
     }
     $xpath = new \DOMXPath($dom);
     $xpath->registerNameSpace('card', Plugin::NS_CARDDAV);
     $xpath->registerNameSpace('dav', 'urn:DAV');
     $contentType = $xpath->evaluate("string(/card:addressbook-query/dav:prop/card:address-data/@content-type)");
     $version = $xpath->evaluate("string(/card:addressbook-query/dav:prop/card:address-data/@version)");
     if ($version) {
         $contentType .= '; version=' . $version;
     }
     $vcardType = $this->negotiateVCard($contentType);
     $validNodes = [];
     foreach ($candidateNodes as $node) {
         if (!$node instanceof ICard) {
             continue;
         }
         $blob = $node->get();
         if (is_resource($blob)) {
             $blob = stream_get_contents($blob);
         }
         if (!$this->validateFilters($blob, $query->filters, $query->test)) {
             continue;
         }
         $validNodes[] = $node;
         if ($query->limit && $query->limit <= count($validNodes)) {
             // We hit the maximum number of items, we can stop now.
             break;
         }
     }
     $result = [];
     foreach ($validNodes as $validNode) {
         if ($depth == 0) {
             $href = $this->server->getRequestUri();
         } else {
             $href = $this->server->getRequestUri() . '/' . $validNode->getName();
         }
         list($props) = $this->server->getPropertiesForPath($href, $query->requestedProperties, 0);
         if (isset($props[200]['{' . self::NS_CARDDAV . '}address-data'])) {
             $props[200]['{' . self::NS_CARDDAV . '}address-data'] = $this->convertVCard($props[200]['{' . self::NS_CARDDAV . '}address-data'], $vcardType);
         }
         $result[] = $props;
     }
     $prefer = $this->server->getHTTPPRefer();
     $this->server->httpResponse->setStatus(207);
     $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8');
     $this->server->httpResponse->setHeader('Vary', 'Brief,Prefer');
     $this->server->httpResponse->setBody($this->server->generateMultiStatus($result, $prefer['return-minimal']));
 }
Ejemplo n.º 2
0
 /**
  * The expand-property report is defined in RFC3253 section 3-8.
  *
  * This report is very similar to a standard PROPFIND. The difference is
  * that it has the additional ability to look at properties containing a
  * {DAV:}href element, follow that property and grab additional elements
  * there.
  *
  * Other rfc's, such as ACL rely on this report, so it made sense to put
  * it in this plugin.
  *
  * @param Xml\Request\ExpandPropertyReport $report
  * @return void
  */
 protected function expandPropertyReport($report)
 {
     $depth = $this->server->getHTTPDepth(0);
     $requestUri = $this->server->getRequestUri();
     $result = $this->expandProperties($requestUri, $report->properties, $depth);
     $xml = $this->server->xml->write('{DAV:}multistatus', new DAV\Xml\Response\MultiStatus($result), $this->server->getBaseUri());
     $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8');
     $this->server->httpResponse->setStatus(207);
     $this->server->httpResponse->setBody($xml);
 }
 /**
  * This function handles the calendar-multiget REPORT.
  *
  * prefetch events into calendar container class, to avoid single lookup of events
  *
  * @param \DOMNode $dom
  * @return void
  */
 public function calendarMultiGetReport($dom)
 {
     $properties = array_keys(\Sabre\DAV\XMLUtil::parseProperties($dom->firstChild));
     $hrefElems = $dom->getElementsByTagNameNS('urn:DAV', 'href');
     $filters = array('name' => 'VCALENDAR', 'comp-filters' => array(array('name' => 'VEVENT', 'prop-filters' => array())));
     foreach ($hrefElems as $elem) {
         list($dirName, $baseName) = \Sabre\DAV\URLUtil::splitPath($elem->nodeValue);
         $filters['comp-filters'][0]['prop-filters'][] = array('name' => 'UID', 'text-match' => array('value' => $baseName));
     }
     $node = $this->server->tree->getNodeForPath($this->server->getRequestUri());
     $node->calendarQuery($filters);
 }
Ejemplo n.º 4
0
 /**
  * principalPropertySearchReport
  *
  * This method is responsible for handing the
  * {DAV:}principal-property-search report. This report can be used for
  * clients to search for groups of principals, based on the value of one
  * or more properties.
  *
  * @param \DOMDocument $dom
  * @return void
  */
 protected function principalPropertySearchReport(\DOMDocument $dom)
 {
     list($searchProperties, $requestedProperties, $applyToPrincipalCollectionSet, $test) = $this->parsePrincipalPropertySearchReportRequest($dom);
     $uri = null;
     if (!$applyToPrincipalCollectionSet) {
         $uri = $this->server->getRequestUri();
     }
     $result = $this->principalSearch($searchProperties, $requestedProperties, $uri, $test);
     $prefer = $this->server->getHTTPPRefer();
     $this->server->httpResponse->setStatus(207);
     $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8');
     $this->server->httpResponse->setHeader('Vary', 'Brief,Prefer');
     $this->server->httpResponse->setBody($this->server->generateMultiStatus($result, $prefer['return-minimal']));
 }
Ejemplo n.º 5
0
 public function checkPreconditions($handleAsGET = false)
 {
     // chunked upload handling
     if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
         $filePath = parent::getRequestUri();
         list($path, $name) = \Sabre\DAV\URLUtil::splitPath($filePath);
         $info = OC_FileChunking::decodeName($name);
         if (!empty($info)) {
             $filePath = $path . '/' . $info['name'];
             $this->overLoadedUri = $filePath;
         }
     }
     $result = parent::checkPreconditions($handleAsGET);
     $this->overLoadedUri = null;
     return $result;
 }
Ejemplo n.º 6
0
 /**
  * This function handles the addressbook-query REPORT
  *
  * This report is used by the client to filter an addressbook based on a
  * complex query.
  *
  * @param \DOMNode $dom
  * @return void
  */
 protected function addressbookQueryReport($dom)
 {
     $query = new AddressBookQueryParser($dom);
     $query->parse();
     $depth = $this->server->getHTTPDepth(0);
     if ($depth == 0) {
         $candidateNodes = array($this->server->tree->getNodeForPath($this->server->getRequestUri()));
     } else {
         $candidateNodes = $this->server->tree->getChildren($this->server->getRequestUri());
     }
     $validNodes = array();
     foreach ($candidateNodes as $node) {
         if (!$node instanceof ICard) {
             continue;
         }
         $blob = $node->get();
         if (is_resource($blob)) {
             $blob = stream_get_contents($blob);
         }
         if (!$this->validateFilters($blob, $query->filters, $query->test)) {
             continue;
         }
         $validNodes[] = $node;
         if ($query->limit && $query->limit <= count($validNodes)) {
             // We hit the maximum number of items, we can stop now.
             break;
         }
     }
     $result = array();
     foreach ($validNodes as $validNode) {
         if ($depth == 0) {
             $href = $this->server->getRequestUri();
         } else {
             $href = $this->server->getRequestUri() . '/' . $validNode->getName();
         }
         list($result[]) = $this->server->getPropertiesForPath($href, $query->requestedProperties, 0);
     }
     $prefer = $this->server->getHTTPPRefer();
     $this->server->httpResponse->sendStatus(207);
     $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8');
     $this->server->httpResponse->setHeader('Vary', 'Brief,Prefer');
     $this->server->httpResponse->sendBody($this->server->generateMultiStatus($result, $prefer['return-minimal']));
 }
Ejemplo n.º 7
0
 /**
  * validateLock should be called when a write operation is about to happen
  * It will check if the requested url is locked, and see if the correct lock tokens are passed
  *
  * @param mixed $urls List of relevant urls. Can be an array, a string or nothing at all for the current request uri
  * @param mixed $lastLock This variable will be populated with the last checked lock object (Sabre\DAV\Locks\LockInfo)
  * @param bool $checkChildLocks If set to true, this function will also look for any locks set on child resources of the supplied urls. This is needed for for example deletion of entire trees.
  * @return bool
  */
 protected function validateLock($urls = null, &$lastLock = null, $checkChildLocks = false)
 {
     if (is_null($urls)) {
         $urls = array($this->server->getRequestUri());
     } elseif (is_string($urls)) {
         $urls = array($urls);
     } elseif (!is_array($urls)) {
         throw new DAV\Exception('The urls parameter should either be null, a string or an array');
     }
     $conditions = $this->getIfConditions();
     // We're going to loop through the urls and make sure all lock conditions are satisfied
     foreach ($urls as $url) {
         $locks = $this->getLocks($url, $checkChildLocks);
         // If there were no conditions, but there were locks, we fail
         if (!$conditions && $locks) {
             reset($locks);
             $lastLock = current($locks);
             return false;
         }
         // If there were no locks or conditions, we go to the next url
         if (!$locks && !$conditions) {
             continue;
         }
         foreach ($conditions as $condition) {
             if (!$condition['uri']) {
                 $conditionUri = $this->server->getRequestUri();
             } else {
                 $conditionUri = $this->server->calculateUri($condition['uri']);
             }
             // If the condition has a url, and it isn't part of the affected url at all, check the next condition
             if ($conditionUri && strpos($url, $conditionUri) !== 0) {
                 continue;
             }
             // The tokens array contians arrays with 2 elements. 0=true/false for normal/not condition, 1=locktoken
             // At least 1 condition has to be satisfied
             foreach ($condition['tokens'] as $conditionToken) {
                 $etagValid = true;
                 $lockValid = true;
                 // key 2 can contain an etag
                 if ($conditionToken[2]) {
                     $uri = $conditionUri ? $conditionUri : $this->server->getRequestUri();
                     $node = $this->server->tree->getNodeForPath($uri);
                     $etagValid = $node->getETag() == $conditionToken[2];
                 }
                 // key 1 can contain a lock token
                 if ($conditionToken[1]) {
                     $lockValid = false;
                     // Match all the locks
                     foreach ($locks as $lockIndex => $lock) {
                         $lockToken = 'opaquelocktoken:' . $lock->token;
                         // Checking NOT
                         if (!$conditionToken[0] && $lockToken != $conditionToken[1]) {
                             // Condition valid, onto the next
                             $lockValid = true;
                             break;
                         }
                         if ($conditionToken[0] && $lockToken == $conditionToken[1]) {
                             $lastLock = $lock;
                             // Condition valid and lock matched
                             unset($locks[$lockIndex]);
                             $lockValid = true;
                             break;
                         }
                     }
                 }
                 // If, after checking both etags and locks they are stil valid,
                 // we can continue with the next condition.
                 if ($etagValid && $lockValid) {
                     continue 2;
                 }
             }
             // No conditions matched, so we fail
             throw new DAV\Exception\PreconditionFailed('The tokens provided in the if header did not match', 'If');
         }
         // Conditions were met, we'll also need to check if all the locks are gone
         if (count($locks)) {
             reset($locks);
             // There's still locks, we fail
             $lastLock = current($locks);
             return false;
         }
     }
     // We got here, this means every condition was satisfied
     return true;
 }