diff options
author | Thomas Citharel <tcit@tcit.fr> | 2016-07-06 12:19:46 +0200 |
---|---|---|
committer | Lukas Reschke <lukas@statuscode.ch> | 2016-09-26 11:55:33 +0200 |
commit | 69d3601dcbb17ea9e2d868144159867a79d8e25c (patch) | |
tree | ffe81147304b66465c9bb5669397864f6e56542e /apps/dav/lib | |
parent | 244de6451b22a1288d3ef698f48fb9c4e78bf15f (diff) | |
download | nextcloud-server-69d3601dcbb17ea9e2d868144159867a79d8e25c.tar.gz nextcloud-server-69d3601dcbb17ea9e2d868144159867a79d8e25c.zip |
Proper work on Publishing
Diffstat (limited to 'apps/dav/lib')
-rw-r--r-- | apps/dav/lib/CalDAV/CalDavBackend.php | 37 | ||||
-rw-r--r-- | apps/dav/lib/CalDAV/Calendar.php | 24 | ||||
-rw-r--r-- | apps/dav/lib/CalDAV/Publishing/PublishPlugin.php | 187 | ||||
-rw-r--r-- | apps/dav/lib/CalDAV/Publishing/Xml/Publisher.php | 55 | ||||
-rw-r--r-- | apps/dav/lib/Server.php | 1 |
5 files changed, 303 insertions, 1 deletions
diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php index 17479c490a9..ed311fa0ded 100644 --- a/apps/dav/lib/CalDAV/CalDavBackend.php +++ b/apps/dav/lib/CalDAV/CalDavBackend.php @@ -1473,6 +1473,43 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription } /** + * @param boolean $value + * @param \OCA\DAV\CalDAV\Calendar $calendar + */ + public function setPublishStatus($value, $calendar) { + $query = $this->db->getQueryBuilder(); + if ($value) { + $query->insert('dav_shares') + ->values([ + 'principaluri' => $query->createNamedParameter($calendar->getPrincipalURI()), + 'type' => $query->createNamedParameter('calendar'), + 'access' => $query->createNamedParameter(self::CLASSIFICATION_PUBLIC), + 'resourceid' => $query->createNamedParameter($calendar->getResourceId()) + ]); + } else { + $query->delete('dav_shares') + ->Where($query->expr()->eq('resourceid', $query->createNamedParameter($calendar->getResourceId()))) + ->andWhere($query->expr()->eq('access', $query->createNamedParameter(self::CLASSIFICATION_PUBLIC))); + } + $query->execute(); + } + + /** + * @param \OCA\DAV\CalDAV\Calendar $calendar + * @return boolean + */ + public function getPublishStatus($calendar) { + $query = $this->db->getQueryBuilder(); + $result = $query->select(['principaluri', 'access']) + ->from('dav_shares') + ->where($query->expr()->eq('resourceid', $query->createNamedParameter($calendar->getResourceId()))) + ->andWhere($query->expr()->eq('type', $query->createNamedParameter(self::CLASSIFICATION_PUBLIC))) + ->execute(); + + return count($result->fetch()) > 0; + } + + /** * @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..f5607c65272 100644 --- a/apps/dav/lib/CalDAV/Calendar.php +++ b/apps/dav/lib/CalDAV/Calendar.php @@ -24,13 +24,14 @@ namespace OCA\DAV\CalDAV; use OCA\DAV\DAV\Sharing\IShareable; +use Sabre\CalDAV\IShareableCalendar; use OCP\IL10N; use Sabre\CalDAV\Backend\BackendInterface; use Sabre\DAV\Exception\Forbidden; use Sabre\DAV\Exception\NotFound; use Sabre\DAV\PropPatch; -class Calendar extends \Sabre\CalDAV\Calendar implements IShareable { +class Calendar extends \Sabre\CalDAV\Calendar implements IShareable, IShareableCalendar { public function __construct(BackendInterface $caldavBackend, $calendarInfo, IL10N $l10n) { parent::__construct($caldavBackend, $calendarInfo); @@ -89,6 +90,13 @@ class Calendar extends \Sabre\CalDAV\Calendar implements IShareable { return $this->calendarInfo['id']; } + /** + * @return str + */ + public function getPrincipalURI() { + return $this->calendarInfo['principaluri']; + } + function getACL() { $acl = [ [ @@ -236,6 +244,20 @@ class Calendar extends \Sabre\CalDAV\Calendar implements IShareable { return $uris; } + /** + * @param boolean $value + */ + function setPublishStatus($value) { + $this->caldavBackend->setPublishStatus($value, $this); + } + + /** + * @return boolean $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']; diff --git a/apps/dav/lib/CalDAV/Publishing/PublishPlugin.php b/apps/dav/lib/CalDAV/Publishing/PublishPlugin.php new file mode 100644 index 00000000000..e6a5f0eb32b --- /dev/null +++ b/apps/dav/lib/CalDAV/Publishing/PublishPlugin.php @@ -0,0 +1,187 @@ +<?php + +namespace OCA\DAV\CalDAV\Publishing; + +//use OCA\DAV\CalDAV\Publishing\Xml; + +use Sabre\DAV\PropFind; +use Sabre\DAV\INode; +use OCP\IRequest; +use Sabre\CalDAV\IShareableCalendar; +use Sabre\DAV\Server; +use Sabre\DAV\ServerPlugin; +use Sabre\HTTP\RequestInterface; +use Sabre\HTTP\ResponseInterface; +use OCA\DAV\CalDAV\Publishing\Xml\Publisher; + +class PublishPlugin extends ServerPlugin +{ + const NS_OWNCLOUD = 'http://owncloud.org/ns'; + const NS_CALENDARSERVER = 'http://calendarserver.org/ns/'; + + /** + * Reference to SabreDAV server object. + * + * @var \Sabre\DAV\Server + */ + protected $server; + + /** + * 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() + { + return ['oc-calendar-publishing']; + } + + /** + * 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']); + } + + function propFind(PropFind $propFind, INode $node) { + if ($node instanceof IShareableCalendar) { + $token = md5(\OC::$server->getConfig()->getSystemValue('secret','') . $node->getName()); + // $propFind->handle('{' . self::NS_CALENDARSERVER . '}publish-url', function() use ($node, $token) { + // return new Publisher($token); + // }); + + $propFind->handle('{' . self::NS_CALENDARSERVER . '}pre-publish-url', function() use ($node, $token) { + if ($node->getPublishStatus()) { + return new Publisher($token); + } + }); + } + } + + /** + * We intercept this to handle POST requests on calendars. + * + * @param RequestInterface $request + * @param ResponseInterface $response + * @return null|bool + */ + 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 (DAV\Exception\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); + + $message = $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 IShareableCalendar) { + 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 IShareableCalendar) { + 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..597652d0ef1 --- /dev/null +++ b/apps/dav/lib/CalDAV/Publishing/Xml/Publisher.php @@ -0,0 +1,55 @@ +<?php + +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 $publishUrl + */ + protected $publishUrl; + + /** + * @param str $publishUrl + */ + function __construct($publishUrl) { + $this->publishUrl = $publishUrl; + } + + /** + * @return str + */ + 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) { + + $cs = '{' . Plugin::NS_CALENDARSERVER . '}'; + $writer->write($this->publishUrl); + + } +} diff --git a/apps/dav/lib/Server.php b/apps/dav/lib/Server.php index 9058548489c..defaddbd642 100644 --- a/apps/dav/lib/Server.php +++ b/apps/dav/lib/Server.php @@ -114,6 +114,7 @@ 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()); // addressbook plugins $this->server->addPlugin(new \OCA\DAV\CardDAV\Plugin()); |