00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "SyncEvolutionConfig.h"
00021 #include "EvolutionSyncSource.h"
00022 #include "EvolutionSyncClient.h"
00023 #include "FileConfigTree.h"
00024 #include "VolatileConfigTree.h"
00025 #include "VolatileConfigNode.h"
00026
00027 #include <boost/foreach.hpp>
00028 #include <iterator>
00029 #include <algorithm>
00030 #include <functional>
00031
00032 #include <unistd.h>
00033 #include "config.h"
00034
00035 void ConfigProperty::splitComment(const string &comment, list<string> &commentLines)
00036 {
00037 size_t start = 0;
00038
00039 while (true) {
00040 size_t end = comment.find('\n', start);
00041 if (end == comment.npos) {
00042 commentLines.push_back(comment.substr(start));
00043 break;
00044 } else {
00045 commentLines.push_back(comment.substr(start, end - start));
00046 start = end + 1;
00047 }
00048 }
00049 }
00050
00051 void ConfigProperty::throwValueError(const ConfigNode &node, const string &name, const string &value, const string &error) const
00052 {
00053 EvolutionSyncClient::throwError(node.getName() + ": " + name + " = " + value + ": " + error);
00054 }
00055
00056 EvolutionSyncConfig::EvolutionSyncConfig() :
00057 m_oldLayout(false)
00058 {
00059 m_tree.reset(new VolatileConfigTree());
00060 m_configNode.reset(new VolatileConfigNode());
00061 m_hiddenNode = m_configNode;
00062 }
00063
00064 EvolutionSyncConfig::EvolutionSyncConfig(const string &server,
00065 boost::shared_ptr<ConfigTree> tree) :
00066 m_server(server),
00067 m_oldLayout(false)
00068 {
00069 string root;
00070
00071 if (tree.get() != NULL) {
00072 m_tree = tree;
00073 } else {
00074
00075 string confname;
00076 root = getOldRoot() + "/" + server;
00077 confname = root + "/spds/syncml/config.txt";
00078 if (!access(confname.c_str(), F_OK)) {
00079 m_oldLayout = true;
00080 } else {
00081 root = getNewRoot() + "/" + server;
00082 }
00083 m_tree.reset(new FileConfigTree(root, m_oldLayout));
00084 }
00085
00086 string path(m_oldLayout ? "spds/syncml" : "");
00087 boost::shared_ptr<ConfigNode> node;
00088 node = m_tree->open(path, ConfigTree::visible);
00089 m_configNode.reset(new FilterConfigNode(node));
00090 m_hiddenNode = m_tree->open(path, ConfigTree::hidden);
00091 }
00092
00093 string EvolutionSyncConfig::getRootPath() const
00094 {
00095 return m_tree->getRootPath();
00096 }
00097
00098 static void addServers(const string &root, EvolutionSyncConfig::ServerList &res) {
00099 FileConfigTree tree(root, false);
00100 list<string> servers = tree.getChildren("");
00101 BOOST_FOREACH(const string &server, servers) {
00102 res.push_back(pair<string, string>(server, root + "/" + server));
00103 }
00104 }
00105
00106 EvolutionSyncConfig::ServerList EvolutionSyncConfig::getServers()
00107 {
00108 ServerList res;
00109
00110 addServers(getOldRoot(), res);
00111 addServers(getNewRoot(), res);
00112
00113 return res;
00114 }
00115
00116 static const InitList< pair<string, string> > serverTemplates =
00117 InitList< pair<string, string> >(pair<string, string>("funambol", "http://my.funambol.com")) +
00118 pair<string, string>("scheduleworld", "http://sync.scheduleworld.com") +
00119 pair<string, string>("synthesis", "http://www.synthesis.ch") +
00120 pair<string, string>("memotoo", "http://www.memotoo.com");
00121
00122 EvolutionSyncConfig::ServerList EvolutionSyncConfig::getServerTemplates()
00123 {
00124 return serverTemplates;
00125 }
00126
00127 boost::shared_ptr<EvolutionSyncConfig> EvolutionSyncConfig::createServerTemplate(const string &server)
00128 {
00129 boost::shared_ptr<ConfigTree> tree(new FileConfigTree("/dev/null", false));
00130 boost::shared_ptr<EvolutionSyncConfig> config(new EvolutionSyncConfig(server, tree));
00131 boost::shared_ptr<PersistentEvolutionSyncSourceConfig> source;
00132
00133 config->setDefaults();
00134
00135
00136
00137
00138 config->setDevID(string("sc-pim-") + UUID());
00139 config->setSourceDefaults("addressbook");
00140 config->setSourceDefaults("calendar");
00141 config->setSourceDefaults("todo");
00142 config->setSourceDefaults("memo");
00143
00144
00145 source = config->getSyncSourceConfig("addressbook");
00146 source->setSourceType("addressbook");
00147 source->setURI("card");
00148 source = config->getSyncSourceConfig("calendar");
00149 source->setSourceType("calendar");
00150 source->setURI("event");
00151 source = config->getSyncSourceConfig("todo");
00152 source->setSourceType("todo");
00153 source->setURI("task");
00154 source = config->getSyncSourceConfig("memo");
00155 source->setSourceType("memo");
00156 source->setURI("note");
00157
00158 if (boost::iequals(server, "scheduleworld") ||
00159 boost::iequals(server, "default")) {
00160 config->setSyncURL("http://sync.scheduleworld.com/funambol/ds");
00161 source = config->getSyncSourceConfig("addressbook");
00162 source->setURI("card3");
00163 source->setSourceType("addressbook:text/vcard");
00164 source = config->getSyncSourceConfig("calendar");
00165 source->setURI("cal2");
00166 source = config->getSyncSourceConfig("todo");
00167 source->setURI("task2");
00168 source = config->getSyncSourceConfig("memo");
00169 source->setURI("note");
00170 } else if (boost::iequals(server, "funambol")) {
00171 config->setSyncURL("http://my.funambol.com/sync");
00172 source = config->getSyncSourceConfig("calendar");
00173 source->setSync("disabled");
00174 source = config->getSyncSourceConfig("todo");
00175 source->setSync("disabled");
00176 } else if (boost::iequals(server, "synthesis")) {
00177 config->setSyncURL("http://www.synthesis.ch/sync");
00178 source = config->getSyncSourceConfig("addressbook");
00179 source->setURI("contacts");
00180 source = config->getSyncSourceConfig("calendar");
00181 source->setURI("events");
00182 source->setSync("disabled");
00183 source = config->getSyncSourceConfig("todo");
00184 source->setURI("tasks");
00185 source->setSync("disabled");
00186 source = config->getSyncSourceConfig("memo");
00187 source->setURI("notes");
00188 } else if (boost::iequals(server, "memotoo")) {
00189 config->setSyncURL("http://sync.memotoo.com/syncML");
00190 source = config->getSyncSourceConfig("addressbook");
00191 source->setURI("con");
00192 source = config->getSyncSourceConfig("calendar");
00193 source->setURI("cal");
00194 source = config->getSyncSourceConfig("todo");
00195 source->setURI("task");
00196 source = config->getSyncSourceConfig("memo");
00197 source->setURI("note");
00198 } else {
00199 config.reset();
00200 }
00201
00202 return config;
00203 }
00204
00205 bool EvolutionSyncConfig::exists() const
00206 {
00207 return m_configNode->exists();
00208 }
00209
00210 void EvolutionSyncConfig::flush()
00211 {
00212 m_tree->flush();
00213 }
00214
00215 boost::shared_ptr<PersistentEvolutionSyncSourceConfig> EvolutionSyncConfig::getSyncSourceConfig(const string &name)
00216 {
00217 SyncSourceNodes nodes = getSyncSourceNodes(name);
00218 return boost::shared_ptr<PersistentEvolutionSyncSourceConfig>(new PersistentEvolutionSyncSourceConfig(name, nodes));
00219 }
00220
00221 list<string> EvolutionSyncConfig::getSyncSources() const
00222 {
00223 return m_tree->getChildren(m_oldLayout ? "spds/sources" : "sources");
00224 }
00225
00226 SyncSourceNodes EvolutionSyncConfig::getSyncSourceNodes(const string &name,
00227 const string &changeId)
00228 {
00229 boost::shared_ptr<FilterConfigNode> configNode;
00230 boost::shared_ptr<ConfigNode> hiddenNode,
00231 trackingNode;
00232
00233 boost::shared_ptr<ConfigNode> node;
00234 string path = string(m_oldLayout ? "spds/sources/" : "sources/") + name;
00235
00236 node = m_tree->open(path, ConfigTree::visible);
00237 configNode.reset(new FilterConfigNode(node, m_sourceFilter));
00238 hiddenNode = m_tree->open(path, ConfigTree::hidden);
00239 trackingNode = m_tree->open(path, ConfigTree::other, changeId);
00240
00241 return SyncSourceNodes(configNode, hiddenNode, trackingNode);
00242 }
00243
00244 ConstSyncSourceNodes EvolutionSyncConfig::getSyncSourceNodes(const string &name,
00245 const string &changeId) const
00246 {
00247 return const_cast<EvolutionSyncConfig *>(this)->getSyncSourceNodes(name, changeId);
00248 }
00249
00250
00251 static ConfigProperty syncPropSyncURL("syncURL",
00252 "the base URL of the SyncML server which is to be used for SyncML;\n"
00253 "some examples:\n"
00254 "- http://my.funambol.com/sync\n"
00255 "- http://sync.scheduleworld.com/funambol/ds\n"
00256 "- http://www.synthesis.ch/sync\n");
00257 static ConfigProperty syncPropDevID("deviceId",
00258 "The SyncML server gets this string and will use it to keep track of\n"
00259 "changes that still need to be synchronized with this particular\n"
00260 "client; it must be set to something unique (like the pseudo-random\n"
00261 "string created automatically for new configurations) among all clients\n"
00262 "accessing the same server.\n"
00263 "myFUNAMBOL also requires that the string starts with sc-pim-");
00264 static ConfigProperty syncPropUsername("username",
00265 "user name used for authorization with the SyncML server",
00266 "your SyncML server account name");
00267 static PasswordConfigProperty syncPropPassword("password",
00268 "password used for authorization with the SyncML server;\n"
00269 "in addition to specifying it directly as plain text, it can\n"
00270 "also be read from the standard input or from an environment\n"
00271 "variable of your choice:\n"
00272 " plain text: password = <insert your password here>\n"
00273 " ask: password = -\n"
00274 "env variable: password = ${<name of environment variable>}\n",
00275 "your SyncML server password");
00276 static BoolConfigProperty syncPropUseProxy("useProxy",
00277 "set to T to enable an HTTP proxy");
00278 static ConfigProperty syncPropProxyHost("proxyHost",
00279 "proxy URL (http://<host>:<port>)");
00280 static ConfigProperty syncPropProxyUsername("proxyUsername",
00281 "authentication for proxy: username");
00282 static PasswordConfigProperty syncPropProxyPassword("proxyPassword",
00283 "proxy password, can be specified in different ways,\n"
00284 "see SyncML server password for details\n");
00285 static StringConfigProperty syncPropClientAuthType("clientAuthType",
00286 "- empty or \"md5\" for secure method (recommended)\n"
00287 "- \"basic\" for insecure method",
00288 "md5",
00289 Values() +
00290 (Aliases("syncml:auth-basic") + "basic") +
00291 (Aliases("syncml:auth-md5") + "md5" + ""));
00292 static ULongConfigProperty syncPropMaxMsgSize("maxMsgSize",
00293 "Support for large objects and limiting the message size was added in\n"
00294 "SyncEvolution 0.5, but still disabled in the example configurations\n"
00295 "of that version. Some servers had problems with that configuration,\n"
00296 "so now both features are enabled by default and it is recommended\n"
00297 "to update existing configurations.\n"
00298 "\n"
00299 "The maximum size of each message can be set (maxMsgSize) and the\n"
00300 "server can be told to never sent items larger than a certain\n"
00301 "threshold (maxObjSize). Presumably the server has to truncate or\n"
00302 "skip larger items. Finally the client and server may be given the\n"
00303 "permission to transmit large items in multiple messages (loSupport =\n"
00304 "large object support).",
00305 "8192");
00306 static BoolConfigProperty syncPropLoSupport("loSupport", "", "T");
00307 static UIntConfigProperty syncPropMaxObjSize("maxObjSize", "", "500000");
00308
00309 static BoolConfigProperty syncPropCompression("enableCompression", "enable compression of network traffic (not currently supported)");
00310 static ConfigProperty syncPropServerNonce("serverNonce",
00311 "used by the SyncML library internally; do not modify");
00312 static ConfigProperty syncPropClientNonce("clientNonce", "");
00313 static ConfigProperty syncPropDevInfHash("devInfoHash", "");
00314 static ConfigProperty syncPropLogDir("logdir",
00315 "full path to directory where automatic backups and logs\n"
00316 "are stored for all synchronizations; if empty, the temporary\n"
00317 "directory \"$TMPDIR/SyncEvolution-<username>-<server>\" will\n"
00318 "be used to keep the data of just the latest synchronization run;\n"
00319 "if \"none\", then no backups of the databases are made and any\n"
00320 "output is printed directly to the screen\n");
00321 static IntConfigProperty syncPropMaxLogDirs("maxlogdirs",
00322 "Unless this option is set, SyncEvolution will never delete\n"
00323 "anything in the \"logdir\". If set, the oldest directories and\n"
00324 "all their content will be removed after a successful sync\n"
00325 "to prevent the number of log directories from growing beyond\n"
00326 "the given limit.");
00327 static IntConfigProperty syncPropLogLevel("loglevel",
00328 "level of detail for log messages:\n"
00329 "- 0 (or unset) = INFO messages without log file, DEBUG with log file\n"
00330 "- 1 = only ERROR messages\n"
00331 "- 2 = also INFO messages\n"
00332 "- 3 = also DEBUG messages");
00333 static ConfigProperty syncPropSSLServerCertificates("SSLServerCertificates",
00334 "A string specifying the location of the certificates\n"
00335 "used to authenticate the server. When empty, the\n"
00336 "system's default location will be searched.");
00337 static BoolConfigProperty syncPropSSLVerifyServer("SSLVerifyServer",
00338 "The client refuses to establish the connection unless\n"
00339 "the server presents a valid certificate. Disabling this\n"
00340 "option considerably reduces the security of SSL\n"
00341 "(man-in-the-middle attacks become possible) and is not\n"
00342 "recommended.\n",
00343 "1");
00344 static BoolConfigProperty syncPropSSLVerifyHost("SSLVerifyHost",
00345 "The client refuses to establish the connection unless the\n"
00346 "server's certificate matches its host name. In cases where\n"
00347 "the certificate still seems to be valid it might make sense\n"
00348 "to disable this option and allow such connections.\n",
00349 "1");
00350
00351 ConfigPropertyRegistry &EvolutionSyncConfig::getRegistry()
00352 {
00353 static ConfigPropertyRegistry registry;
00354 static bool initialized;
00355
00356 if (!initialized) {
00357 registry.push_back(&syncPropSyncURL);
00358 syncPropSyncURL.setObligatory(true);
00359 registry.push_back(&syncPropUsername);
00360 syncPropUsername.setObligatory(true);
00361 registry.push_back(&syncPropPassword);
00362 syncPropPassword.setObligatory(true);
00363 registry.push_back(&syncPropLogDir);
00364 registry.push_back(&syncPropLogLevel);
00365 registry.push_back(&syncPropMaxLogDirs);
00366 registry.push_back(&syncPropUseProxy);
00367 registry.push_back(&syncPropProxyHost);
00368 registry.push_back(&syncPropProxyUsername);
00369 registry.push_back(&syncPropProxyPassword);
00370 registry.push_back(&syncPropClientAuthType);
00371 registry.push_back(&syncPropDevID);
00372 syncPropDevID.setObligatory(true);
00373 registry.push_back(&syncPropMaxMsgSize);
00374 registry.push_back(&syncPropMaxObjSize);
00375 registry.push_back(&syncPropLoSupport);
00376 registry.push_back(&syncPropCompression);
00377 registry.push_back(&syncPropSSLServerCertificates);
00378 registry.push_back(&syncPropSSLVerifyServer);
00379 registry.push_back(&syncPropSSLVerifyHost);
00380
00381 registry.push_back(&syncPropServerNonce);
00382 syncPropServerNonce.setHidden(true);
00383 registry.push_back(&syncPropClientNonce);
00384 syncPropClientNonce.setHidden(true);
00385 registry.push_back(&syncPropDevInfHash);
00386 syncPropDevInfHash.setHidden(true);
00387 initialized = true;
00388 }
00389
00390 return registry;
00391 }
00392
00393 const char *EvolutionSyncConfig::getUsername() const { return m_stringCache.getProperty(*m_configNode, syncPropUsername); }
00394 void EvolutionSyncConfig::setUsername(const string &value, bool temporarily) { syncPropUsername.setProperty(*m_configNode, value, temporarily); }
00395 const char *EvolutionSyncConfig::getPassword() const {
00396 string password = syncPropPassword.getCachedProperty(*m_configNode, m_cachedPassword);
00397 return m_stringCache.storeString(syncPropPassword.getName(), password);
00398 }
00399 void EvolutionSyncConfig::checkPassword(ConfigUserInterface &ui) {
00400 syncPropPassword.checkPassword(*m_configNode, ui, "SyncML server", m_cachedPassword);
00401 }
00402
00403 void PasswordConfigProperty::checkPassword(ConfigNode &node,
00404 ConfigUserInterface &ui,
00405 const string &descr,
00406 string &cachedPassword)
00407 {
00408 string password = getProperty(node);
00409
00410 if (password == "-") {
00411 password = ui.askPassword(descr);
00412 } else if(boost::starts_with(password, "${") &&
00413 boost::ends_with(password, "}")) {
00414 string envname = password.substr(2, password.size() - 3);
00415 const char *envval = getenv(envname.c_str());
00416 if (!envval) {
00417 EvolutionSyncClient::throwError(string("the environment variable '") +
00418 envname +
00419 "' for the '" +
00420 descr +
00421 "' password is not set");
00422 } else {
00423 password = envval;
00424 }
00425 }
00426 cachedPassword = password;
00427 }
00428
00429 string PasswordConfigProperty::getCachedProperty(ConfigNode &node,
00430 const string &cachedPassword)
00431 {
00432 string password;
00433
00434 if (!cachedPassword.empty()) {
00435 password = cachedPassword;
00436 } else {
00437 password = getProperty(node);
00438 }
00439 return password;
00440 }
00441
00442 void EvolutionSyncConfig::setPassword(const string &value, bool temporarily) { m_cachedPassword = ""; syncPropPassword.setProperty(*m_configNode, value, temporarily); }
00443 bool EvolutionSyncConfig::getUseProxy() const { return syncPropUseProxy.getProperty(*m_configNode); }
00444 void EvolutionSyncConfig::setUseProxy(bool value, bool temporarily) { syncPropUseProxy.setProperty(*m_configNode, value, temporarily); }
00445 const char *EvolutionSyncConfig::getProxyHost() const { return m_stringCache.getProperty(*m_configNode, syncPropProxyHost); }
00446 void EvolutionSyncConfig::setProxyHost(const string &value, bool temporarily) { syncPropProxyHost.setProperty(*m_configNode, value, temporarily); }
00447 const char *EvolutionSyncConfig::getProxyUsername() const { return m_stringCache.getProperty(*m_configNode, syncPropProxyUsername); }
00448 void EvolutionSyncConfig::setProxyUsername(const string &value, bool temporarily) { syncPropProxyUsername.setProperty(*m_configNode, value, temporarily); }
00449 const char *EvolutionSyncConfig::getProxyPassword() const {
00450 string password = syncPropProxyPassword.getCachedProperty(*m_configNode, m_cachedProxyPassword);
00451 return m_stringCache.storeString(syncPropProxyPassword.getName(), password);
00452 }
00453 void EvolutionSyncConfig::checkProxyPassword(ConfigUserInterface &ui) {
00454 syncPropProxyPassword.checkPassword(*m_configNode, ui, "proxy", m_cachedProxyPassword);
00455 }
00456 void EvolutionSyncConfig::setProxyPassword(const string &value, bool temporarily) { m_cachedProxyPassword = ""; syncPropProxyPassword.setProperty(*m_configNode, value, temporarily); }
00457 const char *EvolutionSyncConfig::getSyncURL() const { return m_stringCache.getProperty(*m_configNode, syncPropSyncURL); }
00458 void EvolutionSyncConfig::setSyncURL(const string &value, bool temporarily) { syncPropSyncURL.setProperty(*m_configNode, value, temporarily); }
00459 const char *EvolutionSyncConfig::getClientAuthType() const { return m_stringCache.getProperty(*m_configNode, syncPropClientAuthType); }
00460 void EvolutionSyncConfig::setClientAuthType(const string &value, bool temporarily) { syncPropClientAuthType.setProperty(*m_configNode, value, temporarily); }
00461 bool EvolutionSyncConfig::getLoSupport() const { return syncPropLoSupport.getProperty(*m_configNode); }
00462 void EvolutionSyncConfig::setLoSupport(bool value, bool temporarily) { syncPropLoSupport.setProperty(*m_configNode, value, temporarily); }
00463 unsigned long EvolutionSyncConfig::getMaxMsgSize() const { return syncPropMaxMsgSize.getProperty(*m_configNode); }
00464 void EvolutionSyncConfig::setMaxMsgSize(unsigned long value, bool temporarily) { syncPropMaxMsgSize.setProperty(*m_configNode, value, temporarily); }
00465 unsigned int EvolutionSyncConfig::getMaxObjSize() const { return syncPropMaxObjSize.getProperty(*m_configNode); }
00466 void EvolutionSyncConfig::setMaxObjSize(unsigned int value, bool temporarily) { syncPropMaxObjSize.setProperty(*m_configNode, value, temporarily); }
00467 bool EvolutionSyncConfig::getCompression() const { return syncPropCompression.getProperty(*m_configNode); }
00468 void EvolutionSyncConfig::setCompression(bool value, bool temporarily) { syncPropCompression.setProperty(*m_configNode, value, temporarily); }
00469 const char *EvolutionSyncConfig::getDevID() const { return m_stringCache.getProperty(*m_configNode, syncPropDevID); }
00470 void EvolutionSyncConfig::setDevID(const string &value, bool temporarily) { syncPropDevID.setProperty(*m_configNode, value, temporarily); }
00471 const char *EvolutionSyncConfig::getServerNonce() const { return m_stringCache.getProperty(*m_hiddenNode, syncPropServerNonce); }
00472 void EvolutionSyncConfig::setServerNonce(const char *value) { syncPropServerNonce.setProperty(*m_hiddenNode, value); }
00473 const char *EvolutionSyncConfig::getClientNonce() const { return m_stringCache.getProperty(*m_hiddenNode, syncPropClientNonce); }
00474 void EvolutionSyncConfig::setClientNonce(const char *value) { syncPropClientNonce.setProperty(*m_hiddenNode, value); }
00475 const char *EvolutionSyncConfig::getDevInfHash() const { return m_stringCache.getProperty(*m_hiddenNode, syncPropDevInfHash); }
00476 void EvolutionSyncConfig::setDevInfHash(const char *value) { syncPropDevInfHash.setProperty(*m_hiddenNode, value); }
00477 const char *EvolutionSyncConfig::getLogDir() const { return m_stringCache.getProperty(*m_configNode, syncPropLogDir); }
00478 void EvolutionSyncConfig::setLogDir(const string &value, bool temporarily) { syncPropLogDir.setProperty(*m_configNode, value, temporarily); }
00479 int EvolutionSyncConfig::getMaxLogDirs() const { return syncPropMaxLogDirs.getProperty(*m_configNode); }
00480 void EvolutionSyncConfig::setMaxLogDirs(int value, bool temporarily) { syncPropMaxLogDirs.setProperty(*m_configNode, value, temporarily); }
00481 int EvolutionSyncConfig::getLogLevel() const { return syncPropLogLevel.getProperty(*m_configNode); }
00482 void EvolutionSyncConfig::setLogLevel(int value, bool temporarily) { syncPropLogLevel.setProperty(*m_configNode, value, temporarily); }
00483 const char* EvolutionSyncConfig::getSSLServerCertificates() const { return m_stringCache.getProperty(*m_configNode, syncPropSSLServerCertificates); }
00484 void EvolutionSyncConfig::setSSLServerCertificates(const string &value, bool temporarily) { syncPropSSLServerCertificates.setProperty(*m_configNode, value, temporarily); }
00485 bool EvolutionSyncConfig::getSSLVerifyServer() const { return syncPropSSLVerifyServer.getProperty(*m_configNode); }
00486 void EvolutionSyncConfig::setSSLVerifyServer(bool value, bool temporarily) { syncPropSSLVerifyServer.setProperty(*m_configNode, value, temporarily); }
00487 bool EvolutionSyncConfig::getSSLVerifyHost() const { return syncPropSSLVerifyHost.getProperty(*m_configNode); }
00488 void EvolutionSyncConfig::setSSLVerifyHost(bool value, bool temporarily) { syncPropSSLVerifyHost.setProperty(*m_configNode, value, temporarily); }
00489
00490 static void setDefaultProps(const ConfigPropertyRegistry ®istry,
00491 boost::shared_ptr<FilterConfigNode> node)
00492 {
00493 BOOST_FOREACH(const ConfigProperty *prop, registry) {
00494 if (!prop->isHidden()) {
00495 prop->setDefaultProperty(*node, prop->isObligatory());
00496 }
00497 }
00498 }
00499
00500 void EvolutionSyncConfig::setDefaults()
00501 {
00502 setDefaultProps(getRegistry(), m_configNode);
00503 }
00504
00505 void EvolutionSyncConfig::setSourceDefaults(const string &name)
00506 {
00507 SyncSourceNodes nodes = getSyncSourceNodes(name);
00508 setDefaultProps(EvolutionSyncSourceConfig::getRegistry(),
00509 nodes.m_configNode);
00510 }
00511
00512 static void copyProperties(const ConfigNode &fromProps,
00513 ConfigNode &toProps,
00514 bool hidden,
00515 const ConfigPropertyRegistry &allProps)
00516 {
00517 BOOST_FOREACH(const ConfigProperty *prop, allProps) {
00518 if (prop->isHidden() == hidden) {
00519 string name = prop->getName();
00520 bool isDefault;
00521 string value = prop->getProperty(fromProps, &isDefault);
00522 toProps.setProperty(name, value, prop->getComment(),
00523 isDefault ? &value : NULL);
00524 }
00525 }
00526 }
00527
00528 static void copyProperties(const ConfigNode &fromProps,
00529 ConfigNode &toProps)
00530 {
00531 map<string, string> props;
00532 fromProps.readProperties(props);
00533
00534 BOOST_FOREACH(const StringPair &prop, props) {
00535 toProps.setProperty(prop.first, prop.second);
00536 }
00537 }
00538
00539 void EvolutionSyncConfig::copy(const EvolutionSyncConfig &other,
00540 const set<string> *sourceFilter)
00541 {
00542 static const bool visibility[2] = { false, true };
00543 for (int i = 0; i < 2; i++ ) {
00544 boost::shared_ptr<const FilterConfigNode> fromSyncProps(other.getProperties(visibility[i]));
00545 boost::shared_ptr<FilterConfigNode> toSyncProps(this->getProperties(visibility[i]));
00546 copyProperties(*fromSyncProps, *toSyncProps, visibility[i], other.getRegistry());
00547 }
00548
00549 list<string> sources = other.getSyncSources();
00550 BOOST_FOREACH(const string &sourceName, sources) {
00551 if (!sourceFilter ||
00552 sourceFilter->find(sourceName) != sourceFilter->end()) {
00553 ConstSyncSourceNodes fromNodes = other.getSyncSourceNodes(sourceName);
00554 SyncSourceNodes toNodes = this->getSyncSourceNodes(sourceName);
00555 copyProperties(*fromNodes.m_configNode, *toNodes.m_configNode, false, EvolutionSyncSourceConfig::getRegistry());
00556 copyProperties(*fromNodes.m_hiddenNode, *toNodes.m_hiddenNode, true, EvolutionSyncSourceConfig::getRegistry());
00557 copyProperties(*fromNodes.m_trackingNode, *toNodes.m_trackingNode);
00558 }
00559 }
00560 }
00561
00562 const char *EvolutionSyncConfig::getSwv() const { return VERSION; }
00563 const char *EvolutionSyncConfig::getDevType() const { return DEVICE_TYPE; }
00564
00565
00566 EvolutionSyncSourceConfig::EvolutionSyncSourceConfig(const string &name, const SyncSourceNodes &nodes) :
00567 m_name(name),
00568 m_nodes(nodes)
00569 {
00570 }
00571
00572 StringConfigProperty EvolutionSyncSourceConfig::m_sourcePropSync("sync",
00573 "requests a certain synchronization mode:\n"
00574 " two-way = only send/receive changes since last sync\n"
00575 " slow = exchange all items\n"
00576 " refresh-from-client = discard all remote items and replace with\n"
00577 " the items on the client\n"
00578 " refresh-from-server = discard all local items and replace with\n"
00579 " the items on the server\n"
00580 " one-way-from-client = transmit changes from client\n"
00581 " one-way-from-server = transmit changes from server\n"
00582 " none (or disabled) = synchronization disabled",
00583 "two-way",
00584 Values() +
00585 (Aliases("two-way")) +
00586 (Aliases("slow")) +
00587 (Aliases("refresh-from-client") + "refresh-client") +
00588 (Aliases("refresh-from-server") + "refresh-server" + "refresh") +
00589 (Aliases("one-way-from-client") + "one-way-client") +
00590 (Aliases("one-way-from-server") + "one-way-server" + "one-way") +
00591 (Aliases("disabled") + "none"));
00592
00593 static class SourceTypeConfigProperty : public StringConfigProperty {
00594 public:
00595 SourceTypeConfigProperty() :
00596 StringConfigProperty("type",
00597 "Specifies the SyncEvolution backend and thus the\n"
00598 "data which is synchronized by this source. Some\n"
00599 "backends can exchange data in multiple formats.\n"
00600 "Some of them have a default format that is used\n"
00601 "automatically unless specified differently.\n"
00602 "Sometimes the format must be specified.\n"
00603 "\n"
00604 "In all cases the format of this configuration is\n"
00605 " <backend>[:format]\n"
00606 "\n"
00607 "Here are some valid examples:\n"
00608 " contacts - synchronize address book with default vCard 2.1 format\n"
00609 " contacts:text/vcard - address book with vCard 3.0 format\n"
00610 " calendar - synchronize events in iCalendar 2.0 format\n"
00611 "\n"
00612 "Sending and receiving items in the same format as used by the server for\n"
00613 "the uri selected below is essential. Errors while parsing and/or storing\n"
00614 "items on either client or server can be caused by a mismatch between\n"
00615 "type and uri.\n"
00616 "\n"
00617 "Here's the full list of potentially supported backends,\n"
00618 "valid <backend> values for each of them, and possible\n"
00619 "formats. Note that SyncEvolution installations usually\n"
00620 "support only a subset of the backends; that's why e.g.\n"
00621 "\"addressbook\" is unambiguous although there are multiple\n"
00622 "address book backends.\n",
00623 "select backend",
00624 Values() +
00625 (Aliases("calendar") + "events") +
00626 (Aliases("calendar:text/calendar") + "text/calendar") +
00627 (Aliases("calendar:text/x-vcalendar") + "text/x-vcalendar") +
00628 (Aliases("addressbook") + "contacts") +
00629 (Aliases("addressbook:text/x-vcard") + "text/x-vcard") +
00630 (Aliases("addressbook:text/vcard") + "text/vcard") +
00631 (Aliases("todo") + "tasks" + "text/x-todo") +
00632 (Aliases("memo") + "memos" + "notes" + "text/plain") +
00633 (Aliases("memo:text/calendar") + "text/x-journal"))
00634 {}
00635
00636 virtual string getComment() const {
00637 stringstream enabled, disabled;
00638 stringstream res;
00639
00640 SourceRegistry ®istry(EvolutionSyncSource::getSourceRegistry());
00641 BOOST_FOREACH(const RegisterSyncSource *sourceInfos, registry) {
00642 const string &comment = sourceInfos->m_typeDescr;
00643 stringstream *curr = sourceInfos->m_enabled ? &enabled : &disabled;
00644 *curr << comment;
00645 if (comment.size() && comment[comment.size() - 1] != '\n') {
00646 *curr << '\n';
00647 }
00648 }
00649
00650 res << StringConfigProperty::getComment();
00651 if (enabled.str().size()) {
00652 res << "\nCurrently active:\n" << enabled.str();
00653 }
00654 if (disabled.str().size()) {
00655 res << "\nCurrently inactive:\n" << disabled.str();
00656 }
00657
00658 return boost::trim_right_copy(res.str());
00659 }
00660
00661 virtual Values getValues() const {
00662 Values res(StringConfigProperty::getValues());
00663
00664 const SourceRegistry ®istry(EvolutionSyncSource::getSourceRegistry());
00665 BOOST_FOREACH(const RegisterSyncSource *sourceInfos, registry) {
00666 copy(sourceInfos->m_typeValues.begin(),
00667 sourceInfos->m_typeValues.end(),
00668 back_inserter(res));
00669 }
00670
00671 return res;
00672 }
00673
00674
00675 virtual bool checkValue(const string &value, string &error) const {
00676 size_t colon = value.find(':');
00677 if (colon != value.npos) {
00678 string backend = value.substr(0, colon);
00679 return StringConfigProperty::checkValue(backend, error);
00680 } else {
00681 return StringConfigProperty::checkValue(value, error);
00682 }
00683 }
00684 } sourcePropSourceType;
00685
00686 static ConfigProperty sourcePropDatabaseID("evolutionsource",
00687 "Picks one of backend data sources:\n"
00688 "enter either the name or the full URL.\n"
00689 "Most backends have a default data source,\n"
00690 "like for example the system address book.\n"
00691 "Not setting this property selects that default\n"
00692 "data source.\n"
00693 "\n"
00694 "To get a full list of available data sources,\n"
00695 "run syncevolution without parameters. The name\n"
00696 "is printed in front of the colon, followed by\n"
00697 "the URL. Usually the name is unique and can be\n"
00698 "used to reference the data source. The default\n"
00699 "data source is marked with <default> after the\n"
00700 "URL, if there is a default.\n");
00701 static ConfigProperty sourcePropURI("uri",
00702 "this is appended to the server's URL to identify the\n"
00703 "server's database");
00704 static ConfigProperty sourcePropUser("evolutionuser",
00705 "authentication for backend data source; password can be specified\n"
00706 "in multiple ways, see SyncML server password for details\n"
00707 "\n"
00708 "Warning: setting evolutionuser/password in cases where it is not\n"
00709 "needed, as for example with local Evolution calendars and addressbooks,\n"
00710 "can cause the Evolution backend to hang.");
00711 static PasswordConfigProperty sourcePropPassword("evolutionpassword", "");
00712
00713 static StringConfigProperty sourcePropEncoding("encoding",
00714 "\"b64\" enables base64 encoding of outgoing items (not recommended)",
00715 "",
00716 Values() + (Aliases("b64") + "bin") + Aliases(""));
00717 static ULongConfigProperty sourcePropLast("last",
00718 "used by the SyncML library internally; do not modify");
00719
00720 ConfigPropertyRegistry &EvolutionSyncSourceConfig::getRegistry()
00721 {
00722 static ConfigPropertyRegistry registry;
00723 static bool initialized;
00724
00725 if (!initialized) {
00726 registry.push_back(&EvolutionSyncSourceConfig::m_sourcePropSync);
00727 EvolutionSyncSourceConfig::m_sourcePropSync.setObligatory(true);
00728 registry.push_back(&sourcePropSourceType);
00729 sourcePropSourceType.setObligatory(true);
00730 registry.push_back(&sourcePropDatabaseID);
00731 registry.push_back(&sourcePropURI);
00732 registry.push_back(&sourcePropUser);
00733 registry.push_back(&sourcePropPassword);
00734 registry.push_back(&sourcePropEncoding);
00735 registry.push_back(&sourcePropLast);
00736 sourcePropLast.setHidden(true);
00737 initialized = true;
00738 }
00739
00740 return registry;
00741 }
00742
00743 const char *EvolutionSyncSourceConfig::getDatabaseID() const { return m_stringCache.getProperty(*m_nodes.m_configNode, sourcePropDatabaseID); }
00744 void EvolutionSyncSourceConfig::setDatabaseID(const string &value, bool temporarily) { sourcePropDatabaseID.setProperty(*m_nodes.m_configNode, value, temporarily); }
00745 const char *EvolutionSyncSourceConfig::getUser() const { return m_stringCache.getProperty(*m_nodes.m_configNode, sourcePropUser); }
00746 void EvolutionSyncSourceConfig::setUser(const string &value, bool temporarily) { sourcePropUser.setProperty(*m_nodes.m_configNode, value, temporarily); }
00747 const char *EvolutionSyncSourceConfig::getPassword() const {
00748 string password = sourcePropPassword.getCachedProperty(*m_nodes.m_configNode, m_cachedPassword);
00749 return m_stringCache.storeString(sourcePropPassword.getName(), password);
00750 }
00751 void EvolutionSyncSourceConfig::checkPassword(ConfigUserInterface &ui) {
00752 sourcePropPassword.checkPassword(*m_nodes.m_configNode, ui, m_name + " backend", m_cachedPassword);
00753 }
00754 void EvolutionSyncSourceConfig::setPassword(const string &value, bool temporarily) { m_cachedPassword = ""; sourcePropPassword.setProperty(*m_nodes.m_configNode, value, temporarily); }
00755 const char *EvolutionSyncSourceConfig::getURI() const { return m_stringCache.getProperty(*m_nodes.m_configNode, sourcePropURI); }
00756 void EvolutionSyncSourceConfig::setURI(const string &value, bool temporarily) { sourcePropURI.setProperty(*m_nodes.m_configNode, value, temporarily); }
00757 const char *EvolutionSyncSourceConfig::getSync() const { return m_stringCache.getProperty(*m_nodes.m_configNode, m_sourcePropSync); }
00758 void EvolutionSyncSourceConfig::setSync(const string &value, bool temporarily) { m_sourcePropSync.setProperty(*m_nodes.m_configNode, value, temporarily); }
00759 const char *EvolutionSyncSourceConfig::getEncoding() const { return m_stringCache.getProperty(*m_nodes.m_configNode, sourcePropEncoding); }
00760 void EvolutionSyncSourceConfig::setEncoding(const string &value, bool temporarily) { sourcePropEncoding.setProperty(*m_nodes.m_configNode, value, temporarily); }
00761 unsigned long EvolutionSyncSourceConfig::getLast() const { return sourcePropLast.getProperty(*m_nodes.m_hiddenNode); }
00762 void EvolutionSyncSourceConfig::setLast(unsigned long timestamp) { sourcePropLast.setProperty(*m_nodes.m_hiddenNode, timestamp); }
00763 string EvolutionSyncSourceConfig::getSourceTypeString(const SyncSourceNodes &nodes) { return sourcePropSourceType.getProperty(*nodes.m_configNode); }
00764 pair<string, string> EvolutionSyncSourceConfig::getSourceType(const SyncSourceNodes &nodes) {
00765 string type = getSourceTypeString(nodes);
00766 size_t colon = type.find(':');
00767 if (colon != type.npos) {
00768 string backend = type.substr(0, colon);
00769 string format = type.substr(colon + 1);
00770 sourcePropSourceType.normalizeValue(backend);
00771 return pair<string, string>(backend, format);
00772 } else {
00773 return pair<string, string>(type, "");
00774 }
00775 }
00776 pair<string, string> EvolutionSyncSourceConfig::getSourceType() const { return getSourceType(m_nodes); }
00777 void EvolutionSyncSourceConfig::setSourceType(const string &value, bool temporarily) { sourcePropSourceType.setProperty(*m_nodes.m_configNode, value, temporarily); }