* @param string $element
*/
private function unshare($addressBookUri, $element) {
- $user = $element['href'];
- $parts = explode(':', $user, 2);
+ $parts = explode(':', $element, 2);
if ($parts[0] !== 'principal') {
return;
}
use Sabre\DAV\Server;
use Sabre\DAV\ServerPlugin;
use Sabre\DAV\XMLUtil;
+use Sabre\DAVACL\IACL;
use Sabre\HTTP\RequestInterface;
use Sabre\HTTP\ResponseInterface;
class Plugin extends ServerPlugin {
+ /** @var Auth */
+ private $auth;
+
+ /** @var IRequest */
+ private $request;
+
+ /**
+ * Plugin constructor.
+ *
+ * @param Auth $authBackEnd
+ * @param IRequest $request
+ */
public function __construct(Auth $authBackEnd, IRequest $request) {
$this->auth = $authBackEnd;
$this->request = $request;
function initialize(Server $server) {
$this->server = $server;
$server->resourceTypeMapping['OCA\\DAV\CardDAV\\ISharedAddressbook'] = '{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}shared';
+ $this->server->xml->elementMap['{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}share'] = 'OCA\\DAV\\CardDAV\\Sharing\\Xml\\ShareRequest';
$this->server->on('method:POST', [$this, 'httpPost']);
}
// re-populated the request body with the existing data.
$request->setBody($requestBody);
- $dom = XMLUtil::loadDOMDocument($requestBody);
-
- $documentType = XMLUtil::toClarkNotation($dom->firstChild);
+ $message = $this->server->xml->parse($requestBody, $request->getUrl(), $documentType);
switch ($documentType) {
return;
}
- $this->server->transactionType = 'post-calendar-share';
+ $this->server->transactionType = 'post-oc-addressbook-share';
// Getting ACL info
$acl = $this->server->getPlugin('acl');
// If there's no ACL support, we allow everything
if ($acl) {
+ /** @var \Sabre\DAVACL\Plugin $acl */
$acl->checkPrivileges($path, '{DAV:}write');
}
- $mutations = $this->parseShareRequest($dom);
-
- $node->updateShares($mutations[0], $mutations[1]);
+ $node->updateShares($message->set, $message->remove);
$response->setStatus(200);
// Adding this because sending a response body may cause issues,
}
}
- /**
- * Parses the 'share' POST request.
- *
- * This method returns an array, containing two arrays.
- * The first array is a list of new sharees. Every element is a struct
- * containing a:
- * * href element. (usually a mailto: address)
- * * commonName element (often a first and lastname, but can also be
- * false)
- * * readOnly (true or false)
- * * summary (A description of the share, can also be false)
- *
- * The second array is a list of sharees that are to be removed. This is
- * just a simple array with 'hrefs'.
- *
- * @param \DOMDocument $dom
- * @return array
- */
- function parseShareRequest(\DOMDocument $dom) {
-
- $xpath = new \DOMXPath($dom);
- $xpath->registerNamespace('cs', \Sabre\CardDAV\Plugin::NS_CARDDAV);
- $xpath->registerNamespace('d', 'urn:DAV');
-
- $set = [];
- $elems = $xpath->query('cs:set');
-
- for ($i = 0; $i < $elems->length; $i++) {
-
- $xset = $elems->item($i);
- $set[] = [
- 'href' => $xpath->evaluate('string(d:href)', $xset),
- 'commonName' => $xpath->evaluate('string(cs:common-name)', $xset),
- 'summary' => $xpath->evaluate('string(cs:summary)', $xset),
- 'readOnly' => $xpath->evaluate('boolean(cs:read)', $xset) !== false
- ];
-
- }
-
- $remove = [];
- $elems = $xpath->query('cs:remove');
-
- for ($i = 0; $i < $elems->length; $i++) {
-
- $xremove = $elems->item($i);
- $remove[] = $xpath->evaluate('string(d:href)', $xremove);
-
- }
-
- return [$set, $remove];
-
- }
-
private function protectAgainstCSRF() {
$user = $this->auth->getCurrentUser();
if ($this->auth->isDavAuthenticated($user)) {
--- /dev/null
+<?php
+
+namespace OCA\DAV\CardDAV\Sharing\Xml;
+
+use Sabre\Xml\Reader;
+use Sabre\Xml\XmlDeserializable;
+
+class ShareRequest implements XmlDeserializable {
+
+ public $set = [];
+
+ public $remove = [];
+
+ /**
+ * Constructor
+ *
+ * @param array $set
+ * @param array $remove
+ */
+ function __construct(array $set, array $remove) {
+
+ $this->set = $set;
+ $this->remove = $remove;
+
+ }
+
+ static function xmlDeserialize(Reader $reader) {
+
+ $elems = $reader->parseInnerTree([
+ '{' . \Sabre\CardDAV\Plugin::NS_CARDDAV. '}set' => 'Sabre\\Xml\\Element\\KeyValue',
+ '{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}remove' => 'Sabre\\Xml\\Element\\KeyValue',
+ ]);
+
+ $set = [];
+ $remove = [];
+
+ foreach ($elems as $elem) {
+ switch ($elem['name']) {
+
+ case '{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}set' :
+ $sharee = $elem['value'];
+
+ $sumElem = '{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}summary';
+ $commonName = '{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}common-name';
+
+ $set[] = [
+ 'href' => $sharee['{DAV:}href'],
+ 'commonName' => isset($sharee[$commonName]) ? $sharee[$commonName] : null,
+ 'summary' => isset($sharee[$sumElem]) ? $sharee[$sumElem] : null,
+ 'readOnly' => !array_key_exists('{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}read-write', $sharee),
+ ];
+ break;
+
+ case '{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}remove' :
+ $remove[] = $elem['value']['{DAV:}href'];
+ break;
+
+ }
+ }
+
+ return new self($set, $remove);
+
+ }
+
+}
$books = $this->backend->getAddressBooksForUser('principals/best-friend');
$this->assertEquals(1, count($books));
- $this->backend->updateShares('Example', [], [['href' => 'principal:principals/best-friend']]);
+ $this->backend->updateShares('Example', [], ['principal:principals/best-friend']);
$shares = $this->backend->getShares('Example');
$this->assertEquals(0, count($shares));
--- /dev/null
+<?php
+/**
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ *
+ * @copyright Copyright (c) 2015, 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\Tests\Unit\CardDAV;
+
+
+use OCA\DAV\CardDAV\Sharing\IShareableAddressBook;
+use OCA\DAV\CardDAV\Sharing\Plugin;
+use OCA\DAV\Connector\Sabre\Auth;
+use OCP\IRequest;
+use Sabre\DAV\Server;
+use Sabre\DAV\SimpleCollection;
+use Sabre\HTTP\Request;
+use Sabre\HTTP\Response;
+use Test\TestCase;
+
+class PluginTest extends TestCase {
+
+ /** @var Plugin */
+ private $plugin;
+ /** @var Server */
+ private $server;
+ /** @var IShareableAddressBook | \PHPUnit_Framework_MockObject_MockObject */
+ private $book;
+
+ public function setUp() {
+ parent::setUp();
+
+ /** @var Auth | \PHPUnit_Framework_MockObject_MockObject $authBackend */
+ $authBackend = $this->getMockBuilder('OCA\DAV\Connector\Sabre\Auth')->disableOriginalConstructor()->getMock();
+ $authBackend->method('isDavAuthenticated')->willReturn(true);
+
+ /** @var IRequest $request */
+ $request = $this->getMockBuilder('OCP\IRequest')->disableOriginalConstructor()->getMock();
+ $this->plugin = new Plugin($authBackend, $request);
+
+ $root = new SimpleCollection('root');
+ $this->server = new \Sabre\DAV\Server($root);
+ /** @var SimpleCollection $node */
+ $this->book = $this->getMockBuilder('OCA\DAV\CardDAV\Sharing\IShareableAddressBook')->disableOriginalConstructor()->getMock();
+ $this->book->method('getName')->willReturn('addressbook1.vcf');
+ $root->addChild($this->book);
+ $this->plugin->initialize($this->server);
+ }
+
+ public function testSharing() {
+
+ $this->book->expects($this->once())->method('updateShares')->with([[
+ 'href' => 'principal:principals/admin',
+ 'commonName' => null,
+ 'summary' => null,
+ 'readOnly' => false
+ ]], ['mailto:wilfredo@example.com']);
+
+ // setup request
+ $request = new Request();
+ $request->addHeader('Content-Type', 'application/xml');
+ $request->setUrl('addressbook1.vcf');
+ $request->setBody('<?xml version="1.0" encoding="utf-8" ?><CS:share xmlns:D="DAV:" xmlns:CS="urn:ietf:params:xml:ns:carddav"><CS:set><D:href>principal:principals/admin</D:href><CS:read-write/></CS:set> <CS:remove><D:href>mailto:wilfredo@example.com</D:href></CS:remove></CS:share>');
+ $response = new Response();
+ $this->plugin->httpPost($request, $response);
+ }
+}