using new Horde_Icalendar class from vendor for CalDAV/CardDAV and iCal import/export instead of old code in phpgwapi/inc/horde

This commit is contained in:
Ralf Becker 2015-06-24 13:48:14 +00:00
parent 63cd244e97
commit f0e2877698
6 changed files with 152 additions and 169 deletions

View File

@ -12,9 +12,6 @@
* @version $Id$
*/
require_once EGW_SERVER_ROOT.'/phpgwapi/inc/horde/lib/core.php';
require_once(EGW_SERVER_ROOT.'/phpgwapi/inc/horde/Horde/SyncML/State.php');
/**
* Addressbook - vCard parser
*
@ -75,7 +72,7 @@ class addressbook_vcal extends addressbook_bo
'REV' => array('modified'),
//set for Apple: 'X-ABSHOWAS' => array('fileas_type'), // Horde vCard class uses uppercase prop-names!
);
var $supportedFields;
/**
@ -130,8 +127,8 @@ class addressbook_vcal extends addressbook_bo
* import a vard into addressbook
*
* @param string $_vcard the vcard
* @param int/string $_abID=null the internal addressbook id or !$_abID for a new enty
* @param boolean $merge=false merge data with existing entry
* @param int/string $_abID =null the internal addressbook id or !$_abID for a new enty
* @param boolean $merge =false merge data with existing entry
* @param string $charset The encoding charset for $text. Defaults to
* utf-8 for new format, iso-8859-1 for old format.
* @return int contact id
@ -146,7 +143,7 @@ class addressbook_vcal extends addressbook_bo
{
if ($merge)
{
foreach ($contact as $key => $value)
foreach (array_keys($contact) as $key)
{
if (!empty($old_contact[$key]))
{
@ -197,17 +194,13 @@ class addressbook_vcal extends addressbook_bo
* return a vcard
*
* @param int/string $_id the id of the contact
* @param string $_charset='UTF-8' encoding of the vcard, default UTF-8
* @param boolean $extra_charset_attribute=true GroupDAV/CalDAV dont need the charset attribute and some clients have problems with it
* @param string $_charset ='UTF-8' encoding of the vcard, default UTF-8
* @param boolean $extra_charset_attribute =true GroupDAV/CalDAV dont need the charset attribute and some clients have problems with it
* @return string containing the vcard
*/
function getVCard($_id,$_charset='UTF-8',$extra_charset_attribute=true)
{
require_once(EGW_SERVER_ROOT.'/phpgwapi/inc/horde/Horde/iCalendar/vcard.php');
#Horde::logMessage("vCalAddressbook clientProperties:\n" . print_r($this->clientProperties, true), __FILE__, __LINE__, PEAR_LOG_DEBUG);
$vCard = new Horde_iCalendar_vcard($this->version);
$vCard = new Horde_Icalendar_Vcard($this->version);
$vCard->setAttribute('PRODID','-//EGroupware//NONSGML EGroupware Addressbook '.$GLOBALS['egw_info']['apps']['phpgwapi']['version'].'//'.
strtoupper($GLOBALS['egw_info']['user']['preferences']['common']['lang']));
@ -525,7 +518,7 @@ class addressbook_vcal extends addressbook_bo
if (is_array($_supportedFields)) $this->supportedFields = $_supportedFields;
}
function setDatabaseFields($_databaseFields)
{
if (is_array($_databaseFields)) $this->databaseFields = $_databaseFields;
@ -551,8 +544,6 @@ class addressbook_vcal extends addressbook_bo
array2string($_vcard)."\n",3,$this->logfile);
}
require_once(EGW_SERVER_ROOT.'/phpgwapi/inc/horde/Horde/iCalendar.php');
if(!($_vcard instanceof Horde_iCalendar))
{
$container = false;
@ -1053,14 +1044,12 @@ class addressbook_vcal extends addressbook_bo
* return a groupVCard
*
* @param array $list values for 'list_uid', 'list_name', 'list_modified', 'members'
* @param string $version='3.0' vcard version
* @param string $version ='3.0' vcard version
* @return string containing the vcard
*/
function getGroupVCard(array $list,$version='3.0')
{
require_once(EGW_SERVER_ROOT.'/phpgwapi/inc/horde/Horde/iCalendar/vcard.php');
$vCard = new Horde_iCalendar_vcard($version);
$vCard = new Horde_Icalendar_Vcard($version);
$vCard->setAttribute('PRODID','-//EGroupware//NONSGML EGroupware Addressbook '.$GLOBALS['egw_info']['apps']['phpgwapi']['version'].'//'.
strtoupper($GLOBALS['egw_info']['user']['preferences']['common']['lang']));

View File

@ -11,8 +11,6 @@
* @version $Id$
*/
require_once EGW_SERVER_ROOT.'/phpgwapi/inc/horde/lib/core.php';
/**
* EGroupware: CalDAV / GroupDAV access: calendar handler
*
@ -35,7 +33,7 @@ class calendar_groupdav extends groupdav_handler
/**
* vCalendar Instance for parsing
*
* @var Horde_iCalendar
* @var Horde_Icalendar
*/
var $vCalendar;
@ -95,7 +93,7 @@ class calendar_groupdav extends groupdav_handler
parent::__construct($app, $groupdav);
$this->bo = new calendar_boupdate();
$this->vCalendar = new Horde_iCalendar;
$this->vCalendar = new Horde_Icalendar;
// since 1.9.003 we allow clients to specify the URL when creating a new event, as specified by CalDAV
if (version_compare($GLOBALS['egw_info']['apps']['calendar']['version'], '1.9.003', '>='))
@ -1084,8 +1082,7 @@ class calendar_groupdav extends groupdav_handler
*/
protected function outbox_freebusy_request($ical, $charset, $user, array &$options)
{
include_once EGW_SERVER_ROOT.'/phpgwapi/inc/horde/lib/core.php';
$vcal = new Horde_iCalendar();
$vcal = new Horde_Icalendar();
if (!$vcal->parsevCalendar($ical, 'VCALENDAR', $charset))
{
return '400 Bad request';
@ -1098,7 +1095,7 @@ class calendar_groupdav extends groupdav_handler
$handler->setSupportedFields('groupdav');
$handler->calendarOwner = $handler->user = 0; // to NOT default owner/organizer to something
if (!($component = $vcal->getComponent(0)) ||
!($event = $handler->vevent2egw($component, $version, $handler->supportedFields, $this->groupdav->current_user_principal, 'Horde_iCalendar_vfreebusy')))
!($event = $handler->vevent2egw($component, $version, $handler->supportedFields, $this->groupdav->current_user_principal, 'Horde_Icalendar_Vfreebusy')))
{
return '400 Bad request';
}

View File

@ -12,8 +12,6 @@
* @version $Id$
*/
require_once EGW_SERVER_ROOT.'/phpgwapi/inc/horde/lib/core.php';
/**
* iCal import and export via Horde iCalendar classes
*
@ -178,7 +176,7 @@ class calendar_ical extends calendar_boupdate
parent::__construct();
if ($this->log) $this->logfile = $GLOBALS['egw_info']['server']['temp_dir']."/log-vcal";
$this->clientProperties = $_clientProperties;
$this->vCalendar = new Horde_iCalendar;
$this->vCalendar = new Horde_Icalendar;
$this->addressbook = new addressbook_bo;
}
@ -187,12 +185,12 @@ class calendar_ical extends calendar_boupdate
* Exports one calendar event to an iCalendar item
*
* @param int|array $events (array of) cal_id or array of the events with timestamps in server time
* @param string $version='1.0' could be '2.0' too
* @param string $method='PUBLISH'
* @param int $recur_date=0 if set export the next recurrence at or after the timestamp,
* @param string $version ='1.0' could be '2.0' too
* @param string $method ='PUBLISH'
* @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)
* @param string $principalURL='' Used for CalDAV exports
* @param string $charset='UTF-8' encoding of the vcalendar, default UTF-8
* @param string $principalURL ='' Used for CalDAV exports
* @param string $charset ='UTF-8' encoding of the vcalendar, default UTF-8
* @return string|boolean string with iCal or false on error (e.g. no permission to read the event)
*/
function &exportVCal($events, $version='1.0', $method='PUBLISH', $recur_date=0, $principalURL='', $charset='UTF-8')
@ -231,7 +229,7 @@ class calendar_ical extends calendar_boupdate
$version = '2.0';
}
$vcal = new Horde_iCalendar;
$vcal = new Horde_Icalendar;
$vcal->setAttribute('PRODID','-//EGroupware//NONSGML EGroupware Calendar '.$GLOBALS['egw_info']['apps']['calendar']['version'].'//'.
strtoupper($GLOBALS['egw_info']['user']['preferences']['common']['lang']));
$vcal->setAttribute('VERSION', $version);
@ -330,7 +328,7 @@ class calendar_ical extends calendar_boupdate
if ($this->log)
{
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__.
"($_id, $recurrence) Gratuitous pseudo exception, skipped ...\n",
"(, $recurrence) Gratuitous pseudo exception, skipped ...\n",
3,$this->logfile);
}
continue; // unsupported status only exception
@ -377,7 +375,7 @@ class calendar_ical extends calendar_boupdate
}
}
$vevent = Horde_iCalendar::newComponent('VEVENT', $vcal);
$vevent = Horde_Icalendar::newComponent('VEVENT', $vcal);
$parameters = $attributes = $values = array();
if ($this->productManufacturer == 'sonyericsson')
@ -429,6 +427,7 @@ class calendar_ical extends calendar_boupdate
case 'ATTENDEE':
foreach ((array)$event['participants'] as $uid => $status)
{
$quantity = $role = null;
calendar_so::split_status($status, $quantity, $role);
// do not include event owner/ORGANIZER as participant in his own calendar, if he is only participant
if (count($event['participants']) == 1 && $event['owner'] == $uid) continue;
@ -442,10 +441,9 @@ class calendar_ical extends calendar_boupdate
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__ .
'()attendee:' . array2string($info) ."\n",3,$this->logfile);
}
$participantCN = trim(empty($info['cn']) ? $info['name'] : $info['cn']);
$participantCN = str_replace(array('\\', ',', ';', ':'),
array('\\\\', '\\,', '\\;', '\\:'),
$participantCN);
trim(empty($info['cn']) ? $info['name'] : $info['cn']));
if ($version == '1.0')
{
$participantURL = trim('"' . $participantCN . '"' . (empty($info['email']) ? '' : ' <' . $info['email'] .'>'));
@ -861,7 +859,7 @@ class calendar_ical extends calendar_boupdate
$attributes['LAST-MODIFIED'] = $event['modified'];
}
$attributes['DTSTAMP'] = time();
foreach ((array)$event['alarm'] as $alarmID => $alarmData)
foreach ((array)$event['alarm'] as $alarmData)
{
// skip over alarms that don't have the minimum required info
if (!$alarmData['offset'] && !$alarmData['time']) continue;
@ -928,7 +926,7 @@ class calendar_ical extends calendar_boupdate
$alarmData['offset'] = false;
}
$valarm = Horde_iCalendar::newComponent('VALARM',$vevent);
$valarm = Horde_Icalendar::newComponent('VALARM',$vevent);
if ($alarmData['offset'] !== false)
{
$valarm->setAttribute('TRIGGER', -$alarmData['offset'],
@ -1122,6 +1120,7 @@ class calendar_ical extends calendar_boupdate
date_default_timezone_set($tzid);
$msg = null;
foreach ($events as $event)
{
if (!is_array($event)) continue; // the iterator may return false
@ -1390,8 +1389,7 @@ class calendar_ical extends calendar_boupdate
// They can now only remove themselfs, if that is desired, after storing the event first.
|| !isset($event['participants'][$event['owner']]))
{
$status = $event['owner'] == $this->user ? 'A' : 'U';
$status = calendar_so::combine_status($status, 1, 'CHAIR');
$status = calendar_so::combine_status($event['owner'] == $this->user ? 'A' : 'U', 1, 'CHAIR');
if (!is_array($event['participants'])) $event['participants'] = array();
$event['participants'][$event['owner']] = $status;
}
@ -1769,9 +1767,9 @@ class calendar_ical extends calendar_boupdate
/**
* get the value of an attribute by its name
*
* @param array $attributes
* @param array $components
* @param string $name eg. 'DTSTART'
* @param string $what='value'
* @param string $what ='value'
* @return mixed
*/
static function _get_attribute($components,$name,$what='value')
@ -1789,7 +1787,7 @@ class calendar_ical extends calendar_boupdate
static function valarm2egw(&$alarms, &$valarm)
{
$count = 0;
foreach ($valarm->_attributes as $vattr)
foreach ($valarm->getAllAttributes() as $vattr)
{
switch ($vattr['name'])
{
@ -2150,7 +2148,7 @@ class calendar_ical extends calendar_boupdate
* Convert vCalendar data in EGw events
*
* @param string|resource $_vcalData
* @param string $principalURL='' Used for CalDAV imports
* @param string $principalURL ='' Used for CalDAV imports
* @param string $charset The encoding charset for $text. Defaults to
* utf-8 for new format, iso-8859-1 for old format.
* @return Iterator|array|boolean Iterator if resource given or array of events on success, false on failure
@ -2183,7 +2181,7 @@ class calendar_ical extends calendar_boupdate
date_default_timezone_set($tzid);
$events = array();
$vcal = new Horde_iCalendar;
$vcal = new Horde_Icalendar;
if (!$vcal->parsevCalendar($_vcalData, 'VCALENDAR', $charset))
{
if ($this->log)
@ -2194,9 +2192,7 @@ class calendar_ical extends calendar_boupdate
date_default_timezone_set($GLOBALS['egw_info']['server']['server_timezone']);
return false;
}
$version = $vcal->getAttribute('VERSION');
foreach ($vcal->getComponents() as $n => $component)
foreach ($vcal->getComponents() as $component)
{
if (($event = $this->_ical2egw_callback($component,$this->tzid,$principalURL)))
{
@ -2209,14 +2205,15 @@ class calendar_ical extends calendar_boupdate
}
/**
* Callback for egw_ical_iterator to convert Horde_iCalendar_vevent to EGw event array
* Callback for egw_ical_iterator to convert Horde_iCalendar_Vevent to EGw event array
*
* @param Horde_iCalendar $component
* @param string $tzid timezone
* @param string $principalURL='' Used for CalDAV imports
* @return array|boolean event array or false if $component is no Horde_iCalendar_vevent
* @param string $principalURL ='' Used for CalDAV imports
* @param Horde_Icalendar $container =null container to access attributes on container
* @return array|boolean event array or false if $component is no Horde_Icalendar_Vevent
*/
function _ical2egw_callback(Horde_iCalendar $component, $tzid, $principalURL='')
function _ical2egw_callback(Horde_Icalendar $component, $tzid, $principalURL='', Horde_Icalendar $container=null)
{
//unset($component->_container); _debug_array($component);
@ -2225,8 +2222,9 @@ class calendar_ical extends calendar_boupdate
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__.'() '.get_class($component)." found\n",3,$this->logfile);
}
if (!is_a($component, 'Horde_iCalendar_vevent') ||
!($event = $this->vevent2egw($component, $component->_container->getAttribute('VERSION'), $this->supportedFields, $principalURL)))
if (!is_a($component, 'Horde_Icalendar_Vevent') ||
!($event = $this->vevent2egw($component, $container ? $container->getAttributeDefault('VERSION', '2.0') : '2.0',
$this->supportedFields, $principalURL, $container)))
{
return false;
}
@ -2246,7 +2244,7 @@ class calendar_ical extends calendar_boupdate
$alarms = $event['alarm'];
foreach ($component->getComponents() as $valarm)
{
if (is_a($valarm, 'Horde_iCalendar_valarm'))
if (is_a($valarm, 'Horde_Icalendar_Valarm'))
{
$this->valarm2egw($alarms, $valarm);
}
@ -2265,13 +2263,15 @@ class calendar_ical extends calendar_boupdate
* @param array $component VEVENT
* @param string $version vCal version (1.0/2.0)
* @param array $supportedFields supported fields of the device
* @param string $principalURL='' Used for CalDAV imports, no longer used in favor of groupdav_principals::url2uid()
* @param string $check_component='Horde_iCalendar_vevent'
*
* @param string $principalURL ='' Used for CalDAV imports, no longer used in favor of groupdav_principals::url2uid()
* @param string $check_component ='Horde_Icalendar_Vevent'
* @param Horde_Icalendar $container =null container to access attributes on container
* @return array|boolean event on success, false on failure
*/
function vevent2egw(&$component, $version, $supportedFields, $principalURL='', $check_component='Horde_iCalendar_vevent')
function vevent2egw($component, $version, $supportedFields, $principalURL='', $check_component='Horde_Icalendar_Vevent', Horde_Icalendar $container=null)
{
unset($principalURL); // not longer used, but required in function signature
if ($check_component && !is_a($component, $check_component))
{
if ($this->log)
@ -2283,8 +2283,8 @@ class calendar_ical extends calendar_boupdate
}
/*
$mozillaACK = $component->getAttribute('X-MOZ-LASTACK');
if ($this->productName == 'lightning' && !is_a($mozillaACK, 'PEAR_Error'))
$mozillaACK = $component->getAttributeDefault('X-MOZ-LASTACK', null);
if ($this->productName == 'lightning' && !isset($mozillaACK))
{
if ($this->log)
{
@ -2399,7 +2399,7 @@ class calendar_ical extends calendar_boupdate
return false; // not a valid entry
}
// lets see what we can get from the vcard
foreach ($component->_attributes as $attributes)
foreach ($component->getAllAttributes() as $attributes)
{
switch ($attributes['name'])
{
@ -2421,9 +2421,10 @@ class calendar_ical extends calendar_boupdate
break;
case 'DESCRIPTION':
$vcardData['description'] = str_replace("\r\n", "\n", $attributes['value']);
$matches = null;
if (preg_match('/\s*\[UID:(.+)?\]/Usm', $attributes['value'], $matches))
{
if (!isset($vCardData['uid'])
if (!isset($vcardData['uid'])
&& strlen($matches[1]) >= $minimum_uid_length)
{
$vcardData['uid'] = $matches[1];
@ -2463,6 +2464,7 @@ class calendar_ical extends calendar_boupdate
switch($type)
{
case 'D': // 1.0
$recurenceMatches = null;
if (preg_match('/D(\d+) #(\d+)/', $recurence, $recurenceMatches))
{
$vcardData['recur_interval'] = $recurenceMatches[1];
@ -2495,6 +2497,7 @@ class calendar_ical extends calendar_boupdate
$days = explode(' ',trim($recurenceMatches[2]));
}
$repeatMatches = null;
if (preg_match('/#(\d+)/',$recurenceMatches[4],$repeatMatches))
{
if ($repeatMatches[1]) $vcardData['recur_count'] = $repeatMatches[1];
@ -2847,6 +2850,7 @@ class calendar_ical extends calendar_boupdate
{
// keep role 'CHAIR' from an external organizer, even if he is a regular participant with a different role
// as this is currently the only way to store an external organizer and send him iMip responses
$q = $r = null;
if (isset($vcardData['participants'][$uid]) && ($s=$vcardData['participants'][$uid]) &&
calendar_so::split_status($s, $q, $r) && $r == 'CHAIR')
{
@ -2857,9 +2861,11 @@ class calendar_ical extends calendar_boupdate
$vcardData['participants'][$uid] =
calendar_so::combine_status($status, $quantity, $role);
if (!$this->calendarOwner && is_numeric($uid) &&
$role == 'CHAIR' &&
is_a($component->getAttribute('ORGANIZER'), 'PEAR_Error'))
try {
if (!$this->calendarOwner && is_numeric($uid) && $role == 'CHAIR')
$component->getAttribute('ORGANIZER');
}
catch(Horde_Icalendar_Exception $e)
{
// we can store the ORGANIZER as event owner
$event['owner'] = $uid;
@ -2906,9 +2912,8 @@ class calendar_ical extends calendar_boupdate
}
// check if the entry is a birthday
// this field is only set from NOKIA clients
$agendaEntryType = $component->getAttribute('X-EPOCAGENDAENTRYTYPE');
if (!is_a($agendaEntryType, 'PEAR_Error'))
{
try {
$agendaEntryType = $component->getAttribute('X-EPOCAGENDAENTRYTYPE');
if (strtolower($agendaEntryType) == 'anniversary')
{
$event['special'] = '1';
@ -2921,6 +2926,7 @@ class calendar_ical extends calendar_boupdate
$event['special'] = '2';
}
}
catch (Horde_Icalendar_Exception $e) {}
$event['priority'] = 2; // default
$event['alarm'] = $alarms;
@ -3001,13 +3007,15 @@ class calendar_ical extends calendar_boupdate
}
// Apple iCal on OS X uses X-CALENDARSERVER-ACCESS: CONFIDENTIAL on VCALANDAR (not VEVENT!)
if ($this->productManufacturer == 'GroupDAV' &&
($x_calendarserver_access = $component->_container->getAttribute('X-CALENDARSERVER-ACCESS')) &&
!is_a($x_calendarserver_access, 'PEAR_Error'))
{
$event['public'] = (int)(strtoupper($x_calendarserver_access) == 'PUBLIC');
try {
if ($this->productManufacturer == 'GroupDAV' && $container &&
($x_calendarserver_access = $container->getAttribute('X-CALENDARSERVER-ACCESS')))
{
$event['public'] = (int)(strtoupper($x_calendarserver_access) == 'PUBLIC');
}
//error_log(__METHOD__."() X-CALENDARSERVER-ACCESS=".array2string($x_calendarserver_access).' --> public='.array2string($event['public']));
}
//error_log(__METHOD__."() X-CALENDARSERVER-ACCESS=".array2string($x_calendarserver_access).' --> public='.array2string($event['public']));
catch (Horde_Icalendar_Exception $e) {}
// if no end is given in iCal we use the default lenght from user prefs
// whole day events get one day in calendar_boupdate::save()
@ -3019,8 +3027,7 @@ class calendar_ical extends calendar_boupdate
if ($this->calendarOwner) $event['owner'] = $this->calendarOwner;
// parsing ATTACH attributes for managed attachments
$attr = $component->getAttribute('X-EGROUPWARE-ATTACH-INCLUDED');
$event['attach-delete-by-put'] = !is_a($attr, PEAR_Error) && $attr === 'TRUE';
$event['attach-delete-by-put'] = $component->getAttributeDefault('X-EGROUPWARE-ATTACH-INCLUDED', null) === 'TRUE';
$event['attach'] = $component->getAllAttributes('ATTACH');
if ($this->log)
@ -3065,12 +3072,12 @@ class calendar_ical extends calendar_boupdate
* Create a freebusy vCal for the given user(s)
*
* @param int $user account_id
* @param mixed $end=null end-date, default now+1 month
* @param boolean $utc=true if false, use severtime for dates
* @param string $charset='UTF-8' encoding of the vcalendar, default UTF-8
* @param mixed $start=null default now
* @param string $method='PUBLISH' or eg. 'REPLY'
* @param array $extra=null extra attributes to add
* @param mixed $end =null end-date, default now+1 month
* @param boolean $utc =true if false, use severtime for dates
* @param string $charset ='UTF-8' encoding of the vcalendar, default UTF-8
* @param mixed $start =null default now
* @param string $method ='PUBLISH' or eg. 'REPLY'
* @param array $extra =null extra attributes to add
* X-CALENDARSERVER-MASK-UID can be used to not include an event specified by this uid as busy
*/
function freebusy($user,$end=null,$utc=true, $charset='UTF-8', $start=null, $method='PUBLISH', array $extra=null)
@ -3078,14 +3085,13 @@ class calendar_ical extends calendar_boupdate
if (!$start) $start = time(); // default now
if (!$end) $end = time() + 100*DAY_s; // default next 100 days
$vcal = new Horde_iCalendar;
$vcal = new Horde_Icalendar;
$vcal->setAttribute('PRODID','-//EGroupware//NONSGML EGroupware Calendar '.$GLOBALS['egw_info']['apps']['calendar']['version'].'//'.
strtoupper($GLOBALS['egw_info']['user']['preferences']['common']['lang']));
$vcal->setAttribute('VERSION','2.0');
$vcal->setAttribute('METHOD',$method);
$vfreebusy = Horde_iCalendar::newComponent('VFREEBUSY',$vcal);
if ($uid) $vfreebusy->setAttribute('UID', $uid);
$vfreebusy = Horde_Icalendar::newComponent('VFREEBUSY',$vcal);
$attributes = array(
'DTSTAMP' => time(),

View File

@ -380,30 +380,24 @@ class calendar_timezones
/**
* Add VTIMEZONE component to VCALENDAR
*
* @param Horde_iCalendar $vcal
* @param Horde_Icalendar $vcal
* @param string $tzid
* @return boolean false if no vtimezone component available, true on success
*/
public static function add_vtimezone($vcal, $tzid)
public static function add_vtimezone(Horde_Icalendar $vcal, $tzid)
{
include_once EGW_SERVER_ROOT.'/phpgwapi/inc/horde/lib/core.php';
// checking type of $val, now we included the object definition (no need to always include it!)
if (!$vcal instanceof Horde_iCalendar)
{
throw new egw_exception_wrong_parameter(__METHOD__.'('.array2string($vcal).", '$tzid') no Horde_iCalendar!");
}
// check if we have vtimezone component data for $tzid
if (!($vtimezone = calendar_timezones::tz2id($tzid, 'component')))
{
return false;
}
// $vtimezone is a string with a single VTIMEZONE component, afaik Horde_iCalendar can not add it directly
// --> we have to parse it and let Horde_iCalendar add it again
$horde_vtimezone = Horde_iCalendar::newComponent('VTIMEZONE',$container=false);
// $vtimezone is a string with a single VTIMEZONE component, afaik Horde_Icalendar can not add it directly
// --> we have to parse it and let Horde_Icalendar add it again
$horde_vtimezone = Horde_Icalendar::newComponent('VTIMEZONE',$container=false);
$horde_vtimezone->parsevCalendar($vtimezone,'VTIMEZONE');
// DTSTART is in UTC time, Horde_iCalendar parses it in server timezone, which we need to set again for printing
// DTSTART is in UTC time, Horde_Icalendar parses it in server timezone, which we need to set again for printing
$standard = $horde_vtimezone->findComponent('STANDARD');
if (is_a($standard, 'Horde_iCalendar'))
if (is_a($standard, 'Horde_Icalendar'))
{
$time = $standard->getAttribute('DTSTART');
$dtstart = new egw_time($time, egw_time::$server_timezone);
@ -411,7 +405,7 @@ class calendar_timezones
$standard->setAttribute('DTSTART', $dtstart->format('Ymd\THis'), array(), false);
}
$daylight = $horde_vtimezone->findComponent('DAYLIGHT');
if (is_a($daylight, 'Horde_iCalendar'))
if (is_a($daylight, 'Horde_Icalendar'))
{
$time = $daylight->getAttribute('DTSTART');
$dtstart = new egw_time($time, egw_time::$server_timezone);
@ -448,9 +442,8 @@ class calendar_timezones
switch ($type)
{
case 'vcalendar':
include_once EGW_SERVER_ROOT.'/phpgwapi/inc/horde/lib/core.php';
// checking type of $val, now we included the object definition (no need to always include it!)
$vcal = new Horde_iCalendar;
$vcal = new Horde_Icalendar;
$vcal->setAttribute('PRODID','-//EGroupware//NONSGML EGroupware Calendar '.$GLOBALS['egw_info']['apps']['calendar']['version'].'//'.
strtoupper($GLOBALS['egw_info']['user']['preferences']['common']['lang']));
self::add_vtimezone($vcal, $tzid);

View File

@ -7,12 +7,10 @@
* @package infolog
* @subpackage groupdav
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @copyright (c) 2007-13 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @copyright (c) 2007-15 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @version $Id$
*/
require_once EGW_SERVER_ROOT.'/phpgwapi/inc/horde/lib/core.php';
/**
* EGroupware: GroupDAV access: infolog handler
*
@ -66,7 +64,7 @@ class infolog_groupdav extends groupdav_handler
parent::__construct($app, $groupdav);
$this->bo = new infolog_bo();
$this->vCalendar = new Horde_iCalendar;
$this->vCalendar = new Horde_Icalendar;
// since 1.9.002 we allow clients to specify the URL when creating a new event, as specified by CalDAV
if (version_compare($GLOBALS['egw_info']['apps']['calendar']['version'], '1.9.002', '>='))

View File

@ -7,13 +7,10 @@
* @author Joerg Lehrke <jlehrke@noc.de>
* @author Ralf Becker <RalfBecker@outdoor-training.de>
* @package infolog
* @subpackage syncml
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @version $Id$
*/
require_once EGW_SERVER_ROOT.'/phpgwapi/inc/horde/lib/core.php';
/**
* InfoLog: Create and parse iCal's
*/
@ -112,14 +109,14 @@ class infolog_ical extends infolog_bo
* Exports multiple InfoLogs
*
* @param array $tasks array of info_ids or task arrays
* @param string $_version='2.0'
* @param string $_method=null only set for iTip messages
* @param string $charset='UTF-8'
* @param string $_version ='2.0'
* @param string $_method =null only set for iTip messages
* @param string $charset ='UTF-8'
* @return string|boolean string with vCal or false on error (eg. no permission to read the event)
*/
function exportVCalendar(array $tasks, $_version='2.0', $_method=null, $charset='UTF-8')
{
$vcal = new Horde_iCalendar;
$vcal = new Horde_Icalendar;
foreach($tasks as $task)
{
@ -135,14 +132,14 @@ class infolog_ical extends infolog_bo
* Exports one InfoLog tast to an iCalendar VTODO
*
* @param int|array $task infolog_id or infolog-tasks data
* @param string $_version='2.0' could be '1.0' too
* @param string $_method='PUBLISH'
* @param string $charset='UTF-8' encoding of the vcalendar, default UTF-8
* @param Horde_iCalendar $vcal=null optional iCalendar object to add vtodo to
* @param string $_version ='2.0' could be '1.0' too
* @param string $_method ='PUBLISH'
* @param string $charset ='UTF-8' encoding of the vcalendar, default UTF-8
* @param Horde_Icalendar $vcal =null optional iCalendar object to add vtodo to
*
* @return string|boolean string with vCal or false on error (eg. no permission to read the event)
*/
function exportVTODO($task, $_version='2.0',$_method='PUBLISH', $charset='UTF-8',Horde_iCalendar $vcal=null)
function exportVTODO($task, $_version='2.0',$_method='PUBLISH', $charset='UTF-8',Horde_Icalendar $vcal=null)
{
if (is_array($task))
{
@ -190,7 +187,7 @@ class infolog_ical extends infolog_bo
array2string($taskData)."\n",3,$this->logfile);
}
if (!isset($vcal)) $vcal = new Horde_iCalendar;
if (!isset($vcal)) $vcal = new Horde_Icalendar;
$vcal->setAttribute('PRODID','-//EGroupware//NONSGML EGroupware InfoLog '.$GLOBALS['egw_info']['apps']['infolog']['version'].'//'.
strtoupper($GLOBALS['egw_info']['user']['preferences']['common']['lang']),array(),false);
$vcal->setAttribute('VERSION',$_version,array(),false);
@ -203,7 +200,7 @@ class infolog_ical extends infolog_bo
if (!calendar_timezones::add_vtimezone($vcal, $tzid))
{
error_log(__METHOD__."() unknown TZID='$tzid', defaulting to user timezone '".egw_time::$user_timezone->getName()."'!");
calendar_timezones::add_vtimezone($vcal, $tzid=egw_time::$user_timezone->getName());
calendar_timezones::add_vtimezone($vcal, egw_time::$user_timezone->getName());
$tzid = null;
}
if (!isset(self::$tz_cache[$tzid]))
@ -212,7 +209,7 @@ class infolog_ical extends infolog_bo
}
}
$vevent = Horde_iCalendar::newComponent('VTODO',$vcal);
$vevent = Horde_Icalendar::newComponent('VTODO',$vcal);
if (!isset($this->clientProperties['SUMMARY']['Size']))
{
@ -407,7 +404,7 @@ class infolog_ical extends infolog_bo
if ($value[1] == ':' && ($v = unserialize($value)) !== false) $value = $v;
foreach((array)$value as $compvData)
{
$comp = Horde_iCalendar::newComponent(substr($name,3), $vevent);
$comp = Horde_Icalendar::newComponent(substr($name,3), $vevent);
$comp->parsevCalendar($compvData,substr($name,3),'utf-8');
$vevent->addComponent($comp);
}
@ -440,7 +437,7 @@ class infolog_ical extends infolog_bo
* set date-time attribute to DATE or DATE-TIME depending on value
* 00:00 uses DATE else DATE-TIME
*
* @param Horde_iCalendar_* $vevent
* @param Horde_Icalendar_* $vevent
* @param string $attr attribute name
* @param int $time timestamp in server-time
* @param string $tzid timezone to use for client, null for user-time, false for server-time
@ -448,7 +445,7 @@ class infolog_ical extends infolog_bo
static function setDateOrTime(&$vevent, $attr, $time, $tzid)
{
$params = array();
$time_in = $time;
//$time_in = $time;
if ($tzid)
{
@ -507,19 +504,20 @@ class infolog_ical extends infolog_bo
* Import a VTODO component of an iCal
*
* @param string $_vcalData
* @param int $_taskID=-1 info_id, default -1 = new entry
* @param boolean $merge=false merge data with existing entry
* @param int $user=null delegate new task to this account_id, default null
* @param string $charset=null The encoding charset for $text. Defaults to
* @param int $_taskID =-1 info_id, default -1 = new entry
* @param boolean $merge =false merge data with existing entry (no longer used)
* @param int $user =null delegate new task to this account_id, default null
* @param string $charset =null The encoding charset for $text. Defaults to
* utf-8 for new format, iso-8859-1 for old format.
* @param string $caldav_name=null CalDAV URL name-part for new entries
* @param array $callback_data=null array with callback and further parameters, first param is task to save
* @param string $caldav_name =null CalDAV URL name-part for new entries
* @param array $callback_data =null array with callback and further parameters, first param is task to save
* signature array callback($task, $param1, ...)
* @return int|boolean integer info_id or false on error
*/
function importVTODO(&$_vcalData, $_taskID=-1, $merge=false, $user=null, $charset=null, $caldav_name=null,
array $callback_data=null)
{
unset($merge); // no longer used, but required by function signature
if ($this->tzid)
{
@ -575,7 +573,7 @@ class infolog_ical extends infolog_bo
'info_access','info_status','info_percent','info_datecompleted',
)));
// remove all iCal fields not supported by EGroupware (stored like custom fields)
foreach($old as $name => $value)
foreach(array_keys($old) as $name)
{
if (substr($name,0,2) == '##') unset($old[$name]);
}
@ -595,8 +593,8 @@ class infolog_ical extends infolog_bo
* Search a matching infolog entry for the VTODO data
*
* @param string $_vcalData VTODO
* @param int $contentID=null infolog_id (or null, if unkown)
* @param boolean $relax=false if true, a weaker match algorithm is used
* @param int $contentID =null infolog_id (or null, if unkown)
* @param boolean $relax =false if true, a weaker match algorithm is used
* @param string $charset The encoding charset for $text. Defaults to
* utf-8 for new format, iso-8859-1 for old format.
*
@ -630,7 +628,7 @@ class infolog_ical extends infolog_bo
* Convert VTODO into a eGW infolog entry
*
* @param string $_vcalData VTODO data
* @param int $_taskID=-1 infolog_id of the entry
* @param int $_taskID =-1 infolog_id of the entry
* @param string $charset The encoding charset for $text. Defaults to
* utf-8 for new format, iso-8859-1 for old format.
*
@ -644,7 +642,7 @@ class infolog_ical extends infolog_bo
array2string($_vcalData)."\n",3,$this->logfile);
}
$vcal = new Horde_iCalendar;
$vcal = new Horde_Icalendar;
if (!($vcal->parsevCalendar($_vcalData, 'VCALENDAR', $charset)))
{
if ($this->log)
@ -655,8 +653,6 @@ class infolog_ical extends infolog_bo
return false;
}
$version = $vcal->getAttribute('VERSION');
if (isset($GLOBALS['egw_info']['user']['preferences']['syncml']['minimum_uid_length']))
{
$minimum_uid_length = $GLOBALS['egw_info']['user']['preferences']['syncml']['minimum_uid_length'];
@ -670,7 +666,7 @@ class infolog_ical extends infolog_bo
foreach ($vcal->getComponents() as $component)
{
if (!is_a($component, 'Horde_iCalendar_vtodo'))
if (!is_a($component, 'Horde_Icalendar_Vtodo'))
{
if ($this->log)
{
@ -689,15 +685,19 @@ class infolog_ical extends infolog_bo
// iOS reminder app only sets COMPLETED, but never STATUS nor PERCENT-COMPLETED
// if we have no STATUS, set STATUS by existence of COMPLETED and/or PERCENT-COMPLETE and X-INFOLOG-STATUS
// if we have no PERCENT-COMPLETE set it from STATUS: 0=NEEDS-ACTION, 10=IN-PROCESS, 100=COMPLETED
if (!($status = $component->getAttribute('STATUS')) || !is_scalar($status))
try {
$status = $component->getAttribute('STATUS');
}
catch (Horde_Icalendar_Exception $e)
{
$completed = $component->getAttribute('COMPLETED');
$x_infolog_status = $component->getAttribute('X-INFOLOG-STATUS');
unset($e);
$completed = $component->getAttributeDefault('COMPLETED', null);
$x_infolog_status = $component->getAttributeDefault('X-INFOLOG-STATUS', null);
// check if we have a X-INFOLOG-STATUS and it's completed state is different from given COMPLETED attr
if (is_scalar($x_infolog_status) &&
($this->_status2vtodo[$x_infolog_status] === 'COMPLETED') != is_scalar($completed))
{
$percent_completed = $component->getAttribute('PERCENT-COMPLETE');
$percent_completed = $component->getAttributeDefault('PERCENT-COMPLETE', null);
$status = $completed && is_scalar($completed) ? 'COMPLETED' :
($percent_completed && is_scalar($percent_completed) && $percent_completed > 0 ? 'IN-PROCESS' : 'NEEDS-ACTION');
$component->setAttribute('STATUS', $status);
@ -731,6 +731,7 @@ class infolog_ical extends infolog_bo
case 'DESCRIPTION':
$value = str_replace("\r\n", "\n", $attribute['value']);
$matches = null;
if (preg_match('/\s*\[UID:(.+)?\]/Usm', $value, $matches))
{
if (!isset($taskData['info_uid'])
@ -759,7 +760,7 @@ class infolog_ical extends infolog_bo
case 'DURATION':
if (!isset($taskData['info_startdate']))
{
$taskData['info_startdate'] = $component->getAttribute('DTSTART');
$taskData['info_startdate'] = $component->getAttributeDefault('DTSTART', null);
}
$attribute['value'] += $taskData['info_startdate'];
$taskData['##DURATION'] = $attribute['value'];
@ -803,7 +804,7 @@ class infolog_ical extends infolog_bo
case 'STATUS':
// check if we (still) have X-INFOLOG-STATUS set AND it would give an unchanged status (no change by the user)
$taskData['info_status'] = $this->vtodo2status($attribute['value'],
($attr=$component->getAttribute('X-INFOLOG-STATUS')) && is_scalar($attr) ? $attr : null);
$component->getAttributeDefault('X-INFOLOG-STATUS', null));
break;
case 'SUMMARY':
@ -899,7 +900,7 @@ class infolog_ical extends infolog_bo
*
* @param int $_noteID the infolog_id of the entry
* @param string $_type content type (e.g. text/plain)
* @param string $charset='UTF-8' encoding of the vcalendar, default UTF-8
* @param string $charset ='UTF-8' encoding of the vcalendar, default UTF-8
*
* @return string|boolean VNOTE representation of the infolog entry or false on error
*/
@ -923,7 +924,7 @@ class infolog_ical extends infolog_bo
$note['info_cat'] = translation::convert($cats[0],
translation::charset(), $charset);
}
$vnote = new Horde_iCalendar_vnote();
$vnote = new Horde_Icalendar_Vnote();
$vnote->setAttribute('PRODID','-//EGroupware//NONSGML EGroupware InfoLog '.$GLOBALS['egw_info']['apps']['infolog']['version'].'//'.
strtoupper($GLOBALS['egw_info']['user']['preferences']['common']['lang']));
$vnote->setAttribute('VERSION', '1.1');
@ -961,15 +962,15 @@ class infolog_ical extends infolog_bo
$options['ENCODING'] = 'FUNAMBOL-QP';
}
}
$vevent->setAttribute($field, $value, $options);
$vnote->setAttribute($field, $value, $options);
}
if ($note['info_startdate'])
{
$vnote->setAttribute('DCREATED',$note['info_startdate']);
$vnote->setAttribute('CREATED',$note['info_startdate']);
}
else
{
$vnote->setAttribute('DCREATED',$GLOBALS['egw']->contenthistory->getTSforAction('infolog_note',$_noteID,'add'));
$vnote->setAttribute('CREATED',$GLOBALS['egw']->contenthistory->getTSforAction('infolog_note',$_noteID,'add'));
}
$vnote->setAttribute('LAST-MODIFIED',$GLOBALS['egw']->contenthistory->getTSforAction('infolog_note',$_noteID,'modify'));
@ -991,8 +992,8 @@ class infolog_ical extends infolog_bo
*
* @param string $_vcalData
* @param string $_type content type (eg.g text/plain)
* @param int $_noteID=-1 info_id, default -1 = new entry
* @param boolean $merge=false merge data with existing entry
* @param int $_noteID =-1 info_id, default -1 = new entry
* @param boolean $merge =false merge data with existing entry (no longer used)
* @param string $charset The encoding charset for $text. Defaults to
* utf-8 for new format, iso-8859-1 for old format.
*
@ -1000,6 +1001,7 @@ class infolog_ical extends infolog_bo
*/
function importVNOTE(&$_vcalData, $_type, $_noteID=-1, $merge=false, $charset=null)
{
unset($merge); // no longer used, but required by function signature
if ($this->log)
{
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__."()\n" .
@ -1048,7 +1050,7 @@ class infolog_ical extends infolog_bo
*
* @param string $_data VNOTE data
* @param string $_type content type (eg.g text/plain)
* @param int $_noteID=-1 infolog_id of the entry
* @param int $_noteID =-1 infolog_id of the entry
* @param string $charset The encoding charset for $text. Defaults to
* utf-8 for new format, iso-8859-1 for old format.
*
@ -1068,9 +1070,9 @@ class infolog_ical extends infolog_bo
case 'text/plain':
$note = array();
$note['info_type'] = 'note';
$txt = translation::convert($_data, $charset);
$txt = str_replace("\r\n", "\n", $txt);
$txt = str_replace("\r\n", "\n", translation::convert($_data, $charset));
$match = null;
if (preg_match('/([^\n]+)\n\n(.*)/ms', $txt, $match))
{
$note['info_subject'] = $match[1];
@ -1083,19 +1085,18 @@ class infolog_ical extends infolog_bo
break;
case 'text/x-vnote':
$vnote = new Horde_iCalendar;
if (!$vcal->parsevCalendar($_data, 'VCALENDAR', $charset)) return false;
$version = $vcal->getAttribute('VERSION');
$vnote = new Horde_Icalendar;
if (!$vnote->parsevCalendar($_data, 'VCALENDAR', $charset)) return false;
$components = $vnote->getComponent();
foreach ($components as $component)
{
if (is_a($component, 'Horde_iCalendar_vnote'))
if (is_a($component, 'Horde_Icalendar_Vnote'))
{
$note = array();
$note['info_type'] = 'note';
foreach ($component->_attributes as $attribute)
foreach ($component->getAllAttributes() as $attribute)
{
switch ($attribute['name'])
{
@ -1193,10 +1194,9 @@ class infolog_ical extends infolog_bo
")\n" , 3, $this->logfile);
}
Horde::logMessage('setSupportedFields(' . $this->productManufacturer . ', '
. $this->productName .', ' .
($this->tzid ? $this->tzid : egw_time::$user_timezone->getName()) .')',
__FILE__, __LINE__, PEAR_LOG_DEBUG);
//Horde::logMessage('setSupportedFields(' . $this->productManufacturer . ', '
// . $this->productName .', ' .
// ($this->tzid ? $this->tzid : egw_time::$user_timezone->getName()) .')',
// __FILE__, __LINE__, PEAR_LOG_DEBUG);
}
}