883 lines
26 KiB
C++
883 lines
26 KiB
C++
/*
|
|
* This file implements the Synthesis DB API and maps it to
|
|
* EvolutionSyncSources. It was derived from the Synthesis
|
|
* sync_dbapi_demo.c file.
|
|
*
|
|
* The external API of this file are the globally visible
|
|
* C functions defined by sync_dbapidef.h.
|
|
*
|
|
* Copyright (c) 2004-2008 by Synthesis AG
|
|
* Copyright (C) 2009 Intel Corporation
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) version 3.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
* 02110-1301 USA
|
|
*/
|
|
|
|
#include <synthesis/sync_include.h> /* include general SDK definitions */
|
|
#include <synthesis/sync_dbapidef.h> /* include the interface file and utilities */
|
|
#include <synthesis/SDK_util.h> /* include SDK utilities */
|
|
|
|
using namespace sysync;
|
|
|
|
#include <syncevo/SyncContext.h>
|
|
#include <syncevo/SyncSource.h>
|
|
#include <syncevo/IdentityProvider.h>
|
|
|
|
#include <sstream>
|
|
|
|
#include <syncevo/declarations.h>
|
|
SE_BEGIN_CXX
|
|
|
|
#define BuildNumber 0 /* User defined build number, can be 0..255 */
|
|
#define MyDB "SyncEvolution" /* example debug name */
|
|
#define MY_ID 42 /* example datastore context */
|
|
|
|
#define STRLEN 80 /* Max length of local string copies */
|
|
|
|
/* -- MODULE -------------------------------------------------------------------- */
|
|
/* <mContext> will be casted to the SyncSource * structure */
|
|
static SyncSource *MoC(CContext mContext) { return (SyncSource *)mContext; }
|
|
|
|
/**
|
|
* looks up datasource and uses pointer to it as context
|
|
*
|
|
* @param mContextName name of previously instantiated SyncSource, "" when used as session module
|
|
* @retval mContext the corresponding SyncSource
|
|
*/
|
|
extern "C"
|
|
TSyError SyncEvolution_Module_CreateContext( CContext *mContext, cAppCharP moduleName,
|
|
cAppCharP subName,
|
|
cAppCharP mContextName,
|
|
DB_Callback mCB )
|
|
{
|
|
TSyError err = LOCERR_WRONGUSAGE;
|
|
if (!mContextName[0]) {
|
|
*mContext = NULL;
|
|
err = LOCERR_OK;
|
|
} else {
|
|
SyncSource *source = SyncContext::findSource(mContextName);
|
|
if (source) {
|
|
source->pushSynthesisAPI(mCB);
|
|
*mContext = (CContext)source;
|
|
err = LOCERR_OK;
|
|
}
|
|
}
|
|
|
|
SE_LOG_DEBUG(NULL, "CreateContext %s/%s/%s => %d",
|
|
moduleName, subName, mContextName, err);
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* @TODO: introduce and return some kind of SyncEvolution build number
|
|
*/
|
|
extern "C"
|
|
CVersion SyncEvolution_Module_Version(CContext mContext)
|
|
{
|
|
CVersion v = Plugin_Version(BuildNumber);
|
|
|
|
if (mContext) {
|
|
SE_LOG_DEBUG(NULL, "Module_Version = %08lx", (long)v);
|
|
}
|
|
return v;
|
|
}
|
|
|
|
|
|
|
|
/* Get the plug-in's capabilities */
|
|
extern "C"
|
|
TSyError SyncEvolution_Module_Capabilities( CContext mContext, appCharP *mCapabilities )
|
|
{
|
|
SyncSource *source = MoC(mContext);
|
|
|
|
std::stringstream s;
|
|
s << MyPlatform() << "\n"
|
|
<< DLL_Info << "\n"
|
|
<< CA_MinVersion << ":V1.0.6.0\n" /* must not be changed */
|
|
<< CA_Manufacturer << ":SyncEvolution\n"
|
|
<< CA_Description << ":SyncEvolution Synthesis DB Plugin\n"
|
|
<< Plugin_DS_Data_Str << ":no\n"
|
|
<< Plugin_DS_Data_Key << ":yes\n"
|
|
<< CA_ItemAsKey << ":yes\n"
|
|
<< Plugin_DS_Blob <<
|
|
((source && source->getOperations().m_readBlob) ?
|
|
":yes\n" :
|
|
":no\n");
|
|
|
|
if (source && source->getOperations().m_loadAdminData) {
|
|
s << Plugin_DS_Admin << ":yes\n";
|
|
if (source && !source->getOperations().m_readNextMapItem) {
|
|
s << CA_ResumeSupported << ":no\n";
|
|
}
|
|
}
|
|
|
|
*mCapabilities= StrAlloc(s.str().c_str());
|
|
SE_LOG_DEBUG(NULL, "Module_Capabilities:\n%s", *mCapabilities);
|
|
return LOCERR_OK;
|
|
} /* Module_Capabilities */
|
|
|
|
|
|
|
|
extern "C"
|
|
TSyError SyncEvolution_Module_PluginParams( CContext mContext,
|
|
cAppCharP mConfigParams, CVersion engineVersion )
|
|
{
|
|
SyncSource *source = MoC(mContext);
|
|
SE_LOG_DEBUG(source ? source->getDisplayName() : "", "Module_PluginParams\n Engine=%08lX\n %s",
|
|
(long)engineVersion, mConfigParams);
|
|
/*return LOCERR_CFGPARSE;*/ /* if there are unsupported params */
|
|
return LOCERR_OK;
|
|
} /* Module_PluginParams */
|
|
|
|
|
|
|
|
/* Dispose the memory of the module context */
|
|
extern "C"
|
|
void SyncEvolution_Module_DisposeObj( CContext mContext, void* memory )
|
|
{
|
|
StrDispose(memory);
|
|
}
|
|
|
|
extern "C"
|
|
TSyError SyncEvolution_Module_DeleteContext( CContext mContext )
|
|
{
|
|
SyncSource *source = MoC(mContext);
|
|
SE_LOG_DEBUG(NULL, "Module_DeleteContext %s",
|
|
source ? source->getName().c_str() : "'session'");
|
|
if (source) {
|
|
source->popSynthesisAPI();
|
|
}
|
|
return LOCERR_OK;
|
|
}
|
|
|
|
|
|
/* <sContext> will be casted to the SyncContext* structure */
|
|
static SyncContext* SeC( CContext sContext ) { return (SyncContext*)sContext; }
|
|
|
|
|
|
|
|
/* Create a context for a new session. Maps to the existing SyncContext. */
|
|
extern "C"
|
|
TSyError SyncEvolution_Session_CreateContext( CContext *sContext, cAppCharP sessionName, DB_Callback sCB )
|
|
{
|
|
*sContext = (CContext)SyncContext::findContext(sessionName);
|
|
SE_LOG_DEBUG(NULL, "Session_CreateContext '%s' %s",
|
|
sessionName, *sContext ? "found" : "not found");
|
|
if (*sContext) {
|
|
return LOCERR_OK;
|
|
} else {
|
|
return DB_NotFound;
|
|
}
|
|
} /* Session_CreateContext */
|
|
|
|
|
|
|
|
/* ----- "script-like" ADAPT --------- */
|
|
extern "C"
|
|
TSyError SyncEvolution_Session_AdaptItem( CContext sContext, appCharP *sItemData1,
|
|
appCharP *sItemData2,
|
|
appCharP *sLocalVars,
|
|
uInt32 sIdentifier )
|
|
{
|
|
/**** CAN BE ADAPTED BY USER ****/
|
|
// SyncContext* sc= SeC( sContext );
|
|
SE_LOG_DEBUG(NULL, "Session_AdaptItem '%s' '%s' '%s' id=%d",
|
|
*sItemData1,*sItemData2,*sLocalVars, sIdentifier);
|
|
return LOCERR_OK;
|
|
} /* Session_AdaptItem */
|
|
|
|
|
|
|
|
/* Check the database entry of <deviceID> and return its nonce string */
|
|
extern "C"
|
|
TSyError SyncEvolution_Session_CheckDevice( CContext sContext,
|
|
cAppCharP aDeviceID, appCharP *sDevKey,
|
|
appCharP *nonce )
|
|
{
|
|
SyncContext *sc = SeC(sContext);
|
|
if (!sc) {
|
|
return LOCERR_WRONGUSAGE;
|
|
}
|
|
TSyError res = LOCERR_OK;
|
|
|
|
sc->setSyncDeviceID(aDeviceID);
|
|
string id = sc->getRemoteDevID();
|
|
if (id.empty()) {
|
|
sc->setRemoteDevID(aDeviceID);
|
|
sc->flush();
|
|
} else if (id != aDeviceID) {
|
|
// We are using the wrong configuration?! Refuse to continue.
|
|
SE_LOG_ERROR(NULL, "remote device ID '%s' in config does not match the one from the peer '%s' - incorrect configuration?!",
|
|
id.c_str(), aDeviceID);
|
|
res = DB_Forbidden;
|
|
}
|
|
|
|
*sDevKey= StrAlloc(aDeviceID);
|
|
*nonce = StrAlloc(sc->getNonce().c_str());
|
|
SE_LOG_DEBUG(NULL, "Session_CheckDevice dev='%s' nonce='%s' res=%d",
|
|
*sDevKey, *nonce, res);
|
|
return res;
|
|
} /* Session_CheckDevice */
|
|
|
|
|
|
|
|
/* Get a new nonce from the database. If this returns an error, the SyncML engine
|
|
* will create its own nonce.
|
|
*/
|
|
extern "C"
|
|
TSyError SyncEvolution_Session_GetNonce( CContext sContext, appCharP *nonce )
|
|
{
|
|
return DB_NotFound;
|
|
} /* Session_GetNonce */
|
|
|
|
|
|
|
|
/* Save the new nonce (which will be expected to be returned
|
|
* in the next session for this device
|
|
*/
|
|
extern "C"
|
|
TSyError SyncEvolution_Session_SaveNonce( CContext sContext, cAppCharP nonce )
|
|
{
|
|
SyncContext *sc = SeC(sContext);
|
|
if (!sc) {
|
|
return LOCERR_WRONGUSAGE;
|
|
}
|
|
SE_LOG_DEBUG(NULL, "Session_SaveNonce nonce='%s'",
|
|
nonce);
|
|
sc->setNonce(nonce);
|
|
sc->flush();
|
|
return LOCERR_OK;
|
|
} /* Session_SaveNonce */
|
|
|
|
|
|
|
|
/* Save the device info of <sContext> */
|
|
extern "C"
|
|
TSyError SyncEvolution_Session_SaveDeviceInfo( CContext sContext, cAppCharP aDeviceInfo )
|
|
{
|
|
SyncContext *sc = SeC(sContext);
|
|
if (!sc) {
|
|
return LOCERR_WRONGUSAGE;
|
|
}
|
|
SE_LOG_DEBUG(NULL, "Session_SaveDeviceInfo info='%s'",
|
|
aDeviceInfo );
|
|
sc->setDeviceData(aDeviceInfo);
|
|
sc->flush();
|
|
return LOCERR_OK;
|
|
} /* Session_SaveDeviceInfo */
|
|
|
|
|
|
|
|
/* Get the plugin's DB time */
|
|
extern "C"
|
|
TSyError SyncEvolution_Session_GetDBTime( CContext sContext, appCharP *currentDBTime )
|
|
{
|
|
return DB_NotFound;
|
|
} /* Session_GetDBTime */
|
|
|
|
|
|
|
|
/* Return: Password_ClrText_IN 'SessionLogin' will get clear text password
|
|
* Password_ClrText_OUT " must return clear text password
|
|
* Password_MD5_OUT " must return MD5 coded password
|
|
* Password_MD5_Nonce_IN " will get MD5B64(MD5B64(user:pwd):nonce)
|
|
*/
|
|
extern "C"
|
|
sInt32 SyncEvolution_Session_PasswordMode( CContext sContext )
|
|
{
|
|
return Password_ClrText_OUT;
|
|
} /* Session_PasswordMode */
|
|
|
|
|
|
|
|
/* Make login */
|
|
extern "C"
|
|
TSyError SyncEvolution_Session_Login( CContext sContext, cAppCharP sUsername, appCharP *sPassword,
|
|
appCharP *sUsrKey )
|
|
{
|
|
SyncContext *sc = SeC(sContext);
|
|
if (!sc) {
|
|
return LOCERR_WRONGUSAGE;
|
|
}
|
|
TSyError res = DB_Forbidden;
|
|
UserIdentity id = sc->getSyncUser();
|
|
Credentials cred = IdentityProviderCredentials(id, sc->getSyncPassword());
|
|
const std::string &user = cred.m_username;
|
|
const std::string &password = cred.m_password;
|
|
|
|
if (user.empty() && password.empty()) {
|
|
// nothing to check, accept peer
|
|
res = LOCERR_OK;
|
|
} else if (user == sUsername) {
|
|
*sPassword=StrAlloc(password.c_str());
|
|
res = LOCERR_OK;
|
|
}
|
|
|
|
SE_LOG_DEBUG(NULL, "Session_Login usr='%s' expected user='%s' res=%d",
|
|
sUsername, user.c_str(), res);
|
|
return res;
|
|
} /* Session_Login */
|
|
|
|
|
|
|
|
/* Make logout */
|
|
extern "C"
|
|
TSyError SyncEvolution_Session_Logout( CContext sContext )
|
|
{
|
|
return LOCERR_OK;
|
|
} /* Session_Logout */
|
|
|
|
|
|
|
|
extern "C"
|
|
void SyncEvolution_Session_DisposeObj( CContext sContext, void* memory )
|
|
{
|
|
StrDispose ( memory );
|
|
} /* Session_DisposeObj */
|
|
|
|
|
|
|
|
/* Can be implemented empty, if no action is required */
|
|
extern "C"
|
|
void SyncEvolution_Session_ThreadMayChangeNow( CContext sContext )
|
|
{
|
|
} /* Session_ThreadMayChangeNow */
|
|
|
|
|
|
|
|
/* This routine is implemented for debug purposes only and will NOT BE CALLED by the
|
|
* SyncML engine. Can be implemented empty, if not needed
|
|
*/
|
|
extern "C"
|
|
void SyncEvolution_Session_DispItems( CContext sContext, bool allFields, cAppCharP specificItem )
|
|
{
|
|
} /* Session_DispItems */
|
|
|
|
|
|
|
|
/* Delete a session context */
|
|
extern "C"
|
|
TSyError SyncEvolution_Session_DeleteContext( CContext sContext )
|
|
{
|
|
return LOCERR_OK;
|
|
} /* Session_DeleteContext */
|
|
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------- */
|
|
/* This is an example, how a context could be structured */
|
|
/* <aContext> will be casted to the SyncSource structure */
|
|
static SyncSource *DBC( CContext aContext ) { return (SyncSource *)aContext; }
|
|
|
|
|
|
|
|
/* -- OPEN ----------------------------------------------------------------------- */
|
|
/**
|
|
* looks up datasource and uses pointer to it as context
|
|
*
|
|
* @param aContextName name of previously instantiated SyncSource
|
|
* @retval aContext the corresponding SyncSource
|
|
*/
|
|
extern "C"
|
|
TSyError SyncEvolution_CreateContext( CContext *aContext, cAppCharP aContextName, DB_Callback aCB,
|
|
cAppCharP sDevKey,
|
|
cAppCharP sUsrKey )
|
|
{
|
|
TSyError err = LOCERR_WRONGUSAGE;
|
|
SyncSource *source = SyncContext::findSource(aContextName);
|
|
if (source) {
|
|
source->pushSynthesisAPI(aCB);
|
|
*aContext = (CContext)source;
|
|
err = LOCERR_OK;
|
|
}
|
|
SE_LOG_DEBUG(source ? source->getDisplayName() : "", "'%s' dev='%s' usr='%s' err=%d",
|
|
aContextName, sDevKey, sUsrKey, err);
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
extern "C"
|
|
uInt32 SyncEvolution_ContextSupport( CContext aContext, cAppCharP aContextRules )
|
|
{
|
|
SyncSource *source = DBC( aContext );
|
|
if (!source) {
|
|
return LOCERR_WRONGUSAGE;
|
|
}
|
|
SE_LOG_DEBUG(source->getDisplayName(), "ContextSupport %s", aContextRules);
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
extern "C"
|
|
uInt32 SyncEvolution_FilterSupport( CContext aContext, cAppCharP aFilterRules )
|
|
{
|
|
/**** CAN BE ADAPTED BY USER ****/
|
|
SyncSource *source = DBC( aContext );
|
|
if (!source) {
|
|
return LOCERR_WRONGUSAGE;
|
|
}
|
|
SE_LOG_DEBUG(source->getDisplayName(), "FilterSupport %s", aFilterRules);
|
|
return 0;
|
|
} /* FilterSupport */
|
|
|
|
|
|
|
|
/* -- ADMINISTRATION ------------------------------------------------------------ */
|
|
extern "C"
|
|
TSyError SyncEvolution_LoadAdminData( CContext aContext, cAppCharP aLocDB,
|
|
cAppCharP aRemDB, appCharP *adminData )
|
|
{
|
|
SyncSource *source = DBC( aContext );
|
|
if (!source) {
|
|
return LOCERR_WRONGUSAGE;
|
|
}
|
|
TSyError res = source->getOperations().m_loadAdminData(aLocDB, aRemDB, adminData);
|
|
SE_LOG_DEBUG(source->getDisplayName(), "LoadAdminData '%s' '%s', '%s' res=%d",
|
|
aLocDB, aRemDB, *adminData ? *adminData : "", res);
|
|
return res;
|
|
} /* LoadAdminData */
|
|
|
|
|
|
|
|
extern "C"
|
|
TSyError SyncEvolution_SaveAdminData( CContext aContext, cAppCharP adminData )
|
|
{
|
|
SyncSource *source = DBC( aContext );
|
|
if (!source) {
|
|
return LOCERR_WRONGUSAGE;
|
|
}
|
|
TSyError res = source->getOperations().m_saveAdminData(adminData);
|
|
SE_LOG_DEBUG(source->getDisplayName(), "SaveAdminData '%s' res=%d", adminData, res);
|
|
return res;
|
|
} /* SaveAdminData */
|
|
|
|
|
|
|
|
extern "C"
|
|
bool SyncEvolution_ReadNextMapItem( CContext aContext, MapID mID, bool aFirst )
|
|
{
|
|
SyncSource *source = DBC( aContext );
|
|
if (!source) {
|
|
return false;
|
|
}
|
|
bool res = false;
|
|
try {
|
|
// always reset mID, just in case that caller expects it or
|
|
// operation doesn't do it correctly
|
|
mID->localID = NULL;
|
|
mID->remoteID = NULL;
|
|
mID->ident = 0;
|
|
mID->flags = 0;
|
|
if (source->getOperations().m_readNextMapItem) {
|
|
res = source->getOperations().m_readNextMapItem(mID, aFirst);
|
|
}
|
|
} catch (...) {
|
|
res = source->handleException();
|
|
}
|
|
|
|
SE_LOG_DEBUG(source->getDisplayName(), "ReadNextMapItem '%s' + %x = '%s' + %d first=%s res=%d",
|
|
res ? NullPtrCheck(mID->localID) : "(none)",
|
|
res ? mID->ident : 0,
|
|
res ? NullPtrCheck(mID->remoteID) : "(none)",
|
|
res ? mID->flags : 0,
|
|
aFirst ? "yes" : "no",
|
|
res);
|
|
return res;
|
|
} /* ReadNextMapItem */
|
|
|
|
|
|
|
|
extern "C"
|
|
TSyError SyncEvolution_InsertMapItem( CContext aContext, cMapID mID )
|
|
{
|
|
SyncSource *source = DBC( aContext );
|
|
if (!source) {
|
|
return LOCERR_WRONGUSAGE;
|
|
}
|
|
TSyError res = source->getOperations().m_insertMapItem(mID);
|
|
SE_LOG_DEBUG(source->getDisplayName(), "InsertMapItem '%s' + %x = '%s' + %x res=%d",
|
|
NullPtrCheck(mID->localID), mID->ident,
|
|
NullPtrCheck(mID->remoteID), mID->flags,
|
|
res);
|
|
return res;
|
|
} /* InsertMapItem */
|
|
|
|
|
|
|
|
extern "C"
|
|
TSyError SyncEvolution_UpdateMapItem( CContext aContext, cMapID mID )
|
|
{
|
|
SyncSource *source = DBC( aContext );
|
|
if (!source) {
|
|
return LOCERR_WRONGUSAGE;
|
|
}
|
|
TSyError res = source->getOperations().m_updateMapItem(mID);
|
|
SE_LOG_DEBUG(source->getDisplayName(), "UpdateMapItem '%s' + %x = '%s' + %x, res=%d",
|
|
mID->localID, mID->ident,
|
|
mID->remoteID, mID->flags,
|
|
res);
|
|
|
|
return res;
|
|
} /* UpdateMapItem */
|
|
|
|
|
|
|
|
extern "C"
|
|
TSyError SyncEvolution_DeleteMapItem( CContext aContext, cMapID mID )
|
|
{
|
|
SyncSource *source = DBC( aContext );
|
|
if (!source) {
|
|
return LOCERR_WRONGUSAGE;
|
|
}
|
|
TSyError res = source->getOperations().m_deleteMapItem(mID);
|
|
SE_LOG_DEBUG(source->getDisplayName(), "DeleteMapItem '%s' + %x = '%s' + %x res=%d",
|
|
mID->localID, mID->ident,
|
|
mID->remoteID, mID->flags,
|
|
res);
|
|
return res;
|
|
} /* DeleteMapItem */
|
|
|
|
|
|
|
|
|
|
/* -- GENERAL -------------------------------------------------------------------- */
|
|
extern "C"
|
|
void SyncEvolution_DisposeObj( CContext aContext, void* memory )
|
|
{
|
|
free( memory );
|
|
} /* DisposeObj */
|
|
|
|
|
|
|
|
extern "C"
|
|
void SyncEvolution_ThreadMayChangeNow( CContext aContext )
|
|
{
|
|
} /* ThreadMayChangeNow */
|
|
|
|
|
|
|
|
extern "C"
|
|
void SyncEvolution_WriteLogData( CContext aContext, cAppCharP logData )
|
|
{
|
|
} /* WriteLogData */
|
|
|
|
|
|
|
|
/* This routine is implemented for debug purposes only and will NOT BE CALLED by the
|
|
* SyncML engine. Can be implemented empty, if not needed
|
|
*/
|
|
extern "C"
|
|
void SyncEvolution_DispItems( CContext aContext, bool allFields, cAppCharP specificItem )
|
|
{
|
|
} /* DispItems */
|
|
|
|
|
|
|
|
/* ----- "script-like" ADAPT --------- */
|
|
extern "C"
|
|
TSyError SyncEvolution_AdaptItem( CContext aContext, appCharP *aItemData1,
|
|
appCharP *aItemData2,
|
|
appCharP *aLocalVars,
|
|
uInt32 aIdentifier )
|
|
{
|
|
/**** CAN BE ADAPTED BY USER ****/
|
|
SyncSource *source = DBC( aContext );
|
|
if (!source) {
|
|
return LOCERR_WRONGUSAGE;
|
|
}
|
|
SE_LOG_DEBUG(source->getDisplayName(), "AdaptItem '%s' '%s' '%s' id=%d",
|
|
*aItemData1, *aItemData2, *aLocalVars, aIdentifier);
|
|
return LOCERR_OK;
|
|
} /* AdaptItem */
|
|
|
|
|
|
|
|
/* -- READ ---------------------------------------------------------------------- */
|
|
/**
|
|
* Start data access here and complete it in SyncEvolution_EndDataWrite().
|
|
*/
|
|
extern "C"
|
|
TSyError SyncEvolution_StartDataRead( CContext aContext, cAppCharP lastToken,
|
|
cAppCharP resumeToken )
|
|
{
|
|
SyncSource *source = DBC( aContext );
|
|
if (!source) {
|
|
return LOCERR_WRONGUSAGE;
|
|
}
|
|
TSyError res = source->getOperations().m_startDataRead(lastToken, resumeToken);
|
|
SE_LOG_DEBUG(source->getDisplayName(), "StartDataRead last='%s' resume='%s' res=%d",
|
|
lastToken, resumeToken, res);
|
|
return res;
|
|
}
|
|
|
|
|
|
extern "C"
|
|
TSyError SyncEvolution_ReadNextItemAsKey( CContext aContext, ItemID aID, KeyH aItemKey,
|
|
sInt32* aStatus, bool aFirst )
|
|
{
|
|
/**** CAN BE ADAPTED BY USER ****/
|
|
SyncSource *source = DBC( aContext );
|
|
if (!source) {
|
|
return LOCERR_WRONGUSAGE;
|
|
}
|
|
*aStatus = 0;
|
|
memset(aID, 0, sizeof(*aID));
|
|
TSyError res = source->getOperations().m_readNextItem(aID, aStatus, aFirst);
|
|
SE_LOG_DEBUG(source->getDisplayName(), "ReadNextItemAsKey aStatus=%d aID=(%s,%s) res=%d",
|
|
*aStatus, aID->item, aID->parent, res);
|
|
return res;
|
|
}
|
|
|
|
extern "C"
|
|
TSyError SyncEvolution_ReadItemAsKey( CContext aContext, cItemID aID, KeyH aItemKey )
|
|
{
|
|
SyncSource *source = DBC( aContext );
|
|
if (!source) {
|
|
return LOCERR_WRONGUSAGE;
|
|
}
|
|
TSyError res = source->getOperations().m_readItemAsKey(aID, aItemKey);
|
|
SE_LOG_DEBUG(source->getDisplayName(), "ReadItemAsKey aID=(%s,%s) res=%d",
|
|
aID->item, aID->parent, res);
|
|
return res;
|
|
}
|
|
|
|
extern "C"
|
|
sysync::TSyError SyncEvolution_ReadBlob(CContext aContext, cItemID aID, cAppCharP aBlobID,
|
|
appPointer *aBlkPtr, memSize *aBlkSize,
|
|
memSize *aTotSize,
|
|
bool aFirst, bool *aLast)
|
|
{
|
|
SyncSource *source = DBC( aContext );
|
|
if (!source) {
|
|
return LOCERR_WRONGUSAGE;
|
|
}
|
|
|
|
TSyError res;
|
|
if (source->getOperations().m_readBlob) {
|
|
try {
|
|
size_t blksize = aBlkSize ? static_cast<size_t>(*aBlkSize) : 0,
|
|
totsize = aTotSize ? static_cast<size_t>(*aTotSize) : 0;
|
|
/* Another conversion between memSize and size_t to make s390 happy */
|
|
res = source->getOperations().m_readBlob(aID, aBlobID, (void **)aBlkPtr,
|
|
aBlkSize ? &blksize : NULL,
|
|
aTotSize ? &totsize : NULL,
|
|
aFirst, aLast);
|
|
if (aBlkSize) {
|
|
*aBlkSize = blksize;
|
|
}
|
|
if (aTotSize) {
|
|
*aTotSize = totsize;
|
|
}
|
|
|
|
} catch (...) {
|
|
res = source->handleException();
|
|
}
|
|
} else {
|
|
res = LOCERR_NOTIMP;
|
|
}
|
|
|
|
SE_LOG_DEBUG(source->getDisplayName(), "ReadBlob aID=(%s,%s) aBlobID=(%s) aBlkPtr=%p aBlkSize=%lu aTotSize=%lu aFirst=%s aLast=%s res=%d",
|
|
aID->item,aID->parent, aBlobID, aBlkPtr,
|
|
aBlkSize ? (unsigned long)*aBlkSize : 0,
|
|
aTotSize ? (unsigned long)*aTotSize : 0,
|
|
aFirst? "true" : "false", *aLast ? "true" : "false", res);
|
|
return res;
|
|
} /* ReadBlob */
|
|
|
|
|
|
extern "C"
|
|
TSyError SyncEvolution_EndDataRead( CContext aContext )
|
|
{
|
|
SyncSource *source = DBC( aContext );
|
|
if (!source) {
|
|
return LOCERR_WRONGUSAGE;
|
|
}
|
|
TSyError res = source->getOperations().m_endDataRead();
|
|
SE_LOG_DEBUG(source->getDisplayName(), "EndDataRead res=%d", res);
|
|
return res;
|
|
}
|
|
|
|
|
|
|
|
|
|
/* -- WRITE --------------------------------------------------------------------- */
|
|
extern "C"
|
|
TSyError SyncEvolution_StartDataWrite( CContext aContext )
|
|
{
|
|
SyncSource *source = DBC( aContext );
|
|
if (!source) {
|
|
return LOCERR_WRONGUSAGE;
|
|
}
|
|
SE_LOG_DEBUG(source->getDisplayName(), "StartDataWrite");
|
|
return LOCERR_OK;
|
|
}
|
|
|
|
extern "C"
|
|
TSyError SyncEvolution_InsertItemAsKey( CContext aContext, KeyH aItemKey, ItemID newID )
|
|
{
|
|
/**** CAN BE ADAPTED BY USER ****/
|
|
SyncSource *source = DBC( aContext );
|
|
if (!source) {
|
|
return LOCERR_WRONGUSAGE;
|
|
}
|
|
TSyError res = source->getOperations().m_insertItemAsKey(aItemKey, newID);
|
|
SE_LOG_DEBUG(source->getDisplayName(), "InsertItemAsKey res=%d\n", res);
|
|
return res;
|
|
}
|
|
|
|
|
|
extern "C"
|
|
TSyError SyncEvolution_UpdateItemAsKey( CContext aContext, KeyH aItemKey, cItemID aID,
|
|
ItemID updID )
|
|
{
|
|
SyncSource *source = DBC( aContext );
|
|
if (!source) {
|
|
return LOCERR_WRONGUSAGE;
|
|
}
|
|
TSyError res = source->getOperations().m_updateItemAsKey(aItemKey, aID, updID);
|
|
SE_LOG_DEBUG(source->getDisplayName(), "aID=(%s,%s) res=%d",
|
|
aID->item,aID->parent, res);
|
|
return res;
|
|
}
|
|
|
|
|
|
|
|
extern "C"
|
|
TSyError SyncEvolution_MoveItem( CContext aContext, cItemID aID, cAppCharP newParID )
|
|
{
|
|
SyncSource *source = DBC( aContext );
|
|
if (!source) {
|
|
return LOCERR_WRONGUSAGE;
|
|
}
|
|
SE_LOG_DEBUG(source->getDisplayName(), "MoveItem aID=(%s,%s) => (%s,%s)",
|
|
aID->item,aID->parent, aID->item,newParID);
|
|
return LOCERR_NOTIMP;
|
|
}
|
|
|
|
|
|
|
|
extern "C"
|
|
TSyError SyncEvolution_DeleteItem( CContext aContext, cItemID aID )
|
|
{
|
|
SyncSource *source = DBC( aContext );
|
|
if (!source) {
|
|
return LOCERR_WRONGUSAGE;
|
|
}
|
|
TSyError res = source->getOperations().m_deleteItem(aID);
|
|
SE_LOG_DEBUG(source->getDisplayName(), "DeleteItem aID=(%s,%s) res=%d",
|
|
aID->item, aID->parent, res);
|
|
return res;
|
|
}
|
|
|
|
|
|
|
|
extern "C"
|
|
TSyError SyncEvolution_FinalizeLocalID( CContext aContext, cItemID aID, ItemID updID )
|
|
{
|
|
return LOCERR_NOTIMP;
|
|
}
|
|
|
|
|
|
|
|
extern "C"
|
|
TSyError SyncEvolution_DeleteSyncSet( CContext aContext )
|
|
{
|
|
SyncSource *source = DBC( aContext );
|
|
if (!source) {
|
|
return LOCERR_WRONGUSAGE;
|
|
}
|
|
SE_LOG_DEBUG(source->getDisplayName(), "DeleteSyncSet not implemented");
|
|
return LOCERR_NOTIMP;
|
|
}
|
|
|
|
|
|
extern "C"
|
|
TSyError SyncEvolution_WriteBlob(CContext aContext, cItemID aID, cAppCharP aBlobID,
|
|
appPointer aBlkPtr, memSize aBlkSize,
|
|
memSize aTotSize,
|
|
bool aFirst, bool aLast)
|
|
{
|
|
SyncSource *source = DBC( aContext );
|
|
if (!source) {
|
|
return LOCERR_WRONGUSAGE;
|
|
}
|
|
|
|
TSyError res;
|
|
if (source->getOperations().m_writeBlob) {
|
|
try {
|
|
res = source->getOperations().m_writeBlob(aID, aBlobID, aBlkPtr, aBlkSize,
|
|
aTotSize, aFirst, aLast);
|
|
} catch (...) {
|
|
res = source->handleException();
|
|
}
|
|
} else {
|
|
res = LOCERR_NOTIMP;
|
|
}
|
|
|
|
SE_LOG_DEBUG(source->getDisplayName(), "WriteBlob aID=(%s,%s) aBlobID=(%s) aBlkPtr=%p aBlkSize=%lu aTotSize=%lu aFirst=%s aLast=%s res=%d",
|
|
aID->item,aID->parent, aBlobID, aBlkPtr, (unsigned long)aBlkSize, (unsigned long)aTotSize,
|
|
aFirst ? "true" : "false", aLast ? "true" : "false", res);
|
|
return res;
|
|
} /* WriteBlob */
|
|
|
|
|
|
extern "C"
|
|
TSyError SyncEvolution_DeleteBlob( CContext aContext, cItemID aID, cAppCharP aBlobID )
|
|
{
|
|
SyncSource *source = DBC( aContext );
|
|
if (!source) {
|
|
return LOCERR_WRONGUSAGE;
|
|
}
|
|
|
|
TSyError res = source->getOperations().m_deleteBlob(aID, aBlobID);
|
|
SE_LOG_DEBUG(source->getDisplayName(), "DeleteBlob aID=(%s,%s) aBlobID=(%s) res=%d",
|
|
aID->item,aID->parent, aBlobID, res);
|
|
return res;
|
|
} /* DeleteBlob */
|
|
|
|
extern "C"
|
|
TSyError SyncEvolution_EndDataWrite( CContext aContext, bool success, appCharP *newToken )
|
|
{
|
|
SyncSource *source = DBC( aContext );
|
|
if (!source) {
|
|
return LOCERR_WRONGUSAGE;
|
|
}
|
|
TSyError res = source->getOperations().m_endDataWrite(success, newToken);
|
|
SE_LOG_DEBUG(source->getDisplayName(), "EndDataWrite %s '%s' res=%d",
|
|
success ? "COMMIT":"ROLLBACK", *newToken, res);
|
|
return res;
|
|
}
|
|
|
|
/* ----------------------------------- */
|
|
extern "C"
|
|
TSyError SyncEvolution_DeleteContext( CContext aContext )
|
|
{
|
|
/**** CAN BE ADAPTED BY USER ****/
|
|
SyncSource *source = DBC( aContext );
|
|
if (!source) {
|
|
return LOCERR_WRONGUSAGE;
|
|
}
|
|
SE_LOG_DEBUG(source->getDisplayName(), "DeleteContext");
|
|
source->popSynthesisAPI();
|
|
return LOCERR_OK;
|
|
}
|
|
|
|
SE_END_CXX
|