summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Bruederli <bruederli@kolabsys.com>2014-05-06 14:28:51 (GMT)
committerThomas Bruederli <bruederli@kolabsys.com>2014-05-06 14:28:51 (GMT)
commit4561e85e147f3d7470b1afca43913de382327a44 (patch)
tree5154a66417883c82a2fabe4e9650a41888279753
parent5e1b84501a856f1de01d016bed6663f10642420f (diff)
downloadiRony-4561e85e147f3d7470b1afca43913de382327a44.tar.gz
Correctly encode and decode CalDAV/CardDAV object URIs (#3049)
-rw-r--r--lib/Kolab/CalDAV/CalendarBackend.php23
-rw-r--r--lib/Kolab/CardDAV/ContactsBackend.php14
-rw-r--r--lib/Kolab/CardDAV/LDAPDirectory.php9
-rw-r--r--lib/Kolab/Utils/VObjectUtils.php24
4 files changed, 48 insertions, 22 deletions
diff --git a/lib/Kolab/CalDAV/CalendarBackend.php b/lib/Kolab/CalDAV/CalendarBackend.php
index 122ee01..fdef6ca 100644
--- a/lib/Kolab/CalDAV/CalendarBackend.php
+++ b/lib/Kolab/CalDAV/CalendarBackend.php
@@ -292,7 +292,7 @@ class CalendarBackend extends CalDAV\Backend\AbstractBackend
foreach ($storage->select($query) as $event) {
$events[] = array(
'id' => $event['uid'],
- 'uri' => $event['uid'] . '.ics',
+ 'uri' => VObjectUtils::uid2uri($event['uid'], '.ics'),
'lastmodified' => $event['changed'] ? $event['changed']->format('U') : null,
'calendarid' => $calendarId,
'etag' => self::_get_etag($event),
@@ -321,12 +321,13 @@ class CalendarBackend extends CalDAV\Backend\AbstractBackend
{
console(__METHOD__, $calendarId, $objectUri);
- $uid = basename($objectUri, '.ics');
+ $uid = VObjectUtils::uri2uid($objectUri, '.ics');
$storage = $this->get_storage_folder($calendarId);
// attachment content is requested
if (preg_match('!^(.+).ics:attachment:(\d+):.+$!', $objectUri, $m)) {
- $uid = $m[1]; $part = $m[2];
+ $uid = VObjectUtils::uri2uid($m[1]);
+ $part = $m[2];
}
if ($storage && ($event = $storage->get_object($uid))) {
@@ -345,18 +346,18 @@ class CalendarBackend extends CalDAV\Backend\AbstractBackend
// map attributes
$event['attachments'] = $event['_attachments'];
- // compose an absilute URI for referencing object attachments
+ // compose an absolute URI for referencing object attachments
$base_uri = DAVBackend::abs_url(array(
CalDAV\Plugin::CALENDAR_ROOT,
preg_replace('!principals/!', '', $this->calendars[$calendarId]['principaluri']),
$calendarId,
- $event['uid'] . '.ics',
+ VObjectUtils::uid2uri($event['uid'], '.ics'),
));
// default response
return array(
'id' => $event['uid'],
- 'uri' => $event['uid'] . '.ics',
+ 'uri' => VObjectUtils::uid2uri($event['uid'], '.ics'),
'lastmodified' => $event['changed'] ? $event['changed']->format('U') : null,
'calendarid' => $calendarId,
'calendardata' => $this->_to_ical($event, $base_uri, $storage),
@@ -388,7 +389,7 @@ class CalendarBackend extends CalDAV\Backend\AbstractBackend
{
console(__METHOD__, $calendarId, $objectUri, $calendarData);
- $uid = basename($objectUri, '.ics');
+ $uid = VObjectUtils::uri2uid($objectUri, '.ics');
$storage = $this->get_storage_folder($calendarId);
$object = $this->parse_calendar_data($calendarData, $uid);
@@ -398,7 +399,7 @@ class CalendarBackend extends CalDAV\Backend\AbstractBackend
// if URI doesn't match the content's UID, the object might already exist!
if ($object['uid'] != $uid && $storage->get_object($object['uid'])) {
- $objectUri = $object['uid'] . '.ics';
+ $objectUri = VObjectUtils::uid2uri($object['uid'], '.ics');
Plugin::$redirect_basename = $objectUri;
return $this->updateCalendarObject($calendarId, $objectUri, $calendarData);
}
@@ -420,7 +421,7 @@ class CalendarBackend extends CalDAV\Backend\AbstractBackend
// send Location: header if URI doesn't match object's UID (Bug #2109)
if ($object['uid'] != $uid) {
- Plugin::$redirect_basename = $object['uid'].'.ics';
+ Plugin::$redirect_basename = VObjectUtils::uid2uri($object['uid'], '.ics');
}
// return new Etag
@@ -447,7 +448,7 @@ class CalendarBackend extends CalDAV\Backend\AbstractBackend
{
console(__METHOD__, $calendarId, $objectUri, $calendarData);
- $uid = basename($objectUri, '.ics');
+ $uid = VObjectUtils::uri2uid($objectUri, '.ics');
$storage = $this->get_storage_folder($calendarId);
$object = $this->parse_calendar_data($calendarData, $uid);
@@ -512,7 +513,7 @@ class CalendarBackend extends CalDAV\Backend\AbstractBackend
{
console(__METHOD__, $calendarId, $objectUri);
- $uid = basename($objectUri, '.ics');
+ $uid = VObjectUtils::uri2uid($objectUri, '.ics');
if ($storage = $this->get_storage_folder($calendarId)) {
$storage->delete($uid);
}
diff --git a/lib/Kolab/CardDAV/ContactsBackend.php b/lib/Kolab/CardDAV/ContactsBackend.php
index 4b9fff0..70c5b53 100644
--- a/lib/Kolab/CardDAV/ContactsBackend.php
+++ b/lib/Kolab/CardDAV/ContactsBackend.php
@@ -288,7 +288,7 @@ class ContactsBackend extends CardDAV\Backend\AbstractBackend
foreach ($storage->select($query) as $contact) {
$cards[] = array(
'id' => $contact['uid'],
- 'uri' => $contact['uid'] . '.vcf',
+ 'uri' => VObjectUtils::uid2uri($contact['uid'], '.vcf'),
'lastmodified' => is_a($contact['changed'], 'DateTime') ? $contact['changed']->format('U') : null,
'etag' => self::_get_etag($contact),
'size' => $contact['_size'],
@@ -313,7 +313,7 @@ class ContactsBackend extends CardDAV\Backend\AbstractBackend
{
console(__METHOD__, $addressBookId, $cardUri);
- $uid = basename($cardUri, '.vcf');
+ $uid = VObjectUtils::uri2uid($cardUri, '.vcf');
// search all folders for the given card
if ($addressBookId == '__all__') {
@@ -333,7 +333,7 @@ class ContactsBackend extends CardDAV\Backend\AbstractBackend
if ($contact) {
return array(
'id' => $contact['uid'],
- 'uri' => $contact['uid'] . '.vcf',
+ 'uri' => VObjectUtils::uid2uri($contact['uid'], '.vcf'),
'lastmodified' => is_a($contact['changed'], 'DateTime') ? $contact['changed']->format('U') : null,
'carddata' => $this->to_vcard($contact),
'etag' => self::_get_etag($contact),
@@ -370,7 +370,7 @@ class ContactsBackend extends CardDAV\Backend\AbstractBackend
{
console(__METHOD__, $addressBookId, $cardUri, $cardData);
- $uid = basename($cardUri, '.vcf');
+ $uid = VObjectUtils::uri2uid($cardUri, '.vcf');
$storage = $this->get_storage_folder($addressBookId);
$object = $this->parse_vcard($cardData, $uid);
@@ -379,7 +379,7 @@ class ContactsBackend extends CardDAV\Backend\AbstractBackend
}
// if URI doesn't match the content's UID, the object might already exist!
- $cardUri = $object['uid'] . '.vcf';
+ $cardUri = VObjectUtils::uid2uri($object['uid'], '.vcf');
if ($object['uid'] != $uid && $this->getCard($addressBookId, $cardUri)) {
Plugin::$redirect_basename = $cardUri;
return $this->updateCard($addressBookId, $cardUri, $cardData);
@@ -429,7 +429,7 @@ class ContactsBackend extends CardDAV\Backend\AbstractBackend
{
console(__METHOD__, $addressBookId, $cardUri, $cardData);
- $uid = basename($cardUri, '.vcf');
+ $uid = VObjectUtils::uri2uid($cardUri, '.vcf');
$object = $this->parse_vcard($cardData, $uid);
// sanity check
@@ -499,7 +499,7 @@ class ContactsBackend extends CardDAV\Backend\AbstractBackend
{
console(__METHOD__, $addressBookId, $cardUri);
- $uid = basename($cardUri, '.vcf');
+ $uid = VObjectUtils::uri2uid($cardUri, '.vcf');
if ($addressBookId == '__all__') {
$this->get_card_by_uid($uid, $storage);
diff --git a/lib/Kolab/CardDAV/LDAPDirectory.php b/lib/Kolab/CardDAV/LDAPDirectory.php
index 6b41755..ca175f2 100644
--- a/lib/Kolab/CardDAV/LDAPDirectory.php
+++ b/lib/Kolab/CardDAV/LDAPDirectory.php
@@ -33,6 +33,7 @@ use \rcube_ldap_generic;
use Sabre\DAV;
use Sabre\DAVACL;
use Sabre\CardDAV\Property;
+use Kolab\Utils\VObjectUtils;
/**
* CardDAV Directory Gateway implementation
@@ -126,7 +127,7 @@ class LDAPDirectory extends DAV\Collection implements \Sabre\CardDAV\IDirectory,
{
console(__METHOD__, $cardUri);
- $uid = basename($cardUri, '.vcf');
+ $uid = VObjectUtils::uri2uid($cardUri, '.vcf');
$record = null;
// get from cache
@@ -138,7 +139,7 @@ class LDAPDirectory extends DAV\Collection implements \Sabre\CardDAV\IDirectory,
if ($contact = $this->getContactObject($uid)) {
$obj = array(
'id' => $contact['uid'],
- 'uri' => $contact['uid'] . '.vcf',
+ 'uri' => VObjectUtils::uid2uri($contact['uid'], '.vcf'),
'lastmodified' => $contact['_timestamp'],
'carddata' => $this->carddavBackend->to_vcard($contact),
'etag' => self::_get_etag($contact),
@@ -199,7 +200,7 @@ class LDAPDirectory extends DAV\Collection implements \Sabre\CardDAV\IDirectory,
foreach ($cached_index as $uid => $c) {
$obj = array(
'id' => $uid,
- 'uri' => $uid . '.vcf',
+ 'uri' => VObjectUtils::uid2uri($uid, '.vcf'),
'etag' => $c[1],
'lastmodified' => $c[2],
);
@@ -233,7 +234,7 @@ class LDAPDirectory extends DAV\Collection implements \Sabre\CardDAV\IDirectory,
$obj = array(
'id' => $contact['uid'],
- 'uri' => $contact['uid'] . '.vcf',
+ 'uri' => VObjectUtils::uid2uri($contact['uid'], '.vcf'),
'lastmodified' => $contact['_timestamp'],
'carddata' => $this->carddavBackend->to_vcard($contact),
'etag' => self::_get_etag($contact),
diff --git a/lib/Kolab/Utils/VObjectUtils.php b/lib/Kolab/Utils/VObjectUtils.php
index f04884e..82f934b 100644
--- a/lib/Kolab/Utils/VObjectUtils.php
+++ b/lib/Kolab/Utils/VObjectUtils.php
@@ -30,6 +30,30 @@ use Sabre\VObject\Property;
*/
class VObjectUtils
{
+ /**
+ * Convert an object URI into a valid UID value
+ */
+ public static function uri2uid($uri, $suffix = '')
+ {
+ $base = basename($uri, $suffix);
+ $uid = strtr($base, array('%2F' => '/'));
+
+ // assume full URL encoding
+ if (preg_match('/%[A-F0-9]{2}/', $uid)) {
+ return urldecode($base);
+ }
+
+ return $uid;
+ }
+
+ /**
+ * Encode an object UID into a valid URI
+ */
+ public static function uid2uri($uid, $suffix = '')
+ {
+ $encode = strpos($uid, '/') !== false;
+ return ($encode ? urlencode($uid) : $uid) . $suffix;
+ }
/**
* Create a Sabre\VObject\Property instance from a PHP DateTime object