summaryrefslogtreecommitdiffstats
path: root/apps/dav/lib
diff options
context:
space:
mode:
authorVincent Petry <pvince81@owncloud.com>2016-06-10 11:22:11 +0200
committerGitHub <noreply@github.com>2016-06-10 11:22:11 +0200
commit68c3b23e0421a59d5423357e516ab7f4df9fcfbc (patch)
tree2c6b9b8bbca6244d729e87e956ae5500ee064c37 /apps/dav/lib
parentc45b7b0bdf801a2a58fc28602285d52331456222 (diff)
parentbfcd1dc49c6fe296559131841ee0096ec1ce89c7 (diff)
downloadnextcloud-server-68c3b23e0421a59d5423357e516ab7f4df9fcfbc.tar.gz
nextcloud-server-68c3b23e0421a59d5423357e516ab7f4df9fcfbc.zip
Merge pull request #24080 from owncloud/support-calendar-class-property
Extract CLASS property from calendar object and store it in the database
Diffstat (limited to 'apps/dav/lib')
-rw-r--r--apps/dav/lib/AppInfo/Application.php10
-rw-r--r--apps/dav/lib/CalDAV/CalDavBackend.php90
-rw-r--r--apps/dav/lib/CalDAV/Calendar.php77
-rw-r--r--apps/dav/lib/CalDAV/CalendarObject.php92
-rw-r--r--apps/dav/lib/Migration/Classification.php93
5 files changed, 337 insertions, 25 deletions
diff --git a/apps/dav/lib/AppInfo/Application.php b/apps/dav/lib/AppInfo/Application.php
index ba0ef421f97..9e0d2da4e17 100644
--- a/apps/dav/lib/AppInfo/Application.php
+++ b/apps/dav/lib/AppInfo/Application.php
@@ -31,10 +31,12 @@ use OCA\DAV\CardDAV\SyncService;
use OCA\DAV\Connector\Sabre\Principal;
use OCA\DAV\DAV\GroupPrincipalBackend;
use OCA\DAV\HookManager;
+use OCA\DAV\Migration\Classification;
use \OCP\AppFramework\App;
use OCP\AppFramework\IAppContainer;
use OCP\Contacts\IManager;
use OCP\IUser;
+use Sabre\VObject\Reader;
use Symfony\Component\EventDispatcher\GenericEvent;
class Application extends App {
@@ -106,6 +108,14 @@ class Application extends App {
$g
);
});
+
+ $container->registerService('OCA\DAV\Migration\Classification', function ($c) {
+ /** @var IAppContainer $c */
+ return new Classification(
+ $c->query('CalDavBackend'),
+ $c->getServer()->getUserManager()
+ );
+ });
}
/**
diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php
index 64fdf0f7ebe..ce494082976 100644
--- a/apps/dav/lib/CalDAV/CalDavBackend.php
+++ b/apps/dav/lib/CalDAV/CalDavBackend.php
@@ -37,10 +37,11 @@ use Sabre\CalDAV\Xml\Property\ScheduleCalendarTransp;
use Sabre\CalDAV\Xml\Property\SupportedCalendarComponentSet;
use Sabre\DAV;
use Sabre\DAV\Exception\Forbidden;
+use Sabre\DAV\PropPatch;
use Sabre\HTTP\URLUtil;
use Sabre\VObject\DateTimeParser;
use Sabre\VObject\Reader;
-use Sabre\VObject\RecurrenceIterator;
+use Sabre\VObject\Recur\EventIterator;
/**
* Class CalDavBackend
@@ -61,6 +62,10 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
*/
const MAX_DATE = '2038-01-01';
+ const CLASSIFICATION_PUBLIC = 0;
+ const CLASSIFICATION_PRIVATE = 1;
+ const CLASSIFICATION_CONFIDENTIAL = 2;
+
/**
* List of CalDAV properties, and how they map to database field names
* Add your own properties by simply adding on to this array.
@@ -395,10 +400,10 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
*
* Read the PropPatch documentation for more info and examples.
*
- * @param \Sabre\DAV\PropPatch $propPatch
+ * @param PropPatch $propPatch
* @return void
*/
- function updateCalendar($calendarId, \Sabre\DAV\PropPatch $propPatch) {
+ function updateCalendar($calendarId, PropPatch $propPatch) {
$supportedProperties = array_keys($this->propertyMap);
$supportedProperties[] = '{' . Plugin::NS_CALDAV . '}schedule-calendar-transp';
@@ -484,7 +489,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
*/
function getCalendarObjects($calendarId) {
$query = $this->db->getQueryBuilder();
- $query->select(['id', 'uri', 'lastmodified', 'etag', 'calendarid', 'size', 'componenttype'])
+ $query->select(['id', 'uri', 'lastmodified', 'etag', 'calendarid', 'size', 'componenttype', 'classification'])
->from('calendarobjects')
->where($query->expr()->eq('calendarid', $query->createNamedParameter($calendarId)));
$stmt = $query->execute();
@@ -499,6 +504,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
'calendarid' => $row['calendarid'],
'size' => (int)$row['size'],
'component' => strtolower($row['componenttype']),
+ 'classification'=> (int)$row['classification']
];
}
@@ -524,7 +530,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
function getCalendarObject($calendarId, $objectUri) {
$query = $this->db->getQueryBuilder();
- $query->select(['id', 'uri', 'lastmodified', 'etag', 'calendarid', 'size', 'calendardata', 'componenttype'])
+ $query->select(['id', 'uri', 'lastmodified', 'etag', 'calendarid', 'size', 'calendardata', 'componenttype', 'classification'])
->from('calendarobjects')
->where($query->expr()->eq('calendarid', $query->createNamedParameter($calendarId)))
->andWhere($query->expr()->eq('uri', $query->createNamedParameter($objectUri)));
@@ -542,6 +548,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
'size' => (int)$row['size'],
'calendardata' => $this->readBlob($row['calendardata']),
'component' => strtolower($row['componenttype']),
+ 'classification'=> (int)$row['classification']
];
}
@@ -559,7 +566,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
*/
function getMultipleCalendarObjects($calendarId, array $uris) {
$query = $this->db->getQueryBuilder();
- $query->select(['id', 'uri', 'lastmodified', 'etag', 'calendarid', 'size', 'calendardata', 'componenttype'])
+ $query->select(['id', 'uri', 'lastmodified', 'etag', 'calendarid', 'size', 'calendardata', 'componenttype', 'classification'])
->from('calendarobjects')
->where($query->expr()->eq('calendarid', $query->createNamedParameter($calendarId)))
->andWhere($query->expr()->in('uri', $query->createParameter('uri')))
@@ -579,6 +586,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
'size' => (int)$row['size'],
'calendardata' => $this->readBlob($row['calendardata']),
'component' => strtolower($row['componenttype']),
+ 'classification' => (int)$row['classification']
];
}
@@ -618,6 +626,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
'componenttype' => $query->createNamedParameter($extraData['componentType']),
'firstoccurence' => $query->createNamedParameter($extraData['firstOccurence']),
'lastoccurence' => $query->createNamedParameter($extraData['lastOccurence']),
+ 'classification' => $query->createNamedParameter($extraData['classification']),
'uid' => $query->createNamedParameter($extraData['uid']),
])
->execute();
@@ -657,6 +666,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
->set('componenttype', $query->createNamedParameter($extraData['componentType']))
->set('firstoccurence', $query->createNamedParameter($extraData['firstOccurence']))
->set('lastoccurence', $query->createNamedParameter($extraData['lastOccurence']))
+ ->set('classification', $query->createNamedParameter($extraData['classification']))
->set('uid', $query->createNamedParameter($extraData['uid']))
->where($query->expr()->eq('calendarid', $query->createNamedParameter($calendarId)))
->andWhere($query->expr()->eq('uri', $query->createNamedParameter($objectUri)))
@@ -668,6 +678,23 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
}
/**
+ * @param int $calendarObjectId
+ * @param int $classification
+ */
+ public function setClassification($calendarObjectId, $classification) {
+ if (!in_array($classification, [
+ self::CLASSIFICATION_PUBLIC, self::CLASSIFICATION_PRIVATE, self::CLASSIFICATION_CONFIDENTIAL
+ ])) {
+ throw new \InvalidArgumentException();
+ }
+ $query = $this->db->getQueryBuilder();
+ $query->update('calendarobjects')
+ ->set('classification', $query->createNamedParameter($classification))
+ ->where($query->expr()->eq('id', $query->createNamedParameter($calendarObjectId)))
+ ->execute();
+ }
+
+ /**
* Deletes an existing calendar object.
*
* The object uri is only the basename, or filename and not a full path.
@@ -1086,10 +1113,10 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
* Read the PropPatch documentation for more info and examples.
*
* @param mixed $subscriptionId
- * @param \Sabre\DAV\PropPatch $propPatch
+ * @param PropPatch $propPatch
* @return void
*/
- function updateSubscription($subscriptionId, DAV\PropPatch $propPatch) {
+ function updateSubscription($subscriptionId, PropPatch $propPatch) {
$supportedProperties = array_keys($this->subscriptionPropertyMap);
$supportedProperties[] = '{http://calendarserver.org/ns/}source';
@@ -1280,14 +1307,15 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
* @param string $calendarData
* @return array
*/
- protected function getDenormalizedData($calendarData) {
+ public function getDenormalizedData($calendarData) {
$vObject = Reader::read($calendarData);
$componentType = null;
$component = null;
- $firstOccurence = null;
- $lastOccurence = null;
+ $firstOccurrence = null;
+ $lastOccurrence = null;
$uid = null;
+ $classification = self::CLASSIFICATION_PUBLIC;
foreach($vObject->getComponents() as $component) {
if ($component->name!=='VTIMEZONE') {
$componentType = $component->name;
@@ -1299,27 +1327,27 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
throw new \Sabre\DAV\Exception\BadRequest('Calendar objects must have a VJOURNAL, VEVENT or VTODO component');
}
if ($componentType === 'VEVENT' && $component->DTSTART) {
- $firstOccurence = $component->DTSTART->getDateTime()->getTimeStamp();
+ $firstOccurrence = $component->DTSTART->getDateTime()->getTimeStamp();
// Finding the last occurrence is a bit harder
if (!isset($component->RRULE)) {
if (isset($component->DTEND)) {
- $lastOccurence = $component->DTEND->getDateTime()->getTimeStamp();
+ $lastOccurrence = $component->DTEND->getDateTime()->getTimeStamp();
} elseif (isset($component->DURATION)) {
$endDate = clone $component->DTSTART->getDateTime();
$endDate->add(DateTimeParser::parse($component->DURATION->getValue()));
- $lastOccurence = $endDate->getTimeStamp();
+ $lastOccurrence = $endDate->getTimeStamp();
} elseif (!$component->DTSTART->hasTime()) {
$endDate = clone $component->DTSTART->getDateTime();
$endDate->modify('+1 day');
- $lastOccurence = $endDate->getTimeStamp();
+ $lastOccurrence = $endDate->getTimeStamp();
} else {
- $lastOccurence = $firstOccurence;
+ $lastOccurrence = $firstOccurrence;
}
} else {
- $it = new RecurrenceIterator($vObject, (string)$component->UID);
+ $it = new EventIterator($vObject, (string)$component->UID);
$maxDate = new \DateTime(self::MAX_DATE);
if ($it->isInfinite()) {
- $lastOccurence = $maxDate->getTimeStamp();
+ $lastOccurrence = $maxDate->getTimeStamp();
} else {
$end = $it->getDtEnd();
while($it->valid() && $end < $maxDate) {
@@ -1327,19 +1355,31 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
$it->next();
}
- $lastOccurence = $end->getTimeStamp();
+ $lastOccurrence = $end->getTimeStamp();
}
}
}
+ if ($component->CLASS) {
+ $classification = CalDavBackend::CLASSIFICATION_PRIVATE;
+ switch ($component->CLASS->getValue()) {
+ case 'PUBLIC':
+ $classification = CalDavBackend::CLASSIFICATION_PUBLIC;
+ break;
+ case 'CONFIDENTIAL':
+ $classification = CalDavBackend::CLASSIFICATION_CONFIDENTIAL;
+ break;
+ }
+ }
return [
- 'etag' => md5($calendarData),
- 'size' => strlen($calendarData),
- 'componentType' => $componentType,
- 'firstOccurence' => is_null($firstOccurence) ? null : max(0, $firstOccurence),
- 'lastOccurence' => $lastOccurence,
- 'uid' => $uid,
+ 'etag' => md5($calendarData),
+ 'size' => strlen($calendarData),
+ 'componentType' => $componentType,
+ 'firstOccurence' => is_null($firstOccurrence) ? null : max(0, $firstOccurrence),
+ 'lastOccurence' => $lastOccurrence,
+ 'uid' => $uid,
+ 'classification' => $classification
];
}
diff --git a/apps/dav/lib/CalDAV/Calendar.php b/apps/dav/lib/CalDAV/Calendar.php
index 73b3957a9b0..785bb5699e2 100644
--- a/apps/dav/lib/CalDAV/Calendar.php
+++ b/apps/dav/lib/CalDAV/Calendar.php
@@ -26,6 +26,7 @@ use OCA\DAV\DAV\Sharing\IShareable;
use OCP\IL10N;
use Sabre\CalDAV\Backend\BackendInterface;
use Sabre\DAV\Exception\Forbidden;
+use Sabre\DAV\Exception\NotFound;
use Sabre\DAV\PropPatch;
class Calendar extends \Sabre\CalDAV\Calendar implements IShareable {
@@ -162,6 +163,78 @@ class Calendar extends \Sabre\CalDAV\Calendar implements IShareable {
parent::propPatch($propPatch);
}
+ function getChild($name) {
+
+ $obj = $this->caldavBackend->getCalendarObject($this->calendarInfo['id'], $name);
+
+ if (!$obj) {
+ throw new NotFound('Calendar object not found');
+ }
+
+ if ($this->isShared() && $obj['classification'] === CalDavBackend::CLASSIFICATION_PRIVATE) {
+ throw new NotFound('Calendar object not found');
+ }
+
+ $obj['acl'] = $this->getChildACL();
+
+ return new CalendarObject($this->caldavBackend, $this->calendarInfo, $obj);
+
+ }
+
+ function getChildren() {
+
+ $objs = $this->caldavBackend->getCalendarObjects($this->calendarInfo['id']);
+ $children = [];
+ foreach ($objs as $obj) {
+ if ($this->isShared() && $obj['classification'] === CalDavBackend::CLASSIFICATION_PRIVATE) {
+ continue;
+ }
+ $obj['acl'] = $this->getChildACL();
+ $children[] = new CalendarObject($this->caldavBackend, $this->calendarInfo, $obj);
+ }
+ return $children;
+
+ }
+
+ function getMultipleChildren(array $paths) {
+
+ $objs = $this->caldavBackend->getMultipleCalendarObjects($this->calendarInfo['id'], $paths);
+ $children = [];
+ foreach ($objs as $obj) {
+ if ($this->isShared() && $obj['classification'] === CalDavBackend::CLASSIFICATION_PRIVATE) {
+ continue;
+ }
+ $obj['acl'] = $this->getChildACL();
+ $children[] = new CalendarObject($this->caldavBackend, $this->calendarInfo, $obj);
+ }
+ return $children;
+
+ }
+
+ function childExists($name) {
+ $obj = $this->caldavBackend->getCalendarObject($this->calendarInfo['id'], $name);
+ if (!$obj) {
+ return false;
+ }
+ if ($this->isShared() && $obj['classification'] === CalDavBackend::CLASSIFICATION_PRIVATE) {
+ return false;
+ }
+
+ return true;
+ }
+
+ function calendarQuery(array $filters) {
+
+ $uris = $this->caldavBackend->calendarQuery($this->calendarInfo['id'], $filters);
+ if ($this->isShared()) {
+ return array_filter($uris, function ($uri) {
+ return $this->childExists($uri);
+ });
+ }
+
+ return $uris;
+ }
+
private function canWrite() {
if (isset($this->calendarInfo['{http://owncloud.org/ns}read-only'])) {
return !$this->calendarInfo['{http://owncloud.org/ns}read-only'];
@@ -169,4 +242,8 @@ class Calendar extends \Sabre\CalDAV\Calendar implements IShareable {
return true;
}
+ private function isShared() {
+ return isset($this->calendarInfo['{http://owncloud.org/ns}owner-principal']);
+ }
+
}
diff --git a/apps/dav/lib/CalDAV/CalendarObject.php b/apps/dav/lib/CalDAV/CalendarObject.php
new file mode 100644
index 00000000000..b4a58b52093
--- /dev/null
+++ b/apps/dav/lib/CalDAV/CalendarObject.php
@@ -0,0 +1,92 @@
+<?php
+/**
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ *
+ * @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+
+namespace OCA\DAV\CalDAV;
+
+
+use Sabre\VObject\Component;
+use Sabre\VObject\Property;
+use Sabre\VObject\Reader;
+
+class CalendarObject extends \Sabre\CalDAV\CalendarObject {
+
+ /**
+ * @inheritdoc
+ */
+ function get() {
+ $data = parent::get();
+ if ($this->isShared() && $this->objectData['classification'] === CalDavBackend::CLASSIFICATION_CONFIDENTIAL) {
+ return $this->createConfidentialObject($data);
+ }
+ return $data;
+ }
+
+ private function isShared() {
+ return isset($this->calendarInfo['{http://owncloud.org/ns}owner-principal']);
+ }
+
+ /**
+ * @param string $calData
+ * @return string
+ */
+ private static function createConfidentialObject($calData) {
+
+ $vObject = Reader::read($calData);
+
+ /** @var Component $vElement */
+ $vElement = null;
+ if(isset($vObject->VEVENT)) {
+ $vElement = $vObject->VEVENT;
+ }
+ if(isset($vObject->VJOURNAL)) {
+ $vElement = $vObject->VJOURNAL;
+ }
+ if(isset($vObject->VTODO)) {
+ $vElement = $vObject->VTODO;
+ }
+ if(!is_null($vElement)) {
+ foreach ($vElement->children as &$property) {
+ /** @var Property $property */
+ switch($property->name) {
+ case 'CREATED':
+ case 'DTSTART':
+ case 'RRULE':
+ case 'DURATION':
+ case 'DTEND':
+ case 'CLASS':
+ case 'UID':
+ break;
+ case 'SUMMARY':
+ $property->setValue('Busy');
+ break;
+ default:
+ $vElement->__unset($property->name);
+ unset($property);
+ break;
+ }
+ }
+ }
+
+ return $vObject->serialize();
+ }
+
+}
diff --git a/apps/dav/lib/Migration/Classification.php b/apps/dav/lib/Migration/Classification.php
new file mode 100644
index 00000000000..b793f790af5
--- /dev/null
+++ b/apps/dav/lib/Migration/Classification.php
@@ -0,0 +1,93 @@
+<?php
+/**
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ *
+ * @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+
+namespace OCA\DAV\Migration;
+
+use OCA\DAV\CalDAV\CalDavBackend;
+use OCP\IUser;
+use OCP\IUserManager;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
+
+class Classification implements IRepairStep {
+
+ /** @var CalDavBackend */
+ private $calDavBackend;
+
+ /** @var IUserManager */
+ private $userManager;
+
+ /**
+ * Classification constructor.
+ *
+ * @param CalDavBackend $calDavBackend
+ */
+ public function __construct(CalDavBackend $calDavBackend, IUserManager $userManager) {
+ $this->calDavBackend = $calDavBackend;
+ $this->userManager = $userManager;
+ }
+
+ /**
+ * @param IUser $user
+ */
+ public function runForUser($user) {
+ $principal = 'principals/users/' . $user->getUID();
+ $calendars = $this->calDavBackend->getCalendarsForUser($principal);
+ foreach ($calendars as $calendar) {
+ $objects = $this->calDavBackend->getCalendarObjects($calendar['id']);
+ foreach ($objects as $object) {
+ $calObject = $this->calDavBackend->getCalendarObject($calendar['id'], $object['uri']);
+ $classification = $this->extractClassification($calObject['calendardata']);
+ $this->calDavBackend->setClassification($object['id'], $classification);
+ }
+ }
+ }
+
+ /**
+ * @param $calendarData
+ * @return integer
+ * @throws \Sabre\DAV\Exception\BadRequest
+ */
+ protected function extractClassification($calendarData) {
+ return $this->calDavBackend->getDenormalizedData($calendarData)['classification'];
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getName() {
+ return 'Fix classification for calendar objects';
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function run(IOutput $output) {
+ $output->startProgress();
+ $this->userManager->callForAllUsers(function($user) use ($output) {
+ /** @var IUser $user */
+ $output->advance(1, $user->getDisplayName());
+ $this->runForUser($user);
+ });
+ $output->finishProgress();
+ }
+}