diff options
author | Georg Ehrke <dev@georgswebsite.de> | 2012-04-26 18:08:49 +0200 |
---|---|---|
committer | Georg Ehrke <dev@georgswebsite.de> | 2012-04-26 18:08:49 +0200 |
commit | 2b10371bdeb2c8a3d5cc2617ada5cf8195c264c9 (patch) | |
tree | f25b463c90992764887416c3082098fed6ecac65 | |
parent | 40f95ffdf3edf9ab45c15bd5b9018d7f4d92baa9 (diff) | |
parent | 127796218314c6b1f19ba86f74caa913375aac8d (diff) | |
download | nextcloud-server-2b10371bdeb2c8a3d5cc2617ada5cf8195c264c9.tar.gz nextcloud-server-2b10371bdeb2c8a3d5cc2617ada5cf8195c264c9.zip |
fix merge conflicts
241 files changed, 11916 insertions, 5403 deletions
diff --git a/3rdparty/Sabre.includes.php b/3rdparty/Sabre.includes.php index d41b287b77d..c1334373663 100644..100755 --- a/3rdparty/Sabre.includes.php +++ b/3rdparty/Sabre.includes.php @@ -3,125 +3,24 @@ /** * Library include file * + * This file is deprecated, don't use it! + * Instead, use the specific includes files that are in the sub-packages. + * + * Sabre/DAV/includes.php + * Sabre/HTTP/includes.php + * + * etc.. + * * This file contains all includes to the rest of the SabreDAV library - * Make sure the lib/ directory is in PHP's include_path + * Make sure the lib/ directory is in PHP's include_path. * * @package Sabre - * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @deprecated Don't use this file, it will be remove in a future version + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ -/* Utilities */ -include 'Sabre/HTTP/Util.php'; -include 'Sabre/HTTP/Response.php'; -include 'Sabre/HTTP/Request.php'; -include 'Sabre/HTTP/AbstractAuth.php'; -include 'Sabre/HTTP/BasicAuth.php'; -include 'Sabre/HTTP/DigestAuth.php'; -include 'Sabre/HTTP/AWSAuth.php'; - -/* Version */ -include 'Sabre/DAV/Version.php'; -include 'Sabre/HTTP/Version.php'; - -/* Exceptions */ -include 'Sabre/DAV/Exception.php'; -include 'Sabre/DAV/Exception/BadRequest.php'; -include 'Sabre/DAV/Exception/Conflict.php'; -include 'Sabre/DAV/Exception/FileNotFound.php'; -include 'Sabre/DAV/Exception/InsufficientStorage.php'; -include 'Sabre/DAV/Exception/Locked.php'; -include 'Sabre/DAV/Exception/LockTokenMatchesRequestUri.php'; -include 'Sabre/DAV/Exception/MethodNotAllowed.php'; -include 'Sabre/DAV/Exception/NotImplemented.php'; -include 'Sabre/DAV/Exception/Forbidden.php'; -include 'Sabre/DAV/Exception/PreconditionFailed.php'; -include 'Sabre/DAV/Exception/RequestedRangeNotSatisfiable.php'; -include 'Sabre/DAV/Exception/UnsupportedMediaType.php'; -include 'Sabre/DAV/Exception/NotAuthenticated.php'; - -include 'Sabre/DAV/Exception/ConflictingLock.php'; -include 'Sabre/DAV/Exception/ReportNotImplemented.php'; -include 'Sabre/DAV/Exception/InvalidResourceType.php'; - -/* Properties */ -include 'Sabre/DAV/Property.php'; -include 'Sabre/DAV/Property/GetLastModified.php'; -include 'Sabre/DAV/Property/ResourceType.php'; -include 'Sabre/DAV/Property/SupportedLock.php'; -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'; - -/* Node interfaces */ -include 'Sabre/DAV/INode.php'; -include 'Sabre/DAV/IFile.php'; -include 'Sabre/DAV/ICollection.php'; -include 'Sabre/DAV/IProperties.php'; -include 'Sabre/DAV/ILockable.php'; -include 'Sabre/DAV/IQuota.php'; -include 'Sabre/DAV/IExtendedCollection.php'; - -/* Node abstract implementations */ -include 'Sabre/DAV/Node.php'; -include 'Sabre/DAV/File.php'; -include 'Sabre/DAV/Collection.php'; -include 'Sabre/DAV/Directory.php'; - -/* Utilities */ -include 'Sabre/DAV/SimpleCollection.php'; -include 'Sabre/DAV/SimpleDirectory.php'; -include 'Sabre/DAV/XMLUtil.php'; -include 'Sabre/DAV/URLUtil.php'; - -/* Filesystem implementation */ -include 'Sabre/DAV/FS/Node.php'; -include 'Sabre/DAV/FS/File.php'; -include 'Sabre/DAV/FS/Directory.php'; - -/* Advanced filesystem implementation */ -include 'Sabre/DAV/FSExt/Node.php'; -include 'Sabre/DAV/FSExt/File.php'; -include 'Sabre/DAV/FSExt/Directory.php'; - -/* Trees */ -include 'Sabre/DAV/Tree.php'; -include 'Sabre/DAV/ObjectTree.php'; -include 'Sabre/DAV/Tree/Filesystem.php'; - -/* Server */ -include 'Sabre/DAV/Server.php'; -include 'Sabre/DAV/ServerPlugin.php'; - -/* Browser */ -include 'Sabre/DAV/Browser/Plugin.php'; -include 'Sabre/DAV/Browser/MapGetToPropFind.php'; -include 'Sabre/DAV/Browser/GuessContentType.php'; - -/* Locks */ -include 'Sabre/DAV/Locks/LockInfo.php'; -include 'Sabre/DAV/Locks/Plugin.php'; -include 'Sabre/DAV/Locks/Backend/Abstract.php'; -include 'Sabre/DAV/Locks/Backend/FS.php'; -include 'Sabre/DAV/Locks/Backend/PDO.php'; - -/* Temporary File Filter plugin */ -include 'Sabre/DAV/TemporaryFileFilterPlugin.php'; - -/* Authentication plugin */ -include 'Sabre/DAV/Auth/Plugin.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'; - -/* DavMount plugin */ -include 'Sabre/DAV/Mount/Plugin.php'; +include 'Sabre/HTTP/includes.php'; +include 'Sabre/DAV/includes.php'; diff --git a/3rdparty/Sabre/CalDAV/Backend/Abstract.php b/3rdparty/Sabre/CalDAV/Backend/Abstract.php index b694eef49e4..7aba1d69ffe 100644..100755 --- a/3rdparty/Sabre/CalDAV/Backend/Abstract.php +++ b/3rdparty/Sabre/CalDAV/Backend/Abstract.php @@ -2,10 +2,10 @@ /** * Abstract Calendaring backend. Extend this class to create your own backends. - * + * * @package Sabre * @subpackage CalDAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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,16 +17,16 @@ abstract class Sabre_CalDAV_Backend_Abstract { * Every project is an array with the following keys: * * id, a unique id that will be used by other functions to modify the * calendar. This can be the same as the uri or a database key. - * * uri, which the basename of the uri with which the calendar is + * * uri, which the basename of the uri with which the calendar is * accessed. - * * principalUri. The owner of the calendar. Almost always the same as + * * principaluri. The owner of the calendar. Almost always the same as * principalUri passed to this method. * * Furthermore it can contain webdav properties in clark notation. A very - * common one is '{DAV:}displayname'. + * common one is '{DAV:}displayname'. * - * @param string $principalUri - * @return array + * @param string $principalUri + * @return array */ abstract function getCalendarsForUser($principalUri); @@ -39,9 +39,9 @@ abstract class Sabre_CalDAV_Backend_Abstract { * @param string $principalUri * @param string $calendarUri * @param array $properties - * @return void + * @return void */ - abstract function createCalendar($principalUri,$calendarUri,array $properties); + abstract function createCalendar($principalUri,$calendarUri,array $properties); /** * Updates properties for a calendar. @@ -56,7 +56,7 @@ abstract class Sabre_CalDAV_Backend_Abstract { * If the operation was successful, true can be returned. * If the operation failed, false can be returned. * - * Deletion of a non-existant property is always succesful. + * Deletion of a non-existent property is always successful. * * Lastly, it is optional to return detailed information about any * failures. In this case an array should be returned with the following @@ -71,24 +71,24 @@ abstract class Sabre_CalDAV_Backend_Abstract { * ) * ) * - * In this example it was forbidden to update {DAV:}displayname. + * In this example it was forbidden to update {DAV:}displayname. * (403 Forbidden), which in turn also caused {DAV:}owner to fail * (424 Failed Dependency) because the request needs to be atomic. * * @param string $calendarId * @param array $mutations - * @return bool|array + * @return bool|array */ public function updateCalendar($calendarId, array $mutations) { - - return false; + + return false; } /** - * Delete a calendar and all it's objects - * - * @param string $calendarId + * Delete a calendar and all it's objects + * + * @param string $calendarId * @return void */ abstract function deleteCalendar($calendarId); @@ -98,22 +98,27 @@ abstract class Sabre_CalDAV_Backend_Abstract { * * Every item contains an array with the following keys: * * id - unique identifier which will be used for subsequent updates - * * calendardata - The iCalendar-compatible calnedar data + * * calendardata - The iCalendar-compatible calendar 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.: + * * etag - An arbitrary string, surrounded by double-quotes. (e.g.: * ' "abcdef"') * * calendarid - The calendarid as it was passed to this function. + * * size - The size of the calendar objects, in bytes. * - * Note that the etag is optional, but it's highly encouraged to return for + * 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 + * 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 + * + * If neither etag or size are specified, the calendardata will be + * used/fetched to determine these numbers. If both are specified the + * amount of times this is needed is reduced by a great degree. + * + * @param string $calendarId + * @return array */ abstract function getCalendarObjects($calendarId); @@ -121,41 +126,41 @@ abstract class Sabre_CalDAV_Backend_Abstract { * 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 + * 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 - * @return array + * + * @param string $calendarId + * @param string $objectUri + * @return array */ abstract function getCalendarObject($calendarId,$objectUri); /** - * Creates a new calendar object. - * - * @param string $calendarId - * @param string $objectUri - * @param string $calendarData + * Creates a new calendar object. + * + * @param string $calendarId + * @param string $objectUri + * @param string $calendarData * @return void */ abstract function createCalendarObject($calendarId,$objectUri,$calendarData); /** - * Updates an existing calendarobject, based on it's uri. - * - * @param string $calendarId - * @param string $objectUri - * @param string $calendarData + * Updates an existing calendarobject, based on it's uri. + * + * @param string $calendarId + * @param string $objectUri + * @param string $calendarData * @return void */ abstract function updateCalendarObject($calendarId,$objectUri,$calendarData); /** - * Deletes an existing calendar object. - * - * @param string $calendarId - * @param string $objectUri + * Deletes an existing calendar object. + * + * @param string $calendarId + * @param string $objectUri * @return void */ abstract function deleteCalendarObject($calendarId,$objectUri); diff --git a/3rdparty/Sabre/CalDAV/Backend/PDO.php b/3rdparty/Sabre/CalDAV/Backend/PDO.php index 7b1b33b912e..ddacf940c74 100644..100755 --- a/3rdparty/Sabre/CalDAV/Backend/PDO.php +++ b/3rdparty/Sabre/CalDAV/Backend/PDO.php @@ -3,35 +3,35 @@ /** * PDO CalDAV backend * - * This backend is used to store calendar-data in a PDO database, such as + * This backend is used to store calendar-data in a PDO database, such as * sqlite or MySQL - * + * * @package Sabre * @subpackage CalDAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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_Backend_PDO extends Sabre_CalDAV_Backend_Abstract { /** - * pdo - * + * pdo + * * @var PDO */ protected $pdo; /** - * The table name that will be used for calendars - * - * @var string + * The table name that will be used for calendars + * + * @var string */ protected $calendarTableName; /** - * The table name that will be used for calendar objects - * - * @var string + * The table name that will be used for calendar objects + * + * @var string */ protected $calendarObjectTableName; @@ -39,7 +39,7 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract { * List of CalDAV properties, and how they map to database fieldnames * * Add your own properties by simply adding on to this array - * + * * @var array */ public $propertyMap = array( @@ -51,9 +51,11 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract { ); /** - * Creates the backend - * - * @param PDO $pdo + * Creates the backend + * + * @param PDO $pdo + * @param string $calendarTableName + * @param string $calendarObjectTableName */ public function __construct(PDO $pdo, $calendarTableName = 'calendars', $calendarObjectTableName = 'calendarobjects') { @@ -69,16 +71,16 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract { * Every project is an array with the following keys: * * id, a unique id that will be used by other functions to modify the * calendar. This can be the same as the uri or a database key. - * * uri, which the basename of the uri with which the calendar is + * * uri, which the basename of the uri with which the calendar is * accessed. - * * principalUri. The owner of the calendar. Almost always the same as + * * principaluri. The owner of the calendar. Almost always the same as * principalUri passed to this method. * * Furthermore it can contain webdav properties in clark notation. A very - * common one is '{DAV:}displayname'. + * common one is '{DAV:}displayname'. * - * @param string $principalUri - * @return array + * @param string $principalUri + * @return array */ public function getCalendarsForUser($principalUri) { @@ -89,15 +91,18 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract { $fields[] = 'components'; $fields[] = 'principaluri'; - // Making fields a comma-delimited list + // Making fields a comma-delimited list $fields = implode(', ', $fields); - $stmt = $this->pdo->prepare("SELECT " . $fields . " FROM `".$this->calendarTableName."` WHERE principaluri = ?"); + $stmt = $this->pdo->prepare("SELECT " . $fields . " FROM ".$this->calendarTableName." WHERE principaluri = ? ORDER BY calendarorder ASC"); $stmt->execute(array($principalUri)); $calendars = array(); while($row = $stmt->fetch(PDO::FETCH_ASSOC)) { - $components = explode(',',$row['components']); + $components = array(); + if ($row['components']) { + $components = explode(',',$row['components']); + } $calendar = array( 'id' => $row['id'], @@ -106,7 +111,7 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract { '{' . Sabre_CalDAV_Plugin::NS_CALENDARSERVER . '}getctag' => $row['ctag']?$row['ctag']:'0', '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}supported-calendar-component-set' => new Sabre_CalDAV_Property_SupportedCalendarComponentSet($components), ); - + foreach($this->propertyMap as $xmlName=>$dbName) { $calendar[$xmlName] = $row[$dbName]; @@ -129,8 +134,9 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract { * @param string $principalUri * @param string $calendarUri * @param array $properties + * @return string */ - public function createCalendar($principalUri,$calendarUri, array $properties) { + public function createCalendar($principalUri, $calendarUri, array $properties) { $fieldNames = array( 'principaluri', @@ -158,13 +164,12 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract { foreach($this->propertyMap as $xmlName=>$dbName) { if (isset($properties[$xmlName])) { - $myValue = $properties[$xmlName]; $values[':' . $dbName] = $properties[$xmlName]; $fieldNames[] = $dbName; } } - $stmt = $this->pdo->prepare("INSERT INTO `".$this->calendarTableName."` (".implode(', ', $fieldNames).") VALUES (".implode(', ',array_keys($values)).")"); + $stmt = $this->pdo->prepare("INSERT INTO ".$this->calendarTableName." (".implode(', ', $fieldNames).") VALUES (".implode(', ',array_keys($values)).")"); $stmt->execute($values); return $this->pdo->lastInsertId(); @@ -184,7 +189,7 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract { * If the operation was successful, true can be returned. * If the operation failed, false can be returned. * - * Deletion of a non-existant property is always succesful. + * Deletion of a non-existent property is always successful. * * Lastly, it is optional to return detailed information about any * failures. In this case an array should be returned with the following @@ -199,13 +204,13 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract { * ) * ) * - * In this example it was forbidden to update {DAV:}displayname. + * In this example it was forbidden to update {DAV:}displayname. * (403 Forbidden), which in turn also caused {DAV:}owner to fail * (424 Failed Dependency) because the request needs to be atomic. * * @param string $calendarId - * @param array $mutations - * @return bool|array + * @param array $mutations + * @return bool|array */ public function updateCalendar($calendarId, array $mutations) { @@ -220,7 +225,7 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract { foreach($mutations as $propertyName=>$propertyValue) { - // We don't know about this property. + // We don't know about this property. if (!isset($this->propertyMap[$propertyName])) { $hasError = true; $result[403][$propertyName] = null; @@ -230,7 +235,7 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract { $fieldName = $this->propertyMap[$propertyName]; $newValues[$fieldName] = $propertyValue; - + } // If there were any errors we need to fail the request @@ -258,55 +263,60 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract { } $valuesSql[] = 'ctag = ctag + 1'; - $stmt = $this->pdo->prepare("UPDATE `" . $this->calendarTableName . "` SET " . implode(', ',$valuesSql) . " WHERE id = ?"); - $newValues['id'] = $calendarId; + $stmt = $this->pdo->prepare("UPDATE " . $this->calendarTableName . " SET " . implode(', ',$valuesSql) . " WHERE id = ?"); + $newValues['id'] = $calendarId; $stmt->execute(array_values($newValues)); - return true; + return true; } /** - * Delete a calendar and all it's objects - * - * @param string $calendarId + * Delete a calendar and all it's objects + * + * @param string $calendarId * @return void */ public function deleteCalendar($calendarId) { - $stmt = $this->pdo->prepare('DELETE FROM `'.$this->calendarObjectTableName.'` WHERE calendarid = ?'); + $stmt = $this->pdo->prepare('DELETE FROM '.$this->calendarObjectTableName.' WHERE calendarid = ?'); $stmt->execute(array($calendarId)); - $stmt = $this->pdo->prepare('DELETE FROM `'.$this->calendarTableName.'` WHERE id = ?'); + $stmt = $this->pdo->prepare('DELETE FROM '.$this->calendarTableName.' WHERE id = ?'); $stmt->execute(array($calendarId)); } /** - * Returns all calendar objects within a calendar. + * Returns all calendar objects within a calendar. * * Every item contains an array with the following keys: * * id - unique identifier which will be used for subsequent updates - * * calendardata - The iCalendar-compatible calnedar data + * * calendardata - The iCalendar-compatible calendar 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.: + * * etag - An arbitrary string, surrounded by double-quotes. (e.g.: * ' "abcdef"') * * calendarid - The calendarid as it was passed to this function. + * * size - The size of the calendar objects, in bytes. * - * Note that the etag is optional, but it's highly encouraged to return for + * 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 + * 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 + * + * If neither etag or size are specified, the calendardata will be + * used/fetched to determine these numbers. If both are specified the + * amount of times this is needed is reduced by a great degree. + * + * @param string $calendarId + * @return array */ public function getCalendarObjects($calendarId) { - $stmt = $this->pdo->prepare('SELECT * FROM `'.$this->calendarObjectTableName.'` WHERE calendarid = ?'); + $stmt = $this->pdo->prepare('SELECT * FROM '.$this->calendarObjectTableName.' WHERE calendarid = ?'); $stmt->execute(array($calendarId)); return $stmt->fetchAll(); @@ -316,68 +326,68 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract { * 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 + * 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 - * @return array + * + * @param string $calendarId + * @param string $objectUri + * @return array */ public function getCalendarObject($calendarId,$objectUri) { - $stmt = $this->pdo->prepare('SELECT * FROM `'.$this->calendarObjectTableName.'` WHERE calendarid = ? AND uri = ?'); + $stmt = $this->pdo->prepare('SELECT * FROM '.$this->calendarObjectTableName.' WHERE calendarid = ? AND uri = ?'); $stmt->execute(array($calendarId, $objectUri)); return $stmt->fetch(); } /** - * Creates a new calendar object. - * - * @param string $calendarId - * @param string $objectUri - * @param string $calendarData + * Creates a new calendar object. + * + * @param string $calendarId + * @param string $objectUri + * @param string $calendarData * @return void */ public function createCalendarObject($calendarId,$objectUri,$calendarData) { - $stmt = $this->pdo->prepare('INSERT INTO `'.$this->calendarObjectTableName.'` (calendarid, uri, calendardata, lastmodified) VALUES (?,?,?,?)'); + $stmt = $this->pdo->prepare('INSERT INTO '.$this->calendarObjectTableName.' (calendarid, uri, calendardata, lastmodified) VALUES (?,?,?,?)'); $stmt->execute(array($calendarId,$objectUri,$calendarData,time())); - $stmt = $this->pdo->prepare('UPDATE `'.$this->calendarTableName.'` SET ctag = ctag + 1 WHERE id = ?'); + $stmt = $this->pdo->prepare('UPDATE '.$this->calendarTableName.' SET ctag = ctag + 1 WHERE id = ?'); $stmt->execute(array($calendarId)); } /** - * Updates an existing calendarobject, based on it's uri. - * - * @param string $calendarId - * @param string $objectUri - * @param string $calendarData + * Updates an existing calendarobject, based on it's uri. + * + * @param string $calendarId + * @param string $objectUri + * @param string $calendarData * @return void */ public function updateCalendarObject($calendarId,$objectUri,$calendarData) { - $stmt = $this->pdo->prepare('UPDATE `'.$this->calendarObjectTableName.'` SET calendardata = ?, lastmodified = ? WHERE calendarid = ? AND uri = ?'); + $stmt = $this->pdo->prepare('UPDATE '.$this->calendarObjectTableName.' SET calendardata = ?, lastmodified = ? WHERE calendarid = ? AND uri = ?'); $stmt->execute(array($calendarData,time(),$calendarId,$objectUri)); - $stmt = $this->pdo->prepare('UPDATE `'.$this->calendarTableName.'` SET ctag = ctag + 1 WHERE id = ?'); + $stmt = $this->pdo->prepare('UPDATE '.$this->calendarTableName.' SET ctag = ctag + 1 WHERE id = ?'); $stmt->execute(array($calendarId)); } /** - * Deletes an existing calendar object. - * - * @param string $calendarId - * @param string $objectUri + * Deletes an existing calendar object. + * + * @param string $calendarId + * @param string $objectUri * @return void */ public function deleteCalendarObject($calendarId,$objectUri) { - $stmt = $this->pdo->prepare('DELETE FROM `'.$this->calendarObjectTableName.'` WHERE calendarid = ? AND uri = ?'); + $stmt = $this->pdo->prepare('DELETE FROM '.$this->calendarObjectTableName.' WHERE calendarid = ? AND uri = ?'); $stmt->execute(array($calendarId,$objectUri)); - $stmt = $this->pdo->prepare('UPDATE `'. $this->calendarTableName .'` SET ctag = ctag + 1 WHERE id = ?'); + $stmt = $this->pdo->prepare('UPDATE '. $this->calendarTableName .' SET ctag = ctag + 1 WHERE id = ?'); $stmt->execute(array($calendarId)); } diff --git a/3rdparty/Sabre/CalDAV/Calendar.php b/3rdparty/Sabre/CalDAV/Calendar.php index 0d2b3875771..623df2dd1b8 100644..100755 --- a/3rdparty/Sabre/CalDAV/Calendar.php +++ b/3rdparty/Sabre/CalDAV/Calendar.php @@ -5,42 +5,42 @@ * * A calendar can contain multiple TODO and or Events. These are represented * as Sabre_CalDAV_CalendarObject objects. - * + * * @package Sabre * @subpackage CalDAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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_CalDAV_ICalendar, Sabre_DAV_IProperties, Sabre_DAVACL_IACL { /** - * This is an array with calendar information - * - * @var array + * This is an array with calendar information + * + * @var array */ protected $calendarInfo; /** - * CalDAV backend - * - * @var Sabre_CalDAV_Backend_Abstract + * CalDAV backend + * + * @var Sabre_CalDAV_Backend_Abstract */ protected $caldavBackend; /** * Principal backend - * + * * @var Sabre_DAVACL_IPrincipalBackend */ protected $principalBackend; /** - * Constructor - * - * @param Sabre_CalDAV_Backend_Abstract $caldavBackend - * @param array $calendarInfo - * @return void + * Constructor + * + * @param Sabre_DAVACL_IPrincipalBackend $principalBackend + * @param Sabre_CalDAV_Backend_Abstract $caldavBackend + * @param array $calendarInfo */ public function __construct(Sabre_DAVACL_IPrincipalBackend $principalBackend, Sabre_CalDAV_Backend_Abstract $caldavBackend, $calendarInfo) { @@ -52,9 +52,9 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper } /** - * Returns the name of the calendar - * - * @return string + * Returns the name of the calendar + * + * @return string */ public function getName() { @@ -63,10 +63,10 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper } /** - * Updates properties such as the display name and description - * - * @param array $mutations - * @return array + * Updates properties such as the display name and description + * + * @param array $mutations + * @return array */ public function updateProperties($mutations) { @@ -75,10 +75,10 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper } /** - * Returns the list of properties - * - * @param array $properties - * @return array + * Returns the list of properties + * + * @param array $requestedProperties + * @return array */ public function getProperties($requestedProperties) { @@ -86,16 +86,16 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper foreach($requestedProperties as $prop) switch($prop) { - case '{urn:ietf:params:xml:ns:caldav}supported-calendar-data' : - $response[$prop] = new Sabre_CalDAV_Property_SupportedCalendarData(); + case '{urn:ietf:params:xml:ns:caldav}supported-calendar-data' : + $response[$prop] = new Sabre_CalDAV_Property_SupportedCalendarData(); break; - case '{urn:ietf:params:xml:ns:caldav}supported-collation-set' : - $response[$prop] = new Sabre_CalDAV_Property_SupportedCollationSet(); + case '{urn:ietf:params:xml:ns:caldav}supported-collation-set' : + $response[$prop] = new Sabre_CalDAV_Property_SupportedCollationSet(); break; case '{DAV:}owner' : $response[$prop] = new Sabre_DAVACL_Property_Principal(Sabre_DAVACL_Property_Principal::HREF,$this->calendarInfo['principaluri']); break; - default : + default : if (isset($this->calendarInfo[$prop])) $response[$prop] = $this->calendarInfo[$prop]; break; @@ -108,22 +108,22 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper * Returns a calendar object * * The contained calendar objects are for example Events or Todo's. - * - * @param string $name - * @return Sabre_DAV_ICalendarObject + * + * @param string $name + * @return Sabre_DAV_ICalendarObject */ public function getChild($name) { $obj = $this->caldavBackend->getCalendarObject($this->calendarInfo['id'],$name); - if (!$obj) throw new Sabre_DAV_Exception_FileNotFound('Calendar object not found'); + if (!$obj) throw new Sabre_DAV_Exception_NotFound('Calendar object not found'); return new Sabre_CalDAV_CalendarObject($this->caldavBackend,$this->calendarInfo,$obj); } /** - * Returns the full list of calendar objects - * - * @return array + * Returns the full list of calendar objects + * + * @return array */ public function getChildren() { @@ -137,17 +137,17 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper } /** - * Checks if a child-node exists. - * - * @param string $name - * @return bool + * Checks if a child-node exists. + * + * @param string $name + * @return bool */ public function childExists($name) { $obj = $this->caldavBackend->getCalendarObject($this->calendarInfo['id'],$name); - if (!$obj) + if (!$obj) return false; - else + else return true; } @@ -156,8 +156,8 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper * Creates a new directory * * We actually block this, as subdirectories are not allowed in calendars. - * - * @param string $name + * + * @param string $name * @return void */ public function createDirectory($name) { @@ -170,32 +170,23 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper * Creates a new file * * The contents of the new file must be a valid ICalendar string. - * - * @param string $name - * @param resource $calendarData - * @return void + * + * @param string $name + * @param resource $calendarData + * @return string|null */ public function createFile($name,$calendarData = null) { - $calendarData = stream_get_contents($calendarData); - // Converting to UTF-8, if needed - $calendarData = Sabre_DAV_StringUtil::ensureUTF8($calendarData); - - $supportedComponents = $this->calendarInfo['{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}supported-calendar-component-set']; - if ($supportedComponents) { - $supportedComponents = $supportedComponents->getValue(); - } else { - $supportedComponents = null; + if (is_resource($calendarData)) { + $calendarData = stream_get_contents($calendarData); } - Sabre_CalDAV_ICalendarUtil::validateICalendarObject($calendarData, $supportedComponents); - - $this->caldavBackend->createCalendarObject($this->calendarInfo['id'],$name,$calendarData); + return $this->caldavBackend->createCalendarObject($this->calendarInfo['id'],$name,$calendarData); } /** - * Deletes the calendar. - * + * Deletes the calendar. + * * @return void */ public function delete() { @@ -205,10 +196,10 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper } /** - * Renames the calendar. Note that most calendars use the - * {DAV:}displayname to display a name to display a name. - * - * @param string $newName + * Renames the calendar. Note that most calendars use the + * {DAV:}displayname to display a name to display a name. + * + * @param string $newName * @return void */ public function setName($newName) { @@ -219,7 +210,7 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper /** * Returns the last modification date as a unix timestamp. - * + * * @return void */ public function getLastModified() { @@ -231,8 +222,8 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper /** * Returns the owner principal * - * This must be a url to a principal, or null if there's no owner - * + * This must be a url to a principal, or null if there's no owner + * * @return string|null */ public function getOwner() { @@ -245,8 +236,8 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper * Returns a group principal * * This must be a url to a principal, or null if there's no owner - * - * @return string|null + * + * @return string|null */ public function getGroup() { @@ -258,13 +249,13 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper * 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 + * * '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 + * * 'protected' (optional), indicating that this ACE is not allowed to + * be updated. + * + * @return array */ public function getACL() { @@ -294,6 +285,11 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper 'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-read', 'protected' => true, ), + array( + 'privilege' => '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}read-free-busy', + 'principal' => '{DAV:}authenticated', + 'protected' => true, + ), ); @@ -302,9 +298,9 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper /** * Updates the ACL * - * This method will receive a list of new ACE's. - * - * @param array $acl + * This method will receive a list of new ACE's. + * + * @param array $acl * @return void */ public function setACL(array $acl) { @@ -313,6 +309,35 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper } + /** + * Returns the list of supported privileges for this node. + * + * The returned data structure is a list of nested privileges. + * See Sabre_DAVACL_Plugin::getDefaultSupportedPrivilegeSet for a simple + * standard structure. + * + * If null is returned from this method, the default privilege set is used, + * which is fine for most common usecases. + * + * @return array|null + */ + public function getSupportedPrivilegeSet() { + + $default = Sabre_DAVACL_Plugin::getDefaultSupportedPrivilegeSet(); + + // We need to inject 'read-free-busy' in the tree, aggregated under + // {DAV:}read. + foreach($default['aggregates'] as &$agg) { + if ($agg['privilege'] !== '{DAV:}read') continue; + + $agg['aggregates'][] = array( + 'privilege' => '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}read-free-busy', + ); + + } + return $default; + + } } diff --git a/3rdparty/Sabre/CalDAV/CalendarObject.php b/3rdparty/Sabre/CalDAV/CalendarObject.php index 0c99f18deb7..72f0a578d16 100644..100755 --- a/3rdparty/Sabre/CalDAV/CalendarObject.php +++ b/3rdparty/Sabre/CalDAV/CalendarObject.php @@ -1,43 +1,43 @@ <?php /** - * The CalendarObject represents a single VEVENT or VTODO within a Calendar. - * + * The CalendarObject represents a single VEVENT or VTODO within a Calendar. + * * @package Sabre * @subpackage CalDAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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_CalDAV_ICalendarObject, Sabre_DAVACL_IACL { /** - * Sabre_CalDAV_Backend_Abstract - * - * @var array + * Sabre_CalDAV_Backend_Abstract + * + * @var array */ protected $caldavBackend; /** - * Array with information about this CalendarObject - * - * @var array + * Array with information about this CalendarObject + * + * @var array */ protected $objectData; /** * Array with information about the containing calendar - * - * @var array + * + * @var array */ protected $calendarInfo; /** - * Constructor - * + * Constructor + * * @param Sabre_CalDAV_Backend_Abstract $caldavBackend * @param array $calendarInfo - * @param array $objectData + * @param array $objectData */ public function __construct(Sabre_CalDAV_Backend_Abstract $caldavBackend,array $calendarInfo,array $objectData) { @@ -56,9 +56,9 @@ class Sabre_CalDAV_CalendarObject extends Sabre_DAV_File implements Sabre_CalDAV } /** - * Returns the uri for this object - * - * @return string + * Returns the uri for this object + * + * @return string */ public function getName() { @@ -67,9 +67,9 @@ class Sabre_CalDAV_CalendarObject extends Sabre_DAV_File implements Sabre_CalDAV } /** - * Returns the ICalendar-formatted object - * - * @return string + * Returns the ICalendar-formatted object + * + * @return string */ public function get() { @@ -83,35 +83,27 @@ class Sabre_CalDAV_CalendarObject extends Sabre_DAV_File implements Sabre_CalDAV } /** - * Updates the ICalendar-formatted object - * - * @param string $calendarData - * @return void + * Updates the ICalendar-formatted object + * + * @param string $calendarData + * @return void */ public function put($calendarData) { - if (is_resource($calendarData)) + if (is_resource($calendarData)) { $calendarData = stream_get_contents($calendarData); - - // Converting to UTF-8, if needed - $calendarData = Sabre_DAV_StringUtil::ensureUTF8($calendarData); - - $supportedComponents = $this->calendarInfo['{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}supported-calendar-component-set']; - if ($supportedComponents) { - $supportedComponents = $supportedComponents->getValue(); - } else { - $supportedComponents = null; } - Sabre_CalDAV_ICalendarUtil::validateICalendarObject($calendarData, $supportedComponents); - - $this->caldavBackend->updateCalendarObject($this->calendarInfo['id'],$this->objectData['uri'],$calendarData); + $etag = $this->caldavBackend->updateCalendarObject($this->calendarInfo['id'],$this->objectData['uri'],$calendarData); $this->objectData['calendardata'] = $calendarData; + $this->objectData['etag'] = $etag; + + return $etag; } /** - * Deletes the calendar object - * + * Deletes the calendar object + * * @return void */ public function delete() { @@ -121,9 +113,9 @@ class Sabre_CalDAV_CalendarObject extends Sabre_DAV_File implements Sabre_CalDAV } /** - * Returns the mime content-type - * - * @return string + * Returns the mime content-type + * + * @return string */ public function getContentType() { @@ -134,9 +126,9 @@ class Sabre_CalDAV_CalendarObject extends Sabre_DAV_File implements Sabre_CalDAV /** * Returns an ETag for this object. * - * The ETag is an arbritrary string, but MUST be surrounded by double-quotes. - * - * @return string + * The ETag is an arbitrary string, but MUST be surrounded by double-quotes. + * + * @return string */ public function getETag() { @@ -150,8 +142,8 @@ class Sabre_CalDAV_CalendarObject extends Sabre_DAV_File implements Sabre_CalDAV /** * Returns the last modification date as a unix timestamp - * - * @return time + * + * @return time */ public function getLastModified() { @@ -160,21 +152,25 @@ class Sabre_CalDAV_CalendarObject extends Sabre_DAV_File implements Sabre_CalDAV } /** - * Returns the size of this object in bytes - * + * Returns the size of this object in bytes + * * @return int */ public function getSize() { - return strlen($this->objectData['calendardata']); + if (array_key_exists('size',$this->objectData)) { + return $this->objectData['size']; + } else { + return strlen($this->get()); + } } /** * Returns the owner principal * - * This must be a url to a principal, or null if there's no owner - * + * This must be a url to a principal, or null if there's no owner + * * @return string|null */ public function getOwner() { @@ -187,8 +183,8 @@ class Sabre_CalDAV_CalendarObject extends Sabre_DAV_File implements Sabre_CalDAV * Returns a group principal * * This must be a url to a principal, or null if there's no owner - * - * @return string|null + * + * @return string|null */ public function getGroup() { @@ -200,13 +196,13 @@ class Sabre_CalDAV_CalendarObject extends Sabre_DAV_File implements Sabre_CalDAV * 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 + * * '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 + * * 'protected' (optional), indicating that this ACE is not allowed to + * be updated. + * + * @return array */ public function getACL() { @@ -244,9 +240,9 @@ class Sabre_CalDAV_CalendarObject extends Sabre_DAV_File implements Sabre_CalDAV /** * Updates the ACL * - * This method will receive a list of new ACE's. - * - * @param array $acl + * This method will receive a list of new ACE's. + * + * @param array $acl * @return void */ public function setACL(array $acl) { @@ -255,6 +251,23 @@ class Sabre_CalDAV_CalendarObject extends Sabre_DAV_File implements Sabre_CalDAV } + /** + * Returns the list of supported privileges for this node. + * + * The returned data structure is a list of nested privileges. + * See Sabre_DAVACL_Plugin::getDefaultSupportedPrivilegeSet for a simple + * standard structure. + * + * If null is returned from this method, the default privilege set is used, + * which is fine for most common usecases. + * + * @return array|null + */ + public function getSupportedPrivilegeSet() { + + return null; + + } } diff --git a/3rdparty/Sabre/CalDAV/CalendarQueryParser.php b/3rdparty/Sabre/CalDAV/CalendarQueryParser.php new file mode 100755 index 00000000000..bd0d343382f --- /dev/null +++ b/3rdparty/Sabre/CalDAV/CalendarQueryParser.php @@ -0,0 +1,296 @@ +<?php + +/** + * Parses the calendar-query report request body. + * + * Whoever designed this format, and the CalDAV equivalent even more so, + * has no feel for design. + * + * @package Sabre + * @subpackage CalDAV + * @copyright Copyright (C) 2007-2012 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_CalendarQueryParser { + + /** + * List of requested properties the client wanted + * + * @var array + */ + public $requestedProperties; + + /** + * List of property/component filters. + * + * @var array + */ + public $filters; + + /** + * This property will contain null if CALDAV:expand was not specified, + * otherwise it will contain an array with 2 elements (start, end). Each + * contain a DateTime object. + * + * If expand is specified, recurring calendar objects are to be expanded + * into their individual components, and only the components that fall + * within the specified time-range are to be returned. + * + * For more details, see rfc4791, section 9.6.5. + * + * @var null|array + */ + public $expand; + + /** + * DOM Document + * + * @var DOMDocument + */ + protected $dom; + + /** + * DOM XPath object + * + * @var DOMXPath + */ + protected $xpath; + + /** + * Creates the parser + * + * @param DOMDocument $dom + */ + public function __construct(DOMDocument $dom) { + + $this->dom = $dom; + + $this->xpath = new DOMXPath($dom); + $this->xpath->registerNameSpace('cal',Sabre_CalDAV_Plugin::NS_CALDAV); + $this->xpath->registerNameSpace('dav','urn:DAV'); + + } + + /** + * Parses the request. + * + * @return void + */ + public function parse() { + + $filterNode = null; + + $filter = $this->xpath->query('/cal:calendar-query/cal:filter'); + if ($filter->length !== 1) { + throw new Sabre_DAV_Exception_BadRequest('Only one filter element is allowed'); + } + + $compFilters = $this->parseCompFilters($filter->item(0)); + if (count($compFilters)!==1) { + throw new Sabre_DAV_Exception_BadRequest('There must be exactly 1 top-level comp-filter.'); + } + + $this->filters = $compFilters[0]; + $this->requestedProperties = array_keys(Sabre_DAV_XMLUtil::parseProperties($this->dom->firstChild)); + + $expand = $this->xpath->query('/cal:calendar-query/dav:prop/cal:calendar-data/cal:expand'); + if ($expand->length>0) { + $this->expand = $this->parseExpand($expand->item(0)); + } + + + } + + /** + * Parses all the 'comp-filter' elements from a node + * + * @param DOMElement $parentNode + * @return array + */ + protected function parseCompFilters(DOMElement $parentNode) { + + $compFilterNodes = $this->xpath->query('cal:comp-filter', $parentNode); + $result = array(); + + for($ii=0; $ii < $compFilterNodes->length; $ii++) { + + $compFilterNode = $compFilterNodes->item($ii); + + $compFilter = array(); + $compFilter['name'] = $compFilterNode->getAttribute('name'); + $compFilter['is-not-defined'] = $this->xpath->query('cal:is-not-defined', $compFilterNode)->length>0; + $compFilter['comp-filters'] = $this->parseCompFilters($compFilterNode); + $compFilter['prop-filters'] = $this->parsePropFilters($compFilterNode); + $compFilter['time-range'] = $this->parseTimeRange($compFilterNode); + + if ($compFilter['time-range'] && !in_array($compFilter['name'],array( + 'VEVENT', + 'VTODO', + 'VJOURNAL', + 'VFREEBUSY', + 'VALARM', + ))) { + throw new Sabre_DAV_Exception_BadRequest('The time-range filter is not defined for the ' . $compFilter['name'] . ' component'); + }; + + $result[] = $compFilter; + + } + + return $result; + + } + + /** + * Parses all the prop-filter elements from a node + * + * @param DOMElement $parentNode + * @return array + */ + protected function parsePropFilters(DOMElement $parentNode) { + + $propFilterNodes = $this->xpath->query('cal:prop-filter', $parentNode); + $result = array(); + + for ($ii=0; $ii < $propFilterNodes->length; $ii++) { + + $propFilterNode = $propFilterNodes->item($ii); + $propFilter = array(); + $propFilter['name'] = $propFilterNode->getAttribute('name'); + $propFilter['is-not-defined'] = $this->xpath->query('cal:is-not-defined', $propFilterNode)->length>0; + $propFilter['param-filters'] = $this->parseParamFilters($propFilterNode); + $propFilter['text-match'] = $this->parseTextMatch($propFilterNode); + $propFilter['time-range'] = $this->parseTimeRange($propFilterNode); + + $result[] = $propFilter; + + } + + return $result; + + } + + /** + * Parses the param-filter element + * + * @param DOMElement $parentNode + * @return array + */ + protected function parseParamFilters(DOMElement $parentNode) { + + $paramFilterNodes = $this->xpath->query('cal:param-filter', $parentNode); + $result = array(); + + for($ii=0;$ii<$paramFilterNodes->length;$ii++) { + + $paramFilterNode = $paramFilterNodes->item($ii); + $paramFilter = array(); + $paramFilter['name'] = $paramFilterNode->getAttribute('name'); + $paramFilter['is-not-defined'] = $this->xpath->query('cal:is-not-defined', $paramFilterNode)->length>0; + $paramFilter['text-match'] = $this->parseTextMatch($paramFilterNode); + + $result[] = $paramFilter; + + } + + return $result; + + } + + /** + * Parses the text-match element + * + * @param DOMElement $parentNode + * @return array|null + */ + protected function parseTextMatch(DOMElement $parentNode) { + + $textMatchNodes = $this->xpath->query('cal:text-match', $parentNode); + + if ($textMatchNodes->length === 0) + return null; + + $textMatchNode = $textMatchNodes->item(0); + $negateCondition = $textMatchNode->getAttribute('negate-condition'); + $negateCondition = $negateCondition==='yes'; + $collation = $textMatchNode->getAttribute('collation'); + if (!$collation) $collation = 'i;ascii-casemap'; + + return array( + 'negate-condition' => $negateCondition, + 'collation' => $collation, + 'value' => $textMatchNode->nodeValue + ); + + } + + /** + * Parses the time-range element + * + * @param DOMElement $parentNode + * @return array|null + */ + protected function parseTimeRange(DOMElement $parentNode) { + + $timeRangeNodes = $this->xpath->query('cal:time-range', $parentNode); + if ($timeRangeNodes->length === 0) { + return null; + } + + $timeRangeNode = $timeRangeNodes->item(0); + + if ($start = $timeRangeNode->getAttribute('start')) { + $start = Sabre_VObject_DateTimeParser::parseDateTime($start); + } else { + $start = null; + } + if ($end = $timeRangeNode->getAttribute('end')) { + $end = Sabre_VObject_DateTimeParser::parseDateTime($end); + } else { + $end = null; + } + + if (!is_null($start) && !is_null($end) && $end <= $start) { + throw new Sabre_DAV_Exception_BadRequest('The end-date must be larger than the start-date in the time-range filter'); + } + + return array( + 'start' => $start, + 'end' => $end, + ); + + } + + /** + * Parses the CALDAV:expand element + * + * @param DOMElement $parentNode + * @return void + */ + protected function parseExpand(DOMElement $parentNode) { + + $start = $parentNode->getAttribute('start'); + if(!$start) { + throw new Sabre_DAV_Exception_BadRequest('The "start" attribute is required for the CALDAV:expand element'); + } + $start = Sabre_VObject_DateTimeParser::parseDateTime($start); + + $end = $parentNode->getAttribute('end'); + if(!$end) { + throw new Sabre_DAV_Exception_BadRequest('The "end" attribute is required for the CALDAV:expand element'); + } + $end = Sabre_VObject_DateTimeParser::parseDateTime($end); + + if ($end <= $start) { + throw new Sabre_DAV_Exception_BadRequest('The end-date must be larger than the start-date in the expand element.'); + } + + return array( + 'start' => $start, + 'end' => $end, + ); + + } + +} diff --git a/3rdparty/Sabre/CalDAV/CalendarQueryValidator.php b/3rdparty/Sabre/CalDAV/CalendarQueryValidator.php new file mode 100755 index 00000000000..1bb6b5d53fa --- /dev/null +++ b/3rdparty/Sabre/CalDAV/CalendarQueryValidator.php @@ -0,0 +1,347 @@ +<?php + +/** + * CalendarQuery Validator + * + * This class is responsible for checking if an iCalendar object matches a set + * of filters. The main function to do this is 'validate'. + * + * This is used to determine which icalendar objects should be returned for a + * calendar-query REPORT request. + * + * @package Sabre + * @subpackage CalDAV + * @copyright Copyright (C) 2007-2012 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_CalendarQueryValidator { + + /** + * Verify if a list of filters applies to the calendar data object + * + * The list of filters must be formatted as parsed by Sabre_CalDAV_CalendarQueryParser + * + * @param Sabre_VObject_Component $vObject + * @param array $filters + * @return bool + */ + public function validate(Sabre_VObject_Component $vObject,array $filters) { + + // The top level object is always a component filter. + // We'll parse it manually, as it's pretty simple. + if ($vObject->name !== $filters['name']) { + return false; + } + + return + $this->validateCompFilters($vObject, $filters['comp-filters']) && + $this->validatePropFilters($vObject, $filters['prop-filters']); + + + } + + /** + * This method checks the validity of comp-filters. + * + * A list of comp-filters needs to be specified. Also the parent of the + * component we're checking should be specified, not the component to check + * itself. + * + * @param Sabre_VObject_Component $parent + * @param array $filters + * @return bool + */ + protected function validateCompFilters(Sabre_VObject_Component $parent, array $filters) { + + foreach($filters as $filter) { + + $isDefined = isset($parent->$filter['name']); + + if ($filter['is-not-defined']) { + + if ($isDefined) { + return false; + } else { + continue; + } + + } + if (!$isDefined) { + return false; + } + + if ($filter['time-range']) { + foreach($parent->$filter['name'] as $subComponent) { + if ($this->validateTimeRange($subComponent, $filter['time-range']['start'], $filter['time-range']['end'])) { + continue 2; + } + } + return false; + } + + if (!$filter['comp-filters'] && !$filter['prop-filters']) { + continue; + } + + // If there are sub-filters, we need to find at least one component + // for which the subfilters hold true. + foreach($parent->$filter['name'] as $subComponent) { + + if ( + $this->validateCompFilters($subComponent, $filter['comp-filters']) && + $this->validatePropFilters($subComponent, $filter['prop-filters'])) { + // We had a match, so this comp-filter succeeds + continue 2; + } + + } + + // If we got here it means there were sub-comp-filters or + // sub-prop-filters and there was no match. This means this filter + // needs to return false. + return false; + + } + + // If we got here it means we got through all comp-filters alive so the + // filters were all true. + return true; + + } + + /** + * This method checks the validity of prop-filters. + * + * A list of prop-filters needs to be specified. Also the parent of the + * property we're checking should be specified, not the property to check + * itself. + * + * @param Sabre_VObject_Component $parent + * @param array $filters + * @return bool + */ + protected function validatePropFilters(Sabre_VObject_Component $parent, array $filters) { + + foreach($filters as $filter) { + + $isDefined = isset($parent->$filter['name']); + + if ($filter['is-not-defined']) { + + if ($isDefined) { + return false; + } else { + continue; + } + + } + if (!$isDefined) { + return false; + } + + if ($filter['time-range']) { + foreach($parent->$filter['name'] as $subComponent) { + if ($this->validateTimeRange($subComponent, $filter['time-range']['start'], $filter['time-range']['end'])) { + continue 2; + } + } + return false; + } + + if (!$filter['param-filters'] && !$filter['text-match']) { + continue; + } + + // If there are sub-filters, we need to find at least one property + // for which the subfilters hold true. + foreach($parent->$filter['name'] as $subComponent) { + + if( + $this->validateParamFilters($subComponent, $filter['param-filters']) && + (!$filter['text-match'] || $this->validateTextMatch($subComponent, $filter['text-match'])) + ) { + // We had a match, so this prop-filter succeeds + continue 2; + } + + } + + // If we got here it means there were sub-param-filters or + // text-match filters and there was no match. This means the + // filter needs to return false. + return false; + + } + + // If we got here it means we got through all prop-filters alive so the + // filters were all true. + return true; + + } + + /** + * This method checks the validity of param-filters. + * + * A list of param-filters needs to be specified. Also the parent of the + * parameter we're checking should be specified, not the parameter to check + * itself. + * + * @param Sabre_VObject_Property $parent + * @param array $filters + * @return bool + */ + protected function validateParamFilters(Sabre_VObject_Property $parent, array $filters) { + + foreach($filters as $filter) { + + $isDefined = isset($parent[$filter['name']]); + + if ($filter['is-not-defined']) { + + if ($isDefined) { + return false; + } else { + continue; + } + + } + if (!$isDefined) { + return false; + } + + if (!$filter['text-match']) { + continue; + } + + // If there are sub-filters, we need to find at least one parameter + // for which the subfilters hold true. + foreach($parent[$filter['name']] as $subParam) { + + if($this->validateTextMatch($subParam,$filter['text-match'])) { + // We had a match, so this param-filter succeeds + continue 2; + } + + } + + // If we got here it means there was a text-match filter and there + // were no matches. This means the filter needs to return false. + return false; + + } + + // If we got here it means we got through all param-filters alive so the + // filters were all true. + return true; + + } + + /** + * This method checks the validity of a text-match. + * + * A single text-match should be specified as well as the specific property + * or parameter we need to validate. + * + * @param Sabre_VObject_Node $parent + * @param array $textMatch + * @return bool + */ + protected function validateTextMatch(Sabre_VObject_Node $parent, array $textMatch) { + + $value = (string)$parent; + + $isMatching = Sabre_DAV_StringUtil::textMatch($value, $textMatch['value'], $textMatch['collation']); + + return ($textMatch['negate-condition'] xor $isMatching); + + } + + /** + * Validates if a component matches the given time range. + * + * This is all based on the rules specified in rfc4791, which are quite + * complex. + * + * @param Sabre_VObject_Node $component + * @param DateTime $start + * @param DateTime $end + * @return bool + */ + protected function validateTimeRange(Sabre_VObject_Node $component, $start, $end) { + + if (is_null($start)) { + $start = new DateTime('1900-01-01'); + } + if (is_null($end)) { + $end = new DateTime('3000-01-01'); + } + + switch($component->name) { + + case 'VEVENT' : + case 'VTODO' : + case 'VJOURNAL' : + + return $component->isInTimeRange($start, $end); + + case 'VALARM' : + + // If the valarm is wrapped in a recurring event, we need to + // expand the recursions, and validate each. + // + // Our datamodel doesn't easily allow us to do this straight + // in the VALARM component code, so this is a hack, and an + // expensive one too. + if ($component->parent->name === 'VEVENT' && $component->parent->RRULE) { + // Fire up the iterator! + $it = new Sabre_VObject_RecurrenceIterator($component->parent->parent, (string)$component->parent->UID); + while($it->valid()) { + $expandedEvent = $it->getEventObject(); + + // We need to check from these expanded alarms, which + // one is the first to trigger. Based on this, we can + // determine if we can 'give up' expanding events. + $firstAlarm = null; + foreach($expandedEvent->VALARM as $expandedAlarm) { + $effectiveTrigger = $expandedAlarm->getEffectiveTriggerTime(); + if (!$firstAlarm || $effectiveTrigger < $firstAlarm) { + $firstAlarm = $effectiveTrigger; + } + if ($expandedAlarm->isInTimeRange($start, $end)) { + return true; + } + + } + if ($firstAlarm > $end) { + return false; + } + $it->next(); + } + return false; + } else { + return $component->isInTimeRange($start, $end); + } + + case 'VFREEBUSY' : + throw new Sabre_DAV_Exception_NotImplemented('time-range filters are currently not supported on ' . $component->name . ' components'); + + case 'COMPLETED' : + case 'CREATED' : + case 'DTEND' : + case 'DTSTAMP' : + case 'DTSTART' : + case 'DUE' : + case 'LAST-MODIFIED' : + return ($start <= $component->getDateTime() && $end >= $component->getDateTime()); + + + + default : + throw new Sabre_DAV_Exception_BadRequest('You cannot create a time-range filter on a ' . $component->name . ' component'); + + } + + } + +} diff --git a/3rdparty/Sabre/CalDAV/CalendarRootNode.php b/3rdparty/Sabre/CalDAV/CalendarRootNode.php index 69669a9d7fd..3907913cc78 100644..100755 --- a/3rdparty/Sabre/CalDAV/CalendarRootNode.php +++ b/3rdparty/Sabre/CalDAV/CalendarRootNode.php @@ -1,38 +1,38 @@ <?php /** - * Users collection + * Users collection * * This object is responsible for generating a collection of users. * * @package Sabre * @subpackage CalDAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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_CalendarRootNode extends Sabre_DAVACL_AbstractPrincipalCollection { /** - * CalDAV backend - * - * @var Sabre_CalDAV_Backend_Abstract + * CalDAV backend + * + * @var Sabre_CalDAV_Backend_Abstract */ protected $caldavBackend; /** - * Constructor + * Constructor * * This constructor needs both an authentication and a caldav backend. * - * By default this class will show a list of calendar collections for - * principals in the 'principals' collection. If your main principals are - * actually located in a different path, use the $principalPrefix argument + * By default this class will show a list of calendar collections for + * principals in the 'principals' collection. If your main principals are + * actually located in a different path, use the $principalPrefix argument * to override this. * * - * @param Sabre_DAVACL_IPrincipalBackend $principalBackend - * @param Sabre_CalDAV_Backend_Abstract $caldavBackend + * @param Sabre_DAVACL_IPrincipalBackend $principalBackend + * @param Sabre_CalDAV_Backend_Abstract $caldavBackend * @param string $principalPrefix */ public function __construct(Sabre_DAVACL_IPrincipalBackend $principalBackend,Sabre_CalDAV_Backend_Abstract $caldavBackend, $principalPrefix = 'principals') { @@ -46,9 +46,9 @@ class Sabre_CalDAV_CalendarRootNode extends Sabre_DAVACL_AbstractPrincipalCollec * 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 + * and we want it to be Sabre_CalDAV_Plugin::CALENDAR_ROOT + * + * @return string */ public function getName() { @@ -62,9 +62,9 @@ class Sabre_CalDAV_CalendarRootNode extends Sabre_DAVACL_AbstractPrincipalCollec * 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 + * + * @param array $principal + * @return Sabre_DAV_INode */ public function getChildForPrincipal(array $principal) { diff --git a/3rdparty/Sabre/CalDAV/Exception/InvalidICalendarObject.php b/3rdparty/Sabre/CalDAV/Exception/InvalidICalendarObject.php deleted file mode 100644 index 656b7286a66..00000000000 --- a/3rdparty/Sabre/CalDAV/Exception/InvalidICalendarObject.php +++ /dev/null @@ -1,18 +0,0 @@ -<?php - -/** - * InvalidICalendarObject - * - * This exception is thrown when an attempt is made to create or update - * an invalid ICalendar object - * - * @package Sabre - * @subpackage CalDAV - * @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_Exception_InvalidICalendarObject extends Sabre_DAV_Exception_PreconditionFailed { - - -} diff --git a/3rdparty/Sabre/CalDAV/ICSExportPlugin.php b/3rdparty/Sabre/CalDAV/ICSExportPlugin.php index 4e2c6eb93d2..ec42b406b2f 100644..100755 --- a/3rdparty/Sabre/CalDAV/ICSExportPlugin.php +++ b/3rdparty/Sabre/CalDAV/ICSExportPlugin.php @@ -4,28 +4,28 @@ * ICS Exporter * * This plugin adds the ability to export entire calendars as .ics files. - * This is useful for clients that don't support CalDAV yet. They often do + * This is useful for clients that don't support CalDAV yet. They often do * support ics files. - * + * * @package Sabre * @subpackage CalDAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_ICSExportPlugin extends Sabre_DAV_ServerPlugin { /** - * Reference to Server class - * - * @var Sabre_DAV_Server + * Reference to Server class + * + * @var Sabre_DAV_Server */ private $server; /** - * Initializes the plugin and registers event handlers - * - * @param Sabre_DAV_Server $server + * Initializes the plugin and registers event handlers + * + * @param Sabre_DAV_Server $server * @return void */ public function initialize(Sabre_DAV_Server $server) { @@ -38,10 +38,10 @@ class Sabre_CalDAV_ICSExportPlugin extends Sabre_DAV_ServerPlugin { /** * 'beforeMethod' event handles. This event handles intercepts GET requests ending * with ?export - * + * * @param string $method * @param string $uri - * @return void + * @return bool */ public function beforeMethod($method, $uri) { @@ -55,9 +55,19 @@ class Sabre_CalDAV_ICSExportPlugin extends Sabre_DAV_ServerPlugin { if (!($node instanceof Sabre_CalDAV_Calendar)) return; + // Checking ACL, if available. + if ($aclPlugin = $this->server->getPlugin('acl')) { + $aclPlugin->checkPrivileges($uri, '{DAV:}read'); + } + $this->server->httpResponse->setHeader('Content-Type','text/calendar'); $this->server->httpResponse->sendStatus(200); - $this->server->httpResponse->sendBody($this->generateICS($this->server->tree->getChildren($uri))); + + $nodes = $this->server->getPropertiesForPath($uri, array( + '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}calendar-data', + ),1); + + $this->server->httpResponse->sendBody($this->generateICS($nodes)); // Returning false to break the event chain return false; @@ -65,16 +75,20 @@ class Sabre_CalDAV_ICSExportPlugin extends Sabre_DAV_ServerPlugin { } /** - * Merges all calendar objects, and builds one big ics export - * - * @param array $nodes - * @return void + * Merges all calendar objects, and builds one big ics export + * + * @param array $nodes + * @return string */ public function generateICS(array $nodes) { $calendar = new Sabre_VObject_Component('vcalendar'); $calendar->version = '2.0'; - $calendar->prodid = '-//SabreDAV//SabreDAV ' . Sabre_DAV_Version::VERSION . '//EN'; + if (Sabre_DAV_Server::$exposeVersion) { + $calendar->prodid = '-//SabreDAV//SabreDAV ' . Sabre_DAV_Version::VERSION . '//EN'; + } else { + $calendar->prodid = '-//SabreDAV//SabreDAV//EN'; + } $calendar->calscale = 'GREGORIAN'; $collectedTimezones = array(); @@ -84,7 +98,11 @@ class Sabre_CalDAV_ICSExportPlugin extends Sabre_DAV_ServerPlugin { foreach($nodes as $node) { - $nodeData = $node->get(); + if (!isset($node[200]['{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}calendar-data'])) { + continue; + } + $nodeData = $node[200]['{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}calendar-data']; + $nodeComp = Sabre_VObject_Reader::read($nodeData); foreach($nodeComp->children() as $child) { @@ -105,13 +123,10 @@ class Sabre_CalDAV_ICSExportPlugin extends Sabre_DAV_ServerPlugin { $collectedTimezones[] = $child->TZID; break; - } - } - } foreach($timezones as $tz) $calendar->add($tz); @@ -119,6 +134,6 @@ class Sabre_CalDAV_ICSExportPlugin extends Sabre_DAV_ServerPlugin { return $calendar->serialize(); - } + } } diff --git a/3rdparty/Sabre/CalDAV/ICalendar.php b/3rdparty/Sabre/CalDAV/ICalendar.php index 8193dff3a83..15d51ebcf79 100644..100755 --- a/3rdparty/Sabre/CalDAV/ICalendar.php +++ b/3rdparty/Sabre/CalDAV/ICalendar.php @@ -4,15 +4,15 @@ * Calendar interface * * Implement this interface to allow a node to be recognized as an calendar. - * + * * @package Sabre * @subpackage CalDAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ interface Sabre_CalDAV_ICalendar extends Sabre_DAV_ICollection { - + } diff --git a/3rdparty/Sabre/CalDAV/ICalendarObject.php b/3rdparty/Sabre/CalDAV/ICalendarObject.php index 708300ad7bd..280f982a310 100644..100755 --- a/3rdparty/Sabre/CalDAV/ICalendarObject.php +++ b/3rdparty/Sabre/CalDAV/ICalendarObject.php @@ -1,20 +1,20 @@ <?php /** - * CalendarObject interface + * CalendarObject interface /** - * Extend the ICalendarObject interface to allow your custom nodes to be picked up as + * Extend the ICalendarObject interface to allow your custom nodes to be picked up as * CalendarObjects. * * Calendar objects are resources such as Events, Todo's or Journals. - * + * * @package Sabre * @subpackage CalDAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ -interface Sabre_CalDAV_ICalendarObject extends Sabre_DAV_IFile { +interface Sabre_CalDAV_ICalendarObject extends Sabre_DAV_IFile { } diff --git a/3rdparty/Sabre/CalDAV/ICalendarUtil.php b/3rdparty/Sabre/CalDAV/ICalendarUtil.php deleted file mode 100644 index 699abfdd6f5..00000000000 --- a/3rdparty/Sabre/CalDAV/ICalendarUtil.php +++ /dev/null @@ -1,157 +0,0 @@ -<?php - -/** - * 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-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 { - - /** - * Validates an ICalendar object - * - * This method makes sure this ICalendar object is properly formatted. - * If we can't parse it, we'll throw exceptions. - * - * @param string $icalData - * @param array $allowedComponents - * @return bool - */ - static function validateICalendarObject($icalData, array $allowedComponents = null) { - - $xcal = simplexml_load_string(self::toXCal($icalData)); - if (!$xcal) throw new Sabre_CalDAV_Exception_InvalidICalendarObject('Invalid calendarobject format'); - - $xcal->registerXPathNameSpace('cal','urn:ietf:params:xml:ns:xcal'); - - // Check if there's only 1 component - $components = array('vevent','vtodo','vjournal','vfreebusy'); - $componentsFound = array(); - - foreach($components as $component) { - $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('One VEVENT, VTODO, VJOURNAL or VFREEBUSY must be specified. 0 found.'); - } - $component = $componentsFound[0]; - - if (is_null($allowedComponents)) return true; - - // Check if the component is allowed - $name = $component->getName(); - if (!in_array(strtoupper($name),$allowedComponents)) { - throw new Sabre_CalDAV_Exception_InvalidICalendarObject(strtoupper($name) . ' is not allowed in this calendar.'); - } - - if (count($xcal->xpath('/cal:iCalendar/cal:vcalendar/cal:method'))>0) { - throw new Sabre_CalDAV_Exception_InvalidICalendarObject('The METHOD property is not allowed in calendar objects'); - } - - return true; - - } - - /** - * Converts ICalendar data to XML. - * - * Properties are converted to lowercase xml elements. Parameters are; - * converted to attributes. BEGIN:VEVENT is converted to <vevent> and - * END:VEVENT </vevent> as well as other components. - * - * It's a very loose parser. If any line does not conform to the spec, it - * will simply be ignored. It will try to detect if \r\n or \n line endings - * are used. - * - * @todo Currently quoted attributes are not parsed correctly. - * @see http://tools.ietf.org/html/draft-royer-calsch-xcal-03 - * @param string $icalData - * @return string. - */ - static function toXCAL($icalData) { - - // Detecting line endings - $lb="\r\n"; - if (strpos($icalData,"\r\n")!==false) $lb = "\r\n"; - elseif (strpos($icalData,"\n")!==false) $lb = "\n"; - - // Splitting up items per line - $lines = explode($lb,$icalData); - - // Properties can be folded over 2 lines. In this case the second - // line will be preceeded by a space or tab. - $lines2 = array(); - foreach($lines as $line) { - - if (!$line) continue; - if ($line[0]===" " || $line[0]==="\t") { - $lines2[count($lines2)-1].=substr($line,1); - continue; - } - - $lines2[]=$line; - - } - - $xml = '<?xml version="1.0"?>' . "\n"; - $xml.= "<iCalendar xmlns=\"urn:ietf:params:xml:ns:xcal\">\n"; - - $spaces = 2; - foreach($lines2 as $line) { - - $matches = array(); - // This matches PROPERTYNAME;ATTRIBUTES:VALUE - if (!preg_match('/^([^:^;]*)(?:;([^:]*))?:(.*)$/',$line,$matches)) - continue; - - $propertyName = strtolower($matches[1]); - $attributes = $matches[2]; - $value = $matches[3]; - - // If the line was in the format BEGIN:COMPONENT or END:COMPONENT, we need to special case it. - if ($propertyName === 'begin') { - $xml.=str_repeat(" ",$spaces); - $xml.='<' . strtolower($value) . ">\n"; - $spaces+=2; - continue; - } elseif ($propertyName === 'end') { - $spaces-=2; - $xml.=str_repeat(" ",$spaces); - $xml.='</' . strtolower($value) . ">\n"; - continue; - } - - $xml.=str_repeat(" ",$spaces); - $xml.='<' . $propertyName; - if ($attributes) { - // There can be multiple attributes - $attributes = explode(';',$attributes); - foreach($attributes as $att) { - - list($attName,$attValue) = explode('=',$att,2); - $attName = strtolower($attName); - if ($attName === 'language') $attName='xml:lang'; - $xml.=' ' . $attName . '="' . htmlspecialchars($attValue) . '"'; - - } - } - - $xml.='>'. htmlspecialchars(trim($value)) . '</' . $propertyName . ">\n"; - - } - $xml.="</iCalendar>"; - return $xml; - - } - -} - diff --git a/3rdparty/Sabre/CalDAV/Plugin.php b/3rdparty/Sabre/CalDAV/Plugin.php index 02747c8395e..d7d1d970518 100644..100755 --- a/3rdparty/Sabre/CalDAV/Plugin.php +++ b/3rdparty/Sabre/CalDAV/Plugin.php @@ -8,8 +8,8 @@ * * @package Sabre * @subpackage CalDAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_Plugin extends Sabre_DAV_ServerPlugin { @@ -18,7 +18,7 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { * This is the official CalDAV namespace */ const NS_CALDAV = 'urn:ietf:params:xml:ns:caldav'; - + /** * This is the namespace for the proprietary calendarserver extensions */ @@ -41,21 +41,48 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { const CALENDAR_ROOT = 'calendars'; /** - * Reference to server object - * - * @var Sabre_DAV_Server + * Reference to server object + * + * @var Sabre_DAV_Server */ private $server; /** + * The email handler for invites and other scheduling messages. + * + * @var Sabre_CalDAV_Schedule_IMip + */ + protected $imipHandler; + + /** + * Sets the iMIP handler. + * + * iMIP = The email transport of iCalendar scheduling messages. Setting + * this is optional, but if you want the server to allow invites to be sent + * out, you must set a handler. + * + * Specifically iCal will plain assume that the server supports this. If + * the server doesn't, iCal will display errors when inviting people to + * events. + * + * @param Sabre_CalDAV_Schedule_IMip $imipHandler + * @return void + */ + public function setIMipHandler(Sabre_CalDAV_Schedule_IMip $imipHandler) { + + $this->imipHandler = $imipHandler; + + } + + /** * Use this method to tell the server this plugin defines additional * HTTP methods. * - * This method is passed a uri. It should only return HTTP methods that are + * This method is passed a uri. It should only return HTTP methods that are * available for the specified uri. * * @param string $uri - * @return array + * @return array */ public function getHTTPMethods($uri) { @@ -68,7 +95,7 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { if ($node instanceof Sabre_DAV_IExtendedCollection) { try { $node->getChild($name); - } catch (Sabre_DAV_Exception_FileNotFound $e) { + } catch (Sabre_DAV_Exception_NotFound $e) { return array('MKCALENDAR'); } } @@ -77,9 +104,9 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { } /** - * Returns a list of features for the DAV: HTTP header. - * - * @return array + * Returns a list of features for the DAV: HTTP header. + * + * @return array */ public function getFeatures() { @@ -89,11 +116,11 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { /** * Returns a plugin name. - * + * * Using this name other plugins will be able to access other plugins - * using Sabre_DAV_Server::getPlugin - * - * @return string + * using Sabre_DAV_Server::getPlugin + * + * @return string */ public function getPluginName() { @@ -105,38 +132,46 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { * 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 - * + * Note that you still need to subscribe to the 'report' event to actually + * implement them + * * @param string $uri - * @return array + * @return array */ public function getSupportedReportSet($uri) { $node = $this->server->tree->getNodeForPath($uri); + + $reports = array(); if ($node instanceof Sabre_CalDAV_ICalendar || $node instanceof Sabre_CalDAV_ICalendarObject) { - return array( - '{' . self::NS_CALDAV . '}calendar-multiget', - '{' . self::NS_CALDAV . '}calendar-query', - ); + $reports[] = '{' . self::NS_CALDAV . '}calendar-multiget'; + $reports[] = '{' . self::NS_CALDAV . '}calendar-query'; } - return array(); + if ($node instanceof Sabre_CalDAV_ICalendar) { + $reports[] = '{' . self::NS_CALDAV . '}free-busy-query'; + } + return $reports; } /** - * Initializes the plugin - * - * @param Sabre_DAV_Server $server + * Initializes the plugin + * + * @param Sabre_DAV_Server $server * @return void */ public function initialize(Sabre_DAV_Server $server) { $this->server = $server; + $server->subscribeEvent('unknownMethod',array($this,'unknownMethod')); //$server->subscribeEvent('unknownMethod',array($this,'unknownMethod2'),1000); $server->subscribeEvent('report',array($this,'report')); $server->subscribeEvent('beforeGetProperties',array($this,'beforeGetProperties')); + $server->subscribeEvent('onHTMLActionsPanel', array($this,'htmlActionsPanel')); + $server->subscribeEvent('onBrowserPostAction', array($this,'browserPostAction')); + $server->subscribeEvent('beforeWriteContent', array($this, 'beforeWriteContent')); + $server->subscribeEvent('beforeCreateFile', array($this, 'beforeCreateFile')); $server->xmlNamespaces[self::NS_CALDAV] = 'cal'; $server->xmlNamespaces[self::NS_CALENDARSERVER] = 'cs'; @@ -144,6 +179,7 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { $server->propertyMap['{' . self::NS_CALDAV . '}supported-calendar-component-set'] = 'Sabre_CalDAV_Property_SupportedCalendarComponentSet'; $server->resourceTypeMapping['Sabre_CalDAV_ICalendar'] = '{urn:ietf:params:xml:ns:caldav}calendar'; + $server->resourceTypeMapping['Sabre_CalDAV_Schedule_IOutbox'] = '{urn:ietf:params:xml:ns:caldav}schedule-outbox'; $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'; @@ -161,7 +197,10 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { '{' . self::NS_CALDAV . '}calendar-data', // scheduling extension + '{' . self::NS_CALDAV . '}schedule-inbox-URL', + '{' . self::NS_CALDAV . '}schedule-outbox-URL', '{' . self::NS_CALDAV . '}calendar-user-address-set', + '{' . self::NS_CALDAV . '}calendar-user-type', // CalendarServer extensions '{' . self::NS_CALENDARSERVER . '}getctag', @@ -173,36 +212,55 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { /** * This function handles support for the MKCALENDAR method - * - * @param string $method - * @return bool + * + * @param string $method + * @param string $uri + * @return bool */ public function unknownMethod($method, $uri) { - if ($method!=='MKCALENDAR') return; + switch ($method) { + case 'MKCALENDAR' : + $this->httpMkCalendar($uri); + // false is returned to stop the propagation of the + // unknownMethod event. + return false; + case 'POST' : + // Checking if we're talking to an outbox + try { + $node = $this->server->tree->getNodeForPath($uri); + } catch (Sabre_DAV_Exception_NotFound $e) { + return; + } + if (!$node instanceof Sabre_CalDAV_Schedule_IOutbox) + return; - $this->httpMkCalendar($uri); - // false is returned to stop the unknownMethod event - return false; + $this->outboxRequest($node); + return false; + + } } /** - * This functions handles REPORT requests specific to CalDAV - * - * @param string $reportName - * @param DOMNode $dom - * @return bool + * This functions handles REPORT requests specific to CalDAV + * + * @param string $reportName + * @param DOMNode $dom + * @return bool */ public function report($reportName,$dom) { - switch($reportName) { + switch($reportName) { case '{'.self::NS_CALDAV.'}calendar-multiget' : $this->calendarMultiGetReport($dom); return false; case '{'.self::NS_CALDAV.'}calendar-query' : $this->calendarQueryReport($dom); return false; + case '{'.self::NS_CALDAV.'}free-busy-query' : + $this->freeBusyQueryReport($dom); + return false; } @@ -212,9 +270,9 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { /** * This function handles the MKCALENDAR HTTP method, which creates * a new calendar. - * + * * @param string $uri - * @return void + * @return void */ public function httpMkCalendar($uri) { @@ -238,7 +296,7 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { foreach(Sabre_DAV_XMLUtil::parseProperties($child,$this->server->propertyMap) as $k=>$prop) { $properties[$k] = $prop; } - + } } @@ -254,9 +312,9 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { * beforeGetProperties * * This method handler is invoked before any after properties for a - * resource are fetched. This allows us to add in any CalDAV specific - * properties. - * + * resource are fetched. This allows us to add in any CalDAV specific + * properties. + * * @param string $path * @param Sabre_DAV_INode $node * @param array $requestedProperties @@ -270,12 +328,21 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { // calendar-home-set property $calHome = '{' . self::NS_CALDAV . '}calendar-home-set'; if (in_array($calHome,$requestedProperties)) { - $principalId = $node->getName(); + $principalId = $node->getName(); $calendarHomePath = self::CALENDAR_ROOT . '/' . $principalId . '/'; unset($requestedProperties[$calHome]); $returnedProperties[200][$calHome] = new Sabre_DAV_Property_Href($calendarHomePath); } + // schedule-outbox-URL property + $scheduleProp = '{' . self::NS_CALDAV . '}schedule-outbox-URL'; + if (in_array($scheduleProp,$requestedProperties)) { + $principalId = $node->getName(); + $outboxPath = self::CALENDAR_ROOT . '/' . $principalId . '/outbox'; + unset($requestedProperties[$scheduleProp]); + $returnedProperties[200][$scheduleProp] = new Sabre_DAV_Property_Href($outboxPath); + } + // calendar-user-address-set property $calProp = '{' . self::NS_CALDAV . '}calendar-user-address-set'; if (in_array($calProp,$requestedProperties)) { @@ -287,7 +354,7 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { } - // These two properties are shortcuts for ical to easily find + // 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'; @@ -301,8 +368,8 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { $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 + // 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); @@ -327,8 +394,8 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { if ($node instanceof Sabre_CalDAV_ICalendarObject) { - // The calendar-data property is not supposed to be a 'real' - // property, but in large chunks of the spec it does act as such. + // The calendar-data property is not supposed to be a 'real' + // property, but in large chunks of the spec it does act as such. // Therefore we simply expose it as a property. $calDataProp = '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}calendar-data'; if (in_array($calDataProp, $requestedProperties)) { @@ -350,18 +417,52 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { * * This report is used by the client to fetch the content of a series * of urls. Effectively avoiding a lot of redundant requests. - * - * @param DOMNode $dom + * + * @param DOMNode $dom * @return void */ public function calendarMultiGetReport($dom) { $properties = array_keys(Sabre_DAV_XMLUtil::parseProperties($dom->firstChild)); - $hrefElems = $dom->getElementsByTagNameNS('urn:DAV','href'); + + $xpath = new DOMXPath($dom); + $xpath->registerNameSpace('cal',Sabre_CalDAV_Plugin::NS_CALDAV); + $xpath->registerNameSpace('dav','urn:DAV'); + + $expand = $xpath->query('/cal:calendar-multiget/dav:prop/cal:calendar-data/cal:expand'); + if ($expand->length>0) { + $expandElem = $expand->item(0); + $start = $expandElem->getAttribute('start'); + $end = $expandElem->getAttribute('end'); + if(!$start || !$end) { + throw new Sabre_DAV_Exception_BadRequest('The "start" and "end" attributes are required for the CALDAV:expand element'); + } + $start = Sabre_VObject_DateTimeParser::parseDateTime($start); + $end = Sabre_VObject_DateTimeParser::parseDateTime($end); + + if ($end <= $start) { + throw new Sabre_DAV_Exception_BadRequest('The end-date must be larger than the start-date in the expand element.'); + } + + $expand = true; + + } else { + + $expand = false; + + } + foreach($hrefElems as $elem) { $uri = $this->server->calculateUri($elem->nodeValue); list($objProps) = $this->server->getPropertiesForPath($uri,$properties); + + if ($expand && isset($objProps[200]['{' . self::NS_CALDAV . '}calendar-data'])) { + $vObject = Sabre_VObject_Reader::read($objProps[200]['{' . self::NS_CALDAV . '}calendar-data']); + $vObject->expand($start, $end); + $objProps[200]['{' . self::NS_CALDAV . '}calendar-data'] = $vObject->serialize(); + } + $propertyList[]=$objProps; } @@ -377,48 +478,57 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { * * This report is used by clients to request calendar objects based on * complex conditions. - * - * @param DOMNode $dom + * + * @param DOMNode $dom * @return void */ public function calendarQueryReport($dom) { - $requestedProperties = array_keys(Sabre_DAV_XMLUtil::parseProperties($dom->firstChild)); - - $filterNode = $dom->getElementsByTagNameNS('urn:ietf:params:xml:ns:caldav','filter'); - if ($filterNode->length!==1) { - throw new Sabre_DAV_Exception_BadRequest('The calendar-query report must have a filter element'); - } - $filters = Sabre_CalDAV_XMLUtil::parseCalendarQueryFilters($filterNode->item(0)); + $parser = new Sabre_CalDAV_CalendarQueryParser($dom); + $parser->parse(); $requestedCalendarData = true; + $requestedProperties = $parser->requestedProperties; if (!in_array('{urn:ietf:params:xml:ns:caldav}calendar-data', $requestedProperties)) { + // We always retrieve calendar-data, as we need it for filtering. $requestedProperties[] = '{urn:ietf:params:xml:ns:caldav}calendar-data'; - // If calendar-data wasn't explicitly requested, we need to remove + // If calendar-data wasn't explicitly requested, we need to remove // it after processing. $requestedCalendarData = false; } // These are the list of nodes that potentially match the requirement - $candidateNodes = $this->server->getPropertiesForPath($this->server->getRequestUri(),$requestedProperties,$this->server->getHTTPDepth(0)); + $candidateNodes = $this->server->getPropertiesForPath( + $this->server->getRequestUri(), + $requestedProperties, + $this->server->getHTTPDepth(0) + ); $verifiedNodes = array(); + $validator = new Sabre_CalDAV_CalendarQueryValidator(); + foreach($candidateNodes as $node) { // If the node didn't have a calendar-data property, it must not be a calendar object - if (!isset($node[200]['{urn:ietf:params:xml:ns:caldav}calendar-data'])) continue; + if (!isset($node[200]['{urn:ietf:params:xml:ns:caldav}calendar-data'])) + continue; + + $vObject = Sabre_VObject_Reader::read($node[200]['{urn:ietf:params:xml:ns:caldav}calendar-data']); + if ($validator->validate($vObject,$parser->filters)) { - if ($this->validateFilters($node[200]['{urn:ietf:params:xml:ns:caldav}calendar-data'],$filters)) { - if (!$requestedCalendarData) { unset($node[200]['{urn:ietf:params:xml:ns:caldav}calendar-data']); } + if ($parser->expand) { + $vObject->expand($parser->expand['start'], $parser->expand['end']); + $node[200]['{' . self::NS_CALDAV . '}calendar-data'] = $vObject->serialize(); + } $verifiedNodes[] = $node; - } + } } @@ -428,360 +538,291 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { } - /** - * Verify if a list of filters applies to the calendar data object + * This method is responsible for parsing the request and generating the + * response for the CALDAV:free-busy-query REPORT. * - * The calendarData object must be a valid iCalendar blob. The list of - * filters must be formatted as parsed by Sabre_CalDAV_Plugin::parseCalendarQueryFilters - * - * @param string $calendarData - * @param array $filters - * @return bool + * @param DOMNode $dom + * @return void */ - public function validateFilters($calendarData,$filters) { - - // We are converting the calendar object to an XML structure - // This makes it far easier to parse - $xCalendarData = Sabre_CalDAV_ICalendarUtil::toXCal($calendarData); - $xml = simplexml_load_string($xCalendarData); - $xml->registerXPathNamespace('c','urn:ietf:params:xml:ns:xcal'); - - foreach($filters as $xpath=>$filter) { - - // if-not-defined comes first - if (isset($filter['is-not-defined'])) { - if (!$xml->xpath($xpath)) - continue; - else - return false; - - } - - $elem = $xml->xpath($xpath); - - if (!$elem) return false; - $elem = $elem[0]; - - if (isset($filter['time-range'])) { - - switch($elem->getName()) { - case 'vevent' : - $result = $this->validateTimeRangeFilterForEvent($xml,$xpath,$filter); - if ($result===false) return false; - break; - case 'vtodo' : - $result = $this->validateTimeRangeFilterForTodo($xml,$xpath,$filter); - 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' : - $result = $this->validateTimeRangeFilterForFreeBusy($xml,$xpath,$filter); - if ($result===false) return false; - break; - case 'valarm' : - $result = $this->validateTimeRangeFilterForAlarm($xml,$xpath,$filter); - if ($result===false) return false; - break; - - */ - - } + protected function freeBusyQueryReport(DOMNode $dom) { - } + $start = null; + $end = null; - if (isset($filter['text-match'])) { - $currentString = (string)$elem; + foreach($dom->firstChild->childNodes as $childNode) { - $isMatching = Sabre_DAV_StringUtil::textMatch($currentString, $filter['text-match']['value'], $filter['text-match']['collation']); - if ($filter['text-match']['negate-condition'] && $isMatching) return false; - if (!$filter['text-match']['negate-condition'] && !$isMatching) return false; - + $clark = Sabre_DAV_XMLUtil::toClarkNotation($childNode); + if ($clark == '{' . self::NS_CALDAV . '}time-range') { + $start = $childNode->getAttribute('start'); + $end = $childNode->getAttribute('end'); + break; } } - return true; - - } - - /** - * 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 - $xdtstart = $xml->xpath($currentXPath.'/c:dtstart'); - if (!count($xdtstart)) { - throw new Sabre_DAV_Exception_BadRequest('DTSTART property missing from calendar object'); + if ($start) { + $start = Sabre_VObject_DateTimeParser::parseDateTime($start); + } + if ($end) { + $end = Sabre_VObject_DateTimeParser::parseDateTime($end); } - // The dtstart can be both a date, or datetime property - if ((string)$xdtstart[0]['value']==='DATE' || strlen((string)$xdtstart[0])===8) { - $isDateTime = false; - } else { - $isDateTime = true; + if (!$start && !$end) { + throw new Sabre_DAV_Exception_BadRequest('The freebusy report must have a time-range filter'); } + $acl = $this->server->getPlugin('acl'); - // Determining the timezone - if ($tzid = (string)$xdtstart[0]['tzid']) { - $tz = new DateTimeZone($tzid); - } else { - $tz = null; + if (!$acl) { + throw new Sabre_DAV_Exception('The ACL plugin must be loaded for free-busy queries to work'); } - if ($isDateTime) { - $dtstart = Sabre_CalDAV_XMLUtil::parseICalendarDateTime((string)$xdtstart[0],$tz); - } else { - $dtstart = Sabre_CalDAV_XMLUtil::parseICalendarDate((string)$xdtstart[0]); + $uri = $this->server->getRequestUri(); + $acl->checkPrivileges($uri,'{' . self::NS_CALDAV . '}read-free-busy'); + + $calendar = $this->server->tree->getNodeForPath($uri); + if (!$calendar instanceof Sabre_CalDAV_ICalendar) { + throw new Sabre_DAV_Exception_NotImplemented('The free-busy-query REPORT is only implemented on calendars'); } + $objects = array_map(function($child) { + $obj = $child->get(); + if (is_resource($obj)) { + $obj = stream_get_contents($obj); + } + return $obj; + }, $calendar->getChildren()); - // Grabbing the DTEND property - $xdtend = $xml->xpath($currentXPath.'/c:dtend'); - $dtend = null; + $generator = new Sabre_VObject_FreeBusyGenerator(); + $generator->setObjects($objects); + $generator->setTimeRange($start, $end); + $result = $generator->getResult(); + $result = $result->serialize(); - if (count($xdtend)) { - // Determining the timezone - if ($tzid = (string)$xdtend[0]['tzid']) { - $tz = new DateTimeZone($tzid); - } else { - $tz = null; - } + $this->server->httpResponse->sendStatus(200); + $this->server->httpResponse->setHeader('Content-Type', 'text/calendar'); + $this->server->httpResponse->setHeader('Content-Length', strlen($result)); + $this->server->httpResponse->sendBody($result); - // 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); - } else { - $dtend = Sabre_CalDAV_XMLUtil::parseICalendarDate((string)$xdtend[0],$tz); - } + } - } - - if (is_null($dtend)) { - // The DTEND property was not found. We will first see if the event has a duration - // property - - $xduration = $xml->xpath($currentXPath.'/c:duration'); - if (count($xduration)) { - $duration = Sabre_CalDAV_XMLUtil::parseICalendarDuration((string)$xduration[0]); - - // Making sure that the duration is bigger than 0 seconds. - $tempDT = clone $dtstart; - $tempDT->modify($duration); - if ($tempDT > $dtstart) { - - // use DTEND = DTSTART + DURATION - $dtend = $tempDT; - } else { - // use DTEND = DTSTART - $dtend = $dtstart; - } + /** + * This method is triggered before a file gets updated with new content. + * + * This plugin uses this method to ensure that CalDAV objects receive + * valid calendar data. + * + * @param string $path + * @param Sabre_DAV_IFile $node + * @param resource $data + * @return void + */ + public function beforeWriteContent($path, Sabre_DAV_IFile $node, &$data) { - } - } + if (!$node instanceof Sabre_CalDAV_ICalendarObject) + return; + + $this->validateICalendar($data); - if (is_null($dtend)) { - if ($isDateTime) { - // DTEND = DTSTART - $dtend = $dtstart; - } else { - // DTEND = DTSTART + 1 DAY - $dtend = clone $dtstart; - $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 && !$hasRrule) return false; - return true; - } - private function validateTimeRangeFilterForTodo(SimpleXMLElement $xml,$currentXPath,array $filter) { + /** + * This method is triggered before a new file is created. + * + * This plugin uses this method to ensure that newly created calendar + * objects contain valid calendar data. + * + * @param string $path + * @param resource $data + * @param Sabre_DAV_ICollection $parentNode + * @return void + */ + public function beforeCreateFile($path, &$data, Sabre_DAV_ICollection $parentNode) { - // Gathering all relevant elements + if (!$parentNode instanceof Sabre_CalDAV_Calendar) + return; - $dtStart = null; - $duration = null; - $due = null; - $completed = null; - $created = null; + $this->validateICalendar($data); - $xdt = $xml->xpath($currentXPath.'/c:dtstart'); - if (count($xdt)) { - // The dtstart can be both a date, or datetime property - if ((string)$xdt[0]['value']==='DATE') { - $isDateTime = false; - } else { - $isDateTime = true; - } + } - // Determining the timezone - if ($tzid = (string)$xdt[0]['tzid']) { - $tz = new DateTimeZone($tzid); - } else { - $tz = null; - } - if ($isDateTime) { - $dtStart = Sabre_CalDAV_XMLUtil::parseICalendarDateTime((string)$xdt[0],$tz); - } else { - $dtStart = Sabre_CalDAV_XMLUtil::parseICalendarDate((string)$xdt[0]); - } + /** + * Checks if the submitted iCalendar data is in fact, valid. + * + * An exception is thrown if it's not. + * + * @param resource|string $data + * @return void + */ + protected function validateICalendar(&$data) { + + // If it's a stream, we convert it to a string first. + if (is_resource($data)) { + $data = stream_get_contents($data); } - // Only need to grab duration if dtStart is set - if (!is_null($dtStart)) { + // Converting the data to unicode, if needed. + $data = Sabre_DAV_StringUtil::ensureUTF8($data); - $xduration = $xml->xpath($currentXPath.'/c:duration'); - if (count($xduration)) { - $duration = Sabre_CalDAV_XMLUtil::parseICalendarDuration((string)$xduration[0]); - } + try { + + $vobj = Sabre_VObject_Reader::read($data); + + } catch (Sabre_VObject_ParseException $e) { + + throw new Sabre_DAV_Exception_UnsupportedMediaType('This resource only supports valid iCalendar 2.0 data. Parse error: ' . $e->getMessage()); } - if (!is_null($dtStart) && !is_null($duration)) { + } - // Comparision from RFC 4791: - // (start <= DTSTART+DURATION) AND ((end > DTSTART) OR (end >= DTSTART+DURATION)) + /** + * This method handles POST requests to the schedule-outbox + * + * @param Sabre_CalDAV_Schedule_IOutbox $outboxNode + * @return void + */ + public function outboxRequest(Sabre_CalDAV_Schedule_IOutbox $outboxNode) { - $end = clone $dtStart; - $end->modify($duration); + $originator = $this->server->httpRequest->getHeader('Originator'); + $recipients = $this->server->httpRequest->getHeader('Recipient'); - if( (is_null($filter['time-range']['start']) || $filter['time-range']['start'] <= $end) && - (is_null($filter['time-range']['end']) || $filter['time-range']['end'] > $dtStart || $filter['time-range']['end'] >= $end) ) { - return true; - } else { - return false; - } + if (!$originator) { + throw new Sabre_DAV_Exception_BadRequest('The Originator: header must be specified when making POST requests'); + } + if (!$recipients) { + throw new Sabre_DAV_Exception_BadRequest('The Recipient: header must be specified when making POST requests'); + } + if (!preg_match('/^mailto:(.*)@(.*)$/', $originator)) { + throw new Sabre_DAV_Exception_BadRequest('Originator must start with mailto: and must be valid email address'); } + $originator = substr($originator,7); - // Need to grab the DUE property - $xdt = $xml->xpath($currentXPath.'/c:due'); - if (count($xdt)) { - // The due property can be both a date, or datetime property - if ((string)$xdt[0]['value']==='DATE') { - $isDateTime = false; - } else { - $isDateTime = true; - } - // Determining the timezone - if ($tzid = (string)$xdt[0]['tzid']) { - $tz = new DateTimeZone($tzid); - } else { - $tz = null; - } - if ($isDateTime) { - $due = Sabre_CalDAV_XMLUtil::parseICalendarDateTime((string)$xdt[0],$tz); - } else { - $due = Sabre_CalDAV_XMLUtil::parseICalendarDate((string)$xdt[0]); + $recipients = explode(',',$recipients); + foreach($recipients as $k=>$recipient) { + + $recipient = trim($recipient); + if (!preg_match('/^mailto:(.*)@(.*)$/', $recipient)) { + throw new Sabre_DAV_Exception_BadRequest('Recipients must start with mailto: and must be valid email address'); } + $recipient = substr($recipient, 7); + $recipients[$k] = $recipient; } - if (!is_null($dtStart) && !is_null($due)) { - - // Comparision from RFC 4791: - // ((start < DUE) OR (start <= DTSTART)) AND ((end > DTSTART) OR (end >= DUE)) - - if( (is_null($filter['time-range']['start']) || $filter['time-range']['start'] < $due || $filter['time-range']['start'] < $dtstart) && - (is_null($filter['time-range']['end']) || $filter['time-range']['end'] >= $due) ) { - return true; - } else { - return false; - } + // We need to make sure that 'originator' matches one of the email + // addresses of the selected principal. + $principal = $outboxNode->getOwner(); + $props = $this->server->getProperties($principal,array( + '{' . self::NS_CALDAV . '}calendar-user-address-set', + )); + $addresses = array(); + if (isset($props['{' . self::NS_CALDAV . '}calendar-user-address-set'])) { + $addresses = $props['{' . self::NS_CALDAV . '}calendar-user-address-set']->getHrefs(); } - if (!is_null($dtStart)) { - - // Comparision from RFC 4791 - // (start <= DTSTART) AND (end > DTSTART) - if ( (is_null($filter['time-range']['start']) || $filter['time-range']['start'] <= $dtStart) && - (is_null($filter['time-range']['end']) || $filter['time-range']['end'] > $dtStart) ) { - return true; - } else { - return false; - } + if (!in_array('mailto:' . $originator, $addresses)) { + throw new Sabre_DAV_Exception_Forbidden('The addresses specified in the Originator header did not match any addresses in the owners calendar-user-address-set header'); + } + try { + $vObject = Sabre_VObject_Reader::read($this->server->httpRequest->getBody(true)); + } catch (Sabre_VObject_ParseException $e) { + throw new Sabre_DAV_Exception_BadRequest('The request body must be a valid iCalendar object. Parse error: ' . $e->getMessage()); } - if (!is_null($due)) { - - // Comparison from RFC 4791 - // (start < DUE) AND (end >= DUE) - if ( (is_null($filter['time-range']['start']) || $filter['time-range']['start'] < $due) && - (is_null($filter['time-range']['end']) || $filter['time-range']['end'] >= $due) ) { - return true; - } else { - return false; + // Checking for the object type + $componentType = null; + foreach($vObject->getComponents() as $component) { + if ($component->name !== 'VTIMEZONE') { + $componentType = $component->name; + break; } - - } - // Need to grab the COMPLETED property - $xdt = $xml->xpath($currentXPath.'/c:completed'); - if (count($xdt)) { - $completed = Sabre_CalDAV_XMLUtil::parseICalendarDateTime((string)$xdt[0]); } - // Need to grab the CREATED property - $xdt = $xml->xpath($currentXPath.'/c:created'); - if (count($xdt)) { - $created = Sabre_CalDAV_XMLUtil::parseICalendarDateTime((string)$xdt[0]); + if (is_null($componentType)) { + throw new Sabre_DAV_Exception_BadRequest('We expected at least one VTODO, VJOURNAL, VFREEBUSY or VEVENT component'); } - if (!is_null($completed) && !is_null($created)) { - // Comparison from RFC 4791 - // ((start <= CREATED) OR (start <= COMPLETED)) AND ((end >= CREATED) OR (end >= COMPLETED)) - if( (is_null($filter['time-range']['start']) || $filter['time-range']['start'] <= $created || $filter['time-range']['start'] <= $completed) && - (is_null($filter['time-range']['end']) || $filter['time-range']['end'] >= $created || $filter['time-range']['end'] >= $completed)) { - return true; - } else { - return false; - } + // Validating the METHOD + $method = strtoupper((string)$vObject->METHOD); + if (!$method) { + throw new Sabre_DAV_Exception_BadRequest('A METHOD property must be specified in iTIP messages'); } - if (!is_null($completed)) { - // Comparison from RFC 4791 - // (start <= COMPLETED) AND (end >= COMPLETED) - if( (is_null($filter['time-range']['start']) || $filter['time-range']['start'] <= $completed) && - (is_null($filter['time-range']['end']) || $filter['time-range']['end'] >= $completed)) { - return true; - } else { - return false; - } + if (in_array($method, array('REQUEST','REPLY','ADD','CANCEL')) && $componentType==='VEVENT') { + $this->iMIPMessage($originator, $recipients, $vObject); + $this->server->httpResponse->sendStatus(200); + $this->server->httpResponse->sendBody('Messages sent'); + } else { + throw new Sabre_DAV_Exception_NotImplemented('This iTIP method is currently not implemented'); } - if (!is_null($created)) { - // Comparison from RFC 4791 - // (end > CREATED) - if( (is_null($filter['time-range']['end']) || $filter['time-range']['end'] > $created) ) { - return true; - } else { - return false; - } + } + + /** + * Sends an iMIP message by email. + * + * @param string $originator + * @param array $recipients + * @param Sabre_VObject_Component $vObject + * @return void + */ + protected function iMIPMessage($originator, array $recipients, Sabre_VObject_Component $vObject) { + + if (!$this->imipHandler) { + throw new Sabre_DAV_Exception_NotImplemented('No iMIP handler is setup on this server.'); } + $this->imipHandler->sendMessage($originator, $recipients, $vObject); + + } + + /** + * This method is used to generate HTML output for the + * Sabre_DAV_Browser_Plugin. This allows us to generate an interface users + * can use to create new calendars. + * + * @param Sabre_DAV_INode $node + * @param string $output + * @return bool + */ + public function htmlActionsPanel(Sabre_DAV_INode $node, &$output) { + + if (!$node instanceof Sabre_CalDAV_UserCalendars) + return; + + $output.= '<tr><td colspan="2"><form method="post" action=""> + <h3>Create new calendar</h3> + <input type="hidden" name="sabreAction" value="mkcalendar" /> + <label>Name (uri):</label> <input type="text" name="name" /><br /> + <label>Display name:</label> <input type="text" name="{DAV:}displayname" /><br /> + <input type="submit" value="create" /> + </form> + </td></tr>'; + + return false; - // Everything else is TRUE - return true; + } + + /** + * This method allows us to intercept the 'mkcalendar' sabreAction. This + * action enables the user to create new calendars from the browser plugin. + * + * @param string $uri + * @param string $action + * @param array $postVars + * @return bool + */ + public function browserPostAction($uri, $action, array $postVars) { + + if ($action!=='mkcalendar') + return; + + $resourceType = array('{DAV:}collection','{urn:ietf:params:xml:ns:caldav}calendar'); + $properties = array(); + if (isset($postVars['{DAV:}displayname'])) { + $properties['{DAV:}displayname'] = $postVars['{DAV:}displayname']; + } + $this->server->createCollection($uri . '/' . $postVars['name'],$resourceType,$properties); + return false; } diff --git a/3rdparty/Sabre/CalDAV/Principal/Collection.php b/3rdparty/Sabre/CalDAV/Principal/Collection.php index 13435b2448e..abbefa5567a 100644..100755 --- a/3rdparty/Sabre/CalDAV/Principal/Collection.php +++ b/3rdparty/Sabre/CalDAV/Principal/Collection.php @@ -4,23 +4,23 @@ * Principal collection * * This is an alternative collection to the standard ACL principal collection. - * This collection adds support for the calendar-proxy-read and - * calendar-proxy-write sub-principals, as defined by the caldav-proxy + * This collection adds support for the calendar-proxy-read and + * calendar-proxy-write sub-principals, as defined by the caldav-proxy * specification. * * @package Sabre * @subpackage CalDAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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_Principal_Collection extends Sabre_DAVACL_AbstractPrincipalCollection { /** - * Returns a child object based on principal information - * - * @param array $principalInfo - * @return Sabre_CalDAV_Principal_User + * Returns a child object based on principal information + * + * @param array $principalInfo + * @return Sabre_CalDAV_Principal_User */ public function getChildForPrincipal(array $principalInfo) { diff --git a/3rdparty/Sabre/CalDAV/Principal/ProxyRead.php b/3rdparty/Sabre/CalDAV/Principal/ProxyRead.php index f531d85d1ff..4b3f035634a 100644..100755 --- a/3rdparty/Sabre/CalDAV/Principal/ProxyRead.php +++ b/3rdparty/Sabre/CalDAV/Principal/ProxyRead.php @@ -4,38 +4,38 @@ * ProxyRead principal * * This class represents a principal group, hosted under the main principal. - * This is needed to implement 'Calendar delegation' support. This class is + * This is needed to implement 'Calendar delegation' support. This class is * instantiated by Sabre_CalDAV_Principal_User. - * + * * @package Sabre * @subpackage CalDAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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_Principal_ProxyRead implements Sabre_DAVACL_IPrincipal { /** - * Principal information from the parent principal. - * - * @var array + * Principal information from the parent principal. + * + * @var array */ protected $principalInfo; /** - * Principal backend - * - * @var Sabre_DAVACL_IPrincipalBackend + * Principal backend + * + * @var Sabre_DAVACL_IPrincipalBackend */ protected $principalBackend; /** * Creates the object. * - * Note that you MUST supply the parent principal information. - * - * @param Sabre_DAVACL_IPrincipalBackend $principalBackend - * @param array $principalInfo + * Note that you MUST supply the parent principal information. + * + * @param Sabre_DAVACL_IPrincipalBackend $principalBackend + * @param array $principalInfo */ public function __construct(Sabre_DAVACL_IPrincipalBackend $principalBackend, array $principalInfo) { @@ -46,8 +46,8 @@ class Sabre_CalDAV_Principal_ProxyRead implements Sabre_DAVACL_IPrincipal { /** * Returns this principals name. - * - * @return string + * + * @return string */ public function getName() { @@ -56,13 +56,13 @@ class Sabre_CalDAV_Principal_ProxyRead implements Sabre_DAVACL_IPrincipal { } /** - * Returns the last modification time + * Returns the last modification time * - * @return null + * @return null */ public function getLastModified() { - return null; + return null; } @@ -70,7 +70,7 @@ class Sabre_CalDAV_Principal_ProxyRead implements Sabre_DAVACL_IPrincipal { * Deletes the current node * * @throws Sabre_DAV_Exception_Forbidden - * @return void + * @return void */ public function delete() { @@ -80,7 +80,7 @@ class Sabre_CalDAV_Principal_ProxyRead implements Sabre_DAVACL_IPrincipal { /** * Renames the node - * + * * @throws Sabre_DAV_Exception_Forbidden * @param string $name The new name * @return void @@ -93,11 +93,11 @@ class Sabre_CalDAV_Principal_ProxyRead implements Sabre_DAVACL_IPrincipal { /** - * Returns a list of altenative urls for a principal - * + * Returns a list of alternative urls for a principal + * * This can for example be an email address, or ldap url. - * - * @return array + * + * @return array */ public function getAlternateUriSet() { @@ -106,41 +106,41 @@ class Sabre_CalDAV_Principal_ProxyRead implements Sabre_DAVACL_IPrincipal { } /** - * Returns the full principal url - * - * @return string + * Returns the full principal url + * + * @return string */ public function getPrincipalUrl() { - return $this->principalInfo['uri'] . '/' . $this->getName(); + 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. - * + * all member principal uri's for the group. + * * @return array */ public function getGroupMemberSet() { - return $this->principalBackend->getGroupMemberSet($this->getPrincipalUrl()); + 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 + * should return a list of principal uri's for it's members. + * + * @return array */ public function getGroupMembership() { - return $this->principalBackend->getGroupMembership($this->getPrincipalUrl()); + return $this->principalBackend->getGroupMembership($this->getPrincipalUrl()); } @@ -149,11 +149,11 @@ class Sabre_CalDAV_Principal_ProxyRead implements Sabre_DAVACL_IPrincipal { * * 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 + * + * This method should throw an exception if the members could not be set. + * + * @param array $principals + * @return void */ public function setGroupMemberSet(array $principals) { @@ -165,9 +165,9 @@ class Sabre_CalDAV_Principal_ProxyRead implements Sabre_DAVACL_IPrincipal { * Returns the displayname * * This should be a human readable name for the principal. - * If none is available, return the nodename. - * - * @return string + * If none is available, return the nodename. + * + * @return string */ public function getDisplayName() { diff --git a/3rdparty/Sabre/CalDAV/Principal/ProxyWrite.php b/3rdparty/Sabre/CalDAV/Principal/ProxyWrite.php index 4d8face2060..dd0c2e86edd 100644..100755 --- a/3rdparty/Sabre/CalDAV/Principal/ProxyWrite.php +++ b/3rdparty/Sabre/CalDAV/Principal/ProxyWrite.php @@ -4,38 +4,38 @@ * ProxyWrite principal * * This class represents a principal group, hosted under the main principal. - * This is needed to implement 'Calendar delegation' support. This class is + * This is needed to implement 'Calendar delegation' support. This class is * instantiated by Sabre_CalDAV_Principal_User. - * + * * @package Sabre * @subpackage CalDAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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_Principal_ProxyWrite implements Sabre_DAVACL_IPrincipal { /** - * Parent principal information - * - * @var array + * Parent principal information + * + * @var array */ protected $principalInfo; /** - * Principal Backend - * - * @var Sabre_DAVACL_IPrincipalBackend + * Principal Backend + * + * @var Sabre_DAVACL_IPrincipalBackend */ protected $principalBackend; /** * Creates the object * - * Note that you MUST supply the parent principal information. - * - * @param Sabre_DAVACL_IPrincipalBackend $principalBackend - * @param array $principalInfo + * Note that you MUST supply the parent principal information. + * + * @param Sabre_DAVACL_IPrincipalBackend $principalBackend + * @param array $principalInfo */ public function __construct(Sabre_DAVACL_IPrincipalBackend $principalBackend, array $principalInfo) { @@ -46,8 +46,8 @@ class Sabre_CalDAV_Principal_ProxyWrite implements Sabre_DAVACL_IPrincipal { /** * Returns this principals name. - * - * @return string + * + * @return string */ public function getName() { @@ -56,13 +56,13 @@ class Sabre_CalDAV_Principal_ProxyWrite implements Sabre_DAVACL_IPrincipal { } /** - * Returns the last modification time + * Returns the last modification time * - * @return null + * @return null */ public function getLastModified() { - return null; + return null; } @@ -70,7 +70,7 @@ class Sabre_CalDAV_Principal_ProxyWrite implements Sabre_DAVACL_IPrincipal { * Deletes the current node * * @throws Sabre_DAV_Exception_Forbidden - * @return void + * @return void */ public function delete() { @@ -80,7 +80,7 @@ class Sabre_CalDAV_Principal_ProxyWrite implements Sabre_DAVACL_IPrincipal { /** * Renames the node - * + * * @throws Sabre_DAV_Exception_Forbidden * @param string $name The new name * @return void @@ -93,11 +93,11 @@ class Sabre_CalDAV_Principal_ProxyWrite implements Sabre_DAVACL_IPrincipal { /** - * Returns a list of altenative urls for a principal - * + * Returns a list of alternative urls for a principal + * * This can for example be an email address, or ldap url. - * - * @return array + * + * @return array */ public function getAlternateUriSet() { @@ -106,41 +106,41 @@ class Sabre_CalDAV_Principal_ProxyWrite implements Sabre_DAVACL_IPrincipal { } /** - * Returns the full principal url - * - * @return string + * Returns the full principal url + * + * @return string */ public function getPrincipalUrl() { - return $this->principalInfo['uri'] . '/' . $this->getName(); + 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. - * + * all member principal uri's for the group. + * * @return array */ public function getGroupMemberSet() { - return $this->principalBackend->getGroupMemberSet($this->getPrincipalUrl()); + 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 + * should return a list of principal uri's for it's members. + * + * @return array */ public function getGroupMembership() { - return $this->principalBackend->getGroupMembership($this->getPrincipalUrl()); + return $this->principalBackend->getGroupMembership($this->getPrincipalUrl()); } @@ -149,11 +149,11 @@ class Sabre_CalDAV_Principal_ProxyWrite implements Sabre_DAVACL_IPrincipal { * * 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 + * + * This method should throw an exception if the members could not be set. + * + * @param array $principals + * @return void */ public function setGroupMemberSet(array $principals) { @@ -165,9 +165,9 @@ class Sabre_CalDAV_Principal_ProxyWrite implements Sabre_DAVACL_IPrincipal { * Returns the displayname * * This should be a human readable name for the principal. - * If none is available, return the nodename. - * - * @return string + * If none is available, return the nodename. + * + * @return string */ public function getDisplayName() { diff --git a/3rdparty/Sabre/CalDAV/Principal/User.php b/3rdparty/Sabre/CalDAV/Principal/User.php index 034629b89b3..8453b877a73 100644..100755 --- a/3rdparty/Sabre/CalDAV/Principal/User.php +++ b/3rdparty/Sabre/CalDAV/Principal/User.php @@ -1,25 +1,25 @@ <?php /** - * CalDAV principal + * CalDAV principal * - * This is a standard user-principal for CalDAV. This principal is also a - * collection and returns the caldav-proxy-read and caldav-proxy-write child + * This is a standard user-principal for CalDAV. This principal is also a + * collection and returns the caldav-proxy-read and caldav-proxy-write child * principals. - * + * * @package Sabre * @subpackage CalDAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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_Principal_User extends Sabre_DAVACL_Principal implements Sabre_DAV_ICollection { /** - * Creates a new file in the directory - * - * @param string $name Name of the file - * @param resource $data Initial payload, passed as a readable stream resource. + * Creates a new file in the directory + * + * @param string $name Name of the file + * @param resource $data Initial payload, passed as a readable stream resource. * @throws Sabre_DAV_Exception_Forbidden * @return void */ @@ -30,9 +30,9 @@ class Sabre_CalDAV_Principal_User extends Sabre_DAVACL_Principal implements Sabr } /** - * Creates a new subdirectory - * - * @param string $name + * Creates a new subdirectory + * + * @param string $name * @throws Sabre_DAV_Exception_Forbidden * @return void */ @@ -43,45 +43,60 @@ class Sabre_CalDAV_Principal_User extends Sabre_DAVACL_Principal implements Sabr } /** - * Returns a specific child node, referenced by its name - * - * @param string $name - * @return Sabre_DAV_INode + * Returns a specific child node, referenced by its name + * + * @param string $name + * @return Sabre_DAV_INode */ public function getChild($name) { + $principal = $this->principalBackend->getPrincipalByPath($this->getPrincipalURL() . '/' . $name); + if (!$principal) { + throw new Sabre_DAV_Exception_NotFound('Node with name ' . $name . ' was not found'); + } if ($name === 'calendar-proxy-read') return new Sabre_CalDAV_Principal_ProxyRead($this->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'); + throw new Sabre_DAV_Exception_NotFound('Node with name ' . $name . ' was not found'); } /** - * Returns an array with all the child nodes - * - * @return Sabre_DAV_INode[] + * 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), - ); + $r = array(); + if ($this->principalBackend->getPrincipalByPath($this->getPrincipalURL() . '/calendar-proxy-read')) { + $r[] = new Sabre_CalDAV_Principal_ProxyRead($this->principalBackend, $this->principalProperties); + } + if ($this->principalBackend->getPrincipalByPath($this->getPrincipalURL() . '/calendar-proxy-write')) { + $r[] = new Sabre_CalDAV_Principal_ProxyWrite($this->principalBackend, $this->principalProperties); + } + + return $r; } /** - * Checks if a child-node with the specified name exists - * - * @return bool + * Returns whether or not the child node exists + * + * @param string $name + * @return bool */ public function childExists($name) { - return $name === 'calendar-proxy-read' || $name === 'calendar-proxy-write'; + try { + $this->getChild($name); + return true; + } catch (Sabre_DAV_Exception_NotFound $e) { + return false; + } } @@ -89,33 +104,28 @@ class Sabre_CalDAV_Principal_User extends Sabre_DAVACL_Principal implements Sabr * 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 + * * '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 + * * '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, - ), + $acl = parent::getACL(); + $acl[] = array( + 'privilege' => '{DAV:}read', + 'principal' => $this->principalProperties['uri'] . '/calendar-proxy-read', + 'protected' => true, + ); + $acl[] = array( + 'privilege' => '{DAV:}read', + 'principal' => $this->principalProperties['uri'] . '/calendar-proxy-write', + 'protected' => true, ); + return $acl; } diff --git a/3rdparty/Sabre/CalDAV/Property/SupportedCalendarComponentSet.php b/3rdparty/Sabre/CalDAV/Property/SupportedCalendarComponentSet.php index 1bbaca6b8a7..2ea078d7dac 100644..100755 --- a/3rdparty/Sabre/CalDAV/Property/SupportedCalendarComponentSet.php +++ b/3rdparty/Sabre/CalDAV/Property/SupportedCalendarComponentSet.php @@ -3,40 +3,40 @@ /** * Supported component set property * - * This property is a representation of the supported-calendar_component-set + * This property is a representation of the supported-calendar_component-set * property in the CalDAV namespace. It simply requires an array of components, * such as VEVENT, VTODO * * @package Sabre * @subpackage CalDAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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_SupportedCalendarComponentSet extends Sabre_DAV_Property { /** - * List of supported components, such as "VEVENT, VTODO" - * - * @var array + * List of supported components, such as "VEVENT, VTODO" + * + * @var array */ private $components; /** - * Creates the property - * - * @param array $components + * Creates the property + * + * @param array $components */ public function __construct(array $components) { - $this->components = $components; + $this->components = $components; } /** - * Returns the list of supported components - * - * @return array + * Returns the list of supported components + * + * @return array */ public function getValue() { @@ -45,10 +45,10 @@ class Sabre_CalDAV_Property_SupportedCalendarComponentSet extends Sabre_DAV_Prop } /** - * Serializes the property in a DOMDocument - * - * @param Sabre_DAV_Server $server - * @param DOMElement $node + * Serializes the property in a DOMDocument + * + * @param Sabre_DAV_Server $server + * @param DOMElement $node * @return void */ public function serialize(Sabre_DAV_Server $server,DOMElement $node) { @@ -58,7 +58,7 @@ class Sabre_CalDAV_Property_SupportedCalendarComponentSet extends Sabre_DAV_Prop $xcomp = $doc->createElement('cal:comp'); $xcomp->setAttribute('name',$component); - $node->appendChild($xcomp); + $node->appendChild($xcomp); } @@ -66,9 +66,9 @@ class Sabre_CalDAV_Property_SupportedCalendarComponentSet extends Sabre_DAV_Prop /** * Unserializes the DOMElement back into a Property class. - * - * @param DOMElement $node - * @return void + * + * @param DOMElement $node + * @return Sabre_CalDAV_Property_SupportedCalendarComponentSet */ static function unserialize(DOMElement $node) { diff --git a/3rdparty/Sabre/CalDAV/Property/SupportedCalendarData.php b/3rdparty/Sabre/CalDAV/Property/SupportedCalendarData.php index 5010ee6d525..1d848dd5cf6 100644..100755 --- a/3rdparty/Sabre/CalDAV/Property/SupportedCalendarData.php +++ b/3rdparty/Sabre/CalDAV/Property/SupportedCalendarData.php @@ -9,17 +9,17 @@ * * @package Sabre * @subpackage CalDAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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_SupportedCalendarData extends Sabre_DAV_Property { /** - * Serializes the property in a DOMDocument - * - * @param Sabre_DAV_Server $server - * @param DOMElement $node + * Serializes the property in a DOMDocument + * + * @param Sabre_DAV_Server $server + * @param DOMElement $node * @return void */ public function serialize(Sabre_DAV_Server $server,DOMElement $node) { @@ -32,7 +32,7 @@ class Sabre_CalDAV_Property_SupportedCalendarData extends Sabre_DAV_Property { $caldata->setAttribute('content-type','text/calendar'); $caldata->setAttribute('version','2.0'); - $node->appendChild($caldata); + $node->appendChild($caldata); } } diff --git a/3rdparty/Sabre/CalDAV/Property/SupportedCollationSet.php b/3rdparty/Sabre/CalDAV/Property/SupportedCollationSet.php index e585e9db3d8..24e84d4c17d 100644..100755 --- a/3rdparty/Sabre/CalDAV/Property/SupportedCollationSet.php +++ b/3rdparty/Sabre/CalDAV/Property/SupportedCollationSet.php @@ -4,27 +4,27 @@ * supported-collation-set property * * This property is a representation of the supported-collation-set property - * in the CalDAV namespace. + * in the CalDAV namespace. * * @package Sabre * @subpackage CalDAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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 { /** - * Serializes the property in a DOM document - * - * @param Sabre_DAV_Server $server - * @param 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; - + $prefix = $node->lookupPrefix('urn:ietf:params:xml:ns:caldav'); if (!$prefix) $prefix = 'cal'; diff --git a/3rdparty/Sabre/CalDAV/Schedule/IMip.php b/3rdparty/Sabre/CalDAV/Schedule/IMip.php new file mode 100755 index 00000000000..37e75fcc4a7 --- /dev/null +++ b/3rdparty/Sabre/CalDAV/Schedule/IMip.php @@ -0,0 +1,104 @@ +<?php + +/** + * iMIP handler. + * + * This class is responsible for sending out iMIP messages. iMIP is the + * email-based transport for iTIP. iTIP deals with scheduling operations for + * iCalendar objects. + * + * If you want to customize the email that gets sent out, you can do so by + * extending this class and overriding the sendMessage method. + * + * @package Sabre + * @subpackage CalDAV + * @copyright Copyright (C) 2007-2012 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_Schedule_IMip { + + /** + * Email address used in From: header. + * + * @var string + */ + protected $senderEmail; + + /** + * Creates the email handler. + * + * @param string $senderEmail. The 'senderEmail' is the email that shows up + * in the 'From:' address. This should + * generally be some kind of no-reply email + * address you own. + */ + public function __construct($senderEmail) { + + $this->senderEmail = $senderEmail; + + } + + /** + * Sends one or more iTip messages through email. + * + * @param string $originator + * @param array $recipients + * @param Sabre_VObject_Component $vObject + * @return void + */ + public function sendMessage($originator, array $recipients, Sabre_VObject_Component $vObject) { + + foreach($recipients as $recipient) { + + $to = $recipient; + $replyTo = $originator; + $subject = 'SabreDAV iTIP message'; + + switch(strtoupper($vObject->METHOD)) { + case 'REPLY' : + $subject = 'Response for: ' . $vObject->VEVENT->SUMMARY; + break; + case 'REQUEST' : + $subject = 'Invitation for: ' .$vObject->VEVENT->SUMMARY; + break; + case 'CANCEL' : + $subject = 'Cancelled event: ' . $vObject->VEVENT->SUMMARY; + break; + } + + $headers = array(); + $headers[] = 'Reply-To: ' . $replyTo; + $headers[] = 'From: ' . $this->senderEmail; + $headers[] = 'Content-Type: text/calendar; method=' . (string)$vObject->method . '; charset=utf-8'; + if (Sabre_DAV_Server::$exposeVersion) { + $headers[] = 'X-Sabre-Version: ' . Sabre_DAV_Version::VERSION . '-' . Sabre_DAV_Version::STABILITY; + } + + $vcalBody = $vObject->serialize(); + + $this->mail($to, $subject, $vcalBody, $headers); + + } + + } + + /** + * This function is reponsible for sending the actual email. + * + * @param string $to Recipient email address + * @param string $subject Subject of the email + * @param string $body iCalendar body + * @param array $headers List of headers + * @return void + */ + protected function mail($to, $subject, $body, array $headers) { + + mail($to, $subject, $body, implode("\r\n", $headers)); + + } + + +} + +?> diff --git a/3rdparty/Sabre/CalDAV/Schedule/IOutbox.php b/3rdparty/Sabre/CalDAV/Schedule/IOutbox.php new file mode 100755 index 00000000000..46d77514bc0 --- /dev/null +++ b/3rdparty/Sabre/CalDAV/Schedule/IOutbox.php @@ -0,0 +1,16 @@ +<?php + +/** + * Implement this interface to have a node be recognized as a CalDAV scheduling + * outbox. + * + * @package Sabre + * @subpackage CalDAV + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. + * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License + */ +interface Sabre_CalDAV_Schedule_IOutbox extends Sabre_DAV_ICollection, Sabre_DAVACL_IACL { + + +} diff --git a/3rdparty/Sabre/CalDAV/Schedule/Outbox.php b/3rdparty/Sabre/CalDAV/Schedule/Outbox.php new file mode 100755 index 00000000000..014c37230d1 --- /dev/null +++ b/3rdparty/Sabre/CalDAV/Schedule/Outbox.php @@ -0,0 +1,152 @@ +<?php + +/** + * The CalDAV scheduling outbox + * + * The outbox is mainly used as an endpoint in the tree for a client to do + * free-busy requests. This functionality is completely handled by the + * Scheduling plugin, so this object is actually mostly static. + * + * @package Sabre + * @subpackage CalDAV + * @copyright Copyright (C) 2007-2012 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_Schedule_Outbox extends Sabre_DAV_Directory implements Sabre_CalDAV_Schedule_IOutbox { + + /** + * The principal Uri + * + * @var string + */ + protected $principalUri; + + /** + * Constructor + * + * @param string $principalUri + */ + public function __construct($principalUri) { + + $this->principalUri = $principalUri; + + } + + /** + * Returns the name of the node. + * + * This is used to generate the url. + * + * @return string + */ + public function getName() { + + return 'outbox'; + + } + + /** + * Returns an array with all the child nodes + * + * @return Sabre_DAV_INode[] + */ + public function getChildren() { + + return array(); + + } + + /** + * 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->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' => '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}schedule-query-freebusy', + 'principal' => $this->getOwner(), + 'protected' => true, + ), + array( + 'privilege' => '{DAV:}read', + 'principal' => $this->getOwner(), + '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('You\'re not allowed to update the ACL'); + + } + + /** + * Returns the list of supported privileges for this node. + * + * The returned data structure is a list of nested privileges. + * See Sabre_DAVACL_Plugin::getDefaultSupportedPrivilegeSet for a simple + * standard structure. + * + * If null is returned from this method, the default privilege set is used, + * which is fine for most common usecases. + * + * @return array|null + */ + public function getSupportedPrivilegeSet() { + + $default = Sabre_DAVACL_Plugin::getDefaultSupportedPrivilegeSet(); + $default['aggregates'][] = array( + 'privilege' => '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}schedule-query-freebusy', + ); + + return $default; + + } + +} diff --git a/3rdparty/Sabre/CalDAV/Server.php b/3rdparty/Sabre/CalDAV/Server.php index 969d69c6279..325e3d80a7f 100644..100755 --- a/3rdparty/Sabre/CalDAV/Server.php +++ b/3rdparty/Sabre/CalDAV/Server.php @@ -3,17 +3,20 @@ /** * CalDAV server * + * Deprecated! Warning: This class is now officially deprecated + * * 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 + * 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-2011 Rooftop Solutions. All rights reserved. + * @deprecated Don't use this class anymore, it will be removed in version 1.7. + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ @@ -22,17 +25,17 @@ 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. - * + * 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. - * - * @param PDO $pdo + * + * @param PDO $pdo */ public function __construct(PDO $pdo) { diff --git a/3rdparty/Sabre/CalDAV/UserCalendars.php b/3rdparty/Sabre/CalDAV/UserCalendars.php index f52d65e9a73..b8d3f0573fa 100644..100755 --- a/3rdparty/Sabre/CalDAV/UserCalendars.php +++ b/3rdparty/Sabre/CalDAV/UserCalendars.php @@ -1,68 +1,68 @@ <?php /** - * The UserCalenders class contains all calendars associated to one user - * + * The UserCalenders class contains all calendars associated to one user + * * @package Sabre * @subpackage CalDAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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, Sabre_DAVACL_IACL { /** - * Principal backend - * + * Principal backend + * * @var Sabre_DAVACL_IPrincipalBackend */ protected $principalBackend; /** * CalDAV backend - * + * * @var Sabre_CalDAV_Backend_Abstract */ protected $caldavBackend; /** - * Principal information - * - * @var array + * Principal information + * + * @var array */ protected $principalInfo; - + /** - * Constructor - * + * Constructor + * * @param Sabre_DAVACL_IPrincipalBackend $principalBackend - * @param Sabre_CalDAV_Backend_Abstract $caldavBackend - * @param mixed $userUri + * @param Sabre_CalDAV_Backend_Abstract $caldavBackend + * @param mixed $userUri */ public function __construct(Sabre_DAVACL_IPrincipalBackend $principalBackend, Sabre_CalDAV_Backend_Abstract $caldavBackend, $userUri) { $this->principalBackend = $principalBackend; $this->caldavBackend = $caldavBackend; $this->principalInfo = $principalBackend->getPrincipalByPath($userUri); - + } /** - * Returns the name of this object - * + * Returns the name of this object + * * @return string */ public function getName() { - + list(,$name) = Sabre_DAV_URLUtil::splitPath($this->principalInfo['uri']); - return $name; + return $name; } /** - * Updates the name of this object - * - * @param string $name + * Updates the name of this object + * + * @param string $name * @return void */ public function setName($name) { @@ -72,8 +72,8 @@ class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre } /** - * Deletes this object - * + * Deletes this object + * * @return void */ public function delete() { @@ -83,13 +83,13 @@ class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre } /** - * Returns the last modification date - * - * @return int + * Returns the last modification date + * + * @return int */ public function getLastModified() { - return null; + return null; } @@ -97,9 +97,9 @@ class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre * Creates a new file under this object. * * This is currently not allowed - * - * @param string $filename - * @param resource $data + * + * @param string $filename + * @param resource $data * @return void */ public function createFile($filename, $data=null) { @@ -112,8 +112,8 @@ class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre * Creates a new directory under this object. * * This is currently not allowed. - * - * @param string $filename + * + * @param string $filename * @return void */ public function createDirectory($filename) { @@ -123,11 +123,11 @@ class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre } /** - * Returns a single calendar, by name - * + * Returns a single calendar, by name + * * @param string $name * @todo needs optimizing - * @return Sabre_CalDAV_Calendar + * @return Sabre_CalDAV_Calendar */ public function getChild($name) { @@ -136,22 +136,22 @@ class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre return $child; } - throw new Sabre_DAV_Exception_FileNotFound('Calendar with name \'' . $name . '\' could not be found'); + throw new Sabre_DAV_Exception_NotFound('Calendar with name \'' . $name . '\' could not be found'); } /** * Checks if a calendar exists. - * + * * @param string $name * @todo needs optimizing - * @return bool + * @return bool */ public function childExists($name) { foreach($this->getChildren() as $child) { if ($name==$child->getName()) - return true; + return true; } return false; @@ -160,8 +160,8 @@ class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre /** * Returns a list of calendars - * - * @return array + * + * @return array */ public function getChildren() { @@ -170,15 +170,17 @@ class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre foreach($calendars as $calendar) { $objs[] = new Sabre_CalDAV_Calendar($this->principalBackend, $this->caldavBackend, $calendar); } + $objs[] = new Sabre_CalDAV_Schedule_Outbox($this->principalInfo['uri']); return $objs; } /** * Creates a new calendar - * - * @param string $name - * @param string $properties + * + * @param string $name + * @param array $resourceType + * @param array $properties * @return void */ public function createExtendedCollection($name, array $resourceType, array $properties) { @@ -193,8 +195,8 @@ class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre /** * Returns the owner principal * - * This must be a url to a principal, or null if there's no owner - * + * This must be a url to a principal, or null if there's no owner + * * @return string|null */ public function getOwner() { @@ -207,8 +209,8 @@ class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre * Returns a group principal * * This must be a url to a principal, or null if there's no owner - * - * @return string|null + * + * @return string|null */ public function getGroup() { @@ -220,13 +222,13 @@ class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre * 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 + * * '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 + * * 'protected' (optional), indicating that this ACE is not allowed to + * be updated. + * + * @return array */ public function getACL() { @@ -264,9 +266,9 @@ class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre /** * Updates the ACL * - * This method will receive a list of new ACE's. - * - * @param array $acl + * This method will receive a list of new ACE's. + * + * @param array $acl * @return void */ public function setACL(array $acl) { @@ -275,6 +277,22 @@ class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre } + /** + * Returns the list of supported privileges for this node. + * + * The returned data structure is a list of nested privileges. + * See Sabre_DAVACL_Plugin::getDefaultSupportedPrivilegeSet for a simple + * standard structure. + * + * If null is returned from this method, the default privilege set is used, + * which is fine for most common usecases. + * + * @return array|null + */ + public function getSupportedPrivilegeSet() { + + return null; + } } diff --git a/3rdparty/Sabre/CalDAV/Version.php b/3rdparty/Sabre/CalDAV/Version.php index df8fe1f6bd6..939e903c89f 100644..100755 --- a/3rdparty/Sabre/CalDAV/Version.php +++ b/3rdparty/Sabre/CalDAV/Version.php @@ -2,10 +2,10 @@ /** * This class contains the Sabre_CalDAV version constants. - * + * * @package Sabre * @subpackage CalDAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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_CalDAV_Version { /** * Full version number */ - const VERSION = '1.5.3'; + const VERSION = '1.6.2'; /** * Stability : alpha, beta, stable diff --git a/3rdparty/Sabre/CalDAV/XMLUtil.php b/3rdparty/Sabre/CalDAV/XMLUtil.php deleted file mode 100644 index bf349a36aae..00000000000 --- a/3rdparty/Sabre/CalDAV/XMLUtil.php +++ /dev/null @@ -1,208 +0,0 @@ -<?php - -/** - * XML utilities for CalDAV - * - * This class contains a few static methods used for parsing certain CalDAV - * requests. - * - * @package Sabre - * @subpackage CalDAV - * @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_XMLUtil { - - /** - * This function parses the calendar-query report request body - * - * The body is quite complicated, so we're turning it into a PHP - * array. - * - * The resulting associative array has xpath expressions as keys. - * By default the xpath expressions should simply be checked for existance - * The xpath expressions can point to elements or attributes. - * - * The array values can contain a number of items, which alters the query - * filter. - * - * * time-range. Must also check if the todo or event falls within the - * specified timerange. How this is interpreted depends on - * the type of object (VTODO, VEVENT, VJOURNAL, etc) - * * is-not-defined - * Instead of checking if the attribute or element exist, - * we must check if it doesn't. - * * text-match - * Checks if the value of the attribute or element matches - * the specified value. This is actually another array with - * the 'collation', 'value' and 'negate-condition' items. - * - * Refer to the CalDAV spec for more information. - * - * @param DOMNode $domNode - * @param string $basePath used for recursive calls. - * @param array $filters used for recursive calls. - * @return array - */ - static public function parseCalendarQueryFilters($domNode,$basePath = '/c:iCalendar', &$filters = array()) { - - foreach($domNode->childNodes as $child) { - - switch(Sabre_DAV_XMLUtil::toClarkNotation($child)) { - - case '{urn:ietf:params:xml:ns:caldav}comp-filter' : - case '{urn:ietf:params:xml:ns:caldav}prop-filter' : - - $filterName = $basePath . '/' . 'c:' . strtolower($child->getAttribute('name')); - $filters[$filterName] = array(); - - self::parseCalendarQueryFilters($child, $filterName,$filters); - break; - - case '{urn:ietf:params:xml:ns:caldav}time-range' : - - if ($start = $child->getAttribute('start')) { - $start = self::parseICalendarDateTime($start); - } else { - $start = null; - } - if ($end = $child->getAttribute('end')) { - $end = self::parseICalendarDateTime($end); - } else { - $end = null; - } - - if (!is_null($start) && !is_null($end) && $end <= $start) { - throw new Sabre_DAV_Exception_BadRequest('The end-date must be larger than the start-date in the time-range filter'); - } - - $filters[$basePath]['time-range'] = array( - 'start' => $start, - 'end' => $end - ); - break; - - case '{urn:ietf:params:xml:ns:caldav}is-not-defined' : - $filters[$basePath]['is-not-defined'] = true; - break; - - case '{urn:ietf:params:xml:ns:caldav}param-filter' : - - $filterName = $basePath . '/@' . strtolower($child->getAttribute('name')); - $filters[$filterName] = array(); - self::parseCalendarQueryFilters($child, $filterName, $filters); - break; - - case '{urn:ietf:params:xml:ns:caldav}text-match' : - - $collation = $child->getAttribute('collation'); - if (!$collation) $collation = 'i;ascii-casemap'; - - $filters[$basePath]['text-match'] = array( - 'collation' => ($collation == 'default'?'i;ascii-casemap':$collation), - 'negate-condition' => $child->getAttribute('negate-condition')==='yes', - 'value' => $child->nodeValue, - ); - break; - - } - - } - - return $filters; - - } - - /** - * Parses an iCalendar (rfc5545) formatted datetime and returns a DateTime object - * - * Specifying a reference timezone is optional. It will only be used - * if the non-UTC format is used. The argument is used as a reference, the - * returned DateTime object will still be in the UTC timezone. - * - * @param string $dt - * @param DateTimeZone $tz - * @return DateTime - */ - static public function parseICalendarDateTime($dt,DateTimeZone $tz = null) { - - // Format is YYYYMMDD + "T" + hhmmss - $result = preg_match('/^([1-3][0-9]{3})([0-1][0-9])([0-3][0-9])T([0-2][0-9])([0-5][0-9])([0-5][0-9])([Z]?)$/',$dt,$matches); - - if (!$result) { - throw new Sabre_DAV_Exception_BadRequest('The supplied iCalendar datetime value is incorrect: ' . $dt); - } - - if ($matches[7]==='Z' || is_null($tz)) { - $tz = new DateTimeZone('UTC'); - } - $date = new DateTime($matches[1] . '-' . $matches[2] . '-' . $matches[3] . ' ' . $matches[4] . ':' . $matches[5] .':' . $matches[6], $tz); - - // Still resetting the timezone, to normalize everything to UTC - $date->setTimeZone(new DateTimeZone('UTC')); - return $date; - - } - - /** - * Parses an iCalendar (rfc5545) formatted datetime and returns a DateTime object - * - * @param string $date - * @param DateTimeZone $tz - * @return DateTime - */ - static public function parseICalendarDate($date) { - - // Format is YYYYMMDD - $result = preg_match('/^([1-3][0-9]{3})([0-1][0-9])([0-3][0-9])$/',$date,$matches); - - if (!$result) { - throw new Sabre_DAV_Exception_BadRequest('The supplied iCalendar date value is incorrect: ' . $date); - } - - $date = new DateTime($matches[1] . '-' . $matches[2] . '-' . $matches[3], new DateTimeZone('UTC')); - return $date; - - } - - /** - * Parses an iCalendar (RFC5545) formatted duration and returns a string suitable - * for strtotime or DateTime::modify. - * - * NOTE: When we require PHP 5.3 this can be replaced by the DateTimeInterval object, which - * supports ISO 8601 Intervals, which is a superset of ICalendar durations. - * - * For now though, we're just gonna live with this messy system - * - * @param string $duration - * @return string - */ - static public function parseICalendarDuration($duration) { - - $result = preg_match('/^(?P<plusminus>\+|-)?P((?P<week>\d+)W)?((?P<day>\d+)D)?(T((?P<hour>\d+)H)?((?P<minute>\d+)M)?((?P<second>\d+)S)?)?$/', $duration, $matches); - if (!$result) { - throw new Sabre_DAV_Exception_BadRequest('The supplied iCalendar duration value is incorrect: ' . $duration); - } - - $parts = array( - 'week', - 'day', - 'hour', - 'minute', - 'second', - ); - - $newDur = ''; - foreach($parts as $part) { - if (isset($matches[$part]) && $matches[$part]) { - $newDur.=' '.$matches[$part] . ' ' . $part . 's'; - } - } - - $newDur = ($matches['plusminus']==='-'?'-':'+') . trim($newDur); - return $newDur; - - } - -} diff --git a/3rdparty/Sabre/CalDAV/includes.php b/3rdparty/Sabre/CalDAV/includes.php new file mode 100755 index 00000000000..1ecb870a0e1 --- /dev/null +++ b/3rdparty/Sabre/CalDAV/includes.php @@ -0,0 +1,43 @@ +<?php + +/** + * Sabre_CalDAV includes file + * + * Including this file will automatically include all files from the + * Sabre_CalDAV package. + * + * This often allows faster loadtimes, as autoload-speed is often quite slow. + * + * @package Sabre + * @subpackage CalDAV + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. + * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License + */ + +// Begin includes +include __DIR__ . '/Backend/Abstract.php'; +include __DIR__ . '/Backend/PDO.php'; +include __DIR__ . '/CalendarQueryParser.php'; +include __DIR__ . '/CalendarQueryValidator.php'; +include __DIR__ . '/CalendarRootNode.php'; +include __DIR__ . '/ICalendar.php'; +include __DIR__ . '/ICalendarObject.php'; +include __DIR__ . '/ICSExportPlugin.php'; +include __DIR__ . '/Plugin.php'; +include __DIR__ . '/Principal/Collection.php'; +include __DIR__ . '/Principal/ProxyRead.php'; +include __DIR__ . '/Principal/ProxyWrite.php'; +include __DIR__ . '/Principal/User.php'; +include __DIR__ . '/Property/SupportedCalendarComponentSet.php'; +include __DIR__ . '/Property/SupportedCalendarData.php'; +include __DIR__ . '/Property/SupportedCollationSet.php'; +include __DIR__ . '/Schedule/IMip.php'; +include __DIR__ . '/Schedule/IOutbox.php'; +include __DIR__ . '/Schedule/Outbox.php'; +include __DIR__ . '/Server.php'; +include __DIR__ . '/UserCalendars.php'; +include __DIR__ . '/Version.php'; +include __DIR__ . '/Calendar.php'; +include __DIR__ . '/CalendarObject.php'; +// End includes diff --git a/3rdparty/Sabre/CardDAV/AddressBook.php b/3rdparty/Sabre/CardDAV/AddressBook.php index 471ca7b338a..3b381e1eea3 100644..100755 --- a/3rdparty/Sabre/CardDAV/AddressBook.php +++ b/3rdparty/Sabre/CardDAV/AddressBook.php @@ -7,34 +7,33 @@ * * @package Sabre * @subpackage CardDAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_CardDAV_IAddressBook, Sabre_DAV_IProperties, Sabre_DAVACL_IACL { /** - * This is an array with addressbook information - * - * @var array + * This is an array with addressbook information + * + * @var array */ private $addressBookInfo; /** - * CardDAV backend - * - * @var Sabre_CardDAV_Backend_Abstract + * CardDAV backend + * + * @var Sabre_CardDAV_Backend_Abstract */ private $carddavBackend; /** - * Constructor - * - * @param Sabre_CardDAV_Backend_Abstract $carddavBackend - * @param array $addressBookInfo - * @return void + * Constructor + * + * @param Sabre_CardDAV_Backend_Abstract $carddavBackend + * @param array $addressBookInfo */ - public function __construct(Sabre_CardDAV_Backend_Abstract $carddavBackend,array $addressBookInfo) { + public function __construct(Sabre_CardDAV_Backend_Abstract $carddavBackend, array $addressBookInfo) { $this->carddavBackend = $carddavBackend; $this->addressBookInfo = $addressBookInfo; @@ -42,9 +41,9 @@ class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_Ca } /** - * Returns the name of the addressbook - * - * @return string + * Returns the name of the addressbook + * + * @return string */ public function getName() { @@ -55,21 +54,21 @@ class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_Ca /** * Returns a card * - * @param string $name + * @param string $name * @return Sabre_DAV_Card */ public function getChild($name) { $obj = $this->carddavBackend->getCard($this->addressBookInfo['id'],$name); - if (!$obj) throw new Sabre_DAV_Exception_FileNotFound('Card not found'); + if (!$obj) throw new Sabre_DAV_Exception_NotFound('Card not found'); return new Sabre_CardDAV_Card($this->carddavBackend,$this->addressBookInfo,$obj); } /** * Returns the full list of cards - * - * @return array + * + * @return array */ public function getChildren() { @@ -85,9 +84,9 @@ class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_Ca /** * Creates a new directory * - * We actually block this, as subdirectories are not allowed in addressbooks. - * - * @param string $name + * We actually block this, as subdirectories are not allowed in addressbooks. + * + * @param string $name * @return void */ public function createDirectory($name) { @@ -99,11 +98,13 @@ class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_Ca /** * Creates a new file * - * The contents of the new file must be a valid VCARD - * - * @param string $name - * @param resource $vcardData - * @return void + * The contents of the new file must be a valid VCARD. + * + * This method may return an ETag. + * + * @param string $name + * @param resource $vcardData + * @return void|null */ public function createFile($name,$vcardData = null) { @@ -111,13 +112,13 @@ class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_Ca // Converting to UTF-8, if needed $vcardData = Sabre_DAV_StringUtil::ensureUTF8($vcardData); - $this->carddavBackend->createCard($this->addressBookInfo['id'],$name,$vcardData); + return $this->carddavBackend->createCard($this->addressBookInfo['id'],$name,$vcardData); } /** - * Deletes the entire addressbook. - * + * Deletes the entire addressbook. + * * @return void */ public function delete() { @@ -128,8 +129,8 @@ class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_Ca /** * Renames the addressbook - * - * @param string $newName + * + * @param string $newName * @return void */ public function setName($newName) { @@ -140,7 +141,7 @@ class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_Ca /** * Returns the last modification date as a unix timestamp. - * + * * @return void */ public function getLastModified() { @@ -162,7 +163,7 @@ class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_Ca * If the operation was successful, true can be returned. * If the operation failed, false can be returned. * - * Deletion of a non-existant property is always succesful. + * Deletion of a non-existent property is always successful. * * Lastly, it is optional to return detailed information about any * failures. In this case an array should be returned with the following @@ -177,16 +178,16 @@ class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_Ca * ) * ) * - * In this example it was forbidden to update {DAV:}displayname. + * In this example it was forbidden to update {DAV:}displayname. * (403 Forbidden), which in turn also caused {DAV:}owner to fail * (424 Failed Dependency) because the request needs to be atomic. * - * @param array $mutations - * @return bool|array + * @param array $mutations + * @return bool|array */ public function updateProperties($mutations) { - return $this->carddavBackend->updateAddressBook($this->addressBookInfo['id'], $mutations); + return $this->carddavBackend->updateAddressBook($this->addressBookInfo['id'], $mutations); } @@ -198,8 +199,8 @@ class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_Ca * * If the array is empty, it means 'all properties' were requested. * - * @param array $properties - * @return void + * @param array $properties + * @return array */ public function getProperties($properties) { @@ -221,8 +222,8 @@ class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_Ca /** * Returns the owner principal * - * This must be a url to a principal, or null if there's no owner - * + * This must be a url to a principal, or null if there's no owner + * * @return string|null */ public function getOwner() { @@ -235,8 +236,8 @@ class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_Ca * Returns a group principal * * This must be a url to a principal, or null if there's no owner - * - * @return string|null + * + * @return string|null */ public function getGroup() { @@ -248,13 +249,13 @@ class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_Ca * 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 + * * '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 + * * 'protected' (optional), indicating that this ACE is not allowed to + * be updated. + * + * @return array */ public function getACL() { @@ -277,9 +278,9 @@ class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_Ca /** * Updates the ACL * - * This method will receive a list of new ACE's. - * - * @param array $acl + * This method will receive a list of new ACE's. + * + * @param array $acl * @return void */ public function setACL(array $acl) { @@ -288,6 +289,22 @@ class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_Ca } + /** + * Returns the list of supported privileges for this node. + * + * The returned data structure is a list of nested privileges. + * See Sabre_DAVACL_Plugin::getDefaultSupportedPrivilegeSet for a simple + * standard structure. + * + * If null is returned from this method, the default privilege set is used, + * which is fine for most common usecases. + * + * @return array|null + */ + public function getSupportedPrivilegeSet() { + + return null; + } } diff --git a/3rdparty/Sabre/CardDAV/AddressBookQueryParser.php b/3rdparty/Sabre/CardDAV/AddressBookQueryParser.php index 08adc3b8157..85a4963127b 100644..100755 --- a/3rdparty/Sabre/CardDAV/AddressBookQueryParser.php +++ b/3rdparty/Sabre/CardDAV/AddressBookQueryParser.php @@ -3,12 +3,12 @@ /** * Parses the addressbook-query report request body. * - * Whoever designed this format, and the CalDAV equavalent even more so, + * Whoever designed this format, and the CalDAV equivalent even more so, * has no feel for design. - * + * * @package Sabre * @subpackage CardDAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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,8 +19,8 @@ class Sabre_CardDAV_AddressBookQueryParser { /** * List of requested properties the client wanted - * - * @var array + * + * @var array */ public $requestedProperties; @@ -28,44 +28,43 @@ class Sabre_CardDAV_AddressBookQueryParser { * The number of results the client wants * * null means it wasn't specified, which in most cases means 'all results'. - * - * @var int|null + * + * @var int|null */ public $limit; /** * List of property filters. * - * @var array + * @var array */ public $filters; /** * Either TEST_ANYOF or TEST_ALLOF - * - * @var string + * + * @var string */ public $test; /** * DOM Document - * - * @var DOMDocument + * + * @var DOMDocument */ protected $dom; /** - * DOM XPath object - * - * @var DOMXPath + * DOM XPath object + * + * @var DOMXPath */ protected $xpath; /** * Creates the parser - * - * @param DOMNode $dom - * @return void + * + * @param DOMDocument $dom */ public function __construct(DOMDocument $dom) { @@ -77,15 +76,14 @@ class Sabre_CardDAV_AddressBookQueryParser { } /** - * Parses the request. - * - * @param DOMNode $dom + * Parses the request. + * * @return void */ public function parse() { $filterNode = null; - + $limit = $this->xpath->evaluate('number(/card:addressbook-query/card:limit/card:nresults)'); if (is_nan($limit)) $limit = null; @@ -120,9 +118,9 @@ class Sabre_CardDAV_AddressBookQueryParser { /** * Parses the prop-filter xml element - * - * @param DOMElement $propFilterNode - * @return array + * + * @param DOMElement $propFilterNode + * @return array */ protected function parsePropFilterNode(DOMElement $propFilterNode) { @@ -157,13 +155,13 @@ class Sabre_CardDAV_AddressBookQueryParser { } /** - * Parses the param-filter element - * - * @param DOMElement $paramFilterNode - * @return array + * Parses the param-filter element + * + * @param DOMElement $paramFilterNode + * @return array */ public function parseParamFilterNode(DOMElement $paramFilterNode) { - + $paramFilter = array(); $paramFilter['name'] = $paramFilterNode->getAttribute('name'); $paramFilter['is-not-defined'] = $this->xpath->query('card:is-not-defined', $paramFilterNode)->length>0; @@ -174,15 +172,15 @@ class Sabre_CardDAV_AddressBookQueryParser { $paramFilter['text-match'] = $this->parseTextMatchNode($textMatch->item(0)); } - return $paramFilter; + return $paramFilter; } /** * Text match - * - * @param DOMElement $textMatchNode - * @return void + * + * @param DOMElement $textMatchNode + * @return array */ public function parseTextMatchNode(DOMElement $textMatchNode) { @@ -204,8 +202,8 @@ class Sabre_CardDAV_AddressBookQueryParser { 'match-type' => $matchType, 'value' => $textMatchNode->nodeValue ); - - } + + } } diff --git a/3rdparty/Sabre/CardDAV/AddressBookRoot.php b/3rdparty/Sabre/CardDAV/AddressBookRoot.php index 1a80efba35e..9d37b15f08e 100644..100755 --- a/3rdparty/Sabre/CardDAV/AddressBookRoot.php +++ b/3rdparty/Sabre/CardDAV/AddressBookRoot.php @@ -1,45 +1,45 @@ <?php /** - * AddressBook rootnode + * AddressBook rootnode * * This object lists a collection of users, which can contain addressbooks. * * @package Sabre * @subpackage CardDAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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_CardDAV_AddressBookRoot extends Sabre_DAVACL_AbstractPrincipalCollection { /** - * Principal Backend - * + * Principal Backend + * * @var Sabre_DAVACL_IPrincipalBackend */ protected $principalBackend; /** - * CardDAV backend - * - * @var Sabre_CardDAV_Backend_Abstract + * CardDAV backend + * + * @var Sabre_CardDAV_Backend_Abstract */ protected $carddavBackend; /** - * Constructor + * Constructor * * This constructor needs both a principal and a carddav backend. * - * By default this class will show a list of addressbook collections for - * principals in the 'principals' collection. If your main principals are - * actually located in a different path, use the $principalPrefix argument + * By default this class will show a list of addressbook collections for + * principals in the 'principals' collection. If your main principals are + * actually located in a different path, use the $principalPrefix argument * to override this. * - * @param Sabre_DAVACL_IPrincipalBackend $principalBackend + * @param Sabre_DAVACL_IPrincipalBackend $principalBackend * @param Sabre_CardDAV_Backend_Abstract $carddavBackend - * @param string $principalPrefix + * @param string $principalPrefix */ public function __construct(Sabre_DAVACL_IPrincipalBackend $principalBackend,Sabre_CardDAV_Backend_Abstract $carddavBackend, $principalPrefix = 'principals') { @@ -49,9 +49,9 @@ class Sabre_CardDAV_AddressBookRoot extends Sabre_DAVACL_AbstractPrincipalCollec } /** - * Returns the name of the node - * - * @return string + * Returns the name of the node + * + * @return string */ public function getName() { @@ -65,9 +65,9 @@ class Sabre_CardDAV_AddressBookRoot extends Sabre_DAVACL_AbstractPrincipalCollec * 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 + * + * @param array $principal + * @return Sabre_DAV_INode */ public function getChildForPrincipal(array $principal) { diff --git a/3rdparty/Sabre/CardDAV/Backend/Abstract.php b/3rdparty/Sabre/CardDAV/Backend/Abstract.php index 1f0253ddab8..e4806b7161f 100644..100755 --- a/3rdparty/Sabre/CardDAV/Backend/Abstract.php +++ b/3rdparty/Sabre/CardDAV/Backend/Abstract.php @@ -5,14 +5,14 @@ * * This class serves as a base-class for addressbook backends * - * Note that there are references to 'addressBookId' scattered throughout the - * class. The value of the addressBookId is completely up to you, it can be any + * Note that there are references to 'addressBookId' scattered throughout the + * class. The value of the addressBookId is completely up to you, it can be any * arbitrary value you can use as an unique identifier. - * + * * @package Sabre * @subpackage CardDAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_CardDAV_Backend_Abstract { @@ -25,97 +25,142 @@ abstract class Sabre_CardDAV_Backend_Abstract { * uri - the 'basename' part of the url * principaluri - Same as the passed parameter * - * Any additional clark-notation property may be passed besides this. Some + * Any additional clark-notation property may be passed besides this. Some * common ones are : * {DAV:}displayname * {urn:ietf:params:xml:ns:carddav}addressbook-description * {http://calendarserver.org/ns/}getctag - * - * @param string $principalUri - * @return array + * + * @param string $principalUri + * @return array */ - public abstract function getAddressBooksForUser($principalUri); + public abstract function getAddressBooksForUser($principalUri); /** * Updates an addressbook's properties * - * See Sabre_DAV_IProperties for a description of the mutations array, as - * well as the return value. + * See Sabre_DAV_IProperties for a description of the mutations array, as + * well as the return value. * * @param mixed $addressBookId * @param array $mutations * @see Sabre_DAV_IProperties::updateProperties * @return bool|array */ - public abstract function updateAddressBook($addressBookId, array $mutations); + public abstract function updateAddressBook($addressBookId, array $mutations); /** - * Creates a new address book + * Creates a new address book * - * @param string $principalUri - * @param string $url Just the 'basename' of the url. - * @param array $properties + * @param string $principalUri + * @param string $url Just the 'basename' of the url. + * @param array $properties * @return void */ - abstract public function createAddressBook($principalUri, $url, array $properties); + abstract public function createAddressBook($principalUri, $url, array $properties); /** * Deletes an entire addressbook and all its contents * - * @param mixed $addressBookId + * @param mixed $addressBookId * @return void */ - abstract public function deleteAddressBook($addressBookId); + abstract public function deleteAddressBook($addressBookId); /** - * Returns all cards for a specific addressbook id. + * Returns all cards for a specific addressbook id. * * This method should return the following properties for each card: * * carddata - raw vcard data * * uri - Some unique url * * lastmodified - A unix timestamp - - * @param mixed $addressbookId - * @return array + * + * It's recommended to also return the following properties: + * * etag - A unique etag. This must change every time the card changes. + * * size - The size of the card in bytes. + * + * If these last two properties are provided, less time will be spent + * calculating them. If they are specified, you can also ommit carddata. + * This may speed up certain requests, especially with large cards. + * + * @param mixed $addressbookId + * @return array */ - public abstract function getCards($addressbookId); + public abstract function getCards($addressbookId); /** - * Returns a specfic card - * - * @param mixed $addressBookId - * @param string $cardUri - * @return void + * Returns a specfic card. + * + * The same set of properties must be returned as with getCards. The only + * exception is that 'carddata' is absolutely required. + * + * @param mixed $addressBookId + * @param string $cardUri + * @return array */ - public abstract function getCard($addressBookId, $cardUri); + public abstract function getCard($addressBookId, $cardUri); /** - * Creates a new card - * - * @param mixed $addressBookId - * @param string $cardUri - * @param string $cardData - * @return bool + * Creates a new card. + * + * The addressbook id will be passed as the first argument. This is the + * same id as it is returned from the getAddressbooksForUser method. + * + * The cardUri is a base uri, and doesn't include the full path. The + * cardData argument is the vcard body, and is passed as a string. + * + * It is possible to return an ETag from this method. This ETag is for the + * newly created resource, and must be enclosed with double quotes (that + * is, the string itself must contain the double quotes). + * + * You should only return the ETag if you store the carddata as-is. If a + * subsequent GET request on the same card does not have the same body, + * byte-by-byte and you did return an ETag here, clients tend to get + * confused. + * + * If you don't return an ETag, you can just return null. + * + * @param mixed $addressBookId + * @param string $cardUri + * @param string $cardData + * @return string|null */ - abstract public function createCard($addressBookId, $cardUri, $cardData); + abstract public function createCard($addressBookId, $cardUri, $cardData); /** - * Updates a card - * - * @param mixed $addressBookId - * @param string $cardUri - * @param string $cardData - * @return bool + * Updates a card. + * + * The addressbook id will be passed as the first argument. This is the + * same id as it is returned from the getAddressbooksForUser method. + * + * The cardUri is a base uri, and doesn't include the full path. The + * cardData argument is the vcard body, and is passed as a string. + * + * It is possible to return an ETag from this method. This ETag should + * match that of the updated resource, and must be enclosed with double + * quotes (that is: the string itself must contain the actual quotes). + * + * You should only return the ETag if you store the carddata as-is. If a + * subsequent GET request on the same card does not have the same body, + * byte-by-byte and you did return an ETag here, clients tend to get + * confused. + * + * If you don't return an ETag, you can just return null. + * + * @param mixed $addressBookId + * @param string $cardUri + * @param string $cardData + * @return string|null */ - abstract public function updateCard($addressBookId, $cardUri, $cardData); + abstract public function updateCard($addressBookId, $cardUri, $cardData); /** * Deletes a card - * - * @param mixed $addressBookId - * @param string $cardUri - * @return bool + * + * @param mixed $addressBookId + * @param string $cardUri + * @return bool */ - abstract public function deleteCard($addressBookId, $cardUri); + abstract public function deleteCard($addressBookId, $cardUri); } diff --git a/3rdparty/Sabre/CardDAV/Backend/PDO.php b/3rdparty/Sabre/CardDAV/Backend/PDO.php index f4e44610ccf..413a77f3bcc 100644..100755 --- a/3rdparty/Sabre/CardDAV/Backend/PDO.php +++ b/3rdparty/Sabre/CardDAV/Backend/PDO.php @@ -4,19 +4,19 @@ * PDO CardDAV backend * * This CardDAV backend uses PDO to store addressbooks - * + * * @package Sabre * @subpackage CardDAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_CardDAV_Backend_PDO extends Sabre_CardDAV_Backend_Abstract { /** - * PDO connection - * - * @var PDO + * PDO connection + * + * @var PDO */ protected $pdo; @@ -31,28 +31,30 @@ class Sabre_CardDAV_Backend_PDO extends Sabre_CardDAV_Backend_Abstract { protected $cardsTableName; /** - * Sets up the object - * - * @param PDO $pdo + * Sets up the object + * + * @param PDO $pdo + * @param string $addressBooksTableName + * @param string $cardsTableName */ public function __construct(PDO $pdo, $addressBooksTableName = 'addressbooks', $cardsTableName = 'cards') { $this->pdo = $pdo; $this->addressBooksTableName = $addressBooksTableName; - $this->cardsTableName = $cardsTableName; + $this->cardsTableName = $cardsTableName; } /** - * Returns the list of addressbooks for a specific user. - * - * @param string $principalUri - * @return array + * Returns the list of addressbooks for a specific user. + * + * @param string $principalUri + * @return array */ public function getAddressBooksForUser($principalUri) { - $stmt = $this->pdo->prepare('SELECT id, uri, displayname, principaluri, description, ctag FROM `'.$this->addressBooksTableName.'` WHERE principaluri = ?'); - $result = $stmt->execute(array($principalUri)); + $stmt = $this->pdo->prepare('SELECT id, uri, displayname, principaluri, description, ctag FROM '.$this->addressBooksTableName.' WHERE principaluri = ?'); + $stmt->execute(array($principalUri)); $addressBooks = array(); @@ -65,7 +67,7 @@ class Sabre_CardDAV_Backend_PDO extends Sabre_CardDAV_Backend_Abstract { '{DAV:}displayname' => $row['displayname'], '{' . Sabre_CardDAV_Plugin::NS_CARDDAV . '}addressbook-description' => $row['description'], '{http://calendarserver.org/ns/}getctag' => $row['ctag'], - '{' . Sabre_CardDAV_Plugin::NS_CARDDAV . '}supported-address-data' => + '{' . Sabre_CardDAV_Plugin::NS_CARDDAV . '}supported-address-data' => new Sabre_CardDAV_Property_SupportedAddressData(), ); @@ -79,8 +81,8 @@ class Sabre_CardDAV_Backend_PDO extends Sabre_CardDAV_Backend_Abstract { /** * Updates an addressbook's properties * - * See Sabre_DAV_IProperties for a description of the mutations array, as - * well as the return value. + * See Sabre_DAV_IProperties for a description of the mutations array, as + * well as the return value. * * @param mixed $addressBookId * @param array $mutations @@ -88,7 +90,7 @@ class Sabre_CardDAV_Backend_PDO extends Sabre_CardDAV_Backend_Abstract { * @return bool|array */ public function updateAddressBook($addressBookId, array $mutations) { - + $updates = array(); foreach($mutations as $property=>$newValue) { @@ -101,7 +103,7 @@ class Sabre_CardDAV_Backend_PDO extends Sabre_CardDAV_Backend_Abstract { $updates['description'] = $newValue; break; default : - // If any unsupported values were being updated, we must + // If any unsupported values were being updated, we must // let the entire request fail. return false; } @@ -113,7 +115,7 @@ class Sabre_CardDAV_Backend_PDO extends Sabre_CardDAV_Backend_Abstract { return false; } - $query = 'UPDATE `' . $this->addressBooksTableName . '` SET ctag = ctag + 1 '; + $query = 'UPDATE ' . $this->addressBooksTableName . ' SET ctag = ctag + 1 '; foreach($updates as $key=>$value) { $query.=', `' . $key . '` = :' . $key . ' '; } @@ -129,11 +131,11 @@ class Sabre_CardDAV_Backend_PDO extends Sabre_CardDAV_Backend_Abstract { } /** - * Creates a new address book + * Creates a new address book * - * @param string $principalUri - * @param string $url Just the 'basename' of the url. - * @param array $properties + * @param string $principalUri + * @param string $url Just the 'basename' of the url. + * @param array $properties * @return void */ public function createAddressBook($principalUri, $url, array $properties) { @@ -160,7 +162,7 @@ class Sabre_CardDAV_Backend_PDO extends Sabre_CardDAV_Backend_Abstract { } - $query = 'INSERT INTO `' . $this->addressBooksTableName . '` (uri, displayname, description, principaluri, ctag) VALUES (:uri, :displayname, :description, :principaluri, 1)'; + $query = 'INSERT INTO ' . $this->addressBooksTableName . ' (uri, displayname, description, principaluri, ctag) VALUES (:uri, :displayname, :description, :principaluri, 1)'; $stmt = $this->pdo->prepare($query); $stmt->execute($values); @@ -169,44 +171,61 @@ class Sabre_CardDAV_Backend_PDO extends Sabre_CardDAV_Backend_Abstract { /** * Deletes an entire addressbook and all its contents * - * @param int $addressBookId + * @param int $addressBookId * @return void */ public function deleteAddressBook($addressBookId) { - $stmt = $this->pdo->prepare('DELETE FROM `' . $this->cardsTableName . '` WHERE addressbookid = ?'); + $stmt = $this->pdo->prepare('DELETE FROM ' . $this->cardsTableName . ' WHERE addressbookid = ?'); $stmt->execute(array($addressBookId)); - $stmt = $this->pdo->prepare('DELETE FROM `' . $this->addressBooksTableName . '` WHERE id = ?'); + $stmt = $this->pdo->prepare('DELETE FROM ' . $this->addressBooksTableName . ' WHERE id = ?'); $stmt->execute(array($addressBookId)); } /** - * Returns all cards for a specific addressbook id. - * - * @param mixed $addressbookId - * @return array + * Returns all cards for a specific addressbook id. + * + * This method should return the following properties for each card: + * * carddata - raw vcard data + * * uri - Some unique url + * * lastmodified - A unix timestamp + * + * It's recommended to also return the following properties: + * * etag - A unique etag. This must change every time the card changes. + * * size - The size of the card in bytes. + * + * If these last two properties are provided, less time will be spent + * calculating them. If they are specified, you can also ommit carddata. + * This may speed up certain requests, especially with large cards. + * + * @param mixed $addressbookId + * @return array */ public function getCards($addressbookId) { - $stmt = $this->pdo->prepare('SELECT id, carddata, uri, lastmodified FROM `' . $this->cardsTableName . '` WHERE addressbookid = ?'); + $stmt = $this->pdo->prepare('SELECT id, carddata, uri, lastmodified FROM ' . $this->cardsTableName . ' WHERE addressbookid = ?'); $stmt->execute(array($addressbookId)); return $stmt->fetchAll(PDO::FETCH_ASSOC); - + } + /** - * Returns a specfic card - * - * @param mixed $addressBookId - * @param string $cardUri - * @return array + * Returns a specfic card. + * + * The same set of properties must be returned as with getCards. The only + * exception is that 'carddata' is absolutely required. + * + * @param mixed $addressBookId + * @param string $cardUri + * @return array */ public function getCard($addressBookId, $cardUri) { - $stmt = $this->pdo->prepare('SELECT id, carddata, uri, lastmodified FROM `' . $this->cardsTableName . '` WHERE addressbookid = ? AND uri = ? LIMIT 1'); + $stmt = $this->pdo->prepare('SELECT id, carddata, uri, lastmodified FROM ' . $this->cardsTableName . ' WHERE addressbookid = ? AND uri = ? LIMIT 1'); $stmt->execute(array($addressBookId, $cardUri)); $result = $stmt->fetchAll(PDO::FETCH_ASSOC); @@ -216,59 +235,93 @@ class Sabre_CardDAV_Backend_PDO extends Sabre_CardDAV_Backend_Abstract { } /** - * Creates a new card - * - * @param mixed $addressBookId - * @param string $cardUri - * @param string $cardData - * @return bool + * Creates a new card. + * + * The addressbook id will be passed as the first argument. This is the + * same id as it is returned from the getAddressbooksForUser method. + * + * The cardUri is a base uri, and doesn't include the full path. The + * cardData argument is the vcard body, and is passed as a string. + * + * It is possible to return an ETag from this method. This ETag is for the + * newly created resource, and must be enclosed with double quotes (that + * is, the string itself must contain the double quotes). + * + * You should only return the ETag if you store the carddata as-is. If a + * subsequent GET request on the same card does not have the same body, + * byte-by-byte and you did return an ETag here, clients tend to get + * confused. + * + * If you don't return an ETag, you can just return null. + * + * @param mixed $addressBookId + * @param string $cardUri + * @param string $cardData + * @return string|null */ public function createCard($addressBookId, $cardUri, $cardData) { - $stmt = $this->pdo->prepare('INSERT INTO `' . $this->cardsTableName . '` (carddata, uri, lastmodified, addressbookid) VALUES (?, ?, ?, ?)'); + $stmt = $this->pdo->prepare('INSERT INTO ' . $this->cardsTableName . ' (carddata, uri, lastmodified, addressbookid) VALUES (?, ?, ?, ?)'); $result = $stmt->execute(array($cardData, $cardUri, time(), $addressBookId)); - $stmt2 = $this->pdo->prepare('UPDATE `' . $this->addressBooksTableName . '` SET ctag = ctag + 1 WHERE id = ?'); + $stmt2 = $this->pdo->prepare('UPDATE ' . $this->addressBooksTableName . ' SET ctag = ctag + 1 WHERE id = ?'); $stmt2->execute(array($addressBookId)); - return $result; + return '"' . md5($cardData) . '"'; } /** - * Updates a card - * - * @param mixed $addressBookId - * @param string $cardUri - * @param string $cardData - * @return bool + * Updates a card. + * + * The addressbook id will be passed as the first argument. This is the + * same id as it is returned from the getAddressbooksForUser method. + * + * The cardUri is a base uri, and doesn't include the full path. The + * cardData argument is the vcard body, and is passed as a string. + * + * It is possible to return an ETag from this method. This ETag should + * match that of the updated resource, and must be enclosed with double + * quotes (that is: the string itself must contain the actual quotes). + * + * You should only return the ETag if you store the carddata as-is. If a + * subsequent GET request on the same card does not have the same body, + * byte-by-byte and you did return an ETag here, clients tend to get + * confused. + * + * If you don't return an ETag, you can just return null. + * + * @param mixed $addressBookId + * @param string $cardUri + * @param string $cardData + * @return string|null */ public function updateCard($addressBookId, $cardUri, $cardData) { - $stmt = $this->pdo->prepare('UPDATE `' . $this->cardsTableName . '` SET carddata = ?, lastmodified = ? WHERE uri = ? AND addressbookid =?'); - $result = $stmt->execute(array($cardData, time(), $cardUri, $addressBookId)); + $stmt = $this->pdo->prepare('UPDATE ' . $this->cardsTableName . ' SET carddata = ?, lastmodified = ? WHERE uri = ? AND addressbookid =?'); + $stmt->execute(array($cardData, time(), $cardUri, $addressBookId)); - $stmt2 = $this->pdo->prepare('UPDATE `' . $this->addressBooksTableName . '` SET ctag = ctag + 1 WHERE id = ?'); + $stmt2 = $this->pdo->prepare('UPDATE ' . $this->addressBooksTableName . ' SET ctag = ctag + 1 WHERE id = ?'); $stmt2->execute(array($addressBookId)); - return $stmt->rowCount()===1; + return '"' . md5($cardData) . '"'; } /** * Deletes a card - * - * @param mixed $addressBookId - * @param string $cardUri - * @return bool + * + * @param mixed $addressBookId + * @param string $cardUri + * @return bool */ public function deleteCard($addressBookId, $cardUri) { - $stmt = $this->pdo->prepare('DELETE FROM `' . $this->cardsTableName . '` WHERE addressbookid = ? AND uri = ?'); + $stmt = $this->pdo->prepare('DELETE FROM ' . $this->cardsTableName . ' WHERE addressbookid = ? AND uri = ?'); $stmt->execute(array($addressBookId, $cardUri)); - $stmt2 = $this->pdo->prepare('UPDATE `' . $this->addressBooksTableName . '` SET ctag = ctag + 1 WHERE id = ?'); + $stmt2 = $this->pdo->prepare('UPDATE ' . $this->addressBooksTableName . ' SET ctag = ctag + 1 WHERE id = ?'); $stmt2->execute(array($addressBookId)); return $stmt->rowCount()===1; diff --git a/3rdparty/Sabre/CardDAV/Card.php b/3rdparty/Sabre/CardDAV/Card.php index 2844eaf7ed6..d7c66333837 100644..100755 --- a/3rdparty/Sabre/CardDAV/Card.php +++ b/3rdparty/Sabre/CardDAV/Card.php @@ -2,10 +2,10 @@ /** * The Card object represents a single Card from an addressbook - * + * * @package Sabre * @subpackage CardDAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ @@ -13,29 +13,29 @@ class Sabre_CardDAV_Card extends Sabre_DAV_File implements Sabre_CardDAV_ICard, /** * CardDAV backend - * - * @var Sabre_CardDAV_Backend_Abstract + * + * @var Sabre_CardDAV_Backend_Abstract */ private $carddavBackend; /** * Array with information about this Card - * - * @var array + * + * @var array */ private $cardData; /** - * Array with information about the containing addressbook - * - * @var array + * Array with information about the containing addressbook + * + * @var array */ private $addressBookInfo; /** - * Constructor - * - * @param Sabre_CardDAV_Backend_Abstract $carddavBackend + * Constructor + * + * @param Sabre_CardDAV_Backend_Abstract $carddavBackend * @param array $addressBookInfo * @param array $cardData */ @@ -48,9 +48,9 @@ class Sabre_CardDAV_Card extends Sabre_DAV_File implements Sabre_CardDAV_ICard, } /** - * Returns the uri for this object - * - * @return string + * Returns the uri for this object + * + * @return string */ public function getName() { @@ -59,25 +59,26 @@ class Sabre_CardDAV_Card extends Sabre_DAV_File implements Sabre_CardDAV_ICard, } /** - * Returns the VCard-formatted object - * - * @return string + * Returns the VCard-formatted object + * + * @return string */ public function get() { - $cardData = $this->cardData['carddata']; - $s = fopen('php://temp','r+'); - fwrite($s, $cardData); - rewind($s); - return $s; + // Pre-populating 'carddata' is optional. If we don't yet have it + // already, we fetch it from the backend. + if (!isset($this->cardData['carddata'])) { + $this->cardData = $this->carddavBackend->getCard($this->addressBookInfo['id'], $this->cardData['uri']); + } + return $this->cardData['carddata']; } /** - * Updates the VCard-formatted object - * - * @param string $cardData - * @return void + * Updates the VCard-formatted object + * + * @param string $cardData + * @return void */ public function put($cardData) { @@ -87,14 +88,17 @@ class Sabre_CardDAV_Card extends Sabre_DAV_File implements Sabre_CardDAV_ICard, // Converting to UTF-8, if needed $cardData = Sabre_DAV_StringUtil::ensureUTF8($cardData); - $this->carddavBackend->updateCard($this->addressBookInfo['id'],$this->cardData['uri'],$cardData); + $etag = $this->carddavBackend->updateCard($this->addressBookInfo['id'],$this->cardData['uri'],$cardData); $this->cardData['carddata'] = $cardData; + $this->cardData['etag'] = $etag; + + return $etag; } /** * Deletes the card - * + * * @return void */ public function delete() { @@ -104,9 +108,9 @@ class Sabre_CardDAV_Card extends Sabre_DAV_File implements Sabre_CardDAV_ICard, } /** - * Returns the mime content-type - * - * @return string + * Returns the mime content-type + * + * @return string */ public function getContentType() { @@ -115,20 +119,24 @@ class Sabre_CardDAV_Card extends Sabre_DAV_File implements Sabre_CardDAV_ICard, } /** - * Returns an ETag for this object - * - * @return string + * Returns an ETag for this object + * + * @return string */ public function getETag() { - return '"' . md5($this->cardData['carddata']) . '"'; + if (isset($this->cardData['etag'])) { + return $this->cardData['etag']; + } else { + return '"' . md5($this->get()) . '"'; + } } /** * Returns the last modification date as a unix timestamp - * - * @return time + * + * @return time */ public function getLastModified() { @@ -137,21 +145,25 @@ class Sabre_CardDAV_Card extends Sabre_DAV_File implements Sabre_CardDAV_ICard, } /** - * Returns the size of this object in bytes - * + * Returns the size of this object in bytes + * * @return int */ public function getSize() { - return strlen($this->cardData['carddata']); + if (array_key_exists('size', $this->cardData)) { + return $this->cardData['size']; + } else { + return strlen($this->get()); + } } /** * Returns the owner principal * - * This must be a url to a principal, or null if there's no owner - * + * This must be a url to a principal, or null if there's no owner + * * @return string|null */ public function getOwner() { @@ -164,8 +176,8 @@ class Sabre_CardDAV_Card extends Sabre_DAV_File implements Sabre_CardDAV_ICard, * Returns a group principal * * This must be a url to a principal, or null if there's no owner - * - * @return string|null + * + * @return string|null */ public function getGroup() { @@ -177,13 +189,13 @@ class Sabre_CardDAV_Card extends Sabre_DAV_File implements Sabre_CardDAV_ICard, * 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 + * * '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 + * * 'protected' (optional), indicating that this ACE is not allowed to + * be updated. + * + * @return array */ public function getACL() { @@ -205,9 +217,9 @@ class Sabre_CardDAV_Card extends Sabre_DAV_File implements Sabre_CardDAV_ICard, /** * Updates the ACL * - * This method will receive a list of new ACE's. - * - * @param array $acl + * This method will receive a list of new ACE's. + * + * @param array $acl * @return void */ public function setACL(array $acl) { @@ -216,5 +228,23 @@ class Sabre_CardDAV_Card extends Sabre_DAV_File implements Sabre_CardDAV_ICard, } + /** + * Returns the list of supported privileges for this node. + * + * The returned data structure is a list of nested privileges. + * See Sabre_DAVACL_Plugin::getDefaultSupportedPrivilegeSet for a simple + * standard structure. + * + * If null is returned from this method, the default privilege set is used, + * which is fine for most common usecases. + * + * @return array|null + */ + public function getSupportedPrivilegeSet() { + + return null; + + } + } diff --git a/3rdparty/Sabre/CardDAV/IAddressBook.php b/3rdparty/Sabre/CardDAV/IAddressBook.php index a0dffb30aea..2bc275bcf74 100644..100755 --- a/3rdparty/Sabre/CardDAV/IAddressBook.php +++ b/3rdparty/Sabre/CardDAV/IAddressBook.php @@ -4,15 +4,15 @@ * AddressBook interface * * Implement this interface to allow a node to be recognized as an addressbook. - * + * * @package Sabre * @subpackage CardDAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ interface Sabre_CardDAV_IAddressBook extends Sabre_DAV_ICollection { - + } diff --git a/3rdparty/Sabre/CardDAV/ICard.php b/3rdparty/Sabre/CardDAV/ICard.php index 25bcc551b73..a17299316c1 100644..100755 --- a/3rdparty/Sabre/CardDAV/ICard.php +++ b/3rdparty/Sabre/CardDAV/ICard.php @@ -1,18 +1,18 @@ <?php /** - * Card interface + * Card interface + * + * Extend the ICard interface to allow your custom nodes to be picked up as + * 'Cards'. * - * Extend the ICard interface to allow your custom nodes to be picked up as - * 'Cards'. - * * @package Sabre * @subpackage CardDAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ -interface Sabre_CardDAV_ICard extends Sabre_DAV_IFile { +interface Sabre_CardDAV_ICard extends Sabre_DAV_IFile { } diff --git a/3rdparty/Sabre/CardDAV/IDirectory.php b/3rdparty/Sabre/CardDAV/IDirectory.php index e0d0797d285..22d4afeb24a 100644..100755 --- a/3rdparty/Sabre/CardDAV/IDirectory.php +++ b/3rdparty/Sabre/CardDAV/IDirectory.php @@ -3,7 +3,7 @@ /** * IDirectory interface * - * Implement this interface to have an addressbook marked as a 'directory'. A + * Implement this interface to have an addressbook marked as a 'directory'. A * directory is an (often) global addressbook. * * A full description can be found in the IETF draft: @@ -11,7 +11,7 @@ * * @package Sabre * @subpackage CardDAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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/3rdparty/Sabre/CardDAV/Plugin.php b/3rdparty/Sabre/CardDAV/Plugin.php index 14c9c72b0d5..9ebec243eb0 100644..100755 --- a/3rdparty/Sabre/CardDAV/Plugin.php +++ b/3rdparty/Sabre/CardDAV/Plugin.php @@ -7,8 +7,8 @@ * * @package Sabre * @subpackage CardDAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_CardDAV_Plugin extends Sabre_DAV_ServerPlugin { @@ -24,31 +24,34 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin { const NS_CARDDAV = 'urn:ietf:params:xml:ns:carddav'; /** - * Add urls to this property to have them automatically exposed as + * Add urls to this property to have them automatically exposed as * 'directories' to the user. - * + * * @var array */ public $directories = array(); /** - * Server class + * Server class * - * @var Sabre_DAV_Server + * @var Sabre_DAV_Server */ protected $server; /** - * Initializes the plugin + * Initializes the plugin * - * @param Sabre_DAV_Server $server - * @return void + * @param Sabre_DAV_Server $server + * @return void */ public function initialize(Sabre_DAV_Server $server) { /* Events */ $server->subscribeEvent('beforeGetProperties', array($this, 'beforeGetProperties')); + $server->subscribeEvent('updateProperties', array($this, 'updateProperties')); $server->subscribeEvent('report', array($this,'report')); + $server->subscribeEvent('onHTMLActionsPanel', array($this,'htmlActionsPanel')); + $server->subscribeEvent('onBrowserPostAction', array($this,'browserPostAction')); /* Namespaces */ $server->xmlNamespaces[self::NS_CARDDAV] = 'card'; @@ -56,11 +59,14 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin { /* Mapping Interfaces to {DAV:}resourcetype values */ $server->resourceTypeMapping['Sabre_CardDAV_IAddressBook'] = '{' . self::NS_CARDDAV . '}addressbook'; $server->resourceTypeMapping['Sabre_CardDAV_IDirectory'] = '{' . self::NS_CARDDAV . '}directory'; - + /* Adding properties that may never be changed */ $server->protectedProperties[] = '{' . self::NS_CARDDAV . '}supported-address-data'; $server->protectedProperties[] = '{' . self::NS_CARDDAV . '}max-resource-size'; + $server->protectedProperties[] = '{' . self::NS_CARDDAV . '}addressbook-home-set'; + $server->protectedProperties[] = '{' . self::NS_CARDDAV . '}supported-collation-set'; + $server->propertyMap['{http://calendarserver.org/ns/}me-card'] = 'Sabre_DAV_Property_Href'; $this->server = $server; @@ -69,7 +75,7 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin { /** * Returns a list of supported features. * - * This is used in the DAV: header in the OPTIONS and PROPFIND requests. + * This is used in the DAV: header in the OPTIONS and PROPFIND requests. * * @return array */ @@ -83,11 +89,11 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin { * 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 + * Note that you still need to subscribe to the 'report' event to actually + * implement them * * @param string $uri - * @return array + * @return array */ public function getSupportedReportSet($uri) { @@ -104,22 +110,22 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin { /** - * Adds all CardDAV-specific properties + * Adds all CardDAV-specific properties * * @param string $path - * @param Sabre_DAV_INode $node + * @param Sabre_DAV_INode $node * @param array $requestedProperties - * @param array $returnedProperties + * @param array $returnedProperties * @return void */ - public function beforeGetProperties($path, Sabre_DAV_INode $node, array &$requestedProperties, array &$returnedProperties) { + public function beforeGetProperties($path, Sabre_DAV_INode $node, array &$requestedProperties, array &$returnedProperties) { if ($node instanceof Sabre_DAVACL_IPrincipal) { // calendar-home-set property $addHome = '{' . self::NS_CARDDAV . '}addressbook-home-set'; if (in_array($addHome,$requestedProperties)) { - $principalId = $node->getName(); + $principalId = $node->getName(); $addressbookHomePath = self::ADDRESSBOOK_ROOT . '/' . $principalId . '/'; unset($requestedProperties[array_search($addHome, $requestedProperties)]); $returnedProperties[200][$addHome] = new Sabre_DAV_Property_Href($addressbookHomePath); @@ -135,8 +141,8 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin { if ($node instanceof Sabre_CardDAV_ICard) { - // The address-data property is not supposed to be a 'real' - // property, but in large chunks of the spec it does act as such. + // The address-data property is not supposed to be a 'real' + // property, but in large chunks of the spec it does act as such. // Therefore we simply expose it as a property. $addressDataProp = '{' . self::NS_CARDDAV . '}address-data'; if (in_array($addressDataProp, $requestedProperties)) { @@ -151,24 +157,95 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin { } } + if ($node instanceof Sabre_CardDAV_UserAddressBooks) { + + $meCardProp = '{http://calendarserver.org/ns/}me-card'; + if (in_array($meCardProp, $requestedProperties)) { + + $props = $this->server->getProperties($node->getOwner(), array('{http://sabredav.org/ns}vcard-url')); + if (isset($props['{http://sabredav.org/ns}vcard-url'])) { + + $returnedProperties[200][$meCardProp] = new Sabre_DAV_Property_Href( + $props['{http://sabredav.org/ns}vcard-url'] + ); + $pos = array_search($meCardProp, $requestedProperties); + unset($requestedProperties[$pos]); + + } + + } + + } + } /** - * This functions handles REPORT requests specific to CardDAV + * This event is triggered when a PROPPATCH method is executed * - * @param string $reportName + * @param array $mutations + * @param array $result + * @param Sabre_DAV_INode $node + * @return void + */ + public function updateProperties(&$mutations, &$result, $node) { + + if (!$node instanceof Sabre_CardDAV_UserAddressBooks) { + return true; + } + + $meCard = '{http://calendarserver.org/ns/}me-card'; + + // The only property we care about + if (!isset($mutations[$meCard])) + return true; + + $value = $mutations[$meCard]; + unset($mutations[$meCard]); + + if ($value instanceof Sabre_DAV_Property_IHref) { + $value = $value->getHref(); + $value = $this->server->calculateUri($value); + } elseif (!is_null($value)) { + $result[400][$meCard] = null; + return false; + } + + $innerResult = $this->server->updateProperties( + $node->getOwner(), + array( + '{http://sabredav.org/ns}vcard-url' => $value, + ) + ); + + $closureResult = false; + foreach($innerResult as $status => $props) { + if (is_array($props) && array_key_exists('{http://sabredav.org/ns}vcard-url', $props)) { + $result[$status][$meCard] = null; + $closureResult = ($status>=200 && $status<300); + } + + } + + return $result; + + } + + /** + * This functions handles REPORT requests specific to CardDAV + * + * @param string $reportName * @param DOMNode $dom - * @return bool + * @return bool */ public function report($reportName,$dom) { - switch($reportName) { + switch($reportName) { case '{'.self::NS_CARDDAV.'}addressbook-multiget' : $this->addressbookMultiGetReport($dom); return false; case '{'.self::NS_CARDDAV.'}addressbook-query' : $this->addressBookQueryReport($dom); - return false; + return false; default : return; @@ -256,7 +333,8 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin { $result = array(); foreach($validNodes as $validNode) { - if ($depth==0) { + + if ($depth==0) { $href = $this->server->getRequestUri(); } else { $href = $this->server->getRequestUri() . '/' . $validNode->getName(); @@ -265,7 +343,7 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin { list($result[]) = $this->server->getPropertiesForPath($href, $query->requestedProperties, 0); } - + $this->server->httpResponse->sendStatus(207); $this->server->httpResponse->setHeader('Content-Type','application/xml; charset=utf-8'); $this->server->httpResponse->sendBody($this->server->generateMultiStatus($result)); @@ -274,17 +352,15 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin { /** * Validates if a vcard makes it throught a list of filters. - * - * @param string $vcardData - * @param array $filters - * @param string $test anyof or allof (which means OR or AND) - * @return bool + * + * @param string $vcardData + * @param array $filters + * @param string $test anyof or allof (which means OR or AND) + * @return bool */ public function validateFilters($vcardData, array $filters, $test) { $vcard = Sabre_VObject_Reader::read($vcardData); - - $success = true; foreach($filters as $filter) { @@ -299,10 +375,10 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin { // We only need to check for existence $success = $isDefined; - + } else { - $vProperties = $vcard->select($filter['name']); + $vProperties = $vcard->select($filter['name']); $results = array(); if ($filter['param-filters']) { @@ -328,7 +404,7 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin { } // else - // There are two conditions where we can already determine wether + // There are two conditions where we can already determine whether // or not this filter succeeds. if ($test==='anyof' && $success) { return true; @@ -339,29 +415,28 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin { } // foreach - // If we got all the way here, it means we haven't been able to + // If we got all the way here, it means we haven't been able to // determine early if the test failed or not. // - // This implies for 'anyof' that the test failed, and for 'allof' that + // This implies for 'anyof' that the test failed, and for 'allof' that // we succeeded. Sounds weird, but makes sense. return $test==='allof'; } /** - * Validates if a param-filter can be applied to a specific property. - * - * @todo currently we're only validating the first parameter of the passed + * Validates if a param-filter can be applied to a specific property. + * + * @todo currently we're only validating the first parameter of the passed * property. Any subsequence parameters with the same name are * ignored. - * @param Sabre_VObject_Property $vProperty - * @param array $filters - * @param string $test - * @return bool + * @param array $vProperties + * @param array $filters + * @param string $test + * @return bool */ protected function validateParamFilters(array $vProperties, array $filters, $test) { - $success = false; foreach($filters as $filter) { $isDefined = false; @@ -377,17 +452,16 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin { $success = true; } - // If there's no text-match, we can just check for existence + // If there's no text-match, we can just check for existence } elseif (!$filter['text-match'] || !$isDefined) { $success = $isDefined; - + } else { - $texts = array(); $success = false; foreach($vProperties as $vProperty) { - // If we got all the way here, we'll need to validate the + // If we got all the way here, we'll need to validate the // text-match filter. $success = Sabre_DAV_StringUtil::textMatch($vProperty[$filter['name']]->value, $filter['text-match']['value'], $filter['text-match']['collation'], $filter['text-match']['match-type']); if ($success) break; @@ -398,7 +472,7 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin { } // else - // There are two conditions where we can already determine wether + // There are two conditions where we can already determine whether // or not this filter succeeds. if ($test==='anyof' && $success) { return true; @@ -407,24 +481,24 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin { return false; } - } + } - // If we got all the way here, it means we haven't been able to + // If we got all the way here, it means we haven't been able to // determine early if the test failed or not. // - // This implies for 'anyof' that the test failed, and for 'allof' that + // This implies for 'anyof' that the test failed, and for 'allof' that // we succeeded. Sounds weird, but makes sense. return $test==='allof'; } /** - * Validates if a text-filter can be applied to a specific property. - * + * Validates if a text-filter can be applied to a specific property. + * * @param array $texts - * @param array $filters - * @param string $test - * @return bool + * @param array $filters + * @param string $test + * @return bool */ protected function validateTextMatches(array $texts, array $filters, $test) { @@ -440,7 +514,7 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin { if ($filter['negate-condition']) { $success = !$success; } - + if ($success && $test==='anyof') return true; @@ -450,14 +524,64 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin { } - // If we got all the way here, it means we haven't been able to + // If we got all the way here, it means we haven't been able to // determine early if the test failed or not. // - // This implies for 'anyof' that the test failed, and for 'allof' that + // This implies for 'anyof' that the test failed, and for 'allof' that // we succeeded. Sounds weird, but makes sense. return $test==='allof'; } + /** + * This method is used to generate HTML output for the + * Sabre_DAV_Browser_Plugin. This allows us to generate an interface users + * can use to create new calendars. + * + * @param Sabre_DAV_INode $node + * @param string $output + * @return bool + */ + public function htmlActionsPanel(Sabre_DAV_INode $node, &$output) { + + if (!$node instanceof Sabre_CardDAV_UserAddressBooks) + return; + + $output.= '<tr><td colspan="2"><form method="post" action=""> + <h3>Create new address book</h3> + <input type="hidden" name="sabreAction" value="mkaddressbook" /> + <label>Name (uri):</label> <input type="text" name="name" /><br /> + <label>Display name:</label> <input type="text" name="{DAV:}displayname" /><br /> + <input type="submit" value="create" /> + </form> + </td></tr>'; + + return false; + + } + + /** + * This method allows us to intercept the 'mkcalendar' sabreAction. This + * action enables the user to create new calendars from the browser plugin. + * + * @param string $uri + * @param string $action + * @param array $postVars + * @return bool + */ + public function browserPostAction($uri, $action, array $postVars) { + + if ($action!=='mkaddressbook') + return; + + $resourceType = array('{DAV:}collection','{urn:ietf:params:xml:ns:carddav}addressbook'); + $properties = array(); + if (isset($postVars['{DAV:}displayname'])) { + $properties['{DAV:}displayname'] = $postVars['{DAV:}displayname']; + } + $this->server->createCollection($uri . '/' . $postVars['name'],$resourceType,$properties); + return false; + + } } diff --git a/3rdparty/Sabre/CardDAV/Property/SupportedAddressData.php b/3rdparty/Sabre/CardDAV/Property/SupportedAddressData.php index d57d3a6e7bd..36d9306e7aa 100644..100755 --- a/3rdparty/Sabre/CardDAV/Property/SupportedAddressData.php +++ b/3rdparty/Sabre/CardDAV/Property/SupportedAddressData.php @@ -4,11 +4,11 @@ * Supported-address-data property * * This property is a representation of the supported-address-data property - * in the CardDAV namespace. + * in the CardDAV namespace. * * @package Sabre * @subpackage CardDAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ @@ -16,15 +16,15 @@ class Sabre_CardDAV_Property_SupportedAddressData extends Sabre_DAV_Property { /** * supported versions - * - * @var array + * + * @var array */ protected $supportedData = array(); - + /** - * Creates the property - * - * @param array $components + * Creates the property + * + * @param array|null $supportedData */ public function __construct(array $supportedData = null) { @@ -35,22 +35,22 @@ class Sabre_CardDAV_Property_SupportedAddressData extends Sabre_DAV_Property { ); } - $this->supportedData = $supportedData; + $this->supportedData = $supportedData; } - + /** - * Serializes the property in a DOMDocument - * - * @param Sabre_DAV_Server $server - * @param DOMElement $node + * Serializes the property in a DOMDocument + * + * @param Sabre_DAV_Server $server + * @param DOMElement $node * @return void */ public function serialize(Sabre_DAV_Server $server,DOMElement $node) { $doc = $node->ownerDocument; - $prefix = + $prefix = isset($server->xmlNamespaces[Sabre_CardDAV_Plugin::NS_CARDDAV]) ? $server->xmlNamespaces[Sabre_CardDAV_Plugin::NS_CARDDAV] : 'card'; diff --git a/3rdparty/Sabre/CardDAV/UserAddressBooks.php b/3rdparty/Sabre/CardDAV/UserAddressBooks.php index e9f2de7f741..3f11fb11238 100644..100755 --- a/3rdparty/Sabre/CardDAV/UserAddressBooks.php +++ b/3rdparty/Sabre/CardDAV/UserAddressBooks.php @@ -7,7 +7,7 @@ * * @package Sabre * @subpackage CardDAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ @@ -15,47 +15,47 @@ class Sabre_CardDAV_UserAddressBooks extends Sabre_DAV_Collection implements Sab /** * Principal uri - * - * @var array + * + * @var array */ protected $principalUri; /** - * carddavBackend - * - * @var Sabre_CardDAV_Backend_Abstract + * carddavBackend + * + * @var Sabre_CardDAV_Backend_Abstract */ protected $carddavBackend; /** - * Constructor - * - * @param Sabre_CardDAV_Backend_Abstract $carddavBackend - * @param string $principalUri + * Constructor + * + * @param Sabre_CardDAV_Backend_Abstract $carddavBackend + * @param string $principalUri */ public function __construct(Sabre_CardDAV_Backend_Abstract $carddavBackend, $principalUri) { $this->carddavBackend = $carddavBackend; $this->principalUri = $principalUri; - + } /** - * Returns the name of this object - * + * Returns the name of this object + * * @return string */ public function getName() { - + list(,$name) = Sabre_DAV_URLUtil::splitPath($this->principalUri); - return $name; + return $name; } /** - * Updates the name of this object - * - * @param string $name + * Updates the name of this object + * + * @param string $name * @return void */ public function setName($name) { @@ -65,8 +65,8 @@ class Sabre_CardDAV_UserAddressBooks extends Sabre_DAV_Collection implements Sab } /** - * Deletes this object - * + * Deletes this object + * * @return void */ public function delete() { @@ -76,13 +76,13 @@ class Sabre_CardDAV_UserAddressBooks extends Sabre_DAV_Collection implements Sab } /** - * Returns the last modification date - * - * @return int + * Returns the last modification date + * + * @return int */ public function getLastModified() { - return null; + return null; } @@ -90,9 +90,9 @@ class Sabre_CardDAV_UserAddressBooks extends Sabre_DAV_Collection implements Sab * Creates a new file under this object. * * This is currently not allowed - * - * @param string $filename - * @param resource $data + * + * @param string $filename + * @param resource $data * @return void */ public function createFile($filename, $data=null) { @@ -105,8 +105,8 @@ class Sabre_CardDAV_UserAddressBooks extends Sabre_DAV_Collection implements Sab * Creates a new directory under this object. * * This is currently not allowed. - * - * @param string $filename + * + * @param string $filename * @return void */ public function createDirectory($filename) { @@ -116,8 +116,8 @@ class Sabre_CardDAV_UserAddressBooks extends Sabre_DAV_Collection implements Sab } /** - * Returns a single calendar, by name - * + * Returns a single calendar, by name + * * @param string $name * @todo needs optimizing * @return Sabre_CardDAV_AddressBook @@ -129,14 +129,14 @@ class Sabre_CardDAV_UserAddressBooks extends Sabre_DAV_Collection implements Sab return $child; } - throw new Sabre_DAV_Exception_FileNotFound('Addressbook with name \'' . $name . '\' could not be found'); + throw new Sabre_DAV_Exception_NotFound('Addressbook with name \'' . $name . '\' could not be found'); } /** - * Returns a list of addressbooks - * - * @return array + * Returns a list of addressbooks + * + * @return array */ public function getChildren() { @@ -150,11 +150,11 @@ class Sabre_CardDAV_UserAddressBooks extends Sabre_DAV_Collection implements Sab } /** - * Creates a new addressbook - * + * Creates a new addressbook + * * @param string $name - * @param array $resourceType - * @param array $properties + * @param array $resourceType + * @param array $properties * @return void */ public function createExtendedCollection($name, array $resourceType, array $properties) { @@ -169,8 +169,8 @@ class Sabre_CardDAV_UserAddressBooks extends Sabre_DAV_Collection implements Sab /** * Returns the owner principal * - * This must be a url to a principal, or null if there's no owner - * + * This must be a url to a principal, or null if there's no owner + * * @return string|null */ public function getOwner() { @@ -183,8 +183,8 @@ class Sabre_CardDAV_UserAddressBooks extends Sabre_DAV_Collection implements Sab * Returns a group principal * * This must be a url to a principal, or null if there's no owner - * - * @return string|null + * + * @return string|null */ public function getGroup() { @@ -196,13 +196,13 @@ class Sabre_CardDAV_UserAddressBooks extends Sabre_DAV_Collection implements Sab * 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 + * * '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 + * * 'protected' (optional), indicating that this ACE is not allowed to + * be updated. + * + * @return array */ public function getACL() { @@ -225,9 +225,9 @@ class Sabre_CardDAV_UserAddressBooks extends Sabre_DAV_Collection implements Sab /** * Updates the ACL * - * This method will receive a list of new ACE's. - * - * @param array $acl + * This method will receive a list of new ACE's. + * + * @param array $acl * @return void */ public function setACL(array $acl) { @@ -236,5 +236,22 @@ class Sabre_CardDAV_UserAddressBooks extends Sabre_DAV_Collection implements Sab } + /** + * Returns the list of supported privileges for this node. + * + * The returned data structure is a list of nested privileges. + * See Sabre_DAVACL_Plugin::getDefaultSupportedPrivilegeSet for a simple + * standard structure. + * + * If null is returned from this method, the default privilege set is used, + * which is fine for most common usecases. + * + * @return array|null + */ + public function getSupportedPrivilegeSet() { + + return null; + + } } diff --git a/3rdparty/Sabre/CardDAV/Version.php b/3rdparty/Sabre/CardDAV/Version.php index 900fbf5e75c..811b929e397 100644..100755 --- a/3rdparty/Sabre/CardDAV/Version.php +++ b/3rdparty/Sabre/CardDAV/Version.php @@ -4,10 +4,10 @@ * Version Class * * This class contains the Sabre_CardDAV version information - * + * * @package Sabre * @subpackage CardDAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ @@ -16,7 +16,7 @@ class Sabre_CardDAV_Version { /** * Full version number */ - const VERSION = '1.5.3'; + const VERSION = '1.6.1'; /** * Stability : alpha, beta, stable diff --git a/3rdparty/Sabre/CardDAV/includes.php b/3rdparty/Sabre/CardDAV/includes.php new file mode 100755 index 00000000000..c3b8c04b077 --- /dev/null +++ b/3rdparty/Sabre/CardDAV/includes.php @@ -0,0 +1,32 @@ +<?php + +/** + * Sabre_CardDAV includes file + * + * Including this file will automatically include all files from the + * Sabre_CardDAV package. + * + * This often allows faster loadtimes, as autoload-speed is often quite slow. + * + * @package Sabre + * @subpackage CardDAV + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. + * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License + */ + +// Begin includes +include __DIR__ . '/AddressBookQueryParser.php'; +include __DIR__ . '/AddressBookRoot.php'; +include __DIR__ . '/Backend/Abstract.php'; +include __DIR__ . '/Backend/PDO.php'; +include __DIR__ . '/IAddressBook.php'; +include __DIR__ . '/ICard.php'; +include __DIR__ . '/IDirectory.php'; +include __DIR__ . '/Plugin.php'; +include __DIR__ . '/Property/SupportedAddressData.php'; +include __DIR__ . '/UserAddressBooks.php'; +include __DIR__ . '/Version.php'; +include __DIR__ . '/AddressBook.php'; +include __DIR__ . '/Card.php'; +// End includes diff --git a/3rdparty/Sabre/DAV/Auth/Backend/AbstractBasic.php b/3rdparty/Sabre/DAV/Auth/Backend/AbstractBasic.php index 11bab8c7af7..1e89b84f9a1 100644..100755 --- a/3rdparty/Sabre/DAV/Auth/Backend/AbstractBasic.php +++ b/3rdparty/Sabre/DAV/Auth/Backend/AbstractBasic.php @@ -8,9 +8,9 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. * @author James David Low (http://jameslow.com/) - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @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 implements Sabre_DAV_Auth_IBackend { @@ -28,6 +28,8 @@ abstract class Sabre_DAV_Auth_Backend_AbstractBasic implements Sabre_DAV_Auth_IB * This method should return true or false depending on if login * succeeded. * + * @param string $username + * @param string $password * @return bool */ abstract protected function validateUserPass($username, $password); @@ -47,13 +49,15 @@ abstract class Sabre_DAV_Auth_Backend_AbstractBasic implements Sabre_DAV_Auth_IB /** * Authenticates the user based on the current request. * - * If authentication is succesful, true must be returned. + * If authentication is successful, true must be returned. * If authentication fails, an exception must be thrown. * + * @param Sabre_DAV_Server $server + * @param string $realm * @throws Sabre_DAV_Exception_NotAuthenticated * @return bool */ - public function authenticate(Sabre_DAV_Server $server,$realm) { + public function authenticate(Sabre_DAV_Server $server, $realm) { $auth = new Sabre_HTTP_BasicAuth(); $auth->setHTTPRequest($server->httpRequest); @@ -75,5 +79,5 @@ abstract class Sabre_DAV_Auth_Backend_AbstractBasic implements Sabre_DAV_Auth_IB } -} +} diff --git a/3rdparty/Sabre/DAV/Auth/Backend/AbstractDigest.php b/3rdparty/Sabre/DAV/Auth/Backend/AbstractDigest.php index 5bdc72753ec..9833928b976 100644..100755 --- a/3rdparty/Sabre/DAV/Auth/Backend/AbstractDigest.php +++ b/3rdparty/Sabre/DAV/Auth/Backend/AbstractDigest.php @@ -4,12 +4,12 @@ * HTTP Digest authentication backend class * * 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 getDigestHash method + * Most of the digest logic is handled, implementors just need to worry about + * the getDigestHash method * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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,7 +17,7 @@ abstract class Sabre_DAV_Auth_Backend_AbstractDigest implements Sabre_DAV_Auth_I /** * This variable holds the currently logged in username. - * + * * @var array|null */ protected $currentUser; @@ -25,24 +25,26 @@ abstract class Sabre_DAV_Auth_Backend_AbstractDigest implements Sabre_DAV_Auth_I /** * Returns a users digest hash based on the username and realm. * - * If the user was not known, null must be returned. - * + * If the user was not known, null must be returned. + * * @param string $realm - * @param string $username - * @return string|null + * @param string $username + * @return string|null */ - abstract public function getDigestHash($realm,$username); + abstract public function getDigestHash($realm, $username); /** * Authenticates the user based on the current request. * - * If authentication is succesful, true must be returned. + * If authentication is successful, true must be returned. * If authentication fails, an exception must be thrown. * + * @param Sabre_DAV_Server $server + * @param string $realm * @throws Sabre_DAV_Exception_NotAuthenticated - * @return bool + * @return bool */ - public function authenticate(Sabre_DAV_Server $server,$realm) { + public function authenticate(Sabre_DAV_Server $server, $realm) { $digest = new Sabre_HTTP_DigestAuth(); @@ -83,9 +85,9 @@ abstract class Sabre_DAV_Auth_Backend_AbstractDigest implements Sabre_DAV_Auth_I } /** - * Returns the currently logged in username. - * - * @return string|null + * Returns the currently logged in username. + * + * @return string|null */ public function getCurrentUser() { diff --git a/3rdparty/Sabre/DAV/Auth/Backend/Apache.php b/3rdparty/Sabre/DAV/Auth/Backend/Apache.php index 6bcd76bdcb0..d4294ea4d86 100644..100755 --- a/3rdparty/Sabre/DAV/Auth/Backend/Apache.php +++ b/3rdparty/Sabre/DAV/Auth/Backend/Apache.php @@ -4,34 +4,36 @@ * Apache authenticator * * This authentication backend assumes that authentication has been - * conifgured in apache, rather than within SabreDAV. + * configured in apache, rather than within SabreDAV. * * Make sure apache is properly configured for this to work. * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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 implements Sabre_DAV_Auth_IBackend { /** - * Current apache user - * - * @var string + * Current apache user + * + * @var string */ protected $remoteUser; - + /** * Authenticates the user based on the current request. * - * If authentication is succesful, true must be returned. + * If authentication is successful, true must be returned. * If authentication fails, an exception must be thrown. * - * @return bool + * @param Sabre_DAV_Server $server + * @param string $realm + * @return bool */ - public function authenticate(Sabre_DAV_Server $server,$realm) { + public function authenticate(Sabre_DAV_Server $server, $realm) { $remoteUser = $server->httpRequest->getRawServerValue('REMOTE_USER'); if (is_null($remoteUser)) { @@ -47,7 +49,7 @@ class Sabre_DAV_Auth_Backend_Apache implements Sabre_DAV_Auth_IBackend { * Returns information about the currently logged in user. * * If nobody is currently logged in, this method should return null. - * + * * @return array|null */ public function getCurrentUser() { diff --git a/3rdparty/Sabre/DAV/Auth/Backend/File.php b/3rdparty/Sabre/DAV/Auth/Backend/File.php index db1f04c4772..de308d64a67 100644..100755 --- a/3rdparty/Sabre/DAV/Auth/Backend/File.php +++ b/3rdparty/Sabre/DAV/Auth/Backend/File.php @@ -4,29 +4,28 @@ * This is an authentication backend that uses a file to manage passwords. * * The backend file must conform to Apache's htdigest format - * + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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_File extends Sabre_DAV_Auth_Backend_AbstractDigest { /** - * List of users - * + * List of users + * * @var array */ protected $users = array(); /** - * Creates the backend object. + * Creates the backend object. * * If the filename argument is passed in, it will parse out the specified file fist. - * - * @param string $filename - * @return void + * + * @param string|null $filename */ public function __construct($filename=null) { @@ -38,22 +37,22 @@ class Sabre_DAV_Auth_Backend_File extends Sabre_DAV_Auth_Backend_AbstractDigest /** * Loads an htdigest-formatted file. This method can be called multiple times if * more than 1 file is used. - * - * @param string $filename + * + * @param string $filename * @return void */ public function loadFile($filename) { foreach(file($filename,FILE_IGNORE_NEW_LINES) as $line) { - if (substr_count($line, ":") !== 2) + if (substr_count($line, ":") !== 2) throw new Sabre_DAV_Exception('Malformed htdigest file. Every line should contain 2 colons'); - + list($username,$realm,$A1) = explode(':',$line); if (!preg_match('/^[a-zA-Z0-9]{32}$/', $A1)) throw new Sabre_DAV_Exception('Malformed htdigest file. Invalid md5 hash'); - + $this->users[$realm . ':' . $username] = $A1; } @@ -62,10 +61,10 @@ class Sabre_DAV_Auth_Backend_File extends Sabre_DAV_Auth_Backend_AbstractDigest /** * Returns a users' information - * - * @param string $realm - * @param string $username - * @return string + * + * @param string $realm + * @param string $username + * @return string */ public function getDigestHash($realm, $username) { diff --git a/3rdparty/Sabre/DAV/Auth/Backend/PDO.php b/3rdparty/Sabre/DAV/Auth/Backend/PDO.php index 0301503601e..eac18a23fbb 100644..100755 --- a/3rdparty/Sabre/DAV/Auth/Backend/PDO.php +++ b/3rdparty/Sabre/DAV/Auth/Backend/PDO.php @@ -4,38 +4,37 @@ * This is an authentication backend that uses a file to manage passwords. * * The backend file must conform to Apache's htdigest format - * + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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_PDO extends Sabre_DAV_Auth_Backend_AbstractDigest { /** - * Reference to PDO connection - * - * @var PDO + * Reference to PDO connection + * + * @var PDO */ protected $pdo; /** - * PDO table name we'll be using - * + * PDO table name we'll be using + * * @var string */ protected $tableName; /** - * Creates the backend object. + * Creates the backend object. * * If the filename argument is passed in, it will parse out the specified file fist. - * - * @param string $filename - * @param string $tableName The PDO table name to use - * @return void + * + * @param PDO $pdo + * @param string $tableName The PDO table name to use */ public function __construct(PDO $pdo, $tableName = 'users') { @@ -45,15 +44,15 @@ class Sabre_DAV_Auth_Backend_PDO extends Sabre_DAV_Auth_Backend_AbstractDigest { } /** - * Returns the digest hash for a user. - * - * @param string $realm - * @param string $username - * @return string|null + * 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 `'.$this->tableName.'` WHERE username = ?'); + $stmt = $this->pdo->prepare('SELECT username, digesta1 FROM '.$this->tableName.' WHERE username = ?'); $stmt->execute(array($username)); $result = $stmt->fetchAll(); diff --git a/3rdparty/Sabre/DAV/Auth/IBackend.php b/3rdparty/Sabre/DAV/Auth/IBackend.php index 1f67af4c2d9..5be5d1bc93d 100644..100755 --- a/3rdparty/Sabre/DAV/Auth/IBackend.php +++ b/3rdparty/Sabre/DAV/Auth/IBackend.php @@ -5,7 +5,7 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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,18 +14,20 @@ interface Sabre_DAV_Auth_IBackend { /** * Authenticates the user based on the current request. * - * If authentication is succesful, true must be returned. + * If authentication is successful, true must be returned. * If authentication fails, an exception must be thrown. * - * @return bool + * @param Sabre_DAV_Server $server + * @param string $realm + * @return bool */ - function authenticate(Sabre_DAV_Server $server,$realm); + function authenticate(Sabre_DAV_Server $server,$realm); /** * Returns information about the currently logged in username. * * If nobody is currently logged in, this method should return null. - * + * * @return string|null */ function getCurrentUser(); diff --git a/3rdparty/Sabre/DAV/Auth/Plugin.php b/3rdparty/Sabre/DAV/Auth/Plugin.php index f3718fcf469..55a4e391674 100644..100755 --- a/3rdparty/Sabre/DAV/Auth/Plugin.php +++ b/3rdparty/Sabre/DAV/Auth/Plugin.php @@ -2,48 +2,47 @@ /** * This plugin provides Authentication for a WebDAV server. - * + * * It relies on a Backend object, which provides user information. * * Additionally, it provides support for: * * {DAV:}current-user-principal property from RFC5397 * * {DAV:}principal-collection-set property from RFC3744 - * + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_Plugin extends Sabre_DAV_ServerPlugin { /** - * Reference to main server object - * - * @var Sabre_DAV_Server + * Reference to main server object + * + * @var Sabre_DAV_Server */ private $server; /** * Authentication backend - * - * @var Sabre_DAV_Auth_Backend_Abstract + * + * @var Sabre_DAV_Auth_IBackend */ private $authBackend; /** - * The authentication realm. - * - * @var string + * The authentication realm. + * + * @var string */ private $realm; /** - * __construct - * - * @param Sabre_DAV_Auth_Backend_Abstract $authBackend - * @param string $realm - * @return void + * __construct + * + * @param Sabre_DAV_Auth_IBackend $authBackend + * @param string $realm */ public function __construct(Sabre_DAV_Auth_IBackend $authBackend, $realm) { @@ -53,9 +52,9 @@ class Sabre_DAV_Auth_Plugin extends Sabre_DAV_ServerPlugin { } /** - * Initializes the plugin. This function is automatically called by the server - * - * @param Sabre_DAV_Server $server + * 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) { @@ -67,11 +66,11 @@ class Sabre_DAV_Auth_Plugin extends Sabre_DAV_ServerPlugin { /** * Returns a plugin name. - * + * * Using this name other plugins will be able to access other plugins - * using Sabre_DAV_Server::getPlugin - * - * @return string + * using Sabre_DAV_Server::getPlugin + * + * @return string */ public function getPluginName() { @@ -81,10 +80,10 @@ class Sabre_DAV_Auth_Plugin extends Sabre_DAV_ServerPlugin { /** * Returns the current users' principal uri. - * - * If nobody is logged in, this will return null. - * - * @return string|null + * + * If nobody is logged in, this will return null. + * + * @return string|null */ public function getCurrentUser() { @@ -97,10 +96,11 @@ class Sabre_DAV_Auth_Plugin extends Sabre_DAV_ServerPlugin { /** * This method is called before any HTTP method and forces users to be authenticated - * + * * @param string $method + * @param string $uri * @throws Sabre_DAV_Exception_NotAuthenticated - * @return bool + * @return bool */ public function beforeMethod($method, $uri) { diff --git a/3rdparty/Sabre/DAV/Browser/GuessContentType.php b/3rdparty/Sabre/DAV/Browser/GuessContentType.php index ee8c698d782..b6c00d461cb 100644..100755 --- a/3rdparty/Sabre/DAV/Browser/GuessContentType.php +++ b/3rdparty/Sabre/DAV/Browser/GuessContentType.php @@ -10,10 +10,10 @@ * There's really no accurate, fast and portable way to determine the contenttype * so this extension does what the rest of the world does, and guesses it based * on the file extension. - * + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ @@ -43,9 +43,9 @@ class Sabre_DAV_Browser_GuessContentType extends Sabre_DAV_ServerPlugin { ); /** - * Initializes the plugin - * - * @param Sabre_DAV_Server $server + * Initializes the plugin + * + * @param Sabre_DAV_Server $server * @return void */ public function initialize(Sabre_DAV_Server $server) { @@ -57,16 +57,16 @@ class Sabre_DAV_Browser_GuessContentType extends Sabre_DAV_ServerPlugin { } /** - * Handler for teh afterGetProperties event - * - * @param string $path - * @param array $properties + * Handler for teh afterGetProperties event + * + * @param string $path + * @param array $properties * @return void */ public function afterGetProperties($path, &$properties) { if (array_key_exists('{DAV:}getcontenttype', $properties[404])) { - + list(, $fileName) = Sabre_DAV_URLUtil::splitPath($path); $contentType = $this->getContentType($fileName); @@ -81,9 +81,9 @@ class Sabre_DAV_Browser_GuessContentType extends Sabre_DAV_ServerPlugin { /** * Simple method to return the contenttype - * - * @param string $fileName - * @return string + * + * @param string $fileName + * @return string */ protected function getContentType($fileName) { diff --git a/3rdparty/Sabre/DAV/Browser/MapGetToPropFind.php b/3rdparty/Sabre/DAV/Browser/MapGetToPropFind.php index a66b57a3a90..15884887641 100644..100755 --- a/3rdparty/Sabre/DAV/Browser/MapGetToPropFind.php +++ b/3rdparty/Sabre/DAV/Browser/MapGetToPropFind.php @@ -1,30 +1,30 @@ <?php /** - * This is a simple plugin that will map any GET request for non-files to + * This is a simple plugin that will map any GET request for non-files to * PROPFIND allprops-requests. * * This should allow easy debugging of PROPFIND - * + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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_Browser_MapGetToPropFind extends Sabre_DAV_ServerPlugin { /** - * reference to server class - * - * @var Sabre_DAV_Server + * reference to server class + * + * @var Sabre_DAV_Server */ protected $server; /** - * Initializes the plugin and subscribes to events - * - * @param Sabre_DAV_Server $server + * Initializes the plugin and subscribes to events + * + * @param Sabre_DAV_Server $server * @return void */ public function initialize(Sabre_DAV_Server $server) { @@ -34,21 +34,22 @@ class Sabre_DAV_Browser_MapGetToPropFind extends Sabre_DAV_ServerPlugin { } /** - * This method intercepts GET requests to non-files, and changes it into an HTTP PROPFIND request - * - * @param string $method - * @return bool + * This method intercepts GET requests to non-files, and changes it into an HTTP PROPFIND request + * + * @param string $method + * @param string $uri + * @return bool */ public function httpGetInterceptor($method, $uri) { if ($method!='GET') return true; - + $node = $this->server->tree->getNodeForPath($uri); if ($node instanceof Sabre_DAV_IFile) return; $this->server->invokeMethod('PROPFIND',$uri); return false; - + } } diff --git a/3rdparty/Sabre/DAV/Browser/Plugin.php b/3rdparty/Sabre/DAV/Browser/Plugin.php index cd5617babb1..09bbdd2ae02 100644..100755 --- a/3rdparty/Sabre/DAV/Browser/Plugin.php +++ b/3rdparty/Sabre/DAV/Browser/Plugin.php @@ -6,77 +6,126 @@ * This plugin provides a html representation, so that a WebDAV server may be accessed * using a browser. * - * The class intercepts GET requests to collection resources and generates a simple - * html index. - * + * The class intercepts GET requests to collection resources and generates a simple + * html index. + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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_Browser_Plugin extends Sabre_DAV_ServerPlugin { /** - * reference to server class - * - * @var Sabre_DAV_Server + * List of default icons for nodes. + * + * This is an array with class / interface names as keys, and asset names + * as values. + * + * The evaluation order is reversed. The last item in the list gets + * precendence. + * + * @var array + */ + public $iconMap = array( + 'Sabre_DAV_IFile' => 'icons/file', + 'Sabre_DAV_ICollection' => 'icons/collection', + 'Sabre_DAVACL_IPrincipal' => 'icons/principal', + 'Sabre_CalDAV_ICalendar' => 'icons/calendar', + 'Sabre_CardDAV_IAddressBook' => 'icons/addressbook', + 'Sabre_CardDAV_ICard' => 'icons/card', + ); + + /** + * The file extension used for all icons + * + * @var string + */ + public $iconExtension = '.png'; + + /** + * reference to server class + * + * @var Sabre_DAV_Server */ protected $server; /** - * enableEditing - * - * @var bool + * enablePost turns on the 'actions' panel, which allows people to create + * folders and upload files straight from a browser. + * + * @var bool */ protected $enablePost = true; /** + * By default the browser plugin will generate a favicon and other images. + * To turn this off, set this property to false. + * + * @var bool + */ + protected $enableAssets = true; + + /** * Creates the object. * * By default it will allow file creation and uploads. * Specify the first argument as false to disable this - * - * @param bool $enablePost - * @return void + * + * @param bool $enablePost + * @param bool $enableAssets */ - public function __construct($enablePost=true) { + public function __construct($enablePost=true, $enableAssets = true) { - $this->enablePost = $enablePost; + $this->enablePost = $enablePost; + $this->enableAssets = $enableAssets; } /** - * Initializes the plugin and subscribes to events - * - * @param Sabre_DAV_Server $server + * Initializes the plugin and subscribes to events + * + * @param Sabre_DAV_Server $server * @return void */ public function initialize(Sabre_DAV_Server $server) { $this->server = $server; $this->server->subscribeEvent('beforeMethod',array($this,'httpGetInterceptor')); + $this->server->subscribeEvent('onHTMLActionsPanel', array($this, 'htmlActionsPanel'),200); if ($this->enablePost) $this->server->subscribeEvent('unknownMethod',array($this,'httpPOSTHandler')); } /** - * This method intercepts GET requests to collections and returns the html - * - * @param string $method - * @return bool + * This method intercepts GET requests to collections and returns the html + * + * @param string $method + * @param string $uri + * @return bool */ public function httpGetInterceptor($method, $uri) { - if ($method!='GET') return true; + if ($method !== 'GET') return true; + + // We're not using straight-up $_GET, because we want everything to be + // unit testable. + $getVars = array(); + parse_str($this->server->httpRequest->getQueryString(), $getVars); + + if (isset($getVars['sabreAction']) && $getVars['sabreAction'] === 'asset' && isset($getVars['assetName'])) { + $this->serveAsset($getVars['assetName']); + return false; + } - try { + try { $node = $this->server->tree->getNodeForPath($uri); - } catch (Sabre_DAV_Exception_FileNotFound $e) { - // We're simply stopping when the file isn't found to not interfere + } catch (Sabre_DAV_Exception_NotFound $e) { + // We're simply stopping when the file isn't found to not interfere // with other plugins. return; } - if ($node instanceof Sabre_DAV_IFile) + if ($node instanceof Sabre_DAV_IFile) return; $this->server->httpResponse->sendStatus(200); @@ -87,57 +136,71 @@ class Sabre_DAV_Browser_Plugin extends Sabre_DAV_ServerPlugin { ); return false; - + } /** - * Handles POST requests for tree operations - * - * This method is not yet used. - * - * @param string $method + * Handles POST requests for tree operations. + * + * @param string $method + * @param string $uri * @return bool */ public function httpPOSTHandler($method, $uri) { - if ($method!='POST') return true; - if (isset($_POST['sabreAction'])) switch($_POST['sabreAction']) { + if ($method!='POST') return; + $contentType = $this->server->httpRequest->getHeader('Content-Type'); + list($contentType) = explode(';', $contentType); + if ($contentType !== 'application/x-www-form-urlencoded' && + $contentType !== 'multipart/form-data') { + return; + } + $postVars = $this->server->httpRequest->getPostVars(); - case 'mkcol' : - if (isset($_POST['name']) && trim($_POST['name'])) { - // Using basename() because we won't allow slashes - list(, $folderName) = Sabre_DAV_URLUtil::splitPath(trim($_POST['name'])); - $this->server->createDirectory($uri . '/' . $folderName); - } - break; - case 'put' : - if ($_FILES) $file = current($_FILES); - else break; - $newName = trim($file['name']); - list(, $newName) = Sabre_DAV_URLUtil::splitPath(trim($file['name'])); - if (isset($_POST['name']) && trim($_POST['name'])) - $newName = trim($_POST['name']); - - // Making sure we only have a 'basename' component - list(, $newName) = Sabre_DAV_URLUtil::splitPath($newName); - - - if (is_uploaded_file($file['tmp_name'])) { - $parent = $this->server->tree->getNodeForPath(trim($uri,'/')); - $parent->createFile($newName,fopen($file['tmp_name'],'r')); - } + if (!isset($postVars['sabreAction'])) + return; + + if ($this->server->broadcastEvent('onBrowserPostAction', array($uri, $postVars['sabreAction'], $postVars))) { + + switch($postVars['sabreAction']) { + + case 'mkcol' : + if (isset($postVars['name']) && trim($postVars['name'])) { + // Using basename() because we won't allow slashes + list(, $folderName) = Sabre_DAV_URLUtil::splitPath(trim($postVars['name'])); + $this->server->createDirectory($uri . '/' . $folderName); + } + break; + case 'put' : + if ($_FILES) $file = current($_FILES); + else break; + + list(, $newName) = Sabre_DAV_URLUtil::splitPath(trim($file['name'])); + if (isset($postVars['name']) && trim($postVars['name'])) + $newName = trim($postVars['name']); + + // Making sure we only have a 'basename' component + list(, $newName) = Sabre_DAV_URLUtil::splitPath($newName); + + if (is_uploaded_file($file['tmp_name'])) { + $this->server->createFile($uri . '/' . $newName, fopen($file['tmp_name'],'r')); + } + break; + + } } $this->server->httpResponse->setHeader('Location',$this->server->httpRequest->getUri()); + $this->server->httpResponse->sendStatus(302); return false; } /** - * Escapes a string for html. - * - * @param string $value - * @return void + * Escapes a string for html. + * + * @param string $value + * @return string */ public function escapeHTML($value) { @@ -146,118 +209,199 @@ class Sabre_DAV_Browser_Plugin extends Sabre_DAV_ServerPlugin { } /** - * Generates the html directory index for a given url + * Generates the html directory index for a given url * - * @param string $path - * @return string + * @param string $path + * @return string */ public function generateDirectoryIndex($path) { + $version = ''; + if (Sabre_DAV_Server::$exposeVersion) { + $version = Sabre_DAV_Version::VERSION ."-". Sabre_DAV_Version::STABILITY; + } + $html = "<html> <head> - <title>Index for " . $this->escapeHTML($path) . "/ - SabreDAV " . Sabre_DAV_Version::VERSION . "</title> - <style type=\"text/css\"> body { Font-family: arial}</style> -</head> + <title>Index for " . $this->escapeHTML($path) . "/ - SabreDAV " . $version . "</title> + <style type=\"text/css\"> + body { Font-family: arial} + h1 { font-size: 150% } + </style> + "; + + if ($this->enableAssets) { + $html.='<link rel="shortcut icon" href="'.$this->getAssetUrl('favicon.ico').'" type="image/vnd.microsoft.icon" />'; + } + + $html .= "</head> <body> <h1>Index for " . $this->escapeHTML($path) . "/</h1> <table> - <tr><th>Name</th><th>Type</th><th>Size</th><th>Last modified</th></tr> - <tr><td colspan=\"4\"><hr /></td></tr>"; - - $files = $this->server->getPropertiesForPath($path,array( - '{DAV:}displayname', - '{DAV:}resourcetype', - '{DAV:}getcontenttype', - '{DAV:}getcontentlength', - '{DAV:}getlastmodified', - ),1); + <tr><th width=\"24\"></th><th>Name</th><th>Type</th><th>Size</th><th>Last modified</th></tr> + <tr><td colspan=\"5\"><hr /></td></tr>"; - $parent = $this->server->tree->getNodeForPath($path); + $files = $this->server->getPropertiesForPath($path,array( + '{DAV:}displayname', + '{DAV:}resourcetype', + '{DAV:}getcontenttype', + '{DAV:}getcontentlength', + '{DAV:}getlastmodified', + ),1); + $parent = $this->server->tree->getNodeForPath($path); - if ($path) { - list($parentUri) = Sabre_DAV_URLUtil::splitPath($path); - $fullPath = Sabre_DAV_URLUtil::encodePath($this->server->getBaseUri() . $parentUri); + if ($path) { - $html.= "<tr> -<td><a href=\"{$fullPath}\">..</a></td> -<td>[parent]</td> -<td></td> -<td></td> -</tr>"; + list($parentUri) = Sabre_DAV_URLUtil::splitPath($path); + $fullPath = Sabre_DAV_URLUtil::encodePath($this->server->getBaseUri() . $parentUri); - } + $icon = $this->enableAssets?'<a href="' . $fullPath . '"><img src="' . $this->getAssetUrl('icons/parent' . $this->iconExtension) . '" width="24" alt="Parent" /></a>':''; + $html.= "<tr> + <td>$icon</td> + <td><a href=\"{$fullPath}\">..</a></td> + <td>[parent]</td> + <td></td> + <td></td> + </tr>"; - foreach($files as $k=>$file) { + } - // This is the current directory, we can skip it - if (rtrim($file['href'],'/')==$path) continue; + foreach($files as $file) { + + // This is the current directory, we can skip it + if (rtrim($file['href'],'/')==$path) continue; + + list(, $name) = Sabre_DAV_URLUtil::splitPath($file['href']); + + $type = null; + + + if (isset($file[200]['{DAV:}resourcetype'])) { + $type = $file[200]['{DAV:}resourcetype']->getValue(); + + // resourcetype can have multiple values + 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; + case '{urn:ietf:params:xml:ns:carddav}addressbook' : + $type[$k] = 'Addressbook'; + break; + case '{urn:ietf:params:xml:ns:caldav}calendar' : + $type[$k] = 'Calendar'; + break; + case '{urn:ietf:params:xml:ns:caldav}schedule-inbox' : + $type[$k] = 'Schedule Inbox'; + break; + case '{urn:ietf:params:xml:ns:caldav}schedule-outbox' : + $type[$k] = 'Schedule Outbox'; + break; + case '{http://calendarserver.org/ns/}calendar-proxy-read' : + $type[$k] = 'Proxy-Read'; + break; + case '{http://calendarserver.org/ns/}calendar-proxy-write' : + $type[$k] = 'Proxy-Write'; + break; + } - list(, $name) = Sabre_DAV_URLUtil::splitPath($file['href']); + } + $type = implode(', ', $type); + } - $type = null; + // If no resourcetype was found, we attempt to use + // the contenttype property + if (!$type && isset($file[200]['{DAV:}getcontenttype'])) { + $type = $file[200]['{DAV:}getcontenttype']; + } + if (!$type) $type = 'Unknown'; + $size = isset($file[200]['{DAV:}getcontentlength'])?(int)$file[200]['{DAV:}getcontentlength']:''; + $lastmodified = isset($file[200]['{DAV:}getlastmodified'])?$file[200]['{DAV:}getlastmodified']->getTime()->format(DateTime::ATOM):''; - if (isset($file[200]['{DAV:}resourcetype'])) { - $type = $file[200]['{DAV:}resourcetype']->getValue(); + $fullPath = Sabre_DAV_URLUtil::encodePath('/' . trim($this->server->getBaseUri() . ($path?$path . '/':'') . $name,'/')); - // resourcetype can have multiple values - if (!is_array($type)) $type = array($type); + $displayName = isset($file[200]['{DAV:}displayname'])?$file[200]['{DAV:}displayname']:$name; - foreach($type as $k=>$v) { + $displayName = $this->escapeHTML($displayName); + $type = $this->escapeHTML($type); - // Some name mapping is preferred - switch($v) { - case '{DAV:}collection' : - $type[$k] = 'Collection'; - break; - case '{DAV:}principal' : - $type[$k] = 'Principal'; - break; - case '{urn:ietf:params:xml:ns:carddav}addressbook' : - $type[$k] = 'Addressbook'; - break; - case '{urn:ietf:params:xml:ns:caldav}calendar' : - $type[$k] = 'Calendar'; + $icon = ''; + + if ($this->enableAssets) { + $node = $parent->getChild($name); + foreach(array_reverse($this->iconMap) as $class=>$iconName) { + + if ($node instanceof $class) { + $icon = '<a href="' . $fullPath . '"><img src="' . $this->getAssetUrl($iconName . $this->iconExtension) . '" alt="" width="24" /></a>'; break; + } + + } } - $type = implode(', ', $type); - } - // If no resourcetype was found, we attempt to use - // the contenttype property - if (!$type && isset($file[200]['{DAV:}getcontenttype'])) { - $type = $file[200]['{DAV:}getcontenttype']; + $html.= "<tr> + <td>$icon</td> + <td><a href=\"{$fullPath}\">{$displayName}</a></td> + <td>{$type}</td> + <td>{$size}</td> + <td>{$lastmodified}</td> + </tr>"; + } - if (!$type) $type = 'Unknown'; - $size = isset($file[200]['{DAV:}getcontentlength'])?(int)$file[200]['{DAV:}getcontentlength']:''; - $lastmodified = isset($file[200]['{DAV:}getlastmodified'])?$file[200]['{DAV:}getlastmodified']->getTime()->format(DateTime::ATOM):''; + $html.= "<tr><td colspan=\"5\"><hr /></td></tr>"; + + $output = ''; - $fullPath = Sabre_DAV_URLUtil::encodePath('/' . trim($this->server->getBaseUri() . ($path?$path . '/':'') . $name,'/')); + if ($this->enablePost) { + $this->server->broadcastEvent('onHTMLActionsPanel',array($parent, &$output)); + } - $displayName = isset($file[200]['{DAV:}displayname'])?$file[200]['{DAV:}displayname']:$name; + $html.=$output; - $name = $this->escapeHTML($name); - $displayName = $this->escapeHTML($displayName); - $type = $this->escapeHTML($type); + $html.= "</table> + <address>Generated by SabreDAV " . $version . " (c)2007-2012 <a href=\"http://code.google.com/p/sabredav/\">http://code.google.com/p/sabredav/</a></address> + </body> + </html>"; - $html.= "<tr> -<td><a href=\"{$fullPath}\">{$displayName}</a></td> -<td>{$type}</td> -<td>{$size}</td> -<td>{$lastmodified}</td> -</tr>"; + return $html; } - $html.= "<tr><td colspan=\"4\"><hr /></td></tr>"; + /** + * This method is used to generate the 'actions panel' output for + * collections. + * + * This specifically generates the interfaces for creating new files, and + * creating new directories. + * + * @param Sabre_DAV_INode $node + * @param mixed $output + * @return void + */ + public function htmlActionsPanel(Sabre_DAV_INode $node, &$output) { + + if (!$node instanceof Sabre_DAV_ICollection) + return; + + // We also know fairly certain that if an object is a non-extended + // SimpleCollection, we won't need to show the panel either. + if (get_class($node)==='Sabre_DAV_SimpleCollection') + return; - if ($this->enablePost && $parent instanceof Sabre_DAV_ICollection) { - $html.= '<tr><td><form method="post" action=""> + $output.= '<tr><td colspan="2"><form method="post" action=""> <h3>Create new folder</h3> <input type="hidden" name="sabreAction" value="mkcol" /> Name: <input type="text" name="name" /><br /> @@ -270,15 +414,75 @@ class Sabre_DAV_Browser_Plugin extends Sabre_DAV_ServerPlugin { File: <input type="file" name="file" /><br /> <input type="submit" value="upload" /> </form> - </td></tr>'; - } + </td></tr>'; + + } - $html.= "</table> - <address>Generated by SabreDAV " . Sabre_DAV_Version::VERSION ."-". Sabre_DAV_Version::STABILITY . " (c)2007-2011 <a href=\"http://code.google.com/p/sabredav/\">http://code.google.com/p/sabredav/</a></address> -</body> -</html>"; + /** + * This method takes a path/name of an asset and turns it into url + * suiteable for http access. + * + * @param string $assetName + * @return string + */ + protected function getAssetUrl($assetName) { - return $html; + return $this->server->getBaseUri() . '?sabreAction=asset&assetName=' . urlencode($assetName); + + } + + /** + * This method returns a local pathname to an asset. + * + * @param string $assetName + * @return string + */ + protected function getLocalAssetPath($assetName) { + + // Making sure people aren't trying to escape from the base path. + $assetSplit = explode('/', $assetName); + if (in_array('..',$assetSplit)) { + throw new Sabre_DAV_Exception('Incorrect asset path'); + } + $path = __DIR__ . '/assets/' . $assetName; + return $path; + + } + + /** + * This method reads an asset from disk and generates a full http response. + * + * @param string $assetName + * @return void + */ + protected function serveAsset($assetName) { + + $assetPath = $this->getLocalAssetPath($assetName); + if (!file_exists($assetPath)) { + throw new Sabre_DAV_Exception_NotFound('Could not find an asset with this name'); + } + // Rudimentary mime type detection + switch(strtolower(substr($assetPath,strpos($assetPath,'.')+1))) { + + case 'ico' : + $mime = 'image/vnd.microsoft.icon'; + break; + + case 'png' : + $mime = 'image/png'; + break; + + default: + $mime = 'application/octet-stream'; + break; + + } + + $this->server->httpResponse->setHeader('Content-Type', $mime); + $this->server->httpResponse->setHeader('Content-Length', filesize($assetPath)); + $this->server->httpResponse->setHeader('Cache-Control', 'public, max-age=1209600'); + $this->server->httpResponse->sendStatus(200); + $this->server->httpResponse->sendBody(fopen($assetPath,'r')); } diff --git a/3rdparty/Sabre/DAV/Browser/assets/favicon.ico b/3rdparty/Sabre/DAV/Browser/assets/favicon.ico Binary files differnew file mode 100755 index 00000000000..2b2c10a22cc --- /dev/null +++ b/3rdparty/Sabre/DAV/Browser/assets/favicon.ico diff --git a/3rdparty/Sabre/DAV/Browser/assets/icons/addressbook.png b/3rdparty/Sabre/DAV/Browser/assets/icons/addressbook.png Binary files differnew file mode 100755 index 00000000000..c9acc84172d --- /dev/null +++ b/3rdparty/Sabre/DAV/Browser/assets/icons/addressbook.png diff --git a/3rdparty/Sabre/DAV/Browser/assets/icons/calendar.png b/3rdparty/Sabre/DAV/Browser/assets/icons/calendar.png Binary files differnew file mode 100755 index 00000000000..3ecd6a800a0 --- /dev/null +++ b/3rdparty/Sabre/DAV/Browser/assets/icons/calendar.png diff --git a/3rdparty/Sabre/DAV/Browser/assets/icons/card.png b/3rdparty/Sabre/DAV/Browser/assets/icons/card.png Binary files differnew file mode 100755 index 00000000000..2ce954866d8 --- /dev/null +++ b/3rdparty/Sabre/DAV/Browser/assets/icons/card.png diff --git a/3rdparty/Sabre/DAV/Browser/assets/icons/collection.png b/3rdparty/Sabre/DAV/Browser/assets/icons/collection.png Binary files differnew file mode 100755 index 00000000000..156fa64fd50 --- /dev/null +++ b/3rdparty/Sabre/DAV/Browser/assets/icons/collection.png diff --git a/3rdparty/Sabre/DAV/Browser/assets/icons/file.png b/3rdparty/Sabre/DAV/Browser/assets/icons/file.png Binary files differnew file mode 100755 index 00000000000..3b98551cec3 --- /dev/null +++ b/3rdparty/Sabre/DAV/Browser/assets/icons/file.png diff --git a/3rdparty/Sabre/DAV/Browser/assets/icons/parent.png b/3rdparty/Sabre/DAV/Browser/assets/icons/parent.png Binary files differnew file mode 100755 index 00000000000..156fa64fd50 --- /dev/null +++ b/3rdparty/Sabre/DAV/Browser/assets/icons/parent.png diff --git a/3rdparty/Sabre/DAV/Browser/assets/icons/principal.png b/3rdparty/Sabre/DAV/Browser/assets/icons/principal.png Binary files differnew file mode 100755 index 00000000000..f8988f828e6 --- /dev/null +++ b/3rdparty/Sabre/DAV/Browser/assets/icons/principal.png diff --git a/3rdparty/Sabre/DAV/Client.php b/3rdparty/Sabre/DAV/Client.php index fc6a6fff083..a8320dd9782 100644..100755 --- a/3rdparty/Sabre/DAV/Client.php +++ b/3rdparty/Sabre/DAV/Client.php @@ -3,14 +3,14 @@ /** * SabreDAV DAV client * - * This client wraps around Curl to provide a convenient API to a WebDAV + * This client wraps around Curl to provide a convenient API to a WebDAV * server. * * NOTE: This class is experimental, it's api will likely change in the future. - * + * * @package Sabre * @subpackage DAVClient - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ @@ -26,22 +26,22 @@ class Sabre_DAV_Client { /** * Constructor * - * Settings are provided through the 'settings' argument. The following + * Settings are provided through the 'settings' argument. The following * settings are supported: * * * baseUri * * userName (optional) * * password (optional) * * proxy (optional) - * - * @param array $settings + * + * @param array $settings */ public function __construct(array $settings) { if (!isset($settings['baseUri'])) { throw new InvalidArgumentException('A baseUri must be provided'); } - + $validSettings = array( 'baseUri', 'userName', @@ -62,23 +62,23 @@ class Sabre_DAV_Client { /** * Does a PROPFIND request * - * The list of requested properties must be specified as an array, in clark - * notation. + * The list of requested properties must be specified as an array, in clark + * notation. * - * The returned array will contain a list of filenames as keys, and + * The returned array will contain a list of filenames as keys, and * properties as values. * - * The properties array will contain the list of properties. Only properties - * that are actually returned from the server (without error) will be + * The properties array will contain the list of properties. Only properties + * that are actually returned from the server (without error) will be * returned, anything else is discarded. * - * Depth should be either 0 or 1. A depth of 1 will cause a request to be + * Depth should be either 0 or 1. A depth of 1 will cause a request to be * made to the server to also return all child resources. * - * @param string $url - * @param array $properties - * @param int $depth - * @return array + * @param string $url + * @param array $properties + * @param int $depth + * @return array */ public function propFind($url, array $properties, $depth = 0) { @@ -132,14 +132,14 @@ class Sabre_DAV_Client { /** * Updates a list of properties on the server * - * The list of properties must have clark-notation properties for the keys, - * and the actual (string) value for the value. If the value is null, an - * attempt is made to delete the property. + * The list of properties must have clark-notation properties for the keys, + * and the actual (string) value for the value. If the value is null, an + * attempt is made to delete the property. * - * @todo Must be building the request using the DOM, and does not yet - * support complex properties. - * @param string $url - * @param array $properties + * @todo Must be building the request using the DOM, and does not yet + * support complex properties. + * @param string $url + * @param array $properties * @return void */ public function propPatch($url, array $properties) { @@ -175,7 +175,7 @@ class Sabre_DAV_Client { $body.=" <x:" . $elementName . " xmlns:x=\"" . $namespace . "\">"; } // Shitty.. i know - $body.=htmlspecialchars($propValue, ENT_NOQUOTES, 'UTF-8'); + $body.=htmlspecialchars($propValue, ENT_NOQUOTES, 'UTF-8'); if ($namespace === 'DAV:') { $body.='</d:' . $elementName . '>' . "\n"; } else { @@ -189,7 +189,7 @@ class Sabre_DAV_Client { $body.= '</d:propertyupdate>'; - $response = $this->request('PROPPATCH', $url, $body, array( + $this->request('PROPPATCH', $url, $body, array( 'Content-Type' => 'application/xml' )); @@ -198,11 +198,11 @@ class Sabre_DAV_Client { /** * Performs an HTTP options request * - * This method returns all the features from the 'DAV:' header as an array. - * If there was no DAV header, or no contents this method will return an - * empty array. - * - * @return array + * This method returns all the features from the 'DAV:' header as an array. + * If there was no DAV header, or no contents this method will return an + * empty array. + * + * @return array */ public function options() { @@ -222,20 +222,20 @@ class Sabre_DAV_Client { /** * Performs an actual HTTP request, and returns the result. * - * If the specified url is relative, it will be expanded based on the base + * If the specified url is relative, it will be expanded based on the base * url. * * The returned array contains 3 keys: * * body - the response body * * httpCode - a HTTP code (200, 404, etc) - * * headers - a list of response http headers. The header names have + * * headers - a list of response http headers. The header names have * been lowercased. * - * @param string $method - * @param string $url - * @param string $body - * @param array $headers - * @return array + * @param string $method + * @param string $url + * @param string $body + * @param array $headers + * @return array */ public function request($method, $url = '', $body = null, $headers = array()) { @@ -243,14 +243,37 @@ class Sabre_DAV_Client { $curlSettings = array( CURLOPT_RETURNTRANSFER => true, - CURLOPT_CUSTOMREQUEST => $method, - CURLOPT_POSTFIELDS => $body, // Return headers as part of the response - CURLOPT_HEADER => true + CURLOPT_HEADER => true, + CURLOPT_POSTFIELDS => $body, + // Automatically follow redirects + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_MAXREDIRS => 5, ); + switch ($method) { + case 'PUT': + $curlSettings[CURLOPT_PUT] = true; + break; + case 'HEAD' : + + // do not read body with HEAD requests (this is neccessary because cURL does not ignore the body with HEAD + // requests when the Content-Length header is given - which in turn is perfectly valid according to HTTP + // specs...) cURL does unfortunately return an error in this case ("transfer closed transfer closed with + // ... bytes remaining to read") this can be circumvented by explicitly telling cURL to ignore the + // response body + $curlSettings[CURLOPT_NOBODY] = true; + $curlSettings[CURLOPT_CUSTOMREQUEST] = 'HEAD'; + break; + + default: + $curlSettings[CURLOPT_CUSTOMREQUEST] = $method; + break; + + } + // Adding HTTP headers - $nHeaders = array(); + $nHeaders = array(); foreach($headers as $key=>$value) { $nHeaders[] = $key . ': ' . $value; @@ -277,17 +300,17 @@ class Sabre_DAV_Client { $headerBlob = substr($response, 0, $curlInfo['header_size']); $response = substr($response, $curlInfo['header_size']); - // In the case of 100 Continue, or redirects we'll have multiple lists - // of headers for each separate HTTP response. We can easily split this + // In the case of 100 Continue, or redirects we'll have multiple lists + // of headers for each separate HTTP response. We can easily split this // because they are separated by \r\n\r\n $headerBlob = explode("\r\n\r\n", trim($headerBlob, "\r\n")); - + // We only care about the last set of headers $headerBlob = $headerBlob[count($headerBlob)-1]; // Splitting headers $headerBlob = explode("\r\n", $headerBlob); - + $headers = array(); foreach($headerBlob as $header) { $parts = explode(':', $header, 2); @@ -304,10 +327,17 @@ class Sabre_DAV_Client { if ($curlErrNo) { throw new Sabre_DAV_Exception('[CURL] Error while making request: ' . $curlError . ' (error code: ' . $curlErrNo . ')'); - } + } if ($response['statusCode']>=400) { - throw new Sabre_DAV_Exception('HTTP error response. (errorcode ' . $response['statusCode'] . ')'); + switch ($response['statusCode']) { + case 404: + throw new Sabre_DAV_Exception_NotFound('Resource ' . $url . ' not found.'); + break; + + default: + throw new Sabre_DAV_Exception('HTTP error response. (errorcode ' . $response['statusCode'] . ')'); + } } return $response; @@ -317,12 +347,12 @@ class Sabre_DAV_Client { /** * Wrapper for all curl functions. * - * The only reason this was split out in a separate method, is so it - * becomes easier to unittest. + * The only reason this was split out in a separate method, is so it + * becomes easier to unittest. * * @param string $url - * @param array $settings - * @return + * @param array $settings + * @return array */ protected function curlRequest($url, $settings) { @@ -339,20 +369,20 @@ class Sabre_DAV_Client { } /** - * Returns the full url based on the given url (which may be relative). All - * urls are expanded based on the base url as given by the server. - * - * @param string $url - * @return string + * Returns the full url based on the given url (which may be relative). All + * urls are expanded based on the base url as given by the server. + * + * @param string $url + * @return string */ protected function getAbsoluteUrl($url) { - // If the url starts with http:// or https://, the url is already absolute. + // If the url starts with http:// or https://, the url is already absolute. if (preg_match('/^http(s?):\/\//', $url)) { return $url; } - // If the url starts with a slash, we must calculate the url based off + // If the url starts with a slash, we must calculate the url based off // the root of the base url. if (strpos($url,'/') === 0) { $parts = parse_url($this->baseUri); @@ -366,7 +396,7 @@ class Sabre_DAV_Client { /** * Parses a WebDAV multistatus response body - * + * * This method returns an array with the following structure * * array( @@ -387,7 +417,7 @@ class Sabre_DAV_Client { * * * @param string $body xml body - * @return array + * @return array */ public function parseMultiStatus($body) { @@ -397,14 +427,13 @@ class Sabre_DAV_Client { if ($responseXML===false) { throw new InvalidArgumentException('The passed data is not valid XML'); } - - $responseXML->registerXPathNamespace('d','DAV:'); + + $responseXML->registerXPathNamespace('d', 'urn:DAV'); $propResult = array(); foreach($responseXML->xpath('d:response') as $response) { - - $response->registerXPathNamespace('d','DAV:'); + $response->registerXPathNamespace('d', 'urn:DAV'); $href = $response->xpath('d:href'); $href = (string)$href[0]; @@ -412,11 +441,11 @@ class Sabre_DAV_Client { foreach($response->xpath('d:propstat') as $propStat) { - $propStat->registerXPathNamespace('d','DAV:'); + $propStat->registerXPathNamespace('d', 'urn:DAV'); $status = $propStat->xpath('d:status'); list($httpVersion, $statusCode, $message) = explode(' ', (string)$status[0],3); - $properties[$statusCode] = Sabre_DAV_XMLUtil::parseProperties(dom_import_simplexml($propStat), $this->propertyMap); + $properties[$statusCode] = Sabre_DAV_XMLUtil::parseProperties(dom_import_simplexml($propStat), $this->propertyMap); } diff --git a/3rdparty/Sabre/DAV/Collection.php b/3rdparty/Sabre/DAV/Collection.php index 9da04c12792..776c22531b2 100644..100755 --- a/3rdparty/Sabre/DAV/Collection.php +++ b/3rdparty/Sabre/DAV/Collection.php @@ -4,12 +4,12 @@ * Collection class * * This is a helper class, that should aid in getting collections classes setup. - * Most of its methods are implemented, and throw permission denied exceptions - * + * Most of its methods are implemented, and throw permission denied exceptions + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_Collection extends Sabre_DAV_Node implements Sabre_DAV_ICollection { @@ -17,12 +17,12 @@ abstract class Sabre_DAV_Collection extends Sabre_DAV_Node implements Sabre_DAV_ /** * Returns a child object, by its name. * - * This method makes use of the getChildren method to grab all the child nodes, and compares the name. + * This method makes use of the getChildren method to grab all the child nodes, and compares the name. * Generally its wise to override this, as this can usually be optimized - * + * * @param string $name - * @throws Sabre_DAV_Exception_FileNotFound - * @return Sabre_DAV_INode + * @throws Sabre_DAV_Exception_NotFound + * @return Sabre_DAV_INode */ public function getChild($name) { @@ -31,7 +31,7 @@ abstract class Sabre_DAV_Collection extends Sabre_DAV_Node implements Sabre_DAV_ if ($child->getName()==$name) return $child; } - throw new Sabre_DAV_Exception_FileNotFound('File not found: ' . $name); + throw new Sabre_DAV_Exception_NotFound('File not found: ' . $name); } @@ -39,9 +39,9 @@ abstract class Sabre_DAV_Collection extends Sabre_DAV_Node implements Sabre_DAV_ * Checks is a child-node exists. * * It is generally a good idea to try and override this. Usually it can be optimized. - * - * @param string $name - * @return bool + * + * @param string $name + * @return bool */ public function childExists($name) { @@ -50,7 +50,7 @@ abstract class Sabre_DAV_Collection extends Sabre_DAV_Node implements Sabre_DAV_ $this->getChild($name); return true; - } catch(Sabre_DAV_Exception_FileNotFound $e) { + } catch(Sabre_DAV_Exception_NotFound $e) { return false; @@ -59,12 +59,28 @@ abstract class Sabre_DAV_Collection extends Sabre_DAV_Node implements Sabre_DAV_ } /** - * Creates a new file in the directory - * - * @param string $name Name of the file - * @param resource $data Initial payload, passed as a readable stream resource. - * @throws Sabre_DAV_Exception_Forbidden - * @return void + * Creates a new file in the directory + * + * Data will either be supplied as a stream resource, or in certain cases + * as a string. Keep in mind that you may have to support either. + * + * After succesful creation of the file, you may choose to return the ETag + * of the new file here. + * + * The returned ETag must be surrounded by double-quotes (The quotes should + * be part of the actual string). + * + * If you cannot accurately determine the ETag, you should not return it. + * If you don't store the file exactly as-is (you're transforming it + * somehow) you should also not return an ETag. + * + * This means that if a subsequent GET to this new file does not exactly + * return the same contents of what was submitted here, you are strongly + * recommended to omit the ETag. + * + * @param string $name Name of the file + * @param resource|string $data Initial payload + * @return null|string */ public function createFile($name, $data = null) { @@ -73,9 +89,9 @@ abstract class Sabre_DAV_Collection extends Sabre_DAV_Node implements Sabre_DAV_ } /** - * Creates a new subdirectory - * - * @param string $name + * Creates a new subdirectory + * + * @param string $name * @throws Sabre_DAV_Exception_Forbidden * @return void */ diff --git a/3rdparty/Sabre/DAV/Directory.php b/3rdparty/Sabre/DAV/Directory.php index 86af4827b3e..6db8febc02e 100644..100755 --- a/3rdparty/Sabre/DAV/Directory.php +++ b/3rdparty/Sabre/DAV/Directory.php @@ -8,7 +8,7 @@ * @package Sabre * @subpackage DAV * @deprecated Use Sabre_DAV_Collection instead - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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/3rdparty/Sabre/DAV/Exception.php b/3rdparty/Sabre/DAV/Exception.php index 61f8b87c0a6..a2cd6cf5820 100644..100755 --- a/3rdparty/Sabre/DAV/Exception.php +++ b/3rdparty/Sabre/DAV/Exception.php @@ -7,42 +7,42 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ /** - * Main Exception class. + * Main Exception class. * - * This class defines a getHTTPCode method, which should return the appropriate HTTP code for the Exception occured. + * This class defines a getHTTPCode method, which should return the appropriate HTTP code for the Exception occurred. * The default for this is 500. * * This class also allows you to generate custom xml data for your exceptions. This will be displayed * in the 'error' element in the failing response. */ -class Sabre_DAV_Exception extends Exception { +class Sabre_DAV_Exception extends Exception { /** - * Returns the HTTP statuscode for this exception + * Returns the HTTP statuscode for this exception * * @return int */ - public function getHTTPCode() { + public function getHTTPCode() { return 500; } /** - * This method allows the exception to include additonal information into the WebDAV error response + * This method allows the exception to include additional information into the WebDAV error response * * @param Sabre_DAV_Server $server - * @param DOMElement $errorNode + * @param DOMElement $errorNode * @return void */ public function serialize(Sabre_DAV_Server $server,DOMElement $errorNode) { - + } @@ -50,14 +50,15 @@ class Sabre_DAV_Exception extends Exception { * This method allows the exception to return any extra HTTP response headers. * * The headers must be returned as an array. - * - * @return array + * + * @param Sabre_DAV_Server $server + * @return array */ public function getHTTPHeaders(Sabre_DAV_Server $server) { return array(); - } + } } diff --git a/3rdparty/Sabre/DAV/Exception/BadRequest.php b/3rdparty/Sabre/DAV/Exception/BadRequest.php index 7025bb10317..b198648a754 100644..100755 --- a/3rdparty/Sabre/DAV/Exception/BadRequest.php +++ b/3rdparty/Sabre/DAV/Exception/BadRequest.php @@ -4,24 +4,24 @@ * BadRequest * * The BadRequest is thrown when the user submitted an invalid HTTP request - * BadRequest - * + * BadRequest + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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_Exception_BadRequest extends Sabre_DAV_Exception { /** - * Returns the HTTP statuscode for this exception + * Returns the HTTP statuscode for this exception * * @return int */ public function getHTTPCode() { - return 400; + return 400; } diff --git a/3rdparty/Sabre/DAV/Exception/Conflict.php b/3rdparty/Sabre/DAV/Exception/Conflict.php index 7eaa08178ae..6b0bd1fad73 100644..100755 --- a/3rdparty/Sabre/DAV/Exception/Conflict.php +++ b/3rdparty/Sabre/DAV/Exception/Conflict.php @@ -8,14 +8,14 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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_Exception_Conflict extends Sabre_DAV_Exception { /** - * Returns the HTTP statuscode for this exception + * Returns the HTTP statuscode for this exception * * @return int */ diff --git a/3rdparty/Sabre/DAV/Exception/ConflictingLock.php b/3rdparty/Sabre/DAV/Exception/ConflictingLock.php index 279f63dfde7..6121868e69e 100644..100755 --- a/3rdparty/Sabre/DAV/Exception/ConflictingLock.php +++ b/3rdparty/Sabre/DAV/Exception/ConflictingLock.php @@ -1,28 +1,28 @@ <?php /** - * ConflictingLock + * ConflictingLock * - * Similar to Exception_Locked, this exception thrown when a LOCK request + * Similar to Exception_Locked, this exception thrown when a LOCK request * was made, on a resource which was already locked * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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_Exception_ConflictingLock extends Sabre_DAV_Exception_Locked { /** - * This method allows the exception to include additonal information into the WebDAV error response + * This method allows the exception to include additional information into the WebDAV error response * * @param Sabre_DAV_Server $server - * @param DOMElement $errorNode + * @param DOMElement $errorNode * @return void */ public function serialize(Sabre_DAV_Server $server,DOMElement $errorNode) { - + if ($this->lock) { $error = $errorNode->ownerDocument->createElementNS('DAV:','d:no-conflicting-lock'); $errorNode->appendChild($error); diff --git a/3rdparty/Sabre/DAV/Exception/FileNotFound.php b/3rdparty/Sabre/DAV/Exception/FileNotFound.php index b20e4a2fb3f..d76e400c93b 100644..100755 --- a/3rdparty/Sabre/DAV/Exception/FileNotFound.php +++ b/3rdparty/Sabre/DAV/Exception/FileNotFound.php @@ -3,26 +3,17 @@ /** * FileNotFound * - * This Exception is thrown when a Node couldn't be found. It returns HTTP error code 404 + * Deprecated: Warning, this class is deprecated and will be removed in a + * future version of SabreDAV. Please use Sabre_DAV_Exception_NotFound instead. * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @deprecated Use Sabre_DAV_Exception_NotFound instead * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ -class Sabre_DAV_Exception_FileNotFound extends Sabre_DAV_Exception { - - /** - * Returns the HTTP statuscode for this exception - * - * @return int - */ - public function getHTTPCode() { - - return 404; - - } +class Sabre_DAV_Exception_FileNotFound extends Sabre_DAV_Exception_NotFound { } diff --git a/3rdparty/Sabre/DAV/Exception/Forbidden.php b/3rdparty/Sabre/DAV/Exception/Forbidden.php index 167f3c2760a..20b1056e31b 100644..100755 --- a/3rdparty/Sabre/DAV/Exception/Forbidden.php +++ b/3rdparty/Sabre/DAV/Exception/Forbidden.php @@ -4,17 +4,17 @@ * Forbidden * * This exception is thrown whenever a user tries to do an operation he's not allowed to - * + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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_Exception_Forbidden extends Sabre_DAV_Exception { /** - * Returns the HTTP statuscode for this exception + * Returns the HTTP statuscode for this exception * * @return int */ diff --git a/3rdparty/Sabre/DAV/Exception/InsufficientStorage.php b/3rdparty/Sabre/DAV/Exception/InsufficientStorage.php index 15007cdd352..1a15089b0a3 100644..100755 --- a/3rdparty/Sabre/DAV/Exception/InsufficientStorage.php +++ b/3rdparty/Sabre/DAV/Exception/InsufficientStorage.php @@ -1,20 +1,20 @@ <?php /** - * InsufficientStorage + * InsufficientStorage * * This Exception can be thrown, when for example a harddisk is full or a quota is exceeded * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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_Exception_InsufficientStorage extends Sabre_DAV_Exception { /** - * Returns the HTTP statuscode for this exception + * Returns the HTTP statuscode for this exception * * @return int */ diff --git a/3rdparty/Sabre/DAV/Exception/InvalidResourceType.php b/3rdparty/Sabre/DAV/Exception/InvalidResourceType.php index f06810a25ef..2230f1d0811 100644..100755 --- a/3rdparty/Sabre/DAV/Exception/InvalidResourceType.php +++ b/3rdparty/Sabre/DAV/Exception/InvalidResourceType.php @@ -1,26 +1,26 @@ <?php /** - * InvalidResourceType + * InvalidResourceType * * This exception is thrown when the user tried to create a new collection, with * a special resourcetype value that was not recognized by the server. * * See RFC5689 section 3.3 - * + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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_Exception_InvalidResourceType extends Sabre_DAV_Exception_Forbidden { +class Sabre_DAV_Exception_InvalidResourceType extends Sabre_DAV_Exception_Forbidden { /** - * This method allows the exception to include additonal information into the WebDAV error response + * This method allows the exception to include additional information into the WebDAV error response * * @param Sabre_DAV_Server $server - * @param DOMElement $errorNode + * @param DOMElement $errorNode * @return void */ public function serialize(Sabre_DAV_Server $server,DOMElement $errorNode) { @@ -29,5 +29,5 @@ class Sabre_DAV_Exception_InvalidResourceType extends Sabre_DAV_Exception_Forbid $errorNode->appendChild($error); } - + } diff --git a/3rdparty/Sabre/DAV/Exception/LockTokenMatchesRequestUri.php b/3rdparty/Sabre/DAV/Exception/LockTokenMatchesRequestUri.php index 47032cffc75..80ab7aff65a 100644..100755 --- a/3rdparty/Sabre/DAV/Exception/LockTokenMatchesRequestUri.php +++ b/3rdparty/Sabre/DAV/Exception/LockTokenMatchesRequestUri.php @@ -1,13 +1,13 @@ <?php /** - * LockTokenMatchesRequestUri + * LockTokenMatchesRequestUri + * + * This exception is thrown by UNLOCK if a supplied lock-token is invalid * - * This exception is thrown by UNLOCK if a supplied lock-token is invalid - * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ @@ -23,10 +23,10 @@ class Sabre_DAV_Exception_LockTokenMatchesRequestUri extends Sabre_DAV_Exception } /** - * This method allows the exception to include additonal information into the WebDAV error response + * This method allows the exception to include additional information into the WebDAV error response * * @param Sabre_DAV_Server $server - * @param DOMElement $errorNode + * @param DOMElement $errorNode * @return void */ public function serialize(Sabre_DAV_Server $server,DOMElement $errorNode) { diff --git a/3rdparty/Sabre/DAV/Exception/Locked.php b/3rdparty/Sabre/DAV/Exception/Locked.php index b4bb2e0378c..976365ac1f8 100644..100755 --- a/3rdparty/Sabre/DAV/Exception/Locked.php +++ b/3rdparty/Sabre/DAV/Exception/Locked.php @@ -1,32 +1,32 @@ <?php /** - * Locked + * Locked * * The 423 is thrown when a client tried to access a resource that was locked, without supplying a valid lock token - * + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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_Exception_Locked extends Sabre_DAV_Exception { /** - * Lock information - * - * @var Sabre_DAV_Locks_LockInfo + * Lock information + * + * @var Sabre_DAV_Locks_LockInfo */ protected $lock; /** * Creates the exception - * + * * A LockInfo object should be passed if the user should be informed * which lock actually has the file locked. - * - * @param Sabre_DAV_Locks_LockInfo $lock + * + * @param Sabre_DAV_Locks_LockInfo $lock */ public function __construct(Sabre_DAV_Locks_LockInfo $lock = null) { @@ -35,7 +35,7 @@ class Sabre_DAV_Exception_Locked extends Sabre_DAV_Exception { } /** - * Returns the HTTP statuscode for this exception + * Returns the HTTP statuscode for this exception * * @return int */ @@ -46,14 +46,14 @@ class Sabre_DAV_Exception_Locked extends Sabre_DAV_Exception { } /** - * This method allows the exception to include additonal information into the WebDAV error response + * This method allows the exception to include additional information into the WebDAV error response * * @param Sabre_DAV_Server $server - * @param DOMElement $errorNode + * @param DOMElement $errorNode * @return void */ public function serialize(Sabre_DAV_Server $server,DOMElement $errorNode) { - + if ($this->lock) { $error = $errorNode->ownerDocument->createElementNS('DAV:','d:lock-token-submitted'); $errorNode->appendChild($error); diff --git a/3rdparty/Sabre/DAV/Exception/MethodNotAllowed.php b/3rdparty/Sabre/DAV/Exception/MethodNotAllowed.php index 02c145ffeb6..31875751505 100644..100755 --- a/3rdparty/Sabre/DAV/Exception/MethodNotAllowed.php +++ b/3rdparty/Sabre/DAV/Exception/MethodNotAllowed.php @@ -4,17 +4,17 @@ * MethodNotAllowed * * The 405 is thrown when a client tried to create a directory on an already existing directory - * + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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_Exception_MethodNotAllowed extends Sabre_DAV_Exception { /** - * Returns the HTTP statuscode for this exception + * Returns the HTTP statuscode for this exception * * @return int */ @@ -28,8 +28,9 @@ class Sabre_DAV_Exception_MethodNotAllowed extends Sabre_DAV_Exception { * This method allows the exception to return any extra HTTP response headers. * * The headers must be returned as an array. - * - * @return array + * + * @param Sabre_DAV_Server $server + * @return array */ public function getHTTPHeaders(Sabre_DAV_Server $server) { diff --git a/3rdparty/Sabre/DAV/Exception/NotAuthenticated.php b/3rdparty/Sabre/DAV/Exception/NotAuthenticated.php index 1faffddfa00..87ca624429f 100644..100755 --- a/3rdparty/Sabre/DAV/Exception/NotAuthenticated.php +++ b/3rdparty/Sabre/DAV/Exception/NotAuthenticated.php @@ -5,22 +5,22 @@ * * This exception is thrown when the client did not provide valid * authentication credentials. - * + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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_Exception_NotAuthenticated extends Sabre_DAV_Exception { /** - * Returns the HTTP statuscode for this exception + * Returns the HTTP statuscode for this exception * * @return int */ public function getHTTPCode() { - + return 401; } diff --git a/3rdparty/Sabre/DAV/Exception/NotFound.php b/3rdparty/Sabre/DAV/Exception/NotFound.php new file mode 100755 index 00000000000..2b9da560d23 --- /dev/null +++ b/3rdparty/Sabre/DAV/Exception/NotFound.php @@ -0,0 +1,28 @@ +<?php + +/** + * NotFound + * + * This Exception is thrown when a Node couldn't be found. It returns HTTP error code 404 + * + * @package Sabre + * @subpackage DAV + * @copyright Copyright (C) 2007-2012 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_Exception_NotFound extends Sabre_DAV_Exception { + + /** + * Returns the HTTP statuscode for this exception + * + * @return int + */ + public function getHTTPCode() { + + return 404; + + } + +} + diff --git a/3rdparty/Sabre/DAV/Exception/NotImplemented.php b/3rdparty/Sabre/DAV/Exception/NotImplemented.php index cd7f609b09d..d017a19f559 100644..100755 --- a/3rdparty/Sabre/DAV/Exception/NotImplemented.php +++ b/3rdparty/Sabre/DAV/Exception/NotImplemented.php @@ -4,22 +4,22 @@ * NotImplemented * * This exception is thrown when the client tried to call an unsupported HTTP method or other feature - * + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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_Exception_NotImplemented extends Sabre_DAV_Exception { /** - * Returns the HTTP statuscode for this exception + * Returns the HTTP statuscode for this exception * * @return int */ public function getHTTPCode() { - + return 501; } diff --git a/3rdparty/Sabre/DAV/Exception/PaymentRequired.php b/3rdparty/Sabre/DAV/Exception/PaymentRequired.php new file mode 100755 index 00000000000..4982f45a4b5 --- /dev/null +++ b/3rdparty/Sabre/DAV/Exception/PaymentRequired.php @@ -0,0 +1,28 @@ +<?php + +/** + * Payment Required + * + * The PaymentRequired exception may be thrown in a case where a user must pay + * to access a certain resource or operation. + * + * @package Sabre + * @subpackage DAV + * @copyright Copyright (C) 2007-2012 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_Exception_PaymentRequired extends Sabre_DAV_Exception { + + /** + * Returns the HTTP statuscode for this exception + * + * @return int + */ + public function getHTTPCode() { + + return 402; + + } + +} diff --git a/3rdparty/Sabre/DAV/Exception/PreconditionFailed.php b/3rdparty/Sabre/DAV/Exception/PreconditionFailed.php index ebcb9f5b9ac..213e9c52317 100644..100755 --- a/3rdparty/Sabre/DAV/Exception/PreconditionFailed.php +++ b/3rdparty/Sabre/DAV/Exception/PreconditionFailed.php @@ -1,15 +1,15 @@ <?php /** - * PreconditionFailed + * PreconditionFailed * - * This exception is normally thrown when a client submitted a conditional request, - * like for example an If, If-None-Match or If-Match header, which caused the HTTP + * This exception is normally thrown when a client submitted a conditional request, + * like for example an If, If-None-Match or If-Match header, which caused the HTTP * request to not execute (the condition of the header failed) - * + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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,47 +17,47 @@ class Sabre_DAV_Exception_PreconditionFailed extends Sabre_DAV_Exception { /** * When this exception is thrown, the header-name might be set. - * + * * This allows the exception-catching code to determine which HTTP header * caused the exception. - * - * @var string + * + * @var string */ public $header = null; /** - * Create the exception - * - * @param string $message - * @param string $header + * Create the exception + * + * @param string $message + * @param string $header */ public function __construct($message, $header=null) { parent::__construct($message); $this->header = $header; - } + } /** - * Returns the HTTP statuscode for this exception + * Returns the HTTP statuscode for this exception * * @return int */ public function getHTTPCode() { - return 412; + return 412; } /** - * This method allows the exception to include additonal information into the WebDAV error response + * This method allows the exception to include additional information into the WebDAV error response * * @param Sabre_DAV_Server $server - * @param DOMElement $errorNode + * @param DOMElement $errorNode * @return void */ public function serialize(Sabre_DAV_Server $server,DOMElement $errorNode) { - + if ($this->header) { $prop = $errorNode->ownerDocument->createElement('s:header'); $prop->nodeValue = $this->header; diff --git a/3rdparty/Sabre/DAV/Exception/ReportNotImplemented.php b/3rdparty/Sabre/DAV/Exception/ReportNotImplemented.php index e4ed601b16c..e86800f3038 100644..100755 --- a/3rdparty/Sabre/DAV/Exception/ReportNotImplemented.php +++ b/3rdparty/Sabre/DAV/Exception/ReportNotImplemented.php @@ -7,17 +7,17 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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_Exception_ReportNotImplemented extends Sabre_DAV_Exception_NotImplemented { /** - * This method allows the exception to include additonal information into the WebDAV error response + * This method allows the exception to include additional information into the WebDAV error response * * @param Sabre_DAV_Server $server - * @param DOMElement $errorNode + * @param DOMElement $errorNode * @return void */ public function serialize(Sabre_DAV_Server $server,DOMElement $errorNode) { diff --git a/3rdparty/Sabre/DAV/Exception/RequestedRangeNotSatisfiable.php b/3rdparty/Sabre/DAV/Exception/RequestedRangeNotSatisfiable.php index 37abbd729d1..29ee3654a7e 100644..100755 --- a/3rdparty/Sabre/DAV/Exception/RequestedRangeNotSatisfiable.php +++ b/3rdparty/Sabre/DAV/Exception/RequestedRangeNotSatisfiable.php @@ -1,21 +1,21 @@ <?php /** - * RequestedRangeNotSatisfiable + * RequestedRangeNotSatisfiable * - * This exception is normally thrown when the user + * This exception is normally thrown when the user * request a range that is out of the entity bounds. * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_Exception_RequestedRangeNotSatisfiable extends Sabre_DAV_Exception { /** - * returns the http statuscode for this exception + * returns the http statuscode for this exception * * @return int */ diff --git a/3rdparty/Sabre/DAV/Exception/UnsupportedMediaType.php b/3rdparty/Sabre/DAV/Exception/UnsupportedMediaType.php index 4c37d8997cf..9a4693b21a8 100644..100755 --- a/3rdparty/Sabre/DAV/Exception/UnsupportedMediaType.php +++ b/3rdparty/Sabre/DAV/Exception/UnsupportedMediaType.php @@ -3,19 +3,19 @@ /** * UnSupportedMediaType * - * The 415 Unsupported Media Type status code is generally sent back when the client + * The 415 Unsupported Media Type status code is generally sent back when the client * tried to call an HTTP method, with a body the server didn't understand * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_Exception_UnsupportedMediaType extends Sabre_DAV_Exception { +class Sabre_DAV_Exception_UnsupportedMediaType extends Sabre_DAV_Exception { /** - * returns the http statuscode for this exception + * returns the http statuscode for this exception * * @return int */ diff --git a/3rdparty/Sabre/DAV/FS/Directory.php b/3rdparty/Sabre/DAV/FS/Directory.php index ebd6a6c505e..3af2d755583 100644..100755 --- a/3rdparty/Sabre/DAV/FS/Directory.php +++ b/3rdparty/Sabre/DAV/FS/Directory.php @@ -1,24 +1,39 @@ <?php /** - * Directory class - * + * Directory class + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_FS_Directory extends Sabre_DAV_FS_Node implements Sabre_DAV_ICollection, Sabre_DAV_IQuota { /** - * Creates a new file in the directory - * - * data is a readable stream resource + * Creates a new file in the directory * - * @param string $name Name of the file - * @param resource $data Initial payload - * @return void + * Data will either be supplied as a stream resource, or in certain cases + * as a string. Keep in mind that you may have to support either. + * + * After succesful creation of the file, you may choose to return the ETag + * of the new file here. + * + * The returned ETag must be surrounded by double-quotes (The quotes should + * be part of the actual string). + * + * If you cannot accurately determine the ETag, you should not return it. + * If you don't store the file exactly as-is (you're transforming it + * somehow) you should also not return an ETag. + * + * This means that if a subsequent GET to this new file does not exactly + * return the same contents of what was submitted here, you are strongly + * recommended to omit the ETag. + * + * @param string $name Name of the file + * @param resource|string $data Initial payload + * @return null|string */ public function createFile($name, $data = null) { @@ -28,9 +43,9 @@ class Sabre_DAV_FS_Directory extends Sabre_DAV_FS_Node implements Sabre_DAV_ICol } /** - * Creates a new subdirectory - * - * @param string $name + * Creates a new subdirectory + * + * @param string $name * @return void */ public function createDirectory($name) { @@ -41,17 +56,17 @@ class Sabre_DAV_FS_Directory extends Sabre_DAV_FS_Node implements Sabre_DAV_ICol } /** - * Returns a specific child node, referenced by its name - * - * @param string $name - * @throws Sabre_DAV_Exception_FileNotFound - * @return Sabre_DAV_INode + * Returns a specific child node, referenced by its name + * + * @param string $name + * @throws Sabre_DAV_Exception_NotFound + * @return Sabre_DAV_INode */ public function getChild($name) { $path = $this->path . '/' . $name; - if (!file_exists($path)) throw new Sabre_DAV_Exception_FileNotFound('File with name ' . $path . ' could not be located'); + if (!file_exists($path)) throw new Sabre_DAV_Exception_NotFound('File with name ' . $path . ' could not be located'); if (is_dir($path)) { @@ -66,9 +81,9 @@ class Sabre_DAV_FS_Directory extends Sabre_DAV_FS_Node implements Sabre_DAV_ICol } /** - * Returns an array with all the child nodes - * - * @return Sabre_DAV_INode[] + * Returns an array with all the child nodes + * + * @return Sabre_DAV_INode[] */ public function getChildren() { @@ -79,10 +94,10 @@ class Sabre_DAV_FS_Directory extends Sabre_DAV_FS_Node implements Sabre_DAV_ICol } /** - * Checks if a child exists. - * - * @param string $name - * @return bool + * Checks if a child exists. + * + * @param string $name + * @return bool */ public function childExists($name) { @@ -92,8 +107,8 @@ class Sabre_DAV_FS_Directory extends Sabre_DAV_FS_Node implements Sabre_DAV_ICol } /** - * Deletes all files in this directory, and then itself - * + * Deletes all files in this directory, and then itself + * * @return void */ public function delete() { @@ -104,16 +119,16 @@ class Sabre_DAV_FS_Directory extends Sabre_DAV_FS_Node implements Sabre_DAV_ICol } /** - * Returns available diskspace information - * - * @return array + * Returns available diskspace information + * + * @return array */ public function getQuotaInfo() { return array( disk_total_space($this->path)-disk_free_space($this->path), disk_free_space($this->path) - ); + ); } diff --git a/3rdparty/Sabre/DAV/FS/File.php b/3rdparty/Sabre/DAV/FS/File.php index 262187d7e8a..6a8039fe303 100644..100755 --- a/3rdparty/Sabre/DAV/FS/File.php +++ b/3rdparty/Sabre/DAV/FS/File.php @@ -1,21 +1,21 @@ <?php /** - * File class - * + * File class + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_FS_File extends Sabre_DAV_FS_Node implements Sabre_DAV_IFile { /** - * Updates the data - * - * @param resource $data - * @return void + * Updates the data + * + * @param resource $data + * @return void */ public function put($data) { @@ -24,9 +24,9 @@ class Sabre_DAV_FS_File extends Sabre_DAV_FS_Node implements Sabre_DAV_IFile { } /** - * Returns the data - * - * @return string + * Returns the data + * + * @return string */ public function get() { @@ -37,7 +37,7 @@ class Sabre_DAV_FS_File extends Sabre_DAV_FS_Node implements Sabre_DAV_IFile { /** * Delete the current file * - * @return void + * @return void */ public function delete() { @@ -46,12 +46,12 @@ class Sabre_DAV_FS_File extends Sabre_DAV_FS_Node implements Sabre_DAV_IFile { } /** - * Returns the size of the node, in bytes - * - * @return int + * Returns the size of the node, in bytes + * + * @return int */ public function getSize() { - + return filesize($this->path); } @@ -60,10 +60,10 @@ class Sabre_DAV_FS_File extends Sabre_DAV_FS_Node implements Sabre_DAV_IFile { * Returns the ETag for a file * * An ETag is a unique identifier representing the current version of the file. If the file changes, the ETag MUST change. - * The ETag is an arbritrary string, but MUST be surrounded by double-quotes. + * The ETag is an arbitrary string, but MUST be surrounded by double-quotes. * * Return null if the ETag can not effectively be determined - * + * * @return mixed */ public function getETag() { @@ -77,8 +77,8 @@ class Sabre_DAV_FS_File extends Sabre_DAV_FS_Node implements Sabre_DAV_IFile { * * If null is returned, we'll assume application/octet-stream * - * @return mixed - */ + * @return mixed + */ public function getContentType() { return null; diff --git a/3rdparty/Sabre/DAV/FS/Node.php b/3rdparty/Sabre/DAV/FS/Node.php index b8d7bcfe846..1283e9d0fdc 100644..100755 --- a/3rdparty/Sabre/DAV/FS/Node.php +++ b/3rdparty/Sabre/DAV/FS/Node.php @@ -1,30 +1,29 @@ <?php /** - * Base node-class + * Base node-class + * + * The node class implements the method used by both the File and the Directory classes * - * The node class implements the method used by both the File and the Directory classes - * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_FS_Node implements Sabre_DAV_INode { /** * The path to the current node - * - * @var string + * + * @var string */ - protected $path; + protected $path; /** - * Sets up the node, expects a full path name - * - * @param string $path - * @return void + * Sets up the node, expects a full path name + * + * @param string $path */ public function __construct($path) { @@ -35,9 +34,9 @@ abstract class Sabre_DAV_FS_Node implements Sabre_DAV_INode { /** - * Returns the name of the node - * - * @return string + * Returns the name of the node + * + * @return string */ public function getName() { @@ -59,7 +58,7 @@ abstract class Sabre_DAV_FS_Node implements Sabre_DAV_INode { $newPath = $parentPath . '/' . $newName; rename($this->path,$newPath); - + $this->path = $newPath; } @@ -67,9 +66,9 @@ abstract class Sabre_DAV_FS_Node implements Sabre_DAV_INode { /** - * Returns the last modification time, as a unix timestamp - * - * @return int + * Returns the last modification time, as a unix timestamp + * + * @return int */ public function getLastModified() { diff --git a/3rdparty/Sabre/DAV/FSExt/Directory.php b/3rdparty/Sabre/DAV/FSExt/Directory.php index c43d4385ac7..540057183b3 100644..100755 --- a/3rdparty/Sabre/DAV/FSExt/Directory.php +++ b/3rdparty/Sabre/DAV/FSExt/Directory.php @@ -1,22 +1,39 @@ <?php /** - * Directory class - * + * Directory class + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_FSExt_Directory extends Sabre_DAV_FSExt_Node implements Sabre_DAV_ICollection, Sabre_DAV_IQuota { /** - * Creates a new file in the directory - * - * @param string $name Name of the file - * @param resource $data Initial payload - * @return void + * Creates a new file in the directory + * + * Data will either be supplied as a stream resource, or in certain cases + * as a string. Keep in mind that you may have to support either. + * + * After succesful creation of the file, you may choose to return the ETag + * of the new file here. + * + * The returned ETag must be surrounded by double-quotes (The quotes should + * be part of the actual string). + * + * If you cannot accurately determine the ETag, you should not return it. + * If you don't store the file exactly as-is (you're transforming it + * somehow) you should also not return an ETag. + * + * This means that if a subsequent GET to this new file does not exactly + * return the same contents of what was submitted here, you are strongly + * recommended to omit the ETag. + * + * @param string $name Name of the file + * @param resource|string $data Initial payload + * @return null|string */ public function createFile($name, $data = null) { @@ -25,12 +42,14 @@ class Sabre_DAV_FSExt_Directory extends Sabre_DAV_FSExt_Node implements Sabre_DA $newPath = $this->path . '/' . $name; file_put_contents($newPath,$data); + return '"' . md5_file($newPath) . '"'; + } /** - * Creates a new subdirectory - * - * @param string $name + * Creates a new subdirectory + * + * @param string $name * @return void */ public function createDirectory($name) { @@ -43,18 +62,18 @@ class Sabre_DAV_FSExt_Directory extends Sabre_DAV_FSExt_Node implements Sabre_DA } /** - * Returns a specific child node, referenced by its name - * - * @param string $name - * @throws Sabre_DAV_Exception_FileNotFound - * @return Sabre_DAV_INode + * Returns a specific child node, referenced by its name + * + * @param string $name + * @throws Sabre_DAV_Exception_NotFound + * @return Sabre_DAV_INode */ public function getChild($name) { $path = $this->path . '/' . $name; - if (!file_exists($path)) throw new Sabre_DAV_Exception_FileNotFound('File could not be located'); - if ($name=='.' || $name=='..') throw new Sabre_DAV_Exception_Forbidden('Permission denied to . and ..'); + if (!file_exists($path)) throw new Sabre_DAV_Exception_NotFound('File could not be located'); + if ($name=='.' || $name=='..') throw new Sabre_DAV_Exception_Forbidden('Permission denied to . and ..'); if (is_dir($path)) { @@ -69,10 +88,10 @@ class Sabre_DAV_FSExt_Directory extends Sabre_DAV_FSExt_Node implements Sabre_DA } /** - * Checks if a child exists. - * - * @param string $name - * @return bool + * Checks if a child exists. + * + * @param string $name + * @return bool */ public function childExists($name) { @@ -85,9 +104,9 @@ class Sabre_DAV_FSExt_Directory extends Sabre_DAV_FSExt_Node implements Sabre_DA } /** - * Returns an array with all the child nodes - * - * @return Sabre_DAV_INode[] + * Returns an array with all the child nodes + * + * @return Sabre_DAV_INode[] */ public function getChildren() { @@ -98,9 +117,9 @@ class Sabre_DAV_FSExt_Directory extends Sabre_DAV_FSExt_Node implements Sabre_DA } /** - * Deletes all files in this directory, and then itself - * - * @return void + * Deletes all files in this directory, and then itself + * + * @return bool */ public function delete() { @@ -118,16 +137,16 @@ class Sabre_DAV_FSExt_Directory extends Sabre_DAV_FSExt_Node implements Sabre_DA } /** - * Returns available diskspace information - * - * @return array + * Returns available diskspace information + * + * @return array */ public function getQuotaInfo() { return array( disk_total_space($this->path)-disk_free_space($this->path), disk_free_space($this->path) - ); + ); } diff --git a/3rdparty/Sabre/DAV/FSExt/File.php b/3rdparty/Sabre/DAV/FSExt/File.php index 7a8e7a11f21..b93ce5aee21 100644..100755 --- a/3rdparty/Sabre/DAV/FSExt/File.php +++ b/3rdparty/Sabre/DAV/FSExt/File.php @@ -1,34 +1,35 @@ <?php /** - * File class - * + * File class + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_FSExt_File extends Sabre_DAV_FSExt_Node implements Sabre_DAV_IFile { /** - * Updates the data + * Updates the data * * data is a readable stream resource. * - * @param resource $data - * @return void + * @param resource $data + * @return void */ public function put($data) { file_put_contents($this->path,$data); + return '"' . md5_file($this->path) . '"'; } /** * Returns the data * - * @return string + * @return string */ public function get() { @@ -39,7 +40,7 @@ class Sabre_DAV_FSExt_File extends Sabre_DAV_FSExt_Node implements Sabre_DAV_IFi /** * Delete the current file * - * @return void + * @return bool */ public function delete() { @@ -52,9 +53,11 @@ class Sabre_DAV_FSExt_File extends Sabre_DAV_FSExt_Node implements Sabre_DAV_IFi * Returns the ETag for a file * * An ETag is a unique identifier representing the current version of the file. If the file changes, the ETag MUST change. - * The ETag is an arbritrary string, but MUST be surrounded by double-quotes. + * The ETag is an arbitrary string, but MUST be surrounded by double-quotes. * * Return null if the ETag can not effectively be determined + * + * @return string|null */ public function getETag() { @@ -66,7 +69,9 @@ class Sabre_DAV_FSExt_File extends Sabre_DAV_FSExt_Node implements Sabre_DAV_IFi * Returns the mime-type for a file * * If null is returned, we'll assume application/octet-stream - */ + * + * @return string|null + */ public function getContentType() { return null; @@ -74,9 +79,9 @@ class Sabre_DAV_FSExt_File extends Sabre_DAV_FSExt_Node implements Sabre_DAV_IFi } /** - * Returns the size of the file, in bytes - * - * @return int + * Returns the size of the file, in bytes + * + * @return int */ public function getSize() { diff --git a/3rdparty/Sabre/DAV/FSExt/Node.php b/3rdparty/Sabre/DAV/FSExt/Node.php index 9e36222bfd3..68ca06beb7e 100644..100755 --- a/3rdparty/Sabre/DAV/FSExt/Node.php +++ b/3rdparty/Sabre/DAV/FSExt/Node.php @@ -1,95 +1,28 @@ <?php /** - * Base node-class + * Base node-class + * + * The node class implements the method used by both the File and the Directory classes * - * The node class implements the method used by both the File and the Directory classes - * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_FSExt_Node extends Sabre_DAV_FS_Node implements Sabre_DAV_ILockable, Sabre_DAV_IProperties { - - /** - * Returns all the locks on this node - * - * @return array - */ - function getLocks() { - - $resourceData = $this->getResourceData(); - $locks = $resourceData['locks']; - foreach($locks as $k=>$lock) { - if (time() > $lock->timeout + $lock->created) unset($locks[$k]); - } - return $locks; - - } - - /** - * Locks this node - * - * @param Sabre_DAV_Locks_LockInfo $lockInfo - * @return void - */ - function lock(Sabre_DAV_Locks_LockInfo $lockInfo) { - - // We're making the lock timeout 30 minutes - $lockInfo->timeout = 1800; - $lockInfo->created = time(); - - $resourceData = $this->getResourceData(); - if (!isset($resourceData['locks'])) $resourceData['locks'] = array(); - $current = null; - foreach($resourceData['locks'] as $k=>$lock) { - if ($lock->token === $lockInfo->token) $current = $k; - } - if (!is_null($current)) $resourceData['locks'][$current] = $lockInfo; - else $resourceData['locks'][] = $lockInfo; - - $this->putResourceData($resourceData); - - } - - /** - * Removes a lock from this node - * - * @param Sabre_DAV_Locks_LockInfo $lockInfo - * @return bool - */ - function unlock(Sabre_DAV_Locks_LockInfo $lockInfo) { - - //throw new Sabre_DAV_Exception('bla'); - $resourceData = $this->getResourceData(); - foreach($resourceData['locks'] as $k=>$lock) { - - if ($lock->token === $lockInfo->token) { - - unset($resourceData['locks'][$k]); - $this->putResourceData($resourceData); - return true; - - } - } - return false; - - } +abstract class Sabre_DAV_FSExt_Node extends Sabre_DAV_FS_Node implements Sabre_DAV_IProperties { /** * Updates properties on this node, * - * @param array $mutations + * @param array $properties * @see Sabre_DAV_IProperties::updateProperties - * @return bool|array + * @return bool|array */ public function updateProperties($properties) { $resourceData = $this->getResourceData(); - - $result = array(); foreach($properties as $propertyName=>$propertyValue) { @@ -101,11 +34,11 @@ abstract class Sabre_DAV_FSExt_Node extends Sabre_DAV_FS_Node implements Sabre_D } else { $resourceData['properties'][$propertyName] = $propertyValue; } - + } $this->putResourceData($resourceData); - return true; + return true; } /** @@ -114,8 +47,8 @@ abstract class Sabre_DAV_FSExt_Node extends Sabre_DAV_FS_Node implements Sabre_D * The properties list is a list of propertynames the client requested, encoded as xmlnamespace#tagName, for example: http://www.example.org/namespace#author * If the array is empty, all properties should be returned * - * @param array $properties - * @return void + * @param array $properties + * @return array */ function getProperties($properties) { @@ -134,9 +67,9 @@ abstract class Sabre_DAV_FSExt_Node extends Sabre_DAV_FS_Node implements Sabre_D } /** - * Returns the path to the resource file - * - * @return string + * Returns the path to the resource file + * + * @return string */ protected function getResourceInfoPath() { @@ -146,14 +79,14 @@ abstract class Sabre_DAV_FSExt_Node extends Sabre_DAV_FS_Node implements Sabre_D } /** - * Returns all the stored resource information - * - * @return array + * Returns all the stored resource information + * + * @return array */ protected function getResourceData() { $path = $this->getResourceInfoPath(); - if (!file_exists($path)) return array('locks'=>array(), 'properties' => array()); + if (!file_exists($path)) return array('properties' => array()); // opening up the file, and creating a shared lock $handle = fopen($path,'r'); @@ -171,20 +104,19 @@ abstract class Sabre_DAV_FSExt_Node extends Sabre_DAV_FS_Node implements Sabre_D // Unserializing and checking if the resource file contains data for this file $data = unserialize($data); if (!isset($data[$this->getName()])) { - return array('locks'=>array(), 'properties' => array()); + return array('properties' => array()); } $data = $data[$this->getName()]; - if (!isset($data['locks'])) $data['locks'] = array(); if (!isset($data['properties'])) $data['properties'] = array(); return $data; } /** - * Updates the resource information - * - * @param array $newData + * Updates the resource information + * + * @param array $newData * @return void */ protected function putResourceData(array $newData) { @@ -238,6 +170,9 @@ abstract class Sabre_DAV_FSExt_Node extends Sabre_DAV_FS_Node implements Sabre_D } + /** + * @return bool + */ public function deleteResourceData() { // When we're deleting this node, we also need to delete any resource information @@ -264,6 +199,7 @@ abstract class Sabre_DAV_FSExt_Node extends Sabre_DAV_FS_Node implements Sabre_D fwrite($handle,serialize($data)); fclose($handle); + return true; } public function delete() { diff --git a/3rdparty/Sabre/DAV/File.php b/3rdparty/Sabre/DAV/File.php index b74bd9525b3..3126bd8d364 100644..100755 --- a/3rdparty/Sabre/DAV/File.php +++ b/3rdparty/Sabre/DAV/File.php @@ -4,12 +4,12 @@ * File class * * This is a helper class, that should aid in getting file classes setup. - * Most of its methods are implemented, and throw permission denied exceptions - * + * Most of its methods are implemented, and throw permission denied exceptions + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_File extends Sabre_DAV_Node implements Sabre_DAV_IFile { @@ -18,33 +18,33 @@ abstract class Sabre_DAV_File extends Sabre_DAV_Node implements Sabre_DAV_IFile * Updates the data * * data is a readable stream resource. - * - * @param resource $data - * @return void + * + * @param resource $data + * @return void */ - public function put($data) { + public function put($data) { throw new Sabre_DAV_Exception_Forbidden('Permission denied to change data'); } /** - * Returns the data + * Returns the data * * This method may either return a string or a readable stream resource * - * @return mixed + * @return mixed */ - public function get() { + public function get() { throw new Sabre_DAV_Exception_Forbidden('Permission denied to read this file'); } - + /** - * Returns the size of the file, in bytes. - * - * @return int + * Returns the size of the file, in bytes. + * + * @return int */ public function getSize() { @@ -56,9 +56,11 @@ abstract class Sabre_DAV_File extends Sabre_DAV_Node implements Sabre_DAV_IFile * Returns the ETag for a file * * An ETag is a unique identifier representing the current version of the file. If the file changes, the ETag MUST change. - * The ETag is an arbritrary string, but MUST be surrounded by double-quotes. + * The ETag is an arbitrary string, but MUST be surrounded by double-quotes. * * Return null if the ETag can not effectively be determined + * + * @return string|null */ public function getETag() { @@ -70,7 +72,9 @@ abstract class Sabre_DAV_File extends Sabre_DAV_Node implements Sabre_DAV_IFile * Returns the mime-type for a file * * If null is returned, we'll assume application/octet-stream - */ + * + * @return string|null + */ public function getContentType() { return null; diff --git a/3rdparty/Sabre/DAV/ICollection.php b/3rdparty/Sabre/DAV/ICollection.php index 0667d88899d..4626038a66e 100644..100755 --- a/3rdparty/Sabre/DAV/ICollection.php +++ b/3rdparty/Sabre/DAV/ICollection.php @@ -3,54 +3,70 @@ /** * The ICollection Interface * - * This interface should be implemented by each class that represents a collection - * + * This interface should be implemented by each class that represents a collection + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. + * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ interface Sabre_DAV_ICollection extends Sabre_DAV_INode { /** - * Creates a new file in the directory - * - * data is a readable stream resource + * Creates a new file in the directory * - * @param string $name Name of the file - * @param resource $data Initial payload - * @return void + * Data will either be supplied as a stream resource, or in certain cases + * as a string. Keep in mind that you may have to support either. + * + * After succesful creation of the file, you may choose to return the ETag + * of the new file here. + * + * The returned ETag must be surrounded by double-quotes (The quotes should + * be part of the actual string). + * + * If you cannot accurately determine the ETag, you should not return it. + * If you don't store the file exactly as-is (you're transforming it + * somehow) you should also not return an ETag. + * + * This means that if a subsequent GET to this new file does not exactly + * return the same contents of what was submitted here, you are strongly + * recommended to omit the ETag. + * + * @param string $name Name of the file + * @param resource|string $data Initial payload + * @return null|string */ function createFile($name, $data = null); /** - * Creates a new subdirectory - * - * @param string $name + * Creates a new subdirectory + * + * @param string $name * @return void */ function createDirectory($name); /** - * Returns a specific child node, referenced by its name - * - * @param string $name - * @return Sabre_DAV_INode + * Returns a specific child node, referenced by its name + * + * @param string $name + * @return Sabre_DAV_INode */ function getChild($name); /** - * Returns an array with all the child nodes - * - * @return Sabre_DAV_INode[] + * Returns an array with all the child nodes + * + * @return Sabre_DAV_INode[] */ function getChildren(); /** - * Checks if a child-node with the specified name exists - * - * @return bool + * Checks if a child-node with the specified name exists + * + * @param string $name + * @return bool */ function childExists($name); diff --git a/3rdparty/Sabre/DAV/IExtendedCollection.php b/3rdparty/Sabre/DAV/IExtendedCollection.php index b8db1ab2f26..6ec345f9a62 100644..100755 --- a/3rdparty/Sabre/DAV/IExtendedCollection.php +++ b/3rdparty/Sabre/DAV/IExtendedCollection.php @@ -5,11 +5,11 @@ * * This interface can be used to create special-type of collection-resources * as defined by RFC 5689. - * + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. + * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ interface Sabre_DAV_IExtendedCollection extends Sabre_DAV_ICollection { @@ -17,7 +17,7 @@ interface Sabre_DAV_IExtendedCollection extends Sabre_DAV_ICollection { /** * Creates a new collection * - * @param string $name + * @param string $name * @param array $resourceType * @param array $properties * @return void diff --git a/3rdparty/Sabre/DAV/IFile.php b/3rdparty/Sabre/DAV/IFile.php index 446ec86187b..478f822ae71 100644..100755 --- a/3rdparty/Sabre/DAV/IFile.php +++ b/3rdparty/Sabre/DAV/IFile.php @@ -1,34 +1,48 @@ <?php /** - * This interface represents a file or leaf in the tree. + * This interface represents a file in the directory tree + * + * A file is a bit of a broad definition. In general it implies that on + * this specific node a PUT or GET method may be performed, to either update, + * or retrieve the contents of the file. * - * The nature of a file is, as you might be aware of, that it doesn't contain sub-nodes and has contents - * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. + * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ interface Sabre_DAV_IFile extends Sabre_DAV_INode { /** - * Updates the data - * + * Updates the data + * * The data argument is a readable stream resource. * - * @param resource $data - * @return void + * After a succesful put operation, you may choose to return an ETag. The + * etag must always be surrounded by double-quotes. These quotes must + * appear in the actual string you're returning. + * + * Clients may use the ETag from a PUT request to later on make sure that + * when they update the file, the contents haven't changed in the mean + * time. + * + * If you don't plan to store the file byte-by-byte, and you return a + * different object on a subsequent GET you are strongly recommended to not + * return an ETag, and just return null. + * + * @param resource $data + * @return string|null */ function put($data); /** - * Returns the data - * + * Returns the data + * * This method may either return a string or a readable stream resource * - * @return mixed + * @return mixed */ function get(); @@ -36,7 +50,7 @@ interface Sabre_DAV_IFile extends Sabre_DAV_INode { * Returns the mime-type for a file * * If null is returned, we'll assume application/octet-stream - * + * * @return void */ function getContentType(); @@ -47,15 +61,15 @@ interface Sabre_DAV_IFile extends Sabre_DAV_INode { * An ETag is a unique identifier representing the current version of the file. If the file changes, the ETag MUST change. * * Return null if the ETag can not effectively be determined - * + * * @return void */ function getETag(); /** - * Returns the size of the node, in bytes - * - * @return int + * Returns the size of the node, in bytes + * + * @return int */ function getSize(); diff --git a/3rdparty/Sabre/DAV/ILockable.php b/3rdparty/Sabre/DAV/ILockable.php deleted file mode 100644 index f9fb3a70251..00000000000 --- a/3rdparty/Sabre/DAV/ILockable.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php - -/** - * Implement this class to support locking - * - * @package Sabre - * @subpackage DAV - * @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 - */ -interface Sabre_DAV_ILockable extends Sabre_DAV_INode { - - /** - * Returns an array with locks currently on the node - * - * @return Sabre_DAV_Locks_LockInfo[] - */ - function getLocks(); - - /** - * Creates a new lock on the file. - * - * @param Sabre_DAV_Locks_LockInfo $lockInfo The lock information - * @return void - */ - function lock(Sabre_DAV_Locks_LockInfo $lockInfo); - - /** - * Unlocks a file - * - * @param Sabre_DAV_Locks_LockInfo $lockInfo The lock information - * @return void - */ - function unlock(Sabre_DAV_Locks_LockInfo $lockInfo); - -} - diff --git a/3rdparty/Sabre/DAV/INode.php b/3rdparty/Sabre/DAV/INode.php index c0b96bf5377..c57d3923105 100644..100755 --- a/3rdparty/Sabre/DAV/INode.php +++ b/3rdparty/Sabre/DAV/INode.php @@ -2,11 +2,11 @@ /** * The INode interface is the base interface, and the parent class of both ICollection and IFile - * + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. + * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ interface Sabre_DAV_INode { @@ -14,14 +14,16 @@ interface Sabre_DAV_INode { /** * Deleted the current node * - * @return void + * @return void */ function delete(); /** - * Returns the name of the node - * - * @return string + * Returns the name of the node. + * + * This is used to generate the url. + * + * @return string */ function getName(); @@ -34,9 +36,9 @@ interface Sabre_DAV_INode { function setName($name); /** - * Returns the last modification time, as a unix timestamp - * - * @return int + * Returns the last modification time, as a unix timestamp + * + * @return int */ function getLastModified(); diff --git a/3rdparty/Sabre/DAV/IProperties.php b/3rdparty/Sabre/DAV/IProperties.php index af17cad24af..38eaab16dad 100644..100755 --- a/3rdparty/Sabre/DAV/IProperties.php +++ b/3rdparty/Sabre/DAV/IProperties.php @@ -4,11 +4,11 @@ * IProperties interface * * Implement this interface to support custom WebDAV properties requested and sent from clients. - * + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. + * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ interface Sabre_DAV_IProperties extends Sabre_DAV_INode { @@ -26,7 +26,7 @@ interface Sabre_DAV_IProperties extends Sabre_DAV_INode { * If the operation was successful, true can be returned. * If the operation failed, false can be returned. * - * Deletion of a non-existant property is always succesful. + * Deletion of a non-existent property is always successful. * * Lastly, it is optional to return detailed information about any * failures. In this case an array should be returned with the following @@ -41,12 +41,12 @@ interface Sabre_DAV_IProperties extends Sabre_DAV_INode { * ) * ) * - * In this example it was forbidden to update {DAV:}displayname. + * In this example it was forbidden to update {DAV:}displayname. * (403 Forbidden), which in turn also caused {DAV:}owner to fail * (424 Failed Dependency) because the request needs to be atomic. * - * @param array $mutations - * @return bool|array + * @param array $mutations + * @return bool|array */ function updateProperties($mutations); @@ -58,7 +58,7 @@ interface Sabre_DAV_IProperties extends Sabre_DAV_INode { * * If the array is empty, it means 'all properties' were requested. * - * @param array $properties + * @param array $properties * @return void */ function getProperties($properties); diff --git a/3rdparty/Sabre/DAV/IQuota.php b/3rdparty/Sabre/DAV/IQuota.php index 8ff1a4597f8..3fe4c4eced4 100644..100755 --- a/3rdparty/Sabre/DAV/IQuota.php +++ b/3rdparty/Sabre/DAV/IQuota.php @@ -4,13 +4,13 @@ * IQuota interface * * Implement this interface to add the ability to return quota information. The ObjectTree - * will check for quota information on any given node. If the information is not available it will + * will check for quota information on any given node. If the information is not available it will * attempt to fetch the information from the root node. - * + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. + * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ interface Sabre_DAV_IQuota extends Sabre_DAV_ICollection { @@ -21,7 +21,7 @@ interface Sabre_DAV_IQuota extends Sabre_DAV_ICollection { * This method MUST return an array with 2 values, the first being the total used space, * the second the available space (in bytes) */ - function getQuotaInfo(); + function getQuotaInfo(); } diff --git a/3rdparty/Sabre/DAV/Locks/Backend/Abstract.php b/3rdparty/Sabre/DAV/Locks/Backend/Abstract.php index b09f93ddac7..127e643a2b9 100644..100755 --- a/3rdparty/Sabre/DAV/Locks/Backend/Abstract.php +++ b/3rdparty/Sabre/DAV/Locks/Backend/Abstract.php @@ -4,45 +4,45 @@ * The Lock manager allows you to handle all file-locks centrally. * * This is an alternative approach to doing this on a per-node basis - * + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_Locks_Backend_Abstract { /** - * Returns a list of Sabre_DAV_Locks_LockInfo objects - * + * 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 string $uri * @param bool $returnChildLocks - * @return array + * @return array */ abstract function getLocks($uri, $returnChildLocks); /** - * Locks a uri - * - * @param string $uri - * @param Sabre_DAV_Locks_LockInfo $lockInfo - * @return bool + * Locks a uri + * + * @param string $uri + * @param Sabre_DAV_Locks_LockInfo $lockInfo + * @return bool */ abstract function lock($uri,Sabre_DAV_Locks_LockInfo $lockInfo); /** - * Removes a lock from a uri - * - * @param string $uri - * @param Sabre_DAV_Locks_LockInfo $lockInfo - * @return bool + * Removes a lock from a uri + * + * @param string $uri + * @param Sabre_DAV_Locks_LockInfo $lockInfo + * @return bool */ abstract function unlock($uri,Sabre_DAV_Locks_LockInfo $lockInfo); diff --git a/3rdparty/Sabre/DAV/Locks/Backend/FS.php b/3rdparty/Sabre/DAV/Locks/Backend/FS.php index 8653f55b1c6..02cab87fc82 100644..100755 --- a/3rdparty/Sabre/DAV/Locks/Backend/FS.php +++ b/3rdparty/Sabre/DAV/Locks/Backend/FS.php @@ -1,28 +1,30 @@ <?php /** - * The Lock manager allows you to handle all file-locks centrally. + * This Lock Backend stores all its data in the filesystem in separate file per + * node. * - * 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. + * 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. + * + * This also means that using this backend means you will not pass the Neon + * Litmus test. * * 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 * @deprecated - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_Locks_Backend_FS extends Sabre_DAV_Locks_Backend_Abstract { /** - * The default data directory - * - * @var string + * The default data directory + * + * @var string */ private $dataDir; @@ -40,17 +42,17 @@ class Sabre_DAV_Locks_Backend_FS extends Sabre_DAV_Locks_Backend_Abstract { /** - * Returns a list of Sabre_DAV_Locks_LockInfo objects - * + * 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 string $uri * @param bool $returnChildLocks - * @return array + * @return array */ public function getLocks($uri, $returnChildLocks) { @@ -59,15 +61,15 @@ class Sabre_DAV_Locks_Backend_FS extends Sabre_DAV_Locks_Backend_Abstract { foreach(explode('/',$uri) as $uriPart) { - // weird algorithm that can probably be improved, but we're traversing the path top down - if ($currentPath) $currentPath.='/'; + // weird algorithm that can probably be improved, but we're traversing the path top down + if ($currentPath) $currentPath.='/'; $currentPath.=$uriPart; $uriLocks = $this->getData($currentPath); 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; @@ -79,18 +81,18 @@ class Sabre_DAV_Locks_Backend_FS extends Sabre_DAV_Locks_Backend_Abstract { // Checking if we can remove any of these locks foreach($lockList as $k=>$lock) { - if (time() > $lock->timeout + $lock->created) unset($lockList[$k]); + if (time() > $lock->timeout + $lock->created) unset($lockList[$k]); } return $lockList; } /** - * Locks a uri - * - * @param string $uri - * @param Sabre_DAV_Locks_LockInfo $lockInfo - * @return bool + * Locks a uri + * + * @param string $uri + * @param Sabre_DAV_Locks_LockInfo $lockInfo + * @return bool */ public function lock($uri,Sabre_DAV_Locks_LockInfo $lockInfo) { @@ -109,11 +111,11 @@ class Sabre_DAV_Locks_Backend_FS extends Sabre_DAV_Locks_Backend_Abstract { } /** - * Removes a lock from a uri - * - * @param string $uri - * @param Sabre_DAV_Locks_LockInfo $lockInfo - * @return bool + * 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) { @@ -136,7 +138,7 @@ class Sabre_DAV_Locks_Backend_FS extends Sabre_DAV_Locks_Backend_Abstract { * Returns the stored data for a uri * * @param string $uri - * @return array + * @return array */ protected function getData($uri) { @@ -167,7 +169,7 @@ class Sabre_DAV_Locks_Backend_FS extends Sabre_DAV_Locks_Backend_Abstract { * Updates the lock information * * @param string $uri - * @param array $newData + * @param array $newData * @return void */ protected function putData($uri,array $newData) { diff --git a/3rdparty/Sabre/DAV/Locks/Backend/File.php b/3rdparty/Sabre/DAV/Locks/Backend/File.php index f65b20c4306..c33f963514b 100644..100755 --- a/3rdparty/Sabre/DAV/Locks/Backend/File.php +++ b/3rdparty/Sabre/DAV/Locks/Backend/File.php @@ -3,30 +3,30 @@ /** * The Lock manager allows you to handle all file-locks centrally. * - * This Lock Manager stores all its data in a single file. + * This Lock Manager stores all its data in a single file. * * Note that this is not nearly as robust as a database, you are encouraged * to use the PDO backend instead. * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_Locks_Backend_File extends Sabre_DAV_Locks_Backend_Abstract { /** * The storage file - * - * @var string + * + * @var string */ private $locksFile; /** * Constructor * - * @param string $locksFile path to file + * @param string $locksFile path to file */ public function __construct($locksFile) { @@ -35,24 +35,24 @@ class Sabre_DAV_Locks_Backend_File extends Sabre_DAV_Locks_Backend_Abstract { } /** - * Returns a list of Sabre_DAV_Locks_LockInfo objects - * + * 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 string $uri * @param bool $returnChildLocks - * @return array + * @return array */ public function getLocks($uri, $returnChildLocks) { $newLocks = array(); - $currentPath = ''; $locks = $this->getData(); + foreach($locks as $lock) { if ($lock->uri === $uri || @@ -70,29 +70,35 @@ class Sabre_DAV_Locks_Backend_File extends Sabre_DAV_Locks_Backend_Abstract { // Checking if we can remove any of these locks foreach($newLocks as $k=>$lock) { - if (time() > $lock->timeout + $lock->created) unset($newLocks[$k]); + 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 + * Locks a uri + * + * @param string $uri + * @param Sabre_DAV_Locks_LockInfo $lockInfo + * @return bool */ - public function lock($uri,Sabre_DAV_Locks_LockInfo $lockInfo) { + 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); + $locks = $this->getData(); + foreach($locks as $k=>$lock) { - if ($lock->token == $lockInfo->token) unset($locks[$k]); + if ( + ($lock->token == $lockInfo->token) || + (time() > $lock->timeout + $lock->created) + ) { + unset($locks[$k]); + } } $locks[] = $lockInfo; $this->putData($locks); @@ -101,15 +107,15 @@ class Sabre_DAV_Locks_Backend_File extends Sabre_DAV_Locks_Backend_Abstract { } /** - * Removes a lock from a uri - * - * @param string $uri - * @param Sabre_DAV_Locks_LockInfo $lockInfo - * @return bool + * 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) { + public function unlock($uri, Sabre_DAV_Locks_LockInfo $lockInfo) { - $locks = $this->getLocks($uri,false); + $locks = $this->getData(); foreach($locks as $k=>$lock) { if ($lock->token == $lockInfo->token) { @@ -127,7 +133,7 @@ class Sabre_DAV_Locks_Backend_File extends Sabre_DAV_Locks_Backend_Abstract { /** * Loads the lockdata from the filesystem. * - * @return array + * @return array */ protected function getData() { @@ -153,7 +159,7 @@ class Sabre_DAV_Locks_Backend_File extends Sabre_DAV_Locks_Backend_Abstract { /** * Saves the lockdata * - * @param array $newData + * @param array $newData * @return void */ protected function putData(array $newData) { diff --git a/3rdparty/Sabre/DAV/Locks/Backend/PDO.php b/3rdparty/Sabre/DAV/Locks/Backend/PDO.php index c3923af19d3..acce80638ec 100644..100755 --- a/3rdparty/Sabre/DAV/Locks/Backend/PDO.php +++ b/3rdparty/Sabre/DAV/Locks/Backend/PDO.php @@ -5,34 +5,34 @@ * * This Lock Manager stores all its data in a database. You must pass a PDO * connection object in the constructor. - * + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_Locks_Backend_PDO extends Sabre_DAV_Locks_Backend_Abstract { /** - * The PDO connection object - * - * @var pdo + * The PDO connection object + * + * @var pdo */ private $pdo; /** - * The PDO tablename this backend uses. - * + * The PDO tablename this backend uses. + * * @var string */ protected $tableName; /** - * Constructor - * + * Constructor + * * @param PDO $pdo - * @param string $tableName + * @param string $tableName */ public function __construct(PDO $pdo, $tableName = 'locks') { @@ -42,24 +42,24 @@ class Sabre_DAV_Locks_Backend_PDO extends Sabre_DAV_Locks_Backend_Abstract { } /** - * Returns a list of Sabre_DAV_Locks_LockInfo objects - * + * 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 string $uri * @param bool $returnChildLocks - * @return array + * @return array */ 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 + // NOTE: the following 10 lines or so could be easily replaced by + // pure sql. MySQL's non-standard string concatenation prevents us // from doing this though. - $query = 'SELECT owner, token, timeout, created, scope, depth, uri FROM `'.$this->tableName.'` WHERE ((created + timeout) > CAST(? AS UNSIGNED INTEGER)) AND ((uri = ?)'; + $query = 'SELECT owner, token, timeout, created, scope, depth, uri FROM '.$this->tableName.' WHERE ((created + timeout) > CAST(? AS UNSIGNED INTEGER)) AND ((uri = ?)'; $params = array(time(),$uri); // We need to check locks for every part in the uri. @@ -112,11 +112,11 @@ class Sabre_DAV_Locks_Backend_PDO extends Sabre_DAV_Locks_Backend_Abstract { } /** - * Locks a uri - * - * @param string $uri - * @param Sabre_DAV_Locks_LockInfo $lockInfo - * @return bool + * Locks a uri + * + * @param string $uri + * @param Sabre_DAV_Locks_LockInfo $lockInfo + * @return bool */ public function lock($uri,Sabre_DAV_Locks_LockInfo $lockInfo) { @@ -127,15 +127,15 @@ class Sabre_DAV_Locks_Backend_PDO extends Sabre_DAV_Locks_Backend_Abstract { $locks = $this->getLocks($uri,false); $exists = false; - foreach($locks as $k=>$lock) { + foreach($locks as $lock) { if ($lock->token == $lockInfo->token) $exists = true; } - + if ($exists) { - $stmt = $this->pdo->prepare('UPDATE `'.$this->tableName.'` SET owner = ?, timeout = ?, scope = ?, depth = ?, uri = ?, created = ? WHERE token = ?'); + $stmt = $this->pdo->prepare('UPDATE '.$this->tableName.' SET owner = ?, timeout = ?, scope = ?, depth = ?, uri = ?, created = ? WHERE token = ?'); $stmt->execute(array($lockInfo->owner,$lockInfo->timeout,$lockInfo->scope,$lockInfo->depth,$uri,$lockInfo->created,$lockInfo->token)); } else { - $stmt = $this->pdo->prepare('INSERT INTO `'.$this->tableName.'` (owner,timeout,scope,depth,uri,created,token) VALUES (?,?,?,?,?,?,?)'); + $stmt = $this->pdo->prepare('INSERT INTO '.$this->tableName.' (owner,timeout,scope,depth,uri,created,token) VALUES (?,?,?,?,?,?,?)'); $stmt->execute(array($lockInfo->owner,$lockInfo->timeout,$lockInfo->scope,$lockInfo->depth,$uri,$lockInfo->created,$lockInfo->token)); } @@ -146,15 +146,15 @@ class Sabre_DAV_Locks_Backend_PDO extends Sabre_DAV_Locks_Backend_Abstract { /** - * Removes a lock from a uri - * - * @param string $uri - * @param Sabre_DAV_Locks_LockInfo $lockInfo - * @return bool + * 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) { - $stmt = $this->pdo->prepare('DELETE FROM `'.$this->tableName.'` WHERE uri = ? AND token = ?'); + $stmt = $this->pdo->prepare('DELETE FROM '.$this->tableName.' WHERE uri = ? AND token = ?'); $stmt->execute(array($uri,$lockInfo->token)); return $stmt->rowCount()===1; diff --git a/3rdparty/Sabre/DAV/Locks/LockInfo.php b/3rdparty/Sabre/DAV/Locks/LockInfo.php index 6a064466f40..9df014a4281 100644..100755 --- a/3rdparty/Sabre/DAV/Locks/LockInfo.php +++ b/3rdparty/Sabre/DAV/Locks/LockInfo.php @@ -5,11 +5,11 @@ * * An object of the LockInfo class holds all the information relevant to a * single lock. - * + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_Locks_LockInfo { @@ -30,37 +30,37 @@ class Sabre_DAV_Locks_LockInfo { const TIMEOUT_INFINITE = -1; /** - * The owner of the lock - * - * @var string + * The owner of the lock + * + * @var string */ public $owner; /** - * The locktoken - * - * @var string + * The locktoken + * + * @var string */ public $token; /** - * How long till the lock is expiring - * - * @var int + * How long till the lock is expiring + * + * @var int */ public $timeout; /** - * UNIX Timestamp of when this lock was created - * - * @var int + * UNIX Timestamp of when this lock was created + * + * @var int */ public $created; /** - * Exclusive or shared lock - * - * @var int + * Exclusive or shared lock + * + * @var int */ public $scope = self::EXCLUSIVE; @@ -72,7 +72,7 @@ class Sabre_DAV_Locks_LockInfo { /** * The uri this lock locks * - * TODO: This value is not always set + * TODO: This value is not always set * @var mixed */ public $uri; diff --git a/3rdparty/Sabre/DAV/Locks/Plugin.php b/3rdparty/Sabre/DAV/Locks/Plugin.php index 461e2847e0a..fd956950b8a 100644..100755 --- a/3rdparty/Sabre/DAV/Locks/Plugin.php +++ b/3rdparty/Sabre/DAV/Locks/Plugin.php @@ -9,38 +9,37 @@ * $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-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_Locks_Plugin extends Sabre_DAV_ServerPlugin { /** - * locksBackend - * - * @var Sabre_DAV_Locks_Backend_Abstract + * locksBackend + * + * @var Sabre_DAV_Locks_Backend_Abstract */ private $locksBackend; /** * server - * - * @var Sabre_DAV_Server + * + * @var Sabre_DAV_Server */ private $server; /** - * __construct - * - * @param Sabre_DAV_Locks_Backend_Abstract $locksBackend - * @return void + * __construct + * + * @param Sabre_DAV_Locks_Backend_Abstract $locksBackend */ public function __construct(Sabre_DAV_Locks_Backend_Abstract $locksBackend = null) { - $this->locksBackend = $locksBackend; + $this->locksBackend = $locksBackend; } @@ -48,8 +47,8 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin { * Initializes the plugin * * This method is automatically called by the Server class after addPlugin. - * - * @param Sabre_DAV_Server $server + * + * @param Sabre_DAV_Server $server * @return void */ public function initialize(Sabre_DAV_Server $server) { @@ -63,11 +62,11 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin { /** * Returns a plugin name. - * + * * Using this name other plugins will be able to access other plugins - * using Sabre_DAV_Server::getPlugin - * - * @return string + * using Sabre_DAV_Server::getPlugin + * + * @return string */ public function getPluginName() { @@ -76,20 +75,21 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin { } /** - * This method is called by the Server if the user used an HTTP method + * This method is called by the Server if the user used an HTTP method * the server didn't recognize. * * This plugin intercepts the LOCK and UNLOCK methods. - * - * @param string $method - * @return bool + * + * @param string $method + * @param string $uri + * @return bool */ public function unknownMethod($method, $uri) { - switch($method) { + switch($method) { - case 'LOCK' : $this->httpLock($uri); return false; - case 'UNLOCK' : $this->httpUnlock($uri); return false; + case 'LOCK' : $this->httpLock($uri); return false; + case 'UNLOCK' : $this->httpUnlock($uri); return false; } @@ -98,26 +98,20 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin { /** * This method is called after most properties have been found * it allows us to add in any Lock-related properties - * - * @param string $path - * @param array $properties - * @return bool + * + * @param string $path + * @param array $newProperties + * @return bool */ - public function afterGetProperties($path,&$newProperties) { + public function afterGetProperties($path, &$newProperties) { foreach($newProperties[404] as $propName=>$discard) { - $node = null; - switch($propName) { case '{DAV:}supportedlock' : $val = false; if ($this->locksBackend) $val = true; - else { - if (!$node) $node = $this->server->tree->getNodeForPath($path); - if ($node instanceof Sabre_DAV_ILockable) $val = true; - } $newProperties[200][$propName] = new Sabre_DAV_Property_SupportedLock($val); unset($newProperties[404][$propName]); break; @@ -141,10 +135,10 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin { * handled. * * This plugin uses that feature to intercept access to locked resources. - * + * * @param string $method * @param string $uri - * @return bool + * @return bool */ public function beforeMethod($method, $uri) { @@ -187,18 +181,17 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin { * Use this method to tell the server this plugin defines additional * HTTP methods. * - * This method is passed a uri. It should only return HTTP methods that are + * This method is passed a uri. It should only return HTTP methods that are * available for the specified uri. * * @param string $uri - * @return array + * @return array */ public function getHTTPMethods($uri) { - if ($this->locksBackend || - $this->server->tree->getNodeForPath($uri) instanceof Sabre_DAV_ILocks) { + if ($this->locksBackend) return array('LOCK','UNLOCK'); - } + return array(); } @@ -208,8 +201,8 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin { * * In this case this is only the number 2. The 2 in the Dav: header * indicates the server supports locks. - * - * @return array + * + * @return array */ public function getFeatures() { @@ -218,49 +211,23 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin { } /** - * Returns all lock information on a particular uri - * + * Returns all lock information on a particular uri + * * 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 + * 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 string $uri * @param bool $returnChildLocks - * @return array + * @return array */ public function getLocks($uri, $returnChildLocks = false) { $lockList = array(); - $currentPath = ''; - foreach(explode('/',$uri) as $uriPart) { - $uriLocks = array(); - if ($currentPath) $currentPath.='/'; - $currentPath.=$uriPart; - - try { - - $node = $this->server->tree->getNodeForPath($currentPath); - if ($node instanceof Sabre_DAV_ILockable) $uriLocks = $node->getLocks(); - - } catch (Sabre_DAV_Exception_FileNotFound $e){ - // In case the node didn't exist, this could be a lock-null request - } - - foreach($uriLocks as $uriLock) { - - // 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; - } - - } - - } - if ($this->locksBackend) + if ($this->locksBackend) $lockList = array_merge($lockList,$this->locksBackend->getLocks($uri, $returnChildLocks)); return $lockList; @@ -271,13 +238,13 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin { * Locks an uri * * The WebDAV lock request can be operated to either create a new lock on a file, or to refresh an existing lock - * If a new lock is created, a full XML body should be supplied, containing information about the lock such as the type + * If a new lock is created, a full XML body should be supplied, containing information about the lock such as the type * of lock (shared or exclusive) and the owner of the lock * * If a lock is to be refreshed, no body should be supplied and there should be a valid If header containing the lock * - * Additionally, a lock can be requested for a non-existant file. In these case we're obligated to create an empty file as per RFC4918:S7.3 - * + * Additionally, a lock can be requested for a non-existent file. In these case we're obligated to create an empty file as per RFC4918:S7.3 + * * @param string $uri * @return void */ @@ -297,7 +264,7 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin { if ($body = $this->server->httpRequest->getBody(true)) { // This is a new lock request $lockInfo = $this->parseLockRequest($body); - $lockInfo->depth = $this->server->getHTTPDepth(); + $lockInfo->depth = $this->server->getHTTPDepth(); $lockInfo->uri = $uri; if($lastLock && $lockInfo->scope != Sabre_DAV_Locks_LockInfo::SHARED) throw new Sabre_DAV_Exception_ConflictingLock($lastLock); @@ -306,11 +273,11 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin { // This must have been a lock refresh $lockInfo = $lastLock; - // The resource could have been locked through another uri. + // The resource could have been locked through another uri. if ($uri!=$lockInfo->uri) $uri = $lockInfo->uri; } else { - + // There was neither a lock refresh nor a new lock request throw new Sabre_DAV_Exception_BadRequest('An xml body is required for lock requests'); @@ -322,16 +289,16 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin { // If we got this far.. we should go check if this node actually exists. If this is not the case, we need to create it first try { - $node = $this->server->tree->getNodeForPath($uri); - + $this->server->tree->getNodeForPath($uri); + // We need to call the beforeWriteContent event for RFC3744 $this->server->broadcastEvent('beforeWriteContent',array($uri)); - } catch (Sabre_DAV_Exception_FileNotFound $e) { - + } catch (Sabre_DAV_Exception_NotFound $e) { + // It didn't, lets create it - $this->server->createFile($uri,fopen('php://memory','r')); - $newFile = true; + $this->server->createFile($uri,fopen('php://memory','r')); + $newFile = true; } @@ -362,7 +329,7 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin { $locks = $this->getLocks($uri); - // Windows sometimes forgets to include < and > in the Lock-Token + // Windows sometimes forgets to include < and > in the Lock-Token // header if ($lockToken[0]!=='<') $lockToken = '<' . $lockToken . '>'; @@ -370,7 +337,6 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin { if ('<opaquelocktoken:' . $lock->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); @@ -390,21 +356,15 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin { * * All the locking information is supplied in the lockInfo object. The object has a suggested timeout, but this can be safely ignored * It is important that if the existing timeout is ignored, the property is overwritten, as this needs to be sent back to the client - * - * @param string $uri - * @param Sabre_DAV_Locks_LockInfo $lockInfo - * @return void + * + * @param string $uri + * @param Sabre_DAV_Locks_LockInfo $lockInfo + * @return bool */ public function lockNode($uri,Sabre_DAV_Locks_LockInfo $lockInfo) { if (!$this->server->broadcastEvent('beforeLock',array($uri,$lockInfo))) return; - try { - $node = $this->server->tree->getNodeForPath($uri); - if ($node instanceof Sabre_DAV_ILockable) return $node->lock($lockInfo); - } catch (Sabre_DAV_Exception_FileNotFound $e) { - // In case the node didn't exist, this could be a lock-null request - } if ($this->locksBackend) return $this->locksBackend->lock($uri,$lockInfo); throw new Sabre_DAV_Exception_MethodNotAllowed('Locking support is not enabled for this resource. No Locking backend was found so if you didn\'t expect this error, please check your configuration.'); @@ -414,29 +374,22 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin { * Unlocks a uri * * This method removes a lock from a uri. It is assumed all the supplied information is correct and verified - * - * @param string $uri - * @param Sabre_DAV_Locks_LockInfo $lockInfo - * @return void + * + * @param string $uri + * @param Sabre_DAV_Locks_LockInfo $lockInfo + * @return bool */ public function unlockNode($uri,Sabre_DAV_Locks_LockInfo $lockInfo) { if (!$this->server->broadcastEvent('beforeUnlock',array($uri,$lockInfo))) return; - try { - $node = $this->server->tree->getNodeForPath($uri); - if ($node instanceof Sabre_DAV_ILockable) return $node->unlock($lockInfo); - } catch (Sabre_DAV_Exception_FileNotFound $e) { - // In case the node didn't exist, this could be a lock-null request - } - if ($this->locksBackend) return $this->locksBackend->unlock($uri,$lockInfo); } /** - * Returns the contents of the HTTP Timeout header. - * + * Returns the contents of the HTTP Timeout header. + * * The method formats the header into an integer. * * @return int @@ -444,7 +397,7 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin { public function getTimeoutHeader() { $header = $this->server->httpRequest->getHeader('Timeout'); - + if ($header) { if (stripos($header,'second-')===0) $header = (int)(substr($header,7)); @@ -462,16 +415,16 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin { } /** - * Generates the response for successfull LOCK requests - * - * @param Sabre_DAV_Locks_LockInfo $lockInfo - * @return string + * Generates the response for successful LOCK requests + * + * @param Sabre_DAV_Locks_LockInfo $lockInfo + * @return string */ protected function generateLockResponse(Sabre_DAV_Locks_LockInfo $lockInfo) { $dom = new DOMDocument('1.0','utf-8'); $dom->formatOutput = true; - + $prop = $dom->createElementNS('DAV:','d:prop'); $dom->appendChild($prop); @@ -484,10 +437,10 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin { return $dom->saveXML(); } - + /** * validateLock should be called when a write operation is about to happen - * It will check if the requested url is locked, and see if the correct lock tokens are passed + * It will check if the requested url is locked, and see if the correct lock tokens are passed * * @param mixed $urls List of relevant urls. Can be an array, a string or nothing at all for the current request uri * @param mixed $lastLock This variable will be populated with the last checked lock object (Sabre_DAV_Locks_LockInfo) @@ -511,13 +464,13 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin { $locks = $this->getLocks($url, $checkChildLocks); - // If there were no conditions, but there were locks, we fail + // If there were no conditions, but there were locks, we fail if (!$conditions && $locks) { reset($locks); $lastLock = current($locks); return false; } - + // If there were no locks or conditions, we go to the next url if (!$locks && !$conditions) continue; @@ -542,7 +495,7 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin { // key 2 can contain an etag if ($conditionToken[2]) { - $uri = $conditionUri?$conditionUri:$this->server->getRequestUri(); + $uri = $conditionUri?$conditionUri:$this->server->getRequestUri(); $node = $this->server->tree->getNodeForPath($uri); $etagValid = $node->getETag()==$conditionToken[2]; @@ -609,23 +562,23 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin { * This method is created to extract information from the WebDAV HTTP 'If:' header * * 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 + * The function will return an array, containing structs with the following keys * - * * uri - the uri the condition applies to. If this is returned as an + * * 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) + * * tokens - The lock token. another 2 dimensional array containing 2 elements (0 = true/false.. If this is a negative condition its set to false, 1 = the actual token) * * etag - an etag, if supplied - * - * @return void + * + * @return array */ public function getIfConditions() { - $header = $this->server->httpRequest->getHeader('If'); + $header = $this->server->httpRequest->getHeader('If'); if (!$header) return array(); $matches = array(); - $regex = '/(?:\<(?P<uri>.*?)\>\s)?\((?P<not>Not\s)?(?:\<(?P<token>[^\>]*)\>)?(?:\s?)(?:\[(?P<etag>[^\]]*)\])?\)/im'; + $regex = '/(?:\<(?P<uri>.*?)\>\s)?\((?P<not>Not\s)?(?:\<(?P<token>[^\>]*)\>)?(?:\s?)(?:\[(?P<etag>[^\]]*)\])?\)/im'; preg_match_all($regex,$header,$matches,PREG_SET_ORDER); $conditions = array(); @@ -636,7 +589,7 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin { 'uri' => $match['uri'], 'tokens' => array( array($match['not']?0:1,$match['token'],isset($match['etag'])?$match['etag']:'') - ), + ), ); if (!$condition['uri'] && count($conditions)) $conditions[count($conditions)-1]['tokens'][] = array( @@ -655,9 +608,9 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin { } /** - * Parses a webdav lock xml body, and returns a new Sabre_DAV_Locks_LockInfo object - * - * @param string $body + * Parses a webdav lock xml body, and returns a new Sabre_DAV_Locks_LockInfo object + * + * @param string $body * @return Sabre_DAV_Locks_LockInfo */ protected function parseLockRequest($body) { diff --git a/3rdparty/Sabre/DAV/Mount/Plugin.php b/3rdparty/Sabre/DAV/Mount/Plugin.php index f93a1aa25a1..b37a90ae993 100644..100755 --- a/3rdparty/Sabre/DAV/Mount/Plugin.php +++ b/3rdparty/Sabre/DAV/Mount/Plugin.php @@ -4,25 +4,25 @@ * This plugin provides support for RFC4709: Mounting WebDAV servers * * Simply append ?mount to any collection to generate the davmount response. - * + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. + * @author Evert Pot (http://www.rooftopsolutions.nl/) */ class Sabre_DAV_Mount_Plugin extends Sabre_DAV_ServerPlugin { /** - * Reference to Server class - * - * @var Sabre_DAV_Server + * Reference to Server class + * + * @var Sabre_DAV_Server */ private $server; /** - * Initializes the plugin and registers event handles - * - * @param Sabre_DAV_Server $server + * Initializes the plugin and registers event handles + * + * @param Sabre_DAV_Server $server * @return void */ public function initialize(Sabre_DAV_Server $server) { @@ -35,9 +35,10 @@ class Sabre_DAV_Mount_Plugin extends Sabre_DAV_ServerPlugin { /** * 'beforeMethod' event handles. This event handles intercepts GET requests ending * with ?mount - * - * @param string $method - * @return void + * + * @param string $method + * @param string $uri + * @return bool */ public function beforeMethod($method, $uri) { @@ -57,13 +58,13 @@ class Sabre_DAV_Mount_Plugin extends Sabre_DAV_ServerPlugin { } /** - * Generates the davmount response - * - * @param string $uri absolute uri + * Generates the davmount response + * + * @param string $uri absolute uri * @return void */ public function davMount($uri) { - + $this->server->httpResponse->sendStatus(200); $this->server->httpResponse->setHeader('Content-Type','application/davmount+xml'); ob_start(); diff --git a/3rdparty/Sabre/DAV/Node.php b/3rdparty/Sabre/DAV/Node.php index 0510df5fdf2..070b7176afd 100644..100755 --- a/3rdparty/Sabre/DAV/Node.php +++ b/3rdparty/Sabre/DAV/Node.php @@ -3,22 +3,22 @@ /** * Node class * - * This is a helper class, that should aid in getting nodes setup. - * + * This is a helper class, that should aid in getting nodes setup. + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_Node implements Sabre_DAV_INode { /** - * Returns the last modification time + * Returns the last modification time * * In this case, it will simply return the current time * - * @return int + * @return int */ public function getLastModified() { @@ -30,7 +30,7 @@ abstract class Sabre_DAV_Node implements Sabre_DAV_INode { * Deleted the current node * * @throws Sabre_DAV_Exception_Forbidden - * @return void + * @return void */ public function delete() { @@ -40,7 +40,7 @@ abstract class Sabre_DAV_Node implements Sabre_DAV_INode { /** * Renames the node - * + * * @throws Sabre_DAV_Exception_Forbidden * @param string $name The new name * @return void diff --git a/3rdparty/Sabre/DAV/ObjectTree.php b/3rdparty/Sabre/DAV/ObjectTree.php index f12a3683705..bce51463900 100644..100755 --- a/3rdparty/Sabre/DAV/ObjectTree.php +++ b/3rdparty/Sabre/DAV/ObjectTree.php @@ -3,27 +3,27 @@ /** * ObjectTree class * - * This implementation of the Tree class makes use of the INode, IFile and ICollection API's - * + * This implementation of the Tree class makes use of the INode, IFile and ICollection API's + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_ObjectTree extends Sabre_DAV_Tree { /** - * The root node - * + * The root node + * * @var Sabre_DAV_ICollection */ protected $rootNode; /** - * This is the node cache. Accessed nodes are stored here - * - * @var array + * This is the node cache. Accessed nodes are stored here + * + * @var array */ protected $cache = array(); @@ -31,9 +31,8 @@ class Sabre_DAV_ObjectTree extends Sabre_DAV_Tree { * Creates the object * * This method expects the rootObject to be passed as a parameter - * - * @param Sabre_DAV_ICollection $rootNode - * @return void + * + * @param Sabre_DAV_ICollection $rootNode */ public function __construct(Sabre_DAV_ICollection $rootNode) { @@ -42,10 +41,10 @@ class Sabre_DAV_ObjectTree extends Sabre_DAV_Tree { } /** - * Returns the INode object for the requested path - * - * @param string $path - * @return Sabre_DAV_INode + * Returns the INode object for the requested path + * + * @param string $path + * @return Sabre_DAV_INode */ public function getNodeForPath($path) { @@ -54,17 +53,17 @@ class Sabre_DAV_ObjectTree extends Sabre_DAV_Tree { //if (!$path || $path=='.') return $this->rootNode; $currentNode = $this->rootNode; - $i=0; - // We're splitting up the path variable into folder/subfolder components and traverse to the correct node.. + + // We're splitting up the path variable into folder/subfolder components and traverse to the correct node.. foreach(explode('/',$path) as $pathPart) { // If this part of the path is just a dot, it actually means we can skip it if ($pathPart=='.' || $pathPart=='') continue; if (!($currentNode instanceof Sabre_DAV_ICollection)) - throw new Sabre_DAV_Exception_FileNotFound('Could not find node at path: ' . $path); + throw new Sabre_DAV_Exception_NotFound('Could not find node at path: ' . $path); - $currentNode = $currentNode->getChild($pathPart); + $currentNode = $currentNode->getChild($pathPart); } @@ -76,8 +75,8 @@ class Sabre_DAV_ObjectTree extends Sabre_DAV_Tree { /** * This function allows you to check if a node exists. * - * @param string $path - * @return bool + * @param string $path + * @return bool */ public function nodeExists($path) { @@ -92,7 +91,7 @@ class Sabre_DAV_ObjectTree extends Sabre_DAV_Tree { if (!$parentNode instanceof Sabre_DAV_ICollection) return false; return $parentNode->childExists($base); - } catch (Sabre_DAV_Exception_FileNotFound $e) { + } catch (Sabre_DAV_Exception_NotFound $e) { return false; @@ -101,10 +100,10 @@ class Sabre_DAV_ObjectTree extends Sabre_DAV_Tree { } /** - * Returns a list of childnodes for a given path. - * - * @param string $path - * @return array + * Returns a list of childnodes for a given path. + * + * @param string $path + * @return array */ public function getChildren($path) { @@ -127,14 +126,14 @@ class Sabre_DAV_ObjectTree extends Sabre_DAV_Tree { * * node creations * * copy * * move - * * renaming nodes - * + * * renaming nodes + * * If Tree classes implement a form of caching, this will allow * them to make sure caches will be expired. - * + * * If a path is passed, it is assumed that the entire subtree is dirty * - * @param string $path + * @param string $path * @return void */ public function markDirty($path) { @@ -145,7 +144,7 @@ class Sabre_DAV_ObjectTree extends Sabre_DAV_Tree { foreach($this->cache as $nodePath=>$node) { if ($nodePath == $path || strpos($nodePath,$path.'/')===0) unset($this->cache[$nodePath]); - + } } diff --git a/3rdparty/Sabre/DAV/Property.php b/3rdparty/Sabre/DAV/Property.php index 577535b0127..1cfada3236c 100644..100755 --- a/3rdparty/Sabre/DAV/Property.php +++ b/3rdparty/Sabre/DAV/Property.php @@ -4,16 +4,16 @@ * Abstract property class * * Extend this class to create custom complex properties - * + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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_Property { - abstract function serialize(Sabre_DAV_Server $server, DOMElement $prop); + abstract function serialize(Sabre_DAV_Server $server, DOMElement $prop); static function unserialize(DOMElement $prop) { diff --git a/3rdparty/Sabre/DAV/Property/GetLastModified.php b/3rdparty/Sabre/DAV/Property/GetLastModified.php index 4a812629971..bd63f573140 100644..100755 --- a/3rdparty/Sabre/DAV/Property/GetLastModified.php +++ b/3rdparty/Sabre/DAV/Property/GetLastModified.php @@ -2,33 +2,32 @@ /** * This property represents the {DAV:}getlastmodified property. - * + * * Although this is normally a simple property, windows requires us to add * some new attributes. * - * This class uses unix timestamps internally, and converts them to RFC 1123 times for + * This class uses unix timestamps internally, and converts them to RFC 1123 times for * serialization * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_Property_GetLastModified extends Sabre_DAV_Property { /** - * time - * - * @var int + * time + * + * @var int */ public $time; /** - * __construct - * - * @param int|DateTime $time - * @return void + * __construct + * + * @param int|DateTime $time */ public function __construct($time) { @@ -46,9 +45,10 @@ class Sabre_DAV_Property_GetLastModified extends Sabre_DAV_Property { } /** - * serialize - * - * @param DOMElement $prop + * serialize + * + * @param Sabre_DAV_Server $server + * @param DOMElement $prop * @return void */ public function serialize(Sabre_DAV_Server $server, DOMElement $prop) { @@ -56,14 +56,14 @@ class Sabre_DAV_Property_GetLastModified extends Sabre_DAV_Property { $doc = $prop->ownerDocument; $prop->setAttribute('xmlns:b','urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/'); $prop->setAttribute('b:dt','dateTime.rfc1123'); - $prop->nodeValue = $this->time->format(DateTime::RFC1123); + $prop->nodeValue = Sabre_HTTP_Util::toHTTPDate($this->time); } /** - * getTime - * - * @return DateTime + * getTime + * + * @return DateTime */ public function getTime() { diff --git a/3rdparty/Sabre/DAV/Property/Href.php b/3rdparty/Sabre/DAV/Property/Href.php index 3294ff2ac68..dac564f24d7 100644..100755 --- a/3rdparty/Sabre/DAV/Property/Href.php +++ b/3rdparty/Sabre/DAV/Property/Href.php @@ -3,36 +3,36 @@ /** * Href property * - * The href property represpents a url within a {DAV:}href element. + * The href property represents a url within a {DAV:}href element. * This is used by many WebDAV extensions, but not really within the WebDAV core spec - * + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_Property_Href extends Sabre_DAV_Property implements Sabre_DAV_Property_IHref { /** - * href - * - * @var string + * href + * + * @var string */ private $href; /** - * Automatically prefix the url with the server base directory - * - * @var bool + * Automatically prefix the url with the server base directory + * + * @var bool */ private $autoPrefix = true; /** - * __construct - * - * @param string $href - * @return void + * __construct + * + * @param string $href + * @param bool $autoPrefix */ public function __construct($href, $autoPrefix = true) { @@ -42,9 +42,9 @@ class Sabre_DAV_Property_Href extends Sabre_DAV_Property implements Sabre_DAV_Pr } /** - * Returns the uri - * - * @return string + * Returns the uri + * + * @return string */ public function getHref() { @@ -56,12 +56,12 @@ class Sabre_DAV_Property_Href extends Sabre_DAV_Property implements Sabre_DAV_Pr * Serializes this property. * * It will additionally prepend the href property with the server's base uri. - * - * @param Sabre_DAV_Server $server - * @param DOMElement $dom + * + * @param Sabre_DAV_Server $server + * @param DOMElement $dom * @return void */ - public function serialize(Sabre_DAV_Server $server,DOMElement $dom) { + public function serialize(Sabre_DAV_Server $server, DOMElement $dom) { $prefix = $server->xmlNamespaces['DAV:']; @@ -72,13 +72,13 @@ class Sabre_DAV_Property_Href extends Sabre_DAV_Property implements Sabre_DAV_Pr } /** - * Unserializes this property from a DOM Element + * Unserializes this property from a DOM Element * * This method returns an instance of this class. * It will only decode {DAV:}href values. For non-compatible elements null will be returned. * - * @param DOMElement $dom - * @return Sabre_DAV_Property_Href + * @param DOMElement $dom + * @return Sabre_DAV_Property_Href */ static function unserialize(DOMElement $dom) { @@ -86,6 +86,6 @@ class Sabre_DAV_Property_Href extends Sabre_DAV_Property implements Sabre_DAV_Pr return new self($dom->firstChild->textContent,false); } - } + } } diff --git a/3rdparty/Sabre/DAV/Property/HrefList.php b/3rdparty/Sabre/DAV/Property/HrefList.php index 76a5512901c..7a52272e885 100644..100755 --- a/3rdparty/Sabre/DAV/Property/HrefList.php +++ b/3rdparty/Sabre/DAV/Property/HrefList.php @@ -3,35 +3,35 @@ /** * HrefList property * - * This property contains multiple {DAV:}href elements, each containing a url. - * + * This property contains multiple {DAV:}href elements, each containing a url. + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_Property_HrefList extends Sabre_DAV_Property { /** - * hrefs - * - * @var array + * hrefs + * + * @var array */ private $hrefs; /** - * Automatically prefix the url with the server base directory - * - * @var bool + * Automatically prefix the url with the server base directory + * + * @var bool */ private $autoPrefix = true; /** - * __construct - * + * __construct + * * @param array $hrefs - * @param bool $autoPrefix + * @param bool $autoPrefix */ public function __construct(array $hrefs, $autoPrefix = true) { @@ -41,9 +41,9 @@ class Sabre_DAV_Property_HrefList extends Sabre_DAV_Property { } /** - * Returns the uris - * - * @return array + * Returns the uris + * + * @return array */ public function getHrefs() { @@ -55,9 +55,9 @@ class Sabre_DAV_Property_HrefList extends Sabre_DAV_Property { * Serializes this property. * * It will additionally prepend the href property with the server's base uri. - * - * @param Sabre_DAV_Server $server - * @param DOMElement $dom + * + * @param Sabre_DAV_Server $server + * @param DOMElement $dom * @return void */ public function serialize(Sabre_DAV_Server $server,DOMElement $dom) { @@ -73,13 +73,13 @@ class Sabre_DAV_Property_HrefList extends Sabre_DAV_Property { } /** - * Unserializes this property from a DOM Element + * 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 + * @param DOMElement $dom + * @return Sabre_DAV_Property_Href */ static function unserialize(DOMElement $dom) { @@ -91,6 +91,6 @@ class Sabre_DAV_Property_HrefList extends Sabre_DAV_Property { } return new self($hrefs, false); - } + } } diff --git a/3rdparty/Sabre/DAV/Property/IHref.php b/3rdparty/Sabre/DAV/Property/IHref.php index 29d76a44fcd..5c0409064cb 100644..100755 --- a/3rdparty/Sabre/DAV/Property/IHref.php +++ b/3rdparty/Sabre/DAV/Property/IHref.php @@ -9,16 +9,16 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. + * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ interface Sabre_DAV_Property_IHref { /** - * getHref - * - * @return string + * getHref + * + * @return string */ function getHref(); diff --git a/3rdparty/Sabre/DAV/Property/LockDiscovery.php b/3rdparty/Sabre/DAV/Property/LockDiscovery.php index 05c7470b4ed..2ded5649a44 100644..100755 --- a/3rdparty/Sabre/DAV/Property/LockDiscovery.php +++ b/3rdparty/Sabre/DAV/Property/LockDiscovery.php @@ -4,26 +4,26 @@ * Represents {DAV:}lockdiscovery property * * This property contains all the open locks on a given resource - * + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_Property_LockDiscovery extends Sabre_DAV_Property { /** - * locks - * - * @var array + * locks + * + * @var array */ public $locks; - + /** - * Should we show the locktoken as well? - * - * @var bool + * Should we show the locktoken as well? + * + * @var bool */ public $revealLockToken; @@ -36,13 +36,12 @@ class Sabre_DAV_Property_LockDiscovery extends Sabre_DAV_Property { static public $hideLockRoot = false; /** - * __construct - * - * @param array $locks - * @param bool $revealLockToken - * @return void + * __construct + * + * @param array $locks + * @param bool $revealLockToken */ - public function __construct($locks,$revealLockToken = false) { + public function __construct($locks, $revealLockToken = false) { $this->locks = $locks; $this->revealLockToken = $revealLockToken; @@ -50,12 +49,13 @@ class Sabre_DAV_Property_LockDiscovery extends Sabre_DAV_Property { } /** - * serialize - * - * @param DOMElement $prop + * serialize + * + * @param Sabre_DAV_Server $server + * @param DOMElement $prop * @return void */ - public function serialize(Sabre_DAV_Server $server,DOMElement $prop) { + public function serialize(Sabre_DAV_Server $server, DOMElement $prop) { $doc = $prop->ownerDocument; @@ -74,7 +74,7 @@ class Sabre_DAV_Property_LockDiscovery extends Sabre_DAV_Property { $lockType->appendChild($doc->createElementNS('DAV:','d:write')); - /* {DAV:}lockroot */ + /* {DAV:}lockroot */ if (!self::$hideLockRoot) { $lockRoot = $doc->createElementNS('DAV:','d:lockroot'); $activeLock->appendChild($lockRoot); @@ -91,7 +91,7 @@ class Sabre_DAV_Property_LockDiscovery extends Sabre_DAV_Property { $activeLock->appendChild($lockToken); $lockToken->appendChild($doc->createElementNS('DAV:','d:href','opaquelocktoken:' . $lock->token)); } - + $activeLock->appendChild($doc->createElementNS('DAV:','d:owner',$lock->owner)); } diff --git a/3rdparty/Sabre/DAV/Property/ResourceType.php b/3rdparty/Sabre/DAV/Property/ResourceType.php index 2c606c22d60..f6269611e54 100644..100755 --- a/3rdparty/Sabre/DAV/Property/ResourceType.php +++ b/3rdparty/Sabre/DAV/Property/ResourceType.php @@ -4,28 +4,27 @@ * This class represents the {DAV:}resourcetype property * * Normally for files this is empty, and for collection {DAV:}collection. - * However, other specs define different values for this. - * + * However, other specs define different values for this. + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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_Property_ResourceType extends Sabre_DAV_Property { /** - * resourceType - * + * resourceType + * * @var array */ public $resourceType = array(); /** - * __construct - * - * @param mixed $resourceType - * @return void + * __construct + * + * @param mixed $resourceType */ public function __construct($resourceType = array()) { @@ -33,7 +32,7 @@ class Sabre_DAV_Property_ResourceType extends Sabre_DAV_Property { $this->resourceType = array(); elseif ($resourceType === Sabre_DAV_Server::NODE_DIRECTORY) $this->resourceType = array('{DAV:}collection'); - elseif (is_array($resourceType)) + elseif (is_array($resourceType)) $this->resourceType = $resourceType; else $this->resourceType = array($resourceType); @@ -41,25 +40,26 @@ class Sabre_DAV_Property_ResourceType extends Sabre_DAV_Property { } /** - * serialize - * - * @param DOMElement $prop + * serialize + * + * @param Sabre_DAV_Server $server + * @param DOMElement $prop * @return void */ - public function serialize(Sabre_DAV_Server $server,DOMElement $prop) { + public function serialize(Sabre_DAV_Server $server, DOMElement $prop) { $propName = null; $rt = $this->resourceType; - + foreach($rt as $resourceType) { - if (preg_match('/^{([^}]*)}(.*)$/',$resourceType,$propName)) { - + if (preg_match('/^{([^}]*)}(.*)$/',$resourceType,$propName)) { + if (isset($server->xmlNamespaces[$propName[1]])) { $prop->appendChild($prop->ownerDocument->createElement($server->xmlNamespaces[$propName[1]] . ':' . $propName[2])); } else { $prop->appendChild($prop->ownerDocument->createElementNS($propName[1],'custom:' . $propName[2])); } - + } } @@ -69,8 +69,8 @@ class Sabre_DAV_Property_ResourceType extends Sabre_DAV_Property { * Returns the values in clark-notation * * For example array('{DAV:}collection') - * - * @return array + * + * @return array */ public function getValue() { @@ -79,10 +79,10 @@ class Sabre_DAV_Property_ResourceType extends Sabre_DAV_Property { } /** - * Checks if the principal contains a certain value - * - * @param string $type - * @return bool + * Checks if the principal contains a certain value + * + * @param string $type + * @return bool */ public function is($type) { @@ -104,10 +104,10 @@ class Sabre_DAV_Property_ResourceType extends Sabre_DAV_Property { } /** - * Unserializes a DOM element into a ResourceType property. - * - * @param DOMElement $dom - * @return void + * Unserializes a DOM element into a ResourceType property. + * + * @param DOMElement $dom + * @return Sabre_DAV_Property_ResourceType */ static public function unserialize(DOMElement $dom) { diff --git a/3rdparty/Sabre/DAV/Property/Response.php b/3rdparty/Sabre/DAV/Property/Response.php index 7d3a2db0387..88afbcfb26d 100644..100755 --- a/3rdparty/Sabre/DAV/Property/Response.php +++ b/3rdparty/Sabre/DAV/Property/Response.php @@ -1,53 +1,52 @@ <?php /** - * Response property - * + * Response property + * * This class represents the {DAV:}response XML element. - * This is used by the Server class to encode individual items within a multistatus + * This is used by the Server class to encode individual items within a multistatus * response. * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_Property_Response extends Sabre_DAV_Property implements Sabre_DAV_Property_IHref { /** - * Url for the response - * - * @var string + * Url for the response + * + * @var string */ private $href; /** - * Propertylist, ordered by HTTP status code - * - * @var array + * Propertylist, ordered by HTTP status code + * + * @var array */ private $responseProperties; /** * The responseProperties argument is a list of properties * within an array with keys representing HTTP status codes - * - * @param string $href - * @param array $responseProperties - * @return void + * + * @param string $href + * @param array $responseProperties */ - public function __construct($href,array $responseProperties) { + public function __construct($href, array $responseProperties) { $this->href = $href; - $this->responseProperties = $responseProperties; + $this->responseProperties = $responseProperties; } /** - * Returns the url - * - * @return string + * Returns the url + * + * @return string */ public function getHref() { @@ -56,9 +55,9 @@ class Sabre_DAV_Property_Response extends Sabre_DAV_Property implements Sabre_DA } /** - * Returns the property list - * - * @return array + * Returns the property list + * + * @return array */ public function getResponseProperties() { @@ -67,19 +66,19 @@ class Sabre_DAV_Property_Response extends Sabre_DAV_Property implements Sabre_DA } /** - * serialize - * - * @param Sabre_DAV_Server $server - * @param DOMElement $dom + * serialize + * + * @param Sabre_DAV_Server $server + * @param DOMElement $dom * @return void */ - public function serialize(Sabre_DAV_Server $server,DOMElement $dom) { + public function serialize(Sabre_DAV_Server $server, DOMElement $dom) { $document = $dom->ownerDocument; $properties = $this->responseProperties; - + $xresponse = $document->createElement('d:response'); - $dom->appendChild($xresponse); + $dom->appendChild($xresponse); $uri = Sabre_DAV_URLUtil::encodePath($this->href); @@ -87,7 +86,7 @@ class Sabre_DAV_Property_Response extends Sabre_DAV_Property implements Sabre_DA $uri = $server->getBaseUri() . $uri; $xresponse->appendChild($document->createElement('d:href',$uri)); - + // The properties variable is an array containing properties, grouped by // HTTP status foreach($properties as $httpStatus=>$propertyGroup) { @@ -111,7 +110,7 @@ class Sabre_DAV_Property_Response extends Sabre_DAV_Property implements Sabre_DA $propName = null; preg_match('/^{([^}]*)}(.*)$/',$propertyName,$propName); - + // special case for empty namespaces if ($propName[1]=='') { @@ -125,7 +124,7 @@ class Sabre_DAV_Property_Response extends Sabre_DAV_Property implements Sabre_DA $nsList[$propName[1]] = 'x' . count($nsList); } - // If the namespace was defined in the top-level xml namespaces, it means + // If the namespace was defined in the top-level xml namespaces, it means // there was already a namespace declaration, and we don't have to worry about it. if (isset($server->xmlNamespaces[$propName[1]])) { $currentProperty = $document->createElement($nsList[$propName[1]] . ':' . $propName[2]); diff --git a/3rdparty/Sabre/DAV/Property/ResponseList.php b/3rdparty/Sabre/DAV/Property/ResponseList.php index cd70b12861d..cae923afbf9 100644..100755 --- a/3rdparty/Sabre/DAV/Property/ResponseList.php +++ b/3rdparty/Sabre/DAV/Property/ResponseList.php @@ -1,33 +1,32 @@ <?php /** - * ResponseList property - * + * ResponseList property + * * This class represents multiple {DAV:}response XML elements. - * This is used by the Server class to encode items within a multistatus + * This is used by the Server class to encode items within a multistatus * response. * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_Property_ResponseList extends Sabre_DAV_Property { /** - * Response objects. - * - * @var array + * Response objects. + * + * @var array */ private $responses; /** - * The only valid argument is a list of Sabre_DAV_Property_Response + * The only valid argument is a list of Sabre_DAV_Property_Response * objects. - * - * @param array $responses; - * @return void + * + * @param array $responses; */ public function __construct($responses) { @@ -41,10 +40,10 @@ class Sabre_DAV_Property_ResponseList extends Sabre_DAV_Property { } /** - * serialize - * - * @param Sabre_DAV_Server $server - * @param DOMElement $dom + * serialize + * + * @param Sabre_DAV_Server $server + * @param DOMElement $dom * @return void */ public function serialize(Sabre_DAV_Server $server,DOMElement $dom) { diff --git a/3rdparty/Sabre/DAV/Property/SupportedLock.php b/3rdparty/Sabre/DAV/Property/SupportedLock.php index 01e63f58d9d..4e3aaf23a1a 100644..100755 --- a/3rdparty/Sabre/DAV/Property/SupportedLock.php +++ b/3rdparty/Sabre/DAV/Property/SupportedLock.php @@ -5,27 +5,26 @@ * * This property contains information about what kind of locks * this server supports. - * + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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_Property_SupportedLock extends Sabre_DAV_Property { /** - * supportsLocks - * + * supportsLocks + * * @var mixed */ public $supportsLocks = false; /** - * __construct - * - * @param mixed $supportsLocks - * @return void + * __construct + * + * @param mixed $supportsLocks */ public function __construct($supportsLocks) { @@ -34,9 +33,10 @@ class Sabre_DAV_Property_SupportedLock extends Sabre_DAV_Property { } /** - * serialize - * - * @param DOMElement $prop + * serialize + * + * @param Sabre_DAV_Server $server + * @param DOMElement $prop * @return void */ public function serialize(Sabre_DAV_Server $server,DOMElement $prop) { diff --git a/3rdparty/Sabre/DAV/Property/SupportedReportSet.php b/3rdparty/Sabre/DAV/Property/SupportedReportSet.php index acd9219c0f7..e62699f3b5a 100644..100755 --- a/3rdparty/Sabre/DAV/Property/SupportedReportSet.php +++ b/3rdparty/Sabre/DAV/Property/SupportedReportSet.php @@ -5,18 +5,18 @@ * * This property is defined in RFC3253, but since it's * so common in other webdav-related specs, it is part of the core server. - * + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_Property_SupportedReportSet extends Sabre_DAV_Property { /** - * List of reports - * + * List of reports + * * @var array */ protected $reports = array(); @@ -28,13 +28,12 @@ class Sabre_DAV_Property_SupportedReportSet extends Sabre_DAV_Property { * should be valid report-types in clark-notation. * * Either a string or an array of strings must be passed. - * - * @param mixed $reports - * @return void + * + * @param mixed $reports */ public function __construct($reports = null) { - if (!is_null($reports)) + if (!is_null($reports)) $this->addReport($reports); } @@ -44,8 +43,8 @@ class Sabre_DAV_Property_SupportedReportSet extends Sabre_DAV_Property { * * The report must be a string in clark-notation. * Multiple reports can be specified as an array. - * - * @param mixed $report + * + * @param mixed $report * @return void */ public function addReport($report) { @@ -54,7 +53,7 @@ class Sabre_DAV_Property_SupportedReportSet extends Sabre_DAV_Property { foreach($report as $r) { - if (!preg_match('/^{([^}]*)}(.*)$/',$r)) + if (!preg_match('/^{([^}]*)}(.*)$/',$r)) throw new Sabre_DAV_Exception('Reportname must be in clark-notation'); $this->reports[] = $r; @@ -65,8 +64,8 @@ class Sabre_DAV_Property_SupportedReportSet extends Sabre_DAV_Property { /** * Returns the list of supported reports - * - * @return array + * + * @return array */ public function getValue() { @@ -75,16 +74,16 @@ class Sabre_DAV_Property_SupportedReportSet extends Sabre_DAV_Property { } /** - * Serializes the node + * Serializes the node * * @param Sabre_DAV_Server $server - * @param DOMElement $prop + * @param DOMElement $prop * @return void */ - public function serialize(Sabre_DAV_Server $server,DOMElement $prop) { + public function serialize(Sabre_DAV_Server $server, DOMElement $prop) { foreach($this->reports as $reportName) { - + $supportedReport = $prop->ownerDocument->createElement('d:supported-report'); $prop->appendChild($supportedReport); @@ -92,9 +91,9 @@ class Sabre_DAV_Property_SupportedReportSet extends Sabre_DAV_Property { $supportedReport->appendChild($report); preg_match('/^{([^}]*)}(.*)$/',$reportName,$matches); - + list(, $namespace, $element) = $matches; - + $prefix = isset($server->xmlNamespaces[$namespace])?$server->xmlNamespaces[$namespace]:null; if ($prefix) { diff --git a/3rdparty/Sabre/DAV/Server.php b/3rdparty/Sabre/DAV/Server.php index 3d76d4f1918..4284c127b6e 100644..100755 --- a/3rdparty/Sabre/DAV/Server.php +++ b/3rdparty/Sabre/DAV/Server.php @@ -2,11 +2,11 @@ /** * Main DAV server class - * + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_Server { @@ -26,9 +26,6 @@ class Sabre_DAV_Server { */ const NODE_DIRECTORY = 2; - const PROP_SET = 1; - const PROP_REMOVE = 2; - /** * XML namespace for all SabreDAV related elements */ @@ -36,42 +33,42 @@ class Sabre_DAV_Server { /** * The tree object - * - * @var Sabre_DAV_Tree + * + * @var Sabre_DAV_Tree */ public $tree; /** - * The base uri - * - * @var string + * The base uri + * + * @var string */ - protected $baseUri = null; + protected $baseUri = null; /** - * httpResponse - * - * @var Sabre_HTTP_Response + * httpResponse + * + * @var Sabre_HTTP_Response */ public $httpResponse; /** * httpRequest - * - * @var Sabre_HTTP_Request + * + * @var Sabre_HTTP_Request */ public $httpRequest; /** - * The list of plugins - * - * @var array + * The list of plugins + * + * @var array */ protected $plugins = array(); /** - * This array contains a list of callbacks we should call when certain events are triggered - * + * This array contains a list of callbacks we should call when certain events are triggered + * * @var array */ protected $eventSubscriptions = array(); @@ -81,7 +78,7 @@ class Sabre_DAV_Server { * * If you are defining your own custom namespace, add it here to reduce * bandwidth and improve legibility of xml bodies. - * + * * @var array */ public $xmlNamespaces = array( @@ -90,9 +87,9 @@ class Sabre_DAV_Server { ); /** - * The propertymap can be used to map properties from + * The propertymap can be used to map properties from * requests to property classes. - * + * * @var array */ public $propertyMap = array( @@ -125,23 +122,32 @@ class Sabre_DAV_Server { * This is a flag that allow or not showing file, line and code * of the exception in the returned XML * - * @var bool + * @var bool */ public $debugExceptions = false; /** - * This property allows you to automatically add the 'resourcetype' value + * 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 + * 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', ); + /** + * If this setting is turned off, SabreDAV's version number will be hidden + * from various places. + * + * Some people feel this is a good security measure. + * + * @var bool + */ + static public $exposeVersion = true; /** * Sets up the server @@ -150,14 +156,13 @@ class Sabre_DAV_Server { * use it as the directory tree. If a Sabre_DAV_INode is passed, it * will create a Sabre_DAV_ObjectTree and use the node as the root. * - * If nothing is passed, a Sabre_DAV_SimpleCollection is created in + * If nothing is passed, a Sabre_DAV_SimpleCollection 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 + * the nodes in the array as top-level children. + * + * @param Sabre_DAV_Tree|Sabre_DAV_INode|null $treeOrNode The tree object */ public function __construct($treeOrNode = null) { @@ -190,7 +195,7 @@ class Sabre_DAV_Server { } /** - * Starts the DAV Server + * Starts the DAV Server * * @return void */ @@ -218,7 +223,9 @@ class Sabre_DAV_Server { $error->appendChild($DOM->createElement('s:stacktrace',$e->getTraceAsString())); } - $error->appendChild($DOM->createElement('s:sabredav-version',Sabre_DAV_Version::VERSION)); + if (self::$exposeVersion) { + $error->appendChild($DOM->createElement('s:sabredav-version',Sabre_DAV_Version::VERSION)); + } if($e instanceof Sabre_DAV_Exception) { @@ -233,7 +240,7 @@ class Sabre_DAV_Server { } $headers['Content-Type'] = 'application/xml; charset=utf-8'; - + $this->httpResponse->sendStatus($httpCode); $this->httpResponse->setHeaders($headers); $this->httpResponse->sendBody($DOM->saveXML()); @@ -244,24 +251,24 @@ class Sabre_DAV_Server { /** * Sets the base server uri - * + * * @param string $uri * @return void */ public function setBaseUri($uri) { // If the baseUri does not end with a slash, we must add it - if ($uri[strlen($uri)-1]!=='/') + if ($uri[strlen($uri)-1]!=='/') $uri.='/'; - $this->baseUri = $uri; + $this->baseUri = $uri; } /** * Returns the base responding uri - * - * @return string + * + * @return string */ public function getBaseUri() { @@ -272,11 +279,11 @@ class Sabre_DAV_Server { /** * This method attempts to detect the base uri. - * Only the PATH_INFO variable is considered. - * - * If this variable is not set, the root (/) is assumed. + * Only the PATH_INFO variable is considered. * - * @return void + * If this variable is not set, the root (/) is assumed. + * + * @return string */ public function guessBaseUri() { @@ -303,21 +310,21 @@ class Sabre_DAV_Server { return rtrim($baseUri,'/') . '/'; } - throw new Sabre_DAV_Exception('The REQUEST_URI ('. $uri . ') did not end with the contents of PATH_INFO (' . $pathInfo . '). This server might be misconfigured.'); + throw new Sabre_DAV_Exception('The REQUEST_URI ('. $uri . ') did not end with the contents of PATH_INFO (' . $pathInfo . '). This server might be misconfigured.'); - } + } - // The last fallback is that we're just going to assume the server root. + // The last fallback is that we're just going to assume the server root. return '/'; } /** * Adds a plugin to the server - * + * * For more information, console the documentation of Sabre_DAV_ServerPlugin * - * @param Sabre_DAV_ServerPlugin $plugin + * @param Sabre_DAV_ServerPlugin $plugin * @return void */ public function addPlugin(Sabre_DAV_ServerPlugin $plugin) { @@ -333,11 +340,11 @@ class Sabre_DAV_Server { * This function returns null if the plugin was not found. * * @param string $name - * @return Sabre_DAV_ServerPlugin + * @return Sabre_DAV_ServerPlugin */ public function getPlugin($name) { - if (isset($this->plugins[$name])) + if (isset($this->plugins[$name])) return $this->plugins[$name]; // This is a fallback and deprecated. @@ -350,9 +357,9 @@ class Sabre_DAV_Server { } /** - * Returns all plugins - * - * @return array + * Returns all plugins + * + * @return array */ public function getPlugins() { @@ -361,7 +368,6 @@ class Sabre_DAV_Server { } - /** * Subscribe to an event. * @@ -371,9 +377,9 @@ class Sabre_DAV_Server { * * This is for example used to make sure that the authentication plugin * is triggered before anything else. If it's not needed to change this - * number, it is recommended to ommit. - * - * @param string $event + * number, it is recommended to ommit. + * + * @param string $event * @param callback $callback * @param int $priority * @return void @@ -398,7 +404,7 @@ class Sabre_DAV_Server { * * @param string $eventName * @param array $arguments - * @return bool + * @return bool */ public function broadcastEvent($eventName,$arguments = array()) { @@ -418,7 +424,7 @@ class Sabre_DAV_Server { } /** - * Handles a http request, and execute a method based on its name + * Handles a http request, and execute a method based on its name * * @param string $method * @param string $uri @@ -426,7 +432,7 @@ class Sabre_DAV_Server { */ public function invokeMethod($method, $uri) { - $method = strtoupper($method); + $method = strtoupper($method); if (!$this->broadcastEvent('beforeMethod',array($method, $uri))) return; @@ -453,7 +459,7 @@ class Sabre_DAV_Server { if ($this->broadcastEvent('unknownMethod',array($method, $uri))) { // Unsupported method - throw new Sabre_DAV_Exception_NotImplemented(); + throw new Sabre_DAV_Exception_NotImplemented('There was no handler found for this "' . $method . '" method'); } } @@ -461,9 +467,9 @@ class Sabre_DAV_Server { } // {{{ HTTP Method implementations - + /** - * HTTP OPTIONS + * HTTP OPTIONS * * @param string $uri * @return void @@ -476,11 +482,13 @@ class Sabre_DAV_Server { $features = array('1','3', 'extended-mkcol'); foreach($this->plugins as $plugin) $features = array_merge($features,$plugin->getFeatures()); - + $this->httpResponse->setHeader('DAV',implode(', ',$features)); $this->httpResponse->setHeader('MS-Author-Via','DAV'); $this->httpResponse->setHeader('Accept-Ranges','bytes'); - $this->httpResponse->setHeader('X-Sabre-Version',Sabre_DAV_Version::VERSION); + if (self::$exposeVersion) { + $this->httpResponse->setHeader('X-Sabre-Version',Sabre_DAV_Version::VERSION); + } $this->httpResponse->setHeader('Content-Length',0); $this->httpResponse->sendStatus(200); @@ -492,13 +500,13 @@ class Sabre_DAV_Server { * This method simply fetches the contents of a uri, like normal * * @param string $uri - * @return void + * @return bool */ protected function httpGet($uri) { $node = $this->tree->getNodeForPath($uri,0); - if (!$this->checkPreconditions(true)) return false; + if (!$this->checkPreconditions(true)) return false; if (!($node instanceof Sabre_DAV_IFile)) throw new Sabre_DAV_Exception_NotImplemented('GET is only implemented on File objects'); $body = $node->get(); @@ -535,7 +543,7 @@ class Sabre_DAV_Server { } else { $nodeSize = null; } - + $this->httpResponse->setHeaders($httpHeaders); $range = $this->getHTTPRange(); @@ -545,12 +553,12 @@ class Sabre_DAV_Server { // If ifRange is set, and range is specified, we first need to check // the precondition. if ($nodeSize && $range && $ifRange) { - + // if IfRange is parsable as a date we'll treat it as a DateTime // otherwise, we must treat it as an etag. try { $ifRangeDate = new DateTime($ifRange); - + // It's a date. We must check if the entity is modified since // the specified date. if (!isset($httpHeaders['Last-Modified'])) $ignoreRangeHeader = true; @@ -560,8 +568,8 @@ class Sabre_DAV_Server { } } catch (Exception $e) { - - // It's an entity. We can do a simple comparison. + + // It's an entity. We can do a simple comparison. if (!isset($httpHeaders['ETag'])) $ignoreRangeHeader = true; elseif ($httpHeaders['ETag']!==$ifRange) $ignoreRangeHeader = true; } @@ -575,7 +583,7 @@ class Sabre_DAV_Server { $start = $range[0]; $end = $range[1]?$range[1]:$nodeSize-1; - if($start >= $nodeSize) + if($start >= $nodeSize) throw new Sabre_DAV_Exception_RequestedRangeNotSatisfiable('The start offset (' . $range[0] . ') exceeded the size of the entity (' . $nodeSize . ')'); if($end < $start) throw new Sabre_DAV_Exception_RequestedRangeNotSatisfiable('The end offset (' . $range[1] . ') is lower than the start offset (' . $range[0] . ')'); @@ -625,7 +633,7 @@ class Sabre_DAV_Server { $node = $this->tree->getNodeForPath($uri); /* This information is only collection for File objects. - * Ideally we want to throw 405 Method Not Allowed for every + * Ideally we want to throw 405 Method Not Allowed for every * non-file, but MS Office does not like this */ if ($node instanceof Sabre_DAV_IFile) { @@ -640,7 +648,7 @@ class Sabre_DAV_Server { } /** - * HTTP Delete + * HTTP Delete * * The HTTP delete method, deletes a given uri * @@ -651,6 +659,7 @@ class Sabre_DAV_Server { if (!$this->broadcastEvent('beforeUnbind',array($uri))) return; $this->tree->delete($uri); + $this->broadcastEvent('afterUnbind',array($uri)); $this->httpResponse->sendStatus(204); $this->httpResponse->setHeader('Content-Length','0'); @@ -659,13 +668,13 @@ class Sabre_DAV_Server { /** - * WebDAV PROPFIND + * WebDAV PROPFIND * * This WebDAV method requests information about an uri resource, or a list of resources * If a client wants to receive the properties for a single resource it will add an HTTP Depth: header with a 0 value * If the value is 1, it means that it also expects a list of sub-resources (e.g.: files in a directory) * - * The request body contains an XML data structure that has a list of properties the client understands + * The request body contains an XML data structure that has a list of properties the client understands * The response body is also an xml document, containing information about every uri resource and the requested properties * * It has to return a HTTP 207 Multi-status status code @@ -679,7 +688,7 @@ class Sabre_DAV_Server { $requestedProperties = $this->parsePropfindRequest($this->httpRequest->getBody(true)); $depth = $this->getHTTPDepth(1); - // The only two options for the depth of a propfind is 0 or 1 + // The only two options for the depth of a propfind is 0 or 1 if ($depth!=0) $depth = 1; $newProperties = $this->getPropertiesForPath($uri,$requestedProperties,$depth); @@ -688,8 +697,8 @@ class Sabre_DAV_Server { $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 + // 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()); @@ -712,7 +721,7 @@ class Sabre_DAV_Server { protected function httpPropPatch($uri) { $newProperties = $this->parsePropPatchRequest($this->httpRequest->getBody(true)); - + $result = $this->updateProperties($uri, $newProperties); $this->httpResponse->sendStatus(207); @@ -725,14 +734,14 @@ class Sabre_DAV_Server { } /** - * HTTP PUT method - * + * HTTP PUT method + * * This HTTP method updates a file, or creates a new one. * - * If a new resource was created, a 201 Created status code should be returned. If an existing resource is updated, it's a 200 Ok + * If a new resource was created, a 201 Created status code should be returned. If an existing resource is updated, it's a 204 No Content * * @param string $uri - * @return void + * @return bool */ protected function httpPut($uri) { @@ -768,13 +777,13 @@ class Sabre_DAV_Server { // Intercepting the Finder problem if (($expected = $this->httpRequest->getHeader('X-Expected-Entity-Length')) && $expected > 0) { - + /** - Many webservers will not cooperate well with Finder PUT requests, + Many webservers will not cooperate well with Finder PUT requests, because it uses 'Chunked' transfer encoding for the request body. - The symptom of this problem is that Finder sends files to the - server, but they arrive as 0-lenght files in PHP. + The symptom of this problem is that Finder sends files to the + server, but they arrive as 0-length files in PHP. If we don't do anything, the user might think they are uploading files successfully, but they end up empty on the server. Instead, @@ -808,29 +817,36 @@ class Sabre_DAV_Server { } - if ($this->tree->nodeExists($uri)) { + if ($this->tree->nodeExists($uri)) { $node = $this->tree->getNodeForPath($uri); - + // Checking If-None-Match and related headers. if (!$this->checkPreconditions()) return; - + // If the node is a collection, we'll deny it if (!($node instanceof Sabre_DAV_IFile)) throw new Sabre_DAV_Exception_Conflict('PUT is not allowed on non-files.'); - if (!$this->broadcastEvent('beforeWriteContent',array($this->getRequestUri()))) return false; + if (!$this->broadcastEvent('beforeWriteContent',array($uri, $node, &$body))) return false; + + $etag = $node->put($body); + + $this->broadcastEvent('afterWriteContent',array($uri, $node)); - $node->put($body); $this->httpResponse->setHeader('Content-Length','0'); + if ($etag) $this->httpResponse->setHeader('ETag',$etag); $this->httpResponse->sendStatus(204); } else { + $etag = null; // If we got here, the resource didn't exist yet. - if (!$this->createFile($this->getRequestUri(),$body)) { + if (!$this->createFile($this->getRequestUri(),$body,$etag)) { // For one reason or another the file was not created. return; } + $this->httpResponse->setHeader('Content-Length','0'); + if ($etag) $this->httpResponse->setHeader('ETag', $etag); $this->httpResponse->sendStatus(201); } @@ -855,7 +871,7 @@ class Sabre_DAV_Server { $contentType = $this->httpRequest->getHeader('Content-Type'); if (strpos($contentType,'application/xml')!==0 && strpos($contentType,'text/xml')!==0) { - // We must throw 415 for unsupport mkcol bodies + // We must throw 415 for unsupported mkcol bodies throw new Sabre_DAV_Exception_UnsupportedMediaType('The request body for the MKCOL request must have an xml Content-Type'); } @@ -863,7 +879,7 @@ class Sabre_DAV_Server { $dom = Sabre_DAV_XMLUtil::loadDOMDocument($requestBody); if (Sabre_DAV_XMLUtil::toClarkNotation($dom->firstChild)!=='{DAV:}mkcol') { - // We must throw 415 for unsupport mkcol bodies + // We must throw 415 for unsupported mkcol bodies throw new Sabre_DAV_Exception_UnsupportedMediaType('The request body for the MKCOL request must be a {DAV:}mkcol request construct.'); } @@ -875,7 +891,7 @@ class Sabre_DAV_Server { $properties = array_merge($properties, Sabre_DAV_XMLUtil::parseProperties($childNode, $this->propertyMap)); } - if (!isset($properties['{DAV:}resourcetype'])) + if (!isset($properties['{DAV:}resourcetype'])) throw new Sabre_DAV_Exception_BadRequest('The mkcol request must include a {DAV:}resourcetype property'); $resourceType = $properties['{DAV:}resourcetype']->getValue(); @@ -918,19 +934,21 @@ class Sabre_DAV_Server { $moveInfo = $this->getCopyAndMoveInfo(); // If the destination is part of the source tree, we must fail - if ($moveInfo['destination']==$uri) + 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; $this->tree->delete($moveInfo['destination']); + $this->broadcastEvent('afterUnbind',array($moveInfo['destination'])); } if (!$this->broadcastEvent('beforeUnbind',array($uri))) return false; if (!$this->broadcastEvent('beforeBind',array($moveInfo['destination']))) return false; $this->tree->move($uri,$moveInfo['destination']); + $this->broadcastEvent('afterUnbind',array($uri)); $this->broadcastEvent('afterBind',array($moveInfo['destination'])); // If a resource was overwritten we should send a 204, otherwise a 201 @@ -946,13 +964,13 @@ class Sabre_DAV_Server { * A lot of the actual request processing is done in getCopyMoveInfo * * @param string $uri - * @return void + * @return bool */ protected function httpCopy($uri) { $copyInfo = $this->getCopyAndMoveInfo(); // If the destination is part of the source tree, we must fail - if ($copyInfo['destination']==$uri) + if ($copyInfo['destination']==$uri) throw new Sabre_DAV_Exception_Forbidden('Source and destination uri are identical.'); if ($copyInfo['destinationExists']) { @@ -998,13 +1016,13 @@ class Sabre_DAV_Server { } // }}} - // {{{ HTTP/WebDAV protocol helpers + // {{{ HTTP/WebDAV protocol helpers /** - * Returns an array with all the supported HTTP methods for a specific uri. + * Returns an array with all the supported HTTP methods for a specific uri. * - * @param string $uri - * @return array + * @param string $uri + * @return array */ public function getAllowedMethods($uri) { @@ -1023,13 +1041,13 @@ class Sabre_DAV_Server { // The MKCOL is only allowed on an unmapped uri try { - $node = $this->tree->getNodeForPath($uri); - } catch (Sabre_DAV_Exception_FileNotFound $e) { + $this->tree->getNodeForPath($uri); + } catch (Sabre_DAV_Exception_NotFound $e) { $methods[] = 'MKCOL'; } // We're also checking if any of the plugins register any new methods - foreach($this->plugins as $plugin) $methods = array_merge($methods,$plugin->getHTTPMethods($uri)); + foreach($this->plugins as $plugin) $methods = array_merge($methods, $plugin->getHTTPMethods($uri)); array_unique($methods); return $methods; @@ -1037,8 +1055,8 @@ class Sabre_DAV_Server { } /** - * Gets the uri for the request, keeping the base uri into consideration - * + * Gets the uri for the request, keeping the base uri into consideration + * * @return string */ public function getRequestUri() { @@ -1048,9 +1066,9 @@ class Sabre_DAV_Server { } /** - * Calculates the uri for a request, making sure that the base uri is stripped out - * - * @param string $uri + * Calculates the uri for a request, making sure that the base uri is stripped out + * + * @param string $uri * @throws Sabre_DAV_Exception_Forbidden A permission denied exception is thrown whenever there was an attempt to supply a uri outside of the base uri * @return string */ @@ -1068,9 +1086,9 @@ class Sabre_DAV_Server { return trim(Sabre_DAV_URLUtil::decodePath(substr($uri,strlen($this->getBaseUri()))),'/'); - // A special case, if the baseUri was accessed without a trailing - // slash, we'll accept it as well. - } elseif ($uri.'/' === $this->getBaseUri()) { + // A special case, if the baseUri was accessed without a trailing + // slash, we'll accept it as well. + } elseif ($uri.'/' === $this->getBaseUri()) { return ''; @@ -1086,10 +1104,10 @@ class Sabre_DAV_Server { * Returns the HTTP depth header * * This method returns the contents of the HTTP depth request header. If the depth header was 'infinity' it will return the Sabre_DAV_Server::DEPTH_INFINITY object - * It is possible to supply a default depth value, which is used when the depth header has invalid content, or is completely non-existant - * - * @param mixed $default - * @return int + * It is possible to supply a default depth value, which is used when the depth header has invalid content, or is completely non-existent + * + * @param mixed $default + * @return int */ public function getHTTPDepth($default = self::DEPTH_INFINITY) { @@ -1100,7 +1118,7 @@ class Sabre_DAV_Server { if ($depth == 'infinity') return self::DEPTH_INFINITY; - + // If its an unknown value. we'll grab the default if (!ctype_digit($depth)) return $default; @@ -1118,14 +1136,14 @@ class Sabre_DAV_Server { * The second number is the offset of the last byte in the range. * * If the second offset is null, it should be treated as the offset of the last byte of the entity - * If the first offset is null, the second offset should be used to retrieve the last x bytes of the entity + * If the first offset is null, the second offset should be used to retrieve the last x bytes of the entity * - * return $mixed + * @return array|null */ public function getHTTPRange() { $range = $this->httpRequest->getHeader('range'); - if (is_null($range)) return null; + if (is_null($range)) return null; // Matching "Range: bytes=1234-5678: both numbers are optional @@ -1143,15 +1161,15 @@ class Sabre_DAV_Server { /** * Returns information about Copy and Move requests - * - * This function is created to help getting information about the source and the destination for the - * WebDAV MOVE and COPY HTTP request. It also validates a lot of information and throws proper exceptions - * + * + * This function is created to help getting information about the source and the destination for the + * WebDAV MOVE and COPY HTTP request. It also validates a lot of information and throws proper exceptions + * * The returned value is an array with the following keys: * * destination - Destination path - * * destinationExists - Wether or not the destination is an existing url (and should therefore be overwritten) + * * destinationExists - Whether or not the destination is an existing url (and should therefore be overwritten) * - * @return array + * @return array */ public function getCopyAndMoveInfo() { @@ -1170,7 +1188,7 @@ class Sabre_DAV_Server { try { $destinationParent = $this->tree->getNodeForPath($destinationDir); if (!($destinationParent instanceof Sabre_DAV_ICollection)) throw new Sabre_DAV_Exception_UnsupportedMediaType('The destination node is not a collection'); - } catch (Sabre_DAV_Exception_FileNotFound $e) { + } catch (Sabre_DAV_Exception_NotFound $e) { // If the destination parent node is not found, we throw a 409 throw new Sabre_DAV_Exception_Conflict('The destination node is not found'); @@ -1179,12 +1197,12 @@ class Sabre_DAV_Server { try { $destinationNode = $this->tree->getNodeForPath($destination); - + // If this succeeded, it means the destination already exists // we'll need to throw precondition failed in case overwrite is false if (!$overwrite) throw new Sabre_DAV_Exception_PreconditionFailed('The destination node already exists, and the overwrite header is set to false','Overwrite'); - } catch (Sabre_DAV_Exception_FileNotFound $e) { + } catch (Sabre_DAV_Exception_NotFound $e) { // Destination didn't exist, we're all good $destinationNode = false; @@ -1220,22 +1238,50 @@ class Sabre_DAV_Server { } /** + * A kid-friendly way to fetch properties for a node's children. + * + * The returned array will be indexed by the path of the of child node. + * Only properties that are actually found will be returned. + * + * The parent node will not be returned. + * + * @param string $path + * @param array $propertyNames + * @return array + */ + public function getPropertiesForChildren($path, $propertyNames) { + + $result = array(); + foreach($this->getPropertiesForPath($path,$propertyNames,1) as $k=>$row) { + + // Skipping the parent path + if ($k === 0) continue; + + $result[$row['href']] = $row[200]; + + } + return $result; + + } + + /** * Returns a list of HTTP headers for a particular resource * - * The generated http headers are based on properties provided by the + * The generated http headers are based on properties provided by the * resource. The method basically provides a simple mapping between * DAV property and HTTP header. * * The headers are intended to be used for HEAD and GET requests. - * + * * @param string $path + * @return array */ public function getHTTPHeaders($path) { $propertyMap = array( '{DAV:}getcontenttype' => 'Content-Type', '{DAV:}getcontentlength' => 'Content-Length', - '{DAV:}getlastmodified' => 'Last-Modified', + '{DAV:}getlastmodified' => 'Last-Modified', '{DAV:}getetag' => 'ETag', ); @@ -1245,40 +1291,40 @@ class Sabre_DAV_Server { foreach($propertyMap as $property=>$header) { if (!isset($properties[$property])) continue; - if (is_scalar($properties[$property])) { + if (is_scalar($properties[$property])) { $headers[$header] = $properties[$property]; - // GetLastModified gets special cased + // GetLastModified gets special cased } elseif ($properties[$property] instanceof Sabre_DAV_Property_GetLastModified) { - $headers[$header] = $properties[$property]->getTime()->format(DateTime::RFC1123); + $headers[$header] = Sabre_HTTP_Util::toHTTPDate($properties[$property]->getTime()); } } return $headers; - + } /** * Returns a list of properties for a given path - * + * * The path that should be supplied should have the baseUrl stripped out * The list of properties should be supplied in Clark notation. If the list is empty * 'allprops' is assumed. * * If a depth of 1 is requested child elements will also be returned. * - * @param string $path + * @param string $path * @param array $propertyNames - * @param int $depth + * @param int $depth * @return array */ - public function getPropertiesForPath($path,$propertyNames = array(),$depth = 0) { + public function getPropertiesForPath($path, $propertyNames = array(), $depth = 0) { if ($depth!=0) $depth = 1; $returnPropertyList = array(); - + $parentNode = $this->tree->getNodeForPath($path); $nodes = array( $path => $parentNode @@ -1286,11 +1332,11 @@ class Sabre_DAV_Server { if ($depth==1 && $parentNode instanceof Sabre_DAV_ICollection) { foreach($this->tree->getChildren($path) as $childNode) $nodes[$path . '/' . $childNode->getName()] = $childNode; - } - + } + // If the propertyNames array is empty, it means all properties are requested. // We shouldn't actually return everything we know though, and only return a - // sensible list. + // sensible list. $allProperties = count($propertyNames)==0; foreach($nodes as $myPath=>$node) { @@ -1315,8 +1361,8 @@ class Sabre_DAV_Server { ); } - // If the resourceType was not part of the list, we manually add it - // and mark it for removal. We need to know the resourcetype in order + // If the resourceType was not part of the list, we manually add it + // and mark it for removal. We need to know the resourcetype in order // to make certain decisions about the entry. // WebDAV dictates we should add a / and the end of href's for collections $removeRT = false; @@ -1326,32 +1372,39 @@ class Sabre_DAV_Server { } $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 this method explicitly returned false, we must ignore this + // node as it is inaccessible. if ($result===false) continue; if (count($currentPropertyNames) > 0) { - if ($node instanceof Sabre_DAV_IProperties) + 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:}quota-used-bytes' : + case '{DAV:}getcontentlength' : + if ($node instanceof Sabre_DAV_IFile) { + $size = $node->getSize(); + if (!is_null($size)) { + $newProperties[200][$prop] = (int)$node->getSize(); + } + } + break; + case '{DAV:}quota-used-bytes' : if ($node instanceof Sabre_DAV_IQuota) { $quotaInfo = $node->getQuotaInfo(); $newProperties[200][$prop] = $quotaInfo[0]; } break; - case '{DAV:}quota-available-bytes' : + case '{DAV:}quota-available-bytes' : if ($node instanceof Sabre_DAV_IQuota) { $quotaInfo = $node->getQuotaInfo(); $newProperties[200][$prop] = $quotaInfo[1]; @@ -1364,7 +1417,7 @@ class Sabre_DAV_Server { foreach($this->plugins as $plugin) { $reports = array_merge($reports, $plugin->getSupportedReportSet($myPath)); } - $newProperties[200][$prop] = new Sabre_DAV_Property_SupportedReportSet($reports); + $newProperties[200][$prop] = new Sabre_DAV_Property_SupportedReportSet($reports); break; case '{DAV:}resourcetype' : $newProperties[200]['{DAV:}resourcetype'] = new Sabre_DAV_Property_ResourceType(); @@ -1379,14 +1432,14 @@ class Sabre_DAV_Server { if (!$allProperties && !isset($newProperties[200][$prop])) $newProperties[404][$prop] = null; } - + $this->broadcastEvent('afterGetProperties',array(trim($myPath,'/'),&$newProperties)); - $newProperties['href'] = trim($myPath,'/'); + $newProperties['href'] = trim($myPath,'/'); // Its is a WebDAV recommendation to add a trailing slash to collectionnames. // 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 + // 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']) && count($newProperties[200]['{DAV:}resourcetype']->getValue())>0) $newProperties['href'] .='/'; @@ -1397,7 +1450,7 @@ class Sabre_DAV_Server { $returnPropertyList[] = $newProperties; } - + return $returnPropertyList; } @@ -1406,27 +1459,31 @@ class Sabre_DAV_Server { * This method is invoked by sub-systems creating a new file. * * Currently this is done by HTTP PUT and HTTP LOCK (in the Locks_Plugin). - * It was important to get this done through a centralized function, + * It was important to get this done through a centralized function, * allowing plugins to intercept this using the beforeCreateFile event. * * This method will return true if the file was actually created - * - * @param string $uri - * @param resource $data - * @return bool + * + * @param string $uri + * @param resource $data + * @param string $etag + * @return bool */ - public function createFile($uri,$data) { + public function createFile($uri,$data, &$etag = null) { list($dir,$name) = Sabre_DAV_URLUtil::splitPath($uri); if (!$this->broadcastEvent('beforeBind',array($uri))) return false; - if (!$this->broadcastEvent('beforeCreateFile',array($uri,$data))) return false; $parent = $this->tree->getNodeForPath($dir); - $parent->createFile($name,$data); + + if (!$this->broadcastEvent('beforeCreateFile',array($uri, &$data, $parent))) return false; + + $etag = $parent->createFile($name,$data); $this->tree->markDirty($dir); $this->broadcastEvent('afterBind',array($uri)); + $this->broadcastEvent('afterCreateFile',array($uri, $parent)); return true; } @@ -1434,7 +1491,7 @@ class Sabre_DAV_Server { /** * This method is invoked by sub-systems creating a new directory. * - * @param string $uri + * @param string $uri * @return void */ public function createDirectory($uri) { @@ -1447,14 +1504,14 @@ class Sabre_DAV_Server { * Use this method to create a new collection * * The {DAV:}resourcetype is specified using the resourceType array. - * At the very least it must contain {DAV:}collection. + * At the very least it must contain {DAV:}collection. * * The properties array can contain a list of additional properties. - * - * @param string $uri The new uri - * @param array $resourceType The resourceType(s) + * + * @param string $uri The new uri + * @param array $resourceType The resourceType(s) * @param array $properties A list of properties - * @return void + * @return array|null */ public function createCollection($uri, array $resourceType, array $properties) { @@ -1471,7 +1528,7 @@ class Sabre_DAV_Server { $parent = $this->tree->getNodeForPath($parentUri); - } catch (Sabre_DAV_Exception_FileNotFound $e) { + } catch (Sabre_DAV_Exception_NotFound $e) { throw new Sabre_DAV_Exception_Conflict('Parent node does not exist'); @@ -1491,14 +1548,14 @@ class Sabre_DAV_Server { // If we got here.. it means there's already a node on that url, and we need to throw a 405 throw new Sabre_DAV_Exception_MethodNotAllowed('The resource you tried to create already exists'); - } catch (Sabre_DAV_Exception_FileNotFound $e) { + } catch (Sabre_DAV_Exception_NotFound $e) { // This is correct } - + if (!$this->broadcastEvent('beforeBind',array($uri))) return; - // There are 2 modes of operation. The standard collection + // There are 2 modes of operation. The standard collection // creates the directory, and then updates properties // the extended collection can create it directly. if ($parent instanceof Sabre_DAV_IExtendedCollection) { @@ -1513,7 +1570,7 @@ class Sabre_DAV_Server { } $parent->createDirectory($newName); - $rollBack = false; + $rollBack = false; $exception = null; $errorResult = null; @@ -1544,7 +1601,7 @@ class Sabre_DAV_Server { return $errorResult; } - + } $this->tree->markDirty($parentUri); $this->broadcastEvent('afterBind',array($uri)); @@ -1557,29 +1614,29 @@ class Sabre_DAV_Server { * The properties array must be a list of properties. Array-keys are * property names in clarknotation, array-values are it's values. * If a property must be deleted, the value should be null. - * - * Note that this request should either completely succeed, or + * + * Note that this request should either completely succeed, or * completely fail. * * The response is an array with statuscodes for keys, which in turn * contain arrays with propertynames. This response can be used * to generate a multistatus body. - * - * @param string $uri - * @param array $properties - * @return array + * + * @param string $uri + * @param array $properties + * @return array */ public function updateProperties($uri, array $properties) { // we'll start by grabbing the node, this will throw the appropriate - // exceptions if it doesn't. + // exceptions if it doesn't. $node = $this->tree->getNodeForPath($uri); - + $result = array( 200 => array(), 403 => array(), 424 => array(), - ); + ); $remainingProperties = $properties; $hasError = false; @@ -1684,14 +1741,15 @@ class Sabre_DAV_Server { * the appropriate HTTP response headers are already set. * * Normally this method will throw 412 Precondition Failed for failures - * related to If-None-Match, If-Match and If-Unmodified Since. It will + * related to If-None-Match, If-Match and If-Unmodified Since. It will * set the status to 304 Not Modified for If-Modified_since. * - * If the $handleAsGET argument is set to true, it will also return 304 + * If the $handleAsGET argument is set to true, it will also return 304 * Not Modified for failure of the If-None-Match precondition. This is the * desired behaviour for HTTP GET and HTTP HEAD requests. * - * @return bool + * @param bool $handleAsGET + * @return bool */ public function checkPreconditions($handleAsGET = false) { @@ -1708,7 +1766,7 @@ class Sabre_DAV_Server { // request succeed if a resource exists at that url. try { $node = $this->tree->getNodeForPath($uri); - } catch (Sabre_DAV_Exception_FileNotFound $e) { + } catch (Sabre_DAV_Exception_NotFound $e) { throw new Sabre_DAV_Exception_PreconditionFailed('An If-Match header was specified and the resource did not exist','If-Match'); } @@ -1722,7 +1780,7 @@ class Sabre_DAV_Server { // Stripping any extra spaces $ifMatchItem = trim($ifMatchItem,' '); - + $etag = $node->getETag(); if ($etag===$ifMatchItem) { $haveMatch = true; @@ -1744,7 +1802,7 @@ class Sabre_DAV_Server { if (!$node) { try { $node = $this->tree->getNodeForPath($uri); - } catch (Sabre_DAV_Exception_FileNotFound $e) { + } catch (Sabre_DAV_Exception_NotFound $e) { $nodeExists = false; } } @@ -1758,10 +1816,10 @@ class Sabre_DAV_Server { $etag = $node->getETag(); foreach($ifNoneMatch as $ifNoneMatchItem) { - + // Stripping any extra spaces $ifNoneMatchItem = trim($ifNoneMatchItem,' '); - + if ($etag===$ifNoneMatchItem) $haveMatch = true; } @@ -1781,7 +1839,7 @@ class Sabre_DAV_Server { } if (!$ifNoneMatch && ($ifModifiedSince = $this->httpRequest->getHeader('If-Modified-Since'))) { - + // The If-Modified-Since header contains a date. We // will only return the entity if it has been changed since // that date. If it hasn't been changed, we return a 304 @@ -1799,23 +1857,24 @@ class Sabre_DAV_Server { $lastMod = new DateTime('@' . $lastMod); if ($lastMod <= $date) { $this->httpResponse->sendStatus(304); + $this->httpResponse->setHeader('Last-Modified', Sabre_HTTP_Util::toHTTPDate($lastMod)); return false; - } + } } } } if ($ifUnmodifiedSince = $this->httpRequest->getHeader('If-Unmodified-Since')) { - + // The If-Unmodified-Since will allow allow the request if the // entity has not changed since the specified date. $date = Sabre_HTTP_Util::parseHTTPDate($ifUnmodifiedSince); - + // We must only check the date if it's valid if ($date) { if (is_null($node)) { $node = $this->tree->getNodeForPath($uri); - } + } $lastMod = $node->getLastModified(); if ($lastMod) { $lastMod = new DateTime('@' . $lastMod); @@ -1830,16 +1889,15 @@ class Sabre_DAV_Server { } - // }}} - // {{{ XML Readers & Writers - - + // }}} + // {{{ XML Readers & Writers + + /** - * Generates a WebDAV propfind response body based on a list of nodes - * + * Generates a WebDAV propfind response body based on a list of nodes + * * @param array $fileProperties The list with nodes - * @param array $requestedProperties The properties that should be returned - * @return string + * @return string */ public function generateMultiStatus(array $fileProperties) { @@ -1859,7 +1917,7 @@ class Sabre_DAV_Server { $href = $entry['href']; unset($entry['href']); - + $response = new Sabre_DAV_Property_Response($href,$entry); $response->serialize($this,$multiStatus); @@ -1878,7 +1936,7 @@ class Sabre_DAV_Server { * The keys in the returned array contain the property name (e.g.: {DAV:}displayname, * and the value contains the property value. If a property is to be removed the value * will be null. - * + * * @param string $body xml body * @return array list of properties in need of updating or deletion */ @@ -1886,17 +1944,17 @@ class Sabre_DAV_Server { //We'll need to change the DAV namespace declaration to something else in order to make it parsable $dom = Sabre_DAV_XMLUtil::loadDOMDocument($body); - + $newProperties = array(); foreach($dom->firstChild->childNodes as $child) { - if ($child->nodeType !== XML_ELEMENT_NODE) continue; + if ($child->nodeType !== XML_ELEMENT_NODE) continue; $operation = Sabre_DAV_XMLUtil::toClarkNotation($child); if ($operation!=='{DAV:}set' && $operation!=='{DAV:}remove') continue; - + $innerProperties = Sabre_DAV_XMLUtil::parseProperties($child, $this->propertyMap); foreach($innerProperties as $propertyName=>$propertyValue) { @@ -1920,9 +1978,9 @@ class Sabre_DAV_Server { * * This will either be a list of properties, or an empty array; in which case * an {DAV:}allprop was requested. - * - * @param string $body - * @return array + * + * @param string $body + * @return array */ public function parsePropFindRequest($body) { @@ -1931,7 +1989,7 @@ class Sabre_DAV_Server { $dom = Sabre_DAV_XMLUtil::loadDOMDocument($body); $elem = $dom->getElementsByTagNameNS('urn:DAV','propfind')->item(0); - return array_keys(Sabre_DAV_XMLUtil::parseProperties($elem)); + return array_keys(Sabre_DAV_XMLUtil::parseProperties($elem)); } diff --git a/3rdparty/Sabre/DAV/ServerPlugin.php b/3rdparty/Sabre/DAV/ServerPlugin.php index 6909f600c21..131863d13fb 100644..100755 --- a/3rdparty/Sabre/DAV/ServerPlugin.php +++ b/3rdparty/Sabre/DAV/ServerPlugin.php @@ -3,12 +3,12 @@ /** * The baseclass for all server plugins. * - * Plugins can modify or extend the servers behaviour. - * + * Plugins can modify or extend the servers behaviour. + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_ServerPlugin { @@ -20,18 +20,18 @@ abstract class Sabre_DAV_ServerPlugin { * addPlugin is called. * * This method should set up the requires event subscriptions. - * - * @param Sabre_DAV_Server $server + * + * @param Sabre_DAV_Server $server * @return void */ abstract public function initialize(Sabre_DAV_Server $server); - + /** - * This method should return a list of server-features. + * This method should return a list of server-features. * * This is for example 'versioning' and is added to the DAV: header * in an OPTIONS response. - * + * * @return array */ public function getFeatures() { @@ -44,11 +44,11 @@ abstract class Sabre_DAV_ServerPlugin { * Use this method to tell the server this plugin defines additional * HTTP methods. * - * This method is passed a uri. It should only return HTTP methods that are + * This method is passed a uri. It should only return HTTP methods that are * available for the specified uri. * * @param string $uri - * @return array + * @return array */ public function getHTTPMethods($uri) { @@ -58,11 +58,11 @@ abstract class Sabre_DAV_ServerPlugin { /** * Returns a plugin name. - * + * * Using this name other plugins will be able to access other plugins - * using Sabre_DAV_Server::getPlugin - * - * @return string + * using Sabre_DAV_Server::getPlugin + * + * @return string */ public function getPluginName() { @@ -74,11 +74,11 @@ abstract class Sabre_DAV_ServerPlugin { * 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 - * + * Note that you still need to subscribe to the 'report' event to actually + * implement them + * * @param string $uri - * @return array + * @return array */ public function getSupportedReportSet($uri) { diff --git a/3rdparty/Sabre/DAV/SimpleCollection.php b/3rdparty/Sabre/DAV/SimpleCollection.php index 223d05fed55..4acf971caa5 100644..100755 --- a/3rdparty/Sabre/DAV/SimpleCollection.php +++ b/3rdparty/Sabre/DAV/SimpleCollection.php @@ -8,23 +8,23 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_SimpleCollection extends Sabre_DAV_Collection { /** - * List of childnodes + * List of childnodes * * @var array */ protected $children = array(); /** - * Name of this resource - * - * @var string + * Name of this resource + * + * @var string */ protected $name; @@ -33,10 +33,9 @@ class Sabre_DAV_SimpleCollection extends Sabre_DAV_Collection { * * The name of the node must be passed, child nodes can also be bassed. * This nodes must be instances of Sabre_DAV_INode - * - * @param string $name - * @param array $children - * @return void + * + * @param string $name + * @param array $children */ public function __construct($name,array $children = array()) { @@ -51,9 +50,9 @@ class Sabre_DAV_SimpleCollection extends Sabre_DAV_Collection { } /** - * Adds a new childnode to this collection - * - * @param Sabre_DAV_INode $child + * Adds a new childnode to this collection + * + * @param Sabre_DAV_INode $child * @return void */ public function addChild(Sabre_DAV_INode $child) { @@ -63,9 +62,9 @@ class Sabre_DAV_SimpleCollection extends Sabre_DAV_Collection { } /** - * Returns the name of the collection - * - * @return string + * Returns the name of the collection + * + * @return string */ public function getName() { @@ -76,24 +75,24 @@ class Sabre_DAV_SimpleCollection extends Sabre_DAV_Collection { /** * Returns a child object, by its name. * - * This method makes use of the getChildren method to grab all the child nodes, and compares the name. + * This method makes use of the getChildren method to grab all the child nodes, and compares the name. * Generally its wise to override this, as this can usually be optimized - * + * * @param string $name - * @throws Sabre_DAV_Exception_FileNotFound - * @return Sabre_DAV_INode + * @throws Sabre_DAV_Exception_NotFound + * @return Sabre_DAV_INode */ public function getChild($name) { if (isset($this->children[$name])) return $this->children[$name]; - throw new Sabre_DAV_Exception_FileNotFound('File not found: ' . $name . ' in \'' . $this->getName() . '\''); + throw new Sabre_DAV_Exception_NotFound('File not found: ' . $name . ' in \'' . $this->getName() . '\''); } /** - * Returns a list of children for this collection - * - * @return array + * Returns a list of children for this collection + * + * @return array */ public function getChildren() { diff --git a/3rdparty/Sabre/DAV/SimpleDirectory.php b/3rdparty/Sabre/DAV/SimpleDirectory.php index 516a3aa907c..621222ebc53 100644..100755 --- a/3rdparty/Sabre/DAV/SimpleDirectory.php +++ b/3rdparty/Sabre/DAV/SimpleDirectory.php @@ -11,8 +11,8 @@ * @package Sabre * @subpackage DAV * @deprecated Use Sabre_DAV_SimpleCollection instead. - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_SimpleDirectory extends Sabre_DAV_SimpleCollection { diff --git a/3rdparty/Sabre/DAV/SimpleFile.php b/3rdparty/Sabre/DAV/SimpleFile.php index 304dff1c5ec..58330d6861d 100644..100755 --- a/3rdparty/Sabre/DAV/SimpleFile.php +++ b/3rdparty/Sabre/DAV/SimpleFile.php @@ -3,47 +3,48 @@ /** * SimpleFile * - * The 'SimpleFile' class is used to easily add read-only immutable files to - * the directory structure. One usecase would be to add a 'readme.txt' to a + * The 'SimpleFile' class is used to easily add read-only immutable files to + * the directory structure. One usecase would be to add a 'readme.txt' to a * root of a webserver with some standard content. * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_SimpleFile extends Sabre_DAV_File { /** - * File contents + * File contents * - * @var string + * @var string */ protected $contents = array(); /** - * Name of this resource - * - * @var string + * Name of this resource + * + * @var string */ protected $name; /** * A mimetype, such as 'text/plain' or 'text/html' - * - * @var string + * + * @var string */ protected $mimeType; /** * Creates this node * - * The name of the node must be passed, as well as the contents of the + * The name of the node must be passed, as well as the contents of the * file. - * - * @param string $name - * @param string $contents + * + * @param string $name + * @param string $contents + * @param string|null $mimeType */ public function __construct($name, $contents, $mimeType = null) { @@ -57,8 +58,8 @@ class Sabre_DAV_SimpleFile extends Sabre_DAV_File { * Returns the node name for this file. * * This name is used to construct the url. - * - * @return string + * + * @return string */ public function getName() { @@ -67,7 +68,7 @@ class Sabre_DAV_SimpleFile extends Sabre_DAV_File { } /** - * Returns the data + * Returns the data * * This method may either return a string or a readable stream resource * @@ -75,14 +76,14 @@ class Sabre_DAV_SimpleFile extends Sabre_DAV_File { */ public function get() { - return $this->contents; + return $this->contents; } /** - * Returns the size of the file, in bytes. - * - * @return int + * Returns the size of the file, in bytes. + * + * @return int */ public function getSize() { @@ -94,13 +95,14 @@ class Sabre_DAV_SimpleFile extends Sabre_DAV_File { * Returns the ETag for a file * * An ETag is a unique identifier representing the current version of the file. If the file changes, the ETag MUST change. - * The ETag is an arbritrary string, but MUST be surrounded by double-quotes. + * The ETag is an arbitrary string, but MUST be surrounded by double-quotes. * * Return null if the ETag can not effectively be determined + * @return string */ public function getETag() { - return '"' . md5($this->contents) . '"'; + return '"' . md5($this->contents) . '"'; } @@ -108,13 +110,12 @@ class Sabre_DAV_SimpleFile extends Sabre_DAV_File { * Returns the mime-type for a file * * If null is returned, we'll assume application/octet-stream - */ + * @return string + */ public function getContentType() { - return $this->mimeType; + return $this->mimeType; } } - -?> diff --git a/3rdparty/Sabre/DAV/StringUtil.php b/3rdparty/Sabre/DAV/StringUtil.php index 440cf6866ca..b126a94c825 100644..100755 --- a/3rdparty/Sabre/DAV/StringUtil.php +++ b/3rdparty/Sabre/DAV/StringUtil.php @@ -3,14 +3,14 @@ /** * String utility * - * This class is mainly used to implement the 'text-match' filter, used by both - * the CalDAV calendar-query REPORT, and CardDAV addressbook-query REPORT. + * This class is mainly used to implement the 'text-match' filter, used by both + * the CalDAV calendar-query REPORT, and CardDAV addressbook-query REPORT. * Because they both need it, it was decided to put it in Sabre_DAV instead. - * + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_StringUtil { @@ -18,11 +18,11 @@ class Sabre_DAV_StringUtil { /** * Checks if a needle occurs in a haystack ;) * - * @param string $haystack - * @param string $needle - * @param string $collation - * @param string $matchType - * @return bool + * @param string $haystack + * @param string $needle + * @param string $collation + * @param string $matchType + * @return bool */ static public function textMatch($haystack, $needle, $collation, $matchType = 'contains') { @@ -37,7 +37,7 @@ class Sabre_DAV_StringUtil { case 'i;octet' : // Do nothing - break; + break; case 'i;unicode-casemap' : $haystack = mb_strtoupper($haystack, 'UTF-8'); @@ -63,18 +63,18 @@ class Sabre_DAV_StringUtil { throw new Sabre_DAV_Exception_BadRequest('Match-type: ' . $matchType . ' is not supported'); } - + } /** - * This method takes an input string, checks if it's not valid UTF-8 and + * This method takes an input string, checks if it's not valid UTF-8 and * attempts to convert it to UTF-8 if it's not. * - * Note that currently this can only convert ISO-8559-1 to UTF-8 (latin-1), + * Note that currently this can only convert ISO-8559-1 to UTF-8 (latin-1), * anything else will likely fail. * - * @param string $input - * @return string + * @param string $input + * @return string */ static public function ensureUTF8($input) { @@ -84,7 +84,7 @@ class Sabre_DAV_StringUtil { return utf8_encode($input); } else { return $input; - } + } } diff --git a/3rdparty/Sabre/DAV/TemporaryFileFilterPlugin.php b/3rdparty/Sabre/DAV/TemporaryFileFilterPlugin.php index e8276af5613..36096e67775 100644..100755 --- a/3rdparty/Sabre/DAV/TemporaryFileFilterPlugin.php +++ b/3rdparty/Sabre/DAV/TemporaryFileFilterPlugin.php @@ -22,8 +22,8 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_TemporaryFileFilterPlugin extends Sabre_DAV_ServerPlugin { @@ -31,7 +31,7 @@ class Sabre_DAV_TemporaryFileFilterPlugin extends Sabre_DAV_ServerPlugin { /** * This is the list of patterns we intercept. * If new patterns are added, they must be valid patterns for preg_match. - * + * * @var array */ public $temporaryFilePatterns = array( @@ -43,19 +43,19 @@ class Sabre_DAV_TemporaryFileFilterPlugin extends Sabre_DAV_ServerPlugin { '/^\.dat(.*)$/', // Smultron seems to create these '/^~lock.(.*)#$/', // Windows 7 lockfiles ); - + /** * This is the directory where this plugin * will store it's files. - * - * @var string + * + * @var string */ private $dataDir; /** * A reference to the main Server class - * - * @var Sabre_DAV_Server + * + * @var Sabre_DAV_Server */ private $server; @@ -65,9 +65,8 @@ class Sabre_DAV_TemporaryFileFilterPlugin extends Sabre_DAV_ServerPlugin { * Make sure you specify a directory for your files. If you don't, we * will use PHP's directory for session-storage instead, and you might * not want that. - * - * @param string $dataDir - * @return void + * + * @param string|null $dataDir */ public function __construct($dataDir = null) { @@ -75,15 +74,15 @@ class Sabre_DAV_TemporaryFileFilterPlugin extends Sabre_DAV_ServerPlugin { if (!is_dir($dataDir)) mkdir($dataDir); $this->dataDir = $dataDir; - } + } /** * Initialize the plugin * * This is called automatically be the Server class after this plugin is * added with Sabre_DAV_Server::addPlugin() - * - * @param Sabre_DAV_Server $server + * + * @param Sabre_DAV_Server $server * @return void */ public function initialize(Sabre_DAV_Server $server) { @@ -97,11 +96,12 @@ class Sabre_DAV_TemporaryFileFilterPlugin extends Sabre_DAV_ServerPlugin { /** * This method is called before any HTTP method handler * - * This method intercepts any GET, DELETE, PUT and PROPFIND calls to + * This method intercepts any GET, DELETE, PUT and PROPFIND calls to * filenames that are known to match the 'temporary file' regex. - * - * @param string $method - * @return bool + * + * @param string $method + * @param string $uri + * @return bool */ public function beforeMethod($method, $uri) { @@ -125,33 +125,33 @@ class Sabre_DAV_TemporaryFileFilterPlugin extends Sabre_DAV_ServerPlugin { /** * This method is invoked if some subsystem creates a new file. * - * This is used to deal with HTTP LOCK requests which create a new + * This is used to deal with HTTP LOCK requests which create a new * file. - * - * @param string $uri - * @param resource $data - * @return bool + * + * @param string $uri + * @param resource $data + * @return bool */ public function beforeCreateFile($uri,$data) { if ($tempPath = $this->isTempFile($uri)) { - + $hR = $this->server->httpResponse; $hR->setHeader('X-Sabre-Temp','true'); file_put_contents($tempPath,$data); return false; } - return true; + return true; } /** * This method will check if the url matches the temporary file pattern - * if it does, it will return an path based on $this->dataDir for the + * if it does, it will return an path based on $this->dataDir for the * temporary file storage. - * - * @param string $path - * @return boolean|string + * + * @param string $path + * @return boolean|string */ protected function isTempFile($path) { @@ -161,7 +161,7 @@ class Sabre_DAV_TemporaryFileFilterPlugin extends Sabre_DAV_ServerPlugin { foreach($this->temporaryFilePatterns as $tempFile) { if (preg_match($tempFile,$tempPath)) { - return $this->dataDir . '/sabredav_' . md5($path) . '.tempfile'; + return $this->getDataDir() . '/sabredav_' . md5($path) . '.tempfile'; } } @@ -175,9 +175,9 @@ class Sabre_DAV_TemporaryFileFilterPlugin extends Sabre_DAV_ServerPlugin { * This method handles the GET method for temporary files. * If the file doesn't exist, it will return false which will kick in * the regular system for the GET method. - * - * @param string $tempLocation - * @return bool + * + * @param string $tempLocation + * @return bool */ public function httpGet($tempLocation) { @@ -195,9 +195,9 @@ class Sabre_DAV_TemporaryFileFilterPlugin extends Sabre_DAV_ServerPlugin { /** * This method handles the PUT method. - * - * @param string $tempLocation - * @return bool + * + * @param string $tempLocation + * @return bool */ public function httpPut($tempLocation) { @@ -205,7 +205,7 @@ class Sabre_DAV_TemporaryFileFilterPlugin extends Sabre_DAV_ServerPlugin { $hR->setHeader('X-Sabre-Temp','true'); $newFile = !file_exists($tempLocation); - + if (!$newFile && ($this->server->httpRequest->getHeader('If-None-Match'))) { throw new Sabre_DAV_Exception_PreconditionFailed('The resource already exists, and an If-None-Match header was supplied'); } @@ -219,11 +219,11 @@ class Sabre_DAV_TemporaryFileFilterPlugin extends Sabre_DAV_ServerPlugin { /** * This method handles the DELETE method. * - * If the file didn't exist, it will return false, which will make the + * If the file didn't exist, it will return false, which will make the * standard HTTP DELETE handler kick in. - * - * @param string $tempLocation - * @return bool + * + * @param string $tempLocation + * @return bool */ public function httpDelete($tempLocation) { @@ -238,25 +238,26 @@ class Sabre_DAV_TemporaryFileFilterPlugin extends Sabre_DAV_ServerPlugin { } /** - * This method handles the PROPFIND method. + * This method handles the PROPFIND method. * * It's a very lazy method, it won't bother checking the request body * for which properties were requested, and just sends back a default * set of properties. * - * @param string $tempLocation - * @return void + * @param string $tempLocation + * @param string $uri + * @return bool */ public function httpPropfind($tempLocation, $uri) { if (!file_exists($tempLocation)) return true; - + $hR = $this->server->httpResponse; $hR->setHeader('X-Sabre-Temp','true'); $hR->sendStatus(207); $hR->setHeader('Content-Type','application/xml; charset=utf-8'); - $requestedProps = $this->server->parsePropFindRequest($this->server->httpRequest->getBody(true)); + $this->server->parsePropFindRequest($this->server->httpRequest->getBody(true)); $properties = array( 'href' => $uri, @@ -264,7 +265,7 @@ class Sabre_DAV_TemporaryFileFilterPlugin extends Sabre_DAV_ServerPlugin { '{DAV:}getlastmodified' => new Sabre_DAV_Property_GetLastModified(filemtime($tempLocation)), '{DAV:}getcontentlength' => filesize($tempLocation), '{DAV:}resourcetype' => new Sabre_DAV_Property_ResourceType(null), - '{'.Sabre_DAV_Server::NS_SABREDAV.'}tempFile' => true, + '{'.Sabre_DAV_Server::NS_SABREDAV.'}tempFile' => true, ), ); @@ -276,4 +277,13 @@ class Sabre_DAV_TemporaryFileFilterPlugin extends Sabre_DAV_ServerPlugin { } + /** + * This method returns the directory where the temporary files should be stored. + * + * @return string + */ + protected function getDataDir() + { + return $this->dataDir; + } } diff --git a/3rdparty/Sabre/DAV/Tree.php b/3rdparty/Sabre/DAV/Tree.php index 98e6f62c9e5..50216394155 100644..100755 --- a/3rdparty/Sabre/DAV/Tree.php +++ b/3rdparty/Sabre/DAV/Tree.php @@ -1,34 +1,34 @@ <?php /** - * Abstract tree object - * + * Abstract tree object + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_Tree { - + /** * This function must return an INode object for a path - * If a Path doesn't exist, thrown an Exception_FileNotFound - * - * @param string $path - * @throws Exception_FileNotFound - * @return Sabre_DAV_INode + * If a Path doesn't exist, thrown a Exception_NotFound + * + * @param string $path + * @throws Sabre_DAV_Exception_NotFound + * @return Sabre_DAV_INode */ abstract function getNodeForPath($path); /** * This function allows you to check if a node exists. * - * Implementors of this class should override this method to make + * Implementors of this class should override this method to make * it cheaper. - * - * @param string $path - * @return bool + * + * @param string $path + * @return bool */ public function nodeExists($path) { @@ -37,7 +37,7 @@ abstract class Sabre_DAV_Tree { $this->getNodeForPath($path); return true; - } catch (Sabre_DAV_Exception_FileNotFound $e) { + } catch (Sabre_DAV_Exception_NotFound $e) { return false; @@ -50,12 +50,12 @@ abstract class Sabre_DAV_Tree { * * @param string $sourcePath The source location * @param string $destinationPath The full destination path - * @return void + * @return void */ public function copy($sourcePath, $destinationPath) { $sourceNode = $this->getNodeForPath($sourcePath); - + // grab the dirname and basename components list($destinationDir, $destinationName) = Sabre_DAV_URLUtil::splitPath($destinationPath); @@ -67,9 +67,9 @@ abstract class Sabre_DAV_Tree { } /** - * Moves a file from one location to another - * - * @param string $sourcePath The path to the file which should be moved + * Moves a file from one location to another + * + * @param string $sourcePath The path to the file which should be moved * @param string $destinationPath The full destination path, so not just the destination parent node * @return int */ @@ -91,26 +91,26 @@ abstract class Sabre_DAV_Tree { } /** - * Deletes a node from the tree - * - * @param string $path + * Deletes a node from the tree + * + * @param string $path * @return void */ public function delete($path) { $node = $this->getNodeForPath($path); $node->delete(); - + list($parent) = Sabre_DAV_URLUtil::splitPath($path); $this->markDirty($parent); } /** - * Returns a list of childnodes for a given path. - * - * @param string $path - * @return array + * Returns a list of childnodes for a given path. + * + * @param string $path + * @return array */ public function getChildren($path) { @@ -127,14 +127,14 @@ abstract class Sabre_DAV_Tree { * * node creations * * copy * * move - * * renaming nodes - * + * * renaming nodes + * * If Tree classes implement a form of caching, this will allow * them to make sure caches will be expired. - * + * * If a path is passed, it is assumed that the entire subtree is dirty * - * @param string $path + * @param string $path * @return void */ public function markDirty($path) { @@ -143,10 +143,11 @@ abstract class Sabre_DAV_Tree { } /** - * copyNode - * - * @param Sabre_DAV_INode $source - * @param Sabre_DAV_ICollection $destination + * copyNode + * + * @param Sabre_DAV_INode $source + * @param Sabre_DAV_ICollection $destinationParent + * @param string $destinationName * @return void */ protected function copyNode(Sabre_DAV_INode $source,Sabre_DAV_ICollection $destinationParent,$destinationName = null) { @@ -163,14 +164,14 @@ abstract class Sabre_DAV_Tree { fwrite($stream,$data); rewind($stream); $data = $stream; - } + } $destinationParent->createFile($destinationName,$data); $destination = $destinationParent->getChild($destinationName); } elseif ($source instanceof Sabre_DAV_ICollection) { $destinationParent->createDirectory($destinationName); - + $destination = $destinationParent->getChild($destinationName); foreach($source->getChildren() as $child) { diff --git a/3rdparty/Sabre/DAV/Tree/Filesystem.php b/3rdparty/Sabre/DAV/Tree/Filesystem.php index 5c611047e07..85a9ee317be 100644..100755 --- a/3rdparty/Sabre/DAV/Tree/Filesystem.php +++ b/3rdparty/Sabre/DAV/Tree/Filesystem.php @@ -1,12 +1,12 @@ <?php /** - * Sabre_DAV_Tree_Filesystem - * + * Sabre_DAV_Tree_Filesystem + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_Tree_Filesystem extends Sabre_DAV_Tree { @@ -14,7 +14,7 @@ class Sabre_DAV_Tree_Filesystem extends Sabre_DAV_Tree { /** * Base url on the filesystem. * - * @var string + * @var string */ protected $basePath; @@ -22,9 +22,8 @@ class Sabre_DAV_Tree_Filesystem extends Sabre_DAV_Tree { * Creates this tree * * Supply the path you'd like to share. - * - * @param string $basePath - * @return void + * + * @param string $basePath */ public function __construct($basePath) { @@ -33,16 +32,16 @@ class Sabre_DAV_Tree_Filesystem extends Sabre_DAV_Tree { } /** - * Returns a new node for the given path - * - * @param string $path - * @return void + * Returns a new node for the given path + * + * @param string $path + * @return Sabre_DAV_FS_Node */ public function getNodeForPath($path) { $realPath = $this->getRealPath($path); - if (!file_exists($realPath)) throw new Sabre_DAV_Exception_FileNotFound('File at location ' . $realPath . ' not found'); - if (is_dir($realPath)) { + if (!file_exists($realPath)) throw new Sabre_DAV_Exception_NotFound('File at location ' . $realPath . ' not found'); + if (is_dir($realPath)) { return new Sabre_DAV_FS_Directory($path); } else { return new Sabre_DAV_FS_File($path); @@ -51,10 +50,10 @@ class Sabre_DAV_Tree_Filesystem extends Sabre_DAV_Tree { } /** - * Returns the real filesystem path for a webdav url. - * - * @param string $publicPath - * @return string + * Returns the real filesystem path for a webdav url. + * + * @param string $publicPath + * @return string */ protected function getRealPath($publicPath) { @@ -67,24 +66,24 @@ class Sabre_DAV_Tree_Filesystem extends Sabre_DAV_Tree { * * This method must work recursively and delete the destination * if it exists - * - * @param string $source - * @param string $destination + * + * @param string $source + * @param string $destination * @return void */ public function copy($source,$destination) { $source = $this->getRealPath($source); $destination = $this->getRealPath($destination); - $this->realCopy($source,$destination); + $this->realCopy($source,$destination); } /** - * Used by self::copy - * - * @param string $source - * @param string $destination + * Used by self::copy + * + * @param string $source + * @param string $destination * @return void */ protected function realCopy($source,$destination) { @@ -107,9 +106,9 @@ class Sabre_DAV_Tree_Filesystem extends Sabre_DAV_Tree { * Moves a file or directory recursively. * * If the destination exists, delete it first. - * - * @param string $source - * @param string $destination + * + * @param string $source + * @param string $destination * @return void */ public function move($source,$destination) { diff --git a/3rdparty/Sabre/DAV/URLUtil.php b/3rdparty/Sabre/DAV/URLUtil.php index 8f38749264b..794665a44f6 100644..100755 --- a/3rdparty/Sabre/DAV/URLUtil.php +++ b/3rdparty/Sabre/DAV/URLUtil.php @@ -11,11 +11,11 @@ * Specifically, it was found that GVFS (gnome's webdav client) does not like encoding of ( and * ). Since these are reserved, but don't have a reserved meaning in url, these characters are * kept as-is. - * + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_URLUtil { @@ -24,46 +24,42 @@ class Sabre_DAV_URLUtil { * Encodes the path of a url. * * slashes (/) are treated as path-separators. - * - * @param string $path - * @return string + * + * @param string $path + * @return string */ static function encodePath($path) { - $valid_chars = '/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-.~()'; - $newStr = ''; - for( $i=0; isset($path[$i]); ++$i ) { - if( strpos($valid_chars,($c=$path[$i]))===false ) $newStr .= '%'.sprintf('%02x',ord($c)); - else $newStr .= $c; - } - return $newStr; - + return preg_replace_callback('/([^A-Za-z0-9_\-\.~\(\)\/])/',function($match) { + + return '%'.sprintf('%02x',ord($match[0])); + + }, $path); + } /** * Encodes a 1 segment of a path * * Slashes are considered part of the name, and are encoded as %2f - * - * @param string $pathSegment - * @return string + * + * @param string $pathSegment + * @return string */ static function encodePathSegment($pathSegment) { - $valid_chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-.~()'; - $newStr = ''; - for( $i=0; isset($pathSegment[$i]); ++$i ) { - if( strpos($valid_chars,($c=$pathSegment[$i]))===false ) $newStr .= '%'.sprintf('%02x',ord($c)); - else $newStr .= $c; - } - return $newStr; + return preg_replace_callback('/([^A-Za-z0-9_\-\.~\(\)])/',function($match) { + + return '%'.sprintf('%02x',ord($match[0])); + + }, $pathSegment); } /** * Decodes a url-encoded path * - * @param string $path - * @return string + * @param string $path + * @return string */ static function decodePath($path) { @@ -74,17 +70,17 @@ class Sabre_DAV_URLUtil { /** * Decodes a url-encoded path segment * - * @param string $path - * @return string + * @param string $path + * @return string */ static function decodePathSegment($path) { - $path = urldecode($path); + $path = rawurldecode($path); $encoding = mb_detect_encoding($path, array('UTF-8','ISO-8859-1')); switch($encoding) { - case 'ISO-8859-1' : + case 'ISO-8859-1' : $path = utf8_encode($path); } @@ -94,7 +90,7 @@ class Sabre_DAV_URLUtil { } /** - * Returns the 'dirname' and 'basename' for a path. + * Returns the 'dirname' and 'basename' for a path. * * The reason there is a custom function for this purpose, is because * basename() is locale aware (behaviour changes if C locale or a UTF-8 locale is used) @@ -108,8 +104,8 @@ class Sabre_DAV_URLUtil { * If there is no dirname, it will return an empty string. Any / appearing at the end of the * string is stripped off. * - * @param string $path - * @return array + * @param string $path + * @return array */ static function splitPath($path) { diff --git a/3rdparty/Sabre/DAV/UUIDUtil.php b/3rdparty/Sabre/DAV/UUIDUtil.php index e42a536ad8a..f0eebe598e5 100644..100755 --- a/3rdparty/Sabre/DAV/UUIDUtil.php +++ b/3rdparty/Sabre/DAV/UUIDUtil.php @@ -4,13 +4,13 @@ * UUID Utility * * This class has static methods to generate and validate UUID's. - * UUIDs are used a decent amount within various *DAV standards, so it made + * UUIDs are used a decent amount within various *DAV standards, so it made * sense to include it. - * + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_UUIDUtil { @@ -18,10 +18,10 @@ class Sabre_DAV_UUIDUtil { /** * Returns a pseudo-random v4 UUID * - * This function is based on a comment by Andrew Moore on php.net - * + * This function is based on a comment by Andrew Moore on php.net + * * @see http://www.php.net/manual/en/function.uniqid.php#94959 - * @return void + * @return string */ static function getUUID() { @@ -48,9 +48,9 @@ class Sabre_DAV_UUIDUtil { /** * Checks if a string is a valid UUID. - * - * @param string $uuid - * @return bool + * + * @param string $uuid + * @return bool */ static function validateUUID($uuid) { diff --git a/3rdparty/Sabre/DAV/Version.php b/3rdparty/Sabre/DAV/Version.php index 6bece1985e4..5e5d15e4039 100644..100755 --- a/3rdparty/Sabre/DAV/Version.php +++ b/3rdparty/Sabre/DAV/Version.php @@ -2,10 +2,10 @@ /** * This class contains the SabreDAV version constants. - * + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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_DAV_Version { /** * Full version number */ - const VERSION = '1.5.4'; + const VERSION = '1.6.2'; /** * Stability : alpha, beta, stable diff --git a/3rdparty/Sabre/DAV/XMLUtil.php b/3rdparty/Sabre/DAV/XMLUtil.php index bd05be4b229..60eff3b159a 100644..100755 --- a/3rdparty/Sabre/DAV/XMLUtil.php +++ b/3rdparty/Sabre/DAV/XMLUtil.php @@ -2,32 +2,32 @@ /** * XML utilities for WebDAV - * + * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_XMLUtil { /** * Returns the 'clark notation' for an element. - * + * * For example, and element encoded as: * <b:myelem xmlns:b="http://www.example.org/" /> * will be returned as: * {http://www.example.org}myelem * * This format is used throughout the SabreDAV sourcecode. - * Elements encoded with the urn:DAV namespace will + * Elements encoded with the urn:DAV namespace will * be returned as if they were in the DAV: namespace. This is to avoid * compatibility problems. * * This function will return null if a nodetype other than an Element is passed. * - * @param DOMElement $dom - * @return string + * @param DOMNode $dom + * @return string */ static function toClarkNotation(DOMNode $dom) { @@ -35,21 +35,21 @@ class Sabre_DAV_XMLUtil { // Mapping back to the real namespace, in case it was dav if ($dom->namespaceURI=='urn:DAV') $ns = 'DAV:'; else $ns = $dom->namespaceURI; - + // Mapping to clark notation return '{' . $ns . '}' . $dom->localName; } /** - * Parses a clark-notation string, and returns the namespace and element + * Parses a clark-notation string, and returns the namespace and element * name components. * * If the string was invalid, it will throw an InvalidArgumentException. - * + * * @param string $str - * @throws InvalidArgumentException - * @return array + * @throws InvalidArgumentException + * @return array */ static function parseClarkNotation($str) { @@ -70,6 +70,9 @@ class Sabre_DAV_XMLUtil { * * This is unfortunately needed, because the DAV: namespace violates the xml namespaces * spec, and causes the DOM to throw errors + * + * @param string $xmlDocument + * @return array|string|null */ static function convertDAVNamespace($xmlDocument) { @@ -83,17 +86,17 @@ class Sabre_DAV_XMLUtil { * This method provides a generic way to load a DOMDocument for WebDAV use. * * This method throws a Sabre_DAV_Exception_BadRequest exception for any xml errors. - * It does not preserve whitespace, and it converts the DAV: namespace to urn:DAV. - * + * It does not preserve whitespace, and it converts the DAV: namespace to urn:DAV. + * * @param string $xml - * @throws Sabre_DAV_Exception_BadRequest - * @return DOMDocument + * @throws Sabre_DAV_Exception_BadRequest + * @return DOMDocument */ static function loadDOMDocument($xml) { if (empty($xml)) throw new Sabre_DAV_Exception_BadRequest('Empty XML document sent'); - + // The BitKinex client sends xml documents as UTF-16. PHP 5.3.1 (and presumably lower) // does not support this, so we must intercept this and convert to UTF-8. if (substr($xml,0,12) === "\x3c\x00\x3f\x00\x78\x00\x6d\x00\x6c\x00\x20\x00") { @@ -111,7 +114,7 @@ class Sabre_DAV_XMLUtil { // Retaining old error setting $oldErrorSetting = libxml_use_internal_errors(true); - // Clearing any previous errors + // Clearing any previous errors libxml_clear_errors(); $dom = new DOMDocument(); @@ -135,7 +138,7 @@ class Sabre_DAV_XMLUtil { /** * Parses all WebDAV properties out of a DOM Element * - * Generally WebDAV properties are encloded in {DAV:}prop elements. This + * Generally WebDAV properties are enclosed in {DAV:}prop elements. This * method helps by going through all these and pulling out the actual * propertynames, making them array keys and making the property values, * well.. the array values. @@ -145,7 +148,7 @@ class Sabre_DAV_XMLUtil { * * Complex values are supported through the propertyMap argument. The * propertyMap should have the clark-notation properties as it's keys, and - * classnames as values. + * classnames as values. * * When any of these properties are found, the unserialize() method will be * (statically) called. The result of this method is used as the value. @@ -168,7 +171,7 @@ class Sabre_DAV_XMLUtil { $propertyName = Sabre_DAV_XMLUtil::toClarkNotation($propNodeData); if (isset($propertyMap[$propertyName])) { - $propList[$propertyName] = call_user_func(array($propertyMap[$propertyName],'unserialize'),$propNodeData); + $propList[$propertyName] = call_user_func(array($propertyMap[$propertyName],'unserialize'),$propNodeData); } else { $propList[$propertyName] = $propNodeData->textContent; } diff --git a/3rdparty/Sabre/DAV/includes.php b/3rdparty/Sabre/DAV/includes.php new file mode 100755 index 00000000000..6a4890677ea --- /dev/null +++ b/3rdparty/Sabre/DAV/includes.php @@ -0,0 +1,97 @@ +<?php + +/** + * Sabre_DAV includes file + * + * Including this file will automatically include all files from the Sabre_DAV + * package. + * + * This often allows faster loadtimes, as autoload-speed is often quite slow. + * + * @package Sabre + * @subpackage DAV + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. + * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License + */ + +// Begin includes +include __DIR__ . '/Auth/IBackend.php'; +include __DIR__ . '/Client.php'; +include __DIR__ . '/Exception.php'; +include __DIR__ . '/INode.php'; +include __DIR__ . '/IProperties.php'; +include __DIR__ . '/Locks/Backend/Abstract.php'; +include __DIR__ . '/Locks/Backend/File.php'; +include __DIR__ . '/Locks/Backend/FS.php'; +include __DIR__ . '/Locks/Backend/PDO.php'; +include __DIR__ . '/Locks/LockInfo.php'; +include __DIR__ . '/Node.php'; +include __DIR__ . '/Property/IHref.php'; +include __DIR__ . '/Property.php'; +include __DIR__ . '/Server.php'; +include __DIR__ . '/ServerPlugin.php'; +include __DIR__ . '/StringUtil.php'; +include __DIR__ . '/TemporaryFileFilterPlugin.php'; +include __DIR__ . '/Tree.php'; +include __DIR__ . '/URLUtil.php'; +include __DIR__ . '/UUIDUtil.php'; +include __DIR__ . '/Version.php'; +include __DIR__ . '/XMLUtil.php'; +include __DIR__ . '/Auth/Backend/AbstractBasic.php'; +include __DIR__ . '/Auth/Backend/AbstractDigest.php'; +include __DIR__ . '/Auth/Backend/Apache.php'; +include __DIR__ . '/Auth/Backend/File.php'; +include __DIR__ . '/Auth/Backend/PDO.php'; +include __DIR__ . '/Auth/Plugin.php'; +include __DIR__ . '/Browser/GuessContentType.php'; +include __DIR__ . '/Browser/MapGetToPropFind.php'; +include __DIR__ . '/Browser/Plugin.php'; +include __DIR__ . '/Exception/BadRequest.php'; +include __DIR__ . '/Exception/Conflict.php'; +include __DIR__ . '/Exception/Forbidden.php'; +include __DIR__ . '/Exception/InsufficientStorage.php'; +include __DIR__ . '/Exception/InvalidResourceType.php'; +include __DIR__ . '/Exception/Locked.php'; +include __DIR__ . '/Exception/LockTokenMatchesRequestUri.php'; +include __DIR__ . '/Exception/MethodNotAllowed.php'; +include __DIR__ . '/Exception/NotAuthenticated.php'; +include __DIR__ . '/Exception/NotFound.php'; +include __DIR__ . '/Exception/NotImplemented.php'; +include __DIR__ . '/Exception/PaymentRequired.php'; +include __DIR__ . '/Exception/PreconditionFailed.php'; +include __DIR__ . '/Exception/ReportNotImplemented.php'; +include __DIR__ . '/Exception/RequestedRangeNotSatisfiable.php'; +include __DIR__ . '/Exception/UnsupportedMediaType.php'; +include __DIR__ . '/FS/Node.php'; +include __DIR__ . '/FSExt/Node.php'; +include __DIR__ . '/ICollection.php'; +include __DIR__ . '/IExtendedCollection.php'; +include __DIR__ . '/IFile.php'; +include __DIR__ . '/IQuota.php'; +include __DIR__ . '/Locks/Plugin.php'; +include __DIR__ . '/Mount/Plugin.php'; +include __DIR__ . '/ObjectTree.php'; +include __DIR__ . '/Property/GetLastModified.php'; +include __DIR__ . '/Property/Href.php'; +include __DIR__ . '/Property/HrefList.php'; +include __DIR__ . '/Property/LockDiscovery.php'; +include __DIR__ . '/Property/ResourceType.php'; +include __DIR__ . '/Property/Response.php'; +include __DIR__ . '/Property/ResponseList.php'; +include __DIR__ . '/Property/SupportedLock.php'; +include __DIR__ . '/Property/SupportedReportSet.php'; +include __DIR__ . '/Tree/Filesystem.php'; +include __DIR__ . '/Collection.php'; +include __DIR__ . '/Directory.php'; +include __DIR__ . '/Exception/ConflictingLock.php'; +include __DIR__ . '/Exception/FileNotFound.php'; +include __DIR__ . '/File.php'; +include __DIR__ . '/FS/Directory.php'; +include __DIR__ . '/FS/File.php'; +include __DIR__ . '/FSExt/Directory.php'; +include __DIR__ . '/FSExt/File.php'; +include __DIR__ . '/SimpleCollection.php'; +include __DIR__ . '/SimpleDirectory.php'; +include __DIR__ . '/SimpleFile.php'; +// End includes diff --git a/3rdparty/Sabre/DAVACL/AbstractPrincipalCollection.php b/3rdparty/Sabre/DAVACL/AbstractPrincipalCollection.php index a361e054610..e05b7749805 100644..100755 --- a/3rdparty/Sabre/DAVACL/AbstractPrincipalCollection.php +++ b/3rdparty/Sabre/DAVACL/AbstractPrincipalCollection.php @@ -3,53 +3,52 @@ /** * Principals Collection * - * This is a helper class that easily allows you to create a collection that + * This is a helper class that easily allows you to create a collection that * has a childnode for every principal. - * - * To use this class, simply implement the getChildForPrincipal method. + * + * To use this class, simply implement the getChildForPrincipal method. * * @package Sabre * @subpackage DAVACL - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_DAVACL_AbstractPrincipalCollection extends Sabre_DAV_Collection { /** - * Node or 'directory' name. - * - * @var string + * Node or 'directory' name. + * + * @var string */ protected $path; /** - * Principal backend - * - * @var Sabre_DAVACL_IPrincipalBackend + * Principal backend + * + * @var Sabre_DAVACL_IPrincipalBackend */ protected $principalBackend; /** * If this value is set to true, it effectively disables listing of users - * it still allows user to find other users if they have an exact url. - * - * @var bool + * it still allows user to find other users if they have an exact url. + * + * @var bool */ public $disableListing = false; /** * Creates the object * - * This object must be passed the principal backend. This object will - * filter all principals from a specfied prefix ($principalPrefix). The - * default is 'principals', if your principals are stored in a different + * This object must be passed the principal backend. This object will + * filter all principals from a specified prefix ($principalPrefix). The + * default is 'principals', if your principals are stored in a different * collection, override $principalPrefix - * - * - * @param Sabre_DAVACL_IPrincipalBackend $principalBackend + * + * + * @param Sabre_DAVACL_IPrincipalBackend $principalBackend * @param string $principalPrefix - * @param string $nodeName */ public function __construct(Sabre_DAVACL_IPrincipalBackend $principalBackend, $principalPrefix = 'principals') { @@ -64,28 +63,28 @@ abstract class Sabre_DAVACL_AbstractPrincipalCollection extends Sabre_DAV_Collec * 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 + * + * @param array $principalInfo * @return Sabre_DAVACL_IPrincipal */ abstract function getChildForPrincipal(array $principalInfo); /** - * Returns the name of this collection. - * - * @return string + * Returns the name of this collection. + * + * @return string */ public function getName() { list(,$name) = Sabre_DAV_URLUtil::splitPath($this->principalPrefix); - return $name; + return $name; } /** - * Return the list of users - * - * @return void + * Return the list of users + * + * @return array */ public function getChildren() { @@ -99,23 +98,57 @@ abstract class Sabre_DAVACL_AbstractPrincipalCollection extends Sabre_DAV_Collec } - return $children; + return $children; } /** * Returns a child object, by its name. - * + * * @param string $name - * @throws Sabre_DAV_Exception_FileNotFound + * @throws Sabre_DAV_Exception_NotFound * @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'); + if (!$principalInfo) throw new Sabre_DAV_Exception_NotFound('Principal with name ' . $name . ' not found'); return $this->getChildForPrincipal($principalInfo); } + /** + * This method is used to search for principals matching a set of + * properties. + * + * This search is specifically used by RFC3744's principal-property-search + * REPORT. You should at least allow searching on + * http://sabredav.org/ns}email-address. + * + * The actual search should be a unicode-non-case-sensitive search. The + * keys in searchProperties are the WebDAV property names, while the values + * are the property values to search on. + * + * If multiple properties are being searched on, the search should be + * AND'ed. + * + * This method should simply return a list of 'child names', which may be + * used to call $this->getChild in the future. + * + * @param array $searchProperties + * @return array + */ + public function searchPrincipals(array $searchProperties) { + + $result = $this->principalBackend->searchPrincipals($this->principalPrefix, $searchProperties); + $r = array(); + + foreach($result as $row) { + list(, $r[]) = Sabre_DAV_URLUtil::splitPath($row); + } + + return $r; + + } + } diff --git a/3rdparty/Sabre/DAVACL/Exception/AceConflict.php b/3rdparty/Sabre/DAVACL/Exception/AceConflict.php index d10aeb4345c..4b9f93b0036 100644..100755 --- a/3rdparty/Sabre/DAVACL/Exception/AceConflict.php +++ b/3rdparty/Sabre/DAVACL/Exception/AceConflict.php @@ -1,12 +1,12 @@ <?php /** - * Sabre_DAVACL_Exception_AceConflict - * + * Sabre_DAVACL_Exception_AceConflict + * * @package Sabre * @subpackage DAVACL - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_DAVACL_Exception_AceConflict extends Sabre_DAV_Exception_Conflict { @@ -15,20 +15,18 @@ class Sabre_DAVACL_Exception_AceConflict extends Sabre_DAV_Exception_Conflict { * Adds in extra information in the xml response. * * This method adds the {DAV:}no-ace-conflict element as defined in rfc3744 - * - * @param Sabre_DAV_Server $server - * @param DOMElement $errorNode + * + * @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:no-ace-conflict'); $errorNode->appendChild($np); } } - -?> diff --git a/3rdparty/Sabre/DAVACL/Exception/NeedPrivileges.php b/3rdparty/Sabre/DAVACL/Exception/NeedPrivileges.php index 024ab6641f3..9b055dd9709 100644..100755 --- a/3rdparty/Sabre/DAVACL/Exception/NeedPrivileges.php +++ b/3rdparty/Sabre/DAVACL/Exception/NeedPrivileges.php @@ -1,60 +1,61 @@ <?php /** - * NeedPrivileges + * NeedPrivileges * * The 403-need privileges is thrown when a user didn't have the appropriate * permissions to perform an operation - * + * * @package Sabre * @subpackage DAVACL - * @version $Id$ - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_DAVACL_Exception_NeedPrivileges extends Sabre_DAV_Exception_Forbidden { /** - * The relevant uri - * - * @var string + * The relevant uri + * + * @var string */ protected $uri; /** - * The privileges the user didn't have. - * - * @var array + * The privileges the user didn't have. + * + * @var array */ protected $privileges; /** - * Constructor - * - * @param string $uri - * @param array $privileges + * Constructor + * + * @param string $uri + * @param array $privileges */ public function __construct($uri,array $privileges) { $this->uri = $uri; $this->privileges = $privileges; + parent::__construct('User did not have the required privileges (' . implode(',', $privileges) . ') for path "' . $uri . '"'); + } /** * 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 + * + * @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); diff --git a/3rdparty/Sabre/DAVACL/Exception/NoAbstract.php b/3rdparty/Sabre/DAVACL/Exception/NoAbstract.php index 60f49ebff4a..f44e3e32281 100644..100755 --- a/3rdparty/Sabre/DAVACL/Exception/NoAbstract.php +++ b/3rdparty/Sabre/DAVACL/Exception/NoAbstract.php @@ -2,11 +2,11 @@ /** * Sabre_DAVACL_Exception_NoAbstract - * + * * @package Sabre * @subpackage DAVACL - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_DAVACL_Exception_NoAbstract extends Sabre_DAV_Exception_PreconditionFailed { @@ -15,20 +15,18 @@ class Sabre_DAVACL_Exception_NoAbstract extends Sabre_DAV_Exception_Precondition * Adds in extra information in the xml response. * * This method adds the {DAV:}no-abstract element as defined in rfc3744 - * - * @param Sabre_DAV_Server $server - * @param DOMElement $errorNode + * + * @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:no-abstract'); $errorNode->appendChild($np); } } - -?> diff --git a/3rdparty/Sabre/DAVACL/Exception/NotRecognizedPrincipal.php b/3rdparty/Sabre/DAVACL/Exception/NotRecognizedPrincipal.php index e056dc9e4f7..8d1e38ca1b4 100644..100755 --- a/3rdparty/Sabre/DAVACL/Exception/NotRecognizedPrincipal.php +++ b/3rdparty/Sabre/DAVACL/Exception/NotRecognizedPrincipal.php @@ -2,11 +2,11 @@ /** * Sabre_DAVACL_Exception_NotRecognizedPrincipal - * + * * @package Sabre * @subpackage DAVACL - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_DAVACL_Exception_NotRecognizedPrincipal extends Sabre_DAV_Exception_PreconditionFailed { @@ -15,20 +15,18 @@ class Sabre_DAVACL_Exception_NotRecognizedPrincipal extends Sabre_DAV_Exception_ * Adds in extra information in the xml response. * * This method adds the {DAV:}recognized-principal element as defined in rfc3744 - * - * @param Sabre_DAV_Server $server - * @param DOMElement $errorNode + * + * @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:recognized-principal'); $errorNode->appendChild($np); } } - -?> diff --git a/3rdparty/Sabre/DAVACL/Exception/NotSupportedPrivilege.php b/3rdparty/Sabre/DAVACL/Exception/NotSupportedPrivilege.php index 27db7cdd7dd..3b5d012d7fa 100644..100755 --- a/3rdparty/Sabre/DAVACL/Exception/NotSupportedPrivilege.php +++ b/3rdparty/Sabre/DAVACL/Exception/NotSupportedPrivilege.php @@ -2,11 +2,11 @@ /** * Sabre_DAVACL_Exception_NotSupportedPrivilege - * + * * @package Sabre * @subpackage DAVACL - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_DAVACL_Exception_NotSupportedPrivilege extends Sabre_DAV_Exception_PreconditionFailed { @@ -15,20 +15,18 @@ class Sabre_DAVACL_Exception_NotSupportedPrivilege extends Sabre_DAV_Exception_P * Adds in extra information in the xml response. * * This method adds the {DAV:}not-supported-privilege element as defined in rfc3744 - * - * @param Sabre_DAV_Server $server - * @param DOMElement $errorNode + * + * @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:not-supported-privilege'); $errorNode->appendChild($np); } } - -?> diff --git a/3rdparty/Sabre/DAVACL/IACL.php b/3rdparty/Sabre/DAVACL/IACL.php index 506be4248d7..003e6993483 100644..100755 --- a/3rdparty/Sabre/DAVACL/IACL.php +++ b/3rdparty/Sabre/DAVACL/IACL.php @@ -4,11 +4,11 @@ * ACL-enabled node * * If you want to add WebDAV ACL to a node, you must implement this class - * + * * @package Sabre * @subpackage DAVACL - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. + * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ interface Sabre_DAVACL_IACL extends Sabre_DAV_INode { @@ -16,8 +16,8 @@ interface Sabre_DAVACL_IACL extends Sabre_DAV_INode { /** * Returns the owner principal * - * This must be a url to a principal, or null if there's no owner - * + * This must be a url to a principal, or null if there's no owner + * * @return string|null */ function getOwner(); @@ -26,8 +26,8 @@ interface Sabre_DAVACL_IACL extends Sabre_DAV_INode { * Returns a group principal * * This must be a url to a principal, or null if there's no owner - * - * @return string|null + * + * @return string|null */ function getGroup(); @@ -35,24 +35,39 @@ interface Sabre_DAVACL_IACL extends Sabre_DAV_INode { * 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 + * * '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 + * * 'protected' (optional), indicating that this ACE is not allowed to + * be updated. + * + * @return array */ function getACL(); /** * Updates the ACL * - * This method will receive a list of new ACE's. - * - * @param array $acl + * This method will receive a list of new ACE's. + * + * @param array $acl * @return void */ function setACL(array $acl); + /** + * Returns the list of supported privileges for this node. + * + * The returned data structure is a list of nested privileges. + * See Sabre_DAVACL_Plugin::getDefaultSupportedPrivilegeSet for a simple + * standard structure. + * + * If null is returned from this method, the default privilege set is used, + * which is fine for most common usecases. + * + * @return array|null + */ + function getSupportedPrivilegeSet(); + + } diff --git a/3rdparty/Sabre/DAVACL/IPrincipal.php b/3rdparty/Sabre/DAVACL/IPrincipal.php index 7868811db76..fc7605bf625 100644..100755 --- a/3rdparty/Sabre/DAVACL/IPrincipal.php +++ b/3rdparty/Sabre/DAVACL/IPrincipal.php @@ -2,50 +2,50 @@ /** * IPrincipal interface - * + * * Implement this interface to define your own principals - * + * * @package Sabre * @subpackage DAVACL - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. + * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ interface Sabre_DAVACL_IPrincipal extends Sabre_DAV_INode { /** - * Returns a list of altenative urls for a principal - * + * Returns a list of alternative urls for a principal + * * This can for example be an email address, or ldap url. - * - * @return array + * + * @return array */ function getAlternateUriSet(); /** - * Returns the full principal url - * - * @return string + * Returns the full principal url + * + * @return string */ function getPrincipalUrl(); /** * Returns the list of group members - * + * * If this principal is a group, this function should return - * all member principal uri's for the group. - * + * all member principal uri's for the group. + * * @return array */ function getGroupMemberSet(); /** * 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 + * should return a list of principal uri's for it's members. + * + * @return array */ function getGroupMembership(); @@ -54,11 +54,11 @@ interface Sabre_DAVACL_IPrincipal extends Sabre_DAV_INode { * * 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 + * + * This method should throw an exception if the members could not be set. + * + * @param array $principals + * @return void */ function setGroupMemberSet(array $principals); @@ -66,9 +66,9 @@ interface Sabre_DAVACL_IPrincipal extends Sabre_DAV_INode { * Returns the displayname * * This should be a human readable name for the principal. - * If none is available, return the nodename. - * - * @return string + * If none is available, return the nodename. + * + * @return string */ function getDisplayName(); diff --git a/3rdparty/Sabre/DAVACL/IPrincipalBackend.php b/3rdparty/Sabre/DAVACL/IPrincipalBackend.php index 8899f6f80df..e798bf890c0 100644..100755 --- a/3rdparty/Sabre/DAVACL/IPrincipalBackend.php +++ b/3rdparty/Sabre/DAVACL/IPrincipalBackend.php @@ -3,14 +3,14 @@ /** * Implement this interface to create your own principal backends. * - * Creating backends for principals is entirely optional. You can also - * implement Sabre_DAVACL_IPrincipal directly. This interface is used solely by + * Creating backends for principals is entirely optional. You can also + * implement Sabre_DAVACL_IPrincipal directly. This interface is used solely by * Sabre_DAVACL_AbstractPrincipalCollection. * * @package Sabre * @subpackage DAVACL - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. + * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ interface Sabre_DAVACL_IPrincipalBackend { @@ -18,56 +18,136 @@ interface Sabre_DAVACL_IPrincipalBackend { /** * Returns a list of principals based on a prefix. * - * This prefix will often contain something like 'principals'. You are only + * 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 + * 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 + * {DAV:}displayname + * {http://sabredav.org/ns}email-address - This is a custom SabreDAV + * field that's actually injected in a number of other properties. If * you have an email address, use this property. - * - * @param string $prefixPath - * @return array + * + * @param string $prefixPath + * @return array */ function getPrincipalsByPrefix($prefixPath); /** * 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 + * The returned structure should be the exact same as from + * getPrincipalsByPrefix. + * + * @param string $path + * @return array */ function getPrincipalByPath($path); /** - * Returns the list of members for a group-principal - * - * @param string $principal - * @return array + * Updates one ore more webdav properties on a principal. + * + * The list of mutations is supplied as an array. Each key in the array is + * a propertyname, such as {DAV:}displayname. + * + * Each value is the actual value to be updated. If a value is null, it + * must be deleted. + * + * This method should be atomic. It must either completely succeed, or + * completely fail. Success and failure can simply be returned as 'true' or + * 'false'. + * + * It is also possible to return detailed failure information. In that case + * an array such as this should be returned: + * + * array( + * 200 => array( + * '{DAV:}prop1' => null, + * ), + * 201 => array( + * '{DAV:}prop2' => null, + * ), + * 403 => array( + * '{DAV:}prop3' => null, + * ), + * 424 => array( + * '{DAV:}prop4' => null, + * ), + * ); + * + * In this previous example prop1 was successfully updated or deleted, and + * prop2 was succesfully created. + * + * prop3 failed to update due to '403 Forbidden' and because of this prop4 + * also could not be updated with '424 Failed dependency'. + * + * This last example was actually incorrect. While 200 and 201 could appear + * in 1 response, if there's any error (403) the other properties should + * always fail with 423 (failed dependency). + * + * But anyway, if you don't want to scratch your head over this, just + * return true or false. + * + * @param string $path + * @param array $mutations + * @return array|bool + */ + function updatePrincipal($path, $mutations); + + /** + * This method is used to search for principals matching a set of + * properties. + * + * This search is specifically used by RFC3744's principal-property-search + * REPORT. You should at least allow searching on + * http://sabredav.org/ns}email-address. + * + * The actual search should be a unicode-non-case-sensitive search. The + * keys in searchProperties are the WebDAV property names, while the values + * are the property values to search on. + * + * If multiple properties are being searched on, the search should be + * AND'ed. + * + * This method should simply return an array with full principal uri's. + * + * If somebody attempted to search on a property the backend does not + * support, you should simply return 0 results. + * + * You can also just return 0 results if you choose to not support + * searching at all, but keep in mind that this may stop certain features + * from working. + * + * @param string $prefixPath + * @param array $searchProperties + * @return array + */ + function searchPrincipals($prefixPath, array $searchProperties); + + /** + * Returns the list of members for a group-principal + * + * @param string $principal + * @return array */ function getGroupMemberSet($principal); /** - * Returns the list of groups a principal is a member of - * - * @param string $principal - * @return array + * Returns the list of groups a principal is a member of + * + * @param string $principal + * @return array */ function getGroupMembership($principal); /** * 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 + * The principals should be passed as a list of uri's. + * + * @param string $principal + * @param array $members * @return void */ - function setGroupMemberSet($principal, array $members); + function setGroupMemberSet($principal, array $members); } diff --git a/3rdparty/Sabre/DAVACL/Plugin.php b/3rdparty/Sabre/DAVACL/Plugin.php index b964bdb5dec..5c828c6d97b 100644..100755 --- a/3rdparty/Sabre/DAVACL/Plugin.php +++ b/3rdparty/Sabre/DAVACL/Plugin.php @@ -6,14 +6,14 @@ * This plugin provides funcitonality to enforce ACL permissions. * ACL is defined in RFC3744. * - * In addition it also provides support for the {DAV:}current-user-principal - * property, defined in RFC5397 and the {DAV:}expand-property report, as - * defined in RFC3253. - * + * In addition it also provides support for the {DAV:}current-user-principal + * property, defined in RFC5397 and the {DAV:}expand-property report, as + * defined in RFC3253. + * * @package Sabre * @subpackage DAVACL - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { @@ -40,16 +40,16 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { const R_RECURSIVEPARENTS = 3; /** - * Reference to server object. - * - * @var Sabre_DAV_Server + * Reference to server object. + * + * @var Sabre_DAV_Server */ protected $server; /** * List of urls containing principal collections. - * Modify this if your principals are located elsewhere. - * + * Modify this if your principals are located elsewhere. + * * @var array */ public $principalCollectionSet = array( @@ -57,14 +57,14 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { ); /** - * By default ACL is only enforced for nodes that have ACL support (the - * ones that implement Sabre_DAVACL_IACL). For any other node, access is + * By default ACL is only enforced for nodes that have ACL support (the + * ones that implement Sabre_DAVACL_IACL). For any other node, access is * always granted. * - * To override this behaviour you can turn this setting off. This is useful + * To override this behaviour you can turn this setting off. This is useful * if you plan to fully support ACL in the entire tree. * - * @var bool + * @var bool */ public $allowAccessToNodesWithoutACL = true; @@ -72,28 +72,50 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { * By default nodes that are inaccessible by the user, can still be seen * in directory listings (PROPFIND on parent with Depth: 1) * - * In certain cases it's desirable to hide inaccessible nodes. Setting this + * In certain cases it's desirable to hide inaccessible nodes. Setting this * to true will cause these nodes to be hidden from directory listings. - * - * @var bool + * + * @var bool */ public $hideNodesFromListings = false; /** - * This string is prepended to the username of the currently logged in - * user. This allows the plugin to determine the principal path based on + * This string is prepended to the username of the currently logged in + * user. This allows the plugin to determine the principal path based on * the username. - * + * * @var string */ public $defaultUsernamePath = 'principals'; /** + * This list of properties are the properties a client can search on using + * the {DAV:}principal-property-search report. + * + * The keys are the property names, values are descriptions. + * + * @var array + */ + public $principalSearchPropertySet = array( + '{DAV:}displayname' => 'Display name', + '{http://sabredav.org/ns}email-address' => 'Email address', + ); + + /** + * Any principal uri's added here, will automatically be added to the list + * of ACL's. They will effectively receive {DAV:}all privileges, as a + * protected privilege. + * + * @var array + */ + public $adminPrincipals = array(); + + /** * Returns a list of features added by this plugin. * * This list is used in the response of a HTTP OPTIONS request. - * - * @return array + * + * @return array */ public function getFeatures() { @@ -102,10 +124,10 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { } /** - * Returns a list of available methods for a given url - * - * @param string $uri - * @return array + * Returns a list of available methods for a given url + * + * @param string $uri + * @return array */ public function getMethods($uri) { @@ -115,11 +137,11 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { /** * Returns a plugin name. - * + * * Using this name other plugins will be able to access other plugins - * using Sabre_DAV_Server::getPlugin - * - * @return string + * using Sabre_DAV_Server::getPlugin + * + * @return string */ public function getPluginName() { @@ -131,37 +153,38 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { * 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 - * + * Note that you still need to subscribe to the 'report' event to actually + * implement them + * * @param string $uri - * @return array + * @return array */ public function getSupportedReportSet($uri) { return array( '{DAV:}expand-property', '{DAV:}principal-property-search', - '{DAV:}principal-search-property-set', + '{DAV:}principal-search-property-set', ); } /** - * Checks if the current user has the specified privilege(s). - * + * Checks if the current user has the specified privilege(s). + * * You can specify a single privilege, or a list of privileges. * This method will throw an exception if the privilege is not available * and return true otherwise. * * @param string $uri * @param array|string $privileges - * @param bool $throwExceptions if set to false, this method won't through exceptions. + * @param int $recursion + * @param bool $throwExceptions if set to false, this method won't through exceptions. * @throws Sabre_DAVACL_Exception_NeedPrivileges - * @return bool + * @return bool */ - public function checkPrivileges($uri,$privileges,$recursion = self::R_PARENT, $throwExceptions = true) { + public function checkPrivileges($uri, $privileges, $recursion = self::R_PARENT, $throwExceptions = true) { if (!is_array($privileges)) $privileges = array($privileges); @@ -171,7 +194,7 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { if ($this->allowAccessToNodesWithoutACL) { return true; } else { - if ($throwExceptions) + if ($throwExceptions) throw new Sabre_DAVACL_Exception_NeedPrivileges($uri,$privileges); else return false; @@ -189,7 +212,7 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { } if ($failed) { - if ($throwExceptions) + if ($throwExceptions) throw new Sabre_DAVACL_Exception_NeedPrivileges($uri,$failed); else return false; @@ -202,9 +225,9 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { * 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 + * This method will return null if the user wasn't logged in. + * + * @return string|null */ public function getCurrentUserPrincipal() { @@ -220,9 +243,9 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { /** * Returns a list of principals that's associated to the current - * user, either directly or through group membership. - * - * @return array + * user, either directly or through group membership. + * + * @return array */ public function getCurrentUserPrincipals() { @@ -236,7 +259,7 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { while(count($check)) { $principal = array_shift($check); - + $node = $this->server->tree->getNodeForPath($principal); if ($node instanceof Sabre_DAVACL_IPrincipal) { foreach($node->getGroupMembership() as $groupMember) { @@ -262,11 +285,38 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { * Returns the supported privilege structure for this ACL plugin. * * See RFC3744 for more details. Currently we default on a simple, - * standard structure. - * - * @return array + * standard structure. + * + * You can either get the list of privileges by a uri (path) or by + * specifying a Node. + * + * @param string|Sabre_DAV_INode $node + * @return array */ - public function getSupportedPrivilegeSet() { + public function getSupportedPrivilegeSet($node) { + + if (is_string($node)) { + $node = $this->server->tree->getNodeForPath($node); + } + + if ($node instanceof Sabre_DAVACL_IACL) { + $result = $node->getSupportedPrivilegeSet(); + + if ($result) + return $result; + } + + return self::getDefaultSupportedPrivilegeSet(); + + } + + /** + * Returns a fairly standard set of privileges, which may be useful for + * other systems to use as a basis. + * + * @return array + */ + static function getDefaultSupportedPrivilegeSet() { return array( 'privilege' => '{DAV:}all', @@ -314,7 +364,7 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { ), ), ), // {DAV:}write - ), + ), ); // {DAV:}all } @@ -329,12 +379,13 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { * - aggregates * - abstract * - concrete - * - * @return array + * + * @param string|Sabre_DAV_INode $node + * @return array */ - final public function getFlatPrivilegeSet() { + final public function getFlatPrivilegeSet($node) { - $privs = $this->getSupportedPrivilegeSet(); + $privs = $this->getSupportedPrivilegeSet($node); $flat = array(); $this->getFPSTraverse($privs, null, $flat); @@ -346,9 +397,12 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { /** * Traverses the privilege set tree for reordering * - * This function is solely used by getFlatPrivilegeSet, and would have been + * 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. - * + * + * @param array $priv + * @param $concrete + * @param array $flat * @return void */ final private function getFPSTraverse($priv, $concrete, &$flat) { @@ -368,7 +422,7 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { if (isset($priv['aggregates'])) { foreach($priv['aggregates'] as $subPriv) { - + $this->getFPSTraverse($subPriv, $myPriv['concrete'], $flat); } @@ -382,8 +436,8 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { * * Either a uri or a Sabre_DAV_INode may be passed. * - * null will be returned if the node doesn't support ACLs. - * + * null will be returned if the node doesn't support ACLs. + * * @param string|Sabre_DAV_INode $node * @return array */ @@ -392,10 +446,18 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { if (is_string($node)) { $node = $this->server->tree->getNodeForPath($node); } - if ($node instanceof Sabre_DAVACL_IACL) { - return $node->getACL(); + if (!$node instanceof Sabre_DAVACL_IACL) { + return null; } - return null; + $acl = $node->getACL(); + foreach($this->adminPrincipals as $adminPrincipal) { + $acl[] = array( + 'principal' => $adminPrincipal, + 'privilege' => '{DAV:}all', + 'protected' => true, + ); + } + return $acl; } @@ -405,10 +467,10 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { * * 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 + * null will be returned if the node doesn't support ACLs. + * + * @param string|Sabre_DAV_INode $node + * @return array */ public function getCurrentUserPrivilegeSet($node) { @@ -417,6 +479,7 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { } $acl = $this->getACL($node); + if (is_null($acl)) return null; $principals = $this->getCurrentUserPrincipals(); @@ -425,27 +488,121 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { foreach($acl as $ace) { - if (in_array($ace['principal'], $principals)) { - $collected[] = $ace; + $principal = $ace['principal']; + + switch($principal) { + + case '{DAV:}owner' : + $owner = $node->getOwner(); + if ($owner && in_array($owner, $principals)) { + $collected[] = $ace; + } + break; + + + // 'all' matches for every user + case '{DAV:}all' : + + // 'authenticated' matched for every user that's logged in. + // Since it's not possible to use ACL while not being logged + // in, this is also always true. + case '{DAV:}authenticated' : + $collected[] = $ace; + break; + + // 'unauthenticated' can never occur either, so we simply + // ignore these. + case '{DAV:}unauthenticated' : + break; + + default : + if (in_array($ace['principal'], $principals)) { + $collected[] = $ace; + } + break; + } + + } // Now we deduct all aggregated privileges. - $flat = $this->getFlatPrivilegeSet(); + $flat = $this->getFlatPrivilegeSet($node); $collected2 = array(); - foreach($collected as $privilege) { + while(count($collected)) { + + $current = array_pop($collected); + $collected2[] = $current['privilege']; - $collected2[] = $privilege['privilege']; - foreach($flat[$privilege['privilege']]['aggregates'] as $subPriv) { - if (!in_array($subPriv, $collected2)) - $collected2[] = $subPriv; + foreach($flat[$current['privilege']]['aggregates'] as $subPriv) { + $collected2[] = $subPriv; + $collected[] = $flat[$subPriv]; } } - return $collected2; + return array_values(array_unique($collected2)); + + } + + /** + * Principal property search + * + * This method can search for principals matching certain values in + * properties. + * + * This method will return a list of properties for the matched properties. + * + * @param array $searchProperties The properties to search on. This is a + * key-value list. The keys are property + * names, and the values the strings to + * match them on. + * @param array $requestedProperties This is the list of properties to + * return for every match. + * @param string $collectionUri The principal collection to search on. + * If this is ommitted, the standard + * principal collection-set will be used. + * @return array This method returns an array structure similar to + * Sabre_DAV_Server::getPropertiesForPath. Returned + * properties are index by a HTTP status code. + * + */ + public function principalSearch(array $searchProperties, array $requestedProperties, $collectionUri = null) { + + if (!is_null($collectionUri)) { + $uris = array($collectionUri); + } else { + $uris = $this->principalCollectionSet; + } + + $lookupResults = array(); + foreach($uris as $uri) { + + $principalCollection = $this->server->tree->getNodeForPath($uri); + if (!$principalCollection instanceof Sabre_DAVACL_AbstractPrincipalCollection) { + // Not a principal collection, we're simply going to ignore + // this. + continue; + } + + $results = $principalCollection->searchPrincipals($searchProperties); + foreach($results as $result) { + $lookupResults[] = rtrim($uri,'/') . '/' . $result; + } + + } + + $matches = array(); + + foreach($lookupResults as $lookupResult) { + + list($matches[]) = $this->server->getPropertiesForPath($lookupResult, $requestedProperties, 0); + + } + + return $matches; } @@ -453,8 +610,8 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { * Sets up the plugin * * This method is automatically called by the server class. - * - * @param Sabre_DAV_Server $server + * + * @param Sabre_DAV_Server $server * @return void */ public function initialize(Sabre_DAV_Server $server) { @@ -485,11 +642,11 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { '{DAV:}group' ); - // Automatically mapping nodes implementing IPrincipal to the + // 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 + // Mapping the group-member-set property to the HrefList property // class. $server->propertyMap['{DAV:}group-member-set'] = 'Sabre_DAV_Property_HrefList'; @@ -499,10 +656,10 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { /* {{{ Event handlers */ /** - * Triggered before any method is handled - * - * @param string $method - * @param string $uri + * Triggered before any method is handled + * + * @param string $method + * @param string $uri * @return void */ public function beforeMethod($method, $uri) { @@ -523,14 +680,14 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { 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. + 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'); @@ -543,16 +700,16 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { 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 + // 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 + // + // 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. + // 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; @@ -563,11 +720,11 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { /** * 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 + * + * @param string $uri * @return void */ public function beforeBind($uri) { @@ -578,12 +735,12 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { } /** - * Triggered before a node is deleted - * - * This allows us to check permissions for any operation that will delete - * an existing node. - * - * @param string $uri + * 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) { @@ -594,26 +751,26 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { } /** - * Triggered before a node is unlocked. - * - * @param string $uri + * Triggered before a node is unlocked. + * + * @param string $uri * @param Sabre_DAV_Locks_LockInfo $lock - * @TODO: not yet implemented + * @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 + * 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. + * @TODO really should be broken into multiple methods, or even a class. * @return void */ public function beforeGetProperties($uri, Sabre_DAV_INode $node, &$requestedProperties, &$returnedProperties) { @@ -633,7 +790,7 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { } return; - } + } /* Adding principal properties */ if ($node instanceof Sabre_DAVACL_IPrincipal) { @@ -692,7 +849,7 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { 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()); + $returnedProperties[200]['{DAV:}supported-privilege-set'] = new Sabre_DAVACL_Property_SupportedPrivilegeSet($this->getSupportedPrivilegeSet($node)); } if (false !== ($index = array_search('{DAV:}current-user-privilege-set', $requestedProperties))) { @@ -730,16 +887,24 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { } + /* The acl-restrictions property contains information on how privileges + * must behave. + */ + if (false !== ($index = array_search('{DAV:}acl-restrictions', $requestedProperties))) { + unset($requestedProperties[$index]); + $returnedProperties[200]['{DAV:}acl-restrictions'] = new Sabre_DAVACL_Property_AclRestrictions(); + } + } /** - * 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 + * 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 bool */ public function updateProperties(&$propertyDelta, &$result, Sabre_DAV_INode $node) { @@ -763,18 +928,18 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { } $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 + * This method handels HTTP REPORT requests + * + * @param string $reportName + * @param DOMNode $dom + * @return bool */ public function report($reportName, $dom) { @@ -785,7 +950,7 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { return false; case '{DAV:}principal-search-property-set' : $this->principalSearchPropertySetReport($dom); - return false; + return false; case '{DAV:}expand-property' : $this->expandPropertyReport($dom); return false; @@ -795,12 +960,12 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { } /** - * This event is triggered for any HTTP method that is not known by the - * webserver. + * This event is triggered for any HTTP method that is not known by the + * webserver. * - * @param string $method - * @param string $uri - * @return void + * @param string $method + * @param string $uri + * @return bool */ public function unknownMethod($method, $uri) { @@ -817,12 +982,12 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { * @param string $uri * @return void */ - public function httpACL($uri) { + public function httpACL($uri) { $body = $this->server->httpRequest->getBody(true); $dom = Sabre_DAV_XMLUtil::loadDOMDocument($body); - $newAcl = + $newAcl = Sabre_DAVACL_Property_Acl::unserialize($dom->firstChild) ->getPrivileges(); @@ -839,13 +1004,13 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { $oldAcl = $this->getACL($node); - $supportedPrivileges = $this->getFlatPrivilegeSet(); + $supportedPrivileges = $this->getFlatPrivilegeSet($node); - /* Checking if protected principals from the existing principal set are + /* Checking if protected principals from the existing principal set are not overwritten. */ - foreach($oldAcl as $k=>$oldAce) { + foreach($oldAcl as $oldAce) { - if (!isset($oldAce['protected']) || !$oldAce['protected']) continue; + if (!isset($oldAce['protected']) || !$oldAce['protected']) continue; $found = false; foreach($newAcl as $newAce) { @@ -853,16 +1018,16 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { $newAce['privilege'] === $oldAce['privilege'] && $newAce['principal'] === $oldAce['principal'] && $newAce['protected'] - ) + ) $found = true; } - if (!$found) + if (!$found) throw new Sabre_DAVACL_Exception_AceConflict('This resource contained a protected {DAV:}ace, but this privilege did not occur in the ACL request'); } - foreach($newAcl as $k=>$newAce) { + foreach($newAcl as $newAce) { // Do we recognize the privilege if (!isset($supportedPrivileges[$newAce['privilege']])) { @@ -876,12 +1041,12 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { // Looking up the principal try { $principal = $this->server->tree->getNodeForPath($newAce['principal']); - } catch (Sabre_DAV_Exception_FileNotFound $e) { + } catch (Sabre_DAV_Exception_NotFound $e) { throw new Sabre_DAVACL_Exception_NotRecognizedPrincipal('The specified principal (' . $newAce['principal'] . ') does not exist'); } if (!($principal instanceof Sabre_DAVACL_IPrincipal)) { throw new Sabre_DAVACL_Exception_NotRecognizedPrincipal('The specified uri (' . $newAce['principal'] . ') is not a principal'); - } + } } $node->setACL($newAcl); @@ -893,7 +1058,7 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { /* Reports {{{ */ /** - * The expand-property report is defined in RFC3253 section 3-8. + * 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 @@ -903,7 +1068,7 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { * Other rfc's, such as ACL rely on this report, so it made sense to put * it in this plugin. * - * @param DOMElement $dom + * @param DOMElement $dom * @return void */ protected function expandPropertyReport($dom) { @@ -940,9 +1105,9 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { /** * This method is used by expandPropertyReport to parse * out the entire HTTP request. - * - * @param DOMElement $node - * @return array + * + * @param DOMElement $node + * @return array */ protected function parseExpandPropertyReportRequest($node) { @@ -950,9 +1115,9 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { do { if (Sabre_DAV_XMLUtil::toClarkNotation($node)!=='{DAV:}property') continue; - + if ($node->firstChild) { - + $children = $this->parseExpandPropertyReportRequest($node->firstChild); } else { @@ -965,7 +1130,7 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { if (!$namespace) $namespace = 'DAV:'; $propName = '{'.$namespace.'}' . $node->getAttribute('name'); - $requestedProperties[$propName] = $children; + $requestedProperties[$propName] = $children; } while ($node = $node->nextSibling); @@ -979,11 +1144,12 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { * * @param array $path * @param array $requestedProperties the list of required properties - * @param array $depth + * @param int $depth + * @return array */ - protected function expandProperties($path,array $requestedProperties,$depth) { + protected function expandProperties($path, array $requestedProperties, $depth) { - $foundProperties = $this->server->getPropertiesForPath($path,array_keys($requestedProperties),$depth); + $foundProperties = $this->server->getPropertiesForPath($path, array_keys($requestedProperties), $depth); $result = array(); @@ -993,7 +1159,7 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { // 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; @@ -1006,7 +1172,7 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { $childProps = array(); foreach($hrefs as $href) { - $childProps = array_merge($childProps, $this->expandProperties($href,$childRequestedProperties,0)); + $childProps = array_merge($childProps, $this->expandProperties($href, $childRequestedProperties, 0)); } $node[200][$propertyName] = new Sabre_DAV_Property_ResponseList($childProps); @@ -1022,27 +1188,23 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { /** * principalSearchPropertySetReport * - * This method responsible for handing the + * 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 + * + * @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'); + + 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; @@ -1055,16 +1217,16 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { } - $nsList = $this->server->xmlNamespaces; + $nsList = $this->server->xmlNamespaces; - foreach($searchProperties as $propertyName=>$description) { + foreach($this->principalSearchPropertySet 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); @@ -1088,78 +1250,25 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { /** * principalPropertySearchReport * - * This method is reponsible for handing the - * {DAV:}principal-property-search report. This report can be used for + * This method is responsible for handing the + * {DAV:}principal-property-search report. This report can be used for * clients to search for groups of principals, based on the value of one * or more properties. - * - * @param DOMDocument $dom + * + * @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']; - } - - } - + $uri = null; + if (!$applyToPrincipalCollectionSet) { + $uri = $this->server->getRequestUri(); } + $result = $this->principalSearch($searchProperties, $requestedProperties, $uri); - $matchProperties = array(); - - foreach($matches as $match) { - - list($result) = $this->server->getPropertiesForPath($match, $requestedProperties, 0); - $matchProperties[] = $result; - - } - - $xml = $this->server->generateMultiStatus($matchProperties); + $xml = $this->server->generateMultiStatus($result); $this->server->httpResponse->setHeader('Content-Type','application/xml; charset=utf-8'); $this->server->httpResponse->sendStatus(207); $this->server->httpResponse->sendBody($xml); @@ -1175,9 +1284,9 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { * 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 + * + * @param DOMDocument $dom + * @return array */ protected function parsePrincipalPropertySearchReportRequest($dom) { @@ -1193,8 +1302,9 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { // Parsing the search request foreach($dom->firstChild->childNodes as $searchNode) { - if (Sabre_DAV_XMLUtil::toClarkNotation($searchNode) == '{DAV:}apply-to-principal-collection-set') + if (Sabre_DAV_XMLUtil::toClarkNotation($searchNode) == '{DAV:}apply-to-principal-collection-set') { $applyToPrincipalCollectionSet = true; + } if (Sabre_DAV_XMLUtil::toClarkNotation($searchNode)!=='{DAV:}property-search') continue; @@ -1208,7 +1318,7 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { case '{DAV:}prop' : $property = Sabre_DAV_XMLUtil::parseProperties($searchNode); - reset($property); + reset($property); $propertyName = key($property); break; diff --git a/3rdparty/Sabre/DAVACL/Principal.php b/3rdparty/Sabre/DAVACL/Principal.php index 790603c900f..51c6658afd6 100644..100755 --- a/3rdparty/Sabre/DAVACL/Principal.php +++ b/3rdparty/Sabre/DAVACL/Principal.php @@ -4,17 +4,17 @@ * Principal class * * This class is a representation of a simple principal - * - * Many WebDAV specs require a user to show up in the directory - * structure. + * + * Many WebDAV specs require a user to show up in the directory + * structure. * * This principal also has basic ACL settings, only allowing the principal - * access it's own principal. - * + * access it's own principal. + * * @package Sabre * @subpackage DAVACL - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_DAVACL_Principal extends Sabre_DAV_Node implements Sabre_DAVACL_IPrincipal, Sabre_DAV_IProperties, Sabre_DAVACL_IACL { @@ -22,20 +22,21 @@ class Sabre_DAVACL_Principal extends Sabre_DAV_Node implements Sabre_DAVACL_IPri /** * Struct with principal information. * - * @var array + * @var array */ protected $principalProperties; /** - * Principal backend - * - * @var Sabre_DAVACL_IPrincipalBackend + * Principal backend + * + * @var Sabre_DAVACL_IPrincipalBackend */ protected $principalBackend; /** - * Creates the principal object + * Creates the principal object * + * @param Sabre_DAVACL_IPrincipalBackend $principalBackend * @param array $principalProperties */ public function __construct(Sabre_DAVACL_IPrincipalBackend $principalBackend, array $principalProperties = array()) { @@ -49,22 +50,22 @@ class Sabre_DAVACL_Principal extends Sabre_DAV_Node implements Sabre_DAVACL_IPri } /** - * Returns the full principal url - * - * @return string + * Returns the full principal url + * + * @return string */ public function getPrincipalUrl() { return $this->principalProperties['uri']; - } + } /** - * Returns a list of altenative urls for a principal - * + * Returns a list of alternative urls for a principal + * * This can for example be an email address, or ldap url. - * - * @return array + * + * @return array */ public function getAlternateUriSet() { @@ -79,16 +80,16 @@ class Sabre_DAVACL_Principal extends Sabre_DAV_Node implements Sabre_DAVACL_IPri $uris[] = 'mailto:' . $this->principalProperties['{http://sabredav.org/ns}email-address']; } - return array_unique($uris); + return array_unique($uris); } /** * Returns the list of group members - * + * * If this principal is a group, this function should return - * all member principal uri's for the group. - * + * all member principal uri's for the group. + * * @return array */ public function getGroupMemberSet() { @@ -99,11 +100,11 @@ class Sabre_DAVACL_Principal extends Sabre_DAV_Node implements Sabre_DAVACL_IPri /** * 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 + * should return a list of principal uri's for it's members. + * + * @return array */ public function getGroupMembership() { @@ -117,11 +118,11 @@ class Sabre_DAVACL_Principal extends Sabre_DAV_Node implements Sabre_DAVACL_IPri * * 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 + * + * This method should throw an exception if the members could not be set. + * + * @param array $groupMembers + * @return void */ public function setGroupMemberSet(array $groupMembers) { @@ -132,22 +133,21 @@ class Sabre_DAVACL_Principal extends Sabre_DAV_Node implements Sabre_DAVACL_IPri /** * Returns this principals name. - * - * @return string + * + * @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 + * Returns the name of the user + * + * @return string */ public function getDisplayName() { @@ -160,16 +160,16 @@ class Sabre_DAVACL_Principal extends Sabre_DAV_Node implements Sabre_DAVACL_IPri } /** - * Returns a list of properties - * - * @param array $requestedProperties - * @return void + * Returns a list of properties + * + * @param array $requestedProperties + * @return array */ public function getProperties($requestedProperties) { $newProperties = array(); foreach($requestedProperties as $propName) { - + if (isset($this->principalProperties[$propName])) { $newProperties[$propName] = $this->principalProperties[$propName]; } @@ -177,29 +177,27 @@ class Sabre_DAVACL_Principal extends Sabre_DAV_Node implements Sabre_DAVACL_IPri } return $newProperties; - + } /** * Updates this principals properties. - * - * Currently this is not supported * - * @param array $properties + * @param array $mutations * @see Sabre_DAV_IProperties::updateProperties - * @return bool|array + * @return bool|array */ - public function updateProperties($properties) { + public function updateProperties($mutations) { - return false; + return $this->principalBackend->updatePrincipal($this->principalProperties['uri'], $mutations); } /** * Returns the owner principal * - * This must be a url to a principal, or null if there's no owner - * + * This must be a url to a principal, or null if there's no owner + * * @return string|null */ public function getOwner() { @@ -213,8 +211,8 @@ class Sabre_DAVACL_Principal extends Sabre_DAV_Node implements Sabre_DAVACL_IPri * Returns a group principal * * This must be a url to a principal, or null if there's no owner - * - * @return string|null + * + * @return string|null */ public function getGroup() { @@ -226,20 +224,20 @@ class Sabre_DAVACL_Principal extends Sabre_DAV_Node implements Sabre_DAVACL_IPri * 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 + * * '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 + * * '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'], + 'principal' => $this->getPrincipalUrl(), 'protected' => true, ), ); @@ -249,9 +247,9 @@ class Sabre_DAVACL_Principal extends Sabre_DAV_Node implements Sabre_DAVACL_IPri /** * Updates the ACL * - * This method will receive a list of new ACE's. - * - * @param array $acl + * This method will receive a list of new ACE's. + * + * @param array $acl * @return void */ public function setACL(array $acl) { @@ -260,4 +258,22 @@ class Sabre_DAVACL_Principal extends Sabre_DAV_Node implements Sabre_DAVACL_IPri } + /** + * Returns the list of supported privileges for this node. + * + * The returned data structure is a list of nested privileges. + * See Sabre_DAVACL_Plugin::getDefaultSupportedPrivilegeSet for a simple + * standard structure. + * + * If null is returned from this method, the default privilege set is used, + * which is fine for most common usecases. + * + * @return array|null + */ + public function getSupportedPrivilegeSet() { + + return null; + + } + } diff --git a/3rdparty/Sabre/DAVACL/PrincipalBackend/PDO.php b/3rdparty/Sabre/DAVACL/PrincipalBackend/PDO.php index 55bd1903c9b..a76b4a9d727 100644..100755 --- a/3rdparty/Sabre/DAVACL/PrincipalBackend/PDO.php +++ b/3rdparty/Sabre/DAVACL/PrincipalBackend/PDO.php @@ -3,46 +3,80 @@ /** * PDO principal backend * - * This is a simple principal backend that maps exactly to the users table, as + * This is a simple principal backend that maps exactly to the users table, as * used by Sabre_DAV_Auth_Backend_PDO. * - * It assumes all principals are in a single collection. The default collection + * It assumes all principals are in a single collection. The default collection * is 'principals/', but this can be overriden. * * @package Sabre * @subpackage DAVACL - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_DAVACL_PrincipalBackend_PDO implements Sabre_DAVACL_IPrincipalBackend { /** - * pdo - * - * @var PDO + * pdo + * + * @var PDO */ protected $pdo; /** - * PDO table name for 'principals' - * - * @var string + * PDO table name for 'principals' + * + * @var string */ protected $tableName; /** - * PDO table name for 'group members' - * - * @var string + * PDO table name for 'group members' + * + * @var string */ protected $groupMembersTableName; /** + * A list of additional fields to support + * + * @var array + */ + protected $fieldMap = array( + + /** + * This property can be used to display the users' real name. + */ + '{DAV:}displayname' => array( + 'dbField' => 'displayname', + ), + + /** + * This property is actually used by the CardDAV plugin, where it gets + * mapped to {http://calendarserver.orgi/ns/}me-card. + * + * The reason we don't straight-up use that property, is because + * me-card is defined as a property on the users' addressbook + * collection. + */ + '{http://sabredav.org/ns}vcard-url' => array( + 'dbField' => 'vcardurl', + ), + /** + * This is the users' primary email-address. + */ + '{http://sabredav.org/ns}email-address' => array( + 'dbField' => 'email', + ), + ); + + /** * Sets up the backend. - * + * * @param PDO $pdo - * @param string $tableName + * @param string $tableName + * @param string $groupMembersTableName */ public function __construct(PDO $pdo, $tableName = 'principals', $groupMembersTableName = 'groupmembers') { @@ -50,27 +84,35 @@ class Sabre_DAVACL_PrincipalBackend_PDO implements Sabre_DAVACL_IPrincipalBacken $this->tableName = $tableName; $this->groupMembersTableName = $groupMembersTableName; - } + } /** * Returns a list of principals based on a prefix. * - * This prefix will often contain something like 'principals'. You are only + * 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 + * 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 + * {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 + * + * @param string $prefixPath + * @return array */ public function getPrincipalsByPrefix($prefixPath) { - $result = $this->pdo->query('SELECT uri, email, displayname FROM `'. $this->tableName . '`'); + + $fields = array( + 'uri', + ); + + foreach($this->fieldMap as $key=>$value) { + $fields[] = $value['dbField']; + } + $result = $this->pdo->query('SELECT '.implode(',', $fields).' FROM '. $this->tableName); $principals = array(); @@ -80,11 +122,15 @@ class Sabre_DAVACL_PrincipalBackend_PDO implements Sabre_DAVACL_IPrincipalBacken list($rowPrefix) = Sabre_DAV_URLUtil::splitPath($row['uri']); if ($rowPrefix !== $prefixPath) continue; - $principals[] = array( + $principal = array( 'uri' => $row['uri'], - '{DAV:}displayname' => $row['displayname']?$row['displayname']:basename($row['uri']), - '{http://sabredav.org/ns}email-address' => $row['email'], ); + foreach($this->fieldMap as $key=>$value) { + if ($row[$value['dbField']]) { + $principal[$key] = $row[$value['dbField']]; + } + } + $principals[] = $principal; } @@ -94,43 +140,218 @@ class Sabre_DAVACL_PrincipalBackend_PDO implements Sabre_DAVACL_IPrincipalBacken /** * 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 + * 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 `'.$this->tableName.'` WHERE uri = ?'); - $stmt->execute(array($path)); + $fields = array( + 'id', + 'uri', + ); - $users = array(); + foreach($this->fieldMap as $key=>$value) { + $fields[] = $value['dbField']; + } + $stmt = $this->pdo->prepare('SELECT '.implode(',', $fields).' FROM '. $this->tableName . ' WHERE uri = ?'); + $stmt->execute(array($path)); $row = $stmt->fetch(PDO::FETCH_ASSOC); if (!$row) return; - return array( + $principal = array( 'id' => $row['id'], 'uri' => $row['uri'], - '{DAV:}displayname' => $row['displayname']?$row['displayname']:basename($row['uri']), - '{http://sabredav.org/ns}email-address' => $row['email'], ); + foreach($this->fieldMap as $key=>$value) { + if ($row[$value['dbField']]) { + $principal[$key] = $row[$value['dbField']]; + } + } + return $principal; + + } + + /** + * Updates one ore more webdav properties on a principal. + * + * The list of mutations is supplied as an array. Each key in the array is + * a propertyname, such as {DAV:}displayname. + * + * Each value is the actual value to be updated. If a value is null, it + * must be deleted. + * + * This method should be atomic. It must either completely succeed, or + * completely fail. Success and failure can simply be returned as 'true' or + * 'false'. + * + * It is also possible to return detailed failure information. In that case + * an array such as this should be returned: + * + * array( + * 200 => array( + * '{DAV:}prop1' => null, + * ), + * 201 => array( + * '{DAV:}prop2' => null, + * ), + * 403 => array( + * '{DAV:}prop3' => null, + * ), + * 424 => array( + * '{DAV:}prop4' => null, + * ), + * ); + * + * In this previous example prop1 was successfully updated or deleted, and + * prop2 was succesfully created. + * + * prop3 failed to update due to '403 Forbidden' and because of this prop4 + * also could not be updated with '424 Failed dependency'. + * + * This last example was actually incorrect. While 200 and 201 could appear + * in 1 response, if there's any error (403) the other properties should + * always fail with 423 (failed dependency). + * + * But anyway, if you don't want to scratch your head over this, just + * return true or false. + * + * @param string $path + * @param array $mutations + * @return array|bool + */ + public function updatePrincipal($path, $mutations) { + + $updateAble = array(); + foreach($mutations as $key=>$value) { + + // We are not aware of this field, we must fail. + if (!isset($this->fieldMap[$key])) { + + $response = array( + 403 => array( + $key => null, + ), + 424 => array(), + ); + + // Adding the rest to the response as a 424 + foreach($mutations as $subKey=>$subValue) { + if ($subKey !== $key) { + $response[424][$subKey] = null; + } + } + return $response; + } + + $updateAble[$this->fieldMap[$key]['dbField']] = $value; + + } + + // No fields to update + $query = "UPDATE " . $this->tableName . " SET "; + + $first = true; + foreach($updateAble as $key => $value) { + if (!$first) { + $query.= ', '; + } + $first = false; + $query.= "$key = :$key "; + } + $query.='WHERE uri = :uri'; + $stmt = $this->pdo->prepare($query); + $updateAble['uri'] = $path; + $stmt->execute($updateAble); + + return true; } /** - * Returns the list of members for a group-principal - * - * @param string $principal - * @return array + * This method is used to search for principals matching a set of + * properties. + * + * This search is specifically used by RFC3744's principal-property-search + * REPORT. You should at least allow searching on + * http://sabredav.org/ns}email-address. + * + * The actual search should be a unicode-non-case-sensitive search. The + * keys in searchProperties are the WebDAV property names, while the values + * are the property values to search on. + * + * If multiple properties are being searched on, the search should be + * AND'ed. + * + * This method should simply return an array with full principal uri's. + * + * If somebody attempted to search on a property the backend does not + * support, you should simply return 0 results. + * + * You can also just return 0 results if you choose to not support + * searching at all, but keep in mind that this may stop certain features + * from working. + * + * @param string $prefixPath + * @param array $searchProperties + * @return array + */ + public function searchPrincipals($prefixPath, array $searchProperties) { + + $query = 'SELECT uri FROM ' . $this->tableName . ' WHERE 1=1 '; + $values = array(); + foreach($searchProperties as $property => $value) { + + switch($property) { + + case '{DAV:}displayname' : + $query.=' AND displayname LIKE ?'; + $values[] = '%' . $value . '%'; + break; + case '{http://sabredav.org/ns}email-address' : + $query.=' AND email LIKE ?'; + $values[] = '%' . $value . '%'; + break; + default : + // Unsupported property + return array(); + + } + + } + $stmt = $this->pdo->prepare($query); + $stmt->execute($values); + + $principals = array(); + while($row = $stmt->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[] = $row['uri']; + + } + + return $principals; + + } + + /** + * 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 `'.$this->groupMembersTableName.'` AS groupmembers LEFT JOIN `'.$this->tableName.'` AS principals ON groupmembers.member_id = principals.id WHERE groupmembers.principal_id = ?'); + $stmt = $this->pdo->prepare('SELECT principals.uri as uri FROM '.$this->groupMembersTableName.' AS groupmembers LEFT JOIN '.$this->tableName.' AS principals ON groupmembers.member_id = principals.id WHERE groupmembers.principal_id = ?'); $stmt->execute(array($principal['id'])); $result = array(); @@ -138,21 +359,21 @@ class Sabre_DAVACL_PrincipalBackend_PDO implements Sabre_DAVACL_IPrincipalBacken $result[] = $row['uri']; } return $result; - + } /** - * Returns the list of groups a principal is a member of - * - * @param string $principal - * @return array + * 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 `'.$this->groupMembersTableName.'` AS groupmembers LEFT JOIN `'.$this->tableName.'` AS principals ON groupmembers.principal_id = principals.id WHERE groupmembers.member_id = ?'); + $stmt = $this->pdo->prepare('SELECT principals.uri as uri FROM '.$this->groupMembersTableName.' AS groupmembers LEFT JOIN '.$this->tableName.' AS principals ON groupmembers.principal_id = principals.id WHERE groupmembers.member_id = ?'); $stmt->execute(array($principal['id'])); $result = array(); @@ -166,16 +387,16 @@ class Sabre_DAVACL_PrincipalBackend_PDO implements Sabre_DAVACL_IPrincipalBacken /** * 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 + * 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 `'.$this->tableName.'` WHERE uri IN (? ' . str_repeat(', ? ', count($members)) . ');'); + $stmt = $this->pdo->prepare('SELECT id, uri FROM '.$this->tableName.' WHERE uri IN (? ' . str_repeat(', ? ', count($members)) . ');'); $stmt->execute(array_merge(array($principal), $members)); $memberIds = array(); @@ -191,12 +412,12 @@ class Sabre_DAVACL_PrincipalBackend_PDO implements Sabre_DAVACL_IPrincipalBacken if (!$principalId) throw new Sabre_DAV_Exception('Principal not found'); // Wiping out old members - $stmt = $this->pdo->prepare('DELETE FROM `'.$this->groupMembersTableName.'` WHERE principal_id = ?;'); + $stmt = $this->pdo->prepare('DELETE FROM '.$this->groupMembersTableName.' WHERE principal_id = ?;'); $stmt->execute(array($principalId)); foreach($memberIds as $memberId) { - $stmt = $this->pdo->prepare('INSERT INTO `'.$this->groupMembersTableName.'` (principal_id, member_id) VALUES (?, ?);'); + $stmt = $this->pdo->prepare('INSERT INTO '.$this->groupMembersTableName.' (principal_id, member_id) VALUES (?, ?);'); $stmt->execute(array($principalId, $memberId)); } diff --git a/3rdparty/Sabre/DAVACL/PrincipalCollection.php b/3rdparty/Sabre/DAVACL/PrincipalCollection.php index 4d22bf8aa75..c3e4cb83f23 100644..100755 --- a/3rdparty/Sabre/DAVACL/PrincipalCollection.php +++ b/3rdparty/Sabre/DAVACL/PrincipalCollection.php @@ -7,11 +7,11 @@ * Sabre_DAV_Auth_Backend to determine which users are available on the list. * * The users are instances of Sabre_DAV_Auth_Principal - * + * * @package Sabre * @subpackage DAVACL - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_DAVACL_PrincipalCollection extends Sabre_DAVACL_AbstractPrincipalCollection { @@ -22,9 +22,9 @@ class Sabre_DAVACL_PrincipalCollection extends Sabre_DAVACL_AbstractPrincipalCol * 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 + * + * @param array $principal + * @return Sabre_DAV_INode */ public function getChildForPrincipal(array $principal) { diff --git a/3rdparty/Sabre/DAVACL/Property/Acl.php b/3rdparty/Sabre/DAVACL/Property/Acl.php index e41e7411310..05e1a690b3c 100644..100755 --- a/3rdparty/Sabre/DAVACL/Property/Acl.php +++ b/3rdparty/Sabre/DAVACL/Property/Acl.php @@ -1,47 +1,47 @@ <?php /** - * This class represents the {DAV:}acl property - * + * This class represents the {DAV:}acl property + * * @package Sabre * @subpackage DAVACL - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_DAVACL_Property_Acl extends Sabre_DAV_Property { /** - * List of privileges - * - * @var array + * List of privileges + * + * @var array */ private $privileges; /** - * Wether or not the server base url is required to be prefixed when - * serializing the property. - * - * @var boolean + * Whether or not the server base url is required to be prefixed when + * serializing the property. + * + * @var boolean */ private $prefixBaseUrl; /** * Constructor * - * This object requires a structure similar to the return value from + * This object requires a structure similar to the return value from * Sabre_DAVACL_Plugin::getACL(). * - * Each privilege is a an array with at least a 'privilege' property, and a - * 'principal' property. A privilege may have a 'protected' property as - * well. + * Each privilege is a an array with at least a 'privilege' property, and a + * 'principal' property. A privilege may have a 'protected' property as + * well. * - * The prefixBaseUrl should be set to false, if the supplied principal urls - * are already full urls. If this is kept to true, the servers base url - * will automatically be prefixed. + * The prefixBaseUrl should be set to false, if the supplied principal urls + * are already full urls. If this is kept to true, the servers base url + * will automatically be prefixed. * - * @param bool $prefixBaseUrl - * @param array $privileges + * @param bool $prefixBaseUrl + * @param array $privileges */ public function __construct(array $privileges, $prefixBaseUrl = true) { @@ -51,9 +51,9 @@ class Sabre_DAVACL_Property_Acl extends Sabre_DAV_Property { } /** - * Returns the list of privileges for this property - * - * @return array + * Returns the list of privileges for this property + * + * @return array */ public function getPrivileges() { @@ -62,10 +62,10 @@ class Sabre_DAVACL_Property_Acl extends Sabre_DAV_Property { } /** - * Serializes the property into a DOMElement - * - * @param Sabre_DAV_Server $server - * @param DOMElement $node + * 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) { @@ -80,10 +80,10 @@ class Sabre_DAVACL_Property_Acl extends Sabre_DAV_Property { } /** - * Unserializes the {DAV:}acl xml element. - * - * @param DOMElement $dom - * @return Sabre_DAVACL_Property_Acl + * Unserializes the {DAV:}acl xml element. + * + * @param DOMElement $dom + * @return Sabre_DAVACL_Property_Acl */ static public function unserialize(DOMElement $dom) { @@ -98,11 +98,22 @@ class Sabre_DAVACL_Property_Acl extends Sabre_DAV_Property { } $principal = Sabre_DAVACL_Property_Principal::unserialize($principal->item(0)); - if ($principal->getType()!==Sabre_DAVACL_Property_Principal::HREF) { - throw new Sabre_DAV_Exception_NotImplemented('Currently only uri based principals are support, {DAV:}all, {DAV:}unauthenticated and {DAV:}authenticated are not implemented yet'); + switch($principal->getType()) { + case Sabre_DAVACL_Property_Principal::HREF : + $principal = $principal->getHref(); + break; + case Sabre_DAVACL_Property_Principal::AUTHENTICATED : + $principal = '{DAV:}authenticated'; + break; + case Sabre_DAVACL_Property_Principal::UNAUTHENTICATED : + $principal = '{DAV:}unauthenticated'; + break; + case Sabre_DAVACL_Property_Principal::ALL : + $principal = '{DAV:}all'; + break; + } - $principal = $principal->getHref(); $protected = false; if ($xace->getElementsByTagNameNS('urn:DAV','protected')->length > 0) { @@ -140,7 +151,7 @@ class Sabre_DAVACL_Property_Acl extends Sabre_DAV_Property { 'privilege' => $privilegeName, ); - } + } } @@ -149,12 +160,12 @@ class Sabre_DAVACL_Property_Acl extends Sabre_DAV_Property { } /** - * Serializes a single access control entry. - * - * @param DOMDocument $doc - * @param DOMElement $node + * Serializes a single access control entry. + * + * @param DOMDocument $doc + * @param DOMElement $node * @param array $ace - * @param Sabre_DAV_Server $server + * @param Sabre_DAV_Server $server * @return void */ private function serializeAce($doc,$node,$ace, $server) { @@ -164,7 +175,19 @@ class Sabre_DAVACL_Property_Acl extends Sabre_DAV_Property { $principal = $doc->createElementNS('DAV:','d:principal'); $xace->appendChild($principal); - $principal->appendChild($doc->createElementNS('DAV:','d:href',($this->prefixBaseUrl?$server->getBaseUri():'') . $ace['principal'] . '/')); + switch($ace['principal']) { + case '{DAV:}authenticated' : + $principal->appendChild($doc->createElementNS('DAV:','d:authenticated')); + break; + case '{DAV:}unauthenticated' : + $principal->appendChild($doc->createElementNS('DAV:','d:unauthenticated')); + break; + case '{DAV:}all' : + $principal->appendChild($doc->createElementNS('DAV:','d:all')); + break; + default: + $principal->appendChild($doc->createElementNS('DAV:','d:href',($this->prefixBaseUrl?$server->getBaseUri():'') . $ace['principal'] . '/')); + } $grant = $doc->createElementNS('DAV:','d:grant'); $xace->appendChild($grant); diff --git a/3rdparty/Sabre/DAVACL/Property/AclRestrictions.php b/3rdparty/Sabre/DAVACL/Property/AclRestrictions.php new file mode 100755 index 00000000000..a8b054956dd --- /dev/null +++ b/3rdparty/Sabre/DAVACL/Property/AclRestrictions.php @@ -0,0 +1,32 @@ +<?php + +/** + * AclRestrictions property + * + * This property represents {DAV:}acl-restrictions, as defined in RFC3744. + * + * @package Sabre + * @subpackage DAVACL + * @copyright Copyright (C) 2007-2012 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_DAVACL_Property_AclRestrictions extends Sabre_DAV_Property { + + /** + * Serializes the property into a DOMElement + * + * @param Sabre_DAV_Server $server + * @param DOMElement $elem + * @return void + */ + public function serialize(Sabre_DAV_Server $server,DOMElement $elem) { + + $doc = $elem->ownerDocument; + + $elem->appendChild($doc->createElementNS('DAV:','d:grant-only')); + $elem->appendChild($doc->createElementNS('DAV:','d:no-invert')); + + } + +} diff --git a/3rdparty/Sabre/DAVACL/Property/CurrentUserPrivilegeSet.php b/3rdparty/Sabre/DAVACL/Property/CurrentUserPrivilegeSet.php index 72274597b31..94a29640615 100644..100755 --- a/3rdparty/Sabre/DAVACL/Property/CurrentUserPrivilegeSet.php +++ b/3rdparty/Sabre/DAVACL/Property/CurrentUserPrivilegeSet.php @@ -2,31 +2,31 @@ /** * CurrentUserPrivilegeSet - * - * This class represents the current-user-privilege-set property. When - * requested, it contain all the privileges a user has on a specific node. - * + * + * This class represents the current-user-privilege-set property. When + * requested, it contain all the privileges a user has on a specific node. + * * @package Sabre * @subpackage DAVACL - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_DAVACL_Property_CurrentUserPrivilegeSet extends Sabre_DAV_Property { /** - * List of privileges - * - * @var array + * List of privileges + * + * @var array */ private $privileges; /** * Creates the object * - * Pass the privileges in clark-notation - * - * @param array $privileges + * Pass the privileges in clark-notation + * + * @param array $privileges */ public function __construct(array $privileges) { @@ -35,10 +35,10 @@ class Sabre_DAVACL_Property_CurrentUserPrivilegeSet extends Sabre_DAV_Property { } /** - * Serializes the property in the DOM - * - * @param Sabre_DAV_Server $server - * @param DOMElement $node + * 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) { @@ -53,11 +53,11 @@ class Sabre_DAVACL_Property_CurrentUserPrivilegeSet extends Sabre_DAV_Property { } /** - * Serializes one privilege - * - * @param DOMDocument $doc - * @param DOMElement $node - * @param string $privName + * Serializes one privilege + * + * @param DOMDocument $doc + * @param DOMElement $node + * @param string $privName * @return void */ protected function serializePriv($doc,$node,$privName) { diff --git a/3rdparty/Sabre/DAVACL/Property/Principal.php b/3rdparty/Sabre/DAVACL/Property/Principal.php index dad9a3550fb..c36328a58e0 100644..100755 --- a/3rdparty/Sabre/DAVACL/Property/Principal.php +++ b/3rdparty/Sabre/DAVACL/Property/Principal.php @@ -4,12 +4,12 @@ * Principal property * * The principal property represents a principal from RFC3744 (ACL). - * The property can be used to specify a principal or pseudo principals. + * The property can be used to specify a principal or pseudo principals. * * @package Sabre * @subpackage DAVACL - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_DAVACL_Property_Principal extends Sabre_DAV_Property implements Sabre_DAV_Property_IHref { @@ -25,16 +25,21 @@ class Sabre_DAVACL_Property_Principal extends Sabre_DAV_Property implements Sabr const AUTHENTICATED = 2; /** - * Specific princpals can be specified with the HREF + * Specific principals can be specified with the HREF */ const HREF = 3; /** + * Everybody, basically + */ + const ALL = 4; + + /** * Principal-type * * Must be one of the UNAUTHENTICATED, AUTHENTICATED or HREF constants. - * - * @var int + * + * @var int */ private $type; @@ -42,8 +47,8 @@ class Sabre_DAVACL_Property_Principal extends Sabre_DAV_Property implements Sabr * Url to principal * * This value is only used for the HREF principal type. - * - * @var string + * + * @var string */ private $href; @@ -53,10 +58,9 @@ class Sabre_DAVACL_Property_Principal extends Sabre_DAV_Property implements Sabr * The 'type' argument must be one of the type constants defined in this class. * * 'href' is only required for the HREF type. - * - * @param int $type - * @param string $href - * @return void + * + * @param int $type + * @param string|null $href */ public function __construct($type, $href = null) { @@ -70,9 +74,9 @@ class Sabre_DAVACL_Property_Principal extends Sabre_DAV_Property implements Sabr } /** - * Returns the principal type - * - * @return int + * Returns the principal type + * + * @return int */ public function getType() { @@ -81,8 +85,8 @@ class Sabre_DAVACL_Property_Principal extends Sabre_DAV_Property implements Sabr } /** - * Returns the principal uri. - * + * Returns the principal uri. + * * @return string */ public function getHref() { @@ -92,10 +96,10 @@ class Sabre_DAVACL_Property_Principal extends Sabre_DAV_Property implements Sabr } /** - * Serializes the property into a DOMElement. - * - * @param Sabre_DAV_Server $server - * @param DOMElement $node + * 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) { @@ -124,10 +128,10 @@ class Sabre_DAVACL_Property_Principal extends Sabre_DAV_Property implements Sabr } /** - * Deserializes a DOM element into a property object. - * - * @param DOMElement $dom - * @return Sabre_DAV_Property_Principal + * Deserializes a DOM element into a property object. + * + * @param DOMElement $dom + * @return Sabre_DAV_Property_Principal */ static public function unserialize(DOMElement $dom) { @@ -144,6 +148,8 @@ class Sabre_DAVACL_Property_Principal extends Sabre_DAV_Property implements Sabr return new self(self::AUTHENTICATED); case '{DAV:}href': return new self(self::HREF, $parent->textContent); + case '{DAV:}all': + return new self(self::ALL); default : throw new Sabre_DAV_Exception_BadRequest('Unexpected element (' . Sabre_DAV_XMLUtil::toClarkNotation($parent) . '). Could not deserialize'); diff --git a/3rdparty/Sabre/DAVACL/Property/SupportedPrivilegeSet.php b/3rdparty/Sabre/DAVACL/Property/SupportedPrivilegeSet.php index 93c3895035d..276d57ae093 100644..100755 --- a/3rdparty/Sabre/DAVACL/Property/SupportedPrivilegeSet.php +++ b/3rdparty/Sabre/DAVACL/Property/SupportedPrivilegeSet.php @@ -3,32 +3,32 @@ /** * SupportedPrivilegeSet property * - * This property encodes the {DAV:}supported-privilege-set property, as defined + * This property encodes the {DAV:}supported-privilege-set property, as defined * in rfc3744. Please consult the rfc for details about it's structure. * - * This class expects a structure like the one given from - * Sabre_DAVACL_Plugin::getSupportedPrivilegeSet as the argument in its + * This class expects a structure like the one given from + * Sabre_DAVACL_Plugin::getSupportedPrivilegeSet as the argument in its * constructor. - * + * * @package Sabre * @subpackage DAVACL - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_DAVACL_Property_SupportedPrivilegeSet extends Sabre_DAV_Property { /** - * privileges - * - * @var array + * privileges + * + * @var array */ private $privileges; /** - * Constructor - * - * @param array $privileges + * Constructor + * + * @param array $privileges */ public function __construct(array $privileges) { @@ -37,10 +37,10 @@ class Sabre_DAVACL_Property_SupportedPrivilegeSet extends Sabre_DAV_Property { } /** - * Serializes the property into a domdocument. - * - * @param Sabre_DAV_Server $server - * @param DOMElement $node + * 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) { @@ -53,11 +53,11 @@ class Sabre_DAVACL_Property_SupportedPrivilegeSet extends Sabre_DAV_Property { /** * Serializes a property * - * This is a recursive function. - * - * @param DOMDocument $doc - * @param DOMElement $node - * @param array $privilege + * This is a recursive function. + * + * @param DOMDocument $doc + * @param DOMElement $node + * @param array $privilege * @return void */ private function serializePriv($doc,$node,$privilege) { @@ -81,7 +81,7 @@ class Sabre_DAVACL_Property_SupportedPrivilegeSet extends Sabre_DAV_Property { $xsp->appendChild($doc->createElementNS('DAV:','d:description',$privilege['description'])); } - if (isset($privilege['aggregates'])) { + if (isset($privilege['aggregates'])) { foreach($privilege['aggregates'] as $subPrivilege) { $this->serializePriv($doc,$xsp,$subPrivilege); } diff --git a/3rdparty/Sabre/DAVACL/Version.php b/3rdparty/Sabre/DAVACL/Version.php index 124463e311e..9950f748741 100644..100755 --- a/3rdparty/Sabre/DAVACL/Version.php +++ b/3rdparty/Sabre/DAVACL/Version.php @@ -2,10 +2,10 @@ /** * This class contains the SabreDAV version constants. - * + * * @package Sabre * @subpackage DAVACL - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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_DAVACL_Version { /** * Full version number */ - const VERSION = '1.5.2'; + const VERSION = '1.6.0'; /** * Stability : alpha, beta, stable diff --git a/3rdparty/Sabre/DAVACL/includes.php b/3rdparty/Sabre/DAVACL/includes.php new file mode 100755 index 00000000000..28fa3eed225 --- /dev/null +++ b/3rdparty/Sabre/DAVACL/includes.php @@ -0,0 +1,38 @@ +<?php + +/** + * Sabre_DAVACL includes file + * + * Including this file will automatically include all files from the + * Sabre_DAVACL package. + * + * This often allows faster loadtimes, as autoload-speed is often quite slow. + * + * @package Sabre + * @subpackage DAVACL + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. + * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License + */ + +// Begin includes +include __DIR__ . '/AbstractPrincipalCollection.php'; +include __DIR__ . '/Exception/AceConflict.php'; +include __DIR__ . '/Exception/NeedPrivileges.php'; +include __DIR__ . '/Exception/NoAbstract.php'; +include __DIR__ . '/Exception/NotRecognizedPrincipal.php'; +include __DIR__ . '/Exception/NotSupportedPrivilege.php'; +include __DIR__ . '/IACL.php'; +include __DIR__ . '/IPrincipal.php'; +include __DIR__ . '/IPrincipalBackend.php'; +include __DIR__ . '/Plugin.php'; +include __DIR__ . '/Principal.php'; +include __DIR__ . '/PrincipalBackend/PDO.php'; +include __DIR__ . '/PrincipalCollection.php'; +include __DIR__ . '/Property/Acl.php'; +include __DIR__ . '/Property/AclRestrictions.php'; +include __DIR__ . '/Property/CurrentUserPrivilegeSet.php'; +include __DIR__ . '/Property/Principal.php'; +include __DIR__ . '/Property/SupportedPrivilegeSet.php'; +include __DIR__ . '/Version.php'; +// End includes diff --git a/3rdparty/Sabre/HTTP/AWSAuth.php b/3rdparty/Sabre/HTTP/AWSAuth.php index 5e4668cd94d..fb8245c8cbf 100644..100755 --- a/3rdparty/Sabre/HTTP/AWSAuth.php +++ b/3rdparty/Sabre/HTTP/AWSAuth.php @@ -4,34 +4,34 @@ * HTTP AWS Authentication handler * * Use this class to leverage amazon's AWS authentication header - * + * * @package Sabre - * @subpackage HTTP - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @subpackage HTTP + * @copyright Copyright (C) 2007-2012 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_HTTP_AWSAuth extends Sabre_HTTP_AbstractAuth { /** - * The signature supplied by the HTTP client - * - * @var string + * The signature supplied by the HTTP client + * + * @var string */ private $signature = null; /** - * The accesskey supplied by the HTTP client - * - * @var string + * The accesskey supplied by the HTTP client + * + * @var string */ private $accessKey = null; /** * An error code, if any * - * This value will be filled with one of the ERR_* contants - * + * This value will be filled with one of the ERR_* constants + * * @var int */ public $errorCode = 0; @@ -46,8 +46,8 @@ class Sabre_HTTP_AWSAuth extends Sabre_HTTP_AbstractAuth { * Gathers all information from the headers * * This method needs to be called prior to anything else. - * - * @return bool + * + * @return bool */ public function init() { @@ -66,9 +66,9 @@ class Sabre_HTTP_AWSAuth extends Sabre_HTTP_AbstractAuth { } /** - * Returns the username for the request - * - * @return string + * Returns the username for the request + * + * @return string */ public function getAccessKey() { @@ -78,8 +78,9 @@ class Sabre_HTTP_AWSAuth extends Sabre_HTTP_AbstractAuth { /** * Validates the signature based on the secretKey - * - * @return bool + * + * @param string $secretKey + * @return bool */ public function validate($secretKey) { @@ -89,7 +90,7 @@ class Sabre_HTTP_AWSAuth extends Sabre_HTTP_AbstractAuth { // We need to validate the integrity of the request $body = $this->httpRequest->getBody(true); $this->httpRequest->setBody($body,true); - + if ($contentMD5!=base64_encode(md5($body,true))) { // content-md5 header did not match md5 signature of body $this->errorCode = self::ERR_MD5CHECKSUMWRONG; @@ -98,10 +99,10 @@ class Sabre_HTTP_AWSAuth extends Sabre_HTTP_AbstractAuth { } - if (!$requestDate = $this->httpRequest->getHeader('x-amz-date')) + if (!$requestDate = $this->httpRequest->getHeader('x-amz-date')) $requestDate = $this->httpRequest->getHeader('Date'); - if (!$this->validateRFC2616Date($requestDate)) + if (!$this->validateRFC2616Date($requestDate)) return false; $amzHeaders = $this->getAmzHeaders(); @@ -109,10 +110,10 @@ class Sabre_HTTP_AWSAuth extends Sabre_HTTP_AbstractAuth { $signature = base64_encode( $this->hmacsha1($secretKey, $this->httpRequest->getMethod() . "\n" . - $contentMD5 . "\n" . + $contentMD5 . "\n" . $this->httpRequest->getHeader('Content-type') . "\n" . $requestDate . "\n" . - $amzHeaders . + $amzHeaders . $this->httpRequest->getURI() ) ); @@ -146,14 +147,14 @@ class Sabre_HTTP_AWSAuth extends Sabre_HTTP_AbstractAuth { /** * Makes sure the supplied value is a valid RFC2616 date. * - * If we would just use strtotime to get a valid timestamp, we have no way of checking if a + * If we would just use strtotime to get a valid timestamp, we have no way of checking if a * user just supplied the word 'now' for the date header. * - * This function also makes sure the Date header is within 15 minutes of the operating + * This function also makes sure the Date header is within 15 minutes of the operating * system date, to prevent replay attacks. - * - * @param string $dateHeader - * @return bool + * + * @param string $dateHeader + * @return bool */ protected function validateRFC2616Date($dateHeader) { @@ -177,11 +178,11 @@ class Sabre_HTTP_AWSAuth extends Sabre_HTTP_AbstractAuth { return $date; } - + /** - * Returns a list of AMZ headers - * - * @return void + * Returns a list of AMZ headers + * + * @return string */ protected function getAmzHeaders() { @@ -193,7 +194,7 @@ class Sabre_HTTP_AWSAuth extends Sabre_HTTP_AbstractAuth { } } ksort($amzHeaders); - + $headerStr = ''; foreach($amzHeaders as $h=>$v) { $headerStr.=$h.':'.$v; @@ -204,11 +205,11 @@ class Sabre_HTTP_AWSAuth extends Sabre_HTTP_AbstractAuth { } /** - * Generates an HMAC-SHA1 signature - * - * @param string $key - * @param string $message - * @return string + * Generates an HMAC-SHA1 signature + * + * @param string $key + * @param string $message + * @return string */ private function hmacsha1($key, $message) { diff --git a/3rdparty/Sabre/HTTP/AbstractAuth.php b/3rdparty/Sabre/HTTP/AbstractAuth.php index eb528f6fdee..3bccabcd1c1 100644..100755 --- a/3rdparty/Sabre/HTTP/AbstractAuth.php +++ b/3rdparty/Sabre/HTTP/AbstractAuth.php @@ -4,10 +4,10 @@ * HTTP Authentication baseclass * * This class has the common functionality for BasicAuth and DigestAuth - * + * * @package Sabre - * @subpackage HTTP - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @subpackage HTTP + * @copyright Copyright (C) 2007-2012 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,29 +17,29 @@ abstract class Sabre_HTTP_AbstractAuth { * The realm will be displayed in the dialog boxes * * This identifier can be changed through setRealm() - * + * * @var string */ protected $realm = 'SabreDAV'; /** - * HTTP response helper - * - * @var Sabre_HTTP_Response + * HTTP response helper + * + * @var Sabre_HTTP_Response */ protected $httpResponse; /** - * HTTP request helper - * - * @var Sabre_HTTP_Request + * HTTP request helper + * + * @var Sabre_HTTP_Request */ protected $httpRequest; /** - * __construct - * + * __construct + * */ public function __construct() { @@ -49,9 +49,9 @@ abstract class Sabre_HTTP_AbstractAuth { } /** - * Sets an alternative HTTP response object - * - * @param Sabre_HTTP_Response $response + * Sets an alternative HTTP response object + * + * @param Sabre_HTTP_Response $response * @return void */ public function setHTTPResponse(Sabre_HTTP_Response $response) { @@ -61,9 +61,9 @@ abstract class Sabre_HTTP_AbstractAuth { } /** - * Sets an alternative HTTP request object - * - * @param Sabre_HTTP_Request $request + * Sets an alternative HTTP request object + * + * @param Sabre_HTTP_Request $request * @return void */ public function setHTTPRequest(Sabre_HTTP_Request $request) { @@ -78,8 +78,8 @@ abstract class Sabre_HTTP_AbstractAuth { * * The realm is often displayed in authentication dialog boxes * Commonly an application name displayed here - * - * @param string $realm + * + * @param string $realm * @return void */ public function setRealm($realm) { @@ -91,7 +91,7 @@ abstract class Sabre_HTTP_AbstractAuth { /** * Returns the realm * - * @return string + * @return string */ public function getRealm() { @@ -106,6 +106,6 @@ abstract class Sabre_HTTP_AbstractAuth { * * @return void */ - abstract public function requireLogin(); + abstract public function requireLogin(); } diff --git a/3rdparty/Sabre/HTTP/BasicAuth.php b/3rdparty/Sabre/HTTP/BasicAuth.php index 35c22d22dc3..a747cc6a31b 100644..100755 --- a/3rdparty/Sabre/HTTP/BasicAuth.php +++ b/3rdparty/Sabre/HTTP/BasicAuth.php @@ -4,11 +4,11 @@ * HTTP Basic Authentication handler * * Use this class for easy http authentication setup - * + * * @package Sabre - * @subpackage HTTP - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @subpackage HTTP + * @copyright Copyright (C) 2007-2012 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_HTTP_BasicAuth extends Sabre_HTTP_AbstractAuth { @@ -22,7 +22,7 @@ class Sabre_HTTP_BasicAuth extends Sabre_HTTP_AbstractAuth { * * If nothing was supplied, 'false' will be returned * - * @return mixed + * @return mixed */ public function getUserPass() { @@ -33,12 +33,18 @@ class Sabre_HTTP_BasicAuth extends Sabre_HTTP_AbstractAuth { } - // Most other webservers + // Most other webservers $auth = $this->httpRequest->getHeader('Authorization'); + // Apache could prefix environment variables with REDIRECT_ when urls + // are passed through mod_rewrite + if (!$auth) { + $auth = $this->httpRequest->getRawServerValue('REDIRECT_HTTP_AUTHORIZATION'); + } + if (!$auth) return false; - if (strpos(strtolower($auth),'basic')!==0) return false; + if (strpos(strtolower($auth),'basic')!==0) return false; return explode(':', base64_decode(substr($auth, 6))); diff --git a/3rdparty/Sabre/HTTP/DigestAuth.php b/3rdparty/Sabre/HTTP/DigestAuth.php index 5e755929571..ee7f05c08ed 100644..100755 --- a/3rdparty/Sabre/HTTP/DigestAuth.php +++ b/3rdparty/Sabre/HTTP/DigestAuth.php @@ -10,18 +10,18 @@ * 2. Call the setRealm() method with the realm you plan to use * 3. Call the init method function. * 4. Call the getUserName() function. This function may return false if no - * authentication information was supplied. Based on the username you + * authentication information was supplied. Based on the username you * should check your internal database for either the associated password, * or the so-called A1 hash of the digest. * 5. Call either validatePassword() or validateA1(). This will return true - * or false. + * or false. * 6. To make sure an authentication prompt is displayed, call the * requireLogin() method. - * - * + * + * * @package Sabre - * @subpackage HTTP - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @subpackage HTTP + * @copyright Copyright (C) 2007-2012 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,7 +40,7 @@ class Sabre_HTTP_DigestAuth extends Sabre_HTTP_AbstractAuth { protected $qop = self::QOP_AUTH; /** - * Initializes the object + * Initializes the object */ public function __construct() { @@ -54,7 +54,7 @@ class Sabre_HTTP_DigestAuth extends Sabre_HTTP_AbstractAuth { * Gathers all information from the headers * * This method needs to be called prior to anything else. - * + * * @return void */ public function init() { @@ -73,11 +73,11 @@ class Sabre_HTTP_DigestAuth extends Sabre_HTTP_AbstractAuth { * * Multiple values can be specified using logical OR. * - * QOP_AUTHINT ensures integrity of the request body, but this is not - * supported by most HTTP clients. QOP_AUTHINT also requires the entire + * QOP_AUTHINT ensures integrity of the request body, but this is not + * supported by most HTTP clients. QOP_AUTHINT also requires the entire * request body to be md5'ed, which can put strains on CPU and memory. * - * @param int $qop + * @param int $qop * @return void */ public function setQOP($qop) { @@ -91,8 +91,8 @@ class Sabre_HTTP_DigestAuth extends Sabre_HTTP_AbstractAuth { * * The A1 parameter should be md5($username . ':' . $realm . ':' . $password); * - * @param string $A1 - * @return bool + * @param string $A1 + * @return bool */ public function validateA1($A1) { @@ -104,9 +104,9 @@ class Sabre_HTTP_DigestAuth extends Sabre_HTTP_AbstractAuth { /** * Validates authentication through a password. The actual password must be provided here. * It is strongly recommended not store the password in plain-text and use validateA1 instead. - * - * @param string $password - * @return bool + * + * @param string $password + * @return bool */ public function validatePassword($password) { @@ -116,9 +116,9 @@ class Sabre_HTTP_DigestAuth extends Sabre_HTTP_AbstractAuth { } /** - * Returns the username for the request - * - * @return string + * Returns the username for the request + * + * @return string */ public function getUsername() { @@ -127,14 +127,14 @@ class Sabre_HTTP_DigestAuth extends Sabre_HTTP_AbstractAuth { } /** - * Validates the digest challenge - * - * @return bool + * Validates the digest challenge + * + * @return bool */ protected function validate() { $A2 = $this->httpRequest->getMethod() . ':' . $this->digestParts['uri']; - + if ($this->digestParts['qop']=='auth-int') { // Making sure we support this qop value if (!($this->qop & self::QOP_AUTHINT)) return false; @@ -144,16 +144,16 @@ class Sabre_HTTP_DigestAuth extends Sabre_HTTP_AbstractAuth { $A2 .= ':' . md5($body); } else { - // We need to make sure we support this qop value - if (!($this->qop & self::QOP_AUTH)) return false; + // We need to make sure we support this qop value + if (!($this->qop & self::QOP_AUTH)) return false; } $A2 = md5($A2); - $validResponse = md5("{$this->A1}:{$this->digestParts['nonce']}:{$this->digestParts['nc']}:{$this->digestParts['cnonce']}:{$this->digestParts['qop']}:{$A2}"); + $validResponse = md5("{$this->A1}:{$this->digestParts['nonce']}:{$this->digestParts['nc']}:{$this->digestParts['cnonce']}:{$this->digestParts['qop']}:{$A2}"); return $this->digestParts['response']==$validResponse; - + } @@ -186,7 +186,7 @@ class Sabre_HTTP_DigestAuth extends Sabre_HTTP_AbstractAuth { * * If the header could not be found, null will be returned * - * @return mixed + * @return mixed */ public function getDigest() { @@ -197,6 +197,12 @@ class Sabre_HTTP_DigestAuth extends Sabre_HTTP_AbstractAuth { // most other servers $digest = $this->httpRequest->getHeader('Authorization'); + // Apache could prefix environment variables with REDIRECT_ when urls + // are passed through mod_rewrite + if (!$digest) { + $digest = $this->httpRequest->getRawServerValue('REDIRECT_HTTP_AUTHORIZATION'); + } + if ($digest && strpos(strtolower($digest),'digest')===0) { return substr($digest,7); } else { @@ -208,11 +214,11 @@ class Sabre_HTTP_DigestAuth extends Sabre_HTTP_AbstractAuth { /** * Parses the different pieces of the digest string into an array. - * + * * This method returns false if an incomplete digest was supplied * - * @param string $digest - * @return mixed + * @param string $digest + * @return mixed */ protected function parseDigest($digest) { @@ -227,7 +233,7 @@ class Sabre_HTTP_DigestAuth extends Sabre_HTTP_AbstractAuth { unset($needed_parts[$m[1]]); } - return $needed_parts ? false : $data; + return $needed_parts ? false : $data; } diff --git a/3rdparty/Sabre/HTTP/Request.php b/3rdparty/Sabre/HTTP/Request.php index 95a64171aab..4746ef77704 100644..100755 --- a/3rdparty/Sabre/HTTP/Request.php +++ b/3rdparty/Sabre/HTTP/Request.php @@ -6,74 +6,85 @@ * This object can be used to easily access information about an HTTP request. * It can additionally be used to create 'mock' requests. * - * This class mostly operates indepentend, but because of the nature of a single - * request per run it can operate as a singleton. For more information check out + * This class mostly operates independent, but because of the nature of a single + * request per run it can operate as a singleton. For more information check out * the behaviour around 'defaultInputStream'. * * @package Sabre - * @subpackage HTTP - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @subpackage HTTP + * @copyright Copyright (C) 2007-2012 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_HTTP_Request { /** * PHP's $_SERVER data - * - * @var string + * + * @var array */ protected $_SERVER; /** + * PHP's $_POST data + * + * @var array + */ + protected $_POST; + + /** * The request body, if any. * * This is stored in the form of a stream resource. * - * @var resource + * @var resource */ protected $body = null; /** * This will be set as the 'default' inputStream for a specific HTTP request - * We sometimes need to retain, or rebuild this if we need multiple runs + * We sometimes need to retain, or rebuild this if we need multiple runs * of parsing the original HTTP request. - * - * @var resource + * + * @var resource */ static $defaultInputStream=null; /** * Sets up the object * - * The serverData array can be used to override usage of PHP's - * global _SERVER variable. - * - * @param array $serverData + * The serverData and postData array can be used to override usage of PHP's + * global _SERVER and _POST variable respectively. + * + * @param array $serverData + * @param array $postData */ - public function __construct($serverData = null) { + public function __construct(array $serverData = null, array $postData = null) { if ($serverData) $this->_SERVER = $serverData; else $this->_SERVER =& $_SERVER; + if ($postData) $this->_POST = $postData; + else $this->_POST =& $_POST; + } /** * Returns the value for a specific http header. * * This method returns null if the header did not exist. - * - * @param string $name - * @return string + * + * @param string $name + * @return string */ public function getHeader($name) { $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 + // There's a few headers that seem to end up in the top-level // server array. switch($name) { case 'CONTENT_TYPE' : @@ -92,9 +103,9 @@ class Sabre_HTTP_Request { * Returns all (known) HTTP headers. * * All headers are converted to lower-case, and additionally all underscores - * are automatically converted to dashes - * - * @return array + * are automatically converted to dashes + * + * @return array */ public function getHeaders() { @@ -122,9 +133,9 @@ class Sabre_HTTP_Request { /** * Returns the HTTP request method * - * This is for example POST or GET + * This is for example POST or GET * - * @return string + * @return string */ public function getMethod() { @@ -135,18 +146,18 @@ class Sabre_HTTP_Request { /** * Returns the requested uri * - * @return string + * @return string */ public function getUri() { - + return $this->_SERVER['REQUEST_URI']; } /** - * Will return protocol + the hostname + the uri - * - * @return void + * Will return protocol + the hostname + the uri + * + * @return string */ public function getAbsoluteUri() { @@ -157,9 +168,9 @@ class Sabre_HTTP_Request { } /** - * Returns everything after the ? from the current url - * - * @return string + * Returns everything after the ? from the current url + * + * @return string */ public function getQueryString() { @@ -168,13 +179,13 @@ class Sabre_HTTP_Request { } /** - * Returns the HTTP request body body + * Returns the HTTP request body body * * This method returns a readable stream resource. - * If the asString parameter is set to true, a string is sent instead. + * If the asString parameter is set to true, a string is sent instead. * * @param bool asString - * @return resource + * @return resource */ public function getBody($asString = false) { @@ -196,14 +207,14 @@ class Sabre_HTTP_Request { } /** - * Sets the contents of the HTTP request body - * + * Sets the contents of the HTTP request body + * * This method can either accept a string, or a readable stream resource. * - * If the setAsDefaultInputStream is set to true, it means for this run of the + * If the setAsDefaultInputStream is set to true, it means for this run of the * script the supplied body will be used instead of php://input. * - * @param mixed $body + * @param mixed $body * @param bool $setAsDefaultInputStream * @return void */ @@ -226,12 +237,26 @@ class Sabre_HTTP_Request { } /** - * Returns a specific item from the _SERVER array. + * Returns PHP's _POST variable. + * + * The reason this is in a method is so it can be subclassed and + * overridden. + * + * @return array + */ + public function getPostVars() { + + return $this->_POST; + + } + + /** + * Returns a specific item from the _SERVER array. * * Do not rely on this feature, it is for internal use only. * - * @param string $field - * @return string + * @param string $field + * @return string */ public function getRawServerValue($field) { diff --git a/3rdparty/Sabre/HTTP/Response.php b/3rdparty/Sabre/HTTP/Response.php index dce6feac553..ffe9bda2082 100644..100755 --- a/3rdparty/Sabre/HTTP/Response.php +++ b/3rdparty/Sabre/HTTP/Response.php @@ -1,20 +1,20 @@ <?php /** - * Sabre_HTTP_Response - * + * Sabre_HTTP_Response + * * @package Sabre * @subpackage HTTP - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_HTTP_Response { /** - * Returns a full HTTP status message for an HTTP status code - * - * @param int $code + * Returns a full HTTP status message for an HTTP status code + * + * @param int $code * @return string */ public function getStatusMessage($code) { @@ -64,6 +64,9 @@ class Sabre_HTTP_Response { 423 => 'Locked', // RFC 4918 424 => 'Failed Dependency', // RFC 4918 426 => 'Upgrade required', + 428 => 'Precondition required', // draft-nottingham-http-new-status + 429 => 'Too Many Requests', // draft-nottingham-http-new-status + 431 => 'Request Header Fields Too Large', // draft-nottingham-http-new-status 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', @@ -71,25 +74,26 @@ class Sabre_HTTP_Response { 504 => 'Gateway Timeout', 505 => 'HTTP Version not supported', 506 => 'Variant Also Negotiates', - 507 => 'Unsufficient Storage', // RFC 4918 + 507 => 'Insufficient Storage', // RFC 4918 508 => 'Loop Detected', // RFC 5842 509 => 'Bandwidth Limit Exceeded', // non-standard 510 => 'Not extended', - ); + 511 => 'Network Authentication Required', // draft-nottingham-http-new-status + ); return 'HTTP/1.1 ' . $code . ' ' . $msg[$code]; } /** - * Sends an HTTP status header to the client - * - * @param int $code HTTP status code - * @return void + * Sends an HTTP status header to the client + * + * @param int $code HTTP status code + * @return bool */ public function sendStatus($code) { - if (!headers_sent()) + if (!headers_sent()) return header($this->getStatusMessage($code)); else return false; @@ -97,15 +101,16 @@ class Sabre_HTTP_Response { /** * Sets an HTTP header for the response - * - * @param string $name - * @param string $value - * @return void + * + * @param string $name + * @param string $value + * @param bool $replace + * @return bool */ public function setHeader($name, $value, $replace = true) { $value = str_replace(array("\r","\n"),array('\r','\n'),$value); - if (!headers_sent()) + if (!headers_sent()) return header($name . ': ' . $value, $replace); else return false; @@ -115,8 +120,8 @@ class Sabre_HTTP_Response { * Sets a bunch of HTTP Headers * * headersnames are specified as keys, value in the array value - * - * @param array $headers + * + * @param array $headers * @return void */ public function setHeaders(array $headers) { @@ -130,14 +135,14 @@ class Sabre_HTTP_Response { * Sends the entire response body * * This method can accept either an open filestream, or a string. - * - * @param mixed $body + * + * @param mixed $body * @return void */ public function sendBody($body) { if (is_resource($body)) { - + fpassthru($body); } else { diff --git a/3rdparty/Sabre/HTTP/Util.php b/3rdparty/Sabre/HTTP/Util.php index 8a6bd7df487..67bdd489e1e 100644..100755 --- a/3rdparty/Sabre/HTTP/Util.php +++ b/3rdparty/Sabre/HTTP/Util.php @@ -1,11 +1,11 @@ <?php /** - * HTTP utility methods - * + * HTTP utility methods + * * @package Sabre * @subpackage HTTP - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @copyright Copyright (C) 2007-2012 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 @@ -16,9 +16,9 @@ class Sabre_HTTP_Util { * Parses a RFC2616-compatible date string * * This method returns false if the date is invalid - * - * @param string $dateHeader - * @return bool|DateTime + * + * @param string $dateHeader + * @return bool|DateTime */ static function parseHTTPDate($dateHeader) { @@ -42,7 +42,7 @@ class Sabre_HTTP_Util { $rfc1123_date = $wkday . ', ' . $date1 . ' ' . $time . ' GMT'; //allowed date formats by RFC 2616 $HTTP_date = "($rfc1123_date|$rfc850_date|$asctime_date)"; - + //allow for space around the string and strip it $dateHeader = trim($dateHeader, ' '); if (!preg_match('/^' . $HTTP_date . '$/', $dateHeader)) @@ -58,7 +58,24 @@ class Sabre_HTTP_Util { if ($realDate !== false && $realDate >= 0) return new DateTime('@' . $realDate, new DateTimeZone('UTC')); - return false; + } + + /** + * Transforms a DateTime object to HTTP's most common date format. + * + * We're serializing it as the RFC 1123 date, which, for HTTP must be + * specified as GMT. + * + * @param DateTime $dateTime + * @return string + */ + static function toHTTPDate(DateTime $dateTime) { + + // We need to clone it, as we don't want to affect the existing + // DateTime. + $dateTime = clone $dateTime; + $dateTime->setTimeZone(new DateTimeZone('GMT')); + return $dateTime->format('D, d M Y H:i:s \G\M\T'); } diff --git a/3rdparty/Sabre/HTTP/Version.php b/3rdparty/Sabre/HTTP/Version.php index 67be232fc26..23dc7f8a7a1 100644..100755 --- a/3rdparty/Sabre/HTTP/Version.php +++ b/3rdparty/Sabre/HTTP/Version.php @@ -2,10 +2,10 @@ /** * This class contains the Sabre_HTTP version constants. - * + * * @package Sabre - * @subpackage HTTP - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @subpackage HTTP + * @copyright Copyright (C) 2007-2012 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.5.3'; + const VERSION = '1.6.2'; /** * Stability : alpha, beta, stable diff --git a/3rdparty/Sabre/HTTP/includes.php b/3rdparty/Sabre/HTTP/includes.php new file mode 100755 index 00000000000..9d34bf3a8be --- /dev/null +++ b/3rdparty/Sabre/HTTP/includes.php @@ -0,0 +1,27 @@ +<?php + +/** + * Sabre_HTTP includes file + * + * Including this file will automatically include all files from the Sabre_HTTP + * package. + * + * This often allows faster loadtimes, as autoload-speed is often quite slow. + * + * @package Sabre + * @subpackage HTTP + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. + * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License + */ + +// Begin includes +include __DIR__ . '/AbstractAuth.php'; +include __DIR__ . '/AWSAuth.php'; +include __DIR__ . '/BasicAuth.php'; +include __DIR__ . '/DigestAuth.php'; +include __DIR__ . '/Request.php'; +include __DIR__ . '/Response.php'; +include __DIR__ . '/Util.php'; +include __DIR__ . '/Version.php'; +// End includes diff --git a/3rdparty/Sabre/LICENCE b/3rdparty/Sabre/LICENCE deleted file mode 100644 index 3d07eaace83..00000000000 --- a/3rdparty/Sabre/LICENCE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (C) 2007-2011 Rooftop Solutions. -Copyright (C) 2007-2009 FileMobile inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the SabreDAV nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. diff --git a/3rdparty/Sabre/VObject/Component.php b/3rdparty/Sabre/VObject/Component.php index 47cf9f3d812..b78a26133fa 100644..100755 --- a/3rdparty/Sabre/VObject/Component.php +++ b/3rdparty/Sabre/VObject/Component.php @@ -4,39 +4,73 @@ * VObject Component * * This class represents a VCALENDAR/VCARD component. A component is for example - * VEVENT, VTODO and also VCALENDAR. It starts with BEGIN:COMPONENTNAME and + * VEVENT, VTODO and also VCALENDAR. It starts with BEGIN:COMPONENTNAME and * ends with END:COMPONENTNAME * * @package Sabre * @subpackage VObject - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_Component extends Sabre_VObject_Element { /** - * Name, for example VEVENT - * - * @var string + * Name, for example VEVENT + * + * @var string */ public $name; /** - * Children properties and components - * + * Children properties and components + * * @var array */ public $children = array(); + /** + * If coponents are added to this map, they will be automatically mapped + * to their respective classes, if parsed by the reader or constructed with + * the 'create' method. + * + * @var array + */ + static public $classMap = array( + 'VCALENDAR' => 'Sabre_VObject_Component_VCalendar', + 'VEVENT' => 'Sabre_VObject_Component_VEvent', + 'VTODO' => 'Sabre_VObject_Component_VTodo', + 'VJOURNAL' => 'Sabre_VObject_Component_VJournal', + 'VALARM' => 'Sabre_VObject_Component_VAlarm', + ); + + /** + * Creates the new component by name, but in addition will also see if + * there's a class mapped to the property name. + * + * @param string $name + * @param string $value + * @return Sabre_VObject_Component + */ + static public function create($name, $value = null) { + + $name = strtoupper($name); + + if (isset(self::$classMap[$name])) { + return new self::$classMap[$name]($name, $value); + } else { + return new self($name, $value); + } + + } /** * Creates a new component. * - * By default this object will iterate over its own children, but this can + * By default this object will iterate over its own children, but this can * be overridden with the iterator argument - * - * @param string $name + * + * @param string $name * @param Sabre_VObject_ElementList $iterator */ public function __construct($name, Sabre_VObject_ElementList $iterator = null) { @@ -47,23 +81,65 @@ class Sabre_VObject_Component extends Sabre_VObject_Element { } /** - * Turns the object back into a serialized blob. - * - * @return string + * Turns the object back into a serialized blob. + * + * @return string */ public function serialize() { $str = "BEGIN:" . $this->name . "\r\n"; + + /** + * Gives a component a 'score' for sorting purposes. + * + * This is solely used by the childrenSort method. + * + * A higher score means the item will be higher in the list + * + * @param Sabre_VObject_Node $n + * @return int + */ + $sortScore = function($n) { + + if ($n instanceof Sabre_VObject_Component) { + // We want to encode VTIMEZONE first, this is a personal + // preference. + if ($n->name === 'VTIMEZONE') { + return 1; + } else { + return 0; + } + } else { + // VCARD version 4.0 wants the VERSION property to appear first + if ($n->name === 'VERSION') { + return 3; + } else { + return 2; + } + } + + }; + + usort($this->children, function($a, $b) use ($sortScore) { + + $sA = $sortScore($a); + $sB = $sortScore($b); + + if ($sA === $sB) return 0; + + return ($sA > $sB) ? -1 : 1; + + }); + foreach($this->children as $child) $str.=$child->serialize(); $str.= "END:" . $this->name . "\r\n"; - + return $str; } - /** - * Adds a new componenten or element + * Adds a new component or element * * You can call this method with the following syntaxes: * @@ -71,10 +147,10 @@ class Sabre_VObject_Component extends Sabre_VObject_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 + * The second adds a property as a string. + * + * @param mixed $item + * @param mixed $itemValue * @return void */ public function add($item, $itemValue = null) { @@ -90,12 +166,12 @@ class Sabre_VObject_Component extends Sabre_VObject_Element { if (!is_scalar($itemValue)) { throw new InvalidArgumentException('The second argument must be scalar'); } - $item = new Sabre_VObject_Property($item,$itemValue); + $item = Sabre_VObject_Property::create($item,$itemValue); $item->parent = $this; $this->children[] = $item; } else { - + throw new InvalidArgumentException('The first argument must either be a Sabre_VObject_Element or a string'); } @@ -103,9 +179,9 @@ class Sabre_VObject_Component extends Sabre_VObject_Element { } /** - * Returns an iterable list of children - * - * @return Sabre_VObject_ElementList + * Returns an iterable list of children + * + * @return Sabre_VObject_ElementList */ public function children() { @@ -116,18 +192,18 @@ class Sabre_VObject_Component extends Sabre_VObject_Element { /** * Returns an array with elements that match the specified name. * - * This function is also aware of MIME-Directory groups (as they appear in - * vcards). This means that if a property is grouped as "HOME.EMAIL", it - * will also be returned when searching for just "EMAIL". If you want to - * search for a property in a specific group, you can select on the entire - * string ("HOME.EMAIL"). If you want to search on a specific property that + * This function is also aware of MIME-Directory groups (as they appear in + * vcards). This means that if a property is grouped as "HOME.EMAIL", it + * will also be returned when searching for just "EMAIL". If you want to + * search for a property in a specific group, you can select on the entire + * string ("HOME.EMAIL"). If you want to search on a specific property that * has not been assigned a group, specify ".EMAIL". * - * Keys are retained from the 'children' array, which may be confusing in - * certain cases. + * Keys are retained from the 'children' array, which may be confusing in + * certain cases. * - * @param string $name - * @return array + * @param string $name + * @return array */ public function select($name) { @@ -144,7 +220,7 @@ class Sabre_VObject_Component extends Sabre_VObject_Element { strtoupper($child->name) === $name && (is_null($group) || ( $child instanceof Sabre_VObject_Property && strtoupper($child->group) === $group)) ) { - + $result[$key] = $child; } @@ -155,16 +231,35 @@ class Sabre_VObject_Component extends Sabre_VObject_Element { } + /** + * This method only returns a list of sub-components. Properties are + * ignored. + * + * @return array + */ + public function getComponents() { + + $result = array(); + foreach($this->children as $child) { + if ($child instanceof Sabre_VObject_Component) { + $result[] = $child; + } + } + + return $result; + + } + /* Magic property accessors {{{ */ /** - * Using 'get' you will either get a propery or component, + * Using 'get' you will either get a property or component, * * If there were no child-elements found with the specified name, * null is returned. - * - * @param string $name - * @return void + * + * @param string $name + * @return Sabre_VObject_Property */ public function __get($name) { @@ -173,6 +268,7 @@ class Sabre_VObject_Component extends Sabre_VObject_Element { return null; } else { $firstMatch = current($matches); + /** @var $firstMatch Sabre_VObject_Property */ $firstMatch->setIterator(new Sabre_VObject_ElementList(array_values($matches))); return $firstMatch; } @@ -180,10 +276,10 @@ class Sabre_VObject_Component extends Sabre_VObject_Element { } /** - * This method checks if a sub-element with the specified name exists. - * - * @param string $name - * @return bool + * This method checks if a sub-element with the specified name exists. + * + * @param string $name + * @return bool */ public function __isset($name) { @@ -200,7 +296,7 @@ class Sabre_VObject_Component extends Sabre_VObject_Element { * * 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 @@ -218,7 +314,7 @@ class Sabre_VObject_Component extends Sabre_VObject_Element { $this->children[] = $value; } } elseif (is_scalar($value)) { - $property = new Sabre_VObject_Property($name,$value); + $property = Sabre_VObject_Property::create($name,$value); $property->parent = $this; if (!is_null($overWrite)) { $this->children[$overWrite] = $property; @@ -232,9 +328,9 @@ class Sabre_VObject_Component extends Sabre_VObject_Element { } /** - * Removes all properties and components within this component. - * - * @param string $name + * Removes all properties and components within this component. + * + * @param string $name * @return void */ public function __unset($name) { @@ -251,4 +347,19 @@ class Sabre_VObject_Component extends Sabre_VObject_Element { /* }}} */ + /** + * This method is automatically called when the object is cloned. + * Specifically, this will ensure all child elements are also cloned. + * + * @return void + */ + public function __clone() { + + foreach($this->children as $key=>$child) { + $this->children[$key] = clone $child; + $this->children[$key]->parent = $this; + } + + } + } diff --git a/3rdparty/Sabre/VObject/Component/VAlarm.php b/3rdparty/Sabre/VObject/Component/VAlarm.php new file mode 100755 index 00000000000..ebb4a9b18f6 --- /dev/null +++ b/3rdparty/Sabre/VObject/Component/VAlarm.php @@ -0,0 +1,102 @@ +<?php + +/** + * VAlarm component + * + * This component contains some additional functionality specific for VALARMs. + * + * @package Sabre + * @subpackage VObject + * @copyright Copyright (C) 2007-2012 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_Component_VAlarm extends Sabre_VObject_Component { + + /** + * Returns a DateTime object when this alarm is going to trigger. + * + * This ignores repeated alarm, only the first trigger is returned. + * + * @return DateTime + */ + public function getEffectiveTriggerTime() { + + $trigger = $this->TRIGGER; + if(!isset($trigger['VALUE']) || strtoupper($trigger['VALUE']) === 'DURATION') { + $triggerDuration = Sabre_VObject_DateTimeParser::parseDuration($this->TRIGGER); + $related = (isset($trigger['RELATED']) && strtoupper($trigger['RELATED']) == 'END') ? 'END' : 'START'; + + $parentComponent = $this->parent; + if ($related === 'START') { + $effectiveTrigger = clone $parentComponent->DTSTART->getDateTime(); + $effectiveTrigger->add($triggerDuration); + } else { + if ($parentComponent->name === 'VTODO') { + $endProp = 'DUE'; + } elseif ($parentComponent->name === 'VEVENT') { + $endProp = 'DTEND'; + } else { + throw new Sabre_DAV_Exception('time-range filters on VALARM components are only supported when they are a child of VTODO or VEVENT'); + } + + if (isset($parentComponent->$endProp)) { + $effectiveTrigger = clone $parentComponent->$endProp->getDateTime(); + $effectiveTrigger->add($triggerDuration); + } elseif (isset($parentComponent->DURATION)) { + $effectiveTrigger = clone $parentComponent->DTSTART->getDateTime(); + $duration = Sabre_VObject_DateTimeParser::parseDuration($parentComponent->DURATION); + $effectiveTrigger->add($duration); + $effectiveTrigger->add($triggerDuration); + } else { + $effectiveTrigger = clone $parentComponent->DTSTART->getDateTime(); + $effectiveTrigger->add($triggerDuration); + } + } + } else { + $effectiveTrigger = $trigger->getDateTime(); + } + return $effectiveTrigger; + + } + + /** + * Returns true or false depending on if the event falls in the specified + * time-range. This is used for filtering purposes. + * + * The rules used to determine if an event falls within the specified + * time-range is based on the CalDAV specification. + * + * @param DateTime $start + * @param DateTime $end + * @return bool + */ + public function isInTimeRange(DateTime $start, DateTime $end) { + + $effectiveTrigger = $this->getEffectiveTriggerTime(); + + if (isset($this->DURATION)) { + $duration = Sabre_VObject_DateTimeParser::parseDuration($this->DURATION); + $repeat = (string)$this->repeat; + if (!$repeat) { + $repeat = 1; + } + + $period = new DatePeriod($effectiveTrigger, $duration, (int)$repeat); + + foreach($period as $occurrence) { + + if ($start <= $occurrence && $end > $occurrence) { + return true; + } + } + return false; + } else { + return ($start <= $effectiveTrigger && $end > $effectiveTrigger); + } + + } + +} + +?> diff --git a/3rdparty/Sabre/VObject/Component/VCalendar.php b/3rdparty/Sabre/VObject/Component/VCalendar.php new file mode 100755 index 00000000000..f3be29afdbb --- /dev/null +++ b/3rdparty/Sabre/VObject/Component/VCalendar.php @@ -0,0 +1,133 @@ +<?php + +/** + * The VCalendar component + * + * This component adds functionality to a component, specific for a VCALENDAR. + * + * @package Sabre + * @subpackage VObject + * @copyright Copyright (C) 2007-2012 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_Component_VCalendar extends Sabre_VObject_Component { + + /** + * Returns a list of all 'base components'. For instance, if an Event has + * a recurrence rule, and one instance is overridden, the overridden event + * will have the same UID, but will be excluded from this list. + * + * VTIMEZONE components will always be excluded. + * + * @param string $componentName filter by component name + * @return array + */ + public function getBaseComponents($componentName = null) { + + $components = array(); + foreach($this->children as $component) { + + if (!$component instanceof Sabre_VObject_Component) + continue; + + if (isset($component->{'RECURRENCE-ID'})) + continue; + + if ($componentName && $component->name !== strtoupper($componentName)) + continue; + + if ($component->name === 'VTIMEZONE') + continue; + + $components[] = $component; + + } + + return $components; + + } + + /** + * If this calendar object, has events with recurrence rules, this method + * can be used to expand the event into multiple sub-events. + * + * Each event will be stripped from it's recurrence information, and only + * the instances of the event in the specified timerange will be left + * alone. + * + * In addition, this method will cause timezone information to be stripped, + * and normalized to UTC. + * + * This method will alter the VCalendar. This cannot be reversed. + * + * This functionality is specifically used by the CalDAV standard. It is + * possible for clients to request expand events, if they are rather simple + * clients and do not have the possibility to calculate recurrences. + * + * @param DateTime $start + * @param DateTime $end + * @return void + */ + public function expand(DateTime $start, DateTime $end) { + + $newEvents = array(); + + foreach($this->select('VEVENT') as $key=>$vevent) { + + if (isset($vevent->{'RECURRENCE-ID'})) { + unset($this->children[$key]); + continue; + } + + + if (!$vevent->rrule) { + unset($this->children[$key]); + if ($vevent->isInTimeRange($start, $end)) { + $newEvents[] = $vevent; + } + continue; + } + + $uid = (string)$vevent->uid; + if (!$uid) { + throw new LogicException('Event did not have a UID!'); + } + + $it = new Sabre_VObject_RecurrenceIterator($this, $vevent->uid); + $it->fastForward($start); + + while($it->valid() && $it->getDTStart() < $end) { + + if ($it->getDTEnd() > $start) { + + $newEvents[] = $it->getEventObject(); + + } + $it->next(); + + } + unset($this->children[$key]); + + } + + foreach($newEvents as $newEvent) { + + foreach($newEvent->children as $child) { + if ($child instanceof Sabre_VObject_Property_DateTime && + $child->getDateType() == Sabre_VObject_Property_DateTime::LOCALTZ) { + $child->setDateTime($child->getDateTime(),Sabre_VObject_Property_DateTime::UTC); + } + } + + $this->add($newEvent); + + } + + // Removing all VTIMEZONE components + unset($this->VTIMEZONE); + + } + +} + diff --git a/3rdparty/Sabre/VObject/Component/VEvent.php b/3rdparty/Sabre/VObject/Component/VEvent.php new file mode 100755 index 00000000000..4cc1e36d7d6 --- /dev/null +++ b/3rdparty/Sabre/VObject/Component/VEvent.php @@ -0,0 +1,70 @@ +<?php + +/** + * VEvent component + * + * This component contains some additional functionality specific for VEVENT's. + * + * @package Sabre + * @subpackage VObject + * @copyright Copyright (C) 2007-2012 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_Component_VEvent extends Sabre_VObject_Component { + + /** + * Returns true or false depending on if the event falls in the specified + * time-range. This is used for filtering purposes. + * + * The rules used to determine if an event falls within the specified + * time-range is based on the CalDAV specification. + * + * @param DateTime $start + * @param DateTime $end + * @return bool + */ + public function isInTimeRange(DateTime $start, DateTime $end) { + + if ($this->RRULE) { + $it = new Sabre_VObject_RecurrenceIterator($this); + $it->fastForward($start); + + // We fast-forwarded to a spot where the end-time of the + // recurrence instance exceeded the start of the requested + // time-range. + // + // If the starttime of the recurrence did not exceed the + // end of the time range as well, we have a match. + return ($it->getDTStart() < $end && $it->getDTEnd() > $start); + + } + + $effectiveStart = $this->DTSTART->getDateTime(); + if (isset($this->DTEND)) { + $effectiveEnd = $this->DTEND->getDateTime(); + // If this was an all-day event, we should just increase the + // end-date by 1. Otherwise the event will last until the second + // the date changed, by increasing this by 1 day the event lasts + // all of the last day as well. + if ($this->DTSTART->getDateType() == Sabre_VObject_Element_DateTime::DATE) { + $effectiveEnd->modify('+1 day'); + } + } elseif (isset($this->DURATION)) { + $effectiveEnd = clone $effectiveStart; + $effectiveEnd->add( Sabre_VObject_DateTimeParser::parseDuration($this->DURATION) ); + } elseif ($this->DTSTART->getDateType() == Sabre_VObject_Element_DateTime::DATE) { + $effectiveEnd = clone $effectiveStart; + $effectiveEnd->modify('+1 day'); + } else { + $effectiveEnd = clone $effectiveStart; + } + return ( + ($start <= $effectiveEnd) && ($end > $effectiveStart) + ); + + } + +} + +?> diff --git a/3rdparty/Sabre/VObject/Component/VJournal.php b/3rdparty/Sabre/VObject/Component/VJournal.php new file mode 100755 index 00000000000..22b3ec921e5 --- /dev/null +++ b/3rdparty/Sabre/VObject/Component/VJournal.php @@ -0,0 +1,46 @@ +<?php + +/** + * VJournal component + * + * This component contains some additional functionality specific for VJOURNALs. + * + * @package Sabre + * @subpackage VObject + * @copyright Copyright (C) 2007-2012 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_Component_VJournal extends Sabre_VObject_Component { + + /** + * Returns true or false depending on if the event falls in the specified + * time-range. This is used for filtering purposes. + * + * The rules used to determine if an event falls within the specified + * time-range is based on the CalDAV specification. + * + * @param DateTime $start + * @param DateTime $end + * @return bool + */ + public function isInTimeRange(DateTime $start, DateTime $end) { + + $dtstart = isset($this->DTSTART)?$this->DTSTART->getDateTime():null; + if ($dtstart) { + $effectiveEnd = clone $dtstart; + if ($this->DTSTART->getDateType() == Sabre_VObject_Element_DateTime::DATE) { + $effectiveEnd->modify('+1 day'); + } + + return ($start <= $effectiveEnd && $end > $dtstart); + + } + return false; + + + } + +} + +?> diff --git a/3rdparty/Sabre/VObject/Component/VTodo.php b/3rdparty/Sabre/VObject/Component/VTodo.php new file mode 100755 index 00000000000..79d06298d7f --- /dev/null +++ b/3rdparty/Sabre/VObject/Component/VTodo.php @@ -0,0 +1,68 @@ +<?php + +/** + * VTodo component + * + * This component contains some additional functionality specific for VTODOs. + * + * @package Sabre + * @subpackage VObject + * @copyright Copyright (C) 2007-2012 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_Component_VTodo extends Sabre_VObject_Component { + + /** + * Returns true or false depending on if the event falls in the specified + * time-range. This is used for filtering purposes. + * + * The rules used to determine if an event falls within the specified + * time-range is based on the CalDAV specification. + * + * @param DateTime $start + * @param DateTime $end + * @return bool + */ + public function isInTimeRange(DateTime $start, DateTime $end) { + + $dtstart = isset($this->DTSTART)?$this->DTSTART->getDateTime():null; + $duration = isset($this->DURATION)?Sabre_VObject_DateTimeParser::parseDuration($this->DURATION):null; + $due = isset($this->DUE)?$this->DUE->getDateTime():null; + $completed = isset($this->COMPLETED)?$this->COMPLETED->getDateTime():null; + $created = isset($this->CREATED)?$this->CREATED->getDateTime():null; + + if ($dtstart) { + if ($duration) { + $effectiveEnd = clone $dtstart; + $effectiveEnd->add($duration); + return $start <= $effectiveEnd && $end > $dtstart; + } elseif ($due) { + return + ($start < $due || $start <= $dtstart) && + ($end > $dtstart || $end >= $due); + } else { + return $start <= $dtstart && $end > $dtstart; + } + } + if ($due) { + return ($start < $due && $end >= $due); + } + if ($completed && $created) { + return + ($start <= $created || $start <= $completed) && + ($end >= $created || $end >= $completed); + } + if ($completed) { + return ($start <= $completed && $end >= $completed); + } + if ($created) { + return ($end > $created); + } + return true; + + } + +} + +?> diff --git a/3rdparty/Sabre/VObject/DateTimeParser.php b/3rdparty/Sabre/VObject/DateTimeParser.php new file mode 100755 index 00000000000..1e2d54ef3a9 --- /dev/null +++ b/3rdparty/Sabre/VObject/DateTimeParser.php @@ -0,0 +1,177 @@ +<?php + +/** + * DateTimeParser + * + * This class is responsible for parsing the several different date and time + * formats iCalendar and vCards have. + * + * @package Sabre + * @subpackage VObject + * @copyright Copyright (C) 2007-2012 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_DateTimeParser { + + /** + * Parses an iCalendar (rfc5545) formatted datetime and returns a DateTime object + * + * Specifying a reference timezone is optional. It will only be used + * if the non-UTC format is used. The argument is used as a reference, the + * returned DateTime object will still be in the UTC timezone. + * + * @param string $dt + * @param DateTimeZone $tz + * @return DateTime + */ + static public function parseDateTime($dt,DateTimeZone $tz = null) { + + // Format is YYYYMMDD + "T" + hhmmss + $result = preg_match('/^([1-3][0-9]{3})([0-1][0-9])([0-3][0-9])T([0-2][0-9])([0-5][0-9])([0-5][0-9])([Z]?)$/',$dt,$matches); + + if (!$result) { + throw new Sabre_DAV_Exception_BadRequest('The supplied iCalendar datetime value is incorrect: ' . $dt); + } + + if ($matches[7]==='Z' || is_null($tz)) { + $tz = new DateTimeZone('UTC'); + } + $date = new DateTime($matches[1] . '-' . $matches[2] . '-' . $matches[3] . ' ' . $matches[4] . ':' . $matches[5] .':' . $matches[6], $tz); + + // Still resetting the timezone, to normalize everything to UTC + $date->setTimeZone(new DateTimeZone('UTC')); + return $date; + + } + + /** + * Parses an iCalendar (rfc5545) formatted date and returns a DateTime object + * + * @param string $date + * @return DateTime + */ + static public function parseDate($date) { + + // Format is YYYYMMDD + $result = preg_match('/^([1-3][0-9]{3})([0-1][0-9])([0-3][0-9])$/',$date,$matches); + + if (!$result) { + throw new Sabre_DAV_Exception_BadRequest('The supplied iCalendar date value is incorrect: ' . $date); + } + + $date = new DateTime($matches[1] . '-' . $matches[2] . '-' . $matches[3], new DateTimeZone('UTC')); + return $date; + + } + + /** + * Parses an iCalendar (RFC5545) formatted duration value. + * + * This method will either return a DateTimeInterval object, or a string + * suitable for strtotime or DateTime::modify. + * + * @param string $duration + * @param bool $asString + * @return DateInterval|string + */ + static public function parseDuration($duration, $asString = false) { + + $result = preg_match('/^(?P<plusminus>\+|-)?P((?P<week>\d+)W)?((?P<day>\d+)D)?(T((?P<hour>\d+)H)?((?P<minute>\d+)M)?((?P<second>\d+)S)?)?$/', $duration, $matches); + if (!$result) { + throw new Sabre_DAV_Exception_BadRequest('The supplied iCalendar duration value is incorrect: ' . $duration); + } + + if (!$asString) { + $invert = false; + if ($matches['plusminus']==='-') { + $invert = true; + } + + + $parts = array( + 'week', + 'day', + 'hour', + 'minute', + 'second', + ); + foreach($parts as $part) { + $matches[$part] = isset($matches[$part])&&$matches[$part]?(int)$matches[$part]:0; + } + + + // We need to re-construct the $duration string, because weeks and + // days are not supported by DateInterval in the same string. + $duration = 'P'; + $days = $matches['day']; + if ($matches['week']) { + $days+=$matches['week']*7; + } + if ($days) + $duration.=$days . 'D'; + + if ($matches['minute'] || $matches['second'] || $matches['hour']) { + $duration.='T'; + + if ($matches['hour']) + $duration.=$matches['hour'].'H'; + + if ($matches['minute']) + $duration.=$matches['minute'].'M'; + + if ($matches['second']) + $duration.=$matches['second'].'S'; + + } + + $iv = new DateInterval($duration); + if ($invert) $iv->invert = true; + + return $iv; + + } + + + + $parts = array( + 'week', + 'day', + 'hour', + 'minute', + 'second', + ); + + $newDur = ''; + foreach($parts as $part) { + if (isset($matches[$part]) && $matches[$part]) { + $newDur.=' '.$matches[$part] . ' ' . $part . 's'; + } + } + + $newDur = ($matches['plusminus']==='-'?'-':'+') . trim($newDur); + return $newDur; + + } + + /** + * Parses either a Date or DateTime, or Duration value. + * + * @param string $date + * @param DateTimeZone|string $referenceTZ + * @return DateTime|DateInterval + */ + static public function parse($date, $referenceTZ = null) { + + if ($date[0]==='P' || ($date[0]==='-' && $date[1]==='P')) { + return self::parseDuration($date); + } elseif (strlen($date)===8) { + return self::parseDate($date); + } else { + return self::parseDateTime($date, $referenceTZ); + } + + } + + +} diff --git a/3rdparty/Sabre/VObject/Element.php b/3rdparty/Sabre/VObject/Element.php index 8d2b0aaacd1..e20ff0b353c 100644..100755 --- a/3rdparty/Sabre/VObject/Element.php +++ b/3rdparty/Sabre/VObject/Element.php @@ -2,14 +2,15 @@ /** * Base class for all elements - * + * * @package Sabre * @subpackage VObject - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_VObject_Element extends Sabre_VObject_Node { + public $parent = null; } diff --git a/3rdparty/Sabre/VObject/Element/DateTime.php b/3rdparty/Sabre/VObject/Element/DateTime.php index 3350ec02c88..5e5eb7ab6f2 100644..100755 --- a/3rdparty/Sabre/VObject/Element/DateTime.php +++ b/3rdparty/Sabre/VObject/Element/DateTime.php @@ -1,25 +1,18 @@ <?php /** - * DateTime property + * DateTime property * - * This element is used for iCalendar properties such as the DTSTART property. - * It basically provides a few helper functions that make it easier to deal - * with these. It supports both DATE-TIME and DATE values. + * this class got renamed to Sabre_VObject_Property_DateTime * - * In order to use this correctly, you must call setDateTime and getDateTime to - * retrieve and modify dates respectively. - * - * If you use the 'value' or properties directly, this object does not keep - * reference and results might appear incorrectly. - * * @package Sabre * @subpackage VObject - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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 */ -class Sabre_VObject_Element_DateTime extends Sabre_VObject_Property { +class Sabre_VObject_Element_DateTime extends Sabre_VObject_Property_DateTime { /** * Local 'floating' time @@ -41,205 +34,4 @@ class Sabre_VObject_Element_DateTime extends Sabre_VObject_Property { */ const DATE = 4; - /** - * DateTime representation - * - * @var DateTime - */ - protected $dateTime; - - /** - * dateType - * - * @var int - */ - protected $dateType; - - /** - * Updates the Date and Time. - * - * @param DateTime $dt - * @param int $dateType - * @return void - */ - public function setDateTime(DateTime $dt, $dateType = self::LOCALTZ) { - - switch($dateType) { - - case self::LOCAL : - $this->setValue($dt->format('Ymd\\THis')); - $this->offsetUnset('VALUE'); - $this->offsetUnset('TZID'); - $this->offsetSet('VALUE','DATE-TIME'); - break; - case self::UTC : - $dt->setTimeZone(new DateTimeZone('UTC')); - $this->setValue($dt->format('Ymd\\THis\\Z')); - $this->offsetUnset('VALUE'); - $this->offsetUnset('TZID'); - $this->offsetSet('VALUE','DATE-TIME'); - break; - case self::LOCALTZ : - $this->setValue($dt->format('Ymd\\THis')); - $this->offsetUnset('VALUE'); - $this->offsetUnset('TZID'); - $this->offsetSet('VALUE','DATE-TIME'); - $this->offsetSet('TZID', $dt->getTimeZone()->getName()); - break; - case self::DATE : - $this->setValue($dt->format('Ymd')); - $this->offsetUnset('VALUE'); - $this->offsetUnset('TZID'); - $this->offsetSet('VALUE','DATE'); - break; - default : - throw new InvalidArgumentException('You must pass a valid dateType constant'); - - } - $this->dateTime = $dt; - $this->dateType = $dateType; - - } - - /** - * Returns the current DateTime value. - * - * If no value was set, this method returns null. - * - * @return DateTime|null - */ - public function getDateTime() { - - if ($this->dateTime) - return $this->dateTime; - - list( - $this->dateType, - $this->dateTime - ) = self::parseData($this->value, $this); - return $this->dateTime; - - } - - /** - * Returns the type of Date format. - * - * This method returns one of the format constants. If no date was set, - * this method will return null. - * - * @return int|null - */ - public function getDateType() { - - if ($this->dateType) - return $this->dateType; - - list( - $this->dateType, - $this->dateTime, - ) = self::parseData($this->value, $this); - return $this->dateType; - - } - - /** - * Parses the internal data structure to figure out what the current date - * and time is. - * - * The returned array contains two elements: - * 1. A 'DateType' constant (as defined on this class), or null. - * 2. A DateTime object (or null) - * - * @param string|null $propertyValue The string to parse (yymmdd or - * ymmddThhmmss, etc..) - * @param Sabre_VObject_Property|null $property The instance of the - * property we're parsing. - * @return array - */ - static public function parseData($propertyValue, Sabre_VObject_Property $property = null) { - - if (is_null($propertyValue)) { - return array(null, null); - } - - $date = '(?P<year>[1-2][0-9]{3})(?P<month>[0-1][0-9])(?P<date>[0-3][0-9])'; - $time = '(?P<hour>[0-2][0-9])(?P<minute>[0-5][0-9])(?P<second>[0-5][0-9])'; - $regex = "/^$date(T$time(?P<isutc>Z)?)?$/"; - - if (!preg_match($regex, $propertyValue, $matches)) { - throw new InvalidArgumentException($propertyValue . ' is not a valid DateTime or Date string'); - } - - if (!isset($matches['hour'])) { - // Date-only - return array( - self::DATE, - new DateTime($matches['year'] . '-' . $matches['month'] . '-' . $matches['date'] . ' 00:00:00'), - ); - } - - $dateStr = - $matches['year'] .'-' . - $matches['month'] . '-' . - $matches['date'] . ' ' . - $matches['hour'] . ':' . - $matches['minute'] . ':' . - $matches['second']; - - if (isset($matches['isutc'])) { - $dt = new DateTime($dateStr,new DateTimeZone('UTC')); - $dt->setTimeZone(new DateTimeZone('UTC')); - return array( - self::UTC, - $dt - ); - } - - // Finding the timezone. - $tzid = $property['TZID']; - if (!$tzid) { - return array( - self::LOCAL, - new DateTime($dateStr) - ); - } - - try { - $tz = new DateTimeZone($tzid->value); - } catch (Exception $e) { - - // The id was invalid, we're going to try to find the information - // through the VTIMEZONE object. - - // First we find the root object - $root = $property; - while($root->parent) { - $root = $root->parent; - } - - if (isset($root->VTIMEZONE)) { - foreach($root->VTIMEZONE as $vtimezone) { - if (((string)$vtimezone->TZID) == $tzid) { - if (isset($vtimezone->{'X-LIC-LOCATION'})) { - $tzid = (string)$vtimezone->{'X-LIC-LOCATION'}; - } - } - } - } - - $tz = new DateTimeZone($tzid); - - } - $dt = new DateTime($dateStr, $tz); - $dt->setTimeZone($tz); - - return array( - self::LOCALTZ, - $dt - ); - - } - } - -?> diff --git a/3rdparty/Sabre/VObject/Element/MultiDateTime.php b/3rdparty/Sabre/VObject/Element/MultiDateTime.php index dc6ca5abb80..8a12ced94a8 100644..100755 --- a/3rdparty/Sabre/VObject/Element/MultiDateTime.php +++ b/3rdparty/Sabre/VObject/Element/MultiDateTime.php @@ -1,168 +1,17 @@ <?php /** - * Multi-DateTime property + * Multi-DateTime property * - * This element is used for iCalendar properties such as the EXDATE property. - * It basically provides a few helper functions that make it easier to deal - * with these. It supports both DATE-TIME and DATE values. + * This class got renamed to Sabre_VObject_Property_MultiDateTime * - * In order to use this correctly, you must call setDateTimes and getDateTimes - * to retrieve and modify dates respectively. - * - * If you use the 'value' or properties directly, this object does not keep - * reference and results might appear incorrectly. - * * @package Sabre * @subpackage VObject - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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 */ -class Sabre_VObject_Element_MultiDateTime extends Sabre_VObject_Property { - - /** - * DateTime representation - * - * @var DateTime[] - */ - protected $dateTimes; - - /** - * dateType - * - * This is one of the Sabre_VObject_Element_DateTime constants. - * - * @var int - */ - protected $dateType; - - /** - * Updates the value - * - * @param array $dt Must be an array of DateTime objects. - * @param int $dateType - * @return void - */ - public function setDateTimes(array $dt, $dateType = Sabre_VObject_Element_DateTime::LOCALTZ) { - - foreach($dt as $i) - if (!$i instanceof DateTime) - throw new InvalidArgumentException('You must pass an array of DateTime objects'); - - $this->offsetUnset('VALUE'); - $this->offsetUnset('TZID'); - switch($dateType) { - - case Sabre_VObject_Element_DateTime::LOCAL : - $val = array(); - foreach($dt as $i) { - $val[] = $i->format('Ymd\\THis'); - } - $this->setValue(implode(',',$val)); - $this->offsetSet('VALUE','DATE-TIME'); - break; - case Sabre_VObject_Element_DateTime::UTC : - $val = array(); - foreach($dt as $i) { - $i->setTimeZone(new DateTimeZone('UTC')); - $val[] = $i->format('Ymd\\THis\\Z'); - } - $this->setValue(implode(',',$val)); - $this->offsetSet('VALUE','DATE-TIME'); - break; - case Sabre_VObject_Element_DateTime::LOCALTZ : - $val = array(); - foreach($dt as $i) { - $val[] = $i->format('Ymd\\THis'); - } - $this->setValue(implode(',',$val)); - $this->offsetSet('VALUE','DATE-TIME'); - $this->offsetSet('TZID', $dt[0]->getTimeZone()->getName()); - break; - case Sabre_VObject_Element_DateTime::DATE : - $val = array(); - foreach($dt as $i) { - $val[] = $i->format('Ymd'); - } - $this->setValue(implode(',',$val)); - $this->offsetSet('VALUE','DATE'); - break; - default : - throw new InvalidArgumentException('You must pass a valid dateType constant'); - - } - $this->dateTimes = $dt; - $this->dateType = $dateType; - - } - - /** - * Returns the current DateTime value. - * - * If no value was set, this method returns null. - * - * @return array|null - */ - public function getDateTimes() { - - if ($this->dateTimes) - return $this->dateTimes; - - $dts = array(); - - if (!$this->value) { - $this->dateTimes = null; - $this->dateType = null; - return null; - } - - foreach(explode(',',$this->value) as $val) { - list( - $type, - $dt - ) = Sabre_VObject_Element_DateTime::parseData($val, $this); - $dts[] = $dt; - $this->dateType = $type; - } - $this->dateTimes = $dts; - return $this->dateTimes; - - } - - /** - * Returns the type of Date format. - * - * This method returns one of the format constants. If no date was set, - * this method will return null. - * - * @return int|null - */ - public function getDateType() { - - if ($this->dateType) - return $this->dateType; - - if (!$this->value) { - $this->dateTimes = null; - $this->dateType = null; - return null; - } - - $dts = array(); - foreach(explode(',',$this->value) as $val) { - list( - $type, - $dt - ) = Sabre_VObject_Element_DateTime::parseData($val, $this); - $dts[] = $dt; - $this->dateType = $type; - } - $this->dateTimes = $dts; - return $this->dateType; - - } +class Sabre_VObject_Element_MultiDateTime extends Sabre_VObject_Property_MultiDateTime { } - -?> diff --git a/3rdparty/Sabre/VObject/ElementList.php b/3rdparty/Sabre/VObject/ElementList.php index 9922cd587bc..7e508db20f0 100644..100755 --- a/3rdparty/Sabre/VObject/ElementList.php +++ b/3rdparty/Sabre/VObject/ElementList.php @@ -8,15 +8,15 @@ * * @package Sabre * @subpackage VObject - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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 - * + * Inner elements + * * @var array */ protected $elements = array(); @@ -24,37 +24,37 @@ class Sabre_VObject_ElementList implements Iterator, Countable, ArrayAccess { /** * Creates the element list. * - * @param array $elements + * @param array $elements */ public function __construct(array $elements) { $this->elements = $elements; - } + } /* {{{ Iterator interface */ /** - * Current position - * - * @var int + * Current position + * + * @var int */ private $key = 0; /** - * Returns current item in iteration - * - * @return Sabre_VObject_Element + * Returns current item in iteration + * + * @return Sabre_VObject_Element */ public function current() { return $this->elements[$this->key]; } - + /** - * To the next item in the iterator - * + * To the next item in the iterator + * * @return void */ public function next() { @@ -64,8 +64,8 @@ class Sabre_VObject_ElementList implements Iterator, Countable, ArrayAccess { } /** - * Returns the current iterator key - * + * Returns the current iterator key + * * @return int */ public function key() { @@ -75,9 +75,9 @@ class Sabre_VObject_ElementList implements Iterator, Countable, ArrayAccess { } /** - * Returns true if the current position in the iterator is a valid one - * - * @return bool + * Returns true if the current position in the iterator is a valid one + * + * @return bool */ public function valid() { @@ -86,9 +86,9 @@ class Sabre_VObject_ElementList implements Iterator, Countable, ArrayAccess { } /** - * Rewinds the iterator - * - * @return void + * Rewinds the iterator + * + * @return void */ public function rewind() { @@ -101,9 +101,9 @@ class Sabre_VObject_ElementList implements Iterator, Countable, ArrayAccess { /* {{{ Countable interface */ /** - * Returns the number of elements - * - * @return int + * Returns the number of elements + * + * @return int */ public function count() { @@ -115,12 +115,12 @@ class Sabre_VObject_ElementList implements Iterator, Countable, ArrayAccess { /* {{{ ArrayAccess Interface */ - + /** * Checks if an item exists through ArrayAccess. * - * @param int $offset - * @return bool + * @param int $offset + * @return bool */ public function offsetExists($offset) { @@ -131,8 +131,8 @@ class Sabre_VObject_ElementList implements Iterator, Countable, ArrayAccess { /** * Gets an item through ArrayAccess. * - * @param int $offset - * @return mixed + * @param int $offset + * @return mixed */ public function offsetGet($offset) { @@ -143,8 +143,8 @@ class Sabre_VObject_ElementList implements Iterator, Countable, ArrayAccess { /** * Sets an item through ArrayAccess. * - * @param int $offset - * @param mixed $value + * @param int $offset + * @param mixed $value * @return void */ public function offsetSet($offset,$value) { @@ -158,7 +158,7 @@ class Sabre_VObject_ElementList implements Iterator, Countable, ArrayAccess { * * This method just forwards the request to the inner iterator * - * @param int $offset + * @param int $offset * @return void */ public function offsetUnset($offset) { diff --git a/3rdparty/Sabre/VObject/FreeBusyGenerator.php b/3rdparty/Sabre/VObject/FreeBusyGenerator.php new file mode 100755 index 00000000000..1c96a64a004 --- /dev/null +++ b/3rdparty/Sabre/VObject/FreeBusyGenerator.php @@ -0,0 +1,297 @@ +<?php + +/** + * This class helps with generating FREEBUSY reports based on existing sets of + * objects. + * + * It only looks at VEVENT and VFREEBUSY objects from the sourcedata, and + * generates a single VFREEBUSY object. + * + * VFREEBUSY components are described in RFC5545, The rules for what should + * go in a single freebusy report is taken from RFC4791, section 7.10. + * + * @package Sabre + * @subpackage VObject + * @copyright Copyright (C) 2007-2012 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_FreeBusyGenerator { + + /** + * Input objects + * + * @var array + */ + protected $objects; + + /** + * Start of range + * + * @var DateTime|null + */ + protected $start; + + /** + * End of range + * + * @var DateTime|null + */ + protected $end; + + /** + * VCALENDAR object + * + * @var Sabre_VObject_Component + */ + protected $baseObject; + + /** + * Sets the VCALENDAR object. + * + * If this is set, it will not be generated for you. You are responsible + * for setting things like the METHOD, CALSCALE, VERSION, etc.. + * + * The VFREEBUSY object will be automatically added though. + * + * @param Sabre_VObject_Component $vcalendar + * @return void + */ + public function setBaseObject(Sabre_VObject_Component $vcalendar) { + + $this->baseObject = $vcalendar; + + } + + /** + * Sets the input objects + * + * Every object must either be a string or a Sabre_VObject_Component. + * + * @param array $objects + * @return void + */ + public function setObjects(array $objects) { + + $this->objects = array(); + foreach($objects as $object) { + + if (is_string($object)) { + $this->objects[] = Sabre_VObject_Reader::read($object); + } elseif ($object instanceof Sabre_VObject_Component) { + $this->objects[] = $object; + } else { + throw new InvalidArgumentException('You can only pass strings or Sabre_VObject_Component arguments to setObjects'); + } + + } + + } + + /** + * Sets the time range + * + * Any freebusy object falling outside of this time range will be ignored. + * + * @param DateTime $start + * @param DateTime $end + * @return void + */ + public function setTimeRange(DateTime $start = null, DateTime $end = null) { + + $this->start = $start; + $this->end = $end; + + } + + /** + * Parses the input data and returns a correct VFREEBUSY object, wrapped in + * a VCALENDAR. + * + * @return Sabre_VObject_Component + */ + public function getResult() { + + $busyTimes = array(); + + foreach($this->objects as $object) { + + foreach($object->getBaseComponents() as $component) { + + switch($component->name) { + + case 'VEVENT' : + + $FBTYPE = 'BUSY'; + if (isset($component->TRANSP) && (strtoupper($component->TRANSP) === 'TRANSPARENT')) { + break; + } + if (isset($component->STATUS)) { + $status = strtoupper($component->STATUS); + if ($status==='CANCELLED') { + break; + } + if ($status==='TENTATIVE') { + $FBTYPE = 'BUSY-TENTATIVE'; + } + } + + $times = array(); + + if ($component->RRULE) { + + $iterator = new Sabre_VObject_RecurrenceIterator($object, (string)$component->uid); + if ($this->start) { + $iterator->fastForward($this->start); + } + + $maxRecurrences = 200; + + while($iterator->valid() && --$maxRecurrences) { + + $startTime = $iterator->getDTStart(); + if ($this->end && $startTime > $this->end) { + break; + } + $times[] = array( + $iterator->getDTStart(), + $iterator->getDTEnd(), + ); + + $iterator->next(); + + } + + } else { + + $startTime = $component->DTSTART->getDateTime(); + if ($this->end && $startTime > $this->end) { + break; + } + $endTime = null; + if (isset($component->DTEND)) { + $endTime = $component->DTEND->getDateTime(); + } elseif (isset($component->DURATION)) { + $duration = Sabre_VObject_DateTimeParser::parseDuration((string)$component->DURATION); + $endTime = clone $startTime; + $endTime->add($duration); + } elseif ($component->DTSTART->getDateType() === Sabre_VObject_Property_DateTime::DATE) { + $endTime = clone $startTime; + $endTime->modify('+1 day'); + } else { + // The event had no duration (0 seconds) + break; + } + + $times[] = array($startTime, $endTime); + + } + + foreach($times as $time) { + + if ($this->end && $time[0] > $this->end) break; + if ($this->start && $time[1] < $this->start) break; + + $busyTimes[] = array( + $time[0], + $time[1], + $FBTYPE, + ); + } + break; + + case 'VFREEBUSY' : + foreach($component->FREEBUSY as $freebusy) { + + $fbType = isset($freebusy['FBTYPE'])?strtoupper($freebusy['FBTYPE']):'BUSY'; + + // Skipping intervals marked as 'free' + if ($fbType==='FREE') + continue; + + $values = explode(',', $freebusy); + foreach($values as $value) { + list($startTime, $endTime) = explode('/', $value); + $startTime = Sabre_VObject_DateTimeParser::parseDateTime($startTime); + + if (substr($endTime,0,1)==='P' || substr($endTime,0,2)==='-P') { + $duration = Sabre_VObject_DateTimeParser::parseDuration($endTime); + $endTime = clone $startTime; + $endTime->add($duration); + } else { + $endTime = Sabre_VObject_DateTimeParser::parseDateTime($endTime); + } + + if($this->start && $this->start > $endTime) continue; + if($this->end && $this->end < $startTime) continue; + $busyTimes[] = array( + $startTime, + $endTime, + $fbType + ); + + } + + + } + break; + + + + } + + + } + + } + + if ($this->baseObject) { + $calendar = $this->baseObject; + } else { + $calendar = new Sabre_VObject_Component('VCALENDAR'); + $calendar->version = '2.0'; + if (Sabre_DAV_Server::$exposeVersion) { + $calendar->prodid = '-//SabreDAV//Sabre VObject ' . Sabre_VObject_Version::VERSION . '//EN'; + } else { + $calendar->prodid = '-//SabreDAV//Sabre VObject//EN'; + } + $calendar->calscale = 'GREGORIAN'; + } + + $vfreebusy = new Sabre_VObject_Component('VFREEBUSY'); + $calendar->add($vfreebusy); + + if ($this->start) { + $dtstart = new Sabre_VObject_Property_DateTime('DTSTART'); + $dtstart->setDateTime($this->start,Sabre_VObject_Property_DateTime::UTC); + $vfreebusy->add($dtstart); + } + if ($this->end) { + $dtend = new Sabre_VObject_Property_DateTime('DTEND'); + $dtend->setDateTime($this->start,Sabre_VObject_Property_DateTime::UTC); + $vfreebusy->add($dtend); + } + $dtstamp = new Sabre_VObject_Property_DateTime('DTSTAMP'); + $dtstamp->setDateTime(new DateTime('now'), Sabre_VObject_Property_DateTime::UTC); + $vfreebusy->add($dtstamp); + + foreach($busyTimes as $busyTime) { + + $busyTime[0]->setTimeZone(new DateTimeZone('UTC')); + $busyTime[1]->setTimeZone(new DateTimeZone('UTC')); + + $prop = new Sabre_VObject_Property( + 'FREEBUSY', + $busyTime[0]->format('Ymd\\THis\\Z') . '/' . $busyTime[1]->format('Ymd\\THis\\Z') + ); + $prop['FBTYPE'] = $busyTime[2]; + $vfreebusy->add($prop); + + } + + return $calendar; + + } + +} + diff --git a/3rdparty/Sabre/VObject/Node.php b/3rdparty/Sabre/VObject/Node.php index 7100b62f1cb..d89e01b56c6 100644..100755 --- a/3rdparty/Sabre/VObject/Node.php +++ b/3rdparty/Sabre/VObject/Node.php @@ -1,47 +1,47 @@ <?php /** - * Base class for all nodes - * + * Base class for all nodes + * * @package Sabre * @subpackage VObject - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_VObject_Node implements IteratorAggregate, ArrayAccess, Countable { /** - * Turns the object back into a serialized blob. - * - * @return string + * Turns the object back into a serialized blob. + * + * @return string */ abstract function serialize(); /** - * Iterator override - * - * @var Sabre_VObject_ElementList + * Iterator override + * + * @var Sabre_VObject_ElementList */ protected $iterator = null; /** * A link to the parent node - * - * @var Sabre_VObject_Node + * + * @var Sabre_VObject_Node */ - protected $parent = null; + public $parent = null; /* {{{ IteratorAggregator interface */ /** - * Returns the iterator for this object - * - * @return Sabre_VObject_ElementList + * Returns the iterator for this object + * + * @return Sabre_VObject_ElementList */ public function getIterator() { - if (!is_null($this->iterator)) + if (!is_null($this->iterator)) return $this->iterator; return new Sabre_VObject_ElementList(array($this)); @@ -52,8 +52,8 @@ abstract class Sabre_VObject_Node implements IteratorAggregate, ArrayAccess, Cou * Sets the overridden iterator * * Note that this is not actually part of the iterator interface - * - * @param Sabre_VObject_ElementList $iterator + * + * @param Sabre_VObject_ElementList $iterator * @return void */ public function setIterator(Sabre_VObject_ElementList $iterator) { @@ -67,9 +67,9 @@ abstract class Sabre_VObject_Node implements IteratorAggregate, ArrayAccess, Cou /* {{{ Countable interface */ /** - * Returns the number of elements - * - * @return int + * Returns the number of elements + * + * @return int */ public function count() { @@ -82,14 +82,14 @@ abstract class Sabre_VObject_Node implements IteratorAggregate, ArrayAccess, Cou /* {{{ ArrayAccess Interface */ - + /** * Checks if an item exists through ArrayAccess. * * This method just forwards the request to the inner iterator - * - * @param int $offset - * @return bool + * + * @param int $offset + * @return bool */ public function offsetExists($offset) { @@ -103,8 +103,8 @@ abstract class Sabre_VObject_Node implements IteratorAggregate, ArrayAccess, Cou * * This method just forwards the request to the inner iterator * - * @param int $offset - * @return mixed + * @param int $offset + * @return mixed */ public function offsetGet($offset) { @@ -118,8 +118,8 @@ abstract class Sabre_VObject_Node implements IteratorAggregate, ArrayAccess, Cou * * This method just forwards the request to the inner iterator * - * @param int $offset - * @param mixed $value + * @param int $offset + * @param mixed $value * @return void */ public function offsetSet($offset,$value) { @@ -134,7 +134,7 @@ abstract class Sabre_VObject_Node implements IteratorAggregate, ArrayAccess, Cou * * This method just forwards the request to the inner iterator * - * @param int $offset + * @param int $offset * @return void */ public function offsetUnset($offset) { diff --git a/3rdparty/Sabre/VObject/Parameter.php b/3rdparty/Sabre/VObject/Parameter.php index 9ebab6ec69b..2e39af5f78a 100644..100755 --- a/3rdparty/Sabre/VObject/Parameter.php +++ b/3rdparty/Sabre/VObject/Parameter.php @@ -5,51 +5,54 @@ * * This class represents a parameter. A parameter is always tied to a property. * In the case of: - * DTSTART;VALUE=DATE:20101108 + * DTSTART;VALUE=DATE:20101108 * VALUE=DATE would be the parameter name and value. - * + * * @package Sabre * @subpackage VObject - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_Parameter extends Sabre_VObject_Node { /** - * Parameter name - * - * @var string + * Parameter name + * + * @var string */ public $name; /** - * Parameter value - * - * @var string + * Parameter value + * + * @var string */ public $value; /** - * Sets up the object - * - * @param string $name - * @param string $value + * Sets up the object + * + * @param string $name + * @param string $value */ public function __construct($name, $value = null) { $this->name = strtoupper($name); $this->value = $value; - } + } /** - * Turns the object back into a serialized blob. - * - * @return string + * Turns the object back into a serialized blob. + * + * @return string */ public function serialize() { + if (is_null($this->value)) { + return $this->name; + } $src = array( '\\', "\n", @@ -68,9 +71,9 @@ class Sabre_VObject_Parameter extends Sabre_VObject_Node { } /** - * Called when this object is being cast to a string - * - * @return string + * Called when this object is being cast to a string + * + * @return string */ public function __toString() { diff --git a/3rdparty/Sabre/VObject/ParseException.php b/3rdparty/Sabre/VObject/ParseException.php index ed4ef2e8592..1b5e95bf16e 100644..100755 --- a/3rdparty/Sabre/VObject/ParseException.php +++ b/3rdparty/Sabre/VObject/ParseException.php @@ -2,11 +2,11 @@ /** * Exception thrown by Sabre_VObject_Reader if an invalid object was attempted to be parsed. - * + * * @package Sabre * @subpackage VObject - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_ParseException extends Exception { } diff --git a/3rdparty/Sabre/VObject/Property.php b/3rdparty/Sabre/VObject/Property.php index 06058229043..ce74fe3865b 100644..100755 --- a/3rdparty/Sabre/VObject/Property.php +++ b/3rdparty/Sabre/VObject/Property.php @@ -4,58 +4,103 @@ * VObject Property * * A property in VObject is usually in the form PARAMNAME:paramValue. - * An example is : SUMMARY:Weekly meeting + * An example is : SUMMARY:Weekly meeting * * Properties can also have parameters: * SUMMARY;LANG=en:Weekly meeting. * - * Parameters can be accessed using the ArrayAccess interface. + * Parameters can be accessed using the ArrayAccess interface. * * @package Sabre * @subpackage VObject - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_Property extends Sabre_VObject_Element { /** - * Propertyname - * - * @var string + * Propertyname + * + * @var string */ public $name; /** * Group name - * + * * This may be something like 'HOME' for vcards. * - * @var string + * @var string */ public $group; /** - * Property parameters - * - * @var array + * Property parameters + * + * @var array */ public $parameters = array(); /** - * Property value - * - * @var string + * Property value + * + * @var string */ public $value; /** + * If properties are added to this map, they will be automatically mapped + * to their respective classes, if parsed by the reader or constructed with + * the 'create' method. + * + * @var array + */ + static public $classMap = array( + 'COMPLETED' => 'Sabre_VObject_Property_DateTime', + 'CREATED' => 'Sabre_VObject_Property_DateTime', + 'DTEND' => 'Sabre_VObject_Property_DateTime', + 'DTSTAMP' => 'Sabre_VObject_Property_DateTime', + 'DTSTART' => 'Sabre_VObject_Property_DateTime', + 'DUE' => 'Sabre_VObject_Property_DateTime', + 'EXDATE' => 'Sabre_VObject_Property_MultiDateTime', + 'LAST-MODIFIED' => 'Sabre_VObject_Property_DateTime', + 'RECURRENCE-ID' => 'Sabre_VObject_Property_DateTime', + 'TRIGGER' => 'Sabre_VObject_Property_DateTime', + ); + + /** + * Creates the new property by name, but in addition will also see if + * there's a class mapped to the property name. + * + * @param string $name + * @param string $value + * @return void + */ + static public function create($name, $value = null) { + + $name = strtoupper($name); + $shortName = $name; + $group = null; + if (strpos($shortName,'.')!==false) { + list($group, $shortName) = explode('.', $shortName); + } + + if (isset(self::$classMap[$shortName])) { + return new self::$classMap[$shortName]($name, $value); + } else { + return new self($name, $value); + } + + } + + /** * Creates a new property object - * - * By default this object will iterate over its own children, but this can + * + * By default this object will iterate over its own children, but this can * be overridden with the iterator argument - * - * @param string $name + * + * @param string $name * @param string $value * @param Sabre_VObject_ElementList $iterator */ @@ -73,10 +118,12 @@ class Sabre_VObject_Property extends Sabre_VObject_Element { } + + /** - * Updates the internal value - * - * @param string $value + * Updates the internal value + * + * @param string $value * @return void */ public function setValue($value) { @@ -86,9 +133,9 @@ class Sabre_VObject_Property extends Sabre_VObject_Element { } /** - * Turns the object back into a serialized blob. - * - * @return string + * Turns the object back into a serialized blob. + * + * @return string */ public function serialize() { @@ -97,7 +144,7 @@ class Sabre_VObject_Property extends Sabre_VObject_Element { if (count($this->parameters)) { foreach($this->parameters as $param) { - + $str.=';' . $param->serialize(); } @@ -115,8 +162,8 @@ class Sabre_VObject_Property extends Sabre_VObject_Element { $out = ''; while(strlen($str)>0) { if (strlen($str)>75) { - $out.= substr($str,0,75) . "\r\n"; - $str = ' ' . substr($str,75); + $out.= mb_strcut($str,0,75,'utf-8') . "\r\n"; + $str = ' ' . mb_strcut($str,75,strlen($str),'utf-8'); } else { $out.=$str . "\r\n"; $str=''; @@ -136,11 +183,11 @@ class Sabre_VObject_Property extends Sabre_VObject_Element { * add(Sabre_VObject_Parameter $element) * add(string $name, $value) * - * The first version adds an Parameter - * The second adds a property as a string. - * - * @param mixed $item - * @param mixed $itemValue + * The first version adds an Parameter + * The second adds a property as a string. + * + * @param mixed $item + * @param mixed $itemValue * @return void */ public function add($item, $itemValue = null) { @@ -153,7 +200,7 @@ class Sabre_VObject_Property extends Sabre_VObject_Element { $this->parameters[] = $item; } elseif(is_string($item)) { - if (!is_scalar($itemValue)) { + if (!is_scalar($itemValue) && !is_null($itemValue)) { throw new InvalidArgumentException('The second argument must be scalar'); } $parameter = new Sabre_VObject_Parameter($item,$itemValue); @@ -161,21 +208,20 @@ class Sabre_VObject_Property extends Sabre_VObject_Element { $this->parameters[] = $parameter; } else { - + throw new InvalidArgumentException('The first argument must either be a Sabre_VObject_Element or a string'); } } - /* ArrayAccess interface {{{ */ /** * Checks if an array element exists - * - * @param mixed $name - * @return bool + * + * @param mixed $name + * @return bool */ public function offsetExists($name) { @@ -191,16 +237,16 @@ class Sabre_VObject_Property extends Sabre_VObject_Element { } /** - * Returns a parameter, or parameter list. - * - * @param string $name - * @return Sabre_VObject_Element + * 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) @@ -219,8 +265,8 @@ class Sabre_VObject_Property extends Sabre_VObject_Element { } /** - * Creates a new parameter - * + * Creates a new parameter + * * @param string $name * @param mixed $value * @return void @@ -230,7 +276,7 @@ class Sabre_VObject_Property extends Sabre_VObject_Element { if (is_int($name)) return parent::offsetSet($name, $value); if (is_scalar($value)) { - if (!is_string($name)) + 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->offsetUnset($name); @@ -242,7 +288,7 @@ class Sabre_VObject_Property extends Sabre_VObject_Element { 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.'); - $value->parent = $this; + $value->parent = $this; $this->parameters[] = $value; } else { throw new InvalidArgumentException('You can only add parameters to the property object'); @@ -251,17 +297,16 @@ class Sabre_VObject_Property extends Sabre_VObject_Element { } /** - * Removes one or more parameters with the specified name - * - * @param string $name - * @return void + * 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); + if (is_int($name)) return parent::offsetUnset($name); $name = strtoupper($name); - - $result = array(); + foreach($this->parameters as $key=>$parameter) { if ($parameter->name == $name) { $parameter->parent = null; @@ -275,15 +320,29 @@ class Sabre_VObject_Property extends Sabre_VObject_Element { /* }}} */ /** - * Called when this object is being cast to a string - * - * @return string + * Called when this object is being cast to a string + * + * @return string */ public function __toString() { - return $this->value; + return (string)$this->value; } + /** + * This method is automatically called when the object is cloned. + * Specifically, this will ensure all child elements are also cloned. + * + * @return void + */ + public function __clone() { + + foreach($this->parameters as $key=>$child) { + $this->parameters[$key] = clone $child; + $this->parameters[$key]->parent = $this; + } + + } } diff --git a/3rdparty/Sabre/VObject/Property/DateTime.php b/3rdparty/Sabre/VObject/Property/DateTime.php new file mode 100755 index 00000000000..fe2372caa81 --- /dev/null +++ b/3rdparty/Sabre/VObject/Property/DateTime.php @@ -0,0 +1,260 @@ +<?php + +/** + * DateTime property + * + * This element is used for iCalendar properties such as the DTSTART property. + * It basically provides a few helper functions that make it easier to deal + * with these. It supports both DATE-TIME and DATE values. + * + * In order to use this correctly, you must call setDateTime and getDateTime to + * retrieve and modify dates respectively. + * + * If you use the 'value' or properties directly, this object does not keep + * reference and results might appear incorrectly. + * + * @package Sabre + * @subpackage VObject + * @copyright Copyright (C) 2007-2012 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_Property_DateTime extends Sabre_VObject_Property { + + /** + * Local 'floating' time + */ + const LOCAL = 1; + + /** + * UTC-based time + */ + const UTC = 2; + + /** + * Local time plus timezone + */ + const LOCALTZ = 3; + + /** + * Only a date, time is ignored + */ + const DATE = 4; + + /** + * DateTime representation + * + * @var DateTime + */ + protected $dateTime; + + /** + * dateType + * + * @var int + */ + protected $dateType; + + /** + * Updates the Date and Time. + * + * @param DateTime $dt + * @param int $dateType + * @return void + */ + public function setDateTime(DateTime $dt, $dateType = self::LOCALTZ) { + + switch($dateType) { + + case self::LOCAL : + $this->setValue($dt->format('Ymd\\THis')); + $this->offsetUnset('VALUE'); + $this->offsetUnset('TZID'); + $this->offsetSet('VALUE','DATE-TIME'); + break; + case self::UTC : + $dt->setTimeZone(new DateTimeZone('UTC')); + $this->setValue($dt->format('Ymd\\THis\\Z')); + $this->offsetUnset('VALUE'); + $this->offsetUnset('TZID'); + $this->offsetSet('VALUE','DATE-TIME'); + break; + case self::LOCALTZ : + $this->setValue($dt->format('Ymd\\THis')); + $this->offsetUnset('VALUE'); + $this->offsetUnset('TZID'); + $this->offsetSet('VALUE','DATE-TIME'); + $this->offsetSet('TZID', $dt->getTimeZone()->getName()); + break; + case self::DATE : + $this->setValue($dt->format('Ymd')); + $this->offsetUnset('VALUE'); + $this->offsetUnset('TZID'); + $this->offsetSet('VALUE','DATE'); + break; + default : + throw new InvalidArgumentException('You must pass a valid dateType constant'); + + } + $this->dateTime = $dt; + $this->dateType = $dateType; + + } + + /** + * Returns the current DateTime value. + * + * If no value was set, this method returns null. + * + * @return DateTime|null + */ + public function getDateTime() { + + if ($this->dateTime) + return $this->dateTime; + + list( + $this->dateType, + $this->dateTime + ) = self::parseData($this->value, $this); + return $this->dateTime; + + } + + /** + * Returns the type of Date format. + * + * This method returns one of the format constants. If no date was set, + * this method will return null. + * + * @return int|null + */ + public function getDateType() { + + if ($this->dateType) + return $this->dateType; + + list( + $this->dateType, + $this->dateTime, + ) = self::parseData($this->value, $this); + return $this->dateType; + + } + + /** + * Parses the internal data structure to figure out what the current date + * and time is. + * + * The returned array contains two elements: + * 1. A 'DateType' constant (as defined on this class), or null. + * 2. A DateTime object (or null) + * + * @param string|null $propertyValue The string to parse (yymmdd or + * ymmddThhmmss, etc..) + * @param Sabre_VObject_Property|null $property The instance of the + * property we're parsing. + * @return array + */ + static public function parseData($propertyValue, Sabre_VObject_Property $property = null) { + + if (is_null($propertyValue)) { + return array(null, null); + } + + $date = '(?P<year>[1-2][0-9]{3})(?P<month>[0-1][0-9])(?P<date>[0-3][0-9])'; + $time = '(?P<hour>[0-2][0-9])(?P<minute>[0-5][0-9])(?P<second>[0-5][0-9])'; + $regex = "/^$date(T$time(?P<isutc>Z)?)?$/"; + + if (!preg_match($regex, $propertyValue, $matches)) { + throw new InvalidArgumentException($propertyValue . ' is not a valid DateTime or Date string'); + } + + if (!isset($matches['hour'])) { + // Date-only + return array( + self::DATE, + new DateTime($matches['year'] . '-' . $matches['month'] . '-' . $matches['date'] . ' 00:00:00'), + ); + } + + $dateStr = + $matches['year'] .'-' . + $matches['month'] . '-' . + $matches['date'] . ' ' . + $matches['hour'] . ':' . + $matches['minute'] . ':' . + $matches['second']; + + if (isset($matches['isutc'])) { + $dt = new DateTime($dateStr,new DateTimeZone('UTC')); + $dt->setTimeZone(new DateTimeZone('UTC')); + return array( + self::UTC, + $dt + ); + } + + // Finding the timezone. + $tzid = $property['TZID']; + if (!$tzid) { + return array( + self::LOCAL, + new DateTime($dateStr) + ); + } + + try { + // tzid an Olson identifier? + $tz = new DateTimeZone($tzid->value); + } catch (Exception $e) { + + // Not an Olson id, we're going to try to find the information + // through the time zone name map. + $newtzid = Sabre_VObject_WindowsTimezoneMap::lookup($tzid->value); + if (is_null($newtzid)) { + + // Not a well known time zone name either, we're going to try + // to find the information through the VTIMEZONE object. + + // First we find the root object + $root = $property; + while($root->parent) { + $root = $root->parent; + } + + if (isset($root->VTIMEZONE)) { + foreach($root->VTIMEZONE as $vtimezone) { + if (((string)$vtimezone->TZID) == $tzid) { + if (isset($vtimezone->{'X-LIC-LOCATION'})) { + $newtzid = (string)$vtimezone->{'X-LIC-LOCATION'}; + } else { + // No libical location specified. As a last resort we could + // try matching $vtimezone's DST rules against all known + // time zones returned by DateTimeZone::list* + + // TODO + } + } + } + } + } + + try { + $tz = new DateTimeZone($newtzid); + } catch (Exception $e) { + // If all else fails, we use the default PHP timezone + $tz = new DateTimeZone(date_default_timezone_get()); + } + } + $dt = new DateTime($dateStr, $tz); + $dt->setTimeZone($tz); + + return array( + self::LOCALTZ, + $dt + ); + + } + +} diff --git a/3rdparty/Sabre/VObject/Property/MultiDateTime.php b/3rdparty/Sabre/VObject/Property/MultiDateTime.php new file mode 100755 index 00000000000..ae53ab6a617 --- /dev/null +++ b/3rdparty/Sabre/VObject/Property/MultiDateTime.php @@ -0,0 +1,166 @@ +<?php + +/** + * Multi-DateTime property + * + * This element is used for iCalendar properties such as the EXDATE property. + * It basically provides a few helper functions that make it easier to deal + * with these. It supports both DATE-TIME and DATE values. + * + * In order to use this correctly, you must call setDateTimes and getDateTimes + * to retrieve and modify dates respectively. + * + * If you use the 'value' or properties directly, this object does not keep + * reference and results might appear incorrectly. + * + * @package Sabre + * @subpackage VObject + * @copyright Copyright (C) 2007-2012 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_Property_MultiDateTime extends Sabre_VObject_Property { + + /** + * DateTime representation + * + * @var DateTime[] + */ + protected $dateTimes; + + /** + * dateType + * + * This is one of the Sabre_VObject_Property_DateTime constants. + * + * @var int + */ + protected $dateType; + + /** + * Updates the value + * + * @param array $dt Must be an array of DateTime objects. + * @param int $dateType + * @return void + */ + public function setDateTimes(array $dt, $dateType = Sabre_VObject_Property_DateTime::LOCALTZ) { + + foreach($dt as $i) + if (!$i instanceof DateTime) + throw new InvalidArgumentException('You must pass an array of DateTime objects'); + + $this->offsetUnset('VALUE'); + $this->offsetUnset('TZID'); + switch($dateType) { + + case Sabre_VObject_Property_DateTime::LOCAL : + $val = array(); + foreach($dt as $i) { + $val[] = $i->format('Ymd\\THis'); + } + $this->setValue(implode(',',$val)); + $this->offsetSet('VALUE','DATE-TIME'); + break; + case Sabre_VObject_Property_DateTime::UTC : + $val = array(); + foreach($dt as $i) { + $i->setTimeZone(new DateTimeZone('UTC')); + $val[] = $i->format('Ymd\\THis\\Z'); + } + $this->setValue(implode(',',$val)); + $this->offsetSet('VALUE','DATE-TIME'); + break; + case Sabre_VObject_Property_DateTime::LOCALTZ : + $val = array(); + foreach($dt as $i) { + $val[] = $i->format('Ymd\\THis'); + } + $this->setValue(implode(',',$val)); + $this->offsetSet('VALUE','DATE-TIME'); + $this->offsetSet('TZID', $dt[0]->getTimeZone()->getName()); + break; + case Sabre_VObject_Property_DateTime::DATE : + $val = array(); + foreach($dt as $i) { + $val[] = $i->format('Ymd'); + } + $this->setValue(implode(',',$val)); + $this->offsetSet('VALUE','DATE'); + break; + default : + throw new InvalidArgumentException('You must pass a valid dateType constant'); + + } + $this->dateTimes = $dt; + $this->dateType = $dateType; + + } + + /** + * Returns the current DateTime value. + * + * If no value was set, this method returns null. + * + * @return array|null + */ + public function getDateTimes() { + + if ($this->dateTimes) + return $this->dateTimes; + + $dts = array(); + + if (!$this->value) { + $this->dateTimes = null; + $this->dateType = null; + return null; + } + + foreach(explode(',',$this->value) as $val) { + list( + $type, + $dt + ) = Sabre_VObject_Property_DateTime::parseData($val, $this); + $dts[] = $dt; + $this->dateType = $type; + } + $this->dateTimes = $dts; + return $this->dateTimes; + + } + + /** + * Returns the type of Date format. + * + * This method returns one of the format constants. If no date was set, + * this method will return null. + * + * @return int|null + */ + public function getDateType() { + + if ($this->dateType) + return $this->dateType; + + if (!$this->value) { + $this->dateTimes = null; + $this->dateType = null; + return null; + } + + $dts = array(); + foreach(explode(',',$this->value) as $val) { + list( + $type, + $dt + ) = Sabre_VObject_Property_DateTime::parseData($val, $this); + $dts[] = $dt; + $this->dateType = $type; + } + $this->dateTimes = $dts; + return $this->dateType; + + } + +} diff --git a/3rdparty/Sabre/VObject/Reader.php b/3rdparty/Sabre/VObject/Reader.php index 7d1c282838e..eea73fa3dce 100644..100755 --- a/3rdparty/Sabre/VObject/Reader.php +++ b/3rdparty/Sabre/VObject/Reader.php @@ -5,40 +5,22 @@ * * This class reads the vobject file, and returns a full element tree. * + * TODO: this class currently completely works 'statically'. This is pointless, + * and defeats OOP principals. Needs refactoring in a future version. * - * TODO: this class currently completely works 'statically'. This is pointless, - * and defeats OOP principals. Needs refaxtoring in a future version. - * * @package Sabre * @subpackage VObject - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 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_Reader { /** - * This array contains a list of Property names that are automatically - * mapped to specific class names. + * Parses the file and returns the top component * - * Adding to this list allows you to specify custom property classes, - * adding extra functionality. - * - * @var array - */ - static public $elementMap = array( - 'DTSTART' => 'Sabre_VObject_Element_DateTime', - 'DTEND' => 'Sabre_VObject_Element_DateTime', - 'COMPLETED' => 'Sabre_VObject_Element_DateTime', - 'DUE' => 'Sabre_VObject_Element_DateTime', - 'EXDATE' => 'Sabre_VObject_Element_MultiDateTime', - ); - - /** - * Parses the file and returns the top component - * - * @param string $data - * @return Sabre_VObject_Element + * @param string $data + * @return Sabre_VObject_Element */ static function read($data) { @@ -63,11 +45,11 @@ class Sabre_VObject_Reader { } unset($lines); - + reset($lines2); return self::readLine($lines2); - + } /** @@ -75,9 +57,9 @@ class Sabre_VObject_Reader { * * This method receives the full array of lines. The array pointer is used * to traverse. - * - * @param array $lines - * @return Sabre_VObject_Element + * + * @param array $lines + * @return Sabre_VObject_Element */ static private function readLine(&$lines) { @@ -88,22 +70,23 @@ class Sabre_VObject_Reader { // Components if (stripos($line,"BEGIN:")===0) { - // This is a component - $obj = new Sabre_VObject_Component(strtoupper(substr($line,6))); + $componentName = strtoupper(substr($line,6)); + $obj = Sabre_VObject_Component::create($componentName); $nextLine = current($lines); while(stripos($nextLine,"END:")!==0) { $obj->add(self::readLine($lines)); + $nextLine = current($lines); - if ($nextLine===false) + if ($nextLine===false) throw new Sabre_VObject_ParseException('Invalid VObject. Document ended prematurely.'); } - // Checking component name of the 'END:' line. + // 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 . '"'); } @@ -117,7 +100,7 @@ class Sabre_VObject_Reader { //$result = preg_match('/(?P<name>[A-Z0-9-]+)(?:;(?P<parameters>^(?<!:):))(.*)$/',$line,$matches); - $token = '[A-Z0-9-\/\.]+'; + $token = '[A-Z0-9-\.]+'; $parameters = "(?:;(?P<parameters>([^:^\"]|\"([^\"]*)\")*))?"; $regex = "/^(?P<name>$token)$parameters:(?P<value>.*)$/i"; @@ -128,22 +111,23 @@ class Sabre_VObject_Reader { } $propertyName = strtoupper($matches['name']); - $propertyValue = stripcslashes($matches['value']); - - if (isset(self::$elementMap[$propertyName])) { - $className = self::$elementMap[$propertyName]; - } else { - $className = 'Sabre_VObject_Property'; - } + $propertyValue = preg_replace_callback('#(\\\\(\\\\|N|n|;|,))#',function($matches) { + if ($matches[2]==='n' || $matches[2]==='N') { + return "\n"; + } else { + return $matches[2]; + } + }, $matches['value']); - $obj = new $className($propertyName, $propertyValue); + $obj = Sabre_VObject_Property::create($propertyName, $propertyValue); if ($matches['parameters']) { foreach(self::readParameters($matches['parameters']) as $param) { $obj->add($param); } - } + + } return $obj; @@ -151,12 +135,12 @@ class Sabre_VObject_Reader { } /** - * Reads a parameter list from a property + * Reads a parameter list from a property * * This method returns an array of Sabre_VObject_Parameter * - * @param string $parameters - * @return array + * @param string $parameters + * @return array */ static private function readParameters($parameters) { @@ -179,7 +163,15 @@ class Sabre_VObject_Reader { $value = ''; } - $params[] = new Sabre_VObject_Parameter($match['paramName'], stripcslashes($value)); + $value = preg_replace_callback('#(\\\\(\\\\|N|n|;|,))#',function($matches) { + if ($matches[2]==='n' || $matches[2]==='N') { + return "\n"; + } else { + return $matches[2]; + } + }, $value); + + $params[] = new Sabre_VObject_Parameter($match['paramName'], $value); } diff --git a/3rdparty/Sabre/VObject/RecurrenceIterator.php b/3rdparty/Sabre/VObject/RecurrenceIterator.php new file mode 100755 index 00000000000..833aa091ab7 --- /dev/null +++ b/3rdparty/Sabre/VObject/RecurrenceIterator.php @@ -0,0 +1,1009 @@ +<?php + +/** + * This class is used to determine new for a recurring event, when the next + * events occur. + * + * This iterator may loop infinitely in the future, therefore it is important + * that if you use this class, you set hard limits for the amount of iterations + * you want to handle. + * + * Note that currently there is not full support for the entire iCalendar + * specification, as it's very complex and contains a lot of permutations + * that's not yet used very often in software. + * + * For the focus has been on features as they actually appear in Calendaring + * software, but this may well get expanded as needed / on demand + * + * The following RRULE properties are supported + * * UNTIL + * * INTERVAL + * * COUNT + * * FREQ=DAILY + * * BYDAY + * * FREQ=WEEKLY + * * BYDAY + * * WKST + * * FREQ=MONTHLY + * * BYMONTHDAY + * * BYDAY + * * BYSETPOS + * * FREQ=YEARLY + * * BYMONTH + * * BYMONTHDAY (only if BYMONTH is also set) + * * BYDAY (only if BYMONTH is also set) + * + * Anything beyond this is 'undefined', which means that it may get ignored, or + * you may get unexpected results. The effect is that in some applications the + * specified recurrence may look incorrect, or is missing. + * + * @package Sabre + * @subpackage VObject + * @copyright Copyright (C) 2007-2012 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_RecurrenceIterator implements Iterator { + + /** + * The initial event date + * + * @var DateTime + */ + public $startDate; + + /** + * The end-date of the initial event + * + * @var DateTime + */ + public $endDate; + + /** + * The 'current' recurrence. + * + * This will be increased for every iteration. + * + * @var DateTime + */ + public $currentDate; + + + /** + * List of dates that are excluded from the rules. + * + * This list contains the items that have been overriden by the EXDATE + * property. + * + * @var array + */ + public $exceptionDates = array(); + + /** + * Base event + * + * @var Sabre_VObject_Component_VEvent + */ + public $baseEvent; + + /** + * List of dates that are overridden by other events. + * Similar to $overriddenEvents, but this just contains the original dates. + * + * @var array + */ + public $overriddenDates = array(); + + /** + * list of events that are 'overridden'. + * + * This is an array of Sabre_VObject_Component_VEvent objects. + * + * @var array + */ + public $overriddenEvents = array(); + + + /** + * Frequency is one of: secondly, minutely, hourly, daily, weekly, monthly, + * yearly. + * + * @var string + */ + public $frequency; + + /** + * The last instance of this recurrence, inclusively + * + * @var DateTime|null + */ + public $until; + + /** + * The number of recurrences, or 'null' if infinitely recurring. + * + * @var int + */ + public $count; + + /** + * The interval. + * + * If for example frequency is set to daily, interval = 2 would mean every + * 2 days. + * + * @var int + */ + public $interval = 1; + + /** + * Which seconds to recur. + * + * This is an array of integers (between 0 and 60) + * + * @var array + */ + public $bySecond; + + /** + * Which minutes to recur + * + * This is an array of integers (between 0 and 59) + * + * @var array + */ + public $byMinute; + + /** + * Which hours to recur + * + * This is an array of integers (between 0 and 23) + * + * @var array + */ + public $byHour; + + /** + * Which weekdays to recur. + * + * This is an array of weekdays + * + * This may also be preceeded by a positive or negative integer. If present, + * this indicates the nth occurrence of a specific day within the monthly or + * yearly rrule. For instance, -2TU indicates the second-last tuesday of + * the month, or year. + * + * @var array + */ + public $byDay; + + /** + * Which days of the month to recur + * + * This is an array of days of the months (1-31). The value can also be + * negative. -5 for instance means the 5th last day of the month. + * + * @var array + */ + public $byMonthDay; + + /** + * Which days of the year to recur. + * + * This is an array with days of the year (1 to 366). The values can also + * be negative. For instance, -1 will always represent the last day of the + * year. (December 31st). + * + * @var array + */ + public $byYearDay; + + /** + * Which week numbers to recur. + * + * This is an array of integers from 1 to 53. The values can also be + * negative. -1 will always refer to the last week of the year. + * + * @var array + */ + public $byWeekNo; + + /** + * Which months to recur + * + * This is an array of integers from 1 to 12. + * + * @var array + */ + public $byMonth; + + /** + * Which items in an existing st to recur. + * + * These numbers work together with an existing by* rule. It specifies + * exactly which items of the existing by-rule to filter. + * + * Valid values are 1 to 366 and -1 to -366. As an example, this can be + * used to recur the last workday of the month. + * + * This would be done by setting frequency to 'monthly', byDay to + * 'MO,TU,WE,TH,FR' and bySetPos to -1. + * + * @var array + */ + public $bySetPos; + + /** + * When a week starts + * + * @var string + */ + public $weekStart = 'MO'; + + /** + * The current item in the list + * + * @var int + */ + public $counter = 0; + + /** + * Simple mapping from iCalendar day names to day numbers + * + * @var array + */ + private $dayMap = array( + 'SU' => 0, + 'MO' => 1, + 'TU' => 2, + 'WE' => 3, + 'TH' => 4, + 'FR' => 5, + 'SA' => 6, + ); + + /** + * Mappings between the day number and english day name. + * + * @var array + */ + private $dayNames = array( + 0 => 'Sunday', + 1 => 'Monday', + 2 => 'Tuesday', + 3 => 'Wednesday', + 4 => 'Thursday', + 5 => 'Friday', + 6 => 'Saturday', + ); + + /** + * If the current iteration of the event is an overriden event, this + * property will hold the VObject + * + * @var Sabre_Component_VObject + */ + private $currentOverriddenEvent; + + /** + * This property may contain the date of the next not-overridden event. + * This date is calculated sometimes a bit early, before overridden events + * are evaluated. + * + * @var DateTime + */ + private $nextDate; + + /** + * Creates the iterator + * + * You should pass a VCALENDAR component, as well as the UID of the event + * we're going to traverse. + * + * @param Sabre_VObject_Component $vcal + * @param string|null $uid + */ + public function __construct(Sabre_VObject_Component $vcal, $uid=null) { + + if (is_null($uid)) { + if ($vcal->name === 'VCALENDAR') { + throw new InvalidArgumentException('If you pass a VCALENDAR object, you must pass a uid argument as well'); + } + $components = array($vcal); + $uid = (string)$vcal->uid; + } else { + $components = $vcal->select('VEVENT'); + } + foreach($components as $component) { + if ((string)$component->uid == $uid) { + if (isset($component->{'RECURRENCE-ID'})) { + $this->overriddenEvents[$component->DTSTART->getDateTime()->getTimeStamp()] = $component; + $this->overriddenDates[] = $component->{'RECURRENCE-ID'}->getDateTime(); + } else { + $this->baseEvent = $component; + } + } + } + if (!$this->baseEvent) { + throw new InvalidArgumentException('Could not find a base event with uid: ' . $uid); + } + + $this->startDate = clone $this->baseEvent->DTSTART->getDateTime(); + + $this->endDate = null; + if (isset($this->baseEvent->DTEND)) { + $this->endDate = clone $this->baseEvent->DTEND->getDateTime(); + } else { + $this->endDate = clone $this->startDate; + if (isset($this->baseEvent->DURATION)) { + $this->endDate->add(Sabre_VObject_DateTimeParser::parse($this->baseEvent->DURATION->value)); + } + } + $this->currentDate = clone $this->startDate; + + $rrule = (string)$this->baseEvent->RRULE; + + $parts = explode(';', $rrule); + + foreach($parts as $part) { + + list($key, $value) = explode('=', $part, 2); + + switch(strtoupper($key)) { + + case 'FREQ' : + if (!in_array( + strtolower($value), + array('secondly','minutely','hourly','daily','weekly','monthly','yearly') + )) { + throw new InvalidArgumentException('Unknown value for FREQ=' . strtoupper($value)); + + } + $this->frequency = strtolower($value); + break; + + case 'UNTIL' : + $this->until = Sabre_VObject_DateTimeParser::parse($value); + break; + + case 'COUNT' : + $this->count = (int)$value; + break; + + case 'INTERVAL' : + $this->interval = (int)$value; + break; + + case 'BYSECOND' : + $this->bySecond = explode(',', $value); + break; + + case 'BYMINUTE' : + $this->byMinute = explode(',', $value); + break; + + case 'BYHOUR' : + $this->byHour = explode(',', $value); + break; + + case 'BYDAY' : + $this->byDay = explode(',', strtoupper($value)); + break; + + case 'BYMONTHDAY' : + $this->byMonthDay = explode(',', $value); + break; + + case 'BYYEARDAY' : + $this->byYearDay = explode(',', $value); + break; + + case 'BYWEEKNO' : + $this->byWeekNo = explode(',', $value); + break; + + case 'BYMONTH' : + $this->byMonth = explode(',', $value); + break; + + case 'BYSETPOS' : + $this->bySetPos = explode(',', $value); + break; + + case 'WKST' : + $this->weekStart = strtoupper($value); + break; + + } + + } + + // Parsing exception dates + if (isset($this->baseEvent->EXDATE)) { + foreach($this->baseEvent->EXDATE as $exDate) { + + foreach(explode(',', (string)$exDate) as $exceptionDate) { + + $this->exceptionDates[] = + Sabre_VObject_DateTimeParser::parse($exceptionDate, $this->startDate->getTimeZone()); + + } + + } + + } + + } + + /** + * Returns the current item in the list + * + * @return DateTime + */ + public function current() { + + if (!$this->valid()) return null; + return clone $this->currentDate; + + } + + /** + * This method returns the startdate for the current iteration of the + * event. + * + * @return DateTime + */ + public function getDtStart() { + + if (!$this->valid()) return null; + return clone $this->currentDate; + + } + + /** + * This method returns the enddate for the current iteration of the + * event. + * + * @return DateTime + */ + public function getDtEnd() { + + if (!$this->valid()) return null; + $dtEnd = clone $this->currentDate; + $dtEnd->add( $this->startDate->diff( $this->endDate ) ); + return clone $dtEnd; + + } + + /** + * Returns a VEVENT object with the updated start and end date. + * + * Any recurrence information is removed, and this function may return an + * 'overridden' event instead. + * + * This method always returns a cloned instance. + * + * @return void + */ + public function getEventObject() { + + if ($this->currentOverriddenEvent) { + return clone $this->currentOverriddenEvent; + } + $event = clone $this->baseEvent; + unset($event->RRULE); + unset($event->EXDATE); + unset($event->RDATE); + unset($event->EXRULE); + + $event->DTSTART->setDateTime($this->getDTStart(), $event->DTSTART->getDateType()); + if (isset($event->DTEND)) { + $event->DTEND->setDateTime($this->getDtEnd(), $event->DTSTART->getDateType()); + } + if ($this->counter > 0) { + $event->{'RECURRENCE-ID'} = (string)$event->DTSTART; + } + + return $event; + + } + + /** + * Returns the current item number + * + * @return int + */ + public function key() { + + return $this->counter; + + } + + /** + * Whether or not there is a 'next item' + * + * @return bool + */ + public function valid() { + + if (!is_null($this->count)) { + return $this->counter < $this->count; + } + if (!is_null($this->until)) { + return $this->currentDate <= $this->until; + } + return true; + + } + + /** + * Resets the iterator + * + * @return void + */ + public function rewind() { + + $this->currentDate = clone $this->startDate; + $this->counter = 0; + + } + + /** + * This method allows you to quickly go to the next occurrence after the + * specified date. + * + * Note that this checks the current 'endDate', not the 'stardDate'. This + * means that if you forward to January 1st, the iterator will stop at the + * first event that ends *after* January 1st. + * + * @param DateTime $dt + * @return void + */ + public function fastForward(DateTime $dt) { + + while($this->valid() && $this->getDTEnd() < $dt) { + $this->next(); + } + + } + + /** + * Goes on to the next iteration + * + * @return void + */ + public function next() { + + /* + if (!is_null($this->count) && $this->counter >= $this->count) { + $this->currentDate = null; + }*/ + + + $previousStamp = $this->currentDate->getTimeStamp(); + + while(true) { + + $this->currentOverriddenEvent = null; + + // If we have a next date 'stored', we use that + if ($this->nextDate) { + $this->currentDate = $this->nextDate; + $currentStamp = $this->currentDate->getTimeStamp(); + $this->nextDate = null; + } else { + + // Otherwise, we calculate it + switch($this->frequency) { + + case 'daily' : + $this->nextDaily(); + break; + + case 'weekly' : + $this->nextWeekly(); + break; + + case 'monthly' : + $this->nextMonthly(); + break; + + case 'yearly' : + $this->nextYearly(); + break; + + } + $currentStamp = $this->currentDate->getTimeStamp(); + + // Checking exception dates + foreach($this->exceptionDates as $exceptionDate) { + if ($this->currentDate == $exceptionDate) { + $this->counter++; + continue 2; + } + } + foreach($this->overriddenDates as $overriddenDate) { + if ($this->currentDate == $overriddenDate) { + continue 2; + } + } + + } + + // Checking overriden events + foreach($this->overriddenEvents as $index=>$event) { + if ($index > $previousStamp && $index <= $currentStamp) { + + // We're moving the 'next date' aside, for later use. + $this->nextDate = clone $this->currentDate; + + $this->currentDate = $event->DTSTART->getDateTime(); + $this->currentOverriddenEvent = $event; + + break; + } + } + + break; + + } + + /* + if (!is_null($this->until)) { + if($this->currentDate > $this->until) { + $this->currentDate = null; + } + }*/ + + $this->counter++; + + } + + /** + * Does the processing for advancing the iterator for daily frequency. + * + * @return void + */ + protected function nextDaily() { + + if (!$this->byDay) { + $this->currentDate->modify('+' . $this->interval . ' days'); + return; + } + + $recurrenceDays = array(); + foreach($this->byDay as $byDay) { + + // The day may be preceeded with a positive (+n) or + // negative (-n) integer. However, this does not make + // sense in 'weekly' so we ignore it here. + $recurrenceDays[] = $this->dayMap[substr($byDay,-2)]; + + } + + do { + + $this->currentDate->modify('+' . $this->interval . ' days'); + + // Current day of the week + $currentDay = $this->currentDate->format('w'); + + } while (!in_array($currentDay, $recurrenceDays)); + + } + + /** + * Does the processing for advancing the iterator for weekly frequency. + * + * @return void + */ + protected function nextWeekly() { + + if (!$this->byDay) { + $this->currentDate->modify('+' . $this->interval . ' weeks'); + return; + } + + $recurrenceDays = array(); + foreach($this->byDay as $byDay) { + + // The day may be preceeded with a positive (+n) or + // negative (-n) integer. However, this does not make + // sense in 'weekly' so we ignore it here. + $recurrenceDays[] = $this->dayMap[substr($byDay,-2)]; + + } + + // Current day of the week + $currentDay = $this->currentDate->format('w'); + + // First day of the week: + $firstDay = $this->dayMap[$this->weekStart]; + + $time = array( + $this->currentDate->format('H'), + $this->currentDate->format('i'), + $this->currentDate->format('s') + ); + + // Increasing the 'current day' until we find our next + // occurrence. + while(true) { + + $currentDay++; + + if ($currentDay>6) { + $currentDay = 0; + } + + // We need to roll over to the next week + if ($currentDay === $firstDay) { + $this->currentDate->modify('+' . $this->interval . ' weeks'); + + // We need to go to the first day of this week, but only if we + // are not already on this first day of this week. + if($this->currentDate->format('w') != $firstDay) { + $this->currentDate->modify('last ' . $this->dayNames[$this->dayMap[$this->weekStart]]); + $this->currentDate->setTime($time[0],$time[1],$time[2]); + } + } + + // We have a match + if (in_array($currentDay ,$recurrenceDays)) { + $this->currentDate->modify($this->dayNames[$currentDay]); + $this->currentDate->setTime($time[0],$time[1],$time[2]); + break; + } + + } + + } + + /** + * Does the processing for advancing the iterator for monthly frequency. + * + * @return void + */ + protected function nextMonthly() { + + $currentDayOfMonth = $this->currentDate->format('j'); + if (!$this->byMonthDay && !$this->byDay) { + + // If the current day is higher than the 28th, rollover can + // occur to the next month. We Must skip these invalid + // entries. + if ($currentDayOfMonth < 29) { + $this->currentDate->modify('+' . $this->interval . ' months'); + } else { + $increase = 0; + do { + $increase++; + $tempDate = clone $this->currentDate; + $tempDate->modify('+ ' . ($this->interval*$increase) . ' months'); + } while ($tempDate->format('j') != $currentDayOfMonth); + $this->currentDate = $tempDate; + } + return; + } + + while(true) { + + $occurrences = $this->getMonthlyOccurrences(); + + foreach($occurrences as $occurrence) { + + // The first occurrence thats higher than the current + // day of the month wins. + if ($occurrence > $currentDayOfMonth) { + break 2; + } + + } + + // If we made it all the way here, it means there were no + // valid occurrences, and we need to advance to the next + // month. + $this->currentDate->modify('first day of this month'); + $this->currentDate->modify('+ ' . $this->interval . ' months'); + + // This goes to 0 because we need to start counting at hte + // beginning. + $currentDayOfMonth = 0; + + } + + $this->currentDate->setDate($this->currentDate->format('Y'), $this->currentDate->format('n'), $occurrence); + + } + + /** + * Does the processing for advancing the iterator for yearly frequency. + * + * @return void + */ + protected function nextYearly() { + + if (!$this->byMonth) { + $this->currentDate->modify('+' . $this->interval . ' years'); + return; + } + + $currentMonth = $this->currentDate->format('n'); + $currentYear = $this->currentDate->format('Y'); + $currentDayOfMonth = $this->currentDate->format('j'); + + $advancedToNewMonth = false; + + // If we got a byDay or getMonthDay filter, we must first expand + // further. + if ($this->byDay || $this->byMonthDay) { + + while(true) { + + $occurrences = $this->getMonthlyOccurrences(); + + foreach($occurrences as $occurrence) { + + // The first occurrence that's higher than the current + // day of the month wins. + // If we advanced to the next month or year, the first + // occurence is always correct. + if ($occurrence > $currentDayOfMonth || $advancedToNewMonth) { + break 2; + } + + } + + // If we made it here, it means we need to advance to + // the next month or year. + $currentDayOfMonth = 1; + $advancedToNewMonth = true; + do { + + $currentMonth++; + if ($currentMonth>12) { + $currentYear+=$this->interval; + $currentMonth = 1; + } + } while (!in_array($currentMonth, $this->byMonth)); + + $this->currentDate->setDate($currentYear, $currentMonth, $currentDayOfMonth); + + } + + // If we made it here, it means we got a valid occurrence + $this->currentDate->setDate($currentYear, $currentMonth, $occurrence); + return; + + } else { + + // no byDay or byMonthDay, so we can just loop through the + // months. + do { + + $currentMonth++; + if ($currentMonth>12) { + $currentYear+=$this->interval; + $currentMonth = 1; + } + } while (!in_array($currentMonth, $this->byMonth)); + $this->currentDate->setDate($currentYear, $currentMonth, $currentDayOfMonth); + return; + + } + + } + + /** + * Returns all the occurrences for a monthly frequency with a 'byDay' or + * 'byMonthDay' expansion for the current month. + * + * The returned list is an array of integers with the day of month (1-31). + * + * @return array + */ + protected function getMonthlyOccurrences() { + + $startDate = clone $this->currentDate; + + $byDayResults = array(); + + // Our strategy is to simply go through the byDays, advance the date to + // that point and add it to the results. + if ($this->byDay) foreach($this->byDay as $day) { + + $dayName = $this->dayNames[$this->dayMap[substr($day,-2)]]; + + // Dayname will be something like 'wednesday'. Now we need to find + // all wednesdays in this month. + $dayHits = array(); + + $checkDate = clone $startDate; + $checkDate->modify('first day of this month'); + $checkDate->modify($dayName); + + do { + $dayHits[] = $checkDate->format('j'); + $checkDate->modify('next ' . $dayName); + } while ($checkDate->format('n') === $startDate->format('n')); + + // So now we have 'all wednesdays' for month. It is however + // possible that the user only really wanted the 1st, 2nd or last + // wednesday. + if (strlen($day)>2) { + $offset = (int)substr($day,0,-2); + + if ($offset>0) { + // It is possible that the day does not exist, such as a + // 5th or 6th wednesday of the month. + if (isset($dayHits[$offset-1])) { + $byDayResults[] = $dayHits[$offset-1]; + } + } else { + + // if it was negative we count from the end of the array + $byDayResults[] = $dayHits[count($dayHits) + $offset]; + } + } else { + // There was no counter (first, second, last wednesdays), so we + // just need to add the all to the list). + $byDayResults = array_merge($byDayResults, $dayHits); + + } + + } + + $byMonthDayResults = array(); + if ($this->byMonthDay) foreach($this->byMonthDay as $monthDay) { + + // Removing values that are out of range for this month + if ($monthDay > $startDate->format('t') || + $monthDay < 0-$startDate->format('t')) { + continue; + } + if ($monthDay>0) { + $byMonthDayResults[] = $monthDay; + } else { + // Negative values + $byMonthDayResults[] = $startDate->format('t') + 1 + $monthDay; + } + } + + // If there was just byDay or just byMonthDay, they just specify our + // (almost) final list. If both were provided, then byDay limits the + // list. + if ($this->byMonthDay && $this->byDay) { + $result = array_intersect($byMonthDayResults, $byDayResults); + } elseif ($this->byMonthDay) { + $result = $byMonthDayResults; + } else { + $result = $byDayResults; + } + $result = array_unique($result); + sort($result, SORT_NUMERIC); + + // The last thing that needs checking is the BYSETPOS. If it's set, it + // means only certain items in the set survive the filter. + if (!$this->bySetPos) { + return $result; + } + + $filteredResult = array(); + foreach($this->bySetPos as $setPos) { + + if ($setPos<0) { + $setPos = count($result)-($setPos+1); + } + if (isset($result[$setPos-1])) { + $filteredResult[] = $result[$setPos-1]; + } + } + + sort($filteredResult, SORT_NUMERIC); + return $filteredResult; + + } + + +} + diff --git a/3rdparty/Sabre/VObject/Version.php b/3rdparty/Sabre/VObject/Version.php index 937c367e222..00110febc07 100644..100755 --- a/3rdparty/Sabre/VObject/Version.php +++ b/3rdparty/Sabre/VObject/Version.php @@ -2,10 +2,10 @@ /** * This class contains the version number for the VObject package - * + * * @package Sabre - * @subpackage VObject - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @subpackage VObject + * @copyright Copyright (C) 2007-2012 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_VObject_Version { /** * Full version number */ - const VERSION = '1.2.4'; + const VERSION = '1.3.2'; /** * Stability : alpha, beta, stable diff --git a/3rdparty/Sabre/VObject/WindowsTimezoneMap.php b/3rdparty/Sabre/VObject/WindowsTimezoneMap.php new file mode 100755 index 00000000000..5e1cc5d479b --- /dev/null +++ b/3rdparty/Sabre/VObject/WindowsTimezoneMap.php @@ -0,0 +1,128 @@ +<?php + +/** + * Time zone name translation + * + * This file translates well-known time zone names into "Olson database" time zone names. + * + * @package Sabre + * @subpackage VObject + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. + * @author Frank Edelhaeuser (fedel@users.sourceforge.net) + * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License + */ +class Sabre_VObject_WindowsTimezoneMap { + + protected static $map = array( + + // from http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/zone_tzid.html + // snapshot taken on 2012/01/16 + + // windows + 'AUS Central Standard Time'=>'Australia/Darwin', + 'AUS Eastern Standard Time'=>'Australia/Sydney', + 'Afghanistan Standard Time'=>'Asia/Kabul', + 'Alaskan Standard Time'=>'America/Anchorage', + 'Arab Standard Time'=>'Asia/Riyadh', + 'Arabian Standard Time'=>'Asia/Dubai', + 'Arabic Standard Time'=>'Asia/Baghdad', + 'Argentina Standard Time'=>'America/Buenos_Aires', + 'Armenian Standard Time'=>'Asia/Yerevan', + 'Atlantic Standard Time'=>'America/Halifax', + 'Azerbaijan Standard Time'=>'Asia/Baku', + 'Azores Standard Time'=>'Atlantic/Azores', + 'Bangladesh Standard Time'=>'Asia/Dhaka', + 'Canada Central Standard Time'=>'America/Regina', + 'Cape Verde Standard Time'=>'Atlantic/Cape_Verde', + 'Caucasus Standard Time'=>'Asia/Yerevan', + 'Cen. Australia Standard Time'=>'Australia/Adelaide', + 'Central America Standard Time'=>'America/Guatemala', + 'Central Asia Standard Time'=>'Asia/Almaty', + 'Central Brazilian Standard Time'=>'America/Cuiaba', + 'Central Europe Standard Time'=>'Europe/Budapest', + 'Central European Standard Time'=>'Europe/Warsaw', + 'Central Pacific Standard Time'=>'Pacific/Guadalcanal', + 'Central Standard Time'=>'America/Chicago', + 'Central Standard Time (Mexico)'=>'America/Mexico_City', + 'China Standard Time'=>'Asia/Shanghai', + 'Dateline Standard Time'=>'Etc/GMT+12', + 'E. Africa Standard Time'=>'Africa/Nairobi', + 'E. Australia Standard Time'=>'Australia/Brisbane', + 'E. Europe Standard Time'=>'Europe/Minsk', + 'E. South America Standard Time'=>'America/Sao_Paulo', + 'Eastern Standard Time'=>'America/New_York', + 'Egypt Standard Time'=>'Africa/Cairo', + 'Ekaterinburg Standard Time'=>'Asia/Yekaterinburg', + 'FLE Standard Time'=>'Europe/Kiev', + 'Fiji Standard Time'=>'Pacific/Fiji', + 'GMT Standard Time'=>'Europe/London', + 'GTB Standard Time'=>'Europe/Istanbul', + 'Georgian Standard Time'=>'Asia/Tbilisi', + 'Greenland Standard Time'=>'America/Godthab', + 'Greenwich Standard Time'=>'Atlantic/Reykjavik', + 'Hawaiian Standard Time'=>'Pacific/Honolulu', + 'India Standard Time'=>'Asia/Calcutta', + 'Iran Standard Time'=>'Asia/Tehran', + 'Israel Standard Time'=>'Asia/Jerusalem', + 'Jordan Standard Time'=>'Asia/Amman', + 'Kamchatka Standard Time'=>'Asia/Kamchatka', + 'Korea Standard Time'=>'Asia/Seoul', + 'Magadan Standard Time'=>'Asia/Magadan', + 'Mauritius Standard Time'=>'Indian/Mauritius', + 'Mexico Standard Time'=>'America/Mexico_City', + 'Mexico Standard Time 2'=>'America/Chihuahua', + 'Mid-Atlantic Standard Time'=>'Etc/GMT+2', + 'Middle East Standard Time'=>'Asia/Beirut', + 'Montevideo Standard Time'=>'America/Montevideo', + 'Morocco Standard Time'=>'Africa/Casablanca', + 'Mountain Standard Time'=>'America/Denver', + 'Mountain Standard Time (Mexico)'=>'America/Chihuahua', + 'Myanmar Standard Time'=>'Asia/Rangoon', + 'N. Central Asia Standard Time'=>'Asia/Novosibirsk', + 'Namibia Standard Time'=>'Africa/Windhoek', + 'Nepal Standard Time'=>'Asia/Katmandu', + 'New Zealand Standard Time'=>'Pacific/Auckland', + 'Newfoundland Standard Time'=>'America/St_Johns', + 'North Asia East Standard Time'=>'Asia/Irkutsk', + 'North Asia Standard Time'=>'Asia/Krasnoyarsk', + 'Pacific SA Standard Time'=>'America/Santiago', + 'Pacific Standard Time'=>'America/Los_Angeles', + 'Pacific Standard Time (Mexico)'=>'America/Santa_Isabel', + 'Pakistan Standard Time'=>'Asia/Karachi', + 'Paraguay Standard Time'=>'America/Asuncion', + 'Romance Standard Time'=>'Europe/Paris', + 'Russian Standard Time'=>'Europe/Moscow', + 'SA Eastern Standard Time'=>'America/Cayenne', + 'SA Pacific Standard Time'=>'America/Bogota', + 'SA Western Standard Time'=>'America/La_Paz', + 'SE Asia Standard Time'=>'Asia/Bangkok', + 'Samoa Standard Time'=>'Pacific/Apia', + 'Singapore Standard Time'=>'Asia/Singapore', + 'South Africa Standard Time'=>'Africa/Johannesburg', + 'Sri Lanka Standard Time'=>'Asia/Colombo', + 'Syria Standard Time'=>'Asia/Damascus', + 'Taipei Standard Time'=>'Asia/Taipei', + 'Tasmania Standard Time'=>'Australia/Hobart', + 'Tokyo Standard Time'=>'Asia/Tokyo', + 'Tonga Standard Time'=>'Pacific/Tongatapu', + 'US Eastern Standard Time'=>'America/Indianapolis', + 'US Mountain Standard Time'=>'America/Phoenix', + 'UTC'=>'Etc/GMT', + 'UTC+12'=>'Etc/GMT-12', + 'UTC-02'=>'Etc/GMT+2', + 'UTC-11'=>'Etc/GMT+11', + 'Ulaanbaatar Standard Time'=>'Asia/Ulaanbaatar', + 'Venezuela Standard Time'=>'America/Caracas', + 'Vladivostok Standard Time'=>'Asia/Vladivostok', + 'W. Australia Standard Time'=>'Australia/Perth', + 'W. Central Africa Standard Time'=>'Africa/Lagos', + 'W. Europe Standard Time'=>'Europe/Berlin', + 'West Asia Standard Time'=>'Asia/Tashkent', + 'West Pacific Standard Time'=>'Pacific/Port_Moresby', + 'Yakutsk Standard Time'=>'Asia/Yakutsk', + ); + + static public function lookup($tzid) { + return isset(self::$map[$tzid]) ? self::$map[$tzid] : null; + } +} diff --git a/3rdparty/Sabre/VObject/includes.php b/3rdparty/Sabre/VObject/includes.php index f21010fb275..0177a8f1ba6 100644..100755 --- a/3rdparty/Sabre/VObject/includes.php +++ b/3rdparty/Sabre/VObject/includes.php @@ -1,29 +1,41 @@ <?php /** - * VObject includes + * Sabre_VObject includes file * - * This file automatically includes all VObject classes + * Including this file will automatically include all files from the VObject + * package. + * + * This often allows faster loadtimes, as autoload-speed is often quite slow. * * @package Sabre * @subpackage VObject - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. + * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ - -include dirname(__FILE__) . '/ParseException.php'; - -include dirname(__FILE__) . '/Node.php'; -include dirname(__FILE__) . '/Element.php'; -include dirname(__FILE__) . '/ElementList.php'; -include dirname(__FILE__) . '/Parameter.php'; -include dirname(__FILE__) . '/Property.php'; -include dirname(__FILE__) . '/Component.php'; - -include dirname(__FILE__) . '/Element/DateTime.php'; -include dirname(__FILE__) . '/Element/MultiDateTime.php'; - -include dirname(__FILE__) . '/Reader.php'; -include dirname(__FILE__) . '/Version.php'; +// Begin includes +include __DIR__ . '/DateTimeParser.php'; +include __DIR__ . '/ElementList.php'; +include __DIR__ . '/FreeBusyGenerator.php'; +include __DIR__ . '/Node.php'; +include __DIR__ . '/Parameter.php'; +include __DIR__ . '/ParseException.php'; +include __DIR__ . '/Reader.php'; +include __DIR__ . '/RecurrenceIterator.php'; +include __DIR__ . '/Version.php'; +include __DIR__ . '/WindowsTimezoneMap.php'; +include __DIR__ . '/Element.php'; +include __DIR__ . '/Property.php'; +include __DIR__ . '/Component.php'; +include __DIR__ . '/Property/DateTime.php'; +include __DIR__ . '/Property/MultiDateTime.php'; +include __DIR__ . '/Component/VAlarm.php'; +include __DIR__ . '/Component/VCalendar.php'; +include __DIR__ . '/Component/VEvent.php'; +include __DIR__ . '/Component/VJournal.php'; +include __DIR__ . '/Component/VTodo.php'; +include __DIR__ . '/Element/DateTime.php'; +include __DIR__ . '/Element/MultiDateTime.php'; +// End includes diff --git a/3rdparty/Sabre/autoload.php b/3rdparty/Sabre/autoload.php index 0649df655b0..c7b537d83d3 100644..100755 --- a/3rdparty/Sabre/autoload.php +++ b/3rdparty/Sabre/autoload.php @@ -8,11 +8,15 @@ * * @package Sabre * @subpackage DAV - * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. + * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ +/** + * @param string $className + * @return void + */ function Sabre_autoload($className) { if(strpos($className,'Sabre_')===0) { diff --git a/apps/calendar/ajax/event/edit.form.php b/apps/calendar/ajax/event/edit.form.php index ec50b78be6f..e963da32958 100644 --- a/apps/calendar/ajax/event/edit.form.php +++ b/apps/calendar/ajax/event/edit.form.php @@ -27,15 +27,15 @@ $vevent = $object->VEVENT; $dtstart = $vevent->DTSTART; $dtend = OC_Calendar_Object::getDTEndFromVEvent($vevent); switch($dtstart->getDateType()) { - case Sabre_VObject_Element_DateTime::LOCALTZ: - case Sabre_VObject_Element_DateTime::LOCAL: + case Sabre_VObject_Property_DateTime::LOCALTZ: + case Sabre_VObject_Property_DateTime::LOCAL: $startdate = $dtstart->getDateTime()->format('d-m-Y'); $starttime = $dtstart->getDateTime()->format('H:i'); $enddate = $dtend->getDateTime()->format('d-m-Y'); $endtime = $dtend->getDateTime()->format('H:i'); $allday = false; break; - case Sabre_VObject_Element_DateTime::DATE: + case Sabre_VObject_Property_DateTime::DATE: $startdate = $dtstart->getDateTime()->format('d-m-Y'); $starttime = ''; $dtend->getDateTime()->modify('-1 day'); diff --git a/apps/calendar/ajax/event/move.php b/apps/calendar/ajax/event/move.php index 0552c7bbc5b..75d174c13e1 100644 --- a/apps/calendar/ajax/event/move.php +++ b/apps/calendar/ajax/event/move.php @@ -27,19 +27,19 @@ $dtstart = $vevent->DTSTART; $dtend = OC_Calendar_Object::getDTEndFromVEvent($vevent); $start_type = $dtstart->getDateType(); $end_type = $dtend->getDateType(); -if ($allday && $start_type != Sabre_VObject_Element_DateTime::DATE){ - $start_type = $end_type = Sabre_VObject_Element_DateTime::DATE; +if ($allday && $start_type != Sabre_VObject_Property_DateTime::DATE){ + $start_type = $end_type = Sabre_VObject_Property_DateTime::DATE; $dtend->setDateTime($dtend->getDateTime()->modify('+1 day'), $end_type); } -if (!$allday && $start_type == Sabre_VObject_Element_DateTime::DATE){ - $start_type = $end_type = Sabre_VObject_Element_DateTime::LOCALTZ; +if (!$allday && $start_type == Sabre_VObject_Property_DateTime::DATE){ + $start_type = $end_type = Sabre_VObject_Property_DateTime::LOCALTZ; } $dtstart->setDateTime($dtstart->getDateTime()->add($delta), $start_type); $dtend->setDateTime($dtend->getDateTime()->add($delta), $end_type); unset($vevent->DURATION); -$vevent->setDateTime('LAST-MODIFIED', 'now', Sabre_VObject_Element_DateTime::UTC); -$vevent->setDateTime('DTSTAMP', 'now', Sabre_VObject_Element_DateTime::UTC); +$vevent->setDateTime('LAST-MODIFIED', 'now', Sabre_VObject_Property_DateTime::UTC); +$vevent->setDateTime('DTSTAMP', 'now', Sabre_VObject_Property_DateTime::UTC); $result = OC_Calendar_Object::edit($id, $vcalendar->serialize()); $lastmodified = $vevent->__get('LAST-MODIFIED')->getDateTime(); diff --git a/apps/calendar/ajax/event/resize.php b/apps/calendar/ajax/event/resize.php index 593835d86c5..260b6914426 100644 --- a/apps/calendar/ajax/event/resize.php +++ b/apps/calendar/ajax/event/resize.php @@ -30,8 +30,8 @@ $end_type = $dtend->getDateType(); $dtend->setDateTime($dtend->getDateTime()->add($delta), $end_type); unset($vevent->DURATION); -$vevent->setDateTime('LAST-MODIFIED', 'now', Sabre_VObject_Element_DateTime::UTC); -$vevent->setDateTime('DTSTAMP', 'now', Sabre_VObject_Element_DateTime::UTC); +$vevent->setDateTime('LAST-MODIFIED', 'now', Sabre_VObject_Property_DateTime::UTC); +$vevent->setDateTime('DTSTAMP', 'now', Sabre_VObject_Property_DateTime::UTC); OC_Calendar_Object::edit($id, $vcalendar->serialize()); $lastmodified = $vevent->__get('LAST-MODIFIED')->getDateTime(); diff --git a/apps/calendar/ajax/events.php b/apps/calendar/ajax/events.php index 3aa487fd231..8adaa4c98f3 100755 --- a/apps/calendar/ajax/events.php +++ b/apps/calendar/ajax/events.php @@ -20,7 +20,6 @@ $events = OC_Calendar_App::getrequestedEvents($_GET['calendar_id'], $start, $end $output = array(); foreach($events as $event){ $output[] = OC_Calendar_App::generateEventOutput($event, $start, $end); - } OC_JSON::encodedPrint($output); ?> diff --git a/apps/calendar/lib/object.php b/apps/calendar/lib/object.php index 825977c17c5..ae6fce3c842 100644 --- a/apps/calendar/lib/object.php +++ b/apps/calendar/lib/object.php @@ -590,7 +590,7 @@ class OC_Calendar_Object{ $vevent = new OC_VObject('VEVENT'); $vcalendar->add($vevent); - $vevent->setDateTime('CREATED', 'now', Sabre_VObject_Element_DateTime::UTC); + $vevent->setDateTime('CREATED', 'now', Sabre_VObject_Property_DateTime::UTC); $vevent->setUID(); return self::updateVCalendarFromRequest($request, $vcalendar); @@ -751,22 +751,22 @@ class OC_Calendar_Object{ } - $vevent->setDateTime('LAST-MODIFIED', 'now', Sabre_VObject_Element_DateTime::UTC); - $vevent->setDateTime('DTSTAMP', 'now', Sabre_VObject_Element_DateTime::UTC); + $vevent->setDateTime('LAST-MODIFIED', 'now', Sabre_VObject_Property_DateTime::UTC); + $vevent->setDateTime('DTSTAMP', 'now', Sabre_VObject_Property_DateTime::UTC); $vevent->setString('SUMMARY', $title); if($allday){ $start = new DateTime($from); $end = new DateTime($to.' +1 day'); - $vevent->setDateTime('DTSTART', $start, Sabre_VObject_Element_DateTime::DATE); - $vevent->setDateTime('DTEND', $end, Sabre_VObject_Element_DateTime::DATE); + $vevent->setDateTime('DTSTART', $start, Sabre_VObject_Property_DateTime::DATE); + $vevent->setDateTime('DTEND', $end, Sabre_VObject_Property_DateTime::DATE); }else{ $timezone = OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timezone', date_default_timezone_get()); $timezone = new DateTimeZone($timezone); $start = new DateTime($from.' '.$fromtime, $timezone); $end = new DateTime($to.' '.$totime, $timezone); - $vevent->setDateTime('DTSTART', $start, Sabre_VObject_Element_DateTime::LOCALTZ); - $vevent->setDateTime('DTEND', $end, Sabre_VObject_Element_DateTime::LOCALTZ); + $vevent->setDateTime('DTSTART', $start, Sabre_VObject_Property_DateTime::LOCALTZ); + $vevent->setDateTime('DTEND', $end, Sabre_VObject_Property_DateTime::LOCALTZ); } unset($vevent->DURATION); diff --git a/apps/calendar/lib/search.php b/apps/calendar/lib/search.php index da5fa35bc21..0e1a9032666 100644 --- a/apps/calendar/lib/search.php +++ b/apps/calendar/lib/search.php @@ -26,7 +26,7 @@ class OC_Search_Provider_Calendar extends OC_Search_Provider{ $start_dt->setTimezone(new DateTimeZone($user_timezone)); $end_dt = $dtend->getDateTime(); $end_dt->setTimezone(new DateTimeZone($user_timezone)); - if ($dtstart->getDateType() == Sabre_VObject_Element_DateTime::DATE){ + if ($dtstart->getDateType() == Sabre_VObject_Property_DateTime::DATE){ $end_dt->modify('-1 sec'); if($start_dt->format('d.m.Y') != $end_dt->format('d.m.Y')){ $info = $l->t('Date') . ': ' . $start_dt->format('d.m.Y') . ' - ' . $end_dt->format('d.m.Y'); diff --git a/apps/contacts/ajax/uploadimport.php b/apps/contacts/ajax/uploadimport.php index ab680c8823f..f44335a961e 100644 --- a/apps/contacts/ajax/uploadimport.php +++ b/apps/contacts/ajax/uploadimport.php @@ -34,17 +34,52 @@ function debug($msg) { OC_Log::write('contacts','ajax/uploadimport.php: '.$msg, OC_Log::DEBUG); } +$view = OC_App::getStorage('contacts'); +$tmpfile = md5(rand()); + // If it is a Drag'n'Drop transfer it's handled here. $fn = (isset($_SERVER['HTTP_X_FILE_NAME']) ? $_SERVER['HTTP_X_FILE_NAME'] : false); if($fn) { - $view = OC_App::getStorage('contacts'); - $tmpfile = md5(rand()); if($view->file_put_contents('/'.$tmpfile, file_get_contents('php://input'))) { debug($fn.' uploaded'); OC_JSON::success(array('data' => array('path'=>'', 'file'=>$tmpfile))); + exit(); } else { bailOut(OC_Contacts_App::$l10n->t('Error uploading contacts to storage.')); } } +// File input transfers are handled here +if (!isset($_FILES['importfile'])) { + OC_Log::write('contacts','ajax/uploadphoto.php: No file was uploaded. Unknown error.', OC_Log::DEBUG); + OC_JSON::error(array('data' => array( 'message' => 'No file was uploaded. Unknown error' ))); + exit(); +} +$error = $_FILES['importfile']['error']; +if($error !== UPLOAD_ERR_OK) { + $errors = array( + 0=>OC_Contacts_App::$l10n->t("There is no error, the file uploaded with success"), + 1=>OC_Contacts_App::$l10n->t("The uploaded file exceeds the upload_max_filesize directive in php.ini").ini_get('upload_max_filesize'), + 2=>OC_Contacts_App::$l10n->t("The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form"), + 3=>OC_Contacts_App::$l10n->t("The uploaded file was only partially uploaded"), + 4=>OC_Contacts_App::$l10n->t("No file was uploaded"), + 6=>OC_Contacts_App::$l10n->t("Missing a temporary folder") + ); + bailOut($errors[$error]); +} +$file=$_FILES['importfile']; + +$tmpfname = tempnam("/tmp", "occOrig"); +if(file_exists($file['tmp_name'])) { + if($view->file_put_contents('/'.$tmpfile, file_get_contents($file['tmp_name']))) { + debug($fn.' uploaded'); + OC_JSON::success(array('data' => array('path'=>'', 'file'=>$tmpfile))); + } else { + bailOut(OC_Contacts_App::$l10n->t('Error uploading contacts to storage.')); + } +} else { + bailOut('Temporary file: \''.$file['tmp_name'].'\' has gone AWOL?'); +} + + ?> diff --git a/apps/contacts/css/contacts.css b/apps/contacts/css/contacts.css index 0bb9f975fc5..e3d2cfbdd66 100644 --- a/apps/contacts/css/contacts.css +++ b/apps/contacts/css/contacts.css @@ -100,4 +100,4 @@ input[type="checkbox"] { width: 20px; height: 20px; vertical-align: bottom; } .propertylist li > input[type="checkbox"],input[type="radio"] { float: left; clear: left; width: 20px; height: 20px; vertical-align: middle; } .propertylist li > select { float: left; max-width: 8em; } .typelist { float: left; max-width: 10em; } /* for multiselect */ -.addresslist { clear: both; }
\ No newline at end of file +.addresslist { clear: both; } diff --git a/apps/contacts/import.php b/apps/contacts/import.php index ca2c1e1605d..8e0a427399b 100644 --- a/apps/contacts/import.php +++ b/apps/contacts/import.php @@ -24,6 +24,11 @@ if(isset($_POST['fstype']) && $_POST['fstype'] == 'OC_FilesystemView') { } else { $file = OC_Filesystem::file_get_contents($_POST['path'] . '/' . $_POST['file']); } +if(!$file) { + OC_JSON::error(array('message' => 'Import file was empty.')); + exit(); +} +error_log('File: '.$file); if(isset($_POST['method']) && $_POST['method'] == 'new'){ $id = OC_Contacts_Addressbook::add(OC_User::getUser(), $_POST['addressbookname']); OC_Contacts_Addressbook::setActive($id, 1); diff --git a/apps/contacts/js/contacts.js b/apps/contacts/js/contacts.js index 18edb40a3cb..7e0fe8b41cf 100644 --- a/apps/contacts/js/contacts.js +++ b/apps/contacts/js/contacts.js @@ -1287,6 +1287,7 @@ Contacts={ }, Addressbooks:{ droptarget:undefined, + droptext:t('contacts', 'Drop a VCF file to import contacts.'), overview:function(){ if($('#chooseaddressbook_dialog').dialog('isOpen') == true){ $('#chooseaddressbook_dialog').dialog('moveToTop'); @@ -1345,8 +1346,16 @@ Contacts={ } }, loadImportHandlers:function() { + $('#import_upload_start').change(function(){ + Contacts.UI.Addressbooks.uploadImport(this.files); + }); + $('#importaddressbook_dialog').find('.upload').click(function() { + Contacts.UI.Addressbooks.droptarget.html(t('contacts', 'Uploading...')); + Contacts.UI.loading(Contacts.UI.Addressbooks.droptarget, true); + $('#import_upload_start').trigger('click'); + }); + $('#importaddressbook_dialog').find('.upload').tipsy(); this.droptarget = $('#import_drop_target'); - console.log($('#import_drop_target').html()); $(this.droptarget).bind('dragover',function(event){ $(event.target).addClass('droppable'); event.stopPropagation(); @@ -1371,13 +1380,13 @@ Contacts={ console.log('size: '+file.size+', type: '+file.type); if(file.size > $('#max_upload').val()){ OC.dialogs.alert(t('contacts','The file you are trying to upload exceed the maximum size for file uploads on this server.'), t('contacts','Upload too large')); - $(Contacts.UI.Addressbooks.droptarget).html(t('contacts', 'Drop a VCF file to import contacts.')); + $(Contacts.UI.Addressbooks.droptarget).html(Contacts.UI.Addressbooks.droptext); Contacts.UI.loading(Contacts.UI.Addressbooks.droptarget, false); return; } if(file.type.indexOf('text') != 0) { OC.dialogs.alert(t('contacts','You have dropped a file type that cannot be imported: ') + file.type, t('contacts','Wrong file type')); - $(Contacts.UI.Addressbooks.droptarget).html(t('contacts', 'Drop a VCF file to import contacts.')); + $(Contacts.UI.Addressbooks.droptarget).html(Contacts.UI.Addressbooks.droptext); Contacts.UI.loading(Contacts.UI.Addressbooks.droptarget, false); return; } @@ -1392,11 +1401,9 @@ Contacts={ response = $.parseJSON(xhr.responseText); if(response.status == 'success') { if(xhr.status == 200) { - $(Contacts.UI.Addressbooks.droptarget).html(t('contacts', 'Importing...')); - Contacts.UI.loading(Contacts.UI.Addressbooks.droptarget, true); Contacts.UI.Addressbooks.doImport(response.data.path, response.data.file); } else { - $(Contacts.UI.Addressbooks.droptarget).html(t('contacts', 'Drop a VCF file to import contacts.')); + $(Contacts.UI.Addressbooks.droptarget).html(Contacts.UI.Addressbooks.droptext); Contacts.UI.loading(Contacts.UI.Addressbooks.droptarget, false); OC.dialogs.alert(xhr.status + ': ' + xhr.responseText, t('contacts', 'Error')); } @@ -1405,7 +1412,7 @@ Contacts={ } } }; - xhr.open("POST", 'ajax/uploadimport.php?file='+encodeURIComponent(file.name), true); + xhr.open('POST', OC.filePath('contacts', 'ajax', 'uploadimport.php') + '?file='+encodeURIComponent(file.name), true); xhr.setRequestHeader('Cache-Control', 'no-cache'); xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); xhr.setRequestHeader('X_FILE_NAME', encodeURIComponent(file.name)); @@ -1414,12 +1421,39 @@ Contacts={ xhr.send(file); } }, + uploadImport:function(filelist) { + if(!filelist) { + OC.dialogs.alert(t('contacts','No files selected for upload.'), t('contacts', 'Error')); + return; + } + //var file = filelist.item(0); + var file = filelist[0]; + var target = $('#import_upload_target'); + var form = $('#import_upload_form'); + var totalSize=0; + if(file.size > $('#max_upload').val()){ + OC.dialogs.alert(t('contacts','The file you are trying to upload exceed the maximum size for file uploads on this server.'), t('contacts', 'Error')); + return; + } else { + target.load(function(){ + var response=jQuery.parseJSON(target.contents().text()); + if(response != undefined && response.status == 'success'){ + Contacts.UI.Addressbooks.doImport(response.data.path, response.data.file); + }else{ + OC.dialogs.alert(response.data.message, t('contacts', 'Error')); + } + }); + form.submit(); + } + }, importAddressbook:function(object){ var tr = $(document.createElement('tr')) .load(OC.filePath('contacts', 'ajax', 'importaddressbook.php')); $(object).closest('tr').after(tr).hide(); }, doImport:function(path, file){ + $(Contacts.UI.Addressbooks.droptarget).html(t('contacts', 'Importing...')); + Contacts.UI.loading(Contacts.UI.Addressbooks.droptarget, true); var id = $('#importaddressbook_dialog').find('#book').val(); console.log('Selected book: ' + id); $.post(OC.filePath('contacts', '', 'import.php'), { id: id, path: path, file: file, fstype: 'OC_FilesystemView' }, @@ -1428,6 +1462,10 @@ Contacts={ Contacts.UI.Addressbooks.droptarget.html(t('contacts', 'Import done. Success/Failure: ')+jsondata.data.imported+'/'+jsondata.data.failed); $('#chooseaddressbook_dialog').find('#close_button').val(t('contacts', 'OK')); Contacts.UI.Contacts.update(); + setTimeout( + function() { + $(Contacts.UI.Addressbooks.droptarget).html(Contacts.UI.Addressbooks.droptext); + }, 5000); } else { OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error')); } @@ -1590,7 +1628,7 @@ $(document).ready(function(){ * Profile picture upload handling */ // New profile picture selected - $('#file_upload_start').live('change',function(){ + $('#file_upload_start').change(function(){ Contacts.UI.Card.uploadPhoto(this.files); }); $('#contacts_details_photo_wrapper').bind('dragover',function(event){ @@ -1662,7 +1700,7 @@ $(document).ready(function(){ }; // Start loading indicator. //$('#contacts_details_photo_progress').show()(); - xhr.open("POST", OC.filePath('contacts', 'ajax', 'uploadphoto.php')+'?id='+Contacts.UI.Card.id+'&imagefile='+encodeURIComponent(file.name), true); + xhr.open('POST', OC.filePath('contacts', 'ajax', 'uploadphoto.php')+'?id='+Contacts.UI.Card.id+'&imagefile='+encodeURIComponent(file.name), true); xhr.setRequestHeader('Cache-Control', 'no-cache'); xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); xhr.setRequestHeader('X_FILE_NAME', encodeURIComponent(file.name)); @@ -1691,4 +1729,4 @@ $(document).ready(function(){ Contacts.UI.Card.addProperty(type); $('#contacts_propertymenu').hide(); }); -});
\ No newline at end of file +}); diff --git a/apps/contacts/templates/part.contact.php b/apps/contacts/templates/part.contact.php index dec081a9b89..64a024c0926 100644 --- a/apps/contacts/templates/part.contact.php +++ b/apps/contacts/templates/part.contact.php @@ -24,7 +24,6 @@ $id = isset($_['id']) ? $_['id'] : ''; <div id="contact_photo" class="contactsection"> <form class="float" id="file_upload_form" action="ajax/uploadphoto.php" method="post" enctype="multipart/form-data" target="file_upload_target"> - <fieldset id="photo"> <div class="tip propertycontainer" id="contacts_details_photo_wrapper" title="<?php echo $l->t('Click or drop to upload picture'); ?> (max <?php echo $_['uploadMaxHumanFilesize']; ?>)" data-element="PHOTO"> <!-- img style="padding: 1em;" id="contacts_details_photo" alt="Profile picture" src="photo.php?id=<?php echo $_['id']; ?>" / --> <progress id="contacts_details_photo_progress" style="display:none;" value="0" max="100">0 %</progress> @@ -34,7 +33,6 @@ $id = isset($_['id']) ? $_['id'] : ''; <input type="hidden" class="max_human_file_size" value="(max <?php echo $_['uploadMaxHumanFilesize']; ?>)"> <input id="file_upload_start" type="file" accept="image/*" name="imagefile" /> <iframe name="file_upload_target" id='file_upload_target' src=""></iframe> - </fieldset> </form> </div> <!-- contact_photo --> diff --git a/apps/files/ajax/scan.php b/apps/files/ajax/scan.php index 488f68e6b3c..a227dcc3ffc 100644 --- a/apps/files/ajax/scan.php +++ b/apps/files/ajax/scan.php @@ -3,6 +3,7 @@ set_time_limit(0);//scanning can take ages $force=isset($_GET['force']) and $_GET['force']=='true'; +$dir=isset($_GET['dir'])?$_GET['dir']:''; $checkOnly=isset($_GET['checkonly']) and $_GET['checkonly']=='true'; if(!$checkOnly){ @@ -14,7 +15,7 @@ if(!$checkOnly){ if($force or !OC_FileCache::inCache('')){ if(!$checkOnly){ OC_DB::beginTransaction(); - OC_FileCache::scan('',$eventSource); + OC_FileCache::scan($dir,$eventSource); OC_FileCache::clean(); OC_DB::commit(); $eventSource->send('success',true); diff --git a/apps/files/css/files.css b/apps/files/css/files.css index 99623b6355e..a135f7ded5b 100644 --- a/apps/files/css/files.css +++ b/apps/files/css/files.css @@ -30,6 +30,8 @@ .file_upload_filename { position: relative; z-index:100; padding-left: 0.8em; padding-right: 0.8em; cursor:pointer; border-top-left-radius:0; border-bottom-left-radius:0; } .file_upload_filename img { position: absolute; top: 0.4em; left: 0.4em; -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; filter:alpha(opacity=100); opacity:1; } +#upload { position:absolute; right:13.5em; top:0em; } +#upload #uploadprogressbar { position:relative; display:inline-block; width:10em; height:1.5em; top:.4em; } .file_upload_form, .file_upload_wrapper, .file_upload_start, .file_upload_filename, #file_upload_submit { cursor:pointer; } @@ -41,7 +43,7 @@ tbody tr { background-color:#fff; height:2.5em; } tbody tr:hover, tbody tr:active, tbody tr.selected { background-color:#f8f8f8; } tbody tr.selected { background-color:#eee; } tbody a { color:#000; } -span.extension, td.date { color:#999; } +span.extension, span.uploading, td.date { color:#999; } span.extension { text-transform:lowercase; -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=70)"; filter:alpha(opacity=70); opacity:.7; -webkit-transition:opacity 300ms; -moz-transition:opacity 300ms; -o-transition:opacity 300ms; transition:opacity 300ms; } tr:hover span.extension { -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; filter:alpha(opacity=100); opacity:1; color:#777; } div.crumb { float:left; display:block; background:no-repeat right 0; padding:.75em 1.5em 0 1em; height:2.9em; } @@ -60,8 +62,10 @@ table td.filename a.name { display:block; height:1.5em; vertical-align:middle; m table tr[data-type="dir"] td.filename a.name span.nametext {font-weight:bold; } table td.filename a.name input, table td.filename a.name form { width:100%; cursor:text; } table td.filename a, table td.login, table td.logout, table td.download, table td.upload, table td.create, table td.delete { padding:.2em .5em .5em 0; } -table td.filename .nametext, .modified { float:left; padding:.3em 0; } +table td.filename .nametext, .uploadtext, .modified { float:left; padding:.3em 0; } +// TODO fix usability bug (accidental file/folder selection) table td.filename .nametext { width:70%; overflow:hidden; } +table td.filename .uploadtext { font-weight:normal; margin-left:.5em; } table td.filename form { float:left; font-size:.85em; } table thead.fixed tr{ position:fixed; top:6.5em; z-index:49; -moz-box-shadow:0 -3px 7px #ddd; -webkit-box-shadow:0 -3px 7px #ddd; box-shadow:0 -3px 7px #ddd; } table thead.fixed { height:2em; } diff --git a/apps/files/index.php b/apps/files/index.php index 46b511d66eb..8464db30f01 100644 --- a/apps/files/index.php +++ b/apps/files/index.php @@ -26,6 +26,8 @@ OC_Util::checkLoggedIn(); // Load the files we need OC_Util::addStyle( "files", "files" ); +OC_Util::addScript( "files", "jquery.iframe-transport" ); +OC_Util::addScript( "files", "jquery.fileupload" ); OC_Util::addScript( "files", "files" ); OC_Util::addScript( 'files', 'filelist' ); OC_Util::addScript( 'files', 'fileactions' ); diff --git a/apps/files/js/fileactions.js b/apps/files/js/fileactions.js index 481802e0d63..68268a7d3a9 100644 --- a/apps/files/js/fileactions.js +++ b/apps/files/js/fileactions.js @@ -140,7 +140,20 @@ $(document).ready(function(){ }); FileActions.register('all','Delete',function(){return OC.imagePath('core','actions/delete')},function(filename){ - FileList.do_delete(filename); + if(Files.cancelUpload(filename)) { + if(filename.substr){ + filename=[filename]; + } + $.each(filename,function(index,file){ + var filename = $('tr').filterAttr('data-file',file); + filename.hide(); + filename.find('input[type="checkbox"]').removeAttr('checked'); + filename.removeClass('selected'); + }); + procesSelection(); + }else{ + FileList.do_delete(filename); + } }); FileActions.register('all','Rename',function(){return OC.imagePath('core','actions/rename')},function(filename){ diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index 5bd85fc29ef..febdfc473b1 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -43,6 +43,7 @@ FileList={ td.append('<input type="checkbox" />'); var link_elem = $('<a></a>').attr({ "class": "name", "href": "index.php?dir="+ encodeURIComponent($('#dir').val()+'/'+name).replace(/%2F/g, '/') }); link_elem.append($('<span></span>').addClass('nametext').text(name)); + link_elem.append($('<span></span>').attr({'class': 'uploadtext', 'currentUploads': 0})); td.append(link_elem); html.append(td); if(size!='Pending'){ diff --git a/apps/files/js/files.js b/apps/files/js/files.js index 9d83e5e6d26..2dce00035e1 100644 --- a/apps/files/js/files.js +++ b/apps/files/js/files.js @@ -1,3 +1,32 @@ +var uploadingFiles = {}; +Files={ + cancelUpload:function(filename) { + if(uploadingFiles[filename]) { + uploadingFiles[filename].abort(); + delete uploadingFiles[filename]; + return true; + } + return false; + }, + cancelUploads:function() { + $.each(uploadingFiles,function(index,file) { + if(typeof file['abort'] === 'function') { + file.abort(); + var filename = $('tr').filterAttr('data-file',index); + filename.hide(); + filename.find('input[type="checkbox"]').removeAttr('checked'); + filename.removeClass('selected'); + } else { + $.each(file,function(i,f) { + f.abort(); + delete file[i]; + }); + } + delete uploadingFiles[index]; + }); + procesSelection(); + } +} $(document).ready(function() { $('#fileList tr').each(function(){ //little hack to set unescape filenames in attribute @@ -151,83 +180,205 @@ $(document).ready(function() { return false; }); - $('.file_upload_start').live('change',function(){ - var form=$(this).closest('form'); - var that=this; - var uploadId=form.attr('data-upload-id'); - var files=this.files; - var target=form.children('iframe'); - var totalSize=0; - if(files){ - for(var i=0;i<files.length;i++){ - totalSize+=files[i].size; - if(FileList.deleteFiles && FileList.deleteFiles.indexOf(files[i].name)!=-1){//finish delete if we are uploading a deleted file - FileList.finishDelete(function(){ - $(that).change(); - }); - return; - } - } - } - if(totalSize>$('#max_upload').val()){ - $( "#uploadsize-message" ).dialog({ - modal: true, - buttons: { - Close: function() { - $( this ).dialog( "close" ); + // drag&drop support using jquery.fileupload + // TODO use OC.dialogs + $(document).bind('drop dragover', function (e) { + e.preventDefault(); // prevent browser from doing anything, if file isn't dropped in dropZone + }); + + $(function() { + $('.file_upload_start').fileupload({ + dropZone: $('#content'), // restrict dropZone to content div + add: function(e, data) { + var files = data.files; + var totalSize=0; + if(files){ + for(var i=0;i<files.length;i++){ + totalSize+=files[i].size; + if(FileList.deleteFiles && FileList.deleteFiles.indexOf(files[i].name)!=-1){//finish delete if we are uploading a deleted file + FileList.finishDelete(function(){ + $('.file_upload_start').change(); + }); + return; + } } } - }); - }else{ - target.load(function(){ - var response=jQuery.parseJSON(target.contents().find('body').text()); - //set mimetype and if needed filesize - if(response){ - if(response[0] != undefined && response[0].status == 'success'){ - for(var i=0;i<response.length;i++){ - var file=response[i]; + if(totalSize>$('#max_upload').val()){ + $( '#uploadsize-message' ).dialog({ + modal: true, + buttons: { + Close: function() { + $( this ).dialog( 'close' ); + } + } + }); + }else{ + if($.support.xhrFileUpload) { + for(var i=0;i<files.length;i++){ + var fileName = files[i].name + var dropTarget = $(e.originalEvent.target).closest('tr'); + if(dropTarget && dropTarget.attr('data-type') === 'dir') { // drag&drop upload to folder + var dirName = dropTarget.attr('data-file') + var jqXHR = $('.file_upload_start').fileupload('send', {files: files[i], + formData: function(form) { + var formArray = form.serializeArray(); + formArray[1]['value'] = dirName; + return formArray; + }}).success(function(result, textStatus, jqXHR) { + var response; + response=jQuery.parseJSON(result); + if(response[0] == undefined || response[0].status != 'success') { + $('#notification').text(t('files', response.data.message)); + $('#notification').fadeIn(); + } + var file=response[0]; + delete uploadingFiles[dirName][file.name]; + var currentUploads = parseInt(uploadtext.attr('currentUploads')); + currentUploads -= 1; + uploadtext.attr('currentUploads', currentUploads); + if(currentUploads === 0) { + var img = OC.imagePath('core', 'filetypes/folder.png'); + var tr=$('tr').filterAttr('data-file',dirName); + tr.find('td.filename').attr('style','background-image:url('+img+')'); + uploadtext.text(''); + uploadtext.hide(); + } else { + uploadtext.text(currentUploads + ' files uploading') + } + }) + .error(function(jqXHR, textStatus, errorThrown) { + if(errorThrown === 'abort') { + var currentUploads = parseInt(uploadtext.attr('currentUploads')); + currentUploads -= 1; + uploadtext.attr('currentUploads', currentUploads); + if(currentUploads === 0) { + var img = OC.imagePath('core', 'filetypes/folder.png'); + var tr=$('tr').filterAttr('data-file',dirName); + tr.find('td.filename').attr('style','background-image:url('+img+')'); + uploadtext.text(''); + uploadtext.hide(); + } else { + uploadtext.text(currentUploads + ' files uploading') + } + $('#notification').hide(); + $('#notification').text(t('files', 'Upload cancelled.')); + $('#notification').fadeIn(); + } + }); + //TODO test with filenames containing slashes + if(uploadingFiles[dirName] === undefined) { + uploadingFiles[dirName] = {}; + } + uploadingFiles[dirName][fileName] = jqXHR; + } else { + var jqXHR = $('.file_upload_start').fileupload('send', {files: files[i]}) + .success(function(result, textStatus, jqXHR) { + var response; + response=jQuery.parseJSON(result); + if(response[0] != undefined && response[0].status == 'success') { + var file=response[0]; + delete uploadingFiles[file.name]; + $('tr').filterAttr('data-file',file.name).data('mime',file.mime); + var size = $('tr').filterAttr('data-file',file.name).find('td.filesize').text(); + if(size==t('files','Pending')){ + $('tr').filterAttr('data-file',file.name).find('td.filesize').text(file.size); + } + FileList.loadingDone(file.name); + } else { + $('#notification').text(t('files', response.data.message)); + $('#notification').fadeIn(); + $('#fileList > tr').not('[data-mime]').fadeOut(); + $('#fileList > tr').not('[data-mime]').remove(); + } + }) + .error(function(jqXHR, textStatus, errorThrown) { + if(errorThrown === 'abort') { + $('#notification').hide(); + $('#notification').text(t('files', 'Upload cancelled.')); + $('#notification').fadeIn(); + } + }); + uploadingFiles[files[i].name] = jqXHR; + } + } + }else{ + data.submit().success(function(data, status) { + response = jQuery.parseJSON(data[0].body.innerText); + if(response[0] != undefined && response[0].status == 'success') { + var file=response[0]; + delete uploadingFiles[file.name]; $('tr').filterAttr('data-file',file.name).data('mime',file.mime); - if(size=='Pending'){ + var size = $('tr').filterAttr('data-file',file.name).find('td.filesize').text(); + if(size==t('files','Pending')){ $('tr').filterAttr('data-file',file.name).find('td.filesize').text(file.size); } FileList.loadingDone(file.name); + } else { + $('#notification').text(t('files', response.data.message)); + $('#notification').fadeIn(); + $('#fileList > tr').not('[data-mime]').fadeOut(); + $('#fileList > tr').not('[data-mime]').remove(); } - } - else{ - $('#notification').text(t('files',response.data.message)); - $('#notification').fadeIn(); - $('#fileList > tr').not('[data-mime]').fadeOut(); - $('#fileList > tr').not('[data-mime]').remove(); - } + }); } - }); - form.submit(); - var date=new Date(); - if(files){ - for(var i=0;i<files.length;i++){ - if(files[i].size>0){ - var size=files[i].size; - }else{ - var size=t('files','Pending'); - } + + var date=new Date(); if(files){ + for(var i=0;i<files.length;i++){ + if(files[i].size>0){ + var size=files[i].size; + }else{ + var size=t('files','Pending'); + } + if(files && !dirName){ FileList.addFile(getUniqueName(files[i].name),size,date,true); + } else if(dirName) { + var uploadtext = $('tr').filterAttr('data-type', 'dir').filterAttr('data-file', dirName).find('.uploadtext') + var currentUploads = parseInt(uploadtext.attr('currentUploads')); + currentUploads += 1; + uploadtext.attr('currentUploads', currentUploads); + if(currentUploads === 1) { + var img = OC.imagePath('core', 'loading.gif'); + var tr=$('tr').filterAttr('data-file',dirName); + tr.find('td.filename').attr('style','background-image:url('+img+')'); + uploadtext.text('1 file uploading'); + uploadtext.show(); + } else { + uploadtext.text(currentUploads + ' files uploading') + } + } + } + }else{ + var filename=this.value.split('\\').pop(); //ie prepends C:\fakepath\ in front of the filename + FileList.addFile(getUniqueName(filename),'Pending',date,true); } } - }else{ - var filename=this.value.split('\\').pop(); //ie prepends C:\fakepath\ in front of the filename - FileList.addFile(getUniqueName(filename),'Pending',date,true); + }, + fail: function(e, data) { + // TODO: cancel upload & display error notification + }, + progress: function(e, data) { + // TODO: show nice progress bar in file row + }, + progressall: function(e, data) { + var progress = (data.loaded/data.total)*100; + $('#uploadprogressbar').progressbar('value',progress); + }, + start: function(e, data) { + $('#uploadprogressbar').progressbar({value:0}); + $('#uploadprogressbar').fadeIn(); + if(data.dataType != 'iframe ') { + $('#upload input.stop').show(); + } + }, + stop: function(e, data) { + if(data.dataType != 'iframe ') { + $('#upload input.stop').hide(); + } + $('#uploadprogressbar').progressbar('value',100); + $('#uploadprogressbar').fadeOut(); } - - //clone the upload form and hide the new one to allow users to start a new upload while the old one is still uploading - var clone=form.clone(); - uploadId++; - clone.attr('data-upload-id',uploadId); - clone.attr('target','file_upload_target_'+uploadId); - clone.children('iframe').attr('name','file_upload_target_'+uploadId) - clone.insertBefore(form); - form.hide(); - } + }) }); //add multiply file upload attribute to all browsers except konqueror (which crashes when it's used) @@ -370,12 +521,15 @@ $(document).ready(function() { }, "json"); }); -function scanFiles(force){ +function scanFiles(force,dir){ + if(!dir){ + dir=''; + } force=!!force; //cast to bool scanFiles.scanning=true; $('#scanning-message').show(); $('#fileList').remove(); - var scannerEventSource=new OC.EventSource(OC.filePath('files','ajax','scan.php'),{force:force}); + var scannerEventSource=new OC.EventSource(OC.filePath('files','ajax','scan.php'),{force:force,dir:dir}); scanFiles.cancel=scannerEventSource.close.bind(scannerEventSource); scannerEventSource.listen('scanning',function(data){ $('#scan-count').text(data.count+' files scanned'); diff --git a/apps/files/templates/index.php b/apps/files/templates/index.php index 3571950467e..fc385e1ed3a 100644 --- a/apps/files/templates/index.php +++ b/apps/files/templates/index.php @@ -22,6 +22,11 @@ <iframe name="file_upload_target_1" class='file_upload_target' src=""></iframe> </form> </div> + <div id="upload"> + <div id="uploadprogressbar"></div> + <input type="button" class="stop" style="display:none" value="<?php echo $l->t('Cancel upload');?>" onclick="javascript:Files.cancelUploads();" /> + </div> + </div> <div id="file_action_panel"></div> <?php else:?> diff --git a/apps/files/templates/part.list.php b/apps/files/templates/part.list.php index 5a5941fc7ae..b2db4cbb8df 100644 --- a/apps/files/templates/part.list.php +++ b/apps/files/templates/part.list.php @@ -21,6 +21,10 @@ <?php echo htmlspecialchars($file['basename']);?><span class='extension'><?php echo $file['extension'];?></span> <?php endif;?> </span> + <?php if($file['type'] == 'dir'):?> + <span class="uploadtext" currentUploads="0"> + </span> + <?php endif;?> </a> </td> <td class="filesize" title="<?php echo human_file_size($file['size']); ?>" style="color:rgb(<?php echo $simple_size_color.','.$simple_size_color.','.$simple_size_color ?>)"><?php echo $simple_file_size; ?></td> diff --git a/apps/files_encryption/lib/cryptstream.php b/apps/files_encryption/lib/cryptstream.php index 21fa38e4b59..07a2e523a42 100644 --- a/apps/files_encryption/lib/cryptstream.php +++ b/apps/files_encryption/lib/cryptstream.php @@ -33,6 +33,7 @@ class OC_CryptStream{ private $path; private $readBuffer;//for streams that dont support seeking private $meta=array();//header/meta for source stream + private $count; public function stream_open($path, $mode, $options, &$opened_path){ $path=str_replace('crypt://','',$path); @@ -92,16 +93,6 @@ class OC_CryptStream{ $data=substr($block,0,$currentPos%8192).$data; } while(strlen($data)>0){ - if(strlen($data)<8192){ - //fetch the current data in that block and append it to the input so we always write entire blocks - $oldPos=ftell($this->source); - $encryptedBlock=fread($this->source,8192); - fseek($this->source,$oldPos); - if($encryptedBlock){ - $block=OC_Crypt::decrypt($encryptedBlock); - $data.=substr($block,strlen($data)); - } - } $encrypted=OC_Crypt::encrypt(substr($data,0,8192)); fwrite($this->source,$encrypted); $data=substr($data,8192); @@ -139,7 +130,9 @@ class OC_CryptStream{ } public function stream_close(){ - OC_FileCache::put($this->path,array('encrypted'=>true)); + if($this->meta['mode']!='r' and $this->meta['mode']!='rb'){ + OC_FileCache::put($this->path,array('encrypted'=>true)); + } return fclose($this->source); } }
\ No newline at end of file diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index e3a106d0d04..d65bcba8bfa 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -27,7 +27,6 @@ class OC_FileProxy_Encryption extends OC_FileProxy{ private static $blackList=null; //mimetypes blacklisted from encryption - private static $metaData=array(); //metadata cache private static $enableEncryption=null; /** @@ -60,13 +59,8 @@ class OC_FileProxy_Encryption extends OC_FileProxy{ * @return bool */ private static function isEncrypted($path){ - if(isset(self::$metaData[$path])){ - $metadata=self::$metaData[$path]; - }else{ - $metadata=OC_FileCache::getCached($path); - self::$metaData[$path]=$metadata; - } - return (bool)$metadata['encrypted']; + $metadata=OC_FileCache::getCached($path); + return isset($metadata['encrypted']) and (bool)$metadata['encrypted']; } public function preFile_put_contents($path,&$data){ @@ -98,12 +92,7 @@ class OC_FileProxy_Encryption extends OC_FileProxy{ //first encrypt the target file so we don't end up with a half encrypted file OC_Log::write('files_encryption','Decrypting '.$path.' before writing',OC_Log::DEBUG); $tmp=fopen('php://temp'); - while(!feof($result)){ - $chunk=fread($result,8192); - if($chunk){ - fwrite($tmp,$chunk); - } - } + OC_Helper::streamCopy($result,$tmp); fclose($result); OC_Filesystem::file_put_contents($path,$tmp); fclose($tmp); diff --git a/apps/files_external/lib/swift.php b/apps/files_external/lib/swift.php index e53eb1ff3b6..a987d17d799 100644 --- a/apps/files_external/lib/swift.php +++ b/apps/files_external/lib/swift.php @@ -28,6 +28,8 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{ private $rootContainer; private static $tempFiles=array(); + private $objects=array(); + private $containers=array(); const SUBCONTAINER_FILE='.subcontainers'; @@ -38,7 +40,7 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{ */ private function getContainerName($path){ $path=trim($this->root.$path,'/'); - return md5($path); + return str_replace('/','\\',$path); } /** @@ -50,8 +52,12 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{ if($path=='' or $path=='/'){ return $this->rootContainer; } + if(isset($this->containers[$path])){ + return $this->containers[$path]; + } try{ $container=$this->conn->get_container($this->getContainerName($path)); + $this->containers[$path]=$container; return $container; }catch(NoSuchContainerException $e){ return null; @@ -87,12 +93,16 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{ * @return CF_Object */ private function getObject($path){ + if(isset($this->objects[$path])){ + return $this->objects[$path]; + } $container=$this->getContainer(dirname($path)); if(is_null($container)){ return null; }else{ try{ $obj=$container->get_object(basename($path)); + $this->objects[$path]=$obj; return $obj; }catch(NoSuchObjectException $e){ return null; @@ -295,6 +305,7 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{ } $this->conn->delete_container($this->getContainerName($path)); + unset($this->containers[$path]); return true; } } @@ -309,12 +320,14 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{ if($sub){ $this->emptyContainer($path.'/'.$sub); $this->conn->delete_container($this->getContainerName($path.'/'.$sub)); + unset($this->containers[$path.'/'.$sub]); } } $objects=$this->getObjects($container); foreach($objects as $object){ $container->delete_object($object); + unset($this->objects[$path.'/'.$object]); } } @@ -381,6 +394,7 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{ if($this->objectExists($path)){ $container=$this->getContainer(dirname($path)); $container->delete_object(basename($path)); + unset($this->objects[$path]); }else{ return false; } @@ -447,6 +461,7 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{ $sourceContainer=$this->getContainer(dirname($path1)); $targetContainer=$this->getContainer(dirname($path2)); $result=$sourceContainer->move_object_to(basename($path1),$targetContainer,basename($path2)); + unset($this->objects[$path1]); if($result){ $targetObj=$this->getObject($path2); $this->resetMTime($targetObj); diff --git a/apps/files_sharing/ajax/email.php b/apps/files_sharing/ajax/email.php new file mode 100644 index 00000000000..d6d53c49bff --- /dev/null +++ b/apps/files_sharing/ajax/email.php @@ -0,0 +1,15 @@ +<?php + +require_once('../../../lib/base.php'); + +OC_JSON::checkLoggedIn(); +OC_JSON::checkAppEnabled('files_sharing'); +$user = OC_User::getUser(); +// TODO translations +$subject = $user + ' ' + 'shared a file with you'; +$link = $_POST['link'] + '&f=' + $_POST['f']; +$text = $user + ' ' + 'shared the file' + ' ' + $_POST['f'] + ' ' + 'with you.' + ' ' + 'It is available for download here:' + ' ' + $link; +$fromaddress = OC_Preferences::getValue($user, 'settings', 'email', 'owncloud.org'); +OC_Mail::send($_POST['toaddress'], $_POST['toaddress'], $subject, $text, $fromaddress, $user); + +?>
\ No newline at end of file diff --git a/apps/files_sharing/ajax/toggleresharing.php b/apps/files_sharing/ajax/toggleresharing.php new file mode 100644 index 00000000000..72af1eedec1 --- /dev/null +++ b/apps/files_sharing/ajax/toggleresharing.php @@ -0,0 +1,13 @@ +<?php + +require_once('../../../lib/base.php'); + +OC_JSON::checkAppEnabled('files_sharing'); +OC_JSON::checkAdminUser(); +if ($_POST['resharing'] == true) { + OC_Appconfig::setValue('files_sharing', 'resharing', 'yes'); +} else { + OC_Appconfig::setValue('files_sharing', 'resharing', 'no'); +} + +?> diff --git a/apps/files_sharing/appinfo/app.php b/apps/files_sharing/appinfo/app.php index 8049e9b0ae3..645f4f5e4f2 100644 --- a/apps/files_sharing/appinfo/app.php +++ b/apps/files_sharing/appinfo/app.php @@ -3,10 +3,17 @@ require_once('apps/files_sharing/sharedstorage.php'); OC::$CLASSPATH['OC_Share'] = "apps/files_sharing/lib_share.php"; +OC_APP::registerAdmin('files_sharing', 'settings'); OC_Hook::connect("OC_Filesystem", "post_delete", "OC_Share", "deleteItem"); OC_Hook::connect("OC_Filesystem", "post_rename", "OC_Share", "renameItem"); OC_Hook::connect("OC_Filesystem", "post_write", "OC_Share", "updateItem"); -OC_Util::addScript("files_sharing", "share"); +OC_Hook::connect('OC_User', 'post_deleteUser', 'OC_Share', 'removeUser'); +OC_Hook::connect('OC_User', 'post_addToGroup', 'OC_Share', 'addToGroupShare'); +OC_Hook::connect('OC_User', 'post_removeFromGroup', 'OC_Share', 'removeFromGroupShare'); +$dir = isset($_GET['dir']) ? $_GET['dir'] : '/'; +if ($dir != '/Shared' || OC_Appconfig::getValue('files_sharing', 'resharing', 'yes') == 'yes') { + OC_Util::addScript("files_sharing", "share"); +} OC_Util::addScript("3rdparty", "chosen/chosen.jquery.min"); OC_Util::addStyle( 'files_sharing', 'sharing' ); OC_Util::addStyle("3rdparty", "chosen/chosen"); diff --git a/apps/files_sharing/js/settings.js b/apps/files_sharing/js/settings.js new file mode 100644 index 00000000000..bb7d79fecbb --- /dev/null +++ b/apps/files_sharing/js/settings.js @@ -0,0 +1,9 @@ +$(document).ready(function() { + $('#allowResharing').bind('change', function() { + var checked = 1; + if (!this.checked) { + checked = 0; + } + $.post(OC.filePath('files_sharing','ajax','toggleresharing.php'), 'resharing='+checked); + }); +});
\ No newline at end of file diff --git a/apps/files_sharing/js/share.js b/apps/files_sharing/js/share.js index 54d749d833e..4125fd14d25 100644 --- a/apps/files_sharing/js/share.js +++ b/apps/files_sharing/js/share.js @@ -163,6 +163,9 @@ $(document).ready(function() { data: data, success: function(){ $('#link').hide('blind'); + $('#emailBreak').remove(); + $('#email').hide('blind'); + $('#emailButton').hide('blind'); } }); } @@ -172,6 +175,14 @@ $(document).ready(function() { $(this).focus(); $(this).select(); }); + + $('#emailButton').live('click', function() { + $('#email').css('font-weight', 'bold'); + $('#email').animate({ fontWeight: 'normal' }, 2000, function() { + $(this).val(''); + }).val('Email sent'); + $.post(OC.filePath('files_sharing','ajax','email.php'), 'toaddress='+$('#email').val()+'&link='+$('#link').val()); + }); }); function createDropdown(filename, files) { @@ -183,10 +194,12 @@ function createDropdown(filename, files) { html += '<ul id="shared_list"></ul>'; html += '</div>'; html += '<div id="public">'; - html += '<input type="checkbox" name="makelink" id="makelink" value="1" /><label for="makelink">make public</label>'; + html += '<input type="checkbox" name="makelink" id="makelink" value="1" /><label for="makelink">Share with private link</label>'; //html += '<input type="checkbox" name="public_link_write" id="public_link_write" value="1" /><label for="public_link_write">allow upload</label>'; html += '<br />'; html += '<input id="link" style="display:none; width:90%;" />'; + html += '<input id="email" style="display:none; width:65%;" value="" placeholder="Email link to person" />'; + html += '<input id="emailButton" style="display:none;" type="submit" value="Send" />'; html += '</div>'; if (filename) { $('tr').filterAttr('data-file',filename).addClass('mouseOver'); @@ -241,5 +254,9 @@ function showPublicLink(token, file) { $('#makelink').attr('checked', true); $('#link').data('token', token); $('#link').val(parent.location.protocol+'//'+location.host+OC.linkTo('files_sharing','get.php')+'?token='+token+'&f='+file); - $('#link').show('blind'); + $('#link').show('blind', function() { + $('#link').after('<br id="emailBreak" />'); + $('#email').show('blind'); + $('#emailButton').show('blind'); + }); } diff --git a/apps/files_sharing/lib_share.php b/apps/files_sharing/lib_share.php index 673984f393b..62ac05a5952 100644 --- a/apps/files_sharing/lib_share.php +++ b/apps/files_sharing/lib_share.php @@ -436,6 +436,34 @@ class OC_Share { } } + public static function removeUser($arguments) { + $query = OC_DB::prepare('DELETE FROM *PREFIX*sharing WHERE uid_owner = ? OR uid_shared_with '.self::getUsersAndGroups($arguments['uid'])); + $query->execute(array($arguments['uid'])); + } + + public static function addToGroupShare($arguments) { + $length = -strlen($arguments['gid']) - 1; + $query = OC_DB::prepare('SELECT uid_owner, source, permissions FROM *PREFIX*sharing WHERE SUBSTR(uid_shared_with, '.$length.') = ?'); + $gid = '@'.$arguments['gid']; + $result = $query->execute(array($gid))->fetchAll(); + if (count($result) > 0) { + $query = OC_DB::prepare('INSERT INTO *PREFIX*sharing VALUES(?,?,?,?,?)'); + $sharedFolder = '/'.$arguments['uid'].'/files/Shared/'; + $lastSource = ''; + for ($i = 0; $i < count($result) - 1; $i++) { + if ($result[$i]['source'] != $lastSource) { + $query->execute(array($result[$i]['uid_owner'], $arguments['uid'].'@'.$arguments['gid'], $result[$i]['source'], $sharedFolder.basename($result[$i]['source']), $result[$i]['permissions'])); + $lastSource = $result[$i]['source']; + } + } + } + } + + public static function removeFromGroupShare($arguments) { + $query = OC_DB::prepare('DELETE FROM *PREFIX*sharing WHERE uid_shared_with = ?'); + $query->execute(array($arguments['uid'].'@'.$arguments['gid'])); + } + } ?> diff --git a/apps/files_sharing/settings.php b/apps/files_sharing/settings.php new file mode 100644 index 00000000000..b30c4f45cde --- /dev/null +++ b/apps/files_sharing/settings.php @@ -0,0 +1,9 @@ +<?php + +OC_Util::checkAdminUser(); +OC_Util::addScript('files_sharing', 'settings'); +$tmpl = new OC_Template('files_sharing', 'settings'); +$tmpl->assign('allowResharing', OC_Appconfig::getValue('files_sharing', 'resharing', 'yes')); +return $tmpl->fetchPage(); + +?>
\ No newline at end of file diff --git a/apps/files_sharing/templates/settings.php b/apps/files_sharing/templates/settings.php new file mode 100644 index 00000000000..5b6ba5f33ee --- /dev/null +++ b/apps/files_sharing/templates/settings.php @@ -0,0 +1,6 @@ +<form id="resharing"> + <fieldset class="personalblock"> + <input type="checkbox" name="allowResharing" id="allowResharing" value="1" <?php if ($_['allowResharing'] == 'yes') echo ' checked="checked"'; ?> /> <label for="allowResharing"><?php echo $l->t('Enable Resharing'); ?></label> <br/> + <em><?php echo $l->t('Allow users to reshare files they don\'t own');?></em> + </fieldset> +</form>
\ No newline at end of file diff --git a/apps/files_versions/appinfo/app.php b/apps/files_versions/appinfo/app.php index 6e7a803252e..32e4c0ce81b 100644 --- a/apps/files_versions/appinfo/app.php +++ b/apps/files_versions/appinfo/app.php @@ -9,6 +9,7 @@ OC_App::register( array( 'name' => 'Versioning' )); OC_APP::registerAdmin('files_versions', 'settings'); +OC_UTIL::addScript('files_versions', 'versions'); // Listen to write signals OC_Hook::connect(OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_write, "OCA_Versions\Storage", "write_hook"); diff --git a/apps/files_versions/css/versions.css b/apps/files_versions/css/versions.css index 139597f9cb0..b2279e9b05a 100644 --- a/apps/files_versions/css/versions.css +++ b/apps/files_versions/css/versions.css @@ -1,2 +1,3 @@ - - +#history { + margin: 2em 2em 0; +}
\ No newline at end of file diff --git a/apps/files_versions/history.php b/apps/files_versions/history.php index 6c7626ca4ed..b0aa8fdc982 100644 --- a/apps/files_versions/history.php +++ b/apps/files_versions/history.php @@ -20,40 +20,41 @@ * License along with this library. If not, see <http://www.gnu.org/licenses/>. * */ -require_once('../../lib/base.php'); +require_once( '../../lib/base.php' ); -OC_Util::checkLoggedIn(); +OC_Util::checkLoggedIn( ); +OC_Util::addStyle('files_versions','versions'); -if (isset($_GET['path'])) { +if ( isset( $_GET['path'] ) ) { $path = $_GET['path']; - $path = strip_tags($path); + $path = strip_tags( $path); // roll back to old version if button clicked - if(isset($_GET['revert'])) { - \OCA_Versions\Storage::rollback($path,$_GET['revert']); + if( isset( $_GET['revert'] ) ) { + \OCA_Versions\Storage::rollback( $path, $_GET['revert'] ); } // show the history only if there is something to show - if(OCA_Versions\Storage::isversioned($path)) { + if( OCA_Versions\Storage::isversioned( $path ) ) { $count=5; //show the newest revisions - $versions=OCA_Versions\Storage::getversions($path,$count); + $versions=OCA_Versions\Storage::getversions( $path, $count); - $tmpl = new OC_Template('files_versions', 'history', 'user'); - $tmpl->assign('path', $path); - $tmpl->assign('versions', array_reverse($versions)); - $tmpl->printPage(); + $tmpl = new OC_Template( 'files_versions', 'history', 'user' ); + $tmpl->assign( 'path', $path); + $tmpl->assign( 'versions', array_reverse( $versions) ); + $tmpl->printPage( ); }else{ - $tmpl = new OC_Template('files_versions', 'history', 'user'); - $tmpl->assign('path', $path); - $tmpl->assign('message', 'No old versions available'); - $tmpl->printPage(); + $tmpl = new OC_Template( 'files_versions', 'history', 'user' ); + $tmpl->assign( 'path', $path); + $tmpl->assign( 'message', 'No old versions available' ); + $tmpl->printPage( ); } }else{ - $tmpl = new OC_Template('files_versions', 'history', 'user'); - $tmpl->assign('message', 'No path specified'); - $tmpl->printPage(); + $tmpl = new OC_Template( 'files_versions', 'history', 'user' ); + $tmpl->assign( 'message', 'No path specified' ); + $tmpl->printPage( ); } diff --git a/apps/files_versions/js/versions.js b/apps/files_versions/js/versions.js index 139597f9cb0..325ef823a9c 100644 --- a/apps/files_versions/js/versions.js +++ b/apps/files_versions/js/versions.js @@ -1,2 +1,67 @@ +$(document).ready(function(){ + + // Add history button to files/index.php + FileActions.register('file','History',function(){return OC.imagePath('core','actions/history')},function(filename){ + + if (scanFiles.scanning){return;}//workaround to prevent additional http request block scanning feedback + + var file = $('#dir').val()+'/'+filename; + + createVersionsDropdown(filename, file) + //window.location='../apps/files_versions/history.php?path='+encodeURIComponent($('#dir').val()).replace(/%2F/g, '/')+'/'+encodeURIComponent(filename); + + }); + +}); + +function createVersionsDropdown(filename, files) { + var historyUrl = '../apps/files_versions/history.php?path='+encodeURIComponent($('#dir').val()).replace(/%2F/g, '/')+'/'+encodeURIComponent(filename); + //alert( historyUrl ); + var html = '<div id="dropdown" class="drop" data-file="'+files+'">'; + html += '<div id="private">'; + html += '<select data-placeholder="File Version" id="share_with" class="chzen-select">'; + html += '<option value=""></option>'; + html += '</select>'; + html += '<ul id="shared_list"></ul>'; + html += '</div>'; + html += '<div id="public">'; + html += '<input type="button" name="makelink" id="makelink" value="Revert file" />'; + html += '<input type="button" onclick="window.location=\''+historyUrl+'\'" name="makelink" id="makelink" value="More..." />'; + html += '<br />'; + html += '<input id="link" style="display:none; width:90%;" />'; + html += '</div>'; + + if (filename) { + $('tr').filterAttr('data-file',filename).addClass('mouseOver'); + $(html).appendTo($('tr').filterAttr('data-file',filename).find('td.filename')); + } else { + $(html).appendTo($('thead .share')); + } +// $.getJSON(OC.linkTo('files_sharing', 'ajax/userautocomplete.php'), function(users) { +// if (users) { +// $.each(users, function(index, row) { +// $(row).appendTo('#share_with'); +// }); +// $('#share_with').trigger('liszt:updated'); +// } +// }); +// $.getJSON(OC.linkTo('files_sharing', 'ajax/getitem.php'), { source: files }, function(users) { +// if (users) { +// $.each(users, function(index, row) { +// if (row.uid_shared_with == 'public') { +// showPublicLink(row.token, '/'+filename); +// } else if (isNaN(index)) { +// addUser(row.uid_shared_with, row.permissions, index.substr(0, index.lastIndexOf('-'))); +// } else { +// addUser(row.uid_shared_with, row.permissions, false); +// } +// }); +// } +// }); + + $('#dropdown').show('blind'); + $('#share_with').chosen(); + +}
\ No newline at end of file diff --git a/apps/files_versions/templates/history.php b/apps/files_versions/templates/history.php index 1b3de9ce77c..d33d2b0f68b 100644 --- a/apps/files_versions/templates/history.php +++ b/apps/files_versions/templates/history.php @@ -1,3 +1,4 @@ +<div id="history"> <?php if(isset($_['message'])){ @@ -10,9 +11,10 @@ echo('<strong>Versions of '.$_['path']).'</strong><br>'; echo('<p><em>You can click on the revert button to revert to the specific verson.</em></p><br />'); foreach ($_['versions'] as $v){ - echo(' '.OC_Util::formatDate($v).' <a href="history.php?path='.urlencode($_['path']).'&revert='.$v.'" class="button">revert</a><br /><br />'); + echo(' '.OC_Util::formatDate($v).' <a href="history.php?path='.urlencode($_['path']).'&revert='.$v.'" class="button">Revert</a><br /><br />'); } } ?> +</div> diff --git a/apps/files_versions/versions.php b/apps/files_versions/versions.php index 156a4f59c73..167c64a4345 100644 --- a/apps/files_versions/versions.php +++ b/apps/files_versions/versions.php @@ -36,7 +36,7 @@ class Storage { const DEFAULTFOLDER='versions'; const DEFAULTBLACKLIST='avi mp3 mpg mp4'; const DEFAULTMAXFILESIZE=1048576; // 10MB - const DEFAULTMININTERVAL=300; // 5 min + const DEFAULTMININTERVAL=1; // 5 min const DEFAULTMAXVERSIONS=50; /** diff --git a/apps/user_ldap/appinfo/database.xml b/apps/user_ldap/appinfo/database.xml new file mode 100644 index 00000000000..74c56fcf743 --- /dev/null +++ b/apps/user_ldap/appinfo/database.xml @@ -0,0 +1,95 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> +<database> + + <name>*dbname*</name> + <create>true</create> + <overwrite>false</overwrite> + <charset>utf8</charset> + + <table> + + <name>*dbprefix*ldap_user_mapping</name> + + <declaration> + + <field> + <name>ldap_dn</name> + <type>text</type> + <notnull>true</notnull> + <length>255</length> + <default></default> + </field> + + <field> + <name>owncloud_name</name> + <type>text</type> + <notnull>true</notnull> + <length>255</length> + <default></default> + </field> + + <index> + <name>ldap_dn</name> + <unique>true</unique> + <field> + <name>ldap_dn</name> + </field> + </index> + + <index> + <name>owncloud_name</name> + <unique>true</unique> + <field> + <name>owncloud_name</name> + <sorting>ascending</sorting> + </field> + </index> + + </declaration> + + </table> + + <table> + + <name>*dbprefix*ldap_group_mapping</name> + + <declaration> + + <field> + <name>ldap_dn</name> + <type>text</type> + <notnull>true</notnull> + <length>255</length> + <default></default> + </field> + + <field> + <name>owncloud_name</name> + <type>text</type> + <notnull>true</notnull> + <length>255</length> + <default></default> + </field> + + <index> + <name>ldap_dn</name> + <unique>true</unique> + <field> + <name>ldap_dn</name> + </field> + </index> + + <index> + <name>owncloud_name</name> + <unique>true</unique> + <field> + <name>owncloud_name</name> + <sorting>ascending</sorting> + </field> + </index> + + </declaration> + + </table> + +</database>
\ No newline at end of file diff --git a/apps/user_ldap/appinfo/version b/apps/user_ldap/appinfo/version index ceab6e11ece..a0d78bd347e 100644 --- a/apps/user_ldap/appinfo/version +++ b/apps/user_ldap/appinfo/version @@ -1 +1 @@ -0.1
\ No newline at end of file +0.1.90
\ No newline at end of file diff --git a/apps/user_ldap/group_ldap.php b/apps/user_ldap/group_ldap.php index fe0789cdeb7..7773968e208 100644 --- a/apps/user_ldap/group_ldap.php +++ b/apps/user_ldap/group_ldap.php @@ -24,13 +24,9 @@ class OC_GROUP_LDAP extends OC_Group_Backend { // //group specific settings protected $ldapGroupFilter; - protected $ldapGroupDisplayName; - protected $ldapGroupMemberAttr; public function __construct() { $this->ldapGroupFilter = OC_Appconfig::getValue('user_ldap', 'ldap_group_filter', '(objectClass=posixGroup)'); - $this->ldapGroupDisplayName = OC_Appconfig::getValue('user_ldap', 'ldap_group_display_name', 'cn'); - $this->ldapGroupMemberAttr = OC_Appconfig::getValue('user_ldap', 'ldap_group_member_attr', 'memberUid'); } /** @@ -42,18 +38,17 @@ class OC_GROUP_LDAP extends OC_Group_Backend { * Checks whether the user is member of a group or not. */ public function inGroup($uid, $gid) { - $filter = OC_LDAP::combineFilterWithAnd(array( - $this->ldapGroupFilter, - LDAP_GROUP_MEMBER_ASSOC_ATTR.'='.$uid, - $this->ldapGroupDisplayName.'='.$gid - )); - $groups = $this->retrieveList($filter, $this->ldapGroupDisplayName); - - if(count($groups) > 0) { - return true; - } else { + $dn_user = OC_LDAP::username2dn($uid); + $dn_group = OC_LDAP::groupname2dn($gid); +// if($dn_group == 'c') {echo('#sdfsdgfds');die($gid);} + // just in case + if(!$dn_group || !$dn_user) { return false; } +// var_dump($dn_group); + $members = OC_LDAP::readAttribute($dn_group, LDAP_GROUP_MEMBER_ASSOC_ATTR); + + return in_array($dn_user, $members); } /** @@ -65,12 +60,19 @@ class OC_GROUP_LDAP extends OC_Group_Backend { * if the user exists at all. */ public function getUserGroups($uid) { + $userDN = OC_LDAP::username2dn($uid); + if(!$userDN) { + return array(); + } + $filter = OC_LDAP::combineFilterWithAnd(array( $this->ldapGroupFilter, - LDAP_GROUP_MEMBER_ASSOC_ATTR.'='.$uid + LDAP_GROUP_MEMBER_ASSOC_ATTR.'='.$userDN )); + $groups = $this->retrieveList($filter, array(OC_LDAP::conf('ldapGroupDisplayName'),'dn')); + $userGroups = OC_LDAP::ownCloudGroupNames($groups); - return $this->retrieveList($filter, $this->ldapGroupDisplayName); + return array_unique($userGroups, SORT_LOCALE_STRING); } /** @@ -78,12 +80,16 @@ class OC_GROUP_LDAP extends OC_Group_Backend { * @returns array with user ids */ public function usersInGroup($gid) { - $filter = OC_LDAP::combineFilterWithAnd(array( - $this->ldapGroupFilter, - $this->ldapGroupDisplayName.'='.$gid - )); - - return $this->retrieveList($filter, $this->ldapGroupMemberAttr, false); + $groupDN = OC_LDAP::groupname2dn($gid); + if(!$groupDN) { + return array(); + } + $members = OC_LDAP::readAttribute($groupDN, LDAP_GROUP_MEMBER_ASSOC_ATTR); + $result = array(); + foreach($members as $member) { + $result[] = OC_LDAP::dn2username($member); + } + return array_unique($result, SORT_LOCALE_STRING); } /** @@ -93,7 +99,9 @@ class OC_GROUP_LDAP extends OC_Group_Backend { * Returns a list with all groups */ public function getGroups() { - return $this->retrieveList($this->ldapGroupFilter, $this->ldapGroupDisplayName); + $ldap_groups = $this->retrieveList($this->ldapGroupFilter, array(OC_LDAP::conf('ldapGroupDisplayName'), 'dn')); + $groups = OC_LDAP::ownCloudGroupNames($ldap_groups); + return $groups; } /** @@ -112,13 +120,18 @@ class OC_GROUP_LDAP extends OC_Group_Backend { $list = OC_LDAP::searchUsers($filter, $attr); } - if(is_array($list)) { - return array_unique($list, SORT_LOCALE_STRING); + if(count($attr) > 1){ + return $list; + } else { + return array_unique($list, SORT_LOCALE_STRING); + } } //error cause actually, maybe throw an exception in future. return array(); } + + }
\ No newline at end of file diff --git a/apps/user_ldap/js/settings.js b/apps/user_ldap/js/settings.js new file mode 100644 index 00000000000..cae9655e3df --- /dev/null +++ b/apps/user_ldap/js/settings.js @@ -0,0 +1,3 @@ +$(document).ready(function() { + $('#ldapSettings').tabs(); +});
\ No newline at end of file diff --git a/apps/user_ldap/lib_ldap.php b/apps/user_ldap/lib_ldap.php index 752ac4f2289..4efcf0c5a0d 100644 --- a/apps/user_ldap/lib_ldap.php +++ b/apps/user_ldap/lib_ldap.php @@ -21,7 +21,8 @@ * */ -define('LDAP_GROUP_MEMBER_ASSOC_ATTR','memberUid'); +define('LDAP_GROUP_MEMBER_ASSOC_ATTR','uniqueMember'); +define('LDAP_GROUP_DISPLAY_NAME_ATTR','cn'); //needed to unbind, because we use OC_LDAP only statically class OC_LDAP_DESTRUCTOR { @@ -45,7 +46,9 @@ class OC_LDAP { static protected $ldapTLS; static protected $ldapNoCase; // user and group settings, that are needed in both backends - static public $ldapUserDisplayName; + static protected $ldapUserDisplayName; + static protected $ldapUserFilter; + static protected $ldapGroupDisplayName; static public function init() { self::readConfiguration(); @@ -56,14 +59,345 @@ class OC_LDAP { @ldap_unbind(self::$ldapConnectionRes); } + /** + * @brief returns a read-only configuration value + * @param $key the name of the configuration value + * @returns the value on success, otherwise null + * + * returns a read-only configuration values + * + * we cannot work with getters, because it is a static class + */ static public function conf($key) { + if(!self::$configured) { + self::init(); + } + $availableProperties = array( 'ldapUserDisplayName', + 'ldapGroupDisplayName', ); if(in_array($key, $availableProperties)) { return self::$$key; } + + return null; + } + + /** + * gives back the database table for the query + */ + static private function getMapTable($isUser) { + if($isUser) { + return '*PREFIX*ldap_user_mapping'; + } else { + return '*PREFIX*ldap_group_mapping'; + } + } + + /** + * @brief returns the LDAP DN for the given internal ownCloud name of the group + * @param $name the ownCloud name in question + * @returns string with the LDAP DN on success, otherwise false + * + * returns the LDAP DN for the given internal ownCloud name of the group + */ + static public function groupname2dn($name) { + return self::ocname2dn($name, false); + } + + /** + * @brief returns the LDAP DN for the given internal ownCloud name of the user + * @param $name the ownCloud name in question + * @returns string with the LDAP DN on success, otherwise false + * + * returns the LDAP DN for the given internal ownCloud name of the user + */ + static public function username2dn($name) { + $dn = self::ocname2dn($name, true); + if($dn) { + return $dn; + } else { + //fallback: user is not mapped + $filter = self::combineFilterWithAnd(array( + self::$ldapUserFilter, + self::$ldapUserDisplayName . '=' . $name, + )); + $result = self::searchUsers($filter, 'dn'); + if(isset($result[0]['dn'])) { + self::mapUser($result[0], $name); + return $result[0]; + } + } + + return false; + } + + static private function ocname2dn($name, $isUser) { + $table = self::getMapTable($isUser); + + $query = OC_DB::prepare(' + SELECT ldap_dn + FROM '.$table.' + WHERE owncloud_name = ? + '); + + $record = $query->execute(array($name))->fetchOne(); + return $record; + if($name=='Coyotes') { + echo("adsfasdf "); + var_dump($record); + die(); + } + if(isset($record['ldap_dn'])) { + return $record['ldap_dn']; + } + + return false; + } + + /** + * @brief returns the internal ownCloud name for the given LDAP DN of the group + * @param $dn the dn of the group object + * @param $ldapname optional, the display name of the object + * @returns string with with the name to use in ownCloud + * + * returns the internal ownCloud name for the given LDAP DN of the group + */ + static public function dn2groupname($dn, $ldapname = null) { + return self::dn2ocname($dn, $ldapname, false); + } + + /** + * @brief returns the internal ownCloud name for the given LDAP DN of the user + * @param $dn the dn of the user object + * @param $ldapname optional, the display name of the object + * @returns string with with the name to use in ownCloud + * + * returns the internal ownCloud name for the given LDAP DN of the user + */ + static public function dn2username($dn, $ldapname = null) { + return self::dn2ocname($dn, $ldapname, true); + } + + static public function dn2ocname($dn, $ldapname = null, $isUser = true) { + $table = self::getMapTable($isUser); + if($isUser) { + $nameAttribute = self::conf('ldapUserDisplayName'); + } else { + $nameAttribute = self::conf('ldapGroupDisplayName'); + } + + $query = OC_DB::prepare(' + SELECT owncloud_name + FROM '.$table.' + WHERE ldap_dn = ? + '); + + $component = $query->execute(array($dn))->fetchOne(); + if($component) { + return $component; + } + + if(is_null($ldapname)) { + $ldapname = self::readAttribute($dn, $nameAttribute); + $ldapname = $ldapname[0]; + } + + //a new user/group! Then let's try to add it. We're shooting into the blue with the user/group name, assuming that in most cases there will not be a conflict. Otherwise an error will occur and we will continue with our second shot. + if(self::mapComponent($dn, $ldapname, $isUser)) { + return $ldapname; + } + + //doh! There is a conflict. We need to distinguish between users/groups. Adding indexes is an idea, but not much of a help for the user. The DN is ugly, but for now the only reasonable way. But we transform it to a readable format and remove the first part to only give the path where this object is located. + $oc_name = self::alternateOwnCloudName($ldapname, $dn); + if(self::mapComponent($dn, $oc_name, $isUser)) { + return $oc_name; + } + + //and this of course should never been thrown :) + throw new Exception('LDAP backend: unexpected collision of DN and ownCloud Name.'); + } + + /** + * @brief gives back the user names as they are used ownClod internally + * @param $ldapGroups an array with the ldap Users result in style of array ( array ('dn' => foo, 'uid' => bar), ... ) + * @returns an array with the user names to use in ownCloud + * + * gives back the user names as they are used ownClod internally + */ + static public function ownCloudUserNames($ldapUsers) { + return self::ldap2ownCloudNames($ldapUsers, true); + } + + /** + * @brief gives back the group names as they are used ownClod internally + * @param $ldapGroups an array with the ldap Groups result in style of array ( array ('dn' => foo, 'cn' => bar), ... ) + * @returns an array with the group names to use in ownCloud + * + * gives back the group names as they are used ownClod internally + */ + static public function ownCloudGroupNames($ldapGroups) { + return self::ldap2ownCloudNames($ldapGroups, false); + } + + static private function ldap2ownCloudNames($ldapObjects, $isUsers) { + if($isUsers) { + $knownObjects = self::mappedUsers(); + $nameAttribute = self::conf('ldapUserDisplayName'); + } else { + $knownObjects = self::mappedGroups(); + $nameAttribute = self::conf('ldapGroupDisplayName'); + } + $ownCloudNames = array(); + + foreach($ldapObjects as $ldapObject) { + $key = self::recursiveArraySearch($knownObjects, $ldapObject['dn']); + + //everything is fine when we know the group + if($key) { + $ownCloudNames[] = $knownObjects[$key]['owncloud_name']; + continue; + } + + //a new group! Then let's try to add it. We're shooting into the blue with the group name, assuming that in most cases there will not be a conflict + if(self::mapComponent($ldapObject['dn'], $ldapObject[$nameAttribute], $isUsers)) { + $ownCloudNames[] = $ldapObject[$nameAttribute]; + continue; + } + + //doh! There is a conflict. We need to distinguish between groups. Adding indexes is an idea, but not much of a help for the user. The DN is ugly, but for now the only reasonable way. But we transform it to a readable format and remove the first part to only give the path where this entry is located. + $oc_name = self::alternateOwnCloudName($ldapObject[$nameAttribute], $ldapObject['dn']); + if(self::mapComponent($ldapObject['dn'], $oc_name, $isUsers)) { + $ownCloudNames[] = $oc_name; + continue; + } + + //and this of course should never been thrown :) + throw new Exception('LDAP backend: unexpected collision of DN and ownCloud Name.'); + } + return $ownCloudNames; + } + + /** + * @brief creates a hopefully unique name for owncloud based on the display name and the dn of the LDAP object + * @param $name the display name of the object + * @param $dn the dn of the object + * @returns string with with the name to use in ownCloud + * + * creates a hopefully unique name for owncloud based on the display name and the dn of the LDAP object + */ + static private function alternateOwnCloudName($name, $dn) { + $ufn = ldap_dn2ufn($dn); + return $name . ' (' . trim(substr_replace($ufn, '', 0, strpos($ufn, ','))) . ')'; + } + + /** + * @brief retrieves all known groups from the mappings table + * @returns array with the results + * + * retrieves all known groups from the mappings table + */ + static private function mappedGroups() { + return self::mappedComponents(false); + } + + /** + * @brief retrieves all known users from the mappings table + * @returns array with the results + * + * retrieves all known users from the mappings table + */ + static private function mappedUsers() { + return self::mappedComponents(true); + } + + static private function mappedComponents($isUsers) { + $table = self::getMapTable($isUsers); + + $query = OC_DB::prepare(' + SELECT ldap_dn, owncloud_name + FROM '. $table + ); + + return $query->execute()->fetchAll(); + } + + /** + * @brief inserts a new group into the mappings table + * @param $dn the record in question + * @param $ocname the name to use in ownCloud + * @returns true on success, false otherwise + * + * inserts a new group into the mappings table + */ + static private function mapGroup($dn, $ocname) { + return self::mapComponent($dn, $ocname, false); + } + + /** + * @brief inserts a new user into the mappings table + * @param $dn the record in question + * @param $ocname the name to use in ownCloud + * @returns true on success, false otherwise + * + * inserts a new user into the mappings table + */ + static private function mapUser($dn, $ocname) { + return self::mapComponent($dn, $ocname, true); + } + + /** + * @brief inserts a new user or group into the mappings table + * @param $dn the record in question + * @param $ocname the name to use in ownCloud + * @param $isUser is it a user or a group? + * @returns true on success, false otherwise + * + * inserts a new user or group into the mappings table + */ + static private function mapComponent($dn, $ocname, $isUser = true) { + $table = self::getMapTable($isUser); + + $insert = OC_DB::prepare(' + INSERT IGNORE INTO '.$table.' + (ldap_dn, owncloud_name) + VALUES (?,?) + '); + + $res = $insert->execute(array($dn, $ocname)); + + return !OC_DB::isError($res); + } + + /** + * @brief reads a given attribute for an LDAP record identified by a DN + * @param $dn the record in question + * @param $attr the attribute that shall be retrieved + * @returns the values in an array on success, false otherwise + * + * Reads an attribute from an LDAP entry + */ + static public function readAttribute($dn, $attr) { + $cr = self::getConnectionResource(); +// echo("<pre>");var_dump($dn); + $rr = ldap_read($cr, $dn, 'objectClass=*', array($attr)); + if(!$rr) { + echo('<pre>###RA ');var_dump($dn);var_dump(debug_backtrace());die(); + } + $er = ldap_first_entry($cr, $rr); + $result = ldap_get_attributes($cr, $er); + +// if($dn == 'cn=Coyotes,cn=groups,dc=blizzz-oc,dc=bzoc') die((var_dump($result))); + if($result[$attr]['count'] > 0){ + $values = array(); + for($i=0;$i<$result[$attr]['count'];$i++) { + $values[] = $result[$attr][$i]; + } + return $values; + } + return false; } /** @@ -100,15 +434,38 @@ class OC_LDAP { * Executes an LDAP search */ static private function search($filter, $base, $attr = null) { - $sr = ldap_search(self::getConnectionResource(), $base, $filter, array($attr)); + if(!is_null($attr) && !is_array($attr)) { + $attr = array(strtolower($attr)); + } + $sr = ldap_search(self::getConnectionResource(), $base, $filter, $attr); $findings = ldap_get_entries(self::getConnectionResource(), $sr ); if(!is_null($attr)) { $selection = array(); + $multiarray = false; + if(count($attr) > 1) { + $multiarray = true; + $i = 0; + } foreach($findings as $item) { - if(isset($item[strtolower($attr)])) { - $selection[] = $item[strtolower($attr)][0]; + if($multiarray) { + foreach($attr as $key) { + if(isset($item[$key])) { + if($key != 'dn'){ + $selection[$i][$key] = $item[$key][0]; + } else { + $selection[$i][$key] = $item[$key]; + } + } + + } + $i++; + } else { + if(isset($item[$attr[0]])) { + $selection[] = $item[$attr[0]]; + } } + } return $selection; } @@ -173,16 +530,18 @@ class OC_LDAP { */ static private function readConfiguration() { if(!self::$configured) { - self::$ldapHost = OC_Appconfig::getValue('user_ldap', 'ldap_host', ''); - self::$ldapPort = OC_Appconfig::getValue('user_ldap', 'ldap_port', OC_USER_BACKEND_LDAP_DEFAULT_PORT); - self::$ldapAgentName = OC_Appconfig::getValue('user_ldap', 'ldap_dn',''); - self::$ldapAgentPassword = OC_Appconfig::getValue('user_ldap', 'ldap_password',''); - self::$ldapBase = OC_Appconfig::getValue('user_ldap', 'ldap_base', ''); - self::$ldapBaseUsers = OC_Appconfig::getValue('user_ldap', 'ldap_base_users',self::$ldapBase); - self::$ldapBaseGroups = OC_Appconfig::getValue('user_ldap', 'ldap_base_groups', self::$ldapBase); - self::$ldapTLS = OC_Appconfig::getValue('user_ldap', 'ldap_tls',0); - self::$ldapNoCase = OC_Appconfig::getValue('user_ldap', 'ldap_nocase', 0); - self::$ldapUserDisplayName = OC_Appconfig::getValue('user_ldap', 'ldap_display_name', OC_USER_BACKEND_LDAP_DEFAULT_DISPLAY_NAME); + self::$ldapHost = OC_Appconfig::getValue('user_ldap', 'ldap_host', ''); + self::$ldapPort = OC_Appconfig::getValue('user_ldap', 'ldap_port', OC_USER_BACKEND_LDAP_DEFAULT_PORT); + self::$ldapAgentName = OC_Appconfig::getValue('user_ldap', 'ldap_dn',''); + self::$ldapAgentPassword = OC_Appconfig::getValue('user_ldap', 'ldap_password',''); + self::$ldapBase = OC_Appconfig::getValue('user_ldap', 'ldap_base', ''); + self::$ldapBaseUsers = OC_Appconfig::getValue('user_ldap', 'ldap_base_users',self::$ldapBase); + self::$ldapBaseGroups = OC_Appconfig::getValue('user_ldap', 'ldap_base_groups', self::$ldapBase); + self::$ldapTLS = OC_Appconfig::getValue('user_ldap', 'ldap_tls',0); + self::$ldapNoCase = OC_Appconfig::getValue('user_ldap', 'ldap_nocase', 0); + self::$ldapUserDisplayName = OC_Appconfig::getValue('user_ldap', 'ldap_display_name', OC_USER_BACKEND_LDAP_DEFAULT_DISPLAY_NAME); + self::$ldapUserFilter = OC_Appconfig::getValue('user_ldap', 'ldap_userlist_filter','objectClass=person'); + self::$ldapGroupDisplayName = OC_Appconfig::getValue('user_ldap', 'ldap_group_display_name', LDAP_GROUP_DISPLAY_NAME_ATTR); if( !empty(self::$ldapHost) @@ -226,5 +585,23 @@ class OC_LDAP { } } + /** + * taken from http://www.php.net/manual/en/function.array-search.php#97645 + * TODO: move somewhere, where its better placed since it is not LDAP specific. OC_Helper maybe? + */ + static public function recursiveArraySearch($haystack, $needle, $index = null) { + $aIt = new RecursiveArrayIterator($haystack); + $it = new RecursiveIteratorIterator($aIt); + + while($it->valid()) { + if (((isset($index) AND ($it->key() == $index)) OR (!isset($index))) AND ($it->current() == $needle)) { + return $aIt->key(); + } + + $it->next(); + } + + return false; + } }
\ No newline at end of file diff --git a/apps/user_ldap/settings.php b/apps/user_ldap/settings.php index ad44fe95f9e..2226c74609d 100644 --- a/apps/user_ldap/settings.php +++ b/apps/user_ldap/settings.php @@ -20,7 +20,10 @@ * License along with this library. If not, see <http://www.gnu.org/licenses/>. * */ -$params = array('ldap_host', 'ldap_port', 'ldap_dn', 'ldap_password', 'ldap_base', 'ldap_userlist_filter', 'ldap_login_filter', 'ldap_display_name', 'ldap_tls', 'ldap_nocase'. 'ldap_quota_def', 'ldap_quota_attr', 'ldap_email_attr'); +$params = array('ldap_host', 'ldap_port', 'ldap_dn', 'ldap_password', 'ldap_base', 'ldap_base_users', 'ldap_base_groups', 'ldap_userlist_filter', 'ldap_login_filter', 'ldap_display_name', 'ldap_tls', 'ldap_nocase'. 'ldap_quota_def', 'ldap_quota_attr', 'ldap_email_attr'); + +OC_Util::addScript('user_ldap', 'settings'); +OC_Util::addStyle('user_ldap', 'settings'); if ($_POST) { foreach($params as $param){ @@ -45,10 +48,8 @@ foreach($params as $param){ $tmpl->assign($param, $value); } -// ldap_port has a default value +// settings with default values $tmpl->assign( 'ldap_port', OC_Appconfig::getValue('user_ldap', 'ldap_port', OC_USER_BACKEND_LDAP_DEFAULT_PORT)); - -// ldap_display_name has a default value $tmpl->assign( 'ldap_display_name', OC_Appconfig::getValue('user_ldap', 'ldap_display_name', OC_USER_BACKEND_LDAP_DEFAULT_DISPLAY_NAME)); return $tmpl->fetchPage(); diff --git a/apps/user_ldap/templates/settings.php b/apps/user_ldap/templates/settings.php index 828c72cba97..7e327bb0701 100644 --- a/apps/user_ldap/templates/settings.php +++ b/apps/user_ldap/templates/settings.php @@ -1,21 +1,30 @@ <form id="ldap" action="#" method="post"> - <fieldset class="personalblock"> - <legend><strong>LDAP</strong></legend> - <p><label for="ldap_host"><?php echo $l->t('Host');?><input type="text" id="ldap_host" name="ldap_host" value="<?php echo $_['ldap_host']; ?>"></label> - <label for="ldap_port"><?php echo $l->t('Port');?></label><input type="text" id="ldap_port" name="ldap_port" value="<?php echo $_['ldap_port']; ?>" /></p> + <div id="ldapSettings" class="personalblock"> + <ul> + <li><a href="#ldapSettings-1">LDAP Basic</a></li> + <li><a href="#ldapSettings-2">Advanced</a></li> + </ul> + <fieldset id="ldapSettings-1"> + <p><label for="ldap_host"><?php echo $l->t('Host');?><input type="text" id="ldap_host" name="ldap_host" value="<?php echo $_['ldap_host']; ?>"></label> <label for="ldap_base"><?php echo $l->t('Base');?></label><input type="text" id="ldap_base" name="ldap_base" value="<?php echo $_['ldap_base']; ?>" /></p> <p><label for="ldap_dn"><?php echo $l->t('Name');?></label><input type="text" id="ldap_dn" name="ldap_dn" value="<?php echo $_['ldap_dn']; ?>" /> <label for="ldap_password"><?php echo $l->t('Password');?></label><input type="password" id="ldap_password" name="ldap_password" value="<?php echo $_['ldap_password']; ?>" /> <small><?php echo $l->t('Leave both empty for anonymous bind for search, then bind with users credentials.');?></small></p> - <p><label for="ldap_base"><?php echo $l->t('Base');?></label><input type="text" id="ldap_base" name="ldap_base" value="<?php echo $_['ldap_base']; ?>" /></p> <p><label for="ldap_login_filter"><?php echo $l->t('User Login Filter');?></label><input type="text" id="ldap_login_filter" name="ldap_login_filter" value="<?php echo $_['ldap_login_filter']; ?>" /><small><?php echo $l->t('use %%uid placeholder, e.g. uid=%%uid');?></small></p> - <p><label for="ldap_userlist_filter"><?php echo $l->t('User List Filter');?></label><input type="text" id="ldap_userlist_filter" name="ldap_userlist_filter" value="<?php echo $_['ldap_userlist_filter']; ?>" /><small><?php echo $l->t('without any placeholder, e.g. "objectClass=person".');?> </p> - <p><label for="ldap_display_name"><?php echo $l->t('Display Name Field');?></label><input type="text" id="ldap_display_name" name="ldap_display_name" value="<?php echo $_['ldap_display_name']; ?>" /> - <small><?php echo $l->t('Currently the display name field needs to be the same you matched %%uid against in the filter above, because ownCloud doesn\'t distinguish between user id and user name.');?></small></p> + <p><label for="ldap_userlist_filter"><?php echo $l->t('User List Filter');?></label><input type="text" id="ldap_userlist_filter" name="ldap_userlist_filter" value="<?php echo $_['ldap_userlist_filter']; ?>" /><small><?php echo $l->t('without any placeholder, e.g. "objectClass=person".');?></small></p> + </fieldset> + <fieldset id="ldapSettings-2"> + <p><label for="ldap_port"><?php echo $l->t('Port');?></label><input type="text" id="ldap_port" name="ldap_port" value="<?php echo $_['ldap_port']; ?>" /></p> + <p><label for="ldap_base_users"><?php echo $l->t('Base User Tree');?></label><input type="text" id="ldap_base_users" name="ldap_base_users" value="<?php echo $_['ldap_base_users']; ?>" /></p> + <p><label for="ldap_base_groups"><?php echo $l->t('Base Group Tree');?></label><input type="text" id="ldap_base_groups" name="ldap_base_groups" value="<?php echo $_['ldap_base_groups']; ?>" /></p> <p><input type="checkbox" id="ldap_tls" name="ldap_tls" value="1"<?php if ($_['ldap_tls']) echo ' checked'; ?>><label for="ldap_tls"><?php echo $l->t('Use TLS');?></label></p> <p><input type="checkbox" id="ldap_nocase" name="ldap_nocase" value="1"<?php if ($_['ldap_nocase']) echo ' checked'; ?>><label for="ldap_nocase"><?php echo $l->t('Case insensitve LDAP server (Windows)');?></label></p> + <p><label for="ldap_display_name"><?php echo $l->t('Display Name Field');?></label><input type="text" id="ldap_display_name" name="ldap_display_name" value="<?php echo $_['ldap_display_name']; ?>" /> + <small><?php echo $l->t('Currently the display name field needs to be the same you matched %%uid against in the filter above, because ownCloud doesn\'t distinguish between user id and user name.');?></small></p> <p><label for="ldap_quota_attr">Quota Attribute</label><input type="text" id="ldap_quota_attr" name="ldap_quota_attr" value="<?php echo $_['ldap_quota_attr']; ?>" /> - <label for="ldap_quota_def">Quota Default</label><input type="text" id="ldap_quota_def" name="ldap_quota_def" value="<?php echo $_['ldap_quota_def']; ?>" />bytes</p> - <p><label for="ldap_email_attr">Email Attribute</label><input type="text" id="ldap_email_attr" name="ldap_email_attr" value="<?php echo $_['ldap_email_attr']; ?>" /></p> - <input type="submit" value="Save" /> + <label for="ldap_quota_def">Quota Default</label><input type="text" id="ldap_quota_def" name="ldap_quota_def" value="<?php echo $_['ldap_quota_def']; ?>" />bytes</p> + <p><label for="ldap_email_attr">Email Attribute</label><input type="text" id="ldap_email_attr" name="ldap_email_attr" value="<?php echo $_['ldap_email_attr']; ?>" /></p> </fieldset> + <input type="submit" value="Save" /> + </div> + </form> diff --git a/core/img/actions/history.png b/core/img/actions/history.png Binary files differnew file mode 100644 index 00000000000..b1e743651f8 --- /dev/null +++ b/core/img/actions/history.png diff --git a/core/img/actions/history.svg b/core/img/actions/history.svg new file mode 100644 index 00000000000..9c2838d565b --- /dev/null +++ b/core/img/actions/history.svg @@ -0,0 +1,240 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:osb="http://www.openswatchbook.org/uri/2009/osb" + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="17" + height="17" + id="svg3972" + version="1.1" + inkscape:version="0.48.1 r9760" + sodipodi:docname="backup.svg" + inkscape:export-filename="/home/ronny/persoenliches/Programme/JBackpack/jbackpack/src/ch/fhnw/jbackpack/icons/16x16/icon.png" + inkscape:export-xdpi="2.8099999" + inkscape:export-ydpi="2.8099999"> + <defs + id="defs3974"> + <linearGradient + id="linearGradient3820"> + <stop + style="stop-color:#7399ab;stop-opacity:1;" + offset="0" + id="stop3822" /> + <stop + style="stop-color:#fffeff;stop-opacity:1;" + offset="1" + id="stop3824" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + id="linearGradient5144"> + <stop + style="stop-color:#ab7392;stop-opacity:1;" + offset="0" + id="stop5146" /> + <stop + style="stop-color:#ffffff;stop-opacity:0.02909091" + offset="1" + id="stop5148" /> + </linearGradient> + <linearGradient + id="linearGradient5130"> + <stop + id="stop5140" + offset="0" + style="stop-color:#a08f82;stop-opacity:0.74901961;" /> + <stop + id="stop5138" + offset="0.5" + style="stop-color:#ab7392;stop-opacity:0.49803922;" /> + <stop + style="stop-color:#ab7392;stop-opacity:0;" + offset="1" + id="stop5134" /> + </linearGradient> + <linearGradient + id="linearGradient4519" + osb:paint="gradient"> + <stop + style="stop-color:#5d879d;stop-opacity:1;" + offset="0" + id="stop4521" /> + <stop + style="stop-color:#5d879d;stop-opacity:0;" + offset="1" + id="stop4523" /> + </linearGradient> + <filter + id="filter4697" + inkscape:label="Drop shadow" + width="1.5" + height="1.5" + x="-0.25" + y="-0.25" + color-interpolation-filters="sRGB"> + <feGaussianBlur + id="feGaussianBlur4699" + in="SourceAlpha" + stdDeviation="2" + result="blur" /> + <feColorMatrix + id="feColorMatrix4701" + result="bluralpha" + type="matrix" + values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0.5 0 " /> + <feOffset + id="feOffset4703" + in="bluralpha" + dx="4" + dy="4" + result="offsetBlur" /> + <feMerge + id="feMerge4705"> + <feMergeNode + id="feMergeNode4707" + in="offsetBlur" /> + <feMergeNode + id="feMergeNode4709" + in="SourceGraphic" /> + </feMerge> + </filter> + <filter + id="filter5086" + inkscape:label="Drop shadow" + width="1.5" + height="1.5" + x="-0.25" + y="-0.25" + color-interpolation-filters="sRGB"> + <feGaussianBlur + id="feGaussianBlur5088" + in="SourceAlpha" + stdDeviation="5" + result="blur" /> + <feColorMatrix + id="feColorMatrix5090" + result="bluralpha" + type="matrix" + values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0.5 0 " /> + <feOffset + id="feOffset5092" + in="bluralpha" + dx="10" + dy="10" + result="offsetBlur" /> + <feMerge + id="feMerge5094"> + <feMergeNode + id="feMergeNode5096" + in="offsetBlur" /> + <feMergeNode + id="feMergeNode5098" + in="SourceGraphic" /> + </feMerge> + </filter> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient5130" + id="linearGradient5136" + x1="119.76609" + y1="431.36642" + x2="631.76611" + y2="431.36642" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient5144" + id="radialGradient5150" + cx="294.02567" + cy="300.53604" + fx="294.02567" + fy="300.53604" + r="183.84033" + gradientTransform="matrix(0.66691196,0.43225768,-0.44145763,0.68110633,230.61036,-24.143353)" + gradientUnits="userSpaceOnUse" /> + <filter + inkscape:collect="always" + id="filter4381" + color-interpolation-filters="sRGB"> + <feGaussianBlur + inkscape:collect="always" + stdDeviation="2.5" + id="feGaussianBlur4383" /> + </filter> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3820" + id="linearGradient3575" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.06875313,0,0,0.06875313,2.829762,444.82336)" + x1="339.43503" + y1="370.08636" + x2="66.978798" + y2="135.09288" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="45.254834" + inkscape:cx="12.081283" + inkscape:cy="8.5032287" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:window-width="1920" + inkscape:window-height="1033" + inkscape:window-x="-3" + inkscape:window-y="-3" + inkscape:window-maximized="1" + fit-margin-top="0" + fit-margin-left="0" + fit-margin-right="0" + fit-margin-bottom="0"> + <inkscape:grid + type="xygrid" + id="grid4447" + empspacing="5" + visible="true" + enabled="true" + snapvisiblegridlinesonly="true" /> + </sodipodi:namedview> + <metadata + id="metadata3977"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Ebene 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(93.42207,-466.65551)"> + <path + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" + d="m -83.896989,468.73997 c -3.950245,0 -6.534942,3.44694 -6.364259,6.72133 l -2.160822,0 3.904021,3.91738 4.081269,-3.87222 -2.148938,0 c -0.237051,-1.70092 1.163456,-3.1145 2.688727,-3.0921 1.596496,0.0235 2.800571,1.22922 2.800571,2.73336 0.08961,1.59378 -1.629405,3.4279 -3.965431,2.53172 -8.3e-5,1.22806 0.0027,2.54389 0,3.76397 4.189434,0.82896 7.639781,-2.50953 7.639781,-6.25087 0,-3.56212 -2.9188,-6.45252 -6.474921,-6.45252 z" + id="path4438" + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccccccscccccc" + inkscape:export-filename="/home/samtuke/owncloud/git/owncloud/core/img/actions/history.png" + inkscape:export-xdpi="89.929733" + inkscape:export-ydpi="89.929733" /> + </g> +</svg> diff --git a/files/js/jquery.fileupload.js b/files/js/jquery.fileupload.js new file mode 100644 index 00000000000..a89e9dc2c44 --- /dev/null +++ b/files/js/jquery.fileupload.js @@ -0,0 +1,866 @@ +/* + * jQuery File Upload Plugin 5.9 + * https://github.com/blueimp/jQuery-File-Upload + * + * Copyright 2010, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ + +/*jslint nomen: true, unparam: true, regexp: true */ +/*global define, window, document, Blob, FormData, location */ + +(function (factory) { + 'use strict'; + if (typeof define === 'function' && define.amd) { + // Register as an anonymous AMD module: + define([ + 'jquery', + 'jquery.ui.widget' + ], factory); + } else { + // Browser globals: + factory(window.jQuery); + } +}(function ($) { + 'use strict'; + + // The FileReader API is not actually used, but works as feature detection, + // as e.g. Safari supports XHR file uploads via the FormData API, + // but not non-multipart XHR file uploads: + $.support.xhrFileUpload = !!(window.XMLHttpRequestUpload && window.FileReader); + $.support.xhrFormDataFileUpload = !!window.FormData; + + // The fileupload widget listens for change events on file input fields defined + // via fileInput setting and paste or drop events of the given dropZone. + // In addition to the default jQuery Widget methods, the fileupload widget + // exposes the "add" and "send" methods, to add or directly send files using + // the fileupload API. + // By default, files added via file input selection, paste, drag & drop or + // "add" method are uploaded immediately, but it is possible to override + // the "add" callback option to queue file uploads. + $.widget('blueimp.fileupload', { + + options: { + // The namespace used for event handler binding on the dropZone and + // fileInput collections. + // If not set, the name of the widget ("fileupload") is used. + namespace: undefined, + // The drop target collection, by the default the complete document. + // Set to null or an empty collection to disable drag & drop support: + dropZone: $(document), + // The file input field collection, that is listened for change events. + // If undefined, it is set to the file input fields inside + // of the widget element on plugin initialization. + // Set to null or an empty collection to disable the change listener. + fileInput: undefined, + // By default, the file input field is replaced with a clone after + // each input field change event. This is required for iframe transport + // queues and allows change events to be fired for the same file + // selection, but can be disabled by setting the following option to false: + replaceFileInput: true, + // The parameter name for the file form data (the request argument name). + // If undefined or empty, the name property of the file input field is + // used, or "files[]" if the file input name property is also empty: + paramName: undefined, + // By default, each file of a selection is uploaded using an individual + // request for XHR type uploads. Set to false to upload file + // selections in one request each: + singleFileUploads: true, + // To limit the number of files uploaded with one XHR request, + // set the following option to an integer greater than 0: + limitMultiFileUploads: undefined, + // Set the following option to true to issue all file upload requests + // in a sequential order: + sequentialUploads: false, + // To limit the number of concurrent uploads, + // set the following option to an integer greater than 0: + limitConcurrentUploads: undefined, + // Set the following option to true to force iframe transport uploads: + forceIframeTransport: false, + // Set the following option to the location of a redirect url on the + // origin server, for cross-domain iframe transport uploads: + redirect: undefined, + // The parameter name for the redirect url, sent as part of the form + // data and set to 'redirect' if this option is empty: + redirectParamName: undefined, + // Set the following option to the location of a postMessage window, + // to enable postMessage transport uploads: + postMessage: undefined, + // By default, XHR file uploads are sent as multipart/form-data. + // The iframe transport is always using multipart/form-data. + // Set to false to enable non-multipart XHR uploads: + multipart: true, + // To upload large files in smaller chunks, set the following option + // to a preferred maximum chunk size. If set to 0, null or undefined, + // or the browser does not support the required Blob API, files will + // be uploaded as a whole. + maxChunkSize: undefined, + // When a non-multipart upload or a chunked multipart upload has been + // aborted, this option can be used to resume the upload by setting + // it to the size of the already uploaded bytes. This option is most + // useful when modifying the options object inside of the "add" or + // "send" callbacks, as the options are cloned for each file upload. + uploadedBytes: undefined, + // By default, failed (abort or error) file uploads are removed from the + // global progress calculation. Set the following option to false to + // prevent recalculating the global progress data: + recalculateProgress: true, + + // Additional form data to be sent along with the file uploads can be set + // using this option, which accepts an array of objects with name and + // value properties, a function returning such an array, a FormData + // object (for XHR file uploads), or a simple object. + // The form of the first fileInput is given as parameter to the function: + formData: function (form) { + return form.serializeArray(); + }, + + // The add callback is invoked as soon as files are added to the fileupload + // widget (via file input selection, drag & drop, paste or add API call). + // If the singleFileUploads option is enabled, this callback will be + // called once for each file in the selection for XHR file uplaods, else + // once for each file selection. + // The upload starts when the submit method is invoked on the data parameter. + // The data object contains a files property holding the added files + // and allows to override plugin options as well as define ajax settings. + // Listeners for this callback can also be bound the following way: + // .bind('fileuploadadd', func); + // data.submit() returns a Promise object and allows to attach additional + // handlers using jQuery's Deferred callbacks: + // data.submit().done(func).fail(func).always(func); + add: function (e, data) { + data.submit(); + }, + + // Other callbacks: + // Callback for the submit event of each file upload: + // submit: function (e, data) {}, // .bind('fileuploadsubmit', func); + // Callback for the start of each file upload request: + // send: function (e, data) {}, // .bind('fileuploadsend', func); + // Callback for successful uploads: + // done: function (e, data) {}, // .bind('fileuploaddone', func); + // Callback for failed (abort or error) uploads: + // fail: function (e, data) {}, // .bind('fileuploadfail', func); + // Callback for completed (success, abort or error) requests: + // always: function (e, data) {}, // .bind('fileuploadalways', func); + // Callback for upload progress events: + // progress: function (e, data) {}, // .bind('fileuploadprogress', func); + // Callback for global upload progress events: + // progressall: function (e, data) {}, // .bind('fileuploadprogressall', func); + // Callback for uploads start, equivalent to the global ajaxStart event: + // start: function (e) {}, // .bind('fileuploadstart', func); + // Callback for uploads stop, equivalent to the global ajaxStop event: + // stop: function (e) {}, // .bind('fileuploadstop', func); + // Callback for change events of the fileInput collection: + // change: function (e, data) {}, // .bind('fileuploadchange', func); + // Callback for paste events to the dropZone collection: + // paste: function (e, data) {}, // .bind('fileuploadpaste', func); + // Callback for drop events of the dropZone collection: + // drop: function (e, data) {}, // .bind('fileuploaddrop', func); + // Callback for dragover events of the dropZone collection: + // dragover: function (e) {}, // .bind('fileuploaddragover', func); + + // The plugin options are used as settings object for the ajax calls. + // The following are jQuery ajax settings required for the file uploads: + processData: false, + contentType: false, + cache: false + }, + + // A list of options that require a refresh after assigning a new value: + _refreshOptionsList: [ + 'namespace', + 'dropZone', + 'fileInput', + 'multipart', + 'forceIframeTransport' + ], + + _isXHRUpload: function (options) { + return !options.forceIframeTransport && + ((!options.multipart && $.support.xhrFileUpload) || + $.support.xhrFormDataFileUpload); + }, + + _getFormData: function (options) { + var formData; + if (typeof options.formData === 'function') { + return options.formData(options.form); + } else if ($.isArray(options.formData)) { + return options.formData; + } else if (options.formData) { + formData = []; + $.each(options.formData, function (name, value) { + formData.push({name: name, value: value}); + }); + return formData; + } + return []; + }, + + _getTotal: function (files) { + var total = 0; + $.each(files, function (index, file) { + total += file.size || 1; + }); + return total; + }, + + _onProgress: function (e, data) { + if (e.lengthComputable) { + var total = data.total || this._getTotal(data.files), + loaded = parseInt( + e.loaded / e.total * (data.chunkSize || total), + 10 + ) + (data.uploadedBytes || 0); + this._loaded += loaded - (data.loaded || data.uploadedBytes || 0); + data.lengthComputable = true; + data.loaded = loaded; + data.total = total; + // Trigger a custom progress event with a total data property set + // to the file size(s) of the current upload and a loaded data + // property calculated accordingly: + this._trigger('progress', e, data); + // Trigger a global progress event for all current file uploads, + // including ajax calls queued for sequential file uploads: + this._trigger('progressall', e, { + lengthComputable: true, + loaded: this._loaded, + total: this._total + }); + } + }, + + _initProgressListener: function (options) { + var that = this, + xhr = options.xhr ? options.xhr() : $.ajaxSettings.xhr(); + // Accesss to the native XHR object is required to add event listeners + // for the upload progress event: + if (xhr.upload) { + $(xhr.upload).bind('progress', function (e) { + var oe = e.originalEvent; + // Make sure the progress event properties get copied over: + e.lengthComputable = oe.lengthComputable; + e.loaded = oe.loaded; + e.total = oe.total; + that._onProgress(e, options); + }); + options.xhr = function () { + return xhr; + }; + } + }, + + _initXHRData: function (options) { + var formData, + file = options.files[0], + // Ignore non-multipart setting if not supported: + multipart = options.multipart || !$.support.xhrFileUpload; + if (!multipart || options.blob) { + // For non-multipart uploads and chunked uploads, + // file meta data is not part of the request body, + // so we transmit this data as part of the HTTP headers. + // For cross domain requests, these headers must be allowed + // via Access-Control-Allow-Headers or removed using + // the beforeSend callback: + options.headers = $.extend(options.headers, { + 'X-File-Name': file.name, + 'X-File-Type': file.type, + 'X-File-Size': file.size + }); + if (!options.blob) { + // Non-chunked non-multipart upload: + options.contentType = file.type; + options.data = file; + } else if (!multipart) { + // Chunked non-multipart upload: + options.contentType = 'application/octet-stream'; + options.data = options.blob; + } + } + if (multipart && $.support.xhrFormDataFileUpload) { + if (options.postMessage) { + // window.postMessage does not allow sending FormData + // objects, so we just add the File/Blob objects to + // the formData array and let the postMessage window + // create the FormData object out of this array: + formData = this._getFormData(options); + if (options.blob) { + formData.push({ + name: options.paramName, + value: options.blob + }); + } else { + $.each(options.files, function (index, file) { + formData.push({ + name: options.paramName, + value: file + }); + }); + } + } else { + if (options.formData instanceof FormData) { + formData = options.formData; + } else { + formData = new FormData(); + $.each(this._getFormData(options), function (index, field) { + formData.append(field.name, field.value); + }); + } + if (options.blob) { + formData.append(options.paramName, options.blob, file.name); + } else { + $.each(options.files, function (index, file) { + // File objects are also Blob instances. + // This check allows the tests to run with + // dummy objects: + if (file instanceof Blob) { + formData.append(options.paramName, file, file.name); + } + }); + } + } + options.data = formData; + } + // Blob reference is not needed anymore, free memory: + options.blob = null; + }, + + _initIframeSettings: function (options) { + // Setting the dataType to iframe enables the iframe transport: + options.dataType = 'iframe ' + (options.dataType || ''); + // The iframe transport accepts a serialized array as form data: + options.formData = this._getFormData(options); + // Add redirect url to form data on cross-domain uploads: + if (options.redirect && $('<a></a>').prop('href', options.url) + .prop('host') !== location.host) { + options.formData.push({ + name: options.redirectParamName || 'redirect', + value: options.redirect + }); + } + }, + + _initDataSettings: function (options) { + if (this._isXHRUpload(options)) { + if (!this._chunkedUpload(options, true)) { + if (!options.data) { + this._initXHRData(options); + } + this._initProgressListener(options); + } + if (options.postMessage) { + // Setting the dataType to postmessage enables the + // postMessage transport: + options.dataType = 'postmessage ' + (options.dataType || ''); + } + } else { + this._initIframeSettings(options, 'iframe'); + } + }, + + _initFormSettings: function (options) { + // Retrieve missing options from the input field and the + // associated form, if available: + if (!options.form || !options.form.length) { + options.form = $(options.fileInput.prop('form')); + } + if (!options.paramName) { + options.paramName = options.fileInput.prop('name') || + 'files[]'; + } + if (!options.url) { + options.url = options.form.prop('action') || location.href; + } + // The HTTP request method must be "POST" or "PUT": + options.type = (options.type || options.form.prop('method') || '') + .toUpperCase(); + if (options.type !== 'POST' && options.type !== 'PUT') { + options.type = 'POST'; + } + }, + + _getAJAXSettings: function (data) { + var options = $.extend({}, this.options, data); + this._initFormSettings(options); + this._initDataSettings(options); + return options; + }, + + // Maps jqXHR callbacks to the equivalent + // methods of the given Promise object: + _enhancePromise: function (promise) { + promise.success = promise.done; + promise.error = promise.fail; + promise.complete = promise.always; + return promise; + }, + + // Creates and returns a Promise object enhanced with + // the jqXHR methods abort, success, error and complete: + _getXHRPromise: function (resolveOrReject, context, args) { + var dfd = $.Deferred(), + promise = dfd.promise(); + context = context || this.options.context || promise; + if (resolveOrReject === true) { + dfd.resolveWith(context, args); + } else if (resolveOrReject === false) { + dfd.rejectWith(context, args); + } + promise.abort = dfd.promise; + return this._enhancePromise(promise); + }, + + // Uploads a file in multiple, sequential requests + // by splitting the file up in multiple blob chunks. + // If the second parameter is true, only tests if the file + // should be uploaded in chunks, but does not invoke any + // upload requests: + _chunkedUpload: function (options, testOnly) { + var that = this, + file = options.files[0], + fs = file.size, + ub = options.uploadedBytes = options.uploadedBytes || 0, + mcs = options.maxChunkSize || fs, + // Use the Blob methods with the slice implementation + // according to the W3C Blob API specification: + slice = file.webkitSlice || file.mozSlice || file.slice, + upload, + n, + jqXHR, + pipe; + if (!(this._isXHRUpload(options) && slice && (ub || mcs < fs)) || + options.data) { + return false; + } + if (testOnly) { + return true; + } + if (ub >= fs) { + file.error = 'uploadedBytes'; + return this._getXHRPromise( + false, + options.context, + [null, 'error', file.error] + ); + } + // n is the number of blobs to upload, + // calculated via filesize, uploaded bytes and max chunk size: + n = Math.ceil((fs - ub) / mcs); + // The chunk upload method accepting the chunk number as parameter: + upload = function (i) { + if (!i) { + return that._getXHRPromise(true, options.context); + } + // Upload the blobs in sequential order: + return upload(i -= 1).pipe(function () { + // Clone the options object for each chunk upload: + var o = $.extend({}, options); + o.blob = slice.call( + file, + ub + i * mcs, + ub + (i + 1) * mcs + ); + // Store the current chunk size, as the blob itself + // will be dereferenced after data processing: + o.chunkSize = o.blob.size; + // Process the upload data (the blob and potential form data): + that._initXHRData(o); + // Add progress listeners for this chunk upload: + that._initProgressListener(o); + jqXHR = ($.ajax(o) || that._getXHRPromise(false, o.context)) + .done(function () { + // Create a progress event if upload is done and + // no progress event has been invoked for this chunk: + if (!o.loaded) { + that._onProgress($.Event('progress', { + lengthComputable: true, + loaded: o.chunkSize, + total: o.chunkSize + }), o); + } + options.uploadedBytes = o.uploadedBytes += + o.chunkSize; + }); + return jqXHR; + }); + }; + // Return the piped Promise object, enhanced with an abort method, + // which is delegated to the jqXHR object of the current upload, + // and jqXHR callbacks mapped to the equivalent Promise methods: + pipe = upload(n); + pipe.abort = function () { + return jqXHR.abort(); + }; + return this._enhancePromise(pipe); + }, + + _beforeSend: function (e, data) { + if (this._active === 0) { + // the start callback is triggered when an upload starts + // and no other uploads are currently running, + // equivalent to the global ajaxStart event: + this._trigger('start'); + } + this._active += 1; + // Initialize the global progress values: + this._loaded += data.uploadedBytes || 0; + this._total += this._getTotal(data.files); + }, + + _onDone: function (result, textStatus, jqXHR, options) { + if (!this._isXHRUpload(options)) { + // Create a progress event for each iframe load: + this._onProgress($.Event('progress', { + lengthComputable: true, + loaded: 1, + total: 1 + }), options); + } + options.result = result; + options.textStatus = textStatus; + options.jqXHR = jqXHR; + this._trigger('done', null, options); + }, + + _onFail: function (jqXHR, textStatus, errorThrown, options) { + options.jqXHR = jqXHR; + options.textStatus = textStatus; + options.errorThrown = errorThrown; + this._trigger('fail', null, options); + if (options.recalculateProgress) { + // Remove the failed (error or abort) file upload from + // the global progress calculation: + this._loaded -= options.loaded || options.uploadedBytes || 0; + this._total -= options.total || this._getTotal(options.files); + } + }, + + _onAlways: function (jqXHRorResult, textStatus, jqXHRorError, options) { + this._active -= 1; + options.textStatus = textStatus; + if (jqXHRorError && jqXHRorError.always) { + options.jqXHR = jqXHRorError; + options.result = jqXHRorResult; + } else { + options.jqXHR = jqXHRorResult; + options.errorThrown = jqXHRorError; + } + this._trigger('always', null, options); + if (this._active === 0) { + // The stop callback is triggered when all uploads have + // been completed, equivalent to the global ajaxStop event: + this._trigger('stop'); + // Reset the global progress values: + this._loaded = this._total = 0; + } + }, + + _onSend: function (e, data) { + var that = this, + jqXHR, + slot, + pipe, + options = that._getAJAXSettings(data), + send = function (resolve, args) { + that._sending += 1; + jqXHR = jqXHR || ( + (resolve !== false && + that._trigger('send', e, options) !== false && + (that._chunkedUpload(options) || $.ajax(options))) || + that._getXHRPromise(false, options.context, args) + ).done(function (result, textStatus, jqXHR) { + that._onDone(result, textStatus, jqXHR, options); + }).fail(function (jqXHR, textStatus, errorThrown) { + that._onFail(jqXHR, textStatus, errorThrown, options); + }).always(function (jqXHRorResult, textStatus, jqXHRorError) { + that._sending -= 1; + that._onAlways( + jqXHRorResult, + textStatus, + jqXHRorError, + options + ); + if (options.limitConcurrentUploads && + options.limitConcurrentUploads > that._sending) { + // Start the next queued upload, + // that has not been aborted: + var nextSlot = that._slots.shift(); + while (nextSlot) { + if (!nextSlot.isRejected()) { + nextSlot.resolve(); + break; + } + nextSlot = that._slots.shift(); + } + } + }); + return jqXHR; + }; + this._beforeSend(e, options); + if (this.options.sequentialUploads || + (this.options.limitConcurrentUploads && + this.options.limitConcurrentUploads <= this._sending)) { + if (this.options.limitConcurrentUploads > 1) { + slot = $.Deferred(); + this._slots.push(slot); + pipe = slot.pipe(send); + } else { + pipe = (this._sequence = this._sequence.pipe(send, send)); + } + // Return the piped Promise object, enhanced with an abort method, + // which is delegated to the jqXHR object of the current upload, + // and jqXHR callbacks mapped to the equivalent Promise methods: + pipe.abort = function () { + var args = [undefined, 'abort', 'abort']; + if (!jqXHR) { + if (slot) { + slot.rejectWith(args); + } + return send(false, args); + } + return jqXHR.abort(); + }; + return this._enhancePromise(pipe); + } + return send(); + }, + + _onAdd: function (e, data) { + var that = this, + result = true, + options = $.extend({}, this.options, data), + limit = options.limitMultiFileUploads, + fileSet, + i; + if (!(options.singleFileUploads || limit) || + !this._isXHRUpload(options)) { + fileSet = [data.files]; + } else if (!options.singleFileUploads && limit) { + fileSet = []; + for (i = 0; i < data.files.length; i += limit) { + fileSet.push(data.files.slice(i, i + limit)); + } + } + data.originalFiles = data.files; + $.each(fileSet || data.files, function (index, element) { + var files = fileSet ? element : [element], + newData = $.extend({}, data, {files: files}); + newData.submit = function () { + newData.jqXHR = this.jqXHR = + (that._trigger('submit', e, this) !== false) && + that._onSend(e, this); + return this.jqXHR; + }; + return (result = that._trigger('add', e, newData)); + }); + return result; + }, + + // File Normalization for Gecko 1.9.1 (Firefox 3.5) support: + _normalizeFile: function (index, file) { + if (file.name === undefined && file.size === undefined) { + file.name = file.fileName; + file.size = file.fileSize; + } + }, + + _replaceFileInput: function (input) { + var inputClone = input.clone(true); + $('<form></form>').append(inputClone)[0].reset(); + // Detaching allows to insert the fileInput on another form + // without loosing the file input value: + input.after(inputClone).detach(); + // Avoid memory leaks with the detached file input: + $.cleanData(input.unbind('remove')); + // Replace the original file input element in the fileInput + // collection with the clone, which has been copied including + // event handlers: + this.options.fileInput = this.options.fileInput.map(function (i, el) { + if (el === input[0]) { + return inputClone[0]; + } + return el; + }); + // If the widget has been initialized on the file input itself, + // override this.element with the file input clone: + if (input[0] === this.element[0]) { + this.element = inputClone; + } + }, + + _onChange: function (e) { + var that = e.data.fileupload, + data = { + files: $.each($.makeArray(e.target.files), that._normalizeFile), + fileInput: $(e.target), + form: $(e.target.form) + }; + if (!data.files.length) { + // If the files property is not available, the browser does not + // support the File API and we add a pseudo File object with + // the input value as name with path information removed: + data.files = [{name: e.target.value.replace(/^.*\\/, '')}]; + } + if (that.options.replaceFileInput) { + that._replaceFileInput(data.fileInput); + } + if (that._trigger('change', e, data) === false || + that._onAdd(e, data) === false) { + return false; + } + }, + + _onPaste: function (e) { + var that = e.data.fileupload, + cbd = e.originalEvent.clipboardData, + items = (cbd && cbd.items) || [], + data = {files: []}; + $.each(items, function (index, item) { + var file = item.getAsFile && item.getAsFile(); + if (file) { + data.files.push(file); + } + }); + if (that._trigger('paste', e, data) === false || + that._onAdd(e, data) === false) { + return false; + } + }, + + _onDrop: function (e) { + var that = e.data.fileupload, + dataTransfer = e.dataTransfer = e.originalEvent.dataTransfer, + data = { + files: $.each( + $.makeArray(dataTransfer && dataTransfer.files), + that._normalizeFile + ) + }; + if (that._trigger('drop', e, data) === false || + that._onAdd(e, data) === false) { + return false; + } + e.preventDefault(); + }, + + _onDragOver: function (e) { + var that = e.data.fileupload, + dataTransfer = e.dataTransfer = e.originalEvent.dataTransfer; + if (that._trigger('dragover', e) === false) { + return false; + } + if (dataTransfer) { + dataTransfer.dropEffect = dataTransfer.effectAllowed = 'copy'; + } + e.preventDefault(); + }, + + _initEventHandlers: function () { + var ns = this.options.namespace; + if (this._isXHRUpload(this.options)) { + this.options.dropZone + .bind('dragover.' + ns, {fileupload: this}, this._onDragOver) + .bind('drop.' + ns, {fileupload: this}, this._onDrop) + .bind('paste.' + ns, {fileupload: this}, this._onPaste); + } + this.options.fileInput + .bind('change.' + ns, {fileupload: this}, this._onChange); + }, + + _destroyEventHandlers: function () { + var ns = this.options.namespace; + this.options.dropZone + .unbind('dragover.' + ns, this._onDragOver) + .unbind('drop.' + ns, this._onDrop) + .unbind('paste.' + ns, this._onPaste); + this.options.fileInput + .unbind('change.' + ns, this._onChange); + }, + + _setOption: function (key, value) { + var refresh = $.inArray(key, this._refreshOptionsList) !== -1; + if (refresh) { + this._destroyEventHandlers(); + } + $.Widget.prototype._setOption.call(this, key, value); + if (refresh) { + this._initSpecialOptions(); + this._initEventHandlers(); + } + }, + + _initSpecialOptions: function () { + var options = this.options; + if (options.fileInput === undefined) { + options.fileInput = this.element.is('input:file') ? + this.element : this.element.find('input:file'); + } else if (!(options.fileInput instanceof $)) { + options.fileInput = $(options.fileInput); + } + if (!(options.dropZone instanceof $)) { + options.dropZone = $(options.dropZone); + } + }, + + _create: function () { + var options = this.options, + dataOpts = $.extend({}, this.element.data()); + dataOpts[this.widgetName] = undefined; + $.extend(options, dataOpts); + options.namespace = options.namespace || this.widgetName; + this._initSpecialOptions(); + this._slots = []; + this._sequence = this._getXHRPromise(true); + this._sending = this._active = this._loaded = this._total = 0; + this._initEventHandlers(); + }, + + destroy: function () { + this._destroyEventHandlers(); + $.Widget.prototype.destroy.call(this); + }, + + enable: function () { + $.Widget.prototype.enable.call(this); + this._initEventHandlers(); + }, + + disable: function () { + this._destroyEventHandlers(); + $.Widget.prototype.disable.call(this); + }, + + // This method is exposed to the widget API and allows adding files + // using the fileupload API. The data parameter accepts an object which + // must have a files property and can contain additional options: + // .fileupload('add', {files: filesList}); + add: function (data) { + if (!data || this.options.disabled) { + return; + } + data.files = $.each($.makeArray(data.files), this._normalizeFile); + this._onAdd(null, data); + }, + + // This method is exposed to the widget API and allows sending files + // using the fileupload API. The data parameter accepts an object which + // must have a files property and can contain additional options: + // .fileupload('send', {files: filesList}); + // The method returns a Promise object for the file upload call. + send: function (data) { + if (data && !this.options.disabled) { + data.files = $.each($.makeArray(data.files), this._normalizeFile); + if (data.files.length) { + return this._onSend(null, data); + } + } + return this._getXHRPromise(false, data && data.context); + } + + }); + +})); diff --git a/files/js/jquery.iframe-transport.js b/files/js/jquery.iframe-transport.js new file mode 100644 index 00000000000..d85c0c11297 --- /dev/null +++ b/files/js/jquery.iframe-transport.js @@ -0,0 +1,165 @@ +/* + * jQuery Iframe Transport Plugin 1.3 + * https://github.com/blueimp/jQuery-File-Upload + * + * Copyright 2011, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ + +/*jslint unparam: true, nomen: true */ +/*global define, window, document */ + +(function (factory) { + 'use strict'; + if (typeof define === 'function' && define.amd) { + // Register as an anonymous AMD module: + define(['jquery'], factory); + } else { + // Browser globals: + factory(window.jQuery); + } +}(function ($) { + 'use strict'; + + // Helper variable to create unique names for the transport iframes: + var counter = 0; + + // The iframe transport accepts three additional options: + // options.fileInput: a jQuery collection of file input fields + // options.paramName: the parameter name for the file form data, + // overrides the name property of the file input field(s) + // options.formData: an array of objects with name and value properties, + // equivalent to the return data of .serializeArray(), e.g.: + // [{name: 'a', value: 1}, {name: 'b', value: 2}] + $.ajaxTransport('iframe', function (options) { + if (options.async && (options.type === 'POST' || options.type === 'GET')) { + var form, + iframe; + return { + send: function (_, completeCallback) { + form = $('<form style="display:none;"></form>'); + // javascript:false as initial iframe src + // prevents warning popups on HTTPS in IE6. + // IE versions below IE8 cannot set the name property of + // elements that have already been added to the DOM, + // so we set the name along with the iframe HTML markup: + iframe = $( + '<iframe src="javascript:false;" name="iframe-transport-' + + (counter += 1) + '"></iframe>' + ).bind('load', function () { + var fileInputClones; + iframe + .unbind('load') + .bind('load', function () { + var response; + // Wrap in a try/catch block to catch exceptions thrown + // when trying to access cross-domain iframe contents: + try { + response = iframe.contents(); + // Google Chrome and Firefox do not throw an + // exception when calling iframe.contents() on + // cross-domain requests, so we unify the response: + if (!response.length || !response[0].firstChild) { + throw new Error(); + } + } catch (e) { + response = undefined; + } + // The complete callback returns the + // iframe content document as response object: + completeCallback( + 200, + 'success', + {'iframe': response} + ); + // Fix for IE endless progress bar activity bug + // (happens on form submits to iframe targets): + $('<iframe src="javascript:false;"></iframe>') + .appendTo(form); + form.remove(); + }); + form + .prop('target', iframe.prop('name')) + .prop('action', options.url) + .prop('method', options.type); + if (options.formData) { + $.each(options.formData, function (index, field) { + $('<input type="hidden"/>') + .prop('name', field.name) + .val(field.value) + .appendTo(form); + }); + } + if (options.fileInput && options.fileInput.length && + options.type === 'POST') { + fileInputClones = options.fileInput.clone(); + // Insert a clone for each file input field: + options.fileInput.after(function (index) { + return fileInputClones[index]; + }); + if (options.paramName) { + options.fileInput.each(function () { + $(this).prop('name', options.paramName); + }); + } + // Appending the file input fields to the hidden form + // removes them from their original location: + form + .append(options.fileInput) + .prop('enctype', 'multipart/form-data') + // enctype must be set as encoding for IE: + .prop('encoding', 'multipart/form-data'); + } + form.submit(); + // Insert the file input fields at their original location + // by replacing the clones with the originals: + if (fileInputClones && fileInputClones.length) { + options.fileInput.each(function (index, input) { + var clone = $(fileInputClones[index]); + $(input).prop('name', clone.prop('name')); + clone.replaceWith(input); + }); + } + }); + form.append(iframe).appendTo(document.body); + }, + abort: function () { + if (iframe) { + // javascript:false as iframe src aborts the request + // and prevents warning popups on HTTPS in IE6. + // concat is used to avoid the "Script URL" JSLint error: + iframe + .unbind('load') + .prop('src', 'javascript'.concat(':false;')); + } + if (form) { + form.remove(); + } + } + }; + } + }); + + // The iframe transport returns the iframe content document as response. + // The following adds converters from iframe to text, json, html, and script: + $.ajaxSetup({ + converters: { + 'iframe text': function (iframe) { + return $(iframe[0].body).text(); + }, + 'iframe json': function (iframe) { + return $.parseJSON($(iframe[0].body).text()); + }, + 'iframe html': function (iframe) { + return $(iframe[0].body).html(); + }, + 'iframe script': function (iframe) { + return $.globalEval($(iframe[0].body).text()); + } + } + }); + +})); diff --git a/lib/base.php b/lib/base.php index 74693641f6e..fa4c9850a3b 100644 --- a/lib/base.php +++ b/lib/base.php @@ -428,7 +428,7 @@ class OC{ $parent = OC::$APPSROOT . '/' . self::$REQUESTEDAPP; if(!OC_Helper::issubdirectory($subdir, $parent)){ self::$REQUESTEDFILE = null; - //header('HTTP/1.0 404 Not Found'); + header('HTTP/1.0 404 Not Found'); exit; } } diff --git a/lib/connector/sabre/directory.php b/lib/connector/sabre/directory.php index cc37bf22d5d..912c8cd439a 100644 --- a/lib/connector/sabre/directory.php +++ b/lib/connector/sabre/directory.php @@ -50,7 +50,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa $path = $this->path . '/' . $name; - if (!OC_Filesystem::file_exists($path)) throw new Sabre_DAV_Exception_FileNotFound('File with name ' . $path . ' could not be located'); + if (!OC_Filesystem::file_exists($path)) throw new Sabre_DAV_Exception_NotFound('File with name ' . $path . ' could not be located'); if (OC_Filesystem::is_dir($path)) { diff --git a/lib/connector/sabre/principal.php b/lib/connector/sabre/principal.php index 28a36438e87..d1456f7c642 100644 --- a/lib/connector/sabre/principal.php +++ b/lib/connector/sabre/principal.php @@ -46,7 +46,7 @@ class OC_Connector_Sabre_Principal implements Sabre_DAVACL_IPrincipalBackend { * @return array */ public function getPrincipalByPath($path) { - list($prefix,$name) = Sabre_DAV_URLUtil::splitPath($path); + list($prefix,$name) = explode('/', $path); if ($prefix == 'principals' && OC_User::userExists($name)) { return array( @@ -115,4 +115,6 @@ class OC_Connector_Sabre_Principal implements Sabre_DAVACL_IPrincipalBackend { public function setGroupMemberSet($principal, array $members) { throw new Sabre_DAV_Exception('Setting members of the group is not supported yet'); } + function updatePrincipal($path, $mutations){return 0;} + function searchPrincipals($prefixPath, array $searchProperties){return 0;} } diff --git a/lib/filecache.php b/lib/filecache.php index 19286ff746b..28a9eb247a6 100644 --- a/lib/filecache.php +++ b/lib/filecache.php @@ -64,7 +64,7 @@ class OC_FileCache{ if(is_array($result)){ return $result; }else{ - OC_Log::write('get(): file not found in cache ('.$path.')','core',OC_Log::DEBUG); + OC_Log::write('files','get(): file not found in cache ('.$path.')',OC_Log::DEBUG); return false; } } @@ -257,7 +257,7 @@ class OC_FileCache{ if(is_array($result)){ return $result; }else{ - OC_Log::write('getFolderContent(): file not found in cache ('.$path.')','core',OC_Log::DEBUG); + OC_Log::write('files','getFolderContent(): file not found in cache ('.$path.')',OC_Log::DEBUG); return false; } } @@ -300,7 +300,7 @@ class OC_FileCache{ if(is_array($result)){ return $result['id']; }else{ - OC_Log::write('getFileId(): file not found in cache ('.$path.')','core',OC_Log::DEBUG); + OC_Log::write('files','getFileId(): file not found in cache ('.$path.')',OC_Log::DEBUG); return -1; } } @@ -414,8 +414,12 @@ class OC_FileCache{ } return $result; }else{ - OC_Log::write('get(): file not found in cache ('.$path.')','core',OC_Log::DEBUG); - return false; + OC_Log::write('files','getChached(): file not found in cache ('.$path.')',OC_Log::DEBUG); + if(isset(self::$savedData[$path])){ + return self::$savedData[$path]; + }else{ + return array(); + } } } @@ -553,6 +557,7 @@ class OC_FileCache{ $view=new OC_FilesystemView(($root=='/')?'':$root); } if(!$view->is_readable($path)) return; //cant read, nothing we can do + clearstatcache(); $stat=$view->stat($path); $mimetype=$view->getMimeType($path); $writable=$view->is_writable($path); diff --git a/lib/filesystem.php b/lib/filesystem.php index dc678fba74c..1b91eabc7c1 100644 --- a/lib/filesystem.php +++ b/lib/filesystem.php @@ -196,10 +196,58 @@ class OC_Filesystem{ return false; } self::$defaultInstance=new OC_FilesystemView($root); + + //load custom mount config + if(is_file(OC::$SERVERROOT.'/config/mount.php')){ + $mountConfig=include(OC::$SERVERROOT.'/config/mount.php'); + if(isset($mountConfig['global'])){ + foreach($mountConfig['global'] as $mountPoint=>$options){ + self::mount($options['class'],$options['options'],$mountPoint); + } + } + + if(isset($mountConfig['group'])){ + foreach($mountConfig['group'] as $group=>$mounts){ + if(OC_Group::inGroup(OC_User::getUser(),$group)){ + foreach($mounts as $mountPoint=>$options){ + $mountPoint=self::setUserVars($mountPoint); + foreach($options as &$option){ + $option=self::setUserVars($option); + } + self::mount($options['class'],$options['options'],$mountPoint); + } + } + } + } + + if(isset($mountConfig['user'])){ + foreach($mountConfig['user'] as $user=>$mounts){ + if($user==='all' or strtolower($user)===strtolower(OC_User::getUser())){ + foreach($mounts as $mountPoint=>$options){ + $mountPoint=self::setUserVars($mountPoint); + foreach($options as &$option){ + $option=self::setUserVars($option); + } + self::mount($options['class'],$options['options'],$mountPoint); + } + } + } + } + } + self::$loaded=true; } /** + * fill in the correct values for $user, and $password placeholders + * @param string intput + * @return string + */ + private static function setUserVars($input){ + return str_replace('$user',OC_User::getUser(),$input); + } + + /** * get the default filesystem view * @return OC_FilesystemView */ diff --git a/lib/filesystemview.php b/lib/filesystemview.php index 95873bd87cf..ac5a0a3bff5 100644 --- a/lib/filesystemview.php +++ b/lib/filesystemview.php @@ -136,15 +136,16 @@ class OC_FilesystemView { return $this->basicOperation('filesize',$path); } public function readfile($path){ + @ob_end_clean(); $handle=$this->fopen($path,'r'); if ($handle) { - $chunkSize = 1024*1024;// 1 MB chunks + $chunkSize = 8*1024;// 1 MB chunks while (!feof($handle)) { echo fread($handle, $chunkSize); - @ob_flush(); flush(); } - return $this->filesize($path); + $size=$this->filesize($path); + return $size; } return false; } @@ -174,11 +175,23 @@ class OC_FilesystemView { } public function file_put_contents($path,$data){ if(is_resource($data)){//not having to deal with streams in file_put_contents makes life easier + $exists=$this->file_exists($path); + $run=true; + if(!$exists){ + OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_create, array( OC_Filesystem::signal_param_path => $path, OC_Filesystem::signal_param_run => &$run)); + } + OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_write, array( OC_Filesystem::signal_param_path => $path, OC_Filesystem::signal_param_run => &$run)); + if(!$run){ + return false; + } $target=$this->fopen($path,'w'); if($target){ $count=OC_Helper::streamCopy($data,$target); fclose($target); fclose($data); + if(!$exists){ + OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_create, array( OC_Filesystem::signal_param_path => $path)); + } OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_write, array( OC_Filesystem::signal_param_path => $path)); return $count>0; }else{ diff --git a/lib/helper.php b/lib/helper.php index 1d9862bf8b1..c5af76dbe52 100755 --- a/lib/helper.php +++ b/lib/helper.php @@ -569,14 +569,22 @@ class OC_Helper { return false; } if($realpath_sub && $realpath_sub != '' && $realpath_parent && $realpath_parent != ''){ - if(substr($sub, 0, strlen($parent)) == $parent){ + if(substr($realpath_sub, 0, strlen($realpath_parent)) == $realpath_parent){ return true; } }else{ - if(substr($realpath_sub, 0, strlen($realpath_parent)) == $realpath_parent){ + if(substr($sub, 0, strlen($parent)) == $parent){ return true; } } + /* + echo 'SUB: ' . $sub . "\n"; + echo 'PAR: ' . $parent . "\n"; + echo 'REALSUB: ' . $realpath_sub . "\n"; + echo 'REALPAR: ' . $realpath_parent . "\n"; + echo substr($realpath_sub, 0, strlen($realpath_parent)); + exit; + */ return false; } } diff --git a/lib/vobject.php b/lib/vobject.php index e3479fc6d36..ec80e1d605a 100644 --- a/lib/vobject.php +++ b/lib/vobject.php @@ -41,7 +41,7 @@ class OC_VObject{ */ public static function parse($data){ try { - Sabre_VObject_Reader::$elementMap['LAST-MODIFIED'] = 'Sabre_VObject_Element_DateTime'; + Sabre_VObject_Property::$classMap['LAST-MODIFIED'] = 'Sabre_VObject_Property_DateTime'; $vobject = Sabre_VObject_Reader::read($data); if ($vobject instanceof Sabre_VObject_Component){ $vobject = new OC_VObject($vobject); @@ -150,12 +150,12 @@ class OC_VObject{ * @param int $dateType * @return void */ - public function setDateTime($name, $datetime, $dateType=Sabre_VObject_Element_DateTime::LOCALTZ){ + public function setDateTime($name, $datetime, $dateType=Sabre_VObject_Property_DateTime::LOCALTZ){ if ($datetime == 'now'){ $datetime = new DateTime(); } if ($datetime instanceof DateTime){ - $datetime_element = new Sabre_VObject_Element_DateTime($name); + $datetime_element = new Sabre_VObject_Property_DateTime($name); $datetime_element->setDateTime($datetime, $dateType); $this->vobject->__set($name, $datetime_element); }else{ diff --git a/settings/templates/help.php b/settings/templates/help.php index df640d97469..f9eb8615972 100644 --- a/settings/templates/help.php +++ b/settings/templates/help.php @@ -6,6 +6,7 @@ <div id="controls"> <a class="button newquestion" href="http://owncloud.org/support" target="_blank"><?php echo $l->t( 'Documentation' ); ?></a> + <a class="button newquestion" href="http://owncloud.org/support/big-files" target="_blank"><?php echo $l->t( 'Managing Big Files' ); ?></a> <a class="button newquestion" href="http://apps.owncloud.com/knowledgebase/editquestion.php?action=new" target="_blank"><?php echo $l->t( 'Ask a question' ); ?></a> <?php $url=OC_Helper::linkTo( "settings", "help.php" ).'?page='; |