configuration: added support for configuration templates in /etc and server icons

The server config.ini files and icon.[svg|png] in src/default will be installed
in /etc/default/syncevolution. All configurations found there extend and/or
override the builtin templates. The advantage is that file-based templates
can have icons and that templates can be added/modified without recompiling
SyncEvolution.

This meta information is now part of EvolutionSyncConfig:
- getWebURL() returns a URL with further information; this
  replaces the hard-coded URL string that was previously
  returned as comment for templates in the ServerList
- getIconURI() currently returns absolute file paths to
  an icon file (example: icon.png for ScheduleWorld). The
  content and exact URI may vary, depending on how system
  administrators or distributions configure SyncEvolution.
  If possible, callers should be able to handle http://
  and other URI access methods.
This commit is contained in:
Patrick Ohly 2009-04-07 20:33:18 +02:00
parent 905eb74ffd
commit fa2e0c41c9
25 changed files with 267 additions and 50 deletions

11
README
View File

@ -96,6 +96,17 @@ directories before running SyncEvolution for the first time with
Evolution. In older Evolution versions the same data is found in
$HOME/evolution.
Configuration templates for SyncML servers are searched in the following
order:
- "default/syncevolution" inside --sysconfdir DIR, usually
/etc/default/syncevolution (when packaged for a distribution) or
/usr/local/etc/default/syncevolution (when compiling from source)
- built-in templates
The properties defined in a template override the default properties,
so usually only those properties which specifically need to be set for
a certain server should be listed in its template config.
Usage
-----

View File

@ -21,6 +21,7 @@ cat configure-post.in >>configure.in
sed -e "s;@BACKEND_REGISTRIES@;`echo src/backends/*/*Register.cpp | sed -e s%src/%%g`;" \
-e "s;@BACKENDS@;$BACKENDS;" \
-e "s;@TEMPLATE_FILES@;`cd src && find default/syncevolution -type f \( -name '*.png' -o -name '*.svg' -o -name '*.ini' \) -printf '%p '`;" \
src/Makefile-gen.am >src/Makefile.am
sed -e "s;@CONFIG_SUBS@;$SUBS;" \

View File

@ -1,5 +1,5 @@
<?xml version="1.0"?>
<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
<node name="/">
<interface name="org.Moblin.SyncEvolution">

View File

@ -21,6 +21,9 @@ SYNCEVOLUTION_DEP += $(SYNCSOURCES)
endif
EXTRA_DIST = shlibs.local Makefile-gen.am syncevolution.xml
TEMPLATE_FILES = @TEMPLATE_FILES@
nobase_dist_sysconf_DATA = $(TEMPLATE_FILES)
DISTCLEANFILES = synccompare
MAINTAINERCLEANFILES = Makefile.in
CLEANFILES = libstdc++.a client-test $(CLIENT_LIB_TEST_FILES)
@ -225,6 +228,7 @@ valgrind : test
$(srcdir)/Makefile.am: Makefile-gen.am
sed -e 's;[@]BACKEND_REGISTRIES[@];$(BACKEND_REGISTRIES);' \
-e 's;[@]BACKENDS[@];$(BACKENDS);' \
-e 's;[@]TEMPLATE_FILES[@];$(TEMPLATE_FILES);' \
$< >$@
# old-style name for test program(s)

View File

@ -16,10 +16,11 @@
/** @TODO: replace stdio.h with streams */
FileConfigNode::FileConfigNode(const string &path, const string &fileName) :
FileConfigNode::FileConfigNode(const string &path, const string &fileName, bool readonly) :
m_path(path),
m_fileName(fileName),
m_modified(false),
m_readonly(readonly),
m_exists(false)
{
read();
@ -53,6 +54,10 @@ void FileConfigNode::flush()
return;
}
if (m_readonly) {
throw std::runtime_error(m_path + ": internal error: flushing read-only file config node not allowed");
}
mkdir_p(m_path);
string filename = m_path + "/" + m_fileName;

View File

@ -32,20 +32,22 @@ class FileConfigNode : public ConfigNode {
list<string> m_lines;
bool m_modified;
const bool m_readonly;
bool m_exists;
void read();
public:
/**
* Open or create a new file. The file will be physically created
* right away whereas changes to its content will not be written
* immediately.
* Open or create a new file. The file will be read (if it exists)
* but not create or written to unless flush() is called explicitly
*
* @param path node name, maps to directory
* @param fileName name of file inside that directory
* @param readonly do not create or write file, it must exist;
* flush() will throw an exception when changes would have to be written
*/
FileConfigNode(const string &path, const string &fileName);
FileConfigNode(const string &path, const string &fileName, bool readonly);
virtual string getName() const { return m_path + "/" + m_fileName; }

View File

@ -20,7 +20,8 @@
FileConfigTree::FileConfigTree(const string &root,
bool oldLayout) :
m_root(root),
m_oldLayout(oldLayout)
m_oldLayout(oldLayout),
m_readonly(false)
{
}
@ -76,7 +77,7 @@ boost::shared_ptr<ConfigNode> FileConfigTree::open(const string &path,
if (found != m_nodes.end()) {
return found->second;
} else {
boost::shared_ptr<ConfigNode> node(new FileConfigNode(fullpath, filename));
boost::shared_ptr<ConfigNode> node(new FileConfigNode(fullpath, filename, m_readonly));
return m_nodes[fullname] = node;
}
}

View File

@ -26,6 +26,9 @@ class FileConfigTree : public ConfigTree {
FileConfigTree(const string &root,
bool oldLayout);
void setReadOnly(bool readonly) { m_readonly = readonly; }
bool getReadOnly() const { return m_readonly; }
/* ConfigTree API */
virtual string getRootPath() const;
virtual void flush();
@ -38,6 +41,7 @@ class FileConfigTree : public ConfigTree {
private:
const string m_root;
const bool m_oldLayout;
bool m_readonly;
typedef map< string, boost::shared_ptr<ConfigNode> > NodeCache_t;
/** cache of all nodes ever accessed */

View File

@ -85,6 +85,7 @@ CORE_SOURCES = \
libsyncevolution_la_SOURCES = $(CORE_SOURCES)
libsyncevolution_la_LIBADD = @EPACKAGE_LIBS@ @GLIB_LIBS@ $(TRANSPORT_LIBS) @LIBS@ $(SYNTHESIS_LIBS) $(SYNCEVOLUTION_LDADD)
libsyncevolution_la_CXXFLAGS = $(TRANSPORT_CFLAGS) $(SYNCEVOLUTION_CXXFLAGS) $(SYNTHESIS_CFLAGS)
libsyncevolution_la_CPPFLAGS = $(AM_CPPFLAGS) -DTEMPLATE_DIR=\""$(sysconfdir)/default/syncevolution"\"
SyncEvolutionXML.c: $(srcdir)/../syncevolution.xml
echo "const char *SyncEvolutionXML =" > $@

View File

@ -879,6 +879,8 @@ public:
"config.ini:# SSLServerCertificates = \n"
"config.ini:# SSLVerifyServer = 1\n"
"config.ini:# SSLVerifyHost = 1\n"
"config.ini:WebURL = http://sync.scheduleworld.com\n"
"config.ini:# IconURI = \n"
"sources/addressbook/.internal.ini:# last = 0\n"
"sources/addressbook/config.ini:sync = two-way\n"
"sources/addressbook/config.ini:type = addressbook:text/vcard\n"
@ -964,7 +966,7 @@ protected:
cmdline.doit();
string res = scanFiles(root);
removeRandomUUID(res);
string expected = m_scheduleWorldConfig;
string expected = ScheduleWorldConfig();
boost::replace_first(expected,
"# proxyHost = ",
"proxyHost = proxy");
@ -985,7 +987,7 @@ protected:
NULL);
cmdline.doit();
string res = scanFiles(root);
CPPUNIT_ASSERT_EQUAL_DIFF(string(m_scheduleWorldConfig), res);
CPPUNIT_ASSERT_EQUAL_DIFF(ScheduleWorldConfig(), res);
}
}
@ -1004,7 +1006,7 @@ protected:
NULL);
cmdline.doit();
string res = scanFiles(root);
CPPUNIT_ASSERT_EQUAL_DIFF(string(m_scheduleWorldConfig), res);
CPPUNIT_ASSERT_EQUAL_DIFF(ScheduleWorldConfig(), res);
}
void testSetupRenamed() {
string root;
@ -1021,7 +1023,7 @@ protected:
NULL);
cmdline.doit();
string res = scanFiles(root);
CPPUNIT_ASSERT_EQUAL_DIFF(string(m_scheduleWorldConfig), res);
CPPUNIT_ASSERT_EQUAL_DIFF(ScheduleWorldConfig(), res);
}
void testSetupFunambol() {
string root;
@ -1067,9 +1069,9 @@ protected:
help.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("Available configuration templates:\n"
" funambol = http://my.funambol.com\n"
" memotoo = http://www.memotoo.com\n"
" scheduleworld = http://sync.scheduleworld.com\n"
" synthesis = http://www.synthesis.ch\n"
" memotoo = http://www.memotoo.com\n",
" synthesis = http://www.synthesis.ch\n",
help.m_out.str());
CPPUNIT_ASSERT_EQUAL_DIFF("", help.m_err.str());
}
@ -1134,7 +1136,7 @@ protected:
string actual = cmdline.m_out.str();
removeRandomUUID(actual);
string filtered = filterConfig(actual);
CPPUNIT_ASSERT_EQUAL_DIFF(filterConfig(internalToIni(m_scheduleWorldConfig)),
CPPUNIT_ASSERT_EQUAL_DIFF(filterConfig(internalToIni(ScheduleWorldConfig())),
filtered);
// there should have been comments
CPPUNIT_ASSERT(actual.size() > filtered.size());
@ -1146,7 +1148,7 @@ protected:
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
string actual = filterConfig(cmdline.m_out.str());
removeRandomUUID(actual);
CPPUNIT_ASSERT_EQUAL_DIFF(filterConfig(internalToIni(m_scheduleWorldConfig)),
CPPUNIT_ASSERT_EQUAL_DIFF(filterConfig(internalToIni(ScheduleWorldConfig())),
actual);
}
@ -1165,7 +1167,7 @@ protected:
NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
string expected = filterConfig(internalToIni(m_scheduleWorldConfig));
string expected = filterConfig(internalToIni(ScheduleWorldConfig()));
boost::replace_first(expected,
"syncURL = http://sync.scheduleworld.com/funambol/ds",
"syncURL = foo");
@ -1187,7 +1189,7 @@ protected:
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
string actual = cmdline.m_out.str();
removeRandomUUID(actual);
CPPUNIT_ASSERT_EQUAL_DIFF(internalToIni(m_scheduleWorldConfig),
CPPUNIT_ASSERT_EQUAL_DIFF(internalToIni(ScheduleWorldConfig()),
actual);
}
@ -1283,7 +1285,11 @@ protected:
"\n"
"SSLVerifyServer:\n"
"\n"
"SSLVerifyHost:\n");
"SSLVerifyHost:\n"
"\n"
"WebURL:\n"
"\n"
"IconURI:\n");
string sourceProperties("sync:\n"
"\n"
"type:\n"
@ -1561,7 +1567,14 @@ private:
};
string ScheduleWorldConfig() {
return m_scheduleWorldConfig;
string config = m_scheduleWorldConfig;
if (isDir(string(TEMPLATE_DIR) + "/scheduleworld")) {
boost::replace_all(config,
"# IconURI = ",
"IconURI = " TEMPLATE_DIR "/scheduleworld/icon.png");
}
return config;
}
string OldScheduleWorldConfig() {
@ -1591,6 +1604,10 @@ private:
"syncURL = http://sync.scheduleworld.com/funambol/ds",
"syncURL = http://my.funambol.com/sync");
boost::replace_first(config,
"WebURL = http://sync.scheduleworld.com",
"WebURL = http://my.funambol.com");
boost::replace_first(config,
"addressbook/config.ini:uri = card3",
"addressbook/config.ini:uri = card");
@ -1621,6 +1638,10 @@ private:
"syncURL = http://sync.scheduleworld.com/funambol/ds",
"syncURL = http://www.synthesis.ch/sync");
boost::replace_first(config,
"WebURL = http://sync.scheduleworld.com",
"WebURL = http://www.synthesis.ch");
boost::replace_first(config,
"addressbook/config.ini:uri = card3",
"addressbook/config.ini:uri = contacts");

View File

@ -18,6 +18,9 @@
#include <unistd.h>
#include "config.h"
static bool SourcePropSourceTypeIsSet(boost::shared_ptr<EvolutionSyncSourceConfig> source);
static bool SourcePropURIIsSet(boost::shared_ptr<EvolutionSyncSourceConfig> source);
void ConfigProperty::splitComment(const string &comment, list<string> &commentLines)
{
size_t start = 0;
@ -107,43 +110,123 @@ static const InitList< pair<string, string> > serverTemplates =
EvolutionSyncConfig::ServerList EvolutionSyncConfig::getServerTemplates()
{
return serverTemplates;
class TmpList : public ServerList {
public:
void addDefaultTemplate(const string &server, const string &url) {
BOOST_FOREACH(const value_type &entry, static_cast<ServerList &>(*this)) {
if (entry.first == server) {
// already present
return;
}
}
push_back(value_type(server, url));
}
} result;
// scan TEMPLATE_DIR for templates
string templateDir(TEMPLATE_DIR);
if (isDir(templateDir)) {
ReadDir dir(templateDir);
BOOST_FOREACH(const string &entry, dir) {
if (isDir(templateDir + "/" + entry)) {
boost::shared_ptr<EvolutionSyncConfig> config = EvolutionSyncConfig::createServerTemplate(entry);
string comment = config->getWebURL();
if (comment.empty()) {
comment = templateDir + "/" + entry;
}
result.push_back(ServerList::value_type(entry, comment));
}
}
}
// builtin templates if not present
result.addDefaultTemplate("funambol", "http://my.funambol.com");
result.addDefaultTemplate("scheduleworld", "http://sync.scheduleworld.com");
result.addDefaultTemplate("synthesis", "http://www.synthesis.ch");
result.addDefaultTemplate("memotoo", "http://www.memotoo.com");
result.sort();
return result;
}
boost::shared_ptr<EvolutionSyncConfig> EvolutionSyncConfig::createServerTemplate(const string &server)
{
boost::shared_ptr<ConfigTree> tree(new FileConfigTree("/dev/null", false));
string templateConfig(string(TEMPLATE_DIR) + "/");
if (server == "default") {
templateConfig += "scheduleworld";
} else {
templateConfig += server;
}
boost::shared_ptr<FileConfigTree> tree(new FileConfigTree(templateConfig, false));
tree->setReadOnly(true);
boost::shared_ptr<EvolutionSyncConfig> config(new EvolutionSyncConfig(server, tree));
boost::shared_ptr<PersistentEvolutionSyncSourceConfig> source;
config->setDefaults();
config->setDefaults(false);
// The prefix is important: without it, myFUNAMBOL 6.x and 7.0 map
// all SyncEvolution instances to the single phone that they support,
// which leads to unwanted slow syncs when switching between multiple
// instances.
config->setDevID(string("sc-pim-") + UUID());
config->setSourceDefaults("addressbook");
config->setSourceDefaults("calendar");
config->setSourceDefaults("todo");
config->setSourceDefaults("memo");
// set non-default values; this also creates the sync source configs
// create sync source configs and set non-default values
config->setSourceDefaults("addressbook", false);
config->setSourceDefaults("calendar", false);
config->setSourceDefaults("todo", false);
config->setSourceDefaults("memo", false);
source = config->getSyncSourceConfig("addressbook");
source->setSourceType("addressbook");
source->setURI("card");
if (!SourcePropSourceTypeIsSet(source)) {
source->setSourceType("addressbook");
}
if (!SourcePropURIIsSet(source)) {
source->setURI("card");
}
source = config->getSyncSourceConfig("calendar");
source->setSourceType("calendar");
source->setURI("event");
if (!SourcePropSourceTypeIsSet(source)) {
source->setSourceType("calendar");
}
if (!SourcePropURIIsSet(source)) {
source->setURI("event");
}
source = config->getSyncSourceConfig("todo");
source->setSourceType("todo");
source->setURI("task");
if (!SourcePropSourceTypeIsSet(source)) {
source->setSourceType("todo");
}
if (!SourcePropURIIsSet(source)) {
source->setURI("task");
}
source = config->getSyncSourceConfig("memo");
source->setSourceType("memo");
source->setURI("note");
if (!SourcePropSourceTypeIsSet(source)) {
source->setSourceType("memo");
}
if (!SourcePropURIIsSet(source)) {
source->setURI("note");
}
if (isDir(templateConfig)) {
// directory exists, check for icon?
if (config->getIconURI().empty()) {
ReadDir dir(templateConfig);
BOOST_FOREACH(const string &entry, dir) {
if (boost::istarts_with(entry, "icon")) {
config->setIconURI(templateConfig + "/" + entry);
break;
}
}
}
// leave the source configs alone and return the config as it is:
// in order to have sources configured as part of the template,
// the template directory must have directories for all
// sources under "sources"
return config;
}
if (boost::iequals(server, "scheduleworld") ||
boost::iequals(server, "default")) {
config->setSyncURL("http://sync.scheduleworld.com/funambol/ds");
config->setWebURL("http://sync.scheduleworld.com");
source = config->getSyncSourceConfig("addressbook");
source->setURI("card3");
source->setSourceType("addressbook:text/vcard");
@ -155,12 +238,14 @@ boost::shared_ptr<EvolutionSyncConfig> EvolutionSyncConfig::createServerTemplate
source->setURI("note");
} else if (boost::iequals(server, "funambol")) {
config->setSyncURL("http://my.funambol.com/sync");
config->setWebURL("http://my.funambol.com");
source = config->getSyncSourceConfig("calendar");
source->setSync("disabled");
source = config->getSyncSourceConfig("todo");
source->setSync("disabled");
} else if (boost::iequals(server, "synthesis")) {
config->setSyncURL("http://www.synthesis.ch/sync");
config->setWebURL("http://www.synthesis.ch");
source = config->getSyncSourceConfig("addressbook");
source->setURI("contacts");
source = config->getSyncSourceConfig("calendar");
@ -173,6 +258,7 @@ boost::shared_ptr<EvolutionSyncConfig> EvolutionSyncConfig::createServerTemplate
source->setURI("notes");
} else if (boost::iequals(server, "memotoo")) {
config->setSyncURL("http://sync.memotoo.com/syncML");
config->setWebURL("http://www.memotoo.com");
source = config->getSyncSourceConfig("addressbook");
source->setURI("con");
source = config->getSyncSourceConfig("calendar");
@ -333,6 +419,16 @@ static BoolConfigProperty syncPropSSLVerifyHost("SSLVerifyHost",
"to disable this option and allow such connections.\n",
"1");
static ConfigProperty syncPropWebURL("WebURL",
"The URL of a web page with further information about the server.\n"
"Used only by the GUI."
"");
static ConfigProperty syncPropIconURI("IconURI",
"The URI of an icon representing the server graphically.\n"
"Should be a 48x48 pixmap or a SVG (preferred).\n"
"Used only by the GUI.");
ConfigPropertyRegistry &EvolutionSyncConfig::getRegistry()
{
static ConfigPropertyRegistry registry;
@ -363,6 +459,8 @@ ConfigPropertyRegistry &EvolutionSyncConfig::getRegistry()
registry.push_back(&syncPropSSLServerCertificates);
registry.push_back(&syncPropSSLVerifyServer);
registry.push_back(&syncPropSSLVerifyHost);
registry.push_back(&syncPropWebURL);
registry.push_back(&syncPropIconURI);
initialized = true;
}
@ -455,6 +553,10 @@ int EvolutionSyncConfig::getMaxLogDirs() const { return syncPropMaxLogDirs.getPr
void EvolutionSyncConfig::setMaxLogDirs(int value, bool temporarily) { syncPropMaxLogDirs.setProperty(*m_configNode, value, temporarily); }
int EvolutionSyncConfig::getLogLevel() const { return syncPropLogLevel.getProperty(*m_configNode); }
void EvolutionSyncConfig::setLogLevel(int value, bool temporarily) { syncPropLogLevel.setProperty(*m_configNode, value, temporarily); }
std::string EvolutionSyncConfig::getWebURL() const { return syncPropWebURL.getProperty(*m_configNode); }
void EvolutionSyncConfig::setWebURL(const std::string &url, bool temporarily) { syncPropWebURL.setProperty(*m_configNode, url, temporarily); }
std::string EvolutionSyncConfig::getIconURI() const { return syncPropIconURI.getProperty(*m_configNode); }
void EvolutionSyncConfig::setIconURI(const std::string &uri, bool temporarily) { syncPropIconURI.setProperty(*m_configNode, uri, temporarily); }
const char* EvolutionSyncConfig::getSSLServerCertificates() const { return m_stringCache.getProperty(*m_configNode, syncPropSSLServerCertificates); }
void EvolutionSyncConfig::setSSLServerCertificates(const string &value, bool temporarily) { syncPropSSLServerCertificates.setProperty(*m_configNode, value, temporarily); }
bool EvolutionSyncConfig::getSSLVerifyServer() const { return syncPropSSLVerifyServer.getProperty(*m_configNode); }
@ -463,25 +565,30 @@ bool EvolutionSyncConfig::getSSLVerifyHost() const { return syncPropSSLVerifyHos
void EvolutionSyncConfig::setSSLVerifyHost(bool value, bool temporarily) { syncPropSSLVerifyHost.setProperty(*m_configNode, value, temporarily); }
static void setDefaultProps(const ConfigPropertyRegistry &registry,
boost::shared_ptr<FilterConfigNode> node)
boost::shared_ptr<FilterConfigNode> node,
bool force)
{
BOOST_FOREACH(const ConfigProperty *prop, registry) {
if (!prop->isHidden()) {
bool isDefault;
prop->getProperty(*node, &isDefault);
if (!prop->isHidden() &&
(force || isDefault)) {
prop->setDefaultProperty(*node, prop->isObligatory());
}
}
}
void EvolutionSyncConfig::setDefaults()
void EvolutionSyncConfig::setDefaults(bool force)
{
setDefaultProps(getRegistry(), m_configNode);
setDefaultProps(getRegistry(), m_configNode, force);
}
void EvolutionSyncConfig::setSourceDefaults(const string &name)
void EvolutionSyncConfig::setSourceDefaults(const string &name, bool force)
{
SyncSourceNodes nodes = getSyncSourceNodes(name);
setDefaultProps(EvolutionSyncSourceConfig::getRegistry(),
nodes.m_configNode);
nodes.m_configNode, force);
}
static void copyProperties(const ConfigNode &fromProps,
@ -657,6 +764,10 @@ public:
}
}
} sourcePropSourceType;
static bool SourcePropSourceTypeIsSet(boost::shared_ptr<EvolutionSyncSourceConfig> source)
{
return source->isSet(sourcePropSourceType);
}
static ConfigProperty sourcePropDatabaseID("evolutionsource",
"Picks one of backend data sources:\n"
@ -676,6 +787,11 @@ static ConfigProperty sourcePropDatabaseID("evolutionsource",
static ConfigProperty sourcePropURI("uri",
"this is appended to the server's URL to identify the\n"
"server's database");
static bool SourcePropURIIsSet(boost::shared_ptr<EvolutionSyncSourceConfig> source)
{
return source->isSet(sourcePropURI);
}
static ConfigProperty sourcePropUser("evolutionuser",
"authentication for backend data source; password can be specified\n"
"in multiple ways, see SyncML server password for details\n"
@ -697,7 +813,6 @@ ConfigPropertyRegistry &EvolutionSyncSourceConfig::getRegistry()
registry.push_back(&EvolutionSyncSourceConfig::m_sourcePropSync);
EvolutionSyncSourceConfig::m_sourcePropSync.setObligatory(true);
registry.push_back(&sourcePropSourceType);
sourcePropSourceType.setObligatory(true);
registry.push_back(&sourcePropDatabaseID);
registry.push_back(&sourcePropURI);
registry.push_back(&sourcePropUser);

View File

@ -96,7 +96,7 @@ class ConfigProperty {
virtual string getProperty(const ConfigNode &node, bool *isDefault = NULL) const {
string name = getName();
string value = node.readProperty(name);
if (value.size()) {
if (!value.empty()) {
string error;
if (!checkValue(value, error)) {
throwValueError(node, name, value, error);
@ -113,6 +113,13 @@ class ConfigProperty {
}
}
// true if property is set to non-empty value
virtual bool isSet(const ConfigNode &node) const {
string name = getName();
string value = node.readProperty(name);
return !value.empty();
}
protected:
void throwValueError(const ConfigNode &node, const string &name, const string &value, const string &error) const;
@ -470,7 +477,7 @@ class EvolutionSyncConfig {
/** absolute directory name of the configuration root */
string getRootPath() const;
typedef list< pair<string, string> > ServerList;
typedef list< std::pair<std::string, std::string> > ServerList;
/**
* returns list of servers in either the old (.sync4j) or
@ -480,8 +487,7 @@ class EvolutionSyncConfig {
static ServerList getServers();
/**
* returns list of available config templates, given as
* server name and comment
* returns list of available config templates
*/
static ServerList getServerTemplates();
@ -573,12 +579,12 @@ class EvolutionSyncConfig {
/**
* initialize all properties with their default value
*/
void setDefaults();
void setDefaults(bool force = true);
/**
* create a new sync source configuration with default values
*/
void setSourceDefaults(const string &name);
void setSourceDefaults(const string &name, bool force = true);
/**
* Copy all registered properties (hidden and visible) and the
@ -615,6 +621,12 @@ class EvolutionSyncConfig {
virtual int getLogLevel() const;
virtual void setLogLevel(int value, bool temporarily = false);
virtual std::string getWebURL() const;
virtual void setWebURL(const std::string &url, bool temporarily = false);
virtual std::string getIconURI() const;
virtual void setIconURI(const std::string &uri, bool temporarily = false);
/**@}*/
/**
@ -785,6 +797,13 @@ class EvolutionSyncSourceConfig {
bool exists() const { return m_nodes.m_configNode->exists(); }
/** checks if a certain property is set to a non-empty value */
bool isSet(ConfigProperty &prop) {
return prop.isHidden() ?
prop.isSet(*m_nodes.m_hiddenNode) :
prop.isSet(*m_nodes.m_configNode);
}
/**
* @name Settings specific to SyncEvolution SyncSources
*/

View File

@ -16,7 +16,7 @@
class VolatileConfigNode : public FilterConfigNode {
public:
VolatileConfigNode() :
FilterConfigNode(boost::shared_ptr<ConfigNode>(new FileConfigNode("/dev/null", "dummy.ini")))
FilterConfigNode(boost::shared_ptr<ConfigNode>(new FileConfigNode("/dev/null", "dummy.ini", true)))
{}
virtual string getName() const { return "intermediate configuration"; }

17
src/default/README Normal file
View File

@ -0,0 +1,17 @@
The configuration templates in this directory get installed into
sysconfdir/etc/default.
When adding/changing a new server, then only enter the properties
which need to be changed here so that the default values can
be used for the remaining properties.
An icon can be added here for servers. The file name must start with
"icon".
Server configurations must be kept in sync in three different places:
- here (if a server is installed as files)
- in SyncEvolutionConfig.cpp's EvolutionSyncConfig::createServerTemplate()
- in SyncEvolutionCmdline.cpp's test server configs
Note that server icons must come with a suitable license that allows
redistribution. TODO: verify the license of the ScheduleWorld icon.

View File

@ -0,0 +1,2 @@
syncURL = http://my.funambol.com/sync
WebURL = http://my.funambol.com

View File

@ -0,0 +1,2 @@
type = addressbook
uri = card

View File

@ -0,0 +1,2 @@
uri = event
sync = none

View File

@ -0,0 +1 @@
uri = note

View File

@ -0,0 +1,2 @@
uri = task
sync = none

View File

@ -0,0 +1,2 @@
syncURL = http://sync.scheduleworld.com/funambol/ds
WebURL = http://sync.scheduleworld.com

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -0,0 +1,2 @@
type = addressbook:text/vcard
uri = card3

View File

@ -0,0 +1 @@
uri = cal2

View File

@ -0,0 +1 @@
uri = note

View File

@ -0,0 +1 @@
uri = task2