Configuration templates matching: match templates based on metadata
Introduced TemplateConfig to abstracting the template configuration structure, the template metadata used for matching is also parsed here. The fields introduced in the metadata are: PeerIsClient: identify whether this is a server side configuration or a client side configuration. Fingerprint: the matching string for this template, it is a comma separated string with each string modeled as: "Manufacture_Model". The first substring is also used as the name to identify this template so that user can select the template by this name. eg: Nokia 7210c: Nokia_7210c SyncEvolution server: SyncEvolutionServer, SyncEvolution ScheduleWorld: ScheduleWorld,default SyncEvolution client: SyncEvolutionClient, SyncEvolution Description: this is a just a descriptive string not used for matching. GetServerTemplates is changed to add another "devices" parameter to identify it is asking for templates for a list of "devices". Each device is a tuple <matchstring (devicename), matchMode (server/client/all)>. TemplateList as the return type, which is a list of class TemplateDescription so that we can also return enough information for corresponding templates. This list is sorted by the 3-tuple <finger, rank, name>. Add MatchServerTemplates method which will iterating all templates inside the folder and match against the input parameter and finally return a sorted list of matched templates. The atcually fuzzy match algorithm is based on a LCS (added in the following commit). Cmdline interface is changed accordingly: --template ? is changed to --template ?[string], so that user use the former case to match all templates for a tradiontial SyncML client and the latter case to match templates related to an input string. SyncConfig API is also renamed (Server -> Peer) because both server/client configuration/template are handled. The original configuration template (Funambol and ScheduleWorld) has been moved to the new template structure (under servers), they also have a .template.ini file added so that they can be matched and picked up. All templates for supported servers still have built-in template support in the code as before. Templates for SyncEvolution based server is also added. Server side templates are added (Nokia default, Nokia_7210c and SyncEvolutionServer). Add unit test for the new template match use case.
This commit is contained in:
parent
7c48c8d121
commit
d71aa7b2ac
10
README
10
README
|
@ -320,7 +320,7 @@ a list of valid values.
|
|||
sources, so if you want to change a source property of just one specific
|
||||
sync source, then use "--configure --source-property ... <server> <source>".
|
||||
|
||||
--template|-l <server name>|default|?
|
||||
--template|-l <server name>|default|?<device>
|
||||
Can be used to select from one of the built-in default configurations
|
||||
for known SyncML servers. Defaults to the <server> name, so --template
|
||||
only has to be specified when creating multiple different configurations
|
||||
|
@ -330,6 +330,14 @@ a list of valid values.
|
|||
Each template contains a pseudo-random device ID. Therefore setting the
|
||||
"deviceId" sync property is only necessary when manually recreating a
|
||||
configuration or when a more descriptive name is desired.
|
||||
The available templates for different known SyncML servers are listed when
|
||||
using a single question mark instead of template name. When using the
|
||||
?<desireddevice> format, a fuzzy search for a template that might be
|
||||
suitable for talking to such a device is done. The matching works best
|
||||
when using <device> = <Manufacturer>_<Model>. If you don't know the
|
||||
Manufacturer, you can just keep it as empty. The output in this mode
|
||||
gives the template name followed by a short description and a rating how well
|
||||
the template matches the device (higher is better).
|
||||
|
||||
--status|-t
|
||||
The changes made to local data since the last synchronization are
|
||||
|
|
|
@ -188,6 +188,21 @@ nodist_client_test_SOURCES = ../test/test.cpp
|
|||
CLIENT_LIB_TEST_FILES = \
|
||||
testcases/lcs/file1.txt \
|
||||
testcases/lcs/file2.txt \
|
||||
testcases/templates/clients/default/.template.ini \
|
||||
testcases/templates/clients/SyncEvolution/sources/addressbook/config.ini \
|
||||
testcases/templates/clients/SyncEvolution/sources/memo/config.ini \
|
||||
testcases/templates/clients/SyncEvolution/sources/todo/config.ini \
|
||||
testcases/templates/clients/SyncEvolution/sources/calendar/config.ini \
|
||||
testcases/templates/clients/SyncEvolution/.template.ini \
|
||||
testcases/templates/clients/SyncEvolution/config.ini \
|
||||
testcases/templates/clients/phone/nokia/default/.template.ini \
|
||||
testcases/templates/clients/phone/nokia/S40/7210c/sources/addressbook/config.ini \
|
||||
testcases/templates/clients/phone/nokia/S40/7210c/sources/memo/config.ini \
|
||||
testcases/templates/clients/phone/nokia/S40/7210c/sources/todo/config.ini \
|
||||
testcases/templates/clients/phone/nokia/S40/7210c/sources/calendar/config.ini \
|
||||
testcases/templates/clients/phone/nokia/S40/7210c/sources/calendar+todo/config.ini \
|
||||
testcases/templates/clients/phone/nokia/S40/7210c/.template.ini \
|
||||
testcases/templates/clients/phone/nokia/S40/7210c/config.ini \
|
||||
testcases/vcard21.vcf \
|
||||
testcases/vcard30.vcf \
|
||||
testcases/ical20.ics \
|
||||
|
@ -247,7 +262,10 @@ testcase2patch: $(TEST_FILES_GENERATED)
|
|||
done
|
||||
|
||||
# copy base test files
|
||||
$(filter-out %.tem, $(filter testcases/%, $(subst $(srcdir)/../test/,,$(CLIENT_LIB_TEST_FILES)))) : % : $(srcdir)/../test/%
|
||||
$(filter-out %.tem testcases/templates/%, $(filter testcases/%, $(subst $(srcdir)/../test/,,$(CLIENT_LIB_TEST_FILES)))) : % : $(srcdir)/../test/%
|
||||
mkdir -p ${@D}
|
||||
cp $< $@
|
||||
$(filter testcases/templates/%, $(CLIENT_LIB_TEST_FILES)) : testcases/% : $(srcdir)/%
|
||||
mkdir -p ${@D}
|
||||
cp $< $@
|
||||
|
||||
|
|
|
@ -215,7 +215,7 @@ public:
|
|||
// device ID is different
|
||||
config.reset(new SyncConfig(string(server) + "_" + id + "@client-test-" + id));
|
||||
config->setDefaults();
|
||||
from = SyncConfig::createServerTemplate(server);
|
||||
from = SyncConfig::createPeerTemplate(server);
|
||||
if(from) {
|
||||
set<string> filter;
|
||||
config->copy(*from, &filter);
|
||||
|
|
|
@ -1398,14 +1398,18 @@ ReadOperations::ReadOperations(const std::string &config_name) :
|
|||
|
||||
void ReadOperations::getConfigs(bool getTemplates, std::vector<std::string> &configNames)
|
||||
{
|
||||
SyncConfig::ServerList list;
|
||||
if (getTemplates) {
|
||||
list = SyncConfig::getServerTemplates();
|
||||
SyncConfig::DeviceList devices;
|
||||
SyncConfig::TemplateList list = SyncConfig::getPeerTemplates(devices);
|
||||
BOOST_FOREACH(const boost::shared_ptr<SyncConfig::TemplateDescription> server, list) {
|
||||
configNames.push_back(server->m_name);
|
||||
//TODO create the template filters
|
||||
}
|
||||
} else {
|
||||
list = SyncConfig::getServers();
|
||||
}
|
||||
BOOST_FOREACH(const SyncConfig::ServerList::value_type &server, list) {
|
||||
configNames.push_back(server.first);
|
||||
SyncConfig::ConfigList list = SyncConfig::getConfigs();
|
||||
BOOST_FOREACH(const SyncConfig::ConfigList::value_type &server, list) {
|
||||
configNames.push_back(server.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1440,7 +1444,7 @@ void ReadOperations::getConfig(bool getTemplate,
|
|||
SyncConfig::splitConfigString(SyncConfig::normalizeConfigString(m_configName),
|
||||
peer, context);
|
||||
|
||||
syncConfig = SyncConfig::createServerTemplate(peer);
|
||||
syncConfig = SyncConfig::createPeerTemplate(peer);
|
||||
if(!syncConfig.get()) {
|
||||
SE_THROW_EXCEPTION(NoSuchConfig, "No template '" + m_configName + "' found");
|
||||
}
|
||||
|
@ -2666,8 +2670,8 @@ void Connection::process(const Caller_t &caller,
|
|||
// same serverID ("PC Suite"), so check properties of the
|
||||
// of our configs first before going back to the name itself.
|
||||
std::string serverID = san.fServerID;
|
||||
SyncConfig::ServerList servers = SyncConfig::getServers();
|
||||
BOOST_FOREACH(const SyncConfig::ServerList::value_type &server,
|
||||
SyncConfig::ConfigList servers = SyncConfig::getConfigs();
|
||||
BOOST_FOREACH(const SyncConfig::ConfigList::value_type &server,
|
||||
servers) {
|
||||
SyncConfig conf(server.first);
|
||||
if (conf.getSyncURL() == serverID) {
|
||||
|
@ -2682,12 +2686,13 @@ void Connection::process(const Caller_t &caller,
|
|||
if (trans != m_peer.end() && id != m_peer.end()) {
|
||||
if (trans->second == "org.openobex.obexd") {
|
||||
string btAddr = id->second.substr(0, id->second.find("+"));
|
||||
BOOST_FOREACH(const SyncConfig::ServerList::value_type &server,
|
||||
BOOST_FOREACH(const SyncConfig::ConfigList::value_type &server,
|
||||
servers) {
|
||||
SyncConfig conf(server.first);
|
||||
string url = conf.getSyncURL();
|
||||
url = url.substr (0, url.find("+"));
|
||||
SE_LOG_DEBUG (NULL, NULL, "matching against %s",url.c_str());
|
||||
//TODO working with multiple SyncURLs
|
||||
if (url.find ("obex-bt://") ==0 && url.substr(strlen("obex-bt://"), url.npos) == btAddr) {
|
||||
config = server.first;
|
||||
break;
|
||||
|
@ -2697,7 +2702,7 @@ void Connection::process(const Caller_t &caller,
|
|||
}
|
||||
|
||||
if (config.empty()) {
|
||||
BOOST_FOREACH(const SyncConfig::ServerList::value_type &server,
|
||||
BOOST_FOREACH(const SyncConfig::ConfigList::value_type &server,
|
||||
servers) {
|
||||
if (server.first == serverID) {
|
||||
config = serverID;
|
||||
|
@ -2799,8 +2804,8 @@ void Connection::process(const Caller_t &caller,
|
|||
// TODO: proper exception
|
||||
throw runtime_error("could not extract LocURI=deviceID from initial message");
|
||||
}
|
||||
BOOST_FOREACH(const StringPair &entry,
|
||||
SyncConfig::getServers()) {
|
||||
BOOST_FOREACH(const SyncConfig::ConfigList::value_type &entry,
|
||||
SyncConfig::getConfigs()) {
|
||||
SyncConfig peer(entry.first);
|
||||
if (info.m_deviceID == peer.getRemoteDevID()) {
|
||||
config = entry.first;
|
||||
|
|
|
@ -89,7 +89,7 @@ bool Cmdline::parse()
|
|||
m_argv[opt - 1], opt == m_argc ? NULL : m_argv[opt])) {
|
||||
return false;
|
||||
}
|
||||
} else if(boost::iequals(m_argv[opt], "--template") ||
|
||||
}else if(boost::iequals(m_argv[opt], "--template") ||
|
||||
boost::iequals(m_argv[opt], "-l")) {
|
||||
opt++;
|
||||
if (opt >= m_argc) {
|
||||
|
@ -98,10 +98,11 @@ bool Cmdline::parse()
|
|||
}
|
||||
m_template = m_argv[opt];
|
||||
m_configure = true;
|
||||
if (boost::trim_copy(m_template) == "?") {
|
||||
dumpServers("Available configuration templates:",
|
||||
SyncConfig::getServerTemplates());
|
||||
string temp = boost::trim_copy (m_template);
|
||||
if (temp.find ("?") == 0){
|
||||
m_printTemplates = true;
|
||||
m_dontrun = true;
|
||||
m_template = temp.substr (1);
|
||||
}
|
||||
} else if(boost::iequals(m_argv[opt], "--print-servers")) {
|
||||
m_printServers = true;
|
||||
|
@ -185,8 +186,19 @@ bool Cmdline::run() {
|
|||
printf("%s", EDSAbiWrapperInfo());
|
||||
printf("%s", SyncSource::backendsInfo().c_str());
|
||||
} else if (m_printServers || boost::trim_copy(m_server) == "?") {
|
||||
dumpServers("Configured servers:",
|
||||
SyncConfig::getServers());
|
||||
dumpConfigs("Configured servers:",
|
||||
SyncConfig::getConfigs());
|
||||
} else if (m_printTemplates) {
|
||||
SyncConfig::DeviceList devices;
|
||||
if (m_template.empty()){
|
||||
dumpConfigTemplates("Available configuration templates:",
|
||||
SyncConfig::getPeerTemplates(devices), false);
|
||||
} else {
|
||||
//limiting at templates for syncml clients only.
|
||||
devices.push_back (SyncConfig::DeviceList::value_type (m_template, SyncConfig::MATCH_FOR_SERVER_MODE));
|
||||
dumpConfigTemplates("Available configuration templates:",
|
||||
SyncConfig::matchPeerTemplates(devices), true);
|
||||
}
|
||||
} else if (m_dontrun) {
|
||||
// user asked for information
|
||||
} else if (m_argc == 1) {
|
||||
|
@ -236,7 +248,7 @@ bool Cmdline::run() {
|
|||
string peer, context;
|
||||
SyncConfig::splitConfigString(SyncConfig::normalizeConfigString(m_template), peer, context);
|
||||
|
||||
config = SyncConfig::createServerTemplate(peer);
|
||||
config = SyncConfig::createPeerTemplate(peer);
|
||||
if (!config.get()) {
|
||||
m_err << "ERROR: no configuration template for '" << m_template << "' available." << endl;
|
||||
return false;
|
||||
|
@ -340,11 +352,11 @@ bool Cmdline::run() {
|
|||
fromScratch = true;
|
||||
string configTemplate = m_template.empty() ? m_server : m_template;
|
||||
SyncConfig::splitConfigString(SyncConfig::normalizeConfigString(configTemplate), peer, context);
|
||||
from = SyncConfig::createServerTemplate(peer);
|
||||
from = SyncConfig::createPeerTemplate(peer);
|
||||
if (!from.get()) {
|
||||
m_err << "ERROR: no configuration template for '" << configTemplate << "' available." << endl;
|
||||
dumpServers("Available configuration templates:",
|
||||
SyncConfig::getServerTemplates());
|
||||
dumpConfigTemplates("Available configuration templates:",
|
||||
SyncConfig::getPeerTemplates(SyncConfig::DeviceList()));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -762,18 +774,35 @@ void Cmdline::listSources(SyncSource &syncSource, const string &header)
|
|||
}
|
||||
}
|
||||
|
||||
void Cmdline::dumpServers(const string &preamble,
|
||||
const SyncConfig::ServerList &servers)
|
||||
void Cmdline::dumpConfigs(const string &preamble,
|
||||
const SyncConfig::ConfigList &servers)
|
||||
{
|
||||
m_out << preamble << endl;
|
||||
BOOST_FOREACH(const SyncConfig::ServerList::value_type &server,servers) {
|
||||
m_out << " " << server.first << " = " << server.second << endl;
|
||||
BOOST_FOREACH(const SyncConfig::ConfigList::value_type &server,servers) {
|
||||
m_out << " " << server.first << " = " << server.second <<endl;
|
||||
}
|
||||
if (!servers.size()) {
|
||||
m_out << " none" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void Cmdline::dumpConfigTemplates(const string &preamble,
|
||||
const SyncConfig::TemplateList &templates,
|
||||
bool printRank)
|
||||
{
|
||||
m_out << preamble << endl;
|
||||
BOOST_FOREACH(const SyncConfig::TemplateList::value_type server,templates) {
|
||||
m_out << " " << server->m_name << " = " << server->m_description;
|
||||
if (printRank){
|
||||
m_out << " " << server->m_rank;
|
||||
}
|
||||
m_out << endl;
|
||||
}
|
||||
if (!templates.size()) {
|
||||
m_out << " none" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void Cmdline::dumpProperties(const ConfigNode &configuredProps,
|
||||
const ConfigPropertyRegistry &allProps)
|
||||
{
|
||||
|
@ -1234,6 +1263,7 @@ class CmdlineTest : public CppUnit::TestFixture {
|
|||
CPPUNIT_TEST(testPrintConfig);
|
||||
CPPUNIT_TEST(testPrintFileTemplates);
|
||||
CPPUNIT_TEST(testTemplate);
|
||||
CPPUNIT_TEST(testMatchTemplate);
|
||||
CPPUNIT_TEST(testAddSource);
|
||||
CPPUNIT_TEST(testSync);
|
||||
CPPUNIT_TEST(testConfigure);
|
||||
|
@ -1544,12 +1574,54 @@ protected:
|
|||
" Mobical = http://www.mobical.net\n"
|
||||
" Oracle = http://www.oracle.com/technology/products/beehive/index.html\n"
|
||||
" ScheduleWorld = http://www.scheduleworld.com\n"
|
||||
" SyncEvolution = http://www.syncevolution.org\n"
|
||||
" Synthesis = http://www.synthesis.ch\n"
|
||||
" ZYB = http://www.zyb.com\n",
|
||||
help.m_out.str());
|
||||
CPPUNIT_ASSERT_EQUAL_DIFF("", help.m_err.str());
|
||||
}
|
||||
|
||||
void testMatchTemplate() {
|
||||
ScopedEnvChange templates("SYNCEVOLUTION_TEMPLATE_DIR", "testcases/templates");
|
||||
|
||||
TestCmdline help1("--template", "?nokia_7210c", NULL);
|
||||
help1.doit();
|
||||
CPPUNIT_ASSERT_EQUAL_DIFF("Available configuration templates:\n"
|
||||
" Nokia_7210c = Nokia 7210c phone 5\n"
|
||||
" Nokia = Default templates for nokia phone 3\n"
|
||||
" SyncEvolutionClient = SyncEvolution server side template 2\n"
|
||||
" ServerDefault = server side default template 1\n",
|
||||
help1.m_out.str());
|
||||
CPPUNIT_ASSERT_EQUAL_DIFF("", help1.m_err.str());
|
||||
TestCmdline help2("--template", "?nokia", NULL);
|
||||
help2.doit();
|
||||
CPPUNIT_ASSERT_EQUAL_DIFF("Available configuration templates:\n"
|
||||
" Nokia = Default templates for nokia phone 5\n"
|
||||
" Nokia_7210c = Nokia 7210c phone 3\n"
|
||||
" SyncEvolutionClient = SyncEvolution server side template 2\n"
|
||||
" ServerDefault = server side default template 1\n",
|
||||
help2.m_out.str());
|
||||
CPPUNIT_ASSERT_EQUAL_DIFF("", help2.m_err.str());
|
||||
TestCmdline help3("--template", "?7210c", NULL);
|
||||
help3.doit();
|
||||
CPPUNIT_ASSERT_EQUAL_DIFF("Available configuration templates:\n"
|
||||
" Nokia_7210c = Nokia 7210c phone 3\n"
|
||||
" Nokia = Default templates for nokia phone 1\n"
|
||||
" ServerDefault = server side default template 1\n"
|
||||
" SyncEvolutionClient = SyncEvolution server side template 1\n",
|
||||
help3.m_out.str());
|
||||
CPPUNIT_ASSERT_EQUAL_DIFF("", help3.m_err.str());
|
||||
TestCmdline help4("--template", "?syncevolution", NULL);
|
||||
help4.doit();
|
||||
CPPUNIT_ASSERT_EQUAL_DIFF("Available configuration templates:\n"
|
||||
" SyncEvolutionClient = SyncEvolution server side template 5\n"
|
||||
" Nokia = Default templates for nokia phone 2\n"
|
||||
" Nokia_7210c = Nokia 7210c phone 2\n"
|
||||
" ServerDefault = server side default template 2\n",
|
||||
help4.m_out.str());
|
||||
CPPUNIT_ASSERT_EQUAL_DIFF("", help4.m_err.str());
|
||||
}
|
||||
|
||||
void testPrintServers() {
|
||||
ScopedEnvChange templates("SYNCEVOLUTION_TEMPLATE_DIR", "/dev/null");
|
||||
ScopedEnvChange xdg("XDG_CONFIG_HOME", m_testDir);
|
||||
|
|
|
@ -76,6 +76,7 @@ protected:
|
|||
Bool m_run;
|
||||
Bool m_migrate;
|
||||
Bool m_printServers;
|
||||
Bool m_printTemplates;
|
||||
Bool m_printConfig;
|
||||
Bool m_printSessions;
|
||||
Bool m_dontrun;
|
||||
|
@ -135,8 +136,12 @@ protected:
|
|||
*/
|
||||
void listSources(SyncSource &syncSource, const string &header);
|
||||
|
||||
void dumpServers(const string &preamble,
|
||||
const SyncConfig::ServerList &servers);
|
||||
void dumpConfigs(const string &preamble,
|
||||
const SyncConfig::ConfigList &servers);
|
||||
|
||||
void dumpConfigTemplates(const string &preamble,
|
||||
const SyncConfig::TemplateList &templates,
|
||||
bool printRank = false);
|
||||
|
||||
void dumpProperties(const ConfigNode &configuredProps,
|
||||
const ConfigPropertyRegistry &allProps);
|
||||
|
|
|
@ -28,12 +28,14 @@
|
|||
#include <syncevo/VolatileConfigNode.h>
|
||||
#include <syncevo/DevNullConfigNode.h>
|
||||
#include <syncevo/MultiplexConfigNode.h>
|
||||
#include <syncevo/lcs.h>
|
||||
#include <synthesis/timeutil.h>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <queue>
|
||||
|
||||
#include <unistd.h>
|
||||
#include "config.h"
|
||||
|
@ -151,7 +153,7 @@ SyncConfig::SyncConfig(const string &peer,
|
|||
// when ignoring their context. Peer list is sorted by name,
|
||||
// therefore shorter config names (= without context) are
|
||||
// found first, as intended.
|
||||
BOOST_FOREACH(const StringPair &entry, getServers()) {
|
||||
BOOST_FOREACH(const StringPair &entry, getConfigs()) {
|
||||
string entry_peer, entry_context;
|
||||
splitConfigString(entry.first, entry_peer, entry_context);
|
||||
if (m_peer == entry_peer) {
|
||||
|
@ -310,7 +312,7 @@ string SyncConfig::getRootPath() const
|
|||
|
||||
void SyncConfig::addPeers(const string &root,
|
||||
const std::string &configname,
|
||||
SyncConfig::ServerList &res) {
|
||||
SyncConfig::ConfigList &res) {
|
||||
FileConfigTree tree(root, "", false);
|
||||
list<string> servers = tree.getChildren("");
|
||||
BOOST_FOREACH(const string &server, servers) {
|
||||
|
@ -328,18 +330,18 @@ void SyncConfig::addPeers(const string &root,
|
|||
if (!access((root + "/" + peerPath).c_str(), F_OK)) {
|
||||
// not a real HTTP server, search for peers
|
||||
BOOST_FOREACH(const string &peer, tree.getChildren(peerPath)) {
|
||||
res.push_back(pair<string, string>(normalizeConfigString(peer + "@" + server),
|
||||
root + "/" + peerPath + "/" + peer));
|
||||
res.push_back(pair<string, string> (normalizeConfigString(peer + "@" + server),
|
||||
root + "/" + peerPath + "/" + peer));
|
||||
}
|
||||
} else if (!access((root + "/" + server + "/" + configname).c_str(), F_OK)) {
|
||||
res.push_back(pair<string, string>(server, root + "/" + server));
|
||||
res.push_back(pair<string, string> (server, root + "/" + server));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SyncConfig::ServerList SyncConfig::getServers()
|
||||
SyncConfig::ConfigList SyncConfig::getConfigs()
|
||||
{
|
||||
ServerList res;
|
||||
ConfigList res;
|
||||
|
||||
addPeers(getOldRoot(), "config.txt", res);
|
||||
addPeers(getNewRoot(), "config.ini", res);
|
||||
|
@ -350,36 +352,32 @@ SyncConfig::ServerList SyncConfig::getServers()
|
|||
return res;
|
||||
}
|
||||
|
||||
SyncConfig::ServerList SyncConfig::getServerTemplates()
|
||||
/* Get a list of all templates, both for any phones listed in @peers*/
|
||||
SyncConfig::TemplateList SyncConfig::getPeerTemplates(const DeviceList &peers)
|
||||
{
|
||||
class TmpList : public ServerList {
|
||||
public:
|
||||
void addDefaultTemplate(const string &server, const string &url) {
|
||||
BOOST_FOREACH(const value_type &entry, static_cast<ServerList &>(*this)) {
|
||||
if (boost::iequals(entry.first, server)) {
|
||||
// already present
|
||||
return;
|
||||
}
|
||||
}
|
||||
push_back(value_type(server, url));
|
||||
}
|
||||
} result;
|
||||
TemplateList result1, result2;
|
||||
result1 = matchPeerTemplates (peers);
|
||||
result2 = getBuiltInTemplates();
|
||||
|
||||
// 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<SyncConfig> config = SyncConfig::createServerTemplate(entry);
|
||||
string comment = config->getWebURL();
|
||||
if (comment.empty()) {
|
||||
comment = templateDir + "/" + entry;
|
||||
result1.insert (result1.end(), result2.begin(), result2.end());
|
||||
return result1;
|
||||
}
|
||||
|
||||
|
||||
SyncConfig::TemplateList SyncConfig::getBuiltInTemplates()
|
||||
{
|
||||
class TmpList : public TemplateList {
|
||||
public:
|
||||
void addDefaultTemplate(const string &server, const string &url) {
|
||||
BOOST_FOREACH(const boost::shared_ptr<TemplateDescription> entry, static_cast<TemplateList &>(*this)) {
|
||||
if (boost::iequals(entry->m_name, server)) {
|
||||
//already present
|
||||
return;
|
||||
}
|
||||
}
|
||||
result.push_back(ServerList::value_type(entry, comment));
|
||||
push_back (boost::shared_ptr<TemplateDescription> (new TemplateDescription(server, url)));
|
||||
}
|
||||
}
|
||||
}
|
||||
} result;
|
||||
|
||||
// builtin templates if not present
|
||||
result.addDefaultTemplate("Funambol", "http://my.funambol.com");
|
||||
|
@ -391,12 +389,62 @@ SyncConfig::ServerList SyncConfig::getServerTemplates()
|
|||
result.addDefaultTemplate("Mobical", "http://www.mobical.net");
|
||||
result.addDefaultTemplate("Oracle", "http://www.oracle.com/technology/products/beehive/index.html");
|
||||
result.addDefaultTemplate("Goosync", "http://www.goosync.com/");
|
||||
result.addDefaultTemplate("SyncEvolution", "http://www.syncevolution.org");
|
||||
|
||||
result.sort();
|
||||
result.sort (TemplateDescription::compare_op);
|
||||
return result;
|
||||
}
|
||||
|
||||
boost::shared_ptr<SyncConfig> SyncConfig::createServerTemplate(const string &server)
|
||||
static string SyncEvolutionTemplateDir()
|
||||
{
|
||||
string templateDir(TEMPLATE_DIR);
|
||||
const char *envvar = getenv("SYNCEVOLUTION_TEMPLATE_DIR");
|
||||
if (envvar) {
|
||||
templateDir = envvar;
|
||||
}
|
||||
return templateDir;
|
||||
}
|
||||
|
||||
SyncConfig::TemplateList SyncConfig::matchPeerTemplates(const DeviceList &peers)
|
||||
{
|
||||
TemplateList result;
|
||||
// match against all possible templates without any assumption on directory
|
||||
// layout, the match is entirely based on the metadata .template.ini
|
||||
string templateDir(SyncEvolutionTemplateDir());
|
||||
std::queue <std::string, std::list<std::string> > directories;
|
||||
if (isDir(templateDir)) {
|
||||
directories.push (templateDir);
|
||||
}
|
||||
while (!directories.empty()) {
|
||||
string sDir = directories.front();
|
||||
directories.pop();
|
||||
if (!TemplateConfig::isTemplateConfig(sDir)) {
|
||||
ReadDir dir(sDir);
|
||||
//not a template folder, check all sub directories
|
||||
BOOST_FOREACH(const string &entry, dir) {
|
||||
if (isDir(sDir + "/" + entry)) {
|
||||
directories.push (sDir + "/" + entry);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
TemplateConfig templateConf (sDir);
|
||||
BOOST_FOREACH (const DeviceList::value_type &entry, peers){
|
||||
int rank = templateConf.metaMatch (entry.first, entry.second);
|
||||
if (rank > TemplateConfig::NO_MATCH) {
|
||||
result.push_back (boost::shared_ptr<TemplateDescription>(
|
||||
new TemplateDescription(templateConf.getName(),
|
||||
templateConf.getDescription(), rank, entry.first, sDir, templateConf.getFingerprint())));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.sort (TemplateDescription::compare_op);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
boost::shared_ptr<SyncConfig> SyncConfig::createPeerTemplate(const string &server)
|
||||
{
|
||||
if (server.empty()) {
|
||||
// Empty template name => no such template. This check is
|
||||
|
@ -407,24 +455,49 @@ boost::shared_ptr<SyncConfig> SyncConfig::createServerTemplate(const string &ser
|
|||
}
|
||||
|
||||
// case insensitive search for read-only file template config
|
||||
string templateConfig(TEMPLATE_DIR);
|
||||
const char *envvar = getenv("SYNCEVOLUTION_TEMPLATE_DIR");
|
||||
if (envvar) {
|
||||
templateConfig = envvar;
|
||||
}
|
||||
if (isDir(templateConfig)) {
|
||||
ReadDir dir(templateConfig);
|
||||
templateConfig = dir.find(boost::iequals(server, "default") ?
|
||||
string("ScheduleWorld") : server,
|
||||
false);
|
||||
} else {
|
||||
templateConfig = "";
|
||||
}
|
||||
string templateConfig(SyncEvolutionTemplateDir());
|
||||
|
||||
if (templateConfig.empty()) {
|
||||
// not found, avoid reading current directory by using one which doesn't exist
|
||||
templateConfig = "/dev/null";
|
||||
// before starting another fuzzy match process, first try to load the
|
||||
// template directly taking the parameter as the path
|
||||
if (isDir (server) && TemplateConfig::isTemplateConfig(server)) {
|
||||
templateConfig = server;
|
||||
} else {
|
||||
std::queue <std::string, std::list<std::string> > directories;
|
||||
if (isDir(templateConfig)) {
|
||||
directories.push (templateConfig);
|
||||
}
|
||||
templateConfig = "";
|
||||
int maxmatch = TemplateConfig::NO_MATCH;
|
||||
while (!directories.empty()) {
|
||||
string sDir = directories.front();
|
||||
directories.pop();
|
||||
if (!TemplateConfig::isTemplateConfig(sDir)) {
|
||||
ReadDir dir(sDir);
|
||||
//not a template folder, check all sub directories
|
||||
BOOST_FOREACH(const string &entry, dir) {
|
||||
if (isDir(sDir + "/" + entry)) {
|
||||
directories.push (sDir + "/" + entry);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
TemplateConfig templateConf (sDir);
|
||||
int rank = templateConf.metaMatch (server, MATCH_ALL);
|
||||
if (rank > maxmatch){
|
||||
maxmatch = rank;
|
||||
templateConfig = sDir;
|
||||
if (maxmatch == TemplateConfig::BEST_MATCH){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (templateConfig.empty()) {
|
||||
// not found, avoid reading current directory by using one which doesn't exist
|
||||
templateConfig = "/dev/null";
|
||||
}
|
||||
}
|
||||
|
||||
boost::shared_ptr<FileConfigTree> tree(new FileConfigTree(templateConfig, "", false));
|
||||
tree->setReadOnly(true);
|
||||
boost::shared_ptr<SyncConfig> config(new SyncConfig(server, tree));
|
||||
|
@ -633,6 +706,18 @@ boost::shared_ptr<SyncConfig> SyncConfig::createServerTemplate(const string &ser
|
|||
source->setURI("tasks");
|
||||
source = config->getSyncSourceConfig("memo");
|
||||
source->setURI("");
|
||||
} else if (boost::iequals(server, "syncevolution")) {
|
||||
config->setSyncURL("http://yourserver:port");
|
||||
config->setWebURL("http://www.syncevolution.org");
|
||||
config->setConsumerReady(false);
|
||||
source = config->getSyncSourceConfig("addressbook");
|
||||
source->setURI("addressbook");
|
||||
source = config->getSyncSourceConfig("calendar");
|
||||
source->setURI("calendar");
|
||||
source = config->getSyncSourceConfig("todo");
|
||||
source->setURI("todo");
|
||||
source = config->getSyncSourceConfig("memo");
|
||||
source->setURI("memo");
|
||||
} else {
|
||||
config.reset();
|
||||
}
|
||||
|
@ -1911,5 +1996,121 @@ ConfigPasswordKey EvolutionPasswordConfigProperty::getPasswordKey(const string &
|
|||
return key;
|
||||
}
|
||||
|
||||
// Used for built-in templates
|
||||
SyncConfig::TemplateDescription::TemplateDescription (const std::string &name, const std::string &description)
|
||||
: m_name (name), m_description (description)
|
||||
{
|
||||
m_rank = TemplateConfig::LEVEL3_MATCH;
|
||||
m_fingerprint = "";
|
||||
m_path = "";
|
||||
m_matchedModel = name;
|
||||
}
|
||||
|
||||
/* Ranking of template description is controled by the rank field, larger the
|
||||
* better
|
||||
*/
|
||||
bool SyncConfig::TemplateDescription::compare_op (boost::shared_ptr<SyncConfig::TemplateDescription> &left, boost::shared_ptr<SyncConfig::TemplateDescription> &right)
|
||||
{
|
||||
//first sort against the fingerprint string
|
||||
if (left->m_fingerprint != right->m_fingerprint) {
|
||||
return (left->m_fingerprint < right->m_fingerprint);
|
||||
}
|
||||
// sort against the rank
|
||||
if (right->m_rank != left->m_rank) {
|
||||
return (right->m_rank < left->m_rank);
|
||||
}
|
||||
// sort against the config name
|
||||
return (left->m_name < right->m_name);
|
||||
}
|
||||
|
||||
TemplateConfig::TemplateConfig (const string &path)
|
||||
: m_metaNode (new FileConfigNode (path, ".template.ini", true)),
|
||||
m_name("")
|
||||
{
|
||||
m_metaNode->readProperties(m_metaProps);
|
||||
}
|
||||
|
||||
bool TemplateConfig::isTemplateConfig (const string &dir)
|
||||
{
|
||||
return !ReadDir(dir).find (".template.ini", false).empty();
|
||||
}
|
||||
|
||||
int TemplateConfig::serverModeMatch (SyncConfig::MatchMode mode)
|
||||
{
|
||||
std::string peerIsClient = m_metaProps["peerIsClient"];
|
||||
|
||||
//not a match if serverMode does not match
|
||||
if ((peerIsClient.empty() || peerIsClient == "0") && mode == SyncConfig::MATCH_FOR_SERVER_MODE) {
|
||||
return NO_MATCH;
|
||||
}
|
||||
if (peerIsClient == "1" && mode == SyncConfig::MATCH_FOR_CLIENT_MODE){
|
||||
return NO_MATCH;
|
||||
}
|
||||
return BEST_MATCH;
|
||||
}
|
||||
|
||||
/**
|
||||
* The matching is based on Least common string algorithm
|
||||
* */
|
||||
int TemplateConfig::fingerprintMatch (const string &fingerprint)
|
||||
{
|
||||
//if input "", match all
|
||||
if (fingerprint.empty()) {
|
||||
return LEVEL3_MATCH;
|
||||
}
|
||||
|
||||
std::string fingerprintProp = m_metaProps["fingerprint"];
|
||||
std::vector <string> subfingerprints = unescapeJoinedString (fingerprintProp, ',');
|
||||
std::string input = fingerprint;
|
||||
boost::to_lower(input);
|
||||
//return the largest match value
|
||||
int max = NO_MATCH;
|
||||
BOOST_FOREACH (std::string sub, subfingerprints){
|
||||
if (boost::iequals (sub, "default")){
|
||||
if (LEVEL1_MATCH > max) {
|
||||
max = LEVEL1_MATCH;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
std::vector< LCS::Entry <char> > result;
|
||||
std::string match = sub;
|
||||
boost::to_lower(match);
|
||||
LCS::lcs(match, input, std::back_inserter(result), LCS::accessor_sequence<std::string>());
|
||||
int score = result.size() *2 *BEST_MATCH /(sub.size() + fingerprint.size()) ;
|
||||
if (score > max) {
|
||||
max = score;
|
||||
}
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
int TemplateConfig::metaMatch (const std::string &fingerprint, SyncConfig::MatchMode mode)
|
||||
{
|
||||
int serverMatch = serverModeMatch (mode);
|
||||
if (serverMatch == NO_MATCH){
|
||||
return NO_MATCH;
|
||||
}
|
||||
int fMatch = fingerprintMatch (fingerprint);
|
||||
return (serverMatch *1 + fMatch *3) >>2;
|
||||
}
|
||||
|
||||
string TemplateConfig::getDescription(){
|
||||
return m_metaProps["description"];
|
||||
}
|
||||
|
||||
string TemplateConfig::getFingerprint(){
|
||||
return m_metaProps["fingerprint"];
|
||||
}
|
||||
|
||||
string TemplateConfig::getName(){
|
||||
if (m_name.empty()){
|
||||
std::string fingerprintProp = m_metaProps["fingerprint"];
|
||||
if (!fingerprintProp.empty()){
|
||||
std::vector<std::string> subfingerprints = unescapeJoinedString (fingerprintProp, ',');
|
||||
m_name = subfingerprints[0];
|
||||
}
|
||||
}
|
||||
return m_name;
|
||||
}
|
||||
SE_END_CXX
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include <syncevo/FilterConfigNode.h>
|
||||
#include <syncevo/SafeConfigNode.h>
|
||||
#include <syncevo/FileConfigNode.h>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
@ -836,29 +837,101 @@ class SyncConfig {
|
|||
/** absolute directory name of the configuration root */
|
||||
string getRootPath() const;
|
||||
|
||||
typedef list< std::pair<std::string, std::string> > ServerList;
|
||||
typedef list< std::pair<std::string, std::string> > ConfigList;
|
||||
|
||||
/** A simple description of the template or the configuration based on a
|
||||
* template. The rank field is used to indicate how good it matches the
|
||||
* user input <MacAddress, DeviceName> */
|
||||
struct TemplateDescription {
|
||||
// The name of the template
|
||||
std::string m_name;
|
||||
// The description of the template (eg. the web server URL for a
|
||||
// SyncML server. This is not used for UI, only CMD line used this.
|
||||
std::string m_description;
|
||||
// The matched percentage of the template, larger the better.
|
||||
int m_rank;
|
||||
|
||||
// A string identify which fingerprint the template is matched with.
|
||||
std::string m_fingerprint;
|
||||
|
||||
// A unique string identify the template path, so that a later operation
|
||||
// fetching this config will be much easier
|
||||
std::string m_path;
|
||||
|
||||
// A string indicates the original fingerprint in the matched template, this
|
||||
// will not necessarily the same with m_fingerprint
|
||||
std::string m_matchedModel;
|
||||
|
||||
TemplateDescription (const std::string &name, const std::string &description,
|
||||
const int rank, const std::string &fingerprint, const std::string &path, const std::string &model)
|
||||
: m_name (name),
|
||||
m_description (description),
|
||||
m_rank (rank),
|
||||
m_fingerprint (fingerprint),
|
||||
m_path (path),
|
||||
m_matchedModel(model)
|
||||
{
|
||||
}
|
||||
|
||||
TemplateDescription (const std::string &name, const std::string &description);
|
||||
|
||||
static bool compare_op (boost::shared_ptr<TemplateDescription> &left, boost::shared_ptr<TemplateDescription> &right);
|
||||
};
|
||||
|
||||
enum MatchMode {
|
||||
/*Match templates when we work as SyncML server, i.e. the peer is the client*/
|
||||
MATCH_FOR_SERVER_MODE,
|
||||
/*Match templates when work as SyncML client, i.e. the peer is the server*/
|
||||
MATCH_FOR_CLIENT_MODE,
|
||||
/*Match templates for both SyncML server and SyncML client*/
|
||||
MATCH_ALL,
|
||||
INVALID
|
||||
};
|
||||
|
||||
typedef list<boost::shared_ptr <TemplateDescription> > TemplateList;
|
||||
typedef list<std::pair <std::string, SyncConfig::MatchMode> > DeviceList;
|
||||
|
||||
/**
|
||||
* returns list of servers in either the old (.sync4j) or
|
||||
* new config directory (.config), given as server name
|
||||
* and absolute root of config
|
||||
*/
|
||||
static ServerList getServers();
|
||||
static ConfigList getConfigs();
|
||||
|
||||
/**
|
||||
* returns list of available config templates
|
||||
* returns list of available config templates:
|
||||
* for each peer listed in @peers, matching against the fingerprint information
|
||||
* from the peer (deviceName likely), sorted by the matching score,
|
||||
* templates failed to match(as long as it's for SyncML server) will also
|
||||
* be returned as a fallback mechanism so that user can select a configuration
|
||||
* template manually.
|
||||
* Any templates for SyncMl Client is also returned, with a default rank.
|
||||
* The assumption currently is only work for SyncML client peers.
|
||||
* DeviceList is a list of matching tuples <fingerprint, SyncConfig::MatchMode>.
|
||||
*/
|
||||
static ServerList getServerTemplates();
|
||||
static TemplateList getPeerTemplates(const DeviceList &peers);
|
||||
|
||||
/**
|
||||
* match the built-in templates against @param fingerprint, return a list of
|
||||
* servers sorted by the matching rank.
|
||||
* */
|
||||
static TemplateList matchPeerTemplates(const DeviceList &peers);
|
||||
|
||||
/**
|
||||
* get the built-in default templates
|
||||
*/
|
||||
static TemplateList getBuiltInTemplates ();
|
||||
|
||||
/**
|
||||
* Creates a new instance of a configuration template.
|
||||
* The result can be modified to set filters, but it
|
||||
* cannot be flushed.
|
||||
*
|
||||
* @param peer a configuration name, *without* a context (scheduleworld, not scheduleworld@default)
|
||||
* @param peer a configuration name, *without* a context (scheduleworld, not scheduleworld@default),
|
||||
* or a configuration path in the system directory which can avoid another fuzzy match process.
|
||||
* @return NULL if no such template
|
||||
*/
|
||||
static boost::shared_ptr<SyncConfig> createServerTemplate(const string &peer);
|
||||
static boost::shared_ptr<SyncConfig> createPeerTemplate(const string &peer);
|
||||
|
||||
/** true if the main configuration file already exists */
|
||||
bool exists() const;
|
||||
|
@ -1219,7 +1292,7 @@ private:
|
|||
*/
|
||||
static void addPeers(const string &root,
|
||||
const std::string &configname,
|
||||
SyncConfig::ServerList &res);
|
||||
SyncConfig::ConfigList &res);
|
||||
|
||||
/**
|
||||
* set tree and nodes to VolatileConfigTree/Node
|
||||
|
@ -1515,6 +1588,34 @@ class PersistentSyncSourceConfig : public SyncSourceConfig {
|
|||
virtual const char* getSupportedTypes() const { return ""; }
|
||||
};
|
||||
|
||||
/**
|
||||
* Representing a configuration template node used for fuzzy matching.
|
||||
*/
|
||||
class TemplateConfig
|
||||
{
|
||||
boost::shared_ptr<FileConfigNode> m_metaNode;
|
||||
ConfigProps m_metaProps;
|
||||
string m_name;
|
||||
public:
|
||||
TemplateConfig (const string &path);
|
||||
enum {
|
||||
NO_MATCH = 0,
|
||||
LEVEL1_MATCH = 1,
|
||||
LEVEL2_MATCH = 2,
|
||||
LEVEL3_MATCH = 3,
|
||||
LEVEL4_MATCH = 4,
|
||||
BEST_MATCH=5
|
||||
};
|
||||
static bool isTemplateConfig (const string &path);
|
||||
virtual int metaMatch (const string &fingerprint, SyncConfig::MatchMode mode);
|
||||
virtual int serverModeMatch (SyncConfig::MatchMode mode);
|
||||
virtual int fingerprintMatch (const string &fingerprint);
|
||||
virtual string getName();
|
||||
virtual string getDescription();
|
||||
virtual string getFingerprint();
|
||||
};
|
||||
|
||||
|
||||
/**@}*/
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
peerIsClient = 1
|
||||
fingerprint = SyncEvolutionClient, SyncEvolution
|
||||
description = SyncEvolution server side template
|
|
@ -0,0 +1,4 @@
|
|||
username = test
|
||||
password = test
|
||||
PeerIsClient = 1
|
||||
ConsumerReady = 1
|
|
@ -0,0 +1,2 @@
|
|||
sync = two-way
|
||||
uri = addressbook
|
|
@ -0,0 +1,2 @@
|
|||
sync = two-way
|
||||
uri = calendar
|
|
@ -0,0 +1,2 @@
|
|||
sync = two-way
|
||||
uri = memo
|
|
@ -0,0 +1,2 @@
|
|||
sync = two-way
|
||||
uri = todo
|
|
@ -0,0 +1,3 @@
|
|||
peerIsClient = 1
|
||||
fingerprint = ServerDefault
|
||||
description = server side default template
|
|
@ -0,0 +1,3 @@
|
|||
peerIsClient = 1
|
||||
fingerprint = Nokia_7210c
|
||||
description = Nokia 7210c phone
|
|
@ -0,0 +1,2 @@
|
|||
PeerIsClient = 1
|
||||
ConsumerReady = 1
|
|
@ -0,0 +1,2 @@
|
|||
sync = two-way
|
||||
uri = Contacts
|
|
@ -0,0 +1,4 @@
|
|||
sync = two-way
|
||||
type = virtual:text/x-calendar:1.0
|
||||
evolutionsource = calendar,todo
|
||||
uri = Calendar
|
|
@ -0,0 +1 @@
|
|||
sync = none
|
|
@ -0,0 +1,2 @@
|
|||
sync = two-way
|
||||
uri = memo
|
|
@ -0,0 +1 @@
|
|||
sync = none
|
|
@ -0,0 +1,3 @@
|
|||
peerIsClient = 1
|
||||
fingerprint = Nokia
|
||||
description = Default templates for nokia phone
|
|
@ -0,0 +1,3 @@
|
|||
PeerIsClient = 0
|
||||
fingerprint = Funambol
|
||||
description = http://my.funambol.com
|
|
@ -0,0 +1,6 @@
|
|||
# *not* a complete config, do not copy manually into ~/.config
|
||||
|
||||
syncURL = http://my.funambol.com/sync
|
||||
WebURL = http://my.funambol.com
|
||||
enableWBXML = FALSE
|
||||
ConsumerReady = TRUE
|
|
@ -0,0 +1,2 @@
|
|||
type = addressbook
|
||||
uri = card
|
|
@ -0,0 +1,3 @@
|
|||
uri = event
|
||||
sync = two-way
|
||||
type = calendar:text/calendar!
|
|
@ -0,0 +1 @@
|
|||
uri = note
|
|
@ -0,0 +1,3 @@
|
|||
uri = task
|
||||
sync = two-way
|
||||
type = todo:text/calendar!
|
|
@ -0,0 +1,3 @@
|
|||
PeerIsClient = 0
|
||||
fingerprint = ScheduleWorld, default
|
||||
description = http://www.scheduleworld.org
|
|
@ -0,0 +1,5 @@
|
|||
# *not* a complete config, do not copy manually into ~/.config
|
||||
|
||||
syncURL = http://sync.scheduleworld.com/funambol/ds
|
||||
WebURL = http://sync.scheduleworld.com
|
||||
ConsumerReady = TRUE
|
|
@ -0,0 +1,2 @@
|
|||
type = addressbook:text/vcard
|
||||
uri = card3
|
|
@ -0,0 +1 @@
|
|||
uri = cal2
|
|
@ -0,0 +1 @@
|
|||
uri = note
|
|
@ -0,0 +1 @@
|
|||
uri = task2
|
|
@ -0,0 +1,3 @@
|
|||
peerIsClient = 1
|
||||
fingerprint = SyncEvolutionClient, SyncEvolution
|
||||
description = SyncEvolution server side template
|
|
@ -0,0 +1,4 @@
|
|||
username = test
|
||||
password = test
|
||||
PeerIsClient = 1
|
||||
ConsumerReady = 1
|
|
@ -0,0 +1,2 @@
|
|||
sync = two-way
|
||||
uri = addressbook
|
|
@ -0,0 +1,2 @@
|
|||
sync = two-way
|
||||
uri = calendar
|
|
@ -0,0 +1,2 @@
|
|||
sync = two-way
|
||||
uri = memo
|
|
@ -0,0 +1,2 @@
|
|||
sync = two-way
|
||||
uri = todo
|
|
@ -0,0 +1,3 @@
|
|||
peerIsClient = 1
|
||||
fingerprint = ServerDefault
|
||||
description = server side default template
|
|
@ -0,0 +1,3 @@
|
|||
peerIsClient = 1
|
||||
fingerprint = Nokia_7210c
|
||||
description = Nokia 7210c phone
|
|
@ -0,0 +1,2 @@
|
|||
PeerIsClient = 1
|
||||
ConsumerReady = 1
|
|
@ -0,0 +1,2 @@
|
|||
sync = two-way
|
||||
uri = Contacts
|
|
@ -0,0 +1 @@
|
|||
sync = none
|
|
@ -0,0 +1,2 @@
|
|||
sync = two-way
|
||||
uri = memo
|
|
@ -0,0 +1,4 @@
|
|||
sync = two-way
|
||||
type = virtual:text/x-calendar:1.0
|
||||
evolutionsource = calendar,todo
|
||||
uri = Calendar
|
|
@ -0,0 +1 @@
|
|||
sync = none
|
|
@ -0,0 +1,3 @@
|
|||
peerIsClient = 1
|
||||
fingerprint = Nokia
|
||||
description = Default templates for nokia phone
|
|
@ -0,0 +1,3 @@
|
|||
peerIsClient = 0
|
||||
fingerprint = Funambol
|
||||
description = http://my.funambol.com
|
|
@ -0,0 +1,6 @@
|
|||
# *not* a complete config, do not copy manually into ~/.config
|
||||
|
||||
syncURL = http://my.funambol.com/sync
|
||||
WebURL = http://my.funambol.com
|
||||
enableWBXML = FALSE
|
||||
ConsumerReady = TRUE
|
|
@ -0,0 +1,2 @@
|
|||
type = addressbook
|
||||
uri = card
|
|
@ -0,0 +1,3 @@
|
|||
uri = event
|
||||
sync = two-way
|
||||
type = calendar:text/calendar!
|
|
@ -0,0 +1 @@
|
|||
uri = note
|
|
@ -0,0 +1,3 @@
|
|||
uri = task
|
||||
sync = two-way
|
||||
type = todo:text/calendar!
|
|
@ -0,0 +1,3 @@
|
|||
peerIsClient = 0
|
||||
fingerprint = ScheduleWorld, default
|
||||
description = http://sync.scheduleworld.com
|
|
@ -0,0 +1,5 @@
|
|||
# *not* a complete config, do not copy manually into ~/.config
|
||||
|
||||
syncURL = http://sync.scheduleworld.com/funambol/ds
|
||||
WebURL = http://sync.scheduleworld.com
|
||||
ConsumerReady = TRUE
|
|
@ -0,0 +1,2 @@
|
|||
type = addressbook:text/vcard
|
||||
uri = card3
|
|
@ -0,0 +1 @@
|
|||
uri = cal2
|
|
@ -0,0 +1 @@
|
|||
uri = note
|
|
@ -0,0 +1 @@
|
|||
uri = task2
|
Loading…
Reference in New Issue