diff options
Diffstat (limited to 'apps/dav/lib')
-rw-r--r-- | apps/dav/lib/CalDAV/DefaultCalendarValidator.php | 41 | ||||
-rw-r--r-- | apps/dav/lib/CalDAV/InvitationResponse/InvitationResponseServer.php | 3 | ||||
-rw-r--r-- | apps/dav/lib/CalDAV/Schedule/Plugin.php | 19 | ||||
-rw-r--r-- | apps/dav/lib/Connector/Sabre/ServerFactory.php | 4 | ||||
-rw-r--r-- | apps/dav/lib/DAV/CustomPropertiesBackend.php | 9 | ||||
-rw-r--r-- | apps/dav/lib/Server.php | 6 |
6 files changed, 73 insertions, 9 deletions
diff --git a/apps/dav/lib/CalDAV/DefaultCalendarValidator.php b/apps/dav/lib/CalDAV/DefaultCalendarValidator.php new file mode 100644 index 00000000000..266e07ef255 --- /dev/null +++ b/apps/dav/lib/CalDAV/DefaultCalendarValidator.php @@ -0,0 +1,41 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCA\DAV\CalDAV; + +use Sabre\DAV\Exception as DavException; + +class DefaultCalendarValidator { + /** + * Check if a given Calendar node is suitable to be used as the default calendar for scheduling. + * + * @throws DavException If the calendar is not suitable to be used as the default calendar + */ + public function validateScheduleDefaultCalendar(Calendar $calendar): void { + // Sanity checks for a calendar that should handle invitations + if ($calendar->isSubscription() + || !$calendar->canWrite() + || $calendar->isShared() + || $calendar->isDeleted()) { + throw new DavException('Calendar is a subscription, not writable, shared or deleted'); + } + + // Calendar must support VEVENTs + $sCCS = '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set'; + $calendarProperties = $calendar->getProperties([$sCCS]); + if (isset($calendarProperties[$sCCS])) { + $supportedComponents = $calendarProperties[$sCCS]->getValue(); + } else { + $supportedComponents = ['VJOURNAL', 'VTODO', 'VEVENT']; + } + if (!in_array('VEVENT', $supportedComponents, true)) { + throw new DavException('Calendar does not support VEVENT components'); + } + } +} diff --git a/apps/dav/lib/CalDAV/InvitationResponse/InvitationResponseServer.php b/apps/dav/lib/CalDAV/InvitationResponse/InvitationResponseServer.php index 94f95652677..e076b2cd1e2 100644 --- a/apps/dav/lib/CalDAV/InvitationResponse/InvitationResponseServer.php +++ b/apps/dav/lib/CalDAV/InvitationResponse/InvitationResponseServer.php @@ -8,6 +8,7 @@ namespace OCA\DAV\CalDAV\InvitationResponse; use OCA\DAV\AppInfo\PluginManager; use OCA\DAV\CalDAV\Auth\CustomPrincipalPlugin; use OCA\DAV\CalDAV\Auth\PublicPrincipalPlugin; +use OCA\DAV\CalDAV\DefaultCalendarValidator; use OCA\DAV\Connector\Sabre\AnonymousOptionsPlugin; use OCA\DAV\Connector\Sabre\BlockLegacyClientPlugin; use OCA\DAV\Connector\Sabre\CachingTree; @@ -69,7 +70,7 @@ class InvitationResponseServer { // calendar plugins $this->server->addPlugin(new \OCA\DAV\CalDAV\Plugin()); $this->server->addPlugin(new \Sabre\CalDAV\ICSExportPlugin()); - $this->server->addPlugin(new \OCA\DAV\CalDAV\Schedule\Plugin(\OC::$server->getConfig(), \OC::$server->get(LoggerInterface::class))); + $this->server->addPlugin(new \OCA\DAV\CalDAV\Schedule\Plugin(\OC::$server->getConfig(), \OC::$server->get(LoggerInterface::class), \OC::$server->get(DefaultCalendarValidator::class))); $this->server->addPlugin(new \Sabre\CalDAV\Subscriptions\Plugin()); $this->server->addPlugin(new \Sabre\CalDAV\Notifications\Plugin()); //$this->server->addPlugin(new \OCA\DAV\DAV\Sharing\Plugin($authBackend, \OC::$server->getRequest())); diff --git a/apps/dav/lib/CalDAV/Schedule/Plugin.php b/apps/dav/lib/CalDAV/Schedule/Plugin.php index 897901a61a4..5496fb23a96 100644 --- a/apps/dav/lib/CalDAV/Schedule/Plugin.php +++ b/apps/dav/lib/CalDAV/Schedule/Plugin.php @@ -9,11 +9,13 @@ use DateTimeZone; use OCA\DAV\CalDAV\CalDavBackend; use OCA\DAV\CalDAV\Calendar; use OCA\DAV\CalDAV\CalendarHome; +use OCA\DAV\CalDAV\DefaultCalendarValidator; use OCP\IConfig; use Psr\Log\LoggerInterface; use Sabre\CalDAV\ICalendar; use Sabre\CalDAV\ICalendarObject; use Sabre\CalDAV\Schedule\ISchedulingObject; +use Sabre\DAV\Exception as DavException; use Sabre\DAV\INode; use Sabre\DAV\IProperties; use Sabre\DAV\PropFind; @@ -51,13 +53,15 @@ class Plugin extends \Sabre\CalDAV\Schedule\Plugin { public const CALENDAR_USER_TYPE = '{' . self::NS_CALDAV . '}calendar-user-type'; public const SCHEDULE_DEFAULT_CALENDAR_URL = '{' . Plugin::NS_CALDAV . '}schedule-default-calendar-URL'; private LoggerInterface $logger; + private DefaultCalendarValidator $defaultCalendarValidator; /** * @param IConfig $config */ - public function __construct(IConfig $config, LoggerInterface $logger) { + public function __construct(IConfig $config, LoggerInterface $logger, DefaultCalendarValidator $defaultCalendarValidator) { $this->config = $config; $this->logger = $logger; + $this->defaultCalendarValidator = $defaultCalendarValidator; } /** @@ -360,11 +364,20 @@ EOF; * - isn't a calendar subscription * - user can write to it (no virtual/3rd-party calendars) * - calendar isn't a share + * - calendar supports VEVENTs */ foreach ($calendarHome->getChildren() as $node) { - if ($node instanceof Calendar && !$node->isSubscription() && $node->canWrite() && !$node->isShared() && !$node->isDeleted()) { - $userCalendars[] = $node; + if (!($node instanceof Calendar)) { + continue; } + + try { + $this->defaultCalendarValidator->validateScheduleDefaultCalendar($node); + } catch (DavException $e) { + continue; + } + + $userCalendars[] = $node; } if (count($userCalendars) > 0) { diff --git a/apps/dav/lib/Connector/Sabre/ServerFactory.php b/apps/dav/lib/Connector/Sabre/ServerFactory.php index b07cbc904da..89d9b86becc 100644 --- a/apps/dav/lib/Connector/Sabre/ServerFactory.php +++ b/apps/dav/lib/Connector/Sabre/ServerFactory.php @@ -8,6 +8,7 @@ namespace OCA\DAV\Connector\Sabre; use OCA\DAV\AppInfo\PluginManager; +use OCA\DAV\CalDAV\DefaultCalendarValidator; use OCA\DAV\DAV\ViewOnlyPlugin; use OCA\DAV\Files\BrowserErrorPagePlugin; use OCP\EventDispatcher\IEventDispatcher; @@ -167,7 +168,8 @@ class ServerFactory { $server, $objectTree, $this->databaseConnection, - $this->userSession->getUser() + $this->userSession->getUser(), + \OC::$server->get(DefaultCalendarValidator::class), ) ) ); diff --git a/apps/dav/lib/DAV/CustomPropertiesBackend.php b/apps/dav/lib/DAV/CustomPropertiesBackend.php index f4dd9b2d038..c3a547ab07d 100644 --- a/apps/dav/lib/DAV/CustomPropertiesBackend.php +++ b/apps/dav/lib/DAV/CustomPropertiesBackend.php @@ -8,12 +8,13 @@ namespace OCA\DAV\DAV; use Exception; +use OCA\DAV\CalDAV\Calendar; +use OCA\DAV\CalDAV\DefaultCalendarValidator; use OCA\DAV\Connector\Sabre\Directory; use OCA\DAV\Connector\Sabre\FilesPlugin; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IDBConnection; use OCP\IUser; -use Sabre\CalDAV\ICalendar; use Sabre\DAV\Exception as DavException; use Sabre\DAV\PropertyStorage\Backend\BackendInterface; use Sabre\DAV\PropFind; @@ -135,6 +136,7 @@ class CustomPropertiesBackend implements BackendInterface { private Server $server; private XmlService $xmlService; + private DefaultCalendarValidator $defaultCalendarValidator; /** * @param Tree $tree node tree @@ -146,6 +148,7 @@ class CustomPropertiesBackend implements BackendInterface { Tree $tree, IDBConnection $connection, IUser $user, + DefaultCalendarValidator $defaultCalendarValidator, ) { $this->server = $server; $this->tree = $tree; @@ -156,6 +159,7 @@ class CustomPropertiesBackend implements BackendInterface { $this->xmlService->elementMap, self::COMPLEX_XML_ELEMENT_MAP, ); + $this->defaultCalendarValidator = $defaultCalendarValidator; } /** @@ -319,10 +323,11 @@ class CustomPropertiesBackend implements BackendInterface { // $path is the principal here as this prop is only set on principals $node = $this->tree->getNodeForPath($href); - if (!($node instanceof ICalendar) || $node->getOwner() !== $path) { + if (!($node instanceof Calendar) || $node->getOwner() !== $path) { throw new DavException('No such calendar'); } + $this->defaultCalendarValidator->validateScheduleDefaultCalendar($node); break; } } diff --git a/apps/dav/lib/Server.php b/apps/dav/lib/Server.php index 415571ac25a..9e6d601649f 100644 --- a/apps/dav/lib/Server.php +++ b/apps/dav/lib/Server.php @@ -9,6 +9,7 @@ namespace OCA\DAV; use OCA\DAV\AppInfo\PluginManager; use OCA\DAV\BulkUpload\BulkUploadPlugin; use OCA\DAV\CalDAV\BirthdayService; +use OCA\DAV\CalDAV\DefaultCalendarValidator; use OCA\DAV\CalDAV\Schedule\IMipPlugin; use OCA\DAV\CalDAV\Security\RateLimitingPlugin; use OCA\DAV\CalDAV\Validation\CalDavValidatePlugin; @@ -153,7 +154,7 @@ class Server { $this->server->addPlugin(new DAV\Sharing\Plugin($authBackend, \OC::$server->getRequest(), \OC::$server->getConfig())); $this->server->addPlugin(new \OCA\DAV\CalDAV\Plugin()); $this->server->addPlugin(new \OCA\DAV\CalDAV\ICSExportPlugin\ICSExportPlugin(\OC::$server->getConfig(), $logger)); - $this->server->addPlugin(new \OCA\DAV\CalDAV\Schedule\Plugin(\OC::$server->getConfig(), \OC::$server->get(LoggerInterface::class))); + $this->server->addPlugin(new \OCA\DAV\CalDAV\Schedule\Plugin(\OC::$server->getConfig(), \OC::$server->get(LoggerInterface::class), \OC::$server->get(DefaultCalendarValidator::class))); $this->server->addPlugin(\OC::$server->get(\OCA\DAV\CalDAV\Trashbin\Plugin::class)); $this->server->addPlugin(new \OCA\DAV\CalDAV\WebcalCaching\Plugin($request)); @@ -254,7 +255,8 @@ class Server { $this->server, $this->server->tree, \OC::$server->getDatabaseConnection(), - \OC::$server->getUserSession()->getUser() + \OC::$server->getUserSession()->getUser(), + \OC::$server->get(DefaultCalendarValidator::class), ) ) ); |