From 4eb506b01bfe0da11577fcf837bb6f36ba08038b Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Sat, 5 Mar 2011 10:26:17 +0000 Subject: [PATCH] * CalDAV/Lightning: fixed under some conditions infinit poping up alarms and user not able to add alarms - Lightning pops up alarm, until Sequence/etag get updated: if user has no edit rights on an other users calendar, etag never got updated, now we update it - fixed user was not able to add alarms via CalDAV, if he had no edit rights for event (was always possible in web UI) - alarms from other users calendars are not included any more, as they make no sense but a lot of trouble - fixed wrong condition on adding alarms, causing some alarms no being saved --- .../inc/class.addressbook_groupdav.inc.php | 3 +- calendar/inc/class.calendar_groupdav.inc.php | 33 +++++++++--- calendar/inc/class.calendar_ical.inc.php | 50 +++++++++++-------- calendar/inc/class.calendar_so.inc.php | 6 +-- infolog/inc/class.infolog_groupdav.inc.php | 3 +- phpgwapi/inc/class.groupdav.inc.php | 6 +-- phpgwapi/inc/class.groupdav_handler.inc.php | 3 +- .../inc/class.groupdav_principals.inc.php | 11 ++-- 8 files changed, 73 insertions(+), 42 deletions(-) diff --git a/addressbook/inc/class.addressbook_groupdav.inc.php b/addressbook/inc/class.addressbook_groupdav.inc.php index e50a5ddb76..c19b58277d 100644 --- a/addressbook/inc/class.addressbook_groupdav.inc.php +++ b/addressbook/inc/class.addressbook_groupdav.inc.php @@ -276,9 +276,10 @@ class addressbook_groupdav extends groupdav_handler * * @param array &$options * @param int $id + * @param int $user=null account_id * @return mixed boolean true on success, false on failure or string with http status (eg. '404 Not Found') */ - function get(&$options,$id) + function get(&$options,$id,$user=null) { if (!is_array($contact = $this->_common_get_put_delete('GET',$options,$id))) { diff --git a/calendar/inc/class.calendar_groupdav.inc.php b/calendar/inc/class.calendar_groupdav.inc.php index 8919152f79..c8cd75d5b3 100644 --- a/calendar/inc/class.calendar_groupdav.inc.php +++ b/calendar/inc/class.calendar_groupdav.inc.php @@ -220,7 +220,7 @@ error_log(__METHOD__."($path,,".array2string($start).") filter=".array2string($f //error_log(__FILE__ . __METHOD__ . "Calendar Data : $calendar_data"); if ($calendar_data) { - $content = $this->iCal($event); + $content = $this->iCal($event,$filter['users']); $props[] = HTTP_WebDAV_Server::mkprop('getcontentlength',bytes($content)); $props[] = HTTP_WebDAV_Server::mkprop(groupdav::CALDAV,'calendar-data',$content); } @@ -382,15 +382,16 @@ error_log(__METHOD__."($path,,".array2string($start).") filter=".array2string($f * * @param array &$options * @param int $id + * @param int $user=null account_id * @return mixed boolean true on success, false on failure or string with http status (eg. '404 Not Found') */ - function get(&$options,$id) + function get(&$options,$id,$user=null) { if (!is_array($event = $this->_common_get_put_delete('GET',$options,$id))) { return $event; } - $options['data'] = $this->iCal($event); + $options['data'] = $this->iCal($event,$user); $options['mimetype'] = 'text/calendar; charset=utf-8'; header('Content-Encoding: identity'); header('ETag: '.$this->get_etag($event)); @@ -403,13 +404,23 @@ error_log(__METHOD__."($path,,".array2string($start).") filter=".array2string($f * Taking into account virtual an real exceptions for recuring events * * @param array $event + * @param int $user=null account_id of calendar to display * @return string */ - private function iCal(array $event) + private function iCal(array $event,$user=null) { static $handler = null; if (is_null($handler)) $handler = $this->_get_handler(); + if (!$user) $user = $GLOBALS['egw_info']['user']['account_id']; + + // only return alarms in own calendar, not other users calendars + if ($user != $GLOBALS['egw_info']['user']['account_id']) + { + //error_log(__METHOD__.'('.array2string($event).", $user) clearing alarms"); + $event['alarm'] = array(); + } + $events = array($event); // for recuring events we have to add the exceptions @@ -547,8 +558,18 @@ error_log(__METHOD__."($path,,".array2string($start).") filter=".array2string($f } else { - // let lightning think the event is added - $retval = '201 Created'; + $retval = '204 No Content'; + + // lightning will pop up the alarm, as long as the Sequence (etag) does NOT change + // --> update the etag alone, if user has no edit rights + if ($this->agent == 'lightning' && !$this->check_access(EGW_ACL_EDIT, $oldEvent) && + isset($oldEvent['participants'][$GLOBALS['egw_info']['user']['account_id']])) + { + // just update etag in database + $GLOBALS['egw']->db->update($this->bo->so->cal_table,'cal_etag=cal_etag+1',array( + 'cal_id' => $eventId, + ),__LINE__,__FILE__,'calendar'); + } } } else diff --git a/calendar/inc/class.calendar_ical.inc.php b/calendar/inc/class.calendar_ical.inc.php index bc1f1c2a0d..68e67beca9 100644 --- a/calendar/inc/class.calendar_ical.inc.php +++ b/calendar/inc/class.calendar_ical.inc.php @@ -276,7 +276,7 @@ class calendar_ical extends calendar_boupdate } continue; } - + if ($this->log) { error_log(__FILE__.'['.__LINE__.'] '.__METHOD__. @@ -568,7 +568,7 @@ class calendar_ical extends calendar_boupdate 'CUTYPE' => 'INDIVIDUAL', //'RSVP' => 'FALSE', ); - if (!empty($organizerCN)) $options['CN'] = $organizerCN; + if (!empty($organizerCN)) $options['CN'] = $organizerCN; if (!empty($organizerEMail)) $options['EMAIL'] = $organizerEMail; if (!empty($event['owner'])) $options['X-EGROUPWARE-UID'] = $event['owner']; $attributes['ATTENDEE'][] = $organizerURL; @@ -631,7 +631,7 @@ class calendar_ical extends calendar_boupdate $length = ($event['end'] - $event['start']) / 2; $rrule['UNTIL']->modify($length . ' second'); } - + if (!$tzid || $version != '1.0') { if (!isset(self::$tz_cache['UTC'])) @@ -645,7 +645,7 @@ class calendar_ical extends calendar_boupdate if ($version == '1.0') { if ($event['recur_enddate'] && $tzid) - { + { $rrule['UNTIL'] = self::getDateTime($rrule['UNTIL'],$tzid); } $attributes['RRULE'] = $rrule['FREQ'].' '.$rrule['UNTIL']; @@ -690,7 +690,7 @@ class calendar_ical extends calendar_boupdate $event['recur_exception'] = $days; if ($version != '1.0') $parameters['EXDATE']['VALUE'] = 'DATE'; } - if ($this->productManufacturer == 'groupdav' && + if ($this->productManufacturer == 'groupdav' && ($this->productName == 'iphone' || $this->productName == 'davkit')) { foreach ($event['recur_exception'] as $exdate) @@ -917,14 +917,14 @@ class calendar_ical extends calendar_boupdate // RFC requires DESCRIPTION for DISPLAY if (!$event['title'] && !$description) continue; - + if ($this->productName == 'lightning') { // return only future alarms to lightning if (($nextOccurence = $this->read($event['id'], $this->now_su + $alarmData['offset'], false, 'server'))) { $alarmData['time'] = $nextOccurence['start'] - $alarmData['offset']; - $alarmData['offset'] = false; + $alarmData['offset'] = false; } else { @@ -932,12 +932,12 @@ class calendar_ical extends calendar_boupdate } } - if (!empty($event['whole_day']) && $alarmData['offset']) + if (!empty($event['whole_day']) && $alarmData['offset']) { $alarmData['time'] = $event['start'] - $alarmData['offset']; $alarmData['offset'] = false; - } - + } + $valarm = Horde_iCalendar::newComponent('VALARM',$vevent); if ($alarmData['offset']) { @@ -1118,7 +1118,7 @@ class calendar_ical extends calendar_boupdate { calendar_groupdav::fix_series($events); } - + if ($this->tzid) { $tzid = $this->tzid; @@ -1127,9 +1127,9 @@ class calendar_ical extends calendar_boupdate { $tzid = egw_time::$user_timezone->getName(); } - + date_default_timezone_set($tzid); - + foreach ($events as $event) { if (!is_array($event)) continue; // the iterator may return false @@ -1149,7 +1149,7 @@ class calendar_ical extends calendar_boupdate } $updated_id = false; - + if ($replace) { $event_info['type'] = $event['recur_type'] == MCAL_RECUR_NONE ? @@ -1423,6 +1423,12 @@ class calendar_ical extends calendar_boupdate $alarm['owner'] = $this->user; $alarm['all'] = false; + // if no edit rights, allow participants to set alarms directly (like status) + if ($event_info['stored_event'] && !$event_info['acl_edit']) + { + $this->save_alarm($event_info['stored_event']['id'], $alarm); + } + if (is_array($event_info['stored_event']) && count($event_info['stored_event']['alarm']) > 0) { @@ -1458,7 +1464,7 @@ class calendar_ical extends calendar_boupdate } } } - + if ($this->log) { error_log(__FILE__.'['.__LINE__.'] '.__METHOD__ . '(' @@ -1508,7 +1514,7 @@ class calendar_ical extends calendar_boupdate if (is_array($days)) { $recur_exceptions = array(); - + foreach ($event['recur_exception'] as $recur_exception) { if (isset($days[$recur_exception])) @@ -1581,7 +1587,7 @@ class calendar_ical extends calendar_boupdate array_unique(array_merge($event_info['master_event']['recur_exception'], array($event['recurrence']))); } - + $event['reference'] = $event_info['master_event']['id']; $event['category'] = $event_info['master_event']['category']; $event['owner'] = $event_info['master_event']['owner']; @@ -2128,7 +2134,7 @@ class calendar_ical extends calendar_boupdate { return new egw_ical_iterator($_vcalData,'VCALENDAR',$charset,array($this,'_ical2egw_callback'),array($this->tzid,$principalURL)); } - + if ($this->tzid) { $tzid = $this->tzid; @@ -2137,9 +2143,9 @@ class calendar_ical extends calendar_boupdate { $tzid = egw_time::$user_timezone->getName(); } - + date_default_timezone_set($tzid); - + $events = array(); $vcal = new Horde_iCalendar; if (!$vcal->parsevCalendar($_vcalData, 'VCALENDAR', $charset)) @@ -2177,7 +2183,7 @@ class calendar_ical extends calendar_boupdate function _ical2egw_callback(Horde_iCalendar $component, $tzid, $principalURL='') { //unset($component->_container); _debug_array($component); - + if ($this->log) { error_log(__FILE__.'['.__LINE__.'] '.__METHOD__.'() '.get_class($component)." found\n",3,$this->logfile); @@ -2238,7 +2244,7 @@ class calendar_ical extends calendar_boupdate } return false; } - + /* $mozillaACK = $component->getAttribute('X-MOZ-LASTACK'); if ($this->productName == 'lightning' && !is_a($mozillaACK, 'PEAR_Error')) diff --git a/calendar/inc/class.calendar_so.inc.php b/calendar/inc/class.calendar_so.inc.php index 457787d2b7..8a8f1fa8f7 100644 --- a/calendar/inc/class.calendar_so.inc.php +++ b/calendar/inc/class.calendar_so.inc.php @@ -1083,18 +1083,18 @@ ORDER BY cal_user_type, cal_usre_id $alarm['time'] = $event['cal_start'] - $alarm['offset']; } - $start = (int)time() + $alarm['offset']; - if ($alarm['time'] < $start) + if ($alarm['time'] < time()) { //pgoerzen: don't add an alarm in the past if ($event['recur_type'] == MCAL_RECUR_NONE) continue; + $start = (int)time() + $alarm['offset']; $event['start'] = $event['cal_start']; $event['end'] = $event['cal_end']; $event['tzid'] = $event['cal_tzid']; $rrule = calendar_rrule::event2rrule($event, false); foreach ($rrule as $time) { - if ($start< ($ts = egw_time::to($time,'server'))) break; + if ($start < ($ts = egw_time::to($time,'server'))) break; $ts = 0; } if (!$ts) continue; diff --git a/infolog/inc/class.infolog_groupdav.inc.php b/infolog/inc/class.infolog_groupdav.inc.php index 5e92564171..debb0e3a00 100644 --- a/infolog/inc/class.infolog_groupdav.inc.php +++ b/infolog/inc/class.infolog_groupdav.inc.php @@ -331,9 +331,10 @@ class infolog_groupdav extends groupdav_handler * * @param array &$options * @param int $id + * @param int $user=null account_id * @return mixed boolean true on success, false on failure or string with http status (eg. '404 Not Found') */ - function get(&$options,$id) + function get(&$options,$id,$user=null) { if (!is_array($task = $this->_common_get_put_delete('GET',$options,$id))) { diff --git a/phpgwapi/inc/class.groupdav.inc.php b/phpgwapi/inc/class.groupdav.inc.php index c620fc29d4..04437eedc5 100644 --- a/phpgwapi/inc/class.groupdav.inc.php +++ b/phpgwapi/inc/class.groupdav.inc.php @@ -400,7 +400,7 @@ class groupdav extends HTTP_WebDAV_Server { $account_lid = $GLOBALS['egw_info']['user']['account_lid']; } - + if (strlen($user_preferences['calendar']['display_color']) == 9 && $user_preferences['calendar']['display_color'][0] == '#') { @@ -410,7 +410,7 @@ class groupdav extends HTTP_WebDAV_Server { $display_color = '#0040A0FF'; } - + $account = $this->accounts->read($account_lid); $displayname = $GLOBALS['egw']->translation->convert($account['account_fullname'], $GLOBALS['egw']->translation->charset(),'utf-8'); @@ -548,7 +548,7 @@ class groupdav extends HTTP_WebDAV_Server } if (($handler = self::app_handler($app))) { - return $handler->get($options,$id); + return $handler->get($options,$id,$user); } error_log(__METHOD__."(".array2string($options).") 501 Not Implemented"); return '501 Not Implemented'; diff --git a/phpgwapi/inc/class.groupdav_handler.inc.php b/phpgwapi/inc/class.groupdav_handler.inc.php index 3ff46b6e44..dfea82f244 100644 --- a/phpgwapi/inc/class.groupdav_handler.inc.php +++ b/phpgwapi/inc/class.groupdav_handler.inc.php @@ -135,9 +135,10 @@ abstract class groupdav_handler * * @param array &$options * @param int $id + * @param int $user=null account_id * @return mixed boolean true on success, false on failure or string with http status (eg. '404 Not Found') */ - abstract function get(&$options,$id); + abstract function get(&$options,$id,$user=null); /** * Handle get request for an applications entry diff --git a/phpgwapi/inc/class.groupdav_principals.inc.php b/phpgwapi/inc/class.groupdav_principals.inc.php index 3d2cecf464..a8838e4ba3 100644 --- a/phpgwapi/inc/class.groupdav_principals.inc.php +++ b/phpgwapi/inc/class.groupdav_principals.inc.php @@ -13,7 +13,7 @@ /** * EGroupware: GroupDAV access: groupdav/caldav/carddav principals handlers - * + * * @todo All principal urls should either contain no account_lid (eg. base64 of it) or use urlencode($account_lid) */ class groupdav_principals extends groupdav_handler @@ -92,7 +92,7 @@ class groupdav_principals extends groupdav_handler { $displayname = translation::convert($account['account_fullname'], translation::charset(),'utf-8'); - + $props = array( HTTP_WebDAV_Server::mkprop('displayname',$displayname), HTTP_WebDAV_Server::mkprop('getetag',$this->get_etag($account)), @@ -105,7 +105,7 @@ class groupdav_principals extends groupdav_handler HTTP_WebDAV_Server::mkprop(groupdav::CARDDAV,'addressbook-home-set',array( HTTP_WebDAV_Server::mkprop('href',$this->base_uri.'/'.$account['account_lid'].'/'))), ); - + foreach($this->accounts->memberships($account['account_id']) as $gid => $group) { $props[] = HTTP_WebDAV_Server::mkprop('group-membership',$this->base_uri.'/groups/'.$group); @@ -440,9 +440,10 @@ class groupdav_principals extends groupdav_handler * * @param array &$options * @param int $id + * @param int $user=null account_id * @return mixed boolean true on success, false on failure or string with http status (eg. '404 Not Found') */ - function get(&$options,$id) + function get(&$options,$id,$user=null) { if (!is_array($account = $this->_common_get_put_delete('GET',$options,$id))) { @@ -533,7 +534,7 @@ class groupdav_principals extends groupdav_handler } return 'EGw-'.$account['account_id'].':'.md5(serialize($account)). // as the pricipal of current user is influenced by GroupDAV prefs, we have to include them in the etag - ($account['account_id'] == $GLOBALS['egw_info']['user']['account_id'] ? + ($account['account_id'] == $GLOBALS['egw_info']['user']['account_id'] ? ':'.md5(serialize($GLOBALS['egw_info']['user']['preferences']['groupdav'])) : '').'-wGE'; } } \ No newline at end of file