mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-22 16:03:47 +01:00
njv: calendar/groupdav work to improve groupdav compatibility and various sync proplems connected
This commit is contained in:
parent
e1e09203ed
commit
085961d7e1
@ -43,7 +43,7 @@ class calendar_groupdav extends groupdav_handler
|
|||||||
* @param int $debug=null debug-level to set
|
* @param int $debug=null debug-level to set
|
||||||
* @param string $base_uri=null base url of handler
|
* @param string $base_uri=null base url of handler
|
||||||
*/
|
*/
|
||||||
function __construct($app,$debug=null,$base_uri=null)
|
function __construct($app,$debug=null, $base_uri=null)
|
||||||
{
|
{
|
||||||
parent::__construct($app,$debug,$base_uri);
|
parent::__construct($app,$debug,$base_uri);
|
||||||
|
|
||||||
@ -85,18 +85,20 @@ class calendar_groupdav extends groupdav_handler
|
|||||||
function propfind($path,$options,&$files,$user,$id='')
|
function propfind($path,$options,&$files,$user,$id='')
|
||||||
{
|
{
|
||||||
if ($this->debug) error_log(__METHOD__."($path,".array2string($options).",,$user,$id)");
|
if ($this->debug) error_log(__METHOD__."($path,".array2string($options).",,$user,$id)");
|
||||||
|
//error_log(__METHOD__."($path,".array2string($options).",,$user,$id)");//njv:
|
||||||
// ToDo: add parameter to only return id & etag
|
// ToDo: add parameter to only return id & etag
|
||||||
|
//error_log( __FILE__ . __METHOD__ ." :$user ". print_r($options,true));
|
||||||
|
$st = microtime(true);
|
||||||
$cal_filters = array(
|
$cal_filters = array(
|
||||||
'users' => $user,
|
'users' => $user,
|
||||||
'start' => time()-30*24*3600, // default one month back
|
'start' => time()-100*24*3600, // default one month back -30 breaks all sync recurrences
|
||||||
'end' => time()+365*24*3600, // default one year into the future
|
'end' => time()+365*24*3600, // default one year into the future +365
|
||||||
'enum_recuring' => false,
|
'enum_recuring' => false,
|
||||||
'daywise' => false,
|
'daywise' => false,
|
||||||
'date_format' => 'server',
|
'date_format' => 'server',
|
||||||
);
|
);
|
||||||
if ($this->debug > 1) error_log(__METHOD__."($path,,,$user,$id) cal_filters=".array2string($cal_filters));
|
if ($this->debug > 1) error_log(__METHOD__."($path,,,$user,$id) cal_filters=".array2string($cal_filters));
|
||||||
|
//error_log(__METHOD__."($path,,,$user,$id) cal_filters=".array2string($cal_filters));//njv
|
||||||
// process REPORT filters or multiget href's
|
// process REPORT filters or multiget href's
|
||||||
if (($id || $options['root']['name'] != 'propfind') && !$this->_report_filters($options,$cal_filters,$id))
|
if (($id || $options['root']['name'] != 'propfind') && !$this->_report_filters($options,$cal_filters,$id))
|
||||||
{
|
{
|
||||||
@ -114,6 +116,7 @@ class calendar_groupdav extends groupdav_handler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//error_log(__FILE__ . __METHOD__ ."Filters:" .print_r($cal_filters,true));
|
||||||
if (($events = $this->bo->search($cal_filters)))
|
if (($events = $this->bo->search($cal_filters)))
|
||||||
{
|
{
|
||||||
foreach($events as $event)
|
foreach($events as $event)
|
||||||
@ -126,6 +129,7 @@ class calendar_groupdav extends groupdav_handler
|
|||||||
// getlastmodified and getcontentlength are required by WebDAV and Cadaver eg. reports 404 Not found if not set
|
// getlastmodified and getcontentlength are required by WebDAV and Cadaver eg. reports 404 Not found if not set
|
||||||
HTTP_WebDAV_Server::mkprop('getlastmodified', $event['modified']),
|
HTTP_WebDAV_Server::mkprop('getlastmodified', $event['modified']),
|
||||||
);
|
);
|
||||||
|
//error_log(__FILE__ . __METHOD__ . "Calendar Data : $calendar_data");
|
||||||
if ($calendar_data)
|
if ($calendar_data)
|
||||||
{
|
{
|
||||||
if (is_null($handler)) $handler = $this->_get_handler();
|
if (is_null($handler)) $handler = $this->_get_handler();
|
||||||
@ -143,6 +147,8 @@ class calendar_groupdav extends groupdav_handler
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$end = microtime(true) - $st;
|
||||||
|
if ($this->debug) error_log(__FILE__ . __METHOD__ . "Function took : $end");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,6 +175,7 @@ class calendar_groupdav extends groupdav_handler
|
|||||||
{
|
{
|
||||||
case 'comp-filter':
|
case 'comp-filter':
|
||||||
if ($this->debug > 1) 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'])
|
switch($filter['attrs']['name'])
|
||||||
{
|
{
|
||||||
case 'VTODO':
|
case 'VTODO':
|
||||||
@ -177,7 +184,7 @@ class calendar_groupdav extends groupdav_handler
|
|||||||
$infolog_handler = new groupdav_infolog();
|
$infolog_handler = new groupdav_infolog();
|
||||||
return $infolog_handler->propfind($path,$options,$files,$user,$method);
|
return $infolog_handler->propfind($path,$options,$files,$user,$method);
|
||||||
case 'VCALENDAR':
|
case 'VCALENDAR':
|
||||||
CASE 'VEVENT':
|
case 'VEVENT':
|
||||||
break; // that's our default anyway
|
break; // that's our default anyway
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -201,7 +208,7 @@ class calendar_groupdav extends groupdav_handler
|
|||||||
if ($this->debug) error_log(__METHOD__."($path,...) param-filter='{$filter['attrs']['name']}' not (yet) implemented!");
|
if ($this->debug) error_log(__METHOD__."($path,...) param-filter='{$filter['attrs']['name']}' not (yet) implemented!");
|
||||||
break;
|
break;
|
||||||
case 'time-range':
|
case 'time-range':
|
||||||
if ($this->debug > 1) error_log(__METHOD__."($path,...) time-range={$filter['attrs']['start']}-{$filter['attrs']['end']}");
|
if ($this->debug > 1) error_log(__FILE__ . __METHOD__."($path,...) time-range={$filter['attrs']['start']}-{$filter['attrs']['end']}");
|
||||||
$cal_filters['start'] = $filter['attrs']['start'];
|
$cal_filters['start'] = $filter['attrs']['start'];
|
||||||
$cal_filters['end'] = $filter['attrs']['end'];
|
$cal_filters['end'] = $filter['attrs']['end'];
|
||||||
break;
|
break;
|
||||||
@ -217,6 +224,7 @@ class calendar_groupdav extends groupdav_handler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// multiget or propfind on a given id
|
// multiget or propfind on a given id
|
||||||
|
//error_log(__FILE__ . __METHOD__ . "multiget of propfind:");
|
||||||
if ($options['root']['name'] == 'calendar-multiget' || $id)
|
if ($options['root']['name'] == 'calendar-multiget' || $id)
|
||||||
{
|
{
|
||||||
// no standard time-range!
|
// no standard time-range!
|
||||||
@ -241,9 +249,11 @@ class calendar_groupdav extends groupdav_handler
|
|||||||
{
|
{
|
||||||
foreach($options['other'] as $option)
|
foreach($options['other'] as $option)
|
||||||
{
|
{
|
||||||
|
|
||||||
if ($option['name'] == 'href')
|
if ($option['name'] == 'href')
|
||||||
{
|
{
|
||||||
$parts = explode('/',$option['data']);
|
$parts = explode('/',$option['data']);
|
||||||
|
|
||||||
if (is_numeric($id = basename(array_pop($parts),'.ics'))) $ids[] = $id;
|
if (is_numeric($id = basename(array_pop($parts),'.ics'))) $ids[] = $id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -252,7 +262,8 @@ class calendar_groupdav extends groupdav_handler
|
|||||||
{
|
{
|
||||||
$cal_filters['query'][] = 'egw_cal.cal_id IN ('.implode(',',array_map(create_function('$n','return (int)$n;'),$ids)).')';
|
$cal_filters['query'][] = 'egw_cal.cal_id IN ('.implode(',',array_map(create_function('$n','return (int)$n;'),$ids)).')';
|
||||||
}
|
}
|
||||||
if ($this->debug) error_log(__METHOD__."($path,,,$user,$id) calendar-multiget: ids=".implode(',',$ids));
|
|
||||||
|
if ($this->debug > 1) error_log(__FILE__ . __METHOD__ ."($path,,,$user,$id) calendar-multiget: ids=".implode(',',$ids));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -288,10 +299,14 @@ class calendar_groupdav extends groupdav_handler
|
|||||||
*/
|
*/
|
||||||
function put(&$options,$id,$user=null)
|
function put(&$options,$id,$user=null)
|
||||||
{
|
{
|
||||||
|
if($this->debug) error_log(__METHOD__."($id, $user)".print_r($options,true));
|
||||||
$return_no_access=true; // as handled by importVCal anyway and allows it to set the status for participants
|
$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);
|
$event = $this->_common_get_put_delete('PUT',$options,$id,$return_no_access);
|
||||||
|
|
||||||
if (!is_null($event) && !is_array($event))
|
if (!is_null($event) && !is_array($event))
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if($this->debug) error_log(__METHOD__.print_r($event,true).function_backtrace());
|
||||||
return $event;
|
return $event;
|
||||||
}
|
}
|
||||||
$handler = $this->_get_handler();
|
$handler = $this->_get_handler();
|
||||||
@ -346,6 +361,8 @@ class calendar_groupdav extends groupdav_handler
|
|||||||
*/
|
*/
|
||||||
function read($id)
|
function read($id)
|
||||||
{
|
{
|
||||||
|
//$cal_read = $this->bo->read($id,null,false,'server');//njv: do we actually get anything
|
||||||
|
if ($this->debug > 1) error_log("bo-ical read :$id:");//njv:
|
||||||
return $this->bo->read($id,null,false,'server');
|
return $this->bo->read($id,null,false,'server');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -362,12 +379,14 @@ class calendar_groupdav extends groupdav_handler
|
|||||||
{
|
{
|
||||||
$entry = $this->read($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!!!");
|
if (!$entry['id'] || !isset($entry['etag']) || !isset($entry['participants'])) {
|
||||||
|
if ($this->debug > 1) error_log(__FILE__ . __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'];
|
$etag = $entry['id'].':'.$entry['etag'];
|
||||||
// add a hash over the participants and their stati
|
// add a hash over the participants and their stati
|
||||||
ksort($entry['participants']); // create a defined order
|
ksort($entry['participants']); // create a defined order
|
||||||
$etag .= ':'.md5(serialize($entry['participants']));
|
$etag .= ':'.md5(serialize($entry['participants']));
|
||||||
//error_log(__METHOD__."($entry[id] ($entry[etag]): $entry[title] --> etag=$etag");
|
//error_log(__FILE__ .__METHOD__ . "($entry[id] ($entry[etag]): $entry[title] --> etag=$etag");
|
||||||
return $etag;
|
return $etag;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -408,7 +427,8 @@ class calendar_groupdav extends groupdav_handler
|
|||||||
{
|
{
|
||||||
$handler =& new calendar_ical();
|
$handler =& new calendar_ical();
|
||||||
$handler->setSupportedFields('GroupDAV',$this->agent);
|
$handler->setSupportedFields('GroupDAV',$this->agent);
|
||||||
|
if ($this->debug > 1) error_log("ical Handler called:" . $this->agent);
|
||||||
return $handler;
|
return $handler;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,6 +111,7 @@ class calendar_ical extends calendar_boupdate
|
|||||||
*/
|
*/
|
||||||
function &exportVCal($events,$version='1.0', $method='PUBLISH')
|
function &exportVCal($events,$version='1.0', $method='PUBLISH')
|
||||||
{
|
{
|
||||||
|
// error_log(__FILE__ . __METHOD__ ."exportVCal is called ");
|
||||||
$egwSupportedFields = array(
|
$egwSupportedFields = array(
|
||||||
'CLASS' => array('dbName' => 'public'),
|
'CLASS' => array('dbName' => 'public'),
|
||||||
'SUMMARY' => array('dbName' => 'title'),
|
'SUMMARY' => array('dbName' => 'title'),
|
||||||
@ -225,8 +226,8 @@ class calendar_ical extends calendar_boupdate
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'ORGANIZER': // according to iCalendar standard, ORGANIZER not used for events in the own calendar
|
case 'ORGANIZER': // according to iCalendar standard, ORGANIZER not used for events in the own calendar
|
||||||
if ($event['owner'] != $this->user)
|
//if ($event['owner'] != $this->user)
|
||||||
//if (!isset($event['participants'][$event['owner']]) || count($event['participants']) > 1)
|
if (!isset($event['participants'][$event['owner']]) || count($event['participants']) > 1)
|
||||||
{
|
{
|
||||||
$mailtoOrganizer = $GLOBALS['egw']->accounts->id2name($event['owner'],'account_email');
|
$mailtoOrganizer = $GLOBALS['egw']->accounts->id2name($event['owner'],'account_email');
|
||||||
$attributes['ORGANIZER'] = $mailtoOrganizer ? 'MAILTO:'.$mailtoOrganizer : '';
|
$attributes['ORGANIZER'] = $mailtoOrganizer ? 'MAILTO:'.$mailtoOrganizer : '';
|
||||||
@ -237,9 +238,33 @@ class calendar_ical extends calendar_boupdate
|
|||||||
|
|
||||||
case 'DTEND':
|
case 'DTEND':
|
||||||
// write start + end of whole day events as dates
|
// write start + end of whole day events as dates
|
||||||
|
// $event['end'] += 12*3600;
|
||||||
|
// we need the date of the next day, as DTEND is non-inclusive (= exclusive) in rfc2445
|
||||||
|
//njv: This appears to be another urban myth misinterpretation 20090220
|
||||||
|
|
||||||
|
/*
|
||||||
|
DTSTART;VALUE=DATE:20090317 implies 000000Z
|
||||||
|
DTEND;VALUE=DATE:20090317 implies 235959Z
|
||||||
|
And DEFINES an ALLDAY event
|
||||||
|
and as such is "inclusive"
|
||||||
|
some clients(Lightning, Korganiser?) use "exclusive"
|
||||||
|
Legacy: EGW held 235900 As DTEND allday, such entries in databases will exist
|
||||||
|
EGW is internally correct on 235959 "inclusive"
|
||||||
|
*/
|
||||||
|
// Whats in DTSTART/DTEND
|
||||||
|
//error_log(__FILE__ . __METHOD__. "\nDTSTART:". print_r($event['start'],true)."\nDTEND:".print_r($event['end'],true));
|
||||||
|
//Lets do it right first:
|
||||||
|
//If (YMD DTSTART == YMD DTEND) and (His DTSTART == 00:00:00 )and (His DTEND in 235900 or 235959) then we are oneday allday return YMD DTSTART DTEND
|
||||||
|
//if (YMD DTSTART <= YMD DTEND) and (HIS DTSTART == 00:00:00) (His DTEND in 235900 or 235959) then we are all day or allday multiday ending in an allday return DTG DTSTART and DTEND
|
||||||
|
//error_log(__FILE__ . __METHOD__ ." :$this->productManufacturer :$this->productName" );
|
||||||
|
// returns "GroupDAV" "kde"
|
||||||
|
|
||||||
if (date('H:i:s',$event['start']) == '00:00:00' && in_array(date('H:i:s',$event['end']),array('23:59:59','23:59:00')))
|
if (date('H:i:s',$event['start']) == '00:00:00' && in_array(date('H:i:s',$event['end']),array('23:59:59','23:59:00')))
|
||||||
{
|
{
|
||||||
$event['end'] += 12*3600; // we need the date of the next day, as DTEND is non-inclusive (= exclusive) in rfc2445
|
//if kde or lightning increase dtend by 24 hours? 86400 secs
|
||||||
|
if($this->productName == "kde" || $this->productName == "lightning"){
|
||||||
|
$event['end'] += 86400;
|
||||||
|
}
|
||||||
foreach(array('start' => 'DTSTART','end' => 'DTEND') as $f => $t)
|
foreach(array('start' => 'DTSTART','end' => 'DTEND') as $f => $t)
|
||||||
{
|
{
|
||||||
$arr = calendar_bo::date2array($event[$f]);
|
$arr = calendar_bo::date2array($event[$f]);
|
||||||
@ -447,24 +472,34 @@ class calendar_ical extends calendar_boupdate
|
|||||||
$valueData = $GLOBALS['egw']->translation->convert($valueData,$GLOBALS['egw']->translation->charset(),'UTF-8');
|
$valueData = $GLOBALS['egw']->translation->convert($valueData,$GLOBALS['egw']->translation->charset(),'UTF-8');
|
||||||
$paramData = (array) $GLOBALS['egw']->translation->convert(is_array($value) ? $parameters[$key][$valueID] : $parameters[$key],
|
$paramData = (array) $GLOBALS['egw']->translation->convert(is_array($value) ? $parameters[$key][$valueID] : $parameters[$key],
|
||||||
$GLOBALS['egw']->translation->charset(),'UTF-8');
|
$GLOBALS['egw']->translation->charset(),'UTF-8');
|
||||||
//echo "$key:$valueID: value=$valueData, param=".print_r($paramDate,true)."\n";
|
|
||||||
$vevent->setAttribute($key, $valueData, $paramData);
|
$vevent->setAttribute($key, $valueData, $paramData);
|
||||||
$options = array();
|
$options = array();
|
||||||
if ($paramData['CN']) $valueData .= $paramData['CN']; // attendees or organizer CN can contain utf-8 content
|
if ($paramData['CN']) $valueData .= $paramData['CN']; // attendees or organizer CN can contain utf-8 content
|
||||||
if($key != 'RRULE' && preg_match('/([\000-\012\015\016\020-\037\075])/',$valueData))
|
|
||||||
{
|
if($this->productManufacturer == 'file' || $this->productManufacturer == 'GroupDAV') {
|
||||||
$options['ENCODING'] = 'QUOTED-PRINTABLE';
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if($key != 'RRULE' && preg_match('/([\000-\012\015\016\020-\037\075])/',$valueData))
|
||||||
|
{
|
||||||
|
error_log(__FILE__ . __METHOD__ . "QP key $key: ".print_r($valueData,true));
|
||||||
|
$options['ENCODING'] = 'QUOTED-PRINTABLE';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if($this->productManufacturer != 'GroupDAV' && preg_match('/([\177-\377])/',$valueData))
|
|
||||||
|
if($this->productManufacturer != 'GroupDAV' && preg_match('/([\177-\377])/',$valueData))
|
||||||
{
|
{
|
||||||
$options['CHARSET'] = 'UTF-8';
|
$options['CHARSET'] = 'UTF-8';
|
||||||
}
|
}
|
||||||
$vevent->setParameter($key, $options);
|
if(preg_match('/([\000-\012])/',$valueData))
|
||||||
|
{
|
||||||
|
error_log(__FILE__ . __METHOD__ ."Has invalid XML data :$valueData");
|
||||||
|
}
|
||||||
|
$vevent->setParameter($key, $options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$vcal->addComponent($vevent);
|
$vcal->addComponent($vevent);
|
||||||
}
|
}
|
||||||
//_debug_array($vcal->exportvCalendar());
|
|
||||||
|
|
||||||
return $vcal->exportvCalendar();
|
return $vcal->exportvCalendar();
|
||||||
}
|
}
|
||||||
@ -481,7 +516,6 @@ class calendar_ical extends calendar_boupdate
|
|||||||
{
|
{
|
||||||
// our (patched) horde classes, do NOT unfold folded lines, which causes a lot trouble in the import
|
// our (patched) horde classes, do NOT unfold folded lines, which causes a lot trouble in the import
|
||||||
$_vcalData = preg_replace("/[\r\n]+ /",'',$_vcalData);
|
$_vcalData = preg_replace("/[\r\n]+ /",'',$_vcalData);
|
||||||
|
|
||||||
$vcal = &new Horde_iCalendar;
|
$vcal = &new Horde_iCalendar;
|
||||||
if(!$vcal->parsevCalendar($_vcalData))
|
if(!$vcal->parsevCalendar($_vcalData))
|
||||||
{
|
{
|
||||||
@ -489,7 +523,7 @@ class calendar_ical extends calendar_boupdate
|
|||||||
}
|
}
|
||||||
|
|
||||||
$version = $vcal->getAttribute('VERSION');
|
$version = $vcal->getAttribute('VERSION');
|
||||||
|
error_log(__FILE__ . __METHOD__ ."Called with :\n ". print_r($_vcalData,true));
|
||||||
if(!is_array($this->supportedFields))
|
if(!is_array($this->supportedFields))
|
||||||
{
|
{
|
||||||
$this->setSupportedFields();
|
$this->setSupportedFields();
|
||||||
@ -520,6 +554,7 @@ class calendar_ical extends calendar_boupdate
|
|||||||
// lets see what we can get from the vcard
|
// lets see what we can get from the vcard
|
||||||
foreach($component->_attributes as $attributes)
|
foreach($component->_attributes as $attributes)
|
||||||
{
|
{
|
||||||
|
//error_log(__FILE__ . __METHOD__ .":" . print_r($attributes,true));
|
||||||
switch($attributes['name'])
|
switch($attributes['name'])
|
||||||
{
|
{
|
||||||
case 'AALARM':
|
case 'AALARM':
|
||||||
@ -555,10 +590,33 @@ class calendar_ical extends calendar_boupdate
|
|||||||
$vcardData['description'] = $attributes['value'];
|
$vcardData['description'] = $attributes['value'];
|
||||||
break;
|
break;
|
||||||
case 'DTEND':
|
case 'DTEND':
|
||||||
$dtend_ts = is_numeric($attributes['value']) ? $attributes['value'] : $this->date2ts($attributes['value']);
|
/*
|
||||||
if(date('H:i:s',$dtend_ts) == '00:00:00') {
|
DTSTART;VALUE=DATE:20090317 implies 000000Z
|
||||||
$dtend_ts -= 60;
|
DTEND;VALUE=DATE:20090317 implies 235959Z
|
||||||
|
And DEFINES an ALLDAY event
|
||||||
|
and as such is "inclusive"
|
||||||
|
some clients(Lightning, Korganiser?) use "exclusive"
|
||||||
|
Legacy: EGW held 235900 As DTEND allday, such entries in databases will exist
|
||||||
|
EGW is internally correct on 235959 "inclusive"
|
||||||
|
*/
|
||||||
|
// We aren't allday
|
||||||
|
$allday = false;
|
||||||
|
// get and ensure the DTSTART/DTEND is a numeric Timestamp
|
||||||
|
$dtstart_ts = self::_get_attribute($component->_attributes,'DTSTART');
|
||||||
|
$dtstart_ts = is_numeric($dtstart_ts) ? $dtstart_ts : $this->date2ts($dtstart_ts);
|
||||||
|
$dtend_ts = self::_get_attribute($component->_attributes,'DTEND');
|
||||||
|
$dtend_ts = is_numeric($dtend_ts) ? $dtend_ts : $this->date2ts($dtend_ts);
|
||||||
|
//Plausibility Check and Convert Vcal/ical Allday to EGW Allday
|
||||||
|
if($dtstart_ts <= $dtend_ts && date('H:i:s',$dtend_ts) == '00:00:00'){
|
||||||
|
// We are a one day Allday event or Allday last day of a sequence
|
||||||
|
// dtend_ts += 23:59:59 +=86339 = EGW intern
|
||||||
|
$allday = true;
|
||||||
|
$dtend_ts += 86399;
|
||||||
}
|
}
|
||||||
|
//if kde or lightning reduce dtend by 24 hours? 86400 secs
|
||||||
|
if($allday && ($this->productName == "kde" || $this->productName == "lightning")){
|
||||||
|
$dtend_ts -= 86400;
|
||||||
|
}
|
||||||
$vcardData['end'] = $dtend_ts;
|
$vcardData['end'] = $dtend_ts;
|
||||||
break;
|
break;
|
||||||
case 'DTSTART':
|
case 'DTSTART':
|
||||||
@ -784,7 +842,8 @@ class calendar_ical extends calendar_boupdate
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'ATTENDEE':
|
case 'ATTENDEE':
|
||||||
if (preg_match('/MAILTO:([@.a-z0-9_-]+)/i',$attributes['value'],$matches) ||
|
error_log(__FILE__ . __METHOD__ . "case:ATTENDEE:" . print_r($attributes,true));
|
||||||
|
if (preg_match('/MAILTO:([@.a-z0-9_-]+)/i',$attributes['value'],$matches) ||
|
||||||
preg_match('/<([@.a-z0-9_-]+)>/i',$attributes['value'],$matches))
|
preg_match('/<([@.a-z0-9_-]+)>/i',$attributes['value'],$matches))
|
||||||
{
|
{
|
||||||
$email = $matches[1];
|
$email = $matches[1];
|
||||||
@ -838,12 +897,16 @@ class calendar_ical extends calendar_boupdate
|
|||||||
if (!$email) $email = 'no-email@egroupware.org'; // set dummy email to store the CN
|
if (!$email) $email = 'no-email@egroupware.org'; // set dummy email to store the CN
|
||||||
$uid = 'e'.($attributes['params']['CN'] ? $attributes['params']['CN'].' <'.$email.'>' : $email);
|
$uid = 'e'.($attributes['params']['CN'] ? $attributes['params']['CN'].' <'.$email.'>' : $email);
|
||||||
}
|
}
|
||||||
$event['participants'][$uid] = isset($attributes['params']['PARTSTAT']) ?
|
|
||||||
|
error_log(__FILE__ . __METHOD__ . "\n ATTENDEE:" . print_r($attributes['value'],true));
|
||||||
|
$event['participants'][$uid] = isset($attributes['params']['PARTSTAT']) ?
|
||||||
$this->status_ical2egw[strtoupper($attributes['params']['PARTSTAT'])] :
|
$this->status_ical2egw[strtoupper($attributes['params']['PARTSTAT'])] :
|
||||||
($uid == $event['owner'] ? 'A' : 'U');
|
($uid == $event['owner'] ? 'A' : 'U');
|
||||||
break;
|
|
||||||
|
break;
|
||||||
case 'ORGANIZER': // will be written direct to the event
|
case 'ORGANIZER': // will be written direct to the event
|
||||||
if (preg_match('/MAILTO:([@.a-z0-9_-]+)/i',$attributes['value'],$matches) &&
|
error_log(__FILE__ . __METHOD__ . "\n ORGANIZER:" . print_r($attributes['value'],true));
|
||||||
|
if (preg_match('/MAILTO:([@.a-z0-9_-]+)/i',$attributes['value'],$matches) &&
|
||||||
($uid = $GLOBALS['egw']->accounts->name2id($matches[1],'account_email')))
|
($uid = $GLOBALS['egw']->accounts->name2id($matches[1],'account_email')))
|
||||||
{
|
{
|
||||||
$event['owner'] = $uid;
|
$event['owner'] = $uid;
|
||||||
@ -857,7 +920,7 @@ class calendar_ical extends calendar_boupdate
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//error_log(__FILE__ . __METHOD__ . "\n after case:" . print_r($event['participants'],true));
|
||||||
// check if the entry is a birthday
|
// check if the entry is a birthday
|
||||||
// this field is only set from NOKIA clients
|
// this field is only set from NOKIA clients
|
||||||
$agendaEntryType = $component->getAttribute('X-EPOCAGENDAENTRYTYPE');
|
$agendaEntryType = $component->getAttribute('X-EPOCAGENDAENTRYTYPE');
|
||||||
@ -936,6 +999,7 @@ class calendar_ical extends calendar_boupdate
|
|||||||
// participants OR the event no longer contains participants, add them back
|
// participants OR the event no longer contains participants, add them back
|
||||||
if( $cal_id > 0 && (!isset($this->supportedFields['participants']) || !count($event['participants'])))
|
if( $cal_id > 0 && (!isset($this->supportedFields['participants']) || !count($event['participants'])))
|
||||||
{
|
{
|
||||||
|
|
||||||
if (($egw_event = $this->read($cal_id)))
|
if (($egw_event = $this->read($cal_id)))
|
||||||
{
|
{
|
||||||
$event['participants'] = $egw_event['participants'];
|
$event['participants'] = $egw_event['participants'];
|
||||||
@ -973,21 +1037,40 @@ class calendar_ical extends calendar_boupdate
|
|||||||
}
|
}
|
||||||
|
|
||||||
#error_log('ALARMS');
|
#error_log('ALARMS');
|
||||||
#error_log(print_r($event, true));
|
//error_log(__FILE__ . __METHOD__ ."whats in event". print_r($event, true));
|
||||||
|
|
||||||
// if an etag is given, include it in the update
|
// if an etag is given, include it in the update
|
||||||
if (!is_null($etag))
|
if (!is_null($etag))
|
||||||
{
|
{
|
||||||
$event['etag'] = $etag;
|
$event['etag'] = $etag;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
We have for CREATE:
|
||||||
|
if vcal OWNER set then either this->user = OWNER or has add rights to owners Calendar
|
||||||
|
We have for UPDATE:
|
||||||
|
vcal OWNER = EGW owner
|
||||||
|
case: this->user = OWNER then all rights (C-ok,R-ok,U-?,D-ok)
|
||||||
|
*/
|
||||||
|
if($this->user == $event['owner']){
|
||||||
|
//error_log("\nuser:$this->user owner:". print_r($event['owner'],true));
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
case: this->user = participant then only change own status
|
||||||
|
*/
|
||||||
|
if(array_key_exists($this->user,$event['participants'])){
|
||||||
|
// error_log("\nuser:$this->user : ". print_r($egw_event,true));
|
||||||
|
}
|
||||||
|
$original_event = $event;
|
||||||
|
//error_log(__FILE__ . __METHOD__ . "\n after case:" . print_r($event['participants'],true));
|
||||||
if (!($Ok = $this->update($event, TRUE)))
|
if (!($Ok = $this->update($event, TRUE)))
|
||||||
{
|
{
|
||||||
// check if current user is an attendee and tried to change his status
|
// check if current user is an attendee and tried to change his status
|
||||||
|
//error_log(__FILE__ . __METHOD__ . "\n:in update" . print_r($egw_event,true));
|
||||||
if ($Ok === false && $cal_id && ($egw_event = $this->read($cal_id)) && isset($egw_event['participants'][$this->user]) &&
|
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])
|
$egw_event['participants'][$this->user] !== $event['participants'][$this->user])
|
||||||
{
|
{
|
||||||
$this->set_status($egw_event,$this->user,
|
//error_log(__FILE__ . __METHOD__ . "\n:set status" . print_r($egw_event,true));
|
||||||
$status = $event['participants'][$this->user] ? $event['participants'][$this->user] : 'R');
|
$this->set_status($egw_event,$this->user,$status = $event['participants'][$this->user] ? $event['participants'][$this->user] : 'R');
|
||||||
|
|
||||||
$Ok = $cal_id;
|
$Ok = $cal_id;
|
||||||
continue;
|
continue;
|
||||||
@ -997,7 +1080,8 @@ class calendar_ical extends calendar_boupdate
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
$eventID =& $Ok;
|
$eventID =& $Ok;
|
||||||
|
if(isset($egw_event) && $original_event['participants'] != $egw_event['participants'])$this->update_status($original_event,$egw_event);
|
||||||
|
|
||||||
// handle the alarms
|
// handle the alarms
|
||||||
foreach ($component->getComponents() as $valarm)
|
foreach ($component->getComponents() as $valarm)
|
||||||
{
|
{
|
||||||
@ -1089,7 +1173,7 @@ class calendar_ical extends calendar_boupdate
|
|||||||
// break;
|
// break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
error_log('VALARM field:' .$vattr['name'] .':' . print_r($vattrval,true) . ' HAS NO CONVERSION YET');
|
// error_log('VALARM field:' .$vattr['name'] .':' . print_r($vattrval,true) . ' HAS NO CONVERSION YET');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $count;
|
return $count;
|
||||||
@ -1292,6 +1376,17 @@ class calendar_ical extends calendar_boupdate
|
|||||||
$vcardData['description'] = $attributes['value'];
|
$vcardData['description'] = $attributes['value'];
|
||||||
break;
|
break;
|
||||||
case 'DTEND':
|
case 'DTEND':
|
||||||
|
/* write start + end of whole day events as dates
|
||||||
|
DTSTART;VALUE=DATE:20090317 implies 000000Z
|
||||||
|
DTEND;VALUE=DATE:20090317 implies 235959Z
|
||||||
|
And DEFINES an ALLDAY event
|
||||||
|
and as such is "inclusive"
|
||||||
|
some clients(Lightning, Korganiser?) need an "exclusive"
|
||||||
|
Legacy: EGW held 235900 As DTEND allday, such entries in databases will exist
|
||||||
|
EGW is internally correct on 235959 "inclusive"
|
||||||
|
*/
|
||||||
|
//error_log(__FILE__ . __METHOD__. "DTEND:". print_r($attributes['value'],true));
|
||||||
|
|
||||||
if(date('H:i:s',$attributes['value']) == '00:00:00')
|
if(date('H:i:s',$attributes['value']) == '00:00:00')
|
||||||
$attributes['value']--;
|
$attributes['value']--;
|
||||||
$vcardData['end'] = $attributes['value'];
|
$vcardData['end'] = $attributes['value'];
|
||||||
@ -1612,4 +1707,37 @@ class calendar_ical extends calendar_boupdate
|
|||||||
|
|
||||||
return $vcal->exportvCalendar();
|
return $vcal->exportvCalendar();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function update_status($new_event,$old_event)
|
||||||
|
{
|
||||||
|
$modified = $added = $deleted = array();
|
||||||
|
//error_log(__FILE__ . __METHOD__ . "\nnew_event:" . print_r($new_event,true));
|
||||||
|
|
||||||
|
// check the old list against the new list and write the changes
|
||||||
|
foreach($old_event['participants'] as $old_userid => $old_status)
|
||||||
|
{
|
||||||
|
if(isset($new_event['participants'][$old_userid])){
|
||||||
|
if($new_event['participants'][$old_userid] != $old_event['participants'][$old_userid]){
|
||||||
|
//$modified[$old_userid] = $new_event['participants'][$old_userid];
|
||||||
|
$this->set_status($old_event,$old_userid,$status = $new_event['participants'][$old_userid] ? $new_event['participants'][$old_userid] : 'R');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// this doesn't get written from here at the moment
|
||||||
|
$deleted[$old_userid] = $old_status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Find new participants ...
|
||||||
|
foreach($new_event['participants'] as $new_userid => $new_status)
|
||||||
|
{
|
||||||
|
if(!isset($old_event['participants'][$new_userid]))
|
||||||
|
{
|
||||||
|
// this doesn't get written from here at the moment
|
||||||
|
$added[$new_userid] = 'U';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user