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
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);
return $this->calendarInfo['id'];
}
+ /**
+ * @return str
+ */
+ public function getPrincipalURI() {
+ return $this->calendarInfo['principaluri'];
+ }
+
function getACL() {
$acl = [
[
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'];
--- /dev/null
+<?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;
+
+ }
+
+
+
+ }
+}
--- /dev/null
+<?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);
+
+ }
+}