support for slowsync with search

added real working state machine
SyncML conformance improvment
This commit is contained in:
Lars Kneschke 2006-03-21 13:49:13 +00:00
parent e15d167c87
commit 2dedbf0f7c
15 changed files with 994 additions and 646 deletions

View File

@ -127,8 +127,8 @@ class Horde_RPC_syncml extends Horde_RPC {
$xml, $m)) {
$this->_charset = $m[1];
}
NLS::setCharset($this->_charset);
String::setDefaultCharset($this->_charset);
#NLS::setCharset($this->_charset);
#String::setDefaultCharset($this->_charset);
/* Create the XML parser and set method references. */
$this->_parser = xml_parser_create_ns($this->_charset);

View File

@ -155,19 +155,25 @@ class Horde_SyncML_SyncMLHdr extends Horde_SyncML_ContentHandler {
// 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));
if(!empty($_GET['syncml_sessionid'])) {
session_id($_GET['syncml_sessionid']);
Horde::logMessage('SyncML['. session_id() .']: reusing existing session', __FILE__, __LINE__, PEAR_LOG_INFO);
} else {
#session_id('syncml' . preg_replace('/[^a-zA-Z0-9]/', '', $sourceURI . $sessionID));
session_id('syncml-' . md5(uniqid(rand(), true)));
Horde::logMessage('SyncML['. session_id() .']: starting new session for '.$this->_locName, __FILE__, __LINE__, PEAR_LOG_INFO);
}
@session_start();
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);
Horde::logMessage('SyncML['. session_id() .']: create new session state variable', __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);
#if($_SESSION['SyncML.state']->_isAuthorized)
# Horde::logMessage('SyncML['. session_id() .']: is session authorized', __FILE__, __LINE__, PEAR_LOG_DEBUG);
return $_SESSION['SyncML.state'];
}
@ -202,11 +208,13 @@ class Horde_SyncML_SyncMLHdr extends Horde_SyncML_ContentHandler {
*/
// </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);
$state->setVersion($this->_version);
$state->setMsgID($this->_msgID);
$state->setTargetURI($this->_targetURI);
$state->setWBXML(is_a($this->_output, 'XML_WBXML_Encoder'));
if(isset($this->_credData) && isset($this->_locName) && !$state->isAuthorized())
{
$state->setPassword($this->_credData);
@ -262,7 +270,7 @@ class Horde_SyncML_SyncMLHdr extends Horde_SyncML_ContentHandler {
}
$this->_credData = $tmp[1];
Horde::logMessage('SyncML: $this->_locName: ' . $this->_locName, __FILE__, __LINE__, PEAR_LOG_DEBUG);
#Horde::logMessage('SyncML['. session_id() .']: $this->_locName: ' . $this->_locName, __FILE__, __LINE__, PEAR_LOG_DEBUG);
}
break;
@ -344,15 +352,16 @@ class Horde_SyncML_SyncMLHdr extends Horde_SyncML_ContentHandler {
$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');
#}
if(session_id() != '') {
$output->startElement($uri, 'RespURI', $attrs);
if($_SERVER['HTTPS'] == 'on') {
$httpPrefix = 'https://';
} else {
$httpPrefix = 'http://';
}
$output->characters($httpPrefix . $_SERVER['SERVER_NAME'] .':'. $_SERVER['SERVER_PORT'] . $_SERVER['PHP_SELF'] . '?syncml_sessionid=' . session_id());
$output->endElement($uri, 'RespURI');
}
/*
$output->startElement($uri, 'Meta', $attrs);
@ -437,6 +446,7 @@ class Horde_SyncML_SyncMLBody extends Horde_SyncML_ContentHandler {
$state = & $_SESSION['SyncML.state'];
$this->_actionCommands = false; // so far, we have not seen commands that require action from our side
$state->_sendFinal = false;
// <SyncML><SyncBody>
$this->_output->startElement($uri, $element, $attrs);
@ -477,7 +487,7 @@ class Horde_SyncML_SyncMLBody extends Horde_SyncML_ContentHandler {
// We've got to do something! This can't be the last
// packet.
$this->_actionCommands = true;
Horde::logMessage("SyncML: found action commands <$element> " . $this->_actionCommands, __FILE__, __LINE__, PEAR_LOG_INFO);
Horde::logMessage('SyncML['. session_id() ."]: found action commands <$element> " . $this->_actionCommands, __FILE__, __LINE__, PEAR_LOG_DEBUG);
}
switch($element)
@ -490,7 +500,7 @@ class Horde_SyncML_SyncMLBody extends Horde_SyncML_ContentHandler {
# break;
case 'Sync':
$state->setSyncStatus(CLIENT_SYNC_STARTED);
Horde::logMessage('SyncML: syncStatus(client sync started) ' . $state->getSyncStatus(), __FILE__, __LINE__, PEAR_LOG_INFO);
Horde::logMessage('SyncML['. session_id() .']: syncStatus(client sync started) ' . $state->getSyncStatus(), __FILE__, __LINE__, PEAR_LOG_DEBUG);
break;
}
break;
@ -502,65 +512,92 @@ class Horde_SyncML_SyncMLBody extends Horde_SyncML_ContentHandler {
}
}
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();
}
function endElement($uri, $element) {
switch ($this->_xmlStack) {
case 2:
// </SyncBody></SyncML>
$state = & $_SESSION['SyncML.state'];
if($state->getSyncStatus() == CLIENT_SYNC_FINNISHED && $state->getAlert222Received() == true) {
$state->setSyncStatus(CLIENT_SYNC_ACKNOWLEDGED);
$state->setAlert222Received(false);
}
// 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_ACKNOWLEDGED && $state->getSyncStatus() < SERVER_SYNC_FINNISHED) {
Horde::logMessage('SyncML sending syncdata to client '. CLIENT_SYNC_ACKNOWLEDGED .'/'. SERVER_SYNC_FINNISHED .'/'. $state->getSyncStatus(), __FILE__, __LINE__, PEAR_LOG_INFO);
$sync = &new Horde_SyncML_Command_Sync();
$this->_currentCmdID = $sync->syncToClient($this->_currentCmdID, $this->_output);
}
// send the Final tag if possible
#if($state->getSyncStatus() != SERVER_SYNC_DATA_PENDING && $state->getSyncStatus() != CLIENT_SYNC_STARTED) {
if($state->getSyncStatus() >= SERVER_SYNC_FINNISHED || $state->_sendFinal) {
$final = &new Horde_SyncML_Command_Final();
$this->_currentCmdID = $final->output($this->_currentCmdID, $this->_output);
}
$this->_output->endElement($uri, $element);
Horde::logMessage('SyncML['. session_id() .']: syncStatus ' . $state->getSyncStatus() .'actionCommands: '.$this->_actionCommands, __FILE__, __LINE__, PEAR_LOG_DEBUG);
if (!$this->_actionCommands && $state->getSyncStatus() == SERVER_SYNC_FINNISHED) {
// this packet did not contain any real actions, just status and map.
// This means, we're through! The session can be closed and
// the Anchors saved for the next Sync
$state = & $_SESSION['SyncML.state'];
Horde::logMessage('SyncML['. session_id() .']: sync' . session_id() . ' completed successfully!', __FILE__, __LINE__, PEAR_LOG_INFO);
$state->writeSyncSummary();
$log = $state->getLog();
$s="";
foreach($log as $k => $v) {
$s .= " $k=$v";
}
Horde::logMessage('SyncML['. session_id() .']: summary:' . $s, __FILE__, __LINE__, PEAR_LOG_INFO);
# Horde::logMessage('SyncML['. session_id() .']: destroying sync session '.session_id(), __FILE__, __LINE__, PEAR_LOG_INFO);
# // session can be closed here!
# session_unset();
# session_destroy();
}
if (!$this->_actionCommands && $state->getSyncStatus() == SERVER_SYNC_ACKNOWLEDGED) {
// this packet did not contain any real actions, just status and map.
// This means, we're through! The session can be closed and
// the Anchors saved for the next Sync
$state = & $_SESSION['SyncML.state'];
Horde::logMessage('SyncML['. session_id() .']: sync' . session_id() . ' completed successfully!', __FILE__, __LINE__, PEAR_LOG_INFO);
$state->writeSyncSummary();
$log = $state->getLog();
$s="";
foreach($log as $k => $v) {
$s .= " $k=$v";
}
Horde::logMessage('SyncML['. session_id() .']: summary:' . $s, __FILE__, __LINE__, PEAR_LOG_INFO);
if (!$this->_actionCommands && $state->getSyncStatus() == SERVER_SYNC_FINNISHED && $this->_clientSentFinal) {
Horde::logMessage('SyncML: destroying sync session '.session_id(), __FILE__, __LINE__, PEAR_LOG_INFO);
// session can be closed here!
session_unset();
session_destroy();
}
break;
case 3:
// </[Command]></SyncBody></SyncML>
$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
Horde::logMessage('SyncML['. session_id() .']: destroying sync session '.session_id(), __FILE__, __LINE__, PEAR_LOG_INFO);
// session can be closed here!
session_unset();
session_destroy();
}
if($state->getSyncStatus() == CLIENT_SYNC_FINNISHED) {
$state->setSyncStatus(CLIENT_SYNC_ACKNOWLEDGED);
Horde::logMessage('SyncML['. session_id() .']: syncStatus(client sync acknowledged) '.$state->getSyncStatus(), __FILE__, __LINE__, PEAR_LOG_DEBUG);
}
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())
/* if(!$state->getClientDeviceInfo())
{
$attrs = array();
$this->_output->startElement($state->getURI(), 'Get', $attrs);
@ -587,43 +624,49 @@ class Horde_SyncML_SyncMLBody extends Horde_SyncML_ContentHandler {
$this->_output->endElement($state->getURI(), 'Item');
$this->_output->endElement($state->getURI(), 'Get');
}
}
$this->_currentCommand->endElement($uri, $element);
} */
}
$this->_currentCommand->endElement($uri, $element);
switch($element) {
case 'Final':
if($state->getSyncStatus() == CLIENT_SYNC_STARTED) {
$state->setSyncStatus(CLIENT_SYNC_FINNISHED);
Horde::logMessage('SyncML['. session_id() .']: syncStatus(client sync finnished) ' . $state->getSyncStatus(), __FILE__, __LINE__, PEAR_LOG_DEBUG);
}
if($state->getSyncStatus() == SERVER_SYNC_FINNISHED) {
$state->setSyncStatus(SERVER_SYNC_ACKNOWLEDGED);
Horde::logMessage('SyncML['. session_id() .']: syncStatus(server sync acknowledged) ' . $state->getSyncStatus(), __FILE__, __LINE__, PEAR_LOG_DEBUG);
}
$this->_clientSentFinal = true;
#Horde::logMessage('SyncML['. session_id() .']: 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;
switch($element)
{
case 'Final':
if($state->getSyncStatus() == CLIENT_SYNC_STARTED)
{
$state->setSyncStatus(CLIENT_SYNC_FINNISHED);
Horde::logMessage('SyncML: syncStatus(client sync finnished) ' . $state->getSyncStatus(), __FILE__, __LINE__, PEAR_LOG_INFO);
}
$this->_clientSentFinal = true;
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);
}
}
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

@ -196,11 +196,29 @@ class Horde_SyncML_Command_Alert extends Horde_SyncML_Command {
$output->endElement($state->getURI(), 'Item');
$output->endElement($state->getURI(), 'Alert');
$state->_sendFinal = true;
$currentCmdID++;
}
}
else
{
} elseif ($this->_alert == ALERT_NEXT_MESSAGE) {
$status = &new Horde_SyncML_Command_Status(RESPONSE_OK, 'Alert');
$status->setCmdRef($this->_cmdID);
if ($this->_targetLocURI != null) {
$status->setTargetRef((isset($this->_targetLocURIParameters) ? $this->_targetLocURI.'?/'.$this->_targetLocURIParameters : $this->_targetLocURI));
}
if ($this->_sourceLocURI != null) {
$status->setSourceRef($this->_sourceLocURI);
}
$status->setItemSourceLocURI($this->_sourceLocURI);
$status->setItemTargetLocURI(isset($this->_targetLocURIParameters) ? $this->_targetLocURI.'?/'.$this->_targetLocURIParameters : $this->_targetLocURI);
$currentCmdID = $status->output($currentCmdID, $output);
$state->setAlert222Received(true);
#if($state->getSyncStatus() > CLIENT_SYNC_STARTED && $state->getSyncStatus() < CLIENT_SYNC_ACKNOWLEDGED) {
# $state->setSyncStatus(CLIENT_SYNC_ACKNOWLEDGED);
#}
} else {
$status = &new Horde_SyncML_Command_Status(RESPONSE_OK, 'Alert');
$status->setCmdRef($this->_cmdID);
if ($this->_sourceLocURI != null) {

View File

@ -44,6 +44,10 @@ class Horde_SyncML_Command_Status extends Horde_SyncML_Command {
var $_itemDataAnchorLast;
var $_itemTargetLocURI;
var $_itemSourceLocURI;
function Horde_SyncML_Command_Status($response = null, $cmd = null)
{
if ($response != null) {
@ -85,13 +89,6 @@ class Horde_SyncML_Command_Status extends Horde_SyncML_Command {
$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;
@ -99,6 +96,13 @@ class Horde_SyncML_Command_Status extends Horde_SyncML_Command {
$output->endElement($state->getURI(), 'TargetRef');
}
if (isset($this->_sourceRef)) {
$output->startElement($state->getURI(), 'SourceRef', $attrs);
$chars = $this->_sourceRef;
$output->characters($chars);
$output->endElement($state->getURI(), 'SourceRef');
}
// If we are responding to the SyncHdr and we are not
// authorized then request basic authorization.
//
@ -170,9 +174,61 @@ class Horde_SyncML_Command_Status extends Horde_SyncML_Command {
$output->endElement($state->getURI(), 'Item');
}
if (isset($this->_itemTargetLocURI) && isset($this->_itemSourceLocURI)) {
$output->startElement($state->getURI(), 'Item', $attrs);
$output->startElement($state->getURI(), 'Target', $attrs);
$output->startElement($state->getURI(), 'LocURI', $attrs);
$output->characters($this->_itemTargetLocURI);
$output->endElement($state->getURI(), 'LocURI');
$output->endElement($state->getURI(), 'Target');
$output->startElement($state->getURI(), 'Source', $attrs);
$output->startElement($state->getURI(), 'LocURI', $attrs);
$output->characters($this->_itemSourceLocURI);
$output->endElement($state->getURI(), 'LocURI');
$output->endElement($state->getURI(), 'Source');
$output->endElement($state->getURI(), 'Item');
}
$output->endElement($state->getURI(), 'Status');
$currentCmdID++;
// moredata pending request them
/* if($this->_response == RESPONSE_CHUNKED_ITEM_ACCEPTED_AND_BUFFERED) {
$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);
$output->characters(ALERT_NEXT_MESSAGE);
$output->endElement($state->getURI(), 'Data');
if (isset($this->_itemTargetLocURI) && isset($this->_itemSourceLocURI)) {
$output->startElement($state->getURI(), 'Item', $attrs);
$output->startElement($state->getURI(), 'Target', $attrs);
$output->startElement($state->getURI(), 'LocURI', $attrs);
$output->characters($this->_itemTargetLocURI);
$output->endElement($state->getURI(), 'LocURI');
$output->endElement($state->getURI(), 'Target');
$output->startElement($state->getURI(), 'Source', $attrs);
$output->startElement($state->getURI(), 'LocURI', $attrs);
$output->characters($this->_itemSourceLocURI);
$output->endElement($state->getURI(), 'LocURI');
$output->endElement($state->getURI(), 'Source');
}
$output->endElement($state->getURI(), 'Alert');
$currentCmdID++;
} */
}
return $currentCmdID;
@ -248,4 +304,23 @@ class Horde_SyncML_Command_Status extends Horde_SyncML_Command {
$this->_itemDataAnchorLast = $itemDataAnchorLast;
}
/**
* Setter for property itemSourceLocURI.
*
* @param string $itemSourceLocURI New value of property itemSourceLocURI.
*/
function setItemSourceLocURI($itemSourceLocURI)
{
$this->_itemSourceLocURI = $itemSourceLocURI;
}
/**
* Setter for property itemTargetLocURI.
*
* @param string $itemTargetLocURI New value of property itemTargetLocURI.
*/
function setItemTargetLocURI($itemTargetLocURI)
{
$this->_itemTargetLocURI = $itemTargetLocURI;
}
}

View File

@ -22,46 +22,48 @@ include_once 'Horde/SyncML/Sync/OneWayFromServerSync.php';
*/
class Horde_SyncML_Command_Sync extends Horde_Syncml_Command {
var $_isInSource;
var $_currentSyncElement;
var $_syncElements = array();
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);
if($sync = $state->getSync($this->_targetURI)) {
$currentCmdID = $sync->startSync($currentCmdID, $output);
foreach ($this->_syncElements as $element) {
$currentCmdID = $sync->nextSyncCommand($currentCmdID, $element, $output);
}
}
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;
}
return $currentCmdID;
}
function getTargetURI() {
return $this->_targetURI;
}
function startElement($uri, $element, $attrs)
{
@ -96,7 +98,7 @@ class Horde_SyncML_Command_Sync extends Horde_Syncml_Command {
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)
if($state->getSyncStatus() >= CLIENT_SYNC_ACKNOWLEDGED && $state->getSyncStatus() < SERVER_SYNC_FINNISHED)
{
$deviceInfo = $state->getClientDeviceInfo();
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);

View File

@ -108,7 +108,7 @@ class Horde_SyncML_Command_Sync_ContentSyncElement extends Horde_SyncML_Command_
|| isset($this->_locURI) || isset($this->targetURI)) {
$output->startElement($state->getURI(), 'Item', $attrs);
// send only when sending adds
if ($this->_locURI != null && strtolower($command) == 'add') {
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);

View File

@ -16,17 +16,18 @@ include_once 'Horde/SyncML/Command/Sync/SyncElement.php';
* @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($this->_status, 'Replace');
$status->setCmdRef($this->_cmdID);
if (isset($this->_luid)) {
$status->setSourceRef($this->_luid);
}
return $status->output($currentCmdID, $output);
}
function output($currentCmdID, &$output) {
$status = &new Horde_SyncML_Command_Status($this->_status, 'Replace');
$status->setCmdRef($this->_cmdID);
if (isset($this->_luid)) {
$status->setSourceRef($this->_luid);
}
#$status->setItemSourceLocURI($this->_sourceLocURI);
#$status->setItemTargetLocURI(isset($this->_targetLocURIParameters) ? $this->_targetLocURI.'?/'.$this->_targetLocURIParameters : $this->_targetLocURI);
return $status->output($currentCmdID, $output);
}
}

View File

@ -6,6 +6,7 @@ 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>
* Copyright 2005-2006 Lars Kneschke <l.kneschke@metaways.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.
@ -17,75 +18,104 @@ include_once 'Horde/SyncML/Command.php';
*/
class Horde_SyncML_Command_Sync_SyncElement extends Horde_SyncML_Command {
var $_luid;
var $_guid;
var $_isSource;
var $_content;
var $_contentType;
var $_status = RESPONSE_OK;
var $_luid;
var $_guid;
var $_isSource;
var $_content;
var $_contentType;
var $_status = RESPONSE_OK;
var $_items;
function &factory($command, $params = null) {
include_once 'Horde/SyncML/Command/Sync/SyncElementItem.php';
@include_once 'Horde/SyncML/Command/Sync/' . $command . '.php';
$class = 'Horde_SyncML_Command_Sync_' . $command;
if (class_exists($class)) {
#Horde::logMessage('SyncML: Class definition of ' . $class . ' found in SyncElement::factory.', __FILE__, __LINE__, PEAR_LOG_DEBUG);
return $element = &new $class($params);
} else {
Horde::logMessage('SyncML: Class definition of ' . $class . ' not found in SyncElement::factory.', __FILE__, __LINE__, PEAR_LOG_DEBUG);
require_once 'PEAR.php';
return PEAR::raiseError('Class definition of ' . $class . ' not found.');
}
}
function &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) {
$search = array('/ *\n/','/ *$/m');
$replace = array('','');
switch ($this->_xmlStack) {
case 1:
// Need to add sync elements to the Sync method?
#error_log('total # of items: '.count($this->_items));
#error_log(print_r($this->_items[10], true));
break;
case 2;
if($element == 'Item') {
$item = new Horde_SyncML_Command_Sync_SyncElementItem();
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)
{
$search = array('/ *\n/','/ *$/m');
$replace = array('','');
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 = $this->_chars;
} elseif ($element == 'MoreData') {
$this->_moreData = TRUE;
} 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);
} elseif ($element == 'Size') {
$this->_contentSize = trim($this->_chars);
}
break;
}
parent::endElement($uri, $element);
}
if($this->_luid) {
$item->setLocURI($this->_luid);
$item->setContent($this->_content);
$item->setContentType($this->_contentType);
if($this->_contentSize)
$item->setContentType($this->_contentSize);
if($this->_moreData)
$item->setMoreData($this->_moreData);
$this->_items[$this->_luid] = $item;
}
unset($this->_content);
unset($this->_contentSize);
unset($this->_luid);
}
break;
case 3:
if ($element == 'Source') {
$this->_isSource = false;
} elseif ($element == 'Data') {
$this->_content = $this->_chars;
} elseif ($element == 'MoreData') {
$this->_moreData = TRUE;
} elseif ($element == 'Type') {
if(empty($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);
} elseif ($element == 'Size') {
$this->_contentSize = trim($this->_chars);
}
break;
}
parent::endElement($uri, $element);
}
function getSyncElementItems() {
return (array)$this->_items;
}
function getLocURI()
{

View File

@ -126,8 +126,10 @@ 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('CLIENT_SYNC_ACKNOWLEDGED', 3);
define('SERVER_SYNC_DATA_PENDING', 4);
define('SERVER_SYNC_FINNISHED', 5);
define('SERVER_SYNC_ACKNOWLEDGED', 6);
define('MAX_DATA', 19);
define('MAX_ENTRIES', 10);
@ -148,52 +150,55 @@ define('MAX_ENTRIES', 10);
* @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();
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();
// stores if we received Alert 222 already
var $_receivedAlert222 = false;
/**
* Creates a new instance of Horde_SyncML_State.
@ -465,11 +470,11 @@ class Horde_SyncML_State {
* by a <SyncML xmlns="syncml:SYNCML1.1"> element. They require
* just <SyncML>. So don't use an ns for non wbxml devices.
*/
# if ($this->isWBXML()) {
if ($this->isWBXML()) {
return $this->_uri;
# } else {
# return '';
# }
} else {
return '';
}
}
function getURIMeta()
{
@ -625,15 +630,42 @@ class Horde_SyncML_State {
*/
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';
}
# 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';
# }
switch($type) {
case 'contacts':
return 'text/x-vcard';
break;
case 'sifcontacts':
case './sifcontacts':
return 'text/x-s4j-sifc';
break;
case 'siftasks':
case './siftasks':
return 'text/x-s4j-sift';
break;
case 'notes':
return 'text/x-vnote';
break;
case 'tasks':
return 'text/x-vcalendar';
break;
case 'calendar':
return 'text/x-vcalendar';
break;
}
}
/**
@ -889,4 +921,12 @@ class Horde_SyncML_State {
exit;
}
function getAlert222Received() {
return $this->_receivedAlert222;
}
function setAlert222Received($_status) {
$this->_receivedAlert222 = (bool)$_status;
}
}

View File

@ -23,13 +23,13 @@ class EGW_SyncML_State extends Horde_SyncML_State
'map_guid' => $guid,
);
Horde::logMessage('SyncML: getChangeTS for ' . $mapID .' / '. $guid, __FILE__, __LINE__, PEAR_LOG_DEBUG);
#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);
#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'));
}
@ -103,7 +103,7 @@ class EGW_SyncML_State extends Horde_SyncML_State
{
$mapID = $this->_locName . $this->_sourceURI . $type;
Horde::logMessage('SyncML: search GlobalUID for ' . $mapID .' / '.$locid, __FILE__, __LINE__, PEAR_LOG_DEBUG);
#Horde::logMessage('SyncML: search GlobalUID for ' . $mapID .' / '.$locid, __FILE__, __LINE__, PEAR_LOG_DEBUG);
$db = clone($GLOBALS['egw']->db);
@ -145,11 +145,12 @@ class EGW_SyncML_State extends Horde_SyncML_State
'map_id' => $mapID,
'map_guid' => $guid
);
Horde::logMessage('SyncML: search LocID for ' . $mapID .' / '.$guid, __FILE__, __LINE__, PEAR_LOG_DEBUG);
$db->select('egw_contentmap', $cols, $where, __LINE__, __FILE__);
if($db->next_record())
{
Horde::logMessage('SyncML: found LocID: '.$db->f('map_locuid'), __FILE__, __LINE__, PEAR_LOG_DEBUG);
return $db->f('map_locuid');
}
@ -180,10 +181,10 @@ class EGW_SyncML_State extends Horde_SyncML_State
$db->select('egw_syncmlsummary', $cols, $where, __LINE__, __FILE__);
Horde::logMessage("SyncML: get SYNCSummary for $deviceID", __FILE__, __LINE__, PEAR_LOG_DEBUG);
#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);
#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'),
@ -211,12 +212,12 @@ class EGW_SyncML_State extends Horde_SyncML_State
$this->_locName .= '@'.$GLOBALS['phpgw_info']['server']['default_domain'];
}
Horde::logMessage('SyncML: Authenticate ' . $this->_locName . ' - ' . $this->_password, __FILE__, __LINE__, PEAR_LOG_DEBUG);
#Horde::logMessage('SyncML: Authenticate ' . $this->_locName . ' - ' . $this->_password, __FILE__, __LINE__, PEAR_LOG_DEBUG);
if($GLOBALS['sessionid'] = $GLOBALS['egw']->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);
#Horde::logMessage('SyncML_EGW: Authentication of ' . $this->_locName . '/' . $GLOBALS['sessionid'] . ' succeded' , __FILE__, __LINE__, PEAR_LOG_DEBUG);
}
else
{
@ -264,7 +265,7 @@ class EGW_SyncML_State extends Horde_SyncML_State
$guid = $db->f('map_guid');
Horde::logMessage("SyncML: state->removeUID(type=$type,locid=$locid) : removing guid:$guid", __FILE__, __LINE__, PEAR_LOG_DEBUG);
#Horde::logMessage("SyncML: state->removeUID(type=$type,locid=$locid) : removing guid:$guid", __FILE__, __LINE__, PEAR_LOG_DEBUG);
$db->delete('egw_contentmap', $where, __LINE__, __FILE__);
@ -295,7 +296,7 @@ class EGW_SyncML_State extends Horde_SyncML_State
$ts = time();
}
Horde::logMessage("SyncML: setUID $type, $locid, $guid, $ts ".count($guidParts), __FILE__, __LINE__, PEAR_LOG_DEBUG);
#Horde::logMessage("SyncML: setUID $type, $locid, $guid, $ts ".count($guidParts), __FILE__, __LINE__, PEAR_LOG_DEBUG);
$db = clone($GLOBALS['egw']->db);
@ -312,9 +313,10 @@ class EGW_SyncML_State extends Horde_SyncML_State
'map_expired' => 0,
);
$db->delete('egw_contentmap', $where, __LINE__, __FILE__);
$db->insert('egw_contentmap', $data, $where, __LINE__, __FILE__);
Horde::logMessage("SyncML: setUID $type, $locid, $guid, $ts $mapID", __FILE__, __LINE__, PEAR_LOG_DEBUG);
#Horde::logMessage("SyncML: setUID $type, $locid, $guid, $ts $mapID", __FILE__, __LINE__, PEAR_LOG_DEBUG);
}

View File

@ -85,158 +85,146 @@ class Horde_SyncML_Sync {
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() .' moreData '. $command->_moreData, __FILE__, __LINE__, PEAR_LOG_DEBUG);
global $registry;
#require_once 'Horde/History.php';
#$history = &Horde_History::singleton();
$history = $GLOBALS['phpgw']->contenthistory;
$state = &$_SESSION['SyncML.state'];
if(isset($state->_moreData['luid']))
{
if(($command->_luid == $state->_moreData['luid']))
{
$lastChunks = implode('',$state->_moreData['chunks']);
$command->_content = $lastChunks.$command->_content;
$stringlen1 = strlen($lastChunks);
$stringlen2 = strlen($command->_content);
if(!$command->_moreData &&
strlen($command->_content)
!= $state->_moreData['contentSize']
)
{
$command->_status = RESPONSE_SIZE_MISMATCH;
$state->_moreData = array();
return;
}
elseif(!$command->_moreData &&
strlen($command->_content)
== $state->_moreData['contentSize']
)
{
$state->_moreData = array();
return;
}
}
else
{
// alert 223 needed too
#$command->_status = ALERT_NO_END_OF_DATA;
$state->_moreData = array();
return;
}
}
// don't add/replace the data currently, they are not yet complete
if($command->_moreData == TRUE)
{
$state->_moreData['chunks'][] = $command->_content;
$state->_moreData['luid'] = $command->_luid;
// gets only set with the first chunk of data
if(isset($command->_contentSize))
$state->_moreData['contentSize'] = $command->_contentSize;
$command->_status = RESPONSE_CHUNKED_ITEM_ACCEPTED_AND_BUFFERED;
return;
}
$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;
}
/**
* 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() .' moreData '. $command->_moreData, __FILE__, __LINE__, PEAR_LOG_DEBUG);
global $registry;
$history = $GLOBALS['egw']->contenthistory;
$state = &$_SESSION['SyncML.state'];
if(isset($state->_moreData['luid'])) {
if(($command->_luid == $state->_moreData['luid'])) {
Horde::logMessage('SyncML: got next moreData chunk '.$command->getContent(), __FILE__, __LINE__, PEAR_LOG_DEBUG);
$lastChunks = implode('',$state->_moreData['chunks']);
$command->_content = $lastChunks.$command->_content;
$stringlen1 = strlen($lastChunks);
$stringlen2 = strlen($command->_content);
if(!$command->_moreData && strlen($command->_content) != $state->_moreData['contentSize']) {
$command->_status = RESPONSE_SIZE_MISMATCH;
$state->_moreData = array();
return;
} elseif(!$command->_moreData && strlen($command->_content) == $state->_moreData['contentSize']) {
$state->_moreData = array();
Horde::logMessage('SyncML: chunk ended successful type is ' . $command->getContentType() .' content is '. $command->getContent(), __FILE__, __LINE__, PEAR_LOG_DEBUG);
}
} else {
// alert 223 needed too
#$command->_status = ALERT_NO_END_OF_DATA;
$state->_moreData = array();
return;
}
}
// don't add/replace the data currently, they are not yet complete
if($command->_moreData == TRUE) {
$state->_moreData['chunks'][] = $command->_content;
$state->_moreData['luid'] = $command->_luid;
// gets only set with the first chunk of data
if(isset($command->_contentSize))
$state->_moreData['contentSize'] = $command->_contentSize;
$command->_status = RESPONSE_CHUNKED_ITEM_ACCEPTED_AND_BUFFERED;
Horde::logMessage('SyncML: added moreData chunk '.$command->getContent(), __FILE__, __LINE__, PEAR_LOG_DEBUG);
return;
}
$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';
}
$syncElementItems = $command->getSyncElementItems();
foreach($syncElementItems as $syncItem) {
$guid = false;
if (is_a($command, 'Horde_SyncML_Command_Sync_Add')) {
$guid = $registry->call($hordeType . '/import',
array($state->convertClient2Server($syncItem->getContent(), $contentType), $contentType));
if (!is_a($guid, 'PEAR_Error')) {
$ts = $history->getTSforAction($guid, 'add');
$state->setUID($type, $syncItem->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, $syncItem->getLocURI());
#$guid = $state->getGlobalUID($type, $syncItem->getLocURI());
Horde::logMessage('SyncML: about to delete entry ' . $type .' / '. $guid . ' due to client request '.$syncItem->getLocURI(), __FILE__, __LINE__, PEAR_LOG_DEBUG);
if (!is_a($guid, 'PEAR_Error') && $guid != false) {
$registry->call($hordeType . '/delete', array($guid));
#$ts = $history->getTSforAction($guid, 'delete');
#$state->setUID($type, $syncItem->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, $syncItem->getLocURI());
$ok = false;
if ($guid) {
Horde::logMessage('SyncML: locuri'. $syncItem->getLocURI() . ' guid ' . $guid , __FILE__, __LINE__, PEAR_LOG_ERR);
// Entry exists: replace current one.
$ok = $registry->call($hordeType . '/replace',
array($guid, $state->convertClient2Server($syncItem->getContent(), $contentType), $contentType));
if (!is_a($ok, 'PEAR_Error')) {
$ts = $history->getTSforAction($guid, 'modify');
$state->setUID($type, $syncItem->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($syncItem->getContent(), $contentType), $contentType));
if (!is_a($guid, 'PEAR_Error')) {
$ts = $history->getTSforAction($guid, 'add');
$state->setUID($type, $syncItem->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

@ -36,60 +36,190 @@ class Horde_SyncML_Sync_SlowSync extends Horde_SyncML_Sync_TwoWaySync {
# $adds = &$state->getAddedItems($hordeType);
#}
Horde::logMessage("SyncML: ".count($adds). ' added items found for '.$hordeType , __FILE__, __LINE__, PEAR_LOG_DEBUG);
#Horde::logMessage("SyncML: ".count($adds). ' added items found for '.$hordeType , __FILE__, __LINE__, PEAR_LOG_DEBUG);
$serverAnchorNext = $state->getServerAnchorNext($syncType);
$counter = 0;
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: slowsync 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: slowsync add: $guid ignored, came from client", __FILE__, __LINE__, PEAR_LOG_DEBUG);
continue;
}
#$guid_ts = max($history->getTSforAction($guid, 'add'),$history->getTSforAction($guid, 'modify'));
$sync_ts = $state->getChangeTS($syncType, $guid);
#Horde::logMessage("SyncML: slowsync 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: slowsync add: $guid ignored, came from client", __FILE__, __LINE__, PEAR_LOG_DEBUG);
continue;
}
# $locid = $state->getLocID($syncType, $guid);
#
#$locid = $state->getLocID($syncType, $guid);
// Create an Add request for client.
// 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));
Horde::logMessage("SyncML: slowsync add to server $c", __FILE__, __LINE__, PEAR_LOG_DEBUG);
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');
$contentType = $state->getPreferedContentTypeClient($this->_sourceLocURI);
if(is_a($contentType, 'PEAR_Error')) {
// Client did not sent devinfo
$contentType = array('ContentType' => $state->getPreferedContentType($this->_targetLocURI));
}
// return if we have to much data
if(++$counter >= MAX_ENTRIES)
{
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
return $currentCmdID;
}
}
}
Horde::logMessage("SyncML: handling sync ".$currentCmdID, __FILE__, __LINE__, PEAR_LOG_DEBUG);
$cmd = &new Horde_SyncML_Command_Sync_ContentSyncElement();
$c = $registry->call($hordeType . '/export', array('guid' => $guid, 'contentType' => $contentType));
#Horde::logMessage("SyncML: slowsync add to server $c", __FILE__, __LINE__, PEAR_LOG_DEBUG);
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(++$counter >= MAX_ENTRIES)
{
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
return $currentCmdID;
}
}
}
#Horde::logMessage("SyncML: handling sync ".$currentCmdID, __FILE__, __LINE__, PEAR_LOG_DEBUG);
$state->clearSync($syncType);
return $currentCmdID;
}
/**
* Here's where the actual processing of a client-sent Sync
* Command takes place. Entries are added or replaced
* from the server database by using Horde API (Registry) calls.
*/
function runSyncCommand(&$command) {
#Horde::logMessage('SyncML: content type is ' . $command->getContentType() .' moreData '. $command->_moreData, __FILE__, __LINE__, PEAR_LOG_DEBUG);
global $registry;
$history = $GLOBALS['egw']->contenthistory;
$state = &$_SESSION['SyncML.state'];
if(isset($state->_moreData['luid'])) {
if(($command->_luid == $state->_moreData['luid'])) {
Horde::logMessage('SyncML: got next moreData chunk '.$command->getContent(), __FILE__, __LINE__, PEAR_LOG_DEBUG);
$lastChunks = implode('',$state->_moreData['chunks']);
$command->_content = $lastChunks.$command->_content;
$stringlen1 = strlen($lastChunks);
$stringlen2 = strlen($command->_content);
if(!$command->_moreData && strlen($command->_content) != $state->_moreData['contentSize']) {
$command->_status = RESPONSE_SIZE_MISMATCH;
$state->_moreData = array();
return;
} elseif(!$command->_moreData && strlen($command->_content) == $state->_moreData['contentSize']) {
$state->_moreData = array();
Horde::logMessage('SyncML: chunk ended successful type is ' . $command->getContentType() .' content is '. $command->getContent(), __FILE__, __LINE__, PEAR_LOG_DEBUG);
}
} else {
// alert 223 needed too
#$command->_status = ALERT_NO_END_OF_DATA;
$state->_moreData = array();
return;
}
}
// don't add/replace the data currently, they are not yet complete
if($command->_moreData == TRUE) {
$state->_moreData['chunks'][] = $command->_content;
$state->_moreData['luid'] = $command->_luid;
// gets only set with the first chunk of data
if(isset($command->_contentSize))
$state->_moreData['contentSize'] = $command->_contentSize;
$command->_status = RESPONSE_CHUNKED_ITEM_ACCEPTED_AND_BUFFERED;
Horde::logMessage('SyncML: added moreData chunk '.$command->getContent(), __FILE__, __LINE__, PEAR_LOG_DEBUG);
return;
}
$hordeType = $type = $this->_targetLocURI;
// remove the './' from the beginning
$hordeType = str_replace('./','',$hordeType);
$syncElementItems = $command->getSyncElementItems();
foreach($syncElementItems as $syncItem) {
if(!$contentType = $syncItem->getContentType()) {
$contentType = $state->getPreferedContentType($type);
}
if ($this->_targetLocURI == 'calendar' && strpos($syncItem->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($syncItem->getContent(), $contentType), $contentType));
# if (!is_a($guid, 'PEAR_Error')) {
# $ts = $history->getTSforAction($guid, 'add');
# $state->setUID($type, $syncItem->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_Replace')) {
#$guid = $state->getGlobalUID($type, $syncItem->getLocURI());
$guid = $registry->call($hordeType . '/search',
array($state->convertClient2Server($syncItem->getContent(), $contentType), $contentType));
$ok = false;
if ($guid) {
#Horde::logMessage('SyncML: locuri'. $syncItem->getLocURI() . ' guid ' . $guid , __FILE__, __LINE__, PEAR_LOG_ERR);
// Entry exists: replace current one.
$ok = $registry->call($hordeType . '/replace',
array($guid, $state->convertClient2Server($syncItem->getContent(), $contentType), $contentType));
if (!is_a($ok, 'PEAR_Error')) {
$ts = $history->getTSforAction($guid, 'modify');
$state->setUID($type, $syncItem->getLocURI(), $guid, $ts);
#Horde::logMessage('SyncML: replaced entry due to client request guid: '. $guid .' LocURI: '. $syncItem->getLocURI() .' 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 .' to '. $hordeType, __FILE__, __LINE__, PEAR_LOG_DEBUG);
$guid = $registry->call($hordeType . '/import',
array($state->convertClient2Server($syncItem->getContent(), $contentType), $contentType));
if (!is_a($guid, 'PEAR_Error')) {
$ts = $history->getTSforAction($guid, 'add');
$state->setUID($type, $syncItem->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 true;
}
function loadData()
{
@ -99,7 +229,7 @@ class Horde_SyncML_Sync_SlowSync extends Horde_SyncML_Sync_TwoWaySync {
$syncType = $this->_targetLocURI;
$hordeType = str_replace('./','',$syncType);
Horde::logMessage("SyncML: reading added items from database for $hordeType", __FILE__, __LINE__, PEAR_LOG_DEBUG);
#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;

View File

@ -45,74 +45,71 @@ class Horde_SyncML_Sync_TwoWaySync extends Horde_SyncML_Sync {
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'];
$counter = 0;
$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(++$counter >= MAX_ENTRIES)
{
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
return $currentCmdID;
}
}
}
Horde::logMessage("SyncML: handling sync ".$currentCmdID, __FILE__, __LINE__, PEAR_LOG_DEBUG);
function handleSync($currentCmdID, $hordeType, $syncType,&$output, $refts) {
global $registry;
// array of Items which got modified, but got never send to the client before
$missedAdds = array();
$history = $GLOBALS['phpgw']->contenthistory;
$state = &$_SESSION['SyncML.state'];
$counter = 0;
$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.
$contentType = $state->getPreferedContentTypeClient($this->_sourceLocURI);
if(is_a($contentType, 'PEAR_Error')) {
// Client did not sent devinfo
$contentType = array('ContentType' => $state->getPreferedContentType($this->_targetLocURI));
}
$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(++$counter >= MAX_ENTRIES) {
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
return $currentCmdID;
}
}
}
Horde::logMessage("SyncML: handling sync (changes done) ".$currentCmdID, __FILE__, __LINE__, PEAR_LOG_DEBUG);
// deletes
while($guid = array_shift($deletes))
@ -148,72 +145,74 @@ class Horde_SyncML_Sync_TwoWaySync extends Horde_SyncML_Sync {
return $currentCmdID;
}
}
Horde::logMessage("SyncML: handling sync ".$currentCmdID, __FILE__, __LINE__, PEAR_LOG_DEBUG);
#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(++$counter >= MAX_ENTRIES)
{
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
return $currentCmdID;
}
}
}
Horde::logMessage("SyncML: handling sync ".$currentCmdID, __FILE__, __LINE__, PEAR_LOG_DEBUG);
$state->clearSync($syncType);
return $currentCmdID;
}
// 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)) {
$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.
$contentType = $state->getPreferedContentTypeClient($this->_sourceLocURI);
if(is_a($contentType, 'PEAR_Error')) {
// Client did not sent devinfo
$contentType = array('ContentType' => $state->getPreferedContentType($this->_targetLocURI));
}
$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.
$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(++$counter >= MAX_ENTRIES) {
$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()
{
@ -224,13 +223,13 @@ class Horde_SyncML_Sync_TwoWaySync extends Horde_SyncML_Sync {
$hordeType = str_replace('./','',$syncType);
$refts = $state->getServerAnchorLast($syncType);
Horde::logMessage("SyncML: reading changed items from database", __FILE__, __LINE__, PEAR_LOG_DEBUG);
#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);
#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);
#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;

View File

@ -19,9 +19,9 @@ $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']['ident'] = 'EGWSYNC';
$conf['log']['params'] = array();
$conf['log']['name'] = '/tmp/horde.log';
$conf['log']['name'] = '/tmp/egroupware_syncml.log';
$conf['log']['params']['append'] = true;
$conf['log']['type'] = 'file';
$conf['log']['enabled'] = true;

View File

@ -91,6 +91,16 @@ $this->applications['egwcontactssync'] = array(
'menu_parent' => 'organizing'
);
$this->applications['egwsifcontactssync'] = array(
'fileroot' => EGW_SERVER_ROOT.'/syncml/sifcontacts',
'webroot' => $this->applications['horde']['webroot'] . '/mnemo',
'icon' => $this->applications['horde']['webroot'] . '/mnemo/graphics/mnemo.gif',
'name' => _("SIF Contacts"),
'status' => 'active',
'provides' => 'sifcontacts',
'menu_parent' => 'organizing'
);
$this->applications['egwcalendarsync'] = array(
'fileroot' => EGW_SERVER_ROOT.'/syncml/calendar',
'webroot' => $this->applications['horde']['webroot'] . '/mnemo',
@ -111,3 +121,13 @@ $this->applications['egwtaskssync'] = array(
'menu_parent' => 'organizing'
);
$this->applications['egwsiftaskssync'] = array(
'fileroot' => EGW_SERVER_ROOT.'/syncml/siftasks',
'webroot' => $this->applications['horde']['webroot'] . '/mnemo',
'icon' => $this->applications['horde']['webroot'] . '/mnemo/graphics/mnemo.gif',
'name' => _("SIFTasks"),
'status' => 'active',
'provides' => 'siftasks',
'menu_parent' => 'organizing'
);