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

View File

@ -11,8 +11,6 @@
* @version $Id$ * @version $Id$
*/ */
require_once EGW_SERVER_ROOT.'/phpgwapi/inc/horde/lib/core.php';
/** /**
* EGroupware: CalDAV / GroupDAV access: calendar handler * EGroupware: CalDAV / GroupDAV access: calendar handler
* *
@ -35,7 +33,7 @@ class calendar_groupdav extends groupdav_handler
/** /**
* vCalendar Instance for parsing * vCalendar Instance for parsing
* *
* @var Horde_iCalendar * @var Horde_Icalendar
*/ */
var $vCalendar; var $vCalendar;
@ -95,7 +93,7 @@ class calendar_groupdav extends groupdav_handler
parent::__construct($app, $groupdav); parent::__construct($app, $groupdav);
$this->bo = new calendar_boupdate(); $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 // 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', '>=')) 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) 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)) if (!$vcal->parsevCalendar($ical, 'VCALENDAR', $charset))
{ {
return '400 Bad request'; return '400 Bad request';
@ -1098,7 +1095,7 @@ class calendar_groupdav extends groupdav_handler
$handler->setSupportedFields('groupdav'); $handler->setSupportedFields('groupdav');
$handler->calendarOwner = $handler->user = 0; // to NOT default owner/organizer to something $handler->calendarOwner = $handler->user = 0; // to NOT default owner/organizer to something
if (!($component = $vcal->getComponent(0)) || 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'; return '400 Bad request';
} }

View File

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

View File

@ -380,30 +380,24 @@ class calendar_timezones
/** /**
* Add VTIMEZONE component to VCALENDAR * Add VTIMEZONE component to VCALENDAR
* *
* @param Horde_iCalendar $vcal * @param Horde_Icalendar $vcal
* @param string $tzid * @param string $tzid
* @return boolean false if no vtimezone component available, true on success * @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 // check if we have vtimezone component data for $tzid
if (!($vtimezone = calendar_timezones::tz2id($tzid, 'component'))) if (!($vtimezone = calendar_timezones::tz2id($tzid, 'component')))
{ {
return false; return false;
} }
// $vtimezone is a string with a single VTIMEZONE component, afaik Horde_iCalendar can not add it directly // $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 // --> we have to parse it and let Horde_Icalendar add it again
$horde_vtimezone = Horde_iCalendar::newComponent('VTIMEZONE',$container=false); $horde_vtimezone = Horde_Icalendar::newComponent('VTIMEZONE',$container=false);
$horde_vtimezone->parsevCalendar($vtimezone,'VTIMEZONE'); $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'); $standard = $horde_vtimezone->findComponent('STANDARD');
if (is_a($standard, 'Horde_iCalendar')) if (is_a($standard, 'Horde_Icalendar'))
{ {
$time = $standard->getAttribute('DTSTART'); $time = $standard->getAttribute('DTSTART');
$dtstart = new egw_time($time, egw_time::$server_timezone); $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); $standard->setAttribute('DTSTART', $dtstart->format('Ymd\THis'), array(), false);
} }
$daylight = $horde_vtimezone->findComponent('DAYLIGHT'); $daylight = $horde_vtimezone->findComponent('DAYLIGHT');
if (is_a($daylight, 'Horde_iCalendar')) if (is_a($daylight, 'Horde_Icalendar'))
{ {
$time = $daylight->getAttribute('DTSTART'); $time = $daylight->getAttribute('DTSTART');
$dtstart = new egw_time($time, egw_time::$server_timezone); $dtstart = new egw_time($time, egw_time::$server_timezone);
@ -448,9 +442,8 @@ class calendar_timezones
switch ($type) switch ($type)
{ {
case 'vcalendar': 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!) // 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'].'//'. $vcal->setAttribute('PRODID','-//EGroupware//NONSGML EGroupware Calendar '.$GLOBALS['egw_info']['apps']['calendar']['version'].'//'.
strtoupper($GLOBALS['egw_info']['user']['preferences']['common']['lang'])); strtoupper($GLOBALS['egw_info']['user']['preferences']['common']['lang']));
self::add_vtimezone($vcal, $tzid); self::add_vtimezone($vcal, $tzid);

View File

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