diff --git a/core/Bootstrap.php b/core/Bootstrap.php index 64c6f454b..371f7876e 100644 --- a/core/Bootstrap.php +++ b/core/Bootstrap.php @@ -173,7 +173,8 @@ protected function _initRouter() $route1 = new Zend_Controller_Router_Route( Zend_Registry::get('configGlobal')->webdav->path.'/:action/*', array( - 'controller' => 'webdav', + 'module' => 'webdav', + 'controller' => ':action', 'action' => ':action' ) ); diff --git a/core/controllers/AdminController.php b/core/controllers/AdminController.php index bc3038f4a..0cd90e936 100644 --- a/core/controllers/AdminController.php +++ b/core/controllers/AdminController.php @@ -79,20 +79,26 @@ function indexAction() switch (Zend_Registry::get('configDatabase')->database->adapter) { case 'PDO_MYSQL': - $this->Component->Utility->run_mysql_from_file(BASE_PATH.'/modules/'.$moduleName.'/database/mysql/'.$allModules[$moduleName]->version.'.sql', - Zend_Registry::get('configDatabase')->database->params->host, - Zend_Registry::get('configDatabase')->database->params->username, - Zend_Registry::get('configDatabase')->database->params->password, - Zend_Registry::get('configDatabase')->database->params->dbname, - Zend_Registry::get('configDatabase')->database->params->port); + if(file_exists(BASE_PATH.'/modules/'.$moduleName.'/database/mysql/'.$allModules[$moduleName]->version.'.sql')) + { + $this->Component->Utility->run_mysql_from_file(BASE_PATH.'/modules/'.$moduleName.'/database/mysql/'.$allModules[$moduleName]->version.'.sql', + Zend_Registry::get('configDatabase')->database->params->host, + Zend_Registry::get('configDatabase')->database->params->username, + Zend_Registry::get('configDatabase')->database->params->password, + Zend_Registry::get('configDatabase')->database->params->dbname, + Zend_Registry::get('configDatabase')->database->params->port); + } break; case 'PDO_PGSQL': - $this->Component->Utility->run_pgsql_from_file(BASE_PATH.'/modules/'.$key.'/database/pgsql/'.$allModules[$moduleName]->version.'.sql', - Zend_Registry::get('configDatabase')->database->params->host, - Zend_Registry::get('configDatabase')->database->params->username, - Zend_Registry::get('configDatabase')->database->params->password, - Zend_Registry::get('configDatabase')->database->params->dbname, - Zend_Registry::get('configDatabase')->database->params->port); + if(file_exists(BASE_PATH.'/modules/'.$key.'/database/pgsql/'.$allModules[$moduleName]->version.'.sql')) + { + $this->Component->Utility->run_pgsql_from_file(BASE_PATH.'/modules/'.$key.'/database/pgsql/'.$allModules[$moduleName]->version.'.sql', + Zend_Registry::get('configDatabase')->database->params->host, + Zend_Registry::get('configDatabase')->database->params->username, + Zend_Registry::get('configDatabase')->database->params->password, + Zend_Registry::get('configDatabase')->database->params->dbname, + Zend_Registry::get('configDatabase')->database->params->port); + } break; } } diff --git a/library/SabreDAV/lib/Sabre/CalDAV/CalendarRootNode.php b/library/SabreDAV/lib/Sabre/CalDAV/CalendarRootNode.php deleted file mode 100644 index 322722a11..000000000 --- a/library/SabreDAV/lib/Sabre/CalDAV/CalendarRootNode.php +++ /dev/null @@ -1,74 +0,0 @@ -authBackend = $authBackend; - $this->caldavBackend = $caldavBackend; - - } - - /** - * Returns the name of the node - * - * @return string - */ - public function getName() { - - return Sabre_CalDAV_Plugin::CALENDAR_ROOT; - - } - - /** - * Returns the list of users as Sabre_CalDAV_User objects. - * - * @return array - */ - public function getChildren() { - - $users = $this->authBackend->getUsers(); - $children = array(); - foreach($users as $user) { - - $children[] = new Sabre_CalDAV_UserCalendars($this->authBackend, $this->caldavBackend, $user['uri']); - - } - return $children; - - } - -} diff --git a/library/SabreDAV/lib/Sabre/DAV/Auth/Backend/PDO.php b/library/SabreDAV/lib/Sabre/DAV/Auth/Backend/PDO.php deleted file mode 100644 index c88085803..000000000 --- a/library/SabreDAV/lib/Sabre/DAV/Auth/Backend/PDO.php +++ /dev/null @@ -1,79 +0,0 @@ -pdo = $pdo; - - } - - /** - * Returns a users' information - * - * @param string $realm - * @param string $username - * @return string - */ - public function getUserInfo($realm,$username) { - - $stmt = $this->pdo->prepare('SELECT username, digesta1, email FROM users WHERE username = ?'); - $stmt->execute(array($username)); - $result = $stmt->fetchAll(); - - if (!count($result)) return false; - $user = array( - 'uri' => 'principals/' . $result[0]['username'], - 'digestHash' => $result[0]['digesta1'], - ); - if ($result[0]['email']) $user['{http://sabredav.org/ns}email-address'] = $result[0]['email']; - return $user; - - } - - /** - * Returns a list of all users - * - * @return array - */ - public function getUsers() { - - $result = $this->pdo->query('SELECT username, email FROM users')->fetchAll(); - - $rv = array(); - foreach($result as $user) { - - $r = array( - 'uri' => 'principals/' . $user['username'], - ); - if ($user['email']) $r['{http://sabredav.org/ns}email-address'] = $user['email']; - $rv[] = $r; - - } - - return $rv; - - } - -} diff --git a/library/SabreDAV/lib/Sabre/DAV/Auth/Plugin.php b/library/SabreDAV/lib/Sabre/DAV/Auth/Plugin.php deleted file mode 100644 index cc4f25f3f..000000000 --- a/library/SabreDAV/lib/Sabre/DAV/Auth/Plugin.php +++ /dev/null @@ -1,434 +0,0 @@ -authBackend = $authBackend; - $this->realm = $realm; - - } - - /** - * Initializes the plugin. This function is automatically called by the server - * - * @param Sabre_DAV_Server $server - * @return void - */ - public function initialize(Sabre_DAV_Server $server) { - - $this->server = $server; - $this->server->subscribeEvent('beforeMethod',array($this,'beforeMethod'),10); - $this->server->subscribeEvent('afterGetProperties',array($this,'afterGetProperties')); - $this->server->subscribeEvent('report',array($this,'report')); - - } - - /** - * This method intercepts calls to PROPFIND and similar lookups - * - * This is done to inject the current-user-principal if this is requested. - * - * @todo support for 'unauthenticated' - * @return void - */ - public function afterGetProperties($href, &$properties) { - - if (array_key_exists('{DAV:}current-user-principal', $properties[404])) { - if ($ui = $this->authBackend->getCurrentUser()) { - $properties[200]['{DAV:}current-user-principal'] = new Sabre_DAV_Property_Principal(Sabre_DAV_Property_Principal::HREF, $ui['uri']); - } else { - $properties[200]['{DAV:}current-user-principal'] = new Sabre_DAV_Property_Principal(Sabre_DAV_Property_Principal::UNAUTHENTICATED); - } - unset($properties[404]['{DAV:}current-user-principal']); - } - if (array_key_exists('{DAV:}principal-collection-set', $properties[404])) { - $properties[200]['{DAV:}principal-collection-set'] = new Sabre_DAV_Property_Href('principals'); - unset($properties[404]['{DAV:}principal-collection-set']); - } - if (array_key_exists('{DAV:}supported-report-set', $properties[200])) { - $properties[200]['{DAV:}supported-report-set']->addReport(array( - '{DAV:}expand-property', - )); - } - - - } - - /** - * This method is called before any HTTP method and forces users to be authenticated - * - * @param string $method - * @throws Sabre_DAV_Exception_NotAuthenticated - * @return bool - */ - public function beforeMethod($method, $uri) { - - $this->authBackend->authenticate($this->server,$this->realm); - - } - - /** - * This functions handles REPORT requests - * - * @param string $reportName - * @param DOMNode $dom - * @return bool|null - */ - public function report($reportName,$dom) { - - switch($reportName) { - case '{DAV:}expand-property' : - $this->expandPropertyReport($dom); - return false; - case '{DAV:}principal-property-search' : - if ($this->server->getRequestUri()==='principals') { - $this->principalPropertySearchReport($dom); - return false; - } - break; - case '{DAV:}principal-search-property-set' : - if ($this->server->getRequestUri()==='principals') { - $this->principalSearchPropertySetReport($dom); - return false; - } - break; - - } - - } - - /** - * 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 DOMElement $dom - * @return void - */ - protected function expandPropertyReport($dom) { - - $requestedProperties = $this->parseExpandPropertyReportRequest($dom->firstChild->firstChild); - $depth = $this->server->getHTTPDepth(0); - $requestUri = $this->server->getRequestUri(); - - $result = $this->expandProperties($requestUri,$requestedProperties,$depth); - - $dom = new DOMDocument('1.0','utf-8'); - $dom->formatOutput = true; - $multiStatus = $dom->createElement('d:multistatus'); - $dom->appendChild($multiStatus); - - // Adding in default namespaces - foreach($this->server->xmlNamespaces as $namespace=>$prefix) { - - $multiStatus->setAttribute('xmlns:' . $prefix,$namespace); - - } - - foreach($result as $entry) { - - $entry->serialize($this->server,$multiStatus); - - } - - $xml = $dom->saveXML(); - $this->server->httpResponse->setHeader('Content-Type','application/xml; charset=utf-8'); - $this->server->httpResponse->sendStatus(207); - $this->server->httpResponse->sendBody($xml); - - // Make sure the event chain is broken - return false; - - } - - /** - * This method is used by expandPropertyReport to parse - * out the entire HTTP request. - * - * @param DOMElement $node - * @return array - */ - protected function parseExpandPropertyReportRequest($node) { - - $requestedProperties = array(); - do { - - if (Sabre_DAV_XMLUtil::toClarkNotation($node)!=='{DAV:}property') continue; - - if ($node->firstChild) { - - $children = $this->parseExpandPropertyReportRequest($node->firstChild); - - } else { - - $children = array(); - - } - - $namespace = $node->getAttribute('namespace'); - if (!$namespace) $namespace = 'DAV:'; - - $propName = '{'.$namespace.'}' . $node->getAttribute('name'); - $requestedProperties[$propName] = $children; - - } while ($node = $node->nextSibling); - - return $requestedProperties; - - } - - /** - * This method expands all the properties and returns - * a list with property values - * - * @param array $path - * @param array $requestedProperties the list of required properties - * @param array $depth - */ - protected function expandProperties($path,array $requestedProperties,$depth) { - - $foundProperties = $this->server->getPropertiesForPath($path,array_keys($requestedProperties),$depth); - - $result = array(); - - foreach($foundProperties as $node) { - - foreach($requestedProperties as $propertyName=>$childRequestedProperties) { - - // We're only traversing if sub-properties were requested - if(count($childRequestedProperties)===0) continue; - - // We only have to do the expansion if the property was found - // and it contains an href element. - if (!array_key_exists($propertyName,$node[200])) continue; - if (!($node[200][$propertyName] instanceof Sabre_DAV_Property_IHref)) continue; - - $href = $node[200][$propertyName]->getHref(); - list($node[200][$propertyName]) = $this->expandProperties($href,$childRequestedProperties,0); - - } - $result[] = new Sabre_DAV_Property_Response($path, $node); - - } - - return $result; - - } - - protected function principalSearchPropertySetReport(DOMDocument $dom) { - - $searchProperties = array( - '{DAV:}displayname' => 'display name' - - ); - - $httpDepth = $this->server->getHTTPDepth(0); - if ($httpDepth!==0) { - throw new Sabre_DAV_Exception_BadRequest('This report is only defined when Depth: 0'); - } - - if ($dom->firstChild->hasChildNodes()) - throw new Sabre_DAV_Exception_BadRequest('The principal-search-property-set report element is not allowed to have child elements'); - - $dom = new DOMDocument('1.0','utf-8'); - $dom->formatOutput = true; - $root = $dom->createElement('d:principal-search-property-set'); - $dom->appendChild($root); - // Adding in default namespaces - foreach($this->server->xmlNamespaces as $namespace=>$prefix) { - - $root->setAttribute('xmlns:' . $prefix,$namespace); - - } - - $nsList = $this->server->xmlNamespaces; - - foreach($searchProperties as $propertyName=>$description) { - - $psp = $dom->createElement('d:principal-search-property'); - $root->appendChild($psp); - - $prop = $dom->createElement('d:prop'); - $psp->appendChild($prop); - - $propName = null; - preg_match('/^{([^}]*)}(.*)$/',$propertyName,$propName); - - //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 = $dom->createElement($nsList[$propName[1]] . ':' . $propName[2]); - //} else { - // $currentProperty = $dom->createElementNS($propName[1],$nsList[$propName[1]].':' . $propName[2]); - //} - $prop->appendChild($currentProperty); - - $descriptionElem = $dom->createElement('d:description'); - $descriptionElem->setAttribute('xml:lang','en'); - $descriptionElem->appendChild($dom->createTextNode($description)); - $psp->appendChild($descriptionElem); - - - } - - $this->server->httpResponse->setHeader('Content-Type','application/xml; charset=utf-8'); - $this->server->httpResponse->sendStatus(200); - $this->server->httpResponse->sendBody($dom->saveXML()); - - } - - protected function principalPropertySearchReport($dom) { - - $searchableProperties = array( - '{DAV:}displayname' => 'display name' - - ); - - list($searchProperties, $requestedProperties) = $this->parsePrincipalPropertySearchReportRequest($dom); - - $uri = $this->server->getRequestUri(); - - $result = array(); - - $lookupResults = $this->server->getPropertiesForPath($uri, array_keys($searchProperties), 1); - - // The first item in the results is the parent, so we get rid of it. - array_shift($lookupResults); - - $matches = array(); - - foreach($lookupResults as $lookupResult) { - - foreach($searchProperties as $searchProperty=>$searchValue) { - if (!isset($searchableProperties[$searchProperty])) { - throw new Sabre_DAV_Exception_BadRequest('Searching for ' . $searchProperty . ' is not supported'); - } - - if (isset($lookupResult[200][$searchProperty]) && - mb_stripos($lookupResult[200][$searchProperty], $searchValue, 0, 'UTF-8')!==false) { - $matches[] = $lookupResult['href']; - } - - } - - } - - $matchProperties = array(); - - foreach($matches as $match) { - - list($result) = $this->server->getPropertiesForPath($match, $requestedProperties, 0); - $matchProperties[] = $result; - - } - - $xml = $this->server->generateMultiStatus($matchProperties); - $this->server->httpResponse->setHeader('Content-Type','application/xml; charset=utf-8'); - $this->server->httpResponse->sendStatus(207); - $this->server->httpResponse->sendBody($xml); - - } - - 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(); - - // Parsing the search request - foreach($dom->firstChild->childNodes as $searchNode) { - - 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))); - - } - -} diff --git a/library/SabreDAV/lib/Sabre/DAV/Auth/Principal.php b/library/SabreDAV/lib/Sabre/DAV/Auth/Principal.php deleted file mode 100644 index a69ce6f6f..000000000 --- a/library/SabreDAV/lib/Sabre/DAV/Auth/Principal.php +++ /dev/null @@ -1,147 +0,0 @@ -principalUri = $principalUri; - $this->principalProperties = $principalProperties; - - } - - /** - * Returns the name of the element - * - * @return void - */ - public function getName() { - - list(, $name) = Sabre_DAV_URLUtil::splitPath($this->principalUri); - return $name; - - } - - /** - * Returns the name of the user - * - * @return void - */ - public function getDisplayName() { - - if (isset($this->principalProperties['{DAV:}displayname'])) { - return $this->principalProperties['{DAV:}displayname']; - } else { - return $this->getName(); - } - - } - - /** - * Returns a list of properties - * - * @param array $requestedProperties - * @return void - */ - public function getProperties($requestedProperties) { - - if (!count($requestedProperties)) { - - // If all properties were requested - // we will only returns properties from this list - $requestedProperties = array( - '{DAV:}resourcetype', - '{DAV:}displayname', - ); - - } - - // We need to always return the resourcetype - // This is a bug in the core server, but it is easier to do it this way for now - $newProperties = array( - '{DAV:}resourcetype' => new Sabre_DAV_Property_ResourceType('{DAV:}principal') - ); - foreach($requestedProperties as $propName) switch($propName) { - - case '{DAV:}alternate-URI-set' : - if (isset($this->principalProperties['{http://sabredav.org/ns}email-address'])) { - $href = 'mailto:' . $this->principalProperties['{http://sabredav.org/ns}email-address']; - $newProperties[$propName] = new Sabre_DAV_Property_Href($href); - } else { - $newProperties[$propName] = null; - } - break; - case '{DAV:}group-member-set' : - case '{DAV:}group-membership' : - $newProperties[$propName] = null; - break; - - case '{DAV:}principal-URL' : - $newProperties[$propName] = new Sabre_DAV_Property_Href($this->principalUri); - break; - - case '{DAV:}displayname' : - $newProperties[$propName] = $this->getDisplayName(); - break; - - default : - if (isset($this->principalProperties[$propName])) { - $newProperties[$propName] = $this->principalProperties[$propName]; - } - break; - - } - - return $newProperties; - - - } - - /** - * Updates this principals properties. - * - * Currently this is not supported - * - * @param array $properties - * @see Sabre_DAV_IProperties::updateProperties - * @return bool|array - */ - public function updateProperties($properties) { - - return false; - - } - -} diff --git a/library/SabreDAV/lib/Sabre/DAV/Auth/PrincipalCollection.php b/library/SabreDAV/lib/Sabre/DAV/Auth/PrincipalCollection.php deleted file mode 100644 index 75cf3af96..000000000 --- a/library/SabreDAV/lib/Sabre/DAV/Auth/PrincipalCollection.php +++ /dev/null @@ -1,74 +0,0 @@ -authBackend = $authBackend; - - } - - /** - * Returns the name of this collection. - * - * @return string - */ - public function getName() { - - return self::NODENAME; - - } - - /** - * Retursn the list of users - * - * @return void - */ - public function getChildren() { - - $children = array(); - foreach($this->authBackend->getUsers() as $principalInfo) { - - $principalUri = $principalInfo['uri'] . '/'; - $children[] = new Sabre_DAV_Auth_Principal($principalUri,$principalInfo); - - - } - return $children; - - } - -} diff --git a/modules/template/emptymodule/AppController.php b/modules/template/emptymodule/AppController.php new file mode 100644 index 000000000..59d4cd25f --- /dev/null +++ b/modules/template/emptymodule/AppController.php @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/modules/template/emptymodule/configs/.gitignore b/modules/template/emptymodule/configs/.gitignore new file mode 100644 index 000000000..594cfe7c3 --- /dev/null +++ b/modules/template/emptymodule/configs/.gitignore @@ -0,0 +1,2 @@ +*.local.ini +*.local.ini.old \ No newline at end of file diff --git a/modules/template/emptymodule/configs/module.ini b/modules/template/emptymodule/configs/module.ini new file mode 100644 index 000000000..60400ff0b --- /dev/null +++ b/modules/template/emptymodule/configs/module.ini @@ -0,0 +1,9 @@ +[global] +; version of the module +version = 1.0.0 +; full name +fullname= name +; description +description= description +; if true, only an admini can enable the addon and it will be activated for everyone +system = true diff --git a/modules/template/emptymodule/constant/module.php b/modules/template/emptymodule/constant/module.php new file mode 100644 index 000000000..9671af98c --- /dev/null +++ b/modules/template/emptymodule/constant/module.php @@ -0,0 +1,3 @@ + diff --git a/modules/template/emptymodule/controllers/ConfigController.php b/modules/template/emptymodule/controllers/ConfigController.php new file mode 100644 index 000000000..2f83024dd --- /dev/null +++ b/modules/template/emptymodule/controllers/ConfigController.php @@ -0,0 +1,14 @@ +logged||!$this->userSession->Dao->getAdmin()==1) + { + throw new Zend_Exception("You should be an administrator"); + } + } + +}//end class \ No newline at end of file diff --git a/modules/template/emptymodule/controllers/IndexController.php b/modules/template/emptymodule/controllers/IndexController.php new file mode 100644 index 000000000..2f67e36bf --- /dev/null +++ b/modules/template/emptymodule/controllers/IndexController.php @@ -0,0 +1,22 @@ + diff --git a/modules/template/emptymodule/models/AppModel.php b/modules/template/emptymodule/models/AppModel.php new file mode 100644 index 000000000..73406d69c --- /dev/null +++ b/modules/template/emptymodule/models/AppModel.php @@ -0,0 +1,8 @@ + diff --git a/modules/template/emptymodule/translation/fr-main.csv b/modules/template/emptymodule/translation/fr-main.csv new file mode 100644 index 000000000..9d3cbd3ae --- /dev/null +++ b/modules/template/emptymodule/translation/fr-main.csv @@ -0,0 +1 @@ +Hello world;Boujour tout le monde \ No newline at end of file diff --git a/modules/template/emptymodule/views/config/index.phtml b/modules/template/emptymodule/views/config/index.phtml new file mode 100644 index 000000000..6d1710e00 --- /dev/null +++ b/modules/template/emptymodule/views/config/index.phtml @@ -0,0 +1 @@ +Config page \ No newline at end of file diff --git a/modules/template/emptymodule/views/index/index.phtml b/modules/template/emptymodule/views/index/index.phtml new file mode 100644 index 000000000..12fba4c5c --- /dev/null +++ b/modules/template/emptymodule/views/index/index.phtml @@ -0,0 +1 @@ +Main page \ No newline at end of file diff --git a/modules/webdav/AppController.php b/modules/webdav/AppController.php new file mode 100644 index 000000000..72f1967cd --- /dev/null +++ b/modules/webdav/AppController.php @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/modules/webdav/configs/.gitignore b/modules/webdav/configs/.gitignore new file mode 100644 index 000000000..594cfe7c3 --- /dev/null +++ b/modules/webdav/configs/.gitignore @@ -0,0 +1,2 @@ +*.local.ini +*.local.ini.old \ No newline at end of file diff --git a/modules/webdav/configs/module.ini b/modules/webdav/configs/module.ini new file mode 100644 index 000000000..0de4db3f3 --- /dev/null +++ b/modules/webdav/configs/module.ini @@ -0,0 +1,9 @@ +[global] +; version of the module +version = 1.0.0 +; full name +fullname= WebDav +; description +description= "Browse Midas files using SabreDab (Alpha version)" +; if true, only an admini can enable the addon and it will be activated for everyone +system = true diff --git a/modules/webdav/constant/module.php b/modules/webdav/constant/module.php new file mode 100644 index 000000000..9671af98c --- /dev/null +++ b/modules/webdav/constant/module.php @@ -0,0 +1,3 @@ + diff --git a/modules/webdav/controllers/ConfigController.php b/modules/webdav/controllers/ConfigController.php new file mode 100644 index 000000000..a1b1ab898 --- /dev/null +++ b/modules/webdav/controllers/ConfigController.php @@ -0,0 +1,14 @@ +logged||!$this->userSession->Dao->getAdmin()==1) + { + throw new Zend_Exception("You should be an administrator"); + } + } + +}//end class \ No newline at end of file diff --git a/modules/webdav/controllers/IndexController.php b/modules/webdav/controllers/IndexController.php new file mode 100644 index 000000000..bc4273011 --- /dev/null +++ b/modules/webdav/controllers/IndexController.php @@ -0,0 +1,88 @@ +_helper->layout->disableLayout(); + $this->_helper->viewRenderer->setNoRender(); + + // Now we're creating a whole bunch of objects + $fc = Zend_Controller_Front::getInstance(); + $webroot = $fc->getBaseUrl() ; + + // User authentication + $auth = new Sabre_HTTP_BasicAuth(); + $result = $auth->getUserPass(); + + if($result[0] != 'anonymous') + { + //$someone = $this->User->findByEmail($result[0]); + //if($someone['User']['password'] != md5($result[1])) + { + $auth->requireLogin(); + echo "Authentication required\n"; + die(); + } + //$userid = $someone['User']['eperson_id']; + } + else + { + $userid = 0; + } + + // Change public to something else, if you are using a different directory for your files + $rootDirectory = new Sabre_DAV_FS_Directory('C:/WEBS'); + + // The server object is responsible for making sense out of the WebDAV protocol + $server = new Sabre_DAV_Server($rootDirectory); + + // If your server is not on your webroot, make sure the following line has the correct information + $server->setBaseUri($webroot.'/webdav'); + + // $server->setBaseUri('/~evert/mydavfolder'); // if its in some kind of home directory + // $server->setBaseUri('/dav/index.php/'); // if you can't use mod_rewrite, use index.php as a base uri + // $server->setBaseUri('/'); // ideally, SabreDAV lives on a root directory with mod_rewrite sending every request to index.php + + // The lock manager is reponsible for making sure users don't overwrite each others changes. Change 'data' to a different + // directory, if you're storing your data somewhere else. + $lockBackend = new Sabre_DAV_Locks_Backend_FS('C:/WEBS'); + $lockPlugin = new Sabre_DAV_Locks_Plugin($lockBackend); + $browserPlugin = new Sabre_DAV_Browser_Plugin(); + $server->addPlugin($browserPlugin); + $server->addPlugin($lockPlugin); + + $tmpDir = $this->GetTempDirectory()."/webdav"; + + // Temporary file filter (necessary for MacOS at least) + $tempFF = new Sabre_DAV_TemporaryFileFilterPlugin($tmpDir); + $server->addPlugin($tempFF); + + // All we need to do now, is to fire up the server + $server->exec(); + + exit(); // do not process anything else + } // end method indexAction + + /*function indexAction() + { + } */ + +}//end class + \ No newline at end of file diff --git a/library/SabreDAV/ChangeLog b/modules/webdav/library/SabreDAV/ChangeLog similarity index 84% rename from library/SabreDAV/ChangeLog rename to modules/webdav/library/SabreDAV/ChangeLog index df57f2648..d3cda0f5b 100644 --- a/library/SabreDAV/ChangeLog +++ b/modules/webdav/library/SabreDAV/ChangeLog @@ -1,3 +1,76 @@ +1.4.2-beta (2011-04-01) + * Added: It's not possible to disable listing of nodes that are denied + read access by ACL. + * Fixed: Changed a few properties in CalDAV classes from private to + protected. + * Fixed: Issue 119: Terrible things could happen when relying on + guessBaseUri, the server was running on the root of the domain and a user + tried to access a file ending in .php. This is a slight BC break. + * Fixed: Issue 118: Lock tokens in If headers without a uri should be + treated as the request uri, not 'all relevant uri's. + * Fixed: Issue 120: PDO backend was incorrectly fetching too much locks in + cases where there were similar named locked files in a directory. + +1.4.1-beta (2011-02-26) + * Fixed: Sabre_DAV_Locks_Backend_PDO returned too many locks. + * Fixed: Sabre_HTTP_Request::getHeader didn't return Content-Type when + running on apache, so a few workarounds were added. + * Change: Slightly changed CalDAV Backend API's, to allow for heavy + optimizations. This is non-bc breaking. + +1.4.0-beta (2011-02-12) + * Added: Partly RFC3744 ACL support. + * Added: Calendar-delegation (caldav-proxy) support. + * BC break: In order to fix Issue 99, a new argument had to be added to + Sabre_DAV_Locks_Backend_*::getLocks classes. Consult the classes for + details. + * Deprecated: Sabre_DAV_Locks_Backend_FS is now deprecated and will be + removed in a later version. Use PDO or the new File class instead. + * Deprecated: The Sabre_CalDAV_ICalendarUtil class is now marked + deprecated, and will be removed in a future version. Please use + Sabre_VObject instead. + * Removed: All principal-related functionality has been removed from the + Sabre_DAV_Auth_Plugin, and moved to the Sabre_DAVACL_Plugin. + * Added: VObject library, for easy vcard/icalendar parsing using a natural + interface. + * Added: Ability to automatically generate full .ics feeds off calendars. + To use: Add the Sabre_CalDAV_ICSExportPlugin, and add ?export to your + calendar url. + * Added: Plugins can now specify a pluginname, for easy access using + Sabre_DAV_Server::getPlugin(). + * Added: beforeGetProperties event. + * Added: updateProperties event. + * Added: Principal listings and calendar-access can now be done privately, + disallowing users from accessing or modifying other users' data. + * Added: You can now pass arrays to the Sabre_DAV_Server constructor. If + it's an array with node-objects, a Root collection will automatically be + created, and the nodes are used as top-level children. + * Added: The principal base uri is now customizable. It used to be + hardcoded to 'principals/[user]'. + * Added: getSupportedReportSet method in ServerPlugin class. This allows + you to easily specify which reports you're implementing. + * Added: A '..' link to the HTML browser. + * Fixed: Issue 99: Locks on child elements were ignored when their parent + nodes were deleted. + * Fixed: Issue 90: lockdiscovery property and LOCK response now include a + {DAV}lockroot element. + * Fixed: Issue 96: support for 'default' collation in CalDAV text-match + filters. + * Fixed: Issue 102: Ensuring that copy and move with identical source and + destination uri's fails. + * Fixed: Issue 105: Supporting MKCALENDAR with no body. + * Fixed: Issue 109: Small fixes in Sabre_HTTP_Util. + * Fixed: Issue 111: Properly catching the ownername in a lock (if it's a + string) + * Fixed: Sabre_DAV_ObjectTree::nodeExist always returned false for the + root node. + * Added: Global way to easily supply new resourcetypes for cetain node + classes. + * Fixed: Issue 59: Allowing the user to override the authentication realm + in Sabre_CalDAV_Server. + * Update: Issue 97: Looser time-range checking if there's a reccurrence + rule in an event. This fixes 'missing recurring events'. + 1.3.0 (2010-10-14) * Added: childExists method to Sabre_DAV_ICollection. This is an api break, so if you implement Sabre_DAV_ICollection directly, add the method. diff --git a/library/SabreDAV/LICENSE b/modules/webdav/library/SabreDAV/LICENSE similarity index 97% rename from library/SabreDAV/LICENSE rename to modules/webdav/library/SabreDAV/LICENSE index 1eba437f9..0bf9461ef 100644 --- a/library/SabreDAV/LICENSE +++ b/modules/webdav/library/SabreDAV/LICENSE @@ -1,4 +1,4 @@ -Copyright (C) 2007-2010 Rooftop Solutions. +Copyright (C) 2007-2011 Rooftop Solutions. Copyright (C) 2007-2009 FileMobile inc. All rights reserved. diff --git a/library/SabreDAV/lib/Sabre.autoload.php b/modules/webdav/library/SabreDAV/lib/Sabre.autoload.php similarity index 85% rename from library/SabreDAV/lib/Sabre.autoload.php rename to modules/webdav/library/SabreDAV/lib/Sabre.autoload.php index 1c3815f55..0e5601d89 100644 --- a/library/SabreDAV/lib/Sabre.autoload.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre.autoload.php @@ -7,7 +7,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @deprecated * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License diff --git a/library/SabreDAV/lib/Sabre.includes.php b/modules/webdav/library/SabreDAV/lib/Sabre.includes.php similarity index 93% rename from library/SabreDAV/lib/Sabre.includes.php rename to modules/webdav/library/SabreDAV/lib/Sabre.includes.php index 612e13c5e..6e4b50f51 100644 --- a/library/SabreDAV/lib/Sabre.includes.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre.includes.php @@ -8,7 +8,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ @@ -54,8 +54,10 @@ include 'Sabre/DAV/Property/LockDiscovery.php'; include 'Sabre/DAV/Property/IHref.php'; include 'Sabre/DAV/Property/Href.php'; +include 'Sabre/DAV/Property/HrefList.php'; include 'Sabre/DAV/Property/SupportedReportSet.php'; include 'Sabre/DAV/Property/Response.php'; +include 'Sabre/DAV/Property/ResponseList.php'; include 'Sabre/DAV/Property/Principal.php'; /* Node interfaces */ @@ -113,14 +115,12 @@ /* Authentication plugin */ include 'Sabre/DAV/Auth/Plugin.php'; -include 'Sabre/DAV/Auth/Backend/Abstract.php'; +include 'Sabre/DAV/Auth/IBackend.php'; include 'Sabre/DAV/Auth/Backend/AbstractDigest.php'; +include 'Sabre/DAV/Auth/Backend/AbstractBasic.php'; include 'Sabre/DAV/Auth/Backend/File.php'; include 'Sabre/DAV/Auth/Backend/PDO.php'; -include 'Sabre/DAV/Auth/Principal.php'; -include 'Sabre/DAV/Auth/PrincipalCollection.php'; - /* DavMount plugin */ include 'Sabre/DAV/Mount/Plugin.php'; diff --git a/library/SabreDAV/lib/Sabre/CalDAV/Backend/Abstract.php b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Backend/Abstract.php similarity index 86% rename from library/SabreDAV/lib/Sabre/CalDAV/Backend/Abstract.php rename to modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Backend/Abstract.php index c758a38ba..7ac282f44 100644 --- a/library/SabreDAV/lib/Sabre/CalDAV/Backend/Abstract.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Backend/Abstract.php @@ -5,7 +5,7 @@ * * @package Sabre * @subpackage CalDAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ @@ -104,6 +104,16 @@ abstract function deleteCalendar($calendarId); * * calendardata - The iCalendar-compatible calnedar data * * uri - a unique key which will be used to construct the uri. This can be any arbitrary string. * * lastmodified - a timestamp of the last modification time + * * etag - An arbitrary string, surrounded by double-quotes. (e.g.: + * ' "abcdef"') + * * calendarid - The calendarid as it was passed to this function. + * + * Note that the etag is optional, but it's highly encouraged to return for + * speed reasons. + * + * The calendardata is also optional. If it's not returned + * 'getCalendarObject' will be called later, which *is* expected to return + * calendardata. * * @param string $calendarId * @return array @@ -111,7 +121,12 @@ abstract function deleteCalendar($calendarId); abstract function getCalendarObjects($calendarId); /** - * Returns information from a single calendar object, based on it's object uri. + * Returns information from a single calendar object, based on it's object + * uri. + * + * The returned array must have the same keys as getCalendarObjects. The + * 'calendardata' object is required here though, while it's not required + * for getCalendarObjects. * * @param string $calendarId * @param string $objectUri diff --git a/library/SabreDAV/lib/Sabre/CalDAV/Backend/PDO.php b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Backend/PDO.php similarity index 93% rename from library/SabreDAV/lib/Sabre/CalDAV/Backend/PDO.php rename to modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Backend/PDO.php index f60d17370..429b6e80c 100644 --- a/library/SabreDAV/lib/Sabre/CalDAV/Backend/PDO.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Backend/PDO.php @@ -8,7 +8,7 @@ * * @package Sabre * @subpackage CalDAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ @@ -275,6 +275,16 @@ public function deleteCalendar($calendarId) { * * calendardata - The iCalendar-compatible calnedar data * * uri - a unique key which will be used to construct the uri. This can be any arbitrary string. * * lastmodified - a timestamp of the last modification time + * * etag - An arbitrary string, surrounded by double-quotes. (e.g.: + * ' "abcdef"') + * * calendarid - The calendarid as it was passed to this function. + * + * Note that the etag is optional, but it's highly encouraged to return for + * speed reasons. + * + * The calendardata is also optional. If it's not returned + * 'getCalendarObject' will be called later, which *is* expected to return + * calendardata. * * @param string $calendarId * @return array @@ -288,7 +298,12 @@ public function getCalendarObjects($calendarId) { } /** - * Returns information from a single calendar object, based on it's object uri. + * Returns information from a single calendar object, based on it's object + * uri. + * + * The returned array must have the same keys as getCalendarObjects. The + * 'calendardata' object is required here though, while it's not required + * for getCalendarObjects. * * @param string $calendarId * @param string $objectUri diff --git a/library/SabreDAV/lib/Sabre/CalDAV/Calendar.php b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Calendar.php similarity index 66% rename from library/SabreDAV/lib/Sabre/CalDAV/Calendar.php rename to modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Calendar.php index b99878b72..71fbdeb43 100644 --- a/library/SabreDAV/lib/Sabre/CalDAV/Calendar.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Calendar.php @@ -8,32 +8,32 @@ * * @package Sabre * @subpackage CalDAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ -class Sabre_CalDAV_Calendar implements Sabre_DAV_ICollection, Sabre_DAV_IProperties { +class Sabre_CalDAV_Calendar implements Sabre_DAV_ICollection, Sabre_DAV_IProperties, Sabre_DAVACL_IACL { /** * This is an array with calendar information * * @var array */ - private $calendarInfo; + protected $calendarInfo; /** * CalDAV backend * * @var Sabre_CalDAV_Backend_Abstract */ - private $caldavBackend; + protected $caldavBackend; /** - * Authentication backend + * Principal backend * - * @var Sabre_DAV_Auth_Backend_Abstract + * @var Sabre_DAVACL_IPrincipalBackend */ - private $authBackend; + protected $principalBackend; /** * Constructor @@ -42,10 +42,10 @@ class Sabre_CalDAV_Calendar implements Sabre_DAV_ICollection, Sabre_DAV_IPropert * @param array $calendarInfo * @return void */ - public function __construct(Sabre_DAV_Auth_Backend_Abstract $authBackend, Sabre_CalDAV_Backend_Abstract $caldavBackend,$calendarInfo) { + public function __construct(Sabre_DAVACL_IPrincipalBackend $principalBackend, Sabre_CalDAV_Backend_Abstract $caldavBackend, $calendarInfo) { $this->caldavBackend = $caldavBackend; - $this->authBackend = $authBackend; + $this->principalBackend = $principalBackend; $this->calendarInfo = $calendarInfo; @@ -70,7 +70,6 @@ public function getName() { */ public function updateProperties($mutations) { - if (!$this->hasPrivilege()) throw new Sabre_DAV_Exception_Forbidden('Permission denied to access this calendar'); return $this->caldavBackend->updateCalendar($this->calendarInfo['id'],$mutations); } @@ -85,13 +84,8 @@ public function getProperties($requestedProperties) { $response = array(); - if (!$this->hasPrivilege()) return array(); - foreach($requestedProperties as $prop) switch($prop) { - case '{DAV:}resourcetype' : - $response[$prop] = new Sabre_DAV_Property_ResourceType(array('{urn:ietf:params:xml:ns:caldav}calendar','{DAV:}collection')); - break; case '{urn:ietf:params:xml:ns:caldav}supported-calendar-data' : $response[$prop] = new Sabre_CalDAV_Property_SupportedCalendarData(); break; @@ -120,7 +114,6 @@ public function getProperties($requestedProperties) { */ public function getChild($name) { - if (!$this->hasPrivilege()) throw new Sabre_DAV_Exception_Forbidden('Permission denied to access this calendar'); $obj = $this->caldavBackend->getCalendarObject($this->calendarInfo['id'],$name); if (!$obj) throw new Sabre_DAV_Exception_FileNotFound('Calendar object not found'); return new Sabre_CalDAV_CalendarObject($this->caldavBackend,$this->calendarInfo,$obj); @@ -134,7 +127,6 @@ public function getChild($name) { */ public function getChildren() { - if (!$this->hasPrivilege()) throw new Sabre_DAV_Exception_Forbidden('Permission denied to access this calendar'); $objs = $this->caldavBackend->getCalendarObjects($this->calendarInfo['id']); $children = array(); foreach($objs as $obj) { @@ -152,7 +144,6 @@ public function getChildren() { */ public function childExists($name) { - if (!$this->hasPrivilege()) throw new Sabre_DAV_Exception_Forbidden('Permission denied to access this calendar'); $obj = $this->caldavBackend->getCalendarObject($this->calendarInfo['id'],$name); if (!$obj) return false; @@ -171,7 +162,6 @@ public function childExists($name) { */ public function createDirectory($name) { - if (!$this->hasPrivilege()) throw new Sabre_DAV_Exception_Forbidden('Permission denied to access this calendar'); throw new Sabre_DAV_Exception_MethodNotAllowed('Creating collections in calendar objects is not allowed'); } @@ -187,7 +177,6 @@ public function createDirectory($name) { */ public function createFile($name,$calendarData = null) { - if (!$this->hasPrivilege()) throw new Sabre_DAV_Exception_Forbidden('Permission denied to access this calendar'); $calendarData = stream_get_contents($calendarData); $supportedComponents = $this->calendarInfo['{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}supported-calendar-component-set']->getValue(); @@ -204,7 +193,6 @@ public function createFile($name,$calendarData = null) { */ public function delete() { - if (!$this->hasPrivilege()) throw new Sabre_DAV_Exception_Forbidden('Permission denied to access this calendar'); $this->caldavBackend->deleteCalendar($this->calendarInfo['id']); } @@ -218,7 +206,6 @@ public function delete() { */ public function setName($newName) { - if (!$this->hasPrivilege()) throw new Sabre_DAV_Exception_Forbidden('Permission denied to access this calendar'); throw new Sabre_DAV_Exception_MethodNotAllowed('Renaming calendars is not yet supported'); } @@ -235,20 +222,90 @@ public function getLastModified() { } /** - * Check if user has access. + * Returns the owner principal * - * This method does a check if the currently logged in user - * has permission to access this calendar. There is only read-write - * access, so you're in or you're out. + * This must be a url to a principal, or null if there's no owner * - * @return bool + * @return string|null + */ + public function getOwner() { + + return $this->calendarInfo['principaluri']; + + } + + /** + * Returns a group principal + * + * This must be a url to a principal, or null if there's no owner + * + * @return string|null */ - protected function hasPrivilege() { + public function getGroup() { - if (!$user = $this->authBackend->getCurrentUser()) return false; - if ($user['uri']!==$this->calendarInfo['principaluri']) return false; - return true; + return null; } + /** + * Returns a list of ACE's for this node. + * + * Each ACE has the following properties: + * * 'privilege', a string such as {DAV:}read or {DAV:}write. These are + * currently the only supported privileges + * * 'principal', a url to the principal who owns the node + * * 'protected' (optional), indicating that this ACE is not allowed to + * be updated. + * + * @return array + */ + public function getACL() { + + return array( + array( + 'privilege' => '{DAV:}read', + 'principal' => $this->calendarInfo['principaluri'], + 'protected' => true, + ), + array( + 'privilege' => '{DAV:}write', + 'principal' => $this->calendarInfo['principaluri'], + 'protected' => true, + ), + array( + 'privilege' => '{DAV:}read', + 'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write', + 'protected' => true, + ), + array( + 'privilege' => '{DAV:}write', + 'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write', + 'protected' => true, + ), + array( + 'privilege' => '{DAV:}read', + 'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-read', + 'protected' => true, + ), + + ); + + } + + /** + * Updates the ACL + * + * This method will receive a list of new ACE's. + * + * @param array $acl + * @return void + */ + public function setACL(array $acl) { + + throw new Sabre_DAV_Exception_MethodNotAllowed('Changing ACL is not yet supported'); + + } + + + } diff --git a/library/SabreDAV/lib/Sabre/CalDAV/CalendarObject.php b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/CalendarObject.php similarity index 55% rename from library/SabreDAV/lib/Sabre/CalDAV/CalendarObject.php rename to modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/CalendarObject.php index 937bab195..cda5ebc2c 100644 --- a/library/SabreDAV/lib/Sabre/CalDAV/CalendarObject.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/CalendarObject.php @@ -5,32 +5,32 @@ * * @package Sabre * @subpackage CalDAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ -class Sabre_CalDAV_CalendarObject extends Sabre_DAV_File implements Sabre_DAV_IProperties { +class Sabre_CalDAV_CalendarObject extends Sabre_DAV_File implements Sabre_DAV_IProperties, Sabre_DAVACL_IACL { /** * Sabre_CalDAV_Backend_Abstract * * @var array */ - private $caldavBackend; + protected $caldavBackend; /** * Array with information about this CalendarObject * * @var array */ - private $objectData; + protected $objectData; /** * Array with information about the containing calendar * * @var array */ - private $calendarInfo; + protected $calendarInfo; /** * Constructor @@ -64,6 +64,11 @@ public function getName() { */ public function get() { + // Pre-populating the 'calendardata' is optional, if we don't have it + // already we fetch it from the backend. + if (!isset($this->objectData['calendardata'])) { + $this->objectData = $this->calendarBackend->getCalendarObject($this->objectData['calendarid'], $this->objectData['uri']); + } return $this->objectData['calendardata']; } @@ -118,7 +123,11 @@ public function getContentType() { */ public function getETag() { - return '"' . md5($this->objectData['calendardata']). '"'; + if (isset($this->objectData['etag'])) { + return $this->objectData['etag']; + } else { + return '"' . md5($this->get()). '"'; + } } @@ -172,5 +181,92 @@ public function getSize() { return strlen($this->objectData['calendardata']); } + + /** + * Returns the owner principal + * + * This must be a url to a principal, or null if there's no owner + * + * @return string|null + */ + public function getOwner() { + + return $this->calendarInfo['principaluri']; + + } + + /** + * Returns a group principal + * + * This must be a url to a principal, or null if there's no owner + * + * @return string|null + */ + public function getGroup() { + + return null; + + } + + /** + * Returns a list of ACE's for this node. + * + * Each ACE has the following properties: + * * 'privilege', a string such as {DAV:}read or {DAV:}write. These are + * currently the only supported privileges + * * 'principal', a url to the principal who owns the node + * * 'protected' (optional), indicating that this ACE is not allowed to + * be updated. + * + * @return array + */ + public function getACL() { + + return array( + array( + 'privilege' => '{DAV:}read', + 'principal' => $this->calendarInfo['principaluri'], + 'protected' => true, + ), + array( + 'privilege' => '{DAV:}write', + 'principal' => $this->calendarInfo['principaluri'], + 'protected' => true, + ), + array( + 'privilege' => '{DAV:}read', + 'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write', + 'protected' => true, + ), + array( + 'privilege' => '{DAV:}write', + 'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write', + 'protected' => true, + ), + array( + 'privilege' => '{DAV:}read', + 'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-read', + 'protected' => true, + ), + + ); + + } + + /** + * Updates the ACL + * + * This method will receive a list of new ACE's. + * + * @param array $acl + * @return void + */ + public function setACL(array $acl) { + + throw new Sabre_DAV_Exception_MethodNotAllowed('Changing ACL is not yet supported'); + + } + + } diff --git a/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/CalendarRootNode.php b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/CalendarRootNode.php new file mode 100644 index 000000000..5c9b37e7d --- /dev/null +++ b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/CalendarRootNode.php @@ -0,0 +1,68 @@ +caldavBackend = $caldavBackend; + + } + + /** + * Returns the nodename + * + * We're overriding this, because the default will be the 'principalPrefix', + * and we want it to be Sabre_CalDAV_Plugin::CALENDAR_ROOT + * + * @return void + */ + public function getName() { + + return Sabre_CalDAV_Plugin::CALENDAR_ROOT; + + } + + /** + * This method returns a node for a principal. + * + * The passed array contains principal information, and is guaranteed to + * at least contain a uri item. Other properties may or may not be + * supplied by the authentication backend. + * + * @param array $principal + * @return Sabre_DAV_INode + */ + public function getChildForPrincipal(array $principal) { + + return new Sabre_CalDAV_UserCalendars($this->principalBackend, $this->caldavBackend, $principal['uri']); + + } + +} diff --git a/library/SabreDAV/lib/Sabre/CalDAV/Exception/InvalidICalendarObject.php b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Exception/InvalidICalendarObject.php similarity index 87% rename from library/SabreDAV/lib/Sabre/CalDAV/Exception/InvalidICalendarObject.php rename to modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Exception/InvalidICalendarObject.php index 24873f5d2..656b7286a 100644 --- a/library/SabreDAV/lib/Sabre/CalDAV/Exception/InvalidICalendarObject.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Exception/InvalidICalendarObject.php @@ -8,7 +8,7 @@ * * @package Sabre * @subpackage CalDAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/ICSExportPlugin.php b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/ICSExportPlugin.php new file mode 100644 index 000000000..4e2c6eb93 --- /dev/null +++ b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/ICSExportPlugin.php @@ -0,0 +1,124 @@ +server = $server; + $this->server->subscribeEvent('beforeMethod',array($this,'beforeMethod'), 90); + + } + + /** + * 'beforeMethod' event handles. This event handles intercepts GET requests ending + * with ?export + * + * @param string $method + * @param string $uri + * @return void + */ + 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 Sabre_CalDAV_Calendar)) return; + + $this->server->httpResponse->setHeader('Content-Type','text/calendar'); + $this->server->httpResponse->sendStatus(200); + $this->server->httpResponse->sendBody($this->generateICS($this->server->tree->getChildren($uri))); + + // Returning false to break the event chain + return false; + + } + + /** + * Merges all calendar objects, and builds one big ics export + * + * @param array $nodes + * @return void + */ + public function generateICS(array $nodes) { + + $calendar = new Sabre_VObject_Component('vcalendar'); + $calendar->version = '2.0'; + $calendar->prodid = '-//SabreDAV//SabreDAV ' . Sabre_DAV_Version::VERSION . '//EN'; + $calendar->calscale = 'GREGORIAN'; + + $collectedTimezones = array(); + + $timezones = array(); + $objects = array(); + + foreach($nodes as $node) { + + $nodeData = $node->get(); + $nodeComp = Sabre_VObject_Reader::read($nodeData); + + foreach($nodeComp->children() as $child) { + + switch($child->name) { + case 'VEVENT' : + case 'VTODO' : + case 'VJOURNAL' : + $objects[] = $child; + break; + + // VTIMEZONE is special, because we need to filter out the duplicates + case 'VTIMEZONE' : + // Naively just checking tzid. + if (in_array((string)$child->TZID, $collectedTimezones)) continue; + + $timezones[] = $child; + $collectedTimezones[] = $child->TZID; + break; + + + } + + + } + + + } + + foreach($timezones as $tz) $calendar->add($tz); + foreach($objects as $obj) $calendar->add($obj); + + return $calendar->serialize(); + + } + +} diff --git a/library/SabreDAV/lib/Sabre/CalDAV/ICalendarUtil.php b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/ICalendarUtil.php similarity index 95% rename from library/SabreDAV/lib/Sabre/CalDAV/ICalendarUtil.php rename to modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/ICalendarUtil.php index 3772cc6ab..fbfef397a 100644 --- a/library/SabreDAV/lib/Sabre/CalDAV/ICalendarUtil.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/ICalendarUtil.php @@ -3,11 +3,15 @@ /** * This class contains several utilities related to the ICalendar (rfc2445) format * + * This class is now deprecated, and won't be further maintained. Please use + * the Sabre_VObject package for your ics parsing needs. + * * @package Sabre * @subpackage CalDAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License + * @deprecated Use Sabre_VObject instead. */ class Sabre_CalDAV_ICalendarUtil { @@ -36,9 +40,6 @@ static function validateICalendarObject($icalData, array $allowedComponents) { $test = $xcal->xpath('/cal:iCalendar/cal:vcalendar/cal:' . $component); if (is_array($test)) $componentsFound = array_merge($componentsFound, $test); } - if (count($componentsFound)>1) { - throw new Sabre_CalDAV_Exception_InvalidICalendarObject('Only 1 of VEVENT, VTODO, VJOURNAL or VFREEBUSY may be specified per calendar object'); - } if (count($componentsFound)<1) { throw new Sabre_CalDAV_Exception_InvalidICalendarObject('One VEVENT, VTODO, VJOURNAL or VFREEBUSY must be specified. 0 found.'); } diff --git a/library/SabreDAV/lib/Sabre/CalDAV/Plugin.php b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Plugin.php similarity index 82% rename from library/SabreDAV/lib/Sabre/CalDAV/Plugin.php rename to modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Plugin.php index 7a29891bb..c034950d0 100644 --- a/library/SabreDAV/lib/Sabre/CalDAV/Plugin.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Plugin.php @@ -8,7 +8,7 @@ * * @package Sabre * @subpackage CalDAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ @@ -83,7 +83,44 @@ public function getHTTPMethods($uri) { */ public function getFeatures() { - return array('calendar-access'); + return array('calendar-access', 'calendar-proxy'); + + } + + /** + * Returns a plugin name. + * + * Using this name other plugins will be able to access other plugins + * using Sabre_DAV_Server::getPlugin + * + * @return string + */ + public function getPluginName() { + + return 'caldav'; + + } + + /** + * Returns a list of reports this plugin supports. + * + * This will be used in the {DAV:}supported-report-set property. + * Note that you still need to subscribe to the 'report' event to actually + * implement them + * + * @param string $uri + * @return array + */ + public function getSupportedReportSet($uri) { + + $node = $this->server->tree->getNodeForPath($uri); + if ($node instanceof Sabre_CalDAV_Calendar || $node instanceof Sabre_CalDAV_CalendarObject) { + return array( + '{' . self::NS_CALDAV . '}calendar-multiget', + '{' . self::NS_CALDAV . '}calendar-query', + ); + } + return array(); } @@ -106,6 +143,10 @@ public function initialize(Sabre_DAV_Server $server) { $server->propertyMap['{' . self::NS_CALDAV . '}supported-calendar-component-set'] = 'Sabre_CalDAV_Property_SupportedCalendarComponentSet'; + $server->resourceTypeMapping['Sabre_CalDAV_Calendar'] = '{urn:ietf:params:xml:ns:caldav}calendar'; + $server->resourceTypeMapping['Sabre_CalDAV_Principal_ProxyRead'] = '{http://calendarserver.org/ns/}calendar-proxy-read'; + $server->resourceTypeMapping['Sabre_CalDAV_Principal_ProxyWrite'] = '{http://calendarserver.org/ns/}calendar-proxy-write'; + array_push($server->protectedProperties, '{' . self::NS_CALDAV . '}supported-calendar-component-set', @@ -119,7 +160,12 @@ public function initialize(Sabre_DAV_Server $server) { '{' . self::NS_CALDAV . '}supported-collation-set', // scheduling extension - '{' . self::NS_CALDAV . '}calendar-user-address-set' + '{' . self::NS_CALDAV . '}calendar-user-address-set', + + // CalendarServer extensions + '{' . self::NS_CALENDARSERVER . '}getctag', + '{' . self::NS_CALENDARSERVER . '}calendar-proxy-read-for', + '{' . self::NS_CALENDARSERVER . '}calendar-proxy-write-for' ); } @@ -156,8 +202,6 @@ public function report($reportName,$dom) { case '{'.self::NS_CALDAV.'}calendar-query' : $this->calendarQueryReport($dom); return false; - default : - return true; } @@ -181,16 +225,21 @@ public function httpMkCalendar($uri) { //} $body = $this->server->httpRequest->getBody(true); - $dom = Sabre_DAV_XMLUtil::loadDOMDocument($body); - $properties = array(); - foreach($dom->firstChild->childNodes as $child) { - if (Sabre_DAV_XMLUtil::toClarkNotation($child)!=='{DAV:}set') continue; - foreach(Sabre_DAV_XMLUtil::parseProperties($child,$this->server->propertyMap) as $k=>$prop) { - $properties[$k] = $prop; + if ($body) { + + $dom = Sabre_DAV_XMLUtil::loadDOMDocument($body); + + + foreach($dom->firstChild->childNodes as $child) { + + if (Sabre_DAV_XMLUtil::toClarkNotation($child)!=='{DAV:}set') continue; + foreach(Sabre_DAV_XMLUtil::parseProperties($child,$this->server->propertyMap) as $k=>$prop) { + $properties[$k] = $prop; + } + } - } $resourceType = array('{DAV:}collection','{urn:ietf:params:xml:ns:caldav}calendar'); @@ -216,7 +265,8 @@ public function afterGetProperties($path, &$properties) { // Find out if we are currently looking at a principal resource $currentNode = $this->server->tree->getNodeForPath($path); - if ($currentNode instanceof Sabre_DAV_Auth_Principal) { + + if ($currentNode instanceof Sabre_DAVACL_IPrincipal) { // calendar-home-set property $calHome = '{' . self::NS_CALDAV . '}calendar-home-set'; @@ -227,37 +277,54 @@ public function afterGetProperties($path, &$properties) { $properties[200][$calHome] = new Sabre_DAV_Property_Href($calendarHomePath); } + // calendar-user-address-set property $calProp = '{' . self::NS_CALDAV . '}calendar-user-address-set'; if (array_key_exists($calProp,$properties[404])) { - // Do we have an email address? - $props = $currentNode->getProperties(array('{http://sabredav.org/ns}email-address')); - if (isset($props['{http://sabredav.org/ns}email-address'])) { - $email = $props['{http://sabredav.org/ns}email-address']; - } else { - // We're going to make up an emailaddress - $email = $currentNode->getName() . '.sabredav@' . $this->server->httpRequest->getHeader('host'); - } - $properties[200][$calProp] = new Sabre_DAV_Property_Href('mailto:' . $email, false); + $addresses = $currentNode->getAlternateUriSet(); + $addresses[] = $this->server->getBaseUri() . $currentNode->getPrincipalUrl(); + $properties[200][$calProp] = new Sabre_DAV_Property_HrefList($addresses, false); unset($properties[404][$calProp]); } + // These two properties are shortcuts for ical to easily find + // other principals this principal has access to. + $propRead = '{' . self::NS_CALENDARSERVER . '}calendar-proxy-read-for'; + $propWrite = '{' . self::NS_CALENDARSERVER . '}calendar-proxy-write-for'; + if (array_key_exists($propRead,$properties[404]) || array_key_exists($propWrite,$properties[404])) { + $membership = $currentNode->getGroupMembership(); + $readList = array(); + $writeList = array(); + + foreach($membership as $group) { + + $groupNode = $this->server->tree->getNodeForPath($group); + + // If the node is either ap proxy-read or proxy-write + // group, we grab the parent principal and add it to the + // list. + if ($groupNode instanceof Sabre_CalDAV_Principal_ProxyRead) { + list($readList[]) = Sabre_DAV_URLUtil::splitPath($group); + } + if ($groupNode instanceof Sabre_CalDAV_Principal_ProxyWrite) { + list($writeList[]) = Sabre_DAV_URLUtil::splitPath($group); + } - } + } + if (array_key_exists($propRead,$properties[404])) { + unset($properties[404][$propRead]); + $properties[200][$propRead] = new Sabre_DAV_Property_HrefList($readList); + } + if (array_key_exists($propWrite,$properties[404])) { + unset($properties[404][$propWrite]); + $properties[200][$propWrite] = new Sabre_DAV_Property_HrefList($writeList); + } - if ($currentNode instanceof Sabre_CalDAV_Calendar || $currentNode instanceof Sabre_CalDAV_CalendarObject) { - if (array_key_exists('{DAV:}supported-report-set', $properties[200])) { - $properties[200]['{DAV:}supported-report-set']->addReport(array( - '{' . self::NS_CALDAV . '}calendar-multiget', - '{' . self::NS_CALDAV . '}calendar-query', - // '{' . self::NS_CALDAV . '}supported-collation-set', - // '{' . self::NS_CALDAV . '}free-busy-query', - )); } - } + } } @@ -391,24 +458,28 @@ public function validateFilters($calendarData,$filters) { if ($result===false) return false; break; case 'vjournal' : + case 'vfreebusy' : + case 'valarm' : // TODO: not implemented break; + + /* + + case 'vjournal' : $result = $this->validateTimeRangeFilterForJournal($xml,$xpath,$filter); if ($result===false) return false; break; case 'vfreebusy' : - // TODO: not implemented - break; $result = $this->validateTimeRangeFilterForFreeBusy($xml,$xpath,$filter); if ($result===false) return false; break; case 'valarm' : - // TODO: not implemented - break; $result = $this->validateTimeRangeFilterForAlarm($xml,$xpath,$filter); if ($result===false) return false; break; + */ + } } @@ -427,6 +498,14 @@ public function validateFilters($calendarData,$filters) { } + /** + * Checks whether a time-range filter matches an event. + * + * @param SimpleXMLElement $xml Event as xml object + * @param string $currentXPath XPath to check + * @param array $currentFilter Filter information + * @return void + */ private function validateTimeRangeFilterForEvent(SimpleXMLElement $xml,$currentXPath,array $currentFilter) { // Grabbing the DTSTART property @@ -467,7 +546,7 @@ private function validateTimeRangeFilterForEvent(SimpleXMLElement $xml,$currentX $tz = null; } - // Since the VALUE parameter of both DTSTART and DTEND must be the same + // Since the VALUE prameter of both DTSTART and DTEND must be the same // we can assume we don't need to check the VALUE paramter of DTEND. if ($isDateTime) { $dtend = Sabre_CalDAV_XMLUtil::parseICalendarDateTime((string)$xdtend[0],$tz); @@ -510,9 +589,13 @@ private function validateTimeRangeFilterForEvent(SimpleXMLElement $xml,$currentX $dtend->modify('+1 day'); } } + // TODO: we need to properly parse RRULE's, but it's very difficult. + // For now, we're always returning events if they have an RRULE at all. + $rrule = $xml->xpath($currentXPath.'/c:rrule'); + $hasRrule = (count($rrule))>0; if (!is_null($currentFilter['time-range']['start']) && $currentFilter['time-range']['start'] >= $dtend) return false; - if (!is_null($currentFilter['time-range']['end']) && $currentFilter['time-range']['end'] <= $dtstart) return false; + if (!is_null($currentFilter['time-range']['end']) && $currentFilter['time-range']['end'] <= $dtstart && !$hasRrule) return false; return true; } diff --git a/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Principal/Collection.php b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Principal/Collection.php new file mode 100644 index 000000000..13435b244 --- /dev/null +++ b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Principal/Collection.php @@ -0,0 +1,31 @@ +principalBackend, $principalInfo); + + } + +} diff --git a/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Principal/ProxyRead.php b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Principal/ProxyRead.php new file mode 100644 index 000000000..f531d85d1 --- /dev/null +++ b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Principal/ProxyRead.php @@ -0,0 +1,178 @@ +principalInfo = $principalInfo; + $this->principalBackend = $principalBackend; + + } + + /** + * Returns this principals name. + * + * @return string + */ + public function getName() { + + return 'calendar-proxy-read'; + + } + + /** + * Returns the last modification time + * + * @return null + */ + public function getLastModified() { + + return null; + + } + + /** + * Deletes the current node + * + * @throws Sabre_DAV_Exception_Forbidden + * @return void + */ + public function delete() { + + throw new Sabre_DAV_Exception_Forbidden('Permission denied to delete node'); + + } + + /** + * Renames the node + * + * @throws Sabre_DAV_Exception_Forbidden + * @param string $name The new name + * @return void + */ + public function setName($name) { + + throw new Sabre_DAV_Exception_Forbidden('Permission denied to rename file'); + + } + + + /** + * Returns a list of altenative urls for a principal + * + * This can for example be an email address, or ldap url. + * + * @return array + */ + public function getAlternateUriSet() { + + return array(); + + } + + /** + * Returns the full principal url + * + * @return string + */ + public function getPrincipalUrl() { + + return $this->principalInfo['uri'] . '/' . $this->getName(); + + } + + /** + * Returns the list of group members + * + * If this principal is a group, this function should return + * all member principal uri's for the group. + * + * @return array + */ + public function getGroupMemberSet() { + + return $this->principalBackend->getGroupMemberSet($this->getPrincipalUrl()); + + } + + /** + * Returns the list of groups this principal is member of + * + * If this principal is a member of a (list of) groups, this function + * should return a list of principal uri's for it's members. + * + * @return array + */ + public function getGroupMembership() { + + return $this->principalBackend->getGroupMembership($this->getPrincipalUrl()); + + } + + /** + * Sets a list of group members + * + * If this principal is a group, this method sets all the group members. + * The list of members is always overwritten, never appended to. + * + * This method should throw an exception if the members could not be set. + * + * @param array $principals + * @return void + */ + public function setGroupMemberSet(array $principals) { + + $this->principalBackend->setGroupMemberSet($this->getPrincipalUrl(), $principals); + + } + + /** + * Returns the displayname + * + * This should be a human readable name for the principal. + * If none is available, return the nodename. + * + * @return string + */ + public function getDisplayName() { + + return $this->getName(); + + } + +} diff --git a/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Principal/ProxyWrite.php b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Principal/ProxyWrite.php new file mode 100644 index 000000000..4d8face20 --- /dev/null +++ b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Principal/ProxyWrite.php @@ -0,0 +1,178 @@ +principalInfo = $principalInfo; + $this->principalBackend = $principalBackend; + + } + + /** + * Returns this principals name. + * + * @return string + */ + public function getName() { + + return 'calendar-proxy-write'; + + } + + /** + * Returns the last modification time + * + * @return null + */ + public function getLastModified() { + + return null; + + } + + /** + * Deletes the current node + * + * @throws Sabre_DAV_Exception_Forbidden + * @return void + */ + public function delete() { + + throw new Sabre_DAV_Exception_Forbidden('Permission denied to delete node'); + + } + + /** + * Renames the node + * + * @throws Sabre_DAV_Exception_Forbidden + * @param string $name The new name + * @return void + */ + public function setName($name) { + + throw new Sabre_DAV_Exception_Forbidden('Permission denied to rename file'); + + } + + + /** + * Returns a list of altenative urls for a principal + * + * This can for example be an email address, or ldap url. + * + * @return array + */ + public function getAlternateUriSet() { + + return array(); + + } + + /** + * Returns the full principal url + * + * @return string + */ + public function getPrincipalUrl() { + + return $this->principalInfo['uri'] . '/' . $this->getName(); + + } + + /** + * Returns the list of group members + * + * If this principal is a group, this function should return + * all member principal uri's for the group. + * + * @return array + */ + public function getGroupMemberSet() { + + return $this->principalBackend->getGroupMemberSet($this->getPrincipalUrl()); + + } + + /** + * Returns the list of groups this principal is member of + * + * If this principal is a member of a (list of) groups, this function + * should return a list of principal uri's for it's members. + * + * @return array + */ + public function getGroupMembership() { + + return $this->principalBackend->getGroupMembership($this->getPrincipalUrl()); + + } + + /** + * Sets a list of group members + * + * If this principal is a group, this method sets all the group members. + * The list of members is always overwritten, never appended to. + * + * This method should throw an exception if the members could not be set. + * + * @param array $principals + * @return void + */ + public function setGroupMemberSet(array $principals) { + + $this->principalBackend->setGroupMemberSet($this->getPrincipalUrl(), $principals); + + } + + /** + * Returns the displayname + * + * This should be a human readable name for the principal. + * If none is available, return the nodename. + * + * @return string + */ + public function getDisplayName() { + + return $this->getName(); + + } + +} diff --git a/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Principal/User.php b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Principal/User.php new file mode 100644 index 000000000..034629b89 --- /dev/null +++ b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Principal/User.php @@ -0,0 +1,122 @@ +principalBackend, $this->principalProperties); + + if ($name === 'calendar-proxy-write') + return new Sabre_CalDAV_Principal_ProxyWrite($this->principalBackend, $this->principalProperties); + + throw new Sabre_DAV_Exception_FileNotFound('Node with name ' . $name . ' was not found'); + + } + + /** + * Returns an array with all the child nodes + * + * @return Sabre_DAV_INode[] + */ + public function getChildren() { + + return array( + new Sabre_CalDAV_Principal_ProxyRead($this->principalBackend, $this->principalProperties), + new Sabre_CalDAV_Principal_ProxyWrite($this->principalBackend, $this->principalProperties), + ); + + } + + /** + * Checks if a child-node with the specified name exists + * + * @return bool + */ + public function childExists($name) { + + return $name === 'calendar-proxy-read' || $name === 'calendar-proxy-write'; + + } + + /** + * Returns a list of ACE's for this node. + * + * Each ACE has the following properties: + * * 'privilege', a string such as {DAV:}read or {DAV:}write. These are + * currently the only supported privileges + * * 'principal', a url to the principal who owns the node + * * 'protected' (optional), indicating that this ACE is not allowed to + * be updated. + * + * @return array + */ + public function getACL() { + + return array( + array( + 'privilege' => '{DAV:}read', + 'principal' => $this->principalProperties['uri'], + 'protected' => true, + ), + array( + 'privilege' => '{DAV:}read', + 'principal' => $this->principalProperties['uri'] . '/calendar-proxy-read', + 'protected' => true, + ), + array( + 'privilege' => '{DAV:}read', + 'principal' => $this->principalProperties['uri'] . '/calendar-proxy-write', + 'protected' => true, + ), + ); + + } + +} diff --git a/library/SabreDAV/lib/Sabre/CalDAV/Property/SupportedCalendarComponentSet.php b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Property/SupportedCalendarComponentSet.php similarity index 96% rename from library/SabreDAV/lib/Sabre/CalDAV/Property/SupportedCalendarComponentSet.php rename to modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Property/SupportedCalendarComponentSet.php index 5a1862d03..1bbaca6b8 100644 --- a/library/SabreDAV/lib/Sabre/CalDAV/Property/SupportedCalendarComponentSet.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Property/SupportedCalendarComponentSet.php @@ -9,7 +9,7 @@ * * @package Sabre * @subpackage CalDAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/CalDAV/Property/SupportedCalendarData.php b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Property/SupportedCalendarData.php similarity index 94% rename from library/SabreDAV/lib/Sabre/CalDAV/Property/SupportedCalendarData.php rename to modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Property/SupportedCalendarData.php index 3e9a9d765..5010ee6d5 100644 --- a/library/SabreDAV/lib/Sabre/CalDAV/Property/SupportedCalendarData.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Property/SupportedCalendarData.php @@ -9,7 +9,7 @@ * * @package Sabre * @subpackage CalDAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/CalDAV/Property/SupportedCollationSet.php b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Property/SupportedCollationSet.php similarity index 73% rename from library/SabreDAV/lib/Sabre/CalDAV/Property/SupportedCollationSet.php rename to modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Property/SupportedCollationSet.php index 2f96591b7..515efb645 100644 --- a/library/SabreDAV/lib/Sabre/CalDAV/Property/SupportedCollationSet.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Property/SupportedCollationSet.php @@ -8,13 +8,20 @@ * * @package Sabre * @subpackage CalDAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ class Sabre_CalDAV_Property_SupportedCollationSet extends Sabre_DAV_Property { - function serialize(Sabre_DAV_Server $server,DOMElement $node) { + /** + * Serializes the property in a DOM document + * + * @param Sabre_DAV_Server $server + * @param DOMElement $node + * @return void + */ + public function serialize(Sabre_DAV_Server $server,DOMElement $node) { $doc = $node->ownerDocument; diff --git a/library/SabreDAV/lib/Sabre/CalDAV/Server.php b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Server.php similarity index 51% rename from library/SabreDAV/lib/Sabre/CalDAV/Server.php rename to modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Server.php index 33f7a39c1..969d69c62 100644 --- a/library/SabreDAV/lib/Sabre/CalDAV/Server.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Server.php @@ -6,15 +6,29 @@ * This script is a convenience script. It quickly sets up a WebDAV server * with caldav and ACL support, and it creates the root 'principals' and * 'calendars' collections. + * + * Note that if you plan to do anything moderately complex, you are advised to + * not subclass this server, but use Sabre_DAV_Server directly instead. This + * class is nothing more than an 'easy setup'. * * @package Sabre * @subpackage CalDAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ class Sabre_CalDAV_Server extends Sabre_DAV_Server { + /** + * The authentication realm + * + * Note that if this changes, the hashes in the auth backend must also + * be recalculated. + * + * @var string + */ + public $authRealm = 'SabreDAV'; + /** * Sets up the object. A PDO object must be passed to setup all the backends. * @@ -25,23 +39,24 @@ public function __construct(PDO $pdo) { /* Backends */ $authBackend = new Sabre_DAV_Auth_Backend_PDO($pdo); $calendarBackend = new Sabre_CalDAV_Backend_PDO($pdo); + $principalBackend = new Sabre_DAVACL_PrincipalBackend_PDO($pdo); /* Directory structure */ - $root = new Sabre_DAV_SimpleDirectory('root'); - $principals = new Sabre_DAV_Auth_PrincipalCollection($authBackend); - $root->addChild($principals); - $calendars = new Sabre_CalDAV_CalendarRootNode($authBackend, $calendarBackend); - $root->addChild($calendars); - - $objectTree = new Sabre_DAV_ObjectTree($root); - + $tree = array( + new Sabre_CalDAV_Principal_Collection($principalBackend), + new Sabre_CalDAV_CalendarRootNode($principalBackend, $calendarBackend), + ); + /* Initializing server */ - parent::__construct($objectTree); + parent::__construct($tree); /* Server Plugins */ - $authPlugin = new Sabre_DAV_Auth_Plugin($authBackend,'SabreDAV'); + $authPlugin = new Sabre_DAV_Auth_Plugin($authBackend,$this->authRealm); $this->addPlugin($authPlugin); + $aclPlugin = new Sabre_DAVACL_Plugin(); + $this->addPlugin($aclPlugin); + $caldavPlugin = new Sabre_CalDAV_Plugin(); $this->addPlugin($caldavPlugin); diff --git a/library/SabreDAV/lib/Sabre/CalDAV/UserCalendars.php b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/UserCalendars.php similarity index 53% rename from library/SabreDAV/lib/Sabre/CalDAV/UserCalendars.php rename to modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/UserCalendars.php index c81b70bad..f52d65e9a 100644 --- a/library/SabreDAV/lib/Sabre/CalDAV/UserCalendars.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/UserCalendars.php @@ -5,45 +5,45 @@ * * @package Sabre * @subpackage CalDAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ -class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection { +class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre_DAVACL_IACL { /** - * Authentication backend + * Principal backend * - * @var Sabre_DAV_Auth_Backend_Abstract + * @var Sabre_DAVACL_IPrincipalBackend */ - protected $authBackend; + protected $principalBackend; /** - * Array with user information + * CalDAV backend * - * @var array + * @var Sabre_CalDAV_Backend_Abstract */ - protected $userUri; + protected $caldavBackend; /** - * CalDAV backend + * Principal information * - * @var Sabre_CalDAV_Backend_Abstract + * @var array */ - protected $caldavBackend; + protected $principalInfo; /** * Constructor * - * @param Sabre_DAV_Auth_Backend_Abstract $authBackend + * @param Sabre_DAVACL_IPrincipalBackend $principalBackend * @param Sabre_CalDAV_Backend_Abstract $caldavBackend * @param mixed $userUri */ - public function __construct(Sabre_DAV_Auth_Backend_Abstract $authBackend, Sabre_CalDAV_Backend_Abstract $caldavBackend, $userUri) { + public function __construct(Sabre_DAVACL_IPrincipalBackend $principalBackend, Sabre_CalDAV_Backend_Abstract $caldavBackend, $userUri) { - $this->authBackend = $authBackend; + $this->principalBackend = $principalBackend; $this->caldavBackend = $caldavBackend; - $this->userUri = $userUri; + $this->principalInfo = $principalBackend->getPrincipalByPath($userUri); } @@ -54,7 +54,7 @@ public function __construct(Sabre_DAV_Auth_Backend_Abstract $authBackend, Sabre_ */ public function getName() { - list(,$name) = Sabre_DAV_URLUtil::splitPath($this->userUri); + list(,$name) = Sabre_DAV_URLUtil::splitPath($this->principalInfo['uri']); return $name; } @@ -165,10 +165,10 @@ public function childExists($name) { */ public function getChildren() { - $calendars = $this->caldavBackend->getCalendarsForUser($this->userUri); + $calendars = $this->caldavBackend->getCalendarsForUser($this->principalInfo['uri']); $objs = array(); foreach($calendars as $calendar) { - $objs[] = new Sabre_CalDAV_Calendar($this->authBackend, $this->caldavBackend, $calendar); + $objs[] = new Sabre_CalDAV_Calendar($this->principalBackend, $this->caldavBackend, $calendar); } return $objs; @@ -186,8 +186,95 @@ public function createExtendedCollection($name, array $resourceType, array $prop if (!in_array('{urn:ietf:params:xml:ns:caldav}calendar',$resourceType) || count($resourceType)!==2) { throw new Sabre_DAV_Exception_InvalidResourceType('Unknown resourceType for this collection'); } - $this->caldavBackend->createCalendar($this->userUri, $name, $properties); + $this->caldavBackend->createCalendar($this->principalInfo['uri'], $name, $properties); + + } + + /** + * Returns the owner principal + * + * This must be a url to a principal, or null if there's no owner + * + * @return string|null + */ + public function getOwner() { + + return $this->principalInfo['uri']; } + /** + * Returns a group principal + * + * This must be a url to a principal, or null if there's no owner + * + * @return string|null + */ + public function getGroup() { + + return null; + + } + + /** + * Returns a list of ACE's for this node. + * + * Each ACE has the following properties: + * * 'privilege', a string such as {DAV:}read or {DAV:}write. These are + * currently the only supported privileges + * * 'principal', a url to the principal who owns the node + * * 'protected' (optional), indicating that this ACE is not allowed to + * be updated. + * + * @return array + */ + public function getACL() { + + return array( + array( + 'privilege' => '{DAV:}read', + 'principal' => $this->principalInfo['uri'], + 'protected' => true, + ), + array( + 'privilege' => '{DAV:}write', + 'principal' => $this->principalInfo['uri'], + 'protected' => true, + ), + array( + 'privilege' => '{DAV:}read', + 'principal' => $this->principalInfo['uri'] . '/calendar-proxy-write', + 'protected' => true, + ), + array( + 'privilege' => '{DAV:}write', + 'principal' => $this->principalInfo['uri'] . '/calendar-proxy-write', + 'protected' => true, + ), + array( + 'privilege' => '{DAV:}read', + 'principal' => $this->principalInfo['uri'] . '/calendar-proxy-read', + 'protected' => true, + ), + + ); + + } + + /** + * Updates the ACL + * + * This method will receive a list of new ACE's. + * + * @param array $acl + * @return void + */ + public function setACL(array $acl) { + + throw new Sabre_DAV_Exception_MethodNotAllowed('Changing ACL is not yet supported'); + + } + + + } diff --git a/library/SabreDAV/lib/Sabre/CalDAV/Version.php b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Version.php similarity index 76% rename from library/SabreDAV/lib/Sabre/CalDAV/Version.php rename to modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Version.php index d7b2e6aff..2ce00cd42 100644 --- a/library/SabreDAV/lib/Sabre/CalDAV/Version.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/Version.php @@ -5,7 +5,7 @@ * * @package Sabre * @subpackage CalDAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ @@ -14,11 +14,11 @@ class Sabre_CalDAV_Version { /** * Full version number */ - const VERSION = '1.3.0'; + const VERSION = '1.4.2'; /** * Stability : alpha, beta, stable */ - const STABILITY = 'stable'; + const STABILITY = 'beta'; } diff --git a/library/SabreDAV/lib/Sabre/CalDAV/XMLUtil.php b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/XMLUtil.php similarity index 97% rename from library/SabreDAV/lib/Sabre/CalDAV/XMLUtil.php rename to modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/XMLUtil.php index dfa58a0a7..bf349a36a 100644 --- a/library/SabreDAV/lib/Sabre/CalDAV/XMLUtil.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/CalDAV/XMLUtil.php @@ -8,7 +8,7 @@ * * @package Sabre * @subpackage CalDAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ @@ -100,7 +100,7 @@ static public function parseCalendarQueryFilters($domNode,$basePath = '/c:iCalen if (!$collation) $collation = 'i;ascii-casemap'; $filters[$basePath]['text-match'] = array( - 'collation' => $collation, + 'collation' => ($collation == 'default'?'i;ascii-casemap':$collation), 'negate-condition' => $child->getAttribute('negate-condition')==='yes', 'value' => $child->nodeValue, ); diff --git a/library/SabreDAV/lib/Sabre/DAV/Auth/Backend/AbstractBasic.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Auth/Backend/AbstractBasic.php similarity index 66% rename from library/SabreDAV/lib/Sabre/DAV/Auth/Backend/AbstractBasic.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Auth/Backend/AbstractBasic.php index e81ca00f2..11bab8c7a 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Auth/Backend/AbstractBasic.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Auth/Backend/AbstractBasic.php @@ -4,43 +4,40 @@ * * This class can be used by authentication objects wishing to use HTTP Basic * Most of the digest logic is handled, implementors just need to worry about - * the authenticateInternal and getUserInfo methods + * the validateUserPass method. * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author James David Low (http://jameslow.com/) * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ -abstract class Sabre_DAV_Auth_Backend_AbstractBasic extends Sabre_DAV_Auth_Backend_Abstract { +abstract class Sabre_DAV_Auth_Backend_AbstractBasic implements Sabre_DAV_Auth_IBackend { /** - * This variable holds information about the currently - * logged in user. + * This variable holds the currently logged in username. * - * @var array|null + * @var string|null */ protected $currentUser; /** * Validates a username and password * - * If the username and password were correct, this method must return - * an array with at least a 'uri' key. + * This method should return true or false depending on if login + * succeeded. * - * If the credentials are incorrect, this method must return false. - * - * @return bool|array + * @return bool */ abstract protected function validateUserPass($username, $password); /** - * Returns information about the currently logged in user. + * Returns information about the currently logged in username. * * If nobody is currently logged in, this method should return null. * - * @return array|null + * @return string|null */ public function getCurrentUser() { return $this->currentUser; @@ -69,14 +66,11 @@ public function authenticate(Sabre_DAV_Server $server,$realm) { } // Authenticates the user - if (!($userData = $this->validateUserPass($userpass[0],$userpass[1]))) { + if (!$this->validateUserPass($userpass[0],$userpass[1])) { $auth->requireLogin(); throw new Sabre_DAV_Exception_NotAuthenticated('Username or password does not match'); } - if (!isset($userData['uri'])) { - throw new Sabre_DAV_Exception('The returned array from validateUserPass must contain at a uri element'); - } - $this->currentUser = $userData; + $this->currentUser = $userpass[0]; return true; } diff --git a/library/SabreDAV/lib/Sabre/DAV/Auth/Backend/AbstractDigest.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Auth/Backend/AbstractDigest.php similarity index 61% rename from library/SabreDAV/lib/Sabre/DAV/Auth/Backend/AbstractDigest.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Auth/Backend/AbstractDigest.php index d8cdcb184..5bdc72753 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Auth/Backend/AbstractDigest.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Auth/Backend/AbstractDigest.php @@ -5,38 +5,33 @@ * * This class can be used by authentication objects wishing to use HTTP Digest * Most of the digest logic is handled, implementors just need to worry about - * the getUserInfo method + * the getDigestHash method * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ -abstract class Sabre_DAV_Auth_Backend_AbstractDigest extends Sabre_DAV_Auth_Backend_Abstract { +abstract class Sabre_DAV_Auth_Backend_AbstractDigest implements Sabre_DAV_Auth_IBackend { /** - * This variable holds information about the currently - * logged in user. + * This variable holds the currently logged in username. * * @var array|null */ protected $currentUser; /** - * Returns a users information based on its username + * Returns a users digest hash based on the username and realm. * - * The returned struct must contain at least a uri - * element (which can be identical to username) as well as a digestHash - * element. - * - * If the user was not known, false must be returned. + * If the user was not known, null must be returned. * * @param string $realm * @param string $username - * @return array + * @return string|null */ - abstract public function getUserInfo($realm, $username); + abstract public function getDigestHash($realm,$username); /** * Authenticates the user based on the current request. @@ -66,35 +61,31 @@ public function authenticate(Sabre_DAV_Server $server,$realm) { throw new Sabre_DAV_Exception_NotAuthenticated('No digest authentication headers were found'); } - $userData = $this->getUserInfo($realm, $username); + $hash = $this->getDigestHash($realm, $username); // If this was false, the user account didn't exist - if ($userData===false) { + if ($hash===false || is_null($hash)) { $digest->requireLogin(); throw new Sabre_DAV_Exception_NotAuthenticated('The supplied username was not on file'); } - if (!is_array($userData)) { - throw new Sabre_DAV_Exception('The returntype for getUserInfo must be either false or an array'); - } - - if (!isset($userData['uri']) || !isset($userData['digestHash'])) { - throw new Sabre_DAV_Exception('The returned array from getUserInfo must contain at least a uri and digestHash element'); + if (!is_string($hash)) { + throw new Sabre_DAV_Exception('The returned value from getDigestHash must be a string or null'); } // If this was false, the password or part of the hash was incorrect. - if (!$digest->validateA1($userData['digestHash'])) { + if (!$digest->validateA1($hash)) { $digest->requireLogin(); throw new Sabre_DAV_Exception_NotAuthenticated('Incorrect username'); } - $this->currentUser = $userData; + $this->currentUser = $username; return true; } /** - * Returns information about the currently logged in user. + * Returns the currently logged in username. * - * @return array|null + * @return string|null */ public function getCurrentUser() { diff --git a/library/SabreDAV/lib/Sabre/DAV/Auth/Backend/Apache.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Auth/Backend/Apache.php similarity index 69% rename from library/SabreDAV/lib/Sabre/DAV/Auth/Backend/Apache.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Auth/Backend/Apache.php index 0b46270fa..6bcd76bdc 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Auth/Backend/Apache.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Auth/Backend/Apache.php @@ -3,18 +3,18 @@ /** * Apache authenticator * - * This authentication backend assumes that auhtentication has been + * This authentication backend assumes that authentication has been * conifgured in apache, rather than within SabreDAV. * * Make sure apache is properly configured for this to work. * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ -class Sabre_DAV_Auth_Backend_Apache extends Sabre_DAV_Auth_Backend_Abstract { +class Sabre_DAV_Auth_Backend_Apache implements Sabre_DAV_Auth_IBackend { /** * Current apache user @@ -52,24 +52,7 @@ public function authenticate(Sabre_DAV_Server $server,$realm) { */ public function getCurrentUser() { - return array( - 'uri' => 'principals/' . $this->remoteUser, - ); - - } - - /** - * Returns the full list of users. - * - * This method must at least return a uri for each user. - * - * It is optional to implement this. - * - * @return array - */ - public function getUsers() { - - return array($this->getCurrentUser()); + return $this->remoteUser; } diff --git a/library/SabreDAV/lib/Sabre/DAV/Auth/Backend/File.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Auth/Backend/File.php similarity index 73% rename from library/SabreDAV/lib/Sabre/DAV/Auth/Backend/File.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Auth/Backend/File.php index 953c49e67..f11ef40d8 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Auth/Backend/File.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Auth/Backend/File.php @@ -7,7 +7,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ @@ -54,10 +54,7 @@ public function loadFile($filename) { if (!preg_match('/^[a-zA-Z0-9]{32}$/', $A1)) throw new Sabre_DAV_Exception('Malformed htdigest file. Invalid md5 hash'); - $this->users[$username] = array( - 'digestHash' => $A1, - 'uri' => 'principals/' . $username - ); + $this->users[$username] = $A1; } @@ -70,33 +67,10 @@ public function loadFile($filename) { * @param string $username * @return string */ - public function getUserInfo($realm, $username) { + public function getDigestHash($realm, $username) { return isset($this->users[$username])?$this->users[$username]:false; } - - /** - * Returns the full list of users. - * - * This method must at least return a uri for each user. - * - * @return array - */ - public function getUsers() { - - $re = array(); - foreach($this->users as $userName=>$A1) { - - $re[] = array( - 'uri'=>'principals/' . $userName - ); - - } - - return $re; - - } - } diff --git a/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Auth/Backend/PDO.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Auth/Backend/PDO.php new file mode 100644 index 000000000..ed743477f --- /dev/null +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Auth/Backend/PDO.php @@ -0,0 +1,51 @@ +pdo = $pdo; + + } + + /** + * Returns the digest hash for a user. + * + * @param string $realm + * @param string $username + * @return string|null + */ + public function getDigestHash($realm,$username) { + + $stmt = $this->pdo->prepare('SELECT username, digesta1 FROM users WHERE username = ?'); + $stmt->execute(array($username)); + $result = $stmt->fetchAll(); + + if (!count($result)) return; + + return $result[0]['digesta1']; + + } + +} diff --git a/library/SabreDAV/lib/Sabre/DAV/Auth/Backend/Abstract.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Auth/IBackend.php similarity index 50% rename from library/SabreDAV/lib/Sabre/DAV/Auth/Backend/Abstract.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Auth/IBackend.php index 79383fa31..1f67af4c2 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Auth/Backend/Abstract.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Auth/IBackend.php @@ -5,11 +5,11 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ -abstract class Sabre_DAV_Auth_Backend_Abstract { +interface Sabre_DAV_Auth_IBackend { /** * Authenticates the user based on the current request. @@ -19,31 +19,16 @@ abstract class Sabre_DAV_Auth_Backend_Abstract { * * @return bool */ - abstract public function authenticate(Sabre_DAV_Server $server,$realm); + function authenticate(Sabre_DAV_Server $server,$realm); /** - * Returns information about the currently logged in user. + * Returns information about the currently logged in username. * * If nobody is currently logged in, this method should return null. * - * @return array|null + * @return string|null */ - abstract public function getCurrentUser(); - - /** - * Returns the full list of users. - * - * This method must at least return a uri for each user. - * - * It is optional to implement this. - * - * @return array - */ - public function getUsers() { - - return array(); - - } + function getCurrentUser(); } diff --git a/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Auth/Plugin.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Auth/Plugin.php new file mode 100644 index 000000000..f3718fcf4 --- /dev/null +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Auth/Plugin.php @@ -0,0 +1,111 @@ +authBackend = $authBackend; + $this->realm = $realm; + + } + + /** + * Initializes the plugin. This function is automatically called by the server + * + * @param Sabre_DAV_Server $server + * @return void + */ + public function initialize(Sabre_DAV_Server $server) { + + $this->server = $server; + $this->server->subscribeEvent('beforeMethod',array($this,'beforeMethod'),10); + + } + + /** + * Returns a plugin name. + * + * Using this name other plugins will be able to access other plugins + * using Sabre_DAV_Server::getPlugin + * + * @return string + */ + public function getPluginName() { + + return 'auth'; + + } + + /** + * Returns the current users' principal uri. + * + * If nobody is logged in, this will return null. + * + * @return string|null + */ + public function getCurrentUser() { + + $userInfo = $this->authBackend->getCurrentUser(); + if (!$userInfo) return null; + + return $userInfo; + + } + + /** + * This method is called before any HTTP method and forces users to be authenticated + * + * @param string $method + * @throws Sabre_DAV_Exception_NotAuthenticated + * @return bool + */ + public function beforeMethod($method, $uri) { + + $this->authBackend->authenticate($this->server,$this->realm); + + } + +} diff --git a/library/SabreDAV/lib/Sabre/DAV/Browser/GuessContentType.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Browser/GuessContentType.php similarity index 97% rename from library/SabreDAV/lib/Sabre/DAV/Browser/GuessContentType.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Browser/GuessContentType.php index 430ebde87..8b55ec3ad 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Browser/GuessContentType.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Browser/GuessContentType.php @@ -13,7 +13,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/Browser/MapGetToPropFind.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Browser/MapGetToPropFind.php similarity index 95% rename from library/SabreDAV/lib/Sabre/DAV/Browser/MapGetToPropFind.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Browser/MapGetToPropFind.php index df60ae435..a66b57a3a 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Browser/MapGetToPropFind.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Browser/MapGetToPropFind.php @@ -8,7 +8,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/Browser/Plugin.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Browser/Plugin.php similarity index 88% rename from library/SabreDAV/lib/Sabre/DAV/Browser/Plugin.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Browser/Plugin.php index f718b4fe9..ffc33747f 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Browser/Plugin.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Browser/Plugin.php @@ -11,7 +11,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ @@ -165,6 +165,21 @@ public function generateDirectoryIndex($path) { '{DAV:}getlastmodified', ),1); + + if ($path) { + + list($parentUri) = Sabre_DAV_URLUtil::splitPath($path); + $fullPath = Sabre_DAV_URLUtil::encodePath($this->server->getBaseUri() . $parentUri); + + $html.= " +.. +[parent] + + +"; + + } + foreach($files as $k=>$file) { // This is the current directory, we can skip it @@ -178,16 +193,22 @@ public function generateDirectoryIndex($path) { $type = $file[200]['{DAV:}resourcetype']->getValue(); // resourcetype can have multiple values - if (is_array($type)) { - $type = implode(', ', $type); - } + if (!is_array($type)) $type = array($type); + + foreach($type as $k=>$v) { + + // Some name mapping is preferred + switch($v) { + case '{DAV:}collection' : + $type[$k] = 'Collection'; + break; + case '{DAV:}principal' : + $type[$k] = 'Principal'; + break; + } - // Some name mapping is preferred - switch($type) { - case '{DAV:}collection' : - $type = 'Collection'; - break; } + $type = implode(', ', $type); } // If no resourcetype was found, we attempt to use @@ -237,7 +258,7 @@ public function generateDirectoryIndex($path) { } $html.= " -
Generated by SabreDAV " . Sabre_DAV_Version::VERSION ."-". Sabre_DAV_Version::STABILITY . " (c)2007-2010 http://code.google.com/p/sabredav/
+
Generated by SabreDAV " . Sabre_DAV_Version::VERSION ."-". Sabre_DAV_Version::STABILITY . " (c)2007-2011 http://code.google.com/p/sabredav/
"; diff --git a/library/SabreDAV/lib/Sabre/DAV/Directory.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Directory.php similarity index 97% rename from library/SabreDAV/lib/Sabre/DAV/Directory.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Directory.php index ebc266e10..14d7f2cb6 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Directory.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Directory.php @@ -8,7 +8,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/Exception.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception.php similarity index 95% rename from library/SabreDAV/lib/Sabre/DAV/Exception.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception.php index 46b710a0e..61f8b87c0 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Exception.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception.php @@ -7,7 +7,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/Exception/BadRequest.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/BadRequest.php similarity index 89% rename from library/SabreDAV/lib/Sabre/DAV/Exception/BadRequest.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/BadRequest.php index 86f91d5a9..7025bb103 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Exception/BadRequest.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/BadRequest.php @@ -8,7 +8,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/Exception/Conflict.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/Conflict.php similarity index 90% rename from library/SabreDAV/lib/Sabre/DAV/Exception/Conflict.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/Conflict.php index 1d9edbb37..7eaa08178 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Exception/Conflict.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/Conflict.php @@ -8,7 +8,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/Exception/ConflictingLock.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/ConflictingLock.php similarity index 94% rename from library/SabreDAV/lib/Sabre/DAV/Exception/ConflictingLock.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/ConflictingLock.php index 64e463acc..279f63dfd 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Exception/ConflictingLock.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/ConflictingLock.php @@ -8,7 +8,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/Exception/FileNotFound.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/FileNotFound.php similarity index 89% rename from library/SabreDAV/lib/Sabre/DAV/Exception/FileNotFound.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/FileNotFound.php index cd03d4c72..b20e4a2fb 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Exception/FileNotFound.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/FileNotFound.php @@ -7,7 +7,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/Exception/Forbidden.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/Forbidden.php similarity index 89% rename from library/SabreDAV/lib/Sabre/DAV/Exception/Forbidden.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/Forbidden.php index cde3d9c1f..167f3c276 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Exception/Forbidden.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/Forbidden.php @@ -7,7 +7,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/Exception/InsufficientStorage.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/InsufficientStorage.php similarity index 89% rename from library/SabreDAV/lib/Sabre/DAV/Exception/InsufficientStorage.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/InsufficientStorage.php index d18d80895..15007cdd3 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Exception/InsufficientStorage.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/InsufficientStorage.php @@ -7,7 +7,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/Exception/InvalidResourceType.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/InvalidResourceType.php similarity index 93% rename from library/SabreDAV/lib/Sabre/DAV/Exception/InvalidResourceType.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/InvalidResourceType.php index 36248704b..f06810a25 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Exception/InvalidResourceType.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/InvalidResourceType.php @@ -10,7 +10,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/Exception/LockTokenMatchesRequestUri.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/LockTokenMatchesRequestUri.php similarity index 94% rename from library/SabreDAV/lib/Sabre/DAV/Exception/LockTokenMatchesRequestUri.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/LockTokenMatchesRequestUri.php index 059ee3469..47032cffc 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Exception/LockTokenMatchesRequestUri.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/LockTokenMatchesRequestUri.php @@ -7,7 +7,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/Exception/Locked.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/Locked.php similarity index 96% rename from library/SabreDAV/lib/Sabre/DAV/Exception/Locked.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/Locked.php index 3f15ea74a..b4bb2e037 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Exception/Locked.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/Locked.php @@ -7,7 +7,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/Exception/MethodNotAllowed.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/MethodNotAllowed.php similarity index 93% rename from library/SabreDAV/lib/Sabre/DAV/Exception/MethodNotAllowed.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/MethodNotAllowed.php index 67ad9a8ac..02c145ffe 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Exception/MethodNotAllowed.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/MethodNotAllowed.php @@ -7,7 +7,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/Exception/NotAuthenticated.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/NotAuthenticated.php similarity index 89% rename from library/SabreDAV/lib/Sabre/DAV/Exception/NotAuthenticated.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/NotAuthenticated.php index 281598537..1faffddfa 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Exception/NotAuthenticated.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/NotAuthenticated.php @@ -8,7 +8,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/Exception/NotImplemented.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/NotImplemented.php similarity index 89% rename from library/SabreDAV/lib/Sabre/DAV/Exception/NotImplemented.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/NotImplemented.php index 5d746be3f..cd7f609b0 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Exception/NotImplemented.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/NotImplemented.php @@ -7,7 +7,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/Exception/PreconditionFailed.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/PreconditionFailed.php similarity index 96% rename from library/SabreDAV/lib/Sabre/DAV/Exception/PreconditionFailed.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/PreconditionFailed.php index 1d4c18624..ebcb9f5b9 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Exception/PreconditionFailed.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/PreconditionFailed.php @@ -9,7 +9,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/Exception/ReportNotImplemented.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/ReportNotImplemented.php similarity index 93% rename from library/SabreDAV/lib/Sabre/DAV/Exception/ReportNotImplemented.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/ReportNotImplemented.php index 64526f42c..e4ed601b1 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Exception/ReportNotImplemented.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/ReportNotImplemented.php @@ -7,7 +7,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/Exception/RequestedRangeNotSatisfiable.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/RequestedRangeNotSatisfiable.php similarity index 90% rename from library/SabreDAV/lib/Sabre/DAV/Exception/RequestedRangeNotSatisfiable.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/RequestedRangeNotSatisfiable.php index 723138d84..37abbd729 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Exception/RequestedRangeNotSatisfiable.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/RequestedRangeNotSatisfiable.php @@ -8,7 +8,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/Exception/UnsupportedMediaType.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/UnsupportedMediaType.php similarity index 90% rename from library/SabreDAV/lib/Sabre/DAV/Exception/UnsupportedMediaType.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/UnsupportedMediaType.php index d2c31d91a..4c37d8997 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Exception/UnsupportedMediaType.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Exception/UnsupportedMediaType.php @@ -8,7 +8,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/FS/Directory.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/FS/Directory.php similarity index 97% rename from library/SabreDAV/lib/Sabre/DAV/FS/Directory.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/FS/Directory.php index a3e80e124..ebd6a6c50 100644 --- a/library/SabreDAV/lib/Sabre/DAV/FS/Directory.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/FS/Directory.php @@ -5,7 +5,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/FS/File.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/FS/File.php similarity index 96% rename from library/SabreDAV/lib/Sabre/DAV/FS/File.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/FS/File.php index dc2e7f98b..262187d7e 100644 --- a/library/SabreDAV/lib/Sabre/DAV/FS/File.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/FS/File.php @@ -5,7 +5,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/FS/Node.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/FS/Node.php similarity index 95% rename from library/SabreDAV/lib/Sabre/DAV/FS/Node.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/FS/Node.php index 172af8520..b8d7bcfe8 100644 --- a/library/SabreDAV/lib/Sabre/DAV/FS/Node.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/FS/Node.php @@ -7,7 +7,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/FSExt/Directory.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/FSExt/Directory.php similarity index 98% rename from library/SabreDAV/lib/Sabre/DAV/FSExt/Directory.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/FSExt/Directory.php index b42a9a9d7..c43d4385a 100644 --- a/library/SabreDAV/lib/Sabre/DAV/FSExt/Directory.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/FSExt/Directory.php @@ -5,7 +5,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/FSExt/File.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/FSExt/File.php similarity index 96% rename from library/SabreDAV/lib/Sabre/DAV/FSExt/File.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/FSExt/File.php index 987bca336..7a8e7a11f 100644 --- a/library/SabreDAV/lib/Sabre/DAV/FSExt/File.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/FSExt/File.php @@ -5,7 +5,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/FSExt/Node.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/FSExt/Node.php similarity index 99% rename from library/SabreDAV/lib/Sabre/DAV/FSExt/Node.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/FSExt/Node.php index 0af346d1f..9e36222bf 100644 --- a/library/SabreDAV/lib/Sabre/DAV/FSExt/Node.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/FSExt/Node.php @@ -7,7 +7,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/File.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/File.php similarity index 96% rename from library/SabreDAV/lib/Sabre/DAV/File.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/File.php index aaaf88e6b..b74bd9525 100644 --- a/library/SabreDAV/lib/Sabre/DAV/File.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/File.php @@ -8,7 +8,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/ICollection.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/ICollection.php similarity index 95% rename from library/SabreDAV/lib/Sabre/DAV/ICollection.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/ICollection.php index 814387f8a..0667d8889 100644 --- a/library/SabreDAV/lib/Sabre/DAV/ICollection.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/ICollection.php @@ -7,7 +7,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/IExtendedCollection.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/IExtendedCollection.php similarity index 91% rename from library/SabreDAV/lib/Sabre/DAV/IExtendedCollection.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/IExtendedCollection.php index 4210f7f03..b8db1ab2f 100644 --- a/library/SabreDAV/lib/Sabre/DAV/IExtendedCollection.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/IExtendedCollection.php @@ -8,7 +8,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/IFile.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/IFile.php similarity index 95% rename from library/SabreDAV/lib/Sabre/DAV/IFile.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/IFile.php index 949d9a9ba..446ec8618 100644 --- a/library/SabreDAV/lib/Sabre/DAV/IFile.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/IFile.php @@ -7,7 +7,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/ILockable.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/ILockable.php similarity index 93% rename from library/SabreDAV/lib/Sabre/DAV/ILockable.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/ILockable.php index 10ac70671..f9fb3a702 100644 --- a/library/SabreDAV/lib/Sabre/DAV/ILockable.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/ILockable.php @@ -5,7 +5,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/INode.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/INode.php similarity index 92% rename from library/SabreDAV/lib/Sabre/DAV/INode.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/INode.php index c73696b20..c0b96bf53 100644 --- a/library/SabreDAV/lib/Sabre/DAV/INode.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/INode.php @@ -5,7 +5,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/IProperties.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/IProperties.php similarity index 96% rename from library/SabreDAV/lib/Sabre/DAV/IProperties.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/IProperties.php index 46121b454..26287d252 100644 --- a/library/SabreDAV/lib/Sabre/DAV/IProperties.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/IProperties.php @@ -7,7 +7,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/IQuota.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/IQuota.php similarity index 92% rename from library/SabreDAV/lib/Sabre/DAV/IQuota.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/IQuota.php index afba5efdc..8ff1a4597 100644 --- a/library/SabreDAV/lib/Sabre/DAV/IQuota.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/IQuota.php @@ -9,7 +9,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/Locks/Backend/Abstract.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Locks/Backend/Abstract.php similarity index 78% rename from library/SabreDAV/lib/Sabre/DAV/Locks/Backend/Abstract.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Locks/Backend/Abstract.php index 46146f1df..b09f93dda 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Locks/Backend/Abstract.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Locks/Backend/Abstract.php @@ -7,7 +7,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ @@ -19,10 +19,14 @@ abstract class Sabre_DAV_Locks_Backend_Abstract { * This method should return all the locks for a particular uri, including * locks that might be set on a parent uri. * + * If returnChildLocks is set to true, this method should also look for + * any locks in the subtree of the uri for locks. + * * @param string $uri + * @param bool $returnChildLocks * @return array */ - abstract function getLocks($uri); + abstract function getLocks($uri, $returnChildLocks); /** * Locks a uri diff --git a/library/SabreDAV/lib/Sabre/DAV/Locks/Backend/FS.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Locks/Backend/FS.php similarity index 85% rename from library/SabreDAV/lib/Sabre/DAV/Locks/Backend/FS.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Locks/Backend/FS.php index b3e0f5131..8653f55b1 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Locks/Backend/FS.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Locks/Backend/FS.php @@ -3,12 +3,17 @@ /** * The Lock manager allows you to handle all file-locks centrally. * - * This Lock Manager stores all its data in the filesystem. By default it will do this in PHP's standard temporary session directory, - * but this can be overriden by specifiying an alternative path in the contructor + * This Lock Manager is now deprecated. It has a bug that allows parent + * collections to be deletes when children deeper in the tree are locked. + * + * You are recommended to use either the PDO or the File backend instead. + * + * This Lock Manager stores all its data in the filesystem. * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @deprecated + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ @@ -40,10 +45,14 @@ protected function getFileNameForUri($uri) { * This method should return all the locks for a particular uri, including * locks that might be set on a parent uri. * + * If returnChildLocks is set to true, this method should also look for + * any locks in the subtree of the uri for locks. + * * @param string $uri + * @param bool $returnChildLocks * @return array */ - public function getLocks($uri) { + public function getLocks($uri, $returnChildLocks) { $lockList = array(); $currentPath = ''; @@ -89,7 +98,7 @@ public function lock($uri,Sabre_DAV_Locks_LockInfo $lockInfo) { $lockInfo->timeout = 1800; $lockInfo->created = time(); - $locks = $this->getLocks($uri); + $locks = $this->getLocks($uri,false); foreach($locks as $k=>$lock) { if ($lock->token == $lockInfo->token) unset($locks[$k]); } @@ -108,7 +117,7 @@ public function lock($uri,Sabre_DAV_Locks_LockInfo $lockInfo) { */ public function unlock($uri,Sabre_DAV_Locks_LockInfo $lockInfo) { - $locks = $this->getLocks($uri); + $locks = $this->getLocks($uri,false); foreach($locks as $k=>$lock) { if ($lock->token == $lockInfo->token) { diff --git a/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Locks/Backend/File.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Locks/Backend/File.php new file mode 100644 index 000000000..7a898b854 --- /dev/null +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Locks/Backend/File.php @@ -0,0 +1,170 @@ +locksFile = $locksFile; + + } + + /** + * Returns a list of Sabre_DAV_Locks_LockInfo objects + * + * This method should return all the locks for a particular uri, including + * locks that might be set on a parent uri. + * + * If returnChildLocks is set to true, this method should also look for + * any locks in the subtree of the uri for locks. + * + * @param string $uri + * @param bool $returnChildLocks + * @return array + */ + public function getLocks($uri, $returnChildLocks) { + + $newLocks = array(); + $currentPath = ''; + + $locks = $this->getData(); + foreach($locks as $lock) { + + if ($lock->uri === $uri || + //deep locks on parents + ($lock->depth!=0 && strpos($uri, $lock->uri . '/')===0) || + + // locks on children + ($returnChildLocks && (strpos($lock->uri, $uri . '/')===0)) ) { + + $newLocks[] = $lock; + + } + + } + + // Checking if we can remove any of these locks + foreach($newLocks as $k=>$lock) { + if (time() > $lock->timeout + $lock->created) unset($newLocks[$k]); + } + return $newLocks; + + } + + /** + * Locks a uri + * + * @param string $uri + * @param Sabre_DAV_Locks_LockInfo $lockInfo + * @return bool + */ + public function lock($uri,Sabre_DAV_Locks_LockInfo $lockInfo) { + + // We're making the lock timeout 30 minutes + $lockInfo->timeout = 1800; + $lockInfo->created = time(); + $lockInfo->uri = $uri; + + $locks = $this->getLocks($uri,false); + foreach($locks as $k=>$lock) { + if ($lock->token == $lockInfo->token) unset($locks[$k]); + } + $locks[] = $lockInfo; + $this->putData($locks); + return true; + + } + + /** + * Removes a lock from a uri + * + * @param string $uri + * @param Sabre_DAV_Locks_LockInfo $lockInfo + * @return bool + */ + public function unlock($uri,Sabre_DAV_Locks_LockInfo $lockInfo) { + + $locks = $this->getLocks($uri,false); + foreach($locks as $k=>$lock) { + + if ($lock->token == $lockInfo->token) { + + unset($locks[$k]); + $this->putData($locks); + return true; + + } + } + return false; + + } + + /** + * Loads the lockdata from the filesystem. + * + * @return array + */ + protected function getData() { + + if (!file_exists($this->locksFile)) return array(); + + // opening up the file, and creating a shared lock + $handle = fopen($this->locksFile,'r'); + flock($handle,LOCK_SH); + + // Reading data until the eof + $data = stream_get_contents($handle); + + // We're all good + fclose($handle); + + // Unserializing and checking if the resource file contains data for this file + $data = unserialize($data); + if (!$data) return array(); + return $data; + + } + + /** + * Saves the lockdata + * + * @param array $newData + * @return void + */ + protected function putData(array $newData) { + + // opening up the file, and creating an exclusive lock + $handle = fopen($this->locksFile,'a+'); + flock($handle,LOCK_EX); + + // We can only truncate and rewind once the lock is acquired. + ftruncate($handle,0); + rewind($handle); + + fwrite($handle,serialize($newData)); + fclose($handle); + + } + +} + diff --git a/library/SabreDAV/lib/Sabre/DAV/Locks/Backend/PDO.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Locks/Backend/PDO.php similarity index 89% rename from library/SabreDAV/lib/Sabre/DAV/Locks/Backend/PDO.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Locks/Backend/PDO.php index 11c7fa969..ea465f442 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Locks/Backend/PDO.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Locks/Backend/PDO.php @@ -8,7 +8,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ @@ -33,10 +33,14 @@ public function __construct(PDO $pdo) { * This method should return all the locks for a particular uri, including * locks that might be set on a parent uri. * + * If returnChildLocks is set to true, this method should also look for + * any locks in the subtree of the uri for locks. + * * @param string $uri + * @param bool $returnChildLocks * @return array */ - public function getLocks($uri) { + public function getLocks($uri, $returnChildLocks) { // NOTE: the following 10 lines or so could be easily replaced by // pure sql. MySQL's non-standard string concatination prevents us @@ -62,6 +66,12 @@ public function getLocks($uri) { } + if ($returnChildLocks) { + + $query.=' OR (uri LIKE ?)'; + $params[] = $uri . '/%'; + + } $query.=')'; $stmt = $this->pdo->prepare($query); @@ -101,7 +111,7 @@ public function lock($uri,Sabre_DAV_Locks_LockInfo $lockInfo) { $lockInfo->created = time(); $lockInfo->uri = $uri; - $locks = $this->getLocks($uri); + $locks = $this->getLocks($uri,false); $exists = false; foreach($locks as $k=>$lock) { if ($lock->token == $lockInfo->token) $exists = true; diff --git a/library/SabreDAV/lib/Sabre/DAV/Locks/LockInfo.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Locks/LockInfo.php similarity index 95% rename from library/SabreDAV/lib/Sabre/DAV/Locks/LockInfo.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Locks/LockInfo.php index aa174384e..6a064466f 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Locks/LockInfo.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Locks/LockInfo.php @@ -8,7 +8,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/Locks/Plugin.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Locks/Plugin.php similarity index 91% rename from library/SabreDAV/lib/Sabre/DAV/Locks/Plugin.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Locks/Plugin.php index 91dea5fee..3a73fa26f 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Locks/Plugin.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Locks/Plugin.php @@ -6,13 +6,13 @@ * This plugin provides locking support to a WebDAV server. * The easiest way to get started, is by hooking it up as such: * - * $lockBackend = new Sabre_DAV_Locks_Backend_FS('./my_lock_directory'); + * $lockBackend = new Sabre_DAV_Locks_Backend_File('./mylockdb'); * $lockPlugin = new Sabre_DAV_Locks_Plugin($lockBackend); * $server->addPlugin($lockPlugin); * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ @@ -61,6 +61,20 @@ public function initialize(Sabre_DAV_Server $server) { } + /** + * Returns a plugin name. + * + * Using this name other plugins will be able to access other plugins + * using Sabre_DAV_Server::getPlugin + * + * @return string + */ + public function getPluginName() { + + return 'locks'; + + } + /** * This method is called by the Server if the user used an HTTP method * the server didn't recognize. @@ -137,6 +151,10 @@ public function beforeMethod($method, $uri) { switch($method) { case 'DELETE' : + $lastLock = null; + if (!$this->validateLock($uri,$lastLock, true)) + throw new Sabre_DAV_Exception_Locked($lastLock); + break; case 'MKCOL' : case 'PROPPATCH' : case 'PUT' : @@ -149,14 +167,14 @@ public function beforeMethod($method, $uri) { if (!$this->validateLock(array( $uri, $this->server->calculateUri($this->server->httpRequest->getHeader('Destination')), - ),$lastLock)) + ),$lastLock, true)) throw new Sabre_DAV_Exception_Locked($lastLock); break; case 'COPY' : $lastLock = null; if (!$this->validateLock( $this->server->calculateUri($this->server->httpRequest->getHeader('Destination')), - $lastLock)) + $lastLock, true)) throw new Sabre_DAV_Exception_Locked($lastLock); break; } @@ -165,7 +183,6 @@ public function beforeMethod($method, $uri) { } - /** * Use this method to tell the server this plugin defines additional * HTTP methods. @@ -206,11 +223,14 @@ public function getFeatures() { * This function should return an array with Sabre_DAV_Locks_LockInfo objects. If there are no locks on a file, return an empty array. * * Additionally there is also the possibility of locks on parent nodes, so we'll need to traverse every part of the tree + * If the $returnChildLocks argument is set to true, we'll also traverse all the children of the object + * for any possible locks and return those as well. * * @param string $uri + * @param bool $returnChildLocks * @return array */ - public function getLocks($uri) { + public function getLocks($uri, $returnChildLocks = false) { $lockList = array(); $currentPath = ''; @@ -231,7 +251,7 @@ public function getLocks($uri) { foreach($uriLocks as $uriLock) { - // Unless we're on the leaf of the uri-tree we should ingore locks with depth 0 + // Unless we're on the leaf of the uri-tree we should ignore locks with depth 0 if($uri==$currentPath || $uriLock->depth!=0) { $uriLock->uri = $currentPath; $lockList[] = $uriLock; @@ -240,7 +260,9 @@ public function getLocks($uri) { } } - if ($this->locksBackend) $lockList = array_merge($lockList,$this->locksBackend->getLocks($uri)); + if ($this->locksBackend) + $lockList = array_merge($lockList,$this->locksBackend->getLocks($uri, $returnChildLocks)); + return $lockList; } @@ -347,6 +369,7 @@ protected function httpUnlock($uri) { if ('token . '>' == $lockToken) { + $this->server->broadcastEvent('beforeUnlock',array($uri, $lock)); $this->unlockNode($uri,$lock); $this->server->httpResponse->setHeader('Content-Length','0'); $this->server->httpResponse->sendStatus(204); @@ -467,9 +490,10 @@ protected function generateLockResponse(Sabre_DAV_Locks_LockInfo $lockInfo) { * * @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) { + protected function validateLock($urls = null,&$lastLock = null, $checkChildLocks = false) { if (is_null($urls)) { $urls = array($this->server->getRequestUri()); @@ -484,7 +508,7 @@ protected function validateLock($urls = null,&$lastLock = null) { // We're going to loop through the urls and make sure all lock conditions are satisfied foreach($urls as $url) { - $locks = $this->getLocks($url); + $locks = $this->getLocks($url, $checkChildLocks); // If there were no conditions, but there were locks, we fail if (!$conditions && $locks) { @@ -498,7 +522,11 @@ protected function validateLock($urls = null,&$lastLock = null) { foreach($conditions as $condition) { - $conditionUri = $condition['uri']?$this->server->calculateUri($condition['uri']):''; + 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; @@ -582,7 +610,8 @@ protected function validateLock($urls = null,&$lastLock = null) { * The If header can be quite complex, and has a bunch of features. We're using a regex to extract all relevant information * The function will return an array, containg structs with the following keys * - * * uri - the uri the condition applies to. This can be an empty string for 'every relevant url' + * * uri - the uri the condition applies to. If this is returned as an + * empty string, this implies it's referring to the request url. * * tokens - The lock token. another 2 dimensional array containg 2 elements (0 = true/false.. If this is a negative condition its set to false, 1 = the actual token) * * etag - an etag, if supplied * @@ -635,14 +664,11 @@ protected function parseLockRequest($body) { $xml = simplexml_load_string($body,null,LIBXML_NOWARNING); $xml->registerXPathNamespace('d','DAV:'); $lockInfo = new Sabre_DAV_Locks_LockInfo(); - - $lockInfo->owner = (string)$xml->owner; - $lockToken = '44445502'; - $id = md5(microtime() . 'somethingrandom'); - $lockToken.='-' . substr($id,0,4) . '-' . substr($id,4,4) . '-' . substr($id,8,4) . '-' . substr($id,12,12); + $children = $xml->children("DAV:"); + $lockInfo->owner = (string)$children->owner; - $lockInfo->token = $lockToken; + $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; diff --git a/library/SabreDAV/lib/Sabre/DAV/Mount/Plugin.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Mount/Plugin.php similarity index 96% rename from library/SabreDAV/lib/Sabre/DAV/Mount/Plugin.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Mount/Plugin.php index c2dc4296d..f93a1aa25 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Mount/Plugin.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Mount/Plugin.php @@ -7,7 +7,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) */ class Sabre_DAV_Mount_Plugin extends Sabre_DAV_ServerPlugin { diff --git a/library/SabreDAV/lib/Sabre/DAV/Node.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Node.php similarity index 94% rename from library/SabreDAV/lib/Sabre/DAV/Node.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Node.php index 8943b7865..0510df5fd 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Node.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Node.php @@ -7,7 +7,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/ObjectTree.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/ObjectTree.php similarity index 96% rename from library/SabreDAV/lib/Sabre/DAV/ObjectTree.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/ObjectTree.php index 836bdf827..1319c7dae 100644 --- a/library/SabreDAV/lib/Sabre/DAV/ObjectTree.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/ObjectTree.php @@ -7,7 +7,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ @@ -83,7 +83,11 @@ public function nodeExists($path) { try { + // The root always exists + if ($path==='') return true; + list($parent, $base) = Sabre_DAV_URLUtil::splitPath($path); + $parentNode = $this->getNodeForPath($parent); return $parentNode->childExists($base); diff --git a/library/SabreDAV/lib/Sabre/DAV/Property.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property.php similarity index 88% rename from library/SabreDAV/lib/Sabre/DAV/Property.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property.php index ae0a64c6e..a4818bff0 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Property.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property.php @@ -7,7 +7,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/Property/GetLastModified.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property/GetLastModified.php similarity index 96% rename from library/SabreDAV/lib/Sabre/DAV/Property/GetLastModified.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property/GetLastModified.php index b066fee0b..4a8126299 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Property/GetLastModified.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property/GetLastModified.php @@ -11,7 +11,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/Property/Href.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property/Href.php similarity index 97% rename from library/SabreDAV/lib/Sabre/DAV/Property/Href.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property/Href.php index 8b9400fb7..3294ff2ac 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Property/Href.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property/Href.php @@ -8,7 +8,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property/HrefList.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property/HrefList.php new file mode 100644 index 000000000..1868cc74f --- /dev/null +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property/HrefList.php @@ -0,0 +1,96 @@ +hrefs = $hrefs; + $this->autoPrefix = $autoPrefix; + + } + + /** + * Returns the uris + * + * @return array + */ + public function getHrefs() { + + return $this->hrefs; + + } + + /** + * Serializes this property. + * + * It will additionally prepend the href property with the server's base uri. + * + * @param Sabre_DAV_Server $server + * @param DOMElement $dom + * @return void + */ + public function serialize(Sabre_DAV_Server $server,DOMElement $dom) { + + $prefix = $server->xmlNamespaces['DAV:']; + + foreach($this->hrefs as $href) { + $elem = $dom->ownerDocument->createElement($prefix . ':href'); + $elem->nodeValue = ($this->autoPrefix?$server->getBaseUri():'') . $href; + $dom->appendChild($elem); + } + + } + + /** + * 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->children as $child) { + if (Sabre_DAV_XMLUtil::toClarkNotation($child)==='{DAV:}href') { + $hrefs[] = $child->textContent; + } + } + return new self($hrefs, false); + + } + +} diff --git a/library/SabreDAV/lib/Sabre/DAV/Property/IHref.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property/IHref.php similarity index 89% rename from library/SabreDAV/lib/Sabre/DAV/Property/IHref.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property/IHref.php index 56503acd2..29d76a44f 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Property/IHref.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property/IHref.php @@ -9,7 +9,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/Property/LockDiscovery.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property/LockDiscovery.php similarity index 76% rename from library/SabreDAV/lib/Sabre/DAV/Property/LockDiscovery.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property/LockDiscovery.php index 2897f6e64..05c7470b4 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Property/LockDiscovery.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property/LockDiscovery.php @@ -7,7 +7,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ @@ -27,6 +27,14 @@ class Sabre_DAV_Property_LockDiscovery extends Sabre_DAV_Property { */ public $revealLockToken; + /** + * Hides the {DAV:}lockroot element from the response. + * + * It was reported that showing the lockroot in the response can break + * Office 2000 compatibility. + */ + static public $hideLockRoot = false; + /** * __construct * @@ -66,6 +74,15 @@ public function serialize(Sabre_DAV_Server $server,DOMElement $prop) { $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 == Sabre_DAV_Server::DEPTH_INFINITY?'infinity':$lock->depth))); $activeLock->appendChild($doc->createElementNS('DAV:','d:timeout','Second-' . $lock->timeout)); diff --git a/library/SabreDAV/lib/Sabre/DAV/Property/Principal.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property/Principal.php similarity index 97% rename from library/SabreDAV/lib/Sabre/DAV/Property/Principal.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property/Principal.php index df3f78485..28ab399c0 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Property/Principal.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property/Principal.php @@ -8,7 +8,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/Property/ResourceType.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property/ResourceType.php similarity index 62% rename from library/SabreDAV/lib/Sabre/DAV/Property/ResourceType.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property/ResourceType.php index 51022a481..615042774 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Property/ResourceType.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property/ResourceType.php @@ -8,7 +8,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ @@ -17,9 +17,9 @@ class Sabre_DAV_Property_ResourceType extends Sabre_DAV_Property { /** * resourceType * - * @var string + * @var array */ - public $resourceType = null; + public $resourceType = array(); /** * __construct @@ -27,14 +27,16 @@ class Sabre_DAV_Property_ResourceType extends Sabre_DAV_Property { * @param mixed $resourceType * @return void */ - public function __construct($resourceType = null) { + public function __construct($resourceType = array()) { if ($resourceType === Sabre_DAV_Server::NODE_FILE) - $this->resourceType = null; + $this->resourceType = array(); elseif ($resourceType === Sabre_DAV_Server::NODE_DIRECTORY) - $this->resourceType = '{DAV:}collection'; - else + $this->resourceType = array('{DAV:}collection'); + elseif (is_array($resourceType)) $this->resourceType = $resourceType; + else + $this->resourceType = array($resourceType); } @@ -48,7 +50,6 @@ public function serialize(Sabre_DAV_Server $server,DOMElement $prop) { $propName = null; $rt = $this->resourceType; - if (!is_array($rt)) $rt = array($rt); foreach($rt as $resourceType) { if (preg_match('/^{([^}]*)}(.*)$/',$resourceType,$propName)) { @@ -65,11 +66,11 @@ public function serialize(Sabre_DAV_Server $server,DOMElement $prop) { } /** - * Returns the value in clark-notation + * Returns the values in clark-notation * - * For example '{DAV:}collection' + * For example array('{DAV:}collection') * - * @return string + * @return array */ public function getValue() { @@ -77,4 +78,29 @@ public function getValue() { } + /** + * Checks if the principal contains a certain value + * + * @param string $type + * @return bool + */ + public function is($type) { + + return in_array($type, $this->resourceType); + + } + + /** + * Adds a resourcetype value to this property + * + * @param string $type + * @return void + */ + public function add($type) { + + $this->resourceType[] = $type; + $this->resourceType = array_unique($this->resourceType); + + } + } diff --git a/library/SabreDAV/lib/Sabre/DAV/Property/Response.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property/Response.php similarity index 98% rename from library/SabreDAV/lib/Sabre/DAV/Property/Response.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property/Response.php index 6c75e8df9..7d3a2db03 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Property/Response.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property/Response.php @@ -9,7 +9,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property/ResponseList.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property/ResponseList.php new file mode 100644 index 000000000..cd70b1286 --- /dev/null +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property/ResponseList.php @@ -0,0 +1,58 @@ +responses = $responses; + + } + + /** + * serialize + * + * @param Sabre_DAV_Server $server + * @param DOMElement $dom + * @return void + */ + public function serialize(Sabre_DAV_Server $server,DOMElement $dom) { + + foreach($this->responses as $response) { + $response->serialize($server, $dom); + } + + } + +} diff --git a/library/SabreDAV/lib/Sabre/DAV/Property/SupportedLock.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property/SupportedLock.php similarity index 97% rename from library/SabreDAV/lib/Sabre/DAV/Property/SupportedLock.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property/SupportedLock.php index 0b7ca0cf9..01e63f58d 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Property/SupportedLock.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property/SupportedLock.php @@ -8,7 +8,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/Property/SupportedReportSet.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property/SupportedReportSet.php similarity index 94% rename from library/SabreDAV/lib/Sabre/DAV/Property/SupportedReportSet.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property/SupportedReportSet.php index 8676f4c03..acd9219c0 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Property/SupportedReportSet.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Property/SupportedReportSet.php @@ -8,7 +8,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ @@ -32,9 +32,9 @@ class Sabre_DAV_Property_SupportedReportSet extends Sabre_DAV_Property { * @param mixed $reports * @return void */ - public function __construct($report = null) { + public function __construct($reports = null) { - if (!is_null($report)) + if (!is_null($reports)) $this->addReport($reports); } diff --git a/library/SabreDAV/lib/Sabre/DAV/Server.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Server.php similarity index 90% rename from library/SabreDAV/lib/Sabre/DAV/Server.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Server.php index 21a61256e..9b72b0f53 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Server.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Server.php @@ -5,7 +5,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ @@ -112,18 +112,12 @@ class Sabre_DAV_Server { '{DAV:}quota-used-bytes', // RFC3744 - '{DAV:}alternate-URI-set', - '{DAV:}principal-URL', - '{DAV:}group-membership', '{DAV:}supported-privilege-set', '{DAV:}current-user-privilege-set', '{DAV:}acl', '{DAV:}acl-restrictions', '{DAV:}inherited-acl-set', - '{DAV:}principal-collection-set', - // RFC5397 - '{DAV:}current-user-principal', ); /** @@ -134,6 +128,19 @@ class Sabre_DAV_Server { */ public $debugExceptions = false; + /** + * This property allows you to automatically add the 'resourcetype' value + * based on a node's classname or interface. + * + * The preset ensures that {DAV:}collection is automaticlly added for nodes + * implementing Sabre_DAV_ICollection. + * + * @var array + */ + public $resourceTypeMapping = array( + 'Sabre_DAV_ICollection' => '{DAV:}collection', + ); + /** * Sets up the server @@ -144,6 +151,9 @@ class Sabre_DAV_Server { * * If nothing is passed, a Sabre_DAV_SimpleDirectory is created in * a Sabre_DAV_ObjectTree. + * + * If an array is passed, we automatically create a root node, and use + * the nodes in the array as top-level children. * * @param Sabre_DAV_Tree $tree The tree object * @return void @@ -154,11 +164,24 @@ public function __construct($treeOrNode = null) { $this->tree = $treeOrNode; } elseif ($treeOrNode instanceof Sabre_DAV_INode) { $this->tree = new Sabre_DAV_ObjectTree($treeOrNode); + } elseif (is_array($treeOrNode)) { + + // If it's an array, a list of nodes was passed, and we need to + // create the root node. + foreach($treeOrNode as $node) { + if (!($node instanceof Sabre_DAV_INode)) { + throw new Sabre_DAV_Exception('Invalid argument passed to constructor. If you\'re passing an array, all the values must implement Sabre_DAV_INode'); + } + } + + $root = new Sabre_DAV_SimpleDirectory('root', $treeOrNode); + $this->tree = new Sabre_DAV_ObjectTree($root); + } elseif (is_null($treeOrNode)) { $root = new Sabre_DAV_SimpleDirectory('root'); $this->tree = new Sabre_DAV_ObjectTree($root); } else { - throw new Sabre_DAV_Exception('Invalid argument passed to constructor. Argument must either be an instance of Sabre_DAV_Tree, Sabre_DAV_INode or null'); + throw new Sabre_DAV_Exception('Invalid argument passed to constructor. Argument must either be an instance of Sabre_DAV_Tree, Sabre_DAV_INode, an array or null'); } $this->httpResponse = new Sabre_HTTP_Response(); $this->httpRequest = new Sabre_HTTP_Request(); @@ -259,7 +282,7 @@ public function guessBaseUri() { $pathInfo = $this->httpRequest->getRawServerValue('PATH_INFO'); $uri = $this->httpRequest->getRawServerValue('REQUEST_URI'); - // If PATH_INFO is not found, we just return / + // If PATH_INFO is found, we can assume it's accurate. if (!empty($pathInfo)) { // We need to make sure we ignore the QUERY_STRING part @@ -283,11 +306,6 @@ public function guessBaseUri() { } - // If the url ended with .php, we're going to assume that that's the server root - if (strpos($uri,'.php')===strlen($uri)-4) { - return $uri . '/'; - } - // The last fallback is that we're just going to assume the server root. return '/'; @@ -303,26 +321,46 @@ public function guessBaseUri() { */ public function addPlugin(Sabre_DAV_ServerPlugin $plugin) { - $this->plugins[get_class($plugin)] = $plugin; + $this->plugins[$plugin->getPluginName()] = $plugin; $plugin->initialize($this); } /** - * Returns an initialized plugin by it's classname. + * Returns an initialized plugin by it's name. * * This function returns null if the plugin was not found. * - * @param string $className + * @param string $name * @return Sabre_DAV_ServerPlugin */ - public function getPlugin($className) { + public function getPlugin($name) { + + if (isset($this->plugins[$name])) + return $this->plugins[$name]; + + // This is a fallback and deprecated. + foreach($this->plugins as $plugin) { + if (get_class($plugin)===$name) return $plugin; + } - if (isset($this->plugins[$className])) return $this->plugins[$className]; return null; } + /** + * Returns all plugins + * + * @return array + */ + public function getPlugins() { + + return $this->plugins; + + } + + + /** * Subscribe to an event. * @@ -362,7 +400,7 @@ public function subscribeEvent($event, $callback, $priority = 100) { * @return bool */ public function broadcastEvent($eventName,$arguments = array()) { - + if (isset($this->eventSubscriptions[$eventName])) { foreach($this->eventSubscriptions[$eventName] as $subscriber) { @@ -648,6 +686,14 @@ protected function httpPropfind($uri) { // This is a multi-status response $this->httpResponse->sendStatus(207); $this->httpResponse->setHeader('Content-Type','application/xml; charset=utf-8'); + + // Normally this header is only needed for OPTIONS responses, however.. + // iCal seems to also depend on these being set for PROPFIND. Since + // this is not harmful, we'll add it. + $features = array('1','3', 'extended-mkcol'); + foreach($this->plugins as $plugin) $features = array_merge($features,$plugin->getFeatures()); + $this->httpResponse->setHeader('DAV',implode(', ',$features)); + $data = $this->generateMultiStatus($newProperties); $this->httpResponse->sendBody($data); @@ -845,6 +891,11 @@ protected function httpMkcol($uri) { protected function httpMove($uri) { $moveInfo = $this->getCopyAndMoveInfo(); + + // If the destination is part of the source tree, we must fail + if ($moveInfo['destination']==$uri) + throw new Sabre_DAV_Exception_Forbidden('Source and destination uri are identical.'); + if ($moveInfo['destinationExists']) { if (!$this->broadcastEvent('beforeUnbind',array($moveInfo['destination']))) return false; @@ -875,8 +926,11 @@ protected function httpMove($uri) { protected function httpCopy($uri) { $copyInfo = $this->getCopyAndMoveInfo(); - if ($copyInfo['destinationExists']) { + // If the destination is part of the source tree, we must fail + if ($copyInfo['destination']==$uri) + throw new Sabre_DAV_Exception_Forbidden('Source and destination uri are identical.'); + if ($copyInfo['destinationExists']) { if (!$this->broadcastEvent('beforeUnbind',array($copyInfo['destination']))) return false; $this->tree->delete($copyInfo['destination']); @@ -1214,17 +1268,16 @@ public function getPropertiesForPath($path,$propertyNames = array(),$depth = 0) foreach($nodes as $myPath=>$node) { + $currentPropertyNames = $propertyNames; + $newProperties = array( '200' => array(), '404' => array(), ); - if ($node instanceof Sabre_DAV_IProperties) - $newProperties['200'] = $node->getProperties($propertyNames); if ($allProperties) { - // Default list of propertyNames, when all properties were requested. - $propertyNames = array( + $currentPropertyNames = array( '{DAV:}getlastmodified', '{DAV:}getcontentlength', '{DAV:}resourcetype', @@ -1233,14 +1286,6 @@ public function getPropertiesForPath($path,$propertyNames = array(),$depth = 0) '{DAV:}getetag', '{DAV:}getcontenttype', ); - - // We need to make sure this includes any propertyname already returned from - // $node->getProperties(); - $propertyNames = array_merge($propertyNames, array_keys($newProperties[200])); - - // Making sure there's no double entries - $propertyNames = array_unique($propertyNames); - } // If the resourceType was not part of the list, we manually add it @@ -1248,19 +1293,31 @@ public function getPropertiesForPath($path,$propertyNames = array(),$depth = 0) // to make certain decisions about the entry. // WebDAV dictates we should add a / and the end of href's for collections $removeRT = false; - if (!in_array('{DAV:}resourcetype',$propertyNames)) { - $propertyNames[] = '{DAV:}resourcetype'; + if (!in_array('{DAV:}resourcetype',$currentPropertyNames)) { + $currentPropertyNames[] = '{DAV:}resourcetype'; $removeRT = true; } - foreach($propertyNames as $prop) { + $result = $this->broadcastEvent('beforeGetProperties',array($myPath, $node, &$currentPropertyNames, &$newProperties)); + // If this method explicitly returned false, we must ignore this + // node as it is inacessible. + if ($result===false) continue; + + if (count($currentPropertyNames) > 0) { + + if ($node instanceof Sabre_DAV_IProperties) + $newProperties['200'] = $newProperties[200] + $node->getProperties($currentPropertyNames); + + } + + + foreach($currentPropertyNames as $prop) { if (isset($newProperties[200][$prop])) continue; switch($prop) { case '{DAV:}getlastmodified' : if ($node->getLastModified()) $newProperties[200][$prop] = new Sabre_DAV_Property_GetLastModified($node->getLastModified()); break; case '{DAV:}getcontentlength' : if ($node instanceof Sabre_DAV_IFile) $newProperties[200][$prop] = (int)$node->getSize(); break; - case '{DAV:}resourcetype' : $newProperties[200][$prop] = new Sabre_DAV_Property_ResourceType($node instanceof Sabre_DAV_ICollection?self::NODE_DIRECTORY:self::NODE_FILE); break; case '{DAV:}quota-used-bytes' : if ($node instanceof Sabre_DAV_IQuota) { $quotaInfo = $node->getQuotaInfo(); @@ -1275,7 +1332,19 @@ public function getPropertiesForPath($path,$propertyNames = array(),$depth = 0) break; case '{DAV:}getetag' : if ($node instanceof Sabre_DAV_IFile && $etag = $node->getETag()) $newProperties[200][$prop] = $etag; break; case '{DAV:}getcontenttype' : if ($node instanceof Sabre_DAV_IFile && $ct = $node->getContentType()) $newProperties[200][$prop] = $ct; break; - case '{DAV:}supported-report-set' : $newProperties[200][$prop] = new Sabre_DAV_Property_SupportedReportSet(); break; + case '{DAV:}supported-report-set' : + $reports = array(); + foreach($this->plugins as $plugin) { + $reports = array_merge($reports, $plugin->getSupportedReportSet($myPath)); + } + $newProperties[200][$prop] = new Sabre_DAV_Property_SupportedReportSet($reports); + break; + case '{DAV:}resourcetype' : + $newProperties[200]['{DAV:}resourcetype'] = new Sabre_DAV_Property_ResourceType(); + foreach($this->resourceTypeMapping as $className => $resourceType) { + if ($node instanceof $className) $newProperties[200]['{DAV:}resourcetype']->add($resourceType); + } + break; } @@ -1292,7 +1361,7 @@ public function getPropertiesForPath($path,$propertyNames = array(),$depth = 0) // Apple's iCal also requires a trailing slash for principals (rfc 3744). // Therefore we add a trailing / for any non-file. This might need adjustments // if we find there are other edge cases. - if ($myPath!='' && isset($newProperties[200]['{DAV:}resourcetype']) && $newProperties[200]['{DAV:}resourcetype']->getValue()!==null) $newProperties['href'] .='/'; + if ($myPath!='' && isset($newProperties[200]['{DAV:}resourcetype']) && count($newProperties[200]['{DAV:}resourcetype']->getValue())>0) $newProperties['href'] .='/'; // If the resourcetype property was manually added to the requested property list, // we will remove it again. @@ -1483,11 +1552,27 @@ public function updateProperties($uri, array $properties) { $remainingProperties = $properties; $hasError = false; + // Running through all properties to make sure none of them are protected + if (!$hasError) foreach($properties as $propertyName => $value) { + if(in_array($propertyName, $this->protectedProperties)) { + $result[403][$propertyName] = null; + unset($remainingProperties[$propertyName]); + $hasError = true; + } + } + + if (!$hasError) { + // Allowing plugins to take care of property updating + $hasError = !$this->broadcastEvent('updateProperties',array( + &$remainingProperties, + &$result, + $node + )); + } // If the node is not an instance of Sabre_DAV_IProperties, every // property is 403 Forbidden - // simply return a 405. - if (!($node instanceof Sabre_DAV_IProperties)) { + if (!$hasError && count($remainingProperties) && !($node instanceof Sabre_DAV_IProperties)) { $hasError = true; foreach($properties as $propertyName=> $value) { $result[403][$propertyName] = null; @@ -1495,39 +1580,43 @@ public function updateProperties($uri, array $properties) { $remainingProperties = array(); } - // Running through all properties to make sure none of them are protected - if (!$hasError) foreach($properties as $propertyName => $value) { - if(in_array($propertyName, $this->protectedProperties)) { - $result[403][$propertyName] = null; - unset($remainingProperties[$propertyName]); - $hasError = true; - } - } - // Only if there were no errors we may attempt to update the resource if (!$hasError) { - $updateResult = $node->updateProperties($properties); - $remainingProperties = array(); - if ($updateResult===true) { - // success - foreach($properties as $propertyName=>$value) { - $result[200][$propertyName] = null; - } + if (count($remainingProperties)>0) { - } elseif ($updateResult===false) { - // The node failed to update the properties for an - // unknown reason - foreach($properties as $propertyName=>$value) { - $result[403][$propertyName] = null; - } + $updateResult = $node->updateProperties($remainingProperties); - } elseif (is_array($updateResult)) { - // The node has detailed update information - $result = $updateResult; + if ($updateResult===true) { + // success + foreach($remainingProperties as $propertyName=>$value) { + $result[200][$propertyName] = null; + } - } else { - throw new Sabre_DAV_Exception('Invalid result from updateProperties'); + } elseif ($updateResult===false) { + // The node failed to update the properties for an + // unknown reason + foreach($remainingProperties as $propertyName=>$value) { + $result[403][$propertyName] = null; + } + + } elseif (is_array($updateResult)) { + + // The node has detailed update information + // We need to merge the results with the earlier results. + foreach($updateResult as $status => $props) { + if (is_array($props)) { + if (!isset($result[$status])) + $result[$status] = array(); + + $result[$status] = array_merge($result[$status], $updateResult[$status]); + } + } + + } else { + throw new Sabre_DAV_Exception('Invalid result from updateProperties'); + } + $remainingProperties = array(); } } diff --git a/library/SabreDAV/lib/Sabre/DAV/ServerPlugin.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/ServerPlugin.php similarity index 64% rename from library/SabreDAV/lib/Sabre/DAV/ServerPlugin.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/ServerPlugin.php index f38e8aa3f..6909f600c 100644 --- a/library/SabreDAV/lib/Sabre/DAV/ServerPlugin.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/ServerPlugin.php @@ -7,7 +7,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ @@ -56,5 +56,35 @@ public function getHTTPMethods($uri) { } + /** + * Returns a plugin name. + * + * Using this name other plugins will be able to access other plugins + * using Sabre_DAV_Server::getPlugin + * + * @return string + */ + public function getPluginName() { + + return get_class($this); + + } + + /** + * Returns a list of reports this plugin supports. + * + * This will be used in the {DAV:}supported-report-set property. + * Note that you still need to subscribe to the 'report' event to actually + * implement them + * + * @param string $uri + * @return array + */ + public function getSupportedReportSet($uri) { + + return array(); + + } + } diff --git a/library/SabreDAV/lib/Sabre/DAV/SimpleDirectory.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/SimpleDirectory.php similarity index 95% rename from library/SabreDAV/lib/Sabre/DAV/SimpleDirectory.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/SimpleDirectory.php index 132992786..8c79962a9 100644 --- a/library/SabreDAV/lib/Sabre/DAV/SimpleDirectory.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/SimpleDirectory.php @@ -8,7 +8,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ @@ -86,7 +86,7 @@ public function getName() { public function getChild($name) { if (isset($this->children[$name])) return $this->children[$name]; - throw new Sabre_DAV_Exception_FileNotFound('File not found: ' . $name); + throw new Sabre_DAV_Exception_FileNotFound('File not found: ' . $name . ' in \'' . $this->getName() . '\''); } diff --git a/library/SabreDAV/lib/Sabre/DAV/TemporaryFileFilterPlugin.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/TemporaryFileFilterPlugin.php similarity index 99% rename from library/SabreDAV/lib/Sabre/DAV/TemporaryFileFilterPlugin.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/TemporaryFileFilterPlugin.php index 2184f6eea..e8276af56 100644 --- a/library/SabreDAV/lib/Sabre/DAV/TemporaryFileFilterPlugin.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/TemporaryFileFilterPlugin.php @@ -22,7 +22,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/Tree.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Tree.php similarity index 98% rename from library/SabreDAV/lib/Sabre/DAV/Tree.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Tree.php index f7191e239..98e6f62c9 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Tree.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Tree.php @@ -5,7 +5,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/Tree/Filesystem.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Tree/Filesystem.php similarity index 97% rename from library/SabreDAV/lib/Sabre/DAV/Tree/Filesystem.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/Tree/Filesystem.php index ee195eb22..5c611047e 100644 --- a/library/SabreDAV/lib/Sabre/DAV/Tree/Filesystem.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/Tree/Filesystem.php @@ -5,7 +5,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/library/SabreDAV/lib/Sabre/DAV/URLUtil.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/URLUtil.php similarity index 98% rename from library/SabreDAV/lib/Sabre/DAV/URLUtil.php rename to modules/webdav/library/SabreDAV/lib/Sabre/DAV/URLUtil.php index 0dfc68966..1502e4dd2 100644 --- a/library/SabreDAV/lib/Sabre/DAV/URLUtil.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/URLUtil.php @@ -14,7 +14,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ diff --git a/modules/webdav/library/SabreDAV/lib/Sabre/DAV/UUIDUtil.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/UUIDUtil.php new file mode 100644 index 000000000..e42a536ad --- /dev/null +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAV/UUIDUtil.php @@ -0,0 +1,64 @@ +principalPrefix = $principalPrefix; + $this->principalBackend = $principalBackend; + + } + + /** + * This method returns a node for a principal. + * + * The passed array contains principal information, and is guaranteed to + * at least contain a uri item. Other properties may or may not be + * supplied by the authentication backend. + * + * @param array $principalInfo + * @return Sabre_DAVACL_IPrincipal + */ + abstract function getChildForPrincipal(array $principalInfo); + + /** + * Returns the name of this collection. + * + * @return string + */ + public function getName() { + + list(,$name) = Sabre_DAV_URLUtil::splitPath($this->principalPrefix); + return $name; + + } + + /** + * Return the list of users + * + * @return void + */ + public function getChildren() { + + if ($this->disableListing) + throw new Sabre_DAV_Exception_MethodNotAllowed('Listing members of this collection is disabled'); + + $children = array(); + foreach($this->principalBackend->getPrincipalsByPrefix($this->principalPrefix) as $principalInfo) { + + $children[] = $this->getChildForPrincipal($principalInfo); + + + } + return $children; + + } + + /** + * Returns a child object, by its name. + * + * @param string $name + * @throws Sabre_DAV_Exception_FileNotFound + * @return Sabre_DAV_IPrincipal + */ + public function getChild($name) { + + $principalInfo = $this->principalBackend->getPrincipalByPath($this->principalPrefix . '/' . $name); + if (!$principalInfo) throw new Sabre_DAV_Exception_FileNotFound('Principal with name ' . $name . ' not found'); + return $this->getChildForPrincipal($principalInfo); + + } + +} diff --git a/modules/webdav/library/SabreDAV/lib/Sabre/DAVACL/Exception/NeedPrivileges.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAVACL/Exception/NeedPrivileges.php new file mode 100644 index 000000000..640ab8eff --- /dev/null +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAVACL/Exception/NeedPrivileges.php @@ -0,0 +1,84 @@ +uri = $uri; + $this->privileges = $privileges; + + } + + /** + * Adds in extra information in the xml response. + * + * This method adds the {DAV:}need-privileges element as defined in rfc3744 + * + * @param Sabre_DAV_Server $server + * @param DOMElement $errorNode + * @return void + */ + public function serialize(Sabre_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])); + + + } + + } + +} + diff --git a/modules/webdav/library/SabreDAV/lib/Sabre/DAVACL/IACL.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAVACL/IACL.php new file mode 100644 index 000000000..506be4248 --- /dev/null +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAVACL/IACL.php @@ -0,0 +1,58 @@ +getCurrentUserPrivilegeSet($uri); + + if (is_null($acl)) { + if ($this->allowAccessToNodesWithoutACL) { + return true; + } else { + if ($throwExceptions) + throw new Sabre_DAVACL_Exception_NeedPrivileges($uri,$privileges); + else + return false; + + } + } + + $failed = array(); + foreach($privileges as $priv) { + + if (!in_array($priv, $acl)) { + $failed[] = $priv; + } + + } + + if ($failed) { + if ($throwExceptions) + throw new Sabre_DAVACL_Exception_NeedPrivileges($uri,$failed); + else + return false; + } + return true; + + } + + /** + * Returns the standard users' principal. + * + * This is one authorative principal url for the current user. + * This method will return null if the user wasn't logged in. + * + * @return string|null + */ + public function getCurrentUserPrincipal() { + + $authPlugin = $this->server->getPlugin('auth'); + if (is_null($authPlugin)) return null; + + $userName = $authPlugin->getCurrentUser(); + if (!$userName) return null; + + return $this->defaultUsernamePath . '/' . $userName; + + } + + /** + * Returns a list of principals that's associated to the current + * user, either directly or through group membership. + * + * @return array + */ + public function getCurrentUserPrincipals() { + + $currentUser = $this->getCurrentUserPrincipal(); + + if (is_null($currentUser)) return array(); + + $check = array($currentUser); + $principals = array($currentUser); + + while(count($check)) { + + $principal = array_shift($check); + + $node = $this->server->tree->getNodeForPath($principal); + if ($node instanceof Sabre_DAVACL_IPrincipal) { + foreach($node->getGroupMembership() as $groupMember) { + + if (!in_array($groupMember, $principals)) { + + $check[] = $groupMember; + $principals[] = $groupMember; + + } + + } + + } + + } + + return $principals; + + } + + /** + * Returns the supported privilege structure for this ACL plugin. + * + * See RFC3744 for more details. Currently we default on a simple, + * standard structure. + * + * @return array + */ + public function getSupportedPrivilegeSet() { + + return array( + 'privilege' => '{DAV:}all', + 'abstract' => true, + 'aggregates' => array( + array( + 'privilege' => '{DAV:}read', + 'aggregates' => array( + array( + 'privilege' => '{DAV:}read-acl', + 'abstract' => true, + ), + array( + 'privilege' => '{DAV:}read-current-user-privilege-set', + 'abstract' => true, + ), + ), + ), // {DAV:}read + array( + 'privilege' => '{DAV:}write', + 'aggregates' => array( + array( + 'privilege' => '{DAV:}write-acl', + 'abstract' => true, + ), + array( + 'privilege' => '{DAV:}write-properties', + 'abstract' => true, + ), + array( + 'privilege' => '{DAV:}write-content', + 'abstract' => true, + ), + array( + 'privilege' => '{DAV:}bind', + 'abstract' => true, + ), + array( + 'privilege' => '{DAV:}unbind', + 'abstract' => true, + ), + array( + 'privilege' => '{DAV:}unlock', + 'abstract' => true, + ), + ), + ), // {DAV:}write + ), + ); // {DAV:}all + + } + + /** + * Returns the supported privilege set as a flat list + * + * This is much easier to parse. + * + * The returned list will be index by privilege name. + * The value is a struct containing the following properties: + * - aggregates + * - abstract + * - concrete + * + * @return array + */ + final public function getFlatPrivilegeSet() { + + $privs = $this->getSupportedPrivilegeSet(); + + $flat = array(); + $this->getFPSTraverse($privs, null, $flat); + + return $flat; + + } + + /** + * Traverses the privilege set tree for reordering + * + * This function is solely used by getFlatPrivilegeSet, and would have been + * a closure if it wasn't for the fact I need to support PHP 5.2. + * + * @return void + */ + final private function getFPSTraverse($priv, $concrete, &$flat) { + + $myPriv = array( + 'privilege' => $priv['privilege'], + 'abstract' => isset($priv['abstract']) && $priv['abstract'], + 'aggregates' => array(), + 'concrete' => isset($priv['abstract']) && $priv['abstract']?$concrete:$priv['privilege'], + ); + + if (isset($priv['aggregates'])) + foreach($priv['aggregates'] as $subPriv) $myPriv['aggregates'][] = $subPriv['privilege']; + + $flat[$priv['privilege']] = $myPriv; + + if (isset($priv['aggregates'])) { + + foreach($priv['aggregates'] as $subPriv) { + + $this->getFPSTraverse($subPriv, $myPriv['concrete'], $flat); + + } + + } + + } + + /** + * Returns the full ACL list. + * + * Either a uri or a Sabre_DAV_INode may be passed. + * + * null will be returned if the node doesn't support ACLs. + * + * @param string|Sabre_DAV_INode $node + * @return array + */ + public function getACL($node) { + + if (is_string($node)) { + $node = $this->server->tree->getNodeForPath($node); + } + if ($node instanceof Sabre_DAVACL_IACL) { + return $node->getACL(); + } + return null; + + } + + /** + * Returns a list of privileges the current user has + * on a particular node. + * + * Either a uri or a Sabre_DAV_INode may be passed. + * + * null will be returned if the node doesn't support ACLs. + * + * @param string|Sabre_DAV_INode $node + * @return array + */ + public function getCurrentUserPrivilegeSet($node) { + + if (is_string($node)) { + $node = $this->server->tree->getNodeForPath($node); + } + + $acl = $this->getACL($node); + if (is_null($acl)) return null; + + $principals = $this->getCurrentUserPrincipals(); + + $collected = array(); + + foreach($acl as $ace) { + + if (in_array($ace['principal'], $principals)) { + $collected[] = $ace; + } + + } + + // Now we deduct all aggregated privileges. + $flat = $this->getFlatPrivilegeSet(); + + $collected2 = array(); + foreach($collected as $privilege) { + + $collected2[] = $privilege['privilege']; + foreach($flat[$privilege['privilege']]['aggregates'] as $subPriv) { + if (!in_array($subPriv, $collected2)) + $collected2[] = $subPriv; + } + + } + + return $collected2; + + } + + /** + * Sets up the plugin + * + * This method is automatically called by the server class. + * + * @param Sabre_DAV_Server $server + * @return void + */ + public function initialize(Sabre_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')); + + 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['Sabre_DAVACL_IPrincipal'] = '{DAV:}principal'; + + // Mapping the group-member-set property to the HrefList property + // class. + $server->propertyMap['{DAV:}group-member-set'] = 'Sabre_DAV_Property_HrefList'; + + } + + + /* {{{ Event handlers */ + + /** + * Triggered before any method is handled + * + * @param string $method + * @param string $uri + * @return void + */ + public function beforeMethod($method, $uri) { + + $exists = $this->server->tree->nodeExists($uri); + + // If the node doesn't exists, none of these checks apply + if (!$exists) return; + + switch($method) { + + case 'GET' : + case 'HEAD' : + case 'OPTIONS' : + // For these 3 we only need to know if the node is readable. + $this->checkPrivileges($uri,'{DAV:}read'); + break; + + case 'PUT' : + case 'LOCK' : + case 'UNLOCK' : + // This method requires the write-content priv if the node + // already exists, and bind on the parent if the node is being + // created. + // The bind privilege is handled in the beforeBind event. + $this->checkPrivileges($uri,'{DAV:}write-content'); + break; + + + case 'PROPPATCH' : + $this->checkPrivileges($uri,'{DAV:}write-properties'); + break; + + case 'ACL' : + $this->checkPrivileges($uri,'{DAV:}write-acl'); + break; + + case 'COPY' : + case 'MOVE' : + // Copy requires read privileges on the entire source tree. + // If the target exists write-content normally needs to be + // checked, however, we're deleting the node beforehand and + // creating a new one after, so this is handled by the + // beforeUnbind event. + // + // The creation of the new node is handled by the beforeBind + // event. + // + // If MOVE is used beforeUnbind will also be used to check if + // the sourcenode can be deleted. + $this->checkPrivileges($uri,'{DAV:}read',self::R_RECURSIVE); + + break; + + } + + } + + /** + * Triggered before a new node is created. + * + * This allows us to check permissions for any operation that creates a + * new node, such as PUT, MKCOL, MKCALENDAR, LOCK, COPY and MOVE. + * + * @param string $uri + * @return void + */ + public function beforeBind($uri) { + + list($parentUri,$nodeName) = Sabre_DAV_URLUtil::splitPath($uri); + $this->checkPrivileges($parentUri,'{DAV:}bind'); + + } + + /** + * Triggered before a node is deleted + * + * This allows us to check permissions for any operation that will delete + * an existing node. + * + * @param string $uri + * @return void + */ + public function beforeUnbind($uri) { + + list($parentUri,$nodeName) = Sabre_DAV_URLUtil::splitPath($uri); + $this->checkPrivileges($parentUri,'{DAV:}unbind',self::R_RECURSIVEPARENTS); + + } + + /** + * Triggered before a node is unlocked. + * + * @param string $uri + * @param Sabre_DAV_Locks_LockInfo $lock + * @TODO: not yet implemented + * @return void + */ + public function beforeUnlock($uri, Sabre_DAV_Locks_LockInfo $lock) { + + + } + + /** + * Triggered before properties are looked up in specific nodes. + * + * @param string $uri + * @param Sabre_DAV_INode $node + * @param array $requestedProperties + * @param array $returnedProperties + * @TODO really should be broken into multiple methods, or even a class. + * @return void + */ + public function beforeGetProperties($uri, Sabre_DAV_INode $node, &$requestedProperties, &$returnedProperties) { + + // Checking the read permission + if (!$this->checkPrivileges($uri,'{DAV:}read',self::R_PARENT,false)) { + + // User is not allowed to read properties + if ($this->hideNodesFromListings) { + return false; + } + + // Marking all requested properties as '403'. + foreach($requestedProperties as $key=>$requestedProperty) { + unset($requestedProperties[$key]); + $returnedProperties[403][$requestedProperty] = null; + } + return; + + } + + /* Adding principal properties */ + if ($node instanceof Sabre_DAVACL_IPrincipal) { + + if (false !== ($index = array_search('{DAV:}alternate-URI-set', $requestedProperties))) { + + unset($requestedProperties[$index]); + $returnedProperties[200]['{DAV:}alternate-URI-set'] = new Sabre_DAV_Property_HrefList($node->getAlternateUriSet()); + + } + if (false !== ($index = array_search('{DAV:}principal-URL', $requestedProperties))) { + + unset($requestedProperties[$index]); + $returnedProperties[200]['{DAV:}principal-URL'] = new Sabre_DAV_Property_Href($node->getPrincipalUrl() . '/'); + + } + if (false !== ($index = array_search('{DAV:}group-member-set', $requestedProperties))) { + + unset($requestedProperties[$index]); + $returnedProperties[200]['{DAV:}group-member-set'] = new Sabre_DAV_Property_HrefList($node->getGroupMemberSet()); + + } + if (false !== ($index = array_search('{DAV:}group-membership', $requestedProperties))) { + + unset($requestedProperties[$index]); + $returnedProperties[200]['{DAV:}group-membership'] = new Sabre_DAV_Property_HrefList($node->getGroupMembership()); + + } + + if (false !== ($index = array_search('{DAV:}displayname', $requestedProperties))) { + + $returnedProperties[200]['{DAV:}displayname'] = $node->getDisplayName(); + + } + + } + if (false !== ($index = array_search('{DAV:}principal-collection-set', $requestedProperties))) { + + unset($requestedProperties[$index]); + $val = $this->principalCollectionSet; + // Ensuring all collections end with a slash + foreach($val as $k=>$v) $val[$k] = $v . '/'; + $returnedProperties[200]['{DAV:}principal-collection-set'] = new Sabre_DAV_Property_HrefList($val); + + } + if (false !== ($index = array_search('{DAV:}current-user-principal', $requestedProperties))) { + + unset($requestedProperties[$index]); + if ($url = $this->getCurrentUserPrincipal()) { + $returnedProperties[200]['{DAV:}current-user-principal'] = new Sabre_DAV_Property_Principal(Sabre_DAV_Property_Principal::HREF, $url . '/'); + } else { + $returnedProperties[200]['{DAV:}current-user-principal'] = new Sabre_DAV_Property_Principal(Sabre_DAV_Property_Principal::UNAUTHENTICATED); + } + + } + if (false !== ($index = array_search('{DAV:}supported-privilege-set', $requestedProperties))) { + + unset($requestedProperties[$index]); + $returnedProperties[200]['{DAV:}supported-privilege-set'] = new Sabre_DAVACL_Property_SupportedPrivilegeSet($this->getSupportedPrivilegeSet()); + + } + if (false !== ($index = array_search('{DAV:}current-user-privilege-set', $requestedProperties))) { + + if (!$this->checkPrivileges($uri, '{DAV:}read-current-user-privilege-set', self::R_PARENT, false)) { + $returnedProperties[403]['{DAV:}current-user-privilege-set'] = null; + unset($requestedProperties[$index]); + } else { + $val = $this->getCurrentUserPrivilegeSet($node); + if (!is_null($val)) { + unset($requestedProperties[$index]); + $returnedProperties[200]['{DAV:}current-user-privilege-set'] = new Sabre_DAVACL_Property_CurrentUserPrivilegeSet($val); + } + } + + } + + /* The ACL property contains all the permissions */ + if (false !== ($index = array_search('{DAV:}acl', $requestedProperties))) { + + if (!$this->checkPrivileges($uri, '{DAV:}read-acl', self::R_PARENT, false)) { + + unset($requestedProperties[$index]); + $returnedProperties[403]['{DAV:}acl'] = null; + + } else { + + $acl = $this->getACL($node); + if (!is_null($acl)) { + unset($requestedProperties[$index]); + $returnedProperties[200]['{DAV:}acl'] = new Sabre_DAVACL_Property_Acl($this->getACL($node)); + } + + } + + } + + } + + /** + * This method intercepts PROPPATCH methods and make sure the + * group-member-set is updated correctly. + * + * @param array $propertyDelta + * @param array $result + * @param Sabre_DAV_INode $node + * @return void + */ + public function updateProperties(&$propertyDelta, &$result, Sabre_DAV_INode $node) { + + if (!array_key_exists('{DAV:}group-member-set', $propertyDelta)) + return; + + if (is_null($propertyDelta['{DAV:}group-member-set'])) { + $memberSet = array(); + } elseif ($propertyDelta['{DAV:}group-member-set'] instanceof Sabre_DAV_Property_HrefList) { + $memberSet = $propertyDelta['{DAV:}group-member-set']->getHrefs(); + } else { + throw new Sabre_DAV_Exception('The group-member-set property MUST be an instance of Sabre_DAV_Property_HrefList or null'); + } + + if (!($node instanceof Sabre_DAVACL_IPrincipal)) { + $result[403]['{DAV:}group-member-set'] = null; + unset($propertyDelta['{DAV:}group-member-set']); + + // Returning false will stop the updateProperties process + return false; + } + + $node->setGroupMemberSet($memberSet); + + $result[200]['{DAV:}group-member-set'] = null; + unset($propertyDelta['{DAV:}group-member-set']); + + } + + /** + * This method handels HTTP REPORT requests + * + * @param string $reportName + * @param DOMNode $dom + * @return void + */ + public function report($reportName, $dom) { + + switch($reportName) { + + case '{DAV:}principal-property-search' : + $this->principalPropertySearchReport($dom); + return false; + case '{DAV:}principal-search-property-set' : + $this->principalSearchPropertySetReport($dom); + return false; + case '{DAV:}expand-property' : + $this->expandPropertyReport($dom); + return false; + + } + + } + + /* }}} */ + + /* Reports {{{ */ + + /** + * 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 DOMElement $dom + * @return void + */ + protected function expandPropertyReport($dom) { + + $requestedProperties = $this->parseExpandPropertyReportRequest($dom->firstChild->firstChild); + $depth = $this->server->getHTTPDepth(0); + $requestUri = $this->server->getRequestUri(); + + $result = $this->expandProperties($requestUri,$requestedProperties,$depth); + + $dom = new DOMDocument('1.0','utf-8'); + $dom->formatOutput = true; + $multiStatus = $dom->createElement('d:multistatus'); + $dom->appendChild($multiStatus); + + // Adding in default namespaces + foreach($this->server->xmlNamespaces as $namespace=>$prefix) { + + $multiStatus->setAttribute('xmlns:' . $prefix,$namespace); + + } + + foreach($result as $response) { + $response->serialize($this->server, $multiStatus); + } + + $xml = $dom->saveXML(); + $this->server->httpResponse->setHeader('Content-Type','application/xml; charset=utf-8'); + $this->server->httpResponse->sendStatus(207); + $this->server->httpResponse->sendBody($xml); + + } + + /** + * This method is used by expandPropertyReport to parse + * out the entire HTTP request. + * + * @param DOMElement $node + * @return array + */ + protected function parseExpandPropertyReportRequest($node) { + + $requestedProperties = array(); + do { + + if (Sabre_DAV_XMLUtil::toClarkNotation($node)!=='{DAV:}property') continue; + + if ($node->firstChild) { + + $children = $this->parseExpandPropertyReportRequest($node->firstChild); + + } else { + + $children = array(); + + } + + $namespace = $node->getAttribute('namespace'); + if (!$namespace) $namespace = 'DAV:'; + + $propName = '{'.$namespace.'}' . $node->getAttribute('name'); + $requestedProperties[$propName] = $children; + + } while ($node = $node->nextSibling); + + return $requestedProperties; + + } + + /** + * This method expands all the properties and returns + * a list with property values + * + * @param array $path + * @param array $requestedProperties the list of required properties + * @param array $depth + */ + protected function expandProperties($path,array $requestedProperties,$depth) { + + $foundProperties = $this->server->getPropertiesForPath($path,array_keys($requestedProperties),$depth); + + $result = array(); + + foreach($foundProperties as $node) { + + foreach($requestedProperties as $propertyName=>$childRequestedProperties) { + + // We're only traversing if sub-properties were requested + if(count($childRequestedProperties)===0) continue; + + // We only have to do the expansion if the property was found + // and it contains an href element. + if (!array_key_exists($propertyName,$node[200])) continue; + + if ($node[200][$propertyName] instanceof Sabre_DAV_Property_IHref) { + $hrefs = array($node[200][$propertyName]->getHref()); + } elseif ($node[200][$propertyName] instanceof Sabre_DAV_Property_HrefList) { + $hrefs = $node[200][$propertyName]->getHrefs(); + } + + $childProps = array(); + foreach($hrefs as $href) { + $childProps = array_merge($childProps, $this->expandProperties($href,$childRequestedProperties,0)); + } + $node[200][$propertyName] = new Sabre_DAV_Property_ResponseList($childProps); + + } + $result[] = new Sabre_DAV_Property_Response($path, $node); + + } + + return $result; + + } + + /** + * principalSearchPropertySetReport + * + * This method responsible for handing the + * {DAV:}principal-search-property-set report. This report returns a list + * of properties the client may search on, using the + * {DAV:}principal-property-search report. + * + * @param DOMDocument $dom + * @return void + */ + protected function principalSearchPropertySetReport(DOMDocument $dom) { + + $searchProperties = array( + '{DAV:}displayname' => 'display name' + ); + + $httpDepth = $this->server->getHTTPDepth(0); + if ($httpDepth!==0) { + throw new Sabre_DAV_Exception_BadRequest('This report is only defined when Depth: 0'); + } + + if ($dom->firstChild->hasChildNodes()) + throw new Sabre_DAV_Exception_BadRequest('The principal-search-property-set report element is not allowed to have child elements'); + + $dom = new DOMDocument('1.0','utf-8'); + $dom->formatOutput = true; + $root = $dom->createElement('d:principal-search-property-set'); + $dom->appendChild($root); + // Adding in default namespaces + foreach($this->server->xmlNamespaces as $namespace=>$prefix) { + + $root->setAttribute('xmlns:' . $prefix,$namespace); + + } + + $nsList = $this->server->xmlNamespaces; + + foreach($searchProperties as $propertyName=>$description) { + + $psp = $dom->createElement('d:principal-search-property'); + $root->appendChild($psp); + + $prop = $dom->createElement('d:prop'); + $psp->appendChild($prop); + + $propName = null; + preg_match('/^{([^}]*)}(.*)$/',$propertyName,$propName); + + $currentProperty = $dom->createElement($nsList[$propName[1]] . ':' . $propName[2]); + $prop->appendChild($currentProperty); + + $descriptionElem = $dom->createElement('d:description'); + $descriptionElem->setAttribute('xml:lang','en'); + $descriptionElem->appendChild($dom->createTextNode($description)); + $psp->appendChild($descriptionElem); + + + } + + $this->server->httpResponse->setHeader('Content-Type','application/xml; charset=utf-8'); + $this->server->httpResponse->sendStatus(200); + $this->server->httpResponse->sendBody($dom->saveXML()); + + } + + /** + * principalPropertySearchReport + * + * This method is reponsible 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) { + + $searchableProperties = array( + '{DAV:}displayname' => 'display name' + + ); + + list($searchProperties, $requestedProperties, $applyToPrincipalCollectionSet) = $this->parsePrincipalPropertySearchReportRequest($dom); + + $result = array(); + + if ($applyToPrincipalCollectionSet) { + $uris = array(); + } else { + $uris = array($this->server->getRequestUri()); + } + + $lookupResults = array(); + foreach($uris as $uri) { + + $p = array_keys($searchProperties); + $p[] = '{DAV:}resourcetype'; + $r = $this->server->getPropertiesForPath($uri, $p, 1); + + // The first item in the results is the parent, so we get rid of it. + array_shift($r); + $lookupResults = array_merge($lookupResults, $r); + } + + $matches = array(); + + foreach($lookupResults as $lookupResult) { + + // We're only looking for principals + if (!isset($lookupResult[200]['{DAV:}resourcetype']) || + (!($lookupResult[200]['{DAV:}resourcetype'] instanceof Sabre_DAV_Property_ResourceType)) || + !$lookupResult[200]['{DAV:}resourcetype']->is('{DAV:}principal')) continue; + + foreach($searchProperties as $searchProperty=>$searchValue) { + if (!isset($searchableProperties[$searchProperty])) { + // If a property is not 'searchable', the spec dictates + // this is not a match. + continue; + } + + if (isset($lookupResult[200][$searchProperty]) && + mb_stripos($lookupResult[200][$searchProperty], $searchValue, 0, 'UTF-8')!==false) { + $matches[] = $lookupResult['href']; + } + + } + + } + + $matchProperties = array(); + + foreach($matches as $match) { + + list($result) = $this->server->getPropertiesForPath($match, $requestedProperties, 0); + $matchProperties[] = $result; + + } + + $xml = $this->server->generateMultiStatus($matchProperties); + $this->server->httpResponse->setHeader('Content-Type','application/xml; charset=utf-8'); + $this->server->httpResponse->sendStatus(207); + $this->server->httpResponse->sendBody($xml); + + } + + /** + * 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); + + } + + + /* }}} */ + +} diff --git a/modules/webdav/library/SabreDAV/lib/Sabre/DAVACL/Principal.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAVACL/Principal.php new file mode 100644 index 000000000..158b27105 --- /dev/null +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAVACL/Principal.php @@ -0,0 +1,256 @@ +principalBackend = $principalBackend; + $this->principalProperties = $principalProperties; + + } + + /** + * Returns the full principal url + * + * @return string + */ + public function getPrincipalUrl() { + + return $this->principalProperties['uri']; + + } + + /** + * Returns a list of altenative urls for a principal + * + * This can for example be an email address, or ldap url. + * + * @return array + */ + public function getAlternateUriSet() { + + if (isset($this->principalProperties['{http://sabredav.org/ns}email-address'])) { + return array('mailto:' . $this->principalProperties['{http://sabredav.org/ns}email-address']); + } else { + return array(); + } + + } + + /** + * Returns the list of group members + * + * If this principal is a group, this function should return + * all member principal uri's for the group. + * + * @return array + */ + public function getGroupMemberSet() { + + return $this->principalBackend->getGroupMemberSet($this->principalProperties['uri']); + + } + + /** + * Returns the list of groups this principal is member of + * + * If this principal is a member of a (list of) groups, this function + * should return a list of principal uri's for it's members. + * + * @return array + */ + public function getGroupMembership() { + + return $this->principalBackend->getGroupMemberShip($this->principalProperties['uri']); + + } + + + /** + * Sets a list of group members + * + * If this principal is a group, this method sets all the group members. + * The list of members is always overwritten, never appended to. + * + * This method should throw an exception if the members could not be set. + * + * @param array $principals + * @return void + */ + public function setGroupMemberSet(array $groupMembers) { + + $this->principalBackend->setGroupMemberSet($this->principalProperties['uri'], $groupMembers); + + } + + + /** + * Returns this principals name. + * + * @return string + */ + public function getName() { + + $uri = $this->principalProperties['uri']; + list(, $name) = Sabre_DAV_URLUtil::splitPath($uri); + + return $name; + + } + + /** + * Returns the name of the user + * + * @return void + */ + public function getDisplayName() { + + if (isset($this->principalProperties['{DAV:}displayname'])) { + return $this->principalProperties['{DAV:}displayname']; + } else { + return $this->getName(); + } + + } + + /** + * Returns a list of properties + * + * @param array $requestedProperties + * @return void + */ + public function getProperties($requestedProperties) { + + $newProperties = array(); + foreach($requestedProperties as $propName) { + + if (isset($this->principalProperties[$propName])) { + $newProperties[$propName] = $this->principalProperties[$propName]; + } + + } + + return $newProperties; + + } + + /** + * Updates this principals properties. + * + * Currently this is not supported + * + * @param array $properties + * @see Sabre_DAV_IProperties::updateProperties + * @return bool|array + */ + public function updateProperties($properties) { + + return false; + + } + + /** + * Returns the owner principal + * + * This must be a url to a principal, or null if there's no owner + * + * @return string|null + */ + public function getOwner() { + + return $this->principalProperties['uri']; + + + } + + /** + * Returns a group principal + * + * This must be a url to a principal, or null if there's no owner + * + * @return string|null + */ + public function getGroup() { + + return null; + + } + + /** + * Returns a list of ACE's for this node. + * + * Each ACE has the following properties: + * * 'privilege', a string such as {DAV:}read or {DAV:}write. These are + * currently the only supported privileges + * * 'principal', a url to the principal who owns the node + * * 'protected' (optional), indicating that this ACE is not allowed to + * be updated. + * + * @return array + */ + public function getACL() { + + return array( + array( + 'privilege' => '{DAV:}read', + 'principal' => $this->principalProperties['uri'], + 'protected' => true, + ), + ); + + } + + /** + * Updates the ACL + * + * This method will receive a list of new ACE's. + * + * @param array $acl + * @return void + */ + public function setACL(array $acl) { + + throw new Sabre_DAV_Exception_MethodNotAllowed('Updating ACLs is not allowed here'); + + } + +} diff --git a/modules/webdav/library/SabreDAV/lib/Sabre/DAVACL/PrincipalBackend/PDO.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAVACL/PrincipalBackend/PDO.php new file mode 100644 index 000000000..d5b533218 --- /dev/null +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAVACL/PrincipalBackend/PDO.php @@ -0,0 +1,189 @@ +pdo = $pdo; + + } + + + /** + * Returns a list of principals based on a prefix. + * + * This prefix will often contain something like 'principals'. You are only + * expected to return principals that are in this base path. + * + * You are expected to return at least a 'uri' for every user, you can + * return any additional properties if you wish so. Common properties are: + * {DAV:}displayname + * {http://sabredav.org/ns}email-address - This is a custom SabreDAV + * field that's actualy injected in a number of other properties. If + * you have an email address, use this property. + * + * @param string $prefixPath + * @return array + */ + public function getPrincipalsByPrefix($prefixPath) { + $result = $this->pdo->query('SELECT uri, email, displayname FROM principals'); + + $principals = array(); + + while($row = $result->fetch(PDO::FETCH_ASSOC)) { + + // Checking if the principal is in the prefix + list($rowPrefix) = Sabre_DAV_URLUtil::splitPath($row['uri']); + if ($rowPrefix !== $prefixPath) continue; + + $principals[] = array( + 'uri' => $row['uri'], + '{DAV:}displayname' => $row['displayname']?$row['displayname']:basename($row['uri']), + '{http://sabredav.org/ns}email-address' => $row['email'], + ); + + } + + return $principals; + + } + + /** + * Returns a specific principal, specified by it's path. + * The returned structure should be the exact same as from + * getPrincipalsByPrefix. + * + * @param string $path + * @return array + */ + public function getPrincipalByPath($path) { + + $stmt = $this->pdo->prepare('SELECT id, uri, email, displayname FROM principals WHERE uri = ?'); + $stmt->execute(array($path)); + + $users = array(); + + $row = $stmt->fetch(PDO::FETCH_ASSOC); + if (!$row) return; + + return array( + 'id' => $row['id'], + 'uri' => $row['uri'], + '{DAV:}displayname' => $row['displayname']?$row['displayname']:basename($row['uri']), + '{http://sabredav.org/ns}email-address' => $row['email'], + ); + + } + + /** + * Returns the list of members for a group-principal + * + * @param string $principal + * @return array + */ + public function getGroupMemberSet($principal) { + + $principal = $this->getPrincipalByPath($principal); + if (!$principal) throw new Sabre_DAV_Exception('Principal not found'); + + $stmt = $this->pdo->prepare('SELECT principals.uri as uri FROM groupmembers LEFT JOIN principals ON groupmembers.member_id = principals.id WHERE groupmembers.principal_id = ?'); + $stmt->execute(array($principal['id'])); + + $result = array(); + while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { + $result[] = $row['uri']; + } + return $result; + + } + + /** + * Returns the list of groups a principal is a member of + * + * @param string $principal + * @return array + */ + public function getGroupMembership($principal) { + + $principal = $this->getPrincipalByPath($principal); + if (!$principal) throw new Sabre_DAV_Exception('Principal not found'); + + $stmt = $this->pdo->prepare('SELECT principals.uri as uri FROM groupmembers LEFT JOIN principals ON groupmembers.principal_id = principals.id WHERE groupmembers.member_id = ?'); + $stmt->execute(array($principal['id'])); + + $result = array(); + while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { + $result[] = $row['uri']; + } + return $result; + + } + + /** + * Updates the list of group members for a group principal. + * + * The principals should be passed as a list of uri's. + * + * @param string $principal + * @param array $members + * @return void + */ + public function setGroupMemberSet($principal, array $members) { + + // Grabbing the list of principal id's. + $stmt = $this->pdo->prepare('SELECT id, uri FROM principals WHERE uri IN (? ' . str_repeat(', ? ', count($members)) . ');'); + $stmt->execute(array_merge(array($principal), $members)); + + $memberIds = array(); + $principalId = null; + + while($row = $stmt->fetch(PDO::FETCH_ASSOC)) { + if ($row['uri'] == $principal) { + $principalId = $row['id']; + } else { + $memberIds[] = $row['id']; + } + } + if (!$principalId) throw new Sabre_DAV_Exception('Principal not found'); + + // Wiping out old members + $stmt = $this->pdo->prepare('DELETE FROM groupmembers WHERE principal_id = ?;'); + $stmt->execute(array($principalId)); + + foreach($memberIds as $memberId) { + + $stmt = $this->pdo->prepare('INSERT INTO groupmembers (principal_id, member_id) VALUES (?, ?);'); + $stmt->execute(array($principalId, $memberId)); + + } + + } + +} diff --git a/modules/webdav/library/SabreDAV/lib/Sabre/DAVACL/PrincipalCollection.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAVACL/PrincipalCollection.php new file mode 100644 index 000000000..3cc0ae846 --- /dev/null +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAVACL/PrincipalCollection.php @@ -0,0 +1,35 @@ +principalBackend, $principal); + + } + +} diff --git a/modules/webdav/library/SabreDAV/lib/Sabre/DAVACL/Property/Acl.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAVACL/Property/Acl.php new file mode 100644 index 000000000..fcdf17bb2 --- /dev/null +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAVACL/Property/Acl.php @@ -0,0 +1,89 @@ +privileges = $privileges; + + } + + /** + * Serializes the property into a DOMElement + * + * @param Sabre_DAV_Server $server + * @param DOMElement $node + * @return void + */ + public function serialize(Sabre_DAV_Server $server,DOMElement $node) { + + $doc = $node->ownerDocument; + foreach($this->privileges as $ace) { + + $this->serializeAce($doc, $node, $ace, $server); + + } + + } + + /** + * Serializes a single access control entry. + * + * @param DOMDocument $doc + * @param DOMElement $node + * @param array $ace + * @param Sabre_DAV_Server $server + * @return void + */ + private function serializeAce($doc,$node,$ace, $server) { + + $xace = $doc->createElementNS('DAV:','d:ace'); + $node->appendChild($xace); + + $principal = $doc->createElementNS('DAV:','d:principal'); + $xace->appendChild($principal); + $principal->appendChild($doc->createElementNS('DAV:','d:href',$server->getBaseUri() . $ace['principal'] . '/')); + + $grant = $doc->createElementNS('DAV:','d:grant'); + $xace->appendChild($grant); + + foreach($ace['grant'] as $privName) { + + $privParts = null; + + preg_match('/^{([^}]*)}(.*)$/',$privName,$privParts); + + $xprivilege = $doc->createElementNS('DAV:','d:privilege'); + $grant->appendChild($xprivilege); + + $xprivilege->appendChild($doc->createElementNS($privParts[1],'d:'.$privParts[2])); + + } + + } + +} diff --git a/modules/webdav/library/SabreDAV/lib/Sabre/DAVACL/Property/CurrentUserPrivilegeSet.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAVACL/Property/CurrentUserPrivilegeSet.php new file mode 100644 index 000000000..72274597b --- /dev/null +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAVACL/Property/CurrentUserPrivilegeSet.php @@ -0,0 +1,75 @@ +privileges = $privileges; + + } + + /** + * Serializes the property in the DOM + * + * @param Sabre_DAV_Server $server + * @param DOMElement $node + * @return void + */ + public function serialize(Sabre_DAV_Server $server,DOMElement $node) { + + $doc = $node->ownerDocument; + foreach($this->privileges as $privName) { + + $this->serializePriv($doc,$node,$privName); + + } + + } + + /** + * Serializes one privilege + * + * @param DOMDocument $doc + * @param DOMElement $node + * @param string $privName + * @return void + */ + protected function serializePriv($doc,$node,$privName) { + + $xp = $doc->createElementNS('DAV:','d:privilege'); + $node->appendChild($xp); + + $privParts = null; + preg_match('/^{([^}]*)}(.*)$/',$privName,$privParts); + + $xp->appendChild($doc->createElementNS($privParts[1],'d:'.$privParts[2])); + + } + +} diff --git a/modules/webdav/library/SabreDAV/lib/Sabre/DAVACL/Property/SupportedPrivilegeSet.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAVACL/Property/SupportedPrivilegeSet.php new file mode 100644 index 000000000..93c389503 --- /dev/null +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAVACL/Property/SupportedPrivilegeSet.php @@ -0,0 +1,92 @@ +privileges = $privileges; + + } + + /** + * Serializes the property into a domdocument. + * + * @param Sabre_DAV_Server $server + * @param DOMElement $node + * @return void + */ + public function serialize(Sabre_DAV_Server $server,DOMElement $node) { + + $doc = $node->ownerDocument; + $this->serializePriv($doc, $node, $this->privileges); + + } + + /** + * Serializes a property + * + * This is a recursive function. + * + * @param DOMDocument $doc + * @param DOMElement $node + * @param array $privilege + * @return void + */ + private function serializePriv($doc,$node,$privilege) { + + $xsp = $doc->createElementNS('DAV:','d:supported-privilege'); + $node->appendChild($xsp); + + $xp = $doc->createElementNS('DAV:','d:privilege'); + $xsp->appendChild($xp); + + $privParts = null; + preg_match('/^{([^}]*)}(.*)$/',$privilege['privilege'],$privParts); + + $xp->appendChild($doc->createElementNS($privParts[1],'d:'.$privParts[2])); + + if (isset($privilege['abstract']) && $privilege['abstract']) { + $xsp->appendChild($doc->createElementNS('DAV:','d:abstract')); + } + + if (isset($privilege['description'])) { + $xsp->appendChild($doc->createElementNS('DAV:','d:description',$privilege['description'])); + } + + if (isset($privilege['aggregates'])) { + foreach($privilege['aggregates'] as $subPrivilege) { + $this->serializePriv($doc,$xsp,$subPrivilege); + } + } + + } + +} diff --git a/modules/webdav/library/SabreDAV/lib/Sabre/DAVACL/Version.php b/modules/webdav/library/SabreDAV/lib/Sabre/DAVACL/Version.php new file mode 100644 index 000000000..3eade0331 --- /dev/null +++ b/modules/webdav/library/SabreDAV/lib/Sabre/DAVACL/Version.php @@ -0,0 +1,24 @@ +_SERVER[$serverName])?$this->_SERVER[$serverName]:null; + $name = strtoupper(str_replace(array('-'),array('_'),$name)); + if (isset($this->_SERVER['HTTP_' . $name])) { + return $this->_SERVER['HTTP_' . $name]; + } + + // There's a few headers that seem to end up in the top-level + // server array. + switch($name) { + case 'CONTENT_TYPE' : + case 'CONTENT_LENGTH' : + if (isset($this->_SERVER[$name])) { + return $this->_SERVER[$name]; + } + break; + + } + return; } @@ -86,8 +101,16 @@ public function getHeaders() { $hdrs = array(); foreach($this->_SERVER as $key=>$value) { - if (strpos($key,'HTTP_')===0) { - $hdrs[substr(strtolower(str_replace('_','-',$key)),5)] = $value; + switch($key) { + case 'CONTENT_LENGTH' : + case 'CONTENT_TYPE' : + $hdrs[strtolower(str_replace('_','-',$key))] = $value; + break; + default : + if (strpos($key,'HTTP_')===0) { + $hdrs[substr(strtolower(str_replace('_','-',$key)),5)] = $value; + } + break; } } @@ -173,7 +196,7 @@ public function getBody($asString = false) { } /** - * Sets the contents of the HTTP requet body + * Sets the contents of the HTTP request body * * This method can either accept a string, or a readable stream resource. * diff --git a/library/SabreDAV/lib/Sabre/HTTP/Response.php b/modules/webdav/library/SabreDAV/lib/Sabre/HTTP/Response.php similarity index 97% rename from library/SabreDAV/lib/Sabre/HTTP/Response.php rename to modules/webdav/library/SabreDAV/lib/Sabre/HTTP/Response.php index 15a268746..c8c77251a 100644 --- a/library/SabreDAV/lib/Sabre/HTTP/Response.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/HTTP/Response.php @@ -5,7 +5,7 @@ * * @package Sabre * @subpackage HTTP - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ @@ -73,6 +73,7 @@ public function getStatusMessage($code) { 506 => 'Variant Also Negotiates', 507 => 'Unsufficient Storage', // RFC 4918 508 => 'Loop Detected', // RFC 5842 + 509 => 'Bandwidth Limit Exceeded', // non-standard 510 => 'Not extended', ); diff --git a/library/SabreDAV/lib/Sabre/HTTP/Util.php b/modules/webdav/library/SabreDAV/lib/Sabre/HTTP/Util.php similarity index 80% rename from library/SabreDAV/lib/Sabre/HTTP/Util.php rename to modules/webdav/library/SabreDAV/lib/Sabre/HTTP/Util.php index 02ae1c0fa..8a6bd7df4 100644 --- a/library/SabreDAV/lib/Sabre/HTTP/Util.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/HTTP/Util.php @@ -5,7 +5,7 @@ * * @package Sabre * @subpackage HTTP - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @author Paul Voegler * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License @@ -28,18 +28,18 @@ static function parseHTTPDate($dateHeader) { $weekday = '(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday)'; $wkday = '(Mon|Tue|Wed|Thu|Fri|Sat|Sun)'; $time = '[0-2]\d(\:[0-5]\d){2}'; - $date3 = $month . '\ ([1-3]\d|\ \d)'; + $date3 = $month . ' ([1-3]\d| \d)'; $date2 = '[0-3]\d\-' . $month . '\-\d\d'; //4-digit year cannot begin with 0 - unix timestamp begins in 1970 - $date1 = '[0-3]\d\ ' . $month . '\ [1-9]\d{3}'; + $date1 = '[0-3]\d ' . $month . ' [1-9]\d{3}'; //ANSI C's asctime() format //4-digit year cannot begin with 0 - unix timestamp begins in 1970 - $asctime_date = $wkday . '\ ' . $date3 . '\ ' . $time . '\ [1-9]\d{3}'; + $asctime_date = $wkday . ' ' . $date3 . ' ' . $time . ' [1-9]\d{3}'; //RFC 850, obsoleted by RFC 1036 - $rfc850_date = $weekday . ',\ ' . $date2 . '\ ' . $time . '\ GMT'; + $rfc850_date = $weekday . ', ' . $date2 . ' ' . $time . ' GMT'; //RFC 822, updated by RFC 1123 - $rfc1123_date = $wkday . ',\ ' . $date1 . '\ ' . $time . '\ GMT'; + $rfc1123_date = $wkday . ', ' . $date1 . ' ' . $time . ' GMT'; //allowed date formats by RFC 2616 $HTTP_date = "($rfc1123_date|$rfc850_date|$asctime_date)"; @@ -49,7 +49,7 @@ static function parseHTTPDate($dateHeader) { return false; //append implicit GMT timezone to ANSI C time format - if (!preg_match('/\ GMT$/', $dateHeader)) + if (strpos($dateHeader, ' GMT') === false) $dateHeader .= ' GMT'; diff --git a/library/SabreDAV/lib/Sabre/HTTP/Version.php b/modules/webdav/library/SabreDAV/lib/Sabre/HTTP/Version.php similarity index 82% rename from library/SabreDAV/lib/Sabre/HTTP/Version.php rename to modules/webdav/library/SabreDAV/lib/Sabre/HTTP/Version.php index 5372a49c5..f8d1bb754 100644 --- a/library/SabreDAV/lib/Sabre/HTTP/Version.php +++ b/modules/webdav/library/SabreDAV/lib/Sabre/HTTP/Version.php @@ -5,7 +5,7 @@ * * @package Sabre * @subpackage HTTP - * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ @@ -14,7 +14,7 @@ class Sabre_HTTP_Version { /** * Full version number */ - const VERSION = '1.3.0'; + const VERSION = '1.4.1'; /** * Stability : alpha, beta, stable diff --git a/modules/webdav/library/SabreDAV/lib/Sabre/VObject/Component.php b/modules/webdav/library/SabreDAV/lib/Sabre/VObject/Component.php new file mode 100644 index 000000000..84b3558ea --- /dev/null +++ b/modules/webdav/library/SabreDAV/lib/Sabre/VObject/Component.php @@ -0,0 +1,210 @@ +name = strtoupper($name); + if (!is_null($iterator)) $this->iterator = $iterator; + + } + + /** + * Turns the object back into a serialized blob. + * + * @return string + */ + public function serialize() { + + $str = "BEGIN:" . $this->name . "\r\n"; + foreach($this->children as $child) $str.=$child->serialize(); + $str.= "END:" . $this->name . "\r\n"; + + return $str; + + } + + /** + * Adds a new componenten or element + * + * You can call this method with the following syntaxes: + * + * add(Sabre_VObject_Element $element) + * add(string $name, $value) + * + * The first version adds an Element + * The second adds a property as a string. + * + * @param mixed $item + * @param mixed $itemValue + * @return void + */ + public function add($item, $itemValue = null) { + + if ($item instanceof Sabre_VObject_Element) { + if (!is_null($itemValue)) { + throw new InvalidArgumentException('The second argument must not be specified, when passing a VObject'); + } + $this->children[] = $item; + } elseif(is_string($item)) { + + if (!is_scalar($itemValue)) { + throw new InvalidArgumentException('The second argument must be scalar'); + } + $this->children[] = new Sabre_VObject_Property($item,$itemValue); + + } else { + + throw new InvalidArgumentException('The first argument must either be a Sabre_VObject_Element or a string'); + + } + + } + + /** + * Returns an iterable list of children + * + * @return Sabre_VObject_ElementList + */ + public function children() { + + return new Sabre_VObject_ElementList($this->children); + + } + + /* Magic property accessors {{{ */ + + /** + * Using 'get' you will either get a propery or component, + * + * If there were no child-elements found with the specified name, + * null is returned. + * + * @param string $name + * @return void + */ + public function __get($name) { + + $name = strtoupper($name); + $matches = array(); + + foreach($this->children as $child) { + if ($child->name === $name) + $matches[] = $child; + } + + if (count($matches)===0) { + return null; + } else { + $firstMatch = $matches[0]; + $firstMatch->setIterator(new Sabre_VObject_ElementList($matches)); + return $firstMatch; + } + + } + + /** + * This method checks if a sub-element with the specified name exists. + * + * @param string $name + * @return bool + */ + public function __isset($name) { + + $name = strtoupper($name); + + foreach($this->children as $child) { + + if ($child->name === $name) + return true; + + } + return false; + + } + + /** + * Using the setter method you can add properties or subcomponents + * + * You can either pass a Sabre_VObject_Component, Sabre_VObject_Property + * object, or a string to automatically create a Property. + * + * If the item already exists, it will be removed. If you want to add + * a new item with the same name, always use the add() method. + * + * @param string $name + * @param mixed $value + * @return void + */ + public function __set($name, $value) { + + $name = strtoupper($name); + $arrayKey = null; + foreach($this->children as $key=>$child) { + + if ($child->name == $name) { + $arrayKey = $key; + break; + } + + } + + if ($value instanceof Sabre_VObject_Component || $value instanceof Sabre_VObject_Property) { + if (!is_null($arrayKey)) { + $this->children[$arrayKey] = $value; + } else { + $this->children[] = $value; + } + } elseif (is_scalar($value)) { + if (!is_null($arrayKey)) { + $this->children[$arrayKey] = new Sabre_VObject_Property($name,$value); + } else { + $this->children[] = new Sabre_VObject_Property($name,$value); + } + } else { + throw new InvalidArgumentException('You must pass a Sabre_VObject_Component, Sabre_VObject_Property or scalar type'); + } + + } + + /* }}} */ + + +} diff --git a/modules/webdav/library/SabreDAV/lib/Sabre/VObject/Element.php b/modules/webdav/library/SabreDAV/lib/Sabre/VObject/Element.php new file mode 100644 index 000000000..39448f6ce --- /dev/null +++ b/modules/webdav/library/SabreDAV/lib/Sabre/VObject/Element.php @@ -0,0 +1,135 @@ +iterator)) + return $this->iterator; + + return new Sabre_VObject_ElementList(array($this)); + + } + + /** + * Sets the overridden iterator + * + * Note that this is not actually part of the iterator interface + * + * @param Sabre_VObject_ElementList $iterator + * @return void + */ + public function setIterator(Sabre_VObject_ElementList $iterator) { + + $this->iterator = $iterator; + + } + + /* }}} */ + + /* {{{ Countable interface */ + + /** + * Returns the number of elements + * + * @return int + */ + public function count() { + + $it = $this->getIterator(); + return $it->count(); + + } + + /* }}} */ + + /* {{{ ArrayAccess Interface */ + + + /** + * Checks if an item exists through ArrayAccess. + * + * This method just forwards the request to the inner iterator + * + * @param int $offset + * @return bool + */ + public function offsetExists($offset) { + + $iterator = $this->getIterator(); + return $iterator->offsetExists($offset); + + } + + /** + * Gets an item through ArrayAccess. + * + * This method just forwards the request to the inner iterator + * + * @param int $offset + * @return mixed + */ + public function offsetGet($offset) { + + $iterator = $this->getIterator(); + return $iterator->offsetGet($offset); + + } + + /** + * Sets an item through ArrayAccess. + * + * This method just forwards the request to the inner iterator + * + * @param int $offset + * @param mixed $value + * @return void + */ + public function offsetSet($offset,$value) { + + $iterator = $this->getIterator(); + return $iterator->offsetSet($offset,$value); + + } + + /** + * Sets an item through ArrayAccess. + * + * This method just forwards the request to the inner iterator + * + * @param int $offset + * @return void + */ + public function offsetUnset($offset) { + + $iterator = $this->getIterator(); + return $iterator->offsetUnset($offset); + + } + + /* }}} */ + +} diff --git a/modules/webdav/library/SabreDAV/lib/Sabre/VObject/ElementList.php b/modules/webdav/library/SabreDAV/lib/Sabre/VObject/ElementList.php new file mode 100644 index 000000000..9922cd587 --- /dev/null +++ b/modules/webdav/library/SabreDAV/lib/Sabre/VObject/ElementList.php @@ -0,0 +1,172 @@ +vevent where there's multiple VEVENT objects. + * + * @package Sabre + * @subpackage VObject + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License + */ +class Sabre_VObject_ElementList implements Iterator, Countable, ArrayAccess { + + /** + * Inner elements + * + * @var array + */ + protected $elements = array(); + + /** + * Creates the element list. + * + * @param array $elements + */ + public function __construct(array $elements) { + + $this->elements = $elements; + + } + + /* {{{ Iterator interface */ + + /** + * Current position + * + * @var int + */ + private $key = 0; + + /** + * Returns current item in iteration + * + * @return Sabre_VObject_Element + */ + public function current() { + + return $this->elements[$this->key]; + + } + + /** + * To the next item in the iterator + * + * @return void + */ + public function next() { + + $this->key++; + + } + + /** + * Returns the current iterator key + * + * @return int + */ + public function key() { + + return $this->key; + + } + + /** + * Returns true if the current position in the iterator is a valid one + * + * @return bool + */ + public function valid() { + + return isset($this->elements[$this->key]); + + } + + /** + * Rewinds the iterator + * + * @return void + */ + public function rewind() { + + $this->key = 0; + + } + + /* }}} */ + + /* {{{ Countable interface */ + + /** + * Returns the number of elements + * + * @return int + */ + public function count() { + + return count($this->elements); + + } + + /* }}} */ + + /* {{{ ArrayAccess Interface */ + + + /** + * Checks if an item exists through ArrayAccess. + * + * @param int $offset + * @return bool + */ + public function offsetExists($offset) { + + return isset($this->elements[$offset]); + + } + + /** + * Gets an item through ArrayAccess. + * + * @param int $offset + * @return mixed + */ + public function offsetGet($offset) { + + return $this->elements[$offset]; + + } + + /** + * Sets an item through ArrayAccess. + * + * @param int $offset + * @param mixed $value + * @return void + */ + public function offsetSet($offset,$value) { + + throw new LogicException('You can not add new objects to an ElementList'); + + } + + /** + * Sets an item through ArrayAccess. + * + * This method just forwards the request to the inner iterator + * + * @param int $offset + * @return void + */ + public function offsetUnset($offset) { + + throw new LogicException('You can not remove objects from an ElementList'); + + } + + /* }}} */ + +} diff --git a/modules/webdav/library/SabreDAV/lib/Sabre/VObject/Node.php b/modules/webdav/library/SabreDAV/lib/Sabre/VObject/Node.php new file mode 100644 index 000000000..8fbfa1d3f --- /dev/null +++ b/modules/webdav/library/SabreDAV/lib/Sabre/VObject/Node.php @@ -0,0 +1,22 @@ +name = strtoupper($name); + $this->value = $value; + + } + + /** + * Turns the object back into a serialized blob. + * + * @return string + */ + public function serialize() { + + $src = array( + '\\', + "\n", + ';', + ',', + ); + $out = array( + '\\\\', + '\n', + '\;', + '\,', + ); + + return $this->name . '=' . str_replace($src, $out, $this->value); + + } + + /** + * Called when this object is being cast to a string + * + * @return string + */ + public function __toString() { + + return $this->value; + + } + +} diff --git a/modules/webdav/library/SabreDAV/lib/Sabre/VObject/ParseException.php b/modules/webdav/library/SabreDAV/lib/Sabre/VObject/ParseException.php new file mode 100644 index 000000000..ed4ef2e85 --- /dev/null +++ b/modules/webdav/library/SabreDAV/lib/Sabre/VObject/ParseException.php @@ -0,0 +1,12 @@ +name = strtoupper($name); + $this->value = $value; + if (!is_null($iterator)) $this->iterator = $iterator; + + } + + /** + * Turns the object back into a serialized blob. + * + * @return string + */ + public function serialize() { + + $str = $this->name; + if (count($this->parameters)) { + foreach($this->parameters as $param) { + + $str.=';' . $param->serialize(); + + } + } + $src = array( + '\\', + "\n", + ); + $out = array( + '\\\\', + '\n', + ); + $str.=':' . str_replace($src, $out, $this->value); + + $out = ''; + while(strlen($str)>0) { + if (strlen($str)>75) { + $out.= substr($str,0,75) . "\r\n"; + $str = ' ' . substr($str,75); + } else { + $out.=$str . "\r\n"; + $str=''; + break; + } + } + + return $out; + + } + + /* ArrayAccess interface {{{ */ + + /** + * Checks if an array element exists + * + * @param mixed $name + * @return bool + */ + public function offsetExists($name) { + + if (is_int($name)) return parent::offsetExists($name); + + $name = strtoupper($name); + + foreach($this->parameters as $parameter) { + if ($parameter->name == $name) return true; + } + return false; + + } + + /** + * Returns a parameter, or parameter list. + * + * @param string $name + * @return Sabre_VObject_Element + */ + public function offsetGet($name) { + + if (is_int($name)) return parent::offsetGet($name); + $name = strtoupper($name); + + $result = array(); + foreach($this->parameters as $parameter) { + if ($parameter->name == $name) + $result[] = $parameter; + } + + if (count($result)===0) { + return null; + } elseif (count($result)===1) { + return $result[0]; + } else { + return new Sabre_VObject_ElementList($result); + } + + } + + /** + * Creates a new parameter + * + * @param string $name + * @param mixed $value + * @return void + */ + public function offsetSet($name, $value) { + + if (is_int($name)) return parent::offsetSet($name, $value); + if (is_scalar($value)) { + if (!is_string($name)) + throw new InvalidArgumentException('A parameter name must be specified. This means you cannot use the $array[]="string" to add parameters.'); + + $this->parameters[] = new Sabre_VObject_Parameter($name, $value); + } elseif ($value instanceof Sabre_VObject_Parameter) { + if (!is_null($name)) + throw new InvalidArgumentException('Don\'t specify a parameter name if you\'re passing a Sabre_VObject_Parameter. Add using $array[]=$parameterObject.'); + + $this->parameters[] = $value; + } else { + throw new InvalidArgumentException('You can only add parameters to the property object'); + } + + } + + /** + * Removes one or more parameters with the specified name + * + * @param string $name + * @return void + */ + public function offsetUnset($name) { + + if (is_int($name)) return parent::offsetUnset($name, $value); + $name = strtoupper($name); + + $result = array(); + foreach($this->parameters as $key=>$parameter) { + if ($parameter->name == $name) { + unset($this->parameters[$key]); + } + + } + + } + + /* }}} */ + + /** + * Called when this object is being cast to a string + * + * @return string + */ + public function __toString() { + + return $this->value; + + } + + +} diff --git a/modules/webdav/library/SabreDAV/lib/Sabre/VObject/Reader.php b/modules/webdav/library/SabreDAV/lib/Sabre/VObject/Reader.php new file mode 100644 index 000000000..9c747ac3d --- /dev/null +++ b/modules/webdav/library/SabreDAV/lib/Sabre/VObject/Reader.php @@ -0,0 +1,162 @@ +children[] = self::readLine($lines); + $nextLine = current($lines); + + if ($nextLine===false) + throw new Sabre_VObject_ParseException('Invalid VObject. Document ended prematurely.'); + + } + + // Checking component name of the 'END:' line. + if (substr($nextLine,4)!==$obj->name) { + throw new Sabre_VObject_ParseException('Invalid VObject, expected: "END:' . $obj->name . '" got: "' . $nextLine . '"'); + } + next($lines); + + return $obj; + + } + + // Properties + //$result = preg_match('/(?P[A-Z0-9-]+)(?:;(?P^(?([^:^\"]|\"([^\"]*)\")*))?"; + $regex = "/^(?P$token)$parameters:(?P.*)$/i"; + + $result = preg_match($regex,$line,$matches); + + if (!$result) { + throw new Sabre_VObject_ParseException('Invalid VObject, line ' . ($lineNr+1) . ' did not follow icalendar format'); + } + + $obj = new Sabre_VObject_Property(strtoupper($matches['name']), stripcslashes($matches['value'])); + + if ($matches['parameters']) { + + $obj->parameters = self::readParameters($matches['parameters']); + } + + return $obj; + + + } + + /** + * Reads a parameter list from a property + * + * This method returns an array of Sabre_VObject_Parameter + * + * @param string $parameters + * @return array + */ + static private function readParameters($parameters) { + + $token = '[A-Z0-9-]+'; + + $paramValue = '(?P[^\"^;]*|"[^"]*")'; + + $regex = "/(?<=^|;)(?P$token)=$paramValue(?=$|;)/"; + preg_match_all($regex, $parameters, $matches, PREG_SET_ORDER); + + $params = array(); + foreach($matches as $match) { + + $value = $match['paramValue']; + + // Stripping quotes, if needed + if ($value[0] === '"') $value = substr($value,1,strlen($value)-2); + + $params[] = new Sabre_VObject_Parameter($match['paramName'], stripcslashes($value)); + + } + + return $params; + + + } + + +} diff --git a/modules/webdav/library/SabreDAV/lib/Sabre/VObject/Version.php b/modules/webdav/library/SabreDAV/lib/Sabre/VObject/Version.php new file mode 100644 index 000000000..757cdc427 --- /dev/null +++ b/modules/webdav/library/SabreDAV/lib/Sabre/VObject/Version.php @@ -0,0 +1,24 @@ + diff --git a/modules/webdav/models/AppModel.php b/modules/webdav/models/AppModel.php new file mode 100644 index 000000000..a4e6f1c24 --- /dev/null +++ b/modules/webdav/models/AppModel.php @@ -0,0 +1,8 @@ + diff --git a/modules/webdav/translation/fr-main.csv b/modules/webdav/translation/fr-main.csv new file mode 100644 index 000000000..9d3cbd3ae --- /dev/null +++ b/modules/webdav/translation/fr-main.csv @@ -0,0 +1 @@ +Hello world;Boujour tout le monde \ No newline at end of file diff --git a/modules/webdav/views/config/index.phtml b/modules/webdav/views/config/index.phtml new file mode 100644 index 000000000..6d1710e00 --- /dev/null +++ b/modules/webdav/views/config/index.phtml @@ -0,0 +1 @@ +Config page \ No newline at end of file diff --git a/modules/webdav/views/index/index.phtml b/modules/webdav/views/index/index.phtml new file mode 100644 index 000000000..c1f0bc1e9 --- /dev/null +++ b/modules/webdav/views/index/index.phtml @@ -0,0 +1 @@ +WebDav \ No newline at end of file