diff options
Diffstat (limited to 'apps/dav/lib')
-rw-r--r-- | apps/dav/lib/caldav/schedule/imipplugin.php | 110 | ||||
-rw-r--r-- | apps/dav/lib/connector/sabre/principal.php | 24 | ||||
-rw-r--r-- | apps/dav/lib/dav/groupprincipalbackend.php | 153 | ||||
-rw-r--r-- | apps/dav/lib/dav/systemprincipalbackend.php | 6 | ||||
-rw-r--r-- | apps/dav/lib/rootcollection.php | 24 | ||||
-rw-r--r-- | apps/dav/lib/server.php | 6 |
6 files changed, 293 insertions, 30 deletions
diff --git a/apps/dav/lib/caldav/schedule/imipplugin.php b/apps/dav/lib/caldav/schedule/imipplugin.php new file mode 100644 index 00000000000..eafdbe9c1bd --- /dev/null +++ b/apps/dav/lib/caldav/schedule/imipplugin.php @@ -0,0 +1,110 @@ +<?php + +namespace OCA\DAV\CalDAV\Schedule; + +use OCP\ILogger; +use OCP\Mail\IMailer; +use Sabre\DAV; +use Sabre\VObject\ITip; +use Sabre\CalDAV\Schedule\IMipPlugin as SabreIMipPlugin; +/** + * iMIP handler. + * + * This class is responsible for sending out iMIP messages. iMIP is the + * email-based transport for iTIP. iTIP deals with scheduling operations for + * iCalendar objects. + * + * If you want to customize the email that gets sent out, you can do so by + * extending this class and overriding the sendMessage method. + * + * @copyright Copyright (C) 2007-2015 fruux GmbH (https://fruux.com/). + * @author Evert Pot (http://evertpot.com/) + * @license http://sabre.io/license/ Modified BSD License + */ +class IMipPlugin extends SabreIMipPlugin { + + /** @var IMailer */ + private $mailer; + + /** @var ILogger */ + private $logger; + + /** + * Creates the email handler. + * + * @param IMailer $mailer + */ + function __construct(IMailer $mailer, ILogger $logger) { + parent::__construct(''); + $this->mailer = $mailer; + $this->logger = $logger; + } + + /** + * Event handler for the 'schedule' event. + * + * @param ITip\Message $iTipMessage + * @return void + */ + function schedule(ITip\Message $iTipMessage) { + + // Not sending any emails if the system considers the update + // insignificant. + if (!$iTipMessage->significantChange) { + if (!$iTipMessage->scheduleStatus) { + $iTipMessage->scheduleStatus = '1.0;We got the message, but it\'s not significant enough to warrant an email'; + } + return; + } + + $summary = $iTipMessage->message->VEVENT->SUMMARY; + + if (parse_url($iTipMessage->sender, PHP_URL_SCHEME) !== 'mailto') { + return; + } + + if (parse_url($iTipMessage->recipient, PHP_URL_SCHEME) !== 'mailto') { + return; + } + + $sender = substr($iTipMessage->sender, 7); + $recipient = substr($iTipMessage->recipient, 7); + + $senderName = ($iTipMessage->senderName) ? $iTipMessage->senderName : null; + $recipientName = ($iTipMessage->recipientName) ? $iTipMessage->recipientName : null; + + $subject = 'SabreDAV iTIP message'; + switch (strtoupper($iTipMessage->method)) { + case 'REPLY' : + $subject = 'Re: ' . $summary; + break; + case 'REQUEST' : + $subject = $summary; + break; + case 'CANCEL' : + $subject = 'Cancelled: ' . $summary; + break; + } + + $contentType = 'text/calendar; charset=UTF-8; method=' . $iTipMessage->method; + + $message = $this->mailer->createMessage(); + + $message->setReplyTo([$sender => $senderName]) + ->setTo([$recipient => $recipientName]) + ->setSubject($subject) + ->setBody($iTipMessage->message->serialize(), $contentType); + try { + $failed = $this->mailer->send($message); + if ($failed) { + $this->logger->error('Unable to deliver message to {failed}', ['app' => 'dav', 'failed' => implode(', ', $failed)]); + $iTipMessage->scheduleStatus = '5.0; EMail delivery failed'; + } + $iTipMessage->scheduleStatus = '1.1; Scheduling message is sent via iMip'; + } catch(\Exception $ex) { + $this->logger->logException($ex, ['app' => 'dav']); + $iTipMessage->scheduleStatus = '5.0; EMail delivery failed'; + } + } + +} diff --git a/apps/dav/lib/connector/sabre/principal.php b/apps/dav/lib/connector/sabre/principal.php index cc9c1c40d59..c917b11225a 100644 --- a/apps/dav/lib/connector/sabre/principal.php +++ b/apps/dav/lib/connector/sabre/principal.php @@ -33,22 +33,20 @@ namespace OCA\DAV\Connector\Sabre; use OCP\IUser; use OCP\IUserManager; use OCP\IConfig; +use Sabre\DAV\Exception; use \Sabre\DAV\PropPatch; +use Sabre\DAVACL\PrincipalBackend\BackendInterface; use Sabre\HTTP\URLUtil; -class Principal implements \Sabre\DAVACL\PrincipalBackend\BackendInterface { - /** @var IConfig */ - private $config; +class Principal implements BackendInterface { + /** @var IUserManager */ private $userManager; /** - * @param IConfig $config * @param IUserManager $userManager */ - public function __construct(IConfig $config, - IUserManager $userManager) { - $this->config = $config; + public function __construct(IUserManager $userManager) { $this->userManager = $userManager; } @@ -108,13 +106,13 @@ class Principal implements \Sabre\DAVACL\PrincipalBackend\BackendInterface { * * @param string $principal * @return string[] - * @throws \Sabre\DAV\Exception + * @throws Exception */ public function getGroupMemberSet($principal) { // TODO: for now the group principal has only one member, the user itself $principal = $this->getPrincipalByPath($principal); if (!$principal) { - throw new \Sabre\DAV\Exception('Principal not found'); + throw new Exception('Principal not found'); } return [$principal['uri']]; @@ -125,7 +123,7 @@ class Principal implements \Sabre\DAVACL\PrincipalBackend\BackendInterface { * * @param string $principal * @return array - * @throws \Sabre\DAV\Exception + * @throws Exception */ public function getGroupMembership($principal) { list($prefix, $name) = URLUtil::splitPath($principal); @@ -134,7 +132,7 @@ class Principal implements \Sabre\DAVACL\PrincipalBackend\BackendInterface { if ($prefix === 'principals/users') { $principal = $this->getPrincipalByPath($principal); if (!$principal) { - throw new \Sabre\DAV\Exception('Principal not found'); + throw new Exception('Principal not found'); } // TODO: for now the user principal has only its own groups @@ -157,10 +155,10 @@ class Principal implements \Sabre\DAVACL\PrincipalBackend\BackendInterface { * * @param string $principal * @param string[] $members - * @throws \Sabre\DAV\Exception + * @throws Exception */ public function setGroupMemberSet($principal, array $members) { - throw new \Sabre\DAV\Exception('Setting members of the group is not supported yet'); + throw new Exception('Setting members of the group is not supported yet'); } /** diff --git a/apps/dav/lib/dav/groupprincipalbackend.php b/apps/dav/lib/dav/groupprincipalbackend.php new file mode 100644 index 00000000000..156dc2c1285 --- /dev/null +++ b/apps/dav/lib/dav/groupprincipalbackend.php @@ -0,0 +1,153 @@ +<?php + +namespace OCA\DAV\DAV; + +use OCP\IGroup; +use OCP\IGroupManager; +use Sabre\DAV\Exception; +use \Sabre\DAV\PropPatch; +use Sabre\DAVACL\PrincipalBackend\BackendInterface; + +class GroupPrincipalBackend implements BackendInterface { + + const PRINCIPAL_PREFIX = 'principals/groups'; + + /** @var IGroupManager */ + private $groupManager; + + /** + * @param IGroupManager $IGroupManager + */ + public function __construct(IGroupManager $IGroupManager) { + $this->groupManager = $IGroupManager; + } + + /** + * Returns a list of principals based on a prefix. + * + * This prefix will often contain something like 'principals'. You are only + * expected to return principals that are in this base path. + * + * You are expected to return at least a 'uri' for every user, you can + * return any additional properties if you wish so. Common properties are: + * {DAV:}displayname + * + * @param string $prefixPath + * @return string[] + */ + public function getPrincipalsByPrefix($prefixPath) { + $principals = []; + + if ($prefixPath === self::PRINCIPAL_PREFIX) { + foreach($this->groupManager->search('') as $user) { + $principals[] = $this->groupToPrincipal($user); + } + } + + return $principals; + } + + /** + * Returns a specific principal, specified by it's path. + * The returned structure should be the exact same as from + * getPrincipalsByPrefix. + * + * @param string $path + * @return array + */ + public function getPrincipalByPath($path) { + $elements = explode('/', $path); + if ($elements[0] !== 'principals') { + return null; + } + if ($elements[1] !== 'groups') { + return null; + } + $name = $elements[2]; + $user = $this->groupManager->get($name); + + if (!is_null($user)) { + return $this->groupToPrincipal($user); + } + + return null; + } + + /** + * Returns the list of members for a group-principal + * + * @param string $principal + * @return string[] + * @throws Exception + */ + public function getGroupMemberSet($principal) { + // TODO: implement if we want that + return []; + } + + /** + * Returns the list of groups a principal is a member of + * + * @param string $principal + * @return array + * @throws Exception + */ + public function getGroupMembership($principal) { + return []; + } + + /** + * Updates the list of group members for a group principal. + * + * The principals should be passed as a list of uri's. + * + * @param string $principal + * @param string[] $members + * @throws Exception + */ + public function setGroupMemberSet($principal, array $members) { + throw new Exception('Setting members of the group is not supported yet'); + } + + /** + * @param string $path + * @param PropPatch $propPatch + * @return int + */ + function updatePrincipal($path, PropPatch $propPatch) { + return 0; + } + + /** + * @param string $prefixPath + * @param array $searchProperties + * @param string $test + * @return array + */ + function searchPrincipals($prefixPath, array $searchProperties, $test = 'allof') { + return []; + } + + /** + * @param string $uri + * @param string $principalPrefix + * @return string + */ + function findByUri($uri, $principalPrefix) { + return ''; + } + + /** + * @param IGroup $group + * @return array + */ + protected function groupToPrincipal($group) { + $groupId = $group->getGID(); + $principal = [ + 'uri' => "principals/groups/$groupId", + '{DAV:}displayname' => $groupId, + ]; + + return $principal; + } +} diff --git a/apps/dav/lib/dav/systemprincipalbackend.php b/apps/dav/lib/dav/systemprincipalbackend.php index 2c2049ace60..f65cd8bfc36 100644 --- a/apps/dav/lib/dav/systemprincipalbackend.php +++ b/apps/dav/lib/dav/systemprincipalbackend.php @@ -65,11 +65,7 @@ class SystemPrincipalBackend extends AbstractBackend { */ function getPrincipalByPath($path) { - $elements = explode('/', $path); - if ($elements[0] !== 'principals') { - return null; - } - if ($elements[1] === 'system') { + if ($path === 'principals/system/system') { $principal = [ 'uri' => 'principals/system/system', '{DAV:}displayname' => 'system', diff --git a/apps/dav/lib/rootcollection.php b/apps/dav/lib/rootcollection.php index 96cc2bbc46a..2261712200a 100644 --- a/apps/dav/lib/rootcollection.php +++ b/apps/dav/lib/rootcollection.php @@ -6,6 +6,7 @@ use OCA\DAV\CalDAV\CalDavBackend; use OCA\DAV\CardDAV\AddressBookRoot; use OCA\DAV\CardDAV\CardDavBackend; use OCA\DAV\Connector\Sabre\Principal; +use OCA\DAV\DAV\GroupPrincipalBackend; use OCA\DAV\DAV\SystemPrincipalBackend; use Sabre\CalDAV\CalendarRoot; use Sabre\CalDAV\Principal\Collection; @@ -16,22 +17,26 @@ class RootCollection extends SimpleCollection { public function __construct() { $config = \OC::$server->getConfig(); $db = \OC::$server->getDatabaseConnection(); - $principalBackend = new Principal( - $config, - \OC::$server->getUserManager() + $userPrincipalBackend = new Principal( + \OC::$server->getUserManager() + ); + $groupPrincipalBackend = new GroupPrincipalBackend( + \OC::$server->getGroupManager() ); // as soon as debug mode is enabled we allow listing of principals $disableListing = !$config->getSystemValue('debug', false); // setup the first level of the dav tree - $userPrincipals = new Collection($principalBackend, 'principals/users'); + $userPrincipals = new Collection($userPrincipalBackend, 'principals/users'); $userPrincipals->disableListing = $disableListing; + $groupPrincipals = new Collection($groupPrincipalBackend, 'principals/groups'); + $groupPrincipals->disableListing = $disableListing; $systemPrincipals = new Collection(new SystemPrincipalBackend(), 'principals/system'); $systemPrincipals->disableListing = $disableListing; - $filesCollection = new Files\RootCollection($principalBackend, 'principals/users'); + $filesCollection = new Files\RootCollection($userPrincipalBackend, 'principals/users'); $filesCollection->disableListing = $disableListing; $caldavBackend = new CalDavBackend($db); - $calendarRoot = new CalendarRoot($principalBackend, $caldavBackend, 'principals/users'); + $calendarRoot = new CalendarRoot($userPrincipalBackend, $caldavBackend, 'principals/users'); $calendarRoot->disableListing = $disableListing; $systemTagCollection = new SystemTag\SystemTagsByIdCollection( \OC::$server->getSystemTagManager() @@ -41,17 +46,18 @@ class RootCollection extends SimpleCollection { \OC::$server->getSystemTagObjectMapper() ); - $usersCardDavBackend = new CardDavBackend($db, $principalBackend, \OC::$server->getLogger()); - $usersAddressBookRoot = new AddressBookRoot($principalBackend, $usersCardDavBackend, 'principals/users'); + $usersCardDavBackend = new CardDavBackend($db, $userPrincipalBackend, \OC::$server->getLogger()); + $usersAddressBookRoot = new AddressBookRoot($userPrincipalBackend, $usersCardDavBackend, 'principals/users'); $usersAddressBookRoot->disableListing = $disableListing; - $systemCardDavBackend = new CardDavBackend($db, $principalBackend, \OC::$server->getLogger()); + $systemCardDavBackend = new CardDavBackend($db, $userPrincipalBackend, \OC::$server->getLogger()); $systemAddressBookRoot = new AddressBookRoot(new SystemPrincipalBackend(), $systemCardDavBackend, 'principals/system'); $systemAddressBookRoot->disableListing = $disableListing; $children = [ new SimpleCollection('principals', [ $userPrincipals, + $groupPrincipals, $systemPrincipals]), $filesCollection, $calendarRoot, diff --git a/apps/dav/lib/server.php b/apps/dav/lib/server.php index ffcbb02db70..a6ad878d29f 100644 --- a/apps/dav/lib/server.php +++ b/apps/dav/lib/server.php @@ -2,12 +2,12 @@ namespace OCA\DAV; +use OCA\DAV\CalDAV\Schedule\IMipPlugin; use OCA\DAV\Connector\Sabre\Auth; use OCA\DAV\Connector\Sabre\BlockLegacyClientPlugin; use OCA\DAV\Files\CustomPropertiesBackend; use OCP\IRequest; use Sabre\DAV\Auth\Plugin; -use Sabre\HTTP\Util; class Server { @@ -19,6 +19,7 @@ class Server { $this->baseUri = $baseUri; $logger = \OC::$server->getLogger(); $dispatcher = \OC::$server->getEventDispatcher(); + $mailer = \OC::$server->getMailer(); $root = new RootCollection(); $this->server = new \OCA\DAV\Connector\Sabre\Server($root); @@ -49,9 +50,8 @@ class Server { // calendar plugins $this->server->addPlugin(new \Sabre\CalDAV\Plugin()); $this->server->addPlugin(new \Sabre\CalDAV\ICSExportPlugin()); - $senderEmail = \OCP\Util::getDefaultEmailAddress('no-reply'); $this->server->addPlugin(new \Sabre\CalDAV\Schedule\Plugin()); - $this->server->addPlugin(new \Sabre\CalDAV\Schedule\IMipPlugin($senderEmail)); + $this->server->addPlugin(new IMipPlugin($mailer, $logger)); $this->server->addPlugin(new \Sabre\CalDAV\SharingPlugin()); $this->server->addPlugin(new \Sabre\CalDAV\Subscriptions\Plugin()); $this->server->addPlugin(new \Sabre\CalDAV\Notifications\Plugin()); |