mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-24 08:53:37 +01:00
SyncML Improvements
- Multi-Domain support - Funambol encoding issues - various vCalendar flaws fixed - better pseudo exception handling
This commit is contained in:
parent
ed759ac587
commit
2ff7062b22
@ -500,6 +500,12 @@ class egw_session
|
||||
}
|
||||
$this->account_id = $GLOBALS['egw']->accounts->auto_add($this->account_lid, $passwd);
|
||||
}
|
||||
// fix maybe wrong case in username, it makes problems eg. in filemanager (name of homedir)
|
||||
if ($this->account_lid != ($lid = $GLOBALS['egw']->accounts->id2name($this->account_id)))
|
||||
{
|
||||
$this->account_lid = $lid;
|
||||
$this->login = $lid.substr($this->login,strlen($lid));
|
||||
}
|
||||
|
||||
$GLOBALS['egw_info']['user']['account_id'] = $this->account_id;
|
||||
$GLOBALS['egw']->accounts->accounts($this->account_id);
|
||||
@ -740,7 +746,8 @@ class egw_session
|
||||
in_array(basename($_SERVER['SCRIPT_NAME']),array('webdav.php','groupdav.php')))
|
||||
{
|
||||
// we generate a pseudo-sessionid from the basic auth credentials
|
||||
$sessionid = md5($_SERVER['PHP_AUTH_USER'].':'.$_SERVER['PHP_AUTH_PW'].':'.$_SERVER['HTTP_HOST'].':'.EGW_SERVER_ROOT);
|
||||
$sessionid = md5($_SERVER['PHP_AUTH_USER'].':'.$_SERVER['PHP_AUTH_PW'].':'
|
||||
.$_SERVER['HTTP_HOST'].':'.EGW_SERVER_ROOT.':'.self::getuser_ip());
|
||||
}
|
||||
elseif(!$only_basic_auth && isset($_REQUEST[self::EGW_SESSION_NAME]))
|
||||
{
|
||||
@ -830,6 +837,8 @@ class egw_session
|
||||
// This is to ensure that we authenticate to the correct domain (might not be default)
|
||||
if($GLOBALS['egw_info']['user']['domain'] && $this->account_domain != $GLOBALS['egw_info']['user']['domain'])
|
||||
{
|
||||
return false; // session not verified, domain changed
|
||||
|
||||
throw new Exception("Wrong domain! '$this->account_domain' != '{$GLOBALS['egw_info']['user']['domain']}'");
|
||||
/* if (self::ERROR_LOG_DEBUG) error_log(__METHOD__."('$sessionid','$kp3') account_domain='$this->account_domain' != '{$GLOBALS['egw_info']['user']['domain']}'=egw_info[user][domain]");
|
||||
$GLOBALS['egw']->ADOdb = null;
|
||||
@ -1071,7 +1080,7 @@ class egw_session
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($othervars) $extravars .= '&'.$othervars;
|
||||
if ($othervars) $extravars .= ($extravars?'&':'').$othervars;
|
||||
}
|
||||
|
||||
// parse extravars string into the vars array
|
||||
|
@ -19,6 +19,7 @@
|
||||
* @copyright (c) The Horde Project (http://www.horde.org/)
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
include_once 'Horde/SyncML/Command.php';
|
||||
include_once 'Horde/SyncML/Command/Status.php';
|
||||
include_once 'Horde/SyncML/Command/Alert.php';
|
||||
@ -146,7 +147,7 @@ class Horde_SyncML_SyncMLHdr extends Horde_SyncML_ContentHandler {
|
||||
|
||||
var $_maxMsgSize;
|
||||
|
||||
function getStateFromSession($sourceURI, $locName, $sessionID)
|
||||
function &getStateFromSession($sourceURI, $locName, $sessionID)
|
||||
{
|
||||
// Remove any existing session since we'll be contructing a
|
||||
// custom session id.
|
||||
@ -185,7 +186,7 @@ class Horde_SyncML_SyncMLHdr extends Horde_SyncML_ContentHandler {
|
||||
}
|
||||
|
||||
|
||||
if($_SESSION['SyncML.state']->isAuthorized()) {
|
||||
if ($_SESSION['SyncML.state']->isAuthorized()) {
|
||||
Horde::logMessage('SyncML['. session_id() .']: session is authorized',
|
||||
__FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
}
|
||||
@ -214,29 +215,22 @@ class Horde_SyncML_SyncMLHdr extends Horde_SyncML_ContentHandler {
|
||||
{
|
||||
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.
|
||||
#Horde::logMessage('SymcML: SyncHdr done. Try to load state from session.', __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
$state = $this->getStateFromSession($this->_sourceURI, $this->_locName, $this->_sessionID);
|
||||
|
||||
Horde::logMessage('SyncML['. session_id() .']: package '
|
||||
Horde::logMessage('SyncML['. session_id() .']: package '
|
||||
. $this->_msgID.' +++++++++++++++++++++ started',
|
||||
__FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
|
||||
// Find the state.
|
||||
//Horde::logMessage('SymcML: SyncHdr done. Try to load state from session.',
|
||||
// __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
$state =& $this->getStateFromSession($this->_sourceURI, $this->_locName, $this->_sessionID);
|
||||
|
||||
$state->setVersion($this->_version);
|
||||
$state->setMsgID($this->_msgID);
|
||||
$state->setTargetURI($this->_targetURI);
|
||||
$state->setWBXML(is_a($this->_output, 'XML_WBXML_Encoder'));
|
||||
|
||||
if(isset($this->_credData)
|
||||
if (isset($this->_credData)
|
||||
&& isset($this->_locName)
|
||||
&& !$state->isAuthorized()) {
|
||||
$state->setPassword($this->_credData);
|
||||
@ -247,14 +241,7 @@ class Horde_SyncML_SyncMLHdr extends Horde_SyncML_ContentHandler {
|
||||
$state->setMaxMsgSize($this->_maxMsgSize);
|
||||
}
|
||||
|
||||
#$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;
|
||||
// $_SESSION['SyncML.state'] = $state;
|
||||
|
||||
#Horde::logMessage('SymcML: session id 2 =' . session_id(), __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
|
||||
@ -289,14 +276,14 @@ class Horde_SyncML_SyncMLHdr extends Horde_SyncML_ContentHandler {
|
||||
// </Cred></SyncHdr></SyncML>
|
||||
$this->_isCred = false;
|
||||
|
||||
//multisync does not specify the cred format
|
||||
// We only support b64 for now
|
||||
//if ($this->_credFormat == 'b64') {
|
||||
$this->_credData = base64_decode($this->_credData);
|
||||
//}
|
||||
|
||||
$tmp = explode(':', $this->_credData, 2);
|
||||
// set only if not set by LocName already
|
||||
if(!isset($this->_locName)) {
|
||||
if (!isset($this->_locName)) {
|
||||
$this->_locName = $tmp[0];
|
||||
}
|
||||
$this->_credData = $tmp[1];
|
||||
@ -355,7 +342,7 @@ class Horde_SyncML_SyncMLHdr extends Horde_SyncML_ContentHandler {
|
||||
{
|
||||
$attrs = array();
|
||||
|
||||
$state = &$_SESSION['SyncML.state'];
|
||||
$state =& $_SESSION['SyncML.state'];
|
||||
|
||||
$uri = $state->getURI();
|
||||
$uriMeta = $state->getURIMeta();
|
||||
@ -495,7 +482,7 @@ class Horde_SyncML_SyncMLBody extends Horde_SyncML_ContentHandler {
|
||||
function startElement($uri, $element, $attrs)
|
||||
{
|
||||
parent::startElement($uri, $element, $attrs);
|
||||
$state = &$_SESSION['SyncML.state'];
|
||||
$state =& $_SESSION['SyncML.state'];
|
||||
|
||||
switch ($this->_xmlStack) {
|
||||
case 2:
|
||||
@ -505,8 +492,8 @@ class Horde_SyncML_SyncMLBody extends Horde_SyncML_ContentHandler {
|
||||
// <SyncML><SyncBody>
|
||||
$this->_output->startElement($uri, $element, $attrs);
|
||||
|
||||
if($state->getLocName()) {
|
||||
if($state->isAuthConfirmed()) {
|
||||
if ($state->getLocName()) {
|
||||
if ($state->isAuthConfirmed()) {
|
||||
// Right our status about the header
|
||||
$status = new Horde_SyncML_Command_Status(($state->isAuthorized()) ?
|
||||
RESPONSE_OK : RESPONSE_INVALID_CREDENTIALS, 'SyncHdr');
|
||||
@ -550,7 +537,7 @@ class Horde_SyncML_SyncMLBody extends Horde_SyncML_ContentHandler {
|
||||
Horde::logMessage('SyncML['. session_id() ."]: found action commands <$element> ", __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
}
|
||||
|
||||
switch($element)
|
||||
switch ($element)
|
||||
{
|
||||
case 'Sync':
|
||||
$state->setSyncStatus(CLIENT_SYNC_STARTED);
|
||||
@ -568,7 +555,7 @@ class Horde_SyncML_SyncMLBody extends Horde_SyncML_ContentHandler {
|
||||
|
||||
function endElement($uri, $element)
|
||||
{
|
||||
$state = &$_SESSION['SyncML.state'];
|
||||
$state =& $_SESSION['SyncML.state'];
|
||||
|
||||
switch ($this->_xmlStack) {
|
||||
case 2:
|
||||
@ -588,14 +575,14 @@ class Horde_SyncML_SyncMLBody extends Horde_SyncML_ContentHandler {
|
||||
// send the sync reply
|
||||
// we do still have some data to send OR
|
||||
// we should reply to the Sync command
|
||||
if($state->getSyncStatus() > CLIENT_SYNC_FINNISHED && $state->getSyncStatus() < SERVER_SYNC_FINNISHED) {
|
||||
if ($state->getSyncStatus() > CLIENT_SYNC_FINNISHED && $state->getSyncStatus() < SERVER_SYNC_FINNISHED) {
|
||||
$sync = new Horde_SyncML_Command_Sync();
|
||||
$this->_currentCmdID = $sync->syncToClient($this->_currentCmdID, $this->_output);
|
||||
}
|
||||
|
||||
// send the Final tag if possible
|
||||
#if($state->getSyncStatus() != SERVER_SYNC_DATA_PENDING && $state->getSyncStatus() != CLIENT_SYNC_STARTED) {
|
||||
if($state->getSyncStatus() >= SERVER_SYNC_FINNISHED || $state->_sendFinal) {
|
||||
#if ($state->getSyncStatus() != SERVER_SYNC_DATA_PENDING && $state->getSyncStatus() != CLIENT_SYNC_STARTED) {
|
||||
if ($state->getSyncStatus() >= SERVER_SYNC_FINNISHED || $state->_sendFinal) {
|
||||
$final = new Horde_SyncML_Command_Final();
|
||||
$this->_currentCmdID = $final->output($this->_currentCmdID, $this->_output);
|
||||
}
|
||||
@ -609,11 +596,12 @@ class Horde_SyncML_SyncMLBody extends Horde_SyncML_ContentHandler {
|
||||
// this packet did not contain any real actions, just status and map.
|
||||
// This means, we're through! The session can be closed and
|
||||
// the Anchors saved for the next Sync
|
||||
Horde::logMessage('SyncML['. session_id() .']: sync' . session_id() . ' completed successfully!', __FILE__, __LINE__, PEAR_LOG_INFO);
|
||||
Horde::logMessage('SyncML['. session_id() .']: sync' . session_id() . ' completed successfully!',
|
||||
__FILE__, __LINE__, PEAR_LOG_INFO);
|
||||
$state->writeSyncSummary();
|
||||
$log = $state->getLog();
|
||||
$s="";
|
||||
foreach($log as $k => $v) {
|
||||
foreach ($log as $k => $v) {
|
||||
$s .= " $k=$v";
|
||||
}
|
||||
if (strlen(trim($s)) == 0) {
|
||||
@ -630,11 +618,12 @@ class Horde_SyncML_SyncMLBody extends Horde_SyncML_ContentHandler {
|
||||
// this packet did not contain any real actions, just status and map.
|
||||
// This means, we're through! The session can be closed and
|
||||
// the Anchors saved for the next Sync
|
||||
Horde::logMessage('SyncML['. session_id() .']: sync' . session_id() . ' completed successfully!', __FILE__, __LINE__, PEAR_LOG_INFO);
|
||||
Horde::logMessage('SyncML['. session_id() .']: sync' . session_id() . ' completed successfully!',
|
||||
__FILE__, __LINE__, PEAR_LOG_INFO);
|
||||
$state->writeSyncSummary();
|
||||
$log = $state->getLog();
|
||||
$s="";
|
||||
foreach($log as $k => $v) {
|
||||
foreach ($log as $k => $v) {
|
||||
$s .= " $k=$v";
|
||||
}
|
||||
if (strlen(trim($s)) == 0) {
|
||||
@ -654,14 +643,15 @@ class Horde_SyncML_SyncMLBody extends Horde_SyncML_ContentHandler {
|
||||
|
||||
$this->_currentCommand->endElement($uri, $element);
|
||||
|
||||
switch($element) {
|
||||
switch ($element) {
|
||||
case 'Final':
|
||||
$this->_actionCommands = false;
|
||||
$deviceInfo = $state->getClientDeviceInfo();
|
||||
|
||||
if ($state->getSyncStatus() == CLIENT_SYNC_STARTED) {
|
||||
if (strtolower($deviceInfo['manufacturer']) == 'funambol'
|
||||
&& isset($deviceInfo['softwareVersion'])) {
|
||||
if ($state->isAuthorized() &&
|
||||
($deviceInfo = $state->getClientDeviceInfo()) &&
|
||||
strtolower($deviceInfo['manufacturer']) == 'funambol'
|
||||
&& isset($deviceInfo['softwareVersion'])) {
|
||||
$swversion = $deviceInfo['softwareVersion'];
|
||||
if ($swversion < 1.0) {
|
||||
// e.g. Mozilla plugin uses this range
|
||||
@ -679,9 +669,8 @@ class Horde_SyncML_SyncMLBody extends Horde_SyncML_ContentHandler {
|
||||
} else {
|
||||
$state->setSyncStatus(CLIENT_SYNC_ACKNOWLEDGED);
|
||||
}
|
||||
}
|
||||
|
||||
if ($state->getSyncStatus() == SERVER_SYNC_FINNISHED) {
|
||||
} elseif ($state->getSyncStatus() == SERVER_SYNC_FINNISHED) {
|
||||
$state->setSyncStatus(SERVER_SYNC_ACKNOWLEDGED);
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ class Horde_SyncML_Command_Sync_ContentSyncElement extends Horde_SyncML_Command_
|
||||
}
|
||||
*/
|
||||
if (isset($this->_content) && !$this->_moreData) {
|
||||
$this->_content = trim($this->_content);
|
||||
//$this->_content = trim($this->_content);
|
||||
$this->_contentSize = strlen($this->_content);
|
||||
if (strtolower($this->_contentFormat) == 'b64') {
|
||||
$this->_content = base64_encode($this->_content);
|
||||
|
@ -203,6 +203,11 @@ class Horde_SyncML_State {
|
||||
|
||||
var $_password;
|
||||
|
||||
/*
|
||||
* integer 0 authorization pending
|
||||
* -1 authorization failed
|
||||
* 1 session is authorized
|
||||
*/
|
||||
var $_isAuthorized;
|
||||
|
||||
var $_AuthConfirmed;
|
||||
@ -277,7 +282,7 @@ class Horde_SyncML_State {
|
||||
$this->setPassword($password);
|
||||
}
|
||||
|
||||
$this->_isAuthorized = false;
|
||||
$this->_isAuthorized = 0;
|
||||
$this->_isAuthConfirmed = false;
|
||||
}
|
||||
|
||||
@ -560,12 +565,12 @@ class Horde_SyncML_State {
|
||||
|
||||
if($GLOBALS['sessionid'] = $GLOBALS['egw']->session->create($this->_locName,$this->_password,'text','u'))
|
||||
{
|
||||
$this->_isAuthorized = true;
|
||||
$this->_isAuthorized = 1;
|
||||
#Horde::logMessage('SyncML_EGW: Authentication of ' . $this->_locName . '/' . $GLOBALS['sessionid'] . ' succeded' , __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->_isAuthorized = false;
|
||||
$this->_isAuthorized = -1;
|
||||
Horde::logMessage('SyncML: Authentication of ' . $this->_locName . ' failed' , __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
}
|
||||
}
|
||||
@ -577,7 +582,7 @@ class Horde_SyncML_State {
|
||||
Horde::logMessage('SyncML_EGW: egw session('.$sessionID. ') not verified ' , __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
}
|
||||
|
||||
return $this->_isAuthorized;
|
||||
return ($this->_isAuthorized > 0);
|
||||
}
|
||||
|
||||
function isAuthConfirmed()
|
||||
|
@ -13,6 +13,7 @@
|
||||
* @author Joerg Lehrke <jlehrke@noc.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
include_once dirname(__FILE__).'/State.php';
|
||||
|
||||
/**
|
||||
@ -59,6 +60,12 @@ class EGW_SyncML_State extends Horde_SyncML_State
|
||||
|
||||
$ts = $GLOBALS['egw']->contenthistory->getTSforAction($_appName, $_id, $_action);
|
||||
|
||||
if (strstr($_id, ':')) {
|
||||
// pseudo entries are related to parent entry
|
||||
$parentId = array_shift(explode(':', $_id));
|
||||
$pts = $GLOBALS['egw']->contenthistory->getTSforAction($_appName, $parentId, $_action);
|
||||
if ($pts > $ts) $ts = $pts; // We have changed the parent
|
||||
}
|
||||
return $ts;
|
||||
}
|
||||
|
||||
@ -294,65 +301,99 @@ class EGW_SyncML_State extends Horde_SyncML_State
|
||||
}
|
||||
|
||||
function isAuthorized() {
|
||||
if (!$this->_isAuthorized) {
|
||||
if(!isset($this->_locName) && !isset($this->_password)) {
|
||||
Horde::logMessage('SyncML: Authentication not yet possible currently. Username and password not available' , __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!isset($this->_password)) {
|
||||
Horde::logMessage('SyncML: Authentication not yet possible currently. Password not available' , __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
return FALSE;
|
||||
}
|
||||
if(!isset($this->_locName))
|
||||
{
|
||||
Horde::logMessage('SyncML: Authentication not yet possible. Username not available',
|
||||
__FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strpos($this->_locName,'@') === False) {
|
||||
$this->_account_domain = $GLOBALS['egw_info']['server']['default_domain'];
|
||||
$this->_locName .= '@'. $this->_account_domain;
|
||||
} else {
|
||||
$parts = explode('@',$this->_locName);
|
||||
$this->_account_domain = array_pop($parts);
|
||||
}
|
||||
// store sessionID in a variable, because create() and verify() reset this value
|
||||
$sessionID = session_id();
|
||||
|
||||
if (strpos($this->_locName,'@') === False)
|
||||
{
|
||||
$this->_account_domain = $GLOBALS['egw_info']['server']['default_domain'];
|
||||
$this->_locName .= '@'. $this->_account_domain;
|
||||
}
|
||||
else
|
||||
{
|
||||
$parts = explode('@',$this->_locName);
|
||||
$this->_account_domain = array_pop($parts);
|
||||
}
|
||||
|
||||
if (!is_object($GLOBALS['egw']))
|
||||
{
|
||||
// Let the EGw core create the infrastructure classes
|
||||
$_POST['login'] = $this->_locName;
|
||||
$_REQUEST['domain'] = $this->_account_domain;
|
||||
$GLOBALS['egw_info']['server']['default_domain'] = $this->_account_domain;
|
||||
$GLOBALS['egw_info']['user']['domain'] = $this->_account_domain;
|
||||
if (is_array($GLOBALS['egw_domain'][$this->_account_domain]))
|
||||
$GLOBALS['egw_info']['flags']['currentapp'] = 'login';
|
||||
$GLOBALS['egw_info']['flags']['noapi'] = false;
|
||||
require_once(EGW_API_INC . '/functions.inc.php');
|
||||
}
|
||||
|
||||
$GLOBALS['egw_info']['flags']['currentapp'] = 'syncml';
|
||||
|
||||
if (!$this->_isAuthorized)
|
||||
{
|
||||
|
||||
if (!isset($this->_password))
|
||||
{
|
||||
Horde::logMessage('SyncML: Authentication not yet possible. Credetials missing',
|
||||
__FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
return false;
|
||||
}
|
||||
|
||||
$GLOBALS['egw_info']['server']['db_host'] = $GLOBALS['egw_domain'][$this->_account_domain]['db_host'];
|
||||
$GLOBALS['egw_info']['server']['db_port'] = $GLOBALS['egw_domain'][$this->_account_domain]['db_port'];
|
||||
$GLOBALS['egw_info']['server']['db_name'] = $GLOBALS['egw_domain'][$this->_account_domain]['db_name'];
|
||||
$GLOBALS['egw_info']['server']['db_user'] = $GLOBALS['egw_domain'][$this->_account_domain]['db_user'];
|
||||
$GLOBALS['egw_info']['server']['db_pass'] = $GLOBALS['egw_domain'][$this->_account_domain]['db_pass'];
|
||||
$GLOBALS['egw_info']['server']['db_type'] = $GLOBALS['egw_domain'][$this->_account_domain]['db_type'];
|
||||
// It works -- don't ask me why.
|
||||
$this->db = new egw_db($GLOBALS['egw_info']['server']);
|
||||
$this->db->connect();
|
||||
|
||||
#Horde::logMessage('SyncML: authenticate with username: ' . $this->_locName . ' and password: ' . $this->_password, __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
|
||||
if (($GLOBALS['sessionid'] = $GLOBALS['egw']->session->create($this->_locName,$this->_password,'text')))
|
||||
if ($GLOBALS['egw']->session->create($this->_locName,$this->_password,'text'))
|
||||
{
|
||||
if ($GLOBALS['egw_info']['user']['apps']['syncml'])
|
||||
{
|
||||
if ($GLOBALS['egw_info']['user']['apps']['syncml']) {
|
||||
$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 is not enabled for user ' . $this->_locName , __FILE__, __LINE__, PEAR_LOG_ERROR);
|
||||
}
|
||||
return $this->_isAuthorized;
|
||||
$this->_isAuthorized = 1;
|
||||
// restore the original sessionID
|
||||
session_regenerate_id();
|
||||
session_id($sessionID);
|
||||
$GLOBALS['sessionid'] = $sessionID;
|
||||
@session_start();
|
||||
|
||||
Horde::logMessage('SyncML_EGW[' . $GLOBALS['sessionid']
|
||||
.']: Authentication of ' . $this->_locName . ' succeded',
|
||||
__FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
|
||||
$config =& CreateObject('phpgwapi.config','syncml');
|
||||
$config->read_repository();
|
||||
$GLOBALS['config_syncml'] =& $config->config_data;
|
||||
unset($config);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->_isAuthorized = -1; // Authorization failed!
|
||||
Horde::logMessage('SyncML is not enabled for user '
|
||||
. $this->_locName, __FILE__, __LINE__, PEAR_LOG_ERROR);
|
||||
}
|
||||
}
|
||||
$this->_isAuthorized = false;
|
||||
Horde::logMessage('SyncML: Authentication of ' . $this->_locName . ' failed' , __FILE__, __LINE__, PEAR_LOG_INFO);
|
||||
} else {
|
||||
if ($this->log) error_log(__FILE__.'['.__LINE__.'] '.__METHOD__."()\n".var_export($GLOBALS['egw_info'], true)."\n",3,$this->logfile);
|
||||
// store sessionID in a variable, because ->verify maybe resets that value
|
||||
$sessionID = session_id();
|
||||
$GLOBALS['egw_info']['user']['domain'] = $this->_account_domain;
|
||||
if (!$GLOBALS['egw']->session->verify($sessionID, 'staticsyncmlkp3')) {
|
||||
Horde::logMessage('SyncML_EGW: egw session(' .$sessionID. ') not verified ' , __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
else
|
||||
{
|
||||
$this->_isAuthorized = -1;
|
||||
Horde::logMessage('SyncML: Authentication of ' . $this->_locName
|
||||
. ' failed', __FILE__, __LINE__, PEAR_LOG_INFO);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
elseif ($this->_isAuthorized > 0)
|
||||
{
|
||||
if (!$GLOBALS['egw']->session->verify($sessionID, 'staticsyncmlkp3'))
|
||||
{
|
||||
Horde::logMessage('SyncML_EGW: egw session(' . $sessionID
|
||||
. ') could not be not verified' ,
|
||||
__FILE__, __LINE__, PEAR_LOG_ERROR);
|
||||
}
|
||||
}
|
||||
return $this->_isAuthorized;
|
||||
return ($this->_isAuthorized > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -89,6 +89,9 @@ class Horde_SyncML_Sync_RefreshFromServerSync extends Horde_SyncML_Sync_TwoWaySy
|
||||
|
||||
$contentType = $state->getPreferedContentTypeClient($this->_sourceLocURI, $this->_targetLocURI);
|
||||
$c = $registry->call($hordeType . '/export', array('guid' => $guid, 'contentType' => $contentType));
|
||||
|
||||
if ($c === false) continue; // no content to export
|
||||
|
||||
if (is_a($c, 'PEAR_Error')) {
|
||||
Horde::logMessage("SyncML: refresh failed to export guid $guid:\n" . print_r($c, true),
|
||||
__FILE__, __LINE__, PEAR_LOG_WARNING);
|
||||
|
@ -96,6 +96,9 @@ class Horde_SyncML_Sync_SlowSync extends Horde_SyncML_Sync_TwoWaySync {
|
||||
|
||||
$contentType = $state->getPreferedContentTypeClient($this->_sourceLocURI, $this->_targetLocURI);
|
||||
$c = $registry->call($hordeType . '/export', array('guid' => $guid, 'contentType' => $contentType));
|
||||
|
||||
if ($c === false) continue; // no content to export
|
||||
|
||||
if (is_a($c, 'PEAR_Error')) {
|
||||
Horde::logMessage("SyncML: slowsync failed to export guid $guid:\n" . print_r($c, true),
|
||||
__FILE__, __LINE__, PEAR_LOG_WARNING);
|
||||
@ -235,7 +238,7 @@ class Horde_SyncML_Sync_SlowSync extends Horde_SyncML_Sync_TwoWaySync {
|
||||
$guid = false;
|
||||
|
||||
$guid = $registry->call($hordeType . '/search',
|
||||
array($state->convertClient2Server($syncItem->getContent(), $contentType), $contentType, $state->getGlobalUID($type, $syncItem->getLocURI()) ));
|
||||
array($state->convertClient2Server($syncItem->getContent(), $contentType), $contentType, $state->getGlobalUID($type, $syncItem->getLocURI()), $type));
|
||||
|
||||
if ($guid) {
|
||||
// Check if the found entry came from the client
|
||||
|
@ -135,6 +135,9 @@ class Horde_SyncML_Sync_TwoWaySync extends Horde_SyncML_Sync {
|
||||
'guid' => $guid,
|
||||
'contentType' => $contentType
|
||||
));
|
||||
|
||||
if ($c === false) continue; // no content to export
|
||||
|
||||
if (is_a($c, 'PEAR_Error')) {
|
||||
// Item in history but not in database. Strange, but can happen.
|
||||
Horde :: logMessage("SyncML: change: export of guid $guid failed:\n" . print_r($c, true),
|
||||
@ -343,13 +346,14 @@ class Horde_SyncML_Sync_TwoWaySync extends Horde_SyncML_Sync {
|
||||
|
||||
// Create an Add request for client.
|
||||
$contentType = $state->getPreferedContentTypeClient($this->_sourceLocURI, $this->_targetLocURI);
|
||||
|
||||
$c = $registry->call($hordeType . '/export', array (
|
||||
'guid' => $guid,
|
||||
'contentType' => $contentType,
|
||||
|
||||
));
|
||||
|
||||
if ($c === false) continue; // no content to export
|
||||
|
||||
if (is_a($c, 'PEAR_Error')) {
|
||||
// Item in history but not in database. Strange, but can happen.
|
||||
Horde :: logMessage("SyncML: add: export of guid $guid failed:\n" . print_r($c, true),
|
||||
@ -406,7 +410,7 @@ class Horde_SyncML_Sync_TwoWaySync extends Horde_SyncML_Sync {
|
||||
function loadData() {
|
||||
global $registry;
|
||||
|
||||
$state = & $_SESSION['SyncML.state'];
|
||||
$state =& $_SESSION['SyncML.state'];
|
||||
$syncType = $this->_targetLocURI;
|
||||
$hordeType = $state->getHordeType($syncType);
|
||||
$refts = $state->getServerAnchorLast($syncType);
|
||||
@ -421,15 +425,29 @@ class Horde_SyncML_Sync_TwoWaySync extends Horde_SyncML_Sync {
|
||||
|
||||
$state->setAddedItems($syncType, $addedItems);
|
||||
|
||||
$state->setDeletedItems($syncType, $registry->call($hordeType . '/listBy', array (
|
||||
$changedItems =& $state->getChangedItems($syncType);
|
||||
|
||||
$deletedItems =& $registry->call($hordeType . '/listBy', array (
|
||||
'action' => 'delete',
|
||||
'timestamp' => $refts,
|
||||
'type' => $syncType,
|
||||
'filter' => $this->_filterExpression
|
||||
)));
|
||||
));
|
||||
foreach ($deletedItems as $guid)
|
||||
{
|
||||
if (strstr($guid, ':'))
|
||||
{
|
||||
$parentGUID = array_shift(explode(':', $guid));
|
||||
if (!in_array($parentGUID, $changedItems))
|
||||
{
|
||||
$changedItems[] = $parentGUID;
|
||||
}
|
||||
}
|
||||
}
|
||||
$state->setDeletedItems($syncType, $deletedItems);
|
||||
|
||||
$this->_syncDataLoaded = TRUE;
|
||||
$this->_syncDataLoaded = true;
|
||||
|
||||
return count($state->getChangedItems($syncType)) + count($state->getDeletedItems($syncType)) + count($state->getAddedItems($syncType)) + count($state->getConflictItems($syncType));
|
||||
return count($changedItems) + count($deletedItems) + count($addedItems) + count($state->getConflictItems($syncType));
|
||||
}
|
||||
}
|
@ -520,14 +520,20 @@ class Horde_iCalendar {
|
||||
*
|
||||
* @return boolean True on successful import, false otherwise.
|
||||
*/
|
||||
function parsevCalendar($text, $base = 'VCALENDAR', $charset = null,
|
||||
$clear = true)
|
||||
function parsevCalendar($text, $base = 'VCALENDAR', $charset = null, $clear = true)
|
||||
{
|
||||
if ($clear) {
|
||||
$this->clear();
|
||||
}
|
||||
|
||||
if (preg_match('/^BEGIN:' . $base . '(.*)^END:' . $base . '/ism', $text, $matches)) {
|
||||
if ($base == 'VTODO' &&
|
||||
preg_match('/^BEGIN:VTODO(.*)^END:VEVENT/ism', $text, $matches)) {
|
||||
// Workaround for Funambol VTODO bug in Mozilla Sync Plugins
|
||||
Horde::logMessage('iCalendar: Funambol VTODO-bug detected, workaround activated...',
|
||||
__FILE__, __LINE__, PEAR_LOG_WARNING);
|
||||
$container = true;
|
||||
$vCal = $matches[1];
|
||||
} elseif (preg_match('/^BEGIN:' . $base . '(.*)^END:' . $base . '/ism', $text, $matches)) {
|
||||
$container = true;
|
||||
$vCal = $matches[1];
|
||||
} else {
|
||||
@ -543,12 +549,14 @@ class Horde_iCalendar {
|
||||
$this->setAttribute('VERSION', $matches[1]);
|
||||
}
|
||||
|
||||
// Preserve a trailing CR
|
||||
// Preserve a trailing CR
|
||||
$vCal = trim($vCal) . "\n";
|
||||
|
||||
// All subcomponents.
|
||||
$matches = null;
|
||||
if (preg_match_all('/^BEGIN:(.*)(\r\n|\r|\n)(.*)^END:\1/Uims', $vCal, $matches)) {
|
||||
// Workaround for Funambol VTODO bug in Mozilla Sync Plugins
|
||||
if (preg_match_all('/^BEGIN:(VTODO)(\r\n|\r|\n)(.*)^END:VEVENT/Uims', $vCal, $matches) ||
|
||||
preg_match_all('/^BEGIN:(.*)(\r\n|\r|\n)(.*)^END:\1/Uims', $vCal, $matches)) {
|
||||
// vTimezone components are processed first. They are
|
||||
// needed to process vEvents that may use a TZID.
|
||||
foreach ($matches[0] as $key => $data) {
|
||||
@ -602,6 +610,7 @@ class Horde_iCalendar {
|
||||
|
||||
// Unfold any folded lines.
|
||||
if ($this->isOldFormat()) {
|
||||
// old formats force folding at whitespace which must therefore be preserved
|
||||
$vCal = preg_replace('/[\r\n]+([ \t])/', '\1', $vCal);
|
||||
} else {
|
||||
$vCal = preg_replace('/[\r\n]+[ \t]/', '', $vCal);
|
||||
@ -640,222 +649,224 @@ class Horde_iCalendar {
|
||||
if (isset($params['BASE64'])) {
|
||||
$params['ENCODING'] = 'BASE64';
|
||||
}
|
||||
if (isset($params['ENCODING'])) {
|
||||
switch (String::upper($params['ENCODING'])) {
|
||||
case 'Q':
|
||||
case 'QUOTED-PRINTABLE':
|
||||
$value = quoted_printable_decode($value);
|
||||
if (isset($params['CHARSET'])) {
|
||||
$value = $GLOBALS['egw']->translation->convert($value, $params['CHARSET']);
|
||||
} else {
|
||||
$value = $GLOBALS['egw']->translation->convert($value,
|
||||
empty($charset) ? ($this->isOldFormat() ? 'iso-8859-1' : 'utf-8') : $charset);
|
||||
}
|
||||
break;
|
||||
case 'B':
|
||||
case 'BASE64':
|
||||
$value = base64_decode($value);
|
||||
break;
|
||||
}
|
||||
} elseif (isset($params['CHARSET'])) {
|
||||
$value = $GLOBALS['egw']->translation->convert($value, $params['CHARSET']);
|
||||
} else {
|
||||
// As per RFC 2279, assume UTF8 if we don't have an
|
||||
// explicit charset parameter.
|
||||
$value = $GLOBALS['egw']->translation->convert($value,
|
||||
empty($charset) ? ($this->isOldFormat() ? 'iso-8859-1' : 'utf-8') : $charset);
|
||||
}
|
||||
if (isset($params['ENCODING'])) {
|
||||
switch (String::upper($params['ENCODING'])) {
|
||||
case 'Q':
|
||||
case 'QUOTED-PRINTABLE':
|
||||
$value = quoted_printable_decode($value);
|
||||
if (isset($params['CHARSET'])) {
|
||||
$value = $GLOBALS['egw']->translation->convert($value, $params['CHARSET']);
|
||||
} else {
|
||||
$value = $GLOBALS['egw']->translation->convert($value,
|
||||
empty($charset) ? ($this->isOldFormat() ? 'iso-8859-1' : 'utf-8') : $charset);
|
||||
}
|
||||
// Funambol hack :-(
|
||||
$value = str_replace('\\\\n', "\n", $value);
|
||||
break;
|
||||
case 'B':
|
||||
case 'BASE64':
|
||||
$value = base64_decode($value);
|
||||
break;
|
||||
}
|
||||
} elseif (isset($params['CHARSET'])) {
|
||||
$value = $GLOBALS['egw']->translation->convert($value, $params['CHARSET']);
|
||||
} else {
|
||||
// As per RFC 2279, assume UTF8 if we don't have an
|
||||
// explicit charset parameter.
|
||||
$value = $GLOBALS['egw']->translation->convert($value,
|
||||
empty($charset) ? ($this->isOldFormat() ? 'iso-8859-1' : 'utf-8') : $charset);
|
||||
}
|
||||
|
||||
// Get timezone info for date fields from $params.
|
||||
$tzid = isset($params['TZID']) ? trim($params['TZID'], '\"') : false;
|
||||
// Get timezone info for date fields from $params.
|
||||
$tzid = isset($params['TZID']) ? trim($params['TZID'], '\"') : false;
|
||||
|
||||
switch ($tag) {
|
||||
case 'VERSION': // already processed
|
||||
switch ($tag) {
|
||||
case 'VERSION': // already processed
|
||||
break;
|
||||
// Date fields.
|
||||
case 'COMPLETED':
|
||||
case 'CREATED':
|
||||
case 'LAST-MODIFIED':
|
||||
$this->setAttribute($tag, $this->_parseDateTime($value, $tzid), $params);
|
||||
break;
|
||||
|
||||
case 'BDAY':
|
||||
case 'X-SYNCJE-ANNIVERSARY':
|
||||
$this->setAttribute($tag, $value, $params, true, $this->_parseDate($value));
|
||||
break;
|
||||
|
||||
case 'DTEND':
|
||||
case 'DTSTART':
|
||||
case 'DTSTAMP':
|
||||
case 'DUE':
|
||||
case 'AALARM':
|
||||
case 'DALARM':
|
||||
case 'RECURRENCE-ID':
|
||||
case 'X-RECURRENCE-ID':
|
||||
// types like AALARM may contain additional data after a ;
|
||||
// ignore these.
|
||||
$ts = explode(';', $value);
|
||||
if (isset($params['VALUE']) && $params['VALUE'] == 'DATE') {
|
||||
$isDate = true;
|
||||
$this->setAttribute($tag, $this->_parseDateTime($ts[0], $tzid), $params, true, $this->_parseDate($ts[0]));
|
||||
} else {
|
||||
$this->setAttribute($tag, $this->_parseDateTime($ts[0], $tzid), $params);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'TRIGGER':
|
||||
if (isset($params['VALUE'])) {
|
||||
if ($params['VALUE'] == 'DATE-TIME') {
|
||||
$this->setAttribute($tag, $this->_parseDateTime($value, $tzid), $params);
|
||||
} else {
|
||||
$this->setAttribute($tag, $this->_parseDuration($value), $params);
|
||||
}
|
||||
} else {
|
||||
$this->setAttribute($tag, $this->_parseDuration($value), $params);
|
||||
}
|
||||
break;
|
||||
|
||||
// Comma or semicolon seperated dates.
|
||||
case 'EXDATE':
|
||||
case 'RDATE':
|
||||
$dates = array();
|
||||
preg_match_all('/[;,]([^;,]*)/', ';' . $value, $values);
|
||||
|
||||
foreach ($values[1] as $value) {
|
||||
if ((isset($params['VALUE'])
|
||||
&& $params['VALUE'] == 'DATE') || (!isset($params['VALUE']) && $isDate)) {
|
||||
$dates[] = $this->_parseDate(trim($value));
|
||||
} else {
|
||||
$dates[] = $this->_parseDateTime(trim($value), $tzid);
|
||||
}
|
||||
}
|
||||
$this->setAttribute($tag, isset($dates[0]) ? $dates[0] : null, $params, true, $dates);
|
||||
break;
|
||||
|
||||
// Duration fields.
|
||||
case 'DURATION':
|
||||
$this->setAttribute($tag, $this->_parseDuration($value), $params);
|
||||
break;
|
||||
|
||||
// Period of time fields.
|
||||
case 'FREEBUSY':
|
||||
$periods = array();
|
||||
preg_match_all('/,([^,]*)/', ',' . $value, $values);
|
||||
foreach ($values[1] as $value) {
|
||||
$periods[] = $this->_parsePeriod($value);
|
||||
}
|
||||
|
||||
$this->setAttribute($tag, isset($periods[0]) ? $periods[0] : null, $params, true, $periods);
|
||||
break;
|
||||
|
||||
// UTC offset fields.
|
||||
case 'TZOFFSETFROM':
|
||||
case 'TZOFFSETTO':
|
||||
$this->setAttribute($tag, $this->_parseUtcOffset($value), $params);
|
||||
break;
|
||||
|
||||
// Integer fields.
|
||||
case 'PERCENT-COMPLETE':
|
||||
case 'PRIORITY':
|
||||
case 'REPEAT':
|
||||
case 'SEQUENCE':
|
||||
$this->setAttribute($tag, intval($value), $params);
|
||||
break;
|
||||
|
||||
// Geo fields.
|
||||
case 'GEO':
|
||||
if ($this->isOldFormat()) {
|
||||
$floats = explode(',', $value);
|
||||
$value = array('latitude' => floatval($floats[1]),
|
||||
'longitude' => floatval($floats[0]));
|
||||
} else {
|
||||
$floats = explode(';', $value);
|
||||
$value = array('latitude' => floatval($floats[0]),
|
||||
'longitude' => floatval($floats[1]));
|
||||
}
|
||||
$this->setAttribute($tag, $value, $params);
|
||||
break;
|
||||
|
||||
// Recursion fields. # add more flexibility
|
||||
#case 'EXRULE':
|
||||
#case 'RRULE':
|
||||
# $this->setAttribute($tag, trim($value), $params);
|
||||
# break;
|
||||
|
||||
// Binary fields.
|
||||
case 'PHOTO':
|
||||
$this->setAttribute($tag, $value, $params);
|
||||
break;
|
||||
|
||||
// ADR, ORG and N are lists seperated by unescaped semicolons
|
||||
// with a specific number of slots.
|
||||
case 'ADR':
|
||||
case 'N':
|
||||
case 'ORG':
|
||||
$value = trim($value);
|
||||
// As of rfc 2426 2.4.2 semicolon, comma, and colon must
|
||||
// be escaped (comma is unescaped after splitting below).
|
||||
$value = str_replace(array('\\n', '\\N', '\\;', '\\:'),
|
||||
array("\n", "\n", ';', ':'),
|
||||
$value);
|
||||
|
||||
// Split by unescaped semicolons:
|
||||
$values = preg_split('/(?<!\\\\);/', $value);
|
||||
$value = str_replace('\\;', ';', $value);
|
||||
$values = str_replace('\\;', ';', $values);
|
||||
$value = str_replace('\\,', ',', $value);
|
||||
$values = str_replace('\\,', ',', $values);
|
||||
$this->setAttribute($tag, trim($value), $params, true, $values);
|
||||
break;
|
||||
|
||||
// CATEGORIES is a lists seperated by unescaped commas
|
||||
// with a unspecific number of slots.
|
||||
case 'CATEGORIES':
|
||||
$value = trim($value);
|
||||
// As of rfc 2426 2.4.2 semicolon, comma, and colon must
|
||||
// be escaped (semicolon is unescaped after splitting below).
|
||||
$value = str_replace(array('\\n', '\\N', '\\,', '\\:'),
|
||||
array("\n", "\n", ',', ':'),
|
||||
$value);
|
||||
|
||||
// Split by unescaped commas:
|
||||
$values = preg_split('/(?<!\\\\),/', $value);
|
||||
$value = str_replace('\\;', ';', $value);
|
||||
$values = str_replace('\\;', ';', $values);
|
||||
$value = str_replace('\\,', ',', $value);
|
||||
$values = str_replace('\\,', ',', $values);
|
||||
$this->setAttribute($tag, trim($value), $params, true, $values);
|
||||
break;
|
||||
|
||||
// String fields.
|
||||
default:
|
||||
if ($this->isOldFormat()) {
|
||||
// vCalendar 1.0 and vCard 2.1 only escape semicolons
|
||||
// and use unescaped semicolons to create lists.
|
||||
$value = trim($value);
|
||||
// Split by unescaped semicolons:
|
||||
$values = preg_split('/(?<!\\\\);/', $value);
|
||||
$value = str_replace('\\;', ';', $value);
|
||||
$values = str_replace('\\;', ';', $values);
|
||||
$this->setAttribute($tag, trim($value), $params, true, $values);
|
||||
} else {
|
||||
$value = trim($value);
|
||||
// As of rfc 2426 2.4.2 semicolon, comma, and colon
|
||||
// must be escaped (comma is unescaped after splitting
|
||||
// below).
|
||||
$value = str_replace(array('\\n', '\\N', '\\;', '\\:', '\\\\'),
|
||||
array("\n", "\n", ';', ':', '\\'),
|
||||
$value);
|
||||
|
||||
// Split by unescaped commas.
|
||||
$values = preg_split('/(?<!\\\\),/', $value);
|
||||
$value = str_replace('\\,', ',', $value);
|
||||
$values = str_replace('\\,', ',', $values);
|
||||
|
||||
$this->setAttribute($tag, trim($value), $params, true, $values);
|
||||
}
|
||||
break;
|
||||
// Date fields.
|
||||
case 'COMPLETED':
|
||||
case 'CREATED':
|
||||
case 'LAST-MODIFIED':
|
||||
$this->setAttribute($tag, $this->_parseDateTime($value, $tzid), $params);
|
||||
break;
|
||||
|
||||
case 'BDAY':
|
||||
case 'X-SYNCJE-ANNIVERSARY':
|
||||
$this->setAttribute($tag, $value, $params, true, $this->_parseDate($value));
|
||||
break;
|
||||
|
||||
case 'DTEND':
|
||||
case 'DTSTART':
|
||||
case 'DTSTAMP':
|
||||
case 'DUE':
|
||||
case 'AALARM':
|
||||
case 'DALARM':
|
||||
case 'RECURRENCE-ID':
|
||||
case 'X-RECURRENCE-ID':
|
||||
// types like AALARM may contain additional data after a ;
|
||||
// ignore these.
|
||||
$ts = explode(';', $value);
|
||||
if (isset($params['VALUE']) && $params['VALUE'] == 'DATE') {
|
||||
$isDate = true;
|
||||
$this->setAttribute($tag, $this->_parseDateTime($ts[0], $tzid), $params, true, $this->_parseDate($ts[0]));
|
||||
} else {
|
||||
$this->setAttribute($tag, $this->_parseDateTime($ts[0], $tzid), $params);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'TRIGGER':
|
||||
if (isset($params['VALUE'])) {
|
||||
if ($params['VALUE'] == 'DATE-TIME') {
|
||||
$this->setAttribute($tag, $this->_parseDateTime($value, $tzid), $params);
|
||||
} else {
|
||||
$this->setAttribute($tag, $this->_parseDuration($value), $params);
|
||||
}
|
||||
} else {
|
||||
$this->setAttribute($tag, $this->_parseDuration($value), $params);
|
||||
}
|
||||
break;
|
||||
|
||||
// Comma or semicolon seperated dates.
|
||||
case 'EXDATE':
|
||||
case 'RDATE':
|
||||
$dates = array();
|
||||
preg_match_all('/[;,]([^;,]*)/', ';' . $value, $values);
|
||||
|
||||
foreach ($values[1] as $value) {
|
||||
if ((isset($params['VALUE'])
|
||||
&& $params['VALUE'] == 'DATE') || (!isset($params['VALUE']) && $isDate)) {
|
||||
$dates[] = $this->_parseDate($value);
|
||||
} else {
|
||||
$dates[] = $this->_parseDateTime($value, $tzid);
|
||||
}
|
||||
}
|
||||
$this->setAttribute($tag, isset($dates[0]) ? $dates[0] : null, $params, true, $dates);
|
||||
break;
|
||||
|
||||
// Duration fields.
|
||||
case 'DURATION':
|
||||
$this->setAttribute($tag, $this->_parseDuration($value), $params);
|
||||
break;
|
||||
|
||||
// Period of time fields.
|
||||
case 'FREEBUSY':
|
||||
$periods = array();
|
||||
preg_match_all('/,([^,]*)/', ',' . $value, $values);
|
||||
foreach ($values[1] as $value) {
|
||||
$periods[] = $this->_parsePeriod($value);
|
||||
}
|
||||
|
||||
$this->setAttribute($tag, isset($periods[0]) ? $periods[0] : null, $params, true, $periods);
|
||||
break;
|
||||
|
||||
// UTC offset fields.
|
||||
case 'TZOFFSETFROM':
|
||||
case 'TZOFFSETTO':
|
||||
$this->setAttribute($tag, $this->_parseUtcOffset($value), $params);
|
||||
break;
|
||||
|
||||
// Integer fields.
|
||||
case 'PERCENT-COMPLETE':
|
||||
case 'PRIORITY':
|
||||
case 'REPEAT':
|
||||
case 'SEQUENCE':
|
||||
$this->setAttribute($tag, intval($value), $params);
|
||||
break;
|
||||
|
||||
// Geo fields.
|
||||
case 'GEO':
|
||||
if ($this->isOldFormat()) {
|
||||
$floats = explode(',', $value);
|
||||
$value = array('latitude' => floatval($floats[1]),
|
||||
'longitude' => floatval($floats[0]));
|
||||
} else {
|
||||
$floats = explode(';', $value);
|
||||
$value = array('latitude' => floatval($floats[0]),
|
||||
'longitude' => floatval($floats[1]));
|
||||
}
|
||||
$this->setAttribute($tag, $value, $params);
|
||||
break;
|
||||
|
||||
// Recursion fields. # add more flexibility
|
||||
#case 'EXRULE':
|
||||
#case 'RRULE':
|
||||
# $this->setAttribute($tag, trim($value), $params);
|
||||
# break;
|
||||
|
||||
// Binary fields.
|
||||
case 'PHOTO':
|
||||
$this->setAttribute($tag, $value, $params);
|
||||
break;
|
||||
|
||||
// ADR, ORG and N are lists seperated by unescaped semicolons
|
||||
// with a specific number of slots.
|
||||
case 'ADR':
|
||||
case 'N':
|
||||
case 'ORG':
|
||||
$value = trim($value);
|
||||
// As of rfc 2426 2.4.2 semicolon, comma, and colon must
|
||||
// be escaped (comma is unescaped after splitting below).
|
||||
$value = str_replace(array('\\n', '\\N', '\\;', '\\:'),
|
||||
array("\n", "\n", ';', ':'),
|
||||
$value);
|
||||
|
||||
// Split by unescaped semicolons:
|
||||
$values = preg_split('/(?<!\\\\);/', $value);
|
||||
$value = str_replace('\\;', ';', $value);
|
||||
$values = str_replace('\\;', ';', $values);
|
||||
$value = str_replace('\\,', ',', $value);
|
||||
$values = str_replace('\\,', ',', $values);
|
||||
$this->setAttribute($tag, trim($value), $params, true, $values);
|
||||
break;
|
||||
|
||||
// CATEGORIES is a lists seperated by unescaped commas
|
||||
// with a unspecific number of slots.
|
||||
case 'CATEGORIES':
|
||||
$value = trim($value);
|
||||
// As of rfc 2426 2.4.2 semicolon, comma, and colon must
|
||||
// be escaped (semicolon is unescaped after splitting below).
|
||||
$value = str_replace(array('\\n', '\\N', '\\,', '\\:'),
|
||||
array("\n", "\n", ',', ':'),
|
||||
$value);
|
||||
|
||||
// Split by unescaped commas:
|
||||
$values = preg_split('/(?<!\\\\),/', $value);
|
||||
$value = str_replace('\\;', ';', $value);
|
||||
$values = str_replace('\\;', ';', $values);
|
||||
$value = str_replace('\\,', ',', $value);
|
||||
$values = str_replace('\\,', ',', $values);
|
||||
$this->setAttribute($tag, trim($value), $params, true, $values);
|
||||
break;
|
||||
|
||||
// String fields.
|
||||
default:
|
||||
if ($this->isOldFormat()) {
|
||||
// vCalendar 1.0 and vCard 2.1 only escape semicolons
|
||||
// and use unescaped semicolons to create lists.
|
||||
$value = trim($value);
|
||||
// Split by unescaped semicolons:
|
||||
$values = preg_split('/(?<!\\\\);/', $value);
|
||||
$value = str_replace('\\;', ';', $value);
|
||||
$values = str_replace('\\;', ';', $values);
|
||||
$this->setAttribute($tag, trim($value), $params, true, $values);
|
||||
} else {
|
||||
$value = trim($value);
|
||||
// As of rfc 2426 2.4.2 semicolon, comma, and colon
|
||||
// must be escaped (comma is unescaped after splitting
|
||||
// below).
|
||||
$value = str_replace(array('\\n', '\\N', '\\;', '\\:', '\\\\'),
|
||||
array("\n", "\n", ';', ':', '\\'),
|
||||
$value);
|
||||
|
||||
// Split by unescaped commas.
|
||||
$values = preg_split('/(?<!\\\\),/', $value);
|
||||
$value = str_replace('\\,', ',', $value);
|
||||
$values = str_replace('\\,', ',', $values);
|
||||
|
||||
$this->setAttribute($tag, trim($value), $params, true, $values);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -899,7 +910,7 @@ class Horde_iCalendar {
|
||||
&& (!$this->isOldFormat() || empty($param_value))) {
|
||||
continue;
|
||||
}
|
||||
if ($param_name == 'ENCODING' && empty($param_value)) {
|
||||
if ($param_name == 'ENCODING') {
|
||||
continue;
|
||||
}
|
||||
/* Skip VALUE=DATE for vCalendar 1.0 data, not allowed. */
|
||||
@ -928,14 +939,54 @@ class Horde_iCalendar {
|
||||
case 'DCREATED':
|
||||
case 'LAST-MODIFIED':
|
||||
$value = $this->_exportDateTime($value);
|
||||
break;
|
||||
|
||||
|
||||
// Support additional fields after date.
|
||||
case 'AALARM':
|
||||
case 'DALARM':
|
||||
if (isset($params['VALUE'])) {
|
||||
if ($params['VALUE'] == 'DATE') {
|
||||
// VCALENDAR 1.0 uses T000000 - T235959 for all day events:
|
||||
if ($this->isOldFormat() && $name == 'DTEND') {
|
||||
$d = new Horde_Date($value);
|
||||
$value = new Horde_Date(array(
|
||||
'year' => $d->year,
|
||||
'month' => $d->month,
|
||||
'mday' => $d->mday - 1));
|
||||
$value->correct();
|
||||
$value = $this->_exportDate($value, '235959');
|
||||
} else {
|
||||
$value = $this->_exportDate($value, '000000');
|
||||
}
|
||||
} else {
|
||||
$value = $this->_exportDateTime($value);
|
||||
}
|
||||
} else {
|
||||
$value = $this->_exportDateTime($value);
|
||||
}
|
||||
|
||||
if (is_array($attribute['values']) &&
|
||||
count($attribute['values']) > 0) {
|
||||
$values = $attribute['values'];
|
||||
if ($this->isOldFormat()) {
|
||||
$values = str_replace(';', '\\;', $values);
|
||||
} else {
|
||||
// As of rfc 2426 2.5 semicolon and comma must be
|
||||
// escaped.
|
||||
$values = str_replace(array('\\', ';', ','),
|
||||
array('\\\\', '\\;', '\\,'),
|
||||
$values);
|
||||
}
|
||||
$value .= ';' . implode(';', $values);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'DTEND':
|
||||
case 'DTSTART':
|
||||
case 'DTSTAMP':
|
||||
case 'DUE':
|
||||
case 'AALARM':
|
||||
case 'DALARM':
|
||||
case 'RECURRENCE-ID':
|
||||
case 'X-RECURRENCE-ID':
|
||||
if (isset($params['VALUE'])) {
|
||||
@ -1080,20 +1131,20 @@ class Horde_iCalendar {
|
||||
// Text containing newlines or ASCII >= 127 must be BASE64
|
||||
// or QUOTED-PRINTABLE encoded. Currently we use
|
||||
// QUOTED-PRINTABLE as default.
|
||||
if (preg_match("/[^\x20-\x7F]/", $value) &&
|
||||
!isset($params['ENCODING'])) {
|
||||
$params['ENCODING'] = 'QUOTED-PRINTABLE';
|
||||
$params_str .= ';ENCODING=QUOTED-PRINTABLE';
|
||||
// Add CHARSET as well. At least the synthesis client
|
||||
// gets confused otherwise
|
||||
if (!isset($params['CHARSET'])) {
|
||||
$params['CHARSET'] = NLS::getCharset();
|
||||
$params_str .= ';CHARSET=' . $params['CHARSET'];
|
||||
}
|
||||
if (preg_match('/[^\x20-\x7F]/', $value) &&
|
||||
!isset($params['ENCODING'])) {
|
||||
$params['ENCODING'] = 'QUOTED-PRINTABLE';
|
||||
}
|
||||
if (preg_match('/([\177-\377])/', $value) &&
|
||||
!isset($params['CHARSET'])) {
|
||||
// Add CHARSET as well. At least the synthesis client
|
||||
// gets confused otherwise
|
||||
$params['CHARSET'] = NLS::getCharset();
|
||||
$params_str .= ';CHARSET=' . $params['CHARSET'];
|
||||
}
|
||||
} else {
|
||||
if (is_array($attribute['values']) &&
|
||||
count($attribute['values'])) {
|
||||
count($attribute['values']) > 1) {
|
||||
$values = $attribute['values'];
|
||||
if ($name == 'N' || $name == 'ADR' || $name == 'ORG') {
|
||||
$glue = ';';
|
||||
@ -1117,31 +1168,55 @@ class Horde_iCalendar {
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($params['ENCODING']) && strlen(trim($value))) {
|
||||
switch($params['ENCODING']) {
|
||||
case 'Q':
|
||||
case 'QUOTED-PRINTABLE':
|
||||
$value = str_replace("\r", '', $value);
|
||||
$result .= $name . $params_str . ':'
|
||||
. str_replace('=0A', '=0D=0A',
|
||||
$this->_quotedPrintableEncode($value))
|
||||
. $this->_newline;
|
||||
break;
|
||||
case 'B':
|
||||
case 'BASE64':
|
||||
$attr_string = $name . $params_str . ":" . $this->_newline . ' ' . $this->_base64Encode($value);
|
||||
$attr_string = String::wordwrap($attr_string, 75, $this->_newline . ' ',
|
||||
true, 'utf-8', true);
|
||||
$result .= $attr_string . $this->_newline;
|
||||
if ($this->isOldFormat()) {
|
||||
$result .= $this->_newline; // Append an empty line
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
$encoding = (!empty($params['ENCODING']) && strlen(trim($value)) > 0);
|
||||
|
||||
if ($encoding) {
|
||||
switch($params['ENCODING']) {
|
||||
case 'Q':
|
||||
case 'QUOTED-PRINTABLE':
|
||||
if (!$this->isOldFormat())
|
||||
{
|
||||
$enconding = false;
|
||||
break;
|
||||
}
|
||||
$params_str .= ';ENCODING=' . $params['ENCODING'];
|
||||
$value = str_replace("\r", '', $value);
|
||||
$result .= $name . $params_str . ':'
|
||||
. str_replace('=0A', '=0D=0A',
|
||||
$this->_quotedPrintableEncode($value))
|
||||
. $this->_newline;
|
||||
break;
|
||||
case 'FUNAMBOL-QP':
|
||||
// Funambol needs some special quoting
|
||||
$value = str_replace(array('<', "\r"), array('<', ''), $value);
|
||||
if (!$this->isOldFormat())
|
||||
{
|
||||
$encoding = false;
|
||||
break;
|
||||
}
|
||||
$params_str .= ';ENCODING=QUOTED-PRINTABLE';
|
||||
$result .= $name . $params_str . ':'
|
||||
. str_replace('=0A', '=0D=0A',
|
||||
$this->_quotedPrintableEncode($value, false))
|
||||
. $this->_newline;
|
||||
break;
|
||||
case 'B':
|
||||
case 'BASE64':
|
||||
$params_str .= ';ENCODING=' . $params['ENCODING'];
|
||||
$attr_string = $name . $params_str . ':' . $this->_newline . ' ' . $this->_base64Encode($value);
|
||||
$attr_string = String::wordwrap($attr_string, 75, $this->_newline . ' ',
|
||||
true, 'utf-8', true);
|
||||
$result .= $attr_string . $this->_newline;
|
||||
if ($this->isOldFormat()) {
|
||||
$result .= $this->_newline; // Append an empty line
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$encoding) {
|
||||
$value = str_replace(array("\r", "\n"), array('', '\\n'), $value);
|
||||
$attr_string = $name . $params_str;
|
||||
if (!empty($value) || $value === 0 || (is_string($value) && strlen($value) > 0)) {
|
||||
if (strlen($value) > 0) {
|
||||
$attr_string .= ':' . $value;
|
||||
} elseif ($name != 'RRULE') {
|
||||
$attr_string .= ':';
|
||||
@ -1537,7 +1612,7 @@ class Horde_iCalendar {
|
||||
*
|
||||
* @return string The quoted-printable encoded string.
|
||||
*/
|
||||
function _quotedPrintableEncode($input = '')
|
||||
function _quotedPrintableEncode($input = '', $withFolding=true)
|
||||
{
|
||||
$output = $line = '';
|
||||
$len = strlen($input);
|
||||
@ -1555,7 +1630,7 @@ class Horde_iCalendar {
|
||||
}
|
||||
$line .= $chunk;
|
||||
// Wrap long lines (rule 5)
|
||||
if (strlen($line) + 1 > 76) {
|
||||
if ($withFolding && strlen($line) + 1 > 76) {
|
||||
$line = String::wordwrap($line, 75, "=\r\n", true, 'us-ascii', true);
|
||||
$newline = strrchr($line, "\r\n");
|
||||
if ($newline !== false) {
|
||||
@ -1567,7 +1642,7 @@ class Horde_iCalendar {
|
||||
continue;
|
||||
}
|
||||
// Wrap at line breaks for better readability (rule 4).
|
||||
if (substr($line, -3) == '=0A') {
|
||||
if ($withFolding && substr($line, -3) == '=0A') {
|
||||
$output .= $line . "=\r\n";
|
||||
$line = '';
|
||||
}
|
||||
|
28
rpc.php
28
rpc.php
@ -10,22 +10,27 @@
|
||||
|
||||
error_reporting(E_ALL & ~E_NOTICE);
|
||||
@define('AUTH_HANDLER', true);
|
||||
@define('HORDE_BASE', dirname(__FILE__).'/phpgwapi/inc/horde/');
|
||||
@define('EGW_API_INC', dirname(__FILE__) . '/phpgwapi/inc/');
|
||||
@define('HORDE_BASE', EGW_API_INC . '/horde/');
|
||||
require_once HORDE_BASE . '/lib/core.php';
|
||||
require_once 'Horde/RPC.php';
|
||||
//require_once EGW_API_INC . '/common_functions.inc.php';
|
||||
|
||||
$GLOBALS['egw_info'] = array(
|
||||
'flags' => array(
|
||||
'currentapp' => 'login',
|
||||
'noheader' => True,
|
||||
'nonavbar' => True,
|
||||
'disable_Template_class' => True
|
||||
)
|
||||
'currentapp' => 'syncml',
|
||||
'noheader' => true,
|
||||
'nonavbar' => true,
|
||||
'noapi' => true,
|
||||
'disable_Template_class' => true,
|
||||
),
|
||||
'server' => array(
|
||||
'show_domain_selectbox' => true,
|
||||
),
|
||||
);
|
||||
include('./header.inc.php');
|
||||
|
||||
// allow to use an authentication specific for SyncML
|
||||
$GLOBALS['egw_info']['flags']['currentapp'] = 'syncml';
|
||||
|
||||
include('./header.inc.php');
|
||||
|
||||
$errors = array();
|
||||
|
||||
@ -45,11 +50,6 @@ if(version_compare(PHP_VERSION, '5.0.0') < 0) {
|
||||
$errors[] = 'eGroupWare\'s SyncML server requires PHP5. Please update to PHP 5.0.x if you want to use SyncML.';
|
||||
}
|
||||
|
||||
$config =& CreateObject('phpgwapi.config','syncml');
|
||||
$config->read_repository();
|
||||
$GLOBALS['config_syncml'] =& $config->config_data;
|
||||
unset($config);
|
||||
|
||||
/* Look at the Content-type of the request, if it is available, to try
|
||||
* and determine what kind of request this is. */
|
||||
$input = null;
|
||||
|
Loading…
Reference in New Issue
Block a user