diff options
-rw-r--r-- | lib/Kolab/CalDAV/CalendarBackend.php | 38 | ||||
-rw-r--r-- | lib/Kolab/CalDAV/Plugin.php | 31 | ||||
-rw-r--r-- | lib/Kolab/CardDAV/ContactsBackend.php | 34 | ||||
-rw-r--r-- | lib/Kolab/CardDAV/Plugin.php | 31 | ||||
-rw-r--r-- | public_html/debug.php | 1 |
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); } |