summaryrefslogtreecommitdiffstats
path: root/apps/dav/lib
diff options
context:
space:
mode:
Diffstat (limited to 'apps/dav/lib')
-rw-r--r--apps/dav/lib/carddav/addressbookimpl.php219
-rw-r--r--apps/dav/lib/carddav/carddavbackend.php223
-rw-r--r--apps/dav/lib/carddav/sharing/plugin.php78
-rw-r--r--apps/dav/lib/carddav/sharing/xml/sharerequest.php65
-rw-r--r--apps/dav/lib/connector/sabre/auth.php2
-rw-r--r--apps/dav/lib/connector/sabre/file.php2
-rw-r--r--apps/dav/lib/connector/sabre/filesplugin.php11
-rw-r--r--apps/dav/lib/connector/sabre/objecttree.php2
-rw-r--r--apps/dav/lib/rootcollection.php4
-rw-r--r--apps/dav/lib/systemtag/systemtagsbyidcollection.php14
-rw-r--r--apps/dav/lib/systemtag/systemtagsobjecttypecollection.php17
11 files changed, 563 insertions, 74 deletions
diff --git a/apps/dav/lib/carddav/addressbookimpl.php b/apps/dav/lib/carddav/addressbookimpl.php
new file mode 100644
index 00000000000..838ef5aec65
--- /dev/null
+++ b/apps/dav/lib/carddav/addressbookimpl.php
@@ -0,0 +1,219 @@
+<?php
+/**
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ * @author Björn Schießle <schiessle@owncloud.com>
+ *
+ * @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\CardDAV;
+
+use OCP\Constants;
+use OCP\IAddressBook;
+use Sabre\VObject\Component\VCard;
+use Sabre\VObject\Property\Text;
+use Sabre\VObject\Reader;
+use Sabre\VObject\UUIDUtil;
+
+class AddressBookImpl implements IAddressBook {
+
+ /** @var CardDavBackend */
+ private $backend;
+
+ /** @var array */
+ private $addressBookInfo;
+
+ /** @var AddressBook */
+ private $addressBook;
+
+ /**
+ * AddressBookImpl constructor.
+ *
+ * @param AddressBook $addressBook
+ * @param array $addressBookInfo
+ * @param CardDavBackend $backend
+ */
+ public function __construct(
+ AddressBook $addressBook,
+ array $addressBookInfo,
+ CardDavBackend $backend) {
+
+ $this->addressBook = $addressBook;
+ $this->addressBookInfo = $addressBookInfo;
+ $this->backend = $backend;
+ }
+
+ /**
+ * @return string defining the technical unique key
+ * @since 5.0.0
+ */
+ public function getKey() {
+ return $this->addressBookInfo['id'];
+ }
+
+ /**
+ * In comparison to getKey() this function returns a human readable (maybe translated) name
+ *
+ * @return mixed
+ * @since 5.0.0
+ */
+ public function getDisplayName() {
+ return $this->addressBookInfo['{DAV:}displayname'];
+ }
+
+ /**
+ * @param string $pattern which should match within the $searchProperties
+ * @param array $searchProperties defines the properties within the query pattern should match
+ * @param array $options - for future use. One should always have options!
+ * @return array an array of contacts which are arrays of key-value-pairs
+ * @since 5.0.0
+ */
+ public function search($pattern, $searchProperties, $options) {
+ $result = $this->backend->search($this->getKey(), $pattern, $searchProperties);
+
+ $vCards = [];
+ foreach ($result as $cardData) {
+ $vCards[] = $this->vCard2Array($this->readCard($cardData));
+ }
+
+ return $vCards;
+ }
+
+ /**
+ * @param array $properties this array if key-value-pairs defines a contact
+ * @return array an array representing the contact just created or updated
+ * @since 5.0.0
+ */
+ public function createOrUpdate($properties) {
+ $update = false;
+ if (!isset($properties['UID'])) { // create a new contact
+ $uid = $this->createUid();
+ $uri = $uid . '.vcf';
+ $vCard = $this->createEmptyVCard($uid);
+ } else { // update existing contact
+ $uid = $properties['UID'];
+ $uri = $uid . '.vcf';
+ $vCardData = $this->backend->getCard($this->getKey(), $uri);
+ $vCard = $this->readCard($vCardData['carddata']);
+ $update = true;
+ }
+
+ foreach ($properties as $key => $value) {
+ $vCard->$key = $vCard->createProperty($key, $value);
+ }
+
+ if ($update) {
+ $this->backend->updateCard($this->getKey(), $uri, $vCard->serialize());
+ } else {
+ $this->backend->createCard($this->getKey(), $uri, $vCard->serialize());
+ }
+
+ return $this->vCard2Array($vCard);
+
+ }
+
+ /**
+ * @return mixed
+ * @since 5.0.0
+ */
+ public function getPermissions() {
+ $permissions = $this->addressBook->getACL();
+ $result = 0;
+ foreach ($permissions as $permission) {
+ switch($permission['privilege']) {
+ case '{DAV:}read':
+ $result |= Constants::PERMISSION_READ;
+ break;
+ case '{DAV:}write':
+ $result |= Constants::PERMISSION_CREATE;
+ $result |= Constants::PERMISSION_UPDATE;
+ break;
+ case '{DAV:}all':
+ $result |= Constants::PERMISSION_ALL;
+ break;
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * @param object $id the unique identifier to a contact
+ * @return bool successful or not
+ * @since 5.0.0
+ */
+ public function delete($id) {
+ $uri = $this->backend->getCardUri($id);
+ return $this->backend->deleteCard($this->addressBookInfo['id'], $uri);
+ }
+
+ /**
+ * read vCard data into a vCard object
+ *
+ * @param string $cardData
+ * @return VCard
+ */
+ protected function readCard($cardData) {
+ return Reader::read($cardData);
+ }
+
+ /**
+ * create UID for contact
+ *
+ * @return string
+ */
+ protected function createUid() {
+ do {
+ $uid = $this->getUid();
+ } while (!empty($this->backend->getContact($uid . '.vcf')));
+
+ return $uid;
+ }
+
+ /**
+ * getUid is only there for testing, use createUid instead
+ */
+ protected function getUid() {
+ return UUIDUtil::getUUID();
+ }
+
+ /**
+ * create empty vcard
+ *
+ * @param string $uid
+ * @return VCard
+ */
+ protected function createEmptyVCard($uid) {
+ $vCard = new VCard();
+ $vCard->add(new Text($vCard, 'UID', $uid));
+ return $vCard;
+ }
+
+ /**
+ * create array with all vCard properties
+ *
+ * @param VCard $vCard
+ * @return array
+ */
+ protected function vCard2Array(VCard $vCard) {
+ $result = [];
+ foreach ($vCard->children as $property) {
+ $result[$property->name] = $property->getValue();
+ }
+ return $result;
+ }
+}
diff --git a/apps/dav/lib/carddav/carddavbackend.php b/apps/dav/lib/carddav/carddavbackend.php
index 29b056672b4..95175b20d1b 100644
--- a/apps/dav/lib/carddav/carddavbackend.php
+++ b/apps/dav/lib/carddav/carddavbackend.php
@@ -23,19 +23,48 @@
namespace OCA\DAV\CardDAV;
use OCA\DAV\Connector\Sabre\Principal;
+use OCP\IDBConnection;
+use OCP\ILogger;
use Sabre\CardDAV\Backend\BackendInterface;
use Sabre\CardDAV\Backend\SyncSupport;
use Sabre\CardDAV\Plugin;
use Sabre\DAV\Exception\BadRequest;
+use Sabre\VObject\Component\VCard;
+use Sabre\VObject\Reader;
class CardDavBackend implements BackendInterface, SyncSupport {
/** @var Principal */
private $principalBackend;
- public function __construct(\OCP\IDBConnection $db, Principal $principalBackend) {
+ /** @var ILogger */
+ private $logger;
+
+ /** @var string */
+ private $dbCardsTable = 'cards';
+
+ /** @var string */
+ private $dbCardsPropertiesTable = 'cards_properties';
+
+ /** @var IDBConnection */
+ private $db;
+
+ /** @var array properties to index */
+ public static $indexProperties = array(
+ 'BDAY', 'UID', 'N', 'FN', 'TITLE', 'ROLE', 'NOTE', 'NICKNAME',
+ 'ORG', 'CATEGORIES', 'EMAIL', 'TEL', 'IMPP', 'ADR', 'URL', 'GEO', 'CLOUD');
+
+ /**
+ * CardDavBackend constructor.
+ *
+ * @param IDBConnection $db
+ * @param Principal $principalBackend
+ * @param ILogger $logger
+ */
+ public function __construct(IDBConnection $db, Principal $principalBackend, ILogger $logger) {
$this->db = $db;
$this->principalBackend = $principalBackend;
+ $this->logger = $logger;
}
/**
@@ -263,6 +292,11 @@ class CardDavBackend implements BackendInterface, SyncSupport {
->where($query->expr()->eq('resourceid', $query->createNamedParameter($addressBookId)))
->andWhere($query->expr()->eq('type', $query->createNamedParameter('addressbook')))
->execute();
+
+ $query->delete($this->dbCardsPropertiesTable)
+ ->where($query->expr()->eq('addressbookid', $query->createNamedParameter($addressBookId)))
+ ->execute();
+
}
/**
@@ -398,7 +432,7 @@ class CardDavBackend implements BackendInterface, SyncSupport {
$query = $this->db->getQueryBuilder();
$query->insert('cards')
->values([
- 'carddata' => $query->createNamedParameter($cardData),
+ 'carddata' => $query->createNamedParameter($cardData, \PDO::PARAM_LOB),
'uri' => $query->createNamedParameter($cardUri),
'lastmodified' => $query->createNamedParameter(time()),
'addressbookid' => $query->createNamedParameter($addressBookId),
@@ -408,6 +442,7 @@ class CardDavBackend implements BackendInterface, SyncSupport {
->execute();
$this->addChange($addressBookId, $cardUri, 1);
+ $this->updateProperties($addressBookId, $cardUri, $cardData);
return '"' . $etag . '"';
}
@@ -451,6 +486,7 @@ class CardDavBackend implements BackendInterface, SyncSupport {
->execute();
$this->addChange($addressBookId, $cardUri, 2);
+ $this->updateProperties($addressBookId, $cardUri, $cardData);
return '"' . $etag . '"';
}
@@ -463,6 +499,7 @@ class CardDavBackend implements BackendInterface, SyncSupport {
* @return bool
*/
function deleteCard($addressBookId, $cardUri) {
+ $cardId = $this->getCardId($cardUri);
$query = $this->db->getQueryBuilder();
$ret = $query->delete('cards')
->where($query->expr()->eq('addressbookid', $query->createNamedParameter($addressBookId)))
@@ -471,7 +508,12 @@ class CardDavBackend implements BackendInterface, SyncSupport {
$this->addChange($addressBookId, $cardUri, 3);
- return $ret === 1;
+ if ($ret === 1) {
+ $this->purgeProperties($addressBookId, $cardId);
+ return true;
+ }
+
+ return false;
}
/**
@@ -638,6 +680,87 @@ class CardDavBackend implements BackendInterface, SyncSupport {
}
/**
+ * search contact
+ *
+ * @param int $addressBookId
+ * @param string $pattern which should match within the $searchProperties
+ * @param array $searchProperties defines the properties within the query pattern should match
+ * @return array an array of contacts which are arrays of key-value-pairs
+ */
+ public function search($addressBookId, $pattern, $searchProperties) {
+ $query = $this->db->getQueryBuilder();
+ $query2 = $this->db->getQueryBuilder();
+ $query2->selectDistinct('cp.cardid')->from($this->dbCardsPropertiesTable, 'cp');
+ foreach ($searchProperties as $property) {
+ $query2->orWhere(
+ $query2->expr()->andX(
+ $query2->expr()->eq('cp.name', $query->createNamedParameter($property)),
+ $query2->expr()->like('cp.value', $query->createNamedParameter('%' . $this->db->escapeLikeParameter($pattern) . '%'))
+ )
+ );
+ }
+ $query2->andWhere($query2->expr()->eq('cp.addressbookid', $query->createNamedParameter($addressBookId)));
+
+ $query->select('c.carddata')->from($this->dbCardsTable, 'c')
+ ->where($query->expr()->in('c.id', $query->createFunction($query2->getSQL())));
+
+ $result = $query->execute();
+ $cards = $result->fetchAll();
+
+ $result->closeCursor();
+
+ return array_map(function($array) {return $this->readBlob($array['carddata']);}, $cards);
+
+ }
+
+ /**
+ * get URI from a given contact
+ *
+ * @param int $id
+ * @return string
+ */
+ public function getCardUri($id) {
+ $query = $this->db->getQueryBuilder();
+ $query->select('uri')->from($this->dbCardsTable)
+ ->where($query->expr()->eq('id', $query->createParameter('id')))
+ ->setParameter('id', $id);
+
+ $result = $query->execute();
+ $uri = $result->fetch();
+ $result->closeCursor();
+
+ if (!isset($uri['uri'])) {
+ throw new \InvalidArgumentException('Card does not exists: ' . $id);
+ }
+
+ return $uri['uri'];
+ }
+
+ /**
+ * return contact with the given URI
+ *
+ * @param string $uri
+ * @returns array
+ */
+ public function getContact($uri) {
+ $result = [];
+ $query = $this->db->getQueryBuilder();
+ $query->select('*')->from($this->dbCardsTable)
+ ->where($query->expr()->eq('uri', $query->createParameter('uri')))
+ ->setParameter('uri', $uri);
+ $queryResult = $query->execute();
+ $contact = $queryResult->fetch();
+ $queryResult->closeCursor();
+
+ if (is_array($contact)) {
+ $result = $contact;
+ }
+
+ return $result;
+ }
+
+
+ /**
* @param string $addressBookUri
* @param string $element
*/
@@ -658,7 +781,7 @@ class CardDavBackend implements BackendInterface, SyncSupport {
}
// remove the share if it already exists
- $this->unshare($addressBookUri, $element);
+ $this->unshare($addressBookUri, $element['href']);
$query = $this->db->getQueryBuilder();
$query->insert('dav_shares')
@@ -677,8 +800,7 @@ class CardDavBackend implements BackendInterface, SyncSupport {
* @param string $element
*/
private function unshare($addressBookUri, $element) {
- $user = $element['href'];
- $parts = explode(':', $user, 2);
+ $parts = explode(':', $element, 2);
if ($parts[0] !== 'principal') {
return;
}
@@ -734,4 +856,93 @@ class CardDavBackend implements BackendInterface, SyncSupport {
return $shares;
}
+
+ /**
+ * update properties table
+ *
+ * @param int $addressBookId
+ * @param string $cardUri
+ * @param string $vCardSerialized
+ */
+ protected function updateProperties($addressBookId, $cardUri, $vCardSerialized) {
+ $cardId = $this->getCardId($cardUri);
+ $vCard = $this->readCard($vCardSerialized);
+
+ $this->purgeProperties($addressBookId, $cardId);
+
+ $query = $this->db->getQueryBuilder();
+ $query->insert($this->dbCardsPropertiesTable)
+ ->values(
+ [
+ 'addressbookid' => $query->createNamedParameter($addressBookId),
+ 'cardid' => $query->createNamedParameter($cardId),
+ 'name' => $query->createParameter('name'),
+ 'value' => $query->createParameter('value'),
+ 'preferred' => $query->createParameter('preferred')
+ ]
+ );
+
+ foreach ($vCard->children as $property) {
+ if(!in_array($property->name, self::$indexProperties)) {
+ continue;
+ }
+ $preferred = 0;
+ foreach($property->parameters as $parameter) {
+ if ($parameter->name == 'TYPE' && strtoupper($parameter->getValue()) == 'PREF') {
+ $preferred = 1;
+ break;
+ }
+ }
+ $query->setParameter('name', $property->name);
+ $query->setParameter('value', substr($property->getValue(), 0, 254));
+ $query->setParameter('preferred', $preferred);
+ $query->execute();
+ }
+ }
+
+ /**
+ * read vCard data into a vCard object
+ *
+ * @param string $cardData
+ * @return VCard
+ */
+ protected function readCard($cardData) {
+ return Reader::read($cardData);
+ }
+
+ /**
+ * delete all properties from a given card
+ *
+ * @param int $addressBookId
+ * @param int $cardId
+ */
+ protected function purgeProperties($addressBookId, $cardId) {
+ $query = $this->db->getQueryBuilder();
+ $query->delete($this->dbCardsPropertiesTable)
+ ->where($query->expr()->eq('cardid', $query->createNamedParameter($cardId)))
+ ->andWhere($query->expr()->eq('addressbookid', $query->createNamedParameter($addressBookId)));
+ $query->execute();
+ }
+
+ /**
+ * get ID from a given contact
+ *
+ * @param string $uri
+ * @return int
+ */
+ protected function getCardId($uri) {
+ $query = $this->db->getQueryBuilder();
+ $query->select('id')->from($this->dbCardsTable)
+ ->where($query->expr()->eq('uri', $query->createNamedParameter($uri)));
+
+ $result = $query->execute();
+ $cardIds = $result->fetch();
+ $result->closeCursor();
+
+ if (!isset($cardIds['id'])) {
+ throw new \InvalidArgumentException('Card does not exists: ' . $uri);
+ }
+
+ return (int)$cardIds['id'];
+ }
}
diff --git a/apps/dav/lib/carddav/sharing/plugin.php b/apps/dav/lib/carddav/sharing/plugin.php
index 99c6f8f912c..fd415b4566b 100644
--- a/apps/dav/lib/carddav/sharing/plugin.php
+++ b/apps/dav/lib/carddav/sharing/plugin.php
@@ -9,11 +9,24 @@ use Sabre\DAV\Exception\NotFound;
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;
@@ -68,6 +81,7 @@ class Plugin extends ServerPlugin {
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']);
}
@@ -109,9 +123,7 @@ class Plugin extends ServerPlugin {
// 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) {
@@ -124,19 +136,18 @@ class Plugin extends ServerPlugin {
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,
@@ -148,59 +159,6 @@ class Plugin extends ServerPlugin {
}
}
- /**
- * 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)) {
diff --git a/apps/dav/lib/carddav/sharing/xml/sharerequest.php b/apps/dav/lib/carddav/sharing/xml/sharerequest.php
new file mode 100644
index 00000000000..175c5ffc306
--- /dev/null
+++ b/apps/dav/lib/carddav/sharing/xml/sharerequest.php
@@ -0,0 +1,65 @@
+<?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);
+
+ }
+
+}
diff --git a/apps/dav/lib/connector/sabre/auth.php b/apps/dav/lib/connector/sabre/auth.php
index 4f319770234..7f4f4a531b1 100644
--- a/apps/dav/lib/connector/sabre/auth.php
+++ b/apps/dav/lib/connector/sabre/auth.php
@@ -160,7 +160,7 @@ class Auth extends AbstractBasic {
return [true, $this->principalPrefix . $user];
}
- if (!$this->userSession->isLoggedIn() && $request->getHeader('X-Requested-With') === 'XMLHttpRequest') {
+ if (!$this->userSession->isLoggedIn() && in_array('XMLHttpRequest', explode(',', $request->getHeader('X-Requested-With')))) {
// do not re-authenticate over ajax, use dummy auth name to prevent browser popup
$response->addHeader('WWW-Authenticate','DummyBasic realm="' . $this->realm . '"');
$response->setStatus(401);
diff --git a/apps/dav/lib/connector/sabre/file.php b/apps/dav/lib/connector/sabre/file.php
index c66f627c0a3..6a0a39d04e7 100644
--- a/apps/dav/lib/connector/sabre/file.php
+++ b/apps/dav/lib/connector/sabre/file.php
@@ -329,7 +329,7 @@ class File extends Node implements IFile {
if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PROPFIND') {
return $mimeType;
}
- return \OC_Helper::getSecureMimeType($mimeType);
+ return \OC::$server->getMimeTypeDetector()->getSecureMimeType($mimeType);
}
/**
diff --git a/apps/dav/lib/connector/sabre/filesplugin.php b/apps/dav/lib/connector/sabre/filesplugin.php
index 1c78e9dc845..aa756281745 100644
--- a/apps/dav/lib/connector/sabre/filesplugin.php
+++ b/apps/dav/lib/connector/sabre/filesplugin.php
@@ -31,6 +31,7 @@ use \Sabre\DAV\PropFind;
use \Sabre\DAV\PropPatch;
use \Sabre\HTTP\RequestInterface;
use \Sabre\HTTP\ResponseInterface;
+use OCP\Files\StorageNotAvailableException;
class FilesPlugin extends \Sabre\DAV\ServerPlugin {
@@ -225,9 +226,13 @@ class FilesPlugin extends \Sabre\DAV\ServerPlugin {
if ($node instanceof \OCA\DAV\Connector\Sabre\File) {
$propFind->handle(self::DOWNLOADURL_PROPERTYNAME, function() use ($node) {
/** @var $node \OCA\DAV\Connector\Sabre\File */
- $directDownloadUrl = $node->getDirectDownload();
- if (isset($directDownloadUrl['url'])) {
- return $directDownloadUrl['url'];
+ try {
+ $directDownloadUrl = $node->getDirectDownload();
+ if (isset($directDownloadUrl['url'])) {
+ return $directDownloadUrl['url'];
+ }
+ } catch (StorageNotAvailableException $e) {
+ return false;
}
return false;
});
diff --git a/apps/dav/lib/connector/sabre/objecttree.php b/apps/dav/lib/connector/sabre/objecttree.php
index 2e9c1b9916c..809d202aea4 100644
--- a/apps/dav/lib/connector/sabre/objecttree.php
+++ b/apps/dav/lib/connector/sabre/objecttree.php
@@ -190,7 +190,7 @@ class ObjectTree extends \Sabre\DAV\Tree {
$targetNodeExists = $this->nodeExists($destinationPath);
$sourceNode = $this->getNodeForPath($sourcePath);
if ($sourceNode instanceof \Sabre\DAV\ICollection && $targetNodeExists) {
- throw new \Sabre\DAV\Exception\Forbidden('Could not copy directory ' . $sourceNode . ', target exists');
+ throw new \Sabre\DAV\Exception\Forbidden('Could not copy directory ' . $sourceNode->getName() . ', target exists');
}
list($sourceDir,) = \Sabre\HTTP\URLUtil::splitPath($sourcePath);
list($destinationDir,) = \Sabre\HTTP\URLUtil::splitPath($destinationPath);
diff --git a/apps/dav/lib/rootcollection.php b/apps/dav/lib/rootcollection.php
index 9ee32822bbd..96cc2bbc46a 100644
--- a/apps/dav/lib/rootcollection.php
+++ b/apps/dav/lib/rootcollection.php
@@ -41,11 +41,11 @@ class RootCollection extends SimpleCollection {
\OC::$server->getSystemTagObjectMapper()
);
- $usersCardDavBackend = new CardDavBackend($db, $principalBackend);
+ $usersCardDavBackend = new CardDavBackend($db, $principalBackend, \OC::$server->getLogger());
$usersAddressBookRoot = new AddressBookRoot($principalBackend, $usersCardDavBackend, 'principals/users');
$usersAddressBookRoot->disableListing = $disableListing;
- $systemCardDavBackend = new CardDavBackend($db, $principalBackend);
+ $systemCardDavBackend = new CardDavBackend($db, $principalBackend, \OC::$server->getLogger());
$systemAddressBookRoot = new AddressBookRoot(new SystemPrincipalBackend(), $systemCardDavBackend, 'principals/system');
$systemAddressBookRoot->disableListing = $disableListing;
diff --git a/apps/dav/lib/systemtag/systemtagsbyidcollection.php b/apps/dav/lib/systemtag/systemtagsbyidcollection.php
index e7b7b6d0acc..974d04efa5f 100644
--- a/apps/dav/lib/systemtag/systemtagsbyidcollection.php
+++ b/apps/dav/lib/systemtag/systemtagsbyidcollection.php
@@ -46,14 +46,25 @@ class SystemTagsByIdCollection implements ICollection {
$this->tagManager = $tagManager;
}
+ /**
+ * @param string $name
+ * @param resource|string $data Initial payload
+ * @throws Forbidden
+ */
function createFile($name, $data = null) {
throw new Forbidden('Cannot create tags by id');
}
+ /**
+ * @param string $name
+ */
function createDirectory($name) {
throw new Forbidden('Permission denied to create collections');
}
+ /**
+ * @param string $name
+ */
function getChild($name) {
try {
$tags = $this->tagManager->getTagsByIds([$name]);
@@ -72,6 +83,9 @@ class SystemTagsByIdCollection implements ICollection {
}, $tags);
}
+ /**
+ * @param string $name
+ */
function childExists($name) {
try {
$this->tagManager->getTagsByIds([$name]);
diff --git a/apps/dav/lib/systemtag/systemtagsobjecttypecollection.php b/apps/dav/lib/systemtag/systemtagsobjecttypecollection.php
index e544073613f..2a28b9c83aa 100644
--- a/apps/dav/lib/systemtag/systemtagsobjecttypecollection.php
+++ b/apps/dav/lib/systemtag/systemtagsobjecttypecollection.php
@@ -61,14 +61,25 @@ class SystemTagsObjectTypeCollection implements ICollection {
$this->objectType = $objectType;
}
+ /**
+ * @param string $name
+ * @param resource|string $data Initial payload
+ * @throws Forbidden
+ */
function createFile($name, $data = null) {
throw new Forbidden('Permission denied to create nodes');
}
+ /**
+ * @param string $name
+ */
function createDirectory($name) {
throw new Forbidden('Permission denied to create collections');
}
+ /**
+ * @param string $objectId
+ */
function getChild($objectId) {
return new SystemTagsObjectMappingCollection(
$objectId,
@@ -83,6 +94,9 @@ class SystemTagsObjectTypeCollection implements ICollection {
throw new MethodNotAllowed();
}
+ /**
+ * @param string $name
+ */
function childExists($name) {
return true;
}
@@ -95,6 +109,9 @@ class SystemTagsObjectTypeCollection implements ICollection {
return $this->objectType;
}
+ /**
+ * @param string $name
+ */
function setName($name) {
throw new Forbidden('Permission denied to rename this collection');
}