2008-06-07 19:45:33 +02:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* eGroupWare calendar - SIF Parser for SyncML
|
|
|
|
*
|
|
|
|
* @link http://www.egroupware.org
|
|
|
|
* @author Lars Kneschke <lkneschke@egroupware.org>
|
2009-11-16 09:04:18 +01:00
|
|
|
* @author Joerg Lehrke <jlehrke@noc.de>
|
2008-06-07 19:45:33 +02:00
|
|
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
|
|
|
* @package calendar
|
|
|
|
* @subpackage export
|
|
|
|
* @version $Id$
|
|
|
|
*/
|
|
|
|
|
2009-11-16 09:04:18 +01:00
|
|
|
require_once EGW_SERVER_ROOT.'/phpgwapi/inc/horde/lib/core.php';
|
2008-06-07 19:45:33 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* SIF Parser for SyncML
|
|
|
|
*/
|
2008-06-07 19:49:16 +02:00
|
|
|
class calendar_sif extends calendar_boupdate
|
2008-06-07 19:45:33 +02:00
|
|
|
{
|
|
|
|
var $sifMapping = array(
|
|
|
|
'Start' => 'start',
|
|
|
|
'End' => 'end',
|
2010-02-23 19:35:43 +01:00
|
|
|
'AllDayEvent' => 'alldayevent',
|
2009-11-16 09:04:18 +01:00
|
|
|
'Attendees' => '',
|
2008-06-07 19:45:33 +02:00
|
|
|
'BillingInformation' => '',
|
|
|
|
'Body' => 'description',
|
2010-02-23 19:35:43 +01:00
|
|
|
'BusyStatus' => '',
|
|
|
|
'Categories' => 'category',
|
2008-06-07 19:45:33 +02:00
|
|
|
'Companies' => '',
|
2010-02-23 19:35:43 +01:00
|
|
|
'Importance' => 'priority',
|
|
|
|
'IsRecurring' => 'isrecurring',
|
2008-06-07 19:45:33 +02:00
|
|
|
'Location' => 'location',
|
2010-02-23 19:35:43 +01:00
|
|
|
'MeetingStatus' => '',
|
2008-06-07 19:45:33 +02:00
|
|
|
'Mileage' => '',
|
|
|
|
'ReminderMinutesBeforeStart' => 'reminderstart',
|
2010-02-23 19:35:43 +01:00
|
|
|
'ReminderSet' => 'reminderset',
|
|
|
|
'ReminderSoundFile' => '',
|
|
|
|
'ReminderOptions' => '',
|
|
|
|
'ReminderInterval' => '',
|
2009-11-16 09:04:18 +01:00
|
|
|
'ReminderRepeatCount' => '',
|
2010-02-23 19:35:43 +01:00
|
|
|
'Exceptions' => '',
|
2008-06-07 19:45:33 +02:00
|
|
|
'ReplyTime' => '',
|
2010-02-23 19:35:43 +01:00
|
|
|
'Sensitivity' => 'public',
|
2008-06-07 19:45:33 +02:00
|
|
|
'Subject' => 'title',
|
2010-02-23 19:35:43 +01:00
|
|
|
'RecurrenceType' => 'recur_type',
|
2008-06-07 19:45:33 +02:00
|
|
|
'Interval' => 'recur_interval',
|
2010-02-23 19:35:43 +01:00
|
|
|
'MonthOfYear' => '',
|
|
|
|
'DayOfMonth' => '',
|
|
|
|
'DayOfWeekMask' => 'recur_weekmask',
|
2008-06-07 19:45:33 +02:00
|
|
|
'Instance' => '',
|
2010-02-23 19:35:43 +01:00
|
|
|
'PatternStartDate' => '',
|
2008-06-07 19:45:33 +02:00
|
|
|
'NoEndDate' => 'recur_noenddate',
|
2010-02-23 19:35:43 +01:00
|
|
|
'PatternEndDate' => 'recur_enddate',
|
|
|
|
'Occurrences' => '',
|
2008-06-07 19:45:33 +02:00
|
|
|
);
|
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
/**
|
|
|
|
* the calendar event array for the XML Parser
|
|
|
|
*/
|
2008-06-07 19:45:33 +02:00
|
|
|
var $event;
|
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
/**
|
|
|
|
* name and sorftware version of the Funambol client
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
*/
|
2009-11-16 09:04:18 +01:00
|
|
|
var $productName = 'mozilla plugin';
|
|
|
|
var $productSoftwareVersion = '0.3';
|
2010-02-23 19:35:43 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* user preference: import all-day events as non blocking
|
|
|
|
*
|
|
|
|
* @var boolean
|
|
|
|
*/
|
|
|
|
var $nonBlockingAllday = false;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* user preference: attach UID entries to the DESCRIPTION
|
|
|
|
*
|
|
|
|
* @var boolean
|
|
|
|
*/
|
2009-11-16 09:04:18 +01:00
|
|
|
var $uidExtension = false;
|
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
/**
|
|
|
|
* user preference: calendar to synchronize with
|
|
|
|
*
|
|
|
|
* @var int
|
|
|
|
*/
|
|
|
|
var $calendarOwner = 0;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* user preference: use server timezone for exports to device
|
|
|
|
*
|
|
|
|
* @var boolean
|
|
|
|
*/
|
|
|
|
var $useServerTZ = false;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Device CTCap Properties
|
|
|
|
*
|
|
|
|
* @var array
|
|
|
|
*/
|
|
|
|
var $clientProperties;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* vCalendar Instance for parsing
|
|
|
|
*
|
|
|
|
* @var array
|
|
|
|
*/
|
|
|
|
var $vCalendar;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set Logging
|
|
|
|
*
|
|
|
|
* @var boolean
|
|
|
|
*/
|
|
|
|
var $log = false;
|
|
|
|
var $logfile="/tmp/log-sifcal";
|
|
|
|
|
|
|
|
|
2008-06-07 19:45:33 +02:00
|
|
|
// constants for recurence type
|
2010-02-23 19:35:43 +01:00
|
|
|
const olRecursDaily = 0;
|
2008-06-07 19:45:33 +02:00
|
|
|
const olRecursWeekly = 1;
|
|
|
|
const olRecursMonthly = 2;
|
|
|
|
const olRecursMonthNth = 3;
|
|
|
|
const olRecursYearly = 5;
|
|
|
|
const olRecursYearNth = 6;
|
|
|
|
|
|
|
|
// constants for weekdays
|
2010-02-23 19:35:43 +01:00
|
|
|
const olSunday = 1;
|
|
|
|
const olMonday = 2;
|
|
|
|
const olTuesday = 4;
|
|
|
|
const olWednesday = 8;
|
|
|
|
const olThursday = 16;
|
|
|
|
const olFriday = 32;
|
|
|
|
const olSaturday = 64;
|
2008-06-07 19:45:33 +02:00
|
|
|
|
2009-11-16 09:04:18 +01:00
|
|
|
// standard headers
|
|
|
|
const xml_decl = '<?xml version="1.0" encoding="UTF-8"?>';
|
|
|
|
const SIF_decl = '<SIFVersion>1.1</SIFVersion>';
|
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*
|
|
|
|
* @param array $_clientProperties client properties
|
|
|
|
*/
|
|
|
|
function __construct(&$_clientProperties = array())
|
|
|
|
{
|
|
|
|
parent::__construct();
|
|
|
|
if ($this->log) $this->logfile = $GLOBALS['egw_info']['server']['temp_dir']."/log-sifcal";
|
|
|
|
$this->clientProperties = $_clientProperties;
|
|
|
|
$this->vCalendar = new Horde_iCalendar;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-11-16 09:04:18 +01:00
|
|
|
function startElement($_parser, $_tag, $_attributes)
|
|
|
|
{
|
2008-06-07 19:45:33 +02:00
|
|
|
}
|
|
|
|
|
2009-11-16 09:04:18 +01:00
|
|
|
function endElement($_parser, $_tag)
|
|
|
|
{
|
2010-02-23 19:35:43 +01:00
|
|
|
switch (strtolower($_tag))
|
2009-11-16 09:04:18 +01:00
|
|
|
{
|
2010-02-23 19:35:43 +01:00
|
|
|
case 'excludedate':
|
|
|
|
$this->event['recur_exception'][] = trim($this->sifData);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
if(!empty($this->sifMapping[$_tag]))
|
|
|
|
{
|
|
|
|
$this->event[$this->sifMapping[$_tag]] = trim($this->sifData);
|
|
|
|
}
|
2008-06-07 19:45:33 +02:00
|
|
|
}
|
|
|
|
unset($this->sifData);
|
|
|
|
}
|
|
|
|
|
2009-11-16 09:04:18 +01:00
|
|
|
function characterData($_parser, $_data)
|
|
|
|
{
|
2008-06-07 19:45:33 +02:00
|
|
|
$this->sifData .= $_data;
|
|
|
|
}
|
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
/**
|
|
|
|
* Get DateTime value for a given time and timezone
|
|
|
|
*
|
|
|
|
* @param int|string|DateTime $time in server-time as returned by calendar_bo for $data_format='server'
|
|
|
|
* @param boolean $utc=true if true, return timespamps in UTC, else in server time
|
|
|
|
* @return mixed attribute value to set: integer timestamp if $tzid == 'UTC' otherwise Ymd\THis string IN $tzid
|
|
|
|
*/
|
|
|
|
function getDateTime($time, $utc=true)
|
|
|
|
{
|
|
|
|
if ($utc)
|
|
|
|
{
|
|
|
|
return $this->vCalendar->_exportDateTime($time);
|
|
|
|
}
|
|
|
|
return date('Ymd\THis', $time);
|
|
|
|
}
|
|
|
|
|
2009-11-20 15:45:26 +01:00
|
|
|
function siftoegw($sifData, $_calID=-1)
|
2009-11-16 09:04:18 +01:00
|
|
|
{
|
2008-06-07 19:45:33 +02:00
|
|
|
$finalEvent = array();
|
2010-02-23 19:35:43 +01:00
|
|
|
$this->event = array();
|
2008-06-07 19:45:33 +02:00
|
|
|
$sysCharSet = $GLOBALS['egw']->translation->charset();
|
|
|
|
|
|
|
|
$this->xml_parser = xml_parser_create('UTF-8');
|
|
|
|
xml_set_object($this->xml_parser, $this);
|
|
|
|
xml_parser_set_option($this->xml_parser, XML_OPTION_CASE_FOLDING, false);
|
|
|
|
xml_set_element_handler($this->xml_parser, "startElement", "endElement");
|
|
|
|
xml_set_character_data_handler($this->xml_parser, "characterData");
|
|
|
|
$this->strXmlData = xml_parse($this->xml_parser, $sifData);
|
2009-11-16 09:04:18 +01:00
|
|
|
if (!$this->strXmlData)
|
|
|
|
{
|
2008-06-07 19:45:33 +02:00
|
|
|
error_log(sprintf("XML error: %s at line %d",
|
|
|
|
xml_error_string(xml_get_error_code($this->xml_parser)),
|
|
|
|
xml_get_current_line_number($this->xml_parser)));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-11-16 09:04:18 +01:00
|
|
|
foreach ($this->event as $key => $value)
|
|
|
|
{
|
|
|
|
$value = preg_replace('/<\!\[CDATA\[(.+)\]\]>/Usim', '$1', $value);
|
2008-06-07 19:45:33 +02:00
|
|
|
$value = $GLOBALS['egw']->translation->convert($value, 'utf-8', $sysCharSet);
|
2010-02-23 19:35:43 +01:00
|
|
|
/*
|
|
|
|
if ($this->log)
|
|
|
|
{
|
|
|
|
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__.
|
|
|
|
"() $key => $value\n",3,$this->logfile);
|
|
|
|
}
|
|
|
|
*/
|
2009-11-16 09:04:18 +01:00
|
|
|
switch ($key)
|
|
|
|
{
|
2008-06-07 19:45:33 +02:00
|
|
|
case 'alldayevent':
|
2009-11-16 09:04:18 +01:00
|
|
|
if ($value == 1)
|
|
|
|
{
|
|
|
|
$finalEvent['whole_day'] = true;
|
2008-06-07 19:45:33 +02:00
|
|
|
$startParts = explode('-',$this->event['start']);
|
2010-02-23 19:35:43 +01:00
|
|
|
$finalEvent['startdate']['hour'] = $finalEvent['startdate']['minute'] = $finalEvent['startdate']['second'] = 0;
|
|
|
|
$finalEvent['startdate']['year'] = $startParts[0];
|
|
|
|
$finalEvent['startdate']['month'] = $startParts[1];
|
|
|
|
$finalEvent['startdate']['day'] = $startParts[2];
|
|
|
|
$finalEvent['start'] = $this->date2ts($finalEvent['startdate']);
|
2008-06-07 19:45:33 +02:00
|
|
|
$endParts = explode('-',$this->event['end']);
|
2010-02-23 19:35:43 +01:00
|
|
|
$finalEvent['enddate']['hour'] = 23; $finalEvent['enddate']['minute'] = $finalEvent['enddate']['second'] = 59;
|
|
|
|
$finalEvent['enddate']['year'] = $endParts[0];
|
|
|
|
$finalEvent['enddate']['month'] = $endParts[1];
|
|
|
|
$finalEvent['enddate']['day'] = $endParts[2];
|
|
|
|
$finalEvent['end'] = $this->date2ts($finalEvent['enddate']);
|
2008-06-07 19:45:33 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'public':
|
|
|
|
$finalEvent[$key] = ((int)$value > 0) ? 0 : 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'category':
|
2009-11-16 09:04:18 +01:00
|
|
|
if (!empty($value))
|
|
|
|
{
|
2009-11-20 15:45:26 +01:00
|
|
|
$categories1 = explode(',', $value);
|
|
|
|
$categories2 = explode(';', $value);
|
|
|
|
$categories = count($categories1) > count($categories2) ? $categories1 : $categories2;
|
2010-02-23 19:35:43 +01:00
|
|
|
$finalEvent[$key] = $this->find_or_add_categories($categories, $_calID);
|
2008-06-07 19:45:33 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'end':
|
|
|
|
case 'start':
|
2009-11-16 09:04:18 +01:00
|
|
|
if ($this->event['alldayevent'] < 1)
|
|
|
|
{
|
2010-02-23 19:35:43 +01:00
|
|
|
$finalEvent[$key] = $this->vCalendar->_parseDateTime($value);
|
2008-06-07 19:45:33 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'isrecurring':
|
2009-11-16 09:04:18 +01:00
|
|
|
if ($value == 1)
|
|
|
|
{
|
2010-02-23 19:35:43 +01:00
|
|
|
$finalEvent['recur_exception'] = array();
|
|
|
|
if (is_array($this->event['recur_exception']))
|
|
|
|
{
|
|
|
|
foreach ($this->event['recur_exception'] as $day)
|
|
|
|
{
|
|
|
|
$finalEvent['recur_exception'][] = $this->vCalendar->_parseDateTime($day);
|
|
|
|
}
|
|
|
|
array_unique($finalEvent['recur_exception']);
|
|
|
|
}
|
2008-06-07 19:45:33 +02:00
|
|
|
$finalEvent['recur_interval'] = $this->event['recur_interval'];
|
2010-02-23 19:35:43 +01:00
|
|
|
$finalEvent['recur_data'] = 0;
|
2009-11-16 09:04:18 +01:00
|
|
|
if ($this->event['recur_noenddate'] == 0)
|
|
|
|
{
|
2010-02-23 19:35:43 +01:00
|
|
|
$recur_enddate = $this->vCalendar->_parseDateTime($this->event['recur_enddate']);
|
|
|
|
$finalEvent['recur_enddate'] = mktime(0, 0, 0,
|
|
|
|
date('m', $recur_enddate),
|
|
|
|
date('d', $recur_enddate),
|
|
|
|
date('Y', $recur_enddate));
|
2008-06-07 19:45:33 +02:00
|
|
|
}
|
2009-11-16 09:04:18 +01:00
|
|
|
switch ($this->event['recur_type'])
|
|
|
|
{
|
2008-06-07 19:45:33 +02:00
|
|
|
case self::olRecursDaily:
|
|
|
|
$finalEvent['recur_type'] = MCAL_RECUR_DAILY;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case self::olRecursWeekly:
|
|
|
|
$finalEvent['recur_type'] = MCAL_RECUR_WEEKLY;
|
|
|
|
$finalEvent['recur_data'] = $this->event['recur_weekmask'];
|
|
|
|
break;
|
|
|
|
|
|
|
|
case self::olRecursMonthly:
|
|
|
|
$finalEvent['recur_type'] = MCAL_RECUR_MONTHLY_MDAY;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case self::olRecursMonthNth:
|
|
|
|
$finalEvent['recur_type'] = MCAL_RECUR_MONTHLY_WDAY;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case self::olRecursYearly:
|
|
|
|
$finalEvent['recur_type'] = MCAL_RECUR_YEARLY;
|
|
|
|
$finalEvent['recur_interval'] = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'priority':
|
2009-11-16 09:04:18 +01:00
|
|
|
$finalEvent[$key] = $value + 1;
|
2008-06-07 19:45:33 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'reminderset':
|
2009-11-16 09:04:18 +01:00
|
|
|
if ($value == 1)
|
|
|
|
{
|
2008-06-07 19:45:33 +02:00
|
|
|
$finalEvent['alarm'] = $this->event['reminderstart'];
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'recur_type':
|
|
|
|
case 'recur_enddate':
|
|
|
|
case 'recur_interval':
|
|
|
|
case 'recur_weekmask':
|
|
|
|
case 'reminderstart':
|
2010-02-23 19:35:43 +01:00
|
|
|
case 'recur_exception':
|
2008-06-07 19:45:33 +02:00
|
|
|
// do nothing, get's handled in isrecuring clause
|
|
|
|
break;
|
|
|
|
|
2009-11-16 09:04:18 +01:00
|
|
|
case 'description':
|
|
|
|
if (preg_match('/\s*\[UID:(.+)?\]/Usm', $value, $matches))
|
|
|
|
{
|
|
|
|
$finalEvent['uid'] = $matches[1];
|
|
|
|
}
|
|
|
|
|
2008-06-07 19:45:33 +02:00
|
|
|
default:
|
2010-02-23 19:35:43 +01:00
|
|
|
$finalEvent[$key] = str_replace("\r\n", "\n", $value);
|
2008-06-07 19:45:33 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
if ($this->calendarOwner) $finalEvent['owner'] = $this->calendarOwner;
|
2008-06-07 19:45:33 +02:00
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
if ($_calID > 0) $finalEvent['id'] = $_calID;
|
|
|
|
|
|
|
|
if ($this->log)
|
|
|
|
{
|
|
|
|
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__."()\n" .
|
|
|
|
array2string($finalEvent)."\n",3,$this->logfile);
|
|
|
|
}
|
2008-06-07 19:45:33 +02:00
|
|
|
|
|
|
|
return $finalEvent;
|
|
|
|
}
|
|
|
|
|
2009-11-16 09:04:18 +01:00
|
|
|
function search($_sifdata, $contentID=null, $relax=false)
|
|
|
|
{
|
2010-02-23 19:35:43 +01:00
|
|
|
$result = array();
|
|
|
|
$filter = $relax ? 'relax' : 'exact';
|
2008-06-07 19:45:33 +02:00
|
|
|
|
2009-11-20 15:45:26 +01:00
|
|
|
if ($event = $this->siftoegw($_sifdata, $contentID))
|
2009-11-16 09:04:18 +01:00
|
|
|
{
|
|
|
|
if ($contentID) {
|
|
|
|
$event['id'] = $contentID;
|
2008-06-07 19:45:33 +02:00
|
|
|
}
|
2010-02-23 19:35:43 +01:00
|
|
|
$result = $this->find_event($event, $filter);
|
2008-06-07 19:45:33 +02:00
|
|
|
}
|
2009-11-16 09:04:18 +01:00
|
|
|
return $result;
|
2008-06-07 19:45:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2009-11-20 15:45:26 +01:00
|
|
|
* @return int event id
|
|
|
|
* @param string $_sifdata the SIFE data
|
|
|
|
* @param int $_calID=-1 the internal addressbook id
|
2009-11-16 09:04:18 +01:00
|
|
|
* @param boolean $merge=false merge data with existing entry
|
2010-02-23 19:35:43 +01:00
|
|
|
* @param int $recur_date=0 if set, import the recurrence at this timestamp,
|
|
|
|
* default 0 => import whole series (or events, if not recurring)
|
2009-11-20 15:45:26 +01:00
|
|
|
* @desc import a SIFE into the calendar
|
2008-06-07 19:45:33 +02:00
|
|
|
*/
|
2010-02-23 19:35:43 +01:00
|
|
|
function addSIF($_sifdata, $_calID=-1, $merge=false, $recur_date=0)
|
2008-06-07 19:45:33 +02:00
|
|
|
{
|
2010-02-23 19:35:43 +01:00
|
|
|
if ($this->log)
|
|
|
|
{
|
|
|
|
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__."()\n" .
|
|
|
|
array2string($_sifdata)."\n",3,$this->logfile);
|
|
|
|
}
|
2009-11-20 15:45:26 +01:00
|
|
|
if (!$event = $this->siftoegw($_sifdata, $_calID))
|
2009-11-16 09:04:18 +01:00
|
|
|
{
|
2008-06-07 19:45:33 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
if ($recur_date) $event['reference'] = $recur_date;
|
|
|
|
$event_info = $this->get_event_info($event);
|
|
|
|
|
|
|
|
// common adjustments for existing events
|
|
|
|
if (is_array($event_info['stored_event']))
|
2008-06-07 19:45:33 +02:00
|
|
|
{
|
2010-02-23 19:35:43 +01:00
|
|
|
if (empty($event['uid']))
|
|
|
|
{
|
|
|
|
$event['uid'] = $event_info['stored_event']['uid']; // restore the UID if it was not delivered
|
|
|
|
}
|
|
|
|
if ($merge)
|
|
|
|
{
|
|
|
|
// overwrite with server data for merge
|
|
|
|
foreach ($event_info['stored_event'] as $key => $value)
|
|
|
|
{
|
2010-02-24 15:53:15 +01:00
|
|
|
if ($key == 'participants')
|
2010-02-23 19:35:43 +01:00
|
|
|
{
|
|
|
|
unset($event[$key]);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!empty($value)) $event[$key] = $value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// not merge
|
|
|
|
// SIF clients do not support participants => add them back
|
|
|
|
unset($event['participants']);
|
|
|
|
|
|
|
|
// avoid that iCal changes the organizer, which is not allowed
|
|
|
|
$event['owner'] = $event_info['stored_event']['owner'];
|
|
|
|
}
|
2008-06-07 19:45:33 +02:00
|
|
|
}
|
2010-02-23 19:35:43 +01:00
|
|
|
else // common adjustments for new events
|
2009-11-16 09:04:18 +01:00
|
|
|
{
|
2010-02-23 19:35:43 +01:00
|
|
|
// set non blocking all day depending on the user setting
|
|
|
|
if (isset($event['whole_day'])
|
|
|
|
&& $event['whole_day']
|
|
|
|
&& $this->nonBlockingAllday)
|
2009-11-16 09:04:18 +01:00
|
|
|
{
|
2010-02-23 19:35:43 +01:00
|
|
|
$event['non_blocking'] = 1;
|
2009-11-16 09:04:18 +01:00
|
|
|
}
|
2010-02-23 19:35:43 +01:00
|
|
|
|
|
|
|
// check if an owner is set and the current user has add rights
|
|
|
|
// for that owners calendar; if not set the current user
|
|
|
|
if (!isset($event['owner'])
|
|
|
|
|| !$this->check_perms(EGW_ACL_ADD, 0, $event['owner']))
|
|
|
|
{
|
|
|
|
$event['owner'] = $this->user;
|
|
|
|
}
|
|
|
|
|
|
|
|
$status = $event['owner'] == $this->user ? 'A' : 'U';
|
|
|
|
$status = calendar_so::combine_status($status, 1, 'CHAIR');
|
|
|
|
$event['participants'] = array($event['owner'] => $status);
|
2009-11-16 09:04:18 +01:00
|
|
|
}
|
2008-06-07 19:45:33 +02:00
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
unset($event['startdate']);
|
|
|
|
unset($event['enddate']);
|
|
|
|
|
|
|
|
$alarmData = array();
|
|
|
|
if (isset($event['alarm']))
|
2009-11-16 09:04:18 +01:00
|
|
|
{
|
2010-02-23 19:35:43 +01:00
|
|
|
$alarmData['offset'] = $event['alarm'] * 60;
|
|
|
|
$alarmData['time'] = $event['start'] - $alarmData['offset'];
|
|
|
|
$alarmData['owner'] = $this->user;
|
|
|
|
$alarmData['all'] = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// update alarms depending on the given event type
|
|
|
|
if (!empty($alarmData) || isset($this->supportedFields['alarm']))
|
|
|
|
{
|
|
|
|
switch ($event_info['type'])
|
2008-06-07 19:45:33 +02:00
|
|
|
{
|
2010-02-23 19:35:43 +01:00
|
|
|
case 'SINGLE':
|
|
|
|
case 'SERIES-MASTER':
|
|
|
|
case 'SERIES-EXCEPTION':
|
|
|
|
case 'SERIES-EXCEPTION-PROPAGATE':
|
|
|
|
if (isset($event['alarm']))
|
|
|
|
{
|
|
|
|
if (is_array($event_info['stored_event'])
|
|
|
|
&& count($event_info['stored_event']['alarm']) > 0)
|
|
|
|
{
|
|
|
|
foreach ($event_info['stored_event']['alarm'] as $alarm_id => $alarm_data)
|
|
|
|
{
|
|
|
|
if ($alarmData['time'] == $alarm_data['time'] &&
|
|
|
|
($alarm_data['all'] || $alarm_data['owner'] == $this->user))
|
|
|
|
{
|
|
|
|
unset($alarmData);
|
|
|
|
unset($event_info['stored_event']['alarm'][$alarm_id]);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (isset($alarmData)) $event['alarm'][] = $alarmData;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2008-06-07 19:45:33 +02:00
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
case 'SERIES-PSEUDO-EXCEPTION':
|
|
|
|
// nothing to do here
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (is_array($event_info['stored_event'])
|
|
|
|
&& count($event_info['stored_event']['alarm']) > 0)
|
2009-11-16 09:04:18 +01:00
|
|
|
{
|
2010-02-23 19:35:43 +01:00
|
|
|
foreach ($event_info['stored_event']['alarm'] as $alarm_id => $alarm_data)
|
|
|
|
{
|
|
|
|
// only touch own alarms
|
|
|
|
if ($alarm_data['all'] == false && $alarm_data['owner'] == $this->user)
|
|
|
|
{
|
|
|
|
$this->delete_alarm($alarm_id);
|
|
|
|
}
|
|
|
|
}
|
2008-06-07 19:45:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
// save event depending on the given event type
|
|
|
|
switch ($event_info['type'])
|
|
|
|
{
|
|
|
|
case 'SINGLE':
|
|
|
|
if ($this->log)
|
|
|
|
{
|
|
|
|
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__.
|
|
|
|
"(): event SINGLE\n",3,$this->logfile);
|
|
|
|
}
|
|
|
|
|
|
|
|
// update the event
|
|
|
|
if ($event_info['acl_edit'])
|
|
|
|
{
|
|
|
|
// Force SINGLE
|
|
|
|
$event['reference'] = 0;
|
|
|
|
$event_to_store = array($event); // prevent $event from being changed by the update method
|
|
|
|
$this->db2data($event_to_store);
|
|
|
|
$event_to_store = array_shift($event_to_store);
|
|
|
|
$updated_id = $this->update($event_to_store, true);
|
|
|
|
unset($event_to_store);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'SERIES-MASTER':
|
|
|
|
if ($this->log)
|
|
|
|
{
|
|
|
|
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__.
|
|
|
|
"(): event SERIES-MASTER\n",3,$this->logfile);
|
|
|
|
}
|
|
|
|
|
|
|
|
// update the event
|
|
|
|
if ($event_info['acl_edit'])
|
|
|
|
{
|
|
|
|
$event_to_store = array($event); // prevent $event from being changed by the update method
|
|
|
|
$this->db2data($event_to_store);
|
|
|
|
$event_to_store = array_shift($event_to_store);
|
|
|
|
$updated_id = $this->update($event_to_store, true);
|
|
|
|
unset($event_to_store);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'SERIES-EXCEPTION':
|
|
|
|
case 'SERIES-EXCEPTION-PROPAGATE':
|
|
|
|
if ($this->log)
|
|
|
|
{
|
|
|
|
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__.
|
|
|
|
"(): event SERIES-EXCEPTION\n",3,$this->logfile);
|
|
|
|
}
|
|
|
|
|
|
|
|
// update event
|
|
|
|
if ($event_info['acl_edit'])
|
|
|
|
{
|
|
|
|
if (isset($event_info['stored_event']['id']))
|
|
|
|
{
|
|
|
|
// We update an existing exception
|
|
|
|
$event['id'] = $event_info['stored_event']['id'];
|
|
|
|
$event['category'] = $event_info['stored_event']['category'];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// We create a new exception
|
|
|
|
unset($event['id']);
|
|
|
|
unset($event_info['stored_event']);
|
|
|
|
$event['recur_type'] = MCAL_RECUR_NONE;
|
|
|
|
$event_info['master_event']['recur_exception'] =
|
|
|
|
array_unique(array_merge($event_info['master_event']['recur_exception'],
|
|
|
|
array($event['reference'])));
|
|
|
|
$event['category'] = $event_info['master_event']['category'];
|
|
|
|
$event['owner'] = $event_info['master_event']['owner'];
|
|
|
|
$event_to_store = array($event_info['master_event']); // prevent the master_event from being changed by the update method
|
|
|
|
$this->db2data($event_to_store);
|
|
|
|
$event_to_store = array_shift($event_to_store);
|
|
|
|
$this->update($event_to_store, true);
|
|
|
|
unset($event_to_store);
|
|
|
|
}
|
|
|
|
|
|
|
|
$event_to_store = array($event); // prevent $event from being changed by update method
|
|
|
|
$this->db2data($event_to_store);
|
|
|
|
$event_to_store = array_shift($event_to_store);
|
|
|
|
$updated_id = $this->update($event_to_store, true);
|
|
|
|
unset($event_to_store);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'SERIES-PSEUDO-EXCEPTION':
|
|
|
|
if ($this->log)
|
|
|
|
{
|
|
|
|
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__.
|
|
|
|
"(): event SERIES-PSEUDO-EXCEPTION\n",3,$this->logfile);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($event_info['acl_edit'])
|
|
|
|
{
|
|
|
|
// truncate the status only exception from the series master
|
|
|
|
$recur_exceptions = array();
|
|
|
|
foreach ($event_info['master_event']['recur_exception'] as $recur_exception)
|
|
|
|
{
|
|
|
|
if ($recur_exception != $event['reference'])
|
|
|
|
{
|
|
|
|
$recur_exceptions[] = $recur_exception;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$event_info['master_event']['recur_exception'] = $recur_exceptions;
|
|
|
|
|
|
|
|
// save the series master with the adjusted exceptions
|
|
|
|
$event_to_store = array($event_info['master_event']); // prevent the master_event from being changed by the update method
|
|
|
|
$this->db2data($event_to_store);
|
|
|
|
$event_to_store = array_shift($event_to_store);
|
|
|
|
$updated_id = $this->update($event_to_store, true, true, false, false);
|
|
|
|
unset($event_to_store);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// read stored event into info array for fresh stored (new) events
|
|
|
|
if (!is_array($event_info['stored_event']) && $updated_id > 0)
|
|
|
|
{
|
|
|
|
$event_info['stored_event'] = $this->read($updated_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
// choose which id to return to the client
|
|
|
|
switch ($event_info['type'])
|
|
|
|
{
|
|
|
|
case 'SINGLE':
|
|
|
|
case 'SERIES-MASTER':
|
|
|
|
case 'SERIES-EXCEPTION':
|
|
|
|
$return_id = $updated_id;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'SERIES-PSEUDO-EXCEPTION':
|
|
|
|
$return_id = is_array($event_info['master_event']) ? $event_info['master_event']['id'] . ':' . $event['reference'] : false;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'SERIES-EXCEPTION-PROPAGATE':
|
|
|
|
if ($event_info['acl_edit'] && is_array($event_info['stored_event']))
|
|
|
|
{
|
|
|
|
// we had sufficient rights to propagate the status only exception to a real one
|
|
|
|
$return_id = $event_info['stored_event']['id'];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// we did not have sufficient rights to propagate the status only exception to a real one
|
|
|
|
// we have to keep the SERIES-PSEUDO-EXCEPTION id and keep the event untouched
|
|
|
|
$return_id = $event_info['master_event']['id'] . ':' . $event['reference'];
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($this->log)
|
|
|
|
{
|
|
|
|
$recur_date = $this->date2usertime($event_info['stored_event']['start']);
|
|
|
|
$event_info['stored_event'] = $this->read($event_info['stored_event']['id'], $recur_date);
|
|
|
|
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__."()\n" .
|
|
|
|
array2string($event_info['stored_event'])."\n",3,$this->logfile);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $return_id;
|
2008-06-07 19:45:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2009-11-16 09:04:18 +01:00
|
|
|
* return a sife
|
2008-06-07 19:45:33 +02:00
|
|
|
*
|
2009-11-16 09:04:18 +01:00
|
|
|
* @param int $_id the id of the event
|
2010-02-23 19:35:43 +01:00
|
|
|
* @param int $recur_date=0 if set export the next recurrence at or after the timestamp,
|
|
|
|
* default 0 => export whole series (or events, if not recurring)
|
2009-11-20 15:45:26 +01:00
|
|
|
* @return string containing the SIFE
|
2008-06-07 19:45:33 +02:00
|
|
|
*/
|
2010-02-23 19:35:43 +01:00
|
|
|
function getSIF($_id, $recur_date=0)
|
2008-06-07 19:45:33 +02:00
|
|
|
{
|
2010-02-23 19:35:43 +01:00
|
|
|
if ($this->log)
|
|
|
|
{
|
|
|
|
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__.
|
|
|
|
"($_id, $recur_date)\n",3,$this->logfile);
|
|
|
|
}
|
2009-11-16 09:04:18 +01:00
|
|
|
$sysCharSet = $GLOBALS['egw']->translation->charset();
|
|
|
|
|
2008-06-07 19:45:33 +02:00
|
|
|
$fields = array_unique(array_values($this->sifMapping));
|
|
|
|
sort($fields);
|
2010-02-23 19:35:43 +01:00
|
|
|
$utc = true;
|
2008-06-07 19:45:33 +02:00
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
if (!($event = $this->read($_id, $recur_date, false, 'server')))
|
|
|
|
{
|
|
|
|
if ($this->read($_id, $recur_date, true, 'server'))
|
|
|
|
{
|
|
|
|
$retval = -1; // Permission denied
|
|
|
|
if($this->xmlrpc)
|
|
|
|
{
|
|
|
|
$GLOBALS['server']->xmlrpc_error($GLOBALS['xmlrpcerr']['no_access'],
|
|
|
|
$GLOBALS['xmlrpcstr']['no_access']);
|
|
|
|
}
|
|
|
|
if ($this->log)
|
|
|
|
{
|
|
|
|
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__.
|
|
|
|
"() User does not have the permission to read event $_id.\n",
|
|
|
|
3,$this->logfile);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$retval = false; // Entry does not exist
|
|
|
|
if ($this->log)
|
|
|
|
{
|
|
|
|
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__.
|
|
|
|
"() Event $_id not found.\n",3,$this->logfile);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return $retval;
|
|
|
|
}
|
2008-06-07 19:45:33 +02:00
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
if ($this->log)
|
2009-11-16 09:04:18 +01:00
|
|
|
{
|
2010-02-23 19:35:43 +01:00
|
|
|
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__."()\n" .
|
|
|
|
array2string($event)."\n",3,$this->logfile);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($this->isWholeDay($event)) $event['whole_day'] = true;
|
2009-11-16 09:04:18 +01:00
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
if ($recur_date)
|
|
|
|
{
|
|
|
|
if ($this->log)
|
|
|
|
{
|
|
|
|
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__.
|
|
|
|
"($_id, $recur_date) Unsupported status only exception, skipped ...\n",
|
|
|
|
3, $this->logfile);
|
|
|
|
}
|
|
|
|
return false; // unsupported pseudo exception
|
|
|
|
}
|
|
|
|
|
|
|
|
if (date('e', $event['start']) != 'UTC'
|
|
|
|
&& ($event['recur_type'] != MCAL_RECUR_NONE
|
|
|
|
|| $this->useServerTZ))
|
|
|
|
{
|
|
|
|
if (!$this->useServerTZ &&
|
|
|
|
$event['recur_type'] != MCAL_RECUR_NONE
|
|
|
|
&& $event['recur_enddate'])
|
2009-11-16 09:04:18 +01:00
|
|
|
{
|
2010-02-23 19:35:43 +01:00
|
|
|
$startDST = date('I', $event['start']);
|
|
|
|
$finalDST = date('I', $event['recur_enddate']);
|
|
|
|
// Different DST or more than half a year?
|
|
|
|
if ($startDST != $finalDST ||
|
|
|
|
($event['recur_enddate'] - $event['start']) > 15778800)
|
2009-11-16 09:04:18 +01:00
|
|
|
{
|
2010-02-23 19:35:43 +01:00
|
|
|
$utc = false;
|
2009-11-16 09:04:18 +01:00
|
|
|
}
|
|
|
|
}
|
2010-02-23 19:35:43 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
$utc = false;
|
|
|
|
}
|
|
|
|
}
|
2008-06-07 19:45:33 +02:00
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
if ($this->uidExtension)
|
|
|
|
{
|
|
|
|
if (!preg_match('/\[UID:.+\]/m', $event['description']))
|
|
|
|
{
|
|
|
|
$event['description'] .= "\n[UID:" . $event['uid'] . "]";
|
|
|
|
}
|
|
|
|
}
|
2008-06-07 19:45:33 +02:00
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
$sifEvent = self::xml_decl . "<appointment>" . self::SIF_decl;
|
2008-06-07 19:45:33 +02:00
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
foreach ($this->sifMapping as $sifField => $egwField)
|
|
|
|
{
|
|
|
|
if (empty($egwField)) continue;
|
2009-11-16 09:04:18 +01:00
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
$value = $GLOBALS['egw']->translation->convert($event[$egwField], $sysCharSet, 'utf-8');
|
2008-06-07 19:45:33 +02:00
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
switch ($sifField)
|
|
|
|
{
|
|
|
|
case 'Importance':
|
|
|
|
$value = $value-1;
|
|
|
|
$sifEvent .= "<$sifField>$value</$sifField>";
|
|
|
|
break;
|
2008-06-07 19:45:33 +02:00
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
case 'RecurrenceType':
|
|
|
|
case 'Interval':
|
|
|
|
case 'PatternStartDate':
|
|
|
|
case 'NoEndDate':
|
|
|
|
case 'DayOfWeekMask':
|
|
|
|
case 'PatternEndDate':
|
|
|
|
break;
|
2008-06-07 19:45:33 +02:00
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
case 'IsRecurring':
|
|
|
|
if ($event['recur_type'] == MCAL_RECUR_NONE)
|
|
|
|
{
|
|
|
|
$sifEvent .= "<$sifField>0</$sifField>";
|
2008-06-07 19:45:33 +02:00
|
|
|
break;
|
2010-02-23 19:35:43 +01:00
|
|
|
}
|
|
|
|
if ($event['recur_enddate'] == 0)
|
|
|
|
{
|
|
|
|
$sifEvent .= '<NoEndDate>1</NoEndDate>';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$recurrences = $this->so->get_recurrences($_id);
|
|
|
|
$occurrences = count($recurrences) + count($event['recur_exception']) - 1;
|
|
|
|
end($recurrences);
|
|
|
|
$last = key($recurrences);
|
|
|
|
if ($last < end($event['recur_exception']))
|
2009-11-16 09:04:18 +01:00
|
|
|
{
|
2010-02-23 19:35:43 +01:00
|
|
|
$last = end($event['recur_exception']);
|
2009-11-16 09:04:18 +01:00
|
|
|
}
|
2010-02-23 19:35:43 +01:00
|
|
|
$recurEndDate = $last - $event['start'] + $event['end'];
|
|
|
|
$sifEvent .= '<NoEndDate>0</NoEndDate>';
|
|
|
|
$sifEvent .= '<PatternEndDate>'. self::getDateTime($recurEndDate,$utc) .'</PatternEndDate>';
|
|
|
|
}
|
2008-06-07 19:45:33 +02:00
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
$eventInterval = ($event['recur_interval'] > 1 ? $event['recur_interval'] : 1);
|
2008-06-07 19:45:33 +02:00
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
switch ($event['recur_type'])
|
|
|
|
{
|
2008-06-07 19:45:33 +02:00
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
case MCAL_RECUR_DAILY:
|
|
|
|
$sifEvent .= "<$sifField>1</$sifField>";
|
|
|
|
$sifEvent .= '<RecurrenceType>'. self::olRecursDaily .'</RecurrenceType>';
|
|
|
|
$sifEvent .= '<Interval>'. $eventInterval .'</Interval>';
|
|
|
|
$sifEvent .= '<PatternStartDate>'. self::getDateTime($event['start'],$utc) .'</PatternStartDate>';
|
|
|
|
if ($event['recur_enddate'])
|
|
|
|
{
|
|
|
|
$sifEvent .= '<Occurrences>'. $occurrences .'</Occurrences>';
|
|
|
|
}
|
|
|
|
break;
|
2009-11-16 09:04:18 +01:00
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
case MCAL_RECUR_WEEKLY:
|
|
|
|
$sifEvent .= "<$sifField>1</$sifField>";
|
|
|
|
$sifEvent .= '<RecurrenceType>'. self::olRecursWeekly .'</RecurrenceType>';
|
|
|
|
$sifEvent .= '<Interval>'. $eventInterval .'</Interval>';
|
|
|
|
$sifEvent .= '<PatternStartDate>'. self::getDateTime($event['start'],$utc) .'</PatternStartDate>';
|
|
|
|
$sifEvent .= '<DayOfWeekMask>'. $event['recur_data'] .'</DayOfWeekMask>';
|
|
|
|
if ($event['recur_enddate'])
|
|
|
|
{
|
|
|
|
$sifEvent .= '<Occurrences>'. $occurrences .'</Occurrences>';
|
|
|
|
}
|
|
|
|
break;
|
2009-11-16 09:04:18 +01:00
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
case MCAL_RECUR_MONTHLY_MDAY:
|
|
|
|
$sifEvent .= "<$sifField>1</$sifField>";
|
|
|
|
$sifEvent .= '<RecurrenceType>'. self::olRecursMonthly .'</RecurrenceType>';
|
|
|
|
$sifEvent .= '<Interval>'. $eventInterval .'</Interval>';
|
|
|
|
$sifEvent .= '<PatternStartDate>'. self::getDateTime($event['start'],$utc) .'</PatternStartDate>';
|
|
|
|
break;
|
2009-11-16 09:04:18 +01:00
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
case MCAL_RECUR_MONTHLY_WDAY:
|
|
|
|
$weekMaskMap = array('Sun' => self::olSunday, 'Mon' => self::olMonday, 'Tue' => self::olTuesday,
|
|
|
|
'Wed' => self::olWednesday, 'Thu' => self::olThursday, 'Fri' => self::olFriday,
|
|
|
|
'Sat' => self::olSaturday);
|
|
|
|
$sifEvent .= "<$sifField>1</$sifField>";
|
|
|
|
$sifEvent .= '<RecurrenceType>'. self::olRecursMonthNth .'</RecurrenceType>';
|
|
|
|
$sifEvent .= '<Interval>'. $eventInterval .'</Interval>';
|
|
|
|
$sifEvent .= '<PatternStartDate>'. self::getDateTime($event['start'],$utc) .'</PatternStartDate>';
|
|
|
|
$sifEvent .= '<Instance>' . (1 + (int) ((date('d',$event['start'])-1) / 7)) . '</Instance>';
|
|
|
|
$sifEvent .= '<DayOfWeekMask>' . $weekMaskMap[date('D',$event['start'])] . '</DayOfWeekMask>';
|
|
|
|
break;
|
2009-11-16 09:04:18 +01:00
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
case MCAL_RECUR_YEARLY:
|
|
|
|
$sifEvent .= "<$sifField>1</$sifField>";
|
|
|
|
$sifEvent .= '<RecurrenceType>'. self::olRecursYearly .'</RecurrenceType>';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (is_array($event['recur_exception']))
|
|
|
|
{
|
|
|
|
$sifEvent .= '<Exceptions>';
|
|
|
|
foreach ($event['recur_exception'] as $day)
|
|
|
|
{
|
|
|
|
if (isset($event['whole_day']))
|
|
|
|
{
|
|
|
|
$sifEvent .= '<ExcludeDate>' . date('Y-m-d', $day) . '</ExcludeDate>';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$sifEvent .= '<ExcludeDate>' . self::getDateTime($day,$utc) . '</ExcludeDate>';
|
|
|
|
}
|
2008-06-07 19:45:33 +02:00
|
|
|
}
|
2010-02-23 19:35:43 +01:00
|
|
|
$sifEvent .= '</Exceptions>';
|
|
|
|
}
|
|
|
|
break;
|
2008-06-07 19:45:33 +02:00
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
case 'Sensitivity':
|
|
|
|
$value = (!$value ? '2' : '0');
|
|
|
|
$sifEvent .= "<$sifField>$value</$sifField>";
|
|
|
|
break;
|
2008-06-07 19:45:33 +02:00
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
case 'Folder':
|
|
|
|
# skip currently. This is the folder where Outlook stores the contact.
|
|
|
|
#$sifEvent .= "<$sifField>/</$sifField>";
|
|
|
|
break;
|
2008-06-07 19:45:33 +02:00
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
case 'AllDayEvent':
|
|
|
|
case 'End':
|
|
|
|
// get's handled by Start clause
|
|
|
|
break;
|
2008-06-07 19:45:33 +02:00
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
case 'Start':
|
|
|
|
if (isset($event['whole_day']))
|
|
|
|
{
|
|
|
|
$sifEvent .= '<Start>' . date('Y-m-d', $event['start']) . '</Start>';
|
|
|
|
$sifEvent .= '<End>' . date('Y-m-d', $event['end']) . '</End>';
|
|
|
|
$sifEvent .= "<AllDayEvent>1</AllDayEvent>";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$sifEvent .= '<Start>' . self::getDateTime($event['start'],$utc) . '</Start>';
|
|
|
|
$sifEvent .= '<End>' . self::getDateTime($event['end'],$utc) . '</End>';
|
|
|
|
$sifEvent .= "<AllDayEvent>0</AllDayEvent>";
|
|
|
|
}
|
|
|
|
break;
|
2008-06-07 19:45:33 +02:00
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
case 'ReminderMinutesBeforeStart':
|
|
|
|
break;
|
2008-06-07 19:45:33 +02:00
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
case 'ReminderSet':
|
|
|
|
if (count((array)$event['alarm']) > 0)
|
|
|
|
{
|
|
|
|
$sifEvent .= "<$sifField>1</$sifField>";
|
|
|
|
foreach ($event['alarm'] as $alarmID => $alarmData)
|
2009-11-16 09:04:18 +01:00
|
|
|
{
|
2010-02-23 19:35:43 +01:00
|
|
|
$sifEvent .= '<ReminderMinutesBeforeStart>'. $alarmData['offset']/60 .'</ReminderMinutesBeforeStart>';
|
|
|
|
// lets take only the first alarm
|
2009-11-16 09:04:18 +01:00
|
|
|
break;
|
|
|
|
}
|
2010-02-23 19:35:43 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$sifEvent .= "<$sifField>0</$sifField>";
|
|
|
|
}
|
|
|
|
break;
|
2009-11-16 09:04:18 +01:00
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
case 'Categories':
|
|
|
|
if (!empty($value) && ($values = $this->get_categories($value)))
|
|
|
|
{
|
|
|
|
$value = implode(', ', $values);
|
|
|
|
$value = $GLOBALS['egw']->translation->convert($value, $sysCharSet, 'utf-8');
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-06-07 19:45:33 +02:00
|
|
|
break;
|
2010-02-23 19:35:43 +01:00
|
|
|
}
|
2008-06-07 19:45:33 +02:00
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
default:
|
2010-03-15 18:23:08 +01:00
|
|
|
$value = @htmlspecialchars($value, ENT_NOQUOTES, 'utf-8');
|
2010-02-23 19:35:43 +01:00
|
|
|
$sifEvent .= "<$sifField>$value</$sifField>";
|
|
|
|
}
|
2008-06-07 19:45:33 +02:00
|
|
|
}
|
2010-02-23 19:35:43 +01:00
|
|
|
$sifEvent .= "</appointment>";
|
2008-06-07 19:45:33 +02:00
|
|
|
|
2010-02-23 19:35:43 +01:00
|
|
|
if ($this->log)
|
2008-06-07 19:45:33 +02:00
|
|
|
{
|
2010-02-23 19:35:43 +01:00
|
|
|
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__ .
|
|
|
|
"() '$this->productName','$this->productSoftwareVersion'\n",3,$this->logfile);
|
|
|
|
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__ .
|
|
|
|
"()\n".array2string($sifEvent)."\n",3,$this->logfile);
|
2008-06-07 19:45:33 +02:00
|
|
|
}
|
2010-02-23 19:35:43 +01:00
|
|
|
|
|
|
|
return $sifEvent;
|
2008-06-07 19:45:33 +02:00
|
|
|
}
|
|
|
|
|
2009-11-16 09:04:18 +01:00
|
|
|
/**
|
|
|
|
* Set the supported fields
|
|
|
|
*
|
|
|
|
* Currently we only store name and version, manucfacturer is always Funambol
|
|
|
|
*
|
|
|
|
* @param string $_productName
|
|
|
|
* @param string $_productSoftwareVersion
|
|
|
|
*/
|
|
|
|
function setSupportedFields($_productName='', $_productSoftwareVersion='')
|
|
|
|
{
|
2010-02-23 19:35:43 +01:00
|
|
|
$state =& $_SESSION['SyncML.state'];
|
|
|
|
if (isset($state))
|
|
|
|
{
|
|
|
|
$deviceInfo = $state->getClientDeviceInfo();
|
|
|
|
}
|
2009-11-16 09:04:18 +01:00
|
|
|
|
|
|
|
if (isset($deviceInfo) && is_array($deviceInfo))
|
|
|
|
{
|
|
|
|
if (isset($deviceInfo['uidExtension']) &&
|
2010-02-23 19:35:43 +01:00
|
|
|
$deviceInfo['uidExtension'])
|
|
|
|
{
|
|
|
|
$this->uidExtension = true;
|
|
|
|
}
|
|
|
|
if (isset($deviceInfo['nonBlockingAllday']) &&
|
|
|
|
$deviceInfo['nonBlockingAllday'])
|
|
|
|
{
|
|
|
|
$this->nonBlockingAllday = true;
|
|
|
|
}
|
|
|
|
if (isset($deviceInfo['tzid']) &&
|
|
|
|
$deviceInfo['tzid'])
|
|
|
|
{
|
|
|
|
$this->useServerTZ = ($deviceInfo['tzid'] == 1);
|
|
|
|
}
|
|
|
|
if (isset($GLOBALS['egw_info']['user']['preferences']['syncml']['calendar_owner']))
|
|
|
|
{
|
|
|
|
$owner = $GLOBALS['egw_info']['user']['preferences']['syncml']['calendar_owner'];
|
2010-03-24 12:30:38 +01:00
|
|
|
switch ($owner)
|
2010-02-23 19:35:43 +01:00
|
|
|
{
|
2010-03-24 12:30:38 +01:00
|
|
|
case 'G':
|
|
|
|
case 'P':
|
2010-04-14 18:40:19 +02:00
|
|
|
case 0:
|
2010-04-16 07:15:51 +02:00
|
|
|
case -1:
|
2010-03-24 12:30:38 +01:00
|
|
|
$owner = $this->user;
|
|
|
|
break;
|
2010-04-14 18:40:19 +02:00
|
|
|
default:
|
|
|
|
if ((int)$owner && $this->check_perms(EGW_ACL_EDIT, 0, $owner))
|
|
|
|
{
|
|
|
|
$this->calendarOwner = $owner;
|
|
|
|
}
|
2009-11-16 09:04:18 +01:00
|
|
|
}
|
2010-02-23 19:35:43 +01:00
|
|
|
}
|
2009-11-16 09:04:18 +01:00
|
|
|
}
|
2010-02-23 19:35:43 +01:00
|
|
|
// store product name and software version for futher usage
|
2009-11-16 09:04:18 +01:00
|
|
|
if ($_productName)
|
|
|
|
{
|
|
|
|
$this->productName = strtolower($_productName);
|
|
|
|
if (preg_match('/^[^\d]*(\d+\.?\d*)[\.|\d]*$/', $_productSoftwareVersion, $matches))
|
|
|
|
{
|
|
|
|
$this->productSoftwareVersion = $matches[1];
|
|
|
|
}
|
|
|
|
}
|
2010-02-23 19:35:43 +01:00
|
|
|
if ($this->log)
|
|
|
|
{
|
|
|
|
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__.
|
|
|
|
'(' . $this->productName .
|
|
|
|
', '. $this->productSoftwareVersion . ")\n",3,$this->logfile);
|
|
|
|
}
|
2009-11-16 09:04:18 +01:00
|
|
|
}
|
2008-06-07 19:45:33 +02:00
|
|
|
}
|