Skip to content

Commit 32dccaa

Browse files
authored
Merge pull request #42373 from nextcloud/backport/42339/stable28
[stable28] fix(dav): allow multiple organizers if possible
2 parents f0c78b7 + f38ce5c commit 32dccaa

File tree

1 file changed

+67
-1
lines changed

1 file changed

+67
-1
lines changed

apps/dav/lib/CalDAV/Schedule/Plugin.php

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,14 @@
3636
use OCP\IConfig;
3737
use Psr\Log\LoggerInterface;
3838
use Sabre\CalDAV\ICalendar;
39+
use Sabre\CalDAV\ICalendarObject;
40+
use Sabre\CalDAV\Schedule\ISchedulingObject;
3941
use Sabre\DAV\INode;
4042
use Sabre\DAV\IProperties;
4143
use Sabre\DAV\PropFind;
4244
use Sabre\DAV\Server;
4345
use Sabre\DAV\Xml\Property\LocalHref;
46+
use Sabre\DAVACL\IACL;
4447
use Sabre\DAVACL\IPrincipal;
4548
use Sabre\HTTP\RequestInterface;
4649
use Sabre\HTTP\ResponseInterface;
@@ -50,6 +53,7 @@
5053
use Sabre\VObject\DateTimeParser;
5154
use Sabre\VObject\FreeBusyGenerator;
5255
use Sabre\VObject\ITip;
56+
use Sabre\VObject\ITip\SameOrganizerForAllComponentsException;
5357
use Sabre\VObject\Parameter;
5458
use Sabre\VObject\Property;
5559
use Sabre\VObject\Reader;
@@ -161,7 +165,29 @@ public function calendarObjectChange(RequestInterface $request, ResponseInterfac
161165
$this->pathOfCalendarObjectChange = $request->getPath();
162166
}
163167

164-
parent::calendarObjectChange($request, $response, $vCal, $calendarPath, $modified, $isNew);
168+
try {
169+
parent::calendarObjectChange($request, $response, $vCal, $calendarPath, $modified, $isNew);
170+
} catch (SameOrganizerForAllComponentsException $e) {
171+
$this->handleSameOrganizerException($e, $vCal, $calendarPath);
172+
}
173+
}
174+
175+
/**
176+
* @inheritDoc
177+
*/
178+
public function beforeUnbind($path): void {
179+
try {
180+
parent::beforeUnbind($path);
181+
} catch (SameOrganizerForAllComponentsException $e) {
182+
$node = $this->server->tree->getNodeForPath($path);
183+
if (!$node instanceof ICalendarObject || $node instanceof ISchedulingObject) {
184+
throw $e;
185+
}
186+
187+
/** @var VCalendar $vCal */
188+
$vCal = Reader::read($node->get());
189+
$this->handleSameOrganizerException($e, $vCal, $path);
190+
}
165191
}
166192

167193
/**
@@ -630,4 +656,44 @@ private function createCalendar(CalendarHome $calendarHome, string $principalUri
630656
'{DAV:}displayname' => $displayName,
631657
]);
632658
}
659+
660+
/**
661+
* Try to handle the given exception gracefully or throw it if necessary.
662+
*
663+
* @throws SameOrganizerForAllComponentsException If the exception should not be ignored
664+
*/
665+
private function handleSameOrganizerException(
666+
SameOrganizerForAllComponentsException $e,
667+
VCalendar $vCal,
668+
string $calendarPath,
669+
): void {
670+
// This is very hacky! However, we want to allow saving events with multiple
671+
// organizers. Those events are not RFC compliant, but sometimes imported from major
672+
// external calendar services (e.g. Google). If the current user is not an organizer of
673+
// the event we ignore the exception as no scheduling messages will be sent anyway.
674+
675+
// It would be cleaner to patch Sabre to validate organizers *after* checking if
676+
// scheduling messages are necessary. Currently, organizers are validated first and
677+
// afterwards the broker checks if messages should be scheduled. So the code will throw
678+
// even if the organizers are not relevant. This is to ensure compliance with RFCs but
679+
// a bit too strict for real world usage.
680+
681+
if (!isset($vCal->VEVENT)) {
682+
throw $e;
683+
}
684+
685+
$calendarNode = $this->server->tree->getNodeForPath($calendarPath);
686+
if (!($calendarNode instanceof IACL)) {
687+
// Should always be an instance of IACL but just to be sure
688+
throw $e;
689+
}
690+
691+
$addresses = $this->getAddressesForPrincipal($calendarNode->getOwner());
692+
foreach ($vCal->VEVENT as $vevent) {
693+
if (in_array($vevent->ORGANIZER->getNormalizedValue(), $addresses, true)) {
694+
// User is an organizer => throw the exception
695+
throw $e;
696+
}
697+
}
698+
}
633699
}

0 commit comments

Comments
 (0)