/** * serialize * * @param DAV\Server $server * @param \DOMElement $prop * @return void */ public function serialize(DAV\Server $server, \DOMElement $prop) { $doc = $prop->ownerDocument; foreach ($this->locks as $lock) { $activeLock = $doc->createElementNS('DAV:', 'd:activelock'); $prop->appendChild($activeLock); $lockScope = $doc->createElementNS('DAV:', 'd:lockscope'); $activeLock->appendChild($lockScope); $lockScope->appendChild($doc->createElementNS('DAV:', 'd:' . ($lock->scope == DAV\Locks\LockInfo::EXCLUSIVE ? 'exclusive' : 'shared'))); $lockType = $doc->createElementNS('DAV:', 'd:locktype'); $activeLock->appendChild($lockType); $lockType->appendChild($doc->createElementNS('DAV:', 'd:write')); /* {DAV:}lockroot */ if (!self::$hideLockRoot) { $lockRoot = $doc->createElementNS('DAV:', 'd:lockroot'); $activeLock->appendChild($lockRoot); $href = $doc->createElementNS('DAV:', 'd:href'); $href->appendChild($doc->createTextNode($server->getBaseUri() . $lock->uri)); $lockRoot->appendChild($href); } $activeLock->appendChild($doc->createElementNS('DAV:', 'd:depth', $lock->depth == DAV\Server::DEPTH_INFINITY ? 'infinity' : $lock->depth)); $activeLock->appendChild($doc->createElementNS('DAV:', 'd:timeout', 'Second-' . $lock->timeout)); if ($this->revealLockToken) { $lockToken = $doc->createElementNS('DAV:', 'd:locktoken'); $activeLock->appendChild($lockToken); $lockToken->appendChild($doc->createElementNS('DAV:', 'd:href', 'opaquelocktoken:' . $lock->token)); } $activeLock->appendChild($doc->createElementNS('DAV:', 'd:owner', $lock->owner)); } }
/** * Initializes the plugin * * This method is automatically called by the Server class after addPlugin. * * @param DAV\Server $server * @return void */ public function initialize(DAV\Server $server) { $this->server = $server; $server->subscribeEvent('unknownMethod', array($this, 'unknownMethod')); $server->subscribeEvent('beforeMethod', array($this, 'beforeMethod'), 50); $server->subscribeEvent('afterGetProperties', array($this, 'afterGetProperties')); }
/** * serialize * * @param DAV\Server $server * @param \DOMElement $dom * @return void */ public function serialize(DAV\Server $server, \DOMElement $dom) { $document = $dom->ownerDocument; $properties = $this->responseProperties; $xresponse = $document->createElement('d:response'); $dom->appendChild($xresponse); $uri = DAV\URLUtil::encodePath($this->href); // Adding the baseurl to the beginning of the url $uri = $server->getBaseUri() . $uri; $xresponse->appendChild($document->createElement('d:href', $uri)); // The properties variable is an array containing properties, grouped by // HTTP status foreach ($properties as $httpStatus => $propertyGroup) { // The 'href' is also in this array, and it's special cased. // We will ignore it if ($httpStatus == 'href') { continue; } // If there are no properties in this group, we can also just carry on if (!count($propertyGroup)) { continue; } $xpropstat = $document->createElement('d:propstat'); $xresponse->appendChild($xpropstat); $xprop = $document->createElement('d:prop'); $xpropstat->appendChild($xprop); $nsList = $server->xmlNamespaces; foreach ($propertyGroup as $propertyName => $propertyValue) { $propName = null; preg_match('/^{([^}]*)}(.*)$/', $propertyName, $propName); // special case for empty namespaces if ($propName[1] == '') { $currentProperty = $document->createElement($propName[2]); $xprop->appendChild($currentProperty); $currentProperty->setAttribute('xmlns', ''); } else { if (!isset($nsList[$propName[1]])) { $nsList[$propName[1]] = 'x' . count($nsList); } // If the namespace was defined in the top-level xml namespaces, it means // there was already a namespace declaration, and we don't have to worry about it. if (isset($server->xmlNamespaces[$propName[1]])) { $currentProperty = $document->createElement($nsList[$propName[1]] . ':' . $propName[2]); } else { $currentProperty = $document->createElementNS($propName[1], $nsList[$propName[1]] . ':' . $propName[2]); } $xprop->appendChild($currentProperty); } if (is_scalar($propertyValue)) { $text = $document->createTextNode($propertyValue); $currentProperty->appendChild($text); } elseif ($propertyValue instanceof DAV\PropertyInterface) { $propertyValue->serialize($server, $currentProperty); } elseif (!is_null($propertyValue)) { throw new DAV\Exception('Unknown property value type: ' . gettype($propertyValue) . ' for property: ' . $propertyName); } } $xpropstat->appendChild($document->createElement('d:status', $server->httpResponse->getStatusMessage($httpStatus))); } }
/** * 'beforeMethod' event handles. This event handles intercepts GET requests ending * with ?export * * @param string $method * @param string $uri * @return bool */ public function beforeMethod($method, $uri) { if ($method != 'GET') { return; } if ($this->server->httpRequest->getQueryString() != 'export') { return; } // splitting uri list($uri) = explode('?', $uri, 2); $node = $this->server->tree->getNodeForPath($uri); if (!$node instanceof Calendar) { return; } // Checking ACL, if available. if ($aclPlugin = $this->server->getPlugin('acl')) { $aclPlugin->checkPrivileges($uri, '{DAV:}read'); } $this->server->httpResponse->setHeader('Content-Type', 'text/calendar'); $this->server->httpResponse->sendStatus(200); $nodes = $this->server->getPropertiesForPath($uri, array('{' . Plugin::NS_CALDAV . '}calendar-data'), 1); $this->server->httpResponse->sendBody($this->generateICS($nodes)); // Returning false to break the event chain return false; }
/** * Serializes this property. * * It will additionally prepend the href property with the server's base uri. * * @param DAV\Server $server * @param \DOMElement $dom * @return void */ public function serialize(DAV\Server $server, \DOMElement $dom) { $prefix = $server->xmlNamespaces['DAV:']; $elem = $dom->ownerDocument->createElement($prefix . ':href'); if ($this->autoPrefix) { $value = $server->getBaseUri() . DAV\URLUtil::encodePath($this->href); } else { $value = $this->href; } $elem->appendChild($dom->ownerDocument->createTextNode($value)); $dom->appendChild($elem); }
/** * Adds in extra information in the xml response. * * This method adds the {DAV:}need-privileges element as defined in rfc3744 * * @param DAV\Server $server * @param \DOMElement $errorNode * @return void */ public function serialize(DAV\Server $server, \DOMElement $errorNode) { $doc = $errorNode->ownerDocument; $np = $doc->createElementNS('DAV:', 'd:need-privileges'); $errorNode->appendChild($np); foreach ($this->privileges as $privilege) { $resource = $doc->createElementNS('DAV:', 'd:resource'); $np->appendChild($resource); $resource->appendChild($doc->createElementNS('DAV:', 'd:href', $server->getBaseUri() . $this->uri)); $priv = $doc->createElementNS('DAV:', 'd:privilege'); $resource->appendChild($priv); preg_match('/^{([^}]*)}(.*)$/', $privilege, $privilegeParts); $priv->appendChild($doc->createElementNS($privilegeParts[1], 'd:' . $privilegeParts[2])); } }
/** * This method allows us to intercept the 'mkcalendar' sabreAction. This * action enables the user to create new calendars from the browser plugin. * * @param string $uri * @param string $action * @param array $postVars * @return bool */ public function browserPostAction($uri, $action, array $postVars) { if ($action !== 'mkcalendar') { return; } $resourceType = array('{DAV:}collection', '{urn:ietf:params:xml:ns:caldav}calendar'); $properties = array(); if (isset($postVars['{DAV:}displayname'])) { $properties['{DAV:}displayname'] = $postVars['{DAV:}displayname']; } $this->server->createCollection($uri . '/' . $postVars['name'], $resourceType, $properties); return false; }
/** * Initializes the plugin * * @param DAV\Server $server * @return void */ public function initialize(DAV\Server $server) { /* Events */ $server->subscribeEvent('beforeGetProperties', array($this, 'beforeGetProperties')); $server->subscribeEvent('afterGetProperties', array($this, 'afterGetProperties')); $server->subscribeEvent('updateProperties', array($this, 'updateProperties')); $server->subscribeEvent('report', array($this, 'report')); $server->subscribeEvent('onHTMLActionsPanel', array($this, 'htmlActionsPanel')); $server->subscribeEvent('onBrowserPostAction', array($this, 'browserPostAction')); $server->subscribeEvent('beforeWriteContent', array($this, 'beforeWriteContent')); $server->subscribeEvent('beforeCreateFile', array($this, 'beforeCreateFile')); /* Namespaces */ $server->xmlNamespaces[self::NS_CARDDAV] = 'card'; /* Mapping Interfaces to {DAV:}resourcetype values */ $server->resourceTypeMapping['SabreForRainLoop\\CardDAV\\IAddressBook'] = '{' . self::NS_CARDDAV . '}addressbook'; $server->resourceTypeMapping['SabreForRainLoop\\CardDAV\\IDirectory'] = '{' . self::NS_CARDDAV . '}directory'; /* Adding properties that may never be changed */ $server->protectedProperties[] = '{' . self::NS_CARDDAV . '}supported-address-data'; $server->protectedProperties[] = '{' . self::NS_CARDDAV . '}max-resource-size'; $server->protectedProperties[] = '{' . self::NS_CARDDAV . '}addressbook-home-set'; $server->protectedProperties[] = '{' . self::NS_CARDDAV . '}supported-collation-set'; $server->propertyMap['{http://calendarserver.org/ns/}me-card'] = 'SabreForRainLoop\\DAV\\Property\\Href'; $this->server = $server; }
/** * This method allows the exception to return any extra HTTP response headers. * * The headers must be returned as an array. * * @param \SabreForRainLoop\DAV\Server $server * @return array */ public function getHTTPHeaders(\SabreForRainLoop\DAV\Server $server) { $methods = $server->getAllowedMethods($server->getRequestUri()); return array('Allow' => strtoupper(implode(', ', $methods))); }
/** * Sets up the plugin * * This method is automatically called by the server class. * * @param DAV\Server $server * @return void */ public function initialize(DAV\Server $server) { $this->server = $server; $server->subscribeEvent('beforeGetProperties', array($this, 'beforeGetProperties')); $server->subscribeEvent('beforeMethod', array($this, 'beforeMethod'), 20); $server->subscribeEvent('beforeBind', array($this, 'beforeBind'), 20); $server->subscribeEvent('beforeUnbind', array($this, 'beforeUnbind'), 20); $server->subscribeEvent('updateProperties', array($this, 'updateProperties')); $server->subscribeEvent('beforeUnlock', array($this, 'beforeUnlock'), 20); $server->subscribeEvent('report', array($this, 'report')); $server->subscribeEvent('unknownMethod', array($this, 'unknownMethod')); array_push($server->protectedProperties, '{DAV:}alternate-URI-set', '{DAV:}principal-URL', '{DAV:}group-membership', '{DAV:}principal-collection-set', '{DAV:}current-user-principal', '{DAV:}supported-privilege-set', '{DAV:}current-user-privilege-set', '{DAV:}acl', '{DAV:}acl-restrictions', '{DAV:}inherited-acl-set', '{DAV:}owner', '{DAV:}group'); // Automatically mapping nodes implementing IPrincipal to the // {DAV:}principal resourcetype. $server->resourceTypeMapping['SabreForRainLoop\\DAVACL\\IPrincipal'] = '{DAV:}principal'; // Mapping the group-member-set property to the HrefList property // class. $server->propertyMap['{DAV:}group-member-set'] = 'SabreForRainLoop\\DAV\\Property\\HrefList'; }
/** * Serializes a single access control entry. * * @param \DOMDocument $doc * @param \DOMElement $node * @param array $ace * @param DAV\Server $server * @return void */ private function serializeAce($doc, $node, $ace, DAV\Server $server) { $xace = $doc->createElementNS('DAV:', 'd:ace'); $node->appendChild($xace); $principal = $doc->createElementNS('DAV:', 'd:principal'); $xace->appendChild($principal); switch ($ace['principal']) { case '{DAV:}authenticated': $principal->appendChild($doc->createElementNS('DAV:', 'd:authenticated')); break; case '{DAV:}unauthenticated': $principal->appendChild($doc->createElementNS('DAV:', 'd:unauthenticated')); break; case '{DAV:}all': $principal->appendChild($doc->createElementNS('DAV:', 'd:all')); break; default: $principal->appendChild($doc->createElementNS('DAV:', 'd:href', ($this->prefixBaseUrl ? $server->getBaseUri() : '') . $ace['principal'] . '/')); } $grant = $doc->createElementNS('DAV:', 'd:grant'); $xace->appendChild($grant); $privParts = null; preg_match('/^{([^}]*)}(.*)$/', $ace['privilege'], $privParts); $xprivilege = $doc->createElementNS('DAV:', 'd:privilege'); $grant->appendChild($xprivilege); $xprivilege->appendChild($doc->createElementNS($privParts[1], 'd:' . $privParts[2])); if (isset($ace['protected']) && $ace['protected']) { $xace->appendChild($doc->createElement('d:protected')); } }
/** * This method serializes the entire notification, as it is used in the * response body. * * @param DAV\Server $server * @param \DOMElement $node * @return void */ public function serializeBody(DAV\Server $server, \DOMElement $node) { $doc = $node->ownerDocument; $dt = $doc->createElement('cs:dtstamp'); $this->dtStamp->setTimezone(new \DateTimezone('GMT')); $dt->appendChild($doc->createTextNode($this->dtStamp->format('Ymd\\THis\\Z'))); $node->appendChild($dt); $prop = $doc->createElement('cs:invite-reply'); $node->appendChild($prop); $uid = $doc->createElement('cs:uid'); $uid->appendChild($doc->createTextNode($this->id)); $prop->appendChild($uid); $inReplyTo = $doc->createElement('cs:in-reply-to'); $inReplyTo->appendChild($doc->createTextNode($this->inReplyTo)); $prop->appendChild($inReplyTo); $href = $doc->createElement('d:href'); $href->appendChild($doc->createTextNode($this->href)); $prop->appendChild($href); $nodeName = null; switch ($this->type) { case SharingPlugin::STATUS_ACCEPTED: $nodeName = 'cs:invite-accepted'; break; case SharingPlugin::STATUS_DECLINED: $nodeName = 'cs:invite-declined'; break; } $prop->appendChild($doc->createElement($nodeName)); $hostHref = $doc->createElement('d:href', $server->getBaseUri() . $this->hostUrl); $hostUrl = $doc->createElement('cs:hosturl'); $hostUrl->appendChild($hostHref); $prop->appendChild($hostUrl); if ($this->summary) { $summary = $doc->createElement('cs:summary'); $summary->appendChild($doc->createTextNode($this->summary)); $prop->appendChild($summary); } }
/** * Serializes the property into a DOMElement. * * @param DAV\Server $server * @param \DOMElement $node * @return void */ public function serialize(DAV\Server $server, \DOMElement $node) { $prefix = $server->xmlNamespaces['DAV:']; switch ($this->type) { case self::UNAUTHENTICATED: $node->appendChild($node->ownerDocument->createElement($prefix . ':unauthenticated')); break; case self::AUTHENTICATED: $node->appendChild($node->ownerDocument->createElement($prefix . ':authenticated')); break; case self::HREF: $href = $node->ownerDocument->createElement($prefix . ':href'); $href->nodeValue = $server->getBaseUri() . DAV\URLUtil::encodePath($this->href); $node->appendChild($href); break; } }
/** * This method serializes the entire notification, as it is used in the * response body. * * @param DAV\Server $server * @param \DOMElement $node * @return void */ public function serializeBody(DAV\Server $server, \DOMElement $node) { $doc = $node->ownerDocument; $dt = $doc->createElement('cs:dtstamp'); $this->dtStamp->setTimezone(new \DateTimezone('GMT')); $dt->appendChild($doc->createTextNode($this->dtStamp->format('Ymd\\THis\\Z'))); $node->appendChild($dt); $prop = $doc->createElement('cs:invite-notification'); $node->appendChild($prop); $uid = $doc->createElement('cs:uid'); $uid->appendChild($doc->createTextNode($this->id)); $prop->appendChild($uid); $href = $doc->createElement('d:href'); $href->appendChild($doc->createTextNode($this->href)); $prop->appendChild($href); $nodeName = null; switch ($this->type) { case SharingPlugin::STATUS_ACCEPTED: $nodeName = 'cs:invite-accepted'; break; case SharingPlugin::STATUS_DECLINED: $nodeName = 'cs:invite-declined'; break; case SharingPlugin::STATUS_DELETED: $nodeName = 'cs:invite-deleted'; break; case SharingPlugin::STATUS_NORESPONSE: $nodeName = 'cs:invite-noresponse'; break; } $prop->appendChild($doc->createElement($nodeName)); $hostHref = $doc->createElement('d:href', $server->getBaseUri() . $this->hostUrl); $hostUrl = $doc->createElement('cs:hosturl'); $hostUrl->appendChild($hostHref); $prop->appendChild($hostUrl); $access = $doc->createElement('cs:access'); if ($this->readOnly) { $access->appendChild($doc->createElement('cs:read')); } else { $access->appendChild($doc->createElement('cs:read-write')); } $prop->appendChild($access); $organizerUrl = $doc->createElement('cs:organizer'); // If the organizer contains a 'mailto:' part, it means it should be // treated as absolute. if (strtolower(substr($this->organizer, 0, 7)) === 'mailto:') { $organizerHref = new DAV\Property\Href($this->organizer, false); } else { $organizerHref = new DAV\Property\Href($this->organizer, true); } $organizerHref->serialize($server, $organizerUrl); if ($this->commonName) { $commonName = $doc->createElement('cs:common-name'); $commonName->appendChild($doc->createTextNode($this->commonName)); $organizerUrl->appendChild($commonName); $commonNameOld = $doc->createElement('cs:organizer-cn'); $commonNameOld->appendChild($doc->createTextNode($this->commonName)); $prop->appendChild($commonNameOld); } if ($this->firstName) { $firstName = $doc->createElement('cs:first-name'); $firstName->appendChild($doc->createTextNode($this->firstName)); $organizerUrl->appendChild($firstName); $firstNameOld = $doc->createElement('cs:organizer-first'); $firstNameOld->appendChild($doc->createTextNode($this->firstName)); $prop->appendChild($firstNameOld); } if ($this->lastName) { $lastName = $doc->createElement('cs:last-name'); $lastName->appendChild($doc->createTextNode($this->lastName)); $organizerUrl->appendChild($lastName); $lastNameOld = $doc->createElement('cs:organizer-last'); $lastNameOld->appendChild($doc->createTextNode($this->lastName)); $prop->appendChild($lastNameOld); } $prop->appendChild($organizerUrl); if ($this->summary) { $summary = $doc->createElement('cs:summary'); $summary->appendChild($doc->createTextNode($this->summary)); $prop->appendChild($summary); } if ($this->supportedComponents) { $xcomp = $doc->createElement('cal:supported-calendar-component-set'); $this->supportedComponents->serialize($server, $xcomp); $prop->appendChild($xcomp); } }
/** * Initializes the plugin * * @param DAV\Server $server * @return void */ public function initialize(DAV\Server $server) { // Using a relatively low priority (200) to allow other extensions // to set the content-type first. $server->subscribeEvent('afterGetProperties', array($this, 'afterGetProperties'), 200); }
/** * Initializes the plugin * * This method is automatically called by the Server class after addPlugin. * * @param DAV\Server $server * @return void */ public function initialize(DAV\Server $server) { $this->server = $server; $server->subscribeEvent('unknownMethod', array($this, 'unknownMethod')); }