From: Michael J. Rubinsky Date: Thu, 8 Jul 2010 23:56:04 +0000 (-0400) Subject: Handle iTip CANCEL request of a recurring event instance correctly. X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=90a9aa6cd06eeb00f09baf369f2c087210dc68f8;p=horde.git Handle iTip CANCEL request of a recurring event instance correctly. According to RFC 2446, when cancelling an instance of a recurring event, the RECURRENCE-ID value MUST be specified along with the UID. If cancelling the entire event series, the RECURRENCE-ID value MUST NOT be included. Bug: 8956 --- diff --git a/imp/lib/Mime/Viewer/Itip.php b/imp/lib/Mime/Viewer/Itip.php index a7e7f7f1c..e734df4a8 100644 --- a/imp/lib/Mime/Viewer/Itip.php +++ b/imp/lib/Mime/Viewer/Itip.php @@ -115,8 +115,14 @@ class IMP_Horde_Mime_Viewer_Itip extends Horde_Mime_Viewer_Driver // vEvent cancellation. if ($registry->hasMethod('calendar/delete')) { $guid = $components[$key]->getAttribute('UID'); + $deleteParams = array('guid' => $guid); + $instance = $components[$key]->getAttribute('RECURRENCE-ID'); + if (!($instance instanceof PEAR_Error)) { + // This is a cancellation of a recurring event instance. + $deleteParams['recurrenceId'] = $instance; + } try { - $registry->call('calendar/delete', array('guid' => $guid)); + $registry->call('calendar/delete', $deleteParams); $msgs[] = array('success', _("Event successfully deleted.")); } catch (Horde_Exception $e) { $msgs[] = array('error', _("There was an error deleting the event:") . ' ' . $e->getMessage()); @@ -715,7 +721,7 @@ class IMP_Horde_Mime_Viewer_Itip extends Horde_Mime_Viewer_Driver } else { $desc = _("%s has cancelled an instance of the recurring \"%s\"."); if ($registry->hasMethod('calendar/replace')) { - $options[] = ''; + $options[] = ''; } } break; diff --git a/kronolith/lib/Api.php b/kronolith/lib/Api.php index b5f858b17..24f3e098e 100644 --- a/kronolith/lib/Api.php +++ b/kronolith/lib/Api.php @@ -818,12 +818,16 @@ class Kronolith_Api extends Horde_Registry_Api /** * Deletes an event identified by UID. * - * @param string|array $uid A single UID or an array identifying the - * event(s) to delete. + * @param string|array $uid A single UID or an array identifying the + * event(s) to delete. + * + * @param string $recurrenceId The reccurenceId for the event instance, if + * this is a deletion of a recurring event + * instance ($uid must not be an array). * * @throws Kronolith_Exception */ - public function delete($uid) + public function delete($uid, $recurrenceId = null) { // Handle an array of UIDs for convenience of deleting multiple events // at once. @@ -869,7 +873,15 @@ class Kronolith_Api extends Horde_Registry_Api throw new Horde_Exception_PermissionDenied(); } - $kronolith_driver->deleteEvent($event->id); + if ($recurrenceId && $event->recurs()) { + $deleteDate = new Horde_Date($recurrenceId); + $event->recurrence->addException($deleteDate->format('Y'), $deleteDate->format('m'), $deleteDate->format('d')); + $event->save(); + } elseif ($recurrenceId) { + throw new Kronolith_Exception(_("Unable to delete event. An exception date was provided but the event does not seem to be recurring.")); + } else { + $kronolith_driver->deleteEvent($event->id); + } } /** diff --git a/kronolith/lib/Kronolith.php b/kronolith/lib/Kronolith.php index 5f924df25..12acdf31b 100644 --- a/kronolith/lib/Kronolith.php +++ b/kronolith/lib/Kronolith.php @@ -2243,8 +2243,11 @@ class Kronolith $iCal->setAttribute('X-WR-CALNAME', Horde_String::convertCharset($share->get('name'), Horde_Nls::getCharset(), 'utf-8')); $vevent = $event->toiCalendar($iCal); if ($action == self::ITIP_CANCEL && !empty($instance)) { + // Recurring event instance deletion, need to specify the + // RECURRENCE-ID but NOT the EXDATE. $vevent = array_pop($vevent); $vevent->setAttribute('RECURRENCE-ID', $instance, array('VALUE' => 'DATE')); + $vevent->removeAttribute('EXDATE'); } $iCal->addComponent($vevent);