mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-22 16:03:47 +01:00
allow status update via CalDAV/GroupDAV PUT and DELETE for attendees (with no other rights on the event), moved that code from bocalupdate (wasnt working because of wrong param code) to boical, this should work for SyncML and CalDAV/GroupDAV - thought SyncML does not handle the delete to reject an event so far
This commit is contained in:
parent
a659e4eb6b
commit
89eba8038d
@ -81,7 +81,7 @@ class bocalupdate extends bocal
|
||||
*/
|
||||
function update(&$event,$ignore_conflicts=false,$touch_modified=true,$ignore_acl=false)
|
||||
{
|
||||
//error_log(__METHOD__."(".str_replace(array("\n",' '),'',print_r($event,true)).",$ignore_conflicts,$touch_modified,$ignore_acl)");
|
||||
//error_log(__METHOD__."(".array2string($event).",$ignore_conflicts,$touch_modified,$ignore_acl)");
|
||||
if ($this->debug > 1 || $this->debug == 'update')
|
||||
{
|
||||
$this->debug_message('bocalupdate::update(%1,ignore_conflict=%2,touch_modified=%3,ignore_acl=%4)',
|
||||
@ -117,21 +117,6 @@ class bocalupdate extends bocal
|
||||
!$event['id'] && !$this->check_perms(EGW_ACL_EDIT,0,$event['owner'])) &&
|
||||
!$this->check_perms(EGW_ACL_ADD,0,$event['owner']))
|
||||
{
|
||||
// Just update the status, if the user is in the event already
|
||||
// is user is in both original and updated event
|
||||
$egw_event = $this->read($event['id']);
|
||||
|
||||
if ( isset($egw_event['participants'][$this->user])
|
||||
&& isset($event['participants'][$this->user]))
|
||||
{
|
||||
// Update their status in the event and say we're done.
|
||||
// Admittedly, this is false, it's dropping any changes on the floor,
|
||||
// But this will work better than dropping -everything- silently on
|
||||
// the floor
|
||||
$this->set_status($event['id'],'u',$this->user,$event['participants'][$this->user],0);
|
||||
unset($egw_event);
|
||||
return $event['id'];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -234,7 +234,8 @@
|
||||
break;
|
||||
|
||||
case 'ORGANIZER': // according to iCalendar standard, ORGANIZER not used for events in the own calendar
|
||||
if (!isset($event['participants'][$event['owner']]) || count($event['participants']) > 1)
|
||||
if ($event['owner'] != $this->user)
|
||||
//if (!isset($event['participants'][$event['owner']]) || count($event['participants']) > 1)
|
||||
{
|
||||
$mailtoOrganizer = $GLOBALS['egw']->accounts->id2name($event['owner'],'account_email');
|
||||
$attributes['ORGANIZER'] = $mailtoOrganizer ? 'MAILTO:'.$mailtoOrganizer : '';
|
||||
@ -475,7 +476,8 @@
|
||||
$_vcalData = preg_replace("/[\r\n]+ /",'',$_vcalData);
|
||||
|
||||
$vcal = &new Horde_iCalendar;
|
||||
if(!$vcal->parsevCalendar($_vcalData)) {
|
||||
if(!$vcal->parsevCalendar($_vcalData))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -850,6 +852,10 @@
|
||||
{
|
||||
$event['id'] = $cal_id;
|
||||
}
|
||||
elseif($event['id'] && $cal_id <= 0)
|
||||
{
|
||||
$cal_id = $event['id']; // event[id] set via uid
|
||||
}
|
||||
while(($fieldName = array_shift($supportedFields)))
|
||||
{
|
||||
switch($fieldName)
|
||||
@ -892,10 +898,9 @@
|
||||
|
||||
// If this is an updated meeting, and the client doesn't support
|
||||
// participants, add them back
|
||||
if( $cal_id >0 && !isset($this->supportedFields['participants']))
|
||||
if( $cal_id > 0 && !isset($this->supportedFields['participants']))
|
||||
{
|
||||
$egw_event = $this->read($cal_id);
|
||||
if ($egw_event)
|
||||
if (($egw_event = $this->read($cal_id)))
|
||||
{
|
||||
$event['participants'] = $egw_event['participants'];
|
||||
$event['participant_types'] = $egw_event['participant_types'];
|
||||
@ -906,22 +911,26 @@
|
||||
if( $cal_id > 0 )
|
||||
{
|
||||
// for each existing participant:
|
||||
$egw_event = $this->read($cal_id);
|
||||
if ( $egw_event )
|
||||
if (($egw_event = $this->read($cal_id)))
|
||||
{
|
||||
foreach( $egw_event['participants'] as $uid => $status )
|
||||
{
|
||||
// Is it a resource?
|
||||
if ( preg_match("/^r(.*)/", $uid, $matches) )
|
||||
// Is it a resource and not longer present in the event?
|
||||
if ( $uid[0] == 'r' && !isset($event['participants'][$uid]) )
|
||||
{
|
||||
// Add it back in
|
||||
$event['participants'][$uid] = 'A';
|
||||
$event['participant_types']['r'][$matches[1]] = 'A';
|
||||
$event['participants'][$uid] = $event['participant_types']['r'][substr($uid,1)] = $status;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check if iCal changes the organizer, which is not allowed
|
||||
if ($cal_id > 0 && ($egw_event = $this->read($cal_id)) && $event['owner'] != $egw_event['owner'])
|
||||
{
|
||||
$event['owner'] = $egw_event['owner']; // set it back to the original owner
|
||||
}
|
||||
|
||||
#error_log('ALARMS');
|
||||
#error_log(print_r($event, true));
|
||||
|
||||
@ -932,6 +941,16 @@
|
||||
}
|
||||
if (!($Ok = $this->update($event, TRUE)))
|
||||
{
|
||||
// check if current user is an attendee and tried to change his status
|
||||
if ($Ok === false && $cal_id && ($egw_event = $this->read($cal_id)) && isset($egw_event['participants'][$this->user]) &&
|
||||
$egw_event['participants'][$this->user] !== $event['participants'][$this->user])
|
||||
{
|
||||
$this->set_status($egw_event,$this->user,
|
||||
$status = $event['participants'][$this->user] ? $event['participants'][$this->user] : 'R');
|
||||
|
||||
$Ok = $cal_id;
|
||||
continue;
|
||||
}
|
||||
break; // stop with the first error
|
||||
}
|
||||
else
|
||||
|
@ -38,9 +38,16 @@ class calendar_groupdav extends groupdav_handler
|
||||
//'RECURRENCE-ID'
|
||||
);
|
||||
|
||||
function __construct($debug=null)
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $app 'calendar', 'addressbook' or 'infolog'
|
||||
* @param int $debug=null debug-level to set
|
||||
* @param string $base_uri=null base url of handler
|
||||
*/
|
||||
function __construct($app,$debug=null,$base_uri=null)
|
||||
{
|
||||
parent::__construct('calendar',$debug);
|
||||
parent::__construct($app,$debug,$base_uri);
|
||||
|
||||
$this->bo =& new bocalupdate();
|
||||
}
|
||||
@ -57,7 +64,7 @@ class calendar_groupdav extends groupdav_handler
|
||||
*/
|
||||
function propfind($path,$options,&$files,$user,$id='')
|
||||
{
|
||||
if ($this->debug > 2) error_log(__METHOD__."($path,".str_replace(array("\n",' '),'',print_r($options,true)).",,$user,$id)");
|
||||
if ($this->debug) error_log(__METHOD__."($path,".array2string($options).",,$user,$id)");
|
||||
|
||||
// ToDo: add parameter to only return id & etag
|
||||
$cal_filters = array(
|
||||
@ -68,7 +75,7 @@ class calendar_groupdav extends groupdav_handler
|
||||
'daywise' => false,
|
||||
'date_format' => 'server',
|
||||
);
|
||||
error_log(__METHOD__."($path,,,$user,$id) cal_filters=".str_replace(array("\n",' '),'',print_r($cal_filters,true)));
|
||||
if ($this->debug > 1) error_log(__METHOD__."($path,,,$user,$id) cal_filters=".array2string($cal_filters));
|
||||
|
||||
// process REPORT filters or multiget href's
|
||||
if (($id || $options['root']['name'] != 'propfind') && !$this->_report_filters($options,$cal_filters,$id))
|
||||
@ -131,13 +138,13 @@ class calendar_groupdav extends groupdav_handler
|
||||
switch($filter['name'])
|
||||
{
|
||||
case 'comp-filter':
|
||||
error_log(__METHOD__."($path,...) comp-filter='{$filter['attrs']['name']}'");
|
||||
if ($this->debug > 1) error_log(__METHOD__."($path,...) comp-filter='{$filter['attrs']['name']}'");
|
||||
switch($filter['attrs']['name'])
|
||||
{
|
||||
case 'VTODO':
|
||||
return false; // return nothing for now, todo: check if we can pass it on to the infolog handler
|
||||
// todos are handled by the infolog handler
|
||||
$infolog_handler = new infolog_groupdav();
|
||||
$infolog_handler = new groupdav_infolog();
|
||||
return $infolog_handler->propfind($path,$options,$files,$user,$method);
|
||||
case 'VCALENDAR':
|
||||
CASE 'VEVENT':
|
||||
@ -145,14 +152,14 @@ class calendar_groupdav extends groupdav_handler
|
||||
}
|
||||
break;
|
||||
case 'prop-filter':
|
||||
error_log(__METHOD__."($path,...) prop-filter='{$filter['attrs']['name']}'");
|
||||
if ($this->debug > 1) error_log(__METHOD__."($path,...) prop-filter='{$filter['attrs']['name']}'");
|
||||
$prop_filter = $filter['attrs']['name'];
|
||||
break;
|
||||
case 'text-match':
|
||||
error_log(__METHOD__."($path,...) text-match: $prop_filter='{$filter['data']}'");
|
||||
if ($this->debug > 1) error_log(__METHOD__."($path,...) text-match: $prop_filter='{$filter['data']}'");
|
||||
if (!isset($this->filter_prop2cal[strtoupper($prop_filter)]))
|
||||
{
|
||||
error_log(__METHOD__."($path,".str_replace(array("\n",' '),'',print_r($options,true)).",,$user) unknown property '$prop_filter' --> ignored");
|
||||
if ($this->debug) error_log(__METHOD__."($path,".array2string($options).",,$user) unknown property '$prop_filter' --> ignored");
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -161,14 +168,15 @@ class calendar_groupdav extends groupdav_handler
|
||||
unset($prop_filter);
|
||||
break;
|
||||
case 'param-filter':
|
||||
error_log(__METHOD__."($path,...) param-filter='{$filter['attrs']['name']}'");
|
||||
if ($this->debug) error_log(__METHOD__."($path,...) param-filter='{$filter['attrs']['name']}' not (yet) implemented!");
|
||||
break;
|
||||
case 'time-range':
|
||||
error_log(__METHOD__."($path,...) time-range={$filter['attrs']['start']}-{$filter['attrs']['end']}");
|
||||
|
||||
if ($this->debug > 1) error_log(__METHOD__."($path,...) time-range={$filter['attrs']['start']}-{$filter['attrs']['end']}");
|
||||
$cal_filters['start'] = $filter['attrs']['start'];
|
||||
$cal_filters['end'] = $filter['attrs']['end'];
|
||||
break;
|
||||
default:
|
||||
error_log(__METHOD__."($path,".str_replace(array("\n",' '),'',print_r($options,true)).",,$user) unknown filter --> ignored");
|
||||
if ($this->debug) error_log(__METHOD__."($path,".array2string($options).",,$user) unknown filter --> ignored");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -214,7 +222,7 @@ class calendar_groupdav extends groupdav_handler
|
||||
{
|
||||
$cal_filters['query'][] = 'egw_cal.cal_id IN ('.implode(',',array_map(create_function('$n','return (int)$n;'),$ids)).')';
|
||||
}
|
||||
//error_log(__METHOD__."($path,,,$user,$id) calendar-multiget: ids=".implode(',',$ids));
|
||||
if ($this->debug) error_log(__METHOD__."($path,,,$user,$id) calendar-multiget: ids=".implode(',',$ids));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -249,7 +257,8 @@ class calendar_groupdav extends groupdav_handler
|
||||
*/
|
||||
function put(&$options,$id,$user=null)
|
||||
{
|
||||
$event = $this->_common_get_put_delete('PUT',$options,$id);
|
||||
$return_no_access=true; // as handled by importVCal anyway and allows it to set the status for participants
|
||||
$event = $this->_common_get_put_delete('PUT',$options,$id,$return_no_access);
|
||||
if (!is_null($event) && !is_array($event))
|
||||
{
|
||||
return $event;
|
||||
@ -257,14 +266,14 @@ class calendar_groupdav extends groupdav_handler
|
||||
if (!($cal_id = ExecMethod2('calendar.boical.importVCal',$options['content'],is_numeric($id) ? $id : -1,
|
||||
self::etag2value($this->http_if_match))))
|
||||
{
|
||||
if ($this->debug) error_log(__METHOD__."(,$id) import_vevent($options[content]) returned false");
|
||||
return false; // something went wrong ...
|
||||
if ($this->debug) error_log(__METHOD__."(,$id) importVCal($options[content]) returned false");
|
||||
return '403 Forbidden';
|
||||
}
|
||||
|
||||
header('ETag: '.$this->get_etag($cal_id));
|
||||
if (is_null($event))
|
||||
if (is_null($event) || !$return_no_access) // let lightning think the event is added
|
||||
{
|
||||
error_log(__METHOD__."(,$id,$user) cal_id=$cal_id, is_null(\$event)=".(int)is_null($event));
|
||||
if ($this->debug) error_log(__METHOD__."(,$id,$user) cal_id=$cal_id, is_null(\$event)=".(int)is_null($event));
|
||||
header('Location: '.$this->base_uri.'/calendar/'.$cal_id);
|
||||
return '201 Created';
|
||||
}
|
||||
@ -274,14 +283,24 @@ class calendar_groupdav extends groupdav_handler
|
||||
/**
|
||||
* Handle delete request for an event
|
||||
*
|
||||
* If current user has no right to delete the event, but is an attendee, we reject the event for him.
|
||||
*
|
||||
* @param array &$options
|
||||
* @param int $id
|
||||
* @return mixed boolean true on success, false on failure or string with http status (eg. '404 Not Found')
|
||||
*/
|
||||
function delete(&$options,$id)
|
||||
{
|
||||
if (!is_array($event = $this->_common_get_put_delete('DELETE',$options,$id)))
|
||||
$return_no_access=true; // to allow to check if current use is a participant and reject the event for him
|
||||
if (!is_array($event = $this->_common_get_put_delete('DELETE',$options,$id,$return_no_access)) || !$return_no_access)
|
||||
{
|
||||
if (!$return_no_access)
|
||||
{
|
||||
$ret = isset($event['participants'][$this->bo->user]) &&
|
||||
$this->bo->set_status($event,$this->bo->user,'R') ? true : '403 Forbidden';
|
||||
if ($this->debug) error_log(__METHOD__."(,$id) return_no_access=$return_no_access, event[participants]=".array2string($event['participants']).", user={$this->bo->user} --> return $ret");
|
||||
return $ret;
|
||||
}
|
||||
return $event;
|
||||
}
|
||||
return $this->bo->delete($id);
|
||||
@ -306,16 +325,18 @@ class calendar_groupdav extends groupdav_handler
|
||||
*/
|
||||
function get_etag($entry)
|
||||
{
|
||||
$e_in = $entry;
|
||||
if (!is_array($entry))
|
||||
{
|
||||
$entry = $this->read($entry);
|
||||
}
|
||||
if (!$entry['id'] || !isset($entry['etag']) || !isset($entry['participants'])) error_log(__METHOD__."($e_in): id=$entry[id], etag=$entry[etag], isset(participants)=".(int)isset($entry['participants']).", title=$entry[title]: id, etag or participants not set!!!");
|
||||
$etag = $entry['id'].':'.$entry['etag'];
|
||||
// add a hash over the participants and their stati
|
||||
ksort($entry['participants']); // create a defined order
|
||||
$etag .= ':'.md5(serialize($entry['participants']));
|
||||
//error_log(__METHOD__."($entry[id] ($entry[etag]): $entry[title] --> etag=$etag");
|
||||
return $etag;
|
||||
return $etag.'x';
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user