Skip to content

Commit 5193ca4

Browse files
Merge pull request #47826 from nextcloud/fix/issue-8458-imip-improvements-2
feat: add iMip Request Handling
2 parents 3bd8197 + 7ebeed4 commit 5193ca4

File tree

10 files changed

+512
-13
lines changed

10 files changed

+512
-13
lines changed

apps/dav/lib/CalDAV/CachedSubscriptionImpl.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@
99
namespace OCA\DAV\CalDAV;
1010

1111
use OCP\Calendar\ICalendar;
12+
use OCP\Calendar\ICalendarIsShared;
13+
use OCP\Calendar\ICalendarIsWritable;
1214
use OCP\Constants;
1315

14-
class CachedSubscriptionImpl implements ICalendar {
16+
class CachedSubscriptionImpl implements ICalendar, ICalendarIsShared, ICalendarIsWritable {
17+
1518
public function __construct(
1619
private CachedSubscription $calendar,
1720
/** @var array<string, mixed> */
@@ -83,10 +86,18 @@ public function getPermissions(): int {
8386
return $result;
8487
}
8588

89+
public function isWritable(): bool {
90+
return false;
91+
}
92+
8693
public function isDeleted(): bool {
8794
return false;
8895
}
8996

97+
public function isShared(): bool {
98+
return true;
99+
}
100+
90101
public function getSource(): string {
91102
return $this->calendarInfo['source'];
92103
}

apps/dav/lib/CalDAV/CalendarImpl.php

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,13 +127,27 @@ public function getPermissions(): int {
127127
return $result;
128128
}
129129

130+
/**
131+
* @since 31.0.0
132+
*/
133+
public function isWritable(): bool {
134+
return $this->calendar->canWrite();
135+
}
136+
130137
/**
131138
* @since 26.0.0
132139
*/
133140
public function isDeleted(): bool {
134141
return $this->calendar->isDeleted();
135142
}
136143

144+
/**
145+
* @since 31.0.0
146+
*/
147+
public function isShared(): bool {
148+
return $this->calendar->isShared();
149+
}
150+
137151
/**
138152
* Create a new calendar event for this calendar
139153
* by way of an ICS string
@@ -215,7 +229,10 @@ public function handleIMipMessage(string $name, string $calendarData): void {
215229
$attendee = $vEvent->{'ATTENDEE'}->getValue();
216230

217231
$iTipMessage->method = $vObject->{'METHOD'}->getValue();
218-
if ($iTipMessage->method === 'REPLY') {
232+
if ($iTipMessage->method === 'REQUEST') {
233+
$iTipMessage->sender = $organizer;
234+
$iTipMessage->recipient = $attendee;
235+
} elseif ($iTipMessage->method === 'REPLY') {
219236
if ($server->isExternalAttendee($vEvent->{'ATTENDEE'}->getValue())) {
220237
$iTipMessage->recipient = $organizer;
221238
} else {

lib/composer/composer/autoload_classmap.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,8 @@
163163
'OCP\\Calendar\\BackendTemporarilyUnavailableException' => $baseDir . '/lib/public/Calendar/BackendTemporarilyUnavailableException.php',
164164
'OCP\\Calendar\\Exceptions\\CalendarException' => $baseDir . '/lib/public/Calendar/Exceptions/CalendarException.php',
165165
'OCP\\Calendar\\ICalendar' => $baseDir . '/lib/public/Calendar/ICalendar.php',
166+
'OCP\\Calendar\\ICalendarIsShared' => $baseDir . '/lib/public/Calendar/ICalendarIsShared.php',
167+
'OCP\\Calendar\\ICalendarIsWritable' => $baseDir . '/lib/public/Calendar/ICalendarIsWritable.php',
166168
'OCP\\Calendar\\ICalendarProvider' => $baseDir . '/lib/public/Calendar/ICalendarProvider.php',
167169
'OCP\\Calendar\\ICalendarQuery' => $baseDir . '/lib/public/Calendar/ICalendarQuery.php',
168170
'OCP\\Calendar\\ICreateFromString' => $baseDir . '/lib/public/Calendar/ICreateFromString.php',

lib/composer/composer/autoload_static.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,8 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
196196
'OCP\\Calendar\\BackendTemporarilyUnavailableException' => __DIR__ . '/../../..' . '/lib/public/Calendar/BackendTemporarilyUnavailableException.php',
197197
'OCP\\Calendar\\Exceptions\\CalendarException' => __DIR__ . '/../../..' . '/lib/public/Calendar/Exceptions/CalendarException.php',
198198
'OCP\\Calendar\\ICalendar' => __DIR__ . '/../../..' . '/lib/public/Calendar/ICalendar.php',
199+
'OCP\\Calendar\\ICalendarIsShared' => __DIR__ . '/../../..' . '/lib/public/Calendar/ICalendarIsShared.php',
200+
'OCP\\Calendar\\ICalendarIsWritable' => __DIR__ . '/../../..' . '/lib/public/Calendar/ICalendarIsWritable.php',
199201
'OCP\\Calendar\\ICalendarProvider' => __DIR__ . '/../../..' . '/lib/public/Calendar/ICalendarProvider.php',
200202
'OCP\\Calendar\\ICalendarQuery' => __DIR__ . '/../../..' . '/lib/public/Calendar/ICalendarQuery.php',
201203
'OCP\\Calendar\\ICreateFromString' => __DIR__ . '/../../..' . '/lib/public/Calendar/ICreateFromString.php',

lib/private/Calendar/Manager.php

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
use OCP\AppFramework\Utility\ITimeFactory;
1313
use OCP\Calendar\Exceptions\CalendarException;
1414
use OCP\Calendar\ICalendar;
15+
use OCP\Calendar\ICalendarIsShared;
16+
use OCP\Calendar\ICalendarIsWritable;
1517
use OCP\Calendar\ICalendarProvider;
1618
use OCP\Calendar\ICalendarQuery;
1719
use OCP\Calendar\ICreateFromString;
@@ -204,6 +206,87 @@ public function newQuery(string $principalUri): ICalendarQuery {
204206
return new CalendarQuery($principalUri);
205207
}
206208

209+
/**
210+
* @since 31.0.0
211+
* @throws \OCP\DB\Exception
212+
*/
213+
public function handleIMipRequest(
214+
string $principalUri,
215+
string $sender,
216+
string $recipient,
217+
string $calendarData,
218+
): bool {
219+
220+
$userCalendars = $this->getCalendarsForPrincipal($principalUri);
221+
if (empty($userCalendars)) {
222+
$this->logger->warning('iMip message could not be processed because user has no calendars');
223+
return false;
224+
}
225+
226+
/** @var VCalendar $vObject|null */
227+
$calendarObject = Reader::read($calendarData);
228+
229+
if (!isset($calendarObject->METHOD) || $calendarObject->METHOD->getValue() !== 'REQUEST') {
230+
$this->logger->warning('iMip message contains an incorrect or invalid method');
231+
return false;
232+
}
233+
234+
if (!isset($calendarObject->VEVENT)) {
235+
$this->logger->warning('iMip message contains no event');
236+
return false;
237+
}
238+
239+
$eventObject = $calendarObject->VEVENT;
240+
241+
if (!isset($eventObject->UID)) {
242+
$this->logger->warning('iMip message event dose not contains a UID');
243+
return false;
244+
}
245+
246+
if (!isset($eventObject->ATTENDEE)) {
247+
$this->logger->warning('iMip message event dose not contains any attendees');
248+
return false;
249+
}
250+
251+
foreach ($eventObject->ATTENDEE as $entry) {
252+
$address = trim(str_replace('mailto:', '', $entry->getValue()));
253+
if ($address === $recipient) {
254+
$attendee = $address;
255+
break;
256+
}
257+
}
258+
if (!isset($attendee)) {
259+
$this->logger->warning('iMip message event does not contain a attendee that matches the recipient');
260+
return false;
261+
}
262+
263+
foreach ($userCalendars as $calendar) {
264+
265+
if (!$calendar instanceof ICalendarIsWritable && !$calendar instanceof ICalendarIsShared) {
266+
continue;
267+
}
268+
269+
if ($calendar->isDeleted() || !$calendar->isWritable() || $calendar->isShared()) {
270+
continue;
271+
}
272+
273+
if (!empty($calendar->search($recipient, ['ATTENDEE'], ['uid' => $eventObject->UID->getValue()]))) {
274+
try {
275+
if ($calendar instanceof IHandleImipMessage) {
276+
$calendar->handleIMipMessage('', $calendarData);
277+
}
278+
return true;
279+
} catch (CalendarException $e) {
280+
$this->logger->error('An error occurred while processing the iMip message event', ['exception' => $e]);
281+
return false;
282+
}
283+
}
284+
}
285+
286+
$this->logger->warning('iMip message event could not be processed because the no corresponding event was found in any calendar');
287+
return false;
288+
}
289+
207290
/**
208291
* @throws \OCP\DB\Exception
209292
*/

lib/public/Calendar/ICalendar.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ public function search(string $pattern, array $searchProperties = [], array $opt
5959
public function getPermissions(): int;
6060

6161
/**
62-
* Whether the calendar is deleted
62+
* Indicates whether the calendar is in the trash bin
63+
*
6364
* @since 26.0.0
6465
*/
6566
public function isDeleted(): bool;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
7+
* SPDX-License-Identifier: AGPL-3.0-or-later
8+
*/
9+
namespace OCP\Calendar;
10+
11+
/**
12+
* ICalendar Interface Extension
13+
*
14+
* @since 31.0.0
15+
*/
16+
interface ICalendarIsShared {
17+
18+
/**
19+
* Indicates whether the calendar is shared with the current user
20+
*
21+
* @since 31.0.0
22+
*/
23+
public function isShared(): bool;
24+
25+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
7+
* SPDX-License-Identifier: AGPL-3.0-or-later
8+
*/
9+
namespace OCP\Calendar;
10+
11+
/**
12+
* ICalendar Interface Extension
13+
*
14+
* @since 31.0.0
15+
*/
16+
interface ICalendarIsWritable {
17+
18+
/**
19+
* Indicates whether the calendar can be modified
20+
*
21+
* @since 31.0.0
22+
*/
23+
public function isWritable(): bool;
24+
25+
}

lib/public/Calendar/IManager.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,13 @@ public function searchForPrincipal(ICalendarQuery $query): array;
137137
*/
138138
public function newQuery(string $principalUri) : ICalendarQuery;
139139

140+
/**
141+
* Handle a iMip REQUEST message
142+
*
143+
* @since 31.0.0
144+
*/
145+
public function handleIMipRequest(string $principalUri, string $sender, string $recipient, string $calendarData): bool;
146+
140147
/**
141148
* Handle a iMip REPLY message
142149
*

0 commit comments

Comments
 (0)