@@ -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) { |
@@ -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 |
@@ -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']; |
@@ -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; | |||
} | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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()); |