diff options
Diffstat (limited to 'apps/dav/lib/carddav/carddavbackend.php')
-rw-r--r-- | apps/dav/lib/carddav/carddavbackend.php | 218 |
1 files changed, 215 insertions, 3 deletions
diff --git a/apps/dav/lib/carddav/carddavbackend.php b/apps/dav/lib/carddav/carddavbackend.php index 29b056672b4..742d29e92c1 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 */ @@ -734,4 +857,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']; + } } |