summaryrefslogtreecommitdiffstats
path: root/apps/calendar/lib/sabre
diff options
context:
space:
mode:
Diffstat (limited to 'apps/calendar/lib/sabre')
-rw-r--r--apps/calendar/lib/sabre/backend.php318
-rw-r--r--apps/calendar/lib/sabre/calendar.php127
-rw-r--r--apps/calendar/lib/sabre/calendarroot.php45
-rw-r--r--apps/calendar/lib/sabre/object.php87
-rw-r--r--apps/calendar/lib/sabre/usercalendars.php46
5 files changed, 623 insertions, 0 deletions
diff --git a/apps/calendar/lib/sabre/backend.php b/apps/calendar/lib/sabre/backend.php
new file mode 100644
index 00000000000..ac3b26ceb33
--- /dev/null
+++ b/apps/calendar/lib/sabre/backend.php
@@ -0,0 +1,318 @@
+<?php
+
+class OC_Connector_Sabre_CalDAV extends Sabre_CalDAV_Backend_Abstract {
+ /**
+ * List of CalDAV properties, and how they map to database fieldnames
+ *
+ * Add your own properties by simply adding on to this array
+ *
+ * @var array
+ */
+ public $propertyMap = array(
+ '{DAV:}displayname' => 'displayname',
+ '{urn:ietf:params:xml:ns:caldav}calendar-timezone' => 'timezone',
+ '{http://apple.com/ns/ical/}calendar-order' => 'calendarorder',
+ '{http://apple.com/ns/ical/}calendar-color' => 'calendarcolor',
+ );
+
+ /**
+ * 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) {
+ $raw = OC_Calendar_Calendar::allCalendarsWherePrincipalURIIs($principalUri);
+
+ $calendars = array();
+ foreach( $raw as $row ){
+ $components = explode(',',$row['components']);
+
+ $calendar = array(
+ 'id' => $row['id'],
+ 'uri' => $row['uri'],
+ 'principaluri' => 'principals/'.$row['userid'],
+ '{' . Sabre_CalDAV_Plugin::NS_CALENDARSERVER . '}getctag' => $row['ctag']?$row['ctag']:'0',
+ '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}supported-calendar-component-set' => new Sabre_CalDAV_Property_SupportedCalendarComponentSet($components),
+ );
+
+ foreach($this->propertyMap as $xmlName=>$dbName) {
+ $calendar[$xmlName] = $row[$dbName];
+ }
+
+ $calendars[] = $calendar;
+ }
+ return $calendars;
+ }
+
+ /**
+ * 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 mixed
+ */
+ public function createCalendar($principalUri,$calendarUri, array $properties) {
+ $fieldNames = array(
+ 'principaluri',
+ 'uri',
+ 'ctag',
+ );
+ $values = array(
+ ':principaluri' => $principalUri,
+ ':uri' => $calendarUri,
+ ':ctag' => 1,
+ );
+
+ // Default value
+ $sccs = '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set';
+ $fieldNames[] = 'components';
+ if (!isset($properties[$sccs])) {
+ $values[':components'] = 'VEVENT,VTODO';
+ } else {
+ if (!($properties[$sccs] instanceof Sabre_CalDAV_Property_SupportedCalendarComponentSet)) {
+ throw new Sabre_DAV_Exception('The ' . $sccs . ' property must be of type: Sabre_CalDAV_Property_SupportedCalendarComponentSet');
+ }
+ $values[':components'] = implode(',',$properties[$sccs]->getValue());
+ }
+
+ foreach($this->propertyMap as $xmlName=>$dbName) {
+ if (isset($properties[$xmlName])) {
+
+ $myValue = $properties[$xmlName];
+ $values[':' . $dbName] = $properties[$xmlName];
+ $fieldNames[] = $dbName;
+ }
+ }
+
+ if(!isset($newValues['displayname'])) $newValues['displayname'] = 'unnamed';
+ if(!isset($newValues['components'])) $newValues['components'] = 'VEVENT,VTODO';
+ if(!isset($newValues['timezone'])) $newValues['timezone'] = null;
+ if(!isset($newValues['calendarorder'])) $newValues['calendarorder'] = 0;
+ if(!isset($newValues['calendarcolor'])) $newValues['calendarcolor'] = null;
+ if(!is_null($newValues['calendarcolor']) && strlen($newValues['calendarcolor']) == 9){
+ $newValues['calendarcolor'] = substr($newValues['calendarcolor'], 0, 7);
+ }
+
+ return OC_Calendar_Calendar::addCalendarFromDAVData($principalUri,$calendarUri,$newValues['displayname'],$newValues['components'],$newValues['timezone'],$newValues['calendarorder'],$newValues['calendarcolor']);
+ }
+
+ /**
+ * Updates a calendars properties
+ *
+ * The properties 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-existant property is always succesful.
+ *
+ * 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 string $calendarId
+ * @param array $properties
+ * @return bool|array
+ */
+ public function updateCalendar($calendarId, array $properties) {
+
+ $newValues = array();
+ $result = array(
+ 200 => array(), // Ok
+ 403 => array(), // Forbidden
+ 424 => array(), // Failed Dependency
+ );
+
+ $hasError = false;
+
+ foreach($properties as $propertyName=>$propertyValue) {
+
+ // We don't know about this property.
+ if (!isset($this->propertyMap[$propertyName])) {
+ $hasError = true;
+ $result[403][$propertyName] = null;
+ unset($properties[$propertyName]);
+ continue;
+ }
+
+ $fieldName = $this->propertyMap[$propertyName];
+ $newValues[$fieldName] = $propertyValue;
+
+ }
+
+ // If there were any errors we need to fail the request
+ if ($hasError) {
+ // Properties has the remaining properties
+ foreach($properties as $propertyName=>$propertyValue) {
+ $result[424][$propertyName] = null;
+ }
+
+ // Removing unused statuscodes for cleanliness
+ foreach($result as $status=>$properties) {
+ if (is_array($properties) && count($properties)===0) unset($result[$status]);
+ }
+
+ return $result;
+
+ }
+
+ // Success
+ if(!isset($newValues['displayname'])) $newValues['displayname'] = null;
+ if(!isset($newValues['timezone'])) $newValues['timezone'] = null;
+ if(!isset($newValues['calendarorder'])) $newValues['calendarorder'] = null;
+ if(!isset($newValues['calendarcolor'])) $newValues['calendarcolor'] = null;
+ if(!is_null($newValues['calendarcolor']) && strlen($newValues['calendarcolor']) == 9){
+ $newValues['calendarcolor'] = substr($newValues['calendarcolor'], 0, 7);
+ }
+
+ OC_Calendar_Calendar::editCalendar($calendarId,$newValues['displayname'],null,$newValues['timezone'],$newValues['calendarorder'],$newValues['calendarcolor']);
+
+ return true;
+
+ }
+
+ /**
+ * Delete a calendar and all it's objects
+ *
+ * @param string $calendarId
+ * @return void
+ */
+ public function deleteCalendar($calendarId) {
+ if(preg_match( '=iCal/[1-4]?.*Mac OS X/10.[1-6](.[0-9])?=', $_SERVER['HTTP_USER_AGENT'] )){
+ throw new Sabre_DAV_Exception_Forbidden("Action is not possible with OSX 10.6.x", 403);
+ }
+
+ OC_Calendar_Calendar::deleteCalendar($calendarId);
+ }
+
+ /**
+ * Returns all calendar objects within a calendar object.
+ *
+ * Every item contains an array with the following keys:
+ * * id - unique identifier which will be used for subsequent updates
+ * * calendardata - The iCalendar-compatible calnedar data
+ * * uri - a unique key which will be used to construct the uri. This can be any arbitrary string.
+ * * lastmodified - a timestamp of the last modification time
+ * * etag - An arbitrary string, surrounded by double-quotes. (e.g.:
+ * ' "abcdef"')
+ * * calendarid - The calendarid as it was passed to this function.
+ *
+ * Note that the etag is optional, but it's highly encouraged to return for
+ * speed reasons.
+ *
+ * The calendardata is also optional. If it's not returned
+ * 'getCalendarObject' will be called later, which *is* expected to return
+ * calendardata.
+ *
+ * @param string $calendarId
+ * @return array
+ */
+ public function getCalendarObjects($calendarId) {
+ $data = array();
+ foreach(OC_Calendar_Object::all($calendarId) as $row){
+ $data[] = $this->OCAddETag($row);
+ }
+ return $data;
+ }
+
+ /**
+ * Returns information from a single calendar object, based on it's object
+ * uri.
+ *
+ * The returned array must have the same keys as getCalendarObjects. The
+ * 'calendardata' object is required here though, while it's not required
+ * for getCalendarObjects.
+ *
+ * @param string $calendarId
+ * @param string $objectUri
+ * @return array
+ */
+ public function getCalendarObject($calendarId,$objectUri) {
+ $data = OC_Calendar_Object::findWhereDAVDataIs($calendarId,$objectUri);
+ if(is_array($data)){
+ $data = $this->OCAddETag($data);
+ }
+ return $data;
+ }
+
+ /**
+ * Creates a new calendar object.
+ *
+ * @param string $calendarId
+ * @param string $objectUri
+ * @param string $calendarData
+ * @return void
+ */
+ public function createCalendarObject($calendarId,$objectUri,$calendarData) {
+ OC_Calendar_Object::addFromDAVData($calendarId,$objectUri,$calendarData);
+ }
+
+ /**
+ * Updates an existing calendarobject, based on it's uri.
+ *
+ * @param string $calendarId
+ * @param string $objectUri
+ * @param string $calendarData
+ * @return void
+ */
+ public function updateCalendarObject($calendarId,$objectUri,$calendarData){
+ OC_Calendar_Object::editFromDAVData($calendarId,$objectUri,$calendarData);
+ }
+
+ /**
+ * Deletes an existing calendar object.
+ *
+ * @param string $calendarId
+ * @param string $objectUri
+ * @return void
+ */
+ public function deleteCalendarObject($calendarId,$objectUri){
+ OC_Calendar_Object::deleteFromDAVData($calendarId,$objectUri);
+ }
+
+ /**
+ * @brief Creates a etag
+ * @param array $row Database result
+ * @returns associative array
+ *
+ * Adds a key "etag" to the row
+ */
+ private function OCAddETag($row){
+ $row['etag'] = '"'.md5($row['calendarid'].$row['uri'].$row['calendardata'].$row['lastmodified']).'"';
+ return $row;
+ }
+}
diff --git a/apps/calendar/lib/sabre/calendar.php b/apps/calendar/lib/sabre/calendar.php
new file mode 100644
index 00000000000..179be1b2813
--- /dev/null
+++ b/apps/calendar/lib/sabre/calendar.php
@@ -0,0 +1,127 @@
+<?php
+/**
+ * ownCloud - OC_Connector_Sabre_Sabre_CalDAV_Calendar
+ *
+ * @author Thomas Tanghus
+ * @copyright 2012 Thomas Tanghus (thomas@tanghus.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * This class overrides Sabre_CalDAV_Calendar::getACL() to return read/write
+ * permissions based on user and shared state and it overrides
+ * Sabre_CalDAV_Calendar::getChild() and Sabre_CalDAV_Calendar::getChildren()
+ * to instantiate OC_Connector_Sabre_CalDAV_CalendarObjects.
+*/
+class OC_Connector_Sabre_CalDAV_Calendar extends Sabre_CalDAV_Calendar {
+
+ /**
+ * 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() {
+
+ $readprincipal = $this->getOwner();
+ $writeprincipal = $this->getOwner();
+ $uid = OC_Calendar_Calendar::extractUserID($this->getOwner());
+
+ if($uid != OCP\USER::getUser()) {
+ $sharedCalendar = OCP\Share::getItemSharedWithBySource('calendar', $this->$calendarInfo['id']);
+ if ($sharedCalendar && ($sharedCalendar['permissions'] & OCP\Share::PERMISSION_READ)) {
+ $readprincipal = 'principals/' . OCP\USER::getUser();
+ }
+ if ($sharedCalendar && ($sharedCalendar['permissions'] & OCP\Share::PERMISSION_UPDATE)) {
+ $writeprincipal = 'principals/' . OCP\USER::getUser();
+ }
+ }
+
+ return array(
+ array(
+ 'privilege' => '{DAV:}read',
+ 'principal' => $readprincipal,
+ 'protected' => true,
+ ),
+ array(
+ 'privilege' => '{DAV:}write',
+ 'principal' => $writeprincipal,
+ 'protected' => true,
+ ),
+ array(
+ 'privilege' => '{DAV:}read',
+ 'principal' => $readprincipal . '/calendar-proxy-write',
+ 'protected' => true,
+ ),
+ array(
+ 'privilege' => '{DAV:}write',
+ 'principal' => $writeprincipal . '/calendar-proxy-write',
+ 'protected' => true,
+ ),
+ array(
+ 'privilege' => '{DAV:}read',
+ 'principal' => $readprincipal . '/calendar-proxy-read',
+ 'protected' => true,
+ ),
+ array(
+ 'privilege' => '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}read-free-busy',
+ 'principal' => '{DAV:}authenticated',
+ 'protected' => true,
+ ),
+
+ );
+
+ }
+
+ /**
+ * Returns a calendar object
+ *
+ * The contained calendar objects are for example Events or Todo's.
+ *
+ * @param string $name
+ * @return Sabre_DAV_ICalendarObject
+ */
+ public function getChild($name) {
+
+ $obj = $this->caldavBackend->getCalendarObject($this->calendarInfo['id'],$name);
+ if (!$obj) throw new Sabre_DAV_Exception_NotFound('Calendar object not found');
+ return new OC_Connector_Sabre_CalDAV_CalendarObject($this->caldavBackend,$this->calendarInfo,$obj);
+
+ }
+
+ /**
+ * Returns the full list of calendar objects
+ *
+ * @return array
+ */
+ public function getChildren() {
+
+ $objs = $this->caldavBackend->getCalendarObjects($this->calendarInfo['id']);
+ $children = array();
+ foreach($objs as $obj) {
+ $children[] = new OC_Connector_Sabre_CalDAV_CalendarObject($this->caldavBackend,$this->calendarInfo,$obj);
+ }
+ return $children;
+
+ }
+
+} \ No newline at end of file
diff --git a/apps/calendar/lib/sabre/calendarroot.php b/apps/calendar/lib/sabre/calendarroot.php
new file mode 100644
index 00000000000..e09731c95b7
--- /dev/null
+++ b/apps/calendar/lib/sabre/calendarroot.php
@@ -0,0 +1,45 @@
+<?php
+/**
+ * ownCloud - OC_Connector_Sabre_CalDAV_CalendarRoot
+ *
+ * @author Thomas Tanghus
+ * @copyright 2012 Thomas Tanghus (thomas@tanghus.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * This class overrides Sabre_CalDAV_CalendarRootNode::getChildForPrincipal()
+ * to instantiate OC_Connector_Sabre_CalDAV_UserCalendars.
+*/
+class OC_Connector_Sabre_CalDAV_CalendarRoot extends Sabre_CalDAV_CalendarRootNode {
+
+ /**
+ * This method returns a node for a principal.
+ *
+ * The passed array contains principal information, and is guaranteed to
+ * at least contain a uri item. Other properties may or may not be
+ * supplied by the authentication backend.
+ *
+ * @param array $principal
+ * @return Sabre_DAV_INode
+ */
+ public function getChildForPrincipal(array $principal) {
+
+ return new OC_Connector_Sabre_CalDAV_UserCalendars($this->principalBackend, $this->caldavBackend, $principal['uri']);
+
+ }
+
+} \ No newline at end of file
diff --git a/apps/calendar/lib/sabre/object.php b/apps/calendar/lib/sabre/object.php
new file mode 100644
index 00000000000..25954e6ee55
--- /dev/null
+++ b/apps/calendar/lib/sabre/object.php
@@ -0,0 +1,87 @@
+<?php
+/**
+ * ownCloud - OC_Connector_Sabre_CalDAV_CalendarObject
+ *
+ * @author Thomas Tanghus
+ * @copyright 2012 Thomas Tanghus (thomas@tanghus.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * This class overrides Sabre_CalDAV_CalendarObject::getACL()
+ * to return read/write permissions based on user and shared state.
+*/
+class OC_Connector_Sabre_CalDAV_CalendarObject extends Sabre_CalDAV_CalendarObject {
+
+ /**
+ * 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() {
+
+ $readprincipal = $this->getOwner();
+ $writeprincipal = $this->getOwner();
+ $uid = OC_Calendar_Calendar::extractUserID($this->getOwner());
+
+ if($uid != OCP\USER::getUser()) {
+ $sharedAddressbook = OCP\Share::getItemSharedWithBySource('calendar', $this->$calendarInfo['id']);
+ if ($sharedAddressbook && ($sharedAddressbook['permissions'] & OCP\Share::PERMISSION_READ)) {
+ $readprincipal = 'principals/' . OCP\USER::getUser();
+ }
+ if ($sharedAddressbook && ($sharedAddressbook['permissions'] & OCP\Share::PERMISSION_UPDATE)) {
+ $writeprincipal = 'principals/' . OCP\USER::getUser();
+ }
+ }
+
+ return array(
+ array(
+ 'privilege' => '{DAV:}read',
+ 'principal' => $readprincipal,
+ 'protected' => true,
+ ),
+ array(
+ 'privilege' => '{DAV:}write',
+ 'principal' => $writeprincipal,
+ 'protected' => true,
+ ),
+ array(
+ 'privilege' => '{DAV:}read',
+ 'principal' => $readprincipal . '/calendar-proxy-write',
+ 'protected' => true,
+ ),
+ array(
+ 'privilege' => '{DAV:}write',
+ 'principal' => $writeprincipal . '/calendar-proxy-write',
+ 'protected' => true,
+ ),
+ array(
+ 'privilege' => '{DAV:}read',
+ 'principal' => $readprincipal . '/calendar-proxy-read',
+ 'protected' => true,
+ ),
+ );
+
+ }
+
+} \ No newline at end of file
diff --git a/apps/calendar/lib/sabre/usercalendars.php b/apps/calendar/lib/sabre/usercalendars.php
new file mode 100644
index 00000000000..919f6b27e18
--- /dev/null
+++ b/apps/calendar/lib/sabre/usercalendars.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * ownCloud - OC_Connector_Sabre_CalDAV_UserCalendars
+ *
+ * @author Thomas Tanghus
+ * @copyright 2012 Thomas Tanghus (thomas@tanghus.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * This class overrides Sabre_CalDAV_UserCalendars::getChildren()
+ * to instantiate OC_Connector_Sabre_CalDAV_Calendars.
+*/
+class OC_Connector_Sabre_CalDAV_UserCalendars extends Sabre_CalDAV_UserCalendars {
+
+ /**
+ * Returns a list of calendars
+ *
+ * @return array
+ */
+ public function getChildren() {
+
+ $calendars = $this->caldavBackend->getCalendarsForUser($this->principalInfo['uri']);
+ $objs = array();
+ foreach($calendars as $calendar) {
+ $objs[] = new OC_Connector_Sabre_CalDAV_Calendar($this->principalBackend, $this->caldavBackend, $calendar);
+ }
+ $objs[] = new Sabre_CalDAV_Schedule_Outbox($this->principalInfo['uri']);
+ return $objs;
+
+ }
+
+} \ No newline at end of file