summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Bruederli <bruederli@kolabsys.com>2013-09-04 14:28:46 (GMT)
committerThomas Bruederli <bruederli@kolabsys.com>2013-09-04 14:28:46 (GMT)
commit1b3d45fd92e622efe66fabf111da1d79a8826798 (patch)
treec97fb96c3a8e111e77b3af461ac6256a885ab539
parent7164ba811e5f711023a3c87841729b6ff44414b5 (diff)
downloadiRony-1b3d45fd92e622efe66fabf111da1d79a8826798.tar.gz
Accept events/vcards with URI doesn't match the objects's UID. Send a Location: header with the response (#2109)
-rw-r--r--lib/Kolab/CalDAV/CalendarBackend.php38
-rw-r--r--lib/Kolab/CalDAV/Plugin.php31
-rw-r--r--lib/Kolab/CardDAV/ContactsBackend.php34
-rw-r--r--lib/Kolab/CardDAV/Plugin.php31
-rw-r--r--public_html/debug.php1
5 files changed, 103 insertions, 32 deletions
diff --git a/lib/Kolab/CalDAV/CalendarBackend.php b/lib/Kolab/CalDAV/CalendarBackend.php
index f9a6a3f..c151940 100644
--- a/lib/Kolab/CalDAV/CalendarBackend.php
+++ b/lib/Kolab/CalDAV/CalendarBackend.php
@@ -348,7 +348,7 @@ class CalendarBackend extends CalDAV\Backend\AbstractBackend
return array(
'id' => $event['uid'],
'uri' => $event['uid'] . '.ics',
- 'lastmodified' => $event['changed']->format('U'),
+ 'lastmodified' => $event['changed'] ? $event['changed']->format('U') : null,
'calendarid' => $calendarId,
'calendardata' => $this->_to_ical($event, $base_uri, $storage),
'etag' => self::_get_etag($event),
@@ -383,33 +383,34 @@ class CalendarBackend extends CalDAV\Backend\AbstractBackend
$storage = $this->get_storage_folder($calendarId);
$object = $this->parse_calendar_data($calendarData, $uid);
- if (empty($object)) {
+ if (empty($object) || empty($object['uid'])) {
throw new DAV\Exception('Parse error: not a valid iCalendar 2.0 object');
}
- if ($object['uid'] == $uid) {
- // map attachments attribute
- $object['_attachments'] = $object['attachments'];
+ // 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';
+ Plugin::$redirect_basename = $objectUri;
+ return $this->updateCalendarObject($calendarId, $objectUri, $calendarData);
+ }
- $success = $storage->save($object, $object['_type']);
- if (!$success) {
- rcube::raise_error(array(
- 'code' => 600, 'type' => 'php',
- 'file' => __FILE__, 'line' => __LINE__,
- 'message' => "Error saving $object[_type] object to Kolab server"),
- true, false);
+ // map attachments attribute
+ $object['_attachments'] = $object['attachments'];
- throw new DAV\Exception('Error saving calendar object to backend');
- }
- }
- else {
+ $success = $storage->save($object, $object['_type']);
+ if (!$success) {
rcube::raise_error(array(
'code' => 600, 'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
- 'message' => "Error creating calendar object: UID doesn't match object URI"),
+ 'message' => "Error saving $object[_type] object to Kolab server"),
true, false);
- throw new DAV\Exception\NotFound("UID doesn't match object URI");
+ throw new DAV\Exception('Error saving calendar object to backend');
+ }
+
+ // send Location: header if URI doesn't match object's UID (Bug #2109)
+ if ($object['uid'] != $uid) {
+ Plugin::$redirect_basename = $object['uid'].'.ics';
}
// return new Etag
@@ -481,6 +482,7 @@ class CalendarBackend extends CalDAV\Backend\AbstractBackend
'message' => "Error saving event object to Kolab server"),
true, false);
+ Plugin::$redirect_basename = null;
throw new DAV\Exception('Error saving event object to backend');
}
diff --git a/lib/Kolab/CalDAV/Plugin.php b/lib/Kolab/CalDAV/Plugin.php
index b3bc367..c3b064f 100644
--- a/lib/Kolab/CalDAV/Plugin.php
+++ b/lib/Kolab/CalDAV/Plugin.php
@@ -38,6 +38,37 @@ class Plugin extends CalDAV\Plugin
public static $parsed_vcalendar;
public static $parsed_vevent;
+ // allow the backend to force a redirect Location
+ public static $redirect_basename;
+
+ /**
+ * Initializes the plugin
+ *
+ * @param DAV\Server $server
+ * @return void
+ */
+ public function initialize(DAV\Server $server)
+ {
+ parent::initialize($server);
+
+ $server->subscribeEvent('afterCreateFile', array($this, 'afterWriteContent'));
+ $server->subscribeEvent('afterWriteContent', array($this, 'afterWriteContent'));
+ }
+
+ /**
+ * Inject some additional HTTP response headers
+ */
+ public function afterWriteContent($uri, $node)
+ {
+ // send Location: header to corrected URI
+ if (self::$redirect_basename) {
+ $path = explode('/', $uri);
+ array_pop($path);
+ array_push($path, self::$redirect_basename);
+ $this->server->httpResponse->setHeader('Location', $this->server->getBaseUri() . join('/', array_map('urlencode', $path)));
+ self::$redirect_basename = null;
+ }
+ }
/**
* Checks if the submitted iCalendar data is in fact, valid.
diff --git a/lib/Kolab/CardDAV/ContactsBackend.php b/lib/Kolab/CardDAV/ContactsBackend.php
index 17808c1..41e1ca3 100644
--- a/lib/Kolab/CardDAV/ContactsBackend.php
+++ b/lib/Kolab/CardDAV/ContactsBackend.php
@@ -344,26 +344,31 @@ class ContactsBackend extends CardDAV\Backend\AbstractBackend
$storage = $this->get_storage_folder($addressBookId);
$object = $this->parse_vcard($cardData, $uid);
- if ($object['uid'] == $uid) {
- $success = $storage->save($object, $object['_type']);
- if (!$success) {
- rcube::raise_error(array(
- 'code' => 600, 'type' => 'php',
- 'file' => __FILE__, 'line' => __LINE__,
- 'message' => "Error saving contact object to Kolab server"),
- true, false);
-
- throw new DAV\Exception('Error saving contact card to backend');
- }
+ if (empty($object) || empty($object['uid'])) {
+ throw new DAV\Exception('Parse error: not a valid VCard object');
}
- else {
+
+ // if URI doesn't match the content's UID, the object might already exist!
+ $cardUri = $object['uid'] . '.vcf';
+ if ($object['uid'] != $uid && $this->getCard($addressBookId, $cardUri)) {
+ Plugin::$redirect_basename = $cardUri;
+ return $this->updateCard($addressBookId, $cardUri, $cardData);
+ }
+
+ $success = $storage->save($object, $object['_type']);
+ if (!$success) {
rcube::raise_error(array(
'code' => 600, 'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
- 'message' => "Error creating contact object: UID doesn't match object URI"),
+ 'message' => "Error saving contact object to Kolab server"),
true, false);
- throw new DAV\Exception\NotFound("UID doesn't match object URI");
+ throw new DAV\Exception('Error saving contact card to backend');
+ }
+
+ // send Location: header if URI doesn't match object's UID (Bug #2109)
+ if ($object['uid'] != $uid) {
+ Plugin::$redirect_basename = $cardUri;
}
// return new Etag
@@ -445,6 +450,7 @@ class ContactsBackend extends CardDAV\Backend\AbstractBackend
'message' => "Error saving contact object to Kolab server"),
true, false);
+ Plugin::$redirect_basename = null;
throw new DAV\Exception('Error saving contact card to backend');
}
diff --git a/lib/Kolab/CardDAV/Plugin.php b/lib/Kolab/CardDAV/Plugin.php
index 5c39c07..3d7aa7d 100644
--- a/lib/Kolab/CardDAV/Plugin.php
+++ b/lib/Kolab/CardDAV/Plugin.php
@@ -36,6 +36,37 @@ class Plugin extends CardDAV\Plugin
// make already parsed vcard blocks available for later use
public static $parsed_vcard;
+ // allow the backend to force a redirect Location
+ public static $redirect_basename;
+
+ /**
+ * Initializes the plugin
+ *
+ * @param DAV\Server $server
+ * @return void
+ */
+ public function initialize(DAV\Server $server)
+ {
+ parent::initialize($server);
+
+ $server->subscribeEvent('afterCreateFile', array($this, 'afterWriteContent'));
+ $server->subscribeEvent('afterWriteContent', array($this, 'afterWriteContent'));
+ }
+
+ /**
+ * Inject some additional HTTP response headers
+ */
+ public function afterWriteContent($uri, $node)
+ {
+ // send Location: header to corrected URI
+ if (self::$redirect_basename) {
+ $path = explode('/', $uri);
+ array_pop($path);
+ array_push($path, self::$redirect_basename);
+ $this->server->httpResponse->setHeader('Location', $this->server->getBaseUri() . join('/', array_map('urlencode', $path)));
+ self::$redirect_basename = null;
+ }
+ }
/**
* Checks if the submitted iCalendar data is in fact, valid.
diff --git a/public_html/debug.php b/public_html/debug.php
index 84e89b3..10fcea8 100644
--- a/public_html/debug.php
+++ b/public_html/debug.php
@@ -92,6 +92,7 @@ header($result_headers, true);
// forward response headers
unset($response_headers['Transfer-Encoding']);
foreach ($response_headers as $hdr => $value) {
+ $value = str_replace('index.php/', '', $value);
$result_headers .= "\n$hdr: " . $value;
header("$hdr: " . $value, true);
}