Skip to content

Commit 7a614d1

Browse files
fix: aliases and capitalization of emails
Signed-off-by: SebastianKrupinski <[email protected]>
1 parent 0a73113 commit 7a614d1

File tree

9 files changed

+290
-981
lines changed

9 files changed

+290
-981
lines changed

apps/dav/lib/CalDAV/CalendarImpl.php

Lines changed: 80 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use OCP\Calendar\CalendarExportOptions;
1515
use OCP\Calendar\Exceptions\CalendarException;
1616
use OCP\Calendar\ICalendarExport;
17+
use OCP\Calendar\ICalendarHandleImip;
1718
use OCP\Calendar\ICalendarIsEnabled;
1819
use OCP\Calendar\ICalendarIsShared;
1920
use OCP\Calendar\ICalendarIsWritable;
@@ -30,7 +31,7 @@
3031
use Sabre\VObject\Reader;
3132
use function Sabre\Uri\split as uriSplit;
3233

33-
class CalendarImpl implements ICreateFromString, IHandleImipMessage, ICalendarIsWritable, ICalendarIsShared, ICalendarExport, ICalendarIsEnabled {
34+
class CalendarImpl implements ICreateFromString, IHandleImipMessage, ICalendarIsEnabled, ICalendarIsWritable, ICalendarIsShared, ICalendarHandleImip, ICalendarExport {
3435
public function __construct(
3536
private Calendar $calendar,
3637
/** @var array<string, mixed> */
@@ -211,60 +212,95 @@ public function createFromString(string $name, string $calendarData): void {
211212

212213
/**
213214
* @throws CalendarException
215+
*
216+
* @deprecated 32.0.0 Use handleIMip() instead
214217
*/
215218
public function handleIMipMessage(string $name, string $calendarData): void {
216-
$server = $this->getInvitationResponseServer();
219+
/** @var VCalendar $vObject */
220+
$vObject = Reader::read($calendarData);
221+
$this->handleIMip($vObject);
222+
}
217223

218-
/** @var CustomPrincipalPlugin $plugin */
219-
$plugin = $server->getServer()->getPlugin('auth');
220-
// we're working around the previous implementation
221-
// that only allowed the public system principal to be used
222-
// so set the custom principal here
223-
$plugin->setCurrentPrincipal($this->calendar->getPrincipalURI());
224+
/**
225+
* Processes an iMip message
226+
*
227+
* @since 32.0.0
228+
*
229+
* @throws CalendarException
230+
*/
231+
public function handleIMip(VCalendar $vObject): void {
224232

233+
// validate the iMip message
234+
if (!isset($vObject->METHOD)) {
235+
throw new CalendarException('iMip message contains no valid method');
236+
}
237+
if (!isset($vObject->VEVENT)) {
238+
throw new CalendarException('iMip message contains no event');
239+
}
240+
if (!isset($vObject->VEVENT->UID)) {
241+
throw new CalendarException('iMip message event dose not contain a UID');
242+
}
243+
if (!isset($vObject->VEVENT->ORGANIZER)) {
244+
throw new CalendarException('iMip message event dose not contain an organizer');
245+
}
246+
if (!isset($vObject->VEVENT->ATTENDEE)) {
247+
throw new CalendarException('iMip message event dose not contain an attendee');
248+
}
225249
if (empty($this->calendarInfo['uri'])) {
226250
throw new CalendarException('Could not write to calendar as URI parameter is missing');
227251
}
252+
// construct dav server
253+
$server = $this->getInvitationResponseServer();
254+
/** @var CustomPrincipalPlugin $authPlugin */
255+
$authPlugin = $server->getServer()->getPlugin('auth');
256+
// we're working around the previous implementation
257+
// that only allowed the public system principal to be used
258+
// so set the custom principal here
259+
$authPlugin->setCurrentPrincipal($this->calendar->getPrincipalURI());
228260
// Force calendar change URI
229-
/** @var Schedule\Plugin $schedulingPlugin */
261+
/** @var \OCA\DAV\CalDAV\Schedule\Plugin $schedulingPlugin */
230262
$schedulingPlugin = $server->getServer()->getPlugin('caldav-schedule');
231-
// Let sabre handle the rest
232-
$iTipMessage = new Message();
233-
/** @var VCalendar $vObject */
234-
$vObject = Reader::read($calendarData);
235-
/** @var VEvent $vEvent */
236-
$vEvent = $vObject->{'VEVENT'};
237-
238-
if ($vObject->{'METHOD'} === null) {
239-
throw new CalendarException('No Method provided for scheduling data. Could not process message');
240-
}
241-
242-
if (!isset($vEvent->{'ORGANIZER'}) || !isset($vEvent->{'ATTENDEE'})) {
243-
throw new CalendarException('Could not process scheduling data, neccessary data missing from ICAL');
244-
}
245-
$organizer = $vEvent->{'ORGANIZER'}->getValue();
246-
$attendee = $vEvent->{'ATTENDEE'}->getValue();
247-
248-
$iTipMessage->method = $vObject->{'METHOD'}->getValue();
249-
if ($iTipMessage->method === 'REQUEST') {
250-
$iTipMessage->sender = $organizer;
251-
$iTipMessage->recipient = $attendee;
252-
} elseif ($iTipMessage->method === 'REPLY') {
253-
if ($server->isExternalAttendee($vEvent->{'ATTENDEE'}->getValue())) {
254-
$iTipMessage->recipient = $organizer;
255-
} else {
256-
$iTipMessage->recipient = $attendee;
263+
// retrieve all uses addresses
264+
$userAddresses = $schedulingPlugin->getAddressesForPrincipal($this->calendar->getPrincipalURI());
265+
$userAddresses = array_map('strtolower', $userAddresses);
266+
// validate the method, recipient and sender
267+
$imipMethod = strtoupper($vObject->METHOD->getValue());
268+
if (in_array($imipMethod, ['REPLY', 'REFRESH'], true)) {
269+
// extract sender (REPLY and REFRESH method should only have one attendee)
270+
$sender = strtolower($vObject->VEVENT->ATTENDEE->getValue());
271+
// extract and verify the recipient
272+
$recipient = strtolower($vObject->VEVENT->ORGANIZER->getValue());
273+
if (!in_array($recipient, $userAddresses, true)) {
274+
throw new CalendarException('iMip message dose not contain an organizer that matches the user');
275+
}
276+
} elseif (in_array($imipMethod, ['PUBLISH', 'REQUEST', 'ADD', 'CANCEL'], true)) {
277+
// extract sender
278+
$sender = strtolower($vObject->VEVENT->ORGANIZER->getValue());
279+
// extract and verify the recipient
280+
foreach ($vObject->VEVENT->ATTENDEE as $attendee) {
281+
$recipient = strtolower($attendee->getValue());
282+
if (in_array($recipient, $userAddresses, true)) {
283+
break;
284+
}
285+
$recipient = null;
286+
}
287+
if ($recipient === null) {
288+
throw new CalendarException('iMip message dose not contain an attendee that matches the user');
257289
}
258-
$iTipMessage->sender = $attendee;
259-
} elseif ($iTipMessage->method === 'CANCEL') {
260-
$iTipMessage->recipient = $attendee;
261-
$iTipMessage->sender = $organizer;
290+
} else {
291+
throw new CalendarException('iMip message contains a method that is not supported: ' . $imipMethod);
262292
}
263-
$iTipMessage->uid = isset($vEvent->{'UID'}) ? $vEvent->{'UID'}->getValue() : '';
264-
$iTipMessage->component = 'VEVENT';
265-
$iTipMessage->sequence = isset($vEvent->{'SEQUENCE'}) ? (int)$vEvent->{'SEQUENCE'}->getValue() : 0;
266-
$iTipMessage->message = $vObject;
267-
$server->server->emit('schedule', [$iTipMessage]);
293+
// generate the iTip message
294+
$iTip = new Message();
295+
$iTip->method = $imipMethod;
296+
$iTip->sender = $sender;
297+
$iTip->recipient = $recipient;
298+
$iTip->component = 'VEVENT';
299+
$iTip->uid = $vObject->VEVENT->UID->getValue();
300+
$iTip->sequence = (int)$vObject->VEVENT->SEQUENCE->getValue();
301+
$iTip->message = $vObject;
302+
303+
$server->server->emit('schedule', [$iTip]);
268304
}
269305

270306
public function getInvitationResponseServer(): InvitationResponseServer {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ public function propFind(PropFind $propFind, INode $node) {
132132
* @param string $principal
133133
* @return array
134134
*/
135-
protected function getAddressesForPrincipal($principal) {
135+
public function getAddressesForPrincipal($principal) {
136136
$result = parent::getAddressesForPrincipal($principal);
137137

138138
if ($result === null) {

0 commit comments

Comments
 (0)