/**
  * Parses the 'invite-reply' POST request.
  *
  * This method returns an array, containing the following properties:
  *   * href - The sharee who is replying
  *   * status - One of the self::STATUS_* constants
  *   * calendarUri - The url of the shared calendar
  *   * inReplyTo - The unique id of the share invitation.
  *   * summary - Optional description of the reply.
  *
  * @param \DOMDocument $dom
  * @return array
  */
 protected function parseInviteReplyRequest(\DOMDocument $dom)
 {
     $xpath = new \DOMXPath($dom);
     $xpath->registerNamespace('cs', Plugin::NS_CALENDARSERVER);
     $xpath->registerNamespace('d', 'urn:DAV');
     $hostHref = $xpath->evaluate('string(cs:hosturl/d:href)');
     if (!$hostHref) {
         throw new DAV\Exception\BadRequest('The {' . Plugin::NS_CALENDARSERVER . '}hosturl/{DAV:}href element is required');
     }
     return array('href' => $xpath->evaluate('string(d:href)'), 'calendarUri' => $this->server->calculateUri($hostHref), 'inReplyTo' => $xpath->evaluate('string(cs:in-reply-to)'), 'summary' => $xpath->evaluate('string(cs:summary)'), 'status' => $xpath->evaluate('boolean(cs:invite-accepted)') ? self::STATUS_ACCEPTED : self::STATUS_DECLINED);
 }
Exemple #2
0
 /**
  * This method is responsible for handling the 'ACL' event.
  *
  * @param string $uri
  * @return void
  */
 public function httpACL($uri)
 {
     $body = $this->server->httpRequest->getBody(true);
     $dom = DAV\XMLUtil::loadDOMDocument($body);
     $newAcl = Property\Acl::unserialize($dom->firstChild)->getPrivileges();
     // Normalizing urls
     foreach ($newAcl as $k => $newAce) {
         $newAcl[$k]['principal'] = $this->server->calculateUri($newAce['principal']);
     }
     $node = $this->server->tree->getNodeForPath($uri);
     if (!$node instanceof IACL) {
         throw new DAV\Exception\MethodNotAllowed('This node does not support the ACL method');
     }
     $oldAcl = $this->getACL($node);
     $supportedPrivileges = $this->getFlatPrivilegeSet($node);
     /* Checking if protected principals from the existing principal set are
        not overwritten. */
     foreach ($oldAcl as $oldAce) {
         if (!isset($oldAce['protected']) || !$oldAce['protected']) {
             continue;
         }
         $found = false;
         foreach ($newAcl as $newAce) {
             if ($newAce['privilege'] === $oldAce['privilege'] && $newAce['principal'] === $oldAce['principal'] && $newAce['protected']) {
                 $found = true;
             }
         }
         if (!$found) {
             throw new Exception\AceConflict('This resource contained a protected {DAV:}ace, but this privilege did not occur in the ACL request');
         }
     }
     foreach ($newAcl as $newAce) {
         // Do we recognize the privilege
         if (!isset($supportedPrivileges[$newAce['privilege']])) {
             throw new Exception\NotSupportedPrivilege('The privilege you specified (' . $newAce['privilege'] . ') is not recognized by this server');
         }
         if ($supportedPrivileges[$newAce['privilege']]['abstract']) {
             throw new Exception\NoAbstract('The privilege you specified (' . $newAce['privilege'] . ') is an abstract privilege');
         }
         // Looking up the principal
         try {
             $principal = $this->server->tree->getNodeForPath($newAce['principal']);
         } catch (DAV\Exception\NotFound $e) {
             throw new Exception\NotRecognizedPrincipal('The specified principal (' . $newAce['principal'] . ') does not exist');
         }
         if (!$principal instanceof IPrincipal) {
             throw new Exception\NotRecognizedPrincipal('The specified uri (' . $newAce['principal'] . ') is not a principal');
         }
     }
     $node->setACL($newAcl);
 }
Exemple #3
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(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);
     }
     $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($propertyList, $prefer['return-minimal']));
 }
 /**
  * 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 (SabreForRainLoop\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;
 }