Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/server.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Reschke <lukas@statuscode.ch>2012-10-14 00:03:44 +0400
committerLukas Reschke <lukas@statuscode.ch>2012-10-14 00:04:22 +0400
commit183cc22501b75ab8819971f70b88dbc010026ac1 (patch)
tree878db72be46fe5394f8615c2bcf579d9e943d76b /3rdparty
parent5713dcfd11f6d0f57b6302bedeb22c18df5d73bb (diff)
Update SabreDAV to 1.7.1
Diffstat (limited to '3rdparty')
-rwxr-xr-x3rdparty/Sabre/CalDAV/Backend/Abstract.php190
-rwxr-xr-x3rdparty/Sabre/CalDAV/Backend/BackendInterface.php231
-rwxr-xr-x3rdparty/Sabre/CalDAV/Backend/NotificationSupport.php47
-rwxr-xr-x3rdparty/Sabre/CalDAV/Backend/PDO.php337
-rwxr-xr-x3rdparty/Sabre/CalDAV/Backend/SharingSupport.php238
-rwxr-xr-x3rdparty/Sabre/CalDAV/Calendar.php63
-rwxr-xr-x3rdparty/Sabre/CalDAV/CalendarObject.php22
-rwxr-xr-x3rdparty/Sabre/CalDAV/CalendarQueryParser.php12
-rwxr-xr-x3rdparty/Sabre/CalDAV/CalendarQueryValidator.php28
-rwxr-xr-x3rdparty/Sabre/CalDAV/CalendarRootNode.php13
-rwxr-xr-x3rdparty/Sabre/CalDAV/Exception/InvalidComponentType.php32
-rwxr-xr-x3rdparty/Sabre/CalDAV/ICSExportPlugin.php6
-rwxr-xr-x3rdparty/Sabre/CalDAV/ICalendar.php21
-rwxr-xr-x3rdparty/Sabre/CalDAV/IShareableCalendar.php48
-rwxr-xr-x3rdparty/Sabre/CalDAV/ISharedCalendar.php22
-rwxr-xr-x3rdparty/Sabre/CalDAV/Notifications/Collection.php169
-rwxr-xr-x3rdparty/Sabre/CalDAV/Notifications/ICollection.php22
-rwxr-xr-x3rdparty/Sabre/CalDAV/Notifications/INode.php38
-rwxr-xr-x3rdparty/Sabre/CalDAV/Notifications/INotificationType.php43
-rwxr-xr-x3rdparty/Sabre/CalDAV/Notifications/Node.php188
-rwxr-xr-x3rdparty/Sabre/CalDAV/Notifications/Notification/Invite.php276
-rwxr-xr-x3rdparty/Sabre/CalDAV/Notifications/Notification/InviteReply.php216
-rwxr-xr-x3rdparty/Sabre/CalDAV/Notifications/Notification/SystemStatus.php179
-rwxr-xr-x3rdparty/Sabre/CalDAV/Plugin.php579
-rwxr-xr-x3rdparty/Sabre/CalDAV/Property/AllowedSharingModes.php72
-rwxr-xr-x3rdparty/Sabre/CalDAV/Property/Invite.php173
-rwxr-xr-x3rdparty/Sabre/CalDAV/Property/ScheduleCalendarTransp.php99
-rwxr-xr-x3rdparty/Sabre/CalDAV/Schedule/IMip.php18
-rwxr-xr-x3rdparty/Sabre/CalDAV/Schedule/Outbox.php10
-rwxr-xr-x3rdparty/Sabre/CalDAV/Server.php68
-rwxr-xr-x3rdparty/Sabre/CalDAV/ShareableCalendar.php72
-rwxr-xr-x3rdparty/Sabre/CalDAV/SharedCalendar.php98
-rwxr-xr-x3rdparty/Sabre/CalDAV/SharingPlugin.php475
-rwxr-xr-x3rdparty/Sabre/CalDAV/UserCalendars.php64
-rwxr-xr-x3rdparty/Sabre/CalDAV/Version.php2
-rwxr-xr-x3rdparty/Sabre/CalDAV/includes.php25
-rwxr-xr-x3rdparty/Sabre/CardDAV/AddressBook.php4
-rwxr-xr-x3rdparty/Sabre/CardDAV/Card.php16
-rwxr-xr-x3rdparty/Sabre/CardDAV/Plugin.php55
-rwxr-xr-x3rdparty/Sabre/CardDAV/VCFExportPlugin.php107
-rwxr-xr-x3rdparty/Sabre/CardDAV/Version.php2
-rwxr-xr-x3rdparty/Sabre/CardDAV/includes.php1
-rwxr-xr-x3rdparty/Sabre/DAV/Browser/Plugin.php2
-rwxr-xr-x3rdparty/Sabre/DAV/Client.php69
-rwxr-xr-x3rdparty/Sabre/DAV/Collection.php6
-rwxr-xr-x3rdparty/Sabre/DAV/Directory.php17
-rwxr-xr-x3rdparty/Sabre/DAV/Exception/ReportNotSupported.php (renamed from 3rdparty/Sabre/DAV/Exception/ReportNotImplemented.php)4
-rwxr-xr-x3rdparty/Sabre/DAV/FS/Directory.php5
-rwxr-xr-x3rdparty/Sabre/DAV/FSExt/Directory.php5
-rwxr-xr-x3rdparty/Sabre/DAV/FSExt/File.php32
-rwxr-xr-x3rdparty/Sabre/DAV/ICollection.php5
-rwxr-xr-x3rdparty/Sabre/DAV/IFile.php2
-rwxr-xr-x3rdparty/Sabre/DAV/Locks/Plugin.php1
-rwxr-xr-x3rdparty/Sabre/DAV/Node.php2
-rwxr-xr-x3rdparty/Sabre/DAV/ObjectTree.php26
-rwxr-xr-x3rdparty/Sabre/DAV/PartialUpdate/IFile.php38
-rwxr-xr-x3rdparty/Sabre/DAV/PartialUpdate/Plugin.php209
-rwxr-xr-x3rdparty/Sabre/DAV/Property.php12
-rwxr-xr-x3rdparty/Sabre/DAV/Property/Href.php2
-rwxr-xr-x3rdparty/Sabre/DAV/Property/HrefList.php2
-rwxr-xr-x3rdparty/Sabre/DAV/Property/Response.php2
-rwxr-xr-x3rdparty/Sabre/DAV/PropertyInterface.php21
-rwxr-xr-x3rdparty/Sabre/DAV/Server.php175
-rwxr-xr-x3rdparty/Sabre/DAV/ServerPlugin.php2
-rwxr-xr-x3rdparty/Sabre/DAV/SimpleCollection.php5
-rwxr-xr-x3rdparty/Sabre/DAV/SimpleDirectory.php21
-rwxr-xr-x3rdparty/Sabre/DAV/Version.php2
-rwxr-xr-x3rdparty/Sabre/DAV/XMLUtil.php29
-rwxr-xr-x3rdparty/Sabre/DAV/includes.php27
-rwxr-xr-x3rdparty/Sabre/DAVACL/AbstractPrincipalCollection.php2
-rwxr-xr-x3rdparty/Sabre/DAVACL/IACL.php2
-rwxr-xr-x3rdparty/Sabre/DAVACL/Plugin.php54
-rwxr-xr-x3rdparty/Sabre/DAVACL/Property/Acl.php10
-rwxr-xr-x3rdparty/Sabre/DAVACL/Property/Principal.php4
-rwxr-xr-x3rdparty/Sabre/DAVACL/Version.php2
-rwxr-xr-x3rdparty/Sabre/HTTP/Request.php2
-rwxr-xr-x3rdparty/Sabre/HTTP/Response.php7
-rwxr-xr-x3rdparty/Sabre/HTTP/Version.php2
-rwxr-xr-x3rdparty/Sabre/VObject/Component.php365
-rwxr-xr-x3rdparty/Sabre/VObject/Component/VAlarm.php102
-rwxr-xr-x3rdparty/Sabre/VObject/Component/VCalendar.php133
-rwxr-xr-x3rdparty/Sabre/VObject/Component/VEvent.php71
-rwxr-xr-x3rdparty/Sabre/VObject/Component/VJournal.php46
-rwxr-xr-x3rdparty/Sabre/VObject/Component/VTodo.php68
-rwxr-xr-x3rdparty/Sabre/VObject/DateTimeParser.php181
-rwxr-xr-x3rdparty/Sabre/VObject/Element.php16
-rwxr-xr-x3rdparty/Sabre/VObject/Element/DateTime.php37
-rwxr-xr-x3rdparty/Sabre/VObject/Element/MultiDateTime.php17
-rwxr-xr-x3rdparty/Sabre/VObject/ElementList.php172
-rwxr-xr-x3rdparty/Sabre/VObject/FreeBusyGenerator.php297
-rwxr-xr-x3rdparty/Sabre/VObject/Node.php149
-rwxr-xr-x3rdparty/Sabre/VObject/Parameter.php84
-rwxr-xr-x3rdparty/Sabre/VObject/ParseException.php12
-rwxr-xr-x3rdparty/Sabre/VObject/Property.php348
-rwxr-xr-x3rdparty/Sabre/VObject/Property/DateTime.php260
-rwxr-xr-x3rdparty/Sabre/VObject/Property/MultiDateTime.php166
-rwxr-xr-x3rdparty/Sabre/VObject/Reader.php183
-rwxr-xr-x3rdparty/Sabre/VObject/RecurrenceIterator.php1043
-rwxr-xr-x3rdparty/Sabre/VObject/Version.php24
-rwxr-xr-x3rdparty/Sabre/VObject/WindowsTimezoneMap.php128
-rwxr-xr-x3rdparty/Sabre/VObject/includes.php41
-rwxr-xr-x3rdparty/Sabre/autoload.php28
102 files changed, 4658 insertions, 4502 deletions
diff --git a/3rdparty/Sabre/CalDAV/Backend/Abstract.php b/3rdparty/Sabre/CalDAV/Backend/Abstract.php
index 7aba1d69ffe..88e5b4a1a07 100755
--- a/3rdparty/Sabre/CalDAV/Backend/Abstract.php
+++ b/3rdparty/Sabre/CalDAV/Backend/Abstract.php
@@ -1,47 +1,19 @@
<?php
+use Sabre\VObject;
+
/**
* Abstract Calendaring backend. Extend this class to create your own backends.
*
+ * Checkout the BackendInterface for all the methods that must be implemented.
+ *
* @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
*/
-abstract class Sabre_CalDAV_Backend_Abstract {
-
- /**
- * Returns a list of calendars for a principal.
- *
- * Every project is an array with the following keys:
- * * id, a unique id that will be used by other functions to modify the
- * calendar. This can be the same as the uri or a database key.
- * * uri, which the basename of the uri with which the calendar is
- * accessed.
- * * principaluri. The owner of the calendar. Almost always the same as
- * principalUri passed to this method.
- *
- * Furthermore it can contain webdav properties in clark notation. A very
- * common one is '{DAV:}displayname'.
- *
- * @param string $principalUri
- * @return array
- */
- abstract function getCalendarsForUser($principalUri);
-
- /**
- * Creates a new calendar for a principal.
- *
- * If the creation was a success, an id must be returned that can be used to reference
- * this calendar in other methods, such as updateCalendar.
- *
- * @param string $principalUri
- * @param string $calendarUri
- * @param array $properties
- * @return void
- */
- abstract function createCalendar($principalUri,$calendarUri,array $properties);
+abstract class Sabre_CalDAV_Backend_Abstract implements Sabre_CalDAV_Backend_BackendInterface {
/**
* Updates properties for a calendar.
@@ -75,7 +47,7 @@ abstract class Sabre_CalDAV_Backend_Abstract {
* (403 Forbidden), which in turn also caused {DAV:}owner to fail
* (424 Failed Dependency) because the request needs to be atomic.
*
- * @param string $calendarId
+ * @param mixed $calendarId
* @param array $mutations
* @return bool|array
*/
@@ -86,83 +58,97 @@ abstract class Sabre_CalDAV_Backend_Abstract {
}
/**
- * Delete a calendar and all it's objects
+ * Performs a calendar-query on the contents of this calendar.
*
- * @param string $calendarId
- * @return void
- */
- abstract 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 string $calendarId
- * @return array
- */
- abstract function getCalendarObjects($calendarId);
-
- /**
- * Returns information from a single calendar object, based on it's object
- * uri.
+ * 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.
*
- * The returned array must have the same keys as getCalendarObjects. The
- * 'calendardata' object is required here though, while it's not required
- * for getCalendarObjects.
+ * This method provides a default implementation, which parses *all* the
+ * iCalendar objects in the specified calendar.
*
- * @param string $calendarId
- * @param string $objectUri
+ * 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
*/
- abstract function getCalendarObject($calendarId,$objectUri);
+ public function calendarQuery($calendarId, array $filters) {
- /**
- * Creates a new calendar object.
- *
- * @param string $calendarId
- * @param string $objectUri
- * @param string $calendarData
- * @return void
- */
- abstract function createCalendarObject($calendarId,$objectUri,$calendarData);
+ $result = array();
+ $objects = $this->getCalendarObjects($calendarId);
- /**
- * 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);
+ $validator = new Sabre_CalDAV_CalendarQueryValidator();
+
+ foreach($objects as $object) {
+
+ if ($this->validateFilterForObject($object, $filters)) {
+ $result[] = $object['uri'];
+ }
+
+ }
+
+ return $result;
+
+ }
/**
- * Deletes an existing calendar object.
+ * This method validates if a filters (as passed to calendarQuery) matches
+ * the given object.
*
- * @param string $calendarId
- * @param string $objectUri
- * @return void
+ * @param array $object
+ * @param array $filter
+ * @return bool
*/
- abstract function deleteCalendarObject($calendarId,$objectUri);
+ 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);
+
+ $validator = new Sabre_CalDAV_CalendarQueryValidator();
+ return $validator->validate($vObject, $filters);
+
+ }
+
}
diff --git a/3rdparty/Sabre/CalDAV/Backend/BackendInterface.php b/3rdparty/Sabre/CalDAV/Backend/BackendInterface.php
new file mode 100755
index 00000000000..881538ab60e
--- /dev/null
+++ b/3rdparty/Sabre/CalDAV/Backend/BackendInterface.php
@@ -0,0 +1,231 @@
+<?php
+
+/**
+ * Every CalDAV backend must at least implement this interface.
+ *
+ * @package Sabre
+ * @subpackage CalDAV
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+interface Sabre_CalDAV_Backend_BackendInterface {
+
+ /**
+ * Returns a list of calendars for a principal.
+ *
+ * Every project is an array with the following keys:
+ * * id, a unique id that will be used by other functions to modify the
+ * calendar. This can be the same as the uri or a database key.
+ * * uri, which the basename of the uri with which the calendar is
+ * accessed.
+ * * principaluri. The owner of the calendar. Almost always the same as
+ * principalUri passed to this method.
+ *
+ * Furthermore it can contain webdav properties in clark notation. A very
+ * common one is '{DAV:}displayname'.
+ *
+ * @param string $principalUri
+ * @return array
+ */
+ public function getCalendarsForUser($principalUri);
+
+ /**
+ * Creates a new calendar for a principal.
+ *
+ * If the creation was a success, an id must be returned that can be used to reference
+ * this calendar in other methods, such as updateCalendar.
+ *
+ * @param string $principalUri
+ * @param string $calendarUri
+ * @param array $properties
+ * @return void
+ */
+ public function createCalendar($principalUri,$calendarUri,array $properties);
+
+ /**
+ * Updates properties for a calendar.
+ *
+ * The mutations array uses the propertyName in clark-notation as key,
+ * and the array value for the property value. In the case a property
+ * should be deleted, the property value will be null.
+ *
+ * This method must be atomic. If one property cannot be changed, the
+ * entire operation must fail.
+ *
+ * If the operation was successful, true can be returned.
+ * If the operation failed, false can be returned.
+ *
+ * Deletion of a non-existent property is always successful.
+ *
+ * Lastly, it is optional to return detailed information about any
+ * failures. In this case an array should be returned with the following
+ * structure:
+ *
+ * array(
+ * 403 => 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
new file mode 100755
index 00000000000..d5a1409d9b9
--- /dev/null
+++ b/3rdparty/Sabre/CalDAV/Backend/NotificationSupport.php
@@ -0,0 +1,47 @@
+<?php
+
+/**
+ * Adds caldav notification support to a backend.
+ *
+ * Note: This feature is experimental, and may change in between different
+ * SabreDAV versions.
+ *
+ * Notifications are defined at:
+ * http://svn.calendarserver.org/repository/calendarserver/CalendarServer/trunk/doc/Extensions/caldav-notifications.txt
+ *
+ * These notifications are basically a list of server-generated notifications
+ * displayed to the user. Users can dismiss notifications by deleting them.
+ *
+ * The primary usecase is to allow for calendar-sharing.
+ *
+ * @package Sabre
+ * @subpackage CalDAV
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+interface Sabre_CalDAV_Backend_NotificationSupport extends Sabre_CalDAV_Backend_BackendInterface {
+
+ /**
+ * Returns a list of notifications for a given principal url.
+ *
+ * The returned array should only consist of implementations of
+ * Sabre_CalDAV_Notifications_INotificationType.
+ *
+ * @param string $principalUri
+ * @return array
+ */
+ public function getNotificationsForPrincipal($principalUri);
+
+ /**
+ * This deletes a specific notifcation.
+ *
+ * This may be called by a client once it deems a notification handled.
+ *
+ * @param string $principalUri
+ * @param Sabre_CalDAV_Notifications_INotificationType $notification
+ * @return void
+ */
+ public function deleteNotification($principalUri, Sabre_CalDAV_Notifications_INotificationType $notification);
+
+}
diff --git a/3rdparty/Sabre/CalDAV/Backend/PDO.php b/3rdparty/Sabre/CalDAV/Backend/PDO.php
index ddacf940c74..447f5f590cf 100755
--- a/3rdparty/Sabre/CalDAV/Backend/PDO.php
+++ b/3rdparty/Sabre/CalDAV/Backend/PDO.php
@@ -1,5 +1,7 @@
<?php
+use Sabre\VObject;
+
/**
* PDO CalDAV backend
*
@@ -9,12 +11,22 @@
* @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_Backend_PDO extends Sabre_CalDAV_Backend_Abstract {
/**
+ * We need to specify a max date, because we need to stop *somewhere*
+ *
+ * On 32 bit system the maximum for a signed integer is 2147483647, so
+ * MAX_DATE cannot be higher than date('Y-m-d', 2147483647) which results
+ * in 2038-01-19 to avoid problems when the date is converted
+ * to a unix timestamp.
+ */
+ const MAX_DATE = '2038-01-01';
+
+ /**
* pdo
*
* @var PDO
@@ -37,8 +49,9 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract {
/**
* List of CalDAV properties, and how they map to database fieldnames
+ * Add your own properties by simply adding on to this array.
*
- * Add your own properties by simply adding on to this array
+ * Note that only string-based properties are supported here.
*
* @var array
*/
@@ -90,6 +103,7 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract {
$fields[] = 'ctag';
$fields[] = 'components';
$fields[] = 'principaluri';
+ $fields[] = 'transparent';
// Making fields a comma-delimited list
$fields = implode(', ', $fields);
@@ -110,6 +124,7 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract {
'principaluri' => $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'),
);
@@ -142,11 +157,13 @@ 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
@@ -160,6 +177,10 @@ 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])) {
@@ -225,17 +246,25 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract {
foreach($mutations as $propertyName=>$propertyValue) {
- // We don't know about this property.
- if (!isset($this->propertyMap[$propertyName])) {
- $hasError = true;
- $result[403][$propertyName] = null;
- unset($mutations[$propertyName]);
- continue;
+ 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;
}
- $fieldName = $this->propertyMap[$propertyName];
- $newValues[$fieldName] = $propertyValue;
-
}
// If there were any errors we need to fail the request
@@ -316,9 +345,22 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract {
*/
public function getCalendarObjects($calendarId) {
- $stmt = $this->pdo->prepare('SELECT * FROM '.$this->calendarObjectTableName.' WHERE calendarid = ?');
+ $stmt = $this->pdo->prepare('SELECT id, uri, lastmodified, etag, calendarid, size FROM '.$this->calendarObjectTableName.' WHERE calendarid = ?');
$stmt->execute(array($calendarId));
- return $stmt->fetchAll();
+
+ $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;
}
@@ -336,44 +378,166 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract {
*/
public function getCalendarObject($calendarId,$objectUri) {
- $stmt = $this->pdo->prepare('SELECT * FROM '.$this->calendarObjectTableName.' WHERE calendarid = ? AND uri = ?');
+ $stmt = $this->pdo->prepare('SELECT id, uri, lastmodified, etag, calendarid, size, calendardata FROM '.$this->calendarObjectTableName.' WHERE calendarid = ? AND uri = ?');
$stmt->execute(array($calendarId, $objectUri));
- return $stmt->fetch();
+ $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'],
+ );
}
+
/**
* Creates a new calendar object.
*
- * @param string $calendarId
+ * 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 void
+ * @return string|null
*/
public function createCalendarObject($calendarId,$objectUri,$calendarData) {
- $stmt = $this->pdo->prepare('INSERT INTO '.$this->calendarObjectTableName.' (calendarid, uri, calendardata, lastmodified) VALUES (?,?,?,?)');
- $stmt->execute(array($calendarId,$objectUri,$calendarData,time()));
+ $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('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.
*
- * @param string $calendarId
+ * 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 void
+ * @return string|null
*/
public function updateCalendarObject($calendarId,$objectUri,$calendarData) {
- $stmt = $this->pdo->prepare('UPDATE '.$this->calendarObjectTableName.' SET calendardata = ?, lastmodified = ? WHERE calendarid = ? AND uri = ?');
- $stmt->execute(array($calendarData,time(),$calendarId,$objectUri));
+ $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->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,
+ );
+
}
/**
@@ -392,5 +556,132 @@ 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
new file mode 100755
index 00000000000..f73f0ff3d8a
--- /dev/null
+++ b/3rdparty/Sabre/CalDAV/Backend/SharingSupport.php
@@ -0,0 +1,238 @@
+<?php
+
+/**
+ * Adds support for sharing features to a CalDAV server.
+ *
+ * Note: This feature is experimental, and may change in between different
+ * SabreDAV versions.
+ *
+ * Early warning: Currently SabreDAV provides no implementation for this. This
+ * is, because in it's current state there is no elegant way to do this.
+ * The problem lies in the fact that a real CalDAV server with sharing support
+ * would first need email support (with invite notifications), and really also
+ * a browser-frontend that allows people to accept or reject these shares.
+ *
+ * In addition, the CalDAV backends are currently kept as independent as
+ * possible, and should not be aware of principals, email addresses or
+ * accounts.
+ *
+ * Adding an implementation for Sharing to standard-sabredav would contradict
+ * these goals, so for this reason this is currently not implemented, although
+ * it may very well in the future; but probably not before SabreDAV 2.0.
+ *
+ * The interface works however, so if you implement all this, and do it
+ * correctly sharing _will_ work. It's not particularly easy, and I _urge you_
+ * to make yourself acquainted with the following document first:
+ *
+ * https://trac.calendarserver.org/browser/CalendarServer/trunk/doc/Extensions/caldav-sharing.txt
+ *
+ * An overview
+ * ===========
+ *
+ * Implementing this interface will allow a user to share his or her calendars
+ * to other users. Effectively, when a calendar is shared the calendar will
+ * show up in both the Sharer's and Sharee's calendar-home root.
+ * This interface adds a few methods that ensure that this happens, and there
+ * are also a number of new requirements in the base-class you must now follow.
+ *
+ *
+ * How it works
+ * ============
+ *
+ * When a user shares a calendar, the addShare() method will be called with a
+ * list of sharees that are now added, and a list of sharees that have been
+ * removed.
+ * Removal is instant, but when a sharee is added the sharee first gets a
+ * chance to accept or reject the invitation for a share.
+ *
+ * After a share is accepted, the calendar will be returned from
+ * getUserCalendars for both the sharer, and the sharee.
+ *
+ * If the sharee deletes the calendar, only their share gets deleted. When the
+ * owner deletes a calendar, it will be removed for everybody.
+ *
+ *
+ * Notifications
+ * =============
+ *
+ * During all these sharing operations, a lot of notifications are sent back
+ * and forward.
+ *
+ * Whenever the list of sharees for a calendar has been changed (they have been
+ * added, removed or modified) all sharees should get a notification for this
+ * change.
+ * This notification is always represented by:
+ *
+ * Sabre_CalDAV_Notifications_Notification_Invite
+ *
+ * In the case of an invite, the sharee may reply with an 'accept' or
+ * 'decline'. These are always represented by:
+ *
+ * Sabre_CalDAV_Notifications_Notification_Invite
+ *
+ *
+ * Calendar access by sharees
+ * ==========================
+ *
+ * As mentioned earlier, shared calendars must now also be returned for
+ * getCalendarsForUser for sharees. A few things change though.
+ *
+ * The following properties must be specified:
+ *
+ * 1. {http://calendarserver.org/ns/}shared-url
+ *
+ * This property MUST contain the url to the original calendar, that is.. the
+ * path to the calendar from the owner.
+ *
+ * 2. {http://sabredav.org/ns}owner-principal
+ *
+ * This is a url to to the principal who is sharing the calendar.
+ *
+ * 3. {http://sabredav.org/ns}read-only
+ *
+ * This should be either 0 or 1, depending on if the user has read-only or
+ * read-write access to the calendar.
+ *
+ * Only when this is done, the calendar will correctly be marked as a calendar
+ * that's shared to him, thus allowing clients to display the correct interface
+ * and ACL enforcement.
+ *
+ * If a sharee deletes their calendar, only their instance of the calendar
+ * should be deleted, the original should still exists.
+ * Pretty much any 'dead' WebDAV properties on these shared calendars should be
+ * specific to a user. This means that if the displayname is changed by a
+ * sharee, the original is not affected. This is also true for:
+ * * The description
+ * * The color
+ * * The order
+ * * And any other dead properties.
+ *
+ * Properties like a ctag should not be different for multiple instances of the
+ * calendar.
+ *
+ * Lastly, objects *within* calendars should also have user-specific data. The
+ * two things that are user-specific are:
+ * * VALARM objects
+ * * The TRANSP property
+ *
+ * This _also_ implies that if a VALARM is deleted by a sharee for some event,
+ * this has no effect on the original VALARM.
+ *
+ * Understandably, the this last requirement is one of the hardest.
+ * Realisticly, I can see people ignoring this part of the spec, but that could
+ * cause a different set of issues.
+ *
+ *
+ * Publishing
+ * ==========
+ *
+ * When a user publishes a url, the server should generate a 'publish url'.
+ * This is a read-only url, anybody can use to consume the calendar feed.
+ *
+ * Calendars are in one of two states:
+ * * published
+ * * unpublished
+ *
+ * If a calendar is published, the following property should be returned
+ * for each calendar in getCalendarsForPrincipal.
+ *
+ * {http://calendarserver.org/ns/}publish-url
+ *
+ * This element should contain a {DAV:}href element, which points to the
+ * public url that does not require authentication. Unlike every other href,
+ * this url must be absolute.
+ *
+ * Ideally, the following property is always returned
+ *
+ * {http://calendarserver.org/ns/}pre-publish-url
+ *
+ * This property should contain the url that the calendar _would_ have, if it
+ * were to be published. iCal uses this to display the url, before the user
+ * will actually publish it.
+ *
+ *
+ * Selectively disabling publish or share feature
+ * ==============================================
+ *
+ * If Sabre_CalDAV_Property_AllowedSharingModes is returned from
+ * getCalendarsByUser, this allows the server to specify wether either sharing,
+ * or publishing is supported.
+ *
+ * This allows a client to determine in advance which features are available,
+ * and update the interface appropriately. If this property is not returned by
+ * the backend, the SharingPlugin automatically injects it and assumes both
+ * features are available.
+ *
+ * @package Sabre
+ * @subpackage CalDAV
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+interface Sabre_CalDAV_Backend_SharingSupport extends Sabre_CalDAV_Backend_NotificationSupport {
+
+ /**
+ * Updates the list of shares.
+ *
+ * The first array is a list of people that are to be added to the
+ * calendar.
+ *
+ * Every element in the add array has the following properties:
+ * * href - A url. Usually a mailto: address
+ * * commonName - Usually a first and last name, or false
+ * * summary - A description of the share, can also be false
+ * * readOnly - A boolean value
+ *
+ * Every element in the remove array is just the address string.
+ *
+ * Note that if the calendar is currently marked as 'not shared' by and
+ * this method is called, the calendar should be 'upgraded' to a shared
+ * calendar.
+ *
+ * @param mixed $calendarId
+ * @param array $add
+ * @param array $remove
+ * @return void
+ */
+ function updateShares($calendarId, array $add, array $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
+ *
+ * @param mixed $calendarId
+ * @return array
+ */
+ function getShares($calendarId);
+
+ /**
+ * This method is called when a user replied to a request to share.
+ *
+ * If the user chose to accept the share, this method should return the
+ * newly created calendar url.
+ *
+ * @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
+ */
+ function shareReply($href, $status, $calendarUri, $inReplyTo, $summary = null);
+
+ /**
+ * Publishes a calendar
+ *
+ * @param mixed $calendarId
+ * @param bool $value
+ * @return void
+ */
+ function setPublishStatus($calendarId, $value);
+
+}
diff --git a/3rdparty/Sabre/CalDAV/Calendar.php b/3rdparty/Sabre/CalDAV/Calendar.php
index 623df2dd1b8..63253febd5c 100755
--- a/3rdparty/Sabre/CalDAV/Calendar.php
+++ b/3rdparty/Sabre/CalDAV/Calendar.php
@@ -9,7 +9,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_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProperties, Sabre_DAVACL_IACL {
@@ -24,7 +24,7 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper
/**
* CalDAV backend
*
- * @var Sabre_CalDAV_Backend_Abstract
+ * @var Sabre_CalDAV_Backend_BackendInterface
*/
protected $caldavBackend;
@@ -39,16 +39,15 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper
* Constructor
*
* @param Sabre_DAVACL_IPrincipalBackend $principalBackend
- * @param Sabre_CalDAV_Backend_Abstract $caldavBackend
+ * @param Sabre_CalDAV_Backend_BackendInterface $caldavBackend
* @param array $calendarInfo
*/
- public function __construct(Sabre_DAVACL_IPrincipalBackend $principalBackend, Sabre_CalDAV_Backend_Abstract $caldavBackend, $calendarInfo) {
+ public function __construct(Sabre_DAVACL_IPrincipalBackend $principalBackend, Sabre_CalDAV_Backend_BackendInterface $caldavBackend, $calendarInfo) {
$this->caldavBackend = $caldavBackend;
$this->principalBackend = $principalBackend;
$this->calendarInfo = $calendarInfo;
-
}
/**
@@ -92,9 +91,6 @@ 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;
@@ -110,12 +106,21 @@ 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_DAV_ICalendarObject
+ * @return Sabre_CalDAV_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);
}
@@ -130,6 +135,13 @@ 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;
@@ -262,27 +274,27 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper
return array(
array(
'privilege' => '{DAV:}read',
- 'principal' => $this->calendarInfo['principaluri'],
+ 'principal' => $this->getOwner(),
'protected' => true,
),
array(
'privilege' => '{DAV:}write',
- 'principal' => $this->calendarInfo['principaluri'],
+ 'principal' => $this->getOwner(),
'protected' => true,
),
array(
'privilege' => '{DAV:}read',
- 'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write',
+ 'principal' => $this->getOwner() . '/calendar-proxy-write',
'protected' => true,
),
array(
'privilege' => '{DAV:}write',
- 'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write',
+ 'principal' => $this->getOwner() . '/calendar-proxy-write',
'protected' => true,
),
array(
'privilege' => '{DAV:}read',
- 'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-read',
+ 'principal' => $this->getOwner() . '/calendar-proxy-read',
'protected' => true,
),
array(
@@ -340,4 +352,27 @@ 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 72f0a578d16..40bd8588c70 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_Abstract
+ * Sabre_CalDAV_Backend_BackendInterface
*
* @var array
*/
@@ -35,11 +35,11 @@ class Sabre_CalDAV_CalendarObject extends Sabre_DAV_File implements Sabre_CalDAV
/**
* Constructor
*
- * @param Sabre_CalDAV_Backend_Abstract $caldavBackend
+ * @param Sabre_CalDAV_Backend_BackendInterface $caldavBackend
* @param array $calendarInfo
* @param array $objectData
*/
- public function __construct(Sabre_CalDAV_Backend_Abstract $caldavBackend,array $calendarInfo,array $objectData) {
+ public function __construct(Sabre_CalDAV_Backend_BackendInterface $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 $calendarData
- * @return void
+ * @param string|resource $calendarData
+ * @return string
*/
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';
+ return 'text/calendar; charset=utf-8';
}
@@ -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 time
+ * @return int
*/
public function getLastModified() {
@@ -206,6 +206,12 @@ 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 bd0d343382f..b95095f96fc 100755
--- a/3rdparty/Sabre/CalDAV/CalendarQueryParser.php
+++ b/3rdparty/Sabre/CalDAV/CalendarQueryParser.php
@@ -1,5 +1,7 @@
<?php
+use Sabre\VObject;
+
/**
* Parses the calendar-query report request body.
*
@@ -68,7 +70,7 @@ class Sabre_CalDAV_CalendarQueryParser {
$this->xpath = new DOMXPath($dom);
$this->xpath->registerNameSpace('cal',Sabre_CalDAV_Plugin::NS_CALDAV);
- $this->xpath->registerNameSpace('dav','urn:DAV');
+ $this->xpath->registerNameSpace('dav','DAV:');
}
@@ -241,12 +243,12 @@ class Sabre_CalDAV_CalendarQueryParser {
$timeRangeNode = $timeRangeNodes->item(0);
if ($start = $timeRangeNode->getAttribute('start')) {
- $start = Sabre_VObject_DateTimeParser::parseDateTime($start);
+ $start = VObject\DateTimeParser::parseDateTime($start);
} else {
$start = null;
}
if ($end = $timeRangeNode->getAttribute('end')) {
- $end = Sabre_VObject_DateTimeParser::parseDateTime($end);
+ $end = VObject\DateTimeParser::parseDateTime($end);
} else {
$end = null;
}
@@ -274,13 +276,13 @@ class Sabre_CalDAV_CalendarQueryParser {
if(!$start) {
throw new Sabre_DAV_Exception_BadRequest('The "start" attribute is required for the CALDAV:expand element');
}
- $start = Sabre_VObject_DateTimeParser::parseDateTime($start);
+ $start = VObject\DateTimeParser::parseDateTime($start);
$end = $parentNode->getAttribute('end');
if(!$end) {
throw new Sabre_DAV_Exception_BadRequest('The "end" attribute is required for the CALDAV:expand element');
}
- $end = Sabre_VObject_DateTimeParser::parseDateTime($end);
+ $end = 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 8f674840e87..53e86fc509f 100755
--- a/3rdparty/Sabre/CalDAV/CalendarQueryValidator.php
+++ b/3rdparty/Sabre/CalDAV/CalendarQueryValidator.php
@@ -1,5 +1,7 @@
<?php
+use Sabre\VObject;
+
/**
* CalendarQuery Validator
*
@@ -22,11 +24,11 @@ class Sabre_CalDAV_CalendarQueryValidator {
*
* The list of filters must be formatted as parsed by Sabre_CalDAV_CalendarQueryParser
*
- * @param Sabre_VObject_Component $vObject
+ * @param VObject\Component $vObject
* @param array $filters
* @return bool
*/
- public function validate(Sabre_VObject_Component $vObject,array $filters) {
+ public function validate(VObject\Component $vObject,array $filters) {
// The top level object is always a component filter.
// We'll parse it manually, as it's pretty simple.
@@ -48,11 +50,11 @@ class Sabre_CalDAV_CalendarQueryValidator {
* component we're checking should be specified, not the component to check
* itself.
*
- * @param Sabre_VObject_Component $parent
+ * @param VObject\Component $parent
* @param array $filters
* @return bool
*/
- protected function validateCompFilters(Sabre_VObject_Component $parent, array $filters) {
+ protected function validateCompFilters(VObject\Component $parent, array $filters) {
foreach($filters as $filter) {
@@ -117,11 +119,11 @@ class Sabre_CalDAV_CalendarQueryValidator {
* property we're checking should be specified, not the property to check
* itself.
*
- * @param Sabre_VObject_Component $parent
+ * @param VObject\Component $parent
* @param array $filters
* @return bool
*/
- protected function validatePropFilters(Sabre_VObject_Component $parent, array $filters) {
+ protected function validatePropFilters(VObject\Component $parent, array $filters) {
foreach($filters as $filter) {
@@ -187,11 +189,11 @@ class Sabre_CalDAV_CalendarQueryValidator {
* parameter we're checking should be specified, not the parameter to check
* itself.
*
- * @param Sabre_VObject_Property $parent
+ * @param VObject\Property $parent
* @param array $filters
* @return bool
*/
- protected function validateParamFilters(Sabre_VObject_Property $parent, array $filters) {
+ protected function validateParamFilters(VObject\Property $parent, array $filters) {
foreach($filters as $filter) {
@@ -243,11 +245,11 @@ class Sabre_CalDAV_CalendarQueryValidator {
* A single text-match should be specified as well as the specific property
* or parameter we need to validate.
*
- * @param Sabre_VObject_Node $parent
+ * @param VObject\Node $parent
* @param array $textMatch
* @return bool
*/
- protected function validateTextMatch(Sabre_VObject_Node $parent, array $textMatch) {
+ protected function validateTextMatch(VObject\Node $parent, array $textMatch) {
$value = (string)$parent;
@@ -263,12 +265,12 @@ class Sabre_CalDAV_CalendarQueryValidator {
* This is all based on the rules specified in rfc4791, which are quite
* complex.
*
- * @param Sabre_VObject_Node $component
+ * @param VObject\Node $component
* @param DateTime $start
* @param DateTime $end
* @return bool
*/
- protected function validateTimeRange(Sabre_VObject_Node $component, $start, $end) {
+ protected function validateTimeRange(VObject\Node $component, $start, $end) {
if (is_null($start)) {
$start = new DateTime('1900-01-01');
@@ -296,7 +298,7 @@ class Sabre_CalDAV_CalendarQueryValidator {
if ($component->parent->name === 'VEVENT' && $component->parent->RRULE) {
// Fire up the iterator!
- $it = new Sabre_VObject_RecurrenceIterator($component->parent->parent, (string)$component->parent->UID);
+ $it = new 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 3907913cc78..eb62eea75a6 100755
--- a/3rdparty/Sabre/CalDAV/CalendarRootNode.php
+++ b/3rdparty/Sabre/CalDAV/CalendarRootNode.php
@@ -1,14 +1,15 @@
<?php
/**
- * Users collection
+ * Calendars collection
*
- * This object is responsible for generating a collection of users.
+ * This object is responsible for generating a list of calendar-homes for each
+ * user.
*
* @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_CalendarRootNode extends Sabre_DAVACL_AbstractPrincipalCollection {
@@ -16,7 +17,7 @@ class Sabre_CalDAV_CalendarRootNode extends Sabre_DAVACL_AbstractPrincipalCollec
/**
* CalDAV backend
*
- * @var Sabre_CalDAV_Backend_Abstract
+ * @var Sabre_CalDAV_Backend_BackendInterface
*/
protected $caldavBackend;
@@ -32,10 +33,10 @@ class Sabre_CalDAV_CalendarRootNode extends Sabre_DAVACL_AbstractPrincipalCollec
*
*
* @param Sabre_DAVACL_IPrincipalBackend $principalBackend
- * @param Sabre_CalDAV_Backend_Abstract $caldavBackend
+ * @param Sabre_CalDAV_Backend_BackendInterface $caldavBackend
* @param string $principalPrefix
*/
- public function __construct(Sabre_DAVACL_IPrincipalBackend $principalBackend,Sabre_CalDAV_Backend_Abstract $caldavBackend, $principalPrefix = 'principals') {
+ public function __construct(Sabre_DAVACL_IPrincipalBackend $principalBackend,Sabre_CalDAV_Backend_BackendInterface $caldavBackend, $principalPrefix = 'principals') {
parent::__construct($principalBackend, $principalPrefix);
$this->caldavBackend = $caldavBackend;
diff --git a/3rdparty/Sabre/CalDAV/Exception/InvalidComponentType.php b/3rdparty/Sabre/CalDAV/Exception/InvalidComponentType.php
new file mode 100755
index 00000000000..4ac617d22f0
--- /dev/null
+++ b/3rdparty/Sabre/CalDAV/Exception/InvalidComponentType.php
@@ -0,0 +1,32 @@
+<?php
+
+/**
+ * Sabre_CalDAV_Exception_InvalidComponentType
+ *
+ * @package Sabre
+ * @subpackage CalDAV
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class Sabre_CalDAV_Exception_InvalidComponentType extends Sabre_DAV_Exception_Forbidden {
+
+ /**
+ * Adds in extra information in the xml response.
+ *
+ * This method adds the {CALDAV:}supported-calendar-component as defined in rfc4791
+ *
+ * @param Sabre_DAV_Server $server
+ * @param DOMElement $errorNode
+ * @return void
+ */
+ public function serialize(Sabre_DAV_Server $server,DOMElement $errorNode) {
+
+ $doc = $errorNode->ownerDocument;
+
+ $np = $doc->createElementNS(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 ec42b406b2f..d3e4e7b7201 100755
--- a/3rdparty/Sabre/CalDAV/ICSExportPlugin.php
+++ b/3rdparty/Sabre/CalDAV/ICSExportPlugin.php
@@ -1,5 +1,7 @@
<?php
+use Sabre\VObject;
+
/**
* ICS Exporter
*
@@ -82,7 +84,7 @@ class Sabre_CalDAV_ICSExportPlugin extends Sabre_DAV_ServerPlugin {
*/
public function generateICS(array $nodes) {
- $calendar = new Sabre_VObject_Component('vcalendar');
+ $calendar = new VObject\Component('vcalendar');
$calendar->version = '2.0';
if (Sabre_DAV_Server::$exposeVersion) {
$calendar->prodid = '-//SabreDAV//SabreDAV ' . Sabre_DAV_Version::VERSION . '//EN';
@@ -103,7 +105,7 @@ class Sabre_CalDAV_ICSExportPlugin extends Sabre_DAV_ServerPlugin {
}
$nodeData = $node[200]['{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}calendar-data'];
- $nodeComp = Sabre_VObject_Reader::read($nodeData);
+ $nodeComp = VObject\Reader::read($nodeData);
foreach($nodeComp->children() as $child) {
diff --git a/3rdparty/Sabre/CalDAV/ICalendar.php b/3rdparty/Sabre/CalDAV/ICalendar.php
index 15d51ebcf79..40aa9f9579c 100755
--- a/3rdparty/Sabre/CalDAV/ICalendar.php
+++ b/3rdparty/Sabre/CalDAV/ICalendar.php
@@ -8,11 +8,28 @@
* @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
new file mode 100755
index 00000000000..5b55788c014
--- /dev/null
+++ b/3rdparty/Sabre/CalDAV/IShareableCalendar.php
@@ -0,0 +1,48 @@
+<?php
+
+/**
+ * This interface represents a Calendar that can be shared with other users.
+ *
+ * @package Sabre
+ * @subpackage CalDAV
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+interface Sabre_CalDAV_IShareableCalendar extends Sabre_CalDAV_ICalendar {
+
+ /**
+ * Updates the list of shares.
+ *
+ * The first array is a list of people that are to be added to the
+ * calendar.
+ *
+ * Every element in the add array has the following properties:
+ * * href - A url. Usually a mailto: address
+ * * commonName - Usually a first and last name, or false
+ * * summary - A description of the share, can also be false
+ * * readOnly - A boolean value
+ *
+ * Every element in the remove array is just the address string.
+ *
+ * @param array $add
+ * @param array $remove
+ * @return void
+ */
+ function updateShares(array $add, array $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
+ */
+ function getShares();
+
+}
diff --git a/3rdparty/Sabre/CalDAV/ISharedCalendar.php b/3rdparty/Sabre/CalDAV/ISharedCalendar.php
new file mode 100755
index 00000000000..eb4d31fead5
--- /dev/null
+++ b/3rdparty/Sabre/CalDAV/ISharedCalendar.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * This interface represents a Calendar that is shared by a different user.
+ *
+ * @package Sabre
+ * @subpackage CalDAV
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+interface Sabre_CalDAV_ISharedCalendar extends Sabre_CalDAV_ICalendar {
+
+ /**
+ * This method should return the url of the owners' copy of the shared
+ * calendar.
+ *
+ * @return string
+ */
+ function getSharedUrl();
+
+}
diff --git a/3rdparty/Sabre/CalDAV/Notifications/Collection.php b/3rdparty/Sabre/CalDAV/Notifications/Collection.php
new file mode 100755
index 00000000000..83b6c9301dc
--- /dev/null
+++ b/3rdparty/Sabre/CalDAV/Notifications/Collection.php
@@ -0,0 +1,169 @@
+<?php
+
+/**
+ * This node represents a list of notifications.
+ *
+ * It provides no additional functionality, but you must implement this
+ * interface to allow the Notifications plugin to mark the collection
+ * as a notifications collection.
+ *
+ * This collection should only return Sabre_CalDAV_Notifications_INode nodes as
+ * its children.
+ *
+ * @package Sabre
+ * @subpackage CalDAV
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class Sabre_CalDAV_Notifications_Collection extends Sabre_DAV_Collection implements Sabre_CalDAV_Notifications_ICollection, Sabre_DAVACL_IACL {
+
+ /**
+ * The notification backend
+ *
+ * @var Sabre_CalDAV_Backend_NotificationSupport
+ */
+ protected $caldavBackend;
+
+ /**
+ * Principal uri
+ *
+ * @var string
+ */
+ protected $principalUri;
+
+ /**
+ * Constructor
+ *
+ * @param Sabre_CalDAV_Backend_NotificationSupport $caldavBackend
+ * @param string $principalUri
+ */
+ public function __construct(Sabre_CalDAV_Backend_NotificationSupport $caldavBackend, $principalUri) {
+
+ $this->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
new file mode 100755
index 00000000000..eb873af3f92
--- /dev/null
+++ b/3rdparty/Sabre/CalDAV/Notifications/ICollection.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * This node represents a list of notifications.
+ *
+ * It provides no additional functionality, but you must implement this
+ * interface to allow the Notifications plugin to mark the collection
+ * as a notifications collection.
+ *
+ * This collection should only return Sabre_CalDAV_Notifications_INode nodes as
+ * its children.
+ *
+ * @package Sabre
+ * @subpackage CalDAV
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+interface Sabre_CalDAV_Notifications_ICollection extends Sabre_DAV_ICollection {
+
+
+}
diff --git a/3rdparty/Sabre/CalDAV/Notifications/INode.php b/3rdparty/Sabre/CalDAV/Notifications/INode.php
new file mode 100755
index 00000000000..84721de5ab7
--- /dev/null
+++ b/3rdparty/Sabre/CalDAV/Notifications/INode.php
@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * This node represents a single notification.
+ *
+ * The signature is mostly identical to that of Sabre_DAV_IFile, but the get() method
+ * MUST return an xml document that matches the requirements of the
+ * 'caldav-notifications.txt' spec.
+ *
+ * For a complete example, check out the Notification class, which contains
+ * some helper functions.
+ *
+ * @package Sabre
+ * @subpackage CalDAV
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+interface Sabre_CalDAV_Notifications_INode {
+
+ /**
+ * This method must return an xml element, using the
+ * Sabre_CalDAV_Notifications_INotificationType classes.
+ *
+ * @return Sabre_DAVNotification_INotificationType
+ */
+ function getNotificationType();
+
+ /**
+ * Returns the etag for the notification.
+ *
+ * The etag must be surrounded by litteral double-quotes.
+ *
+ * @return string
+ */
+ function getETag();
+
+}
diff --git a/3rdparty/Sabre/CalDAV/Notifications/INotificationType.php b/3rdparty/Sabre/CalDAV/Notifications/INotificationType.php
new file mode 100755
index 00000000000..02a65a01fa3
--- /dev/null
+++ b/3rdparty/Sabre/CalDAV/Notifications/INotificationType.php
@@ -0,0 +1,43 @@
+<?php
+
+/**
+ * This interface reflects a single notification type.
+ *
+ * @package Sabre
+ * @subpackage CalDAV
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+interface Sabre_CalDAV_Notifications_INotificationType extends Sabre_DAV_PropertyInterface {
+
+ /**
+ * This method serializes the entire notification, as it is used in the
+ * response body.
+ *
+ * @param Sabre_DAV_Server $server
+ * @param DOMElement $node
+ * @return void
+ */
+ function serializeBody(Sabre_DAV_Server $server, \DOMElement $node);
+
+ /**
+ * Returns a unique id for this notification
+ *
+ * This is just the base url. This should generally be some kind of unique
+ * id.
+ *
+ * @return string
+ */
+ function getId();
+
+ /**
+ * Returns the ETag for this notification.
+ *
+ * The ETag must be surrounded by literal double-quotes.
+ *
+ * @return string
+ */
+ function getETag();
+
+}
diff --git a/3rdparty/Sabre/CalDAV/Notifications/Node.php b/3rdparty/Sabre/CalDAV/Notifications/Node.php
new file mode 100755
index 00000000000..8021a75debf
--- /dev/null
+++ b/3rdparty/Sabre/CalDAV/Notifications/Node.php
@@ -0,0 +1,188 @@
+<?php
+
+/**
+ * This node represents a single notification.
+ *
+ * The signature is mostly identical to that of Sabre_DAV_IFile, but the get() method
+ * MUST return an xml document that matches the requirements of the
+ * 'caldav-notifications.txt' spec.
+
+ * @package Sabre
+ * @subpackage CalDAV
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class Sabre_CalDAV_Notifications_Node extends Sabre_DAV_File implements Sabre_CalDAV_Notifications_INode, Sabre_DAVACL_IACL {
+
+ /**
+ * The notification backend
+ *
+ * @var Sabre_CalDAV_Backend_NotificationSupport
+ */
+ protected $caldavBackend;
+
+ /**
+ * The actual notification
+ *
+ * @var Sabre_CalDAV_Notifications_INotificationType
+ */
+ protected $notification;
+
+ /**
+ * Owner principal of the notification
+ *
+ * @var string
+ */
+ protected $principalUri;
+
+ /**
+ * Constructor
+ *
+ * @param Sabre_CalDAV_Backend_NotificationSupport $caldavBackend
+ * @param string $principalUri
+ * @param Sabre_CalDAV_Notifications_INotificationType $notification
+ */
+ public function __construct(Sabre_CalDAV_Backend_NotificationSupport $caldavBackend, $principalUri, Sabre_CalDAV_Notifications_INotificationType $notification) {
+
+ $this->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
new file mode 100755
index 00000000000..a6b36203f34
--- /dev/null
+++ b/3rdparty/Sabre/CalDAV/Notifications/Notification/Invite.php
@@ -0,0 +1,276 @@
+<?php
+
+use Sabre_CalDAV_SharingPlugin as SharingPlugin;
+
+/**
+ * This class represents the cs:invite-notification notification element.
+ *
+ * @package Sabre
+ * @subpackage CalDAV
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class Sabre_CalDAV_Notifications_Notification_Invite extends Sabre_DAV_Property implements Sabre_CalDAV_Notifications_INotificationType {
+
+ /**
+ * A unique id for the message
+ *
+ * @var string
+ */
+ protected $id;
+
+ /**
+ * Timestamp of the notification
+ *
+ * @var DateTime
+ */
+ protected $dtStamp;
+
+ /**
+ * A url to the recipient of the notification. This can be an email
+ * address (mailto:), or a principal url.
+ *
+ * @var string
+ */
+ protected $href;
+
+ /**
+ * The type of message, see the SharingPlugin::STATUS_* constants.
+ *
+ * @var int
+ */
+ protected $type;
+
+ /**
+ * True if access to a calendar is read-only.
+ *
+ * @var bool
+ */
+ protected $readOnly;
+
+ /**
+ * A url to the shared calendar.
+ *
+ * @var string
+ */
+ protected $hostUrl;
+
+ /**
+ * Url to the sharer of the calendar
+ *
+ * @var string
+ */
+ protected $organizer;
+
+ /**
+ * The name of the sharer.
+ *
+ * @var string
+ */
+ protected $commonName;
+
+ /**
+ * A description of the share request
+ *
+ * @var string
+ */
+ protected $summary;
+
+ /**
+ * The Etag for the notification
+ *
+ * @var string
+ */
+ protected $etag;
+
+ /**
+ * The list of supported components
+ *
+ * @var Sabre_CalDAV_Property_SupportedCalendarComponentSet
+ */
+ protected $supportedComponents;
+
+ /**
+ * Creates the Invite notification.
+ *
+ * This constructor receives an array with the following elements:
+ *
+ * * id - A unique id
+ * * etag - The etag
+ * * dtStamp - A DateTime object with a timestamp for the notification.
+ * * type - The type of notification, see SharingPlugin::STATUS_*
+ * constants for details.
+ * * readOnly - This must be set to true, if this is an invite for
+ * read-only access to a calendar.
+ * * hostUrl - A url to the shared calendar.
+ * * organizer - Url to the sharer principal.
+ * * commonName - The real name of the sharer (optional).
+ * * summary - Description of the share, can be the same as the
+ * calendar, but may also be modified (optional).
+ * * supportedComponents - An instance of
+ * Sabre_CalDAV_Property_SupportedCalendarComponentSet.
+ * This allows the client to determine which components
+ * will be supported in the shared calendar. This is
+ * also optional.
+ *
+ * @param array $values All the options
+ */
+ public function __construct(array $values) {
+
+ $required = array(
+ 'id',
+ 'etag',
+ 'href',
+ 'dtStamp',
+ 'type',
+ 'readOnly',
+ 'hostUrl',
+ 'organizer',
+ );
+ foreach($required as $item) {
+ if (!isset($values[$item])) {
+ throw new InvalidArgumentException($item . ' is a required constructor option');
+ }
+ }
+
+ foreach($values as $key=>$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
new file mode 100755
index 00000000000..e935aa5aa11
--- /dev/null
+++ b/3rdparty/Sabre/CalDAV/Notifications/Notification/InviteReply.php
@@ -0,0 +1,216 @@
+<?php
+
+use Sabre_CalDAV_SharingPlugin as SharingPlugin;
+
+/**
+ * This class represents the cs:invite-reply notification element.
+ *
+ * @package Sabre
+ * @subpackage CalDAV
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class Sabre_CalDAV_Notifications_Notification_InviteReply extends Sabre_DAV_Property implements Sabre_CalDAV_Notifications_INotificationType {
+
+ /**
+ * A unique id for the message
+ *
+ * @var string
+ */
+ protected $id;
+
+ /**
+ * Timestamp of the notification
+ *
+ * @var DateTime
+ */
+ protected $dtStamp;
+
+ /**
+ * The unique id of the notification this was a reply to.
+ *
+ * @var string
+ */
+ protected $inReplyTo;
+
+ /**
+ * A url to the recipient of the original (!) notification.
+ *
+ * @var string
+ */
+ protected $href;
+
+ /**
+ * The type of message, see the SharingPlugin::STATUS_ constants.
+ *
+ * @var int
+ */
+ protected $type;
+
+ /**
+ * A url to the shared calendar.
+ *
+ * @var string
+ */
+ protected $hostUrl;
+
+ /**
+ * A description of the share request
+ *
+ * @var string
+ */
+ protected $summary;
+
+ /**
+ * Notification Etag
+ *
+ * @var string
+ */
+ protected $etag;
+
+ /**
+ * Creates the Invite Reply Notification.
+ *
+ * This constructor receives an array with the following elements:
+ *
+ * * id - A unique id
+ * * etag - The etag
+ * * dtStamp - A DateTime object with a timestamp for the notification.
+ * * inReplyTo - This should refer to the 'id' of the notification
+ * this is a reply to.
+ * * type - The type of notification, see SharingPlugin::STATUS_*
+ * constants for details.
+ * * hostUrl - A url to the shared calendar.
+ * * summary - Description of the share, can be the same as the
+ * calendar, but may also be modified (optional).
+ */
+ public function __construct(array $values) {
+
+ $required = array(
+ 'id',
+ 'etag',
+ 'href',
+ 'dtStamp',
+ 'inReplyTo',
+ 'type',
+ 'hostUrl',
+ );
+ foreach($required as $item) {
+ if (!isset($values[$item])) {
+ throw new InvalidArgumentException($item . ' is a required constructor option');
+ }
+ }
+
+ foreach($values as $key=>$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
new file mode 100755
index 00000000000..f09ed3525f5
--- /dev/null
+++ b/3rdparty/Sabre/CalDAV/Notifications/Notification/SystemStatus.php
@@ -0,0 +1,179 @@
+<?php
+
+/**
+ * SystemStatus notification
+ *
+ * This notification can be used to indicate to the user that the system is
+ * down.
+ *
+ * @package Sabre
+ * @subpackage CalDAV
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class Sabre_CalDAV_Notifications_Notification_SystemStatus extends Sabre_DAV_Property implements Sabre_CalDAV_Notifications_INotificationType {
+
+ const TYPE_LOW = 1;
+ const TYPE_MEDIUM = 2;
+ const TYPE_HIGH = 3;
+
+ /**
+ * A unique id
+ *
+ * @var string
+ */
+ protected $id;
+
+ /**
+ * The type of alert. This should be one of the TYPE_ constants.
+ *
+ * @var int
+ */
+ protected $type;
+
+ /**
+ * A human-readable description of the problem.
+ *
+ * @var string
+ */
+ protected $description;
+
+ /**
+ * A url to a website with more information for the user.
+ *
+ * @var string
+ */
+ protected $href;
+
+ /**
+ * Notification Etag
+ *
+ * @var string
+ */
+ protected $etag;
+
+ /**
+ * Creates the notification.
+ *
+ * Some kind of unique id should be provided. This is used to generate a
+ * url.
+ *
+ * @param string $id
+ * @param string $etag
+ * @param int $type
+ * @param string $description
+ * @param string $href
+ */
+ public function __construct($id, $etag, $type = self::TYPE_HIGH, $description = null, $href = null) {
+
+ $this->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 c56ab384844..f3d11969c8b 100755
--- a/3rdparty/Sabre/CalDAV/Plugin.php
+++ b/3rdparty/Sabre/CalDAV/Plugin.php
@@ -1,5 +1,7 @@
<?php
+use Sabre\VObject;
+
/**
* CalDAV plugin
*
@@ -25,16 +27,6 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
const NS_CALENDARSERVER = 'http://calendarserver.org/ns/';
/**
- * The following constants are used to differentiate
- * the various filters for the calendar-query report
- */
- const FILTER_COMPFILTER = 1;
- const FILTER_TIMERANGE = 3;
- const FILTER_PROPFILTER = 4;
- const FILTER_PARAMFILTER = 5;
- const FILTER_TEXTMATCH = 6;
-
- /**
* The hardcoded root for calendar objects. It is unfortunate
* that we're stuck with it, but it will have to do for now
*/
@@ -172,16 +164,19 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
$server->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,
@@ -205,7 +200,9 @@ 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 . '}calendar-proxy-write-for',
+ '{' . self::NS_CALENDARSERVER . '}notification-URL',
+ '{' . self::NS_CALENDARSERVER . '}notificationtype'
);
}
@@ -226,6 +223,13 @@ 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);
@@ -235,7 +239,7 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
if (!$node instanceof Sabre_CalDAV_Schedule_IOutbox)
return;
- $this->outboxRequest($node);
+ $this->outboxRequest($node, $uri);
return false;
}
@@ -348,7 +352,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);
@@ -390,8 +394,31 @@ 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'
@@ -424,11 +451,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('urn:DAV','href');
+ $hrefElems = $dom->getElementsByTagNameNS('DAV:','href');
$xpath = new DOMXPath($dom);
$xpath->registerNameSpace('cal',Sabre_CalDAV_Plugin::NS_CALDAV);
- $xpath->registerNameSpace('dav','urn:DAV');
+ $xpath->registerNameSpace('dav','DAV:');
$expand = $xpath->query('/cal:calendar-multiget/dav:prop/cal:calendar-data/cal:expand');
if ($expand->length>0) {
@@ -438,8 +465,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 = Sabre_VObject_DateTimeParser::parseDateTime($start);
- $end = Sabre_VObject_DateTimeParser::parseDateTime($end);
+ $start = VObject\DateTimeParser::parseDateTime($start);
+ $end = 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.');
@@ -458,7 +485,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 = Sabre_VObject_Reader::read($objProps[200]['{' . self::NS_CALDAV . '}calendar-data']);
+ $vObject = VObject\Reader::read($objProps[200]['{' . self::NS_CALDAV . '}calendar-data']);
$vObject->expand($start, $end);
$objProps[200]['{' . self::NS_CALDAV . '}calendar-data'] = $vObject->serialize();
}
@@ -467,9 +494,12 @@ 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->sendBody($this->server->generateMultiStatus($propertyList));
+ $this->server->httpResponse->setHeader('Vary','Brief,Prefer');
+ $this->server->httpResponse->sendBody($this->server->generateMultiStatus($propertyList, $prefer['return-minimal']));
}
@@ -487,54 +517,95 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
$parser = new Sabre_CalDAV_CalendarQueryParser($dom);
$parser->parse();
- $requestedCalendarData = true;
- $requestedProperties = $parser->requestedProperties;
+ $node = $this->server->tree->getNodeForPath($this->server->getRequestUri());
+ $depth = $this->server->getHTTPDepth(0);
- if (!in_array('{urn:ietf:params:xml:ns:caldav}calendar-data', $requestedProperties)) {
+ // The default result is an empty array
+ $result = array();
- // We always retrieve calendar-data, as we need it for filtering.
- $requestedProperties[] = '{urn:ietf:params:xml:ns:caldav}calendar-data';
+ // The calendarobject was requested directly. In this case we handle
+ // this locally.
+ if ($depth == 0 && $node instanceof Sabre_CalDAV_ICalendarObject) {
- // If calendar-data wasn't explicitly requested, we need to remove
- // it after processing.
- $requestedCalendarData = false;
- }
+ $requestedCalendarData = true;
+ $requestedProperties = $parser->requestedProperties;
- // These are the list of nodes that potentially match the requirement
- $candidateNodes = $this->server->getPropertiesForPath(
- $this->server->getRequestUri(),
- $requestedProperties,
- $this->server->getHTTPDepth(0)
- );
+ if (!in_array('{urn:ietf:params:xml:ns:caldav}calendar-data', $requestedProperties)) {
- $verifiedNodes = array();
+ // We always retrieve calendar-data, as we need it for filtering.
+ $requestedProperties[] = '{urn:ietf:params:xml:ns:caldav}calendar-data';
- $validator = new Sabre_CalDAV_CalendarQueryValidator();
+ // If calendar-data wasn't explicitly requested, we need to remove
+ // it after processing.
+ $requestedCalendarData = false;
+ }
- foreach($candidateNodes as $node) {
+ $properties = $this->server->getPropertiesForPath(
+ $this->server->getRequestUri(),
+ $requestedProperties,
+ 0
+ );
- // 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;
+ // This array should have only 1 element, the first calendar
+ // object.
+ $properties = current($properties);
- $vObject = Sabre_VObject_Reader::read($node[200]['{urn:ietf:params:xml:ns:caldav}calendar-data']);
- if ($validator->validate($vObject,$parser->filters)) {
+ // 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();
+ $vObject = VObject\Reader::read($properties[200]['{urn:ietf:params:xml:ns:caldav}calendar-data']);
+ if ($validator->validate($vObject,$parser->filters)) {
+
+ // 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();
+ }
+ }
+
+ $result = array($properties);
- 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']);
- $node[200]['{' . self::NS_CALDAV . '}calendar-data'] = $vObject->serialize();
+ $properties[200]['{' . self::NS_CALDAV . '}calendar-data'] = $vObject->serialize();
}
- $verifiedNodes[] = $node;
+
+ $result[] = $properties;
+
}
}
+ $prefer = $this->server->getHTTPPRefer();
+
$this->server->httpResponse->sendStatus(207);
$this->server->httpResponse->setHeader('Content-Type','application/xml; charset=utf-8');
- $this->server->httpResponse->sendBody($this->server->generateMultiStatus($verifiedNodes));
+ $this->server->httpResponse->setHeader('Vary','Brief,Prefer');
+ $this->server->httpResponse->sendBody($this->server->generateMultiStatus($result, $prefer['return-minimal']));
}
@@ -561,10 +632,10 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
}
if ($start) {
- $start = Sabre_VObject_DateTimeParser::parseDateTime($start);
+ $start = VObject\DateTimeParser::parseDateTime($start);
}
if ($end) {
- $end = Sabre_VObject_DateTimeParser::parseDateTime($end);
+ $end = VObject\DateTimeParser::parseDateTime($end);
}
if (!$start && !$end) {
@@ -583,15 +654,33 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
throw new Sabre_DAV_Exception_NotImplemented('The free-busy-query REPORT is only implemented on calendars');
}
- $objects = array_map(function($child) {
- $obj = $child->get();
- if (is_resource($obj)) {
- $obj = stream_get_contents($obj);
- }
+ // 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();
return $obj;
- }, $calendar->getChildren());
+ }, $urls);
- $generator = new Sabre_VObject_FreeBusyGenerator();
+ $generator = new VObject\FreeBusyGenerator();
$generator->setObjects($objects);
$generator->setTimeRange($start, $end);
$result = $generator->getResult();
@@ -620,7 +709,7 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
if (!$node instanceof Sabre_CalDAV_ICalendarObject)
return;
- $this->validateICalendar($data);
+ $this->validateICalendar($data, $path);
}
@@ -640,7 +729,52 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
if (!$parentNode instanceof Sabre_CalDAV_Calendar)
return;
- $this->validateICalendar($data);
+ $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;
}
@@ -650,9 +784,10 @@ 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) {
+ protected function validateICalendar(&$data, $path) {
// If it's a stream, we convert it to a string first.
if (is_resource($data)) {
@@ -664,9 +799,9 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
try {
- $vobj = Sabre_VObject_Reader::read($data);
+ $vobj = VObject\Reader::read($data);
- } catch (Sabre_VObject_ParseException $e) {
+ } catch (VObject\ParseException $e) {
throw new Sabre_DAV_Exception_UnsupportedMediaType('This resource only supports valid iCalendar 2.0 data. Parse error: ' . $e->getMessage());
@@ -676,6 +811,11 @@ 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) {
@@ -687,6 +827,9 @@ 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');
}
@@ -711,12 +854,81 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
}
/**
- * This method handles POST requests to the schedule-outbox
+ * 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.
*
* @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
*/
- public function outboxRequest(Sabre_CalDAV_Schedule_IOutbox $outboxNode) {
+ protected function handleEventNotification(Sabre_CalDAV_Schedule_IOutbox $outboxNode, VObject\Component $vObject) {
$originator = $this->server->httpRequest->getHeader('Originator');
$recipients = $this->server->httpRequest->getHeader('Recipient');
@@ -760,38 +972,10 @@ 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');
}
- 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');
- }
+ $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));
}
@@ -813,15 +997,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, Sabre_VObject_Component $vObject) {
+ protected function iMIPMessage($originator, array $recipients, VObject\Component $vObject, $principal) {
if (!$this->imipHandler) {
$resultStatus = '5.2;This server does not support this operation';
} else {
- $this->imipHandler->sendMessage($originator, $recipients, $vObject);
+ $this->imipHandler->sendMessage($originator, $recipients, $vObject, $principal);
$resultStatus = '2.0;Success';
}
@@ -832,7 +1016,6 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
return $result;
-
}
/**
@@ -878,6 +1061,204 @@ 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
* can use to create new calendars.
diff --git a/3rdparty/Sabre/CalDAV/Property/AllowedSharingModes.php b/3rdparty/Sabre/CalDAV/Property/AllowedSharingModes.php
new file mode 100755
index 00000000000..efe751732c5
--- /dev/null
+++ b/3rdparty/Sabre/CalDAV/Property/AllowedSharingModes.php
@@ -0,0 +1,72 @@
+<?php
+
+/**
+ * AllowedSharingModes
+ *
+ * This property encodes the 'allowed-sharing-modes' property, as defined by
+ * the 'caldav-sharing-02' spec, in the http://calendarserver.org/ns/
+ * namespace.
+ *
+ * This property is a representation of the supported-calendar_component-set
+ * property in the CalDAV namespace. It simply requires an array of components,
+ * such as VEVENT, VTODO
+ *
+ * @package Sabre
+ * @subpackage CalDAV
+ * @see https://trac.calendarserver.org/browser/CalendarServer/trunk/doc/Extensions/caldav-sharing-02.txt
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class Sabre_CalDAV_Property_AllowedSharingModes extends Sabre_DAV_Property {
+
+ /**
+ * Whether or not a calendar can be shared with another user
+ *
+ * @var bool
+ */
+ protected $canBeShared;
+
+ /**
+ * Whether or not the calendar can be placed on a public url.
+ *
+ * @var bool
+ */
+ protected $canBePublished;
+
+ /**
+ * Constructor
+ *
+ * @param bool $canBeShared
+ * @param bool $canBePublished
+ * @return void
+ */
+ public function __construct($canBeShared, $canBePublished) {
+
+ $this->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
new file mode 100755
index 00000000000..4ed94877df2
--- /dev/null
+++ b/3rdparty/Sabre/CalDAV/Property/Invite.php
@@ -0,0 +1,173 @@
+<?php
+
+use Sabre_CalDAV_SharingPlugin as SharingPlugin;
+
+/**
+ * Invite property
+ *
+ * This property encodes the 'invite' property, as defined by
+ * the 'caldav-sharing-02' spec, in the http://calendarserver.org/ns/
+ * namespace.
+ *
+ * @package Sabre
+ * @subpackage CalDAV
+ * @see https://trac.calendarserver.org/browser/CalendarServer/trunk/doc/Extensions/caldav-sharing-02.txt
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class Sabre_CalDAV_Property_Invite extends Sabre_DAV_Property {
+
+ /**
+ * The list of users a calendar has been shared to.
+ *
+ * @var array
+ */
+ protected $users;
+
+ /**
+ * Creates the property.
+ *
+ * Users is an array. Each element of the array has the following
+ * properties:
+ *
+ * * href - Often a mailto: address
+ * * commonName - Optional, for example a first and lastname for a user.
+ * * status - One of the SharingPlugin::STATUS_* constants.
+ * * readOnly - true or false
+ * * summary - Optional, description of the share
+ *
+ * @param array $users
+ */
+ public function __construct(array $users) {
+
+ $this->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
new file mode 100755
index 00000000000..76c1dbaec21
--- /dev/null
+++ b/3rdparty/Sabre/CalDAV/Property/ScheduleCalendarTransp.php
@@ -0,0 +1,99 @@
+<?php
+
+/**
+ * schedule-calendar-transp property.
+ *
+ * This property is a representation of the schedule-calendar-transp property.
+ * This property is defined in RFC6638 (caldav scheduling).
+ *
+ * Its values are either 'transparent' or 'opaque'. If it's transparent, it
+ * means that this calendar will not be taken into consideration when a
+ * different user queries for free-busy information. If it's 'opaque', it will.
+ *
+ * @package Sabre
+ * @subpackage CalDAV
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class Sabre_CalDAV_Property_ScheduleCalendarTransp extends Sabre_DAV_Property {
+
+ const TRANSPARENT = 'transparent';
+ const OPAQUE = 'opaque';
+
+ protected $value;
+
+ /**
+ * Creates the property
+ *
+ * @param string $value
+ */
+ public function __construct($value) {
+
+ if ($value !== self::TRANSPARENT && $value !== self::OPAQUE) {
+ throw new \InvalidArgumentException('The value must either be specified as "transparent" or "opaque"');
+ }
+ $this->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 37e75fcc4a7..92c3c097c15 100755
--- a/3rdparty/Sabre/CalDAV/Schedule/IMip.php
+++ b/3rdparty/Sabre/CalDAV/Schedule/IMip.php
@@ -1,5 +1,7 @@
<?php
+use Sabre\VObject;
+
/**
* iMIP handler.
*
@@ -42,12 +44,13 @@ class Sabre_CalDAV_Schedule_IMip {
/**
* Sends one or more iTip messages through email.
*
- * @param string $originator
- * @param array $recipients
- * @param Sabre_VObject_Component $vObject
+ * @param string $originator Originator Email
+ * @param array $recipients Array of email addresses
+ * @param Sabre\VObject\Component $vObject
+ * @param string $principal Principal Url of the originator
* @return void
*/
- public function sendMessage($originator, array $recipients, Sabre_VObject_Component $vObject) {
+ public function sendMessage($originator, array $recipients, VObject\Component $vObject, $principal) {
foreach($recipients as $recipient) {
@@ -83,6 +86,9 @@ class Sabre_CalDAV_Schedule_IMip {
}
+ // @codeCoverageIgnoreStart
+ // This is deemed untestable in a reasonable manner
+
/**
* This function is reponsible for sending the actual email.
*
@@ -94,11 +100,11 @@ class Sabre_CalDAV_Schedule_IMip {
*/
protected function mail($to, $subject, $body, array $headers) {
+
mail($to, $subject, $body, implode("\r\n", $headers));
}
+ // @codeCoverageIgnoreEnd
}
-
-?>
diff --git a/3rdparty/Sabre/CalDAV/Schedule/Outbox.php b/3rdparty/Sabre/CalDAV/Schedule/Outbox.php
index 014c37230d1..462aa527e23 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_Directory implements Sabre_CalDAV_Schedule_IOutbox {
+class Sabre_CalDAV_Schedule_Outbox extends Sabre_DAV_Collection implements Sabre_CalDAV_Schedule_IOutbox {
/**
* The principal Uri
@@ -104,6 +104,11 @@ class Sabre_CalDAV_Schedule_Outbox extends Sabre_DAV_Directory implements Sabre_
'protected' => true,
),
array(
+ 'privilege' => '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}schedule-post-vevent',
+ 'principal' => $this->getOwner(),
+ 'protected' => true,
+ ),
+ array(
'privilege' => '{DAV:}read',
'principal' => $this->getOwner(),
'protected' => true,
@@ -144,6 +149,9 @@ class Sabre_CalDAV_Schedule_Outbox extends Sabre_DAV_Directory 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
deleted file mode 100755
index 325e3d80a7f..00000000000
--- a/3rdparty/Sabre/CalDAV/Server.php
+++ /dev/null
@@ -1,68 +0,0 @@
-<?php
-
-/**
- * CalDAV server
- *
- * Deprecated! Warning: This class is now officially deprecated
- *
- * This script is a convenience script. It quickly sets up a WebDAV server
- * with caldav and ACL support, and it creates the root 'principals' and
- * 'calendars' collections.
- *
- * Note that if you plan to do anything moderately complex, you are advised to
- * not subclass this server, but use Sabre_DAV_Server directly instead. This
- * class is nothing more than an 'easy setup'.
- *
- * @package Sabre
- * @subpackage CalDAV
- * @deprecated Don't use this class anymore, it will be removed in version 1.7.
- * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/)
- * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
- */
-class Sabre_CalDAV_Server extends Sabre_DAV_Server {
-
- /**
- * The authentication realm
- *
- * Note that if this changes, the hashes in the auth backend must also
- * be recalculated.
- *
- * @var string
- */
- public $authRealm = 'SabreDAV';
-
- /**
- * Sets up the object. A PDO object must be passed to setup all the backends.
- *
- * @param PDO $pdo
- */
- public function __construct(PDO $pdo) {
-
- /* Backends */
- $authBackend = new Sabre_DAV_Auth_Backend_PDO($pdo);
- $calendarBackend = new Sabre_CalDAV_Backend_PDO($pdo);
- $principalBackend = new Sabre_DAVACL_PrincipalBackend_PDO($pdo);
-
- /* Directory structure */
- $tree = array(
- new Sabre_CalDAV_Principal_Collection($principalBackend),
- new Sabre_CalDAV_CalendarRootNode($principalBackend, $calendarBackend),
- );
-
- /* Initializing server */
- parent::__construct($tree);
-
- /* Server Plugins */
- $authPlugin = new Sabre_DAV_Auth_Plugin($authBackend,$this->authRealm);
- $this->addPlugin($authPlugin);
-
- $aclPlugin = new Sabre_DAVACL_Plugin();
- $this->addPlugin($aclPlugin);
-
- $caldavPlugin = new Sabre_CalDAV_Plugin();
- $this->addPlugin($caldavPlugin);
-
- }
-
-}
diff --git a/3rdparty/Sabre/CalDAV/ShareableCalendar.php b/3rdparty/Sabre/CalDAV/ShareableCalendar.php
new file mode 100755
index 00000000000..0e44885c621
--- /dev/null
+++ b/3rdparty/Sabre/CalDAV/ShareableCalendar.php
@@ -0,0 +1,72 @@
+<?php
+
+/**
+ * This object represents a CalDAV calendar that can be shared with other
+ * users.
+ *
+ * @package Sabre
+ * @subpackage CalDAV
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class Sabre_CalDAV_ShareableCalendar extends Sabre_CalDAV_Calendar implements Sabre_CalDAV_IShareableCalendar {
+
+ /**
+ * Updates the list of shares.
+ *
+ * The first array is a list of people that are to be added to the
+ * calendar.
+ *
+ * Every element in the add array has the following properties:
+ * * href - A url. Usually a mailto: address
+ * * commonName - Usually a first and last name, or false
+ * * summary - A description of the share, can also be false
+ * * readOnly - A boolean value
+ *
+ * Every element in the remove array is just the address string.
+ *
+ * @param array $add
+ * @param array $remove
+ * @return void
+ */
+ public function updateShares(array $add, array $remove) {
+
+ $this->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
new file mode 100755
index 00000000000..9000697d3ec
--- /dev/null
+++ b/3rdparty/Sabre/CalDAV/SharedCalendar.php
@@ -0,0 +1,98 @@
+<?php
+
+/**
+ * This object represents a CalDAV calendar that is shared by a different user.
+ *
+ * @package Sabre
+ * @subpackage CalDAV
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class Sabre_CalDAV_SharedCalendar extends Sabre_CalDAV_Calendar implements Sabre_CalDAV_ISharedCalendar {
+
+ /**
+ * Constructor
+ *
+ * @param Sabre_DAVACL_IPrincipalBackend $principalBackend
+ * @param Sabre_CalDAV_Backend_BackendInterface $caldavBackend
+ * @param array $calendarInfo
+ */
+ public function __construct(Sabre_DAVACL_IPrincipalBackend $principalBackend, Sabre_CalDAV_Backend_BackendInterface $caldavBackend, $calendarInfo) {
+
+ $required = array(
+ '{http://calendarserver.org/ns/}shared-url',
+ '{http://sabredav.org/ns}owner-principal',
+ '{http://sabredav.org/ns}read-only',
+ );
+ foreach($required as $r) {
+ if (!isset($calendarInfo[$r])) {
+ throw new InvalidArgumentException('The ' . $r . ' property must be specified for SharedCalendar(s)');
+ }
+ }
+
+ parent::__construct($principalBackend, $caldavBackend, $calendarInfo);
+
+ }
+
+ /**
+ * This method should return the url of the owners' copy of the shared
+ * calendar.
+ *
+ * @return string
+ */
+ public function getSharedUrl() {
+
+ return $this->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
new file mode 100755
index 00000000000..31df8057b24
--- /dev/null
+++ b/3rdparty/Sabre/CalDAV/SharingPlugin.php
@@ -0,0 +1,475 @@
+<?php
+
+/**
+ * This plugin implements support for caldav sharing.
+ *
+ * This spec is defined at:
+ * http://svn.calendarserver.org/repository/calendarserver/CalendarServer/trunk/doc/Extensions/caldav-sharing.txt
+ *
+ * See:
+ * Sabre_CalDAV_Backend_SharingSupport for all the documentation.
+ *
+ * Note: This feature is experimental, and may change in between different
+ * SabreDAV versions.
+ *
+ * @package Sabre
+ * @subpackage CalDAV
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class Sabre_CalDAV_SharingPlugin extends Sabre_DAV_ServerPlugin {
+
+ /**
+ * These are the various status constants used by sharing-messages.
+ */
+ const STATUS_ACCEPTED = 1;
+ const STATUS_DECLINED = 2;
+ const STATUS_DELETED = 3;
+ const STATUS_NORESPONSE = 4;
+ const STATUS_INVALID = 5;
+
+ /**
+ * Reference to SabreDAV server object.
+ *
+ * @var Sabre_DAV_Server
+ */
+ protected $server;
+
+ /**
+ * This method should return a list of server-features.
+ *
+ * This is for example 'versioning' and is added to the DAV: header
+ * in an OPTIONS response.
+ *
+ * @return array
+ */
+ public function getFeatures() {
+
+ return array('calendarserver-sharing');
+
+ }
+
+ /**
+ * Returns a plugin name.
+ *
+ * Using this name other plugins will be able to access other plugins
+ * using Sabre_DAV_Server::getPlugin
+ *
+ * @return string
+ */
+ public function getPluginName() {
+
+ return 'caldav-sharing';
+
+ }
+
+ /**
+ * This initializes the plugin.
+ *
+ * This function is called by Sabre_DAV_Server, after
+ * addPlugin is called.
+ *
+ * This method should set up the required event subscriptions.
+ *
+ * @param Sabre_DAV_Server $server
+ * @return void
+ */
+ public function initialize(Sabre_DAV_Server $server) {
+
+ $this->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 b8d3f0573fa..3194e6677ab 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_Abstract
+ * @var Sabre_CalDAV_Backend_BackendInterface
*/
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_Abstract $caldavBackend
+ * @param Sabre_CalDAV_Backend_BackendInterface $caldavBackend
* @param mixed $userUri
*/
- public function __construct(Sabre_DAVACL_IPrincipalBackend $principalBackend, Sabre_CalDAV_Backend_Abstract $caldavBackend, $userUri) {
+ public function __construct(Sabre_DAVACL_IPrincipalBackend $principalBackend, Sabre_CalDAV_Backend_BackendInterface $caldavBackend, $userUri) {
$this->principalBackend = $principalBackend;
$this->caldavBackend = $caldavBackend;
@@ -168,9 +168,22 @@ class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre
$calendars = $this->caldavBackend->getCalendarsForUser($this->principalInfo['uri']);
$objs = array();
foreach($calendars as $calendar) {
- $objs[] = new Sabre_CalDAV_Calendar($this->principalBackend, $this->caldavBackend, $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_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;
}
@@ -185,8 +198,22 @@ class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre
*/
public function createExtendedCollection($name, array $resourceType, array $properties) {
- 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');
+ $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');
}
$this->caldavBackend->createCalendar($this->principalInfo['uri'], $name, $properties);
@@ -295,4 +322,27 @@ 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 ace9901c089..0ad14fa0869 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.6.4';
+ const VERSION = '1.7.0';
/**
* Stability : alpha, beta, stable
diff --git a/3rdparty/Sabre/CalDAV/includes.php b/3rdparty/Sabre/CalDAV/includes.php
index 1ecb870a0e1..8b38e398f65 100755
--- a/3rdparty/Sabre/CalDAV/includes.php
+++ b/3rdparty/Sabre/CalDAV/includes.php
@@ -16,28 +16,47 @@
*/
// Begin includes
-include __DIR__ . '/Backend/Abstract.php';
-include __DIR__ . '/Backend/PDO.php';
+include __DIR__ . '/Backend/BackendInterface.php';
+include __DIR__ . '/Backend/NotificationSupport.php';
+include __DIR__ . '/Backend/SharingSupport.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__ . '/Server.php';
+include __DIR__ . '/SharingPlugin.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 12297175a85..8d545114d97 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_DAV_Card
+ * @return Sabre_CardDAV_ICard
*/
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 void|null
+ * @return string|null
*/
public function createFile($name,$vcardData = null) {
diff --git a/3rdparty/Sabre/CardDAV/Card.php b/3rdparty/Sabre/CardDAV/Card.php
index d7c66333837..0e35d321eb8 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 void
+ * @return string|null
*/
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';
+ return 'text/x-vcard; charset=utf-8';
}
@@ -128,7 +128,13 @@ class Sabre_CardDAV_Card extends Sabre_DAV_File implements Sabre_CardDAV_ICard,
if (isset($this->cardData['etag'])) {
return $this->cardData['etag'];
} else {
- return '"' . md5($this->get()) . '"';
+ $data = $this->get();
+ if (is_string($data)) {
+ return '"' . md5($data) . '"';
+ } else {
+ // We refuse to calculate the md5 if it's a stream.
+ return null;
+ }
}
}
@@ -136,7 +142,7 @@ class Sabre_CardDAV_Card extends Sabre_DAV_File implements Sabre_CardDAV_ICard,
/**
* Returns the last modification date as a unix timestamp
*
- * @return time
+ * @return int
*/
public function getLastModified() {
diff --git a/3rdparty/Sabre/CardDAV/Plugin.php b/3rdparty/Sabre/CardDAV/Plugin.php
index 96def6dd96b..12bccaec4fb 100755
--- a/3rdparty/Sabre/CardDAV/Plugin.php
+++ b/3rdparty/Sabre/CardDAV/Plugin.php
@@ -1,5 +1,7 @@
<?php
+use Sabre\VObject;
+
/**
* CardDAV plugin
*
@@ -48,6 +50,7 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin {
/* Events */
$server->subscribeEvent('beforeGetProperties', array($this, 'beforeGetProperties'));
+ $server->subscribeEvent('afterGetProperties', array($this, 'afterGetProperties'));
$server->subscribeEvent('updateProperties', array($this, 'updateProperties'));
$server->subscribeEvent('report', array($this,'report'));
$server->subscribeEvent('onHTMLActionsPanel', array($this,'htmlActionsPanel'));
@@ -153,10 +156,6 @@ 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;
}
@@ -190,7 +189,7 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin {
* @param array $mutations
* @param array $result
* @param Sabre_DAV_INode $node
- * @return void
+ * @return bool
*/
public function updateProperties(&$mutations, &$result, $node) {
@@ -272,7 +271,7 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin {
$properties = array_keys(Sabre_DAV_XMLUtil::parseProperties($dom->firstChild));
- $hrefElems = $dom->getElementsByTagNameNS('urn:DAV','href');
+ $hrefElems = $dom->getElementsByTagNameNS('DAV:','href');
$propertyList = array();
foreach($hrefElems as $elem) {
@@ -282,9 +281,12 @@ 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->sendBody($this->server->generateMultiStatus($propertyList));
+ $this->server->httpResponse->setHeader('Vary','Brief,Prefer');
+ $this->server->httpResponse->sendBody($this->server->generateMultiStatus($propertyList, $prefer['return-minimal']));
}
@@ -348,9 +350,9 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin {
try {
- $vobj = Sabre_VObject_Reader::read($data);
+ $vobj = VObject\Reader::read($data);
- } catch (Sabre_VObject_ParseException $e) {
+ } catch (VObject\ParseException $e) {
throw new Sabre_DAV_Exception_UnsupportedMediaType('This resource only supports valid vcard data. Parse error: ' . $e->getMessage());
@@ -360,6 +362,10 @@ 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.');
+ }
+
}
@@ -424,9 +430,12 @@ 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->sendBody($this->server->generateMultiStatus($result));
+ $this->server->httpResponse->setHeader('Vary','Brief,Prefer');
+ $this->server->httpResponse->sendBody($this->server->generateMultiStatus($result, $prefer['return-minimal']));
}
@@ -440,7 +449,7 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin {
*/
public function validateFilters($vcardData, array $filters, $test) {
- $vcard = Sabre_VObject_Reader::read($vcardData);
+ $vcard = VObject\Reader::read($vcardData);
if (!$filters) return true;
@@ -616,6 +625,30 @@ 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
* can use to create new calendars.
diff --git a/3rdparty/Sabre/CardDAV/VCFExportPlugin.php b/3rdparty/Sabre/CardDAV/VCFExportPlugin.php
new file mode 100755
index 00000000000..8850fef8afb
--- /dev/null
+++ b/3rdparty/Sabre/CardDAV/VCFExportPlugin.php
@@ -0,0 +1,107 @@
+<?php
+
+use Sabre\VObject;
+
+/**
+ * VCF Exporter
+ *
+ * This plugin adds the ability to export entire address books as .vcf files.
+ * This is useful for clients that don't support CardDAV yet. They often do
+ * support vcf files.
+ *
+ * @package Sabre
+ * @subpackage CardDAV
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @author Thomas Tanghus (http://tanghus.net/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class Sabre_CardDAV_VCFExportPlugin extends Sabre_DAV_ServerPlugin {
+
+ /**
+ * Reference to Server class
+ *
+ * @var Sabre_DAV_Server
+ */
+ private $server;
+
+ /**
+ * Initializes the plugin and registers event handlers
+ *
+ * @param Sabre_DAV_Server $server
+ * @return void
+ */
+ public function initialize(Sabre_DAV_Server $server) {
+
+ $this->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 d0623f0d3e8..6b70a2df9b5 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.6.3';
+ const VERSION = '1.7.0';
/**
* Stability : alpha, beta, stable
diff --git a/3rdparty/Sabre/CardDAV/includes.php b/3rdparty/Sabre/CardDAV/includes.php
index c3b8c04b077..08b4f76bd01 100755
--- a/3rdparty/Sabre/CardDAV/includes.php
+++ b/3rdparty/Sabre/CardDAV/includes.php
@@ -26,6 +26,7 @@ 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 09bbdd2ae02..b6440ab6340 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 = $parent->getChild($name);
+ $node = $this->server->tree->getNodeForPath(($path?$path.'/':'') . $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 9a428765e90..9d9f4c96b02 100755
--- a/3rdparty/Sabre/DAV/Client.php
+++ b/3rdparty/Sabre/DAV/Client.php
@@ -16,12 +16,25 @@
*/
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
@@ -88,6 +101,18 @@ 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
*
* The list of requested properties must be specified as an array, in clark
@@ -143,13 +168,13 @@ class Sabre_DAV_Client {
if ($depth===0) {
reset($result);
$result = current($result);
- return $result[200];
+ return isset($result[200])?$result[200]:array();
}
$newResult = array();
foreach($result as $href => $statusList) {
- $newResult[$href] = $statusList[200];
+ $newResult[$href] = isset($statusList[200])?$statusList[200]:array();
}
@@ -279,6 +304,10 @@ class Sabre_DAV_Client {
CURLOPT_MAXREDIRS => 5,
);
+ if($this->trustedCertificates) {
+ $curlSettings[CURLOPT_CAINFO] = $this->trustedCertificates;
+ }
+
switch ($method) {
case 'HEAD' :
@@ -363,10 +392,30 @@ 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 ' . $url . ' not found.');
- break;
-
+ 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');
default:
throw new Sabre_DAV_Exception('HTTP error response. (errorcode ' . $response['statusCode'] . ')');
}
@@ -386,6 +435,7 @@ class Sabre_DAV_Client {
* @param array $settings
* @return array
*/
+ // @codeCoverageIgnoreStart
protected function curlRequest($url, $settings) {
$curl = curl_init($url);
@@ -399,6 +449,7 @@ class Sabre_DAV_Client {
);
}
+ // @codeCoverageIgnoreEnd
/**
* Returns the full url based on the given url (which may be relative). All
@@ -453,19 +504,17 @@ 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', 'urn:DAV');
+ $responseXML->registerXPathNamespace('d', 'DAV:');
$propResult = array();
foreach($responseXML->xpath('d:response') as $response) {
- $response->registerXPathNamespace('d', 'urn:DAV');
+ $response->registerXPathNamespace('d', 'DAV:');
$href = $response->xpath('d:href');
$href = (string)$href[0];
@@ -473,7 +522,7 @@ class Sabre_DAV_Client {
foreach($response->xpath('d:propstat') as $propStat) {
- $propStat->registerXPathNamespace('d', 'urn:DAV');
+ $propStat->registerXPathNamespace('d', '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 776c22531b2..c7648a8a52d 100755
--- a/3rdparty/Sabre/DAV/Collection.php
+++ b/3rdparty/Sabre/DAV/Collection.php
@@ -17,9 +17,13 @@ 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
deleted file mode 100755
index 6db8febc02e..00000000000
--- a/3rdparty/Sabre/DAV/Directory.php
+++ /dev/null
@@ -1,17 +0,0 @@
-<?php
-
-/**
- * Directory class
- *
- * This class is now deprecated in favor of the Sabre_DAV_Collection class.
- *
- * @package Sabre
- * @subpackage DAV
- * @deprecated Use Sabre_DAV_Collection instead
- * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/)
- * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
- */
-abstract class Sabre_DAV_Directory extends Sabre_DAV_Collection {
-}
-
diff --git a/3rdparty/Sabre/DAV/Exception/ReportNotImplemented.php b/3rdparty/Sabre/DAV/Exception/ReportNotSupported.php
index e86800f3038..a2906865f8e 100755
--- a/3rdparty/Sabre/DAV/Exception/ReportNotImplemented.php
+++ b/3rdparty/Sabre/DAV/Exception/ReportNotSupported.php
@@ -1,7 +1,7 @@
<?php
/**
- * ReportNotImplemented
+ * ReportNotSupported
*
* This exception is thrown when the client requested an unknown report through the REPORT method
*
@@ -11,7 +11,7 @@
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
-class Sabre_DAV_Exception_ReportNotImplemented extends Sabre_DAV_Exception_NotImplemented {
+class Sabre_DAV_Exception_ReportNotSupported extends Sabre_DAV_Exception_Forbidden {
/**
* This method allows the exception to include additional information into the WebDAV error response
diff --git a/3rdparty/Sabre/DAV/FS/Directory.php b/3rdparty/Sabre/DAV/FS/Directory.php
index 3af2d755583..72fec744d0f 100755
--- a/3rdparty/Sabre/DAV/FS/Directory.php
+++ b/3rdparty/Sabre/DAV/FS/Directory.php
@@ -17,7 +17,7 @@ class Sabre_DAV_FS_Directory extends Sabre_DAV_FS_Node implements Sabre_DAV_ICol
* Data will either be supplied as a stream resource, or in certain cases
* as a string. Keep in mind that you may have to support either.
*
- * After succesful creation of the file, you may choose to return the ETag
+ * After successful 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
@@ -58,6 +58,9 @@ class Sabre_DAV_FS_Directory extends Sabre_DAV_FS_Node implements Sabre_DAV_ICol
/**
* 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
* @throws Sabre_DAV_Exception_NotFound
* @return Sabre_DAV_INode
diff --git a/3rdparty/Sabre/DAV/FSExt/Directory.php b/3rdparty/Sabre/DAV/FSExt/Directory.php
index 540057183b3..70dfdc2c3b5 100755
--- a/3rdparty/Sabre/DAV/FSExt/Directory.php
+++ b/3rdparty/Sabre/DAV/FSExt/Directory.php
@@ -17,7 +17,7 @@ class Sabre_DAV_FSExt_Directory extends Sabre_DAV_FSExt_Node implements Sabre_DA
* Data will either be supplied as a stream resource, or in certain cases
* as a string. Keep in mind that you may have to support either.
*
- * After succesful creation of the file, you may choose to return the ETag
+ * After successful 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
@@ -64,6 +64,9 @@ class Sabre_DAV_FSExt_Directory extends Sabre_DAV_FSExt_Node implements Sabre_DA
/**
* 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
* @throws Sabre_DAV_Exception_NotFound
* @return Sabre_DAV_INode
diff --git a/3rdparty/Sabre/DAV/FSExt/File.php b/3rdparty/Sabre/DAV/FSExt/File.php
index b93ce5aee21..590fb808e61 100755
--- a/3rdparty/Sabre/DAV/FSExt/File.php
+++ b/3rdparty/Sabre/DAV/FSExt/File.php
@@ -9,15 +9,15 @@
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
-class Sabre_DAV_FSExt_File extends Sabre_DAV_FSExt_Node implements Sabre_DAV_IFile {
+class Sabre_DAV_FSExt_File extends Sabre_DAV_FSExt_Node implements Sabre_DAV_PartialUpdate_IFile {
/**
* Updates the data
*
* data is a readable stream resource.
*
- * @param resource $data
- * @return void
+ * @param resource|string $data
+ * @return string
*/
public function put($data) {
@@ -27,9 +27,33 @@ class Sabre_DAV_FSExt_File extends Sabre_DAV_FSExt_Node implements Sabre_DAV_IFi
}
/**
+ * Updates the data at a given offset
+ *
+ * The data argument is a readable stream resource.
+ * The offset argument is a 0-based offset where the data should be
+ * written.
+ *
+ * param resource|string $data
+ * @return void
+ */
+ public function putRange($data, $offset) {
+
+ $f = fopen($this->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 string
+ * @return resource
*/
public function get() {
diff --git a/3rdparty/Sabre/DAV/ICollection.php b/3rdparty/Sabre/DAV/ICollection.php
index 4626038a66e..94431a0c496 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 succesful creation of the file, you may choose to return the ETag
+ * After successful 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,6 +50,9 @@ 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 478f822ae71..1eca8986a5c 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 void
+ * @return string|null
*/
function getContentType();
diff --git a/3rdparty/Sabre/DAV/Locks/Plugin.php b/3rdparty/Sabre/DAV/Locks/Plugin.php
index 035b3a63863..957ac506a9c 100755
--- a/3rdparty/Sabre/DAV/Locks/Plugin.php
+++ b/3rdparty/Sabre/DAV/Locks/Plugin.php
@@ -152,6 +152,7 @@ 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 070b7176afd..3b95dfec2fa 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 {
}
/**
- * Deleted the current node
+ * Deletes 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 bce51463900..3b7f222d64b 100755
--- a/3rdparty/Sabre/DAV/ObjectTree.php
+++ b/3rdparty/Sabre/DAV/ObjectTree.php
@@ -51,24 +51,30 @@ class Sabre_DAV_ObjectTree extends Sabre_DAV_Tree {
$path = trim($path,'/');
if (isset($this->cache[$path])) return $this->cache[$path];
- //if (!$path || $path=='.') return $this->rootNode;
- $currentNode = $this->rootNode;
+ // Is it the root node?
+ if (!strlen($path)) {
+ return $this->rootNode;
+ }
- // We're splitting up the path variable into folder/subfolder components and traverse to the correct node..
- foreach(explode('/',$path) as $pathPart) {
+ // Attempting to fetch its parent
+ list($parentName, $baseName) = Sabre_DAV_URLUtil::splitPath($path);
- // If this part of the path is just a dot, it actually means we can skip it
- if ($pathPart=='.' || $pathPart=='') continue;
+ // 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 (!($currentNode instanceof Sabre_DAV_ICollection))
+ if (!($parent instanceof Sabre_DAV_ICollection))
throw new Sabre_DAV_Exception_NotFound('Could not find node at path: ' . $path);
- $currentNode = $currentNode->getChild($pathPart);
+ $node = $parent->getChild($baseName);
}
- $this->cache[$path] = $currentNode;
- return $currentNode;
+ $this->cache[$path] = $node;
+ return $node;
}
diff --git a/3rdparty/Sabre/DAV/PartialUpdate/IFile.php b/3rdparty/Sabre/DAV/PartialUpdate/IFile.php
new file mode 100755
index 00000000000..cf5ad55c6de
--- /dev/null
+++ b/3rdparty/Sabre/DAV/PartialUpdate/IFile.php
@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * This interface provides a way to modify only part of a target resource
+ * It may be used to update a file chunk, upload big a file into smaller
+ * chunks or resume an upload
+ *
+ * @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
+ */
+interface Sabre_DAV_PartialUpdate_IFile extends Sabre_DAV_IFile {
+
+ /**
+ * Updates the data at a given offset
+ *
+ * The data argument is a readable stream resource.
+ * The offset argument is an integer describing the offset. Contrary to
+ * what's sent in the request, the offset here is a 0-based index.
+ *
+ * After a successful put operation, you may choose to return an ETag. The
+ * etag must always be surrounded by double-quotes. These quotes must
+ * appear in the actual string you're returning.
+ *
+ * Clients may use the ETag from a PUT request to later on make sure that
+ * when they update the file, the contents haven't changed in the mean
+ * time.
+ *
+ * @param resource $data
+ * @param integer $offset
+ * @return string|null
+ */
+ function putRange($data, $offset);
+
+}
+
diff --git a/3rdparty/Sabre/DAV/PartialUpdate/Plugin.php b/3rdparty/Sabre/DAV/PartialUpdate/Plugin.php
new file mode 100755
index 00000000000..170acbc9785
--- /dev/null
+++ b/3rdparty/Sabre/DAV/PartialUpdate/Plugin.php
@@ -0,0 +1,209 @@
+<?php
+/**
+ * Partial update plugin (Patch method)
+ *
+ * This plugin provides a way to modify only part of a target resource
+ * It may bu used to update a file chunk, upload big a file into smaller
+ * chunks or resume an upload.
+ *
+ * $patchPlugin = new Sabre_DAV_Patch_Plugin();
+ * $server->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 1cfada3236c..6487bf44bc4 100755
--- a/3rdparty/Sabre/DAV/Property.php
+++ b/3rdparty/Sabre/DAV/Property.php
@@ -11,10 +11,16 @@
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
-abstract class Sabre_DAV_Property {
-
- abstract function serialize(Sabre_DAV_Server $server, DOMElement $prop);
+abstract class Sabre_DAV_Property implements Sabre_DAV_PropertyInterface {
+ /**
+ * 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 dac564f24d7..cd1d867f71b 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 (Sabre_DAV_XMLUtil::toClarkNotation($dom->firstChild)==='{DAV:}href') {
+ if ($dom->firstChild && 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 7a52272e885..282c452ca0b 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_Href
+ * @return Sabre_DAV_Property_HrefList
*/
static function unserialize(DOMElement $dom) {
diff --git a/3rdparty/Sabre/DAV/Property/Response.php b/3rdparty/Sabre/DAV/Property/Response.php
index 88afbcfb26d..9f21163d12e 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_Property) {
+ } elseif ($propertyValue instanceof Sabre_DAV_PropertyInterface) {
$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
new file mode 100755
index 00000000000..515072cbd35
--- /dev/null
+++ b/3rdparty/Sabre/DAV/PropertyInterface.php
@@ -0,0 +1,21 @@
+<?php
+
+/**
+ * PropertyInterface
+ *
+ * Implement this interface to create new complex properties
+ *
+ * @package Sabre
+ * @subpackage DAV
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+interface Sabre_DAV_PropertyInterface {
+
+ public function serialize(Sabre_DAV_Server $server, DOMElement $prop);
+
+ static function unserialize(DOMElement $prop);
+
+}
+
diff --git a/3rdparty/Sabre/DAV/Server.php b/3rdparty/Sabre/DAV/Server.php
index 0dfac8b0c71..cf6f87e68ab 100755
--- a/3rdparty/Sabre/DAV/Server.php
+++ b/3rdparty/Sabre/DAV/Server.php
@@ -12,7 +12,7 @@
class Sabre_DAV_Server {
/**
- * Inifinity is used for some request supporting the HTTP Depth header and indicates that the operation should traverse the entire tree
+ * Infinity is used for some request supporting the HTTP Depth header and indicates that the operation should traverse the entire tree
*/
const DEPTH_INFINITY = -1;
@@ -102,7 +102,6 @@ class Sabre_DAV_Server {
'{DAV:}getetag',
'{DAV:}getlastmodified',
'{DAV:}lockdiscovery',
- '{DAV:}resourcetype',
'{DAV:}supportedlock',
// RFC4331
@@ -162,7 +161,7 @@ class Sabre_DAV_Server {
* If an array is passed, we automatically create a root node, and use
* the nodes in the array as top-level children.
*
- * @param Sabre_DAV_Tree|Sabre_DAV_INode|null $treeOrNode The tree object
+ * @param Sabre_DAV_Tree|Sabre_DAV_INode|array|null $treeOrNode The tree object
*/
public function __construct($treeOrNode = null) {
@@ -207,6 +206,10 @@ class Sabre_DAV_Server {
} catch (Exception $e) {
+ try {
+ $this->broadcastEvent('exception', array($e));
+ } catch (Exception $ignore) {
+ }
$DOM = new DOMDocument('1.0','utf-8');
$DOM->formatOutput = true;
@@ -214,17 +217,23 @@ class Sabre_DAV_Server {
$error->setAttribute('xmlns:s',self::NS_SABREDAV);
$DOM->appendChild($error);
- $error->appendChild($DOM->createElement('s:exception',get_class($e)));
- $error->appendChild($DOM->createElement('s:message',$e->getMessage()));
+ $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())));
if ($this->debugExceptions) {
- $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()));
+ $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())));
}
if (self::$exposeVersion) {
- $error->appendChild($DOM->createElement('s:sabredav-version',Sabre_DAV_Version::VERSION));
+ $error->appendChild($DOM->createElement('s:sabredav-version',$h(Sabre_DAV_Version::VERSION)));
}
if($e instanceof Sabre_DAV_Exception) {
@@ -508,7 +517,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.
@@ -696,6 +705,7 @@ 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
@@ -704,7 +714,10 @@ class Sabre_DAV_Server {
foreach($this->plugins as $plugin) $features = array_merge($features,$plugin->getFeatures());
$this->httpResponse->setHeader('DAV',implode(', ',$features));
- $data = $this->generateMultiStatus($newProperties);
+ $prefer = $this->getHTTPPrefer();
+ $minimal = $prefer['return-minimal'];
+
+ $data = $this->generateMultiStatus($newProperties, $minimal);
$this->httpResponse->sendBody($data);
}
@@ -724,6 +737,30 @@ 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');
@@ -927,7 +964,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 void
+ * @return bool
*/
protected function httpMove($uri) {
@@ -1009,7 +1046,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_ReportNotImplemented();
+ throw new Sabre_DAV_Exception_ReportNotSupported();
}
@@ -1158,6 +1195,85 @@ 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<token>[a-z0-9-]+)(?:=(?P<value>[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
@@ -1433,15 +1549,18 @@ class Sabre_DAV_Server {
}
- $this->broadcastEvent('afterGetProperties',array(trim($myPath,'/'),&$newProperties));
+ $this->broadcastEvent('afterGetProperties',array(trim($myPath,'/'),&$newProperties, $node));
$newProperties['href'] = trim($myPath,'/');
// Its is a WebDAV recommendation to add a trailing slash to collectionnames.
- // Apple's iCal also requires a trailing slash for principals (rfc 3744).
- // Therefore we add a trailing / for any non-file. This might need adjustments
- // if we find there are other edge cases.
- if ($myPath!='' && isset($newProperties[200]['{DAV:}resourcetype']) && count($newProperties[200]['{DAV:}resourcetype']->getValue())>0) $newProperties['href'] .='/';
+ // 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'] .='/';
+ }
+ }
// If the resourcetype property was manually added to the requested property list,
// we will remove it again.
@@ -1476,11 +1595,14 @@ 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);
+ $this->tree->markDirty($dir . '/' . $name);
$this->broadcastEvent('afterBind',array($uri));
$this->broadcastEvent('afterCreateFile',array($uri, $parent));
@@ -1901,12 +2023,15 @@ class Sabre_DAV_Server {
/**
- * Generates a WebDAV propfind response body based on a list of nodes
+ * Generates a WebDAV propfind response body based on a list of nodes.
+ *
+ * If 'strip404s' is set to true, all 404 responses will be removed.
*
* @param array $fileProperties The list with nodes
+ * @param bool strip404s
* @return string
*/
- public function generateMultiStatus(array $fileProperties) {
+ public function generateMultiStatus(array $fileProperties, $strip404s = false) {
$dom = new DOMDocument('1.0','utf-8');
//$dom->formatOutput = true;
@@ -1925,6 +2050,10 @@ 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);
@@ -1995,7 +2124,7 @@ class Sabre_DAV_Server {
if (!$body) return array();
$dom = Sabre_DAV_XMLUtil::loadDOMDocument($body);
- $elem = $dom->getElementsByTagNameNS('urn:DAV','propfind')->item(0);
+ $elem = $dom->getElementsByTagNameNS('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 131863d13fb..120569ffccd 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 requires event subscriptions.
+ * This method should set up the required event subscriptions.
*
* @param Sabre_DAV_Server $server
* @return void
diff --git a/3rdparty/Sabre/DAV/SimpleCollection.php b/3rdparty/Sabre/DAV/SimpleCollection.php
index 4acf971caa5..79e2eaaacd4 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 bassed.
+ * The name of the node must be passed, child nodes can also be passed.
* This nodes must be instances of Sabre_DAV_INode
*
* @param string $name
@@ -78,6 +78,9 @@ 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
deleted file mode 100755
index 621222ebc53..00000000000
--- a/3rdparty/Sabre/DAV/SimpleDirectory.php
+++ /dev/null
@@ -1,21 +0,0 @@
-<?php
-
-/**
- * SimpleDirectory
- *
- * The SimpleDirectory is used to quickly setup static directory structures.
- * Just create the object with a proper name, and add children to use it.
- *
- * This class is now deprecated, use Sabre_DAV_SimpleCollection instead.
- *
- * @package Sabre
- * @subpackage DAV
- * @deprecated Use Sabre_DAV_SimpleCollection instead.
- * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/)
- * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
- */
-class Sabre_DAV_SimpleDirectory extends Sabre_DAV_SimpleCollection {
-
-}
-
diff --git a/3rdparty/Sabre/DAV/Version.php b/3rdparty/Sabre/DAV/Version.php
index 274646240ab..55611cf2148 100755
--- a/3rdparty/Sabre/DAV/Version.php
+++ b/3rdparty/Sabre/DAV/Version.php
@@ -14,7 +14,7 @@ class Sabre_DAV_Version {
/**
* Full version number
*/
- const VERSION = '1.6.4';
+ const VERSION = '1.7.1';
/**
* Stability : alpha, beta, stable
diff --git a/3rdparty/Sabre/DAV/XMLUtil.php b/3rdparty/Sabre/DAV/XMLUtil.php
index 60eff3b159a..712fa3fc014 100755
--- a/3rdparty/Sabre/DAV/XMLUtil.php
+++ b/3rdparty/Sabre/DAV/XMLUtil.php
@@ -20,9 +20,6 @@ class Sabre_DAV_XMLUtil {
* {http://www.example.org}myelem
*
* This format is used throughout the SabreDAV sourcecode.
- * Elements encoded with the urn:DAV namespace will
- * be returned as if they were in the DAV: namespace. This is to avoid
- * compatibility problems.
*
* This function will return null if a nodetype other than an Element is passed.
*
@@ -33,8 +30,7 @@ class Sabre_DAV_XMLUtil {
if ($dom->nodeType !== XML_ELEMENT_NODE) return null;
- // Mapping back to the real namespace, in case it was dav
- if ($dom->namespaceURI=='urn:DAV') $ns = 'DAV:'; else $ns = $dom->namespaceURI;
+ $ns = $dom->namespaceURI;
// Mapping to clark notation
return '{' . $ns . '}' . $dom->localName;
@@ -65,28 +61,10 @@ 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, and it converts the DAV: namespace to urn:DAV.
+ * It does not preserve whitespace.
*
* @param string $xml
* @throws Sabre_DAV_Exception_BadRequest
@@ -118,10 +96,11 @@ 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 6a4890677ea..6728f88ce76 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__ . '/Property.php';
+include __DIR__ . '/PropertyInterface.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/ReportNotImplemented.php';
+include __DIR__ . '/Exception/ReportNotSupported.php';
include __DIR__ . '/Exception/RequestedRangeNotSatisfiable.php';
include __DIR__ . '/Exception/UnsupportedMediaType.php';
include __DIR__ . '/FS/Node.php';
@@ -72,18 +72,11 @@ include __DIR__ . '/IQuota.php';
include __DIR__ . '/Locks/Plugin.php';
include __DIR__ . '/Mount/Plugin.php';
include __DIR__ . '/ObjectTree.php';
-include __DIR__ . '/Property/GetLastModified.php';
-include __DIR__ . '/Property/Href.php';
-include __DIR__ . '/Property/HrefList.php';
-include __DIR__ . '/Property/LockDiscovery.php';
-include __DIR__ . '/Property/ResourceType.php';
-include __DIR__ . '/Property/Response.php';
-include __DIR__ . '/Property/ResponseList.php';
-include __DIR__ . '/Property/SupportedLock.php';
-include __DIR__ . '/Property/SupportedReportSet.php';
+include __DIR__ . '/PartialUpdate/IFile.php';
+include __DIR__ . '/PartialUpdate/Plugin.php';
+include __DIR__ . '/Property.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';
@@ -91,7 +84,15 @@ 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';
+include __DIR__ . '/Property/LockDiscovery.php';
+include __DIR__ . '/Property/ResourceType.php';
+include __DIR__ . '/Property/Response.php';
+include __DIR__ . '/Property/ResponseList.php';
+include __DIR__ . '/Property/SupportedLock.php';
+include __DIR__ . '/Property/SupportedReportSet.php';
include __DIR__ . '/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 e05b7749805..f67eadad6e9 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_DAV_IPrincipal
+ * @return Sabre_DAVACL_IPrincipal
*/
public function getChild($name) {
diff --git a/3rdparty/Sabre/DAVACL/IACL.php b/3rdparty/Sabre/DAVACL/IACL.php
index 003e6993483..356bb481d55 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.
+ * This method will receive a list of new ACE's as an array argument.
*
* @param array $acl
* @return void
diff --git a/3rdparty/Sabre/DAVACL/Plugin.php b/3rdparty/Sabre/DAVACL/Plugin.php
index 5c828c6d97b..5b17c838475 100755
--- a/3rdparty/Sabre/DAVACL/Plugin.php
+++ b/3rdparty/Sabre/DAVACL/Plugin.php
@@ -3,7 +3,7 @@
/**
* SabreDAV ACL Plugin
*
- * This plugin provides funcitonality to enforce ACL permissions.
+ * This plugin provides functionality 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,6 +233,7 @@ 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,6 +243,14 @@ 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.
*
@@ -253,6 +262,11 @@ 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);
@@ -277,6 +291,9 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
}
+ // Store the result in the cache
+ $this->currentUserPrincipalsCache[$currentUser] = $principals;
+
return $principals;
}
@@ -771,7 +788,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 void
+ * @return bool
*/
public function beforeGetProperties($uri, Sabre_DAV_INode $node, &$requestedProperties, &$returnedProperties) {
@@ -895,6 +912,18 @@ 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() . '/');
+
+ }
+
+ }
+
}
/**
@@ -928,6 +957,9 @@ 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']);
@@ -935,7 +967,7 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
}
/**
- * This method handels HTTP REPORT requests
+ * This method handles HTTP REPORT requests
*
* @param string $reportName
* @param DOMNode $dom
@@ -1268,10 +1300,12 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
}
$result = $this->principalSearch($searchProperties, $requestedProperties, $uri);
- $xml = $this->server->generateMultiStatus($result);
- $this->server->httpResponse->setHeader('Content-Type','application/xml; charset=utf-8');
+ $prefer = $this->server->getHTTPPRefer();
+
$this->server->httpResponse->sendStatus(207);
- $this->server->httpResponse->sendBody($xml);
+ $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']));
}
diff --git a/3rdparty/Sabre/DAVACL/Property/Acl.php b/3rdparty/Sabre/DAVACL/Property/Acl.php
index 05e1a690b3c..3f79a8d532e 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('urn:DAV','ace');
+ $xaces = $dom->getElementsByTagNameNS('DAV:','ace');
for($ii=0; $ii < $xaces->length; $ii++) {
$xace = $xaces->item($ii);
- $principal = $xace->getElementsByTagNameNS('urn:DAV','principal');
+ $principal = $xace->getElementsByTagNameNS('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('urn:DAV','protected')->length > 0) {
+ if ($xace->getElementsByTagNameNS('DAV:','protected')->length > 0) {
$protected = true;
}
- $grants = $xace->getElementsByTagNameNS('urn:DAV','grant');
+ $grants = $xace->getElementsByTagNameNS('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('urn:DAV','privilege');
+ $xprivs = $grant->getElementsByTagNameNS('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 c36328a58e0..3f681742276 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 UNAUTHENTICTED principal
+ * To specify a not-logged-in user, use the UNAUTHENTICATED 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_DAV_Property_Principal
+ * @return Sabre_DAVACL_Property_Principal
*/
static public function unserialize(DOMElement $dom) {
diff --git a/3rdparty/Sabre/DAVACL/Version.php b/3rdparty/Sabre/DAVACL/Version.php
index 9950f748741..084a9c13c89 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.6.0';
+ const VERSION = '1.7.0';
/**
* Stability : alpha, beta, stable
diff --git a/3rdparty/Sabre/HTTP/Request.php b/3rdparty/Sabre/HTTP/Request.php
index 4746ef77704..74d5ed3d7ee 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 ffe9bda2082..9d436881bdf 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,6 +85,9 @@ class Sabre_HTTP_Response {
}
+ // @codeCoverageIgnoreStart
+ // We cannot reasonably test header() related methods.
+
/**
* Sends an HTTP status header to the client
*
@@ -114,7 +117,9 @@ 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 e6b4f7e5358..8ccd7c9edf6 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.6.4';
+ const VERSION = '1.7.0';
/**
* Stability : alpha, beta, stable
diff --git a/3rdparty/Sabre/VObject/Component.php b/3rdparty/Sabre/VObject/Component.php
deleted file mode 100755
index b78a26133fa..00000000000
--- a/3rdparty/Sabre/VObject/Component.php
+++ /dev/null
@@ -1,365 +0,0 @@
-<?php
-
-/**
- * VObject Component
- *
- * This class represents a VCALENDAR/VCARD component. A component is for example
- * VEVENT, VTODO and also VCALENDAR. It starts with BEGIN:COMPONENTNAME and
- * ends with END:COMPONENTNAME
- *
- * @package Sabre
- * @subpackage VObject
- * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/)
- * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
- */
-class Sabre_VObject_Component extends Sabre_VObject_Element {
-
- /**
- * Name, for example VEVENT
- *
- * @var string
- */
- public $name;
-
- /**
- * Children properties and components
- *
- * @var array
- */
- public $children = array();
-
- /**
- * If coponents are added to this map, they will be automatically mapped
- * to their respective classes, if parsed by the reader or constructed with
- * the 'create' method.
- *
- * @var array
- */
- static public $classMap = array(
- 'VCALENDAR' => 'Sabre_VObject_Component_VCalendar',
- 'VEVENT' => 'Sabre_VObject_Component_VEvent',
- 'VTODO' => 'Sabre_VObject_Component_VTodo',
- 'VJOURNAL' => 'Sabre_VObject_Component_VJournal',
- 'VALARM' => 'Sabre_VObject_Component_VAlarm',
- );
-
- /**
- * Creates the new component by name, but in addition will also see if
- * there's a class mapped to the property name.
- *
- * @param string $name
- * @param string $value
- * @return Sabre_VObject_Component
- */
- static public function create($name, $value = null) {
-
- $name = strtoupper($name);
-
- if (isset(self::$classMap[$name])) {
- return new self::$classMap[$name]($name, $value);
- } else {
- return new self($name, $value);
- }
-
- }
-
- /**
- * Creates a new component.
- *
- * By default this object will iterate over its own children, but this can
- * 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
deleted file mode 100755
index ebb4a9b18f6..00000000000
--- a/3rdparty/Sabre/VObject/Component/VAlarm.php
+++ /dev/null
@@ -1,102 +0,0 @@
-<?php
-
-/**
- * VAlarm component
- *
- * This component contains some additional functionality specific for VALARMs.
- *
- * @package Sabre
- * @subpackage VObject
- * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/)
- * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
- */
-class Sabre_VObject_Component_VAlarm extends Sabre_VObject_Component {
-
- /**
- * Returns a DateTime object when this alarm is going to trigger.
- *
- * This ignores repeated alarm, only the first trigger is returned.
- *
- * @return DateTime
- */
- public function getEffectiveTriggerTime() {
-
- $trigger = $this->TRIGGER;
- if(!isset($trigger['VALUE']) || strtoupper($trigger['VALUE']) === 'DURATION') {
- $triggerDuration = Sabre_VObject_DateTimeParser::parseDuration($this->TRIGGER);
- $related = (isset($trigger['RELATED']) && strtoupper($trigger['RELATED']) == 'END') ? 'END' : 'START';
-
- $parentComponent = $this->parent;
- if ($related === 'START') {
- $effectiveTrigger = clone $parentComponent->DTSTART->getDateTime();
- $effectiveTrigger->add($triggerDuration);
- } else {
- if ($parentComponent->name === 'VTODO') {
- $endProp = 'DUE';
- } elseif ($parentComponent->name === 'VEVENT') {
- $endProp = 'DTEND';
- } else {
- throw new Sabre_DAV_Exception('time-range filters on VALARM components are only supported when they are a child of VTODO or VEVENT');
- }
-
- if (isset($parentComponent->$endProp)) {
- $effectiveTrigger = clone $parentComponent->$endProp->getDateTime();
- $effectiveTrigger->add($triggerDuration);
- } elseif (isset($parentComponent->DURATION)) {
- $effectiveTrigger = clone $parentComponent->DTSTART->getDateTime();
- $duration = Sabre_VObject_DateTimeParser::parseDuration($parentComponent->DURATION);
- $effectiveTrigger->add($duration);
- $effectiveTrigger->add($triggerDuration);
- } else {
- $effectiveTrigger = clone $parentComponent->DTSTART->getDateTime();
- $effectiveTrigger->add($triggerDuration);
- }
- }
- } else {
- $effectiveTrigger = $trigger->getDateTime();
- }
- return $effectiveTrigger;
-
- }
-
- /**
- * Returns true or false depending on if the event falls in the specified
- * time-range. This is used for filtering purposes.
- *
- * The rules used to determine if an event falls within the specified
- * time-range is based on the CalDAV specification.
- *
- * @param DateTime $start
- * @param DateTime $end
- * @return bool
- */
- public function isInTimeRange(DateTime $start, DateTime $end) {
-
- $effectiveTrigger = $this->getEffectiveTriggerTime();
-
- if (isset($this->DURATION)) {
- $duration = Sabre_VObject_DateTimeParser::parseDuration($this->DURATION);
- $repeat = (string)$this->repeat;
- if (!$repeat) {
- $repeat = 1;
- }
-
- $period = new DatePeriod($effectiveTrigger, $duration, (int)$repeat);
-
- foreach($period as $occurrence) {
-
- if ($start <= $occurrence && $end > $occurrence) {
- return true;
- }
- }
- return false;
- } else {
- return ($start <= $effectiveTrigger && $end > $effectiveTrigger);
- }
-
- }
-
-}
-
-?>
diff --git a/3rdparty/Sabre/VObject/Component/VCalendar.php b/3rdparty/Sabre/VObject/Component/VCalendar.php
deleted file mode 100755
index f3be29afdbb..00000000000
--- a/3rdparty/Sabre/VObject/Component/VCalendar.php
+++ /dev/null
@@ -1,133 +0,0 @@
-<?php
-
-/**
- * The VCalendar component
- *
- * This component adds functionality to a component, specific for a VCALENDAR.
- *
- * @package Sabre
- * @subpackage VObject
- * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/)
- * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
- */
-class Sabre_VObject_Component_VCalendar extends Sabre_VObject_Component {
-
- /**
- * Returns a list of all 'base components'. For instance, if an Event has
- * a recurrence rule, and one instance is overridden, the overridden event
- * will have the same UID, but will be excluded from this list.
- *
- * VTIMEZONE components will always be excluded.
- *
- * @param string $componentName filter by component name
- * @return array
- */
- public function getBaseComponents($componentName = null) {
-
- $components = array();
- foreach($this->children as $component) {
-
- if (!$component instanceof Sabre_VObject_Component)
- continue;
-
- if (isset($component->{'RECURRENCE-ID'}))
- continue;
-
- if ($componentName && $component->name !== strtoupper($componentName))
- continue;
-
- if ($component->name === 'VTIMEZONE')
- continue;
-
- $components[] = $component;
-
- }
-
- return $components;
-
- }
-
- /**
- * If this calendar object, has events with recurrence rules, this method
- * can be used to expand the event into multiple sub-events.
- *
- * Each event will be stripped from it's recurrence information, and only
- * the instances of the event in the specified timerange will be left
- * alone.
- *
- * In addition, this method will cause timezone information to be stripped,
- * and normalized to UTC.
- *
- * This method will alter the VCalendar. This cannot be reversed.
- *
- * This functionality is specifically used by the CalDAV standard. It is
- * possible for clients to request expand events, if they are rather simple
- * clients and do not have the possibility to calculate recurrences.
- *
- * @param DateTime $start
- * @param DateTime $end
- * @return void
- */
- public function expand(DateTime $start, DateTime $end) {
-
- $newEvents = array();
-
- foreach($this->select('VEVENT') as $key=>$vevent) {
-
- if (isset($vevent->{'RECURRENCE-ID'})) {
- unset($this->children[$key]);
- continue;
- }
-
-
- if (!$vevent->rrule) {
- unset($this->children[$key]);
- if ($vevent->isInTimeRange($start, $end)) {
- $newEvents[] = $vevent;
- }
- continue;
- }
-
- $uid = (string)$vevent->uid;
- if (!$uid) {
- throw new LogicException('Event did not have a UID!');
- }
-
- $it = new Sabre_VObject_RecurrenceIterator($this, $vevent->uid);
- $it->fastForward($start);
-
- while($it->valid() && $it->getDTStart() < $end) {
-
- if ($it->getDTEnd() > $start) {
-
- $newEvents[] = $it->getEventObject();
-
- }
- $it->next();
-
- }
- unset($this->children[$key]);
-
- }
-
- foreach($newEvents as $newEvent) {
-
- foreach($newEvent->children as $child) {
- if ($child instanceof Sabre_VObject_Property_DateTime &&
- $child->getDateType() == Sabre_VObject_Property_DateTime::LOCALTZ) {
- $child->setDateTime($child->getDateTime(),Sabre_VObject_Property_DateTime::UTC);
- }
- }
-
- $this->add($newEvent);
-
- }
-
- // Removing all VTIMEZONE components
- unset($this->VTIMEZONE);
-
- }
-
-}
-
diff --git a/3rdparty/Sabre/VObject/Component/VEvent.php b/3rdparty/Sabre/VObject/Component/VEvent.php
deleted file mode 100755
index d6b910874d0..00000000000
--- a/3rdparty/Sabre/VObject/Component/VEvent.php
+++ /dev/null
@@ -1,71 +0,0 @@
-<?php
-
-/**
- * VEvent component
- *
- * This component contains some additional functionality specific for VEVENT's.
- *
- * @package Sabre
- * @subpackage VObject
- * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/)
- * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
- */
-class Sabre_VObject_Component_VEvent extends Sabre_VObject_Component {
-
- /**
- * Returns true or false depending on if the event falls in the specified
- * time-range. This is used for filtering purposes.
- *
- * The rules used to determine if an event falls within the specified
- * time-range is based on the CalDAV specification.
- *
- * @param DateTime $start
- * @param DateTime $end
- * @return bool
- */
- public function isInTimeRange(DateTime $start, DateTime $end) {
-
- if ($this->RRULE) {
- $it = new Sabre_VObject_RecurrenceIterator($this);
- $it->fastForward($start);
-
- // We fast-forwarded to a spot where the end-time of the
- // recurrence instance exceeded the start of the requested
- // time-range.
- //
- // If the starttime of the recurrence did not exceed the
- // end of the time range as well, we have a match.
- return ($it->getDTStart() < $end && $it->getDTEnd() > $start);
-
- }
-
- $effectiveStart = $this->DTSTART->getDateTime();
- if (isset($this->DTEND)) {
-
- // 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
deleted file mode 100755
index 22b3ec921e5..00000000000
--- a/3rdparty/Sabre/VObject/Component/VJournal.php
+++ /dev/null
@@ -1,46 +0,0 @@
-<?php
-
-/**
- * VJournal component
- *
- * This component contains some additional functionality specific for VJOURNALs.
- *
- * @package Sabre
- * @subpackage VObject
- * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/)
- * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
- */
-class Sabre_VObject_Component_VJournal extends Sabre_VObject_Component {
-
- /**
- * Returns true or false depending on if the event falls in the specified
- * time-range. This is used for filtering purposes.
- *
- * The rules used to determine if an event falls within the specified
- * time-range is based on the CalDAV specification.
- *
- * @param DateTime $start
- * @param DateTime $end
- * @return bool
- */
- public function isInTimeRange(DateTime $start, DateTime $end) {
-
- $dtstart = isset($this->DTSTART)?$this->DTSTART->getDateTime():null;
- if ($dtstart) {
- $effectiveEnd = clone $dtstart;
- if ($this->DTSTART->getDateType() == Sabre_VObject_Element_DateTime::DATE) {
- $effectiveEnd->modify('+1 day');
- }
-
- return ($start <= $effectiveEnd && $end > $dtstart);
-
- }
- return false;
-
-
- }
-
-}
-
-?>
diff --git a/3rdparty/Sabre/VObject/Component/VTodo.php b/3rdparty/Sabre/VObject/Component/VTodo.php
deleted file mode 100755
index 79d06298d7f..00000000000
--- a/3rdparty/Sabre/VObject/Component/VTodo.php
+++ /dev/null
@@ -1,68 +0,0 @@
-<?php
-
-/**
- * VTodo component
- *
- * This component contains some additional functionality specific for VTODOs.
- *
- * @package Sabre
- * @subpackage VObject
- * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/)
- * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
- */
-class Sabre_VObject_Component_VTodo extends Sabre_VObject_Component {
-
- /**
- * Returns true or false depending on if the event falls in the specified
- * time-range. This is used for filtering purposes.
- *
- * The rules used to determine if an event falls within the specified
- * time-range is based on the CalDAV specification.
- *
- * @param DateTime $start
- * @param DateTime $end
- * @return bool
- */
- public function isInTimeRange(DateTime $start, DateTime $end) {
-
- $dtstart = isset($this->DTSTART)?$this->DTSTART->getDateTime():null;
- $duration = isset($this->DURATION)?Sabre_VObject_DateTimeParser::parseDuration($this->DURATION):null;
- $due = isset($this->DUE)?$this->DUE->getDateTime():null;
- $completed = isset($this->COMPLETED)?$this->COMPLETED->getDateTime():null;
- $created = isset($this->CREATED)?$this->CREATED->getDateTime():null;
-
- if ($dtstart) {
- if ($duration) {
- $effectiveEnd = clone $dtstart;
- $effectiveEnd->add($duration);
- return $start <= $effectiveEnd && $end > $dtstart;
- } elseif ($due) {
- return
- ($start < $due || $start <= $dtstart) &&
- ($end > $dtstart || $end >= $due);
- } else {
- return $start <= $dtstart && $end > $dtstart;
- }
- }
- if ($due) {
- return ($start < $due && $end >= $due);
- }
- if ($completed && $created) {
- return
- ($start <= $created || $start <= $completed) &&
- ($end >= $created || $end >= $completed);
- }
- if ($completed) {
- return ($start <= $completed && $end >= $completed);
- }
- if ($created) {
- return ($end > $created);
- }
- return true;
-
- }
-
-}
-
-?>
diff --git a/3rdparty/Sabre/VObject/DateTimeParser.php b/3rdparty/Sabre/VObject/DateTimeParser.php
deleted file mode 100755
index 23a4bb69916..00000000000
--- a/3rdparty/Sabre/VObject/DateTimeParser.php
+++ /dev/null
@@ -1,181 +0,0 @@
-<?php
-
-/**
- * DateTimeParser
- *
- * This class is responsible for parsing the several different date and time
- * formats iCalendar and vCards have.
- *
- * @package Sabre
- * @subpackage VObject
- * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/)
- * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
- */
-class Sabre_VObject_DateTimeParser {
-
- /**
- * Parses an iCalendar (rfc5545) formatted datetime and returns a DateTime object
- *
- * Specifying a reference timezone is optional. It will only be used
- * if the non-UTC format is used. The argument is used as a reference, the
- * returned DateTime object will still be in the UTC timezone.
- *
- * @param string $dt
- * @param DateTimeZone $tz
- * @return DateTime
- */
- static public function parseDateTime($dt,DateTimeZone $tz = null) {
-
- // Format is YYYYMMDD + "T" + hhmmss
- $result = preg_match('/^([1-3][0-9]{3})([0-1][0-9])([0-3][0-9])T([0-2][0-9])([0-5][0-9])([0-5][0-9])([Z]?)$/',$dt,$matches);
-
- if (!$result) {
- throw new Sabre_DAV_Exception_BadRequest('The supplied iCalendar datetime value is incorrect: ' . $dt);
- }
-
- if ($matches[7]==='Z' || is_null($tz)) {
- $tz = new DateTimeZone('UTC');
- }
- $date = new DateTime($matches[1] . '-' . $matches[2] . '-' . $matches[3] . ' ' . $matches[4] . ':' . $matches[5] .':' . $matches[6], $tz);
-
- // Still resetting the timezone, to normalize everything to UTC
- $date->setTimeZone(new DateTimeZone('UTC'));
- return $date;
-
- }
-
- /**
- * Parses an iCalendar (rfc5545) formatted date and returns a DateTime object
- *
- * @param string $date
- * @return DateTime
- */
- static public function parseDate($date) {
-
- // Format is YYYYMMDD
- $result = preg_match('/^([1-3][0-9]{3})([0-1][0-9])([0-3][0-9])$/',$date,$matches);
-
- if (!$result) {
- throw new Sabre_DAV_Exception_BadRequest('The supplied iCalendar date value is incorrect: ' . $date);
- }
-
- $date = new DateTime($matches[1] . '-' . $matches[2] . '-' . $matches[3], new DateTimeZone('UTC'));
- return $date;
-
- }
-
- /**
- * Parses an iCalendar (RFC5545) formatted duration value.
- *
- * This method will either return a DateTimeInterval object, or a string
- * suitable for strtotime or DateTime::modify.
- *
- * @param string $duration
- * @param bool $asString
- * @return DateInterval|string
- */
- static public function parseDuration($duration, $asString = false) {
-
- $result = preg_match('/^(?P<plusminus>\+|-)?P((?P<week>\d+)W)?((?P<day>\d+)D)?(T((?P<hour>\d+)H)?((?P<minute>\d+)M)?((?P<second>\d+)S)?)?$/', $duration, $matches);
- if (!$result) {
- throw new Sabre_DAV_Exception_BadRequest('The supplied iCalendar duration value is incorrect: ' . $duration);
- }
-
- if (!$asString) {
- $invert = false;
- if ($matches['plusminus']==='-') {
- $invert = true;
- }
-
-
- $parts = array(
- 'week',
- 'day',
- 'hour',
- 'minute',
- 'second',
- );
- foreach($parts as $part) {
- $matches[$part] = isset($matches[$part])&&$matches[$part]?(int)$matches[$part]:0;
- }
-
-
- // We need to re-construct the $duration string, because weeks and
- // days are not supported by DateInterval in the same string.
- $duration = 'P';
- $days = $matches['day'];
- if ($matches['week']) {
- $days+=$matches['week']*7;
- }
- if ($days)
- $duration.=$days . 'D';
-
- if ($matches['minute'] || $matches['second'] || $matches['hour']) {
- $duration.='T';
-
- if ($matches['hour'])
- $duration.=$matches['hour'].'H';
-
- if ($matches['minute'])
- $duration.=$matches['minute'].'M';
-
- if ($matches['second'])
- $duration.=$matches['second'].'S';
-
- }
-
- 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
deleted file mode 100755
index e20ff0b353c..00000000000
--- a/3rdparty/Sabre/VObject/Element.php
+++ /dev/null
@@ -1,16 +0,0 @@
-<?php
-
-/**
- * Base class for all elements
- *
- * @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
- */
-abstract class Sabre_VObject_Element extends Sabre_VObject_Node {
-
- public $parent = null;
-
-}
diff --git a/3rdparty/Sabre/VObject/Element/DateTime.php b/3rdparty/Sabre/VObject/Element/DateTime.php
deleted file mode 100755
index 5e5eb7ab6f2..00000000000
--- a/3rdparty/Sabre/VObject/Element/DateTime.php
+++ /dev/null
@@ -1,37 +0,0 @@
-<?php
-
-/**
- * DateTime property
- *
- * this class got renamed to Sabre_VObject_Property_DateTime
- *
- * @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
- * @deprecated
- */
-class Sabre_VObject_Element_DateTime extends Sabre_VObject_Property_DateTime {
-
- /**
- * Local 'floating' time
- */
- const LOCAL = 1;
-
- /**
- * UTC-based time
- */
- const UTC = 2;
-
- /**
- * Local time plus timezone
- */
- const LOCALTZ = 3;
-
- /**
- * Only a date, time is ignored
- */
- const DATE = 4;
-
-}
diff --git a/3rdparty/Sabre/VObject/Element/MultiDateTime.php b/3rdparty/Sabre/VObject/Element/MultiDateTime.php
deleted file mode 100755
index 8a12ced94a8..00000000000
--- a/3rdparty/Sabre/VObject/Element/MultiDateTime.php
+++ /dev/null
@@ -1,17 +0,0 @@
-<?php
-
-/**
- * Multi-DateTime property
- *
- * This class got renamed to Sabre_VObject_Property_MultiDateTime
- *
- * @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
- * @deprecated
- */
-class Sabre_VObject_Element_MultiDateTime extends Sabre_VObject_Property_MultiDateTime {
-
-}
diff --git a/3rdparty/Sabre/VObject/ElementList.php b/3rdparty/Sabre/VObject/ElementList.php
deleted file mode 100755
index 7e508db20f0..00000000000
--- a/3rdparty/Sabre/VObject/ElementList.php
+++ /dev/null
@@ -1,172 +0,0 @@
-<?php
-
-/**
- * VObject ElementList
- *
- * This class represents a list of elements. Lists are the result of queries,
- * such as doing $vcalendar->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
deleted file mode 100755
index 1c96a64a004..00000000000
--- a/3rdparty/Sabre/VObject/FreeBusyGenerator.php
+++ /dev/null
@@ -1,297 +0,0 @@
-<?php
-
-/**
- * This class helps with generating FREEBUSY reports based on existing sets of
- * objects.
- *
- * It only looks at VEVENT and VFREEBUSY objects from the sourcedata, and
- * generates a single VFREEBUSY object.
- *
- * VFREEBUSY components are described in RFC5545, The rules for what should
- * go in a single freebusy report is taken from RFC4791, section 7.10.
- *
- * @package Sabre
- * @subpackage VObject
- * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/)
- * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
- */
-class Sabre_VObject_FreeBusyGenerator {
-
- /**
- * Input objects
- *
- * @var array
- */
- protected $objects;
-
- /**
- * Start of range
- *
- * @var DateTime|null
- */
- protected $start;
-
- /**
- * End of range
- *
- * @var DateTime|null
- */
- protected $end;
-
- /**
- * VCALENDAR object
- *
- * @var Sabre_VObject_Component
- */
- protected $baseObject;
-
- /**
- * Sets the VCALENDAR object.
- *
- * If this is set, it will not be generated for you. You are responsible
- * for setting things like the METHOD, CALSCALE, VERSION, etc..
- *
- * The VFREEBUSY object will be automatically added though.
- *
- * @param Sabre_VObject_Component $vcalendar
- * @return void
- */
- public function setBaseObject(Sabre_VObject_Component $vcalendar) {
-
- $this->baseObject = $vcalendar;
-
- }
-
- /**
- * Sets the input objects
- *
- * Every object must either be a string or a Sabre_VObject_Component.
- *
- * @param array $objects
- * @return void
- */
- public function setObjects(array $objects) {
-
- $this->objects = array();
- foreach($objects as $object) {
-
- if (is_string($object)) {
- $this->objects[] = Sabre_VObject_Reader::read($object);
- } elseif ($object instanceof Sabre_VObject_Component) {
- $this->objects[] = $object;
- } else {
- throw new InvalidArgumentException('You can only pass strings or Sabre_VObject_Component arguments to setObjects');
- }
-
- }
-
- }
-
- /**
- * Sets the time range
- *
- * Any freebusy object falling outside of this time range will be ignored.
- *
- * @param DateTime $start
- * @param DateTime $end
- * @return void
- */
- public function setTimeRange(DateTime $start = null, DateTime $end = null) {
-
- $this->start = $start;
- $this->end = $end;
-
- }
-
- /**
- * Parses the input data and returns a correct VFREEBUSY object, wrapped in
- * a VCALENDAR.
- *
- * @return Sabre_VObject_Component
- */
- public function getResult() {
-
- $busyTimes = array();
-
- foreach($this->objects as $object) {
-
- foreach($object->getBaseComponents() as $component) {
-
- switch($component->name) {
-
- case 'VEVENT' :
-
- $FBTYPE = 'BUSY';
- if (isset($component->TRANSP) && (strtoupper($component->TRANSP) === 'TRANSPARENT')) {
- break;
- }
- if (isset($component->STATUS)) {
- $status = strtoupper($component->STATUS);
- if ($status==='CANCELLED') {
- break;
- }
- if ($status==='TENTATIVE') {
- $FBTYPE = 'BUSY-TENTATIVE';
- }
- }
-
- $times = array();
-
- if ($component->RRULE) {
-
- $iterator = new Sabre_VObject_RecurrenceIterator($object, (string)$component->uid);
- if ($this->start) {
- $iterator->fastForward($this->start);
- }
-
- $maxRecurrences = 200;
-
- while($iterator->valid() && --$maxRecurrences) {
-
- $startTime = $iterator->getDTStart();
- if ($this->end && $startTime > $this->end) {
- break;
- }
- $times[] = array(
- $iterator->getDTStart(),
- $iterator->getDTEnd(),
- );
-
- $iterator->next();
-
- }
-
- } else {
-
- $startTime = $component->DTSTART->getDateTime();
- if ($this->end && $startTime > $this->end) {
- break;
- }
- $endTime = null;
- if (isset($component->DTEND)) {
- $endTime = $component->DTEND->getDateTime();
- } elseif (isset($component->DURATION)) {
- $duration = Sabre_VObject_DateTimeParser::parseDuration((string)$component->DURATION);
- $endTime = clone $startTime;
- $endTime->add($duration);
- } elseif ($component->DTSTART->getDateType() === Sabre_VObject_Property_DateTime::DATE) {
- $endTime = clone $startTime;
- $endTime->modify('+1 day');
- } else {
- // The event had no duration (0 seconds)
- break;
- }
-
- $times[] = array($startTime, $endTime);
-
- }
-
- foreach($times as $time) {
-
- if ($this->end && $time[0] > $this->end) break;
- if ($this->start && $time[1] < $this->start) break;
-
- $busyTimes[] = array(
- $time[0],
- $time[1],
- $FBTYPE,
- );
- }
- break;
-
- case 'VFREEBUSY' :
- foreach($component->FREEBUSY as $freebusy) {
-
- $fbType = isset($freebusy['FBTYPE'])?strtoupper($freebusy['FBTYPE']):'BUSY';
-
- // Skipping intervals marked as 'free'
- if ($fbType==='FREE')
- continue;
-
- $values = explode(',', $freebusy);
- foreach($values as $value) {
- list($startTime, $endTime) = explode('/', $value);
- $startTime = Sabre_VObject_DateTimeParser::parseDateTime($startTime);
-
- if (substr($endTime,0,1)==='P' || substr($endTime,0,2)==='-P') {
- $duration = Sabre_VObject_DateTimeParser::parseDuration($endTime);
- $endTime = clone $startTime;
- $endTime->add($duration);
- } else {
- $endTime = Sabre_VObject_DateTimeParser::parseDateTime($endTime);
- }
-
- if($this->start && $this->start > $endTime) continue;
- if($this->end && $this->end < $startTime) continue;
- $busyTimes[] = array(
- $startTime,
- $endTime,
- $fbType
- );
-
- }
-
-
- }
- break;
-
-
-
- }
-
-
- }
-
- }
-
- if ($this->baseObject) {
- $calendar = $this->baseObject;
- } else {
- $calendar = new Sabre_VObject_Component('VCALENDAR');
- $calendar->version = '2.0';
- if (Sabre_DAV_Server::$exposeVersion) {
- $calendar->prodid = '-//SabreDAV//Sabre VObject ' . Sabre_VObject_Version::VERSION . '//EN';
- } else {
- $calendar->prodid = '-//SabreDAV//Sabre VObject//EN';
- }
- $calendar->calscale = 'GREGORIAN';
- }
-
- $vfreebusy = new Sabre_VObject_Component('VFREEBUSY');
- $calendar->add($vfreebusy);
-
- if ($this->start) {
- $dtstart = new Sabre_VObject_Property_DateTime('DTSTART');
- $dtstart->setDateTime($this->start,Sabre_VObject_Property_DateTime::UTC);
- $vfreebusy->add($dtstart);
- }
- if ($this->end) {
- $dtend = new Sabre_VObject_Property_DateTime('DTEND');
- $dtend->setDateTime($this->start,Sabre_VObject_Property_DateTime::UTC);
- $vfreebusy->add($dtend);
- }
- $dtstamp = new Sabre_VObject_Property_DateTime('DTSTAMP');
- $dtstamp->setDateTime(new DateTime('now'), Sabre_VObject_Property_DateTime::UTC);
- $vfreebusy->add($dtstamp);
-
- foreach($busyTimes as $busyTime) {
-
- $busyTime[0]->setTimeZone(new DateTimeZone('UTC'));
- $busyTime[1]->setTimeZone(new DateTimeZone('UTC'));
-
- $prop = new Sabre_VObject_Property(
- 'FREEBUSY',
- $busyTime[0]->format('Ymd\\THis\\Z') . '/' . $busyTime[1]->format('Ymd\\THis\\Z')
- );
- $prop['FBTYPE'] = $busyTime[2];
- $vfreebusy->add($prop);
-
- }
-
- return $calendar;
-
- }
-
-}
-
diff --git a/3rdparty/Sabre/VObject/Node.php b/3rdparty/Sabre/VObject/Node.php
deleted file mode 100755
index d89e01b56c6..00000000000
--- a/3rdparty/Sabre/VObject/Node.php
+++ /dev/null
@@ -1,149 +0,0 @@
-<?php
-
-/**
- * Base class for all nodes
- *
- * @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
- */
-abstract class Sabre_VObject_Node implements IteratorAggregate, ArrayAccess, Countable {
-
- /**
- * Turns the object back into a serialized blob.
- *
- * @return string
- */
- abstract function serialize();
-
- /**
- * Iterator override
- *
- * @var Sabre_VObject_ElementList
- */
- protected $iterator = null;
-
- /**
- * A link to the parent node
- *
- * @var Sabre_VObject_Node
- */
- public $parent = null;
-
- /* {{{ IteratorAggregator interface */
-
- /**
- * Returns the iterator for this object
- *
- * @return Sabre_VObject_ElementList
- */
- public function getIterator() {
-
- if (!is_null($this->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
deleted file mode 100755
index 2e39af5f78a..00000000000
--- a/3rdparty/Sabre/VObject/Parameter.php
+++ /dev/null
@@ -1,84 +0,0 @@
-<?php
-
-/**
- * VObject Parameter
- *
- * This class represents a parameter. A parameter is always tied to a property.
- * In the case of:
- * DTSTART;VALUE=DATE:20101108
- * VALUE=DATE would be the parameter name and value.
- *
- * @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_Parameter extends Sabre_VObject_Node {
-
- /**
- * Parameter name
- *
- * @var string
- */
- public $name;
-
- /**
- * Parameter value
- *
- * @var string
- */
- public $value;
-
- /**
- * Sets up the object
- *
- * @param string $name
- * @param string $value
- */
- public function __construct($name, $value = null) {
-
- $this->name = strtoupper($name);
- $this->value = $value;
-
- }
-
- /**
- * Turns the object back into a serialized blob.
- *
- * @return string
- */
- 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
deleted file mode 100755
index 1b5e95bf16e..00000000000
--- a/3rdparty/Sabre/VObject/ParseException.php
+++ /dev/null
@@ -1,12 +0,0 @@
-<?php
-
-/**
- * Exception thrown by Sabre_VObject_Reader if an invalid object was attempted to be parsed.
- *
- * @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_ParseException extends Exception { }
diff --git a/3rdparty/Sabre/VObject/Property.php b/3rdparty/Sabre/VObject/Property.php
deleted file mode 100755
index ce74fe3865b..00000000000
--- a/3rdparty/Sabre/VObject/Property.php
+++ /dev/null
@@ -1,348 +0,0 @@
-<?php
-
-/**
- * VObject Property
- *
- * A property in VObject is usually in the form PARAMNAME:paramValue.
- * An example is : SUMMARY:Weekly meeting
- *
- * Properties can also have parameters:
- * SUMMARY;LANG=en:Weekly meeting.
- *
- * Parameters can be accessed using the ArrayAccess interface.
- *
- * @package Sabre
- * @subpackage VObject
- * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/)
- * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
- */
-class Sabre_VObject_Property extends Sabre_VObject_Element {
-
- /**
- * Propertyname
- *
- * @var string
- */
- public $name;
-
- /**
- * Group name
- *
- * This may be something like 'HOME' for vcards.
- *
- * @var string
- */
- public $group;
-
- /**
- * Property parameters
- *
- * @var array
- */
- public $parameters = array();
-
- /**
- * Property value
- *
- * @var string
- */
- public $value;
-
- /**
- * If properties are added to this map, they will be automatically mapped
- * to their respective classes, if parsed by the reader or constructed with
- * the 'create' method.
- *
- * @var array
- */
- static public $classMap = array(
- 'COMPLETED' => 'Sabre_VObject_Property_DateTime',
- 'CREATED' => 'Sabre_VObject_Property_DateTime',
- 'DTEND' => 'Sabre_VObject_Property_DateTime',
- 'DTSTAMP' => 'Sabre_VObject_Property_DateTime',
- 'DTSTART' => 'Sabre_VObject_Property_DateTime',
- 'DUE' => 'Sabre_VObject_Property_DateTime',
- 'EXDATE' => 'Sabre_VObject_Property_MultiDateTime',
- 'LAST-MODIFIED' => 'Sabre_VObject_Property_DateTime',
- 'RECURRENCE-ID' => 'Sabre_VObject_Property_DateTime',
- 'TRIGGER' => 'Sabre_VObject_Property_DateTime',
- );
-
- /**
- * Creates the new property by name, but in addition will also see if
- * there's a class mapped to the property name.
- *
- * @param string $name
- * @param string $value
- * @return void
- */
- static public function create($name, $value = null) {
-
- $name = strtoupper($name);
- $shortName = $name;
- $group = null;
- if (strpos($shortName,'.')!==false) {
- list($group, $shortName) = explode('.', $shortName);
- }
-
- if (isset(self::$classMap[$shortName])) {
- return new self::$classMap[$shortName]($name, $value);
- } else {
- return new self($name, $value);
- }
-
- }
-
- /**
- * Creates a new property object
- *
- * By default this object will iterate over its own children, but this can
- * 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
deleted file mode 100755
index fe2372caa81..00000000000
--- a/3rdparty/Sabre/VObject/Property/DateTime.php
+++ /dev/null
@@ -1,260 +0,0 @@
-<?php
-
-/**
- * DateTime property
- *
- * This element is used for iCalendar properties such as the DTSTART property.
- * It basically provides a few helper functions that make it easier to deal
- * with these. It supports both DATE-TIME and DATE values.
- *
- * In order to use this correctly, you must call setDateTime and getDateTime to
- * retrieve and modify dates respectively.
- *
- * If you use the 'value' or properties directly, this object does not keep
- * reference and results might appear incorrectly.
- *
- * @package Sabre
- * @subpackage VObject
- * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/)
- * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
- */
-class Sabre_VObject_Property_DateTime extends Sabre_VObject_Property {
-
- /**
- * Local 'floating' time
- */
- const LOCAL = 1;
-
- /**
- * UTC-based time
- */
- const UTC = 2;
-
- /**
- * Local time plus timezone
- */
- const LOCALTZ = 3;
-
- /**
- * Only a date, time is ignored
- */
- const DATE = 4;
-
- /**
- * DateTime representation
- *
- * @var DateTime
- */
- protected $dateTime;
-
- /**
- * dateType
- *
- * @var int
- */
- protected $dateType;
-
- /**
- * Updates the Date and Time.
- *
- * @param DateTime $dt
- * @param int $dateType
- * @return void
- */
- public function setDateTime(DateTime $dt, $dateType = self::LOCALTZ) {
-
- switch($dateType) {
-
- case self::LOCAL :
- $this->setValue($dt->format('Ymd\\THis'));
- $this->offsetUnset('VALUE');
- $this->offsetUnset('TZID');
- $this->offsetSet('VALUE','DATE-TIME');
- break;
- case self::UTC :
- $dt->setTimeZone(new DateTimeZone('UTC'));
- $this->setValue($dt->format('Ymd\\THis\\Z'));
- $this->offsetUnset('VALUE');
- $this->offsetUnset('TZID');
- $this->offsetSet('VALUE','DATE-TIME');
- break;
- case self::LOCALTZ :
- $this->setValue($dt->format('Ymd\\THis'));
- $this->offsetUnset('VALUE');
- $this->offsetUnset('TZID');
- $this->offsetSet('VALUE','DATE-TIME');
- $this->offsetSet('TZID', $dt->getTimeZone()->getName());
- break;
- case self::DATE :
- $this->setValue($dt->format('Ymd'));
- $this->offsetUnset('VALUE');
- $this->offsetUnset('TZID');
- $this->offsetSet('VALUE','DATE');
- break;
- default :
- throw new InvalidArgumentException('You must pass a valid dateType constant');
-
- }
- $this->dateTime = $dt;
- $this->dateType = $dateType;
-
- }
-
- /**
- * Returns the current DateTime value.
- *
- * If no value was set, this method returns null.
- *
- * @return DateTime|null
- */
- public function getDateTime() {
-
- if ($this->dateTime)
- return $this->dateTime;
-
- list(
- $this->dateType,
- $this->dateTime
- ) = self::parseData($this->value, $this);
- return $this->dateTime;
-
- }
-
- /**
- * Returns the type of Date format.
- *
- * This method returns one of the format constants. If no date was set,
- * this method will return null.
- *
- * @return int|null
- */
- public function getDateType() {
-
- if ($this->dateType)
- return $this->dateType;
-
- list(
- $this->dateType,
- $this->dateTime,
- ) = self::parseData($this->value, $this);
- return $this->dateType;
-
- }
-
- /**
- * Parses the internal data structure to figure out what the current date
- * and time is.
- *
- * The returned array contains two elements:
- * 1. A 'DateType' constant (as defined on this class), or null.
- * 2. A DateTime object (or null)
- *
- * @param string|null $propertyValue The string to parse (yymmdd or
- * ymmddThhmmss, etc..)
- * @param Sabre_VObject_Property|null $property The instance of the
- * property we're parsing.
- * @return array
- */
- static public function parseData($propertyValue, Sabre_VObject_Property $property = null) {
-
- if (is_null($propertyValue)) {
- return array(null, null);
- }
-
- $date = '(?P<year>[1-2][0-9]{3})(?P<month>[0-1][0-9])(?P<date>[0-3][0-9])';
- $time = '(?P<hour>[0-2][0-9])(?P<minute>[0-5][0-9])(?P<second>[0-5][0-9])';
- $regex = "/^$date(T$time(?P<isutc>Z)?)?$/";
-
- if (!preg_match($regex, $propertyValue, $matches)) {
- throw new InvalidArgumentException($propertyValue . ' is not a valid DateTime or Date string');
- }
-
- if (!isset($matches['hour'])) {
- // Date-only
- return array(
- self::DATE,
- new DateTime($matches['year'] . '-' . $matches['month'] . '-' . $matches['date'] . ' 00:00:00'),
- );
- }
-
- $dateStr =
- $matches['year'] .'-' .
- $matches['month'] . '-' .
- $matches['date'] . ' ' .
- $matches['hour'] . ':' .
- $matches['minute'] . ':' .
- $matches['second'];
-
- if (isset($matches['isutc'])) {
- $dt = new DateTime($dateStr,new DateTimeZone('UTC'));
- $dt->setTimeZone(new DateTimeZone('UTC'));
- return array(
- self::UTC,
- $dt
- );
- }
-
- // Finding the timezone.
- $tzid = $property['TZID'];
- if (!$tzid) {
- return array(
- self::LOCAL,
- new DateTime($dateStr)
- );
- }
-
- try {
- // tzid an Olson identifier?
- $tz = new DateTimeZone($tzid->value);
- } catch (Exception $e) {
-
- // Not an Olson id, we're going to try to find the information
- // through the time zone name map.
- $newtzid = Sabre_VObject_WindowsTimezoneMap::lookup($tzid->value);
- if (is_null($newtzid)) {
-
- // Not a well known time zone name either, we're going to try
- // to find the information through the VTIMEZONE object.
-
- // First we find the root object
- $root = $property;
- while($root->parent) {
- $root = $root->parent;
- }
-
- if (isset($root->VTIMEZONE)) {
- foreach($root->VTIMEZONE as $vtimezone) {
- if (((string)$vtimezone->TZID) == $tzid) {
- if (isset($vtimezone->{'X-LIC-LOCATION'})) {
- $newtzid = (string)$vtimezone->{'X-LIC-LOCATION'};
- } else {
- // No libical location specified. As a last resort we could
- // try matching $vtimezone's DST rules against all known
- // time zones returned by DateTimeZone::list*
-
- // TODO
- }
- }
- }
- }
- }
-
- try {
- $tz = new DateTimeZone($newtzid);
- } catch (Exception $e) {
- // If all else fails, we use the default PHP timezone
- $tz = new DateTimeZone(date_default_timezone_get());
- }
- }
- $dt = new DateTime($dateStr, $tz);
- $dt->setTimeZone($tz);
-
- return array(
- self::LOCALTZ,
- $dt
- );
-
- }
-
-}
diff --git a/3rdparty/Sabre/VObject/Property/MultiDateTime.php b/3rdparty/Sabre/VObject/Property/MultiDateTime.php
deleted file mode 100755
index ae53ab6a617..00000000000
--- a/3rdparty/Sabre/VObject/Property/MultiDateTime.php
+++ /dev/null
@@ -1,166 +0,0 @@
-<?php
-
-/**
- * Multi-DateTime property
- *
- * This element is used for iCalendar properties such as the EXDATE property.
- * It basically provides a few helper functions that make it easier to deal
- * with these. It supports both DATE-TIME and DATE values.
- *
- * In order to use this correctly, you must call setDateTimes and getDateTimes
- * to retrieve and modify dates respectively.
- *
- * If you use the 'value' or properties directly, this object does not keep
- * reference and results might appear incorrectly.
- *
- * @package Sabre
- * @subpackage VObject
- * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/)
- * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
- */
-class Sabre_VObject_Property_MultiDateTime extends Sabre_VObject_Property {
-
- /**
- * DateTime representation
- *
- * @var DateTime[]
- */
- protected $dateTimes;
-
- /**
- * dateType
- *
- * This is one of the Sabre_VObject_Property_DateTime constants.
- *
- * @var int
- */
- protected $dateType;
-
- /**
- * Updates the value
- *
- * @param array $dt Must be an array of DateTime objects.
- * @param int $dateType
- * @return void
- */
- public function setDateTimes(array $dt, $dateType = Sabre_VObject_Property_DateTime::LOCALTZ) {
-
- foreach($dt as $i)
- if (!$i instanceof DateTime)
- throw new InvalidArgumentException('You must pass an array of DateTime objects');
-
- $this->offsetUnset('VALUE');
- $this->offsetUnset('TZID');
- switch($dateType) {
-
- case Sabre_VObject_Property_DateTime::LOCAL :
- $val = array();
- foreach($dt as $i) {
- $val[] = $i->format('Ymd\\THis');
- }
- $this->setValue(implode(',',$val));
- $this->offsetSet('VALUE','DATE-TIME');
- break;
- case Sabre_VObject_Property_DateTime::UTC :
- $val = array();
- foreach($dt as $i) {
- $i->setTimeZone(new DateTimeZone('UTC'));
- $val[] = $i->format('Ymd\\THis\\Z');
- }
- $this->setValue(implode(',',$val));
- $this->offsetSet('VALUE','DATE-TIME');
- break;
- case Sabre_VObject_Property_DateTime::LOCALTZ :
- $val = array();
- foreach($dt as $i) {
- $val[] = $i->format('Ymd\\THis');
- }
- $this->setValue(implode(',',$val));
- $this->offsetSet('VALUE','DATE-TIME');
- $this->offsetSet('TZID', $dt[0]->getTimeZone()->getName());
- break;
- case Sabre_VObject_Property_DateTime::DATE :
- $val = array();
- foreach($dt as $i) {
- $val[] = $i->format('Ymd');
- }
- $this->setValue(implode(',',$val));
- $this->offsetSet('VALUE','DATE');
- break;
- default :
- throw new InvalidArgumentException('You must pass a valid dateType constant');
-
- }
- $this->dateTimes = $dt;
- $this->dateType = $dateType;
-
- }
-
- /**
- * Returns the current DateTime value.
- *
- * If no value was set, this method returns null.
- *
- * @return array|null
- */
- public function getDateTimes() {
-
- if ($this->dateTimes)
- return $this->dateTimes;
-
- $dts = array();
-
- if (!$this->value) {
- $this->dateTimes = null;
- $this->dateType = null;
- return null;
- }
-
- foreach(explode(',',$this->value) as $val) {
- list(
- $type,
- $dt
- ) = Sabre_VObject_Property_DateTime::parseData($val, $this);
- $dts[] = $dt;
- $this->dateType = $type;
- }
- $this->dateTimes = $dts;
- return $this->dateTimes;
-
- }
-
- /**
- * Returns the type of Date format.
- *
- * This method returns one of the format constants. If no date was set,
- * this method will return null.
- *
- * @return int|null
- */
- public function getDateType() {
-
- if ($this->dateType)
- return $this->dateType;
-
- if (!$this->value) {
- $this->dateTimes = null;
- $this->dateType = null;
- return null;
- }
-
- $dts = array();
- foreach(explode(',',$this->value) as $val) {
- list(
- $type,
- $dt
- ) = Sabre_VObject_Property_DateTime::parseData($val, $this);
- $dts[] = $dt;
- $this->dateType = $type;
- }
- $this->dateTimes = $dts;
- return $this->dateType;
-
- }
-
-}
diff --git a/3rdparty/Sabre/VObject/Reader.php b/3rdparty/Sabre/VObject/Reader.php
deleted file mode 100755
index eea73fa3dce..00000000000
--- a/3rdparty/Sabre/VObject/Reader.php
+++ /dev/null
@@ -1,183 +0,0 @@
-<?php
-
-/**
- * VCALENDAR/VCARD reader
- *
- * This class reads the vobject file, and returns a full element tree.
- *
- * TODO: this class currently completely works 'statically'. This is pointless,
- * and defeats OOP principals. Needs refactoring in a future version.
- *
- * @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_Reader {
-
- /**
- * Parses the file and returns the top component
- *
- * @param string $data
- * @return Sabre_VObject_Element
- */
- static function read($data) {
-
- // Normalizing newlines
- $data = str_replace(array("\r","\n\n"), array("\n","\n"), $data);
-
- $lines = explode("\n", $data);
-
- // Unfolding lines
- $lines2 = array();
- foreach($lines as $line) {
-
- // Skipping empty lines
- if (!$line) continue;
-
- if ($line[0]===" " || $line[0]==="\t") {
- $lines2[count($lines2)-1].=substr($line,1);
- } else {
- $lines2[] = $line;
- }
-
- }
-
- unset($lines);
-
- reset($lines2);
-
- return self::readLine($lines2);
-
- }
-
- /**
- * Reads and parses a single line.
- *
- * This method receives the full array of lines. The array pointer is used
- * to traverse.
- *
- * @param array $lines
- * @return Sabre_VObject_Element
- */
- static private function readLine(&$lines) {
-
- $line = current($lines);
- $lineNr = key($lines);
- next($lines);
-
- // Components
- if (stripos($line,"BEGIN:")===0) {
-
- $componentName = strtoupper(substr($line,6));
- $obj = Sabre_VObject_Component::create($componentName);
-
- $nextLine = current($lines);
-
- while(stripos($nextLine,"END:")!==0) {
-
- $obj->add(self::readLine($lines));
-
- $nextLine = current($lines);
-
- if ($nextLine===false)
- 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<name>[A-Z0-9-]+)(?:;(?P<parameters>^(?<!:):))(.*)$/',$line,$matches);
-
-
- $token = '[A-Z0-9-\.]+';
- $parameters = "(?:;(?P<parameters>([^:^\"]|\"([^\"]*)\")*))?";
- $regex = "/^(?P<name>$token)$parameters:(?P<value>.*)$/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<paramValue>[^\"^;]*|"[^"]*")';
-
- $regex = "/(?<=^|;)(?P<paramName>$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
deleted file mode 100755
index 740270dd8f0..00000000000
--- a/3rdparty/Sabre/VObject/RecurrenceIterator.php
+++ /dev/null
@@ -1,1043 +0,0 @@
-<?php
-
-/**
- * This class is used to determine new for a recurring event, when the next
- * events occur.
- *
- * This iterator may loop infinitely in the future, therefore it is important
- * that if you use this class, you set hard limits for the amount of iterations
- * you want to handle.
- *
- * Note that currently there is not full support for the entire iCalendar
- * specification, as it's very complex and contains a lot of permutations
- * that's not yet used very often in software.
- *
- * For the focus has been on features as they actually appear in Calendaring
- * software, but this may well get expanded as needed / on demand
- *
- * The following RRULE properties are supported
- * * UNTIL
- * * INTERVAL
- * * COUNT
- * * FREQ=DAILY
- * * BYDAY
- * * FREQ=WEEKLY
- * * BYDAY
- * * WKST
- * * FREQ=MONTHLY
- * * BYMONTHDAY
- * * BYDAY
- * * BYSETPOS
- * * FREQ=YEARLY
- * * BYMONTH
- * * BYMONTHDAY (only if BYMONTH is also set)
- * * BYDAY (only if BYMONTH is also set)
- *
- * Anything beyond this is 'undefined', which means that it may get ignored, or
- * you may get unexpected results. The effect is that in some applications the
- * specified recurrence may look incorrect, or is missing.
- *
- * @package Sabre
- * @subpackage VObject
- * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/)
- * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
- */
-class Sabre_VObject_RecurrenceIterator implements Iterator {
-
- /**
- * The initial event date
- *
- * @var DateTime
- */
- public $startDate;
-
- /**
- * The end-date of the initial event
- *
- * @var DateTime
- */
- public $endDate;
-
- /**
- * The 'current' recurrence.
- *
- * This will be increased for every iteration.
- *
- * @var DateTime
- */
- public $currentDate;
-
-
- /**
- * List of dates that are excluded from the rules.
- *
- * This list contains the items that have been overriden by the EXDATE
- * property.
- *
- * @var array
- */
- public $exceptionDates = array();
-
- /**
- * Base event
- *
- * @var Sabre_VObject_Component_VEvent
- */
- public $baseEvent;
-
- /**
- * List of dates that are overridden by other events.
- * Similar to $overriddenEvents, but this just contains the original dates.
- *
- * @var array
- */
- public $overriddenDates = array();
-
- /**
- * list of events that are 'overridden'.
- *
- * This is an array of Sabre_VObject_Component_VEvent objects.
- *
- * @var array
- */
- public $overriddenEvents = array();
-
-
- /**
- * Frequency is one of: secondly, minutely, hourly, daily, weekly, monthly,
- * yearly.
- *
- * @var string
- */
- public $frequency;
-
- /**
- * The last instance of this recurrence, inclusively
- *
- * @var DateTime|null
- */
- public $until;
-
- /**
- * The number of recurrences, or 'null' if infinitely recurring.
- *
- * @var int
- */
- public $count;
-
- /**
- * The interval.
- *
- * If for example frequency is set to daily, interval = 2 would mean every
- * 2 days.
- *
- * @var int
- */
- public $interval = 1;
-
- /**
- * Which seconds to recur.
- *
- * This is an array of integers (between 0 and 60)
- *
- * @var array
- */
- public $bySecond;
-
- /**
- * Which minutes to recur
- *
- * This is an array of integers (between 0 and 59)
- *
- * @var array
- */
- public $byMinute;
-
- /**
- * Which hours to recur
- *
- * This is an array of integers (between 0 and 23)
- *
- * @var array
- */
- public $byHour;
-
- /**
- * Which weekdays to recur.
- *
- * This is an array of weekdays
- *
- * This may also be preceeded by a positive or negative integer. If present,
- * this indicates the nth occurrence of a specific day within the monthly or
- * yearly rrule. For instance, -2TU indicates the second-last tuesday of
- * the month, or year.
- *
- * @var array
- */
- public $byDay;
-
- /**
- * Which days of the month to recur
- *
- * This is an array of days of the months (1-31). The value can also be
- * negative. -5 for instance means the 5th last day of the month.
- *
- * @var array
- */
- public $byMonthDay;
-
- /**
- * Which days of the year to recur.
- *
- * This is an array with days of the year (1 to 366). The values can also
- * be negative. For instance, -1 will always represent the last day of the
- * year. (December 31st).
- *
- * @var array
- */
- public $byYearDay;
-
- /**
- * Which week numbers to recur.
- *
- * This is an array of integers from 1 to 53. The values can also be
- * negative. -1 will always refer to the last week of the year.
- *
- * @var array
- */
- public $byWeekNo;
-
- /**
- * Which months to recur
- *
- * This is an array of integers from 1 to 12.
- *
- * @var array
- */
- public $byMonth;
-
- /**
- * Which items in an existing st to recur.
- *
- * These numbers work together with an existing by* rule. It specifies
- * exactly which items of the existing by-rule to filter.
- *
- * Valid values are 1 to 366 and -1 to -366. As an example, this can be
- * used to recur the last workday of the month.
- *
- * This would be done by setting frequency to 'monthly', byDay to
- * 'MO,TU,WE,TH,FR' and bySetPos to -1.
- *
- * @var array
- */
- public $bySetPos;
-
- /**
- * When a week starts
- *
- * @var string
- */
- public $weekStart = 'MO';
-
- /**
- * The current item in the list
- *
- * @var int
- */
- public $counter = 0;
-
- /**
- * Simple mapping from iCalendar day names to day numbers
- *
- * @var array
- */
- private $dayMap = array(
- 'SU' => 0,
- 'MO' => 1,
- 'TU' => 2,
- 'WE' => 3,
- 'TH' => 4,
- 'FR' => 5,
- 'SA' => 6,
- );
-
- /**
- * Mappings between the day number and english day name.
- *
- * @var array
- */
- private $dayNames = array(
- 0 => 'Sunday',
- 1 => 'Monday',
- 2 => 'Tuesday',
- 3 => 'Wednesday',
- 4 => 'Thursday',
- 5 => 'Friday',
- 6 => 'Saturday',
- );
-
- /**
- * If the current iteration of the event is an overriden event, this
- * property will hold the VObject
- *
- * @var Sabre_Component_VObject
- */
- private $currentOverriddenEvent;
-
- /**
- * This property may contain the date of the next not-overridden event.
- * This date is calculated sometimes a bit early, before overridden events
- * are evaluated.
- *
- * @var DateTime
- */
- private $nextDate;
-
- /**
- * Creates the iterator
- *
- * You should pass a VCALENDAR component, as well as the UID of the event
- * we're going to traverse.
- *
- * @param Sabre_VObject_Component $vcal
- * @param string|null $uid
- */
- public function __construct(Sabre_VObject_Component $vcal, $uid=null) {
-
- if (is_null($uid)) {
- if ($vcal->name === 'VCALENDAR') {
- throw new InvalidArgumentException('If you pass a VCALENDAR object, you must pass a uid argument as well');
- }
- $components = array($vcal);
- $uid = (string)$vcal->uid;
- } else {
- $components = $vcal->select('VEVENT');
- }
- foreach($components as $component) {
- if ((string)$component->uid == $uid) {
- if (isset($component->{'RECURRENCE-ID'})) {
- $this->overriddenEvents[$component->DTSTART->getDateTime()->getTimeStamp()] = $component;
- $this->overriddenDates[] = $component->{'RECURRENCE-ID'}->getDateTime();
- } else {
- $this->baseEvent = $component;
- }
- }
- }
- if (!$this->baseEvent) {
- throw new InvalidArgumentException('Could not find a base event with uid: ' . $uid);
- }
-
- $this->startDate = clone $this->baseEvent->DTSTART->getDateTime();
-
- $this->endDate = null;
- if (isset($this->baseEvent->DTEND)) {
- $this->endDate = clone $this->baseEvent->DTEND->getDateTime();
- } else {
- $this->endDate = clone $this->startDate;
- if (isset($this->baseEvent->DURATION)) {
- $this->endDate->add(Sabre_VObject_DateTimeParser::parse($this->baseEvent->DURATION->value));
- } 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
deleted file mode 100755
index 9ee03d87118..00000000000
--- a/3rdparty/Sabre/VObject/Version.php
+++ /dev/null
@@ -1,24 +0,0 @@
-<?php
-
-/**
- * This class contains the version number for the VObject package
- *
- * @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_Version {
-
- /**
- * Full version number
- */
- const VERSION = '1.3.4';
-
- /**
- * Stability : alpha, beta, stable
- */
- const STABILITY = 'stable';
-
-}
diff --git a/3rdparty/Sabre/VObject/WindowsTimezoneMap.php b/3rdparty/Sabre/VObject/WindowsTimezoneMap.php
deleted file mode 100755
index 5e1cc5d479b..00000000000
--- a/3rdparty/Sabre/VObject/WindowsTimezoneMap.php
+++ /dev/null
@@ -1,128 +0,0 @@
-<?php
-
-/**
- * Time zone name translation
- *
- * This file translates well-known time zone names into "Olson database" time zone names.
- *
- * @package Sabre
- * @subpackage VObject
- * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
- * @author Frank Edelhaeuser (fedel@users.sourceforge.net)
- * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
- */
-class Sabre_VObject_WindowsTimezoneMap {
-
- protected static $map = array(
-
- // from http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/zone_tzid.html
- // snapshot taken on 2012/01/16
-
- // windows
- 'AUS Central Standard Time'=>'Australia/Darwin',
- 'AUS Eastern Standard Time'=>'Australia/Sydney',
- 'Afghanistan Standard Time'=>'Asia/Kabul',
- 'Alaskan Standard Time'=>'America/Anchorage',
- 'Arab Standard Time'=>'Asia/Riyadh',
- 'Arabian Standard Time'=>'Asia/Dubai',
- 'Arabic Standard Time'=>'Asia/Baghdad',
- 'Argentina Standard Time'=>'America/Buenos_Aires',
- 'Armenian Standard Time'=>'Asia/Yerevan',
- 'Atlantic Standard Time'=>'America/Halifax',
- 'Azerbaijan Standard Time'=>'Asia/Baku',
- 'Azores Standard Time'=>'Atlantic/Azores',
- 'Bangladesh Standard Time'=>'Asia/Dhaka',
- 'Canada Central Standard Time'=>'America/Regina',
- 'Cape Verde Standard Time'=>'Atlantic/Cape_Verde',
- 'Caucasus Standard Time'=>'Asia/Yerevan',
- 'Cen. Australia Standard Time'=>'Australia/Adelaide',
- 'Central America Standard Time'=>'America/Guatemala',
- 'Central Asia Standard Time'=>'Asia/Almaty',
- 'Central Brazilian Standard Time'=>'America/Cuiaba',
- 'Central Europe Standard Time'=>'Europe/Budapest',
- 'Central European Standard Time'=>'Europe/Warsaw',
- 'Central Pacific Standard Time'=>'Pacific/Guadalcanal',
- 'Central Standard Time'=>'America/Chicago',
- 'Central Standard Time (Mexico)'=>'America/Mexico_City',
- 'China Standard Time'=>'Asia/Shanghai',
- 'Dateline Standard Time'=>'Etc/GMT+12',
- 'E. Africa Standard Time'=>'Africa/Nairobi',
- 'E. Australia Standard Time'=>'Australia/Brisbane',
- 'E. Europe Standard Time'=>'Europe/Minsk',
- 'E. South America Standard Time'=>'America/Sao_Paulo',
- 'Eastern Standard Time'=>'America/New_York',
- 'Egypt Standard Time'=>'Africa/Cairo',
- 'Ekaterinburg Standard Time'=>'Asia/Yekaterinburg',
- 'FLE Standard Time'=>'Europe/Kiev',
- 'Fiji Standard Time'=>'Pacific/Fiji',
- 'GMT Standard Time'=>'Europe/London',
- 'GTB Standard Time'=>'Europe/Istanbul',
- 'Georgian Standard Time'=>'Asia/Tbilisi',
- 'Greenland Standard Time'=>'America/Godthab',
- 'Greenwich Standard Time'=>'Atlantic/Reykjavik',
- 'Hawaiian Standard Time'=>'Pacific/Honolulu',
- 'India Standard Time'=>'Asia/Calcutta',
- 'Iran Standard Time'=>'Asia/Tehran',
- 'Israel Standard Time'=>'Asia/Jerusalem',
- 'Jordan Standard Time'=>'Asia/Amman',
- 'Kamchatka Standard Time'=>'Asia/Kamchatka',
- 'Korea Standard Time'=>'Asia/Seoul',
- 'Magadan Standard Time'=>'Asia/Magadan',
- 'Mauritius Standard Time'=>'Indian/Mauritius',
- 'Mexico Standard Time'=>'America/Mexico_City',
- 'Mexico Standard Time 2'=>'America/Chihuahua',
- 'Mid-Atlantic Standard Time'=>'Etc/GMT+2',
- 'Middle East Standard Time'=>'Asia/Beirut',
- 'Montevideo Standard Time'=>'America/Montevideo',
- 'Morocco Standard Time'=>'Africa/Casablanca',
- 'Mountain Standard Time'=>'America/Denver',
- 'Mountain Standard Time (Mexico)'=>'America/Chihuahua',
- 'Myanmar Standard Time'=>'Asia/Rangoon',
- 'N. Central Asia Standard Time'=>'Asia/Novosibirsk',
- 'Namibia Standard Time'=>'Africa/Windhoek',
- 'Nepal Standard Time'=>'Asia/Katmandu',
- 'New Zealand Standard Time'=>'Pacific/Auckland',
- 'Newfoundland Standard Time'=>'America/St_Johns',
- 'North Asia East Standard Time'=>'Asia/Irkutsk',
- 'North Asia Standard Time'=>'Asia/Krasnoyarsk',
- 'Pacific SA Standard Time'=>'America/Santiago',
- 'Pacific Standard Time'=>'America/Los_Angeles',
- 'Pacific Standard Time (Mexico)'=>'America/Santa_Isabel',
- 'Pakistan Standard Time'=>'Asia/Karachi',
- 'Paraguay Standard Time'=>'America/Asuncion',
- 'Romance Standard Time'=>'Europe/Paris',
- 'Russian Standard Time'=>'Europe/Moscow',
- 'SA Eastern Standard Time'=>'America/Cayenne',
- 'SA Pacific Standard Time'=>'America/Bogota',
- 'SA Western Standard Time'=>'America/La_Paz',
- 'SE Asia Standard Time'=>'Asia/Bangkok',
- 'Samoa Standard Time'=>'Pacific/Apia',
- 'Singapore Standard Time'=>'Asia/Singapore',
- 'South Africa Standard Time'=>'Africa/Johannesburg',
- 'Sri Lanka Standard Time'=>'Asia/Colombo',
- 'Syria Standard Time'=>'Asia/Damascus',
- 'Taipei Standard Time'=>'Asia/Taipei',
- 'Tasmania Standard Time'=>'Australia/Hobart',
- 'Tokyo Standard Time'=>'Asia/Tokyo',
- 'Tonga Standard Time'=>'Pacific/Tongatapu',
- 'US Eastern Standard Time'=>'America/Indianapolis',
- 'US Mountain Standard Time'=>'America/Phoenix',
- 'UTC'=>'Etc/GMT',
- 'UTC+12'=>'Etc/GMT-12',
- 'UTC-02'=>'Etc/GMT+2',
- 'UTC-11'=>'Etc/GMT+11',
- 'Ulaanbaatar Standard Time'=>'Asia/Ulaanbaatar',
- 'Venezuela Standard Time'=>'America/Caracas',
- 'Vladivostok Standard Time'=>'Asia/Vladivostok',
- 'W. Australia Standard Time'=>'Australia/Perth',
- 'W. Central Africa Standard Time'=>'Africa/Lagos',
- 'W. Europe Standard Time'=>'Europe/Berlin',
- 'West Asia Standard Time'=>'Asia/Tashkent',
- 'West Pacific Standard Time'=>'Pacific/Port_Moresby',
- 'Yakutsk Standard Time'=>'Asia/Yakutsk',
- );
-
- static public function lookup($tzid) {
- return isset(self::$map[$tzid]) ? self::$map[$tzid] : null;
- }
-}
diff --git a/3rdparty/Sabre/VObject/includes.php b/3rdparty/Sabre/VObject/includes.php
deleted file mode 100755
index 0177a8f1ba6..00000000000
--- a/3rdparty/Sabre/VObject/includes.php
+++ /dev/null
@@ -1,41 +0,0 @@
-<?php
-
-/**
- * Sabre_VObject includes file
- *
- * Including this file will automatically include all files from the VObject
- * package.
- *
- * This often allows faster loadtimes, as autoload-speed is often quite slow.
- *
- * @package Sabre
- * @subpackage VObject
- * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/)
- * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
- */
-
-// Begin includes
-include __DIR__ . '/DateTimeParser.php';
-include __DIR__ . '/ElementList.php';
-include __DIR__ . '/FreeBusyGenerator.php';
-include __DIR__ . '/Node.php';
-include __DIR__ . '/Parameter.php';
-include __DIR__ . '/ParseException.php';
-include __DIR__ . '/Reader.php';
-include __DIR__ . '/RecurrenceIterator.php';
-include __DIR__ . '/Version.php';
-include __DIR__ . '/WindowsTimezoneMap.php';
-include __DIR__ . '/Element.php';
-include __DIR__ . '/Property.php';
-include __DIR__ . '/Component.php';
-include __DIR__ . '/Property/DateTime.php';
-include __DIR__ . '/Property/MultiDateTime.php';
-include __DIR__ . '/Component/VAlarm.php';
-include __DIR__ . '/Component/VCalendar.php';
-include __DIR__ . '/Component/VEvent.php';
-include __DIR__ . '/Component/VJournal.php';
-include __DIR__ . '/Component/VTodo.php';
-include __DIR__ . '/Element/DateTime.php';
-include __DIR__ . '/Element/MultiDateTime.php';
-// End includes
diff --git a/3rdparty/Sabre/autoload.php b/3rdparty/Sabre/autoload.php
index c7b537d83d3..505bd36efb0 100755
--- a/3rdparty/Sabre/autoload.php
+++ b/3rdparty/Sabre/autoload.php
@@ -1,31 +1,27 @@
<?php
/**
- * SabreDAV's PHP autoloader
+ * SabreDAV's autoloader
*
- * If you love the autoloader, and don't care as much about performance, this
- * file register a new autoload function using spl_autoload_register.
+ * This file is kept for backwards compatibility purposes.
+ * SabreDAV now uses the composer autoloader.
+ *
+ * You should stop including this file, and include 'vendor/autoload.php'
+ * instead.
*
* @package Sabre
* @subpackage DAV
+ * @deprecated Will be removed in a future version!
* @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
/**
- * @param string $className
- * @return void
+ * We are assuming that the composer autoloader is just 2 directories up.
+ *
+ * This is not the case when sabredav is installed as a dependency. But, in
+ * those cases it's not expected that people will look for this file anyway.
*/
-function Sabre_autoload($className) {
-
- if(strpos($className,'Sabre_')===0) {
-
- include dirname(__FILE__) . '/' . str_replace('_','/',substr($className,6)) . '.php';
-
- }
-
-}
-
-spl_autoload_register('Sabre_autoload');
+require __DIR__ . '/../../vendor/autoload.php';