first commit of syncml code

This commit is contained in:
Lars Kneschke 2005-06-19 19:00:58 +00:00
parent f354eacf66
commit d43bf7d44f
58 changed files with 16048 additions and 0 deletions

1474
phpgwapi/inc/horde/Horde.php Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,412 @@
<?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;
var $_extra;
/**
* 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

@ -0,0 +1,523 @@
<?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

@ -0,0 +1,261 @@
<?php
/**
* The Horde_RPC:: class provides a set of server and client methods for
* RPC communication.
*
* TODO:
* - Introspection documentation and method signatures.
*
* EXAMPLE:
* $response = Horde_RPC::request('xmlrpc',
* '/horde/rpc.php', 'www.example.com', 80,
* 'contacts.search',
* array(array('jan'), array('localsql'),
* array('name', 'email')),
* Auth::getAuth(), Auth::getCredential('password'));
*
* $Horde: framework/RPC/RPC.php,v 1.7 2004/09/08 09:07:25 jan Exp $
*
* Copyright 2002-2004 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>
* @version $Revision$
* @since Horde 3.0
* @package Horde_RPC
*/
class Horde_RPC {
/**
* Whether we need an authorized user or not.
*
* @access protected
* @var boolean $_authorize.
*/
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 (optional) A hash containing any necessary
* parameters for the method call.
* @param $options Optional 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.
*
* @access public
*
* @param mixed $driver The type of concrete RPC subclass to
* return. This is based on the protocol
* driver ($driver). The code is dynamically
* included. If $driver is an array, then
* we will look in $driver[0]/lib/RPC/
* for the subclass implementation named
* $driver[1].php.
* @param optional array $params A hash containing any additional
* configuration or connection parameters
* a subclass might need.
*
* @return object 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)) {
return $ret = &new $class($params);
} else {
require_once 'PEAR.php';
return PEAR::raiseError('Class definition of ' . $class . ' not found.');
}
}
/**
* 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()
*
* @access public
*
* @param string $driver The type of concrete RPC subclass to
* return. This is based on the protocol
* driver ($driver). The code is dynamically
* included.
* @param optional array $params A hash containing any additional
* configuration or connection parameters a
* subclass might need.
*
* @return object 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

@ -0,0 +1,280 @@
<?php
include_once 'Horde/RPC.php';
include_once 'Horde/SyncML.php';
#include_once 'Horde/SyncML/State.php';
include_once 'Horde/SyncML/State_egw.php';
include_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.18 2004/07/13 03:06:12 chuck Exp $
*
* Copyright 2003-2004 Chuck Hagenbuch <chuck@horde.org>, 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>
* @version $Revision$
* @since Horde 3.0
* @package Horde_RPC
*/
class Horde_RPC_syncml extends Horde_RPC {
/**
* Output ContentHandler used to output XML events.
* @var object $_output
*/
var $_output;
/**
* @var integer $_xmlStack
*/
var $_xmlStack = 0;
/**
* Debug directory, if set will store copies of all packets.
*/
var $_debugDir = '/var/www/groupware.groupwareappliance.com/htdocs/syncml/';
/**
* Default character set. Only supports UTF-8(ASCII?).
*/
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 XML packets to
// $this->_debugDir.
if (!empty($this->_debugDir) && is_dir($this->_debugDir)) {
$today = date('Y-m-d');
$deviceName = str_replace('/','',$_SERVER["HTTP_USER_AGENT"]);
if(!is_dir($this->_debugDir .'/'. $today))
{
mkdir($this->_debugDir .'/'. $today);
}
$debugDir = $this->_debugDir .'/'. $today .'/'. $deviceName;
if(!is_dir($debugDir))
{
mkdir($debugDir);
}
$packetNum = @intval(file_get_contents($debugDir . '/syncml.packetnum'));
if (!isset($packetNum)) {
$packetNum = 0;
}
$f = @fopen($debugDir . '/syncml_client_' . $packetNum . '.xml', 'wb');
if ($f) {
fwrite($f, $request);
fclose($f);
}
}
// $this->_output can be already set by a subclass.
// The subclass can use it's own ContentHandler and bypass
// this classes use of the ContentHandler. In this case
// no output is return from this method, instead the output
// comes from the subclasses ContentHandler
// We may need to add this code back when we get to the content
//if (!isset($this->_output)) {
include_once 'XML/WBXML/ContentHandler.php';
$this->_output = &new XML_WBXML_ContentHandler();
//}
$this->_parse($request);
$response = $this->_output->getOutput();
// Very useful for debugging.
if (!empty($this->_debugDir) && is_dir($this->_debugDir)) {
$f = @fopen($debugDir . '/syncml_server_' . $packetNum . '.xml', 'wb');
if ($f) {
fwrite($f, $response);
fclose($f);
}
$fp = @fopen($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($errorLogging, __FILE__, __LINE__, PEAR_LOG_DEBUG);
}
return $response;
}
function _parse($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);
}
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);
}
/**
* Get 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

@ -0,0 +1,110 @@
<?php
include_once 'Horde/RPC/syncml.php';
include_once 'XML/WBXML/Decoder.php';
include_once 'XML/WBXML/Encoder.php';
/**
* The Horde_RPC_syncml class provides a SyncML implementation of the Horde
* RPC system.
*
* $Horde: framework/RPC/RPC/syncml_wbxml.php,v 1.11 2004/07/13 03:06:12 chuck Exp $
*
* Copyright 2003-2004 Chuck Hagenbuch <chuck@horde.org>, 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>
* @version $Revision$
* @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)) {
$today = date('Y-m-d');
$deviceName = str_replace('/','',$_SERVER["HTTP_USER_AGENT"]);
if(!is_dir($this->_debugDir .'/'. $today))
{
mkdir($this->_debugDir .'/'. $today);
}
$debugDir = $this->_debugDir .'/'. $today .'/'. $deviceName;
if(!is_dir($debugDir))
{
mkdir($debugDir);
}
$packetNum = @intval(file_get_contents($debugDir . '/syncml_wbxml.packetnum'));
if (!isset($packetNum)) {
$packetNum = 0;
}
$fp = fopen($debugDir . '/syncml_client_' . $packetNum . '.wbxml', 'wb');
fwrite($fp, $request);
fclose($fp);
}
$decoder = &new XML_WBXML_Decoder();
$xmlinput = $decoder->decode($request);
if (is_a($xmlinput, 'PEAR_Error')) {
return '';
}
$xmloutput = parent::getResponse($xmlinput);
$encoder = &new XML_WBXML_Encoder();
$encoder->setVersion($decoder->getVersion());
$encoder->setCharset($decoder->getCharsetStr());
$response = $encoder->encode($xmloutput);
if (!empty($this->_debugDir) && is_dir($this->_debugDir)) {
$fp = fopen($debugDir . '/syncml_server_' . $packetNum . '.wbxml', 'wb');
fwrite($fp, $response);
fclose($fp);
$fp = fopen($debugDir . '/syncml_wbxml.packetnum', 'w');
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($errorLogging, __FILE__, __LINE__, PEAR_LOG_DEBUG);
}
return $response;
}
/**
* Get 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

@ -0,0 +1,555 @@
<?php
require_once 'Horde/Util.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.50 2005/02/10 17:09:44 jan Exp $
*
* Copyright 2003-2005 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_Util
*/
class String {
/**
* Sets a default charset that the String:: methods will use if none is
* explicitely specified.
*
* @param string $charset The charset to use as the default one.
*/
function setDefaultCharset($charset)
{
$GLOBALS['_HORDE_STRING_CHARSET'] = $charset;
if (Util::extensionExists('mbstring') &&
function_exists('mb_regex_encoding')) {
@mb_regex_encoding($charset);
}
}
/**
* 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.
* @param bool $recursion Internally used.
*
* @return string The converted string.
*/
function convertCharset($input, $from, $to = null, $recursion = false)
{
/* 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 (!$recursion) {
$from = String::lower($from);
$to = String::lower($to);
}
if ($from == $to) {
return $input;
}
if (is_array($input)) {
$tmp = array();
foreach ($input as $key => $val) {
$tmp[String::convertCharset($key, $from, $to, true)] = String::convertCharset($val, $from, $to, true);
}
return $tmp;
}
if (is_object($input)) {
$vars = get_object_vars($input);
foreach ($vars as $key => $val) {
$input->$key = String::convertCharset($val, $from, $to, true);
}
return $input;
}
if (!is_string($input)) {
return $input;
}
$output = false;
/* Use utf8_[en|de]code() if possible. */
$from_check = (($from == 'iso-8859-1') || ($from == 'us-ascii'));
if ($from_check && ($to == 'utf-8')) {
return utf8_encode($input);
}
$to_check = (($to == 'iso-8859-1') || ($to == 'us-ascii'));
if (($from == 'utf-8') && $to_check) {
return utf8_decode($input);
}
/* First try iconv with transliteration. */
if ($from != 'utf7-imap' &&
$to != 'utf7-imap' &&
Util::extensionExists('iconv')) {
ini_set('track_errors', 1);
/* 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. */
$output = @iconv($from, $to . '//TRANSLIT', $input . 'x');
if (isset($php_errormsg)) {
$output = false;
} else {
$output = String::substr($output, 0, -1, $to);
}
ini_restore('track_errors');
}
/* Next try mbstring. */
if (!$output && Util::extensionExists('mbstring')) {
$output = @mb_convert_encoding($input, $to, $from);
}
/* At last try imap_utf7_[en|de]code if appropriate. */
if (!$output && Util::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
*/
function lower($string, $locale = false, $charset = null)
{
static $lowers;
if ($locale) {
/* The existence of mb_strtolower() depends on the platform. */
if (Util::extensionExists('mbstring') &&
function_exists('mb_strtolower')) {
if (is_null($charset)) {
$charset = $GLOBALS['_HORDE_STRING_CHARSET'];
}
$ret = @mb_strtolower($string, $charset);
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, 'en_US');
$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
*/
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'];
}
$ret = @mb_strtoupper($string, $charset);
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, 'en_US');
$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.
*/
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 int $start The part's start position, zero based.
* @param int $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.
*/
function substr($string, $start, $length = null, $charset = null)
{
if (Util::extensionExists('mbstring')) {
if (is_null($charset)) {
$charset = $GLOBALS['_HORDE_STRING_CHARSET'];
}
if (is_null($length)) {
$length = String::length($string, $charset);
}
$ret = @mb_substr($string, $start, $length, $charset);
if (!empty($ret)) {
return $ret;
}
}
if (is_null($length)) {
$length = String::length($string);
}
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.
*/
function length($string, $charset = null)
{
if (Util::extensionExists('mbstring')) {
if (is_null($charset)) {
$charset = $GLOBALS['_HORDE_STRING_CHARSET'];
}
$ret = @mb_strlen($string, $charset);
if (!empty($ret)) {
return $ret;
}
}
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 int $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 int The position of first occurrence.
*/
function pos($haystack, $needle, $offset = 0, $charset = null)
{
if (Util::extensionExists('mbstring')) {
if (is_null($charset)) {
$charset = $GLOBALS['_HORDE_STRING_CHARSET'];
}
ini_set('track_errors', 1);
$ret = @mb_strpos($haystack, $needle, $offset, $charset);
ini_restore('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 int $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.
*/
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.
*
* @todo Make multibyte-save.
*
* @access public
*
* @param string $text String containing the text to wrap.
* @param optional integer $length Wrap $text at this number of
* characters.
* @param optional string $break_char Character(s) to use when breaking
* lines.
* @param optional string $charset Character set to use when breaking
* lines.
* @param optional 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.
*/
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 = wordwrap($input, $length, $break_char);
}
$paragraphs[] = $line;
}
return implode($break_char, $paragraphs);
}
/**
* Returns true if the every character in the parameter is an
* alphabetic character. This method doesn't work with any charset
* other than the current charset yet.
*
* @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.
*/
function isAlpha($string, $charset = null)
{
if (Util::extensionExists('mbstring')) {
$old_charset = mb_regex_encoding();
if ($charset != $old_charset) {
@mb_regex_encoding($charset);
}
$alpha = !mb_ereg_match('[^[:alpha:]]', $string);
if ($charset != $old_charset) {
@mb_regex_encoding($old_charset);
}
return $alpha;
}
return ctype_alpha($string);
}
/**
* Returns true if every character in the parameter is a lowercase
* letter in the current locale.
*
* @access public
*
* @param $string The string to test.
* @param $charset The charset to use when testing the string.
*
* @return boolean True if the parameter was lowercase.
*/
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.
*
* @access public
*
* @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.
*/
function isUpper($string, $charset = null)
{
return ((String::upper($string, true, $charset) === $string) &&
String::isAlpha($string, $charset));
}
/**
* Performs a regex match search on the text provided. Will correctly
* handle text with multibyte characters if the mbstring extensions and
* the mbregex functions are available. Will use the preg_match()
* function if possible or if the mbregex ereg function is not available.
*
* @access public
* @since Horde 3.1
*
* @param string $text The text to search.
* @param array $regex The regular expressions to use. These
* expressions should conform to ereg() rules -
* extended perl rules are NOT supported.
* Additionally, do NOT add perl regex delimiters
* (e.g. '/' or '|') to the beginning/end.
* @param string $charset The character set of the text.
*
* @return array The matches array from the first regex that matches.
*/
function regexMatch($text, $regex, $charset = null)
{
static $mbregex;
if (!isset($mbregex)) {
$mbregex = function_exists('mb_ereg');
}
$use_mb = false;
if ($mbregex && !is_null($charset) &&
(String::lower($charset) != 'utf-8')) {
$old_charset = mb_regex_encoding();
if ($charset != $old_charset) {
@mb_regex_encoding($charset);
} else {
unset($old_charset);
}
$use_mb = true;
}
$matches = array();
foreach ($regex as $val) {
if ($use_mb) {
if (mb_ereg($val, $text, $matches)) {
break;
}
} else {
if (preg_match('/' . $val . '/u', $text, $matches)) {
break;
}
}
}
if (isset($old_charset)) {
@mb_regex_encoding($old_charset);
}
return $matches;
}
}

View File

@ -0,0 +1,611 @@
<?php
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';
/**
* 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.
*
* $Horde: framework/SyncML/SyncML.php,v 1.21 2004/07/21 19:26:36 karsten 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>
* @author Karsten Fourmont <fourmont@gmx.de>
*
* @version $Revision$
* @since Horde 3.0
* @package Horde_SyncML
*/
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) or 1.1 (1).
*
* @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;
function getStateFromSession($sourceURI, $locName, $sessionID)
{
// Remove any existing session since we'll be contructing a
// custom session id.
session_destroy();
// 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.
session_id('syncml' . preg_replace('/[^a-zA-Z0-9]/', '', $sourceURI . $sessionID));
@session_start();
Horde::logMessage('SyncML: session id = ' . session_id(), __FILE__, __LINE__, PEAR_LOG_DEBUG);
if (!isset($_SESSION['SyncML.state'])) {
// Create a new state if one does not already exist.
Horde::logMessage('SyncML: new session state', __FILE__, __LINE__, PEAR_LOG_DEBUG);
# LK $_SESSION['SyncML.state'] = &new Horde_SyncML_State($sourceURI, $locName, $sessionID);
$_SESSION['SyncML.state'] = &new EGW_SyncML_State($sourceURI, $locName, $sessionID);
}
if($_SESSION['SyncML.state']->_isAuthorized)
Horde::logMessage('SyncML: is session authorized', __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:
/*
$str = 'localname=' . $this->_locName;
$str .= ' version=' . $this->_version;
$str .= ' msgid=' . $this->_msgID;
$str .= ' source=' . $this->_sourceURI;
$str .= ' target=' . $this->_targetURI;
$str .= ' sessionID=' . $this->_sessionID;
*/
// </SyncHdr></SyncML>
// Find the state.
$state = $this->getStateFromSession($this->_sourceURI, $this->_locName, $this->_sessionID);
$state->setVersion($this->_version);
$state->setMsgID($this->_msgID);
$state->setTargetURI($this->_targetURI);
if(isset($this->_credData) && isset($this->_locName) && !$state->isAuthorized())
{
$state->setPassword($this->_credData);
$state->setLocName($this->_locName);
}
#$str = 'authorized=' . $state->isAuthorized();
#$str .= ' version=' . $state->getVersion();
#$str .= ' msgid=' . $state->getMsgID();
#$str .= ' source=' . $state->getSourceURI();
#$str .= ' target=' . $state->getTargetURI();
#$str .= ' locName=' . $state->getLocName();
$_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>
if (trim($this->_chars) == 'SyncML/1.1') {
$this->_version = 1;
} else {
$this->_version = 0;
}
} 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;
//multisync does not specify the cred format
//if ($this->_credFormat == 'b64') {
$this->_credData = base64_decode($this->_credData);
//}
$tmp = split(':', $this->_credData);
// set only if not set by LocName already
if(!isset($this->_locName))
{
$this->_locName = $tmp[0];
}
$this->_credData = $tmp[1];
Horde::logMessage('SyncML: $this->_locName: ' . $this->_locName, __FILE__, __LINE__, PEAR_LOG_DEBUG);
}
break;
case 4:
if ($element == 'LocURI') {
if ($this->_isSource) {
// </LocURI></Source></SyncHdr></SyncML>
$this->_sourceURI = trim($this->_chars);
} else {
// </LocURI></Target></SyncHdr></SyncML>
$this->_targetURI = trim($this->_chars);
}
} elseif ($element == 'LocName') {
if ($this->_isSource) {
// </LocName></Source></SyncHdr></SyncML>
$this->_locName = trim($this->_chars);
}
} elseif ($element == 'Data') {
// </Data></Cred></SyncHdr></SyncML>
if ($this->_isCred) {
$this->_credData = trim($this->_chars);
}
}
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);
$chars = ($this->_version == 1) ? '1.1' : '1.0';
$output->characters($chars);
$output->endElement($uri, 'VerDTD');
$output->startElement($uri, 'VerProto', $attrs);
$chars = ($this->_version == 1) ? 'SyncML/1.1' : '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(!strpos($this->_targetURI,'syncit'))
#{
# $output->startElement($uri, 'RespURI', $attrs);
# $output->characters($this->_targetURI.'?syncid='.$GLOBALS['sessionid'].'-'.$GLOBALS['phpgw_info']['user']['kp3']);
# $output->characters($this->_targetURI.'?after=20040101T133000Z-syncid=lars');
# $output->characters($this->_targetURI.'?sincit=10');
# $output->characters('http://192.168.4.227/horde/rpc.php?after=20040101T133000Z-username=lars');
# $output->endElement($uri, 'RespURI');
#}
/*
$output->startElement($uri, 'Meta', $attrs);
// Dummy Max MsqSize, this is just put in to make the packet
// work, it is not a real value.
$output->startElement($uriMeta, 'MaxMsgSize', $attrs);
$chars = '50000';
$output->characters($chars);
$output->endElement($uriMeta, 'MaxMsgSize');
// Dummy MaxObjSize, this is just put in to make the packet
// work, it is not a real value.
$output->startElement($uriMeta, 'MaxObjSize', $attrs);
$chars = '4000000';
$output->characters($chars);
$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;
function startElement($uri, $element, $attrs)
{
parent::startElement($uri, $element, $attrs);
switch ($this->_xmlStack) {
case 2:
$state = & $_SESSION['SyncML.state'];
$this->_actionCommands = false; // so far, we have not seen commands that require action from our side
// <SyncML><SyncBody>
$this->_output->startElement($uri, $element, $attrs);
if($state->getLocName())
{
// 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);
/*$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);
break;
case 3:
$state = & $_SESSION['SyncML.state'];
// <SyncML><SyncBody><[Command]>
$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;
}
switch($element)
{
# case 'Final':
# if($state->getClientSyncStatus() == 1)
# {
# $state->setClientSyncStatus(2);
# }
# break;
case 'Sync':
$state->setSyncStatus(CLIENT_SYNC_STARTED);
break;
}
break;
default:
// <SyncML><SyncBody><Command><...>
$this->_currentCommand->startElement($uri, $element, $attrs);
break;
}
}
function endElement($uri, $element)
{
switch ($this->_xmlStack) {
case 2:
// </SyncBody></SyncML>
$state = & $_SESSION['SyncML.state'];
// send the sync reply
// we do still have some data to send OR
// we should reply to the Sync command
$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)
{
$final = &new Horde_SyncML_Command_Final();
$this->_currentCmdID = $final->output($this->_currentCmdID, $this->_output);
}
$this->_output->endElement($uri, $element);
Horde::logMessage('SyncML: syncStatus ' . $state->getSyncStatus() .'actionCommands: '.$this->_actionCommands, __FILE__, __LINE__, PEAR_LOG_INFO);
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
$state = & $_SESSION['SyncML.state'];
Horde::logMessage('SyncML: sync' . session_id() . ' completed successfully!', __FILE__, __LINE__, PEAR_LOG_INFO);
$state->writeSyncSummary();
$log = $state->getLog();
$s="";
foreach($log as $k => $v) {
$s .= " $k=$v";
}
Horde::logMessage('SyncML: summary:' . $s, __FILE__, __LINE__, PEAR_LOG_INFO);
// session can be closed here!
session_unset();
session_destroy();
}
break;
case 3:
// </[Command]></SyncBody></SyncML>
$state = & $_SESSION['SyncML.state'];
// this should be moved to case 2:
if($element == 'Final')
{
// make sure that we request devinfo, if we not have them already
if(!$state->getClientDeviceInfo())
{
$attrs = array();
$this->_output->startElement($state->getURI(), 'Get', $attrs);
$this->_output->startElement($state->getURI(), 'CmdID', $attrs);
$this->_output->characters($this->_currentCmdID);
$this->_currentCmdID++;
$this->_output->endElement($state->getURI(), 'CmdID');
$this->_output->startElement($state->getURI(), 'Meta', $attrs);
$this->_output->startElement($state->getURI(), 'Type', $attrs);
$this->_output->characters('application/vnd.syncml-devinf+xml');
$this->_output->endElement($state->getURI(), 'Type');
$this->_output->endElement($state->getURI(), 'Meta');
$this->_output->startElement($state->getURI(), 'Item', $attrs);
$this->_output->startElement($state->getURI(), 'Target', $attrs);
$this->_output->startElement($state->getURI(), 'LocURI', $attrs);
$this->_output->characters(($state->getVersion() == 0) ? './devinf10' : './devinf11');
$this->_output->endElement($state->getURI(), 'LocURI');
$this->_output->endElement($state->getURI(), 'Target');
$this->_output->endElement($state->getURI(), 'Item');
$this->_output->endElement($state->getURI(), 'Get');
}
}
$this->_currentCommand->endElement($uri, $element);
switch($element)
{
case 'Final':
if($state->getSyncStatus() == CLIENT_SYNC_STARTED)
{
$state->setSyncStatus(CLIENT_SYNC_FINNISHED);
}
Horde::logMessage('SyncML: Sync _syncTag = '. $state->getSyncStatus(), __FILE__, __LINE__, PEAR_LOG_INFO);
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);
}
}
}

View File

@ -0,0 +1,76 @@
<?php
include_once 'Horde/SyncML/State.php';
/**
* The Horde_SyncML_Command class provides a super class fo SyncBody commands.
*
* $Horde: framework/SyncML/SyncML/Command.php,v 1.4 2004/07/03 15:26:46 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_Command {
var $_cmdID;
var $_xmlStack;
var $_chars;
function &factory($command, $params = null)
{
include_once 'Horde/SyncML/Command/' . $command . '.php';
$class = 'Horde_SyncML_Command_' . $command;
if (class_exists($class)) {
return $cmd = &new $class($params);
} else {
Horde::logMessage('SyncML: Class definition of ' . $class . ' not found.', __FILE__, __LINE__, PEAR_LOG_ERR);
require_once 'PEAR.php';
return PEAR::raiseError('Class definition of ' . $class . ' not found.');
}
}
function output($currentCmdID, $output)
{
}
function startElement($uri, $localName, $attrs)
{
$this->_xmlStack++;
}
function endElement($uri, $element)
{
switch ($this->_xmlStack) {
case 2:
if ($element == 'CmdID') {
$this->_cmdID = intval(trim($this->_chars));
}
break;
}
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;
}
}
}

View File

@ -0,0 +1,364 @@
<?php
include_once 'Horde/SyncML/State.php';
include_once 'Horde/SyncML/Command.php';
/**
* 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.
*
* $Horde: framework/SyncML/SyncML/Command/Alert.php,v 1.18 2004/07/03 15:21:14 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_Command_Alert extends Horde_SyncML_Command {
/**
* @var integer $_alert
*/
var $_alert;
/**
* @var string $_sourceURI
*/
var $_sourceLocURI;
/**
* @var string $_targetURI
*/
var $_targetLocURI;
/**
* @var string $_metaAnchorNext
*/
var $_metaAnchorNext;
/**
* @var integer $_metaAnchorLast
*/
var $_metaAnchorLast;
/**
* Use in xml tag.
*/
var $_isInSource;
/**
* Creates a new instance of Alert.
*/
function Horde_SyncML_Command_Alert($alert = null)
{
if ($alert != null) {
$this->_alert = $alert;
}
}
function output($currentCmdID, &$output)
{
$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;
}
if($this->_alert < ALERT_RESULT_ALERT)
{
$type = $this->_targetLocURI;
// Store client's Next Anchor in State. After successful sync
// this is then written to persistence for negotiation of
// further syncs.
$state->setClientAnchorNext($type, $this->_metaAnchorNext);
$info = $state->getSyncSummary($this->_targetLocURI);
#Horde::logMessage("SyncML: Anchor match, TwoWaySync sinceee " . $clientlast, __FILE__, __LINE__, PEAR_LOG_DEBUG);
if (is_a($info, 'DataTreeObject')) {
$x = $info->get('ClientAnchor');
$clientlast = $x[$type];
$x = $info->get('ServerAnchor');
$state->setServerAnchorLast($type, $x[$type]);
} elseif (is_array($info)) {
$clientlast = $info['ClientAnchor'];
$state->setServerAnchorLast($type, $info['ServerAnchor']);
} else {
$clientlast = 0;
$state->setServerAnchorLast($type, 0);
}
// Set Server Anchor for this sync to current time.
$state->setServerAnchorNext($type,time());
if ($clientlast && $clientlast == $this->_metaAnchorLast) {
// Last Sync Anchor matches, TwoWaySync will do.
$code = RESPONSE_OK;
Horde::logMessage("SyncML: Anchor match, TwoWaySync since " . $clientlast, __FILE__, __LINE__, PEAR_LOG_DEBUG);
} else {
Horde::logMessage("SyncML: Anchor mismatch, enforcing SlowSync clientlast $clientlast serverlast ".$this->_metaAnchorLast, __FILE__, __LINE__, PEAR_LOG_DEBUG);
// Mismatch, enforce slow sync.
$this->_alert = 201;
$code = 508;
// create new synctype
$sync = &Horde_SyncML_Sync::factory($this->_alert);
$sync->_targetLocURI = $this->_targetLocURI;
$sync->_sourceLocURI = $this->_sourceLocURI;
if(isset($this->_targetLocURIParameters))
$sync->_targetLocURIParameters = $this->_targetLocURIParameters;
$state->setSync($this->_targetLocURI, $sync);
}
$status = &new Horde_SyncML_Command_Status($code, '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);
if ($state->isAuthorized()) {
$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 = $this->_alert;
$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);
$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');
$currentCmdID++;
}
}
else
{
if ($state->isAuthorized()) {
$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 = $this->_alert;
$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->endElement($state->getURI(), 'Item');
$output->endElement($state->getURI(), 'Alert');
$currentCmdID++;
}
}
return $currentCmdID;
}
/**
* Setter for property sourceURI.
*
* @param string $sourceURI New value of property sourceURI.
*/
function setSourceLocURI($sourceURI)
{
$this->_sourceLocURI = $sourceURI;
}
function getTargetLocURI()
{
return $this->_targetURI;
}
/**
* Setter for property targetURI.
*
* @param string $targetURI New value of property targetURI.
*/
// is this function still used???
function setTargetURI($targetURI)
{
$this->_targetLocURI = $targetURI;
}
/**
* Setter for property targetURI.
*
* @param string $targetURI New value of property targetURI.
*/
function setTargetLocURI($targetURI)
{
$this->_targetLocURI = $targetURI;
}
function startElement($uri, $element, $attrs)
{
parent::startElement($uri, $element, $attrs);
switch ($this->_xmlStack) {
case 3:
if ($element == 'Target') {
$this->_isInSource = false;
} else {
$this->_isInSource = true;
}
break;
}
}
function endElement($uri, $element)
{
switch ($this->_xmlStack) {
case 1:
$state = & $_SESSION['SyncML.state'];
Horde::logMessage('SyncML: looking for sync for ' . $this->_targetLocURI, __FILE__, __LINE__, PEAR_LOG_DEBUG);
$sync = $state->getSync($this->_targetLocURI);
if (!$sync) {
Horde::logMessage('SyncML: create new sync for ' . $this->_targetLocURI . ' ' . $this->_alert, __FILE__, __LINE__, PEAR_LOG_DEBUG);
$sync = &Horde_SyncML_Sync::factory($this->_alert);
$sync->_targetLocURI = $this->_targetLocURI;
$sync->_sourceLocURI = $this->_sourceLocURI;
if(isset($this->_targetLocURIParameters))
$sync->_targetLocURIParameters = $this->_targetLocURIParameters;
$state->setSync($this->_targetLocURI, $sync);
}
break;
case 2:
if ($element == 'Data') {
$this->_alert = intval(trim($this->_chars));
}
break;
case 4:
if ($element == 'LocURI') {
if ($this->_isInSource) {
$this->_sourceLocURI = trim($this->_chars);
} else {
$targetLocURIData = explode('?/',trim($this->_chars));
$this->_targetLocURI = $targetLocURIData[0];
if(isset($targetLocURIData[1]))
{
$this->_targetLocURIParameters = $targetLocURIData[1];
}
}
}
break;
case 5:
if ($element == 'Next') {
$this->_metaAnchorNext = trim($this->_chars);
} else if ($element == 'Last') {
$this->_metaAnchorLast = trim($this->_chars);
}
break;
}
parent::endElement($uri, $element);
}
function getAlert()
{
return $this->_alert;
}
function setAlert($alert)
{
$this->_alert = $alert;
}
}

View File

@ -0,0 +1,34 @@
<?php
include_once 'Horde/SyncML/Command.php';
/**
* The Horde_SyncML_Command_Final class.
*
* $Horde: framework/SyncML/SyncML/Command/Final.php,v 1.10 2004/05/26 17:41:30 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_Command_Final extends Horde_SyncML_Command {
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

@ -0,0 +1,101 @@
<?php
include_once 'Horde/SyncML/State.php';
include_once 'Horde/SyncML/Command.php';
include_once 'Horde/SyncML/Command/Results.php';
define('DEFAULT_DEFINF_10', '<DevInf xmlns="syncml:devinf"><VerDTD>1.0</VerDTD><Man>The Horde Framework</Man><DevID>4711</DevID><DevTyp>workstation</DevTyp><DataStore><SourceRef>./contacts</SourceRef><Rx-Pref><CTType>text/x-vcard</CTType><VerCT>2.1</VerCT></Rx-Pref><Tx-Pref><CTType>text/x-vcard</CTType><VerCT>2.1</VerCT></Tx-Pref><SyncCap><SyncType>1</SyncType><SyncType>2</SyncType><SyncType>3</SyncType><SyncType>4</SyncType><SyncType>5</SyncType><SyncType>6</SyncType><SyncType>7</SyncType></SyncCap></DataStore><DataStore><SourceRef>./calendar</SourceRef><Rx-Pref><CTType>text/x-vcalendar</CTType><VerCT>2.0</VerCT></Rx-Pref><Rx><CTType>text/x-vcalendar</CTType><VerCT>1.0</VerCT></Rx><Tx-Pref><CTType>text/x-vcalendar</CTType><VerCT>2.0</VerCT></Tx-Pref><Tx><CTType>text/x-vcalendar</CTType><VerCT>1.0</VerCT></Tx><SyncCap><SyncType>1</SyncType><SyncType>2</SyncType><SyncType>3</SyncType><SyncType>4</SyncType><SyncType>5</SyncType><SyncType>6</SyncType><SyncType>7</SyncType></SyncCap></DataStore><CTCap><CTType>text/x-vcalendar</CTType><PropName>BEGIN</PropName><ValEnum>VCALENDAR</ValEnum><ValEnum>VEVENT</ValEnum><ValEnum>VTODO</ValEnum><PropName>DTSTART</PropName><PropName>DTEND</PropName><PropName>DTSTAMP</PropName><PropName>SEQUENCE</PropName><PropName>END</PropName><ValEnum>VCALENDAR</ValEnum><ValEnum>VEVENT</ValEnum><ValEnum>VTODO</ValEnum><PropName>UID</PropName><PropName>SUMMARY</PropName><PropName>VERSION</PropName><ValEnum>1.0</ValEnum><PropName>AALARM</PropName><PropName>CATEGORIES</PropName><PropName>CLASS</PropName><PropName>DALARM</PropName><PropName>EXDATE</PropName><PropName>RESOURCES</PropName><PropName>STATUS</PropName><PropName>ATTACH</PropName><PropName>ATTENDEE</PropName><PropName>DCREATED</PropName><PropName>COMPLETED</PropName><PropName>DESCRIPTION</PropName><PropName>DUE</PropName><PropName>LAST-MODIFIED</PropName><PropName>LOCATION</PropName><PropName>PRIORITY</PropName><PropName>RELATED-TO</PropName><PropName>RRULE</PropName><PropName>TRANSP</PropName><PropName>URL</PropName></CTCap><CTCap><CTType>text/calendar</CTType><PropName>BEGIN</PropName><ValEnum>VCALENDAR</ValEnum><ValEnum>VEVENT</ValEnum><ValEnum>VTODO</ValEnum><ValEnum>VALARM</ValEnum><PropName>DTSTART</PropName><PropName>DTEND</PropName><PropName>DTSTAMP</PropName><PropName>SEQUENCE</PropName><PropName>END</PropName><ValEnum>VCALENDAR</ValEnum><ValEnum>VEVENT</ValEnum><ValEnum>VTODO</ValEnum><ValEnum>VALARM</ValEnum><PropName>UID</PropName><PropName>SUMMARY</PropName><PropName>VERSION</PropName><ValEnum>2.0</ValEnum><PropName>CATEGORIES</PropName><PropName>CLASS</PropName><PropName>DALARM</PropName><PropName>EXDATE</PropName><PropName>RESOURCES</PropName><PropName>STATUS</PropName><PropName>ATTACH</PropName><PropName>ATTENDEE</PropName><PropName>DCREATED</PropName><PropName>COMPLETED</PropName><PropName>DESCRIPTION</PropName><PropName>DUE</PropName><PropName>LAST-MODIFIED</PropName><PropName>LOCATION</PropName><PropName>PRIORITY</PropName><PropName>RELATED-TO</PropName><PropName>TRANSP</PropName><PropName>URL</PropName><PropName>RRULE</PropName><PropName>COMMMENT</PropName><PropName>ACTION</PropName><PropName>TRIGGER</PropName><PropName>DURATION</PropName><PropName>REPEAT</PropName></CTCap><CTCap><CTType>text/x-vcard</CTType><PropName>BEGIN</PropName><ValEnum>VCARD</ValEnum><PropName>END</PropName><ValEnum>VCARD</ValEnum><PropName>VERSION</PropName><ValEnum>2.1</ValEnum><PropName>ENCODING</PropName><PropName>VALUE</PropName><PropName>CHARSET</PropName><PropName>FN</PropName><PropName>N</PropName><PropName>NAME</PropName><PropName>NICKNAME</PropName><PropName>PHOTO</PropName><PropName>BDAY</PropName><PropName>ADR</PropName><PropName>LABEL</PropName><PropName>TEL</PropName><PropName>EMAIL</PropName><PropName>MAILER</PropName><PropName>TZ</PropName><PropName>GEO</PropName><PropName>TITLE</PropName><PropName>ROLE</PropName><PropName>LOGO</PropName><PropName>AGENT</PropName><PropName>ORG</PropName><PropName>CATEGORIES</PropName><PropName>NOTE</PropName><PropName>PRODID</PropName><PropName>REV</PropName><PropName>SORT-STRING</PropName><PropName>SOUND</PropName><PropName>URL</PropName><PropName>UID</PropName><PropName>CLASS</PropName><PropName>KEY</PropName></CTCap></DevInf>');
define('DEFAULT_DEFINF_11', '<DevInf xmlns="syncml:devinf"><VerDTD>1.1</VerDTD><Man>The Horde Framework</Man><DevID>4711</DevID><DevTyp>workstation</DevTyp><DataStore><SourceRef>./contacts</SourceRef><Rx-Pref><CTType>text/x-vcard</CTType><VerCT>2.1</VerCT></Rx-Pref><Tx-Pref><CTType>text/x-vcard</CTType><VerCT>2.1</VerCT></Tx-Pref><SyncCap><SyncType>1</SyncType><SyncType>2</SyncType><SyncType>3</SyncType><SyncType>4</SyncType><SyncType>5</SyncType><SyncType>6</SyncType><SyncType>7</SyncType></SyncCap></DataStore><DataStore><SourceRef>./calendar</SourceRef><Rx-Pref><CTType>text/x-vcalendar</CTType><VerCT>2.0</VerCT></Rx-Pref><Rx><CTType>text/x-vcalendar</CTType><VerCT>1.0</VerCT></Rx><Tx-Pref><CTType>text/x-vcalendar</CTType><VerCT>2.0</VerCT></Tx-Pref><Tx><CTType>text/x-vcalendar</CTType><VerCT>1.0</VerCT></Tx><SyncCap><SyncType>1</SyncType><SyncType>2</SyncType><SyncType>3</SyncType><SyncType>4</SyncType><SyncType>5</SyncType><SyncType>6</SyncType><SyncType>7</SyncType></SyncCap></DataStore><CTCap><CTType>text/x-vcalendar</CTType><PropName>BEGIN</PropName><ValEnum>VCALENDAR</ValEnum><ValEnum>VEVENT</ValEnum><ValEnum>VTODO</ValEnum><PropName>DTSTART</PropName><PropName>DTEND</PropName><PropName>DTSTAMP</PropName><PropName>SEQUENCE</PropName><PropName>END</PropName><ValEnum>VCALENDAR</ValEnum><ValEnum>VEVENT</ValEnum><ValEnum>VTODO</ValEnum><PropName>UID</PropName><PropName>SUMMARY</PropName><PropName>VERSION</PropName><ValEnum>1.0</ValEnum><PropName>AALARM</PropName><PropName>CATEGORIES</PropName><PropName>CLASS</PropName><PropName>DALARM</PropName><PropName>EXDATE</PropName><PropName>RESOURCES</PropName><PropName>STATUS</PropName><PropName>ATTACH</PropName><PropName>ATTENDEE</PropName><PropName>DCREATED</PropName><PropName>COMPLETED</PropName><PropName>DESCRIPTION</PropName><PropName>DUE</PropName><PropName>LAST-MODIFIED</PropName><PropName>LOCATION</PropName><PropName>PRIORITY</PropName><PropName>RELATED-TO</PropName><PropName>RRULE</PropName><PropName>TRANSP</PropName><PropName>URL</PropName></CTCap><CTCap><CTType>text/calendar</CTType><PropName>BEGIN</PropName><ValEnum>VCALENDAR</ValEnum><ValEnum>VEVENT</ValEnum><ValEnum>VTODO</ValEnum><ValEnum>VALARM</ValEnum><PropName>DTSTART</PropName><PropName>DTEND</PropName><PropName>DTSTAMP</PropName><PropName>SEQUENCE</PropName><PropName>END</PropName><ValEnum>VCALENDAR</ValEnum><ValEnum>VEVENT</ValEnum><ValEnum>VTODO</ValEnum><ValEnum>VALARM</ValEnum><PropName>UID</PropName><PropName>SUMMARY</PropName><PropName>VERSION</PropName><ValEnum>2.0</ValEnum><PropName>CATEGORIES</PropName><PropName>CLASS</PropName><PropName>DALARM</PropName><PropName>EXDATE</PropName><PropName>RESOURCES</PropName><PropName>STATUS</PropName><PropName>ATTACH</PropName><PropName>ATTENDEE</PropName><PropName>DCREATED</PropName><PropName>COMPLETED</PropName><PropName>DESCRIPTION</PropName><PropName>DUE</PropName><PropName>LAST-MODIFIED</PropName><PropName>LOCATION</PropName><PropName>PRIORITY</PropName><PropName>RELATED-TO</PropName><PropName>TRANSP</PropName><PropName>URL</PropName><PropName>RRULE</PropName><PropName>COMMMENT</PropName><PropName>ACTION</PropName><PropName>TRIGGER</PropName><PropName>DURATION</PropName><PropName>REPEAT</PropName></CTCap><CTCap><CTType>text/x-vcard</CTType><PropName>BEGIN</PropName><ValEnum>VCARD</ValEnum><PropName>END</PropName><ValEnum>VCARD</ValEnum><PropName>VERSION</PropName><ValEnum>2.1</ValEnum><PropName>ENCODING</PropName><PropName>VALUE</PropName><PropName>CHARSET</PropName><PropName>FN</PropName><PropName>N</PropName><PropName>NAME</PropName><PropName>NICKNAME</PropName><PropName>PHOTO</PropName><PropName>BDAY</PropName><PropName>ADR</PropName><PropName>LABEL</PropName><PropName>TEL</PropName><PropName>EMAIL</PropName><PropName>MAILER</PropName><PropName>TZ</PropName><PropName>GEO</PropName><PropName>TITLE</PropName><PropName>ROLE</PropName><PropName>LOGO</PropName><PropName>AGENT</PropName><PropName>ORG</PropName><PropName>CATEGORIES</PropName><PropName>NOTE</PropName><PropName>PRODID</PropName><PropName>REV</PropName><PropName>SORT-STRING</PropName><PropName>SOUND</PropName><PropName>URL</PropName><PropName>UID</PropName><PropName>CLASS</PropName><PropName>KEY</PropName></CTCap></DevInf>');
#define('DEFAULT_DEFINF', '<DevInf xmlns="syncml:devinf"><VerDTD>1.0</VerDTD><Man>The Horde Framework</Man><DevID>4711</DevID>'.
#'<DevTyp>workstation</DevTyp><DataStore><SourceRef>contacts</SourceRef><Rx-Pref><CTType>text/x-vcard</CTType><VerCT>2.1</VerCT>'.
#'</Rx-Pref><Tx-Pref><CTType>text/x-vcard</CTType><VerCT>2.1</VerCT></Tx-Pref><SyncCap><SyncType>1</SyncType><SyncType>2</SyncType><SyncType>7</SyncType></SyncCap>'.
#'</DataStore>'.
#
#'<DataStore><SourceRef>calendar</SourceRef><Rx-Pref><CTType>text/x-vcalendar</CTType><VerCT>2.0</VerCT></Rx-Pref><Rx>'.
#'<CTType>text/x-vcalendar</CTType><VerCT>1.0</VerCT></Rx><Tx-Pref><CTType>text/x-vcalendar</CTType><VerCT>2.0</VerCT></Tx-Pref>'.
#'<Tx><CTType>text/x-vcalendar</CTType><VerCT>1.0</VerCT></Tx><SyncCap><SyncType>1</SyncType><SyncType>7</SyncType></SyncCap></DataStore>'.
#
#'<CTCap><CTType>text/x-vcalendar</CTType><PropName>BEGIN</PropName><ValEnum>VCALENDAR</ValEnum><ValEnum>VEVENT</ValEnum>'.
#'<ValEnum>VTODO</ValEnum><PropName>DTSTART</PropName><PropName>DTEND</PropName><PropName>DTSTAMP</PropName><PropName>SEQUENCE</PropName>'.
#'<PropName>END</PropName><ValEnum>VCALENDAR</ValEnum><ValEnum>VEVENT</ValEnum><ValEnum>VTODO</ValEnum><PropName>UID</PropName><PropName>'.
#'SUMMARY</PropName><PropName>VERSION</PropName><ValEnum>1.0</ValEnum><PropName>AALARM</PropName><PropName>CATEGORIES</PropName><PropName>',
#'CLASS</PropName><PropName>DALARM</PropName><PropName>EXDATE</PropName><PropName>RESOURCES</PropName><PropName>STATUS</PropName><PropName>',
#'ATTACH</PropName><PropName>ATTENDEE</PropName><PropName>DCREATED</PropName><PropName>COMPLETED</PropName><PropName>DESCRIPTION</PropName>'.
#'<PropName>DUE</PropName><PropName>LAST-MODIFIED</PropName><PropName>LOCATION</PropName><PropName>PRIORITY</PropName>'.
#'<PropName>RELATED-TO</PropName><PropName>RRULE</PropName><PropName>TRANSP</PropName><PropName>URL</PropName></CTCap><CTCap>'.
#'<CTType>text/calendar</CTType><PropName>BEGIN</PropName><ValEnum>VCALENDAR</ValEnum><ValEnum>VEVENT</ValEnum><ValEnum>VTODO</ValEnum>'.
#'<ValEnum>VALARM</ValEnum><PropName>DTSTART</PropName><PropName>DTEND</PropName><PropName>DTSTAMP</PropName><PropName>SEQUENCE</PropName>'.
#'<PropName>END</PropName><ValEnum>VCALENDAR</ValEnum><ValEnum>VEVENT</ValEnum><ValEnum>VTODO</ValEnum><ValEnum>VALARM</ValEnum>'.
#'<PropName>UID</PropName><PropName>SUMMARY</PropName><PropName>VERSION</PropName><ValEnum>2.0</ValEnum><PropName>CATEGORIES</PropName>'.
#'<PropName>CLASS</PropName><PropName>DALARM</PropName><PropName>EXDATE</PropName><PropName>RESOURCES</PropName><PropName>STATUS</PropName>'.
#'<PropName>ATTACH</PropName><PropName>ATTENDEE</PropName><PropName>DCREATED</PropName><PropName>COMPLETED</PropName><PropName>DESCRIPTION'.
#'</PropName><PropName>DUE</PropName><PropName>LAST-MODIFIED</PropName><PropName>LOCATION</PropName><PropName>PRIORITY</PropName>'.
#'<PropName>RELATED-TO</PropName><PropName>TRANSP</PropName><PropName>URL</PropName><PropName>RRULE</PropName><PropName>COMMMENT</PropName>'.
#'<PropName>ACTION</PropName><PropName>TRIGGER</PropName><PropName>DURATION</PropName><PropName>REPEAT</PropName></CTCap><CTCap>'.
#
#'<CTType>text/x-vcard</CTType><PropName>BEGIN</PropName><ValEnum>VCARD</ValEnum><PropName>END</PropName><ValEnum>VCARD</ValEnum><PropName>'.
#'VERSION</PropName><ValEnum>2.1</ValEnum><PropName>ENCODING</PropName><PropName>VALUE</PropName><PropName>CHARSET</PropName>'.
#'<PropName>FN</PropName><PropName>N</PropName><PropName>NAME</PropName><PropName>NICKNAME</PropName><PropName>PHOTO</PropName>'.
#'<PropName>BDAY</PropName><PropName>ADR</PropName><PropName>LABEL</PropName><PropName>TEL</PropName><PropName>EMAIL</PropName>'.
#'<PropName>MAILER</PropName><PropName>TZ</PropName><PropName>GEO</PropName><PropName>TITLE</PropName><PropName>ROLE</PropName>'.
#'<PropName>LOGO</PropName><PropName>AGENT</PropName><PropName>ORG</PropName><PropName>CATEGORIES</PropName><PropName>NOTE</PropName>'.
#'<PropName>PRODID</PropName><PropName>REV</PropName><PropName>SORT-STRING</PropName><PropName>SOUND</PropName><PropName>URL</PropName>'.
#'<PropName>UID</PropName><PropName>CLASS</PropName><PropName>KEY</PropName></CTCap></DevInf>');
/**
* The Horde_SyncML_Command_Get class.
*
* $Horde: framework/SyncML/SyncML/Command/Get.php,v 1.14 2004/07/02 19:24:44 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>
* @author Karsten Fourmont <fourmont@gmx.de>
* @version $Revision$
* @since Horde 3.0
* @package Horde_SyncML
*/
class Horde_SyncML_Command_Get extends Horde_SyncML_Command {
function output($currentCmdID, &$output)
{
$state = $_SESSION['SyncML.state'];
$ref = ($state->getVersion() == 0) ? './devinf10' : './devinf11';
$status = &new Horde_SyncML_Command_Status((($state->isAuthorized()) ? RESPONSE_OK : RESPONSE_INVALID_CREDENTIALS), 'Get');
$status->setCmdRef($this->_cmdID);
$status->setTargetRef($ref);
$currentCmdID = $status->output($currentCmdID, $output);
Horde::logMessage('SyncML: end output ref: '.$ref, __FILE__, __LINE__, PEAR_LOG_DEBUG);
// Currently DEVINF seems to be ok only for SyncML 1.0. But
// this is used by P800/P900 and these seem to require it:
if ($state->isAuthorized() && $state->getVersion() == 0) {
$results = &new Horde_SyncML_Command_Results();
$results->setCmdRef($this->_cmdID);
$results->setType("application/vnd.syncml-devinf+xml");
$results->setlocSourceURI($ref);
$results->setData(DEFAULT_DEFINF_10);
$currentCmdID = $results->output($currentCmdID, $output);
}
elseif($state->isAuthorized() && $state->getVersion() == 1)
{
$results = &new Horde_SyncML_Command_Results();
$results->setCmdRef($this->_cmdID);
$results->setType("application/vnd.syncml-devinf+xml");
$results->setlocSourceURI($ref);
$results->setData(DEFAULT_DEFINF_11);
$currentCmdID = $results->output($currentCmdID, $output);
}
return $currentCmdID;
}
}

View File

@ -0,0 +1,180 @@
<?php
include_once 'Horde/SyncML/State.php';
include_once 'Horde/SyncML/Command.php';
/**
* 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.
*
* $Horde: framework/SyncML/SyncML/Command/Map.php,v 1.1 2004/07/02 19:24:44 chuck Exp $
*
* Copyright 2004 Karsten Fourmont <fourmont@gmx.de>
*
* 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 <fourmont@gmx.de>
* @version $Revision$
* @since Horde 3.0
* @package Horde_SyncML
*/
class Horde_SyncML_Command_Map extends Horde_SyncML_Command {
/**
* @var string $_sourceURI
*/
var $_sourceLocURI;
/**
* @var string $_targetURI
*/
var $_targetLocURI;
/**
* Use in xml tag.
*/
var $_isInSource;
var $_mapTarget;
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;
}
/**
* Setter for property sourceURI.
*
* @param string $sourceURI New value of property sourceURI.
*/
function setSourceLocURI($sourceURI)
{
$this->_sourceURI = $sourceURI;
}
function getTargetLocURI()
{
return $this->_targetURI;
}
/**
* Setter for property targetURI.
*
* @param string $targetURI New value of property targetURI.
*/
function setTargetURI($targetURI)
{
$this->_targetURI = $targetURI;
}
function startElement($uri, $element, $attrs)
{
parent::startElement($uri, $element, $attrs);
switch ($this->_xmlStack) {
case 2:
if ($element == 'Target') {
$this->_isInSource = false;
}
if ($element == 'Source') {
$this->_isInSource = true;
}
if ($element == 'MapItem') {
unset($this->_mapTarget);
unset($this->_mapSource);
}
break;
case 3:
if ($element == 'Target') {
$this->_isInSource = false;
}
if ($element == 'Source') {
$this->_isInSource = true;
}
break;
}
}
function endElement($uri, $element)
{
switch ($this->_xmlStack) {
case 1:
$state = $_SESSION['SyncML.state'];
$sync = $state->getSync($this->_targetLocURI);
if (!$sync) {
}
$_SESSION['SyncML.state'] = $state;
break;
case 2:
if ($element == 'MapItem') {
$state = $_SESSION['SyncML.state'];
$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:
$r = $state->setUID($this->_targetLocURI, $this->_mapSource, $this->_mapTarget);
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->_isInSource) {
$this->_sourceLocURI = trim($this->_chars);
} else {
$targetLocURIData = explode('?/',trim($this->_chars));
$this->_targetLocURI = $targetLocURIData[0];
if(isset($targetLocURIData[1]))
{
$this->_targetLocURIParameters = $targetLocURIData[1];
}
}
}
break;
case 4:
if ($element == 'LocURI') {
if ($this->_isInSource) {
$this->_mapSource = trim($this->_chars);
} else {
$this->_mapTarget = trim($this->_chars);
}
}
break;
}
parent::endElement($uri, $element);
}
}

View File

@ -0,0 +1,157 @@
<?php
include_once 'Horde/SyncML/State.php';
include_once 'Horde/SyncML/Command.php';
/**
* $Horde: framework/SyncML/SyncML/Command/Put.php,v 1.12 2004/07/02 19:24:44 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_Command_Put extends Horde_SyncML_Command {
/**
* @var string $_manufacturer
*/
var $_manufacturer;
/**
* @var string $_model
*/
var $_model;
/**
* @var string $_oem
*/
var $_oem;
/**
* @var string $_softwareVersion
*/
var $_softwareVersion;
function endElement($uri, $element)
{
#Horde::logMessage('SyncML: put endelement ' . $element . ' stack ' . $this->_xmlStack, __FILE__, __LINE__, PEAR_LOG_DEBUG);
switch ($this->_xmlStack) {
case 5:
switch($element) {
case 'DataStore':
$this->_deviceInfo['dataStore'][$this->_sourceReference] = array(
'maxGUIDSize' => $this->_maxGUIDSize,
'rxPreference' => $this->_rxPreference,
'txPreference' => $this->_txPreference,
'syncCapabilities' => $this->_syncCapabilities,
);
break;
case 'DevID':
$this->_deviceInfo['deviceID'] = trim($this->_chars);
break;
case 'DevTyp':
$this->_deviceInfo['deviceType'] = 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 '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 = 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);
break;
case 'SyncType':
$this->_syncCapabilities[] = trim($this->_chars);
break;
case 'VerCT':
$this->_contentVersion = trim($this->_chars);
break;
}
break;
}
parent::endElement($uri, $element);
}
function output($currentCmdID, &$output )
{
$state = &$_SESSION['SyncML.state'];
$status = &new Horde_SyncML_Command_Status((($state->isAuthorized()) ? RESPONSE_OK : RESPONSE_INVALID_CREDENTIALS), 'Put');
$status->setCmdRef($this->_cmdID);
$ref = ($state->getVersion() == 0) ? './devinf10' : './devinf11';
$status->setSourceRef($ref);
if($state->isAuthorized())
{
if(count((array)$this->_deviceInfo) > 0)
{
$state->setClientDeviceInfo($this->_deviceInfo);
$state->writeClientDeviceInfo();
}
}
return $status->output($currentCmdID, $output);
}
function startElement($uri, $element, $attrs)
{
#Horde::logMessage('SyncML: put startelement ' . $element, __FILE__, __LINE__, PEAR_LOG_DEBUG);
parent::startElement($uri, $element, $attrs);
}
}

View File

@ -0,0 +1,25 @@
<?php
include_once 'Horde/SyncML/Command.php';
/**
* $Horde: framework/SyncML/SyncML/Command/Replace.php,v 1.7 2004/05/26 17:41:30 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_Command_Final extends Horde_SyncML_Command {
function output($currentCmdID, &$output)
{
return $currentCmdID;
}
}

View File

@ -0,0 +1,229 @@
<?php
include_once 'Horde/SyncML/State.php';
include_once 'Horde/SyncML/Command.php';
/**
* $Horde: framework/SyncML/SyncML/Command/Results.php,v 1.11 2004/07/02 19:24:44 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_Command_Results extends Horde_SyncML_Command {
var $_cmdRef;
var $_type;
var $_data;
var $_locSourceURI;
var $_deviceInfo;
function endElement($uri, $element)
{
#Horde::logMessage('SyncML: put endelement ' . $element . ' stack ' . $this->_xmlStack, __FILE__, __LINE__, PEAR_LOG_DEBUG);
switch ($this->_xmlStack) {
case 5:
switch($element) {
case 'DataStore':
$this->_deviceInfo['dataStore'][$this->_sourceReference] = array(
'maxGUIDSize' => $this->_maxGUIDSize,
'rxPreference' => $this->_rxPreference,
'txPreference' => $this->_txPreference,
'syncCapabilities' => $this->_syncCapabilities,
);
break;
case 'DevID':
$this->_deviceInfo['deviceID'] = trim($this->_chars);
break;
case 'DevTyp':
$this->_deviceInfo['deviceType'] = 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 '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 = 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);
break;
case 'SyncType':
$this->_syncCapabilities[] = trim($this->_chars);
break;
case 'VerCT':
$this->_contentVersion = trim($this->_chars);
break;
}
break;
}
parent::endElement($uri, $element);
}
function output($currentCmdID, &$output)
{
if(!isset($this->_locSourceURI))
{
Horde::logMessage('SyncML: BIG TODO!!!!!!!!!!!!!!!!!! parse reply', __FILE__, __LINE__, PEAR_LOG_DEBUG);
$state = &$_SESSION['SyncML.state'];
$status = &new Horde_SyncML_Command_Status((($state->isAuthorized()) ? RESPONSE_OK : RESPONSE_INVALID_CREDENTIALS), 'Results');
$status->setCmdRef($this->_cmdID);
$ref = ($state->getVersion() == 0) ? './devinf10' : './devinf11';
$status->setSourceRef($ref);
if($state->isAuthorized())
{
if(count((array)$this->_deviceInfo) > 0)
{
$state->setClientDeviceInfo($this->_deviceInfo);
$state->writeClientDeviceInfo();
}
}
return $status->output($currentCmdID, $output);
}
else
{
Horde::logMessage('SyncML: BIG TODO!!!!!!!!!!!!!!!!!! generate reponse', __FILE__, __LINE__, PEAR_LOG_DEBUG);
$state = $_SESSION['SyncML.state'];
$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->_cmdRef;
$output->characters($chars);
$output->endElement($state->getURI(), 'CmdRef');
$output->startElement($state->getURI(), 'Meta', $attrs);
$output->startElement($state->getURIMeta(), 'Type', $attrs);
$output->characters($this->_type);
$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);
$chars = $this->_locSourceURI;
$output->characters($chars);
$output->endElement($state->getURI(), 'LocURI');
$output->endElement($state->getURI(), 'Source');
$output->startElement($state->getURI(), 'Data', $attrs);
// Need to send this information as opaque data so the WBXML
// will understand it.
$output->opaque($this->_data);
$output->endElement($state->getURI(), 'Data');
$output->endElement($state->getURI(), 'Item');
$output->endElement($state->getURI(), 'Results');
$currentCmdID++;
return $currentCmdID;
}
}
/**
* Setter for property cmdRef.
*
* @param string $cmdRef New value of property cmdRef.
*/
function setCmdRef($cmdRef)
{
$this->_cmdRef = $cmdRef;
}
/**
* Setter for property Type.
*
* @param string $type New value of property type.
*/
function setType($type)
{
$this->_type = $type;
}
/**
* Setter for property data.
*
* @param string $data New value of property data.
*/
function setData($data)
{
$this->_data = $data;
}
/**
* Setter for property locSourceURI.
*
* @param string $locSourceURI New value of property locSourceURI.
*/
function setlocSourceURI($locSourceURI)
{
$this->_locSourceURI = $locSourceURI;
}
}

View File

@ -0,0 +1,251 @@
<?php
include_once 'Horde/SyncML/State.php';
include_once 'Horde/SyncML/Command.php';
/**
* $Horde: framework/SyncML/SyncML/Command/Status.php,v 1.15 2004/07/02 19:24:44 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_Command_Status extends Horde_SyncML_Command {
var $_response;
var $_cmdRef;
/**
* Must be present.
*/
var $_cmd;
/**
* Must if not null (what does this mean?).
*/
var $_sourceRef;
var $_targetRef;
var $_chalMetaFormat;
var $_chalMetaType;
var $_chalMetaNextNonce;
var $_itemDataAnchorNext;
var $_itemDataAnchorLast;
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)
{
$attrs = array();
$state = $_SESSION['SyncML.state'];
if ($this->_cmd != null) {
$attrs = array();
$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->_sourceRef)) {
$output->startElement($state->getURI(), 'SourceRef', $attrs);
$chars = $this->_sourceRef;
$output->characters($chars);
$output->endElement($state->getURI(), 'SourceRef');
}
if (isset($this->_targetRef)) {
$output->startElement($state->getURI(), 'TargetRef', $attrs);
$chars = $this->_targetRef;
$output->characters($chars);
$output->endElement($state->getURI(), 'TargetRef');
}
// 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');
}
$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;
}
}

View File

@ -0,0 +1,222 @@
<?php
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';
/**
* $Horde: framework/SyncML/SyncML/Command/Sync.php,v 1.17 2004/07/03 15:21:14 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_Command_Sync extends Horde_Syncml_Command {
var $_isInSource;
var $_currentSyncElement;
var $_syncElements = array();
function output($currentCmdID, &$output)
{
$state = &$_SESSION['SyncML.state'];
$attrs = array();
Horde::logMessage('SyncML: $this->_targetURI = ' . $this->_targetURI, __FILE__, __LINE__, PEAR_LOG_DEBUG);
$status = &new Horde_SyncML_Command_Status(RESPONSE_OK, 'Sync');
// $status->setState($state);
$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);
$sync = $state->getSync($this->_targetURI);
$currentCmdID = $sync->startSync($currentCmdID, $output);
foreach ($this->_syncElements as $element ) {
$currentCmdID = $sync->nextSyncCommand($currentCmdID, $element, $output);
}
return $currentCmdID;
}
function getTargetURI()
{
return $this->_targetURI;
}
function startElement($uri, $element, $attrs)
{
parent::startElement($uri, $element, $attrs);
switch ($this->_xmlStack) {
case 2:
if ($element == 'Replace' || $element == 'Add' || $element == 'Delete') {
$this->_currentSyncElement = &Horde_SyncML_Command_Sync_SyncElement::factory($element);
// $this->_currentSyncElement->setVersion($this->_version);
// $this->_currentSyncElement->setCmdRef($this->_cmdID);
// $this->_currentSyncElement->setMsgID($this->_msgID);
} elseif ($element == 'Target') {
$this->_isInSource = false;
} else {
$this->_isInSource = true;
}
break;
}
if (isset($this->_currentSyncElement)) {
$this->_currentSyncElement->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_DATA_PENDING)
{
##############
$targets = $state->getTargets();
Horde::logMessage('SyncML: starting sync to client '.$targets[0], __FILE__, __LINE__, PEAR_LOG_DEBUG);
$attrs = array();
foreach($targets as $target)
{
$sync = $state->getSync($target);
$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 = $sync->_targetLocURI;
$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();
$output->startElement($state->getURI(), 'NumberOfChanged', $attrs);
$output->characters($numberOfItems);
$output->endElement($state->getURI(), 'NumberOfChanged');
}
$currentCmdID = $sync->endSync($currentCmdID, $output);
$output->endElement($state->getURI(), 'Sync');
if($currentCmdID > MAX_DATA) break;
}
#Horde::logMessage('SyncML: ending sync to client '.$targets[0], __FILE__, __LINE__, PEAR_LOG_DEBUG);
// no syncs left
if($state->getTargets() === FALSE)
$state->setSyncStatus(SERVER_SYNC_FINNISHED);
#############################
}
# elseif($state->getSyncStatus() == CLIENT_SYNC_STARTED)
# {
# Horde::logMessage('SyncML: client alert '.$state->_currentSourceURI, __FILE__, __LINE__, PEAR_LOG_DEBUG);
# Horde::logMessage('SyncML: client alert '.$state->_currentTargetURI, __FILE__, __LINE__, PEAR_LOG_DEBUG);
# Horde::logMessage('SyncML: client alert '.$state->_currentTargetURIParameters, __FILE__, __LINE__, PEAR_LOG_DEBUG);
# $alert = &new Horde_SyncML_Command_Alert(ALERT_NEXT_MESSAGE);
# $alert->setSourceLocURI($state->_currentSourceURI);
# $alert->setTargetLocURI((isset($state->_currentTargetURIParameters) ? $state->_currentTargetURI.'?/'.$state->_currentTargetURIParameters : $state->_currentTargetURI));
# $currentCmdID = $alert->output($currentCmdID, $output);
# }
return $currentCmdID;
}
function endElement($uri, $element)
{
if (isset($this->_currentSyncElement)) {
$this->_currentSyncElement->endElement($uri, $element);
}
switch ($this->_xmlStack) {
case 2:
if ($element == 'Replace' || $element == 'Add' || $element == 'Delete') {
$this->_syncElements[] = $this->_currentSyncElement;
unset($this->_currentSyncElement);
}
break;
case 3:
$state = & $_SESSION['SyncML.state'];
if ($element == 'LocURI' && !isset($this->_currentSyncElement)) {
if ($this->_isInSource) {
$this->_sourceURI = trim($this->_chars);
$state->_currentSourceURI = $this->_sourceURI;
} else {
$this->_targetURI = trim($this->_chars);
$targetURIData = explode('?/',trim($this->_chars));
$this->_targetURI = $targetURIData[0];
$state->_currentTargetURI = $this->_targetURI;
if(isset($targetURIData[1]))
{
$this->_targetURIParameters = $targetURIData[1];
$state->_currentTargetURIParameters = $this->_targetURIParameters;
}
}
}
break;
}
parent::endElement($uri, $element);
}
function characters($str)
{
if (isset($this->_currentSyncElement)) {
$this->_currentSyncElement->characters($str);
} else {
if (isset($this->_chars)) {
$this->_chars = $this->_chars . $str;
} else {
$this->_chars = $str;
}
}
}
}

View File

@ -0,0 +1,31 @@
<?php
include_once 'Horde/SyncML/Command/Sync/SyncElement.php';
/**
* $Horde: framework/SyncML/SyncML/Command/Sync/Add.php,v 1.10 2004/07/02 19:24:44 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_Command_Sync_Add extends Horde_SyncML_Command_Sync_SyncElement {
function output($currentCmdID, &$output)
{
$status = &new Horde_SyncML_Command_Status(RESPONSE_ITEM_ADDED, 'Add');
$status->setCmdRef($this->_cmdID);
if (isset($this->_luid)) {
$status->setSourceRef($this->_luid);
}
return $status->output($currentCmdID, $output);
}
}

View File

@ -0,0 +1,144 @@
<?php
include_once 'Horde/SyncML/State.php';
include_once 'Horde/SyncML/Command/Sync/SyncElement.php';
/**
* $Horde: framework/SyncML/SyncML/Command/Sync/ContentSyncElement.php,v 1.12 2004/07/02 19:24:44 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_Command_Sync_ContentSyncElement extends Horde_SyncML_Command_Sync_SyncElement {
/**
* The content: vcard data, etc.
*/
var $_content;
/**
* Local to server: our Horde guid.
*/
var $_locURI;
var $_targetURI;
var $_contentType;
function setSourceURI($uri)
{
$this->_locURI = $uri;
}
function getSourceURI()
{
return $this->_locURI;
}
function setTargetURI($uri)
{
$this->_targetURI = $uri;
}
function getTargetURI()
{
return $this->_targetURI;
}
function setContentType($c)
{
$this->_contentType = $c;
}
function getContentType()
{
return $this->_contentType;
}
function getContent()
{
return $this->_content;
}
function setContent($content)
{
$this->_content = $content;
}
function endElement($uri, $element)
{
switch ($this->_xmlStack) {
case 2:
if ($element == 'Data') {
$this->_content = trim($this->_chars);
}
break;
}
parent::endElement($uri, $element);
}
function outputCommand($currentCmdID, &$output, $command)
{
$state = $_SESSION['SyncML.state'];
$attrs = array();
$output->startElement($state->getURI(), $command, $attrs);
$output->startElement($state->getURI(), 'CmdID', $attrs);
$chars = $currentCmdID;
$output->characters($chars);
$output->endElement($state->getURI(), 'CmdID');
if (isset($this->_contentType)) {
$output->startElement($state->getURI(), 'Meta', $attrs);
$output->startElement($state->getURIMeta(), 'Type', $attrs);
$output->characters($this->_contentType);
$output->endElement($state->getURIMeta(), 'Type');
$output->endElement($state->getURI(), 'Meta');
}
if (isset($this->_content)
|| isset($this->_locURI) || isset($this->targetURI)) {
$output->startElement($state->getURI(), 'Item', $attrs);
// send only when sending adds
if ($this->_locURI != null && strtolower($command) == 'add') {
$output->startElement($state->getURI(), 'Source', $attrs);
$output->startElement($state->getURI(), 'LocURI', $attrs);
$chars = substr($this->_locURI,0,39);
$output->characters($chars);
$output->endElement($state->getURI(), 'LocURI');
$output->endElement($state->getURI(), 'Source');
}
if ($this->_targetURI != null) {
$output->startElement($state->getURI(), 'Target', $attrs);
$output->startElement($state->getURI(), 'LocURI', $attrs);
$chars = $this->_targetURI;
$output->characters($chars);
$output->endElement($state->getURI(), 'LocURI');
$output->endElement($state->getURI(), 'Target');
}
if (isset($this->_content)) {
$output->startElement($state->getURI(), 'Data', $attrs);
$chars = $this->_content;
$output->characters($chars);
$output->endElement($state->getURI(), 'Data');
}
$output->endElement($state->getURI(), 'Item');
}
$output->endElement($state->getURI(), $command);
$currentCmdID++;
return $currentCmdID;
}
}

View File

@ -0,0 +1,32 @@
<?php
include_once 'Horde/SyncML/Command/Sync/SyncElement.php';
/**
* $Horde: framework/SyncML/SyncML/Command/Sync/Delete.php,v 1.9 2004/07/02 19:24:44 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_Command_Sync_Delete extends Horde_SyncML_Command_Sync_SyncElement {
function output($currentCmdID, &$output)
{
$status = &new Horde_SyncML_Command_Status(RESPONSE_OK, 'Delete');
$status->setCmdRef($this->_cmdID);
if (isset($this->_luid)) {
$status->setSourceRef($this->_luid);
}
return $status->output($currentCmdID, $output);
}
}

View File

@ -0,0 +1,32 @@
<?php
include_once 'Horde/SyncML/Command/Sync/SyncElement.php';
/**
* $Horde: framework/SyncML/SyncML/Command/Sync/Replace.php,v 1.9 2004/07/02 19:24:44 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_Command_Sync_Replace extends Horde_SyncML_Command_Sync_SyncElement {
function output($currentCmdID, &$output)
{
$status = &new Horde_SyncML_Command_Status(RESPONSE_OK, 'Replace');
$status->setCmdRef($this->_cmdID);
if (isset($this->_luid)) {
$status->setSourceRef($this->_luid);
}
return $status->output($currentCmdID, $output);
}
}

View File

@ -0,0 +1,123 @@
<?php
include_once 'Horde/SyncML/Command.php';
/**
* $Horde: framework/SyncML/SyncML/Command/Sync/SyncElement.php,v 1.11 2004/07/02 19:24:44 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_Command_Sync_SyncElement extends Horde_SyncML_Command {
var $_luid;
var $_guid;
var $_isSource;
var $_content;
var $_contentType;
function &factory($command, $params = null)
{
@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);
switch ($this->_xmlStack) {
case 3:
if ($element == 'Source') {
$this->_isSource = true;
}
break;
}
}
function endElement($uri, $element)
{
switch ($this->_xmlStack) {
case 1:
// Need to add sync elements to the Sync method?
break;
case 3:
if ($element == 'Source') {
$this->_isSource = false;
} elseif ($element == 'Data') {
$this->_content = trim($this->_chars);
} elseif ($element == 'Type') {
if(!isset($this->_contentType))
$this->_contentType = trim($this->_chars);
}
break;
case 4:
if ($element == 'LocURI' && $this->_isSource) {
$this->_luid = trim($this->_chars);
} elseif ($element == 'Type') {
$this->_contentType = trim($this->_chars);
}
break;
}
parent::endElement($uri, $element);
}
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()
{
return $this->_content;
}
function setContent($content)
{
$this->_content = $content;
}
}

View File

@ -0,0 +1,865 @@
<?php
define('ALERT_DISPLAY', 100);
// Not implemented.
define('ALERT_TWO_WAY', 200);
define('ALERT_SLOW_SYNC', 201);
define('ALERT_ONE_WAY_FROM_CLIENT', 202);
define('ALERT_REFRESH_FROM_CLIENT', 203);
define('ALERT_ONE_WAY_FROM_SERVER', 204);
define('ALERT_REFRESH_FROM_SERVER', 205);
// Not implemented.
define('ALERT_TWO_WAY_BY_SERVER', 206);
define('ALERT_ONE_WAY_FROM_CLIENT_BY_SERVER', 207);
define('ALERT_REFRESH_FROM_CLIENT_BY_SERVER', 208);
define('ALERT_ONE_WAY_FROM_SERVER_BY_SERVER', 209);
define('ALERT_REFRESH_FROM_SERVER_BY_SERVER', 210);
define('ALERT_RESULT_ALERT', 221);
define('ALERT_NEXT_MESSAGE', 222);
define('ALERT_NO_END_OF_DATA', 223);
define('MIME_SYNCML_XML', 'application/vnd.syncml+xml');
define('MIME_SYNCML_WBXML', 'application/vnd.syncml+wbxml');
define('MIME_SYNCML_DEVICE_INFO_XML', 'application/vnd.syncml-devinf+xml');
define('MIME_SYNCML_DEVICE_INFO_WBXML', 'application/vnd.syncml-devinf+wbxml');
define('MIME_TEXT_PLAIN', 'text/plain');
define('MIME_VCARD_V21', 'text/x-vcard');
define('MIME_VCARD_V30', 'text/vcard');
define('MIME_VCALENDAR', 'text/x-vcalendar');
define('MIME_ICALENDAR', 'text/calendar');
define('MIME_XML_ICALENDAR', 'application/vnd.syncml-xcal');
define('MIME_MESSAGE', 'text/message');
define('MIME_SYNCML_XML_EMAIL', 'application/vnd.syncml-xmsg');
define('MIME_SYNCML_XML_BOOKMARK', 'application/vnd.syncml-xbookmark');
define('MIME_SYNCML_RELATIONAL_OBJECT', 'application/vnd.syncml-xrelational');
define('RESPONSE_IN_PROGRESS', 101);
define('RESPONSE_OK', 200);
define('RESPONSE_ITEM_ADDED', 201);
define('RESPONSE_ACCEPTED_FOR_PROCESSING', 202);
define('RESPONSE_NONAUTHORIATATIVE_RESPONSE', 203);
define('RESPONSE_NO_CONTENT', 204);
define('RESPONSE_RESET_CONTENT', 205);
define('RESPONSE_PARTIAL_CONTENT', 206);
define('RESPONSE_CONFLICT_RESOLVED_WITH_MERGE', 207);
define('RESPONSE_CONFLICT_RESOLVED_WITH_CLIENT_WINNING', 208);
define('RESPONSE_CONFILCT_RESOLVED_WITH_DUPLICATE', 209);
define('RESPONSE_DELETE_WITHOUT_ARCHIVE', 210);
define('RESPONSE_ITEM_NO_DELETED', 211);
define('RESPONSE_AUTHENTICATION_ACCEPTED', 212);
define('RESPONSE_CHUNKED_ITEM_ACCEPTED_AND_BUFFERED', 213);
define('RESPONSE_OPERATION_CANCELLED', 214);
define('RESPONSE_NO_EXECUTED', 215);
define('RESPONSE_ATOMIC_ROLL_BACK_OK', 216);
define('RESPONSE_MULTIPLE_CHOICES', 300);
// Need to change names.
// define('RESPONSE_MULTIPLE_CHOICES', 301);
// define('RESPONSE_MULTIPLE_CHOICES', 302);
// define('RESPONSE_MULTIPLE_CHOICES', 303);
// define('RESPONSE_MULTIPLE_CHOICES', 304);
define('RESPONSE_USE_PROXY', 305);
define('RESPONSE_BAD_REQUEST', 400);
define('RESPONSE_INVALID_CREDENTIALS', 401);
// Need to change names.
// define('RESPONSE_INVALID_CREDENTIALS', 402);
// define('RESPONSE_INVALID_CREDENTIALS', 403);
define('RESPONSE_NOT_FOUND', 404);
// Need to change names.
// define('RESPONSE_INVALID_CREDENTIALS', 405);
// define('RESPONSE_INVALID_CREDENTIALS', 406);
define('RESPONSE_MISSING_CREDENTIALS', 407);
// define('RESPONSE_INVALID_CREDENTIALS', 408);
// define('RESPONSE_INVALID_CREDENTIALS', 409);
// define('RESPONSE_INVALID_CREDENTIALS', 410);
// define('RESPONSE_INVALID_CREDENTIALS', 411);
// define('RESPONSE_INVALID_CREDENTIALS', 412);
// define('RESPONSE_INVALID_CREDENTIALS', 413);
// define('RESPONSE_INVALID_CREDENTIALS', 414);
// define('RESPONSE_INVALID_CREDENTIALS', 415);
define('RESPONSE_REQUEST_SIZE_TOO_BIG', 416);
// Need to change names.
// define('RESPONSE_INVALID_CREDENTIALS', 417);
// define('RESPONSE_INVALID_CREDENTIALS', 418);
// define('RESPONSE_INVALID_CREDENTIALS', 419);
// define('RESPONSE_INVALID_CREDENTIALS', 420);
// define('RESPONSE_INVALID_CREDENTIALS', 421);
// define('RESPONSE_INVALID_CREDENTIALS', 422);
// define('RESPONSE_INVALID_CREDENTIALS', 423);
define('RESPONSE_SIZE_MISMATCH', 424);
define('RESPONSE_COMMAND_FAILED', 500);
// Need to change names.
// define('RESPONSE_COMMAND_FAILED', 501);
// define('RESPONSE_COMMAND_FAILED', 502);
// define('RESPONSE_COMMAND_FAILED', 503);
// define('RESPONSE_COMMAND_FAILED', 504);
// define('RESPONSE_COMMAND_FAILED', 505);
// define('RESPONSE_COMMAND_FAILED', 506);
// define('RESPONSE_COMMAND_FAILED', 507);
// define('RESPONSE_COMMAND_FAILED', 508);
// define('RESPONSE_COMMAND_FAILED', 509);
// define('RESPONSE_COMMAND_FAILED', 510);
// define('RESPONSE_COMMAND_FAILED', 511);
// define('RESPONSE_COMMAND_FAILED', 512);
// define('RESPONSE_COMMAND_FAILED', 513);
// define('RESPONSE_COMMAND_FAILED', 514);
// define('RESPONSE_COMMAND_FAILED', 515);
define('RESPONSE_ATOMIC_ROLL_BACK_FAILED', 516);
define('NAME_SPACE_URI_SYNCML', 'SYNCML:SYNCML1.0');
define('NAME_SPACE_URI_SYNCML_1_1', 'syncml:syncml1.1');
define('NAME_SPACE_URI_METINF', 'syncml:metinf');
define('NAME_SPACE_URI_METINF_1_1', 'syncml:metinf1.1');
define('NAME_SPACE_URI_DEVINF', 'syncml:devinf');
define('NAME_SPACE_URI_DEVINF_1_1', 'syncml:devinf1.1');
define('CLIENT_SYNC_STARTED', 1);
define('CLIENT_SYNC_FINNISHED', 2);
define('SERVER_SYNC_DATA_PENDING', 3);
define('SERVER_SYNC_FINNISHED', 4);
define('MAX_DATA', 30);
/**
* The Horde_SyncML_State class provides a SyncML state object.
*
* $Horde: framework/SyncML/SyncML/State.php,v 1.15 2004/07/26 09:24:38 jan 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_State {
var $_sessionID;
var $_verProto;
var $_msgID;
var $_targetURI;
var $_sourceURI;
var $_version;
var $_locName;
var $_password;
var $_isAuthorized;
var $_uri;
var $_uriMeta;
var $_syncs = array();
var $_clientAnchorNext = array(); // written to db after successful sync
var $_serverAnchorLast = array();
var $_serverAnchorNext = array(); // written to db after successful sync
var $_clientDeviceInfo = array();
// array list of changed items, which need to be synced to the client
var $_changedItems;
// array list of deleted items, which need to be synced to the client
var $_deletedItems;
// array list of added items, which need to be synced to the client
var $_addedItems;
// bool flag that we need to more data
var $_syncStatus;
var $_log = array();
/**
* Creates a new instance of Horde_SyncML_State.
*/
function Horde_SyncML_State($sourceURI, $locName, $sessionID, $password = false)
{
$this->setSourceURI($sourceURI);
$this->setLocName($locName);
$this->setSessionID($sessionID);
if ($password) {
$this->setPassword($password);
}
$this->isAuthorized = false;
}
/**
* Returns the DataTree used as persistence layer for SyncML. The
* datatree var should not be a class member of State as State is
* stored as a session var. Resource handles (=db connections)
* cannot be stored in sessions.
*
* @return object DataTree The DataTree object.
*/
function &getDataTree()
{
$driver = $GLOBALS['conf']['datatree']['driver'];
$params = Horde::getDriverConfig('datatree', $driver);
$params = array_merge($params, array( 'group' => 'syncml' ));
return DataTree::singleton($driver, $params);
}
function getLocName()
{
if(isset($this->_locName))
return $this->_locName;
else
return False;
}
function getSourceURI()
{
return $this->_sourceURI;
}
function getTargetURI()
{
return $this->_targetURI;
}
function getVersion()
{
return $this->_version;
}
function &getAddedItems($_type)
{
if(isset($this->_addedItems[$_type]))
{
return $this->_addedItems[$_type];
}
return false;
}
function &getChangedItems($_type)
{
if(isset($this->_changedItems[$_type]))
{
return $this->_changedItems[$_type];
}
return false;
}
function &getDeletedItems($_type)
{
if(isset($this->_deletedItems[$_type]))
{
return $this->_deletedItems[$_type];
}
return false;
}
function getMoreDataPending()
{
return $this->_moreDataPending;
}
function getMsgID()
{
return $this->_msgID;
}
function &getSyncStatus()
{
return $this->_syncStatus;
}
function setAddedItems($_type, $_addedItems)
{
$this->_addedItems[$_type] = $_addedItems;
}
function setChangedItems($_type, $_changedItems)
{
$this->_changedItems[$_type] = $_changedItems;
}
function setClientDeviceInfo($clientDeviceInfo)
{
$this->_clientDeviceInfo = $clientDeviceInfo;
}
function setDeletedItems($_type, $_deletedItems)
{
$this->_deletedItems[$_type] = $_deletedItems;
}
function setMoreDataPending($_state)
{
$this->_moreDataPending = $_state;
}
/**
* Setter for property msgID.
* @param msgID New value of property msgID.
*/
function setMsgID($msgID)
{
$this->_msgID = $msgID;
}
/**
* Setter for property locName.
* @param locName New value of property locName.
*/
function setLocName($locName)
{
$this->_locName = $locName;
}
/**
* Setter for property locName.
* @param locName New value of property locName.
*/
function setPassword($password)
{
$this->_password = $password;
}
function setSourceURI($sourceURI)
{
$this->_sourceURI = $sourceURI;
}
function setSyncStatus($_syncStatus)
{
#Horde::logMessage('SyncML: syncState set to ==> ' . $_syncStatus, __FILE__, __LINE__, PEAR_LOG_DEBUG);
$this->_syncStatus = $_syncStatus;
}
function setTargetURI($targetURI)
{
$this->_targetURI = $targetURI;
}
function setVersion($version)
{
$this->_version = $version;
if ($version == 0) {
$this->_uri = NAME_SPACE_URI_SYNCML;
$this->_uriMeta = NAME_SPACE_URI_METINF;
} else {
$this->_uri = NAME_SPACE_URI_SYNCML_1_1;
$this->_uriMeta = NAME_SPACE_URI_METINF_1_1;
}
}
function setSessionID($sessionID)
{
$this->_sessionID = $sessionID;
}
function isAuthorized()
{
if (!$this->_isAuthorized) {
if(strstr($this->_locName,'@') === False)
{
$this->_locName .= '@'.$GLOBALS['phpgw_info']['server']['default_domain'];
}
#Horde::logMessage('SyncML: Authenticate ' . $this->_locName . ' - ' . $this->_password, __FILE__, __LINE__, PEAR_LOG_DEBUG);
if($GLOBALS['sessionid'] = $GLOBALS['phpgw']->session->create($this->_locName,$this->_password,'text','u'))
{
$this->_isAuthorized = true;
#Horde::logMessage('SyncML_EGW: Authentication of ' . $this->_locName . '/' . $GLOBALS['sessionid'] . ' succeded' , __FILE__, __LINE__, PEAR_LOG_DEBUG);
}
else
{
$this->_isAuthorized = false;
Horde::logMessage('SyncML: Authentication of ' . $this->_locName . ' failed' , __FILE__, __LINE__, PEAR_LOG_DEBUG);
}
}
else
{
// store sessionID in a variable, because ->verify maybe resets that value
$sessionID = session_id();
if(!$GLOBALS['phpgw']->session->verify($sessionID, 'staticsyncmlkp3'))
Horde::logMessage('SyncML_EGW: egw session('.$sessionID.') not verified ' , __FILE__, __LINE__, PEAR_LOG_DEBUG);
}
return $this->_isAuthorized;
}
function clearSync($target)
{
unset($this->_syncs[$target]);
}
function setSync($target, $sync)
{
$this->_syncs[$target] = $sync;
}
function getSync($target)
{
if (isset($this->_syncs[$target])) {
return $this->_syncs[$target];
} else {
return false;
}
}
function getTargets()
{
if(count($this->_syncs) < 1)
return FALSE;
foreach($this->_syncs as $target => $sync)
{
$targets[] = $target;
}
return $targets;
}
function getURI()
{
return $this->_uri;
}
function getURIMeta()
{
return $this->_uriMeta;
}
/**
* Converts a Horde 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.
*
* Remember that the datatree is really a tree disguised as a
* table. So to look up the guid above, getId first looks for an
* entry 'kronolith' and then for an entry
* 0d1b415fc124d3427722e95f0e926b75 with kronolith as parent.
*/
function getLocID($type, $guid)
{
$dt = &$this->getDataTree();
$id = $dt->getId($this->_locName . $this->_sourceURI . $type . $guid);
if (is_a($id, 'PEAR_Error')) {
return false;
}
$gid = $dt->getObjectById($id);
if (is_a($gid, 'PEAR_Error')) {
return false;
}
return $gid->get('locid');
}
/**
* 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.
*/
function setUID($type, $locid, $guid, $ts=0)
{
$dt = &$this->getDataTree();
// Set $locid.
$gid = &new DataTreeObject($this->_locName . $this->_sourceURI . $type . $guid);
$gid->set('type', $type);
$gid->set('locid', $locid);
$gid->set('ts', $ts);
$r = $dt->add($gid);
if (is_a($r, 'PEAR_Error')) {
// Object already exists: update instead.
$r = $dt->updateData($gid);
}
$this->dieOnError($r, __FILE__, __LINE__);
// Set $globaluid
$lid = &new DataTreeObject($this->_locName . $this->_sourceURI . $type . $locid);
$lid->set('globaluid', $guid);
$r = $dt->add($lid);
if (is_a($r, 'PEAR_Error')) {
// object already exists: update instead.
$r = $dt->updateData($lid);
}
$this->dieOnError($r, __FILE__, __LINE__);
}
/**
* 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)
{
$this->dieOnError($type, __FILE__, __LINE__);
$this->dieOnError($locid, __FILE__, __LINE__);
$this->dieOnError($locid, __FILE__, __LINE__);
$this->dieOnError($this->_locName, __FILE__, __LINE__);
$this->dieOnError($this->_sourceURI, __FILE__, __LINE__);
$dt = &$this->getDataTree();
$id = $dt->getId($this->_locName . $this->_sourceURI . $type . $locid);
if (is_a($id, 'PEAR_Error')) {
return false;
}
$lid = $dt->getObjectById($id);
if (is_a($lid, 'PEAR_Error')) {
return false;
}
return $lid->get('globaluid');
}
/**
* 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)
{
$dt = &$this->getDataTree();
$id = $dt->getId($this->_locName . $this->_sourceURI . $type . $guid);
if (is_a($id, 'PEAR_Error')) {
return false;
}
$gid = $dt->getObjectById($id);
if (is_a($gid, 'PEAR_Error')) {
return false;
}
return $gid->get('ts');
}
/**
* 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)
{
$dt = &$this->getDataTree();
$id = $dt->getId($this->_locName . $this->_sourceURI . $type . $locid);
if (is_a($id, 'PEAR_Error')) {
Horde::logMessage("SyncML: state->removeUID(type=$type,locid=$locid) : nothing to remove", __FILE__, __LINE__, PEAR_LOG_DEBUG);
return false;
}
$lid = $dt->getObjectById($id);
$guid = $lid->get('globaluid');
Horde::logMessage("SyncML: state->removeUID(type=$type,locid=$locid) : removing guid:$guid and lid:$lid", __FILE__, __LINE__, PEAR_LOG_DEBUG);
$dt->remove($guid);
$dt->remove($lid);
return $guid;
}
/**
* This function should use DevINF information.
*/
function getPreferedContentType($type)
{
if ($type == 'contacts') {
return 'text/x-vcard';
} elseif ($type == 'notes') {
return 'text/x-vnote';
} elseif ($type == 'tasks') {
return 'text/x-vcalendar';
} elseif ($type == 'calendar') {
return 'text/x-vcalendar';
}
}
/**
* Returns the preferred contenttype of the client for the given
* sync data type (database).
*
* This is passed as an option to the Horde API export functions.
*/
function getPreferedContentTypeClient($_sourceLocURI)
{
$deviceInfo = $this->getClientDeviceInfo();
if(isset($deviceInfo['dataStore'][$_sourceLocURI]['rxPreference']['contentType']))
{
return array('ContentType' => $deviceInfo['dataStore'][$_sourceLocURI]['rxPreference']['contentType']);
}
Horde::logMessage('SyncML: sourceLocURI ' . $_sourceLocURI .' not found', __FILE__, __LINE__, PEAR_LOG_DEBUG);
return PEAR::raiseError(_('sourceLocURI not found'));
# elseif ($type == 'contacts') {
# return 'text/x-vcard';
# } elseif ($type == 'notes') {
# return array('ContentType' => 'text/x-vnote',
# 'ENCODING' => 'QUOTED-PRINTABLE',
# 'CHARSET' => 'UTF-8');
# } elseif ($type == 'tasks') {
# return 'text/x-vcalendar';
# } elseif ($type == 'calendar') {
# return array('ContentType' => 'text/x-vcalendar',
# 'ENCODING' => 'QUOTED-PRINTABLE',
# 'CHARSET' => 'UTF-8');
# }
}
function setClientAnchorNext($type, $a)
{
$this->_clientAnchorNext[$type] = $a;
}
function setServerAnchorLast($type, $a)
{
$this->_serverAnchorLast[$type] = $a;
}
function setServerAnchorNext($type, $a)
{
$this->_serverAnchorNext[$type] = $a;
}
function getClientAnchorNext($type)
{
return $this->_clientAnchorNext[$type];
}
function getServerAnchorNext($type)
{
return $this->_serverAnchorNext[$type];
}
function getServerAnchorLast($type)
{
return $this->_serverAnchorLast[$type];
}
/**
* 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)
{
$dt = &$this->getDataTree();
$id = $dt->getId($this->_locName . $this->_sourceURI . $type . 'syncSummary');
if (is_a($id, 'PEAR_Error')) {
return false;
}
return $dt->getObjectById($id);
}
/**
* 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()
{
$dt = &$this->getDataTree();
$id = $dt->getId($this->_locName . $this->_sourceURI . 'deviceInfo');
if (is_a($id, 'PEAR_Error')) {
return false;
}
$info = $dt->getObjectById($id);
return $info->get('ClientDeviceInfo');
}
/**
* write clients device info to database
*/
function writeClientDeviceInfo()
{
if (!isset($this->_clientDeviceInfo) || !is_array($this->_clientDeviceInfo)) {
return;
}
$dt = &$this->getDataTree();
$s = $this->_locName . $this->_sourceURI . 'deviceInfo';
// Set $locid.
$info = &new DataTreeObject($s);
$info->set('ClientDeviceInfo', $this->_clientDeviceInfo);
$r = $dt->add($info);
if (is_a($r, 'PEAR_Error')) {
// Object already exists: update instead.
$dt->updateData($info);
}
}
/**
* 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()
{
if (!isset($this->_serverAnchorNext) || !is_array($this->_serverAnchorNext)) {
return;
}
$dt = &$this->getDataTree();
foreach (array_keys($this->_serverAnchorNext) as $type) {
$s = $this->_locName . $this->_sourceURI . $type . 'syncSummary';
// Set $locid.
$info = &new DataTreeObject($s);
$info->set('ClientAnchor', $this->_clientAnchorNext);
$info->set('ServerAnchor', $this->_serverAnchorNext);
$r = $dt->add($info);
if (is_a($r, 'PEAR_Error')) {
// Object already exists: update instead.
$dt->updateData($info);
}
}
}
/**
* The log simply counts the entries for each topic.
*/
function log($topic)
{
if (isset($this->_log[$topic])) {
$this->_log[$topic] += 1;
} else {
$this->_log[$topic] = 1;
}
}
/**
* The Log is an array where the key is the event name and the
* value says how often this event occured.
*/
function getLog()
{
return $this->_log;
}
/**
* Convert the content.
*
* Currently strips uid (primary key) information as client and
* server might use different ones.
*
* Charset conversions might be added here too.
*/
function convertClient2Server($content, $contentType)
{
switch ($contentType) {
case 'text/calendar':
case 'text/x-icalendar':
case 'text/x-vcalendar':
case 'text/x-vevent':
case 'text/x-vtodo':
$content = preg_replace('/^UID:.*\n/m', '', $content, 1);
break;
}
return $content;
}
/**
* Convert the content.
*
* Currently strips uid (primary key) information as client and
* server might use different ones.
*
* Charset conversions might be added here too.
*/
function convertServer2Client($content, $contentType)
{
switch ($contentType) {
case 'text/calendar':
case 'text/x-icalendar':
case 'text/x-vcalendar':
case 'text/x-vevent':
case 'text/x-vtodo':
$content = preg_replace('/^UID:.*\n/m', '', $content, 1);
break;
}
// FIXME: utf8 really should be fine. But the P900 seems to
// expect ISO 8559 even when &lt;?xml version="1.0"
// encoding="utf-8"&gt; is specified.
//
// So at least make this dependant on the device information.
return utf8_decode($content);
}
/**
* When True, Task Item changes (NAG) are sent to the server
* during "calendar" Syncs. That's the way the P800/900 handles
* things. Should be retrieved from devinf?
*/
function handleTasksInCalendar()
{
return true;
}
/**
* This is a small helper function that can be included to check
* whether a given $obj is a PEAR_Error or not. If so, it logs
* to debug, var_dumps the $obj and exits.
*/
function dieOnError($obj, $file = __FILE__, $line = __LINE__)
{
if (!is_a($obj, 'PEAR_Error')) {
return;
}
Horde::logMessage('SyncML: PEAR Error: ' . $obj->getMessage(), $file, $line, PEAR_LOG_ERR);
print "PEAR ERROR\n\n";
var_dump($obj);
exit;
}
}

View File

@ -0,0 +1,393 @@
<?php
include_once dirname(__FILE__).'/State.php';
class EGW_SyncML_State extends Horde_SyncML_State
{
/**
* 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;
$db = clone($GLOBALS['phpgw']->db);
$cols = array('map_timestamp');
$where = array
(
'map_id' => $mapID,
'map_guid' => $guid,
);
Horde::logMessage('SyncML: getChangeTS for ' . $mapID .' / '. $guid, __FILE__, __LINE__, PEAR_LOG_DEBUG);
$db->select('egw_contentmap', $cols, $where, __LINE__, __FILE__);
if($db->next_record())
{
Horde::logMessage('SyncML: getChangeTS changets is ' . $db->from_timestamp($db->f('map_timestamp')), __FILE__, __LINE__, PEAR_LOG_DEBUG);
return $db->from_timestamp($db->f('map_timestamp'));
}
return false;
}
/**
* 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()
{
$deviceID = $this->_locName . $this->_sourceURI;
$db = clone($GLOBALS['phpgw']->db);
$cols = array
(
'dev_dtdversion',
'dev_numberofchanges',
'dev_largeobjs',
'dev_swversion',
'dev_oem',
'dev_model',
'dev_manufacturer',
'dev_devicetype',
'dev_deviceid',
'dev_datastore',
);
$where = array
(
'dev_id' => $deviceID,
);
$db->select('egw_syncmldevinfo', $cols, $where, __LINE__, __FILE__);
if($db->next_record())
{
$devInfo = array
(
'DTDVersion' => $db->f('dev_dtdversion'),
'supportNumberOfChanges' => $db->f('dev_numberofchanges'),
'supportLargeObjs' => $db->f('dev_largeobjs'),
'softwareVersion' => $db->f('dev_swversion'),
'oem' => $db->f('dev_oem'),
'model' => $db->f('dev_model'),
'manufacturer' => $db->f('dev_manufacturer'),
'deviceType' => $db->f('dev_devicetype'),
'deviceID' => $db->f('dev_deviceid'),
'dataStore' => unserialize($db->f('dev_datastore')),
);
return $devInfo;
}
return false;
}
/**
* 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);
$db = clone($GLOBALS['phpgw']->db);
$cols = array('map_guid');
$where = array
(
'map_id' => $mapID,
'map_locuid' => $locid,
'map_expired' => 0,
);
$db->select('egw_contentmap', $cols, $where, __LINE__, __FILE__);
if($db->next_record())
{
return $db->f('map_guid');
}
return false;
}
/**
* 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;
$db = clone($GLOBALS['phpgw']->db);
$cols = array('map_locuid');
$where = array
(
'map_id' => $mapID,
'map_guid' => $guid
);
$db->select('egw_contentmap', $cols, $where, __LINE__, __FILE__);
if($db->next_record())
{
return $db->f('map_locuid');
}
return false;
}
/**
* 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;
$db = clone($GLOBALS['phpgw']->db);
$cols = array('sync_serverts','sync_clientts');
$where = array
(
'dev_id' => $deviceID,
'sync_path' => $type
);
$db->select('egw_syncmlsummary', $cols, $where, __LINE__, __FILE__);
Horde::logMessage("SyncML: get SYNCSummary for $deviceID", __FILE__, __LINE__, PEAR_LOG_DEBUG);
if($db->next_record())
{
Horde::logMessage("SyncML: get SYNCSummary for $deviceID serverts: ".$db->f('sync_serverts')." clients: ".$db->f('sync_clientts'), __FILE__, __LINE__, PEAR_LOG_DEBUG);
$retData = array
(
'ClientAnchor' => $db->f('sync_clientts'),
'ServerAnchor' => $db->f('sync_serverts'),
);
return $retData;
}
return false;
}
function isAuthorized()
{
if (!$this->_isAuthorized) {
if(!isset($this->_locName) && !isset($this->_password))
{
Horde::logMessage('SyncML: Authentication not possible currently. No username and password available' , __FILE__, __LINE__, PEAR_LOG_DEBUG);
return FALSE;
}
if(strstr($this->_locName,'@') === False)
{
$this->_locName .= '@'.$GLOBALS['phpgw_info']['server']['default_domain'];
}
Horde::logMessage('SyncML: Authenticate ' . $this->_locName . ' - ' . $this->_password, __FILE__, __LINE__, PEAR_LOG_DEBUG);
if($GLOBALS['sessionid'] = $GLOBALS['phpgw']->session->create($this->_locName,$this->_password,'text','u'))
{
$this->_isAuthorized = true;
Horde::logMessage('SyncML_EGW: Authentication of ' . $this->_locName . '/' . $GLOBALS['sessionid'] . ' succeded' , __FILE__, __LINE__, PEAR_LOG_DEBUG);
}
else
{
$this->_isAuthorized = false;
Horde::logMessage('SyncML: Authentication of ' . $this->_locName . ' failed' , __FILE__, __LINE__, PEAR_LOG_DEBUG);
}
}
else
{
// store sessionID in a variable, because ->verify maybe resets that value
$sessionID = session_id();
if(!$GLOBALS['phpgw']->session->verify($sessionID, 'staticsyncmlkp3'))
Horde::logMessage('SyncML_EGW: egw session('.$sessionID.') not verified ' , __FILE__, __LINE__, PEAR_LOG_DEBUG);
}
return $this->_isAuthorized;
}
/**
* 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;
$db = clone($GLOBALS['phpgw']->db);
$cols = array('map_guid');
$where = array
(
'map_id' => $mapID,
'map_locuid' => $locid
);
$db->select('egw_contentmap', $cols, $where, __LINE__, __FILE__);
if(!$db->next_record())
{
Horde::logMessage("SyncML: state->removeUID(type=$type,locid=$locid) : nothing to remove", __FILE__, __LINE__, PEAR_LOG_DEBUG);
return false;
}
$guid = $db->f('map_guid');
Horde::logMessage("SyncML: state->removeUID(type=$type,locid=$locid) : removing guid:$guid", __FILE__, __LINE__, PEAR_LOG_DEBUG);
$db->delete('egw_contentmap', $where, __LINE__, __FILE__);
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.
*/
function setUID($type, $locid, $guid, $ts=0)
{
// fix $guid, it maybe was to long for some devices
// format is appname-id-systemid
$guidParts = explode('-',$guid);
if(count($guidParts) == 3)
{
$guid = $GLOBALS['phpgw']->common->generate_uid($guidParts[0],$guidParts[1]);
}
if($ts == 0)
{
$ts = time();
}
Horde::logMessage("SyncML: setUID $type, $locid, $guid, $ts ".count($guidParts), __FILE__, __LINE__, PEAR_LOG_DEBUG);
$db = clone($GLOBALS['phpgw']->db);
$mapID = $this->_locName . $this->_sourceURI . $type;
$where = array(
'map_id' => $mapID,
'map_guid' => $guid,
);
$data = $where + array(
'map_locuid' => $locid,
'map_timestamp' => $ts,
'map_expired' => 0,
);
$db->insert('egw_contentmap', $data, $where, __LINE__, __FILE__);
Horde::logMessage("SyncML: setUID $type, $locid, $guid, $ts $mapID", __FILE__, __LINE__, PEAR_LOG_DEBUG);
}
/**
* write clients device info to database
*/
function writeClientDeviceInfo()
{
if (!isset($this->_clientDeviceInfo) || !is_array($this->_clientDeviceInfo)) {
return false;
}
$deviceID = $this->_locName . $this->_sourceURI;
$data = array
(
'dev_id' => $deviceID,
'dev_dtdversion' => $this->_clientDeviceInfo['DTDVersion'],
'dev_numberofchanges' => $this->_clientDeviceInfo['supportNumberOfChanges'],
'dev_largeobjs' => $this->_clientDeviceInfo['supportLargeObjs'],
'dev_swversion' => $this->_clientDeviceInfo['softwareVersion'],
'dev_oem' => $this->_clientDeviceInfo['oem'],
'dev_model' => $this->_clientDeviceInfo['model'],
'dev_manufacturer' => $this->_clientDeviceInfo['manufacturer'],
'dev_devicetype' => $this->_clientDeviceInfo['deviceType'],
'dev_deviceid' => $this->_clientDeviceInfo['deviceID'],
'dev_datastore' => serialize($this->_clientDeviceInfo['dataStore']),
);
$where = array
(
'dev_id' => $deviceID,
);
$GLOBALS['phpgw']->db->insert('egw_syncmldevinfo',$data,$where);
}
/**
* 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 = $where + array
(
'sync_serverts' => $a,
'sync_clientts' => $this->_clientAnchorNext[$type]
);
$GLOBALS['phpgw']->db->insert('egw_syncmlsummary', $data, $where, __LINE__, __FILE__);
}
}
}
?>

View File

@ -0,0 +1,184 @@
<?php
/**
* $Horde: framework/SyncML/SyncML/Sync.php,v 1.7 2004/09/14 04:27:05 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 {
/**
* Target, either contacts, notes, events,
*/
var $_targetLocURI;
var $_sourceLocURI;
/**
* Return if all commands success.
*/
var $globalSuccess;
/**
* This is the content type to use to export data.
*/
var $preferedContentType;
/**
* Do have the sync data loaded from the database already?
*/
var $syncDataLoaded;
function &factory($alert)
{
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)
{
$result = $this->runSyncCommand($syncCommand);
return $syncCommand->output($currentCmdID, $output);
}
function startSync($currentCmdID, &$output)
{
return $currentCmdID;
}
function endSync($currentCmdID, &$output)
{
return $currentCmdID;
}
/**
* 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)
{
Horde::logMessage('SyncML: content type is ' . $command->getContentType(), __FILE__, __LINE__, PEAR_LOG_DEBUG);
global $registry;
#require_once 'Horde/History.php';
#$history = &Horde_History::singleton();
$history = $GLOBALS['phpgw']->contenthistory;
$state = &$_SESSION['SyncML.state'];
$hordeType = $type = $this->_targetLocURI;
// remove the './' from the beginning
$hordeType = str_replace('./','',$hordeType);
if(!$contentType = $command->getContentType())
{
$contentType = $state->getPreferedContentType($type);
}
if ($this->_targetLocURI == 'calendar' && strpos($command->getContent(), 'BEGIN:VTODO') !== false) {
$hordeType = 'tasks';
}
$guid = false;
if (is_a($command, 'Horde_SyncML_Command_Sync_Add')) {
$guid = $registry->call($hordeType . '/import',
array($state->convertClient2Server($command->getContent(), $contentType), $contentType));
if (!is_a($guid, 'PEAR_Error')) {
$ts = $history->getTSforAction($guid, 'add');
$state->setUID($type, $command->getLocURI(), $guid, $ts);
$state->log("Client-Add");
Horde::logMessage('SyncML: added client entry as ' . $guid, __FILE__, __LINE__, PEAR_LOG_DEBUG);
} else {
$state->log("Client-AddFailure");
Horde::logMessage('SyncML: Error in adding client entry:' . $guid->message, __FILE__, __LINE__, PEAR_LOG_ERR);
}
} elseif (is_a($command, 'Horde_SyncML_Command_Sync_Delete')) {
// We can't remove the mapping entry as we need to keep
// the timestamp information.
$guid = $state->removeUID($type, $command->getLocURI());
#$guid = $state->getGlobalUID($type, $command->getLocURI());
Horde::logMessage('SyncML: about to delete entry ' . $type .' / '. $guid . ' due to client request '.$command->getLocURI(), __FILE__, __LINE__, PEAR_LOG_DEBUG);
if (!is_a($guid, 'PEAR_Error') && $guid != false) {
$registry->call($hordeType . '/delete', array($guid));
#$ts = $history->getTSforAction($guid, 'delete');
#$state->setUID($type, $command->getLocURI(), $guid, $ts);
$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, maybe gone already on server. msg:'. $guid->message, __FILE__, __LINE__, PEAR_LOG_ERR);
}
} elseif (is_a($command, 'Horde_SyncML_Command_Sync_Replace')) {
$guid = $state->getGlobalUID($type, $command->getLocURI());
$ok = false;
if ($guid) {
Horde::logMessage('SyncML: locuri'. $command->getLocURI() . ' guid ' . $guid , __FILE__, __LINE__, PEAR_LOG_ERR);
// Entry exists: replace current one.
$ok = $registry->call($hordeType . '/replace',
array($guid, $state->convertClient2Server($command->getContent(), $contentType), $contentType));
if (!is_a($ok, 'PEAR_Error')) {
$ts = $history->getTSforAction($guid, 'modify');
$state->setUID($type, $command->getLocURI(), $guid, $ts);
Horde::logMessage('SyncML: replaced entry 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 not exist in map or database: add a new
// one.
Horde::logMessage('SyncML: try to add contentype ' . $contentType, __FILE__, __LINE__, PEAR_LOG_DEBUG);
$guid = $registry->call($hordeType . '/import',
array($state->convertClient2Server($command->getContent(), $contentType), $contentType));
if (!is_a($guid, 'PEAR_Error')) {
$ts = $history->getTSforAction($guid, 'add');
$state->setUID($type, $command->getLocURI(), $guid, $ts);
$state->log("Client-AddReplace");
Horde::logMessage('SyncML: r/ added client entry as ' . $guid, __FILE__, __LINE__, PEAR_LOG_DEBUG);
} else {
Horde::logMessage('SyncML: Error in replacing/add client entry:' . $guid->message, __FILE__, __LINE__, PEAR_LOG_ERR);
$state->log("Client-AddFailure");
}
}
}
return $guid;
}
}

View File

@ -0,0 +1,23 @@
<?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

@ -0,0 +1,79 @@
<?php
include_once 'Horde/SyncML/Sync.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 {
function endSync($currentCmdID, &$output)
{
global $registry;
$state = &$_SESSION['SyncML.state'];
// counter for synced items
$syncItems = 0;
$syncType = $this->_targetLocURI;
$hordeType = str_replace('./','',$syncType);
if(!$adds = &$state->getAddedItems($hordeType))
{
Horde::logMessage("SyncML: reading list of added items", __FILE__, __LINE__, PEAR_LOG_DEBUG);
$adds = $registry->call($hordeType, '/list', array());
$adds = &$state->getAddedItems($hordeType);
}
Horde::logMessage("SyncML: ....... ".count($adds).' items to send ..............', __FILE__, __LINE__, PEAR_LOG_DEBUG);
Horde::logMessage("SyncML: starting OneWayFromServerSync ($hordeType)", __FILE__, __LINE__, PEAR_LOG_DEBUG);
#foreach ($adds as $guid) {
while($guid = array_shift($adds))
{
$contentType = $state->getPreferedContentTypeClient($this->_sourceLocURI);
$cmd = &new Horde_SyncML_Command_Sync_ContentSyncElement();
$c = $registry->call($hordeType . '/export',
array('guid' => $guid,
'contentType' => $contentType
)
);
if (!is_a($c, 'PEAR_Error')) {
// Item in history but not in database. Strange, but
// can happen.
#LK $cmd->setContent($state->convertServer2Client($c, $contentType));
$cmd->setContent($c);
$cmd->setContentType($contentType['ContentType']);
$cmd->setSourceURI($guid);
$currentCmdID = $cmd->outputCommand($currentCmdID, $output, 'Add');
$state->log('Server-Add');
$syncItems++;
// return if we have to much data
if($syncItems > MAX_DATA)
{
$state->setMoreDataPending();
return $currentCmdID;
}
}
}
Horde::logMessage("SyncML: handling OneWayFromServerSync done ".$currentCmdID, __FILE__, __LINE__, PEAR_LOG_DEBUG);
return $currentCmdID;
}
}

View File

@ -0,0 +1,34 @@
<?php
include_once 'Horde/SyncML/Sync.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 {
/**
* We need to erase the current server contents, then we can add
* the client's contents.
*/
function startSync($currentCmdID, &$output)
{
$deletes = $registry->call($this->targetLocURI, '/list', array());
foreach ($delete as $deletes) {
$registry->call($this->targetLocURI . '/delete', array($delete));
}
return $currentCmdID;
}
}

View File

@ -0,0 +1,64 @@
<?php
include_once 'Horde/SyncML/Sync.php';
/**
* $Horde: framework/SyncML/SyncML/Sync/RefreshFromServerSync.php,v 1.9 2004/07/03 15:21:15 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_RefreshFromServerSync extends Horde_SyncML_Sync {
function endSync($currentCmdID, &$output)
{
global $registry;
$state = &$_SESSION['SyncML.state'];
// counter for synced items
$syncItems = 0;
if(!$adds = &$state->getAddedItems($hordeType))
{
Horde::logMessage("SyncML: reading list of added items", __FILE__, __LINE__, PEAR_LOG_DEBUG);
$adds = $registry->call($this->targetLocURI, '/list', array());
$adds = &$state->getAddedItems($hordeType);
}
Horde::logMessage("SyncML: ....... ".count($adds).' items to send ..............', __FILE__, __LINE__, PEAR_LOG_DEBUG);
#foreach ($add as $adds) {
while($guid = array_shift($adds))
{
$locid = $this->_currentState->getLocID($this->targetLocURI, $guid);
// Add a replace.
$add = &new Horde_SyncML_Command_Sync_ContentSyncElement();
$add->setContent($registry->call($this->targetLocURI . '/listByAction',
array($this->_currentState->getPreferedContentType($this->targetLocURI))));
$currentCmdID = $add->outputCommand($currentCmdID, $output, 'Add');
$syncItems++;
// return if we have to much data
if($syncItems > MAX_DATA)
{
$state->setMoreDataPending();
return $currentCmdID;
}
}
// TODO deletes
// TODO modifies
return $currentCmdID;
}
}

View File

@ -0,0 +1,109 @@
<?php
include_once 'Horde/SyncML/Sync/TwoWaySync.php';
/**
* Slow sync may just work; I think most of the work is going to be
* done by the API.
*
* $Horde: framework/SyncML/SyncML/Sync/SlowSync.php,v 1.7 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_SlowSync extends Horde_SyncML_Sync_TwoWaySync {
function handleSync($currentCmdID, $hordeType, $syncType,&$output, $refts)
{
global $registry;
$history = $GLOBALS['phpgw']->contenthistory;
$state = &$_SESSION['SyncML.state'];
$adds = &$state->getAddedItems($hordeType);
#if($adds === FALSE)
#{
# Horde::logMessage("SyncML: reading added items from database", __FILE__, __LINE__, PEAR_LOG_DEBUG);
# $state->setAddedItems($hordeType, $registry->call($hordeType. '/list', array()));
# $adds = &$state->getAddedItems($hordeType);
#}
Horde::logMessage("SyncML: ".count($adds). ' added items found for '.$hordeType , __FILE__, __LINE__, PEAR_LOG_DEBUG);
$serverAnchorNext = $state->getServerAnchorNext($syncType);
while($guid = array_shift($adds))
{
#$guid_ts = max($history->getTSforAction($guid, 'add'),$history->getTSforAction($guid, 'modify'));
$sync_ts = $state->getChangeTS($syncType, $guid);
#Horde::logMessage("SyncML: timestamp add: $guid sync_ts: $sync_ts anchorNext: ". $serverAnchorNext.' / '.time(), __FILE__, __LINE__, PEAR_LOG_DEBUG);
// $sync_ts it got synced from client to server someone
// $sync_ts >= $serverAnchorNext it got synced from client to server in this sync package already
if ($sync_ts && $sync_ts >= $serverAnchorNext) {
// 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;
}
# $locid = $state->getLocID($syncType, $guid);
#
// Create an Add request for client.
# LK $contentType = $state->getPreferedContentTypeClient($syncType);
$contentType = $state->getPreferedContentTypeClient($this->_sourceLocURI);
$cmd = &new Horde_SyncML_Command_Sync_ContentSyncElement();
$c = $registry->call($hordeType . '/export',
array('guid' => $guid,
'contentType' => $contentType));
if (!is_a($c, 'PEAR_Error')) {
// Item in history but not in database. Strange, but
// can happen.
#LK $cmd->setContent($state->convertServer2Client($c, $contentType));
$cmd->setContent($c);
$cmd->setContentType($contentType['ContentType']);
$cmd->setSourceURI($guid);
$currentCmdID = $cmd->outputCommand($currentCmdID, $output, 'Add');
$state->log('Server-Add');
// return if we have to much data
if($currentCmdID > MAX_DATA)
{
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
return $currentCmdID;
}
}
}
Horde::logMessage("SyncML: handling sync ".$currentCmdID, __FILE__, __LINE__, PEAR_LOG_DEBUG);
$state->clearSync($syncType);
return $currentCmdID;
}
function loadData()
{
global $registry;
$state = &$_SESSION['SyncML.state'];
$syncType = $this->_targetLocURI;
$hordeType = str_replace('./','',$syncType);
Horde::logMessage("SyncML: reading added items from database for $hordeType", __FILE__, __LINE__, PEAR_LOG_DEBUG);
$state->setAddedItems($hordeType, $registry->call($hordeType. '/list', array()));
$adds = &$state->getAddedItems($hordeType);
$this->_syncDataLoaded = TRUE;
return count($state->getAddedItems($hordeType));
}
}

View File

@ -0,0 +1,242 @@
<?php
include_once 'Horde/SyncML/Sync.php';
include_once 'Horde/SyncML/Command/Sync/ContentSyncElement.php';
/**
* $Horde: framework/SyncML/SyncML/Sync/TwoWaySync.php,v 1.12 2004/07/26 09:24:38 jan 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>
* @author Karsten Fourmont <fourmont@gmx.de>
*
* @version $Revision$
* @since Horde 3.0
* @package Horde_SyncML
*/
class Horde_SyncML_Sync_TwoWaySync extends Horde_SyncML_Sync {
function endSync($currentCmdID, &$output)
{
global $registry;
$state = &$_SESSION['SyncML.state'];
$syncType = $this->_targetLocURI;
$hordeType = str_replace('./','',$syncType);
$refts = $state->getServerAnchorLast($syncType);
$currentCmdID = $this->handleSync($currentCmdID,
$hordeType,
$syncType,
$output,
$refts);
if ($syncType == 'calendar' && $state->handleTasksInCalendar()) {
Horde::logMessage("SyncML: handling tasks in calendar sync", __FILE__, __LINE__, PEAR_LOG_DEBUG);
$currentCmdID = $this->handleSync($currentCmdID, 'tasks', $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();
#require_once 'Horde/History.php';
#$history = &Horde_History::singleton();
$history = $GLOBALS['phpgw']->contenthistory;
$state = &$_SESSION['SyncML.state'];
$changes = &$state->getChangedItems($hordeType);
$deletes = &$state->getDeletedItems($hordeType);
$adds = &$state->getAddedItems($hordeType);
Horde::logMessage("SyncML: ".count($changes).' changed items found for '.$hordeType, __FILE__, __LINE__, PEAR_LOG_DEBUG);
Horde::logMessage("SyncML: ".count($deletes).' deleted items found for '.$hordeType, __FILE__, __LINE__, PEAR_LOG_DEBUG);
Horde::logMessage("SyncML: ".count($adds). ' added items found for '.$hordeType , __FILE__, __LINE__, PEAR_LOG_DEBUG);
while($guid = array_shift($changes))
{
$guid_ts = $history->getTSforAction($guid, 'modify');
$sync_ts = $state->getChangeTS($syncType, $guid);
Horde::logMessage("SyncML: timestamp modify 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;
}
Horde::logMessage("SyncML: change $guid hs_ts:$guid_ts dt_ts:" . $state->getChangeTS($syncType, $guid), __FILE__, __LINE__, PEAR_LOG_DEBUG);
$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.
# LK $contentType = $state->getPreferedContentTypeClient($syncType);
$contentType = $state->getPreferedContentTypeClient($this->_sourceLocURI);
$c = $registry->call($hordeType. '/export',
array('guid' => $guid, 'contentType' => $contentType));
if (!is_a($c, 'PEAR_Error')) {
// Item in history but not in database. Strange, but
// can happen.
Horde::logMessage("SyncML: change: $guid export content: $c", __FILE__, __LINE__, PEAR_LOG_DEBUG);
$cmd = &new Horde_SyncML_Command_Sync_ContentSyncElement();
# LK $cmd->setContent($state->convertServer2Client($c, $contentType));
$cmd->setContent($c);
$cmd->setSourceURI($guid);
$cmd->setTargetURI($locid);
$cmd->setContentType($contentType['ContentType']);
$currentCmdID = $cmd->outputCommand($currentCmdID, $output, 'Replace');
$state->log('Server-Replace');
// return if we have to much data
if($currentCmdID > MAX_DATA)
{
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
return $currentCmdID;
}
}
}
Horde::logMessage("SyncML: handling sync ".$currentCmdID, __FILE__, __LINE__, PEAR_LOG_DEBUG);
// deletes
while($guid = array_shift($deletes))
{
$guid_ts = $history->getTSforAction($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);
continue;
}
$locid = $state->getLocID($syncType, $guid);
if (!$locid) {
Horde::logMessage("SyncML: unable to create delete for $guid: locid not found in map", __FILE__, __LINE__, PEAR_LOG_WARNING);
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->setTargetURI($locid);
$cmd->setSourceURI($guid);
$currentCmdID = $cmd->outputCommand($currentCmdID, $output, 'Delete');
$state->log('Server-Delete');
$state->removeUID($syncType, $locid);
// return if we have to much data
if($currentCmdID > MAX_DATA)
{
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
return $currentCmdID;
}
}
Horde::logMessage("SyncML: handling sync ".$currentCmdID, __FILE__, __LINE__, PEAR_LOG_DEBUG);
// Get adds.
if(count($missedAdds) > 0)
{
Horde::logMessage("SyncML: add missed changes as adds ".count($adds).' / '.$missedAdds[0], __FILE__, __LINE__, PEAR_LOG_DEBUG);
$state->setAddedItems($hordeType, array_merge($adds, $missedAdds));
$adds = &$state->getAddedItems($hordeType);
Horde::logMessage("SyncML: merged adds counter ".count($adds).' / '.$adds[0], __FILE__, __LINE__, PEAR_LOG_DEBUG);
}
while($guid = array_shift($adds))
{
#if($tempCounter > 10) continue;
$guid_ts = $history->getTSforAction($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;
}
$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.
# LK $contentType = $state->getPreferedContentTypeClient($syncType);
$contentType = $state->getPreferedContentTypeClient($this->_sourceLocURI);
$cmd = &new Horde_SyncML_Command_Sync_ContentSyncElement();
$c = $registry->call($hordeType . '/export',
array('guid' => $guid,
'contentType' => $contentType));
if (!is_a($c, 'PEAR_Error')) {
// Item in history but not in database. Strange, but
// can happen.
#LK $cmd->setContent($state->convertServer2Client($c, $contentType));
$cmd->setContent($c);
$cmd->setContentType($contentType['ContentType']);
$cmd->setSourceURI($guid);
$currentCmdID = $cmd->outputCommand($currentCmdID, $output, 'Add');
$state->log('Server-Add');
// return if we have to much data
if($currentCmdID > MAX_DATA)
{
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
return $currentCmdID;
}
}
}
Horde::logMessage("SyncML: handling sync ".$currentCmdID, __FILE__, __LINE__, PEAR_LOG_DEBUG);
$state->clearSync($syncType);
return $currentCmdID;
}
function loadData()
{
global $registry;
$state = &$_SESSION['SyncML.state'];
$syncType = $this->_targetLocURI;
$hordeType = str_replace('./','',$syncType);
$refts = $state->getServerAnchorLast($syncType);
Horde::logMessage("SyncML: reading changed items from database", __FILE__, __LINE__, PEAR_LOG_DEBUG);
$state->setChangedItems($hordeType, $registry->call($hordeType. '/listBy', array('action' => 'modify', 'timestamp' => $refts)));
Horde::logMessage("SyncML: reading deleted items from database", __FILE__, __LINE__, PEAR_LOG_DEBUG);
$state->setDeletedItems($hordeType, $registry->call($hordeType. '/listBy', array('action' => 'delete', 'timestamp' => $refts)));
Horde::logMessage("SyncML: reading added items from database", __FILE__, __LINE__, PEAR_LOG_DEBUG);
$state->setAddedItems($hordeType, $registry->call($hordeType. '/listBy', array('action' => 'add', 'timestamp' => $refts)));
$this->_syncDataLoaded = TRUE;
return count($state->getChangedItems($hordeType)) +
count($state->getDeletedItems($hordeType)) +
count($state->getAddedItems($hordeType));
}
}

View File

@ -0,0 +1,827 @@
<?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()
{
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,34 @@
<?php
/**
* Class representing vAlarms.
*
* $Horde: framework/iCalendar/iCalendar/valarm.php,v 1.8 2004/08/13 19:11:35 karsten Exp $
*
* Copyright 2003-2004 Mike Cochrane <mike@graftonhall.co.nz>
*
* 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>
* @version $Revision$
* @since Horde 3.0
* @package Horde_iCalendar
*/
class Horde_iCalendar_valarm extends Horde_iCalendar {
function getType()
{
return 'vAlarm';
}
function parsevCalendar($data)
{
parent::parsevCalendar($data, 'VALARM');
}
function exportvCalendar()
{
return parent::_exportvData('VALARM');
}
}

View File

@ -0,0 +1,130 @@
<?php
require_once PHPGW_SERVER_ROOT.'/phpgwapi/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.2 2004/08/18 03:16:24 chuck Exp $
*
* Copyright 2003-2004 Karsten Fourmont (karsten@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>
* @version $Revision$
* @package Horde_iCalendar
*/
class Horde_iCalendar_vcard extends Horde_iCalendar {
function getType()
{
return 'vcard';
}
function parsevCalendar($data)
{
return parent::parsevCalendar($data, 'vcard');
}
/**
* Unlike vevent and vtodo, a vcard is normally not enclosed in an
* iCalendar container. (BEGIN..END)
*/
function exportvCalendar()
{
#$requiredAttributes['BODY'] = '';
$requiredAttributes['VERSION'] = '2.1';
foreach ($requiredAttributes as $name => $default_value) {
if (is_a($this->getattribute($name), 'PEAR_Error')) {
$this->setAttribute($name, $default_value);
}
}
return $this->_exportvData('VCARD') . $this->_newline;
}
/**
* 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;
}
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)
{
require_once 'Mail/RFC822.php';
require_once 'Horde/MIME.php';
static $rfc822;
if (is_null($rfc822)) {
$rfc822 = &new Mail_RFC822();
}
$rfc822->validateMailbox($address);
return MIME::rfc822WriteAddress($address->mailbox, $address->host);
}
}

View File

@ -0,0 +1,230 @@
<?php
/**
* Class representing vEvents.
*
* $Horde: framework/iCalendar/iCalendar/vevent.php,v 1.31 2004/08/18 03:16:24 chuck Exp $
*
* Copyright 2003-2004 Mike Cochrane <mike@graftonhall.co.nz>
*
* 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>
* @version $Revision$
* @since Horde 3.0
* @package Horde_iCalendar
*/
class Horde_iCalendar_vevent extends Horde_iCalendar {
function getType()
{
return 'vEvent';
}
function parsevCalendar($data)
{
parent::parsevCalendar($data, 'VEVENT');
}
function exportvCalendar()
{
// Default values.
$requiredAttributes = array();
$requiredAttributes['DTSTAMP'] = time();
$requiredAttributes['ORGANIZER'] = 'Unknown Organizer';
$requiredAttributes['UID'] = $this->_exportDateTime(time()) . '@' . $_SERVER['SERVER_NAME'];
$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 null;
}
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 object 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 object 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

@ -0,0 +1,290 @@
<?php
/**
* Class representing vFreebusys.
*
* $Horde: framework/iCalendar/iCalendar/vfreebusy.php,v 1.16 2004/08/18 03:16:24 chuck Exp $
*
* Copyright 2003-2004 Mike Cochrane <mike@graftonhall.co.nz>
*
* 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>
* @version $Revision$
* @since Horde 3.0
* @package Horde_iCalendar
*/
class Horde_iCalendar_vfreebusy extends Horde_iCalendar {
var $_busyPeriods = array();
function getType()
{
return 'vFreebusy';
}
function parsevCalendar($data)
{
parent::parsevCalendar($data, 'VFREEBUSY');
// Do something with all the busy periods.
foreach ($this->_attributes as $key => $attribute) {
if ($attribute['name'] == 'FREEBUSY') {
foreach ($attribute['value'] as $value) {
if (array_key_exists('duration', $attribute['value'])) {
$this->addBusyPeriod('BUSY', $value['start'], null, $value['duration']);
} else {
$this->addBusyPeriod('BUSY', $value['start'], $value['end']);
}
}
unset($this->_attributes[$key]);
}
}
}
function exportvCalendar()
{
foreach ($this->_busyPeriods as $start => $end) {
$periods = array(array('start' => $start, 'end' => $end));
$this->setAttribute('FREEBUSY', $periods);
}
$res = parent::_exportvData('VFREEBUSY');
foreach ($this->_attributes as $key => $attribute) {
if ($attribute['name'] == 'FREEBUSY') {
unset($this->_attributes[$key]);
}
}
return $res;
}
/**
* Get a display name for this object.
*/
function getName()
{
$name = '';
$method = !empty($this->_container) ?
$this->_container->getAttribute('METHOD') : 'PUBLISH';
if (is_a($method, 'PEAR_Error') || $method == 'PUBLISH') {
$attr = 'ORGANIZER';
} else if ($method == 'REPLY') {
$attr = 'ATTENDEE';
}
$name = $this->getAttribute($attr, true);
if (array_key_exists('CN', $name[0])) {
return $name[0]['CN'];
}
$name = $this->getAttribute($attr);
if (is_a($name, 'PEAR_Error')) {
return '';
} else {
$name = parse_url($name);
return $name['path'];
}
}
/**
* Get the email address for this object.
*/
function getEmail()
{
$name = '';
$method = !empty($this->_container)
? $this->_container->getAttribute('METHOD') : 'PUBLISH';
if (is_a($method, 'PEAR_Error') || $method == 'PUBLISH') {
$attr = 'ORGANIZER';
} else if ($method == 'REPLY') {
$attr = 'ATTENDEE';
}
$name = $this->getAttribute($attr);
if (is_a($name, 'PEAR_Error')) {
return '';
} else {
$name = parse_url($name);
return $name['path'];
}
}
function getBusyPeriods()
{
return $this->_busyPeriods;
}
/**
* Return all the free periods of time in a given period.
*/
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) {
$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;
}
/**
* Add a busy period to the info.
*/
function addBusyPeriod($type, $start, $end = null, $duration = null)
{
if ($type == "FREE") {
// Make sure this period is not marked as busy.
return false;
}
// Calculate the end time is 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. Extend to the
// length of the longest of the two.
$this->_busyPeriods[$start] = max($end, $this->_busyPeriods[$start]);
} else {
// Add a new busy period.
$this->_busyPeriods[$start] = $end;
}
return true;
}
/**
* Get the timestamp of the start of the time period this free
* busy information covers.
*/
function getStart()
{
if (!is_a($this->getAttribute('DTSTART'), 'PEAR_Error')) {
return $this->getAttribute('DTSTART');
} else if (count($this->_busyPeriods)) {
return min(array_keys($this->_busyPeriods));
} else {
return false;
}
}
/**
* Get the timestamp of the end of the time period this free busy
* information covers.
*/
function getEnd()
{
if (!is_a($this->getAttribute('DTEND'), 'PEAR_Error')) {
return $this->getAttribute('DTEND');
} else if (count($this->_busyPeriods)) {
return max(array_values($this->_busyPeriods));
} else {
return false;
}
}
/**
* Merge the busy periods of another VFreebusy into this one.
*/
function merge($freebusy, $simplify = true)
{
if (!is_a($freebusy, 'Horde_iCalendar_vfreebusy')) {
return false;
}
foreach ($freebusy->getBusyPeriods() as $start => $end) {
$this->addBusyPeriod('BUSY', $start, $end);
}
$thisattr = $this->getAttribute('DTSTART');
$thatattr = $freebusy->getAttribute('DTSTART');
if (is_a($thisattr, 'PEAR_Error') && !is_a($thatattr, 'PEAR_Error')) {
$this->setAttribute('DTSTART', $thatattr);
} elseif (!is_a($thatattr, 'PEAR_Error')) {
if ($thatattr > $thisattr) {
$this->setAttribute('DTSTART', $thatattr);
}
}
$thisattr = $this->getAttribute('DTEND');
$thatattr = $freebusy->getAttribute('DTEND');
if (is_a($thisattr, 'PEAR_Error') && !is_a($thatattr, 'PEAR_Error')) {
$this->setAttribute('DTEND', $thatattr);
} elseif (!is_a($thatattr, 'PEAR_Error')) {
if ($thatattr < $thisattr) {
$this->setAttribute('DTEND', $thatattr);
}
}
if ($simplify) {
$this->simplify();
}
return true;
}
/**
* Remove all overlaps and simplify the busy periods array as much
* as possible.
*/
function simplify()
{
$checked = array();
$checkedEmpty = true;
foreach ($this->_busyPeriods as $start => $end) {
if ($checkedEmpty) {
$checked[$start] = $end;
$checkedEmpty = false;
} else {
$added = false;
foreach ($checked as $testStart => $testEnd) {
if ($start == $testStart) {
$checked[$testStart] = max($testEnd, $end);
$added = true;
} else if ($end <= $testEnd && $end >= $testStart) {
unset($checked[$testStart]);
$checked[min($testStart, $start)] = max($testEnd, $end);
$added = true;
}
if ($added) {
break;
}
}
if (!$added) {
$checked[$start] = $end;
}
}
}
ksort($checked, SORT_NUMERIC);
$this->_busyPeriods = $checked;
}
}

View File

@ -0,0 +1,34 @@
<?php
/**
* Class representing vJournals.
*
* $Horde: framework/iCalendar/iCalendar/vjournal.php,v 1.8 2004/08/13 19:11:35 karsten Exp $
*
* Copyright 2003-2004 Mike Cochrane <mike@graftonhall.co.nz>
*
* 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>
* @version $Revision$
* @since Horde 3.0
* @package Horde_iCalendar
*/
class Horde_iCalendar_vjournal extends Horde_iCalendar {
function getType()
{
return 'vJournal';
}
function parsevCalendar($data)
{
parent::parsevCalendar($data, 'VJOURNAL');
}
function exportvCalendar()
{
return parent::_exportvData('VJOURNAL');
}
}

View File

@ -0,0 +1,49 @@
<?php
require_once PHPGW_SERVER_ROOT.'/phpgwapi/inc/horde/Horde/iCalendar.php';
/**
* Class representing vNotes.
*
* $Horde: framework/iCalendar/iCalendar/vnote.php,v 1.2 2004/08/13 19:11:35 karsten Exp $
*
* Copyright 2003-2004 Mike Cochrane <mike@graftonhall.co.nz>
*
* 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 <fourmont@gmx.de>
* @version $Revision$
* @package Horde_iCalendar
*/
class Horde_iCalendar_vnote extends Horde_iCalendar {
function getType()
{
return 'vNote';
}
function parsevCalendar($data)
{
return parent::parsevCalendar($data, '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') . $this->_newline;
}
}

View File

@ -0,0 +1,78 @@
<?php
/**
* Class representing vTimezones.
*
* $Horde: framework/iCalendar/iCalendar/vtimezone.php,v 1.8 2004/08/13 19:11:35 karsten Exp $
*
* Copyright 2003-2004 Mike Cochrane <mike@graftonhall.co.nz>
*
* 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>
* @version $Revision$
* @since Horde 3.0
* @package Horde_iCalendar
*/
class Horde_iCalendar_vtimezone extends Horde_iCalendar {
function getType()
{
return 'vTimeZone';
}
function parsevCalendar($data)
{
parent::parsevCalendar($data, 'VTIMEZONE');
}
function exportvCalendar()
{
return parent::_exportvData('VTIMEZONE');
}
}
/**
* @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

@ -0,0 +1,90 @@
<?php
/**
* Class representing vTodos.
*
* $Horde: framework/iCalendar/iCalendar/vtodo.php,v 1.13 2004/08/13 19:11:35 karsten Exp $
*
* Copyright 2003-2004 Mike Cochrane <mike@graftonhall.co.nz>
*
* 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>
* @version $Revision$
* @since Horde 3.0
* @package Horde_iCalendar
*/
class Horde_iCalendar_vtodo extends Horde_iCalendar {
function getType()
{
return 'vTodo';
}
function parsevCalendar($data)
{
parent::parsevCalendar($data, '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

@ -0,0 +1,286 @@
<?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_1', '-//SYNCML//DTD SyncML 1.1//EN');
define('DPI_DTD_DEVINF_1_1', '-//SYNCML//DTD DevInf 1.1//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');
/**
* Copyright 2003-2005 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.
*
* $Horde: framework/XML_WBXML/WBXML.php,v 1.14 2005/01/03 13:09:24 jan Exp $
*
* @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);
$out .= chr($bytes3);
$out .= chr($bytes2);
$out .= chr($bytes1);
$out .= 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);
$out .= chr($bytes2);
$out .= chr($bytes1);
$out .= 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);
$out .= chr($bytes1);
$out .= chr($bytes0);
} elseif ($i > 127) {
$bytes0 = 0 | XML_WBXML::getBits(0, $i);
$bytes1 = 128 | XML_WBXML::getBits(1, $i);
$out .= chr($bytes1);
$out .= 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
* @var array $_DPIString
*/
$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,
// 0xFD2 => DPI_DTD_DEVINF_1_1,
);
return isset($DPIString[$i]) ? $DPIString[$i] : null;
}
function getDPIInt($dpi)
{
/**
* ADD CHAPTER
* @var array $_DPIInt
*/
$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 we
// should use the string table.
// 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
* @var array $_charsetString
*/
$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
* @var array $_charsetInt
*/
$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

@ -0,0 +1,153 @@
<?php
/**
* $Horde: framework/XML_WBXML/WBXML/ContentHandler.php,v 1.11 2005/01/20 00:01:19 jan Exp $
*
* Copyright 2003-2005 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.
*
* From Binary XML Content Format Specification Version 1.3, 25 July 2001
* found at http://www.wapforum.org
*
* @package XML_WBXML
*/
class XML_WBXML_ContentHandler {
var $_currentUri;
var $_output = '';
var $_opaqueHandler;
/**
* Charset.
*/
var $_charset = 'UTF-8';
/**
* WBXML Version.
* 1, 2, or 3 supported
*/
var $_wbxmlVersion = 2;
function XML_WBXML_ContentHandler()
{
$this->_currentUri = &new XML_WBXML_LifoQueue();
}
function raiseError($error)
{
include_once '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 = 2;
}
function getOutput()
{
return $this->_output;
}
function startElement($uri, $element, $attrs)
{
$this->_output .= '<' . $element;
$currentUri = $this->_currentUri->top();
if ((!$currentUri) || ($currentUri != $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)
{
// I can check the first chanracter and see if it is WBXML.
if (ord($o[0]) < 10) {
// Should decode this, I really need a call back function.
} else {
$this->_output .= $o;
}
}
function setOpaqueHandler($opaqueHandler)
{
$this->_opaqueHandler = $opaqueHandler;
}
function removeOpaqueHandler()
{
unset($this->_opaqueHandler);
}
}
class XML_WBXML_LifoQueue {
var $_queue = array();
function XML_WBXML_LifoQueue()
{
}
function push($obj)
{
array_push($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

@ -0,0 +1,150 @@
<?php
/**
* $Horde: framework/XML_WBXML/WBXML/DTD.php,v 1.7 2005/01/03 13:09:25 jan Exp $
*
* From Binary XML Content Format Specification Version 1.3, 25 July 2001
* found at http://www.wapforum.org
*
* Copyright 2003-2005 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.
*
* @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);
$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

@ -0,0 +1,85 @@
<?php
include_once 'XML/WBXML/DTD.php';
/**
* $Horde: framework/XML_WBXML/WBXML/DTD/SyncML.php,v 1.7 2005/01/03 13:09:25 jan Exp $
*
* From Binary XML Content Format Specification Version 1.3, 25 July 2001
* found at http://www.wapforum.org
*
* Copyright 2003-2005 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.
*
* @package XML_WBXML
*/
class XML_WBXML_DTD_SyncML extends XML_WBXML_DTD {
function init()
{
$this->setTag(5, 'Add'); // 0x05
$this->setTag(6, 'Alert'); // 0x06
$this->setTag(7, 'Archive'); // 0x07
$this->setTag(8, 'Atomic'); // 0x08
$this->setTag(9, 'Chal'); // 0x09
$this->setTag(10, 'Cmd'); // 0x0A
$this->setTag(11, 'CmdID'); // 0x0B
$this->setTag(12, 'CmdRef'); // 0x0C
$this->setTag(13, 'Copy'); // 0x0D
$this->setTag(14, 'Cred'); // 0x0E
$this->setTag(15, 'Data'); // 0x0F
$this->setTag(16, 'Delete'); // 0x10
$this->setTag(17, 'Exec'); // 0x11
$this->setTag(18, 'Final'); // 0x12
$this->setTag(19, 'Get'); // 0x13
$this->setTag(20, 'Item'); // 0x14
$this->setTag(21, 'Lang'); // 0x15
$this->setTag(22, 'LocName'); // 0x16
$this->setTag(23, 'LocURI'); // 0x17
$this->setTag(24, 'Map'); // 0x18
$this->setTag(25, 'MapItem'); // 0x19
$this->setTag(26, 'Meta'); // 0x1A
$this->setTag(27, 'MsgID'); // 0x1B
$this->setTag(28, 'MsgRef'); // 0x1C
$this->setTag(29, 'NoRssp'); // 0x1D
$this->setTag(30, 'NoResults'); // 0x1E
$this->setTag(31, 'Put'); // 0x1F
$this->setTag(32, 'Replace'); // 0x10
$this->setTag(33, 'RespURI'); // 0x21
$this->setTag(34, 'Results'); // 0x22
$this->setTag(35, 'Search'); // 0x23
$this->setTag(36, 'Sequence'); // 0x24
$this->setTag(37, 'SessionID'); // 0x25
$this->setTag(38, 'SftDel'); // 0x26
$this->setTag(39, 'Source'); // 0x27
$this->setTag(40, 'SourceRef'); // 0x28
$this->setTag(41, 'Status'); // 0x29
$this->setTag(42, 'Sync'); // 0x2A
$this->setTag(43, 'SyncBody'); // 0x2B
$this->setTag(44, 'SyncHdr'); // 0x2C
$this->setTag(45, 'SyncML'); // 0x2D
$this->setTag(46, 'Target'); // 0x2E
$this->setTag(47, 'TargetRef'); // 0x2F
$this->setTag(48, 'Reserved for future use.'); // 0x30
$this->setTag(49, 'VerDTD'); // 0x31
$this->setTag(50, 'VerProto'); // 0x32
$this->setTag(51, 'NumberOfChanged'); // 0x33
$this->setTag(52, 'MoreData'); // 0x34
if ($this->version == 0) {
$this->setCodePage(0, '-//SYNCML//DTD SyncML 1.0//EN', 'syncml:syncml');
$this->setCodePage(1, '-//SYNCML//DTD MetInf 1.0//EN', 'syncml:metinf');
$this->setURI('syncml:syncml');
} else {
$this->setCodePage(0, '-//SYNCML//DTD SyncML 1.1//EN', 'syncml:syncml1.1');
$this->setCodePage(1, '-//SYNCML//DTD MetInf 1.1//EN', 'syncml:metinf1.1');
$this->setURI('syncml:syncml1.1');
}
}
}

View File

@ -0,0 +1,70 @@
<?php
include_once 'XML/WBXML/DTD.php';
/**
* $Horde: framework/XML_WBXML/WBXML/DTD/SyncMLDevInf.php,v 1.5 2005/01/03 13:09:25 jan Exp $
*
* Copyright 2003-2005 Anthony Mills <amills@pyramid6.com>
*
* From Binary XML Content Format Specification Version 1.3, 25 July 2001
* found at http://www.wapforum.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.
*
* @package XML_WBXML
*/
class XML_WBXML_DTD_SyncMLDevInf extends XML_WBXML_DTD {
function init()
{
$this->setTag(5, 'CTCap'); // 0x05
$this->setTag(6, 'CTType'); // 0x06
$this->setTag(7, 'DataStore'); // 0x07
$this->setTag(8, 'DataType'); // 0x08
$this->setTag(9, 'DevID'); // 0x09
$this->setTag(10, 'DevInf'); // 0x0A
$this->setTag(11, 'DevTyp'); // 0x0B
$this->setTag(12, 'DisplayName'); // 0x0C
$this->setTag(13, 'DSMem'); // 0x0D
$this->setTag(14, 'Ext'); // 0x0E
$this->setTag(15, 'FwV'); // 0x0F
$this->setTag(16, 'HwV'); // 0x10
$this->setTag(17, 'Man'); // 0x11
$this->setTag(18, 'MaxGUIDSize'); // 0x12
$this->setTag(19, 'MaxID'); // 0x13
$this->setTag(20, 'MaxMem'); // 0x14
$this->setTag(21, 'Mod'); // 0x15
$this->setTag(22, 'OEM'); // 0x15
$this->setTag(23, 'ParamName'); // 0x17
$this->setTag(24, 'PropName'); // 0x18
$this->setTag(25, 'Rx'); // 0x19
$this->setTag(26, 'Rx-Pref'); // 0x1A
$this->setTag(27, 'SharedMem'); // 0x1B
$this->setTag(28, 'Size'); // 0x1C
$this->setTag(29, 'SourceRef'); // 0x1D
$this->setTag(30, 'SwV'); // 0x1E
$this->setTag(31, 'SyncCap'); // 0x1F
$this->setTag(32, 'SyncType'); // 0x20
$this->setTag(33, 'Tx'); // 0x21
$this->setTag(34, 'Tx-Pref'); // 0x22
$this->setTag(35, 'ValEnum'); // 0x23
$this->setTag(36, 'VerCT'); // 0x24
$this->setTag(37, 'VerDTD'); // 0x25
$this->setTag(38, 'Xnam'); // 0x26
$this->setTag(39, 'Xval'); // 0x27
$this->setTag(40, 'UTC'); // 0x28
$this->setTag(41, 'SupportNumberOfChanges'); // 0x29
$this->setTag(42, 'SupportLargeObjs'); // 0x2A
if ($this->version == 0) {
$this->setCodePage(0, '-//SYNCML//DTD DevInf 1.0//EN', 'syncml:devinf');
$this->setURI('sync:devinf');
} else {
$this->setCodePage(0, '-//SYNCML//DTD DevInf 1.1//EN', 'syncml:devinf1.1');
$this->setURI('sync:devinf1.1');
}
}
}

View File

@ -0,0 +1,51 @@
<?php
include_once 'XML/WBXML/DTD.php';
/**
* $Horde: framework/XML_WBXML/WBXML/DTD/SyncMLMetInf.php,v 1.5 2005/01/03 13:09:25 jan Exp $
*
* Copyright 2003-2005 Anthony Mills <amills@pyramid6.com>
*
* From Binary XML Content Format Specification Version 1.3, 25 July 2001
* found at http://www.wapforum.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.
*
* @package XML_WBXML
*/
class XML_WBXML_DTD_SyncMLMetInf extends XML_WBXML_DTD {
function init()
{
$this->setTag(5, 'Anchor'); // 0x05
$this->setTag(6, 'EMI'); // 0x06
$this->setTag(7, 'Format'); // 0x07
$this->setTag(8, 'FreeID'); // 0x08
$this->setTag(9, 'FreeMem'); // 0x09
$this->setTag(10, 'Last'); // 0x0A
$this->setTag(11, 'Mark'); // 0x0B
$this->setTag(12, 'MaxMsgSize'); // 0x0C
$this->setTag(13, 'Mem'); // 0x0D
$this->setTag(14, 'MetInf'); // 0x0E
$this->setTag(15, 'Next'); // 0x0F
$this->setTag(16, 'NextNonce'); // 0x10
$this->setTag(17, 'SharedMem'); // 0x11
$this->setTag(18, 'Size'); // 0x12
$this->setTag(19, 'Type'); // 0x13
$this->setTag(20, 'Version'); // 0x14
$this->setTag(21, 'MaxObjSize'); // 0x15
if ($this->version == 0) {
$this->setCodePage(0, '-//SYNCML//DTD SyncML 1.0//EN', 'syncml:syncml');
$this->setCodePage(1, '-//SYNCML//DTD MetInf 1.0//EN', 'syncml:metinf');
$this->setURI('syncml:metinf');
} else {
$this->setCodePage(0, '-//SYNCML//DTD SyncML 1.1//EN', 'syncml:syncml1.1');
$this->setCodePage(1, '-//SYNCML//DTD MetInf 1.1//EN', 'syncml:metinf1.1');
$this->setURI('syncml:metinf1.1');
}
}
}

View File

@ -0,0 +1,56 @@
<?php
include_once 'XML/WBXML/DTD/SyncML.php';
include_once 'XML/WBXML/DTD/SyncMLMetInf.php';
include_once 'XML/WBXML/DTD/SyncMLDevInf.php';
/**
* $Horde: framework/XML_WBXML/WBXML/DTDManager.php,v 1.4 2005/01/03 13:09:25 jan Exp $
*
* Copyright 2003-2005 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.
*
* From Binary XML Content Format Specification Version 1.3, 25 July
* 2001 found at http://www.wapforum.org
*
* @package XML_WBXML
*/
class XML_WBXML_DTDManager {
var $_strDTD = array();
var $_strDTDURI = array();
function XML_WBXML_DTDManager()
{
$this->registerDTD('-//SYNCML//DTD SyncML 1.0//EN', 'syncml:syncml', new XML_WBXML_DTD_SyncML(0));
$this->registerDTD('-//SYNCML//DTD SyncML 1.1//EN', 'syncml:syncml1.1', new XML_WBXML_DTD_SyncML(1));
$this->registerDTD('-//SYNCML//DTD MetInf 1.0//EN', 'syncml:metinf', new XML_WBXML_DTD_SyncMLMetInf(0));
$this->registerDTD('-//SYNCML//DTD MetInf 1.1//EN', 'syncml:metinf1.1', new XML_WBXML_DTD_SyncMLMetInf(1));
$this->registerDTD('-//SYNCML//DTD DevInf 1.0//EN', 'syncml:devinf', new XML_WBXML_DTD_SyncMLDevInf(0));
$this->registerDTD('-//SYNCML//DTD DevInf 1.1//EN', 'syncml:devinf1.1', new XML_WBXML_DTD_SyncMLDevInf(1));
}
function getInstance($publicIdentifier)
{
return isset($this->_strDTD[$publicIdentifier]) ? $this->_strDTD[$publicIdentifier] : null;
}
function getInstanceURI($uri)
{
$uri = strtolower($uri);
return isset($this->_strDTDURI[$uri]) ? $this->_strDTDURI[$uri] : null;
}
function registerDTD($publicIdentifier, $uri, &$dtd)
{
$dtd->setDPI($publicIdentifier);
$this->_strDTD[$publicIdentifier] = $dtd;
$this->_strDTDURI[$uri] = $dtd;
}
}

View File

@ -0,0 +1,618 @@
<?php
include_once 'XML/WBXML.php';
include_once 'XML/WBXML/DTDManager.php';
include_once 'XML/WBXML/ContentHandler.php';
/**
* $Horde: framework/XML_WBXML/WBXML/Decoder.php,v 1.23 2005/01/03 13:09:25 jan Exp $
*
* Copyright 2003-2005 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.
*
* From Binary XML Content Format Specification Version 1.3, 25 July
* 2001 found at http://www.wapforum.org
*
* @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;
/**
* The DTD Manager.
* @var object XML_WBXML_DTDManager $dtdManager
*/
var $_dtdManager;
/**
* The string position.
* @var integer $_strpos
*/
var $_strpos;
/**
* Use wbxml2xml from libwbxml.
* @var string $_wbxml2xml
*/
var $_wbxml2xml = '/usr/bin/wbxml2xml';
/**
* Arguments to pass to wbxml2xml.
* @var string $_wbxml2xml_args
*/
var $_wbxml2xml_args = '-o - -';
/**
* Constructor.
*/
function XML_WBXML_Decoder()
{
if (empty($this->_wbxml2xml) || !is_executable($this->_wbxml2xml)) {
$this->_dtdManager = &new XML_WBXML_DTDManager();
}
}
/**
* Return one byte from the input stream.
*
* @param string $input The WBXML input string.
*/
function getByte($input)
{
return ord($input{$this->_strpos++});
}
/**
* Takes a WBXML input document and returns decoded XML.
*
* @param string $wbxml The WBXML document to decode.
*
* @return string The decoded XML document.
*/
function decode($wbxml)
{
// Figure out if we're going to use wbxml2xml to do the
// conversion, or do it all in PHP code.
if (!empty($this->_wbxml2xml) && is_executable($this->_wbxml2xml)) {
$descriptorspec = array(
0 => array('pipe', 'r'),
1 => array('pipe', 'w'),
);
$wbxml2xml = proc_open($this->_wbxml2xml . ' ' . $this->_wbxml2xml_args,
$descriptorspec, $pipes);
if (is_resource($wbxml2xml)) {
fwrite($pipes[0], $wbxml);
fclose($pipes[0]);
// Grab the output of wbxml2xml.
$xml = '';
while (!feof($pipes[1])) {
$xml .= fread($pipes[1], 8192);
}
fclose($pipes[1]);
$rv = proc_close($wbxml2xml);
return $xml;
} else {
return PEAR::raiseError('wbxml2xml failed');
}
} else {
$this->_strpos = 0;
// Get Version Number from Section 5.4
// version = u_int8
// currently 1, 2 or 3
$this->_wbxmlVersion = $this->getVersionNumber($wbxml);
// 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);
// Get String Table from 5.7
// strb1 = length *byte
$this->_stringTable = $this->getStringTable($wbxml, $this->_charset);
// 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->_ch = &new XML_WBXML_ContentHandler();
// 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);
}
$this->_attributeDTD = $this->_tagDTD;
while ($this->_strpos < strlen($wbxml)) {
$this->_decode($wbxml);
}
return $this->_ch->getOutput();
}
}
function getVersionNumber($input)
{
return $this->getByte($input);
}
function getDocumentPublicIdentifier($input)
{
// 'dpiType' 'dpiNumber'
$dpistruct = array();
$i = XML_WBXML::MBUInt32ToInt($input, $this->_strpos);
if ($i == 0) {
$dpiStruct['dpiType'] = 2;
$dpiStruct['dpiNumber'] = $this->getByte($input);
} else {
$dpiStruct['dpiType'] = 1;
$dpiStruct['dpiNumber'] = $i;
}
return $dpiStruct;
}
function getDocumentPublicIdentifierImpl($dpiType, $dpiNumber, $st)
{
if ($dpiType == 1) {
return XML_WBXML::getDPIString($dpiNumber);
} else {
return isset($st[$dpiNumber]) ? $st[$dpiNumber] : 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 getCharset($input)
{
$cs = XML_WBXML::MBUInt32ToInt($input, $this->_strpos);
return $charset = XML_WBXML::getCharsetString($cs);
}
/**
* @TODO needs to be fixed. Does this still really need to be
* fixed?
*/
function getStringTable($input, $cs)
{
$stringTable = array();
$size = XML_WBXML::MBUInt32ToInt($input, $this->_strpos);
// A hack to make it work with arrays.
// How/why is this necessary?
$str = 'j';
$numstr = 0;
$start = 0;
$j = 0;
for ($i = 0; $i < $size; $i++ ) {
/* May need to fix the null detector for more than single
* byte charsets like ASCII, UTF-8, etc. */
$ch = $input[$this->_strpos++];
if (ord($ch) == 0) {
$stringTable[$numstr++] = $str;
$str = '#';
$start = $i + 1;
} else {
$str[$j++] = $ch;
}
}
if ($start < $size) {
$stringTable[$numstr++] = $str;
}
return $stringTable;
}
function _decode($input)
{
$token = $this->getByte($input);
$str = '';
switch ($token) {
case XML_WBXML_GLOBAL_TOKEN_STR_I:
// Section 5.8.4.1
$str = $this->termstr($input);
$this->_ch->characters($str);
break;
case XML_WBXML_GLOBAL_TOKEN_STR_T:
// Section 5.8.4.1
$str = $this->_stringTable[XML_WBXML::MBUInt32ToInt($intput)];
$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->_stringTable[XML_WBXML::MBUInt32ToInt($intput)];
$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("WBXML global token processing instruction(PI, " + token + ") is unsupported!");
break;
case XML_WBXML_GLOBAL_TOKEN_LITERAL:
// Section 5.8.4.5
$str = $this->_stringTable[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->_stringTable[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->_stringTable[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->_stringTable[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);
$b = substr($input, $this->_strpos, $this->_strpos + $size);
$this->_strpos += $size;
$this->_ch->opaque($b);
// 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);
// }
// This can cause some problems. We may have to use a
// event based decoder.
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);
$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);
$this->parseTag($input, $str, $hasAttributes, $hasContent);
if ($realToken == 0x0f) {
// FIXME Don't remember this one.
$this->_isData = true;
}
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';
}
if ($tag == 'Data') {
$this->_isData = false;
}
$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->_stringTable[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->_stringTable[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->_stringTable[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 = 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);
}
/**
* @TODO FIXME reads a null terminated string.
*/
function termstr($input)
{
$str = '#';
$i = 0;
$ch = $input[$this->_strpos++];
while (ord($ch) != 0) {
$str[$i++] = $ch;
$ch = $input[$this->_strpos++];
}
return $str;
}
}

View File

@ -0,0 +1,486 @@
<?php
include_once 'XML/WBXML.php';
include_once 'XML/WBXML/ContentHandler.php';
include_once 'XML/WBXML/DTDManager.php';
include_once 'Horde/String.php';
/**
* $Horde: framework/XML_WBXML/WBXML/Encoder.php,v 1.27 2005/01/03 13:09:25 jan Exp $
*
* Copyright 2003-2005 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.
*
* From Binary XML Content Format Specification Version 1.3, 25 July
* 2001 found at http://www.wapforum.org
*
* @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;
var $_subParserStack = 0;
/**
* These will store the startElement params to see if we should
* call startElementImp or startEndElementImp.
*/
var $_storeURI;
var $_storeName;
var $_storeAttributes;
/**
* The XML parser.
* @var resource $_parser
*/
var $_parser;
/**
* The DTD Manager.
* @var object XML_WBXML_DTDManager $dtdManager
*/
var $_dtdManager;
var $_indent = 0;
/**
* Use wbxml2xml from libwbxml.
* @var string $_xml2wbxml
*/
var $_xml2wbxml = '/usr/bin/xml2wbxml';
/**
* Arguments to pass to xml2wbxml.
* @var string $_xml2wbxml_args
*/
var $_xml2wbxml_args = '-k -n -v 1.2 -o - -';
/**
* Constructor.
*/
function XML_WBXML_Encoder()
{
if (empty($this->_xml2wbxml) || !is_executable($this->_xml2wbxml)) {
$this->_stringTable = &new XML_WBXML_HashTable();
$this->_dtdManager = &new XML_WBXML_DTDManager();
}
}
/**
* Take the input $xml and turn it into WBXML.
*/
function encode($xml)
{
if (!empty($this->_xml2wbxml) && is_executable($this->_xml2wbxml)) {
$descriptorspec = array(
0 => array('pipe', 'r'),
1 => array('pipe', 'w'),
);
$xml2wbxml = proc_open($this->_xml2wbxml . ' ' . $this->_xml2wbxml_args,
$descriptorspec, $pipes);
if (is_resource($xml2wbxml)) {
fwrite($pipes[0], $xml);
fclose($pipes[0]);
// Grab the output of xml2wbxml.
$wbxml = '';
while (!feof($pipes[1])) {
$wbxml .= fread($pipes[1], 8192);
}
fclose($pipes[1]);
$rv = proc_close($xml2wbxml);
return $wbxml;
} else {
return PEAR::raiseError('xml2wbxml failed');
}
} else {
// 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_default_handler($this->_parser, 'defaultHandler');
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);
$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 = 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);
}
/**
* Has no content, 64.
*/
function startEndElementImp($uri, $name, $attributes)
{
if (!$this->_hasWrittenHeader) {
$this->writeHeader($uri);
}
$this->writeTag($name, $attributes, false, $this->_charset);
}
function startElementImp($uri, $name, $attributes)
{
if (!$this->_hasWrittenHeader) {
$this->writeHeader($uri);
}
if ($this->_currentURI != $uri) {
$this->changecodepage($uri);
$this->_currentURI != $uri;
}
$this->writeTag($name, $attributes, true, $this->_charset);
}
function writeStartElement($isEnd)
{
if ($this->_storeName != null) {
if ($isEnd) {
$this->startEndElementImp($this->_storeURI, $this->_storeName, $this->_storeAttributes);
} else {
$this->startElementImp($this->_storeURI, $this->_storeName, $this->_storeAttributes);
}
$this->_storeURI = null;
$this->_storeName = null;
$this->_storeAttributes = null;
}
}
function startElement($uri, $name, $attributes)
{
if ($this->_subParser == null) {
$this->writeStartElement(false);
$this->_storeURI = $uri;
$this->_storeName = $name;
$this->_storeAttributes = $attributes;
} else {
$this->_subParserStack++;
}
}
function _startElement($parser, $tag, $attributes)
{
list($uri, $name) = $this->_splitURI($tag);
$this->startElement($uri, $name, $attributes);
}
function opaque($bytes)
{
if ($this->_subParser == null) {
$this->writeStartElement(false);
$this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_OPAQUE);
XML_WBXML::intToMBUInt32($this->_output, count($bytes));
$this->_output .= $bytes;
}
}
function characters($chars)
{
$chars = trim($chars);
if (strlen($chars)) {
/* We definitely don't want any whitespace. */
if ($this->_subParser == null) {
$this->writeStartElement(false);
$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);
}
}
}
}
function _characters($parser, $chars)
{
$this->characters($chars);
}
function defaultHandler($parser, $data)
{
}
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) {
$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->writeStartElement(false);
$this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_END);
} else {
$this->_subParserStack--;
if ($this->_subParserStack == 0) {
unset($this->_subParser);
}
}
}
function _endElement($parser, $tag)
{
list($uri, $name) = $this->_splitURI($tag);
$this->endElement($uri, $name);
}
function changecodepage($uri)
{
$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);
} else {
$this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_OPAQUE);
$this->_subParser = &new XML_WBXML_Encoder($this->_output);
$this->startElement($this->_storeURI, $this->_storeName, $this->_storeAttributes);
$this->_subParserStack = 2;
$this->_storeURI = null;
$this->_storeName = null;
$this->_storeAttributes = null;
}
}
/**
* Getter for property output.
*/
function getOutput($output)
{
return $this->_output;
}
}

View File

@ -0,0 +1,44 @@
<?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_ALL;
$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'] = 'HORDE';
$conf['log']['params'] = array();
$conf['log']['name'] = '/tmp/horde.log';
$conf['log']['params']['append'] = true;
$conf['log']['type'] = 'file';
$conf['log']['enabled'] = true;
$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

@ -0,0 +1,594 @@
<?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

@ -0,0 +1,102 @@
<?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'])) {
$webroot = strstr(dirname(__FILE__), '/' . array_shift(preg_split(';/;', $_SERVER['PHP_SELF'], 2, PREG_SPLIT_NO_EMPTY)));
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' => 'notes',
'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' => 'contacts',
'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' => 'calendar',
'menu_parent' => 'organizing'
);

View File

@ -0,0 +1,54 @@
<?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

@ -0,0 +1,43 @@
<?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 . 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/NLS.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();
#}