summaryrefslogtreecommitdiff
path: root/lib/Kolab/CalDAV
diff options
context:
space:
mode:
authorThomas Bruederli <bruederli@kolabsys.com>2013-02-21 15:50:05 (GMT)
committerThomas Bruederli <bruederli@kolabsys.com>2013-02-21 15:50:05 (GMT)
commit0c2cc0b881759de6b1728329ed37c8c846381e73 (patch)
treec2680ec28f02cd266b63e7ce46f675e15857de99 /lib/Kolab/CalDAV
parent92151db6cc3cd013080f5f49ca7140f07cadfb35 (diff)
downloadiRony-0c2cc0b881759de6b1728329ed37c8c846381e73.tar.gz
Add our own implementation of the CalDAV plugin to override validation functions
Diffstat (limited to 'lib/Kolab/CalDAV')
-rw-r--r--lib/Kolab/CalDAV/Plugin.php111
1 files changed, 111 insertions, 0 deletions
diff --git a/lib/Kolab/CalDAV/Plugin.php b/lib/Kolab/CalDAV/Plugin.php
new file mode 100644
index 0000000..bc6befb
--- /dev/null
+++ b/lib/Kolab/CalDAV/Plugin.php
@@ -0,0 +1,111 @@
+<?php
+
+/**
+ * Extended CalDAV plugin for the Kolab DAV server
+ *
+ * @author Thomas Bruederli <bruederli@kolabsys.com>
+ *
+ * Copyright (C) 2013, Kolab Systems AG <contact@kolabsys.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace Kolab\CalDAV;
+
+use Sabre\DAV;
+use Sabre\CalDAV;
+use Sabre\VObject;
+
+
+/**
+ * Extended CalDAV plugin to tweak data validation
+ */
+class Plugin extends CalDAV\Plugin
+{
+ /**
+ * Checks if the submitted iCalendar data is in fact, valid.
+ *
+ * An exception is thrown if it's not.
+ *
+ * @param resource|string $data
+ * @param string $path
+ * @return void
+ */
+ protected function validateICalendar(&$data, $path)
+ {
+ // If it's a stream, we convert it to a string first.
+ if (is_resource($data)) {
+ $data = stream_get_contents($data);
+ }
+
+ // Converting the data to unicode, if needed.
+ $data = DAV\StringUtil::ensureUTF8($data);
+
+ try {
+ // modification: Set options to be more tolerant when parsing extended or invalid properties
+ $vobj = VObject\Reader::read($data, VObject\Reader::OPTION_FORGIVING | VObject\Reader::OPTION_IGNORE_INVALID_LINES);
+ // TODO: keep the parsed object in memory for later processing
+ }
+ catch (VObject\ParseException $e) {
+ throw new DAV\Exception\UnsupportedMediaType('This resource requires valid iCalendar 2.0 data. Parse error: ' . $e->getMessage());
+ }
+
+ if ($vobj->name !== 'VCALENDAR') {
+ throw new DAV\Exception\UnsupportedMediaType('This collection can only support iCalendar objects.');
+ }
+
+ // Get the Supported Components for the target calendar
+ list($parentPath,$object) = 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) {
+ switch($component->name) {
+ case 'VTIMEZONE':
+ continue 2;
+
+ case 'VEVENT':
+ case 'VTODO':
+ case 'VJOURNAL':
+ if (is_null($foundType)) {
+ $foundType = $component->name;
+ if (!in_array($foundType, $supportedComponents)) {
+ throw new CalDAV\Exception\InvalidComponentType('This calendar only supports ' . implode(', ', $supportedComponents) . '. We found a ' . $foundType);
+ }
+ if (!isset($component->UID)) {
+ throw new DAV\Exception\BadRequest('Every ' . $component->name . ' component must have an UID');
+ }
+ $foundUID = (string)$component->UID;
+ } else {
+ if ($foundType !== $component->name) {
+ throw new DAV\Exception\BadRequest('A calendar object must only contain 1 component. We found a ' . $component->name . ' as well as a ' . $foundType);
+ }
+ if ($foundUID !== (string)$component->UID) {
+ throw new DAV\Exception\BadRequest('Every ' . $component->name . ' in this object must have identical UIDs');
+ }
+ }
+ break;
+
+ default:
+ throw new DAV\Exception\BadRequest('You are not allowed to create components of type: ' . $component->name . ' here');
+
+ }
+ }
+ if (!$foundType)
+ throw new DAV\Exception\BadRequest('iCalendar object must contain at least 1 of VEVENT, VTODO or VJOURNAL');
+ }
+
+} \ No newline at end of file