summaryrefslogtreecommitdiffstats
path: root/apps/dav/lib/CardDAV
diff options
context:
space:
mode:
Diffstat (limited to 'apps/dav/lib/CardDAV')
-rw-r--r--apps/dav/lib/CardDAV/AddressBookImpl.php44
-rw-r--r--apps/dav/lib/CardDAV/CardDavBackend.php8
-rw-r--r--apps/dav/lib/CardDAV/ContactsManager.php14
-rw-r--r--apps/dav/lib/CardDAV/ImageExportPlugin.php146
4 files changed, 194 insertions, 18 deletions
diff --git a/apps/dav/lib/CardDAV/AddressBookImpl.php b/apps/dav/lib/CardDAV/AddressBookImpl.php
index 310be695185..b26f81766c6 100644
--- a/apps/dav/lib/CardDAV/AddressBookImpl.php
+++ b/apps/dav/lib/CardDAV/AddressBookImpl.php
@@ -24,6 +24,7 @@ namespace OCA\DAV\CardDAV;
use OCP\Constants;
use OCP\IAddressBook;
+use OCP\IURLGenerator;
use Sabre\VObject\Component\VCard;
use Sabre\VObject\Property\Text;
use Sabre\VObject\Reader;
@@ -40,21 +41,27 @@ class AddressBookImpl implements IAddressBook {
/** @var AddressBook */
private $addressBook;
+ /** @var IURLGenerator */
+ private $urlGenerator;
+
/**
* AddressBookImpl constructor.
*
* @param AddressBook $addressBook
* @param array $addressBookInfo
* @param CardDavBackend $backend
+ * @param IUrlGenerator $urlGenerator
*/
public function __construct(
AddressBook $addressBook,
array $addressBookInfo,
- CardDavBackend $backend) {
+ CardDavBackend $backend,
+ IURLGenerator $urlGenerator) {
$this->addressBook = $addressBook;
$this->addressBookInfo = $addressBookInfo;
$this->backend = $backend;
+ $this->urlGenerator = $urlGenerator;
}
/**
@@ -83,11 +90,11 @@ class AddressBookImpl implements IAddressBook {
* @since 5.0.0
*/
public function search($pattern, $searchProperties, $options) {
- $result = $this->backend->search($this->getKey(), $pattern, $searchProperties);
+ $results = $this->backend->search($this->getKey(), $pattern, $searchProperties);
$vCards = [];
- foreach ($result as $cardData) {
- $vCards[] = $this->vCard2Array($this->readCard($cardData));
+ foreach ($results as $result) {
+ $vCards[] = $this->vCard2Array($result['uri'], $this->readCard($result['carddata']));
}
return $vCards;
@@ -100,13 +107,12 @@ class AddressBookImpl implements IAddressBook {
*/
public function createOrUpdate($properties) {
$update = false;
- if (!isset($properties['UID'])) { // create a new contact
+ if (!isset($properties['URI'])) { // create a new contact
$uid = $this->createUid();
$uri = $uid . '.vcf';
$vCard = $this->createEmptyVCard($uid);
} else { // update existing contact
- $uid = $properties['UID'];
- $uri = $uid . '.vcf';
+ $uri = $properties['URI'];
$vCardData = $this->backend->getCard($this->getKey(), $uri);
$vCard = $this->readCard($vCardData['carddata']);
$update = true;
@@ -122,7 +128,7 @@ class AddressBookImpl implements IAddressBook {
$this->backend->createCard($this->getKey(), $uri, $vCard->serialize());
}
- return $this->vCard2Array($vCard);
+ return $this->vCard2Array($uri, $vCard);
}
@@ -207,13 +213,31 @@ class AddressBookImpl implements IAddressBook {
/**
* create array with all vCard properties
*
+ * @param string $uri
* @param VCard $vCard
* @return array
*/
- protected function vCard2Array(VCard $vCard) {
- $result = [];
+ protected function vCard2Array($uri, VCard $vCard) {
+ $result = [
+ 'URI' => $uri,
+ ];
+
foreach ($vCard->children as $property) {
$result[$property->name] = $property->getValue();
+ if ($property->name === 'PHOTO' && $property->getValueType() === 'BINARY') {
+ $url = $this->urlGenerator->getAbsoluteURL(
+ $this->urlGenerator->linkTo('', 'remote.php') . '/dav/');
+ $url .= implode('/', [
+ 'addressbooks',
+ substr($this->addressBookInfo['principaluri'], 11), //cut off 'principals/'
+ $this->addressBookInfo['uri'],
+ $uri
+ ]) . '?photo';
+
+ $result['PHOTO'] = 'VALUE=uri:' . $url;
+ } else {
+ $result[$property->name] = $property->getValue();
+ }
}
if ($this->addressBookInfo['principaluri'] === 'principals/system/system' &&
$this->addressBookInfo['uri'] === 'system') {
diff --git a/apps/dav/lib/CardDAV/CardDavBackend.php b/apps/dav/lib/CardDAV/CardDavBackend.php
index 3d2904df39c..2ad9f4778c9 100644
--- a/apps/dav/lib/CardDAV/CardDavBackend.php
+++ b/apps/dav/lib/CardDAV/CardDavBackend.php
@@ -780,7 +780,7 @@ class CardDavBackend implements BackendInterface, SyncSupport {
}
$query2->andWhere($query2->expr()->eq('cp.addressbookid', $query->createNamedParameter($addressBookId)));
- $query->select('c.carddata')->from($this->dbCardsTable, 'c')
+ $query->select('c.carddata', 'c.uri')->from($this->dbCardsTable, 'c')
->where($query->expr()->in('c.id', $query->createFunction($query2->getSQL())));
$result = $query->execute();
@@ -788,8 +788,10 @@ class CardDavBackend implements BackendInterface, SyncSupport {
$result->closeCursor();
- return array_map(function($array) {return $this->readBlob($array['carddata']);}, $cards);
-
+ return array_map(function($array) {
+ $array['carddata'] = $this->readBlob($array['carddata']);
+ return $array;
+ }, $cards);
}
/**
diff --git a/apps/dav/lib/CardDAV/ContactsManager.php b/apps/dav/lib/CardDAV/ContactsManager.php
index 7900c6ccae0..ad633483fdd 100644
--- a/apps/dav/lib/CardDAV/ContactsManager.php
+++ b/apps/dav/lib/CardDAV/ContactsManager.php
@@ -22,6 +22,7 @@
namespace OCA\DAV\CardDAV;
use OCP\Contacts\IManager;
+use OCP\IURLGenerator;
class ContactsManager {
@@ -37,26 +38,29 @@ class ContactsManager {
/**
* @param IManager $cm
* @param string $userId
+ * @param IURLGenerator $urlGenerator
*/
- public function setupContactsProvider(IManager $cm, $userId) {
+ public function setupContactsProvider(IManager $cm, $userId, IURLGenerator $urlGenerator) {
$addressBooks = $this->backend->getAddressBooksForUser("principals/users/$userId");
- $this->register($cm, $addressBooks);
+ $this->register($cm, $addressBooks, $urlGenerator);
$addressBooks = $this->backend->getAddressBooksForUser("principals/system/system");
- $this->register($cm, $addressBooks);
+ $this->register($cm, $addressBooks, $urlGenerator);
}
/**
* @param IManager $cm
* @param $addressBooks
+ * @param IURLGenerator $urlGenerator
*/
- private function register(IManager $cm, $addressBooks) {
+ private function register(IManager $cm, $addressBooks, $urlGenerator) {
foreach ($addressBooks as $addressBookInfo) {
$addressBook = new \OCA\DAV\CardDAV\AddressBook($this->backend, $addressBookInfo);
$cm->registerAddressBook(
new AddressBookImpl(
$addressBook,
$addressBookInfo,
- $this->backend
+ $this->backend,
+ $urlGenerator
)
);
}
diff --git a/apps/dav/lib/CardDAV/ImageExportPlugin.php b/apps/dav/lib/CardDAV/ImageExportPlugin.php
new file mode 100644
index 00000000000..3f505222491
--- /dev/null
+++ b/apps/dav/lib/CardDAV/ImageExportPlugin.php
@@ -0,0 +1,146 @@
+<?php
+/**
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ *
+ * @copyright Copyright (c) 2016, 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\ILogger;
+use Sabre\CardDAV\Card;
+use Sabre\DAV\Server;
+use Sabre\DAV\ServerPlugin;
+use Sabre\HTTP\RequestInterface;
+use Sabre\HTTP\ResponseInterface;
+use Sabre\VObject\Parameter;
+use Sabre\VObject\Property\Binary;
+use Sabre\VObject\Reader;
+
+class ImageExportPlugin extends ServerPlugin {
+
+ /** @var Server */
+ protected $server;
+ /** @var ILogger */
+ private $logger;
+
+ public function __construct(ILogger $logger) {
+ $this->logger = $logger;
+ }
+
+ /**
+ * Initializes the plugin and registers event handlers
+ *
+ * @param Server $server
+ * @return void
+ */
+ function initialize(Server $server) {
+
+ $this->server = $server;
+ $this->server->on('method:GET', [$this, 'httpGet'], 90);
+ }
+
+ /**
+ * Intercepts GET requests on addressbook urls ending with ?photo.
+ *
+ * @param RequestInterface $request
+ * @param ResponseInterface $response
+ * @return bool|void
+ */
+ function httpGet(RequestInterface $request, ResponseInterface $response) {
+
+ $queryParams = $request->getQueryParameters();
+ // TODO: in addition to photo we should also add logo some point in time
+ if (!array_key_exists('photo', $queryParams)) {
+ return true;
+ }
+
+ $path = $request->getPath();
+ $node = $this->server->tree->getNodeForPath($path);
+
+ if (!($node instanceof Card)) {
+ return true;
+ }
+
+ $this->server->transactionType = 'carddav-image-export';
+
+ // Checking ACL, if available.
+ if ($aclPlugin = $this->server->getPlugin('acl')) {
+ /** @var \Sabre\DAVACL\Plugin $aclPlugin */
+ $aclPlugin->checkPrivileges($path, '{DAV:}read');
+ }
+
+ if ($result = $this->getPhoto($node)) {
+ $response->setHeader('Content-Type', $result['Content-Type']);
+ $response->setStatus(200);
+
+ $response->setBody($result['body']);
+
+ // Returning false to break the event chain
+ return false;
+ }
+ return true;
+ }
+
+ function getPhoto(Card $node) {
+ // TODO: this is kind of expensive - load carddav data from database and parse it
+ // we might want to build up a cache one day
+ try {
+ $vObject = $this->readCard($node->get());
+ if (!$vObject->PHOTO) {
+ return false;
+ }
+
+ $photo = $vObject->PHOTO;
+ $type = $this->getType($photo);
+
+ $valType = $photo->getValueType();
+ $val = ($valType === 'URI' ? $photo->getRawMimeDirValue() : $photo->getValue());
+ return [
+ 'Content-Type' => $type,
+ 'body' => $val
+ ];
+ } catch(\Exception $ex) {
+ $this->logger->logException($ex);
+ }
+ return false;
+ }
+
+ private function readCard($cardData) {
+ return Reader::read($cardData);
+ }
+
+ /**
+ * @param Binary $photo
+ * @return Parameter
+ */
+ private function getType($photo) {
+ $params = $photo->parameters();
+ if (isset($params['TYPE']) || isset($params['MEDIATYPE'])) {
+ /** @var Parameter $typeParam */
+ $typeParam = isset($params['TYPE']) ? $params['TYPE'] : $params['MEDIATYPE'];
+ $type = $typeParam->getValue();
+
+ if (strpos($type, 'image/') === 0) {
+ return $type;
+ } else {
+ return 'image/' . strtolower($type);
+ }
+ }
+ return '';
+ }
+}