using new Horde code in vendor for CalDAV/CardDAV, moved all old Horde and SyncML code to syncml app, not sure it is still functional

This commit is contained in:
Ralf Becker 2015-06-22 15:36:23 +00:00
parent 99b7fc66a0
commit 3b4708f9ea
67 changed files with 100 additions and 22804 deletions

View File

@ -1,315 +0,0 @@
<?php
/**
* Addressbook - SIF parser
*
* @link http://www.egroupware.org
* @author Lars Kneschke <lkneschke@egroupware.org>
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @author Joerg Lehrke <jlehrke@noc.de>
* @package addressbook
* @subpackage export
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @version $Id$
*/
class addressbook_sif extends addressbook_bo
{
var $sifMapping = array(
'Anniversary' => '',
'AssistantName' => 'assistent',
'AssistantTelephoneNumber' => 'tel_assistent',
'BillingInformation' => '',
'Birthday' => 'bday',
'Body' => 'note',
'Business2TelephoneNumber' => '',
'BusinessAddressCity' => 'adr_one_locality',
'BusinessAddressCountry' => 'adr_one_countryname',
'BusinessAddressPostalCode' => 'adr_one_postalcode',
'BusinessAddressPostOfficeBox' => 'adr_one_street2',
'BusinessAddressState' => 'adr_one_region',
'BusinessAddressStreet' => 'adr_one_street',
'BusinessFaxNumber' => 'tel_fax',
'BusinessTelephoneNumber' => 'tel_work',
'CallbackTelephoneNumber' => '',
'CarTelephoneNumber' => 'tel_car',
'Categories' => 'cat_id',
'Children' => '',
'Companies' => '',
'CompanyMainTelephoneNumber' => '',
'CompanyName' => 'org_name',
'ComputerNetworkName' => '',
'Department' => 'org_unit',
'Email1Address' => 'email',
'Email1AddressType' => '',
'Email2Address' => 'email_home',
'Email2AddressType' => '',
'Email3Address' => '',
'Email3AddressType' => '',
'FileAs' => 'n_fileas',
'FirstName' => 'n_given',
'Hobby' => '',
'Home2TelephoneNumber' => '',
'HomeAddressCity' => 'adr_two_locality',
'HomeAddressCountry' => 'adr_two_countryname',
'HomeAddressPostalCode' => 'adr_two_postalcode',
'HomeAddressPostOfficeBox' => 'adr_two_street2',
'HomeAddressState' => 'adr_two_region',
'HomeAddressStreet' => 'adr_two_street',
'HomeFaxNumber' => 'tel_fax_home',
'HomeTelephoneNumber' => 'tel_home',
'Importance' => '',
'Initials' => '',
'JobTitle' => 'title',
'Language' => '',
'LastName' => 'n_family',
'ManagerName' => '',
'MiddleName' => 'n_middle',
'Mileage' => '',
'MobileTelephoneNumber' => 'tel_cell',
'NickName' => '',
'OfficeLocation' => 'room',
'OrganizationalIDNumber' => '',
'OtherAddressCity' => '',
'OtherAddressCountry' => '',
'OtherAddressPostalCode' => '',
'OtherAddressPostOfficeBox' => '',
'OtherAddressState' => '',
'OtherAddressStreet' => '',
'OtherFaxNumber' => '',
'OtherTelephoneNumber' => 'tel_other',
'PagerNumber' => 'tel_pager',
'PrimaryTelephoneNumber' => 'tel_prefer',
'Profession' => 'role',
'RadioTelephoneNumber' => '',
'Sensitivity' => 'private',
'Spouse' => '',
'Subject' => '',
'Suffix' => 'n_suffix',
'TelexNumber' => '',
'Title' => 'n_prefix',
'WebPage' => 'url',
'YomiCompanyName' => '',
'YomiFirstName' => '',
'YomiLastName' => '',
'HomeWebPage' => 'url_home',
'Folder' => '',
);
// standard headers
const xml_decl = '<?xml version="1.0" encoding="UTF-8"?>';
const SIF_decl = '<SIFVersion>1.1</SIFVersion>';
function startElement($_parser, $_tag, $_attributes)
{
}
function endElement($_parser, $_tag)
{
if (!empty($this->sifMapping[$_tag]))
{
$this->contact[$this->sifMapping[$_tag]] = trim($this->sifData);
}
unset($this->sifData);
}
function characterData($_parser, $_data)
{
$this->sifData .= $_data;
}
function siftoegw($sifData)
{
#$tmpfname = tempnam('/tmp/sync/contents','sifc_');
#$handle = fopen($tmpfname, "w");
#fwrite($handle, $sifData);
#fclose($handle);
// Horde::logMessage("SyncML siftoegw:\n$sifData", __FILE__, __LINE__, PEAR_LOG_DEBUG);
$this->xml_parser = xml_parser_create('UTF-8');
xml_set_object($this->xml_parser, $this);
xml_parser_set_option($this->xml_parser, XML_OPTION_CASE_FOLDING, false);
xml_set_element_handler($this->xml_parser, "startElement", "endElement");
xml_set_character_data_handler($this->xml_parser, "characterData");
$this->strXmlData = xml_parse($this->xml_parser, $sifData);
if (!$this->strXmlData)
{
error_log(sprintf("XML error: %s at line %d",
xml_error_string(xml_get_error_code($this->xml_parser)),
xml_get_current_line_number($this->xml_parser)));
return false;
}
foreach ($this->contact as $key => $value)
{
$value = preg_replace('/<\!\[CDATA\[(.+)\]\]>/Usim', '$1', $value);
$value = $GLOBALS['egw']->translation->convert($value, 'utf-8');
switch ($key) {
case 'cat_id':
if (!empty($value))
{
$categories1 = explode(',', $value);
$categories2 = explode(';', $value);
$finalContact[$key] = count($categories1) > count($categories2) ? $categories1 : $categories2;
}
break;
case 'private':
$finalContact[$key] = (int) ($value > 0); // eGW private is 0 (public) or 1 (private), SIF seems to use 0 and 2
break;
default:
$finalContact[$key] = str_replace("\r\n", "\n", $value);
break;
}
}
$this->fixup_contact($finalContact);
// Horde::logMessage("SyncML siftoegw: " . print_r($finalContact, true), __FILE__, __LINE__, PEAR_LOG_DEBUG);
return $finalContact;
}
/**
* Search an exactly matching entry (used for slow sync)
*
* @param string $_sifdata
* @return array of matching contact-ids
*/
function search($_sifdata, $contentID=null, $relax=false)
{
$result = array();
if (($contact = $this->siftoegw($_sifdata)))
{
if ($contentID)
{
$contact['contact_id'] = $contentID;
}
$result = $this->find_contact($contact, $relax);
}
return $result;
}
/**
* import a vard into addressbook
*
* @return int contact id
* @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
*/
function addSIF($_sifdata, $_abID=null, $merge=false)
{
if (!$contact = $this->siftoegw($_sifdata))
{
return false;
}
if ($_abID)
{
if (($old_contact = $this->read($_abID)))
{
if ($merge)
{
foreach ($contact as $key => $value)
{
if (!empty($old_contact[$key]))
{
$contact[$key] = $old_contact[$key];
}
}
}
else
{
if (isset($old_contact['account_id']))
{
$contact['account_id'] = $old_contact['account_id'];
}
if (is_array($contact['cat_id']))
{
$contact['cat_id'] = implode(',',$this->find_or_add_categories($contact['cat_id'], $_abID));
}
else
{
// restore from orignal
$contact['cat_id'] = $old_contact['cat_id'];
}
}
}
// update entry
$contact['id'] = $_abID;
}
else
{
if (is_array($contact['cat_id']))
{
$contact['cat_id'] = implode(',',$this->find_or_add_categories($contact['cat_id'], -1));
}
}
return $this->save($contact);
}
/**
* return a sifc
*
* @param int $_id the id of the contact
* @return string containing the vcard
*/
function getSIF($_id)
{
$sysCharSet = $GLOBALS['egw']->translation->charset();
$fields = array_unique(array_values($this->sifMapping));
sort($fields);
if (!($entry = $this->read($_id))) return false;
$sifContact = self::xml_decl . "\n<contact>" . self::SIF_decl;
#error_log(print_r($entry,true));
// fillup some defaults such as n_fn and n_fileas is needed
$this->fixup_contact($entry);
foreach ($this->sifMapping as $sifField => $egwField)
{
if (empty($egwField)) continue;
#error_log("$sifField => $egwField");
#error_log('VALUE1: '.$entry[0][$egwField]);
$value = $GLOBALS['egw']->translation->convert($entry[$egwField], $sysCharSet, 'utf-8');
#error_log('VALUE2: '.$value);
switch ($sifField)
{
case 'Sensitivity':
$value = 2 * $value; // eGW private is 0 (public) or 1 (private)
$sifContact .= "<$sifField>$value</$sifField>";
break;
case 'Folder':
# skip currently. This is the folder where Outlook stores the contact.
#$sifContact .= "<$sifField>/</$sifField>";
break;
case 'Categories':
if (!empty($value)) {
$value = implode(", ", $this->get_categories($value));
$value = $GLOBALS['egw']->translation->convert($value, $sysCharSet, 'utf-8');
} else {
break;
}
default:
$value = @htmlspecialchars(trim($value), ENT_NOQUOTES, 'utf-8');
$sifContact .= "<$sifField>$value</$sifField>";
break;
}
}
$sifContact .= "</contact>";
return $sifContact;
}
}

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
* *
@ -75,7 +72,7 @@ class addressbook_vcal extends addressbook_bo
'REV' => array('modified'), 'REV' => array('modified'),
//set for Apple: 'X-ABSHOWAS' => array('fileas_type'), // Horde vCard class uses uppercase prop-names! //set for Apple: 'X-ABSHOWAS' => array('fileas_type'), // Horde vCard class uses uppercase prop-names!
); );
var $supportedFields; var $supportedFields;
/** /**
@ -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']));
@ -525,7 +518,7 @@ class addressbook_vcal extends addressbook_bo
if (is_array($_supportedFields)) $this->supportedFields = $_supportedFields; if (is_array($_supportedFields)) $this->supportedFields = $_supportedFields;
} }
function setDatabaseFields($_databaseFields) function setDatabaseFields($_databaseFields)
{ {
if (is_array($_databaseFields)) $this->databaseFields = $_databaseFields; if (is_array($_databaseFields)) $this->databaseFields = $_databaseFields;
@ -551,7 +544,7 @@ 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'); // require_once(EGW_SERVER_ROOT.'/phpgwapi/inc/horde/Horde/iCalendar.php');
if(!($_vcard instanceof Horde_iCalendar)) if(!($_vcard instanceof Horde_iCalendar))
{ {
@ -1053,14 +1046,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

@ -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')
@ -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,14 @@ 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 * @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='')
{ {
//unset($component->_container); _debug_array($component); //unset($component->_container); _debug_array($component);
@ -2225,7 +2221,7 @@ 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, $component->_container->getAttribute('VERSION'), $this->supportedFields, $principalURL)))
{ {
return false; return false;
@ -2246,7 +2242,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 +2261,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'
* *
* @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')
{ {
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)
@ -2421,9 +2419,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 +2462,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 +2495,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 +2848,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')
{ {
@ -3065,12 +3067,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 +3080,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(),

File diff suppressed because it is too large Load Diff

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)
{ {
@ -731,6 +727,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'])
@ -899,7 +896,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 +920,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 +958,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 +988,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 +997,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 +1046,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 +1066,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,14 +1081,13 @@ 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';

View File

@ -1,668 +0,0 @@
<?php
/**
* InfoLog - SIF Parser
*
* @link http://www.egroupware.org
* @author Lars Kneschke <lkneschke@egroupware.org>
* @author Joerg Lehrke <jlehrke@noc.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 SIF
*
*/
class infolog_sif extends infolog_bo
{
// array containing the result of the xml parser
var $_extractedSIFData;
// array containing the current mappings(task or note)
var $_currentSIFMapping;
var $_sifNoteMapping = array(
'Body' => 'info_des',
'Categories' => 'info_cat',
'Color' => '',
'Date' => 'info_startdate',
'Height' => '',
'Left' => '',
'Subject' => 'info_subject',
'Top' => '',
'Width' => '',
);
// mappings for SIFTask to InfologTask
var $_sifTaskMapping = array(
'ActualWork' => '',
'BillingInformation' => '',
'Body' => 'info_des',
'Categories' => 'info_cat',
'Companies' => '',
'Complete' => 'complete',
'DateCompleted' => 'info_datecompleted',
'DueDate' => 'info_enddate',
'Importance' => 'info_priority',
'IsRecurring' => '',
'Mileage' => '',
'PercentComplete' => 'info_percent',
'ReminderSet' => '',
'ReminderTime' => '',
'Sensitivity' => 'info_access',
'StartDate' => 'info_startdate',
'Status' => 'info_status',
'Subject' => 'info_subject',
'TeamTask' => '',
'TotalWork' => '',
'RecurrenceType' => '',
'Interval' => '',
'MonthOfYear' => '',
'DayOfMonth' => '',
'DayOfWeekMask' => '',
'Instance' => '',
'PatternStartDate' => '',
'NoEndDate' => '',
'PatternEndDate' => '',
'Occurrences' => '',
);
// standard headers
const xml_decl = '<?xml version="1.0" encoding="UTF-8"?>';
const SIF_decl = '<SIFVersion>1.1</SIFVersion>';
/**
* name and version of the sync-client
*
* @var string
*/
var $productName = 'mozilla plugin';
var $productSoftwareVersion = '0.3';
/**
* Shall we use the UID extensions of the description field?
*
* @var boolean
*/
var $uidExtension = false;
/**
* user preference: Use this timezone for import from and export to device
*
* @var string
*/
var $tzid = null;
/**
* Set Logging
*
* @var boolean
*/
var $log = false;
var $logfile="/tmp/log-infolog-sif";
/**
* Constructor
*
*/
function __construct()
{
parent::__construct();
if ($this->log) $this->logfile = $GLOBALS['egw_info']['server']['temp_dir']."/log-infolog-sif";
$this->vCalendar = new Horde_iCalendar;
}
/**
* Get DateTime value for a given time and timezone
*
* @param int|string|DateTime $time in server-time as returned by calendar_bo for $data_format='server'
* @param string $tzid TZID of event or 'UTC' or NULL for palmos timestamps in usertime
*
*/
function getDateTime($time, $tzid)
{
if (empty($tzid) || $tzid == 'UTC')
{
return $this->vCalendar->_exportDateTime(egw_time::to($time,'ts'));
}
if (!is_a($time,'DateTime'))
{
$time = new egw_time($time,egw_time::$server_timezone);
}
if (!isset(self::$tz_cache[$tzid]))
{
self::$tz_cache[$tzid] = calendar_timezones::DateTimeZone($tzid);
}
// check for date --> export it as such
if ($time->format('Hi') == '0000')
{
$arr = egw_time::to($time, 'array');
$time = new egw_time($arr, self::$tz_cache[$tzid]);
$value = $time->format('Y-m-d');
}
else
{
$time->setTimezone(self::$tz_cache[$tzid]);
$value = $time->format('Ymd\THis');
}
return $value;
}
function startElement($_parser, $_tag, $_attributes)
{
// nothing to do
}
function endElement($_parser, $_tag)
{
#error_log("infolog: tag=$_tag data=".trim($this->sifData));
if (!empty($this->_currentSIFMapping[$_tag]))
{
$this->_extractedSIFData[$this->_currentSIFMapping[$_tag]] = trim($this->sifData);
}
unset($this->sifData);
}
function characterData($_parser, $_data)
{
$this->sifData .= $_data;
}
/**
* Convert SIF data into a eGW infolog entry
*
* @param string $sifData the SIF data
* @param string $_sifType type (note/task)
* @param int $_id=-1 the infolog id
* @return array infolog entry or false on error
*/
function siftoegw($sifData, $_sifType, $_id=-1)
{
if ($this->log)
{
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__."($_sifType, $_id)\n" .
array2string($sifData) . "\n", 3, $this->logfile);
}
$sysCharSet = $GLOBALS['egw']->translation->charset();
switch ($_sifType)
{
case 'note':
$this->_currentSIFMapping = $this->_sifNoteMapping;
break;
case 'task':
$this->_currentSIFMapping = $this->_sifTaskMapping;
break;
default:
// we don't know how to handle this
return false;
}
$this->xml_parser = xml_parser_create('UTF-8');
xml_set_object($this->xml_parser, $this);
xml_parser_set_option($this->xml_parser, XML_OPTION_CASE_FOLDING, false);
xml_set_element_handler($this->xml_parser, "startElement", "endElement");
xml_set_character_data_handler($this->xml_parser, "characterData");
$this->strXmlData = xml_parse($this->xml_parser, $sifData);
if (!$this->strXmlData)
{
error_log(sprintf("XML error: %s at line %d",
xml_error_string(xml_get_error_code($this->xml_parser)),
xml_get_current_line_number($this->xml_parser)));
return false;
}
if (!array($this->_extractedSIFData))
{
if ($this->log)
{
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__."()[PARSER FAILD]\n",
3, $this->logfile);
}
return false;
}
$infoData = array();
switch ($_sifType)
{
case 'task':
$infoData['info_type'] = 'task';
$infoData['info_status'] = 'not-started';
if (isset($GLOBALS['egw_info']['user']['preferences']['syncml']['minimum_uid_length']))
{
$minimum_uid_length = $GLOBALS['egw_info']['user']['preferences']['syncml']['minimum_uid_length'];
}
else
{
$minimum_uid_length = 8;
}
foreach ($this->_extractedSIFData as $key => $value)
{
$value = preg_replace('/<\!\[CDATA\[(.+)\]\]>/Usim', '$1', $value);
$value = $GLOBALS['egw']->translation->convert($value, 'utf-8', $sysCharSet);
#error_log("infolog key=$key => value=$value");
if (empty($value)) continue;
switch($key)
{
case 'info_access':
$infoData[$key] = ((int)$value > 0) ? 'private' : 'public';
break;
case 'info_datecompleted':
case 'info_enddate':
case 'info_startdate':
if (!empty($value))
{
$infoData[$key] = $this->vCalendar->_parseDateTime($value);
// somehow the client always deliver a timestamp about 3538 seconds, when no startdate set.
if ($infoData[$key] < 10000) unset($infoData[$key]);
}
break;
case 'info_cat':
if (!empty($value))
{
$categories = $this->find_or_add_categories(explode(';', $value), $_id);
$infoData['info_cat'] = $categories[0];
}
break;
case 'info_priority':
$infoData[$key] = (int)$value;
break;
case 'info_status':
switch ($value)
{
case '0':
$infoData[$key] = 'not-started';
break;
case '1':
$infoData[$key] = 'ongoing';
break;
case '2':
$infoData[$key] = 'done';
$infoData['info_percent'] = 100;
break;
case '3':
$infoData[$key] = 'waiting';
break;
case '4':
if ($this->productName == 'blackberry plug-in')
{
$infoData[$key] = 'deferred';
}
else
{
$infoData[$key] = 'cancelled';
}
break;
default:
$infoData[$key] = 'ongoing';
}
break;
case 'complete':
$infoData['info_status'] = 'done';
$infoData['info_percent'] = 100;
break;
case 'info_des':
// extract our UID and PARENT_UID information
if (preg_match('/\s*\[UID:(.+)?\]/Usm', $value, $matches))
{
if (strlen($matches[1]) >= $minimum_uid_length)
{
$infoData['info_uid'] = $matches[1];
}
//$value = str_replace($matches[0], '', $value);
}
if (preg_match('/\s*\[PARENT_UID:(.+)?\]/Usm', $value, $matches))
{
if (strlen($matches[1]) >= $minimum_uid_length)
{
$infoData['info_id_parent'] = $this->getParentID($matches[1]);
}
//$value = str_replace($matches[0], '', $value);
}
default:
$infoData[$key] = str_replace("\r\n", "\n", $value);
}
if ($this->log)
{
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__."()\n" .
"key=$key => value=" . $infoData[$key] . "\n", 3, $this->logfile);
}
}
if (empty($infoData['info_datecompleted']))
{
$infoData['info_datecompleted'] = 0;
}
break;
case 'note':
$infoData['info_type'] = 'note';
foreach ($this->_extractedSIFData as $key => $value)
{
$value = preg_replace('/<\!\[CDATA\[(.+)\]\]>/Usim', '$1', $value);
$value = $GLOBALS['egw']->translation->convert($value, 'utf-8', $sysCharSet);
#error_log("infolog client key=$key => value=" . $value);
switch ($key)
{
case 'info_startdate':
if (!empty($value))
{
$infoData[$key] = $this->vCalendar->_parseDateTime($value);
// somehow the client always deliver a timestamp about 3538 seconds, when no startdate set.
if ($infoData[$key] < 10000) $infoData[$key] = '';
}
else
{
$infoData[$key] = '';
}
break;
case 'info_cat':
if (!empty($value))
{
$categories = $this->find_or_add_categories(explode(';', $value), $_id);
$infoData['info_cat'] = $categories[0];
}
break;
default:
$infoData[$key] = str_replace("\r\n", "\n", $value);
}
if ($this->log)
{
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__."()\n" .
"key=$key => value=" . $infoData[$key] . "\n", 3, $this->logfile);
}
}
}
if ($this->log)
{
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__."()\n" .
array2string($infoData) . "\n", 3, $this->logfile);
}
return $infoData;
}
/**
* Search for SIF data a matching infolog entry
*
* @param string $sifData the SIF data
* @param string $_sifType type (note/task)
* @param int $contentID=null infolog_id (or null, if unkown)
* @param boolean $relax=false if true, a weaker match algorithm is used
* @return infolog_id of a matching entry or false, if nothing was found
*/
function searchSIF($_sifData, $_sifType, $contentID=null, $relax=false)
{
if (!($egwData = $this->siftoegw($_sifData, $_sifType, $contentID))) return array();
if ($contentID) $egwData['info_id'] = $contentID;
if ($_sifType == 'note') unset($egwData['info_startdate']);
return $this->findInfo($egwData, $relax, $this->tzid);
}
/**
* Add SIF data entry
*
* @param string $sifData the SIF data
* @param string $_sifType type (note/task)
* @param boolean $merge=false reserved for future use
* @return infolog_id of the new entry or false, for errors
*/
function addSIF($_sifData, $_id, $_sifType, $merge=false)
{
if ($this->tzid)
{
date_default_timezone_set($this->tzid);
}
$egwData = $this->siftoegw($_sifData, $_sifType, $_id);
if ($this->tzid)
{
date_default_timezone_set($GLOBALS['egw_info']['server']['server_timezone']);
}
if (!$egwData) return false;
if ($_id > 0) $egwData['info_id'] = $_id;
return $this->write($egwData, true, true, false);
}
/**
* Export an infolog entry as SIF data
*
* @param int $_id the infolog_id of the entry
* @param string $_sifType type (note/task)
* @return string SIF representation of the infolog entry
*/
function getSIF($_id, $_sifType)
{
$sysCharSet = $GLOBALS['egw']->translation->charset();
if (!($infoData = $this->read($_id, true, 'server'))) return false;
switch($_sifType)
{
case 'task':
if ($infoData['info_id_parent'])
{
$parent = $this->read($infoData['info_id_parent']);
$infoData['info_id_parent'] = $parent['info_uid'];
}
else
{
$infoData['info_id_parent'] = '';
}
if (!preg_match('/\[UID:.+\]/m', $infoData['info_des']))
{
$infoData['info_des'] .= "\r\n[UID:" . $infoData['info_uid'] . "]";
if ($infoData['info_id_parent'] != '')
{
$infoData['info_des'] .= "\r\n[PARENT_UID:" . $infoData['info_id_parent'] . "]";
}
}
$sifTask = self::xml_decl . "\n<task>" . self::SIF_decl;
foreach ($this->_sifTaskMapping as $sifField => $egwField)
{
if (empty($egwField)) continue;
$value = $GLOBALS['egw']->translation->convert($infoData[$egwField], $sysCharSet, 'utf-8');
switch ($sifField)
{
case 'Complete':
// is handled with DateCompleted
break;
case 'DateCompleted':
if ($infoData[info_status] != 'done')
{
$sifTask .= "<DateCompleted></DateCompleted><Complete>0</Complete>";
continue;
}
$sifTask .= "<Complete>1</Complete>";
case 'DueDate':
case 'StartDate':
$sifTask .= "<$sifField>";
if (!empty($value))
{
$sifTask .= $this->getDateTime($value, $this->tzid);
}
$sifTask .= "</$sifField>";
break;
case 'Importance':
if ($value > 3) $value = 3;
$sifTask .= "<$sifField>$value</$sifField>";
break;
case 'Sensitivity':
$value = ($value == 'private' ? '2' : '0');
$sifTask .= "<$sifField>$value</$sifField>";
break;
case 'Status':
switch ($value)
{
case 'cancelled':
case 'deferred':
$value = '4';
break;
case 'waiting':
case 'nonactive':
$value = '3';
break;
case 'done':
case 'archive':
case 'billed':
$value = '2';
break;
case 'not-started':
case 'template':
$value = '0';
break;
default: //ongoing
$value = 1;
break;
}
$sifTask .= "<$sifField>$value</$sifField>";
break;
case 'Categories':
if (!empty($value) && $value)
{
$value = implode('; ', $this->get_categories(array($value)));
$value = $GLOBALS['egw']->translation->convert($value, $sysCharSet, 'utf-8');
}
else
{
break;
}
default:
$value = @htmlspecialchars($value, ENT_NOQUOTES, 'utf-8');
$sifTask .= "<$sifField>$value</$sifField>";
break;
}
}
$sifTask .= '<ActualWork>0</ActualWork><IsRecurring>0</IsRecurring></task>';
return $sifTask;
case 'note':
$sifNote = self::xml_decl . "\n<note>" . self::SIF_decl;
foreach ($this->_sifNoteMapping as $sifField => $egwField)
{
if(empty($egwField)) continue;
$value = $GLOBALS['egw']->translation->convert($infoData[$egwField], $sysCharSet, 'utf-8');
switch ($sifField)
{
case 'Date':
$sifNote .= "<$sifField>";
if (!empty($value))
{
$sifNote .= $this->getDateTime($value, $this->tzid);
}
$sifNote .= "</$sifField>";
break;
case 'Categories':
if (!empty($value))
{
$value = implode('; ', $this->get_categories(array($value)));
$value = $GLOBALS['egw']->translation->convert($value, $sysCharSet, 'utf-8');
}
else
{
break;
}
default:
$value = @htmlspecialchars($value, ENT_QUOTES, 'utf-8');
$sifNote .= "<$sifField>$value</$sifField>";
break;
}
}
$sifNote .= '</note>';
return $sifNote;
}
return false;
}
/**
* Set the supported fields
*
* Currently we only store name and version, manucfacturer is always Funambol
*
* @param string $_productName
* @param string $_productSoftwareVersion
*/
function setSupportedFields($_productName='', $_productSoftwareVersion='')
{
$state = &$_SESSION['SyncML.state'];
$deviceInfo = $state->getClientDeviceInfo();
if (isset($deviceInfo) && is_array($deviceInfo))
{
if (isset($deviceInfo['uidExtension']) &&
$deviceInfo['uidExtension'])
{
$this->uidExtension = true;
}
if (isset($deviceInfo['tzid']) &&
$deviceInfo['tzid'])
{
switch ($deviceInfo['tzid'])
{
case -1:
$this->tzid = false;
break;
case -2:
$this->tzid = null;
break;
default:
$this->tzid = $deviceInfo['tzid'];
}
}
}
// store product name and version, to be able to use it elsewhere
if ($_productName)
{
$this->productName = strtolower($_productName);
if (preg_match('/^[^\d]*(\d+\.?\d*)[\.|\d]*$/', $_productSoftwareVersion, $matches))
{
$this->productSoftwareVersion = $matches[1];
}
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,411 +0,0 @@
<?php
/**
* The Browser_imode:: class extends the Browser API by providing
* specific information about Imode handsets.
*
* $Horde: framework/Browser/Browser/imode.php,v 1.9 2005/01/12 15:45:17 chuck Exp $
*
* Copyright 2000-2005 Mika Tuupola
* Copyright 2002-2005 Chuck Hagenbuch <chuck@horde.org>
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Chuck Hagenbuch <chuck@horde.org>
* @since Horde 3.0
* @package Horde_Browser
*/
class Browser_imode {
/**
* Device data. From http://www.nttdocomo.co.jp/i/tag/s5.html#5_1
*
* @var array $_data
*/
var $_data = array(
'D209i' => array(
'imagewidth' => 96, 'imageheight' => 90,
'textwidth' => 8, 'textheight' => 7,
'color' => 256,
'imageformats' => array('gif')
),
'F209i' => array(
'imagewidth' => 96, 'imageheight' => 91,
'textwidth' => 8, 'textheight' => 7,
'color' => 256,
'imageformats' => array('gif')
),
'N209i' => array(
'imagewidth' => 108, 'imageheight' => 82,
'textwidth' => 9, 'textheight' => 6,
'color' => 'grey',
'imageformats' => array('gif')
),
'P209i' => array(
'imagewidth' => 96, 'imageheight' => 87,
'textwidth' => 8, 'textheight' => 6,
'color' => 'grey',
'imageformats' => array('gif')
),
'P209is' => array(
'imagewidth' => 96, 'imageheight' => 87,
'textwidth' => 8, 'textheight' => 6,
'color' => 256,
'imageformats' => array('gif')
),
'R209i' => array(
'imagewidth' => 96, 'imageheight' => 72,
'textwidth' => 8, 'textheight' => 6,
'color' => 'grey',
'imageformats' => array('gif')
),
'ER209i' => array(
'imagewidth' => 120, 'imageheight' => 72,
'textwidth' => 10, 'textheight' => 6,
'color' => 'grey',
'imageformats' => array('gif')
),
'KO209i' => array(
'imagewidth' => 96, 'imageheight' => 96,
'textwidth' => 8, 'textheight' => 8,
'color' => 256,
'imageformats' => array('gif')
),
'D210i' => array(
'imagewidth' => 96, 'imageheight' => 91,
'textwidth' => 8, 'textheight' => 7,
'color' => 256,
'imageformats' => array('gif')
),
'F210i' => array(
'imagewidth' => 96, 'imageheight' => 113,
'textwidth' => 8, 'textheight' => 8,
'color' => 256,
'imageformats' => array('gif')
),
'N210i' => array(
'imagewidth' => 118, 'imageheight' => 113,
'textwidth' => 10, 'textheight' => 8,
'color' => 256,
'imageformats' => array('gif')
),
'P210i' => array(
'imagewidth' => 96, 'imageheight' => 91,
'textwidth' => 8, 'textheight' => 6,
'color' => 256,
'imageformats' => array('gif')
),
'KO210i' => array(
'imagewidth' => 96, 'imageheight' => 96,
'textwidth' => 8, 'textheight' => 8,
'color' => 256,
'imageformats' => array('gif')
),
'SO210i' => array(
'imagewidth' => 120, 'imageheight' => 113,
'textwidth' => 8, 'textheight' => 7,
'color' => 256,
'imageformats' => array('gif')
),
'D501i' => array(
'imagewidth' => 96, 'imageheight' => 72,
'textwidth' => 8, 'textheight' => 6,
'color' => 'black',
'imageformats' => array('gif')
),
'F501i' => array(
'imagewidth' => 112, 'imageheight' => 84,
'textwidth' => 8, 'textheight' => 6,
'color' => 'black',
'imageformats' => array('gif')
),
'N501i' => array(
'imagewidth' => 118, 'imageheight' => 128,
'textwidth' => 10, 'textheight' =>10,
'color' => 'black',
'imageformats' => array('gif')
),
'P501i' => array(
'imagewidth' => 96, 'imageheight' => 120,
'textwidth' => 8, 'textheight' => 8,
'color' => 'black',
'imageformats' => array('gif')
),
'D502i' => array(
'imagewidth' => 96, 'imageheight' => 90,
'textwidth' => 8, 'textheight' => 7,
'color' => 256,
'imageformats' => array('gif')
),
'F502i' => array(
'imagewidth' => 96, 'imageheight' => 91,
'textwidth' => 8, 'textheight' => 7,
'color' => 256,
'imageformats' => array('gif')
),
'F502it' => array(
'imagewidth' => 96, 'imageheight' => 91,
'textwidth' => 8, 'textheight' => 7,
'color' => 256,
'imageformats' => array('gif')
),
'N502i' => array(
'imagewidth' => 118, 'imageheight' => 128,
'textwidth' => 10, 'textheight' => 10,
'color' => 'grey',
'imageformats' => array('gif')
),
'N502it' => array(
'imagewidth' => 118, 'imageheight' => 128,
'textwidth' => 10, 'textheight' => 10,
'color' => 256,
'imageformats' => array('gif')
),
'P502i' => array(
'imagewidth' => 96, 'imageheighth' => 117,
'textwidth' => 8, 'textheight' => 8,
'color' => 'grey',
'imageformats' => array('gif')
),
'NM502i' => array(
'imagewidth' => 111, 'imageheight' => 77,
'textwidth' => 8, 'textheight' => 6,
'color' => 'black',
'imageformats' => array('gif')
),
'SO502i' => array(
'imagewidth' => 120, 'imageheight' => 120,
'textwidth' => 8, 'textheight' => 8,
'color' => 'grey',
'imageformats' => array('gif')
),
'SO502iwm' => array(
'imagewidth' => 120, 'imageheight' => 113,
'textwidth' => 8, 'textheight' => 7,
'color' => 256,
'imageformats' => array('gif')
),
'F503i' => array(
'imagewidth' => 120, 'imageheight' => 130,
'textwidth' => 10, 'textheight' => 10,
'color' => 256,
'imageformats' => array('gif')
),
'F503iS' => array(
'imagewidth' => 120, 'imageheight' => 130,
'textwidth' => 12, 'textheight' => 12,
'color' => 4096,
'imageformats' => array('gif')
),
'P503i' => array(
'imagewidth' => 120, 'imageheight' => 130,
'textwidth' => 12, 'textheight' => 10,
'color' => 256,
'imageformats' => array('gif')
),
'P503iS' => array(
'imagewidth' => 120, 'imageheight' => 130,
'textwidth' => 12, 'textheight' => 10,
'color' => 256,
'imageformats' => array('gif')
),
'SO503i' => array(
'imagewidth' => 120, 'imageheight' => 113,
'textwidth' => 8.5, 'textheight' => 7,
'color' => 65536,
'imageformats' => array('gif')
),
'D503i' => array(
'imagewidth' => 132, 'imageheight' => 126,
'textwidth' => 8, 'textheight' => 7,
'color' => 4096,
'imageformats' => array('gif')
),
'N503i' => array(
'imagewidth' => 118, 'imageheight' => 128,
'textwidth' => 10, 'textheight' => 10,
'color' => 4096,
'imageformats' => array('gif', 'jpg')
),
'N503iS' => array(
'imagewidth' => 118, 'imageheight' => 128,
'textwidth' => 10, 'textheight' => 10,
'color' => 4096,
'imageformats' => array('gif', 'jpg')
),
'N691i' => array(
'imagewidth' => 96, 'imageheight' => 72,
'textwidth' => 8, 'textheight' => 6,
'color' => 'grey',
'imageformats' => array('gif')
),
'SH821i' => array(
'imagewidth' => 96, 'imageheight' => 78,
'textwidth' => 8, 'textheight' => 6,
'color' => 256,
'imageformats' => array('gif')
),
'N821i' => array(
'imagewidth' => 118, 'imageheight' => 128,
'textwidth' => 10, 'textheight' => 10,
'color' => 'grey',
'imageformats' => array('gif')
),
'P821i' => array(
'imagewidth' => 118, 'imageheight' => 128,
'textwidth' => 10, 'textheight' => 10,
'color' => 'grey',
'imageformats' => array('gif')
),
'safe' => array(
'imagewidth' => 94, 'imageheight' => 72,
'textwidth' => 8, 'textheight' => 6,
'color' => 'black',
'imageformats' => array('gif')
)
);
var $_manufacturerlist = array(
'D' => 'Mitsubishi',
'P' => 'Panasonic (Matsushita)',
'NM' => 'Nokia',
'SO' => 'Sony',
'F' => 'Fujitsu',
'N' => 'Nec',
'SH' => 'Sharp',
'ER' => 'Ericsson',
'R' => 'Japan Radio',
'KO' => 'Kokusai (Hitachi)'
);
var $_extra = array(
't' => 'Transport layer',
'e' => 'English language',
's' => 'Second version'
);
var $_user_agent;
var $_model;
var $_manufacturer;
var $_httpversion;
var $_cache = 5;
/**
* Does not handle bogus user_agents or most of the other error
* situation properly yet.
*
* Example usage:
* $ua = new Browser_imode($_SERVEr['HTTP_USER_AGENT']);
*
* @param string $input The user agent to match.
*/
function Browser_imode($input)
{
$_error = 0;
$temp = explode('/', $input);
$this->_user_agent = $input;
$this->_httpversion = $temp[1];
$this->_model = $temp[2];
if ($temp[3]) {
$this->_cache = substr($temp[3], 1);
}
preg_match('/(^[a-zA-Z]+)([0-9]+i)(.*)\/?(.*)/', $this->_model, $matches);
// @TODO: Fix situation of unknown manufacturer. Implement
// extrainfo properly.
$this->_manufacturer = $this->_manufacturerlist[$matches[1]];
$this->_extra = $matches[3];
if (!($this->_data[$this->_model])) {
$_error = PEAR::raiseError('Unknown User Agent');
}
}
/**
* Example usage:
* $imagedim = $ua->getImageDimensions();
* $imagewidth = $imagedim[0];
* $imageheight = $imagedim[1];
*
* @return array The maximum imagewidth and imageheight that
* fit on the handset screen without scrolling.
*/
function getImageDimensions()
{
$data = $this->_data[$this->_model];
return array($data['imagewidth'], $data['imageheight']);
}
/**
* Example usage:
* $textdim = $ua->getTextDimensions();
* $textwidth = $textdim[0];
* $textheight = $textdim[1];
*
* @return array The Maximum textwidth and textheight that
* fit on the handset screen without scrolling.
*/
function getTextDimensions()
{
return array($this->_data[$this->_model]['textwidth'],
$this->_data[$this->_model]['textheight']);
}
/**
* @return integer The amount of handset cache in kilobytes.
*/
function getCache()
{
return (int)$this->_cache;
}
function getManufacturer()
{
return $this->_manufacturer;
}
function getExtra()
{
return $this->_extra;
}
function getImageFormats()
{
return $this->_data[$this->_model]['imageformats'];
}
/**
* @return integer Which color model the handset supports.
* Values have the following meaning:
* 0 -> black and white
* 1 -> 4 tone greyscale
* 2 -> 256 color
*/
function getColor()
{
return $this->_data[$this->_model]['color'];
}
function getHTTPVersion()
{
return $this->_httpversion;
}
function isColor()
{
return $this->_data[$this->_model]['color'] == 256;
}
function isGreyScale()
{
return $this->_data[$this->_model]['color'] == 'grey';
}
function isBlackAndWhite()
{
return $this->_data[$this->_model]['color'] == 'black';
}
}

View File

@ -1,769 +0,0 @@
<?php
define('HORDE_DATE_SUNDAY', 0);
define('HORDE_DATE_MONDAY', 1);
define('HORDE_DATE_TUESDAY', 2);
define('HORDE_DATE_WEDNESDAY', 3);
define('HORDE_DATE_THURSDAY', 4);
define('HORDE_DATE_FRIDAY', 5);
define('HORDE_DATE_SATURDAY', 6);
define('HORDE_DATE_MASK_SUNDAY', 1);
define('HORDE_DATE_MASK_MONDAY', 2);
define('HORDE_DATE_MASK_TUESDAY', 4);
define('HORDE_DATE_MASK_WEDNESDAY', 8);
define('HORDE_DATE_MASK_THURSDAY', 16);
define('HORDE_DATE_MASK_FRIDAY', 32);
define('HORDE_DATE_MASK_SATURDAY', 64);
define('HORDE_DATE_MASK_WEEKDAYS', 62);
define('HORDE_DATE_MASK_WEEKEND', 65);
define('HORDE_DATE_MASK_ALLDAYS', 127);
define('HORDE_DATE_MASK_SECOND', 1);
define('HORDE_DATE_MASK_MINUTE', 2);
define('HORDE_DATE_MASK_HOUR', 4);
define('HORDE_DATE_MASK_DAY', 8);
define('HORDE_DATE_MASK_MONTH', 16);
define('HORDE_DATE_MASK_YEAR', 32);
define('HORDE_DATE_MASK_ALLPARTS', 63);
/**
* Horde Date wrapper/logic class, including some calculation
* functions.
*
* $Horde: framework/Date/Date.php,v 1.8.10.18 2008/09/17 08:46:04 jan Exp $
*
* @package Horde_Date
*/
class Horde_Date {
/**
* Year
*
* @var integer
*/
var $year;
/**
* Month
*
* @var integer
*/
var $month;
/**
* Day
*
* @var integer
*/
var $mday;
/**
* Hour
*
* @var integer
*/
var $hour = 0;
/**
* Minute
*
* @var integer
*/
var $min = 0;
/**
* Second
*
* @var integer
*/
var $sec = 0;
/**
* Internally supported strftime() specifiers.
*
* @var string
*/
var $_supportedSpecs = '%CdDeHImMnRStTyY';
/**
* Build a new date object. If $date contains date parts, use them to
* initialize the object.
*
* Recognized formats:
* - arrays with keys 'year', 'month', 'mday', 'day' (since Horde 3.2),
* 'hour', 'min', 'minute' (since Horde 3.2), 'sec'
* - objects with properties 'year', 'month', 'mday', 'hour', 'min', 'sec'
* - yyyy-mm-dd hh:mm:ss (since Horde 3.1)
* - yyyymmddhhmmss (since Horde 3.1)
* - yyyymmddThhmmssZ (since Horde 3.1.4)
* - unix timestamps
*/
function Horde_Date($date = null)
{
if (function_exists('nl_langinfo')) {
$this->_supportedSpecs .= 'bBpxX';
}
if (is_array($date) || is_object($date)) {
foreach ($date as $key => $val) {
if (in_array($key, array('year', 'month', 'mday', 'hour', 'min', 'sec'))) {
$this->$key = (int)$val;
}
}
// If $date['day'] is present and numeric we may have been passed
// a Horde_Form_datetime array.
if (is_array($date) && isset($date['day']) &&
is_numeric($date['day'])) {
$this->mday = (int)$date['day'];
}
// 'minute' key also from Horde_Form_datetime
if (is_array($date) && isset($date['minute'])) {
$this->min = $date['minute'];
}
} elseif (!is_null($date)) {
// Match YYYY-MM-DD HH:MM:SS, YYYYMMDDHHMMSS and YYYYMMDD'T'HHMMSS'Z'.
if (preg_match('/(\d{4})-?(\d{2})-?(\d{2})T? ?(\d{2}):?(\d{2}):?(\d{2})Z?/', $date, $parts)) {
$this->year = (int)$parts[1];
$this->month = (int)$parts[2];
$this->mday = (int)$parts[3];
$this->hour = (int)$parts[4];
$this->min = (int)$parts[5];
$this->sec = (int)$parts[6];
} else {
// Try as a timestamp.
$parts = @getdate($date);
if ($parts) {
$this->year = $parts['year'];
$this->month = $parts['mon'];
$this->mday = $parts['mday'];
$this->hour = $parts['hours'];
$this->min = $parts['minutes'];
$this->sec = $parts['seconds'];
}
}
}
}
/**
* @static
*/
function isLeapYear($year)
{
if (strlen($year) != 4 || preg_match('/\D/', $year)) {
return false;
}
return (($year % 4 == 0 && $year % 100 != 0) || $year % 400 == 0);
}
/**
* Returns the day of the year (1-366) that corresponds to the
* first day of the given week.
*
* TODO: with PHP 5.1+, see http://derickrethans.nl/calculating_start_and_end_dates_of_a_week.php
*
* @param integer $week The week of the year to find the first day of.
* @param integer $year The year to calculate for.
*
* @return integer The day of the year of the first day of the given week.
*/
function firstDayOfWeek($week, $year)
{
$jan1 = new Horde_Date(array('year' => $year, 'month' => 1, 'mday' => 1));
$start = $jan1->dayOfWeek();
if ($start > HORDE_DATE_THURSDAY) {
$start -= 7;
}
return (($week * 7) - (7 + $start)) + 1;
}
/**
* @static
*/
function daysInMonth($month, $year)
{
if ($month == 2) {
if (Horde_Date::isLeapYear($year)) {
return 29;
} else {
return 28;
}
} elseif ($month == 4 || $month == 6 || $month == 9 || $month == 11) {
return 30;
} else {
return 31;
}
}
/**
* Return the day of the week (0 = Sunday, 6 = Saturday) of this
* object's date.
*
* @return integer The day of the week.
*/
function dayOfWeek()
{
if ($this->month > 2) {
$month = $this->month - 2;
$year = $this->year;
} else {
$month = $this->month + 10;
$year = $this->year - 1;
}
$day = (floor((13 * $month - 1) / 5) +
$this->mday + ($year % 100) +
floor(($year % 100) / 4) +
floor(($year / 100) / 4) - 2 *
floor($year / 100) + 77);
return (int)($day - 7 * floor($day / 7));
}
/**
* Returns the day number of the year (1 to 365/366).
*
* @return integer The day of the year.
*/
function dayOfYear()
{
$monthTotals = array(0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334);
$dayOfYear = $this->mday + $monthTotals[$this->month - 1];
if (Horde_Date::isLeapYear($this->year) && $this->month > 2) {
++$dayOfYear;
}
return $dayOfYear;
}
/**
* Returns the week of the month.
*
* @since Horde 3.2
*
* @return integer The week number.
*/
function weekOfMonth()
{
return ceil($this->mday / 7);
}
/**
* Returns the week of the year, first Monday is first day of first week.
*
* @return integer The week number.
*/
function weekOfYear()
{
return $this->format('W');
}
/**
* Return the number of weeks in the given year (52 or 53).
*
* @static
*
* @param integer $year The year to count the number of weeks in.
*
* @return integer $numWeeks The number of weeks in $year.
*/
function weeksInYear($year)
{
// Find the last Thursday of the year.
$day = 31;
$date = new Horde_Date(array('year' => $year, 'month' => 12, 'mday' => $day, 'hour' => 0, 'min' => 0, 'sec' => 0));
while ($date->dayOfWeek() != HORDE_DATE_THURSDAY) {
--$date->mday;
}
return $date->weekOfYear();
}
/**
* Set the date of this object to the $nth weekday of $weekday.
*
* @param integer $weekday The day of the week (0 = Sunday, etc).
* @param integer $nth The $nth $weekday to set to (defaults to 1).
*/
function setNthWeekday($weekday, $nth = 1)
{
if ($weekday < HORDE_DATE_SUNDAY || $weekday > HORDE_DATE_SATURDAY) {
return false;
}
$this->mday = 1;
$first = $this->dayOfWeek();
if ($weekday < $first) {
$this->mday = 8 + $weekday - $first;
} else {
$this->mday = $weekday - $first + 1;
}
$this->mday += 7 * $nth - 7;
$this->correct();
return true;
}
function dump($prefix = '')
{
echo ($prefix ? $prefix . ': ' : '') . $this->year . '-' . $this->month . '-' . $this->mday . "<br />\n";
}
/**
* Is the date currently represented by this object a valid date?
*
* @return boolean Validity, counting leap years, etc.
*/
function isValid()
{
if ($this->year < 0 || $this->year > 9999) {
return false;
}
return checkdate($this->month, $this->mday, $this->year);
}
/**
* Correct any over- or underflows in any of the date's members.
*
* @param integer $mask We may not want to correct some overflows.
*/
function correct($mask = HORDE_DATE_MASK_ALLPARTS)
{
if ($mask & HORDE_DATE_MASK_SECOND) {
while ($this->sec < 0) {
--$this->min;
$this->sec += 60;
}
while ($this->sec > 59) {
++$this->min;
$this->sec -= 60;
}
}
if ($mask & HORDE_DATE_MASK_MINUTE) {
while ($this->min < 0) {
--$this->hour;
$this->min += 60;
}
while ($this->min > 59) {
++$this->hour;
$this->min -= 60;
}
}
if ($mask & HORDE_DATE_MASK_HOUR) {
while ($this->hour < 0) {
--$this->mday;
$this->hour += 24;
}
while ($this->hour > 23) {
++$this->mday;
$this->hour -= 24;
}
}
if ($mask & HORDE_DATE_MASK_MONTH) {
while ($this->month > 12) {
++$this->year;
$this->month -= 12;
}
while ($this->month < 1) {
--$this->year;
$this->month += 12;
}
}
if ($mask & HORDE_DATE_MASK_DAY) {
while ($this->mday > Horde_Date::daysInMonth($this->month, $this->year)) {
$this->mday -= Horde_Date::daysInMonth($this->month, $this->year);
++$this->month;
$this->correct(HORDE_DATE_MASK_MONTH);
}
while ($this->mday < 1) {
--$this->month;
$this->correct(HORDE_DATE_MASK_MONTH);
$this->mday += Horde_Date::daysInMonth($this->month, $this->year);
}
}
}
/**
* Compare this date to another date object to see which one is
* greater (later). Assumes that the dates are in the same
* timezone.
*
* @param mixed $date The date to compare to.
*
* @return integer == 0 if the dates are equal
* >= 1 if this date is greater (later)
* <= -1 if the other date is greater (later)
*/
function compareDate($date)
{
if (!is_a($date, 'Horde_Date')) {
$date = new Horde_Date($date);
}
if ($this->year != $date->year) {
return $this->year - $date->year;
}
if ($this->month != $date->month) {
return $this->month - $date->month;
}
return $this->mday - $date->mday;
}
/**
* Compare this to another date object by time, to see which one
* is greater (later). Assumes that the dates are in the same
* timezone.
*
* @param mixed $date The date to compare to.
*
* @return integer == 0 if the dates are equal
* >= 1 if this date is greater (later)
* <= -1 if the other date is greater (later)
*/
function compareTime($date)
{
if (!is_a($date, 'Horde_Date')) {
$date = new Horde_Date($date);
}
if ($this->hour != $date->hour) {
return $this->hour - $date->hour;
}
if ($this->min != $date->min) {
return $this->min - $date->min;
}
return $this->sec - $date->sec;
}
/**
* Compare this to another date object, including times, to see
* which one is greater (later). Assumes that the dates are in the
* same timezone.
*
* @param mixed $date The date to compare to.
*
* @return integer == 0 if the dates are equal
* >= 1 if this date is greater (later)
* <= -1 if the other date is greater (later)
*/
function compareDateTime($date)
{
if (!is_a($date, 'Horde_Date')) {
$date = new Horde_Date($date);
}
if ($diff = $this->compareDate($date)) {
return $diff;
}
return $this->compareTime($date);
}
/**
* Get the time offset for local time zone.
*
* @param boolean $colon Place a colon between hours and minutes?
*
* @return string Timezone offset as a string in the format +HH:MM.
*/
function tzOffset($colon = true)
{
$secs = $this->format('Z');
if ($secs < 0) {
$sign = '-';
$secs = -$secs;
} else {
$sign = '+';
}
$colon = $colon ? ':' : '';
$mins = intval(($secs + 30) / 60);
return sprintf('%s%02d%s%02d',
$sign, $mins / 60, $colon, $mins % 60);
}
/**
* Return the unix timestamp representation of this date.
*
* @return integer A unix timestamp.
*/
function timestamp()
{
if (class_exists('DateTime')) {
return $this->format('U');
} else {
return Horde_Date::_mktime($this->hour, $this->min, $this->sec, $this->month, $this->mday, $this->year);
}
}
/**
* Return the unix timestamp representation of this date, 12:00am.
*
* @return integer A unix timestamp.
*/
function datestamp()
{
if (class_exists('DateTime')) {
$dt = new DateTime();
$dt->setDate($this->year, $this->month, $this->mday);
$dt->setTime(0, 0, 0);
return $dt->format('U');
} else {
return Horde_Date::_mktime(0, 0, 0, $this->month, $this->mday, $this->year);
}
}
/**
* Format time using the specifiers available in date() or in the DateTime
* class' format() method.
*
* @since Horde 3.3
*
* @param string $format
*
* @return string Formatted time.
*/
function format($format)
{
if (class_exists('DateTime')) {
$dt = new DateTime();
$dt->setDate($this->year, $this->month, $this->mday);
$dt->setTime($this->hour, $this->min, $this->sec);
return $dt->format($format);
} else {
return date($format, $this->timestamp());
}
}
/**
* Format time in ISO-8601 format. Works correctly since Horde 3.2.
*
* @return string Date and time in ISO-8601 format.
*/
function iso8601DateTime()
{
return $this->rfc3339DateTime() . $this->tzOffset();
}
/**
* Format time in RFC 2822 format.
*
* @return string Date and time in RFC 2822 format.
*/
function rfc2822DateTime()
{
return $this->format('D, j M Y H:i:s') . ' ' . $this->tzOffset(false);
}
/**
* Format time in RFC 3339 format.
*
* @since Horde 3.1
*
* @return string Date and time in RFC 3339 format. The seconds part has
* been added with Horde 3.2.
*/
function rfc3339DateTime()
{
return $this->format('Y-m-d\TH:i:s');
}
/**
* Format time to standard 'ctime' format.
*
* @return string Date and time.
*/
function cTime()
{
return $this->format('D M j H:i:s Y');
}
/**
* Format date and time using strftime() format.
*
* @since Horde 3.1
*
* @return string strftime() formatted date and time.
*/
function strftime($format)
{
if (preg_match('/%[^' . $this->_supportedSpecs . ']/', $format)) {
return strftime($format, $this->timestamp());
} else {
return $this->_strftime($format);
}
}
/**
* Format date and time using a limited set of the strftime() format.
*
* @return string strftime() formatted date and time.
*/
function _strftime($format)
{
if (preg_match('/%[bBpxX]/', $format)) {
require_once 'Horde/NLS.php';
}
return preg_replace(
array('/%b/e',
'/%B/e',
'/%C/e',
'/%d/e',
'/%D/e',
'/%e/e',
'/%H/e',
'/%I/e',
'/%m/e',
'/%M/e',
'/%n/',
'/%p/e',
'/%R/e',
'/%S/e',
'/%t/',
'/%T/e',
'/%x/e',
'/%X/e',
'/%y/e',
'/%Y/',
'/%%/'),
array('$this->_strftime(NLS::getLangInfo(constant(\'ABMON_\' . (int)$this->month)))',
'$this->_strftime(NLS::getLangInfo(constant(\'MON_\' . (int)$this->month)))',
'(int)($this->year / 100)',
'sprintf(\'%02d\', $this->mday)',
'$this->_strftime(\'%m/%d/%y\')',
'sprintf(\'%2d\', $this->mday)',
'sprintf(\'%02d\', $this->hour)',
'sprintf(\'%02d\', $this->hour == 0 ? 12 : ($this->hour > 12 ? $this->hour - 12 : $this->hour))',
'sprintf(\'%02d\', $this->month)',
'sprintf(\'%02d\', $this->min)',
"\n",
'$this->_strftime(NLS::getLangInfo($this->hour < 12 ? AM_STR : PM_STR))',
'$this->_strftime(\'%H:%M\')',
'sprintf(\'%02d\', $this->sec)',
"\t",
'$this->_strftime(\'%H:%M:%S\')',
'$this->_strftime(NLS::getLangInfo(D_FMT))',
'$this->_strftime(NLS::getLangInfo(T_FMT))',
'substr(sprintf(\'%04d\', $this->year), -2)',
(int)$this->year,
'%'),
$format);
}
/**
* mktime() implementation that supports dates outside of 1970-2038,
* from http://phplens.com/phpeverywhere/adodb_date_library.
*
* @TODO remove in Horde 4
*
* This does NOT work with pre-1970 daylight saving times.
*
* @static
*/
function _mktime($hr, $min, $sec, $mon = false, $day = false,
$year = false, $is_dst = false, $is_gmt = false)
{
if ($mon === false) {
return $is_gmt
? @gmmktime($hr, $min, $sec)
: @mktime($hr, $min, $sec);
}
if ($year > 1901 && $year < 2038 &&
($year >= 1970 || version_compare(PHP_VERSION, '5.0.0', '>='))) {
return $is_gmt
? @gmmktime($hr, $min, $sec, $mon, $day, $year)
: @mktime($hr, $min, $sec, $mon, $day, $year);
}
$gmt_different = $is_gmt
? 0
: (mktime(0, 0, 0, 1, 2, 1970, 0) - gmmktime(0, 0, 0, 1, 2, 1970, 0));
$mon = intval($mon);
$day = intval($day);
$year = intval($year);
if ($mon > 12) {
$y = floor($mon / 12);
$year += $y;
$mon -= $y * 12;
} elseif ($mon < 1) {
$y = ceil((1 - $mon) / 12);
$year -= $y;
$mon += $y * 12;
}
$_day_power = 86400;
$_hour_power = 3600;
$_min_power = 60;
$_month_table_normal = array('', 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
$_month_table_leaf = array('', 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
$_total_date = 0;
if ($year >= 1970) {
for ($a = 1970; $a <= $year; $a++) {
$leaf = Horde_Date::isLeapYear($a);
if ($leaf == true) {
$loop_table = $_month_table_leaf;
$_add_date = 366;
} else {
$loop_table = $_month_table_normal;
$_add_date = 365;
}
if ($a < $year) {
$_total_date += $_add_date;
} else {
for ($b = 1; $b < $mon; $b++) {
$_total_date += $loop_table[$b];
}
}
}
return ($_total_date + $day - 1) * $_day_power + $hr * $_hour_power + $min * $_min_power + $sec + $gmt_different;
}
for ($a = 1969 ; $a >= $year; $a--) {
$leaf = Horde_Date::isLeapYear($a);
if ($leaf == true) {
$loop_table = $_month_table_leaf;
$_add_date = 366;
} else {
$loop_table = $_month_table_normal;
$_add_date = 365;
}
if ($a > $year) {
$_total_date += $_add_date;
} else {
for ($b = 12; $b > $mon; $b--) {
$_total_date += $loop_table[$b];
}
}
}
$_total_date += $loop_table[$mon] - $day;
$_day_time = $hr * $_hour_power + $min * $_min_power + $sec;
$_day_time = $_day_power - $_day_time;
$ret = -($_total_date * $_day_power + $_day_time - $gmt_different);
if ($ret < -12220185600) {
// If earlier than 5 Oct 1582 - gregorian correction.
return $ret + 10 * 86400;
} elseif ($ret < -12219321600) {
// If in limbo, reset to 15 Oct 1582.
return -12219321600;
} else {
return $ret;
}
}
}

View File

@ -1,523 +0,0 @@
<?php
/**
* The NLS:: class provides Native Language Support. This includes common
* methods for handling language detection and selection, timezones, and
* hostname->country lookups.
*
* $Horde: framework/NLS/NLS.php,v 1.86 2005/02/28 15:45:56 jan Exp $
*
* Copyright 1999-2005 Jon Parise <jon@horde.org>
* Copyright 1999-2005 Chuck Hagenbuch <chuck@horde.org>
* Copyright 2002-2005 Jan Schneider <jan@horde.org>
* Copyright 2003-2005 Michael Slusarz <slusarz@bigworm.colorado.edu>
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Jon Parise <jon@horde.org>
* @author Chuck Hagenbuch <chuck@horde.org>
* @author Jan Schneider <jan@horde.org>
* @author Michael Slusarz <slusarz@bigworm.colorado.edu>
* @version $Revision$
* @since Horde 3.0
* @package Horde_NLS
*/
class NLS {
/**
* Selects the most preferred language for the current client session.
*
* @access public
*
* @return string The selected language abbreviation.
*/
function select()
{
global $nls, $prefs;
$lang = Util::getFormData('new_lang');
/* First, check if language pref is locked and, if so, set it to its
value */
if (isset($prefs) && $prefs->isLocked('language')) {
$language = $prefs->getValue('language');
/* Check if the user selected a language from the login screen */
} elseif (!empty($lang)) {
$language = $lang;
/* Check if we have a language set in a cookie */
} elseif (isset($_SESSION['horde_language'])) {
$language = $_SESSION['horde_language'];
/* Use site-wide default, if one is defined */
} elseif (!empty($nls['defaults']['language'])) {
$language = $nls['defaults']['language'];
/* Try browser-accepted languages. */
} elseif (!empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
/* The browser supplies a list, so return the first valid one. */
$browser_langs = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
foreach ($browser_langs as $lang) {
/* Strip quality value for language */
if (($pos = strpos($lang, ';')) !== false) {
$lang = substr($lang, 0, $pos);
}
$lang = NLS::_map(trim($lang));
if (NLS::isValid($lang)) {
$language = $lang;
break;
}
/* In case no full match, save best guess based on prefix */
if (!isset($partial_lang) &&
NLS::isValid(NLS::_map(substr($lang, 0, 2)))) {
$partial_lang = NLS::_map(substr($lang, 0, 2));
}
}
}
if (!isset($language)) {
if (isset($partial_lang)) {
$language = $partial_lang;
} else {
/* No dice auto-detecting, default to US English. */
$language = 'en_US';
}
}
return basename($language);
}
/**
* Sets the language.
*
* @access public
*
* @param optional string $lang The language abbriviation.
*/
function setLang($lang = null)
{
include_once HORDE_BASE . '/config/nls.php';
if (empty($lang) || !NLS::isValid($lang)) {
$lang = NLS::select();
}
if (isset($GLOBALS['language']) && $GLOBALS['language'] == $lang) {
return;
}
$GLOBALS['language'] = $lang;
/* First try language with the current charset. */
$lang_charset = $lang . '.' . NLS::getCharset();
if ($lang_charset != setlocale(LC_ALL, $lang_charset)) {
/* Next try language with its default charset. */
global $nls;
$charset = !empty($nls['charsets'][$lang]) ? $nls['charsets'][$lang] : $nls['defaults']['charset'];
$lang_charset = $lang . '.' . $charset;
NLS::_cachedCharset(0, $charset);
if ($lang_charset != setlocale(LC_ALL, $lang_charset)) {
/* At last try language solely. */
$lang_charset = $lang;
setlocale(LC_ALL, $lang_charset);
}
}
@putenv('LANG=' . $lang_charset);
@putenv('LANGUAGE=' . $lang_charset);
}
/**
* Sets the gettext domain.
*
* @access public
*
* @param string $app The application name.
* @param string $directory The directory where the application's
* LC_MESSAGES directory resides.
* @param string $charset The charset.
*/
function setTextdomain($app, $directory, $charset)
{
bindtextdomain($app, $directory);
textdomain($app);
/* The existence of this function depends on the platform. */
if (function_exists('bind_textdomain_codeset')) {
NLS::_cachedCharset(0, bind_textdomain_codeset($app, $charset));
}
if (!headers_sent()) {
header('Content-Type: text/html; charset=' . $charset);
}
}
/**
* Determines whether the supplied language is valid.
*
* @access public
*
* @param string $language The abbreviated name of the language.
*
* @return boolean True if the language is valid, false if it's not
* valid or unknown.
*/
function isValid($language)
{
return !empty($GLOBALS['nls']['languages'][$language]);
}
/**
* Maps languages with common two-letter codes (such as nl) to the
* full gettext code (in this case, nl_NL). Returns the language
* unmodified if it isn't an alias.
*
* @access private
*
* @param string $language The language code to map.
*
* @return string The mapped language code.
*/
function _map($language)
{
require_once 'Horde/String.php';
$aliases = &$GLOBALS['nls']['aliases'];
// Translate the $language to get broader matches.
// (eg. de-DE should match de_DE)
$trans_lang = str_replace('-', '_', $language);
$lang_parts = explode('_', $trans_lang);
$trans_lang = String::lower($lang_parts[0]);
if (isset($lang_parts[1])) {
$trans_lang .= '_' . String::upper($lang_parts[1]);
}
// See if we get a match for this
if (!empty($aliases[$trans_lang])) {
return $aliases[$trans_lang];
}
// If we get that far down, the language cannot be found.
// Return $trans_lang.
return $trans_lang;
}
/**
* Returns the charset for the current language.
*
* @access public
*
* @param boolean $original If true returns the original charset of the
* translation, the actually used one otherwise.
*
* @return string The character set that should be used with the current
* locale settings.
*/
function getCharset($original = false)
{
global $language, $nls;
/* Get cached results. */
$cacheKey = intval($original);
$charset = NLS::_cachedCharset($cacheKey);
if (!is_null($charset)) {
return $charset;
}
if ($original) {
$charset = empty($nls['charsets'][$language]) ? $nls['defaults']['charset'] : $nls['charsets'][$language];
} else {
require_once 'Horde/Browser.php';
$browser = &Browser::singleton();
if ($browser->hasFeature('utf') &&
(Util::extensionExists('iconv') ||
Util::extensionExists('mbstring'))) {
$charset = 'UTF-8';
}
}
if (is_null($charset)) {
$charset = NLS::getExternalCharset();
}
NLS::_cachedCharset($cacheKey, $charset);
return $charset;
}
/**
* Returns the current charset of the environment
*
* @access public
*
* @return string The character set that should be used with the current
* locale settings.
*/
function getExternalCharset()
{
global $language, $nls;
/* Get cached results. */
$charset = NLS::_cachedCharset(2);
if (!is_null($charset)) {
return $charset;
}
$lang_charset = setlocale(LC_ALL, 0);
if (strpos($lang_charset, ';') === false &&
strpos($lang_charset, '/') === false) {
$lang_charset = explode('.', $lang_charset);
if ((count($lang_charset) == 2) && !empty($lang_charset[1])) {
NLS::_cachedCharset(2, $lang_charset[1]);
return $lang_charset[1];
}
}
return (!empty($nls['charsets'][$language])) ? $nls['charsets'][$language] : $nls['defaults']['charset'];
}
/**
* Sets or returns the charset used under certain conditions.
*
* @access private
*
* @param integer $index The ID of a cache slot. 0 for the UI charset, 1
* for the translation charset and 2 for the
* external charset.
* @param string $charset If specified, this charset will be stored in the
* given cache slot. Otherwise the content of the
* specified cache slot will be returned.
*/
function _cachedCharset($index, $charset = null)
{
static $cache;
if (!isset($cache)) {
$cache = array();
}
if ($charset == null) {
return isset($cache[$index]) ? $cache[$index] : null;
} else {
$cache[$index] = $charset;
}
}
/**
* Returns the charset to use for outgoing emails.
*
* @return string The preferred charset for outgoing mails based on
* the user's preferences and the current language.
*/
function getEmailCharset()
{
global $prefs, $language, $nls;
$charset = $prefs->getValue('sending_charset');
if (!empty($charset)) {
return $charset;
}
return isset($nls['emails'][$language]) ? $nls['emails'][$language] :
(isset($nls['charsets'][$language]) ? $nls['charsets'][$language] : $nls['defaults']['charset']);
}
/**
* Check to see if character set is valid for htmlspecialchars() calls.
*
* @access public
*
* @param string $charset The character set to check.
*
* @return boolean Is charset valid for the current system?
*/
function checkCharset($charset)
{
static $check;
if (is_null($charset) || empty($charset)) {
return false;
}
if (isset($check[$charset])) {
return $check[$charset];
} elseif (!isset($check)) {
$check = array();
}
$valid = true;
ini_set('track_errors', 1);
@htmlspecialchars('', ENT_COMPAT, $charset);
if (isset($php_errormsg)) {
$valid = false;
}
ini_restore('track_errors');
$check[$charset] = $valid;
return $valid;
}
/**
* Sets the current timezone, if available.
*
* @access public
*/
function setTimeZone()
{
global $prefs;
$tz = $prefs->getValue('timezone');
if (!empty($tz)) {
@putenv('TZ=' . $tz);
}
}
/**
* Get the locale info returned by localeconv(), but cache it, to
* avoid repeated calls.
*
* @access public
*
* @return array The results of localeconv().
*/
function getLocaleInfo()
{
static $lc_info;
if (!isset($lc_info)) {
$lc_info = localeconv();
}
return $lc_info;
}
/**
* Get the language info returned by nl_langinfo(), but cache it, to
* avoid repeated calls.
*
* @access public
* @since Horde 3.1
*
* @param const $item The langinfo item to return.
*
* @return array The results of nl_langinfo().
*/
function getLangInfo($item)
{
static $nl_info = array();
if (!isset($nl_info[$item])) {
$nl_info[$item] = nl_langinfo($item);
}
return $nl_info[$item];
}
/**
* Get country information from a hostname or IP address.
*
* @access public
*
* @param string $host The hostname or IP address.
*
* @return mixed On success, return an array with the following entries:
* 'code' => Country Code
* 'name' => Country Name
* On failure, return false.
*/
function getCountryByHost($host)
{
global $conf;
/* List of generic domains that we know is not in the country TLD
list. See: http://www.iana.org/gtld/gtld.htm */
$generic = array(
'aero', 'biz', 'com', 'coop', 'edu', 'gov', 'info', 'int', 'mil',
'museum', 'name', 'net', 'org', 'pro'
);
$checkHost = $host;
if (preg_match('/^\d+\.\d+\.\d+\.\d+$/', $host)) {
$checkHost = @gethostbyaddr($host);
}
/* Get the TLD of the hostname. */
$pos = strrpos($checkHost, '.');
if ($pos === false) {
return false;
}
$domain = String::lower(substr($checkHost, $pos + 1));
/* Try lookup via TLD first. */
if (!in_array($domain, $generic)) {
require 'Horde/NLS/tld.php';
if (isset($tld[$domain])) {
return array('code' => $domain, 'name' => $tld[$domain]);
}
}
/* Try GeoIP lookup next. */
if (!empty($conf['geoip']['datafile'])) {
require_once 'Horde/NLS/GeoIP.php';
$geoip = &NLS_GeoIP::singleton($conf['geoip']['datafile']);
$id = $geoip->countryIdByName($checkHost);
if (!empty($id)) {
return array('code' => String::lower($GLOBALS['GEOIP_COUNTRY_CODES'][$id]), 'name' => $GLOBALS['GEOIP_COUNTRY_NAMES'][$id]);
}
}
return false;
}
/**
* Returns a Horde image link to the country flag.
*
* @access public
*
* @param string $host The hostname or IP address.
*
* @return string The image URL, or the empty string on error.
*/
function generateFlagImageByHost($host)
{
global $registry;
$data = NLS::getCountryByHost($host);
if ($data !== false) {
$img = $data['code'] . '.png';
if (file_exists($registry->get('themesfs', 'horde') . '/graphics/flags/' . $img)) {
return Horde::img($img, $data['name'], '', $registry->getImageDir('horde') . '/flags');
} else {
return '[' . $data['name'] . ']';
}
}
return '';
}
/**
* Returns either a specific or all ISO-3166 country names.
*
* @access public
*
* @param optional string $code The ISO 3166 country code.
*
* @return mixed If a country code has been requested will return the
* corresponding country name. If empty will return an
* array of all the country codes and their names.
*/
function &getCountryISO($code = '')
{
static $countries = array();
if (empty($countries)) {
require_once 'Horde/NLS/countries.php';
}
if (empty($code)) {
return $countries;
} elseif (isset($countries[$code])) {
return $countries[$code];
}
return false;
}
}

View File

@ -1,252 +0,0 @@
<?php
/**
* The Horde_RPC:: class provides a set of server and client methods for
* RPC communication.
*
* TODO:
* - Introspection documentation and method signatures.
*
* EXAMPLE:
* <code>
* $response = Horde_RPC::request('xmlrpc',
* 'http://localhost:80/horde/rpc.php'
* 'contacts.search',
* array(array('jan'), array('localsql'),
* array('name', 'email')),
* array('user' => Auth::getAuth(),
* 'pass' => Auth::getCredential('password')));
* </code>
*
* $Horde: framework/RPC/RPC.php,v 1.14 2006/01/01 21:10:10 jan Exp $
*
* Copyright 2002-2006 Jan Schneider <jan@horde.org>
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Jan Schneider <jan@horde.org>
* @since Horde 3.0
* @package Horde_RPC
*/
class Horde_RPC {
/**
* Whether we need an authorized user or not.
*
* @access protected
* @var boolean
*/
var $_authorize = true;
/**
* RPC server constructor
*
* @access private
* @return object An RPC server instance.
*/
function Horde_RPC()
{
register_shutdown_function(array($this, 'shutdown'));
}
/**
* Cleans up the RPC server.
*
* @abstract
*/
function shutdown()
{
}
/**
* Check authentication. Different backends may handle
* authentication in different ways. The base class implementation
* checks for HTTP Authentication against the Horde auth setup.
*
* @return boolean Returns true if authentication is successful.
* Should send appropriate "not authorized" headers
* or other response codes/body if auth fails,
* and take care of exiting.
*/
function authorize()
{
if (!$this->_authorize) {
return true;
}
$auth = &Auth::singleton($GLOBALS['conf']['auth']['driver']);
if (isset($_SERVER['PHP_AUTH_USER'])) {
$user = $_SERVER['PHP_AUTH_USER'];
$pass = $_SERVER['PHP_AUTH_PW'];
}
if (!isset($user)
|| !$auth->authenticate($user, array('password' => $pass))) {
header('WWW-Authenticate: Basic realm="Horde RPC"');
header('HTTP/1.0 401 Unauthorized');
echo '401 Unauthorized';
exit;
}
return true;
}
/**
* Get the request body input. Different RPC backends can override
* this to return an open stream to php://stdin, for instance -
* whatever is easiest to handle in the getResponse() method.
*
* The base class implementation looks for $HTTP_RAW_POST_DATA and
* returns that if it's available; otherwise, it returns the
* contents of php://stdin.
*
* @return mixed The input - a string (default), a filehandle, etc.
*/
function getInput()
{
if (isset($GLOBALS['HTTP_RAW_POST_DATA'])) {
return $GLOBALS['HTTP_RAW_POST_DATA'];
} else {
return implode("\r\n", file('php://input'));
}
}
/**
* Sends an RPC request to the server and returns the result.
*
* @param string The raw request string.
*
* @return string The XML encoded response from the server.
*/
function getResponse($request)
{
return _("not implemented");
}
/**
* Get the Content-Type of the response.
*
* @return string The MIME Content-Type of the RPC response.
*/
function getResponseContentType()
{
return 'text/xml';
}
/**
* Builds an RPC request and sends it to the RPC server.
*
* This statically called method is actually the RPC client.
*
* @param string $driver The protocol driver to use. Currently 'soap'
* and 'xmlrpc' are available.
* @param string $url The path to the RPC server on the called host.
* @param string $method The method to call.
* @param array $params A hash containing any necessary parameters for
* the method call.
* @param $options Associative array of parameters depending on
* the selected protocol driver.
*
* @return mixed The returned result from the method or a PEAR
* error object on failure.
*/
function request($driver, $url, $method, $params = null, $options = array())
{
if (is_array($driver)) {
list($app, $driver) = $driver;
}
$driver = basename($driver);
if (!empty($app)) {
require_once $app . '/lib/RPC/' . $driver . '.php';
} elseif (@file_exists(dirname(__FILE__) . '/RPC/' . $driver . '.php')) {
require_once dirname(__FILE__) . '/RPC/' . $driver . '.php';
} else {
@include_once 'Horde/RPC/' . $driver . '.php';
}
$class = 'Horde_RPC_' . $driver;
if (class_exists($class)) {
return call_user_func(array($class, 'request'), $url, $method, $params, $options);
} else {
require_once 'PEAR.php';
return PEAR::raiseError('Class definition of ' . $class . ' not found.');
}
}
/**
* Attempts to return a concrete RPC server instance based on
* $driver.
*
* @param mixed $driver The type of concrete RPC subclass to return. If
* $driver is an array, then we will look in
* $driver[0]/lib/RPC/ for the subclass
* implementation named $driver[1].php.
* @param array $params A hash containing any additional configuration or
* connection parameters a subclass might need.
*
* @return Horde_RPC The newly created concrete Horde_RPC server instance,
* or a PEAR_Error on an error.
*/
function &factory($driver, $params = null)
{
if (is_array($driver)) {
list($app, $driver) = $driver;
}
$driver = basename($driver);
if (!empty($app)) {
require_once $app . '/lib/RPC/' . $driver . '.php';
} elseif (@file_exists(dirname(__FILE__) . '/RPC/' . $driver . '.php')) {
require_once dirname(__FILE__) . '/RPC/' . $driver . '.php';
} else {
@include_once 'Horde/RPC/' . $driver . '.php';
}
$class = 'Horde_RPC_' . $driver;
if (class_exists($class)) {
$rpc = new $class($params);
} else {
require_once 'PEAR.php';
$rpc = PEAR::raiseError('Class definition of ' . $class . ' not found.');
}
return $rpc;
}
/**
* Attempts to return a reference to a concrete RPC server
* instance based on $driver. It will only create a new instance
* if no RPC server instance with the same parameters currently
* exists.
*
* This should be used if multiple RPC servers (and thus, multiple RPC
* server instances) are required.
*
* This method must be invoked as: $var = &Horde_RPC::singleton()
*
* @param string $driver The type of concrete RPC subclass to return.
* @param array $params A hash containing any additional configuration or
* connection parameters a subclass might need.
*
* @return Horde_RPC The concrete Horde_RPC server reference, or a
* PEAR_Error on an error.
*/
function &singleton($driver, $params = null)
{
static $instances;
if (!isset($instances)) {
$instances = array();
}
$signature = serialize(array($driver, $params));
if (!array_key_exists($signature, $instances)) {
$instances[$signature] = &Horde_RPC::factory($driver, $params);
}
return $instances[$signature];
}
}

View File

@ -1,273 +0,0 @@
<?php
require_once 'Horde/SyncML.php';
#require_once 'Horde/SyncML/State.php';
require_once 'Horde/SyncML/State_egw.php';
require_once 'Horde/SyncML/Command/Status.php';
/**
* The Horde_RPC_syncml class provides a SyncML implementation of the Horde
* RPC system.
*
* $Horde: framework/RPC/RPC/syncml.php,v 1.27 2006/01/01 21:10:11 jan Exp $
*
* Copyright 2003-2006 Chuck Hagenbuch <chuck@horde.org>
* Copyright 2003-2006 Anthony Mills <amills@pyramid6.com>
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Chuck Hagenbuch <chuck@horde.org>
* @author Anthony Mills <amills@pyramid6.com>
* @since Horde 3.0
* @package Horde_RPC
*/
class Horde_RPC_syncml extends Horde_RPC {
/**
* Output ContentHandler used to output XML events.
*
* @var object
*/
var $_output;
/**
* @var integer
*/
var $_xmlStack = 0;
/**
* Debug directory, if set will store copies of all packets.
*
* @var string
*/
var $_debugDir = '/tmp/sync';
/**
* Default character set. Only supports UTF-8(ASCII?).
*
* @var string
*/
var $_charset = 'UTF-8';
/**
* SyncML handles authentication internally, so bypass the RPC framework
* auth check by just returning true here.
*/
function authorize()
{
return true;
}
/**
* Sends an RPC request to the server and returns the result.
*
* @param string $request The raw request string.
*
* @return string The XML encoded response from the server.
*/
function getResponse($request)
{
/* Catch any errors/warnings/notices that may get thrown while
* processing. Don't want to let anything go to the client that's not
* part of the valid response. */
ob_start();
/* Very useful for debugging. Logs WBXML packets to
* $this->_debugDir. */
if (!empty($this->_debugDir) && is_dir($this->_debugDir)) {
$packetNum = @intval(file_get_contents($this->_debugDir . '/syncml.packetnum'));
if (!isset($packetNum)) {
$packetNum = 0;
}
$f = @fopen($this->_debugDir . '/syncml_client_' . $packetNum . '.xml', 'wb');
if ($f) {
fwrite($f, $request);
fclose($f);
}
}
require_once 'XML/WBXML/ContentHandler.php';
$this->_output = new XML_WBXML_ContentHandler();
$this->_parse($request);
$response = '<?xml version="1.0" encoding="' . $this->_charset . '"?>';
$response .= $this->_output->getOutput();
/* Very useful for debugging. */
if (!empty($this->_debugDir) && is_dir($this->_debugDir)) {
$f = @fopen($this->_debugDir . '/syncml_server_' . $packetNum . '.xml', 'wb');
if ($f) {
fwrite($f, $response);
fclose($f);
}
$fp = @fopen($this->_debugDir . '/syncml.packetnum', 'w');
if ($fp) {
fwrite($fp, ++$packetNum);
fclose($fp);
}
}
/* Clear the output buffer that we started above, and log anything
* that came up for later debugging. */
$errorLogging = ob_get_clean();
if (!empty($errorLogging)) {
Horde::logMessage('SyncML: caught output=' .
$errorLogging, __FILE__, __LINE__, PEAR_LOG_DEBUG);
}
return $response;
}
function _parse($xml)
{
/* try to extract charset from XML text */
if(preg_match('/^\s*<\?xml[^>]*encoding\s*=\s*"([^"]*)"/i',
$xml, $m)) {
$this->_charset = $m[1];
}
#NLS::setCharset($this->_charset);
#String::setDefaultCharset($this->_charset);
/* Create the XML parser and set method references. */
$this->_parser = xml_parser_create_ns($this->_charset);
xml_set_object($this->_parser, $this);
xml_parser_set_option($this->_parser, XML_OPTION_CASE_FOLDING, false);
xml_set_element_handler($this->_parser, '_startElement', '_endElement');
xml_set_character_data_handler($this->_parser, '_characters');
xml_set_processing_instruction_handler($this->_parser, '');
xml_set_external_entity_ref_handler($this->_parser, '');
if (!xml_parse($this->_parser, $xml)) {
return $this->raiseError(sprintf('XML error: %s at line %d',
xml_error_string(xml_get_error_code($this->_parser)),
xml_get_current_line_number($this->_parser)));
}
xml_parser_free($this->_parser);
}
function _startElement($parser, $tag, $attributes)
{
list($uri, $name) = $this->_splitURI($tag);
$this->startElement($uri, $name, $attributes);
}
function _characters($parser, $chars)
{
$this->characters($chars);
}
function _endElement($parser, $tag)
{
list($uri, $name) = $this->_splitURI($tag);
$this->endElement($uri, $name);
}
function _splitURI($tag)
{
$parts = explode(':', $tag);
$name = array_pop($parts);
$uri = implode(':', $parts);
return array($uri, $name);
}
/**
* Returns the Content-Type of the response.
*
* @return string The MIME Content-Type of the RPC response.
*/
function getResponseContentType()
{
return 'application/vnd.syncml+xml';
}
function startElement($uri, $element, $attrs)
{
$this->_xmlStack++;
switch ($this->_xmlStack) {
case 1:
// <SyncML>
// Defined in SyncML Representation Protocol, version 1.1 5.2.1
$this->_output->startElement($uri, $element, $attrs);
break;
case 2:
// Either <SyncML><SyncHdr> or <SyncML><SyncBody>
if (!isset($this->_contentHandler)) {
// If not defined then create SyncHdr.
$this->_contentHandler = new Horde_SyncML_SyncmlHdr();
$this->_contentHandler->setOutput($this->_output);
}
$this->_contentHandler->startElement($uri, $element, $attrs);
break;
default:
if (isset($this->_contentHandler)) {
$this->_contentHandler->startElement($uri, $element, $attrs);
}
break;
}
}
function endElement($uri, $element)
{
switch ($this->_xmlStack) {
case 1:
// </SyncML>
// Defined in SyncML Representation Protocol, version 1.1 5.2.1
$this->_output->endElement($uri, $element);
break;
case 2:
// Either </SyncHdr></SyncML> or </SyncBody></SyncML>
if ($element == 'SyncHdr') {
// Then we get the state from SyncMLHdr, and create a new
// SyncMLBody.
$this->_contentHandler->endElement($uri, $element);
unset($this->_contentHandler);
$this->_contentHandler = new Horde_SyncML_SyncmlBody();
$this->_contentHandler->setOutput($this->_output);
} else {
// No longer used.
$this->_contentHandler->endElement($uri, $element);
unset($this->_contentHandler);
}
break;
default:
// </*></SyncHdr></SyncML> or </*></SyncBody></SyncML>
if (isset($this->_contentHandler)) {
$this->_contentHandler->endElement($uri, $element);
}
break;
}
if (isset($this->_chars)) {
unset($this->_chars);
}
$this->_xmlStack--;
}
function characters($str)
{
if (isset($this->_contentHandler)) {
$this->_contentHandler->characters($str);
}
}
function raiseError($str)
{
return Horde::logMessage($str, __FILE__, __LINE__, PEAR_LOG_ERR);
}
}

View File

@ -1,108 +0,0 @@
<?php
require_once dirname(__FILE__) . '/syncml.php';
require_once 'XML/WBXML/Decoder.php';
require_once 'XML/WBXML/Encoder.php';
/**
* The Horde_RPC_syncml_wbxml class provides a SyncML implementation of the
* Horde RPC system using WBXML encoding.
*
* $Horde: framework/RPC/RPC/syncml_wbxml.php,v 1.18 2006/01/01 21:10:11 jan Exp $
*
* Copyright 2003-2006 Chuck Hagenbuch <chuck@horde.org>
* Copyright 2003-2006 Anthony Mills <amills@pyramid6.com>
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Chuck Hagenbuch <chuck@horde.org>
* @author Anthony Mills <amills@pyramid6.com>
* @since Horde 3.0
* @package Horde_RPC
*/
class Horde_RPC_syncml_wbxml extends Horde_RPC_syncml {
/**
* Sends an RPC request to the server and returns the result.
*
* @param string $request The raw request string.
*
* @return string The WBXML encoded response from the server (binary).
*/
function getResponse($request)
{
/* Catch any errors/warnings/notices that may get thrown while
* processing. Don't want to let anything go to the client that's not
* part of the valid response. */
ob_start();
/* Very useful for debugging. Logs WBXML packets to
* $this->_debugDir. */
if (!empty($this->_debugDir) && is_dir($this->_debugDir)) {
$packetNum = @intval(file_get_contents($this->_debugDir . '/syncml.packetnum'));
if (!isset($packetNum)) {
$packetNum = 0;
}
$fp = fopen($this->_debugDir . '/syncml_client_' . $packetNum . '.wbxml', 'wb');
fwrite($fp, $request);
fclose($fp);
}
$decoder = new XML_WBXML_Decoder();
$this->_output = new XML_WBXML_Encoder();
$decoder->setContentHandler($this);
$r = $decoder->decode($request);
if (is_a($r, 'PEAR_Error')) {
Horde::logMessage('SyncML: ' .
$r->getMessage(), __FILE__, __LINE__, PEAR_LOG_ERR);
}
$this->_output->setVersion($decoder->getVersion());
$this->_output->setCharset($decoder->getCharsetStr());
$response = $this->_output->getOutput();
if (is_a($response, 'PEAR_Error')) {
Horde::logMessage($response, __FILE__, __LINE__, PEAR_LOG_ERR);
$response = $response->getMessage();
}
if (!empty($this->_debugDir) && is_dir($this->_debugDir)) {
$fp = fopen($this->_debugDir . '/syncml_server_' . $packetNum . '.wbxml', 'wb');
fwrite($fp, $response);
fclose($fp);
$fp = @fopen($this->_debugDir . '/syncml.packetnum', 'w');
if ($fp) {
fwrite($fp, ++$packetNum);
fclose($fp);
}
}
/* Clear the output buffer that we started above, and log anything
* that came up for later debugging. */
$errorLogging = ob_get_clean();
if (!empty($errorLogging)) {
Horde::logMessage('SyncML: caught output=' . $errorLogging,
__FILE__, __LINE__, PEAR_LOG_DEBUG);
}
return $response;
}
/**
* Returns the Content-Type of the response.
*
* @return string The MIME Content-Type of the RPC response.
*/
function getResponseContentType()
{
return 'application/vnd.syncml+wbxml';
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,705 +0,0 @@
<?php
$GLOBALS['_HORDE_STRING_CHARSET'] = 'iso-8859-1';
/**
* The String:: class provides static methods for charset and locale safe
* string manipulation.
*
* $Horde: framework/Util/String.php,v 1.43.6.38 2009-09-15 16:36:14 jan Exp $
*
* Copyright 2003-2009 The Horde Project (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Jan Schneider <jan@horde.org>
* @since Horde 3.0
* @package Horde_Util
*/
class String {
/**
* Caches the result of extension_loaded() calls.
*
* @param string $ext The extension name.
*
* @return boolean Is the extension loaded?
*
* @see Util::extensionExists()
*/
public static function extensionExists($ext)
{
static $cache = array();
if (!isset($cache[$ext])) {
$cache[$ext] = extension_loaded($ext);
}
return $cache[$ext];
}
/**
* Sets a default charset that the String:: methods will use if none is
* explicitly specified.
*
* @param string $charset The charset to use as the default one.
*/
public static function setDefaultCharset($charset)
{
$GLOBALS['_HORDE_STRING_CHARSET'] = $charset;
if (String::extensionExists('mbstring') &&
function_exists('mb_regex_encoding')) {
$old_error = error_reporting(0);
mb_regex_encoding(String::_mbstringCharset($charset));
error_reporting($old_error);
}
}
/**
* Converts a string from one charset to another.
*
* Works only if either the iconv or the mbstring extension
* are present and best if both are available.
* The original string is returned if conversion failed or none
* of the extensions were available.
*
* @param mixed $input The data to be converted. If $input is an an array,
* the array's values get converted recursively.
* @param string $from The string's current charset.
* @param string $to The charset to convert the string to. If not
* specified, the global variable
* $_HORDE_STRING_CHARSET will be used.
*
* @return mixed The converted input data.
*/
public static function convertCharset($input, $from, $to = null)
{
/* Don't bother converting numbers. */
if (is_numeric($input)) {
return $input;
}
/* Get the user's default character set if none passed in. */
if (is_null($to)) {
$to = $GLOBALS['_HORDE_STRING_CHARSET'];
}
/* If the from and to character sets are identical, return now. */
if ($from == $to) {
return $input;
}
$from = String::lower($from);
$to = String::lower($to);
if ($from == $to) {
return $input;
}
if (is_array($input)) {
$tmp = array();
reset($input);
while (list($key, $val) = each($input)) {
$tmp[String::_convertCharset($key, $from, $to)] = String::convertCharset($val, $from, $to);
}
return $tmp;
}
if (is_object($input)) {
// PEAR_Error objects are almost guaranteed to contain recursion,
// which will cause a segfault in PHP. We should never reach
// this line, but add a check and a log message to help the devs
// track down and fix this issue.
if (is_a($input, 'PEAR_Error')) {
Horde::logMessage('Called convertCharset() on a PEAR_Error object. ' . print_r($input, true), __FILE__, __LINE__, PEAR_LOG_DEBUG);
return '';
}
$vars = get_object_vars($input);
while (list($key, $val) = each($vars)) {
$input->$key = String::convertCharset($val, $from, $to);
}
return $input;
}
if (!is_string($input)) {
return $input;
}
return String::_convertCharset($input, $from, $to);
}
/**
* Internal public static function used to do charset conversion.
*
* @access private
*
* @param string $input See String::convertCharset().
* @param string $from See String::convertCharset().
* @param string $to See String::convertCharset().
*
* @return string The converted string.
*/
public static function _convertCharset($input, $from, $to)
{
$output = '';
$from_check = (($from == 'iso-8859-1') || ($from == 'us-ascii'));
$to_check = (($to == 'iso-8859-1') || ($to == 'us-ascii'));
/* Use utf8_[en|de]code() if possible and if the string isn't too
* large (less than 16 MB = 16 * 1024 * 1024 = 16777216 bytes) - these
* public static functions use more memory. */
if (strlen($input) < 16777216 || !(String::extensionExists('iconv') || String::extensionExists('mbstring'))) {
if ($from_check && ($to == 'utf-8')) {
return utf8_encode($input);
}
if (($from == 'utf-8') && $to_check) {
return utf8_decode($input);
}
}
/* First try iconv with transliteration. */
if (($from != 'utf7-imap') &&
($to != 'utf7-imap') &&
String::extensionExists('iconv')) {
/* We need to tack an extra character temporarily because of a bug
* in iconv() if the last character is not a 7 bit ASCII
* character. */
$oldTrackErrors = ini_set('track_errors', 1);
unset($php_errormsg);
$output = @iconv($from, $to . '//TRANSLIT', $input . 'x');
$output = (isset($php_errormsg)) ? false : String::substr($output, 0, -1, $to);
ini_set('track_errors', $oldTrackErrors);
}
/* Next try mbstring. */
if (!$output && String::extensionExists('mbstring')) {
$old_error = error_reporting(0);
$output = mb_convert_encoding($input, $to, String::_mbstringCharset($from));
error_reporting($old_error);
}
/* At last try imap_utf7_[en|de]code if appropriate. */
if (!$output && String::extensionExists('imap')) {
if ($from_check && ($to == 'utf7-imap')) {
return @imap_utf7_encode($input);
}
if (($from == 'utf7-imap') && $to_check) {
return @imap_utf7_decode($input);
}
}
return (!$output) ? $input : $output;
}
/**
* Makes a string lowercase.
*
* @param string $string The string to be converted.
* @param boolean $locale If true the string will be converted based on a
* given charset, locale independent else.
* @param string $charset If $locale is true, the charset to use when
* converting. If not provided the current charset.
*
* @return string The string with lowercase characters
*/
public static function lower($string, $locale = false, $charset = null)
{
static $lowers;
if ($locale) {
/* The existence of mb_strtolower() depends on the platform. */
if (String::extensionExists('mbstring') &&
function_exists('mb_strtolower')) {
if (is_null($charset)) {
$charset = $GLOBALS['_HORDE_STRING_CHARSET'];
}
$old_error = error_reporting(0);
$ret = mb_strtolower($string, String::_mbstringCharset($charset));
error_reporting($old_error);
if (!empty($ret)) {
return $ret;
}
}
return strtolower($string);
}
if (!isset($lowers)) {
$lowers = array();
}
if (!isset($lowers[$string])) {
$language = setlocale(LC_CTYPE, 0);
setlocale(LC_CTYPE, 'C');
$lowers[$string] = strtolower($string);
setlocale(LC_CTYPE, $language);
}
return $lowers[$string];
}
/**
* Makes a string uppercase.
*
* @param string $string The string to be converted.
* @param boolean $locale If true the string will be converted based on a
* given charset, locale independent else.
* @param string $charset If $locale is true, the charset to use when
* converting. If not provided the current charset.
*
* @return string The string with uppercase characters
*/
public static function upper($string, $locale = false, $charset = null)
{
static $uppers;
if ($locale) {
/* The existence of mb_strtoupper() depends on the
* platform. */
if (function_exists('mb_strtoupper')) {
if (is_null($charset)) {
$charset = $GLOBALS['_HORDE_STRING_CHARSET'];
}
$old_error = error_reporting(0);
$ret = mb_strtoupper($string, String::_mbstringCharset($charset));
error_reporting($old_error);
if (!empty($ret)) {
return $ret;
}
}
return strtoupper($string);
}
if (!isset($uppers)) {
$uppers = array();
}
if (!isset($uppers[$string])) {
$language = setlocale(LC_CTYPE, 0);
setlocale(LC_CTYPE, 'C');
$uppers[$string] = strtoupper($string);
setlocale(LC_CTYPE, $language);
}
return $uppers[$string];
}
/**
* Returns a string with the first letter capitalized if it is
* alphabetic.
*
* @param string $string The string to be capitalized.
* @param boolean $locale If true the string will be converted based on a
* given charset, locale independent else.
* @param string $charset The charset to use, defaults to current charset.
*
* @return string The capitalized string.
*/
public static function ucfirst($string, $locale = false, $charset = null)
{
if ($locale) {
$first = String::substr($string, 0, 1, $charset);
if (String::isAlpha($first, $charset)) {
$string = String::upper($first, true, $charset) . String::substr($string, 1, null, $charset);
}
} else {
$string = String::upper(substr($string, 0, 1), false) . substr($string, 1);
}
return $string;
}
/**
* Returns part of a string.
*
* @param string $string The string to be converted.
* @param integer $start The part's start position, zero based.
* @param integer $length The part's length.
* @param string $charset The charset to use when calculating the part's
* position and length, defaults to current
* charset.
*
* @return string The string's part.
*/
public static function substr($string, $start, $length = null, $charset = null)
{
if (is_null($length)) {
$length = String::length($string, $charset) - $start;
}
if ($length == 0) {
return '';
}
/* Try mbstring. */
if (String::extensionExists('mbstring')) {
if (is_null($charset)) {
$charset = $GLOBALS['_HORDE_STRING_CHARSET'];
}
$old_error = error_reporting(0);
$ret = mb_substr($string, $start, $length, String::_mbstringCharset($charset));
error_reporting($old_error);
/* mb_substr() returns empty string on failure. */
if (strlen($ret)) {
return $ret;
}
}
/* Try iconv. */
if (function_exists('iconv_substr')) {
if (is_null($charset)) {
$charset = $GLOBALS['_HORDE_STRING_CHARSET'];
}
$old_error = error_reporting(0);
$ret = iconv_substr($string, $start, $length, $charset);
error_reporting($old_error);
/* iconv_substr() returns false on failure. */
if ($ret !== false) {
return $ret;
}
}
return substr($string, $start, $length);
}
/**
* Returns the character (not byte) length of a string.
*
* @param string $string The string to return the length of.
* @param string $charset The charset to use when calculating the string's
* length.
*
* @return string The string's part.
*/
public static function length($string, $charset = null)
{
if (is_null($charset)) {
$charset = $GLOBALS['_HORDE_STRING_CHARSET'];
}
$charset = String::lower($charset);
if (String::extensionExists('mbstring')) {
$old_error = error_reporting(0);
$ret = mb_strlen($string, String::_mbstringCharset($charset));
error_reporting($old_error);
if (!empty($ret)) {
return $ret;
}
}
if ($charset == 'utf-8' || $charset == 'utf8') {
return strlen(utf8_decode($string));
}
return strlen($string);
}
/**
* Returns the numeric position of the first occurrence of $needle
* in the $haystack string.
*
* @param string $haystack The string to search through.
* @param string $needle The string to search for.
* @param integer $offset Allows to specify which character in haystack
* to start searching.
* @param string $charset The charset to use when searching for the
* $needle string.
*
* @return integer The position of first occurrence.
*/
public static function pos($haystack, $needle, $offset = 0, $charset = null)
{
if (String::extensionExists('mbstring')) {
if (is_null($charset)) {
$charset = $GLOBALS['_HORDE_STRING_CHARSET'];
}
$track_errors = ini_set('track_errors', 1);
$old_error = error_reporting(0);
$ret = mb_strpos($haystack, $needle, $offset, String::_mbstringCharset($charset));
error_reporting($old_error);
ini_set('track_errors', $track_errors);
if (!isset($php_errormsg)) {
return $ret;
}
}
return strpos($haystack, $needle, $offset);
}
/**
* Returns a string padded to a certain length with another string.
*
* This method behaves exactly like str_pad but is multibyte safe.
*
* @param string $input The string to be padded.
* @param integer $length The length of the resulting string.
* @param string $pad The string to pad the input string with. Must
* be in the same charset like the input string.
* @param const $type The padding type. One of STR_PAD_LEFT,
* STR_PAD_RIGHT, or STR_PAD_BOTH.
* @param string $charset The charset of the input and the padding
* strings.
*
* @return string The padded string.
*/
public static function pad($input, $length, $pad = ' ', $type = STR_PAD_RIGHT,
$charset = null)
{
$mb_length = String::length($input, $charset);
$sb_length = strlen($input);
$pad_length = String::length($pad, $charset);
/* Return if we already have the length. */
if ($mb_length >= $length) {
return $input;
}
/* Shortcut for single byte strings. */
if ($mb_length == $sb_length && $pad_length == strlen($pad)) {
return str_pad($input, $length, $pad, $type);
}
switch ($type) {
case STR_PAD_LEFT:
$left = $length - $mb_length;
$output = String::substr(str_repeat($pad, ceil($left / $pad_length)), 0, $left, $charset) . $input;
break;
case STR_PAD_BOTH:
$left = floor(($length - $mb_length) / 2);
$right = ceil(($length - $mb_length) / 2);
$output = String::substr(str_repeat($pad, ceil($left / $pad_length)), 0, $left, $charset) .
$input .
String::substr(str_repeat($pad, ceil($right / $pad_length)), 0, $right, $charset);
break;
case STR_PAD_RIGHT:
$right = $length - $mb_length;
$output = $input . String::substr(str_repeat($pad, ceil($right / $pad_length)), 0, $right, $charset);
break;
}
return $output;
}
/**
* Wraps the text of a message.
*
* @since Horde 3.2
*
* @param string $string String containing the text to wrap.
* @param integer $width Wrap the string at this number of
* characters.
* @param string $break Character(s) to use when breaking lines.
* @param boolean $cut Whether to cut inside words if a line
* can't be wrapped.
* @param string $charset Character set to use when breaking lines.
* @param boolean $line_folding Whether to apply line folding rules per
* RFC 822 or similar. The correct break
* characters including leading whitespace
* have to be specified too.
*
* @return string String containing the wrapped text.
*/
public static function wordwrap($string, $width = 75, $break = "\n", $cut = false,
$charset = null, $line_folding = false)
{
/* Get the user's default character set if none passed in. */
if (is_null($charset)) {
$charset = $GLOBALS['_HORDE_STRING_CHARSET'];
}
$charset = String::_mbstringCharset($charset);
$string = String::convertCharset($string, $charset, 'utf-8');
$wrapped = '';
while (String::length($string, 'utf-8') > $width) {
$line = String::substr($string, 0, $width, 'utf-8');
$string = String::substr($string, String::length($line, 'utf-8'), null, 'utf-8');
// Make sure didn't cut a word, unless we want hard breaks anyway.
if (!$cut && preg_match('/^(.+?)((\s|\r?\n).*)/us', $string, $match)) {
$line .= $match[1];
$string = $match[2];
}
// Wrap at existing line breaks.
if (preg_match('/^(.*?)(\r?\n)(.*)$/u', $line, $match)) {
$wrapped .= $match[1] . $match[2];
$string = $match[3] . $string;
continue;
}
// Wrap at the last colon or semicolon followed by a whitespace if
// doing line folding.
if ($line_folding &&
preg_match('/^(.*?)(;|:)(\s+.*)$/u', $line, $match)) {
$wrapped .= $match[1] . $match[2] . $break;
$string = $match[3] . $string;
continue;
}
// Wrap at the last whitespace of $line.
if ($line_folding) {
$sub = '(.+[^\s])';
} else {
$sub = '(.*)';
}
if (preg_match('/^' . $sub . '(\s+)(.*)$/u', $line, $match)) {
$wrapped .= $match[1] . $break;
$string = ($line_folding ? $match[2] : '') . $match[3] . $string;
continue;
}
// Hard wrap if necessary.
if ($cut) {
$wrapped .= $line . $break;
continue;
}
$wrapped .= $line;
}
return String::convertCharset($wrapped . $string, 'utf-8', $charset);
}
/**
* Wraps the text of a message.
*
* @param string $text String containing the text to wrap.
* @param integer $length Wrap $text at this number of characters.
* @param string $break_char Character(s) to use when breaking lines.
* @param string $charset Character set to use when breaking lines.
* @param boolean $quote Ignore lines that are wrapped with the '>'
* character (RFC 2646)? If true, we don't
* remove any padding whitespace at the end of
* the string.
*
* @return string String containing the wrapped text.
*/
public static function wrap($text, $length = 80, $break_char = "\n", $charset = null,
$quote = false)
{
$paragraphs = array();
foreach (preg_split('/\r?\n/', $text) as $input) {
if ($quote && (strpos($input, '>') === 0)) {
$line = $input;
} else {
/* We need to handle the Usenet-style signature line
* separately; since the space after the two dashes is
* REQUIRED, we don't want to trim the line. */
if ($input != '-- ') {
$input = rtrim($input);
}
$line = String::wordwrap($input, $length, $break_char, false, $charset);
}
$paragraphs[] = $line;
}
return implode($break_char, $paragraphs);
}
/**
* Returns true if the every character in the parameter is an alphabetic
* character.
*
* @param $string The string to test.
* @param $charset The charset to use when testing the string.
*
* @return boolean True if the parameter was alphabetic only.
*/
public static function isAlpha($string, $charset = null)
{
if (!String::extensionExists('mbstring')) {
return ctype_alpha($string);
}
$charset = String::_mbstringCharset($charset);
$old_charset = mb_regex_encoding();
$old_error = error_reporting(0);
if ($charset != $old_charset) {
mb_regex_encoding($charset);
}
$alpha = !mb_ereg_match('[^[:alpha:]]', $string);
if ($charset != $old_charset) {
mb_regex_encoding($old_charset);
}
error_reporting($old_error);
return $alpha;
}
/**
* Returns true if ever character in the parameter is a lowercase letter in
* the current locale.
*
* @param $string The string to test.
* @param $charset The charset to use when testing the string.
*
* @return boolean True if the parameter was lowercase.
*/
public static function isLower($string, $charset = null)
{
return ((String::lower($string, true, $charset) === $string) &&
String::isAlpha($string, $charset));
}
/**
* Returns true if every character in the parameter is an uppercase letter
* in the current locale.
*
* @param string $string The string to test.
* @param string $charset The charset to use when testing the string.
*
* @return boolean True if the parameter was uppercase.
*/
public static function isUpper($string, $charset = null)
{
return ((String::upper($string, true, $charset) === $string) &&
String::isAlpha($string, $charset));
}
/**
* Performs a multibyte safe regex match search on the text provided.
*
* @since Horde 3.1
*
* @param string $text The text to search.
* @param array $regex The regular expressions to use, without perl
* regex delimiters (e.g. '/' or '|').
* @param string $charset The character set of the text.
*
* @return array The matches array from the first regex that matches.
*/
public static function regexMatch($text, $regex, $charset = null)
{
if (!empty($charset)) {
$regex = String::convertCharset($regex, $charset, 'utf-8');
$text = String::convertCharset($text, $charset, 'utf-8');
}
$matches = array();
foreach ($regex as $val) {
if (preg_match('/' . $val . '/u', $text, $matches)) {
break;
}
}
if (!empty($charset)) {
$matches = String::convertCharset($matches, 'utf-8', $charset);
}
return $matches;
}
/**
* Workaround charsets that don't work with mbstring public static functions.
*
* @access private
*
* @param string $charset The original charset.
*
* @return string The charset to use with mbstring public static functions.
*/
public static function _mbstringCharset($charset)
{
/* mbstring public static functions do not handle the 'ks_c_5601-1987' &
* 'ks_c_5601-1989' charsets. However, these charsets are used, for
* example, by various versions of Outlook to send Korean characters.
* Use UHC (CP949) encoding instead. See, e.g.,
* http://lists.w3.org/Archives/Public/ietf-charsets/2001AprJun/0030.html */
if (in_array(String::lower($charset), array('ks_c_5601-1987', 'ks_c_5601-1989'))) {
$charset = 'UHC';
}
return $charset;
}
}

View File

@ -1,752 +0,0 @@
<?php
/**
* eGroupWare - SyncML based on Horde 3.0
*
* The Horde_SyncML_SyncHdr and Horde_SyncML_SyncBody classes provides
* a SyncHdr and SyncBody in SyncML Representation Protocol, version
* 1.1 5.2.2 and 5.2.3. Most of the work is passed on to
* Horde_SyncML_Command_Alert and Horde_SyncML_Command_Sync.
*
* Using the PEAR Log class (which need to be installed!)
*
* @link http://www.egroupware.org
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package api
* @subpackage horde
* @author Anthony Mills <amills@pyramid6.com>
* @author Karsten Fourmont <fourmont@gmx.de>
* @author Joerg Lehrke <jlehrke@noc.de>
* @copyright (c) The Horde Project (http://www.horde.org/)
* @version $Id$
*/
include_once 'Horde/SyncML/Command.php';
include_once 'Horde/SyncML/Command/Status.php';
include_once 'Horde/SyncML/Command/Alert.php';
include_once 'Horde/SyncML/Command/Final.php';
include_once 'Horde/SyncML/Command/Sync.php';
include_once 'Horde/SyncML/Sync.php';
include_once 'Horde/SyncML/Command/Sync/SyncElementItem.php';
class Horde_SyncML_ContentHandler {
/**
* Output ContentHandler used to output XML events.
* @var object $_output
*/
var $_output;
/**
* @var integer $_xmlStack
*/
var $_xmlStack = 1;
/**
* @var string $_chars
*/
var $_chars;
function setOutput(&$output)
{
$this->_output = &$output;
}
function startElement($uri, $element, $attrs)
{
$this->_xmlStack++;
}
function endElement($uri, $element)
{
if (isset($this->_chars)) {
unset($this->_chars);
}
$this->_xmlStack--;
}
function characters($str)
{
if (isset($this->_chars)) {
$this->_chars = $this->_chars . $str;
} else {
$this->_chars = $str;
}
}
}
/**
* Defined in SyncML Representation Protocol, version 1.1 5.2.2
*
* @package Horde_SyncML
*/
class Horde_SyncML_SyncMLHdr extends Horde_SyncML_ContentHandler {
/**
* Used to specify if in Source tag. Defined in SyncML
* Representation Protocol, version 1.1 5.1.20.
*
* @var boolean $_isSource
*/
var $_isSource = false;
/**
* Defined in SyncML Representation Protocol, version 1.1
* 5.1.9. User name.
*
* @var string $_locName
*/
var $_locName;
/**
* Defined in SyncML Representation Protocol, version 1.1 5.1.18
*
* @var string $_sessionID
*/
var $_sessionID;
/**
* Defined in SyncML Representation Protocol, version 1.1. Must
* be 1.0 (0), 1.1 (1) or 1.2(2).
*
* @var string $_version
*/
var $_version;
/**
* Defined in SyncML Representation Protocol, version 1.1 5.1.12
*
* @var string $_msgID
*/
var $_msgID;
/**
* Defined in SyncML Representation Protocol, version 1.1 5.1.10
*
* @var string $_targetURI
*/
var $_targetURI;
/**
* Defined in SyncML Representation Protocol, version 1.1 5.1.10,
* 5.1.20
*
* @var string $_sourceURI
*/
var $_sourceURI;
var $_isCred;
var $_credData;
var $_credFormat;
var $_credType;
var $_maxMsgSize;
function &getStateFromSession($sourceURI, $locName, $sessionID)
{
// Remove any existing session since we'll be contructing a
// custom session id.
session_regenerate_id();
session_destroy();
// we need to (re-)load the eGW session-handler, as session_destroy unloads custom session-handlers
if (function_exists('init_session_handler')) {
init_session_handler();
}
// Reload the Horde SessionHandler if necessary.
Horde::setupSessionHandler();
// It would seem multisync does not send the user name once it
// has been authorized. Make sure we have a valid session id.
if(!empty($_GET['syncml_sessionid'])) {
session_id($_GET['syncml_sessionid']);
Horde::logMessage('SyncML['. session_id() .']: reusing existing session',
__FILE__, __LINE__, PEAR_LOG_DEBUG);
} else {
#session_id('syncml' . preg_replace('/[^a-zA-Z0-9]/', '', $sourceURI . $sessionID));
session_id('syncml-' . md5(uniqid(rand(), true)));
Horde::logMessage('SyncML['. session_id() .']: starting new session for '
. $this->_locName, __FILE__, __LINE__, PEAR_LOG_INFO);
}
@session_start();
if (!isset($_SESSION['SyncML.state'])) {
// Create a new state if one does not already exist.
Horde::logMessage('SyncML['. session_id() .']: create new session state variable for '
. $sourceURI, __FILE__, __LINE__, PEAR_LOG_DEBUG);
$_SESSION['SyncML.state'] = new EGW_SyncML_State($sourceURI, $locName, $sessionID);
}
if ($_SESSION['SyncML.state']->isAuthorized()) {
Horde::logMessage('SyncML['. session_id() .']: session is authorized',
__FILE__, __LINE__, PEAR_LOG_DEBUG);
}
#Horde::logMessage('SyncML['. session_id() . "]:\n" . print_r($_SESSION['SyncML.state'], true), __FILE__, __LINE__, PEAR_LOG_DEBUG);
return $_SESSION['SyncML.state'];
}
function startElement($uri, $element, $attrs)
{
parent::startElement($uri, $element, $attrs);
switch ($this->_xmlStack) {
case 3:
if ($element == 'Source') {
// <SyncML><SyncHdr><Source>
$this->_isSource = true;
} elseif ($element == 'Cred') {
$this->_isCred = true;
}
break;
}
}
function endElement($uri, $element)
{
switch ($this->_xmlStack) {
case 2:
// </SyncHdr></SyncML>
Horde::logMessage('SyncML['. session_id() .']: package '
. $this->_msgID.' +++++++++++++++++++++ started',
__FILE__, __LINE__, PEAR_LOG_DEBUG);
// Find the state.
//Horde::logMessage('SymcML: SyncHdr done. Try to load state from session.',
// __FILE__, __LINE__, PEAR_LOG_DEBUG);
$state =& $this->getStateFromSession($this->_sourceURI, $this->_locName, $this->_sessionID);
$state->setVersion($this->_version);
$state->setMsgID($this->_msgID);
$state->setTargetURI($this->_targetURI);
$state->setWBXML(is_a($this->_output, 'XML_WBXML_Encoder'));
if (isset($this->_credData)
&& isset($this->_locName)
&& !$state->isAuthorized()) {
$state->setPassword($this->_credData);
$state->setLocName($this->_locName);
}
if (isset($this->_maxMsgSize)) {
$state->setMaxMsgSize($this->_maxMsgSize);
}
// $_SESSION['SyncML.state'] = $state;
#Horde::logMessage('SymcML: session id 2 =' . session_id(), __FILE__, __LINE__, PEAR_LOG_DEBUG);
// Got the state; now write our SyncHdr header.
$this->outputSyncHdr($this->_output);
break;
case 3:
if ($element == 'VerProto') {
// </VerProto></SyncHdr></SyncML>
switch (strtolower(trim($this->_chars))) {
case 'syncml/1.2':
$this->_version = 2;
break;
case 'syncml/1.1':
$this->_version = 1;
break;
default:
$this->_version = 0;
break;
}
} elseif ($element == 'SessionID') {
// </SessionID></SyncHdr></SyncML>
$this->_sessionID = trim($this->_chars);
} elseif ($element == 'MsgID') {
// </MsgID></SyncHdr></SyncML>
$this->_msgID = intval(trim($this->_chars));
} elseif ($element == 'Source') {
// </Source></SyncHdr></SyncML>
$this->_isSource = false;
} elseif ($element == 'Cred') {
// </Cred></SyncHdr></SyncML>
$this->_isCred = false;
// We only support b64 for now
//if ($this->_credFormat == 'b64') {
$this->_credData = base64_decode($this->_credData);
//}
$tmp = explode(':', $this->_credData, 2);
// set only if not set by LocName already
if (!isset($this->_locName)) {
$this->_locName = $tmp[0];
}
$this->_credData = $tmp[1];
#Horde::logMessage('SyncML['. session_id() .']: $this->_locName: ' . $this->_locName, __FILE__, __LINE__, PEAR_LOG_DEBUG);
}
break;
case 4:
switch ($element) {
case 'LocURI':
if ($this->_isSource) {
// </LocURI></Source></SyncHdr></SyncML>
$this->_sourceURI = trim($this->_chars);
} else {
// </LocURI></Target></SyncHdr></SyncML>
$this->_targetURI = trim($this->_chars);
}
break;
case 'LocName':
if ($this->_isSource) {
// </LocName></Source></SyncHdr></SyncML>
$this->_locName = trim($this->_chars);
}
break;
case 'Data':
// </Data></Cred></SyncHdr></SyncML>
if ($this->_isCred) {
$this->_credData = trim($this->_chars);
}
break;
case 'MaxMsgSize':
//</MaxMsgSize></Meta></SyncHdr></SyncML>
$this->_maxMsgSize = trim($this->_chars);
break;
}
break;
case 5:
if ($this->_isCred) {
if ($element == 'Format') {
// </Format></Meta></Cred></SyncHdr></SyncML>
$this->_credFormat = trim($this->_chars);
} elseif ($element == 'Type') {
// </Type></Meta></Cred></SyncHdr></SyncML>
$this->_credType = trim($this->_chars);
}
}
break;
}
parent::endElement($uri, $element);
}
function outputSyncHdr(&$output)
{
$attrs = array();
$state =& $_SESSION['SyncML.state'];
$uri = $state->getURI();
$uriMeta = $state->getURIMeta();
$output->startElement($uri, 'SyncHdr', $attrs);
$output->startElement($uri, 'VerDTD', $attrs);
if ($this->_version == 2) {
$chars = '1.2';
} elseif ($this->_version == 1) {
$chars = '1.1';
} else {
$chars = '1.0';
}
$output->characters($chars);
$output->endElement($uri, 'VerDTD');
$output->startElement($uri, 'VerProto', $attrs);
if ($this->_version == 2) {
$chars = 'SyncML/1.2';
} elseif ($this->_version == 1) {
$chars = 'SyncML/1.1';
} else {
$chars = 'SyncML/1.0';
}
$output->characters($chars);
$output->endElement($uri, 'VerProto');
$output->startElement($uri, 'SessionID', $attrs);
$output->characters($this->_sessionID);
$output->endElement($uri, 'SessionID');
$output->startElement($uri, 'MsgID', $attrs);
$output->characters($this->_msgID);
$output->endElement($uri, 'MsgID');
$output->startElement($uri, 'Target', $attrs);
$output->startElement($uri, 'LocURI', $attrs);
$output->characters($this->_sourceURI);
$output->endElement($uri, 'LocURI');
$output->endElement($uri, 'Target');
$output->startElement($uri, 'Source', $attrs);
$output->startElement($uri, 'LocURI', $attrs);
$output->characters($this->_targetURI);
$output->endElement($uri, 'LocURI');
$output->endElement($uri, 'Source');
if (session_id() != '' && !strpos($this->_targetURI,'syncml_sessionid')) {
$output->startElement($uri, 'RespURI', $attrs);
// some clients don't send the whole URL as targetURI
if (strpos($this->_targetURI,$_SERVER['PHP_SELF']) === false) {
$output->characters($this->_targetURI . $_SERVER['PHP_SELF'] . '?syncml_sessionid=' . session_id());
} else {
$output->characters($this->_targetURI . '?syncml_sessionid=' . session_id());
}
$output->endElement($uri, 'RespURI');
}
$output->startElement($uri, 'Meta', $attrs);
if (!($maxMsgSize = $state->getMaxMsgSizeClient()) || $maxMsgSize > 10000) {
// Use a realistic message size to cope with
$maxMsgSize = 10000;
}
$output->startElement($uriMeta, 'MaxMsgSize', $attrs);
$output->characters($maxMsgSize);
$output->endElement($uriMeta, 'MaxMsgSize');
#// Dummy MaxObjSize, this is just put in to make the packet
#// work, it is not our real value.
#if ($this->_version > 0) {
# // Don't send this to old devices
# $output->startElement($uriMeta, 'MaxObjSize', $attrs);
# $output->characters('4000000');
# $output->endElement($uriMeta, 'MaxObjSize');
#}
$output->endElement($uri, 'Meta');
$output->endElement($uri, 'SyncHdr');
}
function getSourceURI()
{
return $this->_sourceURI;
}
function getLocName()
{
return $this->_locName;
}
function getSessionID()
{
return $this->_sessionID;
}
function getVersion()
{
return $this->_version;
}
function getMsgID()
{
return $this->_msgID;
}
function getTargetURI()
{
return $this->_targetURI;
}
function opaque($o)
{
}
}
/**
* Defined in SyncML Representation Protocol, version 1.1 5.2.3
*
* @package Horde_SyncML
*/
class Horde_SyncML_SyncMLBody extends Horde_SyncML_ContentHandler {
var $_currentCmdID = 1;
var $_currentCommand;
var $_actionCommands = false;
var $_clientSentFinal = false;
function startElement($uri, $element, $attrs)
{
parent::startElement($uri, $element, $attrs);
$state =& $_SESSION['SyncML.state'];
switch ($this->_xmlStack) {
case 2:
$this->_actionCommands = false; // so far, we have not seen commands that require action from our side
$state->_sendFinal = false;
// <SyncML><SyncBody>
$this->_output->startElement($uri, $element, $attrs);
if ($state->getLocName()) {
if ($state->isAuthConfirmed()) {
// Right our status about the header
$status = new Horde_SyncML_Command_Status(($state->isAuthorized()) ?
RESPONSE_OK : RESPONSE_INVALID_CREDENTIALS, 'SyncHdr');
} else {
// Right our status about the header.
$status = new Horde_SyncML_Command_Status(($state->isAuthorized()) ?
RESPONSE_AUTHENTICATION_ACCEPTED : RESPONSE_INVALID_CREDENTIALS, 'SyncHdr');
}
} else {
// Request credentials if not sent so far
$status = new Horde_SyncML_Command_Status(RESPONSE_MISSING_CREDENTIALS, 'SyncHdr');
}
$status->setSourceRef($state->getSourceURI());
$status->setTargetRef($state->getTargetURI());
$status->setCmdRef(0);
$state->clearNumberOfElements();
/*$str = 'authorized=' . $state->isAuthorized();
$str .= ' version=' . $state->getVersion();
$str .= ' msgid=' . $state->getMsgID();
$str .= ' source=' . $state->getSourceURI();
$str .= ' target=' . $state->getTargetURI();
*/
$this->_currentCmdID = $status->output($this->_currentCmdID, $this->_output);
if ($state->isAuthorized()) {
$state->AuthConfirmed();
}
break;
case 3:
// <SyncML><SyncBody><[Command]>
#Horde::logMessage('SyncML['. session_id() ."]: found command $element ", __FILE__, __LINE__, PEAR_LOG_DEBUG);
$this->_currentCommand = Horde_SyncML_Command::factory($element);
$this->_currentCommand->startElement($uri, $element, $attrs);
if ($element != 'Status' && $element != 'Map' && $element != 'Final') {
// We've got to do something! This can't be the last
// packet.
$this->_actionCommands = true;
Horde::logMessage('SyncML['. session_id() ."]: found action commands <$element> ", __FILE__, __LINE__, PEAR_LOG_DEBUG);
}
switch ($element)
{
case 'Sync':
$state->setSyncStatus(CLIENT_SYNC_STARTED);
Horde::logMessage('SyncML['. session_id() .']: syncStatus(client sync started) ' . $state->getSyncStatus(), __FILE__, __LINE__, PEAR_LOG_DEBUG);
break;
}
break;
default:
// <SyncML><SyncBody><Command><...>
$this->_currentCommand->startElement($uri, $element, $attrs);
break;
}
}
function endElement($uri, $element)
{
$state =& $_SESSION['SyncML.state'];
switch ($this->_xmlStack) {
case 2:
// </SyncBody></SyncML>
Horde::logMessage('SyncML['. session_id() .']: package ----------------------- done', __FILE__, __LINE__, PEAR_LOG_DEBUG);
if ($state->getAlert222Received() == true) {
// the Funambol specialty
if ($state->getSyncStatus() == CLIENT_SYNC_FINNISHED) {
$state->setSyncStatus(CLIENT_SYNC_ACKNOWLEDGED);
}
$state->setAlert222Received(false);
}
if ($state->needDeviceInfo()) $this->outputGetRequest();
// send the sync reply
// we do still have some data to send OR
// we should reply to the Sync command
if ($state->getSyncStatus() > CLIENT_SYNC_FINNISHED && $state->getSyncStatus() < SERVER_SYNC_FINNISHED) {
$sync = new Horde_SyncML_Command_Sync();
$this->_currentCmdID = $sync->syncToClient($this->_currentCmdID, $this->_output);
}
// send the Final tag if possible
#if ($state->getSyncStatus() != SERVER_SYNC_DATA_PENDING && $state->getSyncStatus() != CLIENT_SYNC_STARTED) {
if ($state->getSyncStatus() >= SERVER_SYNC_FINNISHED || $state->_sendFinal) {
$final = new Horde_SyncML_Command_Final();
$this->_currentCmdID = $final->output($this->_currentCmdID, $this->_output);
}
$this->_output->endElement($uri, $element);
Horde::logMessage('SyncML['. session_id() .']: syncStatus = '. $state->getSyncStatus() .', actionCommands = '.
($this->_actionCommands ? 'True' : 'False'), __FILE__, __LINE__, PEAR_LOG_DEBUG);
if (!$this->_actionCommands && $state->getSyncStatus() == SERVER_SYNC_FINNISHED) {
// this packet did not contain any real actions, just status and map.
// This means, we're through! The session can be closed and
// the Anchors saved for the next Sync
Horde::logMessage('SyncML['. session_id() .']: sync' . session_id() . ' completed successfully!',
__FILE__, __LINE__, PEAR_LOG_INFO);
$state->writeSyncSummary();
$log = $state->getLog();
$s="";
foreach ($log as $k => $v) {
$s .= " $k=$v";
}
if (strlen(trim($s)) == 0) {
$s = ' Both parties were already in sync';
}
Horde::logMessage('SyncML['. session_id() .']: summary:' . $s, __FILE__, __LINE__, PEAR_LOG_INFO);
# Horde::logMessage('SyncML['. session_id() .']: destroying sync session '.session_id(), __FILE__, __LINE__, PEAR_LOG_INFO);
# // session can be closed here!
# session_unset();
# session_destroy();
}
if (!$this->_actionCommands && $state->getSyncStatus() == SERVER_SYNC_ACKNOWLEDGED) {
// this packet did not contain any real actions, just status and map.
// This means, we're through! The session can be closed and
// the Anchors saved for the next Sync
Horde::logMessage('SyncML['. session_id() .']: sync' . session_id() . ' completed successfully!',
__FILE__, __LINE__, PEAR_LOG_INFO);
$state->writeSyncSummary();
$log = $state->getLog();
$s="";
foreach ($log as $k => $v) {
$s .= " $k=$v";
}
if (strlen(trim($s)) == 0) {
$s = ' Both parties were already in sync';
}
Horde::logMessage('SyncML['. session_id() .']: summary:' . $s, __FILE__, __LINE__, PEAR_LOG_INFO);
Horde::logMessage('SyncML['. session_id() .']: destroying sync session '.session_id(), __FILE__, __LINE__, PEAR_LOG_INFO);
// session can be closed here!
session_unset();
session_destroy();
}
break;
case 3:
// </[Command]></SyncBody></SyncML>
$this->_currentCommand->endElement($uri, $element);
switch ($element) {
case 'Final':
$this->_actionCommands = false;
if ($state->getSyncStatus() == CLIENT_SYNC_STARTED) {
if ($state->isAuthorized() &&
($deviceInfo = $state->getClientDeviceInfo()) &&
strtolower($deviceInfo['manufacturer']) == 'funambol'
&& isset($deviceInfo['softwareVersion'])) {
$swversion = $deviceInfo['softwareVersion'];
if ($swversion < 1.0) {
// e.g. Mozilla plugin uses this range
$swversion = $swversion * 10;
}
if (3.0 < $swversion && $swversion < 7.0) {
// We wait for a ALERT_NEXT_MESSAGE from Funambol old clients
Horde::logMessage('SyncML['. session_id()
. "]: Special treatment for Funambol version $swversion activated",
__FILE__, __LINE__, PEAR_LOG_DEBUG);
$state->setSyncStatus(CLIENT_SYNC_FINNISHED);
} else {
$state->setSyncStatus(CLIENT_SYNC_ACKNOWLEDGED);
}
} else {
$state->setSyncStatus(CLIENT_SYNC_ACKNOWLEDGED);
}
} elseif ($state->getSyncStatus() == SERVER_SYNC_FINNISHED) {
$state->setSyncStatus(SERVER_SYNC_ACKNOWLEDGED);
}
$this->_clientSentFinal = true;
Horde::logMessage('SyncML['. session_id() .']: syncStatus(server sync acknowledged) '
. $state->getSyncStatus(), __FILE__, __LINE__, PEAR_LOG_DEBUG);
break;
default:
$this->_currentCmdID = $this->_currentCommand->output($this->_currentCmdID, $this->_output);
break;
}
unset($this->_currentCommand);
break;
default:
// </...></[Command]></SyncBody></SyncML>
$this->_currentCommand->endElement($uri, $element);
break;
}
parent::endElement($uri, $element);
}
function characters($str) {
if (isset($this->_currentCommand)) {
$this->_currentCommand->characters($str);
}
}
function outputGetRequest()
{
$attrs = array();
$state =& $_SESSION['SyncML.state'];
$uri = $state->getURI();
$uriMeta = $state->getURIMeta();
Horde::logMessage('SyncML: PreferedContentTypeClient missing, sending <Get>',
__FILE__, __LINE__, PEAR_LOG_DEBUG);
$this->_output->startElement($uri, 'Get', $attrs);
$this->_output->startElement($uri, 'CmdID', $attrs);
$this->_output->characters($this->_currentCmdID);
$this->_currentCmdID++;
$this->_output->endElement($uri, 'CmdID');
$this->_output->startElement($uri, 'Meta', $attrs);
$this->_output->startElement($uriMeta, 'Type', $attrs);
if (is_a($this->_output, 'XML_WBXML_Encoder')) {
$this->_output->characters('application/vnd.syncml-devinf+wbxml');
} else {
$this->_output->characters('application/vnd.syncml-devinf+xml');
}
$this->_output->endElement($uriMeta, 'Type');
$this->_output->endElement($uri, 'Meta');
$this->_output->startElement($uri, 'Item', $attrs);
$this->_output->startElement($uri, 'Target', $attrs);
$this->_output->startElement($uri, 'LocURI', $attrs);
if ($state->getVersion() == 2) {
$this->_output->characters('./devinf12');
} elseif ($state->getVersion() == 1) {
$this->_output->characters('./devinf11');
} else {
$this->_output->characters('./devinf10');
}
$this->_output->endElement($uri, 'LocURI');
$this->_output->endElement($uri, 'Target');
$this->_output->endElement($uri, 'Item');
$this->_output->endElement($uri, 'Get');
$state->deviceInfoRequested();
}
}

View File

@ -1,167 +0,0 @@
<?php
/**
* eGroupWare - SyncML based on Horde 3
*
* The SyncML_Command class provides a base class for handling all <SyncBody>
* commands.
*
* A SyncML command is a protocol primitive. Each SyncML command specifies to
* a recipient an individual operation that is to be performed.
*
* The SyncML_Command objects are hooked into the XML parser of the
* SyncML_ContentHandler class and are reponsible for parsing a single command
* inside the SyncBody section of a SyncML message. All actions that must be
* executed for a single SyncML command are handled by these objects, by means
* of the handleCommand() method.
*
*
* Using the PEAR Log class (which need to be installed!)
*
* @link http://www.egroupware.org
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package api
* @subpackage horde
* @author Anthony Mills <amills@pyramid6.com>
* @author Jan Schneider <jan@horde.org>
* @author Joerg Lehrke <jlehrke@noc.de>
* @copyright (c) The Horde Project (http://www.horde.org/)
* @version $Id$
*/
include_once 'Horde/SyncML/State_egw.php';
class Horde_SyncML_Command {
/**
* Name of the command, like 'Put'.
*
* Must be overwritten by a sub class.
*
* @var string
*/
var $_cmdName;
/**
* The command ID (<CmdID>).
*
* @var integer
*/
var $_cmdID;
/**
* Stack for holding the XML elements during creation of the object from
* the XML event flow.
*
* @var array
*/
var $_stack = array();
/**
* Buffer for the parsed character data.
*
* @var string
*/
var $_chars = '';
/**
* Start element handler for the XML parser, delegated from
* SyncML_ContentHandler::startElement().
*
* @param string $uri The namespace URI of the element.
* @param string $element The element tag name.
* @param array $attrs A hash with the element's attributes.
*/
function startElement($uri, $element, $attrs)
{
$this->_stack[] = $element;
}
/**
* End element handler for the XML parser, delegated from
* SyncML_ContentHandler::endElement().
*
* @param string $uri The namespace URI of the element.
* @param string $element The element tag name.
*/
function endElement($uri, $element)
{
if (count($this->_stack) == 2 &&
$element == 'CmdID') {
$this->_cmdID = intval(trim($this->_chars));
}
if (strlen($this->_chars)) {
$this->_chars = '';
}
array_pop($this->_stack);
}
/**
* Character data handler for the XML parser, delegated from
* SyncML_ContentHandler::characters().
*
* @param string $str The data string.
*/
function characters($str)
{
if (isset($this->_chars)) {
$this->_chars .= $str;
} else {
$this->_chars = $str;
}
}
/**
* Returns the command name this instance is reponsible for.
*
* @return string The command name this object is handling.
*/
function getCommandName()
{
return $this->_cmdName;
}
/**
* This method is supposed to implement the actual business logic of the
* command once the XML parsing is complete.
*
* @abstract
*/
function output($currentCmdID, &$output)
{
}
/**
* Attempts to return a concrete Horde_SyncML_Command instance based on
* $command.
*
* @param string $command The type of the concrete
* SyncML_Comment subclass to
* return.
* @param $params Optional Parameter.
*
* @return SyncML_Command The newly created concrete SyncML_Command
* instance, or false on error.
*/
function &factory($command, $params = null)
{
$command = basename($command);
$class = 'Horde_SyncML_Command_' . $command;
if (!class_exists($class)) {
include_once 'Horde/SyncML/Command/' . $command . '.php';
}
if (class_exists($class)) {
$cmd = new $class($params);
if (empty($cmd->_cmdName)) $cmd->_cmdName = $command;
} else {
$msg = 'SyncML: Class definition of ' . $class . ' not found.';
Horde::logMessage($msg, __FILE__, __LINE__, PEAR_LOG_ERR);
require_once 'PEAR.php';
$cmd = PEAR::raiseError($msg);
}
return $cmd;
}
}

View File

@ -1,466 +0,0 @@
<?php
/**
* eGroupWare - SyncML based on Horde 3
*
* The Horde_SyncML_Alert class provides a SyncML implementation of
* the Alert command as defined in SyncML Representation Protocol,
* version 1.1 5.5.2.
*
*
* Using the PEAR Log class (which need to be installed!)
*
* @link http://www.egroupware.org
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package api
* @subpackage horde
* @author Anthony Mills <amills@pyramid6.com>
* @author Joerg Lehrke <jlehrke@noc.de>
* @copyright (c) The Horde Project (http://www.horde.org/)
* @version $Id$
*/
include_once 'Horde/SyncML/State_egw.php';
include_once 'Horde/SyncML/Command.php';
class Horde_SyncML_Command_Alert extends Horde_SyncML_Command {
/**
* Name of the command.
*
* @var string
*/
var $_cmdName = 'Alert';
/**
* The alert type. Should be one of the ALERT_* constants.
*
* @var integer
*/
var $_alert;
/**
* Source database of the Alert command.
*
* @var string
*/
var $_sourceLocURI;
/**
* Target database of the Alert command.
*
* @var string
*/
var $_targetLocURI;
/**
* Optional parameter for the Target database.
*
* @var string
*/
var $_targetLocURIParameters;
/**
* The current time this synchronization happens, from the <Meta><Next>
* element.
*
* @var string
*/
var $_metaAnchorNext;
/**
* The last time when synchronization happened, from the <Meta><Last>
* element.
*
* @var integer
*/
var $_metaAnchorLast;
/**
* The filter expression the client provided
* (e.g. the time range for calendar synchronization)
*
* @var string
*/
var $_filterExpression = '';
/**
* Creates a new instance of Alert.
*/
function Horde_SyncML_Command_Alert($alert = null)
{
if ($alert != null) {
$this->_alert = $alert;
}
}
function output($currentCmdID, &$output)
{
global $registry;
$attrs = array();
$state = &$_SESSION['SyncML.state'];
// Handle unauthorized first.
if (!$state->isAuthorized()) {
$status = new Horde_SyncML_Command_Status(RESPONSE_INVALID_CREDENTIALS, 'Alert');
$status->setCmdRef($this->_cmdID);
$currentCmdID = $status->output($currentCmdID, $output);
return $currentCmdID;
}
$type = $this->_targetLocURI;
$clientAnchorNext = $this->_metaAnchorNext;
if ($this->_alert == ALERT_TWO_WAY ||
$this->_alert == ALERT_ONE_WAY_FROM_CLIENT ||
$this->_alert == ALERT_ONE_WAY_FROM_SERVER) {
// Check if we have information about previous sync.
$info = $state->getSyncSummary($this->_targetLocURI);
if (is_a($info, 'DataTreeObject')) {
$x = $info->get('ClientAnchor');
$clientlast = $x[$type];
$x = $info->get('ServerAnchor');
$serverAnchorLast = $x[$type];
} elseif (is_array($info)) {
$clientlast = $info['ClientAnchor'];
$serverAnchorLast = $info['ServerAnchor'];
} else {
$clientlast = false;
$serverAnchorLast = 0;
}
$state->setServerAnchorLast($type, $serverAnchorLast);
if ($clientlast !== false){
// Info about previous successful sync sessions found.
Horde::logMessage('SyncML: Previous sync found for target ' . $type
. '; client timestamp: ' . $clientlast,
__FILE__, __LINE__, PEAR_LOG_DEBUG);
// Check if anchor sent from client matches our own stored
// data.
if ($clientlast == $this->_metaAnchorLast) {
// Last sync anchors match, TwoWaySync will do.
$anchormatch = true;
Horde::logMessage('SyncML: Anchor timestamps match, TwoWaySync possible. Syncing data since '
. date('Y-m-d H:i:s', $serverAnchorLast),
__FILE__, __LINE__, PEAR_LOG_DEBUG);
} else {
// Server and client have different anchors, enforce
// SlowSync/RefreshSync
Horde::logMessage('SyncML: Client requested sync with anchor timestamp '
. $this->_metaAnchorLast
. ' but server has recorded timestamp '
. $clientlast . '. Enforcing SlowSync',
__FILE__, __LINE__, PEAR_LOG_INFO);
$anchormatch = false;
$clientlast = 0;
}
} else {
// No info about previous sync, use SlowSync or RefreshSync.
Horde::logMessage('SyncML: No info about previous syncs found for device ' .
$state->getSourceURI() . ' and target ' . $type,
__FILE__, __LINE__, PEAR_LOG_DEBUG);
$clientlast = 0;
$serverAnchorLast = 0;
$anchormatch = false;
}
} else {
// SlowSync requested, no anchor check required.
$anchormatch = true;
}
// Determine sync type and status response code.
Horde::logMessage("SyncML: Alert " . $this->_alert, __FILE__, __LINE__, PEAR_LOG_DEBUG);
switch ($this->_alert) {
case ALERT_NEXT_MESSAGE:
$state->setAlert222Received(true);
case ALERT_RESULT_ALERT:
case ALERT_NO_END_OF_DATA:
// Nothing to do on our side
$status = new Horde_SyncML_Command_Status(RESPONSE_OK, 'Alert');
$status->setCmdRef($this->_cmdID);
if ($this->_sourceLocURI != null) {
$status->setSourceRef($this->_sourceLocURI);
}
if ($this->_targetLocURI != null) {
$status->setTargetRef((isset($this->_targetLocURIParameters) ? $this->_targetLocURI.'?/'.$this->_targetLocURIParameters : $this->_targetLocURI));
}
if ($this->_alert == ALERT_NEXT_MESSAGE) {
if ($this->_sourceLocURI != null) {
$status->setItemSourceLocURI($this->_sourceLocURI);
}
if ($this->_targetLocURI != null) {
$status->setItemTargetLocURI(isset($this->_targetLocURIParameters) ? $this->_targetLocURI.'?/'.$this->_targetLocURIParameters : $this->_targetLocURI);
}
}
$currentCmdID = $status->output($currentCmdID, $output);
return $currentCmdID;
case ALERT_TWO_WAY:
if ($anchormatch) {
$synctype = ALERT_TWO_WAY;
$response = RESPONSE_OK;
} else {
$synctype = ALERT_SLOW_SYNC;
$response = RESPONSE_REFRESH_REQUIRED;
}
break;
case ALERT_SLOW_SYNC:
$synctype = ALERT_SLOW_SYNC;
$response = $anchormatch ? RESPONSE_OK : RESPONSE_REFRESH_REQUIRED;
break;
case ALERT_ONE_WAY_FROM_CLIENT:
if ($anchormatch) {
$synctype = ALERT_ONE_WAY_FROM_CLIENT;
$response = RESPONSE_OK;
} else {
$synctype = ALERT_REFRESH_FROM_CLIENT;
$response = RESPONSE_REFRESH_REQUIRED;
}
break;
case ALERT_REFRESH_FROM_CLIENT:
$synctype = ALERT_REFRESH_FROM_CLIENT;
$response = $anchormatch ? RESPONSE_OK : RESPONSE_REFRESH_REQUIRED;
// We will erase the current server content,
// then we can add the client's contents.
$hordeType = $state->getHordeType($this->_targetLocURI);
$state->setTargetURI($this->_targetLocURI);
$deletes = $state->getClientItems();
if (is_array($deletes)) {
foreach ($deletes as $delete) {
$registry->call($hordeType . '/delete', array($delete));
}
Horde::logMessage("SyncML: RefreshFromClient " . count($deletes) . " entries deleted for $hordeType", __FILE__, __LINE__, PEAR_LOG_DEBUG);
}
$anchormatch = false;
break;
case ALERT_ONE_WAY_FROM_SERVER:
if ($anchormatch) {
$synctype = ALERT_ONE_WAY_FROM_SERVER;
$response = RESPONSE_OK;
} else {
$synctype = ALERT_REFRESH_FROM_SERVER;
$response = RESPONSE_REFRESH_REQUIRED;
}
break;
case ALERT_REFRESH_FROM_SERVER:
$synctype = ALERT_REFRESH_FROM_SERVER;
$response = $anchormatch ? RESPONSE_OK : RESPONSE_REFRESH_REQUIRED;
$anchormatch = false;
break;
case ALERT_RESUME:
// @TODO: Suspend and Resume is not supported yet
$synctype = ALERT_SLOW_SYNC;
$response = RESPONSE_REFRESH_REQUIRED;
break;
default:
// We can't handle this one
Horde::logMessage('SyncML: Unknown sync type ' . $this->_alert,
__FILE__, __LINE__, PEAR_LOG_ERR);
$status = new Horde_SyncML_Command_Status(RESPONSE_BAD_REQUEST, 'Alert');
$status->setCmdRef($this->_cmdID);
if ($this->_sourceLocURI != null) {
$status->setSourceRef($this->_sourceLocURI);
}
if ($this->_targetLocURI != null) {
$status->setTargetRef((isset($this->_targetLocURIParameters) ? $this->_targetLocURI.'?/'.$this->_targetLocURIParameters : $this->_targetLocURI));
}
$currentCmdID = $status->output($currentCmdID, $output);
return $currentCmdID;
}
// Now set interval to retrieve server changes from, defined by
// ServerAnchor [Last,Next]
if ($synctype != ALERT_TWO_WAY &&
$synctype != ALERT_ONE_WAY_FROM_CLIENT &&
$synctype != ALERT_ONE_WAY_FROM_SERVER) {
$serverAnchorLast = 0;
if (isset($GLOBALS['egw_info']['user']['preferences']['syncml']['slowsync_ignore_map']) &&
$GLOBALS['egw_info']['user']['preferences']['syncml']['slowsync_ignore_map']
|| !$anchormatch) {
// Erase existing map
$state->removeAllUID($this->_targetLocURI);
}
}
// Now create the actual SyncML_Sync object, if it doesn't exist yet.
$sync = &$state->getSync($this->_targetLocURI);
if (!$sync) {
Horde::logMessage('SyncML: Creating SyncML_Sync object for target '
. $this->_targetLocURI . '; sync type ' . $synctype,
__FILE__, __LINE__, PEAR_LOG_DEBUG);
$sync = &Horde_SyncML_Sync::factory($synctype);
$state->clearConflictItems($this->_targetLocURI);
}
$sync->setTargetLocURI($this->_targetLocURI);
$sync->setSourceLocURI($this->_sourceLocURI);
$sync->setLocName($state->getLocName()); // We need it for conflict handling
$sync->setsyncType($synctype);
$sync->setFilterExpression($this->_filterExpression);
$state->setSync($this->_targetLocURI, $sync);
$hordeType = $state->getHordeType($this->_targetLocURI);
$changes =& $registry->call($hordeType. '/listBy',
array('action' => 'modify',
'timestamp' => $serverAnchorLast,
'type' => $this->_targetLocURI,
'filter' => $this->_filterExpression));
$state->setChangedItems($this->_targetLocURI, $changes);
// Store client's Next Anchor in State and
// set server's Next Anchor. After successful sync
// this is then written to persistence for negotiation of
// further syncs.
$state->setClientAnchorNext($type, $this->_metaAnchorNext);
$serverAnchorNext = time();
$state->setServerAnchorNext($type, $serverAnchorNext);
$status = new Horde_SyncML_Command_Status($response, 'Alert');
$status->setCmdRef($this->_cmdID);
if ($this->_sourceLocURI != null) {
$status->setSourceRef($this->_sourceLocURI);
}
if ($this->_targetLocURI != null) {
$status->setTargetRef((isset($this->_targetLocURIParameters) ? $this->_targetLocURI.'?/'.$this->_targetLocURIParameters : $this->_targetLocURI));
}
// Mirror Next Anchor from client back to client.
if (isset($this->_metaAnchorNext)) {
$status->setItemDataAnchorNext($this->_metaAnchorNext);
}
// Mirror Last Anchor from client back to client.
if (isset($this->_metaAnchorLast)) {
$status->setItemDataAnchorLast($this->_metaAnchorLast);
}
$currentCmdID = $status->output($currentCmdID, $output);
$output->startElement($state->getURI(), 'Alert', $attrs);
$output->startElement($state->getURI(), 'CmdID', $attrs);
$chars = $currentCmdID;
$output->characters($chars);
$output->endElement($state->getURI(), 'CmdID');
$output->startElement($state->getURI(), 'Data', $attrs);
$chars = $synctype;
$output->characters($chars);
$output->endElement($state->getURI(), 'Data');
$output->startElement($state->getURI(), 'Item', $attrs);
if ($this->_sourceLocURI != null) {
$output->startElement($state->getURI(), 'Target', $attrs);
$output->startElement($state->getURI(), 'LocURI', $attrs);
$chars = $this->_sourceLocURI;
$output->characters($chars);
$output->endElement($state->getURI(), 'LocURI');
$output->endElement($state->getURI(), 'Target');
}
if ($this->_targetLocURI != null) {
$output->startElement($state->getURI(), 'Source', $attrs);
$output->startElement($state->getURI(), 'LocURI', $attrs);
$chars = (isset($this->_targetLocURIParameters) ? $this->_targetLocURI.'?/'.$this->_targetLocURIParameters : $this->_targetLocURI);
$output->characters($chars);
$output->endElement($state->getURI(), 'LocURI');
$output->endElement($state->getURI(), 'Source');
}
$output->startElement($state->getURI(), 'Meta', $attrs);
$output->startElement($state->getURIMeta(), 'Anchor', $attrs);
$output->startElement($state->getURIMeta(), 'Last', $attrs);
$chars = $state->getServerAnchorLast($type);
$output->characters($chars ? $chars : '0'); // Some devices don't like empty anchors
$output->endElement($state->getURIMeta(), 'Last');
$output->startElement($state->getURIMeta(), 'Next', $attrs);
$chars = $state->getServerAnchorNext($type);
$output->characters($chars);
$output->endElement($state->getURIMeta(), 'Next');
$output->endElement($state->getURIMeta(), 'Anchor');
$output->endElement($state->getURI(), 'Meta');
$output->endElement($state->getURI(), 'Item');
$output->endElement($state->getURI(), 'Alert');
// Final packet of this message
$state->_sendFinal = true;
$currentCmdID++;
return $currentCmdID;
}
/**
* End element handler for the XML parser, delegated from
* SyncML_ContentHandler::endElement().
*
* @param string $uri The namespace URI of the element.
* @param string $element The element tag name.
*/
function endElement($uri, $element)
{
switch (count($this->_stack)) {
case 2:
if ($element == 'Data') {
$this->_alert = intval(trim($this->_chars));
}
break;
case 4:
if ($element == 'LocURI') {
switch ($this->_stack[2]) {
case 'Source':
$this->_sourceLocURI = trim($this->_chars);
break;
case 'Target':
$targetLocURIData = explode('?/',trim($this->_chars));
$this->_targetLocURI = $targetLocURIData[0];
if (isset($targetLocURIData[1])) {
$this->_targetLocURIParameters = $targetLocURIData[1];
}
break;
}
}
break;
case 5:
switch ($element) {
case 'Next':
$this->_metaAnchorNext = trim($this->_chars);
break;
case 'Last':
$this->_metaAnchorLast = trim($this->_chars);
break;
}
break;
case 7:
if ($element == 'Data'
&& $this->_stack[2] == 'Target'
&& $this->_stack[3] == 'Filter'
&& $this->_stack[4] == 'Record'
&& $this->_stack[5] == 'Item') {
$this->_filterExpression = trim($this->_chars);
}
break;
}
parent::endElement($uri, $element);
}
}

View File

@ -1,41 +0,0 @@
<?php
/**
* eGroupWare - SyncML based on Horde 3
*
* The Horde_SyncML_Command_Final class.
*
*
* Using the PEAR Log class (which need to be installed!)
*
* @link http://www.egroupware.org
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package api
* @subpackage horde
* @author Anthony Mills <amills@pyramid6.com>
* @copyright (c) The Horde Project (http://www.horde.org/)
* @version $Id$
*/
include_once 'Horde/SyncML/Command.php';
class Horde_SyncML_Command_Final extends Horde_SyncML_Command {
/**
* Name of the command.
*
* @var string
*/
var $_cmdName = 'Final';
function output($currentCmdID, &$output)
{
$state = $_SESSION['SyncML.state'];
$attrs = array();
$output->startElement($state->getURI(), 'Final', $attrs);
$output->endElement($state->getURI(), 'Final');
return $currentCmdID;
}
}

View File

@ -1,247 +0,0 @@
<?php
/**
* eGroupWare - SyncML based on Horde 3
*
*
* Using the PEAR Log class (which need to be installed!)
*
* @link http://www.egroupware.org
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package api
* @subpackage horde
* @author Anthony Mills <amills@pyramid6.com>
* @author Karsten Fourmont <fourmont@gmx.de>
* @author Joerg Lehrke <jlehrke@noc.de>
* @copyright (c) The Horde Project (http://www.horde.org/)
* @version $Id$
*/
include_once 'Horde/SyncML/State.php';
include_once 'Horde/SyncML/Command.php';
include_once 'Horde/SyncML/Command/Results.php';
class Horde_SyncML_Command_Get extends Horde_SyncML_Command {
/**
* Name of the command.
*
* @var string
*/
var $_cmdName = 'Get';
function output($currentCmdID, &$output)
{
$state = $_SESSION['SyncML.state'];
if ($state->getVersion() == 2) {
$ref = './devinf12';
} elseif ($state->getVersion() == 1) {
$ref = './devinf11';
} else {
$ref = './devinf10';
}
$status = new Horde_SyncML_Command_Status((($state->isAuthorized()) ? RESPONSE_OK : RESPONSE_INVALID_CREDENTIALS), $this->_cmdName);
$status->setCmdRef($this->_cmdID);
$status->setTargetRef($ref);
$currentCmdID = $status->output($currentCmdID, $output);
if ($state->isAuthorized()) {
$attrs = array();
$output->startElement($state->getURI(), 'Results', $attrs);
$output->startElement($state->getURI(), 'CmdID', $attrs);
$chars = $currentCmdID;
$output->characters($chars);
$output->endElement($state->getURI(), 'CmdID');
$output->startElement($state->getURI(), 'MsgRef', $attrs);
$chars = $state->getMsgID();
$output->characters($chars);
$output->endElement($state->getURI(), 'MsgRef');
$output->startElement($state->getURI(), 'CmdRef', $attrs);
$chars = $this->_cmdID;
$output->characters($chars);
$output->endElement($state->getURI(), 'CmdRef');
$output->startElement($state->getURI(), 'Meta', $attrs);
$output->startElement($state->getURIMeta(), 'Type', $attrs);
if (is_a($output, 'XML_WBXML_Encoder')) {
$output->characters(MIME_SYNCML_DEVICE_INFO_WBXML);
} else {
$output->characters(MIME_SYNCML_DEVICE_INFO_XML);
}
$output->endElement($state->getURIMeta(), 'Type');
$output->endElement($state->getURI(), 'Meta');
$output->startElement($state->getURI(), 'Item', $attrs);
$output->startElement($state->getURI(), 'Source', $attrs);
$output->startElement($state->getURI(), 'LocURI', $attrs);
$output->characters($ref);
$output->endElement($state->getURI(), 'LocURI');
$output->endElement($state->getURI(), 'Source');
$output->startElement($state->getURI(), 'Data', $attrs);
$output->startElement($state->getURIDevInf() , 'DevInf', $attrs);
$output->startElement($state->getURIDevInf() , 'VerDTD', $attrs);
if ($state->getVersion() == 2) {
$output->characters('1.2');
} elseif($state->getVersion() == 1) {
$output->characters('1.1');
} else {
$output->characters('1.0');
}
$output->endElement($state->getURIDevInf() , 'VerDTD', $attrs);
$output->startElement($state->getURIDevInf() , 'Man', $attrs);
$output->characters('www.egroupware.org');
$output->endElement($state->getURIDevInf() , 'Man', $attrs);
$output->startElement($state->getURIDevInf() , 'Mod', $attrs);
$output->characters('DS Server');
$output->endElement($state->getURIDevInf() , 'Mod', $attrs);
$output->startElement($state->getURIDevInf() , 'OEM', $attrs);
$output->characters('-');
$output->endElement($state->getURIDevInf() , 'OEM', $attrs);
$output->startElement($state->getURIDevInf() , 'FwV', $attrs);
$output->characters('-');
$output->endElement($state->getURIDevInf() , 'FwV', $attrs);
$output->startElement($state->getURIDevInf() , 'SwV', $attrs);
$output->characters('1.7.x');
$output->endElement($state->getURIDevInf() , 'SwV', $attrs);
$output->startElement($state->getURIDevInf() , 'HwV', $attrs);
$output->characters('-');
$output->endElement($state->getURIDevInf() , 'HwV', $attrs);
$output->startElement($state->getURIDevInf() , 'DevID', $attrs);
$output->characters($_SERVER['HTTP_HOST']);
$output->endElement($state->getURIDevInf() , 'DevID', $attrs);
$output->startElement($state->getURIDevInf() , 'DevTyp', $attrs);
$output->characters('server');
$output->endElement($state->getURIDevInf() , 'DevTyp', $attrs);
$output->startElement($state->getURIDevInf() , 'UTC', $attrs);
$output->endElement($state->getURIDevInf() , 'UTC', $attrs);
$output->startElement($state->getURIDevInf() , 'SupportNumberOfChanges', $attrs);
$output->endElement($state->getURIDevInf() , 'SupportNumberOfChanges', $attrs);
$output->startElement($state->getURIDevInf() , 'SupportLargeObjs', $attrs);
$output->endElement($state->getURIDevInf() , 'SupportLargeObjs', $attrs);
$this->_writeDataStore('notes', 'text/x-vnote', '1.1', $output,
array('text/plain' => '1.0'));
$this->_writeDataStore('contacts', 'text/vcard', '3.0', $output,
array('text/x-vcard' => '2.1'));
$this->_writeDataStore('card', 'text/vcard', '3.0', $output,
array('text/x-vcard' => '2.1'));
$this->_writeDataStore('tasks', 'text/calendar', '2.0', $output,
array('text/x-vcalendar' => '1.0'));
$this->_writeDataStore('jobs', 'text/calendar', '2.0', $output,
array('text/x-vcalendar' => '1.0'));
$this->_writeDataStore('calendar', 'text/calendar', '2.0', $output,
array('text/x-vcalendar' => '1.0'));
$this->_writeDataStore('events', 'text/calendar', '2.0', $output,
array('text/x-vcalendar' => '1.0'));
$this->_writeDataStore('caltasks', 'text/calendar', '2.0', $output,
array('text/x-vcalendar' => '1.0'));
// Funambol special Datastore
$this->_writeDataStore('configuration', 'text/plain', '1.0', $output);
$output->endElement($state->getURIDevInf() , 'DevInf', $attrs);
$output->endElement($state->getURI(), 'Data');
$output->endElement($state->getURI(), 'Item');
$output->endElement($state->getURI(), 'Results');
/*
$output->startElement($state->getURIDevInf() , 'Ext', $attrs);
$output->startElement($state->getURIDevInf() , 'XNam', $attrs);
$output->characters('X-funambol-smartslow');
$output->endElement($state->getURIDevInf() , 'XNam', $attrs);
$output->endElement($state->getURIDevInf() , 'Ext', $attrs);
*/
$currentCmdID++;
}
return $currentCmdID;
}
/**
* Writes DevInf data for one DataStore.
*
* @param string $sourceref: data for SourceRef element.
* @param string $mimetype: data for &lt;(R|T)x-Pref&gt;&lt;CTType&gt;
* @param string $version: data for &lt;(R|T)x-Pref&gt;&lt;VerCT&gt;
* @param string &$output contenthandler that will received the output.
* @param array $additionaltypes: array of additional types for Tx and Rx;
* format array('text/vcard' => '3.0')
*/
function _writeDataStore($sourceref, $mimetype, $version, &$output,
$additionaltypes = false)
{
$attrs = array();
$state = &$_SESSION['SyncML.state'];
$output->startElement($state->getURIDevInf() , 'DataStore', $attrs);
$output->startElement($state->getURIDevInf() , 'SourceRef', $attrs);
$output->characters($sourceref);
$output->endElement($state->getURIDevInf() , 'SourceRef', $attrs);
$output->startElement($state->getURIDevInf() , 'DisplayName', $attrs);
$output->characters($sourceref);
$output->endElement($state->getURIDevInf() , 'DisplayName', $attrs);
$output->startElement($state->getURIDevInf() , 'MaxGUIDSize', $attrs);
$output->characters(255);
$output->endElement($state->getURIDevInf() , 'MaxGUIDSize', $attrs);
$output->startElement($state->getURIDevInf() , 'Rx-Pref', $attrs);
$output->startElement($state->getURIDevInf() , 'CTType', $attrs);
$output->characters($mimetype);
$output->endElement($state->getURIDevInf() , 'CTType', $attrs);
$output->startElement($state->getURIDevInf() , 'VerCT', $attrs);
$output->characters($version);
$output->endElement($state->getURIDevInf() , 'VerCT', $attrs);
$output->endElement($state->getURIDevInf() , 'Rx-Pref', $attrs);
if (is_array($additionaltypes)) {
foreach ($additionaltypes as $ct => $ctver){
$output->startElement($state->getURIDevInf() , 'Rx', $attrs);
$output->startElement($state->getURIDevInf() , 'CTType', $attrs);
$output->characters($ct);
$output->endElement($state->getURIDevInf() , 'CTType', $attrs);
$output->startElement($state->getURIDevInf() , 'VerCT', $attrs);
$output->characters($ctver);
$output->endElement($state->getURIDevInf() , 'VerCT', $attrs);
$output->endElement($state->getURIDevInf() , 'Rx', $attrs);
}
}
$output->startElement($state->getURIDevInf() , 'Tx-Pref', $attrs);
$output->startElement($state->getURIDevInf() , 'CTType', $attrs);
$output->characters($mimetype);
$output->endElement($state->getURIDevInf() , 'CTType', $attrs);
$output->startElement($state->getURIDevInf() , 'VerCT', $attrs);
$output->characters($version);
$output->endElement($state->getURIDevInf() , 'VerCT', $attrs);
$output->endElement($state->getURIDevInf() , 'Tx-Pref', $attrs);
if (is_array($additionaltypes)) {
foreach ($additionaltypes as $ct => $ctver){
$output->startElement($state->getURIDevInf() , 'Tx', $attrs);
$output->startElement($state->getURIDevInf() , 'CTType', $attrs);
$output->characters($ct);
$output->endElement($state->getURIDevInf() , 'CTType', $attrs);
$output->startElement($state->getURIDevInf() , 'VerCT', $attrs);
$output->characters($ctver);
$output->endElement($state->getURIDevInf() , 'VerCT', $attrs);
$output->endElement($state->getURIDevInf() , 'Tx', $attrs);
}
}
$output->startElement($state->getURIDevInf() , 'SyncCap', $attrs);
// We support all sync Types from 1-6: two way, slow, refresh|update
// from client|server
for ($i = 1; $i <= 6; ++$i) {
$output->startElement($state->getURIDevInf(), 'SyncType', $attrs);
$output->characters($i);
$output->endElement($state->getURIDevInf(), 'SyncType', $attrs);
}
$output->endElement($state->getURIDevInf() , 'SyncCap', $attrs);
$output->endElement($state->getURIDevInf() , 'DataStore', $attrs);
}
}

View File

@ -1,141 +0,0 @@
<?php
/**
* eGroupWare - SyncML based on Horde 3
*
* The Horde_SyncML_Map class provides a SyncML implementation of
* the Map command as defined in SyncML Representation Protocol,
* version 1.0.1 5.5.8.
*
*
* Using the PEAR Log class (which need to be installed!)
*
* @link http://www.egroupware.org
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package api
* @subpackage horde
* @author Karsten Fourmont <fourmont@gmx.de>
* @copyright (c) The Horde Project (http://www.horde.org/)
* @version $Id$
*/
include_once 'Horde/SyncML/State.php';
include_once 'Horde/SyncML/Command.php';
class Horde_SyncML_Command_Map extends Horde_SyncML_Command {
/**
* Name of the command.
*
* @var string
*/
var $_cmdName = 'Map';
/**
* Source database of the Map command.
*
* @var string
*/
var $_sourceLocURI;
/**
* Target database of the Map command.
*
* @var string
*/
var $_targetLocURI;
/**
* Recipient map item specifier.
*
* @var string
*/
var $_mapTarget;
/**
* Originator map item specifier.
*
* @var string
*/
var $_mapSource;
function output($currentCmdID, &$output)
{
$attrs = array();
$state = $_SESSION['SyncML.state'];
$status = new Horde_SyncML_Command_Status($state->isAuthorized() ? RESPONSE_OK : RESPONSE_INVALID_CREDENTIALS, 'Map');
$status->setCmdRef($this->_cmdID);
if ($this->_sourceLocURI != null) {
$status->setSourceRef($this->_sourceLocURI);
}
if ($this->_targetLocURI != null) {
$status->setTargetRef($this->_targetLocURI);
}
$currentCmdID = $status->output($currentCmdID, $output);
return $currentCmdID;
}
function startElement($uri, $element, $attrs)
{
parent::startElement($uri, $element, $attrs);
if (count($this->_stack) == 2 &&
$element == 'MapItem') {
unset($this->_mapTarget);
unset($this->_mapSource);
}
}
function endElement($uri, $element)
{
$state = &$_SESSION['SyncML.state'];
switch (count($this->_stack)) {
case 2:
if ($element == 'MapItem') {
$sync = $state->getSync($this->_targetLocURI);
if (!$state->isAuthorized()) {
Horde::logMessage('SyncML: Not Authorized in the middle of MapItem!', __FILE__, __LINE__, PEAR_LOG_ERR);
} else {
Horde::logMessage("SyncML: creating Map for source=" .
$this->_mapSource . " and target=" . $this->_mapTarget, __FILE__, __LINE__, PEAR_LOG_DEBUG);
// Overwrite existing data by removing it first:
$ts = $state->getServerAnchorNext($this->_targetLocURI);
$r = $state->setUID($this->_targetLocURI, $this->_mapSource, $this->_mapTarget, $ts);
if (is_a($r, 'PEAR_Error')) {
Horde::logMessage('SyncML: PEAR Error: ' . $r->getMessage(), __FILE__, __LINE__, PEAR_LOG_ERR);
return false;
}
}
}
break;
case 3:
if ($element == 'LocURI') {
if ($this->_stack[1] == 'Source') {
$this->_sourceLocURI = trim($this->_chars);
} elseif ($this->_stack[1] == 'Target') {
$targetLocURIData = explode('?/',trim($this->_chars));
$this->_targetLocURI = $targetLocURIData[0];
}
}
break;
case 4:
if ($element == 'LocURI') {
if ($this->_stack[2] == 'Source') {
$this->_mapSource = trim($this->_chars);
} elseif ($this->_stack[2] == 'Target') {
$this->_mapTarget = trim($this->_chars);
}
}
break;
}
parent::endElement($uri, $element);
}
}

View File

@ -1,364 +0,0 @@
<?php
/**
* eGroupWare - SyncML based on Horde 3
*
*
* Using the PEAR Log class (which need to be installed!)
*
* @link http://www.egroupware.org
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package api
* @subpackage horde
* @author Anthony Mills <amills@pyramid6.com>
* @author Joerg Lehrke <jlehrke@noc.de>
* @copyright (c) The Horde Project (http://www.horde.org/)
* @version $Id$
*/
include_once 'Horde/SyncML/State.php';
include_once 'Horde/SyncML/Command.php';
class Horde_SyncML_Command_Put extends Horde_SyncML_Command {
/**
* Name of the command.
*
* @var string
*/
var $_cmdName = 'Put';
/**
* @var string $_manufacturer
*/
var $_manufacturer;
/**
* @var string $_model
*/
var $_model;
/**
* @var string $_oem
*/
var $_oem;
/**
* @var array $_deviceInfo
*/
var $_deviceInfo;
/**
* @var string $_softwareVersion
*/
var $_softwareVersion;
function endElement($uri, $element) {
switch (count($this->_stack)) {
case 5:
switch ($element) {
case 'DataStore':
$this->_deviceInfo['dataStore'][$this->_sourceReference] = array (
'maxGUIDSize' => $this->_maxGUIDSize,
'rxPreference' => $this->_rxPreference,
'txPreference' => $this->_txPreference,
'syncCapabilities' => $this->_syncCapabilities,
'properties' => $this->_properties,
);
break;
case 'DevID':
$this->_deviceInfo['deviceID'] = trim($this->_chars);
break;
case 'DevTyp':
$this->_deviceInfo['deviceType'] = trim($this->_chars);
break;
case 'FwV':
$this->_deviceInfo['firmwareVersion'] = trim($this->_chars);
break;
case 'HwV':
$this->_deviceInfo['hardwareVersion'] = trim($this->_chars);
break;
case 'Man':
$this->_deviceInfo['manufacturer'] = trim($this->_chars);
break;
case 'Mod':
$this->_deviceInfo['model'] = trim($this->_chars);
break;
case 'OEM':
$this->_deviceInfo['oem'] = trim($this->_chars);
break;
case 'SwV':
$this->_deviceInfo['softwareVersion'] = trim($this->_chars);
break;
case 'SupportLargeObjs':
$this->_deviceInfo['supportLargeObjs'] = true;
break;
case 'SupportNumberOfChanges':
$this->_deviceInfo['supportNumberOfChanges'] = true;
break;
case 'UTC':
$this->_deviceInfo['UTC'] = true;
break;
case 'VerDTD':
$this->_deviceInfo['DTDVersion'] = trim($this->_chars);
break;
}
break;
case 6:
switch($element) {
case 'MaxGUIDSize':
$this->_maxGUIDSize = trim($this->_chars);
break;
case 'Rx-Pref':
$this->_rxPreference = array(
'contentType' => $this->_contentType,
'contentVersion' => $this->_contentVersion,
);
break;
case 'SourceRef':
$this->_sourceReference = strtolower(trim($this->_chars));
break;
case 'Tx-Pref':
$this->_txPreference = array(
'contentType' => $this->_contentType,
'contentVersion' => $this->_contentVersion,
);
break;
}
break;
case 7:
switch($element) {
case 'CTType':
$this->_contentType = trim($this->_chars);
if (substr($this->_contentType, 0, 14) == "text/x-s4j-sif")
{
// workaround a little bug in sync4j for mobile v3.1.3 (and possibly others)
// where the content-type is set to just one value regardless of
// the source... this further leads to a failure to send updates
// by the server since it does not know how to convert say tasks to text/x-s4j-sifc
// (it should be text/x-s4j-sift).
switch ($this->_sourceReference)
{
case 'contact':
case 'card':
if ($this->_contentType != "text/x-s4j-sifc")
{
error_log("forcing 'contact' content type to 'text/x-s4j-sifc' instead of '".$this->_contentType."'");
$this->_contentType = "text/x-s4j-sifc";
}
break;
case 'calendar':
case 'appointment':
if ($this->_contentType != "text/x-s4j-sife")
{
error_log("forcing 'calendar' content type to 'text/x-s4j-sife' instead of '".$this->_contentType."'");
$this->_contentType = "text/x-s4j-sife";
}
break;
case 'task':
if ($this->_contentType != "text/x-s4j-sift")
{
error_log("forcing 'task' content type to 'text/x-s4j-sift' instead of '".$this->_contentType."'");
$this->_contentType = "text/x-s4j-sift";
}
break;
case 'note':
if ($this->_contentType != "text/x-s4j-sifn")
{
error_log("forcing 'note' content type to 'text/x-s4j-sifn' instead of '".$this->_contentType."'");
$this->_contentType = "text/x-s4j-sifn";
}
break;
default:
#error_log("Leaving ContentType='".$this->_contentType."' as is for source '".$this->_sourceReference."'");
break;
}
}
break;
case 'SyncType':
$this->_syncCapabilities[] = trim($this->_chars);
break;
case 'VerCT':
$this->_contentVersion = trim($this->_chars);
break;
case 'Property':
if (isset($this->_PropName)) {
$this->_properties[$this->_contentType][$this->_contentVersion][$this->_PropName] = array(
'Size' => $this->_PropSize,
'NoTruncate' => $this->_PropNoTruncate,
);
}
break;
}
break;
case 8:
switch($element) {
case 'PropName':
$this->_PropName = trim($this->_chars);
break;
case 'Size':
$this->_PropSize = trim($this->_chars);
break;
case 'NoTruncate':
$this->_PropNoTruncate = true;
break;
}
beak;
}
parent::endElement($uri, $element);
}
function finalizeDeviceInfo()
{
// get some more information about the device from out of band data
$ua = $_SERVER['HTTP_USER_AGENT'];
if (($pos = strpos($ua, 'Funambol'))!== false) {
$this->_deviceInfo['manufacturer'] = 'Funambol';
$this->_deviceInfo['model'] = 'generic';
$this->_deviceInfo['softwareVersion'] = 3.1; // force special treatment
$type = substr($ua, $pos + 9);
if (preg_match("/^(.*) [^\d]*(\d+\.?\d*)[\.|\d]*\s*$/i", $type, $matches)) {
// Funambol uses the hardware Manufacturer we don't care about
$this->_deviceInfo['model'] = trim($matches[1]);
$this->_deviceInfo['softwareVersion'] = floatval($matches[2]);
}
if (!isset($this->_deviceInfo['deviceType'])) {
switch (strtolower(trim($matches[1]))) {
case 'pocket pc plug-in':
$this->_deviceInfo['deviceType'] = 'windowsmobile';
break;
case 'outlook plug-in':
default:
$this->_deviceInfo['deviceType'] = 'workstation';
break;
}
}
}
switch (strtolower($this->_deviceInfo['deviceID'])) {
case 'fmz-thunderbird-plugin':
if (empty($this->_devinceInfo['manufacturer'])) {
$this->_deviceInfo['manufacturer'] = 'Funambol';
}
if (empty($this->_devinceInfo['model'])) {
$this->_deviceInfo['model'] = 'ThunderBird';
}
if (empty($this->_devinceInfo['softwareVersion'])) {
$this->_deviceInfo['softwareVersion'] = '3.0';
}
break;
}
if (preg_match('/Funambol.*/i', $this->_deviceInfo['manufacturer'])) {
$this->_deviceInfo['supportLargeObjs'] = true;
}
switch (strtolower($this->_deviceInfo['manufacturer'])) {
case 'sonyericsson':
case 'sony ericsson':
if (strtolower($this->_deviceInfo['model']) == 'w890i') {
$this->_deviceInfo['supportLargeObjs'] = false;
}
break;
case 'synthesis ag':
foreach ($this->_deviceInfo['dataStore'] as &$ctype) {
$ctype['maxGUIDSize'] = 255;
}
break;
}
}
function output($currentCmdID, &$output ) {
$state = &$_SESSION['SyncML.state'];
$status = new Horde_SyncML_Command_Status((($state->isAuthorized()) ? RESPONSE_OK : RESPONSE_INVALID_CREDENTIALS), $this->_cmdName);
$status->setCmdRef($this->_cmdID);
if ($state->getVersion() == 2) {
$ref = './devinf12';
} elseif ($state->getVersion() == 1) {
$ref = './devinf11';
} else {
$ref = './devinf10';
}
$status->setSourceRef($ref);
if($state->isAuthorized()) {
$this->finalizeDeviceInfo();
if(count((array)$this->_deviceInfo) > 0) {
$devInfo = $state->getClientDeviceInfo();
if (is_array($devInfo['dataStore'])
&& $devInfo['softwareVersion'] == $this->_deviceInfo['softwareVersion']) {
// merge with existing information
$devInfo['dataStore'] =
array_merge($devInfo['dataStore'],
$this->_deviceInfo['dataStore']);
} else {
// new device
$devInfo = $this->_deviceInfo;
}
#Horde::logMessage("SyncML: Put DeviceInfo:\n" . print_r($this->_deviceInfo, true), __FILE__, __LINE__, PEAR_LOG_DEBUG);
$state->setClientDeviceInfo($devInfo);
$state->writeClientDeviceInfo();
}
}
return $status->output($currentCmdID, $output);
}
function startElement($uri, $element, $attrs) {
#Horde::logMessage("SyncML: startElement[" . count($this->_stack) . "] $uri $element", __FILE__, __LINE__, PEAR_LOG_DEBUG);
switch (count($this->_stack)) {
case 4:
switch ($element) {
case 'DataStore':
$this->_properties = array();
break;
}
break;
case 6:
switch ($element) {
case 'Property':
unset($this->_PropName);
$this->_PropSize = -1;
$this->_PropNoTruncate = false;
break;
}
break;
}
parent::startElement($uri, $element, $attrs);
}
}

View File

@ -1,32 +0,0 @@
<?php
/**
* eGroupWare - SyncML based on Horde 3
*
*
* Using the PEAR Log class (which need to be installed!)
*
* @link http://www.egroupware.org
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package api
* @subpackage horde
* @author Anthony Mills <amills@pyramid6.com>
* @copyright (c) The Horde Project (http://www.horde.org/)
* @version $Id$
*/
include_once 'Horde/SyncML/Command.php';
class Horde_SyncML_Command_Replace extends Horde_SyncML_Command {
/**
* Name of the command.
*
* @var string
*/
var $_cmdName = 'Replace';
function output($currentCmdID, &$output)
{
return $currentCmdID;
}
}

View File

@ -1,36 +0,0 @@
<?php
/**
* eGroupWare - SyncML based on Horde 3
*
* The SyncML_Command_Results class provides a SyncML implementation of the
* Results command as defined in SyncML Representation Protocol, version 1.1,
* section 5.5.12.
*
* The Results command is used to return the results of a Search or Get
* command. Currently SyncML_Command_Results behaves the same as
* SyncML_Command_Put. The only results we get is the same DevInf as for the
* Put command.
*
*
* Using the PEAR Log class (which need to be installed!)
*
* @link http://www.egroupware.org
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package api
* @subpackage horde
* @author Anthony Mills <amills@pyramid6.com>
* @copyright (c) The Horde Project (http://www.horde.org/)
* @version $Id$
*/
include_once 'Horde/SyncML/Command/Put.php';
class Horde_SyncML_Command_Results extends Horde_SyncML_Command_Put {
/**
* Name of the command.
*
* @var string
*/
var $_cmdName = 'Results';
}

View File

@ -1,363 +0,0 @@
<?php
/**
* eGroupWare - SyncML based on Horde 3
*
*
* Using the PEAR Log class (which need to be installed!)
*
* @link http://www.egroupware.org
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package api
* @subpackage horde
* @author Anthony Mills <amills@pyramid6.com>
* @author Joerg Lehrke <jlehrke@noc.de>
* @copyright (c) The Horde Project (http://www.horde.org/)
* @version $Id$
*/
include_once 'Horde/SyncML/State.php';
include_once 'Horde/SyncML/Command.php';
class Horde_SyncML_Command_Status extends Horde_SyncML_Command {
/**
* Name of the command.
*
* @var string
*/
var $_cmdName = 'Status';
/**
* The Response code of the command sent to the client, that this
* Status response refers to.
*
* @var integer
*/
var $_response;
/**
* The command ID (CmdID) of the command sent to the client, that this
* Status response refers to.
*
* @var integer
*/
var $_cmdRef;
/**
* The command (Add, Replace, etc) sent to the client, that this Status
* response refers to.
*
* @var string
*/
var $_cmd;
/**
* The server ID of the sent object, that this Status response refers to.
*
* This element is optional. If specified, Status response refers to a
* single Item in the command sent to the client. It refers to all Items in
* the sent command otherwise.
*
* @var string
*/
var $_sourceRef;
/**
* The client ID of the sent object, that this Status response refers to.
*
* This element is optional. If specified, Status response refers to a
* single Item in the command sent to the client. It refers to all Items in
* the sent command otherwise.
*
* @var string
*/
var $_targetRef;
var $_chalMetaFormat;
var $_chalMetaType;
var $_chalMetaNextNonce;
var $_itemDataAnchorNext;
var $_itemDataAnchorLast;
var $_itemTargetLocURI;
var $_itemSourceLocURI;
var $_syncItems;
/**
* Constructor.
*
* @param integer $response The response code.
* @param string $cmd The command sent to the client,
* that this Status response refers to.
*/
function Horde_SyncML_Command_Status($response = null, $cmd = null)
{
if ($response != null) {
$this->_response = $response;
}
if ($cmd != null) {
$this->_cmd = $cmd;
}
}
function output($currentCmdID, &$output)
{
$state = &$_SESSION['SyncML.state'];
$attrs = array();
if ($this->_cmd != null) {
$output->startElement($state->getURI(), 'Status', $attrs);
$output->startElement($state->getURI(), 'CmdID', $attrs);
$chars = $currentCmdID;
$output->characters($chars);
$output->endElement($state->getURI(), 'CmdID');
$output->startElement($state->getURI(), 'MsgRef', $attrs);
$chars = $state->getMsgID();
$output->characters($chars);
$output->endElement($state->getURI(), 'MsgRef');
$output->startElement($state->getURI(), 'CmdRef', $attrs);
$chars = $this->_cmdRef;
$output->characters($chars);
$output->endElement($state->getURI(), 'CmdRef');
$output->startElement($state->getURI(), 'Cmd', $attrs);
$chars = $this->_cmd;
$output->characters($chars);
$output->endElement($state->getURI(), 'Cmd');
if (isset($this->_targetRef)) {
$output->startElement($state->getURI(), 'TargetRef', $attrs);
$chars = $this->_targetRef;
$output->characters($chars);
$output->endElement($state->getURI(), 'TargetRef');
}
if (isset($this->_sourceRef)) {
$output->startElement($state->getURI(), 'SourceRef', $attrs);
$chars = $this->_sourceRef;
$output->characters($chars);
$output->endElement($state->getURI(), 'SourceRef');
}
// If we are responding to the SyncHdr and we are not
// authorized then request basic authorization.
//
// FIXME: Right now we always send this, ignoring the
// isAuthorized() test. Is that correct?
if ($this->_cmd == 'SyncHdr' && !$state->isAuthorized()) {
$this->_chalMetaFormat = 'b64';
$this->_chalMetaType = 'syncml:auth-basic';
}
if (isset($this->_chalMetaFormat) && isset($this->_chalMetaType)) {
$output->startElement($state->getURI(), 'Chal', $attrs);
$output->startElement($state->getURI(), 'Meta', $attrs);
$metainfuri = $state->getURIMeta();
$output->startElement($metainfuri, 'Format', $attrs);
$chars = $this->_chalMetaFormat;
$output->characters($chars);
$output->endElement($metainfuri, 'Format');
$output->startElement($metainfuri, 'Type', $attrs);
$chars = $this->_chalMetaType;
$output->characters($chars);
$output->endElement($metainfuri, 'Type');
// $output->startElement($metainfuri, 'NextNonce', $attrs);
// $chars = $this->_chalMetaNextNonce;
// $output->characters($chars);
// $output->endElement($metainfuri, 'NextNonce');
$output->endElement($state->getURI(), 'Meta');
$output->endElement($state->getURI(), 'Chal');
}
$output->startElement($state->getURI(), 'Data', $attrs);
$chars = $this->_response;
$output->characters($chars);
$output->endElement($state->getURI(), 'Data');
if (isset($this->_itemDataAnchorNext) || isset($this->_itemDataAnchorLast)) {
$output->startElement($state->getURI(), 'Item', $attrs);
$output->startElement($state->getURI(), 'Data', $attrs);
$metainfuri = $state->getURIMeta();
// $metainfuri = $state->getURI(); // debug by FOU
$output->startElement($metainfuri, 'Anchor', $attrs);
if (isset($this->_itemDataAnchorNext)) {
$output->startElement($metainfuri, 'Next', $attrs);
$chars = $this->_itemDataAnchorNext;
$output->characters($chars);
$output->endElement($metainfuri, 'Next');
}
if (isset($this->_itemDataAnchorLast)) {
$output->startElement($metainfuri, 'Last', $attrs);
$chars = $this->_itemDataAnchorLast;
$output->characters($chars);
$output->endElement($metainfuri, 'Last');
}
$output->endElement($metainfuri, 'Anchor');
$output->endElement($state->getURI(), 'Data');
$output->endElement($state->getURI(), 'Item');
}
if (isset($this->_syncItems)) {
// Support multible items per command
foreach ($this->_syncItems as $locURI => &$syncItem) {
$output->startElement($state->getURI(), 'Item', $attrs);
$output->startElement($state->getURI(), 'Source', $attrs);
$output->startElement($state->getURI(), 'LocURI', $attrs);
$output->characters($locURI);
$output->endElement($state->getURI(), 'LocURI');
$output->endElement($state->getURI(), 'Source');
$output->endElement($state->getURI(), 'Item');
}
} elseif (isset($this->_itemTargetLocURI) || isset($this->_itemSourceLocURI)) {
$output->startElement($state->getURI(), 'Item', $attrs);
if (isset($this->_itemTargetLocURI)) {
$output->startElement($state->getURI(), 'Target', $attrs);
$output->startElement($state->getURI(), 'LocURI', $attrs);
$output->characters($this->_itemTargetLocURI);
$output->endElement($state->getURI(), 'LocURI');
$output->endElement($state->getURI(), 'Target');
}
if (isset($this->_itemSourceLocURI)) {
$output->startElement($state->getURI(), 'Source', $attrs);
$output->startElement($state->getURI(), 'LocURI', $attrs);
$output->characters($this->_itemSourceLocURI);
$output->endElement($state->getURI(), 'LocURI');
$output->endElement($state->getURI(), 'Source');
}
$output->endElement($state->getURI(), 'Item');
}
$output->endElement($state->getURI(), 'Status');
$currentCmdID++;
}
return $currentCmdID;
}
/**
* Setter for property response.
*
* @param string $response New value of property response.
*/
function setResponse($response)
{
$this->_response = $response;
}
/**
* Setter for property cmd.
*
* @param string $cmd New value of property cmd.
*/
function setCmd($cmd)
{
$this->_cmd = $cmd;
}
/**
* Setter for property cmdRef.
*
* @param string $cmdRef New value of property cmdRef.
*/
function setCmdRef($cmdRef)
{
$this->_cmdRef = $cmdRef;
}
/**
* Setter for property sourceRef.
*
* @param string $sourceRef New value of property sourceRef.
*/
function setSourceRef($sourceRef)
{
$this->_sourceRef = $sourceRef;
}
/**
* Setter for property targetRef.
*
* @param string $targetRef New value of property targetRef.
*/
function setTargetRef($targetRef)
{
$this->_targetRef = $targetRef;
}
/**
* Setter for property itemDataAnchorNext.
*
* @param string $itemDataAnchorNext New value of property itemDataAnchorNext.
*/
function setItemDataAnchorNext($itemDataAnchorNext)
{
$this->_itemDataAnchorNext = $itemDataAnchorNext;
}
/**
* Setter for property itemDataAnchorLast.
*
* @param string $itemDataAnchorLast New value of property itemDataAnchorLast.
*/
function setItemDataAnchorLast($itemDataAnchorLast)
{
$this->_itemDataAnchorLast = $itemDataAnchorLast;
}
/**
* Setter for property itemSourceLocURI.
*
* @param string $itemSourceLocURI New value of property itemSourceLocURI.
*/
function setItemSourceLocURI($itemSourceLocURI)
{
$this->_itemSourceLocURI = $itemSourceLocURI;
}
/**
* Setter for property itemTargetLocURI.
*
* @param string $itemTargetLocURI New value of property itemTargetLocURI.
*/
function setItemTargetLocURI($itemTargetLocURI)
{
$this->_itemTargetLocURI = $itemTargetLocURI;
}
/**
* Setter for the the list of handled SyncItems
*
* @param array $syncItems The Items of the command
*/
function setSyncItems(&$syncItems)
{
$this->_syncItems = $syncItems;
}
}

View File

@ -1,267 +0,0 @@
<?php
/**
* eGroupWare - SyncML based on Horde 3
*
*
* Using the PEAR Log class (which need to be installed!)
*
* @link http://www.egroupware.org
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package api
* @subpackage horde
* @author Anthony Mills <amills@pyramid6.com>
* @author Joerg Lehrke <jlehrke@noc.de>
* @copyright (c) The Horde Project (http://www.horde.org/)
* @version $Id$
*/
include_once 'Horde/SyncML/State.php';
include_once 'Horde/SyncML/Command.php';
include_once 'Horde/SyncML/Command/Sync/SyncElement.php';
include_once 'Horde/SyncML/Sync/TwoWaySync.php';
include_once 'Horde/SyncML/Sync/SlowSync.php';
include_once 'Horde/SyncML/Sync/OneWayFromServerSync.php';
include_once 'Horde/SyncML/Sync/OneWayFromClientSync.php';
include_once 'Horde/SyncML/Sync/RefreshFromServerSync.php';
include_once 'Horde/SyncML/Sync/RefreshFromClientSync.php';
class Horde_SyncML_Command_Sync extends Horde_SyncML_Command {
/**
* Name of the command.
*
* @var string
*/
var $_cmdName = 'Sync';
/**
* Source database of the <Sync> command.
*
* @var string
*/
var $_sourceURI;
/**
* Target database of the <Sync> command.
*
* @var string
*/
var $_targetURI;
/**
* Optional parameter for the Target.
*
* @var string
*/
var $_targetURIParameters;
/**
* SyncML_SyncElement object for the currently parsed sync command.
*
* @var SyncML_SyncElement
*/
var $_curItem;
/**
* List of all SyncML_SyncElement objects that have parsed.
*
* @var array
*/
var $_syncElements = array();
function output($currentCmdID, &$output)
{
$state = &$_SESSION['SyncML.state'];
Horde::logMessage('SyncML: $this->_targetURI = ' . $this->_targetURI, __FILE__, __LINE__, PEAR_LOG_DEBUG);
$status = new Horde_SyncML_Command_Status(RESPONSE_OK, 'Sync');
$status->setCmdRef($this->_cmdID);
if ($this->_targetURI != null) {
$status->setTargetRef((isset($this->_targetURIParameters) ? $this->_targetURI.'?/'.$this->_targetURIParameters : $this->_targetURI));
}
if ($this->_sourceURI != null) {
$status->setSourceRef($this->_sourceURI);
}
$currentCmdID = $status->output($currentCmdID, $output);
if (($sync = &$state->getSync($this->_targetURI))) {
$currentCmdID = $sync->startSync($currentCmdID, $output);
foreach ($this->_syncElements as $element) {
$currentCmdID = $sync->nextSyncCommand($currentCmdID, $element, $output);
}
}
return $currentCmdID;
}
function startElement($uri, $element, $attrs)
{
parent::startElement($uri, $element, $attrs);
switch (count($this->_stack)) {
case 2:
if ($element == 'Replace' ||
$element == 'Add' ||
$element == 'Delete') {
Horde::logMessage("SyncML: sync element $element found", __FILE__, __LINE__, PEAR_LOG_DEBUG);
$this->_curItem = &Horde_SyncML_Command_Sync_SyncElement::factory($element);
}
break;
}
if (isset($this->_curItem)) {
$this->_curItem->startElement($uri, $element, $attrs);
}
}
// We create a seperate Sync Element for the Sync Data sent
// from the Server to the client as we want to process the
// client sync information before.
function syncToClient($currentCmdID, &$output)
{
Horde::logMessage('SyncML: starting sync to client',
__FILE__, __LINE__, PEAR_LOG_DEBUG);
$state = &$_SESSION['SyncML.state'];
if ($state->getSyncStatus() >= CLIENT_SYNC_FINNISHED
&& $state->getSyncStatus() < SERVER_SYNC_FINNISHED)
{
$deviceInfo = $state->getClientDeviceInfo();
if (($targets = $state->getTargets())) {
foreach ($targets as $target)
{
$sync = &$state->getSync($target);
Horde::logMessage('SyncML[' . session_id() . ']: sync alerttype ' .
$sync->_syncType . ' found for target ' . $target,
__FILE__, __LINE__, PEAR_LOG_DEBUG);
if ($sync->_syncType == ALERT_ONE_WAY_FROM_CLIENT ||
$sync->_syncType == ALERT_REFRESH_FROM_CLIENT) {
Horde::logMessage('SyncML[' . session_id() .
']: From client Sync, no sync of ' . $target .
' to client', __FILE__, __LINE__, PEAR_LOG_DEBUG);
$state->clearSync($target);
} elseif ($state->getSyncStatus() >= CLIENT_SYNC_ACKNOWLEDGED) {
Horde::logMessage("SyncML: starting sync to client $target",
__FILE__, __LINE__, PEAR_LOG_DEBUG);
$attrs = array();
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
$output->startElement($state->getURI(), 'Sync', $attrs);
$output->startElement($state->getURI(), 'CmdID', $attrs);
$output->characters($currentCmdID);
$currentCmdID++;
$output->endElement($state->getURI(), 'CmdID');
$output->startElement($state->getURI(), 'Target', $attrs);
$output->startElement($state->getURI(), 'LocURI', $attrs);
$chars = $sync->_sourceLocURI;
$output->characters($chars);
$output->endElement($state->getURI(), 'LocURI');
$output->endElement($state->getURI(), 'Target');
$output->startElement($state->getURI(), 'Source', $attrs);
$output->startElement($state->getURI(), 'LocURI', $attrs);
$chars = (isset($sync->_targetLocURIParameters) ? $sync->_targetLocURI.'?/'.$sync->_targetLocURIParameters : $sync->_targetLocURI);
$output->characters($chars);
$output->endElement($state->getURI(), 'LocURI');
$output->endElement($state->getURI(), 'Source');
if(!$sync->_syncDataLoaded)
{
$numberOfItems = $sync->loadData();
if($deviceInfo['supportNumberOfChanges'])
{
$output->startElement($state->getURI(), 'NumberOfChanges', $attrs);
$output->characters($numberOfItems);
$output->endElement($state->getURI(), 'NumberOfChanges');
}
}
$currentCmdID = $sync->endSync($currentCmdID, $output);
$output->endElement($state->getURI(), 'Sync');
if (isset($state->curSyncItem) ||
$state->getNumberOfElements() === false) {
break;
}
} else {
Horde::logMessage("SyncML: Waiting for client ACKNOWLEDGE for $target",
__FILE__, __LINE__, PEAR_LOG_DEBUG);
}
}
}
// no syncs left
if ($state->getTargets() === false &&
!isset($state->curSyncItem)) {
$state->setSyncStatus(SERVER_SYNC_FINNISHED);
}
Horde::logMessage('SyncML: syncStatus(syncToClient) = ' .
$state->getSyncStatus(), __FILE__, __LINE__, PEAR_LOG_DEBUG);
}
return $currentCmdID;
}
function endElement($uri, $element)
{
if (isset($this->_curItem)) {
$this->_curItem->endElement($uri, $element);
}
switch (count($this->_stack)) {
case 2:
if ($element == 'Replace' ||
$element == 'Add' ||
$element == 'Delete') {
$this->_syncElements[] = &$this->_curItem;
unset($this->_curItem);
}
break;
case 3:
if ($element == 'LocURI' && !isset($this->_curItem)) {
if ($this->_stack[1] == 'Source') {
$this->_sourceURI = trim($this->_chars);
} elseif ($this->_stack[1] == 'Target') {
$targetURIData = explode('?/',trim($this->_chars));
$this->_targetURI = $targetURIData[0];
if (isset($targetURIData[1])) {
$this->_targetURIParameters = $targetURIData[1];
}
}
}
break;
}
parent::endElement($uri, $element);
}
function characters($str)
{
if (isset($this->_curItem)) {
$this->_curItem->characters($str);
} else {
if (isset($this->_chars)) {
$this->_chars .= $str;
} else {
$this->_chars = $str;
}
}
}
}

View File

@ -1,34 +0,0 @@
<?php
/**
* eGroupWare - SyncML based on Horde 3
*
*
* Using the PEAR Log class (which need to be installed!)
*
* @link http://www.egroupware.org
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package api
* @subpackage horde
* @author Anthony Mills <amills@pyramid6.com>
* @copyright (c) The Horde Project (http://www.horde.org/)
* @version $Id$
*/
include_once 'Horde/SyncML/Command/Sync/SyncElement.php';
class Horde_SyncML_Command_Sync_Add extends Horde_SyncML_Command_Sync_SyncElement {
var $_status = RESPONSE_ITEM_ADDED;
function output($currentCmdID, &$output)
{
$status = new Horde_SyncML_Command_Status($this->_status, 'Add');
$status->setCmdRef($this->_cmdID);
if (!empty($this->_items)) {
$status->setSyncItems($this->_items);
}
return $status->output($currentCmdID, $output);
}
}

View File

@ -1,164 +0,0 @@
<?php
/**
* eGroupWare - SyncML based on Horde 3
*
*
* Using the PEAR Log class (which need to be installed!)
*
* @link http://www.egroupware.org
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package api
* @subpackage horde
* @author Anthony Mills <amills@pyramid6.com>
* @author Joerg Lehrke <jlehrke@noc.de>
* @copyright (c) The Horde Project (http://www.horde.org/)
* @version $Id$
*/
include_once 'Horde/SyncML/State.php';
include_once 'Horde/SyncML/Command/Sync/SyncElementItem.php';
class Horde_SyncML_Command_Sync_ContentSyncElement extends Horde_SyncML_Command_Sync_SyncElementItem {
function outputCommand($currentCmdID, &$output, $command)
{
$state = $_SESSION['SyncML.state'];
$maxMsgSize = $state->getMaxMsgSizeClient();
$maxGUIDSize = $state->getMaxGUIDSizeClient();
if ($this->_moreData) {
$command = $this->_command;
} else {
$this->_command = $command;
}
$attrs = array();
$contentFormat = isset($this->_contentFormat) ? strtolower($this->_contentFormat) : '';
$output->startElement($state->getURI(), $command, $attrs);
$output->startElement($state->getURI(), 'CmdID', $attrs);
$output->characters($currentCmdID);
$output->endElement($state->getURI(), 'CmdID');
if (isset($this->_content) && !$this->_moreData) {
$this->_contentSize = strlen($this->_content);
} else {
$this->_contentSize = 0;
}
switch ($contentFormat) {
case 'strictxml':
break;
case 'htmlenc':
if (!$state->isWBXML() && $this->_contentSize) {
$this->_content = htmlspecialchars($this->_content, ENT_COMPAT, 'UTF-8');
}
break;
case 'b64':
if ($this->_contentSize) {
$this->_content = base64_encode($this->_content);
}
default:
$contentFormat = '';
}
// <command><Meta>
if ($this->_contentSize || isset($this->_contentType) ||
(!$contentFormat && isset($this->_contentFormat))) {
$output->startElement($state->getURI(), 'Meta', $attrs);
if (isset($this->_contentType)) {
$output->startElement($state->getURIMeta(), 'Type', $attrs);
$output->characters($this->_contentType);
$output->endElement($state->getURIMeta(), 'Type');
}
if (!$contentFormat && isset($this->_contentFormat)) {
$output->startElement($state->getURIMeta(), 'Format', $attrs);
$output->characters($this->_contentFormat);
$output->endElement($state->getURIMeta(), 'Format');
}
if ($this->_contentSize) {
$output->startElement($state->getURIMeta(), 'Size', $attrs);
$output->characters(($this->_contentSize));
$output->endElement($state->getURIMeta(), 'Size');
}
$output->endElement($state->getURI(), 'Meta');
}
if (isset($this->_content) || isset($this->_luid) || isset($this->_guid)) {
$output->startElement($state->getURI(), 'Item', $attrs);
// <command><Item><Source><LocURI>
if (isset($this->_guid)) {
$output->startElement($state->getURI(), 'Source', $attrs);
$output->startElement($state->getURI(), 'LocURI', $attrs);
$chars = substr($this->_guid, 0, $maxGUIDSize);
$state->setUIDMapping($this->_guid, $chars);
$output->characters($chars);
$output->endElement($state->getURI(), 'LocURI');
$output->endElement($state->getURI(), 'Source');
}
// <command><Item><Target><LocURI>
if (isset($this->_luid)) {
$output->startElement($state->getURI(), 'Target', $attrs);
$output->startElement($state->getURI(), 'LocURI', $attrs);
$output->characters($this->_luid);
$output->endElement($state->getURI(), 'LocURI');
$output->endElement($state->getURI(), 'Target');
}
// <command><Item><Data>
if (isset($this->_content)) {
$this->_contentSize = strlen($this->_content);
$output->startElement($state->getURI(), 'Data', $attrs);
$currentSize = $output->getOutputSize();
Horde::logMessage("SyncML: $command: current = $currentSize, max = $maxMsgSize", __FILE__, __LINE__, PEAR_LOG_DEBUG);
if (!$maxMsgSize ||
(($currentSize + MIN_MSG_LEFT + $this->_contentSize + 12) <= $maxMsgSize)) {
$chars = $this->_content;
unset($this->_content);
$this->_moreData = false;
} else {
$sizeLeft = $maxMsgSize - $currentSize - MIN_MSG_LEFT - 12;
if ($sizeLeft < 0) {
Horde::logMessage("SyncML: $command: split with $currentSize for $maxMsgSize, increase MIN_MSG_LEFT!", __FILE__, __LINE__, PEAR_LOG_WARNING);
$sizeLeft = 0;
}
// don't let us loose characters by trimming
while (($this->_contentSize > $sizeLeft) &&
(strlen(trim(substr($this->_content, $sizeLeft - 1, 2))) < 2)) {
Horde::logMessage("SyncML: $command: split at $sizeLeft hit WS!", __FILE__, __LINE__, PEAR_LOG_DEBUG);
$sizeLeft++;
}
$chars = substr($this->_content, 0, $sizeLeft);
$this->_content = substr($this->_content, $sizeLeft, $this->_contentSize - $sizeLeft);
Horde::logMessage("SyncML: $command: "
. $this->_contentSize . " split at $sizeLeft:\n"
. $chars, __FILE__, __LINE__, PEAR_LOG_DEBUG);
$this->_moreData = true;
}
switch ($contentFormat) {
case 'strictxml':
if (!$state->isWBXML()) {
$chars = '<![CDATA['. $chars. ']]>';
}
break;
}
$output->characters($chars);
$output->endElement($state->getURI(), 'Data');
// <command><Item><MoreData/>
if ($this->_moreData) {
$output->startElement($state->getURI(), 'MoreData', $attrs);
$output->endElement($state->getURI(), 'MoreData');
}
}
$output->endElement($state->getURI(), 'Item');
}
$output->endElement($state->getURI(), $command);
$currentCmdID++;
return $currentCmdID;
}
}

View File

@ -1,32 +0,0 @@
<?php
/**
* eGroupWare - SyncML based on Horde 3
*
*
* Using the PEAR Log class (which need to be installed!)
*
* @link http://www.egroupware.org
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package api
* @subpackage horde
* @author Anthony Mills <amills@pyramid6.com>
* @copyright (c) The Horde Project (http://www.horde.org/)
* @version $Id$
*/
include_once 'Horde/SyncML/Command/Sync/SyncElement.php';
class Horde_SyncML_Command_Sync_Delete extends Horde_SyncML_Command_Sync_SyncElement {
function output($currentCmdID, &$output)
{
$status = new Horde_SyncML_Command_Status($this->_status, 'Delete');
$status->setCmdRef($this->_cmdID);
if (!empty($this->_items)) {
$status->setSyncItems($this->_items);
}
return $status->output($currentCmdID, $output);
}
}

View File

@ -1,31 +0,0 @@
<?php
/**
* eGroupWare - SyncML based on Horde 3
*
*
* Using the PEAR Log class (which need to be installed!)
*
* @link http://www.egroupware.org
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package api
* @subpackage horde
* @author Anthony Mills <amills@pyramid6.com>
* @copyright (c) The Horde Project (http://www.horde.org/)
* @version $Id$
*/
include_once 'Horde/SyncML/Command/Sync/SyncElement.php';
class Horde_SyncML_Command_Sync_Replace extends Horde_SyncML_Command_Sync_SyncElement {
function output($currentCmdID, &$output) {
$status = new Horde_SyncML_Command_Status($this->_status, 'Replace');
$status->setCmdRef($this->_cmdID);
if (!empty($this->_items)) {
$status->setSyncItems($this->_items);
}
return $status->output($currentCmdID, $output);
}
}

View File

@ -1,232 +0,0 @@
<?php
/**
* eGroupWare - SyncML based on Horde 3
*
*
* Using the PEAR Log class (which need to be installed!)
*
* @link http://www.egroupware.org
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package api
* @subpackage horde
* @author Anthony Mills <amills@pyramid6.com>
* @author Joerg Lehrke <jlehrke@noc.de>
* @copyright (c) The Horde Project (http://www.horde.org/)
* @version $Id$
*/
include_once 'Horde/SyncML/Command.php';
class Horde_SyncML_Command_Sync_SyncElement extends Horde_SyncML_Command {
var $_luid;
var $_guid;
var $_contentSize = 0;
var $_contentType;
var $_contentFormat;
var $_status = RESPONSE_OK;
var $_curItem;
var $_items = array();
var $_failed = array();
var $_moreData = false;
var $_command = false;
function &factory($command, $params = null) {
include_once 'Horde/SyncML/Command/Sync/SyncElementItem.php';
@include_once 'Horde/SyncML/Command/Sync/' . $command . '.php';
$class = 'Horde_SyncML_Command_Sync_' . $command;
if (class_exists($class)) {
#Horde::logMessage('SyncML: Class definition of ' . $class . ' found in SyncElement::factory.', __FILE__, __LINE__, PEAR_LOG_DEBUG);
return $element = new $class($params);
} else {
Horde::logMessage('SyncML: Class definition of ' . $class . ' not found in SyncElement::factory.', __FILE__, __LINE__, PEAR_LOG_DEBUG);
require_once 'PEAR.php';
return PEAR::raiseError('Class definition of ' . $class . ' not found.');
}
}
function startElement($uri, $element, $attrs) {
parent::startElement($uri, $element, $attrs);
$state = &$_SESSION['SyncML.state'];
switch (count($this->_stack)) {
case 1:
$this->_command = $element;
break;
case 2:
if ($element == 'Item') {
if (isset($state->curSyncItem)) {
// Copy from state in case of <MoreData>.
$this->_curItem = &$state->curSyncItem;
if (isset($this->_luid) &&
($this->_luid != $this->_curItem->_luid)) {
Horde::logMessage('SyncML: moreData mismatch for LocURI ' .
$this->_curItem->_luid . ' (' . $this->_luid . ')', __FILE__, __LINE__, PEAR_LOG_ERROR);
} else {
Horde::logMessage('SyncML: moreData item found for LocURI ' . $this->_curItem->_luid, __FILE__, __LINE__, PEAR_LOG_DEBUG);
}
unset($state->curSyncItem);
} else {
$this->_curItem = new Horde_SyncML_Command_Sync_SyncElementItem();
}
$this->_moreData = false;
}
break;
}
}
function endElement($uri, $element) {
$state = &$_SESSION['SyncML.state'];
$search = array('/ *\n/','/ *$/m');
$replace = array('','');
switch (count($this->_stack)) {
case 1:
$this->_command = false;
// Need to add sync elements to the Sync method?
#error_log('total # of items: '.count($this->_items));
#error_log(print_r($this->_items[10], true));
break;
case 2;
if($element == 'Item') {
if ($this->_luid) {
$this->_curItem->setLocURI($this->_luid);
$this->_curItem->setContentType($this->_contentType);
$this->_curItem->setContentFormat($this->_contentFormat);
$this->_curItem->setCommand($this->_command);
if ($this->_contentSize)
$this->_curItem->setContentSize($this->_contentSize);
if ($this->_moreData) {
$state->curSyncItem = &$this->_curItem;
Horde::logMessage('SyncML: moreData item saved for LocURI ' . $this->_curItem->_luid, __FILE__, __LINE__, PEAR_LOG_DEBUG);
} else {
$content = $this->_curItem->getContent();
$contentSize = strlen($content);
if ((($size = $this->_curItem->getContentSize()) !== false) &&
abs($contentSize - $size) > 3) {
Horde::logMessage('SyncML: content size mismatch for LocURI ' . $this->_luid .
": $contentSize ($size) : " . $content,
__FILE__, __LINE__, PEAR_LOG_WARNING);
$this->_failed[$this->_luid] = $this->_curItem;
} else {
if (strtolower($this->_curItem->getContentFormat()) == 'b64') {
$content = ($content ? base64_decode($content) : '');
$this->_curItem->setContent($content);
#Horde::logMessage('SyncML: BASE64 encoded item for LocURI '
# . $this->_curItem->_luid . ":\n $content", __FILE__, __LINE__, PEAR_LOG_DEBUG);
}
#Horde::logMessage('SyncML: Data for ' . $this->_luid . ': ' . $this->_curItem->getContent(), __FILE__, __LINE__, PEAR_LOG_DEBUG);
$this->_items[$this->_luid] = $this->_curItem;
}
}
}
unset($this->_contentSize);
unset($this->_luid);
}
break;
case 3:
switch ($element) {
case 'Data':
$content = $this->_chars;
if ($this->_contentFormat == 'b64') $content = trim($content);
#Horde::logMessage('SyncML: Data for ' . $this->_luid . ': ' . $content, __FILE__, __LINE__, PEAR_LOG_DEBUG);
$this->_curItem->_content .= $content;
break;
case 'MoreData':
$this->_moreData = true;
break;
case 'Type':
if (empty($this->_contentType)) {
$this->_contentType = trim($this->_chars);
}
break;
case 'Format':
$this->_contentFormat = strtolower(trim($this->_chars));
break;
case 'Size':
$this->_contentSize = trim($this->_chars);
break;
}
break;
case 4:
switch ($element) {
case 'LocURI':
if ($this->_stack[2] == 'Source') {
$this->_luid = trim($this->_chars);
}
break;
case 'Type':
$this->_contentType = trim($this->_chars);
break;
case 'Format':
$this->_contentFormat = strtolower(trim($this->_chars));
break;
case 'Size':
$this->_contentSize = trim($this->_chars);
break;
}
break;
}
parent::endElement($uri, $element);
}
function getSyncElementItems() {
return (array)$this->_items;
}
function getSyncElementFailures() {
return (array)$this->_failed;
}
function getLocURI()
{
return $this->_luid;
}
function getGUID()
{
return $this->_guid;
}
function setLocURI($luid)
{
$this->_luid = $luid;
}
function setGUID($guid)
{
$this->_guid = $guid;
}
function setContentType($c)
{
$this->_contentType = $c;
}
function getContentType()
{
return $this->_contentType;
}
function getContent()
{
if ($this->_curItem) {
return $this->_curItem->getcontent();
}
return false;
}
function hasMoreData()
{
return $this->_moreData;
}
function setStatus($_status)
{
$this->_status = $_status;
}
}

View File

@ -1,95 +0,0 @@
<?php
/**
* eGroupWare - SyncML based on Horde 3
*
*
* Using the PEAR Log class (which need to be installed!)
*
* @link http://www.egroupware.org
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package api
* @subpackage horde
* @author Anthony Mills <amills@pyramid6.com>
* @copyright (c) The Horde Project (http://www.horde.org/)
* @version $Id$
*/
include_once 'Horde/SyncML/Command.php';
class Horde_SyncML_Command_Sync_SyncElementItem {
var $_luid;
var $_guid;
var $_content = '';
var $_contentSize;
var $_contentType;
var $_contentFormat;
var $_command;
var $_moreData = false;
function getLocURI() {
return $this->_luid;
}
function getGUID() {
return $this->_guid;
}
function getContentType() {
return $this->_contentType;
}
function getContentFormat() {
return $this->_contentFormat;
}
function getContent() {
return $this->_content;
}
function getContentSize() {
if (isset($this->_contentSize)) {
return $this->_contentSize;
}
return false;
}
function getCommand() {
return $this->_command;
}
function setLocURI($luid) {
$this->_luid = $luid;
}
function setGUID($guid) {
$this->_guid = $guid;
}
function setContent($_content) {
$this->_content = $_content;
}
function setContentSize($_size) {
$this->_contentSize = $_size;
}
function setContentType($_type) {
$this->_contentType = $_type;
}
function setContentFormat($_format) {
$this->_contentFormat = $_format;
}
function setMoreData($_status) {
$this->_moreData = $_status;
}
function hasMoreData() {
return $this->_moreData;
}
function setCommand($_command) {
$this->_command = $_command;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,738 +0,0 @@
<?php
/**
* eGroupWare - SyncML based on Horde 3
*
*
* Using the PEAR Log class (which need to be installed!)
*
* @link http://www.egroupware.org
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package api
* @subpackage horde
* @author Lars Kneschke <lkneschke@egroupware.org>
* @author Joerg Lehrke <jlehrke@noc.de>
* @version $Id$
*/
include_once dirname(__FILE__).'/State.php';
/**
* The EGW_SyncML_State class provides a SyncML state object.
*/
class EGW_SyncML_State extends Horde_SyncML_State
{
var $table_devinfo = 'egw_syncmldevinfo';
/*
* store the mappings of egw uids to client uids
*/
var $uidMappings = array();
/*
* the domain of the current user
*/
var $_account_domain = 'default';
/**
* get the local content id from a syncid
*
* @param sting $_syncid id used in syncml
* @return int local egw content id
*/
function get_egwID($_syncid) {
$syncIDParts = explode('-',$_syncid);
array_shift($syncIDParts);
$_id = implode ('', $syncIDParts);
return $_id;
}
/**
* when got a entry last added/modified/deleted
*
* @param $_syncid containing appName-contentid
* @param $_action string can be add, delete or modify
* @return string the last timestamp
*/
function getSyncTSforAction($_syncid, $_action) {
$syncIDParts = explode('-',$_syncid);
$_appName = array_shift($syncIDParts);
$_id = implode ('', $syncIDParts);
$ts = $GLOBALS['egw']->contenthistory->getTSforAction($_appName, $_id, $_action);
if (strstr($_id, ':')) {
// pseudo entries are related to parent entry
$parentId = array_shift(explode(':', $_id));
$pts = $GLOBALS['egw']->contenthistory->getTSforAction($_appName, $parentId, $_action);
if ($pts > $ts) $ts = $pts; // We have changed the parent
}
return $ts;
}
/**
* get the timestamp for action
*
* find which content changed since $_ts for application $_appName
*
* @param string$_appName the appname example: infolog_notes
* @param string $_action can be modify, add or delete
* @param string $_ts timestamp where to start searching from
* @param array $readableItems (optional) readable items of current user
* @return array containing syncIDs with changes
*/
function getHistory($_appName, $_action, $_ts, $readableItems = false) {
$guidList = array();
$syncIdList = array();
$userItems = false;
if (is_array($readableItems))
{
$userItems = array();
foreach($readableItems as $guid)
{
if (preg_match('/.*-(\d+)(:(\d+))?/', $guid, $matches))
{
// We use only the real items' ids
$userItems[] = $matches[1];
}
}
$userItems = array_unique($userItems);
}
$idList = $GLOBALS['egw']->contenthistory->getHistory($_appName, $_action, $_ts, $userItems);
foreach ($idList as $idItem)
{
if ($idItem) // ignore inconsistent entries
{
$syncIdList[] = $_appName . '-' . $idItem;
}
}
return $syncIdList;
}
/**
* Returns the timestamp (if set) of the last change to the
* obj:guid, that was caused by the client. This is stored to
* avoid mirroring these changes back to the client.
*/
function getChangeTS($type, $guid) {
$mapID = $this->_locName . $this->_sourceURI . $type;
#Horde::logMessage('SyncML: getChangeTS for ' . $mapID
# . ' / '. $guid, __FILE__, __LINE__, PEAR_LOG_DEBUG);
if ($ts = $GLOBALS['egw']->db->select('egw_contentmap', 'map_timestamp',
array(
'map_id' => $mapID,
'map_guid' => $guid,
), __LINE__, __FILE__, false, '', 'syncml')->fetchColumn()) {
#Horde::logMessage('SyncML: getChangeTS changets is '
# . $GLOBALS['egw']->db->from_timestamp($ts),
# __FILE__, __LINE__, PEAR_LOG_DEBUG);
return $GLOBALS['egw']->db->from_timestamp($ts);
}
return false;
}
/**
* Returns the exceptions for a GUID which the client knows of
*/
function getGUIDExceptions($type, $guid) {
$mapID = $this->_locName . $this->_sourceURI . $type;
#Horde::logMessage('SyncML: getChangeTS for ' . $mapID
# . ' / '. $guid, __FILE__, __LINE__, PEAR_LOG_DEBUG);
$guid_exceptions = array();
$where = array ('map_id' => $mapID,);
$where[] = "map_guid LIKE '$guid" . ":%'";
// Fetch all exceptions which the client knows of
foreach ($GLOBALS['egw']->db->select('egw_contentmap', 'map_guid', $where,
__LINE__,__FILE__, false, '', 'syncml') as $row)
{
$parts = preg_split('/:/', $row['map_guid']);
$Id = $parts[0];
$extension = $parts[1];
$guid_exceptions[$extension] = $row['map_guid'];
}
return $guid_exceptions;
}
/**
* Retrieves information about the clients device info if any. Returns
* false if no info found or a DateTreeObject with at least the
* following attributes:
*
* a array containing all available infos about the device
*/
function getClientDeviceInfo() {
#Horde::logMessage("SyncML: getClientDeviceInfo " . $this->_locName
# . ", " . $this->_sourceURI, __FILE__, __LINE__, PEAR_LOG_DEBUG);
$syncml_prefs = $GLOBALS['egw_info']['user']['preferences']['syncml'];
$deviceMaxEntries = 'maxEntries-' . $this->_clientDeviceInfo['devId'];
$deviceUIDExtension = 'uidExtension-' . $this->_clientDeviceInfo['devId'];
$deviceNonBlockingAllday = 'nonBlockingAllday-' . $this->_clientDeviceInfo['devId'];
$deviceTimezone = 'tzid-' . $this->_clientDeviceInfo['devId'];
$deviceCharSet = 'charset-' . $this->_clientDeviceInfo['devId'];
if (isset($this->_clientDeviceInfo)
&& is_array($this->_clientDeviceInfo)) {
// update user preferences
$this->_clientDeviceInfo['maxEntries'] = $syncml_prefs[$deviceMaxEntries];
$this->_clientDeviceInfo['uidExtension'] = $syncml_prefs[$deviceUIDExtension];
$this->_clientDeviceInfo['nonBlockingAllday'] = $syncml_prefs[$deviceNonBlockingAllday];
$this->_clientDeviceInfo['tzid'] = $syncml_prefs[$deviceTimezone];
$this->_clientDeviceInfo['charset'] = $syncml_prefs[$deviceCharSet];
// use cached information
return $this->_clientDeviceInfo;
}
if (!($deviceID = $GLOBALS['egw']->db->select('egw_syncmldeviceowner',
'owner_devid',
array (
'owner_locname' => $this->_locName,
'owner_deviceid' => $this->_sourceURI,
), __LINE__, __FILE__, false, '', 'syncml')->fetchColumn())) {
return false;
}
$cols = array(
'dev_dtdversion',
'dev_numberofchanges',
'dev_largeobjs',
'dev_swversion',
'dev_fwversion',
'dev_hwversion',
'dev_oem',
'dev_model',
'dev_manufacturer',
'dev_devicetype',
'dev_datastore',
'dev_utc',
);
#Horde::logMessage("SyncML: getClientDeviceInfo $deviceID", __FILE__, __LINE__, PEAR_LOG_DEBUG);
$where = array(
'dev_id' => $deviceID,
);
if (($row = $GLOBALS['egw']->db->select('egw_syncmldevinfo',
$cols, $where, __LINE__, __FILE__, false, '', 'syncml')->fetch())) {
$this->_clientDeviceInfo = array (
'DTDVersion' => $row['dev_dtdversion'],
'supportNumberOfChanges' => $row['dev_numberofchanges'],
'supportLargeObjs' => $row['dev_largeobjs'],
'UTC' => $row['dev_utc'],
'softwareVersion' => $row['dev_swversion'],
'hardwareVersion' => $row['dev_hwversion'],
'firmwareVersion' => $row['dev_fwversion'],
'oem' => $row['dev_oem'],
'model' => $row['dev_model'],
'manufacturer' => $row['dev_manufacturer'],
'deviceType' => $row['dev_devicetype'],
'maxMsgSize' => $this->_maxMsgSize,
'maxEntries' => $syncml_prefs[$deviceMaxEntries],
'uidExtension' => $syncml_prefs[$deviceUIDExtension],
'nonBlockingAllday' => $syncml_prefs[$deviceNonBlockingAllday],
'tzid' => $syncml_prefs[$deviceTimezone],
'charset' => $syncml_prefs[$deviceCharSet],
'devId' => $deviceID,
'persistent' => $deviceID,
'dataStore' => unserialize($row['dev_datastore']),
);
return $this->_clientDeviceInfo;
}
return false;
}
/**
* returns GUIDs of all client items
*/
function getClientItems($type=false) {
if (!$type) $type = $this->_targetURI;
$mapID = $this->_locName . $this->_sourceURI . $type;
$guids = array();
foreach($GLOBALS['egw']->db->select('egw_contentmap', 'map_guid', array(
'map_id' => $mapID,
'map_expired' => false,
), __LINE__, __FILE__, false, '', 'syncml') as $row) {
$guids[] = $row['map_guid'];
}
return $guids;
}
/**
* Retrieves the Horde server guid (like
* kronolith:0d1b415fc124d3427722e95f0e926b75) for a given client
* locid. Returns false if no such id is stored yet.
*
* Opposite of getLocId which returns the locid for a given guid.
*/
function getGlobalUID($type, $locid) {
$mapID = $this->_locName . $this->_sourceURI . $type;
#Horde::logMessage('SyncML: search GlobalUID for ' . $mapID .' / '.$locid, __FILE__, __LINE__, PEAR_LOG_DEBUG);
return $GLOBALS['egw']->db->select('egw_contentmap', 'map_guid',
array(
'map_id' => $mapID,
'map_locuid' => $locid,
'map_expired' => false,
), __LINE__, __FILE__, false, '', 'syncml')->fetchColumn();
}
/**
* Converts a EGW GUID (like
* kronolith:0d1b415fc124d3427722e95f0e926b75) to a client ID as
* used by the sync client (like 12) returns false if no such id
* is stored yet.
*/
function getLocID($type, $guid) {
$mapID = $this->_locName . $this->_sourceURI . $type;
Horde::logMessage('SyncML: search LocID for ' . $mapID . ' / ' . $guid, __FILE__, __LINE__, PEAR_LOG_DEBUG);
if (($locuid = $GLOBALS['egw']->db->select('egw_contentmap', 'map_locuid', array(
'map_id' => $mapID,
'map_guid' => $guid
), __LINE__, __FILE__, false, '', 'syncml')->fetchColumn())) {
Horde::logMessage('SyncML: found LocID: '.$locuid, __FILE__, __LINE__, PEAR_LOG_DEBUG);
}
return $locuid;
}
/**
* Retrieves information about the previous sync if any. Returns
* false if no info found or a DateTreeObject with at least the
* following attributes:
*
* ClientAnchor: the clients Next Anchor of the previous sync.
* ServerAnchor: the Server Next Anchor of the previous sync.
*/
function getSyncSummary($type) {
$deviceID = $this->_locName . $this->_sourceURI;
Horde::logMessage("SyncML: getSyncSummary for $deviceID", __FILE__, __LINE__, PEAR_LOG_DEBUG);
if (($row = $GLOBALS['egw']->db->select('egw_syncmlsummary', array('sync_serverts','sync_clientts'), array(
'dev_id' => $deviceID,
'sync_path' => $type
), __LINE__, __FILE__, false, '', 'syncml')->fetch())) {
Horde::logMessage("SyncML: getSyncSummary for $deviceID serverts: ".$row['sync_serverts']." clients: ".$row['sync_clientts'], __FILE__, __LINE__, PEAR_LOG_DEBUG);
return array(
'ClientAnchor' => $row['sync_clientts'],
'ServerAnchor' => $row['sync_serverts'],
);
}
return false;
}
function isAuthorized() {
if(!isset($this->_locName))
{
Horde::logMessage('SyncML: Authentication not yet possible. Username not available',
__FILE__, __LINE__, PEAR_LOG_DEBUG);
return false;
}
// store sessionID in a variable, because create() and verify() reset this value
$sessionID = session_id();
if (strpos($this->_locName,'@') === False)
{
$this->_account_domain = $GLOBALS['egw_info']['server']['default_domain'];
$this->_locName .= '@'. ($this->_account_domain ? $this->_account_domain : 'default');
}
else
{
$parts = explode('@',$this->_locName);
$this->_account_domain = array_pop($parts);
}
if (!is_object($GLOBALS['egw']))
{
// Let the EGw core create the infrastructure classes
$_POST['login'] = $this->_locName;
$_REQUEST['domain'] = $this->_account_domain;
$GLOBALS['egw_info']['server']['default_domain'] = $this->_account_domain;
$GLOBALS['egw_info']['user']['domain'] = $this->_account_domain;
$GLOBALS['egw_info']['flags']['currentapp'] = 'login';
$GLOBALS['egw_info']['flags']['noapi'] = false;
require_once(EGW_API_INC . '/functions.inc.php');
}
$GLOBALS['egw_info']['flags']['currentapp'] = 'syncml';
if (!$this->_isAuthorized)
{
if (!isset($this->_password))
{
Horde::logMessage('SyncML: Authentication not yet possible. Credetials missing',
__FILE__, __LINE__, PEAR_LOG_DEBUG);
return false;
}
if ($GLOBALS['egw']->session->create($this->_locName,$this->_password,'text'))
{
if ($GLOBALS['egw_info']['user']['apps']['syncml'])
{
$this->_isAuthorized = 1;
// restore the original sessionID
session_regenerate_id();
session_id($sessionID);
$GLOBALS['sessionid'] = $sessionID;
@session_start();
Horde::logMessage('SyncML_EGW[' . $GLOBALS['sessionid']
.']: Authentication of ' . $this->_locName . ' succeded',
__FILE__, __LINE__, PEAR_LOG_DEBUG);
$syncml_prefs = $GLOBALS['egw_info']['user']['preferences']['syncml'];
if (($deviceID = $GLOBALS['egw']->db->select('egw_syncmldeviceowner',
'owner_devid',
array (
'owner_locname' => $this->_locName,
'owner_deviceid' => $this->_sourceURI,
), __LINE__, __FILE__, false, '', 'syncml')->fetchColumn())) {
$allowed_name = 'allowed-' . $deviceID;
if (isset($syncml_prefs[$allowed_name]))
{
$deviceAllowed = $syncml_prefs[$allowed_name];
}
else
{
$deviceAllowed = -1;
}
}
else
{
$deviceAllowed = -1; // Unkown device
}
if (!$GLOBALS['egw_info']['user']['apps']['admin'] &&
isset($syncml_prefs['deny_unknown_devices']) &&
$syncml_prefs['deny_unknown_devices'] != 0)
{
if ($syncml_prefs['deny_unknown_devices'] == -1 &&
$deviceAllowed != 1 ||
$syncml_prefs['deny_unknown_devices'] == 1 &&
$deviceAllowed == 0)
{
$this->_isAuthorized = -1;
Horde::logMessage('SyncML: Device is not allowed for user ' . $this->_locName,
__FILE__, __LINE__, PEAR_LOG_INFO);
}
}
}
else
{
$this->_isAuthorized = -1; // Authorization failed!
Horde::logMessage('SyncML is not enabled for user '
. $this->_locName, __FILE__, __LINE__, PEAR_LOG_ERROR);
}
}
else
{
$this->_isAuthorized = -1;
Horde::logMessage('SyncML: Authentication of ' . $this->_locName
. ' failed', __FILE__, __LINE__, PEAR_LOG_INFO);
}
}
elseif ($this->_isAuthorized > 0)
{
if (!$GLOBALS['egw']->session->verify($sessionID, 'staticsyncmlkp3'))
{
Horde::logMessage('SyncML_EGW: egw session(' . $sessionID
. ') could not be not verified' ,
__FILE__, __LINE__, PEAR_LOG_ERROR);
}
if (empty($GLOBALS['egw_info']['user']['passwd']))
{
$GLOBALS['egw_info']['user']['passwd'] = $this->_password;
}
}
return ($this->_isAuthorized > 0);
}
/**
* Removes all locid<->guid mappings for the given type.
* Returns always true.
*/
function removeAllUID($type) {
$mapID = $this->_locName . $this->_sourceURI . $type;
Horde::logMessage("SyncML: state->removeAllUID(type=$type)", __FILE__, __LINE__, PEAR_LOG_DEBUG);
$GLOBALS['egw']->db->delete('egw_contentmap', array('map_id' => $mapID), __LINE__, __FILE__, 'syncml');
return true;
}
/**
* Used in SlowSync
* Removes all locid<->guid mappings for the given type,
* that are older than $ts.
*
* Returns always true.
*/
function removeOldUID($type, $ts) {
$mapID = $this->_locName . $this->_sourceURI . $type;
$where[] = "map_id = '".$mapID."' AND map_timestamp < '".$GLOBALS['egw']->db->to_timestamp($ts)."'";
Horde::logMessage("SyncML: state->removeOldUID(type=$type)", __FILE__, __LINE__, PEAR_LOG_DEBUG);
$GLOBALS['egw']->db->delete('egw_contentmap', $where, __LINE__, __FILE__, 'syncml');
return true;
}
/**
* Used at session end to cleanup expired entries
* Removes all locid<->guid mappings for the given type,
* that are marked as expired and older than $ts.
*
* Returns always true.
*/
function removeExpiredUID($type, $ts) {
$mapID = $this->_locName . $this->_sourceURI . $type;
$where['map_id'] = $mapID;
$where['map_expired'] = true;
$where[] = "map_timestamp <= '".$GLOBALS['egw']->db->to_timestamp($ts)."'";
Horde::logMessage("SyncML: state->removeExpiredUID(type=$type)",
__FILE__, __LINE__, PEAR_LOG_DEBUG);
$GLOBALS['egw']->db->delete('egw_contentmap', $where,
__LINE__, __FILE__, 'syncml');
return true;
}
/**
* Check if an entry is already expired
*
* Returns true for expired mappings.
*/
function isExpiredUID($type, $locid) {
$mapID = $this->_locName . $this->_sourceURI . $type;
$expired = false;
$where = array(
'map_id' => $mapID,
'map_locuid' => $locid,
);
if (($expired = $GLOBALS['egw']->db->select('egw_contentmap', 'map_expired',
$where, __LINE__, __FILE__, false, '', 'syncml')->fetchColumn())) {
Horde::logMessage('SyncML: found LocID: '. $locid,
__FILE__, __LINE__, PEAR_LOG_DEBUG);
}
return $expired;
}
/**
* Removes the locid<->guid mapping for the given locid. Returns
* the guid that was removed or false if no mapping entry was
* found.
*/
function removeUID($type, $locid) {
$mapID = $this->_locName . $this->_sourceURI . $type;
$where = array (
'map_id' => $mapID,
'map_locuid' => $locid
);
if (!($guid = $GLOBALS['egw']->db->select('egw_contentmap', 'map_guid', $where,
__LINE__, __FILE__, false, '', 'syncml')->fetchColumn())) {
Horde::logMessage("SyncML: state->removeUID(type=$type,locid=$locid)"
. " nothing to remove", __FILE__, __LINE__, PEAR_LOG_INFO);
return false;
}
Horde::logMessage("SyncML: state->removeUID(type=$type,locid=$locid): "
. "removing guid $guid", __FILE__, __LINE__, PEAR_LOG_DEBUG);
$GLOBALS['egw']->db->delete('egw_contentmap', $where, __LINE__, __FILE__, 'syncml');
return $guid;
}
/**
* Puts a given client $locid and Horde server $guid pair into the
* map table to allow mapping between the client's and server's
* IDs. Actually there are two maps: from the localid to the guid
* and vice versa. The localid is converted to a key as follows:
* this->_locName . $this->_sourceURI . $type . $locid so you can
* have different syncs with different devices. If an entry
* already exists, it is overwritten.
* Expired entries can be deleted at the next session start.
*/
function setUID($type, $locid, $_guid, $ts=0, $expired=false) {
#Horde::logMessage("SyncML: setUID $type, $locid, $_guid, $ts ", __FILE__, __LINE__, PEAR_LOG_DEBUG);
if (!strlen("$_guid")) {
// We can't handle this case otherwise
return;
}
// problem: entries created from client, come here with the (long) server guid,
// but getUIDMapping does not know them and can not map server-guid <--> client guid
$guid = $this->getUIDMapping($_guid);
if($guid === false) {
// this message is not really usefull here because setUIDMapping is only called when adding content to the client,
// however setUID is called also when adding content from the client. So in all other conditions this
// message will be logged.
//Horde::logMessage("SyncML: setUID $type, $locid, $guid something went wrong!!! Mapping not found.", __FILE__, __LINE__, PEAR_LOG_INFO);
$guid = $_guid;
//return false;
}
#Horde::logMessage("SyncML: setUID $_guid => $guid", __FILE__, __LINE__, PEAR_LOG_DEBUG);
if(!$ts) $ts = time();
Horde::logMessage("SyncML: setUID $type, $locid, $guid, $ts ",
__FILE__, __LINE__, PEAR_LOG_DEBUG);
$mapID = $this->_locName . $this->_sourceURI . $type;
// expire all client id's
$where = array(
'map_id' => $mapID,
'map_locuid' => $locid,
);
$GLOBALS['egw']->db->delete('egw_contentmap', $where,
__LINE__, __FILE__, 'syncml');
// expire old EGw id's
$where = array(
'map_id' => $mapID,
'map_guid' => $guid,
);
$GLOBALS['egw']->db->delete('egw_contentmap', $where,
__LINE__, __FILE__, 'syncml');
/*
$data = array ('map_expired' => true);
$GLOBALS['egw']->db->update('egw_contentmap', $data, $where,
__LINE__, __FILE__, 'syncml');
*/
$data = $where + array(
'map_locuid' => $locid,
'map_timestamp' => $ts,
'map_expired' => ($expired ? true : false),
);
$GLOBALS['egw']->db->insert('egw_contentmap', $data, $where,
__LINE__, __FILE__, 'syncml');
}
/**
* writes clients deviceinfo into database
*/
function writeClientDeviceInfo() {
if (!isset($this->_clientDeviceInfo)
|| !is_array($this->_clientDeviceInfo)) {
return false;
}
if (!isset($this->_clientDeviceInfo['persistent'])) {
// the device information was updated
if(!isset($this->size_dev_hwversion)) {
$tableDefDevInfo = $GLOBALS['egw']->db->get_table_definitions('syncml',$this->table_devinfo);
$this->size_dev_hwversion = $tableDefDevInfo['fd']['dev_hwversion']['precision'];
unset($tableDefDevInfo);
}
$softwareVersion = !empty($this->_clientDeviceInfo['softwareVersion']) ? $this->_clientDeviceInfo['softwareVersion'] : '';
$hardwareVersion = !empty($this->_clientDeviceInfo['hardwareVersion']) ? substr($this->_clientDeviceInfo['hardwareVersion'], 0, $this->size_dev_hwversion) : '';
$firmwareVersion = !empty($this->_clientDeviceInfo['firmwareVersion']) ? $this->_clientDeviceInfo['firmwareVersion'] : '';
$where = array(
'dev_model' => $this->_clientDeviceInfo['model'],
'dev_manufacturer' => $this->_clientDeviceInfo['manufacturer'],
'dev_swversion' => $softwareVersion,
'dev_hwversion' => $hardwareVersion,
'dev_fwversion' => $firmwareVersion,
);
if (($deviceID = $GLOBALS['egw']->db->select('egw_syncmldevinfo', 'dev_id', $where,
__LINE__, __FILE__, false, '', 'syncml')->fetchColumn())) {
$data = array (
'dev_datastore' => serialize($this->_clientDeviceInfo['dataStore']),
);
$GLOBALS['egw']->db->update('egw_syncmldevinfo', $data, $where,
__LINE__, __FILE__, 'syncml');
} else {
$data = array (
'dev_dtdversion' => $this->_clientDeviceInfo['DTDVersion'],
'dev_numberofchanges' => ($this->_clientDeviceInfo['supportNumberOfChanges'] ? true : false),
'dev_largeobjs' => ($this->_clientDeviceInfo['supportLargeObjs'] ? true : false),
'dev_utc' => ($this->_clientDeviceInfo['UTC'] ? true : false),
'dev_swversion' => $softwareVersion,
'dev_hwversion' => $hardwareVersion,
'dev_fwversion' => $firmwareVersion,
'dev_oem' => $this->_clientDeviceInfo['oem'],
'dev_model' => $this->_clientDeviceInfo['model'],
'dev_manufacturer' => $this->_clientDeviceInfo['manufacturer'],
'dev_devicetype' => $this->_clientDeviceInfo['deviceType'],
'dev_datastore' => serialize($this->_clientDeviceInfo['dataStore']),
);
$GLOBALS['egw']->db->insert('egw_syncmldevinfo', $data, $where, __LINE__, __FILE__, 'syncml');
$deviceID = $GLOBALS['egw']->db->get_last_insert_id('egw_syncmldevinfo', 'dev_id');
}
$this->_clientDeviceInfo['persistent'] = $deviceID;
}
$data = $where = array (
'owner_locname' => $this->_locName,
'owner_deviceid' => $this->_sourceURI,
);
$GLOBALS['egw']->db->delete('egw_syncmldeviceowner', $where,
__LINE__, __FILE__, 'syncml');
$data['owner_devid'] = $this->_clientDeviceInfo['persistent'];
$GLOBALS['egw']->db->insert('egw_syncmldeviceowner', $data, $where,
__LINE__, __FILE__, 'syncml');
}
/**
* After a successful sync, the client and server's Next Anchors
* are written to the database so they can be used to negotiate
* upcoming syncs.
*/
function writeSyncSummary() {
#parent::writeSyncSummary();
if (!isset($this->_serverAnchorNext)
|| !is_array($this->_serverAnchorNext)) {
return;
}
$deviceID = $this->_locName . $this->_sourceURI;
foreach((array)$this->_serverAnchorNext as $type => $a) {
Horde::logMessage("SyncML: write SYNCSummary for $deviceID "
. "$type serverts: $a clients: "
. $this->_clientAnchorNext[$type],
__FILE__, __LINE__, PEAR_LOG_DEBUG);
$where = array(
'dev_id' => $deviceID,
'sync_path' => $type,
);
$data = array(
'sync_serverts' => $a,
'sync_clientts' => $this->_clientAnchorNext[$type]
);
$GLOBALS['egw']->db->insert('egw_syncmlsummary', $data, $where,
__LINE__, __FILE__, 'syncml');
}
}
}

View File

@ -1,467 +0,0 @@
<?php
/**
* eGroupWare - SyncML based on Horde 3
*
*
* Using the PEAR Log class (which need to be installed!)
*
* @link http://www.egroupware.org
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package api
* @subpackage horde
* @author Anthony Mills <amills@pyramid6.com>
* @author Joerg Lehrke <jlehrke@noc.de>
* @copyright (c) The Horde Project (http://www.horde.org/)
* @version $Id$
*/
class Horde_SyncML_Sync {
/**
* Target, either contacts, notes, events,
*/
var $_targetLocURI;
var $_sourceLocURI;
var $_locName;
/**
* The synchronization method, one of the ALERT_* constants.
*
* @var integer
*/
var $_syncType;
/**
* Return if all commands success.
*/
var $globalSuccess;
/**
* This is the content type to use to export data.
*/
var $preferedContentType;
/**
* Optional filter expression for this content.
*
* @var string
*/
var $_filterExpression = '';
/**
* Do have the sync data loaded from the database already?
*/
var $syncDataLoaded;
function &factory($alert) {
Horde::logMessage('SyncML: new sync for alerttype ' . $alert, __FILE__, __LINE__, PEAR_LOG_DEBUG);
switch ($alert) {
case ALERT_TWO_WAY:
include_once 'Horde/SyncML/Sync/TwoWaySync.php';
return $sync = new Horde_SyncML_Sync_TwoWaySync();
case ALERT_SLOW_SYNC:
include_once 'Horde/SyncML/Sync/SlowSync.php';
return $sync = new Horde_SyncML_Sync_SlowSync();
case ALERT_ONE_WAY_FROM_CLIENT:
include_once 'Horde/SyncML/Sync/OneWayFromClientSync.php';
return $sync = new Horde_SyncML_Sync_OneWayFromClientSync();
case ALERT_REFRESH_FROM_CLIENT:
include_once 'Horde/SyncML/Sync/RefreshFromClientSync.php';
return $sync = new Horde_SyncML_Sync_RefreshFromClientSync();
case ALERT_ONE_WAY_FROM_SERVER:
include_once 'Horde/SyncML/Sync/OneWayFromServerSync.php';
return $sync = new Horde_SyncML_Sync_OneWayFromServerSync();
case ALERT_REFRESH_FROM_SERVER:
include_once 'Horde/SyncML/Sync/RefreshFromServerSync.php';
return $sync = new Horde_SyncML_Sync_RefreshFromServerSync();
}
require_once 'PEAR.php';
return PEAR::raiseError('Alert ' . $alert . ' not found.');
}
function nextSyncCommand($currentCmdID, &$syncCommand, &$output) {
$this->runSyncCommand($syncCommand);
if ($syncCommand->hasMoreData()) {
Horde::logMessage('SyncML: moreData: TRUE', __FILE__, __LINE__, PEAR_LOG_DEBUG);
$syncCommand->setStatus(RESPONSE_CHUNKED_ITEM_ACCEPTED_AND_BUFFERED);
}
return $syncCommand->output($currentCmdID, $output);
}
function startSync($currentCmdID, &$output) {
return $currentCmdID;
}
function endSync($currentCmdID, &$output) {
return $currentCmdID;
}
/**
* Setter for property sourceURI.
*
* @param string $sourceURI New value of property sourceLocURI.
*/
function setSourceLocURI($sourceURI) {
$this->_sourceLocURI = $sourceURI;
}
/**
* Get sourceURI.
*
* @return string $sourceURI or false on error.
*/
function getSourceLocURI() {
if (empty($this->_sourceLocURI)) {
return false;
}
return $this->_sourceLocURI;
}
/**
* Setter for property targetURI.
*
* @param string $targetURI New value of property targetLocURI.
*/
function setTargetLocURI($targetURI) {
$this->_targetLocURI = $targetURI;
}
/**
* Setter for property syncType.
*
* @param integer $syncType New value of property syncType.
*/
function setSyncType($syncType) {
$this->_syncType = $syncType;
}
/**
* Setter for property locName.
*
* @param string $locName New value of property locName.
*/
function setLocName($locName) {
$this->_locName = $locName;
}
/**
* Setter for property filterExpression.
*
* @param string $expression New value of property filterExpression.
*/
function setFilterExpression($expression) {
$this->_filterExpression = $expression;
}
/**
* Here's where the actual processing of a client-sent Sync
* Command takes place. Entries are added, deleted or replaced
* from the server database by using Horde API (Registry) calls.
*/
function runSyncCommand(&$command) {
global $registry;
$history = $GLOBALS['egw']->contenthistory;
$state = &$_SESSION['SyncML.state'];
$type = $this->_targetLocURI;
$syncml_prefs = $GLOBALS['egw_info']['user']['preferences']['syncml'];
if (isset($syncml_prefs[$type])) {
$sync_conflicts = $syncml_prefs[$type];
} else {
$sync_conflicts = CONFLICT_SERVER_WINNING;
}
$state->setLocName($this->_locName);
$locName = $state->getLocName();
$sourceURI = $state->getSourceURI();
$hordeType = $state->getHordeType($type);
$serverAnchorLast = $state->getServerAnchorLast($type);
$changes = array();
foreach($state->getChangedItems($type) as $change) {
// now we have to remove the ones
// that came from the last sync with this client
$guid_ts = $state->getSyncTSforAction($change, 'modify');
$sync_ts = $state->getChangeTS($type, $change);
if ($sync_ts && $sync_ts == $guid_ts) {
// Change was done by us upon request of client.
Horde::logMessage("SyncML: change: $change ignored, " .
"came from client", __FILE__, __LINE__, PEAR_LOG_DEBUG);
continue;
}
$changes[] = $change;
}
Horde::logMessage('SyncML: runSyncCommand found ' . count($changes) .
" possible conflicts for $type", __FILE__, __LINE__, PEAR_LOG_DEBUG);
if(!$contentType = $command->getContentType()) {
$contentType = $state->getPreferedContentType($type);
}
if (($contentType == 'text/x-vcalendar' || $contentType == 'text/calendar')
&& strpos($command->getContent(), 'BEGIN:VTODO') !== false) {
$hordeType = 'tasks';
}
$syncElementItems = $command->getSyncElementItems();
foreach($syncElementItems as $syncItem) {
$guid = false;
$locURI = $syncItem->getLocURI();
if (is_a($command, 'Horde_SyncML_Command_Sync_Add')) {
if ($sync_conflicts > CONFLICT_RESOLVED_WITH_DUPLICATE) {
// We enforce the client not to change anything
if ($sync_conflicts > CONFLICT_CLIENT_CHANGES_IGNORED) {
// delete this item from client
Horde::logMessage("SyncML: Server RO! REMOVE $locURI from client",
__FILE__, __LINE__, PEAR_LOG_WARNING);
$state->addConflictItem($type, $locURI);
} else {
Horde::logMessage('SyncML: Server RO! '
. 'REJECT all client changes',
__FILE__, __LINE__, PEAR_LOG_WARNING);
$state->log('Client-AddReplaceIgnored');
}
continue;
}
$guid = $registry->call($hordeType . '/import',
array($state->convertClient2Server($syncItem->getContent(), $contentType), $contentType));
if (!is_a($guid, 'PEAR_Error') && $guid != false) {
$ts = $state->getSyncTSforAction($guid, 'add');
$state->setUID($type, $locURI, $guid, $ts);
$state->log('Client-Add');
Horde::logMessage("SyncML: added client entry $locURI as $guid",
__FILE__, __LINE__, PEAR_LOG_DEBUG);
} else {
$state->log('Client-AddFailure');
Horde::logMessage('SyncML: Error in adding client entry ' . $locURI . ': '
. $guid->message, __FILE__, __LINE__, PEAR_LOG_ERR);
}
} elseif (is_a($command, 'Horde_SyncML_Command_Sync_Delete')) {
$guid = $state->removeUID($type, $locURI);
if (!$guid) {
// the entry is no longer on the server
$state->log('Client-DeleteFailure');
Horde::logMessage('SyncML: Failure deleting client entry ' . $locURI
. ', gone on server already!',
__FILE__, __LINE__, PEAR_LOG_ERR);
continue;
}
if ($sync_conflicts > CONFLICT_RESOLVED_WITH_DUPLICATE) {
// We enforce the client not to change anything
if ($sync_conflicts > CONFLICT_CLIENT_CHANGES_IGNORED) {
Horde::logMessage('SyncML: Server RO! ADD '
. $guid . ' to client again',
__FILE__, __LINE__, PEAR_LOG_WARNING);
$state->pushAddedItem($type, $guid);
} else {
Horde::logMessage('SyncML: '.
'Server RO! REJECT all client changes',
__FILE__, __LINE__, PEAR_LOG_WARNING);
}
$state->log('Client-DeleteIgnored');
continue;
}
elseif ($sync_conflicts == CONFLICT_RESOLVED_WITH_DUPLICATE &&
in_array($guid, $changes))
{
Horde::logMessage('SyncML: '.
'Server has updated version to keep',
__FILE__, __LINE__, PEAR_LOG_WARNING);
$state->log('Client-DeleteIgnored');
continue;
}
elseif ($sync_conflicts == CONFLICT_MERGE_DATA)
{
Horde::logMessage('SyncML: Server Merge Only: ADD '
. $guid . ' to client again',
__FILE__, __LINE__, PEAR_LOG_WARNING);
$state->pushAddedItem($type, $guid);
$state->log('Client-DeleteIgnored');
continue;
}
Horde::logMessage('SyncML: about to delete entry '
. $type .' / '. $guid . ' due to client request '
. $syncItem->getLocURI(), __FILE__, __LINE__, PEAR_LOG_DEBUG);
if (!is_a($guid, 'PEAR_Error') && $guid != false) {
$registry->call($hordeType . '/delete', array($guid));
$ts = $state->getSyncTSforAction($guid, 'delete');
$state->setUID($type, $locURI, $guid, $ts, 1);
$state->log('Client-Delete');
Horde::logMessage('SyncML: deleted entry '
. $guid . ' due to client request',
__FILE__, __LINE__, PEAR_LOG_DEBUG);
} else {
$state->log('Client-DeleteFailure');
Horde::logMessage('SyncML: Failure deleting client entry ' . $locURI
. ', maybe gone on server already: '
. $guid->message, __FILE__, __LINE__, PEAR_LOG_ERR);
}
} elseif (is_a($command, 'Horde_SyncML_Command_Sync_Replace')) {
$guid = $state->getGlobalUID($type, $locURI);
$replace = true;
$ok = false;
$merge = false;
if ($hordeType == 'configuration')
{
$command->setStatus(RESPONSE_ALREADY_EXISITS);
}
if ($guid)
{
Horde::logMessage('SyncML: locuri '. $locURI . ' guid ' . $guid , __FILE__, __LINE__, PEAR_LOG_DEBUG);
if (($sync_conflicts > CONFLICT_RESOLVED_WITH_DUPLICATE) || in_array($guid, $changes))
{
Horde::logMessage('SyncML: CONFLICT for locuri ' . $locURI . ' guid ' . $guid , __FILE__, __LINE__, PEAR_LOG_WARNING);
switch ($sync_conflicts)
{
case CONFLICT_CLIENT_WINNING:
$command->setStatus(RESPONSE_CONFLICT_RESOLVED_WITH_CLIENT_WINS);
break;
case CONFLICT_SERVER_WINNING:
Horde::logMessage('SyncML: REJECT client change for locuri ' .
$locURI . ' guid ' . $guid ,
__FILE__, __LINE__, PEAR_LOG_WARNING);
$command->setStatus(RESPONSE_CONFLICT_RESOLVED_WITH_SERVER_WINS);
$ok = true;
$replace = false;
$state->log('Client-AddReplaceIgnored');
break;
case CONFLICT_MERGE_DATA:
Horde::logMessage('SyncML: Merge server and client data for locuri ' .
$locURI . ' guid ' . $guid ,
__FILE__, __LINE__, PEAR_LOG_WARNING);
$command->setStatus(RESPONSE_CONFLICT_RESOLVED_WITH_MERGE);
$merge = true;
break;
case CONFLICT_RESOLVED_WITH_DUPLICATE:
$replace = false;
break;
case CONFLICT_CLIENT_CHANGES_IGNORED:
Horde::logMessage('SyncML: Server RO! REJECT client change for locuri ' .
$locURI . ' guid ' . $guid ,
__FILE__, __LINE__, PEAR_LOG_WARNING);
$command->setStatus(RESPONSE_PERMISSION_DENIED);
$ok = true;
$replace = false;
$ts = $state->getSyncTSforAction($guid, 'modify');
$state->setUID($type, $locURI, $guid, $ts);
$state->log('Client-AddReplaceIgnored');
break;
default: // We enforce our data on client
Horde::logMessage('SyncML: Server RO! UNDO client change for locuri ' .
$locURI . ' guid ' . $guid ,
__FILE__, __LINE__, PEAR_LOG_WARNING);
$command->setStatus(RESPONSE_PERMISSION_DENIED);
$state->pushChangedItem($type, $guid);
$ok = true;
$replace = false;
}
}
elseif ($sync_conflicts == CONFLICT_MERGE_DATA)
{
Horde::logMessage('SyncML: Merge server and client data for locuri ' .
$locURI . ' guid ' . $guid ,
__FILE__, __LINE__, PEAR_LOG_WARNING);
$merge = true;
}
if ($replace)
{
// Entry exists: replace/merge with current one.
$ok = $registry->call($hordeType . '/replace',
array($guid, $state->convertClient2Server($syncItem->getContent(),
$contentType), $contentType, $type, $merge));
if (!is_a($ok, 'PEAR_Error') && $ok != false)
{
$ts = $state->getSyncTSforAction($guid, 'modify');
$state->setUID($type, $locURI, $guid, $ts);
if ($merge)
{
Horde::logMessage('SyncML: Merged entry ' . $locURI . ' due to client request guid: ' .
$guid . ' ts: ' . $ts, __FILE__, __LINE__, PEAR_LOG_DEBUG);
}
else
{
Horde::logMessage('SyncML: replaced entry ' . $locURI . ' due to client request guid: ' .
$guid . ' ts: ' . $ts, __FILE__, __LINE__, PEAR_LOG_DEBUG);
}
$state->log('Client-Replace');
$ok = true;
}
else
{
// Entry may have been deleted; try adding it.
$ok = false;
}
}
}
if (!$ok) {
// Entry does either not exist in map or database, or should be added due to a conflict
if ($sync_conflicts > CONFLICT_RESOLVED_WITH_DUPLICATE) {
// We enforce the client not to change anything
if ($sync_conflicts > CONFLICT_CLIENT_CHANGES_IGNORED) {
// delete this item from client
Horde::logMessage('SyncML: Server RO! REMOVE ' . $locURI . ' from client',
__FILE__, __LINE__, PEAR_LOG_WARNING);
$state->addConflictItem($type, $syncItem->getLocURI());
} else {
Horde::logMessage('SyncML: Server RO! REJECT all client changes',
__FILE__, __LINE__, PEAR_LOG_WARNING);
}
continue;
}
Horde::logMessage('SyncML: try to add contentype '
. $contentType . ' for locuri ' . $locURI,
__FILE__, __LINE__, PEAR_LOG_DEBUG);
//continue;
$oguid = $guid;
$guid = $registry->call($hordeType . '/import',
array($state->convertClient2Server($syncItem->getContent(), $contentType), $contentType, $guid));
if (!is_a($guid, 'PEAR_Error')) {
if ($oguid != $guid) {
// We add a new entry
$ts = $state->getSyncTSforAction($guid, 'add');
Horde::logMessage('SyncML: added entry ' . $locURI . ' guid '
. $guid . ' from client',
__FILE__, __LINE__, PEAR_LOG_DEBUG);
$state->log('Client-Add');
} else {
// We replaced an entry
$ts = $state->getSyncTSforAction($guid, 'modify');
Horde::logMessage('SyncML: replaced entry ' . $locURI . ' guid '
. $guid . ' from client',
__FILE__, __LINE__, PEAR_LOG_DEBUG);
$state->log('Client-Replace');
}
$state->setUID($type, $locURI, $guid, $ts);
} else {
Horde::logMessage('SyncML: Error in replacing/'
. 'add client entry ' . $locURI . ' : ' . $guid->message,
__FILE__, __LINE__, PEAR_LOG_ERR);
$state->log('Client-AddFailure');
}
}
}
}
}
}

View File

@ -1,23 +0,0 @@
<?php
include_once 'Horde/SyncML/Sync.php';
/**
* No need to run anything at begining or end of sync, Sync will
* handle this.
*
* $Horde: framework/SyncML/SyncML/Sync/OneWayFromClientSync.php,v 1.6 2004/05/26 17:32:50 chuck Exp $
*
* Copyright 2003-2004 Anthony Mills <amills@pyramid6.com>
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Anthony Mills <amills@pyramid6.com>
* @version $Revision$
* @since Horde 3.0
* @package Horde_SyncML
*/
class Horde_SyncML_Sync_OneWayFromClientSync extends Horde_SyncML_Sync {
}

View File

@ -1,22 +0,0 @@
<?php
include_once 'Horde/SyncML/Sync/TwoWaySync.php';
/**
* Will run normal $end from TwoWaySync, the client should not send
* any changes.
*
* $Horde: framework/SyncML/SyncML/Sync/OneWayFromServerSync.php,v 1.6 2004/05/26 17:32:50 chuck Exp $
*
* Copyright 2003-2004 Anthony Mills <amills@pyramid6.com>
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Anthony Mills <amills@pyramid6.com>
* @version $Revision$
* @since Horde 3.0
* @package Horde_SyncML
*/
class Horde_SyncML_Sync_OneWayFromServerSync extends Horde_SyncML_Sync_TwoWaySync {
}

View File

@ -1,23 +0,0 @@
<?php
include_once 'Horde/SyncML/Sync/SlowSync.php';
/**
* $Horde: framework/SyncML/SyncML/Sync/RefreshFromClientSync.php,v 1.8 2004/09/14 04:27:06 chuck Exp $
*
* Copyright 2003-2004 Anthony Mills <amills@pyramid6.com>
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Anthony Mills <amills@pyramid6.com>
* @version $Revision$
* @since Horde 3.0
* @package Horde_SyncML
*/
class Horde_SyncML_Sync_RefreshFromClientSync extends Horde_SyncML_Sync_SlowSync {
/**
* We needed to erase the current server contents, then we can add
* the client's contents.
*/
}

View File

@ -1,187 +0,0 @@
<?php
/**
* eGroupWare - SyncML based on Horde 3
*
*
* Using the PEAR Log class (which need to be installed!)
*
* @link http://www.egroupware.org
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package api
* @subpackage horde
* @author Anthony Mills <amills@pyramid6.com>
* @author Joerg Lehrke <jlehrke@noc.de>
* @copyright (c) The Horde Project (http://www.horde.org/)
* @version $Id$
*/
include_once 'Horde/SyncML/Sync.php';
class Horde_SyncML_Sync_RefreshFromServerSync extends Horde_SyncML_Sync_TwoWaySync {
function handleSync($currentCmdID, $hordeType, $syncType, &$output, $refts) {
global $registry;
$state = &$_SESSION['SyncML.state'];
$maxMsgSize = $state->getMaxMsgSizeClient();
$deviceInfo = $state->getClientDeviceInfo();
if (isset($deviceInfo['maxEntries'])) {
$maxEntries = $deviceInfo['maxEntries'];
if (!$maxMsgSize && !$maxEntries) {
// fallback to default
$maxEntries = MAX_ENTRIES;
}
} else {
$maxEntries = MAX_ENTRIES;
}
$serverAnchorNext = $state->getServerAnchorNext($syncType);
if (isset($state->curSyncItem)) {
// Finish the pending sync item
$cmd = &$state->curSyncItem;
if (!is_a($cmd, 'Horde_SyncML_Command_Sync_ContentSyncElement')) {
// Conflict with other datastore
Horde :: logMessage("SyncML: handleSync($currentCmdID, $hordeType, $syncType) moreData conflict found",
__FILE__, __LINE__, PEAR_LOG_WARNING);
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
return $currentCmdID;
}
unset($state->curSyncItem);
$currentCmdID = $cmd->outputCommand($currentCmdID, $output, 'Sync');
// moreData split; save in session state and end current message
if ($cmd->hasMoreData()) {
$state->curSyncItem = &$cmd;
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
return $currentCmdID;
}
$state->incNumberOfElements();
}
$adds = &$state->getAddedItems($syncType);
Horde::logMessage("SyncML: ".count($adds).
' added items found for '.$syncType ,
__FILE__, __LINE__, PEAR_LOG_DEBUG);
if(is_array($adds)) {
while($guid = array_shift($adds)) {
$currentSize = $output->getOutputSize();
// return if we have to much data
if (($maxEntries && ($state->getNumberOfElements() >= $maxEntries)
&& isset($contentType['mayFragment'])
&& $contentType['mayFragment'])
|| ($maxMsgSize
&& (($currentSize + MIN_MSG_LEFT * 2) > $maxMsgSize))) {
// put the item back in the queue
$adds[] = $guid;
$state->maxNumberOfElements();
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
return $currentCmdID;
}
if ($locID = $state->getLocID($syncType, $guid)) {
Horde::logMessage("SyncML: RefreshFromServerSync add to client: $guid ignored, already at client($locID)",
__FILE__, __LINE__, PEAR_LOG_DEBUG);
continue;
}
$guid_ts = $state->getSyncTSforAction($guid, 'add');
if ($guid_ts > $serverAnchorNext) {
// Change was made after we started this sync.
// Don't sent this now to the client.
Horde::logMessage("SyncML: RefreshFromServerSync add $guid is in our future",
__FILE__, __LINE__, PEAR_LOG_DEBUG);
continue;
}
$contentType = $state->getPreferedContentTypeClient($this->_sourceLocURI, $this->_targetLocURI);
$c = $registry->call($hordeType . '/export', array('guid' => $guid, 'contentType' => $contentType));
if ($c === false) continue; // no content to export
if (is_a($c, 'PEAR_Error')) {
Horde::logMessage("SyncML: refresh failed to export guid $guid:\n" . print_r($c, true),
__FILE__, __LINE__, PEAR_LOG_WARNING);
$state->log("Server-ExportFailed");
continue;
}
$size = strlen($c);
// return if we have to much data
if ($maxMsgSize && !$deviceInfo['supportLargeObjs']) {
if (($size + MIN_MSG_LEFT * 2) > $maxMsgSize) {
Horde::logMessage("SyncML: refresh failed to export guid $guid due to size $size",
__FILE__, __LINE__, PEAR_LOG_ERROR);
$state->log("Server-ExportFailed");
continue;
}
if (($currentSize + $size + MIN_MSG_LEFT * 2) > $maxMsgSize) {
// put the item back in the queue
$adds[] = $guid;
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
return $currentCmdID;
}
}
Horde::logMessage("SyncML: refresh add $guid to client\n$c",
__FILE__, __LINE__, PEAR_LOG_DEBUG);
$cmd = new Horde_SyncML_Command_Sync_ContentSyncElement();
$cmd->setContent($c);
$cmd->setContentType($contentType['ContentType']);
if (isset($contentType['ContentFormat'])) {
$cmd->setContentFormat($contentType['ContentFormat']);
}
$cmd->setGUID($guid);
$currentCmdID = $cmd->outputCommand($currentCmdID, $output, 'Add');
$state->log('Server-Add');
// moreData split; put the guid back in the list and return
if ($cmd->hasMoreData()) {
$state->curSyncItem = &$cmd;
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
return $currentCmdID;
}
$state->incNumberOfElements();
}
}
Horde::logMessage("SyncML: All items handled for sync $syncType",
__FILE__, __LINE__, PEAR_LOG_DEBUG);
$state->removeExpiredUID($syncType, $serverAnchorNext);
$state->clearSync($syncType);
return $currentCmdID;
}
function loadData() {
global $registry;
$state = &$_SESSION['SyncML.state'];
$syncType = $this->_targetLocURI;
$hordeType = $state->getHordeType($syncType);
$state->setTargetURI($syncType);
$future = $state->getServerAnchorNext($syncType);
$delta_add = 0;
Horde::logMessage("SyncML: reading added items from database for $hordeType",
__FILE__, __LINE__, PEAR_LOG_DEBUG);
/* The items, which now match the filter criteria are show here, too
$state->setAddedItems($syncType, $registry->call($hordeType. '/listBy',
array('action' => 'add',
'timestamp' => $future,
'type' => $syncType,
'filter' => $this->_filterExpression)));
$delta_add = count($state->getAddedItems($hordeType));
*/
$state->mergeAddedItems($syncType, $registry->call($hordeType. '/list',array('filter' => $this->_filterExpression)));
$this->_syncDataLoaded = TRUE;
return count($state->getAddedItems($syncType)) - $delta_add;
}
}

View File

@ -1,314 +0,0 @@
<?php
/**
* eGroupWare - SyncML based on Horde 3
*
* Slow sync may just work; I think most of the work is going to be
* done by the API.
*
*
* Using the PEAR Log class (which need to be installed!)
*
* @link http://www.egroupware.org
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package api
* @subpackage horde
* @author Anthony Mills <amills@pyramid6.com>
* @author Joerg Lehrke <jlehrke@noc.de>
* @copyright (c) The Horde Project (http://www.horde.org/)
* @version $Id$
*/
include_once 'Horde/SyncML/Sync/TwoWaySync.php';
class Horde_SyncML_Sync_SlowSync extends Horde_SyncML_Sync_TwoWaySync {
function handleSync($currentCmdID, $hordeType, $syncType, &$output, $refts) {
global $registry;
$history = $GLOBALS['egw']->contenthistory;
$state = &$_SESSION['SyncML.state'];
$maxMsgSize = $state->getMaxMsgSizeClient();
$deviceInfo = $state->getClientDeviceInfo();
if (isset($deviceInfo['maxEntries'])) {
$maxEntries = $deviceInfo['maxEntries'];
if (!$maxMsgSize && !$maxEntries) {
// fallback to default
$maxEntries = MAX_ENTRIES;
}
} else {
$maxEntries = MAX_ENTRIES;
}
$serverAnchorNext = $state->getServerAnchorNext($syncType);
// now we remove all UID from contentmap that have not been verified in this slowsync
$state->removeOldUID($syncType, $serverAnchorNext);
if (isset($state->curSyncItem)) {
// Finish the pending sync item
$cmd = &$state->curSyncItem;
if (!is_a($cmd, 'Horde_SyncML_Command_Sync_ContentSyncElement')) {
// Conflict with other datastore
Horde :: logMessage("SyncML: handleSync($currentCmdID, $hordeType, $syncType) moreData conflict found",
__FILE__, __LINE__, PEAR_LOG_WARNING);
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
return $currentCmdID;
}
unset($state->curSyncItem);
$currentCmdID = $cmd->outputCommand($currentCmdID, $output, 'Sync');
// moreData split; save in session state and end current message
if ($cmd->hasMoreData()) {
$state->curSyncItem = &$cmd;
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
return $currentCmdID;
}
$state->incNumberOfElements();
}
$adds =& $state->getAddedItems($syncType);
$conflicts =& $state->getConflictItems($syncType);
Horde::logMessage('SyncML: ' .count($adds). ' added items found for ' .$syncType, __FILE__, __LINE__, PEAR_LOG_DEBUG);
Horde::logMessage('SyncML: ' . count($conflicts) . ' items to delete on client found for ' . $syncType, __FILE__, __LINE__, PEAR_LOG_DEBUG);
if (is_array($adds)) {
while ($guid = array_shift($adds)) {
$currentSize = $output->getOutputSize();
// return if we have to much data
if (($maxEntries && ($state->getNumberOfElements() >= $maxEntries)
&& isset($contentType['mayFragment'])
&& $contentType['mayFragment']) ||
($maxMsgSize && (($currentSize + MIN_MSG_LEFT * 2) > $maxMsgSize))) {
// put the item back in the queue
$adds[] = $guid;
$state->maxNumberOfElements();
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
return $currentCmdID;
}
if (($locID = $state->getLocID($syncType, $guid))) {
Horde::logMessage("SyncML: slowsync add to client: $guid ignored, already at client($locID)",
__FILE__, __LINE__, PEAR_LOG_DEBUG);
continue;
}
$guid_ts = $state->getSyncTSforAction($guid, 'add');
if ($guid_ts > $serverAnchorNext) {
// Change was made after we started this sync.
// Don't sent this now to the client.
Horde::logMessage("SyncML: slowsync add $guid is in our future",
__FILE__, __LINE__, PEAR_LOG_DEBUG);
continue;
}
$contentType = $state->getPreferedContentTypeClient($this->_sourceLocURI, $this->_targetLocURI);
$c = $registry->call($hordeType . '/export', array('guid' => $guid, 'contentType' => $contentType));
if ($c === false) continue; // no content to export
if (is_a($c, 'PEAR_Error')) {
Horde::logMessage("SyncML: slowsync failed to export guid $guid:\n" . print_r($c, true),
__FILE__, __LINE__, PEAR_LOG_WARNING);
continue;
}
$size = strlen($c);
// return if we have to much data
if ($maxMsgSize && !$deviceInfo['supportLargeObjs']) {
if (($size + MIN_MSG_LEFT * 2) > $maxMsgSize) {
Horde::logMessage("SyncML: slowsync failed to export guid $guid due to size $size",
__FILE__, __LINE__, PEAR_LOG_ERROR);
continue;
}
if (($currentSize + $size + MIN_MSG_LEFT * 2) > $maxMsgSize) {
// put the item back in the queue
$adds[] = $guid;
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
return $currentCmdID;
}
}
Horde::logMessage("SyncML: slowsync add guid $guid to client\n$c",
__FILE__, __LINE__, PEAR_LOG_DEBUG);
$cmd = new Horde_SyncML_Command_Sync_ContentSyncElement();
$cmd->setContent($c);
$cmd->setContentType($contentType['ContentType']);
if (isset($contentType['ContentFormat'])) {
$cmd->setContentFormat($contentType['ContentFormat']);
}
$cmd->setGUID($guid);
$currentCmdID = $cmd->outputCommand($currentCmdID, $output, 'Add');
$state->log('Server-Add');
// moreData split; save in session state and end current message
if ($cmd->hasMoreData()) {
$state->curSyncItem = &$cmd;
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
return $currentCmdID;
}
$state->incNumberOfElements();
}
}
// handle remote deletes due to conflicts
if (count($conflicts) > 0) {
while ($locid = array_shift($conflicts)) {
$currentSize = $output->getOutputSize();
// return if we have to much data
if (($maxEntries && ($state->getNumberOfElements() >= $maxEntries)
&& isset ($contentType['mayFragment'])
&& $contentType['mayFragment'])
|| ($maxMsgSize
&& (($currentSize +MIN_MSG_LEFT * 2) > $maxMsgSize))) {
// put the item back in the queue
$conflicts[] = $locid;
$state->maxNumberOfElements();
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
return $currentCmdID;
}
Horde :: logMessage("SyncML: delete client locid: $locid",
__FILE__, __LINE__, PEAR_LOG_DEBUG);
// Create a Delete request for client.
$cmd = new Horde_SyncML_Command_Sync_ContentSyncElement();
$cmd->setLocURI($locid);
$currentCmdID = $cmd->outputCommand($currentCmdID, $output, 'Delete');
$state->log('Server-DeletedConflicts');
$state->removeUID($syncType, $locid);
// moreData split; save in session state and end current message
if ($cmd->hasMoreData()) {
$state->curSyncItem = & $cmd;
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
return $currentCmdID;
}
$state->incNumberOfElements();
}
}
Horde::logMessage("SyncML: All items handled for sync $syncType",
__FILE__, __LINE__, PEAR_LOG_DEBUG);
$state->removeExpiredUID($syncType, $serverAnchorNext);
$state->clearSync($syncType);
return $currentCmdID;
}
/**
* Here's where the actual processing of a client-sent Sync
* Command takes place. Entries are added or replaced
* from the server database by using Horde API (Registry) calls.
*/
function runSyncCommand(&$command) {
global $registry;
$history = $GLOBALS['egw']->contenthistory;
$state = &$_SESSION['SyncML.state'];
$type = $this->_targetLocURI;
$syncml_prefs = $GLOBALS['egw_info']['user']['preferences']['syncml'];
if (isset($syncml_prefs[$type])) {
$sync_conflicts = $syncml_prefs[$type];
} else {
$sync_conflicts = CONFLICT_SERVER_WINNING;
}
$hordeType = $state->getHordeType($type);
$syncElementItems = $command->getSyncElementItems();
foreach($syncElementItems as $syncItem) {
if(!$contentType = $syncItem->getContentType()) {
$contentType = $state->getPreferedContentType($type);
}
if (($contentType == 'text/x-vcalendar' || $contentType == 'text/calendar')
&& strpos($syncItem->getContent(), 'BEGIN:VTODO') !== false) {
$hordeType = 'tasks';
}
$guid = false;
$locURI = $syncItem->getLocURI();
$oguid = $state->getGlobalUID($type, $locURI);
$guid = $registry->call($hordeType . '/search',
array($state->convertClient2Server($syncItem->getContent(), $contentType), $contentType, $oguid, $type));
if (!is_a($guid, 'PEAR_Error') && $guid) {
// Check if the found entry came from the client
$guid_ts = $state->getSyncTSforAction($guid, 'add');
$sync_ts = $state->getChangeTS($type, $guid);
if ($oguid != $guid && $sync_ts && $sync_ts == $guid_ts) {
// Entry came from the client, so we get a duplicate here
Horde::logMessage('SyncML: CONFLICT for locuri ' . $syncItem->getLocURI()
. ' guid ' . $guid , __FILE__, __LINE__, PEAR_LOG_WARNING);
if ($sync_conflicts != CONFLICT_RESOLVED_WITH_DUPLICATE) {
$state->log("Client-AddReplaceIgnored");
$command->setStatus(RESPONSE_CONFILCT_RESOLVED_WITH_DUPLICATE);
continue;
}
} else {
# Entry exists in database already. Just update the mapping
Horde::logMessage("SyncML: adding mapping for locuri: $locURI and guid: $guid",
__FILE__, __LINE__, PEAR_LOG_DEBUG);
$state->setUID($type, $locURI, $guid);
$state->log("Client-Map");
$command->setStatus(RESPONSE_ALREADY_EXISITS);
continue;
}
}
if ($sync_conflicts > CONFLICT_RESOLVED_WITH_DUPLICATE) {
// We enforce the client not to change anything
if ($sync_conflicts > CONFLICT_CLIENT_CHANGES_IGNORED) {
// delete this item from client
Horde::logMessage("SyncML: Server RO! REMOVE $locURI from client",
__FILE__, __LINE__, PEAR_LOG_WARNING);
$state->addConflictItem($type, $locURI);
} else {
Horde::logMessage('SyncML: Server RO! REJECT all client changes',
__FILE__, __LINE__, PEAR_LOG_WARNING);
$state->log("Client-AddReplaceIgnored");
}
$command->setStatus(RESPONSE_NO_EXECUTED);
continue;
}
// Add entry to the database.
$state->removeUID($type, $locURI);
Horde::logMessage("SyncML: try to add $locURI with contentype $contentType to $hordeType",
__FILE__, __LINE__, PEAR_LOG_DEBUG);
$guid = $registry->call($hordeType . '/import',
array($state->convertClient2Server($syncItem->getContent(), $contentType), $contentType));
if (!is_a($guid, 'PEAR_Error') && $guid) {
// first we try the modification timestamp then the creation ts
if (!($ts = $state->getSyncTSforAction($guid, 'modify'))) {
$ts = $state->getSyncTSforAction($guid, 'add');
}
$state->setUID($type, $locURI, $guid, $ts);
$state->log("Client-AddReplace");
Horde::logMessage("SyncML: replaced/added client entry $locURI as $guid",
__FILE__, __LINE__, PEAR_LOG_DEBUG);
} else {
Horde::logMessage('SyncML: Error in replacing/add client entry ' . $locURI . ': '. $guid->message,
__FILE__, __LINE__, PEAR_LOG_ERR);
$state->log("Client-AddFailure");
}
}
}
function loadData() {
global $registry;
$state = &$_SESSION['SyncML.state'];
$syncType = $this->_targetLocURI;
$hordeType = $state->getHordeType($syncType);
$state->setTargetURI($syncType);
$future = $state->getServerAnchorNext($syncType);
$state->mergeAddedItems($syncType, $registry->call($hordeType. '/list', array('filter' => $this->_filterExpression)));
$this->_syncDataLoaded = TRUE;
return count($state->getAddedItems($syncType)) + count($state->getConflictItems($syncType));
}
}

View File

@ -1,460 +0,0 @@
<?php
/**
* eGroupWare - SyncML based on Horde 3
*
*
* Using the PEAR Log class (which need to be installed!)
*
* @link http://www.egroupware.org
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package api
* @subpackage horde
* @author Anthony Mills <amills@pyramid6.com>
* @author Karsten Fourmont <fourmont@gmx.de>
* @author Joerg Lehrke <jlehrke@noc.de>
* @copyright (c) The Horde Project (http://www.horde.org/)
* @version $Id$
*/
include_once 'Horde/SyncML/Sync.php';
include_once 'Horde/SyncML/Command/Sync/ContentSyncElement.php';
class Horde_SyncML_Sync_TwoWaySync extends Horde_SyncML_Sync {
function endSync($currentCmdID, & $output) {
global $registry;
$state = & $_SESSION['SyncML.state'];
$syncType = $this->_targetLocURI;
$hordeType = $state->getHordeType($syncType);
$refts = $state->getServerAnchorLast($syncType);
$currentCmdID = $this->handleSync($currentCmdID, $hordeType, $syncType, $output, $refts);
return $currentCmdID;
}
function handleSync($currentCmdID, $hordeType, $syncType, & $output, $refts) {
global $registry;
// array of Items which got modified, but got never send to the client before
$missedAdds = array ();
$history = $GLOBALS['egw']->contenthistory;
$state = & $_SESSION['SyncML.state'];
$maxMsgSize = $state->getMaxMsgSizeClient();
$deviceInfo = $state->getClientDeviceInfo();
if (isset($deviceInfo['maxEntries'])) {
$maxEntries = $deviceInfo['maxEntries'];
if (!$maxMsgSize && !$maxEntries) {
// fallback to default
$maxEntries = MAX_ENTRIES;
}
} else {
$maxEntries = MAX_ENTRIES;
}
$serverAnchorNext = $state->getServerAnchorNext($syncType);
if (isset ($state->curSyncItem)) {
// Finish the pending sync item
$cmd = & $state->curSyncItem;
if (!is_a($cmd, 'Horde_SyncML_Command_Sync_ContentSyncElement')) {
// Conflict with other datastore
Horde :: logMessage("SyncML: handleSync($currentCmdID, $hordeType, $syncType) moreData conflict found",
__FILE__, __LINE__, PEAR_LOG_WARNING);
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
return $currentCmdID;
}
unset ($state->curSyncItem);
$currentCmdID = $cmd->outputCommand($currentCmdID, $output, 'Sync');
// moreData split; save in session state and end current message
if ($cmd->hasMoreData()) {
$state->curSyncItem = & $cmd;
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
return $currentCmdID;
}
$state->incNumberOfElements();
}
$changes =& $state->getChangedItems($syncType);
$deletes =& $state->getDeletedItems($syncType);
$adds =& $state->getAddedItems($syncType);
$conflicts =& $state->getConflictItems($syncType);
Horde::logMessage('SyncML: ' . count($changes) . ' changed items found for ' . $syncType, __FILE__, __LINE__, PEAR_LOG_DEBUG);
Horde::logMessage('SyncML: ' . count($deletes) . ' deleted items found for ' . $syncType, __FILE__, __LINE__, PEAR_LOG_DEBUG);
Horde::logMessage('SyncML: ' . count($conflicts) . ' items to delete on client found for ' . $syncType, __FILE__, __LINE__, PEAR_LOG_DEBUG);
Horde::logMessage('SyncML: ' . count($adds) . ' added items found for ' . $syncType, __FILE__, __LINE__, PEAR_LOG_DEBUG);
// handle changes
if (is_array($changes)) {
while ($guid = array_shift($changes)) {
$currentSize = $output->getOutputSize();
// return if we have to much data
if (($maxEntries
&& ($state->getNumberOfElements() >= $maxEntries)
&& isset ($contentType['mayFragment'])
&& $contentType['mayFragment'])
|| ($maxMsgSize
&& (($currentSize +MIN_MSG_LEFT * 2) > $maxMsgSize))) {
// put the item back in the queue
$changes[] = $guid;
$state->maxNumberOfElements();
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
return $currentCmdID;
}
$guid_ts = $state->getSyncTSforAction($guid, 'modify');
$sync_ts = $state->getChangeTS($syncType, $guid);
Horde :: logMessage("SyncML: timestamp modify $guid guid_ts: $guid_ts sync_ts: $sync_ts",
__FILE__, __LINE__, PEAR_LOG_DEBUG);
if ($sync_ts && $sync_ts == $guid_ts) {
// Change was done by us upon request of client.
// Don't mirror that back to the client.
Horde :: logMessage("SyncML: change: $guid ignored, came from client",
__FILE__, __LINE__, PEAR_LOG_DEBUG);
continue;
}
if ($guid_ts > $serverAnchorNext) {
// Change was made after we started this sync.
// Don't sent this now to the client.
Horde :: logMessage("SyncML: change $guid is in our future: $serverAnchorNext",
__FILE__, __LINE__, PEAR_LOG_DEBUG);
continue;
}
$locid = $state->getLocID($syncType, $guid);
if (!$locid) {
// somehow we missed to add, lets store the uid, so we add this entry later
$missedAdds[] = $guid;
Horde :: logMessage("SyncML: unable to create change for $guid: locid not found in map",
__FILE__, __LINE__, PEAR_LOG_WARNING);
continue;
}
// Create a replace request for client.
$contentType = $state->getPreferedContentTypeClient($this->_sourceLocURI, $this->_targetLocURI);
$c = $registry->call($hordeType . '/export', array (
'guid' => $guid,
'contentType' => $contentType
));
if ($c === false) continue; // no content to export
if (is_a($c, 'PEAR_Error')) {
// Item in history but not in database. Strange, but can happen.
Horde :: logMessage("SyncML: change: export of guid $guid failed:\n" . print_r($c, true),
__FILE__, __LINE__, PEAR_LOG_WARNING);
continue;
}
$size = strlen($c);
// return if we have to much data
if ($maxMsgSize && !$deviceInfo['supportLargeObjs']) {
if (($size + MIN_MSG_LEFT * 2) > $maxMsgSize) {
Horde :: logMessage("SyncML: change: export of guid $guid failed due to size $size",
__FILE__, __LINE__, PEAR_LOG_ERROR);
$state->log('Server-ExportFailed');
continue;
}
if (($currentSize + $size + MIN_MSG_LEFT * 2) > $maxMsgSize) {
// put the item back in the queue
$changes[] = $guid;
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
return $currentCmdID;
}
}
Horde :: logMessage("SyncML: change: export guid $guid, content:\n$c",
__FILE__, __LINE__, PEAR_LOG_DEBUG);
$cmd = new Horde_SyncML_Command_Sync_ContentSyncElement();
# LK $cmd->setContent($state->convertServer2Client($c, $contentType));
$cmd->setContent($c);
$cmd->setLocURI($locid);
$cmd->setContentType($contentType['ContentType']);
if (isset ($contentType['ContentFormat'])) {
$cmd->setContentFormat($contentType['ContentFormat']);
}
$currentCmdID = $cmd->outputCommand($currentCmdID, $output, 'Replace');
$state->log('Server-Replace');
// moreData split; save in session state and end current message
if ($cmd->hasMoreData()) {
$state->curSyncItem = & $cmd;
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
return $currentCmdID;
}
$state->incNumberOfElements();
}
}
Horde :: logMessage("SyncML: handling sync (changes done) " . $currentCmdID,
__FILE__, __LINE__, PEAR_LOG_DEBUG);
// handle deletes
if (is_array($deletes)) {
while ($guid = array_shift($deletes)) {
$currentSize = $output->getOutputSize();
// return if we have to much data
if (($maxEntries && ($state->getNumberOfElements() >= $maxEntries)
&& isset ($contentType['mayFragment'])
&& $contentType['mayFragment'])
|| ($maxMsgSize
&& (($currentSize + MIN_MSG_LEFT * 2) > $maxMsgSize))) {
// put the item back in the queue
$deletes[] = $guid;
$state->maxNumberOfElements();
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
return $currentCmdID;
}
$guid_ts = $state->getSyncTSforAction($guid, 'delete');
$sync_ts = $state->getChangeTS($syncType, $guid);
Horde :: logMessage("SyncML: timestamp delete guid_ts: $guid_ts sync_ts: $sync_ts",
__FILE__, __LINE__, PEAR_LOG_DEBUG);
if ($sync_ts && $sync_ts == $guid_ts) {
// Change was done by us upon request of client.
// Don't mirror that back to the client.
Horde :: logMessage("SyncML: delete $guid ignored, came from client",
__FILE__, __LINE__, PEAR_LOG_DEBUG);
if ($sync_ts < $serverAnchorNext
&& ($locid = $state->getLocID($syncType, $guid))) {
// Now we can remove the past
$state->removeUID($syncType, $locid);
}
continue;
}
if ($guid_ts > $serverAnchorNext) {
// Change was made after we started this sync.
// Don't sent this now to the client.
Horde :: logMessage("SyncML: delete $guid is in our future: $serverAnchorNext", __FILE__, __LINE__, PEAR_LOG_DEBUG);
continue;
}
$locid = $state->getLocID($syncType, $guid);
if (!$locid) {
Horde :: logMessage("SyncML: unable to delete $guid: locid not found in map", __FILE__, __LINE__, PEAR_LOG_INFO);
$state->log("Server-DeleteFailure");
continue;
}
Horde :: logMessage("SyncML: delete: $guid", __FILE__, __LINE__, PEAR_LOG_DEBUG);
// Create a Delete request for client.
$cmd = new Horde_SyncML_Command_Sync_ContentSyncElement();
$cmd->setLocURI($locid);
$currentCmdID = $cmd->outputCommand($currentCmdID, $output, 'Delete');
$state->log('Server-Delete');
$state->removeUID($syncType, $locid);
// moreData split; save in session state and end current message
if ($cmd->hasMoreData()) {
$state->curSyncItem = & $cmd;
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
return $currentCmdID;
}
$state->incNumberOfElements();
}
}
// handle remote deletes due to conflicts
if (count($conflicts) > 0) {
while ($locid = array_shift($conflicts)) {
$currentSize = $output->getOutputSize();
// return if we have to much data
if (($maxEntries && ($state->getNumberOfElements() >= $maxEntries)
&& isset ($contentType['mayFragment'])
&& $contentType['mayFragment'])
|| ($maxMsgSize
&& (($currentSize +MIN_MSG_LEFT * 2) > $maxMsgSize))) {
// put the item back in the queue
$conflicts[] = $locid;
$state->maxNumberOfElements();
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
return $currentCmdID;
}
Horde :: logMessage("SyncML: delete client locid: $locid", __FILE__, __LINE__, PEAR_LOG_DEBUG);
// Create a Delete request for client.
$cmd = new Horde_SyncML_Command_Sync_ContentSyncElement();
$cmd->setLocURI($locid);
$currentCmdID = $cmd->outputCommand($currentCmdID, $output, 'Delete');
$state->log('Server-DeletedConflicts');
$state->removeUID($syncType, $locid);
// moreData split; save in session state and end current message
if ($cmd->hasMoreData()) {
$state->curSyncItem = & $cmd;
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
return $currentCmdID;
}
$state->incNumberOfElements();
}
}
// Horde::logMessage("SyncML: handling sync ".$currentCmdID, __FILE__, __LINE__, PEAR_LOG_DEBUG);
// handle missing adds.
if (count($missedAdds) > 0) {
Horde :: logMessage("SyncML: add missed changes as adds " . count($adds) . ' / ' . $missedAdds[0],
__FILE__, __LINE__, PEAR_LOG_DEBUG);
$adds = array_merge($adds, $missedAdds);
Horde :: logMessage("SyncML: merged adds counter " . count($adds) . ' / ' . $adds[0],
__FILE__, __LINE__, PEAR_LOG_DEBUG);
}
if (is_array($adds)) {
while ($guid = array_shift($adds)) {
$currentSize = $output->getOutputSize();
// return if we have to much data
if (($maxEntries && ($state->getNumberOfElements() >= $maxEntries)
&& isset ($contentType['mayFragment'])
&& $contentType['mayFragment'])
|| ($maxMsgSize
&& (($currentSize +MIN_MSG_LEFT * 2) > $maxMsgSize))) {
// put the item back in the queue
$adds[] = $guid;
$state->maxNumberOfElements();
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
return $currentCmdID;
}
// first we try the modification timestamp then the creation ts
if (!($guid_ts = $state->getSyncTSforAction($guid, 'modify'))) {
$guid_ts = $state->getSyncTSforAction($guid, 'add');
}
$sync_ts = $state->getChangeTS($syncType, $guid);
Horde :: logMessage("SyncML: timestamp add $guid guid_ts: $guid_ts sync_ts: $sync_ts", __FILE__, __LINE__, PEAR_LOG_DEBUG);
if ($sync_ts && $sync_ts == $guid_ts) {
// Change was done by us upon request of client.
// Don't mirror that back to the client.
Horde :: logMessage("SyncML: add: $guid ignored, came from client",
__FILE__, __LINE__, PEAR_LOG_DEBUG);
continue;
}
if ($guid_ts > $serverAnchorNext && !in_array($guid, $conflicts)) {
// Change was made after we started this sync.
// Don't sent this now to the client.
Horde :: logMessage("SyncML: add $guid is in our future: $serverAnchorNext",
__FILE__, __LINE__, PEAR_LOG_DEBUG);
continue;
}
$locid = $state->getLocID($syncType, $guid);
if ($locid && $refts == 0) {
// For slow sync (ts=0): do not add data for which we
// have a locid again. This is a heuristic to avoid
// duplication of entries.
Horde :: logMessage("SyncML: skipping add of guid $guid as there already is a locid $locid", __FILE__, __LINE__, PEAR_LOG_DEBUG);
continue;
}
Horde :: logMessage("SyncML: add: $guid", __FILE__, __LINE__, PEAR_LOG_DEBUG);
// Create an Add request for client.
$contentType = $state->getPreferedContentTypeClient($this->_sourceLocURI, $this->_targetLocURI);
$c = $registry->call($hordeType . '/export', array (
'guid' => $guid,
'contentType' => $contentType,
));
if ($c === false) continue; // no content to export
if (is_a($c, 'PEAR_Error')) {
// Item in history but not in database. Strange, but can happen.
Horde :: logMessage("SyncML: add: export of guid $guid failed:\n" . print_r($c, true),
__FILE__, __LINE__, PEAR_LOG_WARNING);
continue;
}
$size = strlen($c);
// return if we have to much data
if ($maxMsgSize && !$deviceInfo['supportLargeObjs']) {
if (($size +MIN_MSG_LEFT * 2) > $maxMsgSize) {
Horde :: logMessage("SyncML: add: export of guid $guid failed due to size $size", __FILE__, __LINE__, PEAR_LOG_ERROR);
$state->log("Server-ExportFailed");
continue;
}
if (($currentSize + $size +MIN_MSG_LEFT * 2) > $maxMsgSize) {
// put the item back in the queue
$adds[] = $guid;
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
return $currentCmdID;
}
}
Horde :: logMessage("SyncML: add guid $guid to client\n$c",
__FILE__, __LINE__, PEAR_LOG_DEBUG);
$cmd = new Horde_SyncML_Command_Sync_ContentSyncElement();
$cmd->setContent($c);
$cmd->setContentType($contentType['ContentType']);
if (isset ($contentType['ContentFormat'])) {
$cmd->setContentFormat($contentType['ContentFormat']);
}
$cmd->setGUID($guid);
$currentCmdID = $cmd->outputCommand($currentCmdID, $output, 'Add');
$state->log('Server-Add');
// moreData split; put the guid back in the list and return
if ($cmd->hasMoreData()) {
$state->curSyncItem = & $cmd;
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
return $currentCmdID;
}
$state->incNumberOfElements();
}
}
Horde::logMessage("SyncML: All items handled for sync $syncType",
__FILE__, __LINE__, PEAR_LOG_DEBUG);
$state->removeExpiredUID($syncType, time());
$state->clearSync($syncType);
return $currentCmdID;
}
function loadData() {
global $registry;
$state =& $_SESSION['SyncML.state'];
$syncType = $this->_targetLocURI;
$hordeType = $state->getHordeType($syncType);
$refts = $state->getServerAnchorLast($syncType);
$future = $state->getServerAnchorNext($syncType);
$addedItems =& $registry->call($hordeType . '/listBy', array (
'action' => 'add',
'timestamp' => $refts,
'type' => $syncType,
'filter' => $this->_filterExpression
));
$state->setAddedItems($syncType, $addedItems);
$changedItems =& $state->getChangedItems($syncType);
$deletedItems =& $registry->call($hordeType . '/listBy', array (
'action' => 'delete',
'timestamp' => $refts,
'type' => $syncType,
'filter' => $this->_filterExpression
));
foreach ($deletedItems as $guid)
{
if (strstr($guid, ':'))
{
$parentGUID = array_shift(explode(':', $guid));
if (!in_array($parentGUID, $changedItems))
{
$changedItems[] = $parentGUID;
}
}
}
$state->setDeletedItems($syncType, $deletedItems);
$this->_syncDataLoaded = true;
return count($changedItems) + count($deletedItems) + count($addedItems) + count($state->getConflictItems($syncType));
}
}

View File

@ -1,836 +0,0 @@
<?php
/**
* Error code for a missing driver configuration.
*/
define('HORDE_ERROR_DRIVER_CONFIG_MISSING', 1);
/**
* Error code for an incomplete driver configuration.
*/
define('HORDE_ERROR_DRIVER_CONFIG', 2);
/**
* The Util:: class provides generally useful methods of different kinds.
*
* $Horde: framework/Util/Util.php,v 1.388 2005/01/12 15:51:12 chuck Exp $
*
* Copyright 1999-2005 Chuck Hagenbuch <chuck@horde.org>
* Copyright 1999-2005 Jon Parise <jon@horde.org>
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Chuck Hagenbuch <chuck@horde.org>
* @author Jon Parise <jon@horde.org>
* @since Horde 3.0
* @package Horde_Util
*/
class Util {
/**
* Returns an object's clone.
*
* @param object &$obj The object to clone.
*
* @return object The cloned object.
*/
function &cloneObject(&$obj)
{
if (version_compare(zend_version(), '2', '>')) {
return clone($obj);
} else {
$newObj = $obj;
return $newObj;
}
}
/**
* Buffers the output from a function call, like readfile() or
* highlight_string(), that prints the output directly, so that instead it
* can be returned as a string and used.
*
* @access public
*
* @param string $function The function to run.
* @param mixed $arg1 First argument to $function().
* @param mixed $arg2 Second argument to $function().
* @param mixed $arg... ...
* @param mixed $argN Nth argument to $function().
*
* @return string The output of the function.
*/
function bufferOutput()
{
if (func_num_args() == 0) {
return false;
}
$eval = false;
$args = func_get_args();
$function = array_shift($args);
if (is_array($function)) {
if (!is_callable($function)) {
return false;
}
} elseif (($function == 'include') ||
($function == 'include_once') ||
($function == 'require') ||
($function == 'require_once')) {
$eval = true;
} elseif (!function_exists($function) &&
($function != 'eval')) {
return false;
}
ob_start();
if ($eval) {
eval($function . " '" . implode(',', $args) . "';");
} elseif ($function == 'eval') {
eval($args[0]);
} else {
call_user_func_array($function, $args);
}
$output = ob_get_contents();
ob_end_clean();
return $output;
}
/**
* Checks to see if a value has been set by the script and not by GET,
* POST, or cookie input. The value being checked MUST be in the global
* scope.
*
* @access public
*
* @param string $varname The variable name to check.
*
* @return mixed Null if the var is in user input, the variable value
* otherwise.
*/
function nonInputVar($varname)
{
if (isset($_GET[$varname]) ||
isset($_POST[$varname]) ||
isset($_COOKIE[$varname])) {
return null;
} else {
return isset($GLOBALS[$varname]) ? $GLOBALS[$varname] : null;
}
}
/**
* Adds a name=value pair to the end of an URL, taking care of whether
* there are existing parameters and whether to use ?, & or &amp; as the
* glue. All data will be urlencoded.
*
* @access public
*
* @param string $url The URL to modify
* @param mixed $parameter Either the name=value pair to add
* (DEPRECATED) -or-
* the name value -or-
* an array of name/value pairs.
* @param string $value If specified, the value part ($parameter is
* then assumed to just be the parameter name).
* @param boolean $encode If true, and we don't have argument separators
* yet, the argument separator gets encoded.
*
* @return string The modified URL.
*
* @since Horde 2.1
*/
function addParameter($url, $parameter, $value = null, $encode = true)
{
if (empty($parameter)) {
return $url;
}
if (!is_array($parameter)) {
/* This is deprecated should be removed in the future. */
if (is_null($value)) {
@list($parameter, $value) = explode('=', $parameter, 2);
}
$add = array($parameter => $value);
} else {
$add = $parameter;
}
$arg = $encode ? '&amp;' : '&';
if (($pos = strpos($url, '?')) === false) {
$glue = '?';
} else {
/* Check if the argument separator has been already
* htmlentities-ized in the URL. */
$query = substr($url, $pos + 1);
if (preg_match('/=.*?&amp;.*?=/', $query)) {
$arg = '&amp;';
$query = strtr($query, array_flip(get_html_translation_table(HTML_ENTITIES)));
} elseif (preg_match('/=.*?&.*?=/', $query)) {
$arg = '&';
}
$pairs = explode($arg, $query);
$params = array();
foreach ($pairs as $pair) {
$pair = explode('=', $pair, 2);
$params[$pair[0]] = count($pair) == 2 ? $pair[1] : '';
}
$glue = $arg;
}
$url_params = array();
foreach ($add as $parameter => $value) {
if (!isset($params[$parameter])) {
if (is_array($value)) {
foreach ($value as $val) {
$url_params[] = urlencode($parameter) . '[]=' . urlencode($val);
}
} else {
$url_params[] = urlencode($parameter) . '=' . urlencode($value);
}
}
}
if (count($url_params)) {
return $url . $glue . implode($arg, $url_params);
} else {
return $url;
}
}
/**
* Removes name=value pairs from a URL.
*
* @access public
*
* @param string $url The URL to modify.
* @param mixed $remove Either a single parameter to remove or an array
* of parameters to remove.
*
* @return string The modified URL.
*
* @since Horde 2.2
*/
function removeParameter($url, $remove)
{
if (!is_array($remove)) {
$remove = array($remove);
}
/* Return immediately if there are no parameters to remove. */
if (($pos = strpos($url, '?')) === false) {
return $url;
}
$entities = false;
list($url, $query) = explode('?', $url, 2);
/* Check if the argument separator has been already
* htmlentities-ized in the URL. */
if (preg_match('/=.*?&amp;.*?=/', $query)) {
$entities = true;
$query = strtr($query, array_flip(get_html_translation_table(HTML_ENTITIES)));
}
/* Get the list of parameters. */
$pairs = explode('&', $query);
$params = array();
foreach ($pairs as $pair) {
$pair = explode('=', $pair, 2);
$params[$pair[0]] = count($pair) == 2 ? $pair[1] : '';
}
/* Remove the parameters. */
foreach ($remove as $param) {
unset($params[$param]);
}
if (!count($params)) {
return $url;
}
/* Flatten arrays.
* FIXME: should handle more than one array level somehow. */
$add = array();
foreach ($params as $key => $val) {
if (is_array($val)) {
foreach ($val as $v) {
$add[] = $key . '[]=' . $v;
}
} else {
$add[] = $key . '=' . $val;
}
}
$query = implode('&', $add);
if ($entities) {
$query = htmlentities($query);
}
return $url . '?' . $query;
}
/**
* Returns a url with the 'nocache' parameter added, if the browser is
* buggy and caches old URLs.
*
* @access public
*
* @param string $url The URL to modify.
*
* @return string The requested URI.
*/
function nocacheUrl($url)
{
static $rand_num;
require_once 'Horde/Browser.php';
$browser = &Browser::singleton();
/* We may need to set a dummy parameter 'nocache' since some
* browsers do not always honor the 'no-cache' header. */
if ($browser->hasQuirk('cache_same_url')) {
if (!isset($rand_num)) {
$rand_num = base_convert(microtime(), 10, 36);
}
return Util::addParameter($url, 'nocache', $rand_num);
} else {
return $url;
}
}
/**
* Returns a hidden form input containing the session name and id.
*
* @access public
*
* @param boolean $append_session 0 = only if needed, 1 = always.
*
* @return string The hidden form input, if needed/requested.
*/
function formInput($append_session = 0)
{
if ($append_session == 1 ||
!isset($_COOKIE[session_name()])) {
return '<input type="hidden" name="' . htmlspecialchars(session_name()) . '" value="' . htmlspecialchars(session_id()) . "\" />\n";
} else {
return '';
}
}
/**
* Prints a hidden form input containing the session name and id.
*
* @access public
*
* @param boolean $append_session 0 = only if needed, 1 = always.
*/
function pformInput($append_session = 0)
{
echo Util::formInput($append_session);
}
/**
* If magic_quotes_gpc is in use, run stripslashes() on $var.
*
* @access public
*
* @param string &$var The string to un-quote, if necessary.
*
* @return string $var, minus any magic quotes.
*/
function dispelMagicQuotes(&$var)
{
static $magic_quotes;
if (!isset($magic_quotes)) {
$magic_quotes = get_magic_quotes_gpc();
}
if ($magic_quotes) {
if (!is_array($var)) {
$var = stripslashes($var);
} else {
array_walk($var, array('Util', 'dispelMagicQuotes'));
}
}
return $var;
}
/**
* Gets a form variable from GET or POST data, stripped of magic quotes if
* necessary. If the variable is somehow set in both the GET data and the
* POST data, the value from the POST data will be returned and the GET
* value will be ignored.
*
* @access public
*
* @param string $var The name of the form variable to look for.
* @param string $default The value to return if the variable is not
* there.
*
* @return string The cleaned form variable, or $default.
*/
function getFormData($var, $default = null)
{
return (($val = Util::getPost($var)) !== null)
? $val : Util::getGet($var, $default);
}
/**
* Gets a form variable from GET data, stripped of magic quotes if
* necessary. This function will NOT return a POST variable.
*
* @access public
*
* @param string $var The name of the form variable to look for.
* @param string $default The value to return if the variable is not
* there.
*
* @return string The cleaned form variable, or $default.
*
* @since Horde 2.2
*/
function getGet($var, $default = null)
{
return (isset($_GET[$var]))
? Util::dispelMagicQuotes($_GET[$var])
: $default;
}
/**
* Gets a form variable from POST data, stripped of magic quotes if
* necessary. This function will NOT return a GET variable.
*
* @access public
*
* @param string $var The name of the form variable to look for.
* @param string $default The value to return if the variable is not
* there.
*
* @return string The cleaned form variable, or $default.
*
* @since Horde 2.2
*/
function getPost($var, $default = null)
{
return (isset($_POST[$var]))
? Util::dispelMagicQuotes($_POST[$var])
: $default;
}
/**
* Determines the location of the system temporary directory.
*
* @access public
*
* @return string A directory name which can be used for temp files.
* Returns false if one could not be found.
*/
function getTempDir()
{
/* First, try PHP's upload_tmp_dir directive. */
$tmp = ini_get('upload_tmp_dir');
/* Otherwise, try to determine the TMPDIR environment
* variable. */
if (empty($tmp)) {
$tmp = getenv('TMPDIR');
}
/* If we still cannot determine a value, then cycle through a
* list of preset possibilities. */
$tmp_locations = array('/tmp', '/var/tmp', 'c:\WUTemp', 'c:\temp',
'c:\windows\temp', 'c:\winnt\temp');
while (empty($tmp) && count($tmp_locations)) {
$tmp_check = array_shift($tmp_locations);
if (@is_dir($tmp_check)) {
$tmp = $tmp_check;
}
}
/* If it is still empty, we have failed, so return false;
* otherwise return the directory determined. */
return empty($tmp) ? false : $tmp;
}
/**
* Creates a temporary filename for the lifetime of the script, and
* (optionally) register it to be deleted at request shutdown.
*
* @param string $prefix Prefix to make the temporary name more
* recognizable.
* @param boolean $delete Delete the file at the end of the request?
* @param string $dir Directory to create the temporary file in.
* @param boolean $secure If deleting file, should we securely delete the
* file?
*
* @return string Returns the full path-name to the temporary file.
* Returns false if a temp file could not be created.
*/
function getTempFile($prefix = '', $delete = true, $dir = '', $secure = false)
{
if (empty($dir) || !is_dir($dir)) {
$tmp_dir = Util::getTempDir();
} else {
$tmp_dir = $dir;
}
if (empty($tmp_dir)) {
return false;
}
$tmp_file = tempnam($tmp_dir, $prefix);
/* If the file was created, then register it for deletion and return */
if (empty($tmp_file)) {
return false;
} else {
if ($delete) {
Util::deleteAtShutdown($tmp_file, true, $secure);
}
return $tmp_file;
}
}
/**
* Creates a temporary directory in the system's temporary directory.
*
* @access public
*
* @param boolean $delete Delete the temporary directory at the end of
* the request?
* @param string $temp_dir Use this temporary directory as the directory
* where the temporary directory will be created.
*
* @return string The pathname to the new temporary directory.
* Returns false if directory not created.
*/
function createTempDir($delete = true, $temp_dir = null)
{
if (is_null($temp_dir)) {
$temp_dir = Util::getTempDir();
}
if (empty($temp_dir)) {
return false;
}
/* Get the first 8 characters of a random string to use as a temporary
directory name. */
do {
$temp_dir .= '/' . substr(base_convert(mt_rand() . microtime(), 10, 36), 0, 8);
} while (file_exists($temp_dir));
$old_umask = umask(0000);
if (!mkdir($temp_dir, 0700)) {
$temp_dir = false;
} elseif ($delete) {
Util::deleteAtShutdown($temp_dir);
}
umask($old_umask);
return $temp_dir;
}
/**
* Removes given elements at request shutdown.
*
* If called with a filename will delete that file at request shutdown; if
* called with a directory will remove that directory and all files in that
* directory at request shutdown.
*
* If called with no arguments, return all elements to be deleted (this
* should only be done by Util::_deleteAtShutdown).
*
* The first time it is called, it initializes the array and registers
* Util::_deleteAtShutdown() as a shutdown function - no need to do so
* manually.
*
* The second parameter allows the unregistering of previously registered
* elements.
*
* @access public
*
* @param string $filename The filename to be deleted at the end of the
* request.
* @param boolean $register If true, then register the element for
* deletion, otherwise, unregister it.
* @param boolean $secure If deleting file, should we securely delete
* the file?
*/
function deleteAtShutdown($filename = false, $register = true,
$secure = false)
{
static $dirs, $files, $securedel;
/* Initialization of variables and shutdown functions. */
if (is_null($dirs)){
$dirs = array();
$files = array();
$securedel = array();
register_shutdown_function(array('Util', '_deleteAtShutdown'));
}
if ($filename) {
if ($register) {
if (@is_dir($filename)) {
$dirs[$filename] = true;
} else {
$files[$filename] = true;
}
if ($secure) {
$securedel[$filename] = true;
}
} else {
unset($dirs[$filename]);
unset($files[$filename]);
unset($securedel[$filename]);
}
} else {
return array($dirs, $files, $securedel);
}
}
/**
* Deletes registered files at request shutdown.
*
* This function should never be called manually; it is registered as a
* shutdown function by Util::deleteAtShutdown() and called automatically
* at the end of the request. It will retrieve the list of folders and
* files to delete from Util::deleteAtShutdown()'s static array, and then
* iterate through, deleting folders recursively.
*
* Contains code from gpg_functions.php.
* Copyright (c) 2002-2003 Braverock Ventures
*
* @access private
*/
function _deleteAtShutdown()
{
$registered = Util::deleteAtShutdown();
$dirs = $registered[0];
$files = $registered[1];
$secure = $registered[2];
foreach ($files as $file => $val) {
/* Delete files */
if ($val && @file_exists($file)) {
/* Should we securely delete the file by overwriting the
data with a random string? */
if (isset($secure[$file])) {
$random_str = '';
for ($i = 0; $i < filesize($file); $i++) {
$random_str .= chr(mt_rand(0, 255));
}
$fp = fopen($file, 'r+');
fwrite($fp, $random_str);
fclose($fp);
}
@unlink($file);
}
}
foreach ($dirs as $dir => $val) {
/* Delete directories */
if ($val && @file_exists($dir)) {
/* Make sure directory is empty. */
$dir_class = dir($dir);
while (false !== ($entry = $dir_class->read())) {
if ($entry != '.' && $entry != '..') {
@unlink($dir . '/' . $entry);
}
}
$dir_class->close();
@rmdir($dir);
}
}
}
/**
* Outputs javascript code to close the current window.
*
* @access public
*
* @param string $code Any addtional javascript code to run before
* closing the window.
*/
function closeWindowJS($code = '')
{
echo '<script language="JavaScript" type="text/javascript">' . $code .
'window.close();</script>';
}
/**
* Caches the result of extension_loaded() calls.
*
* @access private
*
* @param string $ext The extension name.
*
* @return boolean Is the extension loaded?
*/
function extensionExists($ext)
{
static $cache = array();
if (!isset($cache[$ext])) {
$cache[$ext] = extension_loaded($ext);
}
return $cache[$ext];
}
/**
* Tries to load a PHP extension, behaving correctly for all operating
* systems.
*
* @param string $ext The extension to load.
*
* @return boolean True if the extension is now loaded, false if not.
* True can mean that the extension was already loaded,
* OR was loaded dynamically.
*/
function loadExtension($ext)
{
/* If $ext is already loaded, our work is done. */
if (Util::extensionExists($ext)) {
return true;
}
/* See if we can call dl() at all, by the current ini settings. */
if ((ini_get('enable_dl') != 1) || (ini_get('safe_mode') == 1)) {
return false;
}
if (substr(PHP_OS, 0, 3) == 'WIN') {
$suffix = 'dll';
} else {
switch (PHP_OS) {
case 'HP-UX':
$suffix = 'sl';
break;
case 'AIX':
$suffix = 'a';
break;
case 'OSX':
$suffix = 'bundle';
break;
default:
$suffix = 'so';
}
}
return @dl($ext . '.' . $suffix) || @dl('php_' . $ext . '.' . $suffix);
}
/**
* Checks if all necessary parameters for a driver's configuration are set
* and returns a PEAR_Error if something is missing.
*
* @param array $params The configuration array with all parameters.
* @param array $fields An array with mandatory parameter names for this
* driver.
* @param string $name The clear text name of the driver. If not
* specified, the application name will be used.
* @param array $info A hash containing detailed information about the
* driver. Will be passed as the userInfo to the
* PEAR_Error.
*/
function assertDriverConfig($params, $fields, $name, $info = array())
{
$info = array_merge($info,
array('params' => $params,
'fields' => $fields,
'name' => $name));
if (!is_array($params) || !count($params)) {
require_once 'PEAR.php';
return PEAR::throwError(sprintf(_("No configuration information specified for %s."), $name),
HORDE_ERROR_DRIVER_CONFIG_MISSING,
$info);
}
foreach ($fields as $field) {
if (!isset($params[$field])) {
require_once 'PEAR.php';
return PEAR::throwError(sprintf(_("Required '%s' not specified in configuration."), $field, $name),
HORDE_ERROR_DRIVER_CONFIG,
$info);
}
}
}
/**
* Returns a format string to be used by strftime().
*
* @param string $format A format string as used by date().
*
* @return string A format string as similar as possible to $format.
*/
function date2strftime($format)
{
$dateSymbols = array('a', 'A', 'd', 'D', 'F', 'g', 'G', 'h', 'H', 'i', 'j', 'l', 'm', 'M', 'n', 'r', 's', 'T', 'w', 'W', 'y', 'Y', 'z', 'm/d/Y', 'M', "\n", 'g:i a', 'G:i', "\t", 'H:i:s', '%');
$strftimeSymbols = array('%p', '%p', '%d', '%a', '%B', '%I', '%H', '%I', '%H', '%M', '%e', '%A', '%m', '%b', '%m', '%a, %e %b %Y %T %Z', '%S', '%Z', '%w', '%V', '%y', '%Y', '%j', '%D', '%h', '%n', '%r', '%R', '%t', '%T', '%%');
$result = '';
for ($pos = 0; $pos < strlen($format);) {
for ($symbol = 0; $symbol < count($dateSymbols); $symbol++) {
if (strpos($format, $dateSymbols[$symbol], $pos) === $pos) {
$result .= $strftimeSymbols[$symbol];
$pos += strlen($dateSymbols[$symbol]);
continue 2;
}
}
$result .= substr($format, $pos, 1);
$pos++;
}
return $result;
}
/**
* Returns a format string to be used by date().
*
* @param string $format A format string as used by strftime().
*
* @return string A format string as similar as possible to $format.
*/
function strftime2date($format)
{
$dateSymbols = array('a', 'A', 'd', 'D', 'F', 'g', 'G', 'h', 'H', 'i', 'j', 'l', 'm', 'M', 'n', 'r', 's', 'T', 'w', 'W', 'y', 'Y', 'z', 'm/d/Y', 'M', "\n", 'g:i a', 'G:i', "\t", 'H:i:s', '%');
$strftimeSymbols = array('%p', '%p', '%d', '%a', '%B', '%I', '%H', '%I', '%H', '%M', '%e', '%A', '%m', '%b', '%m', '%a, %e %b %Y %T %Z', '%S', '%Z', '%w', '%V', '%y', '%Y', '%j', '%D', '%h', '%n', '%r', '%R', '%t', '%T', '%%');
return str_replace($strftimeSymbols, $dateSymbols, $format);
}
}
if (!function_exists('_')) {
function _($string)
{
return $string;
}
function bindtextdomain()
{
}
function textdomain()
{
}
function dgettext($domain, $message)
{
return $message;
}
function ngettext($singular, $plural, $number)
{
return $number > 1 ? $plural : $singular;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,28 +0,0 @@
<?php
/**
* Class representing vAlarms.
*
* $Horde: framework/iCalendar/iCalendar/valarm.php,v 1.8.10.8 2008/07/03 08:42:58 jan Exp $
*
* Copyright 2003-2008 The Horde Project (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Mike Cochrane <mike@graftonhall.co.nz>
* @since Horde 3.0
* @package Horde_iCalendar
*/
class Horde_iCalendar_valarm extends Horde_iCalendar {
function getType()
{
return 'vAlarm';
}
function exportvCalendar()
{
return parent::_exportvData('VALARM');
}
}

View File

@ -1,138 +0,0 @@
<?php
require_once EGW_API_INC.'/horde/Horde/iCalendar.php';
// The following were shamelessly yoinked from Contact_Vcard_Build
// Part numbers for N components.
define('VCARD_N_FAMILY', 0);
define('VCARD_N_GIVEN', 1);
define('VCARD_N_ADDL', 2);
define('VCARD_N_PREFIX', 3);
define('VCARD_N_SUFFIX', 4);
// Part numbers for ADR components.
define('VCARD_ADR_POB', 0);
define('VCARD_ADR_EXTEND', 1);
define('VCARD_ADR_STREET', 2);
define('VCARD_ADR_LOCALITY', 3);
define('VCARD_ADR_REGION', 4);
define('VCARD_ADR_POSTCODE', 5);
define('VCARD_ADR_COUNTRY', 6);
// Part numbers for GEO components.
define('VCARD_GEO_LAT', 0);
define('VCARD_GEO_LON', 1);
/**
* Class representing vCard entries.
*
* $Horde: framework/iCalendar/iCalendar/vcard.php,v 1.3.10.16 2008/09/22 04:16:30 chuck Exp $
*
* Copyright 2003-2008 The Horde Project (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Karsten Fourmont <karsten@horde.org>
* @package Horde_iCalendar
*/
class Horde_iCalendar_vcard extends Horde_iCalendar {
function Horde_iCalendar_vcard($version = '2.1')
{
return parent::Horde_iCalendar($version);
}
function getType()
{
return 'vcard';
}
/**
* Unlike vevent and vtodo, a vcard is normally not enclosed in an
* iCalendar container. (BEGIN..END)
*/
function exportvCalendar()
{
$requiredAttributes['VERSION'] = $this->_version;
$requiredAttributes['N'] = ';;;;;;';
if ($this->_version == '3.0') {
$requiredAttributes['FN'] = '';
}
foreach ($requiredAttributes as $name => $default_value) {
if (is_a($this->getAttribute($name), 'PEAR_Error')) {
$this->setAttribute($name, $default_value);
}
}
return $this->_exportvData('VCARD');
}
/**
* Returns the contents of the "N" tag as a printable Name:
* i.e. converts:
*
* N:Duck;Dagobert;T;Professor;Sen.
* to
* "Professor Dagobert T Duck Sen"
*
* @return string Full name of vcard "N" tag or null if no N tag.
*/
function printableName()
{
$name_parts = $this->getAttributeValues('N');
if (is_a($name_parts, 'PEAR_Error')) {
return null;
}
$name_arr = array();
if (!empty($name_parts[VCARD_N_PREFIX])) {
$name_arr[] = $name_parts[VCARD_N_PREFIX];
}
if (!empty($name_parts[VCARD_N_GIVEN])) {
$name_arr[] = $name_parts[VCARD_N_GIVEN];
}
if (!empty($name_parts[VCARD_N_ADDL])) {
$name_arr[] = $name_parts[VCARD_N_ADDL];
}
if (!empty($name_parts[VCARD_N_FAMILY])) {
$name_arr[] = $name_parts[VCARD_N_FAMILY];
}
if (!empty($name_parts[VCARD_N_SUFFIX])) {
$name_arr[] = $name_parts[VCARD_N_SUFFIX];
}
return implode(' ', $name_arr);
}
/**
* Static function to make a given email address rfc822 compliant.
*
* @param string $address An email address.
*
* @return string The RFC822-formatted email address.
*/
function getBareEmail($address)
{
// Empty values are still empty.
if (!$address) {
return $address;
}
require_once 'Mail/RFC822.php';
require_once 'Horde/MIME.php';
static $rfc822;
if (is_null($rfc822)) {
$rfc822 = new Mail_RFC822();
}
if (!$rfc822->validateMailbox($address)) {
return $address;
}
return MIME::rfc822WriteAddress($address->mailbox, $address->host);
}
}

View File

@ -1,232 +0,0 @@
<?php
/**
* Class representing vEvents.
*
* $Horde: framework/iCalendar/iCalendar/vevent.php,v 1.31.10.15 2008/07/03 08:42:58 jan Exp $
*
* Copyright 2003-2008 The Horde Project (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Mike Cochrane <mike@graftonhall.co.nz>
* @since Horde 3.0
* @package Horde_iCalendar
*/
class Horde_iCalendar_vevent extends Horde_iCalendar {
function getType()
{
return 'vEvent';
}
function exportvCalendar()
{
// Default values.
$requiredAttributes = array();
$requiredAttributes['DTSTAMP'] = time();
/* This is handled by the upper layers.
$requiredAttributes['UID'] = $this->_exportDateTime(time())
. substr(str_pad(base_convert(microtime(), 10, 36), 16, uniqid(mt_rand()), STR_PAD_LEFT), -16)
. '@' . (isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'localhost');
*/
$method = !empty($this->_container) ?
$this->_container->getAttribute('METHOD') : 'PUBLISH';
switch ($method) {
case 'PUBLISH':
$requiredAttributes['DTSTART'] = time();
$requiredAttributes['SUMMARY'] = '';
break;
case 'REQUEST':
$requiredAttributes['ATTENDEE'] = '';
$requiredAttributes['DTSTART'] = time();
$requiredAttributes['SUMMARY'] = '';
break;
case 'REPLY':
$requiredAttributes['ATTENDEE'] = '';
break;
case 'ADD':
$requiredAttributes['DTSTART'] = time();
$requiredAttributes['SEQUENCE'] = 1;
$requiredAttributes['SUMMARY'] = '';
break;
case 'CANCEL':
$requiredAttributes['ATTENDEE'] = '';
$requiredAttributes['SEQUENCE'] = 1;
break;
case 'REFRESH':
$requiredAttributes['ATTENDEE'] = '';
break;
}
foreach ($requiredAttributes as $name => $default_value) {
if (is_a($this->getAttribute($name), 'PEAR_Error')) {
$this->setAttribute($name, $default_value);
}
}
return parent::_exportvData('VEVENT');
}
/**
* Update the status of an attendee of an event.
*
* @param $email The email address of the attendee.
* @param $status The participant status to set.
* @param $fullname The full name of the participant to set.
*/
function updateAttendee($email, $status, $fullname = '')
{
foreach ($this->_attributes as $key => $attribute) {
if ($attribute['name'] == 'ATTENDEE' &&
$attribute['value'] == 'mailto:' . $email) {
$this->_attributes[$key]['params']['PARTSTAT'] = $status;
if (!empty($fullname)) {
$this->_attributes[$key]['params']['CN'] = $fullname;
}
unset($this->_attributes[$key]['params']['RSVP']);
return;
}
}
$params = array('PARTSTAT' => $status);
if (!empty($fullname)) {
$params['CN'] = $fullname;
}
$this->setAttribute('ATTENDEE', 'mailto:' . $email, $params);
}
/**
* Return the organizer display name or email.
*
* @return string The organizer name to display for this event.
*/
function organizerName()
{
$organizer = $this->getAttribute('ORGANIZER', true);
if (is_a($organizer, 'PEAR_Error')) {
return _("An unknown person");
}
if (isset($organizer[0]['CN'])) {
return $organizer[0]['CN'];
}
$organizer = parse_url($this->getAttribute('ORGANIZER'));
return $organizer['path'];
}
/**
* Update this event with details from another event.
*
* @param Horde_iCalendar_vEvent $vevent The vEvent with latest details.
*/
function updateFromvEvent($vevent)
{
$newAttributes = $vevent->getAllAttributes();
foreach ($newAttributes as $newAttribute) {
$currentValue = $this->getAttribute($newAttribute['name']);
if (is_a($currentValue, 'PEAR_error')) {
// Already exists so just add it.
$this->setAttribute($newAttribute['name'],
$newAttribute['value'],
$newAttribute['params']);
} else {
// Already exists so locate and modify.
$found = false;
// Try matching the attribte name and value incase
// only the params changed (eg attendee updating
// status).
foreach ($this->_attributes as $id => $attr) {
if ($attr['name'] == $newAttribute['name'] &&
$attr['value'] == $newAttribute['value']) {
// merge the params
foreach ($newAttribute['params'] as $param_id => $param_name) {
$this->_attributes[$id]['params'][$param_id] = $param_name;
}
$found = true;
break;
}
}
if (!$found) {
// Else match the first attribute with the same
// name (eg changing start time).
foreach ($this->_attributes as $id => $attr) {
if ($attr['name'] == $newAttribute['name']) {
$this->_attributes[$id]['value'] = $newAttribute['value'];
// Merge the params.
foreach ($newAttribute['params'] as $param_id => $param_name) {
$this->_attributes[$id]['params'][$param_id] = $param_name;
}
break;
}
}
}
}
}
}
/**
* Update just the attendess of event with details from another
* event.
*
* @param Horde_iCalendar_vEvent $vevent The vEvent with latest details
*/
function updateAttendeesFromvEvent($vevent)
{
$newAttributes = $vevent->getAllAttributes();
foreach ($newAttributes as $newAttribute) {
if ($newAttribute['name'] != 'ATTENDEE') {
continue;
}
$currentValue = $this->getAttribute($newAttribute['name']);
if (is_a($currentValue, 'PEAR_error')) {
// Already exists so just add it.
$this->setAttribute($newAttribute['name'],
$newAttribute['value'],
$newAttribute['params']);
} else {
// Already exists so locate and modify.
$found = false;
// Try matching the attribte name and value incase
// only the params changed (eg attendee updating
// status).
foreach ($this->_attributes as $id => $attr) {
if ($attr['name'] == $newAttribute['name'] &&
$attr['value'] == $newAttribute['value']) {
// Merge the params.
foreach ($newAttribute['params'] as $param_id => $param_name) {
$this->_attributes[$id]['params'][$param_id] = $param_name;
}
$found = true;
break;
}
}
if (!$found) {
// Else match the first attribute with the same
// name (eg changing start time).
foreach ($this->_attributes as $id => $attr) {
if ($attr['name'] == $newAttribute['name']) {
$this->_attributes[$id]['value'] = $newAttribute['value'];
// Merge the params.
foreach ($newAttribute['params'] as $param_id => $param_name) {
$this->_attributes[$id]['params'][$param_id] = $param_name;
}
break;
}
}
}
}
}
}
}

View File

@ -1,459 +0,0 @@
<?php
/**
* Class representing vFreebusy components.
*
* $Horde: framework/iCalendar/iCalendar/vfreebusy.php,v 1.16.10.17 2008/09/17 08:46:57 jan Exp $
*
* Copyright 2003-2008 The Horde Project (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @todo Don't use timestamps
*
* @author Mike Cochrane <mike@graftonhall.co.nz>
* @since Horde 3.0
* @package Horde_iCalendar
*/
class Horde_iCalendar_vfreebusy extends Horde_iCalendar {
var $_busyPeriods = array();
var $_extraParams = array();
/**
* Returns the type of this calendar component.
*
* @return string The type of this component.
*/
function getType()
{
return 'vFreebusy';
}
/**
* Parses a string containing vFreebusy data.
*
* @param string $data The data to parse.
*/
function parsevCalendar($data, $type = null, $charset = null)
{
parent::parsevCalendar($data, 'VFREEBUSY', $charset);
// Do something with all the busy periods.
foreach ($this->_attributes as $key => $attribute) {
if ($attribute['name'] != 'FREEBUSY') {
continue;
}
foreach ($attribute['values'] as $value) {
$params = isset($attribute['params'])
? $attribute['params']
: array();
if (isset($value['duration'])) {
$this->addBusyPeriod('BUSY', $value['start'], null,
$value['duration'], $params);
} else {
$this->addBusyPeriod('BUSY', $value['start'],
$value['end'], null, $params);
}
}
unset($this->_attributes[$key]);
}
}
/**
* Returns the component exported as string.
*
* @return string The exported vFreeBusy information according to the
* iCalender format specification.
*/
function exportvCalendar()
{
foreach ($this->_busyPeriods as $start => $end) {
$periods = array(array('start' => $start, 'end' => $end));
$this->setAttribute('FREEBUSY', $periods,
isset($this->_extraParams[$start])
? $this->_extraParams[$start] : array());
}
$res = parent::_exportvData('VFREEBUSY');
foreach ($this->_attributes as $key => $attribute) {
if ($attribute['name'] == 'FREEBUSY') {
unset($this->_attributes[$key]);
}
}
return $res;
}
/**
* Returns a display name for this object.
*
* @return string A clear text name for displaying this object.
*/
function getName()
{
$name = '';
$method = !empty($this->_container) ?
$this->_container->getAttribute('METHOD') : 'PUBLISH';
if (is_a($method, 'PEAR_Error') || $method == 'PUBLISH') {
$attr = 'ORGANIZER';
} elseif ($method == 'REPLY') {
$attr = 'ATTENDEE';
}
$name = $this->getAttribute($attr, true);
if (!is_a($name, 'PEAR_Error') && isset($name[0]['CN'])) {
return $name[0]['CN'];
}
$name = $this->getAttribute($attr);
if (is_a($name, 'PEAR_Error')) {
return '';
} else {
$name = parse_url($name);
return $name['path'];
}
}
/**
* Returns the email address for this object.
*
* @return string The email address of this object's owner.
*/
function getEmail()
{
$name = '';
$method = !empty($this->_container)
? $this->_container->getAttribute('METHOD') : 'PUBLISH';
if (is_a($method, 'PEAR_Error') || $method == 'PUBLISH') {
$attr = 'ORGANIZER';
} elseif ($method == 'REPLY') {
$attr = 'ATTENDEE';
}
$name = $this->getAttribute($attr);
if (is_a($name, 'PEAR_Error')) {
return '';
} else {
$name = parse_url($name);
return $name['path'];
}
}
/**
* Returns the busy periods.
*
* @return array All busy periods.
*/
function getBusyPeriods()
{
return $this->_busyPeriods;
}
/**
* Returns any additional freebusy parameters.
*
* @return array Additional parameters of the freebusy periods.
*/
function getExtraParams()
{
return $this->_extraParams;
}
/**
* Returns all the free periods of time in a given period.
*
* @param integer $startStamp The start timestamp.
* @param integer $endStamp The end timestamp.
*
* @return array A hash with free time periods, the start times as the
* keys and the end times as the values.
*/
function getFreePeriods($startStamp, $endStamp)
{
$this->simplify();
$periods = array();
// Check that we have data for some part of this period.
if ($this->getEnd() < $startStamp || $this->getStart() > $endStamp) {
return $periods;
}
// Locate the first time in the requested period we have data for.
$nextstart = max($startStamp, $this->getStart());
// Check each busy period and add free periods in between.
foreach ($this->_busyPeriods as $start => $end) {
if ($start <= $endStamp && $end >= $nextstart) {
if ($nextstart <= $start) {
$periods[$nextstart] = min($start, $endStamp);
}
$nextstart = min($end, $endStamp);
}
}
// If we didn't read the end of the requested period but still have
// data then mark as free to the end of the period or available data.
if ($nextstart < $endStamp && $nextstart < $this->getEnd()) {
$periods[$nextstart] = min($this->getEnd(), $endStamp);
}
return $periods;
}
/**
* Adds a busy period to the info.
*
* This function may throw away data in case you add a period with a start
* date that already exists. The longer of the two periods will be chosen
* (and all information associated with the shorter one will be removed).
*
* @param string $type The type of the period. Either 'FREE' or
* 'BUSY'; only 'BUSY' supported at the moment.
* @param integer $start The start timestamp of the period.
* @param integer $end The end timestamp of the period.
* @param integer $duration The duration of the period. If specified, the
* $end parameter will be ignored.
* @param array $extra Additional parameters for this busy period.
*/
function addBusyPeriod($type, $start, $end = null, $duration = null,
$extra = array())
{
if ($type == 'FREE') {
// Make sure this period is not marked as busy.
return false;
}
// Calculate the end time if duration was specified.
$tempEnd = is_null($duration) ? $end : $start + $duration;
// Make sure the period length is always positive.
$end = max($start, $tempEnd);
$start = min($start, $tempEnd);
if (isset($this->_busyPeriods[$start])) {
// Already a period starting at this time. Change the current
// period only if the new one is longer. This might be a problem
// if the callee assumes that there is no simplification going
// on. But since the periods are stored using the start time of
// the busy periods we have to throw away data here.
if ($end > $this->_busyPeriods[$start]) {
$this->_busyPeriods[$start] = $end;
$this->_extraParams[$start] = $extra;
}
} else {
// Add a new busy period.
$this->_busyPeriods[$start] = $end;
$this->_extraParams[$start] = $extra;
}
return true;
}
/**
* Returns the timestamp of the start of the time period this free busy
* information covers.
*
* @return integer A timestamp.
*/
function getStart()
{
if (!is_a($this->getAttribute('DTSTART'), 'PEAR_Error')) {
return $this->getAttribute('DTSTART');
} elseif (count($this->_busyPeriods)) {
return min(array_keys($this->_busyPeriods));
} else {
return false;
}
}
/**
* Returns the timestamp of the end of the time period this free busy
* information covers.
*
* @return integer A timestamp.
*/
function getEnd()
{
if (!is_a($this->getAttribute('DTEND'), 'PEAR_Error')) {
return $this->getAttribute('DTEND');
} elseif (count($this->_busyPeriods)) {
return max(array_values($this->_busyPeriods));
} else {
return false;
}
}
/**
* Merges the busy periods of another Horde_iCalendar_vfreebusy object
* into this one.
*
* This might lead to simplification no matter what you specify for the
* "simplify" flag since periods with the same start date will lead to the
* shorter period being removed (see addBusyPeriod).
*
* @param Horde_iCalendar_vfreebusy $freebusy A freebusy object.
* @param boolean $simplify If true, simplify() will
* called after the merge.
*/
function merge($freebusy, $simplify = true)
{
if (!is_a($freebusy, 'Horde_iCalendar_vfreebusy')) {
return false;
}
$extra = $freebusy->getExtraParams();
foreach ($freebusy->getBusyPeriods() as $start => $end) {
// This might simplify the busy periods without taking the
// "simplify" flag into account.
$this->addBusyPeriod('BUSY', $start, $end, null,
isset($extra[$start])
? $extra[$start] : array());
}
$thisattr = $this->getAttribute('DTSTART');
$thatattr = $freebusy->getAttribute('DTSTART');
if (is_a($thisattr, 'PEAR_Error') && !is_a($thatattr, 'PEAR_Error')) {
$this->setAttribute('DTSTART', $thatattr, array(), false);
} elseif (!is_a($thatattr, 'PEAR_Error')) {
if ($thatattr < $thisattr) {
$this->setAttribute('DTSTART', $thatattr, array(), false);
}
}
$thisattr = $this->getAttribute('DTEND');
$thatattr = $freebusy->getAttribute('DTEND');
if (is_a($thisattr, 'PEAR_Error') && !is_a($thatattr, 'PEAR_Error')) {
$this->setAttribute('DTEND', $thatattr, array(), false);
} elseif (!is_a($thatattr, 'PEAR_Error')) {
if ($thatattr > $thisattr) {
$this->setAttribute('DTEND', $thatattr, array(), false);
}
}
if ($simplify) {
$this->simplify();
}
return true;
}
/**
* Removes all overlaps and simplifies the busy periods array as much as
* possible.
*/
function simplify()
{
$clean = false;
$busy = array($this->_busyPeriods, $this->_extraParams);
while (!$clean) {
$result = $this->_simplify($busy[0], $busy[1]);
$clean = $result === $busy;
$busy = $result;
}
ksort($result[1], SORT_NUMERIC);
$this->_extraParams = $result[1];
ksort($result[0], SORT_NUMERIC);
$this->_busyPeriods = $result[0];
}
function _simplify($busyPeriods, $extraParams = array())
{
$checked = array();
$checkedExtra = array();
$checkedEmpty = true;
foreach ($busyPeriods as $start => $end) {
if ($checkedEmpty) {
$checked[$start] = $end;
$checkedExtra[$start] = isset($extraParams[$start])
? $extraParams[$start] : array();
$checkedEmpty = false;
} else {
$added = false;
foreach ($checked as $testStart => $testEnd) {
// Replace old period if the new period lies around the
// old period.
if ($start <= $testStart && $end >= $testEnd) {
// Remove old period entry.
unset($checked[$testStart]);
unset($checkedExtra[$testStart]);
// Add replacing entry.
$checked[$start] = $end;
$checkedExtra[$start] = isset($extraParams[$start])
? $extraParams[$start] : array();
$added = true;
} elseif ($start >= $testStart && $end <= $testEnd) {
// The new period lies fully within the old
// period. Just forget about it.
$added = true;
} elseif (($end <= $testEnd && $end >= $testStart) ||
($start >= $testStart && $start <= $testEnd)) {
// Now we are in trouble: Overlapping time periods. If
// we allow for additional parameters we cannot simply
// choose one of the two parameter sets. It's better
// to leave two separated time periods.
$extra = isset($extraParams[$start])
? $extraParams[$start] : array();
$testExtra = isset($checkedExtra[$testStart])
? $checkedExtra[$testStart] : array();
// Remove old period entry.
unset($checked[$testStart]);
unset($checkedExtra[$testStart]);
// We have two periods overlapping. Are their
// additional parameters the same or different?
$newStart = min($start, $testStart);
$newEnd = max($end, $testEnd);
if ($extra === $testExtra) {
// Both periods have the same information. So we
// can just merge.
$checked[$newStart] = $newEnd;
$checkedExtra[$newStart] = $extra;
} else {
// Extra parameters are different. Create one
// period at the beginning with the params of the
// first period and create a trailing period with
// the params of the second period. The break
// point will be the end of the first period.
$break = min($end, $testEnd);
$checked[$newStart] = $break;
$checkedExtra[$newStart] =
isset($extraParams[$newStart])
? $extraParams[$newStart] : array();
$checked[$break] = $newEnd;
$highStart = max($start, $testStart);
$checkedExtra[$break] =
isset($extraParams[$highStart])
? $extraParams[$highStart] : array();
// Ensure we also have the extra data in the
// extraParams.
$extraParams[$break] =
isset($extraParams[$highStart])
? $extraParams[$highStart] : array();
}
$added = true;
}
if ($added) {
break;
}
}
if (!$added) {
$checked[$start] = $end;
$checkedExtra[$start] = isset($extraParams[$start])
? $extraParams[$start] : array();
}
}
}
return array($checked, $checkedExtra);
}
}

View File

@ -1,28 +0,0 @@
<?php
/**
* Class representing vJournals.
*
* $Horde: framework/iCalendar/iCalendar/vjournal.php,v 1.8.10.8 2008/07/03 08:42:58 jan Exp $
*
* Copyright 2003-2008 The Horde Project (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Mike Cochrane <mike@graftonhall.co.nz>
* @since Horde 3.0
* @package Horde_iCalendar
*/
class Horde_iCalendar_vjournal extends Horde_iCalendar {
function getType()
{
return 'vJournal';
}
function exportvCalendar()
{
return parent::_exportvData('VJOURNAL');
}
}

View File

@ -1,49 +0,0 @@
<?php
require_once EGW_API_INC.'/horde/Horde/iCalendar.php';
/**
* Class representing vNotes.
*
* $Horde: framework/iCalendar/iCalendar/vnote.php,v 1.3.10.9 2008/07/03 08:42:58 jan Exp $
*
* Copyright 2003-2008 The Horde Project (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Mike Cochrane <mike@graftonhall.co.nz>
* @author Karsten Fourmont <fourmont@gmx.de>
* @package Horde_iCalendar
*/
class Horde_iCalendar_vnote extends Horde_iCalendar {
function Horde_iCalendar_vnote($version = '1.1')
{
return parent::Horde_iCalendar($version);
}
function getType()
{
return 'vNote';
}
/**
* Unlike vevent and vtodo, a vnote is normally not enclosed in an
* iCalendar container. (BEGIN..END)
*/
function exportvCalendar()
{
$requiredAttributes['BODY'] = '';
$requiredAttributes['VERSION'] = '1.1';
foreach ($requiredAttributes as $name => $default_value) {
if (is_a($this->getattribute($name), 'PEAR_Error')) {
$this->setAttribute($name, $default_value);
}
}
return $this->_exportvData('VNOTE');
}
}

View File

@ -1,254 +0,0 @@
<?php
/**
* Class representing vTimezones.
*
* $Horde: framework/iCalendar/iCalendar/vtimezone.php,v 1.8.10.9 2008/07/03 08:42:58 jan Exp $
*
* Copyright 2003-2008 The Horde Project (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Mike Cochrane <mike@graftonhall.co.nz>
* @since Horde 3.0
* @package Horde_iCalendar
* @changes 2010/02/26 Joerg Lehrke <jlehrke@noc.de>: Add RDATE support (for KDE 4.x)
*/
class Horde_iCalendar_vtimezone extends Horde_iCalendar {
function getType()
{
return 'vTimeZone';
}
function exportvCalendar()
{
return parent::_exportvData('VTIMEZONE');
}
/**
* Parse child components of the vTimezone component. Returns an
* array with the exact time of the time change as well as the
* 'from' and 'to' offsets around the change. Time is arbitrarily
* based on UTC for comparison.
*/
function parseChild(&$child, $year)
{
// Make sure 'time' key is first for sort().
$result['time'] = 0;
$rrule_interval = 0; // 0 undefined, 1 yearly, 12 monthly
$t = $child->getAttribute('TZOFFSETFROM');
if (is_a($t, 'PEAR_Error')) {
return false;
}
$result['from'] = ($t['hour'] * 60 * 60 + $t['minute'] * 60) * ($t['ahead'] ? 1 : -1);
$t = $child->getAttribute('TZOFFSETTO');
if (is_a($t, 'PEAR_Error')) {
return false;
}
$result['to'] = ($t['hour'] * 60 * 60 + $t['minute'] * 60) * ($t['ahead'] ? 1 : -1);
$switch_time = $child->getAttribute('DTSTART');
if (is_a($switch_time, 'PEAR_Error')) {
return false;
}
$rdates = $child->getAttribute('RDATE');
if (!is_a($rdates, 'PEAR_Error')) {
foreach ($rdates as $rdate) {
$switch_time = $switch_time['value'];
$switch_year = date("Y", $switch_time);
if ($switch_year == $year) {
$t = getdate($switch_time);
$result['time'] = @gmmktime($t['hours'], $t['minutes'], $t['seconds'],
$t['mon'], $t['mday'], $t['year']);
return $result;
}
}
}
$rrules = $child->getAttribute('RRULE');
if (is_a($rrules, 'PEAR_Error')) {
if (!is_int($switch_time)) {
return false;
}
// Convert this timestamp from local time to UTC for
// comparison (All dates are compared as if they are UTC).
$t = getdate($switch_time);
$result['time'] = @gmmktime($t['hours'], $t['minutes'], $t['seconds'],
$t['mon'], $t['mday'], $t['year']);
return $result;
}
$switch_year = date("Y", $switch_time);
if ($switch_year > $year) {
return false;
}
$rrules = explode(';', $rrules);
foreach ($rrules as $rrule) {
$t = explode('=', $rrule);
switch ($t[0]) {
case 'FREQ':
switch($t[1]) {
case 'YEARLY':
if ($rrule_interval == 12) {
return false;
}
$rrule_interval = 1;
break;
case 'MONTHLY':
if ($rrule_interval == 1) {
return false;
}
$rrule_interval = 12;
break;
default:
return false;
}
break;
case 'INTERVAL':
if ($rrule_interval && $t[1] != $rrule_interval) {
return false;
}
$rrule_interval = intval($t[1]);
if ($rrule_interval != 1 && $rrule_interval != 12) {
return false;
}
break;
case 'COUNT':
if ($switch_year + intval($t[1]) < intval($year)) {
return false;
}
break;
case 'BYMONTH':
$month = intval($t[1]);
break;
case 'BYDAY':
$len = strspn($t[1], '1234567890-+');
if ($len == 0) {
return false;
}
$weekday = substr($t[1], $len);
$weekdays = array(
'SU' => 0,
'MO' => 1,
'TU' => 2,
'WE' => 3,
'TH' => 4,
'FR' => 5,
'SA' => 6
);
$weekday = $weekdays[$weekday];
$which = intval(substr($t[1], 0, $len));
break;
case 'UNTIL':
if (intval($year) > intval(substr($t[1], 0, 4))) {
return false;
}
break;
}
}
if ($rrule_interval == 12) {
$month = date("n", $switch_time);
}
if (empty($month) || !isset($weekday)) {
return false;
}
if (is_int($switch_time)) {
// Was stored as localtime.
$switch_time = strftime('%H:%M:%S', $switch_time);
$switch_time = explode(':', $switch_time);
} else {
$switch_time = explode('T', $switch_time);
if (count($switch_time) != 2) {
return false;
}
$switch_time[0] = substr($switch_time[1], 0, 2);
$switch_time[2] = substr($switch_time[1], 4, 2);
$switch_time[1] = substr($switch_time[1], 2, 2);
}
// Get the timestamp for the first day of $month.
$when = gmmktime($switch_time[0], $switch_time[1], $switch_time[2],
$month, 1, $year);
// Get the day of the week for the first day of $month.
$first_of_month_weekday = intval(gmstrftime('%w', $when));
// Go to the first $weekday before first day of $month.
if ($weekday >= $first_of_month_weekday) {
$weekday -= 7;
}
$when -= ($first_of_month_weekday - $weekday) * 60 * 60 * 24;
// If going backwards go to the first $weekday after last day
// of $month.
if ($which < 0) {
do {
$when += 60*60*24*7;
} while (intval(gmstrftime('%m', $when)) == $month);
}
// Calculate $weekday number $which.
$when += $which * 60 * 60 * 24 * 7;
$result['time'] = $when;
return $result;
}
}
/**
* @package Horde_iCalendar
*/
class Horde_iCalendar_standard extends Horde_iCalendar {
function getType()
{
return 'standard';
}
function parsevCalendar($data)
{
parent::parsevCalendar($data, 'STANDARD');
}
function exportvCalendar()
{
return parent::_exportvData('STANDARD');
}
}
/**
* @package Horde_iCalendar
*/
class Horde_iCalendar_daylight extends Horde_iCalendar {
function getType()
{
return 'daylight';
}
function parsevCalendar($data)
{
parent::parsevCalendar($data, 'DAYLIGHT');
}
function exportvCalendar()
{
return parent::_exportvData('DAYLIGHT');
}
}

View File

@ -1,84 +0,0 @@
<?php
/**
* Class representing vTodos.
*
* $Horde: framework/iCalendar/iCalendar/vtodo.php,v 1.13.10.8 2008/07/03 08:42:58 jan Exp $
*
* Copyright 2003-2008 The Horde Project (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Mike Cochrane <mike@graftonhall.co.nz>
* @since Horde 3.0
* @package Horde_iCalendar
*/
class Horde_iCalendar_vtodo extends Horde_iCalendar {
function getType()
{
return 'vTodo';
}
function exportvCalendar()
{
return parent::_exportvData('VTODO');
}
/**
* Convert this todo to an array of attributes.
*
* @return array Array containing the details of the todo in a hash
* as used by Horde applications.
*/
function toArray()
{
$todo = array();
$name = $this->getAttribute('SUMMARY');
if (!is_array($name) && !is_a($name, 'PEAR_Error')) {
$todo['name'] = $name;
}
$desc = $this->getAttribute('DESCRIPTION');
if (!is_array($desc) && !is_a($desc, 'PEAR_Error')) {
$todo['desc'] = $desc;
}
$priority = $this->getAttribute('PRIORITY');
if (!is_array($priority) && !is_a($priority, 'PEAR_Error')) {
$todo['priority'] = $priority;
}
$due = $this->getAttribute('DTSTAMP');
if (!is_array($due) && !is_a($due, 'PEAR_Error')) {
$todo['due'] = $due;
}
return $todo;
}
/**
* Set the attributes for this todo item from an array.
*
* @param array $todo Array containing the details of the todo in
* the same format that toArray() exports.
*/
function fromArray($todo)
{
if (isset($todo['name'])) {
$this->setAttribute('SUMMARY', $todo['name']);
}
if (isset($todo['desc'])) {
$this->setAttribute('DESCRIPTION', $todo['desc']);
}
if (isset($todo['priority'])) {
$this->setAttribute('PRIORITY', $todo['priority']);
}
if (isset($todo['due'])) {
$this->setAttribute('DTSTAMP', $todo['due']);
}
}
}

View File

@ -1,300 +0,0 @@
<?php
/**
* Constants are from Binary XML Content Format Specification Version 1.3, 25
* July 2001 found at http://www.wapforum.org
*/
/**
* From 7.1 Global Tokens.
*/
define('XML_WBXML_GLOBAL_TOKEN_SWITCH_PAGE', 0); // 0x00
define('XML_WBXML_GLOBAL_TOKEN_END', 1); // 0x01
define('XML_WBXML_GLOBAL_TOKEN_ENTITY', 2); // 0x02
define('XML_WBXML_GLOBAL_TOKEN_STR_I', 3); // 0x03
define('XML_WBXML_GLOBAL_TOKEN_LITERAL', 4); // 0x04
define('XML_WBXML_GLOBAL_TOKEN_EXT_I_0', 64); // 0x40
define('XML_WBXML_GLOBAL_TOKEN_EXT_I_1', 65); // 0x41
define('XML_WBXML_GLOBAL_TOKEN_EXT_I_2', 66); // 0x42
define('XML_WBXML_GLOBAL_TOKEN_PI', 67); // 0x43
define('XML_WBXML_GLOBAL_TOKEN_LITERAL_C', 68); // 0x44
define('XML_WBXML_GLOBAL_TOKEN_EXT_T_0', 128); // 0x80
define('XML_WBXML_GLOBAL_TOKEN_EXT_T_1', 129); // 0x81
define('XML_WBXML_GLOBAL_TOKEN_EXT_T_2', 130); // 0x82
define('XML_WBXML_GLOBAL_TOKEN_STR_T', 131); // 0x83
define('XML_WBXML_GLOBAL_TOKEN_LITERAL_A', 132); // 0x84
define('XML_WBXML_GLOBAL_TOKEN_EXT_0', 192); // 0xC0
define('XML_WBXML_GLOBAL_TOKEN_EXT_1', 193); // 0xC1
define('XML_WBXML_GLOBAL_TOKEN_EXT_2', 194); // 0xC2
define('XML_WBXML_GLOBAL_TOKEN_OPAQUE', 195); // 0xC3
define('XML_WBXML_GLOBAL_TOKEN_LITERAL_AC', 196); // 0xC4
/**
* Not sure where defined.
* ADD CHAPTER
*/
define('DPI_DTD_WML_1_0', '-//WAPFORUM//DTD WML 1.0//EN');
define('DPI_DTD_WTA_1_0', '-//WAPFORUM//DTD WTA 1.0//EN');
define('DPI_DTD_WML_1_1', '-//WAPFORUM//DTD WML 1.1//EN');
define('DPI_DTD_SI_1_1', '-//WAPFORUM//DTD SI 1.1//EN');
define('DPI_DTD_SL_1_0', '-//WAPFORUM//DTD SL 1.0//EN');
define('DPI_DTD_CO_1_0', '-//WAPFORUM//DTD CO 1.0//EN');
define('DPI_DTD_CHANNEL_1_1', '-//WAPFORUM//DTD CHANNEL 1.1//EN');
define('DPI_DTD_WML_1_2', '-//WAPFORUM//DTD WML 1.2//EN');
define('DPI_DTD_WML_1_3', '-//WAPFORUM//DTD WML 1.3//EN');
define('DPI_DTD_PROV_1_0', '-//WAPFORUM//DTD PROV 1.0//EN');
define('DPI_DTD_WTA_WML_1_2', '-//WAPFORUM//DTD WTA-WML 1.2//EN');
define('DPI_DTD_CHANNEL_1_2', '-//WAPFORUM//DTD CHANNEL 1.2//EN');
define('DPI_DTD_SYNCML_1_0', '-//SYNCML//DTD SyncML 1.0//EN');
define('DPI_DTD_DEVINF_1_0', '-//SYNCML//DTD DevInf 1.0//EN');
define('DPI_DTD_METINF_1_0', '-//SYNCML//DTD MetInf 1.0//EN');
define('DPI_DTD_SYNCML_1_1', '-//SYNCML//DTD SyncML 1.1//EN');
define('DPI_DTD_DEVINF_1_1', '-//SYNCML//DTD DevInf 1.1//EN');
define('DPI_DTD_METINF_1_1', '-//SYNCML//DTD MetInf 1.1//EN');
define('DPI_DTD_SYNCML_1_2', '-//SYNCML//DTD SyncML 1.2//EN');
define('DPI_DTD_DEVINF_1_2', '-//SYNCML//DTD DevInf 1.2//EN');
define('DPI_DTD_METINF_1_2', '-//SYNCML//DTD MetInf 1.2//EN');
/**
* Only default character encodings from J2SE are currently supported.
*/
define('CHARSET_US_ASCII', 'US-ASCII');
define('CHARSET_ISO_8859_1', 'ISO-8859-1');
define('CHARSET_UTF_8', 'UTF-8');
define('CHARSET_UTF_16BE', 'UTF-16BE');
define('CHARSET_UTF_16LE', 'UTF-16LE');
define('CHARSET_UTF_16', 'UTF-16');
/**
* $Horde: framework/XML_WBXML/WBXML.php,v 1.13.12.11 2008/01/02 11:31:02 jan Exp $
*
* Copyright 2003-2008 The Horde Project (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Anthony Mills <amills@pyramid6.com>
* @package XML_WBXML
*/
class XML_WBXML {
/**
* Decoding Multi-byte Integers from Section 5.1
*
* Use long because it is unsigned.
*/
function MBUInt32ToInt($in, &$pos)
{
$val = 0;
do {
$b = ord($in[$pos++]);
$val <<= 7; // Bitshift left 7 bits.
$val += ($b & 127);
} while (($b & 128) != 0);
return $val;
}
/**
* Encoding Multi-byte Integers from Section 5.1
*/
function intToMBUInt32(&$out, $i)
{
if ($i > 268435455) {
$bytes0 = 0 | XML_WBXML::getBits(0, $i);
$bytes1 = 128 | XML_WBXML::getBits(1, $i);
$bytes2 = 128 | XML_WBXML::getBits(2, $i);
$bytes3 = 128 | XML_WBXML::getBits(3, $i);
$bytes4 = 128 | XML_WBXML::getBits(4, $i);
$out .= chr($bytes4) . chr($bytes3) . chr($bytes2) . chr($bytes1) . chr($bytes0);
} elseif ($i > 2097151) {
$bytes0 = 0 | XML_WBXML::getBits(0, $i);
$bytes1 = 128 | XML_WBXML::getBits(1, $i);
$bytes2 = 128 | XML_WBXML::getBits(2, $i);
$bytes3 = 128 | XML_WBXML::getBits(3, $i);
$out .= chr($bytes3) . chr($bytes2) . chr($bytes1) . chr($bytes0);
} elseif ($i > 16383) {
$bytes0 = 0 | XML_WBXML::getBits(0, $i);
$bytes1 = 128 | XML_WBXML::getBits(1, $i);
$bytes2 = 128 | XML_WBXML::getBits(2, $i);
$out .= chr($bytes2) . chr($bytes1) . chr($bytes0);
} elseif ($i > 127) {
$bytes0 = 0 | XML_WBXML::getBits(0, $i);
$bytes1 = 128 | XML_WBXML::getBits(1, $i);
$out .= chr($bytes1) . chr($bytes0);
} else {
$bytes0 = 0 | XML_WBXML::getBits(0, $i);
$out .= chr($bytes0);
}
}
function getBits($num, $l)
{
switch ($num) {
case 0:
return $l & 127; // 0x7F
case 1:
return ($l >> 7) & 127; // 0x7F
case 2:
return ($l >> 14) & 127; // 0x7F
case 3:
return ($l >> 21) & 127; // 0x7F
case 4:
return ($l >> 28) & 127; // 0x7F
}
return 0;
}
function getDPIString($i)
{
/**
* ADD CHAPTER
*/
$DPIString = array(2 => DPI_DTD_WML_1_0,
3 => DPI_DTD_WTA_1_0,
4 => DPI_DTD_WML_1_1,
5 => DPI_DTD_SI_1_1,
6 => DPI_DTD_SL_1_0,
7 => DPI_DTD_CO_1_0,
8 => DPI_DTD_CHANNEL_1_1,
9 => DPI_DTD_WML_1_2,
10 => DPI_DTD_WML_1_3,
11 => DPI_DTD_PROV_1_0,
12 => DPI_DTD_WTA_WML_1_2,
13 => DPI_DTD_CHANNEL_1_2,
// Not all SyncML clients know this, so we
// should use the string table.
// 0xFD1 => DPI_DTD_SYNCML_1_1,
// These codes are taken from libwbxml wbxml_tables.h:
4049 => DPI_DTD_SYNCML_1_0, // 0x0fd1
4050 => DPI_DTD_DEVINF_1_0, // 0x0fd2
4051 => DPI_DTD_SYNCML_1_1, // 0x0fd3
4052 => DPI_DTD_DEVINF_1_1, // 0x0fd4
4609 => DPI_DTD_SYNCML_1_2, // 0x1201
//@todo: verify this:
4611 => DPI_DTD_DEVINF_1_2 // 0x1203
// taken from libxml but might be wrong:
// 4610 => DPI_DTD_DEVINF_1_2, // 0x1202
// 4611 => DPI_DTD_METINF_1_2 // 0x1203
);
return isset($DPIString[$i]) ? $DPIString[$i] : null;
}
function getDPIInt($dpi)
{
/**
* ADD CHAPTER
*/
$DPIInt = array(DPI_DTD_WML_1_0 => 2,
DPI_DTD_WTA_1_0 => 3,
DPI_DTD_WML_1_1 => 4,
DPI_DTD_SI_1_1 => 5,
DPI_DTD_SL_1_0 => 6,
DPI_DTD_CO_1_0 => 7,
DPI_DTD_CHANNEL_1_1 => 8,
DPI_DTD_WML_1_2 => 9,
DPI_DTD_WML_1_3 => 10,
DPI_DTD_PROV_1_0 => 11,
DPI_DTD_WTA_WML_1_2 => 12,
DPI_DTD_CHANNEL_1_2 => 13,
// Not all SyncML clients know this, so maybe we
// should use the string table.
// These codes are taken from libwbxml wbxml_tables.h:
DPI_DTD_SYNCML_1_0 => 4049,
DPI_DTD_DEVINF_1_0 => 4050,
DPI_DTD_SYNCML_1_1 => 4051,
DPI_DTD_DEVINF_1_1 => 4052,
DPI_DTD_SYNCML_1_2 => 4609, // 0x1201
// DPI_DTD_DEVINF_1_2 => 4610, // 0x1202
// DPI_DTD_METINF_1_2 => 4611 // 0x1203
//@todo: verify this
DPI_DTD_DEVINF_1_2 => 4611 // 0x1203
// DPI_DTD_SYNCML_1_1 => 0xFD1,
// DPI_DTD_DEVINF_1_1 => 0xFD2,
);
return isset($DPIInt[$dpi]) ? $DPIInt[$dpi] : 0;
}
/**
* Returns the character encoding.
* only default character encodings from J2SE are supported
* from http://www.iana.org/assignments/character-sets
* and http://java.sun.com/j2se/1.4.2/docs/api/java/nio/charset/Charset.html
*/
function getCharsetString($cs)
{
/**
* From http://www.iana.org/assignments/character-sets
*/
$charsetString = array(3 => 'US-ASCII',
4 => 'ISO-8859-1',
106 => 'UTF-8',
1013 => 'UTF-16BE',
1014 => 'UTF-16LE',
1015 => 'UTF-16');
return isset($charsetString[$cs]) ? $charsetString[$cs] : null;
}
/**
* Returns the character encoding.
*
* Only default character encodings from J2SE are supported.
*
* From http://www.iana.org/assignments/character-sets and
* http://java.sun.com/j2se/1.4.2/docs/api/java/nio/charset/Charset.html
*/
function getCharsetInt($cs)
{
/**
* From http://www.iana.org/assignments/character-sets
*/
$charsetInt = array('US-ASCII' => 3,
'ISO-8859-1' => 4,
'UTF-8' => 106,
'UTF-16BE' => 1013,
'UTF-16LE' => 1014,
'UTF-16' => 1015);
return isset($charsetInt[$cs]) ? $charsetInt[$cs] : null;
}
}
/**
* @package XML_WBXML
*/
class XML_WBXML_HashTable {
var $_h;
function set($k, $v)
{
$this->_h[$k] = $v;
}
function get($k)
{
return isset($this->_h[$k]) ? $this->_h[$k] : null;
}
}

View File

@ -1,167 +0,0 @@
<?php
/**
* From Binary XML Content Format Specification Version 1.3, 25 July 2001
* found at http://www.wapforum.org
*
* $Horde: framework/XML_WBXML/WBXML/ContentHandler.php,v 1.9.10.11 2008/08/26 15:41:13 jan Exp $
*
* Copyright 2003-2008 The Horde Project (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Anthony Mills <amills@pyramid6.com>
* @package XML_WBXML
*/
class XML_WBXML_ContentHandler {
var $_currentUri;
var $_output = '';
var $_opaqueHandler;
/**
* Charset.
*/
var $_charset = 'UTF-8';
/**
* WBXML Version.
* 0, 1 or 2 supported
*/
var $_wbxmlVersion = 2;
function XML_WBXML_ContentHandler()
{
$this->_currentUri = new XML_WBXML_LifoQueue();
}
/**
*/
function raiseError($error)
{
if (!class_exists('PEAR')) {
require 'PEAR.php';
}
return PEAR::raiseError($error);
}
function getCharsetStr()
{
return $this->_charset;
}
function setCharset($cs)
{
$this->_charset = $cs;
}
function getVersion()
{
return $this->_wbxmlVersion;
}
function setVersion($v)
{
$this->_wbxmlVersion = $v;
}
function getOutput()
{
return $this->_output;
}
function getOutputSize()
{
return strlen($this->_output);
}
function startElement($uri, $element, $attrs = array())
{
$this->_output .= '<' . $element;
$currentUri = $this->_currentUri->top();
if (((!$currentUri) || ($currentUri != $uri)) && $uri) {
$this->_output .= ' xmlns="' . $uri . '"';
}
$this->_currentUri->push($uri);
foreach ($attrs as $attr) {
$this->_output .= ' ' . $attr['attribute'] . '="' . $attr['value'] . '"';
}
$this->_output .= '>';
}
function endElement($uri, $element)
{
$this->_output .= '</' . $element . '>';
$this->_currentUri->pop();
}
function characters($str)
{
$this->_output .= $str;
}
function opaque($o)
{
$this->_output .= $o;
}
function setOpaqueHandler($opaqueHandler)
{
$this->_opaqueHandler = $opaqueHandler;
}
function removeOpaqueHandler()
{
unset($this->_opaqueHandler);
}
function createSubHandler()
{
$name = get_class($this); // clone current class
$sh = new $name();
$sh->setCharset($this->getCharsetStr());
$sh->setVersion($this->getVersion());
return $sh;
}
}
class XML_WBXML_LifoQueue {
var $_queue = array();
function XML_WBXML_LifoQueue()
{
}
function push($obj)
{
$this->_queue[] = $obj;
}
function pop()
{
if (count($this->_queue)) {
return array_pop($this->_queue);
} else {
return null;
}
}
function top()
{
if ($count = count($this->_queue)) {
return $this->_queue[$count - 1];
} else {
return null;
}
}
}

View File

@ -1,156 +0,0 @@
<?php
/**
* From Binary XML Content Format Specification Version 1.3, 25 July 2001
* found at http://www.wapforum.org
*
* $Horde: framework/XML_WBXML/WBXML/DTD.php,v 1.6.12.8 2008/01/02 11:31:02 jan Exp $
*
* Copyright 2003-2008 The Horde Project (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Anthony Mills <amills@pyramid6.com>
* @package XML_WBXML
*/
class XML_WBXML_DTD {
var $version;
var $intTags;
var $intAttributes;
var $strTags;
var $strAttributes;
var $intCodePages;
var $strCodePages;
var $strCodePagesURI;
var $URI;
var $XMLNS;
var $DPI;
function XML_WBXML_DTD($v)
{
$this->version = $v;
$this->init();
}
function init()
{
}
function setAttribute($intAttribute, $strAttribute)
{
$this->strAttributes[$strAttribute] = $intAttribute;
$this->intAttributes[$intAttribute] = $strAttribute;
}
function setTag($intTag, $strTag)
{
$this->strTags[$strTag] = $intTag;
$this->intTags[$intTag] = $strTag;
}
function setCodePage($intCodePage, $strCodePage, $strCodePageURI)
{
$this->strCodePagesURI[$strCodePageURI] = $intCodePage;
$this->strCodePages[$strCodePage] = $intCodePage;
$this->intCodePages[$intCodePage] = $strCodePage;
}
function toTagStr($tag)
{
return isset($this->intTags[$tag]) ? $this->intTags[$tag] : false;
}
function toAttributeStr($attribute)
{
return isset($this->intTags[$attribute]) ? $this->intTags[$attribute] : false;
}
function toCodePageStr($codePage)
{
return isset($this->intCodePages[$codePage]) ? $this->intCodePages[$codePage] : false;
}
function toTagInt($tag)
{
return isset($this->strTags[$tag]) ? $this->strTags[$tag] : false;
}
function toAttributeInt($attribute)
{
return isset($this->strAttributes[$attribute]) ? $this->strAttributes[$attribute] : false;
}
function toCodePageInt($codePage)
{
return isset($this->strCodePages[$codePage]) ? $this->strCodePages[$codePage] : false;
}
function toCodePageURI($uri)
{
$uri = strtolower($uri);
if (!isset($this->strCodePagesURI[$uri])) {
//Horde::logMessage("WBXML unable to find codepage for $uri!", __FILE__, __LINE__, PEAR_LOG_DEBUG);
//die("unable to find codepage for $uri!\n");
}
$ret = isset($this->strCodePagesURI[$uri]) ? $this->strCodePagesURI[$uri] : false;
return $ret;
}
/**
* Getter for property version.
* @return Value of property version.
*/
function getVersion()
{
return $this->version;
}
/**
* Setter for property version.
* @param integer $v New value of property version.
*/
function setVersion($v)
{
$this->version = $v;
}
/**
* Getter for property URI.
* @return Value of property URI.
*/
function getURI()
{
return $this->URI;
}
/**
* Setter for property URI.
* @param string $u New value of property URI.
*/
function setURI($u)
{
$this->URI = $u;
}
/**
* Getter for property DPI.
* @return Value of property DPI.
*/
function getDPI()
{
return $this->DPI;
}
/**
* Setter for property DPI.
* @param DPI New value of property DPI.
*/
function setDPI($d)
{
$this->DPI = $d;
}
}

View File

@ -1,102 +0,0 @@
<?php
include_once 'XML/WBXML/DTD.php';
/**
* From Binary XML Content Format Specification Version 1.3, 25 July 2001
* found at http://www.wapforum.org
*
* $Horde: framework/XML_WBXML/WBXML/DTD/SyncML.php,v 1.6.12.8 2008/01/02 11:31:03 jan Exp $
*
* Copyright 2003-2008 The Horde Project (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Anthony Mills <amills@pyramid6.com>
* @package XML_WBXML
*/
class XML_WBXML_DTD_SyncML extends XML_WBXML_DTD {
function init()
{
/* this code table has been extracted from libwbxml
* (see http://libwbxml.aymerick.com/) by using
*
* grep '\"[^\"]*\", *0x.., 0x.. },' wbxml_tables.c
* | sed -e 's#^.*\"\([^\"]*\)\", *\(0x..\), \(0x..\) },.*$# \$this->setTag\(\3, \"\1\"\); // \2#g'
*/
$this->setTag(0x05, "Add"); // 0x00
$this->setTag(0x06, "Alert"); // 0x00
$this->setTag(0x07, "Archive"); // 0x00
$this->setTag(0x08, "Atomic"); // 0x00
$this->setTag(0x09, "Chal"); // 0x00
$this->setTag(0x0a, "Cmd"); // 0x00
$this->setTag(0x0b, "CmdID"); // 0x00
$this->setTag(0x0c, "CmdRef"); // 0x00
$this->setTag(0x0d, "Copy"); // 0x00
$this->setTag(0x0e, "Cred"); // 0x00
$this->setTag(0x0f, "Data"); // 0x00
$this->setTag(0x10, "Delete"); // 0x00
$this->setTag(0x11, "Exec"); // 0x00
$this->setTag(0x12, "Final"); // 0x00
$this->setTag(0x13, "Get"); // 0x00
$this->setTag(0x14, "Item"); // 0x00
$this->setTag(0x15, "Lang"); // 0x00
$this->setTag(0x16, "LocName"); // 0x00
$this->setTag(0x17, "LocURI"); // 0x00
$this->setTag(0x18, "Map"); // 0x00
$this->setTag(0x19, "MapItem"); // 0x00
$this->setTag(0x1a, "Meta"); // 0x00
$this->setTag(0x1b, "MsgID"); // 0x00
$this->setTag(0x1c, "MsgRef"); // 0x00
$this->setTag(0x1d, "NoResp"); // 0x00
$this->setTag(0x1e, "NoResults"); // 0x00
$this->setTag(0x1f, "Put"); // 0x00
$this->setTag(0x20, "Replace"); // 0x00
$this->setTag(0x21, "RespURI"); // 0x00
$this->setTag(0x22, "Results"); // 0x00
$this->setTag(0x23, "Search"); // 0x00
$this->setTag(0x24, "Sequence"); // 0x00
$this->setTag(0x25, "SessionID"); // 0x00
$this->setTag(0x26, "SftDel"); // 0x00
$this->setTag(0x27, "Source"); // 0x00
$this->setTag(0x28, "SourceRef"); // 0x00
$this->setTag(0x29, "Status"); // 0x00
$this->setTag(0x2a, "Sync"); // 0x00
$this->setTag(0x2b, "SyncBody"); // 0x00
$this->setTag(0x2c, "SyncHdr"); // 0x00
$this->setTag(0x2d, "SyncML"); // 0x00
$this->setTag(0x2e, "Target"); // 0x00
$this->setTag(0x2f, "TargetRef"); // 0x00
$this->setTag(0x30, "Reserved for future use"); // 0x00
$this->setTag(0x31, "VerDTD"); // 0x00
$this->setTag(0x32, "VerProto"); // 0x00
$this->setTag(0x33, "NumberOfChanges"); // 0x00
$this->setTag(0x34, "MoreData"); // 0x00
$this->setTag(0x35, "Field"); // 0x00
$this->setTag(0x36, "Filter"); // 0x00
$this->setTag(0x37, "Record"); // 0x00
$this->setTag(0x38, "FilterType"); // 0x00
$this->setTag(0x39, "SourceParent"); // 0x00
$this->setTag(0x3a, "TargetParent"); // 0x00
$this->setTag(0x3b, "Move"); // 0x00
$this->setTag(0x3c, "Correlator"); // 0x00
if ($this->version == 1) {
$this->setCodePage(0, DPI_DTD_SYNCML_1_1, 'syncml:syncml1.1');
$this->setCodePage(1, DPI_DTD_METINF_1_1, 'syncml:metinf1.1');
$this->setURI('syncml:syncml1.1');
} elseif ($this->version == 2) {
$this->setCodePage(0, DPI_DTD_SYNCML_1_2, 'syncml:syncml1.2');
$this->setCodePage(1, DPI_DTD_METINF_1_2, 'syncml:metinf1.2');
$this->setURI('syncml:syncml1.2');
} else {
$this->setCodePage(0, DPI_DTD_SYNCML_1_0, 'syncml:syncml1.0');
$this->setCodePage(1, DPI_DTD_METINF_1_0, 'syncml:metinf1.0');
$this->setURI('syncml:syncml1.0');
}
}
}

View File

@ -1,92 +0,0 @@
<?php
include_once 'XML/WBXML/DTD.php';
/**
* From Binary XML Content Format Specification Version 1.3, 25 July 2001
* found at http://www.wapforum.org
*
* $Horde: framework/XML_WBXML/WBXML/DTD/SyncMLDevInf.php,v 1.4.12.8 2008/01/02 11:31:03 jan Exp $
*
* Copyright 2003-2008 The Horde Project (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Anthony Mills <amills@pyramid6.com>
* @package XML_WBXML
*/
class XML_WBXML_DTD_SyncMLDevInf extends XML_WBXML_DTD {
function init()
{
/* this code table has been extracted from libwbxml
* (see http://libwbxml.aymerick.com/) by using
*
* grep '\"[^\"]*\", *0x.., 0x.. },' wbxml_tables.c
* | sed -e 's#^.*\"\([^\"]*\)\", *\(0x..\), \(0x..\) },.*$# \$this->setTag\(\3, \"\1\"\); // \2#g'
*/
#Horde::logMessage("XML_WBXML_DTD_SyncMLDevInf version=" . $this->version, __FILE__, __LINE__, PEAR_LOG_DEBUG);
$this->setTag(0x05, "CTCap"); // 0x00
$this->setTag(0x06, "CTType"); // 0x00
$this->setTag(0x07, "DataStore"); // 0x00
$this->setTag(0x08, "DataType"); // 0x00
$this->setTag(0x09, "DevID"); // 0x00
$this->setTag(0x0a, "DevInf"); // 0x00
$this->setTag(0x0b, "DevTyp"); // 0x00
$this->setTag(0x0c, "DisplayName"); // 0x00
$this->setTag(0x0d, "DSMem"); // 0x00
$this->setTag(0x0e, "Ext"); // 0x00
$this->setTag(0x0f, "FwV"); // 0x00
$this->setTag(0x10, "HwV"); // 0x00
$this->setTag(0x11, "Man"); // 0x00
$this->setTag(0x12, "MaxGUIDSize"); // 0x00
$this->setTag(0x13, "MaxID"); // 0x00
$this->setTag(0x14, "MaxMem"); // 0x00
$this->setTag(0x15, "Mod"); // 0x00
$this->setTag(0x16, "OEM"); // 0x00
$this->setTag(0x17, "ParamName"); // 0x00
$this->setTag(0x18, "PropName"); // 0x00
$this->setTag(0x19, "Rx"); // 0x00
$this->setTag(0x1a, "Rx-Pref"); // 0x00
$this->setTag(0x1b, "SharedMem"); // 0x00
$this->setTag(0x1c, "Size"); // 0x00
$this->setTag(0x1d, "SourceRef"); // 0x00
$this->setTag(0x1e, "SwV"); // 0x00
$this->setTag(0x1f, "SyncCap"); // 0x00
$this->setTag(0x20, "SyncType"); // 0x00
$this->setTag(0x21, "Tx"); // 0x00
$this->setTag(0x22, "Tx-Pref"); // 0x00
$this->setTag(0x23, "ValEnum"); // 0x00
$this->setTag(0x24, "VerCT"); // 0x00
$this->setTag(0x25, "VerDTD"); // 0x00
$this->setTag(0x26, "XNam"); // 0x00
$this->setTag(0x27, "XVal"); // 0x00
$this->setTag(0x28, "UTC"); // 0x00
$this->setTag(0x29, "SupportNumberOfChanges"); // 0x00
$this->setTag(0x2a, "SupportLargeObjs"); // 0x00
$this->setTag(0x2b, "Property"); // 0x00
$this->setTag(0x2c, "PropParam"); // 0x00
$this->setTag(0x2d, "MaxOccur"); // 0x00
$this->setTag(0x2e, "NoTruncate"); // 0x00
$this->setTag(0x30, "Filter-Rx"); // 0x00
$this->setTag(0x31, "FilterCap"); // 0x00
$this->setTag(0x32, "FilterKeyword"); // 0x00
$this->setTag(0x33, "FieldLevel"); // 0x00
$this->setTag(0x34, "SupportHierarchicalSync"); // 0x00
if ($this->version == 1) {
$this->setCodePage(0, DPI_DTD_DEVINF_1_1, 'syncml:devinf1.1');
$this->setURI('syncml:devinf1.1');
} elseif ($this->version == 2) {
$this->setCodePage(0, DPI_DTD_DEVINF_1_2, 'syncml:devinf1.2');
$this->setURI('syncml:devinf1.2');
} else {
$this->setCodePage(0, DPI_DTD_DEVINF_1_0, 'syncml:devinf1.0');
$this->setURI('syncml:devinf1.0');
}
}
}

View File

@ -1,66 +0,0 @@
<?php
include_once 'XML/WBXML/DTD.php';
/**
* From Binary XML Content Format Specification Version 1.3, 25 July 2001
* found at http://www.wapforum.org
*
* $Horde: framework/XML_WBXML/WBXML/DTD/SyncMLMetInf.php,v 1.4.12.8 2008/01/02 11:31:03 jan Exp $
*
* Copyright 2003-2008 The Horde Project (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Anthony Mills <amills@pyramid6.com>
* @package XML_WBXML
*/
class XML_WBXML_DTD_SyncMLMetInf extends XML_WBXML_DTD {
function init()
{
/* this code table has been extracted from libwbxml
* (see http://libwbxml.aymerick.com/) by using
*
* grep '\"[^\"]*\", *0x.., 0x.. },' wbxml_tables.c
* | sed -e 's#^.*\"\([^\"]*\)\", *\(0x..\), \(0x..\) },.*$# \$this->setTag\(\3, \"\1\"\); // \2#g'
*/
$this->setTag(0x05, "Anchor"); // 0x01
$this->setTag(0x06, "EMI"); // 0x01
$this->setTag(0x07, "Format"); // 0x01
$this->setTag(0x08, "FreeID"); // 0x01
$this->setTag(0x09, "FreeMem"); // 0x01
$this->setTag(0x0a, "Last"); // 0x01
$this->setTag(0x0b, "Mark"); // 0x01
$this->setTag(0x0c, "MaxMsgSize"); // 0x01
$this->setTag(0x15, "MaxObjSize"); // 0x01
$this->setTag(0x0d, "Mem"); // 0x01
$this->setTag(0x0e, "MetInf"); // 0x01
$this->setTag(0x0f, "Next"); // 0x01
$this->setTag(0x10, "NextNonce"); // 0x01
$this->setTag(0x11, "SharedMem"); // 0x01
$this->setTag(0x12, "Size"); // 0x01
$this->setTag(0x13, "Type"); // 0x01
$this->setTag(0x14, "Version"); // 0x01
$this->setTag(0x15, "MaxObjSize"); // 0x01
$this->setTag(0x16, "FieldLevel"); // 0x01
if ($this->version == 1) {
$this->setCodePage(0, DPI_DTD_SYNCML_1_1, 'syncml:syncml1.1');
$this->setCodePage(1, DPI_DTD_METINF_1_1, 'syncml:metinf1.1');
$this->setURI('syncml:metinf1.1');
//$this->setURI('syncml:metinf'); // for some funny reason, libwbxml produces no :metinf1.1 here
} elseif ($this->version == 2) {
$this->setCodePage(0, DPI_DTD_SYNCML_1_2, 'syncml:syncml1.2');
$this->setCodePage(1, DPI_DTD_METINF_1_2, 'syncml:metinf1.2');
$this->setURI('syncml:metinf1.2');
} else {
$this->setCodePage(0, DPI_DTD_SYNCML_1_0, 'syncml:syncml1.0');
$this->setCodePage(1, DPI_DTD_METINF_1_0, 'syncml:metinf1.0');
$this->setURI('syncml:metinf1.0');
}
}
}

View File

@ -1,100 +0,0 @@
<?php
include_once 'XML/WBXML/DTD/SyncML.php';
include_once 'XML/WBXML/DTD/SyncMLMetInf.php';
include_once 'XML/WBXML/DTD/SyncMLDevInf.php';
/**
* From Binary XML Content Format Specification Version 1.3, 25 July 2001
* found at http://www.wapforum.org
*
* $Horde: framework/XML_WBXML/WBXML/DTDManager.php,v 1.3.12.14 2008/01/02 11:31:02 jan Exp $
*
* Copyright 2003-2008 The Horde Project (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Anthony Mills <amills@pyramid6.com>
* @package XML_WBXML
*/
class XML_WBXML_DTDManager {
/**
* @var array
*/
var $_strDTD = array();
/**
* @var array
*/
var $_strDTDURI = array();
/**
*/
function XML_WBXML_DTDManager()
{
$this->registerDTD(DPI_DTD_SYNCML_1_0, 'syncml:syncml1.0', new XML_WBXML_DTD_SyncML(0));
$this->registerDTD(DPI_DTD_SYNCML_1_1, 'syncml:syncml1.1', new XML_WBXML_DTD_SyncML(1));
$this->registerDTD(DPI_DTD_SYNCML_1_2, 'syncml:syncml1.2', new XML_WBXML_DTD_SyncML(2));
$this->registerDTD(DPI_DTD_METINF_1_0, 'syncml:metinf1.0', new XML_WBXML_DTD_SyncMLMetInf(0));
$this->registerDTD(DPI_DTD_METINF_1_1, 'syncml:metinf1.1', new XML_WBXML_DTD_SyncMLMetInf(1));
$this->registerDTD(DPI_DTD_METINF_1_2, 'syncml:metinf1.2', new XML_WBXML_DTD_SyncMLMetInf(2));
$this->registerDTD(DPI_DTD_DEVINF_1_0, 'syncml:devinf1.0', new XML_WBXML_DTD_SyncMLDevInf(0));
$this->registerDTD(DPI_DTD_DEVINF_1_1, 'syncml:devinf1.1', new XML_WBXML_DTD_SyncMLDevInf(1));
$this->registerDTD(DPI_DTD_DEVINF_1_2, 'syncml:devinf1.2', new XML_WBXML_DTD_SyncMLDevInf(2));
}
/**
*/
function &getInstance($publicIdentifier)
{
$publicIdentifier = strtolower($publicIdentifier);
if (isset($this->_strDTD[$publicIdentifier])) {
$dtd = &$this->_strDTD[$publicIdentifier];
} else {
$dtd = null;
}
return $dtd;
}
/**
*/
function &getInstanceURI($uri)
{
$uri = strtolower($uri);
// some manual hacks:
if ($uri == 'syncml:syncml') {
$uri = 'syncml:syncml1.0';
}
if ($uri == 'syncml:metinf') {
$uri = 'syncml:metinf1.0';
}
if ($uri == 'syncml:devinf') {
$uri = 'syncml:devinf1.0';
}
if (isset($this->_strDTDURI[$uri])) {
$dtd = &$this->_strDTDURI[$uri];
} else {
$dtd = null;
}
return $dtd;
}
/**
*/
function registerDTD($publicIdentifier, $uri, &$dtd)
{
$dtd->setDPI($publicIdentifier);
$publicIdentifier = strtolower($publicIdentifier);
$this->_strDTD[$publicIdentifier] = $dtd;
$this->_strDTDURI[strtolower($uri)] = $dtd;
}
}

View File

@ -1,688 +0,0 @@
<?php
include_once 'XML/WBXML.php';
include_once 'XML/WBXML/DTDManager.php';
include_once 'XML/WBXML/ContentHandler.php';
/**
* From Binary XML Content Format Specification Version 1.3, 25 July 2001
* found at http://www.wapforum.org
*
* $Horde: framework/XML_WBXML/WBXML/Decoder.php,v 1.22.10.11 2008/01/02 11:31:02 jan Exp $
*
* Copyright 2003-2008 The Horde Project (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Anthony Mills <amills@pyramid6.com>
* @package XML_WBXML
*/
class XML_WBXML_Decoder extends XML_WBXML_ContentHandler {
/**
* Document Public Identifier type
* 1 mb_u_int32 well known type
* 2 string table
* from spec but converted into a string.
*
* Document Public Identifier
* Used with dpiType.
*/
var $_dpi;
/**
* String table as defined in 5.7
*/
var $_stringTable = array();
/**
* Content handler.
* Currently just outputs raw XML.
*/
var $_ch;
var $_tagDTD;
var $_prevAttributeDTD;
var $_attributeDTD;
/**
* State variables.
*/
var $_tagStack = array();
var $_isAttribute;
var $_isData = false;
var $_error = false;
/**
* The DTD Manager.
*
* @var XML_WBXML_DTDManager
*/
var $_dtdManager;
/**
* The string position.
*
* @var integer
*/
var $_strpos;
/**
* Constructor.
*/
function XML_WBXML_Decoder()
{
$this->_dtdManager = new XML_WBXML_DTDManager();
}
/**
* Sets the contentHandler that will receive the output of the
* decoding.
*
* @param XML_WBXML_ContentHandler $ch The contentHandler
*/
function setContentHandler(&$ch)
{
$this->_ch = &$ch;
}
/**
* Return one byte from the input stream.
*
* @param string $input The WBXML input string.
*/
function getByte($input)
{
$value = $input{$this->_strpos++};
$value = ord($value);
return $value;
}
/**
* Takes a WBXML input document and returns decoded XML.
* However the preferred and more effecient method is to
* use decode() rather than decodeToString() and have an
* appropriate contentHandler deal with the decoded data.
*
* @param string $wbxml The WBXML document to decode.
*
* @return string The decoded XML document.
*/
function decodeToString($wbxml)
{
$this->_ch = new XML_WBXML_ContentHandler();
$r = $this->decode($wbxml);
if (is_a($r, 'PEAR_Error')) {
return $r;
}
return $this->_ch->getOutput();
}
/**
* Takes a WBXML input document and decodes it.
* Decoding result is directly passed to the contentHandler.
* A contenthandler must be set using setContentHandler
* prior to invocation of this method
*
* @param string $wbxml The WBXML document to decode.
*
* @return mixed True on success or PEAR_Error.
*/
function decode($wbxml)
{
$this->_error = false; // reset state
$this->_strpos = 0;
if (empty($this->_ch)) {
return $this->raiseError('No Contenthandler defined.');
}
// Get Version Number from Section 5.4
// version = u_int8
// currently 0, 1 or 2
$this->_wbxmlVersion = $this->getVersionNumber($wbxml);
#Horde::logMessage("WBXML[" . $this->_strpos . "] version " . $this->_wbxmlVersion, __FILE__, __LINE__, PEAR_LOG_DEBUG);
// Get Document Public Idetifier from Section 5.5
// publicid = mb_u_int32 | (zero index)
// zero = u_int8
// Containing the value zero (0)
// The actual DPI is determined after the String Table is read.
$dpiStruct = $this->getDocumentPublicIdentifier($wbxml);
// Get Charset from 5.6
// charset = mb_u_int32
$this->_charset = $this->getCharset($wbxml);
#Horde::logMessage("WBXML[" . $this->_strpos . "] charset " . $this->_charset, __FILE__, __LINE__, PEAR_LOG_DEBUG);
// Get String Table from 5.7
// strb1 = length *byte
$this->retrieveStringTable($wbxml);
// Get Document Public Idetifier from Section 5.5.
$this->_dpi = $this->getDocumentPublicIdentifierImpl($dpiStruct['dpiType'],
$dpiStruct['dpiNumber']);
#$this->_stringTable);
// Now the real fun begins.
// From Sections 5.2 and 5.8
// Default content handler.
$this->_dtdManager = new XML_WBXML_DTDManager();
// Get the starting DTD.
$this->_tagDTD = $this->_dtdManager->getInstance($this->_dpi);
if (!$this->_tagDTD) {
return $this->raiseError('No DTD found for '
. $this->_dpi . '/'
. $dpiStruct['dpiNumber']);
}
$this->_attributeDTD = $this->_tagDTD;
while (empty($this->_error) && $this->_strpos < strlen($wbxml)) {
$this->_decode($wbxml);
}
if (!empty($this->_error)) {
return $this->_error;
}
return true;
}
function getVersionNumber($input)
{
return $this->getByte($input);
}
function getDocumentPublicIdentifier($input)
{
$i = XML_WBXML::MBUInt32ToInt($input, $this->_strpos);
if ($i == 0) {
return array('dpiType' => 2,
'dpiNumber' => $this->getByte($input));
} else {
return array('dpiType' => 1,
'dpiNumber' => $i);
}
}
function getDocumentPublicIdentifierImpl($dpiType, $dpiNumber)
{
if ($dpiType == 1) {
return XML_WBXML::getDPIString($dpiNumber);
} else {
#Horde::logMessage("WBXML string table $dpiNumber:\n" . print_r($this->_stringTable, true), __FILE__, __LINE__, PEAR_LOG_DEBUG);
return $this->getStringTableEntry($dpiNumber);
}
}
/**
* Returns the character encoding. Only default character
* encodings from J2SE are supported. From
* http://www.iana.org/assignments/character-sets and
* http://java.sun.com/j2se/1.4.2/docs/api/java/nio/charset/Charset.html
*/
function getCharset($input)
{
$cs = XML_WBXML::MBUInt32ToInt($input, $this->_strpos);
return XML_WBXML::getCharsetString($cs);
}
/**
* Retrieves the string table.
* The string table consists of an mb_u_int32 length
* and then length bytes forming the table.
* References to the string table refer to the
* starting position of the (null terminated)
* string in this table.
*/
function retrieveStringTable($input)
{
$size = XML_WBXML::MBUInt32ToInt($input, $this->_strpos);
$this->_stringTable = $this->_substr($input, $this->_strpos, $size);
$this->_strpos += $size;
// print "stringtable($size):" . $this->_stringTable ."\n";
}
function getStringTableEntry($index)
{
if ($index >= strlen($this->_stringTable)) {
$this->_error =
$this->raiseError('Invalid offset ' . $index
. ' value encountered around position '
. $this->_strpos
. '. Broken wbxml?');
return '';
}
// copy of method termstr but without modification of this->_strpos
$str = '#'; // must start with nonempty string to allow array access
$i = 0;
$ch = $this->_stringTable[$index++];
if (ord($ch) == 0) {
return ''; // don't return '#'
}
while (ord($ch) != 0) {
$str[$i++] = $ch;
if ($index >= strlen($this->_stringTable)) {
break;
}
$ch = $this->_stringTable[$index++];
}
// print "string table entry: $str\n";
return $str;
}
function _decode($input)
{
$token = $this->getByte($input);
$str = '';
// print "position: " . $this->_strpos . " token: " . $token . " str10: " . substr($input, $this->_strpos, 10) . "\n"; // @todo: remove debug output
switch ($token) {
case XML_WBXML_GLOBAL_TOKEN_STR_I:
// Section 5.8.4.1
$str = $this->termstr($input);
$this->_ch->characters($str);
// print "str:$str\n"; // @TODO Remove debug code
break;
case XML_WBXML_GLOBAL_TOKEN_STR_T:
// Section 5.8.4.1
$x = XML_WBXML::MBUInt32ToInt($input, $this->_strpos);
$str = $this->getStringTableEntry($x);
$this->_ch->characters($str);
break;
case XML_WBXML_GLOBAL_TOKEN_EXT_I_0:
case XML_WBXML_GLOBAL_TOKEN_EXT_I_1:
case XML_WBXML_GLOBAL_TOKEN_EXT_I_2:
// Section 5.8.4.2
$str = $this->termstr($input);
$this->_ch->characters($str);
break;
case XML_WBXML_GLOBAL_TOKEN_EXT_T_0:
case XML_WBXML_GLOBAL_TOKEN_EXT_T_1:
case XML_WBXML_GLOBAL_TOKEN_EXT_T_2:
// Section 5.8.4.2
$str = $this->getStringTableEnty(XML_WBXML::MBUInt32ToInt($input, $this->_strpos));
$this->_ch->characters($str);
break;
case XML_WBXML_GLOBAL_TOKEN_EXT_0:
case XML_WBXML_GLOBAL_TOKEN_EXT_1:
case XML_WBXML_GLOBAL_TOKEN_EXT_2:
// Section 5.8.4.2
$extension = $this->getByte($input);
$this->_ch->characters($extension);
break;
case XML_WBXML_GLOBAL_TOKEN_ENTITY:
// Section 5.8.4.3
// UCS-4 chracter encoding?
$entity = $this->entity(XML_WBXML::MBUInt32ToInt($input, $this->_strpos));
$this->_ch->characters('&#' . $entity . ';');
break;
case XML_WBXML_GLOBAL_TOKEN_PI:
// Section 5.8.4.4
// throw new IOException
// die("WBXML global token processing instruction(PI, " + token + ") is unsupported!\n");
break;
case XML_WBXML_GLOBAL_TOKEN_LITERAL:
// Section 5.8.4.5
$str = $this->getStringTableEntry(XML_WBXML::MBUInt32ToInt($input, $this->_strpos));
$this->parseTag($input, $str, false, false);
break;
case XML_WBXML_GLOBAL_TOKEN_LITERAL_A:
// Section 5.8.4.5
$str = $this->getStringTableEntry(XML_WBXML::MBUInt32ToInt($input, $this->_strpos));
$this->parseTag($input, $str, true, false);
break;
case XML_WBXML_GLOBAL_TOKEN_LITERAL_AC:
// Section 5.8.4.5
$str = $this->getStringTableEntry(XML_WBXML::MBUInt32ToInt($input, $this->_strpos));
$this->parseTag($input, $string, true, true);
break;
case XML_WBXML_GLOBAL_TOKEN_LITERAL_C:
// Section 5.8.4.5
$str = $this->getStringTableEntry(XML_WBXML::MBUInt32ToInt($input, $this->_strpos));
$this->parseTag($input, $str, false, true);
break;
case XML_WBXML_GLOBAL_TOKEN_OPAQUE:
// Section 5.8.4.6
$size = XML_WBXML::MBUInt32ToInt($input, $this->_strpos);
if ($size > 0) {
#Horde::logMessage("WBXML opaque document size=$size, next=" . ord($input{$this->_strpos}), __FILE__, __LINE__, PEAR_LOG_DEBUG);
$b = $this->_substr($input, $this->_strpos, $size);
// print "opaque of size $size: ($b)\n"; // @todo remove debug
$this->_strpos += $size;
// opaque data inside a <data> element may or may not be
// a nested wbxml document (for example devinf data).
// We find out by checking the first byte of the data: if it's
// 1, 2 or 3 we expect it to be the version number of a wbxml
// document and thus start a new wbxml decoder instance on it.
if ($this->_isData && ord($b) < 10) {
#Horde::logMessage("WBXML opaque document size=$size, \$b[0]=" . ord($b), __FILE__, __LINE__, PEAR_LOG_DEBUG);
$decoder = new XML_WBXML_Decoder(true);
$decoder->setContentHandler($this->_ch);
$s = $decoder->decode($b);
// /* // @todo: FIXME currently we can't decode Nokia
// DevInf data. So ignore error for the time beeing.
if (is_a($s, 'PEAR_Error')) {
$this->_error = $s;
return;
}
// */
// $this->_ch->characters($s);
} else {
/* normal opaque behaviour: just copy the raw data: */
// print "opaque handled as string=$b\n"; // @todo remove debug
$this->_ch->characters($b);
}
}
// old approach to deal with opaque data inside ContentHandler:
// FIXME Opaque is used by SYNCML. Opaque data that depends on the context
// if (contentHandler instanceof OpaqueContentHandler) {
// ((OpaqueContentHandler)contentHandler).opaque(b);
// } else {
// String str = new String(b, 0, size, charset);
// char[] chars = str.toCharArray();
// contentHandler.characters(chars, 0, chars.length);
// }
break;
case XML_WBXML_GLOBAL_TOKEN_END:
// Section 5.8.4.7.1
$str = $this->endTag();
break;
case XML_WBXML_GLOBAL_TOKEN_SWITCH_PAGE:
// Section 5.8.4.7.2
$codePage = $this->getByte($input);
// print "switch to codepage $codePage\n"; // @todo: remove debug code
$this->switchElementCodePage($codePage);
break;
default:
// Section 5.8.2
// Section 5.8.3
$hasAttributes = (($token & 0x80) != 0);
$hasContent = (($token & 0x40) != 0);
$realToken = $token & 0x3F;
$str = $this->getTag($realToken);
// print "element:$str\n"; // @TODO Remove debug code
$this->parseTag($input, $str, $hasAttributes, $hasContent);
if ($realToken == 0x0f) {
// store if we're inside a Data tag. This may contain
// an additional enclosed wbxml document on which we have
// to run a seperate encoder
$this->_isData = true;
} else {
$this->_isData = false;
}
break;
}
}
function parseTag($input, $tag, $hasAttributes, $hasContent)
{
$attrs = array();
if ($hasAttributes) {
$attrs = $this->getAttributes($input);
}
$this->_ch->startElement($this->getCurrentURI(), $tag, $attrs);
if ($hasContent) {
// FIXME I forgot what does this does. Not sure if this is
// right?
$this->_tagStack[] = $tag;
} else {
$this->_ch->endElement($this->getCurrentURI(), $tag);
}
}
function endTag()
{
if (count($this->_tagStack)) {
$tag = array_pop($this->_tagStack);
} else {
$tag = 'Unknown';
}
$this->_ch->endElement($this->getCurrentURI(), $tag);
return $tag;
}
function getAttributes($input)
{
$this->startGetAttributes();
$hasMoreAttributes = true;
$attrs = array();
$attr = null;
$value = null;
$token = null;
while ($hasMoreAttributes) {
$token = $this->getByte($input);
switch ($token) {
// Attribute specified.
case XML_WBXML_GLOBAL_TOKEN_LITERAL:
// Section 5.8.4.5
if (isset($attr)) {
$attrs[] = array('attribute' => $attr,
'value' => $value);
}
$attr = $this->getStringTableEntry(XML_WBXML::MBUInt32ToInt($input, $this->_strpos));
break;
// Value specified.
case XML_WBXML_GLOBAL_TOKEN_EXT_I_0:
case XML_WBXML_GLOBAL_TOKEN_EXT_I_1:
case XML_WBXML_GLOBAL_TOKEN_EXT_I_2:
// Section 5.8.4.2
$value .= $this->termstr($input);
break;
case XML_WBXML_GLOBAL_TOKEN_EXT_T_0:
case XML_WBXML_GLOBAL_TOKEN_EXT_T_1:
case XML_WBXML_GLOBAL_TOKEN_EXT_T_2:
// Section 5.8.4.2
$value .= $this->getStringTableEntry(XML_WBXML::MBUInt32ToInt($input, $this->_strpos));
break;
case XML_WBXML_GLOBAL_TOKEN_EXT_0:
case XML_WBXML_GLOBAL_TOKEN_EXT_1:
case XML_WBXML_GLOBAL_TOKEN_EXT_2:
// Section 5.8.4.2
$value .= $input[$this->_strpos++];
break;
case XML_WBXML_GLOBAL_TOKEN_ENTITY:
// Section 5.8.4.3
$value .= $this->entity(XML_WBXML::MBUInt32ToInt($input, $this->_strpos));
break;
case XML_WBXML_GLOBAL_TOKEN_STR_I:
// Section 5.8.4.1
$value .= $this->termstr($input);
break;
case XML_WBXML_GLOBAL_TOKEN_STR_T:
// Section 5.8.4.1
$value .= $this->getStringTableEntry(XML_WBXML::MBUInt32ToInt($input, $this->_strpos));
break;
case XML_WBXML_GLOBAL_TOKEN_OPAQUE:
// Section 5.8.4.6
$size = XML_WBXML::MBUInt32ToInt($input, $this->_strpos);
$b = $this->_substr($input, $this->_strpos, $this->_strpos + $size);
$this->_strpos += $size;
$value .= $b;
break;
case XML_WBXML_GLOBAL_TOKEN_END:
// Section 5.8.4.7.1
$hasMoreAttributes = false;
if (isset($attr)) {
$attrs[] = array('attribute' => $attr,
'value' => $value);
}
break;
case XML_WBXML_GLOBAL_TOKEN_SWITCH_PAGE:
// Section 5.8.4.7.2
$codePage = $this->getByte($input);
if (!$this->_prevAttributeDTD) {
$this->_prevAttributeDTD = $this->_attributeDTD;
}
$this->switchAttributeCodePage($codePage);
break;
default:
if ($token > 128) {
if (isset($attr)) {
$attrs[] = array('attribute' => $attr,
'value' => $value);
}
$attr = $this->_attributeDTD->toAttribute($token);
} else {
// Value.
$value .= $this->_attributeDTD->toAttribute($token);
}
break;
}
}
if (!$this->_prevAttributeDTD) {
$this->_attributeDTD = $this->_prevAttributeDTD;
$this->_prevAttributeDTD = false;
}
$this->stopGetAttributes();
}
function startGetAttributes()
{
$this->_isAttribute = true;
}
function stopGetAttributes()
{
$this->_isAttribute = false;
}
function getCurrentURI()
{
if ($this->_isAttribute) {
return $this->_tagDTD->getURI();
} else {
return $this->_attributeDTD->getURI();
}
}
function writeString($str)
{
$this->_ch->characters($str);
}
function getTag($tag)
{
// Should know which state it is in.
return $this->_tagDTD->toTagStr($tag);
}
function getAttribute($attribute)
{
// Should know which state it is in.
$this->_attributeDTD->toAttributeInt($attribute);
}
function switchElementCodePage($codePage)
{
$this->_tagDTD = &$this->_dtdManager->getInstance($this->_tagDTD->toCodePageStr($codePage));
$this->switchAttributeCodePage($codePage);
}
function switchAttributeCodePage($codePage)
{
$this->_attributeDTD = &$this->_dtdManager->getInstance($this->_attributeDTD->toCodePageStr($codePage));
}
/**
* Return the hex version of the base 10 $entity.
*/
function entity($entity)
{
return dechex($entity);
}
/**
* Reads a null terminated string.
*/
function termstr($input)
{
$str = '#'; // must start with nonempty string to allow array access
$i = 0;
$ch = $input[$this->_strpos++];
if (ord($ch) == 0) {
return ''; // don't return '#'
}
while (ord($ch) != 0) {
$str[$i++] = $ch;
$ch = $input[$this->_strpos++];
}
return $str;
}
/**
* imitate substr()
* This circumvents a bug in the mbstring overloading in some distributions,
* where the mbstring.func_overload=0 INI-setting does not work, if mod_php
* has another value for that setting in another directory-context
*/
function _substr($input,$start,$size)
{
$ret = "";
if (!$input) return $ret;
for ($i = $start; $i < $start+$size; $i++) {
$ret .= $input[$i];
}
return $ret;
}
}

View File

@ -1,425 +0,0 @@
<?php
include_once 'XML/WBXML.php';
include_once 'XML/WBXML/ContentHandler.php';
include_once 'XML/WBXML/DTDManager.php';
include_once 'Horde/String.php';
/**
* From Binary XML Content Format Specification Version 1.3, 25 July 2001
* found at http://www.wapforum.org
*
* $Horde: framework/XML_WBXML/WBXML/Encoder.php,v 1.25.10.17 2008/08/26 15:41:21 jan Exp $
*
* Copyright 2003-2008 The Horde Project (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Anthony Mills <amills@pyramid6.com>
* @package XML_WBXML
*/
class XML_WBXML_Encoder extends XML_WBXML_ContentHandler {
var $_strings = array();
var $_stringTable;
var $_hasWrittenHeader = false;
var $_dtd;
var $_output = '';
var $_uris = array();
var $_uriNums = array();
var $_currentURI;
var $_subParser = null;
var $_subParserStack = 0;
/**
* The XML parser.
*
* @var resource
*/
var $_parser;
/**
* The DTD Manager.
*
* @var XML_WBXML_DTDManager
*/
var $_dtdManager;
/**
* Constructor.
*/
function XML_WBXML_Encoder()
{
$this->_dtdManager = new XML_WBXML_DTDManager();
$this->_stringTable = new XML_WBXML_HashTable();
}
/**
* Take the input $xml and turn it into WBXML. This is _not_ the
* intended way of using this class. It is derived from
* Contenthandler and one should use it as a ContentHandler and
* produce the XML-structure with startElement(), endElement(),
* and characters().
*/
function encode($xml)
{
// Create the XML parser and set method references.
$this->_parser = xml_parser_create_ns($this->_charset);
xml_set_object($this->_parser, $this);
xml_parser_set_option($this->_parser, XML_OPTION_CASE_FOLDING, false);
xml_set_element_handler($this->_parser, '_startElement', '_endElement');
xml_set_character_data_handler($this->_parser, '_characters');
xml_set_processing_instruction_handler($this->_parser, '');
xml_set_external_entity_ref_handler($this->_parser, '');
if (!xml_parse($this->_parser, $xml)) {
return $this->raiseError(sprintf('XML error: %s at line %d',
xml_error_string(xml_get_error_code($this->_parser)),
xml_get_current_line_number($this->_parser)));
}
xml_parser_free($this->_parser);
return $this->_output;
}
/**
* This will write the correct headers.
*/
function writeHeader($uri)
{
$this->_dtd = &$this->_dtdManager->getInstanceURI($uri);
if (!$this->_dtd) {
// TODO: proper error handling
die('Unable to find dtd for ' . $uri);
}
$dpiString = $this->_dtd->getDPI();
// Set Version Number from Section 5.4
// version = u_int8
// currently 1, 2 or 3
$this->writeVersionNumber($this->_wbxmlVersion);
// Set Document Public Idetifier from Section 5.5
// publicid = mb_u_int32 | ( zero index )
// zero = u_int8
// containing the value zero (0)
// The actual DPI is determined after the String Table is read.
$this->writeDocumentPublicIdentifier($dpiString, $this->_strings);
// Set Charset from 5.6
// charset = mb_u_int32
$this->writeCharset($this->_charset);
// Set String Table from 5.7
// strb1 = length *byte
$this->writeStringTable($this->_strings, $this->_charset, $this->_stringTable);
$this->_currentURI = $uri;
$this->_hasWrittenHeader = true;
}
function writeVersionNumber($version)
{
$this->_output .= chr($version);
}
function writeDocumentPublicIdentifier($dpiString, &$strings)
{
$i = 0;
// The OMA test suite doesn't like DPI as integer code.
// So don't try lookup and always send full DPI string.
// $i = XML_WBXML::getDPIInt($dpiString);
if ($i == 0) {
$strings[0] = $dpiString;
$this->_output .= chr(0);
$this->_output .= chr(0);
} else {
XML_WBXML::intToMBUInt32($this->_output, $i);
}
}
function writeCharset($charset)
{
$cs = XML_WBXML::getCharsetInt($charset);
if ($cs == 0) {
return $this->raiseError('Unsupported Charset: ' . $charset);
} else {
XML_WBXML::intToMBUInt32($this->_output, $cs);
}
}
function writeStringTable($strings, $charset, $stringTable)
{
$stringBytes = array();
$count = 0;
foreach ($strings as $str) {
$bytes = $this->_getBytes($str, $charset);
$stringBytes = array_merge($stringBytes, $bytes);
$nullLength = $this->_addNullByte($bytes);
$this->_stringTable->set($str, $count);
$count += count($bytes) + $nullLength;
}
XML_WBXML::intToMBUInt32($this->_output, count($stringBytes));
$this->_output .= implode('', $stringBytes);
}
function writeString($str, $cs)
{
$bytes = $this->_getBytes($str, $cs);
$this->_output .= implode('', $bytes);
$this->writeNull($cs);
}
function writeNull($charset)
{
$this->_output .= chr(0);
return 1;
}
function _addNullByte(&$bytes)
{
$bytes[] = chr(0);
return 1;
}
function _getBytes($string, $cs)
{
$string = String::convertCharset($string, $cs, 'utf-8');
$nbytes = strlen($string);
$bytes = array();
for ($i = 0; $i < $nbytes; $i++) {
$bytes[] = $string{$i};
}
return $bytes;
}
function _splitURI($tag)
{
$parts = explode(':', $tag);
$name = array_pop($parts);
$uri = implode(':', $parts);
return array($uri, $name);
}
function startElement($uri, $name, $attributes = array())
{
#Horde::logMessage("WBXML Encoder $uri, " . ($this->_hasWrittenHeader ? 'true' : 'false'), __FILE__, __LINE__, PEAR_LOG_DEBUG);
if ($this->_subParser == null) {
if (!$this->_hasWrittenHeader) {
$this->writeHeader($uri);
}
if ($this->_currentURI != $uri) {
$this->changecodepage($uri);
}
if ($this->_subParser == null) {
$this->writeTag($name, $attributes, true, $this->_charset);
} else {
$this->_subParser->startElement($uri, $name, $attributes);
}
} else {
$this->_subParserStack++;
$this->_subParser->startElement($uri, $name, $attributes);
}
}
function _startElement($parser, $tag, $attributes)
{
list($uri, $name) = $this->_splitURI($tag);
$this->startElement($uri, $name, $attributes);
}
function opaque($o)
{
if ($this->_subParser == null) {
$this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_OPAQUE);
XML_WBXML::intToMBUInt32($this->_output, strlen($o));
$this->_output .= $o;
}
}
function characters($chars)
{
$chars = trim($chars);
if (strlen($chars)) {
/* We definitely don't want any whitespace. */
if ($this->_subParser == null) {
$i = $this->_stringTable->get($chars);
if ($i != null) {
$this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_STR_T);
XML_WBXML::intToMBUInt32($this->_output, $i);
} else {
$this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_STR_I);
$this->writeString($chars, $this->_charset);
}
} else {
$this->_subParser->characters($chars);
}
}
}
function _characters($parser, $chars)
{
$this->characters($chars);
}
function writeTag($name, $attrs, $hasContent, $cs)
{
if ($attrs != null && !count($attrs)) {
$attrs = null;
}
$t = $this->_dtd->toTagInt($name);
if ($t == -1) {
$i = $this->_stringTable->get($name);
if ($i == null) {
return $this->raiseError($name . ' is not found in String Table or DTD');
} else {
if ($attrs == null && !$hasContent) {
$this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_LITERAL);
} elseif ($attrs == null && $hasContent) {
$this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_LITERAL_A);
} elseif ($attrs != null && $hasContent) {
$this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_LITERAL_C);
} elseif ($attrs != null && !$hasContent) {
$this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_LITERAL_AC);
}
XML_WBXML::intToMBUInt32($this->_output, $i);
}
} else {
if ($attrs == null && !$hasContent) {
$this->_output .= chr($t);
} elseif ($attrs == null && $hasContent) {
$this->_output .= chr($t | 64);
} elseif ($attrs != null && $hasContent) {
$this->_output .= chr($t | 128);
} elseif ($attrs != null && !$hasContent) {
$this->_output .= chr($t | 192);
}
}
if ($attrs != null && is_array($attrs) && count($attrs) > 0) {
$this->writeAttributes($attrs, $cs);
}
}
function writeAttributes($attrs, $cs)
{
foreach ($attrs as $name => $value) {
$this->writeAttribute($name, $value, $cs);
}
$this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_END);
}
function writeAttribute($name, $value, $cs)
{
$a = $this->_dtd->toAttribute($name);
if ($a == -1) {
$i = $this->_stringTable->get($name);
if ($i == null) {
return $this->raiseError($name . ' is not found in String Table or DTD');
} else {
$this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_LITERAL);
XML_WBXML::intToMBUInt32($this->_output, $i);
}
} else {
$this->_output .= $a;
}
$i = $this->_stringTable->get($name);
if ($i != null) {
$this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_STR_T);
XML_WBXML::intToMBUInt32($this->_output, $i);
} else {
$this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_STR_I);
$this->writeString($value, $cs);
}
}
function endElement($uri, $name)
{
if ($this->_subParser == null) {
$this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_END);
} else {
$this->_subParser->endElement($uri, $name);
$this->_subParserStack--;
if ($this->_subParserStack == 0) {
$this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_OPAQUE);
XML_WBXML::intToMBUInt32($this->_output,
strlen($this->_subParser->getOutput()));
$this->_output .= $this->_subParser->getOutput();
$this->_subParser = null;
}
}
}
function _endElement($parser, $tag)
{
list($uri, $name) = $this->_splitURI($tag);
$this->endElement($uri, $name);
}
function changecodepage($uri)
{
if ($this->_dtd->getVersion() == 2 && !preg_match('/1\.2$/', $uri)) {
$uri .= '1.2';
}
if ($this->_dtd->getVersion() == 1 && !preg_match('/1\.1$/', $uri)) {
$uri .= '1.1';
}
if ($this->_dtd->getVersion() == 0 && !preg_match('/1\.0$/', $uri)) {
$uri .= '1.0';
}
$cp = $this->_dtd->toCodePageURI($uri);
if (strlen($cp)) {
$this->_dtd = &$this->_dtdManager->getInstanceURI($uri);
$this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_SWITCH_PAGE);
$this->_output .= chr($cp);
$this->_currentURI = $uri;
} else {
$this->_subParser = new XML_WBXML_Encoder(true);
$this->_subParserStack = 1;
}
}
/**
* Getter for property output.
*/
function getOutput()
{
return $this->_output;
}
function getOutputSize()
{
return strlen($this->_output);
}
}

View File

@ -1,44 +0,0 @@
<?php
/* CONFIG START. DO NOT CHANGE ANYTHING IN OR AFTER THIS LINE. */
// $Horde: horde/config/conf.xml,v 1.79 2005/02/16 15:42:35 jan Exp $
$conf['debug_level'] = E_ERROR | E_WARNING | E_PARSE;
$conf['max_exec_time'] = 0;
$conf['use_ssl'] = 2;
$conf['server']['name'] = $_SERVER['SERVER_NAME'];
$conf['server']['port'] = $_SERVER['SERVER_PORT'];
$conf['compress_pages'] = true;
$conf['umask'] = 077;
$conf['session']['name'] = 'Horde';
$conf['session']['cache_limiter'] = 'nocache';
$conf['session']['timeout'] = 0;
$conf['cookie']['domain'] = $_SERVER['SERVER_NAME'];
$conf['cookie']['path'] = '/horde';
$conf['auth']['admins'] = array('Administrator');
$conf['auth']['checkip'] = true;
$conf['auth']['params']['username'] = 'Administrator';
$conf['auth']['params']['requestuser'] = false;
$conf['auth']['driver'] = 'auto';
$conf['log']['priority'] = PEAR_LOG_DEBUG;
$conf['log']['ident'] = 'EGWSYNC';
$conf['log']['params'] = array();
$conf['log']['name'] = '/tmp/egroupware_syncml-1.6.log';
$conf['log']['params']['append'] = true;
$conf['log']['type'] = 'error_log';
$conf['log']['enabled'] = false;
$conf['log_accesskeys'] = false;
$conf['prefs']['driver'] = 'none';
$conf['datatree']['params']['driverconfig'] = 'horde';
$conf['datatree']['driver'] = 'sql';
$conf['group']['driver'] = 'datatree';
#$conf['cache']['default_lifetime'] = 1800;
#$conf['cache']['params']['dir'] = Horde::getTempDir();
#$conf['cache']['driver'] = 'file';
$conf['token']['driver'] = 'none';
$conf['sessionhandler']['type'] = 'none';
$conf['problems']['email'] = 'webmaster@example.com';
$conf['hooks']['username'] = false;
$conf['hooks']['preauthenticate'] = false;
$conf['hooks']['postauthenticate'] = false;
$conf['hooks']['authldap'] = false;
$conf['kolab']['enabled'] = false;
/* CONFIG END. DO NOT CHANGE ANYTHING IN OR BEFORE THIS LINE. */

View File

@ -1,594 +0,0 @@
<?php
/**
* NLS (National Language Support) configuration file.
*
* $Horde: horde/config/nls.php.dist,v 1.59 2004/09/01 09:59:24 jan Exp $
*/
/**
** Defaults
**/
/* The language to fall back on if we cannot determine one any other
way (user choice or preferences). If empty, we will try to negotiate
with the browser using HTTP_ACCEPT_LANGUAGE. */
$nls['defaults']['language'] = '';
/* The charset to fall back on if we cannot determine one any other
way (chosen language, HTTP_ACCEPT_CHARSETS). */
$nls['defaults']['charset'] = 'ISO-8859-1';
/**
** Language
**/
$nls['languages']['ar_OM'] = 'Arabic (Oman) (&#x0627;&#x0644;&#x0639;&#x0631;&#x0628;&#x064a;&#x0629;)';
$nls['languages']['ar_SY'] = 'Arabic (Syria) (&#x0627;&#x0644;&#x0639;&#x0631;&#x0628;&#x064a;&#x0629;)';
$nls['languages']['id_ID'] = 'Bahasa Indonesia';
$nls['languages']['bg_BG'] = 'Bulgarian (&#x0411;&#x044a;&#x043b;&#x0433;&#x0430;&#x0440;&#x0441;&#x043a;&#x0438;)';
$nls['languages']['ca_ES'] = 'Catal&agrave;';
$nls['languages']['zh_CN'] = 'Chinese (Simplified) (&#x7b80;&#x4f53;&#x4e2d;&#x6587;)';
$nls['languages']['zh_TW'] = 'Chinese (Traditional) (&#x6b63;&#x9ad4;&#x4e2d;&#x6587;)';
$nls['languages']['cs_CZ'] = 'Czech (&#x010c;esky)';
$nls['languages']['da_DK'] = 'Dansk';
$nls['languages']['de_DE'] = 'Deutsch';
$nls['languages']['en_US'] = 'English (American)';
$nls['languages']['en_GB'] = 'English (British)';
$nls['languages']['en_CA'] = 'English (Canadian)';
$nls['languages']['es_ES'] = 'Espa&ntilde;ol';
$nls['languages']['et_EE'] = 'Eesti';
$nls['languages']['fr_FR'] = 'Fran&ccedil;ais';
$nls['languages']['gl_ES'] = 'Galego';
$nls['languages']['el_GR'] = 'Greek (&#x0395;&#x03bb;&#x03bb;&#x03b7;&#x03bd;&#x03b9;&#x03ba;&#x03ac;)';
$nls['languages']['is_IS'] = '&Iacute;slenska';
$nls['languages']['it_IT'] = 'Italiano';
$nls['languages']['ja_JP'] = 'Japanese (&#x65e5;&#x672c;&#x8a9e;)';
$nls['languages']['ko_KR'] = 'Korean (&#xd55c;&#xad6d;&#xc5b4;)';
$nls['languages']['lv_LV'] = 'Latvie&#x0161;u';
$nls['languages']['lt_LT'] = 'Lietuvi&#x0173;';
$nls['languages']['mk_MK'] = 'Macedonian (&#x041c;&#x0430;&#x043a;&#x0435;&#x0434;&#x043e;&#x043d;&#x0441;&#x043a;&#x0438;)';
$nls['languages']['hu_HU'] = 'Magyar';
$nls['languages']['nl_NL'] = 'Nederlands';
$nls['languages']['nb_NO'] = 'Norsk bokm&aring;l';
$nls['languages']['nn_NO'] = 'Norsk nynorsk';
$nls['languages']['fa_IR'] = 'Persian (Western) (&#1601;&#1575;&#1585;&#1587;&#1609;)';
$nls['languages']['pl_PL'] = 'Polski';
$nls['languages']['pt_PT'] = 'Portugu&ecirc;s';
$nls['languages']['pt_BR'] = 'Portugu&ecirc;s Brasileiro';
$nls['languages']['ro_RO'] = 'Rom&acirc;n&auml;';
$nls['languages']['ru_RU'] = 'Russian (&#x0420;&#x0443;&#x0441;&#x0441;&#x043a;&#x0438;&#x0439;)';
$nls['languages']['sk_SK'] = 'Slovak (Sloven&#x010d;ina)';
$nls['languages']['sl_SI'] = 'Slovenian (Sloven&#x0161;&#x010d;ina)';
$nls['languages']['fi_FI'] = 'Suomi';
$nls['languages']['sv_SE'] = 'Svenska';
$nls['languages']['th_TH'] = 'Thai (&#x0e44;&#x0e17;&#x0e22;)';
$nls['languages']['tr_TR'] = 'T&uuml;rk&ccedil;e';
$nls['languages']['uk_UA'] = 'Ukrainian (&#x0423;&#x043a;&#x0440;&#x0430;&#x0457;&#x043d;&#x0441;&#x044c;&#x043a;&#x0430;)';
/**
** Aliases for languages with different browser and gettext codes
**/
$nls['aliases']['ar'] = 'ar_SY';
$nls['aliases']['bg'] = 'bg_BG';
$nls['aliases']['ca'] = 'ca_ES';
$nls['aliases']['cs'] = 'cs_CZ';
$nls['aliases']['da'] = 'da_DK';
$nls['aliases']['de'] = 'de_DE';
$nls['aliases']['el'] = 'el_GR';
$nls['aliases']['en'] = 'en_US';
$nls['aliases']['es'] = 'es_ES';
$nls['aliases']['et'] = 'et_EE';
$nls['aliases']['fa'] = 'fa_IR';
$nls['aliases']['fi'] = 'fi_FI';
$nls['aliases']['fr'] = 'fr_FR';
$nls['aliases']['gl'] = 'gl_ES';
$nls['aliases']['hu'] = 'hu_HU';
$nls['aliases']['id'] = 'id_ID';
$nls['aliases']['is'] = 'is_IS';
$nls['aliases']['it'] = 'it_IT';
$nls['aliases']['ja'] = 'ja_JP';
$nls['aliases']['ko'] = 'ko_KR';
$nls['aliases']['lt'] = 'lt_LT';
$nls['aliases']['lv'] = 'lv_LV';
$nls['aliases']['mk'] = 'mk_MK';
$nls['aliases']['nl'] = 'nl_NL';
$nls['aliases']['nn'] = 'nn_NO';
$nls['aliases']['no'] = 'nb_NO';
$nls['aliases']['pl'] = 'pl_PL';
$nls['aliases']['pt'] = 'pt_PT';
$nls['aliases']['ro'] = 'ro_RO';
$nls['aliases']['ru'] = 'ru_RU';
$nls['aliases']['sk'] = 'sk_SK';
$nls['aliases']['sl'] = 'sl_SI';
$nls['aliases']['sv'] = 'sv_SE';
$nls['aliases']['th'] = 'th_TH';
$nls['aliases']['tr'] = 'tr_TR';
$nls['aliases']['uk'] = 'uk_UA';
/**
** Charsets
**/
$nls['charsets']['ar_OM'] = 'windows-1256';
$nls['charsets']['ar_SY'] = 'windows-1256';
$nls['charsets']['bg_BG'] = 'windows-1251';
$nls['charsets']['cs_CZ'] = 'ISO-8859-2';
$nls['charsets']['el_GR'] = 'ISO-8859-7';
$nls['charsets']['fa_IR'] = 'UTF-8';
$nls['charsets']['hu_HU'] = 'ISO-8859-2';
$nls['charsets']['ja_JP'] = 'SHIFT_JIS';
$nls['charsets']['ko_KR'] = 'EUC-KR';
$nls['charsets']['lt_LT'] = 'ISO-8859-13';
$nls['charsets']['lv_LV'] = 'windows-1257';
$nls['charsets']['mk_MK'] = 'ISO-8859-5';
$nls['charsets']['pl_PL'] = 'ISO-8859-2';
$nls['charsets']['ru_RU'] = 'windows-1251';
$nls['charsets']['ru_RU.KOI8-R'] = 'KOI8-R';
$nls['charsets']['sk_SK'] = 'ISO-8859-2';
$nls['charsets']['sl_SI'] = 'ISO-8859-2';
$nls['charsets']['th_TH'] = 'TIS-620';
$nls['charsets']['tr_TR'] = 'ISO-8859-9';
$nls['charsets']['uk_UA'] = 'KOI8-U';
$nls['charsets']['zh_CN'] = 'GB2312';
$nls['charsets']['zh_TW'] = 'BIG5';
/**
** Multibyte charsets
**/
$nls['multibyte']['BIG5'] = true;
$nls['multibyte']['EUC-KR'] = true;
$nls['multibyte']['GB2312'] = true;
$nls['multibyte']['SHIFT_JIS'] = true;
$nls['multibyte']['UTF-8'] = true;
/**
** Right-to-left languages
**/
$nls['rtl']['ar_OM'] = true;
$nls['rtl']['ar_SY'] = true;
$nls['rtl']['fa_IR'] = true;
/**
** Preferred charsets for email traffic if not the languages' default charsets.
**/
$nls['emails']['ja_JP'] = 'ISO-2022-JP';
/**
** Available charsets for outgoing email traffic.
**/
$nls['encodings']['windows-1256'] = _("Arabic (Windows-1256)");
$nls['encodings']['ARMSCII-8'] = _("Armenian (ARMSCII-8)");
$nls['encodings']['ISO-8859-13'] = _("Baltic (ISO-8859-13)");
$nls['encodings']['ISO-8859-14'] = _("Celtic (ISO-8859-14)");
$nls['encodings']['ISO-8859-2'] = _("Central European (ISO-8859-2)");
$nls['encodings']['GB2312'] = _("Chinese Simplified (GB2312)");
$nls['encodings']['BIG5'] = _("Chinese Traditional (Big5)");
$nls['encodings']['KOI8-R'] = _("Cyrillic (KOI8-R)");
$nls['encodings']['windows-1251'] = _("Cyrillic (Windows-1251)");
$nls['encodings']['KOI8-U'] = _("Cyrillic/Ukrainian (KOI8-U)");
$nls['encodings']['ISO-8859-7'] = _("Greek (ISO-8859-7)");
$nls['encodings']['ISO-8859-8-I'] = _("Hebrew (ISO-8859-8-I)");
$nls['encodings']['ISO-2022-JP'] = _("Japanese (ISO-2022-JP)");
$nls['encodings']['EUC-KR'] = _("Korean (EUC-KR)");
$nls['encodings']['ISO-8859-10'] = _("Nordic (ISO-8859-10)");
$nls['encodings']['ISO-8859-3'] = _("South European (ISO-8859-3)");
$nls['encodings']['TIS-620'] = _("Thai (TIS-620)");
$nls['encodings']['ISO-8859-9'] = _("Turkish (ISO-8859-9)");
$nls['encodings']['UTF-8'] = _("Unicode (UTF-8)");
$nls['encodings']['VISCII'] = _("Vietnamese (VISCII)");
$nls['encodings']['ISO-8859-1'] = _("Western (ISO-8859-1)");
$nls['encodings']['ISO-8859-15'] = _("Western (ISO-8859-15)");
asort($nls['encodings']);
/**
** Multi-language spelling support
**/
$nls['spelling']['cs_CZ'] = '-T latin2 -d czech';
$nls['spelling']['da_DK'] = '-d dansk';
$nls['spelling']['de_DE'] = '-T latin1 -d deutsch';
$nls['spelling']['el_GR'] = '-T latin1 -d ellinika';
$nls['spelling']['en_CA'] = '-d canadian';
$nls['spelling']['en_GB'] = '-d british';
$nls['spelling']['en_US'] = '-d american';
$nls['spelling']['es_ES'] = '-d espanol';
$nls['spelling']['fr_FR'] = '-d francais';
$nls['spelling']['it_IT'] = '-T latin1 -d italian';
$nls['spelling']['nl_NL'] = '-d nederlands';
$nls['spelling']['pl_PL'] = '-d polish';
$nls['spelling']['pt_BR'] = '-d br';
$nls['spelling']['pt_PT'] = '-T latin1 -d portuguese';
$nls['spelling']['ru_RU'] = '-d russian';
$nls['spelling']['sl_SI'] = '-d slovensko';
$nls['spelling']['sv_SE'] = '-d svenska';
$GLOBALS['nls'] = &$nls;
/**
** Timezones
**/
$tz['Africa/Abidjan'] = 'Africa/Abidjan';
$tz['Africa/Accra'] = 'Africa/Accra';
$tz['Africa/Addis_Ababa'] = 'Africa/Addis Ababa';
$tz['Africa/Algiers'] = 'Africa/Algiers';
$tz['Africa/Asmera'] = 'Africa/Asmera';
$tz['Africa/Bamako'] = 'Africa/Bamako';
$tz['Africa/Bangui'] = 'Africa/Bangui';
$tz['Africa/Banjul'] = 'Africa/Banjul';
$tz['Africa/Bissau'] = 'Africa/Bissau';
$tz['Africa/Blantyre'] = 'Africa/Blantyre';
$tz['Africa/Brazzaville'] = 'Africa/Brazzaville';
$tz['Africa/Bujumbura'] = 'Africa/Bujumbura';
$tz['Africa/Cairo'] = 'Africa/Cairo';
$tz['Africa/Casablanca'] = 'Africa/Casablanca';
$tz['Africa/Ceuta'] = 'Africa/Ceuta';
$tz['Africa/Conakry'] = 'Africa/Conakry';
$tz['Africa/Dakar'] = 'Africa/Dakar';
$tz['Africa/Dar_es_Salaam'] = 'Africa/Dar es Salaam';
$tz['Africa/Djibouti'] = 'Africa/Djibouti';
$tz['Africa/Douala'] = 'Africa/Douala';
$tz['Africa/El_Aaiun'] = 'Africa/El Aaiun';
$tz['Africa/Freetown'] = 'Africa/Freetown';
$tz['Africa/Gaborone'] = 'Africa/Gaborone';
$tz['Africa/Harare'] = 'Africa/Harare';
$tz['Africa/Johannesburg'] = 'Africa/Johannesburg';
$tz['Africa/Kampala'] = 'Africa/Kampala';
$tz['Africa/Khartoum'] = 'Africa/Khartoum';
$tz['Africa/Kigali'] = 'Africa/Kigali';
$tz['Africa/Kinshasa'] = 'Africa/Kinshasa';
$tz['Africa/Lagos'] = 'Africa/Lagos';
$tz['Africa/Libreville'] = 'Africa/Libreville';
$tz['Africa/Lome'] = 'Africa/Lome';
$tz['Africa/Luanda'] = 'Africa/Luanda';
$tz['Africa/Lubumbashi'] = 'Africa/Lubumbashi';
$tz['Africa/Lusaka'] = 'Africa/Lusaka';
$tz['Africa/Malabo'] = 'Africa/Malabo';
$tz['Africa/Maputo'] = 'Africa/Maputo';
$tz['Africa/Maseru'] = 'Africa/Maseru';
$tz['Africa/Mbabane'] = 'Africa/Mbabane';
$tz['Africa/Mogadishu'] = 'Africa/Mogadishu';
$tz['Africa/Monrovia'] = 'Africa/Monrovia';
$tz['Africa/Nairobi'] = 'Africa/Nairobi';
$tz['Africa/Ndjamena'] = 'Africa/Ndjamena';
$tz['Africa/Niamey'] = 'Africa/Niamey';
$tz['Africa/Nouakchott'] = 'Africa/Nouakchott';
$tz['Africa/Ouagadougou'] = 'Africa/Ouagadougou';
$tz['Africa/Porto-Novo'] = 'Africa/Porto-Novo';
$tz['Africa/Sao_Tome'] = 'Africa/Sao Tome';
$tz['Africa/Timbuktu'] = 'Africa/Timbuktu';
$tz['Africa/Tripoli'] = 'Africa/Tripoli';
$tz['Africa/Tunis'] = 'Africa/Tunis';
$tz['Africa/Windhoek'] = 'Africa/Windhoek';
$tz['America/Adak'] = 'America/Adak';
$tz['America/Anchorage'] = 'America/Anchorage';
$tz['America/Anguilla'] = 'America/Anguilla';
$tz['America/Antigua'] = 'America/Antigua';
$tz['America/Araguaina'] = 'America/Araguaina';
$tz['America/Aruba'] = 'America/Aruba';
$tz['America/Asuncion'] = 'America/Asuncion';
$tz['America/Barbados'] = 'America/Barbados';
$tz['America/Belem'] = 'America/Belem';
$tz['America/Belize'] = 'America/Belize';
$tz['America/Boa_Vista'] = 'America/Boa Vista';
$tz['America/Bogota'] = 'America/Bogota';
$tz['America/Boise'] = 'America/Boise';
$tz['America/Buenos_Aires'] = 'America/Buenos Aires';
$tz['America/Cambridge_Bay'] = 'America/Cambridge Bay';
$tz['America/Cancun'] = 'America/Cancun';
$tz['America/Caracas'] = 'America/Caracas';
$tz['America/Catamarca'] = 'America/Catamarca';
$tz['America/Cayenne'] = 'America/Cayenne';
$tz['America/Cayman'] = 'America/Cayman';
$tz['America/Chicago'] = 'America/Chicago';
$tz['America/Chihuahua'] = 'America/Chihuahua';
$tz['America/Cordoba'] = 'America/Cordoba';
$tz['America/Costa_Rica'] = 'America/Costa Rica';
$tz['America/Cuiaba'] = 'America/Cuiaba';
$tz['America/Curacao'] = 'America/Curacao';
$tz['America/Dawson'] = 'America/Dawson';
$tz['America/Dawson_Creek'] = 'America/Dawson Creek';
$tz['America/Denver'] = 'America/Denver';
$tz['America/Detroit'] = 'America/Detroit';
$tz['America/Dominica'] = 'America/Dominica';
$tz['America/Edmonton'] = 'America/Edmonton';
$tz['America/Eirunepe'] = 'America/Eirunepe';
$tz['America/El_Salvador'] = 'America/El Salvador';
$tz['America/Fortaleza'] = 'America/Fortaleza';
$tz['America/Glace_Bay'] = 'America/Glace Bay';
$tz['America/Godthab'] = 'America/Godthab';
$tz['America/Goose_Bay'] = 'America/Goose Bay';
$tz['America/Grand_Turk'] = 'America/Grand Turk';
$tz['America/Grenada'] = 'America/Grenada';
$tz['America/Guadeloupe'] = 'America/Guadeloupe';
$tz['America/Guatemala'] = 'America/Guatemala';
$tz['America/Guayaquil'] = 'America/Guayaquil';
$tz['America/Guyana'] = 'America/Guyana';
$tz['America/Halifax'] = 'America/Halifax';
$tz['America/Havana'] = 'America/Havana';
$tz['America/Hermosillo'] = 'America/Hermosillo';
$tz['America/Indiana/Knox'] = 'America/Indiana/Knox';
$tz['America/Indiana/Marengo'] = 'America/Indiana/Marengo';
$tz['America/Indiana/Vevay'] = 'America/Indiana/Vevay';
$tz['America/Indianapolis'] = 'America/Indianapolis';
$tz['America/Inuvik'] = 'America/Inuvik';
$tz['America/Iqaluit'] = 'America/Iqaluit';
$tz['America/Jamaica'] = 'America/Jamaica';
$tz['America/Jujuy'] = 'America/Jujuy';
$tz['America/Juneau'] = 'America/Juneau';
$tz['America/Kentucky/Monticello'] = 'America/Kentucky/Monticello';
$tz['America/La_Paz'] = 'America/La Paz';
$tz['America/Lima'] = 'America/Lima';
$tz['America/Los_Angeles'] = 'America/Los Angeles';
$tz['America/Louisville'] = 'America/Louisville';
$tz['America/Maceio'] = 'America/Maceio';
$tz['America/Managua'] = 'America/Managua';
$tz['America/Manaus'] = 'America/Manaus';
$tz['America/Martinique'] = 'America/Martinique';
$tz['America/Mazatlan'] = 'America/Mazatlan';
$tz['America/Mendoz'] = 'America/Mendoz';
$tz['America/Menominee'] = 'America/Menominee';
$tz['America/Merida'] = 'America/Merida';
$tz['America/Mexico_City'] = 'America/Mexico City';
$tz['America/Miquelon'] = 'America/Miquelon';
$tz['America/Monterrey'] = 'America/Monterrey';
$tz['America/Montevideo'] = 'America/Montevideo';
$tz['America/Montreal'] = 'America/Montreal';
$tz['America/Montserrat'] = 'America/Montserrat';
$tz['America/Nassau'] = 'America/Nassau';
$tz['America/New_York'] = 'America/New York';
$tz['America/Nipigon'] = 'America/Nipigon';
$tz['America/Nome'] = 'America/Nome';
$tz['America/Noronha'] = 'America/Noronha';
$tz['America/Panama'] = 'America/Panama';
$tz['America/Pangnirtung'] = 'America/Pangnirtung';
$tz['America/Paramaribo'] = 'America/Paramaribo';
$tz['America/Phoenix'] = 'America/Phoenix';
$tz['America/Port-au-Prince'] = 'America/Port-au-Prince';
$tz['America/Porto_Velho'] = 'America/Porto Velho';
$tz['America/Port_of_Spain'] = 'America/Port of Spain';
$tz['America/Puerto_Rico'] = 'America/Puerto Rico';
$tz['America/Rainy_River'] = 'America/Rainy River';
$tz['America/Rankin_Inlet'] = 'America/Rankin Inlet';
$tz['America/Recife'] = 'America/Recife';
$tz['America/Regina'] = 'America/Regina';
$tz['America/Rio_Branco'] = 'America/Rio Branco';
$tz['America/Rosario'] = 'America/Rosario';
$tz['America/Santiago'] = 'America/Santiago';
$tz['America/Santo_Domingo'] = 'America/Santo Domingo';
$tz['America/Sao_Paulo'] = 'America/Sao Paulo';
$tz['America/Scoresbysund'] = 'America/Scoresbysund';
$tz['America/Shiprock'] = 'America/Shiprock';
$tz['America/St_Johns'] = 'America/St Johns';
$tz['America/St_Kitts'] = 'America/St Kitts';
$tz['America/St_Lucia'] = 'America/St Lucia';
$tz['America/St_Thomas'] = 'America/St Thomas';
$tz['America/St_Vincent'] = 'America/St Vincent';
$tz['America/Swift_Current'] = 'America/Swift Current';
$tz['America/Tegucigalpa'] = 'America/Tegucigalpa';
$tz['America/Thule'] = 'America/Thule';
$tz['America/Thunder_Bay'] = 'America/Thunder Bay';
$tz['America/Tijuana'] = 'America/Tijuana';
$tz['America/Tortola'] = 'America/Tortola';
$tz['America/Vancouver'] = 'America/Vancouver';
$tz['America/Whitehorse'] = 'America/Whitehorse';
$tz['America/Winnipeg'] = 'America/Winnipeg';
$tz['America/Yakutat'] = 'America/Yakutat';
$tz['America/Yellowknife'] = 'America/Yellowknife';
$tz['Antarctica/Casey'] = 'Antarctica/Casey';
$tz['Antarctica/Davis'] = 'Antarctica/Davis';
$tz['Antarctica/DumontDUrville'] = 'Antarctica/DumontDUrville';
$tz['Antarctica/Mawson'] = 'Antarctica/Mawson';
$tz['Antarctica/McMurdo'] = 'Antarctica/McMurdo';
$tz['Antarctica/Palmer'] = 'Antarctica/Palmer';
$tz['Antarctica/South_Pole'] = 'Antarctica/South Pole';
$tz['Antarctica/Syowa'] = 'Antarctica/Syowa';
$tz['Antarctica/Vostok'] = 'Antarctica/Vostok';
$tz['Arctic/Longyearbyen'] = 'Arctic/Longyearbyen';
$tz['Asia/Aden'] = 'Asia/Aden';
$tz['Asia/Almaty'] = 'Asia/Almaty';
$tz['Asia/Amman'] = 'Asia/Amman';
$tz['Asia/Anadyr'] = 'Asia/Anadyr';
$tz['Asia/Aqtau'] = 'Asia/Aqtau';
$tz['Asia/Aqtobe'] = 'Asia/Aqtobe';
$tz['Asia/Ashgabat'] = 'Asia/Ashgabat';
$tz['Asia/Baghdad'] = 'Asia/Baghdad';
$tz['Asia/Bahrain'] = 'Asia/Bahrain';
$tz['Asia/Baku'] = 'Asia/Baku';
$tz['Asia/Bangkok'] = 'Asia/Bangkok';
$tz['Asia/Beirut'] = 'Asia/Beirut';
$tz['Asia/Bishkek'] = 'Asia/Bishkek';
$tz['Asia/Brunei'] = 'Asia/Brunei';
$tz['Asia/Calcutta'] = 'Asia/Calcutta';
$tz['Asia/Chungking'] = 'Asia/Chungking';
$tz['Asia/Colombo'] = 'Asia/Colombo';
$tz['Asia/Damascus'] = 'Asia/Damascus';
$tz['Asia/Dhaka'] = 'Asia/Dhaka';
$tz['Asia/Dili'] = 'Asia/Dili';
$tz['Asia/Dubai'] = 'Asia/Dubai';
$tz['Asia/Dushanbe'] = 'Asia/Dushanbe';
$tz['Asia/Gaza'] = 'Asia/Gaza';
$tz['Asia/Harbin'] = 'Asia/Harbin';
$tz['Asia/Hong_Kong'] = 'Asia/Hong Kong';
$tz['Asia/Hovd'] = 'Asia/Hovd';
$tz['Asia/Irkutsk'] = 'Asia/Irkutsk';
$tz['Asia/Jakarta'] = 'Asia/Jakarta';
$tz['Asia/Jayapura'] = 'Asia/Jayapura';
$tz['Asia/Jerusalem'] = 'Asia/Jerusalem';
$tz['Asia/Kabul'] = 'Asia/Kabul';
$tz['Asia/Kamchatka'] = 'Asia/Kamchatka';
$tz['Asia/Karachi'] = 'Asia/Karachi';
$tz['Asia/Kashgar'] = 'Asia/Kashgar';
$tz['Asia/Katmandu'] = 'Asia/Katmandu';
$tz['Asia/Krasnoyarsk'] = 'Asia/Krasnoyarsk';
$tz['Asia/Kuala_Lumpur'] = 'Asia/Kuala Lumpur';
$tz['Asia/Kuching'] = 'Asia/Kuching';
$tz['Asia/Kuwait'] = 'Asia/Kuwait';
$tz['Asia/Macao'] = 'Asia/Macao';
$tz['Asia/Magadan'] = 'Asia/Magadan';
$tz['Asia/Manila'] = 'Asia/Manila';
$tz['Asia/Muscat'] = 'Asia/Muscat';
$tz['Asia/Nicosia'] = 'Asia/Nicosia';
$tz['Asia/Novosibirsk'] = 'Asia/Novosibirsk';
$tz['Asia/Omsk'] = 'Asia/Omsk';
$tz['Asia/Phnom_Penh'] = 'Asia/Phnom Penh';
$tz['Asia/Pyongyang'] = 'Asia/Pyongyang';
$tz['Asia/Qatar'] = 'Asia/Qatar';
$tz['Asia/Rangoon'] = 'Asia/Rangoon';
$tz['Asia/Riyadh'] = 'Asia/Riyadh';
$tz['Asia/Saigon'] = 'Asia/Saigon';
$tz['Asia/Samarkand'] = 'Asia/Samarkand';
$tz['Asia/Seoul'] = 'Asia/Seoul';
$tz['Asia/Shanghai'] = 'Asia/Shanghai';
$tz['Asia/Singapore'] = 'Asia/Singapore';
$tz['Asia/Taipei'] = 'Asia/Taipei';
$tz['Asia/Tashkent'] = 'Asia/Tashkent';
$tz['Asia/Tbilisi'] = 'Asia/Tbilisi';
$tz['Asia/Tehran'] = 'Asia/Tehran';
$tz['Asia/Thimphu'] = 'Asia/Thimphu';
$tz['Asia/Tokyo'] = 'Asia/Tokyo';
$tz['Asia/Ujung_Pandang'] = 'Asia/Ujung Pandang';
$tz['Asia/Ulaanbaatar'] = 'Asia/Ulaanbaatar';
$tz['Asia/Urumqi'] = 'Asia/Urumqi';
$tz['Asia/Vientiane'] = 'Asia/Vientiane';
$tz['Asia/Vladivostok'] = 'Asia/Vladivostok';
$tz['Asia/Yakutsk'] = 'Asia/Yakutsk';
$tz['Asia/Yekaterinburg'] = 'Asia/Yekaterinburg';
$tz['Asia/Yerevan'] = 'Asia/Yerevan';
$tz['Atlantic/Azores'] = 'Atlantic/Azores';
$tz['Atlantic/Bermuda'] = 'Atlantic/Bermuda';
$tz['Atlantic/Canary'] = 'Atlantic/Canary';
$tz['Atlantic/Cape_Verde'] = 'Atlantic/Cape Verde';
$tz['Atlantic/Faeroe'] = 'Atlantic/Faeroe';
$tz['Atlantic/Jan_Mayen'] = 'Atlantic/Jan Mayen';
$tz['Atlantic/Madeira'] = 'Atlantic/Madeira';
$tz['Atlantic/Reykjavik'] = 'Atlantic/Reykjavik';
$tz['Atlantic/South_Georgia'] = 'Atlantic/South Georgia';
$tz['Atlantic/Stanley'] = 'Atlantic/Stanley';
$tz['Atlantic/St_Helena'] = 'Atlantic/St Helena';
$tz['Australia/Adelaide'] = 'Australia/Adelaide';
$tz['Australia/Brisbane'] = 'Australia/Brisbane';
$tz['Australia/Broken_Hill'] = 'Australia/Broken Hill';
$tz['Australia/Darwin'] = 'Australia/Darwin';
$tz['Australia/Hobart'] = 'Australia/Hobart';
$tz['Australia/Lindeman'] = 'Australia/Lindeman';
$tz['Australia/Lord_Howe'] = 'Australia/Lord Howe';
$tz['Australia/Melbourne'] = 'Australia/Melbourne';
$tz['Australia/Perth'] = 'Australia/Perth';
$tz['Australia/Sydney'] = 'Australia/Sydney';
$tz['Europe/Amsterdam'] = 'Europe/Amsterdam';
$tz['Europe/Andorra'] = 'Europe/Andorra';
$tz['Europe/Athens'] = 'Europe/Athens';
$tz['Europe/Belfast'] = 'Europe/Belfast';
$tz['Europe/Belgrade'] = 'Europe/Belgrade';
$tz['Europe/Berlin'] = 'Europe/Berlin';
$tz['Europe/Bratislava'] = 'Europe/Bratislava';
$tz['Europe/Brussels'] = 'Europe/Brussels';
$tz['Europe/Bucharest'] = 'Europe/Bucharest';
$tz['Europe/Budapest'] = 'Europe/Budapest';
$tz['Europe/Chisinau'] = 'Europe/Chisinau';
$tz['Europe/Copenhagen'] = 'Europe/Copenhagen';
$tz['Europe/Dublin'] = 'Europe/Dublin';
$tz['Europe/Gibraltar'] = 'Europe/Gibraltar';
$tz['Europe/Helsinki'] = 'Europe/Helsinki';
$tz['Europe/Istanbul'] = 'Europe/Istanbul';
$tz['Europe/Kaliningrad'] = 'Europe/Kaliningrad';
$tz['Europe/Kiev'] = 'Europe/Kiev';
$tz['Europe/Lisbon'] = 'Europe/Lisbon';
$tz['Europe/Ljubljana'] = 'Europe/Ljubljana';
$tz['Europe/London'] = 'Europe/London';
$tz['Europe/Luxembourg'] = 'Europe/Luxembourg';
$tz['Europe/Madrid'] = 'Europe/Madrid';
$tz['Europe/Malta'] = 'Europe/Malta';
$tz['Europe/Minsk'] = 'Europe/Minsk';
$tz['Europe/Monaco'] = 'Europe/Monaco';
$tz['Europe/Moscow'] = 'Europe/Moscow';
$tz['Europe/Oslo'] = 'Europe/Oslo';
$tz['Europe/Paris'] = 'Europe/Paris';
$tz['Europe/Prague'] = 'Europe/Prague';
$tz['Europe/Riga'] = 'Europe/Riga';
$tz['Europe/Rome'] = 'Europe/Rome';
$tz['Europe/Samara'] = 'Europe/Samara';
$tz['Europe/San_Marino'] = 'Europe/San Marino';
$tz['Europe/Sarajevo'] = 'Europe/Sarajevo';
$tz['Europe/Simferopol'] = 'Europe/Simferopol';
$tz['Europe/Skopje'] = 'Europe/Skopje';
$tz['Europe/Sofia'] = 'Europe/Sofia';
$tz['Europe/Stockholm'] = 'Europe/Stockholm';
$tz['Europe/Tallinn'] = 'Europe/Tallinn';
$tz['Europe/Tirane'] = 'Europe/Tirane';
$tz['Europe/Uzhgorod'] = 'Europe/Uzhgorod';
$tz['Europe/Vaduz'] = 'Europe/Vaduz';
$tz['Europe/Vatican'] = 'Europe/Vatican';
$tz['Europe/Vienna'] = 'Europe/Vienna';
$tz['Europe/Vilnius'] = 'Europe/Vilnius';
$tz['Europe/Warsaw'] = 'Europe/Warsaw';
$tz['Europe/Zagreb'] = 'Europe/Zagreb';
$tz['Europe/Zaporozhye'] = 'Europe/Zaporozhye';
$tz['Europe/Zurich'] = 'Europe/Zurich';
$tz['Indian/Antananarivo'] = 'Indian/Antananarivo';
$tz['Indian/Chagos'] = 'Indian/Chagos';
$tz['Indian/Christmas'] = 'Indian/Christmas';
$tz['Indian/Cocos'] = 'Indian/Cocos';
$tz['Indian/Comoro'] = 'Indian/Comoro';
$tz['Indian/Kerguelen'] = 'Indian/Kerguelen';
$tz['Indian/Mahe'] = 'Indian/Mahe';
$tz['Indian/Maldives'] = 'Indian/Maldives';
$tz['Indian/Mauritius'] = 'Indian/Mauritius';
$tz['Indian/Mayotte'] = 'Indian/Mayotte';
$tz['Indian/Reunion'] = 'Indian/Reunion';
$tz['Pacific/Apia'] = 'Pacific/Apia';
$tz['Pacific/Auckland'] = 'Pacific/Auckland';
$tz['Pacific/Chatham'] = 'Pacific/Chatham';
$tz['Pacific/Easter'] = 'Pacific/Easter';
$tz['Pacific/Efate'] = 'Pacific/Efate';
$tz['Pacific/Enderbury'] = 'Pacific/Enderbury';
$tz['Pacific/Fakaofo'] = 'Pacific/Fakaofo';
$tz['Pacific/Fiji'] = 'Pacific/Fiji';
$tz['Pacific/Funafuti'] = 'Pacific/Funafuti';
$tz['Pacific/Galapagos'] = 'Pacific/Galapagos';
$tz['Pacific/Gambier'] = 'Pacific/Gambier';
$tz['Pacific/Guadalcanal'] = 'Pacific/Guadalcanal';
$tz['Pacific/Guam'] = 'Pacific/Guam';
$tz['Pacific/Honolulu'] = 'Pacific/Honolulu';
$tz['Pacific/Johnston'] = 'Pacific/Johnston';
$tz['Pacific/Kiritimati'] = 'Pacific/Kiritimati';
$tz['Pacific/Kosrae'] = 'Pacific/Kosrae';
$tz['Pacific/Kwajalein'] = 'Pacific/Kwajalein';
$tz['Pacific/Majuro'] = 'Pacific/Majuro';
$tz['Pacific/Marquesas'] = 'Pacific/Marquesas';
$tz['Pacific/Midway'] = 'Pacific/Midway';
$tz['Pacific/Nauru'] = 'Pacific/Nauru';
$tz['Pacific/Niue'] = 'Pacific/Niue';
$tz['Pacific/Norfolk'] = 'Pacific/Norfolk';
$tz['Pacific/Noumea'] = 'Pacific/Noumea';
$tz['Pacific/Pago_Pago'] = 'Pacific/Pago Pago';
$tz['Pacific/Palau'] = 'Pacific/Palau';
$tz['Pacific/Pitcairn'] = 'Pacific/Pitcairn';
$tz['Pacific/Ponape'] = 'Pacific/Ponape';
$tz['Pacific/Port_Moresby'] = 'Pacific/Port Moresby';
$tz['Pacific/Rarotonga'] = 'Pacific/Rarotonga';
$tz['Pacific/Saipan'] = 'Pacific/Saipan';
$tz['Pacific/Tahiti'] = 'Pacific/Tahiti';
$tz['Pacific/Tarawa'] = 'Pacific/Tarawa';
$tz['Pacific/Tongatapu'] = 'Pacific/Tongatapu';
$tz['Pacific/Truk'] = 'Pacific/Truk';
$tz['Pacific/Wake'] = 'Pacific/Wake';
$tz['Pacific/Wallis'] = 'Pacific/Wallis';
$tz['Pacific/Yap'] = 'Pacific/Yap';
$GLOBALS['tz'] = &$tz;

View File

@ -1,163 +0,0 @@
<?php
/**
* registry.php -- Horde application registry.
*
* $Horde: horde/config/registry.php.dist,v 1.243 2004/10/05 20:08:13 chuck Exp $
*
* This configuration file is used by Horde to determine which Horde
* applications are installed and where, as well as how they interact.
*
* Application registry
* --------------------
* The following settings register installed Horde applications.
* By default, Horde assumes that the application directories live
* inside the horde directory.
*
* Attribute Type Description
* --------- ---- -----------
* fileroot string The base filesystem path for the module's files
* webroot string The base URI for the module
* graphics string The base URI for the module images
* icon string The URI for an icon to show in menus for the module
* name string The name used in menus and descriptions for a module
* status string 'inactive', 'hidden', 'notoolbar', 'heading',
* 'block', 'admin', or 'active'.
* provides string Service types the module provides.
* initial_page string The initial (default) page (filename) for the module
* templates string The filesystem path to the templates directory
* menu_parent string The name of the 'heading' group that this app should
* show up under.
* target string The (optional) target frame for the link.
*/
// We try to automatically determine the proper webroot for Horde
// here. This still assumes that applications live under horde/. If
// this results in incorrect results for you, simply change the two
// uses of the $webroot variable in the 'horde' stanza below.
//
// Note for Windows users: the below assumes that your PHP_SELF
// variable uses forward slashes. If it does not, you'll have to tweak
// this.
if (isset($_SERVER['PHP_SELF'])) {
$parts = preg_split(';/;', $_SERVER['PHP_SELF'], 2, PREG_SPLIT_NO_EMPTY);
$webroot = strstr(dirname(__FILE__), '/' . array_shift($parts));
if ($webroot !== false) {
$webroot = preg_replace(';/config$;', '', $webroot);
} else {
$webroot = '/horde';
}
} else {
$webroot = '/horde';
}
$this->applications['horde'] = array(
'fileroot' => dirname(__FILE__) . '/..',
'webroot' => $webroot,
'initial_page' => 'login.php',
'icon' => $webroot . '/graphics/horde.png',
'name' => _("Horde"),
'status' => 'active',
'templates' => dirname(__FILE__) . '/../templates',
'provides' => 'horde'
);
#$this->applications['mnemo'] = array(
# 'fileroot' => dirname(__FILE__) . '/../mnemo',
# 'webroot' => $this->applications['horde']['webroot'] . '/mnemo',
# 'icon' => $this->applications['horde']['webroot'] . '/mnemo/graphics/mnemo.gif',
# 'name' => _("Notes"),
# 'status' => 'active',
# 'provides' => 'notes',
# 'menu_parent' => 'organizing'
#);
$this->applications['egwnotessync'] = array(
'fileroot' => EGW_SERVER_ROOT.'/syncml/notes',
'webroot' => $this->applications['horde']['webroot'] . '/mnemo',
'icon' => $this->applications['horde']['webroot'] . '/mnemo/graphics/mnemo.gif',
'name' => _("Notes"),
'status' => 'active',
'provides' => array('notes', 'sifnotes', 'snote'),
'menu_parent' => 'organizing'
);
$this->applications['egwcontactssync'] = array(
'fileroot' => EGW_SERVER_ROOT.'/syncml/contacts',
'webroot' => $this->applications['horde']['webroot'] . '/mnemo',
'icon' => $this->applications['horde']['webroot'] . '/mnemo/graphics/mnemo.gif',
'name' => _("Contacts"),
'status' => 'active',
'provides' => array('contacts', 'sifcontacts', 'scard', 'card'),
'menu_parent' => 'organizing'
);
#$this->applications['egwsifcontactssync'] = array(
# 'fileroot' => EGW_SERVER_ROOT.'/syncml/sifcontacts',
# 'webroot' => $this->applications['horde']['webroot'] . '/mnemo',
# 'icon' => $this->applications['horde']['webroot'] . '/mnemo/graphics/mnemo.gif',
# 'name' => _("SIF Contacts"),
# 'status' => 'active',
# 'provides' => 'sifcontacts',
# 'menu_parent' => 'organizing'
#);
$this->applications['egwcalendarsync'] = array(
'fileroot' => EGW_SERVER_ROOT.'/syncml/calendar',
'webroot' => $this->applications['horde']['webroot'] . '/mnemo',
'icon' => $this->applications['horde']['webroot'] . '/mnemo/graphics/mnemo.gif',
'name' => _("Calendar"),
'status' => 'active',
'provides' => array('calendar', 'sifcalendar', 'scal', 'events'),
'menu_parent' => 'organizing'
);
#$this->applications['egwsifcalendarsync'] = array(
# 'fileroot' => EGW_SERVER_ROOT.'/syncml/sifcalendar',
# 'webroot' => $this->applications['horde']['webroot'] . '/mnemo',
# 'icon' => $this->applications['horde']['webroot'] . '/mnemo/graphics/mnemo.gif',
# 'name' => _("Calendar"),
# 'status' => 'active',
# 'provides' => 'sifcalendar',
# 'menu_parent' => 'organizing'
#);
$this->applications['egwtaskssync'] = array(
'fileroot' => EGW_SERVER_ROOT.'/syncml/tasks',
'webroot' => $this->applications['horde']['webroot'] . '/mnemo',
'icon' => $this->applications['horde']['webroot'] . '/mnemo/graphics/mnemo.gif',
'name' => _("Tasks"),
'status' => 'active',
'provides' => array('tasks', 'siftasks', 'stask', 'jobs'),
'menu_parent' => 'organizing'
);
#$this->applications['egwsiftaskssync'] = array(
# 'fileroot' => EGW_SERVER_ROOT.'/syncml/siftasks',
# 'webroot' => $this->applications['horde']['webroot'] . '/mnemo',
# 'icon' => $this->applications['horde']['webroot'] . '/mnemo/graphics/mnemo.gif',
# 'name' => _("SIFTasks"),
# 'status' => 'active',
# 'provides' => array('siftasks', 'stask'),
# 'menu_parent' => 'organizing'
#);
$this->applications['egwcaltaskssync'] = array(
'fileroot' => EGW_SERVER_ROOT.'/syncml/caltasks',
'webroot' => $this->applications['horde']['webroot'] . '/mnemo',
'icon' => $this->applications['horde']['webroot'] . '/mnemo/graphics/mnemo.gif',
'name' => _("Calendar and Tasks"),
'status' => 'active',
'provides' => 'caltasks',
'menu_parent' => 'organizing'
);
$this->applications['egwconfigurationsync'] = array(
'fileroot' => EGW_SERVER_ROOT.'/syncml/configuration',
'webroot' => $this->applications['horde']['webroot'] . '/mnemo',
'icon' => $this->applications['horde']['webroot'] . '/mnemo/graphics/mnemo.gif',
'name' => _("Funambol Configurations"),
'status' => 'active',
'provides' => array('configuration'),
'menu_parent' => 'organizing'
);

View File

@ -1,54 +0,0 @@
<?php
/**
* Horde base inclusion file.
*
* This file brings in all of the dependencies that Horde
* framework-level scripts will need, and sets up objects that all
* scripts use.
*
* Note: This base file does _not_ check authentication, so as to
* avoid an infinite loop on the Horde login page. You'll need to do
* it yourself in framework-level pages.
*
* $Horde: horde/lib/base.php,v 1.41 2005/01/03 14:35:14 jan Exp $
*
* Copyright 1999-2005 Chuck Hagenbuch <chuck@horde.org>
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*/
// Check for a prior definition of HORDE_BASE (perhaps by an
// auto_prepend_file definition for site customization).
#if (!defined('HORDE_BASE')) {
# @define('HORDE_BASE', dirname(__FILE__) . '/..');
#}
// Load the Horde Framework core, and set up inclusion paths.
#require_once HORDE_BASE . '/lib/core.php';
// Registry.
if (Util::nonInputVar('session_control') == 'none') {
$registry = &Registry::singleton(HORDE_SESSION_NONE);
} else {
$registry = &Registry::singleton();
}
#if (is_a(($pushed = $registry->pushApp('horde', !defined('AUTH_HANDLER'))), 'PEAR_Error')) {
# if ($pushed->getCode() == 'permission_denied') {
# Horde::authenticationFailureRedirect();
# }
# Horde::fatal($pushed, __FILE__, __LINE__, false);
#}
$conf = &$GLOBALS['conf'];
#@define('HORDE_TEMPLATES', $registry->get('templates'));
// Notification System.
#$notification = &Notification::singleton();
#$notification->attach('status');
/* Set up the menu. */
#require_once 'Horde/Menu.php';
#$menu = new Menu();
// Compress output
#Horde::compressOutput();

View File

@ -1,56 +0,0 @@
<?php
/**
* Horde Application Framework core services file.
*
* This file sets up any necessary include path variables and includes
* the minimum required Horde libraries.
*
* $Horde: horde/lib/core.php,v 1.27 2005/01/03 14:35:14 jan Exp $
*
* Copyright 1999-2005 Chuck Hagenbuch <chuck@horde.org>
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*/
/* Turn PHP stuff off that can really screw things up. */
ini_set('magic_quotes_sybase', 0);
ini_set('magic_quotes_runtime', 0);
/* If the Horde Framework packages are not installed in PHP's global
* include_path, you must add an ini_set() call here to add their location to
* the include_path. */
// ini_set('include_path', dirname(__FILE__) . PATH_SEPARATOR . ini_get('include_path'));
//set_include_path(dirname(__FILE__). '/../../horde/' . PATH_SEPARATOR . dirname(__FILE__). '/../../../../egw-pear/' . PATH_SEPARATOR . get_include_path());
@define('EGW_BASE', realpath(dirname(dirname(__FILE__) . '/../../../../rpc.php')));
// Check for a prior definition of HORDE_BASE (perhaps by an
// auto_prepend_file definition for site customization).
if (!defined('HORDE_BASE')) {
@define('HORDE_BASE', EGW_BASE . '/phpgwapi/inc/horde/');
}
$save_include_path = set_include_path(HORDE_BASE . PATH_SEPARATOR . get_include_path());
/* PEAR base class. */
include_once 'PEAR.php';
/* Horde core classes. */
include_once 'Horde.php';
include_once 'Horde/Registry.php';
#include_once 'Horde/DataTree.php';
include_once 'Horde/String.php';
include_once 'Horde/Date.php';
include_once 'Horde/NLS.php';
include_once 'Horde/iCalendar.php';
//include_once 'Horde/Notification.php';
//include_once 'Horde/Auth.php';
//include_once 'Horde/Browser.php';
//include_once 'Horde/Perms.php';
/* Browser detection object. *
if (class_exists('Browser')) {
$browser = &Browser::singleton();
}
*/
// restore EGroupware include path to NOT conflict with new Horde code installed in include-path
set_include_path($save_include_path);