]> source.dussan.org Git - nextcloud-server.git/commitdiff
Proper work on Publishing
authorThomas Citharel <tcit@tcit.fr>
Wed, 6 Jul 2016 10:19:46 +0000 (12:19 +0200)
committerLukas Reschke <lukas@statuscode.ch>
Mon, 26 Sep 2016 09:55:33 +0000 (11:55 +0200)
apps/dav/appinfo/v1/caldav.php
apps/dav/lib/CalDAV/CalDavBackend.php
apps/dav/lib/CalDAV/Calendar.php
apps/dav/lib/CalDAV/Publishing/PublishPlugin.php [new file with mode: 0644]
apps/dav/lib/CalDAV/Publishing/Xml/Publisher.php [new file with mode: 0644]
apps/dav/lib/Server.php

index 13b4d3119ca9166fd17c52075519df69fc6baef8..4ac88ec328ac65cb2845e9417efb4e5c3dc0a309 100644 (file)
@@ -71,6 +71,7 @@ $server->setBaseUri($baseuri);
 $server->addPlugin(new MaintenancePlugin());
 $server->addPlugin(new \Sabre\DAV\Auth\Plugin($authBackend, 'ownCloud'));
 $server->addPlugin(new \Sabre\CalDAV\Plugin());
+$server->addPlugin(new \OCA\DAV\CalDAV\Publishing\PublishPlugin());
 
 $server->addPlugin(new LegacyDAVACL());
 if ($debugging) {
index 17479c490a9e5760eb494a3f9676354b5b60e9f0..ed311fa0dedfa72bf424a875cb3b3261c4c54b0e 100644 (file)
@@ -1472,6 +1472,43 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
                return $this->sharingBackend->getShares($resourceId);
        }
 
+       /**
+        * @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
index 821a71babb11f5c7909807bca77319118e335abd..f5607c6527252a056980d532570245bdeaf1efd3 100644 (file)
 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 (file)
index 0000000..e6a5f0e
--- /dev/null
@@ -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 (file)
index 0000000..597652d
--- /dev/null
@@ -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);
+
+  }
+}
index 9058548489ce9c6ebcfd3174c8400d7c3fd1c8a4..defaddbd6423cc15b74ff9b66fcdbc621e687464 100644 (file)
@@ -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());