2005-06-19 21:00:58 +02:00
|
|
|
<?php
|
|
|
|
/**
|
2009-07-15 21:31:25 +02:00
|
|
|
* eGroupWare - SyncML based on Horde 3
|
2005-06-19 21:00:58 +02:00
|
|
|
*
|
|
|
|
*
|
2009-07-15 21:31:25 +02:00
|
|
|
* Using the PEAR Log class (which need to be installed!)
|
2005-06-19 21:00:58 +02:00
|
|
|
*
|
2009-07-15 21:31:25 +02:00
|
|
|
* @link http://www.egroupware.org
|
|
|
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
|
|
|
* @package api
|
|
|
|
* @subpackage horde
|
|
|
|
* @author Anthony Mills <amills@pyramid6.com>
|
2005-06-19 21:00:58 +02:00
|
|
|
* @author Karsten Fourmont <fourmont@gmx.de>
|
2009-07-15 21:31:25 +02:00
|
|
|
* @author Joerg Lehrke <jlehrke@noc.de>
|
|
|
|
* @copyright (c) The Horde Project (http://www.horde.org/)
|
|
|
|
* @version $Id$
|
2005-06-19 21:00:58 +02:00
|
|
|
*/
|
2009-07-15 21:31:25 +02:00
|
|
|
include_once 'Horde/SyncML/Sync.php';
|
|
|
|
include_once 'Horde/SyncML/Command/Sync/ContentSyncElement.php';
|
|
|
|
|
2005-06-19 21:00:58 +02:00
|
|
|
class Horde_SyncML_Sync_TwoWaySync extends Horde_SyncML_Sync {
|
2006-08-15 16:42:13 +02:00
|
|
|
|
2009-07-15 21:31:25 +02:00
|
|
|
function endSync($currentCmdID, & $output) {
|
2006-07-09 09:27:23 +02:00
|
|
|
global $registry;
|
2008-10-08 20:40:01 +02:00
|
|
|
|
2009-07-15 21:31:25 +02:00
|
|
|
$state = & $_SESSION['SyncML.state'];
|
2008-10-08 20:40:01 +02:00
|
|
|
|
2006-07-09 09:27:23 +02:00
|
|
|
$syncType = $this->_targetLocURI;
|
2008-10-08 20:40:01 +02:00
|
|
|
|
SyncML patches from patrick.bihan-faou-AT-mindstep.com (without
logout+mbstring stuff), small modification to use the already exiting
methodes to generate full name and fileas)
The code is commited to trunk only at the moment to allow testing of it.
If everything goes well, we intend to commit it to 1.4 branch too.
Here's the original description of the patch by Patrick:
- handles the default config for current versions of funambol (i.e. the
scard/stask/snote/scal locations)
- tries to be a bit smarter on how the data content should be encoded
based on what the client specified (sif+base64/vcard, / fragmented or
not, etc.)
- workaround a bug in some versions of funambol, where funambol does not
specify the proper sif type for the type of requested data
- imported patch #117 from egw's tracker
- make sure that the logs generated by the horde code go to stderr so
they can be view in the webserver's logs
- as much as possible reduce code duplication. For example, the
categories are handled in the parent classes for both the SIF avn VCAL
formats for each type of data (addressbook,infolog,calendar).
- make sure the code can handle more than one categories in each
direction
- treat the 'sony ericsson' vendor string just like 'sonyericsson', the
newer phones apparently have a space in the vendor string... (this
touches some files in the icalsrv as well)
- handle notes: these should now work with everything (funambol or
other)
- remove more code duplication: the syncml "api" for the various data
types (calendar, contacts, infolog) is now common for both the vcard and
sif data formats (cf the files that need to be removed)
- handle the "privat" filter in infolog like the "private" filter (some
part of the code use the name without the trailing e)
- imported patch # 267 from egw's tracker
2007-09-29 12:29:48 +02:00
|
|
|
$hordeType = $state->getHordeType($syncType);
|
2008-10-08 20:40:01 +02:00
|
|
|
|
2006-07-09 09:27:23 +02:00
|
|
|
$refts = $state->getServerAnchorLast($syncType);
|
2009-07-15 21:31:25 +02:00
|
|
|
$currentCmdID = $this->handleSync($currentCmdID, $hordeType, $syncType, $output, $refts);
|
2008-10-08 20:40:01 +02:00
|
|
|
|
2006-07-09 09:27:23 +02:00
|
|
|
return $currentCmdID;
|
|
|
|
}
|
2005-06-19 21:00:58 +02:00
|
|
|
|
2009-07-15 21:31:25 +02:00
|
|
|
function handleSync($currentCmdID, $hordeType, $syncType, & $output, $refts) {
|
2006-03-21 14:49:13 +01:00
|
|
|
global $registry;
|
2008-10-08 20:40:01 +02:00
|
|
|
|
2006-03-21 14:49:13 +01:00
|
|
|
// array of Items which got modified, but got never send to the client before
|
2009-07-15 21:31:25 +02:00
|
|
|
$missedAdds = array ();
|
|
|
|
// array of Items which the client wanted to add, but must be deleted due to
|
|
|
|
// user's sync policy
|
|
|
|
$remoteDeletes = array ();
|
2008-10-08 20:40:01 +02:00
|
|
|
|
|
|
|
$history = $GLOBALS['egw']->contenthistory;
|
2009-07-15 21:31:25 +02:00
|
|
|
$state = & $_SESSION['SyncML.state'];
|
|
|
|
$maxMsgSize = $state->getMaxMsgSizeClient();
|
|
|
|
$deviceInfo = $state->getClientDeviceInfo();
|
|
|
|
|
|
|
|
if (isset($deviceInfo['maxEntries'])) {
|
|
|
|
$maxEntries = $deviceInfo['maxEntries'];
|
|
|
|
if (!$maxMsgSize && !$maxEntries) {
|
|
|
|
// fallback to default
|
|
|
|
$maxEntries = MAX_ENTRIES;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$maxEntries = MAX_ENTRIES;
|
|
|
|
}
|
|
|
|
|
|
|
|
$serverAnchorNext = $state->getServerAnchorNext($syncType);
|
2008-10-08 20:40:01 +02:00
|
|
|
|
|
|
|
|
2009-07-15 21:31:25 +02:00
|
|
|
if (isset ($state->curSyncItem)) {
|
|
|
|
// Finish the pending sync item
|
|
|
|
$cmd = & $state->curSyncItem;
|
|
|
|
unset ($state->curSyncItem);
|
|
|
|
$currentCmdID = $cmd->outputCommand($currentCmdID, $output, 'Sync');
|
|
|
|
|
|
|
|
// moreData split; save in session state and end current message
|
|
|
|
if ($cmd->hasMoreData()) {
|
|
|
|
$state->curSyncItem = & $cmd;
|
|
|
|
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
|
|
|
|
return $currentCmdID;
|
|
|
|
}
|
|
|
|
$state->incNumberOfElements();
|
|
|
|
}
|
|
|
|
|
|
|
|
$changes = & $state->getChangedItems($syncType);
|
|
|
|
$deletes = & $state->getDeletedItems($syncType);
|
|
|
|
$adds = & $state->getAddedItems($syncType);
|
|
|
|
$conflicts = & $state->getConflictItems($syncType);
|
|
|
|
|
|
|
|
Horde :: logMessage('SyncML: ' . count($changes) . ' changed items found for ' . $syncType, __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
|
|
|
Horde :: logMessage('SyncML: ' . count($deletes) . ' deleted items found for ' . $syncType, __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
2009-11-11 21:16:34 +01:00
|
|
|
Horde :: logMessage('SyncML: ' . count($conflicts) . ' items to delete on client found for ' . $syncType, __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
|
|
|
Horde :: logMessage('SyncML: ' . count($adds) . ' added items found for ' . $syncType, __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
2008-10-08 20:40:01 +02:00
|
|
|
|
2006-07-09 09:27:23 +02:00
|
|
|
// handle changes
|
2009-07-15 21:31:25 +02:00
|
|
|
if (is_array($changes)) {
|
|
|
|
while ($guid = array_shift($changes)) {
|
|
|
|
$currentSize = $output->getOutputSize();
|
|
|
|
// return if we have to much data
|
|
|
|
if (($maxEntries
|
|
|
|
&& ($state->getNumberOfElements() >= $maxEntries)
|
|
|
|
&& isset ($contentType['mayFragment'])
|
|
|
|
&& $contentType['mayFragment'])
|
|
|
|
|| ($maxMsgSize
|
|
|
|
&& (($currentSize +MIN_MSG_LEFT * 2) > $maxMsgSize))) {
|
|
|
|
// put the item back in the queue
|
|
|
|
$changes[] = $guid;
|
|
|
|
$state->maxNumberOfElements();
|
|
|
|
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
|
|
|
|
return $currentCmdID;
|
|
|
|
}
|
|
|
|
|
2008-11-03 08:44:02 +01:00
|
|
|
$guid_ts = $state->getSyncTSforAction($guid, 'modify');
|
2006-07-09 09:27:23 +02:00
|
|
|
$sync_ts = $state->getChangeTS($syncType, $guid);
|
2009-07-15 21:31:25 +02:00
|
|
|
Horde :: logMessage("SyncML: timestamp modify $guid guid_ts: $guid_ts sync_ts: $sync_ts", __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
2006-07-09 09:27:23 +02:00
|
|
|
if ($sync_ts && $sync_ts == $guid_ts) {
|
|
|
|
// Change was done by us upon request of client.
|
|
|
|
// Don't mirror that back to the client.
|
2009-07-15 21:31:25 +02:00
|
|
|
Horde :: logMessage("SyncML: change: $guid ignored, came from client", __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if ($guid_ts > $serverAnchorNext) {
|
|
|
|
// Change was made after we started this sync.
|
|
|
|
// Don't sent this now to the client.
|
|
|
|
Horde :: logMessage("SyncML: change $guid is in our future: $serverAnchorNext", __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
2006-07-09 09:27:23 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
$locid = $state->getLocID($syncType, $guid);
|
|
|
|
if (!$locid) {
|
|
|
|
// somehow we missed to add, lets store the uid, so we add this entry later
|
|
|
|
$missedAdds[] = $guid;
|
2009-07-15 21:31:25 +02:00
|
|
|
Horde :: logMessage("SyncML: unable to create change for $guid: locid not found in map", __FILE__, __LINE__, PEAR_LOG_WARNING);
|
2006-07-09 09:27:23 +02:00
|
|
|
continue;
|
|
|
|
}
|
2008-10-08 20:40:01 +02:00
|
|
|
|
2006-07-09 09:27:23 +02:00
|
|
|
// Create a replace request for client.
|
SyncML patches from patrick.bihan-faou-AT-mindstep.com (without
logout+mbstring stuff), small modification to use the already exiting
methodes to generate full name and fileas)
The code is commited to trunk only at the moment to allow testing of it.
If everything goes well, we intend to commit it to 1.4 branch too.
Here's the original description of the patch by Patrick:
- handles the default config for current versions of funambol (i.e. the
scard/stask/snote/scal locations)
- tries to be a bit smarter on how the data content should be encoded
based on what the client specified (sif+base64/vcard, / fragmented or
not, etc.)
- workaround a bug in some versions of funambol, where funambol does not
specify the proper sif type for the type of requested data
- imported patch #117 from egw's tracker
- make sure that the logs generated by the horde code go to stderr so
they can be view in the webserver's logs
- as much as possible reduce code duplication. For example, the
categories are handled in the parent classes for both the SIF avn VCAL
formats for each type of data (addressbook,infolog,calendar).
- make sure the code can handle more than one categories in each
direction
- treat the 'sony ericsson' vendor string just like 'sonyericsson', the
newer phones apparently have a space in the vendor string... (this
touches some files in the icalsrv as well)
- handle notes: these should now work with everything (funambol or
other)
- remove more code duplication: the syncml "api" for the various data
types (calendar, contacts, infolog) is now common for both the vcard and
sif data formats (cf the files that need to be removed)
- handle the "privat" filter in infolog like the "private" filter (some
part of the code use the name without the trailing e)
- imported patch # 267 from egw's tracker
2007-09-29 12:29:48 +02:00
|
|
|
$contentType = $state->getPreferedContentTypeClient($this->_sourceLocURI, $this->_targetLocURI);
|
2009-07-15 21:31:25 +02:00
|
|
|
$c = $registry->call($hordeType . '/export', array (
|
|
|
|
'guid' => $guid,
|
|
|
|
'contentType' => $contentType
|
|
|
|
));
|
|
|
|
if (is_a($c, 'PEAR_Error')) {
|
2006-07-09 09:27:23 +02:00
|
|
|
// Item in history but not in database. Strange, but can happen.
|
2009-07-15 21:31:25 +02:00
|
|
|
Horde :: logMessage("SyncML: change: export of guid $guid failed:\n" . print_r($c, true), __FILE__, __LINE__, PEAR_LOG_WARNING);
|
|
|
|
continue;
|
|
|
|
}
|
2008-10-08 20:40:01 +02:00
|
|
|
|
2009-07-15 21:31:25 +02:00
|
|
|
$size = strlen($c);
|
|
|
|
// return if we have to much data
|
|
|
|
if ($maxMsgSize && !$deviceInfo['supportLargeObjs']) {
|
|
|
|
if (($size +MIN_MSG_LEFT * 2) > $maxMsgSize) {
|
|
|
|
Horde :: logMessage("SyncML: change: export of guid $guid failed due to size $size", __FILE__, __LINE__, PEAR_LOG_ERROR);
|
|
|
|
$state->log('Server-ExportFailed');
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (($currentSize + $size +MIN_MSG_LEFT * 2) > $maxMsgSize) {
|
|
|
|
// put the item back in the queue
|
|
|
|
$changes[] = $guid;
|
2006-07-09 09:27:23 +02:00
|
|
|
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
|
|
|
|
return $currentCmdID;
|
|
|
|
}
|
|
|
|
}
|
2009-07-15 21:31:25 +02:00
|
|
|
|
|
|
|
Horde :: logMessage("SyncML: change: export guid $guid, content:\n$c", __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
|
|
|
$cmd = new Horde_SyncML_Command_Sync_ContentSyncElement();
|
|
|
|
# LK $cmd->setContent($state->convertServer2Client($c, $contentType));
|
|
|
|
$cmd->setContent($c);
|
|
|
|
$cmd->setLocURI($locid);
|
|
|
|
$cmd->setContentType($contentType['ContentType']);
|
|
|
|
if (isset ($contentType['ContentFormat'])) {
|
|
|
|
$cmd->setContentFormat($contentType['ContentFormat']);
|
|
|
|
}
|
|
|
|
$currentCmdID = $cmd->outputCommand($currentCmdID, $output, 'Replace');
|
|
|
|
$state->log('Server-Replace');
|
|
|
|
|
|
|
|
// moreData split; save in session state and end current message
|
|
|
|
if ($cmd->hasMoreData()) {
|
|
|
|
$state->curSyncItem = & $cmd;
|
|
|
|
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
|
|
|
|
return $currentCmdID;
|
|
|
|
}
|
|
|
|
$state->incNumberOfElements();
|
2006-03-21 14:49:13 +01:00
|
|
|
}
|
2006-07-09 09:27:23 +02:00
|
|
|
}
|
2009-07-15 21:31:25 +02:00
|
|
|
Horde :: logMessage("SyncML: handling sync (changes done) " . $currentCmdID, __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
2006-07-09 09:27:23 +02:00
|
|
|
|
|
|
|
// handle deletes
|
2009-07-15 21:31:25 +02:00
|
|
|
if (is_array($deletes)) {
|
|
|
|
while ($guid = array_shift($deletes)) {
|
|
|
|
$currentSize = $output->getOutputSize();
|
|
|
|
// return if we have to much data
|
|
|
|
if (($maxEntries && ($state->getNumberOfElements() >= $maxEntries)
|
|
|
|
&& isset ($contentType['mayFragment'])
|
|
|
|
&& $contentType['mayFragment'])
|
|
|
|
|| ($maxMsgSize
|
|
|
|
&& (($currentSize +MIN_MSG_LEFT * 2) > $maxMsgSize))) {
|
|
|
|
// put the item back in the queue
|
|
|
|
$deletes[] = $guid;
|
|
|
|
$state->maxNumberOfElements();
|
|
|
|
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
|
|
|
|
return $currentCmdID;
|
|
|
|
}
|
|
|
|
|
2008-11-03 08:44:02 +01:00
|
|
|
$guid_ts = $state->getSyncTSforAction($guid, 'delete');
|
2006-07-09 09:27:23 +02:00
|
|
|
$sync_ts = $state->getChangeTS($syncType, $guid);
|
2009-07-15 21:31:25 +02:00
|
|
|
Horde :: logMessage("SyncML: timestamp delete guid_ts: $guid_ts sync_ts: $sync_ts",
|
|
|
|
__FILE__, __LINE__, PEAR_LOG_DEBUG);
|
2006-07-09 09:27:23 +02:00
|
|
|
if ($sync_ts && $sync_ts == $guid_ts) {
|
|
|
|
// Change was done by us upon request of client.
|
|
|
|
// Don't mirror that back to the client.
|
2009-07-15 21:31:25 +02:00
|
|
|
Horde :: logMessage("SyncML: delete $guid ignored, came from client",
|
|
|
|
__FILE__, __LINE__, PEAR_LOG_DEBUG);
|
|
|
|
if ($sync_ts < $serverAnchorNext
|
|
|
|
&& ($locid = $state->getLocID($syncType, $guid))) {
|
|
|
|
// Now we can remove the past
|
|
|
|
$state->removeUID($syncType, $locid);
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if ($guid_ts > $serverAnchorNext) {
|
|
|
|
// Change was made after we started this sync.
|
|
|
|
// Don't sent this now to the client.
|
|
|
|
Horde :: logMessage("SyncML: delete $guid is in our future: $serverAnchorNext", __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
2006-07-09 09:27:23 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
$locid = $state->getLocID($syncType, $guid);
|
|
|
|
if (!$locid) {
|
2009-07-15 21:31:25 +02:00
|
|
|
Horde :: logMessage("SyncML: unable to delete $guid: locid not found in map", __FILE__, __LINE__, PEAR_LOG_INFO);
|
|
|
|
$state->log("Server-DeleteFailure");
|
2006-07-09 09:27:23 +02:00
|
|
|
continue;
|
|
|
|
}
|
2008-10-08 20:40:01 +02:00
|
|
|
|
2009-07-15 21:31:25 +02:00
|
|
|
Horde :: logMessage("SyncML: delete: $guid", __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
2006-07-09 09:27:23 +02:00
|
|
|
// Create a Delete request for client.
|
2009-06-08 18:21:14 +02:00
|
|
|
$cmd = new Horde_SyncML_Command_Sync_ContentSyncElement();
|
2009-07-15 21:31:25 +02:00
|
|
|
$cmd->setLocURI($locid);
|
2006-07-09 09:27:23 +02:00
|
|
|
$currentCmdID = $cmd->outputCommand($currentCmdID, $output, 'Delete');
|
|
|
|
$state->log('Server-Delete');
|
|
|
|
$state->removeUID($syncType, $locid);
|
2008-10-08 20:40:01 +02:00
|
|
|
|
2009-07-15 21:31:25 +02:00
|
|
|
// moreData split; save in session state and end current message
|
|
|
|
if ($cmd->hasMoreData()) {
|
|
|
|
$state->curSyncItem = & $cmd;
|
|
|
|
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
|
|
|
|
return $currentCmdID;
|
|
|
|
}
|
|
|
|
$state->incNumberOfElements();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// handle remote deletes due to conflicts
|
2009-11-11 21:16:34 +01:00
|
|
|
if (count($conflicts) > 0) {
|
|
|
|
while ($locid = array_shift($conflicts)) {
|
2009-07-15 21:31:25 +02:00
|
|
|
$currentSize = $output->getOutputSize();
|
2006-03-21 14:49:13 +01:00
|
|
|
// return if we have to much data
|
2009-07-15 21:31:25 +02:00
|
|
|
if (($maxEntries && ($state->getNumberOfElements() >= $maxEntries)
|
|
|
|
&& isset ($contentType['mayFragment'])
|
SyncML patches from patrick.bihan-faou-AT-mindstep.com (without
logout+mbstring stuff), small modification to use the already exiting
methodes to generate full name and fileas)
The code is commited to trunk only at the moment to allow testing of it.
If everything goes well, we intend to commit it to 1.4 branch too.
Here's the original description of the patch by Patrick:
- handles the default config for current versions of funambol (i.e. the
scard/stask/snote/scal locations)
- tries to be a bit smarter on how the data content should be encoded
based on what the client specified (sif+base64/vcard, / fragmented or
not, etc.)
- workaround a bug in some versions of funambol, where funambol does not
specify the proper sif type for the type of requested data
- imported patch #117 from egw's tracker
- make sure that the logs generated by the horde code go to stderr so
they can be view in the webserver's logs
- as much as possible reduce code duplication. For example, the
categories are handled in the parent classes for both the SIF avn VCAL
formats for each type of data (addressbook,infolog,calendar).
- make sure the code can handle more than one categories in each
direction
- treat the 'sony ericsson' vendor string just like 'sonyericsson', the
newer phones apparently have a space in the vendor string... (this
touches some files in the icalsrv as well)
- handle notes: these should now work with everything (funambol or
other)
- remove more code duplication: the syncml "api" for the various data
types (calendar, contacts, infolog) is now common for both the vcard and
sif data formats (cf the files that need to be removed)
- handle the "privat" filter in infolog like the "private" filter (some
part of the code use the name without the trailing e)
- imported patch # 267 from egw's tracker
2007-09-29 12:29:48 +02:00
|
|
|
&& $contentType['mayFragment'])
|
2009-07-15 21:31:25 +02:00
|
|
|
|| ($maxMsgSize
|
|
|
|
&& (($currentSize +MIN_MSG_LEFT * 2) > $maxMsgSize))) {
|
|
|
|
// put the item back in the queue
|
2009-11-11 21:16:34 +01:00
|
|
|
$conflicts[] = $locid;
|
2009-07-15 21:31:25 +02:00
|
|
|
$state->maxNumberOfElements();
|
2006-03-21 14:49:13 +01:00
|
|
|
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
|
|
|
|
return $currentCmdID;
|
|
|
|
}
|
2009-07-15 21:31:25 +02:00
|
|
|
Horde :: logMessage("SyncML: delete client locid: $locid", __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
|
|
|
// Create a Delete request for client.
|
|
|
|
$cmd = new Horde_SyncML_Command_Sync_ContentSyncElement();
|
|
|
|
$cmd->setLocURI($locid);
|
|
|
|
$currentCmdID = $cmd->outputCommand($currentCmdID, $output, 'Delete');
|
|
|
|
$state->log('Server-DeletedConflicts');
|
|
|
|
$state->removeUID($syncType, $locid);
|
|
|
|
|
|
|
|
// moreData split; save in session state and end current message
|
|
|
|
if ($cmd->hasMoreData()) {
|
|
|
|
$state->curSyncItem = & $cmd;
|
|
|
|
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
|
|
|
|
return $currentCmdID;
|
|
|
|
}
|
|
|
|
$state->incNumberOfElements();
|
2006-03-21 14:49:13 +01:00
|
|
|
}
|
|
|
|
}
|
2006-07-09 09:27:23 +02:00
|
|
|
#Horde::logMessage("SyncML: handling sync ".$currentCmdID, __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
2005-06-19 21:00:58 +02:00
|
|
|
|
2006-07-09 09:27:23 +02:00
|
|
|
// handle missing adds.
|
2009-07-15 21:31:25 +02:00
|
|
|
if (count($missedAdds) > 0) {
|
|
|
|
Horde :: logMessage("SyncML: add missed changes as adds " . count($adds) . ' / ' . $missedAdds[0], __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
|
|
|
$adds = array_merge($adds, $missedAdds);
|
|
|
|
Horde :: logMessage("SyncML: merged adds counter " . count($adds) . ' / ' . $adds[0], __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
2006-03-21 14:49:13 +01:00
|
|
|
}
|
2008-10-08 20:40:01 +02:00
|
|
|
|
2009-07-15 21:31:25 +02:00
|
|
|
if (is_array($adds)) {
|
|
|
|
while ($guid = array_shift($adds)) {
|
|
|
|
$currentSize = $output->getOutputSize();
|
|
|
|
// return if we have to much data
|
|
|
|
if (($maxEntries && ($state->getNumberOfElements() >= $maxEntries)
|
|
|
|
&& isset ($contentType['mayFragment'])
|
|
|
|
&& $contentType['mayFragment'])
|
|
|
|
|| ($maxMsgSize
|
|
|
|
&& (($currentSize +MIN_MSG_LEFT * 2) > $maxMsgSize))) {
|
|
|
|
// put the item back in the queue
|
|
|
|
$adds[] = $guid;
|
|
|
|
$state->maxNumberOfElements();
|
|
|
|
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
|
|
|
|
return $currentCmdID;
|
|
|
|
}
|
|
|
|
|
2009-09-28 21:45:35 +02:00
|
|
|
// first we try the modification timestamp then the creation ts
|
|
|
|
if (!($guid_ts = $state->getSyncTSforAction($guid, 'modify'))) {
|
|
|
|
$guid_ts = $state->getSyncTSforAction($guid, 'add');
|
|
|
|
}
|
|
|
|
|
2006-08-15 16:42:13 +02:00
|
|
|
$sync_ts = $state->getChangeTS($syncType, $guid);
|
2009-07-15 21:31:25 +02:00
|
|
|
Horde :: logMessage("SyncML: timestamp add $guid guid_ts: $guid_ts sync_ts: $sync_ts", __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
2006-08-15 16:42:13 +02:00
|
|
|
if ($sync_ts && $sync_ts == $guid_ts) {
|
|
|
|
// Change was done by us upon request of client.
|
|
|
|
// Don't mirror that back to the client.
|
2009-07-15 21:31:25 +02:00
|
|
|
Horde :: logMessage("SyncML: add: $guid ignored, came from client", __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if ($guid_ts > $serverAnchorNext && !in_array($guid, $conflicts)) {
|
|
|
|
// Change was made after we started this sync.
|
|
|
|
// Don't sent this now to the client.
|
|
|
|
Horde :: logMessage("SyncML: add $guid is in our future: $serverAnchorNext", __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
2006-08-15 16:42:13 +02:00
|
|
|
continue;
|
2006-06-01 15:38:37 +02:00
|
|
|
}
|
2008-10-08 20:40:01 +02:00
|
|
|
|
2006-08-15 16:42:13 +02:00
|
|
|
$locid = $state->getLocID($syncType, $guid);
|
2008-10-08 20:40:01 +02:00
|
|
|
|
2006-08-15 16:42:13 +02:00
|
|
|
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.
|
2009-07-15 21:31:25 +02:00
|
|
|
Horde :: logMessage("SyncML: skipping add of guid $guid as there already is a locid $locid", __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
2006-08-15 16:42:13 +02:00
|
|
|
continue;
|
|
|
|
}
|
2009-07-15 21:31:25 +02:00
|
|
|
Horde :: logMessage("SyncML: add: $guid", __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
2008-10-08 20:40:01 +02:00
|
|
|
|
2006-08-15 16:42:13 +02:00
|
|
|
// Create an Add request for client.
|
SyncML patches from patrick.bihan-faou-AT-mindstep.com (without
logout+mbstring stuff), small modification to use the already exiting
methodes to generate full name and fileas)
The code is commited to trunk only at the moment to allow testing of it.
If everything goes well, we intend to commit it to 1.4 branch too.
Here's the original description of the patch by Patrick:
- handles the default config for current versions of funambol (i.e. the
scard/stask/snote/scal locations)
- tries to be a bit smarter on how the data content should be encoded
based on what the client specified (sif+base64/vcard, / fragmented or
not, etc.)
- workaround a bug in some versions of funambol, where funambol does not
specify the proper sif type for the type of requested data
- imported patch #117 from egw's tracker
- make sure that the logs generated by the horde code go to stderr so
they can be view in the webserver's logs
- as much as possible reduce code duplication. For example, the
categories are handled in the parent classes for both the SIF avn VCAL
formats for each type of data (addressbook,infolog,calendar).
- make sure the code can handle more than one categories in each
direction
- treat the 'sony ericsson' vendor string just like 'sonyericsson', the
newer phones apparently have a space in the vendor string... (this
touches some files in the icalsrv as well)
- handle notes: these should now work with everything (funambol or
other)
- remove more code duplication: the syncml "api" for the various data
types (calendar, contacts, infolog) is now common for both the vcard and
sif data formats (cf the files that need to be removed)
- handle the "privat" filter in infolog like the "private" filter (some
part of the code use the name without the trailing e)
- imported patch # 267 from egw's tracker
2007-09-29 12:29:48 +02:00
|
|
|
$contentType = $state->getPreferedContentTypeClient($this->_sourceLocURI, $this->_targetLocURI);
|
2008-10-08 20:40:01 +02:00
|
|
|
|
2009-07-15 21:31:25 +02:00
|
|
|
$c = $registry->call($hordeType . '/export', array (
|
|
|
|
'guid' => $guid,
|
|
|
|
'contentType' => $contentType,
|
|
|
|
|
|
|
|
));
|
|
|
|
|
|
|
|
if (is_a($c, 'PEAR_Error')) {
|
2006-08-15 16:42:13 +02:00
|
|
|
// Item in history but not in database. Strange, but can happen.
|
2009-07-15 21:31:25 +02:00
|
|
|
Horde :: logMessage("SyncML: add: export of guid $guid failed:\n" . print_r($c, true), __FILE__, __LINE__, PEAR_LOG_WARNING);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
$size = strlen($c);
|
|
|
|
// return if we have to much data
|
|
|
|
if ($maxMsgSize && !$deviceInfo['supportLargeObjs']) {
|
|
|
|
if (($size +MIN_MSG_LEFT * 2) > $maxMsgSize) {
|
|
|
|
Horde :: logMessage("SyncML: add: export of guid $guid failed due to size $size", __FILE__, __LINE__, PEAR_LOG_ERROR);
|
|
|
|
$state->log("Server-ExportFailed");
|
|
|
|
continue;
|
SyncML patches from patrick.bihan-faou-AT-mindstep.com (without
logout+mbstring stuff), small modification to use the already exiting
methodes to generate full name and fileas)
The code is commited to trunk only at the moment to allow testing of it.
If everything goes well, we intend to commit it to 1.4 branch too.
Here's the original description of the patch by Patrick:
- handles the default config for current versions of funambol (i.e. the
scard/stask/snote/scal locations)
- tries to be a bit smarter on how the data content should be encoded
based on what the client specified (sif+base64/vcard, / fragmented or
not, etc.)
- workaround a bug in some versions of funambol, where funambol does not
specify the proper sif type for the type of requested data
- imported patch #117 from egw's tracker
- make sure that the logs generated by the horde code go to stderr so
they can be view in the webserver's logs
- as much as possible reduce code duplication. For example, the
categories are handled in the parent classes for both the SIF avn VCAL
formats for each type of data (addressbook,infolog,calendar).
- make sure the code can handle more than one categories in each
direction
- treat the 'sony ericsson' vendor string just like 'sonyericsson', the
newer phones apparently have a space in the vendor string... (this
touches some files in the icalsrv as well)
- handle notes: these should now work with everything (funambol or
other)
- remove more code duplication: the syncml "api" for the various data
types (calendar, contacts, infolog) is now common for both the vcard and
sif data formats (cf the files that need to be removed)
- handle the "privat" filter in infolog like the "private" filter (some
part of the code use the name without the trailing e)
- imported patch # 267 from egw's tracker
2007-09-29 12:29:48 +02:00
|
|
|
}
|
2009-07-15 21:31:25 +02:00
|
|
|
if (($currentSize + $size +MIN_MSG_LEFT * 2) > $maxMsgSize) {
|
|
|
|
// put the item back in the queue
|
|
|
|
$adds[] = $guid;
|
2006-08-15 16:42:13 +02:00
|
|
|
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
|
|
|
|
return $currentCmdID;
|
|
|
|
}
|
2006-03-21 14:49:13 +01:00
|
|
|
}
|
2009-07-15 21:31:25 +02:00
|
|
|
|
|
|
|
Horde :: logMessage("SyncML: add guid $guid to client\n$c", __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
|
|
|
$cmd = new Horde_SyncML_Command_Sync_ContentSyncElement();
|
|
|
|
$cmd->setContent($c);
|
|
|
|
$cmd->setContentType($contentType['ContentType']);
|
|
|
|
if (isset ($contentType['ContentFormat'])) {
|
|
|
|
$cmd->setContentFormat($contentType['ContentFormat']);
|
|
|
|
}
|
|
|
|
$cmd->setGUID($guid);
|
|
|
|
$currentCmdID = $cmd->outputCommand($currentCmdID, $output, 'Add');
|
|
|
|
$state->log('Server-Add');
|
|
|
|
|
|
|
|
// moreData split; put the guid back in the list and return
|
|
|
|
if ($cmd->hasMoreData()) {
|
|
|
|
$state->curSyncItem = & $cmd;
|
|
|
|
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
|
|
|
|
return $currentCmdID;
|
|
|
|
}
|
|
|
|
$state->incNumberOfElements();
|
2006-03-21 14:49:13 +01:00
|
|
|
}
|
|
|
|
}
|
2009-07-15 21:31:25 +02:00
|
|
|
Horde::logMessage("SyncML: All items handled for sync $syncType", __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
2008-10-08 20:40:01 +02:00
|
|
|
|
2009-07-15 21:31:25 +02:00
|
|
|
$state->removeExpiredUID($syncType, time());
|
2006-03-21 14:49:13 +01:00
|
|
|
$state->clearSync($syncType);
|
2008-10-08 20:40:01 +02:00
|
|
|
|
2006-03-21 14:49:13 +01:00
|
|
|
return $currentCmdID;
|
|
|
|
}
|
2008-10-08 20:40:01 +02:00
|
|
|
|
2006-08-15 16:42:13 +02:00
|
|
|
function loadData() {
|
|
|
|
global $registry;
|
2008-10-08 20:40:01 +02:00
|
|
|
|
2009-07-15 21:31:25 +02:00
|
|
|
$state = & $_SESSION['SyncML.state'];
|
2006-08-15 16:42:13 +02:00
|
|
|
$syncType = $this->_targetLocURI;
|
SyncML patches from patrick.bihan-faou-AT-mindstep.com (without
logout+mbstring stuff), small modification to use the already exiting
methodes to generate full name and fileas)
The code is commited to trunk only at the moment to allow testing of it.
If everything goes well, we intend to commit it to 1.4 branch too.
Here's the original description of the patch by Patrick:
- handles the default config for current versions of funambol (i.e. the
scard/stask/snote/scal locations)
- tries to be a bit smarter on how the data content should be encoded
based on what the client specified (sif+base64/vcard, / fragmented or
not, etc.)
- workaround a bug in some versions of funambol, where funambol does not
specify the proper sif type for the type of requested data
- imported patch #117 from egw's tracker
- make sure that the logs generated by the horde code go to stderr so
they can be view in the webserver's logs
- as much as possible reduce code duplication. For example, the
categories are handled in the parent classes for both the SIF avn VCAL
formats for each type of data (addressbook,infolog,calendar).
- make sure the code can handle more than one categories in each
direction
- treat the 'sony ericsson' vendor string just like 'sonyericsson', the
newer phones apparently have a space in the vendor string... (this
touches some files in the icalsrv as well)
- handle notes: these should now work with everything (funambol or
other)
- remove more code duplication: the syncml "api" for the various data
types (calendar, contacts, infolog) is now common for both the vcard and
sif data formats (cf the files that need to be removed)
- handle the "privat" filter in infolog like the "private" filter (some
part of the code use the name without the trailing e)
- imported patch # 267 from egw's tracker
2007-09-29 12:29:48 +02:00
|
|
|
$hordeType = $state->getHordeType($syncType);
|
2009-07-15 21:31:25 +02:00
|
|
|
$state->setTargetURI($syncType);
|
2006-08-15 16:42:13 +02:00
|
|
|
$refts = $state->getServerAnchorLast($syncType);
|
2009-07-15 21:31:25 +02:00
|
|
|
$future = $state->getServerAnchorNext($syncType);
|
|
|
|
$delta_mod = 0;
|
|
|
|
$delta_add = 0;
|
|
|
|
|
|
|
|
Horde :: logMessage("SyncML: reading changed items from database for $hordeType", __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
|
|
|
$delta_mod = count($registry->call($hordeType . '/listBy', array (
|
|
|
|
'action' => 'modify',
|
|
|
|
'timestamp' => $future,
|
|
|
|
'type' => $syncType,
|
|
|
|
'filter' => $this->_filterExpression
|
|
|
|
)));
|
2009-11-11 21:16:34 +01:00
|
|
|
$state->mergeChangedItems($syncType, $registry->call($hordeType . '/listBy', array (
|
2009-07-15 21:31:25 +02:00
|
|
|
'action' => 'modify',
|
|
|
|
'timestamp' => $refts,
|
|
|
|
'type' => $syncType,
|
|
|
|
'filter' => $this->_filterExpression
|
|
|
|
)));
|
|
|
|
|
|
|
|
Horde :: logMessage("SyncML: reading deleted items from database for $hordeType", __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
|
|
|
$state->setDeletedItems($syncType, $registry->call($hordeType . '/listBy', array (
|
|
|
|
'action' => 'delete',
|
|
|
|
'timestamp' => $refts,
|
|
|
|
'type' => $syncType,
|
|
|
|
'filter' => $this->_filterExpression
|
|
|
|
)));
|
|
|
|
|
|
|
|
Horde :: logMessage("SyncML: reading added items from database for $hordeType", __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
|
|
|
$delta_add = count($registry->call($hordeType . '/listBy', array (
|
|
|
|
'action' => 'add',
|
|
|
|
'timestamp' => $future,
|
|
|
|
'type' => $syncType,
|
|
|
|
'filter' => $this->_filterExpression
|
|
|
|
)));
|
2009-11-11 21:16:34 +01:00
|
|
|
$state->mergeAddedItems($syncType, $registry->call($hordeType . '/listBy', array (
|
2009-07-15 21:31:25 +02:00
|
|
|
'action' => 'add',
|
|
|
|
'timestamp' => $refts,
|
|
|
|
'type' => $syncType,
|
|
|
|
'filter' => $this->_filterExpression
|
|
|
|
)));
|
2008-10-08 20:40:01 +02:00
|
|
|
|
2006-08-15 16:42:13 +02:00
|
|
|
$this->_syncDataLoaded = TRUE;
|
2008-10-08 20:40:01 +02:00
|
|
|
|
2009-11-11 21:16:34 +01:00
|
|
|
return count($state->getChangedItems($syncType)) - $delta_mod + count($state->getDeletedItems($syncType)) + count($state->getAddedItems($syncType)) - $delta_add +count($state->getConflictItems($syncType));
|
2006-08-15 16:42:13 +02:00
|
|
|
}
|
2009-07-15 21:31:25 +02:00
|
|
|
}
|