Big patch from Philip Herbert (Knauber) modifying the SyncML code to no

longer use GUIDs containing eGW's install_id, as the information is
irrellevant for SyncML and cause doublications of entries if the
install_id changes.
I plan to have a new rc4 Wednesday or Thursday containing these changes.
This commit is contained in:
Ralf Becker 2008-11-03 07:44:02 +00:00
parent 7c3ab3ab8c
commit 71edd1c938
15 changed files with 131 additions and 38 deletions

View File

@ -243,7 +243,8 @@ switch($_POST['action'])
'trans' => $_POST['trans']
));
@set_time_limit(0);
$fp=fopen($csvfile,'rb');
ini_set('auto_detect_line_endings',true); // to allow to import files created eg. on a mac
$fp=fopen($csvfile,'r');
$csv_fields = fgetcsv($fp,8000,$_POST['fieldsep']);
$csv_fields = $GLOBALS['egw']->translation->convert($csv_fields,$_POST['charset']);
$csv_fields[] = 'no CSV 1'; // eg. for static assignments

View File

@ -421,9 +421,9 @@ class addressbook_vcal extends addressbook_bo
));
$defaultFields[9] = array( // nokia e90
'ADR;WORK' => array('','','adr_one_street','adr_one_locality','adr_one_region',
'ADR;WORK' => array('','adr_one_street2','adr_one_street','adr_one_locality','adr_one_region',
'adr_one_postalcode','adr_one_countryname'),
'ADR;HOME' => array('','','adr_two_street','adr_two_locality','adr_two_region',
'ADR;HOME' => array('','adr_two_street2','adr_two_street','adr_two_locality','adr_two_region',
'adr_two_postalcode','adr_two_countryname'),
'BDAY' => array('bday'),
'X-CLASS' => array('private'),
@ -441,7 +441,7 @@ class addressbook_vcal extends addressbook_bo
'TEL;PAGER;WORK' => array('tel_pager'),
'TEL;VOICE;WORK' => array('tel_work'),
'TEL;VOICE;HOME' => array('tel_home'),
'TITLE' => array('contact_role'),
'TITLE' => array('title'),
'URL;WORK' => array('url'),
'URL;HOME' => array('url_home'),
'X-ASSISTANT' => array('assistent'),
@ -539,6 +539,7 @@ class addressbook_vcal extends addressbook_bo
break;
case 'e51':
case 'e90':
case 'e71':
$this->supportedFields = $defaultFields[9];
break;
case '9300':

View File

@ -391,8 +391,8 @@ class calendar_ical extends calendar_boupdate
}
}
$modified = $GLOBALS['egw']->contenthistory->getTSforAction($eventGUID,'modify');
$created = $GLOBALS['egw']->contenthistory->getTSforAction($eventGUID,'add');
$modified = $GLOBALS['egw']->contenthistory->getTSforAction('calendar',$event['id'],'modify');
$created = $GLOBALS['egw']->contenthistory->getTSforAction('calendar',$event['id'],'add');
if (!$created && !$modified) $created = $event['modified'];
if ($created) $attributes['CREATED'] = $created;
if (!$modified) $modified = $event['modified'];
@ -443,7 +443,8 @@ class calendar_ical extends calendar_boupdate
}
}
$attributes['UID'] = $force_own_uid ? $eventGUID : $event['uid'];
//$attributes['UID'] = $force_own_uid ? $eventGUID : $event['uid'];
$attributes['UID'] = $event['uid'];
foreach($attributes as $key => $value)
{
foreach(is_array($value)&&$parameters[$key]['VALUE']!='DATE' ? $value : array($value) as $valueID => $valueData)
@ -1166,6 +1167,11 @@ class calendar_ical extends calendar_boupdate
case 'e61':
$this->supportedFields = $defaultFields['minimal'];
break;
case 'e51':
case 'e90':
case 'e71':
$this->supportedFields = $defaultFields['basic'];
break;
default:
error_log("Unknown Nokia phone '$_productName', assuming E61");
$this->supportedFields = $defaultFields['minimal'];

View File

@ -81,9 +81,10 @@ class infolog_ical extends infolog_bo
if($taskData['info_datecompleted'])
$vevent->setAttribute('COMPLETED',$taskData['info_datecompleted']);
$vevent->setAttribute('DTSTAMP',time());
$vevent->setAttribute('CREATED',$GLOBALS['egw']->contenthistory->getTSforAction($eventGUID,'add'));
$vevent->setAttribute('LAST-MODIFIED',$GLOBALS['egw']->contenthistory->getTSforAction($eventGUID,'modify'));
$vevent->setAttribute('UID',$force_own_uid ? $taskGUID : $taskData['info_uid']);
$vevent->setAttribute('CREATED',$GLOBALS['egw']->contenthistory->getTSforAction('infolog_task',$_taskID,'add'));
$vevent->setAttribute('LAST-MODIFIED',$GLOBALS['egw']->contenthistory->getTSforAction('infolog_task',$_taskID,'modify'));
//$vevent->setAttribute('UID',$force_own_uid ? $taskGUID : $taskData['info_uid']);
$vevent->setAttribute('UID',$taskData['info_uid']);
$vevent->setAttribute('CLASS',$taskData['info_access'] == 'public' ? 'PUBLIC' : 'PRIVATE');
$vevent->setAttribute('STATUS',$this->status2vtodo($taskData['info_status']));
// we try to preserv the original infolog status as X-INFOLOG-STATUS, so we can restore it, if the user does not modify STATUS
@ -253,8 +254,8 @@ class infolog_ical extends infolog_bo
$vnote->setAttribute('BODY',$note['info_des']);
if($note['info_startdate'])
$vnote->setAttribute('DCREATED',$note['info_startdate']);
$vnote->setAttribute('DCREATED',$GLOBALS['egw']->contenthistory->getTSforAction($eventGUID,'add'));
$vnote->setAttribute('LAST-MODIFIED',$GLOBALS['egw']->contenthistory->getTSforAction($eventGUID,'modify'));
$vnote->setAttribute('DCREATED',$GLOBALS['egw']->contenthistory->getTSforAction('infolog_note',$_noteID,'add'));
$vnote->setAttribute('LAST-MODIFIED',$GLOBALS['egw']->contenthistory->getTSforAction('infolog_note',$_noteID,'modify'));
if (!empty($note['info_cat']))
{
$cats = $this->get_categories(array($note['info_cat']));

View File

@ -459,8 +459,8 @@ class infolog_sif extends infolog_bo
if($taskData['info_enddate'])
$vevent->setAttribute('DUE',$taskData['info_enddate']);
$vevent->setAttribute('DTSTAMP',time());
$vevent->setAttribute('CREATED',$GLOBALS['phpgw']->contenthistory->getTSforAction($eventGUID,'add'));
$vevent->setAttribute('LAST-MODIFIED',$GLOBALS['phpgw']->contenthistory->getTSforAction($eventGUID,'modify'));
$vevent->setAttribute('CREATED',$GLOBALS['phpgw']->contenthistory->getTSforAction('infolog_task',$_taskID,'add'));
$vevent->setAttribute('LAST-MODIFIED',$GLOBALS['phpgw']->contenthistory->getTSforAction('infolog_task',$_taskID,'modify'));
$vevent->setAttribute('UID',$taskGUID);
$vevent->setAttribute('CLASS',(($taskData['info_access'] == 'public')?'PUBLIC':'PRIVATE'));
$vevent->setAttribute('STATUS',(($taskData['info_status'] == 'completed')?'COMPLETED':'NEEDS-ACTION'));

View File

@ -58,7 +58,7 @@ class contenthistory
* @param string$_appName the appname example: infolog_notes
* @param string $_action can be modify, add or delete
* @param string $_ts timestamp where to start searching from
* @return array containing the global UID's
* @return array containing contentIds with changes
*/
function getHistory($_appName, $_action, $_ts)
{
@ -79,13 +79,13 @@ class contenthistory
// no valid $_action set
return array();
}
$guidList = array();
foreach($this->db->select(self::TABLE,'sync_guid',$where,__LINE__,__FILE__) as $row)
$idList = array();
foreach($this->db->select(self::TABLE,'sync_contentid',$where,__LINE__,__FILE__) as $row)
{
$guidList[] = $row['sync_guid'];
$idList[] = $row['sync_contentid'];
}
return $guidList;
return $idList;
}
/**
@ -95,7 +95,7 @@ class contenthistory
* @param $_action string can be add, delete or modify
* @return string the last timestamp
*/
function getTSforAction($_guid, $_action)
function getTSforAction($_appName, $_id, $_action)
{
switch($_action)
{
@ -112,7 +112,8 @@ class contenthistory
return false;
}
$where = array (
'sync_guid' => $_guid,
'sync_appname' => $_appName,
'sync_contentid' => $_id,
);
if (($ts = $this->db->select(self::TABLE,$col,$where,__LINE__,__FILE__)->fetchSingle()))
@ -137,7 +138,6 @@ class contenthistory
'sync_appname' => $_appName,
'sync_contentid' => $_id,
'sync_added' => $this->db->to_timestamp($_ts),
'sync_guid' => $GLOBALS['egw']->common->generate_uid($_appName, $_id),
'sync_changedby' => $GLOBALS['egw_info']['user']['account_id'],
);

View File

@ -779,10 +779,13 @@ class Horde_SyncML_State {
break;
case 'calendar':
case 'caltasks':
return 'calendar';
break;
case 'caltasks':
return 'caltasks';
break;
# funambol related types
case 'sifcalendar':

View File

@ -17,12 +17,67 @@ include_once dirname(__FILE__).'/State.php';
class EGW_SyncML_State extends Horde_SyncML_State
{
var $table_devinfo = 'egw_syncmldevinfo';
/*
* store the mappings of egw uids to client uids
*/
var $uidMappings = array();
/**
* get the local content id from a syncid
*
* @param sting $_syncid id used in syncml
* @return int local egw content id
*/
function get_egwID($_syncid)
{
$syncIDParts = explode('-',$_syncid);
array_shift($syncIDParts);
$_id = implode ('', $syncIDParts);
return $_id;
}
/**
* when got a entry last added/modified/deleted
*
* @param $_syncid containing appName-contentid
* @param $_action string can be add, delete or modify
* @return string the last timestamp
*/
function getSyncTSforAction($_syncid, $_action)
{
$syncIDParts = explode('-',$_syncid);
$_appName = array_shift($syncIDParts);
$_id = implode ('', $syncIDParts);
$ts = $GLOBALS['egw']->contenthistory->getTSforAction($_appName, $_id, $_action);
return $ts;
}
/**
* get the timestamp for action
*
* find which content changed since $_ts for application $_appName
*
* @param string$_appName the appname example: infolog_notes
* @param string $_action can be modify, add or delete
* @param string $_ts timestamp where to start searching from
* @return array containing syncIDs with changes
*/
function getHistory($_appName, $_action, $_ts)
{
$guidList = array ();
$syncIdList = array ();
$idList = $GLOBALS['egw']->contenthistory->getHistory($_appName, $_action, $_ts);
foreach ($idList as $idItem)
{
$syncIdList[] = $_appName . '-' . $idItem;
}
return $syncIdList;
}
/**
* Returns the timestamp (if set) of the last change to the
* obj:guid, that was caused by the client. This is stored to
@ -257,7 +312,7 @@ class EGW_SyncML_State extends Horde_SyncML_State
function removeUID($type, $locid)
{
$mapID = $this->_locName . $this->_sourceURI . $type;
$where = array (
'map_id' => $mapID,
'map_locuid' => $locid
@ -301,6 +356,9 @@ class EGW_SyncML_State extends Horde_SyncML_State
$guid = $this->getUIDMapping($_guid);
if($guid === false)
{
// this message is not really usefull here because setUIDMapping is only called when adding content to the client,
// however setUID is called also when adding content from the client. So in all other conditions this
// message will be logged.
Horde::logMessage("SyncML: setUID $type, $locid, $guid something went wrong!!! Mapping not found.", __FILE__, __LINE__, PEAR_LOG_INFO);
$guid = $_guid;
//return false;

View File

@ -163,7 +163,7 @@ class Horde_SyncML_Sync {
array($state->convertClient2Server($syncItem->getContent(), $contentType), $contentType));
if (!is_a($guid, 'PEAR_Error')) {
$ts = $history->getTSforAction($guid, 'add');
$ts = $state->getSyncTSforAction($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);
@ -180,7 +180,7 @@ class Horde_SyncML_Sync {
if (!is_a($guid, 'PEAR_Error') && $guid != false) {
$registry->call($hordeType . '/delete', array($guid));
#$ts = $history->getTSforAction($guid, 'delete');
#$ts = $state->getSyncTSforAction($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);
@ -194,13 +194,14 @@ class Horde_SyncML_Sync {
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));
$ok = $registry->call($hordeType . '/replace',
array($guid, $state->convertClient2Server($syncItem->getContent(), $contentType), $contentType));
if (!is_a($ok, 'PEAR_Error')) {
$ts = $history->getTSforAction($guid, 'modify');
$ts = $state->getSyncTSforAction($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");
error_log("done_replace");
$ok = true;
} else {
// Entry may have been deleted; try adding it.
@ -214,7 +215,7 @@ class Horde_SyncML_Sync {
$guid = $registry->call($hordeType . '/import',
array($state->convertClient2Server($syncItem->getContent(), $contentType), $contentType));
if (!is_a($guid, 'PEAR_Error')) {
$ts = $history->getTSforAction($guid, 'add');
$ts = $state->getSyncTSforAction($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);

View File

@ -19,7 +19,6 @@ class Horde_SyncML_Sync_RefreshFromServerSync extends Horde_SyncML_Sync_TwoWaySy
function handleSync($currentCmdID, $hordeType, $syncType, &$output, $refts) {
global $registry;
$history = $GLOBALS['egw']->contenthistory;
$state = &$_SESSION['SyncML.state'];
$adds = &$state->getAddedItems($hordeType);

View File

@ -160,7 +160,7 @@ class Horde_SyncML_Sync_SlowSync extends Horde_SyncML_Sync_TwoWaySync {
$guid = $registry->call($hordeType . '/import',
array($state->convertClient2Server($syncItem->getContent(), $contentType), $contentType));
if (!is_a($guid, 'PEAR_Error')) {
$ts = $history->getTSforAction($guid, 'add');
$ts = $state->getSyncTSforAction($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);

View File

@ -60,7 +60,7 @@ class Horde_SyncML_Sync_TwoWaySync extends Horde_SyncML_Sync {
// handle changes
if(is_array($changes)) {
while($guid = array_shift($changes)) {
$guid_ts = $history->getTSforAction($guid, 'modify');
$guid_ts = $state->getSyncTSforAction($guid, 'modify');
$sync_ts = $state->getChangeTS($syncType, $guid);
Horde::logMessage("SyncML: timestamp modify guid_ts: $guid_ts sync_ts: $sync_ts", __FILE__, __LINE__, PEAR_LOG_DEBUG);
if ($sync_ts && $sync_ts == $guid_ts) {
@ -115,7 +115,7 @@ class Horde_SyncML_Sync_TwoWaySync extends Horde_SyncML_Sync {
// handle deletes
if(is_array($deletes)) {
while($guid = array_shift($deletes)) {
$guid_ts = $history->getTSforAction($guid, 'delete');
$guid_ts = $state->getSyncTSforAction($guid, 'delete');
$sync_ts = $state->getChangeTS($syncType, $guid);
Horde::logMessage("SyncML: timestamp delete guid_ts: $guid_ts sync_ts: $sync_ts", __FILE__, __LINE__, PEAR_LOG_DEBUG);
if ($sync_ts && $sync_ts == $guid_ts) {
@ -163,7 +163,7 @@ class Horde_SyncML_Sync_TwoWaySync extends Horde_SyncML_Sync {
if(is_array($adds)) {
while($guid = array_shift($adds)) {
$guid_ts = $history->getTSforAction($guid, 'add');
$guid_ts = $state->getSyncTSforAction($guid, 'add');
$sync_ts = $state->getChangeTS($syncType, $guid);
Horde::logMessage("SyncML: timestamp add $guid guid_ts: $guid_ts sync_ts: $sync_ts", __FILE__, __LINE__, PEAR_LOG_DEBUG);
if ($sync_ts && $sync_ts == $guid_ts) {

View File

@ -12,7 +12,7 @@
/* Basic information about this app */
$setup_info['phpgwapi']['name'] = 'phpgwapi';
$setup_info['phpgwapi']['title'] = 'eGroupWare API';
$setup_info['phpgwapi']['version'] = '1.5.016';
$setup_info['phpgwapi']['version'] = '1.5.017';
$setup_info['phpgwapi']['versions']['current_header'] = '1.29';
$setup_info['phpgwapi']['enable'] = 3;
$setup_info['phpgwapi']['app_order'] = 1;

View File

@ -302,7 +302,6 @@ $phpgw_baseline = array(
'sync_modified' => array('type' => 'timestamp'),
'sync_deleted' => array('type' => 'timestamp'),
'sync_id' => array('type' => 'auto','nullable' => False),
'sync_guid' => array('type' => 'varchar','precision' => '120','nullable' => False),
'sync_changedby' => array('type' => 'int','precision' => '4','nullable' => False)
),
'pk' => array('sync_id'),

View File

@ -578,3 +578,27 @@ function phpgwapi_upgrade1_5_015()
return $GLOBALS['setup_info']['phpgwapi']['currentver'] = '1.5.016';
}
/**
* Drop no longer needed egw_api_content_history.sync_guid column
*/
function phpgwapi_upgrade1_5_016()
{
$GLOBALS['egw_setup']->oProc->DropColumn('egw_api_content_history',array(
'fd' => array(
'sync_appname' => array('type' => 'varchar','precision' => '60','nullable' => False),
'sync_contentid' => array('type' => 'varchar','precision' => '60','nullable' => False),
'sync_added' => array('type' => 'timestamp'),
'sync_modified' => array('type' => 'timestamp'),
'sync_deleted' => array('type' => 'timestamp'),
'sync_id' => array('type' => 'auto','nullable' => False),
'sync_changedby' => array('type' => 'int','precision' => '4','nullable' => False)
),
'pk' => array('sync_id'),
'fk' => array(),
'ix' => array('sync_added','sync_modified','sync_deleted','sync_guid','sync_changedby',array('sync_appname','sync_contentid')),
'uc' => array()
),'sync_guid');
return $GLOBALS['setup_info']['phpgwapi']['currentver'] = '1.5.017';
}