From dcfbbf3db7761b88b8ca801454e90e738a98ec14 Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Sat, 13 Oct 2012 22:29:57 +0200 Subject: [PATCH] Revert "Update SabreDAV to 1.7.1" This reverts commit 183cc22501b75ab8819971f70b88dbc010026ac1. --- 3rdparty/Sabre/CalDAV/Backend/Abstract.php | 190 +-- .../Sabre/CalDAV/Backend/BackendInterface.php | 231 ---- .../CalDAV/Backend/NotificationSupport.php | 47 - 3rdparty/Sabre/CalDAV/Backend/PDO.php | 337 +----- .../Sabre/CalDAV/Backend/SharingSupport.php | 238 ---- 3rdparty/Sabre/CalDAV/Calendar.php | 63 +- 3rdparty/Sabre/CalDAV/CalendarObject.php | 22 +- 3rdparty/Sabre/CalDAV/CalendarQueryParser.php | 12 +- .../Sabre/CalDAV/CalendarQueryValidator.php | 28 +- 3rdparty/Sabre/CalDAV/CalendarRootNode.php | 13 +- .../CalDAV/Exception/InvalidComponentType.php | 32 - 3rdparty/Sabre/CalDAV/ICSExportPlugin.php | 6 +- 3rdparty/Sabre/CalDAV/ICalendar.php | 21 +- 3rdparty/Sabre/CalDAV/IShareableCalendar.php | 48 - 3rdparty/Sabre/CalDAV/ISharedCalendar.php | 22 - .../Sabre/CalDAV/Notifications/Collection.php | 169 --- .../CalDAV/Notifications/ICollection.php | 22 - 3rdparty/Sabre/CalDAV/Notifications/INode.php | 38 - .../Notifications/INotificationType.php | 43 - 3rdparty/Sabre/CalDAV/Notifications/Node.php | 188 --- .../Notifications/Notification/Invite.php | 276 ----- .../Notification/InviteReply.php | 216 ---- .../Notification/SystemStatus.php | 179 --- 3rdparty/Sabre/CalDAV/Plugin.php | 579 ++------- .../CalDAV/Property/AllowedSharingModes.php | 72 -- 3rdparty/Sabre/CalDAV/Property/Invite.php | 173 --- .../Property/ScheduleCalendarTransp.php | 99 -- 3rdparty/Sabre/CalDAV/Schedule/IMip.php | 18 +- 3rdparty/Sabre/CalDAV/Schedule/Outbox.php | 10 +- 3rdparty/Sabre/CalDAV/Server.php | 68 ++ 3rdparty/Sabre/CalDAV/ShareableCalendar.php | 72 -- 3rdparty/Sabre/CalDAV/SharedCalendar.php | 98 -- 3rdparty/Sabre/CalDAV/SharingPlugin.php | 475 -------- 3rdparty/Sabre/CalDAV/UserCalendars.php | 64 +- 3rdparty/Sabre/CalDAV/Version.php | 2 +- 3rdparty/Sabre/CalDAV/includes.php | 25 +- 3rdparty/Sabre/CardDAV/AddressBook.php | 4 +- 3rdparty/Sabre/CardDAV/Card.php | 16 +- 3rdparty/Sabre/CardDAV/Plugin.php | 55 +- 3rdparty/Sabre/CardDAV/VCFExportPlugin.php | 107 -- 3rdparty/Sabre/CardDAV/Version.php | 2 +- 3rdparty/Sabre/CardDAV/includes.php | 1 - 3rdparty/Sabre/DAV/Browser/Plugin.php | 2 +- 3rdparty/Sabre/DAV/Client.php | 69 +- 3rdparty/Sabre/DAV/Collection.php | 6 +- 3rdparty/Sabre/DAV/Directory.php | 17 + ...Supported.php => ReportNotImplemented.php} | 4 +- 3rdparty/Sabre/DAV/FS/Directory.php | 5 +- 3rdparty/Sabre/DAV/FSExt/Directory.php | 5 +- 3rdparty/Sabre/DAV/FSExt/File.php | 32 +- 3rdparty/Sabre/DAV/ICollection.php | 5 +- 3rdparty/Sabre/DAV/IFile.php | 2 +- 3rdparty/Sabre/DAV/Locks/Plugin.php | 1 - 3rdparty/Sabre/DAV/Node.php | 2 +- 3rdparty/Sabre/DAV/ObjectTree.php | 26 +- 3rdparty/Sabre/DAV/PartialUpdate/IFile.php | 38 - 3rdparty/Sabre/DAV/PartialUpdate/Plugin.php | 209 ---- 3rdparty/Sabre/DAV/Property.php | 12 +- 3rdparty/Sabre/DAV/Property/Href.php | 2 +- 3rdparty/Sabre/DAV/Property/HrefList.php | 2 +- 3rdparty/Sabre/DAV/Property/Response.php | 2 +- 3rdparty/Sabre/DAV/PropertyInterface.php | 21 - 3rdparty/Sabre/DAV/Server.php | 175 +-- 3rdparty/Sabre/DAV/ServerPlugin.php | 2 +- 3rdparty/Sabre/DAV/SimpleCollection.php | 5 +- 3rdparty/Sabre/DAV/SimpleDirectory.php | 21 + 3rdparty/Sabre/DAV/Version.php | 2 +- 3rdparty/Sabre/DAV/XMLUtil.php | 29 +- 3rdparty/Sabre/DAV/includes.php | 27 +- .../DAVACL/AbstractPrincipalCollection.php | 2 +- 3rdparty/Sabre/DAVACL/IACL.php | 2 +- 3rdparty/Sabre/DAVACL/Plugin.php | 54 +- 3rdparty/Sabre/DAVACL/Property/Acl.php | 10 +- 3rdparty/Sabre/DAVACL/Property/Principal.php | 4 +- 3rdparty/Sabre/DAVACL/Version.php | 2 +- 3rdparty/Sabre/HTTP/Request.php | 2 +- 3rdparty/Sabre/HTTP/Response.php | 7 +- 3rdparty/Sabre/HTTP/Version.php | 2 +- 3rdparty/Sabre/VObject/Component.php | 365 ++++++ 3rdparty/Sabre/VObject/Component/VAlarm.php | 102 ++ .../Sabre/VObject/Component/VCalendar.php | 133 +++ 3rdparty/Sabre/VObject/Component/VEvent.php | 71 ++ 3rdparty/Sabre/VObject/Component/VJournal.php | 46 + 3rdparty/Sabre/VObject/Component/VTodo.php | 68 ++ 3rdparty/Sabre/VObject/DateTimeParser.php | 181 +++ 3rdparty/Sabre/VObject/Element.php | 16 + 3rdparty/Sabre/VObject/Element/DateTime.php | 37 + .../Sabre/VObject/Element/MultiDateTime.php | 17 + 3rdparty/Sabre/VObject/ElementList.php | 172 +++ 3rdparty/Sabre/VObject/FreeBusyGenerator.php | 297 +++++ 3rdparty/Sabre/VObject/Node.php | 149 +++ 3rdparty/Sabre/VObject/Parameter.php | 84 ++ 3rdparty/Sabre/VObject/ParseException.php | 12 + 3rdparty/Sabre/VObject/Property.php | 348 ++++++ 3rdparty/Sabre/VObject/Property/DateTime.php | 260 ++++ .../Sabre/VObject/Property/MultiDateTime.php | 166 +++ 3rdparty/Sabre/VObject/Reader.php | 183 +++ 3rdparty/Sabre/VObject/RecurrenceIterator.php | 1043 +++++++++++++++++ 3rdparty/Sabre/VObject/Version.php | 24 + 3rdparty/Sabre/VObject/WindowsTimezoneMap.php | 128 ++ 3rdparty/Sabre/VObject/includes.php | 41 + 3rdparty/Sabre/autoload.php | 28 +- 102 files changed, 4502 insertions(+), 4658 deletions(-) delete mode 100755 3rdparty/Sabre/CalDAV/Backend/BackendInterface.php delete mode 100755 3rdparty/Sabre/CalDAV/Backend/NotificationSupport.php delete mode 100755 3rdparty/Sabre/CalDAV/Backend/SharingSupport.php delete mode 100755 3rdparty/Sabre/CalDAV/Exception/InvalidComponentType.php delete mode 100755 3rdparty/Sabre/CalDAV/IShareableCalendar.php delete mode 100755 3rdparty/Sabre/CalDAV/ISharedCalendar.php delete mode 100755 3rdparty/Sabre/CalDAV/Notifications/Collection.php delete mode 100755 3rdparty/Sabre/CalDAV/Notifications/ICollection.php delete mode 100755 3rdparty/Sabre/CalDAV/Notifications/INode.php delete mode 100755 3rdparty/Sabre/CalDAV/Notifications/INotificationType.php delete mode 100755 3rdparty/Sabre/CalDAV/Notifications/Node.php delete mode 100755 3rdparty/Sabre/CalDAV/Notifications/Notification/Invite.php delete mode 100755 3rdparty/Sabre/CalDAV/Notifications/Notification/InviteReply.php delete mode 100755 3rdparty/Sabre/CalDAV/Notifications/Notification/SystemStatus.php delete mode 100755 3rdparty/Sabre/CalDAV/Property/AllowedSharingModes.php delete mode 100755 3rdparty/Sabre/CalDAV/Property/Invite.php delete mode 100755 3rdparty/Sabre/CalDAV/Property/ScheduleCalendarTransp.php create mode 100755 3rdparty/Sabre/CalDAV/Server.php delete mode 100755 3rdparty/Sabre/CalDAV/ShareableCalendar.php delete mode 100755 3rdparty/Sabre/CalDAV/SharedCalendar.php delete mode 100755 3rdparty/Sabre/CalDAV/SharingPlugin.php delete mode 100755 3rdparty/Sabre/CardDAV/VCFExportPlugin.php create mode 100755 3rdparty/Sabre/DAV/Directory.php rename 3rdparty/Sabre/DAV/Exception/{ReportNotSupported.php => ReportNotImplemented.php} (87%) delete mode 100755 3rdparty/Sabre/DAV/PartialUpdate/IFile.php delete mode 100755 3rdparty/Sabre/DAV/PartialUpdate/Plugin.php delete mode 100755 3rdparty/Sabre/DAV/PropertyInterface.php create mode 100755 3rdparty/Sabre/DAV/SimpleDirectory.php create mode 100755 3rdparty/Sabre/VObject/Component.php create mode 100755 3rdparty/Sabre/VObject/Component/VAlarm.php create mode 100755 3rdparty/Sabre/VObject/Component/VCalendar.php create mode 100755 3rdparty/Sabre/VObject/Component/VEvent.php create mode 100755 3rdparty/Sabre/VObject/Component/VJournal.php create mode 100755 3rdparty/Sabre/VObject/Component/VTodo.php create mode 100755 3rdparty/Sabre/VObject/DateTimeParser.php create mode 100755 3rdparty/Sabre/VObject/Element.php create mode 100755 3rdparty/Sabre/VObject/Element/DateTime.php create mode 100755 3rdparty/Sabre/VObject/Element/MultiDateTime.php create mode 100755 3rdparty/Sabre/VObject/ElementList.php create mode 100755 3rdparty/Sabre/VObject/FreeBusyGenerator.php create mode 100755 3rdparty/Sabre/VObject/Node.php create mode 100755 3rdparty/Sabre/VObject/Parameter.php create mode 100755 3rdparty/Sabre/VObject/ParseException.php create mode 100755 3rdparty/Sabre/VObject/Property.php create mode 100755 3rdparty/Sabre/VObject/Property/DateTime.php create mode 100755 3rdparty/Sabre/VObject/Property/MultiDateTime.php create mode 100755 3rdparty/Sabre/VObject/Reader.php create mode 100755 3rdparty/Sabre/VObject/RecurrenceIterator.php create mode 100755 3rdparty/Sabre/VObject/Version.php create mode 100755 3rdparty/Sabre/VObject/WindowsTimezoneMap.php create mode 100755 3rdparty/Sabre/VObject/includes.php diff --git a/3rdparty/Sabre/CalDAV/Backend/Abstract.php b/3rdparty/Sabre/CalDAV/Backend/Abstract.php index 88e5b4a1a07..7aba1d69ffe 100755 --- a/3rdparty/Sabre/CalDAV/Backend/Abstract.php +++ b/3rdparty/Sabre/CalDAV/Backend/Abstract.php @@ -1,19 +1,47 @@ getCalendarObjects($calendarId); - - $validator = new Sabre_CalDAV_CalendarQueryValidator(); - - foreach($objects as $object) { - - if ($this->validateFilterForObject($object, $filters)) { - $result[] = $object['uri']; - } - - } - - return $result; - - } + abstract function getCalendarObject($calendarId,$objectUri); /** - * This method validates if a filters (as passed to calendarQuery) matches - * the given object. + * Creates a new calendar object. * - * @param array $object - * @param array $filter - * @return bool + * @param string $calendarId + * @param string $objectUri + * @param string $calendarData + * @return void */ - protected function validateFilterForObject(array $object, array $filters) { - - // Unfortunately, setting the 'calendardata' here is optional. If - // it was excluded, we actually need another call to get this as - // well. - if (!isset($object['calendardata'])) { - $object = $this->getCalendarObject($object['calendarid'], $object['uri']); - } - - $data = is_resource($object['calendardata'])?stream_get_contents($object['calendardata']):$object['calendardata']; - $vObject = VObject\Reader::read($data); + abstract function createCalendarObject($calendarId,$objectUri,$calendarData); - $validator = new Sabre_CalDAV_CalendarQueryValidator(); - return $validator->validate($vObject, $filters); - - } + /** + * 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 + * @return void + */ + abstract function deleteCalendarObject($calendarId,$objectUri); } diff --git a/3rdparty/Sabre/CalDAV/Backend/BackendInterface.php b/3rdparty/Sabre/CalDAV/Backend/BackendInterface.php deleted file mode 100755 index 881538ab60e..00000000000 --- a/3rdparty/Sabre/CalDAV/Backend/BackendInterface.php +++ /dev/null @@ -1,231 +0,0 @@ - array( - * '{DAV:}displayname' => null, - * ), - * 424 => array( - * '{DAV:}owner' => null, - * ) - * ) - * - * 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 mixed $calendarId - * @param array $mutations - * @return bool|array - */ - public function updateCalendar($calendarId, array $mutations); - - /** - * Delete a calendar and all it's objects - * - * @param mixed $calendarId - * @return void - */ - public function deleteCalendar($calendarId); - - /** - * 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 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.: - * ' "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 - * speed reasons. - * - * The calendardata is also optional. If it's not returned - * 'getCalendarObject' will be called later, which *is* expected to return - * calendardata. - * - * 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 mixed $calendarId - * @return array - */ - public function getCalendarObjects($calendarId); - - /** - * Returns information from a single calendar object, based on it's object - * uri. - * - * The returned array must have the same keys as getCalendarObjects. The - * 'calendardata' object is required here though, while it's not required - * for getCalendarObjects. - * - * @param mixed $calendarId - * @param string $objectUri - * @return array - */ - public function getCalendarObject($calendarId,$objectUri); - - /** - * Creates a new calendar object. - * - * It is possible return an etag from this function, which will be used in - * the response to this PUT request. Note that the ETag must be surrounded - * by double-quotes. - * - * However, you should only really return this ETag if you don't mangle the - * calendar-data. If the result of a subsequent GET to this object is not - * the exact same as this request body, you should omit the ETag. - * - * @param mixed $calendarId - * @param string $objectUri - * @param string $calendarData - * @return string|null - */ - public function createCalendarObject($calendarId,$objectUri,$calendarData); - - /** - * Updates an existing calendarobject, based on it's uri. - * - * It is possible return an etag from this function, which will be used in - * the response to this PUT request. Note that the ETag must be surrounded - * by double-quotes. - * - * However, you should only really return this ETag if you don't mangle the - * calendar-data. If the result of a subsequent GET to this object is not - * the exact same as this request body, you should omit the ETag. - * - * @param mixed $calendarId - * @param string $objectUri - * @param string $calendarData - * @return string|null - */ - public function updateCalendarObject($calendarId,$objectUri,$calendarData); - - /** - * Deletes an existing calendar object. - * - * @param mixed $calendarId - * @param string $objectUri - * @return void - */ - public function deleteCalendarObject($calendarId,$objectUri); - - /** - * Performs a calendar-query on the contents of this calendar. - * - * The calendar-query is defined in RFC4791 : CalDAV. Using the - * calendar-query it is possible for a client to request a specific set of - * object, based on contents of iCalendar properties, date-ranges and - * iCalendar component types (VTODO, VEVENT). - * - * This method should just return a list of (relative) urls that match this - * query. - * - * The list of filters are specified as an array. The exact array is - * documented by Sabre_CalDAV_CalendarQueryParser. - * - * Note that it is extremely likely that getCalendarObject for every path - * returned from this method will be called almost immediately after. You - * may want to anticipate this to speed up these requests. - * - * This method provides a default implementation, which parses *all* the - * iCalendar objects in the specified calendar. - * - * This default may well be good enough for personal use, and calendars - * that aren't very large. But if you anticipate high usage, big calendars - * or high loads, you are strongly adviced to optimize certain paths. - * - * The best way to do so is override this method and to optimize - * specifically for 'common filters'. - * - * Requests that are extremely common are: - * * requests for just VEVENTS - * * requests for just VTODO - * * requests with a time-range-filter on either VEVENT or VTODO. - * - * ..and combinations of these requests. It may not be worth it to try to - * handle every possible situation and just rely on the (relatively - * easy to use) CalendarQueryValidator to handle the rest. - * - * Note that especially time-range-filters may be difficult to parse. A - * time-range filter specified on a VEVENT must for instance also handle - * recurrence rules correctly. - * A good example of how to interprete all these filters can also simply - * be found in Sabre_CalDAV_CalendarQueryFilter. This class is as correct - * as possible, so it gives you a good idea on what type of stuff you need - * to think of. - * - * @param mixed $calendarId - * @param array $filters - * @return array - */ - public function calendarQuery($calendarId, array $filters); - -} diff --git a/3rdparty/Sabre/CalDAV/Backend/NotificationSupport.php b/3rdparty/Sabre/CalDAV/Backend/NotificationSupport.php deleted file mode 100755 index d5a1409d9b9..00000000000 --- a/3rdparty/Sabre/CalDAV/Backend/NotificationSupport.php +++ /dev/null @@ -1,47 +0,0 @@ - $row['principaluri'], '{' . 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), - '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}schedule-calendar-transp' => new Sabre_CalDAV_Property_ScheduleCalendarTransp($row['transparent']?'transparent':'opaque'), ); @@ -157,13 +142,11 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract { 'principaluri', 'uri', 'ctag', - 'transparent', ); $values = array( ':principaluri' => $principalUri, ':uri' => $calendarUri, ':ctag' => 1, - ':transparent' => 0, ); // Default value @@ -177,10 +160,6 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract { } $values[':components'] = implode(',',$properties[$sccs]->getValue()); } - $transp = '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}schedule-calendar-transp'; - if (isset($properties[$transp])) { - $values[':transparent'] = $properties[$transp]->getValue()==='transparent'; - } foreach($this->propertyMap as $xmlName=>$dbName) { if (isset($properties[$xmlName])) { @@ -246,25 +225,17 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract { foreach($mutations as $propertyName=>$propertyValue) { - switch($propertyName) { - case '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}schedule-calendar-transp' : - $fieldName = 'transparent'; - $newValues[$fieldName] = $propertyValue->getValue()==='transparent'; - break; - default : - // Checking the property map - if (!isset($this->propertyMap[$propertyName])) { - // We don't know about this property. - $hasError = true; - $result[403][$propertyName] = null; - unset($mutations[$propertyName]); - continue; - } - - $fieldName = $this->propertyMap[$propertyName]; - $newValues[$fieldName] = $propertyValue; + // We don't know about this property. + if (!isset($this->propertyMap[$propertyName])) { + $hasError = true; + $result[403][$propertyName] = null; + unset($mutations[$propertyName]); + continue; } + $fieldName = $this->propertyMap[$propertyName]; + $newValues[$fieldName] = $propertyValue; + } // If there were any errors we need to fail the request @@ -345,22 +316,9 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract { */ public function getCalendarObjects($calendarId) { - $stmt = $this->pdo->prepare('SELECT id, uri, lastmodified, etag, calendarid, size FROM '.$this->calendarObjectTableName.' WHERE calendarid = ?'); + $stmt = $this->pdo->prepare('SELECT * FROM '.$this->calendarObjectTableName.' WHERE calendarid = ?'); $stmt->execute(array($calendarId)); - - $result = array(); - foreach($stmt->fetchAll(\PDO::FETCH_ASSOC) as $row) { - $result[] = array( - 'id' => $row['id'], - 'uri' => $row['uri'], - 'lastmodified' => $row['lastmodified'], - 'etag' => '"' . $row['etag'] . '"', - 'calendarid' => $row['calendarid'], - 'size' => (int)$row['size'], - ); - } - - return $result; + return $stmt->fetchAll(); } @@ -378,166 +336,44 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract { */ public function getCalendarObject($calendarId,$objectUri) { - $stmt = $this->pdo->prepare('SELECT id, uri, lastmodified, etag, calendarid, size, calendardata FROM '.$this->calendarObjectTableName.' WHERE calendarid = ? AND uri = ?'); + $stmt = $this->pdo->prepare('SELECT * FROM '.$this->calendarObjectTableName.' WHERE calendarid = ? AND uri = ?'); $stmt->execute(array($calendarId, $objectUri)); - $row = $stmt->fetch(\PDO::FETCH_ASSOC); - - if(!$row) return null; - - return array( - 'id' => $row['id'], - 'uri' => $row['uri'], - 'lastmodified' => $row['lastmodified'], - 'etag' => '"' . $row['etag'] . '"', - 'calendarid' => $row['calendarid'], - 'size' => (int)$row['size'], - 'calendardata' => $row['calendardata'], - ); + return $stmt->fetch(); } - /** * Creates a new calendar object. * - * It is possible return an etag from this function, which will be used in - * the response to this PUT request. Note that the ETag must be surrounded - * by double-quotes. - * - * However, you should only really return this ETag if you don't mangle the - * calendar-data. If the result of a subsequent GET to this object is not - * the exact same as this request body, you should omit the ETag. - * - * @param mixed $calendarId + * @param string $calendarId * @param string $objectUri * @param string $calendarData - * @return string|null + * @return void */ public function createCalendarObject($calendarId,$objectUri,$calendarData) { - $extraData = $this->getDenormalizedData($calendarData); - - $stmt = $this->pdo->prepare('INSERT INTO '.$this->calendarObjectTableName.' (calendarid, uri, calendardata, lastmodified, etag, size, componenttype, firstoccurence, lastoccurence) VALUES (?,?,?,?,?,?,?,?,?)'); - $stmt->execute(array( - $calendarId, - $objectUri, - $calendarData, - time(), - $extraData['etag'], - $extraData['size'], - $extraData['componentType'], - $extraData['firstOccurence'], - $extraData['lastOccurence'], - )); + $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->execute(array($calendarId)); - return '"' . $extraData['etag'] . '"'; - } /** * Updates an existing calendarobject, based on it's uri. * - * It is possible return an etag from this function, which will be used in - * the response to this PUT request. Note that the ETag must be surrounded - * by double-quotes. - * - * However, you should only really return this ETag if you don't mangle the - * calendar-data. If the result of a subsequent GET to this object is not - * the exact same as this request body, you should omit the ETag. - * - * @param mixed $calendarId + * @param string $calendarId * @param string $objectUri * @param string $calendarData - * @return string|null + * @return void */ public function updateCalendarObject($calendarId,$objectUri,$calendarData) { - $extraData = $this->getDenormalizedData($calendarData); - - $stmt = $this->pdo->prepare('UPDATE '.$this->calendarObjectTableName.' SET calendardata = ?, lastmodified = ?, etag = ?, size = ?, componenttype = ?, firstoccurence = ?, lastoccurence = ? WHERE calendarid = ? AND uri = ?'); - $stmt->execute(array($calendarData,time(), $extraData['etag'], $extraData['size'], $extraData['componentType'], $extraData['firstOccurence'], $extraData['lastOccurence'] ,$calendarId,$objectUri)); + $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->execute(array($calendarId)); - return '"' . $extraData['etag'] . '"'; - - } - - /** - * Parses some information from calendar objects, used for optimized - * calendar-queries. - * - * Returns an array with the following keys: - * * etag - * * size - * * componentType - * * firstOccurence - * * lastOccurence - * - * @param string $calendarData - * @return array - */ - protected function getDenormalizedData($calendarData) { - - $vObject = VObject\Reader::read($calendarData); - $componentType = null; - $component = null; - $firstOccurence = null; - $lastOccurence = null; - foreach($vObject->getComponents() as $component) { - if ($component->name!=='VTIMEZONE') { - $componentType = $component->name; - break; - } - } - if (!$componentType) { - throw new Sabre_DAV_Exception_BadRequest('Calendar objects must have a VJOURNAL, VEVENT or VTODO component'); - } - if ($componentType === 'VEVENT') { - $firstOccurence = $component->DTSTART->getDateTime()->getTimeStamp(); - // Finding the last occurence is a bit harder - if (!isset($component->RRULE)) { - if (isset($component->DTEND)) { - $lastOccurence = $component->DTEND->getDateTime()->getTimeStamp(); - } elseif (isset($component->DURATION)) { - $endDate = clone $component->DTSTART->getDateTime(); - $endDate->add(VObject\DateTimeParser::parse($component->DURATION->value)); - $lastOccurence = $endDate->getTimeStamp(); - } elseif ($component->DTSTART->getDateType()===VObject\Property\DateTime::DATE) { - $endDate = clone $component->DTSTART->getDateTime(); - $endDate->modify('+1 day'); - $lastOccurence = $endDate->getTimeStamp(); - } else { - $lastOccurence = $firstOccurence; - } - } else { - $it = new VObject\RecurrenceIterator($vObject, (string)$component->UID); - $maxDate = new DateTime(self::MAX_DATE); - if ($it->isInfinite()) { - $lastOccurence = $maxDate->getTimeStamp(); - } else { - $end = $it->getDtEnd(); - while($it->valid() && $end < $maxDate) { - $end = $it->getDtEnd(); - $it->next(); - - } - $lastOccurence = $end->getTimeStamp(); - } - - } - } - - return array( - 'etag' => md5($calendarData), - 'size' => strlen($calendarData), - 'componentType' => $componentType, - 'firstOccurence' => $firstOccurence, - 'lastOccurence' => $lastOccurence, - ); - } /** @@ -556,132 +392,5 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract { } - /** - * Performs a calendar-query on the contents of this calendar. - * - * The calendar-query is defined in RFC4791 : CalDAV. Using the - * calendar-query it is possible for a client to request a specific set of - * object, based on contents of iCalendar properties, date-ranges and - * iCalendar component types (VTODO, VEVENT). - * - * This method should just return a list of (relative) urls that match this - * query. - * - * The list of filters are specified as an array. The exact array is - * documented by Sabre_CalDAV_CalendarQueryParser. - * - * Note that it is extremely likely that getCalendarObject for every path - * returned from this method will be called almost immediately after. You - * may want to anticipate this to speed up these requests. - * - * This method provides a default implementation, which parses *all* the - * iCalendar objects in the specified calendar. - * - * This default may well be good enough for personal use, and calendars - * that aren't very large. But if you anticipate high usage, big calendars - * or high loads, you are strongly adviced to optimize certain paths. - * - * The best way to do so is override this method and to optimize - * specifically for 'common filters'. - * - * Requests that are extremely common are: - * * requests for just VEVENTS - * * requests for just VTODO - * * requests with a time-range-filter on a VEVENT. - * - * ..and combinations of these requests. It may not be worth it to try to - * handle every possible situation and just rely on the (relatively - * easy to use) CalendarQueryValidator to handle the rest. - * - * Note that especially time-range-filters may be difficult to parse. A - * time-range filter specified on a VEVENT must for instance also handle - * recurrence rules correctly. - * A good example of how to interprete all these filters can also simply - * be found in Sabre_CalDAV_CalendarQueryFilter. This class is as correct - * as possible, so it gives you a good idea on what type of stuff you need - * to think of. - * - * This specific implementation (for the PDO) backend optimizes filters on - * specific components, and VEVENT time-ranges. - * - * @param string $calendarId - * @param array $filters - * @return array - */ - public function calendarQuery($calendarId, array $filters) { - - $result = array(); - $validator = new Sabre_CalDAV_CalendarQueryValidator(); - - $componentType = null; - $requirePostFilter = true; - $timeRange = null; - - // if no filters were specified, we don't need to filter after a query - if (!$filters['prop-filters'] && !$filters['comp-filters']) { - $requirePostFilter = false; - } - - // Figuring out if there's a component filter - if (count($filters['comp-filters']) > 0 && !$filters['comp-filters'][0]['is-not-defined']) { - $componentType = $filters['comp-filters'][0]['name']; - - // Checking if we need post-filters - if (!$filters['prop-filters'] && !$filters['comp-filters'][0]['comp-filters'] && !$filters['comp-filters'][0]['time-range'] && !$filters['comp-filters'][0]['prop-filters']) { - $requirePostFilter = false; - } - // There was a time-range filter - if ($componentType == 'VEVENT' && isset($filters['comp-filters'][0]['time-range'])) { - $timeRange = $filters['comp-filters'][0]['time-range']; - - // If start time OR the end time is not specified, we can do a - // 100% accurate mysql query. - if (!$filters['prop-filters'] && !$filters['comp-filters'][0]['comp-filters'] && !$filters['comp-filters'][0]['prop-filters'] && (!$timeRange['start'] || !$timeRange['end'])) { - $requirePostFilter = false; - } - } - } - - if ($requirePostFilter) { - $query = "SELECT uri, calendardata FROM ".$this->calendarObjectTableName." WHERE calendarid = :calendarid"; - } else { - $query = "SELECT uri FROM ".$this->calendarObjectTableName." WHERE calendarid = :calendarid"; - } - - $values = array( - 'calendarid' => $calendarId, - ); - - if ($componentType) { - $query.=" AND componenttype = :componenttype"; - $values['componenttype'] = $componentType; - } - - if ($timeRange && $timeRange['start']) { - $query.=" AND lastoccurence > :startdate"; - $values['startdate'] = $timeRange['start']->getTimeStamp(); - } - if ($timeRange && $timeRange['end']) { - $query.=" AND firstoccurence < :enddate"; - $values['enddate'] = $timeRange['end']->getTimeStamp(); - } - - $stmt = $this->pdo->prepare($query); - $stmt->execute($values); - - $result = array(); - while($row = $stmt->fetch(\PDO::FETCH_ASSOC)) { - if ($requirePostFilter) { - if (!$this->validateFilterForObject($row, $filters)) { - continue; - } - } - $result[] = $row['uri']; - - } - - return $result; - - } } diff --git a/3rdparty/Sabre/CalDAV/Backend/SharingSupport.php b/3rdparty/Sabre/CalDAV/Backend/SharingSupport.php deleted file mode 100755 index f73f0ff3d8a..00000000000 --- a/3rdparty/Sabre/CalDAV/Backend/SharingSupport.php +++ /dev/null @@ -1,238 +0,0 @@ -caldavBackend = $caldavBackend; $this->principalBackend = $principalBackend; $this->calendarInfo = $calendarInfo; + } /** @@ -91,6 +92,9 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper 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 : if (isset($this->calendarInfo[$prop])) $response[$prop] = $this->calendarInfo[$prop]; break; @@ -106,21 +110,12 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper * The contained calendar objects are for example Events or Todo's. * * @param string $name - * @return Sabre_CalDAV_ICalendarObject + * @return Sabre_DAV_ICalendarObject */ public function getChild($name) { $obj = $this->caldavBackend->getCalendarObject($this->calendarInfo['id'],$name); if (!$obj) throw new Sabre_DAV_Exception_NotFound('Calendar object not found'); - - $obj['acl'] = $this->getACL(); - // Removing the irrelivant - foreach($obj['acl'] as $key=>$acl) { - if ($acl['privilege'] === '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}read-free-busy') { - unset($obj['acl'][$key]); - } - } - return new Sabre_CalDAV_CalendarObject($this->caldavBackend,$this->calendarInfo,$obj); } @@ -135,13 +130,6 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper $objs = $this->caldavBackend->getCalendarObjects($this->calendarInfo['id']); $children = array(); foreach($objs as $obj) { - $obj['acl'] = $this->getACL(); - // Removing the irrelivant - foreach($obj['acl'] as $key=>$acl) { - if ($acl['privilege'] === '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}read-free-busy') { - unset($obj['acl'][$key]); - } - } $children[] = new Sabre_CalDAV_CalendarObject($this->caldavBackend,$this->calendarInfo,$obj); } return $children; @@ -274,27 +262,27 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper return array( array( 'privilege' => '{DAV:}read', - 'principal' => $this->getOwner(), + 'principal' => $this->calendarInfo['principaluri'], 'protected' => true, ), array( 'privilege' => '{DAV:}write', - 'principal' => $this->getOwner(), + 'principal' => $this->calendarInfo['principaluri'], 'protected' => true, ), array( 'privilege' => '{DAV:}read', - 'principal' => $this->getOwner() . '/calendar-proxy-write', + 'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write', 'protected' => true, ), array( 'privilege' => '{DAV:}write', - 'principal' => $this->getOwner() . '/calendar-proxy-write', + 'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write', 'protected' => true, ), array( 'privilege' => '{DAV:}read', - 'principal' => $this->getOwner() . '/calendar-proxy-read', + 'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-read', 'protected' => true, ), array( @@ -352,27 +340,4 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper } - /** - * Performs a calendar-query on the contents of this calendar. - * - * The calendar-query is defined in RFC4791 : CalDAV. Using the - * calendar-query it is possible for a client to request a specific set of - * object, based on contents of iCalendar properties, date-ranges and - * iCalendar component types (VTODO, VEVENT). - * - * This method should just return a list of (relative) urls that match this - * query. - * - * The list of filters are specified as an array. The exact array is - * documented by Sabre_CalDAV_CalendarQueryParser. - * - * @param array $filters - * @return array - */ - public function calendarQuery(array $filters) { - - return $this->caldavBackend->calendarQuery($this->calendarInfo['id'], $filters); - - } - } diff --git a/3rdparty/Sabre/CalDAV/CalendarObject.php b/3rdparty/Sabre/CalDAV/CalendarObject.php index 40bd8588c70..72f0a578d16 100755 --- a/3rdparty/Sabre/CalDAV/CalendarObject.php +++ b/3rdparty/Sabre/CalDAV/CalendarObject.php @@ -6,13 +6,13 @@ * @package Sabre * @subpackage CalDAV * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. - * @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 */ class Sabre_CalDAV_CalendarObject extends Sabre_DAV_File implements Sabre_CalDAV_ICalendarObject, Sabre_DAVACL_IACL { /** - * Sabre_CalDAV_Backend_BackendInterface + * Sabre_CalDAV_Backend_Abstract * * @var array */ @@ -35,11 +35,11 @@ class Sabre_CalDAV_CalendarObject extends Sabre_DAV_File implements Sabre_CalDAV /** * Constructor * - * @param Sabre_CalDAV_Backend_BackendInterface $caldavBackend + * @param Sabre_CalDAV_Backend_Abstract $caldavBackend * @param array $calendarInfo * @param array $objectData */ - public function __construct(Sabre_CalDAV_Backend_BackendInterface $caldavBackend,array $calendarInfo,array $objectData) { + public function __construct(Sabre_CalDAV_Backend_Abstract $caldavBackend,array $calendarInfo,array $objectData) { $this->caldavBackend = $caldavBackend; @@ -85,8 +85,8 @@ class Sabre_CalDAV_CalendarObject extends Sabre_DAV_File implements Sabre_CalDAV /** * Updates the ICalendar-formatted object * - * @param string|resource $calendarData - * @return string + * @param string $calendarData + * @return void */ public function put($calendarData) { @@ -119,7 +119,7 @@ class Sabre_CalDAV_CalendarObject extends Sabre_DAV_File implements Sabre_CalDAV */ public function getContentType() { - return 'text/calendar; charset=utf-8'; + return 'text/calendar'; } @@ -143,7 +143,7 @@ class Sabre_CalDAV_CalendarObject extends Sabre_DAV_File implements Sabre_CalDAV /** * Returns the last modification date as a unix timestamp * - * @return int + * @return time */ public function getLastModified() { @@ -206,12 +206,6 @@ class Sabre_CalDAV_CalendarObject extends Sabre_DAV_File implements Sabre_CalDAV */ public function getACL() { - // An alternative acl may be specified in the object data. - if (isset($this->objectData['acl'])) { - return $this->objectData['acl']; - } - - // The default ACL return array( array( 'privilege' => '{DAV:}read', diff --git a/3rdparty/Sabre/CalDAV/CalendarQueryParser.php b/3rdparty/Sabre/CalDAV/CalendarQueryParser.php index b95095f96fc..bd0d343382f 100755 --- a/3rdparty/Sabre/CalDAV/CalendarQueryParser.php +++ b/3rdparty/Sabre/CalDAV/CalendarQueryParser.php @@ -1,7 +1,5 @@ xpath = new DOMXPath($dom); $this->xpath->registerNameSpace('cal',Sabre_CalDAV_Plugin::NS_CALDAV); - $this->xpath->registerNameSpace('dav','DAV:'); + $this->xpath->registerNameSpace('dav','urn:DAV'); } @@ -243,12 +241,12 @@ class Sabre_CalDAV_CalendarQueryParser { $timeRangeNode = $timeRangeNodes->item(0); if ($start = $timeRangeNode->getAttribute('start')) { - $start = VObject\DateTimeParser::parseDateTime($start); + $start = Sabre_VObject_DateTimeParser::parseDateTime($start); } else { $start = null; } if ($end = $timeRangeNode->getAttribute('end')) { - $end = VObject\DateTimeParser::parseDateTime($end); + $end = Sabre_VObject_DateTimeParser::parseDateTime($end); } else { $end = null; } @@ -276,13 +274,13 @@ class Sabre_CalDAV_CalendarQueryParser { if(!$start) { throw new Sabre_DAV_Exception_BadRequest('The "start" attribute is required for the CALDAV:expand element'); } - $start = VObject\DateTimeParser::parseDateTime($start); + $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 = VObject\DateTimeParser::parseDateTime($end); + $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.'); diff --git a/3rdparty/Sabre/CalDAV/CalendarQueryValidator.php b/3rdparty/Sabre/CalDAV/CalendarQueryValidator.php index 53e86fc509f..8f674840e87 100755 --- a/3rdparty/Sabre/CalDAV/CalendarQueryValidator.php +++ b/3rdparty/Sabre/CalDAV/CalendarQueryValidator.php @@ -1,7 +1,5 @@ parent->name === 'VEVENT' && $component->parent->RRULE) { // Fire up the iterator! - $it = new VObject\RecurrenceIterator($component->parent->parent, (string)$component->parent->UID); + $it = new Sabre_VObject_RecurrenceIterator($component->parent->parent, (string)$component->parent->UID); while($it->valid()) { $expandedEvent = $it->getEventObject(); diff --git a/3rdparty/Sabre/CalDAV/CalendarRootNode.php b/3rdparty/Sabre/CalDAV/CalendarRootNode.php index eb62eea75a6..3907913cc78 100755 --- a/3rdparty/Sabre/CalDAV/CalendarRootNode.php +++ b/3rdparty/Sabre/CalDAV/CalendarRootNode.php @@ -1,15 +1,14 @@ caldavBackend = $caldavBackend; diff --git a/3rdparty/Sabre/CalDAV/Exception/InvalidComponentType.php b/3rdparty/Sabre/CalDAV/Exception/InvalidComponentType.php deleted file mode 100755 index 4ac617d22f0..00000000000 --- a/3rdparty/Sabre/CalDAV/Exception/InvalidComponentType.php +++ /dev/null @@ -1,32 +0,0 @@ -ownerDocument; - - $np = $doc->createElementNS(Sabre_CalDAV_Plugin::NS_CALDAV,'cal:supported-calendar-component'); - $errorNode->appendChild($np); - - } - -} \ No newline at end of file diff --git a/3rdparty/Sabre/CalDAV/ICSExportPlugin.php b/3rdparty/Sabre/CalDAV/ICSExportPlugin.php index d3e4e7b7201..ec42b406b2f 100755 --- a/3rdparty/Sabre/CalDAV/ICSExportPlugin.php +++ b/3rdparty/Sabre/CalDAV/ICSExportPlugin.php @@ -1,7 +1,5 @@ version = '2.0'; if (Sabre_DAV_Server::$exposeVersion) { $calendar->prodid = '-//SabreDAV//SabreDAV ' . Sabre_DAV_Version::VERSION . '//EN'; @@ -105,7 +103,7 @@ class Sabre_CalDAV_ICSExportPlugin extends Sabre_DAV_ServerPlugin { } $nodeData = $node[200]['{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}calendar-data']; - $nodeComp = VObject\Reader::read($nodeData); + $nodeComp = Sabre_VObject_Reader::read($nodeData); foreach($nodeComp->children() as $child) { diff --git a/3rdparty/Sabre/CalDAV/ICalendar.php b/3rdparty/Sabre/CalDAV/ICalendar.php index 40aa9f9579c..15d51ebcf79 100755 --- a/3rdparty/Sabre/CalDAV/ICalendar.php +++ b/3rdparty/Sabre/CalDAV/ICalendar.php @@ -8,28 +8,11 @@ * @package Sabre * @subpackage CalDAV * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. - * @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 */ interface Sabre_CalDAV_ICalendar extends Sabre_DAV_ICollection { - /** - * Performs a calendar-query on the contents of this calendar. - * - * The calendar-query is defined in RFC4791 : CalDAV. Using the - * calendar-query it is possible for a client to request a specific set of - * object, based on contents of iCalendar properties, date-ranges and - * iCalendar component types (VTODO, VEVENT). - * - * This method should just return a list of (relative) urls that match this - * query. - * - * The list of filters are specified as an array. The exact array is - * documented by Sabre_CalDAV_CalendarQueryParser. - * - * @param array $filters - * @return array - */ - public function calendarQuery(array $filters); + } diff --git a/3rdparty/Sabre/CalDAV/IShareableCalendar.php b/3rdparty/Sabre/CalDAV/IShareableCalendar.php deleted file mode 100755 index 5b55788c014..00000000000 --- a/3rdparty/Sabre/CalDAV/IShareableCalendar.php +++ /dev/null @@ -1,48 +0,0 @@ -caldavBackend = $caldavBackend; - $this->principalUri = $principalUri; - - } - - /** - * Returns all notifications for a principal - * - * @return array - */ - public function getChildren() { - - $children = array(); - $notifications = $this->caldavBackend->getNotificationsForPrincipal($this->principalUri); - - foreach($notifications as $notification) { - - $children[] = new Sabre_CalDAV_Notifications_Node( - $this->caldavBackend, - $this->principalUri, - $notification - ); - } - - return $children; - - } - - /** - * Returns the name of this object - * - * @return string - */ - public function getName() { - - return 'notifications'; - - } - - /** - * 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( - 'principal' => $this->getOwner(), - 'privilege' => '{DAV:}read', - 'protected' => true, - ), - array( - 'principal' => $this->getOwner(), - 'privilege' => '{DAV:}write', - 'protected' => true, - ) - ); - - } - - /** - * Updates the ACL - * - * This method will receive a list of new ACE's as an array argument. - * - * @param array $acl - * @return void - */ - public function setACL(array $acl) { - - throw new Sabre_DAV_Exception_NotImplemented('Updating ACLs is not implemented here'); - - } - - /** - * 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/Notifications/ICollection.php b/3rdparty/Sabre/CalDAV/Notifications/ICollection.php deleted file mode 100755 index eb873af3f92..00000000000 --- a/3rdparty/Sabre/CalDAV/Notifications/ICollection.php +++ /dev/null @@ -1,22 +0,0 @@ -caldavBackend = $caldavBackend; - $this->principalUri = $principalUri; - $this->notification = $notification; - - } - - /** - * Returns the path name for this notification - * - * @return id - */ - public function getName() { - - return $this->notification->getId() . '.xml'; - - } - - /** - * Returns the etag for the notification. - * - * The etag must be surrounded by litteral double-quotes. - * - * @return string - */ - public function getETag() { - - return $this->notification->getETag(); - - } - - /** - * This method must return an xml element, using the - * Sabre_CalDAV_Notifications_INotificationType classes. - * - * @return Sabre_DAVNotification_INotificationType - */ - public function getNotificationType() { - - return $this->notification; - - } - - /** - * Deletes this notification - * - * @return void - */ - public function delete() { - - $this->caldavBackend->deleteNotification($this->getOwner(), $this->notification); - - } - - /** - * 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( - 'principal' => $this->getOwner(), - 'privilege' => '{DAV:}read', - 'protected' => true, - ), - array( - 'principal' => $this->getOwner(), - 'privilege' => '{DAV:}write', - 'protected' => true, - ) - ); - - } - - /** - * Updates the ACL - * - * This method will receive a list of new ACE's as an array argument. - * - * @param array $acl - * @return void - */ - public function setACL(array $acl) { - - throw new Sabre_DAV_Exception_NotImplemented('Updating ACLs is not implemented here'); - - } - - /** - * 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/Notifications/Notification/Invite.php b/3rdparty/Sabre/CalDAV/Notifications/Notification/Invite.php deleted file mode 100755 index a6b36203f34..00000000000 --- a/3rdparty/Sabre/CalDAV/Notifications/Notification/Invite.php +++ /dev/null @@ -1,276 +0,0 @@ -$value) { - if (!property_exists($this, $key)) { - throw new InvalidArgumentException('Unknown option: ' . $key); - } - $this->$key = $value; - } - - } - - /** - * Serializes the notification as a single property. - * - * You should usually just encode the single top-level element of the - * notification. - * - * @param Sabre_DAV_Server $server - * @param DOMElement $node - * @return void - */ - public function serialize(Sabre_DAV_Server $server, \DOMElement $node) { - - $prop = $node->ownerDocument->createElement('cs:invite-notification'); - $node->appendChild($prop); - - } - - /** - * This method serializes the entire notification, as it is used in the - * response body. - * - * @param Sabre_DAV_Server $server - * @param DOMElement $node - * @return void - */ - public function serializeBody(Sabre_DAV_Server $server, \DOMElement $node) { - - $doc = $node->ownerDocument; - - $dt = $doc->createElement('cs:dtstamp'); - $this->dtStamp->setTimezone(new \DateTimezone('GMT')); - $dt->appendChild($doc->createTextNode($this->dtStamp->format('Ymd\\THis\\Z'))); - $node->appendChild($dt); - - $prop = $doc->createElement('cs:invite-notification'); - $node->appendChild($prop); - - $uid = $doc->createElement('cs:uid'); - $uid->appendChild( $doc->createTextNode($this->id) ); - $prop->appendChild($uid); - - $href = $doc->createElement('d:href'); - $href->appendChild( $doc->createTextNode( $this->href ) ); - $prop->appendChild($href); - - $nodeName = null; - switch($this->type) { - - case SharingPlugin::STATUS_ACCEPTED : - $nodeName = 'cs:invite-accepted'; - break; - case SharingPlugin::STATUS_DECLINED : - $nodeName = 'cs:invite-declined'; - break; - case SharingPlugin::STATUS_DELETED : - $nodeName = 'cs:invite-deleted'; - break; - case SharingPlugin::STATUS_NORESPONSE : - $nodeName = 'cs:invite-noresponse'; - break; - - } - $prop->appendChild( - $doc->createElement($nodeName) - ); - $hostHref = $doc->createElement('d:href', $server->getBaseUri() . $this->hostUrl); - $hostUrl = $doc->createElement('cs:hosturl'); - $hostUrl->appendChild($hostHref); - $prop->appendChild($hostUrl); - - $access = $doc->createElement('cs:access'); - if ($this->readOnly) { - $access->appendChild($doc->createElement('cs:read')); - } else { - $access->appendChild($doc->createElement('cs:read-write')); - } - $prop->appendChild($access); - - $organizerHref = $doc->createElement('d:href', $server->getBaseUri() . $this->organizer); - $organizerUrl = $doc->createElement('cs:organizer'); - if ($this->commonName) { - $commonName = $doc->createElement('cs:common-name'); - $commonName->appendChild($doc->createTextNode($this->commonName)); - $organizerUrl->appendChild($commonName); - } - $organizerUrl->appendChild($organizerHref); - $prop->appendChild($organizerUrl); - - if ($this->summary) { - $summary = $doc->createElement('cs:summary'); - $summary->appendChild($doc->createTextNode($this->summary)); - $prop->appendChild($summary); - } - if ($this->supportedComponents) { - - $xcomp = $doc->createElement('cal:supported-calendar-component-set'); - $this->supportedComponents->serialize($server, $xcomp); - $prop->appendChild($xcomp); - - } - - } - - /** - * Returns a unique id for this notification - * - * This is just the base url. This should generally be some kind of unique - * id. - * - * @return string - */ - public function getId() { - - return $this->id; - - } - - /** - * Returns the ETag for this notification. - * - * The ETag must be surrounded by literal double-quotes. - * - * @return string - */ - public function getETag() { - - return $this->etag; - - } - -} diff --git a/3rdparty/Sabre/CalDAV/Notifications/Notification/InviteReply.php b/3rdparty/Sabre/CalDAV/Notifications/Notification/InviteReply.php deleted file mode 100755 index e935aa5aa11..00000000000 --- a/3rdparty/Sabre/CalDAV/Notifications/Notification/InviteReply.php +++ /dev/null @@ -1,216 +0,0 @@ -$value) { - if (!property_exists($this, $key)) { - throw new InvalidArgumentException('Unknown option: ' . $key); - } - $this->$key = $value; - } - - } - - /** - * Serializes the notification as a single property. - * - * You should usually just encode the single top-level element of the - * notification. - * - * @param Sabre_DAV_Server $server - * @param DOMElement $node - * @return void - */ - public function serialize(Sabre_DAV_Server $server, \DOMElement $node) { - - $prop = $node->ownerDocument->createElement('cs:invite-reply'); - $node->appendChild($prop); - - } - - /** - * This method serializes the entire notification, as it is used in the - * response body. - * - * @param Sabre_DAV_Server $server - * @param DOMElement $node - * @return void - */ - public function serializeBody(Sabre_DAV_Server $server, \DOMElement $node) { - - $doc = $node->ownerDocument; - - $dt = $doc->createElement('cs:dtstamp'); - $this->dtStamp->setTimezone(new \DateTimezone('GMT')); - $dt->appendChild($doc->createTextNode($this->dtStamp->format('Ymd\\THis\\Z'))); - $node->appendChild($dt); - - $prop = $doc->createElement('cs:invite-reply'); - $node->appendChild($prop); - - $uid = $doc->createElement('cs:uid'); - $uid->appendChild($doc->createTextNode($this->id)); - $prop->appendChild($uid); - - $inReplyTo = $doc->createElement('cs:in-reply-to'); - $inReplyTo->appendChild( $doc->createTextNode($this->inReplyTo) ); - $prop->appendChild($inReplyTo); - - $href = $doc->createElement('d:href'); - $href->appendChild( $doc->createTextNode($this->href) ); - $prop->appendChild($href); - - $nodeName = null; - switch($this->type) { - - case SharingPlugin::STATUS_ACCEPTED : - $nodeName = 'cs:invite-accepted'; - break; - case SharingPlugin::STATUS_DECLINED : - $nodeName = 'cs:invite-declined'; - break; - - } - $prop->appendChild( - $doc->createElement($nodeName) - ); - $hostHref = $doc->createElement('d:href', $server->getBaseUri() . $this->hostUrl); - $hostUrl = $doc->createElement('cs:hosturl'); - $hostUrl->appendChild($hostHref); - $prop->appendChild($hostUrl); - - if ($this->summary) { - $summary = $doc->createElement('cs:summary'); - $summary->appendChild($doc->createTextNode($this->summary)); - $prop->appendChild($summary); - } - - } - - /** - * Returns a unique id for this notification - * - * This is just the base url. This should generally be some kind of unique - * id. - * - * @return string - */ - public function getId() { - - return $this->id; - - } - - /** - * Returns the ETag for this notification. - * - * The ETag must be surrounded by literal double-quotes. - * - * @return string - */ - public function getETag() { - - return $this->etag; - - } -} diff --git a/3rdparty/Sabre/CalDAV/Notifications/Notification/SystemStatus.php b/3rdparty/Sabre/CalDAV/Notifications/Notification/SystemStatus.php deleted file mode 100755 index f09ed3525f5..00000000000 --- a/3rdparty/Sabre/CalDAV/Notifications/Notification/SystemStatus.php +++ /dev/null @@ -1,179 +0,0 @@ -id = $id; - $this->type = $type; - $this->description = $description; - $this->href = $href; - $this->etag = $etag; - - } - - /** - * Serializes the notification as a single property. - * - * You should usually just encode the single top-level element of the - * notification. - * - * @param Sabre_DAV_Server $server - * @param DOMElement $node - * @return void - */ - public function serialize(Sabre_DAV_Server $server, \DOMElement $node) { - - switch($this->type) { - case self::TYPE_LOW : - $type = 'low'; - break; - case self::TYPE_MEDIUM : - $type = 'medium'; - break; - default : - case self::TYPE_HIGH : - $type = 'high'; - break; - } - - $prop = $node->ownerDocument->createElement('cs:systemstatus'); - $prop->setAttribute('type', $type); - - $node->appendChild($prop); - - } - - /** - * This method serializes the entire notification, as it is used in the - * response body. - * - * @param Sabre_DAV_Server $server - * @param DOMElement $node - * @return void - */ - public function serializeBody(Sabre_DAV_Server $server, \DOMElement $node) { - - switch($this->type) { - case self::TYPE_LOW : - $type = 'low'; - break; - case self::TYPE_MEDIUM : - $type = 'medium'; - break; - default : - case self::TYPE_HIGH : - $type = 'high'; - break; - } - - $prop = $node->ownerDocument->createElement('cs:systemstatus'); - $prop->setAttribute('type', $type); - - if ($this->description) { - $text = $node->ownerDocument->createTextNode($this->description); - $desc = $node->ownerDocument->createElement('cs:description'); - $desc->appendChild($text); - $prop->appendChild($desc); - } - if ($this->href) { - $text = $node->ownerDocument->createTextNode($this->href); - $href = $node->ownerDocument->createElement('d:href'); - $href->appendChild($text); - $prop->appendChild($href); - } - - $node->appendChild($prop); - - } - - /** - * Returns a unique id for this notification - * - * This is just the base url. This should generally be some kind of unique - * id. - * - * @return string - */ - public function getId() { - - return $this->id; - - } - - /* - * Returns the ETag for this notification. - * - * The ETag must be surrounded by literal double-quotes. - * - * @return string - */ - public function getETag() { - - return $this->etag; - - } -} diff --git a/3rdparty/Sabre/CalDAV/Plugin.php b/3rdparty/Sabre/CalDAV/Plugin.php index f3d11969c8b..c56ab384844 100755 --- a/3rdparty/Sabre/CalDAV/Plugin.php +++ b/3rdparty/Sabre/CalDAV/Plugin.php @@ -1,7 +1,5 @@ subscribeEvent('onBrowserPostAction', array($this,'browserPostAction')); $server->subscribeEvent('beforeWriteContent', array($this, 'beforeWriteContent')); $server->subscribeEvent('beforeCreateFile', array($this, 'beforeCreateFile')); - $server->subscribeEvent('beforeMethod', array($this,'beforeMethod')); $server->xmlNamespaces[self::NS_CALDAV] = 'cal'; $server->xmlNamespaces[self::NS_CALENDARSERVER] = 'cs'; $server->propertyMap['{' . self::NS_CALDAV . '}supported-calendar-component-set'] = 'Sabre_CalDAV_Property_SupportedCalendarComponentSet'; - $server->propertyMap['{' . self::NS_CALDAV . '}schedule-calendar-transp'] = 'Sabre_CalDAV_Property_ScheduleCalendarTransp'; $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'; - $server->resourceTypeMapping['Sabre_CalDAV_Notifications_ICollection'] = '{' . self::NS_CALENDARSERVER . '}notification'; array_push($server->protectedProperties, @@ -200,9 +205,7 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { // CalendarServer extensions '{' . self::NS_CALENDARSERVER . '}getctag', '{' . self::NS_CALENDARSERVER . '}calendar-proxy-read-for', - '{' . self::NS_CALENDARSERVER . '}calendar-proxy-write-for', - '{' . self::NS_CALENDARSERVER . '}notification-URL', - '{' . self::NS_CALENDARSERVER . '}notificationtype' + '{' . self::NS_CALENDARSERVER . '}calendar-proxy-write-for' ); } @@ -223,13 +226,6 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { // unknownMethod event. return false; case 'POST' : - - // Checking if this is a text/calendar content type - $contentType = $this->server->httpRequest->getHeader('Content-Type'); - if (strpos($contentType, 'text/calendar')!==0) { - return; - } - // Checking if we're talking to an outbox try { $node = $this->server->tree->getNodeForPath($uri); @@ -239,7 +235,7 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { if (!$node instanceof Sabre_CalDAV_Schedule_IOutbox) return; - $this->outboxRequest($node, $uri); + $this->outboxRequest($node); return false; } @@ -352,7 +348,7 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { if (in_array($calProp,$requestedProperties)) { $addresses = $node->getAlternateUriSet(); - $addresses[] = $this->server->getBaseUri() . $node->getPrincipalUrl() . '/'; + $addresses[] = $this->server->getBaseUri() . $node->getPrincipalUrl(); unset($requestedProperties[$calProp]); $returnedProperties[200][$calProp] = new Sabre_DAV_Property_HrefList($addresses, false); @@ -394,31 +390,8 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { } - // notification-URL property - $notificationUrl = '{' . self::NS_CALENDARSERVER . '}notification-URL'; - if (($index = array_search($notificationUrl, $requestedProperties)) !== false) { - $principalId = $node->getName(); - $calendarHomePath = 'calendars/' . $principalId . '/notifications/'; - unset($requestedProperties[$index]); - $returnedProperties[200][$notificationUrl] = new Sabre_DAV_Property_Href($calendarHomePath); - } - } // instanceof IPrincipal - if ($node instanceof Sabre_CalDAV_Notifications_INode) { - - $propertyName = '{' . self::NS_CALENDARSERVER . '}notificationtype'; - if (($index = array_search($propertyName, $requestedProperties)) !== false) { - - $returnedProperties[200][$propertyName] = - $node->getNotificationType(); - - unset($requestedProperties[$index]); - - } - - } // instanceof Notifications_INode - if ($node instanceof Sabre_CalDAV_ICalendarObject) { // The calendar-data property is not supposed to be a 'real' @@ -451,11 +424,11 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { public function calendarMultiGetReport($dom) { $properties = array_keys(Sabre_DAV_XMLUtil::parseProperties($dom->firstChild)); - $hrefElems = $dom->getElementsByTagNameNS('DAV:','href'); + $hrefElems = $dom->getElementsByTagNameNS('urn:DAV','href'); $xpath = new DOMXPath($dom); $xpath->registerNameSpace('cal',Sabre_CalDAV_Plugin::NS_CALDAV); - $xpath->registerNameSpace('dav','DAV:'); + $xpath->registerNameSpace('dav','urn:DAV'); $expand = $xpath->query('/cal:calendar-multiget/dav:prop/cal:calendar-data/cal:expand'); if ($expand->length>0) { @@ -465,8 +438,8 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { if(!$start || !$end) { throw new Sabre_DAV_Exception_BadRequest('The "start" and "end" attributes are required for the CALDAV:expand element'); } - $start = VObject\DateTimeParser::parseDateTime($start); - $end = VObject\DateTimeParser::parseDateTime($end); + $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.'); @@ -485,7 +458,7 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { list($objProps) = $this->server->getPropertiesForPath($uri,$properties); if ($expand && isset($objProps[200]['{' . self::NS_CALDAV . '}calendar-data'])) { - $vObject = VObject\Reader::read($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(); } @@ -494,12 +467,9 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { } - $prefer = $this->server->getHTTPPRefer(); - $this->server->httpResponse->sendStatus(207); $this->server->httpResponse->setHeader('Content-Type','application/xml; charset=utf-8'); - $this->server->httpResponse->setHeader('Vary','Brief,Prefer'); - $this->server->httpResponse->sendBody($this->server->generateMultiStatus($propertyList, $prefer['return-minimal'])); + $this->server->httpResponse->sendBody($this->server->generateMultiStatus($propertyList)); } @@ -517,95 +487,54 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { $parser = new Sabre_CalDAV_CalendarQueryParser($dom); $parser->parse(); - $node = $this->server->tree->getNodeForPath($this->server->getRequestUri()); - $depth = $this->server->getHTTPDepth(0); - - // The default result is an empty array - $result = array(); + $requestedCalendarData = true; + $requestedProperties = $parser->requestedProperties; - // The calendarobject was requested directly. In this case we handle - // this locally. - if ($depth == 0 && $node instanceof Sabre_CalDAV_ICalendarObject) { + if (!in_array('{urn:ietf:params:xml:ns:caldav}calendar-data', $requestedProperties)) { - $requestedCalendarData = true; - $requestedProperties = $parser->requestedProperties; + // We always retrieve calendar-data, as we need it for filtering. + $requestedProperties[] = '{urn:ietf:params:xml:ns:caldav}calendar-data'; - 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 - // it after processing. - $requestedCalendarData = false; - } + // If calendar-data wasn't explicitly requested, we need to remove + // it after processing. + $requestedCalendarData = false; + } - $properties = $this->server->getPropertiesForPath( - $this->server->getRequestUri(), - $requestedProperties, - 0 - ); + // These are the list of nodes that potentially match the requirement + $candidateNodes = $this->server->getPropertiesForPath( + $this->server->getRequestUri(), + $requestedProperties, + $this->server->getHTTPDepth(0) + ); - // This array should have only 1 element, the first calendar - // object. - $properties = current($properties); + $verifiedNodes = array(); - // If there wasn't any calendar-data returned somehow, we ignore - // this. - if (isset($properties[200]['{urn:ietf:params:xml:ns:caldav}calendar-data'])) { + $validator = new Sabre_CalDAV_CalendarQueryValidator(); - $validator = new Sabre_CalDAV_CalendarQueryValidator(); - $vObject = VObject\Reader::read($properties[200]['{urn:ietf:params:xml:ns:caldav}calendar-data']); - if ($validator->validate($vObject,$parser->filters)) { + foreach($candidateNodes as $node) { - // If the client didn't require the calendar-data property, - // we won't give it back. - if (!$requestedCalendarData) { - unset($properties[200]['{urn:ietf:params:xml:ns:caldav}calendar-data']); - } else { - if ($parser->expand) { - $vObject->expand($parser->expand['start'], $parser->expand['end']); - $properties[200]['{' . self::NS_CALDAV . '}calendar-data'] = $vObject->serialize(); - } - } + // 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; - $result = array($properties); + $vObject = Sabre_VObject_Reader::read($node[200]['{urn:ietf:params:xml:ns:caldav}calendar-data']); + if ($validator->validate($vObject,$parser->filters)) { + if (!$requestedCalendarData) { + unset($node[200]['{urn:ietf:params:xml:ns:caldav}calendar-data']); } - - } - - } - // If we're dealing with a calendar, the calendar itself is responsible - // for the calendar-query. - if ($node instanceof Sabre_CalDAV_ICalendar && $depth = 1) { - - $nodePaths = $node->calendarQuery($parser->filters); - - foreach($nodePaths as $path) { - - list($properties) = - $this->server->getPropertiesForPath($this->server->getRequestUri() . '/' . $path, $parser->requestedProperties); - if ($parser->expand) { - // We need to do some post-processing - $vObject = VObject\Reader::read($properties[200]['{urn:ietf:params:xml:ns:caldav}calendar-data']); $vObject->expand($parser->expand['start'], $parser->expand['end']); - $properties[200]['{' . self::NS_CALDAV . '}calendar-data'] = $vObject->serialize(); + $node[200]['{' . self::NS_CALDAV . '}calendar-data'] = $vObject->serialize(); } - - $result[] = $properties; - + $verifiedNodes[] = $node; } } - $prefer = $this->server->getHTTPPRefer(); - $this->server->httpResponse->sendStatus(207); $this->server->httpResponse->setHeader('Content-Type','application/xml; charset=utf-8'); - $this->server->httpResponse->setHeader('Vary','Brief,Prefer'); - $this->server->httpResponse->sendBody($this->server->generateMultiStatus($result, $prefer['return-minimal'])); + $this->server->httpResponse->sendBody($this->server->generateMultiStatus($verifiedNodes)); } @@ -632,10 +561,10 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { } if ($start) { - $start = VObject\DateTimeParser::parseDateTime($start); + $start = Sabre_VObject_DateTimeParser::parseDateTime($start); } if ($end) { - $end = VObject\DateTimeParser::parseDateTime($end); + $end = Sabre_VObject_DateTimeParser::parseDateTime($end); } if (!$start && !$end) { @@ -654,33 +583,15 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { throw new Sabre_DAV_Exception_NotImplemented('The free-busy-query REPORT is only implemented on calendars'); } - // Doing a calendar-query first, to make sure we get the most - // performance. - $urls = $calendar->calendarQuery(array( - 'name' => 'VCALENDAR', - 'comp-filters' => array( - array( - 'name' => 'VEVENT', - 'comp-filters' => array(), - 'prop-filters' => array(), - 'is-not-defined' => false, - 'time-range' => array( - 'start' => $start, - 'end' => $end, - ), - ), - ), - 'prop-filters' => array(), - 'is-not-defined' => false, - 'time-range' => null, - )); - - $objects = array_map(function($url) use ($calendar) { - $obj = $calendar->getChild($url)->get(); + $objects = array_map(function($child) { + $obj = $child->get(); + if (is_resource($obj)) { + $obj = stream_get_contents($obj); + } return $obj; - }, $urls); + }, $calendar->getChildren()); - $generator = new VObject\FreeBusyGenerator(); + $generator = new Sabre_VObject_FreeBusyGenerator(); $generator->setObjects($objects); $generator->setTimeRange($start, $end); $result = $generator->getResult(); @@ -709,7 +620,7 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { if (!$node instanceof Sabre_CalDAV_ICalendarObject) return; - $this->validateICalendar($data, $path); + $this->validateICalendar($data); } @@ -729,52 +640,7 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { if (!$parentNode instanceof Sabre_CalDAV_Calendar) return; - $this->validateICalendar($data, $path); - - } - - /** - * This event is triggered before any HTTP request is handled. - * - * We use this to intercept GET calls to notification nodes, and return the - * proper response. - * - * @param string $method - * @param string $path - * @return void - */ - public function beforeMethod($method, $path) { - - if ($method!=='GET') return; - - try { - $node = $this->server->tree->getNodeForPath($path); - } catch (Sabre_DAV_Exception_NotFound $e) { - return; - } - - if (!$node instanceof Sabre_CalDAV_Notifications_INode) - return; - - if (!$this->server->checkPreconditions(true)) return false; - - $dom = new DOMDocument('1.0', 'UTF-8'); - $dom->formatOutput = true; - - $root = $dom->createElement('cs:notification'); - foreach($this->server->xmlNamespaces as $namespace => $prefix) { - $root->setAttribute('xmlns:' . $prefix, $namespace); - } - - $dom->appendChild($root); - $node->getNotificationType()->serializeBody($this->server, $root); - - $this->server->httpResponse->setHeader('Content-Type','application/xml'); - $this->server->httpResponse->setHeader('ETag',$node->getETag()); - $this->server->httpResponse->sendStatus(200); - $this->server->httpResponse->sendBody($dom->saveXML()); - - return false; + $this->validateICalendar($data); } @@ -784,10 +650,9 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { * An exception is thrown if it's not. * * @param resource|string $data - * @param string $path * @return void */ - protected function validateICalendar(&$data, $path) { + protected function validateICalendar(&$data) { // If it's a stream, we convert it to a string first. if (is_resource($data)) { @@ -799,9 +664,9 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { try { - $vobj = VObject\Reader::read($data); + $vobj = Sabre_VObject_Reader::read($data); - } catch (VObject\ParseException $e) { + } catch (Sabre_VObject_ParseException $e) { throw new Sabre_DAV_Exception_UnsupportedMediaType('This resource only supports valid iCalendar 2.0 data. Parse error: ' . $e->getMessage()); @@ -811,11 +676,6 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { throw new Sabre_DAV_Exception_UnsupportedMediaType('This collection can only support iCalendar objects.'); } - // Get the Supported Components for the target calendar - list($parentPath,$object) = Sabre_Dav_URLUtil::splitPath($path); - $calendarProperties = $this->server->getProperties($parentPath,array('{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set')); - $supportedComponents = $calendarProperties['{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set']->getValue(); - $foundType = null; $foundUID = null; foreach($vobj->getComponents() as $component) { @@ -827,9 +687,6 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { case 'VJOURNAL' : if (is_null($foundType)) { $foundType = $component->name; - if (!in_array($foundType, $supportedComponents)) { - throw new Sabre_CalDAV_Exception_InvalidComponentType('This calendar only supports ' . implode(', ', $supportedComponents) . '. We found a ' . $foundType); - } if (!isset($component->UID)) { throw new Sabre_DAV_Exception_BadRequest('Every ' . $component->name . ' component must have an UID'); } @@ -854,81 +711,12 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { } /** - * This method handles POST requests to the schedule-outbox. - * - * Currently, two types of requests are support: - * * FREEBUSY requests from RFC 6638 - * * Simple iTIP messages from draft-desruisseaux-caldav-sched-04 - * - * The latter is from an expired early draft of the CalDAV scheduling - * extensions, but iCal depends on a feature from that spec, so we - * implement it. + * This method handles POST requests to the schedule-outbox * * @param Sabre_CalDAV_Schedule_IOutbox $outboxNode - * @param string $outboxUri - * @return void - */ - public function outboxRequest(Sabre_CalDAV_Schedule_IOutbox $outboxNode, $outboxUri) { - - // Parsing the request body - try { - $vObject = VObject\Reader::read($this->server->httpRequest->getBody(true)); - } catch (VObject\ParseException $e) { - throw new Sabre_DAV_Exception_BadRequest('The request body must be a valid iCalendar object. Parse error: ' . $e->getMessage()); - } - - // The incoming iCalendar object must have a METHOD property, and a - // component. The combination of both determines what type of request - // this is. - $componentType = null; - foreach($vObject->getComponents() as $component) { - if ($component->name !== 'VTIMEZONE') { - $componentType = $component->name; - break; - } - } - if (is_null($componentType)) { - throw new Sabre_DAV_Exception_BadRequest('We expected at least one VTODO, VJOURNAL, VFREEBUSY or VEVENT component'); - } - - // 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'); - } - - // So we support two types of requests: - // - // REQUEST with a VFREEBUSY component - // REQUEST, REPLY, ADD, CANCEL on VEVENT components - - $acl = $this->server->getPlugin('acl'); - - if ($componentType === 'VFREEBUSY' && $method === 'REQUEST') { - - $acl && $acl->checkPrivileges($outboxUri,'{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}schedule-query-freebusy'); - $this->handleFreeBusyRequest($outboxNode, $vObject); - - } elseif ($componentType === 'VEVENT' && in_array($method, array('REQUEST','REPLY','ADD','CANCEL'))) { - - $acl && $acl->checkPrivileges($outboxUri,'{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}schedule-post-vevent'); - $this->handleEventNotification($outboxNode, $vObject); - - } else { - - throw new Sabre_DAV_Exception_NotImplemented('SabreDAV supports only VFREEBUSY (REQUEST) and VEVENT (REQUEST, REPLY, ADD, CANCEL)'); - - } - - } - - /** - * This method handles the REQUEST, REPLY, ADD and CANCEL methods for - * VEVENT iTip messages. - * * @return void */ - protected function handleEventNotification(Sabre_CalDAV_Schedule_IOutbox $outboxNode, VObject\Component $vObject) { + public function outboxRequest(Sabre_CalDAV_Schedule_IOutbox $outboxNode) { $originator = $this->server->httpRequest->getHeader('Originator'); $recipients = $this->server->httpRequest->getHeader('Recipient'); @@ -972,10 +760,38 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { 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'); } - $result = $this->iMIPMessage($originator, $recipients, $vObject, $principal); - $this->server->httpResponse->sendStatus(200); - $this->server->httpResponse->setHeader('Content-Type','application/xml'); - $this->server->httpResponse->sendBody($this->generateScheduleResponse($result)); + 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()); + } + + // Checking for the object type + $componentType = null; + foreach($vObject->getComponents() as $component) { + if ($component->name !== 'VTIMEZONE') { + $componentType = $component->name; + break; + } + } + if (is_null($componentType)) { + throw new Sabre_DAV_Exception_BadRequest('We expected at least one VTODO, VJOURNAL, VFREEBUSY or VEVENT component'); + } + + // 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 (in_array($method, array('REQUEST','REPLY','ADD','CANCEL')) && $componentType==='VEVENT') { + $result = $this->iMIPMessage($originator, $recipients, $vObject); + $this->server->httpResponse->sendStatus(200); + $this->server->httpResponse->setHeader('Content-Type','application/xml'); + $this->server->httpResponse->sendBody($this->generateScheduleResponse($result)); + } else { + throw new Sabre_DAV_Exception_NotImplemented('This iTIP method is currently not implemented'); + } } @@ -997,15 +813,15 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { * * @param string $originator * @param array $recipients - * @param Sabre\VObject\Component $vObject + * @param Sabre_VObject_Component $vObject * @return array */ - protected function iMIPMessage($originator, array $recipients, VObject\Component $vObject, $principal) { + protected function iMIPMessage($originator, array $recipients, Sabre_VObject_Component $vObject) { if (!$this->imipHandler) { $resultStatus = '5.2;This server does not support this operation'; } else { - $this->imipHandler->sendMessage($originator, $recipients, $vObject, $principal); + $this->imipHandler->sendMessage($originator, $recipients, $vObject); $resultStatus = '2.0;Success'; } @@ -1016,6 +832,7 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { return $result; + } /** @@ -1060,204 +877,6 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { } - /** - * This method is responsible for parsing a free-busy query request and - * returning it's result. - * - * @param Sabre_CalDAV_Schedule_IOutbox $outbox - * @param string $request - * @return string - */ - protected function handleFreeBusyRequest(Sabre_CalDAV_Schedule_IOutbox $outbox, VObject\Component $vObject) { - - $vFreeBusy = $vObject->VFREEBUSY; - $organizer = $vFreeBusy->organizer; - - $organizer = (string)$organizer; - - // Validating if the organizer matches the owner of the inbox. - $owner = $outbox->getOwner(); - - $caldavNS = '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}'; - - $uas = $caldavNS . 'calendar-user-address-set'; - $props = $this->server->getProperties($owner,array($uas)); - - if (empty($props[$uas]) || !in_array($organizer, $props[$uas]->getHrefs())) { - throw new Sabre_DAV_Exception_Forbidden('The organizer in the request did not match any of the addresses for the owner of this inbox'); - } - - if (!isset($vFreeBusy->ATTENDEE)) { - throw new Sabre_DAV_Exception_BadRequest('You must at least specify 1 attendee'); - } - - $attendees = array(); - foreach($vFreeBusy->ATTENDEE as $attendee) { - $attendees[]= (string)$attendee; - } - - - if (!isset($vFreeBusy->DTSTART) || !isset($vFreeBusy->DTEND)) { - throw new Sabre_DAV_Exception_BadRequest('DTSTART and DTEND must both be specified'); - } - - $startRange = $vFreeBusy->DTSTART->getDateTime(); - $endRange = $vFreeBusy->DTEND->getDateTime(); - - $results = array(); - foreach($attendees as $attendee) { - $results[] = $this->getFreeBusyForEmail($attendee, $startRange, $endRange, $vObject); - } - - $dom = new DOMDocument('1.0','utf-8'); - $dom->formatOutput = true; - $scheduleResponse = $dom->createElement('cal:schedule-response'); - foreach($this->server->xmlNamespaces as $namespace=>$prefix) { - - $scheduleResponse->setAttribute('xmlns:' . $prefix,$namespace); - - } - $dom->appendChild($scheduleResponse); - - foreach($results as $result) { - $response = $dom->createElement('cal:response'); - - $recipient = $dom->createElement('cal:recipient'); - $recipientHref = $dom->createElement('d:href'); - - $recipientHref->appendChild($dom->createTextNode($result['href'])); - $recipient->appendChild($recipientHref); - $response->appendChild($recipient); - - $reqStatus = $dom->createElement('cal:request-status'); - $reqStatus->appendChild($dom->createTextNode($result['request-status'])); - $response->appendChild($reqStatus); - - if (isset($result['calendar-data'])) { - - $calendardata = $dom->createElement('cal:calendar-data'); - $calendardata->appendChild($dom->createTextNode(str_replace("\r\n","\n",$result['calendar-data']->serialize()))); - $response->appendChild($calendardata); - - } - $scheduleResponse->appendChild($response); - } - - $this->server->httpResponse->sendStatus(200); - $this->server->httpResponse->setHeader('Content-Type','application/xml'); - $this->server->httpResponse->sendBody($dom->saveXML()); - - } - - /** - * Returns free-busy information for a specific address. The returned - * data is an array containing the following properties: - * - * calendar-data : A VFREEBUSY VObject - * request-status : an iTip status code. - * href: The principal's email address, as requested - * - * The following request status codes may be returned: - * * 2.0;description - * * 3.7;description - * - * @param string $email address - * @param DateTime $start - * @param DateTime $end - * @param Sabre_VObject_Component $request - * @return Sabre_VObject_Component - */ - protected function getFreeBusyForEmail($email, DateTime $start, DateTime $end, VObject\Component $request) { - - $caldavNS = '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}'; - - $aclPlugin = $this->server->getPlugin('acl'); - if (substr($email,0,7)==='mailto:') $email = substr($email,7); - - $result = $aclPlugin->principalSearch( - array('{http://sabredav.org/ns}email-address' => $email), - array( - '{DAV:}principal-URL', $caldavNS . 'calendar-home-set', - '{http://sabredav.org/ns}email-address', - ) - ); - - if (!count($result)) { - return array( - 'request-status' => '3.7;Could not find principal', - 'href' => 'mailto:' . $email, - ); - } - - if (!isset($result[0][200][$caldavNS . 'calendar-home-set'])) { - return array( - 'request-status' => '3.7;No calendar-home-set property found', - 'href' => 'mailto:' . $email, - ); - } - $homeSet = $result[0][200][$caldavNS . 'calendar-home-set']->getHref(); - - // Grabbing the calendar list - $objects = array(); - foreach($this->server->tree->getNodeForPath($homeSet)->getChildren() as $node) { - if (!$node instanceof Sabre_CalDAV_ICalendar) { - continue; - } - $aclPlugin->checkPrivileges($homeSet . $node->getName() ,$caldavNS . 'read-free-busy'); - - // Getting the list of object uris within the time-range - $urls = $node->calendarQuery(array( - 'name' => 'VCALENDAR', - 'comp-filters' => array( - array( - 'name' => 'VEVENT', - 'comp-filters' => array(), - 'prop-filters' => array(), - 'is-not-defined' => false, - 'time-range' => array( - 'start' => $start, - 'end' => $end, - ), - ), - ), - 'prop-filters' => array(), - 'is-not-defined' => false, - 'time-range' => null, - )); - - $calObjects = array_map(function($url) use ($node) { - $obj = $node->getChild($url)->get(); - return $obj; - }, $urls); - - $objects = array_merge($objects,$calObjects); - - } - - $vcalendar = VObject\Component::create('VCALENDAR'); - $vcalendar->VERSION = '2.0'; - $vcalendar->METHOD = 'REPLY'; - $vcalendar->CALSCALE = 'GREGORIAN'; - $vcalendar->PRODID = '-//SabreDAV//SabreDAV ' . Sabre_DAV_Version::VERSION . '//EN'; - - $generator = new VObject\FreeBusyGenerator(); - $generator->setObjects($objects); - $generator->setTimeRange($start, $end); - $generator->setBaseObject($vcalendar); - - $result = $generator->getResult(); - - $vcalendar->VFREEBUSY->ATTENDEE = 'mailto:' . $email; - $vcalendar->VFREEBUSY->UID = (string)$request->VFREEBUSY->UID; - $vcalendar->VFREEBUSY->ORGANIZER = clone $request->VFREEBUSY->ORGANIZER; - - return array( - 'calendar-data' => $result, - 'request-status' => '2.0;Success', - 'href' => 'mailto:' . $email, - ); - } - /** * This method is used to generate HTML output for the * Sabre_DAV_Browser_Plugin. This allows us to generate an interface users diff --git a/3rdparty/Sabre/CalDAV/Property/AllowedSharingModes.php b/3rdparty/Sabre/CalDAV/Property/AllowedSharingModes.php deleted file mode 100755 index efe751732c5..00000000000 --- a/3rdparty/Sabre/CalDAV/Property/AllowedSharingModes.php +++ /dev/null @@ -1,72 +0,0 @@ -canBeShared = $canBeShared; - $this->canBePublished = $canBePublished; - - } - - /** - * 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; - if ($this->canBeShared) { - $xcomp = $doc->createElement('cs:can-be-shared'); - $node->appendChild($xcomp); - } - if ($this->canBePublished) { - $xcomp = $doc->createElement('cs:can-be-published'); - $node->appendChild($xcomp); - } - - } - -} diff --git a/3rdparty/Sabre/CalDAV/Property/Invite.php b/3rdparty/Sabre/CalDAV/Property/Invite.php deleted file mode 100755 index 4ed94877df2..00000000000 --- a/3rdparty/Sabre/CalDAV/Property/Invite.php +++ /dev/null @@ -1,173 +0,0 @@ -users = $users; - - } - - /** - * Returns the list of users, as it was passed to the constructor. - * - * @return array - */ - public function getValue() { - - return $this->users; - - } - - /** - * 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; - foreach($this->users as $user) { - - $xuser = $doc->createElement('cs:user'); - - $href = $doc->createElement('d:href'); - $href->appendChild($doc->createTextNode($user['href'])); - $xuser->appendChild($href); - - if (isset($user['commonName']) && $user['commonName']) { - $commonName = $doc->createElement('cs:common-name'); - $commonName->appendChild($doc->createTextNode($user['commonName'])); - $xuser->appendChild($commonName); - } - - switch($user['status']) { - - case SharingPlugin::STATUS_ACCEPTED : - $status = $doc->createElement('cs:invite-accepted'); - $xuser->appendChild($status); - break; - case SharingPlugin::STATUS_DECLINED : - $status = $doc->createElement('cs:invite-declined'); - $xuser->appendChild($status); - break; - case SharingPlugin::STATUS_NORESPONSE : - $status = $doc->createElement('cs:invite-noresponse'); - $xuser->appendChild($status); - break; - case SharingPlugin::STATUS_INVALID : - $status = $doc->createElement('cs:invite-invalid'); - $xuser->appendChild($status); - break; - - } - - $xaccess = $doc->createElement('cs:access'); - - if ($user['readOnly']) { - $xaccess->appendChild( - $doc->createElement('cs:read') - ); - } else { - $xaccess->appendChild( - $doc->createElement('cs:read-write') - ); - } - $xuser->appendChild($xaccess); - - if (isset($user['summary']) && $user['summary']) { - $summary = $doc->createElement('cs:summary'); - $summary->appendChild($doc->createTextNode($user['summary'])); - $xuser->appendChild($summary); - } - - $node->appendChild($xuser); - - } - - } - - /** - * Unserializes the property. - * - * This static method should return a an instance of this object. - * - * @param DOMElement $prop - * @return Sabre_DAV_IProperty - */ - static function unserialize(DOMElement $prop) { - - $xpath = new \DOMXPath($prop->ownerDocument); - $xpath->registerNamespace('cs', Sabre_CalDAV_Plugin::NS_CALENDARSERVER); - $xpath->registerNamespace('d', 'DAV:'); - - $users = array(); - - foreach($xpath->query('cs:user', $prop) as $user) { - - $status = null; - if ($xpath->evaluate('boolean(cs:invite-accepted)', $user)) { - $status = SharingPlugin::STATUS_ACCEPTED; - } elseif ($xpath->evaluate('boolean(cs:invite-declined)', $user)) { - $status = SharingPlugin::STATUS_DECLINED; - } elseif ($xpath->evaluate('boolean(cs:invite-noresponse)', $user)) { - $status = SharingPlugin::STATUS_NORESPONSE; - } elseif ($xpath->evaluate('boolean(cs:invite-invalid)', $user)) { - $status = SharingPlugin::STATUS_INVALID; - } else { - throw new Sabre_DAV_Exception('Every cs:user property must have one of cs:invite-accepted, cs:invite-declined, cs:invite-noresponse or cs:invite-invalid'); - } - $users[] = array( - 'href' => $xpath->evaluate('string(d:href)', $user), - 'commonName' => $xpath->evaluate('string(cs:common-name)', $user), - 'readOnly' => $xpath->evaluate('boolean(cs:access/cs:read)', $user), - 'summary' => $xpath->evaluate('string(cs:summary)', $user), - 'status' => $status, - ); - - } - - return new self($users); - - } - -} diff --git a/3rdparty/Sabre/CalDAV/Property/ScheduleCalendarTransp.php b/3rdparty/Sabre/CalDAV/Property/ScheduleCalendarTransp.php deleted file mode 100755 index 76c1dbaec21..00000000000 --- a/3rdparty/Sabre/CalDAV/Property/ScheduleCalendarTransp.php +++ /dev/null @@ -1,99 +0,0 @@ -value = $value; - - } - - /** - * Returns the current value - * - * @return string - */ - public function getValue() { - - return $this->value; - - } - - /** - * 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; - switch($this->value) { - case self::TRANSPARENT : - $xval = $doc->createElement('cal:transparent'); - break; - case self::OPAQUE : - $xval = $doc->createElement('cal:opaque'); - break; - } - - $node->appendChild($xval); - - } - - /** - * Unserializes the DOMElement back into a Property class. - * - * @param DOMElement $node - * @return Sabre_CalDAV_Property_ScheduleCalendarTransp - */ - static function unserialize(DOMElement $node) { - - $value = null; - foreach($node->childNodes as $childNode) { - switch(Sabre_DAV_XMLUtil::toClarkNotation($childNode)) { - case '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}opaque' : - $value = self::OPAQUE; - break; - case '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}transparent' : - $value = self::TRANSPARENT; - break; - } - } - if (is_null($value)) - return null; - - return new self($value); - - } -} diff --git a/3rdparty/Sabre/CalDAV/Schedule/IMip.php b/3rdparty/Sabre/CalDAV/Schedule/IMip.php index 92c3c097c15..37e75fcc4a7 100755 --- a/3rdparty/Sabre/CalDAV/Schedule/IMip.php +++ b/3rdparty/Sabre/CalDAV/Schedule/IMip.php @@ -1,7 +1,5 @@ diff --git a/3rdparty/Sabre/CalDAV/Schedule/Outbox.php b/3rdparty/Sabre/CalDAV/Schedule/Outbox.php index 462aa527e23..014c37230d1 100755 --- a/3rdparty/Sabre/CalDAV/Schedule/Outbox.php +++ b/3rdparty/Sabre/CalDAV/Schedule/Outbox.php @@ -13,7 +13,7 @@ * @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_Collection implements Sabre_CalDAV_Schedule_IOutbox { +class Sabre_CalDAV_Schedule_Outbox extends Sabre_DAV_Directory implements Sabre_CalDAV_Schedule_IOutbox { /** * The principal Uri @@ -103,11 +103,6 @@ class Sabre_CalDAV_Schedule_Outbox extends Sabre_DAV_Collection implements Sabre 'principal' => $this->getOwner(), 'protected' => true, ), - array( - 'privilege' => '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}schedule-post-vevent', - 'principal' => $this->getOwner(), - 'protected' => true, - ), array( 'privilege' => '{DAV:}read', 'principal' => $this->getOwner(), @@ -149,9 +144,6 @@ class Sabre_CalDAV_Schedule_Outbox extends Sabre_DAV_Collection implements Sabre $default['aggregates'][] = array( 'privilege' => '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}schedule-query-freebusy', ); - $default['aggregates'][] = array( - 'privilege' => '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}schedule-post-vevent', - ); return $default; diff --git a/3rdparty/Sabre/CalDAV/Server.php b/3rdparty/Sabre/CalDAV/Server.php new file mode 100755 index 00000000000..325e3d80a7f --- /dev/null +++ b/3rdparty/Sabre/CalDAV/Server.php @@ -0,0 +1,68 @@ +authRealm); + $this->addPlugin($authPlugin); + + $aclPlugin = new Sabre_DAVACL_Plugin(); + $this->addPlugin($aclPlugin); + + $caldavPlugin = new Sabre_CalDAV_Plugin(); + $this->addPlugin($caldavPlugin); + + } + +} diff --git a/3rdparty/Sabre/CalDAV/ShareableCalendar.php b/3rdparty/Sabre/CalDAV/ShareableCalendar.php deleted file mode 100755 index 0e44885c621..00000000000 --- a/3rdparty/Sabre/CalDAV/ShareableCalendar.php +++ /dev/null @@ -1,72 +0,0 @@ -caldavBackend->updateShares($this->calendarInfo['id'], $add, $remove); - - } - - /** - * Returns the list of people whom this calendar is shared with. - * - * Every element in this array should have the following properties: - * * href - Often a mailto: address - * * commonName - Optional, for example a first + last name - * * status - See the Sabre_CalDAV_SharingPlugin::STATUS_ constants. - * * readOnly - boolean - * * summary - Optional, a description for the share - * - * @return array - */ - public function getShares() { - - return $this->caldavBackend->getShares($this->calendarInfo['id']); - - } - - /** - * Marks this calendar as published. - * - * Publishing a calendar should automatically create a read-only, public, - * subscribable calendar. - * - * @param bool $value - * @return void - */ - public function setPublishStatus($value) { - - $this->caldavBackend->setPublishStatus($this->calendarInfo['id'], $value); - - } - -} diff --git a/3rdparty/Sabre/CalDAV/SharedCalendar.php b/3rdparty/Sabre/CalDAV/SharedCalendar.php deleted file mode 100755 index 9000697d3ec..00000000000 --- a/3rdparty/Sabre/CalDAV/SharedCalendar.php +++ /dev/null @@ -1,98 +0,0 @@ -calendarInfo['{http://calendarserver.org/ns/}shared-url']; - - } - - /** - * Returns the owner principal - * - * This must be a url to a principal, or null if there's no owner - * - * @return string|null - */ - public function getOwner() { - - return $this->calendarInfo['{http://sabredav.org/ns}owner-principal']; - - } - - /** - * 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() { - - // The top-level ACL only contains access information for the true - // owner of the calendar, so we need to add the information for the - // sharee. - $acl = parent::getACL(); - $acl[] = array( - 'privilege' => '{DAV:}read', - 'principal' => $this->calendarInfo['principaluri'], - 'protected' => true, - ); - if (!$this->calendarInfo['{http://sabredav.org/ns}read-only']) { - $acl[] = array( - 'privilege' => '{DAV:}write', - 'principal' => $this->calendarInfo['principaluri'], - 'protected' => true, - ); - } - return $acl; - - } - - -} diff --git a/3rdparty/Sabre/CalDAV/SharingPlugin.php b/3rdparty/Sabre/CalDAV/SharingPlugin.php deleted file mode 100755 index 31df8057b24..00000000000 --- a/3rdparty/Sabre/CalDAV/SharingPlugin.php +++ /dev/null @@ -1,475 +0,0 @@ -server = $server; - //$server->resourceTypeMapping['Sabre_CalDAV_IShareableCalendar'] = '{' . Sabre_CalDAV_Plugin::NS_CALENDARSERVER . '}shared-owner'; - $server->resourceTypeMapping['Sabre_CalDAV_ISharedCalendar'] = '{' . Sabre_CalDAV_Plugin::NS_CALENDARSERVER . '}shared'; - - array_push( - $this->server->protectedProperties, - '{' . Sabre_CalDAV_Plugin::NS_CALENDARSERVER . '}invite', - '{' . Sabre_CalDAV_Plugin::NS_CALENDARSERVER . '}allowed-sharing-modes', - '{' . Sabre_CalDAV_Plugin::NS_CALENDARSERVER . '}shared-url' - ); - - $this->server->subscribeEvent('beforeGetProperties', array($this, 'beforeGetProperties')); - $this->server->subscribeEvent('afterGetProperties', array($this, 'afterGetProperties')); - $this->server->subscribeEvent('updateProperties', array($this, 'updateProperties')); - $this->server->subscribeEvent('unknownMethod', array($this,'unknownMethod')); - - } - - /** - * This event is triggered when properties are requested for a certain - * node. - * - * This allows us to inject any properties early. - * - * @param string $path - * @param Sabre_DAV_INode $node - * @param array $requestedProperties - * @param array $returnedProperties - * @return void - */ - public function beforeGetProperties($path, Sabre_DAV_INode $node, &$requestedProperties, &$returnedProperties) { - - if ($node instanceof Sabre_CalDAV_IShareableCalendar) { - if (($index = array_search('{' . Sabre_CalDAV_Plugin::NS_CALENDARSERVER . '}invite', $requestedProperties))!==false) { - - unset($requestedProperties[$index]); - $returnedProperties[200]['{' . Sabre_CalDAV_Plugin::NS_CALENDARSERVER . '}invite'] = - new Sabre_CalDAV_Property_Invite( - $node->getShares() - ); - - } - - } - if ($node instanceof Sabre_CalDAV_ISharedCalendar) { - if (($index = array_search('{' . Sabre_CalDAV_Plugin::NS_CALENDARSERVER . '}shared-url', $requestedProperties))!==false) { - - unset($requestedProperties[$index]); - $returnedProperties[200]['{' . Sabre_CalDAV_Plugin::NS_CALENDARSERVER . '}shared-url'] = - new Sabre_DAV_Property_Href( - $node->getSharedUrl() - ); - - } - - } - - } - - /** - * This method is triggered *after* all properties have been retrieved. - * This allows us to inject the correct resourcetype for calendars that - * have been shared. - * - * @param string $path - * @param array $properties - * @param Sabre_DAV_INode $node - * @return void - */ - public function afterGetProperties($path, &$properties, Sabre_DAV_INode $node) { - - if ($node instanceof Sabre_CalDAV_IShareableCalendar) { - if (isset($properties[200]['{DAV:}resourcetype'])) { - if (count($node->getShares())>0) { - $properties[200]['{DAV:}resourcetype']->add( - '{' . Sabre_CalDAV_Plugin::NS_CALENDARSERVER . '}shared-owner' - ); - } - } - $propName = '{' . Sabre_CalDAV_Plugin::NS_CALENDARSERVER . '}allowed-sharing-modes'; - if (array_key_exists($propName, $properties[404])) { - unset($properties[404][$propName]); - $properties[200][$propName] = new Sabre_CalDAV_Property_AllowedSharingModes(true,false); - } - - } - - } - - /** - * This method is trigged when a user attempts to update a node's - * properties. - * - * A previous draft of the sharing spec stated that it was possible to use - * PROPPATCH to remove 'shared-owner' from the resourcetype, thus unsharing - * the calendar. - * - * Even though this is no longer in the current spec, we keep this around - * because OS X 10.7 may still make use of this feature. - * - * @param array $mutations - * @param array $result - * @param Sabre_DAV_INode $node - * @return void - */ - public function updateProperties(array &$mutations, array &$result, Sabre_DAV_INode $node) { - - if (!$node instanceof Sabre_CalDAV_IShareableCalendar) - return; - - if (!isset($mutations['{DAV:}resourcetype'])) { - return; - } - - // Only doing something if shared-owner is indeed not in the list. - if($mutations['{DAV:}resourcetype']->is('{' . Sabre_CalDAV_Plugin::NS_CALENDARSERVER . '}shared-owner')) return; - - $shares = $node->getShares(); - $remove = array(); - foreach($shares as $share) { - $remove[] = $share['href']; - } - $node->updateShares(array(), $remove); - - // We're marking this update as 200 OK - $result[200]['{DAV:}resourcetype'] = null; - - // Removing it from the mutations list - unset($mutations['{DAV:}resourcetype']); - - } - - /** - * This event is triggered when the server didn't know how to handle a - * certain request. - * - * We intercept this to handle POST requests on calendars. - * - * @param string $method - * @param string $uri - * @return null|bool - */ - public function unknownMethod($method, $uri) { - - if ($method!=='POST') { - return; - } - - // Only handling xml - $contentType = $this->server->httpRequest->getHeader('Content-Type'); - if (strpos($contentType,'application/xml')===false && strpos($contentType,'text/xml')===false) - return; - - // Making sure the node exists - try { - $node = $this->server->tree->getNodeForPath($uri); - } catch (Sabre_DAV_Exception_NotFound $e) { - return; - } - - - $dom = Sabre_DAV_XMLUtil::loadDOMDocument($this->server->httpRequest->getBody(true)); - - $documentType = Sabre_DAV_XMLUtil::toClarkNotation($dom->firstChild); - - switch($documentType) { - - // Dealing with the 'share' document, which modified invitees on a - // calendar. - case '{' . Sabre_CalDAV_Plugin::NS_CALENDARSERVER . '}share' : - - // We can only deal with IShareableCalendar objects - if (!$node instanceof Sabre_CalDAV_IShareableCalendar) { - return; - } - - // Getting ACL info - $acl = $this->server->getPlugin('acl'); - - // If there's no ACL support, we allow everything - if ($acl) { - $acl->checkPrivileges($uri, '{DAV:}write'); - } - - $mutations = $this->parseShareRequest($dom); - - $node->updateShares($mutations[0], $mutations[1]); - - $this->server->httpResponse->sendStatus(200); - // Adding this because sending a response body may cause issues, - // and I wanted some type of indicator the response was handled. - $this->server->httpResponse->setHeader('X-Sabre-Status', 'everything-went-well'); - - // Breaking the event chain - return false; - - // The invite-reply document is sent when the user replies to an - // invitation of a calendar share. - case '{'. Sabre_CalDAV_Plugin::NS_CALENDARSERVER.'}invite-reply' : - - // This only works on the calendar-home-root node. - if (!$node instanceof Sabre_CalDAV_UserCalendars) { - return; - } - - // Getting ACL info - $acl = $this->server->getPlugin('acl'); - - // If there's no ACL support, we allow everything - if ($acl) { - $acl->checkPrivileges($uri, '{DAV:}write'); - } - - $message = $this->parseInviteReplyRequest($dom); - - $url = $node->shareReply( - $message['href'], - $message['status'], - $message['calendarUri'], - $message['inReplyTo'], - $message['summary'] - ); - - $this->server->httpResponse->sendStatus(200); - // Adding this because sending a response body may cause issues, - // and I wanted some type of indicator the response was handled. - $this->server->httpResponse->setHeader('X-Sabre-Status', 'everything-went-well'); - - if ($url) { - $dom = new DOMDocument('1.0', 'UTF-8'); - $dom->formatOutput = true; - - $root = $dom->createElement('cs:shared-as'); - foreach($this->server->xmlNamespaces as $namespace => $prefix) { - $root->setAttribute('xmlns:' . $prefix, $namespace); - } - - $dom->appendChild($root); - $href = new Sabre_DAV_Property_Href($url); - - $href->serialize($this->server, $root); - $this->server->httpResponse->setHeader('Content-Type','application/xml'); - $this->server->httpResponse->sendBody($dom->saveXML()); - - } - - // Breaking the event chain - return false; - - case '{' . Sabre_CalDAV_Plugin::NS_CALENDARSERVER . '}publish-calendar' : - - // We can only deal with IShareableCalendar objects - if (!$node instanceof Sabre_CalDAV_IShareableCalendar) { - return; - } - - // Getting ACL info - $acl = $this->server->getPlugin('acl'); - - // If there's no ACL support, we allow everything - if ($acl) { - $acl->checkPrivileges($uri, '{DAV:}write'); - } - - $node->setPublishStatus(true); - - // iCloud sends back the 202, so we will too. - $this->server->httpResponse->sendStatus(202); - - // Adding this because sending a response body may cause issues, - // and I wanted some type of indicator the response was handled. - $this->server->httpResponse->setHeader('X-Sabre-Status', 'everything-went-well'); - - // Breaking the event chain - return false; - - case '{' . Sabre_CalDAV_Plugin::NS_CALENDARSERVER . '}unpublish-calendar' : - - // We can only deal with IShareableCalendar objects - if (!$node instanceof Sabre_CalDAV_IShareableCalendar) { - return; - } - - // Getting ACL info - $acl = $this->server->getPlugin('acl'); - - // If there's no ACL support, we allow everything - if ($acl) { - $acl->checkPrivileges($uri, '{DAV:}write'); - } - - $node->setPublishStatus(false); - - $this->server->httpResponse->sendStatus(200); - - // Adding this because sending a response body may cause issues, - // and I wanted some type of indicator the response was handled. - $this->server->httpResponse->setHeader('X-Sabre-Status', 'everything-went-well'); - - // Breaking the event chain - return false; - - } - - - } - - /** - * Parses the 'share' POST request. - * - * This method returns an array, containing two arrays. - * The first array is a list of new sharees. Every element is a struct - * containing a: - * * href element. (usually a mailto: address) - * * commonName element (often a first and lastname, but can also be - * false) - * * readOnly (true or false) - * * summary (A description of the share, can also be false) - * - * The second array is a list of sharees that are to be removed. This is - * just a simple array with 'hrefs'. - * - * @param DOMDocument $dom - * @return array - */ - protected function parseShareRequest(DOMDocument $dom) { - - $xpath = new \DOMXPath($dom); - $xpath->registerNamespace('cs', Sabre_CalDAV_Plugin::NS_CALENDARSERVER); - $xpath->registerNamespace('d', 'DAV:'); - - - $set = array(); - $elems = $xpath->query('cs:set'); - - for($i=0; $i < $elems->length; $i++) { - - $xset = $elems->item($i); - $set[] = array( - 'href' => $xpath->evaluate('string(d:href)', $xset), - 'commonName' => $xpath->evaluate('string(cs:common-name)', $xset), - 'summary' => $xpath->evaluate('string(cs:summary)', $xset), - 'readOnly' => $xpath->evaluate('boolean(cs:read)', $xset)!==false - ); - - } - - $remove = array(); - $elems = $xpath->query('cs:remove'); - - for($i=0; $i < $elems->length; $i++) { - - $xremove = $elems->item($i); - $remove[] = $xpath->evaluate('string(d:href)', $xremove); - - } - - return array($set, $remove); - - } - - /** - * Parses the 'invite-reply' POST request. - * - * This method returns an array, containing the following properties: - * * href - The sharee who is replying - * * status - One of the self::STATUS_* constants - * * calendarUri - The url of the shared calendar - * * inReplyTo - The unique id of the share invitation. - * * summary - Optional description of the reply. - * - * @param DOMDocument $dom - * @return array - */ - protected function parseInviteReplyRequest(DOMDocument $dom) { - - $xpath = new \DOMXPath($dom); - $xpath->registerNamespace('cs', Sabre_CalDAV_Plugin::NS_CALENDARSERVER); - $xpath->registerNamespace('d', 'DAV:'); - - $hostHref = $xpath->evaluate('string(cs:hosturl/d:href)'); - if (!$hostHref) { - throw new Sabre_DAV_Exception_BadRequest('The {' . Sabre_CalDAV_Plugin::NS_CALENDARSERVER . '}hosturl/{DAV:}href element is required'); - } - - return array( - 'href' => $xpath->evaluate('string(d:href)'), - 'calendarUri' => $this->server->calculateUri($hostHref), - 'inReplyTo' => $xpath->evaluate('string(cs:in-reply-to)'), - 'summary' => $xpath->evaluate('string(cs:summary)'), - 'status' => $xpath->evaluate('boolean(cs:invite-accepted)')?self::STATUS_ACCEPTED:self::STATUS_DECLINED - ); - - } - -} diff --git a/3rdparty/Sabre/CalDAV/UserCalendars.php b/3rdparty/Sabre/CalDAV/UserCalendars.php index 3194e6677ab..b8d3f0573fa 100755 --- a/3rdparty/Sabre/CalDAV/UserCalendars.php +++ b/3rdparty/Sabre/CalDAV/UserCalendars.php @@ -6,7 +6,7 @@ * @package Sabre * @subpackage CalDAV * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. - * @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 */ class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre_DAVACL_IACL { @@ -21,7 +21,7 @@ class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre /** * CalDAV backend * - * @var Sabre_CalDAV_Backend_BackendInterface + * @var Sabre_CalDAV_Backend_Abstract */ protected $caldavBackend; @@ -36,10 +36,10 @@ class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre * Constructor * * @param Sabre_DAVACL_IPrincipalBackend $principalBackend - * @param Sabre_CalDAV_Backend_BackendInterface $caldavBackend + * @param Sabre_CalDAV_Backend_Abstract $caldavBackend * @param mixed $userUri */ - public function __construct(Sabre_DAVACL_IPrincipalBackend $principalBackend, Sabre_CalDAV_Backend_BackendInterface $caldavBackend, $userUri) { + public function __construct(Sabre_DAVACL_IPrincipalBackend $principalBackend, Sabre_CalDAV_Backend_Abstract $caldavBackend, $userUri) { $this->principalBackend = $principalBackend; $this->caldavBackend = $caldavBackend; @@ -168,22 +168,9 @@ class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre $calendars = $this->caldavBackend->getCalendarsForUser($this->principalInfo['uri']); $objs = array(); foreach($calendars as $calendar) { - if ($this->caldavBackend instanceof Sabre_CalDAV_Backend_SharingSupport) { - if (isset($calendar['{http://calendarserver.org/ns/}shared-url'])) { - $objs[] = new Sabre_CalDAV_SharedCalendar($this->principalBackend, $this->caldavBackend, $calendar); - } else { - $objs[] = new Sabre_CalDAV_ShareableCalendar($this->principalBackend, $this->caldavBackend, $calendar); - } - } else { - $objs[] = new Sabre_CalDAV_Calendar($this->principalBackend, $this->caldavBackend, $calendar); - } + $objs[] = new Sabre_CalDAV_Calendar($this->principalBackend, $this->caldavBackend, $calendar); } $objs[] = new Sabre_CalDAV_Schedule_Outbox($this->principalInfo['uri']); - - // We're adding a notifications node, if it's supported by the backend. - if ($this->caldavBackend instanceof Sabre_CalDAV_Backend_NotificationSupport) { - $objs[] = new Sabre_CalDAV_Notifications_Collection($this->caldavBackend, $this->principalInfo['uri']); - } return $objs; } @@ -198,22 +185,8 @@ class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre */ public function createExtendedCollection($name, array $resourceType, array $properties) { - $isCalendar = false; - foreach($resourceType as $rt) { - switch ($rt) { - case '{DAV:}collection' : - case '{http://calendarserver.org/ns/}shared-owner' : - // ignore - break; - case '{urn:ietf:params:xml:ns:caldav}calendar' : - $isCalendar = true; - break; - default : - throw new Sabre_DAV_Exception_InvalidResourceType('Unknown resourceType: ' . $rt); - } - } - if (!$isCalendar) { - throw new Sabre_DAV_Exception_InvalidResourceType('You can only create calendars in this collection'); + if (!in_array('{urn:ietf:params:xml:ns:caldav}calendar',$resourceType) || count($resourceType)!==2) { + throw new Sabre_DAV_Exception_InvalidResourceType('Unknown resourceType for this collection'); } $this->caldavBackend->createCalendar($this->principalInfo['uri'], $name, $properties); @@ -322,27 +295,4 @@ class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre } - /** - * This method is called when a user replied to a request to share. - * - * This method should return the url of the newly created calendar if the - * share was accepted. - * - * @param string href The sharee who is replying (often a mailto: address) - * @param int status One of the SharingPlugin::STATUS_* constants - * @param string $calendarUri The url to the calendar thats being shared - * @param string $inReplyTo The unique id this message is a response to - * @param string $summary A description of the reply - * @return null|string - */ - public function shareReply($href, $status, $calendarUri, $inReplyTo, $summary = null) { - - if (!$this->caldavBackend instanceof Sabre_CalDAV_Backend_SharingSupport) { - throw new Sabre_DAV_Exception_NotImplemented('Sharing support is not implemented by this backend.'); - } - - return $this->caldavBackend->shareReply($href, $status, $calendarUri, $inReplyTo, $summary); - - } - } diff --git a/3rdparty/Sabre/CalDAV/Version.php b/3rdparty/Sabre/CalDAV/Version.php index 0ad14fa0869..ace9901c089 100755 --- a/3rdparty/Sabre/CalDAV/Version.php +++ b/3rdparty/Sabre/CalDAV/Version.php @@ -14,7 +14,7 @@ class Sabre_CalDAV_Version { /** * Full version number */ - const VERSION = '1.7.0'; + const VERSION = '1.6.4'; /** * Stability : alpha, beta, stable diff --git a/3rdparty/Sabre/CalDAV/includes.php b/3rdparty/Sabre/CalDAV/includes.php index 8b38e398f65..1ecb870a0e1 100755 --- a/3rdparty/Sabre/CalDAV/includes.php +++ b/3rdparty/Sabre/CalDAV/includes.php @@ -16,47 +16,28 @@ */ // Begin includes -include __DIR__ . '/Backend/BackendInterface.php'; -include __DIR__ . '/Backend/NotificationSupport.php'; -include __DIR__ . '/Backend/SharingSupport.php'; +include __DIR__ . '/Backend/Abstract.php'; +include __DIR__ . '/Backend/PDO.php'; include __DIR__ . '/CalendarQueryParser.php'; include __DIR__ . '/CalendarQueryValidator.php'; include __DIR__ . '/CalendarRootNode.php'; -include __DIR__ . '/Exception/InvalidComponentType.php'; include __DIR__ . '/ICalendar.php'; include __DIR__ . '/ICalendarObject.php'; include __DIR__ . '/ICSExportPlugin.php'; -include __DIR__ . '/IShareableCalendar.php'; -include __DIR__ . '/ISharedCalendar.php'; -include __DIR__ . '/Notifications/ICollection.php'; -include __DIR__ . '/Notifications/INode.php'; -include __DIR__ . '/Notifications/INotificationType.php'; -include __DIR__ . '/Notifications/Node.php'; -include __DIR__ . '/Notifications/Notification/Invite.php'; -include __DIR__ . '/Notifications/Notification/InviteReply.php'; -include __DIR__ . '/Notifications/Notification/SystemStatus.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/AllowedSharingModes.php'; -include __DIR__ . '/Property/Invite.php'; -include __DIR__ . '/Property/ScheduleCalendarTransp.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__ . '/SharingPlugin.php'; +include __DIR__ . '/Server.php'; include __DIR__ . '/UserCalendars.php'; include __DIR__ . '/Version.php'; -include __DIR__ . '/Backend/Abstract.php'; -include __DIR__ . '/Backend/PDO.php'; include __DIR__ . '/Calendar.php'; include __DIR__ . '/CalendarObject.php'; -include __DIR__ . '/Notifications/Collection.php'; -include __DIR__ . '/ShareableCalendar.php'; -include __DIR__ . '/SharedCalendar.php'; // End includes diff --git a/3rdparty/Sabre/CardDAV/AddressBook.php b/3rdparty/Sabre/CardDAV/AddressBook.php index 8d545114d97..12297175a85 100755 --- a/3rdparty/Sabre/CardDAV/AddressBook.php +++ b/3rdparty/Sabre/CardDAV/AddressBook.php @@ -55,7 +55,7 @@ class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_Ca * Returns a card * * @param string $name - * @return Sabre_CardDAV_ICard + * @return Sabre_DAV_Card */ public function getChild($name) { @@ -104,7 +104,7 @@ class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_Ca * * @param string $name * @param resource $vcardData - * @return string|null + * @return void|null */ public function createFile($name,$vcardData = null) { diff --git a/3rdparty/Sabre/CardDAV/Card.php b/3rdparty/Sabre/CardDAV/Card.php index 0e35d321eb8..d7c66333837 100755 --- a/3rdparty/Sabre/CardDAV/Card.php +++ b/3rdparty/Sabre/CardDAV/Card.php @@ -6,7 +6,7 @@ * @package Sabre * @subpackage CardDAV * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. - * @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 */ class Sabre_CardDAV_Card extends Sabre_DAV_File implements Sabre_CardDAV_ICard, Sabre_DAVACL_IACL { @@ -78,7 +78,7 @@ class Sabre_CardDAV_Card extends Sabre_DAV_File implements Sabre_CardDAV_ICard, * Updates the VCard-formatted object * * @param string $cardData - * @return string|null + * @return void */ public function put($cardData) { @@ -114,7 +114,7 @@ class Sabre_CardDAV_Card extends Sabre_DAV_File implements Sabre_CardDAV_ICard, */ public function getContentType() { - return 'text/x-vcard; charset=utf-8'; + return 'text/x-vcard'; } @@ -128,13 +128,7 @@ class Sabre_CardDAV_Card extends Sabre_DAV_File implements Sabre_CardDAV_ICard, if (isset($this->cardData['etag'])) { return $this->cardData['etag']; } else { - $data = $this->get(); - if (is_string($data)) { - return '"' . md5($data) . '"'; - } else { - // We refuse to calculate the md5 if it's a stream. - return null; - } + return '"' . md5($this->get()) . '"'; } } @@ -142,7 +136,7 @@ class Sabre_CardDAV_Card extends Sabre_DAV_File implements Sabre_CardDAV_ICard, /** * Returns the last modification date as a unix timestamp * - * @return int + * @return time */ public function getLastModified() { diff --git a/3rdparty/Sabre/CardDAV/Plugin.php b/3rdparty/Sabre/CardDAV/Plugin.php index 12bccaec4fb..96def6dd96b 100755 --- a/3rdparty/Sabre/CardDAV/Plugin.php +++ b/3rdparty/Sabre/CardDAV/Plugin.php @@ -1,7 +1,5 @@ subscribeEvent('beforeGetProperties', array($this, 'beforeGetProperties')); - $server->subscribeEvent('afterGetProperties', array($this, 'afterGetProperties')); $server->subscribeEvent('updateProperties', array($this, 'updateProperties')); $server->subscribeEvent('report', array($this,'report')); $server->subscribeEvent('onHTMLActionsPanel', array($this,'htmlActionsPanel')); @@ -156,6 +153,10 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin { if (is_resource($val)) $val = stream_get_contents($val); + // Taking out \r to not screw up the xml output + //$returnedProperties[200][$addressDataProp] = str_replace("\r","", $val); + // The stripping of \r breaks the Mail App in OSX Mountain Lion + // this is fixed in master, but not backported. /Tanghus $returnedProperties[200][$addressDataProp] = $val; } @@ -189,7 +190,7 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin { * @param array $mutations * @param array $result * @param Sabre_DAV_INode $node - * @return bool + * @return void */ public function updateProperties(&$mutations, &$result, $node) { @@ -271,7 +272,7 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin { $properties = array_keys(Sabre_DAV_XMLUtil::parseProperties($dom->firstChild)); - $hrefElems = $dom->getElementsByTagNameNS('DAV:','href'); + $hrefElems = $dom->getElementsByTagNameNS('urn:DAV','href'); $propertyList = array(); foreach($hrefElems as $elem) { @@ -281,12 +282,9 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin { } - $prefer = $this->server->getHTTPPRefer(); - $this->server->httpResponse->sendStatus(207); $this->server->httpResponse->setHeader('Content-Type','application/xml; charset=utf-8'); - $this->server->httpResponse->setHeader('Vary','Brief,Prefer'); - $this->server->httpResponse->sendBody($this->server->generateMultiStatus($propertyList, $prefer['return-minimal'])); + $this->server->httpResponse->sendBody($this->server->generateMultiStatus($propertyList)); } @@ -350,9 +348,9 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin { try { - $vobj = VObject\Reader::read($data); + $vobj = Sabre_VObject_Reader::read($data); - } catch (VObject\ParseException $e) { + } catch (Sabre_VObject_ParseException $e) { throw new Sabre_DAV_Exception_UnsupportedMediaType('This resource only supports valid vcard data. Parse error: ' . $e->getMessage()); @@ -362,10 +360,6 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin { throw new Sabre_DAV_Exception_UnsupportedMediaType('This collection can only support vcard objects.'); } - if (!isset($vobj->UID)) { - throw new Sabre_DAV_Exception_BadRequest('Every vcard must have an UID.'); - } - } @@ -430,12 +424,9 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin { } - $prefer = $this->server->getHTTPPRefer(); - $this->server->httpResponse->sendStatus(207); $this->server->httpResponse->setHeader('Content-Type','application/xml; charset=utf-8'); - $this->server->httpResponse->setHeader('Vary','Brief,Prefer'); - $this->server->httpResponse->sendBody($this->server->generateMultiStatus($result, $prefer['return-minimal'])); + $this->server->httpResponse->sendBody($this->server->generateMultiStatus($result)); } @@ -449,7 +440,7 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin { */ public function validateFilters($vcardData, array $filters, $test) { - $vcard = VObject\Reader::read($vcardData); + $vcard = Sabre_VObject_Reader::read($vcardData); if (!$filters) return true; @@ -624,30 +615,6 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin { } - /** - * This event is triggered after webdav-properties have been retrieved. - * - * @return bool - */ - public function afterGetProperties($uri, &$properties) { - - // If the request was made using the SOGO connector, we must rewrite - // the content-type property. By default SabreDAV will send back - // text/x-vcard; charset=utf-8, but for SOGO we must strip that last - // part. - if (!isset($properties[200]['{DAV:}getcontenttype'])) - return; - - if (strpos($this->server->httpRequest->getHeader('User-Agent'),'Thunderbird')===false) { - return; - } - - if (strpos($properties[200]['{DAV:}getcontenttype'],'text/x-vcard')===0) { - $properties[200]['{DAV:}getcontenttype'] = 'text/x-vcard'; - } - - } - /** * This method is used to generate HTML output for the * Sabre_DAV_Browser_Plugin. This allows us to generate an interface users diff --git a/3rdparty/Sabre/CardDAV/VCFExportPlugin.php b/3rdparty/Sabre/CardDAV/VCFExportPlugin.php deleted file mode 100755 index 8850fef8afb..00000000000 --- a/3rdparty/Sabre/CardDAV/VCFExportPlugin.php +++ /dev/null @@ -1,107 +0,0 @@ -server = $server; - $this->server->subscribeEvent('beforeMethod',array($this,'beforeMethod'), 90); - - } - - /** - * 'beforeMethod' event handles. This event handles intercepts GET requests ending - * with ?export - * - * @param string $method - * @param string $uri - * @return bool - */ - public function beforeMethod($method, $uri) { - - if ($method!='GET') return; - if ($this->server->httpRequest->getQueryString()!='export') return; - - // splitting uri - list($uri) = explode('?',$uri,2); - - $node = $this->server->tree->getNodeForPath($uri); - - if (!($node instanceof Sabre_CardDAV_IAddressBook)) return; - - // Checking ACL, if available. - if ($aclPlugin = $this->server->getPlugin('acl')) { - $aclPlugin->checkPrivileges($uri, '{DAV:}read'); - } - - $this->server->httpResponse->setHeader('Content-Type','text/directory'); - $this->server->httpResponse->sendStatus(200); - - $nodes = $this->server->getPropertiesForPath($uri, array( - '{' . Sabre_CardDAV_Plugin::NS_CARDDAV . '}address-data', - ),1); - - $this->server->httpResponse->sendBody($this->generateVCF($nodes)); - - // Returning false to break the event chain - return false; - - } - - /** - * Merges all vcard objects, and builds one big vcf export - * - * @param array $nodes - * @return string - */ - public function generateVCF(array $nodes) { - - $output = ""; - - foreach($nodes as $node) { - - if (!isset($node[200]['{' . Sabre_CardDAV_Plugin::NS_CARDDAV . '}address-data'])) { - continue; - } - $nodeData = $node[200]['{' . Sabre_CardDAV_Plugin::NS_CARDDAV . '}address-data']; - - // Parsing this node so VObject can clean up the output. - $output .= - VObject\Reader::read($nodeData)->serialize(); - - } - - return $output; - - } - -} diff --git a/3rdparty/Sabre/CardDAV/Version.php b/3rdparty/Sabre/CardDAV/Version.php index 6b70a2df9b5..d0623f0d3e8 100755 --- a/3rdparty/Sabre/CardDAV/Version.php +++ b/3rdparty/Sabre/CardDAV/Version.php @@ -16,7 +16,7 @@ class Sabre_CardDAV_Version { /** * Full version number */ - const VERSION = '1.7.0'; + const VERSION = '1.6.3'; /** * Stability : alpha, beta, stable diff --git a/3rdparty/Sabre/CardDAV/includes.php b/3rdparty/Sabre/CardDAV/includes.php index 08b4f76bd01..c3b8c04b077 100755 --- a/3rdparty/Sabre/CardDAV/includes.php +++ b/3rdparty/Sabre/CardDAV/includes.php @@ -26,7 +26,6 @@ include __DIR__ . '/IDirectory.php'; include __DIR__ . '/Plugin.php'; include __DIR__ . '/Property/SupportedAddressData.php'; include __DIR__ . '/UserAddressBooks.php'; -include __DIR__ . '/VCFExportPlugin.php'; include __DIR__ . '/Version.php'; include __DIR__ . '/AddressBook.php'; include __DIR__ . '/Card.php'; diff --git a/3rdparty/Sabre/DAV/Browser/Plugin.php b/3rdparty/Sabre/DAV/Browser/Plugin.php index b6440ab6340..09bbdd2ae02 100755 --- a/3rdparty/Sabre/DAV/Browser/Plugin.php +++ b/3rdparty/Sabre/DAV/Browser/Plugin.php @@ -338,7 +338,7 @@ class Sabre_DAV_Browser_Plugin extends Sabre_DAV_ServerPlugin { $icon = ''; if ($this->enableAssets) { - $node = $this->server->tree->getNodeForPath(($path?$path.'/':'') . $name); + $node = $parent->getChild($name); foreach(array_reverse($this->iconMap) as $class=>$iconName) { if ($node instanceof $class) { diff --git a/3rdparty/Sabre/DAV/Client.php b/3rdparty/Sabre/DAV/Client.php index 9d9f4c96b02..9a428765e90 100755 --- a/3rdparty/Sabre/DAV/Client.php +++ b/3rdparty/Sabre/DAV/Client.php @@ -16,25 +16,12 @@ */ class Sabre_DAV_Client { - /** - * The propertyMap is a key-value array. - * - * If you use the propertyMap, any {DAV:}multistatus responses with the - * proeprties listed in this array, will automatically be mapped to a - * respective class. - * - * The {DAV:}resourcetype property is automatically added. This maps to - * Sabre_DAV_Property_ResourceType - * - * @var array - */ public $propertyMap = array(); protected $baseUri; protected $userName; protected $password; protected $proxy; - protected $trustedCertificates; /** * Basic authentication @@ -100,18 +87,6 @@ class Sabre_DAV_Client { } - /** - * Add trusted root certificates to the webdav client. - * - * The parameter certificates should be a absulute path to a file - * which contains all trusted certificates - * - * @param string $certificates - */ - public function addTrustedCertificates($certificates) { - $this->trustedCertificates = $certificates; - } - /** * Does a PROPFIND request * @@ -168,13 +143,13 @@ class Sabre_DAV_Client { if ($depth===0) { reset($result); $result = current($result); - return isset($result[200])?$result[200]:array(); + return $result[200]; } $newResult = array(); foreach($result as $href => $statusList) { - $newResult[$href] = isset($statusList[200])?$statusList[200]:array(); + $newResult[$href] = $statusList[200]; } @@ -304,10 +279,6 @@ class Sabre_DAV_Client { CURLOPT_MAXREDIRS => 5, ); - if($this->trustedCertificates) { - $curlSettings[CURLOPT_CAINFO] = $this->trustedCertificates; - } - switch ($method) { case 'HEAD' : @@ -392,30 +363,10 @@ class Sabre_DAV_Client { if ($response['statusCode']>=400) { switch ($response['statusCode']) { - case 400 : - throw new Sabre_DAV_Exception_BadRequest('Bad request'); - case 401 : - throw new Sabre_DAV_Exception_NotAuthenticated('Not authenticated'); - case 402 : - throw new Sabre_DAV_Exception_PaymentRequired('Payment required'); - case 403 : - throw new Sabre_DAV_Exception_Forbidden('Forbidden'); case 404: - throw new Sabre_DAV_Exception_NotFound('Resource not found.'); - case 405 : - throw new Sabre_DAV_Exception_MethodNotAllowed('Method not allowed'); - case 409 : - throw new Sabre_DAV_Exception_Conflict('Conflict'); - case 412 : - throw new Sabre_DAV_Exception_PreconditionFailed('Precondition failed'); - case 416 : - throw new Sabre_DAV_Exception_RequestedRangeNotSatisfiable('Requested Range Not Satisfiable'); - case 500 : - throw new Sabre_DAV_Exception('Internal server error'); - case 501 : - throw new Sabre_DAV_Exception_NotImplemented('Not Implemented'); - case 507 : - throw new Sabre_DAV_Exception_InsufficientStorage('Insufficient storage'); + throw new Sabre_DAV_Exception_NotFound('Resource ' . $url . ' not found.'); + break; + default: throw new Sabre_DAV_Exception('HTTP error response. (errorcode ' . $response['statusCode'] . ')'); } @@ -435,7 +386,6 @@ class Sabre_DAV_Client { * @param array $settings * @return array */ - // @codeCoverageIgnoreStart protected function curlRequest($url, $settings) { $curl = curl_init($url); @@ -449,7 +399,6 @@ class Sabre_DAV_Client { ); } - // @codeCoverageIgnoreEnd /** * Returns the full url based on the given url (which may be relative). All @@ -504,17 +453,19 @@ class Sabre_DAV_Client { */ public function parseMultiStatus($body) { + $body = Sabre_DAV_XMLUtil::convertDAVNamespace($body); + $responseXML = simplexml_load_string($body, null, LIBXML_NOBLANKS | LIBXML_NOCDATA); 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]; @@ -522,7 +473,7 @@ 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); diff --git a/3rdparty/Sabre/DAV/Collection.php b/3rdparty/Sabre/DAV/Collection.php index c7648a8a52d..776c22531b2 100755 --- a/3rdparty/Sabre/DAV/Collection.php +++ b/3rdparty/Sabre/DAV/Collection.php @@ -17,13 +17,9 @@ 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 * - * This method must throw Sabre_DAV_Exception_NotFound if the node does not - * exist. - * * @param string $name * @throws Sabre_DAV_Exception_NotFound * @return Sabre_DAV_INode diff --git a/3rdparty/Sabre/DAV/Directory.php b/3rdparty/Sabre/DAV/Directory.php new file mode 100755 index 00000000000..6db8febc02e --- /dev/null +++ b/3rdparty/Sabre/DAV/Directory.php @@ -0,0 +1,17 @@ +path, 'c'); - fseek($f,$offset-1); - if (is_string($data)) { - fwrite($f, $data); - } else { - stream_copy_to_stream($data,$f); - } - fclose($f); - return '"' . md5_file($this->path) . '"'; - - } - /** * Returns the data * - * @return resource + * @return string */ public function get() { diff --git a/3rdparty/Sabre/DAV/ICollection.php b/3rdparty/Sabre/DAV/ICollection.php index 94431a0c496..4626038a66e 100755 --- a/3rdparty/Sabre/DAV/ICollection.php +++ b/3rdparty/Sabre/DAV/ICollection.php @@ -19,7 +19,7 @@ interface Sabre_DAV_ICollection extends Sabre_DAV_INode { * 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 successful creation of the file, you may choose to return the ETag + * 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 @@ -50,9 +50,6 @@ interface Sabre_DAV_ICollection extends Sabre_DAV_INode { /** * Returns a specific child node, referenced by its name * - * This method must throw Sabre_DAV_Exception_NotFound if the node does not - * exist. - * * @param string $name * @return Sabre_DAV_INode */ diff --git a/3rdparty/Sabre/DAV/IFile.php b/3rdparty/Sabre/DAV/IFile.php index 1eca8986a5c..478f822ae71 100755 --- a/3rdparty/Sabre/DAV/IFile.php +++ b/3rdparty/Sabre/DAV/IFile.php @@ -51,7 +51,7 @@ interface Sabre_DAV_IFile extends Sabre_DAV_INode { * * If null is returned, we'll assume application/octet-stream * - * @return string|null + * @return void */ function getContentType(); diff --git a/3rdparty/Sabre/DAV/Locks/Plugin.php b/3rdparty/Sabre/DAV/Locks/Plugin.php index 957ac506a9c..035b3a63863 100755 --- a/3rdparty/Sabre/DAV/Locks/Plugin.php +++ b/3rdparty/Sabre/DAV/Locks/Plugin.php @@ -152,7 +152,6 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin { case 'MKCOL' : case 'PROPPATCH' : case 'PUT' : - case 'PATCH' : $lastLock = null; if (!$this->validateLock($uri,$lastLock)) throw new Sabre_DAV_Exception_Locked($lastLock); diff --git a/3rdparty/Sabre/DAV/Node.php b/3rdparty/Sabre/DAV/Node.php index 3b95dfec2fa..070b7176afd 100755 --- a/3rdparty/Sabre/DAV/Node.php +++ b/3rdparty/Sabre/DAV/Node.php @@ -27,7 +27,7 @@ abstract class Sabre_DAV_Node implements Sabre_DAV_INode { } /** - * Deletes the current node + * Deleted the current node * * @throws Sabre_DAV_Exception_Forbidden * @return void diff --git a/3rdparty/Sabre/DAV/ObjectTree.php b/3rdparty/Sabre/DAV/ObjectTree.php index 3b7f222d64b..bce51463900 100755 --- a/3rdparty/Sabre/DAV/ObjectTree.php +++ b/3rdparty/Sabre/DAV/ObjectTree.php @@ -51,30 +51,24 @@ class Sabre_DAV_ObjectTree extends Sabre_DAV_Tree { $path = trim($path,'/'); if (isset($this->cache[$path])) return $this->cache[$path]; - // Is it the root node? - if (!strlen($path)) { - return $this->rootNode; - } + //if (!$path || $path=='.') return $this->rootNode; + $currentNode = $this->rootNode; - // Attempting to fetch its parent - list($parentName, $baseName) = Sabre_DAV_URLUtil::splitPath($path); + // We're splitting up the path variable into folder/subfolder components and traverse to the correct node.. + foreach(explode('/',$path) as $pathPart) { - // If there was no parent, we must simply ask it from the root node. - if ($parentName==="") { - $node = $this->rootNode->getChild($baseName); - } else { - // Otherwise, we recursively grab the parent and ask him/her. - $parent = $this->getNodeForPath($parentName); + // If this part of the path is just a dot, it actually means we can skip it + if ($pathPart=='.' || $pathPart=='') continue; - if (!($parent instanceof Sabre_DAV_ICollection)) + if (!($currentNode instanceof Sabre_DAV_ICollection)) throw new Sabre_DAV_Exception_NotFound('Could not find node at path: ' . $path); - $node = $parent->getChild($baseName); + $currentNode = $currentNode->getChild($pathPart); } - $this->cache[$path] = $node; - return $node; + $this->cache[$path] = $currentNode; + return $currentNode; } diff --git a/3rdparty/Sabre/DAV/PartialUpdate/IFile.php b/3rdparty/Sabre/DAV/PartialUpdate/IFile.php deleted file mode 100755 index cf5ad55c6de..00000000000 --- a/3rdparty/Sabre/DAV/PartialUpdate/IFile.php +++ /dev/null @@ -1,38 +0,0 @@ -addPlugin($patchPlugin); - * - * @package Sabre - * @subpackage DAV - * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. - * @author Jean-Tiare LE BIGOT (http://www.jtlebi.fr/) - * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License - */ -class Sabre_DAV_PartialUpdate_Plugin extends Sabre_DAV_ServerPlugin { - - /** - * Reference to server - * - * @var Sabre_DAV_Server - */ - protected $server; - - /** - * Initializes the plugin - * - * This method is automatically called by the Server class after addPlugin. - * - * @param Sabre_DAV_Server $server - * @return void - */ - public function initialize(Sabre_DAV_Server $server) { - - $this->server = $server; - $server->subscribeEvent('unknownMethod',array($this,'unknownMethod')); - - } - - /** - * Returns a plugin name. - * - * Using this name other plugins will be able to access other plugins - * using Sabre_DAV_Server::getPlugin - * - * @return string - */ - public function getPluginName() { - - return 'partialupdate'; - - } - - /** - * This method is called by the Server if the user used an HTTP method - * the server didn't recognize. - * - * This plugin intercepts the PATCH methods. - * - * @param string $method - * @param string $uri - * @return bool|null - */ - public function unknownMethod($method, $uri) { - - switch($method) { - - case 'PATCH': - return $this->httpPatch($uri); - - } - - } - - /** - * 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 - * available for the specified uri. - * - * We claim to support PATCH method (partial update) if and only if - * - the node exist - * - the node implements our partial update interface - * - * @param string $uri - * @return array - */ - public function getHTTPMethods($uri) { - - $tree = $this->server->tree; - - if ($tree->nodeExists($uri) && - $tree->getNodeForPath($uri) instanceof Sabre_DAV_PartialUpdate_IFile) { - return array('PATCH'); - } - - return array(); - - } - - /** - * Returns a list of features for the HTTP OPTIONS Dav: header. - * - * @return array - */ - public function getFeatures() { - - return array('sabredav-partialupdate'); - - } - - /** - * Patch an uri - * - * The WebDAV patch request can be used to modify only a part of an - * existing resource. If the resource does not exist yet and the first - * offset is not 0, the request fails - * - * @param string $uri - * @return void - */ - protected function httpPatch($uri) { - - // Get the node. Will throw a 404 if not found - $node = $this->server->tree->getNodeForPath($uri); - if (!($node instanceof Sabre_DAV_PartialUpdate_IFile)) { - throw new Sabre_DAV_Exception_MethodNotAllowed('The target resource does not support the PATCH method.'); - } - - $range = $this->getHTTPUpdateRange(); - - if (!$range) { - throw new Sabre_DAV_Exception_BadRequest('No valid "X-Update-Range" found in the headers'); - } - - $contentType = strtolower( - $this->server->httpRequest->getHeader('Content-Type') - ); - - if ($contentType != 'application/x-sabredav-partialupdate') { - throw new Sabre_DAV_Exception_UnsupportedMediaType('Unknown Content-Type header "' . $contentType . '"'); - } - - $len = $this->server->httpRequest->getHeader('Content-Length'); - - // Load the begin and end data - $start = ($range[0])?$range[0]:0; - $end = ($range[1])?$range[1]:$len-1; - - // Check consistency - if($end < $start) - throw new Sabre_DAV_Exception_RequestedRangeNotSatisfiable('The end offset (' . $range[1] . ') is lower than the start offset (' . $range[0] . ')'); - if($end - $start + 1 != $len) - throw new Sabre_DAV_Exception_RequestedRangeNotSatisfiable('Actual data length (' . $len . ') is not consistent with begin (' . $range[0] . ') and end (' . $range[1] . ') offsets'); - - // Checking If-None-Match and related headers. - if (!$this->server->checkPreconditions()) return; - - if (!$this->server->broadcastEvent('beforeWriteContent',array($uri, $node, null))) - return; - - $body = $this->server->httpRequest->getBody(); - $etag = $node->putRange($body, $start-1); - - $this->server->broadcastEvent('afterWriteContent',array($uri, $node)); - - $this->server->httpResponse->setHeader('Content-Length','0'); - if ($etag) $this->server->httpResponse->setHeader('ETag',$etag); - $this->server->httpResponse->sendStatus(204); - - return false; - - } - - /** - * Returns the HTTP custom range update header - * - * This method returns null if there is no well-formed HTTP range request - * header or array($start, $end). - * - * The first number is the offset of the first byte in the range. - * 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 - * - * @return array|null - */ - public function getHTTPUpdateRange() { - - $range = $this->server->httpRequest->getHeader('X-Update-Range'); - if (is_null($range)) return null; - - // Matching "Range: bytes=1234-5678: both numbers are optional - - if (!preg_match('/^bytes=([0-9]*)-([0-9]*)$/i',$range,$matches)) return null; - - if ($matches[1]==='' && $matches[2]==='') return null; - - return array( - $matches[1]!==''?$matches[1]:null, - $matches[2]!==''?$matches[2]:null, - ); - - } -} diff --git a/3rdparty/Sabre/DAV/Property.php b/3rdparty/Sabre/DAV/Property.php index 6487bf44bc4..1cfada3236c 100755 --- a/3rdparty/Sabre/DAV/Property.php +++ b/3rdparty/Sabre/DAV/Property.php @@ -11,16 +11,10 @@ * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ -abstract class Sabre_DAV_Property implements Sabre_DAV_PropertyInterface { +abstract class Sabre_DAV_Property { + + abstract function serialize(Sabre_DAV_Server $server, DOMElement $prop); - /** - * Unserializes the property. - * - * This static method should return a an instance of this object. - * - * @param DOMElement $prop - * @return Sabre_DAV_IProperty - */ static function unserialize(DOMElement $prop) { throw new Sabre_DAV_Exception('Unserialize has not been implemented for this class'); diff --git a/3rdparty/Sabre/DAV/Property/Href.php b/3rdparty/Sabre/DAV/Property/Href.php index cd1d867f71b..dac564f24d7 100755 --- a/3rdparty/Sabre/DAV/Property/Href.php +++ b/3rdparty/Sabre/DAV/Property/Href.php @@ -82,7 +82,7 @@ class Sabre_DAV_Property_Href extends Sabre_DAV_Property implements Sabre_DAV_Pr */ static function unserialize(DOMElement $dom) { - if ($dom->firstChild && Sabre_DAV_XMLUtil::toClarkNotation($dom->firstChild)==='{DAV:}href') { + if (Sabre_DAV_XMLUtil::toClarkNotation($dom->firstChild)==='{DAV:}href') { return new self($dom->firstChild->textContent,false); } diff --git a/3rdparty/Sabre/DAV/Property/HrefList.php b/3rdparty/Sabre/DAV/Property/HrefList.php index 282c452ca0b..7a52272e885 100755 --- a/3rdparty/Sabre/DAV/Property/HrefList.php +++ b/3rdparty/Sabre/DAV/Property/HrefList.php @@ -79,7 +79,7 @@ class Sabre_DAV_Property_HrefList extends Sabre_DAV_Property { * It will only decode {DAV:}href values. * * @param DOMElement $dom - * @return Sabre_DAV_Property_HrefList + * @return Sabre_DAV_Property_Href */ static function unserialize(DOMElement $dom) { diff --git a/3rdparty/Sabre/DAV/Property/Response.php b/3rdparty/Sabre/DAV/Property/Response.php index 9f21163d12e..88afbcfb26d 100755 --- a/3rdparty/Sabre/DAV/Property/Response.php +++ b/3rdparty/Sabre/DAV/Property/Response.php @@ -138,7 +138,7 @@ class Sabre_DAV_Property_Response extends Sabre_DAV_Property implements Sabre_DA if (is_scalar($propertyValue)) { $text = $document->createTextNode($propertyValue); $currentProperty->appendChild($text); - } elseif ($propertyValue instanceof Sabre_DAV_PropertyInterface) { + } elseif ($propertyValue instanceof Sabre_DAV_Property) { $propertyValue->serialize($server,$currentProperty); } elseif (!is_null($propertyValue)) { throw new Sabre_DAV_Exception('Unknown property value type: ' . gettype($propertyValue) . ' for property: ' . $propertyName); diff --git a/3rdparty/Sabre/DAV/PropertyInterface.php b/3rdparty/Sabre/DAV/PropertyInterface.php deleted file mode 100755 index 515072cbd35..00000000000 --- a/3rdparty/Sabre/DAV/PropertyInterface.php +++ /dev/null @@ -1,21 +0,0 @@ -broadcastEvent('exception', array($e)); - } catch (Exception $ignore) { - } $DOM = new DOMDocument('1.0','utf-8'); $DOM->formatOutput = true; @@ -217,23 +214,17 @@ class Sabre_DAV_Server { $error->setAttribute('xmlns:s',self::NS_SABREDAV); $DOM->appendChild($error); - $h = function($v) { - - return htmlspecialchars($v, ENT_NOQUOTES, 'UTF-8'); - - }; - - $error->appendChild($DOM->createElement('s:exception',$h(get_class($e)))); - $error->appendChild($DOM->createElement('s:message',$h($e->getMessage()))); + $error->appendChild($DOM->createElement('s:exception',get_class($e))); + $error->appendChild($DOM->createElement('s:message',$e->getMessage())); if ($this->debugExceptions) { - $error->appendChild($DOM->createElement('s:file',$h($e->getFile()))); - $error->appendChild($DOM->createElement('s:line',$h($e->getLine()))); - $error->appendChild($DOM->createElement('s:code',$h($e->getCode()))); - $error->appendChild($DOM->createElement('s:stacktrace',$h($e->getTraceAsString()))); + $error->appendChild($DOM->createElement('s:file',$e->getFile())); + $error->appendChild($DOM->createElement('s:line',$e->getLine())); + $error->appendChild($DOM->createElement('s:code',$e->getCode())); + $error->appendChild($DOM->createElement('s:stacktrace',$e->getTraceAsString())); } if (self::$exposeVersion) { - $error->appendChild($DOM->createElement('s:sabredav-version',$h(Sabre_DAV_Version::VERSION))); + $error->appendChild($DOM->createElement('s:sabredav-version',Sabre_DAV_Version::VERSION)); } if($e instanceof Sabre_DAV_Exception) { @@ -517,7 +508,7 @@ class Sabre_DAV_Server { 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'); + if (!($node instanceof Sabre_DAV_IFile)) throw new Sabre_DAV_Exception_NotImplemented('GET is only implemented on File objects'); $body = $node->get(); // Converting string into stream, if needed. @@ -705,7 +696,6 @@ class Sabre_DAV_Server { // This is a multi-status response $this->httpResponse->sendStatus(207); $this->httpResponse->setHeader('Content-Type','application/xml; charset=utf-8'); - $this->httpResponse->setHeader('Vary','Brief,Prefer'); // Normally this header is only needed for OPTIONS responses, however.. // iCal seems to also depend on these being set for PROPFIND. Since @@ -714,10 +704,7 @@ class Sabre_DAV_Server { foreach($this->plugins as $plugin) $features = array_merge($features,$plugin->getFeatures()); $this->httpResponse->setHeader('DAV',implode(', ',$features)); - $prefer = $this->getHTTPPrefer(); - $minimal = $prefer['return-minimal']; - - $data = $this->generateMultiStatus($newProperties, $minimal); + $data = $this->generateMultiStatus($newProperties); $this->httpResponse->sendBody($data); } @@ -737,30 +724,6 @@ class Sabre_DAV_Server { $result = $this->updateProperties($uri, $newProperties); - $prefer = $this->getHTTPPrefer(); - $this->httpResponse->setHeader('Vary','Brief,Prefer'); - - if ($prefer['return-minimal']) { - - // If return-minimal is specified, we only have to check if the - // request was succesful, and don't need to return the - // multi-status. - $ok = true; - foreach($result as $code=>$prop) { - if ((int)$code > 299) { - $ok = false; - } - } - - if ($ok) { - - $this->httpResponse->sendStatus(204); - return; - - } - - } - $this->httpResponse->sendStatus(207); $this->httpResponse->setHeader('Content-Type','application/xml; charset=utf-8'); @@ -964,7 +927,7 @@ class Sabre_DAV_Server { * This method moves one uri to a different uri. A lot of the actual request processing is done in getCopyMoveInfo * * @param string $uri - * @return bool + * @return void */ protected function httpMove($uri) { @@ -1046,7 +1009,7 @@ class Sabre_DAV_Server { if ($this->broadcastEvent('report',array($reportName,$dom, $uri))) { // If broadcastEvent returned true, it means the report was not supported - throw new Sabre_DAV_Exception_ReportNotSupported(); + throw new Sabre_DAV_Exception_ReportNotImplemented(); } @@ -1195,85 +1158,6 @@ class Sabre_DAV_Server { } - /** - * Returns the HTTP Prefer header information. - * - * The prefer header is defined in: - * http://tools.ietf.org/html/draft-snell-http-prefer-14 - * - * This method will return an array with options. - * - * Currently, the following options may be returned: - * array( - * 'return-asynch' => true, - * 'return-minimal' => true, - * 'return-representation' => true, - * 'wait' => 30, - * 'strict' => true, - * 'lenient' => true, - * ) - * - * This method also supports the Brief header, and will also return - * 'return-minimal' if the brief header was set to 't'. - * - * For the boolean options, false will be returned if the headers are not - * specified. For the integer options it will be 'null'. - * - * @return array - */ - public function getHTTPPrefer() { - - $result = array( - 'return-asynch' => false, - 'return-minimal' => false, - 'return-representation' => false, - 'wait' => null, - 'strict' => false, - 'lenient' => false, - ); - - if ($prefer = $this->httpRequest->getHeader('Prefer')) { - - $parameters = array_map('trim', - explode(',', $prefer) - ); - - foreach($parameters as $parameter) { - - // Right now our regex only supports the tokens actually - // specified in the draft. We may need to expand this if new - // tokens get registered. - if(!preg_match('/^(?P[a-z0-9-]+)(?:=(?P[0-9]+))?$/', $parameter, $matches)) { - continue; - } - - switch($matches['token']) { - - case 'return-asynch' : - case 'return-minimal' : - case 'return-representation' : - case 'strict' : - case 'lenient' : - $result[$matches['token']] = true; - break; - case 'wait' : - $result[$matches['token']] = $matches['value']; - break; - - } - - } - - } - - if ($this->httpRequest->getHeader('Brief')=='t') { - $result['return-minimal'] = true; - } - - return $result; - - } - /** * Returns information about Copy and Move requests @@ -1549,18 +1433,15 @@ class Sabre_DAV_Server { } - $this->broadcastEvent('afterGetProperties',array(trim($myPath,'/'),&$newProperties, $node)); + $this->broadcastEvent('afterGetProperties',array(trim($myPath,'/'),&$newProperties)); $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), though this is non-standard. - if ($myPath!='' && isset($newProperties[200]['{DAV:}resourcetype'])) { - $rt = $newProperties[200]['{DAV:}resourcetype']; - if ($rt->is('{DAV:}collection') || $rt->is('{DAV:}principal')) { - $newProperties['href'] .='/'; - } - } + // Apple's iCal also requires a trailing slash for principals (rfc 3744). + // Therefore we add a trailing / for any non-file. This might need adjustments + // if we find there are other edge cases. + if ($myPath!='' && isset($newProperties[200]['{DAV:}resourcetype']) && count($newProperties[200]['{DAV:}resourcetype']->getValue())>0) $newProperties['href'] .='/'; // If the resourcetype property was manually added to the requested property list, // we will remove it again. @@ -1595,14 +1476,11 @@ class Sabre_DAV_Server { if (!$this->broadcastEvent('beforeBind',array($uri))) return false; $parent = $this->tree->getNodeForPath($dir); - if (!$parent instanceof Sabre_DAV_ICollection) { - throw new Sabre_DAV_Exception_Conflict('Files can only be created as children of collections'); - } if (!$this->broadcastEvent('beforeCreateFile',array($uri, &$data, $parent))) return false; $etag = $parent->createFile($name,$data); - $this->tree->markDirty($dir . '/' . $name); + $this->tree->markDirty($dir); $this->broadcastEvent('afterBind',array($uri)); $this->broadcastEvent('afterCreateFile',array($uri, $parent)); @@ -2023,15 +1901,12 @@ class Sabre_DAV_Server { /** - * Generates a WebDAV propfind response body based on a list of nodes. - * - * If 'strip404s' is set to true, all 404 responses will be removed. + * Generates a WebDAV propfind response body based on a list of nodes * * @param array $fileProperties The list with nodes - * @param bool strip404s * @return string */ - public function generateMultiStatus(array $fileProperties, $strip404s = false) { + public function generateMultiStatus(array $fileProperties) { $dom = new DOMDocument('1.0','utf-8'); //$dom->formatOutput = true; @@ -2050,10 +1925,6 @@ class Sabre_DAV_Server { $href = $entry['href']; unset($entry['href']); - if ($strip404s && isset($entry[404])) { - unset($entry[404]); - } - $response = new Sabre_DAV_Property_Response($href,$entry); $response->serialize($this,$multiStatus); @@ -2124,7 +1995,7 @@ class Sabre_DAV_Server { if (!$body) return array(); $dom = Sabre_DAV_XMLUtil::loadDOMDocument($body); - $elem = $dom->getElementsByTagNameNS('DAV:','propfind')->item(0); + $elem = $dom->getElementsByTagNameNS('urn:DAV','propfind')->item(0); return array_keys(Sabre_DAV_XMLUtil::parseProperties($elem)); } diff --git a/3rdparty/Sabre/DAV/ServerPlugin.php b/3rdparty/Sabre/DAV/ServerPlugin.php index 120569ffccd..131863d13fb 100755 --- a/3rdparty/Sabre/DAV/ServerPlugin.php +++ b/3rdparty/Sabre/DAV/ServerPlugin.php @@ -19,7 +19,7 @@ abstract class Sabre_DAV_ServerPlugin { * This function is called by Sabre_DAV_Server, after * addPlugin is called. * - * This method should set up the required event subscriptions. + * This method should set up the requires event subscriptions. * * @param Sabre_DAV_Server $server * @return void diff --git a/3rdparty/Sabre/DAV/SimpleCollection.php b/3rdparty/Sabre/DAV/SimpleCollection.php index 79e2eaaacd4..4acf971caa5 100755 --- a/3rdparty/Sabre/DAV/SimpleCollection.php +++ b/3rdparty/Sabre/DAV/SimpleCollection.php @@ -31,7 +31,7 @@ class Sabre_DAV_SimpleCollection extends Sabre_DAV_Collection { /** * Creates this node * - * The name of the node must be passed, child nodes can also be passed. + * 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 @@ -78,9 +78,6 @@ class Sabre_DAV_SimpleCollection extends Sabre_DAV_Collection { * 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 * - * This method must throw Sabre_DAV_Exception_NotFound if the node does not - * exist. - * * @param string $name * @throws Sabre_DAV_Exception_NotFound * @return Sabre_DAV_INode diff --git a/3rdparty/Sabre/DAV/SimpleDirectory.php b/3rdparty/Sabre/DAV/SimpleDirectory.php new file mode 100755 index 00000000000..621222ebc53 --- /dev/null +++ b/3rdparty/Sabre/DAV/SimpleDirectory.php @@ -0,0 +1,21 @@ +nodeType !== XML_ELEMENT_NODE) return null; - $ns = $dom->namespaceURI; + // 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; @@ -60,11 +64,29 @@ class Sabre_DAV_XMLUtil { } + /** + * This method takes an XML document (as string) and converts all instances of the + * DAV: namespace to urn:DAV + * + * 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) { + + // This is used to map the DAV: namespace to urn:DAV. This is needed, because the DAV: + // namespace is actually a violation of the XML namespaces specification, and will cause errors + return preg_replace("/xmlns(:[A-Za-z0-9_]*)?=(\"|\')DAV:(\\2)/","xmlns\\1=\\2urn:DAV\\2",$xmlDocument); + + } + /** * 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. + * It does not preserve whitespace, and it converts the DAV: namespace to urn:DAV. * * @param string $xml * @throws Sabre_DAV_Exception_BadRequest @@ -96,11 +118,10 @@ class Sabre_DAV_XMLUtil { libxml_clear_errors(); $dom = new DOMDocument(); + $dom->loadXML(self::convertDAVNamespace($xml),LIBXML_NOWARNING | LIBXML_NOERROR); // We don't generally care about any whitespace $dom->preserveWhiteSpace = false; - - $dom->loadXML($xml,LIBXML_NOWARNING | LIBXML_NOERROR); if ($error = libxml_get_last_error()) { libxml_clear_errors(); diff --git a/3rdparty/Sabre/DAV/includes.php b/3rdparty/Sabre/DAV/includes.php index 6728f88ce76..6a4890677ea 100755 --- a/3rdparty/Sabre/DAV/includes.php +++ b/3rdparty/Sabre/DAV/includes.php @@ -28,7 +28,7 @@ include __DIR__ . '/Locks/Backend/PDO.php'; include __DIR__ . '/Locks/LockInfo.php'; include __DIR__ . '/Node.php'; include __DIR__ . '/Property/IHref.php'; -include __DIR__ . '/PropertyInterface.php'; +include __DIR__ . '/Property.php'; include __DIR__ . '/Server.php'; include __DIR__ . '/ServerPlugin.php'; include __DIR__ . '/StringUtil.php'; @@ -60,7 +60,7 @@ include __DIR__ . '/Exception/NotFound.php'; include __DIR__ . '/Exception/NotImplemented.php'; include __DIR__ . '/Exception/PaymentRequired.php'; include __DIR__ . '/Exception/PreconditionFailed.php'; -include __DIR__ . '/Exception/ReportNotSupported.php'; +include __DIR__ . '/Exception/ReportNotImplemented.php'; include __DIR__ . '/Exception/RequestedRangeNotSatisfiable.php'; include __DIR__ . '/Exception/UnsupportedMediaType.php'; include __DIR__ . '/FS/Node.php'; @@ -72,18 +72,6 @@ include __DIR__ . '/IQuota.php'; include __DIR__ . '/Locks/Plugin.php'; include __DIR__ . '/Mount/Plugin.php'; include __DIR__ . '/ObjectTree.php'; -include __DIR__ . '/PartialUpdate/IFile.php'; -include __DIR__ . '/PartialUpdate/Plugin.php'; -include __DIR__ . '/Property.php'; -include __DIR__ . '/Tree/Filesystem.php'; -include __DIR__ . '/Collection.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__ . '/Property/GetLastModified.php'; include __DIR__ . '/Property/Href.php'; include __DIR__ . '/Property/HrefList.php'; @@ -93,6 +81,17 @@ 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 f67eadad6e9..e05b7749805 100755 --- a/3rdparty/Sabre/DAVACL/AbstractPrincipalCollection.php +++ b/3rdparty/Sabre/DAVACL/AbstractPrincipalCollection.php @@ -107,7 +107,7 @@ abstract class Sabre_DAVACL_AbstractPrincipalCollection extends Sabre_DAV_Collec * * @param string $name * @throws Sabre_DAV_Exception_NotFound - * @return Sabre_DAVACL_IPrincipal + * @return Sabre_DAV_IPrincipal */ public function getChild($name) { diff --git a/3rdparty/Sabre/DAVACL/IACL.php b/3rdparty/Sabre/DAVACL/IACL.php index 356bb481d55..003e6993483 100755 --- a/3rdparty/Sabre/DAVACL/IACL.php +++ b/3rdparty/Sabre/DAVACL/IACL.php @@ -48,7 +48,7 @@ interface Sabre_DAVACL_IACL extends Sabre_DAV_INode { /** * Updates the ACL * - * This method will receive a list of new ACE's as an array argument. + * This method will receive a list of new ACE's. * * @param array $acl * @return void diff --git a/3rdparty/Sabre/DAVACL/Plugin.php b/3rdparty/Sabre/DAVACL/Plugin.php index 5b17c838475..5c828c6d97b 100755 --- a/3rdparty/Sabre/DAVACL/Plugin.php +++ b/3rdparty/Sabre/DAVACL/Plugin.php @@ -3,7 +3,7 @@ /** * SabreDAV ACL Plugin * - * This plugin provides functionality to enforce ACL permissions. + * 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 @@ -102,11 +102,11 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { ); /** - * 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 + * 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 + * + * @var array */ public $adminPrincipals = array(); @@ -233,7 +233,6 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { $authPlugin = $this->server->getPlugin('auth'); if (is_null($authPlugin)) return null; - /** @var $authPlugin Sabre_DAV_Auth_Plugin */ $userName = $authPlugin->getCurrentUser(); if (!$userName) return null; @@ -242,14 +241,6 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { } - /** - * This array holds a cache for all the principals that are associated with - * a single principal. - * - * @var array - */ - protected $currentUserPrincipalsCache = array(); - /** * Returns a list of principals that's associated to the current * user, either directly or through group membership. @@ -262,11 +253,6 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { if (is_null($currentUser)) return array(); - // First check our cache - if (isset($this->currentUserPrincipalsCache[$currentUser])) { - return $this->currentUserPrincipalsCache[$currentUser]; - } - $check = array($currentUser); $principals = array($currentUser); @@ -291,9 +277,6 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { } - // Store the result in the cache - $this->currentUserPrincipalsCache[$currentUser] = $principals; - return $principals; } @@ -788,7 +771,7 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { * @param array $requestedProperties * @param array $returnedProperties * @TODO really should be broken into multiple methods, or even a class. - * @return bool + * @return void */ public function beforeGetProperties($uri, Sabre_DAV_INode $node, &$requestedProperties, &$returnedProperties) { @@ -912,18 +895,6 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { $returnedProperties[200]['{DAV:}acl-restrictions'] = new Sabre_DAVACL_Property_AclRestrictions(); } - /* Adding ACL properties */ - if ($node instanceof Sabre_DAVACL_IACL) { - - if (false !== ($index = array_search('{DAV:}owner', $requestedProperties))) { - - unset($requestedProperties[$index]); - $returnedProperties[200]['{DAV:}owner'] = new Sabre_DAV_Property_Href($node->getOwner() . '/'); - - } - - } - } /** @@ -957,9 +928,6 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { } $node->setGroupMemberSet($memberSet); - // We must also clear our cache, just in case - - $this->currentUserPrincipalsCache = array(); $result[200]['{DAV:}group-member-set'] = null; unset($propertyDelta['{DAV:}group-member-set']); @@ -967,7 +935,7 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { } /** - * This method handles HTTP REPORT requests + * This method handels HTTP REPORT requests * * @param string $reportName * @param DOMNode $dom @@ -1300,12 +1268,10 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin { } $result = $this->principalSearch($searchProperties, $requestedProperties, $uri); - $prefer = $this->server->getHTTPPRefer(); - - $this->server->httpResponse->sendStatus(207); + $xml = $this->server->generateMultiStatus($result); $this->server->httpResponse->setHeader('Content-Type','application/xml; charset=utf-8'); - $this->server->httpResponse->setHeader('Vary','Brief,Prefer'); - $this->server->httpResponse->sendBody($this->server->generateMultiStatus($result, $prefer['return-minimal'])); + $this->server->httpResponse->sendStatus(207); + $this->server->httpResponse->sendBody($xml); } diff --git a/3rdparty/Sabre/DAVACL/Property/Acl.php b/3rdparty/Sabre/DAVACL/Property/Acl.php index 3f79a8d532e..05e1a690b3c 100755 --- a/3rdparty/Sabre/DAVACL/Property/Acl.php +++ b/3rdparty/Sabre/DAVACL/Property/Acl.php @@ -88,11 +88,11 @@ class Sabre_DAVACL_Property_Acl extends Sabre_DAV_Property { static public function unserialize(DOMElement $dom) { $privileges = array(); - $xaces = $dom->getElementsByTagNameNS('DAV:','ace'); + $xaces = $dom->getElementsByTagNameNS('urn:DAV','ace'); for($ii=0; $ii < $xaces->length; $ii++) { $xace = $xaces->item($ii); - $principal = $xace->getElementsByTagNameNS('DAV:','principal'); + $principal = $xace->getElementsByTagNameNS('urn:DAV','principal'); if ($principal->length !== 1) { throw new Sabre_DAV_Exception_BadRequest('Each {DAV:}ace element must have one {DAV:}principal element'); } @@ -116,17 +116,17 @@ class Sabre_DAVACL_Property_Acl extends Sabre_DAV_Property { $protected = false; - if ($xace->getElementsByTagNameNS('DAV:','protected')->length > 0) { + if ($xace->getElementsByTagNameNS('urn:DAV','protected')->length > 0) { $protected = true; } - $grants = $xace->getElementsByTagNameNS('DAV:','grant'); + $grants = $xace->getElementsByTagNameNS('urn:DAV','grant'); if ($grants->length < 1) { throw new Sabre_DAV_Exception_NotImplemented('Every {DAV:}ace element must have a {DAV:}grant element. {DAV:}deny is not yet supported'); } $grant = $grants->item(0); - $xprivs = $grant->getElementsByTagNameNS('DAV:','privilege'); + $xprivs = $grant->getElementsByTagNameNS('urn:DAV','privilege'); for($jj=0; $jj<$xprivs->length; $jj++) { $xpriv = $xprivs->item($jj); diff --git a/3rdparty/Sabre/DAVACL/Property/Principal.php b/3rdparty/Sabre/DAVACL/Property/Principal.php index 3f681742276..c36328a58e0 100755 --- a/3rdparty/Sabre/DAVACL/Property/Principal.php +++ b/3rdparty/Sabre/DAVACL/Property/Principal.php @@ -15,7 +15,7 @@ class Sabre_DAVACL_Property_Principal extends Sabre_DAV_Property implements Sabre_DAV_Property_IHref { /** - * To specify a not-logged-in user, use the UNAUTHENTICATED principal + * To specify a not-logged-in user, use the UNAUTHENTICTED principal */ const UNAUTHENTICATED = 1; @@ -131,7 +131,7 @@ class Sabre_DAVACL_Property_Principal extends Sabre_DAV_Property implements Sabr * Deserializes a DOM element into a property object. * * @param DOMElement $dom - * @return Sabre_DAVACL_Property_Principal + * @return Sabre_DAV_Property_Principal */ static public function unserialize(DOMElement $dom) { diff --git a/3rdparty/Sabre/DAVACL/Version.php b/3rdparty/Sabre/DAVACL/Version.php index 084a9c13c89..9950f748741 100755 --- a/3rdparty/Sabre/DAVACL/Version.php +++ b/3rdparty/Sabre/DAVACL/Version.php @@ -14,7 +14,7 @@ class Sabre_DAVACL_Version { /** * Full version number */ - const VERSION = '1.7.0'; + const VERSION = '1.6.0'; /** * Stability : alpha, beta, stable diff --git a/3rdparty/Sabre/HTTP/Request.php b/3rdparty/Sabre/HTTP/Request.php index 74d5ed3d7ee..4746ef77704 100755 --- a/3rdparty/Sabre/HTTP/Request.php +++ b/3rdparty/Sabre/HTTP/Request.php @@ -184,7 +184,7 @@ class Sabre_HTTP_Request { * This method returns a readable stream resource. * If the asString parameter is set to true, a string is sent instead. * - * @param bool $asString + * @param bool asString * @return resource */ public function getBody($asString = false) { diff --git a/3rdparty/Sabre/HTTP/Response.php b/3rdparty/Sabre/HTTP/Response.php index 9d436881bdf..ffe9bda2082 100755 --- a/3rdparty/Sabre/HTTP/Response.php +++ b/3rdparty/Sabre/HTTP/Response.php @@ -4,7 +4,7 @@ * Sabre_HTTP_Response * * @package Sabre - * @subpackage HTTP + * @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 @@ -85,9 +85,6 @@ class Sabre_HTTP_Response { } - // @codeCoverageIgnoreStart - // We cannot reasonably test header() related methods. - /** * Sends an HTTP status header to the client * @@ -117,9 +114,7 @@ class Sabre_HTTP_Response { return header($name . ': ' . $value, $replace); else return false; - } - // @codeCoverageIgnoreEnd /** * Sets a bunch of HTTP Headers diff --git a/3rdparty/Sabre/HTTP/Version.php b/3rdparty/Sabre/HTTP/Version.php index 8ccd7c9edf6..e6b4f7e5358 100755 --- a/3rdparty/Sabre/HTTP/Version.php +++ b/3rdparty/Sabre/HTTP/Version.php @@ -14,7 +14,7 @@ class Sabre_HTTP_Version { /** * Full version number */ - const VERSION = '1.7.0'; + const VERSION = '1.6.4'; /** * Stability : alpha, beta, stable diff --git a/3rdparty/Sabre/VObject/Component.php b/3rdparty/Sabre/VObject/Component.php new file mode 100755 index 00000000000..b78a26133fa --- /dev/null +++ b/3rdparty/Sabre/VObject/Component.php @@ -0,0 +1,365 @@ + '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 + * be overridden with the iterator argument + * + * @param string $name + * @param Sabre_VObject_ElementList $iterator + */ + public function __construct($name, Sabre_VObject_ElementList $iterator = null) { + + $this->name = strtoupper($name); + if (!is_null($iterator)) $this->iterator = $iterator; + + } + + /** + * Turns the object back into a serialized blob. + * + * @return string + */ + public function serialize() { + + $str = "BEGIN:" . $this->name . "\r\n"; + + /** + * 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 component or element + * + * You can call this method with the following syntaxes: + * + * add(Sabre_VObject_Element $element) + * add(string $name, $value) + * + * The first version adds an Element + * The second adds a property as a string. + * + * @param mixed $item + * @param mixed $itemValue + * @return void + */ + public function add($item, $itemValue = null) { + + if ($item instanceof Sabre_VObject_Element) { + if (!is_null($itemValue)) { + throw new InvalidArgumentException('The second argument must not be specified, when passing a VObject'); + } + $item->parent = $this; + $this->children[] = $item; + } elseif(is_string($item)) { + + if (!is_scalar($itemValue)) { + throw new InvalidArgumentException('The second argument must be scalar'); + } + $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'); + + } + + } + + /** + * Returns an iterable list of children + * + * @return Sabre_VObject_ElementList + */ + public function children() { + + return new Sabre_VObject_ElementList($this->children); + + } + + /** + * 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 + * has not been assigned a group, specify ".EMAIL". + * + * Keys are retained from the 'children' array, which may be confusing in + * certain cases. + * + * @param string $name + * @return array + */ + public function select($name) { + + $group = null; + $name = strtoupper($name); + if (strpos($name,'.')!==false) { + list($group,$name) = explode('.', $name, 2); + } + + $result = array(); + foreach($this->children as $key=>$child) { + + if ( + strtoupper($child->name) === $name && + (is_null($group) || ( $child instanceof Sabre_VObject_Property && strtoupper($child->group) === $group)) + ) { + + $result[$key] = $child; + + } + } + + reset($result); + return $result; + + } + + /** + * 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 property or component, + * + * If there were no child-elements found with the specified name, + * null is returned. + * + * @param string $name + * @return Sabre_VObject_Property + */ + public function __get($name) { + + $matches = $this->select($name); + if (count($matches)===0) { + return null; + } else { + $firstMatch = current($matches); + /** @var $firstMatch Sabre_VObject_Property */ + $firstMatch->setIterator(new Sabre_VObject_ElementList(array_values($matches))); + return $firstMatch; + } + + } + + /** + * This method checks if a sub-element with the specified name exists. + * + * @param string $name + * @return bool + */ + public function __isset($name) { + + $matches = $this->select($name); + return count($matches)>0; + + } + + /** + * Using the setter method you can add properties or subcomponents + * + * You can either pass a Sabre_VObject_Component, Sabre_VObject_Property + * object, or a string to automatically create a Property. + * + * If the item already exists, it will be removed. If you want to add + * a new item with the same name, always use the add() method. + * + * @param string $name + * @param mixed $value + * @return void + */ + public function __set($name, $value) { + + $matches = $this->select($name); + $overWrite = count($matches)?key($matches):null; + + if ($value instanceof Sabre_VObject_Component || $value instanceof Sabre_VObject_Property) { + $value->parent = $this; + if (!is_null($overWrite)) { + $this->children[$overWrite] = $value; + } else { + $this->children[] = $value; + } + } elseif (is_scalar($value)) { + $property = Sabre_VObject_Property::create($name,$value); + $property->parent = $this; + if (!is_null($overWrite)) { + $this->children[$overWrite] = $property; + } else { + $this->children[] = $property; + } + } else { + throw new InvalidArgumentException('You must pass a Sabre_VObject_Component, Sabre_VObject_Property or scalar type'); + } + + } + + /** + * Removes all properties and components within this component. + * + * @param string $name + * @return void + */ + public function __unset($name) { + + $matches = $this->select($name); + foreach($matches as $k=>$child) { + + unset($this->children[$k]); + $child->parent = null; + + } + + } + + /* }}} */ + + /** + * 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 @@ +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 @@ +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..d6b910874d0 --- /dev/null +++ b/3rdparty/Sabre/VObject/Component/VEvent.php @@ -0,0 +1,71 @@ +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)) { + + // The DTEND property is considered non inclusive. So for a 3 day + // event in july, dtstart and dtend would have to be July 1st and + // July 4th respectively. + // + // See: + // http://tools.ietf.org/html/rfc5545#page-54 + $effectiveEnd = $this->DTEND->getDateTime(); + + } 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 @@ +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 @@ +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..23a4bb69916 --- /dev/null +++ b/3rdparty/Sabre/VObject/DateTimeParser.php @@ -0,0 +1,181 @@ +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\+|-)?P((?P\d+)W)?((?P\d+)D)?(T((?P\d+)H)?((?P\d+)M)?((?P\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'; + + } + + if ($duration==='P') { + $duration = 'PT0S'; + } + $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); + if ($newDur === '+') { $newDur = '+0 seconds'; }; + 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 new file mode 100755 index 00000000000..e20ff0b353c --- /dev/null +++ b/3rdparty/Sabre/VObject/Element.php @@ -0,0 +1,16 @@ +vevent where there's multiple VEVENT objects. + * + * @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_ElementList implements Iterator, Countable, ArrayAccess { + + /** + * Inner elements + * + * @var array + */ + protected $elements = array(); + + /** + * Creates the element list. + * + * @param array $elements + */ + public function __construct(array $elements) { + + $this->elements = $elements; + + } + + /* {{{ Iterator interface */ + + /** + * Current position + * + * @var int + */ + private $key = 0; + + /** + * Returns current item in iteration + * + * @return Sabre_VObject_Element + */ + public function current() { + + return $this->elements[$this->key]; + + } + + /** + * To the next item in the iterator + * + * @return void + */ + public function next() { + + $this->key++; + + } + + /** + * Returns the current iterator key + * + * @return int + */ + public function key() { + + return $this->key; + + } + + /** + * Returns true if the current position in the iterator is a valid one + * + * @return bool + */ + public function valid() { + + return isset($this->elements[$this->key]); + + } + + /** + * Rewinds the iterator + * + * @return void + */ + public function rewind() { + + $this->key = 0; + + } + + /* }}} */ + + /* {{{ Countable interface */ + + /** + * Returns the number of elements + * + * @return int + */ + public function count() { + + return count($this->elements); + + } + + /* }}} */ + + /* {{{ ArrayAccess Interface */ + + + /** + * Checks if an item exists through ArrayAccess. + * + * @param int $offset + * @return bool + */ + public function offsetExists($offset) { + + return isset($this->elements[$offset]); + + } + + /** + * Gets an item through ArrayAccess. + * + * @param int $offset + * @return mixed + */ + public function offsetGet($offset) { + + return $this->elements[$offset]; + + } + + /** + * Sets an item through ArrayAccess. + * + * @param int $offset + * @param mixed $value + * @return void + */ + public function offsetSet($offset,$value) { + + throw new LogicException('You can not add new objects to an ElementList'); + + } + + /** + * Sets an item through ArrayAccess. + * + * This method just forwards the request to the inner iterator + * + * @param int $offset + * @return void + */ + public function offsetUnset($offset) { + + throw new LogicException('You can not remove objects from an ElementList'); + + } + + /* }}} */ + +} diff --git a/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 @@ +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 new file mode 100755 index 00000000000..d89e01b56c6 --- /dev/null +++ b/3rdparty/Sabre/VObject/Node.php @@ -0,0 +1,149 @@ +iterator)) + return $this->iterator; + + return new Sabre_VObject_ElementList(array($this)); + + } + + /** + * Sets the overridden iterator + * + * Note that this is not actually part of the iterator interface + * + * @param Sabre_VObject_ElementList $iterator + * @return void + */ + public function setIterator(Sabre_VObject_ElementList $iterator) { + + $this->iterator = $iterator; + + } + + /* }}} */ + + /* {{{ Countable interface */ + + /** + * Returns the number of elements + * + * @return int + */ + public function count() { + + $it = $this->getIterator(); + return $it->count(); + + } + + /* }}} */ + + /* {{{ ArrayAccess Interface */ + + + /** + * Checks if an item exists through ArrayAccess. + * + * This method just forwards the request to the inner iterator + * + * @param int $offset + * @return bool + */ + public function offsetExists($offset) { + + $iterator = $this->getIterator(); + return $iterator->offsetExists($offset); + + } + + /** + * Gets an item through ArrayAccess. + * + * This method just forwards the request to the inner iterator + * + * @param int $offset + * @return mixed + */ + public function offsetGet($offset) { + + $iterator = $this->getIterator(); + return $iterator->offsetGet($offset); + + } + + /** + * Sets an item through ArrayAccess. + * + * This method just forwards the request to the inner iterator + * + * @param int $offset + * @param mixed $value + * @return void + */ + public function offsetSet($offset,$value) { + + $iterator = $this->getIterator(); + return $iterator->offsetSet($offset,$value); + + } + + /** + * Sets an item through ArrayAccess. + * + * This method just forwards the request to the inner iterator + * + * @param int $offset + * @return void + */ + public function offsetUnset($offset) { + + $iterator = $this->getIterator(); + return $iterator->offsetUnset($offset); + + } + + /* }}} */ + +} diff --git a/3rdparty/Sabre/VObject/Parameter.php b/3rdparty/Sabre/VObject/Parameter.php new file mode 100755 index 00000000000..2e39af5f78a --- /dev/null +++ b/3rdparty/Sabre/VObject/Parameter.php @@ -0,0 +1,84 @@ +name = strtoupper($name); + $this->value = $value; + + } + + /** + * Turns the object back into a serialized blob. + * + * @return string + */ + public function serialize() { + + if (is_null($this->value)) { + return $this->name; + } + $src = array( + '\\', + "\n", + ';', + ',', + ); + $out = array( + '\\\\', + '\n', + '\;', + '\,', + ); + + return $this->name . '=' . str_replace($src, $out, $this->value); + + } + + /** + * Called when this object is being cast to a string + * + * @return string + */ + public function __toString() { + + return $this->value; + + } + +} diff --git a/3rdparty/Sabre/VObject/ParseException.php b/3rdparty/Sabre/VObject/ParseException.php new file mode 100755 index 00000000000..1b5e95bf16e --- /dev/null +++ b/3rdparty/Sabre/VObject/ParseException.php @@ -0,0 +1,12 @@ + '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 + * be overridden with the iterator argument + * + * @param string $name + * @param string $value + * @param Sabre_VObject_ElementList $iterator + */ + public function __construct($name, $value = null, $iterator = null) { + + $name = strtoupper($name); + $group = null; + if (strpos($name,'.')!==false) { + list($group, $name) = explode('.', $name); + } + $this->name = $name; + $this->group = $group; + if (!is_null($iterator)) $this->iterator = $iterator; + $this->setValue($value); + + } + + + + /** + * Updates the internal value + * + * @param string $value + * @return void + */ + public function setValue($value) { + + $this->value = $value; + + } + + /** + * Turns the object back into a serialized blob. + * + * @return string + */ + public function serialize() { + + $str = $this->name; + if ($this->group) $str = $this->group . '.' . $this->name; + + if (count($this->parameters)) { + foreach($this->parameters as $param) { + + $str.=';' . $param->serialize(); + + } + } + $src = array( + '\\', + "\n", + ); + $out = array( + '\\\\', + '\n', + ); + $str.=':' . str_replace($src, $out, $this->value); + + $out = ''; + while(strlen($str)>0) { + if (strlen($str)>75) { + $out.= mb_strcut($str,0,75,'utf-8') . "\r\n"; + $str = ' ' . mb_strcut($str,75,strlen($str),'utf-8'); + } else { + $out.=$str . "\r\n"; + $str=''; + break; + } + } + + return $out; + + } + + /** + * Adds a new componenten or element + * + * You can call this method with the following syntaxes: + * + * 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 + * @return void + */ + public function add($item, $itemValue = null) { + + if ($item instanceof Sabre_VObject_Parameter) { + if (!is_null($itemValue)) { + throw new InvalidArgumentException('The second argument must not be specified, when passing a VObject'); + } + $item->parent = $this; + $this->parameters[] = $item; + } elseif(is_string($item)) { + + if (!is_scalar($itemValue) && !is_null($itemValue)) { + throw new InvalidArgumentException('The second argument must be scalar'); + } + $parameter = new Sabre_VObject_Parameter($item,$itemValue); + $parameter->parent = $this; + $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 + */ + public function offsetExists($name) { + + if (is_int($name)) return parent::offsetExists($name); + + $name = strtoupper($name); + + foreach($this->parameters as $parameter) { + if ($parameter->name == $name) return true; + } + return false; + + } + + /** + * Returns a parameter, or parameter list. + * + * @param string $name + * @return Sabre_VObject_Element + */ + public function offsetGet($name) { + + if (is_int($name)) return parent::offsetGet($name); + $name = strtoupper($name); + + $result = array(); + foreach($this->parameters as $parameter) { + if ($parameter->name == $name) + $result[] = $parameter; + } + + if (count($result)===0) { + return null; + } elseif (count($result)===1) { + return $result[0]; + } else { + $result[0]->setIterator(new Sabre_VObject_ElementList($result)); + return $result[0]; + } + + } + + /** + * Creates a new parameter + * + * @param string $name + * @param mixed $value + * @return void + */ + public function offsetSet($name, $value) { + + if (is_int($name)) return parent::offsetSet($name, $value); + + if (is_scalar($value)) { + if (!is_string($name)) + throw new InvalidArgumentException('A parameter name must be specified. This means you cannot use the $array[]="string" to add parameters.'); + + $this->offsetUnset($name); + $parameter = new Sabre_VObject_Parameter($name, $value); + $parameter->parent = $this; + $this->parameters[] = $parameter; + + } elseif ($value instanceof Sabre_VObject_Parameter) { + if (!is_null($name)) + throw new InvalidArgumentException('Don\'t specify a parameter name if you\'re passing a Sabre_VObject_Parameter. Add using $array[]=$parameterObject.'); + + $value->parent = $this; + $this->parameters[] = $value; + } else { + throw new InvalidArgumentException('You can only add parameters to the property object'); + } + + } + + /** + * Removes one or more parameters with the specified name + * + * @param string $name + * @return void + */ + public function offsetUnset($name) { + + if (is_int($name)) return parent::offsetUnset($name); + $name = strtoupper($name); + + foreach($this->parameters as $key=>$parameter) { + if ($parameter->name == $name) { + $parameter->parent = null; + unset($this->parameters[$key]); + } + + } + + } + + /* }}} */ + + /** + * Called when this object is being cast to a string + * + * @return string + */ + public function __toString() { + + 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 @@ +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[1-2][0-9]{3})(?P[0-1][0-9])(?P[0-3][0-9])'; + $time = '(?P[0-2][0-9])(?P[0-5][0-9])(?P[0-5][0-9])'; + $regex = "/^$date(T$time(?PZ)?)?$/"; + + 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 @@ +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 new file mode 100755 index 00000000000..eea73fa3dce --- /dev/null +++ b/3rdparty/Sabre/VObject/Reader.php @@ -0,0 +1,183 @@ +add(self::readLine($lines)); + + $nextLine = current($lines); + + if ($nextLine===false) + throw new Sabre_VObject_ParseException('Invalid VObject. Document ended prematurely.'); + + } + + // Checking component name of the 'END:' line. + if (substr($nextLine,4)!==$obj->name) { + throw new Sabre_VObject_ParseException('Invalid VObject, expected: "END:' . $obj->name . '" got: "' . $nextLine . '"'); + } + next($lines); + + return $obj; + + } + + // Properties + //$result = preg_match('/(?P[A-Z0-9-]+)(?:;(?P^(?([^:^\"]|\"([^\"]*)\")*))?"; + $regex = "/^(?P$token)$parameters:(?P.*)$/i"; + + $result = preg_match($regex,$line,$matches); + + if (!$result) { + throw new Sabre_VObject_ParseException('Invalid VObject, line ' . ($lineNr+1) . ' did not follow the icalendar/vcard format'); + } + + $propertyName = strtoupper($matches['name']); + $propertyValue = preg_replace_callback('#(\\\\(\\\\|N|n|;|,))#',function($matches) { + if ($matches[2]==='n' || $matches[2]==='N') { + return "\n"; + } else { + return $matches[2]; + } + }, $matches['value']); + + $obj = Sabre_VObject_Property::create($propertyName, $propertyValue); + + if ($matches['parameters']) { + + foreach(self::readParameters($matches['parameters']) as $param) { + $obj->add($param); + } + + } + + return $obj; + + + } + + /** + * Reads a parameter list from a property + * + * This method returns an array of Sabre_VObject_Parameter + * + * @param string $parameters + * @return array + */ + static private function readParameters($parameters) { + + $token = '[A-Z0-9-]+'; + + $paramValue = '(?P[^\"^;]*|"[^"]*")'; + + $regex = "/(?<=^|;)(?P$token)(=$paramValue(?=$|;))?/i"; + preg_match_all($regex, $parameters, $matches, PREG_SET_ORDER); + + $params = array(); + foreach($matches as $match) { + + $value = isset($match['paramValue'])?$match['paramValue']:null; + + if (isset($value[0])) { + // Stripping quotes, if needed + if ($value[0] === '"') $value = substr($value,1,strlen($value)-2); + } else { + $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); + + } + + return $params; + + } + + +} diff --git a/3rdparty/Sabre/VObject/RecurrenceIterator.php b/3rdparty/Sabre/VObject/RecurrenceIterator.php new file mode 100755 index 00000000000..740270dd8f0 --- /dev/null +++ b/3rdparty/Sabre/VObject/RecurrenceIterator.php @@ -0,0 +1,1043 @@ + 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)); + } elseif ($this->baseEvent->DTSTART->getDateType()===Sabre_VObject_Property_DateTime::DATE) { + $this->endDate->modify('+1 day'); + } + } + $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() { + + $currentMonth = $this->currentDate->format('n'); + $currentYear = $this->currentDate->format('Y'); + $currentDayOfMonth = $this->currentDate->format('j'); + + // No sub-rules, so we just advance by year + if (!$this->byMonth) { + + // Unless it was a leap day! + if ($currentMonth==2 && $currentDayOfMonth==29) { + + $counter = 0; + do { + $counter++; + // Here we increase the year count by the interval, until + // we hit a date that's also in a leap year. + // + // We could just find the next interval that's dividable by + // 4, but that would ignore the rule that there's no leap + // year every year that's dividable by a 100, but not by + // 400. (1800, 1900, 2100). So we just rely on the datetime + // functions instead. + $nextDate = clone $this->currentDate; + $nextDate->modify('+ ' . ($this->interval*$counter) . ' years'); + } while ($nextDate->format('n')!=2); + $this->currentDate = $nextDate; + + return; + + } + + // The easiest form + $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 { + + // These are the 'byMonth' rules, if there are no byDay or + // byMonthDay sub-rules. + 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 new file mode 100755 index 00000000000..9ee03d87118 --- /dev/null +++ b/3rdparty/Sabre/VObject/Version.php @@ -0,0 +1,24 @@ +'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 new file mode 100755 index 00000000000..0177a8f1ba6 --- /dev/null +++ b/3rdparty/Sabre/VObject/includes.php @@ -0,0 +1,41 @@ +