SyncML: workarounds for broken peers

Some peers have problems with meta data (CtCap, old Nokia phones) and
the sync mode extensions required for advertising the restart
capability (Oracle Beehive).

Because the problem occurs when SyncEvolution contacts the peers
before it gets the device information from the peer, dynamic rules
based on the peer identifiers cannot be used. Instead the local config
must already disable these extra features in advance.

The "SyncMLVersion" property gets extended for this. Instead of just
"SyncMLVersion = 1.0" (as before) it now becomes possible to say
"SyncMLVersion = 1.0, noctcap, norestart".

"noctcap" disables sending CtCap. "norestart" disables the sync mode
extensions and thus doing multiple sync cycles in the same session
(used between SyncEvolution instances in some cases to get client and
server into sync in one session).

Both keywords are case-insensitive. There's no error checking for
typos, so beware!

The "SyncMLVersion" property was chosen because it was already in use
for configuring SyncML compatibility aspects and adding a new property
would have been harder.
This commit is contained in:
Patrick Ohly 2012-11-06 10:49:26 +01:00
parent f0308a9386
commit a0375e0160
3 changed files with 52 additions and 19 deletions

View File

@ -1335,21 +1335,28 @@ static SafeConfigProperty syncPropPeerName("PeerName",
"An arbitrary name for the peer referenced by this config.\n"
"Might be used by a GUI. The command line tool always uses the\n"
"the configuration name.");
static StringConfigProperty syncPropSyncMLVersion("SyncMLVersion",
"On a client, the latest commonly supported SyncML version \n"
"is used when contacting a server. one of '1.0/1.1/1.2' can\n"
"be used to pick a specific version explicitly.\n"
"\n"
"On a server, this option controls what kind of Server Alerted \n"
"Notification is sent to the client to start a synchronization.\n"
"By default, first the format from 1.2 is tried, then in case \n"
"of failure, the older one from 1.1. 1.2/1.1 can be choosen \n"
"explictely which disables the automatism\n",
"",
"",
Values() +
Aliases("") + Aliases("1.0") + Aliases ("1.1") + Aliases ("1.2")
);
static ConfigProperty syncPropSyncMLVersion("SyncMLVersion",
"On a client, the latest commonly supported SyncML version\n"
"is used when contacting a server. One of '1.0/1.1/1.2' can\n"
"be used to pick a specific version explicitly.\n"
"\n"
"On a server, this option controls what kind of Server Alerted\n"
"Notification is sent to the client to start a synchronization.\n"
"By default, first the format from 1.2 is tried, then in case\n"
"of failure, the older one from 1.1. 1.2/1.1 can be set\n"
"explicitly, which disables the automatism.\n"
"\n"
"Instead or in adddition to the version, several keywords can\n"
"be set in this property (separated by spaces or commas):\n"
"\n"
"- NOCTCAP = avoid sending CtCap meta information\n"
"- NORESTART = disable the sync mode extension that SyncEvolution\n"
" client and server use to negotiate whether both sides support\n"
" running multiple sync iterations in the same session\n"
"\n"
"Setting these flags should only be necessary as workaround for\n"
"broken peers.\n"
);
static ConfigProperty syncPropRemoteIdentifier("remoteIdentifier",
"the identifier sent to the remote peer for a server initiated sync.\n"
@ -1937,8 +1944,27 @@ void SyncConfig::setRemoteIdentifier (const string &value, bool temporarily) { r
InitState<bool> SyncConfig::getPeerIsClient() const { return syncPropPeerIsClient.getPropertyValue(*getNode(syncPropPeerIsClient)); }
void SyncConfig::setPeerIsClient(bool value, bool temporarily) { syncPropPeerIsClient.setProperty(*getNode(syncPropPeerIsClient), value, temporarily); }
InitStateString SyncConfig::getSyncMLVersion() const { return syncPropSyncMLVersion.getProperty(*getNode(syncPropSyncMLVersion)); }
void SyncConfig::setSyncMLVersion(const string &value, bool temporarily) { syncPropSyncMLVersion.setProperty(*getNode(syncPropSyncMLVersion), value, temporarily); }
InitStateString SyncConfig::getSyncMLVersion() const {
InitState< std::set<std::string> > flags = getSyncMLFlags();
static const char * const versions[] = { "1.2", "1.1", "1.0" };
BOOST_FOREACH (const char *version, versions) {
if (flags.find(version) != flags.end()) {
return InitStateString(version, flags.wasSet());
}
}
return InitStateString("", flags.wasSet());
}
InitState< std::set<std::string> > SyncConfig::getSyncMLFlags() const {
InitStateString value = syncPropSyncMLVersion.getProperty(*getNode(syncPropSyncMLVersion));
std::list<std::string> keywords;
boost::split(keywords, value, boost::is_any_of(" ,"));
std::set<std::string> flags;
BOOST_FOREACH (std::string &keyword, keywords) {
boost::to_lower(keyword);
flags.insert(keyword);
}
return InitState< std::set<std::string> >(flags, value.wasSet());
}
InitStateString SyncConfig::getUserPeerName() const { return syncPropPeerName.getProperty(*getNode(syncPropPeerName)); }
void SyncConfig::setUserPeerName(const InitStateString &name) { syncPropPeerName.setProperty(*getNode(syncPropPeerName), name); }

View File

@ -1492,8 +1492,12 @@ class SyncConfig {
virtual void setRemoteIdentifier (const std::string &value, bool temporaritly = false);
virtual InitState<bool> getPeerIsClient () const;
virtual void setPeerIsClient (bool value, bool temporarily = false);
/** the 1.0/1.1/1.2 part of the SyncMLVersion property */
virtual InitStateString getSyncMLVersion() const;
virtual void setSyncMLVersion (const std::string &value, bool temporarily = false);
/** all flags that are set in the SyncMLVersion property, including the 1.0/1.1/1.2 versions */
virtual InitState< std::set<std::string> > getSyncMLFlags() const;
/**
* An arbitrary name assigned to the peer configuration,

View File

@ -2340,7 +2340,9 @@ void SyncContext::getConfigXML(string &xml, string &configname)
unsigned long hash = 0;
const char *noctcap = getenv("SYNCEVOLUTION_NOCTCAP");
std::set<std::string> flags = getSyncMLFlags();
bool noctcap = flags.find("noctcap") != flags.end();
bool norestart = flags.find("norestart") != flags.end();
const char *sessioninitscript =
" <sessioninitscript><![CDATA[\n"
" // these variables are possibly modified by rule scripts\n"
@ -2400,6 +2402,7 @@ void SyncContext::getConfigXML(string &xml, string &configname)
<<syncMLVersion.c_str()<<"</defaultsyncmlversion>\n";
}
clientorserver << " <syncmodeextensions>" << (norestart ? "no" : "yes" ) << "</syncmodeextensions>\n";
if (noctcap) {
clientorserver << " <showctcapproperties>no</showctcapproperties>\n"
"\n";