Skip to content

Commit

Permalink
feat: add iMip Request Handling
Browse files Browse the repository at this point in the history
Signed-off-by: SebastianKrupinski <krupinskis05@gmail.com>
  • Loading branch information
SebastianKrupinski committed Nov 8, 2024
1 parent 3bd8197 commit 4bc3d19
Show file tree
Hide file tree
Showing 10 changed files with 513 additions and 13 deletions.
13 changes: 12 additions & 1 deletion apps/dav/lib/CalDAV/CachedSubscriptionImpl.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@
namespace OCA\DAV\CalDAV;

use OCP\Calendar\ICalendar;
use OCP\Calendar\ICalendarIsShared;
use OCP\Calendar\ICalendarIsWritable;
use OCP\Constants;

class CachedSubscriptionImpl implements ICalendar {
class CachedSubscriptionImpl implements ICalendar, ICalendarIsShared, ICalendarIsWritable {

public function __construct(
private CachedSubscription $calendar,
/** @var array<string, mixed> */
Expand Down Expand Up @@ -83,10 +86,18 @@ public function getPermissions(): int {
return $result;
}

public function isWritable(): bool {
return false;
}

public function isDeleted(): bool {
return false;
}

public function isShared(): bool {
return true;
}

public function getSource(): string {
return $this->calendarInfo['source'];
}
Expand Down
19 changes: 18 additions & 1 deletion apps/dav/lib/CalDAV/CalendarImpl.php
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,27 @@ public function getPermissions(): int {
return $result;
}

/**
* @since 31.0.0
*/
public function isWritable(): bool {
return $this->calendar->canWrite();
}

/**
* @since 26.0.0
*/
public function isDeleted(): bool {
return $this->calendar->isDeleted();
}

/**
* @since 31.0.0
*/
public function isShared(): bool {
return $this->calendar->isShared();
}

/**
* Create a new calendar event for this calendar
* by way of an ICS string
Expand Down Expand Up @@ -215,7 +229,10 @@ public function handleIMipMessage(string $name, string $calendarData): void {
$attendee = $vEvent->{'ATTENDEE'}->getValue();

$iTipMessage->method = $vObject->{'METHOD'}->getValue();
if ($iTipMessage->method === 'REPLY') {
if ($iTipMessage->method === 'REQUEST') {
$iTipMessage->sender = $organizer;
$iTipMessage->recipient = $attendee;
} elseif ($iTipMessage->method === 'REPLY') {
if ($server->isExternalAttendee($vEvent->{'ATTENDEE'}->getValue())) {
$iTipMessage->recipient = $organizer;
} else {
Expand Down
2 changes: 2 additions & 0 deletions lib/composer/composer/autoload_classmap.php
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@
'OCP\\Calendar\\BackendTemporarilyUnavailableException' => $baseDir . '/lib/public/Calendar/BackendTemporarilyUnavailableException.php',
'OCP\\Calendar\\Exceptions\\CalendarException' => $baseDir . '/lib/public/Calendar/Exceptions/CalendarException.php',
'OCP\\Calendar\\ICalendar' => $baseDir . '/lib/public/Calendar/ICalendar.php',
'OCP\\Calendar\\ICalendarIsShared' => $baseDir . '/lib/public/Calendar/ICalendarIsShared.php',
'OCP\\Calendar\\ICalendarIsWritable' => $baseDir . '/lib/public/Calendar/ICalendarIsWritable.php',
'OCP\\Calendar\\ICalendarProvider' => $baseDir . '/lib/public/Calendar/ICalendarProvider.php',
'OCP\\Calendar\\ICalendarQuery' => $baseDir . '/lib/public/Calendar/ICalendarQuery.php',
'OCP\\Calendar\\ICreateFromString' => $baseDir . '/lib/public/Calendar/ICreateFromString.php',
Expand Down
2 changes: 2 additions & 0 deletions lib/composer/composer/autoload_static.php
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OCP\\Calendar\\BackendTemporarilyUnavailableException' => __DIR__ . '/../../..' . '/lib/public/Calendar/BackendTemporarilyUnavailableException.php',
'OCP\\Calendar\\Exceptions\\CalendarException' => __DIR__ . '/../../..' . '/lib/public/Calendar/Exceptions/CalendarException.php',
'OCP\\Calendar\\ICalendar' => __DIR__ . '/../../..' . '/lib/public/Calendar/ICalendar.php',
'OCP\\Calendar\\ICalendarIsShared' => __DIR__ . '/../../..' . '/lib/public/Calendar/ICalendarIsShared.php',
'OCP\\Calendar\\ICalendarIsWritable' => __DIR__ . '/../../..' . '/lib/public/Calendar/ICalendarIsWritable.php',
'OCP\\Calendar\\ICalendarProvider' => __DIR__ . '/../../..' . '/lib/public/Calendar/ICalendarProvider.php',
'OCP\\Calendar\\ICalendarQuery' => __DIR__ . '/../../..' . '/lib/public/Calendar/ICalendarQuery.php',
'OCP\\Calendar\\ICreateFromString' => __DIR__ . '/../../..' . '/lib/public/Calendar/ICreateFromString.php',
Expand Down
83 changes: 83 additions & 0 deletions lib/private/Calendar/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Calendar\Exceptions\CalendarException;
use OCP\Calendar\ICalendar;
use OCP\Calendar\ICalendarIsShared;
use OCP\Calendar\ICalendarIsWritable;
use OCP\Calendar\ICalendarProvider;
use OCP\Calendar\ICalendarQuery;
use OCP\Calendar\ICreateFromString;
Expand Down Expand Up @@ -204,6 +206,87 @@ public function newQuery(string $principalUri): ICalendarQuery {
return new CalendarQuery($principalUri);
}

/**
* @since 31.0.0
* @throws \OCP\DB\Exception
*/
public function handleIMipRequest(
string $principalUri,
string $sender,
string $recipient,
string $calendarData,
): bool {

$userCalendars = $this->getCalendarsForPrincipal($principalUri);
if (empty($userCalendars)) {
$this->logger->warning('iMip message could not be processed because user has no calendars');
return false;
}

/** @var VCalendar $vObject|null */
$calendarObject = Reader::read($calendarData);

if (!isset($calendarObject->METHOD) || $calendarObject->METHOD->getValue() !== 'REQUEST') {
$this->logger->warning('iMip message contains an incorrect or invalid method');
return false;
}

if (!isset($calendarObject->VEVENT)) {
$this->logger->warning('iMip message contains no event');
return false;
}

$eventObject = $calendarObject->VEVENT;

if (!isset($eventObject->UID)) {
$this->logger->warning('iMip message event dose not contains a UID');
return false;
}

if (!isset($eventObject->ATTENDEE)) {
$this->logger->warning('iMip message event dose not contains any attendees');
return false;
}

foreach ($eventObject->ATTENDEE as $entry) {
$address = trim(str_replace('mailto:', '', $entry->getValue()));
if ($address === $recipient) {
$attendee = $address;
break;
}
}
if (!isset($attendee)) {
$this->logger->warning('iMip message event does not contain a attendee that matches the recipient');
return false;
}

foreach ($userCalendars as $calendar) {

if (!$calendar instanceof ICalendarIsWritable && !$calendar instanceof ICalendarIsShared) {
continue;
}

if ($calendar->isDeleted() || !$calendar->isWritable() || $calendar->isShared()) {
continue;
}

if (!empty($calendar->search($recipient, ['ATTENDEE'], ['uid' => $eventObject->UID->getValue()]))) {
try {
if ($calendar instanceof IHandleImipMessage) {
$calendar->handleIMipMessage('', $calendarData);
}
return true;
} catch (CalendarException $e) {
$this->logger->error('An error occurred while processing the iMip message event', ['exception' => $e]);
return false;
}
}
}

$this->logger->warning('iMip message event could not be processed because the no corresponding event was found in any calendar');
return false;
}

/**
* @throws \OCP\DB\Exception
*/
Expand Down
3 changes: 2 additions & 1 deletion lib/public/Calendar/ICalendar.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ public function search(string $pattern, array $searchProperties = [], array $opt
public function getPermissions(): int;

/**
* Whether the calendar is deleted
* Indicates whether the calendar is in the trash bin
*
* @since 26.0.0
*/
public function isDeleted(): bool;
Expand Down
25 changes: 25 additions & 0 deletions lib/public/Calendar/ICalendarIsShared.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCP\Calendar;

/**
* ICalendar Interface Extension
*
* @since 31.0.0
*/
interface ICalendarIsShared {

/**
* Indicates whether the calendar is shared with the current user
*
* @since 31.0.0
*/
public function isShared(): bool;

}
25 changes: 25 additions & 0 deletions lib/public/Calendar/ICalendarIsWritable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCP\Calendar;

/**
* ICalendar Interface Extension
*
* @since 31.0.0
*/
interface ICalendarIsWritable {

/**
* Indicates whether the calendar can be modified
*
* @since 31.0.0
*/
public function isWritable(): bool;

}
7 changes: 7 additions & 0 deletions lib/public/Calendar/IManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,13 @@ public function searchForPrincipal(ICalendarQuery $query): array;
*/
public function newQuery(string $principalUri) : ICalendarQuery;

/**
* Handle a iMip REQUEST message
*
* @since 31.0.0
*/
public function handleIMipRequest(string $principalUri, string $sender, string $recipient, string $calendarData): bool;

/**
* Handle a iMip REPLY message
*
Expand Down
Loading

0 comments on commit 4bc3d19

Please sign in to comment.