2005-11-26 22:16:03 +01:00
|
|
|
/*
|
2008-08-26 19:45:28 +02:00
|
|
|
* Copyright (C) 2005-2008 Patrick Ohly
|
2005-11-26 22:16:03 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef INCL_EVOLUTIONSYNCCLIENT
|
|
|
|
#define INCL_EVOLUTIONSYNCCLIENT
|
|
|
|
|
2006-04-06 19:02:43 +02:00
|
|
|
#include <config.h>
|
2005-11-26 22:16:03 +01:00
|
|
|
|
2006-08-14 22:52:34 +02:00
|
|
|
#include "EvolutionSmartPtr.h"
|
2008-03-06 23:23:13 +01:00
|
|
|
#include "SyncEvolutionConfig.h"
|
2009-02-17 12:18:15 +01:00
|
|
|
#include "SyncML.h"
|
2009-03-08 14:41:20 +01:00
|
|
|
#include "SynthesisEngine.h"
|
2006-08-14 22:52:34 +02:00
|
|
|
|
2005-11-26 22:16:03 +01:00
|
|
|
#include <string>
|
2006-04-09 13:48:11 +02:00
|
|
|
#include <set>
|
2009-03-12 09:40:20 +01:00
|
|
|
#include <map>
|
2009-02-01 16:16:16 +01:00
|
|
|
#include <stdint.h>
|
2005-11-26 22:16:03 +01:00
|
|
|
using namespace std;
|
|
|
|
|
2009-02-15 15:22:07 +01:00
|
|
|
#include <boost/smart_ptr.hpp>
|
|
|
|
|
|
|
|
namespace SyncEvolution {
|
|
|
|
class TransportAgent;
|
|
|
|
}
|
|
|
|
using namespace SyncEvolution;
|
2007-10-11 23:02:49 +02:00
|
|
|
class SourceList;
|
2009-02-01 16:16:16 +01:00
|
|
|
class EvolutionSyncSource;
|
2007-10-11 23:02:49 +02:00
|
|
|
|
2009-02-01 16:16:16 +01:00
|
|
|
/**
|
|
|
|
* This is the main class inside SyncEvolution which
|
2005-11-26 22:16:03 +01:00
|
|
|
* looks at the configuration, activates all enabled
|
|
|
|
* sources and executes the synchronization.
|
|
|
|
*
|
2009-02-01 16:16:16 +01:00
|
|
|
* All interaction with the user (reporting progress, asking for
|
|
|
|
* passwords, ...) is done via virtual methods. The default
|
|
|
|
* implementation of those uses stdin/out.
|
|
|
|
*
|
2005-11-26 22:16:03 +01:00
|
|
|
*/
|
2009-02-17 12:18:15 +01:00
|
|
|
class EvolutionSyncClient : public EvolutionSyncConfig, public ConfigUserInterface {
|
2005-11-26 22:16:03 +01:00
|
|
|
const string m_server;
|
2006-04-09 13:48:11 +02:00
|
|
|
const set<string> m_sources;
|
2006-08-06 09:56:41 +02:00
|
|
|
const bool m_doLogging;
|
2007-11-08 22:22:52 +01:00
|
|
|
bool m_quiet;
|
2005-11-26 22:16:03 +01:00
|
|
|
|
2007-10-11 23:02:49 +02:00
|
|
|
/**
|
|
|
|
* a pointer to the active SourceList instance if one exists;
|
|
|
|
* used for error handling in throwError() on the iPhone
|
|
|
|
*/
|
|
|
|
static SourceList *m_sourceListPtr;
|
|
|
|
|
2009-02-01 16:16:16 +01:00
|
|
|
/**
|
|
|
|
* Connection to the Synthesis engine. Always valid in a
|
|
|
|
* constructed EvolutionSyncClient. Use getEngine() to reference
|
|
|
|
* it.
|
|
|
|
*/
|
2009-03-08 14:41:20 +01:00
|
|
|
SharedEngine m_engine;
|
2009-02-01 16:16:16 +01:00
|
|
|
|
2009-03-11 15:01:07 +01:00
|
|
|
/**
|
|
|
|
* Synthesis session handle. Only valid while sync is running.
|
|
|
|
*/
|
|
|
|
SharedSession m_session;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* installs session in EvolutionSyncClient and removes it again
|
|
|
|
* when going out of scope
|
|
|
|
*/
|
|
|
|
class SessionSentinel {
|
|
|
|
EvolutionSyncClient &m_client;
|
|
|
|
public:
|
|
|
|
SessionSentinel(EvolutionSyncClient &client, SharedSession &session) :
|
|
|
|
m_client(client) {
|
|
|
|
m_client.m_session = session;
|
|
|
|
}
|
|
|
|
~SessionSentinel() {
|
|
|
|
m_client.m_session.reset();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2005-11-26 22:16:03 +01:00
|
|
|
public:
|
|
|
|
/**
|
|
|
|
* @param server identifies the server config to be used
|
2006-08-06 09:56:41 +02:00
|
|
|
* @param doLogging write additional log and datatbase files about the sync
|
2005-11-26 22:16:03 +01:00
|
|
|
*/
|
2006-08-06 09:56:41 +02:00
|
|
|
EvolutionSyncClient(const string &server,
|
|
|
|
bool doLogging = false,
|
2008-03-06 23:23:13 +01:00
|
|
|
const set<string> &sources = set<string>());
|
2005-11-26 22:16:03 +01:00
|
|
|
~EvolutionSyncClient();
|
|
|
|
|
2007-11-08 22:22:52 +01:00
|
|
|
bool getQuiet() { return m_quiet; }
|
|
|
|
void setQuiet(bool quiet) { m_quiet = quiet; }
|
|
|
|
|
2005-11-26 22:16:03 +01:00
|
|
|
/**
|
2006-03-19 22:37:30 +01:00
|
|
|
* Executes the sync, throws an exception in case of failure.
|
|
|
|
* Handles automatic backups and report generation.
|
2009-02-19 14:53:55 +01:00
|
|
|
*
|
|
|
|
* @retval complete sync report, skipped if NULL
|
|
|
|
* @return overall sync status, for individual sources see report
|
2005-11-26 22:16:03 +01:00
|
|
|
*/
|
2009-02-19 14:53:55 +01:00
|
|
|
SyncMLStatus sync(SyncReport *report = NULL);
|
2006-09-29 01:02:43 +02:00
|
|
|
|
2007-11-08 22:22:52 +01:00
|
|
|
/**
|
|
|
|
* Determines the log directory of the previous sync (either in
|
|
|
|
* temp or logdir) and shows changes since then.
|
|
|
|
*/
|
|
|
|
void status();
|
|
|
|
|
2007-10-11 23:02:49 +02:00
|
|
|
/**
|
|
|
|
* throws a runtime_error with the given string
|
|
|
|
* or (on the iPhone, where exception handling is not
|
|
|
|
* supported by the toolchain) prints an error directly
|
|
|
|
* and aborts
|
|
|
|
*
|
2008-08-09 12:26:52 +02:00
|
|
|
* output format: <error>
|
|
|
|
*
|
2007-10-11 23:02:49 +02:00
|
|
|
* @param error a string describing the error
|
|
|
|
*/
|
|
|
|
static void throwError(const string &error);
|
|
|
|
|
2008-08-09 12:26:52 +02:00
|
|
|
/**
|
|
|
|
* throw an exception after an operation failed and
|
|
|
|
* remember that this instance has failed
|
|
|
|
*
|
|
|
|
* output format: <action>: <error string>
|
|
|
|
*
|
|
|
|
* @Param action a string describing the operation or object involved
|
|
|
|
* @param error the errno error code for the failure
|
|
|
|
*/
|
|
|
|
static void throwError(const string &action, int error);
|
|
|
|
|
2007-11-03 18:07:42 +01:00
|
|
|
/**
|
|
|
|
* An error handler which prints the error message and then
|
|
|
|
* stops the program. Never returns.
|
|
|
|
*
|
|
|
|
* The API was chosen so that it can be used as libebook/libecal
|
|
|
|
* "backend-dies" signal handler.
|
|
|
|
*/
|
|
|
|
static void fatalError(void *object, const char *error);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* When using Evolution this function starts a background thread
|
|
|
|
* which drives the default event loop. Without that loop
|
|
|
|
* "backend-died" signals are not delivered. The problem with
|
|
|
|
* the thread is that it seems to interfere with gconf startup
|
|
|
|
* when added to the main() function of syncevolution. Therefore
|
|
|
|
* it is started by EvolutionSyncSource::beginSync() (for unit
|
|
|
|
* testing of sync sources) and EvolutionSyncClient::sync() (for
|
|
|
|
* normal operation).
|
|
|
|
*/
|
|
|
|
static void startLoopThread();
|
|
|
|
|
2009-02-06 17:52:18 +01:00
|
|
|
/**
|
|
|
|
* Finds activated sync source by name. May return NULL
|
|
|
|
* if no such sync source was defined or is not currently
|
|
|
|
* instantiated. Pointer remains valid throughout the sync
|
|
|
|
* session. Called by Synthesis DB plugin to find active
|
|
|
|
* sources.
|
|
|
|
*
|
|
|
|
* @TODO: roll SourceList into EvolutionSyncClient and
|
|
|
|
* make this non-static
|
|
|
|
*/
|
|
|
|
static EvolutionSyncSource *findSource(const char *name);
|
2008-03-06 23:23:13 +01:00
|
|
|
|
2008-06-15 23:31:36 +02:00
|
|
|
/**
|
|
|
|
* intercept config filters
|
|
|
|
*
|
|
|
|
* This call removes the "sync" source property and remembers
|
|
|
|
* it separately because it has to be applied to only the active
|
|
|
|
* sync sources; the generic config handling code would apply
|
|
|
|
* it to all sources.
|
|
|
|
*/
|
|
|
|
virtual void setConfigFilter(bool sync, const FilterConfigNode::ConfigFilter &filter);
|
|
|
|
|
2009-03-08 14:41:20 +01:00
|
|
|
SharedEngine getEngine() { return m_engine; }
|
|
|
|
const SharedEngine getEngine() const { return m_engine; }
|
2009-03-11 15:01:07 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Handle for active session, may be NULL.
|
|
|
|
*/
|
|
|
|
SharedSession getSession() { return m_session; }
|
|
|
|
|
|
|
|
protected:
|
2009-03-08 14:41:20 +01:00
|
|
|
SharedEngine swapEngine(SharedEngine newengine) {
|
|
|
|
SharedEngine oldengine = m_engine;
|
2009-02-17 12:18:15 +01:00
|
|
|
m_engine = newengine;
|
|
|
|
return oldengine;
|
|
|
|
}
|
|
|
|
|
2009-03-12 09:40:20 +01:00
|
|
|
/**
|
|
|
|
* Maps from source name to sync mode with one default
|
|
|
|
* for all sources which don't have a specific entry
|
|
|
|
* in the hash.
|
|
|
|
*/
|
|
|
|
class SyncModes : public std::map<string, SyncMode> {
|
|
|
|
SyncMode m_syncMode;
|
|
|
|
|
|
|
|
public:
|
|
|
|
SyncModes(SyncMode syncMode = SYNC_NONE) :
|
|
|
|
m_syncMode(syncMode)
|
|
|
|
{}
|
|
|
|
|
|
|
|
SyncMode getDefaultSyncMode() { return m_syncMode; }
|
|
|
|
void setDefaultMode(SyncMode syncMode) { m_syncMode = syncMode; }
|
|
|
|
|
|
|
|
SyncMode getSyncMode(const string &sourceName) const {
|
|
|
|
const_iterator it = find(sourceName);
|
|
|
|
if (it == end()) {
|
|
|
|
return m_syncMode;
|
|
|
|
} else {
|
|
|
|
return it->second;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void setSyncMode(const string &sourceName, SyncMode syncMode) {
|
|
|
|
(*this)[sourceName] = syncMode;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* An utility function which can be used as part of
|
|
|
|
* prepare() below to reconfigure the sync mode that
|
|
|
|
* is going to be used for the active sync session.
|
|
|
|
* SYNC_NONE as mode means that the sync mode of the
|
|
|
|
* source is not modified and the default from the
|
|
|
|
* configuration is used.
|
|
|
|
*/
|
|
|
|
void setSyncModes(const std::vector<EvolutionSyncSource *> &sources,
|
|
|
|
const SyncModes &modes);
|
|
|
|
|
2009-02-06 17:52:18 +01:00
|
|
|
/**
|
|
|
|
* Return skeleton Synthesis client XML configuration.
|
|
|
|
*
|
|
|
|
* If it contains a <datastore/> element, then that element will
|
|
|
|
* be replaced by the configurations of all active sync
|
|
|
|
* sources. Otherwise the configuration is used as-is.
|
|
|
|
*
|
|
|
|
* The default implementation of this function takes the configuration from
|
|
|
|
* (in this order):
|
|
|
|
* - ./syncevolution.xml
|
|
|
|
* - <server config dir>/syncevolution.xml
|
|
|
|
* - built-in default
|
|
|
|
*
|
|
|
|
* @retval xml is filled with Synthesis client config which may hav <datastore/>
|
|
|
|
* @retval configname a string describing where the config came from
|
|
|
|
*/
|
|
|
|
virtual void getConfigTemplateXML(string &xml, string &configname);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return complete Synthesis XML configuration.
|
|
|
|
*
|
|
|
|
* Calls getConfigTemplateXML(), then fills in
|
|
|
|
* sync source XML fragments if necessary.
|
|
|
|
*
|
|
|
|
* @retval xml is filled with complete Synthesis client config
|
|
|
|
* @retval configname a string describing where the config came from
|
|
|
|
*/
|
|
|
|
virtual void getConfigXML(string &xml, string &configname);
|
|
|
|
|
2009-02-01 16:16:16 +01:00
|
|
|
/**
|
|
|
|
* A helper function which interactively asks the user for
|
|
|
|
* a certain password. May throw errors.
|
|
|
|
*
|
|
|
|
* The default implementation uses stdin/stdout to communicate
|
|
|
|
* with the user.
|
|
|
|
*
|
|
|
|
* @param descr A simple string explaining what the password is needed for,
|
|
|
|
* e.g. "SyncML server". Has to be unique and understandable
|
|
|
|
* by the user.
|
|
|
|
* @return entered password
|
|
|
|
*/
|
|
|
|
virtual string askPassword(const string &descr);
|
|
|
|
|
2009-02-19 10:52:35 +01:00
|
|
|
/**
|
|
|
|
* Callback for derived classes: called after initializing the
|
|
|
|
* client, but before doing anything with its configuration.
|
|
|
|
* Can be used to override the client configuration.
|
|
|
|
*/
|
|
|
|
virtual void prepare() {}
|
|
|
|
|
2006-09-29 01:02:43 +02:00
|
|
|
/**
|
|
|
|
* Callback for derived classes: called after setting up the client's
|
2009-02-19 10:52:35 +01:00
|
|
|
* and sources' configuration. Can be used to reconfigure sources before
|
2006-09-29 01:02:43 +02:00
|
|
|
* actually starting the synchronization.
|
|
|
|
*
|
|
|
|
* @param sources a NULL terminated array of all active sources
|
|
|
|
*/
|
2009-02-17 14:24:07 +01:00
|
|
|
virtual void prepare(const std::vector<EvolutionSyncSource *> &sources) {}
|
2007-11-08 22:22:52 +01:00
|
|
|
|
2009-02-15 15:22:07 +01:00
|
|
|
/**
|
|
|
|
* instantiate transport agent
|
|
|
|
*
|
|
|
|
* Called by engine when it needs to do HTTP POST requests. The
|
|
|
|
* transport agent will be used throughout the sync session and
|
|
|
|
* unref'ed when no longer needed. At most one agent will be
|
|
|
|
* requested at a time. The transport agent is intentionally
|
|
|
|
* returned as a Boost shared pointer so that a pointer to a
|
|
|
|
* class with a different life cycle is possible, either by
|
|
|
|
* keeping a reference or by returning a shared_ptr where the
|
|
|
|
* destructor doesn't do anything.
|
|
|
|
*
|
|
|
|
* The default implementation instantiates one of the builtin
|
|
|
|
* transport agents, depending on how it was compiled.
|
|
|
|
*
|
|
|
|
* @return transport agent
|
|
|
|
*/
|
|
|
|
virtual boost::shared_ptr<TransportAgent> createTransportAgent();
|
|
|
|
|
2009-02-01 16:16:16 +01:00
|
|
|
/**
|
|
|
|
* display a text message from the server
|
|
|
|
*
|
|
|
|
* Not really used by SyncML servers. Could be displayed in a
|
|
|
|
* modal dialog.
|
|
|
|
*
|
|
|
|
* @param message string with local encoding, possibly with line breaks
|
|
|
|
*/
|
|
|
|
virtual void displayServerMessage(const string &message);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* display general sync session progress
|
|
|
|
*
|
|
|
|
* @param type PEV_*, see "synthesis/engine_defs.h"
|
|
|
|
* @param extra1 extra information depending on type
|
|
|
|
* @param extra2 extra information depending on type
|
|
|
|
* @param extra3 extra information depending on type
|
|
|
|
*/
|
2009-02-23 16:36:17 +01:00
|
|
|
virtual void displaySyncProgress(sysync::TProgressEventEnum type,
|
2009-02-01 16:16:16 +01:00
|
|
|
int32_t extra1, int32_t extra2, int32_t extra3);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* display sync source specific progress
|
|
|
|
*
|
|
|
|
* @param type PEV_*, see "synthesis/engine_defs.h"
|
|
|
|
* @param source source which is the target of the event
|
|
|
|
* @param extra1 extra information depending on type
|
|
|
|
* @param extra2 extra information depending on type
|
|
|
|
* @param extra3 extra information depending on type
|
|
|
|
*/
|
2009-02-23 16:36:17 +01:00
|
|
|
virtual void displaySourceProgress(sysync::TProgressEventEnum type,
|
2009-02-01 16:16:16 +01:00
|
|
|
EvolutionSyncSource &source,
|
|
|
|
int32_t extra1, int32_t extra2, int32_t extra3);
|
|
|
|
|
2009-03-11 12:59:25 +01:00
|
|
|
/**
|
|
|
|
* Called to find out whether user wants to abort sync.
|
|
|
|
*
|
|
|
|
* Will be called regularly. Once it has flagged an abort, all
|
|
|
|
* following calls should return the same value. When the engine
|
|
|
|
* aborts, the sync is shut down as soon as possible. The next
|
|
|
|
* sync most likely has to be done in slow mode, so don't do this
|
|
|
|
* unless absolutely necessary.
|
|
|
|
*
|
|
|
|
* @return true if user wants to abort
|
|
|
|
*/
|
|
|
|
virtual bool checkForAbort() { return false; }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Called to find out whether user wants to suspend sync.
|
|
|
|
*
|
|
|
|
* Same as checkForAbort(), but the session is finished
|
|
|
|
* gracefully so that it can be resumed.
|
|
|
|
*/
|
|
|
|
virtual bool checkForSuspend() { return false; }
|
|
|
|
|
2007-11-08 22:22:52 +01:00
|
|
|
private:
|
|
|
|
/**
|
|
|
|
* the code common to init() and status():
|
|
|
|
* populate source list with active sources and open
|
|
|
|
* them for reading without changing their state yet
|
|
|
|
*/
|
2008-03-06 23:23:13 +01:00
|
|
|
void initSources(SourceList &sourceList);
|
2008-06-15 23:31:36 +02:00
|
|
|
|
2009-02-19 14:53:55 +01:00
|
|
|
/**
|
|
|
|
* Fills the report with information about all sources and
|
|
|
|
* the client itself.
|
|
|
|
*/
|
|
|
|
void createSyncReport(SyncReport &report, SourceList &sourceList) const;
|
|
|
|
|
2009-02-01 16:16:16 +01:00
|
|
|
/**
|
|
|
|
* sets up Synthesis session and executes it
|
|
|
|
*/
|
2009-02-20 19:20:08 +01:00
|
|
|
SyncMLStatus doSync();
|
2009-02-01 16:16:16 +01:00
|
|
|
|
2008-06-15 23:31:36 +02:00
|
|
|
/**
|
|
|
|
* override sync mode of all active sync sources if set
|
|
|
|
*/
|
|
|
|
string m_overrideMode;
|
2005-11-26 22:16:03 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif // INCL_EVOLUTIONSYNCCLIENT
|