aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMorris Jobke <hey@morrisjobke.de>2017-09-06 22:48:46 +0200
committerGitHub <noreply@github.com>2017-09-06 22:48:46 +0200
commit8e6d86a862576ab23d884700700580f44cc8cac3 (patch)
treeffd5d03dd60a2345ef7478ddcc56a84e85e78405
parenta10c4517cbb20625b5ee32c1809bee40ecbb5456 (diff)
parenta1df91da9d1c2ea7e81601e2cf66ae747536d61f (diff)
downloadnextcloud-server-8e6d86a862576ab23d884700700580f44cc8cac3.tar.gz
nextcloud-server-8e6d86a862576ab23d884700700580f44cc8cac3.zip
Merge pull request #5304 from nextcloud/bugfix/2855/dont_send_invitations_for_past_events
don't send invitation emails for past events
-rw-r--r--apps/dav/appinfo/v1/caldav.php2
-rw-r--r--apps/dav/lib/CalDAV/Schedule/IMipPlugin.php67
-rw-r--r--apps/dav/lib/Server.php4
-rw-r--r--apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php66
4 files changed, 134 insertions, 5 deletions
diff --git a/apps/dav/appinfo/v1/caldav.php b/apps/dav/appinfo/v1/caldav.php
index 301ea4b5486..bd9de775f44 100644
--- a/apps/dav/appinfo/v1/caldav.php
+++ b/apps/dav/appinfo/v1/caldav.php
@@ -84,7 +84,7 @@ if ($debugging) {
$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!
diff --git a/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php b/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php
index c21edb45848..8e1d7e2563d 100644
--- a/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php
+++ b/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php
@@ -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
*
@@ -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.
*
@@ -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;
}
/**
@@ -85,6 +100,11 @@ class IMipPlugin extends SabreIMipPlugin {
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);
@@ -125,4 +145,49 @@ class IMipPlugin extends SabreIMipPlugin {
}
}
+ /**
+ * 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;
+ }
}
diff --git a/apps/dav/lib/Server.php b/apps/dav/lib/Server.php
index b93f3e6390a..ac0abc8b4eb 100644
--- a/apps/dav/lib/Server.php
+++ b/apps/dav/lib/Server.php
@@ -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;
@@ -74,6 +75,7 @@ class Server {
$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(new CachingTree($root));
@@ -135,7 +137,7 @@ class Server {
$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()));
diff --git a/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php b/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php
index 2b9d10c9e81..56eb00406da 100644
--- a/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php
+++ b/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php
@@ -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
*
@@ -25,6 +27,7 @@ namespace OCA\DAV\Tests\unit\CalDAV\Schedule;
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;
@@ -40,8 +43,10 @@ class IMipPluginTest extends TestCase {
$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();
@@ -49,6 +54,7 @@ class IMipPluginTest extends TestCase {
'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';
@@ -69,8 +75,10 @@ class IMipPluginTest extends TestCase {
$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();
@@ -78,6 +86,7 @@ class IMipPluginTest extends TestCase {
'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';
@@ -90,4 +99,57 @@ class IMipPluginTest extends TestCase {
$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],
+ ];
+ }
}