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)) { $xml, $m)) {
$this->_charset = $m[1]; $this->_charset = $m[1];
} }
NLS::setCharset($this->_charset); #NLS::setCharset($this->_charset);
String::setDefaultCharset($this->_charset); #String::setDefaultCharset($this->_charset);
/* Create the XML parser and set method references. */ /* Create the XML parser and set method references. */
$this->_parser = xml_parser_create_ns($this->_charset); $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 // It would seem multisync does not send the user name once it
// has been authorized. Make sure we have a valid session id. // 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(); @session_start();
Horde::logMessage('SyncML: session id = ' . session_id(), __FILE__, __LINE__, PEAR_LOG_DEBUG);
if (!isset($_SESSION['SyncML.state'])) { if (!isset($_SESSION['SyncML.state'])) {
// Create a new state if one does not already exist. // 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); # LK $_SESSION['SyncML.state'] = &new Horde_SyncML_State($sourceURI, $locName, $sessionID);
$_SESSION['SyncML.state'] = &new EGW_SyncML_State($sourceURI, $locName, $sessionID); $_SESSION['SyncML.state'] = &new EGW_SyncML_State($sourceURI, $locName, $sessionID);
} }
if($_SESSION['SyncML.state']->_isAuthorized) #if($_SESSION['SyncML.state']->_isAuthorized)
Horde::logMessage('SyncML: is session authorized', __FILE__, __LINE__, PEAR_LOG_DEBUG); # Horde::logMessage('SyncML['. session_id() .']: is session authorized', __FILE__, __LINE__, PEAR_LOG_DEBUG);
return $_SESSION['SyncML.state']; return $_SESSION['SyncML.state'];
} }
@ -202,11 +208,13 @@ class Horde_SyncML_SyncMLHdr extends Horde_SyncML_ContentHandler {
*/ */
// </SyncHdr></SyncML> // </SyncHdr></SyncML>
// Find the state. // 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 = $this->getStateFromSession($this->_sourceURI, $this->_locName, $this->_sessionID);
$state->setVersion($this->_version); $state->setVersion($this->_version);
$state->setMsgID($this->_msgID); $state->setMsgID($this->_msgID);
$state->setTargetURI($this->_targetURI); $state->setTargetURI($this->_targetURI);
$state->setWBXML(is_a($this->_output, 'XML_WBXML_Encoder'));
if(isset($this->_credData) && isset($this->_locName) && !$state->isAuthorized()) if(isset($this->_credData) && isset($this->_locName) && !$state->isAuthorized())
{ {
$state->setPassword($this->_credData); $state->setPassword($this->_credData);
@ -262,7 +270,7 @@ class Horde_SyncML_SyncMLHdr extends Horde_SyncML_ContentHandler {
} }
$this->_credData = $tmp[1]; $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; break;
@ -344,15 +352,16 @@ class Horde_SyncML_SyncMLHdr extends Horde_SyncML_ContentHandler {
$output->endElement($uri, 'LocURI'); $output->endElement($uri, 'LocURI');
$output->endElement($uri, 'Source'); $output->endElement($uri, 'Source');
#if(!strpos($this->_targetURI,'syncit')) if(session_id() != '') {
#{ $output->startElement($uri, 'RespURI', $attrs);
# $output->startElement($uri, 'RespURI', $attrs); if($_SERVER['HTTPS'] == 'on') {
# $output->characters($this->_targetURI.'?syncid='.$GLOBALS['sessionid'].'-'.$GLOBALS['phpgw_info']['user']['kp3']); $httpPrefix = 'https://';
# $output->characters($this->_targetURI.'?after=20040101T133000Z-syncid=lars'); } else {
# $output->characters($this->_targetURI.'?sincit=10'); $httpPrefix = 'http://';
# $output->characters('http://192.168.4.227/horde/rpc.php?after=20040101T133000Z-username=lars'); }
# $output->endElement($uri, 'RespURI'); $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); $output->startElement($uri, 'Meta', $attrs);
@ -437,6 +446,7 @@ class Horde_SyncML_SyncMLBody extends Horde_SyncML_ContentHandler {
$state = & $_SESSION['SyncML.state']; $state = & $_SESSION['SyncML.state'];
$this->_actionCommands = false; // so far, we have not seen commands that require action from our side $this->_actionCommands = false; // so far, we have not seen commands that require action from our side
$state->_sendFinal = false;
// <SyncML><SyncBody> // <SyncML><SyncBody>
$this->_output->startElement($uri, $element, $attrs); $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 // We've got to do something! This can't be the last
// packet. // packet.
$this->_actionCommands = true; $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) switch($element)
@ -490,7 +500,7 @@ class Horde_SyncML_SyncMLBody extends Horde_SyncML_ContentHandler {
# break; # break;
case 'Sync': case 'Sync':
$state->setSyncStatus(CLIENT_SYNC_STARTED); $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;
} }
break; break;
@ -502,65 +512,92 @@ class Horde_SyncML_SyncMLBody extends Horde_SyncML_ContentHandler {
} }
} }
function endElement($uri, $element) function endElement($uri, $element) {
{ switch ($this->_xmlStack) {
switch ($this->_xmlStack) { case 2:
case 2: // </SyncBody></SyncML>
// </SyncBody></SyncML> $state = & $_SESSION['SyncML.state'];
$state = & $_SESSION['SyncML.state'];
if($state->getSyncStatus() == CLIENT_SYNC_FINNISHED && $state->getAlert222Received() == true) {
// send the sync reply $state->setSyncStatus(CLIENT_SYNC_ACKNOWLEDGED);
// we do still have some data to send OR $state->setAlert222Received(false);
// we should reply to the Sync command }
$sync = &new Horde_SyncML_Command_Sync();
$this->_currentCmdID = $sync->syncToClient($this->_currentCmdID, $this->_output); // send the sync reply
// we do still have some data to send OR
// send the Final tag if possible // we should reply to the Sync command
if($state->getSyncStatus() != SERVER_SYNC_DATA_PENDING && $state->getSyncStatus() != CLIENT_SYNC_STARTED) 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);
$final = &new Horde_SyncML_Command_Final(); $sync = &new Horde_SyncML_Command_Sync();
$this->_currentCmdID = $final->output($this->_currentCmdID, $this->_output); $this->_currentCmdID = $sync->syncToClient($this->_currentCmdID, $this->_output);
} }
$this->_output->endElement($uri, $element); // send the Final tag if possible
#if($state->getSyncStatus() != SERVER_SYNC_DATA_PENDING && $state->getSyncStatus() != CLIENT_SYNC_STARTED) {
Horde::logMessage('SyncML: syncStatus ' . $state->getSyncStatus() .'actionCommands: '.$this->_actionCommands, __FILE__, __LINE__, PEAR_LOG_INFO); if($state->getSyncStatus() >= SERVER_SYNC_FINNISHED || $state->_sendFinal) {
if (!$this->_actionCommands && $state->getSyncStatus() == SERVER_SYNC_FINNISHED) { $final = &new Horde_SyncML_Command_Final();
// this packet did not contain any real actions, just status and map. $this->_currentCmdID = $final->output($this->_currentCmdID, $this->_output);
// This means, we're through! The session can be closed and }
// the Anchors saved for the next Sync
$state = & $_SESSION['SyncML.state']; $this->_output->endElement($uri, $element);
Horde::logMessage('SyncML: sync' . session_id() . ' completed successfully!', __FILE__, __LINE__, PEAR_LOG_INFO);
$state->writeSyncSummary(); Horde::logMessage('SyncML['. session_id() .']: syncStatus ' . $state->getSyncStatus() .'actionCommands: '.$this->_actionCommands, __FILE__, __LINE__, PEAR_LOG_DEBUG);
$log = $state->getLog();
$s=""; if (!$this->_actionCommands && $state->getSyncStatus() == SERVER_SYNC_FINNISHED) {
foreach($log as $k => $v) { // this packet did not contain any real actions, just status and map.
$s .= " $k=$v"; // This means, we're through! The session can be closed and
} // the Anchors saved for the next Sync
Horde::logMessage('SyncML: summary:' . $s, __FILE__, __LINE__, PEAR_LOG_INFO); $state = & $_SESSION['SyncML.state'];
// session can be closed here! Horde::logMessage('SyncML['. session_id() .']: sync' . session_id() . ' completed successfully!', __FILE__, __LINE__, PEAR_LOG_INFO);
#session_unset(); $state->writeSyncSummary();
#session_destroy(); $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['. session_id() .']: destroying sync session '.session_id(), __FILE__, __LINE__, PEAR_LOG_INFO);
Horde::logMessage('SyncML: destroying sync session '.session_id(), __FILE__, __LINE__, PEAR_LOG_INFO); // session can be closed here!
// session can be closed here! session_unset();
session_unset(); session_destroy();
session_destroy(); }
} if($state->getSyncStatus() == CLIENT_SYNC_FINNISHED) {
break; $state->setSyncStatus(CLIENT_SYNC_ACKNOWLEDGED);
Horde::logMessage('SyncML['. session_id() .']: syncStatus(client sync acknowledged) '.$state->getSyncStatus(), __FILE__, __LINE__, PEAR_LOG_DEBUG);
case 3: }
// </[Command]></SyncBody></SyncML>
$state = & $_SESSION['SyncML.state']; break;
// this should be moved to case 2: case 3:
if($element == 'Final') // </[Command]></SyncBody></SyncML>
{ $state = & $_SESSION['SyncML.state'];
// make sure that we request devinfo, if we not have them already
// 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(); $attrs = array();
$this->_output->startElement($state->getURI(), 'Get', $attrs); $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(), 'Item');
$this->_output->endElement($state->getURI(), 'Get'); $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) default:
{ // </...></[Command]></SyncBody></SyncML>
case 'Final': $this->_currentCommand->endElement($uri, $element);
if($state->getSyncStatus() == CLIENT_SYNC_STARTED) break;
{ }
$state->setSyncStatus(CLIENT_SYNC_FINNISHED);
Horde::logMessage('SyncML: syncStatus(client sync finnished) ' . $state->getSyncStatus(), __FILE__, __LINE__, PEAR_LOG_INFO); parent::endElement($uri, $element);
} }
$this->_clientSentFinal = true;
Horde::logMessage('SyncML: Sync _syncTag = '. $state->getSyncStatus(), __FILE__, __LINE__, PEAR_LOG_INFO); function characters($str) {
break; if (isset($this->_currentCommand)) {
default: $this->_currentCommand->characters($str);
$this->_currentCmdID = $this->_currentCommand->output($this->_currentCmdID, $this->_output); }
break; }
}
unset($this->_currentCommand);
break;
default:
// </...></[Command]></SyncBody></SyncML>
$this->_currentCommand->endElement($uri, $element);
break;
}
parent::endElement($uri, $element);
}
function characters($str)
{
if (isset($this->_currentCommand)) {
$this->_currentCommand->characters($str);
}
}
} }

View File

@ -196,11 +196,29 @@ class Horde_SyncML_Command_Alert extends Horde_SyncML_Command {
$output->endElement($state->getURI(), 'Item'); $output->endElement($state->getURI(), 'Item');
$output->endElement($state->getURI(), 'Alert'); $output->endElement($state->getURI(), 'Alert');
$state->_sendFinal = true;
$currentCmdID++; $currentCmdID++;
} }
} } elseif ($this->_alert == ALERT_NEXT_MESSAGE) {
else $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 = &new Horde_SyncML_Command_Status(RESPONSE_OK, 'Alert');
$status->setCmdRef($this->_cmdID); $status->setCmdRef($this->_cmdID);
if ($this->_sourceLocURI != null) { if ($this->_sourceLocURI != null) {

View File

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

View File

@ -22,46 +22,48 @@ include_once 'Horde/SyncML/Sync/OneWayFromServerSync.php';
*/ */
class Horde_SyncML_Command_Sync extends Horde_Syncml_Command { class Horde_SyncML_Command_Sync extends Horde_Syncml_Command {
var $_isInSource; var $_isInSource;
var $_currentSyncElement; var $_currentSyncElement;
var $_syncElements = array(); 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) return $currentCmdID;
{ }
$state = &$_SESSION['SyncML.state'];
function getTargetURI() {
$attrs = array(); return $this->_targetURI;
}
Horde::logMessage('SyncML: $this->_targetURI = ' . $this->_targetURI, __FILE__, __LINE__, PEAR_LOG_DEBUG);
$status = &new Horde_SyncML_Command_Status(RESPONSE_OK, 'Sync');
// $status->setState($state);
$status->setCmdRef($this->_cmdID);
if ($this->_targetURI != null) {
$status->setTargetRef((isset($this->_targetURIParameters) ? $this->_targetURI.'?/'.$this->_targetURIParameters : $this->_targetURI));
}
if ($this->_sourceURI != null) {
$status->setSourceRef($this->_sourceURI);
}
$currentCmdID = $status->output($currentCmdID, $output);
$sync = $state->getSync($this->_targetURI);
$currentCmdID = $sync->startSync($currentCmdID, $output);
foreach ($this->_syncElements as $element ) {
$currentCmdID = $sync->nextSyncCommand($currentCmdID, $element, $output);
}
return $currentCmdID;
}
function getTargetURI()
{
return $this->_targetURI;
}
function startElement($uri, $element, $attrs) 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); Horde::logMessage('SyncML: starting sync to client', __FILE__, __LINE__, PEAR_LOG_DEBUG);
$state = $_SESSION['SyncML.state']; $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(); $deviceInfo = $state->getClientDeviceInfo();
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING); $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)) { || isset($this->_locURI) || isset($this->targetURI)) {
$output->startElement($state->getURI(), 'Item', $attrs); $output->startElement($state->getURI(), 'Item', $attrs);
// send only when sending adds // 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(), 'Source', $attrs);
$output->startElement($state->getURI(), 'LocURI', $attrs); $output->startElement($state->getURI(), 'LocURI', $attrs);
$chars = substr($this->_locURI,0,39); $chars = substr($this->_locURI,0,39);

View File

@ -16,17 +16,18 @@ include_once 'Horde/SyncML/Command/Sync/SyncElement.php';
* @package Horde_SyncML * @package Horde_SyncML
*/ */
class Horde_SyncML_Command_Sync_Replace extends Horde_SyncML_Command_Sync_SyncElement { class Horde_SyncML_Command_Sync_Replace extends Horde_SyncML_Command_Sync_SyncElement {
function output($currentCmdID, &$output) {
function output($currentCmdID, &$output) $status = &new Horde_SyncML_Command_Status($this->_status, 'Replace');
{ $status->setCmdRef($this->_cmdID);
$status = &new Horde_SyncML_Command_Status($this->_status, 'Replace');
$status->setCmdRef($this->_cmdID); if (isset($this->_luid)) {
$status->setSourceRef($this->_luid);
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);
} 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 $ * $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 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 * See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. * 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 { class Horde_SyncML_Command_Sync_SyncElement extends Horde_SyncML_Command {
var $_luid; var $_luid;
var $_guid; var $_guid;
var $_isSource; var $_isSource;
var $_content; var $_content;
var $_contentType; var $_contentType;
var $_status = RESPONSE_OK; 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) function startElement($uri, $element, $attrs) {
{ parent::startElement($uri, $element, $attrs);
@include_once 'Horde/SyncML/Command/Sync/' . $command . '.php';
$class = 'Horde_SyncML_Command_Sync_' . $command; switch ($this->_xmlStack) {
if (class_exists($class)) { case 3:
#Horde::logMessage('SyncML: Class definition of ' . $class . ' found in SyncElement::factory.', __FILE__, __LINE__, PEAR_LOG_DEBUG); if ($element == 'Source') {
return $element = &new $class($params); $this->_isSource = true;
} else { }
Horde::logMessage('SyncML: Class definition of ' . $class . ' not found in SyncElement::factory.', __FILE__, __LINE__, PEAR_LOG_DEBUG); break;
require_once 'PEAR.php'; }
return PEAR::raiseError('Class definition of ' . $class . ' not found.'); }
}
} 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) if($this->_luid) {
{ $item->setLocURI($this->_luid);
parent::startElement($uri, $element, $attrs); $item->setContent($this->_content);
$item->setContentType($this->_contentType);
switch ($this->_xmlStack) {
case 3: if($this->_contentSize)
if ($element == 'Source') { $item->setContentType($this->_contentSize);
$this->_isSource = true; if($this->_moreData)
} $item->setMoreData($this->_moreData);
break;
} $this->_items[$this->_luid] = $item;
} }
function endElement($uri, $element) unset($this->_content);
{ unset($this->_contentSize);
$search = array('/ *\n/','/ *$/m'); unset($this->_luid);
$replace = array('',''); }
switch ($this->_xmlStack) { break;
case 1: case 3:
// Need to add sync elements to the Sync method? if ($element == 'Source') {
break; $this->_isSource = false;
} elseif ($element == 'Data') {
case 3: $this->_content = $this->_chars;
if ($element == 'Source') { } elseif ($element == 'MoreData') {
$this->_isSource = false; $this->_moreData = TRUE;
} elseif ($element == 'Data') { } elseif ($element == 'Type') {
$this->_content = $this->_chars; if(empty($this->_contentType))
} elseif ($element == 'MoreData') { $this->_contentType = trim($this->_chars);
$this->_moreData = TRUE; }
} elseif ($element == 'Type') { break;
if(!isset($this->_contentType))
$this->_contentType = trim($this->_chars); case 4:
} if ($element == 'LocURI' && $this->_isSource) {
break; $this->_luid = trim($this->_chars);
} elseif ($element == 'Type') {
case 4: $this->_contentType = trim($this->_chars);
if ($element == 'LocURI' && $this->_isSource) { } elseif ($element == 'Size') {
$this->_luid = trim($this->_chars); $this->_contentSize = trim($this->_chars);
} elseif ($element == 'Type') { }
$this->_contentType = trim($this->_chars); break;
} elseif ($element == 'Size') { }
$this->_contentSize = trim($this->_chars);
} parent::endElement($uri, $element);
break; }
}
function getSyncElementItems() {
parent::endElement($uri, $element); return (array)$this->_items;
} }
function getLocURI() 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_STARTED', 1);
define('CLIENT_SYNC_FINNISHED', 2); define('CLIENT_SYNC_FINNISHED', 2);
define('SERVER_SYNC_DATA_PENDING', 3); define('CLIENT_SYNC_ACKNOWLEDGED', 3);
define('SERVER_SYNC_FINNISHED', 4); define('SERVER_SYNC_DATA_PENDING', 4);
define('SERVER_SYNC_FINNISHED', 5);
define('SERVER_SYNC_ACKNOWLEDGED', 6);
define('MAX_DATA', 19); define('MAX_DATA', 19);
define('MAX_ENTRIES', 10); define('MAX_ENTRIES', 10);
@ -148,52 +150,55 @@ define('MAX_ENTRIES', 10);
* @package Horde_SyncML * @package Horde_SyncML
*/ */
class Horde_SyncML_State { class Horde_SyncML_State {
var $_sessionID; var $_sessionID;
var $_verProto; var $_verProto;
var $_msgID; var $_msgID;
var $_targetURI; var $_targetURI;
var $_sourceURI; var $_sourceURI;
var $_version; var $_version;
var $_locName; var $_locName;
var $_password; var $_password;
var $_isAuthorized; var $_isAuthorized;
var $_uri; var $_uri;
var $_uriMeta; var $_uriMeta;
var $_syncs = array(); var $_syncs = array();
var $_clientAnchorNext = array(); // written to db after successful sync var $_clientAnchorNext = array(); // written to db after successful sync
var $_serverAnchorLast = array(); var $_serverAnchorLast = array();
var $_serverAnchorNext = array(); // written to db after successful sync var $_serverAnchorNext = array(); // written to db after successful sync
var $_clientDeviceInfo = array(); var $_clientDeviceInfo = array();
// array list of changed items, which need to be synced to the client // array list of changed items, which need to be synced to the client
var $_changedItems; var $_changedItems;
// array list of deleted items, which need to be synced to the client // array list of deleted items, which need to be synced to the client
var $_deletedItems; var $_deletedItems;
// array list of added items, which need to be synced to the client // array list of added items, which need to be synced to the client
var $_addedItems; var $_addedItems;
// bool flag that we need to more data // bool flag that we need to more data
var $_syncStatus; var $_syncStatus;
var $_log = array(); var $_log = array();
// stores if we received Alert 222 already
var $_receivedAlert222 = false;
/** /**
* Creates a new instance of Horde_SyncML_State. * 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 * by a <SyncML xmlns="syncml:SYNCML1.1"> element. They require
* just <SyncML>. So don't use an ns for non wbxml devices. * just <SyncML>. So don't use an ns for non wbxml devices.
*/ */
# if ($this->isWBXML()) { if ($this->isWBXML()) {
return $this->_uri; return $this->_uri;
# } else { } else {
# return ''; return '';
# } }
} }
function getURIMeta() function getURIMeta()
{ {
@ -625,15 +630,42 @@ class Horde_SyncML_State {
*/ */
function getPreferedContentType($type) function getPreferedContentType($type)
{ {
if ($type == 'contacts') { # if ($type == 'contacts') {
return 'text/x-vcard'; # return 'text/x-vcard';
} elseif ($type == 'notes') { # } elseif ($type == 'notes') {
return 'text/x-vnote'; # return 'text/x-vnote';
} elseif ($type == 'tasks') { # } elseif ($type == 'tasks') {
return 'text/x-vcalendar'; # return 'text/x-vcalendar';
} elseif ($type == 'calendar') { # } elseif ($type == 'calendar') {
return 'text/x-vcalendar'; # 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; 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, '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__); $db->select('egw_contentmap', $cols, $where, __LINE__, __FILE__);
if($db->next_record()) 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')); 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; $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); $db = clone($GLOBALS['egw']->db);
@ -145,11 +145,12 @@ class EGW_SyncML_State extends Horde_SyncML_State
'map_id' => $mapID, 'map_id' => $mapID,
'map_guid' => $guid 'map_guid' => $guid
); );
Horde::logMessage('SyncML: search LocID for ' . $mapID .' / '.$guid, __FILE__, __LINE__, PEAR_LOG_DEBUG);
$db->select('egw_contentmap', $cols, $where, __LINE__, __FILE__); $db->select('egw_contentmap', $cols, $where, __LINE__, __FILE__);
if($db->next_record()) if($db->next_record())
{ {
Horde::logMessage('SyncML: found LocID: '.$db->f('map_locuid'), __FILE__, __LINE__, PEAR_LOG_DEBUG);
return $db->f('map_locuid'); 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__); $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()) 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 $retData = array
( (
'ClientAnchor' => $db->f('sync_clientts'), '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']; $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')) if($GLOBALS['sessionid'] = $GLOBALS['egw']->session->create($this->_locName,$this->_password,'text','u'))
{ {
$this->_isAuthorized = true; $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 else
{ {
@ -264,7 +265,7 @@ class EGW_SyncML_State extends Horde_SyncML_State
$guid = $db->f('map_guid'); $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__); $db->delete('egw_contentmap', $where, __LINE__, __FILE__);
@ -295,7 +296,7 @@ class EGW_SyncML_State extends Horde_SyncML_State
$ts = time(); $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); $db = clone($GLOBALS['egw']->db);
@ -312,9 +313,10 @@ class EGW_SyncML_State extends Horde_SyncML_State
'map_expired' => 0, 'map_expired' => 0,
); );
$db->delete('egw_contentmap', $where, __LINE__, __FILE__);
$db->insert('egw_contentmap', $data, $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; return $currentCmdID;
} }
/** /**
* Here's where the actual processing of a client-sent Sync * Here's where the actual processing of a client-sent Sync
* Command takes place. Entries are added, deleted or replaced * Command takes place. Entries are added, deleted or replaced
* from the server database by using Horde API (Registry) calls. * from the server database by using Horde API (Registry) calls.
*/ */
function runSyncCommand(&$command) function runSyncCommand(&$command) {
{ #Horde::logMessage('SyncML: content type is ' . $command->getContentType() .' moreData '. $command->_moreData, __FILE__, __LINE__, PEAR_LOG_DEBUG);
Horde::logMessage('SyncML: content type is ' . $command->getContentType() .' moreData '. $command->_moreData, __FILE__, __LINE__, PEAR_LOG_DEBUG); global $registry;
global $registry;
$history = $GLOBALS['egw']->contenthistory;
#require_once 'Horde/History.php';
#$history = &Horde_History::singleton(); $state = &$_SESSION['SyncML.state'];
$history = $GLOBALS['phpgw']->contenthistory;
if(isset($state->_moreData['luid'])) {
$state = &$_SESSION['SyncML.state']; if(($command->_luid == $state->_moreData['luid'])) {
Horde::logMessage('SyncML: got next moreData chunk '.$command->getContent(), __FILE__, __LINE__, PEAR_LOG_DEBUG);
if(isset($state->_moreData['luid'])) $lastChunks = implode('',$state->_moreData['chunks']);
{ $command->_content = $lastChunks.$command->_content;
if(($command->_luid == $state->_moreData['luid'])) $stringlen1 = strlen($lastChunks);
{ $stringlen2 = strlen($command->_content);
$lastChunks = implode('',$state->_moreData['chunks']);
$command->_content = $lastChunks.$command->_content; if(!$command->_moreData && strlen($command->_content) != $state->_moreData['contentSize']) {
$stringlen1 = strlen($lastChunks); $command->_status = RESPONSE_SIZE_MISMATCH;
$stringlen2 = strlen($command->_content); $state->_moreData = array();
if(!$command->_moreData && return;
strlen($command->_content) } elseif(!$command->_moreData && strlen($command->_content) == $state->_moreData['contentSize']) {
!= $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);
{ }
$command->_status = RESPONSE_SIZE_MISMATCH; } else {
$state->_moreData = array(); // alert 223 needed too
#$command->_status = ALERT_NO_END_OF_DATA;
return;
} $state->_moreData = array();
elseif(!$command->_moreData &&
strlen($command->_content) return;
== $state->_moreData['contentSize'] }
) }
{
$state->_moreData = array(); // don't add/replace the data currently, they are not yet complete
if($command->_moreData == TRUE) {
return; $state->_moreData['chunks'][] = $command->_content;
} $state->_moreData['luid'] = $command->_luid;
} // gets only set with the first chunk of data
else if(isset($command->_contentSize))
{ $state->_moreData['contentSize'] = $command->_contentSize;
// alert 223 needed too
#$command->_status = ALERT_NO_END_OF_DATA; $command->_status = RESPONSE_CHUNKED_ITEM_ACCEPTED_AND_BUFFERED;
Horde::logMessage('SyncML: added moreData chunk '.$command->getContent(), __FILE__, __LINE__, PEAR_LOG_DEBUG);
$state->_moreData = array();
return;
return; }
}
} $hordeType = $type = $this->_targetLocURI;
// remove the './' from the beginning
// don't add/replace the data currently, they are not yet complete $hordeType = str_replace('./','',$hordeType);
if($command->_moreData == TRUE) if(!$contentType = $command->getContentType()) {
{ $contentType = $state->getPreferedContentType($type);
$state->_moreData['chunks'][] = $command->_content; }
$state->_moreData['luid'] = $command->_luid;
if ($this->_targetLocURI == 'calendar' && strpos($command->getContent(), 'BEGIN:VTODO') !== false) {
// gets only set with the first chunk of data $hordeType = 'tasks';
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;
}
$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); # $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); $serverAnchorNext = $state->getServerAnchorNext($syncType);
$counter = 0; $counter = 0;
while($guid = array_shift($adds)) while($guid = array_shift($adds))
{ {
#$guid_ts = max($history->getTSforAction($guid, 'add'),$history->getTSforAction($guid, 'modify')); #$guid_ts = max($history->getTSforAction($guid, 'add'),$history->getTSforAction($guid, 'modify'));
$sync_ts = $state->getChangeTS($syncType, $guid); $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); #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 it got synced from client to server someone
// $sync_ts >= $serverAnchorNext it got synced from client to server in this sync package already // $sync_ts >= $serverAnchorNext it got synced from client to server in this sync package already
if ($sync_ts && $sync_ts >= $serverAnchorNext) { if ($sync_ts && $sync_ts >= $serverAnchorNext) {
// Change was done by us upon request of client. // Change was done by us upon request of client.
// Don't mirror that back to the client. // Don't mirror that back to the client.
//Horde::logMessage("SyncML: slowsync add: $guid ignored, came from client", __FILE__, __LINE__, PEAR_LOG_DEBUG); //Horde::logMessage("SyncML: slowsync add: $guid ignored, came from client", __FILE__, __LINE__, PEAR_LOG_DEBUG);
continue; 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); # LK $contentType = $state->getPreferedContentTypeClient($syncType);
$contentType = $state->getPreferedContentTypeClient($this->_sourceLocURI);
$cmd = &new Horde_SyncML_Command_Sync_ContentSyncElement(); $contentType = $state->getPreferedContentTypeClient($this->_sourceLocURI);
$c = $registry->call($hordeType . '/export', if(is_a($contentType, 'PEAR_Error')) {
array('guid' => $guid, // Client did not sent devinfo
'contentType' => $contentType)); $contentType = array('ContentType' => $state->getPreferedContentType($this->_targetLocURI));
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 $cmd = &new Horde_SyncML_Command_Sync_ContentSyncElement();
if(++$counter >= MAX_ENTRIES) $c = $registry->call($hordeType . '/export', array('guid' => $guid, 'contentType' => $contentType));
{ #Horde::logMessage("SyncML: slowsync add to server $c", __FILE__, __LINE__, PEAR_LOG_DEBUG);
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING); if (!is_a($c, 'PEAR_Error')) {
return $currentCmdID; // Item in history but not in database. Strange, but
} // can happen.
} #LK $cmd->setContent($state->convertServer2Client($c, $contentType));
} $cmd->setContent($c);
Horde::logMessage("SyncML: handling sync ".$currentCmdID, __FILE__, __LINE__, PEAR_LOG_DEBUG); $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); $state->clearSync($syncType);
return $currentCmdID; 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() function loadData()
{ {
@ -99,7 +229,7 @@ class Horde_SyncML_Sync_SlowSync extends Horde_SyncML_Sync_TwoWaySync {
$syncType = $this->_targetLocURI; $syncType = $this->_targetLocURI;
$hordeType = str_replace('./','',$syncType); $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())); $state->setAddedItems($hordeType, $registry->call($hordeType. '/list', array()));
$adds = &$state->getAddedItems($hordeType); $adds = &$state->getAddedItems($hordeType);
$this->_syncDataLoaded = TRUE; $this->_syncDataLoaded = TRUE;

View File

@ -45,74 +45,71 @@ class Horde_SyncML_Sync_TwoWaySync extends Horde_SyncML_Sync {
return $currentCmdID; return $currentCmdID;
} }
function handleSync($currentCmdID, $hordeType, $syncType,&$output, $refts) function handleSync($currentCmdID, $hordeType, $syncType,&$output, $refts) {
{ global $registry;
global $registry;
// array of Items which got modified, but got never send to the client before
// array of Items which got modified, but got never send to the client before $missedAdds = array();
$missedAdds = array();
$history = $GLOBALS['phpgw']->contenthistory;
#require_once 'Horde/History.php'; $state = &$_SESSION['SyncML.state'];
#$history = &Horde_History::singleton(); $counter = 0;
$history = $GLOBALS['phpgw']->contenthistory;
$state = &$_SESSION['SyncML.state']; $changes = &$state->getChangedItems($hordeType);
$counter = 0; $deletes = &$state->getDeletedItems($hordeType);
$adds = &$state->getAddedItems($hordeType);
$changes = &$state->getChangedItems($hordeType);
$deletes = &$state->getDeletedItems($hordeType); Horde::logMessage("SyncML: ".count($changes).' changed items found for '.$hordeType, __FILE__, __LINE__, PEAR_LOG_DEBUG);
$adds = &$state->getAddedItems($hordeType); 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);
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); while($guid = array_shift($changes)) {
Horde::logMessage("SyncML: ".count($adds). ' added items found for '.$hordeType , __FILE__, __LINE__, PEAR_LOG_DEBUG); $guid_ts = $history->getTSforAction($guid, 'modify');
$sync_ts = $state->getChangeTS($syncType, $guid);
while($guid = array_shift($changes)) 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) {
$guid_ts = $history->getTSforAction($guid, 'modify'); // Change was done by us upon request of client.
$sync_ts = $state->getChangeTS($syncType, $guid); // Don't mirror that back to the client.
Horde::logMessage("SyncML: timestamp modify guid_ts: $guid_ts sync_ts: $sync_ts", __FILE__, __LINE__, PEAR_LOG_DEBUG); Horde::logMessage("SyncML: change: $guid ignored, came from client", __FILE__, __LINE__, PEAR_LOG_DEBUG);
if ($sync_ts && $sync_ts == $guid_ts) { continue;
// Change was done by us upon request of client. }
// Don't mirror that back to the client. Horde::logMessage("SyncML: change $guid hs_ts:$guid_ts dt_ts:" . $state->getChangeTS($syncType, $guid), __FILE__, __LINE__, PEAR_LOG_DEBUG);
Horde::logMessage("SyncML: change: $guid ignored, came from client", __FILE__, __LINE__, PEAR_LOG_DEBUG); $locid = $state->getLocID($syncType, $guid);
continue; if (!$locid) {
} // somehow we missed to add, lets store the uid, so we add this entry later
Horde::logMessage("SyncML: change $guid hs_ts:$guid_ts dt_ts:" . $state->getChangeTS($syncType, $guid), __FILE__, __LINE__, PEAR_LOG_DEBUG); $missedAdds[] = $guid;
$locid = $state->getLocID($syncType, $guid); Horde::logMessage("SyncML: unable to create change for $guid: locid not found in map", __FILE__, __LINE__, PEAR_LOG_WARNING);
if (!$locid) { continue;
// 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); // Create a replace request for client.
continue; $contentType = $state->getPreferedContentTypeClient($this->_sourceLocURI);
} if(is_a($contentType, 'PEAR_Error')) {
// Client did not sent devinfo
// Create a replace request for client. $contentType = array('ContentType' => $state->getPreferedContentType($this->_targetLocURI));
# LK $contentType = $state->getPreferedContentTypeClient($syncType); }
$contentType = $state->getPreferedContentTypeClient($this->_sourceLocURI); $c = $registry->call($hordeType. '/export',
$c = $registry->call($hordeType. '/export', array('guid' => $guid, 'contentType' => $contentType));
array('guid' => $guid, 'contentType' => $contentType)); if (!is_a($c, 'PEAR_Error')) {
if (!is_a($c, 'PEAR_Error')) { // Item in history but not in database. Strange, but can happen.
// Item in history but not in database. Strange, but Horde::logMessage("SyncML: change: $guid export content: $c", __FILE__, __LINE__, PEAR_LOG_DEBUG);
// can happen. $cmd = &new Horde_SyncML_Command_Sync_ContentSyncElement();
Horde::logMessage("SyncML: change: $guid export content: $c", __FILE__, __LINE__, PEAR_LOG_DEBUG); # LK $cmd->setContent($state->convertServer2Client($c, $contentType));
$cmd = &new Horde_SyncML_Command_Sync_ContentSyncElement(); $cmd->setContent($c);
# LK $cmd->setContent($state->convertServer2Client($c, $contentType)); $cmd->setSourceURI($guid);
$cmd->setContent($c); $cmd->setTargetURI($locid);
$cmd->setSourceURI($guid); $cmd->setContentType($contentType['ContentType']);
$cmd->setTargetURI($locid); $currentCmdID = $cmd->outputCommand($currentCmdID, $output, 'Replace');
$cmd->setContentType($contentType['ContentType']); $state->log('Server-Replace');
$currentCmdID = $cmd->outputCommand($currentCmdID, $output, 'Replace');
$state->log('Server-Replace'); // return if we have to much data
if(++$counter >= MAX_ENTRIES) {
// return if we have to much data $state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
if(++$counter >= MAX_ENTRIES) return $currentCmdID;
{ }
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING); }
return $currentCmdID; }
} Horde::logMessage("SyncML: handling sync (changes done) ".$currentCmdID, __FILE__, __LINE__, PEAR_LOG_DEBUG);
}
}
Horde::logMessage("SyncML: handling sync ".$currentCmdID, __FILE__, __LINE__, PEAR_LOG_DEBUG);
// deletes // deletes
while($guid = array_shift($deletes)) while($guid = array_shift($deletes))
@ -148,72 +145,74 @@ class Horde_SyncML_Sync_TwoWaySync extends Horde_SyncML_Sync {
return $currentCmdID; 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. // Get adds.
if(count($missedAdds) > 0) if(count($missedAdds) > 0) {
{ Horde::logMessage("SyncML: add missed changes as adds ".count($adds).' / '.$missedAdds[0], __FILE__, __LINE__, PEAR_LOG_DEBUG);
Horde::logMessage("SyncML: add missed changes as adds ".count($adds).' / '.$missedAdds[0], __FILE__, __LINE__, PEAR_LOG_DEBUG); $state->setAddedItems($hordeType, array_merge($adds, $missedAdds));
$state->setAddedItems($hordeType, array_merge($adds, $missedAdds)); $adds = &$state->getAddedItems($hordeType);
$adds = &$state->getAddedItems($hordeType); Horde::logMessage("SyncML: merged adds counter ".count($adds).' / '.$adds[0], __FILE__, __LINE__, PEAR_LOG_DEBUG);
Horde::logMessage("SyncML: merged adds counter ".count($adds).' / '.$adds[0], __FILE__, __LINE__, PEAR_LOG_DEBUG); }
}
while($guid = array_shift($adds)) while($guid = array_shift($adds)) {
{ $guid_ts = $history->getTSforAction($guid, 'add');
#if($tempCounter > 10) continue; $sync_ts = $state->getChangeTS($syncType, $guid);
$guid_ts = $history->getTSforAction($guid, 'add'); Horde::logMessage("SyncML: timestamp add $guid guid_ts: $guid_ts sync_ts: $sync_ts", __FILE__, __LINE__, PEAR_LOG_DEBUG);
$sync_ts = $state->getChangeTS($syncType, $guid); if ($sync_ts && $sync_ts == $guid_ts) {
Horde::logMessage("SyncML: timestamp add $guid guid_ts: $guid_ts sync_ts: $sync_ts", __FILE__, __LINE__, PEAR_LOG_DEBUG); // Change was done by us upon request of client.
if ($sync_ts && $sync_ts == $guid_ts) { // Don't mirror that back to the client.
// Change was done by us upon request of client. Horde::logMessage("SyncML: add: $guid ignored, came from client", __FILE__, __LINE__, PEAR_LOG_DEBUG);
// Don't mirror that back to the client. continue;
Horde::logMessage("SyncML: add: $guid ignored, came from client", __FILE__, __LINE__, PEAR_LOG_DEBUG); }
continue;
} $locid = $state->getLocID($syncType, $guid);
$locid = $state->getLocID($syncType, $guid); if ($locid && $refts == 0) {
// For slow sync (ts=0): do not add data for which we
if ($locid && $refts == 0) { // have a locid again. This is a heuristic to avoid
// For slow sync (ts=0): do not add data for which we // duplication of entries.
// have a locid again. This is a heuristic to avoid Horde::logMessage("SyncML: skipping add of guid $guid as there already is a locid $locid", __FILE__, __LINE__, PEAR_LOG_DEBUG);
// duplication of entries. continue;
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);
}
Horde::logMessage("SyncML: add: $guid", __FILE__, __LINE__, PEAR_LOG_DEBUG); // Create an Add request for client.
$contentType = $state->getPreferedContentTypeClient($this->_sourceLocURI);
// Create an Add request for client. if(is_a($contentType, 'PEAR_Error')) {
# LK $contentType = $state->getPreferedContentTypeClient($syncType); // Client did not sent devinfo
$contentType = $state->getPreferedContentTypeClient($this->_sourceLocURI); $contentType = array('ContentType' => $state->getPreferedContentType($this->_targetLocURI));
}
$cmd = &new Horde_SyncML_Command_Sync_ContentSyncElement();
$c = $registry->call($hordeType . '/export', $cmd = &new Horde_SyncML_Command_Sync_ContentSyncElement();
array('guid' => $guid, $c = $registry->call($hordeType . '/export',
'contentType' => $contentType)); array(
if (!is_a($c, 'PEAR_Error')) { 'guid' => $guid ,
// Item in history but not in database. Strange, but 'contentType' => $contentType ,
// can happen. )
#LK $cmd->setContent($state->convertServer2Client($c, $contentType)); );
$cmd->setContent($c);
$cmd->setContentType($contentType['ContentType']); if (!is_a($c, 'PEAR_Error')) {
$cmd->setSourceURI($guid); // Item in history but not in database. Strange, but can happen.
$currentCmdID = $cmd->outputCommand($currentCmdID, $output, 'Add'); $cmd->setContent($c);
$state->log('Server-Add'); $cmd->setContentType($contentType['ContentType']);
$cmd->setSourceURI($guid);
// return if we have to much data $currentCmdID = $cmd->outputCommand($currentCmdID, $output, 'Add');
if(++$counter >= MAX_ENTRIES) $state->log('Server-Add');
{
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING); // return if we have to much data
return $currentCmdID; 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); Horde::logMessage("SyncML: handling sync ".$currentCmdID, __FILE__, __LINE__, PEAR_LOG_DEBUG);
return $currentCmdID; $state->clearSync($syncType);
}
return $currentCmdID;
}
function loadData() function loadData()
{ {
@ -224,13 +223,13 @@ class Horde_SyncML_Sync_TwoWaySync extends Horde_SyncML_Sync {
$hordeType = str_replace('./','',$syncType); $hordeType = str_replace('./','',$syncType);
$refts = $state->getServerAnchorLast($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))); $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))); $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))); $state->setAddedItems($hordeType, $registry->call($hordeType. '/listBy', array('action' => 'add', 'timestamp' => $refts)));
$this->_syncDataLoaded = TRUE; $this->_syncDataLoaded = TRUE;

View File

@ -19,9 +19,9 @@ $conf['auth']['params']['username'] = 'Administrator';
$conf['auth']['params']['requestuser'] = false; $conf['auth']['params']['requestuser'] = false;
$conf['auth']['driver'] = 'auto'; $conf['auth']['driver'] = 'auto';
$conf['log']['priority'] = PEAR_LOG_DEBUG; $conf['log']['priority'] = PEAR_LOG_DEBUG;
$conf['log']['ident'] = 'HORDE'; $conf['log']['ident'] = 'EGWSYNC';
$conf['log']['params'] = array(); $conf['log']['params'] = array();
$conf['log']['name'] = '/tmp/horde.log'; $conf['log']['name'] = '/tmp/egroupware_syncml.log';
$conf['log']['params']['append'] = true; $conf['log']['params']['append'] = true;
$conf['log']['type'] = 'file'; $conf['log']['type'] = 'file';
$conf['log']['enabled'] = true; $conf['log']['enabled'] = true;

View File

@ -91,6 +91,16 @@ $this->applications['egwcontactssync'] = array(
'menu_parent' => 'organizing' '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( $this->applications['egwcalendarsync'] = array(
'fileroot' => EGW_SERVER_ROOT.'/syncml/calendar', 'fileroot' => EGW_SERVER_ROOT.'/syncml/calendar',
'webroot' => $this->applications['horde']['webroot'] . '/mnemo', 'webroot' => $this->applications['horde']['webroot'] . '/mnemo',
@ -111,3 +121,13 @@ $this->applications['egwtaskssync'] = array(
'menu_parent' => 'organizing' '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'
);