Skip to content

Commit

Permalink
Merge pull request #5841 from nextcloud/bugfix-stable12/2855/dont_sen…
Browse files Browse the repository at this point in the history
…d_invitations_for_past_events

[stable12] dont send invitations for past events
  • Loading branch information
MorrisJobke committed Aug 30, 2017
2 parents bf72005 + 7b113bb commit 6704e89
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 5 deletions.
2 changes: 1 addition & 1 deletion apps/dav/appinfo/v1/caldav.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@
$server->addPlugin(new \Sabre\DAV\Sync\Plugin());
$server->addPlugin(new \Sabre\CalDAV\ICSExportPlugin());
$server->addPlugin(new \OCA\DAV\CalDAV\Schedule\Plugin());
$server->addPlugin(new \OCA\DAV\CalDAV\Schedule\IMipPlugin( \OC::$server->getMailer(), \OC::$server->getLogger()));
$server->addPlugin(new \OCA\DAV\CalDAV\Schedule\IMipPlugin( \OC::$server->getMailer(), \OC::$server->getLogger(), new \OC\AppFramework\Utility\TimeFactory()));
$server->addPlugin(new ExceptionLoggerPlugin('caldav', \OC::$server->getLogger()));

// And off we go!
Expand Down
67 changes: 66 additions & 1 deletion apps/dav/lib/CalDAV/Schedule/IMipPlugin.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
<?php
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
* @copyright Copyright (c) 2017, Georg Ehrke
*
* @author Thomas Müller <thomas.mueller@tmit.eu>
* @author Georg Ehrke <oc.list@georgehrke.com>
*
* @license AGPL-3.0
*
Expand All @@ -21,10 +23,15 @@
*/
namespace OCA\DAV\CalDAV\Schedule;

use OCP\AppFramework\Utility\ITimeFactory;
use OCP\ILogger;
use OCP\Mail\IMailer;
use Sabre\VObject\Component\VCalendar;
use Sabre\VObject\DateTimeParser;
use Sabre\VObject\ITip;
use Sabre\CalDAV\Schedule\IMipPlugin as SabreIMipPlugin;
use Sabre\VObject\Recur\EventIterator;

/**
* iMIP handler.
*
Expand All @@ -47,15 +54,23 @@ class IMipPlugin extends SabreIMipPlugin {
/** @var ILogger */
private $logger;

/** @var ITimeFactory */
private $timeFactory;

const MAX_DATE = '2038-01-01';

/**
* Creates the email handler.
*
* @param IMailer $mailer
* @param ILogger $logger
* @param ITimeFactory $timeFactory
*/
function __construct(IMailer $mailer, ILogger $logger) {
function __construct(IMailer $mailer, ILogger $logger, ITimeFactory $timeFactory) {
parent::__construct('');
$this->mailer = $mailer;
$this->logger = $logger;
$this->timeFactory = $timeFactory;
}

/**
Expand Down Expand Up @@ -85,6 +100,11 @@ function schedule(ITip\Message $iTipMessage) {
return;
}

// don't send out mails for events that already took place
if ($this->isEventInThePast($iTipMessage->message)) {
return;
}

$sender = substr($iTipMessage->sender, 7);
$recipient = substr($iTipMessage->recipient, 7);

Expand Down Expand Up @@ -125,4 +145,49 @@ function schedule(ITip\Message $iTipMessage) {
}
}

/**
* check if event took place in the past already
* @param VCalendar $vObject
* @return bool
*/
private function isEventInThePast(VCalendar $vObject) {
$component = $vObject->VEVENT;

$firstOccurrence = $component->DTSTART->getDateTime()->getTimeStamp();
// Finding the last occurrence is a bit harder
if (!isset($component->RRULE)) {
if (isset($component->DTEND)) {
$lastOccurrence = $component->DTEND->getDateTime()->getTimeStamp();
} elseif (isset($component->DURATION)) {
$endDate = clone $component->DTSTART->getDateTime();
// $component->DTEND->getDateTime() returns DateTimeImmutable
$endDate = $endDate->add(DateTimeParser::parse($component->DURATION->getValue()));
$lastOccurrence = $endDate->getTimeStamp();
} elseif (!$component->DTSTART->hasTime()) {
$endDate = clone $component->DTSTART->getDateTime();
// $component->DTSTART->getDateTime() returns DateTimeImmutable
$endDate = $endDate->modify('+1 day');
$lastOccurrence = $endDate->getTimeStamp();
} else {
$lastOccurrence = $firstOccurrence;
}
} else {
$it = new EventIterator($vObject, (string)$component->UID);
$maxDate = new \DateTime(self::MAX_DATE);
if ($it->isInfinite()) {
$lastOccurrence = $maxDate->getTimestamp();
} else {
$end = $it->getDtEnd();
while($it->valid() && $end < $maxDate) {
$end = $it->getDtEnd();
$it->next();

}
$lastOccurrence = $end->getTimestamp();
}
}

$currentTime = $this->timeFactory->getTime();
return $lastOccurrence < $currentTime;
}
}
4 changes: 3 additions & 1 deletion apps/dav/lib/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
*/
namespace OCA\DAV;

use OC\AppFramework\Utility\TimeFactory;
use OCA\DAV\CalDAV\Schedule\IMipPlugin;
use OCA\DAV\CardDAV\ImageExportPlugin;
use OCA\DAV\CardDAV\PhotoCache;
Expand Down Expand Up @@ -73,6 +74,7 @@ public function __construct(IRequest $request, $baseUri) {
$logger = \OC::$server->getLogger();
$mailer = \OC::$server->getMailer();
$dispatcher = \OC::$server->getEventDispatcher();
$timezone = new TimeFactory();

$root = new RootCollection();
$this->server = new \OCA\DAV\Connector\Sabre\Server($root);
Expand Down Expand Up @@ -134,7 +136,7 @@ public function __construct(IRequest $request, $baseUri) {
$this->server->addPlugin(new \OCA\DAV\CalDAV\Plugin());
$this->server->addPlugin(new \Sabre\CalDAV\ICSExportPlugin());
$this->server->addPlugin(new \OCA\DAV\CalDAV\Schedule\Plugin());
$this->server->addPlugin(new IMipPlugin($mailer, $logger));
$this->server->addPlugin(new IMipPlugin($mailer, $logger, $timezone));
$this->server->addPlugin(new \Sabre\CalDAV\Subscriptions\Plugin());
$this->server->addPlugin(new \Sabre\CalDAV\Notifications\Plugin());
$this->server->addPlugin(new DAV\Sharing\Plugin($authBackend, \OC::$server->getRequest()));
Expand Down
66 changes: 64 additions & 2 deletions apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
<?php
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
* @copyright Copyright (c) 2017, Georg Ehrke
*
* @author Joas Schilling <coding@schilljs.com>
* @author Thomas Müller <thomas.mueller@tmit.eu>
* @author Georg Ehrke <oc.list@georgehrke.com>
*
* @license AGPL-3.0
*
Expand All @@ -25,6 +27,7 @@

use OC\Mail\Mailer;
use OCA\DAV\CalDAV\Schedule\IMipPlugin;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\ILogger;
use Sabre\VObject\Component\VCalendar;
use Sabre\VObject\ITip\Message;
Expand All @@ -40,15 +43,18 @@ public function testDelivery() {
$mailer->expects($this->once())->method('send');
/** @var ILogger | \PHPUnit_Framework_MockObject_MockObject $logger */
$logger = $this->getMockBuilder('OC\Log')->disableOriginalConstructor()->getMock();
$timeFactory = $this->getMockBuilder(ITimeFactory::class)->disableOriginalConstructor()->getMock();
$timeFactory->method('getTime')->willReturn(1);

$plugin = new IMipPlugin($mailer, $logger);
$plugin = new IMipPlugin($mailer, $logger, $timeFactory);
$message = new Message();
$message->method = 'REQUEST';
$message->message = new VCalendar();
$message->message->add('VEVENT', [
'UID' => $message->uid,
'SEQUENCE' => $message->sequence,
'SUMMARY' => 'Fellowship meeting',
'DTSTART' => new \DateTime('2017-01-01 00:00:00') // 1483228800
]);
$message->sender = 'mailto:gandalf@wiz.ard';
$message->recipient = 'mailto:frodo@hobb.it';
Expand All @@ -69,15 +75,18 @@ public function testFailedDelivery() {
$mailer->method('send')->willThrowException(new \Exception());
/** @var ILogger | \PHPUnit_Framework_MockObject_MockObject $logger */
$logger = $this->getMockBuilder('OC\Log')->disableOriginalConstructor()->getMock();
$timeFactory = $this->getMockBuilder(ITimeFactory::class)->disableOriginalConstructor()->getMock();
$timeFactory->method('getTime')->willReturn(1);

$plugin = new IMipPlugin($mailer, $logger);
$plugin = new IMipPlugin($mailer, $logger, $timeFactory);
$message = new Message();
$message->method = 'REQUEST';
$message->message = new VCalendar();
$message->message->add('VEVENT', [
'UID' => $message->uid,
'SEQUENCE' => $message->sequence,
'SUMMARY' => 'Fellowship meeting',
'DTSTART' => new \DateTime('2017-01-01 00:00:00') // 1483228800
]);
$message->sender = 'mailto:gandalf@wiz.ard';
$message->recipient = 'mailto:frodo@hobb.it';
Expand All @@ -90,4 +99,57 @@ public function testFailedDelivery() {
$this->assertEquals('text/calendar; charset=UTF-8; method=REQUEST', $mailMessage->getSwiftMessage()->getContentType());
}

/**
* @dataProvider dataNoMessageSendForPastEvents
*/
public function testNoMessageSendForPastEvents($veventParams, $expectsMail) {
$mailMessage = new \OC\Mail\Message(new \Swift_Message());
/** @var Mailer | \PHPUnit_Framework_MockObject_MockObject $mailer */
$mailer = $this->getMockBuilder('OC\Mail\Mailer')->disableOriginalConstructor()->getMock();
$mailer->method('createMessage')->willReturn($mailMessage);
if ($expectsMail) {
$mailer->expects($this->once())->method('send');
} else {
$mailer->expects($this->never())->method('send');
}
/** @var ILogger | \PHPUnit_Framework_MockObject_MockObject $logger */
$logger = $this->getMockBuilder('OC\Log')->disableOriginalConstructor()->getMock();
$timeFactory = $this->getMockBuilder(ITimeFactory::class)->disableOriginalConstructor()->getMock();
$timeFactory->method('getTime')->willReturn(1496912528);

$plugin = new IMipPlugin($mailer, $logger, $timeFactory);
$message = new Message();
$message->method = 'REQUEST';
$message->message = new VCalendar();
$message->message->add('VEVENT', array_merge([
'UID' => 'uid1337',
'SEQUENCE' => 42,
'SUMMARY' => 'Fellowship meeting',
], $veventParams));
$message->sender = 'mailto:gandalf@wiz.ard';
$message->recipient = 'mailto:frodo@hobb.it';

$plugin->schedule($message);

if ($expectsMail) {
$this->assertEquals('1.1', $message->getScheduleStatus());
} else {
$this->assertEquals(false, $message->getScheduleStatus());
}
}

public function dataNoMessageSendForPastEvents() {
return [
[['DTSTART' => new \DateTime('2017-01-01 00:00:00')], false],
[['DTSTART' => new \DateTime('2017-01-01 00:00:00'), 'DTEND' => new \DateTime('2017-01-01 00:00:00')], false],
[['DTSTART' => new \DateTime('2017-01-01 00:00:00'), 'DTEND' => new \DateTime('2017-12-31 00:00:00')], true],
[['DTSTART' => new \DateTime('2017-01-01 00:00:00'), 'DURATION' => 'P1D'], false],
[['DTSTART' => new \DateTime('2017-01-01 00:00:00'), 'DURATION' => 'P52W'], true],
[['DTSTART' => new \DateTime('2017-01-01 00:00:00'), 'DTEND' => new \DateTime('2017-01-01 00:00:00'), 'RRULE' => 'FREQ=WEEKLY'], true],
[['DTSTART' => new \DateTime('2017-01-01 00:00:00'), 'DTEND' => new \DateTime('2017-01-01 00:00:00'), 'RRULE' => 'FREQ=WEEKLY;COUNT=3'], false],
[['DTSTART' => new \DateTime('2017-01-01 00:00:00'), 'DTEND' => new \DateTime('2017-01-01 00:00:00'), 'RRULE' => 'FREQ=WEEKLY;UNTIL=20170301T000000Z'], false],
[['DTSTART' => new \DateTime('2017-01-01 00:00:00'), 'DTEND' => new \DateTime('2017-01-01 00:00:00'), 'RRULE' => 'FREQ=WEEKLY;COUNT=33'], true],
[['DTSTART' => new \DateTime('2017-01-01 00:00:00'), 'DTEND' => new \DateTime('2017-01-01 00:00:00'), 'RRULE' => 'FREQ=WEEKLY;UNTIL=20171001T000000Z'], true],
];
}
}

0 comments on commit 6704e89

Please sign in to comment.