summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/dav/appinfo/database.xml8
-rw-r--r--apps/dav/appinfo/v1/caldav.php5
-rw-r--r--apps/dav/lib/CalDAV/CalDavBackend.php178
-rw-r--r--apps/dav/lib/CalDAV/Calendar.php39
-rw-r--r--apps/dav/lib/CalDAV/PublicCalendarRoot.php67
-rw-r--r--apps/dav/lib/CalDAV/Publishing/PublishPlugin.php227
-rw-r--r--apps/dav/lib/CalDAV/Publishing/Xml/Publisher.php83
-rw-r--r--apps/dav/lib/Command/CreateCalendar.php5
-rw-r--r--apps/dav/lib/DAV/PublicAuth.php92
-rw-r--r--apps/dav/lib/DAV/SystemPrincipalBackend.php11
-rw-r--r--apps/dav/lib/RootCollection.php10
-rw-r--r--apps/dav/lib/Server.php7
-rw-r--r--apps/dav/tests/unit/CalDAV/AbstractCalDavBackendTest.php13
-rw-r--r--apps/dav/tests/unit/CalDAV/CalDavBackendTest.php29
-rw-r--r--apps/dav/tests/unit/CalDAV/PublicCalendarRootTest.php122
-rw-r--r--apps/dav/tests/unit/CalDAV/Publishing/PublisherTest.php56
-rw-r--r--apps/dav/tests/unit/CalDAV/Publishing/PublishingTest.php82
-rw-r--r--apps/dav/tests/unit/DAV/SystemPrincipalBackendTest.php7
18 files changed, 1033 insertions, 8 deletions
diff --git a/apps/dav/appinfo/database.xml b/apps/dav/appinfo/database.xml
index b86129485d8..0efd2a46d61 100644
--- a/apps/dav/appinfo/database.xml
+++ b/apps/dav/appinfo/database.xml
@@ -703,6 +703,11 @@ CREATE TABLE calendarobjects (
<notnull>true</notnull>
<unsigned>true</unsigned>
</field>
+ <field>
+ <name>publicuri</name>
+ <type>text</type>
+ <length>255</length>
+ </field>
<index>
<name>dav_shares_index</name>
<unique>true</unique>
@@ -715,6 +720,9 @@ CREATE TABLE calendarobjects (
<field>
<name>type</name>
</field>
+ <field>
+ <name>publicuri</name>
+ </field>
</index>
</declaration>
</table>
diff --git a/apps/dav/appinfo/v1/caldav.php b/apps/dav/appinfo/v1/caldav.php
index 13b4d3119ca..d18e93dd7a9 100644
--- a/apps/dav/appinfo/v1/caldav.php
+++ b/apps/dav/appinfo/v1/caldav.php
@@ -46,7 +46,10 @@ $principalBackend = new Principal(
'principals/'
);
$db = \OC::$server->getDatabaseConnection();
-$calDavBackend = new CalDavBackend($db, $principalBackend, \OC::$server->getUserManager());
+$config = \OC::$server->getConfig();
+$userManager = \OC::$server->getUserManager();
+$random = \OC::$server->getSecureRandom();
+$calDavBackend = new CalDavBackend($db, $principalBackend, $userManager, $config, $random);
$debugging = \OC::$server->getConfig()->getSystemValue('debug', false);
diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php
index 17479c490a9..440188c13ca 100644
--- a/apps/dav/lib/CalDAV/CalDavBackend.php
+++ b/apps/dav/lib/CalDAV/CalDavBackend.php
@@ -29,9 +29,11 @@ use OCA\DAV\DAV\Sharing\IShareable;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCA\DAV\Connector\Sabre\Principal;
use OCA\DAV\DAV\Sharing\Backend;
+use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IUser;
use OCP\IUserManager;
+use OCP\Security\ISecureRandom;
use Sabre\CalDAV\Backend\AbstractBackend;
use Sabre\CalDAV\Backend\SchedulingSupport;
use Sabre\CalDAV\Backend\SubscriptionSupport;
@@ -41,6 +43,7 @@ use Sabre\CalDAV\Xml\Property\ScheduleCalendarTransp;
use Sabre\CalDAV\Xml\Property\SupportedCalendarComponentSet;
use Sabre\DAV;
use Sabre\DAV\Exception\Forbidden;
+use Sabre\DAV\Exception\NotFound;
use Sabre\DAV\PropPatch;
use Sabre\HTTP\URLUtil;
use Sabre\VObject\DateTimeParser;
@@ -66,6 +69,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
*/
const MAX_DATE = '2038-01-01';
+ const ACCESS_PUBLIC = 4;
const CLASSIFICATION_PUBLIC = 0;
const CLASSIFICATION_PRIVATE = 1;
const CLASSIFICATION_CONFIDENTIAL = 2;
@@ -117,6 +121,12 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
/** @var IUserManager */
private $userManager;
+
+ /** @var IConfig */
+ private $config;
+
+ /** @var ISecureRandom */
+ private $random;
/**
* CalDavBackend constructor.
@@ -124,12 +134,20 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
* @param IDBConnection $db
* @param Principal $principalBackend
* @param IUserManager $userManager
+ * @param IConfig $config
+ * @param ISecureRandom $random
*/
- public function __construct(IDBConnection $db, Principal $principalBackend, IUserManager $userManager) {
+ public function __construct(IDBConnection $db,
+ Principal $principalBackend,
+ IUserManager $userManager,
+ IConfig $config,
+ ISecureRandom $random) {
$this->db = $db;
$this->principalBackend = $principalBackend;
$this->userManager = $userManager;
$this->sharingBackend = new Backend($this->db, $principalBackend, 'calendar');
+ $this->config = $config;
+ $this->random = $random;
}
/**
@@ -295,6 +313,120 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
return $this->userDisplayNames[$uid];
}
+
+ /**
+ * @return array
+ */
+ public function getPublicCalendars() {
+ $fields = array_values($this->propertyMap);
+ $fields[] = 'a.id';
+ $fields[] = 'a.uri';
+ $fields[] = 'a.synctoken';
+ $fields[] = 'a.components';
+ $fields[] = 'a.principaluri';
+ $fields[] = 'a.transparent';
+ $fields[] = 's.access';
+ $fields[] = 's.publicuri';
+ $calendars = [];
+ $query = $this->db->getQueryBuilder();
+ $result = $query->select($fields)
+ ->from('dav_shares', 's')
+ ->join('s', 'calendars', 'a', $query->expr()->eq('s.resourceid', 'a.id'))
+ ->where($query->expr()->in('s.access', $query->createNamedParameter(self::ACCESS_PUBLIC)))
+ ->andWhere($query->expr()->eq('s.type', $query->createNamedParameter('calendar')))
+ ->execute();
+
+ while($row = $result->fetch()) {
+ list(, $name) = URLUtil::splitPath($row['principaluri']);
+ $row['displayname'] = $row['displayname'] . "($name)";
+ $components = [];
+ if ($row['components']) {
+ $components = explode(',',$row['components']);
+ }
+ $calendar = [
+ 'id' => $row['id'],
+ 'uri' => $row['publicuri'],
+ 'principaluri' => $row['principaluri'],
+ '{' . Plugin::NS_CALENDARSERVER . '}getctag' => 'http://sabre.io/ns/sync/' . ($row['synctoken']?$row['synctoken']:'0'),
+ '{http://sabredav.org/ns}sync-token' => $row['synctoken']?$row['synctoken']:'0',
+ '{' . Plugin::NS_CALDAV . '}supported-calendar-component-set' => new SupportedCalendarComponentSet($components),
+ '{' . Plugin::NS_CALDAV . '}schedule-calendar-transp' => new ScheduleCalendarTransp($row['transparent']?'transparent':'opaque'),
+ '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}owner-principal' => $row['principaluri'],
+ '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}read-only' => (int)$row['access'] === Backend::ACCESS_READ,
+ '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}public' => (int)$row['access'] === self::ACCESS_PUBLIC,
+ ];
+
+ foreach($this->propertyMap as $xmlName=>$dbName) {
+ $calendar[$xmlName] = $row[$dbName];
+ }
+
+ if (!isset($calendars[$calendar['id']])) {
+ $calendars[$calendar['id']] = $calendar;
+ }
+ }
+ $result->closeCursor();
+
+ return array_values($calendars);
+ }
+
+ /**
+ * @param string $uri
+ * @return array
+ * @throws NotFound
+ */
+ public function getPublicCalendar($uri) {
+ $fields = array_values($this->propertyMap);
+ $fields[] = 'a.id';
+ $fields[] = 'a.uri';
+ $fields[] = 'a.synctoken';
+ $fields[] = 'a.components';
+ $fields[] = 'a.principaluri';
+ $fields[] = 'a.transparent';
+ $fields[] = 's.access';
+ $fields[] = 's.publicuri';
+ $query = $this->db->getQueryBuilder();
+ $result = $query->select($fields)
+ ->from('dav_shares', 's')
+ ->join('s', 'calendars', 'a', $query->expr()->eq('s.resourceid', 'a.id'))
+ ->where($query->expr()->in('s.access', $query->createNamedParameter(self::ACCESS_PUBLIC)))
+ ->andWhere($query->expr()->eq('s.type', $query->createNamedParameter('calendar')))
+ ->andWhere($query->expr()->eq('s.publicuri', $query->createNamedParameter($uri)))
+ ->execute();
+
+ $row = $result->fetch(\PDO::FETCH_ASSOC);
+
+ $result->closeCursor();
+
+ if ($row === false) {
+ throw new NotFound('Node with name \'' . $uri . '\' could not be found');
+ }
+
+ list(, $name) = URLUtil::splitPath($row['principaluri']);
+ $row['displayname'] = $row['displayname'] . ' ' . "($name)";
+ $components = [];
+ if ($row['components']) {
+ $components = explode(',',$row['components']);
+ }
+ $calendar = [
+ 'id' => $row['id'],
+ 'uri' => $row['publicuri'],
+ 'principaluri' => $row['principaluri'],
+ '{' . Plugin::NS_CALENDARSERVER . '}getctag' => 'http://sabre.io/ns/sync/' . ($row['synctoken']?$row['synctoken']:'0'),
+ '{http://sabredav.org/ns}sync-token' => $row['synctoken']?$row['synctoken']:'0',
+ '{' . Plugin::NS_CALDAV . '}supported-calendar-component-set' => new SupportedCalendarComponentSet($components),
+ '{' . Plugin::NS_CALDAV . '}schedule-calendar-transp' => new ScheduleCalendarTransp($row['transparent']?'transparent':'opaque'),
+ '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}owner-principal' => $row['principaluri'],
+ '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}read-only' => (int)$row['access'] === Backend::ACCESS_READ,
+ '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}public' => (int)$row['access'] === self::ACCESS_PUBLIC,
+ ];
+
+ foreach($this->propertyMap as $xmlName=>$dbName) {
+ $calendar[$xmlName] = $row[$dbName];
+ }
+
+ return $calendar;
+
+ }
/**
* @param string $principal
@@ -1473,6 +1605,50 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
}
/**
+ * @param boolean $value
+ * @param \OCA\DAV\CalDAV\Calendar $calendar
+ * @return string|null
+ */
+ public function setPublishStatus($value, $calendar) {
+ $query = $this->db->getQueryBuilder();
+ if ($value) {
+ $publicUri = $this->random->generate(16, ISecureRandom::CHAR_UPPER.ISecureRandom::CHAR_DIGITS);
+ $query->insert('dav_shares')
+ ->values([
+ 'principaluri' => $query->createNamedParameter($calendar->getPrincipalURI()),
+ 'type' => $query->createNamedParameter('calendar'),
+ 'access' => $query->createNamedParameter(self::ACCESS_PUBLIC),
+ 'resourceid' => $query->createNamedParameter($calendar->getResourceId()),
+ 'publicuri' => $query->createNamedParameter($publicUri)
+ ]);
+ $query->execute();
+ return $publicUri;
+ }
+ $query->delete('dav_shares')
+ ->where($query->expr()->eq('resourceid', $query->createNamedParameter($calendar->getResourceId())))
+ ->andWhere($query->expr()->eq('access', $query->createNamedParameter(self::ACCESS_PUBLIC)));
+ $query->execute();
+ return null;
+ }
+
+ /**
+ * @param \OCA\DAV\CalDAV\Calendar $calendar
+ * @return mixed
+ */
+ public function getPublishStatus($calendar) {
+ $query = $this->db->getQueryBuilder();
+ $result = $query->select('publicuri')
+ ->from('dav_shares')
+ ->where($query->expr()->eq('resourceid', $query->createNamedParameter($calendar->getResourceId())))
+ ->andWhere($query->expr()->eq('access', $query->createNamedParameter(self::ACCESS_PUBLIC)))
+ ->execute();
+
+ $row = $result->fetch();
+ $result->closeCursor();
+ return $row ? reset($row) : false;
+ }
+
+ /**
* @param int $resourceId
* @param array $acl
* @return array
diff --git a/apps/dav/lib/CalDAV/Calendar.php b/apps/dav/lib/CalDAV/Calendar.php
index 821a71babb1..3fbcd87acc0 100644
--- a/apps/dav/lib/CalDAV/Calendar.php
+++ b/apps/dav/lib/CalDAV/Calendar.php
@@ -89,6 +89,13 @@ class Calendar extends \Sabre\CalDAV\Calendar implements IShareable {
return $this->calendarInfo['id'];
}
+ /**
+ * @return string
+ */
+ public function getPrincipalURI() {
+ return $this->calendarInfo['principaluri'];
+ }
+
function getACL() {
$acl = [
[
@@ -117,6 +124,13 @@ class Calendar extends \Sabre\CalDAV\Calendar implements IShareable {
];
}
}
+ if ($this->isPublic()) {
+ $acl[] = [
+ 'privilege' => '{DAV:}read',
+ 'principal' => 'principals/system/public',
+ 'protected' => true,
+ ];
+ }
/** @var CalDavBackend $calDavBackend */
$calDavBackend = $this->caldavBackend;
@@ -236,6 +250,23 @@ class Calendar extends \Sabre\CalDAV\Calendar implements IShareable {
return $uris;
}
+ /**
+ * @param boolean $value
+ * @return string|null
+ */
+ function setPublishStatus($value) {
+ $publicUri = $this->caldavBackend->setPublishStatus($value, $this);
+ $this->calendarInfo['publicuri'] = $publicUri;
+ return $publicUri;
+ }
+
+ /**
+ * @return mixed $value
+ */
+ function getPublishStatus() {
+ return $this->caldavBackend->getPublishStatus($this);
+ }
+
private function canWrite() {
if (isset($this->calendarInfo['{http://owncloud.org/ns}read-only'])) {
return !$this->calendarInfo['{http://owncloud.org/ns}read-only'];
@@ -243,8 +274,16 @@ class Calendar extends \Sabre\CalDAV\Calendar implements IShareable {
return true;
}
+ private function isPublic() {
+ return isset($this->calendarInfo['{http://owncloud.org/ns}public']);
+ }
+
private function isShared() {
return isset($this->calendarInfo['{http://owncloud.org/ns}owner-principal']);
}
+ public function isSubscription() {
+ return isset($this->calendarInfo['{http://calendarserver.org/ns/}source']);
+ }
+
}
diff --git a/apps/dav/lib/CalDAV/PublicCalendarRoot.php b/apps/dav/lib/CalDAV/PublicCalendarRoot.php
new file mode 100644
index 00000000000..6d74b97f96e
--- /dev/null
+++ b/apps/dav/lib/CalDAV/PublicCalendarRoot.php
@@ -0,0 +1,67 @@
+<?php
+/**
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ *
+ * @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+namespace OCA\DAV\CalDAV;
+
+use Sabre\DAV\Collection;
+use Sabre\DAV\Exception\NotFound;
+
+class PublicCalendarRoot extends Collection {
+
+ /** @var CalDavBackend */
+ protected $caldavBackend;
+
+ /** @var \OCP\IL10N */
+ protected $l10n;
+
+ function __construct(CalDavBackend $caldavBackend) {
+ $this->caldavBackend = $caldavBackend;
+ $this->l10n = \OC::$server->getL10N('dav');
+ }
+
+ /**
+ * @inheritdoc
+ */
+ function getName() {
+ return 'public-calendars';
+ }
+
+ /**
+ * @inheritdoc
+ */
+ function getChild($name) {
+ $calendar = $this->caldavBackend->getPublicCalendar($name);
+ return new Calendar($this->caldavBackend, $calendar, $this->l10n);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ function getChildren() {
+ $calendars = $this->caldavBackend->getPublicCalendars();
+ $children = [];
+ foreach ($calendars as $calendar) {
+ // TODO: maybe implement a new class PublicCalendar ???
+ $children[] = new Calendar($this->caldavBackend, $calendar, $this->l10n);
+ }
+
+ return $children;
+ }
+}
diff --git a/apps/dav/lib/CalDAV/Publishing/PublishPlugin.php b/apps/dav/lib/CalDAV/Publishing/PublishPlugin.php
new file mode 100644
index 00000000000..199bc67e615
--- /dev/null
+++ b/apps/dav/lib/CalDAV/Publishing/PublishPlugin.php
@@ -0,0 +1,227 @@
+<?php
+/**
+ * @author Thomas Citharel <tcit@tcit.fr>
+ *
+ * @copyright Copyright (c) 2016 Thomas Citharel <tcit@tcit.fr>
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+namespace OCA\DAV\CalDAV\Publishing;
+
+use Sabre\DAV\PropFind;
+use Sabre\DAV\INode;
+use Sabre\DAV\Server;
+use Sabre\DAV\ServerPlugin;
+use Sabre\DAV\Exception\NotFound;
+use Sabre\HTTP\RequestInterface;
+use Sabre\HTTP\ResponseInterface;
+use Sabre\CalDAV\Xml\Property\AllowedSharingModes;
+use OCA\DAV\CalDAV\Publishing\Xml\Publisher;
+use OCA\DAV\CalDAV\Calendar;
+use OCP\IURLGenerator;
+use OCP\IConfig;
+
+class PublishPlugin extends ServerPlugin {
+ const NS_CALENDARSERVER = 'http://calendarserver.org/ns/';
+
+ /**
+ * Reference to SabreDAV server object.
+ *
+ * @var \Sabre\DAV\Server
+ */
+ protected $server;
+
+ /**
+ * Config instance to get instance secret.
+ *
+ * @var IConfig
+ */
+ protected $config;
+
+ /**
+ * URL Generator for absolute URLs.
+ *
+ * @var IURLGenerator
+ */
+ protected $urlGenerator;
+
+ /**
+ * PublishPlugin constructor.
+ *
+ * @param IConfig $config
+ * @param IURLGenerator $urlGenerator
+ */
+ public function __construct(IConfig $config, IURLGenerator $urlGenerator) {
+ $this->config = $config;
+ $this->urlGenerator = $urlGenerator;
+ }
+
+ /**
+ * This method should return a list of server-features.
+ *
+ * This is for example 'versioning' and is added to the DAV: header
+ * in an OPTIONS response.
+ *
+ * @return string[]
+ */
+ public function getFeatures() {
+ // May have to be changed to be detected
+ return ['oc-calendar-publishing', 'calendarserver-sharing'];
+ }
+
+ /**
+ * Returns a plugin name.
+ *
+ * Using this name other plugins will be able to access other plugins
+ * using Sabre\DAV\Server::getPlugin
+ *
+ * @return string
+ */
+ public function getPluginName() {
+ return 'oc-calendar-publishing';
+ }
+
+ /**
+ * This initializes the plugin.
+ *
+ * This function is called by Sabre\DAV\Server, after
+ * addPlugin is called.
+ *
+ * This method should set up the required event subscriptions.
+ *
+ * @param Server $server
+ */
+ public function initialize(Server $server) {
+ $this->server = $server;
+
+ $this->server->on('method:POST', [$this, 'httpPost']);
+ $this->server->on('propFind', [$this, 'propFind']);
+ }
+
+ public function propFind(PropFind $propFind, INode $node) {
+ if ($node instanceof Calendar) {
+ $propFind->handle('{'.self::NS_CALENDARSERVER.'}publish-url', function () use ($node) {
+ if ($node->getPublishStatus()) {
+ // We return the publish-url only if the calendar is published.
+ $token = $node->getPublishStatus();
+ $publishUrl = $this->urlGenerator->getAbsoluteURL($this->server->getBaseUri().'public-calendars/').$token;
+
+ return new Publisher($publishUrl, true);
+ }
+ });
+
+ $propFind->handle('{'.self::NS_CALENDARSERVER.'}allowed-sharing-modes', function() use ($node) {
+ return new AllowedSharingModes(!$node->isSubscription(), !$node->isSubscription());
+ });
+ }
+ }
+
+ /**
+ * We intercept this to handle POST requests on calendars.
+ *
+ * @param RequestInterface $request
+ * @param ResponseInterface $response
+ *
+ * @return void|bool
+ */
+ public function httpPost(RequestInterface $request, ResponseInterface $response) {
+ $path = $request->getPath();
+
+ // Only handling xml
+ $contentType = $request->getHeader('Content-Type');
+ if (strpos($contentType, 'application/xml') === false && strpos($contentType, 'text/xml') === false) {
+ return;
+ }
+
+ // Making sure the node exists
+ try {
+ $node = $this->server->tree->getNodeForPath($path);
+ } catch (NotFound $e) {
+ return;
+ }
+
+ $requestBody = $request->getBodyAsString();
+
+ // If this request handler could not deal with this POST request, it
+ // will return 'null' and other plugins get a chance to handle the
+ // request.
+ //
+ // However, we already requested the full body. This is a problem,
+ // because a body can only be read once. This is why we preemptively
+ // re-populated the request body with the existing data.
+ $request->setBody($requestBody);
+
+ $this->server->xml->parse($requestBody, $request->getUrl(), $documentType);
+
+ switch ($documentType) {
+
+ case '{'.self::NS_CALENDARSERVER.'}publish-calendar' :
+
+ // We can only deal with IShareableCalendar objects
+ if (!$node instanceof Calendar) {
+ return;
+ }
+ $this->server->transactionType = 'post-publish-calendar';
+
+ // Getting ACL info
+ $acl = $this->server->getPlugin('acl');
+
+ // If there's no ACL support, we allow everything
+ if ($acl) {
+ $acl->checkPrivileges($path, '{DAV:}write');
+ }
+
+ $node->setPublishStatus(true);
+
+ // iCloud sends back the 202, so we will too.
+ $response->setStatus(202);
+
+ // Adding this because sending a response body may cause issues,
+ // and I wanted some type of indicator the response was handled.
+ $response->setHeader('X-Sabre-Status', 'everything-went-well');
+
+ // Breaking the event chain
+ return false;
+
+ case '{'.self::NS_CALENDARSERVER.'}unpublish-calendar' :
+
+ // We can only deal with IShareableCalendar objects
+ if (!$node instanceof Calendar) {
+ return;
+ }
+ $this->server->transactionType = 'post-unpublish-calendar';
+
+ // Getting ACL info
+ $acl = $this->server->getPlugin('acl');
+
+ // If there's no ACL support, we allow everything
+ if ($acl) {
+ $acl->checkPrivileges($path, '{DAV:}write');
+ }
+
+ $node->setPublishStatus(false);
+
+ $response->setStatus(200);
+
+ // Adding this because sending a response body may cause issues,
+ // and I wanted some type of indicator the response was handled.
+ $response->setHeader('X-Sabre-Status', 'everything-went-well');
+
+ // Breaking the event chain
+ return false;
+
+ }
+ }
+}
diff --git a/apps/dav/lib/CalDAV/Publishing/Xml/Publisher.php b/apps/dav/lib/CalDAV/Publishing/Xml/Publisher.php
new file mode 100644
index 00000000000..1fdba22e9e0
--- /dev/null
+++ b/apps/dav/lib/CalDAV/Publishing/Xml/Publisher.php
@@ -0,0 +1,83 @@
+<?php
+/**
+ * @author Thomas Citharel <tcit@tcit.fr>
+ *
+ * @copyright Copyright (c) 2016 Thomas Citharel <tcit@tcit.fr>
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+namespace OCA\DAV\CalDAV\Publishing\Xml;
+
+use OCA\DAV\CalDAV\Publishing\PublishPlugin as Plugin;
+use Sabre\Xml\Writer;
+use Sabre\Xml\XmlSerializable;
+
+class Publisher implements XmlSerializable {
+
+ /**
+ * @var string $publishUrl
+ */
+ protected $publishUrl;
+
+ /**
+ * @var boolean $isPublished
+ */
+ protected $isPublished;
+
+ /**
+ * @param string $publishUrl
+ * @param boolean $isPublished
+ */
+ function __construct($publishUrl, $isPublished) {
+ $this->publishUrl = $publishUrl;
+ $this->isPublished = $isPublished;
+ }
+
+ /**
+ * @return string
+ */
+ function getValue() {
+ return $this->publishUrl;
+ }
+
+ /**
+ * The xmlSerialize metod is called during xml writing.
+ *
+ * Use the $writer argument to write its own xml serialization.
+ *
+ * An important note: do _not_ create a parent element. Any element
+ * implementing XmlSerializble should only ever write what's considered
+ * its 'inner xml'.
+ *
+ * The parent of the current element is responsible for writing a
+ * containing element.
+ *
+ * This allows serializers to be re-used for different element names.
+ *
+ * If you are opening new elements, you must also close them again.
+ *
+ * @param Writer $writer
+ * @return void
+ */
+ function xmlSerialize(Writer $writer) {
+ if (!$this->isPublished) {
+ // for pre-publish-url
+ $writer->write($this->publishUrl);
+ } else {
+ // for publish-url
+ $writer->writeElement('{DAV:}href', $this->publishUrl);
+ }
+ }
+}
diff --git a/apps/dav/lib/Command/CreateCalendar.php b/apps/dav/lib/Command/CreateCalendar.php
index 0bc6398250e..da1f706a8b8 100644
--- a/apps/dav/lib/Command/CreateCalendar.php
+++ b/apps/dav/lib/Command/CreateCalendar.php
@@ -44,6 +44,7 @@ class CreateCalendar extends Command {
/**
* @param IUserManager $userManager
+ * @param IGroupManager $groupManager
* @param IDBConnection $dbConnection
*/
function __construct(IUserManager $userManager, IGroupManager $groupManager, IDBConnection $dbConnection) {
@@ -74,9 +75,11 @@ class CreateCalendar extends Command {
$this->userManager,
$this->groupManager
);
+ $config = \OC::$server->getConfig();
+ $random = \OC::$server->getSecureRandom();
$name = $input->getArgument('name');
- $caldav = new CalDavBackend($this->dbConnection, $principalBackend, $this->userManager);
+ $caldav = new CalDavBackend($this->dbConnection, $principalBackend, $this->userManager, $config, $random);
$caldav->createCalendar("principals/users/$user", $name, []);
}
}
diff --git a/apps/dav/lib/DAV/PublicAuth.php b/apps/dav/lib/DAV/PublicAuth.php
new file mode 100644
index 00000000000..ffc588c4a56
--- /dev/null
+++ b/apps/dav/lib/DAV/PublicAuth.php
@@ -0,0 +1,92 @@
+<?php
+/**
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ *
+ * @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+namespace OCA\DAV\DAV;
+
+use Sabre\DAV\Auth\Backend\BackendInterface;
+use Sabre\HTTP\RequestInterface;
+use Sabre\HTTP\ResponseInterface;
+
+class PublicAuth implements BackendInterface {
+
+ /** @var string[] */
+ private $publicURLs;
+
+ public function __construct() {
+ $this->publicURLs = [
+ 'public-calendars',
+ 'principals/system/public'
+ ];
+ }
+
+ /**
+ * When this method is called, the backend must check if authentication was
+ * successful.
+ *
+ * The returned value must be one of the following
+ *
+ * [true, "principals/username"]
+ * [false, "reason for failure"]
+ *
+ * If authentication was successful, it's expected that the authentication
+ * backend returns a so-called principal url.
+ *
+ * Examples of a principal url:
+ *
+ * principals/admin
+ * principals/user1
+ * principals/users/joe
+ * principals/uid/123457
+ *
+ * If you don't use WebDAV ACL (RFC3744) we recommend that you simply
+ * return a string such as:
+ *
+ * principals/users/[username]
+ *
+ * @param RequestInterface $request
+ * @param ResponseInterface $response
+ * @return array
+ */
+ function check(RequestInterface $request, ResponseInterface $response) {
+
+ if ($this->isRequestPublic($request)) {
+ return [true, "principals/system/public"];
+ }
+ return [false, "No public access to this resource."];
+ }
+
+ /**
+ * @inheritdoc
+ */
+ function challenge(RequestInterface $request, ResponseInterface $response) {
+ }
+
+ /**
+ * @param RequestInterface $request
+ * @return bool
+ */
+ private function isRequestPublic(RequestInterface $request) {
+ $url = $request->getPath();
+ $matchingUrls = array_filter($this->publicURLs, function ($publicUrl) use ($url) {
+ return strpos($url, $publicUrl, 0) === 0;
+ });
+ return !empty($matchingUrls);
+ }
+}
diff --git a/apps/dav/lib/DAV/SystemPrincipalBackend.php b/apps/dav/lib/DAV/SystemPrincipalBackend.php
index ba7e73f165e..6a71909c6fd 100644
--- a/apps/dav/lib/DAV/SystemPrincipalBackend.php
+++ b/apps/dav/lib/DAV/SystemPrincipalBackend.php
@@ -51,6 +51,10 @@ class SystemPrincipalBackend extends AbstractBackend {
'uri' => 'principals/system/system',
'{DAV:}displayname' => 'system',
];
+ $principals[] = [
+ 'uri' => 'principals/system/public',
+ '{DAV:}displayname' => 'public',
+ ];
}
return $principals;
@@ -73,6 +77,13 @@ class SystemPrincipalBackend extends AbstractBackend {
];
return $principal;
}
+ if ($path === 'principals/system/public') {
+ $principal = [
+ 'uri' => 'principals/system/public',
+ '{DAV:}displayname' => 'public',
+ ];
+ return $principal;
+ }
return null;
}
diff --git a/apps/dav/lib/RootCollection.php b/apps/dav/lib/RootCollection.php
index 974d08bc34f..4c76dc30c3f 100644
--- a/apps/dav/lib/RootCollection.php
+++ b/apps/dav/lib/RootCollection.php
@@ -26,6 +26,7 @@ namespace OCA\DAV;
use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\CalDAV\CalendarRoot;
+use OCA\DAV\CalDAV\PublicCalendarRoot;
use OCA\DAV\CardDAV\AddressBookRoot;
use OCA\DAV\CardDAV\CardDavBackend;
use OCA\DAV\Connector\Sabre\Principal;
@@ -38,10 +39,12 @@ class RootCollection extends SimpleCollection {
public function __construct() {
$config = \OC::$server->getConfig();
+ $random = \OC::$server->getSecureRandom();
+ $userManager = \OC::$server->getUserManager();
$db = \OC::$server->getDatabaseConnection();
$dispatcher = \OC::$server->getEventDispatcher();
$userPrincipalBackend = new Principal(
- \OC::$server->getUserManager(),
+ $userManager,
\OC::$server->getGroupManager()
);
$groupPrincipalBackend = new GroupPrincipalBackend(
@@ -59,9 +62,11 @@ class RootCollection extends SimpleCollection {
$systemPrincipals->disableListing = $disableListing;
$filesCollection = new Files\RootCollection($userPrincipalBackend, 'principals/users');
$filesCollection->disableListing = $disableListing;
- $caldavBackend = new CalDavBackend($db, $userPrincipalBackend, \OC::$server->getUserManager());
+ $caldavBackend = new CalDavBackend($db, $userPrincipalBackend, $userManager, $config, $random);
$calendarRoot = new CalendarRoot($userPrincipalBackend, $caldavBackend, 'principals/users');
$calendarRoot->disableListing = $disableListing;
+ $publicCalendarRoot = new PublicCalendarRoot($caldavBackend);
+ $publicCalendarRoot->disableListing = $disableListing;
$systemTagCollection = new SystemTag\SystemTagsByIdCollection(
\OC::$server->getSystemTagManager(),
@@ -101,6 +106,7 @@ class RootCollection extends SimpleCollection {
$systemPrincipals]),
$filesCollection,
$calendarRoot,
+ $publicCalendarRoot,
new SimpleCollection('addressbooks', [
$usersAddressBookRoot,
$systemAddressBookRoot]),
diff --git a/apps/dav/lib/Server.php b/apps/dav/lib/Server.php
index 9058548489c..d67417a10d5 100644
--- a/apps/dav/lib/Server.php
+++ b/apps/dav/lib/Server.php
@@ -35,6 +35,7 @@ use OCA\DAV\Connector\Sabre\BlockLegacyClientPlugin;
use OCA\DAV\Connector\Sabre\DavAclPlugin;
use OCA\DAV\Connector\Sabre\DummyGetResponsePlugin;
use OCA\DAV\Connector\Sabre\FilesPlugin;
+use OCA\DAV\DAV\PublicAuth;
use OCA\DAV\Files\BrowserErrorPagePlugin;
use OCA\DAV\Files\CustomPropertiesBackend;
use OCP\IRequest;
@@ -78,6 +79,8 @@ class Server {
$this->server->addPlugin(new BlockLegacyClientPlugin(\OC::$server->getConfig()));
$authPlugin = new Plugin();
+ $authPlugin->addBackend($authBackend);
+ $authPlugin->addBackend(new PublicAuth());
$this->server->addPlugin($authPlugin);
// allow setup of additional auth backends
@@ -114,6 +117,10 @@ class Server {
$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()));
+ $this->server->addPlugin(new \OCA\DAV\CalDAV\Publishing\PublishPlugin(
+ \OC::$server->getConfig(),
+ \OC::$server->getUrlGenerator()
+ ));
// addressbook plugins
$this->server->addPlugin(new \OCA\DAV\CardDAV\Plugin());
diff --git a/apps/dav/tests/unit/CalDAV/AbstractCalDavBackendTest.php b/apps/dav/tests/unit/CalDAV/AbstractCalDavBackendTest.php
index 0e2e1b0ee51..2559ecbbf89 100644
--- a/apps/dav/tests/unit/CalDAV/AbstractCalDavBackendTest.php
+++ b/apps/dav/tests/unit/CalDAV/AbstractCalDavBackendTest.php
@@ -28,6 +28,8 @@ use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\CalDAV\Calendar;
use OCA\DAV\Connector\Sabre\Principal;
use OCP\IL10N;
+use OCP\IConfig;
+use OCP\Security\ISecureRandom;
use Sabre\CalDAV\Xml\Property\SupportedCalendarComponentSet;
use Sabre\DAV\PropPatch;
use Sabre\DAV\Xml\Property\Href;
@@ -51,6 +53,12 @@ abstract class AbstractCalDavBackendTest extends TestCase {
/** @var \OCP\IUserManager|\PHPUnit_Framework_MockObject_MockObject */
protected $userManager;
+
+ /** var OCP\IConfig */
+ protected $config;
+
+ /** @var ISecureRandom */
+ private $random;
const UNIT_TEST_USER = 'principals/users/caldav-unit-test';
const UNIT_TEST_USER1 = 'principals/users/caldav-unit-test1';
@@ -75,8 +83,9 @@ abstract class AbstractCalDavBackendTest extends TestCase {
->willReturn([self::UNIT_TEST_GROUP]);
$db = \OC::$server->getDatabaseConnection();
- $this->backend = new CalDavBackend($db, $this->principal, $this->userManager);
-
+ $this->config = \OC::$server->getConfig();
+ $this->random = \OC::$server->getSecureRandom();
+ $this->backend = new CalDavBackend($db, $this->principal, $this->userManager, $this->config, $this->random);
$this->tearDown();
}
diff --git a/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php b/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php
index 1a5673161de..8349d98cd94 100644
--- a/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php
+++ b/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php
@@ -334,6 +334,35 @@ EOD;
$this->assertEquals($event, $changes['added'][0]);
}
+ public function testPublications() {
+ $this->backend->createCalendar(self::UNIT_TEST_USER, 'Example', []);
+
+ $calendarInfo = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER)[0];
+
+ $l10n = $this->getMockBuilder('\OCP\IL10N')
+ ->disableOriginalConstructor()->getMock();
+
+ $calendar = new Calendar($this->backend, $calendarInfo, $l10n);
+ $calendar->setPublishStatus(true);
+ $this->assertNotEquals(false, $calendar->getPublishStatus());
+
+ $publicCalendars = $this->backend->getPublicCalendars();
+ $this->assertEquals(1, count($publicCalendars));
+ $this->assertEquals(true, $publicCalendars[0]['{http://owncloud.org/ns}public']);
+
+ $publicCalendarURI = $publicCalendars[0]['uri'];
+ $publicCalendar = $this->backend->getPublicCalendar($publicCalendarURI);
+ $this->assertEquals(true, $publicCalendar['{http://owncloud.org/ns}public']);
+
+ $calendar->setPublishStatus(false);
+ $this->assertEquals(false, $calendar->getPublishStatus());
+
+ $publicCalendarURI = md5($this->config->getSystemValue('secret', '') . $calendar->getResourceId());
+ $this->setExpectedException('Sabre\DAV\Exception\NotFound');
+ $publicCalendar = $this->backend->getPublicCalendar($publicCalendarURI);
+
+ }
+
public function testSubscriptions() {
$id = $this->backend->createSubscription(self::UNIT_TEST_USER, 'Subscription', [
'{http://calendarserver.org/ns/}source' => new Href('test-source'),
diff --git a/apps/dav/tests/unit/CalDAV/PublicCalendarRootTest.php b/apps/dav/tests/unit/CalDAV/PublicCalendarRootTest.php
new file mode 100644
index 00000000000..6dfec6d7e1f
--- /dev/null
+++ b/apps/dav/tests/unit/CalDAV/PublicCalendarRootTest.php
@@ -0,0 +1,122 @@
+<?php
+
+namespace OCA\DAV\Tests\unit\CalDAV;
+
+use OCA\DAV\CalDAV\Calendar;
+use OCA\DAV\Connector\Sabre\Principal;
+use OCP\IL10N;
+use OCA\DAV\CalDAV\CalDavBackend;
+use OCA\DAV\CalDAV\PublicCalendarRoot;
+use OCP\IUserManager;
+use OCP\Security\ISecureRandom;
+use Test\TestCase;
+
+/**
+ * Class PublicCalendarRootTest
+ *
+ * @group DB
+ *
+ * @package OCA\DAV\Tests\unit\CalDAV
+ */
+class PublicCalendarRootTest extends TestCase {
+
+ const UNIT_TEST_USER = 'principals/users/caldav-unit-test';
+ /** @var CalDavBackend */
+ private $backend;
+ /** @var PublicCalendarRoot */
+ private $publicCalendarRoot;
+ /** @var IL10N */
+ private $l10n;
+ /** @var IUserManager */
+ private $userManager;
+ /** @var Principal */
+ private $principal;
+ /** var IConfig */
+ protected $config;
+ /** @var ISecureRandom */
+ private $random;
+
+ public function setUp() {
+ parent::setUp();
+
+ $db = \OC::$server->getDatabaseConnection();
+ $this->principal = $this->getMockBuilder('OCA\DAV\Connector\Sabre\Principal')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->config = \OC::$server->getConfig();
+ $this->userManager = $this->getMockBuilder('\OCP\IUserManager')->getMock();
+ $this->random = \OC::$server->getSecureRandom();
+
+ $this->backend = new CalDavBackend(
+ $db,
+ $this->principal,
+ $this->userManager,
+ $this->config,
+ $this->random
+ );
+
+ $this->publicCalendarRoot = new PublicCalendarRoot($this->backend);
+
+ $this->l10n = $this->getMockBuilder('\OCP\IL10N')
+ ->disableOriginalConstructor()->getMock();
+ }
+
+ public function tearDown() {
+ parent::tearDown();
+
+ if (is_null($this->backend)) {
+ return;
+ }
+ $books = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER);
+ foreach ($books as $book) {
+ $this->backend->deleteCalendar($book['id']);
+ }
+ }
+
+ public function testGetName() {
+ $name = $this->publicCalendarRoot->getName();
+ $this->assertEquals('public-calendars', $name);
+ }
+
+ public function testGetChild() {
+
+ $calendar = $this->createPublicCalendar();
+
+ $publicCalendars = $this->backend->getPublicCalendars();
+ $this->assertEquals(1, count($publicCalendars));
+ $this->assertEquals(true, $publicCalendars[0]['{http://owncloud.org/ns}public']);
+
+ $publicCalendarURI = $publicCalendars[0]['uri'];
+
+ $calendarResult = $this->publicCalendarRoot->getChild($publicCalendarURI);
+ $this->assertEquals($calendar, $calendarResult);
+ }
+
+ public function testGetChildren() {
+ $this->createPublicCalendar();
+
+ $publicCalendars = $this->backend->getPublicCalendars();
+
+ $calendarResults = $this->publicCalendarRoot->getChildren();
+
+ $this->assertEquals(1, count($calendarResults));
+ $this->assertEquals(new Calendar($this->backend, $publicCalendars[0], $this->l10n), $calendarResults[0]);
+ }
+
+ /**
+ * @return Calendar
+ */
+ protected function createPublicCalendar() {
+ $this->backend->createCalendar(self::UNIT_TEST_USER, 'Example', []);
+
+ $calendarInfo = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER)[0];
+ $calendar = new Calendar($this->backend, $calendarInfo, $this->l10n);
+ $publicUri = $calendar->setPublishStatus(true);
+
+ $calendarInfo = $this->backend->getPublicCalendar($publicUri);
+ $calendar = new Calendar($this->backend, $calendarInfo, $this->l10n);
+
+ return $calendar;
+ }
+
+}
diff --git a/apps/dav/tests/unit/CalDAV/Publishing/PublisherTest.php b/apps/dav/tests/unit/CalDAV/Publishing/PublisherTest.php
new file mode 100644
index 00000000000..b6b1e4381b5
--- /dev/null
+++ b/apps/dav/tests/unit/CalDAV/Publishing/PublisherTest.php
@@ -0,0 +1,56 @@
+<?php
+
+namespace OCA\DAV\Tests\unit\CalDAV\Publishing;
+
+use OCA\DAV\CalDAV\Publishing\Xml\Publisher;
+use Sabre\Xml\Writer;
+
+class PublisherTest extends \PHPUnit_Framework_TestCase {
+
+ const NS_CALENDARSERVER = 'http://calendarserver.org/ns/';
+
+ public function testSerializePublished() {
+ $publish = new Publisher('urltopublish', true);
+
+ $xml = $this->write([
+ '{' . self::NS_CALENDARSERVER . '}publish-url' => $publish,
+ ]);
+
+ $this->assertEquals('urltopublish', $publish->getValue());
+
+ $this->assertXmlStringEqualsXmlString(
+ '<?xml version="1.0"?>
+ <x1:publish-url xmlns:d="DAV:" xmlns:x1="' . self::NS_CALENDARSERVER . '">
+ <d:href>urltopublish</d:href>
+ </x1:publish-url>', $xml);
+ }
+
+ public function testSerializeNotPublished() {
+ $publish = new Publisher('urltopublish', false);
+
+ $xml = $this->write([
+ '{' . self::NS_CALENDARSERVER . '}pre-publish-url' => $publish,
+ ]);
+
+ $this->assertEquals('urltopublish', $publish->getValue());
+
+ $this->assertXmlStringEqualsXmlString(
+ '<?xml version="1.0"?>
+ <x1:pre-publish-url xmlns:d="DAV:" xmlns:x1="' . self::NS_CALENDARSERVER . '">urltopublish</x1:pre-publish-url>', $xml);
+ }
+
+
+ protected $elementMap = [];
+ protected $namespaceMap = ['DAV:' => 'd'];
+ protected $contextUri = '/';
+
+ private function write($input) {
+ $writer = new Writer();
+ $writer->contextUri = $this->contextUri;
+ $writer->namespaceMap = $this->namespaceMap;
+ $writer->openMemory();
+ $writer->setIndent(true);
+ $writer->write($input);
+ return $writer->outputMemory();
+ }
+}
diff --git a/apps/dav/tests/unit/CalDAV/Publishing/PublishingTest.php b/apps/dav/tests/unit/CalDAV/Publishing/PublishingTest.php
new file mode 100644
index 00000000000..69de507dac5
--- /dev/null
+++ b/apps/dav/tests/unit/CalDAV/Publishing/PublishingTest.php
@@ -0,0 +1,82 @@
+<?php
+
+namespace OCA\DAV\Tests\unit\CalDAV\Publishing;
+
+use OCA\DAV\CalDAV\Calendar;
+use OCA\DAV\CalDAV\Publishing\PublishPlugin;
+use OCP\IRequest;
+use OCP\IURLGenerator;
+use OCP\IConfig;
+use Sabre\DAV\Server;
+use Sabre\DAV\SimpleCollection;
+use Sabre\HTTP\Request;
+use Sabre\HTTP\Response;
+use Test\TestCase;
+
+class PluginTest extends TestCase {
+
+ /** @var PublishPlugin */
+ private $plugin;
+ /** @var Server */
+ private $server;
+ /** @var Calendar | \PHPUnit_Framework_MockObject_MockObject */
+ private $book;
+ /** @var IConfig | \PHPUnit_Framework_MockObject_MockObject */
+ private $config;
+ /** @var IURLGenerator | \PHPUnit_Framework_MockObject_MockObject */
+ private $urlGenerator;
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->config = $this->getMockBuilder('\OCP\IConfig')->
+ disableOriginalConstructor()->
+ getMock();
+ $this->config->expects($this->any())->method('getSystemValue')
+ ->with($this->equalTo('secret'))
+ ->willReturn('mysecret');
+
+ $this->urlGenerator = $this->getMockBuilder('OCP\IURLGenerator')->
+ disableOriginalConstructor()->
+ getMock();
+
+ /** @var IRequest $request */
+ $this->plugin = new PublishPlugin($this->config, $this->urlGenerator);
+
+ $root = new SimpleCollection('calendars');
+ $this->server = new Server($root);
+ /** @var SimpleCollection $node */
+ $this->book = $this->getMockBuilder('OCA\DAV\CalDAV\Calendar')->
+ disableOriginalConstructor()->
+ getMock();
+ $this->book->method('getName')->willReturn('cal1');
+ $root->addChild($this->book);
+ $this->plugin->initialize($this->server);
+ }
+
+ public function testPublishing() {
+
+ $this->book->expects($this->once())->method('setPublishStatus')->with(true);
+
+ // setup request
+ $request = new Request();
+ $request->addHeader('Content-Type', 'application/xml');
+ $request->setUrl('cal1');
+ $request->setBody('<o:publish-calendar xmlns:o="http://calendarserver.org/ns/"/>');
+ $response = new Response();
+ $this->plugin->httpPost($request, $response);
+ }
+
+ public function testUnPublishing() {
+
+ $this->book->expects($this->once())->method('setPublishStatus')->with(false);
+
+ // setup request
+ $request = new Request();
+ $request->addHeader('Content-Type', 'application/xml');
+ $request->setUrl('cal1');
+ $request->setBody('<o:unpublish-calendar xmlns:o="http://calendarserver.org/ns/"/>');
+ $response = new Response();
+ $this->plugin->httpPost($request, $response);
+ }
+}
diff --git a/apps/dav/tests/unit/DAV/SystemPrincipalBackendTest.php b/apps/dav/tests/unit/DAV/SystemPrincipalBackendTest.php
index 3a5566e8f70..71bdfb3b2bc 100644
--- a/apps/dav/tests/unit/DAV/SystemPrincipalBackendTest.php
+++ b/apps/dav/tests/unit/DAV/SystemPrincipalBackendTest.php
@@ -45,7 +45,12 @@ class SystemPrincipalBackendTest extends TestCase {
[[[
'uri' => 'principals/system/system',
'{DAV:}displayname' => 'system',
- ]], 'principals/system'],
+ ],
+ [
+ 'uri' => 'principals/system/public',
+ '{DAV:}displayname' => 'public',
+ ]
+ ], 'principals/system'],
];
}