Imported Upstream version 0.9.2~1.0alpha1 upstream/0.9.2_1.0alpha1
authorPatrick Ohly <patrick.ohly@intel.com>
Fri, 28 Jun 2013 11:40:07 +0000 (11:40 +0000)
committerPatrick Ohly <patrick.ohly@intel.com>
Fri, 28 Jun 2013 11:40:07 +0000 (11:40 +0000)
282 files changed:
ChangeLog
HACKING
Makefile-gen.am
Makefile.am
Makefile.in
NEWS
config.h.in
configure
configure-post.in
configure-pre.in
configure.in
po/LINGUAS
po/POTFILES.in
po/ca.po [deleted file]
src/CmdlineSyncClient.cpp
src/CmdlineSyncClient.h
src/DBusSyncClient.cpp [deleted file]
src/DBusSyncClient.h [deleted file]
src/Makefile-gen.am
src/Makefile.am
src/Makefile.in
src/backends/addressbook/Makefile.in
src/backends/evolution/EvolutionCalendarSource.cpp
src/backends/evolution/EvolutionCalendarSourceRegister.cpp
src/backends/evolution/EvolutionContactSourceRegister.cpp
src/backends/evolution/Makefile.am
src/backends/evolution/Makefile.in
src/backends/evolution/configure-sub.in
src/backends/file/FileSyncSourceRegister.cpp
src/backends/file/Makefile.am
src/backends/file/Makefile.in
src/backends/maemo/MaemoCalendarSource.cpp [deleted file]
src/backends/maemo/MaemoCalendarSource.h [deleted file]
src/backends/maemo/MaemoCalendarSourceRegister.cpp [deleted file]
src/backends/maemo/Makefile.am [deleted file]
src/backends/maemo/configure-sub.in [deleted file]
src/backends/sqlite/Makefile.in
src/backends/sqlite/SQLiteContactSource.cpp
src/backends/sqlite/SQLiteContactSource.h
src/backends/xmlrpc/Makefile.am [deleted file]
src/backends/xmlrpc/Makefile.in [deleted file]
src/backends/xmlrpc/README [deleted file]
src/backends/xmlrpc/XMLRPCSyncSource.cpp [deleted file]
src/backends/xmlrpc/XMLRPCSyncSource.h [deleted file]
src/backends/xmlrpc/XMLRPCSyncSourceRegister.cpp [deleted file]
src/backends/xmlrpc/configure-sub.in [deleted file]
src/client-test-app.cpp
src/dbus/Makefile.am
src/dbus/Makefile.in
src/dbus/README
src/dbus/interfaces/Makefile.am
src/dbus/interfaces/Makefile.in
src/dbus/interfaces/spec-to-docbook.xsl [new file with mode: 0644]
src/dbus/interfaces/syncevo-connection-full.xml [new file with mode: 0644]
src/dbus/interfaces/syncevo-marshal.list
src/dbus/interfaces/syncevo-server-full.xml [new file with mode: 0644]
src/dbus/interfaces/syncevo-session-full.xml [new file with mode: 0644]
src/dbus/interfaces/syncevo.xml [deleted file]
src/dbus/syncevo-dbus-types.c
src/dbus/syncevo-dbus-types.h
src/dbus/syncevo-dbus.c [deleted file]
src/dbus/syncevo-dbus.h [deleted file]
src/dbus/syncevo-server.c [new file with mode: 0644]
src/dbus/syncevo-server.h [new file with mode: 0644]
src/dbus/syncevo-session.c [new file with mode: 0644]
src/dbus/syncevo-session.h [new file with mode: 0644]
src/dbus/test.c
src/gdbus/Makefile.am [new file with mode: 0644]
src/gdbus/Makefile.in [moved from src/backends/maemo/Makefile.in with 65% similarity]
src/gdbus/README [new file with mode: 0644]
src/gdbus/debug.c [new file with mode: 0644]
src/gdbus/debug.h [new file with mode: 0644]
src/gdbus/gdbus-cxx-bridge.h [new file with mode: 0644]
src/gdbus/gdbus-cxx.h [new file with mode: 0644]
src/gdbus/gdbus.h [new file with mode: 0644]
src/gdbus/mainloop.c [new file with mode: 0644]
src/gdbus/object.c [new file with mode: 0644]
src/gdbus/test/example.cpp [new file with mode: 0644]
src/gdbus/watch.c [new file with mode: 0644]
src/gtk-ui/Makefile.am
src/gtk-ui/Makefile.in
src/gtk-ui/mux-icon-button.c
src/gtk-ui/mux-icon-button.h
src/gtk-ui/mux-window.c
src/gtk-ui/mux-window.h
src/gtk-ui/sync-config-widget.c [new file with mode: 0644]
src/gtk-ui/sync-config-widget.h [new file with mode: 0644]
src/gtk-ui/sync-ui-config.c
src/gtk-ui/sync-ui-config.h
src/gtk-ui/sync-ui-marshal.list [deleted file]
src/gtk-ui/sync-ui.c
src/gtk-ui/sync-ui.h
src/gtk-ui/ui.glade
src/org.syncevolution.service.in [moved from src/org.Moblin.SyncEvolution.service.in with 64% similarity]
src/syncclient_sample_config.xml
src/syncevo-dbus-server.cpp
src/syncevo-dbus-server.h [deleted file]
src/syncevo/Cmdline.cpp
src/syncevo/Cmdline.h
src/syncevo/ConfigNode.h
src/syncevo/ConfigTree.h
src/syncevo/CurlTransportAgent.cpp
src/syncevo/CurlTransportAgent.h
src/syncevo/DevNullConfigNode.h [new file with mode: 0644]
src/syncevo/FileConfigNode.cpp
src/syncevo/FileConfigNode.h
src/syncevo/FileConfigTree.cpp
src/syncevo/FileConfigTree.h
src/syncevo/FilterConfigNode.cpp
src/syncevo/FilterConfigNode.h
src/syncevo/HashConfigNode.h
src/syncevo/Makefile.am
src/syncevo/Makefile.in
src/syncevo/MultiplexConfigNode.cpp [new file with mode: 0644]
src/syncevo/MultiplexConfigNode.h [new file with mode: 0644]
src/syncevo/ObexTransportAgent.cpp [new file with mode: 0644]
src/syncevo/ObexTransportAgent.h [new file with mode: 0644]
src/syncevo/PrefixConfigNode.cpp
src/syncevo/PrefixConfigNode.h
src/syncevo/SafeConfigNode.cpp
src/syncevo/SafeConfigNode.h
src/syncevo/SoupTransportAgent.cpp
src/syncevo/SoupTransportAgent.h
src/syncevo/SyncConfig.cpp
src/syncevo/SyncConfig.h
src/syncevo/SyncContext.cpp
src/syncevo/SyncContext.h
src/syncevo/SyncEvolutionXML.c
src/syncevo/SyncML.cpp
src/syncevo/SyncML.h
src/syncevo/SyncSource.cpp
src/syncevo/SyncSource.h
src/syncevo/SynthesisDBPlugin.cpp
src/syncevo/SynthesisEngine.cpp
src/syncevo/SynthesisEngine.h
src/syncevo/TrackingSyncSource.cpp
src/syncevo/TrackingSyncSource.h
src/syncevo/TransportAgent.cpp [new file with mode: 0644]
src/syncevo/TransportAgent.h
src/syncevo/VolatileConfigTree.h
src/syncevo/eds_abi_wrapper.cpp
src/syncevo/eds_abi_wrapper.h
src/syncevo/util.cpp
src/syncevo/util.h
src/syncevolution.cpp
src/synthesis/ChangeLog
src/synthesis/Makefile.am
src/synthesis/Makefile.in
src/synthesis/config.h.in
src/synthesis/configure
src/synthesis/configure.in
src/synthesis/src/DB_interfaces/api_db/pluginapiagent.cpp
src/synthesis/src/DB_interfaces/api_db/pluginapiagent.h
src/synthesis/src/DB_interfaces/api_db/pluginapids.cpp
src/synthesis/src/DB_interfaces/api_db/pluginapids.h
src/synthesis/src/DB_interfaces/odbc_db/odbcapiagent.cpp
src/synthesis/src/DB_interfaces/odbc_db/odbcapiagent.h
src/synthesis/src/DB_interfaces/odbc_db/odbcapids.cpp
src/synthesis/src/DB_interfaces/odbc_db/odbcdb.h
src/synthesis/src/EXCLUDE_FILES
src/synthesis/src/EXTRA_FILES
src/synthesis/src/Makefile.am
src/synthesis/src/Makefile.am.in
src/synthesis/src/Makefile.in
src/synthesis/src/SDK_FILES
src/synthesis/src/SERVER_FILES
src/synthesis/src/Targets/ReleasedProducts/combiEngine_opensource_linux/combiengine_demo++.pch [new file with mode: 0644]
src/synthesis/src/Targets/ReleasedProducts/combiEngine_opensource_linux/combiengine_demo.pch [new file with mode: 0644]
src/synthesis/src/Targets/ReleasedProducts/combiEngine_opensource_linux/combiengine_opensource_linux_prefix.h [new file with mode: 0644]
src/synthesis/src/Targets/ReleasedProducts/combiEngine_opensource_linux/define.h [new file with mode: 0644]
src/synthesis/src/Targets/ReleasedProducts/combiEngine_opensource_linux/target_options.h [new file with mode: 0644]
src/synthesis/src/Targets/ReleasedProducts/serverEngine_opensource_linux/serverengine_opensource++.pch [moved from src/synthesis/src/Targets/ReleasedProducts/serverEngine_opensource_linux/serverengine_demo++.pch with 100% similarity]
src/synthesis/src/Targets/ReleasedProducts/serverEngine_opensource_linux/serverengine_opensource.pch [moved from src/synthesis/src/Targets/ReleasedProducts/serverEngine_opensource_linux/serverengine_demo.pch with 100% similarity]
src/synthesis/src/Targets/ReleasedProducts/serverEngine_opensource_linux/target_options.h
src/synthesis/src/Transport_interfaces/engine/engine_server.h [new file with mode: 0644]
src/synthesis/src/Transport_interfaces/engine/engine_server_precomp.h [new file with mode: 0644]
src/synthesis/src/Transport_interfaces/engine/engineclientbase.cpp
src/synthesis/src/Transport_interfaces/engine/engineclientbase.h
src/synthesis/src/Transport_interfaces/engine/enginesessiondispatch.cpp [new file with mode: 0644]
src/synthesis/src/Transport_interfaces/engine/enginesessiondispatch.h [new file with mode: 0644]
src/synthesis/src/client_engine_linux.mk
src/synthesis/src/combi_engine_linux.mk [new file with mode: 0644]
src/synthesis/src/gen-makefile-am.sh
src/synthesis/src/global_options.h
src/synthesis/src/platform_adapters/linux/configfiles.cpp
src/synthesis/src/platform_adapters/linux/platform_DLL.cpp
src/synthesis/src/platform_adapters/linux/platform_time.cpp
src/synthesis/src/platform_adapters/platform_thread.h
src/synthesis/src/platform_adapters/unix_common/platform_thread.cpp
src/synthesis/src/server_engine_linux.mk [new file with mode: 0644]
src/synthesis/src/syncapps/clientEngine_custom/clientengine_custom_Base.cpp
src/synthesis/src/syncapps/clientEngine_custom/product_options.h
src/synthesis/src/syncapps/serverEngine_custom/combi_product_options.h [new file with mode: 0644]
src/synthesis/src/syncapps/serverEngine_custom/product_options.h [new file with mode: 0644]
src/synthesis/src/syncapps/serverEngine_custom/serverengine_custom.h [new file with mode: 0644]
src/synthesis/src/syncapps/serverEngine_custom/serverengine_custom_Base.cpp [new file with mode: 0644]
src/synthesis/src/syncapps/serverEngine_custom/serverengine_custom_Base.h [new file with mode: 0644]
src/synthesis/src/syncapps/serverEngine_custom/serverengine_custom_precomp.h [new file with mode: 0644]
src/synthesis/src/syncapps/sysytool/sysytool.cpp
src/synthesis/src/syncml_tk/src/sml/xlt/all/xltenc.c
src/synthesis/src/synthesis-linker.map
src/synthesis/src/sysync/binfileimplclient.cpp
src/synthesis/src/sysync/binfileimplclient.h
src/synthesis/src/sysync/binfileimplds.cpp
src/synthesis/src/sysync/binfileimplds.h
src/synthesis/src/sysync/customimplagent.cpp
src/synthesis/src/sysync/customimplagent.h
src/synthesis/src/sysync/customimplds.cpp
src/synthesis/src/sysync/customimplds.h
src/synthesis/src/sysync/dataconversion.cpp
src/synthesis/src/sysync/dataobjtype.cpp
src/synthesis/src/sysync/debuglogger.cpp
src/synthesis/src/sysync/debuglogger.h
src/synthesis/src/sysync/engineentry.h
src/synthesis/src/sysync/engineinterface.cpp
src/synthesis/src/sysync/engineinterface.h
src/synthesis/src/sysync/localengineds.cpp
src/synthesis/src/sysync/localengineds.h
src/synthesis/src/sysync/mimedirprofile.cpp
src/synthesis/src/sysync/multifielditem.cpp
src/synthesis/src/sysync/multifielditem.h
src/synthesis/src/sysync/multifielditemtype.cpp
src/synthesis/src/sysync/remotedatastore.cpp
src/synthesis/src/sysync/remotedatastore.h
src/synthesis/src/sysync/scriptcontext.cpp
src/synthesis/src/sysync/stdlogicagent.cpp
src/synthesis/src/sysync/stdlogicagent.h
src/synthesis/src/sysync/stdlogicds.cpp
src/synthesis/src/sysync/stdlogicds.h
src/synthesis/src/sysync/stringutils.cpp
src/synthesis/src/sysync/superdatastore.cpp
src/synthesis/src/sysync/superdatastore.h
src/synthesis/src/sysync/syncagent.cpp [new file with mode: 0755]
src/synthesis/src/sysync/syncagent.h [moved from src/synthesis/src/sysync/syncclient.h with 60% similarity]
src/synthesis/src/sysync/syncappbase.cpp
src/synthesis/src/sysync/syncappbase.h
src/synthesis/src/sysync/syncclient.cpp [deleted file]
src/synthesis/src/sysync/syncclientbase.cpp
src/synthesis/src/sysync/syncclientbase.h
src/synthesis/src/sysync/synccommand.cpp
src/synthesis/src/sysync/synccommand.h
src/synthesis/src/sysync/syncdatastore.cpp
src/synthesis/src/sysync/syncdatastore.h
src/synthesis/src/sysync/syncitem.cpp
src/synthesis/src/sysync/syncitem.h
src/synthesis/src/sysync/syncserver.cpp [deleted file]
src/synthesis/src/sysync/syncserver.h [deleted file]
src/synthesis/src/sysync/syncsession.cpp
src/synthesis/src/sysync/syncsession.h
src/synthesis/src/sysync/syncsessiondispatch.cpp
src/synthesis/src/sysync/syncsessiondispatch.h
src/synthesis/src/sysync/syserial.h
src/synthesis/src/sysync/sysync_globs.h
src/synthesis/src/sysync/sysync_precomp.h
src/synthesis/src/sysync/textprofile.cpp
src/synthesis/src/sysync_SDK/DB_Interfaces/text_db/sync_dbapi_text.cpp
src/synthesis/src/sysync_SDK/Sources/SDK_util.c
src/synthesis/src/sysync_SDK/Sources/UI_util.cpp
src/synthesis/src/sysync_SDK/Sources/UI_util.h
src/synthesis/src/sysync_SDK/Sources/enginemodulebase.h
src/synthesis/src/sysync_SDK/Sources/enginemodulebridge.cpp
src/synthesis/src/sysync_SDK/Sources/enginemodulebridge.h
src/synthesis/src/sysync_SDK/Sources/enginestubs.c [new file with mode: 0644]
src/synthesis/src/sysync_SDK/Sources/generic_types.h
src/synthesis/src/sysync_SDK/Sources/san.cpp [moved from src/synthesis/src/sysync/san.cpp with 99% similarity]
src/synthesis/src/sysync_SDK/Sources/san.h [moved from src/synthesis/src/sysync/san.h with 100% similarity]
src/synthesis/src/sysync_SDK/Sources/stringutil.cpp
src/synthesis/src/sysync_SDK/Sources/sync_dbapidef.h
src/synthesis/src/sysync_SDK/Sources/sysync_b64.cpp [moved from src/synthesis/src/sysync/sysync_b64.cpp with 97% similarity]
src/synthesis/src/sysync_SDK/Sources/sysync_b64.h [moved from src/synthesis/src/sysync/sysync_b64.h with 100% similarity]
src/synthesis/src/sysync_SDK/Sources/sysync_md5.cpp [moved from src/synthesis/src/sysync/sysync_md5.cpp with 97% similarity]
src/synthesis/src/sysync_SDK/Sources/sysync_md5.h [moved from src/synthesis/src/sysync/sysync_md5.h with 89% similarity]
src/synthesis/src/sysync_SDK/configs/syncserv_sample_config.xml [new file with mode: 0755]
src/synthesis/synthesis-sdk.pc.in [new file with mode: 0644]
src/synthesis/synthesis.pc.in
src/testcases/vcard30.vcf.zyb.tem [new file with mode: 0644]
test/ClientTest.cpp
test/ClientTest.h
test/Makefile.in
test/README.mobical
test/README.zyb [new file with mode: 0644]
test/synccompare.pl

index 2666969..709d159 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
 # Generated by configure.  Do no edit.
 
-2010-01-22  Patrick Ohly  <patrick.ohly@intel.com>
+2009-12-02  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * po/POTFILES.in:
+
+       autotools + GTK GUI: added sync-config-widget.c to PO files
+
+2009-12-02  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/dbus/interfaces/Makefile.am:
 
+       autotools + D-Bus API: must include the new .xml and .xsl files
+
+2009-12-02  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * NEWS:
        * configure-pre.in:
 
-       configure: version bumped to 0.9.2
+       NEWS + configure: SyncEvolution 1.0 alpha 1 snapshot
 
-2010-01-22  Patrick Ohly  <patrick.ohly@intel.com>
+2009-12-02  Jussi Kukkonen  <jku@linux.intel.com>
 
-       * src/backends/maemo/configure-sub.in:
+       * src/gtk-ui/sync-ui.c:
 
-       Maemo backend: fixed static linking
+       gtk-ui: make sure we only sync once whe nasked
 
-2010-01-22  Patrick Ohly  <patrick.ohly@intel.com>
+2009-12-02  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * src/Makefile-gen.am:
+       * src/syncevo-dbus-server.cpp:
+       * test/test-dbus.py:
 
-       autotools: fixed typo in CPPUnit patch
+       CheckSource(): did not handle invalid or missing "type" property
+       (MB #8317)
 
-2010-01-22  Patrick Ohly  <patrick.ohly@intel.com>
+2009-11-30  Jussi Kukkonen  <jku@linux.intel.com>
 
-       * NEWS:
+       * configure-pre.in:
+       * src/gtk-ui/sync-config-widget.c:
+       * src/gtk-ui/sync-ui.c:
 
-       NEWS: final 0.9.2
+       gtk-ui: use defaultPeer config value on startup
 
-2010-01-22  Patrick Ohly  <patrick.ohly@intel.com>
+2009-12-02  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * src/backends/maemo/MaemoCalendarSourceRegister.cpp:
+       * src/syncevo/SoupTransportAgent.cpp:
 
-       Maemo backend + testing: unique names, always enabled
+       SoupTransportAgent + syncevo-dbus-server: avoid segfault when
+       aborting (MB #8385)
 
-2010-01-22  Patrick Ohly  <patrick.ohly@intel.com>
+2009-11-26  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
 
-       * src/Makefile-gen.am:
-       * src/backends/evolution/EvolutionCalendarSourceRegister.cpp:
-       * src/backends/evolution/EvolutionContactSourceRegister.cpp:
-       * src/backends/file/FileSyncSourceRegister.cpp:
-       * src/syncevo/SyncSource.h:
+       * src/syncevo-dbus-server.cpp:
+       * test/test-dbus.py:
 
-        CPPUnit header file dependency for backends (MB #9149)
+       DBus server: apply temporary configs (MB#8116)
 
-2010-01-21  Ove Kaaven  <ovek@arcticnet.no>
+2009-12-02  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
 
-       * src/backends/maemo/Makefile.am:
+       * src/syncevo/SyncConfig.cpp:
 
-       Remove dependency on cppunit, like recently done in the other
-       backends as well.
+       SyncConfig: return sources in shared, peer and filters for
+       getSyncSources
 
-2010-01-21  Ove Kaaven  <ovek@arcticnet.no>
+2009-12-01  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
 
-       * debian/control:
+       * test/test-dbus.py:
 
-       Added some missing build dependencies
+       DBus testing: add unit tests for status and progress
 
-2010-01-19  Ove Kaaven  <ovek@arcticnet.no>
+2009-11-30  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
 
-       * debian/control:
+       * src/syncevo-dbus-server.cpp:
 
-       Set appropriate (non-user) section for dev package
+       DBus server: only flush status when changed for SESSION_END
 
-2010-01-19  Ove Kaaven  <ovek@arcticnet.no>
+2009-11-27  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
 
-       * debian/rules:
+       * src/syncevo-dbus-server.cpp:
 
-       Set configure flags that I'll use on Maemo 5
+       DBus server: set 'running' status in Session.run
 
-2010-01-19  Ove Kaaven  <ovek@arcticnet.no>
+2009-11-30  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
 
-       * debian/control:
+       * test/test-dbus.py:
 
-       Updated build depends, added a description, and made myself
-       maintainer.
+       DBus testing: remove one obsolete unit test for GetReports
 
-2010-01-19  Ove Kaaven  <ovek@arcticnet.no>
+2009-12-01  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * debian/changelog:
+       * Makefile-gen.am:
 
-       Bump version, ready to release
+       autotools + deb: removed dependency on doc_pak
 
-2010-01-19  Ove Kaaven  <ovek@arcticnet.no>
+2009-11-25  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * debian/optify:
+       * test/runtests.py:
 
-       Enable auto-optification
+       nightly testing: git fetch fixes
 
-2010-01-19  Ove Kaaven  <ovek@arcticnet.no>
+2009-11-24  tester  <tester@knlcst4.ikn.intel.com>
 
-       * src/backends/maemo/MaemoCalendarSource.cpp:
-       * src/backends/maemo/MaemoCalendarSource.h:
-       * src/backends/maemo/MaemoCalendarSourceRegister.cpp:
-       * src/backends/maemo/Makefile.am:
-       * src/backends/maemo/configure-sub.in:
+       * test/runtests.py:
 
-       Checkin of working Maemo backend
+       test/runtest.py: git checkout debugging
 
-2010-01-09  Ove Kaaven  <ovek@arcticnet.no>
+2009-11-17  Chen Congwu  <congwu.chen@intel.com>
 
-       * debian/changelog:
+       * test/resultchecker.py:
 
-       Put "beta" in the version number
+       Testing: result check
 
-2010-01-09  Ove Kaaven  <ovek@arcticnet.no>
+2009-11-13  Chen Congwu  <congwu.chen@intel.com>
 
-       * debian/syncevolution.install:
+       * test/resultchecker.py:
 
-       Install /usr/share instead of /etc/default
+       Testing: A special case set has slightly differnt case name
 
-2010-01-09  Ove Kaaven  <ovek@arcticnet.no>
+2009-11-12  Chen Congwu  <congwu.chen@intel.com>
 
-       * debian/changelog:
+       * test/resultchecker.py:
 
-       Update Debian changelog again
+       Testing Result Check: check "okay" instead of "fail" because of
+       possible crash
 
-2010-01-22  Patrick Ohly  <patrick.ohly@intel.com>
+2009-11-11  Chen Congwu  <congwu.chen@intel.com>
 
-       * src/syncclient_sample_config.xml:
+       * test/resultchecker.py:
 
-       syncclient_sample_config.xml: added "GENDER" and "SIP"
+        Testing result checker: change the result checker grep criteria
 
-2009-12-23  Ove Kaaven  <ovek@arcticnet.no>
+2009-11-10  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * test/Algorithm/Diff.pm.bak:
+       * test/runtests.py:
 
-       Remove redundant file
+       runtests.py: run setup command twice, just to be sure
 
-2009-12-23  Ove Kaaven  <ovek@arcticnet.no>
+2009-10-28  Chen Congwu  <congwu.chen@intel.com>
 
-       * debian/changelog:
+       * test/resultchecker.py:
 
-       Update Debian changelog
+       Testing: fix some issues for prebuilt test
 
-2009-12-23  Ove Kaaven  <ovek@arcticnet.no>
+2009-10-28  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
 
-       * debian/rules:
+       * test/runtests.py:
 
-       Set sysconfdir.
+       Testing: clean log/test files before a new testing
 
-2009-12-23  Ove Kaaven  <ovek@arcticnet.no>
+2009-10-27  Chen Congwu  <congwu.chen@intel.com>
 
-       * debian/control:
-       * debian/rules:
-       * debian/syncevolution-dev.install:
-       * debian/syncevolution.install:
+       * test/resultchecker.py:
 
-       Split package into "syncevolution" and "syncevolution-dev"
-       packages.
+       Testing: show evolution-prebuilt in html output(bug#7160)
 
-2010-01-06  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+2009-10-23  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
 
-       * src/syncclient_sample_config.xml:
+       * test/compare.xsl:
+       * test/generate-html.xsl:
 
-       Config: add support for 'X-SKYPE' for evolution (MB#8948)
+       Testing: show evolution-prebuilt in html output(bug#7160)
 
-2010-01-19  Patrick Ohly  <patrick.ohly@intel.com>
+2009-10-21  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * src/Makefile-gen.am:
+       * test/runtests.py:
 
-       fixed link error related to CPPUnit
+       runtest.py: fixed checking out branch from git
 
-2010-01-19  Patrick Ohly  <patrick.ohly@intel.com>
+2009-10-21  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * configure-pre.in:
+       * test/runtests.py:
 
-       set version to 0.9.1+0.9.2
+       runtest.py: point prebuilt binaries to correct location of
+       backends
 
-2010-01-19  Patrick Ohly  <patrick.ohly@intel.com>
+2009-10-21  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
 
-       * NEWS:
+       * test/evo.supp:
+
+       Testing: add suppressions for valgrind in evo.supp
+
+2009-10-19  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * test/resultchecker.py:
+       * test/runtests.py:
+
+       Testing: refine return code checkings(bug#6457)
+
+2009-10-16  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * test/valgrindcheck.sh:
+
+       valgrindcheck.sh: don't force --leak-check and --trace-children
+
+2009-07-15  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * test/README.zyb:
+       * test/testcases/vcard30.vcf.zyb.tem.patch:
+
+       ZYB: add README.zyb and customize test cases(MB#2424)
+
+2009-07-13  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * test/ClientTest.cpp:
+       * test/ClientTest.h:
+
+       client-test+ZYB: set maxMsgSize and maxObjSize as default value
+       (MB#2424)
+
+2009-07-13  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * test/synccompare.pl:
+
+       ZYB: Ignore some properties comparison(MB#2424)
+
+2009-12-01  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * src/syncclient_sample_config.xml:
+
+       syncclient config: disable anchors checking for ZYB(MB#8138)
+
+2009-12-01  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * test/README.mobical:
+       * test/runtests.py:
 
-       NEWS: updated for 0.9.2
+       Mobical: skip unit test testOneWayFromClient(MB#8121)
 
-2010-01-18  Patrick Ohly  <patrick.ohly@intel.com>
+2009-12-01  Patrick Ohly  <patrick.ohly@intel.com>
 
        * src/syncevo/Cmdline.cpp:
+       * test/test-dbus.py:
+
+       shared config + templates: must share global properties
+
+2009-12-01  Patrick Ohly  <patrick.ohly@intel.com>
+
        * src/syncevo/SyncConfig.cpp:
 
-       ScheduleWorld: changed webURL
+       defaultPeer: also shared when using legacy configs (MB #8334)
 
-2010-01-18  Patrick Ohly  <patrick.ohly@intel.com>
+2009-12-01  Patrick Ohly  <patrick.ohly@intel.com>
 
+       * src/Makefile-gen.am:
        * src/syncevo/Cmdline.cpp:
        * src/syncevo/SyncConfig.cpp:
 
-       Goosync: added template (MB #9113)
+       fixed reading templates from file (MB #8335)
 
-2009-10-29  Patrick Ohly  <patrick.ohly@intel.com>
+2009-12-01  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * src/syncevo/Cmdline.cpp:
        * src/syncevo/SyncConfig.cpp:
 
-       Oracle: added template
+       virtual backend help text: updated evolutionsource comment
 
-2010-01-15  Patrick Ohly  <patrick.ohly@intel.com>
+2009-12-01  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * NEWS:
+       * src/syncevo/SyncConfig.cpp:
 
-       updated for 0.9.2
+       config templates: "sync" property expected to be set
 
-2010-01-15  Patrick Ohly  <patrick.ohly@intel.com>
+2009-12-01  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * src/syncevo/eds_abi_wrapper.cpp:
-       * src/syncevo/eds_abi_wrapper.h:
 
-       build issue: icalproperty_remove_parameter_by_kind in EDS wrapper
+       Merge remote branch 'origin/syncevolution-0-9-branch'
 
-2010-01-15  Patrick Ohly  <patrick.ohly@intel.com>
+2009-12-01  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * Makefile-gen.am:
+       * src/syncevo/SyncSource.cpp:
 
-       autotools: fixed 'make dist' error cause by doc-pak
+       SyncSource.cpp: g++ 4.4 compiler bug workaround
 
-2009-12-18  Rajyalakshmi Bommaraju  <Rajyalakshmi.Bommaraju@intel.com>
+2009-11-30  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * src/syncclient_sample_config.xml:
+       * configure-post.in:
 
-       syncclient_sample_config.xml: create fullname if empty (MB#5664)
+       autotools: fixed installation of backends with recent libtool
 
-2010-01-15  Patrick Ohly  <patrick.ohly@intel.com>
+2009-11-25  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * src/syncevo/TrackingSyncSource.cpp:
-       * src/syncevo/TrackingSyncSource.h:
+       * src/syncevo/Cmdline.cpp:
 
-       syncevolution --status: statistics empty (MB #9097)
+       syncevolution --migrate: support migration into a certain context
 
-2009-12-15  Rajyalakshmi Bommaraju  <Rajyalakshmi.Bommaraju@intel.com>
+2009-11-25  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * src/syncevo/SyncConfig.cpp:
+       * src/syncevo/Cmdline.cpp:
 
-       SyncConfig: Read http_proxy from environment (MB#8177)
+       syncevolution --migrate: copy .synthesis directory (MB #8048)
 
-2010-01-11  Patrick Ohly  <patrick.ohly@intel.com>
+2009-11-25  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * configure-post.in:
+       * src/syncevo/util.cpp:
+       * src/syncevo/util.h:
 
-       autotools: added workaround for lack of --with-docdir
+       utility function: cp_r() for recursive copying
 
-2009-12-11  Rajyalakshmi Bommaraju  <rajyalakshmi.bommaraju@intel.com>
+2009-12-01  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * src/backends/evolution/EvolutionCalendarSource.cpp:
+       * src/syncevo/SyncContext.cpp:
 
-       Evolution calendar: work around 'cannot encode item' problem (MB
-       #7879)
+       syncevo-dbus-server: incoming SyncML message not handled
 
-2010-01-11  Patrick Ohly  <patrick.ohly@intel.com>
+2009-12-01  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * src/syncevo/TrackingSyncSource.h:
+       * test/test-dbus.py:
 
-       TrackingSyncSource: clarify what "raw" means
+       test-dbus.py: adapted to new org.syncevolution.SourceUnusable
 
-2010-01-11  Patrick Ohly  <patrick.ohly@intel.com>
+2009-12-01  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * src/backends/evolution/EvolutionCalendarSourceRegister.cpp:
+       * src/syncevo-dbus-server.cpp:
 
-       EvolutionCalendarSource: fixed typo in "type" description
+       syncevo-dbus-server: GetConfig() and check for existing config
 
-2010-01-06  Chen Congwu  <congwu.chen@intel.com>
+2009-11-30  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * configure-pre.in:
-       * src/backends/evolution/Makefile.am:
-       * src/backends/file/Makefile.am:
-       * src/backends/xmlrpc/Makefile.am:
 
-       Build: do not depend on cppunit for backends
+       Merge remote branch 'origin/syncevolution-0-9-branch'
+
+2009-11-30  Patrick Ohly  <patrick.ohly@intel.com>
 
-2010-01-02  gforcada  <gforcada@gnome.org>
+       * src/syncevo-dbus-server.cpp:
 
-       * po/ca.po:
+       syncevo-dbus-server: fixed size_t printing
 
-       l10n: Added Catalan translation
+2009-11-30  Patrick Ohly  <patrick.ohly@intel.com>
 
-2009-12-14  Franz Knipp  <knipp@m-otion.com>
+       * src/dbus/syncevo-server.c:
 
-       * src/backends/xmlrpc/Makefile.am:
-       * src/backends/xmlrpc/README:
-       * src/backends/xmlrpc/XMLRPCSyncSource.cpp:
-       * src/backends/xmlrpc/XMLRPCSyncSource.h:
-       * src/backends/xmlrpc/XMLRPCSyncSourceRegister.cpp:
-       * src/backends/xmlrpc/configure-sub.in:
+       syncevo-server.c: detach_cb unused compiler warning
 
-       XMLRPC backend
+2009-11-30  Patrick Ohly  <patrick.ohly@intel.com>
 
-2009-12-09  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * src/backends/evolution/EvolutionCalendarSource.cpp:
+       Merge branch 'origin/jku' (early part)
 
-       EDS Calendar: set pointer to NULL to protect against ecal bug (MB
-       #8005)
+2009-11-30  Patrick Ohly  <patrick.ohly@intel.com>
 
-2009-12-09  Patrick Ohly  <patrick.ohly@intel.com>
+       * src/gdbus/Makefile.am:
 
-       * configure-post.in:
-       * src/Makefile-gen.am:
-       * src/backends/evolution/configure-sub.in:
+       gdbus-cxx: header file must be distributed
+
+2009-11-30  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-ui.c:
+
+       gtk-ui: remove unused function + variable
+
+2009-11-30  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/dbus/syncevo-dbus-types.c:
+
+       dbus wrapper: take copy of source name for SyncevoSourceProgress
+
+2009-11-30  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-ui.c:
+
+       gtk-ui: remove window title in moblin version (MB#6806)
+
+2009-11-27  Chen Congwu  <congwu.chen@intel.com>
+
+       * src/syncevo/SyncContext.cpp:
+
+       Server alerted Sync: fix the timeout and signal handling during
+       SAN
+
+2009-11-27  Chen Congwu  <congwu.chen@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+       * src/syncevo/SyncContext.cpp:
 
-       autotools: cleaned up checking for GNOME/EDS libs (MB #8338)
+       SyncContext: detect server or client session before instantiating
+       the engine.
 
-2009-12-09  Patrick Ohly  <patrick.ohly@intel.com>
+2009-11-27  Chen Congwu  <congwu.chen@intel.com>
+
+       * src/syncevo/SyncContext.cpp:
+       * src/syncevo/SyncContext.h:
+
+       Revert "Server alerted sync: ensure only one SynthesisEngine is
+       active"
+
+2009-11-27  Chen Congwu  <congwu.chen@intel.com>
 
        * src/backends/file/FileSyncSourceRegister.cpp:
+       * src/syncevo/SyncConfig.cpp:
+       * src/syncevo/SyncML.cpp:
+       * src/syncevo/SyncSource.cpp:
+       * src/syncevo/SyncSource.h:
 
-       file backend: clarified documenation (MB #8146)
+       FileSyncSource: use x-vcalendar instead of x-calendar
 
-2009-12-02  Patrick Ohly  <patrick.ohly@intel.com>
+2009-11-26  Chen Congwu  <congwu.chen@intel.com>
 
-       * src/syncevo/SoupTransportAgent.cpp:
+       * src/syncevo/SyncML.cpp:
 
-       SoupTransportAgent + syncevo-dbus-server: avoid segfault when
-       aborting (MB #8385)
+       Server alerted sync: fix a typo in SyncMode parsing
+
+2009-11-26  Chen Congwu  <congwu.chen@intel.com>
+
+       * src/syncevo/ObexTransportAgent.cpp:
+       * src/syncevo/ObexTransportAgent.h:
+
+       ObexTransportAgent: fixing an obex event leak for SyncML server
+       case
+
+2009-11-26  Chen Congwu  <congwu.chen@intel.com>
+
+       * src/syncevo/SyncContext.cpp:
+
+       Server alerted Sync: Throw error if no source is enabled during
+       SAN generation.
+
+2009-11-23  Chen Congwu  <congwu.chen@intel.com>
+
+       * src/syncevo/SyncConfig.cpp:
+       * src/syncevo/SyncContext.cpp:
+       * src/syncevo/SyncSource.h:
+       * src/syncevo/util.cpp:
+       * src/syncevo/util.h:
+
+       Join/dejoin Mutiple SyncSources, MB#4611
+
+2009-11-18  Chen Congwu  <congwu.chen@intel.com>
+
+       * src/syncevo/SyncConfig.cpp:
+       * src/syncevo/SyncContext.cpp:
+
+       Sever Alerted Sync: SAN generation
+
+2009-11-18  Chen Congwu  <congwu.chen@intel.com>
+
+       * src/syncevo/ObexTransportAgent.cpp:
+       * src/syncevo/SyncContext.cpp:
+
+       Server Alerted Sync: SAN generation
+
+2009-11-18  Chen Congwu  <congwu.chen@intel.com>
+
+       * src/syncevo/SyncML.cpp:
+
+       Server Alerted Sync: SAN generation
+
+2009-11-18  Chen Congwu  <congwu.chen@intel.com>
+
+       * src/backends/sqlite/SQLiteContactSource.h:
+       * src/syncevo/SyncContext.cpp:
+       * src/syncevo/SyncML.cpp:
+       * src/syncevo/SyncML.h:
+       * src/syncevo/SyncSource.h:
+       * src/syncevo/TrackingSyncSource.cpp:
+       * src/syncevo/TrackingSyncSource.h:
+
+       Server Alerted Sync: Set Content Type in SAN
+
+2009-11-30  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-ui.c:
+
+       gtk-ui: change name 'Addressbook'->'Contacts' (MB#6514)
+
+2009-11-30  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-ui.c:
+       * src/gtk-ui/ui.glade:
+
+       gtk-ui: bring back the destuctive sync mode options
 
 2009-11-30  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * configure-post.in:
+       * src/syncevo/SyncContext.cpp:
 
-       autotools: fixed installation of backends with recent libtool
+       SyncContext: set log file name to "syncevolution-log.html"
+
+2009-11-30  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-ui.c:
+
+       gtk-ui: set sync-button sensitivity based on Presence
+
+2009-11-27  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/Cmdline.cpp:
+       * src/syncevo/SyncConfig.cpp:
+
+       configuration: updated to match server use cases (MB #7710)
+
+2009-11-27  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/dbus/interfaces/syncevo-server-full.xml:
+
+       D-Bus API: further explanations for Server.GetReports()
+
+2009-11-25  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * src/dbus/interfaces/syncevo-server-full.xml:
+       * src/syncevo-dbus-server.cpp:
+       * test/test-dbus.py:
+
+       DBus server: change the behavior of GetReports(MB#8049)
 
 2009-11-27  Patrick Ohly  <patrick.ohly@intel.com>
 
 
 2009-11-27  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * gen-autotools.sh:
-       * src/Makefile-gen.am:
-       * src/README.templates:
-       * src/default/README:
-       * src/default/syncevolution/Funambol/config.ini:
-       * src/default/syncevolution/Funambol/sources/addressbook/config.ini:
-       * src/default/syncevolution/Funambol/sources/calendar/config.ini:
-       * src/default/syncevolution/Funambol/sources/memo/config.ini:
-       * src/default/syncevolution/Funambol/sources/todo/config.ini:
-       * src/default/syncevolution/ScheduleWorld/config.ini:
-       * src/default/syncevolution/ScheduleWorld/sources/addressbook/config.ini:
-       * src/default/syncevolution/ScheduleWorld/sources/calendar/config.ini:
-       * src/default/syncevolution/ScheduleWorld/sources/memo/config.ini:
+       * src/backends/evolution/EvolutionContactSource.cpp:
+
+       Evolution Address Book: avoid picking CouchDB by default (MB
+       #7877)
+
+2009-11-27  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-config-widget.c:
+       * src/gtk-ui/sync-ui.c:
+
+       gtk-ui: solve focus and scroll issues in service list
+
+2009-11-27  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/SyncContext.cpp:
+
+       SyncContext::createTransport(): https not recognized (MB #8300)
+
+2009-11-27  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * gen-autotools.sh:
+       * src/Makefile-gen.am:
+       * src/README.templates:
+       * src/default/README:
+       * src/default/syncevolution/Funambol/config.ini:
+       * src/default/syncevolution/Funambol/sources/addressbook/config.ini:
+       * src/default/syncevolution/Funambol/sources/calendar/config.ini:
+       * src/default/syncevolution/Funambol/sources/memo/config.ini:
+       * src/default/syncevolution/Funambol/sources/todo/config.ini:
+       * src/default/syncevolution/ScheduleWorld/config.ini:
+       * src/default/syncevolution/ScheduleWorld/sources/addressbook/config.ini:
+       * src/default/syncevolution/ScheduleWorld/sources/calendar/config.ini:
+       * src/default/syncevolution/ScheduleWorld/sources/memo/config.ini:
        * src/default/syncevolution/ScheduleWorld/sources/todo/config.ini:
        * src/syncevo/Makefile.am:
        * src/templates/Funambol/config.ini:
        * src/templates/ScheduleWorld/sources/memo/config.ini:
        * src/templates/ScheduleWorld/sources/todo/config.ini:
 
-       installation: templates now in $(datadir)/syncevolution/templates
-       (MB #7808)
+       installation: templates now in $(datadir)/syncevolution/templates
+       (MB #7808)
+
+2009-11-27  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * Makefile-gen.am:
+
+       autotools: install doc files in normal --docdir (MB #7168)
+
+2009-11-27  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * Makefile-gen.am:
+
+       autotools: include gen-autotools.sh in source tar ball (MB #7822)
+
+2009-11-24  Kristho  <lakristho@gmail.com>
+
+       * po/da.po:
+
+       l10n: Danish translation of syncevolution.
+
+2009-11-16  itsoftex  <yousef@itsoftex.com>
+
+       * po/ar.po:
+
+       l10n: Updates to Arabic (ar) translation
+
+2009-11-16  itsoftex  <yousef@itsoftex.com>
+
+       * po/ar.po:
+
+       l10n: Arabic Translation, partial upload.
+
+2009-11-12  GLS_JPN  <etsukox.murozono@intel.com>
+
+       * po/ja.po:
+
+       l10n: Updates to Japanese (ja) translation
+
+2009-11-24  tomasgalicia  <tomas.galicia@intel.com>
+
+       * po/pt_BR.po:
+
+       l10n: Updates to Brazilian Portuguese (pt_BR) translation
+
+2009-11-24  tomasgalicia  <tomas.galicia@intel.com>
+
+       * po/it.po:
+
+       l10n: Updates to Italian (it) translation
+
+2009-11-26  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/SyncConfig.cpp:
+
+       deviceData property: updated comment
+
+2009-11-26  Chen Congwu  <congwu.chen@intel.com>
+
+       * src/syncevo/SyncContext.cpp:
+
+       Fix a compiler warning
+
+2009-11-26  tester  <tester@knlcst4.ikn.intel.com>
+
+       * src/Makefile-gen.am:
+
+       syncevo-dbus-server: libsoup compile problem
+
+2009-11-26  tester  <tester@knlcst4.ikn.intel.com>
+
+       * configure-pre.in:
+
+       link problem: sysync::SySyncDebugPuts()
+
+2009-11-26  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-config-widget.c:
+       * src/gtk-ui/sync-ui.c:
+
+       gtk-ui: add better comments for missing error msgs
+
+2009-11-26  Jussi Kukkonen  <jku@linux.intel.com>
+
+
+       Merge branch 'master' into jku
+
+2009-11-25  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/SyncConfig.cpp:
+       * src/syncevo/SyncConfig.h:
+
+       shared config: when no context is given, search for config
+
+2009-11-25  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * configure-pre.in:
+       * src/gtk-ui/sync-config-widget.c:
+       * src/gtk-ui/sync-config-widget.h:
+       * src/gtk-ui/sync-ui.c:
+
+       gtk-ui: Derive SyncConfigWidget from GtkContainer
+
+2009-11-25  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/client-test-app.cpp:
+
+       client-test: create new configs in @client-test-[12]
+
+2009-11-25  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * configure-pre.in:
+
+       bumped version to 0.9.1+1.0alpha1
+
+2009-11-24  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/Cmdline.cpp:
+       * src/syncevo/Cmdline.h:
+       * src/syncevo/SyncConfig.h:
+
+       command line: preserve and show shared properties (MB #8048)
+
+2009-11-24  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/Cmdline.cpp:
+
+       client-test: updated SyncEvo::CmdlineTest to work with shared
+       config layout
+
+2009-11-23  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/dbus/interfaces/syncevo-session-full.xml:
+
+       D-Bus API: clarified meaning of "empty config" in
+       Session.SetConfig()
+
+2009-11-21  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+       * src/syncevo/SyncConfig.cpp:
+       * src/syncevo/SyncConfig.h:
+       * test/test-dbus.py:
+
+       config: creating templates for a specific context
+
+2009-11-21  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/SyncConfig.cpp:
+       * test/test-dbus.py:
+
+       deviceId: shared between peers
+
+2009-11-21  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/ConfigNode.h:
+       * src/syncevo/FileConfigNode.cpp:
+       * src/syncevo/FileConfigNode.h:
+       * src/syncevo/FilterConfigNode.cpp:
+       * src/syncevo/FilterConfigNode.h:
+       * src/syncevo/PrefixConfigNode.cpp:
+       * src/syncevo/PrefixConfigNode.h:
+       * src/syncevo/SafeConfigNode.cpp:
+       * src/syncevo/SafeConfigNode.h:
+       * src/syncevo/SyncConfig.cpp:
+       * src/syncevo/SyncSource.cpp:
+       * src/syncevo/SyncSource.h:
+
+       ConfigNode: use map with case-insensitive keys for properties
+
+2009-11-21  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/FilterConfigNode.cpp:
+
+       FilterConfigNode: existing properties not overwritten?!
+
+2009-11-21  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/SyncConfig.cpp:
+       * src/syncevo/SyncConfig.h:
+
+       SyncConfig::setConfigFilter(): per source-set properties were
+       broken
+
+2009-11-20  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/test-dbus.py:
+
+       D-Bus testing: split up TestMultipleConfigs
+
+2009-11-20  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/test-dbus.py:
+
+       D-Bus testing: fixed typo for "use gdb" code path
+
+2009-11-20  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+       * test/test-dbus.py:
+
+       D-Bus API + testing + implementation: GetDatabases() requires
+       source config
+
+2009-11-20  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/dbus/interfaces/syncevo-session-full.xml:
+       * src/syncevo-dbus-server.cpp:
+       * src/syncevo/ConfigTree.h:
+       * src/syncevo/FileConfigTree.cpp:
+       * src/syncevo/FileConfigTree.h:
+       * src/syncevo/SyncConfig.cpp:
+       * src/syncevo/SyncConfig.h:
+       * test/test-dbus.py:
+
+       syncevo-dbus-server: removing/clearing of properties in shared
+       configs (MB# 8059)
+
+2009-11-20  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/test-dbus.py:
+
+       D-Bus testing: Server/Session.CheckSource() does not need
+       existing configuration
+
+2009-11-16  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/FileConfigTree.cpp:
+
+       FileConfigTree clearNodes() + reset(): fail when nodes are shared
+
+2009-11-13  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+       * src/syncevo/DevNullConfigNode.h:
+       * src/syncevo/FileConfigTree.cpp:
+       * src/syncevo/FilterConfigNode.h:
+       * src/syncevo/Makefile.am:
+       * src/syncevo/MultiplexConfigNode.cpp:
+       * src/syncevo/MultiplexConfigNode.h:
+       * src/syncevo/SyncConfig.cpp:
+       * src/syncevo/SyncConfig.h:
+       * src/syncevo/SyncContext.cpp:
+       * src/syncevo/SyncContext.h:
+       * test/test-dbus.py:
+
+       config: share properties between peers, configuration view
+       without peer
+
+2009-11-13  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/Cmdline.cpp:
+       * src/syncevo/SyncConfig.cpp:
+       * src/syncevo/SyncConfig.h:
+
+       config: added "defaultPeer" global property + SaveConfigNode
+       "hidden" flags
+
+2009-11-13  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/backends/sqlite/SQLiteContactSource.cpp:
+       * src/backends/sqlite/SQLiteContactSource.h:
+       * src/client-test-app.cpp:
+       * src/syncevo-dbus-server.cpp:
+       * src/syncevo/Cmdline.cpp:
+       * src/syncevo/FileConfigTree.cpp:
+       * src/syncevo/FileConfigTree.h:
+       * src/syncevo/SyncConfig.cpp:
+       * src/syncevo/SyncConfig.h:
+       * src/syncevo/SyncContext.cpp:
+       * src/syncevo/SyncSource.cpp:
+       * src/syncevo/SyncSource.h:
+       * src/syncevo/TrackingSyncSource.cpp:
+       * src/syncevo/VolatileConfigTree.h:
+
+       config: reorganized for shared config layout (MB#7707)
+
+2009-11-13  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/Cmdline.cpp:
+       * src/syncevo/SyncConfig.cpp:
+       * src/syncevo/SyncConfig.h:
+
+       SyncSourceConfig: removed cruft
+
+2009-11-20  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/test-dbus.py:
+       * test/test-dbus/cache/syncevolution/dummy-test-2009-11-18-12-52/status.ini:
+       * test/test-dbus/cache/syncevolution/dummy-test-2009-11-18-12-55/status.ini:
+       * test/test-dbus/cache/syncevolution/dummy-test-2009-11-18-12-57/status.ini:
+       * test/test-dbus/cache/syncevolution/dummy-test-2009-11-18-12-58/status.ini:
+       * test/test-dbus/cache/syncevolution/dummy-test-2009-11-18-12-59/status.ini:
+       * test/test-dbus/reports/cache/syncevolution/dummy-test-2009-11-18-12-52/status.ini:
+       * test/test-dbus/reports/cache/syncevolution/dummy-test-2009-11-18-12-55/status.ini:
+       * test/test-dbus/reports/cache/syncevolution/dummy-test-2009-11-18-12-57/status.ini:
+       * test/test-dbus/reports/cache/syncevolution/dummy-test-2009-11-18-12-58/status.ini:
+       * test/test-dbus/reports/cache/syncevolution/dummy-test-2009-11-18-12-59/status.ini:
+
+       D-Bus testing: setupFiles() + multiple snapshots
+
+2009-11-25  Chen Congwu  <congwu.chen@intel.com>
+
+       * src/syncevo/SyncContext.cpp:
+
+       Fix a compiler warining.
+
+2009-11-25  Chen Congwu  <congwu.chen@intel.com>
+
+       * src/syncevo/SyncContext.cpp:
+       * src/syncevo/SyncContext.h:
+
+       Server alerted sync: ensure only one SynthesisEngine is active
+
+2009-11-25  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-ui.c:
+
+       gtk-ui: set printChanges to 0 before syncing
+
+2009-11-25  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/dbus/interfaces/syncevo-server-full.xml:
+       * src/dbus/interfaces/syncevo-session-full.xml:
+
+       D-Bus documentation fixes
+
+2009-11-25  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/dbus/test.c:
+       * src/gtk-ui/sync-ui.c:
+
+       gtk-ui: remove unused pointer access
+
+2009-11-24  tomasgalicia  <tomas.galicia@intel.com>
+
+       * po/it.po:
+
+       l10n: Updates to Italian (it) translation
+
+2009-11-24  tomasgalicia  <tomas.galicia@intel.com>
+
+       * po/pt_BR.po:
+
+       l10n: Updates to Brazilian Portuguese (pt_BR) translation
+
+2009-11-24  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/SyncContext.cpp:
+
+       SyncContext: only use one engine instance, fixes slow sync issue
+
+2009-11-24  Kristho  <lakristho@gmail.com>
+
+       * po/da.po:
+
+       l10n: Danish translation of syncevolution.
+
+2009-11-24  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-ui.c:
+
+       gtk-ui: handle NoSuchServer when loading initial config
+
+2009-11-24  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-ui-config.h:
+       * src/gtk-ui/sync-ui.c:
+       * src/gtk-ui/ui.glade:
+
+       gtk-ui: fix sync mode selection
+
+2009-11-24  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * configure-pre.in:
+       * src/gtk-ui/sync-config-widget.c:
+       * src/gtk-ui/sync-config-widget.h:
+       * src/gtk-ui/sync-ui.c:
+
+       gtk-ui: remove keyring use -- server will take care of this
+
+2009-11-24  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/dbus/interfaces/syncevo-marshal.list:
+       * src/dbus/syncevo-server.c:
+       * src/dbus/syncevo-server.h:
+       * src/gtk-ui/sync-ui.c:
+
+       gtk-ui: add (empty) InfoRequest callback
+
+2009-11-24  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-config-widget.c:
+       * src/gtk-ui/sync-ui-config.c:
+       * src/gtk-ui/sync-ui-config.h:
+       * src/gtk-ui/sync-ui.c:
+
+       gtk-ui: use CheckSource() to hide unsupported sources
+
+2009-11-24  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/dbus/syncevo-dbus-types.h:
+       * src/dbus/syncevo-server.c:
+       * src/dbus/syncevo-server.h:
+
+       Add SourceUnusable exception to dbus wrapper
+
+2009-11-24  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-ui.c:
+
+       gtk-ui: remove debug ouput
+
+2009-11-24  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+
+       syncevo-dbus-server: Add DBusSyncException SourceUnusable
+
+2009-11-24  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/dbus/syncevo-server.c:
+       * src/dbus/syncevo-server.h:
+       * src/gtk-ui/sync-ui.c:
+
+       implement CheckSource in dbus wrapper
+
+2009-11-23  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-ui.c:
+
+       gtk-ui: Use 'Presence' and update UI based on that
+
+2009-11-23  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/dbus/interfaces/syncevo-marshal.list:
+       * src/dbus/syncevo-server.c:
+       * src/dbus/syncevo-server.h:
+
+       add Presence to dbus wrapper
+
+2009-11-23  Jussi Kukkonen  <jku@linux.intel.com>
+
+
+       Merge branch 'jku-dbus-update' into jku
+
+2009-11-18  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+
+       syncevo-dbus-server: fix an integer overflow in GetReports
+
+2009-11-18  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * test/test-dbus.py:
+       * test/test-dbus/cache/syncevolution/dummy-test-2009-11-18-12-52/status.ini:
+       * test/test-dbus/cache/syncevolution/dummy-test-2009-11-18-12-55/status.ini:
+       * test/test-dbus/cache/syncevolution/dummy-test-2009-11-18-12-57/status.ini:
+       * test/test-dbus/cache/syncevolution/dummy-test-2009-11-18-12-58/status.ini:
+       * test/test-dbus/cache/syncevolution/dummy-test-2009-11-18-12-59/status.ini:
+
+       D-Bus testing: add testGetReportsByRef in TestSessionAPIsDummy
+
+2009-11-18  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * test/test-dbus.py:
+
+       D-Bus testing: change comment for testGetReportsNoConfig
+
+2009-11-18  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * test/test-dbus.py:
+
+       D-Bus testing: remove reduntant 'cleanAllConfig'
+
+2009-11-18  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * test/test-dbus.py:
+
+       D-Bus testing: add 'setupFiles' function in DBusUtil
+
+2009-11-18  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * test/test-dbus.py:
+
+       D-Bus testing: change the server name in TestSessionAPIsDummy
+
+2009-11-20  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/dbus/syncevo-dbus-types.h:
+
+       fix syncevolution exception names in dbus wrapper
+
+2009-11-20  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-ui.c:
+
+       gtk-ui: implement enabling/disabling sources in main view
+
+2009-11-20  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/dbus/interfaces/syncevo-server-full.xml:
+       * src/syncevo-dbus-server.cpp:
+       * test/test-dbus.py:
+
+       syncevo-dbus-server: implement Server.GetSessions() (MB #8061)
+
+2009-11-19  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-ui.c:
+
+       gtk-ui: remove old service icon before adding new one
+
+2009-11-19  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-ui.c:
+
+       gtk-ui: set ui state to ok when config is received
+
+2009-11-19  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-config-widget.c:
+
+       gtk-ui: implement saving config
+
+2009-11-19  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/dbus/syncevo-dbus-types.c:
+
+       fix double free in dbus C wrapper
+
+2009-11-19  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/Cmdline.cpp:
+
+       client-test: added remoteIdentifier + PeerIsClient
+
+2009-11-19  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/Cmdline.cpp:
+       * src/syncevo/SyncConfig.cpp:
+
+       username/password: empty in templates
+
+2009-11-19  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-config-widget.c:
+       * src/gtk-ui/sync-config-widget.h:
+
+       gtk-ui: only show ConsumerReady services
+
+2009-11-19  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-config-widget.c:
+       * src/gtk-ui/sync-config-widget.h:
+       * src/gtk-ui/sync-ui.c:
+
+       gtk-ui: make configuration widgets handle their state better
+
+2009-11-19  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/dbus/interfaces/syncevo-server-full.xml:
+       * src/syncevo-dbus-server.cpp:
+
+       D-Bus API + syncevo-dbus-server: added
+       Server.CheckSource()/GetDatabases() (MB #8091)
+
+2009-11-19  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+       * test/test-dbus.py:
+
+       syncevo-dbus-server: StatusChanged "idle" was not sent
+
+2009-11-19  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/dbus/syncevo-dbus-types.c:
+       * src/dbus/syncevo-dbus-types.h:
+       * src/gtk-ui/sync-config-widget.c:
+       * src/gtk-ui/sync-config-widget.h:
+       * src/gtk-ui/sync-ui.c:
+
+       gtk-ui: improve SyncConfigWidget, don't run a session all the
+       time
+
+2009-11-19  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/test-dbus.py:
+
+       D-Bus testing: added testSyncSecondSession
+
+2009-11-19  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/test-dbus.py:
+
+       D-Bus testing: SessionChanged signal handling was wrong
+
+2009-11-19  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+
+       syncevo-dbus-server: send SYNC_DONE status after shutting down
+       connection
+
+2009-11-18  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/test-dbus.py:
+
+       D-Bus testing: only react to D-Bus signals while the test runs
+
+2009-11-18  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/test-dbus.py:
+
+       D-Bus testing: added glib independent timeouts
+
+2009-11-18  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/dbus/syncevo-dbus-types.c:
+       * src/dbus/syncevo-dbus-types.h:
+       * src/gtk-ui/sync-config-widget.c:
+       * src/gtk-ui/sync-config-widget.h:
+       * src/gtk-ui/sync-ui-config.h:
+       * src/gtk-ui/sync-ui.c:
+
+       gtk-ui: re-implement service configuration view
+
+2009-11-18  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-config-widget.c:
+       * src/gtk-ui/sync-config-widget.h:
+       * src/gtk-ui/sync-ui-config.h:
+       * src/gtk-ui/sync-ui.c:
+       * src/gtk-ui/sync-ui.h:
+
+       gtk-ui: more coverage for new dbus api
+
+2009-11-17  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/test-dbus.py:
+
+       D-Bus testing: avoid duplicate testSync methods, minor
+       improvements
+
+2009-11-17  Jussi Kukkonen  <jku@linux.intel.com>
+
+
+       Merge remote branch 'origin/jku-single-window' into
+       jku-dbus-update
+
+2009-09-30  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-config-widget.h:
+       * src/gtk-ui/sync-ui-config.c:
+       * src/gtk-ui/sync-ui-config.h:
+       * src/gtk-ui/sync-ui.c:
+       * src/gtk-ui/sync-ui.h:
+       * src/gtk-ui/ui.glade:
+
+       gtk-ui: add automatic expansion to service list
+
+2009-11-17  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/SyncContext.cpp:
+
+       SyncContext::createTransportAgent(): removed unused agent
+       variable
+
+2009-11-17  Jussi Kukkonen  <jku@linux.intel.com>
+
+
+       implement the service list contents as widgets
+
+2009-11-17  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/Makefile.am:
+       * src/gtk-ui/sync-ui-config.h:
+       * src/gtk-ui/sync-ui-marshal.list:
+       * src/gtk-ui/sync-ui.c:
+
+       fix build problems, fix compiler warnings
+
+2009-11-17  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/SyncContext.cpp:
+
+       OBEX transport: fix compiler error when OBEX transport is off
+
+2009-09-28  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * configure-pre.in:
+       * src/gtk-ui/sync-ui.c:
+       * src/gtk-ui/ui.glade:
+
+       gtk-ui: use NbtkGtkExpander in service list
+
+2009-11-16  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+
+       syncevo-dbus-server: change error message for getReports
+
+2009-11-16  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+
+       syncevo-dbus-server: change error message for getDatabases
+
+2009-11-13  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+
+       syncevo-dbus-server: change error message of checkSource
+
+2009-11-16  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+
+       syncevo-dbus-server: change error message for setConfig
+
+2009-11-16  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+
+       syncevo-dbus-server: change error message for getConfig
+
+2009-11-14  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * test/test-dbus.py:
+
+       D-Bus testing: add unit tests for Session.GetReports
+
+2009-11-13  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * test/test-dbus.py:
+
+       D-Bus testing: add unit tests for Session.GetDatabases
+
+2009-11-13  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * test/test-dbus.py:
+
+       D-Bus testing: add unit tests for Session.CheckSource
+
+2009-11-16  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * test/test-dbus.py:
+
+       D-Bus testing: add TestSessionAPIsEmptyName class
+
+2009-11-17  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * test/test-dbus.py:
+
+       D-Bus testing: change comments for unit tests of config
+
+2009-09-28  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/mux-icon-button.c:
+       * src/gtk-ui/mux-icon-button.h:
+       * src/gtk-ui/mux-window.c:
+       * src/gtk-ui/mux-window.h:
+       * src/gtk-ui/sync-ui.c:
+       * src/gtk-ui/ui.glade:
+
+       implement first phase of "single window mode"
+
+2009-11-17  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-ui-config.c:
+       * src/gtk-ui/sync-ui-config.h:
+       * src/gtk-ui/sync-ui.c:
+
+       gtk-ui: only sync enabled and locall supported sources
+
+2009-11-17  Chen Congwu  <congwu.chen@intel.com>
+
+       * src/syncevo/ObexTransportAgent.cpp:
+       * src/syncevo/ObexTransportAgent.h:
+
+       ObexTransportAgent:  compiling fixes MB#5188
+
+2009-11-17  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/SyncConfig.cpp:
+
+       syncURL: example for HTTPS, OBEX channel selection
+
+2009-11-13  Chen Congwu  <congwu.chen@intel.com>
+
+       * configure-pre.in:
+       * src/syncevo/Makefile.am:
+       * src/syncevo/ObexTransportAgent.cpp:
+       * src/syncevo/ObexTransportAgent.h:
+       * src/syncevo/SyncConfig.cpp:
+       * src/syncevo/SyncContext.cpp:
+
+       OBEX Client Transport: in-process OBEX client (binding over
+       Bluetooth, #5188)
+
+2009-11-13  Chen Congwu  <congwu.chen@intel.com>
+
+       * src/syncevo/Cmdline.cpp:
+       * src/syncevo/SyncConfig.cpp:
+       * src/syncevo/SyncConfig.h:
+       * src/syncevo/SyncContext.cpp:
+       * src/syncevo/SyncContext.h:
+       * src/syncevo/SyncML.cpp:
+       * src/syncevo/SyncML.h:
+
+       Server Alerted Sync: SAN generation
+
+2009-11-13  Chen Congwu  <congwu.chen@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+
+       Server Alerted Sync: SAN Parsing
+
+2009-11-13  Chen Congwu  <congwu.chen@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+
+       Server Alerted Sync: SAN Parsing
+
+2009-11-13  Chen Congwu  <congwu.chen@intel.com>
+
+       * src/syncevo/SyncSource.cpp:
+
+       SyncML Server: explictly declare support "refresh-from-remote"
+
+2009-11-13  Chen Congwu  <congwu.chen@intel.com>
+
+       * src/syncevo/SyncSource.cpp:
+
+       SyncML Server: flush luid-guid map immediately
+
+2009-11-10  Chen Congwu  <congwu.chen@intel.com>
+
+       * src/gdbus/gdbus.h:
+
+       gdbus: fix a compile error
+
+2009-11-10  Chen Congwu  <congwu.chen@intel.com>
+
+       * test/ClientTest.cpp:
+       * test/ClientTest.h:
+
+       ClienTest: Fix a resource leak
+
+2009-10-16  Chen Congwu  <congwu.chen@intel.com>
+
+       * configure-pre.in:
+
+       DevType: change DevType from "desktop" to "workstation"
+
+2009-11-16  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-ui.c:
+
+       gtk-ui: improve error dbus handling
+
+2009-11-16  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/Makefile-gen.am:
+       * src/org.syncevolution.service.in:
+
+       fix D-Bus .service file (needed for d-Bus autostart)
+
+2009-11-16  itsoftex  <yousef@itsoftex.com>
+
+       * po/ar.po:
+
+       l10n: Updates to Arabic (ar) translation
+
+2009-11-16  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/dbus/syncevo-dbus-types.c:
+       * src/dbus/syncevo-dbus-types.h:
+       * src/gtk-ui/sync-ui.c:
+
+       gtk-ui: start handling source errors
+
+2009-11-16  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/dbus/syncevo-dbus-types.c:
+       * src/dbus/syncevo-dbus-types.h:
+       * src/gtk-ui/sync-ui.c:
+       * src/org.syncevolution.service.in:
+
+       gtk-ui: enable actual syncing
+
+2009-11-16  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/dbus/interfaces/syncevo-marshal.list:
+       * src/dbus/syncevo-session.c:
+       * src/dbus/test.c:
+       * src/org.Moblin.SyncEvolution.service.in:
+       * src/org.syncevolution.service.in:
+
+       fix bug in status-changed signal definition in dbus wrapper
+
+2009-11-16  itsoftex  <yousef@itsoftex.com>
+
+       * po/ar.po:
+
+       l10n: Arabic Translation, partial upload.
+
+2009-11-12  GLS_JPN  <etsukox.murozono@intel.com>
+
+       * po/ja.po:
+
+       l10n: Updates to Japanese (ja) translation
+
+2009-11-12  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/Cmdline.cpp:
+       * src/syncevo/SyncConfig.cpp:
+       * src/syncevo/SyncConfig.h:
+       * src/syncevo/SynthesisDBPlugin.cpp:
+
+       server config: fixed tests and code for new config options
+
+2009-11-12  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/Cmdline.cpp:
+       * src/syncevo/SyncConfig.cpp:
+
+       cmdline --print-servers: sort by server name
+
+2009-11-11  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+       * src/syncevo/SyncContext.cpp:
+       * src/syncevo/SyncContext.h:
+       * src/syncevo/SynthesisDBPlugin.cpp:
+       * test/test-dbus.py:
+
+       syncevo-dbus-server: removed special case for unauthenticated
+       Connections
+
+2009-11-11  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/SyncContext.cpp:
+
+       SyncML server: accept basic authentication
+
+2009-11-11  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * test/test-dbus.py:
+
+       D-Bus testing: add unit tests for session.SetConfig/GetConfig
+
+2009-11-10  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/SyncContext.cpp:
+
+       SyncML server: explicitly state that any kind of log in is valid
+
+2009-11-05  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/Makefile-gen.am:
+
+       client-test: unit tests not included when building statically
+
+2009-11-10  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+       * test/test-dbus.py:
+
+       syncevo-dbus-server: Server.GetConfig() should not create configs
+
+2009-11-10  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/test-dbus.py:
+
+       D-Bus testing: check for some error reporting situations
+
+2009-11-09  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+       * src/syncevo/SyncContext.cpp:
+       * test/test-dbus.py:
+
+       syncevo-dbus-server: kill old session(s) when the same client
+       connects again (MB#7710)
+
+2009-11-09  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/dbus/interfaces/syncevo-connection-full.xml:
+       * src/syncevo-dbus-server.cpp:
+
+       syncevo-dbus-server + D-Bus API: no Reply after Abort signal
+
+2009-11-09  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/test-dbus.py:
+
+       test-dbus.py: also kill dbus-monitor at start of run
+
+2009-11-02  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * src/gdbus/gdbus-cxx-bridge.h:
+       * src/syncevo-dbus-server.cpp:
+
+       syncevo-dbus-server: add specific exceptions (MB#6548)
+
+2009-10-30  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+       * src/syncevo/CurlTransportAgent.cpp:
+       * src/syncevo/SoupTransportAgent.cpp:
+       * src/syncevo/SyncContext.cpp:
+       * src/syncevo/SyncContext.h:
+       * test/test-dbus.py:
+
+       syncevo-dbus-server + syncevolution: fixed signal handling and
+       D-Bus suspend/abort/shutdown (MB#7555)
+
+2009-10-30  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+       * src/syncevo/SyncContext.cpp:
+
+       syncevo-dbus-server: handle CTRL-C/SIGINT/SIGTERM(bug #7555)
+
+2009-11-09  Patrick Ohly  <patrick.ohly@intel.com>
+
+
+       Merge branch 'syncevolution-0-9-x'
+
+2009-11-09  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * configure-pre.in:
+
+       autotools + Boost: --with-boost had no effect (MB#7856)
+
+2009-11-06  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+       * src/syncevo/SyncContext.cpp:
+       * src/syncevo/SyncContext.h:
+       * src/syncevo/SynthesisDBPlugin.cpp:
+       * test/syncevo-http-server.py:
+       * test/test-dbus.py:
+
+       SyncML server: find configuration for client automatically
+       (MB#7710)
+
+2009-11-06  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/SynthesisDBPlugin.cpp:
+
+       SynthesisDBPlugin: added NULL context pointer checks
+
+2009-11-05  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+
+       synevo-dbus-server: Session.Sync() signature fix
+
+2009-11-05  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/test-dbus.py:
+
+       test-dbus.py: added Connection tests
+
+2009-11-05  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/test-dbus.py:
+
+       test-dbus.py: more reliable process handling
+
+2009-11-05  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/dbus/interfaces/syncevo-connection-full.xml:
+       * src/syncevo-dbus-server.cpp:
+
+       D-Bus API + syncev-dbus-server: Connection.Abort signal only sent
+       once
+
+2009-11-05  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+
+       syncevo-dbus-server: use unbuffered output
+
+2009-11-05  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+
+       syncevo-dbus-server: use random session IDs
+
+2009-11-05  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/test-dbus.py:
+
+       test-dbus.py: removed dependency on Python 2.6 and python-gobject
+       >= 2.16
+
+2009-11-05  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/Makefile-gen.am:
+
+       client-test: unit tests not included when building statically
+
+2009-11-03  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+       * src/syncevo/SyncContext.cpp:
+       * src/syncevo/SyncContext.h:
+       * src/syncevo/SynthesisDBPlugin.cpp:
+
+       SyncML server: don't check client credentials if not required
+
+2009-11-03  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/syncevo-http-server.py:
+
+       syncevolution-http-server.py: clients must authenticate
+
+2009-10-25  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/SyncConfig.cpp:
+       * src/syncevo/SyncConfig.h:
+       * src/syncevo/SyncContext.cpp:
+       * src/syncevo/SyncContext.h:
+       * src/syncevo/SyncSource.cpp:
+       * src/syncevo/SynthesisDBPlugin.cpp:
+
+       Synthesis server: session auth and device admin
+
+2009-10-29  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/SyncContext.cpp:
+
+       logging + XML config: print config when it cannot be parsed
+
+2009-10-29  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/SafeConfigNode.cpp:
+
+       SafeConfigNode::escape(): did not work correctly for strings with
+       ! in them
+
+2009-10-29  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/default/README:
+
+       adding templates: also need to go into test/test-dbus.py
+
+2009-10-09  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+
+       syncevo-dbus-server: implement progress (bug #7134)
+
+2009-11-03  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * gen-autotools.sh:
+
+       gen-autotools.sh: avoid GNU find -printf
+
+2009-11-04  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * configure-pre.in:
+
+       configure: detect incorrect use of --with-synthesis-src
+
+2009-11-03  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/backends/sqlite/SQLiteContactSource.cpp:
+       * src/backends/sqlite/SQLiteContactSource.h:
+
+       SQLite backend: added server admin calls
+
+2009-11-03  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * gen-autotools.sh:
+
+       gen-autotools.sh: avoid GNU find -printf
+
+2009-11-03  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/LogRedirect.cpp:
+
+       stderr redirection: detect "error" messages and show them
+       (MB#7655)
+
+2009-11-01  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * po/POTFILES.in:
+       * src/gtk-ui/sync-ui-config.c:
+       * src/gtk-ui/sync-ui-config.h:
+       * src/gtk-ui/sync-ui.c:
+
+       gtk-ui: simplify report handling & source checking
+
+2009-11-01  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-ui.c:
+
+       gtk-ui: add sync report and progress handling
+
+2009-11-01  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/dbus/syncevo-dbus-types.c:
+       * src/dbus/syncevo-dbus-types.h:
+
+       add 'done' to sessions statuses in dbus wrapper
+
+2009-11-12  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/dbus/test.c:
+
+       improve test binary for dbus wrapper
+
+2009-11-12  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/dbus/syncevo-server.c:
+       * src/dbus/syncevo-server.h:
+       * src/dbus/syncevo-session.c:
+       * src/dbus/syncevo-session.h:
+
+       bugfixes in dbus wrapper
+
+2009-11-12  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/dbus/syncevo-dbus-types.c:
+       * src/dbus/syncevo-dbus-types.h:
+
+       fix sessions-data handling in client wrapper
+
+2009-11-12  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/dbus/syncevo-server.c:
+       * src/gtk-ui/sync-ui.c:
+
+       use Attach/Detach automatically in dbus client wrapper
+
+2009-11-12  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/dbus/interfaces/syncevo-server-full.xml:
+
+       dbus documentation fixes
+
+2009-11-12  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-ui-config.c:
+       * src/gtk-ui/sync-ui-config.h:
+       * src/gtk-ui/sync-ui.c:
+
+       gtk-ui: read current configuration from Session
+
+2009-11-12  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/dbus/syncevo-dbus-types.c:
+       * src/dbus/syncevo-dbus-types.h:
+       * src/dbus/syncevo-session.c:
+       * src/dbus/syncevo-session.h:
+
+       add missing CheckSource implementation to cient wrapper
+
+2009-11-12  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/dbus/test.c:
+       * src/gtk-ui/sync-ui-config.c:
+       * src/gtk-ui/sync-ui.c:
+
+       gtk-ui : fix the build (compiles, does not work)
+
+2009-11-11  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/dbus/Makefile.am:
+       * src/dbus/test.c:
+
+       add temporary test binary
+
+2009-11-11  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/dbus/interfaces/syncevo-session-full.xml:
+       * src/dbus/syncevo-session.c:
+       * src/dbus/syncevo-session.h:
+
+       fix dbus signature for GetConfig
+
+2009-11-11  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/dbus/interfaces/syncevo-marshal.list:
+       * src/dbus/syncevo-dbus-types.c:
+       * src/dbus/syncevo-dbus-types.h:
+       * src/dbus/syncevo-server.c:
+       * src/dbus/syncevo-server.h:
+       * src/dbus/syncevo-session.c:
+       * src/dbus/syncevo-session.h:
+       * src/gtk-ui/sync-ui-config.h:
+       * src/gtk-ui/sync-ui.c:
+
+       add missing session signals to client dbus wrapper
+
+2009-11-11  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/dbus/Makefile.am:
+       * src/dbus/README:
+       * src/dbus/interfaces/Makefile.am:
+       * src/dbus/interfaces/syncevo-full.xml:
+       * src/dbus/interfaces/syncevo-marshal.list:
+       * src/dbus/syncevo-dbus-types.c:
+       * src/dbus/syncevo-dbus-types.h:
+       * src/dbus/syncevo-dbus.c:
+       * src/dbus/syncevo-dbus.h:
+       * src/dbus/syncevo-server.c:
+       * src/dbus/syncevo-server.h:
+       * src/dbus/syncevo-session.c:
+       * src/dbus/syncevo-session.h:
+       * src/dbus/test.c:
+
+       implement new dbus api in the C wrapper
+
+2009-11-11  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+       * src/syncevo/SyncContext.cpp:
+       * src/syncevo/SyncContext.h:
+       * src/syncevo/SynthesisDBPlugin.cpp:
+       * test/test-dbus.py:
+
+       syncevo-dbus-server: removed special case for unauthenticated
+       Connections
+
+2009-11-11  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/SyncContext.cpp:
+
+       SyncML server: accept basic authentication
+
+2009-10-29  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/client-test-app.cpp:
+
+       testing: Client::Sync broke when removing the source array in the
+       sync() method
+
+2009-10-29  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/test-dbus.py:
+
+       D-Bus testing: adapted to fully implemented GetConfigs()
+
+2009-10-29  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/test-dbus.py:
+
+       D-Bus testing: set up environment also for running under debugger
+
+2009-10-29  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+
+       syncevo-dbus-server: fixed compiler warning
+
+2009-10-13  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+
+       syncevo-dbus-server: use enum values to represent sync statuses
+
+2009-10-21  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * test/dbus-server-config.py:
+
+       syncevo-dbus-server: add test script for getConfigs
+
+2009-10-21  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+
+       syncevo-dbus-server: implement getConfigs
+
+2009-10-15  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+
+       syncevo-dbus-server: hook up checkForSuspend and checkForAbort
+
+2009-10-12  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+
+       syncevo-dbus-server: add timeout mechanism for status and
+       progress
+
+2009-10-09  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+
+       syncevo-dbus-server: change checkSource and getDatabases
+
+2009-10-09  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+       * src/syncevo/ConfigTree.h:
+       * src/syncevo/FileConfigTree.cpp:
+       * src/syncevo/FileConfigTree.h:
+       * src/syncevo/SyncConfig.cpp:
+       * src/syncevo/SyncConfig.h:
+
+       syncevo-dbus-server setConfig: reserve meta information
+
+2009-10-26  GLSQA  <namfonx.yeates@intel.com>
+
+       * po/fi.po:
+
+       l10n: Updates to Finnish (fi) translation
+
+2009-10-26  GLSQA  <namfonx.yeates@intel.com>
+
+       * po/fi.po:
+
+       l10n: Updates to Finnish (fi) translation
+
+2009-10-26  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * NEWS:
+       * configure-pre.in:
+
+       NEWS, version: updated for 0.9.1
+
+2009-10-23  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/SyncSource.cpp:
+
+       SyncSourceAdmin::insertMapItem(): silently update existing items
+
+2009-10-23  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/SynthesisDBPlugin.cpp:
+
+       Synthesis DB interface: logging of local operations
+
+2009-10-23  Patrick Ohly  <patrick.ohly@intel.com>
+
+
+       Merge commit 'origin/master' into dbus-api
+
+2009-10-21  ZhuYanhai  <zhu.yanhai@gmail.com>
+
+       * po/zh_CN.po:
+
+       l10n: Updates to Chinese (China) (zh_CN) translation
+
+2009-10-21  ZhuYanhai  <zhu.yanhai@gmail.com>
+
+       * po/zh_CN.po:
+
+       l10n: Updates to Chinese (China) (zh_CN) translation
+
+2009-10-20  Patrick Ohly  <patrick.ohly@intel.com>
+
+
+       Merge branch 'master' into dbus-api
+
+2009-10-19  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * NEWS:
+       * configure-pre.in:
+
+       NEWS, version: updated for 0.9.1 beta 2
+
+2009-10-16  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/ClientTest.cpp:
+       * test/ClientTest.h:
+
+       client-test: added testManyDeletes, improved testManyItems
+
+2009-10-16  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * test/valgrindcheck.sh:
+
+       valgrindcheck.sh: return 100 when valgrind finds a problem
+
+2009-10-16  Congwu Chen  <congwu.chen@intel.com>
+
+       * test/runtests.py:
+
+       runtests.py: added configuration of Resend test
+
+2009-10-16  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/runtests.py:
+
+       runtests.py: reformatted source code to split up long lines
+
+2009-10-16  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/runtests.py:
+
+       runtests.py: build RPMs in addition to DEBs
+
+2009-10-12  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/runtests.py:
+
+       runtests.py: fixed "prebuilt" tests
+
+2009-10-12  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/runtests.py:
+
+       runtests.py: fixed building lpia .deb
+
+2009-10-13  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * test/generate-html.xsl:
+
+       Testing: add valgrind result checking and generate result in html
+       output
+
+2009-10-13  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * test/runtests.py:
+
+       Testing: add nightly test for memotoo
+
+2009-10-13  Chen Congwu  <congwu.chen@intel.com>
+
+       * test/runtests.py:
+
+       Testing: add time info for mail title
+
+2009-10-13  Chen Congwu  <congwu.chen@intel.com>
+
+       * test/runtests.py:
+
+       Testing: change know failures to skip for google testing
+
+2009-09-28  Chen Congwu  <congwu.chen@intel.com>
+
+       * test/runtests.py:
+
+       Testing: add valgrind check result and backend scan dir
+
+2009-09-28  Chen Congwu  <congwu.chen@intel.com>
+
+       * test/resultchecker.py:
+       * test/runtests.py:
+
+       Testing: add valgrind check result and backend scan dir
+
+2009-10-16  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/SyncContext.cpp:
+
+       fixed typo: Aboring -> Aborting
+
+2009-10-15  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/README.mobical:
+       * test/synccompare.pl:
+
+       Mobical: PHOTOs preserved verbatim (MB#6668)
+
+2009-10-15  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/Makefile.am:
+       * src/syncevo/installcheck-local.sh:
+
+       packaging: another fix for installcheck-local
+
+2009-10-15  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * Makefile-gen.am:
+
+       packaging: force serialization of "install" and "installcheck"
+
+2009-10-15  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * src/syncevo/SyncSource.cpp:
+
+       SyncSourceSerialize: a typo for vCalendar1.0 in getSynthesisInfo
+
+2009-10-15  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * src/syncclient_sample_config.xml:
+       * src/syncevo/SyncSource.cpp:
+
+       SyncSource: Add 'prioprity' conversion between vCalendar1.0 and
+       2.0
+
+2009-10-15  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * src/backends/evolution/EvolutionContactSource.h:
+       * src/syncclient_sample_config.xml:
+       * src/syncevo/SyncSource.cpp:
+       * src/syncevo/SyncSource.h:
+
+       SyncSource: change names for m_incomingScript and
+       m_outgointScript
+
+2009-10-14  xosecalvo  <ubuntu@galizaweb.net>
+
+       * po/gl.po:
+
+       l10n: First Galician translation
+
+2009-10-14  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/test-dbus.py:
+
+       D-Bus testing: reorganized code, added session and sync testing
+
+2009-10-14  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+
+       syncevo-dbus-server: cleaned up read-only methods and added
+       GetConfigs()
+
+2009-10-14  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+
+       syncevo-dbus-server: fixed name of Session signals
+
+2009-10-14  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+
+       syncevo-dbus-server: fixed reporting of status "idle"
+
+2009-10-14  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/test-dbus.py:
+
+       D-Bus testing: use dbus-monitor in normal mode
+
+2009-10-14  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/gdbus/test/example.cpp:
+
+       gdbus C++: demonstrate how to bind methods in private base
+       classes
+
+2009-10-12  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/gdbus/test/example.cpp:
+
+       gdbus C++ example: added static and const function callback
+
+2009-10-12  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/gdbus/gdbus-cxx-bridge.h:
+       * src/gdbus/test/example.cpp:
+       * src/gdbus/test/test-example:
+       * src/syncevo-dbus-server.cpp:
+
+       gdbus C++: simplified method declaration
+
+2009-10-12  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/gdbus/gdbus.h:
+       * src/gdbus/object.c:
+
+       gdbus: per-method callback data
+
+2009-10-12  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/gdbus/gdbus.h:
+
+       gdbus: add _NONE = 0 enum value for C++
+
+2009-10-14  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * Makefile-gen.am:
+       * src/syncevo/Makefile.am:
+       * src/syncevo/installcheck-local.sh:
+
+       packaging: fix for installcheck
+
+2009-10-13  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/Cmdline.cpp:
+
+       command line: removing non-existant configuration prints error
+       (MB #6673)
+
+2009-10-13  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/SyncConfig.cpp:
+       * src/syncevo/SyncContext.cpp:
+
+       message resend: zero interval disables resending (MB #6500)
+
+2009-10-13  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/SyncConfig.h:
+
+       command line config value checking: detect negative values on 32
+       bit (MB #6500)
+
+2009-10-13  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * NEWS:
+
+       NEWS: fixed some typos, improved wording
+
+2009-10-12  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * Makefile-gen.am:
+       * configure-post.in:
+       * src/syncevo/eds_abi_wrapper.cpp:
+       * src/syncevo/eds_abi_wrapper.h:
+
+       --enable-evolution-compatibility: added
+       icalcomp_get_location/summary (MB#6552), added test
+
+2009-10-13  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+       * test/test-dbus.py:
+
+       D-Bus testing: use 'unittest' to write tests, watch
+       syncevo-dbus-server
+
+2009-10-13  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-ui-config.c:
+       * src/gtk-ui/sync-ui-config.h:
+       * src/gtk-ui/sync-ui.c:
+
+       gtk-ui: disable sources that are not supported (MB#6672)
+
+2009-10-13  andika  <andika@gmail.com>
+
+       * po/id.po:
+
+       l10n: Updates to Indonesian (id) translation
+
+2009-10-13  andika  <andika@gmail.com>
+
+       * po/id.po:
+
+       l10n: Updates to Indonesian (id) translation
+
+2009-10-10  GLS_CHS  <yunx.nie@intel.com>
+
+       * po/zh_CN.po:
+
+       l10n: Updates to Chinese (China) (zh_CN) translation
+
+2009-09-24  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+
+       syncevo-dbus-server: use Server Alerted Notification (SAN)
+       message content
+
+2009-09-24  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/SyncML.cpp:
+       * src/syncevo/SyncML.h:
+
+       SyncMode: use values that are consistent with SyncML spec
+
+2009-10-07  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+
+       syncevo-dbus-server setConfig: added TODO
+
+2009-09-27  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+       * test/dbus-server-config.py:
+
+       syncevo-dbus-server: implement checkSource and getDatabases
+
+2009-09-25  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+
+       syncevo-dbus-server: add workarounds for getConfig/getReports
+
+2009-09-21  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * src/dbus/interfaces/syncevo-server-full.xml:
+       * src/syncevo-dbus-server.cpp:
+       * test/dbus-server-config.py:
+
+       syncevo-dbus-server: add implementation for getReports
+
+2009-09-22  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+       * src/syncevo/FileConfigNode.cpp:
+       * test/dbus-server-config.py:
+
+       syncevo-dbus-server: implement getConfig/setConfig
+
+2009-09-14  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * src/dbus/interfaces/syncevo-server-full.xml:
+
+       DBUS-API: fix a xml syntax error in dbus-api
+
+2009-10-01  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+       * src/syncevo/SyncContext.cpp:
+
+       EvolutionSyncClient: added some more TODOs
+
+2009-09-30  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+
+       syncevo-dbus-server: close connection on error
+
+2009-09-29  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/Cmdline.cpp:
+       * src/syncevo/ConfigTree.h:
+       * src/syncevo/FileConfigTree.cpp:
+       * src/syncevo/SyncConfig.cpp:
+       * src/syncevo/SyncConfig.h:
+       * src/syncevo/SyncContext.cpp:
+       * src/syncevo/SyncSource.cpp:
+       * src/syncevo/SyncSource.h:
+       * src/syncevo/SynthesisDBPlugin.cpp:
+       * src/syncevo/TrackingSyncSource.cpp:
+       * src/syncevo/TrackingSyncSource.h:
+
+       SyncML server: handle admin data inside SyncEvolution, use
+       <simpleauthuser/pw>
+
+2009-09-29  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/SyncConfig.cpp:
+
+       config: allow empty username/password
+
+2009-09-29  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/ConfigNode.h:
+       * src/syncevo/FileConfigNode.cpp:
+       * src/syncevo/FileConfigNode.h:
+       * src/syncevo/FilterConfigNode.cpp:
+       * src/syncevo/FilterConfigNode.h:
+       * src/syncevo/HashConfigNode.h:
+       * src/syncevo/PrefixConfigNode.h:
+       * src/syncevo/SafeConfigNode.h:
+
+       ConfigNode API: added writeProperties() and clear()
+
+2009-09-29  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/SafeConfigNode.cpp:
+       * src/syncevo/SafeConfigNode.h:
+
+       SafeConfigNode: make escape/unescape utility functions public
+
+2009-09-27  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * HACKING:
+       * configure-pre.in:
+       * src/Makefile-gen.am:
+       * src/syncclient_sample_config.xml:
+       * src/syncevo-dbus-server.cpp:
+       * src/syncevo/Makefile.am:
+       * src/syncevo/SyncContext.cpp:
+       * src/syncevo/SyncContext.h:
+       * src/syncevo/SynthesisEngine.cpp:
+       * src/syncevo/SynthesisEngine.h:
+       * test/syncevo-http-server.py:
+
+       syncevo-dbus-server/syncevolution-http-server.py: SyncML HTTP
+       server
+
+2009-09-27  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/util.h:
+
+       StringMap: alias for std::map<std::string, std::string>
+
+2009-09-24  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/dbus/interfaces/syncevo-server-full.xml:
+
+       D-Bus API: added error specification
+
+2009-09-23  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/dbus/interfaces/syncevo-session-full.xml:
+
+       D-Bus API: added database listing and config checking
+
+2009-09-23  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/SyncConfig.h:
+       * src/syncevo/SyncContext.cpp:
+       * src/syncevo/SyncSource.h:
+
+       sync progress: generate information about inactive sources
+
+2009-09-23  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/dbus/interfaces/syncevo-server-full.xml:
+
+       D-Bus API: added Server.InfoRequest/Response
+
+2009-09-23  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+
+       syncevo-dbus-server: use string for session identifier
+
+2009-09-22  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+
+       syncevo-dbus-server: added stubs for
+       Attach/Detach/Presence/CheckPresence
+
+2009-09-21  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+       * src/syncevo/TransportAgent.cpp:
+       * src/syncevo/TransportAgent.h:
+
+       syncevo-dbus-server: allow SAN messages to start a Connection
+
+2009-09-21  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/SyncContext.cpp:
+
+       transport logic: avoid calling the engine with STEPCMD_SENTDATA
+       twice
+
+2009-09-17  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+       * test/dbus-server-http.py:
+
+       syncevo-dbus-server: implemented syncs via Connection API
+
+2009-09-17  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+
+       syncevo-dbus-server: fix for handling of active session
+
+2009-10-07  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/CurlTransportAgent.cpp:
+       * src/syncevo/CurlTransportAgent.h:
+       * src/syncevo/Makefile.am:
+       * src/syncevo/SoupTransportAgent.cpp:
+       * src/syncevo/SoupTransportAgent.h:
+       * src/syncevo/SyncConfig.cpp:
+       * src/syncevo/SyncConfig.h:
+       * src/syncevo/SyncContext.cpp:
+       * src/syncevo/SyncContext.h:
+       * src/syncevo/TransportAgent.cpp:
+       * src/syncevo/TransportAgent.h:
+       * test/ClientTest.h:
+
+       TransportAgent: added shutdown(), moved HTTP setup out of core
+       engine
+
+2009-09-17  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/SynthesisEngine.h:
+
+       SharedBuffer: added the possibility to create a SharedBuffer from
+       const memory
+
+2009-09-14  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo-dbus-server.cpp:
+       * test/dbus-server-sync.py:
+
+       syncevo-dbus-server: implemented Session.Sync() parameter
+       handling
+
+2009-09-14  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/CmdlineSyncClient.cpp:
+       * src/CmdlineSyncClient.h:
+       * src/client-test-app.cpp:
+       * src/syncevo-dbus-server.cpp:
+       * src/syncevo/Cmdline.cpp:
+       * src/syncevo/SyncConfig.cpp:
+       * src/syncevo/SyncConfig.h:
+       * src/syncevo/SyncContext.cpp:
+       * src/syncevo/SyncContext.h:
+       * src/syncevolution.cpp:
+
+       sync source handling: implemented per-source property filtering,
+       Cmdline uses it
 
-2009-11-27  Patrick Ohly  <patrick.ohly@intel.com>
+2009-09-14  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * Makefile-gen.am:
+       * src/syncevo-dbus-server.cpp:
+       * test/dbus-server-sync.py:
 
-       autotools: install doc files in normal --docdir (MB #7168)
+       syncevo-dbus-server: implemented Session.Sync() and sync
+       status/progress
 
-2009-11-27  Patrick Ohly  <patrick.ohly@intel.com>
+2009-09-14  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * Makefile-gen.am:
+       * src/syncevo/SyncContext.cpp:
+       * src/syncevo/SyncContext.h:
 
-       autotools: include gen-autotools.sh in source tar ball (MB #7822)
+       SyncContext: added handleException()
 
-2009-11-24  Kristho  <lakristho@gmail.com>
+2009-09-09  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * po/da.po:
+       * src/syncevo-dbus-server.cpp:
 
-       l10n: Danish translation of syncevolution.
+       syncevo-dbus-server: added stubs for
+       Server/Session.GetConfig/GetReports()
 
-2009-11-16  itsoftex  <yousef@itsoftex.com>
+2009-09-08  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * po/ar.po:
+       * src/DBusSyncClient.cpp:
+       * src/DBusSyncClient.h:
+       * src/Makefile-gen.am:
+       * src/syncevo-dbus-server.cpp:
+       * src/syncevo-dbus-server.h:
+       * test/dbus-server-connect.py:
 
-       l10n: Updates to Arabic (ar) translation
+       syncevo-dbus-server: moved to gdbus with C++ bridge
 
-2009-11-16  itsoftex  <yousef@itsoftex.com>
+2009-10-07  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * po/ar.po:
+       * src/dbus/interfaces/Makefile.am:
+       * src/dbus/interfaces/spec-to-docbook.xsl:
+       * src/dbus/interfaces/syncevo-connection-full.xml:
+       * src/dbus/interfaces/syncevo-server-full.xml:
+       * src/dbus/interfaces/syncevo-session-full.xml:
 
-       l10n: Arabic Translation, partial upload.
+       D-Bus API: added next generation D-Bus UI API
 
-2009-11-12  GLS_JPN  <etsukox.murozono@intel.com>
+2009-09-03  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * po/ja.po:
+       * src/gdbus/gdbus-cxx-bridge.h:
+       * src/gdbus/test/example.cpp:
+       * src/gdbus/test/test-example:
 
-       l10n: Updates to Japanese (ja) translation
+       D-Bus C++: added support for structs
 
-2009-11-24  tomasgalicia  <tomas.galicia@intel.com>
+2009-09-02  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * po/pt_BR.po:
+       * src/gdbus/gdbus-cxx-bridge.h:
 
-       l10n: Updates to Brazilian Portuguese (pt_BR) translation
+       D-Bus C++: added support for in-place passing of basic arrays
 
-2009-11-24  tomasgalicia  <tomas.galicia@intel.com>
+2009-09-02  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * po/it.po:
+       * src/gdbus/gdbus-cxx-bridge.h:
 
-       l10n: Updates to Italian (it) translation
+       D-Bus C++: let app use char and unsigned char for D-BUS BYTE
 
-2009-11-05  Patrick Ohly  <patrick.ohly@intel.com>
+2009-08-28  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * src/Makefile-gen.am:
+       * src/gdbus/gdbus-cxx-bridge.h:
+       * src/gdbus/gdbus-cxx.h:
+       * src/gdbus/test/example.cpp:
 
-       client-test: unit tests not included when building statically
+       D-Bus C++: added the possibility to pass Caller ID string and a
+       watch
 
-2009-11-09  Patrick Ohly  <patrick.ohly@intel.com>
+2009-09-08  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * configure-pre.in:
+       * src/gdbus/Makefile.am:
+       * src/gdbus/gdbus-cxx-bridge.h:
+       * src/gdbus/gdbus-cxx.h:
+       * src/gdbus/test/example.cpp:
+       * src/gdbus/test/test-example:
 
-       autotools + Boost: --with-boost had no effect (MB#7856)
+       D-Bus C++: C++ helper classes for libdbus/libgdbus
 
-2009-11-03  Patrick Ohly  <patrick.ohly@intel.com>
+2009-09-02  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * gen-autotools.sh:
+       * src/gdbus/watch.c:
 
-       gen-autotools.sh: avoid GNU find -printf
+       gdbus: fixed segfault in watch disconnect function
 
-2009-11-04  Patrick Ohly  <patrick.ohly@intel.com>
+2009-08-27  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * configure-pre.in:
+       * src/gdbus/object.c:
 
-       configure: detect incorrect use of --with-synthesis-src
+       gdbus: allow registering multiple interfaces per object
 
-2009-11-03  Patrick Ohly  <patrick.ohly@intel.com>
+2009-08-27  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * src/syncevo/LogRedirect.cpp:
+       * src/gdbus/object.c:
 
-       stderr redirection: detect "error" messages and show them
-       (MB#7655)
+       g_dbus_unregister_object(): fix same invalid memory reuse as for
+       watches
 
-2009-10-26  GLSQA  <namfonx.yeates@intel.com>
+2009-08-20  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * po/fi.po:
+       * src/gdbus/object.c:
 
-       l10n: Updates to Finnish (fi) translation
+       g_dbus_create_error(): implemented support for detailed error
+       description
 
-2009-10-26  Patrick Ohly  <patrick.ohly@intel.com>
+2009-08-19  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * NEWS:
+       * configure-post.in:
        * configure-pre.in:
+       * src/Makefile-gen.am:
+       * src/gdbus/Makefile.am:
 
-       NEWS, version: updated for 0.9.1
+       gdbus: compile the gdbus utility library
 
-2009-10-21  ZhuYanhai  <zhu.yanhai@gmail.com>
+2009-08-26  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * po/zh_CN.po:
+       * src/gdbus/watch.c:
 
-       l10n: Updates to Chinese (China) (zh_CN) translation
+       watch: call dbus_bus_remove_match() for each dbus_bus_add_match()
 
-2009-10-21  ZhuYanhai  <zhu.yanhai@gmail.com>
+2009-08-26  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * po/zh_CN.po:
+       * src/gdbus/watch.c:
 
-       l10n: Updates to Chinese (China) (zh_CN) translation
+       fix for ConnectionData handling
 
-2009-10-19  Patrick Ohly  <patrick.ohly@intel.com>
+2008-10-17  Marcel Holtmann  <marcel@holtmann.org>
 
-       * NEWS:
-       * configure-pre.in:
+       * src/gdbus/gdbus.h:
+       * src/gdbus/watch.c:
 
-       NEWS, version: updated for 0.9.1 beta 2
+       Extended GDBusWatchFunction parameter list
 
-2009-10-16  Patrick Ohly  <patrick.ohly@intel.com>
+2008-08-13  Marcel Holtmann  <marcel@holtmann.org>
 
-       * test/ClientTest.cpp:
-       * test/ClientTest.h:
+       * src/gdbus/gdbus.h:
+       * src/gdbus/mainloop.c:
+       * src/gdbus/object.c:
+       * src/gdbus/watch.c:
 
-       client-test: added testManyDeletes, improved testManyItems
+       Convert all documentation to gtk-doc style
 
-2009-10-16  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+2008-07-30  Marcel Holtmann  <marcel@holtmann.org>
 
-       * test/valgrindcheck.sh:
+       * src/gdbus/object.c:
 
-       valgrindcheck.sh: return 100 when valgrind finds a problem
+       Protect the interface list with a static mutex
 
-2009-10-16  Congwu Chen  <congwu.chen@intel.com>
+2008-07-01  Marcel Holtmann  <marcel@holtmann.org>
 
-       * test/runtests.py:
+       * src/gdbus/mainloop.c:
 
-       runtests.py: added configuration of Resend test
+       Use a GSource for message dispatching
 
-2009-10-16  Patrick Ohly  <patrick.ohly@intel.com>
+2008-07-01  Marcel Holtmann  <marcel@holtmann.org>
 
-       * test/runtests.py:
+       * src/gdbus/debug.h:
 
-       runtests.py: reformatted source code to split up long lines
+       Don't add an extra newline in the debug messages
 
-2009-10-16  Patrick Ohly  <patrick.ohly@intel.com>
+2008-07-01  Marcel Holtmann  <marcel@holtmann.org>
 
-       * test/runtests.py:
+       * src/gdbus/watch.c:
 
-       runtests.py: build RPMs in addition to DEBs
+       Fix typo in debug statement
 
-2009-10-12  Patrick Ohly  <patrick.ohly@intel.com>
+2008-06-30  Marcel Holtmann  <marcel@holtmann.org>
 
-       * test/runtests.py:
+       * src/gdbus/gdbus.h:
+       * src/gdbus/watch.c:
 
-       runtests.py: fixed "prebuilt" tests
+       Add watch helper for receiving signals
 
-2009-10-12  Patrick Ohly  <patrick.ohly@intel.com>
+2008-06-25  Marcel Holtmann  <marcel@holtmann.org>
 
-       * test/runtests.py:
+       * src/gdbus/gdbus.h:
+       * src/gdbus/mainloop.c:
+       * src/gdbus/object.c:
 
-       runtests.py: fixed building lpia .deb
+       Use automatic object registration only
 
-2009-10-13  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+2008-05-29  Marcel Holtmann  <marcel@holtmann.org>
 
-       * test/generate-html.xsl:
+       * src/gdbus/gdbus.h:
+       * src/gdbus/mainloop.c:
+       * src/gdbus/watch.c:
 
-       Testing: add valgrind result checking and generate result in html
-       output
+       Use common GDBusWatchFunction prototype
 
-2009-10-13  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+2008-05-29  Marcel Holtmann  <marcel@holtmann.org>
 
-       * test/runtests.py:
+       * src/gdbus/gdbus.h:
+       * src/gdbus/watch.c:
 
-       Testing: add nightly test for memotoo
+       Remove return parameter from disconnect watch callback
 
-2009-10-13  Chen Congwu  <congwu.chen@intel.com>
+2008-05-27  Marcel Holtmann  <marcel@holtmann.org>
 
-       * test/runtests.py:
+       * src/gdbus/gdbus.h:
+       * src/gdbus/object.c:
 
-       Testing: add time info for mail title
+       Add more flexible error handling helpers
 
-2009-10-13  Chen Congwu  <congwu.chen@intel.com>
+2008-05-27  Marcel Holtmann  <marcel@holtmann.org>
 
-       * test/runtests.py:
+       * src/gdbus/gdbus.h:
+       * src/gdbus/object.c:
 
-       Testing: change know failures to skip for google testing
+       Add support for per interface user data
 
-2009-09-28  Chen Congwu  <congwu.chen@intel.com>
+2008-05-19  Marcel Holtmann  <marcel@holtmann.org>
 
-       * test/runtests.py:
+       * src/gdbus/gdbus.h:
+       * src/gdbus/object.c:
 
-       Testing: add valgrind check result and backend scan dir
+       Add helper functions for creating errors and replies
 
-2009-09-28  Chen Congwu  <congwu.chen@intel.com>
+2008-05-19  Marcel Holtmann  <marcel@holtmann.org>
 
-       * test/resultchecker.py:
-       * test/runtests.py:
+       * src/gdbus/gdbus.h:
+       * src/gdbus/object.c:
 
-       Testing: add valgrind check result and backend scan dir
+       Add helper functions for sending errors and replies
 
-2009-10-16  Patrick Ohly  <patrick.ohly@intel.com>
+2008-05-17  Marcel Holtmann  <marcel@holtmann.org>
 
-       * src/syncevo/SyncContext.cpp:
+       * src/gdbus/object.c:
 
-       fixed typo: Aboring -> Aborting
+       Protect the object list with a static mutex
 
-2009-10-15  Patrick Ohly  <patrick.ohly@intel.com>
+2008-05-16  Marcel Holtmann  <marcel@holtmann.org>
 
-       * test/README.mobical:
-       * test/synccompare.pl:
+       * src/gdbus/debug.c:
+       * src/gdbus/debug.h:
+       * src/gdbus/gdbus.h:
+       * src/gdbus/mainloop.c:
+       * src/gdbus/object.c:
+       * src/gdbus/watch.c:
 
-       Mobical: PHOTOs preserved verbatim (MB#6668)
+       Update copyright information
 
-2009-10-15  Patrick Ohly  <patrick.ohly@intel.com>
+2008-05-16  Marcel Holtmann  <marcel@holtmann.org>
 
-       * src/syncevo/Makefile.am:
-       * src/syncevo/installcheck-local.sh:
+       * src/gdbus/mainloop.c:
 
-       packaging: another fix for installcheck-local
+       Remove option for using dbus-glib's mainloop integration
 
-2009-10-15  Patrick Ohly  <patrick.ohly@intel.com>
+2008-02-22  Marcel Holtmann  <marcel@holtmann.org>
 
-       * Makefile-gen.am:
+       * src/gdbus/mainloop.c:
 
-       packaging: force serialization of "install" and "installcheck"
+       Add additional checks for error handling
 
-2009-10-15  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+2008-02-18  Marcel Holtmann  <marcel@holtmann.org>
 
-       * src/syncevo/SyncSource.cpp:
+       * src/gdbus/mainloop.c:
 
-       SyncSourceSerialize: a typo for vCalendar1.0 in getSynthesisInfo
+       Add option to use dbus-glib's mainloop integration
 
-2009-10-15  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+2008-02-15  Marcel Holtmann  <marcel@holtmann.org>
 
-       * src/syncclient_sample_config.xml:
-       * src/syncevo/SyncSource.cpp:
+       * src/gdbus/gdbus.h:
+       * src/gdbus/mainloop.c:
 
-       SyncSource: Add 'prioprity' conversion between vCalendar1.0 and
-       2.0
+       Add error parameter to setup functions
 
-2009-10-15  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+2008-02-04  Marcel Holtmann  <marcel@holtmann.org>
 
-       * src/backends/evolution/EvolutionContactSource.h:
-       * src/syncclient_sample_config.xml:
-       * src/syncevo/SyncSource.cpp:
-       * src/syncevo/SyncSource.h:
+       * src/gdbus/gdbus.h:
+       * src/gdbus/object.c:
 
-       SyncSource: change names for m_incomingScript and
-       m_outgointScript
+       Add annotation for asynchronous methods
 
-2009-10-14  xosecalvo  <ubuntu@galizaweb.net>
+2008-01-24  Marcel Holtmann  <marcel@holtmann.org>
 
-       * po/gl.po:
+       * src/gdbus/mainloop.c:
 
-       l10n: First Galician translation
+       Add error handling if bus is not available
 
-2009-10-14  Patrick Ohly  <patrick.ohly@intel.com>
+2008-01-03  Marcel Holtmann  <marcel@holtmann.org>
 
-       * Makefile-gen.am:
-       * src/syncevo/Makefile.am:
-       * src/syncevo/installcheck-local.sh:
+       * src/gdbus/gdbus.h:
+       * src/gdbus/mainloop.c:
 
-       packaging: fix for installcheck
+       Add function for requesting additional bus names
 
-2009-10-13  Patrick Ohly  <patrick.ohly@intel.com>
+2007-12-24  Marcel Holtmann  <marcel@holtmann.org>
 
-       * src/syncevo/Cmdline.cpp:
+       * src/gdbus/gdbus.h:
+       * src/gdbus/object.c:
 
-       command line: removing non-existant configuration prints error
-       (MB #6673)
+       Fix naming of object flags
 
-2009-10-13  Patrick Ohly  <patrick.ohly@intel.com>
+2007-12-22  Marcel Holtmann  <marcel@holtmann.org>
 
-       * src/syncevo/SyncConfig.cpp:
-       * src/syncevo/SyncContext.cpp:
+       * src/gdbus/object.c:
 
-       message resend: zero interval disables resending (MB #6500)
+       Fix parent path validation check
 
-2009-10-13  Patrick Ohly  <patrick.ohly@intel.com>
+2007-12-22  Marcel Holtmann  <marcel@holtmann.org>
 
-       * src/syncevo/SyncConfig.h:
+       * src/gdbus/object.c:
 
-       command line config value checking: detect negative values on 32
-       bit (MB #6500)
+       Fix user data in property callbacks
 
-2009-10-13  Patrick Ohly  <patrick.ohly@intel.com>
+2007-12-21  Marcel Holtmann  <marcel@holtmann.org>
 
-       * NEWS:
+       * src/gdbus/object.c:
 
-       NEWS: fixed some typos, improved wording
+       Fix introspection update for parent objects
 
-2009-10-12  Patrick Ohly  <patrick.ohly@intel.com>
+2007-12-20  Marcel Holtmann  <marcel@holtmann.org>
 
-       * Makefile-gen.am:
-       * configure-post.in:
-       * src/syncevo/eds_abi_wrapper.cpp:
-       * src/syncevo/eds_abi_wrapper.h:
+       * src/gdbus/gdbus.h:
+       * src/gdbus/mainloop.c:
 
-       --enable-evolution-compatibility: added
-       icalcomp_get_location/summary (MB#6552), added test
+       Add function for connecting to specific bus addresses
 
-2009-10-13  Jussi Kukkonen  <jku@linux.intel.com>
+2007-12-19  Marcel Holtmann  <marcel@holtmann.org>
 
-       * src/gtk-ui/sync-ui-config.c:
-       * src/gtk-ui/sync-ui-config.h:
-       * src/gtk-ui/sync-ui.c:
+       * src/gdbus/gdbus.h:
 
-       gtk-ui: disable sources that are not supported (MB#6672)
+       Add documentation groups
 
-2009-10-13  andika  <andika@gmail.com>
+2007-12-19  Marcel Holtmann  <marcel@holtmann.org>
 
-       * po/id.po:
+       * src/gdbus/gdbus.h:
+       * src/gdbus/mainloop.c:
 
-       l10n: Updates to Indonesian (id) translation
+       Add skeleton for message bus disconnect handling
 
-2009-10-13  andika  <andika@gmail.com>
+2007-12-19  Marcel Holtmann  <marcel@holtmann.org>
 
-       * po/id.po:
+       * src/gdbus/Makefile.am:
+       * src/gdbus/gdbus.h:
+       * src/gdbus/mainloop.c:
+       * src/gdbus/watch.c:
 
-       l10n: Updates to Indonesian (id) translation
+       Add functions for client monitoring
 
-2009-10-10  GLS_CHS  <yunx.nie@intel.com>
+2007-12-19  Marcel Holtmann  <marcel@holtmann.org>
 
-       * po/zh_CN.po:
+       * src/gdbus/Makefile.am:
+       * src/gdbus/gdbus.h:
+       * src/gdbus/mainloop.c:
+       * src/gdbus/object.c:
 
-       l10n: Updates to Chinese (China) (zh_CN) translation
+       Add functions for object and interface handling
+
+2007-12-19  Marcel Holtmann  <marcel@holtmann.org>
+
+       * src/gdbus/Makefile.am:
+       * src/gdbus/debug.c:
+       * src/gdbus/debug.h:
+       * src/gdbus/gdbus.h:
+       * src/gdbus/mainloop.c:
+
+       Add functions for mainloop integration
+
+2009-09-08  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * build/import-foreign-git.sh:
+       * build/import-gdbus.sh:
+       * build/import-synthesis-xml.sh:
+       * src/gdbus/README:
+
+       gdbus: start importing the complete upstream development history
 
 2009-10-06  Patrick Ohly  <patrick.ohly@intel.com>
 
 
        NEWS/Mobical.net: note about password, mention SQLite backend
 
+2009-09-30  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-config-widget.c:
+       * src/gtk-ui/sync-config-widget.h:
+       * src/gtk-ui/sync-ui.c:
+
+       gtk-ui: minor button label changes
+
+2009-09-30  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-config-widget.c:
+       * src/gtk-ui/sync-ui-config.c:
+
+       gtk-ui: don't use default username at all
+
+2009-09-30  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-config-widget.c:
+
+       gtk-ui: SyncConfigWidget expander button fix
+
+2009-09-30  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-config-widget.c:
+
+       gtk-ui: add translator comments, modify server expander label
+
+2009-09-30  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-config-widget.c:
+
+       gtk-ui: add "(manually setup)" to manual service titles
+
+2009-09-30  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-config-widget.c:
+
+       gtk-ui: i18n fixes
+
+2009-09-30  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-config-widget.c:
+       * src/gtk-ui/sync-ui-config.c:
+       * src/gtk-ui/sync-ui.c:
+
+       gtk-ui: handle config changes in current config better
+
+2009-09-30  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-config-widget.c:
+       * src/gtk-ui/sync-config-widget.h:
+       * src/gtk-ui/sync-ui.c:
+
+       gtk-ui: implement save
+
+2009-09-30  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-config-widget-gtk.c:
+       * src/gtk-ui/sync-config-widget-gtk.h:
+       * src/gtk-ui/sync-config-widget-moblin.c:
+       * src/gtk-ui/sync-config-widget-moblin.h:
+       * src/gtk-ui/sync-config-widget.c:
+       * src/gtk-ui/sync-config-widget.h:
+
+       gtk-ui: add forgotten files
+
+2009-09-30  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/sync-config-widget.h:
+       * src/gtk-ui/sync-ui.c:
+       * src/gtk-ui/ui.glade:
+
+       gtk-ui: add automatic expansion to service list
+
+2009-09-29  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/Makefile.am:
+       * src/gtk-ui/sync-config-widget-gtk.c:
+       * src/gtk-ui/sync-config-widget-gtk.h:
+       * src/gtk-ui/sync-config-widget-moblin.c:
+       * src/gtk-ui/sync-config-widget-moblin.h:
+       * src/gtk-ui/sync-config-widget.h:
+       * src/gtk-ui/sync-ui-config.c:
+       * src/gtk-ui/sync-ui-config.h:
+       * src/gtk-ui/sync-ui.c:
+       * src/gtk-ui/sync-ui.h:
+       * src/gtk-ui/ui.glade:
+
+       gtk-ui: implement the service list contents as widgets
+
+2009-09-28  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * configure-pre.in:
+       * src/gtk-ui/sync-ui.c:
+       * src/gtk-ui/ui.glade:
+
+       gtk-ui: use NbtkGtkExpander in service list
+
+2009-09-28  Jussi Kukkonen  <jku@linux.intel.com>
+
+       * src/gtk-ui/mux-icon-button.c:
+       * src/gtk-ui/mux-icon-button.h:
+       * src/gtk-ui/mux-window.c:
+       * src/gtk-ui/mux-window.h:
+       * src/gtk-ui/sync-ui.c:
+       * src/gtk-ui/ui.glade:
+
+       implement first phase of "single window mode"
+
 2009-09-27  Chen Congwu  <congwu.chen@intel.com>
 
        * src/backends/evolution/EvolutionCalendarSource.h:
diff --git a/HACKING b/HACKING
index b9f5791..af25ee7 100644 (file)
--- a/HACKING
+++ b/HACKING
@@ -30,11 +30,15 @@ For doing development work the recommended configure line is:
              CXXFLAGS="-g -Wall -Werror -Wno-unknown-pragmas" \
              --enable-unit-tests \
              --enable-libcurl \
+             --disable-shared \
              --enable-developer-mode
 
 Enabling libcurl explicitly ensures that it gets built even when not
 the default.
 
+--disable-shared results in easier to debug executables (no shell
+wrapper scripts, all symbols available before the program runs).
+
 Backend libraries are dynamically scannned and loaded into syncevolution, the
 library path defaults to $prefix/syncevolution/backends. When developer-mode is
 enabled, it will scan libraries in current build directory instead.
index 212140b..f304225 100644 (file)
@@ -129,7 +129,7 @@ dist/$(distdir): all
        rm -rf $(call DEV_FILE_PATTERN, $@)
 clean-local: clean_dist
 clean_dist:
-       rm -rf dist description-pak
+       rm -rf dist doc-pak description-pak
 
 # install doc files via normal autotools
 dist_doc_DATA = README NEWS COPYING $(TEST_README_FILES)
index 0b37ef2..d78976d 100644 (file)
@@ -129,7 +129,7 @@ dist/$(distdir): all
        rm -rf $(call DEV_FILE_PATTERN, $@)
 clean-local: clean_dist
 clean_dist:
-       rm -rf dist description-pak
+       rm -rf dist doc-pak description-pak
 
 # install doc files via normal autotools
 dist_doc_DATA = README NEWS COPYING $(TEST_README_FILES)
@@ -162,7 +162,7 @@ clean-html:
 # Because backend-related variables need to be substituted in
 # Makefile-gen.am and configure.in we need an explicit rule to redo that work
 # so that "make" rebuilds derived files correctly.
-CONFIG_SUBS =  src/backends/addressbook/configure-sub.in src/backends/evolution/configure-sub.in src/backends/file/configure-sub.in src/backends/maemo/configure-sub.in src/backends/sqlite/configure-sub.in src/backends/xmlrpc/configure-sub.in
+CONFIG_SUBS =  src/backends/addressbook/configure-sub.in src/backends/evolution/configure-sub.in src/backends/file/configure-sub.in src/backends/sqlite/configure-sub.in
 $(srcdir)/configure.in: configure-pre.in configure-post.in $(CONFIG_SUBS)
        rm -f $@
        cat $(srcdir)/configure-pre.in >>$@
index 260b9b9..14a89f2 100644 (file)
@@ -94,6 +94,8 @@ AUTOMAKE = @AUTOMAKE@
 AWK = @AWK@
 BACKEND_CPPFLAGS = @BACKEND_CPPFLAGS@
 BACKEND_DEFINES = @BACKEND_DEFINES@
+BLUEZ_CFLAGS = @BLUEZ_CFLAGS@
+BLUEZ_LIBS = @BLUEZ_LIBS@
 BOOST_CPPFLAGS = @BOOST_CPPFLAGS@
 BOOST_LDFLAGS = @BOOST_LDFLAGS@
 CATALOGS = @CATALOGS@
@@ -101,7 +103,6 @@ CATOBJEXT = @CATOBJEXT@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
-CLEAN_CLIENT_SRC = @CLEAN_CLIENT_SRC@
 CORE_LDADD_DEP = @CORE_LDADD_DEP@
 CPP = @CPP@
 CPPFLAGS = @CPPFLAGS@
@@ -114,8 +115,10 @@ CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
 DATADIRNAME = @DATADIRNAME@
 DBUS_BINDING_TOOL = @DBUS_BINDING_TOOL@
+DBUS_CFLAGS = @DBUS_CFLAGS@
 DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@
 DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@
+DBUS_LIBS = @DBUS_LIBS@
 DBUS_SERVICES_DIR = @DBUS_SERVICES_DIR@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
@@ -142,11 +145,7 @@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
 GLIB_LIBS = @GLIB_LIBS@
 GMOFILES = @GMOFILES@
 GMSGFMT = @GMSGFMT@
-GOBJECT_CFLAGS = @GOBJECT_CFLAGS@
-GOBJECT_LIBS = @GOBJECT_LIBS@
 GREP = @GREP@
-GTHREAD_CFLAGS = @GTHREAD_CFLAGS@
-GTHREAD_LIBS = @GTHREAD_LIBS@
 GTK_BUILDER_CONV = @GTK_BUILDER_CONV@
 GUI_CFLAGS = @GUI_CFLAGS@
 GUI_DESKTOP_FILES = @GUI_DESKTOP_FILES@
@@ -170,6 +169,8 @@ KEYRING_LIBS = @KEYRING_LIBS@
 LDFLAGS = @LDFLAGS@
 LIBEXECDIR = @LIBEXECDIR@
 LIBOBJS = @LIBOBJS@
+LIBOPENOBEX_CFLAGS = @LIBOPENOBEX_CFLAGS@
+LIBOPENOBEX_LIBS = @LIBOPENOBEX_LIBS@
 LIBS = @LIBS@
 LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@
 LIBSOUP_LIBS = @LIBSOUP_LIBS@
@@ -177,8 +178,6 @@ LIBTOOL = @LIBTOOL@
 LN_S = @LN_S@
 LTLIBOBJS = @LTLIBOBJS@
 MAKEINFO = @MAKEINFO@
-MCALB_CFLAGS = @MCALB_CFLAGS@
-MCALB_LIBS = @MCALB_LIBS@
 MKDIR_P = @MKDIR_P@
 MKINSTALLDIRS = @MKINSTALLDIRS@
 MODIFY_SYNCCOMPARE = @MODIFY_SYNCCOMPARE@
@@ -214,6 +213,7 @@ SYNTHESIS = @SYNTHESIS@
 SYNTHESISSRC = @SYNTHESISSRC@
 SYNTHESIS_CFLAGS = @SYNTHESIS_CFLAGS@
 SYNTHESIS_DEP = @SYNTHESIS_DEP@
+SYNTHESIS_ENGINE = @SYNTHESIS_ENGINE@
 SYNTHESIS_LIB = @SYNTHESIS_LIB@
 SYNTHESIS_LIBS = @SYNTHESIS_LIBS@
 SYNTHESIS_SRC = @SYNTHESIS_SRC@
@@ -225,8 +225,6 @@ UNIQUE_LIBS = @UNIQUE_LIBS@
 USE_NLS = @USE_NLS@
 VERSION = @VERSION@
 XGETTEXT = @XGETTEXT@
-XMLRPC_CFLAGS = @XMLRPC_CFLAGS@
-XMLRPC_LIBS = @XMLRPC_LIBS@
 XSLT = @XSLT@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
@@ -324,7 +322,7 @@ dist_doc_DATA = README NEWS COPYING $(TEST_README_FILES)
 # Because backend-related variables need to be substituted in
 # Makefile-gen.am and configure.in we need an explicit rule to redo that work
 # so that "make" rebuilds derived files correctly.
-CONFIG_SUBS = src/backends/addressbook/configure-sub.in src/backends/evolution/configure-sub.in src/backends/file/configure-sub.in src/backends/maemo/configure-sub.in src/backends/sqlite/configure-sub.in src/backends/xmlrpc/configure-sub.in
+CONFIG_SUBS = src/backends/addressbook/configure-sub.in src/backends/evolution/configure-sub.in src/backends/file/configure-sub.in src/backends/sqlite/configure-sub.in
 all: config.h
        $(MAKE) $(AM_MAKEFLAGS) all-recursive
 
@@ -885,7 +883,7 @@ dist/$(distdir): all
        rm -rf $(call DEV_FILE_PATTERN, $@)
 clean-local: clean_dist
 clean_dist:
-       rm -rf dist description-pak
+       rm -rf dist doc-pak description-pak
 
 # required by dpkg-shlibdeps
 dist/debian/control:
diff --git a/NEWS b/NEWS
index 6457dc2..8ca2947 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -145,30 +145,12 @@ Upgrading from 0.9.x:
   above). Such configs cannot be used by older SyncEvolution releases.
 
 
-SyncEvolution 0.9.1 -> 0.9.2, 23.01.2010
-========================================
+SyncEvolution 0.9.1 -> 0.9.2, not released yet
+==============================================
 Synthesis SyncML Engine version: see src/synthesis/ChangeLog
 
-New Maemo 5/Nokia N900 calendar backend and packages, brought to you
-by Ove Kaaven. These packages are available via the Maemo extras-devel
-repository. Bug reports can be submitted both in http://bugs.maemo.org
-and http://bugzilla.moblin.org. The latter is the tracker that is
-monitored by the SyncEvolution team, which will also incorporate
-patches. In general, Ove is the main maintainer of the new backend.
-
-New XMLRPC backend, contributed by Franz Knipp/M-otion. It accesses
-data inside a web service via a SOUP API and thus allows synchronizing
-it via SyncML. See src/backends/xmlrpc/README for more information.
-
-Added templates for Oracle Beehive and Goosync. Both are not currently
-part of the regular testing.
-
-In addition to that, 0.9.2 is an incremental update, with several
-updated translations and addressing all of the issues reported by
-users for 0.9.1:
-
-- vCard dialects: added "X-GENDER/X-SIP" (used by Maemo) and X-SKYPE
-  (used by Maemo and recent Evolution, MB #8948)
+Incremental update, with several updated translations and addressing
+most of the issues reported by users for 0.9.1:
 
 - Evolution Address Book: avoid picking CouchDB by default (MB #7877, evolution-couchdb #479110)
 
@@ -193,14 +175,10 @@ users for 0.9.1:
   into syncevolution.org .tar.gz/.deb/.rpm archives as part of
   custom make rules and thus missing in other installations.
 
-- building: --with-boost had no effect (MB#7856), detect incorrect
-  use of --with-synthesis-src, workaround for lack of --with-docdir
-  in older autoconf, do not unnecessarily depend on CPPUnit header
-  files and GNOME/EDS libs (MB#8338), workaround for libtool bug
-  ("cannot install `syncecal.la' to a directory not ending in ..."),
+- autotools + Boost: --with-boost had no effect (MB#7856)
+
+- configure: detect incorrect use of --with-synthesis-src
 
-- clarified documentation of properties for file backend (MB#8146)
-  
 - stderr redirection: detect "error" messages and show them (MB#7655)
   The "GConf Error: Failed to contact configuration server..." error
   message was suppressed by the code which catches noise from libraries
@@ -209,22 +187,6 @@ users for 0.9.1:
   additional changes:
   http://www.estamos.de/blog/2009/05/08/running-syncevolution-as-cron-job/
 
-- importing contacts from SyncML server without full name (MB#5664):
-  Evolution expects the name to be set and shows an empty string if
-  it is missing. Now the name is re-added by appending first, middle and
-  last name.
-
-- Evolution calendar: work around 'cannot encode item' problem (MB #7879)
-  Happens when the calendar file contains broken events which reference
-  a timezone that is not defined. Now the event is treated like one in
-  the local timezone.
-
-- "http_proxy" env variable is supported regardless which HTTP transport
-  is used (MB#8177).
-
-- avoid crashes when libecal sets neither error nor pointer (MB#8005)
-  and when aborting a running sync in the syncevo-dbus-server (MB#8385)
-
 Upgrading from 0.9.1:
 
 * nothing to do, upgrading and downgrading should work seamlessly
index 0039dba..8b1c958 100644 (file)
@@ -9,6 +9,9 @@
 /* addressbook available */
 #undef ENABLE_ADDRESSBOOK
 
+/* define if bluez library is available */
+#undef ENABLE_BLUETOOTH
+
 /* libebook available */
 #undef ENABLE_EBOOK
 
@@ -18,9 +21,6 @@
 /* file available */
 #undef ENABLE_FILE
 
-/* enable integration tests inside the final library */
-#undef ENABLE_INTEGRATION_TESTS
-
 /* enable libcurl transport */
 #undef ENABLE_LIBCURL
 
 /* enable Maemo hacks */
 #undef ENABLE_MAEMO
 
-/* Maemo 5 calendar available */
-#undef ENABLE_MAEMO_CALENDAR
-
 /* enable dynamically opening sync source backends */
 #undef ENABLE_MODULES
 
 /* always defined to indicate that i18n is enabled */
 #undef ENABLE_NLS
 
+/* define if openobex library is available */
+#undef ENABLE_OBEX
+
 /* sqlite available */
 #undef ENABLE_SQLITE
 
 /* enable SSL certificate check in server templates */
 #undef ENABLE_SSL_CERTIFICATE_CHECK
 
+/* SyncML client support available */
+#undef ENABLE_SYNCML_CLIENT
+
+/* SyncML engines are linked directly */
+#undef ENABLE_SYNCML_LINKED
+
+/* SyncML server support available */
+#undef ENABLE_SYNCML_SERVER
+
 /* enable single-app-instance functionality */
 #undef ENABLE_UNIQUE
 
 /* enable unit tests inside the library's source code */
 #undef ENABLE_UNIT_TESTS
 
-/* XMLRPC available */
-#undef ENABLE_XMLRPC
-
 /* avoid hard dependency on Evolution shared objects */
 #undef EVOLUTION_COMPATIBILITY
 
 /* compiling for iPhone */
 #undef IPHONE
 
+/* Define to 1 if you need the dbus_watch_get_unix_fd() function. */
+#undef NEED_DBUS_WATCH_GET_UNIX_FD
+
 /* Name of package */
 #undef PACKAGE
 
 /* define if gnome keyring should be used in dbus service */
 #undef USE_GNOME_KEYRING
 
-/* Use the MUX widget library */
+/* Use Moblin UI widgets */
 #undef USE_MOBLIN_UX
 
 /* Version number of package */
index e264b56..5e7dbf8 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.61 for syncevolution 0.9.2.
+# Generated by GNU Autoconf 2.61 for syncevolution 0.9.2+1.0alpha1.
 #
 # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
 # 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
@@ -726,8 +726,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
 # Identity of this package.
 PACKAGE_NAME='syncevolution'
 PACKAGE_TARNAME='syncevolution'
-PACKAGE_VERSION='0.9.2'
-PACKAGE_STRING='syncevolution 0.9.2'
+PACKAGE_VERSION='0.9.2+1.0alpha1'
+PACKAGE_STRING='syncevolution 0.9.2+1.0alpha1'
 PACKAGE_BUGREPORT=''
 
 # Factoring default headers for most tests.
@@ -852,10 +852,17 @@ ENABLE_UNIT_TESTS_FALSE
 ENABLE_TESTING_TRUE
 ENABLE_TESTING_FALSE
 CORE_LDADD_DEP
-CLEAN_CLIENT_SRC
 PKG_CONFIG
 LIBSOUP_CFLAGS
 LIBSOUP_LIBS
+LIBOPENOBEX_CFLAGS
+LIBOPENOBEX_LIBS
+BLUEZ_CFLAGS
+BLUEZ_LIBS
+ENABLE_OBEX_TRUE
+ENABLE_OBEX_FALSE
+ENABLE_BLUETOOTH_TRUE
+ENABLE_BLUETOOTH_FALSE
 TRANSPORT_LIBS
 TRANSPORT_CFLAGS
 XSLT
@@ -871,6 +878,8 @@ DBUS_GLIB_CFLAGS
 DBUS_GLIB_LIBS
 DBUS_BINDING_TOOL
 GLIB_GENMARSHAL
+DBUS_CFLAGS
+DBUS_LIBS
 LIBEXECDIR
 DBUS_SERVICES_DIR
 UNIQUE_CFLAGS
@@ -937,6 +946,7 @@ SYNTHESIS_LIBS
 SYNTHESIS
 SYNTHESIS_SUBDIR
 SYNTHESIS_DEP
+SYNTHESIS_ENGINE
 SYNTHESIS_LIB
 SYNTHESISSRC
 SYNCSOURCES
@@ -954,12 +964,10 @@ ENABLE_ECAL_TRUE
 ENABLE_ECAL_FALSE
 FILE_CFLAGS
 FILE_LIBS
-MCALB_CFLAGS
-MCALB_LIBS
 SQLITE_CFLAGS
 SQLITE_LIBS
-XMLRPC_CFLAGS
-XMLRPC_LIBS
+GLIB_CFLAGS
+GLIB_LIBS
 build
 build_cpu
 build_vendor
@@ -980,12 +988,6 @@ F77
 FFLAGS
 ac_ct_F77
 LIBTOOL
-GLIB_CFLAGS
-GLIB_LIBS
-GTHREAD_CFLAGS
-GTHREAD_LIBS
-GOBJECT_CFLAGS
-GOBJECT_LIBS
 ENABLE_MODULES_TRUE
 ENABLE_MODULES_FALSE
 SYNCEVOLUTION_LDADD
@@ -1009,12 +1011,18 @@ CPP
 PKG_CONFIG
 LIBSOUP_CFLAGS
 LIBSOUP_LIBS
+LIBOPENOBEX_CFLAGS
+LIBOPENOBEX_LIBS
+BLUEZ_CFLAGS
+BLUEZ_LIBS
 KEYRING_CFLAGS
 KEYRING_LIBS
 KEYRING_2_20_CFLAGS
 KEYRING_2_20_LIBS
 DBUS_GLIB_CFLAGS
 DBUS_GLIB_LIBS
+DBUS_CFLAGS
+DBUS_LIBS
 UNIQUE_CFLAGS
 UNIQUE_LIBS
 GUI_CFLAGS
@@ -1030,19 +1038,13 @@ ECAL_CFLAGS
 ECAL_LIBS
 EBOOK_CFLAGS
 EBOOK_LIBS
-MCALB_CFLAGS
-MCALB_LIBS
 SQLITE_CFLAGS
 SQLITE_LIBS
-CXXCPP
-F77
-FFLAGS
 GLIB_CFLAGS
 GLIB_LIBS
-GTHREAD_CFLAGS
-GTHREAD_LIBS
-GOBJECT_CFLAGS
-GOBJECT_LIBS'
+CXXCPP
+F77
+FFLAGS'
 
 
 # Initialize some variables set by options.
@@ -1545,7 +1547,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures syncevolution 0.9.2 to adapt to many kinds of systems.
+\`configure' configures syncevolution 0.9.2+1.0alpha1 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1615,7 +1617,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of syncevolution 0.9.2:";;
+     short | recursive ) echo "Configuration of syncevolution 0.9.2+1.0alpha1:";;
    esac
   cat <<\_ACEOF
 
@@ -1669,12 +1671,8 @@ Optional Features:
                           (must be used to compile without it)
 --disable-file          disable file-based backend which stores items in
                           separate files in a fixed directory (default on)
---enable-maemo-calendar enable access to PIM data stored in Maemo 5 calendar
-                          application (default off)
 --enable-sqlite         enable access to PIM data stored in SQLite files
                           (experimental, default off)
---enable-xmlrpc         enable XMLRPC-based backend which stores items on a
-                          central web service (default off)
   --enable-shared[=PKGS]  build shared libraries [default=yes]
   --enable-static[=PKGS]  build static libraries [default=yes]
   --enable-fast-install[=PKGS]
@@ -1699,6 +1697,10 @@ Optional Packages:
                           copy if the directory already exists. Default:
                           bundled source in src/synthesis (in released
                           SyncEvolution sources),  otherwise.
+  --with-syncml-engines=client|server|both
+                          Determines which kind of support for SyncML is
+                          compiled and linked into SyncEvolution. Default is
+                          both. Currently has no effect.
   --with-synthesis-username=<svn username>
                           username to use when checking out
                           --with-synthesis-src sources from Subversion,
@@ -1742,6 +1744,13 @@ Some influential environment variables:
               C compiler flags for LIBSOUP, overriding pkg-config
   LIBSOUP_LIBS
               linker flags for LIBSOUP, overriding pkg-config
+  LIBOPENOBEX_CFLAGS
+              C compiler flags for LIBOPENOBEX, overriding pkg-config
+  LIBOPENOBEX_LIBS
+              linker flags for LIBOPENOBEX, overriding pkg-config
+  BLUEZ_CFLAGS
+              C compiler flags for BLUEZ, overriding pkg-config
+  BLUEZ_LIBS  linker flags for BLUEZ, overriding pkg-config
   KEYRING_CFLAGS
               C compiler flags for KEYRING, overriding pkg-config
   KEYRING_LIBS
@@ -1754,6 +1763,8 @@ Some influential environment variables:
               C compiler flags for DBUS_GLIB, overriding pkg-config
   DBUS_GLIB_LIBS
               linker flags for DBUS_GLIB, overriding pkg-config
+  DBUS_CFLAGS C compiler flags for DBUS, overriding pkg-config
+  DBUS_LIBS   linker flags for DBUS, overriding pkg-config
   UNIQUE_CFLAGS
               C compiler flags for UNIQUE, overriding pkg-config
   UNIQUE_LIBS linker flags for UNIQUE, overriding pkg-config
@@ -1774,25 +1785,14 @@ Some influential environment variables:
   EBOOK_CFLAGS
               C compiler flags for EBOOK, overriding pkg-config
   EBOOK_LIBS  linker flags for EBOOK, overriding pkg-config
-  MCALB_CFLAGS
-              C compiler flags for MCALB, overriding pkg-config
-  MCALB_LIBS  linker flags for MCALB, overriding pkg-config
   SQLITE_CFLAGS
               C compiler flags for SQLITE, overriding pkg-config
   SQLITE_LIBS linker flags for SQLITE, overriding pkg-config
+  GLIB_CFLAGS C compiler flags for GLIB, overriding pkg-config
+  GLIB_LIBS   linker flags for GLIB, overriding pkg-config
   CXXCPP      C++ preprocessor
   F77         Fortran 77 compiler command
   FFLAGS      Fortran 77 compiler flags
-  GLIB_CFLAGS C compiler flags for GLIB, overriding pkg-config
-  GLIB_LIBS   linker flags for GLIB, overriding pkg-config
-  GTHREAD_CFLAGS
-              C compiler flags for GTHREAD, overriding pkg-config
-  GTHREAD_LIBS
-              linker flags for GTHREAD, overriding pkg-config
-  GOBJECT_CFLAGS
-              C compiler flags for GOBJECT, overriding pkg-config
-  GOBJECT_LIBS
-              linker flags for GOBJECT, overriding pkg-config
 
 Use these variables to override the choices made by `configure' or to help
 it to find libraries and programs with nonstandard names/locations.
@@ -1857,7 +1857,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-syncevolution configure 0.9.2
+syncevolution configure 0.9.2+1.0alpha1
 generated by GNU Autoconf 2.61
 
 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -1871,7 +1871,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by syncevolution $as_me 0.9.2, which was
+It was created by syncevolution $as_me 0.9.2+1.0alpha1, which was
 generated by GNU Autoconf 2.61.  Invocation command line was
 
   $ $0 $@
@@ -2561,7 +2561,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='syncevolution'
- VERSION='0.9.2'
+ VERSION='0.9.2+1.0alpha1'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -2796,7 +2796,7 @@ ac_config_headers="$ac_config_headers config.h"
 
 
 
-DEVICE_TYPE=desktop
+DEVICE_TYPE=workstation
 
 
 # Check whether --with-synthesis-src was given.
@@ -2811,6 +2811,29 @@ fi
 
 
 
+# Check whether --with-syncml-engines was given.
+if test "${with_syncml_engines+set}" = set; then
+  withval=$with_syncml_engines; SYNCML_ENGINES="$withval"
+else
+  SYNCML_ENGINES=both
+fi
+
+
+case $SYNCML_ENGINES in both|client)
+cat >>confdefs.h <<\_ACEOF
+#define ENABLE_SYNCML_CLIENT 1
+_ACEOF
+;; esac
+case $SYNCML_ENGINES in both|server)
+cat >>confdefs.h <<\_ACEOF
+#define ENABLE_SYNCML_SERVER 1
+_ACEOF
+;; esac
+case $SYNCML_ENGINES in both|server|client) true;; *) { { echo "$as_me:$LINENO: error: Invalid value for --with-syncml-engines: $SYNCML_ENGINES" >&5
+echo "$as_me: error: Invalid value for --with-syncml-engines: $SYNCML_ENGINES" >&2;}
+   { (exit 1); exit 1; }; };; esac
+
+
 # Check whether --with-synthesis-username was given.
 if test "${with_synthesis_username+set}" = set; then
   withval=$with_synthesis_username; USERNAME="$withval"
@@ -4785,13 +4808,6 @@ cat >>confdefs.h <<\_ACEOF
 _ACEOF
 
 fi
-if test "$enable_integration_tests" = "yes"; then
-
-cat >>confdefs.h <<\_ACEOF
-#define ENABLE_INTEGRATION_TESTS 1
-_ACEOF
-
-fi
  if test "$enable_unit_tests" = "yes"; then
   ENABLE_UNIT_TESTS_TRUE=
   ENABLE_UNIT_TESTS_FALSE='#'
@@ -4815,13 +4831,6 @@ if test $enable_static_cxx == "yes"; then
 fi
 
 
-# preserve src/synthesis by default,
-# always
-CLEAN_SYNTHESIS_SRC=
-SYNTHESIS_LIB=$PWD/src/build-synthesis/src/libsynthesissdk.la
-
-
-
 # Check for transport layer.
 # Both curl and libsoup can be enabled and disabled explicitly.
 # The default is to use libsoup if available, otherwise curl.
@@ -5174,6 +5183,184 @@ cat >>confdefs.h <<\_ACEOF
 _ACEOF
 
 fi
+
+
+pkg_failed=no
+{ echo "$as_me:$LINENO: checking for LIBOPENOBEX" >&5
+echo $ECHO_N "checking for LIBOPENOBEX... $ECHO_C" >&6; }
+
+if test -n "$PKG_CONFIG"; then
+    if test -n "$LIBOPENOBEX_CFLAGS"; then
+        pkg_cv_LIBOPENOBEX_CFLAGS="$LIBOPENOBEX_CFLAGS"
+    else
+        if test -n "$PKG_CONFIG" && \
+    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"openobex\"") >&5
+  ($PKG_CONFIG --exists --print-errors "openobex") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  pkg_cv_LIBOPENOBEX_CFLAGS=`$PKG_CONFIG --cflags "openobex" 2>/dev/null`
+else
+  pkg_failed=yes
+fi
+    fi
+else
+       pkg_failed=untried
+fi
+if test -n "$PKG_CONFIG"; then
+    if test -n "$LIBOPENOBEX_LIBS"; then
+        pkg_cv_LIBOPENOBEX_LIBS="$LIBOPENOBEX_LIBS"
+    else
+        if test -n "$PKG_CONFIG" && \
+    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"openobex\"") >&5
+  ($PKG_CONFIG --exists --print-errors "openobex") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  pkg_cv_LIBOPENOBEX_LIBS=`$PKG_CONFIG --libs "openobex" 2>/dev/null`
+else
+  pkg_failed=yes
+fi
+    fi
+else
+       pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+               LIBOPENOBEX_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "openobex"`
+        else
+               LIBOPENOBEX_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "openobex"`
+        fi
+       # Put the nasty error message in config.log where it belongs
+       echo "$LIBOPENOBEX_PKG_ERRORS" >&5
+
+       { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+                have_obex="no"
+elif test $pkg_failed = untried; then
+       have_obex="no"
+else
+       LIBOPENOBEX_CFLAGS=$pkg_cv_LIBOPENOBEX_CFLAGS
+       LIBOPENOBEX_LIBS=$pkg_cv_LIBOPENOBEX_LIBS
+        { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+       have_obex="yes"
+fi
+if test $have_obex == "yes"; then
+
+cat >>confdefs.h <<\_ACEOF
+#define ENABLE_OBEX 1
+_ACEOF
+
+
+pkg_failed=no
+{ echo "$as_me:$LINENO: checking for BLUEZ" >&5
+echo $ECHO_N "checking for BLUEZ... $ECHO_C" >&6; }
+
+if test -n "$PKG_CONFIG"; then
+    if test -n "$BLUEZ_CFLAGS"; then
+        pkg_cv_BLUEZ_CFLAGS="$BLUEZ_CFLAGS"
+    else
+        if test -n "$PKG_CONFIG" && \
+    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"bluez\"") >&5
+  ($PKG_CONFIG --exists --print-errors "bluez") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  pkg_cv_BLUEZ_CFLAGS=`$PKG_CONFIG --cflags "bluez" 2>/dev/null`
+else
+  pkg_failed=yes
+fi
+    fi
+else
+       pkg_failed=untried
+fi
+if test -n "$PKG_CONFIG"; then
+    if test -n "$BLUEZ_LIBS"; then
+        pkg_cv_BLUEZ_LIBS="$BLUEZ_LIBS"
+    else
+        if test -n "$PKG_CONFIG" && \
+    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"bluez\"") >&5
+  ($PKG_CONFIG --exists --print-errors "bluez") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  pkg_cv_BLUEZ_LIBS=`$PKG_CONFIG --libs "bluez" 2>/dev/null`
+else
+  pkg_failed=yes
+fi
+    fi
+else
+       pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+               BLUEZ_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "bluez"`
+        else
+               BLUEZ_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "bluez"`
+        fi
+       # Put the nasty error message in config.log where it belongs
+       echo "$BLUEZ_PKG_ERRORS" >&5
+
+       { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+                have_bluez="no"
+elif test $pkg_failed = untried; then
+       have_bluez="no"
+else
+       BLUEZ_CFLAGS=$pkg_cv_BLUEZ_CFLAGS
+       BLUEZ_LIBS=$pkg_cv_BLUEZ_LIBS
+        { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+       have_bluez="yes"
+fi
+    if test $have_bluez == "yes"; then
+
+cat >>confdefs.h <<\_ACEOF
+#define ENABLE_BLUETOOTH 1
+_ACEOF
+
+    fi
+fi
+ if test "$have_obex" = "yes"; then
+  ENABLE_OBEX_TRUE=
+  ENABLE_OBEX_FALSE='#'
+else
+  ENABLE_OBEX_TRUE='#'
+  ENABLE_OBEX_FALSE=
+fi
+
+ if test "$have_bluez" = "yes"; then
+  ENABLE_BLUETOOTH_TRUE=
+  ENABLE_BLUETOOTH_FALSE='#'
+else
+  ENABLE_BLUETOOTH_TRUE='#'
+  ENABLE_BLUETOOTH_FALSE=
+fi
+
+
+
+
+
+
 TRANSPORT=
 TRANSPORT_LIBS=
 TRANSPORT_CFLAGS=
@@ -5257,7 +5444,8 @@ fi
 
 if test ! "$TRANSPORT" &&
    test "$libsoup_disabled" != "yes" &&
-   test "$libcurl_disabled" != "yes"; then
+   test "$libcurl_disabled" != "yes" &&
+   test "$have_bluez" != "yes" ; then
    { { echo "$as_me:$LINENO: error: no transport library found, configure with --disable-libcurl --disable-libsoup to continue anyway (only useful if users of libsyncevolution provide transport implementation)" >&5
 echo "$as_me: error: no transport library found, configure with --disable-libcurl --disable-libsoup to continue anyway (only useful if users of libsyncevolution provide transport implementation)" >&2;}
    { (exit 1); exit 1; }; }
@@ -5366,14 +5554,6 @@ else
 fi
 
 
-if test $enable_gui == "moblin"; then
-
-cat >>confdefs.h <<\_ACEOF
-#define USE_MOBLIN_UX 1
-_ACEOF
-
-fi
-
 # Check whether --enable-dbus-service was given.
 if test "${enable_dbus_service+set}" = set; then
   enableval=$enable_dbus_service; enable_dbus_service="$enableval"
@@ -5754,51 +5934,22 @@ fi
 echo "$as_me: error: xsltproc not found, is required for D-Bus service" >&2;}
    { (exit 1); exit 1; }; }
     fi
-fi
-
-
-
-
-
-
-DBUS_SERVICES_DIR="${datadir}/dbus-1/services"
-
-
-cat >>confdefs.h <<_ACEOF
-#define DBUS_SERVICES_DIR "$DBUS_SERVICES_DIR"
-_ACEOF
-
-
-# decide which sync-ui(s) we are building:
-# sync-ui (in either GTK or Moblin mode) or both (in separate binaries)
-case $enable_gui in
-     all) GUI_PROGRAMS='sync-ui-gtk${EXEEXT} sync-ui-moblin${EXEEXT}'; GUI_DESKTOP_FILES="sync-gtk.desktop sync-moblin.desktop";;
-     gtk|moblin) GUI_PROGRAMS='sync-ui${EXEEXT}'; GUI_DESKTOP_FILES="sync.desktop";;
-     no) GUI_PROGRAMS=; GUI_DESKTOP_FILES=;;
-     *) { { echo "$as_me:$LINENO: error: Unknown enable_gui type: '$enable_gui'" >&5
-echo "$as_me: error: Unknown enable_gui type: '$enable_gui'" >&2;}
-   { (exit 1); exit 1; }; }
-esac
-
-if test $enable_gui != "no"; then
-    gui_modules="glib-2.0 dbus-glib-1 >= 0.60 gtk+-2.0 libglade-2.0 gconf-2.0 gio-2.0 gnome-keyring-1"
-
 
 pkg_failed=no
-{ echo "$as_me:$LINENO: checking for UNIQUE" >&5
-echo $ECHO_N "checking for UNIQUE... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: checking for DBUS" >&5
+echo $ECHO_N "checking for DBUS... $ECHO_C" >&6; }
 
 if test -n "$PKG_CONFIG"; then
-    if test -n "$UNIQUE_CFLAGS"; then
-        pkg_cv_UNIQUE_CFLAGS="$UNIQUE_CFLAGS"
+    if test -n "$DBUS_CFLAGS"; then
+        pkg_cv_DBUS_CFLAGS="$DBUS_CFLAGS"
     else
         if test -n "$PKG_CONFIG" && \
-    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"unique-1.0\"") >&5
-  ($PKG_CONFIG --exists --print-errors "unique-1.0") 2>&5
+    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"dbus-1\"") >&5
+  ($PKG_CONFIG --exists --print-errors "dbus-1") 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; then
-  pkg_cv_UNIQUE_CFLAGS=`$PKG_CONFIG --cflags "unique-1.0" 2>/dev/null`
+  pkg_cv_DBUS_CFLAGS=`$PKG_CONFIG --cflags "dbus-1" 2>/dev/null`
 else
   pkg_failed=yes
 fi
@@ -5807,16 +5958,16 @@ else
        pkg_failed=untried
 fi
 if test -n "$PKG_CONFIG"; then
-    if test -n "$UNIQUE_LIBS"; then
-        pkg_cv_UNIQUE_LIBS="$UNIQUE_LIBS"
+    if test -n "$DBUS_LIBS"; then
+        pkg_cv_DBUS_LIBS="$DBUS_LIBS"
     else
         if test -n "$PKG_CONFIG" && \
-    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"unique-1.0\"") >&5
-  ($PKG_CONFIG --exists --print-errors "unique-1.0") 2>&5
+    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"dbus-1\"") >&5
+  ($PKG_CONFIG --exists --print-errors "dbus-1") 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; then
-  pkg_cv_UNIQUE_LIBS=`$PKG_CONFIG --libs "unique-1.0" 2>/dev/null`
+  pkg_cv_DBUS_LIBS=`$PKG_CONFIG --libs "dbus-1" 2>/dev/null`
 else
   pkg_failed=yes
 fi
@@ -5835,63 +5986,248 @@ else
         _pkg_short_errors_supported=no
 fi
         if test $_pkg_short_errors_supported = yes; then
-               UNIQUE_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "unique-1.0"`
+               DBUS_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "dbus-1"`
         else
-               UNIQUE_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "unique-1.0"`
+               DBUS_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "dbus-1"`
         fi
        # Put the nasty error message in config.log where it belongs
-       echo "$UNIQUE_PKG_ERRORS" >&5
+       echo "$DBUS_PKG_ERRORS" >&5
 
        { echo "$as_me:$LINENO: result: no" >&5
 echo "${ECHO_T}no" >&6; }
-                have_unique="no"
+                { { echo "$as_me:$LINENO: error: libdbus-1 is required" >&5
+echo "$as_me: error: libdbus-1 is required" >&2;}
+   { (exit 1); exit 1; }; }
 elif test $pkg_failed = untried; then
-       have_unique="no"
+       { { echo "$as_me:$LINENO: error: libdbus-1 is required" >&5
+echo "$as_me: error: libdbus-1 is required" >&2;}
+   { (exit 1); exit 1; }; }
 else
-       UNIQUE_CFLAGS=$pkg_cv_UNIQUE_CFLAGS
-       UNIQUE_LIBS=$pkg_cv_UNIQUE_LIBS
+       DBUS_CFLAGS=$pkg_cv_DBUS_CFLAGS
+       DBUS_LIBS=$pkg_cv_DBUS_LIBS
         { echo "$as_me:$LINENO: result: yes" >&5
 echo "${ECHO_T}yes" >&6; }
-       have_unique="yes"
+       dummy=yes
 fi
-    if test $have_unique == "yes"; then
-        gui_modules="$gui_modules unique-1.0"
-
-cat >>confdefs.h <<\_ACEOF
-#define ENABLE_UNIQUE 1
+    { echo "$as_me:$LINENO: checking for dbus_watch_get_unix_fd in -ldbus-1" >&5
+echo $ECHO_N "checking for dbus_watch_get_unix_fd in -ldbus-1... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dbus_1_dbus_watch_get_unix_fd+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldbus-1  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
 _ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
 
-    fi
-
-pkg_failed=no
-{ echo "$as_me:$LINENO: checking for GUI" >&5
-echo $ECHO_N "checking for GUI... $ECHO_C" >&6; }
-
-if test -n "$PKG_CONFIG"; then
-    if test -n "$GUI_CFLAGS"; then
-        pkg_cv_GUI_CFLAGS="$GUI_CFLAGS"
-    else
-        if test -n "$PKG_CONFIG" && \
-    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"\$gui_modules\"") >&5
-  ($PKG_CONFIG --exists --print-errors "$gui_modules") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; then
-  pkg_cv_GUI_CFLAGS=`$PKG_CONFIG --cflags "$gui_modules" 2>/dev/null`
-else
-  pkg_failed=yes
-fi
-    fi
-else
-       pkg_failed=untried
-fi
-if test -n "$PKG_CONFIG"; then
-    if test -n "$GUI_LIBS"; then
-        pkg_cv_GUI_LIBS="$GUI_LIBS"
-    else
-        if test -n "$PKG_CONFIG" && \
-    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"\$gui_modules\"") >&5
-  ($PKG_CONFIG --exists --print-errors "$gui_modules") 2>&5
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dbus_watch_get_unix_fd ();
+int
+main ()
+{
+return dbus_watch_get_unix_fd ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_dbus_1_dbus_watch_get_unix_fd=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_dbus_1_dbus_watch_get_unix_fd=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dbus_1_dbus_watch_get_unix_fd" >&5
+echo "${ECHO_T}$ac_cv_lib_dbus_1_dbus_watch_get_unix_fd" >&6; }
+if test $ac_cv_lib_dbus_1_dbus_watch_get_unix_fd = yes; then
+  dummy=yes
+else
+
+cat >>confdefs.h <<\_ACEOF
+#define NEED_DBUS_WATCH_GET_UNIX_FD 1
+_ACEOF
+
+fi
+
+    need_glib=yes
+fi
+
+
+
+
+
+
+
+
+DBUS_SERVICES_DIR="${datadir}/dbus-1/services"
+
+
+cat >>confdefs.h <<_ACEOF
+#define DBUS_SERVICES_DIR "$DBUS_SERVICES_DIR"
+_ACEOF
+
+
+# decide which sync-ui(s) we are building:
+# sync-ui (in either GTK or Moblin mode) or both (in separate binaries)
+case $enable_gui in
+     all) GUI_PROGRAMS='sync-ui-gtk${EXEEXT} sync-ui-moblin${EXEEXT}'; GUI_DESKTOP_FILES="sync-gtk.desktop sync-moblin.desktop";;
+     gtk|moblin) GUI_PROGRAMS='sync-ui${EXEEXT}'; GUI_DESKTOP_FILES="sync.desktop";;
+     no) GUI_PROGRAMS=; GUI_DESKTOP_FILES=;;
+     *) { { echo "$as_me:$LINENO: error: Unknown enable_gui type: '$enable_gui'" >&5
+echo "$as_me: error: Unknown enable_gui type: '$enable_gui'" >&2;}
+   { (exit 1); exit 1; }; }
+esac
+
+if test $enable_gui != "no"; then
+    gui_modules="glib-2.0 dbus-glib-1 >= 0.60 gtk+-2.0 libglade-2.0 gio-2.0"
+    if test $enable_gui == "moblin"; then
+
+cat >>confdefs.h <<\_ACEOF
+#define USE_MOBLIN_UX 1
+_ACEOF
+
+    fi
+
+
+pkg_failed=no
+{ echo "$as_me:$LINENO: checking for UNIQUE" >&5
+echo $ECHO_N "checking for UNIQUE... $ECHO_C" >&6; }
+
+if test -n "$PKG_CONFIG"; then
+    if test -n "$UNIQUE_CFLAGS"; then
+        pkg_cv_UNIQUE_CFLAGS="$UNIQUE_CFLAGS"
+    else
+        if test -n "$PKG_CONFIG" && \
+    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"unique-1.0\"") >&5
+  ($PKG_CONFIG --exists --print-errors "unique-1.0") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  pkg_cv_UNIQUE_CFLAGS=`$PKG_CONFIG --cflags "unique-1.0" 2>/dev/null`
+else
+  pkg_failed=yes
+fi
+    fi
+else
+       pkg_failed=untried
+fi
+if test -n "$PKG_CONFIG"; then
+    if test -n "$UNIQUE_LIBS"; then
+        pkg_cv_UNIQUE_LIBS="$UNIQUE_LIBS"
+    else
+        if test -n "$PKG_CONFIG" && \
+    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"unique-1.0\"") >&5
+  ($PKG_CONFIG --exists --print-errors "unique-1.0") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  pkg_cv_UNIQUE_LIBS=`$PKG_CONFIG --libs "unique-1.0" 2>/dev/null`
+else
+  pkg_failed=yes
+fi
+    fi
+else
+       pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+               UNIQUE_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "unique-1.0"`
+        else
+               UNIQUE_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "unique-1.0"`
+        fi
+       # Put the nasty error message in config.log where it belongs
+       echo "$UNIQUE_PKG_ERRORS" >&5
+
+       { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+                have_unique="no"
+elif test $pkg_failed = untried; then
+       have_unique="no"
+else
+       UNIQUE_CFLAGS=$pkg_cv_UNIQUE_CFLAGS
+       UNIQUE_LIBS=$pkg_cv_UNIQUE_LIBS
+        { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+       have_unique="yes"
+fi
+    if test $have_unique == "yes"; then
+        gui_modules="$gui_modules unique-1.0"
+
+cat >>confdefs.h <<\_ACEOF
+#define ENABLE_UNIQUE 1
+_ACEOF
+
+    fi
+
+pkg_failed=no
+{ echo "$as_me:$LINENO: checking for GUI" >&5
+echo $ECHO_N "checking for GUI... $ECHO_C" >&6; }
+
+if test -n "$PKG_CONFIG"; then
+    if test -n "$GUI_CFLAGS"; then
+        pkg_cv_GUI_CFLAGS="$GUI_CFLAGS"
+    else
+        if test -n "$PKG_CONFIG" && \
+    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"\$gui_modules\"") >&5
+  ($PKG_CONFIG --exists --print-errors "$gui_modules") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  pkg_cv_GUI_CFLAGS=`$PKG_CONFIG --cflags "$gui_modules" 2>/dev/null`
+else
+  pkg_failed=yes
+fi
+    fi
+else
+       pkg_failed=untried
+fi
+if test -n "$PKG_CONFIG"; then
+    if test -n "$GUI_LIBS"; then
+        pkg_cv_GUI_LIBS="$GUI_LIBS"
+    else
+        if test -n "$PKG_CONFIG" && \
+    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"\$gui_modules\"") >&5
+  ($PKG_CONFIG --exists --print-errors "$gui_modules") 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; then
@@ -9077,7 +9413,126 @@ elif test "$SYNTHESISSRC" != "none" && test -d $srcdir/src/synthesis; then
          /*) SYNTHESIS_SRC="$srcdir/src/synthesis";;
          *) SYNTHESIS_SRC="$PWD/$srcdir/src/synthesis";;
     esac
+elif test "$enable_shared" = "no"; then
+    # link against engine
+
+pkg_failed=no
+{ echo "$as_me:$LINENO: checking for SYNTHESIS" >&5
+echo $ECHO_N "checking for SYNTHESIS... $ECHO_C" >&6; }
+
+if test -n "$PKG_CONFIG"; then
+    if test -n "$SYNTHESIS_CFLAGS"; then
+        pkg_cv_SYNTHESIS_CFLAGS="$SYNTHESIS_CFLAGS"
+    else
+        if test -n "$PKG_CONFIG" && \
+    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"\"synthesis\"\"") >&5
+  ($PKG_CONFIG --exists --print-errors ""synthesis"") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  pkg_cv_SYNTHESIS_CFLAGS=`$PKG_CONFIG --cflags ""synthesis"" 2>/dev/null`
+else
+  pkg_failed=yes
+fi
+    fi
 else
+       pkg_failed=untried
+fi
+if test -n "$PKG_CONFIG"; then
+    if test -n "$SYNTHESIS_LIBS"; then
+        pkg_cv_SYNTHESIS_LIBS="$SYNTHESIS_LIBS"
+    else
+        if test -n "$PKG_CONFIG" && \
+    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"\"synthesis\"\"") >&5
+  ($PKG_CONFIG --exists --print-errors ""synthesis"") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  pkg_cv_SYNTHESIS_LIBS=`$PKG_CONFIG --libs ""synthesis"" 2>/dev/null`
+else
+  pkg_failed=yes
+fi
+    fi
+else
+       pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+               SYNTHESIS_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors ""synthesis""`
+        else
+               SYNTHESIS_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors ""synthesis""`
+        fi
+       # Put the nasty error message in config.log where it belongs
+       echo "$SYNTHESIS_PKG_ERRORS" >&5
+
+       { { echo "$as_me:$LINENO: error: Package requirements (\"synthesis\") were not met:
+
+$SYNTHESIS_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables SYNTHESIS_CFLAGS
+and SYNTHESIS_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+" >&5
+echo "$as_me: error: Package requirements (\"synthesis\") were not met:
+
+$SYNTHESIS_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables SYNTHESIS_CFLAGS
+and SYNTHESIS_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+" >&2;}
+   { (exit 1); exit 1; }; }
+elif test $pkg_failed = untried; then
+       { { echo "$as_me:$LINENO: error: The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+Alternatively, you may set the environment variables SYNTHESIS_CFLAGS
+and SYNTHESIS_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details." >&5
+echo "$as_me: error: The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+Alternatively, you may set the environment variables SYNTHESIS_CFLAGS
+and SYNTHESIS_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+else
+       SYNTHESIS_CFLAGS=$pkg_cv_SYNTHESIS_CFLAGS
+       SYNTHESIS_LIBS=$pkg_cv_SYNTHESIS_LIBS
+        { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+       :
+fi
+    SYNTHESIS_ENGINE="$SYNTHESIS_LIBS -lsynthesis"
+else
+    # link against SDK alone, except in client-test
+    #PKG_CHECK_MODULES(SYNTHESIS, "synthesis-sdk")
+    #SYNTHESIS_ENGINE="`echo $SYNTHESIS_LIBS | sed -e 's/-lsynthesisstubs/-lsynthesis/'`"
+
+    # can't use the SDK alone because of sysync::SySyncDebugPuts()
 
 pkg_failed=no
 { echo "$as_me:$LINENO: checking for SYNTHESIS" >&5
@@ -9189,6 +9644,7 @@ else
 echo "${ECHO_T}yes" >&6; }
        :
 fi
+    SYNTHESIS_ENGINE="$SYNTHESIS_LIBS"
 fi
 
 if test $SYNTHESIS_SRC != "no-synthesis-source"; then
@@ -9202,10 +9658,28 @@ echo "$as_me: error: --with-synthesis-src=$SYNTHESIS_SRC: no Synthesis configure
     # use local copy of the sources, with dependencies
     # to trigger building the synthesis library
     SYNTHESIS_SUBDIR=$PWD/src/build-synthesis
-    SYNTHESIS_DEP=$PWD/src/build-synthesis/src/libsynthesissdk.la
-
     SYNTHESIS_CFLAGS="-I$SYNTHESIS_SUBDIR/src"
-    SYNTHESIS_LIBS="-L$SYNTHESIS_SUBDIR/src -lsynthesissdk -lsynthesis"
+    SYNTHESIS_LIBS="$SYNTHESIS_SUBDIR/src/libsynthesissdk.la"
+
+    if test "$enable_shared" = "no"; then
+        # link against the engines that were enabled
+        case $SYNCML_ENGINES in both|client|server) SYNTHESIS_LIBS="$SYNTHESIS_LIBS $SYNTHESIS_SUBDIR/src/libsynthesis.la";; esac
+
+cat >>confdefs.h <<\_ACEOF
+#define ENABLE_SYNCML_LINKED 1
+_ACEOF
+
+    else
+        # It would be nice if we could avoid linking against libsynthesis.la here.
+        # This doesn't work at the moment because sysync::SySyncDebugPuts()
+        # is called directly by the libsynthesissdk instead of going through
+        # the normal C function pointer lookup.
+        SYNTHESIS_LIBS="$SYNTHESIS_LIBS $SYNTHESIS_SUBDIR/src/libsynthesis.la"
+    fi
+    SYNTHESIS_DEP=$SYNTHESIS_LIBS
+
+    # for linking client-test
+    SYNTHESIS_ENGINE="$SYNTHESIS_SUBDIR/src/libsynthesis.la"
 
     { echo "$as_me:$LINENO: configuring the Synthesis library " >&5
 echo "$as_me: configuring the Synthesis library " >&6;}
@@ -9224,6 +9698,7 @@ fi
 
 
 
+
 BACKENDS=""
 
 # AC_ARG_ENABLE_BACKEND(BACKEND, DIR, HELP-STRING, [ACTION-IF-GIVEN],
@@ -9525,6 +10000,9 @@ fi
 fi
 
 
+BACKEND_CPPFLAGS="$BACKEND_CPPFLAGS $EPACKAGE_CFLAGS"
+
+
 pkg_failed=no
 { echo "$as_me:$LINENO: checking for ECAL" >&5
 echo $ECHO_N "checking for ECAL... $ECHO_C" >&6; }
@@ -9743,6 +10221,9 @@ fi
 fi
 
 
+BACKEND_CPPFLAGS="$BACKEND_CPPFLAGS $ECAL_CFLAGS"
+
+
 pkg_failed=no
 { echo "$as_me:$LINENO: checking for EBOOK" >&5
 echo $ECHO_N "checking for EBOOK... $ECHO_C" >&6; }
@@ -9961,6 +10442,9 @@ fi
 fi
 
 
+BACKEND_CPPFLAGS="$BACKEND_CPPFLAGS $EBOOK_CFLAGS"
+
+
         # Check whether --enable-ebook was given.
 if test "${enable_ebook+set}" = set; then
   enableval=$enable_ebook; enable_ebook="$enableval"
@@ -10006,9 +10490,6 @@ cat >>confdefs.h <<\_ACEOF
 _ACEOF
 
         enable_evo="yes"
-else
-        EBOOK_CFLAGS=
-        EBOOK_LIBS=
 fi
 
  if test "$enable_ecal" == "yes"; then
@@ -10029,13 +10510,11 @@ cat >>confdefs.h <<\_ACEOF
 _ACEOF
 
         enable_evo="yes"
-else
-        ECAL_CFLAGS=
-        ECAL_LIBS=
 fi
 
+need_glib="yes"
+
 if test "$enable_evo" = "yes"; then
-        need_glib="yes"
         if test "$EDSFOUND" = "yes"; then
 
 cat >>confdefs.h <<\_ACEOF
@@ -10051,8 +10530,6 @@ else
         EPACKAGE_CFLAGS=
         EPACKAGE_LIBS=
 fi
-
-BACKEND_CPPFLAGS="$BACKEND_CPPFLAGS $EPACKAGE_CFLAGS $ECAL_CFLAGS $EBOOK_CFLAGS"
 ac_config_files="$ac_config_files src/backends/evolution/Makefile"
 
 # ^^^^^^^^^^^^^^ src/backends/evolution/configure-sub.in ^^^^^^^^^^^^^^
@@ -10094,112 +10571,6 @@ ac_config_files="$ac_config_files src/backends/file/Makefile"
 
 # ^^^^^^^^^^^^^^ src/backends/file/configure-sub.in ^^^^^^^^^^^^^^
 
-# vvvvvvvvvvvvvv src/backends/maemo/configure-sub.in vvvvvvvvvvvvvv
-
-
-pkg_failed=no
-{ echo "$as_me:$LINENO: checking for MCALB" >&5
-echo $ECHO_N "checking for MCALB... $ECHO_C" >&6; }
-
-if test -n "$PKG_CONFIG"; then
-    if test -n "$MCALB_CFLAGS"; then
-        pkg_cv_MCALB_CFLAGS="$MCALB_CFLAGS"
-    else
-        if test -n "$PKG_CONFIG" && \
-    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"calendar-backend\"") >&5
-  ($PKG_CONFIG --exists --print-errors "calendar-backend") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; then
-  pkg_cv_MCALB_CFLAGS=`$PKG_CONFIG --cflags "calendar-backend" 2>/dev/null`
-else
-  pkg_failed=yes
-fi
-    fi
-else
-       pkg_failed=untried
-fi
-if test -n "$PKG_CONFIG"; then
-    if test -n "$MCALB_LIBS"; then
-        pkg_cv_MCALB_LIBS="$MCALB_LIBS"
-    else
-        if test -n "$PKG_CONFIG" && \
-    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"calendar-backend\"") >&5
-  ($PKG_CONFIG --exists --print-errors "calendar-backend") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; then
-  pkg_cv_MCALB_LIBS=`$PKG_CONFIG --libs "calendar-backend" 2>/dev/null`
-else
-  pkg_failed=yes
-fi
-    fi
-else
-       pkg_failed=untried
-fi
-
-
-
-if test $pkg_failed = yes; then
-
-if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
-        _pkg_short_errors_supported=yes
-else
-        _pkg_short_errors_supported=no
-fi
-        if test $_pkg_short_errors_supported = yes; then
-               MCALB_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "calendar-backend"`
-        else
-               MCALB_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "calendar-backend"`
-        fi
-       # Put the nasty error message in config.log where it belongs
-       echo "$MCALB_PKG_ERRORS" >&5
-
-       { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-                MCALBFOUND=no
-elif test $pkg_failed = untried; then
-       MCALBFOUND=no
-else
-       MCALB_CFLAGS=$pkg_cv_MCALB_CFLAGS
-       MCALB_LIBS=$pkg_cv_MCALB_LIBS
-        { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-       MCALBFOUND=yes
-fi
-
-
-BACKEND_CPPFLAGS="$BACKEND_CPPFLAGS $MCALB_CFLAGS"
-
-
-        # Check whether --enable-maemocal was given.
-if test "${enable_maemocal+set}" = set; then
-  enableval=$enable_maemocal; enable_maemocal="$enableval"
-else
-  enable_maemocal="no"
-fi
-
-        BACKENDS="$BACKENDS maemocal"
-        BACKEND_DEFINES="$BACKEND_DEFINES ENABLE_`echo maemocal | tr a-z A-Z`"
-        for source in maemo; do
-            SYNCSOURCES="$SYNCSOURCES backends/maemo/syncmaemocal.la"
-        done
-
-
-if test "$enable_maemocal" = "yes"; then
-        test "x${MCALBFOUND}" == "xyes" || { { echo "$as_me:$LINENO: error: --enable-maemo-calendar requires pkg-config information for calendar-backend, which was not found" >&5
-echo "$as_me: error: --enable-maemo-calendar requires pkg-config information for calendar-backend, which was not found" >&2;}
-   { (exit 1); exit 1; }; }
-
-cat >>confdefs.h <<\_ACEOF
-#define ENABLE_MAEMO_CALENDAR 1
-_ACEOF
-
-fi
-ac_config_files="$ac_config_files src/backends/maemo/Makefile"
-
-# ^^^^^^^^^^^^^^ src/backends/maemo/configure-sub.in ^^^^^^^^^^^^^^
-
 # vvvvvvvvvvvvvv src/backends/sqlite/configure-sub.in vvvvvvvvvvvvvv
 
 
@@ -10310,68 +10681,104 @@ ac_config_files="$ac_config_files src/backends/sqlite/Makefile"
 
 # ^^^^^^^^^^^^^^ src/backends/sqlite/configure-sub.in ^^^^^^^^^^^^^^
 
-# vvvvvvvvvvvvvv src/backends/xmlrpc/configure-sub.in vvvvvvvvvvvvvv
 
 
 
+enable_any="no"
+backend_is_enabled () {
+    eval echo \${enable_${1}}
+}
+for backend in $BACKENDS; do
+    if test `backend_is_enabled $backend` == "yes"; then
+       enable_any="yes"
+       SYNCEVOLUTION_MODULES="$SYNCEVOLUTION_MODULES src/backends/sync${backend}.la"
+    fi
+done
 
-        # Check whether --enable-xmlrpc was given.
-if test "${enable_xmlrpc+set}" = set; then
-  enableval=$enable_xmlrpc; enable_xmlrpc="$enableval"
-else
-  enable_xmlrpc="no"
-
+if test "$enable_any" = "no"; then
+        { { echo "$as_me:$LINENO: error: no backend enabled - refusing to continue: $anymissing" >&5
+echo "$as_me: error: no backend enabled - refusing to continue: $anymissing" >&2;}
+   { (exit 1); exit 1; }; }
 fi
 
-        BACKENDS="$BACKENDS xmlrpc"
-        BACKEND_DEFINES="$BACKEND_DEFINES ENABLE_`echo xmlrpc | tr a-z A-Z`"
-        for source in xmlrpc; do
-            SYNCSOURCES="$SYNCSOURCES backends/xmlrpc/syncxmlrpc.la"
-        done
-
 
-if test "$enable_xmlrpc" = "yes"; then
-
-        test -e /usr/bin/xmlrpc-c-config || { { echo "$as_me:$LINENO: error: --enable-xmlrpc requires xmlrpc-c-config, which was not found" >&5
-echo "$as_me: error: --enable-xmlrpc requires xmlrpc-c-config, which was not found" >&2;}
-   { (exit 1); exit 1; }; }
-
-        XMLRPC_CFLAGS=`/usr/bin/xmlrpc-c-config c++2 client --cflags`
-        XMLRPC_LIBS=`/usr/bin/xmlrpc-c-config c++2 client --libs`
+pkg_failed=no
+{ echo "$as_me:$LINENO: checking for GLIB" >&5
+echo $ECHO_N "checking for GLIB... $ECHO_C" >&6; }
 
+if test -n "$PKG_CONFIG"; then
+    if test -n "$GLIB_CFLAGS"; then
+        pkg_cv_GLIB_CFLAGS="$GLIB_CFLAGS"
+    else
+        if test -n "$PKG_CONFIG" && \
+    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"\"glib-2.0\"\"") >&5
+  ($PKG_CONFIG --exists --print-errors ""glib-2.0"") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  pkg_cv_GLIB_CFLAGS=`$PKG_CONFIG --cflags ""glib-2.0"" 2>/dev/null`
+else
+  pkg_failed=yes
+fi
+    fi
+else
+       pkg_failed=untried
+fi
+if test -n "$PKG_CONFIG"; then
+    if test -n "$GLIB_LIBS"; then
+        pkg_cv_GLIB_LIBS="$GLIB_LIBS"
+    else
+        if test -n "$PKG_CONFIG" && \
+    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"\"glib-2.0\"\"") >&5
+  ($PKG_CONFIG --exists --print-errors ""glib-2.0"") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  pkg_cv_GLIB_LIBS=`$PKG_CONFIG --libs ""glib-2.0"" 2>/dev/null`
+else
+  pkg_failed=yes
+fi
+    fi
+else
+       pkg_failed=untried
+fi
 
 
-                        BACKEND_CPPFLAGS="$BACKEND_CPPFLAGS $XMLRPC_CFLAGS"
 
+if test $pkg_failed = yes; then
 
-cat >>confdefs.h <<\_ACEOF
-#define ENABLE_XMLRPC 1
-_ACEOF
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+               GLIB_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors ""glib-2.0""`
+        else
+               GLIB_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors ""glib-2.0""`
+        fi
+       # Put the nasty error message in config.log where it belongs
+       echo "$GLIB_PKG_ERRORS" >&5
 
+       { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+                GLIBFOUND=no
+elif test $pkg_failed = untried; then
+       GLIBFOUND=no
+else
+       GLIB_CFLAGS=$pkg_cv_GLIB_CFLAGS
+       GLIB_LIBS=$pkg_cv_GLIB_LIBS
+        { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+       GLIBFOUND=yes
 fi
-ac_config_files="$ac_config_files src/backends/xmlrpc/Makefile"
-
-# ^^^^^^^^^^^^^^ src/backends/xmlrpc/configure-sub.in ^^^^^^^^^^^^^^
-
-
+# This check here is broken on Ubuntu 8.04: it calls glib-config,
+# which isn't found, but the error is not detected by configure.
+#if test "x${GLIBFOUND}" = "xno"; then
+#      PKG_CHECK_MODULES(GLIB, "glib", GLIBFOUND=yes, GLIBFOUND=no)
+#fi
 
 
-enable_any="no"
-backend_is_enabled () {
-    eval echo \${enable_${1}}
-}
-for backend in $BACKENDS; do
-    if test `backend_is_enabled $backend` == "yes"; then
-       enable_any="yes"
-       SYNCEVOLUTION_MODULES="$SYNCEVOLUTION_MODULES src/backends/sync${backend}.la"
-    fi
-done
-
-if test "$enable_any" = "no"; then
-        { { echo "$as_me:$LINENO: error: no backend enabled - refusing to continue: $anymissing" >&5
-echo "$as_me: error: no backend enabled - refusing to continue: $anymissing" >&2;}
-   { (exit 1); exit 1; }; }
-fi
 
 ac_ext=cpp
 ac_cpp='$CXXCPP $CPPFLAGS'
@@ -11490,7 +11897,7 @@ ia64-*-hpux*)
   ;;
 *-*-irix6*)
   # Find out which ABI we are using.
-  echo '#line 11493 "configure"' > conftest.$ac_ext
+  echo '#line 11900 "configure"' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -13595,11 +14002,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:13598: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:14005: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:13602: \$? = $ac_status" >&5
+   echo "$as_me:14009: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -13885,11 +14292,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:13888: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:14295: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:13892: \$? = $ac_status" >&5
+   echo "$as_me:14299: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -13989,11 +14396,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:13992: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:14399: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:13996: \$? = $ac_status" >&5
+   echo "$as_me:14403: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -16366,7 +16773,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 16369 "configure"
+#line 16776 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -16466,7 +16873,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 16469 "configure"
+#line 16876 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -18867,11 +19274,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:18870: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:19277: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:18874: \$? = $ac_status" >&5
+   echo "$as_me:19281: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -18971,11 +19378,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:18974: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:19381: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:18978: \$? = $ac_status" >&5
+   echo "$as_me:19385: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -20569,11 +20976,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:20572: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:20979: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:20576: \$? = $ac_status" >&5
+   echo "$as_me:20983: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -20673,11 +21080,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:20676: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:21083: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:20680: \$? = $ac_status" >&5
+   echo "$as_me:21087: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -22893,11 +23300,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:22896: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:23303: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:22900: \$? = $ac_status" >&5
+   echo "$as_me:23307: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -23183,11 +23590,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:23186: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:23593: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:23190: \$? = $ac_status" >&5
+   echo "$as_me:23597: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -23287,11 +23694,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:23290: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:23697: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:23294: \$? = $ac_status" >&5
+   echo "$as_me:23701: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -26008,244 +26415,18 @@ echo "${ECHO_T}no" >&6; }
 fi
 
 
-if test "$need_glib" = "yes"; then
-        # HAVE_GLIB (aka GLIBFOUND) are a catch-all for these
-        # three GNOME libs. Assume we have all three unless one of
-        # the checks fails.
-        GLIBFOUND=yes
-
-
-pkg_failed=no
-{ echo "$as_me:$LINENO: checking for GLIB" >&5
-echo $ECHO_N "checking for GLIB... $ECHO_C" >&6; }
-
-if test -n "$PKG_CONFIG"; then
-    if test -n "$GLIB_CFLAGS"; then
-        pkg_cv_GLIB_CFLAGS="$GLIB_CFLAGS"
-    else
-        if test -n "$PKG_CONFIG" && \
-    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"\"glib-2.0\"\"") >&5
-  ($PKG_CONFIG --exists --print-errors ""glib-2.0"") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; then
-  pkg_cv_GLIB_CFLAGS=`$PKG_CONFIG --cflags ""glib-2.0"" 2>/dev/null`
-else
-  pkg_failed=yes
-fi
-    fi
-else
-       pkg_failed=untried
-fi
-if test -n "$PKG_CONFIG"; then
-    if test -n "$GLIB_LIBS"; then
-        pkg_cv_GLIB_LIBS="$GLIB_LIBS"
-    else
-        if test -n "$PKG_CONFIG" && \
-    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"\"glib-2.0\"\"") >&5
-  ($PKG_CONFIG --exists --print-errors ""glib-2.0"") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; then
-  pkg_cv_GLIB_LIBS=`$PKG_CONFIG --libs ""glib-2.0"" 2>/dev/null`
-else
-  pkg_failed=yes
-fi
-    fi
-else
-       pkg_failed=untried
-fi
-
-
-
-if test $pkg_failed = yes; then
-
-if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
-        _pkg_short_errors_supported=yes
-else
-        _pkg_short_errors_supported=no
-fi
-        if test $_pkg_short_errors_supported = yes; then
-               GLIB_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors ""glib-2.0""`
-        else
-               GLIB_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors ""glib-2.0""`
-        fi
-       # Put the nasty error message in config.log where it belongs
-       echo "$GLIB_PKG_ERRORS" >&5
-
-       { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-                GLIBFOUND=no
-elif test $pkg_failed = untried; then
-       GLIBFOUND=no
-else
-       GLIB_CFLAGS=$pkg_cv_GLIB_CFLAGS
-       GLIB_LIBS=$pkg_cv_GLIB_LIBS
-        { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-       :
-fi
-        # This check here is broken on Ubuntu 8.04: it calls glib-config,
-        # which isn't found, but the error is not detected by configure.
-        #if test "x${GLIBFOUND}" = "xno"; then
-        #      PKG_CHECK_MODULES(GLIB, "glib", GLIBFOUND=yes, GLIBFOUND=no)
-        #fi
-
-
-pkg_failed=no
-{ echo "$as_me:$LINENO: checking for GTHREAD" >&5
-echo $ECHO_N "checking for GTHREAD... $ECHO_C" >&6; }
-
-if test -n "$PKG_CONFIG"; then
-    if test -n "$GTHREAD_CFLAGS"; then
-        pkg_cv_GTHREAD_CFLAGS="$GTHREAD_CFLAGS"
-    else
-        if test -n "$PKG_CONFIG" && \
-    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"\"gthread-2.0\"\"") >&5
-  ($PKG_CONFIG --exists --print-errors ""gthread-2.0"") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; then
-  pkg_cv_GTHREAD_CFLAGS=`$PKG_CONFIG --cflags ""gthread-2.0"" 2>/dev/null`
-else
-  pkg_failed=yes
-fi
-    fi
-else
-       pkg_failed=untried
-fi
-if test -n "$PKG_CONFIG"; then
-    if test -n "$GTHREAD_LIBS"; then
-        pkg_cv_GTHREAD_LIBS="$GTHREAD_LIBS"
-    else
-        if test -n "$PKG_CONFIG" && \
-    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"\"gthread-2.0\"\"") >&5
-  ($PKG_CONFIG --exists --print-errors ""gthread-2.0"") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; then
-  pkg_cv_GTHREAD_LIBS=`$PKG_CONFIG --libs ""gthread-2.0"" 2>/dev/null`
-else
-  pkg_failed=yes
-fi
-    fi
-else
-       pkg_failed=untried
-fi
-
-
-
-if test $pkg_failed = yes; then
-
-if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
-        _pkg_short_errors_supported=yes
-else
-        _pkg_short_errors_supported=no
-fi
-        if test $_pkg_short_errors_supported = yes; then
-               GTHREAD_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors ""gthread-2.0""`
-        else
-               GTHREAD_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors ""gthread-2.0""`
-        fi
-       # Put the nasty error message in config.log where it belongs
-       echo "$GTHREAD_PKG_ERRORS" >&5
-
-       { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-                GLIBFOUND=no
-elif test $pkg_failed = untried; then
-       GLIBFOUND=no
-else
-       GTHREAD_CFLAGS=$pkg_cv_GTHREAD_CFLAGS
-       GTHREAD_LIBS=$pkg_cv_GTHREAD_LIBS
-        { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-       :
-fi
-
-pkg_failed=no
-{ echo "$as_me:$LINENO: checking for GOBJECT" >&5
-echo $ECHO_N "checking for GOBJECT... $ECHO_C" >&6; }
-
-if test -n "$PKG_CONFIG"; then
-    if test -n "$GOBJECT_CFLAGS"; then
-        pkg_cv_GOBJECT_CFLAGS="$GOBJECT_CFLAGS"
-    else
-        if test -n "$PKG_CONFIG" && \
-    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"\"gobject-2.0\"\"") >&5
-  ($PKG_CONFIG --exists --print-errors ""gobject-2.0"") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; then
-  pkg_cv_GOBJECT_CFLAGS=`$PKG_CONFIG --cflags ""gobject-2.0"" 2>/dev/null`
-else
-  pkg_failed=yes
-fi
-    fi
-else
-       pkg_failed=untried
-fi
-if test -n "$PKG_CONFIG"; then
-    if test -n "$GOBJECT_LIBS"; then
-        pkg_cv_GOBJECT_LIBS="$GOBJECT_LIBS"
-    else
-        if test -n "$PKG_CONFIG" && \
-    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"\"gobject-2.0\"\"") >&5
-  ($PKG_CONFIG --exists --print-errors ""gobject-2.0"") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; then
-  pkg_cv_GOBJECT_LIBS=`$PKG_CONFIG --libs ""gobject-2.0"" 2>/dev/null`
-else
-  pkg_failed=yes
-fi
-    fi
-else
-       pkg_failed=untried
-fi
-
-
-
-if test $pkg_failed = yes; then
-
-if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
-        _pkg_short_errors_supported=yes
-else
-        _pkg_short_errors_supported=no
-fi
-        if test $_pkg_short_errors_supported = yes; then
-               GOBJECT_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors ""gobject-2.0""`
-        else
-               GOBJECT_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors ""gobject-2.0""`
-        fi
-       # Put the nasty error message in config.log where it belongs
-       echo "$GOBJECT_PKG_ERRORS" >&5
-
-       { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-                GLIBFOUND=no
-elif test $pkg_failed = untried; then
-       GLIBFOUND=no
+if test "$need_glib" != "yes"; then
+        GLIB_CFLAGS=
+        GLIB_LIBS=
 else
-       GOBJECT_CFLAGS=$pkg_cv_GOBJECT_CFLAGS
-       GOBJECT_LIBS=$pkg_cv_GOBJECT_LIBS
-        { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-       :
-fi
-
         if  test "x${GLIBFOUND}" = "xyes"; then
 
 cat >>confdefs.h <<\_ACEOF
 #define HAVE_GLIB 1
 _ACEOF
 
-        else
-            { { echo "$as_me:$LINENO: error: not all GNOME libraries found" >&5
-echo "$as_me: error: not all GNOME libraries found" >&2;}
-   { (exit 1); exit 1; }; }
         fi
-        BACKEND_CPPFLAGS="$BACKEND_CPPFLAGS $GLIB_CFLAGS $GTHREAD_CFLAGS $GOBJECT_CFLAGS"
+        BACKEND_CPPFLAGS="$BACKEND_CPPFLAGS $GLIB_CFLAGS"
 fi
 
  if test "$enable_shared" == "yes"; then
@@ -26457,13 +26638,7 @@ cat >>confdefs.h <<\_ACEOF
 _ACEOF
 
 
-# fallback for lack of --with-docdir support in older automake
-if test ! "$docdir"; then
-   docdir = ${datadir}/doc/syncevolution
-
-fi
-
-ac_config_files="$ac_config_files Makefile src/dbus/interfaces/Makefile src/dbus/Makefile src/Makefile src/syncevo/Makefile src/syncevo/syncevolution.pc src/gtk-ui/Makefile po/Makefile.in test/Makefile src/dbus/syncevo-dbus.pc"
+ac_config_files="$ac_config_files Makefile src/dbus/interfaces/Makefile src/gdbus/Makefile src/dbus/Makefile src/Makefile src/syncevo/Makefile src/syncevo/syncevolution.pc src/gtk-ui/Makefile po/Makefile.in test/Makefile src/dbus/syncevo-dbus.pc"
 
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
@@ -26589,6 +26764,20 @@ echo "$as_me: error: conditional \"ENABLE_TESTING\" was never defined.
 Usually this means the macro was only invoked conditionally." >&2;}
    { (exit 1); exit 1; }; }
 fi
+if test -z "${ENABLE_OBEX_TRUE}" && test -z "${ENABLE_OBEX_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"ENABLE_OBEX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"ENABLE_OBEX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${ENABLE_BLUETOOTH_TRUE}" && test -z "${ENABLE_BLUETOOTH_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"ENABLE_BLUETOOTH\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"ENABLE_BLUETOOTH\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
 if test -z "${COND_GUI_TRUE}" && test -z "${COND_GUI_FALSE}"; then
   { { echo "$as_me:$LINENO: error: conditional \"COND_GUI\" was never defined.
 Usually this means the macro was only invoked conditionally." >&5
@@ -26942,7 +27131,7 @@ exec 6>&1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by syncevolution $as_me 0.9.2, which was
+This file was extended by syncevolution $as_me 0.9.2+1.0alpha1, which was
 generated by GNU Autoconf 2.61.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -26995,7 +27184,7 @@ Report bugs to <bug-autoconf@gnu.org>."
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
 ac_cs_version="\\
-syncevolution config.status 0.9.2
+syncevolution config.status 0.9.2+1.0alpha1
 configured by $0, generated by GNU Autoconf 2.61,
   with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
 
     "src/backends/addressbook/Makefile") CONFIG_FILES="$CONFIG_FILES src/backends/addressbook/Makefile" ;;
     "src/backends/evolution/Makefile") CONFIG_FILES="$CONFIG_FILES src/backends/evolution/Makefile" ;;
     "src/backends/file/Makefile") CONFIG_FILES="$CONFIG_FILES src/backends/file/Makefile" ;;
-    "src/backends/maemo/Makefile") CONFIG_FILES="$CONFIG_FILES src/backends/maemo/Makefile" ;;
     "src/backends/sqlite/Makefile") CONFIG_FILES="$CONFIG_FILES src/backends/sqlite/Makefile" ;;
-    "src/backends/xmlrpc/Makefile") CONFIG_FILES="$CONFIG_FILES src/backends/xmlrpc/Makefile" ;;
     "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
     "src/dbus/interfaces/Makefile") CONFIG_FILES="$CONFIG_FILES src/dbus/interfaces/Makefile" ;;
+    "src/gdbus/Makefile") CONFIG_FILES="$CONFIG_FILES src/gdbus/Makefile" ;;
     "src/dbus/Makefile") CONFIG_FILES="$CONFIG_FILES src/dbus/Makefile" ;;
     "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
     "src/syncevo/Makefile") CONFIG_FILES="$CONFIG_FILES src/syncevo/Makefile" ;;
@@ -27278,17 +27466,17 @@ ENABLE_UNIT_TESTS_FALSE!$ENABLE_UNIT_TESTS_FALSE$ac_delim
 ENABLE_TESTING_TRUE!$ENABLE_TESTING_TRUE$ac_delim
 ENABLE_TESTING_FALSE!$ENABLE_TESTING_FALSE$ac_delim
 CORE_LDADD_DEP!$CORE_LDADD_DEP$ac_delim
-CLEAN_CLIENT_SRC!$CLEAN_CLIENT_SRC$ac_delim
 PKG_CONFIG!$PKG_CONFIG$ac_delim
 LIBSOUP_CFLAGS!$LIBSOUP_CFLAGS$ac_delim
 LIBSOUP_LIBS!$LIBSOUP_LIBS$ac_delim
-TRANSPORT_LIBS!$TRANSPORT_LIBS$ac_delim
-TRANSPORT_CFLAGS!$TRANSPORT_CFLAGS$ac_delim
-XSLT!$XSLT$ac_delim
-COND_GUI_TRUE!$COND_GUI_TRUE$ac_delim
-COND_GUI_FALSE!$COND_GUI_FALSE$ac_delim
-COND_DBUS_TRUE!$COND_DBUS_TRUE$ac_delim
-COND_DBUS_FALSE!$COND_DBUS_FALSE$ac_delim
+LIBOPENOBEX_CFLAGS!$LIBOPENOBEX_CFLAGS$ac_delim
+LIBOPENOBEX_LIBS!$LIBOPENOBEX_LIBS$ac_delim
+BLUEZ_CFLAGS!$BLUEZ_CFLAGS$ac_delim
+BLUEZ_LIBS!$BLUEZ_LIBS$ac_delim
+ENABLE_OBEX_TRUE!$ENABLE_OBEX_TRUE$ac_delim
+ENABLE_OBEX_FALSE!$ENABLE_OBEX_FALSE$ac_delim
+ENABLE_BLUETOOTH_TRUE!$ENABLE_BLUETOOTH_TRUE$ac_delim
+ENABLE_BLUETOOTH_FALSE!$ENABLE_BLUETOOTH_FALSE$ac_delim
 _ACEOF
 
   if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then
@@ -27330,6 +27518,13 @@ _ACEOF
 ac_delim='%!_!# '
 for ac_last_try in false false false false false :; do
   cat >conf$$subs.sed <<_ACEOF
+TRANSPORT_LIBS!$TRANSPORT_LIBS$ac_delim
+TRANSPORT_CFLAGS!$TRANSPORT_CFLAGS$ac_delim
+XSLT!$XSLT$ac_delim
+COND_GUI_TRUE!$COND_GUI_TRUE$ac_delim
+COND_GUI_FALSE!$COND_GUI_FALSE$ac_delim
+COND_DBUS_TRUE!$COND_DBUS_TRUE$ac_delim
+COND_DBUS_FALSE!$COND_DBUS_FALSE$ac_delim
 KEYRING_CFLAGS!$KEYRING_CFLAGS$ac_delim
 KEYRING_LIBS!$KEYRING_LIBS$ac_delim
 KEYRING_2_20_CFLAGS!$KEYRING_2_20_CFLAGS$ac_delim
@@ -27338,6 +27533,8 @@ DBUS_GLIB_CFLAGS!$DBUS_GLIB_CFLAGS$ac_delim
 DBUS_GLIB_LIBS!$DBUS_GLIB_LIBS$ac_delim
 DBUS_BINDING_TOOL!$DBUS_BINDING_TOOL$ac_delim
 GLIB_GENMARSHAL!$GLIB_GENMARSHAL$ac_delim
+DBUS_CFLAGS!$DBUS_CFLAGS$ac_delim
+DBUS_LIBS!$DBUS_LIBS$ac_delim
 LIBEXECDIR!$LIBEXECDIR$ac_delim
 DBUS_SERVICES_DIR!$DBUS_SERVICES_DIR$ac_delim
 UNIQUE_CFLAGS!$UNIQUE_CFLAGS$ac_delim
@@ -27404,6 +27601,7 @@ SYNTHESIS_LIBS!$SYNTHESIS_LIBS$ac_delim
 SYNTHESIS!$SYNTHESIS$ac_delim
 SYNTHESIS_SUBDIR!$SYNTHESIS_SUBDIR$ac_delim
 SYNTHESIS_DEP!$SYNTHESIS_DEP$ac_delim
+SYNTHESIS_ENGINE!$SYNTHESIS_ENGINE$ac_delim
 SYNTHESIS_LIB!$SYNTHESIS_LIB$ac_delim
 SYNTHESISSRC!$SYNTHESISSRC$ac_delim
 SYNCSOURCES!$SYNCSOURCES$ac_delim
@@ -27417,16 +27615,6 @@ ECAL_CFLAGS!$ECAL_CFLAGS$ac_delim
 ECAL_LIBS!$ECAL_LIBS$ac_delim
 EBOOK_CFLAGS!$EBOOK_CFLAGS$ac_delim
 EBOOK_LIBS!$EBOOK_LIBS$ac_delim
-ENABLE_ECAL_TRUE!$ENABLE_ECAL_TRUE$ac_delim
-ENABLE_ECAL_FALSE!$ENABLE_ECAL_FALSE$ac_delim
-FILE_CFLAGS!$FILE_CFLAGS$ac_delim
-FILE_LIBS!$FILE_LIBS$ac_delim
-MCALB_CFLAGS!$MCALB_CFLAGS$ac_delim
-MCALB_LIBS!$MCALB_LIBS$ac_delim
-SQLITE_CFLAGS!$SQLITE_CFLAGS$ac_delim
-SQLITE_LIBS!$SQLITE_LIBS$ac_delim
-XMLRPC_CFLAGS!$XMLRPC_CFLAGS$ac_delim
-XMLRPC_LIBS!$XMLRPC_LIBS$ac_delim
 _ACEOF
 
   if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then
@@ -27468,6 +27656,14 @@ _ACEOF
 ac_delim='%!_!# '
 for ac_last_try in false false false false false :; do
   cat >conf$$subs.sed <<_ACEOF
+ENABLE_ECAL_TRUE!$ENABLE_ECAL_TRUE$ac_delim
+ENABLE_ECAL_FALSE!$ENABLE_ECAL_FALSE$ac_delim
+FILE_CFLAGS!$FILE_CFLAGS$ac_delim
+FILE_LIBS!$FILE_LIBS$ac_delim
+SQLITE_CFLAGS!$SQLITE_CFLAGS$ac_delim
+SQLITE_LIBS!$SQLITE_LIBS$ac_delim
+GLIB_CFLAGS!$GLIB_CFLAGS$ac_delim
+GLIB_LIBS!$GLIB_LIBS$ac_delim
 build!$build$ac_delim
 build_cpu!$build_cpu$ac_delim
 build_vendor!$build_vendor$ac_delim
@@ -27488,12 +27684,6 @@ F77!$F77$ac_delim
 FFLAGS!$FFLAGS$ac_delim
 ac_ct_F77!$ac_ct_F77$ac_delim
 LIBTOOL!$LIBTOOL$ac_delim
-GLIB_CFLAGS!$GLIB_CFLAGS$ac_delim
-GLIB_LIBS!$GLIB_LIBS$ac_delim
-GTHREAD_CFLAGS!$GTHREAD_CFLAGS$ac_delim
-GTHREAD_LIBS!$GTHREAD_LIBS$ac_delim
-GOBJECT_CFLAGS!$GOBJECT_CFLAGS$ac_delim
-GOBJECT_LIBS!$GOBJECT_LIBS$ac_delim
 ENABLE_MODULES_TRUE!$ENABLE_MODULES_TRUE$ac_delim
 ENABLE_MODULES_FALSE!$ENABLE_MODULES_FALSE$ac_delim
 SYNCEVOLUTION_LDADD!$SYNCEVOLUTION_LDADD$ac_delim
@@ -27506,7 +27696,7 @@ LIBOBJS!$LIBOBJS$ac_delim
 LTLIBOBJS!$LTLIBOBJS$ac_delim
 _ACEOF
 
-  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 36; then
+  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 38; then
     break
   elif $ac_last_try; then
     { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
index ab3bb5d..5b3f16c 100644 (file)
@@ -19,6 +19,16 @@ if test "$enable_any" = "no"; then
         AC_MSG_ERROR([no backend enabled - refusing to continue: $anymissing])
 fi
 
+dnl check for glib - calling g_type_init() is expected on Maemo
+PKG_CHECK_MODULES(GLIB, "glib-2.0", GLIBFOUND=yes, GLIBFOUND=no)
+# This check here is broken on Ubuntu 8.04: it calls glib-config,
+# which isn't found, but the error is not detected by configure.
+#if test "x${GLIBFOUND}" = "xno"; then
+#      PKG_CHECK_MODULES(GLIB, "glib", GLIBFOUND=yes, GLIBFOUND=no)
+#fi
+AC_SUBST(GLIB_CFLAGS)
+AC_SUBST(GLIB_LIBS)
+
 dnl check for programs.
 AC_PROG_CXX
 AC_PROG_LIBTOOL
@@ -26,29 +36,14 @@ AC_PROG_MAKE_SET
 
 dnl glib initialization is done only if requested by some configure-sub.in,
 dnl for not needed otherwise even if found
-if test "$need_glib" = "yes"; then
-        # HAVE_GLIB (aka GLIBFOUND) are a catch-all for these
-        # three GNOME libs. Assume we have all three unless one of
-        # the checks fails.
-        GLIBFOUND=yes
-
-        dnl check for glib - calling g_type_init() is expected on Maemo
-        PKG_CHECK_MODULES(GLIB, "glib-2.0", , GLIBFOUND=no)
-        # This check here is broken on Ubuntu 8.04: it calls glib-config,
-        # which isn't found, but the error is not detected by configure.
-        #if test "x${GLIBFOUND}" = "xno"; then
-        #      PKG_CHECK_MODULES(GLIB, "glib", GLIBFOUND=yes, GLIBFOUND=no)
-        #fi
-
-        PKG_CHECK_MODULES(GTHREAD, "gthread-2.0", , GLIBFOUND=no)
-        PKG_CHECK_MODULES(GOBJECT, "gobject-2.0", , GLIBFOUND=no)
-
+if test "$need_glib" != "yes"; then
+        GLIB_CFLAGS=
+        GLIB_LIBS=
+else
         if  test "x${GLIBFOUND}" = "xyes"; then
             AC_DEFINE(HAVE_GLIB, 1, [glib found])
-        else
-            AC_ERROR([not all GNOME libraries found])
         fi
-        BACKEND_CPPFLAGS="$BACKEND_CPPFLAGS $GLIB_CFLAGS $GTHREAD_CFLAGS $GOBJECT_CFLAGS"
+        BACKEND_CPPFLAGS="$BACKEND_CPPFLAGS $GLIB_CFLAGS"
 fi
 
 dnl figure out whether we link all code statically or as modules
@@ -98,13 +93,7 @@ AC_CHECK_HEADERS(stdarg.h valgrind/valgrind.h execinfo.h)
 
 AC_DEFINE(SYNTHESIS, 1, "using Synthesis engine")
 
-# fallback for lack of --with-docdir support in older automake
-if test ! "$docdir"; then
-   docdir = ${datadir}/doc/syncevolution
-   AC_SUBST(docdir)
-fi
-
-AC_CONFIG_FILES(Makefile src/dbus/interfaces/Makefile src/dbus/Makefile src/Makefile src/syncevo/Makefile src/syncevo/syncevolution.pc src/gtk-ui/Makefile po/Makefile.in test/Makefile src/dbus/syncevo-dbus.pc)
+AC_CONFIG_FILES(Makefile src/dbus/interfaces/Makefile src/gdbus/Makefile src/dbus/Makefile src/Makefile src/syncevo/Makefile src/syncevo/syncevolution.pc src/gtk-ui/Makefile po/Makefile.in test/Makefile src/dbus/syncevo-dbus.pc)
 AC_OUTPUT
 
 echo
index 0bf81c2..9caa3dc 100644 (file)
@@ -1,7 +1,7 @@
 dnl -*- mode: Autoconf; -*-
 dnl Invoke autogen.sh to produce a configure script.
 
-AC_INIT([syncevolution], [0.9.2])
+AC_INIT([syncevolution], [0.9.2+1.0alpha1])
 AM_INIT_AUTOMAKE([tar-ustar])
 AC_CONFIG_MACRO_DIR([m4])
 define([SYNTHESISSRC_REPO], [])
@@ -12,7 +12,7 @@ AM_CONFIG_HEADER(config.h)
 AC_LIBTOOL_DLOPEN
 
 dnl default device type (see AC_DEFINE below)
-DEVICE_TYPE=desktop
+DEVICE_TYPE=workstation
 
 AC_ARG_WITH(synthesis-src,
             AS_HELP_STRING([--with-synthesis-src=<base directory|svn URL|git URL>],
@@ -32,6 +32,15 @@ AC_ARG_WITH(synthesis-src,
              test "$SYNTHESISSRC" != "yes" || AC_MSG_ERROR([--with-synthesis-src requires a parameter (base directory, svn URL or git URL)])],
             [SYNTHESISSRC="$SYNTHESISSRC_DEF"; REVISION="SYNTHESISSRC_REVISION"])
 
+AC_ARG_WITH(syncml-engines,
+            AS_HELP_STRING([--with-syncml-engines=client|server|both],
+                           [Determines which kind of support for SyncML is compiled and linked into SyncEvolution. Default is both. Currently has no effect.]),
+            [SYNCML_ENGINES="$withval"], SYNCML_ENGINES=both)
+
+case $SYNCML_ENGINES in both|client) AC_DEFINE(ENABLE_SYNCML_CLIENT, 1, [SyncML client support available]);; esac
+case $SYNCML_ENGINES in both|server) AC_DEFINE(ENABLE_SYNCML_SERVER, 1, [SyncML server support available]);; esac
+case $SYNCML_ENGINES in both|server|client) true;; *) AC_ERROR([Invalid value for --with-syncml-engines: $SYNCML_ENGINES]);; esac
+
 AC_ARG_WITH(synthesis-username,
             AS_HELP_STRING([--with-synthesis-username=<svn username>],
                            [username to use when checking out --with-synthesis-src sources from Subversion, default 'guest']),
@@ -101,9 +110,6 @@ AC_SUBST(CPPUNIT_LDFLAGS)
 if test "$enable_unit_tests" = "yes"; then
         AC_DEFINE(ENABLE_UNIT_TESTS, 1, [enable unit tests inside the library's source code])
 fi
-if test "$enable_integration_tests" = "yes"; then
-        AC_DEFINE(ENABLE_INTEGRATION_TESTS, 1, [enable integration tests inside the final library])
-fi
 AM_CONDITIONAL([ENABLE_UNIT_TESTS], [test "$enable_unit_tests" = "yes"])
 AM_CONDITIONAL([ENABLE_TESTING], [test "$enable_unit_tests" = "yes" || test "$enable_integration_tests" = "yes" ])
 
@@ -113,13 +119,6 @@ if test $enable_static_cxx == "yes"; then
 fi
 AC_SUBST(CORE_LDADD_DEP)
 
-# preserve src/synthesis by default,
-# always
-CLEAN_SYNTHESIS_SRC=
-SYNTHESIS_LIB=$PWD/src/build-synthesis/src/libsynthesissdk.la
-
-AC_SUBST(CLEAN_CLIENT_SRC)
-
 # Check for transport layer.
 # Both curl and libsoup can be enabled and disabled explicitly.
 # The default is to use libsoup if available, otherwise curl.
@@ -139,6 +138,22 @@ PKG_CHECK_MODULES(LIBSOUP, libsoup-gnome-2.4,
                   [PKG_CHECK_MODULES(LIBSOUP, libsoup-2.4,
                                      have_libsoup="yes",
                                      have_libsoup="no")])
+
+PKG_CHECK_MODULES(LIBOPENOBEX, openobex, have_obex="yes", have_obex="no")
+if test $have_obex == "yes"; then
+AC_DEFINE(ENABLE_OBEX, 1, [define if openobex library is available])
+    PKG_CHECK_MODULES(BLUEZ, bluez, have_bluez="yes", have_bluez="no")
+    if test $have_bluez == "yes"; then
+    AC_DEFINE(ENABLE_BLUETOOTH, 1, [define if bluez library is available])
+    fi
+fi
+AM_CONDITIONAL([ENABLE_OBEX], [test "$have_obex" = "yes"])
+AM_CONDITIONAL([ENABLE_BLUETOOTH], [test "$have_bluez" = "yes"])
+AC_SUBST(LIBOPENOBEX_CFLAGS)
+AC_SUBST(LIBOPENOBEX_LIBS)
+AC_SUBST(BLUEZ_CFLAGS)
+AC_SUBST(BLUEZ_LIBS)
+
 TRANSPORT=
 TRANSPORT_LIBS=
 TRANSPORT_CFLAGS=
@@ -199,7 +214,8 @@ AC_ARG_ENABLE(libsoup,
 
 if test ! "$TRANSPORT" &&
    test "$libsoup_disabled" != "yes" &&
-   test "$libcurl_disabled" != "yes"; then
+   test "$libcurl_disabled" != "yes" &&
+   test "$have_bluez" != "yes" ; then
    AC_ERROR([no transport library found, configure with --disable-libcurl --disable-libsoup to continue anyway (only useful if users of libsyncevolution provide transport implementation)])
 fi
 
@@ -255,10 +271,6 @@ AC_ARG_ENABLE(gui,
 
 AM_CONDITIONAL([COND_GUI], [test "$enable_gui" != "no"])
 
-if test $enable_gui == "moblin"; then
-    AC_DEFINE(USE_MOBLIN_UX, 1, [Use the MUX widget library])
-fi
-
 AC_ARG_ENABLE(dbus-service,
               AS_HELP_STRING([--enable-dbus-service],
                              [enables building the dbus service executable and the wrapper library for it]),
@@ -290,7 +302,15 @@ if test $enable_dbus_service == "yes"; then
     if test -z "$XSLT"; then
        AC_ERROR([xsltproc not found, is required for D-Bus service])
     fi
+    PKG_CHECK_MODULES(DBUS, dbus-1, dummy=yes,
+                      AC_MSG_ERROR(libdbus-1 is required))
+    AC_CHECK_LIB(dbus-1, dbus_watch_get_unix_fd, dummy=yes,
+                 AC_DEFINE(NEED_DBUS_WATCH_GET_UNIX_FD, 1,
+                 [Define to 1 if you need the dbus_watch_get_unix_fd() function.]))
+    need_glib=yes
 fi
+AC_SUBST(DBUS_CFLAGS)
+AC_SUBST(DBUS_LIBS)
 AC_SUBST(DBUS_GLIB_CFLAGS)
 AC_SUBST(DBUS_GLIB_LIBS)
 AC_SUBST(KEYRING_CFLAGS) 
@@ -311,7 +331,10 @@ case $enable_gui in
 esac
 
 if test $enable_gui != "no"; then
-    gui_modules="glib-2.0 dbus-glib-1 >= 0.60 gtk+-2.0 libglade-2.0 gconf-2.0 gio-2.0 gnome-keyring-1"
+    gui_modules="glib-2.0 dbus-glib-1 >= 0.60 gtk+-2.0 libglade-2.0 gio-2.0"
+    if test $enable_gui == "moblin"; then
+        AC_DEFINE(USE_MOBLIN_UX, 1, [Use Moblin UI widgets])
+    fi
 
     PKG_CHECK_MODULES(UNIQUE, unique-1.0,
                       have_unique="yes",
@@ -408,8 +431,18 @@ elif test "$SYNTHESISSRC" != "none" && test -d $srcdir/src/synthesis; then
          /*) SYNTHESIS_SRC="$srcdir/src/synthesis";;
          *) SYNTHESIS_SRC="$PWD/$srcdir/src/synthesis";;
     esac
+elif test "$enable_shared" = "no"; then
+    # link against engine
+    PKG_CHECK_MODULES(SYNTHESIS, "synthesis")
+    SYNTHESIS_ENGINE="$SYNTHESIS_LIBS -lsynthesis"
 else
+    # link against SDK alone, except in client-test
+    #PKG_CHECK_MODULES(SYNTHESIS, "synthesis-sdk")
+    #SYNTHESIS_ENGINE="`echo $SYNTHESIS_LIBS | sed -e 's/-lsynthesisstubs/-lsynthesis/'`"
+
+    # can't use the SDK alone because of sysync::SySyncDebugPuts()
     PKG_CHECK_MODULES(SYNTHESIS, "synthesis")
+    SYNTHESIS_ENGINE="$SYNTHESIS_LIBS"
 fi
 
 if test $SYNTHESIS_SRC != "no-synthesis-source"; then
@@ -421,10 +454,24 @@ if test $SYNTHESIS_SRC != "no-synthesis-source"; then
     # use local copy of the sources, with dependencies
     # to trigger building the synthesis library
     SYNTHESIS_SUBDIR=$PWD/src/build-synthesis
-    SYNTHESIS_DEP=$PWD/src/build-synthesis/src/libsynthesissdk.la
-
     SYNTHESIS_CFLAGS="-I$SYNTHESIS_SUBDIR/src"
-    SYNTHESIS_LIBS="-L$SYNTHESIS_SUBDIR/src -lsynthesissdk -lsynthesis"
+    SYNTHESIS_LIBS="$SYNTHESIS_SUBDIR/src/libsynthesissdk.la"
+
+    if test "$enable_shared" = "no"; then
+        # link against the engines that were enabled
+        case $SYNCML_ENGINES in both|client|server) SYNTHESIS_LIBS="$SYNTHESIS_LIBS $SYNTHESIS_SUBDIR/src/libsynthesis.la";; esac
+        AC_DEFINE(ENABLE_SYNCML_LINKED, 1, [SyncML engines are linked directly])
+    else
+        # It would be nice if we could avoid linking against libsynthesis.la here.
+        # This doesn't work at the moment because sysync::SySyncDebugPuts()
+        # is called directly by the libsynthesissdk instead of going through
+        # the normal C function pointer lookup.
+        SYNTHESIS_LIBS="$SYNTHESIS_LIBS $SYNTHESIS_SUBDIR/src/libsynthesis.la"
+    fi
+    SYNTHESIS_DEP=$SYNTHESIS_LIBS
+
+    # for linking client-test
+    SYNTHESIS_ENGINE="$SYNTHESIS_SUBDIR/src/libsynthesis.la"
 
     AC_MSG_NOTICE( [configuring the Synthesis library] )
     if (set -x; mkdir -p $SYNTHESIS_SUBDIR && cd $SYNTHESIS_SUBDIR && eval "\$SHELL \"\$SYNTHESIS_CONFIGURE\" $ac_configure_args \"--srcdir=\$SYNTHESIS_SRC\" " ); then true; else
@@ -437,6 +484,7 @@ AC_SUBST(SYNTHESIS_LIBS)
 AC_SUBST(SYNTHESIS)
 AC_SUBST(SYNTHESIS_SUBDIR)
 AC_SUBST(SYNTHESIS_DEP)
+AC_SUBST(SYNTHESIS_ENGINE)
 AC_SUBST(SYNTHESIS_LIB)
 AC_SUBST(SYNTHESISSRC)
 
index 2aae276..a7640ed 100644 (file)
@@ -1,7 +1,7 @@
 dnl -*- mode: Autoconf; -*-
 dnl Invoke autogen.sh to produce a configure script.
 
-AC_INIT([syncevolution], [0.9.2])
+AC_INIT([syncevolution], [0.9.2+1.0alpha1])
 AM_INIT_AUTOMAKE([tar-ustar])
 AC_CONFIG_MACRO_DIR([m4])
 define([SYNTHESISSRC_REPO], [])
@@ -12,7 +12,7 @@ AM_CONFIG_HEADER(config.h)
 AC_LIBTOOL_DLOPEN
 
 dnl default device type (see AC_DEFINE below)
-DEVICE_TYPE=desktop
+DEVICE_TYPE=workstation
 
 AC_ARG_WITH(synthesis-src,
             AS_HELP_STRING([--with-synthesis-src=<base directory|svn URL|git URL>],
@@ -32,6 +32,15 @@ AC_ARG_WITH(synthesis-src,
              test "$SYNTHESISSRC" != "yes" || AC_MSG_ERROR([--with-synthesis-src requires a parameter (base directory, svn URL or git URL)])],
             [SYNTHESISSRC="$SYNTHESISSRC_DEF"; REVISION="SYNTHESISSRC_REVISION"])
 
+AC_ARG_WITH(syncml-engines,
+            AS_HELP_STRING([--with-syncml-engines=client|server|both],
+                           [Determines which kind of support for SyncML is compiled and linked into SyncEvolution. Default is both. Currently has no effect.]),
+            [SYNCML_ENGINES="$withval"], SYNCML_ENGINES=both)
+
+case $SYNCML_ENGINES in both|client) AC_DEFINE(ENABLE_SYNCML_CLIENT, 1, [SyncML client support available]);; esac
+case $SYNCML_ENGINES in both|server) AC_DEFINE(ENABLE_SYNCML_SERVER, 1, [SyncML server support available]);; esac
+case $SYNCML_ENGINES in both|server|client) true;; *) AC_ERROR([Invalid value for --with-syncml-engines: $SYNCML_ENGINES]);; esac
+
 AC_ARG_WITH(synthesis-username,
             AS_HELP_STRING([--with-synthesis-username=<svn username>],
                            [username to use when checking out --with-synthesis-src sources from Subversion, default 'guest']),
@@ -101,9 +110,6 @@ AC_SUBST(CPPUNIT_LDFLAGS)
 if test "$enable_unit_tests" = "yes"; then
         AC_DEFINE(ENABLE_UNIT_TESTS, 1, [enable unit tests inside the library's source code])
 fi
-if test "$enable_integration_tests" = "yes"; then
-        AC_DEFINE(ENABLE_INTEGRATION_TESTS, 1, [enable integration tests inside the final library])
-fi
 AM_CONDITIONAL([ENABLE_UNIT_TESTS], [test "$enable_unit_tests" = "yes"])
 AM_CONDITIONAL([ENABLE_TESTING], [test "$enable_unit_tests" = "yes" || test "$enable_integration_tests" = "yes" ])
 
@@ -113,13 +119,6 @@ if test $enable_static_cxx == "yes"; then
 fi
 AC_SUBST(CORE_LDADD_DEP)
 
-# preserve src/synthesis by default,
-# always
-CLEAN_SYNTHESIS_SRC=
-SYNTHESIS_LIB=$PWD/src/build-synthesis/src/libsynthesissdk.la
-
-AC_SUBST(CLEAN_CLIENT_SRC)
-
 # Check for transport layer.
 # Both curl and libsoup can be enabled and disabled explicitly.
 # The default is to use libsoup if available, otherwise curl.
@@ -139,6 +138,22 @@ PKG_CHECK_MODULES(LIBSOUP, libsoup-gnome-2.4,
                   [PKG_CHECK_MODULES(LIBSOUP, libsoup-2.4,
                                      have_libsoup="yes",
                                      have_libsoup="no")])
+
+PKG_CHECK_MODULES(LIBOPENOBEX, openobex, have_obex="yes", have_obex="no")
+if test $have_obex == "yes"; then
+AC_DEFINE(ENABLE_OBEX, 1, [define if openobex library is available])
+    PKG_CHECK_MODULES(BLUEZ, bluez, have_bluez="yes", have_bluez="no")
+    if test $have_bluez == "yes"; then
+    AC_DEFINE(ENABLE_BLUETOOTH, 1, [define if bluez library is available])
+    fi
+fi
+AM_CONDITIONAL([ENABLE_OBEX], [test "$have_obex" = "yes"])
+AM_CONDITIONAL([ENABLE_BLUETOOTH], [test "$have_bluez" = "yes"])
+AC_SUBST(LIBOPENOBEX_CFLAGS)
+AC_SUBST(LIBOPENOBEX_LIBS)
+AC_SUBST(BLUEZ_CFLAGS)
+AC_SUBST(BLUEZ_LIBS)
+
 TRANSPORT=
 TRANSPORT_LIBS=
 TRANSPORT_CFLAGS=
@@ -199,7 +214,8 @@ AC_ARG_ENABLE(libsoup,
 
 if test ! "$TRANSPORT" &&
    test "$libsoup_disabled" != "yes" &&
-   test "$libcurl_disabled" != "yes"; then
+   test "$libcurl_disabled" != "yes" &&
+   test "$have_bluez" != "yes" ; then
    AC_ERROR([no transport library found, configure with --disable-libcurl --disable-libsoup to continue anyway (only useful if users of libsyncevolution provide transport implementation)])
 fi
 
@@ -255,10 +271,6 @@ AC_ARG_ENABLE(gui,
 
 AM_CONDITIONAL([COND_GUI], [test "$enable_gui" != "no"])
 
-if test $enable_gui == "moblin"; then
-    AC_DEFINE(USE_MOBLIN_UX, 1, [Use the MUX widget library])
-fi
-
 AC_ARG_ENABLE(dbus-service,
               AS_HELP_STRING([--enable-dbus-service],
                              [enables building the dbus service executable and the wrapper library for it]),
@@ -290,7 +302,15 @@ if test $enable_dbus_service == "yes"; then
     if test -z "$XSLT"; then
        AC_ERROR([xsltproc not found, is required for D-Bus service])
     fi
-fi
+    PKG_CHECK_MODULES(DBUS, dbus-1, dummy=yes,
+                      AC_MSG_ERROR(libdbus-1 is required))
+    AC_CHECK_LIB(dbus-1, dbus_watch_get_unix_fd, dummy=yes,
+                 AC_DEFINE(NEED_DBUS_WATCH_GET_UNIX_FD, 1,
+                 [Define to 1 if you need the dbus_watch_get_unix_fd() function.]))
+    need_glib=yes
+fi
+AC_SUBST(DBUS_CFLAGS)
+AC_SUBST(DBUS_LIBS)
 AC_SUBST(DBUS_GLIB_CFLAGS)
 AC_SUBST(DBUS_GLIB_LIBS)
 AC_SUBST(KEYRING_CFLAGS) 
@@ -311,7 +331,10 @@ case $enable_gui in
 esac
 
 if test $enable_gui != "no"; then
-    gui_modules="glib-2.0 dbus-glib-1 >= 0.60 gtk+-2.0 libglade-2.0 gconf-2.0 gio-2.0 gnome-keyring-1"
+    gui_modules="glib-2.0 dbus-glib-1 >= 0.60 gtk+-2.0 libglade-2.0 gio-2.0"
+    if test $enable_gui == "moblin"; then
+        AC_DEFINE(USE_MOBLIN_UX, 1, [Use Moblin UI widgets])
+    fi
 
     PKG_CHECK_MODULES(UNIQUE, unique-1.0,
                       have_unique="yes",
@@ -408,8 +431,18 @@ elif test "$SYNTHESISSRC" != "none" && test -d $srcdir/src/synthesis; then
          /*) SYNTHESIS_SRC="$srcdir/src/synthesis";;
          *) SYNTHESIS_SRC="$PWD/$srcdir/src/synthesis";;
     esac
+elif test "$enable_shared" = "no"; then
+    # link against engine
+    PKG_CHECK_MODULES(SYNTHESIS, "synthesis")
+    SYNTHESIS_ENGINE="$SYNTHESIS_LIBS -lsynthesis"
 else
+    # link against SDK alone, except in client-test
+    #PKG_CHECK_MODULES(SYNTHESIS, "synthesis-sdk")
+    #SYNTHESIS_ENGINE="`echo $SYNTHESIS_LIBS | sed -e 's/-lsynthesisstubs/-lsynthesis/'`"
+
+    # can't use the SDK alone because of sysync::SySyncDebugPuts()
     PKG_CHECK_MODULES(SYNTHESIS, "synthesis")
+    SYNTHESIS_ENGINE="$SYNTHESIS_LIBS"
 fi
 
 if test $SYNTHESIS_SRC != "no-synthesis-source"; then
@@ -421,10 +454,24 @@ if test $SYNTHESIS_SRC != "no-synthesis-source"; then
     # use local copy of the sources, with dependencies
     # to trigger building the synthesis library
     SYNTHESIS_SUBDIR=$PWD/src/build-synthesis
-    SYNTHESIS_DEP=$PWD/src/build-synthesis/src/libsynthesissdk.la
-
     SYNTHESIS_CFLAGS="-I$SYNTHESIS_SUBDIR/src"
-    SYNTHESIS_LIBS="-L$SYNTHESIS_SUBDIR/src -lsynthesissdk -lsynthesis"
+    SYNTHESIS_LIBS="$SYNTHESIS_SUBDIR/src/libsynthesissdk.la"
+
+    if test "$enable_shared" = "no"; then
+        # link against the engines that were enabled
+        case $SYNCML_ENGINES in both|client|server) SYNTHESIS_LIBS="$SYNTHESIS_LIBS $SYNTHESIS_SUBDIR/src/libsynthesis.la";; esac
+        AC_DEFINE(ENABLE_SYNCML_LINKED, 1, [SyncML engines are linked directly])
+    else
+        # It would be nice if we could avoid linking against libsynthesis.la here.
+        # This doesn't work at the moment because sysync::SySyncDebugPuts()
+        # is called directly by the libsynthesissdk instead of going through
+        # the normal C function pointer lookup.
+        SYNTHESIS_LIBS="$SYNTHESIS_LIBS $SYNTHESIS_SUBDIR/src/libsynthesis.la"
+    fi
+    SYNTHESIS_DEP=$SYNTHESIS_LIBS
+
+    # for linking client-test
+    SYNTHESIS_ENGINE="$SYNTHESIS_SUBDIR/src/libsynthesis.la"
 
     AC_MSG_NOTICE( [configuring the Synthesis library] )
     if (set -x; mkdir -p $SYNTHESIS_SUBDIR && cd $SYNTHESIS_SUBDIR && eval "\$SHELL \"\$SYNTHESIS_CONFIGURE\" $ac_configure_args \"--srcdir=\$SYNTHESIS_SRC\" " ); then true; else
@@ -437,6 +484,7 @@ AC_SUBST(SYNTHESIS_LIBS)
 AC_SUBST(SYNTHESIS)
 AC_SUBST(SYNTHESIS_SUBDIR)
 AC_SUBST(SYNTHESIS_DEP)
+AC_SUBST(SYNTHESIS_ENGINE)
 AC_SUBST(SYNTHESIS_LIB)
 AC_SUBST(SYNTHESISSRC)
 
@@ -529,6 +577,9 @@ if test "x${EDSFOUND}" = "xno"; then
               PKG_CHECK_MODULES(EPACKAGE, [$pkg_emodules_10], EDSFOUND=yes, [EDSFOUND=no])
       fi
 fi
+AC_SUBST(EPACKAGE_CFLAGS)
+AC_SUBST(EPACKAGE_LIBS)
+BACKEND_CPPFLAGS="$BACKEND_CPPFLAGS $EPACKAGE_CFLAGS"
 
 dnl check for Evolution calendar packages
 PKG_CHECK_MODULES(ECAL, [$pkg_ecal_12], ECALFOUND=yes, [ECALFOUND=no])
@@ -538,6 +589,9 @@ if test "x${ECALFOUND}" = "xno"; then
                PKG_CHECK_MODULES(ECAL, [$pkg_ecal_10], ECALFOUND=yes, [ECALFOUND=no])
        fi
 fi
+AC_SUBST(ECAL_CFLAGS)
+AC_SUBST(ECAL_LIBS)
+BACKEND_CPPFLAGS="$BACKEND_CPPFLAGS $ECAL_CFLAGS"
 
 dnl check for Evolution contact packages
 PKG_CHECK_MODULES(EBOOK, [$pkg_ebook_12], EBOOKFOUND=yes, [EBOOKFOUND=no])
@@ -547,6 +601,9 @@ if test "x${EBOOKFOUND}" = "xno"; then
                PKG_CHECK_MODULES(EBOOK, [$pkg_ebook_10], EBOOKFOUND=yes, [EBOOKFOUND=no])
        fi
 fi
+AC_SUBST(EBOOK_CFLAGS)
+AC_SUBST(EBOOK_LIBS)
+BACKEND_CPPFLAGS="$BACKEND_CPPFLAGS $EBOOK_CFLAGS"
 
 AC_ARG_ENABLE_BACKEND(ebook, evolution,
                       AS_HELP_STRING([--disable-ebook], [disable access to Evolution addressbooks (must be used to compile without it)]),
@@ -564,9 +621,6 @@ if test "$enable_ebook" = "yes"; then
         test "x${EBOOKFOUND}" == "xyes" || AC_MSG_ERROR([--enable-ebook requires pkg-config information for libebook, which was not found])
         AC_DEFINE(ENABLE_EBOOK, 1, [libebook available])
         enable_evo="yes"
-else
-        EBOOK_CFLAGS=
-        EBOOK_LIBS=
 fi
 
 AM_CONDITIONAL([ENABLE_ECAL], [test "$enable_ecal" == "yes"])
@@ -574,13 +628,11 @@ if test "$enable_ecal" = "yes"; then
         test "x${ECALFOUND}" == "xyes" || AC_MSG_ERROR([--enable-ecal requires pkg-config information for libecal, which was not found"])
         AC_DEFINE(ENABLE_ECAL, 1, [libecal available])
         enable_evo="yes"
-else
-        ECAL_CFLAGS=
-        ECAL_LIBS=
 fi
 
+need_glib="yes"
+
 if test "$enable_evo" = "yes"; then
-        need_glib="yes"
         if test "$EDSFOUND" = "yes"; then
                 AC_DEFINE(HAVE_EDS, 1, [evolution-dataserver available])
         else
@@ -590,8 +642,6 @@ else
         EPACKAGE_CFLAGS=
         EPACKAGE_LIBS=
 fi
-
-BACKEND_CPPFLAGS="$BACKEND_CPPFLAGS $EPACKAGE_CFLAGS $ECAL_CFLAGS $EBOOK_CFLAGS"
 AC_CONFIG_FILES(src/backends/evolution/Makefile)
 # ^^^^^^^^^^^^^^ src/backends/evolution/configure-sub.in ^^^^^^^^^^^^^^
 
@@ -636,28 +686,6 @@ fi
 AC_CONFIG_FILES(src/backends/file/Makefile)
 # ^^^^^^^^^^^^^^ src/backends/file/configure-sub.in ^^^^^^^^^^^^^^
 
-# vvvvvvvvvvvvvv src/backends/maemo/configure-sub.in vvvvvvvvvvvvvv
-dnl -*- mode: Autoconf; -*-
-dnl Invoke autogen.sh to produce a configure script.
-
-dnl Check for calendar-backend
-PKG_CHECK_MODULES(MCALB, calendar-backend, MCALBFOUND=yes, [MCALBFOUND=no])
-AC_SUBST(MCALB_CFLAGS)
-AC_SUBST(MCALB_LIBS)
-BACKEND_CPPFLAGS="$BACKEND_CPPFLAGS $MCALB_CFLAGS"
-
-AC_ARG_ENABLE_BACKEND(maemocal, maemo,
-                      AS_HELP_STRING([--enable-maemo-calendar],
-                                     [enable access to PIM data stored in Maemo 5 calendar application (default off)]),
-                     [enable_maemocal="$enableval"], [enable_maemocal="no"])
-
-if test "$enable_maemocal" = "yes"; then
-        test "x${MCALBFOUND}" == "xyes" || AC_MSG_ERROR([--enable-maemo-calendar requires pkg-config information for calendar-backend, which was not found])
-        AC_DEFINE(ENABLE_MAEMO_CALENDAR, 1, [Maemo 5 calendar available])
-fi
-AC_CONFIG_FILES(src/backends/maemo/Makefile)
-# ^^^^^^^^^^^^^^ src/backends/maemo/configure-sub.in ^^^^^^^^^^^^^^
-
 # vvvvvvvvvvvvvv src/backends/sqlite/configure-sub.in vvvvvvvvvvvvvv
 dnl -*- mode: Autoconf; -*-
 dnl Invoke autogen.sh to produce a configure script.
@@ -683,53 +711,6 @@ fi
 AC_CONFIG_FILES(src/backends/sqlite/Makefile)
 # ^^^^^^^^^^^^^^ src/backends/sqlite/configure-sub.in ^^^^^^^^^^^^^^
 
-# vvvvvvvvvvvvvv src/backends/xmlrpc/configure-sub.in vvvvvvvvvvvvvv
-dnl -*- mode: Autoconf; -*-
-dnl Invoke autogen.sh to produce a configure script.
-
-dnl Checks for required libraries.
-dnl
-dnl This is from the sqlite backend:
-dnl PKG_CHECK_MODULES(SQLITE, sqlite3, SQLITEFOUND=yes, [SQLITEFOUND=no])
-dnl AC_SUBST(SQLITE_CFLAGS)
-dnl AC_SUBST(SQLITE_LIBS)
-
-dnl No pkg-config available for xmlrpc-c
-dnl PKG_CHECK_MODULES(XMLRPC,xmlrpc-c,XMLRPCFOUND=yes, [XMLRPCFOUND=no])
-
-dnl name of backend library (there could be more than one per directory),
-dnl name of the directory,
-dnl help string,
-dnl --enable/disable chosen explicitly
-dnl default, may depend on availability of prerequisites in more complex backends
-AC_ARG_ENABLE_BACKEND(xmlrpc,
-                      xmlrpc,
-                      AS_HELP_STRING([--enable-xmlrpc],
-                                     [enable XMLRPC-based backend which stores items on a central web service (default off)]),
-                                 [enable_xmlrpc="$enableval"],
-                      [enable_xmlrpc="no"]
-                      )
-
-if test "$enable_xmlrpc" = "yes"; then
-        dnl It's good to check the prerequisites here, in case --enable-xmlrpc was used.
-        dnl test "x${SQLITEFOUND}" == "xyes" || AC_MSG_ERROR([--enable-sqlite requires pkg-config information for sqlite3, which was not found])
-        
-        test -e /usr/bin/xmlrpc-c-config || AC_MSG_ERROR([--enable-xmlrpc requires xmlrpc-c-config, which was not found])
-        
-        XMLRPC_CFLAGS=`/usr/bin/xmlrpc-c-config c++2 client --cflags`
-        XMLRPC_LIBS=`/usr/bin/xmlrpc-c-config c++2 client --libs`
-        AC_SUBST(XMLRPC_CFLAGS)
-        AC_SUBST(XMLRPC_LIBS)
-
-        dnl If additional compile flags are necessary to include the header
-        dnl files of the backend, then add them here.
-        BACKEND_CPPFLAGS="$BACKEND_CPPFLAGS $XMLRPC_CFLAGS"
-
-        AC_DEFINE(ENABLE_XMLRPC, 1, [XMLRPC available])
-fi
-AC_CONFIG_FILES(src/backends/xmlrpc/Makefile)
-# ^^^^^^^^^^^^^^ src/backends/xmlrpc/configure-sub.in ^^^^^^^^^^^^^^
-
 dnl -*- mode: Autoconf; -*-
 dnl Invoke autogen.sh to produce a configure script.
 dnl configure-pre.in and src/backends/*/configure-sub.in and configure-post.in come before this part
@@ -751,6 +732,16 @@ if test "$enable_any" = "no"; then
         AC_MSG_ERROR([no backend enabled - refusing to continue: $anymissing])
 fi
 
+dnl check for glib - calling g_type_init() is expected on Maemo
+PKG_CHECK_MODULES(GLIB, "glib-2.0", GLIBFOUND=yes, GLIBFOUND=no)
+# This check here is broken on Ubuntu 8.04: it calls glib-config,
+# which isn't found, but the error is not detected by configure.
+#if test "x${GLIBFOUND}" = "xno"; then
+#      PKG_CHECK_MODULES(GLIB, "glib", GLIBFOUND=yes, GLIBFOUND=no)
+#fi
+AC_SUBST(GLIB_CFLAGS)
+AC_SUBST(GLIB_LIBS)
+
 dnl check for programs.
 AC_PROG_CXX
 AC_PROG_LIBTOOL
@@ -758,29 +749,14 @@ AC_PROG_MAKE_SET
 
 dnl glib initialization is done only if requested by some configure-sub.in,
 dnl for not needed otherwise even if found
-if test "$need_glib" = "yes"; then
-        # HAVE_GLIB (aka GLIBFOUND) are a catch-all for these
-        # three GNOME libs. Assume we have all three unless one of
-        # the checks fails.
-        GLIBFOUND=yes
-
-        dnl check for glib - calling g_type_init() is expected on Maemo
-        PKG_CHECK_MODULES(GLIB, "glib-2.0", , GLIBFOUND=no)
-        # This check here is broken on Ubuntu 8.04: it calls glib-config,
-        # which isn't found, but the error is not detected by configure.
-        #if test "x${GLIBFOUND}" = "xno"; then
-        #      PKG_CHECK_MODULES(GLIB, "glib", GLIBFOUND=yes, GLIBFOUND=no)
-        #fi
-
-        PKG_CHECK_MODULES(GTHREAD, "gthread-2.0", , GLIBFOUND=no)
-        PKG_CHECK_MODULES(GOBJECT, "gobject-2.0", , GLIBFOUND=no)
-
+if test "$need_glib" != "yes"; then
+        GLIB_CFLAGS=
+        GLIB_LIBS=
+else
         if  test "x${GLIBFOUND}" = "xyes"; then
             AC_DEFINE(HAVE_GLIB, 1, [glib found])
-        else
-            AC_ERROR([not all GNOME libraries found])
         fi
-        BACKEND_CPPFLAGS="$BACKEND_CPPFLAGS $GLIB_CFLAGS $GTHREAD_CFLAGS $GOBJECT_CFLAGS"
+        BACKEND_CPPFLAGS="$BACKEND_CPPFLAGS $GLIB_CFLAGS"
 fi
 
 dnl figure out whether we link all code statically or as modules
@@ -830,13 +806,7 @@ AC_CHECK_HEADERS(stdarg.h valgrind/valgrind.h execinfo.h)
 
 AC_DEFINE(SYNTHESIS, 1, "using Synthesis engine")
 
-# fallback for lack of --with-docdir support in older automake
-if test ! "$docdir"; then
-   docdir = ${datadir}/doc/syncevolution
-   AC_SUBST(docdir)
-fi
-
-AC_CONFIG_FILES(Makefile src/dbus/interfaces/Makefile src/dbus/Makefile src/Makefile src/syncevo/Makefile src/syncevo/syncevolution.pc src/gtk-ui/Makefile po/Makefile.in test/Makefile src/dbus/syncevo-dbus.pc)
+AC_CONFIG_FILES(Makefile src/dbus/interfaces/Makefile src/gdbus/Makefile src/dbus/Makefile src/Makefile src/syncevo/Makefile src/syncevo/syncevolution.pc src/gtk-ui/Makefile po/Makefile.in test/Makefile src/dbus/syncevo-dbus.pc)
 AC_OUTPUT
 
 echo
index 5538f3c..6488b1e 100644 (file)
@@ -1,5 +1,4 @@
 ar
-ca
 da
 de
 es
index 7fb6bec..12ae40a 100644 (file)
@@ -1,5 +1,7 @@
 src/gtk-ui/main.c
 src/gtk-ui/sync-ui.c
+src/gtk-ui/sync-ui-config.c
 src/gtk-ui/ui.glade
 src/gtk-ui/sync.desktop.in
 src/gtk-ui/sync-gtk.desktop.in
+src/gtk-ui/sync-config-widget.c
diff --git a/po/ca.po b/po/ca.po
deleted file mode 100644 (file)
index e49b179..0000000
--- a/po/ca.po
+++ /dev/null
@@ -1,557 +0,0 @@
-# Syncevolution Catalan translation.
-# Copyright (C) 2009 Free Software Foundation, Inc.
-# This file is distributed under the same license as the Syncevolution package.
-# Gil Forcada <gilforcada@guifi.net>, 2009.
-#
-#: ../src/gtk-ui/sync-ui.c:765
-msgid ""
-msgstr ""
-"Project-Id-Version: Syncevolution 2.x\n"
-"Report-Msgid-Bugs-To: http://moblin.org/projects/syncevolution\n"
-"POT-Creation-Date: 2009-08-15 09:21+0000\n"
-"PO-Revision-Date: 2010-01-02 14:18+0100\n"
-"Last-Translator: Gil Forcada <gilforcada@guifi.net>\n"
-"Language-Team: Catalan <tradgnome@softcatala.org>\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=2; plural=n != 1;\n"
-
-#. TRANSLATORS: this is the application name that may be used by e.g.
-#. the windowmanager
-#: ../src/gtk-ui/main.c:31 ../src/gtk-ui/ui.glade.h:28
-#: ../src/gtk-ui/sync.desktop.in.h:1
-msgid "Sync"
-msgstr "Sincronització"
-
-#: ../src/gtk-ui/sync-ui.c:259
-msgid "Addressbook"
-msgstr "Llibreta d'adreces"
-
-#: ../src/gtk-ui/sync-ui.c:261
-msgid "Calendar"
-msgstr "Calendari"
-
-#: ../src/gtk-ui/sync-ui.c:263
-msgid "Todo"
-msgstr "Tasques"
-
-#: ../src/gtk-ui/sync-ui.c:265
-msgid "Memo"
-msgstr "Anotacions"
-
-#: ../src/gtk-ui/sync-ui.c:320
-msgid "Failed to save current service in GConf configuration system"
-msgstr ""
-"No s'ha pogut desar el servei actual en el sistema de configuració GConf"
-
-#: ../src/gtk-ui/sync-ui.c:331
-msgid "Failed to save service configuration to SyncEvolution"
-msgstr "No s'ha pogut desar la configuració del servei al SyncEvolution"
-
-#: ../src/gtk-ui/sync-ui.c:416
-msgid "Failed to get service configuration from SyncEvolution"
-msgstr "No s'ha pogut obtenir la configuració del servei del SyncEvolution"
-
-#: ../src/gtk-ui/sync-ui.c:480
-msgid "Failed to remove service configuration from SyncEvolution"
-msgstr "No s'ha pogut suprimir la configuració del servei del SyncEvolution"
-
-#: ../src/gtk-ui/sync-ui.c:600
-msgid "Service must have a name and server URL"
-msgstr "El servei ha de tenir un nom i l'URL de servidor"
-
-#. sync is no longer in progress for some reason
-#: ../src/gtk-ui/sync-ui.c:676
-msgid "Failed to cancel: sync was no longer in progress"
-msgstr "No s'ha pogut cancel·lar: ja no s'estava sincronitzant"
-
-#: ../src/gtk-ui/sync-ui.c:680
-msgid "Failed to cancel sync"
-msgstr "No s'ha pogut cancel·lar la sincronització"
-
-#: ../src/gtk-ui/sync-ui.c:684
-msgid "Canceling sync"
-msgstr "S'està cancel·lant la sincronització"
-
-#: ../src/gtk-ui/sync-ui.c:698
-msgid "Trying to cancel sync"
-msgstr "S'està intentant cancel·lar la sincronització"
-
-#: ../src/gtk-ui/sync-ui.c:705
-#, c-format
-msgid ""
-"Do you want to delete all local data and replace it with data from %s? This "
-"is not usually advised."
-msgstr ""
-"Voleu suprimir totes les dades locals i reemplaçar-les amb les dades de %s? "
-"Normalment no Ã©s recomanable fer-ho."
-
-#: ../src/gtk-ui/sync-ui.c:710
-#, c-format
-msgid ""
-"Do you want to delete all data in %s and replace it with your local data? "
-"This is not usually advised."
-msgstr ""
-"Voleu suprimir totes les dades de %s i reemplaçar-les amb les vostres dades "
-"locals? Normalment no Ã©s recomanable fer-ho."
-
-#: ../src/gtk-ui/sync-ui.c:727
-msgid "No, cancel sync"
-msgstr "No, cancel·la la sincronització"
-
-#: ../src/gtk-ui/sync-ui.c:728
-msgid "Yes, delete and replace"
-msgstr "Sí, suprimeix-ho i reemplaça-ho"
-
-#: ../src/gtk-ui/sync-ui.c:750
-msgid "No sources are enabled, not syncing"
-msgstr "No hi ha cap font habilitada, no se sincronitzarà"
-
-#: ../src/gtk-ui/sync-ui.c:767
-msgid "A sync is already in progress"
-msgstr "Ja s'està sincronitzant"
-
-#: ../src/gtk-ui/sync-ui.c:769
-msgid "Failed to start sync"
-msgstr "No s'ha pogut iniciar la sincronització"
-
-#: ../src/gtk-ui/sync-ui.c:774
-msgid "Starting sync"
-msgstr "S'està iniciant la sincronització"
-
-#: ../src/gtk-ui/sync-ui.c:799
-msgid "Last synced just seconds ago"
-msgstr "Acabeu de sincronitzar"
-
-#: ../src/gtk-ui/sync-ui.c:802
-msgid "Last synced a minute ago"
-msgstr "Fa alguns minuts que s'ha realitzat l'última sincronització"
-
-#: ../src/gtk-ui/sync-ui.c:805
-#, c-format
-msgid "Last synced %ld minutes ago"
-msgstr "Fa %ld minuts que s'ha realitzat l'última sincronització"
-
-#: ../src/gtk-ui/sync-ui.c:808
-msgid "Last synced an hour ago"
-msgstr "Fa una hora que s'ha realitzat l'última sincronització"
-
-#: ../src/gtk-ui/sync-ui.c:811
-#, c-format
-msgid "Last synced %ld hours ago"
-msgstr "Fa %ld hores que s'ha realitzat l'última sincronització"
-
-#: ../src/gtk-ui/sync-ui.c:814
-msgid "Last synced a day ago"
-msgstr "Ahir es va realitzar l'última sincronització"
-
-#: ../src/gtk-ui/sync-ui.c:817
-#, c-format
-msgid "Last synced %ld days ago"
-msgstr "Fa %ld dies que es va realitzar l'última sincronització"
-
-#: ../src/gtk-ui/sync-ui.c:902
-msgid "Sync again"
-msgstr "Sincronitza una altra vegada"
-
-#: ../src/gtk-ui/sync-ui.c:904 ../src/gtk-ui/ui.glade.h:29
-msgid "Sync now"
-msgstr "Sincronitza ara"
-
-#: ../src/gtk-ui/sync-ui.c:913
-msgid "Syncing"
-msgstr "S'està sincronitzant"
-
-#: ../src/gtk-ui/sync-ui.c:919
-msgid "Cancel sync"
-msgstr "Cancel·la la sincronització"
-
-#. TRANSLATORS: placeholder is a source name, shown with checkboxes in main window
-#: ../src/gtk-ui/sync-ui.c:1266
-#, c-format
-msgid "%s (not supported by this service)"
-msgstr "%s (aquest servei no permet fer-ho)"
-
-#: ../src/gtk-ui/sync-ui.c:1299
-#, c-format
-msgid "There was one remote rejection."
-msgid_plural "There were %d remote rejections."
-msgstr[0] "Hi ha hagut un rebuig remot."
-msgstr[1] "Hi ha hagut %d rebuigs remots."
-
-#: ../src/gtk-ui/sync-ui.c:1304
-#, c-format
-msgid "There was one local rejection."
-msgid_plural "There were %d local rejections."
-msgstr[0] "Hi ha hagut un rebuig local."
-msgstr[1] "Hi ha hagut %d rebuigs locals."
-
-#: ../src/gtk-ui/sync-ui.c:1309
-#, c-format
-msgid "There were %d local rejections and %d remote rejections."
-msgstr "Hi han hagut %d rebuigs locals i %d rebuigs remots."
-
-#: ../src/gtk-ui/sync-ui.c:1314
-#, c-format
-msgid "Last time: No changes."
-msgstr "L'última vegada: cap canvi."
-
-#: ../src/gtk-ui/sync-ui.c:1316
-#, c-format
-msgid "Last time: Sent one change."
-msgid_plural "Last time: Sent %d changes."
-msgstr[0] "L'última vegada: es va enviar un canvi."
-msgstr[1] "L'última vegada: es van enviar %d canvis."
-
-#. This is about changes made to the local data. Not all of these
-#. changes were requested by the remote server, so "applied"
-#. is a better word than "received" (bug #5185).
-#: ../src/gtk-ui/sync-ui.c:1324
-#, c-format
-msgid "Last time: Applied one change."
-msgid_plural "Last time: Applied %d changes."
-msgstr[0] "L'última vegada: es va aplicar un canvi."
-msgstr[1] "L'última vegada: es van aplicar %d canvis."
-
-#: ../src/gtk-ui/sync-ui.c:1329
-#, c-format
-msgid "Last time: Applied %d changes and sent %d changes."
-msgstr "L'última vegada: es van aplicar %d canvis i se'n van enviar %d."
-
-#: ../src/gtk-ui/sync-ui.c:1421
-msgid "Failed to get server configuration from SyncEvolution"
-msgstr "No s'ha pogut obtenir la configuració del servidor del SyncEvolution"
-
-#: ../src/gtk-ui/sync-ui.c:1473
-msgid ""
-"ScheduleWorld enables you to keep your contacts, events, tasks, and notes in "
-"sync."
-msgstr ""
-"El ScheduleWorld us permet mantenir sincronitzats els contactes, els "
-"esdeveniments, les tasques i les anotacions."
-
-#: ../src/gtk-ui/sync-ui.c:1476
-msgid ""
-"Google Sync can backup and synchronize your Address Book with your Gmail "
-"contacts."
-msgstr ""
-"El Google Sync pot fer còpies de seguretat i sincronitzar la llibreta "
-"d'adreces amb els contactes del GMail."
-
-#. TRANSLATORS: Please include the word "demo" (or the equivalent in
-#. your language): Funambol is going to be a 90 day demo service
-#. in the future
-#: ../src/gtk-ui/sync-ui.c:1482
-msgid ""
-"Backup your contacts and calendar. Sync with a singleclick, anytime, "
-"anywhere (DEMO)."
-msgstr ""
-"Feu una còpia de seguretat dels vostres contactes i calendaris. "
-"Sincronitzeu-los amb un sol clic, a qualsevol hora a qualsevol lloc "
-"(DEMOSTRACIÓ)."
-
-#: ../src/gtk-ui/sync-ui.c:1510
-msgid "New service"
-msgstr "Servei nou"
-
-#: ../src/gtk-ui/sync-ui.c:1557
-msgid "Server URL"
-msgstr "URL del servidor"
-
-#. TRANSLATORS: placeholder is a source name in settings window
-#: ../src/gtk-ui/sync-ui.c:1579
-#, c-format
-msgid "%s URI"
-msgstr "URI de %s"
-
-#: ../src/gtk-ui/sync-ui.c:1716 ../src/gtk-ui/ui.glade.h:17
-msgid "Launch website"
-msgstr "Obre el lloc web"
-
-#: ../src/gtk-ui/sync-ui.c:1720
-msgid "Setup and use"
-msgstr "Configureu i utilitzeu"
-
-#: ../src/gtk-ui/sync-ui.c:1766
-msgid "Failed to get list of manually setup services from SyncEvolution"
-msgstr ""
-"No s'ha pogut obtenir la llista dels serveis configurats manualment del "
-"SyncEvolution"
-
-#: ../src/gtk-ui/sync-ui.c:1807
-msgid "Failed to get list of supported services from SyncEvolution"
-msgstr "No s'ha pogut obtenir la llista dels serveis admesos pel SyncEvolution"
-
-#. TODO: this is a hack... SyncEnd should be a signal of it's own,
-#. not just hacked on top of the syncevolution error codes
-#: ../src/gtk-ui/sync-ui.c:1968
-msgid "Service configuration not found"
-msgstr "No s'ha trobat la configuració del servei"
-
-#: ../src/gtk-ui/sync-ui.c:1974
-msgid "Not authorized"
-msgstr "No autoritzat"
-
-#: ../src/gtk-ui/sync-ui.c:1976
-msgid "Forbidden"
-msgstr "Prohibit"
-
-#: ../src/gtk-ui/sync-ui.c:1978
-msgid "Not found"
-msgstr "No s'ha trobat"
-
-#: ../src/gtk-ui/sync-ui.c:1980
-msgid "Fatal database error"
-msgstr "Error greu a la base de dades"
-
-#: ../src/gtk-ui/sync-ui.c:1982
-msgid "Database error"
-msgstr "Error en la base de dades"
-
-#: ../src/gtk-ui/sync-ui.c:1984
-msgid "No space left"
-msgstr "No queda espai lliure"
-
-#. TODO identify problem item somehow ?
-#: ../src/gtk-ui/sync-ui.c:1987
-msgid "Failed to process SyncML"
-msgstr "No s'ha pogut processar el SyncML"
-
-#: ../src/gtk-ui/sync-ui.c:1989
-msgid "Server authorization failed"
-msgstr "Ha fallat l'autorització del servidor"
-
-#: ../src/gtk-ui/sync-ui.c:1991
-msgid "Failed to parse configuration file"
-msgstr "No s'ha pogut analitzar el fitxer de configuració"
-
-#: ../src/gtk-ui/sync-ui.c:1993
-msgid "Failed to read configuration file"
-msgstr "No s'ha pogut llegir el fitxer de configuració"
-
-#: ../src/gtk-ui/sync-ui.c:1995
-msgid "No configuration found"
-msgstr "No s'ha trobat la configuració"
-
-#: ../src/gtk-ui/sync-ui.c:1997
-msgid "No configuration file found"
-msgstr "No s'ha trobat el fitxer de configuració"
-
-#: ../src/gtk-ui/sync-ui.c:1999
-msgid "Server sent bad content"
-msgstr "El servidor ha enviat continguts erronis"
-
-#: ../src/gtk-ui/sync-ui.c:2001
-msgid "Transport failure (no connection?)"
-msgstr "Error en la transmissió (no hi ha connexió?)"
-
-#: ../src/gtk-ui/sync-ui.c:2003
-msgid "Connection timed out"
-msgstr "La connexió ha expirat"
-
-#: ../src/gtk-ui/sync-ui.c:2005
-msgid "Connection certificate has expired"
-msgstr "El certificat de la connexió ha expirat"
-
-#: ../src/gtk-ui/sync-ui.c:2007
-msgid "Connection certificate is invalid"
-msgstr "El certificat de la connexió no Ã©s vàlid"
-
-#: ../src/gtk-ui/sync-ui.c:2010
-msgid "Connection failed"
-msgstr "Ha fallat la connexió"
-
-#: ../src/gtk-ui/sync-ui.c:2012
-msgid "URL is bad"
-msgstr "L'URL Ã©s errònia"
-
-#: ../src/gtk-ui/sync-ui.c:2014
-msgid "Server not found"
-msgstr "No s'ha trobat el servidor"
-
-#: ../src/gtk-ui/sync-ui.c:2016
-#, c-format
-msgid "Error %d"
-msgstr "Error %d"
-
-#: ../src/gtk-ui/sync-ui.c:2026
-msgid "Sync D-Bus service exited unexpectedly"
-msgstr "El servei de D-Bus de sincronització s'ha tancat inesperadament"
-
-#: ../src/gtk-ui/sync-ui.c:2029 ../src/gtk-ui/sync-ui.c:2080
-msgid "Sync Failed"
-msgstr "Ha fallat la sincronització"
-
-#: ../src/gtk-ui/sync-ui.c:2072
-msgid "Sync complete"
-msgstr "S'ha completat la sincronització"
-
-#: ../src/gtk-ui/sync-ui.c:2077
-msgid "Sync canceled"
-msgstr "S'ha cancel·lat la sincronització"
-
-#. NOTE extra1 can be error here
-#: ../src/gtk-ui/sync-ui.c:2095
-msgid "Ending sync"
-msgstr "S'està acabat la sincronització"
-
-#. TRANSLATORS: placeholder is a source name (e.g. 'Calendar') in a progress text
-#: ../src/gtk-ui/sync-ui.c:2119
-#, c-format
-msgid "Preparing '%s'"
-msgstr "S'està preparant Â«%s»"
-
-#. TRANSLATORS: placeholder is a source name in a progress text
-#: ../src/gtk-ui/sync-ui.c:2131
-#, c-format
-msgid "Sending '%s'"
-msgstr "S'està enviant Â«%s»"
-
-#. TRANSLATORS: placeholder is a source name in a progress text
-#: ../src/gtk-ui/sync-ui.c:2143
-#, c-format
-msgid "Receiving '%s'"
-msgstr "S'està rebent Â«%s»"
-
-#: ../src/gtk-ui/ui.glade.h:1
-msgid "<b>Data</b>"
-msgstr "<b>Dades</b>"
-
-#: ../src/gtk-ui/ui.glade.h:2
-msgid "<b>No sync service in use</b>"
-msgstr "<b>No s'està utilitzant cap servei de sincronització</b>"
-
-#: ../src/gtk-ui/ui.glade.h:3
-msgid "<b>Sync failure</b>"
-msgstr "<b>S'ha produït un error en la sincronització</b>"
-
-#: ../src/gtk-ui/ui.glade.h:4
-msgid "<b>Type of Sync</b>"
-msgstr "<b>Tipus de sincronització</b>"
-
-#: ../src/gtk-ui/ui.glade.h:5
-msgid "<big>Manual setup</big>"
-msgstr "<big>Configuració manual</big>"
-
-#: ../src/gtk-ui/ui.glade.h:6
-msgid "<big>Supported services</big>"
-msgstr "<big>Serveis coneguts</big>"
-
-#: ../src/gtk-ui/ui.glade.h:7
-msgid "Add new service"
-msgstr "Afegeix un servei nou"
-
-#: ../src/gtk-ui/ui.glade.h:8
-msgid "Back to sync"
-msgstr "Torna a la sincronització"
-
-#: ../src/gtk-ui/ui.glade.h:9
-msgid ""
-"Change sync\n"
-"service"
-msgstr ""
-"Canvia el servei\n"
-"de sincronització"
-
-#: ../src/gtk-ui/ui.glade.h:11
-msgid "Delete all local data and replace it with remote data"
-msgstr "Suprimeix totes les dades locals i reemplaça-les per les remotes"
-
-#: ../src/gtk-ui/ui.glade.h:12
-msgid "Delete all remote data and replace it with local data"
-msgstr "Suprimeix totes les dades remotes i reemplaça-les per les locals"
-
-#: ../src/gtk-ui/ui.glade.h:13
-msgid "Delete this service"
-msgstr "Suprimeix aquest servei"
-
-#: ../src/gtk-ui/ui.glade.h:14
-msgid "Edit service settings"
-msgstr "Edita els paràmetres del servei"
-
-#: ../src/gtk-ui/ui.glade.h:15
-msgid ""
-"If you don't see your service above but know that your sync provider uses "
-"SyncML\n"
-"you can setup a service manually."
-msgstr ""
-"Si no veieu el vostre servei aquí sobre però sabeu que el vostre proveïdor "
-"de sincronització permet utilitzar SyncML\n"
-"podeu configurar un servei manualment."
-
-#: ../src/gtk-ui/ui.glade.h:18
-msgid "Merge local and remote data (recommended)"
-msgstr "Unifica les dades locals i remotes (recomanat)"
-
-#: ../src/gtk-ui/ui.glade.h:19
-msgid "Password"
-msgstr "Contrasenya"
-
-#: ../src/gtk-ui/ui.glade.h:20
-msgid "Reset original server settings"
-msgstr "Reinicia els paràmetres originals del servidor"
-
-#: ../src/gtk-ui/ui.glade.h:21
-msgid "Save and use this service"
-msgstr "Desa i utilitza aquest servei"
-
-#: ../src/gtk-ui/ui.glade.h:22
-msgid "Select sync service"
-msgstr "Seleccioneu el servei de sincronització"
-
-#: ../src/gtk-ui/ui.glade.h:23
-msgid "Server settings"
-msgstr "Paràmetres del servidor"
-
-#: ../src/gtk-ui/ui.glade.h:24
-msgid "Service name"
-msgstr "Nom del servei"
-
-#: ../src/gtk-ui/ui.glade.h:25
-msgid ""
-"Sorry, you need an internet\n"
-"connection to sync."
-msgstr ""
-"Heu d'estar connectat a Internet\n"
-"per a poder fer una sincronització."
-
-#: ../src/gtk-ui/ui.glade.h:27
-msgid "Stop using this service"
-msgstr "No facis servir més aquest servei"
-
-#: ../src/gtk-ui/ui.glade.h:30
-msgid ""
-"Synchronization is not available (D-Bus service does not answer), sorry."
-msgstr ""
-"No està disponible la sincronització (el servei de D-Bus no respon)."
-
-#: ../src/gtk-ui/ui.glade.h:31
-msgid ""
-"To sync you'll need a network connection and an account with a sync "
-"service.\n"
-"We support the following services: "
-msgstr ""
-"Per a poder sincronitzar necessiteu una connexió a Internet i un compte "
-"a un servei de sincronització.\n"
-"Ja hi ha configuracions per als següents serveis:"
-
-#: ../src/gtk-ui/ui.glade.h:33
-msgid "Username"
-msgstr "Nom d'usuari"
-
-#: ../src/gtk-ui/ui.glade.h:34
-msgid ""
-"You haven't selected a sync service yet. Sync services let you \n"
-"synchronize your data between your netbook and a web service."
-msgstr ""
-"Encara no heu seleccionat cap servei de sincronització. Aquests us \n"
-"permeten sincronitzar dades entre el vostre ordinador i serveis webs."
-
-#: ../src/gtk-ui/sync.desktop.in.h:2 ../src/gtk-ui/sync-gtk.desktop.in.h:2
-msgid "Up to date"
-msgstr "Actualitzat"
-
-#: ../src/gtk-ui/sync-gtk.desktop.in.h:1
-msgid "Sync (GTK)"
-msgstr "Sincronització (GTK)"
index 3653aea..5c4704d 100644 (file)
@@ -31,9 +31,8 @@ using namespace std;
 
 CmdlineSyncClient::CmdlineSyncClient(const string &server,
                                      bool doLogging,
-                                     const set<string> &sources,
                                      bool useKeyring):
-    SyncContext(server, doLogging, sources),
+    SyncContext(server, doLogging),
     m_keyring(useKeyring)
 {
 }
index 4f88971..8cd935e 100644 (file)
@@ -34,7 +34,6 @@ class CmdlineSyncClient : public SyncContext {
  public:
     CmdlineSyncClient(const string &server,
                       bool doLogging = false,
-                      const set<string> &sources = set<string>(),
                       bool useKeyring = false);
 
     using SyncConfig::savePassword;
diff --git a/src/DBusSyncClient.cpp b/src/DBusSyncClient.cpp
deleted file mode 100644 (file)
index 168d3da..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2009 Intel Corporation
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) version 3.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301  USA
- */
-
-#include "DBusSyncClient.h"
-#include <syncevo/SyncSource.h>
-
-
-DBusSyncClient::DBusSyncClient(const string &server,
-                               const map<string, int> &source_map,
-                               void (*progress) (const char *source,int type,int extra1,int extra2,int extra3,gpointer data),
-                               void (*server_message) (const char *message,gpointer data),
-                               char* (*need_password) (const char *username, const char *server_url, gpointer data),
-                               gboolean (*check_for_suspend)(gpointer data),
-                               gpointer userdata) : 
-       SyncContext(server, true, getSyncSources (source_map)),
-       m_source_map (source_map),
-       m_userdata (userdata),
-       m_progress (progress),
-       m_server_message (server_message),
-       m_need_password (need_password),
-       m_check_for_suspend (check_for_suspend)
-{
-}
-
-DBusSyncClient::~DBusSyncClient()
-{
-}
-
-void DBusSyncClient::prepare(const std::vector<SyncSource *> &sources)
-{
-       SyncModes modes (SYNC_NONE);
-
-       map<string,int>::const_iterator iter;
-       for (iter = m_source_map.begin (); iter != m_source_map.end (); iter++) {
-               modes.setSyncMode (iter->first, (SyncMode)iter->second);
-       }
-       setSyncModes (sources, modes);
-
-}
-
-bool DBusSyncClient::getPrintChanges() const
-{
-       return false;
-}
-
-string DBusSyncClient::askPassword(const string &passwordName, const string &descr, const ConfigPasswordKey &key)
-{
-       string retval;
-       char *password = NULL;
-       if (!m_need_password)
-               throwError(string("Password query not supported"));
-
-       password = m_need_password (getUsername (), getSyncURL(), m_userdata);
-       if (password)
-               retval = string (password);
-       return retval;
-}
-
-void DBusSyncClient::displayServerMessage(const string &message)
-{
-       m_server_message (message.c_str(), m_userdata);
-}
-
-void DBusSyncClient::displaySyncProgress(sysync::TProgressEventEnum type,
-                                         int32_t extra1, int32_t extra2, int32_t extra3)
-{
-       m_progress (NULL, type, extra1, extra2, extra3, m_userdata);
-       SyncContext::displaySyncProgress(type, extra1, extra2, extra3);
-}
-
-void DBusSyncClient::displaySourceProgress(sysync::TProgressEventEnum type,
-                                           SyncSource &source,
-                                           int32_t extra1, int32_t extra2, int32_t extra3)
-{
-       m_progress (g_strdup (source.getName()), type, extra1, extra2,
-                    // Synthesis engine doesn't count locally
-                    // deleted items during
-                    // refresh-from-server. That's a matter of
-                    // taste. In SyncEvolution we'd like these
-                    // items to show up, so add it here.
-                    (type == sysync::PEV_DSSTATS_L &&
-                     source.getFinalSyncMode() == SYNC_REFRESH_FROM_SERVER) ? 
-                    source.getNumDeleted() :
-                    extra3,
-                    m_userdata);
-       SyncContext::displaySourceProgress(type, source, extra1, extra2, extra3);
-}
-
-bool DBusSyncClient::checkForSuspend()
-{
-       return m_check_for_suspend (m_userdata);
-}
-
-int DBusSyncClient::sleep (int intervals)
-{
-    time_t start = time(NULL);
-    while (true) {
-        g_main_context_iteration(NULL, FALSE);
-        time_t now = time(NULL);
-        if (m_check_for_suspend(m_userdata)) {
-            return  (intervals - now + start);
-        } 
-        if (intervals - now + start <=0) {
-            return intervals - now +start;
-        }
-    }
-}
diff --git a/src/DBusSyncClient.h b/src/DBusSyncClient.h
deleted file mode 100644 (file)
index 9e424e6..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2009 Intel Corporation
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) version 3.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301  USA
- */
-
-/* This is an implementation of SyncContext
- * that is a DBus service. Internally it uses a 
- * SyncevoDBusServer GObject to handle the DBus side
- * of things.
- * */
-
-
-#ifndef INCL_DBUSSYNCCLIENT
-#define INCL_DBUSSYNCCLIENT
-
-#include "config.h"
-
-#include <synthesis/sync_declarations.h>
-#include <syncevo/SyncContext.h>
-
-#include <string>
-#include <set>
-#include <map>
-
-using namespace SyncEvo;
-
-class DBusSyncClient : public SyncContext {
-
-public:
-       DBusSyncClient(const string &server,
-                                  const map<string, int> &source_map,
-                                  void (*progress) (const char *source,int type,int extra1,int extra2,int extra3,gpointer data) = NULL,
-                                  void (*server_message) (const char *message,gpointer data) = NULL,
-                                  char* (*need_password) (const char *username, const char *server_url, gpointer data) = NULL,
-                                  gboolean (*check_for_suspend)(gpointer data) = NULL,
-                                  gpointer userdata = NULL);
-
-       ~DBusSyncClient();
-
-protected:
-       virtual void prepare(const std::vector<SyncSource *> &sources);
-
-       virtual bool getPrintChanges() const;
-
-       virtual string askPassword(const string &passwordName, const string &descr, const ConfigPasswordKey &key);
-
-       virtual void displayServerMessage(const string &message);
-
-       virtual void displaySyncProgress(sysync::TProgressEventEnum type,
-                                        int32_t extra1, int32_t extra2, int32_t extra3);
-
-       virtual void displaySourceProgress(sysync::TProgressEventEnum type,
-                                          SyncSource &source,
-                                          int32_t extra1, int32_t extra2, int32_t extra3);
-
-       virtual bool checkForSuspend();
-
-    virtual int sleep (int intervals);
-
-private:
-       map<string, int> m_source_map;
-       gpointer m_userdata;
-
-       void (*m_progress) (const char *source,int type,int extra1,int extra2,int extra3,gpointer data);
-       void (*m_server_message) (const char *message, gpointer data);
-       char* (*m_need_password) (const char *username, const char *server_url, gpointer data);
-       gboolean (*m_check_for_suspend) (gpointer data);
-
-       static set<string> getSyncSources (const map<string, int> &source_map)
-       {
-               set<string> sources;
-               map<string,int>::const_iterator iter;
-
-               for (iter = source_map.begin (); iter != source_map.end (); iter++)
-                       sources.insert (iter->first);
-
-               return sources;
-       }
-};
-
-#endif
index f969865..15d9e33 100644 (file)
@@ -1,17 +1,17 @@
 BACKENDS = @BACKENDS@
 
-service_in_files = org.Moblin.SyncEvolution.service.in
+service_in_files = org.syncevolution.service.in
 if COND_DBUS
 servicedir = $(DBUS_SERVICES_DIR)
 service_DATA = $(service_in_files:.service.in=.service)
 $(service_DATA): $(service_in_files) Makefile
        @sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
 
-DBUS_DIR = dbus
+DBUS_DIRS = gdbus dbus
 else
 if COND_GUI
 # jump into interface directory directly instead of going through dbus
-DBUS_DIR = dbus/interfaces
+DBUS_DIRS = dbus/interfaces
 endif
 endif
 
@@ -19,11 +19,11 @@ if COND_GUI
 GUI_DIR = gtk-ui
 endif
 
-SUBDIRS = $(SYNTHESIS_SUBDIR) $(DBUS_DIR) syncevo $(BACKENDS) $(GUI_DIR)
-DIST_SUBDIRS = dbus syncevo $(BACKENDS) gtk-ui
+SUBDIRS = $(SYNTHESIS_SUBDIR) $(DBUS_DIRS) syncevo $(BACKENDS) $(GUI_DIR)
+DIST_SUBDIRS = gdbus dbus syncevo $(BACKENDS) gtk-ui
 BUILT_SOURCES =
 
-AM_CPPFLAGS = $(SUBDIRS:%=-I$(srcdir)/%) -I$(srcdir)/../test -I$(top_srcdir) $(BACKEND_CPPFLAGS)
+AM_CPPFLAGS = $(SUBDIRS:%=-I$(srcdir)/%) -I$(srcdir)/../test -I$(top_srcdir) $(BACKEND_CPPFLAGS) $(GLIB_CFLAGS)
 
 EXTRA_PROGRAMS =
 TESTS =
@@ -48,7 +48,7 @@ nobase_dist_template_DATA = $(TEMPLATE_FILES)
 DISTCLEANFILES = synccompare
 MAINTAINERCLEANFILES = Makefile.in
 CLEANFILES = libstdc++.a client-test $(CLIENT_LIB_TEST_FILES) \
-       org.Moblin.SyncEvolution.service
+       org.syncevolution.service
 
 # synccompare is created by replacing its 'import Algorithm::Diff;'
 # with a simplified copy of Diff.pm.
@@ -75,7 +75,7 @@ CORE_SOURCES += $(BACKEND_REGISTRIES)
 endif
 
 CORE_CXXFLAGS = $(SYNTHESIS_CFLAGS)
-CORE_LDADD = $(SYNCEVOLUTION_LDADD) syncevo/libsyncevolution.la $(GLIB_LIBS) $(GTHREAD_LIBS) $(GOBJECT_LIBS) $(LIBS)
+CORE_LDADD = $(SYNCEVOLUTION_LDADD) syncevo/libsyncevolution.la $(GLIB_LIBS) $(LIBS)
 CORE_DEP = $(SYNCEVOLUTION_DEP) syncevo/libsyncevolution.la $(SYNTHESIS_DEP)
 CORE_LD_FLAGS = -uSyncEvolution_Module_Version -Wl,--export-dynamic
 
@@ -88,9 +88,7 @@ syncevolution_SOURCES = \
        CmdlineSyncClient.h \
        CmdlineSyncClient.cpp \
        $(CORE_SOURCES)
-if ENABLE_UNIT_TESTS
 nodist_syncevolution_SOURCES = ../test/test.cpp
-endif
 
 # SYNCEVOLUTION_LDADD will be replaced with libsyncebook.la/libsyncecal.la/libsyncsqlite.la
 # if linking statically against them, empty otherwise;
@@ -143,21 +141,16 @@ distclean-local:
 
 if COND_DBUS
 syncevo_dbus_server_SOURCES = \
-       syncevo-dbus-server.cpp syncevo-dbus-server.h \
-       DBusSyncClient.cpp DBusSyncClient.h \
+       syncevo-dbus-server.cpp \
        $(CORE_SOURCES)
 nodist_syncevo_dbus_server_SOURCES = \
-       dbus/interfaces/syncevo-marshal.c
-if ENABLE_UNIT_TESTS
-nodist_syncevo_dbus_server_SOURCES += \
        ../test/test.cpp
-endif
 
-syncevo_dbus_server_LDADD = $(DBUS_GLIB_LIBS) $(KEYRING_LIBS) $(CORE_LDADD)
-syncevo_dbus_server_CPPFLAGS = -DHAVE_CONFIG_H -Idbus/interfaces $(DBUS_GLIB_CFLAGS) $(KEYRING_CFLAGS) $(AM_CPPFLAGS)
-syncevo_dbus_server_CXXFLAGS = $(SYNCEVOLUTION_CXXFLAGS) $(CORE_CXXFLAGS)
-syncevo_dbus_server_LDFLAGS = $(CORE_LD_FLAGS)
-syncevo_dbus_server_DEPENDENCIES = $(EXTRA_LTLIBRARIES) $(CORE_DEP) $(SYNTHESIS_DEP)
+syncevo_dbus_server_LDADD = gdbus/libgdbus.la $(CORE_LDADD)
+syncevo_dbus_server_CPPFLAGS = -DHAVE_CONFIG_H -I$(srcdir)/gdbus $(AM_CPPFLAGS)
+syncevo_dbus_server_CXXFLAGS = $(SYNCEVOLUTION_CXXFLAGS) $(CORE_CXXFLAGS) $(GLIB_CFLAGS) $(DBUS_CFLAGS) $(LIBSOUP_CFLAGS)
+syncevo_dbus_server_LDFLAGS = $(CORE_LD_FLAGS) $(LIBSOUP_LIBS)
+syncevo_dbus_server_DEPENDENCIES = gdbus/libgdbus.la $(EXTRA_LTLIBRARIES) $(CORE_DEP) $(SYNTHESIS_DEP)
 endif
 
 # With --disable-shared autotools links against libfunambol.a which does not
@@ -172,6 +165,17 @@ client_test_SOURCES = \
        $(CORE_SOURCES)
 nodist_client_test_SOURCES = ../test/test.cpp
 
+# Always compile the registry files into client-test because that is
+# the only place where they are compiled with
+# ENABLE_INTEGRATION_TESTS.  This works without undefined references
+# because client-test is linked against all shared backend libraries
+# (non-portable, but works).
+# Disabled now, the client test can also be dynamically loaded and registered
+# just the same as syncevolution
+# if ENABLE_MODULES
+# client_test_SOURCES += $(BACKEND_REGISTRIES)
+# endif
+
 # list of test file base files
 #
 # Generated files (testcases/ical20.ics.funambol.tem) are derived from
@@ -244,8 +248,16 @@ $(filter-out %.tem, $(filter testcases/%, $(subst $(srcdir)/../test/,,$(CLIENT_L
 # The binary does not really depend on the test cases, only running it does.
 # Listing the dependencies here is done to ensure that one doesn't accidentally
 # runs the binary with out-dated auxiliary files.
-client_test_DEPENDENCIES = $(EXTRA_LTLIBRARIES) $(CORE_DEP) $(CLIENT_LIB_TEST_FILES) testcase2patch synccompare
-
+client_test_DEPENDENCIES = $(EXTRA_LTLIBRARIES) $(CORE_DEP) $(CLIENT_LIB_TEST_FILES) testcase2patch synccompare templates
+
+# copy template directory into current working directory, if not there
+# yet
+.PHONY: templates
+templates:
+       if test "$(srcdir)/templates" != "./templates"; then \
+               rm -rf ./templates; \
+               cp -r "$(srcdir)/templates" .; \
+       fi
 
 # distribute test system?
 if ENABLE_TESTING
index 5a34be0..15cd7e5 100644 (file)
@@ -1,17 +1,17 @@
-BACKENDS =  backends/addressbook backends/evolution backends/file backends/maemo backends/sqlite backends/xmlrpc
+BACKENDS =  backends/addressbook backends/evolution backends/file backends/sqlite
 
-service_in_files = org.Moblin.SyncEvolution.service.in
+service_in_files = org.syncevolution.service.in
 if COND_DBUS
 servicedir = $(DBUS_SERVICES_DIR)
 service_DATA = $(service_in_files:.service.in=.service)
 $(service_DATA): $(service_in_files) Makefile
        @sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
 
-DBUS_DIR = dbus
+DBUS_DIRS = gdbus dbus
 else
 if COND_GUI
 # jump into interface directory directly instead of going through dbus
-DBUS_DIR = dbus/interfaces
+DBUS_DIRS = dbus/interfaces
 endif
 endif
 
@@ -19,11 +19,11 @@ if COND_GUI
 GUI_DIR = gtk-ui
 endif
 
-SUBDIRS = $(SYNTHESIS_SUBDIR) $(DBUS_DIR) syncevo $(BACKENDS) $(GUI_DIR)
-DIST_SUBDIRS = dbus syncevo $(BACKENDS) gtk-ui
+SUBDIRS = $(SYNTHESIS_SUBDIR) $(DBUS_DIRS) syncevo $(BACKENDS) $(GUI_DIR)
+DIST_SUBDIRS = gdbus dbus syncevo $(BACKENDS) gtk-ui
 BUILT_SOURCES =
 
-AM_CPPFLAGS = $(SUBDIRS:%=-I$(srcdir)/%) -I$(srcdir)/../test -I$(top_srcdir) $(BACKEND_CPPFLAGS)
+AM_CPPFLAGS = $(SUBDIRS:%=-I$(srcdir)/%) -I$(srcdir)/../test -I$(top_srcdir) $(BACKEND_CPPFLAGS) $(GLIB_CFLAGS)
 
 EXTRA_PROGRAMS =
 TESTS =
@@ -48,7 +48,7 @@ nobase_dist_template_DATA = $(TEMPLATE_FILES)
 DISTCLEANFILES = synccompare
 MAINTAINERCLEANFILES = Makefile.in
 CLEANFILES = libstdc++.a client-test $(CLIENT_LIB_TEST_FILES) \
-       org.Moblin.SyncEvolution.service
+       org.syncevolution.service
 
 # synccompare is created by replacing its 'import Algorithm::Diff;'
 # with a simplified copy of Diff.pm.
@@ -67,7 +67,7 @@ CORE_SOURCES =
 # When using modules the registration is done inside the
 # module and the register file is unnecessary. However, they
 # still need to be included in "make dist".
-BACKEND_REGISTRIES = backends/addressbook/AddressBookSourceRegister.cpp backends/evolution/EvolutionCalendarSourceRegister.cpp backends/evolution/EvolutionContactSourceRegister.cpp backends/file/FileSyncSourceRegister.cpp backends/maemo/MaemoCalendarSourceRegister.cpp backends/sqlite/SQLiteContactSourceRegister.cpp backends/xmlrpc/XMLRPCSyncSourceRegister.cpp
+BACKEND_REGISTRIES = backends/addressbook/AddressBookSourceRegister.cpp backends/evolution/EvolutionCalendarSourceRegister.cpp backends/evolution/EvolutionContactSourceRegister.cpp backends/file/FileSyncSourceRegister.cpp backends/sqlite/SQLiteContactSourceRegister.cpp
 if ENABLE_MODULES
 EXTRA_DIST += $(BACKEND_REGISTRIES)
 else
@@ -75,7 +75,7 @@ CORE_SOURCES += $(BACKEND_REGISTRIES)
 endif
 
 CORE_CXXFLAGS = $(SYNTHESIS_CFLAGS)
-CORE_LDADD = $(SYNCEVOLUTION_LDADD) syncevo/libsyncevolution.la $(GLIB_LIBS) $(GTHREAD_LIBS) $(GOBJECT_LIBS) $(LIBS)
+CORE_LDADD = $(SYNCEVOLUTION_LDADD) syncevo/libsyncevolution.la $(GLIB_LIBS) $(LIBS)
 CORE_DEP = $(SYNCEVOLUTION_DEP) syncevo/libsyncevolution.la $(SYNTHESIS_DEP)
 CORE_LD_FLAGS = -uSyncEvolution_Module_Version -Wl,--export-dynamic
 
@@ -88,9 +88,7 @@ syncevolution_SOURCES = \
        CmdlineSyncClient.h \
        CmdlineSyncClient.cpp \
        $(CORE_SOURCES)
-if ENABLE_UNIT_TESTS
 nodist_syncevolution_SOURCES = ../test/test.cpp
-endif
 
 # SYNCEVOLUTION_LDADD will be replaced with libsyncebook.la/libsyncecal.la/libsyncsqlite.la
 # if linking statically against them, empty otherwise;
@@ -143,21 +141,16 @@ distclean-local:
 
 if COND_DBUS
 syncevo_dbus_server_SOURCES = \
-       syncevo-dbus-server.cpp syncevo-dbus-server.h \
-       DBusSyncClient.cpp DBusSyncClient.h \
+       syncevo-dbus-server.cpp \
        $(CORE_SOURCES)
 nodist_syncevo_dbus_server_SOURCES = \
-       dbus/interfaces/syncevo-marshal.c
-if ENABLE_UNIT_TESTS
-nodist_syncevo_dbus_server_SOURCES += \
        ../test/test.cpp
-endif
 
-syncevo_dbus_server_LDADD = $(DBUS_GLIB_LIBS) $(KEYRING_LIBS) $(CORE_LDADD)
-syncevo_dbus_server_CPPFLAGS = -DHAVE_CONFIG_H -Idbus/interfaces $(DBUS_GLIB_CFLAGS) $(KEYRING_CFLAGS) $(AM_CPPFLAGS)
-syncevo_dbus_server_CXXFLAGS = $(SYNCEVOLUTION_CXXFLAGS) $(CORE_CXXFLAGS)
-syncevo_dbus_server_LDFLAGS = $(CORE_LD_FLAGS)
-syncevo_dbus_server_DEPENDENCIES = $(EXTRA_LTLIBRARIES) $(CORE_DEP) $(SYNTHESIS_DEP)
+syncevo_dbus_server_LDADD = gdbus/libgdbus.la $(CORE_LDADD)
+syncevo_dbus_server_CPPFLAGS = -DHAVE_CONFIG_H -I$(srcdir)/gdbus $(AM_CPPFLAGS)
+syncevo_dbus_server_CXXFLAGS = $(SYNCEVOLUTION_CXXFLAGS) $(CORE_CXXFLAGS) $(GLIB_CFLAGS) $(DBUS_CFLAGS) $(LIBSOUP_CFLAGS)
+syncevo_dbus_server_LDFLAGS = $(CORE_LD_FLAGS) $(LIBSOUP_LIBS)
+syncevo_dbus_server_DEPENDENCIES = gdbus/libgdbus.la $(EXTRA_LTLIBRARIES) $(CORE_DEP) $(SYNTHESIS_DEP)
 endif
 
 # With --disable-shared autotools links against libfunambol.a which does not
@@ -172,6 +165,17 @@ client_test_SOURCES = \
        $(CORE_SOURCES)
 nodist_client_test_SOURCES = ../test/test.cpp
 
+# Always compile the registry files into client-test because that is
+# the only place where they are compiled with
+# ENABLE_INTEGRATION_TESTS.  This works without undefined references
+# because client-test is linked against all shared backend libraries
+# (non-portable, but works).
+# Disabled now, the client test can also be dynamically loaded and registered
+# just the same as syncevolution
+# if ENABLE_MODULES
+# client_test_SOURCES += $(BACKEND_REGISTRIES)
+# endif
+
 # list of test file base files
 #
 # Generated files (testcases/ical20.ics.funambol.tem) are derived from
@@ -244,8 +248,16 @@ $(filter-out %.tem, $(filter testcases/%, $(subst $(srcdir)/../test/,,$(CLIENT_L
 # The binary does not really depend on the test cases, only running it does.
 # Listing the dependencies here is done to ensure that one doesn't accidentally
 # runs the binary with out-dated auxiliary files.
-client_test_DEPENDENCIES = $(EXTRA_LTLIBRARIES) $(CORE_DEP) $(CLIENT_LIB_TEST_FILES) testcase2patch synccompare
-
+client_test_DEPENDENCIES = $(EXTRA_LTLIBRARIES) $(CORE_DEP) $(CLIENT_LIB_TEST_FILES) testcase2patch synccompare templates
+
+# copy template directory into current working directory, if not there
+# yet
+.PHONY: templates
+templates:
+       if test "$(srcdir)/templates" != "./templates"; then \
+               rm -rf ./templates; \
+               cp -r "$(srcdir)/templates" .; \
+       fi
 
 # distribute test system?
 if ENABLE_TESTING
index 3ca087b..884e7d5 100644 (file)
@@ -42,20 +42,17 @@ bin_PROGRAMS = syncevolution$(EXEEXT) $(am__EXEEXT_2)
 @ENABLE_MODULES_FALSE@am__append_2 = $(SYNCSOURCES)
 @ENABLE_MODULES_TRUE@am__append_3 = $(BACKEND_REGISTRIES)
 @ENABLE_MODULES_FALSE@am__append_4 = $(BACKEND_REGISTRIES)
-@COND_DBUS_TRUE@@ENABLE_UNIT_TESTS_TRUE@am__append_5 = \
-@COND_DBUS_TRUE@@ENABLE_UNIT_TESTS_TRUE@       ../test/test.cpp
-
 
 # distribute test system?
 # yes: install client-test in bindir, test files in datadir
+@ENABLE_TESTING_TRUE@am__append_5 = client-test
 @ENABLE_TESTING_TRUE@am__append_6 = client-test
-@ENABLE_TESTING_TRUE@am__append_7 = client-test
 # The "all" dependency causes a rebuild even if the actual input files
 # haven't changed. If client-test is part of the regular targets built
 # by "all", then it must not depend on all!
-@ENABLE_TESTING_FALSE@am__append_8 = client-test
-@ENABLE_TESTING_FALSE@am__append_9 = $(CLIENT_LIB_TEST_FILES)
-@ENABLE_TESTING_FALSE@am__append_10 = all
+@ENABLE_TESTING_FALSE@am__append_7 = client-test
+@ENABLE_TESTING_FALSE@am__append_8 = $(CLIENT_LIB_TEST_FILES)
+@ENABLE_TESTING_FALSE@am__append_9 = all
 subdir = src
 DIST_COMMON = $(am__nobase_dist_doc_DATA_DIST) \
        $(nobase_dist_template_DATA) $(srcdir)/Makefile.am \
@@ -82,7 +79,6 @@ am__DEPENDENCIES_1 =
 @ENABLE_MODULES_FALSE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
 am__DEPENDENCIES_3 = $(am__DEPENDENCIES_2)
 am__DEPENDENCIES_4 = $(am__DEPENDENCIES_3) syncevo/libsyncevolution.la \
-       $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
        $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
 abort_redirect_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
        $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
@@ -95,16 +91,12 @@ am__client_test_SOURCES_DIST = client-test-app.cpp \
        backends/evolution/EvolutionCalendarSourceRegister.cpp \
        backends/evolution/EvolutionContactSourceRegister.cpp \
        backends/file/FileSyncSourceRegister.cpp \
-       backends/maemo/MaemoCalendarSourceRegister.cpp \
-       backends/sqlite/SQLiteContactSourceRegister.cpp \
-       backends/xmlrpc/XMLRPCSyncSourceRegister.cpp
+       backends/sqlite/SQLiteContactSourceRegister.cpp
 am__objects_1 = client_test-AddressBookSourceRegister.$(OBJEXT) \
        client_test-EvolutionCalendarSourceRegister.$(OBJEXT) \
        client_test-EvolutionContactSourceRegister.$(OBJEXT) \
        client_test-FileSyncSourceRegister.$(OBJEXT) \
-       client_test-MaemoCalendarSourceRegister.$(OBJEXT) \
-       client_test-SQLiteContactSourceRegister.$(OBJEXT) \
-       client_test-XMLRPCSyncSourceRegister.$(OBJEXT)
+       client_test-SQLiteContactSourceRegister.$(OBJEXT)
 @ENABLE_MODULES_FALSE@am__objects_2 = $(am__objects_1)
 am__objects_3 = $(am__objects_2)
 am_client_test_OBJECTS = client_test-client-test-app.$(OBJEXT) \
@@ -121,31 +113,23 @@ client_test_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
        $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(client_test_CXXFLAGS) \
        $(CXXFLAGS) $(client_test_LDFLAGS) $(LDFLAGS) -o $@
 am__syncevo_dbus_server_SOURCES_DIST = syncevo-dbus-server.cpp \
-       syncevo-dbus-server.h DBusSyncClient.cpp DBusSyncClient.h \
        backends/addressbook/AddressBookSourceRegister.cpp \
        backends/evolution/EvolutionCalendarSourceRegister.cpp \
        backends/evolution/EvolutionContactSourceRegister.cpp \
        backends/file/FileSyncSourceRegister.cpp \
-       backends/maemo/MaemoCalendarSourceRegister.cpp \
-       backends/sqlite/SQLiteContactSourceRegister.cpp \
-       backends/xmlrpc/XMLRPCSyncSourceRegister.cpp
+       backends/sqlite/SQLiteContactSourceRegister.cpp
 am__objects_7 =  \
        syncevo_dbus_server-AddressBookSourceRegister.$(OBJEXT) \
        syncevo_dbus_server-EvolutionCalendarSourceRegister.$(OBJEXT) \
        syncevo_dbus_server-EvolutionContactSourceRegister.$(OBJEXT) \
        syncevo_dbus_server-FileSyncSourceRegister.$(OBJEXT) \
-       syncevo_dbus_server-MaemoCalendarSourceRegister.$(OBJEXT) \
-       syncevo_dbus_server-SQLiteContactSourceRegister.$(OBJEXT) \
-       syncevo_dbus_server-XMLRPCSyncSourceRegister.$(OBJEXT)
+       syncevo_dbus_server-SQLiteContactSourceRegister.$(OBJEXT)
 @ENABLE_MODULES_FALSE@am__objects_8 = $(am__objects_7)
 am__objects_9 = $(am__objects_8)
 @COND_DBUS_TRUE@am_syncevo_dbus_server_OBJECTS = syncevo_dbus_server-syncevo-dbus-server.$(OBJEXT) \
-@COND_DBUS_TRUE@       syncevo_dbus_server-DBusSyncClient.$(OBJEXT) \
 @COND_DBUS_TRUE@       $(am__objects_9)
-@COND_DBUS_TRUE@@ENABLE_UNIT_TESTS_TRUE@am__objects_10 = syncevo_dbus_server-test.$(OBJEXT)
 @COND_DBUS_TRUE@nodist_syncevo_dbus_server_OBJECTS =  \
-@COND_DBUS_TRUE@       syncevo_dbus_server-syncevo-marshal.$(OBJEXT) \
-@COND_DBUS_TRUE@       $(am__objects_10)
+@COND_DBUS_TRUE@       syncevo_dbus_server-test.$(OBJEXT)
 syncevo_dbus_server_OBJECTS = $(am_syncevo_dbus_server_OBJECTS) \
        $(nodist_syncevo_dbus_server_OBJECTS)
 syncevo_dbus_server_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
@@ -158,22 +142,17 @@ am__syncevolution_SOURCES_DIST = syncevolution.cpp CmdlineSyncClient.h \
        backends/evolution/EvolutionCalendarSourceRegister.cpp \
        backends/evolution/EvolutionContactSourceRegister.cpp \
        backends/file/FileSyncSourceRegister.cpp \
-       backends/maemo/MaemoCalendarSourceRegister.cpp \
-       backends/sqlite/SQLiteContactSourceRegister.cpp \
-       backends/xmlrpc/XMLRPCSyncSourceRegister.cpp
-am__objects_11 = syncevolution-AddressBookSourceRegister.$(OBJEXT) \
+       backends/sqlite/SQLiteContactSourceRegister.cpp
+am__objects_10 = syncevolution-AddressBookSourceRegister.$(OBJEXT) \
        syncevolution-EvolutionCalendarSourceRegister.$(OBJEXT) \
        syncevolution-EvolutionContactSourceRegister.$(OBJEXT) \
        syncevolution-FileSyncSourceRegister.$(OBJEXT) \
-       syncevolution-MaemoCalendarSourceRegister.$(OBJEXT) \
-       syncevolution-SQLiteContactSourceRegister.$(OBJEXT) \
-       syncevolution-XMLRPCSyncSourceRegister.$(OBJEXT)
-@ENABLE_MODULES_FALSE@am__objects_12 = $(am__objects_11)
-am__objects_13 = $(am__objects_12)
+       syncevolution-SQLiteContactSourceRegister.$(OBJEXT)
+@ENABLE_MODULES_FALSE@am__objects_11 = $(am__objects_10)
+am__objects_12 = $(am__objects_11)
 am_syncevolution_OBJECTS = syncevolution-syncevolution.$(OBJEXT) \
-       syncevolution-CmdlineSyncClient.$(OBJEXT) $(am__objects_13)
-@ENABLE_UNIT_TESTS_TRUE@nodist_syncevolution_OBJECTS =  \
-@ENABLE_UNIT_TESTS_TRUE@       syncevolution-test.$(OBJEXT)
+       syncevolution-CmdlineSyncClient.$(OBJEXT) $(am__objects_12)
+nodist_syncevolution_OBJECTS = syncevolution-test.$(OBJEXT)
 syncevolution_OBJECTS = $(am_syncevolution_OBJECTS) \
        $(nodist_syncevolution_OBJECTS)
 syncevolution_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
@@ -184,15 +163,6 @@ SCRIPTS = $(bin_SCRIPTS)
 DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
 depcomp = $(SHELL) $(top_srcdir)/depcomp
 am__depfiles_maybe = depfiles
-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
-       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
-       --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
-       $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-CCLD = $(CC)
-LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
-       --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
-       $(LDFLAGS) -o $@
 CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
        $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
 LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
@@ -202,6 +172,15 @@ CXXLD = $(CXX)
 CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
        --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
        $(LDFLAGS) -o $@
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+       --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+       $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+       --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+       $(LDFLAGS) -o $@
 SOURCES = $(abort_redirect_SOURCES) $(client_test_SOURCES) \
        $(nodist_client_test_SOURCES) $(syncevo_dbus_server_SOURCES) \
        $(nodist_syncevo_dbus_server_SOURCES) $(syncevolution_SOURCES) \
@@ -249,6 +228,8 @@ AUTOMAKE = @AUTOMAKE@
 AWK = @AWK@
 BACKEND_CPPFLAGS = @BACKEND_CPPFLAGS@
 BACKEND_DEFINES = @BACKEND_DEFINES@
+BLUEZ_CFLAGS = @BLUEZ_CFLAGS@
+BLUEZ_LIBS = @BLUEZ_LIBS@
 BOOST_CPPFLAGS = @BOOST_CPPFLAGS@
 BOOST_LDFLAGS = @BOOST_LDFLAGS@
 CATALOGS = @CATALOGS@
@@ -256,7 +237,6 @@ CATOBJEXT = @CATOBJEXT@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
-CLEAN_CLIENT_SRC = @CLEAN_CLIENT_SRC@
 CORE_LDADD_DEP = @CORE_LDADD_DEP@
 CPP = @CPP@
 CPPFLAGS = @CPPFLAGS@
@@ -269,8 +249,10 @@ CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
 DATADIRNAME = @DATADIRNAME@
 DBUS_BINDING_TOOL = @DBUS_BINDING_TOOL@
+DBUS_CFLAGS = @DBUS_CFLAGS@
 DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@
 DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@
+DBUS_LIBS = @DBUS_LIBS@
 DBUS_SERVICES_DIR = @DBUS_SERVICES_DIR@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
@@ -297,11 +279,7 @@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
 GLIB_LIBS = @GLIB_LIBS@
 GMOFILES = @GMOFILES@
 GMSGFMT = @GMSGFMT@
-GOBJECT_CFLAGS = @GOBJECT_CFLAGS@
-GOBJECT_LIBS = @GOBJECT_LIBS@
 GREP = @GREP@
-GTHREAD_CFLAGS = @GTHREAD_CFLAGS@
-GTHREAD_LIBS = @GTHREAD_LIBS@
 GTK_BUILDER_CONV = @GTK_BUILDER_CONV@
 GUI_CFLAGS = @GUI_CFLAGS@
 GUI_DESKTOP_FILES = @GUI_DESKTOP_FILES@
@@ -325,6 +303,8 @@ KEYRING_LIBS = @KEYRING_LIBS@
 LDFLAGS = @LDFLAGS@
 LIBEXECDIR = @LIBEXECDIR@
 LIBOBJS = @LIBOBJS@
+LIBOPENOBEX_CFLAGS = @LIBOPENOBEX_CFLAGS@
+LIBOPENOBEX_LIBS = @LIBOPENOBEX_LIBS@
 LIBS = @LIBS@
 LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@
 LIBSOUP_LIBS = @LIBSOUP_LIBS@
@@ -332,8 +312,6 @@ LIBTOOL = @LIBTOOL@
 LN_S = @LN_S@
 LTLIBOBJS = @LTLIBOBJS@
 MAKEINFO = @MAKEINFO@
-MCALB_CFLAGS = @MCALB_CFLAGS@
-MCALB_LIBS = @MCALB_LIBS@
 MKDIR_P = @MKDIR_P@
 MKINSTALLDIRS = @MKINSTALLDIRS@
 MODIFY_SYNCCOMPARE = @MODIFY_SYNCCOMPARE@
@@ -369,6 +347,7 @@ SYNTHESIS = @SYNTHESIS@
 SYNTHESISSRC = @SYNTHESISSRC@
 SYNTHESIS_CFLAGS = @SYNTHESIS_CFLAGS@
 SYNTHESIS_DEP = @SYNTHESIS_DEP@
+SYNTHESIS_ENGINE = @SYNTHESIS_ENGINE@
 SYNTHESIS_LIB = @SYNTHESIS_LIB@
 SYNTHESIS_LIBS = @SYNTHESIS_LIBS@
 SYNTHESIS_SRC = @SYNTHESIS_SRC@
@@ -380,8 +359,6 @@ UNIQUE_LIBS = @UNIQUE_LIBS@
 USE_NLS = @USE_NLS@
 VERSION = @VERSION@
 XGETTEXT = @XGETTEXT@
-XMLRPC_CFLAGS = @XMLRPC_CFLAGS@
-XMLRPC_LIBS = @XMLRPC_LIBS@
 XSLT = @XSLT@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
@@ -436,18 +413,18 @@ sysconfdir = @sysconfdir@
 target_alias = @target_alias@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
-BACKENDS = backends/addressbook backends/evolution backends/file backends/maemo backends/sqlite backends/xmlrpc
-service_in_files = org.Moblin.SyncEvolution.service.in
+BACKENDS = backends/addressbook backends/evolution backends/file backends/sqlite
+service_in_files = org.syncevolution.service.in
 @COND_DBUS_TRUE@servicedir = $(DBUS_SERVICES_DIR)
 @COND_DBUS_TRUE@service_DATA = $(service_in_files:.service.in=.service)
 # jump into interface directory directly instead of going through dbus
-@COND_DBUS_FALSE@@COND_GUI_TRUE@DBUS_DIR = dbus/interfaces
-@COND_DBUS_TRUE@DBUS_DIR = dbus
+@COND_DBUS_FALSE@@COND_GUI_TRUE@DBUS_DIRS = dbus/interfaces
+@COND_DBUS_TRUE@DBUS_DIRS = gdbus dbus
 @COND_GUI_TRUE@GUI_DIR = gtk-ui
-SUBDIRS = $(SYNTHESIS_SUBDIR) $(DBUS_DIR) syncevo $(BACKENDS) $(GUI_DIR)
-DIST_SUBDIRS = dbus syncevo $(BACKENDS) gtk-ui
+SUBDIRS = $(SYNTHESIS_SUBDIR) $(DBUS_DIRS) syncevo $(BACKENDS) $(GUI_DIR)
+DIST_SUBDIRS = gdbus dbus syncevo $(BACKENDS) gtk-ui
 BUILT_SOURCES = 
-AM_CPPFLAGS = $(SUBDIRS:%=-I$(srcdir)/%) -I$(srcdir)/../test -I$(top_srcdir) $(BACKEND_CPPFLAGS)
+AM_CPPFLAGS = $(SUBDIRS:%=-I$(srcdir)/%) -I$(srcdir)/../test -I$(top_srcdir) $(BACKEND_CPPFLAGS) $(GLIB_CFLAGS)
 bin_SCRIPTS = synccompare
 SYNCEVOLUTION_DEP = $(am__append_2)
 EXTRA_DIST = shlibs.local Makefile-gen.am syncclient_sample_config.xml \
@@ -458,7 +435,7 @@ nobase_dist_template_DATA = $(TEMPLATE_FILES)
 DISTCLEANFILES = synccompare
 MAINTAINERCLEANFILES = Makefile.in
 CLEANFILES = libstdc++.a client-test $(CLIENT_LIB_TEST_FILES) \
-       org.Moblin.SyncEvolution.service abort-redirect.log
+       org.syncevolution.service abort-redirect.log
 CORE_SOURCES = $(am__append_4)
 
 # The files which register backends have to be compiled into
@@ -470,9 +447,9 @@ CORE_SOURCES = $(am__append_4)
 # When using modules the registration is done inside the
 # module and the register file is unnecessary. However, they
 # still need to be included in "make dist".
-BACKEND_REGISTRIES = backends/addressbook/AddressBookSourceRegister.cpp backends/evolution/EvolutionCalendarSourceRegister.cpp backends/evolution/EvolutionContactSourceRegister.cpp backends/file/FileSyncSourceRegister.cpp backends/maemo/MaemoCalendarSourceRegister.cpp backends/sqlite/SQLiteContactSourceRegister.cpp backends/xmlrpc/XMLRPCSyncSourceRegister.cpp
+BACKEND_REGISTRIES = backends/addressbook/AddressBookSourceRegister.cpp backends/evolution/EvolutionCalendarSourceRegister.cpp backends/evolution/EvolutionContactSourceRegister.cpp backends/file/FileSyncSourceRegister.cpp backends/sqlite/SQLiteContactSourceRegister.cpp
 CORE_CXXFLAGS = $(SYNTHESIS_CFLAGS)
-CORE_LDADD = $(SYNCEVOLUTION_LDADD) syncevo/libsyncevolution.la $(GLIB_LIBS) $(GTHREAD_LIBS) $(GOBJECT_LIBS) $(LIBS)
+CORE_LDADD = $(SYNCEVOLUTION_LDADD) syncevo/libsyncevolution.la $(GLIB_LIBS) $(LIBS)
 CORE_DEP = $(SYNCEVOLUTION_DEP) syncevo/libsyncevolution.la $(SYNTHESIS_DEP)
 CORE_LD_FLAGS = -uSyncEvolution_Module_Version -Wl,--export-dynamic
 syncevolution_SOURCES = \
@@ -481,7 +458,7 @@ syncevolution_SOURCES = \
        CmdlineSyncClient.cpp \
        $(CORE_SOURCES)
 
-@ENABLE_UNIT_TESTS_TRUE@nodist_syncevolution_SOURCES = ../test/test.cpp
+nodist_syncevolution_SOURCES = ../test/test.cpp
 
 # SYNCEVOLUTION_LDADD will be replaced with libsyncebook.la/libsyncecal.la/libsyncsqlite.la
 # if linking statically against them, empty otherwise;
@@ -491,18 +468,17 @@ syncevolution_LDFLAGS = $(CORE_LD_FLAGS)
 syncevolution_CXXFLAGS = $(SYNCEVOLUTION_CXXFLAGS) $(CORE_CXXFLAGS) $(KEYRING_CFLAGS)
 syncevolution_DEPENDENCIES = $(EXTRA_LTLIBRARIES) $(CORE_DEP) # $(SYNTHESIS_DEP)
 @COND_DBUS_TRUE@syncevo_dbus_server_SOURCES = \
-@COND_DBUS_TRUE@       syncevo-dbus-server.cpp syncevo-dbus-server.h \
-@COND_DBUS_TRUE@       DBusSyncClient.cpp DBusSyncClient.h \
+@COND_DBUS_TRUE@       syncevo-dbus-server.cpp \
 @COND_DBUS_TRUE@       $(CORE_SOURCES)
 
-@COND_DBUS_TRUE@nodist_syncevo_dbus_server_SOURCES =  \
-@COND_DBUS_TRUE@       dbus/interfaces/syncevo-marshal.c \
-@COND_DBUS_TRUE@       $(am__append_5)
-@COND_DBUS_TRUE@syncevo_dbus_server_LDADD = $(DBUS_GLIB_LIBS) $(KEYRING_LIBS) $(CORE_LDADD)
-@COND_DBUS_TRUE@syncevo_dbus_server_CPPFLAGS = -DHAVE_CONFIG_H -Idbus/interfaces $(DBUS_GLIB_CFLAGS) $(KEYRING_CFLAGS) $(AM_CPPFLAGS)
-@COND_DBUS_TRUE@syncevo_dbus_server_CXXFLAGS = $(SYNCEVOLUTION_CXXFLAGS) $(CORE_CXXFLAGS)
-@COND_DBUS_TRUE@syncevo_dbus_server_LDFLAGS = $(CORE_LD_FLAGS)
-@COND_DBUS_TRUE@syncevo_dbus_server_DEPENDENCIES = $(EXTRA_LTLIBRARIES) $(CORE_DEP) $(SYNTHESIS_DEP)
+@COND_DBUS_TRUE@nodist_syncevo_dbus_server_SOURCES = \
+@COND_DBUS_TRUE@       ../test/test.cpp
+
+@COND_DBUS_TRUE@syncevo_dbus_server_LDADD = gdbus/libgdbus.la $(CORE_LDADD)
+@COND_DBUS_TRUE@syncevo_dbus_server_CPPFLAGS = -DHAVE_CONFIG_H -I$(srcdir)/gdbus $(AM_CPPFLAGS)
+@COND_DBUS_TRUE@syncevo_dbus_server_CXXFLAGS = $(SYNCEVOLUTION_CXXFLAGS) $(CORE_CXXFLAGS) $(GLIB_CFLAGS) $(DBUS_CFLAGS) $(LIBSOUP_CFLAGS)
+@COND_DBUS_TRUE@syncevo_dbus_server_LDFLAGS = $(CORE_LD_FLAGS) $(LIBSOUP_LIBS)
+@COND_DBUS_TRUE@syncevo_dbus_server_DEPENDENCIES = gdbus/libgdbus.la $(EXTRA_LTLIBRARIES) $(CORE_DEP) $(SYNTHESIS_DEP)
 
 # With --disable-shared autotools links against libfunambol.a which does not
 # pull any of the test suites into the test binary, so they would not be
@@ -515,7 +491,18 @@ client_test_SOURCES = \
        ../test/client-test-main.cpp \
        $(CORE_SOURCES)
 
-nodist_client_test_SOURCES = ../test/test.cpp $(am__append_9)
+nodist_client_test_SOURCES = ../test/test.cpp $(am__append_8)
+
+# Always compile the registry files into client-test because that is
+# the only place where they are compiled with
+# ENABLE_INTEGRATION_TESTS.  This works without undefined references
+# because client-test is linked against all shared backend libraries
+# (non-portable, but works).
+# Disabled now, the client test can also be dynamically loaded and registered
+# just the same as syncevolution
+# if ENABLE_MODULES
+# client_test_SOURCES += $(BACKEND_REGISTRIES)
+# endif
 
 # list of test file base files
 #
@@ -542,8 +529,8 @@ client_test_LDADD = $(CORE_LDADD) $(SYNTHESIS_ENGINE)
 # Listing the dependencies here is done to ensure that one doesn't accidentally
 # runs the binary with out-dated auxiliary files.
 client_test_DEPENDENCIES = $(EXTRA_LTLIBRARIES) $(CORE_DEP) \
-       $(CLIENT_LIB_TEST_FILES) testcase2patch synccompare \
-       $(am__append_10)
+       $(CLIENT_LIB_TEST_FILES) testcase2patch synccompare templates \
+       $(am__append_9)
 @ENABLE_TESTING_TRUE@nobase_dist_doc_DATA = $(CLIENT_LIB_TEST_FILES)
 abort_redirect_SOURCES = ../test/abort-redirect.cpp
 abort_redirect_CPPFLAGS = -DHAVE_CONFIG_H $(AM_CPPFLAGS)
@@ -555,7 +542,7 @@ all: $(BUILT_SOURCES)
        $(MAKE) $(AM_MAKEFLAGS) all-recursive
 
 .SUFFIXES:
-.SUFFIXES: .c .cpp .lo .o .obj
+.SUFFIXES: .cpp .lo .o .obj
 $(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
        @for dep in $?; do \
          case '$(am__configure_deps)' in \
@@ -685,69 +672,26 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client_test-EvolutionCalendarSourceRegister.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client_test-EvolutionContactSourceRegister.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client_test-FileSyncSourceRegister.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client_test-MaemoCalendarSourceRegister.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client_test-SQLiteContactSourceRegister.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client_test-XMLRPCSyncSourceRegister.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client_test-client-test-app.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client_test-client-test-main.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client_test-test.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syncevo_dbus_server-AddressBookSourceRegister.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syncevo_dbus_server-DBusSyncClient.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syncevo_dbus_server-EvolutionCalendarSourceRegister.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syncevo_dbus_server-EvolutionContactSourceRegister.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syncevo_dbus_server-FileSyncSourceRegister.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syncevo_dbus_server-MaemoCalendarSourceRegister.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syncevo_dbus_server-SQLiteContactSourceRegister.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syncevo_dbus_server-XMLRPCSyncSourceRegister.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syncevo_dbus_server-syncevo-dbus-server.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syncevo_dbus_server-syncevo-marshal.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syncevo_dbus_server-test.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syncevolution-AddressBookSourceRegister.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syncevolution-CmdlineSyncClient.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syncevolution-EvolutionCalendarSourceRegister.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syncevolution-EvolutionContactSourceRegister.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syncevolution-FileSyncSourceRegister.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syncevolution-MaemoCalendarSourceRegister.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syncevolution-SQLiteContactSourceRegister.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syncevolution-XMLRPCSyncSourceRegister.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syncevolution-syncevolution.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syncevolution-test.Po@am__quote@
 
-.c.o:
-@am__fastdepCC_TRUE@   $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(COMPILE) -c $<
-
-.c.obj:
-@am__fastdepCC_TRUE@   $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(COMPILE) -c `$(CYGPATH_W) '$<'`
-
-.c.lo:
-@am__fastdepCC_TRUE@   $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(LTCOMPILE) -c -o $@ $<
-
-syncevo_dbus_server-syncevo-marshal.o: dbus/interfaces/syncevo-marshal.c
-@am__fastdepCC_TRUE@   $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(syncevo_dbus_server_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT syncevo_dbus_server-syncevo-marshal.o -MD -MP -MF $(DEPDIR)/syncevo_dbus_server-syncevo-marshal.Tpo -c -o syncevo_dbus_server-syncevo-marshal.o `test -f 'dbus/interfaces/syncevo-marshal.c' || echo '$(srcdir)/'`dbus/interfaces/syncevo-marshal.c
-@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/syncevo_dbus_server-syncevo-marshal.Tpo $(DEPDIR)/syncevo_dbus_server-syncevo-marshal.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='dbus/interfaces/syncevo-marshal.c' object='syncevo_dbus_server-syncevo-marshal.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(syncevo_dbus_server_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o syncevo_dbus_server-syncevo-marshal.o `test -f 'dbus/interfaces/syncevo-marshal.c' || echo '$(srcdir)/'`dbus/interfaces/syncevo-marshal.c
-
-syncevo_dbus_server-syncevo-marshal.obj: dbus/interfaces/syncevo-marshal.c
-@am__fastdepCC_TRUE@   $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(syncevo_dbus_server_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT syncevo_dbus_server-syncevo-marshal.obj -MD -MP -MF $(DEPDIR)/syncevo_dbus_server-syncevo-marshal.Tpo -c -o syncevo_dbus_server-syncevo-marshal.obj `if test -f 'dbus/interfaces/syncevo-marshal.c'; then $(CYGPATH_W) 'dbus/interfaces/syncevo-marshal.c'; else $(CYGPATH_W) '$(srcdir)/dbus/interfaces/syncevo-marshal.c'; fi`
-@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/syncevo_dbus_server-syncevo-marshal.Tpo $(DEPDIR)/syncevo_dbus_server-syncevo-marshal.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='dbus/interfaces/syncevo-marshal.c' object='syncevo_dbus_server-syncevo-marshal.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(syncevo_dbus_server_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o syncevo_dbus_server-syncevo-marshal.obj `if test -f 'dbus/interfaces/syncevo-marshal.c'; then $(CYGPATH_W) 'dbus/interfaces/syncevo-marshal.c'; else $(CYGPATH_W) '$(srcdir)/dbus/interfaces/syncevo-marshal.c'; fi`
-
 .cpp.o:
 @am__fastdepCXX_TRUE@  $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
 @am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@@ -881,20 +825,6 @@ client_test-FileSyncSourceRegister.obj: backends/file/FileSyncSourceRegister.cpp
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(client_test_CPPFLAGS) $(CPPFLAGS) $(client_test_CXXFLAGS) $(CXXFLAGS) -c -o client_test-FileSyncSourceRegister.obj `if test -f 'backends/file/FileSyncSourceRegister.cpp'; then $(CYGPATH_W) 'backends/file/FileSyncSourceRegister.cpp'; else $(CYGPATH_W) '$(srcdir)/backends/file/FileSyncSourceRegister.cpp'; fi`
 
-client_test-MaemoCalendarSourceRegister.o: backends/maemo/MaemoCalendarSourceRegister.cpp
-@am__fastdepCXX_TRUE@  $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(client_test_CPPFLAGS) $(CPPFLAGS) $(client_test_CXXFLAGS) $(CXXFLAGS) -MT client_test-MaemoCalendarSourceRegister.o -MD -MP -MF $(DEPDIR)/client_test-MaemoCalendarSourceRegister.Tpo -c -o client_test-MaemoCalendarSourceRegister.o `test -f 'backends/maemo/MaemoCalendarSourceRegister.cpp' || echo '$(srcdir)/'`backends/maemo/MaemoCalendarSourceRegister.cpp
-@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/client_test-MaemoCalendarSourceRegister.Tpo $(DEPDIR)/client_test-MaemoCalendarSourceRegister.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='backends/maemo/MaemoCalendarSourceRegister.cpp' object='client_test-MaemoCalendarSourceRegister.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(client_test_CPPFLAGS) $(CPPFLAGS) $(client_test_CXXFLAGS) $(CXXFLAGS) -c -o client_test-MaemoCalendarSourceRegister.o `test -f 'backends/maemo/MaemoCalendarSourceRegister.cpp' || echo '$(srcdir)/'`backends/maemo/MaemoCalendarSourceRegister.cpp
-
-client_test-MaemoCalendarSourceRegister.obj: backends/maemo/MaemoCalendarSourceRegister.cpp
-@am__fastdepCXX_TRUE@  $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(client_test_CPPFLAGS) $(CPPFLAGS) $(client_test_CXXFLAGS) $(CXXFLAGS) -MT client_test-MaemoCalendarSourceRegister.obj -MD -MP -MF $(DEPDIR)/client_test-MaemoCalendarSourceRegister.Tpo -c -o client_test-MaemoCalendarSourceRegister.obj `if test -f 'backends/maemo/MaemoCalendarSourceRegister.cpp'; then $(CYGPATH_W) 'backends/maemo/MaemoCalendarSourceRegister.cpp'; else $(CYGPATH_W) '$(srcdir)/backends/maemo/MaemoCalendarSourceRegister.cpp'; fi`
-@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/client_test-MaemoCalendarSourceRegister.Tpo $(DEPDIR)/client_test-MaemoCalendarSourceRegister.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='backends/maemo/MaemoCalendarSourceRegister.cpp' object='client_test-MaemoCalendarSourceRegister.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(client_test_CPPFLAGS) $(CPPFLAGS) $(client_test_CXXFLAGS) $(CXXFLAGS) -c -o client_test-MaemoCalendarSourceRegister.obj `if test -f 'backends/maemo/MaemoCalendarSourceRegister.cpp'; then $(CYGPATH_W) 'backends/maemo/MaemoCalendarSourceRegister.cpp'; else $(CYGPATH_W) '$(srcdir)/backends/maemo/MaemoCalendarSourceRegister.cpp'; fi`
-
 client_test-SQLiteContactSourceRegister.o: backends/sqlite/SQLiteContactSourceRegister.cpp
 @am__fastdepCXX_TRUE@  $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(client_test_CPPFLAGS) $(CPPFLAGS) $(client_test_CXXFLAGS) $(CXXFLAGS) -MT client_test-SQLiteContactSourceRegister.o -MD -MP -MF $(DEPDIR)/client_test-SQLiteContactSourceRegister.Tpo -c -o client_test-SQLiteContactSourceRegister.o `test -f 'backends/sqlite/SQLiteContactSourceRegister.cpp' || echo '$(srcdir)/'`backends/sqlite/SQLiteContactSourceRegister.cpp
 @am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/client_test-SQLiteContactSourceRegister.Tpo $(DEPDIR)/client_test-SQLiteContactSourceRegister.Po
@@ -909,20 +839,6 @@ client_test-SQLiteContactSourceRegister.obj: backends/sqlite/SQLiteContactSource
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(client_test_CPPFLAGS) $(CPPFLAGS) $(client_test_CXXFLAGS) $(CXXFLAGS) -c -o client_test-SQLiteContactSourceRegister.obj `if test -f 'backends/sqlite/SQLiteContactSourceRegister.cpp'; then $(CYGPATH_W) 'backends/sqlite/SQLiteContactSourceRegister.cpp'; else $(CYGPATH_W) '$(srcdir)/backends/sqlite/SQLiteContactSourceRegister.cpp'; fi`
 
-client_test-XMLRPCSyncSourceRegister.o: backends/xmlrpc/XMLRPCSyncSourceRegister.cpp
-@am__fastdepCXX_TRUE@  $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(client_test_CPPFLAGS) $(CPPFLAGS) $(client_test_CXXFLAGS) $(CXXFLAGS) -MT client_test-XMLRPCSyncSourceRegister.o -MD -MP -MF $(DEPDIR)/client_test-XMLRPCSyncSourceRegister.Tpo -c -o client_test-XMLRPCSyncSourceRegister.o `test -f 'backends/xmlrpc/XMLRPCSyncSourceRegister.cpp' || echo '$(srcdir)/'`backends/xmlrpc/XMLRPCSyncSourceRegister.cpp
-@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/client_test-XMLRPCSyncSourceRegister.Tpo $(DEPDIR)/client_test-XMLRPCSyncSourceRegister.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='backends/xmlrpc/XMLRPCSyncSourceRegister.cpp' object='client_test-XMLRPCSyncSourceRegister.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(client_test_CPPFLAGS) $(CPPFLAGS) $(client_test_CXXFLAGS) $(CXXFLAGS) -c -o client_test-XMLRPCSyncSourceRegister.o `test -f 'backends/xmlrpc/XMLRPCSyncSourceRegister.cpp' || echo '$(srcdir)/'`backends/xmlrpc/XMLRPCSyncSourceRegister.cpp
-
-client_test-XMLRPCSyncSourceRegister.obj: backends/xmlrpc/XMLRPCSyncSourceRegister.cpp
-@am__fastdepCXX_TRUE@  $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(client_test_CPPFLAGS) $(CPPFLAGS) $(client_test_CXXFLAGS) $(CXXFLAGS) -MT client_test-XMLRPCSyncSourceRegister.obj -MD -MP -MF $(DEPDIR)/client_test-XMLRPCSyncSourceRegister.Tpo -c -o client_test-XMLRPCSyncSourceRegister.obj `if test -f 'backends/xmlrpc/XMLRPCSyncSourceRegister.cpp'; then $(CYGPATH_W) 'backends/xmlrpc/XMLRPCSyncSourceRegister.cpp'; else $(CYGPATH_W) '$(srcdir)/backends/xmlrpc/XMLRPCSyncSourceRegister.cpp'; fi`
-@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/client_test-XMLRPCSyncSourceRegister.Tpo $(DEPDIR)/client_test-XMLRPCSyncSourceRegister.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='backends/xmlrpc/XMLRPCSyncSourceRegister.cpp' object='client_test-XMLRPCSyncSourceRegister.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(client_test_CPPFLAGS) $(CPPFLAGS) $(client_test_CXXFLAGS) $(CXXFLAGS) -c -o client_test-XMLRPCSyncSourceRegister.obj `if test -f 'backends/xmlrpc/XMLRPCSyncSourceRegister.cpp'; then $(CYGPATH_W) 'backends/xmlrpc/XMLRPCSyncSourceRegister.cpp'; else $(CYGPATH_W) '$(srcdir)/backends/xmlrpc/XMLRPCSyncSourceRegister.cpp'; fi`
-
 client_test-test.o: ../test/test.cpp
 @am__fastdepCXX_TRUE@  $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(client_test_CPPFLAGS) $(CPPFLAGS) $(client_test_CXXFLAGS) $(CXXFLAGS) -MT client_test-test.o -MD -MP -MF $(DEPDIR)/client_test-test.Tpo -c -o client_test-test.o `test -f '../test/test.cpp' || echo '$(srcdir)/'`../test/test.cpp
 @am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/client_test-test.Tpo $(DEPDIR)/client_test-test.Po
@@ -951,20 +867,6 @@ syncevo_dbus_server-syncevo-dbus-server.obj: syncevo-dbus-server.cpp
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(syncevo_dbus_server_CPPFLAGS) $(CPPFLAGS) $(syncevo_dbus_server_CXXFLAGS) $(CXXFLAGS) -c -o syncevo_dbus_server-syncevo-dbus-server.obj `if test -f 'syncevo-dbus-server.cpp'; then $(CYGPATH_W) 'syncevo-dbus-server.cpp'; else $(CYGPATH_W) '$(srcdir)/syncevo-dbus-server.cpp'; fi`
 
-syncevo_dbus_server-DBusSyncClient.o: DBusSyncClient.cpp
-@am__fastdepCXX_TRUE@  $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(syncevo_dbus_server_CPPFLAGS) $(CPPFLAGS) $(syncevo_dbus_server_CXXFLAGS) $(CXXFLAGS) -MT syncevo_dbus_server-DBusSyncClient.o -MD -MP -MF $(DEPDIR)/syncevo_dbus_server-DBusSyncClient.Tpo -c -o syncevo_dbus_server-DBusSyncClient.o `test -f 'DBusSyncClient.cpp' || echo '$(srcdir)/'`DBusSyncClient.cpp
-@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/syncevo_dbus_server-DBusSyncClient.Tpo $(DEPDIR)/syncevo_dbus_server-DBusSyncClient.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='DBusSyncClient.cpp' object='syncevo_dbus_server-DBusSyncClient.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(syncevo_dbus_server_CPPFLAGS) $(CPPFLAGS) $(syncevo_dbus_server_CXXFLAGS) $(CXXFLAGS) -c -o syncevo_dbus_server-DBusSyncClient.o `test -f 'DBusSyncClient.cpp' || echo '$(srcdir)/'`DBusSyncClient.cpp
-
-syncevo_dbus_server-DBusSyncClient.obj: DBusSyncClient.cpp
-@am__fastdepCXX_TRUE@  $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(syncevo_dbus_server_CPPFLAGS) $(CPPFLAGS) $(syncevo_dbus_server_CXXFLAGS) $(CXXFLAGS) -MT syncevo_dbus_server-DBusSyncClient.obj -MD -MP -MF $(DEPDIR)/syncevo_dbus_server-DBusSyncClient.Tpo -c -o syncevo_dbus_server-DBusSyncClient.obj `if test -f 'DBusSyncClient.cpp'; then $(CYGPATH_W) 'DBusSyncClient.cpp'; else $(CYGPATH_W) '$(srcdir)/DBusSyncClient.cpp'; fi`
-@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/syncevo_dbus_server-DBusSyncClient.Tpo $(DEPDIR)/syncevo_dbus_server-DBusSyncClient.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='DBusSyncClient.cpp' object='syncevo_dbus_server-DBusSyncClient.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(syncevo_dbus_server_CPPFLAGS) $(CPPFLAGS) $(syncevo_dbus_server_CXXFLAGS) $(CXXFLAGS) -c -o syncevo_dbus_server-DBusSyncClient.obj `if test -f 'DBusSyncClient.cpp'; then $(CYGPATH_W) 'DBusSyncClient.cpp'; else $(CYGPATH_W) '$(srcdir)/DBusSyncClient.cpp'; fi`
-
 syncevo_dbus_server-AddressBookSourceRegister.o: backends/addressbook/AddressBookSourceRegister.cpp
 @am__fastdepCXX_TRUE@  $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(syncevo_dbus_server_CPPFLAGS) $(CPPFLAGS) $(syncevo_dbus_server_CXXFLAGS) $(CXXFLAGS) -MT syncevo_dbus_server-AddressBookSourceRegister.o -MD -MP -MF $(DEPDIR)/syncevo_dbus_server-AddressBookSourceRegister.Tpo -c -o syncevo_dbus_server-AddressBookSourceRegister.o `test -f 'backends/addressbook/AddressBookSourceRegister.cpp' || echo '$(srcdir)/'`backends/addressbook/AddressBookSourceRegister.cpp
 @am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/syncevo_dbus_server-AddressBookSourceRegister.Tpo $(DEPDIR)/syncevo_dbus_server-AddressBookSourceRegister.Po
@@ -1021,20 +923,6 @@ syncevo_dbus_server-FileSyncSourceRegister.obj: backends/file/FileSyncSourceRegi
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(syncevo_dbus_server_CPPFLAGS) $(CPPFLAGS) $(syncevo_dbus_server_CXXFLAGS) $(CXXFLAGS) -c -o syncevo_dbus_server-FileSyncSourceRegister.obj `if test -f 'backends/file/FileSyncSourceRegister.cpp'; then $(CYGPATH_W) 'backends/file/FileSyncSourceRegister.cpp'; else $(CYGPATH_W) '$(srcdir)/backends/file/FileSyncSourceRegister.cpp'; fi`
 
-syncevo_dbus_server-MaemoCalendarSourceRegister.o: backends/maemo/MaemoCalendarSourceRegister.cpp
-@am__fastdepCXX_TRUE@  $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(syncevo_dbus_server_CPPFLAGS) $(CPPFLAGS) $(syncevo_dbus_server_CXXFLAGS) $(CXXFLAGS) -MT syncevo_dbus_server-MaemoCalendarSourceRegister.o -MD -MP -MF $(DEPDIR)/syncevo_dbus_server-MaemoCalendarSourceRegister.Tpo -c -o syncevo_dbus_server-MaemoCalendarSourceRegister.o `test -f 'backends/maemo/MaemoCalendarSourceRegister.cpp' || echo '$(srcdir)/'`backends/maemo/MaemoCalendarSourceRegister.cpp
-@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/syncevo_dbus_server-MaemoCalendarSourceRegister.Tpo $(DEPDIR)/syncevo_dbus_server-MaemoCalendarSourceRegister.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='backends/maemo/MaemoCalendarSourceRegister.cpp' object='syncevo_dbus_server-MaemoCalendarSourceRegister.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(syncevo_dbus_server_CPPFLAGS) $(CPPFLAGS) $(syncevo_dbus_server_CXXFLAGS) $(CXXFLAGS) -c -o syncevo_dbus_server-MaemoCalendarSourceRegister.o `test -f 'backends/maemo/MaemoCalendarSourceRegister.cpp' || echo '$(srcdir)/'`backends/maemo/MaemoCalendarSourceRegister.cpp
-
-syncevo_dbus_server-MaemoCalendarSourceRegister.obj: backends/maemo/MaemoCalendarSourceRegister.cpp
-@am__fastdepCXX_TRUE@  $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(syncevo_dbus_server_CPPFLAGS) $(CPPFLAGS) $(syncevo_dbus_server_CXXFLAGS) $(CXXFLAGS) -MT syncevo_dbus_server-MaemoCalendarSourceRegister.obj -MD -MP -MF $(DEPDIR)/syncevo_dbus_server-MaemoCalendarSourceRegister.Tpo -c -o syncevo_dbus_server-MaemoCalendarSourceRegister.obj `if test -f 'backends/maemo/MaemoCalendarSourceRegister.cpp'; then $(CYGPATH_W) 'backends/maemo/MaemoCalendarSourceRegister.cpp'; else $(CYGPATH_W) '$(srcdir)/backends/maemo/MaemoCalendarSourceRegister.cpp'; fi`
-@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/syncevo_dbus_server-MaemoCalendarSourceRegister.Tpo $(DEPDIR)/syncevo_dbus_server-MaemoCalendarSourceRegister.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='backends/maemo/MaemoCalendarSourceRegister.cpp' object='syncevo_dbus_server-MaemoCalendarSourceRegister.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(syncevo_dbus_server_CPPFLAGS) $(CPPFLAGS) $(syncevo_dbus_server_CXXFLAGS) $(CXXFLAGS) -c -o syncevo_dbus_server-MaemoCalendarSourceRegister.obj `if test -f 'backends/maemo/MaemoCalendarSourceRegister.cpp'; then $(CYGPATH_W) 'backends/maemo/MaemoCalendarSourceRegister.cpp'; else $(CYGPATH_W) '$(srcdir)/backends/maemo/MaemoCalendarSourceRegister.cpp'; fi`
-
 syncevo_dbus_server-SQLiteContactSourceRegister.o: backends/sqlite/SQLiteContactSourceRegister.cpp
 @am__fastdepCXX_TRUE@  $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(syncevo_dbus_server_CPPFLAGS) $(CPPFLAGS) $(syncevo_dbus_server_CXXFLAGS) $(CXXFLAGS) -MT syncevo_dbus_server-SQLiteContactSourceRegister.o -MD -MP -MF $(DEPDIR)/syncevo_dbus_server-SQLiteContactSourceRegister.Tpo -c -o syncevo_dbus_server-SQLiteContactSourceRegister.o `test -f 'backends/sqlite/SQLiteContactSourceRegister.cpp' || echo '$(srcdir)/'`backends/sqlite/SQLiteContactSourceRegister.cpp
 @am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/syncevo_dbus_server-SQLiteContactSourceRegister.Tpo $(DEPDIR)/syncevo_dbus_server-SQLiteContactSourceRegister.Po
@@ -1049,20 +937,6 @@ syncevo_dbus_server-SQLiteContactSourceRegister.obj: backends/sqlite/SQLiteConta
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(syncevo_dbus_server_CPPFLAGS) $(CPPFLAGS) $(syncevo_dbus_server_CXXFLAGS) $(CXXFLAGS) -c -o syncevo_dbus_server-SQLiteContactSourceRegister.obj `if test -f 'backends/sqlite/SQLiteContactSourceRegister.cpp'; then $(CYGPATH_W) 'backends/sqlite/SQLiteContactSourceRegister.cpp'; else $(CYGPATH_W) '$(srcdir)/backends/sqlite/SQLiteContactSourceRegister.cpp'; fi`
 
-syncevo_dbus_server-XMLRPCSyncSourceRegister.o: backends/xmlrpc/XMLRPCSyncSourceRegister.cpp
-@am__fastdepCXX_TRUE@  $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(syncevo_dbus_server_CPPFLAGS) $(CPPFLAGS) $(syncevo_dbus_server_CXXFLAGS) $(CXXFLAGS) -MT syncevo_dbus_server-XMLRPCSyncSourceRegister.o -MD -MP -MF $(DEPDIR)/syncevo_dbus_server-XMLRPCSyncSourceRegister.Tpo -c -o syncevo_dbus_server-XMLRPCSyncSourceRegister.o `test -f 'backends/xmlrpc/XMLRPCSyncSourceRegister.cpp' || echo '$(srcdir)/'`backends/xmlrpc/XMLRPCSyncSourceRegister.cpp
-@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/syncevo_dbus_server-XMLRPCSyncSourceRegister.Tpo $(DEPDIR)/syncevo_dbus_server-XMLRPCSyncSourceRegister.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='backends/xmlrpc/XMLRPCSyncSourceRegister.cpp' object='syncevo_dbus_server-XMLRPCSyncSourceRegister.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(syncevo_dbus_server_CPPFLAGS) $(CPPFLAGS) $(syncevo_dbus_server_CXXFLAGS) $(CXXFLAGS) -c -o syncevo_dbus_server-XMLRPCSyncSourceRegister.o `test -f 'backends/xmlrpc/XMLRPCSyncSourceRegister.cpp' || echo '$(srcdir)/'`backends/xmlrpc/XMLRPCSyncSourceRegister.cpp
-
-syncevo_dbus_server-XMLRPCSyncSourceRegister.obj: backends/xmlrpc/XMLRPCSyncSourceRegister.cpp
-@am__fastdepCXX_TRUE@  $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(syncevo_dbus_server_CPPFLAGS) $(CPPFLAGS) $(syncevo_dbus_server_CXXFLAGS) $(CXXFLAGS) -MT syncevo_dbus_server-XMLRPCSyncSourceRegister.obj -MD -MP -MF $(DEPDIR)/syncevo_dbus_server-XMLRPCSyncSourceRegister.Tpo -c -o syncevo_dbus_server-XMLRPCSyncSourceRegister.obj `if test -f 'backends/xmlrpc/XMLRPCSyncSourceRegister.cpp'; then $(CYGPATH_W) 'backends/xmlrpc/XMLRPCSyncSourceRegister.cpp'; else $(CYGPATH_W) '$(srcdir)/backends/xmlrpc/XMLRPCSyncSourceRegister.cpp'; fi`
-@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/syncevo_dbus_server-XMLRPCSyncSourceRegister.Tpo $(DEPDIR)/syncevo_dbus_server-XMLRPCSyncSourceRegister.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='backends/xmlrpc/XMLRPCSyncSourceRegister.cpp' object='syncevo_dbus_server-XMLRPCSyncSourceRegister.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(syncevo_dbus_server_CPPFLAGS) $(CPPFLAGS) $(syncevo_dbus_server_CXXFLAGS) $(CXXFLAGS) -c -o syncevo_dbus_server-XMLRPCSyncSourceRegister.obj `if test -f 'backends/xmlrpc/XMLRPCSyncSourceRegister.cpp'; then $(CYGPATH_W) 'backends/xmlrpc/XMLRPCSyncSourceRegister.cpp'; else $(CYGPATH_W) '$(srcdir)/backends/xmlrpc/XMLRPCSyncSourceRegister.cpp'; fi`
-
 syncevo_dbus_server-test.o: ../test/test.cpp
 @am__fastdepCXX_TRUE@  $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(syncevo_dbus_server_CPPFLAGS) $(CPPFLAGS) $(syncevo_dbus_server_CXXFLAGS) $(CXXFLAGS) -MT syncevo_dbus_server-test.o -MD -MP -MF $(DEPDIR)/syncevo_dbus_server-test.Tpo -c -o syncevo_dbus_server-test.o `test -f '../test/test.cpp' || echo '$(srcdir)/'`../test/test.cpp
 @am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/syncevo_dbus_server-test.Tpo $(DEPDIR)/syncevo_dbus_server-test.Po
@@ -1161,20 +1035,6 @@ syncevolution-FileSyncSourceRegister.obj: backends/file/FileSyncSourceRegister.c
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(syncevolution_CXXFLAGS) $(CXXFLAGS) -c -o syncevolution-FileSyncSourceRegister.obj `if test -f 'backends/file/FileSyncSourceRegister.cpp'; then $(CYGPATH_W) 'backends/file/FileSyncSourceRegister.cpp'; else $(CYGPATH_W) '$(srcdir)/backends/file/FileSyncSourceRegister.cpp'; fi`
 
-syncevolution-MaemoCalendarSourceRegister.o: backends/maemo/MaemoCalendarSourceRegister.cpp
-@am__fastdepCXX_TRUE@  $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(syncevolution_CXXFLAGS) $(CXXFLAGS) -MT syncevolution-MaemoCalendarSourceRegister.o -MD -MP -MF $(DEPDIR)/syncevolution-MaemoCalendarSourceRegister.Tpo -c -o syncevolution-MaemoCalendarSourceRegister.o `test -f 'backends/maemo/MaemoCalendarSourceRegister.cpp' || echo '$(srcdir)/'`backends/maemo/MaemoCalendarSourceRegister.cpp
-@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/syncevolution-MaemoCalendarSourceRegister.Tpo $(DEPDIR)/syncevolution-MaemoCalendarSourceRegister.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='backends/maemo/MaemoCalendarSourceRegister.cpp' object='syncevolution-MaemoCalendarSourceRegister.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(syncevolution_CXXFLAGS) $(CXXFLAGS) -c -o syncevolution-MaemoCalendarSourceRegister.o `test -f 'backends/maemo/MaemoCalendarSourceRegister.cpp' || echo '$(srcdir)/'`backends/maemo/MaemoCalendarSourceRegister.cpp
-
-syncevolution-MaemoCalendarSourceRegister.obj: backends/maemo/MaemoCalendarSourceRegister.cpp
-@am__fastdepCXX_TRUE@  $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(syncevolution_CXXFLAGS) $(CXXFLAGS) -MT syncevolution-MaemoCalendarSourceRegister.obj -MD -MP -MF $(DEPDIR)/syncevolution-MaemoCalendarSourceRegister.Tpo -c -o syncevolution-MaemoCalendarSourceRegister.obj `if test -f 'backends/maemo/MaemoCalendarSourceRegister.cpp'; then $(CYGPATH_W) 'backends/maemo/MaemoCalendarSourceRegister.cpp'; else $(CYGPATH_W) '$(srcdir)/backends/maemo/MaemoCalendarSourceRegister.cpp'; fi`
-@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/syncevolution-MaemoCalendarSourceRegister.Tpo $(DEPDIR)/syncevolution-MaemoCalendarSourceRegister.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='backends/maemo/MaemoCalendarSourceRegister.cpp' object='syncevolution-MaemoCalendarSourceRegister.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(syncevolution_CXXFLAGS) $(CXXFLAGS) -c -o syncevolution-MaemoCalendarSourceRegister.obj `if test -f 'backends/maemo/MaemoCalendarSourceRegister.cpp'; then $(CYGPATH_W) 'backends/maemo/MaemoCalendarSourceRegister.cpp'; else $(CYGPATH_W) '$(srcdir)/backends/maemo/MaemoCalendarSourceRegister.cpp'; fi`
-
 syncevolution-SQLiteContactSourceRegister.o: backends/sqlite/SQLiteContactSourceRegister.cpp
 @am__fastdepCXX_TRUE@  $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(syncevolution_CXXFLAGS) $(CXXFLAGS) -MT syncevolution-SQLiteContactSourceRegister.o -MD -MP -MF $(DEPDIR)/syncevolution-SQLiteContactSourceRegister.Tpo -c -o syncevolution-SQLiteContactSourceRegister.o `test -f 'backends/sqlite/SQLiteContactSourceRegister.cpp' || echo '$(srcdir)/'`backends/sqlite/SQLiteContactSourceRegister.cpp
 @am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/syncevolution-SQLiteContactSourceRegister.Tpo $(DEPDIR)/syncevolution-SQLiteContactSourceRegister.Po
@@ -1189,20 +1049,6 @@ syncevolution-SQLiteContactSourceRegister.obj: backends/sqlite/SQLiteContactSour
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(syncevolution_CXXFLAGS) $(CXXFLAGS) -c -o syncevolution-SQLiteContactSourceRegister.obj `if test -f 'backends/sqlite/SQLiteContactSourceRegister.cpp'; then $(CYGPATH_W) 'backends/sqlite/SQLiteContactSourceRegister.cpp'; else $(CYGPATH_W) '$(srcdir)/backends/sqlite/SQLiteContactSourceRegister.cpp'; fi`
 
-syncevolution-XMLRPCSyncSourceRegister.o: backends/xmlrpc/XMLRPCSyncSourceRegister.cpp
-@am__fastdepCXX_TRUE@  $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(syncevolution_CXXFLAGS) $(CXXFLAGS) -MT syncevolution-XMLRPCSyncSourceRegister.o -MD -MP -MF $(DEPDIR)/syncevolution-XMLRPCSyncSourceRegister.Tpo -c -o syncevolution-XMLRPCSyncSourceRegister.o `test -f 'backends/xmlrpc/XMLRPCSyncSourceRegister.cpp' || echo '$(srcdir)/'`backends/xmlrpc/XMLRPCSyncSourceRegister.cpp
-@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/syncevolution-XMLRPCSyncSourceRegister.Tpo $(DEPDIR)/syncevolution-XMLRPCSyncSourceRegister.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='backends/xmlrpc/XMLRPCSyncSourceRegister.cpp' object='syncevolution-XMLRPCSyncSourceRegister.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(syncevolution_CXXFLAGS) $(CXXFLAGS) -c -o syncevolution-XMLRPCSyncSourceRegister.o `test -f 'backends/xmlrpc/XMLRPCSyncSourceRegister.cpp' || echo '$(srcdir)/'`backends/xmlrpc/XMLRPCSyncSourceRegister.cpp
-
-syncevolution-XMLRPCSyncSourceRegister.obj: backends/xmlrpc/XMLRPCSyncSourceRegister.cpp
-@am__fastdepCXX_TRUE@  $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(syncevolution_CXXFLAGS) $(CXXFLAGS) -MT syncevolution-XMLRPCSyncSourceRegister.obj -MD -MP -MF $(DEPDIR)/syncevolution-XMLRPCSyncSourceRegister.Tpo -c -o syncevolution-XMLRPCSyncSourceRegister.obj `if test -f 'backends/xmlrpc/XMLRPCSyncSourceRegister.cpp'; then $(CYGPATH_W) 'backends/xmlrpc/XMLRPCSyncSourceRegister.cpp'; else $(CYGPATH_W) '$(srcdir)/backends/xmlrpc/XMLRPCSyncSourceRegister.cpp'; fi`
-@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/syncevolution-XMLRPCSyncSourceRegister.Tpo $(DEPDIR)/syncevolution-XMLRPCSyncSourceRegister.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='backends/xmlrpc/XMLRPCSyncSourceRegister.cpp' object='syncevolution-XMLRPCSyncSourceRegister.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(syncevolution_CXXFLAGS) $(CXXFLAGS) -c -o syncevolution-XMLRPCSyncSourceRegister.obj `if test -f 'backends/xmlrpc/XMLRPCSyncSourceRegister.cpp'; then $(CYGPATH_W) 'backends/xmlrpc/XMLRPCSyncSourceRegister.cpp'; else $(CYGPATH_W) '$(srcdir)/backends/xmlrpc/XMLRPCSyncSourceRegister.cpp'; fi`
-
 syncevolution-test.o: ../test/test.cpp
 @am__fastdepCXX_TRUE@  $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(syncevolution_CXXFLAGS) $(CXXFLAGS) -MT syncevolution-test.o -MD -MP -MF $(DEPDIR)/syncevolution-test.Tpo -c -o syncevolution-test.o `test -f '../test/test.cpp' || echo '$(srcdir)/'`../test/test.cpp
 @am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/syncevolution-test.Tpo $(DEPDIR)/syncevolution-test.Po
@@ -1750,6 +1596,15 @@ $(filter-out %.tem, $(filter testcases/%, $(subst $(srcdir)/../test/,,$(CLIENT_L
        mkdir -p testcases
        cp $< $@
 
+# copy template directory into current working directory, if not there
+# yet
+.PHONY: templates
+templates:
+       if test "$(srcdir)/templates" != "./templates"; then \
+               rm -rf ./templates; \
+               cp -r "$(srcdir)/templates" .; \
+       fi
+
 # special target for testing with valgrind
 valgrind : test
        valgrind --leak-check=yes --suppressions=valgrind.supp ./test
index 0036934..657c7ea 100644 (file)
@@ -102,6 +102,8 @@ AUTOMAKE = @AUTOMAKE@
 AWK = @AWK@
 BACKEND_CPPFLAGS = @BACKEND_CPPFLAGS@
 BACKEND_DEFINES = @BACKEND_DEFINES@
+BLUEZ_CFLAGS = @BLUEZ_CFLAGS@
+BLUEZ_LIBS = @BLUEZ_LIBS@
 BOOST_CPPFLAGS = @BOOST_CPPFLAGS@
 BOOST_LDFLAGS = @BOOST_LDFLAGS@
 CATALOGS = @CATALOGS@
@@ -109,7 +111,6 @@ CATOBJEXT = @CATOBJEXT@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
-CLEAN_CLIENT_SRC = @CLEAN_CLIENT_SRC@
 CORE_LDADD_DEP = @CORE_LDADD_DEP@
 CPP = @CPP@
 CPPFLAGS = @CPPFLAGS@
@@ -122,8 +123,10 @@ CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
 DATADIRNAME = @DATADIRNAME@
 DBUS_BINDING_TOOL = @DBUS_BINDING_TOOL@
+DBUS_CFLAGS = @DBUS_CFLAGS@
 DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@
 DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@
+DBUS_LIBS = @DBUS_LIBS@
 DBUS_SERVICES_DIR = @DBUS_SERVICES_DIR@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
@@ -150,11 +153,7 @@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
 GLIB_LIBS = @GLIB_LIBS@
 GMOFILES = @GMOFILES@
 GMSGFMT = @GMSGFMT@
-GOBJECT_CFLAGS = @GOBJECT_CFLAGS@
-GOBJECT_LIBS = @GOBJECT_LIBS@
 GREP = @GREP@
-GTHREAD_CFLAGS = @GTHREAD_CFLAGS@
-GTHREAD_LIBS = @GTHREAD_LIBS@
 GTK_BUILDER_CONV = @GTK_BUILDER_CONV@
 GUI_CFLAGS = @GUI_CFLAGS@
 GUI_DESKTOP_FILES = @GUI_DESKTOP_FILES@
@@ -178,6 +177,8 @@ KEYRING_LIBS = @KEYRING_LIBS@
 LDFLAGS = @LDFLAGS@
 LIBEXECDIR = @LIBEXECDIR@
 LIBOBJS = @LIBOBJS@
+LIBOPENOBEX_CFLAGS = @LIBOPENOBEX_CFLAGS@
+LIBOPENOBEX_LIBS = @LIBOPENOBEX_LIBS@
 LIBS = @LIBS@
 LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@
 LIBSOUP_LIBS = @LIBSOUP_LIBS@
@@ -185,8 +186,6 @@ LIBTOOL = @LIBTOOL@
 LN_S = @LN_S@
 LTLIBOBJS = @LTLIBOBJS@
 MAKEINFO = @MAKEINFO@
-MCALB_CFLAGS = @MCALB_CFLAGS@
-MCALB_LIBS = @MCALB_LIBS@
 MKDIR_P = @MKDIR_P@
 MKINSTALLDIRS = @MKINSTALLDIRS@
 MODIFY_SYNCCOMPARE = @MODIFY_SYNCCOMPARE@
@@ -222,6 +221,7 @@ SYNTHESIS = @SYNTHESIS@
 SYNTHESISSRC = @SYNTHESISSRC@
 SYNTHESIS_CFLAGS = @SYNTHESIS_CFLAGS@
 SYNTHESIS_DEP = @SYNTHESIS_DEP@
+SYNTHESIS_ENGINE = @SYNTHESIS_ENGINE@
 SYNTHESIS_LIB = @SYNTHESIS_LIB@
 SYNTHESIS_LIBS = @SYNTHESIS_LIBS@
 SYNTHESIS_SRC = @SYNTHESIS_SRC@
@@ -233,8 +233,6 @@ UNIQUE_LIBS = @UNIQUE_LIBS@
 USE_NLS = @USE_NLS@
 VERSION = @VERSION@
 XGETTEXT = @XGETTEXT@
-XMLRPC_CFLAGS = @XMLRPC_CFLAGS@
-XMLRPC_LIBS = @XMLRPC_LIBS@
 XSLT = @XSLT@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
index dc42ae9..c7b0d3a 100644 (file)
@@ -560,7 +560,7 @@ void EvolutionCalendarSource::removeItem(const string &luid)
 icalcomponent *EvolutionCalendarSource::retrieveItem(const ItemID &id)
 {
     GError *gerror = NULL;
-    icalcomponent *comp = NULL;
+    icalcomponent *comp;
 
     if (!e_cal_get_object(m_calendar,
                           id.m_uid.c_str(),
@@ -582,32 +582,8 @@ string EvolutionCalendarSource::retrieveItemAsString(const ItemID &id)
     eptr<char> icalstr;
 
     icalstr = e_cal_get_component_as_string(m_calendar, comp);
-
     if (!icalstr) {
-        // One reason why e_cal_get_component_as_string() can fail is
-        // that it uses a TZID which has no corresponding VTIMEZONE
-        // definition. Evolution GUI ignores the TZID and interprets
-        // the times as local time. Do the same when exporting the
-        // event by removing the bogus TZID.
-        icalproperty *prop = icalcomponent_get_first_property (comp,
-                                                               ICAL_ANY_PROPERTY);
-
-        while (prop) {
-            icalparameter *param = icalproperty_get_first_parameter(prop,
-                                                                    ICAL_TZID_PARAMETER);
-            while (param) {
-                icalproperty_remove_parameter_by_kind(prop, ICAL_TZID_PARAMETER);
-                param = icalproperty_get_next_parameter (prop, ICAL_TZID_PARAMETER);
-            }
-            prop = icalcomponent_get_next_property (comp,
-                                                    ICAL_ANY_PROPERTY);
-        }
-
-        // now try again
-        icalstr = icalcomponent_as_ical_string(comp);
-        if (!icalstr) {
-            throwError(string("could not encode item as iCalendar: ") + id.getLUID());
-        }
+        throwError(string("could not encode item as iCal: ") + id.getLUID());
     }
 
     /*
index 4b9059a..49ef3d3 100644 (file)
@@ -91,14 +91,14 @@ static RegisterSyncSource registerMe("Evolution Calendar/Task List/Memos",
 #endif
                                      createSource,
                                      "Evolution Calendar = calendar = events = evolution-events\n"
-                                     "   iCalendar 2.0 (default) = text/calendar\n"
+                                     "   iCalendar 2.0 (default) = text/calendar)\n"
                                      "   vCalendar 1.0 = text/x-calendar\n"
                                      "Evolution Task List = Evolution Tasks = todo = tasks = evolution-tasks\n"
-                                     "   iCalendar 2.0 (default) = text/calendar\n"
+                                     "   iCalendar 2.0 (default) = text/calendar)\n"
                                      "   vCalendar 1.0 = text/x-calendar\n"
                                      "Evolution Memos = memo = memos = evolution-memos\n"
                                      "   plain text in UTF-8 (default) = text/plain\n"
-                                     "   iCalendar 2.0 = text/calendar\n"
+                                     "   iCalendar 2.0 = text/calendar)\n"
                                      "   vCalendar 1.0 = text/x-calendar\n"
                                      "   The later format is not tested because none of the\n"
                                      "   supported SyncML servers accepts it.\n",
@@ -301,6 +301,8 @@ SYNCEVOLUTION_TEST_SUITE_REGISTRATION(EvolutionCalendarTest);
 
 #endif // ENABLE_UNIT_TESTS
 
+#ifdef ENABLE_INTEGRATION_TESTS
+
 namespace {
 #if 0
 }
@@ -337,6 +339,7 @@ public:
 } memoTest;
 
 }
+#endif // ENABLE_INTEGRATION_TESTS
 
 #endif // ENABLE_ECAL
 
index 4756045..3b40efc 100644 (file)
@@ -142,6 +142,8 @@ protected:
 SYNCEVOLUTION_TEST_SUITE_REGISTRATION(EvolutionContactTest);
 #endif // ENABLE_UNIT_TESTS
 
+#ifdef ENABLE_INTEGRATION_TESTS
+
 namespace {
 #if 0
 }
@@ -180,6 +182,7 @@ public:
 } vCard30Test;
 
 }
+#endif // ENABLE_INTEGRATION_TESTS
 
 #endif // ENABLE_EBOOK
 
index 8847fac..23bf672 100644 (file)
@@ -42,6 +42,7 @@ syncecal_la_CPPFLAGS = -D_GNU_SOURCE \
        -De_cal_tzlookup_ecal=syncevolution_tzlookup_ecal \
        -De_cal_tzlookup_icomp=syncevolution_tzlookup_icomp \
        -De_cal_match_tzid=syncevolution_match_tzid \
+       -DENABLE_INTEGRATION_TESTS \
        $(AM_CPPFLAGS)
 syncecal_la_LDFLAGS = -module -avoid-version -ldl
 syncecal_la_CXXFLAGS = $(SYNCEVOLUTION_CXXFLAGS)
@@ -49,4 +50,4 @@ syncecal_la_CXXFLAGS = $(SYNCEVOLUTION_CXXFLAGS)
 syncebook_la_SOURCES = $(SYNCEBOOK_SOURCES)
 syncebook_la_LIBADD = $(EBOOK_LIBS) ../../syncevo/libsyncevolution.la
 syncebook_la_LDFLAGS = -module -avoid-version 
-syncebook_la_CXXFLAGS = $(SYNCEVOLUTION_CXXFLAGS)
+syncebook_la_CXXFLAGS = $(SYNCEVOLUTION_CXXFLAGS) -DENABLE_INTEGRATION_TESTS
index c00505b..3753750 100644 (file)
@@ -126,6 +126,8 @@ AUTOMAKE = @AUTOMAKE@
 AWK = @AWK@
 BACKEND_CPPFLAGS = @BACKEND_CPPFLAGS@
 BACKEND_DEFINES = @BACKEND_DEFINES@
+BLUEZ_CFLAGS = @BLUEZ_CFLAGS@
+BLUEZ_LIBS = @BLUEZ_LIBS@
 BOOST_CPPFLAGS = @BOOST_CPPFLAGS@
 BOOST_LDFLAGS = @BOOST_LDFLAGS@
 CATALOGS = @CATALOGS@
@@ -133,7 +135,6 @@ CATOBJEXT = @CATOBJEXT@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
-CLEAN_CLIENT_SRC = @CLEAN_CLIENT_SRC@
 CORE_LDADD_DEP = @CORE_LDADD_DEP@
 CPP = @CPP@
 CPPFLAGS = @CPPFLAGS@
@@ -146,8 +147,10 @@ CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
 DATADIRNAME = @DATADIRNAME@
 DBUS_BINDING_TOOL = @DBUS_BINDING_TOOL@
+DBUS_CFLAGS = @DBUS_CFLAGS@
 DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@
 DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@
+DBUS_LIBS = @DBUS_LIBS@
 DBUS_SERVICES_DIR = @DBUS_SERVICES_DIR@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
@@ -174,11 +177,7 @@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
 GLIB_LIBS = @GLIB_LIBS@
 GMOFILES = @GMOFILES@
 GMSGFMT = @GMSGFMT@
-GOBJECT_CFLAGS = @GOBJECT_CFLAGS@
-GOBJECT_LIBS = @GOBJECT_LIBS@
 GREP = @GREP@
-GTHREAD_CFLAGS = @GTHREAD_CFLAGS@
-GTHREAD_LIBS = @GTHREAD_LIBS@
 GTK_BUILDER_CONV = @GTK_BUILDER_CONV@
 GUI_CFLAGS = @GUI_CFLAGS@
 GUI_DESKTOP_FILES = @GUI_DESKTOP_FILES@
@@ -202,6 +201,8 @@ KEYRING_LIBS = @KEYRING_LIBS@
 LDFLAGS = @LDFLAGS@
 LIBEXECDIR = @LIBEXECDIR@
 LIBOBJS = @LIBOBJS@
+LIBOPENOBEX_CFLAGS = @LIBOPENOBEX_CFLAGS@
+LIBOPENOBEX_LIBS = @LIBOPENOBEX_LIBS@
 LIBS = @LIBS@
 LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@
 LIBSOUP_LIBS = @LIBSOUP_LIBS@
@@ -209,8 +210,6 @@ LIBTOOL = @LIBTOOL@
 LN_S = @LN_S@
 LTLIBOBJS = @LTLIBOBJS@
 MAKEINFO = @MAKEINFO@
-MCALB_CFLAGS = @MCALB_CFLAGS@
-MCALB_LIBS = @MCALB_LIBS@
 MKDIR_P = @MKDIR_P@
 MKINSTALLDIRS = @MKINSTALLDIRS@
 MODIFY_SYNCCOMPARE = @MODIFY_SYNCCOMPARE@
@@ -246,6 +245,7 @@ SYNTHESIS = @SYNTHESIS@
 SYNTHESISSRC = @SYNTHESISSRC@
 SYNTHESIS_CFLAGS = @SYNTHESIS_CFLAGS@
 SYNTHESIS_DEP = @SYNTHESIS_DEP@
+SYNTHESIS_ENGINE = @SYNTHESIS_ENGINE@
 SYNTHESIS_LIB = @SYNTHESIS_LIB@
 SYNTHESIS_LIBS = @SYNTHESIS_LIBS@
 SYNTHESIS_SRC = @SYNTHESIS_SRC@
@@ -257,8 +257,6 @@ UNIQUE_LIBS = @UNIQUE_LIBS@
 USE_NLS = @USE_NLS@
 VERSION = @VERSION@
 XGETTEXT = @XGETTEXT@
-XMLRPC_CFLAGS = @XMLRPC_CFLAGS@
-XMLRPC_LIBS = @XMLRPC_LIBS@
 XSLT = @XSLT@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
@@ -337,6 +335,7 @@ syncecal_la_CPPFLAGS = -D_GNU_SOURCE \
        -De_cal_tzlookup_ecal=syncevolution_tzlookup_ecal \
        -De_cal_tzlookup_icomp=syncevolution_tzlookup_icomp \
        -De_cal_match_tzid=syncevolution_match_tzid \
+       -DENABLE_INTEGRATION_TESTS \
        $(AM_CPPFLAGS)
 
 syncecal_la_LDFLAGS = -module -avoid-version -ldl
@@ -344,7 +343,7 @@ syncecal_la_CXXFLAGS = $(SYNCEVOLUTION_CXXFLAGS)
 syncebook_la_SOURCES = $(SYNCEBOOK_SOURCES)
 syncebook_la_LIBADD = $(EBOOK_LIBS) ../../syncevo/libsyncevolution.la
 syncebook_la_LDFLAGS = -module -avoid-version 
-syncebook_la_CXXFLAGS = $(SYNCEVOLUTION_CXXFLAGS)
+syncebook_la_CXXFLAGS = $(SYNCEVOLUTION_CXXFLAGS) -DENABLE_INTEGRATION_TESTS
 all: all-am
 
 .SUFFIXES:
index cb3a39b..37a9c94 100644 (file)
@@ -31,6 +31,9 @@ if test "x${EDSFOUND}" = "xno"; then
               PKG_CHECK_MODULES(EPACKAGE, [$pkg_emodules_10], EDSFOUND=yes, [EDSFOUND=no])
       fi
 fi
+AC_SUBST(EPACKAGE_CFLAGS)
+AC_SUBST(EPACKAGE_LIBS)
+BACKEND_CPPFLAGS="$BACKEND_CPPFLAGS $EPACKAGE_CFLAGS"
 
 dnl check for Evolution calendar packages
 PKG_CHECK_MODULES(ECAL, [$pkg_ecal_12], ECALFOUND=yes, [ECALFOUND=no])
@@ -40,6 +43,9 @@ if test "x${ECALFOUND}" = "xno"; then
                PKG_CHECK_MODULES(ECAL, [$pkg_ecal_10], ECALFOUND=yes, [ECALFOUND=no])
        fi
 fi
+AC_SUBST(ECAL_CFLAGS)
+AC_SUBST(ECAL_LIBS)
+BACKEND_CPPFLAGS="$BACKEND_CPPFLAGS $ECAL_CFLAGS"
 
 dnl check for Evolution contact packages
 PKG_CHECK_MODULES(EBOOK, [$pkg_ebook_12], EBOOKFOUND=yes, [EBOOKFOUND=no])
@@ -49,6 +55,9 @@ if test "x${EBOOKFOUND}" = "xno"; then
                PKG_CHECK_MODULES(EBOOK, [$pkg_ebook_10], EBOOKFOUND=yes, [EBOOKFOUND=no])
        fi
 fi
+AC_SUBST(EBOOK_CFLAGS)
+AC_SUBST(EBOOK_LIBS)
+BACKEND_CPPFLAGS="$BACKEND_CPPFLAGS $EBOOK_CFLAGS"
 
 AC_ARG_ENABLE_BACKEND(ebook, evolution,
                       AS_HELP_STRING([--disable-ebook], [disable access to Evolution addressbooks (must be used to compile without it)]),
@@ -66,9 +75,6 @@ if test "$enable_ebook" = "yes"; then
         test "x${EBOOKFOUND}" == "xyes" || AC_MSG_ERROR([--enable-ebook requires pkg-config information for libebook, which was not found])
         AC_DEFINE(ENABLE_EBOOK, 1, [libebook available])
         enable_evo="yes"
-else
-        EBOOK_CFLAGS=
-        EBOOK_LIBS=
 fi
 
 AM_CONDITIONAL([ENABLE_ECAL], [test "$enable_ecal" == "yes"])
@@ -76,13 +82,11 @@ if test "$enable_ecal" = "yes"; then
         test "x${ECALFOUND}" == "xyes" || AC_MSG_ERROR([--enable-ecal requires pkg-config information for libecal, which was not found"])
         AC_DEFINE(ENABLE_ECAL, 1, [libecal available])
         enable_evo="yes"
-else
-        ECAL_CFLAGS=
-        ECAL_LIBS=
 fi
 
+need_glib="yes"
+
 if test "$enable_evo" = "yes"; then
-        need_glib="yes"
         if test "$EDSFOUND" = "yes"; then
                 AC_DEFINE(HAVE_EDS, 1, [evolution-dataserver available])
         else
@@ -92,5 +96,3 @@ else
         EPACKAGE_CFLAGS=
         EPACKAGE_LIBS=
 fi
-
-BACKEND_CPPFLAGS="$BACKEND_CPPFLAGS $EPACKAGE_CFLAGS $ECAL_CFLAGS $EBOOK_CFLAGS"
index 128f5be..9ebfddc 100644 (file)
@@ -63,20 +63,17 @@ static RegisterSyncSource registerMe("Files in one directory",
                                      createSource,
                                      "Files in one directory = file\n"
                                      "   Stores items in one directory as one file per item.\n"
-                                     "   The directory is selected via evolutionsource=[file://]<path>.\n"
-                                     "   It will only be created if the prefix is given, otherwise\n"
+                                     "   The directory is selected via [file://]<path>; it\n"
+                                     "   will only be created if the prefix is given, otherwise\n"
                                      "   it must exist already. Only items of the same type can\n"
                                      "   be synchronized and this type must be specified explicitly\n"
                                      "   with both mime type and version.\n"
-                                     "   Examples for type:\n"
+                                     "   Examples:\n"
                                      "      file:text/plain:1.0\n"
                                      "      file:text/x-vcard:2.1\n"
                                      "      file:text/vcard:3.0\n"
-                                     "      file:text/x-calendar:1.0\n"
-                                     "      file:text/calendar:2.0\n"
-                                     "   Examples for evolutionsource:\n"
-                                     "      /home/joe/datadir - directory must exist\n"
-                                     "      file:///tmp/scratch - directory is created\n",
+                                     "      file:text/x-vcalendar:1.0\n"
+                                     "      file:text/calendar:2.0\n",
                                      Values() +
                                      (Aliases("Files in one directory") + "file"));
 
@@ -101,6 +98,8 @@ SYNCEVOLUTION_TEST_SUITE_REGISTRATION(FileSyncSourceUnitTest);
 
 #endif // ENABLE_UNIT_TESTS
 
+#ifdef ENABLE_INTEGRATION_TESTS
+
 // The anonymous namespace ensures that we don't get
 // name clashes: although the classes and objects are
 // only defined in this file, the methods generated
@@ -172,6 +171,7 @@ public:
 } ITodo20Test;
 
 }
+#endif // ENABLE_INTEGRATION_TESTS
 
 #endif // ENABLE_FILE
 
index 7a2061d..69081f4 100644 (file)
@@ -19,7 +19,7 @@ SYNCFILE_SOURCES = \
 syncfile_la_SOURCES = $(SYNCFILE_SOURCES)
 syncfile_la_LIBADD = $(FILE_LIBS)
 syncfile_la_LDFLAGS = -module -avoid-version
-syncfile_la_CXXFLAGS = $(SYNCEVOLUTION_CXXFLAGS)
+syncfile_la_CXXFLAGS = $(SYNCEVOLUTION_CXXFLAGS) -DENABLE_INTEGRATION_TESTS
 # If you need special test cases for your sync source, then
 # install them here. Here's how the sqlite backend does that:
 #
index 4c0aaff..7c80edd 100644 (file)
@@ -99,6 +99,8 @@ AUTOMAKE = @AUTOMAKE@
 AWK = @AWK@
 BACKEND_CPPFLAGS = @BACKEND_CPPFLAGS@
 BACKEND_DEFINES = @BACKEND_DEFINES@
+BLUEZ_CFLAGS = @BLUEZ_CFLAGS@
+BLUEZ_LIBS = @BLUEZ_LIBS@
 BOOST_CPPFLAGS = @BOOST_CPPFLAGS@
 BOOST_LDFLAGS = @BOOST_LDFLAGS@
 CATALOGS = @CATALOGS@
@@ -106,7 +108,6 @@ CATOBJEXT = @CATOBJEXT@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
-CLEAN_CLIENT_SRC = @CLEAN_CLIENT_SRC@
 CORE_LDADD_DEP = @CORE_LDADD_DEP@
 CPP = @CPP@
 CPPFLAGS = @CPPFLAGS@
@@ -119,8 +120,10 @@ CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
 DATADIRNAME = @DATADIRNAME@
 DBUS_BINDING_TOOL = @DBUS_BINDING_TOOL@
+DBUS_CFLAGS = @DBUS_CFLAGS@
 DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@
 DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@
+DBUS_LIBS = @DBUS_LIBS@
 DBUS_SERVICES_DIR = @DBUS_SERVICES_DIR@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
@@ -147,11 +150,7 @@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
 GLIB_LIBS = @GLIB_LIBS@
 GMOFILES = @GMOFILES@
 GMSGFMT = @GMSGFMT@
-GOBJECT_CFLAGS = @GOBJECT_CFLAGS@
-GOBJECT_LIBS = @GOBJECT_LIBS@
 GREP = @GREP@
-GTHREAD_CFLAGS = @GTHREAD_CFLAGS@
-GTHREAD_LIBS = @GTHREAD_LIBS@
 GTK_BUILDER_CONV = @GTK_BUILDER_CONV@
 GUI_CFLAGS = @GUI_CFLAGS@
 GUI_DESKTOP_FILES = @GUI_DESKTOP_FILES@
@@ -175,6 +174,8 @@ KEYRING_LIBS = @KEYRING_LIBS@
 LDFLAGS = @LDFLAGS@
 LIBEXECDIR = @LIBEXECDIR@
 LIBOBJS = @LIBOBJS@
+LIBOPENOBEX_CFLAGS = @LIBOPENOBEX_CFLAGS@
+LIBOPENOBEX_LIBS = @LIBOPENOBEX_LIBS@
 LIBS = @LIBS@
 LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@
 LIBSOUP_LIBS = @LIBSOUP_LIBS@
@@ -182,8 +183,6 @@ LIBTOOL = @LIBTOOL@
 LN_S = @LN_S@
 LTLIBOBJS = @LTLIBOBJS@
 MAKEINFO = @MAKEINFO@
-MCALB_CFLAGS = @MCALB_CFLAGS@
-MCALB_LIBS = @MCALB_LIBS@
 MKDIR_P = @MKDIR_P@
 MKINSTALLDIRS = @MKINSTALLDIRS@
 MODIFY_SYNCCOMPARE = @MODIFY_SYNCCOMPARE@
@@ -219,6 +218,7 @@ SYNTHESIS = @SYNTHESIS@
 SYNTHESISSRC = @SYNTHESISSRC@
 SYNTHESIS_CFLAGS = @SYNTHESIS_CFLAGS@
 SYNTHESIS_DEP = @SYNTHESIS_DEP@
+SYNTHESIS_ENGINE = @SYNTHESIS_ENGINE@
 SYNTHESIS_LIB = @SYNTHESIS_LIB@
 SYNTHESIS_LIBS = @SYNTHESIS_LIBS@
 SYNTHESIS_SRC = @SYNTHESIS_SRC@
@@ -230,8 +230,6 @@ UNIQUE_LIBS = @UNIQUE_LIBS@
 USE_NLS = @USE_NLS@
 VERSION = @VERSION@
 XGETTEXT = @XGETTEXT@
-XMLRPC_CFLAGS = @XMLRPC_CFLAGS@
-XMLRPC_LIBS = @XMLRPC_LIBS@
 XSLT = @XSLT@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
@@ -299,7 +297,7 @@ SYNCFILE_SOURCES = \
 syncfile_la_SOURCES = $(SYNCFILE_SOURCES)
 syncfile_la_LIBADD = $(FILE_LIBS)
 syncfile_la_LDFLAGS = -module -avoid-version
-syncfile_la_CXXFLAGS = $(SYNCEVOLUTION_CXXFLAGS)
+syncfile_la_CXXFLAGS = $(SYNCEVOLUTION_CXXFLAGS) -DENABLE_INTEGRATION_TESTS
 all: all-am
 
 .SUFFIXES:
diff --git a/src/backends/maemo/MaemoCalendarSource.cpp b/src/backends/maemo/MaemoCalendarSource.cpp
deleted file mode 100644 (file)
index de56e92..0000000
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * Copyright (C) 2007-2009 Patrick Ohly <patrick.ohly@gmx.de>
- * Copyright (C) 2009 Intel Corporation
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) version 3.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301  USA
- */
-
-#include "config.h"
-
-#ifdef ENABLE_MAEMO_CALENDAR
-
-#include "MaemoCalendarSource.h"
-
-#include <CalendarErrors.h>
-
-#include <boost/algorithm/string/case_conv.hpp>
-
-#include <errno.h>
-#include <unistd.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <syncevo/util.h>
-
-#include <sstream>
-#include <fstream>
-
-#include <syncevo/declarations.h>
-SE_BEGIN_CXX
-
-MaemoCalendarSource::MaemoCalendarSource(int EntryType, int EntryFormat,
-                                         const SyncSourceParams &params) :
-    TrackingSyncSource(params),
-    entry_type(EntryType), entry_format(EntryFormat)
-{
-    mc = CMulticalendar::MCInstance();
-    cal = NULL;
-    if (!mc) {
-        throwError("Could not connect to Maemo Calendar backend");
-    }
-}
-
-const char *MaemoCalendarSource::getMimeType() const
-{
-    switch (entry_format) {
-    case -1: return "text/plain";
-    case ICAL_TYPE: return "text/calendar";
-    case VCAL_TYPE: return "text/x-calendar";
-    default: return NULL;
-    }
-}
-
-const char *MaemoCalendarSource::getMimeVersion() const
-{
-    switch (entry_format) {
-    case -1: return "1.0";
-    case ICAL_TYPE: return "2.0";
-    case VCAL_TYPE: return "1.0";
-    default: return NULL;
-    }
-}
-
-void MaemoCalendarSource::open()
-{
-    string id = getDatabaseID();
-    const string id_prefix("id:");
-    int err;
-
-    if (!id.size()) {
-        CCalendar *def_cal = mc->getSynchronizedCalendar();
-        // generate a new instance of default calendar,
-        // which we can safely delete in the close() method
-        cal = mc->getCalendarById(def_cal->getCalendarId(), err);
-    }
-    else if (boost::starts_with(id, id_prefix)) {
-        istringstream uri(id.substr(id_prefix.size()));
-        int cid;
-        uri >> cid;
-        cal = mc->getCalendarById(cid, err);
-    }
-    else {
-        // try the calendar's name
-        cal = mc->getCalendarByName(id, err);
-    }
-
-    if (!cal) {
-        throwError(string("not found: ") + id);
-    }
-    conv = new ICalConverter;
-    conv->setSyncing(true); // not sure what this does, but may as well tell the truth
-}
-
-void MaemoCalendarSource::close()
-{
-    delete conv;
-    conv = NULL;
-    delete cal;
-    cal = NULL;
-    // since timestamps are rounded down to nearest second,
-    // sleep until next second, just in case
-    sleep(1);
-}
-
-MaemoCalendarSource::Databases MaemoCalendarSource::getDatabases()
-{
-    // getDefaultCalendar returns the Private calendar,
-    // getSynchronizedCalendar returns the Main calendar
-    // (the same calendar Nokia PC Suite would sync with)
-    CCalendar *def_cal = mc->getSynchronizedCalendar();
-    int def_id = def_cal->getCalendarId();
-    vector< CCalendar * > calendars = mc->getListCalFromMc();
-    Databases result;
-
-    BOOST_FOREACH(CCalendar * c, calendars) {
-        int id = c->getCalendarId();
-        ostringstream uri;
-        uri << "id:" << id;
-        result.push_back(Database(c->getCalendarName(),
-                                  uri.str(),
-                                  id == def_id));
-    }
-
-    mc->releaseListCalendars(calendars);
-
-    return result;
-}
-
-void MaemoCalendarSource::listAllItems(RevisionMap_t &revisions)
-{
-#if 0 /* this code exposes a bug in calendar-backend, https://bugs.maemo.org/show_bug.cgi?id=8277 */
-    // I've found no way to query the last modified time of a component
-    // without getting the whole component.
-    // This limit should hopefully reduce memory usage of that a bit
-    static const int limit = 1024;
-    int ofs = 0, err;
-    vector< CComponent * > comps;
-
-    for (;;) {
-        comps = cal->getComponents(entry_type, -1, -1,
-                                   limit, ofs, err);
-        // Note that non-success value in "err" is not necessarily fatal,
-        // I seem to get a nonspecific "application error" if there are no
-        // components of the specified type, so just ignore it for now
-        if (!comps.size())
-            break;
-        BOOST_FOREACH(CComponent * c, comps) {
-            revisions[c->getId()] = get_revision(c);
-            // Testing shows that the backend doesn't free the memory itself
-            delete c;
-            ofs++;
-        }
-    }
-#else
-    // this avoids the calendar-backend bug, but may use unlimited memory;
-    // hopefully the users aren't saving their entire life here!
-    int err;
-    vector< CComponent * > comps;
-
-    comps = cal->getComponents(entry_type, -1, -1, err);
-    BOOST_FOREACH(CComponent * c, comps) {
-        revisions[c->getId()] = get_revision(c);
-        delete c;
-    }
-#endif
-}
-
-void MaemoCalendarSource::readItem(const string &uid, std::string &item, bool raw)
-{
-    int err;
-    CComponent * c = cal->getEntry(uid, entry_type, err);
-    if (!c) {
-        throwError(string("retrieving item: ") + uid);
-    }
-    if (entry_format == -1) {
-        item = c->getDescription();
-        err = CALENDAR_OPERATION_SUCCESSFUL;
-    } else {
-        item = conv->localToIcalVcal(c, FileType(entry_format), err);
-    }
-    delete c;
-    if (err != CALENDAR_OPERATION_SUCCESSFUL) {
-        throwError(string("generating ical for item: ") + uid);
-    }
-}
-
-TrackingSyncSource::InsertItemResult MaemoCalendarSource::insertItem(const string &uid, const std::string &item, bool raw)
-{
-    int err;
-    CComponent *c;
-    bool r, u = false;
-    TrackingSyncSource::InsertItemResult result;
-
-    if (cal->getCalendarType() == BIRTHDAY_CALENDAR) {
-        // stubbornly refuse to try this
-        throwError(string("can't sync smart calendar ") + cal->getCalendarName());
-    }
-
-    if (entry_format == -1) {
-        c = new CJournal(item);
-        err = CALENDAR_OPERATION_SUCCESSFUL;
-    } else {
-        vector< CComponent * > comps = conv->icalVcalToLocal(item, FileType(entry_format), err);
-        // Note that a non-success value in "err" is not necessarily fatal,
-        // I seem to get a nonspecific "application error" on certain types of
-        // barely-legal input (mostly on todo entries), yet a component is returned
-        if (!comps.size()) {
-            if (err != CALENDAR_OPERATION_SUCCESSFUL) {
-                throwError(string("parsing ical: ") + item);
-            } else {
-                throwError(string("no events in ical: ") + item);
-            }
-        }
-        vector< CComponent * >::iterator it = comps.begin();
-        if (comps.size() > 1) {
-            for (; it != comps.end(); it++) {
-                delete (*it);
-            }
-            throwError(string("too many events in ical: ") + item);
-        }
-        c = *it;
-    }
-
-    // I wish there were public modifyEntry and addEntry methods,
-    // so I wouldn't need the switches
-    // (using the batch-operation modifyComponents and addComponents methods on
-    // individual items would probably be inefficient)
-    if (uid.size()) {
-        c->setId(uid);
-        switch (entry_type) {
-        case EVENT:   r = cal->modifyEvent  (static_cast< CEvent   * >(c), err); break;
-        case TODO:    r = cal->modifyTodo   (static_cast< CTodo    * >(c), err); break;
-        case JOURNAL: r = cal->modifyJournal(static_cast< CJournal * >(c), err); break;
-        default: r = false; err = CALENDAR_SYSTEM_ERROR;
-        }
-        if (!r) {
-            throwError(string("updating item ") + uid);
-        }
-    } else {
-        switch (entry_type) {
-        case EVENT:   r = cal->addEvent  (static_cast< CEvent   * >(c), err); break;
-        case TODO:    r = cal->addTodo   (static_cast< CTodo    * >(c), err); break;
-        case JOURNAL: r = cal->addJournal(static_cast< CJournal * >(c), err); break;
-        default: r = false; err = CALENDAR_SYSTEM_ERROR;
-        }
-        if (!r) {
-            throwError(string("creating item "));
-        }
-        if (err == CALENDAR_ENTRY_DUPLICATED) {
-            u = true;
-        }
-    }
-
-    result = InsertItemResult(c->getId(), get_revision(c), u);
-    delete c;
-    return result;
-}
-
-
-void MaemoCalendarSource::removeItem(const string &uid)
-{
-    int err;
-    cal->deleteComponent(uid, err);
-    if (err != CALENDAR_OPERATION_SUCCESSFUL) {
-        throwError(string("deleting item: ") + uid);
-    }
-}
-
-string MaemoCalendarSource::get_revision(CComponent * c)
-{
-    time_t mtime = c->getLastModified();
-
-    ostringstream revision;
-    revision << mtime;
-
-    return revision.str();
-}
-
-SE_END_CXX
-
-#endif /* ENABLE_MAEMO_CALENDAR */
-
-#ifdef ENABLE_MODULES
-# include "MaemoCalendarSourceRegister.cpp"
-#endif
diff --git a/src/backends/maemo/MaemoCalendarSource.h b/src/backends/maemo/MaemoCalendarSource.h
deleted file mode 100644 (file)
index af500a2..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2007-2009 Patrick Ohly <patrick.ohly@gmx.de>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) version 3.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301  USA
- */
-
-#ifndef INCL_MAEMOCALENDARSOURCE
-#define INCL_MAEMOCALENDARSOURCE
-
-#include <syncevo/TrackingSyncSource.h>
-
-#ifdef ENABLE_MAEMO_CALENDAR
-
-#include <CMulticalendar.h>
-#include <ICalConverter.h>
-
-#include <memory>
-#include <boost/noncopyable.hpp>
-
-#include <syncevo/declarations.h>
-SE_BEGIN_CXX
-
-/**
- * Implement access to Maemo calendar.
- * Change tracking is done by using the last-modified time.
- * It might be possible to improve on it by taking the last sync time
- * and calling the getAllAdded/Modified/Deleted(...) methods provided by
- * the CCalendar class, instead of comparing every single record in
- * the database like TrackingSyncSource probably needs to do otherwise.
- */
-class MaemoCalendarSource : public TrackingSyncSource, private boost::noncopyable
-{
-  public:
-    MaemoCalendarSource(int EntryType, int EntryFormat,
-                        const SyncSourceParams &params);
-
-
- protected:
-    /* implementation of SyncSource interface */
-    virtual void open();
-    virtual void close();
-    virtual Databases getDatabases();
-    virtual const char *getMimeType() const;
-    virtual const char *getMimeVersion() const;
-
-    /* implementation of TrackingSyncSource interface */
-    virtual void listAllItems(RevisionMap_t &revisions);
-    virtual InsertItemResult insertItem(const string &luid, const std::string &item, bool raw);
-    void readItem(const std::string &luid, std::string &item, bool raw);
-    virtual void removeItem(const string &uid);
-
- private:
-    CMulticalendar *mc; /**< multicalendar */
-    CCalendar *cal;   /**< calendar */
-    int entry_type;   /**< entry type */
-    int entry_format; /**< entry format */
-    ICalConverter *conv; /**< converter */
-
-    string get_revision(CComponent * c);
-};
-
-SE_END_CXX
-
-#endif // ENABLE_MAEMO_CALENDAR
-#endif // INCL_MAEMOCALENDARSOURCE
diff --git a/src/backends/maemo/MaemoCalendarSourceRegister.cpp b/src/backends/maemo/MaemoCalendarSourceRegister.cpp
deleted file mode 100644 (file)
index 0fcc6bc..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 2008-2009 Patrick Ohly <patrick.ohly@gmx.de>
- * Copyright (C) 2009 Intel Corporation
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) version 3.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301  USA
- */
-
-#include "MaemoCalendarSource.h"
-#include "test.h"
-
-#include <syncevo/declarations.h>
-SE_BEGIN_CXX
-
-static SyncSource *createSource(const SyncSourceParams &params)
-{
-    SourceType sourceType = SyncSource::getSourceType(params.m_nodes);
-    bool isMe = sourceType.m_backend == "Maemo Calendar";
-#ifndef ENABLE_MAEMO_CALENDAR
-    if (isMe) return RegisterSyncSource::InactiveSource;
-#else
-    bool maybeMe = sourceType.m_backend == "calendar";
-
-    if (isMe || maybeMe) {
-        if (sourceType.m_format == "" || sourceType.m_format == "text/calendar") {
-            return new MaemoCalendarSource(EVENT, ICAL_TYPE, params);
-        } else if (sourceType.m_format == "text/x-vcalendar") {
-            return new MaemoCalendarSource(EVENT, VCAL_TYPE, params);
-        } else {
-            return NULL;
-        }
-    }
-#endif
-
-    isMe = sourceType.m_backend == "Maemo Tasks";
-#ifndef ENABLE_MAEMO_CALENDAR
-    if (isMe) return RegisterSyncSource::InactiveSource;
-#else
-    maybeMe = sourceType.m_backend == "todo";
-
-    if (isMe || maybeMe) {
-        if (sourceType.m_format == "" || sourceType.m_format == "text/calendar") {
-            return new MaemoCalendarSource(TODO, ICAL_TYPE, params);
-        } else if (sourceType.m_format == "text/x-vcalendar") {
-            return new MaemoCalendarSource(TODO, VCAL_TYPE, params);
-        } else {
-            return NULL;
-        }
-    }
-#endif
-
-    isMe = sourceType.m_backend == "Maemo Notes";
-#ifndef ENABLE_MAEMO_CALENDAR
-    if (isMe) return RegisterSyncSource::InactiveSource;
-#else
-    maybeMe = sourceType.m_backend == "memo";
-
-    if (isMe || maybeMe) {
-        if (sourceType.m_format == "" || sourceType.m_format == "text/plain") {
-            return new MaemoCalendarSource(JOURNAL, -1, params);
-        } else if (sourceType.m_format == "text/calendar") {
-            return new MaemoCalendarSource(JOURNAL, ICAL_TYPE, params);
-        } else if (sourceType.m_format == "text/x-vcalendar") {
-            return new MaemoCalendarSource(JOURNAL, VCAL_TYPE, params);
-        } else {
-            return NULL;
-        }
-    }
-#endif
-
-    return NULL;
-}
-
-static RegisterSyncSource registerMe("Maemo Calendar/Tasks/Notes",
-#ifdef ENABLE_MAEMO_CALENDAR
-                                     true,
-#else
-                                     false,
-#endif
-                                     createSource,
-                                     "Maemo Calendar = calendar = events = maemo-events\n"
-                                     "   iCalendar 2.0 (default) = text/calendar\n"
-                                     "   vCalendar 1.0 = text/x-vcalendar\n"
-                                     "Maemo Tasks = todo = tasks = maemo-tasks\n"
-                                     "   iCalendar 2.0 (default) = text/calendar\n"
-                                     "   vCalendar 1.0 = text/x-vcalendar\n"
-                                     "Maemo Notes = memo = memos = notes = journal = maemo-notes\n"
-                                     "   plain text in UTF-8 (default) = text/plain\n"
-                                     "   iCalendar 2.0 = text/calendar\n"
-                                     "   vCalendar 1.0 = text/x-vcalendar\n",
-                                     Values() +
-                                     (Aliases("Maemo Calendar") + "maemo-events") +
-                                     (Aliases("Maemo Tasks") + "maemo-tasks") +
-                                     (Aliases("Maemo Notes") + "maemo-notes"));
-
-#ifdef ENABLE_MAEMO_CALENDAR
-#ifdef ENABLE_UNIT_TESTS
-
-class MaemoCalendarSourceUnitTest : public CppUnit::TestFixture {
-    CPPUNIT_TEST_SUITE(MaemoCalendarSourceUnitTest);
-    CPPUNIT_TEST(testInstantiate);
-    CPPUNIT_TEST_SUITE_END();
-
-protected:
-    void testInstantiate() {
-        boost::shared_ptr<SyncSource> source;
-        source.reset(SyncSource::createTestingSource("calendar", "calendar", true));
-        source.reset(SyncSource::createTestingSource("calendar", "maemo-events", true));
-        source.reset(SyncSource::createTestingSource("calendar", "Maemo Calendar:text/calendar", true));
-    }
-};
-
-SYNCEVOLUTION_TEST_SUITE_REGISTRATION(MaemoCalendarSourceUnitTest);
-
-#endif // ENABLE_UNIT_TESTS
-
-namespace {
-#if 0
-}
-#endif
-
-static class iCal20Test : public RegisterSyncSourceTest {
-public:
-    iCal20Test() : RegisterSyncSourceTest("ical20_maemo", "ical20") {}
-
-    virtual void updateConfig(ClientTestConfig &config) const
-    {
-        config.type = "maemo-events";
-    }
-} iCal20Test;
-
-static class iTodo20Test : public RegisterSyncSourceTest {
-public:
-    iTodo20Test() : RegisterSyncSourceTest("itodo20_maemo", "itodo20") {}
-
-    virtual void updateConfig(ClientTestConfig &config) const
-    {
-        config.type = "maemo-tasks";
-    }
-} iTodo20Test;
-
-static class MemoTest : public RegisterSyncSourceTest {
-public:
-    MemoTest() : RegisterSyncSourceTest("text_maemo", "text") {}
-
-    virtual void updateConfig(ClientTestConfig &config) const
-    {
-        config.type = "maemo-notes";
-    }
-} memoTest;
-
-}
-
-#endif // ENABLE_MAEMO_CALENDAR
-
-SE_END_CXX
diff --git a/src/backends/maemo/Makefile.am b/src/backends/maemo/Makefile.am
deleted file mode 100644 (file)
index 72bba11..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-AM_CPPFLAGS = -I$(srcdir)/../../ -I$(top_srcdir)/test $(BACKEND_CPPFLAGS)
-
-EXTRA_DIST = configure-sub.in
-
-SYNCSOURCES = syncmaemocal.la
-MOSTLYCLEANFILES = $(SYNCSOURCES)
-if ENABLE_MODULES
-backend_LTLIBRARIES = $(SYNCSOURCES)
-else
-noinst_LTLIBRARIES = $(SYNCSOURCES)
-endif
-
-MAINTAINERCLEANFILES = Makefile.in
-
-SYNCMAEMOCAL_SOURCES = \
-       MaemoCalendarSource.h \
-       MaemoCalendarSource.cpp
-
-syncmaemocal_la_SOURCES = $(SYNCMAEMOCAL_SOURCES)
-syncmaemocal_la_LIBADD = $(MCALB_LIBS)
-syncmaemocal_la_LDFLAGS = -module -avoid-version
-syncmaemocal_la_CXXFLAGS = $(SYNCEVOLUTION_CXXFLAGS)
diff --git a/src/backends/maemo/configure-sub.in b/src/backends/maemo/configure-sub.in
deleted file mode 100644 (file)
index b97da6f..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-dnl -*- mode: Autoconf; -*-
-dnl Invoke autogen.sh to produce a configure script.
-
-dnl Check for calendar-backend
-PKG_CHECK_MODULES(MCALB, calendar-backend, MCALBFOUND=yes, [MCALBFOUND=no])
-AC_SUBST(MCALB_CFLAGS)
-AC_SUBST(MCALB_LIBS)
-BACKEND_CPPFLAGS="$BACKEND_CPPFLAGS $MCALB_CFLAGS"
-
-AC_ARG_ENABLE_BACKEND(maemocal, maemo,
-                      AS_HELP_STRING([--enable-maemo-calendar],
-                                     [enable access to PIM data stored in Maemo 5 calendar application (default off)]),
-                     [enable_maemocal="$enableval"], [enable_maemocal="no"])
-
-if test "$enable_maemocal" = "yes"; then
-        test "x${MCALBFOUND}" == "xyes" || AC_MSG_ERROR([--enable-maemo-calendar requires pkg-config information for calendar-backend, which was not found])
-        AC_DEFINE(ENABLE_MAEMO_CALENDAR, 1, [Maemo 5 calendar available])
-fi
index d26ecfa..a72e26b 100644 (file)
@@ -100,6 +100,8 @@ AUTOMAKE = @AUTOMAKE@
 AWK = @AWK@
 BACKEND_CPPFLAGS = @BACKEND_CPPFLAGS@
 BACKEND_DEFINES = @BACKEND_DEFINES@
+BLUEZ_CFLAGS = @BLUEZ_CFLAGS@
+BLUEZ_LIBS = @BLUEZ_LIBS@
 BOOST_CPPFLAGS = @BOOST_CPPFLAGS@
 BOOST_LDFLAGS = @BOOST_LDFLAGS@
 CATALOGS = @CATALOGS@
@@ -107,7 +109,6 @@ CATOBJEXT = @CATOBJEXT@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
-CLEAN_CLIENT_SRC = @CLEAN_CLIENT_SRC@
 CORE_LDADD_DEP = @CORE_LDADD_DEP@
 CPP = @CPP@
 CPPFLAGS = @CPPFLAGS@
@@ -120,8 +121,10 @@ CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
 DATADIRNAME = @DATADIRNAME@
 DBUS_BINDING_TOOL = @DBUS_BINDING_TOOL@
+DBUS_CFLAGS = @DBUS_CFLAGS@
 DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@
 DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@
+DBUS_LIBS = @DBUS_LIBS@
 DBUS_SERVICES_DIR = @DBUS_SERVICES_DIR@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
@@ -148,11 +151,7 @@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
 GLIB_LIBS = @GLIB_LIBS@
 GMOFILES = @GMOFILES@
 GMSGFMT = @GMSGFMT@
-GOBJECT_CFLAGS = @GOBJECT_CFLAGS@
-GOBJECT_LIBS = @GOBJECT_LIBS@
 GREP = @GREP@
-GTHREAD_CFLAGS = @GTHREAD_CFLAGS@
-GTHREAD_LIBS = @GTHREAD_LIBS@
 GTK_BUILDER_CONV = @GTK_BUILDER_CONV@
 GUI_CFLAGS = @GUI_CFLAGS@
 GUI_DESKTOP_FILES = @GUI_DESKTOP_FILES@
@@ -176,6 +175,8 @@ KEYRING_LIBS = @KEYRING_LIBS@
 LDFLAGS = @LDFLAGS@
 LIBEXECDIR = @LIBEXECDIR@
 LIBOBJS = @LIBOBJS@
+LIBOPENOBEX_CFLAGS = @LIBOPENOBEX_CFLAGS@
+LIBOPENOBEX_LIBS = @LIBOPENOBEX_LIBS@
 LIBS = @LIBS@
 LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@
 LIBSOUP_LIBS = @LIBSOUP_LIBS@
@@ -183,8 +184,6 @@ LIBTOOL = @LIBTOOL@
 LN_S = @LN_S@
 LTLIBOBJS = @LTLIBOBJS@
 MAKEINFO = @MAKEINFO@
-MCALB_CFLAGS = @MCALB_CFLAGS@
-MCALB_LIBS = @MCALB_LIBS@
 MKDIR_P = @MKDIR_P@
 MKINSTALLDIRS = @MKINSTALLDIRS@
 MODIFY_SYNCCOMPARE = @MODIFY_SYNCCOMPARE@
@@ -220,6 +219,7 @@ SYNTHESIS = @SYNTHESIS@
 SYNTHESISSRC = @SYNTHESISSRC@
 SYNTHESIS_CFLAGS = @SYNTHESIS_CFLAGS@
 SYNTHESIS_DEP = @SYNTHESIS_DEP@
+SYNTHESIS_ENGINE = @SYNTHESIS_ENGINE@
 SYNTHESIS_LIB = @SYNTHESIS_LIB@
 SYNTHESIS_LIBS = @SYNTHESIS_LIBS@
 SYNTHESIS_SRC = @SYNTHESIS_SRC@
@@ -231,8 +231,6 @@ UNIQUE_LIBS = @UNIQUE_LIBS@
 USE_NLS = @USE_NLS@
 VERSION = @VERSION@
 XGETTEXT = @XGETTEXT@
-XMLRPC_CFLAGS = @XMLRPC_CFLAGS@
-XMLRPC_LIBS = @XMLRPC_LIBS@
 XSLT = @XSLT@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
index 5dddf23..6853116 100644 (file)
@@ -349,6 +349,16 @@ void SQLiteContactSource::deleteItem(const string& uid)
     deleteRevision(*m_trackingNode, uid);
 }
 
+void SQLiteContactSource::enableServerMode()
+{
+    SyncSourceAdmin::init(m_operations, this);
+}
+
+bool SQLiteContactSource::serverModeEnabled() const
+{
+    return m_operations.m_loadAdminData;
+}
+
 
 void SQLiteContactSource::beginSync(const std::string &lastToken, const std::string &resumeToken)
 {
index 91f7802..759b31a 100644 (file)
@@ -53,6 +53,7 @@ SE_BEGIN_CXX
  */
 class SQLiteContactSource : public SyncSource,
     virtual public SyncSourceSession,
+    virtual public SyncSourceAdmin,
     virtual public SyncSourceRevisions,
     virtual public SyncSourceDelete,
     virtual public SyncSourceLogging,
@@ -62,7 +63,7 @@ class SQLiteContactSource : public SyncSource,
     SQLiteContactSource(const SyncSourceParams &params) :
         SyncSource(params),
         m_trackingNode(new PrefixConfigNode("item-",
-                                        boost::shared_ptr<ConfigNode>(new SafeConfigNode(params.m_nodes.m_trackingNode))))
+                                            boost::shared_ptr<ConfigNode>(new SafeConfigNode(params.m_nodes.getTrackingNode()))))
         {
             SyncSourceSession::init(m_operations);
             SyncSourceDelete::init(m_operations);
@@ -82,6 +83,9 @@ class SQLiteContactSource : public SyncSource,
     virtual Databases getDatabases();
     virtual const char *getMimeType() const { return "text/x-vcard"; }
     virtual const char *getMimeVersion() const { return "2.1"; }
+    virtual void enableServerMode();
+    virtual bool serverModeEnabled() const;
+    virtual const char *getPeerMimeType() const {return getMimeType(); }
 
     /* Methods in SyncSource */
     virtual void getSynthesisInfo (SynthesisInfo &info, XMLConfigFragments &fragment);
diff --git a/src/backends/xmlrpc/Makefile.am b/src/backends/xmlrpc/Makefile.am
deleted file mode 100644 (file)
index 61beb4c..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-AM_CPPFLAGS = -I$(srcdir)/../../ -I$(top_srcdir)/test $(BACKEND_CPPFLAGS)
-
-EXTRA_DIST = configure-sub.in
-
-SYNCSOURCES = syncxmlrpc.la
-MOSTLYCLEANFILES = $(SYNCSOURCES)
-if ENABLE_MODULES
-backend_LTLIBRARIES = $(SYNCSOURCES)
-else
-noinst_LTLIBRARIES = $(SYNCSOURCES)
-endif
-
-MAINTAINERCLEANFILES = Makefile.in
-
-SYNCXMLRPC_SOURCES = \
-       XMLRPCSyncSource.h \
-       XMLRPCSyncSource.cpp
-
-syncxmlrpc_la_SOURCES = $(SYNCXMLRPC_SOURCES)
-syncxmlrpc_la_LIBADD = $(XMLRPC_LIBS)
-syncxmlrpc_la_LDFLAGS = -module -avoid-version
-syncxmlrpc_la_CXXFLAGS = $(SYNCEVOLUTION_CXXFLAGS)
-# If you need special test cases for your sync source, then
-# install them here. Here's how the sqlite backend does that:
-#
-#../../testcases/sqlite_vcard21.vcf: $(FUNAMBOL_SUBDIR)/test/test/testcases/vcard21.vcf
-#      mkdir -p ${@D}
-#      perl -e '$$_ = join("", <>); s/^(ADR|TEL|EMAIL|PHOTO).*?(?=^\S)//msg; s/;X-EVOLUTION-UI-SLOT=\d+//g; print;' $< >$@
-#all: ../../testcases/sqlite_vcard21.vcf
diff --git a/src/backends/xmlrpc/Makefile.in b/src/backends/xmlrpc/Makefile.in
deleted file mode 100644 (file)
index 191c500..0000000
+++ /dev/null
@@ -1,608 +0,0 @@
-# Makefile.in generated by automake 1.10.1 from Makefile.am.
-# @configure_input@
-
-# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2006, 2007, 2008  Free Software Foundation, Inc.
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-@SET_MAKE@
-
-VPATH = @srcdir@
-pkgdatadir = $(datadir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
-install_sh_DATA = $(install_sh) -c -m 644
-install_sh_PROGRAM = $(install_sh) -c
-install_sh_SCRIPT = $(install_sh) -c
-INSTALL_HEADER = $(INSTALL_DATA)
-transform = $(program_transform_name)
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-build_triplet = @build@
-host_triplet = @host@
-subdir = src/backends/xmlrpc
-DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4-repo/ax_boost_base.m4 \
-       $(top_srcdir)/m4/intltool.m4 $(top_srcdir)/configure.in
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
-       $(ACLOCAL_M4)
-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
-CONFIG_HEADER = $(top_builddir)/config.h
-CONFIG_CLEAN_FILES =
-am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
-am__vpath_adj = case $$p in \
-    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
-    *) f=$$p;; \
-  esac;
-am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
-am__installdirs = "$(DESTDIR)$(backenddir)"
-backendLTLIBRARIES_INSTALL = $(INSTALL)
-LTLIBRARIES = $(backend_LTLIBRARIES) $(noinst_LTLIBRARIES)
-am__DEPENDENCIES_1 =
-syncxmlrpc_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
-am__objects_1 = syncxmlrpc_la-XMLRPCSyncSource.lo
-am_syncxmlrpc_la_OBJECTS = $(am__objects_1)
-syncxmlrpc_la_OBJECTS = $(am_syncxmlrpc_la_OBJECTS)
-syncxmlrpc_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
-       $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(syncxmlrpc_la_CXXFLAGS) \
-       $(CXXFLAGS) $(syncxmlrpc_la_LDFLAGS) $(LDFLAGS) -o $@
-@ENABLE_MODULES_FALSE@am_syncxmlrpc_la_rpath =
-@ENABLE_MODULES_TRUE@am_syncxmlrpc_la_rpath = -rpath $(backenddir)
-DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
-depcomp = $(SHELL) $(top_srcdir)/depcomp
-am__depfiles_maybe = depfiles
-CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
-       $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
-LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
-       --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
-       $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
-CXXLD = $(CXX)
-CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
-       --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
-       $(LDFLAGS) -o $@
-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
-       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
-       --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
-       $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-CCLD = $(CC)
-LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
-       --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
-       $(LDFLAGS) -o $@
-SOURCES = $(syncxmlrpc_la_SOURCES)
-DIST_SOURCES = $(syncxmlrpc_la_SOURCES)
-ETAGS = etags
-CTAGS = ctags
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-ACLOCAL = @ACLOCAL@
-ADDRESSBOOK_CFLAGS = @ADDRESSBOOK_CFLAGS@
-ADDRESSBOOK_LIBS = @ADDRESSBOOK_LIBS@
-ALL_LINGUAS = @ALL_LINGUAS@
-AMTAR = @AMTAR@
-AR = @AR@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-BACKEND_CPPFLAGS = @BACKEND_CPPFLAGS@
-BACKEND_DEFINES = @BACKEND_DEFINES@
-BOOST_CPPFLAGS = @BOOST_CPPFLAGS@
-BOOST_LDFLAGS = @BOOST_LDFLAGS@
-CATALOGS = @CATALOGS@
-CATOBJEXT = @CATOBJEXT@
-CC = @CC@
-CCDEPMODE = @CCDEPMODE@
-CFLAGS = @CFLAGS@
-CLEAN_CLIENT_SRC = @CLEAN_CLIENT_SRC@
-CORE_LDADD_DEP = @CORE_LDADD_DEP@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CPPUNIT_CXXFLAGS = @CPPUNIT_CXXFLAGS@
-CPPUNIT_LDFLAGS = @CPPUNIT_LDFLAGS@
-CXX = @CXX@
-CXXCPP = @CXXCPP@
-CXXDEPMODE = @CXXDEPMODE@
-CXXFLAGS = @CXXFLAGS@
-CYGPATH_W = @CYGPATH_W@
-DATADIRNAME = @DATADIRNAME@
-DBUS_BINDING_TOOL = @DBUS_BINDING_TOOL@
-DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@
-DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@
-DBUS_SERVICES_DIR = @DBUS_SERVICES_DIR@
-DEFS = @DEFS@
-DEPDIR = @DEPDIR@
-DSYMUTIL = @DSYMUTIL@
-EBOOK_CFLAGS = @EBOOK_CFLAGS@
-EBOOK_LIBS = @EBOOK_LIBS@
-ECAL_CFLAGS = @ECAL_CFLAGS@
-ECAL_LIBS = @ECAL_LIBS@
-ECHO = @ECHO@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EGREP = @EGREP@
-EPACKAGE_CFLAGS = @EPACKAGE_CFLAGS@
-EPACKAGE_LIBS = @EPACKAGE_LIBS@
-EXEEXT = @EXEEXT@
-F77 = @F77@
-FFLAGS = @FFLAGS@
-FILE_CFLAGS = @FILE_CFLAGS@
-FILE_LIBS = @FILE_LIBS@
-GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
-GLIB_CFLAGS = @GLIB_CFLAGS@
-GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
-GLIB_LIBS = @GLIB_LIBS@
-GMOFILES = @GMOFILES@
-GMSGFMT = @GMSGFMT@
-GOBJECT_CFLAGS = @GOBJECT_CFLAGS@
-GOBJECT_LIBS = @GOBJECT_LIBS@
-GREP = @GREP@
-GTHREAD_CFLAGS = @GTHREAD_CFLAGS@
-GTHREAD_LIBS = @GTHREAD_LIBS@
-GTK_BUILDER_CONV = @GTK_BUILDER_CONV@
-GUI_CFLAGS = @GUI_CFLAGS@
-GUI_DESKTOP_FILES = @GUI_DESKTOP_FILES@
-GUI_LIBS = @GUI_LIBS@
-GUI_PROGRAMS = @GUI_PROGRAMS@
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-INSTOBJEXT = @INSTOBJEXT@
-INTLLIBS = @INTLLIBS@
-INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
-INTLTOOL_MERGE = @INTLTOOL_MERGE@
-INTLTOOL_PERL = @INTLTOOL_PERL@
-INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
-KEYRING_2_20_CFLAGS = @KEYRING_2_20_CFLAGS@
-KEYRING_2_20_LIBS = @KEYRING_2_20_LIBS@
-KEYRING_CFLAGS = @KEYRING_CFLAGS@
-KEYRING_LIBS = @KEYRING_LIBS@
-LDFLAGS = @LDFLAGS@
-LIBEXECDIR = @LIBEXECDIR@
-LIBOBJS = @LIBOBJS@
-LIBS = @LIBS@
-LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@
-LIBSOUP_LIBS = @LIBSOUP_LIBS@
-LIBTOOL = @LIBTOOL@
-LN_S = @LN_S@
-LTLIBOBJS = @LTLIBOBJS@
-MAKEINFO = @MAKEINFO@
-MCALB_CFLAGS = @MCALB_CFLAGS@
-MCALB_LIBS = @MCALB_LIBS@
-MKDIR_P = @MKDIR_P@
-MKINSTALLDIRS = @MKINSTALLDIRS@
-MODIFY_SYNCCOMPARE = @MODIFY_SYNCCOMPARE@
-MSGFMT = @MSGFMT@
-MSGFMT_OPTS = @MSGFMT_OPTS@
-MSGMERGE = @MSGMERGE@
-NMEDIT = @NMEDIT@
-OBJEXT = @OBJEXT@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-PKG_CONFIG = @PKG_CONFIG@
-POFILES = @POFILES@
-POSUB = @POSUB@
-PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
-PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
-RANLIB = @RANLIB@
-SED = @SED@
-SET_MAKE = @SET_MAKE@
-SHELL = @SHELL@
-SQLITE_CFLAGS = @SQLITE_CFLAGS@
-SQLITE_LIBS = @SQLITE_LIBS@
-STRIP = @STRIP@
-SYNCEVOLUTION_CXXFLAGS = @SYNCEVOLUTION_CXXFLAGS@
-SYNCEVOLUTION_LDADD = @SYNCEVOLUTION_LDADD@
-SYNCEVOLUTION_LOCALEDIR = @SYNCEVOLUTION_LOCALEDIR@
-SYNCSOURCES = syncxmlrpc.la
-SYNTHESIS = @SYNTHESIS@
-SYNTHESISSRC = @SYNTHESISSRC@
-SYNTHESIS_CFLAGS = @SYNTHESIS_CFLAGS@
-SYNTHESIS_DEP = @SYNTHESIS_DEP@
-SYNTHESIS_LIB = @SYNTHESIS_LIB@
-SYNTHESIS_LIBS = @SYNTHESIS_LIBS@
-SYNTHESIS_SRC = @SYNTHESIS_SRC@
-SYNTHESIS_SUBDIR = @SYNTHESIS_SUBDIR@
-TRANSPORT_CFLAGS = @TRANSPORT_CFLAGS@
-TRANSPORT_LIBS = @TRANSPORT_LIBS@
-UNIQUE_CFLAGS = @UNIQUE_CFLAGS@
-UNIQUE_LIBS = @UNIQUE_LIBS@
-USE_NLS = @USE_NLS@
-VERSION = @VERSION@
-XGETTEXT = @XGETTEXT@
-XMLRPC_CFLAGS = @XMLRPC_CFLAGS@
-XMLRPC_LIBS = @XMLRPC_LIBS@
-XSLT = @XSLT@
-abs_builddir = @abs_builddir@
-abs_srcdir = @abs_srcdir@
-abs_top_builddir = @abs_top_builddir@
-abs_top_srcdir = @abs_top_srcdir@
-ac_ct_CC = @ac_ct_CC@
-ac_ct_CXX = @ac_ct_CXX@
-ac_ct_F77 = @ac_ct_F77@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-am__tar = @am__tar@
-am__untar = @am__untar@
-backenddir = @backenddir@
-backendsearchdir = @backendsearchdir@
-bindir = @bindir@
-build = @build@
-build_alias = @build_alias@
-build_cpu = @build_cpu@
-build_os = @build_os@
-build_vendor = @build_vendor@
-builddir = @builddir@
-datadir = @datadir@
-datarootdir = @datarootdir@
-docdir = @docdir@
-dvidir = @dvidir@
-exec_prefix = @exec_prefix@
-host = @host@
-host_alias = @host_alias@
-host_cpu = @host_cpu@
-host_os = @host_os@
-host_vendor = @host_vendor@
-htmldir = @htmldir@
-includedir = @includedir@
-infodir = @infodir@
-install_sh = @install_sh@
-libdir = @libdir@
-libexecdir = @libexecdir@
-localedir = @localedir@
-localstatedir = @localstatedir@
-mandir = @mandir@
-mkdir_p = @mkdir_p@
-oldincludedir = @oldincludedir@
-pdfdir = @pdfdir@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-psdir = @psdir@
-sbindir = @sbindir@
-sharedstatedir = @sharedstatedir@
-srcdir = @srcdir@
-sysconfdir = @sysconfdir@
-target_alias = @target_alias@
-top_builddir = @top_builddir@
-top_srcdir = @top_srcdir@
-AM_CPPFLAGS = -I$(srcdir)/../../ -I$(top_srcdir)/test $(BACKEND_CPPFLAGS)
-EXTRA_DIST = configure-sub.in
-MOSTLYCLEANFILES = $(SYNCSOURCES)
-@ENABLE_MODULES_TRUE@backend_LTLIBRARIES = $(SYNCSOURCES)
-@ENABLE_MODULES_FALSE@noinst_LTLIBRARIES = $(SYNCSOURCES)
-MAINTAINERCLEANFILES = Makefile.in
-SYNCXMLRPC_SOURCES = \
-       XMLRPCSyncSource.h \
-       XMLRPCSyncSource.cpp
-
-syncxmlrpc_la_SOURCES = $(SYNCXMLRPC_SOURCES)
-syncxmlrpc_la_LIBADD = $(XMLRPC_LIBS)
-syncxmlrpc_la_LDFLAGS = -module -avoid-version
-syncxmlrpc_la_CXXFLAGS = $(SYNCEVOLUTION_CXXFLAGS)
-all: all-am
-
-.SUFFIXES:
-.SUFFIXES: .cpp .lo .o .obj
-$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
-       @for dep in $?; do \
-         case '$(am__configure_deps)' in \
-           *$$dep*) \
-             cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
-               && exit 0; \
-             exit 1;; \
-         esac; \
-       done; \
-       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu  src/backends/xmlrpc/Makefile'; \
-       cd $(top_srcdir) && \
-         $(AUTOMAKE) --gnu  src/backends/xmlrpc/Makefile
-.PRECIOUS: Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
-       @case '$?' in \
-         *config.status*) \
-           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
-         *) \
-           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
-           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
-       esac;
-
-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
-       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-
-$(top_srcdir)/configure:  $(am__configure_deps)
-       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
-       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-install-backendLTLIBRARIES: $(backend_LTLIBRARIES)
-       @$(NORMAL_INSTALL)
-       test -z "$(backenddir)" || $(MKDIR_P) "$(DESTDIR)$(backenddir)"
-       @list='$(backend_LTLIBRARIES)'; for p in $$list; do \
-         if test -f $$p; then \
-           f=$(am__strip_dir) \
-           echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(backendLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(backenddir)/$$f'"; \
-           $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(backendLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(backenddir)/$$f"; \
-         else :; fi; \
-       done
-
-uninstall-backendLTLIBRARIES:
-       @$(NORMAL_UNINSTALL)
-       @list='$(backend_LTLIBRARIES)'; for p in $$list; do \
-         p=$(am__strip_dir) \
-         echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(backenddir)/$$p'"; \
-         $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(backenddir)/$$p"; \
-       done
-
-clean-backendLTLIBRARIES:
-       -test -z "$(backend_LTLIBRARIES)" || rm -f $(backend_LTLIBRARIES)
-       @list='$(backend_LTLIBRARIES)'; for p in $$list; do \
-         dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
-         test "$$dir" != "$$p" || dir=.; \
-         echo "rm -f \"$${dir}/so_locations\""; \
-         rm -f "$${dir}/so_locations"; \
-       done
-
-clean-noinstLTLIBRARIES:
-       -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
-       @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
-         dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
-         test "$$dir" != "$$p" || dir=.; \
-         echo "rm -f \"$${dir}/so_locations\""; \
-         rm -f "$${dir}/so_locations"; \
-       done
-syncxmlrpc.la: $(syncxmlrpc_la_OBJECTS) $(syncxmlrpc_la_DEPENDENCIES) 
-       $(syncxmlrpc_la_LINK) $(am_syncxmlrpc_la_rpath) $(syncxmlrpc_la_OBJECTS) $(syncxmlrpc_la_LIBADD) $(LIBS)
-
-mostlyclean-compile:
-       -rm -f *.$(OBJEXT)
-
-distclean-compile:
-       -rm -f *.tab.c
-
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syncxmlrpc_la-XMLRPCSyncSource.Plo@am__quote@
-
-.cpp.o:
-@am__fastdepCXX_TRUE@  $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
-
-.cpp.obj:
-@am__fastdepCXX_TRUE@  $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
-
-.cpp.lo:
-@am__fastdepCXX_TRUE@  $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $<
-
-syncxmlrpc_la-XMLRPCSyncSource.lo: XMLRPCSyncSource.cpp
-@am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(syncxmlrpc_la_CXXFLAGS) $(CXXFLAGS) -MT syncxmlrpc_la-XMLRPCSyncSource.lo -MD -MP -MF $(DEPDIR)/syncxmlrpc_la-XMLRPCSyncSource.Tpo -c -o syncxmlrpc_la-XMLRPCSyncSource.lo `test -f 'XMLRPCSyncSource.cpp' || echo '$(srcdir)/'`XMLRPCSyncSource.cpp
-@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/syncxmlrpc_la-XMLRPCSyncSource.Tpo $(DEPDIR)/syncxmlrpc_la-XMLRPCSyncSource.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='XMLRPCSyncSource.cpp' object='syncxmlrpc_la-XMLRPCSyncSource.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(syncxmlrpc_la_CXXFLAGS) $(CXXFLAGS) -c -o syncxmlrpc_la-XMLRPCSyncSource.lo `test -f 'XMLRPCSyncSource.cpp' || echo '$(srcdir)/'`XMLRPCSyncSource.cpp
-
-mostlyclean-libtool:
-       -rm -f *.lo
-
-clean-libtool:
-       -rm -rf .libs _libs
-
-ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
-       list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
-       unique=`for i in $$list; do \
-           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-         done | \
-         $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
-             END { if (nonempty) { for (i in files) print i; }; }'`; \
-       mkid -fID $$unique
-tags: TAGS
-
-TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
-               $(TAGS_FILES) $(LISP)
-       tags=; \
-       here=`pwd`; \
-       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
-       unique=`for i in $$list; do \
-           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-         done | \
-         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
-             END { if (nonempty) { for (i in files) print i; }; }'`; \
-       if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
-         test -n "$$unique" || unique=$$empty_fix; \
-         $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-           $$tags $$unique; \
-       fi
-ctags: CTAGS
-CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
-               $(TAGS_FILES) $(LISP)
-       tags=; \
-       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
-       unique=`for i in $$list; do \
-           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-         done | \
-         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
-             END { if (nonempty) { for (i in files) print i; }; }'`; \
-       test -z "$(CTAGS_ARGS)$$tags$$unique" \
-         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
-            $$tags $$unique
-
-GTAGS:
-       here=`$(am__cd) $(top_builddir) && pwd` \
-         && cd $(top_srcdir) \
-         && gtags -i $(GTAGS_ARGS) $$here
-
-distclean-tags:
-       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-
-distdir: $(DISTFILES)
-       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-       list='$(DISTFILES)'; \
-         dist_files=`for file in $$list; do echo $$file; done | \
-         sed -e "s|^$$srcdirstrip/||;t" \
-             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
-       case $$dist_files in \
-         */*) $(MKDIR_P) `echo "$$dist_files" | \
-                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
-                          sort -u` ;; \
-       esac; \
-       for file in $$dist_files; do \
-         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
-         if test -d $$d/$$file; then \
-           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
-           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
-             cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
-           fi; \
-           cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
-         else \
-           test -f $(distdir)/$$file \
-           || cp -p $$d/$$file $(distdir)/$$file \
-           || exit 1; \
-         fi; \
-       done
-check-am: all-am
-check: check-am
-all-am: Makefile $(LTLIBRARIES)
-installdirs:
-       for dir in "$(DESTDIR)$(backenddir)"; do \
-         test -z "$$dir" || $(MKDIR_P) "$$dir"; \
-       done
-install: install-am
-install-exec: install-exec-am
-install-data: install-data-am
-uninstall: uninstall-am
-
-install-am: all-am
-       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-
-installcheck: installcheck-am
-install-strip:
-       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-         install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-         `test -z '$(STRIP)' || \
-           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
-mostlyclean-generic:
-       -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
-
-clean-generic:
-
-distclean-generic:
-       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-
-maintainer-clean-generic:
-       @echo "This command is intended for maintainers to use"
-       @echo "it deletes files that may require special tools to rebuild."
-       -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
-clean: clean-am
-
-clean-am: clean-backendLTLIBRARIES clean-generic clean-libtool \
-       clean-noinstLTLIBRARIES mostlyclean-am
-
-distclean: distclean-am
-       -rm -rf ./$(DEPDIR)
-       -rm -f Makefile
-distclean-am: clean-am distclean-compile distclean-generic \
-       distclean-tags
-
-dvi: dvi-am
-
-dvi-am:
-
-html: html-am
-
-info: info-am
-
-info-am:
-
-install-data-am: install-backendLTLIBRARIES
-
-install-dvi: install-dvi-am
-
-install-exec-am:
-
-install-html: install-html-am
-
-install-info: install-info-am
-
-install-man:
-
-install-pdf: install-pdf-am
-
-install-ps: install-ps-am
-
-installcheck-am:
-
-maintainer-clean: maintainer-clean-am
-       -rm -rf ./$(DEPDIR)
-       -rm -f Makefile
-maintainer-clean-am: distclean-am maintainer-clean-generic
-
-mostlyclean: mostlyclean-am
-
-mostlyclean-am: mostlyclean-compile mostlyclean-generic \
-       mostlyclean-libtool
-
-pdf: pdf-am
-
-pdf-am:
-
-ps: ps-am
-
-ps-am:
-
-uninstall-am: uninstall-backendLTLIBRARIES
-
-.MAKE: install-am install-strip
-
-.PHONY: CTAGS GTAGS all all-am check check-am clean \
-       clean-backendLTLIBRARIES clean-generic clean-libtool \
-       clean-noinstLTLIBRARIES ctags distclean distclean-compile \
-       distclean-generic distclean-libtool distclean-tags distdir dvi \
-       dvi-am html html-am info info-am install install-am \
-       install-backendLTLIBRARIES install-data install-data-am \
-       install-dvi install-dvi-am install-exec install-exec-am \
-       install-html install-html-am install-info install-info-am \
-       install-man install-pdf install-pdf-am install-ps \
-       install-ps-am install-strip installcheck installcheck-am \
-       installdirs maintainer-clean maintainer-clean-generic \
-       mostlyclean mostlyclean-compile mostlyclean-generic \
-       mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
-       uninstall-am uninstall-backendLTLIBRARIES
-
-# If you need special test cases for your sync source, then
-# install them here. Here's how the sqlite backend does that:
-#
-#../../testcases/sqlite_vcard21.vcf: $(FUNAMBOL_SUBDIR)/test/test/testcases/vcard21.vcf
-#      mkdir -p ${@D}
-#      perl -e '$$_ = join("", <>); s/^(ADR|TEL|EMAIL|PHOTO).*?(?=^\S)//msg; s/;X-EVOLUTION-UI-SLOT=\d+//g; print;' $< >$@
-#all: ../../testcases/sqlite_vcard21.vcf
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
diff --git a/src/backends/xmlrpc/README b/src/backends/xmlrpc/README
deleted file mode 100644 (file)
index 1c52b82..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-== Summary ==
-
-This is a backend to use a web application, probably a webmail or PIM
-application, as data store. The communication is done using XMLRPC.
-
-== Installation ==
-
-This backend requires the Xmlrpc-c libraries from
-http://xmlrpc-c.sourceforge.net
-
-Precompiled packages exist for many Linux distributions, on Ubuntu or
-Debian, they development package is installed by:
-
-  apt-get install libxmlrpc-c3-dev
-
-To compile this backend as part of SyncEvolution, configure with
---enable-xmlrpc.
-
-== Configuration ==
-
-The type parameter is similar to that on the file backend, e.g.
-
-  type = xmlrpc:text/calendar:2.0
-
-MIME type and version must be set according to the implementation on the
-XMLRPC interface side.
-
-The evolutionsource parameter contains the information of the XMLRPC service,
-e.g.
-
-  evolutionsource = http://hostname/xmlrpc|database|username|password
-
-The parameter contains several fields, delimited by a pipe character.
-
-The parameters after the URL are used as the first parameters in every XMLRPC
-request. Their number is not fixed, it depends on the implementation of the
-XMLRPC interface.
-
-== XMLRPC interface ==
-
-The parameters after the URL in the evolutionsource parameter are passed as
-the first parameters of the XMLRPC request. Their number is not limited by
-the backend, the number may even be 0, if the respective information is given
-as part of the URL (or not necessary). This set of parameters is represented
-in the specification below with "...".
-
-All parameters are sent and expected as string values.
-
-Four methods have to implemented in the XMLRPC interface:
-
-* listAllItems(...)
-
-Returns a list of id with some kind of version information, e.g. timestamp of
-the last modification, as XMLRPC struct. The id is a string value.
-
-* readItem(..., id)
-
-Reads a single item from the data store. The return value contains a string
-containing the element as vcard or icalender object.
-
-* insertItem(..., id, object)
-
-Creates a new or updates an existing object in the data store. With an empty
-id parameter, a new object will be created.
-
-The return value contains a struct, equal to that of listAllItems, but with
-only one entry, namely the updated or created one.
-
-* removeItem(..., id)
-
-Removes an object from the data store. The return value is ignored by the
-backend.
-
-== Sample XMLRPC snippets ==
-
-The following snippets of the method requests and response shall explain the
-used data types. If incorrect datatypes (e.g. int value instead of string)
-are used, the communication will fail.
-
-* listAllItems
-
-XML-RPC CALL:
-
-<?xml version="1.0" encoding="UTF-8"?>
-<methodCall>
-  <methodName>listAllItems</methodName>
-  <params>
-    <param><value><string>addr</string></value></param>
-    <param><value><string>testmb04</string></value></param>
-    <param><value><string>*secret*</string></value></param>
-  </params>
-</methodCall>
-
-XML-RPC RESPONSE:
-
-<?xml version="1.0" encoding="UTF-8"?>
-<methodResponse>
-  <params>
-    <param><value><struct>
-      <member><name>4854</name><value><string>1259607642</string></value></member>
-      <member><name>4855</name><value><string>1259605716</string></value></member>
-      <member><name>4856</name><value><string>1259842773</string></value></member>
-      <member><name>4858</name><value><string>1259610815</string></value></member>
-      <member><name>4857</name><value><string>1259605717</string></value></member>
-    </struct></value></param>
-  </params>
-</methodResponse>
-
-* readItem
-
-XML-RPC CALL:
-
-<?xml version="1.0" encoding="UTF-8"?>
-<methodCall>
-  <methodName>readItem</methodName>
-  <params>
-    <param><value><string>addr</string></value></param>
-    <param><value><string>testmb04</string></value></param>
-    <param><value><string>*secret*</string></value></param>
-    <param><value><string>4855</string></value></param>
-  </params>
-</methodCall>
-
-XML-RPC RESPONSE:
-
-<?xml version="1.0"? encoding="UTF-8"?>
-<methodResponse>
-  <params>
-    <param><value><string>BEGIN:VCARD
-VERSION:3.0
-N:Knipp;Franz;;;
-FN:Franz Knipp
-EMAIL:knipp@m-otion.com
-END:VCARD
-</string></value></param>
-  </params>
-</methodResponse>
-
-* insertItem
-
-XML-RPC CALL:
-
-<?xml version="1.0" encoding="UTF-8"?>
-<methodCall>
-  <methodName>insertItem</methodName>
-  <params>
-    <param><value><string>addr</string></value></param>
-    <param><value><string>testmb04</string></value></param>
-    <param><value><string>*secret*</string></value></param>
-    <param><value><string></string></value></param>
-    <param><value><string>BEGIN:VCARD
-VERSION:3.0
-FN:Patrick Ohly
-N:Ohly;Patrick;;;
-EMAIL:patrick.ohly@intel.com
-END:VCARD
-</string></value></param>
-  </params>
-</methodCall>
-
-XML-RPC RESPONSE:
-
-<?xml version="1.0" encoding="UTF-8"?>
-<methodResponse>
-  <params>
-    <param><value><struct>
-      <member><name>4863</name><value><string>1260216497</string></value></member>
-    </struct></value></param>
-  </params>
-</methodResponse>
-
-* removeItem
-
-XML-RPC CALL:
-
-<?xml version="1.0" encoding="UTF-8"?>
-<methodCall>
-  <methodName>removeItem</methodName>
-  <params>
-    <param><value><string>addr</string></value></param>
-    <param><value><string>testmb04</string></value></param>
-    <param><value><string>*secret*</string></value></param>
-    <param><value><string>4863</string></value></param>
-  </params>
-</methodCall>
-
-XML-RPC RESPONSE:
-
-<?xml version="1.0" encoding="UTF-8"?>
-<methodResponse>
-  <params><param><value></value></param></params>
-</methodResponse>
\ No newline at end of file
diff --git a/src/backends/xmlrpc/XMLRPCSyncSource.cpp b/src/backends/xmlrpc/XMLRPCSyncSource.cpp
deleted file mode 100644 (file)
index c414cab..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2009 m-otion communications GmbH <knipp@m-otion.com>, waived
- * Copyright (C) 2007-2009 Patrick Ohly <patrick.ohly@gmx.de>
- * Copyright (C) 2009 Intel Corporation
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) version 3.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301  USA
- */
-
-#include "config.h"
-
-#ifdef ENABLE_XMLRPC
-
-#include "XMLRPCSyncSource.h"
-
-#include <boost/algorithm/string/split.hpp>
-
-#include <syncevo/declarations.h>
-SE_BEGIN_CXX
-
-XMLRPCSyncSource::XMLRPCSyncSource(const SyncSourceParams &params,
-                                   const string &dataformat) :
-    TrackingSyncSource(params)
-{
-    if (dataformat.empty()) {
-        throwError("a data format must be specified");
-    }
-    size_t sep = dataformat.find(':');
-    if (sep == dataformat.npos) {
-        throwError(string("data format not specified as <mime type>:<mime version>: " + dataformat));
-    }
-    m_mimeType.assign(dataformat, 0, sep);
-    m_mimeVersion = dataformat.substr(sep + 1);
-    m_supportedTypes = dataformat;
-
-    string const dbid = getDatabaseID();
-    boost::split(m_splitDatabase, dbid, boost::is_any_of("|"));
-    m_serverUrl = m_splitDatabase[0];
-}
-
-const char *XMLRPCSyncSource::getMimeType() const
-{
-    return m_mimeType.c_str();
-}
-
-const char *XMLRPCSyncSource::getMimeVersion() const
-{
-    return m_mimeVersion.c_str();
-}
-
-void XMLRPCSyncSource::open()
-{
-}
-
-void XMLRPCSyncSource::close()
-{
-}
-
-XMLRPCSyncSource::Databases XMLRPCSyncSource::getDatabases()
-{
-    Databases result;
-
-    result.push_back(Database("select database via URL",
-                              "<serverUrl>"));
-    return result;
-}
-
-void XMLRPCSyncSource::listAllItems(RevisionMap_t &revisions)
-{
-
-    xmlrpc_c::value result;
-
-    client.call(m_serverUrl, "listAllItems", prepareParamList(), &result);
-
-    if(result.type() == xmlrpc_c::value::TYPE_STRUCT) {
-        xmlrpc_c::value_struct const tmp(result);
-        map<string, xmlrpc_c::value> const resultMap(
-            static_cast<map<string, xmlrpc_c::value> >(tmp));
-        map<string, xmlrpc_c::value>::const_iterator it;
-
-        for(it = resultMap.begin(); it != resultMap.end(); it++)
-            revisions[(*it).first] = xmlrpc_c::value_string((*it).second);
-
-    }
-}
-
-void XMLRPCSyncSource::readItem(const string &uid, std::string &item, bool raw)
-{
-
-    xmlrpc_c::paramList p = prepareParamList();
-    p.add(xmlrpc_c::value_string(uid));
-    xmlrpc_c::value result;
-
-    client.call(m_serverUrl, "readItem", p, &result);
-
-    item = xmlrpc_c::value_string(result);
-
-}
-
-TrackingSyncSource::InsertItemResult XMLRPCSyncSource::insertItem(const string &uid, const std::string &item, bool raw)
-{
-
-    xmlrpc_c::paramList p = prepareParamList();
-    p.add(xmlrpc_c::value_string(uid));
-    p.add(xmlrpc_c::value_string(item));
-    xmlrpc_c::value result;
-
-    client.call(m_serverUrl, "insertItem", p, &result);
-
-    xmlrpc_c::value_struct const tmp(result);
-    map<string, xmlrpc_c::value> const resultMap(
-        static_cast<map<string, xmlrpc_c::value> >(tmp));
-
-    if(resultMap.size() != 1) {
-        throw("Return value of insertItem has wrong length.");
-    }
-
-    map<string, xmlrpc_c::value>::const_iterator it;
-    it = resultMap.begin();
-
-    return InsertItemResult((*it).first,
-                            xmlrpc_c::value_string((*it).second),
-                            false);
-}
-
-
-void XMLRPCSyncSource::removeItem(const string &uid)
-{
-    xmlrpc_c::paramList p = prepareParamList();
-    p.add(xmlrpc_c::value_string(uid));
-    xmlrpc_c::value result;
-
-    client.call(m_serverUrl, "removeItem", p, &result);
-}
-
-xmlrpc_c::paramList XMLRPCSyncSource::prepareParamList()
-{
-    xmlrpc_c::paramList p;
-    for(size_t i = 1; i < m_splitDatabase.size(); i++) {
-        p.add(xmlrpc_c::value_string(m_splitDatabase[i]));
-    }
-
-    return p;
-}
-
-SE_END_CXX
-
-#endif /* ENABLE_XMLRPC */
-
-#ifdef ENABLE_MODULES
-# include "XMLRPCSyncSourceRegister.cpp"
-#endif
diff --git a/src/backends/xmlrpc/XMLRPCSyncSource.h b/src/backends/xmlrpc/XMLRPCSyncSource.h
deleted file mode 100644 (file)
index b84c34d..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2009 m-otion communications GmbH <knipp@m-otion.com>, waived
- * Copyright (C) 2007-2009 Patrick Ohly <patrick.ohly@gmx.de>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) version 3.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301  USA
- */
-
-#ifndef INCL_XMLRPCSYNCSOURCE
-#define INCL_XMLRPCSYNCSOURCE
-
-#include <syncevo/TrackingSyncSource.h>
-
-#ifdef ENABLE_XMLRPC
-
-#include <xmlrpc-c/base.hpp>
-#include <xmlrpc-c/client_simple.hpp>
-
-#include <syncevo/declarations.h>
-SE_BEGIN_CXX
-
-class XMLRPCSyncSource : public TrackingSyncSource
-{
-  public:
-    XMLRPCSyncSource(const SyncSourceParams &params,
-                     const string &dataformat);
-
-
- protected:
-    /* implementation of SyncSource interface */
-    virtual void open();
-    virtual void close();
-    virtual Databases getDatabases();
-    virtual const char *getMimeType() const;
-    virtual const char *getMimeVersion() const;
-
-    /* implementation of TrackingSyncSource interface */
-    virtual void listAllItems(RevisionMap_t &revisions);
-    virtual InsertItemResult insertItem(const string &luid, const std::string &item, bool raw);
-    void readItem(const std::string &luid, std::string &item, bool raw);
-    virtual void removeItem(const string &uid);
-
- private:
-    /**
-     * @name values obtained from the source's type property
-     *
-     * Other sync sources only support one hard-coded type and
-     * don't need such variables.
-     */
-    /**@{*/
-    string m_mimeType;
-    string m_mimeVersion;
-    string m_supportedTypes;
-    /**@}*/
-
-    /** @name values obtained from the database name */
-    string m_serverUrl;
-    vector <string> m_splitDatabase;
-
-    xmlrpc_c::paramList prepareParamList();
-    xmlrpc_c::clientSimple client;
-
-};
-
-SE_END_CXX
-
-#endif // ENABLE_XMLRPC
-#endif // INCL_XMLRPCSYNCSOURCE
diff --git a/src/backends/xmlrpc/XMLRPCSyncSourceRegister.cpp b/src/backends/xmlrpc/XMLRPCSyncSourceRegister.cpp
deleted file mode 100644 (file)
index 53187cb..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (C) 2009 m-otion communications GmbH <knipp@m-otion.com>, waived
- * Copyright (C) 2008-2009 Patrick Ohly <patrick.ohly@gmx.de>
- * Copyright (C) 2009 Intel Corporation
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) version 3.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301  USA
- */
-
-#include "XMLRPCSyncSource.h"
-#include "test.h"
-
-#include <syncevo/declarations.h>
-SE_BEGIN_CXX
-
-static SyncSource *createSource(const SyncSourceParams &params)
-{
-    SourceType sourceType = SyncSource::getSourceType(params.m_nodes);
-    // The string returned by getSourceType() is always the one
-    // registered as main Aliases() below.
-    bool isMe = sourceType.m_backend == "XMLRPC interface";
-
-#ifndef ENABLE_XMLRPC
-    // tell SyncEvolution if the user wanted to use a disabled sync source,
-    // otherwise let it continue searching
-    return isMe ? RegisterSyncSource::InactiveSource : NULL;
-#else
-    // Also recognize one of the standard types?
-    // Not in the FileSyncSource!
-    bool maybeMe = false /* sourceType.m_backend == "addressbook" */;
-
-    if (isMe || maybeMe) {
-        // The FileSyncSource always needs the data format
-        // parameter in sourceType.m_format.
-        if (/* sourceType.m_format == "" || sourceType.m_format == "text/x-vcard" */
-            sourceType.m_format.size()) {
-            return new XMLRPCSyncSource(params, sourceType.m_format);
-        } else {
-            return NULL;
-        }
-    }
-    return NULL;
-#endif
-}
-
-static RegisterSyncSource registerMe("XMLRPC interface for data exchange",
-#ifdef ENABLE_XMLRPC
-                                     true,
-#else
-                                     false,
-#endif
-                                     createSource,
-                                     "XMLRPC interface = xmlrpc\n"
-                                     "   Data exchange is done via an XMLRPC interface on the datastore.\n"
-                                     "   Examples:\n"
-                                     "      xmlrpc:text/plain:1.0\n"
-                                     "      xmlrpc:text/x-vcard:2.1\n"
-                                     "      xmlrpc:text/vcard:3.0\n"
-                                     "      xmlrpc:text/x-calendar:1.0\n"
-                                     "      xmlrpc:text/calendar:2.0\n",
-                                     Values() +
-                                     (Aliases("XMLRPC interface") + "xmlrpc"));
-
-#ifdef ENABLE_XMLRPC
-#ifdef ENABLE_UNIT_TESTS
-
-class XMLRPCSyncSourceUnitTest : public CppUnit::TestFixture {
-    CPPUNIT_TEST_SUITE(XMLRPCSyncSourceUnitTest);
-    CPPUNIT_TEST(testInstantiate);
-    CPPUNIT_TEST_SUITE_END();
-
-protected:
-    void testInstantiate() {
-        boost::shared_ptr<SyncSource> source;
-        source.reset(SyncSource::createTestingSource("xmlrpc", "xmlrpc:text/vcard:3.0", true));
-        source.reset(SyncSource::createTestingSource("xmlrpc", "xmlrpc:text/plain:1.0", true));
-        source.reset(SyncSource::createTestingSource("xmlrpc", "XMLRPC interface:text/x-vcard:2.1", true));
-    }
-};
-
-SYNCEVOLUTION_TEST_SUITE_REGISTRATION(XMLRPCSyncSourceUnitTest);
-
-#endif // ENABLE_UNIT_TESTS
-
-#ifdef ENABLE_INTEGRATION_TESTS
-
-// The anonymous namespace ensures that we don't get
-// name clashes: although the classes and objects are
-// only defined in this file, the methods generated
-// for local classes will clash with other methods
-// of other classes with the same name if no namespace
-// is used.
-//
-// The code above is not yet inside the anonymous
-// name space because it would show up inside
-// the CPPUnit unit test names. Use a unique class
-// name there.
-namespace {
-#if 0
-}
-#endif
-
-static class VCard21Test : public RegisterSyncSourceTest {
-public:
-    VCard21Test() : RegisterSyncSourceTest("xmlrpc_vcard21", "vcard21") {}
-
-    virtual void updateConfig(ClientTestConfig &config) const
-    {
-        // set type as required by XMLRPCSyncSource
-        // and leave everything else at its default
-        config.type = "xmlrpc:text/x-vcard:2.1";
-    }
-} VCard21Test;
-
-static class VCard30Test : public RegisterSyncSourceTest {
-public:
-    VCard30Test() : RegisterSyncSourceTest("xmlrpc_vcard30", "vcard30") {}
-
-    virtual void updateConfig(ClientTestConfig &config) const
-    {
-        config.type = "xmlrpc:text/vcard:3.0";
-    }
-} VCard30Test;
-
-static class ICal20Test : public RegisterSyncSourceTest {
-public:
-    ICal20Test() : RegisterSyncSourceTest("xmlrpc_ical20", "ical20") {}
-
-    virtual void updateConfig(ClientTestConfig &config) const
-    {
-        config.type = "xmlrpc:text/calendar:2.0";
-
-        // A sync source which supports linked items (= recurring
-        // event with detached exception) is expected to handle
-        // inserting the parent or child twice by turning the
-        // second operation into an update. The file backend is
-        // to dumb for that and therefore fails these tests:
-        //
-        // Client::Source::file_ical20::testLinkedItemsInsertParentTwice
-        // Client::Source::file_ical20::testLinkedItemsInsertChildTwice
-        //
-        // Disable linked item testing to avoid this.
-        config.sourceKnowsItemSemantic = false;
-    }
-} ICal20Test;
-
-static class ITodo20Test : public RegisterSyncSourceTest {
-public:
-    ITodo20Test() : RegisterSyncSourceTest("xmlrpc_itodo20", "itodo20") {}
-
-    virtual void updateConfig(ClientTestConfig &config) const
-    {
-        config.type = "xmlrpc:text/calendar:2.0";
-    }
-} ITodo20Test;
-
-}
-#endif // ENABLE_INTEGRATION_TESTS
-
-#endif // ENABLE_XMLRPC
-
-SE_END_CXX
diff --git a/src/backends/xmlrpc/configure-sub.in b/src/backends/xmlrpc/configure-sub.in
deleted file mode 100644 (file)
index b4a6866..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-dnl -*- mode: Autoconf; -*-
-dnl Invoke autogen.sh to produce a configure script.
-
-dnl Checks for required libraries.
-dnl
-dnl This is from the sqlite backend:
-dnl PKG_CHECK_MODULES(SQLITE, sqlite3, SQLITEFOUND=yes, [SQLITEFOUND=no])
-dnl AC_SUBST(SQLITE_CFLAGS)
-dnl AC_SUBST(SQLITE_LIBS)
-
-dnl No pkg-config available for xmlrpc-c
-dnl PKG_CHECK_MODULES(XMLRPC,xmlrpc-c,XMLRPCFOUND=yes, [XMLRPCFOUND=no])
-
-dnl name of backend library (there could be more than one per directory),
-dnl name of the directory,
-dnl help string,
-dnl --enable/disable chosen explicitly
-dnl default, may depend on availability of prerequisites in more complex backends
-AC_ARG_ENABLE_BACKEND(xmlrpc,
-                      xmlrpc,
-                      AS_HELP_STRING([--enable-xmlrpc],
-                                     [enable XMLRPC-based backend which stores items on a central web service (default off)]),
-                                 [enable_xmlrpc="$enableval"],
-                      [enable_xmlrpc="no"]
-                      )
-
-if test "$enable_xmlrpc" = "yes"; then
-        dnl It's good to check the prerequisites here, in case --enable-xmlrpc was used.
-        dnl test "x${SQLITEFOUND}" == "xyes" || AC_MSG_ERROR([--enable-sqlite requires pkg-config information for sqlite3, which was not found])
-        
-        test -e /usr/bin/xmlrpc-c-config || AC_MSG_ERROR([--enable-xmlrpc requires xmlrpc-c-config, which was not found])
-        
-        XMLRPC_CFLAGS=`/usr/bin/xmlrpc-c-config c++2 client --cflags`
-        XMLRPC_LIBS=`/usr/bin/xmlrpc-c-config c++2 client --libs`
-        AC_SUBST(XMLRPC_CFLAGS)
-        AC_SUBST(XMLRPC_LIBS)
-
-        dnl If additional compile flags are necessary to include the header
-        dnl files of the backend, then add them here.
-        BACKEND_CPPFLAGS="$BACKEND_CPPFLAGS $XMLRPC_CFLAGS"
-
-        AC_DEFINE(ENABLE_XMLRPC, 1, [XMLRPC available])
-fi
index 8d0831c..cc82e15 100644 (file)
@@ -192,29 +192,31 @@ public:
         // get configuration and set obligatory fields
         LoggerBase::instance().setLevel(Logger::DEBUG);
         std::string root = std::string("evolution/") + server + "_" + id;
-        SyncConfig config(string(server) + "_" + id);
+        boost::shared_ptr<SyncConfig> config(new SyncConfig(string(server) + "_" + id));
         boost::shared_ptr<SyncConfig> from = boost::shared_ptr<SyncConfig> ();
 
-        if (!config.exists()) {
-            // no configuration yet
-            config.setDefaults();
+        if (!config->exists()) {
+            // no configuration yet, create in different contexts because
+            // device ID is different
+            config.reset(new SyncConfig(string(server) + "_" + id + "@client-test-" + id));
+            config->setDefaults();
             from = SyncConfig::createServerTemplate(server);
             if(from) {
                 set<string> filter;
-                config.copy(*from, &filter);
+                config->copy(*from, &filter);
             }
-            config.setDevID(id == "1" ? "sc-api-nat" : "sc-pim-ppc");
+            config->setDevID(id == "1" ? "sc-api-nat" : "sc-pim-ppc");
         }
         BOOST_FOREACH(const RegisterSyncSourceTest *test, m_configs) {
             ClientTest::Config testconfig;
             getSourceConfig(test, testconfig);
             CPPUNIT_ASSERT(testconfig.type);
 
-            boost::shared_ptr<SyncSourceConfig> sc = config.getSyncSourceConfig(testconfig.sourceName);
+            boost::shared_ptr<SyncSourceConfig> sc = config->getSyncSourceConfig(testconfig.sourceName);
             if (!sc || !sc->exists()) {
                 // no configuration yet
-                config.setSourceDefaults(testconfig.sourceName);
-                sc = config.getSyncSourceConfig(testconfig.sourceName);
+                config->setSourceDefaults(testconfig.sourceName);
+                sc = config->getSyncSourceConfig(testconfig.sourceName);
                 CPPUNIT_ASSERT(sc);
                 sc->setURI(testconfig.uri);
                 if(from && testconfig.sourceNameServerTemplate){
@@ -230,7 +232,7 @@ public:
             sc->setUser(m_evoUser);
             sc->setPassword(m_evoPassword);
         }
-        config.flush();
+        config->flush();
     }
 
     virtual LocalTests *createLocalTests(const std::string &name, int sourceParam, ClientTest::Config &co) {
@@ -267,11 +269,6 @@ public:
                                 const std::string &logbase,
                                 const SyncOptions &options)
     {
-        set<string> activeSources;
-        for(int i = 0; sources[i] >= 0; i++) {
-            activeSources.insert(m_source2Config[sources[i]]);
-        }
-
         string server = getenv("CLIENT_TEST_SERVER") ? getenv("CLIENT_TEST_SERVER") : "funambol";
         server += "_";
         server += m_clientID;
@@ -279,10 +276,9 @@ public:
         class ClientTest : public SyncContext {
         public:
             ClientTest(const string &server,
-                       const set<string> &activeSources,
                        const string &logbase,
                        const SyncOptions &options) :
-                SyncContext(server, false, activeSources),
+                SyncContext(server, false),
                 m_logbase(logbase),
                 m_options(options),
                 m_started(false)
@@ -297,11 +293,6 @@ public:
                 setWBXML(m_options.m_isWBXML, true);
                 SyncContext::prepare();
             }
-            virtual void prepare(const std::vector<SyncSource *> &sources) {
-                SyncModes modes(m_options.m_syncMode);
-                setSyncModes(sources, modes);
-                SyncContext::prepare(sources);
-            }
 
             virtual void displaySyncProgress(sysync::TProgressEventEnum type,
                                              int32_t extra1, int32_t extra2, int32_t extra3)
@@ -332,7 +323,18 @@ public:
             const string m_logbase;
             SyncOptions m_options;
             bool m_started;
-        } client(server, activeSources, logbase, options);
+        } client(server, logbase, options);
+
+        // configure active sources with the desired sync mode,
+        // disable the rest
+        FilterConfigNode::ConfigFilter filter;
+        filter[SyncSourceConfig::m_sourcePropSync.getName()] = "none";
+        client.setConfigFilter(false, "", filter);
+        filter[SyncSourceConfig::m_sourcePropSync.getName()] =
+            PrettyPrintSyncMode(options.m_syncMode);
+        for(int i = 0; sources[i] >= 0; i++) {
+            client.setConfigFilter(false, m_source2Config[sources[i]], filter);
+        }
 
         SyncReport report;
         SyncMLStatus status = client.sync(&report);
@@ -362,9 +364,7 @@ private:
     
     static TestingSyncSource *createSource(ClientTest &client, int source, bool isSourceA) {
         TestEvolution &evClient((TestEvolution &)client);
-        string changeID = "SyncEvolution Change ID #";
         string name = evClient.m_source2Config[source];
-        changeID += isSourceA ? "1" : "2";
         string database = evClient.getDatabaseName(name);
 
         SyncConfig config("client-test-changes");
@@ -373,13 +373,12 @@ private:
                                                           "_" + (isSourceA ? "A" : "B"));
 
         // always set this property: the name might have changes since last test run
-        nodes.m_configNode->setProperty("evolutionsource", database.c_str());
-        nodes.m_configNode->setProperty("evolutionuser", evClient.m_evoUser.c_str());
-        nodes.m_configNode->setProperty("evolutionpassword", evClient.m_evoPassword.c_str());
+        nodes.getProperties()->setProperty("evolutionsource", database.c_str());
+        nodes.getProperties()->setProperty("evolutionuser", evClient.m_evoUser.c_str());
+        nodes.getProperties()->setProperty("evolutionpassword", evClient.m_evoPassword.c_str());
 
         SyncSourceParams params(name,
-                                nodes,
-                                changeID);
+                                nodes);
 
         const RegisterSyncSourceTest *test = evClient.m_configs[name];
         ClientTestConfig testConfig;
index 0c58a5e..f18d923 100644 (file)
@@ -9,8 +9,7 @@ EXTRA_DIST = syncevo-dbus.pc.in
 pkgconfig_DATA = syncevo-dbus.pc
 pkgconfigdir = $(libdir)/pkgconfig
 
-noinst_PROGRAMS = \
-       test-syncevo-dbus
+noinst_PROGRAMS = test-syncevo-dbus
 
 test_syncevo_dbus_SOURCES = test.c
 test_syncevo_dbus_LDADD = $(DBUS_GLIB_LIBS) libsyncevo-dbus.la
@@ -22,7 +21,8 @@ nodist_libsyncevo_dbus_la_SOURCES = \
 libsyncevo_dbus_la_SOURCES = \
        $(syncevo_dbus_headers) \
        syncevo-dbus-types.c \
-       syncevo-dbus.c
+       syncevo-server.c \
+       syncevo-session.c
 
 libsyncevo_dbus_la_CFLAGS = \
        -I$(top_srcdir) \
@@ -34,7 +34,8 @@ libsyncevo_dbus_la_LIBADD = \
 
 syncevo_dbus_headers = \
        syncevo-dbus-types.h \
-       syncevo-dbus.h
+       syncevo-server.h \
+       syncevo-session.h
 
 libsyncevo_dbus_includedir = $(includedir)/syncevo-dbus
 libsyncevo_dbus_include_HEADERS =      \
index 2d37db5..1fecdfe 100644 (file)
@@ -63,7 +63,8 @@ libsyncevo_dbus_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
 am__objects_1 =
 am_libsyncevo_dbus_la_OBJECTS = $(am__objects_1) \
        libsyncevo_dbus_la-syncevo-dbus-types.lo \
-       libsyncevo_dbus_la-syncevo-dbus.lo
+       libsyncevo_dbus_la-syncevo-server.lo \
+       libsyncevo_dbus_la-syncevo-session.lo
 nodist_libsyncevo_dbus_la_OBJECTS =  \
        libsyncevo_dbus_la-syncevo-marshal.lo
 libsyncevo_dbus_la_OBJECTS = $(am_libsyncevo_dbus_la_OBJECTS) \
@@ -127,6 +128,8 @@ AUTOMAKE = @AUTOMAKE@
 AWK = @AWK@
 BACKEND_CPPFLAGS = @BACKEND_CPPFLAGS@
 BACKEND_DEFINES = @BACKEND_DEFINES@
+BLUEZ_CFLAGS = @BLUEZ_CFLAGS@
+BLUEZ_LIBS = @BLUEZ_LIBS@
 BOOST_CPPFLAGS = @BOOST_CPPFLAGS@
 BOOST_LDFLAGS = @BOOST_LDFLAGS@
 CATALOGS = @CATALOGS@
@@ -134,7 +137,6 @@ CATOBJEXT = @CATOBJEXT@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
-CLEAN_CLIENT_SRC = @CLEAN_CLIENT_SRC@
 CORE_LDADD_DEP = @CORE_LDADD_DEP@
 CPP = @CPP@
 CPPFLAGS = @CPPFLAGS@
@@ -147,8 +149,10 @@ CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
 DATADIRNAME = @DATADIRNAME@
 DBUS_BINDING_TOOL = @DBUS_BINDING_TOOL@
+DBUS_CFLAGS = @DBUS_CFLAGS@
 DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@
 DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@
+DBUS_LIBS = @DBUS_LIBS@
 DBUS_SERVICES_DIR = @DBUS_SERVICES_DIR@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
@@ -175,11 +179,7 @@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
 GLIB_LIBS = @GLIB_LIBS@
 GMOFILES = @GMOFILES@
 GMSGFMT = @GMSGFMT@
-GOBJECT_CFLAGS = @GOBJECT_CFLAGS@
-GOBJECT_LIBS = @GOBJECT_LIBS@
 GREP = @GREP@
-GTHREAD_CFLAGS = @GTHREAD_CFLAGS@
-GTHREAD_LIBS = @GTHREAD_LIBS@
 GTK_BUILDER_CONV = @GTK_BUILDER_CONV@
 GUI_CFLAGS = @GUI_CFLAGS@
 GUI_DESKTOP_FILES = @GUI_DESKTOP_FILES@
@@ -203,6 +203,8 @@ KEYRING_LIBS = @KEYRING_LIBS@
 LDFLAGS = @LDFLAGS@
 LIBEXECDIR = @LIBEXECDIR@
 LIBOBJS = @LIBOBJS@
+LIBOPENOBEX_CFLAGS = @LIBOPENOBEX_CFLAGS@
+LIBOPENOBEX_LIBS = @LIBOPENOBEX_LIBS@
 LIBS = @LIBS@
 LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@
 LIBSOUP_LIBS = @LIBSOUP_LIBS@
@@ -210,8 +212,6 @@ LIBTOOL = @LIBTOOL@
 LN_S = @LN_S@
 LTLIBOBJS = @LTLIBOBJS@
 MAKEINFO = @MAKEINFO@
-MCALB_CFLAGS = @MCALB_CFLAGS@
-MCALB_LIBS = @MCALB_LIBS@
 MKDIR_P = @MKDIR_P@
 MKINSTALLDIRS = @MKINSTALLDIRS@
 MODIFY_SYNCCOMPARE = @MODIFY_SYNCCOMPARE@
@@ -247,6 +247,7 @@ SYNTHESIS = @SYNTHESIS@
 SYNTHESISSRC = @SYNTHESISSRC@
 SYNTHESIS_CFLAGS = @SYNTHESIS_CFLAGS@
 SYNTHESIS_DEP = @SYNTHESIS_DEP@
+SYNTHESIS_ENGINE = @SYNTHESIS_ENGINE@
 SYNTHESIS_LIB = @SYNTHESIS_LIB@
 SYNTHESIS_LIBS = @SYNTHESIS_LIBS@
 SYNTHESIS_SRC = @SYNTHESIS_SRC@
@@ -258,8 +259,6 @@ UNIQUE_LIBS = @UNIQUE_LIBS@
 USE_NLS = @USE_NLS@
 VERSION = @VERSION@
 XGETTEXT = @XGETTEXT@
-XMLRPC_CFLAGS = @XMLRPC_CFLAGS@
-XMLRPC_LIBS = @XMLRPC_LIBS@
 XSLT = @XSLT@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
@@ -330,7 +329,8 @@ nodist_libsyncevo_dbus_la_SOURCES = \
 libsyncevo_dbus_la_SOURCES = \
        $(syncevo_dbus_headers) \
        syncevo-dbus-types.c \
-       syncevo-dbus.c
+       syncevo-server.c \
+       syncevo-session.c
 
 libsyncevo_dbus_la_CFLAGS = \
        -I$(top_srcdir) \
@@ -342,7 +342,8 @@ libsyncevo_dbus_la_LIBADD = \
 
 syncevo_dbus_headers = \
        syncevo-dbus-types.h \
-       syncevo-dbus.h
+       syncevo-server.h \
+       syncevo-session.h
 
 libsyncevo_dbus_includedir = $(includedir)/syncevo-dbus
 libsyncevo_dbus_include_HEADERS = \
@@ -430,8 +431,9 @@ distclean-compile:
        -rm -f *.tab.c
 
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsyncevo_dbus_la-syncevo-dbus-types.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsyncevo_dbus_la-syncevo-dbus.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsyncevo_dbus_la-syncevo-marshal.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsyncevo_dbus_la-syncevo-server.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsyncevo_dbus_la-syncevo-session.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_syncevo_dbus-test.Po@am__quote@
 
 .c.o:
@@ -462,12 +464,19 @@ libsyncevo_dbus_la-syncevo-dbus-types.lo: syncevo-dbus-types.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@  $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsyncevo_dbus_la_CFLAGS) $(CFLAGS) -c -o libsyncevo_dbus_la-syncevo-dbus-types.lo `test -f 'syncevo-dbus-types.c' || echo '$(srcdir)/'`syncevo-dbus-types.c
 
-libsyncevo_dbus_la-syncevo-dbus.lo: syncevo-dbus.c
-@am__fastdepCC_TRUE@   $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsyncevo_dbus_la_CFLAGS) $(CFLAGS) -MT libsyncevo_dbus_la-syncevo-dbus.lo -MD -MP -MF $(DEPDIR)/libsyncevo_dbus_la-syncevo-dbus.Tpo -c -o libsyncevo_dbus_la-syncevo-dbus.lo `test -f 'syncevo-dbus.c' || echo '$(srcdir)/'`syncevo-dbus.c
-@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/libsyncevo_dbus_la-syncevo-dbus.Tpo $(DEPDIR)/libsyncevo_dbus_la-syncevo-dbus.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='syncevo-dbus.c' object='libsyncevo_dbus_la-syncevo-dbus.lo' libtool=yes @AMDEPBACKSLASH@
+libsyncevo_dbus_la-syncevo-server.lo: syncevo-server.c
+@am__fastdepCC_TRUE@   $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsyncevo_dbus_la_CFLAGS) $(CFLAGS) -MT libsyncevo_dbus_la-syncevo-server.lo -MD -MP -MF $(DEPDIR)/libsyncevo_dbus_la-syncevo-server.Tpo -c -o libsyncevo_dbus_la-syncevo-server.lo `test -f 'syncevo-server.c' || echo '$(srcdir)/'`syncevo-server.c
+@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/libsyncevo_dbus_la-syncevo-server.Tpo $(DEPDIR)/libsyncevo_dbus_la-syncevo-server.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='syncevo-server.c' object='libsyncevo_dbus_la-syncevo-server.lo' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsyncevo_dbus_la_CFLAGS) $(CFLAGS) -c -o libsyncevo_dbus_la-syncevo-dbus.lo `test -f 'syncevo-dbus.c' || echo '$(srcdir)/'`syncevo-dbus.c
+@am__fastdepCC_FALSE@  $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsyncevo_dbus_la_CFLAGS) $(CFLAGS) -c -o libsyncevo_dbus_la-syncevo-server.lo `test -f 'syncevo-server.c' || echo '$(srcdir)/'`syncevo-server.c
+
+libsyncevo_dbus_la-syncevo-session.lo: syncevo-session.c
+@am__fastdepCC_TRUE@   $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsyncevo_dbus_la_CFLAGS) $(CFLAGS) -MT libsyncevo_dbus_la-syncevo-session.lo -MD -MP -MF $(DEPDIR)/libsyncevo_dbus_la-syncevo-session.Tpo -c -o libsyncevo_dbus_la-syncevo-session.lo `test -f 'syncevo-session.c' || echo '$(srcdir)/'`syncevo-session.c
+@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/libsyncevo_dbus_la-syncevo-session.Tpo $(DEPDIR)/libsyncevo_dbus_la-syncevo-session.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='syncevo-session.c' object='libsyncevo_dbus_la-syncevo-session.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsyncevo_dbus_la_CFLAGS) $(CFLAGS) -c -o libsyncevo_dbus_la-syncevo-session.lo `test -f 'syncevo-session.c' || echo '$(srcdir)/'`syncevo-session.c
 
 libsyncevo_dbus_la-syncevo-marshal.lo: interfaces/syncevo-marshal.c
 @am__fastdepCC_TRUE@   $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsyncevo_dbus_la_CFLAGS) $(CFLAGS) -MT libsyncevo_dbus_la-syncevo-marshal.lo -MD -MP -MF $(DEPDIR)/libsyncevo_dbus_la-syncevo-marshal.Tpo -c -o libsyncevo_dbus_la-syncevo-marshal.lo `test -f 'interfaces/syncevo-marshal.c' || echo '$(srcdir)/'`interfaces/syncevo-marshal.c
index 74d88b1..7658cbf 100644 (file)
@@ -1 +1,2 @@
-This is the C wrapper for the SyncEvolution DBus API
+This is the C wrapper for the SyncEvolution DBus API. It is used by the GTK ui.
+
index b5ce594..3952fda 100644 (file)
@@ -1,11 +1,22 @@
 %.xml: %-full.xml
        $(XSLT) -o $@ $(srcdir)/spec-strip-docs.xsl $<
 
-BUILT_SOURCES = syncevo.xml syncevo-dbus-glue.h syncevo-marshal.c syncevo-marshal.h syncevo-bindings.h
+%-doc.xml: %-full.xml
+       $(XSLT) -o $@ $(srcdir)/spec-to-docbook.xsl $<
 
-noinst_DATA = syncevo.xml
-CLEANFILES = $(noinst_DATA) $(BUILT_SOURCES) stamp-syncevo-dbus-glue.h
-EXTRA_DIST = syncevo-marshal.list spec-strip-docs.xsl $(noinst_DATA)
+BUILT_SOURCES =  syncevo-marshal.c syncevo-marshal.h \
+       syncevo-server-bindings.h syncevo-connection-bindings.h syncevo-session-bindings.h \
+       syncevo-server-glue.h syncevo-connection-glue.h syncevo-session-glue.h \
+       syncevo-server-doc.xml syncevo-connection-doc.xml syncevo-session-doc.xml \
+       syncevo-server.xml syncevo-connection.xml syncevo-session.xml
+
+CLEANFILES = $(BUILT_SOURCES) stamp-syncevo-dbus-glue.h
+EXTRA_DIST = syncevo-marshal.list \
+       spec-strip-docs.xsl \
+       spec-to-docbook.xsl \
+       syncevo-connection-full.xml  \
+       syncevo-server-full.xml \
+       syncevo-session-full.xml
 
 %-bindings.h: stamp-%-bindings.h
        @true
@@ -21,9 +32,9 @@ syncevo-marshal.c: $(srcdir)/syncevo-marshal.list syncevo-marshal.h $(GLIB_GENMA
        echo "#include \"syncevo-marshal.h\"" > $@ \
        && $(GLIB_GENMARSHAL) --prefix=syncevo_marshal $(srcdir)/syncevo-marshal.list --body >> $@
 
-syncevo-dbus-glue.h: stamp-syncevo-dbus-glue.h
+%-glue.h: stamp-%-glue.h
        @true
-stamp-syncevo-dbus-glue.h: syncevo.xml
+stamp-%-glue.h: %.xml
        $(DBUS_BINDING_TOOL) --prefix=syncevo --mode=glib-server $< > xgen-$(@F) \
        && (cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%)) \
        && rm -f xgen-$(@F) \
index 0be4018..c216420 100644 (file)
@@ -13,7 +13,6 @@
 # PARTICULAR PURPOSE.
 
 @SET_MAKE@
-
 VPATH = @srcdir@
 pkgdatadir = $(datadir)/@PACKAGE@
 pkglibdir = $(libdir)/@PACKAGE@
@@ -44,7 +43,6 @@ CONFIG_HEADER = $(top_builddir)/config.h
 CONFIG_CLEAN_FILES =
 SOURCES =
 DIST_SOURCES =
-DATA = $(noinst_DATA)
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
 ACLOCAL = @ACLOCAL@
 ADDRESSBOOK_CFLAGS = @ADDRESSBOOK_CFLAGS@
@@ -58,6 +56,8 @@ AUTOMAKE = @AUTOMAKE@
 AWK = @AWK@
 BACKEND_CPPFLAGS = @BACKEND_CPPFLAGS@
 BACKEND_DEFINES = @BACKEND_DEFINES@
+BLUEZ_CFLAGS = @BLUEZ_CFLAGS@
+BLUEZ_LIBS = @BLUEZ_LIBS@
 BOOST_CPPFLAGS = @BOOST_CPPFLAGS@
 BOOST_LDFLAGS = @BOOST_LDFLAGS@
 CATALOGS = @CATALOGS@
@@ -65,7 +65,6 @@ CATOBJEXT = @CATOBJEXT@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
-CLEAN_CLIENT_SRC = @CLEAN_CLIENT_SRC@
 CORE_LDADD_DEP = @CORE_LDADD_DEP@
 CPP = @CPP@
 CPPFLAGS = @CPPFLAGS@
@@ -78,8 +77,10 @@ CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
 DATADIRNAME = @DATADIRNAME@
 DBUS_BINDING_TOOL = @DBUS_BINDING_TOOL@
+DBUS_CFLAGS = @DBUS_CFLAGS@
 DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@
 DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@
+DBUS_LIBS = @DBUS_LIBS@
 DBUS_SERVICES_DIR = @DBUS_SERVICES_DIR@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
@@ -106,11 +107,7 @@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
 GLIB_LIBS = @GLIB_LIBS@
 GMOFILES = @GMOFILES@
 GMSGFMT = @GMSGFMT@
-GOBJECT_CFLAGS = @GOBJECT_CFLAGS@
-GOBJECT_LIBS = @GOBJECT_LIBS@
 GREP = @GREP@
-GTHREAD_CFLAGS = @GTHREAD_CFLAGS@
-GTHREAD_LIBS = @GTHREAD_LIBS@
 GTK_BUILDER_CONV = @GTK_BUILDER_CONV@
 GUI_CFLAGS = @GUI_CFLAGS@
 GUI_DESKTOP_FILES = @GUI_DESKTOP_FILES@
@@ -134,6 +131,8 @@ KEYRING_LIBS = @KEYRING_LIBS@
 LDFLAGS = @LDFLAGS@
 LIBEXECDIR = @LIBEXECDIR@
 LIBOBJS = @LIBOBJS@
+LIBOPENOBEX_CFLAGS = @LIBOPENOBEX_CFLAGS@
+LIBOPENOBEX_LIBS = @LIBOPENOBEX_LIBS@
 LIBS = @LIBS@
 LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@
 LIBSOUP_LIBS = @LIBSOUP_LIBS@
@@ -141,8 +140,6 @@ LIBTOOL = @LIBTOOL@
 LN_S = @LN_S@
 LTLIBOBJS = @LTLIBOBJS@
 MAKEINFO = @MAKEINFO@
-MCALB_CFLAGS = @MCALB_CFLAGS@
-MCALB_LIBS = @MCALB_LIBS@
 MKDIR_P = @MKDIR_P@
 MKINSTALLDIRS = @MKINSTALLDIRS@
 MODIFY_SYNCCOMPARE = @MODIFY_SYNCCOMPARE@
@@ -178,6 +175,7 @@ SYNTHESIS = @SYNTHESIS@
 SYNTHESISSRC = @SYNTHESISSRC@
 SYNTHESIS_CFLAGS = @SYNTHESIS_CFLAGS@
 SYNTHESIS_DEP = @SYNTHESIS_DEP@
+SYNTHESIS_ENGINE = @SYNTHESIS_ENGINE@
 SYNTHESIS_LIB = @SYNTHESIS_LIB@
 SYNTHESIS_LIBS = @SYNTHESIS_LIBS@
 SYNTHESIS_SRC = @SYNTHESIS_SRC@
@@ -189,8 +187,6 @@ UNIQUE_LIBS = @UNIQUE_LIBS@
 USE_NLS = @USE_NLS@
 VERSION = @VERSION@
 XGETTEXT = @XGETTEXT@
-XMLRPC_CFLAGS = @XMLRPC_CFLAGS@
-XMLRPC_LIBS = @XMLRPC_LIBS@
 XSLT = @XSLT@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
@@ -245,10 +241,20 @@ sysconfdir = @sysconfdir@
 target_alias = @target_alias@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
-BUILT_SOURCES = syncevo.xml syncevo-dbus-glue.h syncevo-marshal.c syncevo-marshal.h syncevo-bindings.h
-noinst_DATA = syncevo.xml
-CLEANFILES = $(noinst_DATA) $(BUILT_SOURCES) stamp-syncevo-dbus-glue.h
-EXTRA_DIST = syncevo-marshal.list spec-strip-docs.xsl $(noinst_DATA)
+BUILT_SOURCES = syncevo-marshal.c syncevo-marshal.h \
+       syncevo-server-bindings.h syncevo-connection-bindings.h syncevo-session-bindings.h \
+       syncevo-server-glue.h syncevo-connection-glue.h syncevo-session-glue.h \
+       syncevo-server-doc.xml syncevo-connection-doc.xml syncevo-session-doc.xml \
+       syncevo-server.xml syncevo-connection.xml syncevo-session.xml
+
+CLEANFILES = $(BUILT_SOURCES) stamp-syncevo-dbus-glue.h
+EXTRA_DIST = syncevo-marshal.list \
+       spec-strip-docs.xsl \
+       spec-to-docbook.xsl \
+       syncevo-connection-full.xml  \
+       syncevo-server-full.xml \
+       syncevo-session-full.xml
+
 all: $(BUILT_SOURCES)
        $(MAKE) $(AM_MAKEFLAGS) all-am
 
@@ -324,7 +330,7 @@ distdir: $(DISTFILES)
 check-am: all-am
 check: $(BUILT_SOURCES)
        $(MAKE) $(AM_MAKEFLAGS) check-am
-all-am: Makefile $(DATA)
+all-am: Makefile
 installdirs:
 install: $(BUILT_SOURCES)
        $(MAKE) $(AM_MAKEFLAGS) install-am
@@ -423,6 +429,9 @@ uninstall-am:
 %.xml: %-full.xml
        $(XSLT) -o $@ $(srcdir)/spec-strip-docs.xsl $<
 
+%-doc.xml: %-full.xml
+       $(XSLT) -o $@ $(srcdir)/spec-to-docbook.xsl $<
+
 %-bindings.h: stamp-%-bindings.h
        @true
 stamp-%-bindings.h: %.xml
@@ -437,9 +446,9 @@ syncevo-marshal.c: $(srcdir)/syncevo-marshal.list syncevo-marshal.h $(GLIB_GENMA
        echo "#include \"syncevo-marshal.h\"" > $@ \
        && $(GLIB_GENMARSHAL) --prefix=syncevo_marshal $(srcdir)/syncevo-marshal.list --body >> $@
 
-syncevo-dbus-glue.h: stamp-syncevo-dbus-glue.h
+%-glue.h: stamp-%-glue.h
        @true
-stamp-syncevo-dbus-glue.h: syncevo.xml
+stamp-%-glue.h: %.xml
        $(DBUS_BINDING_TOOL) --prefix=syncevo --mode=glib-server $< > xgen-$(@F) \
        && (cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%)) \
        && rm -f xgen-$(@F) \
diff --git a/src/dbus/interfaces/spec-to-docbook.xsl b/src/dbus/interfaces/spec-to-docbook.xsl
new file mode 100644 (file)
index 0000000..7431ae3
--- /dev/null
@@ -0,0 +1,452 @@
+<?xml version='1.0'?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd"
+  exclude-result-prefixes="doc">
+<!--
+     Convert D-Bus Glib xml into DocBook refentries
+     Copyright (C) 2007 William Jon McCann
+     License: GPL
+-->
+<xsl:output method="xml" indent="yes" encoding="UTF-8"/>
+
+<xsl:template match="/node">
+  <reference>
+    <xsl:attribute name="id"><xsl:value-of select="@doc:id"/></xsl:attribute>
+    <title>
+      <xsl:value-of select="doc:doc/doc:summary"/>
+    </title>
+  <xsl:apply-templates select="interface"/>
+</reference>
+</xsl:template>
+
+<xsl:template match="interface">
+
+<xsl:variable name="interface" select="@name"/>
+<xsl:variable name="basename">
+  <xsl:call-template name="interface-basename">
+    <xsl:with-param name="str" select="$interface"/>
+  </xsl:call-template>
+</xsl:variable>
+
+<refentry><xsl:attribute name="id"><xsl:value-of select="$basename"/></xsl:attribute>
+  <refmeta>
+    <refentrytitle role="top_of_page"><xsl:value-of select="@name"/></refentrytitle>
+  </refmeta>
+
+  <refnamediv>
+    <refname><xsl:value-of select="@name"/></refname>
+    <refpurpose><xsl:value-of select="$basename"/> interface</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv role="synopsis">
+    <title role="synopsis.title">Methods</title>
+    <synopsis>
+  <xsl:call-template name="methods-synopsis">
+    <xsl:with-param name="basename" select="$basename"/>
+  </xsl:call-template>
+    </synopsis>
+  </refsynopsisdiv>
+
+  <refsect1 role="signal_proto">
+    <title role="signal_proto.title">Signals</title>
+    <synopsis>
+  <xsl:call-template name="signals-synopsis">
+    <xsl:with-param name="basename" select="$basename"/>
+  </xsl:call-template>
+    </synopsis>
+  </refsect1>
+
+  <refsect1 role="impl_interfaces">
+    <title role="impl_interfaces.title">Implemented Interfaces</title>
+    <para>
+    <xsl:value-of select="$interface"/> implements
+    org.freedesktop.DBus.Introspectable,
+    org.freedesktop.DBus.Properties
+    </para>
+  </refsect1>
+
+  <refsect1 role="properties">
+    <title role="properties.title">Properties</title>
+    <synopsis>
+  <xsl:call-template name="properties-synopsis">
+    <xsl:with-param name="basename" select="$basename"/>
+  </xsl:call-template>
+    </synopsis>
+  </refsect1>
+
+  <refsect1 role="desc">
+    <title role="desc.title">Description</title>
+    <para>
+      <xsl:apply-templates select="doc:doc"/>
+    </para>
+  </refsect1>
+
+  <refsect1 role="details">
+    <title role="details.title">Details</title>
+    <xsl:call-template name="method-details">
+      <xsl:with-param name="basename" select="$basename"/>
+    </xsl:call-template>
+  </refsect1>
+
+  <refsect1 role="signals">
+    <title role="signals.title">Signal Details</title>
+    <xsl:call-template name="signal-details">
+      <xsl:with-param name="basename" select="$basename"/>
+    </xsl:call-template>
+  </refsect1>
+
+  <refsect1 role="property_details">
+    <title role="property_details.title">Property Details</title>
+    <xsl:call-template name="property-details">
+      <xsl:with-param name="basename" select="$basename"/>
+    </xsl:call-template>
+  </refsect1>
+
+</refentry>
+</xsl:template>
+
+
+<xsl:template name="property-doc">
+  <xsl:apply-templates select="doc:doc/doc:description"/>
+
+  <variablelist role="params">
+    <xsl:for-each select="arg">
+<varlistentry><term><parameter><xsl:value-of select="@name"/></parameter>:</term>
+<listitem><simpara><xsl:value-of select="doc:doc/doc:summary"/></simpara></listitem>
+</varlistentry>
+    </xsl:for-each>
+  </variablelist>
+
+  <xsl:apply-templates select="doc:doc/doc:since"/>
+  <xsl:apply-templates select="doc:doc/doc:deprecated"/>
+  <xsl:apply-templates select="doc:doc/doc:permission"/>
+  <xsl:apply-templates select="doc:doc/doc:seealso"/>
+</xsl:template>
+
+
+<xsl:template name="property-details">
+  <xsl:param name="basename"/>
+  <xsl:variable name="longest">
+    <xsl:call-template name="find-longest">
+      <xsl:with-param name="set" select="@name"/>
+    </xsl:call-template>
+  </xsl:variable>
+  <xsl:for-each select="property">
+  <refsect2>
+    <title><anchor role="function"><xsl:attribute name="id"><xsl:value-of select="$basename"/>:<xsl:value-of select="@name"/></xsl:attribute></anchor>The "<xsl:value-of select="@name"/>" property</title>
+<indexterm><primary><xsl:value-of select="@name"/></primary><secondary><xsl:value-of select="$basename"/></secondary></indexterm>
+<programlisting>'<xsl:value-of select="@name"/>'<xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="2"/></xsl:call-template>
+<xsl:call-template name="property-args"><xsl:with-param name="indent" select="string-length(@name) + 2"/></xsl:call-template></programlisting>
+
+  <xsl:call-template name="property-doc"/>
+
+  </refsect2>
+  </xsl:for-each>
+</xsl:template>
+
+<xsl:template name="signal-doc">
+  <xsl:apply-templates select="doc:doc/doc:description"/>
+
+  <variablelist role="params">
+    <xsl:for-each select="arg">
+<varlistentry><term><parameter><xsl:value-of select="@name"/></parameter>:</term>
+<listitem><simpara><xsl:value-of select="doc:doc/doc:summary"/></simpara></listitem>
+</varlistentry>
+    </xsl:for-each>
+  </variablelist>
+
+  <xsl:apply-templates select="doc:doc/doc:since"/>
+  <xsl:apply-templates select="doc:doc/doc:deprecated"/>
+  <xsl:apply-templates select="doc:doc/doc:permission"/>
+  <xsl:apply-templates select="doc:doc/doc:seealso"/>
+</xsl:template>
+
+<xsl:template name="signal-details">
+  <xsl:param name="basename"/>
+  <xsl:variable name="longest">
+    <xsl:call-template name="find-longest">
+      <xsl:with-param name="set" select="@name"/>
+    </xsl:call-template>
+  </xsl:variable>
+  <xsl:for-each select="signal">
+  <refsect2>
+    <title><anchor role="function"><xsl:attribute name="id"><xsl:value-of select="$basename"/>::<xsl:value-of select="@name"/></xsl:attribute></anchor>The <xsl:value-of select="@name"/> signal</title>
+<indexterm><primary><xsl:value-of select="@name"/></primary><secondary><xsl:value-of select="$basename"/></secondary></indexterm>
+<programlisting><xsl:value-of select="@name"/> (<xsl:call-template name="signal-args"><xsl:with-param name="indent" select="string-length(@name) + 2"/><xsl:with-param name="prefix" select="."/></xsl:call-template>)</programlisting>
+
+  <xsl:call-template name="signal-doc"/>
+
+  </refsect2>
+  </xsl:for-each>
+</xsl:template>
+
+<xsl:template match="doc:code">
+<programlisting>
+<xsl:apply-templates />
+</programlisting>
+</xsl:template>
+
+<xsl:template match="doc:summary">
+<!-- by default don't display -->
+</xsl:template>
+
+<xsl:template match="doc:example">
+<informalexample>
+<xsl:apply-templates />
+</informalexample>
+</xsl:template>
+
+<xsl:template match="doc:para">
+<para>
+<xsl:apply-templates />
+</para>
+</xsl:template>
+
+<xsl:template match="doc:description">
+<xsl:apply-templates />
+</xsl:template>
+
+<xsl:template match="doc:since">
+<para role="since">Since <xsl:value-of select="@version"/>
+</para>
+</xsl:template>
+
+<xsl:template match="doc:deprecated">
+  <xsl:variable name="name" select="../../@name"/>
+  <xsl:variable name="parent">
+    <xsl:call-template name="interface-basename">
+      <xsl:with-param name="str" select="../../../@name"/>/>
+    </xsl:call-template>
+  </xsl:variable>
+
+  <xsl:variable name="type" select="name(../..)"/>
+
+  <para role="deprecated">
+  <warning><para><literal><xsl:value-of select="$name"/></literal> is deprecated since version <xsl:value-of select="@version"/> and should not be used in newly-written code. Use
+
+  <xsl:variable name="to">
+  <xsl:choose>
+    <xsl:when test="contains($type,'property')">
+      <xsl:value-of select="$parent"/>:<xsl:value-of select="@instead"/>
+    </xsl:when>
+    <xsl:when test="contains($type,'signal')">
+      <xsl:value-of select="$parent"/>::<xsl:value-of select="@instead"/>
+    </xsl:when>
+    <xsl:when test="contains($type,'method')">
+      <xsl:value-of select="$parent"/>.<xsl:value-of select="@instead"/>
+    </xsl:when>
+    <xsl:when test="contains($type,'interface')">
+      <xsl:value-of select="@instead"/>
+    </xsl:when>
+    <xsl:otherwise>
+      <xsl:value-of select="@instead"/>
+    </xsl:otherwise>
+  </xsl:choose>
+  </xsl:variable>
+
+  <xsl:call-template name="create-link">
+    <xsl:with-param name="type" select="$type"/>
+    <xsl:with-param name="to" select="$to"/>
+    <xsl:with-param name="val" select="@instead"/>
+  </xsl:call-template>
+instead.</para></warning>
+</para>
+</xsl:template>
+
+<xsl:template match="doc:permission">
+<para role="permission">
+<xsl:apply-templates />
+</para>
+</xsl:template>
+
+<xsl:template match="doc:seealso">
+<para>
+See also:
+<xsl:apply-templates />
+
+</para>
+</xsl:template>
+
+<xsl:template name="create-link">
+  <xsl:param name="type"/>
+  <xsl:param name="to"/>
+  <xsl:param name="val"/>
+
+  <xsl:choose>
+    <xsl:when test="contains($type,'property')">
+      <link><xsl:attribute name="linkend"><xsl:value-of select="$to"/></xsl:attribute><literal><xsl:value-of select="$val"/></literal></link>
+    </xsl:when>
+    <xsl:when test="contains($type,'signal')">
+      <link><xsl:attribute name="linkend"><xsl:value-of select="$to"/></xsl:attribute><literal><xsl:value-of select="$val"/></literal></link>
+    </xsl:when>
+    <xsl:when test="contains($type,'method')">
+      <link><xsl:attribute name="linkend"><xsl:value-of select="$to"/></xsl:attribute><function><xsl:value-of select="$val"/></function></link>
+    </xsl:when>
+    <xsl:when test="contains($type,'interface')">
+      <link><xsl:attribute name="linkend"><xsl:value-of select="$to"/></xsl:attribute><xsl:value-of select="$val"/></link>
+    </xsl:when>
+    <xsl:when test="contains($type,'xref')">
+      <xref><xsl:attribute name="linkend"><xsl:value-of select="$to"/></xsl:attribute></xref>
+    </xsl:when>
+  </xsl:choose>
+</xsl:template>
+
+<xsl:template match="doc:ref">
+  <xsl:call-template name="create-link">
+    <xsl:with-param name="type" select="@type"/>
+    <xsl:with-param name="to" select="@to"/>
+    <xsl:with-param name="val" select="."/>
+  </xsl:call-template>
+</xsl:template>
+
+<xsl:template name="method-doc">
+  <xsl:apply-templates select="doc:doc/doc:description"/>
+
+  <variablelist role="params">
+    <xsl:for-each select="arg">
+<varlistentry><term><parameter><xsl:value-of select="@name"/></parameter>:</term>
+<listitem>
+<para><xsl:value-of select="doc:doc/doc:summary"/></para>
+  <xsl:apply-templates select="doc:doc/doc:description"/>
+</listitem>
+</varlistentry>
+    </xsl:for-each>
+  </variablelist>
+
+  <xsl:apply-templates select="doc:doc/doc:since"/>
+  <xsl:apply-templates select="doc:doc/doc:deprecated"/>
+  <xsl:apply-templates select="doc:doc/doc:permission"/>
+  <xsl:apply-templates select="doc:doc/doc:seealso"/>
+</xsl:template>
+
+<xsl:template name="method-details">
+  <xsl:param name="basename"/>
+  <xsl:variable name="longest">
+    <xsl:call-template name="find-longest">
+      <xsl:with-param name="set" select="@name"/>
+    </xsl:call-template>
+  </xsl:variable>
+  <xsl:for-each select="method">
+    <refsect2>
+    <title><anchor role="function"><xsl:attribute name="id"><xsl:value-of select="$basename"/>.<xsl:value-of select="@name"/></xsl:attribute></anchor><xsl:value-of select="@name"/> ()</title>
+<indexterm><primary><xsl:value-of select="@name"/></primary><secondary><xsl:value-of select="$basename"/></secondary></indexterm>
+<programlisting><xsl:value-of select="@name"/> (<xsl:call-template name="method-args"><xsl:with-param name="indent" select="string-length(@name) + 2"/><xsl:with-param name="prefix" select="."/></xsl:call-template>)</programlisting>
+
+    <xsl:call-template name="method-doc"/>
+    </refsect2>
+
+  </xsl:for-each>
+</xsl:template>
+
+
+<xsl:template name="properties-synopsis">
+  <xsl:param name="basename"/>
+  <xsl:variable name="longest">
+    <xsl:call-template name="find-longest">
+      <xsl:with-param name="set" select="property/@name"/>
+    </xsl:call-template>
+  </xsl:variable>
+  <xsl:for-each select="property">
+<link><xsl:attribute name="linkend"><xsl:value-of select="$basename"/>:<xsl:value-of select="@name"/></xsl:attribute>'<xsl:value-of select="@name"/>'</link><xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="$longest - string-length(@name) + 1"/></xsl:call-template> <xsl:call-template name="property-args"><xsl:with-param name="indent" select="$longest + 2"/></xsl:call-template>
+</xsl:for-each>
+</xsl:template>
+
+
+<xsl:template name="signals-synopsis">
+  <xsl:param name="basename"/>
+  <xsl:variable name="longest">
+    <xsl:call-template name="find-longest">
+      <xsl:with-param name="set" select="signal/@name"/>
+    </xsl:call-template>
+  </xsl:variable>
+  <xsl:for-each select="signal">
+<link><xsl:attribute name="linkend"><xsl:value-of select="$basename"/>::<xsl:value-of select="@name"/></xsl:attribute><xsl:value-of select="@name"/></link><xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="$longest - string-length(@name) + 1"/></xsl:call-template>(<xsl:call-template name="signal-args"><xsl:with-param name="indent" select="$longest + 2"/><xsl:with-param name="prefix" select="signal"/></xsl:call-template>)
+</xsl:for-each>
+</xsl:template>
+
+
+<xsl:template name="methods-synopsis">
+  <xsl:param name="basename"/>
+  <xsl:variable name="longest">
+    <xsl:call-template name="find-longest">
+      <xsl:with-param name="set" select="method/@name"/>
+    </xsl:call-template>
+  </xsl:variable>
+  <xsl:for-each select="method">
+<link><xsl:attribute name="linkend"><xsl:value-of select="$basename"/>.<xsl:value-of select="@name"/></xsl:attribute><xsl:value-of select="@name"/></link><xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="$longest - string-length(@name) + 1"/></xsl:call-template>(<xsl:call-template name="method-args"><xsl:with-param name="indent" select="$longest + 2"/><xsl:with-param name="prefix" select="method"/></xsl:call-template>)
+</xsl:for-each>
+</xsl:template>
+
+
+<xsl:template name="method-args"><xsl:param name="indent"/><xsl:param name="prefix"/><xsl:variable name="longest"><xsl:call-template name="find-longest"><xsl:with-param name="set" select="$prefix/arg/@type"/></xsl:call-template></xsl:variable><xsl:for-each select="arg"><xsl:value-of select="@direction"/>
+<xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="4 - string-length(@direction)"/></xsl:call-template>'<xsl:value-of select="@type"/>'<xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="$longest - string-length(@type) + 1"/></xsl:call-template>
+<xsl:value-of select="@name"/><xsl:if test="not(position() = last())">,
+<xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="$indent"/></xsl:call-template></xsl:if>
+</xsl:for-each>
+</xsl:template>
+
+
+<xsl:template name="signal-args"><xsl:param name="indent"/><xsl:param name="prefix"/><xsl:variable name="longest"><xsl:call-template name="find-longest"><xsl:with-param name="set" select="$prefix/arg/@type"/></xsl:call-template></xsl:variable><xsl:for-each select="arg">'<xsl:value-of select="@type"/>'<xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="$longest - string-length(@type) + 1"/></xsl:call-template>
+<xsl:value-of select="@name"/><xsl:if test="not(position() = last())">,
+<xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="$indent"/></xsl:call-template></xsl:if>
+</xsl:for-each>
+</xsl:template>
+
+
+<xsl:template name="property-args"><xsl:param name="indent"/>
+<xsl:value-of select="@access"/><xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="9 - string-length(@access) + 1"/></xsl:call-template>'<xsl:value-of select="@type"/>'
+</xsl:template>
+
+
+<xsl:template name="pad-spaces">
+  <xsl:param name="width"/>
+  <xsl:variable name="spaces" xml:space="preserve">                                                                        </xsl:variable>
+  <xsl:value-of select="substring($spaces,1,$width)"/>
+</xsl:template>
+
+
+<xsl:template name="find-longest">
+  <xsl:param name="set"/>
+  <xsl:param name="index" select="1"/>
+  <xsl:param name="longest" select="0"/>
+
+  <xsl:choose>
+    <xsl:when test="$index > count($set)">
+      <!--finished looking-->
+      <xsl:value-of select="$longest"/>
+    </xsl:when>
+    <xsl:when test="string-length($set[$index])>$longest">
+      <!--found new longest-->
+      <xsl:call-template name="find-longest">
+        <xsl:with-param name="set" select="$set"/>
+        <xsl:with-param name="index" select="$index + 1"/>
+        <xsl:with-param name="longest" select="string-length($set[$index])"/>
+      </xsl:call-template>
+    </xsl:when>
+    <xsl:otherwise>
+      <!--this isn't any longer-->
+      <xsl:call-template name="find-longest">
+        <xsl:with-param name="set" select="$set"/>
+        <xsl:with-param name="index" select="$index + 1"/>
+        <xsl:with-param name="longest" select="$longest"/>
+      </xsl:call-template>
+    </xsl:otherwise>
+  </xsl:choose>
+</xsl:template>
+
+
+<xsl:template name="interface-basename">
+  <xsl:param name="str"/>
+  <xsl:choose>
+    <xsl:when test="contains($str,'.')">
+      <xsl:call-template name="interface-basename">
+       <xsl:with-param name="str" select="substring-after($str,'.')"/>
+      </xsl:call-template>
+    </xsl:when>
+    <xsl:otherwise>
+      <xsl:value-of select="$str"/>
+    </xsl:otherwise>
+  </xsl:choose>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/src/dbus/interfaces/syncevo-connection-full.xml b/src/dbus/interfaces/syncevo-connection-full.xml
new file mode 100644 (file)
index 0000000..b6b4c13
--- /dev/null
@@ -0,0 +1,147 @@
+<?xml version="1.0"?>
+<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
+  <interface name="org.syncevolution.Connection">
+    <doc:doc>
+      <doc:para>
+        The SyncEvolution connection object can be used to exchange
+        messages.
+      </doc:para>
+    </doc:doc>
+
+    <method name="Process">
+      <doc:doc>
+        <doc:summary>
+          Pass data to SyncEvolution. The response is returned
+          via the Reply-signal, so subscribe to that first.
+        </doc:summary>
+      </doc:doc>
+
+      <arg type="ay" name="message" direction="in">
+        <doc:doc>
+          <doc:summary>
+            The data to be processed. Empty messages are invalid
+            and will trigger an error.
+          </doc:summary>
+        </doc:doc>
+      </arg>
+
+      <arg type="s" name="message_type" direction="in">
+        <doc:doc>
+          <doc:summary>
+            The MIME type of the
+            message. "application/vnd.syncml.ds.notification",
+            "application/vnd.syncml+xml" and
+            "application/vnd.syncml+wbxml" are currently supported.
+          </doc:summary>
+        </doc:doc>
+      </arg>
+    </method>
+
+    <method name="Close">
+      <doc:doc>
+        <doc:summary>
+          Indicates that the connection object is no longer needed.
+        </doc:summary>
+      </doc:doc>
+
+      <arg type="b" name="normal" direction="in">
+        <doc:doc>
+          <doc:summary>
+            TRUE if the connection is being closed after successfully
+            delivering the final response. FALSE if an error is
+            encountered that cannot be handled by the peer or its
+            transport. SyncEvolution cannot rely on getting a close(FALSE)
+            call in all cases. If its caller disappears from the bus
+            it must assume that there was a fatal error and close the
+            connection.
+          </doc:summary>
+        </doc:doc>
+      </arg>
+
+      <arg type="s" name="error" direction="in">
+        <doc:doc>
+          <doc:summary>
+            A description which explains the error, may be empty.
+            Used for debugging.
+          </doc:summary>
+        </doc:doc>
+      </arg>
+    </method>
+
+    <signal name="Reply">
+      <arg type="ay" name="reply">
+        <doc:doc>
+          <doc:summary>
+            The data to be returned to the peer. An empty reply is
+            possible as response to the last message; it must not be
+            delivered. Instead, final will be true and the connection
+            needs to be closed.
+
+            It is possible that a non-empty reply is sent without the
+            final flag, immediately followed by an empty reply which
+            has the flag set. As described above, the empty reply must
+            be ignored and close() must be called once the non-empty
+            reply is delivered.
+          </doc:summary>
+        </doc:doc>
+      </arg>
+
+      <arg type="s" name="reply_type">
+        <doc:doc>
+          <doc:summary>
+            The MIME type of the reply. The same types as for the
+            message are supported.
+          </doc:summary>
+        </doc:doc>
+      </arg>
+
+      <arg type="a{ss}" name="meta">
+        <doc:doc>
+          <doc:summary>
+            Transport specific meta information. Currently defined:
+            "URL" - the URL for an HTTP POST.
+          </doc:summary>
+        </doc:doc>
+      </arg>      
+
+      <arg type="b" name="final">
+        <doc:doc>
+          <doc:summary>
+            True if this is the last reply. No further messages are
+            expected and the session should be closed once the reply
+            was delivered successfully.
+          </doc:summary>
+        </doc:doc>
+      </arg>
+
+      <arg type="s" name="session">
+        <doc:doc>
+          <doc:summary>
+            The first message in a new connection triggers the
+            creation of a new, random session ID which is returned
+            together with the response. The caller is responsible for
+            ensuring that only messages belonging to this session are
+            passed to future process() calls.
+
+            In practice the session ID does not change after the
+            first message, but this is not guaranteed and the caller
+            should always use the most recent value.
+          </doc:summary>
+        </doc:doc>
+      </arg>
+    </signal>
+
+    <signal name="Abort">
+      <doc:doc>
+        <doc:summary>
+          Sent when the server has to shut down the connection.  All
+          further operations on it will fail.  Resuming the connection
+          may or may not work in such a case.
+
+          This signal is sent at most once for each connection. No
+          reply will be sent on an aborted connection.
+        </doc:summary>
+      </doc:doc>
+    </signal>
+  </interface>
+</node>
index 42a8aaf..1fc1368 100644 (file)
@@ -1,2 +1,7 @@
 VOID:STRING,STRING,INT,INT,INT,INT
 VOID:STRING,STRING
+VOID:STRING,BOOLEAN
+VOID:STRING,STRING,STRING
+VOID:STRING,STRING,STRING,STRING,STRING
+VOID:INT,BOXED
+VOID:UINT,UINT,BOXED
diff --git a/src/dbus/interfaces/syncevo-server-full.xml b/src/dbus/interfaces/syncevo-server-full.xml
new file mode 100644 (file)
index 0000000..11f6ed7
--- /dev/null
@@ -0,0 +1,563 @@
+<?xml version="1.0"?>
+<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
+  <interface name="org.syncevolution.Server">
+    <doc:doc>
+      <doc:para>
+        Server is the entry object for SyncEvolution client API. It
+        can be used to query information and to start and monitor
+        sessions.
+      </doc:para>
+
+      <doc:para>
+        Sessions are required to modify the state of SyncEvolution and
+        to synchronize data. They are implemented by additional
+        objects, which exist as long as they are needed (= have
+        clients) or are executing (for example, running a sync
+        session).
+      </doc:para>
+
+      <doc:para>
+        A session must be active before it can be used. If there are
+        multiple conflicting session requests, they will be queued and
+        started one after the other. At the moment, SyncEvolution
+        will only run one session at a time, although the API would
+        allow concurrent sessions.
+      </doc:para>
+
+      <doc:para>
+        To be notified when a session is ready for use, subscribe to
+        the SessionChanged signal before asking for a session. It
+        may fire before the request to create a session returns. Either
+        handle that or use Session.GetStatus() to check whether the
+        session is still "queueing".
+      </doc:para>
+
+      <doc:para>
+        Method calls may fail with the following errors:
+        "org.syncevolution.Exception" - catch-all error condition.
+        "org.syncevolution.NoSuchConfig" - server configuration name is invalid
+        "org.syncevolution.NoSuchSource" - source name is invalid
+        "org.syncevolution.SourceUnusable" - CheckSource() may return this
+        if source is not usable (for various possible reasons).
+        "org.syncevolution.InvalidCall" - a call is (perhaps no longer) allowed
+        or suitable in the current situation, like Detach() when the client
+        is not attached.
+      </doc:para>
+    </doc:doc>
+
+    <method name="Attach">
+      <doc:doc>
+        <doc:description>
+          With no client attached, the server will shut down after a
+          certain period of inactivity. Attaching to the server
+          prevents that. Attaching is not necessary to invoke methods.
+          The main purpose is to keep the server running while clients
+          are around and listen for signals, in particular the
+          Presence signal.
+        </doc:description>
+      </doc:doc>
+    </method>
+
+    <method name="Detach">
+      <doc:doc>
+        <doc:description>
+          Detaches an attached client. A client which disconnects
+          from D-Bus is automatically detached from the server.
+        </doc:description>
+      </doc:doc>
+    </method>
+
+    <method name ="GetConfigs">
+      <doc:doc><doc:description>
+        Get an array of all configured servers (or templates)
+      </doc:description></doc:doc>
+      <arg type="b" name="template" direction="in">
+        <doc:doc><doc:summary>
+          if TRUE, will return template names, otherwise will return 
+          configured servers
+        </doc:summary></doc:doc>
+      </arg>
+      <arg type="as" name="servers" direction="out">
+        <doc:doc><doc:summary>
+          array of configured server (or template) names
+        </doc:summary></doc:doc>
+      </arg>
+    </method>
+
+    <method name="GetConfig">
+      <doc:doc><doc:description>
+        Get the configuration of a specific server (or template)
+      </doc:description></doc:doc>
+      <arg type="s" name="server" direction="in">
+        <doc:doc><doc:summary>server name</doc:summary></doc:doc>
+      </arg>
+      <arg type="b" name="template" direction="in">
+        <doc:doc><doc:summary>
+          if TRUE, will return a matching template configuration, otherwise
+          will return a matching server configuration
+        </doc:summary></doc:doc>
+      </arg>
+      <arg type="a{sa{ss}}" name="configuration" direction="out">
+        <doc:doc><doc:summary>
+          server (or template) configuration
+        </doc:summary></doc:doc>
+        <doc:doc><doc:description>
+          The dictionary keys are "source/&lt;source name&gt;" for
+          sources and the empty string for the main server
+          configuration. More keys might be added in the future. The
+          values are "configuration dictionaries" which contain keys
+          and values matching those in the SyncEvolution server 
+          configuration files. 
+          Properties which are not set are also not present in the
+          configuration dictionaries. The semantic difference between
+          "not set" and "empty" or "set to default" is that unset
+          values will always use the default value, even after that
+          changed during a software update. Properties that are set
+          always use the chosen value.
+
+          Note that property keys are case insensitive. The D-Bus
+          interface specification would allow to send two
+          properties whose keys only differ in case to the
+          server. The result is undefined.
+        </doc:description></doc:doc>
+      </arg>
+    </method>
+
+    <method name="CheckPresence">
+      <doc:doc><doc:description>
+        Checks whether a sync with a particular server can start.
+      </doc:description></doc:doc>
+      <arg type="s" name="server" direction="in">
+        <doc:doc><doc:summary>server name</doc:summary></doc:doc>
+      </arg>
+      <arg type="s" name="status" direction="out">
+        <doc:doc>
+          <doc:summary>
+            See Presence signal for details.
+          </doc:summary>
+        </doc:doc>
+      </arg>
+      <arg type="as" name="transports" direction="out">
+        <doc:doc>
+          <doc:summary>
+            All currently available transports. See Presence signal for details.
+          </doc:summary>
+        </doc:doc>
+      </arg>
+    </method>      
+
+    <method name="GetReports">
+      <doc:doc><doc:description>
+        Get synchronization reports for a specific server
+      </doc:description></doc:doc>
+      <arg type="s" name="server" direction="in">
+        <doc:doc><doc:summary>server name</doc:summary></doc:doc>
+      </arg>
+      <arg type="u" name="start" direction="in">
+        <doc:doc><doc:summary>
+          index of the first (newest) report that will be returned;
+          reports are number starting with zero for the newest
+        </doc:summary></doc:doc>
+      </arg>
+      <arg type="u" name="count" direction="in">
+        <doc:doc><doc:summary>
+          maximum number of returned reports
+        </doc:summary></doc:doc>
+      </arg>
+      <arg type="aa{ss}" name="reports" direction="out">
+        <doc:doc><doc:summary>synchronization reports</doc:summary></doc:doc>
+        <doc:doc><doc:description>The array contains report dictionaries. The dictionary keys can be defined by below BNFs:
+                Key ::= 'start' | 'end' | 'status' | SourceKey
+                SourceKey ::= SourcePrefix SourcePart
+                SourcePrefix ::= 'source' Sep SourceName
+                SourceName ::= character+ 
+                SourcePart ::= Sep ('mode' | 'first' | 'resume' | 'status' | 'backup-before' 
+                               | 'backup-after' | StatPart)
+                StatPart ::= 'stat' Sep LocName Sep StateName Sep ResultName
+                LocName ::= 'local' | 'remote'
+                StateName ::= 'added' | 'updated' | 'removed' | 'any'
+                ResultName ::= 'total' | 'reject' | 'match' | 'conflict_server_won' | 'conflict_client_won' 
+                                | 'conflict_duplicated' | 'sent' | 'received'
+                Sep ::= '-'
+
+                If SourceName has characters '_' and '-', they will be
+                escaped with '__' and '_+' respectively. This means
+                that a key can be split at '-' before replacing these
+                escape sequences in the source name.
+
+                For a key which contains StatPart, if its value is 0,
+                its pair-value won't be included in the dictionary.
+        </doc:description></doc:doc>
+      </arg>
+    </method>
+
+    <method name="GetDatabases">
+      <doc:doc>
+        <doc:description>
+          Get list of available databases that can be synchronized
+          by a source backend.
+        </doc:description>
+      </doc:doc>
+      <arg type="s" name="server" direction="in">
+        <doc:doc><doc:summary>server name</doc:summary></doc:doc>
+      </arg>
+      <arg type="s" name="source" direction="in">
+        <doc:doc>
+          <doc:summary>
+            name of the source configuration which defines
+            the backend ("type" property)
+          </doc:summary>
+        </doc:doc>
+      </arg>
+      <arg type="a(ssb)" name="databases" direction="out">
+        <doc:doc><doc:summary>information about all available databases</doc:summary></doc:doc>
+        <doc:doc>
+          <doc:description>
+            each entry contains in this order:
+            an optional name that can be shown to the user
+            (already localized or chosen by the user, empty if unavailable),
+            a unique value for the "evolutionSource" property,
+            a boolean which is true at most once for the default source
+          </doc:description>
+        </doc:doc>
+      </arg>
+    </method>
+
+    <method name="CheckSource">
+      <doc:doc>
+        <doc:description>Tests whether the source configuration
+          is correct. Raises the SourceUnusable exception if not.
+        </doc:description>
+      </doc:doc>
+      <arg type="s" name="server" direction="in">
+        <doc:doc><doc:summary>server name</doc:summary></doc:doc>
+      </arg>
+      <arg type="s" name="source" direction="in">
+        <doc:doc>
+          <doc:summary>
+            name of the source configuration which is to be tested
+          </doc:summary>
+        </doc:doc>
+      </arg>
+    </method>
+
+    <method name="StartSession">
+      <doc:doc><doc:description>
+        Start a session. The object is created instantly but will not be
+        ready for method calls until status changes from "queueing" to "idle".
+        The Detach() method can be called before that.
+      </doc:description></doc:doc>
+      <arg type="s" name="server" direction="in">
+        <doc:doc><doc:summary>server name</doc:summary></doc:doc>
+      </arg>
+      <arg type="o" name="session" direction="out">
+        <doc:doc><doc:summary>session D-Bus object path</doc:summary></doc:doc>
+      </arg>
+    </method>
+
+    <method name="Connect">
+      <doc:doc>
+        <doc:description>
+          <doc:para>
+            Establishes a connection between SyncEvolution and a peer
+            (SyncML client or server). That peer might contact
+            SyncEvolution via D-Bus directly (local sync) or via a
+            SyncEvolution server stub that acts as gateway between a
+            peer that is connected to the stub via some other
+            transport mechanism (remote sync). For SyncEvolution this
+            difference is almost completely transparent.
+          </doc:para>
+
+          <doc:para>
+            In contrast to connections established by SyncEvolution
+            itself, the peer has to send the first message and
+            SyncEvolution replies. If the first message is a normal
+            SyncML message, then SyncEvolution acts as SyncML server.
+            Alternatively, a Notification message can be sent to
+            request that SyncEvolution initiates a SyncML session as
+            client.
+          </doc:para>
+
+          <doc:para>
+            In the later case, SyncEvolution may or may not use the
+            connection established by Connect(), depending on the
+            content of that first message.
+          </doc:para>
+
+          <doc:para>
+            The result of Connect() is an object that implements the
+            org.syncevolution.Connection interface. It has to be used
+            for sending at least one message to start the sync. If
+            SyncEvolution needs to abort the connection, it will issue
+            the Close-signal and remove the object. A peer needs to
+            subscribe to that signal before starting to wait for a
+            reply. In addition, the client should also watch out for
+            SyncEvolution quitting unexpectedly.
+          </doc:para>
+
+          <doc:para>
+            SyncEvolution supports re-establishing a connection that was
+            interrupted. This only works when the peer is a SyncML
+            client, supports resending messages, and the non-D-Bus
+            message transport supports sending the session number as
+            part of the meta information.
+          </doc:para>
+        </doc:description>
+      </doc:doc>
+      <arg type="a{ss}" name="peer" direction="in">
+        <doc:doc>
+          <doc:summary>
+            Various information about the peer who initiated the
+            connection. All of it is optional unless explicitly
+            specified otherwise. Short, single line strings are
+            preferred.
+
+            "description" - a description of the peer in a format and
+            language that is understood by the user.
+
+            "id" - a unique ID for this particular peer, in a format
+            that is specific to the transport. The ID only has to be
+            unique among peers using that transport at the current
+            point in time.
+
+            "transport" - a string identifying the entity which talks
+            directly to SyncEvolution (peer or transport stub). If
+            available, this should be a D-Bus interface name, like
+            "org.openobex.obexd". The main purpose right now is for
+            informing the user and debugging.  Later it might also be
+            used to call methods in that interface or for choosing a
+            local configuration for the peer based on its ID.
+
+            "transport_description" - could be used to describe the
+            version of the transport entity.
+          </doc:summary>
+        </doc:doc>
+      </arg>
+      <arg type="b" name="must_authenticate" direction="in">
+        <doc:doc>
+          <doc:summary>
+            <doc:para>
+              If false, then the peer is trusted and shall be given
+              access to SyncEvolution without further checks by
+              SyncEvolution itself. This is useful for peers which
+              already run as local user processes with same access
+              rights to the data as SyncEvolution or for transports that
+              authenticate and authorize access via their own
+              mechanisms.
+            </doc:para>
+
+            <doc:para>
+              If true, then a SyncML client peer must provide valid
+              credentials as part of the SyncML session. For a server,
+              a valid configuration must exist. SyncEvolution searches
+              for such a configuration by matching the sync URL in
+              the Notification with sync URLs in the configurations.
+            </doc:para>
+          </doc:summary>
+        </doc:doc>
+      </arg>
+      <arg type="s" name="session" direction="in">
+        <doc:doc>
+          <doc:summary>
+            If this is a reconnect for an older session,
+            then pass the session ID here. Otherwise
+            pass an empty string. New session IDs are created in
+            response to the initial message, see Reply signal.
+          </doc:summary>
+        </doc:doc>
+      </arg>      
+      <arg type="o" name="connection" direction="out">
+        <doc:doc>
+          <doc:summary>
+            The connection object created by SyncEvolution in response
+            to this connection request. Implements the
+            org.syncevolution.Connection interface.
+          </doc:summary>
+        </doc:doc>
+      </arg>
+    </method>
+
+    <method name="GetSessions">
+      <doc:doc><doc:description>
+        Get currently existing sessions. This includes active and
+        queueing sessions.
+      </doc:description></doc:doc>
+      <arg type="ao" name="sessions" direction="out">
+        <doc:doc><doc:summary>array of session D-Bus object paths,
+            in the order in which they will run, running ones first</doc:summary></doc:doc>
+      </arg>
+    </method>
+
+    <signal name="SessionChanged">
+      <doc:doc><doc:description>Session start or end</doc:description></doc:doc>
+      <arg type="o" name="session">
+        <doc:doc><doc:summary>session D-Bus object path</doc:summary></doc:doc>
+      </arg>
+      <arg type="b" name="started">
+        <doc:doc><doc:summary>
+          TRUE if session was started and is active now (= ready for use),
+          FALSE if it ended
+        </doc:summary></doc:doc>
+      </arg>
+    </signal>
+
+    <signal name="Presence">
+      <doc:doc>
+        <doc:description>
+          Indicates whether a server can be reached right now.  This
+          signal can be used by GUIs to prevent starting a sync when
+          it is known to fail, for example because the network is
+          currently down.
+
+          At the moment, the SyncEvolution server can only monitor
+          network connectivity, which is a cheap local operation and
+          thus done unconditionally while the server runs (see
+          Attach()). Detecting the presence of non-HTTP-based peers
+          might be more costly. Additional APIs might be added to turn
+          that on only when needed. The CheckPresence() method will
+          always force a check.
+        </doc:description>
+      </doc:doc>
+      <arg type="s" name="server">
+        <doc:doc><doc:summary>
+          name of the server configuration
+        </doc:summary></doc:doc>
+      </arg>
+      <arg type="s" name="status">
+        <doc:doc>
+          <doc:summary>
+            "no transport" - the transport necessary to reach the server is not working.
+            "not present" - the server is known to be down or unreachable.
+            "" - the server might be usable. Syncs can still fail.
+            Other non-empty strings might be added in the future. They always
+            indicate a condition which prevents syncing.
+          </doc:summary>
+        </doc:doc>
+      </arg>
+      <arg type="s" name="transport">
+        <doc:doc>
+          <doc:summary>
+            If the server can be reached via multiple transports, this
+            is the one which triggered the signal. Content of the
+            string to be decided...
+          </doc:summary>
+        </doc:doc>
+      </arg>
+    </signal>
+
+    <signal name="InfoRequest">
+      <doc:doc>
+        <doc:description>
+          <doc:para>
+            Emitted whenever the server needs information that only a
+            client can provide. Because the server does not know whether
+            clients are monitoring it (attaching to the server is
+            optional) and/or which of the attached clients are able to
+            handle the request, it broadcasts the request.
+          </doc:para>
+
+          <doc:para>
+            Clients react by calling InfoResponse.  The flow is this:
+            information needed, InfoRequest("request"),
+            InfoResponse("working") + dialog is opened (if necessary),
+            InfoRequest("waiting"), information becomes available,
+            InfoResponse("response"), InfoRequest("done").
+          </doc:para>
+
+          <doc:para>
+            Clients should work on those requests that they support,
+            unless another client was faster (InfoRequest("waiting")).
+            Because there is a race condition, multiple dialogs might
+            be opened. The user only has to enter data in one of them.
+            A client can close his dialog upon InfoRequest("done")
+            and/or InfoRequest("waiting") with a 'handler' parameter
+            which is some other client. If the server does not get a
+            InfoResponse("working") soon enough (in the range of
+            minutes, not seconds), it has to assume that no client can
+            provide the information and fall back to some default or
+            abort.
+          </doc:para>
+        </doc:description>
+      </doc:doc>
+
+      <arg type="s" name="id">
+        <doc:doc><doc:summary>unique ID for the request</doc:summary></doc:doc>
+      </arg>
+      <arg type="o" name="session">
+        <doc:doc><doc:summary>the Session which is affected, may be empty</doc:summary></doc:doc>
+      </arg>
+      <arg type="s" name="state">
+        <doc:doc>
+          <doc:summary>
+            "request" for a new request,
+            "waiting" for one which is being serviced by some client,
+            "done" for a request which was resolved or timed out
+          </doc:summary>
+        </doc:doc>
+      </arg>
+      <arg type="o" name="handler">
+        <doc:doc>
+          <doc:summary>
+            for state="waiting": the client which first replied
+            with InfoResponse("working")
+          </doc:summary>
+        </doc:doc>
+      </arg>
+      <arg type="s" name="type">
+        <doc:doc>
+          <doc:summary>
+            Determines which information is needed. Currently only
+            "password" for interactive password requests is defined.
+          </doc:summary>
+        </doc:doc>
+      </arg>
+
+      <arg type="a{ss}" name="parameters">
+        <doc:doc>
+          <doc:summary>
+            Auxiliary parameters which depend on the type.
+
+            For "password" the following keys are used:
+            "name" - name of the password property in the config.
+            "description" - unique English description of the required password.
+            Content is determined by the individual password property, so this
+            may change. Currently used are "SyncML Server", "proxy",
+            "'source name' backend" (with 'source name' replaced by the same
+            names also used for the corresponding config entry).
+            "user", "server", "domain", "object", "protocol", "authtype", "port" -
+            optional keys as they would be used in the GNOME keyring.
+          </doc:summary>
+        </doc:doc>
+      </arg>
+    </signal>
+
+    <method name="InfoResponse">
+      <doc:doc><doc:description>reply for a specific InfoRequest</doc:description></doc:doc>
+
+      <arg type="s" name="id">
+        <doc:doc><doc:summary>unique ID sent by InfoRequest</doc:summary></doc:doc>
+      </arg>
+      <arg type="s" name="state">
+        <doc:doc>
+          <doc:summary>
+            "working" to indicate that a response will be sent later,
+            "response" for the actual reply
+          </doc:summary>
+        </doc:doc>
+      </arg>
+
+      <arg type="a{ss}" name="response">
+        <doc:doc>
+          <doc:summary>
+            Response values, valid in state="response", depend on type.
+
+            For "password" the following keys are used:
+            "password" - the password text, optional, do not set the key if the
+            user cancelled the request
+          </doc:summary>
+        </doc:doc>
+      </arg>
+    </method>
+
+  </interface>
+</node>
diff --git a/src/dbus/interfaces/syncevo-session-full.xml b/src/dbus/interfaces/syncevo-session-full.xml
new file mode 100644 (file)
index 0000000..950ab35
--- /dev/null
@@ -0,0 +1,221 @@
+<?xml version="1.0"?>
+<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
+  <interface name="org.syncevolution.Session">
+    <doc:doc><doc:description>
+      <doc:para>A Session object is used to do do syncs and to modify the server configurations. Clients can create a Session with Server.StartSession() and detach from it with Session.Detach().</doc:para>
+      <doc:para>Commands (other than Detach()) cannot be used before the status changes to "idle" (see GetStatus() and StatusChanged).</doc:para>
+    </doc:description></doc:doc>
+
+    <method name="GetConfig">
+      <doc:doc><doc:description>Get the configuration of the server</doc:description></doc:doc>
+      <arg type="b" name="template" direction="in">
+        <doc:doc><doc:summary>if TRUE, will return a matching template configuration, otherwise will return a matching server configuration</doc:summary></doc:doc>
+      </arg>
+      <arg type="a{sa{ss}}" name="configuration" direction="out">
+        <doc:doc><doc:summary>server configuration</doc:summary></doc:doc>
+        <doc:doc><doc:description>See Server.GetConfig() for dictionary description.</doc:description></doc:doc>
+      </arg>
+    </method>
+
+    <method name="SetConfig">
+      <doc:doc><doc:description>Set the configuration of the server</doc:description></doc:doc>
+      <arg type="b" name="update" direction="in">
+        <doc:doc><doc:summary>TRUE if existing configuration should be updated. FALSE if existing configuration should be cleared.
+            "Cleared" in this context means that all existing
+            properties are removed before setting those passed as
+            argument. Configuration entries (the user-visible part as
+            well as the related meta information, plus the containing
+            directory if it is empty) which are not referenced by a
+            key in the configuration are removed. Setting a completely
+            empty configuration with "update=FALSE" can thus be used
+            to remove the entire configuration.
+
+            "Completely empty" means "no entries at all" ({} in Python
+            notation). This is different from a config with no properties
+            set ({"": {}} = sync properties reset to defaults, no sources;
+            {"": {}, "source/addressbook": {}} = same, with address book
+            reset to defaults).
+
+            When a specific peer was selected via the configuration
+            name, clearing and removing properties is done only
+            for the peer-specific properties.
+
+            When no specific peer was selected, setting an empty
+            configuration with "update=FALSE" removes all source
+            settings and all peers. This allows starting from scratch;
+            setting a non-empty configuration with "update=FALSE"
+            will replace the peer-independent source properties with
+            those that are sent in the new configuration and remove
+            the sources which are not listed, also in all peers.
+        </doc:summary></doc:doc>
+      </arg>
+      <arg type="b" name="temporary" direction="in">
+        <doc:doc><doc:summary>TRUE if configuration changes should only be used for the duration of the session.
+            This is useful to run a single sync session with different settings,
+            for example with an increased logging level. "update=FALSE" and
+            "temporary=TRUE" are mutually exclusive. Temporary config changes
+            do not affect getting or setting permanent configurations.
+        </doc:summary></doc:doc>
+      </arg>
+      <arg type="a{sa{ss}}" name="configuration" direction="in">
+        <doc:doc><doc:summary>server configuration</doc:summary></doc:doc>
+        <doc:doc><doc:description>See Server.GetConfig() for dictionary description.</doc:description></doc:doc>
+      </arg>
+    </method>
+
+    <method name="GetReports">
+      <doc:doc><doc:description>Get synchronization reports for the server</doc:description></doc:doc>
+      <arg type="u" name="start" direction="in">
+        <doc:doc><doc:summary>index of the first (newest) report that will be returned</doc:summary></doc:doc>
+      </arg>
+      <arg type="u" name="count" direction="in">
+        <doc:doc><doc:summary>maximum number of returned reports</doc:summary></doc:doc>
+      </arg>
+      <arg type="aa{ss}" name="reports" direction="out">
+        <doc:doc><doc:summary>synchronization reports</doc:summary></doc:doc>
+        <doc:doc><doc:description>See Server.GetReports() for array description.</doc:description></doc:doc>
+      </arg>
+    </method>
+
+    
+    <method name="GetDatabases">
+      <doc:doc>
+        <doc:description>
+          Get list of available databases that can be synchronized
+          by a source backend.
+        </doc:description>
+      </doc:doc>
+      <arg type="s" name="source" direction="in">
+        <doc:doc>
+          <doc:summary>
+            name of the source configuration which defines
+            the backend ("type" property); a temporary config
+            is allowed here
+          </doc:summary>
+        </doc:doc>
+      </arg>
+      <arg type="a(ssb)" name="databases" direction="out">
+        <doc:doc><doc:summary>information about all available databases</doc:summary></doc:doc>
+        <doc:doc>
+          <doc:description>
+            each entry contains in this order:
+            an optional name that can be shown to the user
+            (already localized or chosen by the user, empty if unavailable),
+            a unique value for the "evolutionSource" property,
+            a boolean which is true at most once for the default source
+          </doc:description>
+        </doc:doc>
+      </arg>
+    </method>
+
+    <method name="CheckSource">
+      <doc:doc>
+        <doc:description>Tests whether the source configuration
+          is correct. Raises the SourceUnusable exception if not.
+        </doc:description>
+      </doc:doc>
+      <arg type="s" name="source" direction="in">
+        <doc:doc>
+          <doc:summary>
+            name of the source configuration which is to be tested;
+            a temporary config is allowed here
+          </doc:summary>
+        </doc:doc>
+      </arg>
+    </method>
+
+    <method name="Sync">
+      <doc:doc><doc:description>
+        <doc:para>
+          Start synchronization. The synchronization mode selection for sources works like this: Primarily, use mode from "sources" array. If the source was not found or its mode was empty, use the mode parameter. If mode parameter is empty, use the mode in configuration.
+              Examples:
+              * sync all with mode from config
+              Sync (NULL, ())
+              * refresh all from server
+              Sync ("refresh-from-server", ())
+              * force slow sync for calendar, use mode from config for others
+              Sync (NULL, (("calendar", "slow")))
+              * sync only calendar and addressbook, with mode from config
+              Sync ("none", (("calendar", NULL), ("addressbook", NULL)))
+        </doc:para>
+        <doc:para>
+          Syncevolution will by default output a sync "diff" in the end of Sync().
+          Producing the diff can be expensive CPU-wise, so setting the 
+          configuration value "printChanges" to 0 before a Sync() is advised
+          for clients who are not interested in the diff.
+        </doc:para>
+      </doc:description></doc:doc>
+      <arg type="s" name="mode" direction="in">
+        <doc:doc><doc:summary>synchronization mode</doc:summary></doc:doc>
+        <doc:doc><doc:description>Valid values are all synchronization modes used in syncevolution server configuration files and the empty string.</doc:description></doc:doc>
+      </arg>
+      <arg type="a{ss}" name="sources" direction="in">
+        <doc:doc><doc:summary>synchronization source modes</doc:summary></doc:doc>
+        <doc:doc><doc:description>Source modes to override the 'mode' variable for specific sources. The dictionary key is source name, value is synchronization mode. Valid synchronization modes are all synchronization modes used in syncevolution server configuration files and the empty string.</doc:description></doc:doc>
+      </arg>
+    </method>
+
+    <method name="Abort">
+      <doc:doc><doc:description>Abort synchronization. See Status-signal for results.</doc:description></doc:doc>
+    </method>
+
+    <method name="Suspend">
+      <doc:doc><doc:description>Suspend synchronization. See Status-signal for results.</doc:description></doc:doc>
+    </method>
+
+    <method name="Detach">
+      <doc:doc><doc:description>Detach from the session.</doc:description></doc:doc>
+    </method>
+
+    <method name="CheckPresence">
+      <doc:doc><doc:description>Checks whether a sync with the current server can start.</doc:description></doc:doc>
+      <arg type="s" name="status">
+        <doc:doc>
+          <doc:summary>
+            See org.syncevolution.Server Presence signal for details.
+          </doc:summary>
+        </doc:doc>
+      </arg>
+    </method>
+
+    <method name="GetStatus">
+      <doc:doc><doc:description>Get session status. Individual source statuses are relevant and provided only when status is neither "queuing" nor "idle".</doc:description></doc:doc>
+      <arg type="s" name="status" direction="out">
+        <doc:doc><doc:summary>Session status</doc:summary></doc:doc>
+        <doc:doc><doc:description>Valid values include strings starting with "queueing", "idle" (ready to execute commands), "running", "aborting", "suspending", "done" (a sync was executed, individual source statuses for that sync are available, session is now inactive and cannot execute new commands). The strings may contain additional specifiers separated by a semicolons: "running;processing", "suspending;waiting". There may be several specifiers: "running;waiting;foo"</doc:description></doc:doc>
+      </arg>
+      <arg type="u" name="error" direction="out">
+        <doc:doc><doc:summary>Error code for current or last action (zero for no error).</doc:summary></doc:doc>
+      </arg>
+      <arg type="a{s(ssu)}" name="sources" direction="out">
+        <doc:doc><doc:summary>Synchronization source status dictionary</doc:summary></doc:doc>
+        <doc:doc><doc:description>Dictionary key is source name. The value structs contain synchronization mode, source status and error code. Valid values for status are the same as for status parameter above. "done" represents a synced source when the whole sync is not done yet.</doc:description></doc:doc>
+      </arg>
+    </method>
+
+    <method name="GetProgress">
+      <doc:doc><doc:description>Get synchronization progress</doc:description></doc:doc>
+      <arg type="i" name="progress" direction="out">
+        <doc:doc><doc:summary>Rough estimate of current progress 0-100.</doc:summary></doc:doc>
+      </arg>
+      <arg type="a{s(siiiiii)}" name="sources" direction="out">
+        <doc:doc><doc:summary>Synchronization source progress dictionary</doc:summary></doc:doc>
+        <doc:doc><doc:description>Dictionary key is source name. The value structs contain phase (can be one of "", "preparing", "sending", "receiving"), prepare count, prepare total, send count, send total, receive count and receive total. -1 is used for unknown. Normally only the 'counts' increase but there are cases where the total will increase as well.</doc:description></doc:doc>
+      </arg>
+    </method>
+
+    <signal name="StatusChanged">
+      <doc:doc><doc:description>Session status change. See GetStatus() for argument descriptions.</doc:description></doc:doc>
+      <arg type="s" name="status"/>
+      <arg type="u" name="error"/>
+      <arg type="a{s(ssu)}" name="sources"/>
+    </signal> 
+
+    <signal name="ProgressChanged">
+      <doc:doc><doc:description>Synchronization progress change. See GetProgress() for argument descriptions.</doc:description></doc:doc>
+      <arg type="i" name="progress"/>
+      <arg type="a{s(siiiiii)}" name="sources"/>
+    </signal>
+
+  </interface>
+</node>
diff --git a/src/dbus/interfaces/syncevo.xml b/src/dbus/interfaces/syncevo.xml
deleted file mode 100644 (file)
index 18b935f..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
-<node name="/">
-  <interface name="org.Moblin.SyncEvolution">
-    <method name="StartSync">
-      <arg type="s" name="server" direction="in"/>
-      <arg type="a(si)" name="sources" direction="in"/>
-    </method>
-    <method name="AbortSync">
-      <arg type="s" name="server" direction="in"/>
-    </method>
-    <signal name="Progress">
-      <arg type="s" name="server"/>
-      <arg type="s" name="source"/>
-      <arg type="i" name="type"/>
-      <arg type="i" name="extra1"/>
-      <arg type="i" name="extra2"/>
-      <arg type="i" name="extra3"/>
-    </signal>
-    <signal name="ServerMessage">
-      <arg type="s" name="server"/>
-      <arg type="s" name="message"/>
-    </signal>
-    <method name="GetTemplates">
-      <arg type="a(sssb)" name="templates" direction="out"/>
-    </method>
-    <method name="GetTemplateConfig">
-      <arg type="s" name="template" direction="in"/>
-      <arg type="a(sss)" name="properties" direction="out"/>
-    </method>
-    <method name="GetServers">
-      <arg type="a(sssb)" name="servers" direction="out"/>
-    </method>
-    <method name="GetServerConfig">
-      <arg type="s" name="server" direction="in"/>
-      <arg type="a(sss)" name="properties" direction="out"/>
-    </method>
-    <method name="SetServerConfig">
-      <arg type="s" name="server" direction="in"/>
-      <arg type="a(sss)" name="properties" direction="in"/>
-    </method>
-    <method name="RemoveServerConfig">
-      <arg type="s" name="server" direction="in"/>
-    </method>
-    <method name="GetSyncReports">
-      <arg type="s" name="server" direction="in"/>
-      <arg type="i" name="count" direction="in"/>
-      <arg type="a(ia(siiiiiiiiiiiii))" name="reports" direction="out"/>
-    </method>
-  </interface>
-</node>
index c27d417..cb313f7 100644 (file)
  * 02110-1301  USA
  */
 
+#include <string.h>
+#include <glib.h>
+#include <dbus/dbus-glib.h>
 #include "syncevo-dbus-types.h"
 
-SyncevoSource*
-syncevo_source_new (char *name, int mode)
-{
-       GValue val = {0, };
-
-       g_value_init (&val, SYNCEVO_SOURCE_TYPE);
-       g_value_take_boxed (&val, dbus_g_type_specialized_construct (SYNCEVO_SOURCE_TYPE));
-       dbus_g_type_struct_set (&val, 0, name, 1, mode, G_MAXUINT);
 
-       return (SyncevoSource*) g_value_get_boxed (&val);
-}
-
-void
-syncevo_source_get (SyncevoSource *source, const char **name, int *mode)
+gboolean
+syncevo_config_get_value (SyncevoConfig *config,
+                          const char *source,
+                          const char *key,
+                          char **value)
 {
-       g_return_if_fail (source);
-
-       if (name) {
-               *name = g_value_get_string (g_value_array_get_nth (source, 0));
-       }
-       if (mode) {
-               *mode = g_value_get_int (g_value_array_get_nth (source, 1));
-       }
+    char *name;
+    GHashTable *source_config;
+
+    g_return_val_if_fail (config, FALSE);
+    g_return_val_if_fail (value, FALSE);
+
+    if (!source || strlen (source) == 0) {
+        name = g_strdup ("");
+    } else {
+        name = g_strdup_printf ("sources/%s", source);
+    }
+
+    source_config = (GHashTable*)g_hash_table_lookup (config, name);
+    g_free (name);
+
+    if (source_config) {
+        *value = (char*)g_hash_table_lookup (source_config, key);
+        return TRUE;
+    }
+    
+    return FALSE;
 }
 
-void
-syncevo_source_free (SyncevoSource *source)
+gboolean
+syncevo_config_set_value (SyncevoConfig *config,
+                          const char *source,
+                          const char *key,
+                          const char *value)
 {
-       if (source) {
-               g_boxed_free (SYNCEVO_SOURCE_TYPE, source);
-       }
+    gboolean changed;
+    char *name;
+    char *old_value;
+    GHashTable *source_config;
+
+    g_return_val_if_fail (config, FALSE);
+    g_return_val_if_fail (key, FALSE);
+
+    if (!source || strlen (source) == 0) {
+        name = g_strdup ("");
+    } else {
+        name = g_strdup_printf ("sources/%s", source);
+    }
+
+    source_config = (GHashTable*)g_hash_table_lookup (config, name);
+    if (!source_config) {
+        source_config = g_hash_table_new (g_str_hash, g_str_equal);
+        g_hash_table_insert (config, name, source_config);
+    } else {
+        g_free (name);
+    }
+
+    old_value = g_hash_table_lookup (source_config, key);
+    if ((!old_value && !value) ||
+        (old_value && value && strcmp (old_value, value) == 0)) {
+        changed = FALSE;
+    } else {
+        changed = TRUE;
+        g_hash_table_insert (source_config, g_strdup (key), g_strdup (value));
+    }
+
+    return changed;
 }
 
-SyncevoOption*
-syncevo_option_new (char *ns, char *key, char *value)
+void syncevo_config_foreach_source (SyncevoConfig *config,
+                                    ConfigFunc func,
+                                    gpointer userdata)
 {
-       GValue val = {0, };
+    GHashTableIter iter;
+    char *key;
+    GHashTable *value;
 
-       g_value_init (&val, SYNCEVO_OPTION_TYPE);
-       g_value_take_boxed (&val, dbus_g_type_specialized_construct (SYNCEVO_OPTION_TYPE));
-       dbus_g_type_struct_set (&val, 0, ns, 1, key, 2, value, G_MAXUINT);
+    g_hash_table_iter_init (&iter, config);
+    while (g_hash_table_iter_next (&iter, (gpointer*)&key, (gpointer*)&value)) {
 
-       return (SyncevoOption*) g_value_get_boxed (&val);
-}
+        if (key && g_str_has_prefix (key, "source/")) {
+            char *name;
 
-void
-syncevo_option_get (SyncevoOption *option, const char **ns, const char **key, const char **value)
-{
-       g_return_if_fail (option);
-
-       if (ns) {
-               *ns = g_value_get_string (g_value_array_get_nth (option, 0));
-       }
-       if (key) {
-               *key = g_value_get_string (g_value_array_get_nth (option, 1));
-       }
-       if (value) {
-               *value = g_value_get_string (g_value_array_get_nth (option, 2));
-       }
+            name = key+7;
+            func (name, value, userdata);
+        }
+    }
 }
 
+
 void
-syncevo_option_free (SyncevoOption *option)
+syncevo_config_free (SyncevoConfig *config)
 {
-       if (option) {
-               g_boxed_free (SYNCEVO_OPTION_TYPE, option);
-       }
+    /* NOTE: Hashtables gcreated by dbus-glib should free their contents */
+    g_hash_table_destroy (config);
 }
 
-SyncevoServer* syncevo_server_new (char *name, char *url, char *icon, gboolean consumer_ready)
+const char*
+syncevo_sync_mode_to_string (SyncevoSyncMode mode)
 {
-       GValue val = {0, };
-
-       g_value_init (&val, SYNCEVO_SERVER_TYPE);
-       g_value_take_boxed (&val, dbus_g_type_specialized_construct (SYNCEVO_SERVER_TYPE));
-       dbus_g_type_struct_set (&val,
-                               0, name,
-                               1, url,
-                               2, icon,
-                               3, consumer_ready,
-                               G_MAXUINT);
-
-       return (SyncevoServer*) g_value_get_boxed (&val);
+    const char *mode_str;
+
+    switch (mode) {
+    case SYNCEVO_SYNC_NONE:
+        mode_str = "none";
+        break;
+    case SYNCEVO_SYNC_TWO_WAY:
+        mode_str = "two-way";
+        break;
+    case SYNCEVO_SYNC_SLOW:
+        mode_str = "slow";
+        break;
+    case SYNCEVO_SYNC_REFRESH_FROM_CLIENT:
+        mode_str = "refresh-from-client";
+        break;
+    case SYNCEVO_SYNC_REFRESH_FROM_SERVER:
+        mode_str = "refresh-from-server";
+        break;
+    case SYNCEVO_SYNC_ONE_WAY_FROM_CLIENT:
+        mode_str = "one-way-from-client";
+        break;
+    case SYNCEVO_SYNC_ONE_WAY_FROM_SERVER:
+        mode_str = "one-way-from-server";
+        break;
+    case SYNCEVO_SYNC_DEFAULT:
+        mode_str = "";
+        break;
+    default:
+        mode_str = "";
+        break;
+    }
+
+    return mode_str;
 }
 
-void syncevo_server_get (SyncevoServer *server, const char **name, const char **url, const char **icon, gboolean *consumer_ready)
+SyncevoSourceModes*
+syncevo_source_modes_new ()
 {
-       g_return_if_fail (server);
-
-       if (name) {
-               *name = g_value_get_string (g_value_array_get_nth (server, 0));
-       }
-       if (url) {
-               *url = g_value_get_string (g_value_array_get_nth (server, 1));
-       }
-       if (icon) {
-               *icon = g_value_get_string (g_value_array_get_nth (server, 2));
-       }
-       if (consumer_ready) {
-               *consumer_ready = g_value_get_boolean (g_value_array_get_nth (server, 3));
-       }
+    return g_hash_table_new_full (g_str_hash, g_str_equal,
+                                  NULL, NULL);
 }
 
-void syncevo_server_free (SyncevoServer *server)
+void
+syncevo_source_modes_add (SyncevoSourceModes *source_modes,
+                          char *source,
+                          SyncevoSyncMode mode)
 {
-       if (server) {
-               g_boxed_free (SYNCEVO_SERVER_TYPE, server);
-       }
-}
+    const char *mode_str;
 
-SyncevoReport* 
-syncevo_report_new (char *source)
-{
-       GValue val = {0, };
+    g_return_if_fail (source_modes);
+    g_return_if_fail (source);
 
-       g_value_init (&val, SYNCEVO_REPORT_TYPE);
-       g_value_take_boxed (&val, dbus_g_type_specialized_construct (SYNCEVO_REPORT_TYPE));
-       dbus_g_type_struct_set (&val,
-                               0, source,
-                               G_MAXUINT);
+    mode_str = syncevo_sync_mode_to_string (mode);
 
-       return (SyncevoReport*) g_value_get_boxed (&val);
+    g_hash_table_insert (source_modes, source, (char*)mode_str);
 }
 
-static void
-insert_int (SyncevoReport *report, int index, int value)
+void
+syncevo_source_modes_free (SyncevoSourceModes *source_modes)
 {
-       GValue val = {0};
+    /* no need to free keys/values */
+    g_hash_table_destroy (source_modes);
+}
 
-       g_value_init (&val, G_TYPE_INT);
-       g_value_set_int (&val, value);
-       g_value_array_insert (report, index, &val);
+SyncevoSessionStatus
+syncevo_session_status_from_string (const char *status_str)
+{
+    SyncevoSessionStatus status;
+
+    if (!status_str) {
+        status = SYNCEVO_STATUS_UNKNOWN;
+    } else if (g_str_has_prefix (status_str, "queueing")) {
+        status = SYNCEVO_STATUS_QUEUEING;
+    } else if (g_str_has_prefix (status_str, "idle")) {
+        status = SYNCEVO_STATUS_IDLE;
+    } else if (g_str_has_prefix (status_str, "done")) {
+        status = SYNCEVO_STATUS_DONE;
+    } else if (g_str_has_prefix (status_str, "running")) {
+        status = SYNCEVO_STATUS_RUNNING;
+    } else if (g_str_has_prefix (status_str, "aborting")) {
+        status = SYNCEVO_STATUS_ABORTING;
+    } else if (g_str_has_prefix (status_str, "suspending")) {
+        status = SYNCEVO_STATUS_SUSPENDING;
+    } else {
+        status = SYNCEVO_STATUS_UNKNOWN;
+    }
+
+    return status;
 }
 
 void
-syncevo_report_set_io (SyncevoReport *report, 
-                       int sent_bytes, int received_bytes)
+syncevo_source_statuses_foreach (SyncevoSourceStatuses *source_statuses,
+                                 SourceStatusFunc func,
+                                 gpointer data)
 {
-       g_return_if_fail (report);
-
-       insert_int (report, 1, sent_bytes);
-       insert_int (report, 2, received_bytes);
+    GHashTableIter iter;
+    GValueArray *source_status;
+    
+    char *name;
+
+    g_return_if_fail (source_statuses);
+
+    g_hash_table_iter_init (&iter, source_statuses);
+    while (g_hash_table_iter_next (&iter, (gpointer)&name, (gpointer)&source_status)) {
+        const char *mode_str;
+        const char *status_str;
+        SyncevoSyncMode mode;
+        SyncevoSourceStatus status;
+        guint error_code;
+
+        mode_str = g_value_get_string (g_value_array_get_nth (source_status, 0));
+        if (!mode_str) {
+            mode = SYNCEVO_SYNC_UNKNOWN;
+        } else if (g_str_has_prefix (mode_str, "none")) {
+            mode = SYNCEVO_SYNC_NONE;
+        } else if (g_str_has_prefix (mode_str, "two-way")) {
+            mode = SYNCEVO_SYNC_TWO_WAY;
+        } else if (g_str_has_prefix (mode_str, "slow")) {
+            mode = SYNCEVO_SYNC_SLOW;
+        } else if (g_str_has_prefix (mode_str, "refresh-from-client")) {
+            mode = SYNCEVO_SYNC_REFRESH_FROM_CLIENT;
+        } else if (g_str_has_prefix (mode_str, "refresh-from-server")) {
+            mode = SYNCEVO_SYNC_REFRESH_FROM_SERVER;
+        } else if (g_str_has_prefix (mode_str, "one-way-from-client")) {
+            mode = SYNCEVO_SYNC_ONE_WAY_FROM_CLIENT;
+        } else if (g_str_has_prefix (mode_str, "one-way-from-server")) {
+            mode = SYNCEVO_SYNC_ONE_WAY_FROM_SERVER;
+        } else {
+            mode = SYNCEVO_SYNC_UNKNOWN;
+        }
+
+        status_str = g_value_get_string (g_value_array_get_nth (source_status, 1));
+        status = syncevo_session_status_from_string (status_str);
+        error_code = g_value_get_uint (g_value_array_get_nth (source_status, 2));
+
+        func (name, mode, status, error_code, data);
+    }
 }
 
 
-void 
-syncevo_report_set_local (SyncevoReport *report, 
-                          int adds, int updates, int removes, int rejects)
+static void
+free_source_status_item (char *source,
+                         GValueArray *status_array)
 {
-       g_return_if_fail (report);
-
-       insert_int (report, 3, adds);
-       insert_int (report, 4, updates);
-       insert_int (report, 5, removes);
-       insert_int (report, 6, rejects);
+    g_free (source);
+    g_boxed_free (SYNCEVO_TYPE_SOURCE_STATUS, status_array);
 }
 
 void
-syncevo_report_set_remote (SyncevoReport *report, 
-                           int adds, int updates, int removes, int rejects)
+syncevo_source_statuses_free (SyncevoSourceStatuses *source_statuses)
 {
-       g_return_if_fail (report);
+    g_hash_table_foreach (source_statuses, 
+                          (GHFunc)free_source_status_item,
+                          NULL);
+    g_hash_table_destroy (source_statuses);
+}
 
-       insert_int (report, 7, adds);
-       insert_int (report, 8, updates);
-       insert_int (report, 9, removes);
-       insert_int (report, 10, rejects);
+/* The return value contents are only valid as long as the
+ * SyncevoSourceProgresses is. */
+SyncevoSourceProgress*
+syncevo_source_progresses_get_current (SyncevoSourceProgresses *source_progresses)
+{
+    const char *phase_str, *name;
+    GHashTableIter iter;
+    GValueArray *progress_array;
+    GValue *val;
+    SyncevoSourceProgress *progress = NULL;
+
+    g_return_val_if_fail (source_progresses, FALSE);
+
+    g_hash_table_iter_init (&iter, source_progresses);
+    while (g_hash_table_iter_next (&iter, (gpointer)&name, (gpointer)&progress_array)) {
+        SyncevoSourcePhase phase;
+        phase_str = g_value_get_string (g_value_array_get_nth (progress_array, 0));
+
+        if (!phase_str) {
+            phase = SYNCEVO_PHASE_NONE;
+        } else if (g_str_has_prefix (phase_str, "preparing")) {
+            phase = SYNCEVO_PHASE_PREPARING;
+        } else if (g_str_has_prefix (phase_str, "sending")) {
+            phase = SYNCEVO_PHASE_SENDING;
+        } else if (g_str_has_prefix (phase_str, "receiving")) {
+            phase = SYNCEVO_PHASE_RECEIVING;
+        } else {
+            phase = SYNCEVO_PHASE_NONE;
+        }
+
+        if (phase == SYNCEVO_PHASE_NONE) {
+            continue;
+        }
+
+        progress = g_slice_new (SyncevoSourceProgress);
+        progress->name = g_strdup (name);
+        progress->phase = phase;
+
+        val = g_value_array_get_nth (progress_array, 1);
+        progress->prepare_current = g_value_get_int (val);
+        val = g_value_array_get_nth (progress_array, 2);
+        progress->prepare_total = g_value_get_int (val);
+        val = g_value_array_get_nth (progress_array, 3);
+        progress->send_current = g_value_get_int (val);
+        val = g_value_array_get_nth (progress_array, 4);
+        progress->send_total = g_value_get_int (val);
+        val = g_value_array_get_nth (progress_array, 5);
+        progress->receive_current = g_value_get_int (val);
+        val = g_value_array_get_nth (progress_array, 6);
+        progress->receive_total = g_value_get_int (val);
+
+        break;
+    }
+    return progress;
 }
 
 void
-syncevo_report_set_conflicts (SyncevoReport *report, 
-                              int local_won, int remote_won, int duplicated)
+syncevo_source_progress_free (SyncevoSourceProgress *progress)
 {
-       g_return_if_fail (report);
-
-       insert_int (report, 11, local_won);
-       insert_int (report, 12, remote_won);
-       insert_int (report, 13, duplicated);
+    g_free (progress->name);
+    g_slice_free (SyncevoSourceProgress, progress);
 }
-
-const char*
-syncevo_report_get_name (SyncevoReport *report)
+static void
+free_source_progress_item (char *source,
+                           GValueArray *progress_array)
 {
-       g_return_val_if_fail (report, NULL);
-
-       return g_value_get_string (g_value_array_get_nth (report, 0));
-
+    g_free (source);
+    g_boxed_free (SYNCEVO_TYPE_SOURCE_PROGRESS, progress_array);
 }
 
 void
-syncevo_report_get_io (SyncevoReport *report, 
-                       int *bytes_sent, int *bytes_received)
+syncevo_source_progresses_free (SyncevoSourceProgresses *source_progresses)
 {
-       g_return_if_fail (report);
-
-       if (bytes_sent) {
-               *bytes_sent = g_value_get_int (g_value_array_get_nth (report, 1));
-       }
-       if (bytes_received) {
-               *bytes_received = g_value_get_int (g_value_array_get_nth (report, 2));
-       }
+    g_hash_table_foreach (source_progresses, 
+                          (GHFunc)free_source_progress_item,
+                          NULL);
+    g_hash_table_destroy (source_progresses);
 }
 
-void
-syncevo_report_get_local (SyncevoReport *report, 
-                          int *adds, int *updates, int *removes, int *rejects)
+static void
+free_report_item (char *key, char *value)
 {
-       g_return_if_fail (report);
-
-       if (adds) {
-               *adds = g_value_get_int (g_value_array_get_nth (report, 3));
-       }
-       if (updates) {
-               *updates = g_value_get_int (g_value_array_get_nth (report, 4));
-       }
-       if (removes) {
-               *removes = g_value_get_int (g_value_array_get_nth (report, 5));
-       }
-       if (rejects) {
-               *rejects = g_value_get_int (g_value_array_get_nth (report, 6));
-       }
+    g_free (key);
+    g_free (value);
 }
 
-void
-syncevo_report_get_remote (SyncevoReport *report, 
-                           int *adds, int *updates, int *removes, int *rejects)
+static void
+syncevo_report_free (GHashTable *report)
 {
-       g_return_if_fail (report);
-
-       if (adds) {
-               *adds = g_value_get_int (g_value_array_get_nth (report, 7));
-       }
-       if (updates) {
-               *updates = g_value_get_int (g_value_array_get_nth (report, 8));
-       }
-       if (removes) {
-               *removes = g_value_get_int (g_value_array_get_nth (report, 9));
-       }
-       if (rejects) {
-               *rejects = g_value_get_int (g_value_array_get_nth (report, 10));
-       }
+    g_hash_table_foreach (report, 
+                          (GHFunc)free_report_item,
+                          NULL);
+    g_hash_table_destroy (report);
 }
 
-void
-syncevo_report_get_conflicts (SyncevoReport *report, 
-                              int *local_won, int *remote_won, int *duplicated)
+GHashTable*
+syncevo_reports_index (SyncevoReports *reports,
+                       guint index)
 {
-       g_return_if_fail (report);
-
-       if (local_won) {
-               *local_won = g_value_get_int (g_value_array_get_nth (report, 11));
-       }
-       if (remote_won) {
-               *remote_won = g_value_get_int (g_value_array_get_nth (report, 12));
-       }
-       if (duplicated) {
-               *duplicated = g_value_get_int (g_value_array_get_nth (report, 13));
-       }
+    g_return_val_if_fail (reports, NULL);
+
+    return (GHashTable*)g_ptr_array_index (reports, index);
 }
 
-void
-syncevo_report_free (SyncevoReport *report)
+guint
+syncevo_reports_get_length (SyncevoReports *reports)
 {
-       if (report) {
-               g_boxed_free (SYNCEVO_REPORT_TYPE, report);
-       }
+    return reports->len;
 }
 
-SyncevoReportArray* syncevo_report_array_new (int end_time, GPtrArray *reports)
+void
+syncevo_reports_free (SyncevoReports *reports)
 {
-       GValue val = {0, };
-
-       g_value_init (&val, SYNCEVO_REPORT_ARRAY_TYPE);
-       g_value_take_boxed (&val, dbus_g_type_specialized_construct (SYNCEVO_REPORT_ARRAY_TYPE));
-       dbus_g_type_struct_set (&val,
-                               0, end_time,
-                               1, reports,
-                               G_MAXUINT);
-       return (SyncevoReportArray*) g_value_get_boxed (&val);
+    g_ptr_array_foreach (reports,
+                         (GFunc)syncevo_report_free,
+                         NULL);
+    g_ptr_array_free (reports, TRUE);
 }
 
-void syncevo_report_array_get (SyncevoReportArray *array, int *end_time, GPtrArray **reports)
+const char*
+syncevo_sessions_index (SyncevoSessions *sessions,
+                        guint index)
 {
-       g_return_if_fail (array);
-
-       if (end_time) {
-               *end_time = g_value_get_int (g_value_array_get_nth (array, 0));
-       }
-       if (reports) {
-               *reports = g_value_get_boxed (g_value_array_get_nth (array, 1));
-       }
+    g_return_val_if_fail (sessions, NULL);
+
+    if (index >= sessions->len) {
+        return NULL;
+    }
+    return (const char*)g_ptr_array_index (sessions, index);
 }
 
 void
-syncevo_report_array_free (SyncevoReportArray *array)
+syncevo_sessions_free (SyncevoSessions *sessions)
 {
-       if (array) {
-               g_boxed_free (SYNCEVO_REPORT_ARRAY_TYPE, array);
-       }
+    g_ptr_array_foreach (sessions,
+                         (GFunc)g_free,
+                         NULL);
+    g_ptr_array_free (sessions, TRUE);
 }
 
index 62633d8..369bfd5 100644 (file)
  * 02110-1301  USA
  */
 
-#ifndef __SYNCEVO_DBUS_TYPES_H__
-#define __SYNCEVO_DBUS_TYPES_H__
+#ifndef __SYNCEVO_TYPES_H__
+#define __SYNCEVO_TYPES_H__
 
 #include <glib.h>
-#include <dbus/dbus-glib.h>
-
-#define SYNCEVO_DBUS_ERROR_GENERIC_ERROR "org.Moblin.SyncEvolution.GenericError"
-#define SYNCEVO_DBUS_ERROR_NO_SUCH_SERVER "org.Moblin.SyncEvolution.NoSuchServer"
-#define SYNCEVO_DBUS_ERROR_MISSING_ARGS "org.Moblin.SyncEvolution.MissingArgs"
-#define SYNCEVO_DBUS_ERROR_INVALID_CALL "org.Moblin.SyncEvolution.InvalidCall"
-
-#define SYNCEVO_SOURCE_TYPE (dbus_g_type_get_struct ("GValueArray", G_TYPE_STRING, G_TYPE_INT, G_TYPE_INVALID))
-typedef GValueArray SyncevoSource;
-
-#define SYNCEVO_OPTION_TYPE (dbus_g_type_get_struct ("GValueArray", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID))
-typedef GValueArray SyncevoOption;
-
-#define SYNCEVO_SERVER_TYPE (dbus_g_type_get_struct ("GValueArray", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_INVALID))
-typedef GValueArray SyncevoServer;
-
-#define SYNCEVO_REPORT_TYPE (dbus_g_type_get_struct ("GValueArray", G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INVALID))
-typedef GValueArray SyncevoReport;
-
-#define SYNCEVO_REPORT_ARRAY_TYPE (dbus_g_type_get_struct ("GValueArray", G_TYPE_INT, dbus_g_type_get_collection ("GPtrArray", SYNCEVO_REPORT_TYPE)))
-typedef GValueArray SyncevoReportArray;
-
-SyncevoOption* syncevo_option_new (char *ns, char *key, char *value);
-void syncevo_option_get (SyncevoOption *option, const char **ns, const char **key, const char **value);
-void syncevo_option_free (SyncevoOption *option);
-
-SyncevoSource* syncevo_source_new (char *name, int mode);
-void syncevo_source_get (SyncevoSource *source, const char **name, int *mode);
-void syncevo_source_free (SyncevoSource *source);
-
-SyncevoServer* syncevo_server_new (char *name, char *url, char *icon, gboolean consumer_ready);
-void syncevo_server_get (SyncevoServer *server, const char **name, const char **url, const char **icon, gboolean *consumer_ready);
-void syncevo_server_free (SyncevoServer *server);
-
-
-SyncevoReport* syncevo_report_new (char *source);
-
-void syncevo_report_set_io (SyncevoReport *report, 
-                            int sent_bytes, int received_bytes);
-void syncevo_report_set_local (SyncevoReport *report, 
-                               int adds, int updates, int removes, int rejects);
-void syncevo_report_set_remote (SyncevoReport *report, 
-                                int adds, int updates, int removes, int rejects);
-void syncevo_report_set_conflicts (SyncevoReport *report, 
-                                   int local_won, int remote_won, int duplicated);
-
-const char* syncevo_report_get_name (SyncevoReport *report);
-void syncevo_report_get_io (SyncevoReport *report,
-                            int *bytes_sent, int *bytes_received);
-void syncevo_report_get_local (SyncevoReport *report, 
-                               int *adds, int *updates, int *removes, int *rejects);
-void syncevo_report_get_remote (SyncevoReport *report, 
-                               int *adds, int *updates, int *removes, int *rejects);
-void syncevo_report_get_conflicts (SyncevoReport *report, 
-                                   int *local_won, int *remote_won, int *duplicated);
-
-void syncevo_report_free (SyncevoReport *report);
-
-
-SyncevoReportArray* syncevo_report_array_new (int end_time, GPtrArray *reports);
-void syncevo_report_array_get (SyncevoReportArray *array, int *end_time, GPtrArray **reports);
-void syncevo_report_array_free (SyncevoReportArray *array);
 
+#define SYNCEVO_DBUS_ERROR_EXCEPTION "org.syncevolution.Exception"
+#define SYNCEVO_DBUS_ERROR_NO_SUCH_CONFIG "org.syncevolution.NoSuchConfig"
+#define SYNCEVO_DBUS_ERROR_NO_SUCH_SOURCE "org.syncevolution.NoSuchsource"
+#define SYNCEVO_DBUS_ERROR_INVALID_CALL "org.syncevolution.InvalidCall"
+#define SYNCEVO_DBUS_ERROR_SOURCE_UNUSABLE "org.syncevolution.SourceUnusable"
+
+typedef enum {
+  SYNCEVO_SYNC_UNKNOWN, /* Cannot be used in Sync */
+  SYNCEVO_SYNC_DEFAULT, /* cannot be received in GetStatus*/
+  SYNCEVO_SYNC_NONE,
+  SYNCEVO_SYNC_TWO_WAY,
+  SYNCEVO_SYNC_SLOW,
+  SYNCEVO_SYNC_REFRESH_FROM_CLIENT,
+  SYNCEVO_SYNC_REFRESH_FROM_SERVER,
+  SYNCEVO_SYNC_ONE_WAY_FROM_CLIENT,
+  SYNCEVO_SYNC_ONE_WAY_FROM_SERVER,
+} SyncevoSyncMode;
+
+typedef enum {
+  SYNCEVO_STATUS_UNKNOWN,
+  SYNCEVO_STATUS_QUEUEING,
+  SYNCEVO_STATUS_IDLE,
+  SYNCEVO_STATUS_RUNNING,
+  SYNCEVO_STATUS_ABORTING,
+  SYNCEVO_STATUS_SUSPENDING,
+  SYNCEVO_STATUS_DONE,
+} SyncevoSessionStatus;
+
+typedef enum {
+  SYNCEVO_SOURCE_IDLE,
+  SYNCEVO_SOURCE_RUNNING,
+  SYNCEVO_SOURCE_RUNNING_WAITING,
+  SYNCEVO_SOURCE_RUNNING_PROCESSING,
+  SYNCEVO_SOURCE_DONE,
+} SyncevoSourceStatus;
+
+typedef enum {
+  SYNCEVO_PHASE_NONE,
+  SYNCEVO_PHASE_PREPARING,
+  SYNCEVO_PHASE_SENDING,
+  SYNCEVO_PHASE_RECEIVING,
+} SyncevoSourcePhase;
+
+typedef struct {
+  char *name;
+  SyncevoSourcePhase phase;
+  int prepare_current;
+  int prepare_total;
+  int send_current;
+  int send_total;
+  int receive_current;
+  int receive_total;
+} SyncevoSourceProgress;  
+
+#define SYNCEVO_TYPE_SOURCE_STATUS (dbus_g_type_get_struct ("GValueArray", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_INVALID))
+#define SYNCEVO_TYPE_SOURCE_STATUSES (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, SYNCEVO_TYPE_SOURCE_STATUS))
+#define SYNCEVO_TYPE_SOURCE_PROGRESS (dbus_g_type_get_struct ("GValueArray", G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INVALID))
+#define SYNCEVO_TYPE_SOURCE_PROGRESSES (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, SYNCEVO_TYPE_SOURCE_PROGRESS))
+
+typedef GHashTable SyncevoConfig;
+typedef GHashTable SyncevoSourceModes;
+typedef GHashTable SyncevoSourceStatuses;
+typedef GHashTable SyncevoSourceProgresses;
+typedef GPtrArray SyncevoReports;
+typedef GPtrArray SyncevoSessions;
+
+
+gboolean syncevo_config_get_value (SyncevoConfig *config,
+                                   const char *source,
+                                   const char *key,
+                                   char **value);
+gboolean syncevo_config_set_value (SyncevoConfig *config,
+                                   const char *source,
+                                   const char *key,
+                                   const char *value);
+
+typedef void (*ConfigFunc) (char *name,
+                            GHashTable *source_configuration,
+                            gpointer user_data);
+
+void syncevo_config_foreach_source (SyncevoConfig *config,
+                                    ConfigFunc func,
+                                    gpointer userdata);
+void syncevo_config_free (SyncevoConfig *config);
+
+const char* syncevo_sync_mode_to_string (SyncevoSyncMode mode);
+
+SyncevoSourceModes* syncevo_source_modes_new ();
+void syncevo_source_modes_add (SyncevoSourceModes *source_modes,
+                               char *source,
+                               SyncevoSyncMode mode);
+void syncevo_source_modes_free (SyncevoSourceModes *source_modes);
+
+SyncevoSessionStatus syncevo_session_status_from_string (const char *status_str);
+
+
+typedef void (*SourceStatusFunc) (char *name,
+                                  SyncevoSyncMode mode,
+                                  SyncevoSourceStatus status,
+                                  guint error_code,
+                                  gpointer user_data);
+void
+syncevo_source_statuses_foreach (SyncevoSourceStatuses *source_statuses,
+                                 SourceStatusFunc func,
+                                 gpointer data);
+
+void syncevo_source_statuses_free (SyncevoSourceStatuses *source_statuses);
+
+
+SyncevoSourceProgress* syncevo_source_progresses_get_current (SyncevoSourceProgresses *source_progresses);
+
+void syncevo_source_progresses_free (SyncevoSourceProgresses *source_progresses);
+
+void syncevo_source_progress_free (SyncevoSourceProgress *progress);
+
+
+GHashTable* syncevo_reports_index (SyncevoReports *reports,
+                                   guint index);
+guint syncevo_reports_get_length (SyncevoReports *reports);
+
+void syncevo_reports_free (SyncevoReports *reports);
+
+
+const char* syncevo_sessions_index (SyncevoSessions *sessions,
+                                    guint index);
+void syncevo_sessions_free (SyncevoSessions *sessions);
 
 #endif
diff --git a/src/dbus/syncevo-dbus.c b/src/dbus/syncevo-dbus.c
deleted file mode 100644 (file)
index ca47b4c..0000000
+++ /dev/null
@@ -1,954 +0,0 @@
-/*
- * Copyright (C) 2009 Intel Corporation
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) version 3.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301  USA
- */
-
-#include <glib-object.h>
-#include <string.h>
-
-#include "syncevo-dbus.h"
-#include "syncevo-marshal.h"
-#include "syncevo-bindings.h"
-
-typedef struct _SyncevoAsyncData {
-       SyncevoService *service;
-       GCallback callback;
-       gpointer userdata;
-} SyncevoAsyncData;
-
-
-enum {
-       PROGRESS,
-       SERVER_MESSAGE,
-       SERVER_SHUTDOWN,
-       LAST_SIGNAL
-};
-
-typedef struct _SyncevoServicePrivate {
-       DBusGProxy *proxy;
-} SyncevoServicePrivate;
-
-#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SYNCEVO_TYPE_SERVICE, SyncevoServicePrivate))
-
-static void progress_cb (DBusGProxy *proxy,
-                         char *server,
-                         char *source,
-                         int type,
-                         int extra1, int extra2, int extra3,
-                         SyncevoService *service);
-static void server_message_cb (DBusGProxy *proxy,
-                               char *server,
-                               char *message,
-                               SyncevoService *service);
-static void proxy_destroyed (DBusGProxy *proxy,
-                             SyncevoService *service);
-
-G_DEFINE_TYPE (SyncevoService, syncevo_service, G_TYPE_OBJECT);
-
-static guint32 signals[LAST_SIGNAL] = {0, };
-
-static void
-finalize (GObject *object)
-{
-       SyncevoServicePrivate *priv;
-
-       priv = GET_PRIVATE (object);
-
-       G_OBJECT_CLASS (syncevo_service_parent_class)->finalize (object);
-}
-
-static void
-dispose (GObject *object)
-{
-       SyncevoServicePrivate *priv;
-
-       priv = GET_PRIVATE (object);
-
-       if (priv->proxy) {
-               dbus_g_proxy_disconnect_signal (priv->proxy, "Progress",
-                                               G_CALLBACK (progress_cb),
-                                               object);
-               dbus_g_proxy_disconnect_signal (priv->proxy, "ServerMessage",
-                                               G_CALLBACK (server_message_cb),
-                                               object);
-
-               g_object_unref (priv->proxy);
-               priv->proxy = NULL;
-       }
-
-       G_OBJECT_CLASS (syncevo_service_parent_class)->dispose (object);
-}
-
-static void progress_cb (DBusGProxy *proxy,
-                         char *server,
-                         char *source,
-                         int type,
-                         int extra1, int extra2, int extra3,
-                         SyncevoService *service)
-{
-       g_signal_emit (service, signals[PROGRESS], 0, 
-                      server, source, type, extra1, extra2, extra3);
-}
-
-static void server_message_cb (DBusGProxy *proxy,
-                               char *server,
-                               char *message,
-                               SyncevoService *service)
-{
-       g_signal_emit (service, signals[SERVER_MESSAGE], 0, 
-                      server, message);
-}
-
-static gboolean
-syncevo_service_get_new_proxy (SyncevoService *service)
-{
-       DBusGConnection *connection;
-       GError *error;
-       guint32 result;
-       SyncevoServicePrivate *priv;
-       DBusGProxy *proxy;
-
-       priv = GET_PRIVATE (service);
-       error = NULL;
-
-       connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
-       if (connection == NULL) {
-               g_printerr ("Failed to open connection to bus: %s\n",
-                           error->message);
-               g_error_free (error);
-               priv->proxy = NULL;
-               return FALSE;
-       }
-
-       /* we want to use dbus_g_proxy_new_for_name_owner() for the destroy signal
-        * so need to start the service by hand by using DBUS proxy: */
-       proxy = dbus_g_proxy_new_for_name (connection,
-                                          DBUS_SERVICE_DBUS,
-                                          DBUS_PATH_DBUS,
-                                          DBUS_INTERFACE_DBUS);
-       if (!dbus_g_proxy_call (proxy, "StartServiceByName", NULL,
-                               G_TYPE_STRING, SYNCEVO_SERVICE_DBUS_SERVICE,
-                               G_TYPE_UINT, 0,
-                               G_TYPE_INVALID,
-                               G_TYPE_UINT, &result,
-                               G_TYPE_INVALID)) {
-               g_warning ("StartServiceByName call failed");
-       }
-       g_object_unref (proxy);
-
-       /* the real proxy */
-       proxy = dbus_g_proxy_new_for_name_owner (connection,
-                                                SYNCEVO_SERVICE_DBUS_SERVICE,
-                                                SYNCEVO_SERVICE_DBUS_PATH,
-                                                SYNCEVO_SERVICE_DBUS_INTERFACE,
-                                                &error);
-       if (proxy == NULL) {
-               g_printerr ("dbus_g_proxy_new_for_name_owner() failed");
-               priv->proxy = NULL;
-               return FALSE;
-       }
-
-       dbus_g_proxy_add_signal (proxy, "Progress",
-                                G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INVALID);
-       dbus_g_proxy_connect_signal (proxy, "Progress",
-                                    G_CALLBACK (progress_cb), service, NULL);
-       dbus_g_proxy_add_signal (proxy, "ServerMessage",
-                                G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
-       dbus_g_proxy_connect_signal (proxy, "ServerMessage",
-                                    G_CALLBACK (server_message_cb), service, NULL);
-
-       g_signal_connect (proxy, "destroy",
-                         G_CALLBACK (proxy_destroyed), service);
-
-       priv->proxy = proxy;
-       return TRUE;
-}
-
-static void
-proxy_destroyed (DBusGProxy *proxy,
-                 SyncevoService *service)
-{
-       SyncevoServicePrivate *priv;
-       priv = GET_PRIVATE (service);
-
-       if (priv->proxy) {
-               g_object_unref (priv->proxy);
-       }
-       priv->proxy = NULL;
-
-       g_signal_emit (service, signals[SERVER_SHUTDOWN], 0);
-}
-
-static GObject *
-constructor (GType                  type,
-             guint                  n_construct_properties,
-             GObjectConstructParam *construct_properties)
-{
-       SyncevoService *service;
-       SyncevoServicePrivate *priv;
-
-       service = SYNCEVO_SERVICE (G_OBJECT_CLASS (syncevo_service_parent_class)->constructor
-                       (type, n_construct_properties, construct_properties));
-       priv = GET_PRIVATE (service);
-
-       dbus_g_object_register_marshaller (syncevo_marshal_VOID__STRING_STRING_INT_INT_INT_INT,
-                                          G_TYPE_NONE,
-                                          G_TYPE_STRING,
-                                          G_TYPE_STRING,
-                                          G_TYPE_INT,
-                                          G_TYPE_INT,
-                                          G_TYPE_INT,
-                                          G_TYPE_INT,
-                                          G_TYPE_INVALID);
-       dbus_g_object_register_marshaller (syncevo_marshal_VOID__STRING_STRING,
-                                          G_TYPE_NONE,
-                                          G_TYPE_STRING,
-                                          G_TYPE_STRING,
-                                          G_TYPE_INVALID);
-
-       syncevo_service_get_new_proxy (service);
-
-       return G_OBJECT (service);
-}
-
-static void
-syncevo_service_class_init (SyncevoServiceClass *klass)
-{
-       GObjectClass *o_class = (GObjectClass *) klass;
-
-       o_class->finalize = finalize;
-       o_class->dispose = dispose;
-       o_class->constructor = constructor;
-
-       g_type_class_add_private (klass, sizeof (SyncevoServicePrivate));
-
-       signals[PROGRESS] = g_signal_new ("progress",
-                                         G_TYPE_FROM_CLASS (klass),
-                                         G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
-                                         G_STRUCT_OFFSET (SyncevoServiceClass, progress),
-                                         NULL, NULL,
-                                         syncevo_marshal_VOID__STRING_STRING_INT_INT_INT_INT,
-                                         G_TYPE_NONE, 
-                                         6, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT);
-       signals[SERVER_MESSAGE] = g_signal_new ("server-message",
-                                         G_TYPE_FROM_CLASS (klass),
-                                         G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
-                                         G_STRUCT_OFFSET (SyncevoServiceClass, server_message),
-                                         NULL, NULL,
-                                         syncevo_marshal_VOID__STRING_STRING,
-                                         G_TYPE_NONE, 
-                                         2, G_TYPE_STRING, G_TYPE_STRING);
-       signals[SERVER_SHUTDOWN] = g_signal_new ("server-shutdown",
-                                         G_TYPE_FROM_CLASS (klass),
-                                         G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
-                                         G_STRUCT_OFFSET (SyncevoServiceClass, server_shutdown),
-                                         NULL, NULL,
-                                         g_cclosure_marshal_VOID__VOID,
-                                         G_TYPE_NONE, 
-                                         0);
-}
-
-static void
-syncevo_service_init (SyncevoService *service)
-{
-}
-
-
-SyncevoService *
-syncevo_service_get_default ()
-{
-       static SyncevoService *default_service = NULL;
-
-       if (default_service == NULL) {
-               default_service = g_object_new (SYNCEVO_TYPE_SERVICE, NULL);
-               g_object_add_weak_pointer (G_OBJECT (default_service),
-                                          (gpointer) &default_service);
-               return default_service;
-       }
-
-       return g_object_ref (default_service);
-}
-
-
-
-gboolean syncevo_service_start_sync (SyncevoService *service,
-                                     char *server,
-                                     GPtrArray *sources,
-                                     GError **error)
-{
-       SyncevoServicePrivate *priv;
-
-       priv = GET_PRIVATE (service);
-
-       if (!priv->proxy && !syncevo_service_get_new_proxy (service)) {
-               if (error) {
-                       *error = g_error_new_literal (g_quark_from_static_string ("syncevo-service"),
-                                                     SYNCEVO_SERVICE_ERROR_COULD_NOT_START, 
-                                                     "Could not start service");
-               }
-               return FALSE;
-       }
-
-       return org_Moblin_SyncEvolution_start_sync (priv->proxy, 
-                                                   server, 
-                                                   sources,
-                                                   error);
-}
-
-gboolean syncevo_service_abort_sync (SyncevoService *service,
-                                     char *server,
-                                     GError **error)
-{
-       SyncevoServicePrivate *priv;
-
-       priv = GET_PRIVATE (service);
-
-       if (!priv->proxy && !syncevo_service_get_new_proxy (service)) {
-               if (error) {
-                       *error = g_error_new_literal (g_quark_from_static_string ("syncevo-service"),
-                                                     SYNCEVO_SERVICE_ERROR_COULD_NOT_START, 
-                                                     "Could not start service");
-               }
-               return FALSE;
-       }
-
-       return org_Moblin_SyncEvolution_abort_sync (priv->proxy, 
-                                                   server, 
-                                                   error);
-}
-
-static void
-abort_sync_async_callback (DBusGProxy *proxy, 
-                           GError *error,
-                           SyncevoAsyncData *data)
-{
-       (*(SyncevoAbortSyncCb)data->callback) (data->service,
-                                              error,
-                                              data->userdata);
-       g_slice_free (SyncevoAsyncData, data);
-}
-
-static gboolean
-abort_sync_async_error (SyncevoAsyncData *data)
-{
-       GError *error;
-
-       error = g_error_new_literal (g_quark_from_static_string ("syncevo-service"),
-                                                                SYNCEVO_SERVICE_ERROR_COULD_NOT_START, 
-                                                                "Could not start service");
-       (*(SyncevoAbortSyncCb)data->callback) (data->service,
-                                              error,
-                                              data->userdata);
-       g_slice_free (SyncevoAsyncData, data);
-
-       return FALSE;
-}
-
-void 
-syncevo_service_abort_sync_async (SyncevoService *service,
-                                  char *server,
-                                  SyncevoAbortSyncCb callback,
-                                  gpointer userdata)
-{
-       SyncevoAsyncData *data;
-       SyncevoServicePrivate *priv;
-
-       priv = GET_PRIVATE (service);
-
-       data = g_slice_new0 (SyncevoAsyncData);
-       data->service = service;
-       data->callback = G_CALLBACK (callback);
-       data->userdata = userdata;
-
-       if (!priv->proxy && !syncevo_service_get_new_proxy (service)) {
-               g_idle_add ((GSourceFunc)abort_sync_async_error, data);
-               return;
-       }
-
-       org_Moblin_SyncEvolution_abort_sync_async 
-                       (priv->proxy,
-                        server,
-                        (org_Moblin_SyncEvolution_abort_sync_reply) abort_sync_async_callback,
-                        data);
-}
-
-
-gboolean syncevo_service_get_servers (SyncevoService *service,
-                                      GPtrArray **servers,
-                                      GError **error)
-{
-       SyncevoServicePrivate *priv;
-
-       priv = GET_PRIVATE (service);
-
-       if (!priv->proxy && !syncevo_service_get_new_proxy (service)) {
-               if (error) {
-                       *error = g_error_new_literal (g_quark_from_static_string ("syncevo-service"),
-                                                     SYNCEVO_SERVICE_ERROR_COULD_NOT_START, 
-                                                     "Could not start service");
-               }
-               return FALSE;
-       }
-
-       return org_Moblin_SyncEvolution_get_servers (priv->proxy, 
-                                                    servers, 
-                                                    error);
-}
-
-static void
-get_servers_async_callback (DBusGProxy *proxy, 
-                            GPtrArray *servers,
-                            GError *error,
-                            SyncevoAsyncData *data)
-{
-       (*(SyncevoGetServersCb)data->callback) (data->service,
-                                               servers,
-                                               error,
-                                               data->userdata);
-       g_slice_free (SyncevoAsyncData, data);
-}
-
-static gboolean
-get_servers_async_error (SyncevoAsyncData *data)
-{
-       GError *error;
-
-       error = g_error_new_literal (g_quark_from_static_string ("syncevo-service"),
-                                                                SYNCEVO_SERVICE_ERROR_COULD_NOT_START, 
-                                                                "Could not start service");
-       (*(SyncevoGetServersCb)data->callback) (data->service,
-                                               NULL,
-                                               error,
-                                               data->userdata);
-       g_slice_free (SyncevoAsyncData, data);
-
-       return FALSE;
-}
-
-void 
-syncevo_service_get_servers_async (SyncevoService *service,
-                                   SyncevoGetServersCb callback,
-                                   gpointer userdata)
-{
-       SyncevoAsyncData *data;
-       SyncevoServicePrivate *priv;
-
-       priv = GET_PRIVATE (service);
-
-       data = g_slice_new0 (SyncevoAsyncData);
-       data->service = service;
-       data->callback = G_CALLBACK (callback);
-       data->userdata = userdata;
-
-       if (!priv->proxy && !syncevo_service_get_new_proxy (service)) {
-               g_idle_add ((GSourceFunc)get_servers_async_error, data);
-               return;
-       }
-
-       org_Moblin_SyncEvolution_get_servers_async 
-                       (priv->proxy,
-                        (org_Moblin_SyncEvolution_get_servers_reply) get_servers_async_callback,
-                        data);
-}
-
-gboolean syncevo_service_get_templates (SyncevoService *service,
-                                        GPtrArray **templates,
-                                        GError **error)
-{
-       SyncevoServicePrivate *priv;
-
-       priv = GET_PRIVATE (service);
-
-       if (!priv->proxy && !syncevo_service_get_new_proxy (service)) {
-               if (error) {
-                       *error = g_error_new_literal (g_quark_from_static_string ("syncevo-service"),
-                                                     SYNCEVO_SERVICE_ERROR_COULD_NOT_START, 
-                                                     "Could not start service");
-               }
-               return FALSE;
-       }
-
-       return org_Moblin_SyncEvolution_get_templates (priv->proxy, 
-                                                      templates, 
-                                                      error);
-}
-
-static void
-get_templates_async_callback (DBusGProxy *proxy, 
-                              GPtrArray *templates,
-                              GError *error,
-                              SyncevoAsyncData *data)
-{
-       (*(SyncevoGetTemplatesCb)data->callback) (data->service,
-                                                 templates,
-                                                 error,
-                                                 data->userdata);
-       g_slice_free (SyncevoAsyncData, data);
-}
-
-static gboolean
-get_templates_async_error (SyncevoAsyncData *data)
-{
-       GError *error;
-
-       error = g_error_new_literal (g_quark_from_static_string ("syncevo-service"),
-                                                                SYNCEVO_SERVICE_ERROR_COULD_NOT_START, 
-                                                                "Could not start service");
-       (*(SyncevoGetTemplatesCb)data->callback) (data->service,
-                                                 NULL,
-                                                 error,
-                                                 data->userdata);
-       g_slice_free (SyncevoAsyncData, data);
-
-       return FALSE;
-}
-
-void syncevo_service_get_templates_async (SyncevoService *service,
-                                          SyncevoGetTemplatesCb callback,
-                                          gpointer userdata)
-{
-       SyncevoAsyncData *data;
-       SyncevoServicePrivate *priv;
-
-       priv = GET_PRIVATE (service);
-
-       data = g_slice_new0 (SyncevoAsyncData);
-       data->service = service;
-       data->callback = G_CALLBACK (callback);
-       data->userdata = userdata;
-
-       if (!priv->proxy && !syncevo_service_get_new_proxy (service)) {
-               g_idle_add ((GSourceFunc)get_templates_async_error, data);
-               return;
-       }
-
-       org_Moblin_SyncEvolution_get_templates_async 
-                       (priv->proxy,
-                        (org_Moblin_SyncEvolution_get_templates_reply) get_templates_async_callback,
-                        data);
-}
-
-gboolean syncevo_service_get_template_config (SyncevoService *service,
-                                              char *template,
-                                              GPtrArray **options,
-                                              GError **error)
-{
-       SyncevoServicePrivate *priv;
-
-       priv = GET_PRIVATE (service);
-
-       if (!priv->proxy && !syncevo_service_get_new_proxy (service)) {
-               if (error) {
-                       *error = g_error_new_literal (g_quark_from_static_string ("syncevo-service"),
-                                                     SYNCEVO_SERVICE_ERROR_COULD_NOT_START, 
-                                                     "Could not start service");
-               }
-               return FALSE;
-       }
-
-       return org_Moblin_SyncEvolution_get_template_config (priv->proxy, 
-                                                            template,
-                                                            options, 
-                                                            error);
-}
-
-static void
-get_template_config_async_callback (DBusGProxy *proxy, 
-                                    GPtrArray *options,
-                                    GError *error,
-                                    SyncevoAsyncData *data)
-{
-       (*(SyncevoGetTemplateConfigCb)data->callback) (data->service,
-                                                      options,
-                                                      error,
-                                                      data->userdata);
-       g_slice_free (SyncevoAsyncData, data);
-}
-
-static gboolean
-get_template_config_async_error (SyncevoAsyncData *data)
-{
-       GError *error;
-
-       error = g_error_new_literal (g_quark_from_static_string ("syncevo-service"),
-                                                                SYNCEVO_SERVICE_ERROR_COULD_NOT_START, 
-                                                                "Could not start service");
-       (*(SyncevoGetTemplateConfigCb)data->callback) (data->service,
-                                                      NULL,
-                                                      error,
-                                                      data->userdata);
-       g_slice_free (SyncevoAsyncData, data);
-
-       return FALSE;
-}
-
-void 
-syncevo_service_get_template_config_async (SyncevoService *service,
-                                           char *template,
-                                           SyncevoGetServerConfigCb callback,
-                                           gpointer userdata)
-{
-       SyncevoAsyncData *data;
-       SyncevoServicePrivate *priv;
-
-       priv = GET_PRIVATE (service);
-
-       data = g_slice_new0 (SyncevoAsyncData);
-       data->service = service;
-       data->callback = G_CALLBACK (callback);
-       data->userdata = userdata;
-
-       if (!priv->proxy && !syncevo_service_get_new_proxy (service)) {
-               g_idle_add ((GSourceFunc)get_template_config_async_error, data);
-               return;
-       }
-
-       org_Moblin_SyncEvolution_get_template_config_async 
-                       (priv->proxy,
-                        template,
-                        (org_Moblin_SyncEvolution_get_server_config_reply) get_template_config_async_callback,
-                        data);
-}
-
-gboolean syncevo_service_get_server_config (SyncevoService *service,
-                                            char *server,
-                                            GPtrArray **options,
-                                            GError **error)
-{
-       SyncevoServicePrivate *priv;
-
-       priv = GET_PRIVATE (service);
-
-       if (!priv->proxy && !syncevo_service_get_new_proxy (service)) {
-               if (error) {
-                       *error = g_error_new_literal (g_quark_from_static_string ("syncevo-service"),
-                                                     SYNCEVO_SERVICE_ERROR_COULD_NOT_START, 
-                                                     "Could not start service");
-               }
-               return FALSE;
-       }
-
-       return org_Moblin_SyncEvolution_get_server_config (priv->proxy, 
-                                                          server,
-                                                          options, 
-                                                          error);
-}
-
-static void
-get_server_config_async_callback (DBusGProxy *proxy, 
-                                  GPtrArray *options,
-                                  GError *error,
-                                  SyncevoAsyncData *data)
-{
-       (*(SyncevoGetServerConfigCb)data->callback) (data->service,
-                                                    options,
-                                                    error,
-                                                    data->userdata);
-       g_slice_free (SyncevoAsyncData, data);
-}
-
-static gboolean
-get_server_config_async_error (SyncevoAsyncData *data)
-{
-       GError *error;
-
-       error = g_error_new_literal (g_quark_from_static_string ("syncevo-service"),
-                                                                SYNCEVO_SERVICE_ERROR_COULD_NOT_START, 
-                                                                "Could not start service");
-       (*(SyncevoGetServerConfigCb)data->callback) (data->service,
-                                                    NULL,
-                                                    error,
-                                                    data->userdata);
-
-       return FALSE;
-}
-
-void 
-syncevo_service_get_server_config_async (SyncevoService *service,
-                                         char *server,
-                                         SyncevoGetServerConfigCb callback,
-                                         gpointer userdata)
-{
-       SyncevoAsyncData *data;
-       SyncevoServicePrivate *priv;
-
-       priv = GET_PRIVATE (service);
-
-       data = g_slice_new0 (SyncevoAsyncData);
-       data->service = service;
-       data->callback = G_CALLBACK (callback);
-       data->userdata = userdata;
-
-       if (!priv->proxy && !syncevo_service_get_new_proxy (service)) {
-               g_idle_add ((GSourceFunc)get_server_config_async_error, data);
-               return;
-       }
-
-       org_Moblin_SyncEvolution_get_server_config_async 
-                       (priv->proxy,
-                        server,
-                        (org_Moblin_SyncEvolution_get_server_config_reply) get_server_config_async_callback,
-                        data);
-}
-
-
-gboolean syncevo_service_set_server_config (SyncevoService *service,
-                                            char *server,
-                                            GPtrArray *options,
-                                            GError **error)
-{
-       SyncevoServicePrivate *priv;
-
-       priv = GET_PRIVATE (service);
-
-       if (!priv->proxy && !syncevo_service_get_new_proxy (service)) {
-               if (error) {
-                       *error = g_error_new_literal (g_quark_from_static_string ("syncevo-service"),
-                                                     SYNCEVO_SERVICE_ERROR_COULD_NOT_START, 
-                                                     "Could not start service");
-               }
-               return FALSE;
-       }
-
-       return org_Moblin_SyncEvolution_set_server_config (priv->proxy, 
-                                                          server,
-                                                          options, 
-                                                          error);
-}
-
-static void
-set_server_config_async_callback (DBusGProxy *proxy, 
-                                  GError *error,
-                                  SyncevoAsyncData *data)
-{
-       (*(SyncevoSetServerConfigCb)data->callback) (data->service,
-                                                    error,
-                                                    data->userdata);
-       g_slice_free (SyncevoAsyncData, data);
-}
-
-static gboolean
-set_server_config_async_error (SyncevoAsyncData *data)
-{
-       GError *error;
-
-       error = g_error_new_literal (g_quark_from_static_string ("syncevo-service"),
-                                                                SYNCEVO_SERVICE_ERROR_COULD_NOT_START, 
-                                                                "Could not start service");
-       (*(SyncevoSetServerConfigCb)data->callback) (data->service,
-                                                    error,
-                                                    data->userdata);
-       g_slice_free (SyncevoAsyncData, data);
-
-       return FALSE;
-}
-
-void 
-syncevo_service_set_server_config_async (SyncevoService *service,
-                                         char *server,
-                                         GPtrArray *options,
-                                         SyncevoSetServerConfigCb callback,
-                                         gpointer userdata)
-{
-       SyncevoAsyncData *data;
-       SyncevoServicePrivate *priv;
-
-       priv = GET_PRIVATE (service);
-
-       data = g_slice_new0 (SyncevoAsyncData);
-       data->service = service;
-       data->callback = G_CALLBACK (callback);
-       data->userdata = userdata;
-
-       if (!priv->proxy && !syncevo_service_get_new_proxy (service)) {
-               g_idle_add ((GSourceFunc)set_server_config_async_error, data);
-               return;
-       }
-
-       org_Moblin_SyncEvolution_set_server_config_async
-                       (priv->proxy,
-                        server,
-                        options,
-                        (org_Moblin_SyncEvolution_set_server_config_reply) set_server_config_async_callback,
-                        data);
-}
-
-gboolean 
-syncevo_service_remove_server_config (SyncevoService *service,
-                                      char *server,
-                                      GError **error)
-{
-       SyncevoServicePrivate *priv;
-
-       priv = GET_PRIVATE (service);
-
-       if (!priv->proxy && !syncevo_service_get_new_proxy (service)) {
-               if (error) {
-                       *error = g_error_new_literal (g_quark_from_static_string ("syncevo-service"),
-                                                     SYNCEVO_SERVICE_ERROR_COULD_NOT_START, 
-                                                     "Could not start service");
-               }
-               return FALSE;
-       }
-
-       return org_Moblin_SyncEvolution_remove_server_config (priv->proxy, 
-                                                             server,
-                                                             error);
-}
-
-static void
-remove_server_config_async_callback (DBusGProxy *proxy, 
-                                     GError *error,
-                                     SyncevoAsyncData *data)
-{
-       (*(SyncevoRemoveServerConfigCb)data->callback) (data->service,
-                                                    error,
-                                                    data->userdata);
-       g_slice_free (SyncevoAsyncData, data);
-}
-
-static gboolean
-remove_server_config_async_error (SyncevoAsyncData *data)
-{
-       GError *error;
-
-       error = g_error_new_literal (g_quark_from_static_string ("syncevo-service"),
-                                                                SYNCEVO_SERVICE_ERROR_COULD_NOT_START, 
-                                                                "Could not start service");
-       (*(SyncevoRemoveServerConfigCb)data->callback) (data->service,
-                                                       error,
-                                                       data->userdata);
-       g_slice_free (SyncevoAsyncData, data);
-
-       return FALSE;
-}
-
-void 
-syncevo_service_remove_server_config_async (SyncevoService *service,
-                                            char *server,
-                                            SyncevoRemoveServerConfigCb callback,
-                                            gpointer userdata)
-{
-       SyncevoAsyncData *data;
-       SyncevoServicePrivate *priv;
-
-       priv = GET_PRIVATE (service);
-
-       data = g_slice_new0 (SyncevoAsyncData);
-       data->service = service;
-       data->callback = G_CALLBACK (callback);
-       data->userdata = userdata;
-
-       if (!priv->proxy && !syncevo_service_get_new_proxy (service)) {
-               g_idle_add ((GSourceFunc)remove_server_config_async_error, data);
-               return;
-       }
-
-       org_Moblin_SyncEvolution_remove_server_config_async 
-                       (priv->proxy,
-                        server,
-                        (org_Moblin_SyncEvolution_remove_server_config_reply) remove_server_config_async_callback,
-                        data);
-}
-
-gboolean 
-syncevo_service_get_sync_reports (SyncevoService *service,
-                                  char *server,
-                                  int count,
-                                  GPtrArray **reports,
-                                  GError **error)
-{
-       SyncevoServicePrivate *priv;
-
-       priv = GET_PRIVATE (service);
-
-       if (!priv->proxy && !syncevo_service_get_new_proxy (service)) {
-               if (error) {
-                       *error = g_error_new_literal (g_quark_from_static_string ("syncevo-service"),
-                                                     SYNCEVO_SERVICE_ERROR_COULD_NOT_START, 
-                                                     "Could not start service");
-               }
-               return FALSE;
-       }
-
-       return org_Moblin_SyncEvolution_get_sync_reports ( 
-                       priv->proxy,
-                       server,
-                       count,
-                       reports,
-                       error);
-}
-
-static void
-get_sync_reports_async_callback (DBusGProxy *proxy, 
-                                 GPtrArray *reports,
-                                 GError *error,
-                                 SyncevoAsyncData *data)
-{
-       (*(SyncevoGetSyncReportsCb)data->callback) (data->service,
-                                                   reports,
-                                                   error,
-                                                   data->userdata);
-       g_slice_free (SyncevoAsyncData, data);
-}
-
-static gboolean
-get_sync_reports_async_error (SyncevoAsyncData *data)
-{
-       GError *error;
-
-       error = g_error_new_literal (g_quark_from_static_string ("syncevo-service"),
-                                                                SYNCEVO_SERVICE_ERROR_COULD_NOT_START, 
-                                                                "Could not start service");
-       (*(SyncevoGetSyncReportsCb)data->callback) (data->service,
-                                                   NULL,
-                                                   error,
-                                                   data->userdata);
-       g_slice_free (SyncevoAsyncData, data);
-
-       return FALSE;
-}
-
-void 
-syncevo_service_get_sync_reports_async (SyncevoService *service,
-                                       char *server,
-                                       int count,
-                                       SyncevoGetSyncReportsCb callback,
-                                       gpointer userdata)
-{
-       SyncevoAsyncData *data;
-       SyncevoServicePrivate *priv;
-
-       priv = GET_PRIVATE (service);
-
-       data = g_slice_new0 (SyncevoAsyncData);
-       data->service = service;
-       data->callback = G_CALLBACK (callback);
-       data->userdata = userdata;
-
-       if (!priv->proxy && !syncevo_service_get_new_proxy (service)) {
-               g_idle_add ((GSourceFunc)get_sync_reports_async_error, data);
-               return;
-       }
-
-       org_Moblin_SyncEvolution_get_sync_reports_async 
-                       (priv->proxy,
-                        server,
-                        count,
-                        (org_Moblin_SyncEvolution_get_sync_reports_reply) get_sync_reports_async_callback,
-                        data);
-}
diff --git a/src/dbus/syncevo-dbus.h b/src/dbus/syncevo-dbus.h
deleted file mode 100644 (file)
index 7590a48..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (C) 2009 Intel Corporation
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) version 3.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301  USA
- */
-
-#ifndef __SYNCEVO_SERVICE_H__
-#define __SYNCEVO_SERVICE_H__
-
-#include <glib-object.h>
-#include "syncevo-dbus-types.h"
-
-G_BEGIN_DECLS 
-
-enum SyncevoServiceError{
-       SYNCEVO_SERVICE_ERROR_COULD_NOT_START = 1,
-};
-
-#define SYNCEVO_SERVICE_DBUS_SERVICE "org.Moblin.SyncEvolution"
-#define SYNCEVO_SERVICE_DBUS_PATH "/org/Moblin/SyncEvolution"
-#define SYNCEVO_SERVICE_DBUS_INTERFACE "org.Moblin.SyncEvolution"
-
-#define SYNCEVO_TYPE_SERVICE (syncevo_service_get_type ())
-#define SYNCEVO_SERVICE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SYNCEVO_TYPE_SERVICE, SyncevoService))
-#define SYNCEVO_IS_SERVICE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SYNCEVO_TYPE_SERVICE))
-
-
-typedef struct _SyncevoService {
-       GObject parent_object;
-} SyncevoService;
-
-typedef struct _SyncevoServiceClass {
-       GObjectClass parent_class;
-
-       void (*progress) (SyncevoService *service,
-                         char *server,
-                         char *source,
-                         int type,
-                         int extra1, int extra2, int extra3);
-       void (*server_message) (SyncevoService *service,
-                               char *server,
-                               char *message);
-       void (*server_shutdown) (SyncevoService *service);
-} SyncevoServiceClass;
-
-GType syncevo_service_get_type (void);
-
-SyncevoService *syncevo_service_get_default ();
-
-gboolean syncevo_service_start_sync (SyncevoService *service,
-                                     char *server,
-                                     GPtrArray *sources,
-                                     GError **error);
-gboolean syncevo_service_abort_sync (SyncevoService *service,
-                                     char *server,
-                                     GError **error);
-typedef void (*SyncevoAbortSyncCb) (SyncevoService *service,
-                                     GError *error,
-                                     gpointer userdata);
-void  syncevo_service_abort_sync_async (SyncevoService *service,
-                                        char *server,
-                                        SyncevoAbortSyncCb callback,
-                                        gpointer userdata);
-
-gboolean syncevo_service_get_servers (SyncevoService *service,
-                                      GPtrArray **servers,
-                                      GError **error);
-typedef void (*SyncevoGetServersCb) (SyncevoService *service,
-                                     GPtrArray *servers,
-                                     GError *error,
-                                     gpointer userdata);
-void syncevo_service_get_servers_async (SyncevoService *service,
-                                        SyncevoGetServersCb callback,
-                                        gpointer userdata);
-
-gboolean syncevo_service_get_templates (SyncevoService *service,
-                                        GPtrArray **templates,
-                                        GError **error);
-typedef void (*SyncevoGetTemplatesCb) (SyncevoService *service,
-                                       GPtrArray *templates,
-                                       GError *error,
-                                       gpointer userdata);
-void syncevo_service_get_templates_async (SyncevoService *service,
-                                          SyncevoGetTemplatesCb callback,
-                                          gpointer userdata);
-
-gboolean syncevo_service_get_template_config (SyncevoService *service,
-                                              char *template,
-                                              GPtrArray **options,
-                                              GError **error);
-typedef void (*SyncevoGetTemplateConfigCb) (SyncevoService *service,
-                                            GPtrArray *options,
-                                            GError *error,
-                                            gpointer userdata);
-void syncevo_service_get_template_config_async (SyncevoService *service,
-                                                char *template,
-                                                SyncevoGetTemplateConfigCb callback,
-                                                gpointer userdata);
-
-gboolean syncevo_service_get_server_config (SyncevoService *service,
-                                            char *server,
-                                            GPtrArray **options,
-                                            GError **error);
-typedef void (*SyncevoGetServerConfigCb) (SyncevoService *service,
-                                          GPtrArray *options,
-                                          GError *error,
-                                          gpointer userdata);
-void syncevo_service_get_server_config_async (SyncevoService *service,
-                                              char *server,
-                                              SyncevoGetServerConfigCb callback,
-                                              gpointer userdata);
-
-gboolean syncevo_service_set_server_config (SyncevoService *service,
-                                            char *server,
-                                            GPtrArray *options,
-                                            GError **error);
-typedef void (*SyncevoSetServerConfigCb) (SyncevoService *service,
-                                          GError *error,
-                                          gpointer userdata);
-void syncevo_service_set_server_config_async (SyncevoService *service,
-                                              char *server,
-                                              GPtrArray *options,
-                                              SyncevoSetServerConfigCb callback,
-                                              gpointer userdata);
-
-gboolean syncevo_service_remove_server_config (SyncevoService *service,
-                                               char *server,
-                                               GError **error);
-typedef void (*SyncevoRemoveServerConfigCb) (SyncevoService *service,
-                                             GError *error,
-                                             gpointer userdata);
-void syncevo_service_remove_server_config_async (SyncevoService *service,
-                                                 char *server,
-                                                 SyncevoRemoveServerConfigCb callback,
-                                                 gpointer userdata);
-
-
-gboolean syncevo_service_get_sync_reports (SyncevoService *service,
-                                           char *server,
-                                           int count,
-                                           GPtrArray **reports,
-                                           GError **error);
-typedef void (*SyncevoGetSyncReportsCb) (SyncevoService *service,
-                                         GPtrArray *reports,
-                                         GError *error,
-                                         gpointer userdata);
-void syncevo_service_get_sync_reports_async (SyncevoService *service,
-                                             char *server,
-                                             int count,
-                                             SyncevoGetSyncReportsCb callback,
-                                             gpointer userdata);
-
-
-G_END_DECLS
-
-#endif
diff --git a/src/dbus/syncevo-server.c b/src/dbus/syncevo-server.c
new file mode 100644 (file)
index 0000000..0542780
--- /dev/null
@@ -0,0 +1,794 @@
+/*
+ * Copyright (C) 2009 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) version 3.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301  USA
+ */
+
+#include <glib-object.h>
+#include <string.h>
+
+#include "syncevo-server.h"
+#include "syncevo-marshal.h"
+#include "syncevo-server-bindings.h"
+
+typedef struct _ServerAsyncData {
+    SyncevoServer *server;
+    GCallback callback;
+    gpointer userdata;
+} ServerAsyncData;
+
+enum {
+    SESSION_CHANGED,
+    PRESENCE_CHANGED,
+    INFO_REQUEST,
+    SHUTDOWN,
+    LAST_SIGNAL
+};
+static guint32 signals[LAST_SIGNAL] = {0, };
+
+typedef struct _SyncevoServerPrivate {
+    DBusGProxy *proxy;
+} SyncevoServerPrivate;
+
+#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SYNCEVO_TYPE_SERVER, SyncevoServerPrivate))
+G_DEFINE_TYPE (SyncevoServer, syncevo_server, G_TYPE_OBJECT);
+
+static ServerAsyncData*
+server_async_data_new (SyncevoServer *server,
+                        GCallback callback,
+                        gpointer userdata)
+{
+    ServerAsyncData *data;
+
+    data = g_slice_new0 (ServerAsyncData);
+    data->server = server;
+    data->callback = G_CALLBACK (callback);
+    data->userdata = userdata;
+
+    return data;
+}
+
+static void
+server_async_data_free (ServerAsyncData *data)
+{
+    g_slice_free (ServerAsyncData, data);
+}
+
+static void
+generic_callback (DBusGProxy *proxy,
+                  GError *error,
+                  ServerAsyncData *data)
+{
+    if (data->callback) {
+        (*(SyncevoServerGenericCb)data->callback) (data->server,
+                                                   error,
+                                                   data->userdata);
+    }
+    server_async_data_free (data);
+}
+
+static gboolean
+generic_error (ServerAsyncData *data)
+{
+    GError *error;
+
+    error = g_error_new_literal (SYNCEVO_SERVER_ERROR_QUARK,
+                                 SYNCEVO_SERVER_ERROR_NO_DBUS_OBJECT, 
+                                 "The D-Bus object does not exist");
+    (*(SyncevoServerGenericCb)data->callback) (data->server,
+                                               error,
+                                               data->userdata);
+    server_async_data_free (data);
+
+    return FALSE;
+}
+
+static void
+session_changed_cb (DBusGProxy *proxy,
+                    char *session_path,
+                    gboolean started,
+                    SyncevoServer *server)
+{
+    g_signal_emit (server, signals[SESSION_CHANGED], 0, 
+                   session_path, started);
+}
+
+static void
+presence_cb (DBusGProxy *proxy,
+             char *configuration,
+             char *status,
+             char *transport,
+             SyncevoServer *server)
+{
+    g_signal_emit (server, signals[PRESENCE_CHANGED], 0, 
+                   configuration, status, transport);
+}
+
+static void
+info_request_cb (DBusGProxy *proxy,
+                 char *id,
+                 char *session_path,
+                 char *state,
+                 char *handler_path,
+                 char *type,
+                 SyncevoServer *server)
+{
+    g_signal_emit (server, signals[INFO_REQUEST], 0, 
+                   id, session_path, state, handler_path, type);
+}
+
+static void
+proxy_destroy_cb (DBusGProxy *proxy, 
+                  SyncevoServer *server)
+{
+    SyncevoServerPrivate *priv;
+    priv = GET_PRIVATE (server);
+
+    if (priv->proxy) {
+        g_object_unref (priv->proxy);
+    }
+    priv->proxy = NULL;
+
+    g_signal_emit (server, signals[SHUTDOWN], 0);
+}
+
+#if 0
+static void
+detach_cb (DBusGProxy *proxy,
+           GError *error,
+           gpointer userdata)
+{
+    if (error) {
+        g_warning ("Server.Detach failed: %s", error->message);
+        g_error_free (error);
+    }
+}
+#endif
+
+static void
+dispose (GObject *object)
+{
+    SyncevoServerPrivate *priv;
+
+    priv = GET_PRIVATE (object);
+
+    if (priv->proxy) {
+        dbus_g_proxy_disconnect_signal (priv->proxy, "SessionChanged",
+                                        G_CALLBACK (session_changed_cb),
+                                        object);
+        dbus_g_proxy_disconnect_signal (priv->proxy, "Presence",
+                                        G_CALLBACK (presence_cb),
+                                        object);
+        dbus_g_proxy_disconnect_signal (priv->proxy, "InfoRequest",
+                                        G_CALLBACK (info_request_cb),
+                                        object);
+        dbus_g_proxy_disconnect_signal (priv->proxy, "destroy",
+                                        G_CALLBACK (proxy_destroy_cb),
+                                        object);
+        org_syncevolution_Server_detach (priv->proxy, NULL);
+
+        g_object_unref (priv->proxy);
+        priv->proxy = NULL;
+    }
+
+    G_OBJECT_CLASS (syncevo_server_parent_class)->dispose (object);
+}
+
+static void
+attach_cb (DBusGProxy *proxy,
+           GError *error,
+           gpointer userdata)
+{
+    if (error) {
+        g_warning ("Server.Attach failed: %s", error->message);
+        g_error_free (error);
+    }
+}
+
+static gboolean
+syncevo_server_get_new_proxy (SyncevoServer *server)
+{
+    DBusGConnection *connection;
+    GError *error;
+    guint32 result;
+    SyncevoServerPrivate *priv;
+    DBusGProxy *proxy;
+
+    priv = GET_PRIVATE (server);
+    error = NULL;
+
+    connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+    if (connection == NULL) {
+        g_printerr ("Failed to open connection to bus: %s\n",
+                    error->message);
+        g_error_free (error);
+        priv->proxy = NULL;
+        return FALSE;
+    }
+
+    /* we want to use dbus_g_proxy_new_for_name_owner() for the destroy signal
+     * so need to start the service by hand by using DBUS proxy: */
+    proxy = dbus_g_proxy_new_for_name (connection,
+                                       DBUS_SERVICE_DBUS,
+                                       DBUS_PATH_DBUS,
+                                       DBUS_INTERFACE_DBUS);
+    if (!dbus_g_proxy_call (proxy, "StartServiceByName", NULL,
+                            G_TYPE_STRING, DBUS_SERVICE_SYNCEVO_SERVER,
+                            G_TYPE_UINT, 0,
+                            G_TYPE_INVALID,
+                            G_TYPE_UINT, &result,
+                            G_TYPE_INVALID)) {
+        g_warning ("StartServiceByName call failed");
+    }
+    g_object_unref (proxy);
+
+    /* the real proxy */
+    priv->proxy = dbus_g_proxy_new_for_name_owner (connection,
+                                             DBUS_SERVICE_SYNCEVO_SERVER,
+                                             DBUS_PATH_SYNCEVO_SERVER,
+                                             DBUS_INTERFACE_SYNCEVO_SERVER,
+                                             &error);
+    if (priv->proxy == NULL) {
+        g_printerr ("dbus_g_proxy_new_for_name_owner() failed: %s\n", error->message);
+        g_error_free (error);
+        return FALSE;
+    }
+
+    dbus_g_proxy_add_signal (priv->proxy, "SessionChanged",
+                             DBUS_TYPE_G_OBJECT_PATH, G_TYPE_BOOLEAN, G_TYPE_INVALID);
+    dbus_g_proxy_connect_signal (priv->proxy, "SessionChanged",
+                                 G_CALLBACK (session_changed_cb), server, NULL);
+    dbus_g_proxy_add_signal (priv->proxy, "Presence",
+                             G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
+    dbus_g_proxy_connect_signal (priv->proxy, "Presence",
+                                 G_CALLBACK (presence_cb), server, NULL);
+    dbus_g_proxy_add_signal (priv->proxy, "InfoRequest",
+                             G_TYPE_STRING,
+                             DBUS_TYPE_G_OBJECT_PATH,
+                             G_TYPE_STRING,
+                             DBUS_TYPE_G_OBJECT_PATH,
+                             G_TYPE_STRING,
+                             G_TYPE_INVALID);
+    dbus_g_proxy_connect_signal (priv->proxy, "InfoRequest",
+                                 G_CALLBACK (info_request_cb), server, NULL);
+    g_signal_connect (priv->proxy, "destroy",
+                      G_CALLBACK (proxy_destroy_cb), server);
+
+    org_syncevolution_Server_attach_async (priv->proxy,
+                                           (org_syncevolution_Server_attach_reply)attach_cb,
+                                           NULL);
+
+    return TRUE;
+}
+
+
+static void
+syncevo_server_init (SyncevoServer *server)
+{
+    SyncevoServerPrivate *priv;
+
+    priv = GET_PRIVATE (server);
+
+    /* SessionChanged */
+    dbus_g_object_register_marshaller (syncevo_marshal_VOID__STRING_BOOLEAN,
+                                       G_TYPE_NONE,
+                                       DBUS_TYPE_G_OBJECT_PATH,
+                                       G_TYPE_BOOLEAN,
+                                       G_TYPE_INVALID);
+    /* Presence */
+    dbus_g_object_register_marshaller (syncevo_marshal_VOID__STRING_STRING_STRING,
+                                       G_TYPE_NONE,
+                                       G_TYPE_STRING,
+                                       G_TYPE_STRING,
+                                       G_TYPE_STRING,
+                                       G_TYPE_INVALID);
+    /* InfoRequest */
+    dbus_g_object_register_marshaller (syncevo_marshal_VOID__STRING_STRING_STRING_STRING_STRING,
+                                       G_TYPE_NONE,
+                                       G_TYPE_STRING,
+                                       DBUS_TYPE_G_OBJECT_PATH,
+                                       G_TYPE_STRING,
+                                       DBUS_TYPE_G_OBJECT_PATH,
+                                       G_TYPE_STRING,
+                                       G_TYPE_INVALID);
+
+    syncevo_server_get_new_proxy (server);
+}
+
+static void
+syncevo_server_class_init (SyncevoServerClass *klass)
+{
+    GObjectClass *o_class = (GObjectClass *) klass;
+
+    o_class->dispose = dispose;
+
+    g_type_class_add_private (klass, sizeof (SyncevoServerPrivate));
+
+    signals[SESSION_CHANGED] =
+            g_signal_new ("session-changed",
+                          G_TYPE_FROM_CLASS (klass),
+                          G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
+                          G_STRUCT_OFFSET (SyncevoServerClass, session_changed),
+                          NULL, NULL,
+                          syncevo_marshal_VOID__STRING_BOOLEAN,
+                          G_TYPE_NONE,
+                          2, G_TYPE_STRING, G_TYPE_BOOLEAN);
+    signals[PRESENCE_CHANGED] =
+            g_signal_new ("presence-changed",
+                          G_TYPE_FROM_CLASS (klass),
+                          G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
+                          G_STRUCT_OFFSET (SyncevoServerClass, presence_changed),
+                          NULL, NULL,
+                          syncevo_marshal_VOID__STRING_STRING_STRING,
+                          G_TYPE_NONE,
+                          3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+    signals[INFO_REQUEST] =
+            g_signal_new ("info-request",
+                          G_TYPE_FROM_CLASS (klass),
+                          G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
+                          G_STRUCT_OFFSET (SyncevoServerClass, info_request),
+                          NULL, NULL,
+                          syncevo_marshal_VOID__STRING_STRING_STRING_STRING_STRING,
+                          G_TYPE_NONE,
+                          5, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+    signals[SHUTDOWN] =
+            g_signal_new ("shutdown",
+                          G_TYPE_FROM_CLASS (klass),
+                          G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
+                          G_STRUCT_OFFSET (SyncevoServerClass, shutdown),
+                          NULL, NULL,
+                          g_cclosure_marshal_VOID__VOID,
+                          G_TYPE_NONE,
+                          0);
+}
+
+SyncevoServer *
+syncevo_server_get_default ()
+{
+    static SyncevoServer *server = NULL;
+
+    if (server == NULL) {
+        server = g_object_new (SYNCEVO_TYPE_SERVER, NULL);
+        g_object_add_weak_pointer (G_OBJECT (server),
+                                   (gpointer) &server);
+        return server;
+    }
+
+    return g_object_ref (server);
+}
+
+
+static void
+get_configs_callback (DBusGProxy *proxy, 
+                      char **config_names,
+                      GError *error,
+                      ServerAsyncData *data)
+{
+    if (data->callback) {
+        (*(SyncevoServerGetConfigsCb)data->callback) (data->server,
+                                                      config_names,
+                                                      error,
+                                                      data->userdata);
+    }
+    server_async_data_free (data);
+}
+
+static gboolean
+get_configs_error (ServerAsyncData *data)
+{
+    GError *error;
+
+    error = g_error_new_literal (SYNCEVO_SERVER_ERROR_QUARK,
+                                 SYNCEVO_SERVER_ERROR_NO_DBUS_OBJECT, 
+                                 "Could not start service");
+    (*(SyncevoServerGetConfigsCb)data->callback) (data->server,
+                                                  NULL,
+                                                  error,
+                                                  data->userdata);
+    server_async_data_free (data);
+
+    return FALSE;
+}
+
+void
+syncevo_server_get_configs (SyncevoServer *syncevo,
+                            gboolean template,
+                            SyncevoServerGetConfigsCb callback,
+                            gpointer userdata)
+{
+    ServerAsyncData *data;
+    SyncevoServerPrivate *priv;
+
+    priv = GET_PRIVATE (syncevo);
+
+    data = server_async_data_new (syncevo, G_CALLBACK (callback), userdata);
+
+    if (!priv->proxy && !syncevo_server_get_new_proxy (syncevo)) {
+        if (callback) {
+            g_idle_add ((GSourceFunc)get_configs_error, data);
+        }
+        return;
+    }
+
+    org_syncevolution_Server_get_configs_async
+            (priv->proxy,
+             template,
+             (org_syncevolution_Server_get_configs_reply) get_configs_callback,
+             data);
+}
+
+static void
+get_config_callback (DBusGProxy *proxy,
+                     SyncevoConfig *configuration,
+                     GError *error,
+                     ServerAsyncData *data)
+{
+    if (data->callback) {
+        (*(SyncevoServerGetConfigCb)data->callback) (data->server,
+                                                     configuration,
+                                                     error,
+                                                     data->userdata);
+    }
+    server_async_data_free (data);
+}
+
+static gboolean
+get_config_error (ServerAsyncData *data)
+{
+    GError *error;
+
+    error = g_error_new_literal (SYNCEVO_SERVER_ERROR_QUARK,
+                                 SYNCEVO_SERVER_ERROR_NO_DBUS_OBJECT, 
+                                 "Could not start service");
+    (*(SyncevoServerGetConfigCb)data->callback) (data->server,
+                                                 NULL,
+                                                 error,
+                                                 data->userdata);
+    server_async_data_free (data);
+
+    return FALSE;
+}
+
+void
+syncevo_server_get_config (SyncevoServer *syncevo,
+                           const char *config_name, 
+                           gboolean template,
+                           SyncevoServerGetConfigCb callback,
+                           gpointer userdata)
+{
+    ServerAsyncData *data;
+    SyncevoServerPrivate *priv;
+
+    priv = GET_PRIVATE (syncevo);
+
+    data = server_async_data_new (syncevo, G_CALLBACK (callback), userdata);
+
+    if (!priv->proxy && !syncevo_server_get_new_proxy (syncevo)) {
+        if (callback) {
+            g_idle_add ((GSourceFunc)get_config_error, data);
+        }
+        return;
+    }
+
+    org_syncevolution_Server_get_config_async 
+            (priv->proxy,
+             config_name,
+             template,
+             (org_syncevolution_Server_get_config_reply) get_config_callback,
+             data);
+}
+
+static void
+get_reports_callback (DBusGProxy *proxy,
+                      SyncevoReports *reports,
+                      GError *error,
+                      ServerAsyncData *data)
+{
+    if (data->callback) {
+        (*(SyncevoServerGetReportsCb)data->callback) (data->server,
+                                                      reports,
+                                                      error,
+                                                      data->userdata);
+    }
+    server_async_data_free (data);
+}
+
+static gboolean
+get_reports_error (ServerAsyncData *data)
+{
+    GError *error;
+
+    error = g_error_new_literal (SYNCEVO_SERVER_ERROR_QUARK,
+                                 SYNCEVO_SERVER_ERROR_NO_DBUS_OBJECT, 
+                                 "Could not start service");
+    (*(SyncevoServerGetReportsCb)data->callback) (data->server,
+                                                  NULL,
+                                                  error,
+                                                  data->userdata);
+    server_async_data_free (data);
+
+    return FALSE;    
+}
+
+void
+syncevo_server_get_reports (SyncevoServer *syncevo,
+                            const char *config_name,
+                            guint start,
+                            guint count,
+                            SyncevoServerGetReportsCb callback,
+                            gpointer userdata)
+{
+    ServerAsyncData *data;
+    SyncevoServerPrivate *priv;
+
+    priv = GET_PRIVATE (syncevo);
+
+    data = server_async_data_new (syncevo, G_CALLBACK (callback), userdata);
+
+    if (!priv->proxy && !syncevo_server_get_new_proxy (syncevo)) {
+        if (callback) {
+            g_idle_add ((GSourceFunc)get_reports_error, data);
+        }
+        return;
+    }
+
+    org_syncevolution_Server_get_reports_async
+            (priv->proxy,
+             config_name,
+             start,
+             count,
+             (org_syncevolution_Server_get_reports_reply) get_reports_callback,
+             data);
+}
+
+static void
+start_session_callback (SyncevoServer *syncevo,
+                        char *session_path,
+                        GError *error,
+                        ServerAsyncData *data)
+{
+    if (data->callback) {
+        (*(SyncevoServerStartSessionCb)data->callback) (data->server,
+                                                        session_path,
+                                                        error,
+                                                        data->userdata);
+    }
+    server_async_data_free (data);
+}
+
+static gboolean
+start_session_error (ServerAsyncData *data)
+{
+    GError *error;
+
+    error = g_error_new_literal (SYNCEVO_SERVER_ERROR_QUARK,
+                                 SYNCEVO_SERVER_ERROR_NO_DBUS_OBJECT, 
+                                 "Could not start service");
+    (*(SyncevoServerStartSessionCb)data->callback) (data->server,
+                                                    NULL,
+                                                    error,
+                                                    data->userdata);
+    server_async_data_free (data);
+
+    return FALSE;    
+}
+
+void
+syncevo_server_start_session (SyncevoServer *syncevo,
+                              const char *config_name, 
+                              SyncevoServerStartSessionCb callback,
+                              gpointer userdata)
+{
+    ServerAsyncData *data;
+    SyncevoServerPrivate *priv;
+
+    priv = GET_PRIVATE (syncevo);
+
+    data = server_async_data_new (syncevo, G_CALLBACK (callback), userdata);
+
+    if (!priv->proxy && !syncevo_server_get_new_proxy (syncevo)) {
+        if (callback) {
+            g_idle_add ((GSourceFunc)start_session_error, data);
+        }
+        return;
+    }
+
+    org_syncevolution_Server_start_session_async
+            (priv->proxy,
+             config_name,
+             (org_syncevolution_Server_start_session_reply) start_session_callback,
+             data);
+}
+
+static void
+get_sessions_callback (SyncevoServer *syncevo,
+                       SyncevoSessions *sessions,
+                       GError *error,
+                       ServerAsyncData *data)
+{
+    if (data->callback) {
+        (*(SyncevoServerGetSessionsCb)data->callback) (data->server,
+                                                       sessions,
+                                                       error,
+                                                       data->userdata);
+    }
+    server_async_data_free (data);
+}
+
+static gboolean
+get_sessions_error (ServerAsyncData *data)
+{
+    GError *error;
+
+    error = g_error_new_literal (SYNCEVO_SERVER_ERROR_QUARK,
+                                 SYNCEVO_SERVER_ERROR_NO_DBUS_OBJECT, 
+                                 "Could not start service");
+    (*(SyncevoServerGetSessionsCb)data->callback) (data->server,
+                                                   NULL,
+                                                   error,
+                                                   data->userdata);
+    server_async_data_free (data);
+
+    return FALSE;    
+}
+
+void
+syncevo_server_get_sessions (SyncevoServer *syncevo,
+                             SyncevoServerGetSessionsCb callback,
+                             gpointer userdata)
+{
+    ServerAsyncData *data;
+    SyncevoServerPrivate *priv;
+
+    priv = GET_PRIVATE (syncevo);
+
+    data = server_async_data_new (syncevo, G_CALLBACK (callback), userdata);
+
+    if (!priv->proxy && !syncevo_server_get_new_proxy (syncevo)) {
+        if (callback) {
+            g_idle_add ((GSourceFunc)get_sessions_error, data);
+        }
+        return;
+    }
+
+    org_syncevolution_Server_get_sessions_async
+            (priv->proxy,
+             (org_syncevolution_Server_get_reports_reply) get_sessions_callback,
+             data);
+}
+
+
+static void
+check_presence_callback (SyncevoServer *syncevo,
+                         char *status,
+                         char *transport,
+                         GError *error,
+                         ServerAsyncData *data)
+{
+    if (data->callback) {
+        (*(SyncevoServerGetPresenceCb)data->callback) (data->server,
+                                                       status,
+                                                       transport,
+                                                       error,
+                                                       data->userdata);
+    }
+    server_async_data_free (data);
+}
+
+static gboolean
+check_presence_error (ServerAsyncData *data)
+{
+    GError *error;
+
+    error = g_error_new_literal (SYNCEVO_SERVER_ERROR_QUARK,
+                                 SYNCEVO_SERVER_ERROR_NO_DBUS_OBJECT, 
+                                 "Could not start service");
+    (*(SyncevoServerGetPresenceCb)data->callback) (data->server,
+                                                   NULL,
+                                                   NULL,
+                                                   error,
+                                                   data->userdata);
+    server_async_data_free (data);
+
+    return FALSE;
+}
+
+
+void
+syncevo_server_get_presence (SyncevoServer *syncevo,
+                             const char *config_name,
+                             SyncevoServerGetPresenceCb callback,
+                             gpointer userdata)
+{
+    ServerAsyncData *data;
+    SyncevoServerPrivate *priv;
+
+    priv = GET_PRIVATE (syncevo);
+
+    data = server_async_data_new (syncevo, G_CALLBACK (callback), userdata);
+
+    if (!priv->proxy && !syncevo_server_get_new_proxy (syncevo)) {
+        if (callback) {
+            g_idle_add ((GSourceFunc)check_presence_error, data);
+        }
+        return;
+    }
+
+    org_syncevolution_Server_check_presence_async
+            (priv->proxy,
+             config_name,
+             (org_syncevolution_Server_check_presence_reply) check_presence_callback,
+             data);
+}
+
+void syncevo_server_check_source (SyncevoServer *server,
+                                  const char *config,
+                                  const char *source,
+                                  SyncevoServerGenericCb callback,
+                                  gpointer userdata)
+{
+    ServerAsyncData *data;
+    SyncevoServerPrivate *priv;
+
+    priv = GET_PRIVATE (server);
+
+    data = server_async_data_new (server, G_CALLBACK (callback), userdata);
+
+    if (!priv->proxy) {
+        if (callback) {
+            g_idle_add ((GSourceFunc)generic_error, data);
+        }
+        return;
+    }
+
+    org_syncevolution_Server_check_source_async 
+            (priv->proxy,
+             config,
+             source,
+             (org_syncevolution_Server_check_source_reply) generic_callback,
+             data);
+}
+
+void
+syncevo_server_info_response (SyncevoServer *server,
+                              const char *id,
+                              const char *state,
+                              GHashTable *response,
+                              SyncevoServerGenericCb callback,
+                              gpointer userdata)
+{
+    ServerAsyncData *data;
+    SyncevoServerPrivate *priv;
+
+    priv = GET_PRIVATE (server);
+
+    data = server_async_data_new (server, G_CALLBACK (callback), userdata);
+
+    if (!priv->proxy) {
+        if (callback) {
+            g_idle_add ((GSourceFunc)generic_error, data);
+        }
+        return;
+    }
+
+    org_syncevolution_Server_info_response_async
+            (priv->proxy,
+             id,
+             state,
+             response,
+             (org_syncevolution_Server_info_response_reply) generic_callback,
+             data);
+}
diff --git a/src/dbus/syncevo-server.h b/src/dbus/syncevo-server.h
new file mode 100644 (file)
index 0000000..3cf8fd0
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2009 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) version 3.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301  USA
+ */
+
+#ifndef __SYNCEVO_SERVER_H__
+#define __SYNCEVO_SERVER_H__
+
+#include <glib-object.h>
+#include "syncevo-dbus-types.h"
+#include "syncevo-session.h"
+
+G_BEGIN_DECLS 
+
+enum SyncevoServerError{
+    SYNCEVO_SERVER_ERROR_NO_DBUS_OBJECT = 1,
+};
+
+#define SYNCEVO_SERVER_ERROR_QUARK g_quark_from_static_string ("syncevo-server")
+
+#define DBUS_SERVICE_SYNCEVO_SERVER "org.syncevolution"
+#define DBUS_PATH_SYNCEVO_SERVER "/org/syncevolution/Server"
+#define DBUS_INTERFACE_SYNCEVO_SERVER "org.syncevolution.Server"
+
+#define SYNCEVO_TYPE_SERVER (syncevo_server_get_type ())
+#define SYNCEVO_SERVER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SYNCEVO_TYPE_SERVER, SyncevoServer))
+#define SYNCEVO_IS_SERVER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SYNCEVO_TYPE_SERVER))
+
+
+typedef struct _SyncevoServer {
+    GObject parent_object;
+} SyncevoServer;
+
+typedef struct _SyncevoServerClass {
+    GObjectClass parent_class;
+
+    void (*session_changed) (SyncevoServer *syncevo,
+                             char *session_path,
+                             gboolean started);
+
+    void (*presence_changed) (SyncevoServer *syncevo,
+                              char *configuration,
+                              char *status,
+                              char *transport);
+
+    void (*info_request) (SyncevoServer *syncevo,
+                          char *id,
+                          char *session_path,
+                          char *state,
+                          char *handler_path,
+                          char *type);
+
+    void (*shutdown) (SyncevoServer *syncevo);
+} SyncevoServerClass;
+
+GType syncevo_server_get_type (void);
+
+SyncevoServer *syncevo_server_get_default ();
+
+typedef void (*SyncevoServerGenericCb) (SyncevoServer *server,
+                                        GError *error,
+                                        gpointer userdata);
+
+typedef void (*SyncevoServerGetConfigsCb) (SyncevoServer *syncevo,
+                                           char **config_names,
+                                           GError *error,
+                                           gpointer userdata);
+void syncevo_server_get_configs (SyncevoServer *syncevo,
+                                 gboolean template,
+                                 SyncevoServerGetConfigsCb callback,
+                                 gpointer userdata);
+
+typedef void (*SyncevoServerGetConfigCb) (SyncevoServer *syncevo,
+                                          SyncevoConfig *config,
+                                          GError *error,
+                                          gpointer userdata);
+void syncevo_server_get_config (SyncevoServer *syncevo,
+                                const char *config_name, 
+                                gboolean template,
+                                SyncevoServerGetConfigCb callback,
+                                gpointer userdata);
+
+typedef void (*SyncevoServerGetReportsCb) (SyncevoServer *syncevo,
+                                           SyncevoReports *reports,
+                                           GError *error,
+                                           gpointer userdata);
+void syncevo_server_get_reports (SyncevoServer *syncevo,
+                                 const char *config_name,
+                                 guint start,
+                                 guint count,
+                                 SyncevoServerGetReportsCb callback,
+                                 gpointer userdata);
+
+typedef void (*SyncevoServerStartSessionCb) (SyncevoServer *syncevo,
+                                             char *session_path,
+                                             GError *error,
+                                             gpointer userdata);
+void syncevo_server_start_session (SyncevoServer *syncevo,
+                                   const char *config_name, 
+                                   SyncevoServerStartSessionCb callback,
+                                   gpointer userdata);
+
+typedef void (*SyncevoServerGetSessionsCb) (SyncevoServer *syncevo,
+                                            SyncevoSessions *sessions,
+                                            GError *error,
+                                            gpointer userdata);
+void syncevo_server_get_sessions (SyncevoServer *syncevo,
+                                  SyncevoServerGetSessionsCb callback,
+                                  gpointer userdata);
+
+typedef void (*SyncevoServerGetPresenceCb) (SyncevoServer *syncevo,
+                                            char *status,
+                                            char *transport,
+                                            GError *error,
+                                            gpointer userdata);
+void syncevo_server_get_presence (SyncevoServer *syncevo,
+                                  const char *config_name,
+                                  SyncevoServerGetPresenceCb callback,
+                                  gpointer userdata);
+
+void syncevo_server_check_source (SyncevoServer *server,
+                                  const char *config,
+                                  const char *source,
+                                  SyncevoServerGenericCb callback,
+                                  gpointer userdata);
+
+void syncevo_server_info_response (SyncevoServer *server,
+                                   const char *id,
+                                   const char *state,
+                                   GHashTable *response,
+                                   SyncevoServerGenericCb callback,
+                                   gpointer userdata);
+
+G_END_DECLS
+
+#endif
diff --git a/src/dbus/syncevo-session.c b/src/dbus/syncevo-session.c
new file mode 100644 (file)
index 0000000..2ef0303
--- /dev/null
@@ -0,0 +1,688 @@
+/*
+ * Copyright (C) 2009 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) version 3.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301  USA
+ */
+
+#include <glib-object.h>
+#include <string.h>
+
+#include "syncevo-session.h"
+#include "syncevo-marshal.h"
+#include "syncevo-session-bindings.h"
+
+typedef struct _SessionAsyncData {
+    SyncevoSession *session;
+    GCallback callback;
+    gpointer userdata;
+} SessionAsyncData;
+
+enum {
+       PROP_0,
+       PROP_SESSION_PATH,
+};
+
+enum {
+    STATUS_CHANGED,
+    PROGRESS_CHANGED,
+    LAST_SIGNAL
+};
+static guint32 signals[LAST_SIGNAL] = {0, };
+
+typedef struct _SyncevoSessionPrivate {
+    DBusGProxy *proxy;
+    char *path;
+} SyncevoSessionPrivate;
+
+#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SYNCEVO_TYPE_SESSION, SyncevoSessionPrivate))
+G_DEFINE_TYPE (SyncevoSession, syncevo_session, G_TYPE_OBJECT);
+
+static SessionAsyncData*
+session_async_data_new (SyncevoSession *session,
+                        GCallback callback,
+                        gpointer userdata)
+{
+    SessionAsyncData *data;
+
+    data = g_slice_new0 (SessionAsyncData);
+    data->session = session;
+    data->callback = G_CALLBACK (callback);
+    data->userdata = userdata;
+
+    return data;
+}
+
+static void
+session_async_data_free (SessionAsyncData *data)
+{
+    g_slice_free (SessionAsyncData, data);
+}
+
+static void
+status_changed_cb (DBusGProxy *proxy,
+                   char *status,
+                   guint error_code,
+                   SyncevoSourceStatuses *source_statuses,
+                   SyncevoSession *session)
+{
+    g_signal_emit (session, signals[STATUS_CHANGED], 0, 
+                   syncevo_session_status_from_string (status),
+                   error_code,
+                   source_statuses);
+}
+
+static void
+progress_changed_cb (DBusGProxy *proxy,
+                     int progress,
+                     SyncevoSourceProgresses *source_progresses,
+                     SyncevoSession *session)
+{
+    g_signal_emit (session, signals[PROGRESS_CHANGED], 0, 
+                   progress,
+                   source_progresses);
+}
+
+static void
+syncevo_session_get_property (GObject *object, guint property_id,
+                              GValue *value, GParamSpec *pspec)
+{
+    SyncevoSession *session = SYNCEVO_SESSION (object);
+    SyncevoSessionPrivate *priv;
+
+    priv = GET_PRIVATE (session);
+
+    switch (property_id) {
+    case PROP_SESSION_PATH:
+        g_value_set_string (value, priv->path);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    }
+}
+
+static void 
+syncevo_session_set_path (SyncevoSession *session, const char *path)
+{
+    SyncevoSessionPrivate *priv;
+    DBusGConnection *connection;
+    GError *error;
+
+    priv = GET_PRIVATE (session);
+    error = NULL;
+
+    priv->path = g_strdup (path);
+
+    if (!priv->path) {
+        return;
+    }
+
+    connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+    if (connection == NULL) {
+        g_printerr ("Failed to open connection to bus: %s\n",
+                    error->message);
+        g_error_free (error);
+        priv->proxy = NULL;
+        return;
+    }
+
+
+    priv->proxy = dbus_g_proxy_new_for_name (connection,
+                                             SYNCEVO_SESSION_DBUS_SERVICE,
+                                             priv->path,
+                                             SYNCEVO_SESSION_DBUS_INTERFACE);
+    if (priv->proxy == NULL) {
+        g_printerr ("dbus_g_proxy_new_for_name() failed for path '%s'", priv->path);
+        return;
+    }
+
+    dbus_g_proxy_add_signal (priv->proxy, "StatusChanged",
+                             G_TYPE_STRING, G_TYPE_UINT, SYNCEVO_TYPE_SOURCE_STATUSES, G_TYPE_INVALID);
+    dbus_g_proxy_connect_signal (priv->proxy, "StatusChanged",
+                                 G_CALLBACK (status_changed_cb), session, NULL);
+
+    dbus_g_proxy_add_signal (priv->proxy, "ProgressChanged",
+                             G_TYPE_INT, SYNCEVO_TYPE_SOURCE_PROGRESSES, G_TYPE_INVALID);
+    dbus_g_proxy_connect_signal (priv->proxy, "ProgressChanged",
+                                 G_CALLBACK (progress_changed_cb), session, NULL);
+
+}
+
+static void
+syncevo_session_set_property (GObject *object, guint property_id,
+                              const GValue *value, GParamSpec *pspec)
+{
+    SyncevoSession *session = SYNCEVO_SESSION (object);
+
+    switch (property_id) {
+    case PROP_SESSION_PATH:
+        syncevo_session_set_path (session, g_value_get_string (value));
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    }
+}
+
+static void
+dispose (GObject *object)
+{
+    SyncevoSessionPrivate *priv;
+
+    priv = GET_PRIVATE (object);
+
+    if (priv->proxy) {
+        dbus_g_proxy_disconnect_signal (priv->proxy, "ProgressChanged",
+                                        G_CALLBACK (progress_changed_cb),
+                                        object);
+        dbus_g_proxy_disconnect_signal (priv->proxy, "StatusChanged",
+                                        G_CALLBACK (status_changed_cb),
+                                        object);
+
+        /* TODO: need to do this async... */
+        org_syncevolution_Session_detach (priv->proxy, NULL);
+
+        g_object_unref (priv->proxy);
+        priv->proxy = NULL;
+    }
+
+    G_OBJECT_CLASS (syncevo_session_parent_class)->dispose (object);
+}
+
+static void
+syncevo_session_class_init (SyncevoSessionClass *klass)
+{
+    GObjectClass *o_class = (GObjectClass *) klass;
+    GParamSpec *pspec;
+
+    o_class->dispose = dispose;
+    o_class->set_property = syncevo_session_set_property;
+    o_class->get_property = syncevo_session_get_property;
+
+    g_type_class_add_private (klass, sizeof (SyncevoSessionPrivate));
+
+    signals[STATUS_CHANGED] =
+            g_signal_new ("status-changed",
+                          G_TYPE_FROM_CLASS (klass),
+                          G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
+                          G_STRUCT_OFFSET (SyncevoSessionClass, status_changed),
+                          NULL, NULL,
+                          syncevo_marshal_VOID__UINT_UINT_BOXED,
+                          G_TYPE_NONE, 
+                          3, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_POINTER);
+    signals[PROGRESS_CHANGED] =
+            g_signal_new ("progress-changed",
+                          G_TYPE_FROM_CLASS (klass),
+                          G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
+                          G_STRUCT_OFFSET (SyncevoSessionClass, progress_changed),
+                          NULL, NULL,
+                          syncevo_marshal_VOID__INT_BOXED,
+                          G_TYPE_NONE, 
+                          2, G_TYPE_INT, G_TYPE_POINTER);
+
+    pspec = g_param_spec_string ("session-path",
+                                 "Session path",
+                                 "The D-Bus path this Syncevolution session uses",
+                                 NULL,
+                                 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+    g_object_class_install_property (o_class, PROP_SESSION_PATH, pspec);
+}
+
+static void
+syncevo_session_init (SyncevoSession *session)
+{
+    SyncevoSessionPrivate *priv;
+
+    priv = GET_PRIVATE (session);
+
+    /* ProgressChanged */
+    dbus_g_object_register_marshaller (syncevo_marshal_VOID__INT_BOXED,
+                                       G_TYPE_NONE,
+                                       G_TYPE_INT,
+                                       G_TYPE_BOXED,
+                                       G_TYPE_INVALID);
+    /* StatusChanged */
+    dbus_g_object_register_marshaller (syncevo_marshal_VOID__UINT_UINT_BOXED,
+                                       G_TYPE_NONE,
+                                       G_TYPE_STRING,
+                                       G_TYPE_UINT,
+                                       G_TYPE_BOXED,
+                                       G_TYPE_INVALID);
+}
+
+
+
+static void
+generic_callback (DBusGProxy *proxy,
+                  GError *error,
+                  SessionAsyncData *data)
+{
+    if (data->callback) {
+        (*(SyncevoSessionGenericCb)data->callback) (data->session,
+                                                    error,
+                                                    data->userdata);
+    }
+    session_async_data_free (data);
+}
+
+static gboolean
+generic_error (SessionAsyncData *data)
+{
+    GError *error;
+
+    error = g_error_new_literal (g_quark_from_static_string ("syncevo-session"),
+                                 SYNCEVO_SESSION_ERROR_NO_DBUS_OBJECT, 
+                                 "The D-Bus object does not exist");
+    (*(SyncevoSessionGenericCb)data->callback) (data->session,
+                                                error,
+                                                data->userdata);
+    session_async_data_free (data);
+
+    return FALSE;
+}
+
+static void
+get_config_callback (DBusGProxy *proxy,
+                     SyncevoConfig *configuration,
+                     GError *error,
+                     SessionAsyncData *data)
+{
+    if (data->callback) {
+        (*(SyncevoSessionGetConfigCb)data->callback) (data->session,
+                                                      configuration,
+                                                      error,
+                                                      data->userdata);
+    }
+    session_async_data_free (data);
+}
+
+static gboolean
+get_config_error (SessionAsyncData *data)
+{
+    GError *error;
+
+    error = g_error_new_literal (g_quark_from_static_string ("syncevo-session"),
+                                 SYNCEVO_SESSION_ERROR_NO_DBUS_OBJECT, 
+                                 "The D-Bus object does not exist");
+    (*(SyncevoSessionGetConfigCb)data->callback) (data->session,
+                                                  NULL,
+                                                  error,
+                                                  data->userdata);
+    session_async_data_free (data);
+
+    return FALSE;
+}
+
+void
+syncevo_session_get_config (SyncevoSession *session,
+                            gboolean template,
+                            SyncevoSessionGetConfigCb callback,
+                            gpointer userdata)
+{
+    SessionAsyncData *data;
+    SyncevoSessionPrivate *priv;
+
+    priv = GET_PRIVATE (session);
+
+    data = session_async_data_new (session, G_CALLBACK (callback), userdata);
+
+    if (!priv->proxy) {
+        if (callback) {
+            g_idle_add ((GSourceFunc)get_config_error, data);
+        }
+        return;
+    }
+    org_syncevolution_Session_get_config_async
+            (priv->proxy,
+             template,
+             (org_syncevolution_Session_get_config_reply) get_config_callback,
+             data);
+}
+
+void
+syncevo_session_set_config (SyncevoSession *session,
+                            gboolean update,
+                            gboolean temporary,
+                            SyncevoConfig *config,
+                            SyncevoSessionGenericCb callback,
+                            gpointer userdata)
+{
+    SessionAsyncData *data;
+    SyncevoSessionPrivate *priv;
+
+    priv = GET_PRIVATE (session);
+
+    data = session_async_data_new (session, G_CALLBACK (callback), userdata);
+
+    if (!priv->proxy) {
+        if (callback) {
+            g_idle_add ((GSourceFunc)generic_error, data);
+        }
+        return;
+    }
+
+    org_syncevolution_Session_set_config_async
+            (priv->proxy,
+             update,
+             temporary,
+             config,
+             (org_syncevolution_Session_set_config_reply) generic_callback,
+             data);
+}
+
+static void
+get_reports_callback (DBusGProxy *proxy,
+                      SyncevoReports *reports,
+                      GError *error,
+                      SessionAsyncData *data)
+{
+    if (data->callback) {
+        (*(SyncevoSessionGetReportsCb)data->callback) (data->session,
+                                                       reports,
+                                                       error,
+                                                       data->userdata);
+    }
+    session_async_data_free (data);
+}
+
+static gboolean
+get_reports_error (SessionAsyncData *data)
+{
+    GError *error;
+
+    error = g_error_new_literal (g_quark_from_static_string ("syncevo-session"),
+                                 SYNCEVO_SESSION_ERROR_NO_DBUS_OBJECT, 
+                                 "The D-Bus object does not exist");
+    (*(SyncevoSessionGetReportsCb)data->callback) (data->session,
+                                                   NULL,
+                                                   error,
+                                                   data->userdata);
+    session_async_data_free (data);
+
+    return FALSE;
+}
+
+void
+syncevo_session_get_reports (SyncevoSession *session,
+                             guint start,
+                             guint count,
+                             SyncevoSessionGetReportsCb callback,
+                             gpointer userdata)
+{
+    SessionAsyncData *data;
+    SyncevoSessionPrivate *priv;
+
+    priv = GET_PRIVATE (session);
+
+    data = session_async_data_new (session, G_CALLBACK (callback), userdata);
+
+    if (!priv->proxy) {
+        if (callback) {
+            g_idle_add ((GSourceFunc)get_reports_error, data);
+        }
+        return;
+    }
+
+    org_syncevolution_Session_get_reports_async
+            (priv->proxy,
+             start,
+             count,
+             (org_syncevolution_Session_get_reports_reply)get_reports_callback,
+             data);
+}
+
+void
+syncevo_session_sync (SyncevoSession *session,
+                      SyncevoSyncMode mode,
+                      SyncevoSourceModes *source_modes,
+                      SyncevoSessionGenericCb callback,
+                      gpointer userdata)
+{
+    SessionAsyncData *data;
+    SyncevoSessionPrivate *priv;
+
+    priv = GET_PRIVATE (session);
+
+    data = session_async_data_new (session, G_CALLBACK (callback), userdata);
+
+    if (!priv->proxy) {
+        if (callback) {
+            g_idle_add ((GSourceFunc)generic_error, data);
+        }
+        return;
+    }
+
+    org_syncevolution_Session_sync_async
+            (priv->proxy,
+             syncevo_sync_mode_to_string (mode),
+             source_modes,
+             (org_syncevolution_Session_sync_reply) generic_callback,
+             data);
+}
+
+void
+syncevo_session_abort (SyncevoSession *session,
+                       SyncevoSessionGenericCb callback,
+                       gpointer userdata)
+{
+    SessionAsyncData *data;
+    SyncevoSessionPrivate *priv;
+
+    priv = GET_PRIVATE (session);
+
+    data = session_async_data_new (session, G_CALLBACK (callback), userdata);
+
+    if (!priv->proxy) {
+        if (callback) {
+            g_idle_add ((GSourceFunc)generic_error, data);
+        }
+        return;
+    }
+
+    org_syncevolution_Session_abort_async
+            (priv->proxy,
+             (org_syncevolution_Session_abort_reply) generic_callback,
+             data);
+}
+
+void
+syncevo_session_suspend (SyncevoSession *session,
+                         SyncevoSessionGenericCb callback,
+                         gpointer userdata)
+{
+    SessionAsyncData *data;
+    SyncevoSessionPrivate *priv;
+
+    priv = GET_PRIVATE (session);
+
+    data = session_async_data_new (session, G_CALLBACK (callback), userdata);
+
+    if (!priv->proxy) {
+        if (callback) {
+            g_idle_add ((GSourceFunc)generic_error, data);
+        }
+        return;
+    }
+
+    org_syncevolution_Session_suspend_async
+            (priv->proxy,
+             (org_syncevolution_Session_suspend_reply) generic_callback,
+             data);
+}
+
+static void
+get_status_callback (DBusGProxy *proxy,
+                     char *status,
+                     guint error_code,
+                     SyncevoSourceStatuses *sources,
+                     GError *error,
+                     SessionAsyncData *data)
+{
+    if (data->callback) {
+        (*(SyncevoSessionGetStatusCb)data->callback) (data->session,
+                                                      syncevo_session_status_from_string (status),
+                                                      error_code,
+                                                      sources,
+                                                      error,
+                                                      data->userdata);
+    }
+    session_async_data_free (data);
+}
+
+static gboolean
+get_status_error (SessionAsyncData *data)
+{
+    GError *error;
+
+    error = g_error_new_literal (g_quark_from_static_string ("syncevo-session"),
+                                 SYNCEVO_SESSION_ERROR_NO_DBUS_OBJECT, 
+                                 "The D-Bus object does not exist");
+    (*(SyncevoSessionGetStatusCb)data->callback) (data->session,
+                                                  SYNCEVO_STATUS_UNKNOWN,
+                                                  0,
+                                                  NULL,
+                                                  error,
+                                                  data->userdata);
+    session_async_data_free (data);
+
+    return FALSE;
+}
+
+void
+syncevo_session_get_status (SyncevoSession *session,
+                            SyncevoSessionGetStatusCb callback,
+                            gpointer userdata)
+{
+    SessionAsyncData *data;
+    SyncevoSessionPrivate *priv;
+
+    priv = GET_PRIVATE (session);
+
+    data = session_async_data_new (session, G_CALLBACK (callback), userdata);
+
+    if (!priv->proxy) {
+        if (callback) {
+            g_idle_add ((GSourceFunc)get_status_error, data);
+        }
+        return;
+    }
+
+    org_syncevolution_Session_get_status_async
+            (priv->proxy,
+             (org_syncevolution_Session_get_status_reply) get_status_callback,
+             data);
+}
+static void
+get_progress_callback (DBusGProxy *proxy,
+                       int progress,
+                       SyncevoSourceProgresses *source_progresses,
+                       GError *error,
+                       SessionAsyncData *data)
+{
+    if (data->callback) {
+        (*(SyncevoSessionGetProgressCb)data->callback) (data->session,
+                                                        progress,
+                                                        source_progresses,
+                                                        error,
+                                                        data->userdata);
+    }
+    session_async_data_free (data);
+}
+
+static gboolean
+get_progress_error (SessionAsyncData *data)
+{
+    GError *error;
+
+    error = g_error_new_literal (g_quark_from_static_string ("syncevo-session"),
+                                 SYNCEVO_SESSION_ERROR_NO_DBUS_OBJECT, 
+                                 "The D-Bus object does not exist");
+    (*(SyncevoSessionGetProgressCb)data->callback) (data->session,
+                                                    -1,
+                                                    NULL,
+                                                    error,
+                                                    data->userdata);
+    session_async_data_free (data);
+
+    return FALSE;
+}
+
+void
+syncevo_session_get_progress (SyncevoSession *session,
+                              SyncevoSessionGetProgressCb callback,
+                              gpointer userdata)
+{
+    SessionAsyncData *data;
+    SyncevoSessionPrivate *priv;
+
+    priv = GET_PRIVATE (session);
+
+    data = session_async_data_new (session, G_CALLBACK (callback), userdata);
+
+    if (!priv->proxy) {
+        if (callback) {
+            g_idle_add ((GSourceFunc)get_progress_error, data);
+        }
+        return;
+    }
+
+    org_syncevolution_Session_get_progress_async
+            (priv->proxy,
+             (org_syncevolution_Session_get_progress_reply) get_progress_callback,
+             data);
+}
+
+void
+syncevo_session_check_source (SyncevoSession *session,
+                              const char *source,
+                              SyncevoSessionGenericCb callback,
+                              gpointer userdata)
+{
+    SessionAsyncData *data;
+    SyncevoSessionPrivate *priv;
+
+    priv = GET_PRIVATE (session);
+
+    data = session_async_data_new (session, G_CALLBACK (callback), userdata);
+
+    if (!priv->proxy) {
+        if (callback) {
+            g_idle_add ((GSourceFunc)generic_error, data);
+        }
+        return;
+    }
+
+    org_syncevolution_Session_check_source_async
+            (priv->proxy,
+             source,
+             (org_syncevolution_Session_check_source_reply) generic_callback,
+             data);
+}
+
+const char*
+syncevo_session_get_path (SyncevoSession *session)
+{
+    SyncevoSessionPrivate *priv;
+
+    priv = GET_PRIVATE (session);
+    return priv->path;
+}
+
+SyncevoSession*
+syncevo_session_new (const char *path)
+{
+    return g_object_new (SYNCEVO_TYPE_SESSION,
+                         "session-path", path,
+                         NULL);
+}
diff --git a/src/dbus/syncevo-session.h b/src/dbus/syncevo-session.h
new file mode 100644 (file)
index 0000000..1210186
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2009 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) version 3.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301  USA
+ */
+
+#ifndef __SYNCEVO_SESSION_H__
+#define __SYNCEVO_SESSION_H__
+
+#include <glib-object.h>
+#include "syncevo-dbus-types.h"
+
+G_BEGIN_DECLS 
+
+enum SyncevoSessionError{
+    SYNCEVO_SESSION_ERROR_NO_DBUS_OBJECT = 1,
+};
+
+#define SYNCEVO_SESSION_DBUS_SERVICE "org.syncevolution"
+#define SYNCEVO_SESSION_DBUS_INTERFACE "org.syncevolution.Session"
+
+#define SYNCEVO_TYPE_SESSION (syncevo_session_get_type ())
+#define SYNCEVO_SESSION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SYNCEVO_TYPE_SESSION, SyncevoSession))
+#define SYNCEVO_IS_SESSION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SYNCEVO_TYPE_SESSION))
+
+typedef struct _SyncevoSession {
+    GObject parent_object;
+} SyncevoSession;
+
+typedef struct _SyncevoSessionClass {
+    GObjectClass parent_class;
+
+    void (*status_changed) (SyncevoSession *session,
+                            SyncevoSessionStatus status,
+                            guint error_code,
+                            SyncevoSourceStatuses *source_statuses);
+
+    void (*progress_changed) (SyncevoSession *session,
+                              int progress,
+                              SyncevoSourceProgresses *source_progresses);
+
+} SyncevoSessionClass;
+
+GType syncevo_session_get_type (void);
+
+typedef void (*SyncevoSessionGenericCb) (SyncevoSession *session,
+                                         GError *error,
+                                         gpointer userdata);
+
+typedef void (*SyncevoSessionGetConfigCb) (SyncevoSession *session,
+                                           SyncevoConfig *config,
+                                           GError *error,
+                                           gpointer userdata);
+void syncevo_session_get_config (SyncevoSession *session,
+                                 gboolean template,
+                                 SyncevoSessionGetConfigCb callback,
+                                 gpointer userdata);
+
+void syncevo_session_set_config (SyncevoSession *session,
+                                 gboolean update,
+                                 gboolean temporary,
+                                 SyncevoConfig *config,
+                                 SyncevoSessionGenericCb callback,
+                                 gpointer userdata);
+
+typedef void (*SyncevoSessionGetReportsCb) (SyncevoSession *session,
+                                            SyncevoReports *reports,
+                                            GError *error,
+                                            gpointer userdata);
+void syncevo_session_get_reports (SyncevoSession *session,
+                                  guint start,
+                                  guint count,
+                                  SyncevoSessionGetReportsCb callback,
+                                  gpointer userdata);
+
+void syncevo_session_sync (SyncevoSession *session,
+                           SyncevoSyncMode mode,
+                           SyncevoSourceModes *source_modes,
+                           SyncevoSessionGenericCb callback,
+                           gpointer userdata);
+
+void syncevo_session_abort (SyncevoSession *session,
+                            SyncevoSessionGenericCb callback,
+                            gpointer userdata);
+
+void syncevo_session_suspend (SyncevoSession *session,
+                              SyncevoSessionGenericCb callback,
+                              gpointer userdata);
+
+typedef void (*SyncevoSessionGetStatusCb) (SyncevoSession *session,
+                                           SyncevoSessionStatus status,
+                                           guint error_code,
+                                           SyncevoSourceStatuses *source_statuses,
+                                           GError *error,
+                                           gpointer userdata);
+void syncevo_session_get_status (SyncevoSession *session,
+                                 SyncevoSessionGetStatusCb callback,
+                                 gpointer userdata);
+
+typedef void (*SyncevoSessionGetProgressCb) (SyncevoSession *session,
+                                             guint progress,
+                                             SyncevoSourceProgresses *source_progresses,
+                                             GError *error,
+                                             gpointer userdata);
+void syncevo_session_get_progress (SyncevoSession *session,
+                                   SyncevoSessionGetProgressCb callback,
+                                   gpointer userdata);
+
+void syncevo_session_check_source (SyncevoSession *session,
+                                   const char *source,
+                                   SyncevoSessionGenericCb callback,
+                                   gpointer userdata);
+
+const char *syncevo_session_get_path (SyncevoSession *session);
+
+SyncevoSession *syncevo_session_new (const char *path);
+
+G_END_DECLS
+
+#endif
index 316eb48..128db31 100644 (file)
  * 02110-1301  USA
  */
 
-/* test syncevo dbus */
+/* test syncevo dbus client wrappers */
 
-#include "syncevo-dbus.h"
+#include "syncevo-server.h"
 
 #include <synthesis/syerror.h>
 #include <synthesis/engine_defs.h>
 
-static void
-print_option (SyncevoOption *option, gpointer userdata)
-{
-       const char *ns, *key, *value;
-
-       syncevo_option_get (option, &ns, &key, &value);
-       g_debug ("  Got option [%s] %s = %s", ns, key, value);
-}
-
-static void
-print_server (SyncevoServer *temp, gpointer userdata)
-{
-       const char *name, *url, *icon;
-       gboolean ready;
-
-       syncevo_server_get (temp, &name, &url, &icon, &ready);
-       g_debug ("  Got server %s (%s, %s, %sconsumer ready)",
-                name, url, icon,
-                ready ? "" : "non-");
-}
+gboolean stop = FALSE;
+GMainLoop *loop;
 
+/*
+// This is the old progress callback, here for future reference...
 static void
 progress_cb (SyncevoService *service,
              char *server,
@@ -138,67 +122,192 @@ progress_cb (SyncevoService *service,
     }
 }
 
-int main (int argc, char *argv[])
-{
-    SyncevoService *service;
-    GMainLoop *loop;
-    GPtrArray *sources;
-    GError *error = NULL;
-    GPtrArray *array;
-    char *server = NULL;
+*/
 
-    g_type_init();
+static void
+get_template_configs_cb(SyncevoServer *server,
+               char **config_names,
+               GError *error,
+               gpointer userdata)
+{
+    char **name;
+    
+    if (error) {
+        g_printerr ("GetConfigs error: %s", error->message);
+        g_error_free (error);
+        return;
+    }
+    g_print ("GetConfigs (template=TRUE):\n");
 
-    if (argc > 1) {
-        server = argv[1];
+    for (name = config_names; name && *name; name++) {
+        g_print ("\t%s\n", *name);
     }
+    g_print ("\n");
+}
 
-    service = syncevo_service_get_default ();
+static void
+print_config_value (char *key, char *value, gpointer data)
+{
+    g_print ("\t\t%s = %s\n", key, value);
+}
+static void
+print_config (char *key, GHashTable *sourceconfig, gpointer data)
+{
+    g_print ("\tsource = %s\n", key);
+    g_hash_table_foreach (sourceconfig, (GHFunc)print_config_value, NULL);
+}
 
-    array = g_ptr_array_new();
-    g_print ("Testing syncevo_service_get_servers()\n");
-    syncevo_service_get_servers (service, &array, &error);
+static void
+get_config_cb (SyncevoSession *session,
+               SyncevoConfig *config,
+               GError *error,
+               gpointer userdata)
+{
     if (error) {
-        g_error ("  syncevo_service_get_servers() failed with %s", error->message);
+        g_printerr ("GetConfig error: %s\n", error->message);
+        g_error_free (error);
+        return;
     }
-    g_ptr_array_foreach (array, (GFunc)print_server, NULL);
 
-    array = g_ptr_array_new();
-    g_print ("Testing syncevo_service_get_templates()\n");
-    syncevo_service_get_templates (service, &array, &error);
-    if (error) {
-        g_error ("  syncevo_service_get_templates() failed with %s", error->message);
-    }
-    g_ptr_array_foreach (array, (GFunc)print_server, NULL);
-    
+    g_print ("Session configuration:\n");
+    g_hash_table_foreach (config, (GHFunc)print_config, NULL);
+}
 
-    if (!server) {
-        g_print ("No server given, stopping here\n");
-        return 0;
+static void
+progress_cb (SyncevoSession *session,
+             int progress,
+             SyncevoSourceProgresses *source_progresses)
+{
+    g_print ("\tprogress = %d\n", progress);
+}
+
+static void
+status_cb (SyncevoSession *session,
+           SyncevoSessionStatus status,
+           guint error_code,
+           SyncevoSourceStatuses *source_statuses,
+           gpointer *data)
+{
+    if (status == SYNCEVO_STATUS_DONE) {
+        g_print ("Session done.");
+        g_object_unref (session);
+        g_main_loop_quit (loop);
     }
+}
 
+static void
+start_session_cb (SyncevoServer *server,
+                  char *path,
+                  GError *error,
+                  gpointer userdata)
+{
+    GHashTable *source_modes;
+    SyncevoSession *session;
 
-    array = g_ptr_array_new();
-    g_print ("Testing syncevo_service_get_config() with server %s\n", server);
-    syncevo_service_get_server_config (service, server, &array, &error);
     if (error) {
-        g_error ("  syncevo_service_get_server_config() failed with %s", error->message);
+        g_printerr ("StartSession error: %s\n", error->message);
+        g_error_free (error);
+        return;
     }
-    g_ptr_array_foreach (array, (GFunc)print_option, NULL);
 
-    loop = g_main_loop_new (NULL, TRUE);
-    g_signal_connect (service, "progress", (GCallback)progress_cb, loop);
-    
-    g_print ("Testing syncevo_service_start_sync() with server %s\n", server);
-    sources = g_ptr_array_new (); /*empty*/
-    syncevo_service_start_sync (service, 
-                                server,
-                                sources,
-                                &error);
+    g_print ("\nTesting Session...\n\n");
+
+    session = syncevo_session_new (path);
+    syncevo_session_get_config (session,
+                                FALSE,
+                                (SyncevoSessionGetConfigCb)get_config_cb,
+                                NULL);
+
+    g_signal_connect (session, "progress-changed",
+                      G_CALLBACK (progress_cb), NULL);
+    g_signal_connect (session, "status-changed",
+                      G_CALLBACK (status_cb), NULL);
+
+
+    /* TODO should wait for session status == idle */
+    source_modes = g_hash_table_new (g_str_hash, g_str_equal);
+    syncevo_session_sync (session, 
+                          SYNCEVO_SYNC_DEFAULT,
+                          source_modes,
+                          NULL,
+                          NULL);
+    g_hash_table_unref (source_modes);
+}
+
+
+static void
+get_configs_cb(SyncevoServer *server,
+               char **config_names,
+               GError *error,
+               char *service_name)
+{
+    char **name;
+
     if (error) {
-        g_error ("  syncevo_service_start_sync() failed with %s", error->message);
+        g_printerr ("GetConfigs error: %s\n", error->message);
+        g_error_free (error);
+        return;
+    }
+    g_print ("GetConfigs (template=FALSE):\n");
+
+    for (name = config_names; name && *name; name++){
+        g_print ("\t%s\n", *name);
+    }
+    g_print ("\n");
+
+    if (stop) {
+        g_print ("No server given, stopping here.\n");
+        g_main_loop_quit (loop);
     }
+}
+
+static void 
+session_changed_cb (SyncevoServer *server,
+                    char *path,
+                    gboolean active,
+                    gpointer data) 
+{
+    g_print ("Session %s is now %s\n",
+             path,
+             active ? "active" : "not active");
+}
+
+int main (int argc, char *argv[])
+{
+    SyncevoServer *server;
+    char *service = NULL;
+
+    g_type_init();
 
+
+    g_print ("Testing Server...\n");
+
+    server = syncevo_server_get_default ();
+
+    syncevo_server_get_configs (server,
+                                TRUE,
+                                (SyncevoServerGetConfigsCb)get_template_configs_cb,
+                                NULL);
+    syncevo_server_get_configs (server,
+                                FALSE,
+                                (SyncevoServerGetConfigsCb)get_configs_cb,
+                                NULL);
+    g_signal_connect (server, "session-changed",
+                      G_CALLBACK (session_changed_cb), NULL);
+
+    if (argc < 2) {
+        stop = TRUE;
+    }
+
+    service = argv[1];
+    if (service)
+        syncevo_server_start_session (server,
+                                      service,
+                                      (SyncevoServerStartSessionCb)start_session_cb,
+                                      NULL);
+
+
+    loop = g_main_loop_new (NULL, TRUE);
     g_main_loop_run (loop);
 
     return 0;
diff --git a/src/gdbus/Makefile.am b/src/gdbus/Makefile.am
new file mode 100644 (file)
index 0000000..09a618d
--- /dev/null
@@ -0,0 +1,22 @@
+include_HEADERS = gdbus.h
+
+if ENABLE_MODULES
+pkglib_LTLIBRARIES = libgdbus.la
+else
+noinst_LTLIBRARIES = libgdbus.la
+endif
+
+libgdbus_la_SOURCES = debug.h debug.c mainloop.c object.c watch.c
+libgdbus_la_LDFLAGS = -version-info 0:0:0 -export-symbols-regex g_dbus_.*
+
+libgdbus_la_LIBADD = @GLIB_LIBS@ @DBUS_LIBS@
+
+AM_CFLAGS = @GLIB_CFLAGS@ @DBUS_CFLAGS@
+
+MAINTAINERCLEANFILES = Makefile.in
+
+include_HEADERS += gdbus-cxx-bridge.h gdbus-cxx.h
+noinst_PROGRAMS = example
+example_SOURCES = test/example.cpp
+example_CXXFLAGS = @GLIB_CFLAGS@ @DBUS_CFLAGS@
+example_LDADD = libgdbus.la @GLIB_LIBS@ @DBUS_LIBS@
similarity index 65%
rename from src/backends/maemo/Makefile.in
rename to src/gdbus/Makefile.in
index 3b2168c..bb47ac2 100644 (file)
@@ -14,6 +14,8 @@
 
 @SET_MAKE@
 
+
+
 VPATH = @srcdir@
 pkgdatadir = $(datadir)/@PACKAGE@
 pkglibdir = $(libdir)/@PACKAGE@
@@ -32,8 +34,10 @@ PRE_UNINSTALL = :
 POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
-subdir = src/backends/maemo
-DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+noinst_PROGRAMS = example$(EXEEXT)
+subdir = src/gdbus
+DIST_COMMON = README $(include_HEADERS) $(srcdir)/Makefile.am \
+       $(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/m4-repo/ax_boost_base.m4 \
        $(top_srcdir)/m4/intltool.m4 $(top_srcdir)/configure.in
@@ -48,32 +52,27 @@ am__vpath_adj = case $$p in \
     *) f=$$p;; \
   esac;
 am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
-am__installdirs = "$(DESTDIR)$(backenddir)"
-backendLTLIBRARIES_INSTALL = $(INSTALL)
-LTLIBRARIES = $(backend_LTLIBRARIES) $(noinst_LTLIBRARIES)
-am__DEPENDENCIES_1 =
-syncmaemocal_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
-am__objects_1 = syncmaemocal_la-MaemoCalendarSource.lo
-am_syncmaemocal_la_OBJECTS = $(am__objects_1)
-syncmaemocal_la_OBJECTS = $(am_syncmaemocal_la_OBJECTS)
-syncmaemocal_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
-       $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
-       $(syncmaemocal_la_CXXFLAGS) $(CXXFLAGS) \
-       $(syncmaemocal_la_LDFLAGS) $(LDFLAGS) -o $@
-@ENABLE_MODULES_FALSE@am_syncmaemocal_la_rpath =
-@ENABLE_MODULES_TRUE@am_syncmaemocal_la_rpath = -rpath $(backenddir)
+am__installdirs = "$(DESTDIR)$(pkglibdir)" "$(DESTDIR)$(includedir)"
+pkglibLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(pkglib_LTLIBRARIES)
+libgdbus_la_DEPENDENCIES =
+am_libgdbus_la_OBJECTS = debug.lo mainloop.lo object.lo watch.lo
+libgdbus_la_OBJECTS = $(am_libgdbus_la_OBJECTS)
+libgdbus_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(libgdbus_la_LDFLAGS) $(LDFLAGS) -o $@
+@ENABLE_MODULES_FALSE@am_libgdbus_la_rpath =
+@ENABLE_MODULES_TRUE@am_libgdbus_la_rpath = -rpath $(pkglibdir)
+PROGRAMS = $(noinst_PROGRAMS)
+am_example_OBJECTS = example-example.$(OBJEXT)
+example_OBJECTS = $(am_example_OBJECTS)
+example_DEPENDENCIES = libgdbus.la
+example_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+       --mode=link $(CXXLD) $(example_CXXFLAGS) $(CXXFLAGS) \
+       $(AM_LDFLAGS) $(LDFLAGS) -o $@
 DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
 depcomp = $(SHELL) $(top_srcdir)/depcomp
 am__depfiles_maybe = depfiles
-CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
-       $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
-LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
-       --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
-       $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
-CXXLD = $(CXX)
-CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
-       --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
-       $(LDFLAGS) -o $@
 COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
        $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
 LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
@@ -83,8 +82,19 @@ CCLD = $(CC)
 LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
        --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
        $(LDFLAGS) -o $@
-SOURCES = $(syncmaemocal_la_SOURCES)
-DIST_SOURCES = $(syncmaemocal_la_SOURCES)
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+       $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+       --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+       $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+       --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
+       $(LDFLAGS) -o $@
+SOURCES = $(libgdbus_la_SOURCES) $(example_SOURCES)
+DIST_SOURCES = $(libgdbus_la_SOURCES) $(example_SOURCES)
+includeHEADERS_INSTALL = $(INSTALL_HEADER)
+HEADERS = $(include_HEADERS)
 ETAGS = etags
 CTAGS = ctags
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -100,6 +110,8 @@ AUTOMAKE = @AUTOMAKE@
 AWK = @AWK@
 BACKEND_CPPFLAGS = @BACKEND_CPPFLAGS@
 BACKEND_DEFINES = @BACKEND_DEFINES@
+BLUEZ_CFLAGS = @BLUEZ_CFLAGS@
+BLUEZ_LIBS = @BLUEZ_LIBS@
 BOOST_CPPFLAGS = @BOOST_CPPFLAGS@
 BOOST_LDFLAGS = @BOOST_LDFLAGS@
 CATALOGS = @CATALOGS@
@@ -107,7 +119,6 @@ CATOBJEXT = @CATOBJEXT@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
-CLEAN_CLIENT_SRC = @CLEAN_CLIENT_SRC@
 CORE_LDADD_DEP = @CORE_LDADD_DEP@
 CPP = @CPP@
 CPPFLAGS = @CPPFLAGS@
@@ -120,8 +131,10 @@ CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
 DATADIRNAME = @DATADIRNAME@
 DBUS_BINDING_TOOL = @DBUS_BINDING_TOOL@
+DBUS_CFLAGS = @DBUS_CFLAGS@
 DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@
 DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@
+DBUS_LIBS = @DBUS_LIBS@
 DBUS_SERVICES_DIR = @DBUS_SERVICES_DIR@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
@@ -148,11 +161,7 @@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
 GLIB_LIBS = @GLIB_LIBS@
 GMOFILES = @GMOFILES@
 GMSGFMT = @GMSGFMT@
-GOBJECT_CFLAGS = @GOBJECT_CFLAGS@
-GOBJECT_LIBS = @GOBJECT_LIBS@
 GREP = @GREP@
-GTHREAD_CFLAGS = @GTHREAD_CFLAGS@
-GTHREAD_LIBS = @GTHREAD_LIBS@
 GTK_BUILDER_CONV = @GTK_BUILDER_CONV@
 GUI_CFLAGS = @GUI_CFLAGS@
 GUI_DESKTOP_FILES = @GUI_DESKTOP_FILES@
@@ -176,6 +185,8 @@ KEYRING_LIBS = @KEYRING_LIBS@
 LDFLAGS = @LDFLAGS@
 LIBEXECDIR = @LIBEXECDIR@
 LIBOBJS = @LIBOBJS@
+LIBOPENOBEX_CFLAGS = @LIBOPENOBEX_CFLAGS@
+LIBOPENOBEX_LIBS = @LIBOPENOBEX_LIBS@
 LIBS = @LIBS@
 LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@
 LIBSOUP_LIBS = @LIBSOUP_LIBS@
@@ -183,8 +194,6 @@ LIBTOOL = @LIBTOOL@
 LN_S = @LN_S@
 LTLIBOBJS = @LTLIBOBJS@
 MAKEINFO = @MAKEINFO@
-MCALB_CFLAGS = @MCALB_CFLAGS@
-MCALB_LIBS = @MCALB_LIBS@
 MKDIR_P = @MKDIR_P@
 MKINSTALLDIRS = @MKINSTALLDIRS@
 MODIFY_SYNCCOMPARE = @MODIFY_SYNCCOMPARE@
@@ -215,11 +224,12 @@ STRIP = @STRIP@
 SYNCEVOLUTION_CXXFLAGS = @SYNCEVOLUTION_CXXFLAGS@
 SYNCEVOLUTION_LDADD = @SYNCEVOLUTION_LDADD@
 SYNCEVOLUTION_LOCALEDIR = @SYNCEVOLUTION_LOCALEDIR@
-SYNCSOURCES = syncmaemocal.la
+SYNCSOURCES = @SYNCSOURCES@
 SYNTHESIS = @SYNTHESIS@
 SYNTHESISSRC = @SYNTHESISSRC@
 SYNTHESIS_CFLAGS = @SYNTHESIS_CFLAGS@
 SYNTHESIS_DEP = @SYNTHESIS_DEP@
+SYNTHESIS_ENGINE = @SYNTHESIS_ENGINE@
 SYNTHESIS_LIB = @SYNTHESIS_LIB@
 SYNTHESIS_LIBS = @SYNTHESIS_LIBS@
 SYNTHESIS_SRC = @SYNTHESIS_SRC@
@@ -231,8 +241,6 @@ UNIQUE_LIBS = @UNIQUE_LIBS@
 USE_NLS = @USE_NLS@
 VERSION = @VERSION@
 XGETTEXT = @XGETTEXT@
-XMLRPC_CFLAGS = @XMLRPC_CFLAGS@
-XMLRPC_LIBS = @XMLRPC_LIBS@
 XSLT = @XSLT@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
@@ -287,24 +295,21 @@ sysconfdir = @sysconfdir@
 target_alias = @target_alias@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
-AM_CPPFLAGS = -I$(srcdir)/../../ -I$(top_srcdir)/test $(BACKEND_CPPFLAGS)
-EXTRA_DIST = configure-sub.in
-MOSTLYCLEANFILES = $(SYNCSOURCES)
-@ENABLE_MODULES_TRUE@backend_LTLIBRARIES = $(SYNCSOURCES)
-@ENABLE_MODULES_FALSE@noinst_LTLIBRARIES = $(SYNCSOURCES)
+include_HEADERS = gdbus.h gdbus-cxx-bridge.h gdbus-cxx.h
+@ENABLE_MODULES_TRUE@pkglib_LTLIBRARIES = libgdbus.la
+@ENABLE_MODULES_FALSE@noinst_LTLIBRARIES = libgdbus.la
+libgdbus_la_SOURCES = debug.h debug.c mainloop.c object.c watch.c
+libgdbus_la_LDFLAGS = -version-info 0:0:0 -export-symbols-regex g_dbus_.*
+libgdbus_la_LIBADD = @GLIB_LIBS@ @DBUS_LIBS@
+AM_CFLAGS = @GLIB_CFLAGS@ @DBUS_CFLAGS@
 MAINTAINERCLEANFILES = Makefile.in
-SYNCMAEMOCAL_SOURCES = \
-       MaemoCalendarSource.h \
-       MaemoCalendarSource.cpp
-
-syncmaemocal_la_SOURCES = $(SYNCMAEMOCAL_SOURCES)
-syncmaemocal_la_LIBADD = $(MCALB_LIBS)
-syncmaemocal_la_LDFLAGS = -module -avoid-version
-syncmaemocal_la_CXXFLAGS = $(SYNCEVOLUTION_CXXFLAGS)
+example_SOURCES = test/example.cpp
+example_CXXFLAGS = @GLIB_CFLAGS@ @DBUS_CFLAGS@
+example_LDADD = libgdbus.la @GLIB_LIBS@ @DBUS_LIBS@
 all: all-am
 
 .SUFFIXES:
-.SUFFIXES: .cpp .lo .o .obj
+.SUFFIXES: .c .cpp .lo .o .obj
 $(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
        @for dep in $?; do \
          case '$(am__configure_deps)' in \
@@ -314,9 +319,9 @@ $(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
              exit 1;; \
          esac; \
        done; \
-       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu  src/backends/maemo/Makefile'; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu  src/gdbus/Makefile'; \
        cd $(top_srcdir) && \
-         $(AUTOMAKE) --gnu  src/backends/maemo/Makefile
+         $(AUTOMAKE) --gnu  src/gdbus/Makefile
 .PRECIOUS: Makefile
 Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
        @case '$?' in \
@@ -334,44 +339,54 @@ $(top_srcdir)/configure:  $(am__configure_deps)
        cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
 $(ACLOCAL_M4):  $(am__aclocal_m4_deps)
        cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-install-backendLTLIBRARIES: $(backend_LTLIBRARIES)
+
+clean-noinstLTLIBRARIES:
+       -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+       @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+         dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+         test "$$dir" != "$$p" || dir=.; \
+         echo "rm -f \"$${dir}/so_locations\""; \
+         rm -f "$${dir}/so_locations"; \
+       done
+install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES)
        @$(NORMAL_INSTALL)
-       test -z "$(backenddir)" || $(MKDIR_P) "$(DESTDIR)$(backenddir)"
-       @list='$(backend_LTLIBRARIES)'; for p in $$list; do \
+       test -z "$(pkglibdir)" || $(MKDIR_P) "$(DESTDIR)$(pkglibdir)"
+       @list='$(pkglib_LTLIBRARIES)'; for p in $$list; do \
          if test -f $$p; then \
            f=$(am__strip_dir) \
-           echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(backendLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(backenddir)/$$f'"; \
-           $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(backendLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(backenddir)/$$f"; \
+           echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pkglibLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(pkglibdir)/$$f'"; \
+           $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pkglibLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(pkglibdir)/$$f"; \
          else :; fi; \
        done
 
-uninstall-backendLTLIBRARIES:
+uninstall-pkglibLTLIBRARIES:
        @$(NORMAL_UNINSTALL)
-       @list='$(backend_LTLIBRARIES)'; for p in $$list; do \
+       @list='$(pkglib_LTLIBRARIES)'; for p in $$list; do \
          p=$(am__strip_dir) \
-         echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(backenddir)/$$p'"; \
-         $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(backenddir)/$$p"; \
+         echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$p'"; \
+         $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$p"; \
        done
 
-clean-backendLTLIBRARIES:
-       -test -z "$(backend_LTLIBRARIES)" || rm -f $(backend_LTLIBRARIES)
-       @list='$(backend_LTLIBRARIES)'; for p in $$list; do \
+clean-pkglibLTLIBRARIES:
+       -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES)
+       @list='$(pkglib_LTLIBRARIES)'; for p in $$list; do \
          dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
          test "$$dir" != "$$p" || dir=.; \
          echo "rm -f \"$${dir}/so_locations\""; \
          rm -f "$${dir}/so_locations"; \
        done
-
-clean-noinstLTLIBRARIES:
-       -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
-       @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
-         dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
-         test "$$dir" != "$$p" || dir=.; \
-         echo "rm -f \"$${dir}/so_locations\""; \
-         rm -f "$${dir}/so_locations"; \
+libgdbus.la: $(libgdbus_la_OBJECTS) $(libgdbus_la_DEPENDENCIES) 
+       $(libgdbus_la_LINK) $(am_libgdbus_la_rpath) $(libgdbus_la_OBJECTS) $(libgdbus_la_LIBADD) $(LIBS)
+
+clean-noinstPROGRAMS:
+       @list='$(noinst_PROGRAMS)'; for p in $$list; do \
+         f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+         echo " rm -f $$p $$f"; \
+         rm -f $$p $$f ; \
        done
-syncmaemocal.la: $(syncmaemocal_la_OBJECTS) $(syncmaemocal_la_DEPENDENCIES) 
-       $(syncmaemocal_la_LINK) $(am_syncmaemocal_la_rpath) $(syncmaemocal_la_OBJECTS) $(syncmaemocal_la_LIBADD) $(LIBS)
+example$(EXEEXT): $(example_OBJECTS) $(example_DEPENDENCIES) 
+       @rm -f example$(EXEEXT)
+       $(example_LINK) $(example_OBJECTS) $(example_LDADD) $(LIBS)
 
 mostlyclean-compile:
        -rm -f *.$(OBJEXT)
@@ -379,7 +394,32 @@ mostlyclean-compile:
 distclean-compile:
        -rm -f *.tab.c
 
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syncmaemocal_la-MaemoCalendarSource.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/example-example.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mainloop.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/object.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/watch.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@   $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@   $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@   $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LTCOMPILE) -c -o $@ $<
 
 .cpp.o:
 @am__fastdepCXX_TRUE@  $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@@ -402,18 +442,42 @@ distclean-compile:
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $<
 
-syncmaemocal_la-MaemoCalendarSource.lo: MaemoCalendarSource.cpp
-@am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(syncmaemocal_la_CXXFLAGS) $(CXXFLAGS) -MT syncmaemocal_la-MaemoCalendarSource.lo -MD -MP -MF $(DEPDIR)/syncmaemocal_la-MaemoCalendarSource.Tpo -c -o syncmaemocal_la-MaemoCalendarSource.lo `test -f 'MaemoCalendarSource.cpp' || echo '$(srcdir)/'`MaemoCalendarSource.cpp
-@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/syncmaemocal_la-MaemoCalendarSource.Tpo $(DEPDIR)/syncmaemocal_la-MaemoCalendarSource.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='MaemoCalendarSource.cpp' object='syncmaemocal_la-MaemoCalendarSource.lo' libtool=yes @AMDEPBACKSLASH@
+example-example.o: test/example.cpp
+@am__fastdepCXX_TRUE@  $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(example_CXXFLAGS) $(CXXFLAGS) -MT example-example.o -MD -MP -MF $(DEPDIR)/example-example.Tpo -c -o example-example.o `test -f 'test/example.cpp' || echo '$(srcdir)/'`test/example.cpp
+@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/example-example.Tpo $(DEPDIR)/example-example.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='test/example.cpp' object='example-example.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(example_CXXFLAGS) $(CXXFLAGS) -c -o example-example.o `test -f 'test/example.cpp' || echo '$(srcdir)/'`test/example.cpp
+
+example-example.obj: test/example.cpp
+@am__fastdepCXX_TRUE@  $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(example_CXXFLAGS) $(CXXFLAGS) -MT example-example.obj -MD -MP -MF $(DEPDIR)/example-example.Tpo -c -o example-example.obj `if test -f 'test/example.cpp'; then $(CYGPATH_W) 'test/example.cpp'; else $(CYGPATH_W) '$(srcdir)/test/example.cpp'; fi`
+@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/example-example.Tpo $(DEPDIR)/example-example.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='test/example.cpp' object='example-example.obj' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(syncmaemocal_la_CXXFLAGS) $(CXXFLAGS) -c -o syncmaemocal_la-MaemoCalendarSource.lo `test -f 'MaemoCalendarSource.cpp' || echo '$(srcdir)/'`MaemoCalendarSource.cpp
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(example_CXXFLAGS) $(CXXFLAGS) -c -o example-example.obj `if test -f 'test/example.cpp'; then $(CYGPATH_W) 'test/example.cpp'; else $(CYGPATH_W) '$(srcdir)/test/example.cpp'; fi`
 
 mostlyclean-libtool:
        -rm -f *.lo
 
 clean-libtool:
        -rm -rf .libs _libs
+install-includeHEADERS: $(include_HEADERS)
+       @$(NORMAL_INSTALL)
+       test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)"
+       @list='$(include_HEADERS)'; for p in $$list; do \
+         if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+         f=$(am__strip_dir) \
+         echo " $(includeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(includedir)/$$f'"; \
+         $(includeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(includedir)/$$f"; \
+       done
+
+uninstall-includeHEADERS:
+       @$(NORMAL_UNINSTALL)
+       @list='$(include_HEADERS)'; for p in $$list; do \
+         f=$(am__strip_dir) \
+         echo " rm -f '$(DESTDIR)$(includedir)/$$f'"; \
+         rm -f "$(DESTDIR)$(includedir)/$$f"; \
+       done
 
 ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
        list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
@@ -490,9 +554,9 @@ distdir: $(DISTFILES)
        done
 check-am: all-am
 check: check-am
-all-am: Makefile $(LTLIBRARIES)
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS)
 installdirs:
-       for dir in "$(DESTDIR)$(backenddir)"; do \
+       for dir in "$(DESTDIR)$(pkglibdir)" "$(DESTDIR)$(includedir)"; do \
          test -z "$$dir" || $(MKDIR_P) "$$dir"; \
        done
 install: install-am
@@ -510,7 +574,6 @@ install-strip:
          `test -z '$(STRIP)' || \
            echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
 mostlyclean-generic:
-       -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
 
 clean-generic:
 
@@ -523,8 +586,8 @@ maintainer-clean-generic:
        -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
 clean: clean-am
 
-clean-am: clean-backendLTLIBRARIES clean-generic clean-libtool \
-       clean-noinstLTLIBRARIES mostlyclean-am
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+       clean-noinstPROGRAMS clean-pkglibLTLIBRARIES mostlyclean-am
 
 distclean: distclean-am
        -rm -rf ./$(DEPDIR)
@@ -542,11 +605,11 @@ info: info-am
 
 info-am:
 
-install-data-am: install-backendLTLIBRARIES
+install-data-am: install-includeHEADERS
 
 install-dvi: install-dvi-am
 
-install-exec-am:
+install-exec-am: install-pkglibLTLIBRARIES
 
 install-html: install-html-am
 
@@ -578,24 +641,25 @@ ps: ps-am
 
 ps-am:
 
-uninstall-am: uninstall-backendLTLIBRARIES
+uninstall-am: uninstall-includeHEADERS uninstall-pkglibLTLIBRARIES
 
 .MAKE: install-am install-strip
 
-.PHONY: CTAGS GTAGS all all-am check check-am clean \
-       clean-backendLTLIBRARIES clean-generic clean-libtool \
-       clean-noinstLTLIBRARIES ctags distclean distclean-compile \
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+       clean-libtool clean-noinstLTLIBRARIES clean-noinstPROGRAMS \
+       clean-pkglibLTLIBRARIES ctags distclean distclean-compile \
        distclean-generic distclean-libtool distclean-tags distdir dvi \
        dvi-am html html-am info info-am install install-am \
-       install-backendLTLIBRARIES install-data install-data-am \
-       install-dvi install-dvi-am install-exec install-exec-am \
-       install-html install-html-am install-info install-info-am \
-       install-man install-pdf install-pdf-am install-ps \
-       install-ps-am install-strip installcheck installcheck-am \
-       installdirs maintainer-clean maintainer-clean-generic \
-       mostlyclean mostlyclean-compile mostlyclean-generic \
-       mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
-       uninstall-am uninstall-backendLTLIBRARIES
+       install-data install-data-am install-dvi install-dvi-am \
+       install-exec install-exec-am install-html install-html-am \
+       install-includeHEADERS install-info install-info-am \
+       install-man install-pdf install-pdf-am \
+       install-pkglibLTLIBRARIES install-ps install-ps-am \
+       install-strip installcheck installcheck-am installdirs \
+       maintainer-clean maintainer-clean-generic mostlyclean \
+       mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+       pdf pdf-am ps ps-am tags uninstall uninstall-am \
+       uninstall-includeHEADERS uninstall-pkglibLTLIBRARIES
 
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
diff --git a/src/gdbus/README b/src/gdbus/README
new file mode 100644 (file)
index 0000000..542034f
--- /dev/null
@@ -0,0 +1,11 @@
+This is a copy of the libgdbus source code:
+http://git.kernel.org/?p=bluetooth/libgdbus.git;a=summary
+
+It is licensed under LGPL v2.1, see upstream COPYING.
+
+The source is included here because there is no stable
+upstream release. Patches added here need to be submitted
+upstream. Likewise, patches applied upstream must be imported.
+
+The build/import-gdbus.sh script automates that process.
+See build/import-foreign-git.sh for details.
diff --git a/src/gdbus/debug.c b/src/gdbus/debug.c
new file mode 100644 (file)
index 0000000..680370e
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ *
+ *  Library for simple D-Bus integration with GLib
+ *
+ *  Copyright (C) 2007-2008  Intel Corporation. All rights reserved.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License version 2.1 as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "debug.h"
+
+static void __attribute__ ((constructor)) __init(void)
+{
+       DBG("");
+}
+
+static void __attribute__ ((destructor)) __cleanup(void)
+{
+       DBG("");
+}
diff --git a/src/gdbus/debug.h b/src/gdbus/debug.h
new file mode 100644 (file)
index 0000000..65e1b11
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ *
+ *  Library for simple D-Bus integration with GLib
+ *
+ *  Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License version 2.1 as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <glib/gmessages.h>
+
+//#define DBG(fmt, arg...)  g_debug("%s: " fmt, __FUNCTION__ , ## arg)
+#define DBG(fmt, arg...)
diff --git a/src/gdbus/gdbus-cxx-bridge.h b/src/gdbus/gdbus-cxx-bridge.h
new file mode 100644 (file)
index 0000000..d743a02
--- /dev/null
@@ -0,0 +1,3849 @@
+/*
+ * Copyright (C) 2009 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) version 3.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301  USA
+ */
+
+/**
+ * This file contains everything that a D-Bus server needs to
+ * integrate a normal C++ class into D-Bus. Argument and result
+ * marshaling is done in wrapper functions which convert directly
+ * to normal C++ types (bool, integers, std::string, std::map<>, ...).
+ * See dbus_traits for the full list of supported types.
+ *
+ * Before explaining the binding, some terminology first:
+ * - A function has a return type and multiple parameters.
+ * - Input parameters are read-only arguments of the function.
+ * - The function can return values to the caller via the
+ *   return type and output parameters (retvals).
+ *
+ * The C++ binding roughly looks like this:
+ * - Arguments can be passed as plain types or const references:
+     void foo(int arg); void bar(const std::string &str);
+ * - A single result can be returned as return value:
+ *   int foo();
+ * - Multiple results can be copied into instances provided by
+ *   the wrapper, passed by reference: void foo(std::string &res);
+ * - A return value, arguments and retvals can be combined
+ *   arbitrarily. In the D-Bus reply the return code comes before
+ *   all return values.
+ *
+ * Asynchronous methods are possible by declaring one parameter as a
+ * Result pointer and later calling the virtual function provided by
+ * it. Parameter passing of results is less flexible than that of
+ * method parameters: the later allows both std::string as well as
+ * const std::string &, for results only the const reference is
+ * supported. The Result instance is passed as pointer and then owned
+ * by the called method.
+ *
+ * Reference counting via boost::intrusive_ptr ensures that all
+ * D-Bus objects are handled automatically internally.
+ */
+
+
+#ifndef INCL_GDBUS_CXX_BRIDGE
+#define INCL_GDBUS_CXX_BRIDGE
+
+#include "gdbus.h"
+#include "gdbus-cxx.h"
+
+#include <map>
+#include <vector>
+
+#include <boost/bind.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/shared_ptr.hpp>
+
+namespace boost {
+    void intrusive_ptr_add_ref(DBusConnection *con) { dbus_connection_ref(con); }
+    void intrusive_ptr_release(DBusConnection *con) { dbus_connection_unref(con); }
+    void intrusive_ptr_add_ref(DBusMessage *msg) { dbus_message_ref(msg); }
+    void intrusive_ptr_release(DBusMessage *msg) { dbus_message_unref(msg); }
+}
+
+class DBusConnectionPtr : public boost::intrusive_ptr<DBusConnection>
+{
+ public:
+    DBusConnectionPtr() {}
+    // connections are typically created once, so increment the ref counter by default
+    DBusConnectionPtr(DBusConnection *conn, bool add_ref = true) :
+      boost::intrusive_ptr<DBusConnection>(conn, add_ref)
+    {}
+
+    DBusConnection *reference(void) throw()
+    {
+        DBusConnection *conn = get();
+        dbus_connection_ref(conn);
+        return conn;
+    }
+};
+
+class DBusMessagePtr : public boost::intrusive_ptr<DBusMessage>
+{
+ public:
+    DBusMessagePtr() {}
+    // expected to be used for messages created anew,
+    // so use the reference already incremented for us
+    // and don't increment by default
+    DBusMessagePtr(DBusMessage *msg, bool add_ref = false) :
+      boost::intrusive_ptr<DBusMessage>(msg, add_ref)
+    {}
+
+    DBusMessage *reference(void) throw()
+    {
+        DBusMessage *msg = get();
+        dbus_message_ref(msg);
+        return msg;
+    }
+};
+
+/**
+ * wrapper around DBusError which initializes
+ * the struct automatically, then can be used to
+ * throw an exception
+ */
+class DBusErrorCXX : public DBusError
+{
+ public:
+    DBusErrorCXX() { dbus_error_init(this); }
+    void throwFailure(const std::string &operation)
+    {
+        if (dbus_error_is_set(this)) {
+            throw std::runtime_error(operation + ": " + message);
+        } else {
+            throw std::runtime_error(operation + " failed");
+        }
+    }
+
+    operator bool ()
+    {
+        return dbus_error_is_set(this);
+    }
+};
+
+/**
+ * Special type for object paths. A string in practice.
+ */
+class DBusObject_t : public std::string
+{
+ public:
+    DBusObject_t() {}
+    template <class T> DBusObject_t(T val) : std::string(val) {}
+    template <class T> DBusObject_t &operator = (T val) { assign(val); return *this; }
+};
+
+/**
+ * specializations of this must defined methods for encoding and
+ * decoding type C and declare its signature
+ */
+template<class C> struct dbus_traits {};
+
+struct dbus_traits_base
+{
+    /**
+     * A C++ method or function can handle a call asynchronously by
+     * asking to be passed a "boost::shared_ptr<Result*>" parameter.
+     * The dbus_traits for those parameters have "asynchronous" set to
+     * true, which skips all processing after calling the method.
+     */
+    static const bool asynchronous = false;
+};
+
+/**
+ * Append a varying number of parameters as result to the
+ * message. Types can be anything that has a dbus_traits, including
+ * types which are normally recognized as input parameters in D-Bus
+ * method calls.
+ */
+template <class A1, class A2, class A3, class A4, class A5,
+    class A6, class A7, class A8, class A9, class A10>
+void append_retvals(DBusMessagePtr &msg,
+                    A1 a1,
+                    A2 a2,
+                    A3 a3,
+                    A4 a4,
+                    A5 a5,
+                    A6 a6,
+                    A7 a7,
+                    A8 a8,
+                    A9 a9,
+                    A10 a10)
+{
+    DBusMessageIter iter;
+    dbus_message_iter_init_append(msg.get(), &iter);
+    dbus_traits<A1>::append_retval(iter, a1);
+    dbus_traits<A2>::append_retval(iter, a2);
+    dbus_traits<A3>::append_retval(iter, a3);
+    dbus_traits<A4>::append_retval(iter, a4);
+    dbus_traits<A5>::append_retval(iter, a5);
+    dbus_traits<A6>::append_retval(iter, a6);
+    dbus_traits<A7>::append_retval(iter, a7);
+    dbus_traits<A8>::append_retval(iter, a8);
+    dbus_traits<A9>::append_retval(iter, a9);
+    dbus_traits<A10>::append_retval(iter, a10);
+}
+
+template <class A1, class A2, class A3, class A4, class A5,
+    class A6, class A7, class A8, class A9>
+void append_retvals(DBusMessagePtr &msg,
+                    A1 a1,
+                    A2 a2,
+                    A3 a3,
+                    A4 a4,
+                    A5 a5,
+                    A6 a6,
+                    A7 a7,
+                    A8 a8,
+                    A9 a9)
+{
+    DBusMessageIter iter;
+    dbus_message_iter_init_append(msg.get(), &iter);
+    dbus_traits<A1>::append_retval(iter, a1);
+    dbus_traits<A2>::append_retval(iter, a2);
+    dbus_traits<A3>::append_retval(iter, a3);
+    dbus_traits<A4>::append_retval(iter, a4);
+    dbus_traits<A5>::append_retval(iter, a5);
+    dbus_traits<A6>::append_retval(iter, a6);
+    dbus_traits<A7>::append_retval(iter, a7);
+    dbus_traits<A8>::append_retval(iter, a8);
+    dbus_traits<A9>::append_retval(iter, a9);
+}
+
+template <class A1, class A2, class A3, class A4, class A5,
+    class A6, class A7, class A8>
+void append_retvals(DBusMessagePtr &msg,
+                    A1 a1,
+                    A2 a2,
+                    A3 a3,
+                    A4 a4,
+                    A5 a5,
+                    A6 a6,
+                    A7 a7,
+                    A8 a8)
+{
+    DBusMessageIter iter;
+    dbus_message_iter_init_append(msg.get(), &iter);
+    dbus_traits<A1>::append_retval(iter, a1);
+    dbus_traits<A2>::append_retval(iter, a2);
+    dbus_traits<A3>::append_retval(iter, a3);
+    dbus_traits<A4>::append_retval(iter, a4);
+    dbus_traits<A5>::append_retval(iter, a5);
+    dbus_traits<A6>::append_retval(iter, a6);
+    dbus_traits<A7>::append_retval(iter, a7);
+    dbus_traits<A8>::append_retval(iter, a8);
+}
+
+template <class A1, class A2, class A3, class A4, class A5,
+    class A6, class A7>
+void append_retvals(DBusMessagePtr &msg,
+                    A1 a1,
+                    A2 a2,
+                    A3 a3,
+                    A4 a4,
+                    A5 a5,
+                    A6 a6,
+                    A7 a7)
+{
+    DBusMessageIter iter;
+    dbus_message_iter_init_append(msg.get(), &iter);
+    dbus_traits<A1>::append_retval(iter, a1);
+    dbus_traits<A2>::append_retval(iter, a2);
+    dbus_traits<A3>::append_retval(iter, a3);
+    dbus_traits<A4>::append_retval(iter, a4);
+    dbus_traits<A5>::append_retval(iter, a5);
+    dbus_traits<A6>::append_retval(iter, a6);
+    dbus_traits<A7>::append_retval(iter, a7);
+}
+
+template <class A1, class A2, class A3, class A4, class A5,
+    class A6>
+void append_retvals(DBusMessagePtr &msg,
+                    A1 a1,
+                    A2 a2,
+                    A3 a3,
+                    A4 a4,
+                    A5 a5,
+                    A6 a6)
+{
+    DBusMessageIter iter;
+    dbus_message_iter_init_append(msg.get(), &iter);
+    dbus_traits<A1>::append_retval(iter, a1);
+    dbus_traits<A2>::append_retval(iter, a2);
+    dbus_traits<A3>::append_retval(iter, a3);
+    dbus_traits<A4>::append_retval(iter, a4);
+    dbus_traits<A5>::append_retval(iter, a5);
+    dbus_traits<A6>::append_retval(iter, a6);
+}
+
+template <class A1, class A2, class A3, class A4, class A5>
+void append_retvals(DBusMessagePtr &msg,
+                    A1 a1,
+                    A2 a2,
+                    A3 a3,
+                    A4 a4,
+                    A5 a5)
+{
+    DBusMessageIter iter;
+    dbus_message_iter_init_append(msg.get(), &iter);
+    dbus_traits<A1>::append_retval(iter, a1);
+    dbus_traits<A2>::append_retval(iter, a2);
+    dbus_traits<A3>::append_retval(iter, a3);
+    dbus_traits<A4>::append_retval(iter, a4);
+    dbus_traits<A5>::append_retval(iter, a5);
+}
+
+template <class A1, class A2, class A3, class A4>
+void append_retvals(DBusMessagePtr &msg,
+                    A1 a1,
+                    A2 a2,
+                    A3 a3,
+                    A4 a4)
+{
+    DBusMessageIter iter;
+    dbus_message_iter_init_append(msg.get(), &iter);
+    dbus_traits<A1>::append_retval(iter, a1);
+    dbus_traits<A2>::append_retval(iter, a2);
+    dbus_traits<A3>::append_retval(iter, a3);
+    dbus_traits<A4>::append_retval(iter, a4);
+}
+
+template <class A1, class A2, class A3>
+void append_retvals(DBusMessagePtr &msg,
+                    A1 a1,
+                    A2 a2,
+                    A3 a3)
+{
+    DBusMessageIter iter;
+    dbus_message_iter_init_append(msg.get(), &iter);
+    dbus_traits<A1>::append_retval(iter, a1);
+    dbus_traits<A2>::append_retval(iter, a2);
+    dbus_traits<A3>::append_retval(iter, a3);
+}
+
+template <class A1, class A2>
+void append_retvals(DBusMessagePtr &msg,
+                    A1 a1,
+                    A2 a2)
+{
+    DBusMessageIter iter;
+    dbus_message_iter_init_append(msg.get(), &iter);
+    dbus_traits<A1>::append_retval(iter, a1);
+    dbus_traits<A2>::append_retval(iter, a2);
+}
+
+template <class A1>
+void append_retvals(DBusMessagePtr &msg,
+                    A1 a1)
+{
+    DBusMessageIter iter;
+    dbus_message_iter_init_append(msg.get(), &iter);
+    dbus_traits<A1>::append_retval(iter, a1);
+}
+
+/**
+ * interface expected by EmitSignal
+ */
+class DBusObject
+{
+ public:
+    virtual ~DBusObject() {}
+
+    virtual DBusConnection *getConnection() const = 0;
+    virtual const char *getPath() const = 0;
+    virtual const char *getInterface() const = 0;
+};
+
+class EmitSignal0
+{
+    const DBusObject &m_object;
+    const std::string m_signal;
+
+ public:
+    EmitSignal0(const DBusObject &object,
+                const std::string &signal) :
+        m_object(object),
+        m_signal(signal)
+    {}
+
+    void operator () ()
+    {
+        DBusMessagePtr msg(dbus_message_new_signal(m_object.getPath(),
+                                                   m_object.getInterface(),
+                                                   m_signal.c_str()));
+        if (!msg) {
+            throw std::runtime_error("dbus_message_new_signal() failed");
+        }
+
+        if (!dbus_connection_send(m_object.getConnection(), msg.get(), NULL)) {
+            throw std::runtime_error("dbus_connection_send failed");
+        }
+    }
+
+    GDBusSignalTable makeSignalEntry(GDBusSignalFlags flags = G_DBUS_SIGNAL_FLAG_NONE) const
+    {
+        GDBusSignalTable entry;
+        entry.name = m_signal.c_str();
+        std::string buffer;
+        entry.signature = strdup(buffer.c_str());
+        entry.flags = flags;
+        return entry;
+    }
+};
+
+template <typename A1>
+class EmitSignal1
+{
+    const DBusObject &m_object;
+    const std::string m_signal;
+
+ public:
+    EmitSignal1(const DBusObject &object,
+                const std::string &signal) :
+        m_object(object),
+        m_signal(signal)
+    {}
+
+    void operator () (A1 a1)
+    {
+        DBusMessagePtr msg(dbus_message_new_signal(m_object.getPath(),
+                                                   m_object.getInterface(),
+                                                   m_signal.c_str()));
+        if (!msg) {
+            throw std::runtime_error("dbus_message_new_signal() failed");
+        }
+        append_retvals(msg, a1);
+
+        if (!dbus_connection_send(m_object.getConnection(), msg.get(), NULL)) {
+            throw std::runtime_error("dbus_connection_send failed");
+        }
+    }
+
+    GDBusSignalTable makeSignalEntry(GDBusSignalFlags flags = G_DBUS_SIGNAL_FLAG_NONE) const
+    {
+        GDBusSignalTable entry;
+        entry.name = m_signal.c_str();
+        std::string buffer;
+        buffer += dbus_traits<A1>::getSignature();
+        entry.signature = strdup(buffer.c_str());
+        entry.flags = flags;
+        return entry;
+    }
+};
+
+template <typename A1, typename A2>
+class EmitSignal2
+{
+    const DBusObject &m_object;
+    const std::string m_signal;
+
+ public:
+    EmitSignal2(const DBusObject &object,
+                const std::string &signal) :
+        m_object(object),
+        m_signal(signal)
+    {}
+
+    void operator () (A1 a1, A2 a2)
+    {
+        DBusMessagePtr msg(dbus_message_new_signal(m_object.getPath(),
+                                                   m_object.getInterface(),
+                                                   m_signal.c_str()));
+        if (!msg) {
+            throw std::runtime_error("dbus_message_new_signal() failed");
+        }
+        append_retvals(msg, a1, a2);
+
+        if (!dbus_connection_send(m_object.getConnection(), msg.get(), NULL)) {
+            throw std::runtime_error("dbus_connection_send failed");
+        }
+    }
+
+    GDBusSignalTable makeSignalEntry(GDBusSignalFlags flags = G_DBUS_SIGNAL_FLAG_NONE) const
+    {
+        GDBusSignalTable entry;
+        entry.name = m_signal.c_str();
+        std::string buffer;
+        buffer += dbus_traits<A1>::getSignature();
+        buffer += dbus_traits<A2>::getSignature();
+        entry.signature = strdup(buffer.c_str());
+        entry.flags = flags;
+        return entry;
+    }
+};
+
+template <typename A1, typename A2, typename A3>
+class EmitSignal3
+{
+    const DBusObject &m_object;
+    const std::string m_signal;
+
+ public:
+    EmitSignal3(const DBusObject &object,
+                const std::string &signal) :
+        m_object(object),
+        m_signal(signal)
+    {}
+
+    void operator () (A1 a1, A2 a2, A3 a3)
+    {
+        DBusMessagePtr msg(dbus_message_new_signal(m_object.getPath(),
+                                                   m_object.getInterface(),
+                                                   m_signal.c_str()));
+        if (!msg) {
+            throw std::runtime_error("dbus_message_new_signal() failed");
+        }
+        append_retvals(msg, a1, a2, a3);
+        if (!dbus_connection_send(m_object.getConnection(), msg.get(), NULL)) {
+            throw std::runtime_error("dbus_connection_send failed");
+        }
+    }
+
+    GDBusSignalTable makeSignalEntry(GDBusSignalFlags flags = G_DBUS_SIGNAL_FLAG_NONE) const
+    {
+        GDBusSignalTable entry;
+        entry.name = m_signal.c_str();
+        std::string buffer;
+        buffer += dbus_traits<A1>::getSignature();
+        buffer += dbus_traits<A2>::getSignature();
+        buffer += dbus_traits<A3>::getSignature();
+        entry.signature = strdup(buffer.c_str());
+        entry.flags = flags;
+        return entry;
+    }
+};
+
+template <typename A1, typename A2, typename A3, typename A4>
+class EmitSignal4
+{
+    const DBusObject &m_object;
+    const std::string m_signal;
+
+ public:
+    EmitSignal4(const DBusObject &object,
+                const std::string &signal) :
+        m_object(object),
+        m_signal(signal)
+    {}
+
+    void operator () (A1 a1, A2 a2, A3 a3, A4 a4)
+    {
+        DBusMessagePtr msg(dbus_message_new_signal(m_object.getPath(),
+                                                   m_object.getInterface(),
+                                                   m_signal.c_str()));
+        if (!msg) {
+            throw std::runtime_error("dbus_message_new_signal() failed");
+        }
+        append_retvals(msg, a1, a2, a3, a4);
+        if (!dbus_connection_send(m_object.getConnection(), msg.get(), NULL)) {
+            throw std::runtime_error("dbus_connection_send failed");
+        }
+    }
+
+    GDBusSignalTable makeSignalEntry(GDBusSignalFlags flags = G_DBUS_SIGNAL_FLAG_NONE) const
+    {
+        GDBusSignalTable entry;
+        entry.name = m_signal.c_str();
+        std::string buffer;
+        buffer += dbus_traits<A1>::getSignature();
+        buffer += dbus_traits<A2>::getSignature();
+        buffer += dbus_traits<A3>::getSignature();
+        buffer += dbus_traits<A4>::getSignature();
+        entry.signature = strdup(buffer.c_str());
+        entry.flags = flags;
+        return entry;
+    }
+};
+
+template <typename A1, typename A2, typename A3, typename A4, typename A5>
+class EmitSignal5
+{
+    const DBusObject &m_object;
+    const std::string m_signal;
+
+ public:
+    EmitSignal5(const DBusObject &object,
+                const std::string &signal) :
+        m_object(object),
+        m_signal(signal)
+    {}
+
+    void operator () (A1 a1, A2 a2, A3 a3, A4 a4, A5 a5)
+    {
+        DBusMessagePtr msg(dbus_message_new_signal(m_object.getPath(),
+                                                   m_object.getInterface(),
+                                                   m_signal.c_str()));
+        if (!msg) {
+            throw std::runtime_error("dbus_message_new_signal() failed");
+        }
+        append_retvals(msg, a1, a2, a3, a4, a5);
+        if (!dbus_connection_send(m_object.getConnection(), msg.get(), NULL)) {
+            throw std::runtime_error("dbus_connection_send failed");
+        }
+    }
+
+    GDBusSignalTable makeSignalEntry(GDBusSignalFlags flags = G_DBUS_SIGNAL_FLAG_NONE) const
+    {
+        GDBusSignalTable entry;
+        entry.name = m_signal.c_str();
+        std::string buffer;
+        buffer += dbus_traits<A1>::getSignature();
+        buffer += dbus_traits<A2>::getSignature();
+        buffer += dbus_traits<A3>::getSignature();
+        buffer += dbus_traits<A4>::getSignature();
+        buffer += dbus_traits<A5>::getSignature();
+        entry.signature = strdup(buffer.c_str());
+        entry.flags = flags;
+        return entry;
+    }
+};
+
+template <class M>
+struct MakeMethodEntry
+{
+    // There is no generic implementation of this method.
+    // If you get an error about it missing, then write
+    // a specialization for your type M (the method pointer).
+    //
+    // static GDBusMethodTable make(const char *name,
+    //                              GDBusMethodFlags flags)
+};
+
+/**
+ * Storage for method/signal/property arrays.
+ * Always contains at least one empty element
+ * at the end or is NULL.
+ */
+template <class T> class DBusVector {
+    size_t m_entries;
+    size_t m_size;
+    T *m_elements;
+
+    static void destroy(GDBusMethodTable &entry) {
+        free(const_cast<char *>(entry.name));
+        free(const_cast<char *>(entry.signature));
+        free(const_cast<char *>(entry.reply));
+        if (entry.destroy) {
+            entry.destroy(&entry);
+        }
+    }
+
+    static void destroy(GDBusSignalTable &entry) {
+        free(const_cast<char *>(entry.signature));
+        // if (entry.destroy) {
+        // entry.destroy(&entry);
+        // }
+    }
+
+ public:
+    DBusVector() : m_entries(0), m_size(0), m_elements(NULL) {}
+    ~DBusVector() {
+        if (m_elements) {
+            for (size_t i = 0; i < m_entries; i++) {
+                destroy(m_elements[i]);
+            }
+            free(m_elements);
+        }
+    }
+
+    T *get() { return m_elements; }
+    void push_back(const T &element) {
+        if (m_entries + 1 >= m_size) {
+            size_t newSize = m_size ? m_size * 2 : 16;
+            m_elements = static_cast<T *>(realloc(m_elements, newSize * sizeof(T)));
+            if (!m_elements) {
+                throw std::bad_alloc();
+            }
+            m_size = newSize;
+        }
+        m_elements[m_entries] = element;
+        m_entries++;
+        memset(m_elements + m_entries, 0, sizeof(T));
+    }
+};
+
+/**
+ * utility class for registering an interface
+ */
+class DBusObjectHelper : public DBusObject
+{
+    DBusConnectionPtr m_conn;
+    std::string m_path;
+    std::string m_interface;
+    bool m_activated;
+    DBusVector<GDBusMethodTable> m_methods;
+    DBusVector<GDBusSignalTable> m_signals;
+
+ public:
+    DBusObjectHelper(DBusConnection *conn,
+                     const std::string &path,
+                     const std::string &interface) :
+        m_conn(conn),
+        m_path(path),
+        m_interface(interface),
+        m_activated(false)
+    {
+    }
+
+    ~DBusObjectHelper()
+    {
+        deactivate();
+    }
+
+    virtual DBusConnection *getConnection() const { return m_conn.get(); }
+    virtual const char *getPath() const { return m_path.c_str(); }
+    virtual const char *getInterface() const { return m_interface.c_str(); }
+
+    /**
+     * binds a member to the this pointer of its instance
+     * and invokes it when the specified method is called
+     */
+    template <class A1, class C, class M> void add(A1 instance, M C::*method,
+                                                   const char *name, GDBusMethodFlags flags = G_DBUS_METHOD_FLAG_NONE) {
+        typedef MakeMethodEntry< boost::function<M> > entry_type;
+        m_methods.push_back(entry_type::make(name, flags, entry_type::boostptr(method, instance)));
+    }
+
+
+    /**
+     * binds a plain function pointer with no additional arguments and
+     * invokes it when the specified method is called
+     */
+    template <class M> void add(M *function,
+                                const char *name, GDBusMethodFlags flags = G_DBUS_METHOD_FLAG_NONE) {
+        m_methods.push_back(MakeMethodEntry< boost::function<M> >::make(name, flags, function));
+    }
+
+    /**
+     * add an existing signal entry
+     */
+    template <class S> void add(const S &s) {
+        m_signals.push_back(s.makeSignalEntry());
+    }
+
+    void activate(GDBusMethodTable *methods,
+                  GDBusSignalTable *signals,
+                  GDBusPropertyTable *properties,
+                  void *user_data) {
+        if (!g_dbus_register_interface(getConnection(), getPath(), getInterface(),
+                                       methods, signals, properties, user_data, NULL)) {
+            throw std::runtime_error(std::string("g_dbus_register_interface() failed for ") + getPath() + " " + getInterface());
+        }
+        m_activated = true;
+    }
+
+    void activate() {
+        if (!g_dbus_register_interface(getConnection(), getPath(), getInterface(),
+                                       m_methods.get(), m_signals.get(), NULL, NULL, NULL)) {
+            throw std::runtime_error(std::string("g_dbus_register_interface() failed for ") + getPath() + " " + getInterface());
+        }
+        m_activated = true;
+    }
+
+    void deactivate()
+    {
+        if (m_activated) {
+            if (!g_dbus_unregister_interface(getConnection(),
+                                             getPath(),
+                                             getInterface())) {
+                throw std::runtime_error(std::string("g_dbus_unregister_interface() failed for ") + getPath() + " " + getInterface());
+            }
+            m_activated = false;
+        }
+    }
+};
+
+
+/**
+ * to be used for plain parameters like int32_t:
+ * treat as arguments which have to be extracted
+ * from the D-Bus message and can be skipped when
+ * encoding the reply
+ */
+template<class host, int dbus> struct basic_marshal : public dbus_traits_base
+{
+    typedef host host_type;
+    typedef host arg_type;
+    static const int dbus_type = dbus;
+
+    /**
+     * copy value from D-Bus iterator into variable
+     */
+    static void get(DBusConnection *conn, DBusMessage *msg,
+                    DBusMessageIter &iter, host &value)
+    {
+        if (dbus_message_iter_get_arg_type(&iter) != dbus) {
+            throw std::runtime_error("invalid argument");
+        }
+        dbus_message_iter_get_basic(&iter, &value);
+        dbus_message_iter_next(&iter);
+    }
+
+    /**
+     * copy value from return value into D-Bus iterator,
+     * empty here because plain types are no return values
+     */
+    static void append(DBusMessageIter &iter, arg_type value)
+    {
+        // nothing to do
+    }
+
+    /**
+     * utility function to be used by derived classes which
+     * need to copy a variable of this underlying type
+     */
+    static void append_retval(DBusMessageIter &iter, arg_type value)
+    {
+        if (!dbus_message_iter_append_basic(&iter, dbus, &value)) {
+            throw std::runtime_error("out of memory");
+        }
+    }
+};
+
+template<> struct dbus_traits<uint8_t> :
+    public basic_marshal< uint8_t, DBUS_TYPE_BYTE >
+{
+    /**
+     * plain type, regardless of whether used as
+     * input or output parameter
+     */
+    static std::string getType() { return "y"; }
+
+    /**
+     * plain type => input parameter => non-empty signature
+     */
+    static std::string getSignature() {return getType(); }
+
+    /**
+     * plain type => not returned to caller
+     */
+    static std::string getReply() { return ""; }
+    
+};
+
+/** if the app wants to use signed char, let it and treat it like a byte */
+template<> struct dbus_traits<int8_t> : dbus_traits<uint8_t>
+{
+    typedef int8_t host_type;
+    typedef int8_t arg_type;
+
+    static void get(DBusConnection *conn, DBusMessage *msg,
+                    DBusMessageIter &iter, host_type &value)
+    {
+        dbus_traits<uint8_t>::get(conn, msg, iter, reinterpret_cast<uint8_t &>(value));
+    }
+};
+
+template<> struct dbus_traits<int16_t> :
+    public basic_marshal< int16_t, DBUS_TYPE_INT16 >
+{
+    static std::string getType() { return "n"; }
+    static std::string getSignature() {return getType(); }
+    static std::string getReply() { return ""; }
+};
+template<> struct dbus_traits<uint16_t> :
+    public basic_marshal< uint16_t, DBUS_TYPE_UINT16 >
+{
+    static std::string getType() { return "q"; }
+    static std::string getSignature() {return getType(); }
+    static std::string getReply() { return ""; }
+};
+template<> struct dbus_traits<int32_t> :
+    public basic_marshal< int32_t, DBUS_TYPE_INT32 >
+{
+    static std::string getType() { return "i"; }
+    static std::string getSignature() {return getType(); }
+    static std::string getReply() { return ""; }
+};
+template<> struct dbus_traits<uint32_t> :
+    public basic_marshal< uint32_t, DBUS_TYPE_UINT32 >
+{
+    static std::string getType() { return "u"; }
+    static std::string getSignature() {return getType(); }
+    static std::string getReply() { return ""; }
+};
+
+template<> struct dbus_traits<bool> : public dbus_traits_base
+{
+    static std::string getType() { return "b"; }
+    static std::string getSignature() {return getType(); }
+    static std::string getReply() { return ""; }
+    static const int dbus = DBUS_TYPE_BOOLEAN;
+
+    static void get(DBusConnection *conn, DBusMessage *msg,
+                    DBusMessageIter &iter, bool &value)
+    {
+        if (dbus_message_iter_get_arg_type(&iter) != dbus) {
+            throw std::runtime_error("invalid argument");
+        }
+        dbus_bool_t dbus_value;
+        dbus_message_iter_get_basic(&iter, &dbus_value);
+        dbus_message_iter_next(&iter);
+        value = dbus_value;
+    }    
+
+    static void append(DBusMessageIter &iter, bool value) {}
+
+    static void append_retval(DBusMessageIter &iter, bool value)
+    {
+        dbus_bool_t dbus_value = value;
+        if (!dbus_message_iter_append_basic(&iter, dbus, &dbus_value)) {
+            throw std::runtime_error("out of memory");
+        }
+    }
+
+    typedef bool host_type;
+    typedef bool arg_type;
+};
+
+template<> struct dbus_traits<std::string> : public dbus_traits_base
+{
+    static std::string getType() { return "s"; }
+    static std::string getSignature() {return getType(); }
+    static std::string getReply() { return ""; }
+    static const int dbus = DBUS_TYPE_STRING;
+
+    static void get(DBusConnection *conn, DBusMessage *msg,
+                    DBusMessageIter &iter, std::string &value)
+    {
+        if (dbus_message_iter_get_arg_type(&iter) != dbus) {
+            throw std::runtime_error("invalid argument");
+        }
+        const char *str;
+        dbus_message_iter_get_basic(&iter, &str);
+        dbus_message_iter_next(&iter);
+        value = str;
+    }
+
+    static void append(DBusMessageIter &iter, const std::string &value) {}
+
+    static void append_retval(DBusMessageIter &iter, const std::string &value)
+    {
+        const char *str = value.c_str();
+        if (!dbus_message_iter_append_basic(&iter, dbus, &str)) {
+            throw std::runtime_error("out of memory");
+        }
+    }
+
+    typedef std::string host_type;
+    typedef const std::string &arg_type;
+};
+
+template <> struct dbus_traits<DBusObject_t> : public dbus_traits_base
+{
+    static std::string getType() { return "o"; }
+    static std::string getSignature() {return getType(); }
+    static std::string getReply() { return ""; }
+    static const int dbus = DBUS_TYPE_OBJECT_PATH;
+
+    static void get(DBusConnection *conn, DBusMessage *msg,
+                    DBusMessageIter &iter, DBusObject_t &value)
+    {
+        if (dbus_message_iter_get_arg_type(&iter) != dbus) {
+            throw std::runtime_error("invalid argument");
+        }
+        const char *str;
+        dbus_message_iter_get_basic(&iter, &str);
+        dbus_message_iter_next(&iter);
+        value = str;
+    }
+
+    static void append(DBusMessageIter &iter, const DBusObject_t &value) {}
+
+    static void append_retval(DBusMessageIter &iter, const DBusObject_t &value)
+    {
+        const char *str = value.c_str();
+        if (!dbus_message_iter_append_basic(&iter, dbus, &str)) {
+            throw std::runtime_error("out of memory");
+        }
+    }
+
+    typedef DBusObject_t host_type;
+    typedef const DBusObject_t &arg_type;
+};
+
+/**
+ * pseudo-parameter: not part of D-Bus signature,
+ * but rather extracted from message attributes
+ */
+template <> struct dbus_traits<Caller_t> : public dbus_traits_base
+{
+    static std::string getType() { return ""; }
+    static std::string getSignature() { return ""; }
+    static std::string getReply() { return ""; }
+
+    static void get(DBusConnection *conn, DBusMessage *msg,
+                    DBusMessageIter &iter, Caller_t &value)
+    {
+        const char *peer = dbus_message_get_sender(msg);
+        if (!peer) {
+            throw std::runtime_error("D-Bus method call without sender?!");
+        }
+        value = peer;
+    }
+
+    static void append(DBusMessageIter &iter, const DBusObject_t &value) {}
+
+    typedef Caller_t host_type;
+    typedef const Caller_t &arg_type;
+};
+
+/**
+ * Pass array of basic type plus its number of entries.
+ * Can only be used in cases where the caller owns the
+ * memory and can discard it when the call returns, in
+ * other words, for method calls, asynchronous replys and
+ * signals, but not for return values.
+ */
+template<class V> struct dbus_traits< std::pair<size_t, const V *> > : public dbus_traits_base
+{
+    static std::string getContainedType()
+    {
+        return dbus_traits<V>::getType();
+    }
+    static std::string getType()
+    {
+        return std::string("a") +
+            dbus_traits<V>::getType();
+    }
+    static std::string getSignature() {return getType(); }
+    static std::string getReply() { return ""; }
+    typedef std::pair<size_t, const V *> host_type;
+    typedef const host_type &arg_type;
+
+    static void get(DBusConnection *conn, DBusMessage *msg,
+                    DBusMessageIter &iter, host_type &array)
+    {
+        if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
+            throw std::runtime_error("invalid argument");
+        }
+        DBusMessageIter sub;
+        dbus_message_iter_recurse(&iter, &sub);
+        int type = dbus_message_iter_get_arg_type(&sub);
+        if (type != dbus_traits<V>::dbus_type) {
+            throw std::runtime_error("invalid argument");
+        }
+        int nelements;
+        typename dbus_traits<V>::host_type *data;
+        dbus_message_iter_get_fixed_array(&sub, &data, &nelements);
+        array.first = nelements;
+        array.second = data;
+        dbus_message_iter_next(&iter);
+    }
+
+    static void append(DBusMessageIter &iter, arg_type array) {}
+
+    static void append_retval(DBusMessageIter &iter, arg_type array)
+    {
+        DBusMessageIter sub;
+        if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, getContainedType().c_str(), &sub) ||
+            !dbus_message_iter_append_fixed_array(&sub, dbus_traits<V>::dbus_type, &array.second, array.first) ||
+            !dbus_message_iter_close_container(&iter, &sub)) {
+            throw std::runtime_error("out of memory");
+        }
+    }
+};
+
+/**
+ * a std::map - treat it like a D-Bus dict
+ */
+template<class K, class V> struct dbus_traits< std::map<K, V> > : public dbus_traits_base
+{
+    static std::string getContainedType()
+    {
+        return std::string("{") +
+            dbus_traits<K>::getType() +
+            dbus_traits<V>::getType() +
+            "}";
+    }
+    static std::string getType()
+    {
+        return std::string("a") +
+            getContainedType();
+    }
+    static std::string getSignature() {return getType(); }
+    static std::string getReply() { return ""; }
+    typedef std::map<K, V> host_type;
+    typedef const std::map<K, V> &arg_type;
+
+    static void get(DBusConnection *conn, DBusMessage *msg,
+                    DBusMessageIter &iter, host_type &dict)
+    {
+        if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
+            throw std::runtime_error("invalid argument");
+        }
+        DBusMessageIter sub;
+        dbus_message_iter_recurse(&iter, &sub);
+        int type;
+        while ((type = dbus_message_iter_get_arg_type(&sub)) != DBUS_TYPE_INVALID) {
+            if (type != DBUS_TYPE_DICT_ENTRY) {
+                throw std::runtime_error("invalid argument");
+            }
+            DBusMessageIter entry;
+            dbus_message_iter_recurse(&sub, &entry);
+            K key;
+            V value;
+            dbus_traits<K>::get(conn, msg, entry, key);
+            dbus_traits<V>::get(conn, msg, entry, value);
+            dict.insert(std::make_pair(key, value));
+            dbus_message_iter_next(&sub);
+        }
+        dbus_message_iter_next(&iter);
+    }
+
+    static void append(DBusMessageIter &iter, arg_type dict) {}
+
+    static void append_retval(DBusMessageIter &iter, arg_type dict)
+    {
+        DBusMessageIter sub;
+        if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, getContainedType().c_str(), &sub)) {
+            throw std::runtime_error("out of memory");
+        }
+
+        for(typename host_type::const_iterator it = dict.begin();
+            it != dict.end();
+            ++it) {
+            DBusMessageIter entry;
+            if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_DICT_ENTRY, NULL, &entry)) {
+                throw std::runtime_error("out of memory");
+            }
+            dbus_traits<K>::append_retval(entry, it->first);
+            dbus_traits<V>::append_retval(entry, it->second);
+            if (!dbus_message_iter_close_container(&sub, &entry)) {
+                throw std::runtime_error("out of memory");
+            }
+        }
+        if (!dbus_message_iter_close_container(&iter, &sub)) {
+            throw std::runtime_error("out of memory");
+        }
+    }
+};
+
+/**
+ * a std::vector - maps to D-Bus array, but with inefficient marshaling
+ * because we cannot get a base pointer for the whole array
+ */
+template<class V> struct dbus_traits< std::vector<V> > : public dbus_traits_base
+{
+    static std::string getContainedType()
+    {
+        return dbus_traits<V>::getType();
+    }
+    static std::string getType()
+    {
+        return std::string("a") +
+            getContainedType();
+    }
+    static std::string getSignature() {return getType(); }
+    static std::string getReply() { return ""; }
+    typedef std::vector<V> host_type;
+    typedef const std::vector<V> &arg_type;
+
+    static void get(DBusConnection *conn, DBusMessage *msg,
+                    DBusMessageIter &iter, host_type &array)
+    {
+        if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
+            throw std::runtime_error("invalid argument");
+        }
+        DBusMessageIter sub;
+        dbus_message_iter_recurse(&iter, &sub);
+        while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
+            V value;
+            dbus_traits<V>::get(conn, msg, sub, value);
+            array.push_back(value);
+        }
+        dbus_message_iter_next(&iter);
+    }
+
+    static void append(DBusMessageIter &iter, arg_type array) {}
+
+    static void append_retval(DBusMessageIter &iter, arg_type array)
+    {
+        DBusMessageIter sub;
+        if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, getContainedType().c_str(), &sub)) {
+            throw std::runtime_error("out of memory");
+        }
+
+        for(typename host_type::const_iterator it = array.begin();
+            it != array.end();
+            ++it) {
+            dbus_traits<V>::append_retval(sub, *it);
+        }
+        if (!dbus_message_iter_close_container(&iter, &sub)) {
+            throw std::runtime_error("out of memory");
+        }
+    }
+};
+
+/**
+ * a single member m of type V in a struct K
+ */
+template<class K, class V, V K::*m> struct dbus_member_single
+{
+    static std::string getType()
+    {
+        return dbus_traits<V>::getType();
+    }
+    typedef V host_type;
+
+    static void get(DBusConnection *conn, DBusMessage *msg,
+                    DBusMessageIter &iter, K &val)
+    {
+        dbus_traits<V>::get(conn, msg, iter, val.*m);
+    }
+
+    static void append_retval(DBusMessageIter &iter, const K &val)
+    {
+        dbus_traits<V>::append_retval(iter, val.*m);
+    }
+};
+
+/**
+ * a member m of type V in a struct K, followed by another dbus_member
+ * or dbus_member_single to end the chain
+ */
+template<class K, class V, V K::*m, class M> struct dbus_member
+{
+    static std::string getType()
+    {
+        return dbus_traits<V>::getType() + M::getType();
+    }
+    typedef V host_type;
+
+    static void get(DBusConnection *conn, DBusMessage *msg,
+                    DBusMessageIter &iter, K &val)
+    {
+        dbus_traits<V>::get(conn, msg, iter, val.*m);
+        M::get(conn, msg, iter, val);
+    }
+
+    static void append_retval(DBusMessageIter &iter, const K &val)
+    {
+        dbus_traits<V>::append_retval(iter, val.*m);
+        M::append_retval(iter, val);
+    }
+};
+
+/**
+ * a helper class which implements dbus_traits for
+ * a class, use with:
+ * struct foo { int a; std::string b;  };
+ * template<> struct dbus_traits< foo > : dbus_struct_traits< foo,
+ *                                                            dbus_member<foo, int, &foo::a,
+ *                                                            dbus_member_single<foo, std::string, &foo::b> > > {};
+ */
+template<class K, class M> struct dbus_struct_traits : public dbus_traits_base
+{
+    static std::string getContainedType()
+    {
+        return M::getType();
+    }
+    static std::string getType()
+    {
+        return std::string("(") +
+            getContainedType() +
+            ")";
+    }
+    static std::string getSignature() {return getType(); }
+    static std::string getReply() { return ""; }
+    typedef K host_type;
+    typedef const K &arg_type;
+
+    static void get(DBusConnection *conn, DBusMessage *msg,
+                    DBusMessageIter &iter, host_type &val)
+    {
+        
+        if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRUCT) {
+            throw std::runtime_error("invalid argument");
+        }
+        DBusMessageIter sub;
+        dbus_message_iter_recurse(&iter, &sub);
+        M::get(conn, msg, sub, val);
+        dbus_message_iter_next(&iter);
+    }
+
+    static void append(DBusMessageIter &iter, arg_type val) {}
+
+    static void append_retval(DBusMessageIter &iter, arg_type val)
+    {
+        DBusMessageIter sub;
+        if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_STRUCT, NULL, &sub)) {
+            throw std::runtime_error("out of memory");
+        }
+        M::append_retval(sub, val);
+        if (!dbus_message_iter_close_container(&iter, &sub)) {
+            throw std::runtime_error("out of memory");
+        }
+    }
+};
+
+/**
+ * special case const reference parameter:
+ * treat like pass-by-value input argument
+ *
+ * Example: const std::string &arg
+ */
+template<class C> struct dbus_traits<const C &> : public dbus_traits<C> {};
+
+/**
+ * special case writeable reference parameter:
+ * must be a return value, so provide our own
+ * get() and pack() where get() doesn't do
+ * anything and pack() really encodes the value
+ *
+ * Example: std::string &retval
+ */
+template<class C> struct dbus_traits<C &> : public dbus_traits<C>
+{
+    /**
+     * skip when extracting input arguments
+     */
+    static void get(DBusConnection *conn, DBusMessage *msg,
+                    DBusMessageIter &iter, C &value) {}
+    static std::string getSignature() { return ""; }
+
+    /**
+     * use utility function provided by underlying trait
+     */
+    static void append(DBusMessageIter &iter, const C &value)
+    {
+        dbus_traits<C>::append_retval(iter, value);
+    }
+    static std::string getReply() { return dbus_traits<C>::getType(); }
+};
+
+/**
+ * dbus-cxx base exception thrown in dbus server 
+ * org.syncevolution.gdbus-cxx.Exception 
+ * This base class only contains interfaces, no data members
+ */
+class DBusCXXException 
+{
+ public:
+    /**
+     * get exception name, used to convert to dbus error name
+     * subclasses should override it
+     */
+    virtual std::string getName() const { return "org.syncevolution.gdbus-cxx.Exception"; }
+
+    /**
+     * get error message
+     */
+    virtual const char* getMessage() const { return "unknown"; }
+};
+
+static DBusMessage *handleException(DBusMessage *msg)
+{
+    try {
+#ifdef DBUS_CXX_EXCEPTION_HANDLER
+        return DBUS_CXX_EXCEPTION_HANDLER(msg);
+#else
+        throw;
+#endif
+    } catch (const dbus_error &ex) {
+        return g_dbus_create_error(msg, ex.dbusName().c_str(), "%s", ex.what());
+    } catch (const DBusCXXException &ex) {
+        return g_dbus_create_error(msg, ex.getName().c_str(), "%s", ex.getMessage());
+    } catch (const std::runtime_error &ex) {
+        return g_dbus_create_error(msg, "org.syncevolution.gdbus-cxx.Exception", "%s", ex.what());
+    } catch (...) {
+        return g_dbus_create_error(msg, "org.syncevolution.gdbus-cxx.Exception", "unknown");
+    }
+}
+
+/**
+ * Check presence of a certain D-Bus client.
+ */
+class DBusWatch : public Watch
+{
+    DBusConnectionPtr m_conn;
+    boost::function<void (void)> m_callback;
+    bool m_called;
+    guint m_watchID;
+
+    static void disconnect(DBusConnection *connection,
+                           void *user_data)
+    {
+        DBusWatch *watch = static_cast<DBusWatch *>(user_data);
+        if (!watch->m_called) {
+            watch->m_called = true;
+            if (watch->m_callback) {
+                watch->m_callback();
+            }
+        }
+    }
+
+ public:
+    DBusWatch(const DBusConnectionPtr &conn,
+              const boost::function<void (void)> &callback = boost::function<void (void)>()) :
+        m_conn(conn),
+        m_callback(callback),
+        m_called(false),
+        m_watchID(0)
+    {
+    }
+
+    virtual void setCallback(const boost::function<void (void)> &callback)
+    {
+        m_callback = callback;
+        if (m_called && m_callback) {
+            m_callback();
+        }
+    }
+
+    void activate(const char *peer)
+    {
+        if (!peer) {
+            throw std::runtime_error("DBusWatch::activate(): no peer");
+        }
+
+        // Install watch first ...
+        m_watchID = g_dbus_add_disconnect_watch(m_conn.get(),
+                                                peer,
+                                                disconnect,
+                                                this,
+                                                NULL);
+        if (!m_watchID) {
+            throw std::runtime_error("g_dbus_add_disconnect_watch() failed");
+        }
+
+        // ... then check that the peer really exists,
+        // otherwise we'll never notice the disconnect.
+        // If it disconnects while we are doing this,
+        // then disconnect() will be called twice,
+        // but it handles that.
+        DBusErrorCXX error;
+        if (!dbus_bus_name_has_owner(m_conn.get(),
+                                     peer,
+                                     &error)) {
+            if (error) {
+                error.throwFailure("dbus_bus_name_has_owner()");
+            }
+            disconnect(m_conn.get(), this);
+        }
+    }
+
+    ~DBusWatch()
+    {
+        if (m_watchID) {
+            if (!g_dbus_remove_watch(m_conn.get(), m_watchID)) {
+                // this may happen because the watch is
+                // removed automatically when it was triggered
+            }
+            m_watchID = 0;
+        }
+    }
+};
+
+/**
+ * pseudo-parameter: not part of D-Bus signature,
+ * but rather extracted from message attributes
+ */
+template <> struct dbus_traits< boost::shared_ptr<Watch> >  : public dbus_traits_base
+{
+    static std::string getType() { return ""; }
+    static std::string getSignature() { return ""; }
+    static std::string getReply() { return ""; }
+
+    static void get(DBusConnection *conn, DBusMessage *msg,
+                    DBusMessageIter &iter, boost::shared_ptr<Watch> &value)
+    {
+        boost::shared_ptr<DBusWatch> watch(new DBusWatch(conn));
+        watch->activate(dbus_message_get_sender(msg));
+        value = watch;
+    }
+
+    static void append(DBusMessageIter &iter, const boost::shared_ptr<Watch> &value) {}
+
+    typedef boost::shared_ptr<Watch> host_type;
+    typedef const boost::shared_ptr<Watch> &arg_type;
+};
+
+/**
+ * base class for D-Bus results,
+ * keeps references to required objects and provides the
+ * failed() method
+ */
+class DBusResult : virtual public Result
+{
+ protected:
+    DBusConnectionPtr m_conn;     /**< connection via which the message was received */
+    DBusMessagePtr m_msg;         /**< the method invocation message */
+
+ public:
+    DBusResult(DBusConnection *conn,
+               DBusMessage *msg) :
+        m_conn(conn, true),
+        m_msg(msg, true)
+    {}
+
+    virtual void failed(const dbus_error &error)
+    {
+        if (!g_dbus_send_error(m_conn.get(), m_msg.get(),
+                               error.dbusName().c_str(),
+                               "%s", error.what())) {
+            throw std::runtime_error("g_dbus_send_error() failed");
+        }
+    }
+
+    virtual Watch *createWatch(const boost::function<void (void)> &callback)
+    {
+        std::auto_ptr<DBusWatch> watch(new DBusWatch(m_conn, callback));
+        watch->activate(dbus_message_get_sender(m_msg.get()));
+        return watch.release();
+    }
+};
+
+class DBusResult0 :
+    public Result0,
+    public DBusResult
+{
+ public:
+    DBusResult0(DBusConnection *conn,
+                DBusMessage *msg) :
+        DBusResult(conn, msg)
+    {}
+  
+    virtual void done()
+    {
+        DBusMessagePtr reply(g_dbus_create_reply(m_msg.get(), DBUS_TYPE_INVALID));
+        if (!reply) {
+            throw std::runtime_error("no DBusMessage");
+        }
+        if (!dbus_connection_send(m_conn.get(), reply.get(), NULL)) {
+            throw std::runtime_error("dbus_connection_send failed");
+        }
+    }
+
+    static std::string getSignature() { return ""; }
+    static void append(DBusMessageIter &iter) {}
+};
+
+template <typename A1>
+class DBusResult1 :
+    public Result1<A1>,
+    public DBusResult
+{
+ public:
+    DBusResult1(DBusConnection *conn,
+                DBusMessage *msg) :
+        DBusResult(conn, msg)
+    {}
+  
+    virtual void done(A1 a1)
+    {
+        DBusMessagePtr reply(g_dbus_create_reply(m_msg.get(), DBUS_TYPE_INVALID));
+        if (!reply) {
+            throw std::runtime_error("no DBusMessage");
+        }
+        append_retvals(reply, a1);
+        if (!dbus_connection_send(m_conn.get(), reply.get(), NULL)) {
+            throw std::runtime_error("dbus_connection_send failed");
+        }
+    }
+
+    static std::string getSignature() { return dbus_traits<A1>::getSignature(); }
+
+    static const bool asynchronous =
+        dbus_traits<A1>::asynchronous;
+};
+
+template <typename A1, typename A2>
+class DBusResult2 :
+    public Result2<A1, A2>,
+    public DBusResult
+{
+ public:
+    DBusResult2(DBusConnection *conn,
+                DBusMessage *msg) :
+        DBusResult(conn, msg)
+    {}
+  
+    virtual void done(A1 a1, A2 a2)
+    {
+        DBusMessagePtr reply(g_dbus_create_reply(m_msg.get(), DBUS_TYPE_INVALID));
+        if (!reply) {
+            throw std::runtime_error("no DBusMessage");
+        }
+        append_retvals(reply, a1, a2);
+        if (!dbus_connection_send(m_conn.get(), reply.get(), NULL)) {
+            throw std::runtime_error("dbus_connection_send failed");
+        }
+    }
+
+    static std::string getSignature() {
+        return dbus_traits<A1>::getSignature() +
+            DBusResult1<A2>::getSignature();
+    }
+
+    static const bool asynchronous =
+        dbus_traits<A1>::asynchronous ||
+        DBusResult1<A2>::asynchronous;
+};
+
+template <typename A1, typename A2, typename A3>
+class DBusResult3 :
+    public Result3<A1, A2, A3>,
+    public DBusResult
+{
+ public:
+    DBusResult3(DBusConnection *conn,
+                DBusMessage *msg) :
+        DBusResult(conn, msg)
+    {}
+  
+    virtual void done(A1 a1, A2 a2, A3 a3)
+    {
+        DBusMessagePtr reply(g_dbus_create_reply(m_msg.get(), DBUS_TYPE_INVALID));
+        if (!reply) {
+            throw std::runtime_error("no DBusMessage");
+        }
+        append_retvals(reply, a1, a2, a3);
+        if (!dbus_connection_send(m_conn.get(), reply.get(), NULL)) {
+            throw std::runtime_error("dbus_connection_send failed");
+        }
+    }
+
+    static std::string getSignature() {
+        return dbus_traits<A1>::getSignature() +
+            DBusResult2<A2, A3>::getSignature();
+    }
+
+    static const bool asynchronous =
+        dbus_traits<A1>::asynchronous ||
+        DBusResult2<A2, A3>::asynchronous;
+};
+
+template <typename A1, typename A2, typename A3, typename A4>
+class DBusResult4 :
+    public Result4<A1, A2, A3, A4>,
+    public DBusResult
+{
+ public:
+    DBusResult4(DBusConnection *conn,
+                DBusMessage *msg) :
+        DBusResult(conn, msg)
+    {}
+  
+    virtual void done(A1 a1, A2 a2, A3 a3, A4 a4)
+    {
+        DBusMessagePtr reply(g_dbus_create_reply(m_msg.get(), DBUS_TYPE_INVALID));
+        if (!reply) {
+            throw std::runtime_error("no DBusMessage");
+        }
+        append_retvals(reply, a1, a2, a3, a4);
+        if (!dbus_connection_send(m_conn.get(), reply.get(), NULL)) {
+            throw std::runtime_error("dbus_connection_send failed");
+        }
+    }
+
+    static std::string getSignature() {
+        return dbus_traits<A1>::getSignature() +
+            DBusResult3<A2, A3, A4>::getSignature();
+    }
+
+    static const bool asynchronous =
+        dbus_traits<A1>::asynchronous ||
+        DBusResult3<A2, A3, A4>::asynchronous;
+};
+
+template <typename A1, typename A2, typename A3, typename A4, typename A5>
+class DBusResult5 :
+    public Result5<A1, A2, A3, A4, A5>,
+    public DBusResult
+{
+ public:
+    DBusResult5(DBusConnection *conn,
+                DBusMessage *msg) :
+        DBusResult(conn, msg)
+    {}
+  
+    virtual void done(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5)
+    {
+        DBusMessagePtr reply(g_dbus_create_reply(m_msg.get(), DBUS_TYPE_INVALID));
+        if (!reply) {
+            throw std::runtime_error("no DBusMessage");
+        }
+        append_retvals(reply, a1, a2, a3, a4, a5);
+        if (!dbus_connection_send(m_conn.get(), reply.get(), NULL)) {
+            throw std::runtime_error("dbus_connection_send failed");
+        }
+    }
+
+    static std::string getSignature() {
+        return dbus_traits<A1>::getSignature() +
+            DBusResult4<A2, A3, A4, A5>::getSignature();
+    }
+
+    static const bool asynchronous =
+        dbus_traits<A1>::asynchronous ||
+        DBusResult4<A2, A3, A4, A5>::asynchronous;
+};
+
+template <typename A1, typename A2, typename A3, typename A4, typename A5,
+          typename A6>
+class DBusResult6 :
+    public Result6<A1, A2, A3, A4, A5, A6>,
+    public DBusResult
+{
+ public:
+    DBusResult6(DBusConnection *conn,
+                DBusMessage *msg) :
+        DBusResult(conn, msg)
+    {}
+  
+    virtual void done(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6)
+    {
+        DBusMessagePtr reply(g_dbus_create_reply(m_msg.get(), DBUS_TYPE_INVALID));
+        if (!reply) {
+            throw std::runtime_error("no DBusMessage");
+        }
+        append_retvals(reply, a1, a2, a3, a4, a5, a6);
+        if (!dbus_connection_send(m_conn.get(), reply.get(), NULL)) {
+            throw std::runtime_error("dbus_connection_send failed");
+        }
+    }
+
+    static std::string getSignature() {
+        return dbus_traits<A1>::getSignature() +
+            DBusResult5<A2, A3, A4, A5, A6>::getSignature();
+    }
+
+    static const bool asynchronous =
+        dbus_traits<A1>::asynchronous ||
+        DBusResult5<A2, A3, A4, A5, A6>::asynchronous;
+};
+
+template <typename A1, typename A2, typename A3, typename A4, typename A5,
+          typename A6, typename A7>
+class DBusResult7 :
+    public Result7<A1, A2, A3, A4, A5, A6, A7>,
+    public DBusResult
+{
+ public:
+    DBusResult7(DBusConnection *conn,
+                DBusMessage *msg) :
+        DBusResult(conn, msg)
+    {}
+  
+    virtual void done(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7)
+    {
+        DBusMessagePtr reply(g_dbus_create_reply(m_msg.get(), DBUS_TYPE_INVALID));
+        if (!reply) {
+            throw std::runtime_error("no DBusMessage");
+        }
+        append_retvals(reply, a1, a2, a3, a4, a5, a6, a7);
+        if (!dbus_connection_send(m_conn.get(), reply.get(), NULL)) {
+            throw std::runtime_error("dbus_connection_send failed");
+        }
+    }
+
+    static std::string getSignature() {
+        return dbus_traits<A1>::getSignature() +
+            DBusResult6<A2, A3, A4, A5, A6, A7>::getSignature();
+    }
+
+    static const bool asynchronous =
+        dbus_traits<A1>::asynchronous ||
+        DBusResult6<A2, A3, A4, A5, A6, A7>::asynchronous;
+};
+
+template <typename A1, typename A2, typename A3, typename A4, typename A5,
+          typename A6, typename A7, typename A8>
+class DBusResult8 :
+    public Result8<A1, A2, A3, A4, A5, A6, A7, A8>,
+    public DBusResult
+{
+ public:
+    DBusResult8(DBusConnection *conn,
+                DBusMessage *msg) :
+        DBusResult(conn, msg)
+    {}
+  
+    virtual void done(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8)
+    {
+        DBusMessagePtr reply(g_dbus_create_reply(m_msg.get(), DBUS_TYPE_INVALID));
+        if (!reply) {
+            throw std::runtime_error("no DBusMessage");
+        }
+        append_retvals(reply, a1, a2, a3, a4, a5, a6, a7, a8);
+        if (!dbus_connection_send(m_conn.get(), reply.get(), NULL)) {
+            throw std::runtime_error("dbus_connection_send failed");
+        }
+    }
+
+    static std::string getSignature() {
+        return dbus_traits<A1>::getSignature() +
+            DBusResult7<A2, A3, A4, A5, A6, A7, A8>::getSignature();
+    }
+
+    static const bool asynchronous =
+        dbus_traits<A1>::asynchronous ||
+        DBusResult7<A2, A3, A4, A5, A6, A7, A8>::asynchronous;
+};
+
+template <typename A1, typename A2, typename A3, typename A4, typename A5,
+          typename A6, typename A7, typename A8, typename A9>
+class DBusResult9 :
+    public Result9<A1, A2, A3, A4, A5, A6, A7, A8, A9>,
+    public DBusResult
+{
+ public:
+    DBusResult9(DBusConnection *conn,
+                DBusMessage *msg) :
+        DBusResult(conn, msg)
+    {}
+  
+    virtual void done(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9)
+    {
+        DBusMessagePtr reply(g_dbus_create_reply(m_msg.get(), DBUS_TYPE_INVALID));
+        if (!reply) {
+            throw std::runtime_error("no DBusMessage");
+        }
+        append_retvals(reply, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+        if (!dbus_connection_send(m_conn.get(), reply.get(), NULL)) {
+            throw std::runtime_error("dbus_connection_send failed");
+        }
+    }
+
+    static std::string getSignature() {
+        return dbus_traits<A1>::getSignature() +
+            DBusResult8<A2, A3, A4, A5, A6, A7, A8, A9>::getSignature();
+    }
+
+    static const bool asynchronous =
+        dbus_traits<A1>::asynchronous ||
+        DBusResult8<A2, A3, A4, A5, A6, A7, A8, A9>::asynchronous;
+};
+
+template <typename A1, typename A2, typename A3, typename A4, typename A5,
+          typename A6, typename A7, typename A8, typename A9, typename A10>
+class DBusResult10 :
+    public Result10<A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>,
+    public DBusResult
+{
+ public:
+    DBusResult10(DBusConnection *conn,
+                 DBusMessage *msg) :
+        DBusResult(conn, msg)
+    {}
+  
+    virtual void done(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10)
+    {
+        DBusMessagePtr reply(g_dbus_create_reply(m_msg.get(), DBUS_TYPE_INVALID));
+        if (!reply) {
+            throw std::runtime_error("no DBusMessage");
+        }
+        append_retvals(reply, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
+        if (!dbus_connection_send(m_conn.get(), reply.get(), NULL)) {
+            throw std::runtime_error("dbus_connection_send failed");
+        }
+    }
+
+    static std::string getSignature() {
+        return dbus_traits<A1>::getSignature() +
+            DBusResult9<A2, A3, A4, A5, A6, A7, A8, A9, A10>::getSignature();
+    }
+
+    static const bool asynchronous =
+        dbus_traits<A1>::asynchronous ||
+        DBusResult9<A2, A3, A4, A5, A6, A7, A8, A9, A10>::asynchronous;
+};
+
+/**
+ * A parameter which points towards one of our Result* structures.
+ * All of the types contained in it count towards the Reply signature.
+ * The requested Result type itself is constructed here.
+ *
+ * @param R      Result0, Result1<type>, ...
+ * @param DBusR  the class implementing R
+ */
+template <class R, class DBusR> struct dbus_traits_result
+{
+    static std::string getType() { return DBusR::getSignature(); }
+    static std::string getSignature() { return ""; }
+    static std::string getReply() { return getType(); }
+
+    typedef boost::shared_ptr<R> host_type;
+    typedef boost::shared_ptr<R> &arg_type;
+    static const bool asynchronous = true;
+
+    static void get(DBusConnection *conn, DBusMessage *msg,
+                    DBusMessageIter &iter, host_type &value)
+    {
+        value.reset(new DBusR(conn, msg));
+    }
+
+    static void append(DBusMessageIter &iter, const host_type &value) {}
+    static void append_retval(DBusMessageIter &iter, const host_type &value) {}
+};
+
+template <>
+struct dbus_traits< boost::shared_ptr<Result0> > :
+    public dbus_traits_result<Result0, DBusResult0>
+{};
+template <class A1>
+struct dbus_traits< boost::shared_ptr< Result1<A1> > >:
+    public dbus_traits_result< Result1<A1>, DBusResult1<A1> >
+{};
+template <class A1, class A2>
+struct dbus_traits< boost::shared_ptr< Result2<A1, A2> > >:
+    public dbus_traits_result< Result2<A1, A2>, DBusResult2<A1, A2> >
+{};
+template <class A1, class A2, class A3>
+    struct dbus_traits< boost::shared_ptr< Result3<A1, A2, A3> > >:
+    public dbus_traits_result< Result3<A1, A2, A3>, DBusResult3<A1, A2, A3> >
+{};
+template <class A1, class A2, class A3, class A4>
+    struct dbus_traits< boost::shared_ptr< Result4<A1, A2, A3, A4> > >:
+    public dbus_traits_result< Result4<A1, A2, A3, A4>, DBusResult4<A1, A2, A3, A4> >
+{};
+template <class A1, class A2, class A3, class A4, class A5>
+    struct dbus_traits< boost::shared_ptr< Result5<A1, A2, A3, A4, A5> > >:
+    public dbus_traits_result< Result5<A1, A2, A3, A4, A5>, DBusResult5<A1, A2, A3, A4, A5> >
+{};
+template <class A1, class A2, class A3, class A4, class A5, class A6>
+    struct dbus_traits< boost::shared_ptr< Result6<A1, A2, A3, A4, A5, A6> > >:
+    public dbus_traits_result< Result6<A1, A2, A3, A4, A5, A6>, DBusResult6<A1, A2, A3, A4, A5, A6> >
+{};
+template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
+    struct dbus_traits< boost::shared_ptr< Result7<A1, A2, A3, A4, A5, A6, A7> > >:
+    public dbus_traits_result< Result7<A1, A2, A3, A4, A5, A6, A7>, DBusResult7<A1, A2, A3, A4, A5, A6, A7> >
+{};
+template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
+    struct dbus_traits< boost::shared_ptr< Result8<A1, A2, A3, A4, A5, A6, A7, A8> > >:
+    public dbus_traits_result< Result8<A1, A2, A3, A4, A5, A6, A7, A8>, DBusResult8<A1, A2, A3, A4, A5, A6, A7, A8> >
+{};
+template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
+    struct dbus_traits< boost::shared_ptr< Result9<A1, A2, A3, A4, A5, A6, A7, A8, A9> > >:
+    public dbus_traits_result< Result9<A1, A2, A3, A4, A5, A6, A7, A8, A9>, DBusResult9<A1, A2, A3, A4, A5, A6, A7, A8, A9> >
+{};
+template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
+    struct dbus_traits< boost::shared_ptr< Result10<A1, A2, A3, A4, A5, A6, A7, A8, A9, A10> > >:
+    public dbus_traits_result< Result10<A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>, DBusResult10<A1, A2, A3, A4, A5, A6, A7, A8, A9, A10> >
+{};
+
+
+#if 0
+/**
+ * Call with two parameters and one return code. All other calls are
+ * variations of this, so this one is fully documented to explain all
+ * tricks used in these templates. The actual code without comments is
+ * below.
+ */
+template <class R, class A1, class A2>
+struct MakeMethodEntry< boost::function<R (A1, A2)> >
+{
+    typedef boost::function<R (A1, A2)> M;
+
+    // Any type a Result parameter? This can be computed at compile time.
+    static const bool asynchronous = dbus_traits< DBusResult2<A1, A2> >::asynchronous;
+
+    static DBusMessage *methodFunction(DBusConnection *conn,
+                                       DBusMessage *msg, void *data)
+    {
+        // all exceptions must be caught and translated into
+        // a suitable D-Bus reply
+        try {
+            // Argument types might may be references or pointers.
+            // To instantiate a variable we need the underlying
+            // datatype, which is provided by the dbus_traits.
+            // "typename" is necessary to tell the compiler
+            // that host_type really is a type.
+            typename dbus_traits<R>::host_type r;
+            typename dbus_traits<A1>::host_type a1;
+            typename dbus_traits<A2>::host_type a2;
+
+            // Extract all parameters. Because we don't now
+            // whether a parameter is an argument or a return
+            // value, we call get() for each of them and let
+            // the corresponding dbus_traits decide that. Traits
+            // for types which are plain types or const references
+            // have a non-empty get(), whereas references are treated
+            // as return values and have an empty get().
+            DBusMessageIter iter;
+            dbus_message_iter_init(msg, &iter);
+            dbus_traits<A1>::get(conn, msg, iter, a1);
+            dbus_traits<A2>::get(conn, msg, iter, a2);
+
+            // The data pointer is a pointer to a boost function,
+            // as set up for us by make(). The compiler knows the
+            // exact method prototype and thus can handle
+            // call-by-value and call-by-reference correctly.
+            r = (*static_cast<M *>(data))(a1, a2);
+
+            // No reply necessary? If any of the types is asking for
+            // a Result handle, then the reply will be sent later.
+            if (asynchronous) {
+                return NULL;
+            }
+
+            // Now prepare the reply. As with extracting parameters,
+            // append() is empty for those parameters where nothing
+            // has to be done.
+            DBusMessage *reply = dbus_message_new_method_return(msg);
+            if (!reply)
+                return NULL;
+            dbus_message_iter_init_append(reply, &iter);
+            // We know that the return value has to be appended,
+            // even though the trait would not normally do that
+            // because it is a plain type => call utility function
+            // directly.
+            dbus_traits<R>::append_retval(iter, r);
+            dbus_traits<A1>::append(iter, a1);
+            dbus_traits<A2>::append(iter, a2);
+            return reply;
+        } catch (...) {
+            // let handleException rethrow the exception
+            // to determine its type
+            return handleException(msg);
+        }
+    }
+
+    /**
+     * The boost function doesn't have a virtual destructor.
+     * Therefore we have to cast down to the right type M
+     * before deleting it. The rest of the allocated data
+     * is freed by GDBusVector.
+     */
+    static void destroyFunction(void *user_data)
+    {
+        GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
+        delete static_cast<M *>(entry->method_data);
+    }
+
+    /**
+     * Creates a GDBusMethodTable entry.
+     * The strings inside the entry are allocated
+     * with strdup(), to be freed by GDBusVector::destroy().
+     */
+    GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
+    {
+        GDBusMethodTable entry;
+        entry.name = strdup(name);
+        // same trick as before: only argument types
+        // are added to the signature
+        std::string buffer;
+        buffer += dbus_traits<A1>::getSignature();
+        buffer += dbus_traits<A2>::getSignature();
+        entry.signature = strdup(buffer.c_str());
+        // now the same for reply types
+        buffer.clear();
+        buffer += dbus_traits<R>::getReply();
+        buffer += dbus_traits<A1>::getReply();
+        buffer += dbus_traits<A2>::getReply();
+        entry.reply = strdup(buffer.c_str());
+        // these are the function templates above
+        entry.function = methodFunction;
+        entry.destroy = destroyFunction;
+        // make sure that methodFunction has access to the boost function
+        entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
+                                       (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
+        entry.method_data = new M(m);
+        return entry;
+    }
+};
+#endif // 0
+
+/** ===> 10 parameters */
+template <class A1, class A2, class A3, class A4, class A5,
+          class A6, class A7, class A8, class A9, class A10>
+struct MakeMethodEntry< boost::function<void (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)> >
+{
+    typedef void (Mptr)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10);
+    typedef boost::function<Mptr> M;
+
+    template <class I, class C> static M bind(Mptr C::*method, I instance) {
+        // this fails because bind() only supports up to 9 parameters, including
+        // the initial this pointer
+        return boost::bind(method, instance, _1, _2, _3, _4, _5, _6, _7, _8, _9 /* _10 */);
+    }
+
+    static const bool asynchronous = dbus_traits< DBusResult10<A1, A2, A3, A4, A5, A6, A7, A8, A9, A10> >::asynchronous;
+
+    static DBusMessage *methodFunction(DBusConnection *conn,
+                                       DBusMessage *msg, void *data)
+    {
+        try {
+            typename dbus_traits<A1>::host_type a1;
+            typename dbus_traits<A2>::host_type a2;
+            typename dbus_traits<A3>::host_type a3;
+            typename dbus_traits<A4>::host_type a4;
+            typename dbus_traits<A5>::host_type a5;
+            typename dbus_traits<A6>::host_type a6;
+            typename dbus_traits<A7>::host_type a7;
+            typename dbus_traits<A8>::host_type a8;
+            typename dbus_traits<A9>::host_type a9;
+            typename dbus_traits<A10>::host_type a10;
+
+            DBusMessageIter iter;
+            dbus_message_iter_init(msg, &iter);
+            dbus_traits<A1>::get(conn, msg, iter, a1);
+            dbus_traits<A2>::get(conn, msg, iter, a2);
+            dbus_traits<A3>::get(conn, msg, iter, a3);
+            dbus_traits<A4>::get(conn, msg, iter, a4);
+            dbus_traits<A5>::get(conn, msg, iter, a5);
+            dbus_traits<A6>::get(conn, msg, iter, a6);
+            dbus_traits<A7>::get(conn, msg, iter, a7);
+            dbus_traits<A8>::get(conn, msg, iter, a8);
+            dbus_traits<A9>::get(conn, msg, iter, a9);
+            dbus_traits<A10>::get(conn, msg, iter, a10);
+
+            (*static_cast<M *>(data))(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
+
+            if (asynchronous) {
+                return NULL;
+            }
+
+            DBusMessage *reply = dbus_message_new_method_return(msg);
+            if (!reply)
+                return NULL;
+            dbus_message_iter_init_append(reply, &iter);
+            dbus_traits<A1>::append(iter, a1);
+            dbus_traits<A2>::append(iter, a2);
+            dbus_traits<A3>::append(iter, a3);
+            dbus_traits<A4>::append(iter, a4);
+            dbus_traits<A5>::append(iter, a5);
+            dbus_traits<A6>::append(iter, a6);
+            dbus_traits<A7>::append(iter, a7);
+            dbus_traits<A8>::append(iter, a8);
+            dbus_traits<A9>::append(iter, a9);
+            dbus_traits<A10>::append(iter, a10);
+            return reply;
+        } catch (...) {
+            return handleException(msg);
+        }
+    }
+
+    static void destroyFunction(void *user_data)
+    {
+        GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
+        delete static_cast<M *>(entry->method_data);
+    }
+
+    static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
+    {
+        GDBusMethodTable entry;
+        entry.name = strdup(name);
+        std::string buffer;
+        buffer += dbus_traits<A1>::getSignature();
+        buffer += dbus_traits<A2>::getSignature();
+        buffer += dbus_traits<A3>::getSignature();
+        buffer += dbus_traits<A4>::getSignature();
+        buffer += dbus_traits<A5>::getSignature();
+        buffer += dbus_traits<A6>::getSignature();
+        buffer += dbus_traits<A7>::getSignature();
+        buffer += dbus_traits<A8>::getSignature();
+        buffer += dbus_traits<A9>::getSignature();
+        buffer += dbus_traits<A10>::getSignature();
+        entry.signature = strdup(buffer.c_str());
+        buffer.clear();
+        buffer += dbus_traits<A1>::getReply();
+        buffer += dbus_traits<A2>::getReply();
+        buffer += dbus_traits<A3>::getReply();
+        buffer += dbus_traits<A4>::getReply();
+        buffer += dbus_traits<A5>::getReply();
+        buffer += dbus_traits<A6>::getReply();
+        buffer += dbus_traits<A7>::getReply();
+        buffer += dbus_traits<A8>::getReply();
+        buffer += dbus_traits<A9>::getReply();
+        buffer += dbus_traits<A10>::getReply();
+        entry.reply = strdup(buffer.c_str());
+        entry.function = methodFunction;
+        entry.destroy = destroyFunction;
+        entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
+                                       (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
+        entry.method_data = new M(m);
+        return entry;
+    }
+};
+
+/** 9 arguments, 1 return value */
+template <class R,
+          class A1, class A2, class A3, class A4, class A5,
+          class A6, class A7, class A8, class A9>
+struct MakeMethodEntry< boost::function<R (A1, A2, A3, A4, A5, A6, A7, A8, A9)> >
+{
+    typedef R (Mptr)(A1, A2, A3, A4, A5, A6, A7, A8, A9);
+    typedef boost::function<Mptr> M;
+
+    template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
+        // this fails because bind() only supports up to 9 parameters, including
+        // the initial this pointer
+        return boost::bind(method, instance, _1, _2, _3, _4, _5, _6, _7, _8, _9);
+    }
+
+    static const bool asynchronous = DBusResult9<A1, A2, A3, A4, A5, A6, A7, A8, A9>::asynchronous;
+
+    static DBusMessage *methodFunction(DBusConnection *conn,
+                                       DBusMessage *msg, void *data)
+    {
+        try {
+            typename dbus_traits<R>::host_type r;
+            typename dbus_traits<A1>::host_type a1;
+            typename dbus_traits<A2>::host_type a2;
+            typename dbus_traits<A3>::host_type a3;
+            typename dbus_traits<A4>::host_type a4;
+            typename dbus_traits<A5>::host_type a5;
+            typename dbus_traits<A6>::host_type a6;
+            typename dbus_traits<A7>::host_type a7;
+            typename dbus_traits<A8>::host_type a8;
+            typename dbus_traits<A9>::host_type a9;
+
+            DBusMessageIter iter;
+            dbus_message_iter_init(msg, &iter);
+            dbus_traits<A1>::get(conn, msg, iter, a1);
+            dbus_traits<A2>::get(conn, msg, iter, a2);
+            dbus_traits<A3>::get(conn, msg, iter, a3);
+            dbus_traits<A4>::get(conn, msg, iter, a4);
+            dbus_traits<A5>::get(conn, msg, iter, a5);
+            dbus_traits<A6>::get(conn, msg, iter, a6);
+            dbus_traits<A7>::get(conn, msg, iter, a7);
+            dbus_traits<A8>::get(conn, msg, iter, a8);
+            dbus_traits<A9>::get(conn, msg, iter, a9);
+
+            r = (*static_cast<M *>(data))(a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+            if (asynchronous) {
+                return NULL;
+            }
+
+            DBusMessage *reply = dbus_message_new_method_return(msg);
+            if (!reply)
+                return NULL;
+            dbus_message_iter_init_append(reply, &iter);
+            dbus_traits<R>::append_retval(iter, r);
+            dbus_traits<A1>::append(iter, a1);
+            dbus_traits<A2>::append(iter, a2);
+            dbus_traits<A3>::append(iter, a3);
+            dbus_traits<A4>::append(iter, a4);
+            dbus_traits<A5>::append(iter, a5);
+            dbus_traits<A6>::append(iter, a6);
+            dbus_traits<A7>::append(iter, a7);
+            dbus_traits<A8>::append(iter, a8);
+            dbus_traits<A9>::append(iter, a9);
+            return reply;
+        } catch (...) {
+            return handleException(msg);
+        }
+    }
+
+    static void destroyFunction(void *user_data)
+    {
+        GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
+        delete static_cast<M *>(entry->method_data);
+    }
+
+    static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
+    {
+        GDBusMethodTable entry;
+        entry.name = strdup(name);
+        std::string buffer;
+        buffer += dbus_traits<A1>::getSignature();
+        buffer += dbus_traits<A2>::getSignature();
+        buffer += dbus_traits<A3>::getSignature();
+        buffer += dbus_traits<A4>::getSignature();
+        buffer += dbus_traits<A5>::getSignature();
+        buffer += dbus_traits<A6>::getSignature();
+        buffer += dbus_traits<A7>::getSignature();
+        buffer += dbus_traits<A8>::getSignature();
+        buffer += dbus_traits<A9>::getSignature();
+        entry.signature = strdup(buffer.c_str());
+        buffer.clear();
+        buffer += dbus_traits<R>::getReply();
+        buffer += dbus_traits<A1>::getReply();
+        buffer += dbus_traits<A2>::getReply();
+        buffer += dbus_traits<A3>::getReply();
+        buffer += dbus_traits<A4>::getReply();
+        buffer += dbus_traits<A5>::getReply();
+        buffer += dbus_traits<A6>::getReply();
+        buffer += dbus_traits<A7>::getReply();
+        buffer += dbus_traits<A8>::getReply();
+        buffer += dbus_traits<A9>::getReply();
+        entry.reply = strdup(buffer.c_str());
+        entry.function = methodFunction;
+        entry.destroy = destroyFunction;
+        entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
+                                       (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
+        entry.method_data = new M(m);
+        return entry;
+    }
+};
+
+/** ===> 9 parameters */
+template <class A1, class A2, class A3, class A4, class A5,
+          class A6, class A7, class A8, class A9>
+struct MakeMethodEntry< boost::function<void (A1, A2, A3, A4, A5, A6, A7, A8, A9)> >
+{
+    typedef void (Mptr)(A1, A2, A3, A4, A5, A6, A7, A8, A9);
+    typedef boost::function<Mptr> M;
+
+    template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
+        return boost::bind(method, instance, _1, _2, _3, _4, _5, _6, _7, _8, _9);
+    }
+
+    static const bool asynchronous = DBusResult9<A1, A2, A3, A4, A5, A6, A7, A8, A9>::asynchronous;
+
+    static DBusMessage *methodFunction(DBusConnection *conn,
+                                       DBusMessage *msg, void *data)
+    {
+        try {
+            typename dbus_traits<A1>::host_type a1;
+            typename dbus_traits<A2>::host_type a2;
+            typename dbus_traits<A3>::host_type a3;
+            typename dbus_traits<A4>::host_type a4;
+            typename dbus_traits<A5>::host_type a5;
+            typename dbus_traits<A6>::host_type a6;
+            typename dbus_traits<A7>::host_type a7;
+            typename dbus_traits<A8>::host_type a8;
+            typename dbus_traits<A9>::host_type a9;
+
+            DBusMessageIter iter;
+            dbus_message_iter_init(msg, &iter);
+            dbus_traits<A1>::get(conn, msg, iter, a1);
+            dbus_traits<A2>::get(conn, msg, iter, a2);
+            dbus_traits<A3>::get(conn, msg, iter, a3);
+            dbus_traits<A4>::get(conn, msg, iter, a4);
+            dbus_traits<A5>::get(conn, msg, iter, a5);
+            dbus_traits<A6>::get(conn, msg, iter, a6);
+            dbus_traits<A7>::get(conn, msg, iter, a7);
+            dbus_traits<A8>::get(conn, msg, iter, a8);
+            dbus_traits<A9>::get(conn, msg, iter, a9);
+
+            (*static_cast<M *>(data))(a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+            if (asynchronous) {
+                return NULL;
+            }
+
+            DBusMessage *reply = dbus_message_new_method_return(msg);
+            if (!reply)
+                return NULL;
+            dbus_message_iter_init_append(reply, &iter);
+            dbus_traits<A1>::append(iter, a1);
+            dbus_traits<A2>::append(iter, a2);
+            dbus_traits<A3>::append(iter, a3);
+            dbus_traits<A4>::append(iter, a4);
+            dbus_traits<A5>::append(iter, a5);
+            dbus_traits<A6>::append(iter, a6);
+            dbus_traits<A7>::append(iter, a7);
+            dbus_traits<A8>::append(iter, a8);
+            dbus_traits<A9>::append(iter, a9);
+            return reply;
+        } catch (...) {
+            return handleException(msg);
+        }
+    }
+
+    static void destroyFunction(void *user_data)
+    {
+        GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
+        delete static_cast<M *>(entry->method_data);
+    }
+
+    static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
+    {
+        GDBusMethodTable entry;
+        entry.name = strdup(name);
+        std::string buffer;
+        buffer += dbus_traits<A1>::getSignature();
+        buffer += dbus_traits<A2>::getSignature();
+        buffer += dbus_traits<A3>::getSignature();
+        buffer += dbus_traits<A4>::getSignature();
+        buffer += dbus_traits<A5>::getSignature();
+        buffer += dbus_traits<A6>::getSignature();
+        buffer += dbus_traits<A7>::getSignature();
+        buffer += dbus_traits<A8>::getSignature();
+        buffer += dbus_traits<A9>::getSignature();
+        entry.signature = strdup(buffer.c_str());
+        buffer.clear();
+        buffer += dbus_traits<A1>::getReply();
+        buffer += dbus_traits<A2>::getReply();
+        buffer += dbus_traits<A3>::getReply();
+        buffer += dbus_traits<A4>::getReply();
+        buffer += dbus_traits<A5>::getReply();
+        buffer += dbus_traits<A6>::getReply();
+        buffer += dbus_traits<A7>::getReply();
+        buffer += dbus_traits<A8>::getReply();
+        buffer += dbus_traits<A9>::getReply();
+        entry.reply = strdup(buffer.c_str());
+        entry.function = methodFunction;
+        entry.destroy = destroyFunction;
+        entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
+                                       (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
+        entry.method_data = new M(m);
+        return entry;
+    }
+};
+
+/** 8 arguments, 1 return value */
+template <class R,
+          class A1, class A2, class A3, class A4, class A5,
+          class A6, class A7, class A8>
+struct MakeMethodEntry< boost::function<R (A1, A2, A3, A4, A5, A6, A7, A8)> >
+{
+    typedef R (Mptr)(A1, A2, A3, A4, A5, A6, A7, A8);
+    typedef boost::function<Mptr> M;
+
+    template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
+        return boost::bind(method, instance, _1, _2, _3, _4, _5, _6, _7, _8);
+    }
+
+    static const bool asynchronous = DBusResult8<A1, A2, A3, A4, A5, A6, A7, A8>::asynchronous;
+
+    static DBusMessage *methodFunction(DBusConnection *conn,
+                                       DBusMessage *msg, void *data)
+    {
+        try {
+            typename dbus_traits<R>::host_type r;
+            typename dbus_traits<A1>::host_type a1;
+            typename dbus_traits<A2>::host_type a2;
+            typename dbus_traits<A3>::host_type a3;
+            typename dbus_traits<A4>::host_type a4;
+            typename dbus_traits<A5>::host_type a5;
+            typename dbus_traits<A6>::host_type a6;
+            typename dbus_traits<A7>::host_type a7;
+            typename dbus_traits<A8>::host_type a8;
+
+            DBusMessageIter iter;
+            dbus_message_iter_init(msg, &iter);
+            dbus_traits<A1>::get(conn, msg, iter, a1);
+            dbus_traits<A2>::get(conn, msg, iter, a2);
+            dbus_traits<A3>::get(conn, msg, iter, a3);
+            dbus_traits<A4>::get(conn, msg, iter, a4);
+            dbus_traits<A5>::get(conn, msg, iter, a5);
+            dbus_traits<A6>::get(conn, msg, iter, a6);
+            dbus_traits<A7>::get(conn, msg, iter, a7);
+            dbus_traits<A8>::get(conn, msg, iter, a8);
+
+            r = (*static_cast<M *>(data))(a1, a2, a3, a4, a5, a6, a7, a8);
+
+            if (asynchronous) {
+                return NULL;
+            }
+
+            DBusMessage *reply = dbus_message_new_method_return(msg);
+            if (!reply)
+                return NULL;
+            dbus_message_iter_init_append(reply, &iter);
+            dbus_traits<R>::append_retval(iter, r);
+            dbus_traits<A1>::append(iter, a1);
+            dbus_traits<A2>::append(iter, a2);
+            dbus_traits<A3>::append(iter, a3);
+            dbus_traits<A4>::append(iter, a4);
+            dbus_traits<A5>::append(iter, a5);
+            dbus_traits<A6>::append(iter, a6);
+            dbus_traits<A7>::append(iter, a7);
+            dbus_traits<A8>::append(iter, a8);
+            return reply;
+        } catch (...) {
+            return handleException(msg);
+        }
+    }
+
+    static void destroyFunction(void *user_data)
+    {
+        GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
+        delete static_cast<M *>(entry->method_data);
+    }
+
+    static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
+    {
+        GDBusMethodTable entry;
+        entry.name = strdup(name);
+        std::string buffer;
+        buffer += dbus_traits<A1>::getSignature();
+        buffer += dbus_traits<A2>::getSignature();
+        buffer += dbus_traits<A3>::getSignature();
+        buffer += dbus_traits<A4>::getSignature();
+        buffer += dbus_traits<A5>::getSignature();
+        buffer += dbus_traits<A6>::getSignature();
+        buffer += dbus_traits<A7>::getSignature();
+        buffer += dbus_traits<A8>::getSignature();
+        entry.signature = strdup(buffer.c_str());
+        buffer.clear();
+        buffer += dbus_traits<R>::getReply();
+        buffer += dbus_traits<A1>::getReply();
+        buffer += dbus_traits<A2>::getReply();
+        buffer += dbus_traits<A3>::getReply();
+        buffer += dbus_traits<A4>::getReply();
+        buffer += dbus_traits<A5>::getReply();
+        buffer += dbus_traits<A6>::getReply();
+        buffer += dbus_traits<A7>::getReply();
+        buffer += dbus_traits<A8>::getReply();
+        entry.reply = strdup(buffer.c_str());
+        entry.function = methodFunction;
+        entry.destroy = destroyFunction;
+        entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
+                                       (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
+        entry.method_data = new M(m);
+        return entry;
+    }
+};
+
+/** ===> 8 parameters */
+template <class A1, class A2, class A3, class A4, class A5,
+          class A6, class A7, class A8>
+struct MakeMethodEntry< boost::function<void (A1, A2, A3, A4, A5, A6, A7, A8)> >
+{
+    typedef void (Mptr)(A1, A2, A3, A4, A5, A6, A7, A8);
+    typedef boost::function<Mptr> M;
+
+    template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
+        return boost::bind(method, instance, _1, _2, _3, _4, _5, _6, _7, _8);
+    }
+
+    static const bool asynchronous = DBusResult8<A1, A2, A3, A4, A5, A6, A7, A8>::asynchronous;
+
+    static DBusMessage *methodFunction(DBusConnection *conn,
+                                       DBusMessage *msg, void *data)
+    {
+        try {
+            typename dbus_traits<A1>::host_type a1;
+            typename dbus_traits<A2>::host_type a2;
+            typename dbus_traits<A3>::host_type a3;
+            typename dbus_traits<A4>::host_type a4;
+            typename dbus_traits<A5>::host_type a5;
+            typename dbus_traits<A6>::host_type a6;
+            typename dbus_traits<A7>::host_type a7;
+            typename dbus_traits<A8>::host_type a8;
+
+            DBusMessageIter iter;
+            dbus_message_iter_init(msg, &iter);
+            dbus_traits<A1>::get(conn, msg, iter, a1);
+            dbus_traits<A2>::get(conn, msg, iter, a2);
+            dbus_traits<A3>::get(conn, msg, iter, a3);
+            dbus_traits<A4>::get(conn, msg, iter, a4);
+            dbus_traits<A5>::get(conn, msg, iter, a5);
+            dbus_traits<A6>::get(conn, msg, iter, a6);
+            dbus_traits<A7>::get(conn, msg, iter, a7);
+            dbus_traits<A8>::get(conn, msg, iter, a8);
+
+            (*static_cast<M *>(data))(a1, a2, a3, a4, a5, a6, a7, a8);
+
+            if (asynchronous) {
+                return NULL;
+            }
+
+            DBusMessage *reply = dbus_message_new_method_return(msg);
+            if (!reply)
+                return NULL;
+            dbus_message_iter_init_append(reply, &iter);
+            dbus_traits<A1>::append(iter, a1);
+            dbus_traits<A2>::append(iter, a2);
+            dbus_traits<A3>::append(iter, a3);
+            dbus_traits<A4>::append(iter, a4);
+            dbus_traits<A5>::append(iter, a5);
+            dbus_traits<A6>::append(iter, a6);
+            dbus_traits<A7>::append(iter, a7);
+            dbus_traits<A8>::append(iter, a8);
+            return reply;
+        } catch (...) {
+            return handleException(msg);
+        }
+    }
+
+    static void destroyFunction(void *user_data)
+    {
+        GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
+        delete static_cast<M *>(entry->method_data);
+    }
+
+    static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
+    {
+        GDBusMethodTable entry;
+        entry.name = strdup(name);
+        std::string buffer;
+        buffer += dbus_traits<A1>::getSignature();
+        buffer += dbus_traits<A2>::getSignature();
+        buffer += dbus_traits<A3>::getSignature();
+        buffer += dbus_traits<A4>::getSignature();
+        buffer += dbus_traits<A5>::getSignature();
+        buffer += dbus_traits<A6>::getSignature();
+        buffer += dbus_traits<A7>::getSignature();
+        buffer += dbus_traits<A8>::getSignature();
+        entry.signature = strdup(buffer.c_str());
+        buffer.clear();
+        buffer += dbus_traits<A1>::getReply();
+        buffer += dbus_traits<A2>::getReply();
+        buffer += dbus_traits<A3>::getReply();
+        buffer += dbus_traits<A4>::getReply();
+        buffer += dbus_traits<A5>::getReply();
+        buffer += dbus_traits<A6>::getReply();
+        buffer += dbus_traits<A7>::getReply();
+        buffer += dbus_traits<A8>::getReply();
+        entry.reply = strdup(buffer.c_str());
+        entry.function = methodFunction;
+        entry.destroy = destroyFunction;
+        entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
+                                       (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
+        entry.method_data = new M(m);
+        return entry;
+    }
+};
+
+/** 7 arguments, 1 return value */
+template <class R,
+          class A1, class A2, class A3, class A4, class A5,
+          class A6, class A7>
+struct MakeMethodEntry< boost::function<R (A1, A2, A3, A4, A5, A6, A7)> >
+{
+    typedef R (Mptr)(A1, A2, A3, A4, A5, A6, A7);
+    typedef boost::function<Mptr> M;
+
+    template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
+        return boost::bind(method, instance, _1, _2, _3, _4, _5, _6, _7);
+    }
+
+    static const bool asynchronous = DBusResult7<A1, A2, A3, A4, A5, A6, A7>::asynchronous;
+
+    static DBusMessage *methodFunction(DBusConnection *conn,
+                                       DBusMessage *msg, void *data)
+    {
+        try {
+            typename dbus_traits<R>::host_type r;
+            typename dbus_traits<A1>::host_type a1;
+            typename dbus_traits<A2>::host_type a2;
+            typename dbus_traits<A3>::host_type a3;
+            typename dbus_traits<A4>::host_type a4;
+            typename dbus_traits<A5>::host_type a5;
+            typename dbus_traits<A6>::host_type a6;
+            typename dbus_traits<A7>::host_type a7;
+
+            DBusMessageIter iter;
+            dbus_message_iter_init(msg, &iter);
+            dbus_traits<A1>::get(conn, msg, iter, a1);
+            dbus_traits<A2>::get(conn, msg, iter, a2);
+            dbus_traits<A3>::get(conn, msg, iter, a3);
+            dbus_traits<A4>::get(conn, msg, iter, a4);
+            dbus_traits<A5>::get(conn, msg, iter, a5);
+            dbus_traits<A6>::get(conn, msg, iter, a6);
+            dbus_traits<A7>::get(conn, msg, iter, a7);
+
+            r = (*static_cast<M *>(data))(a1, a2, a3, a4, a5, a6, a7);
+
+            if (asynchronous) {
+                return NULL;
+            }
+
+            DBusMessage *reply = dbus_message_new_method_return(msg);
+            if (!reply)
+                return NULL;
+            dbus_message_iter_init_append(reply, &iter);
+            dbus_traits<R>::append_retval(iter, r);
+            dbus_traits<A1>::append(iter, a1);
+            dbus_traits<A2>::append(iter, a2);
+            dbus_traits<A3>::append(iter, a3);
+            dbus_traits<A4>::append(iter, a4);
+            dbus_traits<A5>::append(iter, a5);
+            dbus_traits<A6>::append(iter, a6);
+            dbus_traits<A7>::append(iter, a7);
+            return reply;
+        } catch (...) {
+            return handleException(msg);
+        }
+    }
+
+    static void destroyFunction(void *user_data)
+    {
+        GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
+        delete static_cast<M *>(entry->method_data);
+    }
+
+    static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
+    {
+        GDBusMethodTable entry;
+        entry.name = strdup(name);
+        std::string buffer;
+        buffer += dbus_traits<A1>::getSignature();
+        buffer += dbus_traits<A2>::getSignature();
+        buffer += dbus_traits<A3>::getSignature();
+        buffer += dbus_traits<A4>::getSignature();
+        buffer += dbus_traits<A5>::getSignature();
+        buffer += dbus_traits<A6>::getSignature();
+        buffer += dbus_traits<A7>::getSignature();
+        entry.signature = strdup(buffer.c_str());
+        buffer.clear();
+        buffer += dbus_traits<R>::getReply();
+        buffer += dbus_traits<A1>::getReply();
+        buffer += dbus_traits<A2>::getReply();
+        buffer += dbus_traits<A3>::getReply();
+        buffer += dbus_traits<A4>::getReply();
+        buffer += dbus_traits<A5>::getReply();
+        buffer += dbus_traits<A6>::getReply();
+        buffer += dbus_traits<A7>::getReply();
+        entry.reply = strdup(buffer.c_str());
+        entry.function = methodFunction;
+        entry.destroy = destroyFunction;
+        entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
+                                       (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
+        entry.method_data = new M(m);
+        return entry;
+    }
+};
+
+/** ===> 7 parameters */
+template <class A1, class A2, class A3, class A4, class A5,
+          class A6, class A7>
+struct MakeMethodEntry< boost::function<void (A1, A2, A3, A4, A5, A6, A7)> >
+{
+    typedef void (Mptr)(A1, A2, A3, A4, A5, A6, A7);
+    typedef boost::function<Mptr> M;
+
+    template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
+        return boost::bind(method, instance, _1, _2, _3, _4, _5, _6, _7);
+    }
+
+    static const bool asynchronous = DBusResult7<A1, A2, A3, A4, A5, A6, A7>::asynchronous;
+
+    static DBusMessage *methodFunction(DBusConnection *conn,
+                                       DBusMessage *msg, void *data)
+    {
+        try {
+            typename dbus_traits<A1>::host_type a1;
+            typename dbus_traits<A2>::host_type a2;
+            typename dbus_traits<A3>::host_type a3;
+            typename dbus_traits<A4>::host_type a4;
+            typename dbus_traits<A5>::host_type a5;
+            typename dbus_traits<A6>::host_type a6;
+            typename dbus_traits<A7>::host_type a7;
+
+            DBusMessageIter iter;
+            dbus_message_iter_init(msg, &iter);
+            dbus_traits<A1>::get(conn, msg, iter, a1);
+            dbus_traits<A2>::get(conn, msg, iter, a2);
+            dbus_traits<A3>::get(conn, msg, iter, a3);
+            dbus_traits<A4>::get(conn, msg, iter, a4);
+            dbus_traits<A5>::get(conn, msg, iter, a5);
+            dbus_traits<A6>::get(conn, msg, iter, a6);
+            dbus_traits<A7>::get(conn, msg, iter, a7);
+
+            (*static_cast<M *>(data))(a1, a2, a3, a4, a5, a6, a7);
+
+            if (asynchronous) {
+                return NULL;
+            }
+
+            DBusMessage *reply = dbus_message_new_method_return(msg);
+            if (!reply)
+                return NULL;
+            dbus_message_iter_init_append(reply, &iter);
+            dbus_traits<A1>::append(iter, a1);
+            dbus_traits<A2>::append(iter, a2);
+            dbus_traits<A3>::append(iter, a3);
+            dbus_traits<A4>::append(iter, a4);
+            dbus_traits<A5>::append(iter, a5);
+            dbus_traits<A6>::append(iter, a6);
+            dbus_traits<A7>::append(iter, a7);
+            return reply;
+        } catch (...) {
+            return handleException(msg);
+        }
+    }
+
+    static void destroyFunction(void *user_data)
+    {
+        GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
+        delete static_cast<M *>(entry->method_data);
+    }
+
+    static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
+    {
+        GDBusMethodTable entry;
+        entry.name = strdup(name);
+        std::string buffer;
+        buffer += dbus_traits<A1>::getSignature();
+        buffer += dbus_traits<A2>::getSignature();
+        buffer += dbus_traits<A3>::getSignature();
+        buffer += dbus_traits<A4>::getSignature();
+        buffer += dbus_traits<A5>::getSignature();
+        buffer += dbus_traits<A6>::getSignature();
+        buffer += dbus_traits<A7>::getSignature();
+        entry.signature = strdup(buffer.c_str());
+        buffer.clear();
+        buffer += dbus_traits<A1>::getReply();
+        buffer += dbus_traits<A2>::getReply();
+        buffer += dbus_traits<A3>::getReply();
+        buffer += dbus_traits<A4>::getReply();
+        buffer += dbus_traits<A5>::getReply();
+        buffer += dbus_traits<A6>::getReply();
+        buffer += dbus_traits<A7>::getReply();
+        entry.reply = strdup(buffer.c_str());
+        entry.function = methodFunction;
+        entry.destroy = destroyFunction;
+        entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
+                                       (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
+        entry.method_data = new M(m);
+        return entry;
+    }
+};
+
+/** 6 arguments, 1 return value */
+template <class R,
+          class A1, class A2, class A3, class A4, class A5,
+          class A6>
+struct MakeMethodEntry< boost::function<R (A1, A2, A3, A4, A5, A6)> >
+{
+    typedef R (Mptr)(A1, A2, A3, A4, A5, A6);
+    typedef boost::function<Mptr> M;
+
+    template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
+        return boost::bind(method, instance, _1, _2, _3, _4, _5, _6);
+    }
+
+    static const bool asynchronous = DBusResult6<A1, A2, A3, A4, A5, A6>::asynchronous;
+
+    static DBusMessage *methodFunction(DBusConnection *conn,
+                                       DBusMessage *msg, void *data)
+    {
+        try {
+            typename dbus_traits<R>::host_type r;
+            typename dbus_traits<A1>::host_type a1;
+            typename dbus_traits<A2>::host_type a2;
+            typename dbus_traits<A3>::host_type a3;
+            typename dbus_traits<A4>::host_type a4;
+            typename dbus_traits<A5>::host_type a5;
+            typename dbus_traits<A6>::host_type a6;
+
+            DBusMessageIter iter;
+            dbus_message_iter_init(msg, &iter);
+            dbus_traits<A1>::get(conn, msg, iter, a1);
+            dbus_traits<A2>::get(conn, msg, iter, a2);
+            dbus_traits<A3>::get(conn, msg, iter, a3);
+            dbus_traits<A4>::get(conn, msg, iter, a4);
+            dbus_traits<A5>::get(conn, msg, iter, a5);
+            dbus_traits<A6>::get(conn, msg, iter, a6);
+
+            r = (*static_cast<M *>(data))(a1, a2, a3, a4, a5, a6);
+
+            if (asynchronous) {
+                return NULL;
+            }
+
+            DBusMessage *reply = dbus_message_new_method_return(msg);
+            if (!reply)
+                return NULL;
+            dbus_message_iter_init_append(reply, &iter);
+            dbus_traits<R>::append_retval(iter, r);
+            dbus_traits<A1>::append(iter, a1);
+            dbus_traits<A2>::append(iter, a2);
+            dbus_traits<A3>::append(iter, a3);
+            dbus_traits<A4>::append(iter, a4);
+            dbus_traits<A5>::append(iter, a5);
+            dbus_traits<A6>::append(iter, a6);
+            return reply;
+        } catch (...) {
+            return handleException(msg);
+        }
+    }
+
+    static void destroyFunction(void *user_data)
+    {
+        GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
+        delete static_cast<M *>(entry->method_data);
+    }
+
+    static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
+    {
+        GDBusMethodTable entry;
+        entry.name = strdup(name);
+        std::string buffer;
+        buffer += dbus_traits<A1>::getSignature();
+        buffer += dbus_traits<A2>::getSignature();
+        buffer += dbus_traits<A3>::getSignature();
+        buffer += dbus_traits<A4>::getSignature();
+        buffer += dbus_traits<A5>::getSignature();
+        buffer += dbus_traits<A6>::getSignature();
+        entry.signature = strdup(buffer.c_str());
+        buffer.clear();
+        buffer += dbus_traits<R>::getReply();
+        buffer += dbus_traits<A1>::getReply();
+        buffer += dbus_traits<A2>::getReply();
+        buffer += dbus_traits<A3>::getReply();
+        buffer += dbus_traits<A4>::getReply();
+        buffer += dbus_traits<A5>::getReply();
+        buffer += dbus_traits<A6>::getReply();
+        entry.reply = strdup(buffer.c_str());
+        entry.function = methodFunction;
+        entry.destroy = destroyFunction;
+        entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
+                                       (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
+        entry.method_data = new M(m);
+        return entry;
+    }
+};
+
+/** ===> 6 parameters */
+template <class A1, class A2, class A3, class A4, class A5,
+          class A6>
+struct MakeMethodEntry< boost::function<void (A1, A2, A3, A4, A5, A6)> >
+{
+    typedef void (Mptr)(A1, A2, A3, A4, A5, A6);
+    typedef boost::function<Mptr> M;
+
+    template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
+        return boost::bind(method, instance, _1, _2, _3, _4, _5, _6);
+    }
+
+    static const bool asynchronous = DBusResult6<A1, A2, A3, A4, A5, A6>::asynchronous;
+
+    static DBusMessage *methodFunction(DBusConnection *conn,
+                                       DBusMessage *msg, void *data)
+    {
+        try {
+            typename dbus_traits<A1>::host_type a1;
+            typename dbus_traits<A2>::host_type a2;
+            typename dbus_traits<A3>::host_type a3;
+            typename dbus_traits<A4>::host_type a4;
+            typename dbus_traits<A5>::host_type a5;
+            typename dbus_traits<A6>::host_type a6;
+
+            DBusMessageIter iter;
+            dbus_message_iter_init(msg, &iter);
+            dbus_traits<A1>::get(conn, msg, iter, a1);
+            dbus_traits<A2>::get(conn, msg, iter, a2);
+            dbus_traits<A3>::get(conn, msg, iter, a3);
+            dbus_traits<A4>::get(conn, msg, iter, a4);
+            dbus_traits<A5>::get(conn, msg, iter, a5);
+            dbus_traits<A6>::get(conn, msg, iter, a6);
+
+            (*static_cast<M *>(data))(a1, a2, a3, a4, a5, a6);
+
+            if (asynchronous) {
+                return NULL;
+            }
+
+            DBusMessage *reply = dbus_message_new_method_return(msg);
+            if (!reply)
+                return NULL;
+            dbus_message_iter_init_append(reply, &iter);
+            dbus_traits<A1>::append(iter, a1);
+            dbus_traits<A2>::append(iter, a2);
+            dbus_traits<A3>::append(iter, a3);
+            dbus_traits<A4>::append(iter, a4);
+            dbus_traits<A5>::append(iter, a5);
+            dbus_traits<A6>::append(iter, a6);
+            return reply;
+        } catch (...) {
+            return handleException(msg);
+        }
+    }
+    static void destroyFunction(void *user_data)
+    {
+        GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
+        delete static_cast<M *>(entry->method_data);
+    }
+
+    static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
+    {
+        GDBusMethodTable entry;
+        entry.name = strdup(name);
+        std::string buffer;
+        buffer += dbus_traits<A1>::getSignature();
+        buffer += dbus_traits<A2>::getSignature();
+        buffer += dbus_traits<A3>::getSignature();
+        buffer += dbus_traits<A4>::getSignature();
+        buffer += dbus_traits<A5>::getSignature();
+        buffer += dbus_traits<A6>::getSignature();
+        entry.signature = strdup(buffer.c_str());
+        buffer.clear();
+        buffer += dbus_traits<A1>::getReply();
+        buffer += dbus_traits<A2>::getReply();
+        buffer += dbus_traits<A3>::getReply();
+        buffer += dbus_traits<A4>::getReply();
+        buffer += dbus_traits<A5>::getReply();
+        buffer += dbus_traits<A6>::getReply();
+        entry.reply = strdup(buffer.c_str());
+        entry.function = methodFunction;
+        entry.destroy = destroyFunction;
+        entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
+                                       (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
+        entry.method_data = new M(m);
+        return entry;
+    }
+};
+
+/** 5 arguments, 1 return value */
+template <class R,
+          class A1, class A2, class A3, class A4, class A5>
+struct MakeMethodEntry< boost::function<R (A1, A2, A3, A4, A5)> >
+{
+    typedef R (Mptr)(A1, A2, A3, A4, A5);
+    typedef boost::function<Mptr> M;
+
+    template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
+        return boost::bind(method, instance, _1, _2, _3, _4, _5);
+    }
+
+    static const bool asynchronous = DBusResult5<A1, A2, A3, A4, A5>::asynchronous;
+
+    static DBusMessage *methodFunction(DBusConnection *conn,
+                                       DBusMessage *msg, void *data)
+    {
+        try {
+            typename dbus_traits<R>::host_type r;
+            typename dbus_traits<A1>::host_type a1;
+            typename dbus_traits<A2>::host_type a2;
+            typename dbus_traits<A3>::host_type a3;
+            typename dbus_traits<A4>::host_type a4;
+            typename dbus_traits<A5>::host_type a5;
+
+            DBusMessageIter iter;
+            dbus_message_iter_init(msg, &iter);
+            dbus_traits<A1>::get(conn, msg, iter, a1);
+            dbus_traits<A2>::get(conn, msg, iter, a2);
+            dbus_traits<A3>::get(conn, msg, iter, a3);
+            dbus_traits<A4>::get(conn, msg, iter, a4);
+            dbus_traits<A5>::get(conn, msg, iter, a5);
+
+            r = (*static_cast<M *>(data))(a1, a2, a3, a4, a5);
+
+            if (asynchronous) {
+                return NULL;
+            }
+
+            DBusMessage *reply = dbus_message_new_method_return(msg);
+            if (!reply)
+                return NULL;
+            dbus_message_iter_init_append(reply, &iter);
+            dbus_traits<R>::append_retval(iter, r);
+            dbus_traits<A1>::append(iter, a1);
+            dbus_traits<A2>::append(iter, a2);
+            dbus_traits<A3>::append(iter, a3);
+            dbus_traits<A4>::append(iter, a4);
+            dbus_traits<A5>::append(iter, a5);
+            return reply;
+        } catch (...) {
+            return handleException(msg);
+        }
+    }
+
+    static void destroyFunction(void *user_data)
+    {
+        GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
+        delete static_cast<M *>(entry->method_data);
+    }
+
+    static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
+    {
+        GDBusMethodTable entry;
+        entry.name = strdup(name);
+        std::string buffer;
+        buffer += dbus_traits<A1>::getSignature();
+        buffer += dbus_traits<A2>::getSignature();
+        buffer += dbus_traits<A3>::getSignature();
+        buffer += dbus_traits<A4>::getSignature();
+        buffer += dbus_traits<A5>::getSignature();
+        entry.signature = strdup(buffer.c_str());
+        buffer.clear();
+        buffer += dbus_traits<R>::getReply();
+        buffer += dbus_traits<A1>::getReply();
+        buffer += dbus_traits<A2>::getReply();
+        buffer += dbus_traits<A3>::getReply();
+        buffer += dbus_traits<A4>::getReply();
+        buffer += dbus_traits<A5>::getReply();
+        entry.reply = strdup(buffer.c_str());
+        entry.function = methodFunction;
+        entry.destroy = destroyFunction;
+        entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
+                                       (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
+        entry.method_data = new M(m);
+        return entry;
+    }
+};
+
+/** ===> 5 parameters */
+template <class A1, class A2, class A3, class A4, class A5>
+struct MakeMethodEntry< boost::function<void (A1, A2, A3, A4, A5)> >
+{
+    typedef void (Mptr)(A1, A2, A3, A4, A5);
+    typedef boost::function<Mptr> M;
+
+    template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
+        return boost::bind(method, instance, _1, _2, _3, _4, _5, _6, _7, _8);
+    }
+
+    static const bool asynchronous = DBusResult5<A1, A2, A3, A4, A5>::asynchronous;
+
+    static DBusMessage *methodFunction(DBusConnection *conn,
+                                       DBusMessage *msg, void *data)
+    {
+        try {
+            typename dbus_traits<A1>::host_type a1;
+            typename dbus_traits<A2>::host_type a2;
+            typename dbus_traits<A3>::host_type a3;
+            typename dbus_traits<A4>::host_type a4;
+            typename dbus_traits<A5>::host_type a5;
+
+            DBusMessageIter iter;
+            dbus_message_iter_init(msg, &iter);
+            dbus_traits<A1>::get(conn, msg, iter, a1);
+            dbus_traits<A2>::get(conn, msg, iter, a2);
+            dbus_traits<A3>::get(conn, msg, iter, a3);
+            dbus_traits<A4>::get(conn, msg, iter, a4);
+            dbus_traits<A5>::get(conn, msg, iter, a5);
+
+            (*static_cast<M *>(data))(a1, a2, a3, a4, a5);
+
+            if (asynchronous) {
+                return NULL;
+            }
+
+            DBusMessage *reply = dbus_message_new_method_return(msg);
+            if (!reply)
+                return NULL;
+            dbus_message_iter_init_append(reply, &iter);
+            dbus_traits<A1>::append(iter, a1);
+            dbus_traits<A2>::append(iter, a2);
+            dbus_traits<A3>::append(iter, a3);
+            dbus_traits<A4>::append(iter, a4);
+            dbus_traits<A5>::append(iter, a5);
+            return reply;
+        } catch (...) {
+            return handleException(msg);
+        }
+    }
+
+    static void destroyFunction(void *user_data)
+    {
+        GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
+        delete static_cast<M *>(entry->method_data);
+    }
+
+    static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
+    {
+        GDBusMethodTable entry;
+        entry.name = strdup(name);
+        std::string buffer;
+        buffer += dbus_traits<A1>::getSignature();
+        buffer += dbus_traits<A2>::getSignature();
+        buffer += dbus_traits<A3>::getSignature();
+        buffer += dbus_traits<A4>::getSignature();
+        buffer += dbus_traits<A5>::getSignature();
+        entry.signature = strdup(buffer.c_str());
+        buffer.clear();
+        buffer += dbus_traits<A1>::getReply();
+        buffer += dbus_traits<A2>::getReply();
+        buffer += dbus_traits<A3>::getReply();
+        buffer += dbus_traits<A4>::getReply();
+        buffer += dbus_traits<A5>::getReply();
+        entry.reply = strdup(buffer.c_str());
+        entry.function = methodFunction;
+        entry.destroy = destroyFunction;
+        entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
+                                       (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
+        entry.method_data = new M(m);
+        return entry;
+    }
+};
+
+/** 4 arguments, 1 return value */
+template <class R,
+          class A1, class A2, class A3, class A4>
+struct MakeMethodEntry< boost::function<R (A1, A2, A3, A4)> >
+{
+    typedef R (Mptr)(A1, A2, A3, A4);
+    typedef boost::function<Mptr> M;
+
+    template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
+        return boost::bind(method, instance, _1, _2, _3, _4);
+    }
+
+    static const bool asynchronous = DBusResult4<A1, A2, A3, A4>::asynchronous;
+
+    static DBusMessage *methodFunction(DBusConnection *conn,
+                                       DBusMessage *msg, void *data)
+    {
+        try {
+            typename dbus_traits<R>::host_type r;
+            typename dbus_traits<A1>::host_type a1;
+            typename dbus_traits<A2>::host_type a2;
+            typename dbus_traits<A3>::host_type a3;
+            typename dbus_traits<A4>::host_type a4;
+
+            DBusMessageIter iter;
+            dbus_message_iter_init(msg, &iter);
+            dbus_traits<A1>::get(conn, msg, iter, a1);
+            dbus_traits<A2>::get(conn, msg, iter, a2);
+            dbus_traits<A3>::get(conn, msg, iter, a3);
+            dbus_traits<A4>::get(conn, msg, iter, a4);
+
+            r = (*static_cast<M *>(data))(a1, a2, a3, a4);
+
+            if (asynchronous) {
+                return NULL;
+            }
+
+            DBusMessage *reply = dbus_message_new_method_return(msg);
+            if (!reply)
+                return NULL;
+            dbus_message_iter_init_append(reply, &iter);
+            dbus_traits<R>::append_retval(iter, r);
+            dbus_traits<A1>::append(iter, a1);
+            dbus_traits<A2>::append(iter, a2);
+            dbus_traits<A3>::append(iter, a3);
+            dbus_traits<A4>::append(iter, a4);
+            return reply;
+        } catch (...) {
+            return handleException(msg);
+        }
+    }
+
+    static void destroyFunction(void *user_data)
+    {
+        GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
+        delete static_cast<M *>(entry->method_data);
+    }
+
+    static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
+    {
+        GDBusMethodTable entry;
+        entry.name = strdup(name);
+        std::string buffer;
+        buffer += dbus_traits<A1>::getSignature();
+        buffer += dbus_traits<A2>::getSignature();
+        buffer += dbus_traits<A3>::getSignature();
+        buffer += dbus_traits<A4>::getSignature();
+        entry.signature = strdup(buffer.c_str());
+        buffer.clear();
+        buffer += dbus_traits<R>::getReply();
+        buffer += dbus_traits<A1>::getReply();
+        buffer += dbus_traits<A2>::getReply();
+        buffer += dbus_traits<A3>::getReply();
+        buffer += dbus_traits<A4>::getReply();
+        entry.reply = strdup(buffer.c_str());
+        entry.function = methodFunction;
+        entry.destroy = destroyFunction;
+        entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
+                                       (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
+        entry.method_data = new M(m);
+        return entry;
+    }
+};
+
+/** ===> 4 parameters */
+template <class A1, class A2, class A3, class A4>
+struct MakeMethodEntry< boost::function<void (A1, A2, A3, A4)> >
+{
+    typedef void (Mptr)(A1, A2, A3, A4);
+    typedef boost::function<Mptr> M;
+
+    template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
+        return boost::bind(method, instance, _1, _2, _3, _4);
+    }
+
+    static const bool asynchronous = DBusResult4<A1, A2, A3, A4>::asynchronous;
+
+    static DBusMessage *methodFunction(DBusConnection *conn,
+                                       DBusMessage *msg, void *data)
+    {
+        try {
+            typename dbus_traits<A1>::host_type a1;
+            typename dbus_traits<A2>::host_type a2;
+            typename dbus_traits<A3>::host_type a3;
+            typename dbus_traits<A4>::host_type a4;
+
+            DBusMessageIter iter;
+            dbus_message_iter_init(msg, &iter);
+            dbus_traits<A1>::get(conn, msg, iter, a1);
+            dbus_traits<A2>::get(conn, msg, iter, a2);
+            dbus_traits<A3>::get(conn, msg, iter, a3);
+            dbus_traits<A4>::get(conn, msg, iter, a4);
+
+            (*static_cast<M *>(data))(a1, a2, a3, a4);
+
+            if (asynchronous) {
+                return NULL;
+            }
+
+            DBusMessage *reply = dbus_message_new_method_return(msg);
+            if (!reply)
+                return NULL;
+            dbus_message_iter_init_append(reply, &iter);
+            dbus_traits<A1>::append(iter, a1);
+            dbus_traits<A2>::append(iter, a2);
+            dbus_traits<A3>::append(iter, a3);
+            dbus_traits<A4>::append(iter, a4);
+            return reply;
+        } catch (...) {
+            return handleException(msg);
+        }
+    }
+
+    static void destroyFunction(void *user_data)
+    {
+        GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
+        delete static_cast<M *>(entry->method_data);
+    }
+
+    static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
+    {
+        GDBusMethodTable entry;
+        entry.name = strdup(name);
+        std::string buffer;
+        buffer += dbus_traits<A1>::getSignature();
+        buffer += dbus_traits<A2>::getSignature();
+        buffer += dbus_traits<A3>::getSignature();
+        buffer += dbus_traits<A4>::getSignature();
+        entry.signature = strdup(buffer.c_str());
+        buffer.clear();
+        buffer += dbus_traits<A1>::getReply();
+        buffer += dbus_traits<A2>::getReply();
+        buffer += dbus_traits<A3>::getReply();
+        buffer += dbus_traits<A4>::getReply();
+        entry.reply = strdup(buffer.c_str());
+        entry.function = methodFunction;
+        entry.destroy = destroyFunction;
+        entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
+                                       (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
+        entry.method_data = new M(m);
+        return entry;
+    }
+};
+
+/** 3 arguments, 1 return value */
+template <class R,
+          class A1, class A2, class A3>
+struct MakeMethodEntry< boost::function<R (A1, A2, A3)> >
+{
+    typedef R (Mptr)(A1, A2, A3);
+    typedef boost::function<Mptr> M;
+
+    template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
+        return boost::bind(method, instance, _1, _2, _3);
+    }
+
+    static const bool asynchronous = DBusResult3<A1, A2, A3>::asynchronous;
+
+    static DBusMessage *methodFunction(DBusConnection *conn,
+                                       DBusMessage *msg, void *data)
+    {
+        try {
+            typename dbus_traits<R>::host_type r;
+            typename dbus_traits<A1>::host_type a1;
+            typename dbus_traits<A2>::host_type a2;
+            typename dbus_traits<A3>::host_type a3;
+
+            DBusMessageIter iter;
+            dbus_message_iter_init(msg, &iter);
+            dbus_traits<A1>::get(conn, msg, iter, a1);
+            dbus_traits<A2>::get(conn, msg, iter, a2);
+            dbus_traits<A3>::get(conn, msg, iter, a3);
+
+            r = (*static_cast<M *>(data))(a1, a2, a3);
+
+            if (asynchronous) {
+                return NULL;
+            }
+
+            DBusMessage *reply = dbus_message_new_method_return(msg);
+            if (!reply)
+                return NULL;
+            dbus_message_iter_init_append(reply, &iter);
+            dbus_traits<R>::append_retval(iter, r);
+            dbus_traits<A1>::append(iter, a1);
+            dbus_traits<A2>::append(iter, a2);
+            dbus_traits<A3>::append(iter, a3);
+            return reply;
+        } catch (...) {
+            return handleException(msg);
+        }
+    }
+
+    static void destroyFunction(void *user_data)
+    {
+        GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
+        delete static_cast<M *>(entry->method_data);
+    }
+
+    static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
+    {
+        GDBusMethodTable entry;
+        entry.name = strdup(name);
+        std::string buffer;
+        buffer += dbus_traits<A1>::getSignature();
+        buffer += dbus_traits<A2>::getSignature();
+        buffer += dbus_traits<A3>::getSignature();
+        entry.signature = strdup(buffer.c_str());
+        buffer.clear();
+        buffer += dbus_traits<R>::getReply();
+        buffer += dbus_traits<A1>::getReply();
+        buffer += dbus_traits<A2>::getReply();
+        buffer += dbus_traits<A3>::getReply();
+        entry.reply = strdup(buffer.c_str());
+        entry.function = methodFunction;
+        entry.destroy = destroyFunction;
+        entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
+                                       (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
+        entry.method_data = new M(m);
+        return entry;
+    }
+};
+
+/** ===> 3 parameters */
+template <class A1, class A2, class A3>
+struct MakeMethodEntry< boost::function<void (A1, A2, A3)> >
+{
+    typedef void (Mptr)(A1, A2, A3);
+    typedef boost::function<Mptr> M;
+
+    template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
+        return boost::bind(method, instance, _1, _2, _3);
+    }
+
+    static const bool asynchronous = DBusResult3<A1, A2, A3>::asynchronous;
+
+    static DBusMessage *methodFunction(DBusConnection *conn,
+                                       DBusMessage *msg, void *data)
+    {
+        try {
+            typename dbus_traits<A1>::host_type a1;
+            typename dbus_traits<A2>::host_type a2;
+            typename dbus_traits<A3>::host_type a3;
+
+            DBusMessageIter iter;
+            dbus_message_iter_init(msg, &iter);
+            dbus_traits<A1>::get(conn, msg, iter, a1);
+            dbus_traits<A2>::get(conn, msg, iter, a2);
+            dbus_traits<A3>::get(conn, msg, iter, a3);
+
+            (*static_cast<M *>(data))(a1, a2, a3);
+
+            if (asynchronous) {
+                return NULL;
+            }
+
+            DBusMessage *reply = dbus_message_new_method_return(msg);
+            if (!reply)
+                return NULL;
+            dbus_message_iter_init_append(reply, &iter);
+            dbus_traits<A1>::append(iter, a1);
+            dbus_traits<A2>::append(iter, a2);
+            dbus_traits<A3>::append(iter, a3);
+            return reply;
+        } catch (...) {
+            return handleException(msg);
+        }
+    }
+
+    static void destroyFunction(void *user_data)
+    {
+        GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
+        delete static_cast<M *>(entry->method_data);
+    }
+
+    static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
+    {
+        GDBusMethodTable entry;
+        entry.name = strdup(name);
+        std::string buffer;
+        buffer += dbus_traits<A1>::getSignature();
+        buffer += dbus_traits<A2>::getSignature();
+        buffer += dbus_traits<A3>::getSignature();
+        entry.signature = strdup(buffer.c_str());
+        buffer.clear();
+        buffer += dbus_traits<A1>::getReply();
+        buffer += dbus_traits<A2>::getReply();
+        buffer += dbus_traits<A3>::getReply();
+        entry.reply = strdup(buffer.c_str());
+        entry.function = methodFunction;
+        entry.destroy = destroyFunction;
+        entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
+                                       (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
+        entry.method_data = new M(m);
+        return entry;
+    }
+};
+
+/** 2 arguments, 1 return value */
+template <class R,
+          class A1, class A2>
+struct MakeMethodEntry< boost::function<R (A1, A2)> >
+{
+    typedef R (Mptr)(A1, A2);
+    typedef boost::function<Mptr> M;
+
+    template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
+        return boost::bind(method, instance, _1, _2);
+    }
+
+    static const bool asynchronous = DBusResult2<A1, A2>::asynchronous;
+
+    static DBusMessage *methodFunction(DBusConnection *conn,
+                                       DBusMessage *msg, void *data)
+    {
+        try {
+            typename dbus_traits<R>::host_type r;
+            typename dbus_traits<A1>::host_type a1;
+            typename dbus_traits<A2>::host_type a2;
+
+            DBusMessageIter iter;
+            dbus_message_iter_init(msg, &iter);
+            dbus_traits<A1>::get(conn, msg, iter, a1);
+            dbus_traits<A2>::get(conn, msg, iter, a2);
+
+            r = (*static_cast<M *>(data))(a1, a2);
+
+            if (asynchronous) {
+                return NULL;
+            }
+
+            DBusMessage *reply = dbus_message_new_method_return(msg);
+            if (!reply)
+                return NULL;
+            dbus_message_iter_init_append(reply, &iter);
+            dbus_traits<R>::append_retval(iter, r);
+            dbus_traits<A1>::append(iter, a1);
+            dbus_traits<A2>::append(iter, a2);
+            return reply;
+        } catch (...) {
+            return handleException(msg);
+        }
+    }
+
+    static void destroyFunction(void *user_data)
+    {
+        GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
+        delete static_cast<M *>(entry->method_data);
+    }
+
+    static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
+    {
+        GDBusMethodTable entry;
+        entry.name = strdup(name);
+        std::string buffer;
+        buffer += dbus_traits<A1>::getSignature();
+        buffer += dbus_traits<A2>::getSignature();
+        entry.signature = strdup(buffer.c_str());
+        buffer.clear();
+        buffer += dbus_traits<R>::getReply();
+        buffer += dbus_traits<A1>::getReply();
+        buffer += dbus_traits<A2>::getReply();
+        entry.reply = strdup(buffer.c_str());
+        entry.function = methodFunction;
+        entry.destroy = destroyFunction;
+        entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
+                                       (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
+        entry.method_data = new M(m);
+        return entry;
+    }
+};
+
+/** ===> 2 parameters */
+template <class A1, class A2>
+struct MakeMethodEntry< boost::function<void (A1, A2)> >
+{
+    typedef void (Mptr)(A1, A2);
+    typedef boost::function<Mptr> M;
+
+    template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
+        return boost::bind(method, instance, _1, _2);
+    }
+
+    static const bool asynchronous = DBusResult2<A1, A2>::asynchronous;
+
+    static DBusMessage *methodFunction(DBusConnection *conn,
+                                       DBusMessage *msg, void *data)
+    {
+        try {
+            typename dbus_traits<A1>::host_type a1;
+            typename dbus_traits<A2>::host_type a2;
+
+            DBusMessageIter iter;
+            dbus_message_iter_init(msg, &iter);
+            dbus_traits<A1>::get(conn, msg, iter, a1);
+            dbus_traits<A2>::get(conn, msg, iter, a2);
+
+            (*static_cast<M *>(data))(a1, a2);
+
+            if (asynchronous) {
+                return NULL;
+            }
+
+            DBusMessage *reply = dbus_message_new_method_return(msg);
+            if (!reply)
+                return NULL;
+            dbus_message_iter_init_append(reply, &iter);
+            dbus_traits<A1>::append(iter, a1);
+            dbus_traits<A2>::append(iter, a2);
+            return reply;
+        } catch (...) {
+            return handleException(msg);
+        }
+    }
+
+    static void destroyFunction(void *user_data)
+    {
+        GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
+        delete static_cast<M *>(entry->method_data);
+    }
+
+    static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
+    {
+        GDBusMethodTable entry;
+        entry.name = strdup(name);
+        std::string buffer;
+        buffer += dbus_traits<A1>::getSignature();
+        buffer += dbus_traits<A2>::getSignature();
+        entry.signature = strdup(buffer.c_str());
+        buffer.clear();
+        buffer += dbus_traits<A1>::getReply();
+        buffer += dbus_traits<A2>::getReply();
+        entry.reply = strdup(buffer.c_str());
+        entry.function = methodFunction;
+        entry.destroy = destroyFunction;
+        entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
+                                       (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
+        entry.method_data = new M(m);
+        return entry;
+    }
+};
+
+/** 1 argument, 1 return value */
+template <class R,
+          class A1>
+struct MakeMethodEntry< boost::function<R (A1)> >
+{
+    typedef R (Mptr)(A1);
+    typedef boost::function<Mptr> M;
+
+    template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
+        return boost::bind(method, instance, _1);
+    }
+
+    static const bool asynchronous = DBusResult1<A1>::asynchronous;
+
+    static DBusMessage *methodFunction(DBusConnection *conn,
+                                       DBusMessage *msg, void *data)
+    {
+        try {
+            typename dbus_traits<R>::host_type r;
+            typename dbus_traits<A1>::host_type a1;
+
+            DBusMessageIter iter;
+            dbus_message_iter_init(msg, &iter);
+            dbus_traits<A1>::get(conn, msg, iter, a1);
+
+            r = (*static_cast<M *>(data))(a1);
+
+            if (asynchronous) {
+                return NULL;
+            }
+
+            DBusMessage *reply = dbus_message_new_method_return(msg);
+            if (!reply)
+                return NULL;
+            dbus_message_iter_init_append(reply, &iter);
+            dbus_traits<R>::append_retval(iter, r);
+            dbus_traits<A1>::append(iter, a1);
+            return reply;
+        } catch (...) {
+            return handleException(msg);
+        }
+    }
+
+    static void destroyFunction(void *user_data)
+    {
+        GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
+        delete static_cast<M *>(entry->method_data);
+    }
+
+    static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
+    {
+        GDBusMethodTable entry;
+        entry.name = strdup(name);
+        std::string buffer;
+        buffer += dbus_traits<A1>::getSignature();
+        entry.signature = strdup(buffer.c_str());
+        buffer.clear();
+        buffer += dbus_traits<R>::getReply();
+        buffer += dbus_traits<A1>::getReply();
+        entry.reply = strdup(buffer.c_str());
+        entry.function = methodFunction;
+        entry.destroy = destroyFunction;
+        entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
+                                       (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
+        entry.method_data = new M(m);
+        return entry;
+    }
+};
+
+/** ===> 1 parameter */
+template <class A1>
+struct MakeMethodEntry< boost::function<void (A1)> >
+{
+    typedef void (Mptr)(A1);
+    typedef boost::function<void (A1)> M;
+
+    template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
+        return boost::bind(method, instance, _1);
+    }
+
+    static const bool asynchronous = DBusResult1<A1>::asynchronous;
+
+    static DBusMessage *methodFunction(DBusConnection *conn,
+                                       DBusMessage *msg, void *data)
+    {
+        try {
+            typename dbus_traits<A1>::host_type a1;
+
+            DBusMessageIter iter;
+            dbus_message_iter_init(msg, &iter);
+            dbus_traits<A1>::get(conn, msg, iter, a1);
+
+            (*static_cast<M *>(data))(a1);
+
+            if (asynchronous) {
+                return NULL;
+            }
+
+            DBusMessage *reply = dbus_message_new_method_return(msg);
+            if (!reply)
+                return NULL;
+            dbus_message_iter_init_append(reply, &iter);
+            dbus_traits<A1>::append(iter, a1);
+            return reply;
+        } catch (...) {
+            return handleException(msg);
+        }
+    }
+
+    static void destroyFunction(void *user_data)
+    {
+        GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
+        delete static_cast<M *>(entry->method_data);
+    }
+
+    static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
+    {
+        GDBusMethodTable entry;
+        entry.name = strdup(name);
+        std::string buffer;
+        buffer += dbus_traits<A1>::getSignature();
+        entry.signature = strdup(buffer.c_str());
+        buffer.clear();
+        buffer += dbus_traits<A1>::getReply();
+        entry.reply = strdup(buffer.c_str());
+        entry.function = methodFunction;
+        entry.destroy = destroyFunction;
+        entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
+                                       (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
+        entry.method_data = new M(m);
+        return entry;
+    }
+};
+
+/** 0 arguments, 1 return value */
+template <class R>
+struct MakeMethodEntry< boost::function<R ()> >
+{
+    typedef R (Mptr)();
+    typedef boost::function<Mptr> M;
+
+    template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
+        return boost::bind(method, instance);
+    }
+
+    static DBusMessage *methodFunction(DBusConnection *conn,
+                                       DBusMessage *msg, void *data)
+    {
+        try {
+            typename dbus_traits<R>::host_type r;
+
+            r = (*static_cast<M *>(data))();
+
+            DBusMessage *reply = dbus_message_new_method_return(msg);
+            if (!reply)
+                return NULL;
+            DBusMessageIter iter;
+            dbus_message_iter_init_append(reply, &iter);
+            dbus_traits<R>::append_retval(iter, r);
+            return reply;
+        } catch (...) {
+            return handleException(msg);
+        }
+    }
+    static void destroyFunction(void *user_data)
+    {
+        GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
+        delete static_cast<M *>(entry->method_data);
+    }
+
+    static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
+    {
+        GDBusMethodTable entry;
+        entry.name = strdup(name);
+        std::string buffer;
+        entry.signature = strdup(buffer.c_str());
+        buffer.clear();
+        buffer += dbus_traits<R>::getReply();
+        entry.reply = strdup(buffer.c_str());
+        entry.function = methodFunction;
+        entry.destroy = destroyFunction;
+        entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA);
+        entry.method_data = new M(m);
+        return entry;
+    }
+};
+
+/** ===> 0 parameter */
+template <>
+struct MakeMethodEntry< boost::function<void ()> >
+{
+    typedef void (Mptr)();
+    typedef boost::function<Mptr> M;
+
+    template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
+        return boost::bind(method, instance);
+    }
+
+    static DBusMessage *methodFunction(DBusConnection *conn,
+                                       DBusMessage *msg, void *data)
+    {
+        try {
+            (*static_cast<M *>(data))();
+
+            DBusMessage *reply = dbus_message_new_method_return(msg);
+            if (!reply)
+                return NULL;
+            return reply;
+        } catch (...) {
+            return handleException(msg);
+        }
+    }
+
+    static void destroyFunction(void *user_data)
+    {
+        GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
+        delete static_cast<M *>(entry->method_data);
+    }
+
+    static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
+    {
+        GDBusMethodTable entry;
+        entry.name = strdup(name);
+        std::string buffer;
+        entry.signature = strdup(buffer.c_str());
+        buffer.clear();
+        entry.reply = strdup(buffer.c_str());
+        entry.function = methodFunction;
+        entry.destroy = destroyFunction;
+        entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA);
+        entry.method_data = new M(m);
+        return entry;
+    }
+};
+
+#endif // INCL_GDBUS_CXX_BRIDGE
diff --git a/src/gdbus/gdbus-cxx.h b/src/gdbus/gdbus-cxx.h
new file mode 100644 (file)
index 0000000..95d063b
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2009 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) version 3.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301  USA
+ */
+
+#ifndef INCL_GDBUS_CXX
+#define INCL_GDBUS_CXX
+
+#include <string>
+#include <stdexcept>
+#include <boost/function.hpp>
+#include <boost/noncopyable.hpp>
+
+/**
+ * An exception class which can be thrown to create
+ * specific D-Bus exception on the bus.
+ */
+class dbus_error : public std::runtime_error
+{
+public:
+    /**
+     * @param dbus_name     the D-Bus error name, like "org.example.error.Invalid"
+     * @param what          a more detailed description
+     */
+    dbus_error(const std::string &dbus_name, const std::string &what) :
+        std::runtime_error(what),
+        m_dbus_name(dbus_name)
+        {}
+    ~dbus_error() throw() {}
+
+    const std::string &dbusName() const { return m_dbus_name; }
+
+private:
+    std::string m_dbus_name;
+};
+
+class Watch : private boost::noncopyable
+{
+ public:
+    virtual ~Watch() {};
+
+    /**
+     * Changes the callback triggered by this Watch.  If the watch has
+     * already fired, the callback is invoked immediately.
+     */
+    virtual void setCallback(const boost::function<void (void)> &callback) = 0;
+};
+
+/**
+ * Special parameter type that identifies a caller. A string in practice.
+ */
+class Caller_t : public std::string
+{
+ public:
+    Caller_t() {}
+    template <class T> Caller_t(T val) : std::string(val) {}
+    template <class T> Caller_t &operator = (T val) { assign(val); return *this; }
+};
+
+/**
+ * Call object which needs to be called with the results
+ * of an asynchronous method call. So instead of
+ * "int foo()" one would implement
+ * "void foo(Result1<int> > *r)"
+ * and after foo has returned, call r->done(res). Use const
+ * references as type for complex results.
+ *
+ * A Result instance can be copied, but only called once.
+ */
+class Result
+{
+ public:
+    virtual ~Result() {}
+
+    /** report failure to caller */
+    virtual void failed(const dbus_error &error) = 0;
+
+    /**
+     * Calls the given callback once when the peer that the result
+     * would be delivered to disconnects.  The callback will also be
+     * called if the peer is already gone by the time that the watch
+     * is requested.
+     *
+     * Alternatively a method can ask to get called with a life Watch
+     * by specifying "const boost::shared_ptr<Watch> &" as parameter
+     * and then calling its setCallback().
+     */
+    virtual Watch *createWatch(const boost::function<void (void)> &callback) = 0;
+ };
+
+class Result0 : virtual public Result
+{
+ public:
+    /** tell caller that we are done */
+    virtual void done() = 0;
+};
+
+template <typename A1>
+class Result1 : virtual public Result
+{
+ public:
+    /** return result to caller */
+    virtual void done(A1 a1) = 0;
+};
+
+template <typename A1, typename A2>
+struct Result2 : virtual public Result
+{
+    virtual void done(A1 a1, A2 a2) = 0;
+};
+
+template <typename A1, typename A2, typename A3>
+struct Result3 : virtual public Result
+{
+    virtual void done(A1 a1, A2 a2, A3 a3) = 0;
+};
+
+template <typename A1, typename A2, typename A3, typename A4>
+struct Result4 : virtual public Result
+{
+    virtual void done(A1 a1, A2 a2, A3 a3, A4 a4) = 0;
+};
+
+template <typename A1, typename A2, typename A3, typename A4, typename A5>
+struct Result5 : virtual public Result
+{
+    virtual void done(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) = 0;
+};
+
+template <typename A1, typename A2, typename A3, typename A4, typename A5,
+          typename A6>
+struct Result6 : virtual public Result
+{
+    virtual void done(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) = 0;
+};
+
+template <typename A1, typename A2, typename A3, typename A4, typename A5,
+          typename A6, typename A7>
+struct Result7 : virtual public Result
+{
+    virtual void done(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) = 0;
+};
+
+template <typename A1, typename A2, typename A3, typename A4, typename A5,
+          typename A6, typename A7, typename A8>
+struct Result8 : virtual public Result
+{
+    virtual void done(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) = 0;
+};
+
+template <typename A1, typename A2, typename A3, typename A4, typename A5,
+          typename A6, typename A7, typename A8, typename A9>
+struct Result9 : virtual public Result
+{
+    virtual void done(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) = 0;
+};
+
+template <typename A1, typename A2, typename A3, typename A4, typename A5,
+          typename A6, typename A7, typename A8, typename A9, typename A10>
+struct Result10 : virtual public Result
+{
+    virtual void done(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) = 0;
+};
+
+
+
+#endif // INCL_GDBUS_CXX
diff --git a/src/gdbus/gdbus.h b/src/gdbus/gdbus.h
new file mode 100644 (file)
index 0000000..8a7e349
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+ *
+ *  Library for simple D-Bus integration with GLib
+ *
+ *  Copyright (C) 2007-2008  Intel Corporation. All rights reserved.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License version 2.1 as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __GDBUS_H
+#define __GDBUS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdarg.h>
+#include <stdint.h>
+
+#include <dbus/dbus.h>
+#include <glib.h>
+
+/**
+ * SECTION:gdbus
+ * @title: D-Bus helper library
+ * @short_description: Library for simple D-Bus integration with GLib
+ */
+
+/**
+ * GDBusDestroyFunction:
+ * @user_data: user data to pass to the function
+ *
+ * Destroy function
+ */
+typedef void (* GDBusDestroyFunction) (void *user_data);
+
+/**
+ * GDBusWatchFunction:
+ * @connection: a #DBusConnection
+ * @user_data: user data to pass to the function
+ *
+ * Watch function
+ */
+typedef void (* GDBusWatchFunction) (DBusConnection *connection,
+                                                       void *user_data);
+
+/**
+ * GDBusSignalFunction:
+ * @connection: a #DBusConnection
+ * @message: a #DBusMessage
+ * @user_data: user data to pass to the function
+ *
+ * Signal function
+ *
+ * Returns: #FALSE to remove this watch
+ */
+typedef gboolean (* GDBusSignalFunction) (DBusConnection *connection,
+                                       DBusMessage *message, void *user_data);
+
+/**
+ * GDBusMethodFunction:
+ * @connection: a #DBusConnection
+ * @message: a #DBusMessage
+ * @user_data: user data to pass to the function
+ *
+ * Method function
+ *
+ * Returns: #DBusMessage reply
+ */
+typedef DBusMessage * (* GDBusMethodFunction) (DBusConnection *connection,
+                                       DBusMessage *message, void *user_data);
+
+/**
+ * GDBusPropertyGetFunction:
+ * @connection: a #DBusConnection
+ * @iter: a #DBusMessageIter
+ * @user_data: user data to pass to the function
+ *
+ * Property get function
+ *
+ * Returns: #TRUE on success
+ */
+typedef dbus_bool_t (* GDBusPropertyGetFunction) (DBusConnection *connection,
+                                       DBusMessageIter *iter, void *user_data);
+
+/**
+ * GDBusPropertySetFunction:
+ * @connection: a #DBusConnection
+ * @iter: a #DBusMessageIter
+ * @user_data: user data to pass to the function
+ *
+ * Property set function
+ *
+ * Returns: #TRUE on success
+ */
+typedef dbus_bool_t (* GDBusPropertySetFunction) (DBusConnection *connection,
+                                       DBusMessageIter *iter, void *user_data);
+
+/**
+ * GDBusMethodFlags:
+ * @G_DBUS_METHOD_FLAG_DEPRECATED: annotate deprecated methods
+ * @G_DBUS_METHOD_FLAG_NOREPLY: annotate methods with no reply
+ * @G_DBUS_METHOD_FLAG_ASYNC: annotate asynchronous methods
+ * @G_DBUS_METHOD_FLAG_METHOD_DATA: the method is passed the
+ *                                  GDBusMethodTable method_data pointer
+ *                                  instead of the g_dbus_register_interface()
+ *                                  user_data pointer
+ *
+ * Method flags
+ */
+typedef enum {
+       G_DBUS_METHOD_FLAG_NONE = 0,
+       G_DBUS_METHOD_FLAG_DEPRECATED = (1 << 0),
+       G_DBUS_METHOD_FLAG_NOREPLY    = (1 << 1),
+       G_DBUS_METHOD_FLAG_ASYNC      = (1 << 2),
+       G_DBUS_METHOD_FLAG_METHOD_DATA = (1 << 3),
+} GDBusMethodFlags;
+
+/**
+ * GDBusSignalFlags:
+ * @G_DBUS_SIGNAL_FLAG_DEPRECATED: annotate deprecated signals
+ *
+ * Signal flags
+ */
+typedef enum {
+       G_DBUS_SIGNAL_FLAG_NONE = 0,
+       G_DBUS_SIGNAL_FLAG_DEPRECATED = (1 << 0),
+} GDBusSignalFlags;
+
+/**
+ * GDBusPropertyFlags:
+ * @G_DBUS_PROPERTY_FLAG_DEPRECATED: annotate deprecated properties
+ *
+ * Property flags
+ */
+typedef enum {
+       G_DBUS_PROPERTY_FLAG_NONE = 0,
+       G_DBUS_PROPERTY_FLAG_DEPRECATED = (1 << 0),
+} GDBusPropertyFlags;
+
+/**
+ * GDBusMethodTable:
+ * @name: method name
+ * @signature: method signature
+ * @reply: reply signature
+ * @function: method function
+ * @flags: method flags
+ * @method_data: passed as GDBusMethodFunction user_data if
+ *               G_DBUS_METHOD_FLAG_METHOD_DATA is set
+ * @destroy: destructor function for method table; not called
+ *           by gdbus itself, because it never frees GDBusMethodTable
+ *           entries, but useful in upper layers
+ *
+ * Method table
+ */
+typedef struct {
+       const char *name;
+       const char *signature;
+       const char *reply;
+       GDBusMethodFunction function;
+       GDBusMethodFlags flags;
+       void *method_data;
+       GDBusDestroyFunction destroy;
+} GDBusMethodTable;
+
+/**
+ * GDBusSignalTable:
+ * @name: signal name
+ * @signature: signal signature
+ * @flags: signal flags
+ *
+ * Signal table
+ */
+typedef struct {
+       const char *name;
+       const char *signature;
+       GDBusSignalFlags flags;
+} GDBusSignalTable;
+
+/**
+ * GDBusPropertyTable:
+ * @name: property name
+ * @type: property value type
+ * @get: property get function
+ * @set: property set function
+ * @flags: property flags
+ *
+ * Property table
+ */
+typedef struct {
+       const char *name;
+       const char *type;
+       GDBusPropertyGetFunction get;
+       GDBusPropertyGetFunction set;
+       GDBusPropertyFlags flags;
+} GDBusPropertyTable;
+
+void g_dbus_setup_connection(DBusConnection *connection,
+                                               GMainContext *context);
+void g_dbus_cleanup_connection(DBusConnection *connection);
+
+DBusConnection *g_dbus_setup_bus(DBusBusType type, const char *name,
+                                                       DBusError *error);
+
+DBusConnection *g_dbus_setup_address(const char *address, DBusError *error);
+
+gboolean g_dbus_request_name(DBusConnection *connection, const char *name,
+                                                       DBusError *error);
+
+gboolean g_dbus_set_disconnect_function(DBusConnection *connection,
+                               GDBusWatchFunction function,
+                               void *user_data, GDBusDestroyFunction destroy);
+
+gboolean g_dbus_register_interface(DBusConnection *connection,
+                                       const char *path, const char *name,
+                                       GDBusMethodTable *methods,
+                                       GDBusSignalTable *signals,
+                                       GDBusPropertyTable *properties,
+                                       void *user_data,
+                                       GDBusDestroyFunction destroy);
+gboolean g_dbus_unregister_interface(DBusConnection *connection,
+                                       const char *path, const char *name);
+
+DBusMessage *g_dbus_create_error(DBusMessage *message, const char *name,
+                                               const char *format, ...);
+DBusMessage *g_dbus_create_error_valist(DBusMessage *message, const char *name,
+                                       const char *format, va_list args);
+DBusMessage *g_dbus_create_reply(DBusMessage *message, int type, ...);
+DBusMessage *g_dbus_create_reply_valist(DBusMessage *message,
+                                               int type, va_list args);
+
+gboolean g_dbus_send_message(DBusConnection *connection, DBusMessage *message);
+gboolean g_dbus_send_error(DBusConnection *connection, DBusMessage *message,
+                               const char *name, const char *format, ...);
+
+gboolean g_dbus_send_reply(DBusConnection *connection,
+                               DBusMessage *message, int type, ...);
+gboolean g_dbus_send_reply_valist(DBusConnection *connection,
+                               DBusMessage *message, int type, va_list args);
+
+gboolean g_dbus_emit_signal(DBusConnection *connection,
+                               const char *path, const char *interface,
+                               const char *name, int type, ...);
+gboolean g_dbus_emit_signal_valist(DBusConnection *connection,
+                               const char *path, const char *interface,
+                               const char *name, int type, va_list args);
+
+guint g_dbus_add_service_watch(DBusConnection *connection, const char *name,
+                               GDBusWatchFunction connect,
+                               GDBusWatchFunction disconnect,
+                               void *user_data, GDBusDestroyFunction destroy);
+guint g_dbus_add_disconnect_watch(DBusConnection *connection,
+                               const char *name, GDBusWatchFunction function,
+                               void *user_data, GDBusDestroyFunction destroy);
+guint g_dbus_add_signal_watch(DBusConnection *connection,
+                               const char *rule, GDBusSignalFunction function,
+                               void *user_data, GDBusDestroyFunction destroy);
+gboolean g_dbus_remove_watch(DBusConnection *connection, guint tag);
+void g_dbus_remove_all_watches(DBusConnection *connection);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GDBUS_H */
diff --git a/src/gdbus/mainloop.c b/src/gdbus/mainloop.c
new file mode 100644 (file)
index 0000000..fd7a71b
--- /dev/null
@@ -0,0 +1,589 @@
+/*
+ *
+ *  Library for simple D-Bus integration with GLib
+ *
+ *  Copyright (C) 2007-2008  Intel Corporation. All rights reserved.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License version 2.1 as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <dbus/dbus.h>
+#include <glib.h>
+
+#ifdef NEED_DBUS_WATCH_GET_UNIX_FD
+#define dbus_watch_get_unix_fd dbus_watch_get_fd
+#endif
+
+#include "gdbus.h"
+#include "debug.h"
+
+static dbus_int32_t connection_slot = -1;
+
+typedef struct {
+       DBusConnection *connection;
+       GMainContext *context;
+       GSource *queue;
+} ConnectionData;
+
+typedef struct {
+       DBusWatch *watch;
+       GSource *source;
+} WatchData;
+
+typedef struct {
+       DBusTimeout *timeout;
+       guint id;
+} TimeoutData;
+
+typedef struct {
+       GSource source;
+       DBusConnection *connection;
+} QueueData;
+
+static GSList *watches = NULL;
+static GSList *timeouts = NULL;
+
+static gboolean queue_prepare(GSource *source, gint *timeout)
+{
+       DBusConnection *connection = ((QueueData *) source)->connection;
+
+       DBG("source %p", source);
+
+       *timeout = -1;
+
+       return (dbus_connection_get_dispatch_status(connection) ==
+                                               DBUS_DISPATCH_DATA_REMAINS);
+}
+
+static gboolean queue_check(GSource *source)
+{
+       DBG("source %p", source);
+
+       return FALSE;
+}
+
+static gboolean queue_dispatch(GSource *source, GSourceFunc callback,
+                                                       gpointer user_data)
+{
+       DBusConnection *connection = ((QueueData *) source)->connection;
+
+       DBG("source %p", source);
+
+       dbus_connection_ref(connection);
+
+       dbus_connection_dispatch(connection);
+
+       dbus_connection_unref(connection);
+
+       return TRUE;
+}
+
+static GSourceFuncs queue_funcs = {
+       queue_prepare,
+       queue_check,
+       queue_dispatch,
+       NULL
+};
+
+static gboolean dispatch_watch(GIOChannel *source,
+                               GIOCondition condition, gpointer user_data)
+{
+       WatchData *data = user_data;
+       unsigned int flags = 0;
+
+       DBG("source %p condition %d watch data %p", source, condition, data);
+
+       if (condition & G_IO_IN)
+               flags |= DBUS_WATCH_READABLE;
+
+       if (condition & G_IO_OUT)
+               flags |= DBUS_WATCH_WRITABLE;
+
+       if (condition & G_IO_ERR)
+               flags |= DBUS_WATCH_ERROR;
+
+       if (condition & G_IO_HUP)
+               flags |= DBUS_WATCH_HANGUP;
+
+       dbus_watch_handle(data->watch, flags);
+
+       return TRUE;
+}
+
+static void finalize_watch(gpointer memory)
+{
+       WatchData *watch_data = memory;
+
+       DBG("watch data %p", watch_data);
+
+       if (watch_data->watch)
+               dbus_watch_set_data(watch_data->watch, NULL, NULL);
+
+       g_free(watch_data);
+}
+
+static void free_watch(void *memory)
+{
+       WatchData *watch_data = memory;
+
+       DBG("watch data %p", watch_data);
+
+       if (watch_data->source == NULL)
+               return;
+
+       watches = g_slist_remove(watches, watch_data);
+
+       g_source_destroy(watch_data->source);
+       g_source_unref(watch_data->source);
+}
+
+static dbus_bool_t add_watch(DBusWatch *watch, void *user_data)
+{
+       ConnectionData *data = user_data;
+       GIOCondition condition = G_IO_ERR | G_IO_HUP;
+       GIOChannel *channel;
+       GSource *source;
+       WatchData *watch_data;
+       unsigned int flags;
+       int fd;
+
+       DBG("watch %p connection data %p", watch, data);
+
+       if (dbus_watch_get_enabled(watch) == FALSE)
+               return TRUE;
+
+       flags = dbus_watch_get_flags(watch);
+
+       if (flags & DBUS_WATCH_READABLE)
+               condition |= G_IO_IN;
+
+       if (flags & DBUS_WATCH_WRITABLE)
+               condition |= G_IO_OUT;
+
+       fd = dbus_watch_get_unix_fd(watch);
+
+       DBG("flags %d fd %d", flags, fd);
+
+       watch_data = g_new0(WatchData, 1);
+
+       channel = g_io_channel_unix_new(fd);
+
+       source = g_io_create_watch(channel, condition);
+
+       watch_data->watch = watch;
+       watch_data->source = source;
+
+       g_source_set_callback(source, (GSourceFunc) dispatch_watch,
+                                               watch_data, finalize_watch);
+
+       g_source_attach(source, data->context);
+
+       watches = g_slist_prepend(watches, watch_data);
+
+       dbus_watch_set_data(watch, watch_data, free_watch);
+
+       g_io_channel_unref(channel);
+
+       DBG("watch data %p", watch_data);
+
+       return TRUE;
+}
+
+static void remove_watch(DBusWatch *watch, void *user_data)
+{
+       WatchData *watch_data = dbus_watch_get_data(watch);
+
+       DBG("watch %p connection data %p", watch, user_data);
+
+       dbus_watch_set_data(watch, NULL, NULL);
+
+       if (watch_data == NULL)
+               return;
+
+       watches = g_slist_remove(watches, watch_data);
+
+       g_source_destroy(watch_data->source);
+       g_source_unref(watch_data->source);
+}
+
+static void watch_toggled(DBusWatch *watch, void *user_data)
+{
+       DBG("watch %p connection data %p", watch, user_data);
+
+       if (dbus_watch_get_enabled(watch) == TRUE)
+               add_watch(watch, user_data);
+       else
+               remove_watch(watch, user_data);
+}
+
+static gboolean dispatch_timeout(gpointer user_data)
+{
+       TimeoutData *timeout_data = user_data;
+
+       DBG("timeout data %p", timeout_data);
+
+       dbus_timeout_handle(timeout_data->timeout);
+
+       return FALSE;
+}
+
+static void free_timeout(void *memory)
+{
+       TimeoutData *timeout_data = memory;
+
+       DBG("timeout data %p", timeout_data);
+
+       if (timeout_data->id > 0)
+               g_source_remove(timeout_data->id);
+
+       g_free(timeout_data);
+}
+
+static dbus_bool_t add_timeout(DBusTimeout *timeout, void *user_data)
+{
+       TimeoutData *timeout_data;
+
+       DBG("timeout %p connection data %p", timeout, user_data);
+
+       if (dbus_timeout_get_enabled(timeout) == FALSE)
+               return TRUE;
+
+       timeout_data = g_new0(TimeoutData, 1);
+
+       timeout_data->timeout = timeout;
+
+       timeout_data->id = g_timeout_add(dbus_timeout_get_interval(timeout),
+                                       dispatch_timeout, timeout_data);
+
+       timeouts = g_slist_prepend(timeouts, timeout_data);
+
+       dbus_timeout_set_data(timeout, timeout_data, free_timeout);
+
+       DBG("timeout data %p", timeout_data);
+
+       return TRUE;
+}
+
+static void remove_timeout(DBusTimeout *timeout, void *user_data)
+{
+       TimeoutData *timeout_data = dbus_timeout_get_data(timeout);
+
+       DBG("timeout %p connection data %p", timeout, user_data);
+
+       if (timeout_data == NULL)
+               return;
+
+       timeouts = g_slist_remove(timeouts, timeout_data);
+
+       if (timeout_data->id > 0)
+               g_source_remove(timeout_data->id);
+
+       timeout_data->id = 0;
+}
+
+static void timeout_toggled(DBusTimeout *timeout, void *user_data)
+{
+       DBG("timeout %p connection data %p", timeout, user_data);
+
+       if (dbus_timeout_get_enabled(timeout) == TRUE)
+               add_timeout(timeout, user_data);
+       else
+               remove_timeout(timeout, user_data);
+}
+
+static void wakeup_context(void *user_data)
+{
+       ConnectionData *data = user_data;
+
+       DBG("connection data %p", data);
+
+       g_main_context_wakeup(data->context);
+}
+
+static ConnectionData *setup_connection(DBusConnection *connection,
+                                               GMainContext *context)
+{
+       ConnectionData *data;
+
+       DBG("connection %p context %p", connection, context);
+
+       data = g_new0(ConnectionData, 1);
+
+       data->context = g_main_context_ref(context);
+
+       DBG("connection data %p", data);
+
+       if (connection == NULL)
+               return data;
+
+       data->connection = connection;
+
+       data->queue = g_source_new(&queue_funcs, sizeof(QueueData));
+
+       ((QueueData *) data->queue)->connection = connection;
+
+       g_source_attach(data->queue, context);
+
+       return data;
+}
+
+static void free_connection(void *memory)
+{
+       ConnectionData *data = memory;
+
+       DBG("connection data %p", data);
+
+       g_dbus_remove_all_watches(data->connection);
+
+       //g_dbus_unregister_all_objects(data->connection);
+
+       dbus_connection_unref(data->connection);
+
+       g_main_context_unref(data->context);
+
+       g_free(data);
+}
+
+/**
+ * g_dbus_setup_connection:
+ * @connection: a #DBusConnection
+ * @context: a #GMainContext or #NULL for default context
+ *
+ * Setup connection with main context
+ *
+ * Sets the watch and timeout functions of a #DBusConnection
+ * to integrate the connection with the GLib main loop.
+ * Pass in #NULL for the #GMainContext unless you're
+ * doing something specialized.
+ */
+void g_dbus_setup_connection(DBusConnection *connection,
+                                               GMainContext *context)
+{
+       ConnectionData *data;
+
+       DBG("connection %p context %p", connection, context);
+
+       if (dbus_connection_allocate_data_slot(&connection_slot) == FALSE)
+               return;
+
+       DBG("connection slot %d", connection_slot);
+
+       data = dbus_connection_get_data(connection, connection_slot);
+       if (data != NULL)
+               return;
+
+       dbus_connection_set_exit_on_disconnect(connection, TRUE);
+
+       if (context == NULL)
+               context = g_main_context_default();
+
+       data = setup_connection(connection, context);
+       if (data == NULL)
+               return;
+
+       if (dbus_connection_set_data(connection, connection_slot,
+                                       data, free_connection) == FALSE) {
+               g_free(data);
+               return;
+       }
+
+       dbus_connection_set_watch_functions(connection, add_watch,
+                               remove_watch, watch_toggled, data, NULL);
+
+       dbus_connection_set_timeout_functions(connection, add_timeout,
+                               remove_timeout, timeout_toggled, data, NULL);
+
+       dbus_connection_set_wakeup_main_function(connection,
+                                               wakeup_context, data, NULL);
+}
+
+/**
+ * g_dbus_cleanup_connection:
+ * @connection: a #DBusConnection
+ *
+ * Cleanup the setup of DBusConnection and free the
+ * allocated memory.
+ */
+void g_dbus_cleanup_connection(DBusConnection *connection)
+{
+       DBG("connection %p slot %d", connection, connection_slot);
+
+       if (connection_slot < 0)
+               return;
+
+       dbus_connection_set_data(connection, connection_slot, NULL, NULL);
+
+       dbus_connection_free_data_slot(&connection_slot);
+
+       DBG("connection slot %d", connection_slot);
+}
+
+/**
+ * g_dbus_setup_bus:
+ * @type: a #DBusBusType
+ * @name: well known name
+ * @error: a #DBusError
+ *
+ * Connect to bus and setup connection
+ *
+ * Returns a connection to the given bus and requests a
+ * well known name for it. Sets the watch and timeout
+ * functions for it.
+ *
+ * Returns: newly setup #DBusConnection
+ */
+DBusConnection *g_dbus_setup_bus(DBusBusType type, const char *name,
+                                                       DBusError *error)
+{
+       DBusConnection *connection;
+
+       DBG("type %d name %s error %p", type, name, error);
+
+       connection = dbus_bus_get(type, error);
+
+       if (error != NULL) {
+               if (dbus_error_is_set(error) == TRUE)
+                       return NULL;
+       }
+
+       if (connection == NULL)
+               return NULL;
+
+       if (name != NULL) {
+               if (dbus_bus_request_name(connection, name,
+                               DBUS_NAME_FLAG_DO_NOT_QUEUE, error) !=
+                               DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER ) {
+                       dbus_connection_unref(connection);
+                       return NULL;
+               }
+
+               if (error != NULL) {
+                       if (dbus_error_is_set(error) == TRUE) {
+                               dbus_connection_unref(connection);
+                               return NULL;
+                       }
+               }
+       }
+
+       g_dbus_setup_connection(connection, NULL);
+
+       return connection;
+}
+
+/**
+ * g_dbus_setup_address:
+ * @address: bus address
+ * @error: a #DBusError
+ *
+ * Connect to bus and setup connection
+ *
+ * Returns a connection to the bus specified via
+ * the given address and sets the watch and timeout
+ * functions for it.
+ *
+ * Returns: newly setup #DBusConnection
+ */
+DBusConnection *g_dbus_setup_address(const char *address, DBusError *error)
+{
+       DBusConnection *connection;
+
+       DBG("address %s error %p", address, error);
+
+       connection = dbus_connection_open(address, error);
+
+       if (error != NULL) {
+               if (dbus_error_is_set(error) == TRUE)
+                       return NULL;
+       }
+
+       if (connection == NULL)
+               return NULL;
+
+       g_dbus_setup_connection(connection, NULL);
+
+       return connection;
+}
+
+/**
+ * g_dbus_request_name:
+ * @connection: a #DBusConnection
+ * @name: well known name
+ * @error: a #DBusError
+ *
+ * Requests a well known name for connection.
+ *
+ * Returns: #TRUE on success
+ */
+gboolean g_dbus_request_name(DBusConnection *connection, const char *name,
+                                                       DBusError *error)
+{
+       DBG("connection %p name %s error %p", connection, name, error);
+
+       if (name == NULL)
+               return FALSE;
+
+       if (dbus_bus_request_name(connection, name,
+                       DBUS_NAME_FLAG_DO_NOT_QUEUE, error) !=
+                               DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER )
+               return FALSE;
+
+       if (error != NULL) {
+               if (dbus_error_is_set(error) == TRUE)
+                       return FALSE;
+       }
+
+       return TRUE;
+}
+
+static DBusHandlerResult disconnect_filter(DBusConnection *connection,
+                                       DBusMessage *message, void *data)
+{
+       if (dbus_message_is_signal(message,
+                       DBUS_INTERFACE_LOCAL, "Disconnected") == FALSE)
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+       DBG("disconnected");
+
+       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+/**
+ * g_dbus_set_disconnect_function:
+ * @connection: a #DBusConnection
+ * @function: a #GDBusWatchFunction
+ * @user_data: user data to pass to the function
+ * @destroy: a #GDBusDestroyFunction
+ *
+ * Set a callback function that will be called when the
+ * D-Bus message bus exits.
+ *
+ * Returns: #TRUE on success
+ */
+gboolean g_dbus_set_disconnect_function(DBusConnection *connection,
+                               GDBusWatchFunction function,
+                               void *user_data, GDBusDestroyFunction destroy)
+{
+       dbus_connection_set_exit_on_disconnect(connection, FALSE);
+
+       if (dbus_connection_add_filter(connection,
+                               disconnect_filter, NULL, NULL) == FALSE)
+               return FALSE;
+
+       return TRUE;
+}
diff --git a/src/gdbus/object.c b/src/gdbus/object.c
new file mode 100644 (file)
index 0000000..f35ac31
--- /dev/null
@@ -0,0 +1,1409 @@
+/*
+ *
+ *  Library for simple D-Bus integration with GLib
+ *
+ *  Copyright (C) 2007-2008  Intel Corporation. All rights reserved.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License version 2.1 as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <dbus/dbus.h>
+
+#include "gdbus.h"
+#include "debug.h"
+
+static dbus_int32_t connection_slot = -1;
+
+typedef struct {
+       GStaticMutex mutex;
+       GSList *objects;
+} ConnectionData;
+
+typedef struct {
+       gint refcount;
+       char *path;
+       GStaticMutex mutex;
+       GSList *interfaces;
+       char *introspect;
+} ObjectData;
+
+typedef struct {
+       char *name;
+       GDBusMethodTable *methods;
+       GDBusSignalTable *signals;
+       GDBusPropertyTable *properties;
+       void *user_data;
+       GDBusDestroyFunction destroy;
+} InterfaceData;
+
+static InterfaceData *find_interface(GSList *interfaces, const char *name)
+{
+       GSList *list;
+
+       for (list = interfaces; list; list = list->next) {
+               InterfaceData *interface = list->data;
+
+               if (strcmp(name, interface->name) == 0)
+                       return interface;
+       }
+
+       return NULL;
+}
+
+static ObjectData *find_object(GSList *objects, const char *path)
+{
+       GSList *list;
+
+       for (list = objects; list; list = list->next) {
+               ObjectData *object = list->data;
+
+               if (strcmp(path, object->path) == 0)
+                       return object;
+       }
+
+       return NULL;
+}
+
+static GDBusPropertyTable *find_property(InterfaceData *interface,
+                                                       const char *name)
+{
+       GDBusPropertyTable *property;
+
+       if (interface == NULL)
+               return NULL;
+
+       for (property = interface->properties; property->name; property++)
+               if (strcmp(property->name, name) == 0)
+                       return property;
+
+       return NULL;
+}
+
+static void add_arguments(GString *xml, const char *direction,
+                                               const char *signature)
+{
+       DBusSignatureIter iter;
+
+       dbus_signature_iter_init(&iter, signature);
+
+       if (dbus_signature_iter_get_current_type(&iter) == DBUS_TYPE_INVALID)
+               return;
+
+       do {
+               g_string_append_printf(xml, "\t\t\t<arg type=\"%s\"",
+                               dbus_signature_iter_get_signature(&iter));
+
+               if (direction != NULL)
+                       g_string_append_printf(xml, " direction=\"%s\"/>\n",
+                                                               direction);
+               else
+                       g_string_append(xml, "/>\n");
+       } while (dbus_signature_iter_next(&iter) == TRUE);
+}
+
+static inline void add_annotation(GString *xml, const char *name)
+{
+       g_string_append_printf(xml,
+               "\t\t\t<annotation name=\"%s\" value=\"true\"/>\n", name);
+}
+
+static inline void add_methods(GString *xml, GDBusMethodTable *methods)
+{
+       GDBusMethodTable *method;
+
+       for (method = methods; method && method->name; method++) {
+               g_string_append_printf(xml, "\t\t<method name=\"%s\">\n",
+                                                               method->name);
+
+               add_arguments(xml, "in", method->signature);
+               add_arguments(xml, "out", method->reply);
+
+               if (method->flags & G_DBUS_METHOD_FLAG_DEPRECATED)
+                       add_annotation(xml, "org.freedesktop.DBus.Deprecated");
+
+               if (method->flags & G_DBUS_METHOD_FLAG_NOREPLY)
+                       add_annotation(xml, "org.freedesktop.DBus.Method.NoReply");
+
+               g_string_append(xml, "\t\t</method>\n");
+       }
+}
+
+static inline void add_signals(GString *xml, GDBusSignalTable *signals)
+{
+       GDBusSignalTable *signal;
+
+       for (signal = signals; signal && signal->name; signal++) {
+               g_string_append_printf(xml, "\t\t<signal name=\"%s\">\n",
+                                                               signal->name);
+
+               add_arguments(xml, NULL, signal->signature);
+
+               if (signal->flags & G_DBUS_SIGNAL_FLAG_DEPRECATED)
+                       add_annotation(xml, "org.freedesktop.DBus.Deprecated");
+
+               g_string_append(xml, "\t\t</signal>\n");
+       }
+}
+
+static inline void add_properties(GString *xml, GDBusPropertyTable *properties)
+{
+       GDBusPropertyTable *property;
+
+       for (property = properties; property && property->name; property++) {
+               const char *access;
+
+               if (property->type == NULL)
+                       continue;
+
+               if (property->get == NULL && property->set == NULL)
+                       continue;
+
+               if (property->get != NULL) {
+                       if (property->set == NULL)
+                               access = "read";
+                       else
+                               access = "readwrite";
+               } else
+                       access = "write";
+
+               g_string_append_printf(xml,
+                       "\t\t<property name=\"%s\" type=\"%s\" access=\"%s\">\n",
+                                       property->name, property->type, access);
+
+               if (property->flags & G_DBUS_PROPERTY_FLAG_DEPRECATED)
+                       add_annotation(xml, "org.freedesktop.DBus.Deprecated");
+
+               g_string_append(xml, "\t\t</property>\n");
+       }
+}
+
+static char *generate_introspect(DBusConnection *connection,
+                                       const char *path, ObjectData *data)
+{
+       GString *xml;
+       GSList *list;
+       char **children;
+       int i;
+
+       DBG("connection %p path %s", connection, path);
+
+       xml = g_string_new(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE);
+
+       g_string_append_printf(xml, "<node name=\"%s\">\n", path);
+
+       g_string_append_printf(xml, "\t<interface name=\"%s\">\n",
+                                       DBUS_INTERFACE_INTROSPECTABLE);
+
+       g_string_append(xml, "\t\t<method name=\"Introspect\">\n");
+       add_arguments(xml, "out", "s");
+       g_string_append(xml, "\t\t</method>\n");
+
+       g_string_append(xml, "\t</interface>\n");
+
+       g_string_append_printf(xml, "\t<interface name=\"%s\">\n",
+                                               DBUS_INTERFACE_PROPERTIES);
+
+       g_string_append(xml, "\t\t<method name=\"Get\">\n");
+       add_arguments(xml, "in", "ss");
+       add_arguments(xml, "out", "v");
+       g_string_append(xml, "\t\t</method>\n");
+
+       g_string_append(xml, "\t\t<method name=\"Set\">\n");
+       add_arguments(xml, "in", "ssv");
+       g_string_append(xml, "\t\t</method>\n");
+
+       g_string_append(xml, "\t\t<method name=\"GetAll\">\n");
+       add_arguments(xml, "in", "s");
+       add_arguments(xml, "out", "a{sv}");
+       g_string_append(xml, "\t\t</method>\n");
+
+       g_string_append(xml, "\t</interface>\n");
+
+       for (list = data->interfaces; list; list = list->next) {
+               InterfaceData *interface = list->data;
+
+               g_string_append_printf(xml, "\t<interface name=\"%s\">\n",
+                                                       interface->name);
+
+               add_methods(xml, interface->methods);
+               add_signals(xml, interface->signals);
+               add_properties(xml, interface->properties);
+
+               g_string_append(xml, "\t</interface>\n");
+       }
+
+       if (dbus_connection_list_registered(connection,
+                                               path, &children) == FALSE)
+               goto done;
+
+       for (i = 0; children[i]; i++)
+               g_string_append_printf(xml, "\t<node name=\"%s\"/>\n",
+                                                               children[i]);
+
+       dbus_free_string_array(children);
+
+done:
+       g_string_append(xml, "</node>\n");
+
+       return g_string_free(xml, FALSE);
+}
+
+static void update_parent(DBusConnection *connection, const char *path)
+{
+       ObjectData *data;
+       char *parent;
+
+       DBG("connection %p path %s", connection, path);
+
+       if (strlen(path) < 2 || path[0] != '/')
+               return;
+
+       parent = g_path_get_dirname(path);
+       if (parent == NULL)
+               return;
+
+       if (dbus_connection_get_object_path_data(connection,
+                                       parent, (void *) &data) == FALSE) {
+               update_parent(connection, parent);
+               goto done;
+       }
+
+       if (data == NULL) {
+               update_parent(connection, parent);
+               goto done;
+       }
+
+       g_free(data->introspect);
+       data->introspect = generate_introspect(connection, parent, data);
+
+done:
+       g_free(parent);
+}
+
+static DBusHandlerResult send_message(DBusConnection *connection,
+                                               DBusMessage *message)
+{
+       dbus_bool_t result;
+
+       result = dbus_connection_send(connection, message, NULL);
+
+       dbus_message_unref(message);
+
+       if (result == FALSE)
+               return DBUS_HANDLER_RESULT_NEED_MEMORY;
+
+       return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult send_error(DBusConnection *connection,
+                                       DBusMessage *message,
+                                       const char *name, const char *text)
+{
+       DBusMessage *error;
+
+       error = dbus_message_new_error(message, name, text);
+       if (error == NULL)
+               return DBUS_HANDLER_RESULT_NEED_MEMORY;
+
+       return send_message(connection, error);
+}
+
+static DBusHandlerResult introspect(DBusConnection *connection,
+                               DBusMessage *message, ObjectData *data)
+{
+       DBusMessage *reply;
+
+       DBG("connection %p message %p object data %p",
+                                       connection, message, data);
+
+       if (data->introspect == NULL)
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+       if (dbus_message_has_signature(message,
+                               DBUS_TYPE_INVALID_AS_STRING) == FALSE)
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+       reply = dbus_message_new_method_return(message);
+       if (reply == NULL)
+               return DBUS_HANDLER_RESULT_NEED_MEMORY;
+
+       dbus_message_append_args(reply,
+               DBUS_TYPE_STRING, &data->introspect, DBUS_TYPE_INVALID);
+
+       return send_message(connection, reply);
+}
+
+static DBusHandlerResult properties_get(DBusConnection *connection,
+                               DBusMessage *message, ObjectData *data)
+{
+       DBusMessage *reply;
+       GDBusPropertyTable *property;
+       DBusMessageIter iter, value;
+       dbus_bool_t result;
+       const char *interface, *name;
+       InterfaceData *iface;
+
+       DBG("connection %p message %p object data %p",
+                                       connection, message, data);
+
+       if (dbus_message_has_signature(message,
+                       DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_STRING_AS_STRING
+                               DBUS_TYPE_INVALID_AS_STRING) == FALSE)
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+       dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &interface,
+                               DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID);
+
+       DBG("interface %s name %s", interface, name);
+
+       iface = find_interface(data->interfaces, interface);
+       property = find_property(iface, name);
+       if (property == NULL)
+               return send_error(connection, message,
+                               DBUS_ERROR_BAD_ADDRESS, "Property not found");
+
+       if (property->get == NULL)
+               return send_error(connection, message,
+                                       DBUS_ERROR_ACCESS_DENIED,
+                                       "Reading of property not allowed");
+
+       reply = dbus_message_new_method_return(message);
+       if (reply == NULL)
+               return DBUS_HANDLER_RESULT_NEED_MEMORY;
+
+       dbus_message_iter_init_append(reply, &iter);
+
+       dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
+                                               property->type, &value);
+
+       result = property->get(connection, &value, iface->user_data);
+
+       dbus_message_iter_close_container(&iter, &value);
+
+       if (result == FALSE) {
+               dbus_message_unref(reply);
+               return send_error(connection, message, DBUS_ERROR_FAILED,
+                                               "Reading of property failed");
+       }
+
+       return send_message(connection, reply);
+}
+
+static DBusHandlerResult properties_set(DBusConnection *connection,
+                               DBusMessage *message, ObjectData *data)
+{
+       DBusMessage *reply;
+       GDBusPropertyTable *property;
+       DBusMessageIter iter, value;
+       const char *interface, *name;
+       InterfaceData *iface;
+
+       DBG("connection %p message %p object data %p",
+                                       connection, message, data);
+
+       if (dbus_message_has_signature(message, DBUS_TYPE_STRING_AS_STRING
+                       DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
+                                       DBUS_TYPE_INVALID_AS_STRING) == FALSE)
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+       dbus_message_iter_init(message, &iter);
+
+       dbus_message_iter_get_basic(&iter, &interface);
+       dbus_message_iter_next(&iter);
+
+       dbus_message_iter_get_basic(&iter, &name);
+       dbus_message_iter_next(&iter);
+
+       dbus_message_iter_recurse(&iter, &value);
+
+       DBG("interface %s name %s", interface, name);
+
+       iface = find_interface(data->interfaces, interface);
+       property = find_property(iface, name);
+       if (property == NULL)
+               return send_error(connection, message,
+                               DBUS_ERROR_BAD_ADDRESS, "Property not found");
+
+       if (property->set == NULL)
+               return send_error(connection, message,
+                                       DBUS_ERROR_ACCESS_DENIED,
+                                       "Writing to property not allowed");
+
+       reply = dbus_message_new_method_return(message);
+       if (reply == NULL)
+               return DBUS_HANDLER_RESULT_NEED_MEMORY;
+
+       dbus_message_append_args(reply, DBUS_TYPE_INVALID);
+
+       if (property->set(connection, &value, iface->user_data) == FALSE) {
+               dbus_message_unref(reply);
+               return send_error(connection, message, DBUS_ERROR_FAILED,
+                                               "Writing to property failed");
+       }
+
+       return send_message(connection, reply);
+}
+
+static inline void append_message(DBusMessageIter *value, DBusMessage *message)
+{
+       DBusMessageIter iter, temp;
+
+       dbus_message_iter_init(message, &temp);
+       dbus_message_iter_recurse(&temp, &iter);
+
+       do {
+               int type = dbus_message_iter_get_arg_type(&iter);
+               void *data;
+
+               dbus_message_iter_get_basic(&iter, &data);
+               dbus_message_iter_append_basic(value, type, &data);
+       } while (dbus_message_iter_next(&iter) == TRUE);
+}
+
+static void do_getall(DBusConnection *connection, DBusMessageIter *iter,
+                               InterfaceData *interface, ObjectData *data)
+{
+       GDBusPropertyTable *property;
+
+       if (interface == NULL)
+               return;
+
+       for (property = interface->properties; property->name; property++) {
+               DBusMessage *message;
+               DBusMessageIter entry, value;
+               dbus_bool_t result;
+
+               if (property->get == NULL)
+                       continue;
+
+               message = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN);
+               if (message == NULL)
+                       continue;
+
+               dbus_message_iter_init_append(message, &entry);
+
+               dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
+                                               property->type, &value);
+
+               result = property->get(connection, &value, interface->user_data);
+
+               dbus_message_iter_close_container(&entry, &value);
+
+               if (result == TRUE) {
+                       dbus_message_iter_open_container(iter,
+                                       DBUS_TYPE_DICT_ENTRY, NULL, &entry);
+
+                       dbus_message_iter_append_basic(&entry,
+                                       DBUS_TYPE_STRING, &property->name);
+
+                       dbus_message_iter_open_container(&entry,
+                                               DBUS_TYPE_VARIANT,
+                                               property->type, &value);
+
+                       append_message(&value, message);
+
+                       dbus_message_iter_close_container(&entry, &value);
+
+                       dbus_message_iter_close_container(iter, &entry);
+               }
+
+               dbus_message_unref(message);
+       }
+}
+
+static DBusHandlerResult properties_getall(DBusConnection *connection,
+                               DBusMessage *message, ObjectData *data)
+{
+       DBusMessage *reply;
+       DBusMessageIter iter, dict;
+       const char *interface;
+
+       DBG("connection %p message %p object data %p",
+                                       connection, message, data);
+
+       if (dbus_message_has_signature(message, DBUS_TYPE_STRING_AS_STRING
+                                       DBUS_TYPE_INVALID_AS_STRING) == FALSE)
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+       dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &interface,
+                                                       DBUS_TYPE_INVALID);
+
+       DBG("interface %s", interface);
+
+       reply = dbus_message_new_method_return(message);
+       if (reply == NULL)
+               return DBUS_HANDLER_RESULT_NEED_MEMORY;
+
+       dbus_message_iter_init_append(reply, &iter);
+
+       dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+                       DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+                       DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
+                       DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
+
+       do_getall(connection, &dict,
+                       find_interface(data->interfaces, interface), data);
+
+       dbus_message_iter_close_container(&iter, &dict);
+
+       return send_message(connection, reply);
+}
+
+static DBusHandlerResult handle_message(DBusConnection *connection,
+                                       DBusMessage *message, void *user_data)
+{
+       ObjectData *data = user_data;
+       InterfaceData *interface;
+       GDBusMethodTable *method;
+
+       DBG("object data %p", data);
+
+       if (dbus_message_is_method_call(message,
+                       DBUS_INTERFACE_INTROSPECTABLE, "Introspect") == TRUE)
+               return introspect(connection, message, data);
+
+       if (dbus_message_is_method_call(message,
+                               DBUS_INTERFACE_PROPERTIES, "Get") == TRUE)
+               return properties_get(connection, message, data);
+
+       if (dbus_message_is_method_call(message,
+                               DBUS_INTERFACE_PROPERTIES, "Set") == TRUE)
+               return properties_set(connection, message, data);
+
+       if (dbus_message_is_method_call(message,
+                               DBUS_INTERFACE_PROPERTIES, "GetAll") == TRUE)
+               return properties_getall(connection, message, data);
+
+       interface = find_interface(data->interfaces,
+                                       dbus_message_get_interface(message));
+       if (interface == NULL)
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+       DBG("interface data %p name %s", interface, interface->name);
+
+       for (method = interface->methods;
+                               method->name && method->function; method++) {
+               DBusMessage *reply;
+
+               if (dbus_message_is_method_call(message,
+                               interface->name, method->name) == FALSE)
+                       continue;
+
+               if (dbus_message_has_signature(message,
+                                       method->signature) == FALSE)
+                       continue;
+
+               reply = method->function(connection,
+                                               message,
+                                               (method->flags & 
+                                                G_DBUS_METHOD_FLAG_METHOD_DATA) ?
+                                               method->method_data :
+                                               interface->user_data);
+
+               if (method->flags & G_DBUS_METHOD_FLAG_NOREPLY) {
+                       if (reply != NULL)
+                               dbus_message_unref(reply);
+                       return DBUS_HANDLER_RESULT_HANDLED;
+               }
+
+               if (method->flags & G_DBUS_METHOD_FLAG_ASYNC) {
+                       if (reply == NULL)
+                               return DBUS_HANDLER_RESULT_HANDLED;
+               }
+
+               if (reply == NULL)
+                       return DBUS_HANDLER_RESULT_NEED_MEMORY;
+
+               return send_message(connection, reply);
+       }
+
+       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static void handle_unregister(DBusConnection *connection, void *user_data)
+{
+       ObjectData *data = user_data;
+       GSList *list;
+
+       DBG("object data %p path %s", data, data->path);
+
+       g_free(data->path);
+
+       for (list = data->interfaces; list; list = list->next) {
+               InterfaceData *interface = list->data;
+
+               DBG("interface data %p name %s", interface, interface->name);
+
+               if (interface->destroy)
+                       interface->destroy(interface->user_data);
+
+               g_free(interface->name);
+               g_free(interface);
+       }
+
+       g_slist_free(data->interfaces);
+
+       g_free(data->introspect);
+       g_free(data);
+}
+
+static DBusObjectPathVTable object_table = {
+       .unregister_function = handle_unregister,
+       .message_function    = handle_message,
+};
+
+/**
+ * g_dbus_register_object:
+ * @connection: the connection
+ * @path: object path
+ *
+ * Registers a path in the object hierarchy.
+ *
+ * Returns: #TRUE on success
+ */
+static gboolean g_dbus_register_object(DBusConnection *connection,
+                                                       const char *path)
+{
+       ConnectionData *data;
+       ObjectData *object;
+
+       DBG("connection %p path %s", connection, path);
+
+       if (dbus_connection_allocate_data_slot(&connection_slot) == FALSE)
+               return FALSE;
+
+       DBG("connection slot %d", connection_slot);
+
+       data = dbus_connection_get_data(connection, connection_slot);
+       if (data == NULL) {
+               data = g_try_new0(ConnectionData, 1);
+               if (data == NULL) {
+                       dbus_connection_free_data_slot(&connection_slot);
+                       return 0;
+               }
+
+               g_static_mutex_init(&data->mutex);
+
+               if (dbus_connection_set_data(connection, connection_slot,
+                                                       data, NULL) == FALSE) {
+                       dbus_connection_free_data_slot(&connection_slot);
+                       g_free(data);
+                       return 0;
+               }
+       }
+
+       DBG("connection data %p", data);
+
+       g_static_mutex_lock(&data->mutex);
+
+       object = find_object(data->objects, path);
+
+       if (!object) {
+               object = g_new0(ObjectData, 1);
+               g_static_mutex_init(&object->mutex);
+               object->path = g_strdup(path);
+               object->interfaces = NULL;
+               object->refcount = 0;
+               object->introspect = generate_introspect(connection, path, object);
+               if (dbus_connection_register_object_path(connection, path,
+                                               &object_table, object) == FALSE) {
+                       g_free(object->introspect);
+                       g_free(object);
+                       return FALSE;
+               }
+
+               data->objects = g_slist_append(data->objects, object);
+        }
+
+       object->refcount++;
+
+       g_static_mutex_unlock(&data->mutex);
+
+       DBG("object data %p", object);
+
+       update_parent(connection, path);
+
+       return TRUE;
+}
+
+/**
+ * g_dbus_unregister_object:
+ * @connection: the connection
+ * @path: object path
+ *
+ * Unregister the given path in the object hierarchy and
+ * free the assigned data structures.
+ *
+ * Returns: #TRUE on success
+ */
+static gboolean g_dbus_unregister_object(DBusConnection *connection,
+                                                       const char *path)
+{
+       ConnectionData *data;
+       ObjectData *object;
+       gboolean result = TRUE;
+
+
+       DBG("connection %p path %s", connection, path);
+
+       data = dbus_connection_get_data(connection, connection_slot);
+       if (data == NULL)
+               return FALSE;
+
+       if (dbus_connection_get_object_path_data(connection,
+                                       path, (void *) &object) == FALSE)
+               return FALSE;
+
+       if (object == NULL)
+               return FALSE;
+
+       g_static_mutex_lock(&data->mutex);
+
+       object->refcount--;
+       if (!object->refcount) {
+               result = dbus_connection_unregister_object_path(connection, path);
+               data->objects = g_slist_remove(data->objects, object);
+               if (!data->objects)
+                       dbus_connection_set_data(connection, connection_slot, NULL, NULL);
+        }
+
+       g_static_mutex_unlock(&data->mutex);
+
+       dbus_connection_free_data_slot(&connection_slot);
+
+       DBG("connection slot %d", connection_slot);
+
+       if (!data->objects) {
+               g_static_mutex_free(&data->mutex);
+               g_free(data);
+       }
+
+       update_parent(connection, path);
+
+       return result;
+}
+
+#if 0
+/**
+ * g_dbus_unregister_object_hierarchy:
+ * @connection: the connection
+ * @path: object path
+ *
+ * Unregister the given path and all subpaths in the
+ * object hierarchy and free all assigned data strcutures.
+ *
+ * Returns: #TRUE on success
+ */
+static gboolean g_dbus_unregister_object_hierarchy(DBusConnection *connection,
+                                                       const char *path)
+{
+       ConnectionData *data;
+       ObjectData *object;
+       GSList *list;
+       size_t pathlen;
+       dbus_bool_t result;
+
+       DBG("connection %p path %s", connection, path);
+
+       data = dbus_connection_get_data(connection, connection_slot);
+       if (data == NULL)
+               return FALSE;
+
+       if (dbus_connection_get_object_path_data(connection,
+                                       path, (void *) &object) == FALSE)
+               return FALSE;
+
+       if (object == NULL)
+               return FALSE;
+
+       pathlen = strlen(path);
+
+       g_static_mutex_lock(&data->mutex);
+
+       for (list = data->objects; list; list = list->next) {
+               ObjectData *object = list->data;
+
+               if (strlen(object->path) <= pathlen)
+                       continue;
+
+               if (strncmp(object->path, path, pathlen) != 0)
+                       continue;
+
+               DBG("object data %p path %s", object, object->path);
+
+               data->objects = g_slist_remove(data->objects, object);
+
+               dbus_connection_unregister_object_path(connection,
+                                                       object->path);
+
+               dbus_connection_free_data_slot(&connection_slot);
+
+               DBG("connection slot %d", connection_slot);
+       }
+
+       g_static_mutex_unlock(&data->mutex);
+
+       result = g_dbus_unregister_object(connection, path);
+       if (result == FALSE)
+               return FALSE;
+
+       update_parent(connection, path);
+
+       return TRUE;
+}
+
+/**
+ * g_dbus_unregister_all_objects:
+ * @connection: the connection
+ *
+ * Unregister the all paths in the object hierarchy.
+ */
+static void g_dbus_unregister_all_objects(DBusConnection *connection)
+{
+       ConnectionData *data;
+       GSList *list;
+
+       DBG("connection %p slot %d", connection, connection_slot);
+
+       if (connection_slot < 0)
+               return;
+
+       data = dbus_connection_get_data(connection, connection_slot);
+       if (data == NULL)
+               return;
+
+       DBG("connection data %p", data);
+
+       g_static_mutex_lock(&data->mutex);
+
+       for (list = data->objects; list; list = list->next) {
+               ObjectData *object = list->data;
+
+               DBG("object data %p path %s", object, object->path);
+
+               dbus_connection_unregister_object_path(connection,
+                                                       object->path);
+
+               dbus_connection_free_data_slot(&connection_slot);
+
+               DBG("connection slot %d", connection_slot);
+       }
+
+       g_slist_free(data->objects);
+
+       g_static_mutex_unlock(&data->mutex);
+
+       g_free(data);
+}
+#endif
+
+/**
+ * g_dbus_register_interface:
+ * @connection: the connection
+ * @path: object path
+ * @name: interface name
+ * @methods: method table
+ * @signals: signal table
+ * @properties: property table
+ * @user_data: user data to assign to interface
+ * @destroy: function called to destroy user_data
+ *
+ * Registers an interface for the given path in the
+ * object hierarchy with the given methods, signals
+ * and/or properties.
+ *
+ * Returns: #TRUE on success
+ */
+gboolean g_dbus_register_interface(DBusConnection *connection,
+                                       const char *path, const char *name,
+                                       GDBusMethodTable *methods,
+                                       GDBusSignalTable *signals,
+                                       GDBusPropertyTable *properties,
+                                       void *user_data,
+                                       GDBusDestroyFunction destroy)
+{
+       ObjectData *object;
+       InterfaceData *interface;
+
+       DBG("connection %p path %s name %s", connection, path, name);
+
+       if (g_dbus_register_object(connection, path) == FALSE)
+               return FALSE;
+
+       if (dbus_connection_get_object_path_data(connection,
+                                       path, (void *) &object) == FALSE)
+               return FALSE;
+
+       if (object == NULL)
+               return FALSE;
+
+       if (find_interface(object->interfaces, name) != NULL)
+               return FALSE;
+
+       interface = g_new0(InterfaceData, 1);
+
+       interface->name = g_strdup(name);
+       interface->methods = methods;
+       interface->signals = signals;
+       interface->properties = properties;
+       interface->user_data = user_data;
+       interface->destroy = destroy;
+
+       g_static_mutex_lock(&object->mutex);
+
+       object->interfaces = g_slist_append(object->interfaces, interface);
+
+       g_free(object->introspect);
+       object->introspect = generate_introspect(connection, path, object);
+
+       g_static_mutex_unlock(&object->mutex);
+
+       return TRUE;
+}
+
+/**
+ * g_dbus_unregister_interface:
+ * @connection: the connection
+ * @path: object path
+ * @name: interface name
+ *
+ * Unregister the given interface for the given path
+ * in the object hierarchy.
+ *
+ * Returns: #TRUE on success
+ */
+gboolean g_dbus_unregister_interface(DBusConnection *connection,
+                                       const char *path, const char *name)
+{
+       ObjectData *object;
+       InterfaceData *interface;
+
+       DBG("connection %p path %s name %s", connection, path, name);
+
+       if (dbus_connection_get_object_path_data(connection,
+                                       path, (void *) &object) == FALSE)
+               return FALSE;
+
+       if (object == NULL)
+               return FALSE;
+
+       interface = find_interface(object->interfaces, name);
+       if (interface == NULL)
+               return FALSE;
+
+       g_static_mutex_lock(&object->mutex);
+
+       object->interfaces = g_slist_remove(object->interfaces, interface);
+
+       g_free(object->introspect);
+       object->introspect = generate_introspect(connection, path, object);
+
+       g_static_mutex_unlock(&object->mutex);
+
+       g_free(interface->name);
+       g_free(interface);
+
+       g_dbus_unregister_object(connection, path);
+
+       return TRUE;
+}
+
+char *printf_dyn(const char *format, va_list ap)
+{
+    va_list aq;
+
+    char *buffer = NULL;
+    ssize_t size = 0;
+    ssize_t realsize = 255;
+    do {
+        // vsnprintf() destroys ap, so make a copy first
+        va_copy(aq, ap);
+
+        if (size < realsize) {
+            buffer = (char *)realloc(buffer, realsize + 1);
+            if (!buffer) {
+                if (buffer) {
+                    free(buffer);
+                }
+                return "";
+            }
+            size = realsize;
+        }
+
+        realsize = vsnprintf(buffer, size + 1, format, aq);
+        if (realsize == -1) {
+            // old-style vnsprintf: exact len unknown, try again with doubled size
+            realsize = size * 2;
+        }
+        va_end(aq);
+    } while(realsize > size);
+
+    return buffer;
+}
+
+/**
+ * g_dbus_create_error_valist:
+ * @message: the originating message
+ * @name: the error name
+ * @format: the error description
+ * @args: argument list
+ *
+ * Create error reply for the given message.
+ *
+ * Returns: reply message on success
+ */
+DBusMessage *g_dbus_create_error_valist(DBusMessage *message, const char *name,
+                                               const char *format, va_list args)
+{
+       DBusMessage *msg;
+        char *descr;
+
+       DBG("message %p name %s", message, name);
+
+       descr = printf_dyn(format, args);
+       msg = dbus_message_new_error(message, name, descr);
+       free(descr);
+       return msg;
+}
+
+/**
+ * g_dbus_create_error:
+ * @message: the originating message
+ * @name: the error name
+ * @format: the error description
+ * @varargs: list of parameters
+ *
+ * Create error reply for the given message.
+ *
+ * Returns: reply message on success
+ */
+DBusMessage *g_dbus_create_error(DBusMessage *message, const char *name,
+                                               const char *format, ...)
+{
+       va_list args;
+       DBusMessage *reply;
+
+       DBG("message %p name %s", message, name);
+
+       va_start(args, format);
+
+       reply = g_dbus_create_error_valist(message, name, format, args);
+
+       va_end(args);
+
+       return reply;
+}
+
+/**
+ * g_dbus_create_reply_valist:
+ * @message: the originating message
+ * @type: first argument type
+ * @args: argument list
+ *
+ * Create reply for the given message.
+ *
+ * Returns: reply message on success
+ */
+DBusMessage *g_dbus_create_reply_valist(DBusMessage *message,
+                                               int type, va_list args)
+{
+       DBusMessage *reply;
+
+       DBG("message %p", message);
+
+       reply = dbus_message_new_method_return(message);
+       if (reply == NULL)
+               return NULL;
+
+       if (dbus_message_append_args_valist(reply, type, args) == FALSE) {
+               dbus_message_unref(reply);
+               return NULL;
+       }
+
+       return reply;
+}
+
+/**
+ * g_dbus_create_reply:
+ * @message: the originating message
+ * @type: first argument type
+ * @varargs: list of parameters
+ *
+ * Create reply for the given message.
+ *
+ * Returns: reply message on success
+ */
+DBusMessage *g_dbus_create_reply(DBusMessage *message, int type, ...)
+{
+       va_list args;
+       DBusMessage *reply;
+
+       DBG("message %p", message);
+
+       va_start(args, type);
+
+       reply = g_dbus_create_reply_valist(message, type, args);
+
+       va_end(args);
+
+       return reply;
+}
+
+/**
+ * g_dbus_send_message:
+ * @connection: the connection
+ * @message: the message to send
+ *
+ * Send message via the given D-Bus connection.
+ *
+ * The reference count for the message will be decremented by this
+ * function.
+ *
+ * Returns: #TRUE on success
+ */
+gboolean g_dbus_send_message(DBusConnection *connection, DBusMessage *message)
+{
+       dbus_bool_t result;
+
+       DBG("connection %p message %p", connection, message);
+
+       result = dbus_connection_send(connection, message, NULL);
+
+       dbus_message_unref(message);
+
+       return result;
+}
+
+/**
+ * g_dbus_send_error:
+ * @connection: the connection
+ * @message: the originating message
+ * @name: the error name
+ * @format: the error description
+ * @varargs: list of parameters
+ *
+ * Send error reply for the given message and via the given D-Bus
+ * connection.
+ *
+ * Returns: #TRUE on success
+ */
+gboolean g_dbus_send_error(DBusConnection *connection, DBusMessage *message,
+                               const char *name, const char *format, ...)
+{
+       va_list args;
+       DBusMessage *error;
+
+       DBG("connection %p message %p", connection, message);
+
+       va_start(args, format);
+
+       error = g_dbus_create_error(message, name, format, args);
+
+       va_end(args);
+
+       if (error == NULL)
+               return FALSE;
+
+       return g_dbus_send_message(connection, error);
+}
+
+/**
+ * g_dbus_send_reply_valist:
+ * @connection: the connection
+ * @message: the originating message
+ * @type: first argument type
+ * @args: argument list
+ *
+ * Send reply for the given message and via the given D-Bus
+ * connection.
+ *
+ * Returns: #TRUE on success
+ */
+gboolean g_dbus_send_reply_valist(DBusConnection *connection,
+                               DBusMessage *message, int type, va_list args)
+{
+       DBusMessage *reply;
+
+       DBG("connection %p message %p", connection, message);
+
+       reply = dbus_message_new_method_return(message);
+       if (reply == NULL)
+               return FALSE;
+
+       if (dbus_message_append_args_valist(reply, type, args) == FALSE) {
+               dbus_message_unref(reply);
+               return FALSE;
+       }
+
+       return g_dbus_send_message(connection, reply);
+}
+
+/**
+ * g_dbus_send_reply:
+ * @connection: the connection
+ * @message: the originating message
+ * @type: first argument type
+ * @varargs: list of parameters
+ *
+ * Send reply for the given message and via the given D-Bus
+ * connection.
+ *
+ * Returns: #TRUE on success
+ */
+gboolean g_dbus_send_reply(DBusConnection *connection,
+                               DBusMessage *message, int type, ...)
+{
+       va_list args;
+       gboolean result;
+
+       DBG("connection %p message %p", connection, message);
+
+       va_start(args, type);
+
+       result = g_dbus_send_reply_valist(connection, message, type, args);
+
+       va_end(args);
+
+       return result;
+}
+
+static GDBusSignalTable *find_signal(GSList *interfaces,
+                               const char *interface, const char *name)
+{
+       InterfaceData *data;
+       GDBusSignalTable *signal;
+
+       data = find_interface(interfaces, interface);
+       if (data == NULL)
+               return NULL;
+
+       for (signal = data->signals; signal && signal->name; signal++) {
+               if (strcmp(signal->name, name) == 0)
+                       break;
+       }
+
+       return signal;
+}
+
+/**
+ * g_dbus_emit_signal_valist:
+ * @connection: the connection
+ * @path: object path
+ * @interface: interface name
+ * @name: signal name
+ * @type: first argument type
+ * @args: argument list
+ *
+ * Emit a signal for the given path and interface with
+ * the given signal name.
+ *
+ * The signal signature will be check against the registered
+ * signal table.
+ *
+ * Returns: #TRUE on success
+ */
+gboolean g_dbus_emit_signal_valist(DBusConnection *connection,
+                               const char *path, const char *interface,
+                               const char *name, int type, va_list args)
+{
+       ObjectData *object;
+       GDBusSignalTable *signal;
+       DBusMessage *message;
+       const char *signature;
+       gboolean result = FALSE;
+
+       DBG("connection %p path %s name %s.%s",
+                       connection, path, interface, name);
+
+       if (dbus_connection_get_object_path_data(connection,
+                                       path, (void *) &object) == FALSE)
+               return FALSE;
+
+       if (object == NULL)
+               return FALSE;
+
+       signal = find_signal(object->interfaces, interface, name);
+       if (signal == NULL)
+               return FALSE;
+
+       message = dbus_message_new_signal(path, interface, name);
+       if (message == NULL)
+               return FALSE;
+
+       if (dbus_message_append_args_valist(message, type, args) == FALSE)
+               goto done;
+
+       signature = dbus_message_get_signature(message);
+       if (strcmp(signal->signature, signature) != 0)
+               goto done;
+
+       DBG("connection %p signature \"%s\"", connection, signature);
+
+       if (dbus_connection_send(connection, message, NULL) == FALSE)
+               goto done;
+
+       result = TRUE;
+
+done:
+       dbus_message_unref(message);
+
+       return result;
+}
+
+/**
+ * g_dbus_emit_signal:
+ * @connection: the connection
+ * @path: object path
+ * @interface: interface name
+ * @name: signal name
+ * @type: first argument type
+ * @varargs: list of parameters
+ *
+ * Emit a signal for the given path and interface with
+ * the given signal name.
+ *
+ * The signal signature will be check against the registered
+ * signal table.
+ *
+ * Returns: #TRUE on success
+ */
+gboolean g_dbus_emit_signal(DBusConnection *connection,
+                               const char *path, const char *interface,
+                               const char *name, int type, ...)
+{
+       va_list args;
+       gboolean result;
+
+       DBG("connection %p path %s name %s.%s",
+                       connection, path, interface, name);
+
+       va_start(args, type);
+
+       result = g_dbus_emit_signal_valist(connection, path, interface,
+                                                       name, type, args);
+
+       va_end(args);
+
+       return result;
+}
diff --git a/src/gdbus/test/example.cpp b/src/gdbus/test/example.cpp
new file mode 100644 (file)
index 0000000..3a5e099
--- /dev/null
@@ -0,0 +1,284 @@
+/*
+ *
+ *  Library for simple D-Bus integration with GLib
+ *
+ *  Copyright (C) 2009  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/signal.h>
+
+#include "gdbus-cxx-bridge.h"
+#include <memory>
+#include <iostream>
+
+struct args {
+    int a;
+    std::string b;
+    std::map<std::string, std::string> c;
+};
+
+static void hello_global() {}
+
+class Test {
+    typedef boost::shared_ptr< Result1<const std::string&> > string_result;
+    struct async
+    {
+        async(const boost::shared_ptr<Watch> &watch, Watch *watch2, const string_result &result):
+            m_watch(watch),
+            m_watch2(watch2),
+            m_result(result)
+        {}
+        ~async()
+        {
+            delete m_watch2;
+        }
+
+        boost::shared_ptr<Watch> m_watch;
+        Watch *m_watch2;
+        string_result m_result;
+    };
+        
+
+    static gboolean method_idle(gpointer data)
+    {
+        std::auto_ptr<async> mydata(static_cast<async *>(data));
+        std::cout << "replying to method_async" << std::endl;
+        mydata->m_result->done("Hello World, asynchronous and delayed");
+        return false;
+    }
+
+    static void disconnect(const std::string &id, const std::string &peer)
+    {
+        std::cout << id << ": " << peer << " has disconnected." << std::endl;
+    }
+
+public:
+
+    static void hello_static() {}
+    void hello_const() const {}
+    static void hello_world(const char *msg) { puts(msg); }
+    void hello_base() {}
+
+    void method(std::string &text)
+    {
+        text = "Hello World";
+    }
+
+    void method_async(const Caller_t &caller,
+                      const boost::shared_ptr<Watch> &watch,
+                      int32_t secs,
+                      const string_result &r)
+    {
+        watch->setCallback(boost::bind(disconnect, "watch1", caller));
+        Watch *watch2 = r->createWatch(boost::bind(disconnect, "watch2", caller));
+        std::cout << "method_async called by " << caller << " delay " << secs << std::endl;
+        g_timeout_add_seconds(secs, method_idle, new async(watch, watch2, r));
+    }
+
+    void method2(int32_t arg, int32_t &ret)
+    {
+        ret = arg * 2;
+    }
+
+    int32_t method3(int32_t arg)
+    {
+        return arg * 3;
+    }
+
+    void method8_simple(int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5,
+                        int32_t a6, int32_t a7, int32_t a8)
+    {
+    }
+
+    void method9_async(Result9<int32_t, int32_t, int32_t, int32_t, int32_t,
+                               int32_t, int32_t, int32_t, int32_t> *r)
+    {
+        r->done(1, 2, 3, 4, 5, 6, 7, 8, 9);
+        delete r;
+    }
+
+    int32_t method9(int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5,
+                    int32_t a6, int32_t a7, int32_t a8, int32_t a9)
+    {
+        return 0;
+    }
+
+
+    void hash(const std::map<int8_t, int32_t> &in, std::map<int16_t, int32_t> &out)
+    {
+        for (std::map<int8_t, int32_t>::const_iterator it = in.begin();
+             it != in.end();
+             ++it) {
+            out.insert(std::make_pair((int16_t)it->first, it->second * it->second));
+        }
+    }
+
+    void array(const std::vector<int32_t> &in, std::vector<int32_t> &out)
+    {
+        for (std::vector<int32_t>::const_iterator it = in.begin();
+             it != in.end();
+             ++it) {
+            out.push_back(*it * *it);
+        }
+    }
+
+    void error()
+    {
+        throw dbus_error("org.example.error.Invalid", "error");
+    }
+
+    void argtest(const args &in, args &out)
+    {
+        out = in;
+        out.a = in.a + 1;
+    }
+};
+
+class Test2
+{
+public:
+    void test2() {}
+};
+
+template<> struct dbus_traits<args> :
+    public dbus_struct_traits<args, dbus_member<args, int, &args::a,
+                                    dbus_member<args, std::string, &args::b,
+                                    dbus_member_single<args, std::map<std::string, std::string>, &args::c> > > >
+{};
+
+class DBusTest : public Test, private Test2
+{
+    DBusObjectHelper m_object;
+    DBusObjectHelper m_secondary;
+
+public:
+    DBusTest(DBusConnection *conn) :
+        m_object(conn, "/test", "org.example.Test"),
+        // same path!
+        m_secondary(conn, m_object.getPath(), "org.example.Secondary"),
+        signal(m_object, "Signal")
+    {
+        m_object.add(this, &Test::method8_simple, "Method8Simple");
+        // m_object.add(this, &Test::method10_async, "Method10Async", G_DBUS_METHOD_FLAG_ASYNC);
+        // m_object.add(this, &Test::method9, "Method9");
+        m_object.add(this, &Test::method2, "Method2");
+        m_object.add(this, &Test::method3, "Method3");
+        m_object.add(this, &Test::method, "Test");
+        m_object.add(this, &Test::method_async, "TestAsync");
+        m_object.add(this, &Test::argtest, "ArgTest");
+        m_object.add(this, &Test::hash, "Hash");
+        m_object.add(this, &Test::array, "Array");
+        m_object.add(this, &Test::error, "Error");
+        m_object.add(&hello_global, "Global");
+        m_object.add(&DBusTest::hello_static, "Static");
+        m_object.add(static_cast<Test2 *>(this), &Test2::test2, "Private");
+        // The hello_const() method cannot be registered
+        // because there is no matching MakeMethodEntry<>
+        // specialization for it or DBusObjectHelper::add()
+        // fails to determine the right function type,
+        // depending how one wants to interpret the problem.
+        // m_object.add2(this, &DBusTest::hello_const, "Const");
+
+        m_object.add(signal);
+
+        m_secondary.add(this, &DBusTest::hello, "Hello");
+    }
+
+    ~DBusTest()
+    {
+    }
+
+    EmitSignal3<int32_t, const std::string &, const std::map<int32_t, int32_t> &>signal;
+
+    void hello() {}
+    static void hello_static() {}
+    void hello_const() const {}
+
+    void activate()
+    {
+        m_secondary.activate();
+        m_object.activate();
+    }
+
+    void deactivate()
+    {
+        m_object.deactivate();
+        m_secondary.deactivate();
+    }
+};
+
+static GMainLoop *main_loop = NULL;
+
+static void sig_term(int sig)
+{
+    g_main_loop_quit(main_loop);
+}
+
+int main(int argc, char *argv[])
+{
+    DBusConnection *conn;
+    DBusError err;
+    struct sigaction sa;
+
+    memset(&sa, 0, sizeof(sa));
+    sa.sa_handler = sig_term;
+    sigaction(SIGINT, &sa, NULL);
+    sigaction(SIGTERM, &sa, NULL);
+
+    sa.sa_handler = SIG_IGN;
+    sigaction(SIGCHLD, &sa, NULL);
+    sigaction(SIGPIPE, &sa, NULL);
+
+    main_loop = g_main_loop_new(NULL, FALSE);
+
+    dbus_error_init(&err);
+
+    conn = g_dbus_setup_bus(DBUS_BUS_SESSION, "org.example", &err);
+    if (conn == NULL) {
+        if (dbus_error_is_set(&err) == TRUE) {
+            fprintf(stderr, "%s\n", err.message);
+            dbus_error_free(&err);
+        } else
+            fprintf(stderr, "Can't register with session bus\n");
+        exit(1);
+    }
+
+    std::auto_ptr<DBusTest> test(new DBusTest(conn));
+    test->activate();
+    test->signal(42, "hello world", std::map<int32_t, int32_t>());
+    test->deactivate();
+    test->activate();
+    test->signal(123, "here I am again", std::map<int32_t, int32_t>());
+
+    g_main_loop_run(main_loop);
+
+    test.reset();
+
+    g_dbus_cleanup_connection(conn);
+
+    g_main_loop_unref(main_loop);
+
+    return 0;
+}
diff --git a/src/gdbus/watch.c b/src/gdbus/watch.c
new file mode 100644 (file)
index 0000000..3e9081c
--- /dev/null
@@ -0,0 +1,519 @@
+/*
+ *
+ *  Library for simple D-Bus integration with GLib
+ *
+ *  Copyright (C) 2007-2008  Intel Corporation. All rights reserved.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License version 2.1 as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+
+#include "gdbus.h"
+#include "debug.h"
+
+static dbus_int32_t connection_slot = -1;
+
+typedef struct {
+       GSList *watches;
+       GSList *handlers;
+       guint next_id;
+} ConnectionData;
+
+typedef struct {
+       guint id;
+       char *name;
+       void *user_data;
+       char *match;
+       GDBusWatchFunction connect;
+       GDBusWatchFunction disconn;
+       GDBusDestroyFunction destroy;
+} WatchData;
+
+typedef struct {
+       guint id;
+       void *user_data;
+       GDBusWatchFunction function;
+       GDBusDestroyFunction destroy;
+} DisconnectData;
+
+typedef struct {
+       guint id;
+       void *user_data;
+       char *match;
+       GDBusSignalFunction function;
+       GDBusDestroyFunction destroy;
+} SignalData;
+
+static DBusHandlerResult signal_function(DBusConnection *connection,
+                                       DBusMessage *message, void *user_data)
+{
+       ConnectionData *data = user_data;
+       GSList *list;
+
+       DBG("connection %p message %p", connection, message);
+
+       for (list = data->handlers; list; list = list->next) {
+               SignalData *signal = list->data;
+               gboolean result;
+
+               if (signal->function == NULL)
+                       continue;
+
+               result = signal->function(connection, message,
+                                                       signal->user_data);
+               if (result == TRUE)
+                       continue;
+
+               if (signal->destroy != NULL)
+                       signal->destroy(signal->user_data);
+       }
+
+       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static DBusHandlerResult owner_function(DBusConnection *connection,
+                                       DBusMessage *message, void *user_data)
+{
+       ConnectionData *data = user_data;
+       GSList *list;
+       const char *name, *old, *new;
+
+       DBG("connection %p message %p", connection, message);
+
+       if (dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &name,
+                                               DBUS_TYPE_STRING, &old,
+                                               DBUS_TYPE_STRING, &new,
+                                               DBUS_TYPE_INVALID) == FALSE)
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+       DBG("name %s \"%s\" => \"%s\"", name, old, new);
+
+       for (list = data->watches; list; list = list->next) {
+               WatchData *watch = list->data;
+
+               if (strcmp(name, watch->name) != 0)
+                       continue;
+
+               if (watch->connect != NULL && *old == '\0' && *new != '\0')
+                       watch->connect(connection, watch->user_data);
+
+               if (watch->disconn != NULL && *old != '\0' && *new == '\0')
+                       watch->disconn(connection, watch->user_data);
+       }
+
+       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static DBusHandlerResult filter_function(DBusConnection *connection,
+                                       DBusMessage *message, void *user_data)
+{
+       if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS,
+                                               "NameOwnerChanged") == TRUE)
+               return owner_function(connection, message, user_data);
+
+       if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL)
+               return signal_function(connection, message, user_data);
+
+       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static ConnectionData *get_connection_data(DBusConnection *connection)
+{
+       ConnectionData *data;
+       dbus_bool_t result;
+
+       DBG("connection %p", connection);
+
+       if (dbus_connection_allocate_data_slot(&connection_slot) == FALSE)
+               return NULL;
+
+       DBG("connection slot %d", connection_slot);
+
+       data = dbus_connection_get_data(connection, connection_slot);
+       if (data == NULL) {
+               data = g_try_new0(ConnectionData, 1);
+               if (data == NULL) {
+                       dbus_connection_free_data_slot(&connection_slot);
+                       return NULL;
+               }
+
+               data->next_id = 1;
+
+               if (dbus_connection_set_data(connection, connection_slot,
+                                                       data, NULL) == FALSE) {
+                       dbus_connection_free_data_slot(&connection_slot);
+                       g_free(data);
+                       return NULL;
+               }
+
+               result = dbus_connection_add_filter(connection,
+                                               filter_function, data, NULL);
+       }
+
+       return data;
+}
+
+static void put_connection_data(DBusConnection *connection)
+{
+       dbus_connection_free_data_slot(&connection_slot);
+}
+
+/**
+ * g_dbus_add_service_watch:
+ * @connection: the connection
+ * @name: unique or well known name
+ * @connect: function called on name connect
+ * @disconnect: function called on name disconnect
+ * @user_data: user data to pass to the function
+ * @destroy: function called to destroy user_data
+ *
+ * Add new watch to listen for connects and/or disconnects
+ * of a client for the given connection.
+ *
+ * Returns: identifier of the watch
+ */
+guint g_dbus_add_service_watch(DBusConnection *connection, const char *name,
+                               GDBusWatchFunction connect,
+                               GDBusWatchFunction disconnect,
+                               void *user_data, GDBusDestroyFunction destroy)
+{
+       ConnectionData *data;
+       WatchData *watch;
+       DBusError error;
+
+       DBG("connection %p name %s", connection, name);
+
+       data = get_connection_data(connection);
+       if (data == NULL)
+               return 0;
+
+       DBG("connection data %p", data);
+
+       watch = g_try_new0(WatchData, 1);
+       if (watch == NULL)
+               goto error;
+
+       watch->name = g_strdup(name);
+       if (watch->name == NULL)
+               goto error;
+
+       watch->user_data = user_data;
+
+       watch->connect = connect;
+       watch->disconn = disconnect;
+       watch->destroy = destroy;
+       watch->match = g_strdup_printf("interface=%s,member=NameOwnerChanged,arg0=%s",
+                                               DBUS_INTERFACE_DBUS, name);
+       if (watch->match == NULL)
+               goto error;
+
+       dbus_error_init(&error);
+
+       dbus_bus_add_match(connection, watch->match, &error);
+
+       if (dbus_error_is_set(&error) == TRUE) {
+               dbus_error_free(&error);
+               goto error;
+       }
+
+       watch->id = data->next_id++;
+
+       data->watches = g_slist_append(data->watches, watch);
+
+       DBG("tag %d", watch->id);
+
+       return watch->id;
+
+error:
+       if (watch != NULL) {
+               g_free(watch->name);
+               g_free(watch->match);
+       }
+       g_free(watch);
+
+       put_connection_data(connection);
+
+       return 0;
+}
+
+/**
+ * g_dbus_remove_watch:
+ * @connection: the connection
+ * @tag: watch identifier
+ *
+ * Removes the watch for the given identifier.
+ *
+ * Returns: #TRUE on success
+ */
+gboolean g_dbus_remove_watch(DBusConnection *connection, guint tag)
+{
+       ConnectionData *data;
+       GSList *list;
+
+       DBG("connection %p tag %d", connection, tag);
+
+       if (connection_slot < 0)
+               return FALSE;
+
+       data = dbus_connection_get_data(connection, connection_slot);
+       if (data == NULL)
+               return FALSE;
+
+       for (list = data->watches; list; list = list->next) {
+               WatchData *watch = list->data;
+
+               if (watch->id == tag) {
+                       data->watches = g_slist_remove(data->watches, watch);
+                       if (watch->destroy != NULL)
+                               watch->destroy(watch->user_data);
+                       dbus_bus_remove_match(connection, watch->match, NULL);
+                       g_free(watch->name);
+                        g_free(watch->match);
+                       g_free(watch);
+                       goto done;
+               }
+       }
+
+       for (list = data->handlers; list; list = list->next) {
+               SignalData *signal = list->data;
+
+               if (signal->id == tag) {
+                       data->handlers = g_slist_remove(data->handlers, signal);
+                       if (signal->destroy != NULL)
+                               signal->destroy(signal->user_data);
+                       dbus_bus_remove_match(connection, signal->match, NULL);
+                       g_free(signal->match);
+                       g_free(signal);
+                       goto done;
+               }
+       }
+
+       return FALSE;
+
+done:
+        if (!data->watches && !data->handlers) {
+               dbus_connection_remove_filter(connection,
+                                               filter_function, data);
+               dbus_connection_set_data(connection, connection_slot, NULL, NULL);
+                g_free(data);
+       }
+
+       dbus_connection_free_data_slot(&connection_slot);
+
+       DBG("connection slot %d", connection_slot);
+
+       return TRUE;
+}
+
+/**
+ * g_dbus_remove_all_watches:
+ * @connection: the connection
+ *
+ * Removes all registered watches.
+ */
+void g_dbus_remove_all_watches(DBusConnection *connection)
+{
+       ConnectionData *data;
+       GSList *list;
+
+       DBG("connection %p slot %d", connection, connection_slot);
+
+       if (connection_slot < 0)
+               return;
+
+       data = dbus_connection_get_data(connection, connection_slot);
+       if (data == NULL)
+               return;
+
+       DBG("connection data %p", data);
+
+       for (list = data->watches; list; list = list->next) {
+               WatchData *watch = list->data;
+
+               DBG("watch data %p tag %d", watch, watch->id);
+
+               if (watch->destroy != NULL)
+                       watch->destroy(watch->user_data);
+               dbus_bus_remove_match(connection, watch->match, NULL);
+               g_free(watch->match);
+               g_free(watch->name);
+               g_free(watch);
+
+               dbus_connection_free_data_slot(&connection_slot);
+
+               DBG("connection slot %d", connection_slot);
+       }
+
+       g_slist_free(data->watches);
+
+       for (list = data->handlers; list; list = list->next) {
+               SignalData *signal = list->data;
+
+               DBG("signal data %p tag %d", signal, signal->id);
+
+               if (signal->destroy != NULL)
+                       signal->destroy(signal->user_data);
+               dbus_bus_remove_match(connection, signal->match, NULL);
+               g_free(signal->match);
+               g_free(signal);
+
+               dbus_connection_free_data_slot(&connection_slot);
+
+               DBG("connection slot %d", connection_slot);
+       }
+
+       g_slist_free(data->handlers);
+
+       dbus_connection_remove_filter(connection, filter_function, data);
+
+       g_free(data);
+}
+
+static void disconnect_function(DBusConnection *connection, void *user_data)
+{
+       DisconnectData *data = user_data;
+
+       // The callback function might remove the watch,
+       // which invalidates the data pointer. Remember
+       // the ID.
+       guint id = data->id;
+
+       data->function(connection, data->user_data);
+
+       g_dbus_remove_watch(connection, id);
+}
+
+static void disconnect_release(void *user_data)
+{
+       g_free(user_data);
+}
+
+/**
+ * g_dbus_add_disconnect_watch:
+ * @connection: the connection
+ * @name: unique or well known name
+ * @function: function called on name disconnect
+ * @user_data: user data to pass to the function
+ * @destroy: function called to destroy user_data
+ *
+ * Add new watch to listen for disconnect of a client
+ * for the given connection.
+ *
+ * After the callback has been called, this watch will be
+ * automatically removed.
+ *
+ * Returns: identifier of the watch
+ */
+guint g_dbus_add_disconnect_watch(DBusConnection *connection,
+                               const char *name, GDBusWatchFunction function,
+                               void *user_data, GDBusDestroyFunction destroy)
+{
+       DisconnectData *data;
+
+       data = g_try_new0(DisconnectData, 1);
+       if (data == NULL)
+               return 0;
+
+       data->user_data = user_data;
+       data->function = function;
+       data->destroy = destroy;
+
+       data->id = g_dbus_add_service_watch(connection, name, NULL,
+                       disconnect_function, data, disconnect_release);
+
+       if (data->id == 0) {
+               g_free(data);
+               return 0;
+       }
+
+       return data->id;
+}
+
+/**
+ * g_dbus_add_signal_watch:
+ * @connection: the connection
+ * @rule: matching rule for this signal
+ * @function: function called when signal arrives
+ * @user_data: user data to pass to the function
+ * @destroy: function called to destroy user_data
+ *
+ * Add new watch to listen for specific signals of
+ * a client for the given connection.
+ *
+ * If the callback returns #FALSE this watch will be
+ * automatically removed.
+ *
+ * Returns: identifier of the watch
+ */
+guint g_dbus_add_signal_watch(DBusConnection *connection,
+                               const char *rule, GDBusSignalFunction function,
+                               void *user_data, GDBusDestroyFunction destroy)
+{
+       ConnectionData *data;
+       SignalData *signal;
+       DBusError error;
+
+       DBG("connection %p rule %s", connection, rule);
+
+       data = get_connection_data(connection);
+       if (data == NULL)
+               return 0;
+
+       DBG("connection data %p", data);
+
+       signal = g_try_new0(SignalData, 1);
+       if (signal == NULL)
+               goto error;
+
+       signal->match = g_strdup(rule);
+       if (!signal->match)
+               goto error;
+
+       signal->user_data = user_data;
+
+       signal->function = function;
+       signal->destroy = destroy;
+
+       dbus_error_init(&error);
+
+       dbus_bus_add_match(connection, rule, &error);
+
+       if (dbus_error_is_set(&error) == TRUE) {
+               dbus_error_free(&error);
+               goto error;
+       }
+
+       signal->id = data->next_id++;
+
+       data->handlers = g_slist_append(data->handlers, signal);
+
+       DBG("tag %d", signal->id);
+
+       return signal->id;
+
+error:
+        if (signal)
+               g_free(signal->match);
+       g_free(signal);
+
+       put_connection_data(connection);
+
+       return 0;
+}
index 5afef59..f2d7cd6 100644 (file)
@@ -50,8 +50,9 @@ bin_PROGRAMS = $(GUI_PROGRAMS)
 
 sync_ui_SOURCES = \
        main.c sync-ui.c sync-ui.h sync-ui-config.c sync-ui-config.h \
-       mux-frame.c mux-frame.h mux-window.c mux-window.h mux-icon-button.c mux-icon-button.h
-nodist_sync_ui_SOURCES = sync-ui-marshal.c sync-ui-marshal.h
+       mux-frame.c mux-frame.h mux-window.c mux-window.h mux-icon-button.c mux-icon-button.h \
+       sync-config-widget.c sync-config-widget.h
+
 sync_ui_LDADD = $(GUI_LIBS) $(DBUS_GLIB_LIBS) $(top_builddir)/src/dbus/libsyncevo-dbus.la
 sync_ui_CFLAGS = $(GUI_CFLAGS) \
        $(DBUS_GLIB_CFLAGS) \
@@ -73,26 +74,7 @@ sync_ui_moblin_LDADD = $(sync_ui_LDADD)
 sync_ui_moblin_CFLAGS = $(sync_ui_CFLAGS)
 sync_ui_moblin_CPPFLAGS = $(sync_ui_CPPFLAGS) -DUSE_MOBLIN_UX
 
-noinst_DATA = sync-ui-marshal.list
-if COND_GUI
-BUILT_SOURCES = \
-       syncevo-bindings.h sync-ui-marshal.c sync-ui-marshal.h
-endif
 CLEANFILES = $(BUILT_SOURCES) \
        ui.xml \
        sync-moblin.desktop \
         $(applications_generated)
-
-%-bindings.h: stamp-%-bindings.h
-       @true
-stamp-%-bindings.h: $(top_builddir)/src/dbus/interfaces/%.xml
-       $(DBUS_BINDING_TOOL) --mode=glib-client --prefix=syncevo $< > xgen-$(@F) \
-       && (cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%)) \
-       && rm -f xgen-$(@F) \
-       && echo timestamp > $(@F)
-
-sync-ui-marshal.h: $(srcdir)/sync-ui-marshal.list $(GLIB_GENMARSHAL)
-       $(GLIB_GENMARSHAL) $< --header --prefix=sync_ui_marshal > $@
-sync-ui-marshal.c: $(srcdir)/sync-ui-marshal.list sync-ui-marshal.h $(GLIB_GENMARSHAL)
-       echo "#include \"sync-ui-marshal.h\"" > $@ \
-       && $(GLIB_GENMARSHAL) --prefix=sync_ui_marshal $(srcdir)/sync-ui-marshal.list --body >> $@
index 06ab3fa..2972e53 100644 (file)
@@ -53,9 +53,9 @@ binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
 PROGRAMS = $(bin_PROGRAMS)
 am_sync_ui_OBJECTS = sync_ui-main.$(OBJEXT) sync_ui-sync-ui.$(OBJEXT) \
        sync_ui-sync-ui-config.$(OBJEXT) sync_ui-mux-frame.$(OBJEXT) \
-       sync_ui-mux-window.$(OBJEXT) sync_ui-mux-icon-button.$(OBJEXT)
-nodist_sync_ui_OBJECTS = sync_ui-sync-ui-marshal.$(OBJEXT)
-sync_ui_OBJECTS = $(am_sync_ui_OBJECTS) $(nodist_sync_ui_OBJECTS)
+       sync_ui-mux-window.$(OBJEXT) sync_ui-mux-icon-button.$(OBJEXT) \
+       sync_ui-sync-config-widget.$(OBJEXT)
+sync_ui_OBJECTS = $(am_sync_ui_OBJECTS)
 am__DEPENDENCIES_1 =
 sync_ui_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
        $(top_builddir)/src/dbus/libsyncevo-dbus.la
@@ -67,10 +67,10 @@ am__objects_1 = sync_ui_gtk-main.$(OBJEXT) \
        sync_ui_gtk-sync-ui-config.$(OBJEXT) \
        sync_ui_gtk-mux-frame.$(OBJEXT) \
        sync_ui_gtk-mux-window.$(OBJEXT) \
-       sync_ui_gtk-mux-icon-button.$(OBJEXT)
+       sync_ui_gtk-mux-icon-button.$(OBJEXT) \
+       sync_ui_gtk-sync-config-widget.$(OBJEXT)
 am_sync_ui_gtk_OBJECTS = $(am__objects_1)
-am__objects_2 = sync_ui_gtk-sync-ui-marshal.$(OBJEXT)
-nodist_sync_ui_gtk_OBJECTS = $(am__objects_2)
+nodist_sync_ui_gtk_OBJECTS =
 sync_ui_gtk_OBJECTS = $(am_sync_ui_gtk_OBJECTS) \
        $(nodist_sync_ui_gtk_OBJECTS)
 am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
@@ -79,15 +79,15 @@ sync_ui_gtk_DEPENDENCIES = $(am__DEPENDENCIES_2)
 sync_ui_gtk_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
        $(LIBTOOLFLAGS) --mode=link $(CCLD) $(sync_ui_gtk_CFLAGS) \
        $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
-am__objects_3 = sync_ui_moblin-main.$(OBJEXT) \
+am__objects_2 = sync_ui_moblin-main.$(OBJEXT) \
        sync_ui_moblin-sync-ui.$(OBJEXT) \
        sync_ui_moblin-sync-ui-config.$(OBJEXT) \
        sync_ui_moblin-mux-frame.$(OBJEXT) \
        sync_ui_moblin-mux-window.$(OBJEXT) \
-       sync_ui_moblin-mux-icon-button.$(OBJEXT)
-am_sync_ui_moblin_OBJECTS = $(am__objects_3)
-am__objects_4 = sync_ui_moblin-sync-ui-marshal.$(OBJEXT)
-nodist_sync_ui_moblin_OBJECTS = $(am__objects_4)
+       sync_ui_moblin-mux-icon-button.$(OBJEXT) \
+       sync_ui_moblin-sync-config-widget.$(OBJEXT)
+am_sync_ui_moblin_OBJECTS = $(am__objects_2)
+nodist_sync_ui_moblin_OBJECTS =
 sync_ui_moblin_OBJECTS = $(am_sync_ui_moblin_OBJECTS) \
        $(nodist_sync_ui_moblin_OBJECTS)
 sync_ui_moblin_DEPENDENCIES = $(am__DEPENDENCIES_2)
@@ -106,9 +106,9 @@ CCLD = $(CC)
 LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
        --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
        $(LDFLAGS) -o $@
-SOURCES = $(sync_ui_SOURCES) $(nodist_sync_ui_SOURCES) \
-       $(sync_ui_gtk_SOURCES) $(nodist_sync_ui_gtk_SOURCES) \
-       $(sync_ui_moblin_SOURCES) $(nodist_sync_ui_moblin_SOURCES)
+SOURCES = $(sync_ui_SOURCES) $(sync_ui_gtk_SOURCES) \
+       $(nodist_sync_ui_gtk_SOURCES) $(sync_ui_moblin_SOURCES) \
+       $(nodist_sync_ui_moblin_SOURCES)
 DIST_SOURCES = $(sync_ui_SOURCES) $(sync_ui_gtk_SOURCES) \
        $(sync_ui_moblin_SOURCES)
 am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
@@ -122,7 +122,7 @@ dist_iconDATA_INSTALL = $(INSTALL_DATA)
 gladeDATA_INSTALL = $(INSTALL_DATA)
 themercDATA_INSTALL = $(INSTALL_DATA)
 DATA = $(applications_DATA) $(dist_icon_DATA) $(glade_DATA) \
-       $(noinst_DATA) $(themerc_DATA)
+       $(themerc_DATA)
 ETAGS = etags
 CTAGS = ctags
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -138,6 +138,8 @@ AUTOMAKE = @AUTOMAKE@
 AWK = @AWK@
 BACKEND_CPPFLAGS = @BACKEND_CPPFLAGS@
 BACKEND_DEFINES = @BACKEND_DEFINES@
+BLUEZ_CFLAGS = @BLUEZ_CFLAGS@
+BLUEZ_LIBS = @BLUEZ_LIBS@
 BOOST_CPPFLAGS = @BOOST_CPPFLAGS@
 BOOST_LDFLAGS = @BOOST_LDFLAGS@
 CATALOGS = @CATALOGS@
@@ -145,7 +147,6 @@ CATOBJEXT = @CATOBJEXT@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
-CLEAN_CLIENT_SRC = @CLEAN_CLIENT_SRC@
 CORE_LDADD_DEP = @CORE_LDADD_DEP@
 CPP = @CPP@
 CPPFLAGS = @CPPFLAGS@
@@ -158,8 +159,10 @@ CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
 DATADIRNAME = @DATADIRNAME@
 DBUS_BINDING_TOOL = @DBUS_BINDING_TOOL@
+DBUS_CFLAGS = @DBUS_CFLAGS@
 DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@
 DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@
+DBUS_LIBS = @DBUS_LIBS@
 DBUS_SERVICES_DIR = @DBUS_SERVICES_DIR@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
@@ -186,11 +189,7 @@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
 GLIB_LIBS = @GLIB_LIBS@
 GMOFILES = @GMOFILES@
 GMSGFMT = @GMSGFMT@
-GOBJECT_CFLAGS = @GOBJECT_CFLAGS@
-GOBJECT_LIBS = @GOBJECT_LIBS@
 GREP = @GREP@
-GTHREAD_CFLAGS = @GTHREAD_CFLAGS@
-GTHREAD_LIBS = @GTHREAD_LIBS@
 GTK_BUILDER_CONV = @GTK_BUILDER_CONV@
 GUI_CFLAGS = @GUI_CFLAGS@
 GUI_DESKTOP_FILES = @GUI_DESKTOP_FILES@
@@ -214,6 +213,8 @@ KEYRING_LIBS = @KEYRING_LIBS@
 LDFLAGS = @LDFLAGS@
 LIBEXECDIR = @LIBEXECDIR@
 LIBOBJS = @LIBOBJS@
+LIBOPENOBEX_CFLAGS = @LIBOPENOBEX_CFLAGS@
+LIBOPENOBEX_LIBS = @LIBOPENOBEX_LIBS@
 LIBS = @LIBS@
 LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@
 LIBSOUP_LIBS = @LIBSOUP_LIBS@
@@ -221,8 +222,6 @@ LIBTOOL = @LIBTOOL@
 LN_S = @LN_S@
 LTLIBOBJS = @LTLIBOBJS@
 MAKEINFO = @MAKEINFO@
-MCALB_CFLAGS = @MCALB_CFLAGS@
-MCALB_LIBS = @MCALB_LIBS@
 MKDIR_P = @MKDIR_P@
 MKINSTALLDIRS = @MKINSTALLDIRS@
 MODIFY_SYNCCOMPARE = @MODIFY_SYNCCOMPARE@
@@ -258,6 +257,7 @@ SYNTHESIS = @SYNTHESIS@
 SYNTHESISSRC = @SYNTHESISSRC@
 SYNTHESIS_CFLAGS = @SYNTHESIS_CFLAGS@
 SYNTHESIS_DEP = @SYNTHESIS_DEP@
+SYNTHESIS_ENGINE = @SYNTHESIS_ENGINE@
 SYNTHESIS_LIB = @SYNTHESIS_LIB@
 SYNTHESIS_LIBS = @SYNTHESIS_LIBS@
 SYNTHESIS_SRC = @SYNTHESIS_SRC@
@@ -269,8 +269,6 @@ UNIQUE_LIBS = @UNIQUE_LIBS@
 USE_NLS = @USE_NLS@
 VERSION = @VERSION@
 XGETTEXT = @XGETTEXT@
-XMLRPC_CFLAGS = @XMLRPC_CFLAGS@
-XMLRPC_LIBS = @XMLRPC_LIBS@
 XSLT = @XSLT@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
@@ -351,9 +349,9 @@ EXTRA_DIST = \
 bin_PROGRAMS = $(GUI_PROGRAMS)
 sync_ui_SOURCES = \
        main.c sync-ui.c sync-ui.h sync-ui-config.c sync-ui-config.h \
-       mux-frame.c mux-frame.h mux-window.c mux-window.h mux-icon-button.c mux-icon-button.h
+       mux-frame.c mux-frame.h mux-window.c mux-window.h mux-icon-button.c mux-icon-button.h \
+       sync-config-widget.c sync-config-widget.h
 
-nodist_sync_ui_SOURCES = sync-ui-marshal.c sync-ui-marshal.h
 sync_ui_LDADD = $(GUI_LIBS) $(DBUS_GLIB_LIBS) $(top_builddir)/src/dbus/libsyncevo-dbus.la
 sync_ui_CFLAGS = $(GUI_CFLAGS) \
        $(DBUS_GLIB_CFLAGS) \
@@ -373,17 +371,12 @@ nodist_sync_ui_moblin_SOURCES = $(nodist_sync_ui_SOURCES)
 sync_ui_moblin_LDADD = $(sync_ui_LDADD)
 sync_ui_moblin_CFLAGS = $(sync_ui_CFLAGS)
 sync_ui_moblin_CPPFLAGS = $(sync_ui_CPPFLAGS) -DUSE_MOBLIN_UX
-noinst_DATA = sync-ui-marshal.list
-@COND_GUI_TRUE@BUILT_SOURCES = \
-@COND_GUI_TRUE@        syncevo-bindings.h sync-ui-marshal.c sync-ui-marshal.h
-
 CLEANFILES = $(BUILT_SOURCES) \
        ui.xml \
        sync-moblin.desktop \
         $(applications_generated)
 
-all: $(BUILT_SOURCES)
-       $(MAKE) $(AM_MAKEFLAGS) all-am
+all: all-am
 
 .SUFFIXES:
 .SUFFIXES: .c .lo .o .obj
@@ -464,22 +457,22 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sync_ui-mux-frame.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sync_ui-mux-icon-button.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sync_ui-mux-window.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sync_ui-sync-config-widget.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sync_ui-sync-ui-config.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sync_ui-sync-ui-marshal.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sync_ui-sync-ui.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sync_ui_gtk-main.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sync_ui_gtk-mux-frame.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sync_ui_gtk-mux-icon-button.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sync_ui_gtk-mux-window.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sync_ui_gtk-sync-config-widget.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sync_ui_gtk-sync-ui-config.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sync_ui_gtk-sync-ui-marshal.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sync_ui_gtk-sync-ui.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sync_ui_moblin-main.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sync_ui_moblin-mux-frame.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sync_ui_moblin-mux-icon-button.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sync_ui_moblin-mux-window.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sync_ui_moblin-sync-config-widget.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sync_ui_moblin-sync-ui-config.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sync_ui_moblin-sync-ui-marshal.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sync_ui_moblin-sync-ui.Po@am__quote@
 
 .c.o:
@@ -587,19 +580,19 @@ sync_ui-mux-icon-button.obj: mux-icon-button.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sync_ui_CPPFLAGS) $(CPPFLAGS) $(sync_ui_CFLAGS) $(CFLAGS) -c -o sync_ui-mux-icon-button.obj `if test -f 'mux-icon-button.c'; then $(CYGPATH_W) 'mux-icon-button.c'; else $(CYGPATH_W) '$(srcdir)/mux-icon-button.c'; fi`
 
-sync_ui-sync-ui-marshal.o: sync-ui-marshal.c
-@am__fastdepCC_TRUE@   $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sync_ui_CPPFLAGS) $(CPPFLAGS) $(sync_ui_CFLAGS) $(CFLAGS) -MT sync_ui-sync-ui-marshal.o -MD -MP -MF $(DEPDIR)/sync_ui-sync-ui-marshal.Tpo -c -o sync_ui-sync-ui-marshal.o `test -f 'sync-ui-marshal.c' || echo '$(srcdir)/'`sync-ui-marshal.c
-@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/sync_ui-sync-ui-marshal.Tpo $(DEPDIR)/sync_ui-sync-ui-marshal.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='sync-ui-marshal.c' object='sync_ui-sync-ui-marshal.o' libtool=no @AMDEPBACKSLASH@
+sync_ui-sync-config-widget.o: sync-config-widget.c
+@am__fastdepCC_TRUE@   $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sync_ui_CPPFLAGS) $(CPPFLAGS) $(sync_ui_CFLAGS) $(CFLAGS) -MT sync_ui-sync-config-widget.o -MD -MP -MF $(DEPDIR)/sync_ui-sync-config-widget.Tpo -c -o sync_ui-sync-config-widget.o `test -f 'sync-config-widget.c' || echo '$(srcdir)/'`sync-config-widget.c
+@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/sync_ui-sync-config-widget.Tpo $(DEPDIR)/sync_ui-sync-config-widget.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='sync-config-widget.c' object='sync_ui-sync-config-widget.o' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sync_ui_CPPFLAGS) $(CPPFLAGS) $(sync_ui_CFLAGS) $(CFLAGS) -c -o sync_ui-sync-ui-marshal.o `test -f 'sync-ui-marshal.c' || echo '$(srcdir)/'`sync-ui-marshal.c
+@am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sync_ui_CPPFLAGS) $(CPPFLAGS) $(sync_ui_CFLAGS) $(CFLAGS) -c -o sync_ui-sync-config-widget.o `test -f 'sync-config-widget.c' || echo '$(srcdir)/'`sync-config-widget.c
 
-sync_ui-sync-ui-marshal.obj: sync-ui-marshal.c
-@am__fastdepCC_TRUE@   $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sync_ui_CPPFLAGS) $(CPPFLAGS) $(sync_ui_CFLAGS) $(CFLAGS) -MT sync_ui-sync-ui-marshal.obj -MD -MP -MF $(DEPDIR)/sync_ui-sync-ui-marshal.Tpo -c -o sync_ui-sync-ui-marshal.obj `if test -f 'sync-ui-marshal.c'; then $(CYGPATH_W) 'sync-ui-marshal.c'; else $(CYGPATH_W) '$(srcdir)/sync-ui-marshal.c'; fi`
-@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/sync_ui-sync-ui-marshal.Tpo $(DEPDIR)/sync_ui-sync-ui-marshal.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='sync-ui-marshal.c' object='sync_ui-sync-ui-marshal.obj' libtool=no @AMDEPBACKSLASH@
+sync_ui-sync-config-widget.obj: sync-config-widget.c
+@am__fastdepCC_TRUE@   $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sync_ui_CPPFLAGS) $(CPPFLAGS) $(sync_ui_CFLAGS) $(CFLAGS) -MT sync_ui-sync-config-widget.obj -MD -MP -MF $(DEPDIR)/sync_ui-sync-config-widget.Tpo -c -o sync_ui-sync-config-widget.obj `if test -f 'sync-config-widget.c'; then $(CYGPATH_W) 'sync-config-widget.c'; else $(CYGPATH_W) '$(srcdir)/sync-config-widget.c'; fi`
+@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/sync_ui-sync-config-widget.Tpo $(DEPDIR)/sync_ui-sync-config-widget.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='sync-config-widget.c' object='sync_ui-sync-config-widget.obj' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sync_ui_CPPFLAGS) $(CPPFLAGS) $(sync_ui_CFLAGS) $(CFLAGS) -c -o sync_ui-sync-ui-marshal.obj `if test -f 'sync-ui-marshal.c'; then $(CYGPATH_W) 'sync-ui-marshal.c'; else $(CYGPATH_W) '$(srcdir)/sync-ui-marshal.c'; fi`
+@am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sync_ui_CPPFLAGS) $(CPPFLAGS) $(sync_ui_CFLAGS) $(CFLAGS) -c -o sync_ui-sync-config-widget.obj `if test -f 'sync-config-widget.c'; then $(CYGPATH_W) 'sync-config-widget.c'; else $(CYGPATH_W) '$(srcdir)/sync-config-widget.c'; fi`
 
 sync_ui_gtk-main.o: main.c
 @am__fastdepCC_TRUE@   $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sync_ui_gtk_CPPFLAGS) $(CPPFLAGS) $(sync_ui_gtk_CFLAGS) $(CFLAGS) -MT sync_ui_gtk-main.o -MD -MP -MF $(DEPDIR)/sync_ui_gtk-main.Tpo -c -o sync_ui_gtk-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c
@@ -685,19 +678,19 @@ sync_ui_gtk-mux-icon-button.obj: mux-icon-button.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sync_ui_gtk_CPPFLAGS) $(CPPFLAGS) $(sync_ui_gtk_CFLAGS) $(CFLAGS) -c -o sync_ui_gtk-mux-icon-button.obj `if test -f 'mux-icon-button.c'; then $(CYGPATH_W) 'mux-icon-button.c'; else $(CYGPATH_W) '$(srcdir)/mux-icon-button.c'; fi`
 
-sync_ui_gtk-sync-ui-marshal.o: sync-ui-marshal.c
-@am__fastdepCC_TRUE@   $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sync_ui_gtk_CPPFLAGS) $(CPPFLAGS) $(sync_ui_gtk_CFLAGS) $(CFLAGS) -MT sync_ui_gtk-sync-ui-marshal.o -MD -MP -MF $(DEPDIR)/sync_ui_gtk-sync-ui-marshal.Tpo -c -o sync_ui_gtk-sync-ui-marshal.o `test -f 'sync-ui-marshal.c' || echo '$(srcdir)/'`sync-ui-marshal.c
-@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/sync_ui_gtk-sync-ui-marshal.Tpo $(DEPDIR)/sync_ui_gtk-sync-ui-marshal.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='sync-ui-marshal.c' object='sync_ui_gtk-sync-ui-marshal.o' libtool=no @AMDEPBACKSLASH@
+sync_ui_gtk-sync-config-widget.o: sync-config-widget.c
+@am__fastdepCC_TRUE@   $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sync_ui_gtk_CPPFLAGS) $(CPPFLAGS) $(sync_ui_gtk_CFLAGS) $(CFLAGS) -MT sync_ui_gtk-sync-config-widget.o -MD -MP -MF $(DEPDIR)/sync_ui_gtk-sync-config-widget.Tpo -c -o sync_ui_gtk-sync-config-widget.o `test -f 'sync-config-widget.c' || echo '$(srcdir)/'`sync-config-widget.c
+@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/sync_ui_gtk-sync-config-widget.Tpo $(DEPDIR)/sync_ui_gtk-sync-config-widget.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='sync-config-widget.c' object='sync_ui_gtk-sync-config-widget.o' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sync_ui_gtk_CPPFLAGS) $(CPPFLAGS) $(sync_ui_gtk_CFLAGS) $(CFLAGS) -c -o sync_ui_gtk-sync-ui-marshal.o `test -f 'sync-ui-marshal.c' || echo '$(srcdir)/'`sync-ui-marshal.c
+@am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sync_ui_gtk_CPPFLAGS) $(CPPFLAGS) $(sync_ui_gtk_CFLAGS) $(CFLAGS) -c -o sync_ui_gtk-sync-config-widget.o `test -f 'sync-config-widget.c' || echo '$(srcdir)/'`sync-config-widget.c
 
-sync_ui_gtk-sync-ui-marshal.obj: sync-ui-marshal.c
-@am__fastdepCC_TRUE@   $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sync_ui_gtk_CPPFLAGS) $(CPPFLAGS) $(sync_ui_gtk_CFLAGS) $(CFLAGS) -MT sync_ui_gtk-sync-ui-marshal.obj -MD -MP -MF $(DEPDIR)/sync_ui_gtk-sync-ui-marshal.Tpo -c -o sync_ui_gtk-sync-ui-marshal.obj `if test -f 'sync-ui-marshal.c'; then $(CYGPATH_W) 'sync-ui-marshal.c'; else $(CYGPATH_W) '$(srcdir)/sync-ui-marshal.c'; fi`
-@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/sync_ui_gtk-sync-ui-marshal.Tpo $(DEPDIR)/sync_ui_gtk-sync-ui-marshal.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='sync-ui-marshal.c' object='sync_ui_gtk-sync-ui-marshal.obj' libtool=no @AMDEPBACKSLASH@
+sync_ui_gtk-sync-config-widget.obj: sync-config-widget.c
+@am__fastdepCC_TRUE@   $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sync_ui_gtk_CPPFLAGS) $(CPPFLAGS) $(sync_ui_gtk_CFLAGS) $(CFLAGS) -MT sync_ui_gtk-sync-config-widget.obj -MD -MP -MF $(DEPDIR)/sync_ui_gtk-sync-config-widget.Tpo -c -o sync_ui_gtk-sync-config-widget.obj `if test -f 'sync-config-widget.c'; then $(CYGPATH_W) 'sync-config-widget.c'; else $(CYGPATH_W) '$(srcdir)/sync-config-widget.c'; fi`
+@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/sync_ui_gtk-sync-config-widget.Tpo $(DEPDIR)/sync_ui_gtk-sync-config-widget.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='sync-config-widget.c' object='sync_ui_gtk-sync-config-widget.obj' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sync_ui_gtk_CPPFLAGS) $(CPPFLAGS) $(sync_ui_gtk_CFLAGS) $(CFLAGS) -c -o sync_ui_gtk-sync-ui-marshal.obj `if test -f 'sync-ui-marshal.c'; then $(CYGPATH_W) 'sync-ui-marshal.c'; else $(CYGPATH_W) '$(srcdir)/sync-ui-marshal.c'; fi`
+@am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sync_ui_gtk_CPPFLAGS) $(CPPFLAGS) $(sync_ui_gtk_CFLAGS) $(CFLAGS) -c -o sync_ui_gtk-sync-config-widget.obj `if test -f 'sync-config-widget.c'; then $(CYGPATH_W) 'sync-config-widget.c'; else $(CYGPATH_W) '$(srcdir)/sync-config-widget.c'; fi`
 
 sync_ui_moblin-main.o: main.c
 @am__fastdepCC_TRUE@   $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sync_ui_moblin_CPPFLAGS) $(CPPFLAGS) $(sync_ui_moblin_CFLAGS) $(CFLAGS) -MT sync_ui_moblin-main.o -MD -MP -MF $(DEPDIR)/sync_ui_moblin-main.Tpo -c -o sync_ui_moblin-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c
@@ -783,19 +776,19 @@ sync_ui_moblin-mux-icon-button.obj: mux-icon-button.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sync_ui_moblin_CPPFLAGS) $(CPPFLAGS) $(sync_ui_moblin_CFLAGS) $(CFLAGS) -c -o sync_ui_moblin-mux-icon-button.obj `if test -f 'mux-icon-button.c'; then $(CYGPATH_W) 'mux-icon-button.c'; else $(CYGPATH_W) '$(srcdir)/mux-icon-button.c'; fi`
 
-sync_ui_moblin-sync-ui-marshal.o: sync-ui-marshal.c
-@am__fastdepCC_TRUE@   $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sync_ui_moblin_CPPFLAGS) $(CPPFLAGS) $(sync_ui_moblin_CFLAGS) $(CFLAGS) -MT sync_ui_moblin-sync-ui-marshal.o -MD -MP -MF $(DEPDIR)/sync_ui_moblin-sync-ui-marshal.Tpo -c -o sync_ui_moblin-sync-ui-marshal.o `test -f 'sync-ui-marshal.c' || echo '$(srcdir)/'`sync-ui-marshal.c
-@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/sync_ui_moblin-sync-ui-marshal.Tpo $(DEPDIR)/sync_ui_moblin-sync-ui-marshal.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='sync-ui-marshal.c' object='sync_ui_moblin-sync-ui-marshal.o' libtool=no @AMDEPBACKSLASH@
+sync_ui_moblin-sync-config-widget.o: sync-config-widget.c
+@am__fastdepCC_TRUE@   $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sync_ui_moblin_CPPFLAGS) $(CPPFLAGS) $(sync_ui_moblin_CFLAGS) $(CFLAGS) -MT sync_ui_moblin-sync-config-widget.o -MD -MP -MF $(DEPDIR)/sync_ui_moblin-sync-config-widget.Tpo -c -o sync_ui_moblin-sync-config-widget.o `test -f 'sync-config-widget.c' || echo '$(srcdir)/'`sync-config-widget.c
+@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/sync_ui_moblin-sync-config-widget.Tpo $(DEPDIR)/sync_ui_moblin-sync-config-widget.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='sync-config-widget.c' object='sync_ui_moblin-sync-config-widget.o' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sync_ui_moblin_CPPFLAGS) $(CPPFLAGS) $(sync_ui_moblin_CFLAGS) $(CFLAGS) -c -o sync_ui_moblin-sync-ui-marshal.o `test -f 'sync-ui-marshal.c' || echo '$(srcdir)/'`sync-ui-marshal.c
+@am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sync_ui_moblin_CPPFLAGS) $(CPPFLAGS) $(sync_ui_moblin_CFLAGS) $(CFLAGS) -c -o sync_ui_moblin-sync-config-widget.o `test -f 'sync-config-widget.c' || echo '$(srcdir)/'`sync-config-widget.c
 
-sync_ui_moblin-sync-ui-marshal.obj: sync-ui-marshal.c
-@am__fastdepCC_TRUE@   $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sync_ui_moblin_CPPFLAGS) $(CPPFLAGS) $(sync_ui_moblin_CFLAGS) $(CFLAGS) -MT sync_ui_moblin-sync-ui-marshal.obj -MD -MP -MF $(DEPDIR)/sync_ui_moblin-sync-ui-marshal.Tpo -c -o sync_ui_moblin-sync-ui-marshal.obj `if test -f 'sync-ui-marshal.c'; then $(CYGPATH_W) 'sync-ui-marshal.c'; else $(CYGPATH_W) '$(srcdir)/sync-ui-marshal.c'; fi`
-@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/sync_ui_moblin-sync-ui-marshal.Tpo $(DEPDIR)/sync_ui_moblin-sync-ui-marshal.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='sync-ui-marshal.c' object='sync_ui_moblin-sync-ui-marshal.obj' libtool=no @AMDEPBACKSLASH@
+sync_ui_moblin-sync-config-widget.obj: sync-config-widget.c
+@am__fastdepCC_TRUE@   $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sync_ui_moblin_CPPFLAGS) $(CPPFLAGS) $(sync_ui_moblin_CFLAGS) $(CFLAGS) -MT sync_ui_moblin-sync-config-widget.obj -MD -MP -MF $(DEPDIR)/sync_ui_moblin-sync-config-widget.Tpo -c -o sync_ui_moblin-sync-config-widget.obj `if test -f 'sync-config-widget.c'; then $(CYGPATH_W) 'sync-config-widget.c'; else $(CYGPATH_W) '$(srcdir)/sync-config-widget.c'; fi`
+@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/sync_ui_moblin-sync-config-widget.Tpo $(DEPDIR)/sync_ui_moblin-sync-config-widget.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='sync-config-widget.c' object='sync_ui_moblin-sync-config-widget.obj' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sync_ui_moblin_CPPFLAGS) $(CPPFLAGS) $(sync_ui_moblin_CFLAGS) $(CFLAGS) -c -o sync_ui_moblin-sync-ui-marshal.obj `if test -f 'sync-ui-marshal.c'; then $(CYGPATH_W) 'sync-ui-marshal.c'; else $(CYGPATH_W) '$(srcdir)/sync-ui-marshal.c'; fi`
+@am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sync_ui_moblin_CPPFLAGS) $(CPPFLAGS) $(sync_ui_moblin_CFLAGS) $(CFLAGS) -c -o sync_ui_moblin-sync-config-widget.obj `if test -f 'sync-config-widget.c'; then $(CYGPATH_W) 'sync-config-widget.c'; else $(CYGPATH_W) '$(srcdir)/sync-config-widget.c'; fi`
 
 mostlyclean-libtool:
        -rm -f *.lo
@@ -945,15 +938,13 @@ distdir: $(DISTFILES)
          fi; \
        done
 check-am: all-am
-check: $(BUILT_SOURCES)
-       $(MAKE) $(AM_MAKEFLAGS) check-am
+check: check-am
 all-am: Makefile $(PROGRAMS) $(DATA)
 installdirs:
        for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(applicationsdir)" "$(DESTDIR)$(icondir)" "$(DESTDIR)$(gladedir)" "$(DESTDIR)$(themercdir)"; do \
          test -z "$$dir" || $(MKDIR_P) "$$dir"; \
        done
-install: $(BUILT_SOURCES)
-       $(MAKE) $(AM_MAKEFLAGS) install-am
+install: install-am
 install-exec: install-exec-am
 install-data: install-data-am
 uninstall: uninstall-am
@@ -978,7 +969,6 @@ distclean-generic:
 maintainer-clean-generic:
        @echo "This command is intended for maintainers to use"
        @echo "it deletes files that may require special tools to rebuild."
-       -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
 clean: clean-am
 
 clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am
@@ -1072,20 +1062,6 @@ sync-moblin.desktop: sync.desktop
 
 ui.xml: ui.glade
        $(GTK_BUILDER_CONV) $< $(@F)
-
-%-bindings.h: stamp-%-bindings.h
-       @true
-stamp-%-bindings.h: $(top_builddir)/src/dbus/interfaces/%.xml
-       $(DBUS_BINDING_TOOL) --mode=glib-client --prefix=syncevo $< > xgen-$(@F) \
-       && (cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%)) \
-       && rm -f xgen-$(@F) \
-       && echo timestamp > $(@F)
-
-sync-ui-marshal.h: $(srcdir)/sync-ui-marshal.list $(GLIB_GENMARSHAL)
-       $(GLIB_GENMARSHAL) $< --header --prefix=sync_ui_marshal > $@
-sync-ui-marshal.c: $(srcdir)/sync-ui-marshal.list sync-ui-marshal.h $(GLIB_GENMARSHAL)
-       echo "#include \"sync-ui-marshal.h\"" > $@ \
-       && $(GLIB_GENMARSHAL) --prefix=sync_ui_marshal $(srcdir)/sync-ui-marshal.list --body >> $@
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
 .NOEXPORT:
index c33ddeb..54961e4 100644 (file)
@@ -23,6 +23,7 @@
 
 enum {
        PROP_0,
+       PROP_TOGGLEABLE,
        PROP_PIXBUF_NORMAL,
        PROP_PIXBUF_ACTIVE,
        PROP_PIXBUF_PRELIGHT,
@@ -40,6 +41,9 @@ mux_icon_button_get_property (GObject *object, guint property_id,
     MuxIconButton *btn = MUX_ICON_BUTTON (object);
     
     switch (property_id) {
+    case PROP_TOGGLEABLE:
+        g_value_set_boolean (value, btn->toggleable);
+        break;
     case PROP_PIXBUF_NORMAL:
         g_value_set_object (value, mux_icon_button_get_pixbuf (btn, GTK_STATE_NORMAL));
         break;
@@ -68,6 +72,9 @@ mux_icon_button_set_property (GObject *object, guint property_id,
     GdkPixbuf *pixbuf;
     
     switch (property_id) {
+    case PROP_TOGGLEABLE:
+        btn->toggleable = g_value_get_boolean (value);
+        break;
     case PROP_PIXBUF_NORMAL:
         pixbuf = GDK_PIXBUF (g_value_get_object (value));
         mux_icon_button_set_pixbuf (btn, GTK_STATE_NORMAL, pixbuf);
@@ -127,9 +134,17 @@ mux_icon_button_expose (GtkWidget *widget,
     GdkRectangle dirty_area, btn_area;
     MuxIconButton *btn = MUX_ICON_BUTTON (widget);
     GdkPixbuf *pixbuf;
+    GtkStateType state;
+
+    if (btn->active) {
+        /* this is a active toggle button */
+        state = GTK_STATE_ACTIVE;
+    } else {
+        state = GTK_WIDGET_STATE (widget);
+    }
 
-    if (btn->pixbufs[GTK_WIDGET_STATE (widget)]) {
-        pixbuf = btn->pixbufs[GTK_WIDGET_STATE (widget)];
+    if (btn->pixbufs[state]) {
+        pixbuf = btn->pixbufs[state];
     } else {
         pixbuf = btn->pixbufs[GTK_STATE_NORMAL];
     }
@@ -155,10 +170,21 @@ mux_icon_button_expose (GtkWidget *widget,
 }
 
 static void
+mux_icon_button_clicked (GtkButton *button)
+{
+    MuxIconButton *icon_button = MUX_ICON_BUTTON (button);
+    
+    if (icon_button->toggleable) {
+        icon_button->active = !icon_button->active;
+    }
+}
+
+static void
 mux_icon_button_class_init (MuxIconButtonClass *klass)
 {
     GObjectClass *object_class = G_OBJECT_CLASS (klass);
     GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+    GtkButtonClass *button_class = GTK_BUTTON_CLASS (klass);
     GParamSpec *pspec;
 
     object_class->get_property = mux_icon_button_get_property;
@@ -168,6 +194,14 @@ mux_icon_button_class_init (MuxIconButtonClass *klass)
     widget_class->size_request = mux_icon_button_size_request;
     widget_class->expose_event = mux_icon_button_expose;
 
+    button_class->clicked = mux_icon_button_clicked;
+
+    pspec = g_param_spec_boolean ("toggleable",
+                                 "Toggleable",
+                                 "Is icon button button a toggle or normal",
+                                 FALSE,
+                                 G_PARAM_READWRITE);
+    g_object_class_install_property (object_class, PROP_TOGGLEABLE, pspec);
     pspec = g_param_spec_object ("normal-state-pixbuf",
                                  "Normal state pixbuf",
                                  "GdkPixbuf for GTK_STATE_NORMAL",
@@ -206,10 +240,11 @@ mux_icon_button_init (MuxIconButton *self)
 }
 
 GtkWidget*
-mux_icon_button_new (GdkPixbuf *normal_pixbuf)
+mux_icon_button_new (GdkPixbuf *normal_pixbuf, gboolean toggleable)
 {
     return g_object_new (MUX_TYPE_ICON_BUTTON, 
                          "normal-state-pixbuf", normal_pixbuf,
+                         "toggleable", toggleable,
                          NULL);
 }
 
@@ -233,3 +268,16 @@ mux_icon_button_get_pixbuf (MuxIconButton *button, GtkStateType state)
 {
     return button->pixbufs[state];
 }
+
+void
+mux_icon_button_set_active (MuxIconButton *button, gboolean active)
+{
+    button->active = active;
+    gtk_widget_queue_draw (GTK_WIDGET (button));
+}
+
+gboolean 
+mux_icon_button_get_active (MuxIconButton *button)
+{
+    return button->active;
+}
index 545fb86..a6e0130 100644 (file)
@@ -44,6 +44,9 @@ G_BEGIN_DECLS
 typedef struct {
     GtkButton parent;
     GdkPixbuf *pixbufs[5];
+
+    gboolean toggleable;
+    gboolean active;
 } MuxIconButton;
 
 typedef struct {
@@ -52,12 +55,17 @@ typedef struct {
 
 GType mux_icon_button_get_type (void);
 
-GtkWidget* mux_icon_button_new (GdkPixbuf *normal_pixbuf);
+GtkWidget* mux_icon_button_new (GdkPixbuf *normal_pixbuf, gboolean toggleable);
 
 void mux_icon_button_set_pixbuf (MuxIconButton *button, GtkStateType state, GdkPixbuf *pixbuf);
 
 GdkPixbuf* mux_icon_button_get_pixbuf (MuxIconButton *button, GtkStateType state);
 
+/* for togglebuttons */
+void mux_icon_button_set_active (MuxIconButton *button, gboolean active);
+
+gboolean mux_icon_button_get_active (MuxIconButton *button);
+
 G_END_DECLS
 
 #endif
index 058cf51..82f78ff 100644 (file)
@@ -47,7 +47,7 @@ enum {
 };
 
 enum {
-  SETTINGS_CLICKED,
+  SETTINGS_VISIBILITY_CHANGED,
   LAST_SIGNAL
 };
 
@@ -159,12 +159,37 @@ mux_window_forall (GtkContainer *container,
     MuxWindow *mux_win = MUX_WINDOW (container);
     GtkBin *bin = GTK_BIN (container);
 
-    /* FIXME: call parents forall instead */
+    /* FIXME: call parents forall instead */
     if (bin->child)
         (* callback) (bin->child, callback_data);
 
     if (mux_win->title_bar)
         (* callback) (mux_win->title_bar, callback_data);
+    if (mux_win->settings)
+        (* callback) (mux_win->settings, callback_data);
+}
+
+static void
+mux_window_add (GtkContainer *container,
+                GtkWidget *widget)
+{
+    MuxWindowClass *klass;
+    GtkContainerClass *parent_container_class;
+    GtkBin *bin = GTK_BIN (container);
+
+    klass = MUX_WINDOW_GET_CLASS (container);
+    parent_container_class = GTK_CONTAINER_CLASS (g_type_class_peek_parent (klass));
+
+    if (!bin->child) {
+        GtkWidget *w;
+        /* create a dummy container so we can hide the contents when settings 
+         * are shown */
+        w = gtk_vbox_new (FALSE, 0);
+        parent_container_class->add (container, w);
+        if (!MUX_WINDOW (container)->settings_visible)
+            gtk_widget_show (w);
+    }
+    gtk_container_add (GTK_CONTAINER (bin->child), widget);
 }
 
 static void
@@ -172,13 +197,23 @@ mux_window_remove (GtkContainer *container,
                    GtkWidget *child)
 {
     MuxWindow *win = MUX_WINDOW (container);
+    GtkBin *bin = GTK_BIN (container);
 
     if (child == win->title_bar) {
         gtk_widget_unparent (win->title_bar);
         win->title_bar = NULL;
         win->title_label = NULL;
-    } else {
-        GTK_CONTAINER_CLASS (mux_window_parent_class)->remove (container, child);
+    } else if (child == win->settings) {
+        gtk_widget_unparent (win->settings);
+        win->settings = NULL;
+    } else if (bin->child) {
+        if (bin->child == child) {
+            /* should call parents remove... */
+            gtk_widget_unparent (child);
+            bin->child = NULL;
+        } else {
+            gtk_container_remove (GTK_CONTAINER (bin->child), child);
+        }
     }
 }
 
@@ -197,6 +232,8 @@ mux_window_size_request (GtkWidget *widget,
         gtk_widget_size_request (mux_win->title_bar, &req);
     if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
         gtk_widget_size_request (bin->child, &req);
+    if (mux_win->settings && GTK_WIDGET_VISIBLE (mux_win->settings))
+        gtk_widget_size_request (mux_win->settings, &req);
 
     requisition->width = 1024;
     requisition->height = 600;
@@ -249,10 +286,13 @@ mux_window_size_allocate (GtkWidget *widget,
         gtk_widget_size_allocate (bin->child, &child_allocation);
     }
 
+    if (mux_win->settings && GTK_WIDGET_VISIBLE (mux_win->settings)) {
+        gtk_widget_size_allocate (mux_win->settings, &child_allocation);
+    }
+
     mux_win->child_allocation = child_allocation;
 }
 
-
 static void
 mux_window_class_init (MuxWindowClass *klass)
 {
@@ -272,6 +312,7 @@ mux_window_class_init (MuxWindowClass *klass)
 
     container_class->forall = mux_window_forall;
     container_class->remove = mux_window_remove;
+    container_class->add = mux_window_add;
 
     pspec = g_param_spec_uint ("title-bar-height",
                                "Title bar height",
@@ -308,11 +349,11 @@ mux_window_class_init (MuxWindowClass *klass)
                                      PROP_DECORATIONS,
                                      pspec);
 
-    mux_window_signals[SETTINGS_CLICKED] = 
-            g_signal_new ("settings-clicked",
+    mux_window_signals[SETTINGS_VISIBILITY_CHANGED] = 
+            g_signal_new ("settings-visibility-changed",
                           G_OBJECT_CLASS_TYPE (object_class),
                           G_SIGNAL_RUN_FIRST,
-                          G_STRUCT_OFFSET (MuxWindowClass, settings_clicked),
+                          G_STRUCT_OFFSET (MuxWindowClass, settings_visibility_changed),
                           NULL, NULL,
                           g_cclosure_marshal_VOID__VOID,
                           G_TYPE_NONE, 0, NULL);
@@ -320,9 +361,47 @@ mux_window_class_init (MuxWindowClass *klass)
 }
 
 static void
-mux_window_settings_clicked (MuxWindow *window)
+update_show_settings (MuxWindow *window)
 {
-    g_signal_emit (window, mux_window_signals[SETTINGS_CLICKED], 0, NULL);
+    GtkBin *bin = GTK_BIN (window);
+
+    if (window->settings_visible) {
+        if (bin->child) {
+            gtk_widget_hide (bin->child);
+        }
+        if (window->settings){
+            gtk_widget_show (window->settings);
+            gtk_widget_map (window->settings);
+            if (window->settings_title) {
+                gtk_label_set_text (GTK_LABEL (window->title_label), 
+                                    window->settings_title);
+            }
+        }
+    } else {
+        if (window->settings) {
+            gtk_widget_hide (window->settings);
+        }
+        if (bin->child) {
+            gtk_widget_show (bin->child);
+        }
+        /* reset the window title */
+        gtk_label_set_text (GTK_LABEL (window->title_label), 
+                            gtk_window_get_title(GTK_WINDOW (window)));
+    }
+    g_signal_emit (window, mux_window_signals[SETTINGS_VISIBILITY_CHANGED], 0);
+}
+
+static void
+mux_window_settings_clicked (MuxIconButton *button, MuxWindow *window)
+{
+    gboolean active;
+    active = mux_icon_button_get_active (button);;
+
+    if (window->settings_visible != active) {
+        window->settings_visible = active;
+
+        update_show_settings (window);
+    }
 }
 
 static void
@@ -377,7 +456,7 @@ load_icon (MuxWindow *window, const char *icon_name)
 static void
 mux_window_build_title_bar (MuxWindow *window)
 {
-    GtkWidget *box, *btn, *sep;
+    GtkWidget *box, *btn;
     GdkPixbuf *pixbuf, *pixbuf_hover;
 
     if (window->title_bar) {
@@ -413,23 +492,19 @@ mux_window_build_title_bar (MuxWindow *window)
     }
 
     if (window->decorations & MUX_DECOR_SETTINGS) {
-        sep = gtk_vseparator_new ();
-        gtk_box_pack_end (GTK_BOX (box), sep, FALSE, FALSE, 0);
-        gtk_widget_show (sep);
-    }
-
-    if (window->decorations & MUX_DECOR_SETTINGS) {
         pixbuf = load_icon (window, "settings");
         pixbuf_hover = load_icon (window, "settings_hover");
-        btn = g_object_new (MUX_TYPE_ICON_BUTTON,
-                            "normal-state-pixbuf", pixbuf,
-                            "prelight-state-pixbuf", pixbuf_hover,
-                            NULL);
-        gtk_widget_set_name (btn, "mux_icon_button_settings");
-        g_signal_connect_swapped (btn, "clicked", 
-                                  G_CALLBACK (mux_window_settings_clicked), window);
-        gtk_box_pack_end (GTK_BOX (box), btn, FALSE, FALSE, 0);
-        gtk_widget_show (btn);
+        window->settings_button = g_object_new (MUX_TYPE_ICON_BUTTON,
+                                  "normal-state-pixbuf", pixbuf,
+                                  "prelight-state-pixbuf", pixbuf_hover,
+                                  "active-state-pixbuf", pixbuf_hover,
+                                  "toggleable", TRUE,
+                                  NULL);
+        gtk_widget_set_name (window->settings_button, "mux_icon_button_settings");
+        g_signal_connect (window->settings_button, "clicked", 
+                          G_CALLBACK (mux_window_settings_clicked), window);
+        gtk_box_pack_end (GTK_BOX (box), window->settings_button, FALSE, FALSE, 0);
+        gtk_widget_show (window->settings_button);
     }
 
     mux_window_update_style (window);
@@ -445,7 +520,7 @@ mux_window_title_changed (MuxWindow *window,
                           GParamSpec *pspec,
                           gpointer user_data)
 {
-    if (window->title_label) {
+    if (window->title_label && !window->settings_visible) {
         gtk_label_set_text (GTK_LABEL (window->title_label), 
                             gtk_window_get_title (GTK_WINDOW (window)));
     }
@@ -505,3 +580,66 @@ mux_window_get_decorations (MuxWindow *window)
 
     return window->decorations;
 }
+
+void
+mux_window_set_settings_widget (MuxWindow *window, GtkWidget *widget)
+{
+    if (widget != window->settings) {
+        if (window->settings) {
+            gtk_widget_unparent (window->settings);
+        }
+
+        window->settings = widget;
+
+        if (widget) {
+            gtk_widget_set_parent (widget, GTK_WIDGET (window));
+        }
+    }
+}
+
+GtkWidget*
+mux_window_get_settings_widget (MuxWindow *window)
+{
+    return window->settings;
+}
+
+void
+mux_window_set_settings_visible (MuxWindow *window, gboolean visible)
+{
+    if (window->settings_visible != visible) {
+        window->settings_visible = visible;
+
+        update_show_settings (window);
+
+        if (window->settings_button)
+            mux_icon_button_set_active (MUX_ICON_BUTTON (window->settings_button),
+                                        visible);
+    }
+}
+
+gboolean
+mux_window_get_settings_visible (MuxWindow *window)
+{
+    return window->settings_visible;
+}
+
+void
+mux_window_set_settings_title (MuxWindow *window, const char *title)
+{
+    if (window->settings_title) {
+        g_free (window->settings_title);
+    }
+
+    window->settings_title = g_strdup (title);
+
+    if (window->settings_visible) {
+        gtk_label_set_text (GTK_LABEL (window->title_label), 
+                            window->settings_title);
+    }
+}
+
+const char*
+mux_window_get_settings_title (MuxWindow *window)
+{
+    return window->settings_title;
+}
index 2f63149..8bf1338 100644 (file)
@@ -52,18 +52,24 @@ typedef struct {
     GtkWidget *title_bar;
     GtkWidget *title_label;
     GtkWidget *title_alignment;
+    GtkWidget *settings;
+    GtkWidget *settings_button;
 
     GtkAllocation child_allocation;
 
     MuxDecorations decorations;
     GdkColor title_bar_color;
     guint title_bar_height;
+    
+    gboolean settings_visible;
+
+    char *settings_title;
 } MuxWindow;
 
 typedef struct {
     GtkWindowClass parent_class;
 
-    void (*settings_clicked) (MuxWindow *window);
+    void (*settings_visibility_changed) (MuxWindow *window);
 } MuxWindowClass;
 
 GType mux_window_get_type (void);
@@ -72,6 +78,17 @@ GtkWidget* mux_window_new (void);
 
 void mux_window_set_decorations (MuxWindow *window, MuxDecorations decorations);
 MuxDecorations mux_window_get_decorations (MuxWindow *window);
+
+void mux_window_set_settings_widget (MuxWindow *window, GtkWidget *widget);
+GtkWidget *mux_window_get_settings_widget (MuxWindow *window);
+
+void mux_window_set_settings_title (MuxWindow *window, const char *title);
+const char *mux_window_get_settings_title (MuxWindow *window);
+
+void mux_window_set_settings_visible (MuxWindow *window, gboolean visible);
+gboolean mux_window_get_settings_visible (MuxWindow *window);
+
+
 G_END_DECLS
 
 #endif
diff --git a/src/gtk-ui/sync-config-widget.c b/src/gtk-ui/sync-config-widget.c
new file mode 100644 (file)
index 0000000..767cf92
--- /dev/null
@@ -0,0 +1,1404 @@
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <dbus/dbus-glib.h>
+
+#include "sync-ui.h"
+#include "sync-config-widget.h"
+
+#define INDICATOR_SIZE 16
+#define CHILD_PADDING 3
+
+G_DEFINE_TYPE (SyncConfigWidget, sync_config_widget, GTK_TYPE_CONTAINER)
+
+enum
+{
+  PROP_0,
+
+  PROP_SERVER,
+  PROP_NAME,
+  PROP_CURRENT,
+  PROP_HAS_TEMPLATE,
+  PROP_CONFIGURED,
+  PROP_UNSET,
+  PROP_EXPANDED,
+};
+
+enum {
+       SIGNAL_CHANGED,
+       LAST_SIGNAL
+};
+static guint32 signals[LAST_SIGNAL] = {0, };
+
+static void sync_config_widget_update_label (SyncConfigWidget *self);
+
+static void
+remove_child (GtkWidget *widget, GtkContainer *container)
+{
+    gtk_container_remove (container, widget);
+}
+
+const char*
+get_service_description (const char *service)
+{
+    if (!service)
+        return "";
+
+    if (strcmp (service, "ScheduleWorld") == 0) {
+        return _("ScheduleWorld enables you to keep your contacts, events, "
+                 "tasks, and notes in sync.");
+    }else if (strcmp (service, "Google") == 0) {
+        return _("Google Sync can backup and synchronize your Address Book "
+                 "with your Gmail contacts.");
+    }else if (strcmp (service, "Funambol") == 0) {
+        /* TRANSLATORS: Please include the word "demo" (or the equivalent in
+           your language): Funambol is going to be a 90 day demo service
+           in the future */
+        return _("Backup your contacts and calendar. Sync with a single"
+                 "click, anytime, anywhere (DEMO).");
+    }
+
+    return "";
+}
+
+static void
+stop_clicked_cb (GtkButton *btn, SyncConfigWidget *self)
+{
+    sync_config_widget_set_current (self, FALSE);
+    g_signal_emit (self, signals[SIGNAL_CHANGED], 0);
+}
+
+static void
+update_source_config (char *name,
+                      GHashTable *source_configuration,
+                      SyncConfigWidget *self)
+{
+    const char *uri;
+    GtkEntry *entry;
+
+    entry = GTK_ENTRY (g_hash_table_lookup (self->uri_entries, name));
+    if (!entry) {
+        g_warning ("No entry found for source %s", name);
+        return;
+    }
+
+    uri = gtk_entry_get_text (entry);
+    g_hash_table_insert (source_configuration, g_strdup ("uri"), g_strdup (uri));
+}
+
+static void
+set_config_cb (SyncevoSession *session,
+               GError *error,
+               SyncConfigWidget *self)
+{
+    if (error) {
+        g_warning ("Error in Session.SetConfig: %s", error->message);
+        g_error_free (error);
+        /* TODO show in UI: save failed in service list */
+        return;
+    }
+
+    g_object_unref (session);
+
+    g_signal_emit (self, signals[SIGNAL_CHANGED], 0);
+}
+
+static void
+sync_config_widget_save_config (SyncConfigWidget *self,
+                                SyncevoSession *session,
+                                gboolean delete)
+{
+    if (delete) {
+        syncevo_config_free (self->config->config);
+        self->config->config = g_hash_table_new (g_str_hash, g_str_equal);
+    } else {
+        sync_config_widget_set_current (self, TRUE);
+    }
+    syncevo_session_set_config (session,
+                                FALSE,
+                                FALSE,
+                                self->config->config,
+                                (SyncevoSessionGenericCb)set_config_cb,
+                                self);
+}
+
+typedef struct save_config_data {
+    SyncConfigWidget *widget;
+    gboolean delete;
+} save_config_data;
+
+static void
+status_changed_for_config_write_cb (SyncevoSession *session,
+                                    SyncevoSessionStatus status,
+                                    guint error_code,
+                                    SyncevoSourceStatuses *source_statuses,
+                                    save_config_data *data)
+{
+    if (status == SYNCEVO_STATUS_IDLE) {
+        sync_config_widget_save_config (data->widget, session, data->delete);
+    }
+}
+
+static void
+get_status_for_config_write_cb (SyncevoSession *session,
+                                SyncevoSessionStatus status,
+                                guint error_code,
+                                SyncevoSourceStatuses *source_statuses,
+                                GError *error,
+                                save_config_data *data)
+{
+    if (error) {
+        g_warning ("Error in Session.GetStatus: %s", error->message);
+        g_error_free (error);
+        g_object_unref (session);
+        /* TODO show in UI: save failed in service list */
+        return;
+    }
+
+    syncevo_source_statuses_free (source_statuses);
+
+    if (status == SYNCEVO_STATUS_IDLE) {
+        sync_config_widget_save_config (data->widget, session, data->delete);
+    }
+}
+
+
+static void
+start_session_for_config_write_cb (SyncevoServer *server,
+                                   char *path,
+                                   GError *error,
+                                   save_config_data *data)
+{
+    SyncevoSession *session;
+
+    if (error) {
+        g_warning ("Error in Server.StartSession: %s", error->message);
+        g_error_free (error);
+        /* TODO show in UI: save failed in service list */
+        return;
+    }
+
+    session = syncevo_session_new (path);
+
+    /* we want to know about status changes to our session */
+    g_signal_connect (session, "status-changed",
+                      G_CALLBACK (status_changed_for_config_write_cb), data);
+    syncevo_session_get_status (session,
+                                (SyncevoSessionGetStatusCb)get_status_for_config_write_cb,
+                                data);
+}
+
+static void
+use_clicked_cb (GtkButton *btn, SyncConfigWidget *self)
+{
+    SyncevoConfig *config;
+    save_config_data *data;
+    const char *username, *password, *sync_url, *name;
+    char *real_url;
+
+    if (!self->config) {
+        return;
+    }
+
+    config = self->config->config;
+
+    name = gtk_entry_get_text (GTK_ENTRY (self->entry));
+
+    username = gtk_entry_get_text (GTK_ENTRY (self->username_entry));
+    syncevo_config_set_value (config, NULL, "username", username);
+
+    sync_url = gtk_entry_get_text (GTK_ENTRY (self->baseurl_entry));
+    /* make a wild guess if no scheme in url */
+    if (strstr (sync_url, "://") == NULL) {
+        real_url = g_strdup_printf ("http://%s", sync_url);
+    } else {
+        real_url = g_strdup (sync_url);
+    }
+    syncevo_config_set_value (config, NULL, "syncURL", real_url);
+
+    password = gtk_entry_get_text (GTK_ENTRY (self->password_entry));
+    syncevo_config_set_value (config, NULL, "password", password);
+
+
+    if (!name || strlen (name) == 0 ||
+        !sync_url || strlen (sync_url) == 0) {
+        /* TODO show in UI: service settings missing name or url */
+        show_error_dialog (GTK_WIDGET (self), 
+                           _("Service must have a name and server URL"));
+        return;
+    }
+
+    syncevo_config_set_value (config, NULL, "defaultPeer", name);
+
+    syncevo_config_foreach_source (config,
+                                   (ConfigFunc)update_source_config,
+                                   self);
+
+    data = g_slice_new (save_config_data);
+    data->widget = self;
+    data->delete = FALSE;
+    syncevo_server_start_session (self->server,
+                                  name,
+                                  (SyncevoServerStartSessionCb)start_session_for_config_write_cb,
+                                  data);
+
+    g_free (real_url);
+}
+
+static void
+reset_delete_clicked_cb (GtkButton *btn, SyncConfigWidget *self)
+{
+    save_config_data *data;
+
+    if (!self->config) {
+        return;
+    }
+
+    data = g_slice_new (save_config_data);
+    data->widget = self;
+    data->delete = TRUE;
+    syncevo_server_start_session (self->server,
+                                  self->config->name,
+                                  (SyncevoServerStartSessionCb)start_session_for_config_write_cb,
+                                  data);
+}
+
+static void update_buttons (SyncConfigWidget *self)
+{
+    if (self->has_template) {
+        /* TRANSLATORS: button labels */
+        gtk_button_set_label (GTK_BUTTON (self->reset_delete_button),
+                              _("Reset service"));
+    } else {
+        gtk_button_set_label (GTK_BUTTON (self->reset_delete_button),
+                              _("Delete service"));
+        if (self->configured) {
+            gtk_widget_show (GTK_WIDGET (self->reset_delete_button));
+        } else {
+            gtk_widget_hide (GTK_WIDGET (self->reset_delete_button));
+        }
+    }
+
+    if (self->unset || self->current) {
+        gtk_button_set_label (GTK_BUTTON (self->use_button),
+                              _("Save and use"));
+    } else { 
+        gtk_button_set_label (GTK_BUTTON (self->use_button),
+                              _("Save and replace\ncurrent service"));
+    }
+
+    if (self->current) {
+        gtk_widget_show (self->stop_button);
+    } else { 
+        gtk_widget_hide (self->stop_button);
+    }
+}
+
+typedef struct source_row_data {
+    GtkWidget *label;
+    GtkWidget *entry;
+} source_row_data;
+
+static void
+check_source_cb (SyncevoServer *server,
+                 GError *error,
+                 source_row_data *data)
+{
+    gboolean show = TRUE;
+
+    if (error) {
+        if(error->code == DBUS_GERROR_REMOTE_EXCEPTION &&
+           dbus_g_error_has_name (error, SYNCEVO_DBUS_ERROR_SOURCE_UNUSABLE)) {
+
+            show = FALSE;
+        } else if (error->code == DBUS_GERROR_REMOTE_EXCEPTION &&
+                   dbus_g_error_has_name (error,
+                                          SYNCEVO_DBUS_ERROR_NO_SUCH_CONFIG)){
+            /* apparently templates can't be checked... */
+            /* TODO: could use a temporary config to do it... */
+        } else {
+            g_warning ("CheckSource failed: %s", error->message);
+            /* non-fatal, ignore in UI */
+        }
+        g_error_free (error);
+    }
+
+    if (show) {
+        gtk_widget_show (data->label);
+        gtk_widget_show (data->entry);
+    }
+    g_slice_free (source_row_data, data);
+}
+
+static void
+init_source (char *name,
+             GHashTable *source_configuration,
+             SyncConfigWidget *self)
+{
+    char *str, *pretty_name;
+    const char *uri;
+    guint row;
+    source_row_data *row_data;
+
+    row_data = g_slice_new (source_row_data);
+
+    g_object_get (self->server_settings_table,
+                  "n-rows", &row,
+                  NULL);
+
+    uri = g_hash_table_lookup (source_configuration, "uri");
+    pretty_name = get_pretty_source_name (name);
+
+    /* TRANSLATORS: label for an entry in service configuration.
+     * Placeholder is a source  name in settings window. 
+     * Example: "Addressbook URI" */
+    str = g_strdup_printf (_("%s URI"), pretty_name);
+    row_data->label = gtk_label_new (str);
+    g_free (str);
+    g_free (pretty_name);
+
+    gtk_misc_set_alignment (GTK_MISC (row_data->label), 1.0, 0.5);
+    gtk_table_attach (GTK_TABLE (self->server_settings_table), row_data->label,
+                      0, 1, row, row + 1, GTK_FILL, GTK_EXPAND, 0, 0);
+
+    row_data->entry = gtk_entry_new ();
+    gtk_entry_set_max_length (GTK_ENTRY (row_data->entry), 99);
+    gtk_entry_set_width_chars (GTK_ENTRY (row_data->entry), 80);
+    if (uri) {
+        gtk_entry_set_text (GTK_ENTRY (row_data->entry), uri);
+    }
+    g_hash_table_insert (self->uri_entries, name, row_data->entry);
+    gtk_table_attach_defaults (GTK_TABLE (self->server_settings_table), row_data->entry,
+                               1, 2, row, row + 1);
+
+    syncevo_server_check_source (self->server,
+                                 self->config->name,
+                                 name,
+                                 (SyncevoServerGenericCb)check_source_cb,
+                                 row_data);
+}
+
+static void
+sync_config_widget_update_expander (SyncConfigWidget *self)
+{
+    char *username = "";
+    char *password = "";
+    char *sync_url = "";
+    GtkWidget *label;
+    SyncevoConfig *config = self->config->config;
+
+    gtk_container_foreach (GTK_CONTAINER (self->server_settings_table),
+                           (GtkCallback)remove_child,
+                           self->server_settings_table);
+    gtk_table_resize (GTK_TABLE (self->server_settings_table), 
+                      2, 1);
+
+    if (self->config->name) {
+        gtk_entry_set_text (GTK_ENTRY (self->entry), self->config->name);
+    }
+
+    gtk_label_set_text (GTK_LABEL (self->description_label),
+                        get_service_description (self->config->name));
+
+    /* TODO set expanded status based on user pref? */
+
+    update_buttons (self);
+
+    syncevo_config_get_value (config, NULL, "username", &username);
+    syncevo_config_get_value (config, NULL, "password", &password);
+    syncevo_config_get_value (config, NULL, "syncURL", &sync_url);
+
+    if (username) {
+        gtk_entry_set_text (GTK_ENTRY (self->username_entry), username);
+    }
+    if (password) {
+        gtk_entry_set_text (GTK_ENTRY (self->password_entry), password);
+    }
+
+    // TRANSLATORS: label of a entry in service configuration
+    label = gtk_label_new (_("Server URL"));
+    gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
+    gtk_widget_show (label);
+    gtk_table_attach (GTK_TABLE (self->server_settings_table), label,
+                      0, 1, 0, 1, GTK_FILL, GTK_EXPAND, 0, 0);
+
+    self->baseurl_entry = gtk_entry_new ();
+    gtk_entry_set_max_length (GTK_ENTRY (self->baseurl_entry), 99);
+    gtk_entry_set_width_chars (GTK_ENTRY (self->baseurl_entry), 80);
+    if (sync_url) {
+        gtk_entry_set_text (GTK_ENTRY (self->baseurl_entry), sync_url);
+    }
+    gtk_widget_show (self->baseurl_entry);
+
+    gtk_table_attach_defaults (GTK_TABLE (self->server_settings_table),
+                               self->baseurl_entry,
+                               1, 2, 0, 1);
+
+    /* update source uris */
+    if (self->uri_entries) {
+        g_hash_table_destroy (self->uri_entries);
+    }
+    self->uri_entries = g_hash_table_new (g_str_hash, g_str_equal);
+    syncevo_config_foreach_source (config,
+                                   (ConfigFunc)init_source,
+                                   self);
+
+}
+
+static void
+setup_service_clicked (GtkButton *btn, SyncConfigWidget *self)
+{
+    sync_config_widget_set_expanded (self, TRUE);
+}
+
+static void
+server_settings_expand_cb (GtkExpander *expander, SyncConfigWidget *self)
+{
+    if (gtk_expander_get_expanded (expander)) {
+        /* TRANSLATORS: this is the epander label for server settings */
+        gtk_expander_set_label (expander, _("Hide server settings"));
+    } else {
+        gtk_expander_set_label (expander, _("Show server settings"));
+    }
+}
+
+static GdkPixbuf*
+load_icon (const char *uri, guint icon_size)
+{
+    GError *error = NULL;
+    GdkPixbuf *pixbuf;
+    const char *filename;
+    
+    if (uri && strlen (uri) > 0) {
+        if (g_str_has_prefix (uri, "file://")) {
+            filename = uri+7;
+        } else {
+            g_warning ("only file:// icon uri is supported: %s", uri);
+            filename = THEMEDIR "sync-generic.png";
+        }
+    } else {
+        filename = THEMEDIR "sync-generic.png";
+    }
+    pixbuf = gdk_pixbuf_new_from_file_at_scale (filename,
+                                                icon_size, icon_size,
+                                                TRUE, &error);
+
+    if (!pixbuf) {
+        g_warning ("Failed to load service icon: %s", error->message);
+        g_error_free (error);
+        return NULL;
+    }
+
+    return pixbuf;
+}
+
+static void
+sync_config_widget_update_label (SyncConfigWidget *self)
+{
+    if (self->config && self->config->name && self->config->config) {
+        char *url;
+        char *str;
+
+        syncevo_config_get_value (self->config->config, NULL, "WebURL", &url);
+
+        if (self->current) {
+            str = g_strdup_printf ("<b>%s</b>", self->config->name);
+        } else {
+            str = g_strdup_printf ("%s", self->config->name);
+        }
+        if (!self->has_template) {
+            /* TRANSLATORS: service title for services that are not based on a 
+             * template in service list, the placeholder is the name of the service */
+            char *tmp = g_strdup_printf (_("%s - manually setup"), str);
+            g_free (str);
+            str = tmp;
+        } else if (url && strlen (url) > 0) {
+            char *tmp = g_strdup_printf ("%s -",str);
+            g_free (str);
+            str = tmp;
+        }
+
+        gtk_label_set_markup (GTK_LABEL (self->label), str);
+        g_free (str);
+    }
+}
+
+void
+sync_config_widget_set_unset (SyncConfigWidget *self,
+                              gboolean unset)
+{
+    self->unset = unset;
+
+    update_buttons (self);
+}
+
+void
+sync_config_widget_set_current (SyncConfigWidget *self,
+                                gboolean current)
+{
+    if (self->current != current) {
+        self->current = current;
+        sync_config_widget_update_label (self);
+    }
+}
+
+static void
+set_session (SyncConfigWidget *self, const char *path)
+{
+    g_free (self->running_session);
+    self->running_session = g_strdup (path);
+
+    gtk_widget_set_sensitive (GTK_WIDGET (self->reset_delete_button),
+                              !self->running_session);
+    gtk_widget_set_sensitive (GTK_WIDGET (self->use_button),
+                              !self->running_session);
+
+    /* TODO: maybe add a explanation text somewhere:
+     * "Configuration changes are not possible while a sync is in progress" */
+}
+
+static void
+session_changed_cb (SyncevoServer *server,
+                    char *path,
+                    gboolean started,
+                    SyncConfigWidget *self)
+{
+
+    if (started) {
+        set_session (self, path);
+    } else if (self->running_session &&
+               strcmp (self->running_session, path) == 0 ) {
+        set_session (self, NULL);
+    }
+}
+
+static void
+get_sessions_cb (SyncevoServer *server,
+                 SyncevoSessions *sessions,
+                 GError *error,
+                 SyncConfigWidget *self)
+{
+    if (error) {
+        g_warning ("Server.GetSessions failed: %s", error->message);
+        g_error_free (error);
+        /* non-fatal, ignore in UI */
+        return;
+    }
+
+    set_session (self, syncevo_sessions_index (sessions, 0));
+    syncevo_sessions_free (sessions);
+}
+
+void
+sync_config_widget_set_server (SyncConfigWidget *self,
+                               SyncevoServer *server)
+{
+    if (self->server) {
+        g_signal_handlers_disconnect_by_func (self->server,
+                                              session_changed_cb,
+                                              self);
+        g_object_unref (self->server);
+        self->server = NULL;
+    }
+    if (!server && !self->server) {
+        return;
+    }
+
+    self->server = g_object_ref (server);
+
+    /* monitor sessions so we can set editing buttons insensitive */
+    g_signal_connect (self->server, "session-changed",
+                      G_CALLBACK (session_changed_cb), self);
+
+    /* TODO: this is stupid, every widget running the same dbus call*/
+    syncevo_server_get_sessions (self->server,
+                                 (SyncevoServerGetSessionsCb)get_sessions_cb,
+                                 self);
+}
+
+static void
+sync_config_widget_set_name (SyncConfigWidget *self,
+                             const char *name)
+{
+    self->config = g_slice_new0 (server_config);
+    self->config->name = g_strdup (name);
+}
+
+static void
+sync_config_widget_set_property (GObject      *object,
+                                        guint         property_id,
+                                        const GValue *value,
+                                        GParamSpec   *pspec)
+{
+    SyncConfigWidget *self = SYNC_CONFIG_WIDGET (object);
+
+    switch (property_id) {
+    case PROP_SERVER:
+        sync_config_widget_set_server (self, g_value_get_pointer (value));
+        break;
+    case PROP_NAME:
+        sync_config_widget_set_name (self, g_value_get_string (value));
+        break;
+    case PROP_CURRENT:
+        sync_config_widget_set_current (self, g_value_get_boolean (value));
+        break;
+    case PROP_HAS_TEMPLATE:
+        sync_config_widget_set_has_template (self, g_value_get_boolean (value));
+        break;
+    case PROP_CONFIGURED:
+        sync_config_widget_set_configured (self, g_value_get_boolean (value));
+        break;
+    case PROP_UNSET:
+        sync_config_widget_set_unset (self, g_value_get_boolean (value));
+        break;
+    case PROP_EXPANDED:
+        sync_config_widget_set_expanded (self, g_value_get_boolean (value));
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    }
+}
+
+static void
+sync_config_widget_get_property (GObject    *object,
+                                 guint       property_id,
+                                 GValue     *value,
+                                 GParamSpec *pspec)
+{
+    SyncConfigWidget *self = SYNC_CONFIG_WIDGET (object);
+
+    switch (property_id) {
+    case PROP_SERVER:
+        g_value_set_pointer (value, self->server);
+    case PROP_NAME:
+        if (self->config)
+            g_value_set_string (value, self->config->name);
+        else
+            g_value_set_string (value, NULL);
+    case PROP_CURRENT:
+        g_value_set_boolean (value, self->current);
+    case PROP_HAS_TEMPLATE:
+        g_value_set_boolean (value, self->has_template);
+    case PROP_CONFIGURED:
+        g_value_set_boolean (value, self->configured);
+    case PROP_UNSET:
+        g_value_set_boolean (value, self->unset);
+    case PROP_EXPANDED:
+      g_value_set_boolean (value, self->expanded);
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    }
+}
+
+static void
+sync_config_widget_dispose (GObject *object)
+{
+    SyncConfigWidget *self = SYNC_CONFIG_WIDGET (object);
+
+    sync_config_widget_set_server (self, NULL);
+
+    G_OBJECT_CLASS (sync_config_widget_parent_class)->dispose (object);
+}
+
+static void
+init_default_config (server_config *config)
+{
+    g_free (config->name);
+    /* TRANSLATORS: title in service list for new services
+       (there will be a entry to the right of the title) */
+    config->name = g_strdup (_(""));
+
+    syncevo_config_set_value (config->config, NULL, "username", "");
+    syncevo_config_set_value (config->config, NULL, "password", "");
+    syncevo_config_set_value (config->config, NULL, "syncURL", "");
+    syncevo_config_set_value (config->config, NULL, "WebURL", "");
+    syncevo_config_set_value (config->config, "memo", "uri", "");
+    syncevo_config_set_value (config->config, "todo", "uri", "");
+    syncevo_config_set_value (config->config, "addressbook", "uri", "");
+    syncevo_config_set_value (config->config, "calendar", "uri", "");
+
+}
+
+static void
+sync_config_widget_real_init (SyncConfigWidget *self,
+                              SyncevoConfig *config)
+{
+    char *url, *icon;
+    GdkPixbuf *buf;
+    server_config_init (self->config, config);
+    if (self->config->name &&
+        strcmp (self->config->name, "default") == 0) {
+
+        init_default_config (self->config);
+        gtk_widget_show (self->entry);
+    } else {
+        /**/
+        gtk_widget_hide (self->entry);
+    }
+
+    syncevo_config_get_value (self->config->config, NULL, "syncURL", &url);
+    syncevo_config_get_value (self->config->config, NULL, "IconURI", &icon);
+
+    buf = load_icon (icon, SYNC_UI_LIST_ICON_SIZE);
+    gtk_image_set_from_pixbuf (GTK_IMAGE (self->image), buf);
+    g_object_unref (buf);
+
+    if (url && strlen (url) > 0) {
+        gtk_link_button_set_uri (GTK_LINK_BUTTON (self->link), url);
+        gtk_widget_show (self->link);
+    } else {
+        gtk_widget_hide (self->link);
+    }
+
+    sync_config_widget_update_label (self);
+    sync_config_widget_update_expander (self);
+
+    if (self->showing) {
+        gtk_widget_show (GTK_WIDGET (self));
+
+        /* hack to get focus in the right place on "Setup new service" */
+        if (GTK_WIDGET_VISIBLE (self->entry)) {
+            gtk_widget_grab_focus (self->entry);
+        }
+    }
+}
+
+static void
+get_config_cb (SyncevoServer *syncevo,
+               SyncevoConfig *config,
+               GError *error,
+               SyncConfigWidget *self)
+{
+    if (error) {
+        g_warning ("Server.GetConfig failed: %s", error->message);
+        g_error_free (error);
+
+        /* TODO: show in UI */
+        return;
+    }
+    sync_config_widget_real_init (self, config);
+
+}
+
+static gboolean
+sync_config_widget_expose_event (GtkWidget      *widget,
+                                 GdkEventExpose *event)
+{
+    GdkRectangle rect;
+    GtkExpanderStyle style;
+    gint indicator_x, indicator_y;
+    SyncConfigWidget *self = SYNC_CONFIG_WIDGET (widget);
+
+    rect.x = widget->allocation.x;
+    rect.y = widget->allocation.y;
+    rect.height = widget->allocation.height;
+    rect.width = widget->allocation.width;
+
+    gtk_paint_box (widget->style,
+                   widget->window,
+                   widget->state,
+                   GTK_SHADOW_OUT,
+                   &rect,
+                   widget,
+                   NULL,
+                   rect.x,
+                   rect.y,
+                   rect.width,
+                   rect.height);
+
+    if (self->expanded) {
+        gint shadow_x, shadow_y;
+
+        shadow_x = rect.x + widget->style->xthickness;
+        shadow_y = rect.y + 2 * widget->style->ythickness +
+                   MAX (INDICATOR_SIZE, self->label_box->allocation.height);
+
+        gtk_paint_box (widget->style,
+                       widget->window,
+                       widget->state,
+                       GTK_SHADOW_IN,
+                       &rect,
+                       widget,
+                       NULL,
+                       shadow_x,
+                       shadow_y,
+                       rect.width - (shadow_x - rect.x) - widget->style->xthickness,
+                       rect.height - (shadow_y - rect.y) - widget->style->ythickness);
+    }
+
+
+    if (self->expanded) {
+        style = GTK_EXPANDER_EXPANDED;
+    } else {
+        style = GTK_EXPANDER_COLLAPSED;
+    }
+
+    indicator_x = rect.x + widget->style->xthickness + INDICATOR_SIZE / 2;
+    indicator_y = rect.y + (widget->style->ythickness * 2 +
+                            MAX (self->label_box->allocation.height, INDICATOR_SIZE)) / 2;
+
+    gtk_paint_expander (widget->style,
+                        widget->window,
+                        widget->state,
+                        NULL,
+                        widget,
+                        NULL,
+                        indicator_x,
+                        indicator_y,
+                        style);
+
+    gtk_container_propagate_expose (GTK_CONTAINER (self),
+                                    self->label_box, event);
+    gtk_container_propagate_expose (GTK_CONTAINER (self),
+                                    self->expando_box, event);
+    return FALSE;
+}
+
+
+static void
+sync_config_widget_size_allocate (GtkWidget     *widget,
+                                  GtkAllocation *allocation)
+{
+    GtkRequisition req;
+    GtkAllocation alloc;
+    SyncConfigWidget *self = SYNC_CONFIG_WIDGET (widget);
+    gint label_h;
+
+    GTK_WIDGET_CLASS (sync_config_widget_parent_class)->size_allocate (widget,
+                                                                       allocation);
+
+    gtk_widget_size_request (self->label_box, &req);
+
+    alloc.x = allocation->x + widget->style->xthickness;
+    alloc.y = allocation->y + widget->style->ythickness;
+    alloc.width = allocation->width - 2 * widget->style->xthickness;
+    alloc.height = req.height;
+
+    /* make room for indicator */
+    alloc.x += INDICATOR_SIZE + widget->style->xthickness;
+    alloc.width -= INDICATOR_SIZE + widget->style->xthickness;
+
+    gtk_widget_size_allocate (self->label_box, &alloc);
+
+    label_h = MAX (INDICATOR_SIZE, alloc.height);
+
+
+    if (self->expanded) {
+        gtk_widget_size_request (self->expando_box, &req);
+
+        alloc.x = allocation->x + 2 * widget->style->xthickness;
+        alloc.y = allocation->y + widget->style->ythickness +
+                  label_h + CHILD_PADDING;
+        alloc.width = allocation->width - 4 * widget->style->xthickness;
+        alloc.height = req.height;
+
+        gtk_widget_size_allocate (self->expando_box, &alloc);
+    }
+}
+
+static void
+sync_config_widget_size_request (GtkWidget      *widget,
+                                 GtkRequisition *requisition)
+{
+    SyncConfigWidget *self = SYNC_CONFIG_WIDGET (widget);
+    GtkRequisition req;
+
+    requisition->width = widget->style->xthickness * 2;
+    requisition->height = widget->style->ythickness * 2;
+
+    gtk_widget_size_request (self->label_box, &req);
+
+    requisition->width += req.width;
+    requisition->height = MAX (req.height,
+                               INDICATOR_SIZE +
+                               widget->style->ythickness * 2);
+
+    if (self->expanded) {
+
+        gtk_widget_size_request (self->expando_box, &req);
+        requisition->width = MAX (requisition->width,
+                                  req.width + widget->style->xthickness * 4);
+        requisition->height += req.height + 2 * widget->style->ythickness;
+    }
+}
+
+static GObject *
+sync_config_widget_constructor (GType                  gtype,
+                                guint                  n_properties,
+                                GObjectConstructParam *properties)
+{
+    SyncConfigWidget *self;
+    GObjectClass *parent_class;  
+
+    parent_class = G_OBJECT_CLASS (sync_config_widget_parent_class);
+    self = SYNC_CONFIG_WIDGET (parent_class->constructor (gtype,
+                                                          n_properties,
+                                                          properties));
+
+    if (!self->server) {
+        g_warning ("No SyncevoServer set for SyncConfigWidget");
+    }
+
+    syncevo_server_get_config (self->server,
+                               self->config->name,
+                               self->has_template && !self->configured,
+                               (SyncevoServerGetConfigCb)get_config_cb,
+                               self);
+    return G_OBJECT (self);
+}
+
+static void
+sync_config_widget_show (GtkWidget *widget)
+{
+    char *ready;
+    SyncConfigWidget *self = SYNC_CONFIG_WIDGET (widget);
+
+    self->showing = TRUE;
+    if (self->config && self->config->config) {
+        syncevo_config_get_value (self->config->config,
+                                  NULL, "ConsumerReady", &ready);
+
+        if (ready && strcmp ("1", ready) == 0) {
+            GTK_WIDGET_CLASS (sync_config_widget_parent_class)->show (widget);
+        }
+    }
+}
+
+static void
+sync_config_widget_hide (GtkWidget *widget)
+{
+    SyncConfigWidget *self = SYNC_CONFIG_WIDGET (widget);
+
+    self->showing = FALSE;
+    GTK_WIDGET_CLASS (sync_config_widget_parent_class)->hide (widget);
+}
+
+static void
+sync_config_widget_map (GtkWidget *widget)
+{
+    SyncConfigWidget *self = SYNC_CONFIG_WIDGET (widget);
+
+    if (self->label_box && GTK_WIDGET_VISIBLE (self->expando_box)) {
+        gtk_widget_map (self->label_box);
+    }
+    if (self->expando_box && GTK_WIDGET_VISIBLE (self->expando_box)) {
+        gtk_widget_map (self->expando_box);
+    }
+    GTK_WIDGET_CLASS (sync_config_widget_parent_class)->map (widget);
+}
+
+static void
+sync_config_widget_unmap (GtkWidget *widget)
+{
+    SyncConfigWidget *self = SYNC_CONFIG_WIDGET (widget);
+
+    GTK_WIDGET_CLASS (sync_config_widget_parent_class)->unmap (widget);
+
+    if (self->label_box) {
+        gtk_widget_unmap (self->label_box);
+    }
+    if (self->expando_box) {
+        gtk_widget_unmap (self->expando_box);
+    }
+}
+
+static void
+sync_config_widget_realize (GtkWidget *widget)
+{
+    GTK_WIDGET_CLASS (sync_config_widget_parent_class)->realize (widget);
+}
+
+static void
+sync_config_widget_unrealize (GtkWidget *widget)
+{
+    GTK_WIDGET_CLASS (sync_config_widget_parent_class)->unrealize (widget);
+}
+
+static void
+sync_config_widget_add (GtkContainer *container,
+                        GtkWidget    *widget)
+{
+    g_warning ("Can't add widgets in to SyncConfigWidget!");
+}
+
+static void
+sync_config_widget_remove (GtkContainer *container,
+                           GtkWidget    *widget)
+{
+    SyncConfigWidget *self = SYNC_CONFIG_WIDGET (container);
+
+    
+    if (self->label_box == widget) {
+        gtk_widget_unparent (widget);
+        self->label_box = NULL;
+    }
+    if (self->expando_box == widget) {
+        gtk_widget_unparent (widget);
+        self->expando_box = NULL;
+    }
+}
+
+static void
+sync_config_widget_forall (GtkContainer *container,
+                           gboolean      include_internals,
+                           GtkCallback   callback,
+                           gpointer      callback_data)
+{
+    SyncConfigWidget *self = SYNC_CONFIG_WIDGET (container);
+
+    if (self->label_box) {
+        (* callback) (self->label_box, callback_data);
+    }
+    if (self->expando_box) {
+        (* callback) (self->expando_box, callback_data);
+    }
+}
+
+
+static void
+sync_config_widget_class_init (SyncConfigWidgetClass *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (klass);
+    GtkWidgetClass *w_class = GTK_WIDGET_CLASS (klass);
+    GtkContainerClass *c_class = GTK_CONTAINER_CLASS (klass);
+    GParamSpec *pspec;
+
+    object_class->set_property = sync_config_widget_set_property;
+    object_class->get_property = sync_config_widget_get_property;
+    object_class->dispose = sync_config_widget_dispose;
+    object_class->constructor = sync_config_widget_constructor;
+
+    w_class->show = sync_config_widget_show;
+    w_class->hide = sync_config_widget_hide;
+    w_class->expose_event = sync_config_widget_expose_event;
+    w_class->size_request = sync_config_widget_size_request;
+    w_class->size_allocate = sync_config_widget_size_allocate;
+    w_class->map = sync_config_widget_map;
+    w_class->unmap = sync_config_widget_unmap;
+    w_class->realize = sync_config_widget_realize;
+    w_class->unrealize = sync_config_widget_unrealize;
+
+    c_class->add = sync_config_widget_add;
+    c_class->remove = sync_config_widget_remove;
+    c_class->forall = sync_config_widget_forall;
+
+    pspec = g_param_spec_pointer ("server",
+                                  "SyncevoServer",
+                                  "The SyncevoServer struct this widget represents",
+                                  G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
+    g_object_class_install_property (object_class, PROP_SERVER, pspec);
+
+    pspec = g_param_spec_string ("name",
+                                 "Configuration name",
+                                 "The name of the Syncevolution service configuration",
+                                 NULL,
+                                 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
+    g_object_class_install_property (object_class, PROP_NAME, pspec);
+
+    pspec = g_param_spec_boolean ("current",
+                                  "Current",
+                                  "Whether the service is currently used",
+                                  FALSE,
+                                  G_PARAM_READWRITE);
+    g_object_class_install_property (object_class, PROP_CURRENT, pspec);
+
+    pspec = g_param_spec_boolean ("has-template",
+                                  "has template",
+                                  "Whether the service has a matching template",
+                                  FALSE,
+                                  G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
+    g_object_class_install_property (object_class, PROP_HAS_TEMPLATE, pspec);
+
+    pspec = g_param_spec_boolean ("configured",
+                                  "Configured",
+                                  "Whether the service has a configuration already",
+                                  FALSE,
+                                  G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
+    g_object_class_install_property (object_class, PROP_CONFIGURED, pspec);
+
+    pspec = g_param_spec_boolean ("unset",
+                                  "Unset",
+                                  "Whether there is a currently used service at all",
+                                  TRUE,
+                                  G_PARAM_READWRITE);
+    g_object_class_install_property (object_class, PROP_UNSET, pspec);
+
+    pspec = g_param_spec_boolean ("expanded",
+                                  "Expanded",
+                                  "Whether the expander is open or closed",
+                                  FALSE,
+                                  G_PARAM_READWRITE);
+    g_object_class_install_property (object_class, PROP_EXPANDED, pspec);
+
+    pspec = g_param_spec_int ("expander-size",
+                              "Expander Size",
+                              "Size of the expander indicator",
+                              0, G_MAXINT, INDICATOR_SIZE,
+                              G_PARAM_READABLE);
+
+  gtk_widget_class_install_style_property (w_class, pspec);
+
+
+    signals[SIGNAL_CHANGED] = 
+            g_signal_new ("changed",
+                          G_TYPE_FROM_CLASS (klass),
+                          G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
+                          G_STRUCT_OFFSET (SyncConfigWidgetClass, changed),
+                          NULL, NULL,
+                          g_cclosure_marshal_VOID__VOID,
+                          G_TYPE_NONE, 
+                          0);
+
+}
+
+static void
+sync_config_widget_init (SyncConfigWidget *self)
+{
+    GtkWidget *tmp_box, *vbox, *table, *label;
+
+    GTK_WIDGET_SET_FLAGS (GTK_WIDGET (self), GTK_NO_WINDOW);
+
+    self->label_box = gtk_hbox_new (FALSE, 0);
+    gtk_widget_set_size_request (self->label_box, -1, SYNC_UI_LIST_ICON_SIZE + 6);
+    gtk_widget_show (self->label_box);
+    gtk_widget_set_parent (self->label_box, GTK_WIDGET (self));
+
+    self->image = gtk_image_new ();
+    gtk_widget_set_size_request (self->image, 
+                                 SYNC_UI_LIST_ICON_SIZE,
+                                 SYNC_UI_LIST_ICON_SIZE);
+    gtk_widget_show (self->image);
+    gtk_box_pack_start (GTK_BOX (self->label_box), self->image, FALSE, FALSE, 8);
+
+    tmp_box = gtk_hbox_new (FALSE, 0);
+    gtk_widget_show (tmp_box);
+    gtk_box_pack_start (GTK_BOX (self->label_box), tmp_box, FALSE, FALSE, 8);
+
+    self->label = gtk_label_new ("");
+    gtk_misc_set_alignment (GTK_MISC (self->label), 0.0, 0.5);
+    gtk_widget_show (self->label);
+    gtk_box_pack_start (GTK_BOX (tmp_box), self->label, FALSE, FALSE, 0);
+
+    self->entry = gtk_entry_new ();
+    gtk_widget_set_no_show_all (self->entry, TRUE);
+    gtk_box_pack_start (GTK_BOX (tmp_box), self->entry, FALSE, FALSE, 4);
+
+    vbox = gtk_vbox_new (FALSE, 0);
+    gtk_widget_show (vbox);
+    gtk_box_pack_start (GTK_BOX (tmp_box), vbox, FALSE, FALSE, 0);
+
+    /* TRANSLATORS: linkbutton label */
+    self->link = gtk_link_button_new_with_label ("", _("Launch website"));
+    gtk_widget_set_no_show_all (self->link, TRUE);
+    gtk_box_pack_start (GTK_BOX (vbox), self->link, TRUE, FALSE, 0);
+
+    vbox = gtk_vbox_new (FALSE, 0);
+    gtk_widget_show (vbox);
+    gtk_box_pack_end (GTK_BOX (self->label_box), vbox, FALSE, FALSE, 32);
+
+    /* TRANSLATORS: button label  */
+    self->button = gtk_button_new_with_label (_("Setup now"));
+    gtk_widget_set_size_request (self->button, SYNC_UI_LIST_BTN_WIDTH, -1);
+    g_signal_connect (self->button, "clicked",
+                      G_CALLBACK (setup_service_clicked), self);
+
+    gtk_widget_show (self->button);
+    gtk_box_pack_start (GTK_BOX (vbox), self->button, TRUE, FALSE, 0);
+
+    /* label_box built, now build expando_box */
+
+    self->expando_box = gtk_hbox_new (FALSE, 0);
+    gtk_widget_set_no_show_all (self->expando_box, TRUE);
+    gtk_widget_set_parent (self->expando_box, GTK_WIDGET (self));
+
+    vbox = gtk_vbox_new (FALSE, 8);
+    gtk_widget_show (vbox);
+    gtk_box_pack_start (GTK_BOX (self->expando_box), vbox, TRUE, TRUE, 16);
+
+    tmp_box = gtk_vbox_new (FALSE, 0);
+    gtk_widget_show (tmp_box);
+    gtk_box_pack_start (GTK_BOX (vbox), tmp_box, FALSE, FALSE, 8);
+
+    self->description_label = gtk_label_new ("");
+    gtk_misc_set_alignment (GTK_MISC (self->description_label), 0.0, 0.5);
+    gtk_widget_set_size_request (self->description_label, 700, -1);
+    gtk_box_pack_start (GTK_BOX (tmp_box), self->description_label, FALSE, FALSE, 0);
+
+    tmp_box = gtk_hbox_new (FALSE, 0);
+    gtk_widget_show (tmp_box);
+    gtk_box_pack_start (GTK_BOX (vbox), tmp_box, FALSE, FALSE, 0);
+
+    table = gtk_table_new (3, 2, FALSE);
+    gtk_table_set_row_spacings (GTK_TABLE (table), 2);
+    gtk_table_set_col_spacings (GTK_TABLE (table), 5);
+    gtk_widget_show (table);
+    gtk_box_pack_start (GTK_BOX (tmp_box), table, FALSE, FALSE, 0);
+
+    /* TRANSLATORS: labels of entries  */
+    label = gtk_label_new (_("Username"));
+    gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
+    gtk_widget_show (label);
+    gtk_table_attach_defaults (GTK_TABLE (table), label,
+                               0, 1,
+                               0, 1);
+
+    self->username_entry = gtk_entry_new ();
+    gtk_widget_show (self->username_entry);
+    gtk_entry_set_width_chars (GTK_ENTRY (self->username_entry), 40);
+    gtk_entry_set_max_length (GTK_ENTRY (self->username_entry), 99);
+    gtk_table_attach_defaults (GTK_TABLE (table), self->username_entry,
+                               1, 2,
+                               0, 1);
+
+    label = gtk_label_new (_("Password"));
+    gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
+    gtk_widget_show (label);
+    gtk_table_attach_defaults (GTK_TABLE (table), label,
+                               0, 1,
+                               1, 2);
+
+    self->password_entry = gtk_entry_new ();
+    gtk_widget_show (self->password_entry);
+    gtk_entry_set_width_chars (GTK_ENTRY (self->password_entry), 40);
+    gtk_entry_set_max_length (GTK_ENTRY (self->password_entry), 99);
+    gtk_table_attach_defaults (GTK_TABLE (table), self->password_entry,
+                               1, 2,
+                               1, 2);
+
+    self->expander = gtk_expander_new ("");
+    gtk_widget_show (self->expander);
+    gtk_box_pack_start (GTK_BOX (vbox), self->expander, FALSE, FALSE, 0);
+    g_signal_connect (self->expander, "notify::expanded",
+                      G_CALLBACK (server_settings_expand_cb), self);
+    server_settings_expand_cb (GTK_EXPANDER (self->expander), self);
+
+    tmp_box = gtk_hbox_new (FALSE, 0);
+    gtk_widget_show (tmp_box);
+    gtk_container_add (GTK_CONTAINER (self->expander), tmp_box);
+
+    self->server_settings_table = gtk_table_new (1, 1, FALSE);
+    gtk_table_set_row_spacings (GTK_TABLE (self->server_settings_table), 2);
+    gtk_table_set_col_spacings (GTK_TABLE (self->server_settings_table), 5);
+    gtk_widget_show (self->server_settings_table);
+    gtk_box_pack_start (GTK_BOX (tmp_box), self->server_settings_table, FALSE, FALSE, 0);
+
+
+    tmp_box = gtk_hbox_new (FALSE, 0);
+    gtk_widget_show (tmp_box);
+    gtk_box_pack_start (GTK_BOX (vbox), tmp_box, FALSE, FALSE, 8);
+
+    /* TRANSLATORS: button labels  */
+    self->use_button = gtk_button_new ();
+    gtk_widget_show (self->use_button);
+    gtk_box_pack_end (GTK_BOX (tmp_box), self->use_button, FALSE, FALSE, 8);
+    g_signal_connect (self->use_button, "clicked",
+                      G_CALLBACK (use_clicked_cb), self);
+
+    self->stop_button = gtk_button_new_with_label (_("Stop using service"));
+    gtk_box_pack_end (GTK_BOX (tmp_box), self->stop_button, FALSE, FALSE, 8);
+    g_signal_connect (self->stop_button, "clicked",
+                      G_CALLBACK (stop_clicked_cb), self);
+
+    self->reset_delete_button = gtk_button_new ();
+    gtk_widget_show (self->reset_delete_button);
+    gtk_box_pack_end (GTK_BOX (tmp_box), self->reset_delete_button, FALSE, FALSE, 8);
+    g_signal_connect (self->reset_delete_button, "clicked",
+                      G_CALLBACK (reset_delete_clicked_cb), self);
+}
+
+
+GtkWidget*
+sync_config_widget_new (SyncevoServer *server,
+                        const char *name,
+                        gboolean current,
+                        gboolean unset,
+                        gboolean configured,
+                        gboolean has_template)
+{
+  return g_object_new (SYNC_TYPE_CONFIG_WIDGET,
+                       "server", server,
+                       "name", name,
+                       "current", current,
+                       "unset", unset,
+                       "configured", configured,
+                       "has-template", has_template,
+                       NULL);
+}
+
+void
+sync_config_widget_set_expanded (SyncConfigWidget *self, gboolean expanded)
+{
+    g_return_if_fail (SYNC_IS_CONFIG_WIDGET (self));
+
+    if (self->expanded != expanded) {
+
+        self->expanded = expanded;
+        if (self->expanded) {
+            gtk_widget_hide (self->button);
+            gtk_widget_show (self->expando_box);
+            if (GTK_WIDGET_VISIBLE (self->entry)) {
+                gtk_widget_grab_focus (self->entry);
+            } else {
+                gtk_widget_grab_focus (self->username_entry);
+            }
+        } else {
+            gtk_widget_show (self->button);
+            gtk_widget_hide (self->expando_box);
+        }
+        g_object_notify (G_OBJECT (self), "expanded");
+
+    }
+}
+
+gboolean
+sync_config_widget_get_expanded (SyncConfigWidget *self)
+{
+    return self->expanded;
+}
+
+void
+sync_config_widget_set_has_template (SyncConfigWidget *self, gboolean has_template)
+{
+    if (self->has_template != has_template) {
+        self->has_template = has_template;
+        update_buttons (self);
+        sync_config_widget_update_label (self);
+    }
+}
+
+gboolean
+sync_config_widget_get_has_template (SyncConfigWidget *self)
+{
+    return self->has_template;
+}
+
+void
+sync_config_widget_set_configured (SyncConfigWidget *self, gboolean configured)
+{
+    if (self->configured != configured) {
+        self->configured = configured;
+        update_buttons (self);
+    }
+}
+
+gboolean
+sync_config_widget_get_configured (SyncConfigWidget *self)
+{
+    return self->configured;
+}
+
+
+gboolean
+sync_config_widget_get_current (SyncConfigWidget *widget)
+{
+    return widget->current;
+}
+
+const char*
+sync_config_widget_get_name (SyncConfigWidget *widget)
+{
+    if (!widget->config)
+        return NULL;
+
+    return widget->config->name;
+}
diff --git a/src/gtk-ui/sync-config-widget.h b/src/gtk-ui/sync-config-widget.h
new file mode 100644 (file)
index 0000000..d567289
--- /dev/null
@@ -0,0 +1,99 @@
+#ifndef _SYNC_CONFIG_WIDGET
+#define _SYNC_CONFIG_WIDGET
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include "syncevo-server.h"
+#include "sync-ui-config.h"
+
+G_BEGIN_DECLS
+
+#define SYNC_TYPE_CONFIG_WIDGET sync_config_widget_get_type()
+
+#define SYNC_CONFIG_WIDGET(obj) \
+    (G_TYPE_CHECK_INSTANCE_CAST ((obj), SYNC_TYPE_CONFIG_WIDGET, SyncConfigWidget))
+
+#define SYNC_CONFIG_WIDGET_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_CAST ((klass), SYNC_TYPE_CONFIG_WIDGET, SyncConfigWidgetClass))
+
+#define SYNC_IS_CONFIG_WIDGET(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SYNC_TYPE_CONFIG_WIDGET))
+
+#define SYNC_IS_CONFIG_WIDGET_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE ((klass), SYNC_TYPE_CONFIG_WIDGET))
+
+#define SYNC_CONFIG_WIDGET_GET_CLASS(obj) \
+    (G_TYPE_INSTANCE_GET_CLASS ((obj), SYNC_TYPE_CONFIG_WIDGET, SyncConfigWidgetClass))
+
+typedef struct {
+    GtkContainer parent;
+    GtkWidget *expando_box;
+    GtkWidget *label_box;
+
+    gboolean current; /* is this currently used config */
+    gboolean unset; /* is there a current config at all */
+    gboolean configured; /* actual service configuration exists on server */
+    gboolean has_template; /* this service configuration has a matching template */
+    gboolean showing;
+    gboolean expanded;
+
+    SyncevoServer *server;
+    server_config *config;
+    
+    char *running_session;
+
+    /* label */
+    GtkWidget *image;
+    GtkWidget *label;
+    GtkWidget *entry;
+    GtkWidget *link;
+    GtkWidget *button;
+
+    /* content */
+    GtkWidget *description_label;
+    GtkWidget *name_label;
+    GtkWidget *name_entry;
+    GtkWidget *username_entry;
+    GtkWidget *password_entry;
+    GtkWidget *baseurl_entry;
+    GtkWidget *expander;
+    GtkWidget *server_settings_table;
+    GtkWidget *reset_delete_button;
+    GtkWidget *stop_button;
+    GtkWidget *use_button;
+    GHashTable *uri_entries;
+} SyncConfigWidget;
+
+typedef struct {
+    GtkContainerClass parent_class;
+
+    void (*changed) (SyncConfigWidget *widget);
+} SyncConfigWidgetClass;
+
+GType sync_config_widget_get_type (void);
+
+GtkWidget *sync_config_widget_new (SyncevoServer *server,
+                                   const char *name,
+                                   gboolean current,
+                                   gboolean unset,
+                                   gboolean configured,
+                                   gboolean has_template);
+
+void sync_config_widget_set_expanded (SyncConfigWidget *widget, gboolean expanded);
+gboolean sync_config_widget_get_expanded (SyncConfigWidget *widget);
+
+gboolean sync_config_widget_get_current (SyncConfigWidget *widget);
+void sync_config_widget_set_current (SyncConfigWidget *self, gboolean current);
+
+void sync_config_widget_set_has_template (SyncConfigWidget *self, gboolean has_template);
+gboolean sync_config_widget_get_has_template (SyncConfigWidget *self);
+
+void sync_config_widget_set_configured (SyncConfigWidget *self, gboolean configured);
+gboolean sync_config_widget_get_configured (SyncConfigWidget *self);
+
+const char *sync_config_widget_get_name (SyncConfigWidget *widget);
+G_END_DECLS
+
+
+#endif
index 2629c28..835ed9f 100644 (file)
  * 02110-1301  USA
  */
 
+#include <glib/gi18n.h>
+
 #include <string.h>
 #include "sync-ui-config.h"
 
 void
-source_config_free (source_config *source)
-{
-    if (!source)
-        return;
-
-    g_free (source->name);
-    g_free (source->uri);
-    g_slice_free (source_config, source);
-}
-
-void
 server_config_free (server_config *server)
 {
     if (!server)
         return;
 
     g_free (server->name);
-    g_free (server->base_url);
-    g_free (server->username);
-    g_free (server->password);
-    g_list_foreach (server->source_configs, (GFunc)source_config_free, NULL);
-    g_list_free (server->source_configs);
+    syncevo_config_free (server->config);
+
     g_slice_free (server_config, server);
 }
 
@@ -62,6 +50,7 @@ server_config_update_from_entry (server_config *server, GtkEntry *entry)
 
         server->changed = TRUE;
 
+/*
         if (*str == server->password) {
             server->auth_changed = TRUE;
             server->password_changed = TRUE;
@@ -69,12 +58,13 @@ server_config_update_from_entry (server_config *server, GtkEntry *entry)
                    *str == server->base_url) {
             server->auth_changed = TRUE;
         }
-
+*/
         g_free (*str);
         *str = g_strdup (new_str);
     }
 }
 
+/*
 void
 server_config_update_from_option (server_config *server, SyncevoOption *option)
 {
@@ -88,7 +78,13 @@ server_config_update_from_option (server_config *server, SyncevoOption *option)
             server->base_url = g_strdup (value);
         } else if (strcmp (key, "username") == 0) {
             g_free (server->username);
-            server->username = g_strdup (value);
+            //skip the informative username
+            if (value &&
+                strcmp (value, "your SyncML server account name") == 0) {
+                server->username = g_strdup ("");
+            } else {
+                server->username = g_strdup (value);
+            }
         } else if (strcmp (key, "webURL") == 0) {
             if (server->web_url)
             g_free (server->web_url);
@@ -110,7 +106,7 @@ server_config_update_from_option (server_config *server, SyncevoOption *option)
         } else if (strcmp (key, "sync") == 0) {
             if (strcmp (value, "disabled") == 0 ||
                  strcmp (value, "none") == 0) {
-                /* consider this source not available at all */
+                // consider this source not available at all
                 source->enabled = FALSE;
             } else {
                 source->enabled = TRUE;
@@ -120,7 +116,9 @@ server_config_update_from_option (server_config *server, SyncevoOption *option)
         }
     }
 }
+*/
 
+/*
 GPtrArray*
 server_config_get_option_array (server_config *server)
 {
@@ -140,8 +138,8 @@ server_config_get_option_array (server_config *server)
     option = syncevo_option_new (NULL, g_strdup ("iconURI"), g_strdup (server->icon_uri));
     g_ptr_array_add (options, option);
 
-    /* if gnome-keyring password was set, set password option to "-"
-     * (meaning 'use AskPassword()'). Otherwise don't touch the password */
+    // if gnome-keyring password was set, set password option to "-"
+    //(meaning 'use AskPassword()'). Otherwise don't touch the password
     if (server->password_changed) {
         option = syncevo_option_new (NULL, g_strdup ("password"), g_strdup ("-"));
         g_ptr_array_add (options, option);
@@ -150,10 +148,6 @@ server_config_get_option_array (server_config *server)
     for (l = server->source_configs; l; l = l->next) {
         source_config *source = (source_config*)l->data;
 
-        /* sources may have been added as place holders */
-        if (!source->uri)
-            continue;
-
         option = syncevo_option_new (source->name, g_strdup ("uri"), g_strdup (source->uri));
         g_ptr_array_add (options, option);
 
@@ -164,7 +158,9 @@ server_config_get_option_array (server_config *server)
 
     return options;
 }
+*/
 
+/*
 GPtrArray*
 server_config_get_source_array (server_config *server, SyncMode mode)
 {
@@ -184,54 +180,146 @@ server_config_get_source_array (server_config *server, SyncMode mode)
 
     return sources;
 }
+*/
+
+static void
+add_source_config (char *name,
+                   GHashTable *syncevo_source_config,
+                   GHashTable *source_configs)
+{
+    source_config *new_conf;
+
+    new_conf = g_slice_new (source_config);
+    new_conf->name = name;
+    new_conf->supported_locally = TRUE;
+    new_conf->config = syncevo_source_config;
+
+    g_hash_table_insert (source_configs, name, new_conf);
+}
 
 void
-server_config_disable_unsupported_sources (server_config *server)
+server_config_init (server_config *server, SyncevoConfig *config)
 {
-    GList *l;
+    server->config = config;
 
-    for (l = server->source_configs; l; l = l->next) {
-        source_config* config = (source_config*)l->data;
+    /* build source_configs */
+    server->source_configs = g_hash_table_new (g_str_hash, g_str_equal);
+    syncevo_config_foreach_source (config,
+                                   (ConfigFunc)add_source_config,
+                                   server->source_configs);
 
-        if (!config->supported_locally) {
-            config->enabled = FALSE;
-        }
+}
+
+static char*
+get_report_summary (int local_changes, int remote_changes, int local_rejects, int remote_rejects)
+{
+    char *rejects, *changes, *msg;
+
+    if (local_rejects + remote_rejects == 0) {
+        rejects = NULL;
+    } else if (local_rejects == 0) {
+        rejects = g_strdup_printf (ngettext ("There was one remote rejection.", 
+                                             "There were %d remote rejections.",
+                                             remote_rejects),
+                                   remote_rejects);
+    } else if (remote_rejects == 0) {
+        rejects = g_strdup_printf (ngettext ("There was one local rejection.", 
+                                             "There were %d local rejections.",
+                                             local_rejects),
+                                   local_rejects);
+    } else {
+        rejects = g_strdup_printf (_ ("There were %d local rejections and %d remote rejections."),
+                                   local_rejects, remote_rejects);
     }
+
+    if (local_changes + remote_changes == 0) {
+        changes = g_strdup_printf (_("Last time: No changes."));
+    } else if (local_changes == 0) {
+        changes = g_strdup_printf (ngettext ("Last time: Sent one change.",
+                                             "Last time: Sent %d changes.",
+                                             remote_changes),
+                                   remote_changes);
+    } else if (remote_changes == 0) {
+        // This is about changes made to the local data. Not all of these
+        // changes were requested by the remote server, so "applied"
+        // is a better word than "received" (bug #5185).
+        changes = g_strdup_printf (ngettext ("Last time: Applied one change.",
+                                             "Last time: Applied %d changes.",
+                                             local_changes),
+                                   local_changes);
+    } else {
+        changes = g_strdup_printf (_("Last time: Applied %d changes and sent %d changes."),
+                                   local_changes, remote_changes);
+    }
+
+    if (rejects)
+        msg = g_strdup_printf ("%s\n%s", changes, rejects);
+    else
+        msg = g_strdup (changes);
+    g_free (rejects);
+    g_free (changes);
+    return msg;
 }
 
+void
+source_config_update_label (source_config *source)
+{
+    char *msg;
+
+    if (!source->label) {
+        return;
+    }
 
+    msg = get_report_summary (source->local_changes,
+                              source->remote_changes,
+                              source->local_rejections,
+                              source->remote_rejections);
+    gtk_label_set_text (GTK_LABEL (source->label), msg);
+    g_free (msg);
+}
 
-static int
-source_config_compare (source_config *a, source_config *b)
+gboolean
+source_config_is_enabled (source_config *source)
 {
-    g_assert (a && a->name);
-    g_assert (b && b->name);
+    char *mode;
+
+    mode = g_hash_table_lookup (source->config, "sync");
 
-    return strcmp (a->name, b->name);
+    if (mode &&
+        (strcmp (mode, "none") == 0 ||
+         strcmp (mode, "disabled") == 0)) {
+        return FALSE;
+    }
+    return TRUE;
 }
 
-source_config*
-server_config_get_source_config (server_config *server, const char *name)
+server_data*
+server_data_new (const char *name, gpointer *data)
 {
-    GList *l;
-    source_config *source = NULL;
-    
-    g_assert (name);
-    
-    /* return existing source config if found */
-    for (l = server->source_configs; l; l = l->next) {
-        source = (source_config*)l->data;
-        if (strcmp (source->name, name) == 0) {
-            return source; 
-        }
+    server_data *serv_data;
+
+    serv_data = g_slice_new0 (server_data);
+    serv_data->data = data;
+    serv_data->config = g_slice_new0 (server_config);
+    serv_data->config->name = g_strdup (name);
+
+    return serv_data;
+}
+
+void
+server_data_free (server_data *data, gboolean free_config)
+{
+    if (!data)
+        return;
+
+    if (free_config && data->config) {
+        server_config_free (data->config);
     }
-    
-    /* create new source config */
-    source = g_slice_new0 (source_config);
-    source->name = g_strdup (name);
-    server->source_configs = g_list_insert_sorted (server->source_configs, 
-                                                   source,
-                                                   (GCompareFunc)source_config_compare);
-
-    return source;
+    if (data->options_override) {
+/*
+        g_ptr_array_foreach (data->options_override, (GFunc)syncevo_option_free, NULL);
+*/
+        g_ptr_array_free (data->options_override, TRUE);
+    }
+    g_slice_free (server_data, data);
 }
index 2be5777..ced1513 100644 (file)
 #define SYNC_UI_CONFIG_H
 
 #include <gtk/gtk.h>
-#include "syncevo-dbus.h"
-
-typedef enum {
-    SYNC_NONE,
-    SYNC_TWO_WAY,
-    SYNC_SLOW,
-    SYNC_ONE_WAY_FROM_CLIENT,
-    SYNC_REFRESH_FROM_CLIENT,
-    SYNC_ONE_WAY_FROM_SERVER,
-    SYNC_REFRESH_FROM_SERVER,
-    SYNC_MODE_MAX
-}SyncMode;
+#include "syncevo-session.h"
+#include "syncevo-server.h"
 
+/* need a separate struct for sources because we need to know local support ... */
 typedef struct source_config {
     char *name;
-    gboolean enabled;
     gboolean supported_locally;
-    char *uri;
+
+    long local_changes;
+    long remote_changes;
+    long local_rejections;
+    long remote_rejections;
+
+    GtkWidget *label; /* source report label, after ui has been constructed */
+    GtkWidget *box; /* source box, after ui has been constructed */
+
+    GHashTable *config; /* link to a "sub-hashtable" inside server_config->config */
 } source_config;
 
 typedef struct server_config {
     char *name;
-    char *base_url;
-    char *web_url;
-    char *icon_uri;
-
-    char *username;
     char *password;
-
-    GList *source_configs;
-    
-    /* any field in struct has changed */
+    /* any field in config has changed */
     gboolean changed;
 
     /* a authentication detail (base_url/username/password) has changed */
@@ -60,16 +51,35 @@ typedef struct server_config {
 
     gboolean password_changed;
 
-    gboolean from_template;
+    GHashTable *source_configs; /* source_config's*/
+
+    SyncevoConfig *config;
 } server_config;
 
+gboolean source_config_is_enabled (source_config *source);
+void source_config_update_label (source_config *source);
 void source_config_free (source_config *source);
+
+void server_config_init (server_config *server, SyncevoConfig *config);
 void server_config_free (server_config *server);
-void server_config_update_from_option (server_config *server, SyncevoOption *option);
+
 void server_config_update_from_entry (server_config *server, GtkEntry *entry);
 GPtrArray* server_config_get_option_array (server_config *server);
-GPtrArray* server_config_get_source_array (server_config *server, SyncMode mode);
 void server_config_disable_unsupported_sources (server_config *server);
-source_config* server_config_get_source_config (server_config *server, const char *name);
+
+void server_config_ensure_default_sources_exist (server_config *server);
+
+/* data structure for syncevo_service_get_template_config_async and
+ * syncevo_service_get_server_config_async. server is the server that
+ * the method was called for. options_override are options that should
+ * be overridden on the config we get.
+ */
+typedef struct server_data {
+    server_config *config;
+    GPtrArray *options_override;
+    gpointer *data;
+} server_data;
+server_data* server_data_new (const char *name, gpointer *data);
+void server_data_free (server_data *data, gboolean free_config);
 
 #endif
diff --git a/src/gtk-ui/sync-ui-marshal.list b/src/gtk-ui/sync-ui-marshal.list
deleted file mode 100755 (executable)
index e72aa4b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-VOID:STRING,BOXED
index 830c2ad..b6d7cbd 100644 (file)
  * 02110-1301  USA
  */
 
-/*
- * TODO
- * 
- * * redesign main window? (talk with nick/patrick). Issues:
-      - sync types (other than two-way) should maybe be available somewhere 
-        else than main window?
-      - showing usable statistic
-      - sync errors can flood the ui... need to dicuss with nick.
-        Possible solution: show only a few errors, but have a linkbutton to open a
-        separate error window
- * * get history data from syncevolution
- * * backup/restore ? 
- * * GTK styling missing:
- *    - current implementation of MuxFrame results in a slight flicker on window open
- * * notes on dbus API:
- *    - a more cleaner solution would be to have StartSync return a 
- *      dbus path that could be used to connect to signals related to that specific
- *      sync
- */
-
 
 #include <stdlib.h>
 #include <math.h>
 #include <string.h>
 #include <gdk/gdkkeysyms.h>
 #include <gtk/gtk.h>
-#include <gconf/gconf-client.h>
 #include <glib/gi18n.h>
 #include <gio/gio.h>
-#include <gnome-keyring.h>
+#include <dbus/dbus-glib.h>
 
-#include "syncevo-dbus.h"
-#include "sync-ui-marshal.h"
+#include "syncevo-server.h"
+#include "syncevo-session.h"
 
 /* for return value definitions */
 /* TODO: would be nice to have a non-synthesis-dependent API but for now it's like this... */
@@ -59,6 +38,7 @@
 #include "config.h"
 #include "sync-ui-config.h"
 #include "sync-ui.h"
+#include "sync-config-widget.h"
 
 #ifdef USE_MOBLIN_UX
 #include "mux-frame.h"
 
 static gboolean support_canceling = FALSE;
 
-#define SYNC_UI_GCONF_DIR "/apps/sync-ui"
-#define SYNC_UI_SERVER_KEY SYNC_UI_GCONF_DIR"/server"
-
 #define SYNC_UI_ICON_SIZE 48
-#define SYNC_UI_LIST_ICON_SIZE 32
-#define SYNC_UI_LIST_BTN_WIDTH 150
 
 #define STRING_VARIANT_HASHTABLE (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE))
 
-/* for connman state property */
-static DBusGProxy *proxy = NULL;
-
-typedef struct source_progress {
-    char* name;
-    
-    /* progress */
-    int prepare_current;
-    int prepare_total;
-    int send_current;
-    int send_total;
-    int receive_current;
-    int receive_total;
-    
-    /* statistics */
-    int added_local;
-    int modified_local;
-    int deleted_local;
-    int rejected_local;
-    int added_remote;
-    int modified_remote;
-    int deleted_remote;
-    int rejected_remote;
-    int bytes_uploaded;
-    int bytes_downloaded;
-} source_progress;
-
 typedef enum app_state {
-    SYNC_UI_STATE_CURRENT_STATE = 0, /* so you can call update_app_state with old values */
+    SYNC_UI_STATE_CURRENT_STATE,
     SYNC_UI_STATE_GETTING_SERVER,
     SYNC_UI_STATE_NO_SERVER,
     SYNC_UI_STATE_SERVER_OK,
@@ -112,27 +60,9 @@ typedef enum app_state {
     SYNC_UI_STATE_SYNCING,
 } app_state;
 
-/* absolute progress amounts 0-100 */
-const float sync_progress_clicked = 0.02;
-const float sync_progress_session_start = 0.04;
-const float sync_progress_sync_start = 0.06;    /* prepare/send/receive cycles start here */
-const float sync_progress_sync_end = 0.96;
-
-/* how are prepare/send/receive weighed -- sum should be 100 */
-const float sync_weight_prepare = 0.50;
-const float sync_weight_send = 0.25;
-const float sync_weight_receive = 0.25;
-
-/* non-abolute progress amounts for prepare/send/receive (for all sources) */
-#define SYNC_PROGRESS_PREPARE ((sync_progress_sync_end - sync_progress_sync_start) * sync_weight_prepare)
-#define SYNC_PROGRESS_SEND ((sync_progress_sync_end - sync_progress_sync_start) * sync_weight_send)
-#define SYNC_PROGRESS_RECEIVE ((sync_progress_sync_end - sync_progress_sync_start) * sync_weight_receive)
-
-
 typedef struct app_data {
     GtkWidget *sync_win;
-    GtkWidget *services_win;
-    GtkWidget *service_settings_win;
+    GtkWidget *services_win; /* will be NULL when USE_MOBLIN_UX is set*/
 
     GtkWidget *server_box;
     GtkWidget *server_failure_box;
@@ -156,23 +86,10 @@ typedef struct app_data {
     GtkWidget *sources_box;
 
     GtkWidget *new_service_btn;
-    GtkWidget *services_table;
-    GtkWidget *manual_services_table;
-    GtkWidget *manual_services_scrolled;
+    GtkWidget *services_box;
+    GtkWidget *scrolled_window;
     GtkWidget *back_btn;
-
-    GtkWidget *service_settings_frame;
-    GtkWidget *service_link;
-    GtkWidget *service_description_label;
-    GtkWidget *service_name_label;
-    GtkWidget *service_name_entry;
-    GtkWidget *username_entry;
-    GtkWidget *password_entry;
-    GtkWidget *server_settings_expander;
-    GtkWidget *server_settings_table;
-    GtkWidget *reset_server_btn;
-    GtkWidget *stop_using_service_btn;
-    GtkWidget *delete_service_btn;
+    GtkWidget *expanded_config;
 
     gboolean online;
 
@@ -180,23 +97,60 @@ typedef struct app_data {
     gboolean synced_this_session;
     int last_sync;
     guint last_sync_src_id;
-    GList *source_progresses;
-
-    GHashTable *source_report_labels;
 
-    SyncMode mode;
-    SyncevoService *service;
+    SyncevoSyncMode mode;
 
     server_config *current_service;
+    app_state current_state;
+    gboolean open_current; /* should the service list open the current 
+                              service when it populates next time*/
+
+    SyncevoServer *server;
+
+    SyncevoSession *running_session; /* session that is currently active */
 } app_data;
 
+typedef struct operation_data {
+    app_data *data;
+    enum op {
+        OP_SYNC,
+        OP_SAVE,
+    } operation;
+    gboolean started;
+} operation_data;
+
 static void set_sync_progress (app_data *data, float progress, char *status);
 static void set_app_state (app_data *data, app_state state);
-static void show_services_window (app_data *data);
-static void show_settings_window (app_data *data, server_config *config);
-static void ensure_default_sources_exist(server_config *server);
-static void add_server_option (SyncevoOption *option, server_config *server);
+static void show_main_view (app_data *data);
+static void show_services_list (app_data *data);
+static void update_services_list (app_data *data);
 static void setup_new_service_clicked (GtkButton *btn, app_data *data);
+static void get_presence_cb (SyncevoServer *server, char *status, char *transport,
+                             GError *error, app_data *data);
+static void get_reports_cb (SyncevoServer *server, SyncevoReports *reports, 
+                            GError *error, app_data *data);
+static void start_session_cb (SyncevoServer *server, char *path,
+                              GError *error, operation_data *op_data);
+static void get_config_for_main_win_cb (SyncevoServer *server, SyncevoConfig *config,
+                                        GError *error, app_data *data);
+static char* get_error_string_for_code (int error_code);
+
+void
+show_error_dialog (GtkWidget *widget, const char* message)
+{
+    GtkWindow *window = GTK_WINDOW (gtk_widget_get_toplevel (widget));
+
+    GtkWidget *w;
+    w = gtk_message_dialog_new (window,
+                                GTK_DIALOG_MODAL,
+                                GTK_MESSAGE_ERROR,
+                                GTK_BUTTONS_OK,
+                                "%s",
+                                message);
+    gtk_dialog_run (GTK_DIALOG (w));
+    gtk_widget_destroy (w);
+}
+
 
 static void
 remove_child (GtkWidget *widget, GtkContainer *container)
@@ -207,7 +161,7 @@ remove_child (GtkWidget *widget, GtkContainer *container)
 static void 
 change_service_clicked_cb (GtkButton *btn, app_data *data)
 {
-    show_services_window (data);
+    show_services_list (data);
 }
 
 static void 
@@ -215,31 +169,8 @@ edit_service_clicked_cb (GtkButton *btn, app_data *data)
 {
     g_assert (data);
 
-    data->current_service->changed = FALSE;
-    gtk_window_set_transient_for (GTK_WINDOW (data->service_settings_win), 
-                                  GTK_WINDOW (data->sync_win));
-    show_settings_window (data, data->current_service);
-}
-
-static void
-update_server_config (GtkWidget *widget, server_config *config)
-{
-    if (GTK_IS_ENTRY (widget))
-        server_config_update_from_entry (config, GTK_ENTRY (widget));
-}
-
-static void
-show_error_dialog (GtkWindow *parent, const char* message)
-{
-    GtkWidget *w;
-    w = gtk_message_dialog_new (parent,
-                                GTK_DIALOG_MODAL,
-                                GTK_MESSAGE_ERROR,
-                                GTK_BUTTONS_OK,
-                                "%s",
-                                message);
-    gtk_dialog_run (GTK_DIALOG (w));
-    gtk_widget_destroy (w);
+    data->open_current = TRUE;
+    show_services_list (data);
 }
 
 static void
@@ -252,11 +183,14 @@ clear_error_info (app_data *data)
     gtk_widget_hide (data->errors_box);
 }
 
-static char*
+char*
 get_pretty_source_name (const char *source_name)
 {
     if (strcmp (source_name, "addressbook") == 0) {
-        return g_strdup (_("Addressbook"));
+        /* TRANSLATORS: The name was changed from 'Addressbook' to
+           'Contacts' to match naming in rest of moblin. Please make sure the
+           name you use matches the name in the panel and Contacts application. */
+        return g_strdup (_("Contacts"));
     } else if (strcmp (source_name, "calendar") == 0) {
         return g_strdup (_("Calendar"));
     } else if (strcmp (source_name, "todo") == 0) {
@@ -307,406 +241,84 @@ add_error_info (app_data *data, const char *message, const char *external_reason
 }
 
 static void
-save_gconf_settings (app_data *data, char *service_name)
-{
-    GConfClient* client;
-    GError *err = NULL;
-
-    client = gconf_client_get_default ();
-    if (!gconf_client_set_string (client, SYNC_UI_SERVER_KEY, 
-                                  service_name ? service_name : "", 
-                                  &err)) {
-        show_error_dialog (GTK_WINDOW (data->sync_win),
-                           _("Failed to save current service in GConf configuration system"));
-        g_warning ("Failed to save current service in GConf configuration system: %s", err->message);
-        g_error_free (err);
-    }
-}
-
-static void
-set_server_config_cb (SyncevoService *service, GError *error, app_data *data)
-{
-    if (error) {
-        show_error_dialog (GTK_WINDOW (data->sync_win),
-                           _("Failed to save service configuration to SyncEvolution"));
-        g_warning ("Failed to save service configuration to SyncEvolution: %s",
-                   error->message);
-        g_error_free (error);
-        return;
-    }
-    save_gconf_settings (data, data->current_service->name);
-}
-
-
-/* temporary data structure for syncevo_service_get_template_config_async and
- * syncevo_service_get_server_config_async. server is the server that 
- * the method was called for. options_override are options that should 
- * be overridden on the config we get. */
-typedef struct server_data {
-    server_config *config;
-    GPtrArray *options_override;
-    app_data *data;
-} server_data;
-
-static server_data*
-server_data_new (const char *name, app_data *data)
-{
-    server_data *serv_data;
-
-    serv_data = g_slice_new0 (server_data);
-    serv_data->data = data;
-    serv_data->config = g_slice_new0 (server_config);
-    serv_data->config->name = g_strdup (name);
-
-    return serv_data;
-}
-
-static void
-server_data_free (server_data *data, gboolean free_config)
+reload_config (app_data *data, const char *server)
 {
-    if (!data)
-        return;
+    server_config_free (data->current_service);
 
-    if (free_config && data->config) {
-        server_config_free (data->config);
-    }
-    if (data->options_override) {
-        g_ptr_array_foreach (data->options_override, (GFunc)syncevo_option_free, NULL);
-        g_ptr_array_free (data->options_override, TRUE);
-    }
-    g_slice_free (server_data, data);
-}
+    if (!server || strlen (server) == 0) {
+        set_app_state (data, SYNC_UI_STATE_NO_SERVER);
+        data->current_service = NULL;
+    } else {
+        set_app_state (data, SYNC_UI_STATE_GETTING_SERVER);
+        data->synced_this_session = FALSE;
+        data->current_service = g_slice_new0 (server_config);
+        data->current_service->name = g_strdup (server);
 
-static void
-find_password_for_settings_cb (GnomeKeyringResult result, GList *list, server_data *data)
-{
-    switch (result) {
-    case GNOME_KEYRING_RESULT_NO_MATCH:
-        g_warning ("no password found in keyring");
-        break;
-    case GNOME_KEYRING_RESULT_OK:
-        if (list && list->data) {
-            GnomeKeyringNetworkPasswordData *key_data;
-            key_data = (GnomeKeyringNetworkPasswordData*)list->data;
-            data->config->password = g_strdup (key_data->password);
-        }
-        break;
-    default:
-        g_warning ("getting password from GNOME keyring failed: %s",
-                   gnome_keyring_result_to_message (result));
-        break;
+        syncevo_server_get_config (data->server,
+                                   data->current_service->name,
+                                   FALSE,
+                                   (SyncevoServerGetConfigCb)get_config_for_main_win_cb,
+                                   data);
+        
     }
-    show_settings_window (data->data, data->config);
-
-    /* dialog should free server config */
-    server_data_free (data, FALSE);
-    return;
 }
 
 
-/* called when service is reset or service settings are opened 
- * (for a new or existing service )*/
 static void
-get_server_config_for_template_cb (SyncevoService *service, GPtrArray *options, GError *error, server_data *data)
+abort_sync_cb (SyncevoSession *session,
+               GError *error,
+               app_data *data)
 {
-    gboolean getting_password = FALSE;
-
     if (error) {
-        show_error_dialog (GTK_WINDOW (data->data->sync_win),
-                           _("Failed to get service configuration from SyncEvolution"));
-        g_warning ("Failed to get service configuration from SyncEvolution: %s",
-                   error->message);
+        /* TODO show in UI: failed to abort sync (while syncing) */
+        add_error_info (data, _("Failed to abort sync"), error->message);
         g_error_free (error);
-        server_data_free (data, TRUE);
-    } else {
-        char *server_address;
-
-        g_ptr_array_foreach (options, (GFunc)add_server_option, data->config);
-        if (data->options_override)
-            g_ptr_array_foreach (data->options_override, (GFunc)add_server_option, data->config);
-
-        ensure_default_sources_exist (data->config);
-        server_config_disable_unsupported_sources (data->config);
-
-        data->config->changed = TRUE;
-
-        /* get password from keyring if we have an url */
-        if (data->config->base_url) {
-            server_address = strstr (data->config->base_url, "://");
-            if (server_address)
-                server_address = server_address + 3;
-
-            if (!server_address) {
-                g_warning ("Server configuration has suspect URL '%s'",
-                           data->config->base_url);
-            } else {
-                gnome_keyring_find_network_password (data->config->username,
-                                                     NULL,
-                                                     server_address,
-                                                     NULL,
-                                                     NULL,
-                                                     NULL,
-                                                     0,
-                                                     (GnomeKeyringOperationGetListCallback)find_password_for_settings_cb,
-                                                     data,
-                                                     NULL);
-                getting_password = TRUE;
-            }
-        }
-
-        if (!getting_password) {
-            show_settings_window (data->data, data->config);
-
-            /* dialog should free server config */
-            server_data_free (data, FALSE);
-        }
-
-        if (options) {
-            g_ptr_array_foreach (options, (GFunc)syncevo_option_free, NULL);
-            g_ptr_array_free (options, TRUE);
-        }
     }
+
+    /* status change handler takes care of updating UI */
 }
 
 static void
-remove_server_config_cb (SyncevoService *service, 
-                         GError *error, 
-                         server_data *data)
+sync_cb (SyncevoSession *session,
+         GError *error,
+         app_data *data)
 {
-    g_assert (data);
-
     if (error) {
-        show_error_dialog (GTK_WINDOW (data->data->sync_win),
-                           _("Failed to remove service configuration from SyncEvolution"));
-        g_warning ("Failed to remove service configuration from SyncEvolution: %s", 
-                   error->message);
+        /* TODO show in UI: sync failed (failed to even start) */
+        add_error_info (data, _("Failed to start sync"), error->message);
         g_error_free (error);
-    } else {
-        /* update list if visible */
-        if (GTK_WIDGET_VISIBLE (data->data->services_win))
-            show_services_window (data->data);
-
-        if (data->data->current_service && data->data->current_service->name &&
-            strcmp (data->data->current_service->name, data->config->name) == 0)
-            save_gconf_settings (data->data, NULL);
-    }
-
-    server_data_free (data, TRUE);
-}
-
-static void
-stop_using_service_clicked_cb (GtkButton *btn, app_data *data)
-{
-    server_config *server;
-
-    server = g_object_get_data (G_OBJECT (data->service_settings_win), "server");
-    g_assert (server);
-
-    gtk_widget_hide (GTK_WIDGET (data->service_settings_win));
-    gtk_widget_hide (GTK_WIDGET (data->services_win));
-
-    save_gconf_settings (data, NULL);
-}
-
-static void
-delete_service_clicked_cb (GtkButton *btn, app_data *data)
-{
-    server_config *server;
-    server_data* serv_data;
-
-    server = g_object_get_data (G_OBJECT (data->service_settings_win), "server");
-    g_assert (server);
-
-    gtk_widget_hide (GTK_WIDGET (data->service_settings_win));
-
-    serv_data = server_data_new (server->name, data);
-
-    syncevo_service_remove_server_config_async (data->service,
-                                                server->name, 
-                                                (SyncevoRemoveServerConfigCb)remove_server_config_cb,
-                                                serv_data);
-}
-
-static void
-reset_service_clicked_cb (GtkButton *btn, app_data *data)
-{
-    server_config *server;
-    server_data* serv_data;
-    SyncevoOption *option;
-
-    server = g_object_get_data (G_OBJECT (data->service_settings_win), "server");
-    g_assert (server);
-
-    serv_data = server_data_new (server->name, data);
-    serv_data->options_override = g_ptr_array_new ();
-
-    option = syncevo_option_new (NULL, g_strdup ("username"), g_strdup (server->username));
-    g_ptr_array_add (serv_data->options_override, option);
-
-    syncevo_service_get_template_config_async (data->service, 
-                                               server->name, 
-                                               (SyncevoGetTemplateConfigCb)get_server_config_for_template_cb,
-                                               serv_data);
-}
-
-static void
-add_to_acl_cb (GnomeKeyringResult result)
-{
-    if (result != GNOME_KEYRING_RESULT_OK)
-        g_warning ("Adding server to GNOME keyring access control list failed: %s",
-                   gnome_keyring_result_to_message (result));
-}
-
-static void
-set_password_cb (GnomeKeyringResult result, guint32 id, app_data *data)
-{
-    if (result != GNOME_KEYRING_RESULT_OK) {
-        g_warning ("setting password in GNOME keyring failed: %s",
-                   gnome_keyring_result_to_message (result));
-        return;
-    }
-
-    /* add the server to access control list */
-    /* TODO: name and path must match the ones syncevo-dbus-server really has,
-     * so this call should be in the dbus-wrapper library */
-    gnome_keyring_item_grant_access_rights (NULL, 
-                                            "SyncEvolution",
-                                            LIBEXECDIR "/syncevo-dbus-server",
-                                            id,
-                                            GNOME_KEYRING_ACCESS_READ,
-                                            (GnomeKeyringOperationDoneCallback)add_to_acl_cb,
-                                            NULL, NULL);
-}
-
-static void
-service_save_clicked_cb (GtkButton *btn, app_data *data)
-{
-    GPtrArray *options;
-    server_config *server;
-
-    server = g_object_get_data (G_OBJECT (data->service_settings_win), "server");
-    g_assert (server);
-
-    server_config_update_from_entry (server, GTK_ENTRY (data->service_name_entry));
-    server_config_update_from_entry (server, GTK_ENTRY (data->username_entry));
-    server_config_update_from_entry (server, GTK_ENTRY (data->password_entry));
-
-    gtk_container_foreach (GTK_CONTAINER (data->server_settings_table), 
-                           (GtkCallback)update_server_config, server);
-
-    if (!server->name || strlen (server->name) == 0 ||
-        !server->base_url || strlen (server->base_url) == 0) {
-        show_error_dialog (GTK_WINDOW (data->service_settings_win), 
-                           _("Service must have a name and server URL"));
+        g_object_unref (session);
         return;
     }
-    /* make a wild guess if no scheme in url */
-    if (strstr (server->base_url, "://") == NULL) {
-        char *tmp = g_strdup_printf ("http://%s", server->base_url);
-        g_free (server->base_url);
-        server->base_url = tmp;
-    }
-
-    gtk_widget_hide (GTK_WIDGET (data->service_settings_win));
-    gtk_widget_hide (GTK_WIDGET (data->services_win));
-
-    if (data->current_service && data->current_service != server) {
-        server_config_free (data->current_service);
-    }
-    data->current_service = server;
-
-    if (server->auth_changed) {
-        char *server_address;
-        char *password;
-        char *username;
-
-        server_address = strstr (server->base_url, "://");
-        if (server_address)
-            server_address = server_address + 3;
-
-        password = server->password;
-        if (!password)
-            password = "";
-
-        username = server->username;
-        if (!username)
-            username = "";
-
-        gnome_keyring_set_network_password (NULL, /* default keyring */
-                                            username,
-                                            NULL,
-                                            server_address,
-                                            NULL,
-                                            NULL,
-                                            NULL,
-                                            0,
-                                            password,
-                                            (GnomeKeyringOperationGetIntCallback)set_password_cb,
-                                            data, NULL);
-    }
-
-    if (!server->changed) {
-        /* no need to save first, set the gconf key right away */
-        save_gconf_settings (data, data->current_service->name);
-    } else {
-        /* save the server, let callback change current server gconf key */
-        options = server_config_get_option_array (server);
-        syncevo_service_set_server_config_async (data->service, 
-                                                 server->name,
-                                                 options,
-                                                 (SyncevoSetServerConfigCb)set_server_config_cb, 
-                                                 data);
-        g_ptr_array_foreach (options, (GFunc)syncevo_option_free, NULL);
-        g_ptr_array_free (options, TRUE);
-    }
-
-    server->auth_changed = FALSE;
-    server->password_changed = FALSE;
-    server->changed = FALSE;
-}
-
-static void
-abort_sync_cb (SyncevoService *service, GError *error, app_data *data)
-{
-    if (error) {
-        if (error->code == DBUS_GERROR_REMOTE_EXCEPTION &&
-            dbus_g_error_has_name (error, SYNCEVO_DBUS_ERROR_INVALID_CALL)) {
 
-            /* sync is no longer in progress for some reason */
-            add_error_info (data, _("Failed to cancel: sync was no longer in progress"), error->message);
-            set_sync_progress (data, 1.0 , "");
-            set_app_state (data, SYNC_UI_STATE_SERVER_OK);
-        } else {
-            add_error_info (data, _("Failed to cancel sync"), error->message);
-        }
-        g_error_free (error);
-    } else {
-        set_sync_progress (data, -1.0, _("Canceling sync"));
-    }
+    set_sync_progress (data, 0.0, _("Starting sync"));
+    /* stop updates of "last synced" */
+    if (data->last_sync_src_id > 0)
+        g_source_remove (data->last_sync_src_id);
+    set_app_state (data, SYNC_UI_STATE_SYNCING);
 }
 
 static void 
 sync_clicked_cb (GtkButton *btn, app_data *data)
 {
-    GPtrArray *sources;
-    GList *list;
-    GError *error = NULL;
+    operation_data *op_data;
 
     if (data->syncing) {
-        syncevo_service_abort_sync_async (data->service, data->current_service->name, 
-                                          (SyncevoAbortSyncCb)abort_sync_cb, data);
+        syncevo_session_abort (data->running_session,
+                               (SyncevoSessionGenericCb)abort_sync_cb,
+                               data);
         set_sync_progress (data, -1.0, _("Trying to cancel sync"));
     } else {
         char *message = NULL;
 
         /* confirmation dialog for destructive sync options */
         switch (data->mode) {
-        case SYNC_REFRESH_FROM_SERVER:
+        case SYNCEVO_SYNC_REFRESH_FROM_SERVER:
             message = g_strdup_printf (_("Do you want to delete all local data and replace it with "
                                          "data from %s? This is not usually advised."),
                                        data->current_service->name);
             break;
-        case SYNC_REFRESH_FROM_CLIENT:
+        case SYNCEVO_SYNC_REFRESH_FROM_CLIENT:
             message = g_strdup_printf (_("Do you want to delete all data in %s and replace it with "
                                          "your local data? This is not usually advised."),
                                        data->current_service->name);
@@ -724,8 +336,10 @@ sync_clicked_cb (GtkButton *btn, app_data *data)
                                         "%s",
                                         message);
             gtk_dialog_add_buttons (GTK_DIALOG (w), 
-                                    _("No, cancel sync"), GTK_RESPONSE_NO,
-                                    _("Yes, delete and replace"), GTK_RESPONSE_YES,
+                                    _("No, cancel sync"),
+                                    GTK_RESPONSE_NO,
+                                    _("Yes, delete and replace"),
+                                    GTK_RESPONSE_YES,
                                     NULL);
             ret = gtk_dialog_run (GTK_DIALOG (w));
             gtk_widget_destroy (w);
@@ -735,54 +349,19 @@ sync_clicked_cb (GtkButton *btn, app_data *data)
             }
         }
 
-        /* empty source progress list */
-        list = data->source_progresses;
-        for (list = data->source_progresses; list; list = list->next) {
-            g_free (((source_progress*)list->data)->name);
-            g_slice_free (source_progress, list->data);
-        }
-        g_list_free (data->source_progresses);
-        data->source_progresses = NULL;
-
-        sources = server_config_get_source_array (data->current_service, data->mode);
-        if (sources->len == 0) {
-            g_ptr_array_free (sources, TRUE);
-            add_error_info (data, _("No sources are enabled, not syncing"), NULL);
-            return;
-        }
-        syncevo_service_start_sync (data->service, 
-                                    data->current_service->name,
-                                    sources,
-                                    &error);
-        if (error) {
-            if (error->code == DBUS_GERROR_REMOTE_EXCEPTION &&
-                dbus_g_error_has_name (error, SYNCEVO_DBUS_ERROR_INVALID_CALL)) {
-
-                /* stop updates of "last synced" */
-                if (data->last_sync_src_id > 0)
-                    g_source_remove (data->last_sync_src_id);
-                set_app_state (data, SYNC_UI_STATE_SYNCING);
-                set_sync_progress (data, sync_progress_clicked, _(""));
-                
-                add_error_info (data, _("A sync is already in progress"), error->message);
-            } else {
-                add_error_info (data, _("Failed to start sync"), error->message);
-                g_error_free (error);
-                return;
-            }
-        } else {
-            set_sync_progress (data, sync_progress_clicked, _("Starting sync"));
-            /* stop updates of "last synced" */
-            if (data->last_sync_src_id > 0)
-                g_source_remove (data->last_sync_src_id);
-            set_app_state (data, SYNC_UI_STATE_SYNCING);
-        }
-
+        op_data = g_slice_new (operation_data);
+        op_data->data = data;
+        op_data->operation = OP_SYNC;
+        op_data->started = FALSE;
+        syncevo_server_start_session (data->server,
+                                      data->current_service->name,
+                                      (SyncevoServerStartSessionCb)start_session_cb,
+                                      op_data);
     }
 }
 
 static gboolean
-refresh_last_synced_label (app_data *data)
+    refresh_last_synced_label (app_data *data)
 {
     GTimeVal val;
     glong diff;
@@ -842,15 +421,14 @@ set_sync_progress (app_data *data, float progress, char *status)
 static void
 set_app_state (app_data *data, app_state state)
 {
-    static int current_state = SYNC_UI_STATE_GETTING_SERVER;
 
-    if (current_state == state)
+    if (data->current_state == state)
         return;
 
     if (state != SYNC_UI_STATE_CURRENT_STATE)
-        current_state = state;
+        data->current_state = state;
 
-    switch (current_state) {
+    switch (data->current_state) {
     case SYNC_UI_STATE_GETTING_SERVER:
         clear_error_info (data);
         gtk_widget_show (data->server_box);
@@ -886,6 +464,7 @@ set_app_state (app_data *data, app_state state)
         gtk_widget_set_sensitive (data->change_service_btn, FALSE);
         break;
     case SYNC_UI_STATE_SERVER_OK:
+        /* we have a active, idle session */
         gtk_widget_show (data->server_box);
         gtk_widget_hide (data->server_failure_box);
         gtk_widget_hide (data->no_server_box);
@@ -908,6 +487,8 @@ set_app_state (app_data *data, app_state state)
         break;
         
     case SYNC_UI_STATE_SYNCING:
+        /* we have a active session, and a session is running
+           (the running session may or may not be ours) */
         clear_error_info (data);
         gtk_widget_show (data->progress);
         gtk_label_set_text (GTK_LABEL (data->sync_status_label), _("Syncing"));
@@ -934,11 +515,19 @@ sync_type_toggled_cb (GObject *radio, app_data *data)
     }
 }
 
-
 #ifdef USE_MOBLIN_UX
+static void
+settings_visibility_changed_cb (GtkWidget *window, app_data *data)
+{
+    if (mux_window_get_settings_visible (MUX_WINDOW (window))) {
+        update_services_list (data);
+    }
+}
+
 /* truly stupid, but glade doesn't allow custom containers.
    Now glade file has dummy containers that will be replaced here.
    The dummy should be a gtkbin and it's parent should be a box with just one child */ 
+
 static GtkWidget*
 switch_dummy_to_mux_frame (GtkWidget *dummy)
 {
@@ -974,21 +563,43 @@ static GtkWidget*
 switch_dummy_to_mux_window (GtkWidget *dummy)
 {
     GtkWidget *window;
-    const char *title;
 
     g_assert (GTK_IS_WINDOW (dummy));
 
     window = mux_window_new ();
     gtk_window_set_default_size (GTK_WINDOW (window), 1024, 600);
     gtk_widget_set_name (window, gtk_widget_get_name (dummy));
-    title = gtk_window_get_title (GTK_WINDOW (dummy));
-    if (title && strlen (title) > 0)
-        gtk_window_set_title (GTK_WINDOW (window), title);
+    gtk_window_set_modal (GTK_WINDOW (window),
+                          gtk_window_get_modal (GTK_WINDOW (dummy)));
+
     mux_window_set_decorations (MUX_WINDOW (window), MUX_DECOR_CLOSE);
     gtk_widget_reparent (gtk_bin_get_child (GTK_BIN (dummy)), window);
 
     return window;
 }
+
+static void
+switch_main_and_settings_to_mux_window (app_data *data,
+                                        GtkWidget *main, GtkWidget *settings)
+{
+    GtkWidget *mux_main;
+    GtkWidget *tmp;
+
+    mux_main = switch_dummy_to_mux_window (main);
+    mux_window_set_decorations (MUX_WINDOW (mux_main), MUX_DECOR_SETTINGS|MUX_DECOR_CLOSE);
+    g_signal_connect (mux_main, "settings-visibility-changed",
+                      G_CALLBACK (settings_visibility_changed_cb), data);
+
+    tmp = g_object_ref (gtk_bin_get_child (GTK_BIN (settings)));
+    gtk_container_remove (GTK_CONTAINER (settings), tmp);
+    mux_window_set_settings_widget (MUX_WINDOW (mux_main), tmp);
+    g_object_unref (tmp);
+
+    data->sync_win = mux_main;
+    data->services_win = NULL;
+}
+
+
 #else
 
 /* return the placeholders themselves when not using Moblin UX */
@@ -996,24 +607,38 @@ static GtkWidget*
 switch_dummy_to_mux_frame (GtkWidget *dummy) {
     return dummy;
 }
-static GtkWidget*
-switch_dummy_to_mux_window (GtkWidget *dummy)
+static void
+switch_main_and_settings_to_mux_window (app_data *data,
+                                        GtkWidget *main, GtkWidget *settings)
 {
-    return dummy;
+    data->sync_win = main;
+    data->services_win = settings;
+    gtk_window_set_transient_for (GTK_WINDOW (data->services_win),
+                                  GTK_WINDOW (data->sync_win));
+    g_signal_connect (data->services_win, "delete-event",
+                      G_CALLBACK (gtk_widget_hide_on_delete), NULL);
 }
 #endif
 
-/* keypress handler for the transient windows (service list & service settings) */
-static gboolean
-key_press_cb (GtkWidget *widget,
-              GdkEventKey *event,
-              gpointer user_data)
+/* This is a hacky way to achieve autoscrolling when the expanders open/close */
+static void
+services_box_allocate_cb (GtkWidget     *widget,
+                          GtkAllocation *allocation,
+                          app_data *data)
 {
-    if (event->keyval == GDK_Escape) {
-        gtk_widget_hide (widget);
-        return TRUE;
+    if (data->expanded_config) {
+        int y, height;
+        GtkAdjustment *adj;
+
+        gtk_widget_translate_coordinates (data->expanded_config,
+                                          data->services_box,
+                                          0, 0, NULL, &y);
+        height = data->expanded_config->allocation.height;
+
+        adj = gtk_scrolled_window_get_vadjustment
+                (GTK_SCROLLED_WINDOW (data->scrolled_window));
+        gtk_adjustment_clamp_page (adj, y, y + height);
     }
-    return FALSE;
 }
 
 static gboolean
@@ -1022,7 +647,7 @@ init_ui (app_data *data)
     GtkBuilder *builder;
     GError *error = NULL;
     GObject *radio;
-    GtkWidget *frame, *service_save_btn, *setup_service_btn , *image;
+    GtkWidget *frame, *setup_service_btn , *image;
 
     gtk_rc_parse (THEMEDIR "sync-ui.rc");
 
@@ -1068,70 +693,39 @@ init_ui (app_data *data)
     g_signal_connect (data->new_service_btn, "clicked",
                       G_CALLBACK (setup_new_service_clicked), data);
 
-    data->services_table = GTK_WIDGET (gtk_builder_get_object (builder, "services_table"));
-    data->manual_services_table = GTK_WIDGET (gtk_builder_get_object (builder, "manual_services_table"));
-    data->manual_services_scrolled = GTK_WIDGET (gtk_builder_get_object (builder, "manual_services_scrolled"));
+    data->scrolled_window = GTK_WIDGET (gtk_builder_get_object (builder, "scrolledwindow"));
+    data->services_box = GTK_WIDGET (gtk_builder_get_object (builder, "services_box"));
+    g_signal_connect(data->services_box, "size-allocate",
+                     G_CALLBACK (services_box_allocate_cb), data);
     data->back_btn = GTK_WIDGET (gtk_builder_get_object (builder, "back_btn"));
 
-    data->service_link = GTK_WIDGET (gtk_builder_get_object (builder, "service_link"));
-    data->service_description_label = GTK_WIDGET (gtk_builder_get_object (builder, "service_description_label"));
-    data->service_name_label = GTK_WIDGET (gtk_builder_get_object (builder, "service_name_label"));
-    data->service_name_entry = GTK_WIDGET (gtk_builder_get_object (builder, "service_name_entry"));
-    data->server_settings_expander = GTK_WIDGET (gtk_builder_get_object (builder, "server_settings_expander"));
-    data->username_entry = GTK_WIDGET (gtk_builder_get_object (builder, "username_entry"));
-    data->password_entry = GTK_WIDGET (gtk_builder_get_object (builder, "password_entry"));
-    data->server_settings_table = GTK_WIDGET (gtk_builder_get_object (builder, "server_settings_table"));
-    data->reset_server_btn = GTK_WIDGET (gtk_builder_get_object (builder, "reset_server_btn"));
-    data->delete_service_btn = GTK_WIDGET (gtk_builder_get_object (builder, "delete_service_btn"));
-    data->stop_using_service_btn = GTK_WIDGET (gtk_builder_get_object (builder, "stop_using_service_btn"));
-    service_save_btn = GTK_WIDGET (gtk_builder_get_object (builder, "service_save_btn"));
-
     radio = gtk_builder_get_object (builder, "two_way_radio");
-    g_object_set_data (radio, "mode", GINT_TO_POINTER (SYNC_TWO_WAY));
+    g_object_set_data (radio, "mode", GINT_TO_POINTER (SYNCEVO_SYNC_TWO_WAY));
     g_signal_connect (radio, "toggled",
                       G_CALLBACK (sync_type_toggled_cb), data);
     radio = gtk_builder_get_object (builder, "one_way_from_remote_radio");
-    g_object_set_data (radio, "mode", GINT_TO_POINTER (SYNC_REFRESH_FROM_SERVER));
+    g_object_set_data (radio, "mode", GINT_TO_POINTER (SYNCEVO_SYNC_REFRESH_FROM_SERVER));
     g_signal_connect (radio, "toggled",
                       G_CALLBACK (sync_type_toggled_cb), data);
     radio = gtk_builder_get_object (builder, "one_way_from_local_radio");
-    g_object_set_data (radio, "mode", GINT_TO_POINTER (SYNC_REFRESH_FROM_CLIENT));
+    g_object_set_data (radio, "mode", GINT_TO_POINTER (SYNCEVO_SYNC_REFRESH_FROM_CLIENT));
     g_signal_connect (radio, "toggled",
                       G_CALLBACK (sync_type_toggled_cb), data);
 
     /* No (documented) way to add own widgets to gtkbuilder it seems...
        swap the all dummy widgets with Muxwidgets */
-    data->sync_win = switch_dummy_to_mux_window (GTK_WIDGET (gtk_builder_get_object (builder, "sync_win")));
-    data->services_win = switch_dummy_to_mux_window (GTK_WIDGET (gtk_builder_get_object (builder, "services_win")));
-    gtk_window_set_transient_for (GTK_WINDOW (data->services_win), 
-                                  GTK_WINDOW (data->sync_win));
-    data->service_settings_win = switch_dummy_to_mux_window (GTK_WIDGET (gtk_builder_get_object (builder, "service_settings_win")));
+    switch_main_and_settings_to_mux_window (data,
+                                            GTK_WIDGET (gtk_builder_get_object (builder, "sync_win")),
+                                            GTK_WIDGET (gtk_builder_get_object (builder, "services_win")));
 
     data->main_frame = switch_dummy_to_mux_frame (GTK_WIDGET (gtk_builder_get_object (builder, "main_frame")));
     data->log_frame = switch_dummy_to_mux_frame (GTK_WIDGET (gtk_builder_get_object (builder, "log_frame")));
     frame = switch_dummy_to_mux_frame (GTK_WIDGET (gtk_builder_get_object (builder, "services_list_frame")));
-    data->service_settings_frame = switch_dummy_to_mux_frame (GTK_WIDGET (gtk_builder_get_object (builder, "service_settings_frame")));
 
     g_signal_connect (data->sync_win, "destroy",
                       G_CALLBACK (gtk_main_quit), NULL);
-    g_signal_connect (data->services_win, "delete-event",
-                      G_CALLBACK (gtk_widget_hide_on_delete), NULL);
-    g_signal_connect (data->services_win, "key-press-event",
-                      G_CALLBACK (key_press_cb), NULL);
-    g_signal_connect (data->service_settings_win, "delete-event",
-                      G_CALLBACK (gtk_widget_hide_on_delete), NULL);
-    g_signal_connect (data->service_settings_win, "key-press-event",
-                      G_CALLBACK (key_press_cb), NULL);
     g_signal_connect_swapped (data->back_btn, "clicked",
-                      G_CALLBACK (gtk_widget_hide), data->services_win);
-    g_signal_connect (data->delete_service_btn, "clicked",
-                      G_CALLBACK (delete_service_clicked_cb), data);
-    g_signal_connect (data->stop_using_service_btn, "clicked",
-                      G_CALLBACK (stop_using_service_clicked_cb), data);
-    g_signal_connect (data->reset_server_btn, "clicked",
-                      G_CALLBACK (reset_service_clicked_cb), data);
-    g_signal_connect (service_save_btn, "clicked",
-                      G_CALLBACK (service_save_clicked_cb), data);
+                      G_CALLBACK (show_main_view), data);
     g_signal_connect (data->change_service_btn, "clicked",
                       G_CALLBACK (change_service_clicked_cb), data);
     g_signal_connect (setup_service_btn, "clicked",
@@ -1146,29 +740,27 @@ init_ui (app_data *data)
 }
 
 static void
-add_server_option (SyncevoOption *option, server_config *server)
-{
-    server_config_update_from_option (server, option);
-}
-
-static void
 source_check_toggled_cb (GtkCheckButton *check, app_data *data)
 {
-    GPtrArray *options;
-    gboolean *enabled;
-    
-    enabled = g_object_get_data (G_OBJECT (check), "enabled");
-    *enabled = !*enabled;
-    
-    options = server_config_get_option_array (data->current_service);
-    syncevo_service_set_server_config_async (data->service, 
-                                             data->current_service->name,
-                                             options,
-                                             (SyncevoSetServerConfigCb)set_server_config_cb, 
-                                             data);
-
-    g_ptr_array_foreach (options, (GFunc)syncevo_option_free, NULL);
-    g_ptr_array_free (options, TRUE);
+    operation_data *op_data;
+    source_config *source;
+    char *value;
+
+    source = (source_config*) g_object_get_data (G_OBJECT (check), "source");
+    g_return_if_fail (source);
+
+    value = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check)) ?
+            g_strdup ("two-way") : g_strdup ("none");
+    g_hash_table_insert (source->config, g_strdup ("sync"), value);
+
+    op_data = g_slice_new (operation_data);
+    op_data->data = data;
+    op_data->operation = OP_SAVE;
+    op_data->started = FALSE;
+    syncevo_server_start_session (data->server,
+                                  data->current_service->name,
+                                  (SyncevoServerStartSessionCb)start_session_cb,
+                                  op_data);
 }
 
 static void
@@ -1200,772 +792,885 @@ load_icon (const char *uri, GtkBox *icon_box, guint icon_size)
     }
 
     image = gtk_image_new_from_pixbuf (pixbuf);
+    gtk_widget_set_size_request (image, icon_size, icon_size);
     g_object_unref (pixbuf);
-    gtk_container_foreach (GTK_CONTAINER (icon_box),
+    gtk_container_foreach (GTK_CONTAINER(icon_box),
                            (GtkCallback)remove_child,
                            icon_box);
-    gtk_box_pack_start_defaults (icon_box, image);
+   gtk_box_pack_start (icon_box, image, FALSE, FALSE, 0);
     gtk_widget_show (image);
 }
 
 static void
-update_service_ui (app_data *data)
+update_service_source_ui (const char *name, source_config *conf, app_data *data)
 {
-    GList *l;
-
-    g_assert (data->current_service);
-
-    gtk_container_foreach (GTK_CONTAINER (data->sources_box),
-                           (GtkCallback)remove_child,
-                           data->sources_box);
-    g_hash_table_remove_all (data->source_report_labels);
+    GtkWidget *check, *box, *lbl;
+    char *pretty_name;
+    const char *source_uri, *sync;
+    gboolean enabled;
+
+    pretty_name = get_pretty_source_name (name);
+    source_uri = g_hash_table_lookup (conf->config, "uri");
+    sync = g_hash_table_lookup (conf->config, "sync");
+    if (!sync || 
+        strcmp (sync, "disabled") == 0 ||
+        strcmp (sync, "none") == 0) {
+        // consider this source not available at all
+        enabled = FALSE;
+    } else {
+        enabled = TRUE;
+    }
 
-    if (data->current_service->name)
-        gtk_label_set_markup (GTK_LABEL (data->server_label), data->current_service->name);
+    /* argh, GtkCheckButton won't layout nicely with several labels... 
+       There is no way to align the check with the top row and 
+       get the labels to align and not use way too much vertical space.
+       In this hack the labels are not related to the checkbutton at all,
+       this is definitely not nice but looks better */
 
-    load_icon (data->current_service->icon_uri, 
-               GTK_BOX (data->server_icon_box), 
-               SYNC_UI_ICON_SIZE);
+    conf->box = gtk_hbox_new (FALSE, 0);
+    gtk_box_pack_start_defaults (GTK_BOX (data->sources_box), conf->box);
     
-    for (l = data->current_service->source_configs; l; l = l->next) {
-        source_config *source = (source_config*)l->data;
-        GtkWidget *check, *hbox, *box, *lbl;
-        char *name;
-        
-        if (!source->supported_locally) {
-            /* could also show as insensitive, like with unsupported services... */
-            continue;
-        }
-
-        name = get_pretty_source_name (source->name);
-        
-        /* argh, GtkCheckButton won't layout nicely with several labels... 
-           There is no way to align the check with the top row and 
-           get the labels to align and not use way too much vertical space.
-           In this hack the labels are not related to the checkbutton at all,
-           this is definitely not nice but looks better */
-
-        hbox = gtk_hbox_new (FALSE, 0);
-        gtk_box_pack_start_defaults (GTK_BOX (data->sources_box), hbox);
-        box = gtk_vbox_new (FALSE, 0);
-        gtk_box_pack_start (GTK_BOX (hbox), box, FALSE, FALSE, 0);
-        check = gtk_check_button_new ();
-        gtk_box_pack_start (GTK_BOX (box), check, FALSE, FALSE, 0);
-
-        box = gtk_vbox_new (FALSE, 0);
-        gtk_box_pack_start_defaults (GTK_BOX (hbox), box);
-        gtk_container_set_border_width (GTK_CONTAINER (box), 2);
-        if (source->uri && strlen (source->uri) > 0) {
-            lbl = gtk_label_new (name);
-            gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), source->enabled);
-            gtk_widget_set_sensitive (check, TRUE);
-        } else {
-            char *text;
-            /* TRANSLATORS: placeholder is a source name, shown with checkboxes in main window */
-            text = g_strdup_printf (_("%s (not supported by this service)"), name);
-            lbl = gtk_label_new (text);
-            g_free (text);
-            gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), FALSE);
-            gtk_widget_set_sensitive (check, FALSE);
-        }
-        g_free (name);
-        gtk_misc_set_alignment (GTK_MISC (lbl), 0.0, 0.5);
-        gtk_box_pack_start_defaults (GTK_BOX (box), lbl);
-
-        lbl = gtk_label_new (NULL);
-        gtk_misc_set_alignment (GTK_MISC (lbl), 0.0, 0.5);
-        gtk_box_pack_start_defaults (GTK_BOX (box), lbl);
-        /* this is a bit hacky... maybe the link to the label should be in source_config ? */
-        g_hash_table_insert (data->source_report_labels, source->name, lbl);
-
-        g_object_set_data (G_OBJECT (check), "enabled", &source->enabled);
-        g_signal_connect (check, "toggled",
-                          G_CALLBACK (source_check_toggled_cb), data);
  
+    box = gtk_vbox_new (FALSE, 0);
+    gtk_box_pack_start (GTK_BOX (conf->box), box, FALSE, FALSE, 0);
+    check = gtk_check_button_new ();
+    gtk_box_pack_start (GTK_BOX (box), check, FALSE, FALSE, 0);
+
+    box = gtk_vbox_new (FALSE, 0);
+    gtk_box_pack_start_defaults (GTK_BOX (conf->box), box);
+    gtk_container_set_border_width (GTK_CONTAINER (box), 2);
+
+    if (source_uri && strlen (source_uri) > 0) {
+        lbl = gtk_label_new (pretty_name);
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), enabled);
+        gtk_widget_set_sensitive (check, TRUE);
+    } else {
+        char *text;
+        /* TRANSLATORS: placeholder is a source name, shown with checkboxes in main window */
+        text = g_strdup_printf (_("%s (not supported by this service)"), pretty_name);
+        lbl = gtk_label_new (text);
+        g_free (text);
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), FALSE);
+        gtk_widget_set_sensitive (check, FALSE);
     }
-    gtk_widget_show_all (data->sources_box);
+    g_free (pretty_name);
 
-}
+    gtk_misc_set_alignment (GTK_MISC (lbl), 0.0, 0.5);
+    gtk_box_pack_start_defaults (GTK_BOX (box), lbl);
 
-static char*
-get_report_summary (int local_changes, int remote_changes, int local_rejects, int remote_rejects)
-{
-    char *rejects, *changes, *msg;
-
-    if (local_rejects + remote_rejects == 0) {
-        rejects = NULL;
-    } else if (local_rejects == 0) {
-        rejects = g_strdup_printf (ngettext ("There was one remote rejection.", 
-                                             "There were %d remote rejections.",
-                                             remote_rejects),
-                                   remote_rejects);
-    } else if (remote_rejects == 0) {
-        rejects = g_strdup_printf (ngettext ("There was one local rejection.", 
-                                             "There were %d local rejections.",
-                                             local_rejects),
-                                   local_rejects);
-    } else {
-        rejects = g_strdup_printf (_ ("There were %d local rejections and %d remote rejections."),
-                                   local_rejects, remote_rejects);
-    }
+    conf->label = gtk_label_new (NULL);
+    gtk_misc_set_alignment (GTK_MISC (conf->label), 0.0, 0.5);
+    gtk_box_pack_start_defaults (GTK_BOX (box), conf->label);
 
-    if (local_changes + remote_changes == 0) {
-        changes = g_strdup_printf (_("Last time: No changes."));
-    } else if (local_changes == 0) {
-        changes = g_strdup_printf (ngettext ("Last time: Sent one change.",
-                                             "Last time: Sent %d changes.",
-                                             remote_changes),
-                                   remote_changes);
-    } else if (remote_changes == 0) {
-        // This is about changes made to the local data. Not all of these
-        // changes were requested by the remote server, so "applied"
-        // is a better word than "received" (bug #5185).
-        changes = g_strdup_printf (ngettext ("Last time: Applied one change.",
-                                             "Last time: Applied %d changes.",
-                                             local_changes),
-                                   local_changes);
-    } else {
-        changes = g_strdup_printf (_("Last time: Applied %d changes and sent %d changes."),
-                                   local_changes, remote_changes);
-    }
+    source_config_update_label (conf);
 
-    if (rejects)
-        msg = g_strdup_printf ("%s\n%s", changes, rejects);
-    else
-        msg = g_strdup (changes);
-    g_free (rejects);
-    g_free (changes);
-    return msg;
+    g_object_set_data (G_OBJECT (check), "source", (gpointer)conf);
+    g_signal_connect (check, "toggled",
+                      G_CALLBACK (source_check_toggled_cb), data);
+
+    if (conf->supported_locally) {
+        gtk_widget_show_all (conf->box); 
+    }
 }
 
 static void
-update_sync_report_data (SyncevoReport *report, app_data *data)
+check_source_cb (SyncevoSession *session,
+                 GError *error,
+                 source_config *source)
 {
-    const char *name;
-    GtkLabel *lbl;
-    
-    name = syncevo_report_get_name (report);
-    lbl = GTK_LABEL (g_hash_table_lookup (data->source_report_labels, name));
-    if (lbl) {
-        char *msg;
-        int local_changes, local_adds, local_updates, local_removes, local_rejects;
-        int remote_changes, remote_adds, remote_updates, remote_removes, remote_rejects;
-        
-        syncevo_report_get_local (report, &local_adds, &local_updates, &local_removes, &local_rejects);
-        syncevo_report_get_remote (report, &remote_adds, &remote_updates, &remote_removes, &remote_rejects);
-        local_changes = local_adds + local_updates + local_removes;
-        remote_changes = remote_adds + remote_updates + remote_removes;
+    if (error) {
+        if(error->code == DBUS_GERROR_REMOTE_EXCEPTION &&
+           dbus_g_error_has_name (error, SYNCEVO_DBUS_ERROR_SOURCE_UNUSABLE)) {
+            /* source is not supported locally */
+            if (source) {
+                source->supported_locally = FALSE;
+                if (source->box) {
+                    /* widget is already on screen, hide it */
+                    gtk_widget_hide (source->box); 
+                }
+            }
+        } else {
+            g_warning ("CheckSource failed: %s", error->message);
+            /* non-fatal, unknown error */
+        }
 
-        msg = get_report_summary (local_changes, remote_changes, local_rejects, remote_rejects);
-        gtk_label_set_text (lbl, msg);
-        g_free (msg);
+        g_error_free (error);
+        return;
     }
 }
 
 static void
-get_sync_reports_cb (SyncevoService *service, GPtrArray *reports, GError *error, app_data *data)
+update_service_ui (app_data *data)
 {
-    if (error) {
-        g_warning ("Failed to get sync reports from SyncEvolution: %s", error->message);
-        g_error_free (error);
-        return;
-    }
+    char *icon_uri;
 
-    if (reports->len < 1) {
-        data->last_sync = -1; 
-    } else {
-        GPtrArray *source_reports;
-        SyncevoReportArray *session_report = (SyncevoReportArray*)g_ptr_array_index (reports, 0);
-        syncevo_report_array_get (session_report, &data->last_sync, &source_reports);
-        g_ptr_array_foreach (source_reports, (GFunc)update_sync_report_data, data);
+    g_assert (data->current_service && data->current_service->config);
+
+    gtk_container_foreach (GTK_CONTAINER (data->sources_box),
+                           (GtkCallback)remove_child,
+                           data->sources_box);
+
+    syncevo_config_get_value (data->current_service->config,
+                              NULL, "IconURI", &icon_uri);
+
+    if (data->current_service->name){
+        gtk_label_set_markup (GTK_LABEL (data->server_label), 
+                              data->current_service->name);
     }
-    refresh_last_synced_label (data);
+    if (icon_uri) {
+        load_icon (icon_uri,
+                   GTK_BOX (data->server_icon_box),
+                   SYNC_UI_ICON_SIZE);
+    }
+
+    g_hash_table_foreach (data->current_service->source_configs,
+                          (GHFunc)update_service_source_ui,
+                          data);
 
-    g_ptr_array_foreach (reports, (GFunc)syncevo_report_array_free, NULL);
-    g_ptr_array_free (reports, TRUE);
+/* TODO: make sure all default sources are visible
+ * (iow add missing sources as insensitive) */
 
+    gtk_widget_show_all (data->sources_box);
 }
 
 static void
-find_password_cb (GnomeKeyringResult result, GList *list, app_data *data)
+unexpand_config_widget (GtkWidget *w, GtkWidget *exception)
 {
-    switch (result) {
-    case GNOME_KEYRING_RESULT_NO_MATCH:
-        break;
-    case GNOME_KEYRING_RESULT_OK:
-        if (list && list->data) {
-            GnomeKeyringNetworkPasswordData *key_data;
-            key_data = (GnomeKeyringNetworkPasswordData*)list->data;
-            data->current_service->password = g_strdup (key_data->password);
-        }
-        break;
-    default:
-        g_warning ("getting password from GNOME keyring failed: %s",
-                   gnome_keyring_result_to_message (result));
-        break;
+    if (SYNC_IS_CONFIG_WIDGET (w) && exception && exception != w) {
+        sync_config_widget_set_expanded (SYNC_CONFIG_WIDGET (w), FALSE);
     }
-    return;
 }
 
 static void
-get_server_config_cb (SyncevoService *service, GPtrArray *options, GError *error, app_data *data)
+config_widget_expanded_cb (GtkWidget *widget, GParamSpec *pspec, app_data *data)
 {
-    char *server_address;
+    if (sync_config_widget_get_expanded (SYNC_CONFIG_WIDGET (widget))) {
+        data->expanded_config = widget;
+        gtk_container_foreach (GTK_CONTAINER (data->services_box),
+                               (GtkCallback)unexpand_config_widget,
+                               widget);
+    }
+}
 
-    if (error) {
-        /* just warn if current server has disappeared -- probably just command line use */
-        if (error->code == DBUS_GERROR_REMOTE_EXCEPTION &&
-            dbus_g_error_has_name (error, SYNCEVO_DBUS_ERROR_NO_SUCH_SERVER)) {
-            add_error_info (data, 
-                            _("Failed to get server configuration from SyncEvolution"), 
-                            error->message);
-            set_app_state (data, SYNC_UI_STATE_NO_SERVER);
-        } else {
-            set_app_state (data, SYNC_UI_STATE_SERVER_FAILURE);
-        }
-        g_error_free (error);
-        return;
+static void
+config_widget_changed_cb (GtkWidget *widget, app_data *data)
+{
+    const char *name = NULL;
+
+    if (sync_config_widget_get_current (SYNC_CONFIG_WIDGET (widget))) {
+        name = sync_config_widget_get_name (SYNC_CONFIG_WIDGET (widget));
     }
+    reload_config (data, name);
 
-    g_ptr_array_foreach (options, (GFunc)add_server_option, data->current_service);
-    ensure_default_sources_exist (data->current_service);
-    
-    update_service_ui (data);
-    set_app_state (data, SYNC_UI_STATE_SERVER_OK);
+    update_services_list (data);
+}
 
-    server_address = strstr (data->current_service->base_url, "://");
-    if (server_address)
-        server_address = server_address + 3;
+static GtkWidget*
+add_server_to_box (GtkBox *box,
+                   const char *name,
+                   gboolean configured,
+                   gboolean has_template,
+                   app_data *data)
+{
+    GtkWidget *item = NULL;
+    gboolean current = FALSE;
+    gboolean unset;
 
-    if (!server_address) {
-        g_warning ("Server configuration has suspect URL '%s'",
-                   data->current_service->base_url);
-    } else {
-        gnome_keyring_find_network_password (data->current_service->username,
-                                             NULL,
-                                             server_address,
-                                             NULL,
-                                             NULL,
-                                             NULL,
-                                             0,
-                                             (GnomeKeyringOperationGetListCallback)find_password_cb,
-                                             data,
-                                             NULL);
+    if (data->current_service && data->current_service->name &&
+        name && strcmp (name, data->current_service->name) == 0) {
+        current = TRUE;
+     }
+    unset = !data->current_service;
+
+    item = sync_config_widget_new (data->server, name,
+                                   current, unset, configured, has_template);
+    g_signal_connect (item, "changed",
+                      G_CALLBACK (config_widget_changed_cb), data);
+    g_signal_connect (item, "notify::expanded",
+                      G_CALLBACK (config_widget_expanded_cb), data);
+    gtk_widget_show (item);
+    gtk_box_pack_start (box, item, FALSE, FALSE, 0);
+
+    if (current) {
+        sync_config_widget_set_expanded (SYNC_CONFIG_WIDGET (item),
+                                        data->open_current);
+        data->open_current = FALSE;
     }
 
-    /* get last sync report (for last sync time) */
-    syncevo_service_get_sync_reports_async (service, data->current_service->name, 1,
-                                            (SyncevoGetSyncReportsCb)get_sync_reports_cb,
-                                            data);
-
-    g_ptr_array_foreach (options, (GFunc)syncevo_option_free, NULL);
-    g_ptr_array_free (options, TRUE);
+    return item;
 }
 
-const char*
-get_service_description (const char *service)
+
+static void
+setup_new_service_clicked (GtkButton *btn, app_data *data)
 {
-    if (!service)
-        return "";
 
-    if (strcmp (service, "ScheduleWorld") == 0) {
-        return _("ScheduleWorld enables you to keep your contacts, events, "
-                 "tasks, and notes in sync.");
-    }else if (strcmp (service, "Google") == 0) {
-        return _("Google Sync can backup and synchronize your Address Book "
-                 "with your Gmail contacts.");
-    }else if (strcmp (service, "Funambol") == 0) {
-        /* TRANSLATORS: Please include the word "demo" (or the equivalent in
-           your language): Funambol is going to be a 90 day demo service
-           in the future */
-        return _("Backup your contacts and calendar. Sync with a single"
-                 "click, anytime, anywhere (DEMO).");
-    }
+    GtkWidget *widget;
+
+    gtk_container_foreach (GTK_CONTAINER (data->services_box),
+                           (GtkCallback)unexpand_config_widget,
+                           NULL);
 
-    return "";
+    widget = add_server_to_box (GTK_BOX (data->services_box),
+                                "default",
+                                FALSE, TRUE,
+                                data);
+    sync_config_widget_set_expanded (SYNC_CONFIG_WIDGET (widget), TRUE);
 }
 
+
+typedef struct templates_data {
+    app_data *data;
+    char **templates;
+} templates_data;
+
 static void
-show_settings_window (app_data *data, server_config *config)
+get_configs_cb (SyncevoServer *server,
+                char **configs,
+                GError *error,
+                templates_data *templ_data)
 {
-    GList *l;
-    GtkWidget *label, *entry;
-    int i = 0;
+    char **config_iter, **template_iter, **templates;
+    app_data *data;
+    GtkWidget *widget;
 
-    gtk_container_foreach (GTK_CONTAINER (data->server_settings_table),
-                           (GtkCallback)remove_child,
-                           data->server_settings_table);
-    gtk_table_resize (GTK_TABLE (data->server_settings_table), 
-                      2, g_list_length (config->source_configs) + 1);
-
-    gtk_entry_set_text (GTK_ENTRY (data->service_name_entry), 
-                        config->name ? config->name : "");
-    g_object_set_data (G_OBJECT (data->service_name_entry), "value", &config->name);
-    if (config->name) {
-        gtk_frame_set_label (GTK_FRAME (data->service_settings_frame), config->name);
-        gtk_widget_hide (data->service_name_label);
-        gtk_widget_hide (data->service_name_entry);
-    } else {
-        gtk_frame_set_label (GTK_FRAME (data->service_settings_frame), _("New service"));
-        gtk_widget_show (data->service_name_label);
-        gtk_widget_show (data->service_name_entry);
+    templates = templ_data->templates;
+    data = templ_data->data;
+    g_slice_free (templates_data, templ_data);
+
+    if (error) {
+        show_main_view (data);
+        /* TODO show in UI: failed to show service list */
+        show_error_dialog (data->sync_win, 
+                           _("Failed to get list of configured services from SyncEvolution"));
+        g_warning ("Server.GetConfigs() failed: %s", error->message);
+        g_strfreev (templates);
+        g_error_free (error);
+        return;
     }
 
-    gtk_label_set_text (GTK_LABEL (data->service_description_label),
-                        get_service_description (config->name));
+    for (template_iter = templates; *template_iter; template_iter++){
+        gboolean found_config = FALSE;
 
-    if (config->web_url) {
-        gtk_link_button_set_uri (GTK_LINK_BUTTON (data->service_link), 
-                                 config->web_url);
-        gtk_widget_show (data->service_link);
-    } else {
-        gtk_widget_hide (data->service_link);
+        for (config_iter = configs; *config_iter; config_iter++) {
+            if (*template_iter && 
+                *config_iter && 
+                g_ascii_strncasecmp (*template_iter,
+                                     *config_iter,
+                                     strlen (*config_iter)) == 0) {
+
+                widget = add_server_to_box (GTK_BOX (data->services_box),
+                                            *config_iter,
+                                            TRUE, TRUE,
+                                            data);
+                found_config = TRUE;
+                break;
+            }
+        }
+        if (!found_config) {
+            widget = add_server_to_box (GTK_BOX (data->services_box),
+                                        *template_iter,
+                                        FALSE, TRUE,
+                                        data);
+        }
     }
 
-    gtk_expander_set_expanded (GTK_EXPANDER (data->server_settings_expander), 
-                               !config->from_template);
-    if (config->from_template) {
-        gtk_widget_show (GTK_WIDGET (data->reset_server_btn));
-        gtk_widget_hide (GTK_WIDGET (data->delete_service_btn));
-    } else {
-        gtk_widget_hide (GTK_WIDGET (data->reset_server_btn));
-        if (config->name) {
-            gtk_widget_show (GTK_WIDGET (data->delete_service_btn));
-        } else {
-            gtk_widget_hide (GTK_WIDGET (data->delete_service_btn));
+    for (config_iter = configs; *config_iter; config_iter++) {
+        gboolean found_template = FALSE;
+
+        for (template_iter = templates; *template_iter; template_iter++) {
+            if (*template_iter && 
+                *config_iter && 
+                g_ascii_strncasecmp (*template_iter,
+                                     *config_iter,
+                                     strlen (*config_iter)) == 0) {
+
+                found_template = TRUE;
+                break;
+            }
+        }
+        if (!found_template) {
+            widget = add_server_to_box (GTK_BOX (data->services_box),
+                                        *config_iter,
+                                        TRUE, FALSE,
+                                        data);
         }
     }
 
-    if (data->current_service && data->current_service->name && config->name &&
-        strcmp (data->current_service->name, config->name) == 0)
-        gtk_widget_show (data->stop_using_service_btn);
-    else 
-        gtk_widget_hide (data->stop_using_service_btn);
-
-    gtk_entry_set_text (GTK_ENTRY (data->username_entry), 
-                        (config->username &&
-                         strcmp(config->username, "your SyncML server account name")) ?
-                        config->username :
-                        "");
-    g_object_set_data (G_OBJECT (data->username_entry), "value", &config->username);
-
-    gtk_entry_set_text (GTK_ENTRY (data->password_entry),
-                        config->password ? config->password : "");
-    g_object_set_data (G_OBJECT (data->password_entry), "value", &config->password);
-
-    label = gtk_label_new (_("Server URL"));
-    gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
-    gtk_table_attach (GTK_TABLE (data->server_settings_table), label,
-                      0, 1, i, i + 1, GTK_FILL, GTK_EXPAND, 0, 0);
-
-    entry = gtk_entry_new ();
-    gtk_entry_set_max_length (GTK_ENTRY (entry), 99);
-    gtk_entry_set_width_chars (GTK_ENTRY (entry), 80);
-    gtk_entry_set_text (GTK_ENTRY (entry), 
-                        config->base_url ? config->base_url : "");
-    g_object_set_data (G_OBJECT (entry), "value", &config->base_url);
-    gtk_table_attach_defaults (GTK_TABLE (data->server_settings_table), entry,
-                               1, 2, i, i + 1);
-
-    for (l = config->source_configs; l; l = l->next) {
-        source_config *source = (source_config*)l->data;
-        char *str;
-        char *name;
-        i++;
-
-        name = get_pretty_source_name (source->name);
-        /* TRANSLATORS: placeholder is a source name in settings window */
-        str = g_strdup_printf (_("%s URI"), name);
-        label = gtk_label_new (str);
-        g_free (str);
-        g_free (name);
-        gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
-        gtk_table_attach (GTK_TABLE (data->server_settings_table), label,
-                          0, 1, i, i + 1, GTK_FILL, GTK_EXPAND, 0, 0);
-
-        entry = gtk_entry_new ();
-        gtk_entry_set_max_length (GTK_ENTRY (entry), 99);
-        gtk_entry_set_width_chars (GTK_ENTRY (entry), 80);
-        gtk_entry_set_text (GTK_ENTRY (entry), 
-                            source->uri ? source->uri : "");
-        g_object_set_data (G_OBJECT (entry), "value", &source->uri);
-        g_object_set_data (G_OBJECT (entry), "enabled", &source->enabled);
-        gtk_table_attach_defaults (GTK_TABLE (data->server_settings_table), entry,
-                                   1, 2, i, i + 1);
+    g_strfreev (configs);
+    g_strfreev (templates);
+}
+
+static void
+get_template_configs_cb (SyncevoServer *server,
+                         char **templates,
+                         GError *error,
+                         app_data *data)
+{
+    templates_data *templ_data;
+
+    if (error) {
+        show_main_view (data);
+        /* TODO show in UI: failed to show service list */
+        show_error_dialog (data->sync_win, 
+                           _("Failed to get list of supported services from SyncEvolution"));
+        g_warning ("Server.GetConfigs() failed: %s", error->message);
+        g_error_free (error);
+        return;
     }
-    gtk_widget_show_all (data->server_settings_table);
 
-    /* TODO should free old server config... make sure do not free currently used config */
-    g_object_set_data (G_OBJECT (data->service_settings_win), "server", config);
+    templ_data = g_slice_new (templates_data);
+    templ_data->data = data;
+    templ_data->templates = templates;
 
-    gtk_window_present (GTK_WINDOW (data->service_settings_win));
+    syncevo_server_get_configs (data->server,
+                                FALSE,
+                                (SyncevoServerGetConfigsCb)get_configs_cb,
+                                templ_data);
 }
 
 static void
-ensure_default_sources_exist(server_config *server)
+update_services_list (app_data *data)
 {
-    server_config_get_source_config (server, "addressbook");
-    server_config_get_source_config (server, "calendar");
-    /* server_config_get_source_config (server, "memo"); */
-    server_config_get_source_config (server, "todo");
+    /* NOTE: could get this on ui startup as well for instant action.
+       Downside is stale data.... */
+
+    gtk_container_foreach (GTK_CONTAINER (data->services_box),
+                           (GtkCallback)remove_child,
+                           data->services_box);
+
+    syncevo_server_get_configs (data->server,
+                                TRUE,
+                                (SyncevoServerGetConfigsCb)get_template_configs_cb,
+                                data);
 }
 
 static void
-setup_service_clicked (GtkButton *btn, app_data *data)
+get_config_for_main_win_cb (SyncevoServer *server,
+                            SyncevoConfig *config,
+                            GError *error,
+                            app_data *data)
 {
-    SyncevoServer *server;
-    server_data *serv_data;
-    const char *name;
+    if (error) {
+        if (error->code == DBUS_GERROR_REMOTE_EXCEPTION &&
+            dbus_g_error_has_name (error, SYNCEVO_DBUS_ERROR_NO_SUCH_CONFIG)) {
+            /* another syncevolution client probably removed the config */
+        } else {
+            g_warning ("Error in Server.GetConfig: %s", error->message);
+            /* non-fatal, ignore in UI */
+        }
+        set_app_state (data, SYNC_UI_STATE_NO_SERVER);
+        g_error_free (error);
 
-    server = g_object_get_data (G_OBJECT (btn), "server");
-    syncevo_server_get (server, &name, NULL, NULL, NULL);
+        return;
+    }
+    
+    if (config) {
+        GHashTableIter iter;
+        char *name;
+        source_config *source;
 
-    serv_data = g_slice_new0 (server_data);
-    serv_data->data = data;
-    serv_data->config = g_slice_new0 (server_config);
-    serv_data->config->name = g_strdup (name);
+        server_config_init (data->current_service, config);
+        set_app_state (data, SYNC_UI_STATE_SERVER_OK);
+
+        /* get "locally supported" status for all sources */
+        g_hash_table_iter_init (&iter, data->current_service->source_configs);
+        while (g_hash_table_iter_next (&iter, (gpointer)&name, (gpointer)&source)) {
+
+            syncevo_server_check_source (data->server,
+                                         data->current_service->name,
+                                         name,
+                                         (SyncevoServerGenericCb)check_source_cb,
+                                         source);
+        }
+
+        syncevo_server_get_presence (server,
+                                     data->current_service->name,
+                                     (SyncevoServerGetPresenceCb)get_presence_cb,
+                                     data);
 
-    gtk_window_set_transient_for (GTK_WINDOW (data->service_settings_win), 
-                                  GTK_WINDOW (data->services_win));
+        syncevo_server_get_reports (server,
+                                    data->current_service->name,
+                                    0, 1,
+                                    (SyncevoServerGetReportsCb)get_reports_cb,
+                                    data);
 
-    syncevo_service_get_server_config_async (data->service, 
-                                             (char*)serv_data->config->name,
-                                             (SyncevoGetServerConfigCb)get_server_config_for_template_cb,
-                                             serv_data);
+        update_service_ui (data);
+
+    }
 }
 
 static void
-setup_new_service_clicked (GtkButton *btn, app_data *data)
+set_running_session_status (app_data *data, SyncevoSessionStatus status)
 {
-    server_data *serv_data;
-    SyncevoOption *option;
-    
-    serv_data = server_data_new (NULL, data);
-
-    /* syncevolution defaults are not empty, override ... */
-    serv_data->options_override = g_ptr_array_new ();
-    option = syncevo_option_new (NULL, "username", NULL);
-    g_ptr_array_add (serv_data->options_override, option);
-    option = syncevo_option_new (NULL, "password", NULL);
-    g_ptr_array_add (serv_data->options_override, option);
-    option = syncevo_option_new (NULL, "syncURL", NULL);
-    g_ptr_array_add (serv_data->options_override, option);
-    option = syncevo_option_new (NULL, "webURL", NULL);
-    g_ptr_array_add (serv_data->options_override, option);
-    option = syncevo_option_new (NULL, "fromTemplate", "no");
-    g_ptr_array_add (serv_data->options_override, option);
-    option = syncevo_option_new ("memo", "uri", NULL);
-    g_ptr_array_add (serv_data->options_override, option);
-    option = syncevo_option_new ("todo", "uri", NULL);
-    g_ptr_array_add (serv_data->options_override, option);
-    option = syncevo_option_new ("addressbook", "uri", NULL);
-    g_ptr_array_add (serv_data->options_override, option);
-    option = syncevo_option_new ("calendar", "uri", NULL);
-    g_ptr_array_add (serv_data->options_override, option);
-
-    gtk_window_set_transient_for (GTK_WINDOW (data->service_settings_win), 
-                                  GTK_WINDOW (data->services_win));
-
-    syncevo_service_get_server_config_async (data->service, 
-                                             "default",
-                                             (SyncevoGetServerConfigCb)get_server_config_for_template_cb,
-                                             serv_data);
-}
-
-enum ServerCols {
-    COL_ICON = 0,
-    COL_NAME,
-    COL_LINK,
-    COL_BUTTON,
-
-    NR_SERVER_COLS
-};
+    switch (status) {
+    case SYNCEVO_STATUS_QUEUEING:
+        g_warning ("Running session is queued, this shouldn't happen...");
+        break;
+    case SYNCEVO_STATUS_IDLE:
+        set_app_state (data, SYNC_UI_STATE_SERVER_OK);
+        break;
+    case SYNCEVO_STATUS_RUNNING:
+    case SYNCEVO_STATUS_SUSPENDING:
+    case SYNCEVO_STATUS_ABORTING:
+        set_app_state (data, SYNC_UI_STATE_SYNCING);
+        break;
+    case SYNCEVO_STATUS_DONE:
+        gtk_label_set_text (GTK_LABEL (data->sync_status_label), 
+                            _("Sync complete"));
+        set_app_state (data, SYNC_UI_STATE_SERVER_OK);
+        set_sync_progress (data, 1.0, "");
+        
+        break;
+    default:
+        g_warning ("unknown session status  %d used!", status);
+    }
+}
 
 static void
-add_server_to_table (GtkTable *table, int row, SyncevoServer *server, app_data *data)
+update_source_status (char *name,
+                      SyncevoSyncMode mode,
+                      SyncevoSourceStatus status,
+                      guint error_code,
+                      app_data *data)
 {
-    GtkWidget *label, *box, *link, *btn;
-    const char *name, *url, *icon;
+    char *error;
     
-    syncevo_server_get (server, &name, &url, &icon, NULL);
-    
-    box = gtk_hbox_new (FALSE, 0);
-    gtk_widget_set_size_request (box, SYNC_UI_LIST_ICON_SIZE, SYNC_UI_LIST_ICON_SIZE);
-    gtk_table_attach (table, box, COL_ICON, COL_ICON + 1, row, row+1,
-                      GTK_SHRINK|GTK_FILL, GTK_EXPAND|GTK_FILL, 5, 0);
-    load_icon (icon, GTK_BOX (box), SYNC_UI_LIST_ICON_SIZE);
-
-    label = gtk_label_new (name);
-    if (data->current_service && data->current_service->name &&
-        strcmp (name, data->current_service->name) == 0) {
-        char *str = g_strdup_printf ("<b>%s</b>", name);
-        gtk_label_set_markup (GTK_LABEL (label), str);
-        g_free (str);
-    }
-
-    gtk_widget_set_size_request (label, SYNC_UI_LIST_BTN_WIDTH, -1);
-    gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
-    gtk_table_attach (table, label, COL_NAME, COL_NAME + 1, row, row+1,
-                      GTK_SHRINK|GTK_FILL, GTK_EXPAND|GTK_FILL, 5, 0);
-
-    box = gtk_hbox_new (FALSE, 0);
-    gtk_table_attach (table, box, COL_LINK, COL_LINK + 1, row, row+1,
-                      GTK_EXPAND|GTK_FILL, GTK_EXPAND|GTK_FILL, 5, 0);
-    if (url && strlen (url) > 0) {
-        link = gtk_link_button_new_with_label (url, _("Launch website"));
-        gtk_box_pack_start (GTK_BOX (box), link, FALSE, FALSE, 0);
+    error = get_error_string_for_code (error_code);
+    if (error) {
+        /* TODO show sync error in UI -- but not duplicates */
+        g_warning ("Source '%s' error: %s", name, error);
+        g_free (error);
     }
-
-    btn = gtk_button_new_with_label (_("Setup and use"));
-    gtk_widget_set_size_request (btn, SYNC_UI_LIST_BTN_WIDTH, -1);
-    g_signal_connect (btn, "clicked",
-                      G_CALLBACK (setup_service_clicked), data);
-    gtk_table_attach (table, btn, COL_BUTTON, COL_BUTTON + 1, row, row+1,
-                      GTK_SHRINK|GTK_FILL, GTK_EXPAND|GTK_FILL, 5, 0);
-
-    g_object_set_data_full (G_OBJECT (btn), "server", server, 
-                            (GDestroyNotify)syncevo_server_free);
 }
 
-typedef struct templates_data {
-    app_data *data;
-    GPtrArray *templates;
-}templates_data;
-
-static gboolean
-server_array_contains (GPtrArray *array, SyncevoServer *server)
+static void
+running_session_status_changed_cb (SyncevoSession *session,
+                                   SyncevoSessionStatus status,
+                                   guint error_code,
+                                   SyncevoSourceStatuses *source_statuses,
+                                   app_data *data)
 {
-    int i;
-    const char *name;
+    /* TODO: show errors in UI -- but not duplicates */
+
+    char *error;
 
-    syncevo_server_get (server, &name, NULL, NULL, NULL);
+    set_running_session_status (data, status);
 
-    for (i = 0; i < array->len; i++) {
-        const char *n;
-        SyncevoServer *s = (SyncevoServer*)g_ptr_array_index (array, i);
-        syncevo_server_get (s, &n, NULL, NULL, NULL);
-        if (g_ascii_strcasecmp (name, n) == 0)
-            return TRUE;
+    syncevo_source_statuses_foreach (source_statuses,
+                                     (SourceStatusFunc)update_source_status,
+                                     data);
+
+    error = get_error_string_for_code (error_code);
+    if (error) {
+        /* TODO show sync error in UI -- but not duplicates */
+        g_warning ("Error %s", error);
+        g_free (error);
     }
-    return FALSE;
 }
 
 static void
-get_servers_cb (SyncevoService *service, 
-                GPtrArray *servers, 
-                GError *error, 
-                templates_data *templ_data)
+get_running_session_status_cb (SyncevoSession *session,
+                               SyncevoSessionStatus status,
+                               guint error_code,
+                               SyncevoSourceStatuses *source_statuses,
+                               GError *error,
+                               app_data *data)
 {
-    int i, k = 0;
-    app_data *data = templ_data->data;
-
     if (error) {
-        gtk_widget_hide (data->services_win);
-        show_error_dialog (GTK_WINDOW (data->sync_win), 
-                           _("Failed to get list of manually setup services from SyncEvolution"));
-        g_warning ("Failed to get list of manually setup services from SyncEvolution: %s", 
-                   error->message);
+        g_warning ("Error in Session.GetStatus: %s", error->message);
         g_error_free (error);
+        /* non-fatal, unknown error */
         return;
     }
 
-    gtk_table_resize (GTK_TABLE (data->manual_services_table), 2, 4);
-    for (i = 0; i < servers->len; i++) {
-        SyncevoServer *server = (SyncevoServer*)g_ptr_array_index (servers, i);
-        
-        /* make sure server is not added as template already */
-        if (!server_array_contains (templ_data->templates, server)) {
-            add_server_to_table (GTK_TABLE (data->manual_services_table), k++,
-                                 server, data);
-        }
+    set_running_session_status (data, status);
+}
+
+static void
+running_session_progress_changed_cb (SyncevoSession *session,
+                                     int progress,
+                                     SyncevoSourceProgresses *source_progresses,
+                                     app_data *data)
+{
+    SyncevoSourceProgress *s_progress;
+    char *name;
+    char *msg = NULL;
+
+    s_progress = syncevo_source_progresses_get_current (source_progresses);
+    if (!s_progress) {
+        return;
     }
-    
-    if (k > 0) {
-        gtk_widget_show_all (data->manual_services_scrolled);
-    } else {
-        gtk_widget_hide (data->manual_services_scrolled);
+
+    name = get_pretty_source_name (s_progress->name);
+
+    switch (s_progress->phase) {
+    case SYNCEVO_PHASE_PREPARING:
+        msg = g_strdup_printf (_("Preparing '%s'"), name);
+        break;
+    case SYNCEVO_PHASE_RECEIVING:
+        msg = g_strdup_printf (_("Receiving '%s'"), name);
+        break;
+    case SYNCEVO_PHASE_SENDING:
+        msg = g_strdup_printf (_("Sending '%s'"), name);
+        break;
+    default:
+        ;
     }
+    g_free (name);
 
-    /* the SyncevoServers in arrays are freed when the table gets freed */
-    g_ptr_array_free (templ_data->templates, TRUE);
-    g_ptr_array_free (servers, TRUE);
-    g_slice_free (templates_data, templ_data);
+    if (msg) {
+        set_sync_progress (data, ((float)progress) / 100, msg);
+        g_free (msg);
+    }
+
+    syncevo_source_progress_free (s_progress);
 }
 
+typedef struct source_stats {
+    long local_changes;
+    long remote_changes;
+    long local_rejections;
+    long remote_rejections;
+} source_stats;
+
 static void
-get_templates_cb (SyncevoService *service, 
-                  GPtrArray *templates, 
-                  GError *error, 
-                  app_data *data)
+free_source_stats (source_stats *stats)
 {
-    int i;
-    templates_data *temps_data;
+    g_slice_free (source_stats, stats);
+}
 
+static void
+get_reports_cb (SyncevoServer *server,
+                SyncevoReports *reports,
+                GError *error,
+                app_data *data)
+{
     if (error) {
-        show_error_dialog (GTK_WINDOW (data->sync_win), 
-                           _("Failed to get list of supported services from SyncEvolution"));
-        g_warning ("Failed to get list of supported services from SyncEvolution: %s", 
-                   error->message);
+        g_warning ("Error in Session.GetReports: %s", error->message);
         g_error_free (error);
-        gtk_widget_hide (data->services_win);
+        /* non-fatal, unknown error */
         return;
     }
 
-    gtk_table_resize (GTK_TABLE (data->services_table), 
-                      templates->len, 4);
+    if (syncevo_reports_get_length (reports) > 0) {
+        GHashTableIter iter;
+        GHashTable *sources; /* key is source name, value is a source_stats */
+        const char *key, *val;
+        GHashTable *report = syncevo_reports_index (reports, 0);
+        source_stats *stats;
+
+        sources = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                         g_free, (GDestroyNotify)free_source_stats);
+
+        g_hash_table_iter_init (&iter, report);
+        while (g_hash_table_iter_next (&iter, (gpointer)&key, (gpointer)&val)) {
+            char **strs;
+
+            strs = g_strsplit (key, "-", 6);
+            if (g_strv_length (strs) != 6) {
+                g_warning ("'%s' not parsable as a sync report item", key);
+                g_strfreev (strs);
+                continue;
+            }
 
-    for (i = 0; i < templates->len; i++) {
-        SyncevoServer *server;
-        gboolean consumer_ready;
+            stats = g_hash_table_lookup (sources, strs[1]);
+            if (!stats) {
+                stats = g_slice_new0 (source_stats);
+                g_hash_table_insert (sources, g_strdup (strs[1]), stats);
+            }
 
-        server = (SyncevoServer*)g_ptr_array_index (templates, i);
-        syncevo_server_get (server, NULL, NULL, NULL, &consumer_ready);
-        if (consumer_ready) {
-            add_server_to_table (GTK_TABLE (data->services_table), i, 
-                                 server,
-                                 data);
+            if (strcmp (strs[3], "remote") == 0) {
+                if (strcmp (strs[4], "added") == 0 ||
+                    strcmp (strs[4], "updated") == 0 ||
+                    strcmp (strs[4], "removed") == 0) {
+                    stats->remote_changes += strtol (val, NULL, 10);
+                } else if (strcmp (strs[5], "reject") == 0) {
+                    stats->remote_rejections += strtol (val, NULL, 10);
+                }
+
+            }
+            if (strcmp (strs[3], "local") == 0) {
+                if (strcmp (strs[4], "added") == 0 ||
+                    strcmp (strs[4], "updated") == 0 ||
+                    strcmp (strs[4], "removed") == 0) {
+                    stats->local_changes += strtol (val, NULL, 10);
+                } else if (strcmp (strs[5], "reject") == 0) {
+                    stats->local_rejections += strtol (val, NULL, 10);
+                }
+            }
+            g_strfreev (strs);
+            
+        }
+
+        /* sources now has all statistics we want */
+        g_hash_table_iter_init (&iter, sources);
+        while (g_hash_table_iter_next (&iter, (gpointer)&key, (gpointer)&stats)) {
+            source_config *source_conf;
+
+            /* store the statistics in source config */
+            source_conf = g_hash_table_lookup (data->current_service->source_configs,
+                                               key);
+            if (source_conf) {
+                source_conf->local_changes = stats->local_changes;
+                source_conf->remote_changes = stats->remote_changes;
+                source_conf->local_rejections = stats->local_rejections;
+                source_conf->remote_rejections = stats->remote_rejections;
+            }
+
+            /* if ui has been constructed already, update it */
+            source_config_update_label (source_conf);
         }
+
+        g_hash_table_destroy (sources);
     }
-    gtk_widget_show_all (data->services_table);
+}
 
-    temps_data = g_slice_new0 (templates_data);
-    temps_data->data = data;
-    temps_data->templates = templates;
-    syncevo_service_get_servers_async (data->service,
-                                       (SyncevoGetServerConfigCb)get_servers_cb,
-                                       temps_data);
+static void
+set_config_cb (SyncevoSession *session,
+               GError *error,
+               app_data *data)
+{
+    if (error) {
+        g_warning ("Error in Session.SetConfig: %s", error->message);
+        g_error_free (error);
+        /* TODO show in UI: save failed */
+    }
+    g_object_unref (session);
 }
 
+static void
+save_config (app_data *data, SyncevoSession *session)
+{
+    syncevo_session_set_config (session,
+                                TRUE,
+                                FALSE,
+                                data->current_service->config,
+                                (SyncevoSessionGenericCb)set_config_cb,
+                                data);
+}
 
-static void show_services_window (app_data *data)
+static void
+sync (app_data *data, SyncevoSession *session)
 {
-    gtk_container_foreach (GTK_CONTAINER (data->services_table),
-                           (GtkCallback)remove_child,
-                           data->services_table);
-    gtk_container_foreach (GTK_CONTAINER (data->manual_services_table),
-                           (GtkCallback)remove_child,
-                           data->manual_services_table);
+    GHashTable *source_modes;
+    GHashTableIter iter;
+    source_config *source;
+
+   /* override the sync mode in config with data->mode,
+     * then override all non-supported sources with "none".  */
+    source_modes = syncevo_source_modes_new ();
+
+    g_hash_table_iter_init (&iter, data->current_service->source_configs);
+    while (g_hash_table_iter_next (&iter, NULL, (gpointer)&source)) {
+        if (!source->supported_locally ||
+            !source_config_is_enabled (source)) {
+
+            syncevo_source_modes_add (source_modes,
+                                      source->name,
+                                      SYNCEVO_SYNC_NONE);
+        }
+    }
 
-    syncevo_service_get_templates_async (data->service,
-                                         (SyncevoGetTemplatesCb)get_templates_cb,
-                                         data);
-    gtk_window_present (GTK_WINDOW (data->services_win));
+    syncevo_session_sync (session,
+                          data->mode,
+                          source_modes,
+                          (SyncevoSessionGenericCb)sync_cb,
+                          data);
+    syncevo_source_modes_free (source_modes);
 }
 
 static void
-gconf_change_cb (GConfClient *client, guint id, GConfEntry *entry, app_data *data)
+set_config_for_sync_cb (SyncevoSession *session,
+                        GError *error,
+                        app_data *data)
 {
-    char *server = NULL;
-    GError *error = NULL;
-
-    server = gconf_client_get_string (client, SYNC_UI_SERVER_KEY, &error);
     if (error) {
-        g_warning ("Could not read current server name from gconf: %s", error->message);
+        g_warning ("Error in Session.SetConfig: %s", error->message);
         g_error_free (error);
-        error = NULL;
+        /* TODO show in UI: sync failed (failed to even start) */
+        return;
     }
 
-    /*TODO: avoid the rest if server did not actually change */
+    sync (data, session);
+}
 
-    gtk_widget_hide (data->progress);
+static void
+run_operation (operation_data *op_data, SyncevoSession *session)
+{
+    /* when we first get idle, start the operation */
+    if (op_data->started) {
+        return;
+    }
+    op_data->started = TRUE;
+
+    /* time for business */
+    switch (op_data->operation) {
+    case OP_SYNC:
+        /* Make sure we don't get change diffs printed out, then sync */
+        syncevo_config_set_value (op_data->data->current_service->config,
+                                  NULL, "printChanges", "0");
+        syncevo_session_set_config (session,
+                                    TRUE,
+                                    TRUE,
+                                    op_data->data->current_service->config,
+                                    (SyncevoSessionGenericCb)set_config_for_sync_cb,
+                                    op_data->data);
 
-    server_config_free (data->current_service);
-    if (!server || strlen (server) == 0) {
-        data->current_service = NULL; 
-        set_app_state (data, SYNC_UI_STATE_NO_SERVER);
-    } else {
-        data->synced_this_session = FALSE;
-        data->current_service = g_slice_new0 (server_config);
-        data->current_service->name = server;
-        set_app_state (data, SYNC_UI_STATE_GETTING_SERVER);
-        syncevo_service_get_server_config_async (data->service, 
-                                                 server,
-                                                 (SyncevoGetServerConfigCb)get_server_config_cb,
-                                                 data);
+        break;
+    case OP_SAVE:
+        save_config (op_data->data, session);
+        break;
+    default:
+        g_warn_if_reached ();
     }
 }
-
+/* Our sync session status */
 static void
-init_configuration (app_data *data)
+status_changed_cb (SyncevoSession *session,
+                   SyncevoSessionStatus status,
+                   guint error_code,
+                   SyncevoSourceStatuses *source_statuses,
+                   operation_data *op_data)
 {
-    GConfClient* client;
+    GTimeVal val;
+
+    switch (status) {
+    case SYNCEVO_STATUS_IDLE:
+        run_operation (op_data, session);
+        break;
+    case SYNCEVO_STATUS_DONE:
+        g_get_current_time (&val);
+        op_data->data->last_sync = val.tv_sec;
+        refresh_last_synced_label (op_data->data);
+        
+        op_data->data->synced_this_session = TRUE;
 
-    client = gconf_client_get_default ();
-    gconf_client_add_dir (client, SYNC_UI_GCONF_DIR, GCONF_CLIENT_PRELOAD_RECURSIVE, NULL);
-    gconf_client_notify_add (client, SYNC_UI_GCONF_DIR, (GConfClientNotifyFunc)gconf_change_cb,
-                             data, NULL, NULL);
+        /* no need for sync session anymore */
+        g_object_unref (session);
 
-    /* fake gconf change to init values */
-    gconf_change_cb (client, 0, NULL, data);
+        /* refresh stats -- the service may no longer be the one syncing,
+         * and we might have only saved config but what the heck... */
+        syncevo_server_get_reports (op_data->data->server,
+                                    op_data->data->current_service->name,
+                                    0, 1,
+                                    (SyncevoServerGetReportsCb)get_reports_cb,
+                                    op_data->data);
+
+        g_slice_free (operation_data, op_data);
+    default:
+        ;
+    }
 }
 
+/* Our sync (or config-save) session status */
 static void
-calc_and_update_progress (app_data *data, char *msg)
+get_status_cb (SyncevoSession *session,
+               SyncevoSessionStatus status,
+               guint error_code,
+               SyncevoSourceStatuses *source_statuses,
+               GError *error,
+               operation_data *op_data)
 {
-    float progress;
-    GList *list;
-    int count = 0;
-    
-    progress = 0.0;
-    for (list = data->source_progresses; list; list = list->next) {
-        source_progress *p = (source_progress*)list->data;
-        if (p->prepare_total > 0)
-            progress += SYNC_PROGRESS_PREPARE * p->prepare_current / p->prepare_total;
-        if (p->send_total > 0)
-            progress += SYNC_PROGRESS_SEND * p->send_current / p->send_total;
-        if (p->receive_total > 0)
-            progress += SYNC_PROGRESS_RECEIVE * p->receive_current / p->receive_total;
-        count++;
+    if (error) {
+        g_warning ("Error in Session.GetStatus: %s", error->message);
+        g_error_free (error);
+        g_object_unref (session);
+
+        switch (op_data->operation) {
+        case OP_SYNC:
+            /* TODO show in UI: sync failed (failed to even start) */
+            break;
+        case OP_SAVE:
+            /* TODO show in UI: save failed */
+            break;
+        default:
+            g_warn_if_reached ();
+        }
+        g_slice_free (operation_data, op_data);
+        return;
+    }
+
+    if (status == SYNCEVO_STATUS_IDLE) {
+        run_operation (op_data, session);
     }
-    set_sync_progress (data, sync_progress_sync_start + (progress / count), msg);
 }
 
 static void
-refresh_statistics (app_data *data)
+start_session_cb (SyncevoServer *server,
+                  char *path,
+                  GError *error,
+                  operation_data *op_data)
 {
-    GList *list;
+    SyncevoSession *session;
+    app_data *data = op_data->data;
 
-    for (list = data->source_progresses; list; list = list->next) {
-        source_progress *p = (source_progress*)list->data;
-        GtkLabel *lbl;
-        
-        lbl = GTK_LABEL (g_hash_table_lookup (data->source_report_labels, p->name));
-        if (lbl) {
-            char *msg;
-            
-            msg = get_report_summary (p->added_local + p->modified_local + p->deleted_local,
-                                      p->added_remote + p->modified_remote + p->deleted_remote,
-                                      p->rejected_local,
-                                      p->rejected_remote);
-            gtk_label_set_text (lbl, msg);
-            g_free (msg);
+    if (error) {
+        g_warning ("Error in Server.StartSession: %s", error->message);
+        g_error_free (error);
+        g_free (path);
+
+        switch (op_data->operation) {
+        case OP_SYNC:
+            /* TODO show in UI: sync failed (failed to even start) */
+            break;
+        case OP_SAVE:
+            /* TODO show in UI: save failed */
+            break;
+        default:
+            g_warn_if_reached ();
+        }
+        g_slice_free (operation_data, op_data);
+        return;
     }
+
+    session = syncevo_session_new (path);
+
+    if (data->running_session &&
+        strcmp (path, syncevo_session_get_path (data->running_session)) != 0) {
+        /* This is a really unfortunate event:
+           Someone got a session and we did not have time to set UI insensitive... */
+        gtk_label_set_markup (GTK_LABEL (data->server_label), 
+                              _("Waiting for current operation to finish..."));
+        gtk_widget_show_all (data->sources_box);
     }
+
+    /* we want to know about status changes to our session */
+    g_signal_connect (session, "status-changed",
+                      G_CALLBACK (status_changed_cb), op_data);
+    syncevo_session_get_status (session,
+                                (SyncevoSessionGetStatusCb)get_status_cb,
+                                op_data);
+
+    g_free (path);
 }
 
-static source_progress*
-find_source_progress (GList *source_progresses, char *name)
+static void
+show_services_list (app_data *data)
 {
-    GList *list;
+#ifdef USE_MOBLIN_UX
+    mux_window_set_settings_visible (MUX_WINDOW (data->sync_win), TRUE);
+#else
+    gtk_window_present (GTK_WINDOW (data->services_win));
+    update_services_list (data);
+#endif
+}
 
-    /* TODO: it would make more sense if source_progresses was a GHashTable */
-    for (list = source_progresses; list; list = list->next) {
-        if (strcmp (((source_progress*)list->data)->name, name) == 0) {
-            return (source_progress*)list->data;
-        }
-    }
-    return NULL;
+static void
+show_main_view (app_data *data)
+{
+#ifdef USE_MOBLIN_UX
+    mux_window_set_settings_visible (MUX_WINDOW (data->sync_win), FALSE);
+#else
+    gtk_widget_hide (data->services_win);
+#endif
+    gtk_window_present (GTK_WINDOW (data->sync_win));
 }
 
 static char*
 get_error_string_for_code (int error_code)
 {
     switch (error_code) {
-    case -1:
-        /* TODO: this is a hack... SyncEnd should be a signal of it's own,
-           not just hacked on top of the syncevolution error codes */
-        return g_strdup(_("Service configuration not found"));
     case 0:
     case LOCERR_USERABORT:
     case LOCERR_USERSUSPEND:
@@ -2017,13 +1722,14 @@ get_error_string_for_code (int error_code)
     }
 }
 
-
 static void
-server_shutdown_cb (SyncevoService *service,
+server_shutdown_cb (SyncevoServer *server,
                     app_data *data)
 {
     if (data->syncing) {
-        add_error_info (data, _("Sync D-Bus service exited unexpectedly"), NULL);
+        /* TODO show in UI: server disappeared */
+
+        add_error_info (data, _("Syncevolution.Server D-Bus service exited unexpectedly"), NULL);
 
         gtk_label_set_text (GTK_LABEL (data->sync_status_label), 
                             _("Sync Failed"));
@@ -2032,226 +1738,151 @@ server_shutdown_cb (SyncevoService *service,
     }
 }
 
-static void
-sync_progress_cb (SyncevoService *service,
-                  char *server,
-                  char *source,
-                  int type,
-                  int extra1, int extra2, int extra3,
-                  app_data *data)
-{
-    static source_progress *source_prog = NULL;
-    char *msg = NULL;
-    char *error = NULL;
-    char *name = NULL;
-    GTimeVal val;
-
-    /* just in case UI was just started and there is another sync in progress */
-    set_app_state (data, SYNC_UI_STATE_SYNCING);
 
-    /* if this is a source event, find the right source_progress */
-    if (source) {
-        source_prog = find_source_progress (data->source_progresses, source);
+static void
+set_running_session (app_data *data, const char *path)
+{
+    if (data->running_session) {
+        g_object_unref (data->running_session);
     }
 
-    switch(type) {
-    case -1:
-        /* syncevolution finished sync */
-        error = get_error_string_for_code (extra1);
-        if (error)
-            add_error_info (data, error, NULL);
-
-        switch (extra1) {
-        case 0:
-            g_get_current_time (&val);
-            data->last_sync = val.tv_sec;
-            refresh_last_synced_label (data);
-            
-            data->synced_this_session = TRUE;
-            gtk_label_set_text (GTK_LABEL (data->sync_status_label), 
-                                _("Sync complete"));
-            break;
-        case LOCERR_USERABORT:
-        case LOCERR_USERSUSPEND:
-            gtk_label_set_text (GTK_LABEL (data->sync_status_label), 
-                                _("Sync canceled"));
-        default:
-            gtk_label_set_text (GTK_LABEL (data->sync_status_label), 
-                                _("Sync Failed"));
-        }
-        /* get sync report */
-        refresh_statistics (data);
-        set_sync_progress (data, 1.0 , "");
-        set_app_state (data, SYNC_UI_STATE_SERVER_OK);
-
-        break;
-    case PEV_SESSIONSTART:
-        /* double check we're in correct state*/
-        set_app_state (data, SYNC_UI_STATE_SYNCING);
-        set_sync_progress (data, sync_progress_session_start, NULL);
-        break;
-    case PEV_SESSIONEND:
-        /* NOTE extra1 can be error here */
-        set_sync_progress (data, sync_progress_sync_end, _("Ending sync"));
-        break;
-
-    case PEV_ALERTED:
-        source_prog = g_slice_new0 (source_progress);
-        source_prog->name = g_strdup (source);
-        data->source_progresses = g_list_append (data->source_progresses, source_prog);
-        break;
-
-    case PEV_SENDSTART:
-    case PEV_SENDEND:
-    case PEV_RECVSTART:
-    case PEV_RECVEND:
-        /* these would be useful but they have no source so I can't tell how far we are... */
-        break;
-    case PEV_PREPARING:
-        if (source_prog) {
-            source_prog->prepare_current = CLAMP (extra1, 0, extra2);
-            source_prog->prepare_total = extra2;
-        }
+    if (!path) {
+        data->running_session = NULL;
+        return;
+    }
 
-        name = get_pretty_source_name (source);
-        /* TRANSLATORS: placeholder is a source name (e.g. 'Calendar') in a progress text */
-        msg = g_strdup_printf (_("Preparing '%s'"), name);
-        calc_and_update_progress(data, msg);
-        break;
+    data->running_session = syncevo_session_new (path);
 
-    case PEV_ITEMSENT:
-        if (source_prog) {
-            source_prog->send_current = CLAMP (extra1, 0, extra2);
-            source_prog->send_total = extra2;
-        }
+    g_signal_connect (data->running_session, "progress-changed",
+                      G_CALLBACK (running_session_progress_changed_cb), data);
+    g_signal_connect (data->running_session, "status-changed",
+                      G_CALLBACK (running_session_status_changed_cb), data);
+    syncevo_session_get_status (data->running_session,
+                                (SyncevoSessionGetStatusCb)get_running_session_status_cb,
+                                data);
+}
 
-        name = get_pretty_source_name (source);
-        /* TRANSLATORS: placeholder is a source name in a progress text */
-        msg = g_strdup_printf (_("Sending '%s'"), name);
-        calc_and_update_progress (data, msg);
-        break;
+static void
+set_online_status (app_data *data, gboolean online)
+{
+   if (online != data->online) {
+        data->online = online;
 
-    case PEV_ITEMRECEIVED:
-        if (source_prog) {
-            source_prog->receive_current = CLAMP (extra1, 0, extra2);
-            source_prog->receive_total = extra2;
+        if (data->current_state == SYNC_UI_STATE_SERVER_OK) {
+            if (data->online) {
+                gtk_widget_hide (data->no_connection_box);
+            } else {
+                gtk_widget_show (data->no_connection_box);
+            }
         }
+        gtk_widget_set_sensitive (data->sync_btn, data->online);
+    }
+}
 
-        name = get_pretty_source_name (source);
-        /* TRANSLATORS: placeholder is a source name in a progress text */
-        msg = g_strdup_printf (_("Receiving '%s'"), name);
-        calc_and_update_progress (data, msg);
-        break;
-
-    case PEV_SYNCEND:
-        error = get_error_string_for_code (extra1);
-        if (error) {
-            name = get_pretty_source_name (source);
-            msg = g_strdup_printf ("%s: %s", name, error);
-            add_error_info (data, msg, NULL);
-        }
-        break;
-    case PEV_DSSTATS_L:
-        if (!source_prog)
-            return;
+static void
+get_presence_cb (SyncevoServer *server,
+                 char *status,
+                 char *transport,
+                 GError *error,
+                 app_data *data)
+{
+    if (error) {
+        g_warning ("Server.GetSessions failed: %s", error->message);
+        g_error_free (error);
+        /* non-fatal, ignore in UI */
+        return;
+    }
 
-        source_prog->added_local = extra1;
-        source_prog->modified_local = extra2;
-        source_prog->deleted_local = extra3;
-        break;
-    case PEV_DSSTATS_R:
-        if (!source_prog)
-            return;
+    if (data->current_service && status) {
+        set_online_status (data, strcmp (status, "") == 0);
+    }
+    g_free (status);
+    g_free (transport);
+}
 
-        source_prog->added_remote = extra1;
-        source_prog->modified_remote = extra2;
-        source_prog->deleted_remote = extra3;
-        break;
-    case PEV_DSSTATS_E:
-        if (!source_prog)
-            return;
+static void
+info_request_cb (SyncevoServer *syncevo,
+                 char *id,
+                 char *session_path,
+                 char *state,
+                 char *handler_path,
+                 char *type,
+                 app_data *data)
+{
+    /* Implementation waiting for moblin bug #6376*/
+    g_warning ("InfoRequest handler not implemented yet");
+}
 
-        source_prog->rejected_local = extra1;
-        source_prog->rejected_remote = extra2;
-        break;
-    case PEV_DSSTATS_D:
-        if (!source_prog)
-            return;
+static void
+server_presence_changed_cb (SyncevoServer *server,
+                            char *config_name,
+                            char *status,
+                            char *transport,
+                            app_data *data)
+{
+    if (data->current_service &&
+        config_name && status &&
+        strcmp (data->current_service->name, config_name) == 0) {
 
-        source_prog->bytes_uploaded = extra1;
-        source_prog->bytes_downloaded = extra2;
-        break;
-    default:
-        ;
+        set_online_status (data, strcmp (status, "") == 0);
     }
-    g_free (msg);
-    g_free (error);
-    g_free (name);
 }
 
+static void
+server_session_changed_cb (SyncevoServer *server,
+                           char *path,
+                           gboolean started,
+                           app_data *data)
+{
+    if (started) {
+        set_running_session (data, path);
+    } else if (data->running_session &&
+               strcmp (syncevo_session_get_path (data->running_session), path) == 0 ) {
+        set_running_session (data, NULL);
+    }
+}
 
 static void
-connman_props_changed (DBusGProxy *proxy, const char *key, GValue *v, app_data *data)
+get_sessions_cb (SyncevoServer *server,
+                 SyncevoSessions *sessions,
+                 GError *error,
+                 app_data *data)
 {
-    const char *state;
-    gboolean online;
+    const char *path;
 
-    if (strcmp (key, "State") != 0)
+    if (error) {
+        g_warning ("Server.GetSessions failed: %s", error->message);
+        g_error_free (error);
+        /* TODO show in UI: failed first syncevo call (unexpected, fatal?) */
         return;
-    state = g_value_get_string (v);
-    online = (strcmp (state, "online") == 0);
-    if (online != data->online) {
-        data->online = online;
-        set_app_state (data, SYNC_UI_STATE_CURRENT_STATE);
     }
+
+    /* assume first one is active */
+    path = syncevo_sessions_index (sessions, 0);
+    set_running_session (data, path);
+
+    syncevo_sessions_free (sessions);
 }
 
 static void
-init_connman (app_data *data)
+get_config_for_default_peer_cb (SyncevoServer *syncevo,
+                                SyncevoConfig *config,
+                                GError *error,
+                                app_data *data)
 {
-    DBusGConnection *connection;
-    GHashTable *props;
-    GError *error = NULL;
+    char *name;
 
-    connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
-    if (connection == NULL) {
-        g_warning ("Failed to open connection to bus: %s\n",
-                   error->message);
+    if (error) {
+        g_warning ("Server.GetConfig failed: %s", error->message);
         g_error_free (error);
-        proxy = NULL;
+        /* TODO show in UI: failed first syncevo call (unexpected, fatal?) */
         return;
     }
 
-    proxy = dbus_g_proxy_new_for_name (connection,
-                                       "org.moblin.connman",
-                                       "/",
-                                       "org.moblin.connman.Manager");
-    if (proxy == NULL) {
-        g_printerr ("Failed to get a proxy for Connman");
-        return;
-    }  
-
-    dbus_g_object_register_marshaller (sync_ui_marshal_VOID__STRING_BOXED,
-                                       G_TYPE_NONE,
-                                       G_TYPE_STRING, G_TYPE_BOXED, G_TYPE_INVALID);
-    dbus_g_proxy_add_signal (proxy, "PropertyChanged",
-                             G_TYPE_STRING, G_TYPE_VALUE, NULL);
-    dbus_g_proxy_connect_signal (proxy, "PropertyChanged",
-                                 G_CALLBACK (connman_props_changed), data, NULL);
-
-    /* get initial State value*/
-    if (dbus_g_proxy_call (proxy, "GetProperties", NULL,
-                            G_TYPE_INVALID,
-                            STRING_VARIANT_HASHTABLE, &props, G_TYPE_INVALID)) {
-        GValue *value;
-
-        value = g_hash_table_lookup (props, "State");
-        if (value) {
-            connman_props_changed (proxy, "State", value, data);
-        }
-        g_hash_table_unref (props);
-    }
+    syncevo_config_get_value (config, NULL, "defaultPeer", &name);
+    reload_config (data, name);
+
+    syncevo_config_free (config);
 }
 
 GtkWidget*
@@ -2260,20 +1891,31 @@ sync_ui_create_main_window ()
     app_data *data;
 
     data = g_slice_new0 (app_data);
-    data->source_report_labels = g_hash_table_new (g_str_hash, g_str_equal);
     data->online = TRUE;
+    data->current_state = SYNC_UI_STATE_GETTING_SERVER;
     if (!init_ui (data)) {
         return NULL;
     }
 
-    init_connman (data);
-
-    data->service = syncevo_service_get_default();
-    g_signal_connect (data->service, "progress", 
-                      G_CALLBACK (sync_progress_cb), data);
-    g_signal_connect (data->service, "server-shutdown", 
+    data->server = syncevo_server_get_default();
+    g_signal_connect (data->server, "shutdown", 
                       G_CALLBACK (server_shutdown_cb), data);
-    init_configuration (data);
+    g_signal_connect (data->server, "session-changed",
+                      G_CALLBACK (server_session_changed_cb), data);
+    g_signal_connect (data->server, "presence_changed",
+                      G_CALLBACK (server_presence_changed_cb), data);
+    g_signal_connect (data->server, "info-request",
+                      G_CALLBACK (info_request_cb), data);
+
+    syncevo_server_get_config (data->server,
+                               "",
+                               FALSE,
+                               (SyncevoServerGetConfigCb)get_config_for_default_peer_cb,
+                               data);
+
+    syncevo_server_get_sessions (data->server,
+                                 (SyncevoServerGetSessionsCb)get_sessions_cb,
+                                 data);
 
     gtk_window_present (GTK_WINDOW (data->sync_win));
 
index 6f34f92..d4d34f6 100644 (file)
 #define SYNC_UI_H
 
 #include <gtk/gtk.h>
+#include "config.h"
+#include "sync-ui-config.h"
+#include "sync-ui.h"
+
+#define SYNC_UI_LIST_ICON_SIZE 32
+#define SYNC_UI_LIST_BTN_WIDTH 150
+
+
+char* get_pretty_source_name (const char *source_name);
+void show_error_dialog (GtkWidget *widget, const char* message);
+
 
 GtkWidget* sync_ui_create_main_window ();
 
index 40fe3e3..326eb87 100644 (file)
@@ -737,7 +737,7 @@ service</property>
   </widget>
   <widget class="GtkWindow" id="services_win">
     <property name="border_width">5</property>
-    <property name="title" translatable="yes">Sync</property>
+    <property name="title" translatable="yes">Sync settings</property>
     <property name="modal">True</property>
     <property name="default_width">800</property>
     <property name="default_height">550</property>
@@ -797,8 +797,7 @@ We support the following services: </property>
                           </packing>
                         </child>
                         <child>
-                          <widget class="GtkScrolledWindow" id="scrolledwindow1">
-                            <property name="height_request">165</property>
+                          <widget class="GtkScrolledWindow" id="scrolledwindow">
                             <property name="visible">True</property>
                             <property name="can_focus">True</property>
                             <property name="hscrollbar_policy">never</property>
@@ -808,57 +807,11 @@ We support the following services: </property>
                                 <property name="visible">True</property>
                                 <property name="resize_mode">queue</property>
                                 <child>
-                                  <widget class="GtkVBox" id="vbox1">
+                                  <widget class="GtkVBox" id="services_box">
                                     <property name="visible">True</property>
                                     <property name="orientation">vertical</property>
                                     <child>
-                                      <widget class="GtkTable" id="services_table">
-                                        <property name="visible">True</property>
-                                        <property name="n_rows">4</property>
-                                        <property name="n_columns">3</property>
-                                        <property name="row_spacing">2</property>
-                                        <child>
-                                          <placeholder/>
-                                        </child>
-                                        <child>
-                                          <placeholder/>
-                                        </child>
-                                        <child>
-                                          <placeholder/>
-                                        </child>
-                                        <child>
-                                          <placeholder/>
-                                        </child>
-                                        <child>
-                                          <placeholder/>
-                                        </child>
-                                        <child>
-                                          <placeholder/>
-                                        </child>
-                                        <child>
-                                          <placeholder/>
-                                        </child>
-                                        <child>
-                                          <placeholder/>
-                                        </child>
-                                        <child>
-                                          <placeholder/>
-                                        </child>
-                                        <child>
-                                          <placeholder/>
-                                        </child>
-                                        <child>
-                                          <placeholder/>
-                                        </child>
-                                        <child>
-                                          <placeholder/>
-                                        </child>
-                                      </widget>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="padding">4</property>
-                                        <property name="position">0</property>
-                                      </packing>
+                                      <placeholder/>
                                     </child>
                                     <child>
                                       <placeholder/>
@@ -869,14 +822,12 @@ We support the following services: </property>
                             </child>
                           </widget>
                           <packing>
-                            <property name="expand">False</property>
                             <property name="position">2</property>
                           </packing>
                         </child>
                       </widget>
                       <packing>
-                        <property name="expand">False</property>
-                        <property name="padding">10</property>
+                        <property name="padding">8</property>
                         <property name="position">0</property>
                       </packing>
                     </child>
@@ -931,83 +882,10 @@ you can setup a service manually.</property>
                             <property name="position">1</property>
                           </packing>
                         </child>
-                        <child>
-                          <widget class="GtkScrolledWindow" id="manual_services_scrolled">
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="hscrollbar_policy">never</property>
-                            <property name="vscrollbar_policy">automatic</property>
-                            <child>
-                              <widget class="GtkViewport" id="viewport2">
-                                <property name="visible">True</property>
-                                <property name="resize_mode">queue</property>
-                                <child>
-                                  <widget class="GtkVBox" id="vbox11">
-                                    <property name="visible">True</property>
-                                    <property name="orientation">vertical</property>
-                                    <child>
-                                      <widget class="GtkTable" id="manual_services_table">
-                                        <property name="visible">True</property>
-                                        <property name="n_rows">4</property>
-                                        <property name="n_columns">3</property>
-                                        <property name="row_spacing">2</property>
-                                        <child>
-                                          <placeholder/>
-                                        </child>
-                                        <child>
-                                          <placeholder/>
-                                        </child>
-                                        <child>
-                                          <placeholder/>
-                                        </child>
-                                        <child>
-                                          <placeholder/>
-                                        </child>
-                                        <child>
-                                          <placeholder/>
-                                        </child>
-                                        <child>
-                                          <placeholder/>
-                                        </child>
-                                        <child>
-                                          <placeholder/>
-                                        </child>
-                                        <child>
-                                          <placeholder/>
-                                        </child>
-                                        <child>
-                                          <placeholder/>
-                                        </child>
-                                        <child>
-                                          <placeholder/>
-                                        </child>
-                                        <child>
-                                          <placeholder/>
-                                        </child>
-                                        <child>
-                                          <placeholder/>
-                                        </child>
-                                      </widget>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="padding">4</property>
-                                        <property name="position">0</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <placeholder/>
-                                    </child>
-                                  </widget>
-                                </child>
-                              </widget>
-                            </child>
-                          </widget>
-                          <packing>
-                            <property name="position">2</property>
-                          </packing>
-                        </child>
                       </widget>
                       <packing>
+                        <property name="expand">False</property>
+                        <property name="padding">8</property>
                         <property name="position">1</property>
                       </packing>
                     </child>
@@ -1029,7 +907,7 @@ you can setup a service manually.</property>
                       </widget>
                       <packing>
                         <property name="expand">False</property>
-                        <property name="padding">10</property>
+                        <property name="padding">16</property>
                         <property name="pack_type">end</property>
                         <property name="position">2</property>
                       </packing>
@@ -1059,364 +937,4 @@ you can setup a service manually.</property>
       </widget>
     </child>
   </widget>
-  <widget class="GtkWindow" id="service_settings_win">
-    <property name="border_width">5</property>
-    <property name="title" translatable="yes">Sync</property>
-    <property name="modal">True</property>
-    <property name="default_width">800</property>
-    <property name="default_height">550</property>
-    <child>
-      <widget class="GtkVBox" id="vbox21">
-        <property name="visible">True</property>
-        <property name="orientation">vertical</property>
-        <child>
-          <widget class="GtkFrame" id="service_settings_frame">
-            <property name="visible">True</property>
-            <property name="label_xalign">0</property>
-            <property name="shadow_type">none</property>
-            <child>
-              <widget class="GtkAlignment" id="alignment4">
-                <property name="visible">True</property>
-                <property name="left_padding">45</property>
-                <property name="right_padding">45</property>
-                <child>
-                  <widget class="GtkVBox" id="vbox14">
-                    <property name="visible">True</property>
-                    <property name="orientation">vertical</property>
-                    <child>
-                      <placeholder/>
-                    </child>
-                    <child>
-                      <widget class="GtkHBox" id="hbox19">
-                        <property name="visible">True</property>
-                        <child>
-                          <widget class="GtkVBox" id="service_description_vbox">
-                            <property name="visible">True</property>
-                            <property name="orientation">vertical</property>
-                            <child>
-                              <widget class="GtkLabel" id="service_description_label">
-                                <property name="width_request">700</property>
-                                <property name="visible">True</property>
-                                <property name="xalign">0</property>
-                                <property name="wrap">True</property>
-                              </widget>
-                              <packing>
-                                <property name="padding">5</property>
-                                <property name="position">0</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <widget class="GtkHBox" id="service_link_hbox">
-                                <property name="visible">True</property>
-                                <child>
-                                  <widget class="GtkLinkButton" id="service_link">
-                                    <property name="label" translatable="yes">Launch website</property>
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">True</property>
-                                    <property name="receives_default">True</property>
-                                    <property name="relief">none</property>
-                                  </widget>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">False</property>
-                                    <property name="position">0</property>
-                                  </packing>
-                                </child>
-                              </widget>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">False</property>
-                                <property name="position">1</property>
-                              </packing>
-                            </child>
-                          </widget>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                      </widget>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="padding">5</property>
-                        <property name="position">1</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <widget class="GtkHBox" id="basic_settings_box">
-                        <property name="visible">True</property>
-                        <property name="spacing">10</property>
-                        <child>
-                          <widget class="GtkTable" id="table1">
-                            <property name="visible">True</property>
-                            <property name="n_rows">3</property>
-                            <property name="n_columns">2</property>
-                            <property name="column_spacing">5</property>
-                            <property name="row_spacing">4</property>
-                            <child>
-                              <widget class="GtkEntry" id="service_name_entry">
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="max_length">99</property>
-                                <property name="width_chars">40</property>
-                              </widget>
-                              <packing>
-                                <property name="left_attach">1</property>
-                                <property name="right_attach">2</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <widget class="GtkLabel" id="service_name_label">
-                                <property name="visible">True</property>
-                                <property name="xalign">1</property>
-                                <property name="label" translatable="yes">Service name</property>
-                              </widget>
-                              <packing>
-                                <property name="x_options">GTK_SHRINK | GTK_FILL</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <widget class="GtkEntry" id="username_entry">
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="max_length">99</property>
-                                <property name="width_chars">40</property>
-                              </widget>
-                              <packing>
-                                <property name="left_attach">1</property>
-                                <property name="right_attach">2</property>
-                                <property name="top_attach">1</property>
-                                <property name="bottom_attach">2</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <widget class="GtkEntry" id="password_entry">
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="max_length">99</property>
-                                <property name="visibility">False</property>
-                                <property name="width_chars">40</property>
-                              </widget>
-                              <packing>
-                                <property name="left_attach">1</property>
-                                <property name="right_attach">2</property>
-                                <property name="top_attach">2</property>
-                                <property name="bottom_attach">3</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <widget class="GtkLabel" id="label9">
-                                <property name="visible">True</property>
-                                <property name="xalign">1</property>
-                                <property name="label" translatable="yes">Username</property>
-                              </widget>
-                              <packing>
-                                <property name="top_attach">1</property>
-                                <property name="bottom_attach">2</property>
-                                <property name="x_options">GTK_SHRINK | GTK_FILL</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <widget class="GtkLabel" id="label10">
-                                <property name="visible">True</property>
-                                <property name="xalign">1</property>
-                                <property name="label" translatable="yes">Password</property>
-                              </widget>
-                              <packing>
-                                <property name="top_attach">2</property>
-                                <property name="bottom_attach">3</property>
-                                <property name="x_options">GTK_SHRINK | GTK_FILL</property>
-                              </packing>
-                            </child>
-                          </widget>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="padding">5</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                      </widget>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
-                        <property name="padding">15</property>
-                        <property name="position">3</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <widget class="GtkExpander" id="server_settings_expander">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <child>
-                          <widget class="GtkVBox" id="vbox4">
-                            <property name="visible">True</property>
-                            <property name="orientation">vertical</property>
-                            <child>
-                              <widget class="GtkHBox" id="hbox5">
-                                <property name="visible">True</property>
-                                <child>
-                                  <widget class="GtkTable" id="server_settings_table">
-                                    <property name="visible">True</property>
-                                    <property name="n_rows">5</property>
-                                    <property name="n_columns">2</property>
-                                    <property name="column_spacing">5</property>
-                                    <property name="row_spacing">4</property>
-                                    <child>
-                                      <placeholder/>
-                                    </child>
-                                    <child>
-                                      <placeholder/>
-                                    </child>
-                                    <child>
-                                      <placeholder/>
-                                    </child>
-                                    <child>
-                                      <placeholder/>
-                                    </child>
-                                    <child>
-                                      <placeholder/>
-                                    </child>
-                                    <child>
-                                      <placeholder/>
-                                    </child>
-                                    <child>
-                                      <placeholder/>
-                                    </child>
-                                    <child>
-                                      <placeholder/>
-                                    </child>
-                                    <child>
-                                      <placeholder/>
-                                    </child>
-                                    <child>
-                                      <placeholder/>
-                                    </child>
-                                  </widget>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">False</property>
-                                    <property name="padding">5</property>
-                                    <property name="position">0</property>
-                                  </packing>
-                                </child>
-                              </widget>
-                              <packing>
-                                <property name="position">0</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <widget class="GtkHBox" id="hbox12">
-                                <property name="visible">True</property>
-                                <child>
-                                  <widget class="GtkButton" id="reset_server_btn">
-                                    <property name="label" translatable="yes">Reset original server settings</property>
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">True</property>
-                                    <property name="receives_default">True</property>
-                                  </widget>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="padding">10</property>
-                                    <property name="pack_type">end</property>
-                                    <property name="position">0</property>
-                                  </packing>
-                                </child>
-                              </widget>
-                              <packing>
-                                <property name="padding">10</property>
-                                <property name="position">1</property>
-                              </packing>
-                            </child>
-                          </widget>
-                        </child>
-                        <child>
-                          <widget class="GtkLabel" id="label4">
-                            <property name="visible">True</property>
-                            <property name="label" translatable="yes">Server settings</property>
-                          </widget>
-                          <packing>
-                            <property name="type">label_item</property>
-                          </packing>
-                        </child>
-                      </widget>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="position">4</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <widget class="GtkHBox" id="button_box">
-                        <property name="visible">True</property>
-                        <property name="spacing">10</property>
-                        <child>
-                          <widget class="GtkButton" id="delete_service_btn">
-                            <property name="label" translatable="yes">Delete this service</property>
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">True</property>
-                          </widget>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="pack_type">end</property>
-                            <property name="position">2</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <widget class="GtkButton" id="stop_using_service_btn">
-                            <property name="label" translatable="yes">Stop using this service</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">True</property>
-                          </widget>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="pack_type">end</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <widget class="GtkButton" id="service_save_btn">
-                            <property name="label" translatable="yes">Save and use this service</property>
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">True</property>
-                          </widget>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="pack_type">end</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                      </widget>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="padding">10</property>
-                        <property name="pack_type">end</property>
-                        <property name="position">2</property>
-                      </packing>
-                    </child>
-                  </widget>
-                </child>
-              </widget>
-            </child>
-            <child>
-              <widget class="GtkLabel" id="label14">
-                <property name="visible">True</property>
-                <property name="use_markup">True</property>
-              </widget>
-              <packing>
-                <property name="type">label_item</property>
-              </packing>
-            </child>
-          </widget>
-          <packing>
-            <property name="position">0</property>
-          </packing>
-        </child>
-      </widget>
-    </child>
-  </widget>
 </glade-interface>
similarity index 64%
rename from src/org.Moblin.SyncEvolution.service.in
rename to src/org.syncevolution.service.in
index d5ac7c4..db8a0b4 100644 (file)
@@ -1,3 +1,3 @@
 [D-BUS Service]
-Name=org.Moblin.SyncEvolution
+Name=org.syncevolution
 Exec=@libexecdir@/syncevo-dbus-server
index ab4755a..25ca366 100644 (file)
       $VCALENDAR_10TO20_PRIORITY_CONVERSION;
     ]]></macro>
 
-    <macro name="VCARD_INCOMING_NAMECHANGE_SCRIPT"><![CDATA[
-      STRING tmp;
-      tmp=NORMALIZED(FN);
-      if (tmp==EMPTY){
-        tmp=N_FIRST;
-        if (N_MIDDLE != EMPTY) {
-          if (tmp != EMPTY) {
-            tmp = tmp + " ";
-          }
-          tmp = tmp + N_MIDDLE;
-        }
-        if (N_LAST != EMPTY) {
-          if (tmp != EMPTY) {
-            tmp = tmp + " ";
-          }
-          tmp = tmp + N_LAST;
-        }
-        FN = tmp;
-      }
-    ]]></macro>
-
                <!-- define script macros for scripts that are used by both vCalendar 1.0 and iCalendar 2.0 -->
 
     <macro name="VCALENDAR_INCOMING_SCRIPT"><![CDATA[
       }
     ]]></macro>
 
+
     <macro name="VCALENDAR_OUTGOING_SCRIPT"><![CDATA[
       // set UTC time of generation for iCalendar 2.0 DTSTAMP
       DGENERATED = NOW();
       <field name="FN" type="string" compare="conflict" merge="fillempty"/>
       <field name="FILE-AS" type="string" compare="conflict" merge="fillempty"/>
 
-      <field name="GENDER" type="string" compare="conflict" merge="fillempty"/>
-
       <!-- categories and classification -->
       <field name="CATEGORIES" array="yes" type="string" compare="conflict"/>
 
       <field name="MSN_SLOT"          array="yes" type="string" compare="conflict"/>
       <field name="YAHOO_HANDLE"        array="yes" type="string" compare="conflict"/>
       <field name="YAHOO_SLOT"          array="yes" type="string" compare="conflict"/>
-      <field name="SKYPE_HANDLE"      array="yes" type="string" compare="conflict"/>
-      <field name="SKYPE_SLOT"        array="yes" type="string" compare="conflict"/>
-      <field name="SIP_HANDLE"        array="yes" type="string" compare="conflict"/>
-      <field name="SIP_SLOT"          array="yes" type="string" compare="conflict"/>
 
       <!-- home address -->
       <field name="ADR_STREET"        array="yes" type="multiline" compare="conflict"/>
           <value field="FILE-AS"/>
         </property>
 
-        <property name="X-GENDER">
-          <value field="GENDER"/>
-        </property>
-
         <!-- onlyformode="standard": not part of vCard 2.1, but some
              peers (like the Funambol server) accept it anyway in
              vCard 2.1 -->
           </parameter>
         </property>
 
-        <property name="X-SKYPE" suppressempty="yes"> 
-          <value field="SKYPE_HANDLE"/>
-          <parameter name="X-EVOLUTION-UI-SLOT" positional="no" show="yes">
-            <value field="SKYPE_SLOT"/>
-          </parameter>
-        </property>
-
-        <property name="X-SIP" suppressempty="yes">
-          <value field="SIP_HANDLE"/>
-          <parameter name="X-EVOLUTION-UI-SLOT" positional="no" show="yes">
-            <value field="SIP_SLOT"/>
-          </parameter>
-        </property>
-
         <property name="ADR" values="7">
           <value index="0" field="ADR_POBOX"/>
           <value index="1" field="ADR_ADDTL"/>
     <datatype name="vCard21" basetype="vcard">
       <version>2.1</version>
       <use mimeprofile="vCard"/>
-     <incomingscript><![CDATA[
-        $VCARD_INCOMING_NAMECHANGE_SCRIPT
-      ]]></incomingscript>
     </datatype>
 
     <!-- vCard 3.0 datatype, using vCard profile defined above -->
     <datatype name="vCard30" basetype="vcard">
       <version>3.0</version>
       <use mimeprofile="vCard"/>
-      <incomingscript><![CDATA[
-        $VCARD_INCOMING_NAMECHANGE_SCRIPT
-      ]]></incomingscript>
     </datatype>
 
 
       <incomingscript><![CDATA[
         $VCALENDAR_INCOMING_SCRIPT
       ]]></incomingscript>
-      
+
       <outgoingscript><![CDATA[
         $VCALENDAR_OUTGOING_SCRIPT
       ]]></outgoingscript>
         $VCALENDAR_INCOMING_SCRIPT
       ]]></incomingscript>
 
-
       <outgoingscript><![CDATA[
         $VCALENDAR_OUTGOING_SCRIPT
       ]]></outgoingscript>
     <datatypes/>
   </datatypes>
 
+  <clientorserver/>
 
   <client type="plugin">
-    <binfilespath>$(binfilepath)</binfilespath>
-    <defaultauth/>
-
-    <!-- SyncEvolution has traditionally not folded long lines in
-         vCard.  Testing showed that servers still have problems with
-         it, so avoid it by default -->
-    <donotfoldcontent>yes</donotfoldcontent>
-
-    <fakedeviceid/>
-
-    <datastore/>
-
-    <remoterule name="EVOLUTION">
-      <deviceid>none - this rule is activated via its name in MAKE/PARSETEXTWITHPROFILE() macro calls</deviceid>
-    </remoterule>
-
-    <remoterules/>
+      <remoterule name="ZYB">
+          <manufacturer>ZYB</manufacturer>
+          <model>ZYB</model>
+          <!-- information to disable anchors checking -->
+          <lenientmode>yes</lenientmode>
+      </remoterule>
   </client>
 
 </sysync_config>
index 13cdfb3..839d064 100644 (file)
 #include "config.h"
 #endif
 
+#include <syncevo/Logging.h>
+#include <syncevo/util.h>
+#include <syncevo/SyncContext.h>
+#include <syncevo/SoupTransportAgent.h>
+#include <syncevo/SyncSource.h>
+#include <syncevo/SyncML.h>
+#include <syncevo/FileConfigNode.h>
+
+#include <synthesis/san.h>
+
 #include <unistd.h>
 #include <stdlib.h>
 #include <signal.h>
 #include <stdio.h>
 #include <string.h>
 #include <limits.h>
+#include <sys/time.h>
+
+#include <list>
+#include <map>
+#include <memory>
+#include <iostream>
+#include <limits>
+#include <cmath>
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/noncopyable.hpp>
+
+#include <glib-object.h>
+
+class DBusMessage;
+static DBusMessage *SyncEvoHandleException(DBusMessage *msg);
+#define DBUS_CXX_EXCEPTION_HANDLER SyncEvoHandleException
+#include "gdbus-cxx-bridge.h"
+
+using namespace SyncEvo;
+
+static GMainLoop *loop = NULL;
+static bool shutdownRequested = false;
 
-#include <dbus/dbus-glib-bindings.h>
+/**
+ * Anything that can be owned by a client, like a connection
+ * or session.
+ */
+class Resource {
+public:
+    virtual ~Resource() {}
+};
+
+class Session;
+class Connection;
+class Client;
+class DBusTransportAgent;
+
+class DBusSyncException : public DBusCXXException, public Exception
+{
+ public:
+    DBusSyncException(const std::string &file,
+                  int line,
+                  const std::string &what) : Exception(file, line, what)
+    {}
+    /**
+     * get exception name, used to convert to dbus error name
+     * subclasses should override it
+     */
+    virtual std::string getName() const { return "org.syncevolution.Exception"; }
+
+    virtual const char* getMessage() const { return Exception::what(); }
+};
+
+/**
+ * exceptions classes deriving from DBusException
+ * org.syncevolution.NoSuchConfig 
+ */
+class NoSuchConfig: public DBusSyncException
+{
+ public:
+    NoSuchConfig(const std::string &file,
+                 int line,
+                 const std::string &error): DBusSyncException(file, line, error)
+    {}
+    virtual std::string getName() const { return "org.syncevolution.NoSuchConfig";}
+};
+
+/**
+ * org.syncevolution.NoSuchSource 
+ */
+class NoSuchSource : public DBusSyncException
+{
+ public:
+    NoSuchSource(const std::string &file,
+                 int line,
+                 const std::string &error): DBusSyncException(file, line, error)
+    {}
+    virtual std::string getName() const { return "org.syncevolution.NoSuchSource";}
+};
+
+/**
+ * org.syncevolution.InvalidCall 
+ */
+class InvalidCall : public DBusSyncException
+{
+ public:
+    InvalidCall(const std::string &file,
+                 int line,
+                 const std::string &error): DBusSyncException(file, line, error)
+    {}
+    virtual std::string getName() const { return "org.syncevolution.InvalidCall";}
+};
 
-#ifdef USE_GNOME_KEYRING
-// extern "C" is missing in 2.24.1, leading to
-// link errors. Specifying it here is a workaround.
-extern "C" {
-#include <gnome-keyring.h>
+/**
+ * org.syncevolution.SourceUnusable
+ * CheckSource will use this when the source cannot be used for whatever reason 
+ */
+class SourceUnusable : public DBusSyncException
+{
+ public:
+    SourceUnusable(const std::string &file,
+                   int line,
+                   const std::string &error): DBusSyncException(file, line, error)
+    {}
+    virtual std::string getName() const { return "org.syncevolution.SourceUnusable";}
+};
+
+/**
+ * implement syncevolution exception handler
+ * to cover its default implementation
+ */
+static DBusMessage* SyncEvoHandleException(DBusMessage *msg)
+{
+    /** give an opportunity to let syncevolution handle exception */
+    Exception::handle();
+    try {
+        throw;
+    } catch (const dbus_error &ex) {
+        return g_dbus_create_error(msg, ex.dbusName().c_str(), "%s", ex.what());
+    } catch (const DBusCXXException &ex) {
+        return g_dbus_create_error(msg, ex.getName().c_str(), "%s", ex.getMessage());
+    } catch (const std::runtime_error &ex) {
+        return g_dbus_create_error(msg, "org.syncevolution.Exception", "%s", ex.what());
+    } catch (...) {
+        return g_dbus_create_error(msg, "org.syncevolution.Exception", "unknown");
+    }
 }
-#endif
 
-#include "EvolutionSyncSource.h"
-#include "syncevo-dbus-server.h"
-#include "syncevo-marshal.h"
-
-static gboolean syncevo_start_sync (SyncevoDBusServer *obj, char *server, GPtrArray *sources, GError **error);
-static gboolean syncevo_abort_sync (SyncevoDBusServer *obj, char *server, GError **error);
-static gboolean syncevo_get_templates (SyncevoDBusServer *obj, GPtrArray **templates, GError **error);
-static gboolean syncevo_get_template_config (SyncevoDBusServer *obj, char *templ, GPtrArray **options, GError **error);
-static gboolean syncevo_get_servers (SyncevoDBusServer *obj, GPtrArray **servers, GError **error);
-static gboolean syncevo_get_server_config (SyncevoDBusServer *obj, char *server, GPtrArray **options, GError **error);
-static gboolean syncevo_set_server_config (SyncevoDBusServer *obj, char *server, GPtrArray *options, GError **error);
-static gboolean syncevo_remove_server_config (SyncevoDBusServer *obj, char *server, GError **error);
-static gboolean syncevo_get_sync_reports (SyncevoDBusServer *obj, char *server, int count, GPtrArray **reports, GError **error);
-#include "syncevo-dbus-glue.h"
-
-enum SyncevoDBusError{
-       SYNCEVO_DBUS_ERROR_GENERIC_ERROR,
-       SYNCEVO_DBUS_ERROR_NO_SUCH_SERVER,
-       SYNCEVO_DBUS_ERROR_MISSING_ARGS,
-       SYNCEVO_DBUS_ERROR_INVALID_CALL, /* abort called when not syncing, or sync called when already syncing */
+/**
+ * Implements the read-only methods in a Session and the Server.
+ * Only data is the server configuration name, everything else
+ * is created and destroyed inside the methods.
+ */
+class ReadOperations
+{
+public:
+    const std::string m_configName;
+
+    ReadOperations(const std::string &config_name);
+
+    /** the double dictionary used to represent configurations */
+    typedef std::map< std::string, StringMap > Config_t;
+
+    /** the array of reports filled by getReports() */
+    typedef std::vector< StringMap > Reports_t;
+
+    /** the array of databases used by getDatabases() */
+    typedef SyncSource::Database SourceDatabase;
+    typedef SyncSource::Databases SourceDatabases_t;
+
+    /** implementation of D-Bus GetConfigs() */
+    static void getConfigs(bool getTemplates, std::vector<std::string> &configNames);
+
+    /** implementation of D-Bus GetConfig() for m_configName as server configuration */
+    void getConfig(bool getTemplate,
+                   Config_t &config);
+
+    /** implementation of D-Bus GetReports() for m_configName as server configuration */
+    void getReports(uint32_t start, uint32_t count,
+                    Reports_t &reports);
+
+    /** Session.CheckSource() */
+    void checkSource(const string &sourceName);
+
+    /** Session.GetDatabases() */
+    void getDatabases(const string &sourceName, SourceDatabases_t &databases);
+
+private:
+    /** 
+     * This virtual function is used to let subclass set
+     * filters to config. Only used internally.
+     */
+    virtual void setFilters(SyncConfig &config) {}
+
+    /** utility method which constructs a SyncConfig which references a local configuration (never a template) */
+    boost::shared_ptr<SyncConfig> getLocalConfig(const std::string &configName);
+};
+
+/**
+ * dbus_traits for SourceDatabase. Put it here for 
+ * avoiding polluting gxx-dbus-bridge.h
+ */
+template<> struct dbus_traits<ReadOperations::SourceDatabase> :
+    public dbus_struct_traits<ReadOperations::SourceDatabase,
+                              dbus_member<ReadOperations::SourceDatabase, std::string, &ReadOperations::SourceDatabase::m_name,
+                              dbus_member<ReadOperations::SourceDatabase, std::string, &ReadOperations::SourceDatabase::m_uri,
+                              dbus_member_single<ReadOperations::SourceDatabase, bool, &ReadOperations::SourceDatabase::m_isDefault> > > >{}; 
+
+
+/**
+ * Implements the main org.syncevolution.Server interface.
+ *
+ * All objects created by it get a reference to the creating
+ * DBusServer instance so that they can call some of its
+ * methods. Because that instance holds references to all
+ * of these objects and deletes them before destructing itself,
+ * that reference is guaranteed to remain valid.
+ */
+class DBusServer : public DBusObjectHelper
+{
+    GMainLoop *m_loop;
+    uint32_t m_lastSession;
+    typedef std::list< std::pair< boost::shared_ptr<Watch>, boost::shared_ptr<Client> > > Clients_t;
+    Clients_t m_clients;
+
+    /**
+     * The session which currently holds the main lock on the server.
+     * To avoid issues with concurrent modification of data or configs,
+     * only one session may make such modifications at a time. A
+     * plain pointer which is reset by the session's deconstructor.
+     *
+     * A weak pointer alone did not work because it does not provide access
+     * to the underlying pointer after the last corresponding shared
+     * pointer is gone (which triggers the deconstructing of the session).
+     */
+    Session *m_activeSession;
+
+    /**
+     * The weak pointer that corresponds to m_activeSession.
+     */
+    boost::weak_ptr<Session> m_activeSessionRef;
+
+    /**
+     * The running sync session. Having a separate reference to it
+     * ensures that the object won't go away prematurely, even if all
+     * clients disconnect.
+     */
+    boost::shared_ptr<Session> m_syncSession;
+
+    typedef std::list< boost::weak_ptr<Session> > WorkQueue_t;
+    /**
+     * A queue of pending, idle Sessions. Sorted by priority, most
+     * important one first. Currently this is used to give client
+     * requests a boost over remote connections and (in the future)
+     * automatic syncs.
+     *
+     * Active sessions are removed from this list and then continue
+     * to exist as long as a client in m_clients references it or
+     * it is the currently running sync session (m_syncSession).
+     */
+    WorkQueue_t m_workQueue;
+
+    /**
+     * Watch callback for a specific client or connection.
+     */
+    void clientGone(Client *c);
+
+    /**
+     * Returns new unique session ID. Implemented with a running
+     * counter. Checks for overflow, but not currently for active
+     * sessions.
+     */
+    std::string getNextSession();
+
+    /** Server.Attach() */
+    void attachClient(const Caller_t &caller,
+                      const boost::shared_ptr<Watch> &watch);
+
+    /** Server.Detach() */
+    void detachClient(const Caller_t &caller);
+
+    /** Server.Connect() */
+    void connect(const Caller_t &caller,
+                 const boost::shared_ptr<Watch> &watch,
+                 const StringMap &peer,
+                 bool must_authenticate,
+                 const std::string &session,
+                 DBusObject_t &object);
+
+    /** Server.StartSession() */
+    void startSession(const Caller_t &caller,
+                      const boost::shared_ptr<Watch> &watch,
+                      const std::string &server,
+                      DBusObject_t &object);
+
+    /** Server.GetConfig() */
+    void getConfig(const std::string &config_name,
+                   bool getTemplate,
+                   ReadOperations::Config_t &config)
+    {
+        ReadOperations ops(config_name);
+        ops.getConfig(getTemplate , config);
+    }
+
+    /** Server.GetReports() */
+    void getReports(const std::string &config_name,
+                    uint32_t start, uint32_t count,
+                    ReadOperations::Reports_t &reports)
+    {
+        ReadOperations ops(config_name);
+        ops.getReports(start, count, reports);
+    }
+
+    /** Server.CheckSource() */
+    void checkSource(const std::string &configName,
+                     const std::string &sourceName)
+    {
+        ReadOperations ops(configName);
+        ops.checkSource(sourceName);
+    }
+
+    /** Server.GetDatabases() */
+    void getDatabases(const std::string &configName,
+                      const string &sourceName,
+                      ReadOperations::SourceDatabases_t &databases)
+    {
+        ReadOperations ops(configName);
+        ops.getDatabases(sourceName, databases);
+    }
+
+    /** Server.CheckPresence() */
+    void checkPresence(const std::string &server,
+                       std::string &status,
+                       std::vector<std::string> &transports);
+
+    /** Server.GetSessions() */
+    void getSessions(std::vector<std::string> &sessions);
+
+    /** Server.SessionChanged */
+    EmitSignal2<const DBusObject_t &,
+                bool> sessionChanged;
+
+    /** Server.PresenceChanged */
+    EmitSignal3<const std::string &,
+                const std::string &,
+                const std::string &> presence;
+
+public:
+    DBusServer(GMainLoop *loop, const DBusConnectionPtr &conn);
+    ~DBusServer();
+
+    /** access to the GMainLoop reference used by this DBusServer instance */
+    GMainLoop *getLoop() { return m_loop; }
+
+    /** process D-Bus calls until the server is ready to quit */
+    void run();
+
+    /**
+     * look up client by its ID
+     */
+    boost::shared_ptr<Client> findClient(const Caller_t &ID);
+
+    /**
+     * find client by its ID or create one anew
+     */
+    boost::shared_ptr<Client> addClient(const DBusConnectionPtr &conn,
+                                        const Caller_t &ID,
+                                        const boost::shared_ptr<Watch> &watch);
+
+    /** detach this resource from all clients which own it */
+    void detach(Resource *resource);
+
+    /**
+     * Enqueue a session. Might also make it ready immediately,
+     * if nothing else is first in the queue. To be called
+     * by the creator of the session, *after* the session is
+     * ready to run.
+     */
+    void enqueue(const boost::shared_ptr<Session> &session);
+
+    /**
+     * Remove all sessions with this device ID from the
+     * queue. If the active session also has this ID,
+     * the session will be aborted and/or deactivated.
+     */
+    int killSessions(const std::string &peerDeviceID);
+
+    /**
+     * Remove a session from the work queue. If it is running a sync,
+     * it will keep running and nothing will change. Otherwise, if it
+     * is "ready" (= holds a lock on its configuration), then release
+     * that lock.
+     */
+    void dequeue(Session *session);
+
+    /**
+     * Checks whether the server is ready to run another session
+     * and if so, activates the first one in the queue.
+     */
+    void checkQueue();
 };
 
-static GQuark syncevo_dbus_error_quark(void)
+
+/**
+ * Tracks a single client and all sessions and connections that it is
+ * connected to. Referencing them ensures that they stay around as
+ * long as needed.
+ */
+class Client
+{
+    typedef std::list< boost::shared_ptr<Resource> > Resources_t;
+    Resources_t m_resources;
+
+public:
+    const Caller_t m_ID;
+
+    Client(const Caller_t &ID) :
+        m_ID(ID)
+    {}
+
+    ~Client()
+    {
+        SE_LOG_DEBUG(NULL, NULL, "D-Bus client %s is destructing", m_ID.c_str());
+    }
+        
+
+    /**
+     * Attach a specific resource to this client. As long as the
+     * resource is attached, it cannot be freed. Can be called
+     * multiple times, which means that detach() also has to be called
+     * the same number of times to finally detach the resource.
+     */
+    void attach(boost::shared_ptr<Resource> resource)
+    {
+        m_resources.push_back(resource);
+    }
+
+    /**
+     * Detach once from the given resource. Has to be called as
+     * often as attach() to really remove all references to the
+     * session. It's an error to call detach() more often than
+     * attach().
+     */
+    void detach(Resource *resource)
+    {
+        for (Resources_t::iterator it = m_resources.begin();
+             it != m_resources.end();
+             ++it) {
+            if (it->get() == resource) {
+                // got it
+                m_resources.erase(it);
+                return;
+            }
+        }
+
+        SE_THROW_EXCEPTION(InvalidCall, "cannot detach from resource that client is not attached to");
+    }
+    void detach(boost::shared_ptr<Resource> resource)
+    {
+        detach(resource.get());
+    }
+
+    /**
+     * Remove all references to the given resource, regardless whether
+     * it was referenced not at all or multiple times.
+     */
+    void detachAll(Resource *resource) {
+        Resources_t::iterator it = m_resources.begin();
+        while (it != m_resources.end()) {
+            if (it->get() == resource) {
+                it = m_resources.erase(it);
+            } else {
+                ++it;
+            }
+        }
+    }
+    void detachAll(boost::shared_ptr<Resource> resource)
+    {
+        detachAll(resource.get());
+    }
+
+    /**
+     * return corresponding smart pointer for a certain resource,
+     * empty pointer if not found
+     */
+    boost::shared_ptr<Resource> findResource(Resource *resource)
+    {
+        for (Resources_t::iterator it = m_resources.begin();
+             it != m_resources.end();
+             ++it) {
+            if (it->get() == resource) {
+                // got it
+                return *it;
+            }
+        }
+        return boost::shared_ptr<Resource>();
+    }
+};
+
+struct SourceStatus
+{
+    SourceStatus() :
+        m_mode("none"),
+        m_status("idle"),
+        m_error(0)
+    {}
+    void set(const std::string &mode, const std::string &status, uint32_t error)
+    {
+        m_mode = mode;
+        m_status = status;
+        m_error = error;
+    }
+
+    std::string m_mode;
+    std::string m_status;
+    uint32_t m_error;
+};
+
+template<> struct dbus_traits<SourceStatus> :
+    public dbus_struct_traits<SourceStatus,
+                              dbus_member<SourceStatus, std::string, &SourceStatus::m_mode,
+                              dbus_member<SourceStatus, std::string, &SourceStatus::m_status,
+                              dbus_member_single<SourceStatus, uint32_t, &SourceStatus::m_error> > > >
+{};
+
+struct SourceProgress
 {
-       static GQuark quark = 0;
-       if (!quark)
-               quark = g_quark_from_static_string("syncevo-dbus-server");
-       return quark;
+    SourceProgress() :
+        m_phase(""),
+        m_prepareCount(-1), m_prepareTotal(-1),
+        m_sendCount(-1), m_sendTotal(-1),
+        m_receiveCount(-1), m_receiveTotal(-1)
+    {}
+
+    std::string m_phase;
+    int32_t m_prepareCount, m_prepareTotal;
+    int32_t m_sendCount, m_sendTotal;
+    int32_t m_receiveCount, m_receiveTotal;
+};
+
+template<> struct dbus_traits<SourceProgress> :
+    public dbus_struct_traits<SourceProgress,
+                              dbus_member<SourceProgress, std::string, &SourceProgress::m_phase,
+                              dbus_member<SourceProgress, int32_t, &SourceProgress::m_prepareCount,
+                              dbus_member<SourceProgress, int32_t, &SourceProgress::m_prepareTotal,
+                              dbus_member<SourceProgress, int32_t, &SourceProgress::m_sendCount,
+                              dbus_member<SourceProgress, int32_t, &SourceProgress::m_sendTotal,
+                              dbus_member<SourceProgress, int32_t, &SourceProgress::m_receiveCount,
+                              dbus_member_single<SourceProgress, int32_t, &SourceProgress::m_receiveTotal> > > > > > > >
+{};
+
+/**
+ * A running sync engine which keeps answering on D-Bus whenever
+ * possible and updates the Session while the sync runs.
+ */
+class DBusSync : public SyncContext
+{
+    Session &m_session;
+
+public:
+    DBusSync(const std::string &config,
+             Session &session);
+    ~DBusSync() {}
+
+protected:
+    virtual boost::shared_ptr<TransportAgent> createTransportAgent();
+    virtual void displaySyncProgress(sysync::TProgressEventEnum type,
+                                     int32_t extra1, int32_t extra2, int32_t extra3);
+    virtual void displaySourceProgress(sysync::TProgressEventEnum type,
+                                       SyncSource &source,
+                                       int32_t extra1, int32_t extra2, int32_t extra3);
+
+    /**
+     * Implement checkForSuspend and checkForAbort.
+     * They will check whether dbus clients suspend
+     * or abort the session in addition to checking
+     * whether suspend/abort were requested via
+     * signals, using SyncContext's signal handling.
+     */
+    virtual bool checkForSuspend(); 
+    virtual bool checkForAbort();
+    virtual int sleep(int intervals);
+};
+
+/**
+ * A timer helper to check whether now is timeout according to
+ * user's setting. Timeout is calculated in milliseconds
+ */ 
+class Timer {
+    timeval m_startTime;  ///< start time
+    unsigned long m_timeoutMs; ///< timeout in milliseconds, set by user
+
+    /**
+     * calculate duration between now and start time
+     * return value is in milliseconds
+     */
+    unsigned long duration(const timeval &minuend, const timeval &subtrahend)
+    {
+        unsigned long result = 0;
+        if(minuend.tv_sec > subtrahend.tv_sec || 
+                (minuend.tv_sec == subtrahend.tv_sec && minuend.tv_usec > subtrahend.tv_usec)) {
+            result = minuend.tv_sec - subtrahend.tv_sec;
+            result *= 1000;
+            result += (minuend.tv_usec - subtrahend.tv_usec) / 1000;
+        }
+        return result;
+    }
+
+ public:
+    /**
+     * constructor
+     * @param timeoutMs timeout in milliseconds
+     */
+    Timer(unsigned long timeoutMs) : m_timeoutMs(timeoutMs)
+    {
+        reset();
+    }
+
+    /**
+     * reset the timer and mark start time as current time
+     */
+    void reset() { gettimeofday(&m_startTime, NULL); }
+
+    /**
+     * check whether it is timeout
+     */
+    bool timeout() 
+    {
+        timeval now;
+        gettimeofday(&now, NULL);
+        return duration(now, m_startTime) >= m_timeoutMs;
+    }
+};
+
+/**
+ * Hold progress info and try to estimate current progress
+ */
+class ProgressData {
+public:
+    /**
+     * big steps, each step contains many operations, such as
+     * data prepare, message send/receive.
+     * The partitions of these steps are based on profiling data
+     * for many usage scenarios and different sync modes
+     */
+    enum ProgressStep {
+        /** an invalid step */
+        PRO_SYNC_INVALID = 0,
+        /** 
+         * sync prepare step: do some preparations and checkings, 
+         * such as source preparation, engine preparation
+         */
+        PRO_SYNC_PREPARE,
+        /** 
+         * session init step: transport connection set up, 
+         * start a session, authentication and dev info generation
+         * normally it needs one time syncML messages send-receive.
+         * Sometimes it may need messages send/receive many times to 
+         * handle authentication
+         */
+        PRO_SYNC_INIT,
+        /** 
+         * prepare sync data and send data, also receive data from server.
+         * Also may need send/receive messages more than one time if too 
+         * much data.
+         * assume 5 items to be sent by default
+         */
+        PRO_SYNC_DATA,
+        /** 
+         * item receive handling, send client's status to server and 
+         * close the session 
+         * assume 5 items to be received by default
+         */
+        PRO_SYNC_UNINIT,
+        /** number of sync steps */
+        PRO_SYNC_TOTAL
+    };
+    /**
+     * internal mode to represent whether it is possible that data is sent to 
+     * server or received from server. This could help remove some incorrect
+     * hypothesis. For example, if only to client, then it is no data item 
+     * sending to server. 
+     */
+    enum InternalMode {
+        INTERNAL_NONE = 0,
+        INTERNAL_ONLY_TO_CLIENT = 1,
+        INTERNAL_ONLY_TO_SERVER = 1 << 1,
+        INTERNAL_TWO_WAY = 1 + (1 << 1)
+    };
+
+    /**
+     * treat a one-time send-receive without data items
+     * as an internal standard unit.
+     * below are ratios of other operations compared to one 
+     * standard unit.
+     * These ratios might be dynamicall changed in the future.
+     */
+    /** PRO_SYNC_PREPARE step ratio to standard unit */
+    static const float PRO_SYNC_PREPARE_RATIO = 0.2;
+    /** data prepare for data items to standard unit. All are combined by profiling data */
+    static const float DATA_PREPARE_RATIO = 0.10;
+    /** one data item send's ratio to standard unit */
+    static const float ONEITEM_SEND_RATIO = 0.05;
+    /** one data item receive&parse's ratio to standard unit */
+    static const float ONEITEM_RECEIVE_RATIO = 0.05;
+    /** connection setup to standard unit */
+    static const float CONN_SETUP_RATIO = 0.5;
+    /** assume the number of data items */
+    static const int DEFAULT_ITEMS = 5;
+    /** default times of message send/receive in each step */
+    static const int MSG_SEND_RECEIVE_TIMES = 1;
+
+    ProgressData(int32_t &progress);
+
+    /**
+     * change the big step 
+     */
+    void setStep(ProgressStep step); 
+
+    /**
+     * calc progress when a message is sent
+     */
+    void sendStart();
+
+    /**
+     * calc progress when a message is received from server 
+     */
+    void receiveEnd();
+
+    /** 
+     * re-calc progress proportions according to syncmode hint
+     * typically, if only refresh-from-client, then
+     * client won't receive data items.
+     */
+    void addSyncMode(SyncMode mode);
+
+    /**
+     * calc progress when data prepare for sending 
+     */
+    void itemPrepare();
+
+    /**
+     * calc progress when a data item is received
+     */
+    void itemReceive(const string &source, int count, int total);
+
+private:
+
+    /** update progress data */
+    void updateProg(float ratio);
+
+    /** dynamically adapt the proportion of each step by their current units */
+    void recalc();
+
+    /** internally check sync mode */
+    void checkInternalMode();
+
+    /** get total units of current step and remaining steps */
+    float getRemainTotalUnits();
+
+    /** get default units of given step */
+    static float getDefaultUnits(ProgressStep step);
+
+private:
+    /** a reference of progress percentage */
+    int32_t &m_progress;
+    /** current big step */
+    ProgressStep m_step;
+    /** count of message send/receive in current step. Cleared in the start of a new step */
+    int m_sendCounts;
+    /** internal sync mode combinations */ 
+    int m_internalMode;
+    /** proportions when each step is end */
+    float m_syncProp[PRO_SYNC_TOTAL];
+    /** remaining units of each step according to current step */
+    float m_syncUnits[PRO_SYNC_TOTAL];
+    /** proportion of a standard unit, may changes dynamically */
+    float m_propOfUnit;
+    /** current sync source */
+    string m_source;
+};
+
+/**
+ * Represents and implements the Session interface.  Use
+ * boost::shared_ptr to track it and ensure that there are references
+ * to it as long as the connection is needed.
+ */
+class Session : public DBusObjectHelper,
+                public Resource,
+                private ReadOperations,
+                private boost::noncopyable
+{
+    DBusServer &m_server;
+    const std::string m_sessionID;
+    std::string m_peerDeviceID;
+
+    bool m_serverMode;
+    SharedBuffer m_initialMessage;
+    string m_initialMessageType;
+
+    boost::weak_ptr<Connection> m_connection;
+    std::string m_connectionError;
+    bool m_useConnection;
+
+    /** temporary config changes */
+    FilterConfigNode::ConfigFilter m_syncFilter;
+    FilterConfigNode::ConfigFilter m_sourceFilter;
+    typedef std::map<std::string, FilterConfigNode::ConfigFilter> SourceFilters_t;
+    SourceFilters_t m_sourceFilters;
+
+    /** whether dbus clients set temporary configs */
+    bool m_tempConfig;
+
+    /**
+     * True while clients are allowed to make calls other than Detach(),
+     * which is always allowed. Some calls are not allowed while this
+     * session runs a sync, which is indicated by a non-NULL m_sync
+     * pointer.
+     */
+    bool m_active;
+
+    /**
+     * The SyncEvolution instance which currently prepares or runs a sync.
+     */
+    boost::shared_ptr<DBusSync> m_sync;
+
+    /**
+     * the sync status for session
+     */
+    enum SyncStatus {
+        SYNC_QUEUEING,    ///< waiting to become ready for use
+        SYNC_IDLE,        ///< ready, session is initiated but sync not started
+        SYNC_RUNNING, ///< sync is running
+        SYNC_ABORT, ///< sync is aborting
+        SYNC_SUSPEND, ///< sync is suspending
+        SYNC_DONE, ///< sync is done
+        SYNC_ILLEGAL 
+    };
+
+    /** current sync status */
+    SyncStatus m_syncStatus;
+
+    /**
+     * Priority which determines position in queue.
+     * Lower is more important. PRI_DEFAULT is zero.
+     */
+    int m_priority;
+
+    int32_t m_progress;
+
+    /** progress data, holding progress calculation related info */
+    ProgressData m_progData;
+
+    typedef std::map<std::string, SourceStatus> SourceStatuses_t;
+    SourceStatuses_t m_sourceStatus;
+
+    uint32_t m_error;
+    typedef std::map<std::string, SourceProgress> SourceProgresses_t;
+    SourceProgresses_t m_sourceProgress;
+
+    /** timer for fire status/progress usages */
+    Timer m_statusTimer;
+    Timer m_progressTimer;
+
+    /** Session.Detach() */
+    void detach(const Caller_t &caller);
+
+    /** Session.SetConfig() */
+    void setConfig(bool update, bool temporary,
+                   const ReadOperations::Config_t &config);
+
+    /** Session.GetStatus() */
+    void getStatus(std::string &status,
+                   uint32_t &error,
+                   SourceStatuses_t &sources);
+    /** Session.GetProgress() */
+    void getProgress(int32_t &progress,
+                     SourceProgresses_t &sources);
+
+    /**
+     * Must be called each time that properties changing the
+     * overall status are changed. Ensures that the corresponding
+     * D-Bus signal is sent.
+     *
+     * Doesn't always send the signal immediately, because often it is
+     * likely that more status changes will follow shortly. To ensure
+     * that the "final" status is sent, call with flush=true.
+     *
+     * @param flush      force sending the current status
+     */
+    void fireStatus(bool flush = false);
+    /** like fireStatus() for progress information */
+    void fireProgress(bool flush = false);
+
+    /** Session.StatusChanged */
+    EmitSignal3<const std::string &,
+                uint32_t,
+                const SourceStatuses_t &> emitStatus;
+    /** Session.ProgressChanged */
+    EmitSignal2<int32_t,
+                const SourceProgresses_t &> emitProgress;
+
+    static string syncStatusToString(SyncStatus state);
+
+public:
+    Session(DBusServer &server,
+            const std::string &peerDeviceID,
+            const std::string &config_name,
+            const std::string &session);
+    ~Session();
+
+    enum {
+        PRI_DEFAULT = 0,
+        PRI_CONNECTION = 10
+    };
+
+    /**
+     * Default priority is 0. Higher means less important.
+     */
+    void setPriority(int priority) { m_priority = priority; }
+    int getPriority() const { return m_priority; }
+
+    void initServer(SharedBuffer data, const std::string &messageType);
+    void setConnection(const boost::shared_ptr<Connection> c) { m_connection = c; m_useConnection = c; }
+    boost::weak_ptr<Connection> getConnection() { return m_connection; }
+    bool useConnection() { return m_useConnection; }
+
+    /**
+     * After the connection closes, the Connection instance is
+     * destructed immediately. This is necessary so that the
+     * corresponding cleanup can remove all other classes
+     * only referenced by the Connection.
+     *
+     * This leads to the problem that an active sync cannot
+     * query the final error code of the connection. This
+     * is solved by setting a generic error code here when
+     * the sync starts and overwriting it when the connection
+     * closes.
+     */
+    void setConnectionError(const std::string error) { m_connectionError = error; }
+    std::string getConnectionError() { return m_connectionError; }
+
+
+    DBusServer &getServer() { return m_server; }
+    std::string getConfigName() { return m_configName; }
+    std::string getSessionID() const { return m_sessionID; }
+    std::string getPeerDeviceID() const { return m_peerDeviceID; }
+
+    /**
+     * TRUE if the session is ready to take over control
+     */
+    bool readyToRun() { return (m_syncStatus != SYNC_DONE) && m_sync; }
+
+    /**
+     * transfer control to the session for the duration of the sync,
+     * returns when the sync is done (successfully or unsuccessfully)
+     */
+    void run();
+
+    /**
+     * called when the session is ready to run (true) or
+     * lost the right to make changes (false)
+     */
+    void setActive(bool active);
+
+    void syncProgress(sysync::TProgressEventEnum type,
+                      int32_t extra1, int32_t extra2, int32_t extra3);
+    void sourceProgress(sysync::TProgressEventEnum type,
+                        SyncSource &source,
+                        int32_t extra1, int32_t extra2, int32_t extra3);
+
+    typedef StringMap SourceModes_t;
+    /** Session.Sync() */
+    void sync(const std::string &mode, const SourceModes_t &source_modes);
+    /** Session.Abort() */
+    void abort();
+    /** Session.Suspend() */
+    void suspend();
+
+    bool isSuspend() { return m_syncStatus == SYNC_SUSPEND; }
+    bool isAbort() { return m_syncStatus == SYNC_ABORT; }
+
+private:
+    /** set m_syncFilter and m_sourceFilters to config */
+    virtual void setFilters(SyncConfig &config);
+};
+
+
+/**
+ * Represents and implements the Connection interface.
+ *
+ * The connection interacts with a Session by creating the Session and
+ * exchanging data with it. For that, the connection registers itself
+ * with the Session and unregisters again when it goes away.
+ *
+ * In contrast to clients, the Session only keeps a weak_ptr, which
+ * becomes invalid when the referenced object gets deleted. Typically
+ * this means the Session has to abort, unless reconnecting is
+ * supported.
+ */
+class Connection : public DBusObjectHelper, public Resource
+{
+    DBusServer &m_server;
+    StringMap m_peer;
+    bool m_mustAuthenticate;
+    enum {
+        SETUP,          /**< ready for first message */
+        PROCESSING,     /**< received message, waiting for engine's reply */
+        WAITING,        /**< waiting for next follow-up message */
+        FINAL,          /**< engine has sent final reply, wait for ACK by peer */
+        DONE,           /**< peer has closed normally after the final reply */
+        FAILED          /**< in a failed state, no further operation possible */
+    } m_state;
+    std::string m_failure;
+
+    /** first parameter for Session::sync() */
+    std::string m_syncMode;
+    /** second parameter for Session::sync() */
+    Session::SourceModes_t m_sourceModes;
+
+    const std::string m_sessionID;
+    boost::shared_ptr<Session> m_session;
+
+    /**
+     * main loop that our DBusTransportAgent is currently waiting in,
+     * NULL if not waiting
+     */
+    GMainLoop *m_loop;
+
+    /**
+     * get our peer session out of the DBusTransportAgent,
+     * if it is currently waiting for us (indicated via m_loop)
+     */
+    void wakeupSession();
+
+    /**
+     * buffer for received data, waiting here for engine to ask
+     * for it via DBusTransportAgent::getReply().
+     */
+    SharedBuffer m_incomingMsg;
+    std::string m_incomingMsgType;
+
+    /**
+     * records the reason for the failure, sends Abort signal and puts
+     * the connection into the FAILED state.
+     */
+    void failed(const std::string &reason);
+
+    /**
+     * returns "<description> (<ID> via <transport> <transport_description>)"
+     */
+    static std::string buildDescription(const StringMap &peer);
+
+    /** Connection.Process() */
+    void process(const Caller_t &caller,
+                 const std::pair<size_t, const uint8_t *> &message,
+                 const std::string &message_type);
+    /** Connection.Close() */
+    void close(const Caller_t &caller,
+               bool normal,
+               const std::string &error);
+    /** wrapper around sendAbort */
+    void abort();
+    /** Connection.Abort */
+    EmitSignal0 sendAbort;
+    bool m_abortSent;
+    /** Connection.Reply */
+    EmitSignal5<const std::pair<size_t, const uint8_t *> &,
+                const std::string &,
+                const StringMap &,
+                bool,
+                const std::string &> reply;
+
+    friend class DBusTransportAgent;
+
+public:
+    const std::string m_description;
+
+    Connection(DBusServer &server,
+               const DBusConnectionPtr &conn,
+               const std::string &session_num,
+               const StringMap &peer,
+               bool must_authenticate);
+
+    ~Connection();
+
+    /** session requested by us is ready to run a sync */
+    void ready();
+
+    /** connection is no longer needed, ensure that it gets deleted */
+    void shutdown();
+
+    /** peer is not trusted, must authenticate as part of SyncML */
+    bool mustAuthenticate() const { return m_mustAuthenticate; }
+};
+
+/**
+ * A proxy for a Connection instance. The Connection instance can go
+ * away (weak pointer, must be locked and and checked each time it is
+ * needed). The agent must remain available as long as the engine
+ * needs and basically becomes unusuable once the connection dies.
+ *
+ * Reconnecting is not currently supported.
+ */ 
+class DBusTransportAgent : public TransportAgent
+{
+    GMainLoop *m_loop;
+    Session &m_session;
+    boost::weak_ptr<Connection> m_connection;
+
+    std::string m_url;
+    std::string m_type;
+    TransportCallback m_callback;
+    void *m_callbackData;
+    int m_callbackInterval;
+
+    SharedBuffer m_incomingMsg;
+    std::string m_incomingMsgType;
+
+    void doWait(boost::shared_ptr<Connection> &connection);
+
+ public:
+    DBusTransportAgent(GMainLoop *loop,
+                       Session &session,
+                       boost::weak_ptr<Connection> connection);
+    ~DBusTransportAgent();
+
+    virtual void setURL(const std::string &url) { m_url = url; }
+    virtual void setContentType(const std::string &type) { m_type = type; }
+    virtual void send(const char *data, size_t len);
+    virtual void cancel() {}
+    virtual void shutdown();
+    virtual Status wait(bool noReply = false);
+    virtual void setCallback (TransportCallback cb, void * udata, int interval)
+    {
+        m_callback = cb;
+        m_callbackData = udata;
+        m_callbackInterval = interval;
+    }
+    virtual void getReply(const char *&data, size_t &len, std::string &contentType);
+};
+
+/***************** ReadOperations implementation ****************/
+
+ReadOperations::ReadOperations(const std::string &config_name) :
+    m_configName(config_name)
+{}
+
+void ReadOperations::getConfigs(bool getTemplates, std::vector<std::string> &configNames)
+{
+    SyncConfig::ServerList list;
+    if (getTemplates) {
+        list = SyncConfig::getServerTemplates();
+    } else {
+        list = SyncConfig::getServers();
+    }
+    BOOST_FOREACH(const SyncConfig::ServerList::value_type &server, list) {
+        configNames.push_back(server.first);
+    }
 }
-#define SYNCEVO_DBUS_ERROR (syncevo_dbus_error_quark())
 
-static GType
-syncevo_dbus_error_get_type (void)
+boost::shared_ptr<SyncConfig> ReadOperations::getLocalConfig(const string &configName)
 {
-       static GType etype = 0;
-       if (G_UNLIKELY (etype == 0)) {
-               static const GEnumValue values[] = {
-                       { SYNCEVO_DBUS_ERROR_GENERIC_ERROR, "SYNCEVO_DBUS_ERROR_GENERIC_ERROR", "GenericError" },
-                       { SYNCEVO_DBUS_ERROR_NO_SUCH_SERVER, "SYNCEVO_DBUS_ERROR_NO_SUCH_SERVER", "NoSuchServer" },
-                       { SYNCEVO_DBUS_ERROR_MISSING_ARGS, "SYNCEVO_DBUS_ERROR_MISSING_ARGS", "MissingArgs" },
-                       { SYNCEVO_DBUS_ERROR_INVALID_CALL, "SYNCEVO_DBUS_ERROR_INVALID_CALL", "InvalidCall" },
-                       { 0 }
-               };
-               etype = g_enum_register_static ("SyncevoDBusError", values);
-       }
-       return etype;
+    string peer, context;
+    SyncConfig::splitConfigString(SyncConfig::normalizeConfigString(configName),
+                                  peer, context);
+
+    boost::shared_ptr<SyncConfig> syncConfig(new SyncConfig(configName));
+    // the default configuration can always be opened for reading,
+    // everything else must exist
+    if ((context != "default" || peer != "") &&
+        !syncConfig->exists()) {
+        SE_THROW_EXCEPTION(NoSuchConfig, "No configuration '" + configName + "' found");
+    }
+
+    // TODO: handle temporary configs (MB #8116)
+    // - if config was set temporarily, it doesn't have to exist on disk =>
+    //   the check above is too strict
+    // - set temporary properties as filters
+
+    return syncConfig;
 }
-#define SYNCEVO_DBUS_ERROR_TYPE (syncevo_dbus_error_get_type ())
 
+void ReadOperations::getConfig(bool getTemplate,
+                               Config_t &config)
+{
+    map<string, string> localConfigs;
+    boost::shared_ptr<SyncConfig> syncConfig;
+    /** get server template */
+    if(getTemplate) {
+        string peer, context;
+        SyncConfig::splitConfigString(SyncConfig::normalizeConfigString(m_configName),
+                                      peer, context);
+
+        syncConfig = SyncConfig::createServerTemplate(peer);
+        if(!syncConfig.get()) {
+            SE_THROW_EXCEPTION(NoSuchConfig, "No template '" + m_configName + "' found");
+        }
+
+        // use the shared properties from the right context as filter
+        // so that the returned template preserves existing properties
+        boost::shared_ptr<SyncConfig> shared = getLocalConfig(string("@") + context);
+
+        ConfigProps props;
+        shared->getProperties()->readProperties(props);
+        syncConfig->setConfigFilter(true, "", props);
+        BOOST_FOREACH(std::string source, shared->getSyncSources()) {
+            SyncSourceNodes nodes = shared->getSyncSourceNodes(source, "");
+            props.clear();
+            nodes.getProperties()->readProperties(props);
+            syncConfig->setConfigFilter(false, source, props);
+        }
+    } else {
+        syncConfig = getLocalConfig(m_configName);
+    }
+    setFilters(*syncConfig);
+
+    /** get sync properties and their values */
+    ConfigPropertyRegistry &syncRegistry = SyncConfig::getRegistry();
+    BOOST_FOREACH(const ConfigProperty *prop, syncRegistry) {
+        bool isDefault = false;
+        string value = prop->getProperty(*syncConfig->getProperties(), &isDefault);
+        if(!isDefault) {
+            localConfigs.insert(pair<string, string>(prop->getName(), value));
+        }
+    }
+
+    config.insert(pair<string,map<string, string> >("", localConfigs));
+
+    /* get configurations from sources */
+    list<string> sources = syncConfig->getSyncSources();
+    BOOST_FOREACH(const string &name, sources) {
+        localConfigs.clear();
+        SyncSourceNodes sourceNodes = syncConfig->getSyncSourceNodes(name);
+        ConfigPropertyRegistry &sourceRegistry = SyncSourceConfig::getRegistry();
+        BOOST_FOREACH(const ConfigProperty *prop, sourceRegistry) {
+            bool isDefault = false;
+            string value = prop->getProperty(*sourceNodes.getProperties(), &isDefault);
+            if(!isDefault) {
+                localConfigs.insert(pair<string, string>(prop->getName(), value));
+            }
+        }
+        config.insert(pair<string, map<string, string> >( "source/" + name, localConfigs));
+    }
+}
 
-#define SYNCEVO_SOURCE_TYPE (dbus_g_type_get_struct ("GValueArray", G_TYPE_STRING, G_TYPE_INT, G_TYPE_INVALID))
-typedef GValueArray SyncevoSource;
-#define SYNCEVO_OPTION_TYPE (dbus_g_type_get_struct ("GValueArray", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID))
-typedef GValueArray SyncevoOption;
-#define SYNCEVO_SERVER_TYPE (dbus_g_type_get_struct ("GValueArray", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_INVALID))
-typedef GValueArray SyncevoServer;
+void ReadOperations::getReports(uint32_t start, uint32_t count,
+                                Reports_t &reports)
+{
+    if(m_configName.empty()) {
+        // TODO: an empty config name should return reports for
+        // all peers (MB#8049)
+        SE_THROW_EXCEPTION(NoSuchConfig,
+                           "listing reports without peer name not implemented yet");
+    }
+    SyncContext client(m_configName, false);
+    std::vector<string> dirs;
+    client.getSessions(dirs);
+
+    uint32_t index = 0;
+    BOOST_FOREACH( const string &dir, dirs) {
+        /** if start plus count is bigger than actual size, then return actual - size reports */
+        if(index >= start && index - start < count) {
+            std::map<string, string> aReport;
+            SyncReport report;
+            client.readSessionInfo(dir,report);
+
+            /** serialize report to ConfigProps and then copy them to reports */
+            HashFileConfigNode node("/dev/null","",true);
+            node << report;
+            ConfigProps props;
+            node.readProperties(props);
+
+            BOOST_FOREACH(const ConfigProps::value_type &entry, props) {
+                aReport.insert(entry);
+            }
+            reports.push_back(aReport);
+        }
+        index++;
+    }
+}
 
-#define SYNCEVO_REPORT_TYPE (dbus_g_type_get_struct ("GValueArray", G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INVALID))
-typedef GValueArray SyncevoReport;
-#define SYNCEVO_REPORT_ARRAY_TYPE (dbus_g_type_get_struct ("GValueArray", G_TYPE_INT, dbus_g_type_get_collection ("GPtrArray", SYNCEVO_REPORT_TYPE), G_TYPE_INVALID))
-typedef GValueArray SyncevoReportArray;
+void ReadOperations::checkSource(const std::string &sourceName)
+{
+    boost::shared_ptr<SyncConfig> config(new SyncConfig(m_configName));
+    setFilters(*config);
+
+    list<std::string> sourceNames = config->getSyncSources();
+    list<std::string>::iterator it;
+    for(it = sourceNames.begin(); it != sourceNames.end(); ++it) {
+        if(*it == sourceName) {
+            break;
+        }
+    }
+    if(it == sourceNames.end()) {
+        SE_THROW_EXCEPTION(NoSuchSource, "'" + m_configName + "' has no '" + sourceName + "' source");
+    }
+    bool checked = false;
+    try {
+        // this can already throw exceptions when the config is invalid
+        SyncSourceParams params(sourceName, config->getSyncSourceNodes(sourceName));
+        auto_ptr<SyncSource> syncSource(SyncSource::createSource(params, false));
+
+        if (syncSource.get()) {
+            syncSource->open();
+            // success!
+            checked = true;
+        }
+    } catch (...) {
+        Exception::handle();
+    }
+
+    if (!checked) {
+        SE_THROW_EXCEPTION(SourceUnusable, "The source '" + sourceName + "' is not usable");
+    }
+}
+void ReadOperations::getDatabases(const string &sourceName, SourceDatabases_t &databases)
+{
+    boost::shared_ptr<SyncConfig> config(new SyncConfig(m_configName));
+    setFilters(*config);
+
+    SyncSourceParams params(sourceName, config->getSyncSourceNodes(sourceName));
+    const SourceRegistry &registry(SyncSource::getSourceRegistry());
+    BOOST_FOREACH(const RegisterSyncSource *sourceInfo, registry) {
+        SyncSource *source = sourceInfo->m_create(params);
+        if (!source) {
+            continue;
+        } else if (source == RegisterSyncSource::InactiveSource) {
+            SE_THROW_EXCEPTION(NoSuchSource, "'" + m_configName + "' backend of source '" + sourceName + "' is not supported");
+        } else {
+            auto_ptr<SyncSource> autoSource(source);
+            databases = autoSource->getDatabases();
+            return;
+        }
+    }
+
+    SE_THROW_EXCEPTION(NoSuchSource, "'" + m_configName + "' has no '" + sourceName + "' source");
+}
 
-GMainLoop *loop;
+/***************** DBusSync implementation **********************/
 
+DBusSync::DBusSync(const std::string &config,
+                   Session &session) :
+    SyncContext(config, true),
+    m_session(session)
+{
+}
 
-SyncevoSource*
-syncevo_source_new (char *name, int mode)
+boost::shared_ptr<TransportAgent> DBusSync::createTransportAgent()
 {
-       GValue val = {0, };
+    if (m_session.useConnection()) {
+        // use the D-Bus Connection to send and receive messages
+        return boost::shared_ptr<TransportAgent>(new DBusTransportAgent(m_session.getServer().getLoop(),
+                                                                        m_session,
+                                                                        m_session.getConnection()));
+    } else {
+        // no connection, use HTTP via libsoup/GMainLoop
+        GMainLoop *loop = m_session.getServer().getLoop();
+        g_main_loop_ref(loop);
+        boost::shared_ptr<HTTPTransportAgent> agent(new SoupTransportAgent(loop));
+        agent->setConfig(*this);
+        return agent;
+    }
+}
 
-       g_value_init (&val, SYNCEVO_SOURCE_TYPE);
-       g_value_take_boxed (&val, dbus_g_type_specialized_construct (SYNCEVO_SOURCE_TYPE));
-       dbus_g_type_struct_set (&val, 0, name, 1, mode, G_MAXUINT);
+void DBusSync::displaySyncProgress(sysync::TProgressEventEnum type,
+                                   int32_t extra1, int32_t extra2, int32_t extra3)
+{
+    SyncContext::displaySyncProgress(type, extra1, extra2, extra3);
+    m_session.syncProgress(type, extra1, extra2, extra3);
+}
 
-       return (SyncevoSource*) g_value_get_boxed (&val);
+void DBusSync::displaySourceProgress(sysync::TProgressEventEnum type,
+                                     SyncSource &source,
+                                     int32_t extra1, int32_t extra2, int32_t extra3)
+{
+    SyncContext::displaySourceProgress(type, source, extra1, extra2, extra3);
+    m_session.sourceProgress(type, source, extra1, extra2, extra3);
 }
 
-void
-syncevo_source_get (SyncevoSource *source, const char **name, int *mode)
+bool DBusSync::checkForSuspend()
 {
-       if (name) {
-               *name = g_value_get_string (g_value_array_get_nth (source, 0));
-       }
-       if (mode) {
-               *mode = g_value_get_int (g_value_array_get_nth (source, 1));
-       }
+    return m_session.isSuspend() || SyncContext::checkForSuspend();
 }
 
-static void
-syncevo_source_add_to_map (SyncevoSource *source, map<string, int> source_map)
+bool DBusSync::checkForAbort()
 {
-       const char *str;
-       int mode;
-       
-       syncevo_source_get (source, &str, &mode);
-       source_map.insert (make_pair (str, mode));
+    return m_session.isAbort() || SyncContext::checkForAbort();
 }
 
-void
-syncevo_source_free (SyncevoSource *source)
+int DBusSync::sleep(int intervals)
 {
-       if (source) {
-               g_boxed_free (SYNCEVO_SOURCE_TYPE, source);
-       }
+    time_t start = time(NULL);
+    while (true) {
+        g_main_context_iteration(NULL, false);
+        time_t now = time(NULL);
+        if (checkForSuspend() || checkForAbort()) {
+            return  (intervals - now + start);
+        } 
+        if (intervals - now + start <= 0) {
+            return intervals - now +start;
+        }
+    }
 }
 
-SyncevoOption*
-syncevo_option_new (char *ns, char *key, char *value)
+/***************** Session implementation ***********************/
+
+void Session::detach(const Caller_t &caller)
 {
-       GValue val = {0, };
+    boost::shared_ptr<Client> client(m_server.findClient(caller));
+    if (!client) {
+        throw runtime_error("unknown client");
+    }
+    client->detach(this);
+}
 
-       g_value_init (&val, SYNCEVO_OPTION_TYPE);
-       g_value_take_boxed (&val, dbus_g_type_specialized_construct (SYNCEVO_OPTION_TYPE));
-       dbus_g_type_struct_set (&val, 0, ns, 1, key, 2, value, G_MAXUINT);
+static void setSyncFilters(const ReadOperations::Config_t &config,FilterConfigNode::ConfigFilter &syncFilter,std::map<std::string, FilterConfigNode::ConfigFilter> &sourceFilters)
+{
+    ReadOperations::Config_t::const_iterator it;
+    for (it = config.begin(); it != config.end(); it++) {
+        map<string, string>::const_iterator sit;
+        if(it->first.empty()) {
+            for (sit = it->second.begin(); sit != it->second.end(); sit++) {
+                syncFilter.insert(*sit);
+            }
+        } else {
+            string name = it->first;
+            if(name.find("source/") == 0) {
+                name = name.substr(7); ///> 7 is the length of "source/"
+                FilterConfigNode::ConfigFilter &sourceFilter = sourceFilters[name];
+                for (sit = it->second.begin(); sit != it->second.end(); sit++) {
+                    sourceFilter.insert(*sit);
+                }
+            }
+        }
+    }
+}
+void Session::setConfig(bool update, bool temporary,
+                        const ReadOperations::Config_t &config)
+{
+    if (!m_active) {
+        SE_THROW_EXCEPTION(InvalidCall, "session is not active, call not allowed at this time");
+    }
+    if (m_sync) {
+        SE_THROW_EXCEPTION(InvalidCall, "sync started, cannot change configuration at this time");
+    }
+    if (!update && temporary) {
+        throw std::runtime_error("Clearing existing configuration and temporary configuration changes which only affects the duration of the session are mutually exclusive");
+    }
+
+    /** check whether we need remove the entire configuration */
+    if(!update && config.empty()) {
+        boost::shared_ptr<SyncConfig> syncConfig(new SyncConfig(getConfigName()));
+        if(syncConfig.get()) {
+            syncConfig->remove();
+        }
+        return;
+    }
+    if(temporary) {
+        /* save temporary configs in session filters */
+        setSyncFilters(config, m_syncFilter, m_sourceFilters);
+        m_tempConfig = true;
+    } else {
+        FilterConfigNode::ConfigFilter syncFilter;
+        std::map<std::string, FilterConfigNode::ConfigFilter> sourceFilters;
+        setSyncFilters(config, syncFilter, sourceFilters);
+        /* need to save configurations */
+        boost::shared_ptr<SyncConfig> from(new SyncConfig(getConfigName()));
+        /* if it is not clear mode and config does not exist, an error throws */
+        if(update && !from->exists()) {
+            SE_THROW_EXCEPTION(NoSuchConfig, "The configuration '" + getConfigName() + "' doesn't exist" );
+        }
+        if(!update) {
+            list<string> sources = from->getSyncSources();
+            list<string>::iterator it;
+            for(it = sources.begin(); it != sources.end(); ++it) {
+                string source = "source/";
+                source += *it;
+                ReadOperations::Config_t::const_iterator configIt = config.find(source);
+                if(configIt == config.end()) {
+                    /** if no config for this source, we remove it */
+                    from->removeSyncSource(*it);
+                } else {
+                    /** just clear visiable properties, remove them and their values */
+                    from->clearSyncSourceProperties(*it);
+                }
+            }
+            from->clearSyncProperties();
+        }
+        /** generate new sources in the config map */
+        for (ReadOperations::Config_t::const_iterator it = config.begin(); it != config.end(); ++it) {
+            string sourceName = it->first;
+            if(sourceName.find("source/") == 0) {
+                sourceName = sourceName.substr(7); ///> 7 is the length of "source/"
+                from->getSyncSourceNodes(sourceName);
+            }
+        }
+        /* apply user settings */
+        from->setConfigFilter(true, "", syncFilter);
+        map<string, FilterConfigNode::ConfigFilter>::iterator it;
+        for ( it = sourceFilters.begin(); it != sourceFilters.end(); it++ ) {
+            from->setConfigFilter(false, it->first, it->second);
+        }
+        boost::shared_ptr<DBusSync> syncConfig(new DBusSync(getConfigName(), *this));
+        syncConfig->copy(*from, NULL);
+
+        syncConfig->preFlush(*syncConfig);
+        syncConfig->flush();
+    }
+}
 
-       return (SyncevoOption*) g_value_get_boxed (&val);
+void Session::initServer(SharedBuffer data, const std::string &messageType)
+{
+    m_serverMode = true;
+    m_initialMessage = data;
+    m_initialMessageType = messageType;
 }
 
-void
-syncevo_option_get (SyncevoOption *option, const char **ns, const char **key, const char **value)
+void Session::sync(const std::string &mode, const SourceModes_t &source_modes)
 {
-       if (ns) {
-               *ns = g_value_get_string (g_value_array_get_nth (option, 0));
-       }
-       if (key) {
-               *key = g_value_get_string (g_value_array_get_nth (option, 1));
-       }
-       if (value) {
-               *value = g_value_get_string (g_value_array_get_nth (option, 2));
-       }
+    if (!m_active) {
+        SE_THROW_EXCEPTION(InvalidCall, "session is not active, call not allowed at this time");
+    }
+    if (m_sync) {
+        SE_THROW_EXCEPTION(InvalidCall, "sync started, cannot start again");
+    }
+
+    m_sync.reset(new DBusSync(getConfigName(), *this));
+    if (m_serverMode) {
+        m_sync->initServer(m_sessionID,
+                           m_initialMessage,
+                           m_initialMessageType);
+        boost::shared_ptr<Connection> c = m_connection.lock();
+        if (c && !c->mustAuthenticate()) {
+            // unsetting username/password disables checking them
+            m_syncFilter["password"] = "";
+            m_syncFilter["username"] = "";
+        }
+    }
+
+    // Apply temporary config filters. The parameters of this function
+    // override the source filters, if set.
+    m_sync->setConfigFilter(true, "", m_syncFilter);
+    FilterConfigNode::ConfigFilter filter;
+    filter = m_sourceFilter;
+    if (!mode.empty()) {
+        filter[SyncSourceConfig::m_sourcePropSync.getName()] = mode;
+    }
+    m_sync->setConfigFilter(false, "", filter);
+    BOOST_FOREACH(const std::string &source,
+                  m_sync->getSyncSources()) {
+        filter = m_sourceFilters[source];
+        SourceModes_t::const_iterator it = source_modes.find(source);
+        if (it != source_modes.end()) {
+            filter[SyncSourceConfig::m_sourcePropSync.getName()] = it->second;
+        }
+        m_sync->setConfigFilter(false, source, filter);
+    }
+
+    // Update status and progress. From now on, all configured sources
+    // have their default entry (referencing them by name creates the
+    // entry).
+    BOOST_FOREACH(const std::string source,
+                  m_sync->getSyncSources()) {
+        m_sourceStatus[source];
+        m_sourceProgress[source];
+    }
+    fireProgress(true);
+    fireStatus(true);
+
+    // now that we have a DBusSync object, return from the main loop
+    // and once that is done, transfer control to that object
+    g_main_loop_quit(loop);
 }
 
-void
-syncevo_option_free (SyncevoOption *option)
+void Session::abort()
 {
-       if (option) {
-               g_boxed_free (SYNCEVO_OPTION_TYPE, option);
-       }
+    if (!m_sync) {
+        SE_THROW_EXCEPTION(InvalidCall, "sync not started, cannot abort at this time");
+    }
+    m_syncStatus = SYNC_ABORT;
+    fireStatus(true);
+
+    // state change, return to caller so that it can react
+    g_main_loop_quit(m_server.getLoop());
 }
 
-SyncevoServer* syncevo_server_new (char *name, char *url, char *icon, gboolean consumer_ready)
+void Session::suspend()
 {
-       GValue val = {0, };
+    if (!m_sync) {
+        SE_THROW_EXCEPTION(InvalidCall, "sync not started, cannot suspend at this time");
+    }
+    m_syncStatus = SYNC_SUSPEND;
+    fireStatus(true);
+    g_main_loop_quit(m_server.getLoop());
+}
 
-       g_value_init (&val, SYNCEVO_SERVER_TYPE);
-       g_value_take_boxed (&val, dbus_g_type_specialized_construct (SYNCEVO_SERVER_TYPE));
-       dbus_g_type_struct_set (&val,
-                               0, name,
-                               1, url,
-                               2, icon,
-                               3, consumer_ready,
-                               G_MAXUINT);
+void Session::getStatus(std::string &status,
+                        uint32_t &error,
+                        SourceStatuses_t &sources)
+{
+    status = syncStatusToString(m_syncStatus);
+    // TODO: append ";processing" or ";waiting"
 
-       return (SyncevoServer*) g_value_get_boxed (&val);
+    error = m_error;
+    sources = m_sourceStatus;
 }
 
-void syncevo_server_get (SyncevoServer *server, const char **name, const char **url, const char **icon, gboolean *consumer_ready)
+void Session::getProgress(int32_t &progress,
+                          SourceProgresses_t &sources)
 {
-       if (name) {
-               *name = g_value_get_string (g_value_array_get_nth (server, 0));
-       }
-       if (url) {
-               *url = g_value_get_string (g_value_array_get_nth (server, 1));
-       }
-       if (icon) {
-               *icon = g_value_get_string (g_value_array_get_nth (server, 2));
-       }
-       if (consumer_ready) {
-               *consumer_ready = g_value_get_boolean (g_value_array_get_nth (server, 3));
-       }
+    progress = m_progress;
+    sources = m_sourceProgress;
 }
 
-void syncevo_server_free (SyncevoServer *server)
+void Session::fireStatus(bool flush)
 {
-       if (server) {
-               g_boxed_free (SYNCEVO_SERVER_TYPE, server);
-       }
+    std::string status;
+    uint32_t error;
+    SourceStatuses_t sources;
+
+    /** not force flushing and not timeout, return */
+    if(!flush && !m_statusTimer.timeout()) {
+        return;
+    }
+    m_statusTimer.reset();
+
+    getStatus(status, error, sources);
+    emitStatus(status, error, sources);
 }
 
-SyncevoReport* 
-syncevo_report_new (char *source)
+void Session::fireProgress(bool flush)
 {
-       GValue val = {0, };
+    int32_t progress;
+    SourceProgresses_t sources;
 
-       g_value_init (&val, SYNCEVO_REPORT_TYPE);
-       g_value_take_boxed (&val, dbus_g_type_specialized_construct (SYNCEVO_REPORT_TYPE));
-       dbus_g_type_struct_set (&val,
-                               0, source,
-                               G_MAXUINT);
+    /** not force flushing and not timeout, return */
+    if(!flush && !m_progressTimer.timeout()) {
+        return;
+    }
+    m_progressTimer.reset();
 
-       return (SyncevoReport*) g_value_get_boxed (&val);
+    getProgress(progress, sources);
+    emitProgress(progress, sources);
 }
-
-static void
-insert_int (SyncevoReport *report, int index, int value)
+string Session::syncStatusToString(SyncStatus state)
 {
-       GValue val = {0};
+    switch(state) {
+    case SYNC_QUEUEING:
+        return "queueing";
+    case SYNC_IDLE:
+        return "idle";
+    case SYNC_RUNNING:
+        return "running";
+    case SYNC_ABORT:
+        return "aborting";
+    case SYNC_SUSPEND:
+        return "suspending";
+    case SYNC_DONE:
+        return "done";
+    default:
+        return "";
+    };
+}
 
-       g_value_init (&val, G_TYPE_INT);
-       g_value_set_int (&val, value);
-       g_value_array_insert (report, index, &val);
+Session::Session(DBusServer &server,
+                 const std::string &peerDeviceID,
+                 const std::string &config_name,
+                 const std::string &session) :
+    DBusObjectHelper(server.getConnection(),
+                     std::string("/org/syncevolution/Session/") + session,
+                     "org.syncevolution.Session"),
+    ReadOperations(config_name),
+    m_server(server),
+    m_sessionID(session),
+    m_peerDeviceID(peerDeviceID),
+    m_serverMode(false),
+    m_useConnection(false),
+    m_tempConfig(false),
+    m_active(false),
+    m_syncStatus(SYNC_QUEUEING),
+    m_priority(PRI_DEFAULT),
+    m_progress(0),
+    m_progData(m_progress),
+    m_error(0),
+    m_statusTimer(100),
+    m_progressTimer(50),
+    emitStatus(*this, "StatusChanged"),
+    emitProgress(*this, "ProgressChanged")
+{
+    add(this, &Session::detach, "Detach");
+    add(&ReadOperations::getConfigs, "GetConfigs");
+    add(static_cast<ReadOperations *>(this), &ReadOperations::getConfig, "GetConfig");
+    add(this, &Session::setConfig, "SetConfig");
+    add(static_cast<ReadOperations *>(this), &ReadOperations::getReports, "GetReports");
+    add(static_cast<ReadOperations *>(this), &ReadOperations::checkSource, "CheckSource");
+    add(static_cast<ReadOperations *>(this), &ReadOperations::getDatabases, "GetDatabases");
+    add(this, &Session::sync, "Sync");
+    add(this, &Session::abort, "Abort");
+    add(this, &Session::suspend, "Suspend");
+    add(this, &Session::getStatus, "GetStatus");
+    add(this, &Session::getProgress, "GetProgress");
+    add(emitStatus);
+    add(emitProgress);
 }
 
-void
-syncevo_report_set_io (SyncevoReport *report, 
-                       int sent_bytes, int received_bytes)
+Session::~Session()
 {
-       g_return_if_fail (report);
+    m_server.dequeue(this);
+}
+    
 
-       insert_int (report, 1, sent_bytes);
-       insert_int (report, 2, received_bytes);
+void Session::setActive(bool active)
+{
+    m_active = active;
+    if (active) {
+        if (m_syncStatus == SYNC_QUEUEING) {
+            m_syncStatus = SYNC_IDLE;
+            fireStatus(true);
+        }
+
+        boost::shared_ptr<Connection> c = m_connection.lock();
+        if (c) {
+            c->ready();
+        }
+    }
 }
 
+void Session::syncProgress(sysync::TProgressEventEnum type,
+                           int32_t extra1, int32_t extra2, int32_t extra3)
+{
+    switch(type) {
+    case sysync::PEV_SESSIONSTART:
+        m_progData.setStep(ProgressData::PRO_SYNC_INIT);
+        fireProgress(true);
+        break;
+    case sysync::PEV_SESSIONEND:
+        if((uint32_t)extra1 != m_error) {
+            m_error = extra1;
+            fireStatus(true);
+        }
+        m_progData.setStep(ProgressData::PRO_SYNC_INVALID);
+        fireProgress(true);
+        break;
+    case sysync::PEV_SENDSTART:
+        m_progData.sendStart();
+        break;
+    case sysync::PEV_SENDEND:
+    case sysync::PEV_RECVSTART:
+    case sysync::PEV_RECVEND:
+        m_progData.receiveEnd();
+        fireProgress();
+        break;
+    case sysync::PEV_DISPLAY100:
+    case sysync::PEV_SUSPENDCHECK:
+    case sysync::PEV_DELETING:
+        break;
+    case sysync::PEV_SUSPENDING:
+        m_syncStatus = SYNC_SUSPEND;
+        fireStatus(true);
+        break;
+    default:
+        ;
+    }
+}
 
-void 
-syncevo_report_set_local (SyncevoReport *report, 
-                          int adds, int updates, int removes, int rejects)
+void Session::sourceProgress(sysync::TProgressEventEnum type,
+                             SyncSource &source,
+                             int32_t extra1, int32_t extra2, int32_t extra3)
 {
-       g_return_if_fail (report);
+    SourceProgress &progress = m_sourceProgress[source.getName()];
+    SourceStatus &status = m_sourceStatus[source.getName()];
+    switch(type) {
+    case sysync::PEV_SYNCSTART:
+        if(source.getFinalSyncMode() != SYNC_NONE) {
+            m_progData.setStep(ProgressData::PRO_SYNC_UNINIT);
+            fireProgress();
+        }
+        break;
+    case sysync::PEV_SYNCEND:
+        if(source.getFinalSyncMode() != SYNC_NONE) {
+            status.set(PrettyPrintSyncMode(source.getFinalSyncMode()), "done", extra1);
+            fireStatus(true);
+        }
+        break;
+    case sysync::PEV_PREPARING:
+        if(source.getFinalSyncMode() != SYNC_NONE) {
+            progress.m_phase        = "preparing";
+            progress.m_prepareCount = extra1;
+            progress.m_prepareTotal = extra2;
+            m_progData.itemPrepare();
+            fireProgress(true);
+        }
+        break;
+    case sysync::PEV_ITEMSENT:
+        if(source.getFinalSyncMode() != SYNC_NONE) {
+            progress.m_phase     = "sending";
+            progress.m_sendCount = extra1;
+            progress.m_sendTotal = extra2;
+            fireProgress(true);
+        }
+        break;
+    case sysync::PEV_ITEMRECEIVED:
+        if(source.getFinalSyncMode() != SYNC_NONE) {
+            progress.m_phase        = "receiving";
+            progress.m_receiveCount = extra1;
+            progress.m_receiveTotal = extra2;
+            m_progData.itemReceive(source.getName(), extra1, extra2);
+            fireProgress(true);
+        }
+        break;
+    case sysync::PEV_ALERTED:
+        if(source.getFinalSyncMode() != SYNC_NONE) {
+            status.set(PrettyPrintSyncMode(source.getFinalSyncMode()), "running", 0);
+            fireStatus(true);
+            m_progData.setStep(ProgressData::PRO_SYNC_DATA);
+            m_progData.addSyncMode(source.getFinalSyncMode());
+            fireProgress();
+        }
+        break;
+    default:
+        ;
+    }
+}
 
-       insert_int (report, 3, adds);
-       insert_int (report, 4, updates);
-       insert_int (report, 5, removes);
-       insert_int (report, 6, rejects);
+void Session::run()
+{
+    if (m_sync) {
+        try {
+            m_syncStatus = SYNC_RUNNING;
+            fireStatus(true);
+            SyncMLStatus status;
+            m_progData.setStep(ProgressData::PRO_SYNC_PREPARE);
+            try {
+                status = m_sync->sync();
+            } catch (...) {
+                status = m_sync->handleException();
+            }
+            if (!m_error) {
+                m_error = status;
+            }
+
+            // if there is a connection, then it is no longer needed
+            boost::shared_ptr<Connection> c = m_connection.lock();
+            if (c) {
+                c->shutdown();
+            }
+        } catch (...) {
+            // we must enter SYNC_DONE under all circumstances,
+            // even when failing during connection shutdown
+            m_syncStatus = SYNC_DONE;
+            fireStatus(true);
+            throw;
+        }
+        m_syncStatus = SYNC_DONE;
+        fireStatus(true);
+    }
 }
 
-void
-syncevo_report_set_remote (SyncevoReport *report, 
-                           int adds, int updates, int removes, int rejects)
+void Session::setFilters(SyncConfig &config)
 {
-       g_return_if_fail (report);
+    /** apply temporary configs to config */
+    config.setConfigFilter(true, "", m_syncFilter);
+    // set all sources in the filter to config
+    BOOST_FOREACH(const SourceFilters_t::value_type &value, m_sourceFilters) {
+        config.setConfigFilter(false, value.first, value.second);
+    }
+}
 
-       insert_int (report, 7, adds);
-       insert_int (report, 8, updates);
-       insert_int (report, 9, removes);
-       insert_int (report, 10, rejects);
+/************************ ProgressData implementation *****************/
+ProgressData::ProgressData(int32_t &progress) 
+    : m_progress(progress),
+    m_step(PRO_SYNC_INVALID),
+    m_sendCounts(0),
+    m_internalMode(INTERNAL_NONE)
+{
+    /**
+     * init default units of each step 
+     */
+    float totalUnits = 0.0;
+    for(int i = 0; i < PRO_SYNC_TOTAL; i++) {
+        float units = getDefaultUnits((ProgressStep)i);
+        m_syncUnits[i] = units;
+        totalUnits += units;
+    }
+    m_propOfUnit = 1.0 / totalUnits;
+
+    /** 
+     * init default sync step proportions. each step stores proportions of
+     * its previous steps and itself.
+     */
+    m_syncProp[0] = 0;
+    for(int i = 1; i < PRO_SYNC_TOTAL - 1; i++) {
+        m_syncProp[i] = m_syncProp[i - 1] + m_syncUnits[i] / totalUnits;
+    }
+    m_syncProp[PRO_SYNC_TOTAL - 1] = 1.0;
 }
 
-void
-syncevo_report_set_conflicts (SyncevoReport *report, 
-                              int local_won, int remote_won, int duplicated)
+void ProgressData::setStep(ProgressStep step) 
 {
-       g_return_if_fail (report);
+    if(m_step != step) {
+        /** if state is changed, progress is set as the end of current step*/
+        m_progress = 100.0 * m_syncProp[(int)m_step];
+        m_step = step; ///< change to new state
+        m_sendCounts = 0; ///< clear send/receive counts 
+        m_source = ""; ///< clear source
+    }
+}
 
-       insert_int (report, 11, local_won);
-       insert_int (report, 12, remote_won);
-       insert_int (report, 13, duplicated);
+void ProgressData::sendStart()
+{
+    checkInternalMode();
+    m_sendCounts++;
+
+    /* self adapts. If a new send and not default, we need re-calculate proportions */
+    if(m_sendCounts > MSG_SEND_RECEIVE_TIMES) {
+        m_syncUnits[(int)m_step] += 1;
+        recalc();
+    }
+    /** 
+     * If in the send operation of PRO_SYNC_UNINIT, it often takes extra time
+     * to send message due to items handling 
+     */
+    if(m_step == PRO_SYNC_UNINIT && m_syncUnits[(int)m_step] != MSG_SEND_RECEIVE_TIMES) {
+        updateProg(DATA_PREPARE_RATIO);
+    }
 }
 
-const char*
-syncevo_report_get_name (SyncevoReport *report)
+void ProgressData::receiveEnd()
 {
-       g_return_val_if_fail (report, NULL);
+    /** 
+     * often receiveEnd is the last operation of each step by default.
+     * If more send/receive, then we need expand proportion of current 
+     * step and re-calc them
+     */
+    updateProg(m_syncUnits[(int)m_step]);
+}
 
-       return g_value_get_string (g_value_array_get_nth (report, 0));
+void ProgressData::addSyncMode(SyncMode mode)
+{
+    switch(mode) {
+        case SYNC_TWO_WAY:
+        case SYNC_SLOW:
+            m_internalMode |= INTERNAL_TWO_WAY;
+            break;
+        case SYNC_ONE_WAY_FROM_CLIENT:
+        case SYNC_REFRESH_FROM_CLIENT:
+            m_internalMode |= INTERNAL_ONLY_TO_CLIENT;
+            break;
+        case SYNC_ONE_WAY_FROM_SERVER:
+        case SYNC_REFRESH_FROM_SERVER:
+            m_internalMode |= INTERNAL_ONLY_TO_SERVER;
+            break;
+        default:
+            ;
+    };
+}
 
+void ProgressData::itemPrepare()
+{
+    checkInternalMode();
+    /**
+     * only the first PEV_ITEMPREPARE event takes some time
+     * due to data access, other events don't according to
+     * profiling data
+     */
+    if(m_source.empty()) {
+        m_source = "source"; ///< use this to check whether itemPrepare occurs
+        updateProg(DATA_PREPARE_RATIO);
+    }
 }
 
-void
-syncevo_report_get_io (SyncevoReport *report, 
-                       int *bytes_sent, int *bytes_received)
+void ProgressData::itemReceive(const string &source, int count, int total)
 {
-       g_return_if_fail (report);
+    /** 
+     * source is used to check whether a new source is received
+     * If the first source, we compare its total number and default number
+     * then re-calc sync units
+     */
+    if(m_source.empty()) {
+        m_source = source;
+        if(total != 0) {
+            m_syncUnits[PRO_SYNC_UNINIT] += ONEITEM_RECEIVE_RATIO * (total - DEFAULT_ITEMS);
+            recalc();
+        }
+    /** if another new source, add them into sync units */
+    } else if(m_source != source){
+        m_source = source;
+        if(total != 0) {
+            m_syncUnits[PRO_SYNC_UNINIT] += ONEITEM_RECEIVE_RATIO * total;
+            recalc();
+        }
+    } 
+    updateProg(ONEITEM_RECEIVE_RATIO);
+}
 
-       if (bytes_sent) {
-               *bytes_sent = g_value_get_int (g_value_array_get_nth (report, 1));
-       }
-       if (bytes_received) {
-               *bytes_received = g_value_get_int (g_value_array_get_nth (report, 2));
-       }
+void ProgressData::updateProg(float ratio)
+{
+    m_progress += m_propOfUnit * 100 * ratio;
+    m_syncUnits[(int)m_step] -= ratio;
 }
 
-void
-syncevo_report_get_local (SyncevoReport *report, 
-                          int *adds, int *updates, int *removes, int *rejects)
+/** dynamically adapt the proportion of each step by their current units */
+void ProgressData::recalc()
 {
-       g_return_if_fail (report);
+    float units = getRemainTotalUnits();
+    if(std::abs(units) < std::numeric_limits<float>::epsilon()) {
+        m_propOfUnit = 0.0;
+    } else {
+        m_propOfUnit = ( 100.0 - m_progress ) / (100.0 * units);
+    }
+    if(m_step != PRO_SYNC_TOTAL -1 ) {
+        m_syncProp[(int)m_step] = m_progress / 100.0 + m_syncUnits[(int)m_step] * m_propOfUnit;
+        for(int i = ((int)m_step) + 1; i < PRO_SYNC_TOTAL - 1; i++) {
+            m_syncProp[i] = m_syncProp[i - 1] + m_syncUnits[i] * m_propOfUnit;
+        }
+    }
+}
 
-       if (adds) {
-               *adds = g_value_get_int (g_value_array_get_nth (report, 3));
-       }
-       if (updates) {
-               *updates = g_value_get_int (g_value_array_get_nth (report, 4));
-       }
-       if (removes) {
-               *removes = g_value_get_int (g_value_array_get_nth (report, 5));
-       }
-       if (rejects) {
-               *rejects = g_value_get_int (g_value_array_get_nth (report, 6));
-       }
+void ProgressData::checkInternalMode() 
+{
+    if(!m_internalMode) {
+        return;
+    } else if(m_internalMode & INTERNAL_TWO_WAY) {
+        // don't adjust
+    } else if(m_internalMode & INTERNAL_ONLY_TO_CLIENT) {
+        // only to client, remove units of prepare and send
+        m_syncUnits[PRO_SYNC_DATA] -= (ONEITEM_RECEIVE_RATIO * DEFAULT_ITEMS + DATA_PREPARE_RATIO);
+        recalc();
+    } else if(m_internalMode & INTERNAL_ONLY_TO_SERVER) {
+        // only to server, remove units of receive
+        m_syncUnits[PRO_SYNC_UNINIT] -= (ONEITEM_RECEIVE_RATIO * DEFAULT_ITEMS + DATA_PREPARE_RATIO);
+        recalc();
+    }
+    m_internalMode = INTERNAL_NONE;
 }
 
-void
-syncevo_report_get_remote (SyncevoReport *report, 
-                           int *adds, int *updates, int *removes, int *rejects)
+float ProgressData::getRemainTotalUnits()
 {
-       g_return_if_fail (report);
+    float total = 0.0;
+    for(int i = (int)m_step; i < PRO_SYNC_TOTAL; i++) {
+        total += m_syncUnits[i];
+    }
+    return total;
+}
 
-       if (adds) {
-               *adds = g_value_get_int (g_value_array_get_nth (report, 7));
-       }
-       if (updates) {
-               *updates = g_value_get_int (g_value_array_get_nth (report, 8));
-       }
-       if (removes) {
-               *removes = g_value_get_int (g_value_array_get_nth (report, 9));
-       }
-       if (rejects) {
-               *rejects = g_value_get_int (g_value_array_get_nth (report, 10));
-       }
+float ProgressData::getDefaultUnits(ProgressStep step)
+{
+    switch(step) {
+        case PRO_SYNC_PREPARE:
+            return PRO_SYNC_PREPARE_RATIO;
+        case PRO_SYNC_INIT:
+            return CONN_SETUP_RATIO + MSG_SEND_RECEIVE_TIMES;
+        case PRO_SYNC_DATA:
+            return ONEITEM_SEND_RATIO * DEFAULT_ITEMS + DATA_PREPARE_RATIO + MSG_SEND_RECEIVE_TIMES;
+        case PRO_SYNC_UNINIT:
+            return ONEITEM_RECEIVE_RATIO * DEFAULT_ITEMS + DATA_PREPARE_RATIO + MSG_SEND_RECEIVE_TIMES;
+        default:
+            return 0;
+    };
 }
 
-void
-syncevo_report_get_conflicts (SyncevoReport *report, 
-                              int *local_won, int *remote_won, int *duplicated)
+/************************ Connection implementation *****************/
+
+void Connection::failed(const std::string &reason)
 {
-       g_return_if_fail (report);
+    if (m_failure.empty()) {
+        m_failure = reason;
+        if (m_session) {
+            m_session->setConnectionError(reason);
+        }
+    }
+    if (m_state != FAILED) {
+        abort();
+    }
+    m_state = FAILED;
+}
 
-       if (local_won) {
-               *local_won = g_value_get_int (g_value_array_get_nth (report, 11));
-       }
-       if (remote_won) {
-               *remote_won = g_value_get_int (g_value_array_get_nth (report, 12));
-       }
-       if (duplicated) {
-               *duplicated = g_value_get_int (g_value_array_get_nth (report, 13));
-       }
+std::string Connection::buildDescription(const StringMap &peer)
+{
+    StringMap::const_iterator
+        desc = peer.find("description"),
+        id = peer.find("id"),
+        trans = peer.find("transport"),
+        trans_desc = peer.find("transport_description");
+    std::string buffer;
+    buffer.reserve(256);
+    if (desc != peer.end()) {
+        buffer += desc->second;
+    }
+    if (id != peer.end() || trans != peer.end()) {
+        if (!buffer.empty()) {
+            buffer += " ";
+        }
+        buffer += "(";
+        if (id != peer.end()) {
+            buffer += id->second;
+            if (trans != peer.end()) {
+                buffer += " via ";
+            }
+        }
+        if (trans != peer.end()) {
+            buffer += trans->second;
+            if (trans_desc != peer.end()) {
+                buffer += " ";
+                buffer += trans_desc->second;
+            }
+        }
+        buffer += ")";
+    }
+    return buffer;
 }
 
-void
-syncevo_report_free (SyncevoReport *report)
+void Connection::wakeupSession()
 {
-       if (report) {
-               g_boxed_free (SYNCEVO_REPORT_TYPE, report);
-       }
+    if (m_loop) {
+        g_main_loop_quit(m_loop);
+        m_loop = NULL;
+    }
 }
 
-SyncevoReportArray* syncevo_report_array_new (int end_time, GPtrArray *reports)
+void Connection::process(const Caller_t &caller,
+             const std::pair<size_t, const uint8_t *> &message,
+             const std::string &message_type)
 {
-       GValue val = {0, };
+    SE_LOG_DEBUG(NULL, NULL, "D-Bus client %s sends %lu bytes via connection %s, %s",
+                 caller.c_str(),
+                 (unsigned long)message.first,
+                 getPath(),
+                 message_type.c_str());
+
+    boost::shared_ptr<Client> client(m_server.findClient(caller));
+    if (!client) {
+        throw runtime_error("unknown client");
+    }
+
+    boost::shared_ptr<Connection> myself =
+        boost::static_pointer_cast<Connection, Resource>(client->findResource(this));
+    if (!myself) {
+        throw runtime_error("client does not own connection");
+    }
+
+    // any kind of error from now on terminates the connection
+    try {
+        switch (m_state) {
+        case SETUP: {
+            std::string config;
+            std::string peerDeviceID;
+            bool serverMode = false;
+            // check message type, determine whether we act
+            // as client or server, choose config
+            if (message_type == "HTTP Config") {
+                // type used for testing, payload is config name
+                config.assign(reinterpret_cast<const char *>(message.second),
+                              message.first);
+            } else if (message_type == TransportAgent::m_contentTypeServerAlertedNotificationDS) {
+               sysync::SanPackage san;
+               if (san.PassSan(const_cast<uint8_t *>(message.second), message.first) || san.GetHeader()) {
+                    // We are very tolerant regarding the content of the message.
+                    // If it doesn't parse, try to do something useful anyway.
+                    config = "default";
+                    SE_LOG_DEBUG(NULL, NULL, "SAN parsing failed, falling back to 'default' config");
+               } else {
+                    // Extract server ID and match it against a server
+                    // configuration.  Multiple different peers might use the
+                    // 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,
+                                 servers) {
+                       SyncContext context(server.first);
+                       if (context.getSyncURL() == serverID) {
+                            config = server.first;
+                           break;
+                       }
+
+                       // TODO: for other transports match against
+                       // transport specific properties, like Bluetooth MAC
+                        // address
+                    }
+                    if (config.empty()) {
+                        BOOST_FOREACH(const SyncConfig::ServerList::value_type &server,
+                                      servers) {
+                            if (server.first == serverID) {
+                                config = serverID;
+                                break;
+                            }
+                        }
+                    }
+
+                    // pick "default" as configuration name if none matched
+                    if (config.empty()) {
+                        config = "default";
+                        SE_LOG_DEBUG(NULL, NULL, "SAN Server ID '%s' unknown, falling back to 'default' config", serverID.c_str());
+                    }
+
+                    // TODO: create a suitable configuration automatically?!
+
+                    SE_LOG_DEBUG(NULL, NULL, "SAN sync with config %s", config.c_str());
+
+                    // extract number of sources
+                    int numSources = san.fNSync;
+                    int syncType;
+                    uint32_t contentType;
+                    std::string serverURI;
+                    if (!numSources) {
+                        SE_LOG_DEBUG(NULL, NULL, "SAN message with no sources");
+                        // Synchronize all known sources with the selected mode.
+                        if (san.GetNthSync(0, syncType, contentType, serverURI)) {
+                            SE_LOG_DEBUG(NULL, NULL, "SAN invalid header, using default modes");
+                        } else if (syncType < SYNC_FIRST || syncType > SYNC_LAST) {
+                            SE_LOG_DEBUG(NULL, NULL, "SAN invalid sync type %d, using default modes", syncType);
+                        } else {
+                            m_syncMode = PrettyPrintSyncMode(SyncMode(syncType), true);
+                            SE_LOG_DEBUG(NULL, NULL, "SAN sync mode for all configured sources: %s", m_syncMode.c_str());
+                        }
+                    } else {
+                        const SyncContext context(config);
+                        std::list<std::string> sources = context.getSyncSources();
+
+                        // check what the server wants us to synchronize
+                        // and only synchronize that
+                        m_syncMode = "disabled";
+                        for (int sync = 1; sync <= numSources; sync++) {
+                            if (san.GetNthSync(sync, syncType, contentType, serverURI)) {
+                                SE_LOG_DEBUG(NULL, NULL, "SAN invalid sync entry #%d", sync);
+                            } else if (syncType < SYNC_FIRST || syncType > SYNC_LAST) {
+                                SE_LOG_DEBUG(NULL, NULL, "SAN invalid sync type %d for entry #%d, ignoring entry", syncType, sync);
+                            } else {
+                                std::string syncMode = PrettyPrintSyncMode(SyncMode(syncType), true);
+                                bool found = false;
+                                BOOST_FOREACH(const std::string &source, sources) {
+                                    boost::shared_ptr<const PersistentSyncSourceConfig> sourceConfig(context.getSyncSourceConfig(source));
+                                    // prefix match because the local
+                                    // configuration might contain
+                                    // additional parameters (like date
+                                    // range selection for events)
+                                    if (boost::starts_with(sourceConfig->getURI(), serverURI)) {
+                                        SE_LOG_DEBUG(NULL, NULL,
+                                                     "SAN entry #%d = source %s with mode %s",
+                                                     sync, source.c_str(), syncMode.c_str());
+                                        m_sourceModes[source] = syncMode;
+                                        found = true;
+                                        break;
+                                    }
+                                }
+                                if (!found) {
+                                    SE_LOG_DEBUG(NULL, NULL,
+                                                 "SAN entry #%d with mode %s ignored because Server URI %s is unknown",
+                                                 sync, syncMode.c_str(), serverURI.c_str());
+                                }
+                            }
+                        }
+
+                        if (m_sourceModes.empty()) {
+                            SE_LOG_DEBUG(NULL, NULL,
+                                         "SAN message with no known entries, falling back to default");
+                            m_syncMode = "";
+                        }
+                    }
+                }
+
+                // TODO: use the session ID set by the server if non-null
+            } else if (message_type == TransportAgent::m_contentTypeSyncML ||
+                       message_type == TransportAgent::m_contentTypeSyncWBXML) {
+                // run a new SyncML session as server
+                serverMode = true;
+                if (m_peer.find("config") == m_peer.end() &&
+                    !m_peer["config"].empty()) {
+                    SE_LOG_DEBUG(NULL, NULL, "ignoring pre-chosen config '%s'",
+                                 m_peer["config"].c_str());
+                }
+
+                // peek into the data to extract the locURI = device ID,
+                // then use it to find the configuration
+                SyncContext::SyncMLMessageInfo info;
+                info = SyncContext::analyzeSyncMLMessage(reinterpret_cast<const char *>(message.second),
+                                                         message.first,
+                                                         message_type);
+                if (info.m_deviceID.empty()) {
+                    // TODO: proper exception
+                    throw runtime_error("could not extract LocURI=deviceID from initial message");
+                }
+                BOOST_FOREACH(const StringPair &entry,
+                              SyncConfig::getServers()) {
+                    SyncConfig peer(entry.first);
+                    if (info.m_deviceID == peer.getRemoteDevID()) {
+                        config = entry.first;
+                        SE_LOG_DEBUG(NULL, NULL, "matched %s against config %s (%s)",
+                                     info.toString().c_str(),
+                                     entry.first.c_str(),
+                                     entry.second.c_str());
+                        break;
+                    }
+                }
+                if (config.empty()) {
+                    // TODO: proper exception
+                    throw runtime_error(string("no configuration found for ") +
+                                        info.toString());
+                }
+
+                // abort previous session of this client
+                m_server.killSessions(info.m_deviceID);
+                peerDeviceID = info.m_deviceID;
+            } else {
+                throw runtime_error("message type not supported for starting a sync");
+            }
+
+            // run session as client or server
+            m_state = PROCESSING;
+            m_session.reset(new Session(m_server,
+                                        peerDeviceID,
+                                        config,
+                                        m_sessionID));
+            if (serverMode) {
+                m_session->initServer(SharedBuffer(reinterpret_cast<const char *>(message.second),
+                                                   message.first),
+                                      message_type);
+            }
+            m_session->setPriority(Session::PRI_CONNECTION);
+            m_session->setConnection(myself);
+            // this will be reset only when the connection shuts down okay
+            // or overwritten with the error given to us in
+            // Connection::close()
+            m_session->setConnectionError("closed prematurely");
+            m_server.enqueue(m_session);
+            break;
+        }
+        case PROCESSING:
+            throw std::runtime_error("protocol error: already processing a message");
+            break;        
+        case WAITING:
+            m_incomingMsg = SharedBuffer(reinterpret_cast<const char *>(message.second),
+                                         message.first);
+            m_incomingMsgType = message_type;
+            m_state = PROCESSING;
+            // get out of DBusTransportAgent::wait()
+            wakeupSession();
+            break;
+        case FINAL:
+            wakeupSession();
+            throw std::runtime_error("protocol error: final reply sent, no further message processing possible");
+        case DONE:
+            throw std::runtime_error("protocol error: connection closed, no further message processing possible");
+            break;
+        case FAILED:
+            throw std::runtime_error(m_failure);
+            break;
+        default:
+            throw std::runtime_error("protocol error: unknown internal state");
+            break;
+        }
+    } catch (const std::exception &error) {
+        failed(error.what());
+        throw;
+    } catch (...) {
+        failed("unknown exception in Connection::process");
+        throw;
+    }
+}
 
-       g_value_init (&val, SYNCEVO_REPORT_ARRAY_TYPE);
-       g_value_take_boxed (&val, dbus_g_type_specialized_construct (SYNCEVO_REPORT_ARRAY_TYPE));
-       dbus_g_type_struct_set (&val,
-                               0, end_time,
-                               1, reports,
-                               G_MAXUINT);
-       return (SyncevoReportArray*) g_value_get_boxed (&val);
+void Connection::close(const Caller_t &caller,
+                       bool normal,
+                       const std::string &error)
+{
+    SE_LOG_DEBUG(NULL, NULL, "D-Bus client %s closes connection %s %s%s%s",
+                 caller.c_str(),
+                 getPath(),
+                 normal ? "normally" : "with error",
+                 error.empty() ? "" : ": ",
+                 error.c_str());
+
+    boost::shared_ptr<Client> client(m_server.findClient(caller));
+    if (!client) {
+        throw runtime_error("unknown client");
+    }
+
+    if (!normal ||
+        m_state != FINAL) {
+        std::string err = error.empty() ?
+            "connection closed unexpectedly" :
+            error;
+        if (m_session) {
+            m_session->setConnectionError(err);
+        }
+        failed(err);
+    } else {
+        m_state = DONE;
+        if (m_session) {
+            m_session->setConnectionError("");
+        }
+    }
+
+    // remove reference to us from client, will destruct *this*
+    // instance!
+    client->detach(this);
 }
 
-void syncevo_report_array_get (SyncevoReportArray *array, int *end_time, GPtrArray **reports)
+void Connection::abort()
 {
-       g_return_if_fail (array);
+    if (!m_abortSent) {
+        sendAbort();
+        m_abortSent = true;
+        m_state = FAILED;
+    }
+}
 
-       if (end_time) {
-               *end_time = g_value_get_int (g_value_array_get_nth (array, 0));
-       }
-       if (reports) {
-               *reports = (GPtrArray*)g_value_get_boxed (g_value_array_get_nth (array, 1));
-       }
+void Connection::shutdown()
+{
+    // trigger removal of this connection by removing all
+    // references to it
+    m_server.detach(this);
 }
 
-void
-syncevo_report_array_free (SyncevoReportArray *array)
+Connection::Connection(DBusServer &server,
+                       const DBusConnectionPtr &conn,
+                       const std::string &sessionID,
+                       const StringMap &peer,
+                       bool must_authenticate) :
+    DBusObjectHelper(conn.get(),
+                     std::string("/org/syncevolution/Connection/") + sessionID,
+                     "org.syncevolution.Connection"),
+    m_server(server),
+    m_peer(peer),
+    m_mustAuthenticate(must_authenticate),
+    m_state(SETUP),
+    m_sessionID(sessionID),
+    m_loop(NULL),
+    sendAbort(*this, "Abort"),
+    m_abortSent(false),
+    reply(*this, "Reply"),
+    m_description(buildDescription(peer))
 {
-       if (array) {
-               g_boxed_free (SYNCEVO_REPORT_ARRAY_TYPE, array);
-       }
+    add(this, &Connection::process, "Process");
+    add(this, &Connection::close, "Close");
+    add(sendAbort);
+    add(reply);
 }
 
+Connection::~Connection()
+{
+    SE_LOG_DEBUG(NULL, NULL, "done with connection to '%s'%s%s%s",
+                 m_description.c_str(),
+                 m_state == DONE ? ", normal shutdown" : " unexpectedly",
+                 m_failure.empty() ? "" : ": ",
+                 m_failure.c_str());
+    try {
+        if (m_state != DONE) {
+            abort();
+        }
+        // DBusTransportAgent waiting? Wake it up.
+        wakeupSession();
+        m_session.use_count();
+        m_session.reset();
+    } catch (...) {
+        // log errors, but do not propagate them because we are
+        // destructing
+        Exception::handle();
+    }
+}
 
-enum {
-       PROGRESS,
-       SERVER_MESSAGE,
-       LAST_SIGNAL
-};
-static guint signals[LAST_SIGNAL] = {0};
+void Connection::ready()
+{
+    // proceed with sync now that our session is ready
+    m_session->sync(m_syncMode, m_sourceModes);
+}
 
-G_DEFINE_TYPE (SyncevoDBusServer, syncevo_dbus_server, G_TYPE_OBJECT);
+/****************** DBusTransportAgent implementation **************/
 
-static gboolean
-shutdown ()
+DBusTransportAgent::DBusTransportAgent(GMainLoop *loop,
+                                       Session &session,
+                                       boost::weak_ptr<Connection> connection) :
+    m_loop(loop),
+    m_session(session),
+    m_connection(connection)
 {
-       g_main_loop_quit (loop);
+}
 
-       return FALSE;
+DBusTransportAgent::~DBusTransportAgent()
+{
+    boost::shared_ptr<Connection> connection = m_connection.lock();
+    if (connection) {
+        connection->shutdown();
+    }
 }
 
-static void
-update_shutdown_timer (SyncevoDBusServer *obj)
+void DBusTransportAgent::send(const char *data, size_t len)
 {
-       if (obj->shutdown_timeout_src > 0)
-               g_source_remove (obj->shutdown_timeout_src);
+    boost::shared_ptr<Connection> connection = m_connection.lock();
+
+    if (!connection) {
+        SE_THROW_EXCEPTION(TransportException,
+                           "D-Bus peer has disconnected");
+    }
+
+    if (connection->m_state != Connection::PROCESSING) {
+        SE_THROW_EXCEPTION(TransportException,
+                           "cannot send to our D-Bus peer");
+    }
+
+    // Change state in advance. If we fail while replying, then all
+    // further resends will fail with the error above.
+    connection->m_state = Connection::WAITING;
+    connection->m_incomingMsg = SharedBuffer();
+
+    // TODO: turn D-Bus exceptions into transport exceptions
+    StringMap meta;
+    meta["URL"] = m_url;
+    connection->reply(std::make_pair(len, reinterpret_cast<const uint8_t *>(data)),
+                      m_type, meta, false, connection->m_sessionID);
+}
 
-       obj->shutdown_timeout_src = g_timeout_add_seconds (120,
-                                                          (GSourceFunc)shutdown,
-                                                          NULL);
+void DBusTransportAgent::shutdown()
+{
+    boost::shared_ptr<Connection> connection = m_connection.lock();
+
+    if (!connection) {
+        SE_THROW_EXCEPTION(TransportException,
+                           "D-Bus peer has disconnected");
+    }
+
+    if (connection->m_state != Connection::FAILED) {
+        // send final, empty message and wait for close
+        connection->m_state = Connection::FINAL;
+        connection->reply(std::pair<size_t, const uint8_t *>(0, 0),
+                          "", StringMap(),
+                          true, connection->m_sessionID);
+    }
 }
 
-void
-emit_progress (const char *source,
-                      int type,
-                      int extra1,
-                      int extra2,
-                      int extra3,
-                      gpointer data)
+void DBusTransportAgent::doWait(boost::shared_ptr<Connection> &connection)
 {
-       SyncevoDBusServer *obj = (SyncevoDBusServer *)data;
+    // let Connection wake us up when it has a reply or
+    // when it closes down
+    connection->m_loop = m_loop;
 
-       g_signal_emit (obj, signals[PROGRESS], 0,
-                      obj->server,
-                      source,
-                      type,
-                      extra1,
-                      extra2,
-                      extra3);
+    // release our reference so that the Connection instance can
+    // be destructed when requested by the D-Bus peer
+    connection.reset();
+
+    // TODO: setup regular callback
+
+    // now wait
+    g_main_loop_run(m_loop);
 }
 
-void
-emit_server_message (const char *message,
-                     gpointer data)
+DBusTransportAgent::Status DBusTransportAgent::wait(bool noReply)
 {
-       SyncevoDBusServer *obj = (SyncevoDBusServer *)data;
+    boost::shared_ptr<Connection> connection = m_connection.lock();
+
+    if (!connection) {
+        SE_THROW_EXCEPTION(TransportException,
+                           "D-Bus peer has disconnected");
+    }
+
+    switch (connection->m_state) {
+    case Connection::PROCESSING:
+        m_incomingMsg = connection->m_incomingMsg;
+        m_incomingMsgType = connection->m_incomingMsgType;
+        return GOT_REPLY;
+        break;
+    case Connection::FINAL:
+        doWait(connection);
+
+        // if the connection is still available, then keep waiting
+        connection = m_connection.lock();
+        if (connection) {
+            return ACTIVE;
+        } else if (m_session.getConnectionError().empty()) {
+            return INACTIVE;
+        } else {
+            SE_THROW_EXCEPTION(TransportException, m_session.getConnectionError());
+            return FAILED;
+        }
+        break;
+    case Connection::WAITING:
+        if (noReply) {
+            // message is sent as far as we know, so return
+            return INACTIVE;
+        }
+
+        doWait(connection);
+
+        // tell caller to check again
+        return ACTIVE;
+        break;
+    case Connection::DONE:
+        if (!noReply) {
+            SE_THROW_EXCEPTION(TransportException,
+                               "internal error: transport has shut down, can no longer receive reply");
+        }
+        
+        return CLOSED;
+    default:
+        SE_THROW_EXCEPTION(TransportException,
+                           "internal error: send() on connection which is not ready");
+        break;
+    }
+
+    return FAILED;
+}
 
-       g_signal_emit (obj, signals[SERVER_MESSAGE], 0,
-                      obj->server,
-                      message);
+void DBusTransportAgent::getReply(const char *&data, size_t &len, std::string &contentType)
+{
+    data = m_incomingMsg.get();
+    len = m_incomingMsg.size();
+    contentType = m_incomingMsgType;
 }
 
-#ifdef USE_GNOME_KEYRING
-char*
-need_password (const char *username,
-               const char *server_url,
-               gpointer data)
+
+/********************** DBusServer implementation ******************/
+
+void DBusServer::clientGone(Client *c)
 {
-       char *password = NULL;
-       const char *server = NULL;
-       GnomeKeyringResult res;
+    for(Clients_t::iterator it = m_clients.begin();
+        it != m_clients.end();
+        ++it) {
+        if (it->second.get() == c) {
+            SE_LOG_DEBUG(NULL, NULL, "D-Bus client %s has disconnected",
+                         c->m_ID.c_str());
+            m_clients.erase(it);
+            return;
+        }
+    }
+    SE_LOG_DEBUG(NULL, NULL, "unknown client has disconnected?!");
+}
 
-       server = strstr (server_url, "://");
-       if (server)
-               server = server + 3;
+std::string DBusServer::getNextSession()
+{
+    // Make the session ID somewhat random. This protects to
+    // some extend against injecting unwanted messages into the
+    // communication.
+    m_lastSession++;
+    if (!m_lastSession) {
+        m_lastSession++;
+    }
+    return StringPrintf("%u%u", rand(), m_lastSession);
+}
 
-       if (!server)
-               return NULL;
+void DBusServer::attachClient(const Caller_t &caller,
+                              const boost::shared_ptr<Watch> &watch)
+{
+    // TODO: implement idle detection and automatic shutdown of the server
+}
 
-       res = gnome_keyring_find_password_sync (GNOME_KEYRING_NETWORK_PASSWORD,
-                                               &password,
-                                               "user", username,
-                                               "server", server,
-                                               NULL);
+void DBusServer::detachClient(const Caller_t &caller)
+{
+}
 
-       switch (res) {
-       case GNOME_KEYRING_RESULT_OK:
-       case GNOME_KEYRING_RESULT_NO_MATCH:
-               break;
-       default:
-               g_warning ("Failed to get password from keyring: %s", 
-                          gnome_keyring_result_to_message (res));
-               break;
-       }
+void DBusServer::connect(const Caller_t &caller,
+                         const boost::shared_ptr<Watch> &watch,
+                         const StringMap &peer,
+                         bool must_authenticate,
+                         const std::string &session,
+                         DBusObject_t &object)
+{
+    if (!session.empty()) {
+        // reconnecting to old connection is not implemented yet
+        throw std::runtime_error("not implemented");
+    }
+    std::string new_session = getNextSession();
+
+    boost::shared_ptr<Connection> c(new Connection(*this,
+                                                   getConnection(),
+                                                   new_session,
+                                                   peer,
+                                                   must_authenticate));
+    SE_LOG_DEBUG(NULL, NULL, "connecting D-Bus client %s with connection %s '%s'",
+                 caller.c_str(),
+                 c->getPath(),
+                 c->m_description.c_str());
+        
+    boost::shared_ptr<Client> client = addClient(getConnection(),
+                                                 caller,
+                                                 watch);
+    client->attach(c);
+    c->activate();
+
+    object = c->getPath();
+}
 
-       return password;
+void DBusServer::startSession(const Caller_t &caller,
+                              const boost::shared_ptr<Watch> &watch,
+                              const std::string &server,
+                              DBusObject_t &object)
+{
+    boost::shared_ptr<Client> client = addClient(getConnection(),
+                                                 caller,
+                                                 watch);
+    std::string new_session = getNextSession();   
+    boost::shared_ptr<Session> session(new Session(*this,
+                                                   "is this a client or server session?",
+                                                   server,
+                                                   new_session));
+    client->attach(session);
+    session->activate();
+    enqueue(session);
+    object = session->getPath();
 }
-#endif
 
-gboolean 
-check_for_suspend (gpointer data)
-{
-       SyncevoDBusServer *obj = (SyncevoDBusServer *)data;
-
-       return obj->aborted;
-}
-
-static gboolean 
-do_sync (SyncevoDBusServer *obj)
-{
-       int ret;
-
-       try {
-               SyncReport report;
-               ret = (*obj->client).sync(&report);
-               if (ret != 0) {
-                       g_printerr ("sync returned error %d\n", ret);
-               }
-       } catch (...) {
-               g_printerr ("sync failed (non-existing server?)\n");
-               ret = -1;
-       }
-
-       /* adding a progress signal on top of synthesis ones */
-       g_signal_emit (obj, signals[PROGRESS], 0,
-                      obj->server,
-                      NULL,
-                      -1,
-                      ret,
-                      0,
-                      0);
-
-       delete obj->client;
-       g_free (obj->server);
-       obj->server = NULL;
-       obj->sources = NULL;
-
-       /* shutdown after a moment of inactivity */
-       update_shutdown_timer (obj);
-
-       return FALSE;
-}
-
-static gboolean  
-syncevo_start_sync (SyncevoDBusServer *obj, 
-                    char *server,
-                    GPtrArray *sources,
-                    GError **error)
-{
-       if (obj->server) {
-               *error = g_error_new (SYNCEVO_DBUS_ERROR,
-                                     SYNCEVO_DBUS_ERROR_INVALID_CALL,
-                                     "Sync already in progress. Concurrent syncs are currently not supported");
-               return FALSE;
-       }
-       if (!server) {
-               *error = g_error_new (SYNCEVO_DBUS_ERROR,
-                                     SYNCEVO_DBUS_ERROR_MISSING_ARGS, 
-                                     "Server argument must be set");
-               return FALSE;
-       }
-
-       /* don't auto-shutdown while syncing */
-       if (obj->shutdown_timeout_src > 0) {
-               g_source_remove (obj->shutdown_timeout_src);
-               obj->shutdown_timeout_src = 0;
-       }
-
-       obj->aborted = FALSE;
-       obj->server = g_strdup (server);
-
-       map<string,int> source_map;
-       g_ptr_array_foreach (sources, (GFunc)syncevo_source_add_to_map, &source_map);
-
-#ifdef USE_GNOME_KEYRING
-       obj->client = new DBusSyncClient (string (server), source_map, 
-                                         emit_progress, emit_server_message, need_password, check_for_suspend,
-                                         obj);
-#else
-       obj->client = new DBusSyncClient (string (server), source_map, 
-                                         emit_progress, emit_server_message, NULL, check_for_suspend,
-                                         obj);
-#endif
+void DBusServer::checkPresence(const std::string &server,
+                               std::string &status,
+                               std::vector<std::string> &transports)
+{
+    // TODO: implement this, right now always return status = "" = available
+}
 
-       g_idle_add ((GSourceFunc)do_sync, obj); 
+void DBusServer::getSessions(std::vector<std::string> &sessions)
+{
+    sessions.reserve(m_workQueue.size() + 1);
+    if (m_activeSession) {
+        sessions.push_back(m_activeSession->getPath());
+    }
+    BOOST_FOREACH(boost::weak_ptr<Session> &session, m_workQueue) {
+        boost::shared_ptr<Session> s = session.lock();
+        if (s) {
+            sessions.push_back(s->getPath());
+        }
+    }
+}
 
-       return TRUE;
+DBusServer::DBusServer(GMainLoop *loop, const DBusConnectionPtr &conn) :
+    DBusObjectHelper(conn.get(), "/org/syncevolution/Server", "org.syncevolution.Server"),
+    m_loop(loop),
+    m_lastSession(time(NULL)),
+    m_activeSession(NULL),
+    sessionChanged(*this, "SessionChanged"),
+    presence(*this, "Presence")
+{
+    struct timeval tv;
+    gettimeofday(&tv, NULL);
+    srand(tv.tv_usec);
+    add(this, &DBusServer::attachClient, "Attach");
+    add(this, &DBusServer::detachClient, "Detach");
+    add(this, &DBusServer::connect, "Connect");
+    add(this, &DBusServer::startSession, "StartSession");
+    add(&ReadOperations::getConfigs, "GetConfigs");
+    add(this, &DBusServer::getConfig, "GetConfig");
+    add(this, &DBusServer::getReports, "GetReports");
+    add(this, &DBusServer::checkSource, "CheckSource");
+    add(this, &DBusServer::getDatabases, "GetDatabases");
+    add(this, &DBusServer::checkPresence, "CheckPresence");
+    add(this, &DBusServer::getSessions, "GetSessions");
+    add(sessionChanged);
+    add(presence);
 }
 
-static gboolean 
-syncevo_abort_sync (SyncevoDBusServer *obj,
-                            char *server,
-                            GError **error)
+DBusServer::~DBusServer()
 {
-       if (!server) {
-               *error = g_error_new (SYNCEVO_DBUS_ERROR,
-                                     SYNCEVO_DBUS_ERROR_MISSING_ARGS, 
-                                     "Server variable must be set");
-               return FALSE;
-       }
+    // make sure all other objects are gone before destructing ourselves
+    m_syncSession.reset();
+    m_workQueue.clear();
+    m_clients.clear();
+}
 
-       if ((!obj->server) || strcmp (server, obj->server) != 0) {
-               *error = g_error_new (SYNCEVO_DBUS_ERROR,
-                                     SYNCEVO_DBUS_ERROR_INVALID_CALL, 
-                                     "Not syncing server '%s'", server);
-               return FALSE;
-       }
+void DBusServer::run()
+{
+    while (!shutdownRequested) {
+        if (!m_activeSession ||
+            !m_activeSession->readyToRun()) {
+            g_main_loop_run(m_loop);
+        }
+        if (m_activeSession &&
+            m_activeSession->readyToRun()) {
+            // this session must be owned by someone, otherwise
+            // it would not be set as active session
+            boost::shared_ptr<Session> session = m_activeSessionRef.lock();
+            if (!session) {
+                throw runtime_error("internal error: session no longer available");
+            }
+            try {
+                // ensure that the session doesn't go away
+                m_syncSession.swap(session);
+                m_activeSession->run();
+            } catch (const std::exception &ex) {
+                SE_LOG_ERROR(NULL, NULL, "%s", ex.what());
+            } catch (...) {
+                SE_LOG_ERROR(NULL, NULL, "unknown error");
+            }
+            session.swap(m_syncSession);
+            dequeue(session.get());
+        }
+    }
+}
 
-       obj->aborted = TRUE;
 
-       return TRUE;
+/**
+ * look up client by its ID
+ */
+boost::shared_ptr<Client> DBusServer::findClient(const Caller_t &ID)
+{
+    for(Clients_t::iterator it = m_clients.begin();
+        it != m_clients.end();
+        ++it) {
+        if (it->second->m_ID == ID) {
+            return it->second;
+        }
+    }
+    return boost::shared_ptr<Client>();
 }
 
-static gboolean 
-syncevo_get_servers (SyncevoDBusServer *obj,
-                     GPtrArray **servers,
-                     GError **error)
+boost::shared_ptr<Client> DBusServer::addClient(const DBusConnectionPtr &conn,
+                                                const Caller_t &ID,
+                                                const boost::shared_ptr<Watch> &watch)
 {
-       if (!servers) {
-               *error = g_error_new (SYNCEVO_DBUS_ERROR,
-                                     SYNCEVO_DBUS_ERROR_MISSING_ARGS, 
-                                     "servers argument must be set");
-               return FALSE;
-       }
+    boost::shared_ptr<Client> client(findClient(ID));
+    if (client) {
+        return client;
+    }
+    client.reset(new Client(ID));
+    // add to our list *before* checking that peer exists, so
+    // that clientGone() can remove it if the check fails
+    m_clients.push_back(std::make_pair(watch, client));
+    watch->setCallback(boost::bind(&DBusServer::clientGone, this, client.get()));
+    return client;
+}
+
 
-       *servers = g_ptr_array_new ();
-
-       SyncConfig::ServerList list = SyncConfig::getServers();
+void DBusServer::detach(Resource *resource)
+{
+    BOOST_FOREACH(const Clients_t::value_type &client_entry,
+                  m_clients) {
+        client_entry.second->detachAll(resource);
+    }
+}
 
-       BOOST_FOREACH(const SyncConfig::ServerList::value_type &server,list) {
-               char *name = NULL;
-               char *url = NULL;
-               char *icon = NULL;
-               gboolean ready = TRUE;
-               SyncevoServer *srv;
+void DBusServer::enqueue(const boost::shared_ptr<Session> &session)
+{
+    WorkQueue_t::iterator it = m_workQueue.end();
+    while (it != m_workQueue.begin()) {
+        --it;
+        if (it->lock()->getPriority() <= session->getPriority()) {
+            ++it;
+            break;
+        }
+    }
+    m_workQueue.insert(it, session);
+
+    checkQueue();
+}
 
-               boost::shared_ptr<SyncConfig> config (SyncConfig::createServerTemplate (server.first));
-               url = icon = NULL;
-               if (config.get()) {
-                       url = g_strdup (config->getWebURL().c_str());
-                       icon = g_strdup (config->getIconURI().c_str());
-                       ready = config->getConsumerReady();
-               }
-               name = g_strdup (server.first.c_str());
-               srv = syncevo_server_new (name, url, icon, ready);
+int DBusServer::killSessions(const std::string &peerDeviceID)
+{
+    int count = 0;
+
+    WorkQueue_t::iterator it = m_workQueue.begin();
+    while (it != m_workQueue.end()) {
+        boost::shared_ptr<Session> session = it->lock();
+        if (session && session->getPeerDeviceID() == peerDeviceID) {
+            SE_LOG_DEBUG(NULL, NULL, "removing pending session %s because it matches deviceID %s",
+                         session->getSessionID().c_str(),
+                         peerDeviceID.c_str());
+            // remove session and its corresponding connection
+            boost::shared_ptr<Connection> c = session->getConnection().lock();
+            if (c) {
+                c->shutdown();
+            }
+            it = m_workQueue.erase(it);
+            count++;
+        } else {
+            ++it;
+        }
+    }
+
+    if (m_activeSession &&
+        m_activeSession->getPeerDeviceID() == peerDeviceID) {
+        SE_LOG_DEBUG(NULL, NULL, "aborting active session %s because it matches deviceID %s",
+                     m_activeSession->getSessionID().c_str(),
+                     peerDeviceID.c_str());
+        try {
+            // abort, even if not necessary right now
+            m_activeSession->abort();
+        } catch (...) {
+            // TODO: catch only that exception which indicates
+            // incorrect use of the function
+        }
+        dequeue(m_activeSession);
+        count++;
+    }
+
+    return count;
+}
 
-               g_ptr_array_add (*servers, srv);
-       }
+void DBusServer::dequeue(Session *session)
+{
+    if (m_syncSession.get() == session) {
+        // This is the running sync session.
+        // It's not in the work queue and we have to
+        // keep it active, so nothing to do.
+        return;
+    }
+
+    for (WorkQueue_t::iterator it = m_workQueue.begin();
+         it != m_workQueue.end();
+         ++it) {
+        if (it->lock().get() == session) {
+            // remove from queue
+            m_workQueue.erase(it);
+            // session was idle, so nothing else to do
+            return;
+        }
+    }
+
+    if (m_activeSession == session) {
+        // The session is releasing the lock, so someone else might
+        // run now.
+        session->setActive(false);
+        sessionChanged(session->getPath(), false);
+        m_activeSession = NULL;
+        m_activeSessionRef.reset();
+        checkQueue();
+        return;
+    }
+}
 
-       update_shutdown_timer (obj);
-
-       return TRUE;
-}
-
-static gboolean 
-syncevo_get_templates (SyncevoDBusServer *obj,
-                       GPtrArray **templates,
-                       GError **error)
-{
-       if (!templates) {
-               *error = g_error_new (SYNCEVO_DBUS_ERROR,
-                                     SYNCEVO_DBUS_ERROR_MISSING_ARGS, 
-                                     "templates argument must be set");
-               return FALSE;
-       }
-
-       *templates = g_ptr_array_new ();
-
-       SyncConfig::ServerList list = SyncConfig::getServerTemplates();
-
-       BOOST_FOREACH(const SyncConfig::ServerList::value_type &server,list) {
-               char *name, *url, *icon;
-               gboolean ready;
-               SyncevoServer *temp;
-
-               boost::shared_ptr<SyncConfig> config (SyncConfig::createServerTemplate (server.first));
-               name = g_strdup (server.first.c_str());
-               url = g_strdup (config->getWebURL().c_str());
-               icon = g_strdup (config->getIconURI().c_str());
-               ready = config->getConsumerReady();
-               temp = syncevo_server_new (name, url, icon, ready);
-
-               g_ptr_array_add (*templates, temp);
-       }
-
-       update_shutdown_timer (obj);
-
-       return TRUE;
-}
-
-static gboolean 
-syncevo_get_template_config (SyncevoDBusServer *obj, 
-                             char *templ, 
-                             GPtrArray **options, 
-                             GError **error)
-{
-       SyncevoOption *option;
-       const char *ready;
-
-       if (!templ || !options) {
-               if (options)
-                       *options = NULL;
-
-               *error = g_error_new (SYNCEVO_DBUS_ERROR,
-                                     SYNCEVO_DBUS_ERROR_MISSING_ARGS, 
-                                     "Template and options arguments must be given");
-               return FALSE;
-       }
-
-       boost::shared_ptr<SyncConfig> config (SyncConfig::createServerTemplate (string (templ)));
-       if (!config.get()) {
-               *options = NULL;
-               *error = g_error_new (SYNCEVO_DBUS_ERROR,
-                                     SYNCEVO_DBUS_ERROR_NO_SUCH_SERVER, 
-                                     "No template '%s' found", templ);
-               return FALSE;
-       }
-
-       *options = g_ptr_array_new ();
-       option = syncevo_option_new (NULL, g_strdup ("syncURL"), g_strdup(config->getSyncURL()));
-       g_ptr_array_add (*options, option);
-       option = syncevo_option_new (NULL, g_strdup("username"), g_strdup(config->getUsername()));
-       g_ptr_array_add (*options, option);
-       option = syncevo_option_new (NULL, g_strdup("webURL"), g_strdup(config->getWebURL().c_str()));
-       g_ptr_array_add (*options, option);
-       option = syncevo_option_new (NULL, g_strdup("iconURI"), g_strdup(config->getIconURI().c_str()));
-       g_ptr_array_add (*options, option);
-
-       ready = (config->getConsumerReady() ? "yes" : "no");
-       option = syncevo_option_new (NULL, g_strdup("consumerReady"), g_strdup(ready));
-       g_ptr_array_add (*options, option);
-
-       option = syncevo_option_new (NULL, g_strdup("fromTemplate"), g_strdup("yes"));
-       g_ptr_array_add (*options, option);
-
-       list<string> sources = config->getSyncSources();
-       BOOST_FOREACH(const string &name, sources) {
-               gboolean local;
-
-               boost::shared_ptr<SyncSourceConfig> source_config = config->getSyncSourceConfig(name);
-
-               option = syncevo_option_new (g_strdup (name.c_str()), g_strdup ("sync"), g_strdup (source_config->getSync()));
-               g_ptr_array_add (*options, option);
-               option = syncevo_option_new (g_strdup (name.c_str()), g_strdup ("uri"), g_strdup (source_config->getURI()));
-               g_ptr_array_add (*options, option);
-
-               /* check whether we have support locally */
-               SyncSourceParams params(name, config->getSyncSourceNodes(name), "");
-               auto_ptr<SyncSource> syncSource(SyncSource::createSource(params, false));
-               try {
-                       local = FALSE;
-                       if (syncSource.get()) {
-                               syncSource->open();
-                               local = TRUE;
-                       }
-               } catch (...) {}
-               option = syncevo_option_new (g_strdup (name.c_str()), 
-                                            g_strdup ("localDB"), 
-                                            g_strdup_printf ("%d", local));
-               g_ptr_array_add (*options, option);
-       }
-
-       update_shutdown_timer (obj);
-
-       return TRUE;
-}
-
-static gboolean 
-syncevo_get_server_config (SyncevoDBusServer *obj,
-                           char *server,
-                           GPtrArray **options,
-                           GError **error)
-{
-       SyncevoOption *option;
-
-       if (!server || !options) {
-               if (options)
-                       *options = NULL;
-               *error = g_error_new (SYNCEVO_DBUS_ERROR,
-                                     SYNCEVO_DBUS_ERROR_MISSING_ARGS, 
-                                     "Server and options arguments must be given");
-               return FALSE;
-       }
-
-       boost::shared_ptr<SyncConfig> from;
-       boost::shared_ptr<SyncConfig> config(new SyncConfig (string (server)));
-       /* if config does not exist, create from template */
-       if (!config->exists()) {
-               from = SyncConfig::createServerTemplate( string (server));
-               if (!from.get()) {
-                       *options = NULL;
-                       *error = g_error_new (SYNCEVO_DBUS_ERROR,
-                                             SYNCEVO_DBUS_ERROR_NO_SUCH_SERVER,
-                                             "No server or template '%s' found", server);
-                       return FALSE;
-               }
-               config->copy(*from, NULL);
-       }
-
-       *options = g_ptr_array_new ();
-       option = syncevo_option_new (NULL, g_strdup ("syncURL"), g_strdup(config->getSyncURL()));
-       g_ptr_array_add (*options, option);
-       option = syncevo_option_new (NULL, g_strdup("username"), g_strdup(config->getUsername()));
-       g_ptr_array_add (*options, option);
-
-       /* get template options if template exists */
-       boost::shared_ptr<SyncConfig> templ = SyncConfig::createServerTemplate( string (server));
-       if (templ.get()) {
-               const char *ready;
-
-               option = syncevo_option_new (NULL, g_strdup("fromTemplate"), g_strdup("yes"));
-               g_ptr_array_add (*options, option);
-               option = syncevo_option_new (NULL, g_strdup("webURL"), g_strdup(templ->getWebURL().c_str()));
-               g_ptr_array_add (*options, option);
-               option = syncevo_option_new (NULL, g_strdup("iconURI"), g_strdup(templ->getIconURI().c_str()));
-               g_ptr_array_add (*options, option);
-
-               ready = templ->getConsumerReady() ? "yes" : "no";
-               option = syncevo_option_new (NULL, g_strdup("consumerReady"), g_strdup (ready));
-               g_ptr_array_add (*options, option);
-       }
-
-       list<string> sources = config->getSyncSources();
-       BOOST_FOREACH(const string &name, sources) {
-               gboolean local;
-
-               boost::shared_ptr<SyncSourceConfig> source_config = config->getSyncSourceConfig(name);
-
-               option = syncevo_option_new (g_strdup (name.c_str()), g_strdup ("sync"), g_strdup (source_config->getSync()));
-               g_ptr_array_add (*options, option);
-               option = syncevo_option_new (g_strdup (name.c_str()), g_strdup ("uri"), g_strdup (source_config->getURI()));
-               g_ptr_array_add (*options, option);
-
-               /* check whether we have support locally */
-               SyncSourceParams params(name, config->getSyncSourceNodes(name), "");
-               auto_ptr<SyncSource> syncSource(SyncSource::createSource(params, false));
-               try {
-                       local = FALSE;
-                       if (syncSource.get()) {
-                               syncSource->open();
-                               local = TRUE;
-                       }
-               } catch (...) {}
-               option = syncevo_option_new (g_strdup (name.c_str()), 
-                                            g_strdup ("localDB"), 
-                                            g_strdup_printf ("%d", local));
-               g_ptr_array_add (*options, option);
-
-       }
-
-       update_shutdown_timer (obj);
-
-       return TRUE;
-}
-
-
-static gboolean 
-syncevo_set_server_config (SyncevoDBusServer *obj,
-                           char *server,
-                           GPtrArray *options,
-                           GError **error)
-{
-       int i;
-       
-       if (!server || !options) {
-               *error = g_error_new (SYNCEVO_DBUS_ERROR,
-                                     SYNCEVO_DBUS_ERROR_MISSING_ARGS, 
-                                     "Server and options parameters must be given");
-               return FALSE;
-       }
-
-       if (obj->server) {
-               *error = g_error_new (SYNCEVO_DBUS_ERROR,
-                                     SYNCEVO_DBUS_ERROR_GENERIC_ERROR, 
-                                     "GetServers is currently not supported when a sync is in progress");
-               return FALSE;
-       }
-
-       boost::shared_ptr<SyncConfig> from(new SyncConfig (string (server)));
-       /* if config does not exist, create from template */
-       if (!from->exists()) {
-               from = SyncConfig::createServerTemplate( string (server));
-               if (!from.get()) {
-                       from = SyncConfig::createServerTemplate( string ("default"));
-               }
-       }
-       boost::shared_ptr<SyncConfig> config(new SyncConfig(string (server)));
-       config->copy(*from, NULL);
-       
-       for (i = 0; i < (int)options->len; i++) {
-               const char *ns, *key, *value;
-               SyncevoOption *option = (SyncevoOption*)g_ptr_array_index (options, i);
-
-               syncevo_option_get (option, &ns, &key, &value);
-
-               if ((!ns || strlen (ns) == 0) && key) {
-                       if (strcmp (key, "syncURL") == 0) {
-                               config->setSyncURL (string (value));
-                       } else if (strcmp (key, "username") == 0) {
-                               config->setUsername (string (value));
-                       } else if (strcmp (key, "password") == 0) {
-                               config->setPassword (string (value));
-                       } else if (strcmp (key, "webURL") == 0) {
-                               config->setWebURL (string (value));
-                       } else if (strcmp (key, "iconURI") == 0) {
-                               config->setIconURI (string (value));
-                       }
-               } else if (ns && key) {
-                       boost::shared_ptr<SyncSourceConfig> source_config = config->getSyncSourceConfig(ns);
-                       if (strcmp (key, "sync") == 0) {
-                               source_config->setSync (string (value));
-                       } else if (strcmp (key, "uri") == 0) {
-                               source_config->setURI (string (value));
-                       }
-               }
-       }
-       config->flush();
-
-       update_shutdown_timer (obj);
-
-       return TRUE;
-}
-
-static gboolean 
-syncevo_remove_server_config (SyncevoDBusServer *obj,
-                              char *server,
-                              GError **error)
-{
-       if (!server) {
-               *error = g_error_new (SYNCEVO_DBUS_ERROR,
-                                     SYNCEVO_DBUS_ERROR_MISSING_ARGS, 
-                                     "Server argument must be given");
-               return FALSE;
-       }
-
-       if (obj->server) {
-               *error = g_error_new (SYNCEVO_DBUS_ERROR,
-                                     SYNCEVO_DBUS_ERROR_GENERIC_ERROR, 
-                                     "RemoveServerConfig is not supported when a sync is in progress");
-               return FALSE;
-       }
-
-       boost::shared_ptr<SyncConfig> config(new SyncConfig (string (server)));
-       if (!config->exists()) {
-               *error = g_error_new (SYNCEVO_DBUS_ERROR,
-                                     SYNCEVO_DBUS_ERROR_NO_SUCH_SERVER,
-                                     "No server '%s' found", server);
-               return FALSE;
-       }
-       config->remove();
-
-       update_shutdown_timer (obj);
-
-       return TRUE;
-}
-
-static gboolean 
-syncevo_get_sync_reports (SyncevoDBusServer *obj, 
-                          char *server, 
-                          int count,
-                          GPtrArray **reports,
-                          GError **error)
-{
-       if (!server) {
-               *error = g_error_new (SYNCEVO_DBUS_ERROR,
-                                     SYNCEVO_DBUS_ERROR_MISSING_ARGS, 
-                                     "Server argument must be given");
-               return FALSE;
-       }
-
-       if (!reports) {
-               *error = g_error_new (SYNCEVO_DBUS_ERROR,
-                                     SYNCEVO_DBUS_ERROR_MISSING_ARGS, 
-                                     "reports argument must be given");
-               return FALSE;
-       }
-
-       SyncContext client (string (server), false);
-       vector<string> dirs;
-       *reports = g_ptr_array_new ();
-
-       client.getSessions (dirs);
-       int start_from = dirs.size () - count;
-       int index = 0;
-
-       BOOST_FOREACH (const string &dir, dirs) {
-               if (index < start_from) {
-                       index++;
-               } else {
-                       SyncevoReportArray * session_report;
-                       GPtrArray *source_reports;
-                       SyncReport report;
-
-                       client.readSessionInfo (dir, report);
-                       source_reports = g_ptr_array_new ();
-
-                       for (SyncReport::iterator it = report.begin(); it != report.end(); ++it) {
-                               SyncevoReport *source_report;
-
-                               SyncSourceReport srcrep = it->second;
-                               source_report = syncevo_report_new (g_strdup (it->first.c_str ()));
-
-                               syncevo_report_set_io (source_report,
-                                                      srcrep.getItemStat (SyncSourceReport::ITEM_LOCAL, 
-                                                                          SyncSourceReport::ITEM_ANY, 
-                                                                          SyncSourceReport::ITEM_SENT_BYTES),
-                                                      srcrep.getItemStat (SyncSourceReport::ITEM_LOCAL, 
-                                                                          SyncSourceReport::ITEM_ANY, 
-                                                                          SyncSourceReport::ITEM_RECEIVED_BYTES));
-                               syncevo_report_set_local (source_report, 
-                                                         srcrep.getItemStat (SyncSourceReport::ITEM_LOCAL, 
-                                                                             SyncSourceReport::ITEM_ADDED, 
-                                                                             SyncSourceReport::ITEM_TOTAL),
-                                                         srcrep.getItemStat (SyncSourceReport::ITEM_LOCAL, 
-                                                                             SyncSourceReport::ITEM_UPDATED, 
-                                                                             SyncSourceReport::ITEM_TOTAL),
-                                                         srcrep.getItemStat (SyncSourceReport::ITEM_LOCAL, 
-                                                                             SyncSourceReport::ITEM_REMOVED, 
-                                                                             SyncSourceReport::ITEM_TOTAL),
-                                                         srcrep.getItemStat (SyncSourceReport::ITEM_LOCAL, 
-                                                                             SyncSourceReport::ITEM_ANY, 
-                                                                             SyncSourceReport::ITEM_REJECT));
-                               syncevo_report_set_remote (source_report, 
-                                                          srcrep.getItemStat (SyncSourceReport::ITEM_REMOTE, 
-                                                                              SyncSourceReport::ITEM_ADDED, 
-                                                                              SyncSourceReport::ITEM_TOTAL),
-                                                          srcrep.getItemStat (SyncSourceReport::ITEM_REMOTE, 
-                                                                              SyncSourceReport::ITEM_UPDATED, 
-                                                                              SyncSourceReport::ITEM_TOTAL),
-                                                          srcrep.getItemStat (SyncSourceReport::ITEM_REMOTE, 
-                                                                              SyncSourceReport::ITEM_REMOVED, 
-                                                                              SyncSourceReport::ITEM_TOTAL),
-                                                          srcrep.getItemStat (SyncSourceReport::ITEM_REMOTE, 
-                                                                              SyncSourceReport::ITEM_ANY, 
-                                                                              SyncSourceReport::ITEM_REJECT));
-                               syncevo_report_set_conflicts (source_report,
-                                                             srcrep.getItemStat (SyncSourceReport::ITEM_REMOTE, 
-                                                                                 SyncSourceReport::ITEM_ANY, 
-                                                                                 SyncSourceReport::ITEM_CONFLICT_CLIENT_WON),
-                                                             srcrep.getItemStat (SyncSourceReport::ITEM_REMOTE, 
-                                                                                 SyncSourceReport::ITEM_ANY, 
-                                                                                 SyncSourceReport::ITEM_CONFLICT_SERVER_WON),
-                                                             srcrep.getItemStat (SyncSourceReport::ITEM_REMOTE, 
-                                                                                 SyncSourceReport::ITEM_ANY, 
-                                                                                 SyncSourceReport::ITEM_CONFLICT_DUPLICATED));
-                               g_ptr_array_add (source_reports, source_report);
-                       }
-                       session_report = syncevo_report_array_new (report.getEnd (), source_reports);
-                       g_ptr_array_add (*reports, session_report);
-               }
-       }
-
-       update_shutdown_timer (obj);
-
-       return TRUE;
-}
-
-static void
-syncevo_dbus_server_class_init(SyncevoDBusServerClass *klass)
-{
-       GError *error = NULL;
-
-       klass->connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
-       if (klass->connection == NULL)
-       {
-               g_warning("Unable to connect to dbus: %s", error->message);
-               g_error_free (error);
-               return;
-       }
-
-       signals[PROGRESS] = g_signal_new ("progress",
-                                         G_TYPE_FROM_CLASS (klass),
-                                         (GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE),
-                                         G_STRUCT_OFFSET (SyncevoDBusServerClass, progress),
-                                         NULL, NULL,
-                                         syncevo_marshal_VOID__STRING_STRING_INT_INT_INT_INT,
-                                         G_TYPE_NONE, 
-                                         6, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT);
-       signals[SERVER_MESSAGE] = g_signal_new ("server-message",
-                                         G_TYPE_FROM_CLASS (klass),
-                                         (GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE),
-                                         G_STRUCT_OFFSET (SyncevoDBusServerClass, server_message),
-                                         NULL, NULL,
-                                         syncevo_marshal_VOID__STRING_STRING,
-                                         G_TYPE_NONE, 
-                                         2, G_TYPE_STRING, G_TYPE_STRING);
-
-       /* dbus_glib_syncevo_object_info is provided in the generated glue file */
-       dbus_g_object_type_install_info (SYNCEVO_TYPE_DBUS_SERVER, &dbus_glib_syncevo_object_info);
-
-       /* register error domain so clients get proper error names with dbus_g_error_get_name() */
-       dbus_g_error_domain_register (SYNCEVO_DBUS_ERROR, NULL, SYNCEVO_DBUS_ERROR_TYPE);
-}
-
-static void
-syncevo_dbus_server_init(SyncevoDBusServer *obj)
-{
-       GError *error = NULL;
-       DBusGProxy *proxy;
-       guint request_ret;
-       SyncevoDBusServerClass *klass = SYNCEVO_DBUS_SERVER_GET_CLASS (obj);
-
-       dbus_g_connection_register_g_object (klass->connection,
-                                            "/org/Moblin/SyncEvolution",
-                                            G_OBJECT (obj));
-
-       proxy = dbus_g_proxy_new_for_name (klass->connection,
-                                          DBUS_SERVICE_DBUS,
-                                          DBUS_PATH_DBUS,
-                                          DBUS_INTERFACE_DBUS);
-
-       if(!org_freedesktop_DBus_request_name (proxy,
-                                              "org.Moblin.SyncEvolution",
-                                              0, &request_ret,
-                                              &error)) {
-               g_warning("Unable to register service: %s", error->message);
-               g_error_free (error);
-       }
-       g_object_unref (proxy);
-
-       update_shutdown_timer (obj);
+void DBusServer::checkQueue()
+{
+    if (m_activeSession) {
+        // still busy
+        return;
+    }
+
+    while (!m_workQueue.empty()) {
+        boost::shared_ptr<Session> session = m_workQueue.front().lock();
+        m_workQueue.pop_front();
+        if (session) {
+            // activate the session
+            m_activeSession = session.get();
+            m_activeSessionRef = session;
+            session->setActive(true);
+            sessionChanged(session->getPath(), true);
+            return;
+        }
+    }
 }
 
+/**************************** main *************************/
+
 void niam(int sig)
 {
-       g_main_loop_quit (loop);
+    shutdownRequested = true;
+    SyncContext::handleSignal(sig);
+    g_main_loop_quit (loop);
 }
 
-int main()
+int main(int argc, char **argv)
 {
-       SyncevoDBusServer *server;
+    try {
+        g_type_init();
+        g_thread_init(NULL);
+        g_set_application_name("SyncEvolution");
+        loop = g_main_loop_new (NULL, FALSE);
+
+        setvbuf(stderr, NULL, _IONBF, 0);
+        setvbuf(stdout, NULL, _IONBF, 0);
 
-       signal(SIGTERM, niam);
-       signal(SIGINT, niam);
+        signal(SIGTERM, niam);
+        signal(SIGINT, niam);
 
-       g_type_init ();
-       g_thread_init (NULL);
-       g_set_application_name ("SyncEvolution");
-       dbus_g_thread_init ();
+        LoggerBase::instance().setLevel(LoggerBase::DEBUG);
 
-       server = (SyncevoDBusServer*)g_object_new (SYNCEVO_TYPE_DBUS_SERVER, NULL);
+        DBusErrorCXX err;
+        DBusConnectionPtr conn = g_dbus_setup_bus(DBUS_BUS_SESSION,
+                                                  "org.syncevolution",
+                                                  &err);
+        if (!conn) {
+            err.throwFailure("g_dbus_setup_bus()");
+        }
 
-       loop = g_main_loop_new (NULL, FALSE);
-       g_main_loop_run (loop);
+        DBusServer server(loop, conn);
+        server.activate();
 
-       g_main_loop_unref (loop);
-       g_object_unref (server);
+        std::cout << argv[0] << " ready to run\n" << std::flush;
+        server.run();
        return 0;
+    } catch ( const std::exception &ex ) {
+        SE_LOG_ERROR(NULL, NULL, "%s", ex.what());
+    } catch (...) {
+        SE_LOG_ERROR(NULL, NULL, "unknown error");
+    }
+
+    return 1;
 }
diff --git a/src/syncevo-dbus-server.h b/src/syncevo-dbus-server.h
deleted file mode 100644 (file)
index 9cde8bf..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2009 Intel Corporation
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) version 3.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301  USA
- */
-
-#ifndef __SYNCEVO_DBUS_SERVER_H
-#define __SYNCEVO_DBUS_SERVER_H
-
-#include <glib-object.h>
-#include <dbus/dbus-glib.h>
-
-typedef struct _SyncevoDBusServer SyncevoDBusServer;
-#include "DBusSyncClient.h"
-
-#define SYNCEVO_TYPE_DBUS_SERVER (syncevo_dbus_server_get_type ())
-#define SYNCEVO_DBUS_SERVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SYNCEVO_TYPE_DBUS_SERVER, SyncevoDBusServerClass))
-
-typedef struct _SyncevoDBusServer {
-       GObject parent_object;
-
-       DBusSyncClient *client;
-       char *server;
-       GPtrArray *sources;
-       
-       gboolean aborted;
-
-       guint shutdown_timeout_src;
-} SyncevoDBusServer;
-
-typedef struct _SyncevoDBusServerClass {
-       GObjectClass parent_class;
-       DBusGConnection *connection;
-       
-       /* DBus signals*/
-       void (*progress) (SyncevoDBusServer *service,
-                         char *server,
-                         char *source,
-                         int type,
-                         int extra1, int extra2, int extra3);
-       void (*server_message) (SyncevoDBusServer *service,
-                               char *server,
-                               char *message);
-} SyncevoDBusServerClass;
-
-GType syncevo_dbus_server_get_type (void);
-
-void
-emit_progress (const char *source,
-               int type,
-               int extra1,
-               int extra2,
-               int extra3, 
-               gpointer data);
-
-void
-emit_server_message (const char *message, 
-                     gpointer data);
-
-gboolean 
-check_for_suspend (gpointer data);
-
-#endif // __SYNCEVO_DBUS_SERVER_H
index 5a6d6e6..de86f58 100644 (file)
@@ -192,11 +192,13 @@ bool Cmdline::run() {
     } else if (m_argc == 1) {
         // no parameters: list databases and short usage
         const SourceRegistry &registry(SyncSource::getSourceRegistry());
+        boost::shared_ptr<FilterConfigNode> sharedNode(new VolatileConfigNode());
         boost::shared_ptr<FilterConfigNode> configNode(new VolatileConfigNode());
         boost::shared_ptr<FilterConfigNode> hiddenNode(new VolatileConfigNode());
         boost::shared_ptr<FilterConfigNode> trackingNode(new VolatileConfigNode());
-        SyncSourceNodes nodes(configNode, hiddenNode, trackingNode);
-        SyncSourceParams params("list", nodes, "");
+        boost::shared_ptr<FilterConfigNode> serverNode(new VolatileConfigNode());
+        SyncSourceNodes nodes(sharedNode, configNode, hiddenNode, trackingNode, serverNode);
+        SyncSourceParams params("list", nodes);
         
         BOOST_FOREACH(const RegisterSyncSource *source, registry) {
             BOOST_FOREACH(const Values::value_type &alias, source->m_typeValues) {
@@ -214,6 +216,8 @@ bool Cmdline::run() {
         usage(false);
     } else if (m_printConfig) {
         boost::shared_ptr<SyncConfig> config;
+        ConfigProps syncFilter;
+        SourceFilters_t sourceFilters;
 
         if (m_template.empty()) {
             if (m_server.empty()) {
@@ -225,18 +229,26 @@ bool Cmdline::run() {
                 m_err << "ERROR: server '" << m_server << "' has not been configured yet." << endl;
                 return false;
             }
+
+            syncFilter = m_syncProps;
+            sourceFilters[""] = m_sourceProps;
         } else {
-            config = SyncConfig::createServerTemplate(m_template);
+            string peer, context;
+            SyncConfig::splitConfigString(SyncConfig::normalizeConfigString(m_template), peer, context);
+
+            config = SyncConfig::createServerTemplate(peer);
             if (!config.get()) {
                 m_err << "ERROR: no configuration template for '" << m_template << "' available." << endl;
                 return false;
             }
+
+            getFilters(context, syncFilter, sourceFilters);
         }
 
         if (m_sources.empty() ||
             m_sources.find("main") != m_sources.end()) {
             boost::shared_ptr<FilterConfigNode> syncProps(config->getProperties());
-            syncProps->setFilter(m_syncProps);
+            syncProps->setFilter(syncFilter);
             dumpProperties(*syncProps, config->getRegistry());
         }
 
@@ -246,9 +258,14 @@ bool Cmdline::run() {
             if (m_sources.empty() ||
                 m_sources.find(name) != m_sources.end()) {
                 m_out << endl << "[" << name << "]" << endl;
-                ConstSyncSourceNodes nodes = config->getSyncSourceNodes(name);
-                boost::shared_ptr<FilterConfigNode> sourceProps(new FilterConfigNode(boost::shared_ptr<const ConfigNode>(nodes.m_configNode)));
-                sourceProps->setFilter(m_sourceProps);
+                SyncSourceNodes nodes = config->getSyncSourceNodes(name);
+                boost::shared_ptr<FilterConfigNode> sourceProps = nodes.getProperties();
+                SourceFilters_t::const_iterator it = sourceFilters.find(name);
+                if (it != sourceFilters.end()) {
+                    sourceProps->setFilter(it->second);
+                } else {
+                    sourceProps->setFilter(sourceFilters[""]);
+                }
                 dumpProperties(*sourceProps, SyncSourceConfig::getRegistry());
             }
         }
@@ -270,16 +287,24 @@ bool Cmdline::run() {
         }
 
         bool fromScratch = false;
+        string peer, context;
+        SyncConfig::splitConfigString(SyncConfig::normalizeConfigString(m_server), peer, context);
 
         // Both config changes and migration are implemented as copying from
         // another config (template resp. old one). Migration also moves
         // the old config.
         boost::shared_ptr<SyncConfig> from;
         if (m_migrate) {
+            string oldContext = context;
             from.reset(new SyncConfig(m_server));
             if (!from->exists()) {
-                m_err << "ERROR: server '" << m_server << "' has not been configured yet." << endl;
-                return false;
+                // for migration into a different context, search for config without context
+                oldContext = "";
+                from.reset(new SyncConfig(peer));
+                if (!from->exists()) {
+                    m_err << "ERROR: server '" << m_server << "' has not been configured yet." << endl;
+                    return false;
+                }
             }
 
             int counter = 0;
@@ -305,26 +330,53 @@ bool Cmdline::run() {
                 counter++;
             }
 
-            from.reset(new SyncConfig(m_server + suffix));
+            from.reset(new SyncConfig(peer + suffix +
+                                      (oldContext.empty() ? "" : "@") +
+                                      oldContext));
         } else {
             from.reset(new SyncConfig(m_server));
             if (!from->exists()) {
                 // creating from scratch, look for template
                 fromScratch = true;
                 string configTemplate = m_template.empty() ? m_server : m_template;
-                from = SyncConfig::createServerTemplate(configTemplate);
+                SyncConfig::splitConfigString(SyncConfig::normalizeConfigString(configTemplate), peer, context);
+                from = SyncConfig::createServerTemplate(peer);
                 if (!from.get()) {
                     m_err << "ERROR: no configuration template for '" << configTemplate << "' available." << endl;
                     dumpServers("Available configuration templates:",
                                 SyncConfig::getServerTemplates());
                     return false;
                 }
+
+                // Templates no longer contain these strings, because
+                // GUIs would have to localize them. For configs created
+                // via the command line, the extra hint that these
+                // properties need to be set is useful, so set these
+                // strings here. They'll get copied into the new
+                // config only if no other value was given on the
+                // command line.
+                if (!from->getUsername()[0]) {
+                    from->setUsername("your SyncML server account name");
+                }
+                if (!from->getPassword()[0]) {
+                    from->setPassword("your SyncML server password");
+                }
             }
         }
 
-        // apply config changes on-the-fly
-        from->setConfigFilter(true, m_syncProps);
-        from->setConfigFilter(false, m_sourceProps);
+        // Apply config changes on-the-fly. Regardless what we do
+        // (changing an existing config, migrating, creating from
+        // a template), existing shared properties in the desired
+        // context must be preserved unless explicitly overwritten.
+        // Therefore read those, update with command line properties,
+        // then set as filter.
+        ConfigProps syncFilter;
+        SourceFilters_t sourceFilters;
+        getFilters(context, syncFilter, sourceFilters);
+        from->setConfigFilter(true, "", syncFilter);
+        BOOST_FOREACH(const SourceFilters_t::value_type &entry, sourceFilters) {
+            from->setConfigFilter(false, entry.first, entry.second);
+        }
 
         // write into the requested configuration, creating it if necessary
         boost::shared_ptr<SyncContext> to(createSyncClient());
@@ -354,7 +406,7 @@ bool Cmdline::run() {
                     }
 
                     // check whether the sync source works
-                    SyncSourceParams params("list", to->getSyncSourceNodes(source), "");
+                    SyncSourceParams params("list", to->getSyncSourceNodes(source));
                     auto_ptr<SyncSource> syncSource(SyncSource::createSource(params, false));
                     if (syncSource.get() == NULL) {
                         disable = "no backend available";
@@ -394,6 +446,16 @@ bool Cmdline::run() {
 
         // done, now write it
         to->flush();
+
+        // also copy .synthesis dir?
+        if (m_migrate) {
+            string fromDir, toDir;
+            fromDir = from->getRootPath() + "/.synthesis";
+            toDir = to->getRootPath() + "/.synthesis";
+            if (isDir(fromDir)) {
+                cp_r(fromDir, toDir);
+            }
+        }
     } else if (m_remove) {
         if (m_dryrun) {
             SyncContext::throwError("--dry-run not supported for removing configurations");
@@ -415,17 +477,78 @@ bool Cmdline::run() {
             return true;
         }
     } else {
-        boost::shared_ptr<SyncContext> client;
-        client.reset(createSyncClient());
-        client->setQuiet(m_quiet);
-        client->setDryRun(m_dryrun);
-        client->setConfigFilter(true, m_syncProps);
-        client->setConfigFilter(false, m_sourceProps);
+        std::set<std::string> unmatchedSources;
+        boost::shared_ptr<SyncContext> context;
+        context.reset(createSyncClient());
+        context->setQuiet(m_quiet);
+        context->setDryRun(m_dryrun);
+        context->setConfigFilter(true, "", m_syncProps);
+        if (m_sources.empty()) {
+            if (m_sourceProps.empty()) {
+                // empty source list, empty source filter => run with
+                // existing configuration without filtering it
+            } else {
+                // Special semantic of 'no source selected': apply
+                // filter only to sources which are
+                // *active*. Configuration of inactive sources is left
+                // unchanged. This way we don't activate sync sources
+                // accidentally when the sync mode is modified
+                // temporarily.
+                BOOST_FOREACH(const std::string &source,
+                              context->getSyncSources()) {
+                    boost::shared_ptr<PersistentSyncSourceConfig> source_config =
+                        context->getSyncSourceConfig(source);
+                    if (strcmp(source_config->getSync(), "disabled")) {
+                        context->setConfigFilter(false, source, m_sourceProps);
+                    }
+                }
+            }
+        } else {
+            // apply (possibly empty) source filter to selected sources
+            BOOST_FOREACH(const std::string &source,
+                          m_sources) {
+                boost::shared_ptr<PersistentSyncSourceConfig> source_config =
+                        context->getSyncSourceConfig(source);
+                if (!source_config || !source_config->exists()) {
+                    // invalid source name in m_sources, remember and
+                    // report this below
+                    unmatchedSources.insert(source);
+                } else if (m_sourceProps.find(SyncSourceConfig::m_sourcePropSync.getName()) ==
+                           m_sourceProps.end()) {
+                    // Sync mode is not set, must override the
+                    // "sync=disabled" set below with the original
+                    // sync mode for the source or (if that is also
+                    // "disabled") with "two-way". The latter is part
+                    // of the command line semantic that listing a
+                    // source activates it.
+                    FilterConfigNode::ConfigFilter filter = m_sourceProps;
+                    string sync = source_config->getSync();
+                    filter[SyncSourceConfig::m_sourcePropSync.getName()] =
+                        sync == "disabled" ? "two-way" : sync;
+                    context->setConfigFilter(false, source, filter);
+                } else {
+                    // sync mode is set, can use m_sourceProps
+                    // directly to apply it
+                    context->setConfigFilter(false, source, m_sourceProps);
+                }
+            }
+
+            // temporarily disable the rest
+            FilterConfigNode::ConfigFilter disabled;
+            disabled[SyncSourceConfig::m_sourcePropSync.getName()] = "disabled";
+            context->setConfigFilter(false, "", disabled);
+        }
+
+        // check whether there were any sources specified which do not exist
+        if (unmatchedSources.size()) {
+            context->throwError(string("no such source(s): ") + boost::join(unmatchedSources, " "));
+        }
+
         if (m_status) {
-            client->status();
+            context->status();
         } else if (m_printSessions) {
             vector<string> dirs;
-            client->getSessions(dirs);
+            context->getSessions(dirs);
             bool first = true;
             BOOST_FOREACH(const string &dir, dirs) {
                 if (first) {
@@ -436,7 +559,7 @@ bool Cmdline::run() {
                 cout << dir << endl;
                 if (!m_quiet) {
                     SyncReport report;
-                    client->readSessionInfo(dir, report);
+                    context->readSessionInfo(dir, report);
                     cout << report;
                 }
             }
@@ -451,10 +574,10 @@ bool Cmdline::run() {
                 usage(false, "Sources must be selected explicitly for --restore to prevent accidental restore.");
                 return false;
             }
-            client->restore(m_restore,
-                            m_after ?
-                            SyncContext::DATABASE_AFTER_SYNC :
-                            SyncContext::DATABASE_BEFORE_SYNC);
+            context->restore(m_restore,
+                             m_after ?
+                             SyncContext::DATABASE_AFTER_SYNC :
+                             SyncContext::DATABASE_BEFORE_SYNC);
         } else {
             if (m_dryrun) {
                 SyncContext::throwError("--dry-run not supported for running a synchronization");
@@ -468,7 +591,7 @@ bool Cmdline::run() {
                 return false;
             }
 
-            return ( client->sync() == STATUS_OK);
+            return (context->sync() == STATUS_OK);
         }
     }
 
@@ -594,6 +717,37 @@ bool Cmdline::listProperties(const ConfigPropertyRegistry &validProps,
     return true;
 }
 
+void Cmdline::getFilters(const string &context,
+                         ConfigProps &syncFilter,
+                         map<string, ConfigProps> &sourceFilters)
+{
+    // Read from context. If it does not exist, we simply set no properties
+    // as filter. Previously there was a check for existance, but that was
+    // flawed because it ignored the global property "defaultPeer".
+    boost::shared_ptr<SyncConfig> shared(new SyncConfig(string("@") + context));
+    shared->getProperties()->readProperties(syncFilter);
+    BOOST_FOREACH(StringPair entry, m_syncProps) {
+        syncFilter[entry.first] = entry.second;
+    }
+
+    BOOST_FOREACH(std::string source, shared->getSyncSources()) {
+        SyncSourceNodes nodes = shared->getSyncSourceNodes(source, "");
+        ConfigProps &props = sourceFilters[source];
+        nodes.getProperties()->readProperties(props);
+
+        // Special case "type" property: the value in the context
+        // is not preserved. Every new peer must ensure that
+        // its own value is compatible (= same backend) with
+        // the other peers.
+        props.erase("type");
+
+        BOOST_FOREACH(StringPair entry, m_sourceProps) {
+            props[entry.first] = entry.second;
+        }
+    }
+    sourceFilters[""] = m_sourceProps;
+}
+
 void Cmdline::listSources(SyncSource &syncSource, const string &header)
 {
     m_out << header << ":\n";
@@ -814,7 +968,7 @@ void Cmdline::usage(bool full, const string &error, const string &param)
 }
 
 SyncContext* Cmdline::createSyncClient() {
-    return new SyncContext(m_server, true, m_sources);
+    return new SyncContext(m_server, true);
 }
 
 #ifdef ENABLE_UNIT_TESTS
@@ -899,7 +1053,8 @@ static bool isPropAssignment(const string &buffer) {
 }
 
 // remove pure comment lines from buffer,
-// also empty lines
+// also empty lines,
+// also defaultPeer (because reference properties do not include global props)
 static string filterConfig(const string &buffer)
 {
     ostringstream res;
@@ -911,6 +1066,7 @@ static string filterConfig(const string &buffer)
          ++it) {
         string line = boost::copy_range<string>(*it);
         if (!line.empty() &&
+            line.find("defaultPeer =") == line.npos &&
             (!boost::starts_with(line, "# ") ||
              isPropAssignment(line.substr(2)))) {
             res << line << endl;
@@ -920,6 +1076,21 @@ static string filterConfig(const string &buffer)
     return res.str();
 }
 
+static string injectValues(const string &buffer)
+{
+    string res = buffer;
+
+    // username/password not set in templates, only in configs created via
+    // the command line
+    boost::replace_first(res,
+                         "# username = ",
+                         "username = your SyncML server account name");
+    boost::replace_first(res,
+                         "# password = ",
+                         "password = your SyncML server password");
+    return res;
+}
+
 // remove lines indented with spaces
 static string filterIndented(const string &buffer)
 {
@@ -944,7 +1115,42 @@ static string filterIndented(const string &buffer)
     return res.str();
 }
 
-// convert the internal config dump to .ini style
+// sort lines by file, preserving order inside each line
+static void sortConfig(string &config)
+{
+    // file name, line number, property
+    typedef pair<string, pair<int, string> > line_t;
+    vector<line_t> lines;
+    typedef boost::split_iterator<string::iterator> string_split_iterator;
+    int linenr = 0;
+    for (string_split_iterator it =
+             boost::make_split_iterator(config, boost::first_finder("\n", boost::is_iequal()));
+         it != string_split_iterator();
+         ++it, ++linenr) {
+        string line(it->begin(), it->end());
+        if (line.empty()) {
+            continue;
+        }
+
+        size_t colon = line.find(':');
+        string prefix = line.substr(0, colon);
+        lines.push_back(make_pair(prefix, make_pair(linenr, line.substr(colon))));
+    }
+
+    // stable sort because of line number
+    sort(lines.begin(), lines.end());
+
+    size_t len = config.size();
+    config.resize(0);
+    config.reserve(len);
+    BOOST_FOREACH(const line_t &line, lines) {
+        config += line.first;
+        config += line.second.second;
+        config += "\n";
+    }
+}
+
+// convert the internal config dump to .ini style (--print-config)
 static string internalToIni(const string &config)
 {
     ostringstream res;
@@ -962,10 +1168,20 @@ static string internalToIni(const string &config)
 
         size_t colon = line.find(':');
         string prefix = line.substr(0, colon);
+
+        // internal values are not part of the --print-config output
         if (boost::contains(prefix, ".internal.ini") ||
             boost::contains(line, "= internal value")) {
             continue;
         }
+
+        // --print-config also doesn't duplicate the "type" property
+        // => remove the shared property
+        if (boost::contains(line, ":type = ") &&
+            boost::starts_with(line, "sources/")) {
+            continue;
+        }
+
         // sources/<name>/config.ini or
         // spds/sources/<name>/config.ini
         size_t endslash = prefix.rfind('/');
@@ -974,8 +1190,9 @@ static string internalToIni(const string &config)
             if (slash != line.npos) {
                 string newsource = prefix.substr(slash + 1, endslash - slash - 1);
                 if (newsource != section &&
+                    prefix.find("/sources/") != prefix.npos &&
                     newsource != "syncml") {
-                    res << endl << "[" << newsource << "]" << endl;
+                    res << "[" << newsource << "]" << endl;
                     section = newsource;
                 }
             }
@@ -1015,6 +1232,7 @@ class CmdlineTest : public CppUnit::TestFixture {
     CPPUNIT_TEST(testSetupSynthesis);
     CPPUNIT_TEST(testPrintServers);
     CPPUNIT_TEST(testPrintConfig);
+    CPPUNIT_TEST(testPrintFileTemplates);
     CPPUNIT_TEST(testTemplate);
     CPPUNIT_TEST(testSync);
     CPPUNIT_TEST(testConfigure);
@@ -1026,61 +1244,76 @@ class CmdlineTest : public CppUnit::TestFixture {
 public:
     CmdlineTest() :
         m_testDir("CmdlineTest"),
-        m_scheduleWorldConfig(".internal.ini:# HashCode = 0\n"
-                              ".internal.ini:# ConfigDate = \n"
-                              "config.ini:syncURL = http://sync.scheduleworld.com/funambol/ds\n"
-                              "config.ini:username = your SyncML server account name\n"
-                              "config.ini:password = your SyncML server password\n"
+        // properties sorted by the order in which they are defined
+        // in the sync and sync source property registry
+        m_scheduleWorldConfig("peers/scheduleworld/.internal.ini:# HashCode = 0\n"
+                              "peers/scheduleworld/.internal.ini:# ConfigDate = \n"
+                              "peers/scheduleworld/.internal.ini:# lastNonce = \n"
+                              "peers/scheduleworld/.internal.ini:# deviceData = \n"
+                              "peers/scheduleworld/config.ini:syncURL = http://sync.scheduleworld.com/funambol/ds\n"
+                              "peers/scheduleworld/config.ini:username = your SyncML server account name\n"
+                              "peers/scheduleworld/config.ini:password = your SyncML server password\n"
                               "config.ini:# logdir = \n"
-                              "config.ini:# loglevel = 0\n"
-                              "config.ini:# printChanges = 1\n"
+                              "peers/scheduleworld/config.ini:# loglevel = 0\n"
+                              "peers/scheduleworld/config.ini:# printChanges = 1\n"
                               "config.ini:# maxlogdirs = 10\n"
-                              "config.ini:# useProxy = 0\n"
-                              "config.ini:# proxyHost = \n"
-                              "config.ini:# proxyUsername = \n"
-                              "config.ini:# proxyPassword = \n"
-                              "config.ini:# clientAuthType = md5\n"
-                              "config.ini:# RetryDuration = 300\n"
-                              "config.ini:# RetryInterval = 60\n"
+                              "peers/scheduleworld/config.ini:# useProxy = 0\n"
+                              "peers/scheduleworld/config.ini:# proxyHost = \n"
+                              "peers/scheduleworld/config.ini:# proxyUsername = \n"
+                              "peers/scheduleworld/config.ini:# proxyPassword = \n"
+                              "peers/scheduleworld/config.ini:# clientAuthType = md5\n"
+                              "peers/scheduleworld/config.ini:# RetryDuration = 300\n"
+                              "peers/scheduleworld/config.ini:# RetryInterval = 60\n"
+                              "peers/scheduleworld/config.ini:# remoteIdentifier = \n"
+                              "peers/scheduleworld/config.ini:# PeerIsClient = 0\n"
                               "config.ini:deviceId = fixed-devid\n" /* this is not the default! */
-                              "config.ini:# enableWBXML = 1\n"
-                              "config.ini:# maxMsgSize = 20000\n"
-                              "config.ini:# maxObjSize = 4000000\n"
-                              "config.ini:# enableCompression = 0\n"
-                              "config.ini:# SSLServerCertificates = \n"
-                              "config.ini:# SSLVerifyServer = 1\n"
-                              "config.ini:# SSLVerifyHost = 1\n"
-                              "config.ini:WebURL = http://www.scheduleworld.com\n"
-                              "config.ini:# IconURI = \n"
-                              "config.ini:ConsumerReady = 1\n"
-                              "sources/addressbook/.internal.ini:# last = 0\n"
-                              "sources/addressbook/config.ini:sync = two-way\n"
+                              "peers/scheduleworld/config.ini:# remoteDeviceId = \n"
+                              "peers/scheduleworld/config.ini:# enableWBXML = 1\n"
+                              "peers/scheduleworld/config.ini:# maxMsgSize = 20000\n"
+                              "peers/scheduleworld/config.ini:# maxObjSize = 4000000\n"
+                              "peers/scheduleworld/config.ini:# enableCompression = 0\n"
+                              "peers/scheduleworld/config.ini:# SSLServerCertificates = \n"
+                              "peers/scheduleworld/config.ini:# SSLVerifyServer = 1\n"
+                              "peers/scheduleworld/config.ini:# SSLVerifyHost = 1\n"
+                              "peers/scheduleworld/config.ini:WebURL = http://sync.scheduleworld.com\n"
+                              "peers/scheduleworld/config.ini:# IconURI = \n"
+                              "peers/scheduleworld/config.ini:ConsumerReady = 1\n"
+
+                              "peers/scheduleworld/sources/addressbook/.internal.ini:# adminData = \n"
+                              "peers/scheduleworld/sources/addressbook/config.ini:sync = two-way\n"
                               "sources/addressbook/config.ini:type = addressbook:text/vcard\n"
+                              "peers/scheduleworld/sources/addressbook/config.ini:type = addressbook:text/vcard\n"
                               "sources/addressbook/config.ini:# evolutionsource = \n"
-                              "sources/addressbook/config.ini:uri = card3\n"
+                              "peers/scheduleworld/sources/addressbook/config.ini:uri = card3\n"
                               "sources/addressbook/config.ini:# evolutionuser = \n"
                               "sources/addressbook/config.ini:# evolutionpassword = \n"
-                              "sources/calendar/.internal.ini:# last = 0\n"
-                              "sources/calendar/config.ini:sync = two-way\n"
+
+                              "peers/scheduleworld/sources/calendar/.internal.ini:# adminData = \n"
+                              "peers/scheduleworld/sources/calendar/config.ini:sync = two-way\n"
                               "sources/calendar/config.ini:type = calendar\n"
+                              "peers/scheduleworld/sources/calendar/config.ini:type = calendar\n"
                               "sources/calendar/config.ini:# evolutionsource = \n"
-                              "sources/calendar/config.ini:uri = cal2\n"
+                              "peers/scheduleworld/sources/calendar/config.ini:uri = cal2\n"
                               "sources/calendar/config.ini:# evolutionuser = \n"
                               "sources/calendar/config.ini:# evolutionpassword = \n"
-                              "sources/memo/.internal.ini:# last = 0\n"
-                              "sources/memo/config.ini:sync = two-way\n"
+
+                              "peers/scheduleworld/sources/memo/.internal.ini:# adminData = \n"
+                              "peers/scheduleworld/sources/memo/config.ini:sync = two-way\n"
                               "sources/memo/config.ini:type = memo\n"
+                              "peers/scheduleworld/sources/memo/config.ini:type = memo\n"
                               "sources/memo/config.ini:# evolutionsource = \n"
-                              "sources/memo/config.ini:uri = note\n"
+                              "peers/scheduleworld/sources/memo/config.ini:uri = note\n"
                               "sources/memo/config.ini:# evolutionuser = \n"
                               "sources/memo/config.ini:# evolutionpassword = \n"
-                              "sources/todo/.internal.ini:# last = 0\n"
-                              "sources/todo/config.ini:sync = two-way\n"
+
+                              "peers/scheduleworld/sources/todo/.internal.ini:# adminData = \n"
+                              "peers/scheduleworld/sources/todo/config.ini:sync = two-way\n"
                               "sources/todo/config.ini:type = todo\n"
+                              "peers/scheduleworld/sources/todo/config.ini:type = todo\n"
                               "sources/todo/config.ini:# evolutionsource = \n"
-                              "sources/todo/config.ini:uri = task2\n"
+                              "peers/scheduleworld/sources/todo/config.ini:uri = task2\n"
                               "sources/todo/config.ini:# evolutionuser = \n"
-                              "sources/todo/config.ini:# evolutionpassword = \n")
+                              "sources/todo/config.ini:# evolutionpassword = ")
     {
 #ifdef ENABLE_LIBSOUP
         // path to SSL certificates has to be set only for libsoup
@@ -1127,16 +1360,24 @@ protected:
     }
 
     /** create new configurations */
-    void testSetupScheduleWorld() {
+    void testSetupScheduleWorld() { doSetupScheduleWorld(false); }
+    void doSetupScheduleWorld(bool shared) {
         string root;
+        ScopedEnvChange templates("SYNCEVOLUTION_TEMPLATE_DIR", "/dev/null");
         ScopedEnvChange xdg("XDG_CONFIG_HOME", m_testDir);
         ScopedEnvChange home("HOME", m_testDir);
 
         root = m_testDir;
-        root += "/syncevolution/scheduleworld";
+        root += "/syncevolution/default";
+        string peer;
+        if (shared) {
+            peer = root + "/peers/scheduleworld";
+        } else {
+            peer = root;
+        }
 
         {
-            rm_r(root);
+            rm_r(peer);
             TestCmdline cmdline("--configure",
                                 "--sync-property", "proxyHost = proxy",
                                 "scheduleworld",
@@ -1146,6 +1387,7 @@ protected:
             string res = scanFiles(root);
             removeRandomUUID(res);
             string expected = ScheduleWorldConfig();
+            sortConfig(expected);
             boost::replace_first(expected,
                                  "# proxyHost = ",
                                  "proxyHost = proxy");
@@ -1159,24 +1401,27 @@ protected:
         }
 
         {
-            rm_r(root);
+            rm_r(peer);
             TestCmdline cmdline("--configure",
                                 "--sync-property", "deviceID = fixed-devid",
                                 "scheduleworld",
                                 NULL);
             cmdline.doit();
             string res = scanFiles(root);
-            CPPUNIT_ASSERT_EQUAL_DIFF(ScheduleWorldConfig(), res);
+            string expected = ScheduleWorldConfig();
+            sortConfig(expected);
+            CPPUNIT_ASSERT_EQUAL_DIFF(expected, res);
         }
     }
 
     void testSetupDefault() {
         string root;
+        ScopedEnvChange templates("SYNCEVOLUTION_TEMPLATE_DIR", "/dev/null");
         ScopedEnvChange xdg("XDG_CONFIG_HOME", m_testDir);
         ScopedEnvChange home("HOME", m_testDir);
 
         root = m_testDir;
-        root += "/syncevolution/some-other-server";
+        root += "/syncevolution/default";
         rm_r(root);
         TestCmdline cmdline("--configure",
                             "--template", "default",
@@ -1184,16 +1429,20 @@ protected:
                             "some-other-server",
                             NULL);
         cmdline.doit();
-        string res = scanFiles(root);
-        CPPUNIT_ASSERT_EQUAL_DIFF(ScheduleWorldConfig(), res);
+        string res = scanFiles(root, "some-other-server");
+        string expected = ScheduleWorldConfig();
+        sortConfig(expected);
+        boost::replace_all(expected, "/scheduleworld/", "/some-other-server/");
+        CPPUNIT_ASSERT_EQUAL_DIFF(expected, res);
     }
     void testSetupRenamed() {
         string root;
+        ScopedEnvChange templates("SYNCEVOLUTION_TEMPLATE_DIR", "/dev/null");
         ScopedEnvChange xdg("XDG_CONFIG_HOME", m_testDir);
         ScopedEnvChange home("HOME", m_testDir);
 
         root = m_testDir;
-        root += "/syncevolution/scheduleworld2";
+        root += "/syncevolution/default";
         rm_r(root);
         TestCmdline cmdline("--configure",
                             "--template", "scheduleworld",
@@ -1201,42 +1450,81 @@ protected:
                             "scheduleworld2",
                             NULL);
         cmdline.doit();
-        string res = scanFiles(root);
-        CPPUNIT_ASSERT_EQUAL_DIFF(ScheduleWorldConfig(), res);
+        string res = scanFiles(root, "scheduleworld2");
+        string expected = ScheduleWorldConfig();
+        sortConfig(expected);
+        boost::replace_all(expected, "/scheduleworld/", "/scheduleworld2/");
+        CPPUNIT_ASSERT_EQUAL_DIFF(expected, res);
     }
-    void testSetupFunambol() {
+
+    void testSetupFunambol() { doSetupFunambol(false); }
+    void doSetupFunambol(bool shared) {
         string root;
+        ScopedEnvChange templates("SYNCEVOLUTION_TEMPLATE_DIR", "/dev/null");
         ScopedEnvChange xdg("XDG_CONFIG_HOME", m_testDir);
         ScopedEnvChange home("HOME", m_testDir);
 
         root = m_testDir;
-        root += "/syncevolution/funambol";
-        rm_r(root);
-        TestCmdline cmdline("--configure",
-                            "--sync-property", "deviceID = fixed-devid",
-                            // templates are case-insensitive
-                            "FunamBOL",
-                            NULL);
+        root += "/syncevolution/default";
+        string peer;
+        if (shared) {
+            peer = root + "/peers/funambol";
+        } else {
+            peer = root;
+        }
+
+        rm_r(peer);
+        const char * const argv_fixed[] = {
+                "--configure",
+                "--sync-property", "deviceID = fixed-devid",
+                // templates are case-insensitive
+                "FunamBOL",
+                NULL
+        }, * const argv_shared[] = {
+            "--configure",
+            "FunamBOL",
+            NULL
+        };
+        TestCmdline cmdline(shared ? argv_shared : argv_fixed);
         cmdline.doit();
-        string res = scanFiles(root);
-        CPPUNIT_ASSERT_EQUAL_DIFF(FunambolConfig(), res);
+        string res = scanFiles(root, "funambol");
+        string expected = FunambolConfig();
+        sortConfig(expected);
+        CPPUNIT_ASSERT_EQUAL_DIFF(expected, res);
     }
 
-    void testSetupSynthesis() {
+    void testSetupSynthesis() { doSetupSynthesis(false); }
+    void doSetupSynthesis(bool shared) {
         string root;
+        ScopedEnvChange templates("SYNCEVOLUTION_TEMPLATE_DIR", "/dev/null");
         ScopedEnvChange xdg("XDG_CONFIG_HOME", m_testDir);
         ScopedEnvChange home("HOME", m_testDir);
 
         root = m_testDir;
-        root += "/syncevolution/synthesis";
-        rm_r(root);
-        TestCmdline cmdline("--configure",
-                            "--sync-property", "deviceID = fixed-devid",
-                            "synthesis",
-                            NULL);
+        root += "/syncevolution/default";
+        string peer;
+        if (shared) {
+            peer = root + "/peers/synthesis";
+        } else {
+            peer = root;
+        }
+        rm_r(peer);
+        const char * const argv_fixed[] = {
+                "--configure",
+                "--sync-property", "deviceID = fixed-devid",
+                "synthesis",
+                NULL
+        }, * const argv_shared[] = {
+            "--configure",
+            "synthesis",
+            NULL
+        };
+        TestCmdline cmdline(shared ? argv_shared : argv_fixed);
         cmdline.doit();
-        string res = scanFiles(root);
-        CPPUNIT_ASSERT_EQUAL_DIFF(SynthesisConfig(), res);
+        string res = scanFiles(root, "synthesis");
+        string expected = SynthesisConfig();
+        sortConfig(expected);
+        CPPUNIT_ASSERT_EQUAL_DIFF(expected, res);
     }
 
     void testTemplate() {
@@ -1250,11 +1538,9 @@ protected:
         CPPUNIT_ASSERT_EQUAL_DIFF("Available configuration templates:\n"
                                   "   Funambol = http://my.funambol.com\n"
                                   "   Google = http://m.google.com/sync\n"
-                                  "   Goosync = http://www.goosync.com/\n"
                                   "   Memotoo = http://www.memotoo.com\n"
                                   "   Mobical = http://www.mobical.net\n"
-                                  "   Oracle = http://www.oracle.com/technology/products/beehive/index.html\n"
-                                  "   ScheduleWorld = http://www.scheduleworld.com\n"
+                                  "   ScheduleWorld = http://sync.scheduleworld.com\n"
                                   "   Synthesis = http://www.synthesis.ch\n"
                                   "   ZYB = http://www.zyb.com\n",
                                   help.m_out.str());
@@ -1262,25 +1548,27 @@ protected:
     }
 
     void testPrintServers() {
+        ScopedEnvChange templates("SYNCEVOLUTION_TEMPLATE_DIR", "/dev/null");
         ScopedEnvChange xdg("XDG_CONFIG_HOME", m_testDir);
         ScopedEnvChange home("HOME", m_testDir);
 
         rm_r(m_testDir);
-        testSetupScheduleWorld();
-        testSetupSynthesis();
-        testSetupFunambol();
+        doSetupScheduleWorld(false);
+        doSetupSynthesis(true);
+        doSetupFunambol(true);
 
         TestCmdline cmdline("--print-servers", NULL);
         cmdline.doit();
         CPPUNIT_ASSERT_EQUAL_DIFF("Configured servers:\n"
-                                  "   scheduleworld = CmdlineTest/syncevolution/scheduleworld\n"
-                                  "   synthesis = CmdlineTest/syncevolution/synthesis\n"
-                                  "   funambol = CmdlineTest/syncevolution/funambol\n",
+                                  "   funambol = CmdlineTest/syncevolution/default/peers/funambol\n"
+                                  "   scheduleworld = CmdlineTest/syncevolution/default/peers/scheduleworld\n"
+                                  "   synthesis = CmdlineTest/syncevolution/default/peers/synthesis\n",
                                   cmdline.m_out.str());
         CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
     }
 
     void testPrintConfig() {
+        ScopedEnvChange templates("SYNCEVOLUTION_TEMPLATE_DIR", "/dev/null");
         ScopedEnvChange xdg("XDG_CONFIG_HOME", m_testDir);
         ScopedEnvChange home("HOME", m_testDir);
 
@@ -1319,8 +1607,9 @@ protected:
             cmdline.doit();
             CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
             string actual = cmdline.m_out.str();
-            removeRandomUUID(actual);
-            string filtered = filterConfig(actual);
+            // deviceId must be the one from Funambol
+            CPPUNIT_ASSERT(boost::contains(actual, "deviceId = fixed-devid"));
+            string filtered = injectValues(filterConfig(actual));
             CPPUNIT_ASSERT_EQUAL_DIFF(filterConfig(internalToIni(ScheduleWorldConfig())),
                                       filtered);
             // there should have been comments
@@ -1331,8 +1620,8 @@ protected:
             TestCmdline cmdline("--print-config", "--template", "Default", NULL);
             cmdline.doit();
             CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
-            string actual = filterConfig(cmdline.m_out.str());
-            removeRandomUUID(actual);
+            string actual = injectValues(filterConfig(cmdline.m_out.str()));
+            CPPUNIT_ASSERT(boost::contains(actual, "deviceId = fixed-devid"));
             CPPUNIT_ASSERT_EQUAL_DIFF(filterConfig(internalToIni(ScheduleWorldConfig())),
                                       actual);
         }
@@ -1342,12 +1631,14 @@ protected:
             cmdline.doit();
             CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
             CPPUNIT_ASSERT_EQUAL_DIFF(filterConfig(internalToIni(FunambolConfig())),
-                                      filterConfig(cmdline.m_out.str()));
+                                      injectValues(filterConfig(cmdline.m_out.str())));
         }
 
         {
+            // override context and template properties
             TestCmdline cmdline("--print-config", "--template", "scheduleworld",
                                 "--sync-property", "syncURL=foo",
+                                "--source-property", "evolutionsource=Personal",
                                 "--source-property", "sync=disabled",
                                 NULL);
             cmdline.doit();
@@ -1357,10 +1648,13 @@ protected:
                                  "syncURL = http://sync.scheduleworld.com/funambol/ds",
                                  "syncURL = foo");
             boost::replace_all(expected,
+                               "# evolutionsource = ",
+                               "evolutionsource = Personal");
+            boost::replace_all(expected,
                                "sync = two-way",
                                "sync = disabled");
-            string actual = filterConfig(cmdline.m_out.str());
-            removeRandomUUID(actual);
+            string actual = injectValues(filterConfig(cmdline.m_out.str()));
+            CPPUNIT_ASSERT(boost::contains(actual, "deviceId = fixed-devid"));
             CPPUNIT_ASSERT_EQUAL_DIFF(expected,
                                       actual);
         }
@@ -1373,13 +1667,72 @@ protected:
             cmdline.doit();
             CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
             string actual = cmdline.m_out.str();
-            removeRandomUUID(actual);
+            CPPUNIT_ASSERT(boost::contains(actual, "deviceId = fixed-devid"));
             CPPUNIT_ASSERT_EQUAL_DIFF(internalToIni(ScheduleWorldConfig()),
+                                      injectValues(filterConfig(actual)));
+        }
+
+        {
+            // change shared source properties, then check template again
+            TestCmdline cmdline("--configure",
+                                "--source-property", "evolutionsource=Personal",
+                                "funambol",
+                                NULL);
+            cmdline.doit();
+            CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
+        }
+        {
+            TestCmdline cmdline("--print-config", "--quiet",
+                                "--template", "scheduleworld",
+                                "funambol",
+                                NULL);
+            cmdline.doit();
+            CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
+            string expected = filterConfig(internalToIni(ScheduleWorldConfig()));
+            // from modified Funambol config
+            boost::replace_all(expected,
+                               "# evolutionsource = ",
+                               "evolutionsource = Personal");
+            string actual = injectValues(filterConfig(cmdline.m_out.str()));
+            CPPUNIT_ASSERT(boost::contains(actual, "deviceId = fixed-devid"));
+            CPPUNIT_ASSERT_EQUAL_DIFF(expected,
                                       actual);
         }
-        
     }
 
+    void testPrintFileTemplates() {
+        // use local copy of templates in build dir (no need to install)
+        ScopedEnvChange templates("SYNCEVOLUTION_TEMPLATE_DIR", "./templates");
+        ScopedEnvChange xdg("XDG_CONFIG_HOME", m_testDir);
+        ScopedEnvChange home("HOME", m_testDir);
+
+        rm_r(m_testDir);
+        testSetupFunambol();
+
+        {
+            TestCmdline cmdline("--print-config", "--template", "scheduleworld", NULL);
+            cmdline.doit();
+            CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
+            string actual = cmdline.m_out.str();
+            // deviceId must be the one from Funambol
+            CPPUNIT_ASSERT(boost::contains(actual, "deviceId = fixed-devid"));
+            string filtered = injectValues(filterConfig(actual));
+            CPPUNIT_ASSERT_EQUAL_DIFF(filterConfig(internalToIni(ScheduleWorldConfig())),
+                                      filtered);
+            // there should have been comments
+            CPPUNIT_ASSERT(actual.size() > filtered.size());
+        }
+
+        {
+            TestCmdline cmdline("--print-config", "funambol", NULL);
+            cmdline.doit();
+            CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
+            CPPUNIT_ASSERT_EQUAL_DIFF(filterConfig(internalToIni(FunambolConfig())),
+                                      injectValues(filterConfig(cmdline.m_out.str())));
+        }
+    }
+
+
     void testSync() {
         TestCmdline failure("--sync", NULL);
         CPPUNIT_ASSERT(!failure.m_cmdline->parse());
@@ -1427,6 +1780,7 @@ protected:
     }
 
     void testConfigure() {
+        ScopedEnvChange templates("SYNCEVOLUTION_TEMPLATE_DIR", "/dev/null");
         ScopedEnvChange xdg("XDG_CONFIG_HOME", m_testDir);
         ScopedEnvChange home("HOME", m_testDir);
 
@@ -1462,8 +1816,14 @@ protected:
                               "\n"
                               "RetryInterval:\n"
                               "\n"
+                              "remoteIdentifier:\n"
+                              "\n"
+                              "PeerIsClient:\n"
+                              "\n"
                               "deviceId:\n"
                               "\n"
+                              "remoteDeviceId:\n"
+                              "\n"
                               "enableWBXML:\n"
                               "\n"
                               "maxMsgSize:\n"
@@ -1481,7 +1841,9 @@ protected:
                               "\n"
                               "IconURI:\n"
                               "\n"
-                              "ConsumerReady:\n");
+                              "ConsumerReady:\n"
+                              "\n"
+                              "defaultPeer:\n");
         string sourceProperties("sync:\n"
                                 "\n"
                                 "type:\n"
@@ -1533,6 +1895,7 @@ protected:
     }
 
     void testOldConfigure() {
+        ScopedEnvChange templates("SYNCEVOLUTION_TEMPLATE_DIR", "/dev/null");
         ScopedEnvChange xdg("XDG_CONFIG_HOME", m_testDir);
         ScopedEnvChange home("HOME", m_testDir);
 
@@ -1542,6 +1905,9 @@ protected:
             "devInfoHash" +
             "HashCode" +
             "ConfigDate" +
+            "deviceData" +
+            "adminData" +
+            "lastNonce" +
             "last";
         BOOST_FOREACH(string &prop, props) {
             boost::replace_all(oldConfig,
@@ -1626,19 +1992,21 @@ protected:
     }
 
     void testListSources() {
-        TestCmdline cmdline(NULL);
+        // pick the varargs constructor; NULL alone is ambiguous
+        TestCmdline cmdline(NULL, NULL);
         cmdline.doit();
         CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
         // exact output varies, do not test
     }
 
     void testMigrate() {
+        ScopedEnvChange templates("SYNCEVOLUTION_TEMPLATE_DIR", "/dev/null");
         ScopedEnvChange xdg("XDG_CONFIG_HOME", m_testDir);
         ScopedEnvChange home("HOME", m_testDir);
 
         rm_r(m_testDir);
         string oldRoot = m_testDir + "/.sync4j/evolution/scheduleworld";
-        string newRoot = m_testDir + "/syncevolution/scheduleworld";
+        string newRoot = m_testDir + "/syncevolution/default";
 
         string oldConfig = OldScheduleWorldConfig();
 
@@ -1654,18 +2022,24 @@ protected:
             CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_out.str());
 
             string migratedConfig = scanFiles(newRoot);
-            CPPUNIT_ASSERT_EQUAL_DIFF(m_scheduleWorldConfig, migratedConfig);
+            string expected = ScheduleWorldConfig();
+            sortConfig(expected);
+            CPPUNIT_ASSERT_EQUAL_DIFF(expected, migratedConfig);
             string renamedConfig = scanFiles(oldRoot + ".old");
             CPPUNIT_ASSERT_EQUAL_DIFF(createdConfig, renamedConfig);
         }
 
         {
-            // rewrite existing config
-            createFiles(newRoot,
+            // rewrite existing config with obsolete properties
+            // => these properties should get removed
+            //
+            // There is one limitation: shared nodes are not rewritten.
+            // This is acceptable.
+            createFiles(newRoot + "/peers/scheduleworld",
                         "config.ini:# obsolete comment\n"
                         "config.ini:obsoleteprop = foo\n",
                         true);
-            string createdConfig = scanFiles(newRoot);
+            string createdConfig = scanFiles(newRoot, "scheduleworld");
 
             TestCmdline cmdline("--migrate",
                                 "scheduleworld",
@@ -1674,16 +2048,20 @@ protected:
             CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
             CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_out.str());
 
-            string migratedConfig = scanFiles(newRoot);
-            CPPUNIT_ASSERT_EQUAL_DIFF(m_scheduleWorldConfig, migratedConfig);
-            string renamedConfig = scanFiles(newRoot + ".old");
+            string migratedConfig = scanFiles(newRoot, "scheduleworld");
+            string expected = ScheduleWorldConfig();
+            sortConfig(expected);
+            CPPUNIT_ASSERT_EQUAL_DIFF(expected, migratedConfig);
+            string renamedConfig = scanFiles(newRoot, "scheduleworld.old");
+            boost::replace_all(createdConfig, "/scheduleworld/", "/scheduleworld.old/");
             CPPUNIT_ASSERT_EQUAL_DIFF(createdConfig, renamedConfig);
         }
 
         {
-            // migrate old config with changes, a second time
+            // migrate old config with changes and .synthesis directory, a second time
             createFiles(oldRoot, oldConfig);
             createFiles(oldRoot,
+                        ".synthesis/dummy-file.bfi:dummy = foobar\n"
                         "spds/sources/addressbook/changes/config.txt:foo = bar\n"
                         "spds/sources/addressbook/changes/config.txt:foo2 = bar2\n",
                         true);
@@ -1698,15 +2076,61 @@ protected:
 
             string migratedConfig = scanFiles(newRoot);
             string expected = m_scheduleWorldConfig;
+            sortConfig(expected);
             boost::replace_first(expected,
-                                 "sources/addressbook/config.ini",
-                                 "sources/addressbook/.other.ini:foo = bar\n"
-                                 "sources/addressbook/.other.ini:foo2 = bar2\n"
-                                 "sources/addressbook/config.ini");
+                                 "peers/scheduleworld/sources/addressbook/config.ini",
+                                 "peers/scheduleworld/sources/addressbook/.other.ini:foo = bar\n"
+                                 "peers/scheduleworld/sources/addressbook/.other.ini:foo2 = bar2\n"
+                                 "peers/scheduleworld/sources/addressbook/config.ini");
+            boost::replace_first(expected,
+                                 "peers/scheduleworld/config.ini",
+                                 "peers/scheduleworld/.synthesis/dummy-file.bfi:dummy = foobar\n"
+                                 "peers/scheduleworld/config.ini");
             CPPUNIT_ASSERT_EQUAL_DIFF(expected, migratedConfig);
             string renamedConfig = scanFiles(oldRoot + ".old.1");
             CPPUNIT_ASSERT_EQUAL_DIFF(createdConfig, renamedConfig);
         }
+
+        {
+            string otherRoot = m_testDir + "/syncevolution/other";
+            rm_r(otherRoot);
+
+            // migrate old config into non-default context
+            createFiles(oldRoot, oldConfig);
+            string createdConfig = scanFiles(oldRoot);
+            {
+                TestCmdline cmdline("--migrate",
+                                    "scheduleworld@other",
+                                    NULL);
+                cmdline.doit();
+                CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
+                CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_out.str());
+            }
+
+            string migratedConfig = scanFiles(otherRoot);
+            string expected = ScheduleWorldConfig();
+            sortConfig(expected);
+            CPPUNIT_ASSERT_EQUAL_DIFF(expected, migratedConfig);
+            string renamedConfig = scanFiles(oldRoot + ".old");
+            CPPUNIT_ASSERT_EQUAL_DIFF(createdConfig, renamedConfig);
+
+            // migrate the migrated config again inside the "other" context
+            {
+                TestCmdline cmdline("--migrate",
+                                    "scheduleworld@other",
+                                    NULL);
+                cmdline.doit();
+                CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
+                CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_out.str());
+            }
+            migratedConfig = scanFiles(otherRoot, "scheduleworld");
+            expected = ScheduleWorldConfig();
+            sortConfig(expected);
+            CPPUNIT_ASSERT_EQUAL_DIFF(expected, migratedConfig);
+            renamedConfig = scanFiles(otherRoot, "scheduleworld.old");
+            boost::replace_all(expected, "/scheduleworld/", "/scheduleworld.old/");
+            CPPUNIT_ASSERT_EQUAL_DIFF(expected, renamedConfig);
+        }
     }
 
     const string m_testDir;
@@ -1720,6 +2144,19 @@ private:
      * out and error stream into stringstream members
      */
     class TestCmdline {
+        void init() {
+            m_argv.reset(new const char *[m_argvstr.size() + 1]);
+            m_argv[0] = "client-test";
+            for (size_t index = 0;
+                 index < m_argvstr.size();
+                 ++index) {
+                m_argv[index + 1] = m_argvstr[index].c_str();
+            }
+
+            m_cmdline.set(new Cmdline(m_argvstr.size() + 1, m_argv.get(), m_out, m_err), "cmdline");
+            
+        }
+
     public:
         TestCmdline(const char *arg, ...) {
             va_list argList;
@@ -1730,16 +2167,14 @@ private:
                 m_argvstr.push_back(curr);
             }
             va_end(argList);
+            init();
+        }
 
-            m_argv.reset(new const char *[m_argvstr.size() + 1]);
-            m_argv[0] = "client-test";
-            for (size_t index = 0;
-                 index < m_argvstr.size();
-                 ++index) {
-                m_argv[index + 1] = m_argvstr[index].c_str();
+        TestCmdline(const char * const argv[]) {
+            for (int i = 0; argv[i]; i++) {
+                m_argvstr.push_back(argv[i]);
             }
-
-            m_cmdline.set(new Cmdline(m_argvstr.size() + 1, m_argv.get(), m_out, m_err), "cmdline");
+            init();
         }
 
         void doit() {
@@ -1763,43 +2198,99 @@ private:
     string ScheduleWorldConfig() {
         string config = m_scheduleWorldConfig;
 
-        if (isDir(string(TEMPLATE_DIR) + "/ScheduleWorld")) {
+#if 0
+        // Currently we don't have an icon for ScheduleWorld. If we
+        // had (MB #2062) one, then this code would ensure that the
+        // reference config also has the right path for it.
+        const char *templateDir = getenv("SYNCEVOLUTION_TEMPLATE_DIR");
+        if (!templateDir) {
+            templateDir = TEMPLATE_DIR;
+        }
+
+
+        if (isDir(string(templateDir) + "/ScheduleWorld")) {
             boost::replace_all(config,
                                "# IconURI = ",
-                               "IconURI = file://" TEMPLATE_DIR "/ScheduleWorld/icon.png");
+                               string("IconURI = file://") + templateDir + "/ScheduleWorld/icon.png");
         }
+#endif
         return config;
     }
 
     string OldScheduleWorldConfig() {
-        string oldConfig = m_scheduleWorldConfig;
-        boost::replace_all(oldConfig,
-                           ".internal.ini",
-                           "config.ini");
-        InitList<string> sources = InitList<string>("addressbook") +
-            "calendar" +
-            "memo" +
-            "todo";
-        BOOST_FOREACH(string &source, sources) {
-            boost::replace_all(oldConfig,
-                               string("sources/") + source + "/config.ini",
-                               string("spds/sources/") + source + "/config.txt");
-        }
-        boost::replace_all(oldConfig,
-                           "config.ini",
-                           "spds/syncml/config.txt");
+        // old style paths
+        string oldConfig =
+            "spds/syncml/config.txt:syncURL = http://sync.scheduleworld.com/funambol/ds\n"
+            "spds/syncml/config.txt:username = your SyncML server account name\n"
+            "spds/syncml/config.txt:password = your SyncML server password\n"
+            "spds/syncml/config.txt:# logdir = \n"
+            "spds/syncml/config.txt:# loglevel = 0\n"
+            "spds/syncml/config.txt:# printChanges = 1\n"
+            "spds/syncml/config.txt:# maxlogdirs = 10\n"
+            "spds/syncml/config.txt:# useProxy = 0\n"
+            "spds/syncml/config.txt:# proxyHost = \n"
+            "spds/syncml/config.txt:# proxyUsername = \n"
+            "spds/syncml/config.txt:# proxyPassword = \n"
+            "spds/syncml/config.txt:# clientAuthType = md5\n"
+            "spds/syncml/config.txt:# RetryDuration = 300\n"
+            "spds/syncml/config.txt:# RetryInterval = 60\n"
+            "spds/syncml/config.txt:# remoteIdentifier = \n"
+            "spds/syncml/config.txt:# PeerIsClient = 0\n"
+            "spds/syncml/config.txt:deviceId = fixed-devid\n" /* this is not the default! */
+            "spds/syncml/config.txt:# remoteDeviceId = \n"
+            "spds/syncml/config.txt:# enableWBXML = 1\n"
+            "spds/syncml/config.txt:# maxMsgSize = 20000\n"
+            "spds/syncml/config.txt:# maxObjSize = 4000000\n"
+            "spds/syncml/config.txt:# enableCompression = 0\n"
+#ifdef ENABLE_LIBSOUP
+            // path to SSL certificates is only set for libsoup
+            "spds/syncml/config.txt:# SSLServerCertificates = /etc/ssl/certs/ca-certificates.crt:/etc/pki/tls/certs/ca-bundle.crt:/usr/share/ssl/certs/ca-bundle.crt\n"
+
+#else
+            "spds/syncml/config.txt:# SSLServerCertificates = \n"
+#endif
+            "spds/syncml/config.txt:# SSLVerifyServer = 1\n"
+            "spds/syncml/config.txt:# SSLVerifyHost = 1\n"
+            "spds/syncml/config.txt:WebURL = http://sync.scheduleworld.com\n"
+            "spds/syncml/config.txt:# IconURI = \n"
+            "spds/syncml/config.txt:ConsumerReady = 1\n"
+            "spds/sources/addressbook/config.txt:sync = two-way\n"
+            "spds/sources/addressbook/config.txt:type = addressbook:text/vcard\n"
+            "spds/sources/addressbook/config.txt:# evolutionsource = \n"
+            "spds/sources/addressbook/config.txt:uri = card3\n"
+            "spds/sources/addressbook/config.txt:# evolutionuser = \n"
+            "spds/sources/addressbook/config.txt:# evolutionpassword = \n"
+            "spds/sources/calendar/config.txt:sync = two-way\n"
+            "spds/sources/calendar/config.txt:type = calendar\n"
+            "spds/sources/calendar/config.txt:# evolutionsource = \n"
+            "spds/sources/calendar/config.txt:uri = cal2\n"
+            "spds/sources/calendar/config.txt:# evolutionuser = \n"
+            "spds/sources/calendar/config.txt:# evolutionpassword = \n"
+            "spds/sources/memo/config.txt:sync = two-way\n"
+            "spds/sources/memo/config.txt:type = memo\n"
+            "spds/sources/memo/config.txt:# evolutionsource = \n"
+            "spds/sources/memo/config.txt:uri = note\n"
+            "spds/sources/memo/config.txt:# evolutionuser = \n"
+            "spds/sources/memo/config.txt:# evolutionpassword = \n"
+            "spds/sources/todo/config.txt:sync = two-way\n"
+            "spds/sources/todo/config.txt:type = todo\n"
+            "spds/sources/todo/config.txt:# evolutionsource = \n"
+            "spds/sources/todo/config.txt:uri = task2\n"
+            "spds/sources/todo/config.txt:# evolutionuser = \n"
+            "spds/sources/todo/config.txt:# evolutionpassword = \n";
         return oldConfig;
     }
 
     string FunambolConfig() {
         string config = m_scheduleWorldConfig;
+        boost::replace_all(config, "/scheduleworld/", "/funambol/");
 
         boost::replace_first(config,
                              "syncURL = http://sync.scheduleworld.com/funambol/ds",
                              "syncURL = http://my.funambol.com/sync");
 
         boost::replace_first(config,
-                             "WebURL = http://www.scheduleworld.com",
+                             "WebURL = http://sync.scheduleworld.com",
                              "WebURL = http://my.funambol.com");
 
         boost::replace_first(config,
@@ -1809,35 +2300,37 @@ private:
         boost::replace_first(config,
                              "addressbook/config.ini:uri = card3",
                              "addressbook/config.ini:uri = card");
-        boost::replace_first(config,
-                             "addressbook/config.ini:type = addressbook:text/vcard",
-                             "addressbook/config.ini:type = addressbook");
+        boost::replace_all(config,
+                           "addressbook/config.ini:type = addressbook:text/vcard",
+                           "addressbook/config.ini:type = addressbook");
 
         boost::replace_first(config,
                              "calendar/config.ini:uri = cal2",
                              "calendar/config.ini:uri = event");
-        boost::replace_first(config,
-                             "calendar/config.ini:type = calendar",
-                             "calendar/config.ini:type = calendar:text/calendar!");
+        boost::replace_all(config,
+                           "calendar/config.ini:type = calendar",
+                           "calendar/config.ini:type = calendar:text/calendar!");
 
         boost::replace_first(config,
                              "todo/config.ini:uri = task2",
                              "todo/config.ini:uri = task");
-        boost::replace_first(config,
-                             "todo/config.ini:type = todo",
-                             "todo/config.ini:type = todo:text/calendar!");
+        boost::replace_all(config,
+                           "todo/config.ini:type = todo",
+                           "todo/config.ini:type = todo:text/calendar!");
 
         return config;
     }
 
     string SynthesisConfig() {
         string config = m_scheduleWorldConfig;
+        boost::replace_all(config, "/scheduleworld/", "/synthesis/");
+
         boost::replace_first(config,
                              "syncURL = http://sync.scheduleworld.com/funambol/ds",
                              "syncURL = http://www.synthesis.ch/sync");
 
         boost::replace_first(config,
-                             "WebURL = http://www.scheduleworld.com",
+                             "WebURL = http://sync.scheduleworld.com",
                              "WebURL = http://www.synthesis.ch");        
 
         boost::replace_first(config,
@@ -1847,9 +2340,9 @@ private:
         boost::replace_first(config,
                              "addressbook/config.ini:uri = card3",
                              "addressbook/config.ini:uri = contacts");
-        boost::replace_first(config,
-                             "addressbook/config.ini:type = addressbook:text/vcard",
-                             "addressbook/config.ini:type = addressbook");
+        boost::replace_all(config,
+                           "addressbook/config.ini:type = addressbook:text/vcard",
+                           "addressbook/config.ini:type = addressbook");
 
         boost::replace_first(config,
                              "calendar/config.ini:uri = cal2",
@@ -1938,15 +2431,21 @@ private:
         }
     }
 
-    /** turn directory hierarchy into string */
-    string scanFiles(const string &root, bool onlyProps = true) {
+    /** turn directory hierarchy into string
+     *
+     * @param root       root path in file system
+     * @param peer       if non-empty, then ignore all <root>/peers/<foo> directories
+     *                   where <foo> != peer
+     * @param onlyProps  ignore lines which are comments
+     */
+    string scanFiles(const string &root, const string &peer = "", bool onlyProps = true) {
         ostringstream out;
 
-        scanFiles(root, "", out, onlyProps);
+        scanFiles(root, "", peer, out, onlyProps);
         return out.str();
     }
 
-    void scanFiles(const string &root, const string &dir, ostringstream &out, bool onlyProps) {
+    void scanFiles(const string &root, const string &dir, const string &peer, ostringstream &out, bool onlyProps) {
         string newroot = root;
         newroot += "/";
         newroot += dir;
@@ -1955,7 +2454,14 @@ private:
 
         BOOST_FOREACH(const string &entry, readDir) {
             if (isDir(newroot + "/" + entry)) {
-                scanFiles(root, dir + (dir.empty() ? "" : "/") + entry, out, onlyProps);
+                if (boost::ends_with(newroot, "/peers") &&
+                    !peer.empty() &&
+                    entry != peer) {
+                    // skip different peer directory
+                    continue;
+                } else {
+                    scanFiles(root, dir + (dir.empty() ? "" : "/") + entry, peer, out, onlyProps);
+                }
             } else {
                 ifstream in;
                 in.exceptions(ios_base::badbit /* failbit must not trigger exception because is set when reaching eof ?! */);
@@ -1980,6 +2486,7 @@ private:
     }
 
     string printConfig(const string &server) {
+        ScopedEnvChange templates("SYNCEVOLUTION_TEMPLATE_DIR", "/dev/null");
         ScopedEnvChange xdg("XDG_CONFIG_HOME", m_testDir);
         ScopedEnvChange home("HOME", m_testDir);
 
index e9146bf..11b22be 100644 (file)
@@ -116,6 +116,20 @@ protected:
     bool listProperties(const ConfigPropertyRegistry &validProps,
                         const string &opt);
 
+    typedef map<string, ConfigProps> SourceFilters_t;
+
+    /**
+     * read properties from context, then update with
+     * command line properties
+     *
+     * @param context         context name, without @ sign
+     * @retval syncFilter     global sync properties
+     * @retval sourceFilters  entries for specific sources, key "" as fallback
+     */
+    void getFilters(const string &context,
+                    ConfigProps &syncFilter,
+                    SourceFilters_t &sourceFilters);
+
     /**
      * list all known data sources of a certain type
      */
index 9403a2b..aa428b8 100644 (file)
@@ -28,10 +28,19 @@ using namespace std;
 
 #include <boost/shared_ptr.hpp>
 #include <boost/algorithm/string/predicate.hpp>
+#include <boost/foreach.hpp>
 
 #include <syncevo/declarations.h>
+#include <syncevo/util.h>
 SE_BEGIN_CXX
 
+/** a case-insensitive string to string mapping */
+class ConfigProps : public map<string, string, Nocase<string> > {
+ public:
+    /** format as <key> = <value> lines */
+    operator string () const;
+};
+
 /**
  * This class corresponds to the Funambol C++ client
  * DeviceManagementNode, but offers a slightly different API.  See
@@ -146,6 +155,8 @@ class ConfigNode {
         }
     }
 
+    // defined here for source code backwards compatibility
+    typedef ConfigProps PropsType;
 
     /**
      * Extract all list of all currently defined properties
@@ -156,8 +167,18 @@ class ConfigNode {
      * @retval props    to be filled with key/value pairs; guaranteed
      *                  to be empty before the call
      */
-    virtual void readProperties(map<string, string> &props) const = 0;
-    typedef map<string, string> PropsType;
+    virtual void readProperties(ConfigProps &props) const = 0;
+
+    /**
+     * Add the given properties. To replace the content of the
+     * node, call clear() first.
+     */
+    virtual void writeProperties(const ConfigProps &props)
+    {
+        BOOST_FOREACH(const ConfigProps::value_type &entry, props) {
+            setProperty(entry.first, entry.second);
+        }
+    }
 
     /**
      * Remove a certain property.
@@ -167,6 +188,11 @@ class ConfigNode {
     virtual void removeProperty(const string &property) = 0;
 
     /**
+     * Remove all properties.
+     */
+    virtual void clear() = 0;
+
+    /**
      * Node exists in backend storage.
      */
     virtual bool exists() const = 0;
index 6d141be..3f42418 100644 (file)
@@ -70,9 +70,14 @@ class ConfigTree {
     /** ensure that all changes are saved persistently */
     virtual void flush() = 0;
 
-    /** remove all configuration nodes and (if based on files)
-        directories created for them, if empty after file removal */
-    virtual void remove() = 0;
+    /**
+     * Remove all configuration nodes below and including a certain
+     * path and (if based on files) directories created for them, if
+     * empty after file removal.
+     *
+     * The nodes must not be in use for this to work.
+     */
+    virtual void remove(const string &path) = 0;
 
     /** a string identifying the root of the configuration - exact meaning varies */
     virtual string getRootPath() const = 0;
@@ -84,7 +89,8 @@ class ConfigTree {
     enum PropertyType {
         visible,   /**< visible configuration properties */
         hidden,    /**< hidden read/write properties */
-        other      /**< additional node selected via otherID */
+        other,     /**< additional node selected via otherID */
+        server,    /**< yet another additional node, similar to other */
     };
 
     /**
@@ -94,8 +100,8 @@ class ConfigTree {
      *
      * @param path      a relative path with / as separator
      * @param type      selects which fork of that path is to be opened
-     *                  (visible, hidden, change tracking)
-     * @param otherId   an additional string to be attached to the other
+     *                  (visible, hidden, change tracking, server)
+     * @param otherId   an additional string to be attached to the 'other' or 'server'
      *                  node's name (allows having multiple different such
      *                  nodes); an empty string is allowed
      */
index 9c11fd9..db8f06a 100644 (file)
@@ -150,6 +150,10 @@ void CurlTransportAgent::setCallback (TransportCallback cb, void *udata, int int
     m_cbInterval = interval;
 }
 
+void CurlTransportAgent::shutdown()
+{
+}
+
 void CurlTransportAgent::send(const char *data, size_t len)
 {
     CURLcode code;
@@ -200,7 +204,7 @@ void CurlTransportAgent::cancel()
     /* nothing to do */
 }
 
-TransportAgent::Status CurlTransportAgent::wait()
+TransportAgent::Status CurlTransportAgent::wait(bool noReply)
 {
     return m_status;
 }
@@ -276,7 +280,7 @@ void CurlTransportAgent::checkCurl(CURLcode code, bool exception)
 int CurlTransportAgent::progressCallback(void* transport, double, double, double, double)
 {
     CurlTransportAgent *agent = static_cast<CurlTransportAgent *> (transport);
-    SuspendFlags& s_flags = SyncContext::getSuspendFlags();
+    const SuspendFlags &s_flags = SyncContext::getSuspendFlags();
     //abort transfer
     if (s_flags.state == SuspendFlags::CLIENT_ABORT){
         agent->setAborting (true);
index 5760297..62eba3f 100644 (file)
@@ -37,7 +37,7 @@ SE_BEGIN_CXX
  * The simple curl API is used, so sending blocks until the
  * reply is ready.
  */
-class CurlTransportAgent : public TransportAgent
+class CurlTransportAgent : public HTTPTransportAgent
 {
  public:
     CurlTransportAgent();
@@ -51,9 +51,10 @@ class CurlTransportAgent : public TransportAgent
                         bool verifyHost);
     virtual void setContentType(const std::string &type);
     virtual void setUserAgent(const std::string &agent);
+    virtual void shutdown();
     virtual void send(const char *data, size_t len);
     virtual void cancel();
-    virtual Status wait();
+    virtual Status wait(bool noReply = false);
     virtual void getReply(const char *&data, size_t &len, std::string &contentType);
     virtual void setCallback (TransportCallback cb, void * udata, int interval);
     int processCallback();
diff --git a/src/syncevo/DevNullConfigNode.h b/src/syncevo/DevNullConfigNode.h
new file mode 100644 (file)
index 0000000..7685857
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2009 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) version 3.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301  USA
+ */
+
+#ifndef INCL_SYNCEVO_DEVNULL_CONFIG_NODE
+# define INCL_SYNCEVO_DEVNULL_CONFIG_NODE
+
+#include <syncevo/ConfigNode.h>
+#include <syncevo/util.h>
+SE_BEGIN_CXX
+
+/**
+ * A read-only node which raises an exception when someone tries to
+ * write into it.
+ */
+class DevNullConfigNode : public ConfigNode {
+    string m_name;
+
+ public:
+    DevNullConfigNode(const string &name) : m_name() {}
+
+    virtual string getName() const { return m_name; }
+    virtual void flush() {}
+    virtual string readProperty(const string &property) const { return ""; }
+    virtual void setProperty(const string &property,
+                             const string &value,
+                             const string &comment = string(""),
+                             const string *defValue = NULL)
+    {
+        SE_THROW(m_name + ": virtual read-only configuration node, cannot write property " +
+                 property + " = " + value);
+    }
+    virtual void readProperties(PropsType &props) const {}
+    virtual void writeProperties(const PropsType &props)
+    {
+        if (!props.empty()) {
+            SE_THROW(m_name + ": virtual read-only configuration node, cannot write properties");
+        }
+    }
+    virtual void removeProperty(const string &property) {}
+    virtual void clear() {}
+    virtual bool exists() const { return false; }
+};
+
+
+SE_END_CXX
+#endif // SYNCEVO_DEVNULL_CONFIG_NODE
index be7c3da..8ce84d6 100644 (file)
@@ -247,7 +247,7 @@ string FileConfigNode::readProperty(const string &property) const {
 
 
 
-void FileConfigNode::readProperties(map<string, string> &props) const {
+void FileConfigNode::readProperties(ConfigProps &props) const {
     map<string, string> res;
     string value, property;
 
@@ -323,6 +323,12 @@ void FileConfigNode::setProperty(const string &property,
     m_modified = true;
 }
 
+void FileConfigNode::clear()
+{
+    m_lines.clear();
+    m_modified = true;
+}
+
 HashFileConfigNode::HashFileConfigNode(const string &path, const string &fileName, bool readonly) :
     FileBaseConfigNode(path,fileName,readonly)
 {
@@ -366,12 +372,20 @@ void HashFileConfigNode::toFile(FILE* file) {
     }
 }
 
-void HashFileConfigNode::readProperties(map<string, string> &props) const {
+void HashFileConfigNode::readProperties(ConfigProps &props) const {
     BOOST_FOREACH(const StringPair &prop, m_props) {
         props.insert(prop);
     }
 }
 
+void HashFileConfigNode::writeProperties(const ConfigProps &props) {
+    if (!props.empty()) {
+        m_props.insert(props.begin(), props.end());
+        m_modified = true;
+    }
+}
+
+
 string HashFileConfigNode::readProperty(const string &property) const {
     std::map<std::string, std::string>::const_iterator it = m_props.find(property);
     if (it != m_props.end()) {
@@ -389,6 +403,14 @@ void HashFileConfigNode::removeProperty(const string &property){
     }
 }
 
+void HashFileConfigNode::clear()
+{
+    if (!m_props.empty()) {
+        m_props.clear();
+        m_modified = true;
+    }
+}
+
 void HashFileConfigNode::setProperty(const string &property,
                                  const string &newvalue,
                                  const string &comment,
@@ -396,6 +418,7 @@ void HashFileConfigNode::setProperty(const string &property,
     /** we don't support property comments here. Also, we ignore comment*/
     if (defValue &&
         *defValue == newvalue) {
+        removeProperty(property);
         return;
     }
     map<string, string>::iterator it = m_props.find(property);
index 761e348..b6a75f2 100644 (file)
@@ -104,8 +104,9 @@ class FileConfigNode : public FileBaseConfigNode {
                              const string &value,
                              const string &comment = "",
                              const string *defValue = NULL);
-    virtual void readProperties(map<string, string> &props) const;
+    virtual void readProperties(ConfigProps &props) const;
     virtual void removeProperty(const string &property);
+    virtual void clear();
 };
 
 /**
@@ -131,8 +132,10 @@ class HashFileConfigNode: public FileBaseConfigNode {
                              const string &value,
                              const string &comment = "",
                              const string *defValue = NULL);
-    virtual void readProperties(map<string, string> &props) const;
+    virtual void readProperties(ConfigProps &props) const;
+    virtual void writeProperties(const ConfigProps &props);
     virtual void removeProperty(const string &property);
+    virtual void clear();
 };
 
 
index e6eefc1..3c7a0a6 100644 (file)
 SE_BEGIN_CXX
 
 FileConfigTree::FileConfigTree(const string &root,
+                               const string &peer,
                                bool oldLayout) :
     m_root(root),
+    m_peer(peer),
     m_oldLayout(oldLayout),
     m_readonly(false)
 {
@@ -46,7 +48,7 @@ FileConfigTree::FileConfigTree(const string &root,
 
 string FileConfigTree::getRootPath() const
 {
-    return normalizePath(m_root);
+    return normalizePath(m_root + "/" + m_peer);
 }
 
 void FileConfigTree::flush()
@@ -74,23 +76,62 @@ static bool rm_filter(const string &path, bool isDir)
             boost::ends_with(path, "/config.txt~") ||
             boost::ends_with(path, "/.other.ini") ||
             boost::ends_with(path, "/.other.ini~") ||
+            boost::ends_with(path, "/.server.ini") ||
+            boost::ends_with(path, "/.server.ini~") ||
             boost::ends_with(path, "/.internal.ini") ||
             boost::ends_with(path, "/.internal.ini~") ||
             path.find("/.synthesis/") != path.npos;
     }
 }
 
-void FileConfigTree::remove()
+void FileConfigTree::remove(const string &path)
 {
-    reset();
-    rm_r(getRootPath(), rm_filter);
+    string fullpath = m_root + "/" + path;
+    clearNodes(fullpath);
+    rm_r(fullpath, rm_filter);
 }
 
 void FileConfigTree::reset()
 {
+    for (NodeCache_t::iterator it = m_nodes.begin();
+         it != m_nodes.end();
+         ++it) {
+        if (it->second.use_count() > 1) {
+            // If the use count is larger than 1, then someone besides
+            // the cache is referencing the node. We cannot force that
+            // other entity to drop the reference, so bail out here.
+            SE_THROW(it->second->getName() +
+                     ": cannot be removed while in use");
+        }
+    }
     m_nodes.clear();
 }
 
+void FileConfigTree::clearNodes(const string &fullpath) 
+{
+    NodeCache_t::iterator it;
+    it = m_nodes.begin();
+    while (it != m_nodes.end()) {
+        const string &key = it->first;
+        if (boost::starts_with(key, fullpath)){
+            /* 'it = m_nodes.erase(it);' doesn't make sense
+             * because 'map::erase' returns 'void' in gcc. But other 
+             * containers like list, vector could work! :( 
+             * Below is STL recommended usage. 
+             */
+            NodeCache_t::iterator erased = it++;
+            if (erased->second.use_count() > 1) {
+                // same check as in reset()
+                SE_THROW(erased->second->getName() +
+                         ": cannot be removed while in use");
+            }
+            m_nodes.erase(erased);
+        } else {
+            ++it;
+        }
+    }
+}
+
 boost::shared_ptr<ConfigNode> FileConfigTree::open(const string &path,
                                                    ConfigTree::PropertyType type,
                                                    const string &otherId)
@@ -116,7 +157,8 @@ boost::shared_ptr<ConfigNode> FileConfigTree::open(const string &path,
             filename += ".ini";
         }
     } else {
-        filename = m_oldLayout ? "config.txt" :
+        filename = type == server ? ".server.ini" :
+            m_oldLayout ? "config.txt" :
             type == hidden ? ".internal.ini" :
             "config.ini";
     }
@@ -125,7 +167,7 @@ boost::shared_ptr<ConfigNode> FileConfigTree::open(const string &path,
     NodeCache_t::iterator found = m_nodes.find(fullname);
     if (found != m_nodes.end()) {
         return found->second;
-    } else if(type != other){
+    } else if(type != other && type != server) {
         boost::shared_ptr<ConfigNode> node(new FileConfigNode(fullpath, filename, m_readonly));
         return m_nodes[fullname] = node;
     } else {
index b09d0c0..fc4e322 100644 (file)
@@ -38,10 +38,13 @@ using namespace std;
 class FileConfigTree : public ConfigTree {
  public:
     /**
-     * @param root              absolute filesystem path
-     * @param oldLayout         use file names as in SyncEvolution <= 0.7
+     * @param root              absolute filesystem path for
+     *                          .syncj4/evolution or .config/syncevolution
+     * @param peer              the relative path to the peer configuration
+     * @param oldLayout         true: use pre-0.7 file names
      */
     FileConfigTree(const string &root,
+                   const string &peer,
                    bool oldLayout);
 
     void setReadOnly(bool readonly) { m_readonly = readonly; }
@@ -50,7 +53,7 @@ class FileConfigTree : public ConfigTree {
     /* ConfigTree API */
     virtual string getRootPath() const;
     virtual void flush();
-    virtual void remove();
+    virtual void remove(const string &path);
     virtual void reset();
     virtual boost::shared_ptr<ConfigNode> open(const string &path,
                                                PropertyType type,
@@ -58,7 +61,15 @@ class FileConfigTree : public ConfigTree {
     list<string> getChildren(const string &path);
 
  private:
+    /**
+     * remove all nodes from the node cache which are located at 'fullpath' 
+     * or are contained inside it
+     */
+    void clearNodes(const string &fullpath);
+
+ private:
     const string m_root;
+    const string m_peer;
     const bool m_oldLayout;
     bool m_readonly;
 
index 42aad30..ee15f76 100644 (file)
@@ -80,12 +80,13 @@ void FilterConfigNode::setProperty(const string &property,
     m_node->setProperty(property, value, comment, defValue);
 }
 
-void FilterConfigNode::readProperties(map<string, string> &props) const
+void FilterConfigNode::readProperties(ConfigProps &props) const
 {
     m_readOnlyNode->readProperties(props);
 
     BOOST_FOREACH(const StringPair &filter, m_filter) {
-        props.insert(filter);
+        // overwrite existing values or add new ones
+        props[filter.first] = filter.second;
     }
 }
 
@@ -103,6 +104,12 @@ void FilterConfigNode::removeProperty(const string &property)
     m_node->removeProperty(property);
 }
 
+void FilterConfigNode::clear()
+{
+    m_filter.clear();
+    m_node->clear();
+}
+
 void FilterConfigNode::flush()
 {
     if (!m_node.get()) {
index c55bc06..ca1a619 100644 (file)
@@ -25,8 +25,6 @@
 #include <boost/algorithm/string/case_conv.hpp>
 #include <boost/algorithm/string.hpp>
 
-#include <syncevo/util.h>
-
 #include <map>
 #include <utility>
 #include <vector>
@@ -47,12 +45,8 @@ using namespace std;
  */
 class FilterConfigNode : public ConfigNode {
  public:
-    /** a case-insensitive string to string mapping */
-    class ConfigFilter : public map<string, string, Nocase<string> > {
-    public:
-        /** format as <key> = <value> lines */
-        operator string () const;
-    };
+    /** config filters are the same case-insensitive string to string mapping as property sets */
+    typedef ConfigProps ConfigFilter;
 
     /** read-write access to underlying node */
     FilterConfigNode(const boost::shared_ptr<ConfigNode> &node,
@@ -65,12 +59,12 @@ class FilterConfigNode : public ConfigNode {
     virtual string getName() const { return m_readOnlyNode->getName(); }
 
     /** add another entry to the list of filter properties */
-    void addFilter(const string &property,
-                   const string &value);
+    virtual void addFilter(const string &property,
+                           const string &value);
 
     /** replace current filter list with new one */
-    void setFilter(const ConfigFilter &filter);
-    const ConfigFilter &getFilter() const { return m_filter; }
+    virtual void setFilter(const ConfigFilter &filter);
+    virtual const ConfigFilter &getFilter() const { return m_filter; }
 
     /* ConfigNode API */
     virtual void flush();
@@ -79,9 +73,10 @@ class FilterConfigNode : public ConfigNode {
                              const string &value,
                              const string &comment = "",
                              const string *defValue = NULL);
-    virtual void readProperties(map<string, string> &props) const;
+    virtual void readProperties(ConfigProps &props) const;
     virtual void removeProperty(const string &property);
     virtual bool exists() const { return m_readOnlyNode->exists(); }
+    virtual void clear();
 
  private:
     ConfigFilter m_filter;
index a57a3d8..c0e1a80 100644 (file)
@@ -45,8 +45,10 @@ class HashConfigNode : public ConfigNode {
                              const string &comment = "",
                              const string *defValue = NULL) { m_props[property] = value; }
     virtual void readProperties(std::map<std::string, std::string> &props) const { props = m_props; }
+    virtual void writeProperties(const PropsType &props) { m_props.insert(props.begin(), props.end()); }
     virtual void removeProperty(const std::string &property) { m_props.erase(property); }
     virtual bool exists() const { return true; }
+    virtual void clear() { m_props.clear(); }
 };
 
 
index 35b4cee..bfaa96b 100644 (file)
@@ -38,6 +38,7 @@ SYNCEVOLUTION_SOURCES  = \
        LogRedirect.cpp \
        \
        TransportAgent.h \
+       TransportAgent.cpp \
        CurlTransportAgent.h \
        CurlTransportAgent.cpp \
        \
@@ -62,6 +63,10 @@ SYNCEVOLUTION_SOURCES  = \
        SyncConfig.h \
        SyncConfig.cpp \
        \
+       DevNullConfigNode.h \
+       MultiplexConfigNode.h \
+       MultiplexConfigNode.cpp \
+       \
        FilterConfigNode.h \
        FilterConfigNode.cpp \
        \
@@ -97,6 +102,15 @@ libsyncevolution_include_HEADERS = \
                                                                  eds_abi_wrapper.h \
                                                                  SmartPtr.h \
                                                                  ConfigNode.h 
+if ENABLE_OBEX 
+SYNCEVOLUTION_SOURCES += ObexTransportAgent.h ObexTransportAgent.cpp
+SYNCEVOLUTION_LDADD += $(LIBOPENOBEX_LIBS)
+SYNCEVOLUTION_CXXFLAGS += $(LIBOPENOBEX_CFLAGS)
+if ENABLE_BLUETOOTH
+SYNCEVOLUTION_LDADD += $(BLUEZ_LIBS)
+SYNCEVOLUTION_CXXFLAGS += $(BLUEZ_CFLAGS)
+endif
+endif
 
 pkgconfigdir=$(libdir)/pkgconfig
 pkgconfig_DATA=syncevolution.pc
@@ -107,6 +121,7 @@ libsyncevolution_la_SOURCES = $(SYNCEVOLUTION_SOURCES)
 libsyncevolution_la_LIBADD = @EPACKAGE_LIBS@ @GLIB_LIBS@ $(SYNTHESIS_LIBS) $(TRANSPORT_LIBS) @LIBS@ $(SYNCEVOLUTION_LDADD)
 libsyncevolution_la_CXXFLAGS = $(TRANSPORT_CFLAGS) $(SYNCEVOLUTION_CXXFLAGS) $(SYNTHESIS_CFLAGS)
 libsyncevolution_la_CPPFLAGS = $(AM_CPPFLAGS) -DTEMPLATE_DIR=\""$(datadir)/syncevolution/templates"\" -DLIBDIR=\""$(libdir)"\"
+libsyncevolution_la_DEPENDENCIES = $(SYNTHESIS_DEP)
 
 if ENABLE_MODULES
 libsyncevolution_la_LDFLAGS =
index e5a8128..b235ebb 100644 (file)
@@ -36,6 +36,11 @@ build_triplet = @build@
 host_triplet = @host@
 @ENABLE_UNIT_TESTS_TRUE@am__append_1 = $(CPPUNIT_CXXFLAGS)
 @ENABLE_UNIT_TESTS_TRUE@am__append_2 = $(CPPUNIT_LDFLAGS)
+@ENABLE_OBEX_TRUE@am__append_3 = ObexTransportAgent.h ObexTransportAgent.cpp
+@ENABLE_OBEX_TRUE@am__append_4 = $(LIBOPENOBEX_LIBS)
+@ENABLE_OBEX_TRUE@am__append_5 = $(LIBOPENOBEX_CFLAGS)
+@ENABLE_BLUETOOTH_TRUE@@ENABLE_OBEX_TRUE@am__append_6 = $(BLUEZ_LIBS)
+@ENABLE_BLUETOOTH_TRUE@@ENABLE_OBEX_TRUE@am__append_7 = $(BLUEZ_CFLAGS)
 subdir = src/syncevo
 DIST_COMMON = $(libsyncevolution_include_HEADERS) \
        $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
@@ -60,15 +65,37 @@ libLTLIBRARIES_INSTALL = $(INSTALL)
 LTLIBRARIES = $(lib_LTLIBRARIES)
 am__DEPENDENCIES_1 =
 @ENABLE_UNIT_TESTS_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
-am__DEPENDENCIES_3 = $(am__DEPENDENCIES_2)
-libsyncevolution_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
-       $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_3)
-am__objects_1 = libsyncevolution_la-eds_abi_wrapper.lo \
+@ENABLE_OBEX_TRUE@am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1)
+@ENABLE_BLUETOOTH_TRUE@@ENABLE_OBEX_TRUE@am__DEPENDENCIES_4 = $(am__DEPENDENCIES_1)
+am__DEPENDENCIES_5 = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_3) \
+       $(am__DEPENDENCIES_4)
+am__libsyncevolution_la_SOURCES_DIST = ConfigTree.h ConfigNode.h \
+       HashConfigNode.h VolatileConfigNode.h VolatileConfigTree.h \
+       SmartPtr.h eds_abi_wrapper.h eds_abi_wrapper.cpp SyncML.h \
+       SyncML.cpp SynthesisEngine.h SynthesisEngine.cpp Logging.h \
+       Logging.cpp LogStdout.h LogStdout.cpp LogRedirect.h \
+       LogRedirect.cpp TransportAgent.h TransportAgent.cpp \
+       CurlTransportAgent.h CurlTransportAgent.cpp \
+       SoupTransportAgent.h SoupTransportAgent.cpp util.cpp util.h \
+       Cmdline.cpp Cmdline.h SyncSource.h SyncSource.cpp \
+       SynthesisDBPlugin.cpp SyncEvolutionXML.c SyncContext.h \
+       SyncContext.cpp SyncConfig.h SyncConfig.cpp \
+       DevNullConfigNode.h MultiplexConfigNode.h \
+       MultiplexConfigNode.cpp FilterConfigNode.h \
+       FilterConfigNode.cpp SafeConfigNode.h SafeConfigNode.cpp \
+       PrefixConfigNode.h PrefixConfigNode.cpp FileConfigNode.h \
+       FileConfigNode.cpp FileConfigTree.h FileConfigTree.cpp \
+       TrackingSyncSource.h TrackingSyncSource.cpp \
+       ObexTransportAgent.h ObexTransportAgent.cpp
+@ENABLE_OBEX_TRUE@am__objects_1 =  \
+@ENABLE_OBEX_TRUE@     libsyncevolution_la-ObexTransportAgent.lo
+am__objects_2 = libsyncevolution_la-eds_abi_wrapper.lo \
        libsyncevolution_la-SyncML.lo \
        libsyncevolution_la-SynthesisEngine.lo \
        libsyncevolution_la-Logging.lo \
        libsyncevolution_la-LogStdout.lo \
        libsyncevolution_la-LogRedirect.lo \
+       libsyncevolution_la-TransportAgent.lo \
        libsyncevolution_la-CurlTransportAgent.lo \
        libsyncevolution_la-SoupTransportAgent.lo \
        libsyncevolution_la-util.lo libsyncevolution_la-Cmdline.lo \
@@ -77,13 +104,14 @@ am__objects_1 = libsyncevolution_la-eds_abi_wrapper.lo \
        libsyncevolution_la-SyncEvolutionXML.lo \
        libsyncevolution_la-SyncContext.lo \
        libsyncevolution_la-SyncConfig.lo \
+       libsyncevolution_la-MultiplexConfigNode.lo \
        libsyncevolution_la-FilterConfigNode.lo \
        libsyncevolution_la-SafeConfigNode.lo \
        libsyncevolution_la-PrefixConfigNode.lo \
        libsyncevolution_la-FileConfigNode.lo \
        libsyncevolution_la-FileConfigTree.lo \
-       libsyncevolution_la-TrackingSyncSource.lo
-am_libsyncevolution_la_OBJECTS = $(am__objects_1)
+       libsyncevolution_la-TrackingSyncSource.lo $(am__objects_1)
+am_libsyncevolution_la_OBJECTS = $(am__objects_2)
 libsyncevolution_la_OBJECTS = $(am_libsyncevolution_la_OBJECTS)
 libsyncevolution_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
        $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
@@ -111,7 +139,7 @@ CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
        --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
        $(LDFLAGS) -o $@
 SOURCES = $(libsyncevolution_la_SOURCES)
-DIST_SOURCES = $(libsyncevolution_la_SOURCES)
+DIST_SOURCES = $(am__libsyncevolution_la_SOURCES_DIST)
 pkgconfigDATA_INSTALL = $(INSTALL_DATA)
 DATA = $(pkgconfig_DATA)
 libsyncevolution_includeHEADERS_INSTALL = $(INSTALL_HEADER)
@@ -131,6 +159,8 @@ AUTOMAKE = @AUTOMAKE@
 AWK = @AWK@
 BACKEND_CPPFLAGS = @BACKEND_CPPFLAGS@
 BACKEND_DEFINES = @BACKEND_DEFINES@
+BLUEZ_CFLAGS = @BLUEZ_CFLAGS@
+BLUEZ_LIBS = @BLUEZ_LIBS@
 BOOST_CPPFLAGS = @BOOST_CPPFLAGS@
 BOOST_LDFLAGS = @BOOST_LDFLAGS@
 CATALOGS = @CATALOGS@
@@ -138,7 +168,6 @@ CATOBJEXT = @CATOBJEXT@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
-CLEAN_CLIENT_SRC = @CLEAN_CLIENT_SRC@
 CORE_LDADD_DEP = @CORE_LDADD_DEP@
 CPP = @CPP@
 CPPFLAGS = @CPPFLAGS@
@@ -151,8 +180,10 @@ CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
 DATADIRNAME = @DATADIRNAME@
 DBUS_BINDING_TOOL = @DBUS_BINDING_TOOL@
+DBUS_CFLAGS = @DBUS_CFLAGS@
 DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@
 DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@
+DBUS_LIBS = @DBUS_LIBS@
 DBUS_SERVICES_DIR = @DBUS_SERVICES_DIR@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
@@ -179,11 +210,7 @@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
 GLIB_LIBS = @GLIB_LIBS@
 GMOFILES = @GMOFILES@
 GMSGFMT = @GMSGFMT@
-GOBJECT_CFLAGS = @GOBJECT_CFLAGS@
-GOBJECT_LIBS = @GOBJECT_LIBS@
 GREP = @GREP@
-GTHREAD_CFLAGS = @GTHREAD_CFLAGS@
-GTHREAD_LIBS = @GTHREAD_LIBS@
 GTK_BUILDER_CONV = @GTK_BUILDER_CONV@
 GUI_CFLAGS = @GUI_CFLAGS@
 GUI_DESKTOP_FILES = @GUI_DESKTOP_FILES@
@@ -207,6 +234,8 @@ KEYRING_LIBS = @KEYRING_LIBS@
 LDFLAGS = @LDFLAGS@
 LIBEXECDIR = @LIBEXECDIR@
 LIBOBJS = @LIBOBJS@
+LIBOPENOBEX_CFLAGS = @LIBOPENOBEX_CFLAGS@
+LIBOPENOBEX_LIBS = @LIBOPENOBEX_LIBS@
 LIBS = @LIBS@
 LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@
 LIBSOUP_LIBS = @LIBSOUP_LIBS@
@@ -214,8 +243,6 @@ LIBTOOL = @LIBTOOL@
 LN_S = @LN_S@
 LTLIBOBJS = @LTLIBOBJS@
 MAKEINFO = @MAKEINFO@
-MCALB_CFLAGS = @MCALB_CFLAGS@
-MCALB_LIBS = @MCALB_LIBS@
 MKDIR_P = @MKDIR_P@
 MKINSTALLDIRS = @MKINSTALLDIRS@
 MODIFY_SYNCCOMPARE = @MODIFY_SYNCCOMPARE@
@@ -246,14 +273,17 @@ STRIP = @STRIP@
 
 # applies to sources in SyncEvolution repository, but not
 # the Funambol C++ client library
-SYNCEVOLUTION_CXXFLAGS = @SYNCEVOLUTION_CXXFLAGS@ $(am__append_1)
-SYNCEVOLUTION_LDADD = @SYNCEVOLUTION_LDADD@ $(am__append_2)
+SYNCEVOLUTION_CXXFLAGS = @SYNCEVOLUTION_CXXFLAGS@ $(am__append_1) \
+       $(am__append_5) $(am__append_7)
+SYNCEVOLUTION_LDADD = @SYNCEVOLUTION_LDADD@ $(am__append_2) \
+       $(am__append_4) $(am__append_6)
 SYNCEVOLUTION_LOCALEDIR = @SYNCEVOLUTION_LOCALEDIR@
 SYNCSOURCES = @SYNCSOURCES@
 SYNTHESIS = @SYNTHESIS@
 SYNTHESISSRC = @SYNTHESISSRC@
 SYNTHESIS_CFLAGS = @SYNTHESIS_CFLAGS@
 SYNTHESIS_DEP = @SYNTHESIS_DEP@
+SYNTHESIS_ENGINE = @SYNTHESIS_ENGINE@
 SYNTHESIS_LIB = @SYNTHESIS_LIB@
 SYNTHESIS_LIBS = @SYNTHESIS_LIBS@
 SYNTHESIS_SRC = @SYNTHESIS_SRC@
@@ -265,8 +295,6 @@ UNIQUE_LIBS = @UNIQUE_LIBS@
 USE_NLS = @USE_NLS@
 VERSION = @VERSION@
 XGETTEXT = @XGETTEXT@
-XMLRPC_CFLAGS = @XMLRPC_CFLAGS@
-XMLRPC_LIBS = @XMLRPC_LIBS@
 XSLT = @XSLT@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
@@ -324,72 +352,22 @@ top_srcdir = @top_srcdir@
 AM_CPPFLAGS = @BACKEND_CPPFLAGS@ @GLIB_CFLAGS@ -I$(top_srcdir)/test -I$(top_srcdir)/src -DSYNCEVO_BACKEND=\"$(backendsearchdir)\"
 MAINTAINERCLEANFILES = Makefile.in
 lib_LTLIBRARIES = libsyncevolution.la
-SYNCEVOLUTION_SOURCES = \
-       ConfigTree.h \
-       ConfigNode.h \
-       HashConfigNode.h \
-       VolatileConfigNode.h \
-       VolatileConfigTree.h \
-        SmartPtr.h \
-       eds_abi_wrapper.h \
-       eds_abi_wrapper.cpp \
-       \
-       SyncML.h \
-       SyncML.cpp \
-       \
-       SynthesisEngine.h \
-       SynthesisEngine.cpp \
-       \
-       Logging.h \
-       Logging.cpp \
-       LogStdout.h \
-       LogStdout.cpp \
-       LogRedirect.h \
-       LogRedirect.cpp \
-       \
-       TransportAgent.h \
-       CurlTransportAgent.h \
-       CurlTransportAgent.cpp \
-       \
-       SoupTransportAgent.h \
-       SoupTransportAgent.cpp \
-       \
-       util.cpp \
-       util.h \
-        \
-       Cmdline.cpp \
-        Cmdline.h \
-       \
-        SyncSource.h \
-        SyncSource.cpp \
-       \
-       SynthesisDBPlugin.cpp \
-       \
-       SyncEvolutionXML.c \
-        SyncContext.h \
-       SyncContext.cpp \
-       \
-       SyncConfig.h \
-       SyncConfig.cpp \
-       \
-       FilterConfigNode.h \
-       FilterConfigNode.cpp \
-       \
-       SafeConfigNode.h \
-       SafeConfigNode.cpp \
-       \
-       PrefixConfigNode.h \
-       PrefixConfigNode.cpp \
-       \
-       FileConfigNode.h \
-       FileConfigNode.cpp \
-       \
-       FileConfigTree.h \
-       FileConfigTree.cpp \
-       \
-       TrackingSyncSource.h \
-       TrackingSyncSource.cpp
-
+SYNCEVOLUTION_SOURCES = ConfigTree.h ConfigNode.h HashConfigNode.h \
+       VolatileConfigNode.h VolatileConfigTree.h SmartPtr.h \
+       eds_abi_wrapper.h eds_abi_wrapper.cpp SyncML.h SyncML.cpp \
+       SynthesisEngine.h SynthesisEngine.cpp Logging.h Logging.cpp \
+       LogStdout.h LogStdout.cpp LogRedirect.h LogRedirect.cpp \
+       TransportAgent.h TransportAgent.cpp CurlTransportAgent.h \
+       CurlTransportAgent.cpp SoupTransportAgent.h \
+       SoupTransportAgent.cpp util.cpp util.h Cmdline.cpp Cmdline.h \
+       SyncSource.h SyncSource.cpp SynthesisDBPlugin.cpp \
+       SyncEvolutionXML.c SyncContext.h SyncContext.cpp SyncConfig.h \
+       SyncConfig.cpp DevNullConfigNode.h MultiplexConfigNode.h \
+       MultiplexConfigNode.cpp FilterConfigNode.h \
+       FilterConfigNode.cpp SafeConfigNode.h SafeConfigNode.cpp \
+       PrefixConfigNode.h PrefixConfigNode.cpp FileConfigNode.h \
+       FileConfigNode.cpp FileConfigTree.h FileConfigTree.cpp \
+       TrackingSyncSource.h TrackingSyncSource.cpp $(am__append_3)
 libsyncevolution_includedir = $(includedir)/syncevo
 libsyncevolution_include_HEADERS = \
        declarations.h \
@@ -416,6 +394,7 @@ libsyncevolution_la_SOURCES = $(SYNCEVOLUTION_SOURCES)
 libsyncevolution_la_LIBADD = @EPACKAGE_LIBS@ @GLIB_LIBS@ $(SYNTHESIS_LIBS) $(TRANSPORT_LIBS) @LIBS@ $(SYNCEVOLUTION_LDADD)
 libsyncevolution_la_CXXFLAGS = $(TRANSPORT_CFLAGS) $(SYNCEVOLUTION_CXXFLAGS) $(SYNTHESIS_CFLAGS)
 libsyncevolution_la_CPPFLAGS = $(AM_CPPFLAGS) -DTEMPLATE_DIR=\""$(datadir)/syncevolution/templates"\" -DLIBDIR=\""$(libdir)"\"
+libsyncevolution_la_DEPENDENCIES = $(SYNTHESIS_DEP)
 @ENABLE_MODULES_FALSE@libsyncevolution_la_LDFLAGS = -static
 @ENABLE_MODULES_TRUE@libsyncevolution_la_LDFLAGS = 
 all: all-am
@@ -497,6 +476,8 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsyncevolution_la-LogRedirect.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsyncevolution_la-LogStdout.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsyncevolution_la-Logging.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsyncevolution_la-MultiplexConfigNode.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsyncevolution_la-ObexTransportAgent.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsyncevolution_la-PrefixConfigNode.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsyncevolution_la-SafeConfigNode.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsyncevolution_la-SoupTransportAgent.Plo@am__quote@
@@ -508,6 +489,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsyncevolution_la-SynthesisDBPlugin.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsyncevolution_la-SynthesisEngine.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsyncevolution_la-TrackingSyncSource.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsyncevolution_la-TransportAgent.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsyncevolution_la-eds_abi_wrapper.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsyncevolution_la-util.Plo@am__quote@
 
@@ -602,6 +584,13 @@ libsyncevolution_la-LogRedirect.lo: LogRedirect.cpp
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsyncevolution_la_CPPFLAGS) $(CPPFLAGS) $(libsyncevolution_la_CXXFLAGS) $(CXXFLAGS) -c -o libsyncevolution_la-LogRedirect.lo `test -f 'LogRedirect.cpp' || echo '$(srcdir)/'`LogRedirect.cpp
 
+libsyncevolution_la-TransportAgent.lo: TransportAgent.cpp
+@am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsyncevolution_la_CPPFLAGS) $(CPPFLAGS) $(libsyncevolution_la_CXXFLAGS) $(CXXFLAGS) -MT libsyncevolution_la-TransportAgent.lo -MD -MP -MF $(DEPDIR)/libsyncevolution_la-TransportAgent.Tpo -c -o libsyncevolution_la-TransportAgent.lo `test -f 'TransportAgent.cpp' || echo '$(srcdir)/'`TransportAgent.cpp
+@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/libsyncevolution_la-TransportAgent.Tpo $(DEPDIR)/libsyncevolution_la-TransportAgent.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='TransportAgent.cpp' object='libsyncevolution_la-TransportAgent.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsyncevolution_la_CPPFLAGS) $(CPPFLAGS) $(libsyncevolution_la_CXXFLAGS) $(CXXFLAGS) -c -o libsyncevolution_la-TransportAgent.lo `test -f 'TransportAgent.cpp' || echo '$(srcdir)/'`TransportAgent.cpp
+
 libsyncevolution_la-CurlTransportAgent.lo: CurlTransportAgent.cpp
 @am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsyncevolution_la_CPPFLAGS) $(CPPFLAGS) $(libsyncevolution_la_CXXFLAGS) $(CXXFLAGS) -MT libsyncevolution_la-CurlTransportAgent.lo -MD -MP -MF $(DEPDIR)/libsyncevolution_la-CurlTransportAgent.Tpo -c -o libsyncevolution_la-CurlTransportAgent.lo `test -f 'CurlTransportAgent.cpp' || echo '$(srcdir)/'`CurlTransportAgent.cpp
 @am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/libsyncevolution_la-CurlTransportAgent.Tpo $(DEPDIR)/libsyncevolution_la-CurlTransportAgent.Plo
@@ -658,6 +647,13 @@ libsyncevolution_la-SyncConfig.lo: SyncConfig.cpp
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsyncevolution_la_CPPFLAGS) $(CPPFLAGS) $(libsyncevolution_la_CXXFLAGS) $(CXXFLAGS) -c -o libsyncevolution_la-SyncConfig.lo `test -f 'SyncConfig.cpp' || echo '$(srcdir)/'`SyncConfig.cpp
 
+libsyncevolution_la-MultiplexConfigNode.lo: MultiplexConfigNode.cpp
+@am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsyncevolution_la_CPPFLAGS) $(CPPFLAGS) $(libsyncevolution_la_CXXFLAGS) $(CXXFLAGS) -MT libsyncevolution_la-MultiplexConfigNode.lo -MD -MP -MF $(DEPDIR)/libsyncevolution_la-MultiplexConfigNode.Tpo -c -o libsyncevolution_la-MultiplexConfigNode.lo `test -f 'MultiplexConfigNode.cpp' || echo '$(srcdir)/'`MultiplexConfigNode.cpp
+@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/libsyncevolution_la-MultiplexConfigNode.Tpo $(DEPDIR)/libsyncevolution_la-MultiplexConfigNode.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='MultiplexConfigNode.cpp' object='libsyncevolution_la-MultiplexConfigNode.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsyncevolution_la_CPPFLAGS) $(CPPFLAGS) $(libsyncevolution_la_CXXFLAGS) $(CXXFLAGS) -c -o libsyncevolution_la-MultiplexConfigNode.lo `test -f 'MultiplexConfigNode.cpp' || echo '$(srcdir)/'`MultiplexConfigNode.cpp
+
 libsyncevolution_la-FilterConfigNode.lo: FilterConfigNode.cpp
 @am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsyncevolution_la_CPPFLAGS) $(CPPFLAGS) $(libsyncevolution_la_CXXFLAGS) $(CXXFLAGS) -MT libsyncevolution_la-FilterConfigNode.lo -MD -MP -MF $(DEPDIR)/libsyncevolution_la-FilterConfigNode.Tpo -c -o libsyncevolution_la-FilterConfigNode.lo `test -f 'FilterConfigNode.cpp' || echo '$(srcdir)/'`FilterConfigNode.cpp
 @am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/libsyncevolution_la-FilterConfigNode.Tpo $(DEPDIR)/libsyncevolution_la-FilterConfigNode.Plo
@@ -700,6 +696,13 @@ libsyncevolution_la-TrackingSyncSource.lo: TrackingSyncSource.cpp
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsyncevolution_la_CPPFLAGS) $(CPPFLAGS) $(libsyncevolution_la_CXXFLAGS) $(CXXFLAGS) -c -o libsyncevolution_la-TrackingSyncSource.lo `test -f 'TrackingSyncSource.cpp' || echo '$(srcdir)/'`TrackingSyncSource.cpp
 
+libsyncevolution_la-ObexTransportAgent.lo: ObexTransportAgent.cpp
+@am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsyncevolution_la_CPPFLAGS) $(CPPFLAGS) $(libsyncevolution_la_CXXFLAGS) $(CXXFLAGS) -MT libsyncevolution_la-ObexTransportAgent.lo -MD -MP -MF $(DEPDIR)/libsyncevolution_la-ObexTransportAgent.Tpo -c -o libsyncevolution_la-ObexTransportAgent.lo `test -f 'ObexTransportAgent.cpp' || echo '$(srcdir)/'`ObexTransportAgent.cpp
+@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/libsyncevolution_la-ObexTransportAgent.Tpo $(DEPDIR)/libsyncevolution_la-ObexTransportAgent.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='ObexTransportAgent.cpp' object='libsyncevolution_la-ObexTransportAgent.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsyncevolution_la_CPPFLAGS) $(CPPFLAGS) $(libsyncevolution_la_CXXFLAGS) $(CXXFLAGS) -c -o libsyncevolution_la-ObexTransportAgent.lo `test -f 'ObexTransportAgent.cpp' || echo '$(srcdir)/'`ObexTransportAgent.cpp
+
 mostlyclean-libtool:
        -rm -f *.lo
 
diff --git a/src/syncevo/MultiplexConfigNode.cpp b/src/syncevo/MultiplexConfigNode.cpp
new file mode 100644 (file)
index 0000000..3aa1341
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2009 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) version 3.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301  USA
+ */
+
+#include <syncevo/MultiplexConfigNode.h>
+#include <boost/algorithm/string/predicate.hpp>
+
+SE_BEGIN_CXX
+
+FilterConfigNode *
+MultiplexConfigNode::getNode(const string &property,
+                             const ConfigProperty **found) const
+{
+    BOOST_FOREACH(const ConfigProperty *prop, m_registry) {
+        if (boost::iequals(prop->getName(), property)) {
+            if (found) {
+                *found = prop;
+            }
+
+            FilterConfigNode *node = 
+                m_nodes[prop->isHidden()][prop->getSharing()].get();
+
+            // special case: fall back to shared node if no unshared
+            // node, and property isprimarily stored unshared, but
+            // also in the shared node
+            if (!node &&
+                (prop->getFlags() & ConfigProperty::SHARED_AND_UNSHARED)) {
+                node = m_nodes[prop->isHidden()][ConfigProperty::SOURCE_SET_SHARING].get();
+            }
+
+            return node;
+        }
+    }
+
+    return NULL;
+}
+
+void MultiplexConfigNode::addFilter(const string &property,
+                                    const string &value)
+{
+    FilterConfigNode::addFilter(property, value);
+    for (int i = 0; i < 2; i++) {
+        for (int e = 0; e < 3; e++) {
+            if (m_nodes[i][e]) {
+                m_nodes[i][e]->addFilter(property, value);
+            }
+        }
+    }
+}
+
+void MultiplexConfigNode::setFilter(const ConfigFilter &filter)
+{
+    FilterConfigNode::setFilter(filter);
+    for (int i = 0; i < 2; i++) {
+        for (int e = 0; e < 3; e++) {
+            if (m_nodes[i][e]) {
+                m_nodes[i][e]->setFilter(filter);
+            }
+        }
+    }
+}
+
+void MultiplexConfigNode::flush()
+{
+    for (int i = 0; i < 2; i++) {
+        for (int e = 0; e < 3; e++) {
+            if (m_nodes[i][e]) {
+                m_nodes[i][e]->flush();
+            }
+        }
+    }
+}
+
+string MultiplexConfigNode::readProperty(const string &property) const
+{
+    FilterConfigNode *node = getNode(property);
+    if (node) {
+        return node->readProperty(property);
+    } else {
+        return "";
+    }
+}
+
+void MultiplexConfigNode::setProperty(const string &property,
+                                      const string &value,
+                                      const string &comment,
+                                      const string *defValue)
+{
+    const ConfigProperty *prop;
+    FilterConfigNode *node = getNode(property, &prop);
+    if (node) {
+        node->setProperty(property, value, comment, defValue);
+        bool hidden = prop->isHidden();
+        if (node == m_nodes[hidden][ConfigProperty::NO_SHARING].get() &&
+            (node = m_nodes[hidden][ConfigProperty::SOURCE_SET_SHARING].get()) != NULL &&
+            (prop->getFlags() & ConfigProperty::SHARED_AND_UNSHARED)) {
+            node->setProperty(property, value, comment, defValue);
+        }
+    } else {
+        SE_THROW(property + ": not supported by configuration multiplexer");
+    }
+}
+
+void MultiplexConfigNode::readProperties(PropsType &props) const
+{
+    for (int i = 0; i < 2; i++) {
+        for (int e = 0; e < 3; e++) {
+            if (m_nodes[i][e]) {
+                m_nodes[i][e]->readProperties(props);
+            }
+        }
+    }
+}
+
+void MultiplexConfigNode::removeProperty(const string &property)
+{
+#if 1
+    SE_THROW(property + ": removing via configuration multiplexer not supported");
+#else
+    for (int i = 0; i < 2; i++) {
+        for (int e = 0; e < 3; e++) {
+            if (m_nodes[i][e]) {
+                m_nodes[i][e]->removeProperty(property);
+            }
+        }
+    }
+#endif
+}
+
+void MultiplexConfigNode::clear()
+{
+#if 1
+    SE_THROW("configuration multiplexer cannot be cleared");
+#else
+    for (int i = 0; i < 2; i++) {
+        for (int e = 0; e < 3; e++) {
+            if (m_nodes[i][e]) {
+                m_nodes[i][e]->clear();
+            }
+        }
+    }
+#endif
+}
+
+bool MultiplexConfigNode::exists() const
+{
+    for (int i = 0; i < 2; i++) {
+        for (int e = 0; e < 3; e++) {
+            if (m_nodes[i][e] &&
+                m_nodes[i][e]->exists()) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+SE_END_CXX
diff --git a/src/syncevo/MultiplexConfigNode.h b/src/syncevo/MultiplexConfigNode.h
new file mode 100644 (file)
index 0000000..960dea8
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2009 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) version 3.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301  USA
+ */
+#ifndef INCL_SYNCEVO_MULTIPLEX_CONFIG_NODE
+# define INCL_SYNCEVO_MULTIPLEX_CONFIG_NODE
+
+#include <syncevo/declarations.h>
+#include <syncevo/ConfigNode.h>
+#include <syncevo/SyncConfig.h>
+SE_BEGIN_CXX
+
+/**
+ * Joins properties from the different nodes that might be used by a
+ * SyncConfig or SyncSourceConfig (global/shared/not shared,
+ * hidden/user-visible) and presents them as one node. Reading takes
+ * the union of all set properties. Writing is directed to the
+ * node for which the property was registered.
+ */
+class MultiplexConfigNode : public FilterConfigNode
+{
+    const std::string m_name;
+    boost::shared_ptr<FilterConfigNode> m_nodes[2][3];
+    const ConfigPropertyRegistry &m_registry;
+    int m_hiddenLower, m_hiddenUpper;
+
+    FilterConfigNode *getNode(const string &property,
+                              const ConfigProperty **prop = NULL) const;
+
+ public:
+    /** join both hidden and user-visible properties */
+    MultiplexConfigNode(const std::string &name,
+                        const ConfigPropertyRegistry &registry) :
+        FilterConfigNode(boost::shared_ptr<ConfigNode>()),
+        m_name(name),
+        m_registry(registry),
+        m_hiddenLower(0), m_hiddenUpper(1) {}
+
+    /** only join hidden or user-visible properties */
+    MultiplexConfigNode(const std::string &name,
+                        const ConfigPropertyRegistry &registry,
+                        bool hidden) :
+        FilterConfigNode(boost::shared_ptr<ConfigNode>()),
+        m_name(name),
+        m_registry(registry),
+        m_hiddenLower(hidden), m_hiddenUpper(hidden) {}
+
+    /** configure the nodes to use */
+    void setNode(bool hidden, ConfigProperty::Sharing sharing,
+                 const boost::shared_ptr<FilterConfigNode> &node) {
+        m_nodes[hidden][sharing] = node;
+    }
+    void setNode(bool hidden, ConfigProperty::Sharing sharing,
+                 const boost::shared_ptr<ConfigNode> &node) {
+        m_nodes[hidden][sharing].reset(new FilterConfigNode(node));
+    }
+
+    virtual void addFilter(const string &property,
+                           const string &value);
+    virtual void setFilter(const ConfigFilter &filter);
+
+    virtual string getName() const { return m_name; }
+    virtual void flush();
+    virtual string readProperty(const string &property) const;
+    virtual void setProperty(const string &property,
+                             const string &value,
+                             const string &comment = string(""),
+                             const string *defValue = NULL);
+    virtual void readProperties(PropsType &props) const;
+
+    /*
+     * removing or clearing something is not implemented because it is
+     * not certain what should be deleted: only properties which are
+     * not shared?!
+     */
+    virtual void removeProperty(const string &property);
+    virtual void clear();
+
+    /**
+     * true if any of the nodes exists
+     */
+    virtual bool exists() const;
+};
+
+SE_END_CXX
+
+#endif // INCL_SYNCEVO_MULTIPLEX_CONFIG_NODE
diff --git a/src/syncevo/ObexTransportAgent.cpp b/src/syncevo/ObexTransportAgent.cpp
new file mode 100644 (file)
index 0000000..ce7a7b0
--- /dev/null
@@ -0,0 +1,798 @@
+/*
+ * Copyright (C) 2009 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) version 3.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301  USA
+ */
+
+#include <config.h>
+
+#ifdef ENABLE_OBEX
+#ifdef ENABLE_BLUETOOTH
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>
+#include <bluetooth/rfcomm.h>
+#endif
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <glib/giochannel.h>
+#include <syncevo/SyncContext.h>
+#include <syncevo/ObexTransportAgent.h>
+
+#include <syncevo/declarations.h>
+
+SE_BEGIN_CXX
+
+ObexTransportAgent::ObexTransportAgent (OBEX_TRANS_TYPE type) :
+    m_status(INACTIVE),
+    m_transType(type),
+    m_address(""),
+    m_port(-1),
+    m_buffer(NULL),
+    m_bufferSize(0),
+    m_cb(NULL),
+    m_disconnecting(false),
+    m_connectStatus(START)
+{
+}
+
+ObexTransportAgent::~ObexTransportAgent()
+{
+    if(m_buffer){
+        free (m_buffer);
+    }
+}
+
+/*
+ * Only setURL if the address/port has not been initialized;
+ * because the URL is not likely be changed during a
+ * sync session. 
+ * For Bluetooth devices the URL maybe splitted as two parts:
+ * address and channel, the delimiter is '+'.
+ **/
+void ObexTransportAgent::setURL(const std::string &url)
+{
+    if(m_address.empty()){
+        if(m_transType == OBEX_BLUETOOTH) {
+            size_t pos = url.find_last_of('+');
+            if (pos != std::string::npos) {
+                m_address = url.substr(0,pos);
+                m_port = atoi(url.substr(pos+1, std::string::npos).c_str());
+                if(!m_port) {
+                    SE_THROW_EXCEPTION(TransportException, "ObexTransport: Malformed url");
+                }
+            } else {
+                m_address = url;
+            }
+            if(m_address.empty()) {
+                SE_THROW_EXCEPTION (TransportException, "ObexTransport: Malformed url");
+            }
+        }
+    }
+}
+
+void ObexTransportAgent::setContentType(const std::string &type) {
+    m_contentType = type;
+}
+
+
+void ObexTransportAgent::setCallback (TransportCallback cb, void *data, int interval)
+{
+    m_cb = cb;
+    m_cbData = data;
+    m_cbInterval = interval;
+}
+
+void ObexTransportAgent::connect() {
+    m_obexReady = false;
+    if(m_transType == OBEX_BLUETOOTH) {
+        if(m_port == -1) {
+            //use sdp to detect the appropriate channel
+            //Do not use BDADDR_ANY to avoid a warning
+            bdaddr_t bdaddr, anyaddr ={{0,0,0,0,0,0}};
+            str2ba (m_address.c_str(), &bdaddr);
+            m_sdp = sdp_connect(&anyaddr, &bdaddr, SDP_NON_BLOCKING);
+            if(!m_sdp) {
+                SE_THROW_EXCEPTION (TransportException, "ObexTransport Bluetooth sdp connect failed");
+            }
+            m_connectStatus = SDP_START;
+            GIOChannel *sdpIO = g_io_channel_unix_new (sdp_get_socket (m_sdp));
+            if (sdpIO == NULL) {
+                sdp_close (m_sdp);
+                SE_THROW_EXCEPTION (TransportException, "ObexTransport: sdp socket channel create failed");
+            }
+            g_io_add_watch (sdpIO, (GIOCondition) (G_IO_IN|G_IO_OUT|G_IO_HUP|G_IO_ERR|G_IO_NVAL), sdp_source_cb, static_cast <void*> (this));
+            g_io_channel_unref (sdpIO);
+        } else {
+            m_connectStatus = ADDR_READY;
+            connectInit();
+        }
+    }
+    /*Wait until connection is sucessfully set up*/
+    wait(true);
+    if (m_connectStatus != CONNECTED) {
+        SE_THROW_EXCEPTION (TransportException, "ObexTransport: connection setup failed");
+    }
+}
+
+/*
+ * Called when the address of remote peer is available, maybe via some
+ * discovery mechanism.
+ */
+void ObexTransportAgent::connectInit () {
+    if (m_connectStatus != ADDR_READY) {
+        SE_THROW_EXCEPTION (TransportException, "ObexTransport: address info for remote peer not ready");
+    }
+    if(m_transType == OBEX_BLUETOOTH) {
+        bdaddr_t bdaddr;
+        str2ba (m_address.c_str(), &bdaddr);
+        if(m_port == -1) {
+            SE_THROW_EXCEPTION (TransportException, 
+                    "ObexTransport: no channel found for Bluetooth peer");
+        }
+        int sockfd = socket (AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
+        if (sockfd == -1) {
+            SE_THROW_EXCEPTION (TransportException, "Error creating Bluetooth socket");
+        }
+        cxxptr<Socket> sockObj (new Socket (sockfd));  
+        SE_LOG_DEV(NULL,NULL, "Connecting Bluetooth device with address %s and channel %d",
+                m_address.c_str(), m_port);
+        // Init the OBEX handle
+        obex_t *h = OBEX_Init (OBEX_TRANS_FD, obex_event, 0);
+        if(!h) {
+            SE_THROW_EXCEPTION (TransportException, "ObexTransport: Obex Handle Init failed");
+        }
+
+        cxxptr<ObexHandle> handle (new ObexHandle (h));
+        OBEX_SetUserData (handle->get(), static_cast<void *> (this));
+        // Connect the device, do not use BtOBEX_TransportConnect as it is
+        // blocking.
+        sockaddr_rc any;
+        bdaddr_t anyaddr ={{0,0,0,0,0,0}};
+        any.rc_family = AF_BLUETOOTH;
+        bacpy (&any.rc_bdaddr, &anyaddr);
+        any.rc_channel = 0;
+        if (bind (sockfd, (struct sockaddr *) &any, sizeof (sockaddr_rc)) <0){
+            SE_THROW_EXCEPTION (TransportException, "ObexTransport: Socket bind failed");
+        }
+        //set socket to non-blocking
+        int flags = fcntl (sockfd, F_GETFL);
+        fcntl(sockfd, F_SETFL, flags & ~O_NONBLOCK);
+        //create the io channel
+        cxxptr<Channel> channel (new Channel (g_io_channel_unix_new (sockfd)));
+        if(!channel) {
+            SE_THROW_EXCEPTION (TransportException, "ObexTransport: io channel create failed");
+        }
+        guint obexEventSource = g_io_add_watch (channel->get(), (GIOCondition) (G_IO_IN|G_IO_OUT|G_IO_HUP|G_IO_ERR|G_IO_NVAL), obex_fd_source_cb, static_cast<void *> (this));
+
+        cxxptr<ObexEvent> obexEvent (new ObexEvent (obexEventSource));
+        //connect to remote device
+        sockaddr_rc peer;
+        peer.rc_family = AF_BLUETOOTH;
+        bacpy (&peer.rc_bdaddr , &bdaddr);
+        peer.rc_channel = m_port;
+
+        if (::connect (sockfd, (struct sockaddr *) &peer, sizeof (sockaddr_rc)) == -1) {
+            //check the error status
+            if (errno == EINPROGRESS || errno == EAGAIN){
+                m_connectStatus = INIT0;
+                //copy sockobj so that it will not close the underlying socket
+                m_sock = sockObj;
+                m_obexEvent = obexEvent;
+                m_channel = channel;
+                m_handle = handle;
+                return;
+            } else {
+                SE_LOG_ERROR (NULL, NULL, "connect failed with error code %d", errno);
+                SE_THROW_EXCEPTION (TransportException, "ObexTransport: connect request failed with error");
+            }
+        }
+
+        // Put Connect Cmd to init the session
+        m_connectStatus = INIT1;
+        m_sock = sockObj;
+        m_obexEvent = obexEvent;
+        m_channel = channel;
+        m_handle = handle;
+        connectReq();
+    }//Bluetooth
+    else {
+        m_status = FAILED;
+        SE_LOG_ERROR (NULL, NULL, "ObexTransport: unsuported transport type");
+        return;
+    }
+}
+
+/* After OBEX Handle is inited and the device is connected, 
+ * send the connect cmd to initialize the session 
+ */
+void ObexTransportAgent::connectReq() {
+    if (m_connectStatus!=INIT1 || !m_handle) {
+        SE_THROW_EXCEPTION (TransportException, "ObexTransport: OBEX Handle not inited or device not connected");
+    }
+
+    //set up transport mtu
+    OBEX_SetTransportMTU (m_handle->get(), DEFAULT_RX_MTU, DEFAULT_TX_MTU);
+
+    // set up the fd transport
+    if (FdOBEX_TransportSetup (m_handle->get(), m_sock->get(), m_sock->get(), OBEX_MAXIMUM_MTU) <0) {
+        SE_THROW_EXCEPTION (TransportException, "ObexTransport: Fd transport set up failed");
+    }
+
+    obex_object_t *connect = newCmd(OBEX_CMD_CONNECT);
+    /* Add the header for the sync target */
+    obex_headerdata_t header;
+    header.bs = (unsigned char *) "SYNCML-SYNC";
+    OBEX_ObjectAddHeader(m_handle->get(), connect, OBEX_HDR_TARGET, header, strlen ((char *) header.bs), OBEX_FL_FIT_ONE_PACKET);
+    m_obexReady = false;
+    if (OBEX_Request (m_handle->get(), connect) <0) {
+        SE_THROW_EXCEPTION (TransportException, "ObexTransport: OBEX connect init failed");
+    }
+    m_connectStatus = INIT2;
+}
+
+void ObexTransportAgent::shutdown() {
+    obex_object_t *disconnect = newCmd(OBEX_CMD_DISCONNECT);
+    //add header "connection id"
+    obex_headerdata_t header;
+    header.bq4 = m_connectId;
+    OBEX_ObjectAddHeader (m_handle->get(), disconnect, OBEX_HDR_CONNECTION, header, sizeof
+            (m_connectId), OBEX_FL_FIT_ONE_PACKET);
+
+    /*
+     * This is a must check when working with SyncML server case:
+     * It will not call wait() for the last send(), which caused the
+     * event source set up during that send() has no chance to be removed
+     * until here.
+     * */
+    if (m_obexEvent) {
+        m_obexEvent.set(NULL);
+    }
+
+    //reset up obex fd soruce 
+    guint obexSource = g_io_add_watch (m_channel->get(), (GIOCondition) (G_IO_IN|G_IO_OUT|G_IO_HUP|G_IO_ERR|G_IO_NVAL), obex_fd_source_cb, static_cast<void *> (this));
+    cxxptr<ObexEvent> obexEventSource (new ObexEvent (obexSource));
+
+    /* It might be true there is an ongoing OBEX request undergoing, 
+     * must cancel it before sending another cmd */
+    OBEX_CancelRequest (m_handle->get(), 0);
+
+    //block a while waiting for the disconnect response, we will disconnects
+    //always even without a response.
+    m_obexReady = false;
+    m_disconnecting = true;
+    if (OBEX_Request (m_handle->get(), disconnect) <0) {
+        m_status = FAILED;
+        SE_THROW_EXCEPTION (TransportException, "ObexTransport: OBEX disconnect cmd failed");
+    }
+    m_obexEvent = obexEventSource;
+}
+
+/**
+ * Send the request to peer
+ */
+void ObexTransportAgent::send(const char *data, size_t len) {
+    SE_LOG_DEV (NULL, NULL, "ObexTransport send is called");
+    cxxptr<Socket> sockObj = m_sock;
+    cxxptr<Channel> channel = m_channel;
+    if(m_connectStatus != CONNECTED) {
+        SE_THROW_EXCEPTION (TransportException, "ObexTransport send: underlying transport is not conncted");
+    }
+    obex_object_t *put = newCmd(OBEX_CMD_PUT);
+    //add header "connection id"
+    obex_headerdata_t header;
+    header.bq4 = m_connectId;
+    OBEX_ObjectAddHeader (m_handle->get(), put, OBEX_HDR_CONNECTION, header, sizeof
+            (m_connectId), OBEX_FL_FIT_ONE_PACKET);
+    //add header "target"
+    header.bs =  reinterpret_cast<unsigned char *> (const_cast <char *>(m_contentType.c_str()));
+    OBEX_ObjectAddHeader (m_handle->get(), put, OBEX_HDR_TYPE, header, m_contentType.size()+1, 0);
+    //add header "length"
+    header.bq4 = len;
+    OBEX_ObjectAddHeader (m_handle->get(), put, OBEX_HDR_LENGTH, header, sizeof (size_t), 0);
+    //add header "body"
+    header.bs = reinterpret_cast <const uint8_t *> (data);
+    OBEX_ObjectAddHeader (m_handle->get(), put, OBEX_HDR_BODY, header, len, 0);
+
+    /*
+     * This is a safe check, the problem is: 
+     * If application called send() and without calling wait() it calls send()
+     * again, this will leading to a event leak.
+     * */
+    if (m_obexEvent) {
+        m_obexEvent.set(NULL);
+    }
+    //reset up the OBEX fd source 
+    guint obexSource = g_io_add_watch (channel->get(), (GIOCondition) (G_IO_IN|G_IO_OUT|G_IO_HUP|G_IO_ERR|G_IO_NVAL), obex_fd_source_cb, static_cast<void *> (this));
+    cxxptr<ObexEvent> obexEventSource (new ObexEvent (obexSource));
+
+    //send the request
+    m_status = ACTIVE;
+    m_requestStart = time (NULL);
+    m_obexReady = false;
+    if (OBEX_Request (m_handle->get(), put) < 0) {
+        SE_THROW_EXCEPTION (TransportException, "ObexTransport: send failed");
+    }
+    m_sock = sockObj;
+    m_channel = channel;
+    m_obexEvent = obexEventSource;
+}
+
+/*
+ * Abort the transport session; 
+ */
+void ObexTransportAgent::cancel() {
+    m_requestStart = 0;
+    if(m_disconnecting) {
+        m_connectStatus = END;
+        OBEX_TransportDisconnect(m_handle->get());
+        SE_LOG_WARNING (NULL, NULL, "Cancel disconncting process");
+        if (m_status != CLOSED) {
+            m_status = FAILED;
+        }
+    } else {
+        m_status = CANCELED;
+        //remove the event source 
+        cxxptr<ObexEvent> obexEventSource = m_obexEvent;
+        shutdown();
+    }
+}
+
+/**
+ * 1)Wait until the connection is set up.
+ * 2)Wait until the response is ready, which means:
+ * waits for the Put request being successfully sent
+ * sends the Get request to pull response 
+ * waits until Get response is successfully received
+ *
+ * Runs the main loop manually so that it does not block other components.
+ */
+TransportAgent::Status ObexTransportAgent::wait(bool noReply) {
+    cxxptr<Socket> sockObj;
+    cxxptr<ObexEvent> obexEvent;
+    cxxptr<Channel> channel;
+
+    while (!m_obexReady) {
+        g_main_context_iteration (NULL, FALSE);
+        if (m_status == FAILED) {
+            if (m_obexEvent) {
+                obexEvent = m_obexEvent;
+            }
+            if (m_sock) {
+                sockObj = m_sock;
+            }
+            if (m_channel) {
+                channel = m_channel;
+            }
+            SE_THROW_EXCEPTION (TransportException, "ObexTransprotAgent: Underlying transport error");
+        }
+    }
+
+    //remove the obex event source here
+    //only at this point we can be sure obexEvent is propertely set up
+    obexEvent = m_obexEvent;
+    sockObj = m_sock;
+    channel = m_channel;
+
+    if (!noReply) {
+        //send the Get request
+        obex_object_t *get = newCmd(OBEX_CMD_GET);
+        //add header "connection id"
+        obex_headerdata_t header;
+        header.bq4 = m_connectId;
+        OBEX_ObjectAddHeader (m_handle->get(), get, OBEX_HDR_CONNECTION, header, sizeof
+                (m_connectId), OBEX_FL_FIT_ONE_PACKET);
+        //add header "target"
+        header.bs =  reinterpret_cast <const unsigned char *> (m_contentType.c_str());
+        OBEX_ObjectAddHeader (m_handle->get(), get, OBEX_HDR_TYPE, header, m_contentType.size()+1, 0);
+
+        //send the request
+        m_obexReady = false;
+        if (OBEX_Request (m_handle->get(), get) < 0) {
+            SE_THROW_EXCEPTION (TransportException, "ObexTransport: get failed");
+        }
+
+        while (!m_obexReady) {
+            g_main_context_iteration (NULL, FALSE);
+            if (m_status == FAILED) {
+                SE_THROW_EXCEPTION (TransportException, 
+                        "ObexTransprotAgent: Underlying transport error");
+            }
+        }
+    }
+
+    if(m_status != CLOSED) {
+        m_sock = sockObj;
+        m_channel = channel;
+    } 
+    return m_status;
+}
+
+/**
+ * read the response from the buffer
+ */
+void ObexTransportAgent::getReply(const char *&data, size_t &len, std::string &contentType){
+   cxxptr<Socket> sockObj = m_sock;
+   cxxptr<Channel> channel = m_channel;
+   if (m_status != GOT_REPLY || !m_buffer || !m_bufferSize) {
+       SE_THROW_EXCEPTION (TransportException, "");
+   }
+   data = m_buffer;
+   len = m_bufferSize;
+   // There is no content type sent back from the peer according to the spec 
+   contentType = "";
+   m_sock = sockObj;
+   m_channel = channel;
+}
+
+gboolean ObexTransportAgent::sdp_source_cb (GIOChannel *io, GIOCondition cond, void *udata)
+{
+    return static_cast <ObexTransportAgent*> (udata) -> sdp_source_cb_impl(io, cond);
+}
+
+gboolean ObexTransportAgent::obex_fd_source_cb (GIOChannel *io, GIOCondition cond, void *udata)
+{
+    return static_cast <ObexTransportAgent*> (udata) -> obex_fd_source_cb_impl(io, cond);
+}
+
+void ObexTransportAgent::sdp_callback (uint8_t type, uint16_t status, uint8_t *rsp, size_t size, void *udata) 
+{
+    return static_cast <ObexTransportAgent *> (udata) -> sdp_callback_impl(type, status, rsp, size);
+}
+
+void ObexTransportAgent::obex_event (obex_t *handle, obex_object_t *object, int mode, int event, int obex_cmd, int obex_rsp){
+    (static_cast<ObexTransportAgent *> (OBEX_GetUserData (handle)))
+        ->obex_callback(object, mode, event, obex_cmd, obex_rsp);
+}
+
+gboolean ObexTransportAgent::sdp_source_cb_impl (GIOChannel *io, GIOCondition cond)
+{
+    try {
+        if(cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)){
+            SE_THROW_EXCEPTION (TransportException, "SDP connection end unexpectedly");
+        } else if ((cond &G_IO_OUT) && m_connectStatus == SDP_START) {
+            m_connectStatus = SDP_REQ;
+            sdp_set_notify (m_sdp, sdp_callback, static_cast <void *> (this));
+            const unsigned char syncml_client_uuid[] = {
+                0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x00,
+                0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x02};
+            uint32_t range = 0x0000ffff;
+            uuid_t uuid;
+            sdp_list_t *services, *attrs;
+            sdp_uuid128_create(&uuid, syncml_client_uuid);
+            services = sdp_list_append(NULL, &uuid);
+            attrs = sdp_list_append(NULL, &range);
+            if (sdp_service_search_attr_async(m_sdp, services, SDP_ATTR_REQ_RANGE, attrs) < 0) {
+                sdp_list_free (attrs, NULL);
+                sdp_list_free (services, NULL);
+                SE_THROW_EXCEPTION(TransportException, "ObexTransport: Bluetooth sdp service search failed");
+            }
+            sdp_list_free(attrs, NULL);
+            sdp_list_free(services, NULL);
+            return TRUE;
+        } else if ((cond &G_IO_IN) && m_connectStatus == SDP_REQ) {
+            sdp_process (m_sdp);
+            sdp_close (m_sdp);
+            return FALSE;
+        } else {
+            return TRUE;
+        }
+    } catch (const TransportException &te) {
+        SE_LOG_ERROR (NULL, NULL, "ObexTransport: Transport Exception in sdp_source_cb");
+        m_status = FAILED;
+        sdp_close (m_sdp);
+        return FALSE;
+    } catch (...) {
+        SE_LOG_ERROR (NULL, NULL, "ObexTransport: Exception in sdp_source_cb");
+        m_status = FAILED;
+        sdp_close (m_sdp);
+        return FALSE;
+    }
+}
+
+void ObexTransportAgent::sdp_callback_impl (uint8_t type, uint16_t status, uint8_t *rsp, size_t size)
+{
+       size_t scanned;
+    int bufSize = size;
+       int channel = -1;
+
+    try {
+        m_connectStatus = SDP_DONE;
+        if (status || type != SDP_SVC_SEARCH_ATTR_RSP) {
+            SE_THROW_EXCEPTION (TransportException, "ObexTransportAgent: Bluetooth service search failed");
+        }
+
+           int seqSize = 0;
+        uint8_t dtdp;
+        scanned = sdp_extract_seqtype(rsp, bufSize, &dtdp, &seqSize);
+        if (!scanned || !seqSize) {
+            SE_THROW_EXCEPTION (TransportException, "ObexTransportAgent: Bluetooth service search failed");
+        }
+
+        rsp += scanned;
+        bufSize -= scanned;
+        do {
+            sdp_record_t *rec;
+            sdp_list_t *protos;
+            int recSize;
+
+            recSize = 0;
+            rec = sdp_extract_pdu(rsp, bufSize, &recSize);
+            if (!rec) {
+                SE_THROW_EXCEPTION (TransportException, "ObexTransportAgent: sdp_extract_pdu failed");
+            }
+            if (!recSize) {
+                sdp_record_free(rec);
+                SE_THROW_EXCEPTION (TransportException, "ObexTransportAgent: sdp_extract_pdu failed");
+            }
+            if (!sdp_get_access_protos(rec, &protos)) {
+                channel = sdp_get_proto_port(protos, RFCOMM_UUID);
+                sdp_list_foreach(protos,
+                        (sdp_list_func_t) sdp_list_free, NULL);
+                sdp_list_free(protos, NULL);
+            }
+            sdp_record_free(rec);
+            if (channel > 0) {
+                break;
+            }
+            scanned += recSize;
+            rsp += recSize;
+            bufSize -= recSize;
+        } while (scanned < size && bufSize > 0);
+
+        if (channel <= 0) {
+            SE_THROW_EXCEPTION (TransportException, "ObexTransportAgent: Bluetooth service search failed");
+        }
+
+        m_port = channel;
+        m_connectStatus = ADDR_READY;
+        connectInit();
+    } catch (const TransportException &ex) {
+        SE_LOG_ERROR (NULL, NULL, "ObexTransport: Transport Exception in sdp_callback_impl");
+        SE_LOG_ERROR (NULL, NULL, "%s", ex.what());
+        m_status = FAILED;
+    } catch (...) {
+        m_status = FAILED;
+        SE_LOG_ERROR (NULL, NULL, "ObexTransport: exception thrown in sdp_callback");
+    }
+
+}
+
+/* obex event source callbackg*/
+gboolean ObexTransportAgent::obex_fd_source_cb_impl (GIOChannel *io, GIOCondition cond)
+{
+    cxxptr<Socket> sockObj = m_sock;
+    cxxptr<Channel> channel = m_channel;
+
+    if (m_status == CLOSED) {
+        return TRUE;
+    }
+
+    try {
+        if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
+            SE_LOG_ERROR (NULL, NULL, "obex_fd_source_cb_impl: got event %s%s%s", 
+                    (cond & G_IO_HUP) ?"HUP":"",
+                    (cond & G_IO_ERR) ?"ERR":"",
+                    (cond & G_IO_NVAL) ?"NVAL":"");
+            m_status = FAILED;
+            return FALSE;
+        }
+
+        if (m_connectStatus == INIT0 && (cond & G_IO_OUT)) {
+            int status = -1;
+            socklen_t optLen = sizeof (int);
+            if (!getsockopt (sockObj->get(), SOL_SOCKET, SO_ERROR, &status, &optLen) && status == 0) {
+                m_connectStatus = INIT1;
+                m_sock = sockObj;
+                m_channel = channel;
+                connectReq();
+                return TRUE;
+            } else {
+                SE_THROW_EXCEPTION (TransportException, "OBEXTransport: socket connect failed");
+            }
+        }
+
+        SuspendFlags s_flags = SyncContext::getSuspendFlags();
+        //abort transfer, only process the abort one time.
+        if (s_flags.state == SuspendFlags::CLIENT_ABORT /*&& !m_disconnectingi*/){
+            //first check abort flag
+            cancel();
+            m_sock = sockObj;
+            m_channel = channel;
+            return TRUE;
+        }
+
+        time_t now = time(NULL);
+        if (m_cb && (m_requestStart != 0) 
+                && (now - m_requestStart > m_cbInterval)) {
+            if (m_cb (m_cbData)){
+                //timeout
+                m_status = TIME_OUT;
+                //currently we will not support transport resend for 
+                //OBEX transport ??
+                cancel();
+            } else {
+                //abort
+                cancel();
+            }
+            m_sock = sockObj;
+            m_channel = channel;
+            return TRUE;
+        }
+
+        if (OBEX_HandleInput (m_handle->get(), OBEX_POLL_INTERVAL) <0) {
+            //transport error
+            //no way to recovery, simply abort
+            //disconnect without sending disconnect request
+            m_disconnecting = true;
+            cancel();
+        }
+        m_sock = sockObj;
+        m_channel = channel;
+        return TRUE;
+    } catch (const TransportException &ex) {
+        SE_LOG_ERROR (NULL, NULL, "ObexTransport: Transport Exception in obex_fd_source_cb_impl");
+        SE_LOG_ERROR (NULL, NULL, "%s", ex.what());
+        m_status = FAILED;
+    } catch (...){
+        SE_LOG_ERROR (NULL, NULL, "ObexTransport: Transport Exception in obex_fd_source_cb_impl");
+        m_status = FAILED;
+    }
+    return FALSE;
+}
+
+
+/**
+ * Obex Event Callback
+ */
+void ObexTransportAgent::obex_callback (obex_object_t *object, int mode, int event, int obex_cmd, int obex_rsp) {
+    try {
+        switch (event) {
+            case OBEX_EV_PROGRESS:
+                SE_LOG_DEV (NULL, NULL, "OBEX progress");
+                break;
+            case OBEX_EV_REQDONE:
+                m_obexReady = true;
+                m_requestStart = 0;
+                if (obex_rsp != OBEX_RSP_SUCCESS) {
+                    SE_LOG_ERROR (NULL, NULL, "OBEX Request %d got a failed response %s",
+                            obex_cmd,OBEX_ResponseToString(obex_rsp));
+                    m_status = FAILED;
+                    return;
+                } else {
+                    switch (obex_cmd) {
+                        case OBEX_CMD_CONNECT:
+                            {
+                                uint8_t headertype = 0;
+                                obex_headerdata_t header;
+                                uint32_t len;
+
+                                while (OBEX_ObjectGetNextHeader (m_handle->get(), object, &headertype, &header, &len)) {
+                                    if (headertype == OBEX_HDR_CONNECTION) {
+                                        m_connectId = header.bq4;
+                                    } else if (headertype == OBEX_HDR_WHO) { 
+                                        SE_LOG_DEV (NULL, NULL, 
+                                                "OBEX Transport: get header who from connect response with value %s", header.bs);
+                                    } else {
+                                        SE_LOG_WARNING (NULL, NULL, 
+                                                "OBEX Transport: Unknow header from connect response");
+                                    }
+                                }
+                                if (m_connectId == 0) {
+                                    m_status = FAILED;
+                                    SE_LOG_ERROR(NULL, NULL, 
+                                            "No connection id received from connect response");
+                                }
+                                m_connectStatus = CONNECTED;
+
+                                break;
+                            }
+                        case OBEX_CMD_DISCONNECT:
+                            {
+                                if (m_connectStatus == CONNECTED) {
+                                    m_connectStatus = END;
+                                    OBEX_TransportDisconnect (m_handle->get());
+                                    m_status = CLOSED;
+                                }
+                                break;
+                            }
+                        case OBEX_CMD_GET:
+                            {
+                                int length = 0;
+                                uint8_t headertype = 0;
+                                obex_headerdata_t header;
+                                uint32_t len;
+                                while (OBEX_ObjectGetNextHeader (m_handle->get(), object, &headertype, &header, &len)) {
+                                    if (headertype == OBEX_HDR_LENGTH) {
+                                        length = header.bq4;
+                                    } else if (headertype == OBEX_HDR_BODY) {
+                                        if (length ==0) {
+                                            length = len;
+                                            SE_LOG_DEV (NULL, NULL, 
+                                                    "No length header for get response is recevied, using body size %d", len);
+                                        }
+                                        if (length ==0) {
+                                            m_status = FAILED;
+                                            SE_LOG_ERROR (NULL, NULL, 
+                                                    "ObexTransport: Get zero sized response body for Get");
+                                        }
+                                        if(!m_buffer) {
+                                            free (m_buffer);
+                                            m_buffer = NULL;
+                                        }
+                                        m_buffer = new char[length];
+                                        m_bufferSize = length;
+                                        if(m_buffer) {
+                                            memcpy (m_buffer, header.bs, length);
+                                        } else {
+                                            m_status = FAILED;
+                                            SE_LOG_ERROR (NULL, NULL, "Allocating buffer failed");
+                                            return;
+                                        }
+                                    } else {
+                                        SE_LOG_WARNING (NULL, NULL, "Unknow header received for Get cmd");
+                                    }
+                                }
+                                if( !length || !m_buffer) {
+                                    m_status = FAILED;
+                                    SE_LOG_ERROR (NULL, NULL, "Get Cmd response have no body");
+                                }
+                                m_status = GOT_REPLY;
+                                break;
+                            }
+                    }
+                }//else
+                break;
+            case OBEX_EV_LINKERR:
+                {
+                    if (obex_rsp == 0 && m_disconnecting) {
+                        //disconnct event
+                        m_connectStatus = END;
+                        OBEX_TransportDisconnect (m_handle->get());
+                        m_status = CLOSED;
+                    } else if (obex_rsp !=0) {
+                        SE_LOG_ERROR (NULL, NULL, "ObexTransport Error %d", obex_rsp);
+                        m_status = FAILED;
+                        return;
+                    }
+                    break;
+                }
+            case OBEX_EV_STREAMEMPTY:
+            case OBEX_EV_STREAMAVAIL:
+                break;
+        }
+    } catch (...) {
+        m_status = FAILED;
+        SE_LOG_ERROR (NULL, NULL, "ObexTransport: exception thrown in obex_callback");
+    }
+
+}
+
+obex_object_t* ObexTransportAgent::newCmd(uint8_t cmd) {
+    obex_object_t *cmdObject = OBEX_ObjectNew (m_handle->get(), cmd);
+    if(!cmdObject) {
+        m_status = FAILED;
+        SE_LOG_ERROR (NULL, NULL, "ObexTransport: OBEX Object New failed");
+        return NULL;
+    } else {
+        return cmdObject;
+    }
+}
+
+#endif //ENABLE_OBEX
+SE_END_CXX
diff --git a/src/syncevo/ObexTransportAgent.h b/src/syncevo/ObexTransportAgent.h
new file mode 100644 (file)
index 0000000..fb7afab
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2009 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) version 3.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301  USA
+ */
+
+#ifndef INCL_OBEXTRANSPORTAGENT
+#define INCL_OBEXTRANSPORTAGENT
+
+#include <config.h>
+
+#ifdef ENABLE_OBEX
+
+#include <syncevo/TransportAgent.h>
+#include <syncevo/Logging.h>
+#include <syncevo/declarations.h>
+#include <syncevo/SmartPtr.h>
+
+#ifdef  ENABLE_BLUETOOTH
+#include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>
+#endif
+#include <openobex/obex.h>
+
+SE_BEGIN_CXX
+
+class Socket {
+    int socketfd;
+ public:
+     Socket() {socketfd = -1;}
+     Socket(int fd) {socketfd = fd;}
+     ~Socket() { if (socketfd !=-1) {::close (socketfd);} }
+     int get() {return socketfd;}
+}; 
+
+class Channel {
+    GIOChannel *channel;
+ public:
+     Channel() {channel = NULL;}
+     Channel(GIOChannel *c) {channel = c;}
+     ~Channel() { if (!channel) {g_io_channel_unref (channel);}}
+     GIOChannel* get() {return channel;}
+};
+
+class ObexEvent {
+    guint event;
+public:
+    ObexEvent() {event = 0;}
+    ObexEvent (guint e) {event = e; SE_LOG_DEBUG (NULL, NULL, "ObexTransportAgent: creating obex event %d", e);}
+    ~ObexEvent () {if (event) {g_source_remove (event);} 
+                   SE_LOG_DEBUG (NULL, NULL, "ObexTransportAgent: removing obex event %d", event);}
+    guint get() {return event;}
+};
+
+class ObexHandle {
+    obex_t *handle;
+public:
+    ObexHandle() {handle = NULL;}
+    ObexHandle(obex_t *h) {handle = h;}
+    ~ObexHandle() {if (!handle) {OBEX_Cleanup (handle);}}
+    obex_t* get() {return handle;}
+};
+
+/**
+ * message send/receive with libopenobex
+ * should work with a transport binding (Bluetooth, USB, etc.)
+ */
+class ObexTransportAgent : public TransportAgent 
+{
+    public:
+        enum OBEX_TRANS_TYPE{
+            OBEX_BLUETOOTH,
+            OBEX_USB,
+            INVALID
+        };
+
+        ObexTransportAgent(OBEX_TRANS_TYPE type);
+        ~ObexTransportAgent();
+
+        virtual void setURL (const std::string &url);
+        virtual void setContentType(const std::string &type);
+        virtual void shutdown();
+        virtual void send(const char *data, size_t len);
+        virtual void cancel();
+        virtual Status wait(bool noReply);
+        virtual void getReply(const char *&data, size_t &len, std::string &contentType);
+        virtual void setCallback (TransportCallback cb, void *udata, int interval);
+        /* Obex specific api: connecting the underlying transport */
+        void connect();
+
+    private:
+        /*call back used by libopenobex, will route to member function obex_callback*/
+        static void obex_event (obex_t *handle, obex_object_t *object, int mode, int event, int obex_cmd, int obex_rsp);
+        /* callback used by obex fd poll, will route to member function
+         * obex_fd_source_cb_impl */
+        static gboolean obex_fd_source_cb (GIOChannel *io, GIOCondition cond, void *udata);
+        /* callback used by Bluetooth sdp poll, will route to member function
+         * sdp_source_cb_impl */
+        static gboolean sdp_source_cb (GIOChannel *io, GIOCondition cond, void *udata);
+        /* callback called when a sdp async transaction is finished, route to
+         * member function sdp_callback_impl*/
+        static void sdp_callback (uint8_t type, uint16_t status, uint8_t *rsp, size_t size, void *user_data);
+
+        void obex_callback (obex_object_t *object, int mode, int event, int obex_cmd, int obex_rsp);
+        gboolean obex_fd_source_cb_impl (GIOChannel *io, GIOCondition cond);
+        gboolean sdp_source_cb_impl (GIOChannel *io, GIOCondition cond);
+        void sdp_callback_impl (uint8_t type, uint16_t status, uint8_t *rsp, size_t size);
+
+        /* First phase of OBEX connect: connect to remote peer */
+        void connectInit ();
+        /* Second phase of OBEX connect: send connect cmd to initalize */
+        void connectReq ();
+
+        /* wrapper of OBEX_ObjectNew*/
+        obex_object_t * newCmd (uint8_t cmd);
+
+        static const int DEFAULT_RX_MTU=32767;
+        static const int DEFAULT_TX_MTU=32767;
+
+        /*Indicates when the OBEX transport has finished it's part of working,
+         * it's the application to turn to do something */
+        bool m_obexReady;
+        Status m_status;
+
+        /*
+         * The underlying transport type: Bluetooth, USB.
+         */
+        OBEX_TRANS_TYPE m_transType;
+
+        /* The address of the remote device  
+         * macadd for Bluetooth; device name for usb; host name for
+         * tcp/ip
+         */
+        std::string m_address;
+        /*
+         * Service port for the remote device 
+         * channel for Bluetooth, port for tcp/ip
+         */
+        int m_port;
+
+        /*The underlying socket fd*/
+        cxxptr<Socket> m_sock;
+        cxxptr<ObexEvent> m_obexEvent;
+        cxxptr<Channel> m_channel;
+
+        std::string m_contentType;
+        char *m_buffer;
+        int m_bufferSize;
+
+        sdp_session_t *m_sdp;
+
+        /* callback supplied by the user of the transport */
+        TransportCallback m_cb;
+        void *m_cbData;
+        time_t m_cbInterval;
+        time_t m_requestStart;
+        /** OBEX poll interval */
+        static const int OBEX_POLL_INTERVAL = 1;
+
+        uint32_t m_connectId;
+        //already fired disconnect
+        bool m_disconnecting;
+
+        cxxptr<ObexHandle> m_handle;
+        enum CONNECT_STATUS {
+            START, 
+            SDP_START, //sdp transaction start
+            SDP_REQ, //sdp request has been sent
+            SDP_DONE, //sdp transaction finished
+            ADDR_READY, //address is prepared
+            INIT0,  //connect is called but not finished
+            INIT1,  //connect is finished. 
+            INIT2,  //connect cmd is sent, but not finished.
+            CONNECTED, //connection sucessfully setup
+            ERROR,  //connection in error state
+            END
+        };
+        CONNECT_STATUS m_connectStatus;
+};
+
+SE_END_CXX
+#endif //ENABLE_OBEX
+#endif
index f5374d8..bab5b52 100644 (file)
@@ -57,9 +57,9 @@ void PrefixConfigNode::setProperty(const string &property,
                         defValue);
 }
 
-void PrefixConfigNode::readProperties(map<string, string> &props) const
+void PrefixConfigNode::readProperties(ConfigProps &props) const
 {
-    map<string, string> original;
+    ConfigProps original;
     m_readOnlyNode->readProperties(original);
 
     BOOST_FOREACH(const StringPair &prop, original) {
index 0a3e31a..b0125aa 100644 (file)
@@ -60,9 +60,10 @@ class PrefixConfigNode : public ConfigNode {
                              const string &value,
                              const string &comment = "",
                              const string *defValue = NULL);
-    virtual void readProperties(map<string, string> &props) const;
+    virtual void readProperties(ConfigProps &props) const;
     virtual void removeProperty(const string &property);
     virtual bool exists() const { return m_readOnlyNode->exists(); }
+    virtual void clear() { m_node->clear(); }
 
  private:
     string m_prefix;
index 2a0a280..dc92254 100644 (file)
@@ -54,9 +54,9 @@ void SafeConfigNode::setProperty(const string &property,
                         defValue);
 }
 
-void SafeConfigNode::readProperties(map<string, string> &props) const
+void SafeConfigNode::readProperties(ConfigProps &props) const
 {
-    map<string, string> original;
+    ConfigProps original;
     m_readOnlyNode->readProperties(original);
 
     BOOST_FOREACH(const StringPair &prop, original) {
@@ -80,7 +80,7 @@ void SafeConfigNode::flush()
     m_node->flush();
 }
 
-string SafeConfigNode::escape(const string &str) const
+string SafeConfigNode::escape(const string &str, bool allSpaces, bool strictMode)
 {
     string res;
     char buffer[4];
@@ -88,12 +88,14 @@ string SafeConfigNode::escape(const string &str) const
     res.reserve(str.size() * 3);
 
     BOOST_FOREACH(char c, str) {
-        if(m_strictMode ?
+        if(strictMode ?
            (isalnum(c) ||
             c == '-' ||
             c == '_') :
-           !((isLeadingSpace && isspace(c)) ||
+           !(((isLeadingSpace || allSpaces) && isspace(c)) ||
              c == '=' ||
+             c == '!' ||
+             c == '\r' ||
              c == '\n')) {
             res += c;
             if (!isspace(c)) {
@@ -107,7 +109,7 @@ string SafeConfigNode::escape(const string &str) const
     }
 
     // also encode trailing space?
-    if (!m_strictMode) {
+    if (!strictMode || allSpaces) {
         size_t numspaces = 0;
         ssize_t off = res.size() - 1;
         while (off >= 0 && isspace(res[off])) {
@@ -125,7 +127,7 @@ string SafeConfigNode::escape(const string &str) const
     return res;
 }
 
-string SafeConfigNode::unescape(const string &str) const
+string SafeConfigNode::unescape(const string &str)
 {
     string res;
     size_t curr;
index ffaa797..8f32e87 100644 (file)
@@ -62,6 +62,18 @@ class SafeConfigNode : public ConfigNode {
     /* keep underlying methods visible; our own setProperty() would hide them */
     using ConfigNode::setProperty;
 
+    /**
+     * turn str into something which can be used as key or value in ConfigNode
+     * @param allSpaces     escape all spaces, not just those at the start and end
+     * @paramm strictMode   same as in setMode()
+     */
+    static string escape(const string &str, bool allSpaces, bool strictMode);
+    string escape(const string &str) const { return escape(str, false, m_strictMode); }
+
+    /** inverse operation for escape() */
+    static string unescape(const string &str);
+
+
     /* ConfigNode API */
     virtual void flush();
     virtual string readProperty(const string &property) const;
@@ -69,22 +81,15 @@ class SafeConfigNode : public ConfigNode {
                              const string &value,
                              const string &comment = "",
                              const string *defValue = NULL);
-    virtual void readProperties(map<string, string> &props) const;
+    virtual void readProperties(ConfigProps &props) const;
     virtual void removeProperty(const string &property);
     virtual bool exists() const { return m_readOnlyNode->exists(); }
+    virtual void clear() { m_node->clear(); }
 
  private:
     boost::shared_ptr<ConfigNode> m_node;
     boost::shared_ptr<const ConfigNode> m_readOnlyNode;
     bool m_strictMode;
-
-    /**
-     * turn str into something which can be used as key or value in ConfigNode
-     */
-    string escape(const string &str) const;
-
-    /** inverse operation for escape() */
-    string unescape(const string &str) const;
 };
 
 
index 01c8b5d..dc551d2 100644 (file)
@@ -158,7 +158,7 @@ void SoupTransportAgent::cancel()
       g_main_loop_quit(m_loop.get());
 }
 
-TransportAgent::Status SoupTransportAgent::wait()
+TransportAgent::Status SoupTransportAgent::wait(bool noReply)
 {
     if (!m_failure.empty()) {
         std::string failure;
@@ -167,6 +167,9 @@ TransportAgent::Status SoupTransportAgent::wait()
     }
 
     switch (m_status) {
+    case CLOSED:
+        return CLOSED;
+        break;
     case ACTIVE:
         // block in main loop until our HandleSessionCallback() stops the loop
         g_main_loop_run(m_loop.get());
@@ -250,7 +253,7 @@ void SoupTransportAgent::HandleSessionCallback(SoupSession *session,
 
 gboolean SoupTransportAgent::AbortCallback(gpointer transport)
 {
-    SuspendFlags& s_flags = SyncContext::getSuspendFlags();
+    const SuspendFlags &s_flags = SyncContext::getSuspendFlags();
 
     if (s_flags.state == SuspendFlags::CLIENT_ABORT)
     {
index ba77351..6bc1a8c 100644 (file)
@@ -47,7 +47,7 @@ class GLibUnref {
  * An asynchronous soup session is used and the main loop
  * is invoked in the wait() method to make progress.
  */
-class SoupTransportAgent : public TransportAgent
+class SoupTransportAgent : public HTTPTransportAgent
 {
  public:
     /**
@@ -66,9 +66,10 @@ class SoupTransportAgent : public TransportAgent
                         bool verifyHost);
     virtual void setContentType(const std::string &type);
     virtual void setUserAgent(const std::string &agent);
+    virtual void shutdown() { m_status = CLOSED; }
     virtual void send(const char *data, size_t len);
     virtual void cancel();
-    virtual Status wait();
+    virtual Status wait(bool noReply = false);
     virtual void getReply(const char *&data, size_t &len, std::string &contentType);
     virtual void setCallback (TransportCallback cb, void *udata, int interval);
     gboolean processCallback();
index f4e0ada..b9262e0 100644 (file)
@@ -26,6 +26,8 @@
 #include <syncevo/FileConfigTree.h>
 #include <syncevo/VolatileConfigTree.h>
 #include <syncevo/VolatileConfigNode.h>
+#include <syncevo/DevNullConfigNode.h>
+#include <syncevo/MultiplexConfigNode.h>
 #include <synthesis/timeutil.h>
 
 #include <boost/foreach.hpp>
 #include <syncevo/declarations.h>
 SE_BEGIN_CXX
 
+const char *const SourceAdminDataName = "adminData";
+
 static bool SourcePropSourceTypeIsSet(boost::shared_ptr<SyncSourceConfig> source);
 static bool SourcePropURIIsSet(boost::shared_ptr<SyncSourceConfig> source);
+static bool SourcePropSyncIsSet(boost::shared_ptr<SyncSourceConfig> source);
 
 void ConfigProperty::splitComment(const string &comment, list<string> &commentLines)
 {
@@ -63,43 +68,239 @@ void ConfigProperty::throwValueError(const ConfigNode &node, const string &name,
     SyncContext::throwError(node.getName() + ": " + name + " = " + value + ": " + error);
 }
 
+string SyncConfig::normalizeConfigString(const string &config)
+{
+    string normal, context;
+    normalizeConfigString(config, normal, context);
+    return normal;
+}
+
+void SyncConfig::normalizeConfigString(const string &config, string &normal, string &context)
+{
+    context = "";
+    normal = config;
+    boost::to_lower(normal);
+    if (boost::ends_with(normal, "@default")) {
+        context = "default";
+        normal.resize(normal.size() - strlen("@default"));
+    } else if (boost::ends_with(normal, "@")) {
+        normal.resize(normal.size() - 1);
+    } else {
+        // context specified?
+        size_t at = normal.rfind('@');
+        if (at != normal.npos) {
+            context = normal.substr(at + 1);
+        }
+    }
+    if (normal.empty()) {
+        // leave context empty, it wasn't set explicitly
+        normal = "@default";
+    }
+}
+
+void SyncConfig::splitConfigString(const string &config, string &peer, string &context)
+{
+    string::size_type at = config.rfind('@');
+    if (at != config.npos) {
+        peer = config.substr(0, at);
+        context = config.substr(at + 1);
+    } else {
+        peer = config;
+        context = "default";
+    }    
+}
+
 SyncConfig::SyncConfig() :
-    m_oldLayout(false)
+    m_layout(HTTP_SERVER_LAYOUT) // use more compact layout with shorter paths and less source nodes
+{
+    // initialize properties
+    SyncConfig::getRegistry();
+    SyncSourceConfig::getRegistry();
+
+    m_peerPath =
+        m_contextPath = "volatile";
+    makeVolatile();
+}
+
+void SyncConfig::makeVolatile()
 {
     m_tree.reset(new VolatileConfigTree());
-    m_configNode.reset(new VolatileConfigNode());
-    m_hiddenNode = m_configNode;
+    m_peerNode.reset(new VolatileConfigNode());
+    m_hiddenPeerNode = m_peerNode;
+    m_globalNode = m_peerNode;
+    m_contextNode = m_peerNode;
+    m_contextHiddenNode = m_peerNode;
+    m_props[false] = m_peerNode;
+    m_props[true] = m_peerNode;
 }
 
-SyncConfig::SyncConfig(const string &server,
-                                         boost::shared_ptr<ConfigTree> tree) :
-    m_server(server),
-    m_oldLayout(false)
+SyncConfig::SyncConfig(const string &peer,
+                       boost::shared_ptr<ConfigTree> tree) :
+    m_layout(SHARED_LAYOUT)
 {
+    // initialize properties
+    SyncConfig::getRegistry();
+    SyncSourceConfig::getRegistry();
+
     string root;
 
+    string context;
+    normalizeConfigString(peer, m_peer, context);
+    if (context.empty()) {
+        // No explicit context. Pick the first server which matches
+        // 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()) {
+            string entry_peer, entry_context;
+            splitConfigString(entry.first, entry_peer, entry_context);
+            if (m_peer == entry_peer) {
+                // found a matching, existing config, use it
+                m_peer = entry.first;
+                break;
+            }
+        }
+    }
+
+    // except for SHARED_LAYOUT (set below),
+    // everything is below the directory called like
+    // the peer
+    m_peerPath =
+        m_contextPath = 
+        m_peer;
+
     if (tree.get() != NULL) {
+        // existing tree points into simple configuration
         m_tree = tree;
+        m_layout = HTTP_SERVER_LAYOUT;
+        m_peerPath =
+            m_contextPath = "";
     } else {
         // search for configuration in various places...
-        string lower = server;
-        boost::to_lower(lower);
-        string confname;
-        root = getOldRoot() + "/" + lower;
-        confname = root + "/spds/syncml/config.txt";
-        if (!access(confname.c_str(), F_OK)) {
-            m_oldLayout = true;
+        root = getOldRoot();
+        string path = root + "/" + m_peerPath;
+        if (!access((path + "/spds/syncml/config.txt").c_str(), F_OK)) {
+            m_layout = SYNC4J_LAYOUT;
         } else {
-            root = getNewRoot() + "/" + lower;
+            root = getNewRoot();
+            path = root + "/" + m_peerPath;
+            if (!access((path + "/config.ini").c_str(), F_OK) &&
+                !access((path + "/sources").c_str(), F_OK)) {
+                m_layout = HTTP_SERVER_LAYOUT;
+            } else {
+                // check whether config name specifies a context,
+                // otherwise use "default"
+                splitConfigString(m_peer, m_peerPath, m_contextPath);
+                if (!m_peerPath.empty()) {
+                    m_peerPath = m_contextPath + "/peers/" + m_peerPath;
+                }
+            }
         }
-        m_tree.reset(new FileConfigTree(root, m_oldLayout));
+        m_tree.reset(new FileConfigTree(root, m_peerPath,
+                                        m_layout == SYNC4J_LAYOUT));
     }
 
-    string path(m_oldLayout ? "spds/syncml" : "");
+    string path;
     boost::shared_ptr<ConfigNode> node;
-    node = m_tree->open(path, ConfigTree::visible);
-    m_configNode.reset(new FilterConfigNode(node));
-    m_hiddenNode = m_tree->open(path, ConfigTree::hidden);
+    switch (m_layout) {
+    case SYNC4J_LAYOUT:
+        // all properties reside in the same node
+        path = m_peerPath + "/spds/syncml";
+        node = m_tree->open(path, ConfigTree::visible);
+        m_peerNode.reset(new FilterConfigNode(node));
+        m_globalNode =
+            m_contextNode = m_peerNode;
+        m_hiddenPeerNode =
+            m_contextHiddenNode =
+            node;
+        m_props[false] = m_peerNode;
+        m_props[true].reset(new FilterConfigNode(m_hiddenPeerNode));
+        break;
+    case HTTP_SERVER_LAYOUT: {
+        // properties which are normally considered shared are
+        // stored in the same nodes as the per-peer properties,
+        // except for global ones
+        path = "";
+        node = m_tree->open(path, ConfigTree::visible);
+        m_globalNode.reset(new FilterConfigNode(node));
+        path = m_peerPath;      
+        node = m_tree->open(path, ConfigTree::visible);
+        m_peerNode.reset(new FilterConfigNode(node));
+        m_contextNode = m_peerNode;
+        m_hiddenPeerNode =
+            m_contextHiddenNode =
+            m_tree->open(path, ConfigTree::hidden);
+
+        // similar multiplexing as for SHARED_LAYOUT,
+        // with two nodes underneath
+        boost::shared_ptr<MultiplexConfigNode> mnode;
+        mnode.reset(new MultiplexConfigNode(m_peerNode->getName(),
+                                            getRegistry(),
+                                            false));
+        m_props[false] = mnode;
+        mnode->setNode(false, ConfigProperty::GLOBAL_SHARING,
+                       m_globalNode);
+        mnode->setNode(false, ConfigProperty::SOURCE_SET_SHARING,
+                       m_peerNode);
+        mnode->setNode(false, ConfigProperty::NO_SHARING,
+                       m_peerNode);
+
+        // no multiplexing necessary for hidden nodes
+        m_props[true].reset(new FilterConfigNode(m_hiddenPeerNode));
+        break;
+    }
+    case SHARED_LAYOUT:
+        // really use different nodes for everything
+        path = "";
+        node = m_tree->open(path, ConfigTree::visible);
+        m_globalNode.reset(new FilterConfigNode(node));
+
+        path = m_peerPath;
+        if (path.empty()) {
+            node.reset(new DevNullConfigNode(m_contextPath + " without peer config"));
+        } else {
+            node = m_tree->open(path, ConfigTree::visible);
+        }
+        m_peerNode.reset(new FilterConfigNode(node));
+        if (path.empty()) {
+            m_hiddenPeerNode = m_peerNode;
+        } else {
+            m_hiddenPeerNode = m_tree->open(path, ConfigTree::hidden);
+        }
+
+        path = m_contextPath;
+        node = m_tree->open(path, ConfigTree::visible);
+        m_contextNode.reset(new FilterConfigNode(node));
+        m_contextHiddenNode = m_tree->open(path, ConfigTree::hidden);
+
+        // Instantiate multiplexer with the most specific node name in
+        // the set, the peer node's name. This is slightly inaccurate:
+        // error messages generated for this node in will reference
+        // the wrong config.ini file for shared properties. But
+        // there no shared properties which can trigger such an error
+        // at the moment, so this is good enough for now (MB#8037).
+        boost::shared_ptr<MultiplexConfigNode> mnode;
+        mnode.reset(new MultiplexConfigNode(m_peerNode->getName(),
+                                            getRegistry(),
+                                            false));
+        m_props[false] = mnode;
+        mnode->setNode(false, ConfigProperty::GLOBAL_SHARING,
+                       m_globalNode);
+        mnode->setNode(false, ConfigProperty::SOURCE_SET_SHARING,
+                       m_contextNode);
+        mnode->setNode(false, ConfigProperty::NO_SHARING,
+                       m_peerNode);
+
+        mnode.reset(new MultiplexConfigNode(m_hiddenPeerNode->getName(),
+                                            getRegistry(),
+                                            true));
+        m_props[true] = mnode;
+        mnode->setNode(true, ConfigProperty::SOURCE_SET_SHARING,
+                       m_contextHiddenNode);
+        mnode->setNode(true, ConfigProperty::NO_SHARING,
+                       m_hiddenPeerNode);
+        break;
+    }
 }
 
 string SyncConfig::getRootPath() const
@@ -107,14 +308,30 @@ string SyncConfig::getRootPath() const
     return m_tree->getRootPath();
 }
 
-static void addServers(const string &root, SyncConfig::ServerList &res) {
-    FileConfigTree tree(root, false);
+void SyncConfig::addPeers(const string &root,
+                          const std::string &configname,
+                          SyncConfig::ServerList &res) {
+    FileConfigTree tree(root, "", false);
     list<string> servers = tree.getChildren("");
     BOOST_FOREACH(const string &server, servers) {
         // sanity check: only list server directories which actually
-        // contain a configuration
-        SyncConfig config(server);
-        if (config.exists()) {
+        // contain a configuration. To distinguish between a context
+        // (~/.config/syncevolution/default) and an HTTP server config
+        // (~/.config/syncevolution/scheduleworld), we check for the
+        // "peer" subdirectory that is only in the former.
+        //
+        // Contexts which don't have a peer are therefore incorrectly
+        // listed as a peer. Short of adding a special hidden file
+        // this can't be fixed. This is probably overkill and thus not
+        // done yet.
+        string peerPath = server + "/peers";
+        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));
+            }
+        } else if (!access((root + "/" + server + "/" + configname).c_str(), F_OK)) {
             res.push_back(pair<string, string>(server, root + "/" + server));
         }
     }
@@ -124,8 +341,11 @@ SyncConfig::ServerList SyncConfig::getServers()
 {
     ServerList res;
 
-    addServers(getOldRoot(), res);
-    addServers(getNewRoot(), res);
+    addPeers(getOldRoot(), "config.txt", res);
+    addPeers(getNewRoot(), "config.ini", res);
+
+    // sort the list; better than returning it in random order
+    res.sort();
 
     return res;
 }
@@ -163,14 +383,12 @@ SyncConfig::ServerList SyncConfig::getServerTemplates()
 
     // builtin templates if not present
     result.addDefaultTemplate("Funambol", "http://my.funambol.com");
-    result.addDefaultTemplate("ScheduleWorld", "http://www.scheduleworld.com");
+    result.addDefaultTemplate("ScheduleWorld", "http://sync.scheduleworld.com");
     result.addDefaultTemplate("Synthesis", "http://www.synthesis.ch");
     result.addDefaultTemplate("Memotoo", "http://www.memotoo.com");
     result.addDefaultTemplate("Google", "http://m.google.com/sync");
     result.addDefaultTemplate("ZYB", "http://www.zyb.com");
     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.sort();
     return result;
@@ -178,8 +396,20 @@ SyncConfig::ServerList SyncConfig::getServerTemplates()
 
 boost::shared_ptr<SyncConfig> SyncConfig::createServerTemplate(const string &server)
 {
+    if (server.empty()) {
+        // Empty template name => no such template. This check is
+        // necessary because otherwise we end up with SyncConfig(""),
+        // which is a configuration where peer-specific properties
+        // cannot be set, triggering an errror in config->setDevID().
+        return boost::shared_ptr<SyncConfig>();
+    }
+
     // 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") ?
@@ -193,7 +423,7 @@ boost::shared_ptr<SyncConfig> SyncConfig::createServerTemplate(const string &ser
         // 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));
+    boost::shared_ptr<FileConfigTree> tree(new FileConfigTree(templateConfig, "", false));
     tree->setReadOnly(true);
     boost::shared_ptr<SyncConfig> config(new SyncConfig(server, tree));
     boost::shared_ptr<PersistentSyncSourceConfig> source;
@@ -218,6 +448,10 @@ boost::shared_ptr<SyncConfig> SyncConfig::createServerTemplate(const string &ser
     if (!SourcePropURIIsSet(source)) {
         source->setURI("card");
     }
+    if (!SourcePropSyncIsSet(source)) {
+        source->setSync("two-way");
+    }
+
     source = config->getSyncSourceConfig("calendar");
     if (!SourcePropSourceTypeIsSet(source)) {
         source->setSourceType("calendar");
@@ -225,6 +459,10 @@ boost::shared_ptr<SyncConfig> SyncConfig::createServerTemplate(const string &ser
     if (!SourcePropURIIsSet(source)) {
         source->setURI("event");
     }
+    if (!SourcePropSyncIsSet(source)) {
+        source->setSync("two-way");
+    }
+
     source = config->getSyncSourceConfig("todo");
     if (!SourcePropSourceTypeIsSet(source)) {
         source->setSourceType("todo");
@@ -232,6 +470,10 @@ boost::shared_ptr<SyncConfig> SyncConfig::createServerTemplate(const string &ser
     if (!SourcePropURIIsSet(source)) {
         source->setURI("task");
     }
+    if (!SourcePropSyncIsSet(source)) {
+        source->setSync("two-way");
+    }
+
     source = config->getSyncSourceConfig("memo");
     if (!SourcePropSourceTypeIsSet(source)) {
         source->setSourceType("memo");
@@ -239,6 +481,9 @@ boost::shared_ptr<SyncConfig> SyncConfig::createServerTemplate(const string &ser
     if (!SourcePropURIIsSet(source)) {
         source->setURI("note");
     }
+    if (!SourcePropSyncIsSet(source)) {
+        source->setSync("two-way");
+    }
 
     if (isDir(templateConfig)) {
         // directory exists, check for icon?
@@ -262,7 +507,7 @@ boost::shared_ptr<SyncConfig> SyncConfig::createServerTemplate(const string &ser
     if (boost::iequals(server, "scheduleworld") ||
         boost::iequals(server, "default")) {
         config->setSyncURL("http://sync.scheduleworld.com/funambol/ds");
-        config->setWebURL("http://www.scheduleworld.com");
+        config->setWebURL("http://sync.scheduleworld.com");
         config->setConsumerReady(true);
         source = config->getSyncSourceConfig("addressbook");
         source->setURI("card3");
@@ -362,28 +607,6 @@ boost::shared_ptr<SyncConfig> SyncConfig::createServerTemplate(const string &ser
         source->setURI("task");
         source = config->getSyncSourceConfig("memo");
         source->setURI("pnote");
-    } else if (boost::iequals(server, "oracle")) {
-        config->setSyncURL("https://your.company/mobilesync/server");
-        config->setWebURL("http://www.oracle.com/technology/products/beehive/");
-        source = config->getSyncSourceConfig("addressbook");
-        source->setURI("./contacts");
-        source = config->getSyncSourceConfig("calendar");
-        source->setURI("./calendar/events");
-        source = config->getSyncSourceConfig("todo");
-        source->setURI("./calendar/tasks");
-        source = config->getSyncSourceConfig("memo");
-        source->setURI("./notes");
-    } else if (boost::iequals(server, "goosync")) {
-        config->setSyncURL("http://sync2.goosync.com/");
-        config->setWebURL("http://www.goosync.com/");
-        source = config->getSyncSourceConfig("addressbook");
-        source->setURI("contacts");
-        source = config->getSyncSourceConfig("calendar");
-        source->setURI("calendar");
-        source = config->getSyncSourceConfig("todo");
-        source->setURI("tasks");
-        source = config->getSyncSourceConfig("memo");
-        source->setURI("");
     } else {
         config.reset();
     }
@@ -393,7 +616,9 @@ boost::shared_ptr<SyncConfig> SyncConfig::createServerTemplate(const string &ser
 
 bool SyncConfig::exists() const
 {
-    return m_configNode->exists();
+    return m_peerPath.empty() ?
+        m_contextNode->exists() :
+        m_peerNode->exists();
 }
 
 void SyncConfig::preFlush(ConfigUserInterface &ui)
@@ -404,7 +629,7 @@ void SyncConfig::preFlush(ConfigUserInterface &ui)
     /* save password in the global config node */
     ConfigPropertyRegistry& registry = getRegistry();
     BOOST_FOREACH(const ConfigProperty *prop, registry) {
-        prop->savePassword(ui, m_server, *m_configNode);
+        prop->savePassword(ui, m_peer, *getProperties());
     }
 
     /** grep each source and save their password */
@@ -415,7 +640,8 @@ void SyncConfig::preFlush(ConfigUserInterface &ui)
         SyncSourceNodes sourceNodes = getSyncSourceNodes(sourceName);
 
         BOOST_FOREACH(const ConfigProperty *prop, registry) {
-            prop->savePassword(ui, m_server,*m_configNode,sourceName,sourceNodes.m_configNode);
+            prop->savePassword(ui, m_peer, *getProperties(),
+                               sourceName, sourceNodes.getProperties());
         }
     }
 }
@@ -427,8 +653,14 @@ void SyncConfig::flush()
 
 void SyncConfig::remove()
 {
-    m_tree->remove();
-    m_tree.reset(new VolatileConfigTree());
+    boost::shared_ptr<ConfigTree> tree = m_tree;
+
+    // stop using the config nodes, they might get removed now
+    makeVolatile();
+
+    tree->remove(m_peerPath.empty() ?
+                 m_contextPath :
+                 m_peerPath);
 }
 
 boost::shared_ptr<PersistentSyncSourceConfig> SyncConfig::getSyncSourceConfig(const string &name)
@@ -439,44 +671,136 @@ boost::shared_ptr<PersistentSyncSourceConfig> SyncConfig::getSyncSourceConfig(co
 
 list<string> SyncConfig::getSyncSources() const
 {
-    return m_tree->getChildren(m_oldLayout ? "spds/sources" : "sources");
+    // Return *all* sources configured in this context,
+    // not just those configured for the peer. This
+    // is necessary so that sources created for some other peer
+    // show up for the current one, to prevent overwriting
+    // existing properties unintentionally.
+    // Returned sources are an union of:
+    // 1. contextpath/sources
+    // 2. peers/[one-peer]/sources
+    // 3. sources in source filter
+    list<string> sources;
+    if (m_layout == SHARED_LAYOUT) {
+        // get sources in context
+        sources = m_tree->getChildren(m_contextPath + "/sources");
+        list<string> peerSources;
+        // get sources from peer if it's not empty
+        if (!m_peerPath.empty()) {
+            peerSources = m_tree->getChildren(m_peerPath + "/sources");
+        }
+        // union sources in specific peer
+        BOOST_FOREACH(const string &peerSource, peerSources) {
+            list<string>::iterator it = std::find(sources.begin(), sources.end(), peerSource);
+            // not found
+            if ( it == sources.end()) {
+                sources.push_back(peerSource); 
+            }
+        }
+    } else {
+        // get sources from peer
+        sources = m_tree->getChildren(m_peerPath +
+                                      (m_layout == SYNC4J_LAYOUT ? 
+                                       "/spds/sources" :
+                                       "/sources"));
+    }
+    // get sources from filter and union them into returned sources
+    BOOST_FOREACH(const SourceFilters_t::value_type &value, m_sourceFilters) {
+        list<string>::iterator it = std::find(sources.begin(), sources.end(), value.first);
+        if ( it == sources.end()) {
+            sources.push_back(value.first); 
+        }
+    }
+
+    return sources;
 }
 
 SyncSourceNodes SyncConfig::getSyncSourceNodes(const string &name,
-                                                        const string &changeId)
+                                               const string &changeId)
 {
-    boost::shared_ptr<FilterConfigNode> configNode;
-    boost::shared_ptr<ConfigNode> hiddenNode,
+    /** shared source properties */
+    boost::shared_ptr<FilterConfigNode> sharedNode;
+    /** per-peer source properties */
+    boost::shared_ptr<FilterConfigNode> peerNode;
+    /** per-peer internal properties and meta data */
+    boost::shared_ptr<ConfigNode> hiddenPeerNode,
+        serverNode,
         trackingNode;
 
-    boost::shared_ptr<ConfigNode> node;
-    string path = string(m_oldLayout ? "spds/sources/" : "sources/");
     // store configs lower case even if the UI uses mixed case
     string lower = name;
     boost::to_lower(lower);
-    path += lower;
 
-    node = m_tree->open(path, ConfigTree::visible);
-    configNode.reset(new FilterConfigNode(node, m_sourceFilter));
-    hiddenNode = m_tree->open(path, ConfigTree::hidden);
-    trackingNode = m_tree->open(path, ConfigTree::other, changeId);
+    boost::shared_ptr<ConfigNode> node;
+    string sharedPath, peerPath;
+    switch (m_layout) {
+    case SYNC4J_LAYOUT:
+        peerPath = m_peerPath + "/spds/sources/" + lower;
+        break;
+    case HTTP_SERVER_LAYOUT:
+        peerPath = m_peerPath + "/sources/" + lower;
+        break;
+    case SHARED_LAYOUT:
+        if (!m_peerPath.empty()) {
+            peerPath = m_peerPath + "/sources/" + lower;
+        }
+        sharedPath = m_contextPath + string("/sources/") + lower;
+        break;
+    }
+
+    if (peerPath.empty()) {
+        node.reset(new DevNullConfigNode(m_contextPath + " without peer configuration"));
+        peerNode.reset(new FilterConfigNode(node));
+        hiddenPeerNode =
+            trackingNode =
+            serverNode = node;
+    } else {
+        node = m_tree->open(peerPath, ConfigTree::visible);
+        peerNode.reset(new FilterConfigNode(node, m_sourceFilter));
+        SourceFilters_t::const_iterator filter = m_sourceFilters.find(name);
+        if (filter != m_sourceFilters.end()) {
+            peerNode =
+                boost::shared_ptr<FilterConfigNode>(new FilterConfigNode(boost::shared_ptr<ConfigNode>(peerNode), filter->second));
+        }
+        hiddenPeerNode = m_tree->open(peerPath, ConfigTree::hidden);
+        trackingNode = m_tree->open(peerPath, ConfigTree::other, changeId);
+        serverNode = m_tree->open(peerPath, ConfigTree::server, changeId);
+    }
 
-    return SyncSourceNodes(configNode, hiddenNode, trackingNode);
+    if (sharedPath.empty()) {
+        sharedNode = peerNode;
+    } else {
+        node = m_tree->open(sharedPath, ConfigTree::visible);
+        sharedNode.reset(new FilterConfigNode(node, m_sourceFilter));
+        SourceFilters_t::const_iterator filter = m_sourceFilters.find(name);
+        if (filter != m_sourceFilters.end()) {
+            sharedNode =
+                boost::shared_ptr<FilterConfigNode>(new FilterConfigNode(boost::shared_ptr<ConfigNode>(sharedNode), filter->second));
+        }
+    }
+
+    return SyncSourceNodes(sharedNode, peerNode, hiddenPeerNode, trackingNode, serverNode);
 }
 
 ConstSyncSourceNodes SyncConfig::getSyncSourceNodes(const string &name,
-                                                             const string &changeId) const
+                                                    const string &changeId) const
 {
     return const_cast<SyncConfig *>(this)->getSyncSourceNodes(name, changeId);
 }
 
-
 static ConfigProperty syncPropSyncURL("syncURL",
-                                      "the base URL of the SyncML server which is to be used for SyncML;\n"
-                                      "some examples:\n"
-                                      "- http://my.funambol.com/sync\n"
-                                      "- http://sync.scheduleworld.com/funambol/ds\n"
-                                      "- http://www.synthesis.ch/sync\n");
+                                      "Identifies how to contact the peer,\n"
+                                      "best explained with some examples.\n"
+                                      "HTTP(S) SyncML servers:\n"
+                                      "  http://my.funambol.com/sync\n"
+                                      "  http://sync.scheduleworld.com/funambol/ds\n"
+                                      "  https://m.google.com/syncml\n"
+                                      "OBEX over Bluetooth uses the MAC address, with\n"
+                                      "the channel chosen automatically:\n"
+                                      "  obex-bt://00:0A:94:03:F3:7E\n"
+                                      "If the automatism fails, the channel can also be specified:\n"
+                                      "  obex-bt://00:0A:94:03:F3:7E+16\n");
+
 static ConfigProperty syncPropDevID("deviceId",
                                     "The SyncML server gets this string and will use it to keep track of\n"
                                     "changes that still need to be synchronized with this particular\n"
@@ -486,7 +810,7 @@ static ConfigProperty syncPropDevID("deviceId",
                                     "myFUNAMBOL also requires that the string starts with sc-pim-");
 static ConfigProperty syncPropUsername("username",
                                        "user name used for authorization with the SyncML server",
-                                       "your SyncML server account name");
+                                       "");
 static PasswordConfigProperty syncPropPassword("password",
                                                "password used for authorization with the SyncML server;\n"
                                                "in addition to specifying it directly as plain text, it can\n"
@@ -495,11 +819,12 @@ static PasswordConfigProperty syncPropPassword("password",
                                                "  plain text: password = <insert your password here>\n"
                                                "         ask: password = -\n"
                                                "env variable: password = ${<name of environment variable>}\n",
-                                               "your SyncML server password",
+                                               "",
                                                "SyncML server");
 static BoolConfigProperty syncPropUseProxy("useProxy",
                                            "set to T to choose an HTTP proxy explicitly; otherwise the default\n"
-                                           "proxy settings of the underlying HTTP transport mechanism are used");
+                                           "proxy settings of the underlying HTTP transport mechanism are used;\n"
+                                           "only relevant when contacting the peer via HTTP");
 static ConfigProperty syncPropProxyHost("proxyHost",
                                         "proxy URL (http://<host>:<port>)");
 static ConfigProperty syncPropProxyUsername("proxyUsername",
@@ -516,7 +841,9 @@ static StringConfigProperty syncPropClientAuthType("clientAuthType",
                                                    "This setting is only for debugging purpose and only\n"
                                                    "has an effect during the initial sync of a client.\n"
                                                    "Later it remembers the method that was supported by\n"
-                                                   "the server and uses that.",
+                                                   "the server and uses that. When acting as server,\n"
+                                                   "clients contacting us can use both basic and md5\n"
+                                                   "authentication.\n",
                                                    "md5",
                                                    "",
                                                    Values() +
@@ -524,15 +851,17 @@ static StringConfigProperty syncPropClientAuthType("clientAuthType",
                                                    (Aliases("md5") + "syncml:auth-md5" + ""));
 static ULongConfigProperty syncPropMaxMsgSize("maxMsgSize",
                                               "The maximum size of each message can be set (maxMsgSize) and the\n"
-                                              "server can be told to never sent items larger than a certain\n"
-                                              "threshold (maxObjSize). Presumably the server has to truncate or\n"
+                                              "peer can be told to never sent items larger than a certain\n"
+                                              "threshold (maxObjSize). Presumably the peer has to truncate or\n"
                                               "skip larger items. Sizes are specified as number of bytes.",
                                               "20000");
 static UIntConfigProperty syncPropMaxObjSize("maxObjSize", "", "4000000");
 
 static BoolConfigProperty syncPropCompression("enableCompression", "enable compression of network traffic (not currently supported)");
 static BoolConfigProperty syncPropWBXML("enableWBXML",
-                                        "use the more compact binary XML (WBXML) for messages between client and server",
+                                        "use the more compact binary XML (WBXML) for messages between client and server;\n"
+                                        "not applicable when the peer is a SyncML client, because then the client\n"
+                                        "chooses the encoding",
                                         "TRUE");
 static ConfigProperty syncPropLogDir("logdir",
                                      "full path to directory where automatic backups and logs\n"
@@ -567,7 +896,11 @@ static UIntConfigProperty syncPropRetryDuration("RetryDuration",
                                           "is received or the message could not be delivered due\n"
                                           "to transport problems. When this time is exceeded\n"
                                           "without a response, the synchronization aborts without\n"
-                                          "sending further messages to the server."
+                                          "sending further messages to the server.\n"
+                                          "\n"
+                                          "When acting as server, this setting controls how long\n"
+                                          "a client is allowed to not send a message before the\n"
+                                          "synchronization is aborted."
                                           ,"300");
 static UIntConfigProperty syncPropRetryInterval("RetryInterval",
                                           "The number of seconds between the start of message sending\n"
@@ -575,12 +908,26 @@ static UIntConfigProperty syncPropRetryInterval("RetryInterval",
                                           "already passed when a message send returns, the\n"
                                           "message is resent immediately. Resending without\n"
                                           "any delay will never succeed and therefore specifying 0\n"
-                                          "disables retries."
+                                          "disables retries.\n"
+                                          "\n"
+                                          "Servers cannot resend messages, so this setting has no\n"
+                                          "effect in that case."
                                           ,"60");
+static BoolConfigProperty syncPropPeerIsClient("PeerIsClient",
+                                          "Indicates whether this configuration is about a\n"
+                                          "client peer or server peer.\n",
+                                          "0");
+static ConfigProperty syncPropRemoteIdentifier("remoteIdentifier",
+                                      "the identifier sent to the remote peer for a server initiated sync.\n"
+                                      "if not set, deviceId will be used instead\n",
+                                      "");
 static ConfigProperty syncPropSSLServerCertificates("SSLServerCertificates",
                                                     "A string specifying the location of the certificates\n"
                                                     "used to authenticate the server. When empty, the\n"
-                                                    "system's default location will be searched.",
+                                                    "system's default location will be searched.\n"
+                                                    "\n"
+                                                    "SSL support when acting as HTTP server is implemented\n"
+                                                    "by the HTTP server frontend, not with these properties.",
                                                     SYNCEVOLUTION_SSL_SERVER_CERTIFICATES);
 static BoolConfigProperty syncPropSSLVerifyServer("SSLVerifyServer",
                                                   "The client refuses to establish the connection unless\n"
@@ -618,6 +965,30 @@ static ULongConfigProperty syncPropHashCode("HashCode", "used by the SyncML libr
 
 static ConfigProperty syncPropConfigDate("ConfigDate", "used by the SyncML library internally; do not modify");
 
+static SafeConfigProperty syncPropRemoteDevID("remoteDeviceId",
+                                              "SyncML ID of our peer, empty if unknown; must be set only when\n"
+                                              "the peer is a SyncML client contacting us via HTTP.\n"
+                                              "Clients contacting us via OBEX/Bluetooth can be identified\n"
+                                              "either via this remoteDeviceId property or by their MAC\n"
+                                              "address, if that was set in the syncURL property.\n"
+                                              "\n"
+                                              "If this property is empty and the peer synchronizes with\n"
+                                              "this configuration chosen by some other means, then its ID\n"
+                                              "is recorded here automatically and later used to verify that\n"
+                                              "the configuration is not accidentally used by a different\n"
+                                              "peer.");
+
+static SafeConfigProperty syncPropNonce("lastNonce",
+                                        "MD5 nonce of our peer, empty if not set yet; do not edit, used internally");
+
+// used both as source and sync property, internal in both cases
+static SafeConfigProperty syncPropDeviceData("deviceData",
+                                             "information about the peer in the format described in the\n"
+                                             "Synthesis SDK manual under 'Session_SaveDeviceInfo'");
+
+static SafeConfigProperty syncPropDefaultPeer("defaultPeer",
+                                              "the peer which is used by default in some frontends, like the sync-UI");
+
 ConfigPropertyRegistry &SyncConfig::getRegistry()
 {
     static ConfigPropertyRegistry registry;
@@ -625,11 +996,8 @@ ConfigPropertyRegistry &SyncConfig::getRegistry()
 
     if (!initialized) {
         registry.push_back(&syncPropSyncURL);
-        syncPropSyncURL.setObligatory(true);
         registry.push_back(&syncPropUsername);
-        syncPropUsername.setObligatory(true);
         registry.push_back(&syncPropPassword);
-        syncPropPassword.setObligatory(true);
         registry.push_back(&syncPropLogDir);
         registry.push_back(&syncPropLogLevel);
         registry.push_back(&syncPropPrintChanges);
@@ -641,8 +1009,10 @@ ConfigPropertyRegistry &SyncConfig::getRegistry()
         registry.push_back(&syncPropClientAuthType);
         registry.push_back(&syncPropRetryDuration);
         registry.push_back(&syncPropRetryInterval);
+        registry.push_back(&syncPropRemoteIdentifier);
+        registry.push_back(&syncPropPeerIsClient);
         registry.push_back(&syncPropDevID);
-        syncPropDevID.setObligatory(true);
+        registry.push_back(&syncPropRemoteDevID);
         registry.push_back(&syncPropWBXML);
         registry.push_back(&syncPropMaxMsgSize);
         registry.push_back(&syncPropMaxObjSize);
@@ -654,26 +1024,48 @@ ConfigPropertyRegistry &SyncConfig::getRegistry()
         registry.push_back(&syncPropIconURI);
         registry.push_back(&syncPropConsumerReady);
         registry.push_back(&syncPropHashCode);
-        syncPropHashCode.setHidden(true);
         registry.push_back(&syncPropConfigDate);
+        registry.push_back(&syncPropNonce);
+        registry.push_back(&syncPropDeviceData);
+        registry.push_back(&syncPropDefaultPeer);
+
+        // obligatory sync properties
+        syncPropUsername.setObligatory(true);
+        syncPropPassword.setObligatory(true);
+        syncPropDevID.setObligatory(true);
+        syncPropSyncURL.setObligatory(true);
+
+        // hidden sync properties
+        syncPropHashCode.setHidden(true);
         syncPropConfigDate.setHidden(true);
+        syncPropNonce.setHidden(true);
+        syncPropDeviceData.setHidden(true);
+
+        // global sync properties
+        syncPropDefaultPeer.setSharing(ConfigProperty::GLOBAL_SHARING);
+
+        // peer independent sync properties
+        syncPropLogDir.setSharing(ConfigProperty::SOURCE_SET_SHARING);
+        syncPropMaxLogDirs.setSharing(ConfigProperty::SOURCE_SET_SHARING);
+        syncPropDevID.setSharing(ConfigProperty::SOURCE_SET_SHARING);
+
         initialized = true;
     }
 
     return registry;
 }
 
-const char *SyncConfig::getUsername() const { return m_stringCache.getProperty(*m_configNode, syncPropUsername); }
-void SyncConfig::setUsername(const string &value, bool temporarily) { syncPropUsername.setProperty(*m_configNode, value, temporarily); }
+const char *SyncConfig::getUsername() const { return m_stringCache.getProperty(*getNode(syncPropUsername), syncPropUsername); }
+void SyncConfig::setUsername(const string &value, bool temporarily) { syncPropUsername.setProperty(*getNode(syncPropUsername), value, temporarily); }
 const char *SyncConfig::getPassword() const {
-    string password = syncPropPassword.getCachedProperty(*m_configNode, m_cachedPassword);
+    string password = syncPropPassword.getCachedProperty(*getNode(syncPropPassword), m_cachedPassword);
     return m_stringCache.storeString(syncPropPassword.getName(), password);
 }
 void SyncConfig::checkPassword(ConfigUserInterface &ui) {
-    syncPropPassword.checkPassword(ui, m_server, *m_configNode, "", boost::shared_ptr<FilterConfigNode>());
+    syncPropPassword.checkPassword(ui, m_peer, *getProperties());
 }
 void SyncConfig::savePassword(ConfigUserInterface &ui) {
-    syncPropPassword.savePassword(ui,m_server, *m_configNode, "", boost::shared_ptr<FilterConfigNode>());
+    syncPropPassword.savePassword(ui, m_peer, *getProperties());
 }
 
 void PasswordConfigProperty::checkPassword(ConfigUserInterface &ui,
@@ -752,7 +1144,7 @@ void PasswordConfigProperty::savePassword(ConfigUserInterface &ui,
     }
 }
 
-string PasswordConfigProperty::getCachedProperty(ConfigNode &node,
+string PasswordConfigProperty::getCachedProperty(const ConfigNode &node,
                                                  const string &cachedPassword)
 {
     string password;
@@ -799,7 +1191,7 @@ void ProxyPasswordConfigProperty::checkPassword(ConfigUserInterface &ui,
                                            const boost::shared_ptr<FilterConfigNode> &sourceConfigNode) const
 {
     /* if useProxy is set 'true', then check proxypassword */
-    if(syncPropUseProxy.getProperty(globalConfigNode)) {
+    if(syncPropUseProxy.getPropertyValue(globalConfigNode)) {
         PasswordConfigProperty::checkPassword(ui, serverName, globalConfigNode, sourceName, sourceConfigNode);
     }
 }
@@ -816,132 +1208,248 @@ ConfigPasswordKey ProxyPasswordConfigProperty::getPasswordKey(const string &desc
     return key;
 }
 
-void SyncConfig::setPassword(const string &value, bool temporarily) { m_cachedPassword = ""; syncPropPassword.setProperty(*m_configNode, value, temporarily); }
-
-static const char *ProxyString = "http_proxy";
-
-/* Reads http_proxy from environment, if not available returns configured value */
-bool SyncConfig::getUseProxy() const {
-    char *proxy = getenv(ProxyString);
-    if (!proxy ) {
-        return syncPropUseProxy.getProperty(*m_configNode);
-    } else if (strlen(proxy)>0) {
-        return TRUE;
-    } else {
-        return FALSE;
-    }
-}
-
-void SyncConfig::setUseProxy(bool value, bool temporarily) { syncPropUseProxy.setProperty(*m_configNode, value, temporarily); }
-
-/* If http_proxy set in the environment returns it, otherwise configured value */
-const char *SyncConfig::getProxyHost() const {
-    char *proxy = getenv(ProxyString);
-    if (!proxy) {
-        return m_stringCache.getProperty(*m_configNode,syncPropProxyHost); 
-    } else {
-        return m_stringCache.storeString(syncPropProxyHost.getName(), proxy);
-    }
-}
-
-void SyncConfig::setProxyHost(const string &value, bool temporarily) { syncPropProxyHost.setProperty(*m_configNode, value, temporarily); }
-const char *SyncConfig::getProxyUsername() const { return m_stringCache.getProperty(*m_configNode, syncPropProxyUsername); }
-void SyncConfig::setProxyUsername(const string &value, bool temporarily) { syncPropProxyUsername.setProperty(*m_configNode, value, temporarily); }
+void SyncConfig::setPassword(const string &value, bool temporarily) { m_cachedPassword = ""; syncPropPassword.setProperty(*getNode(syncPropPassword), value, temporarily); }
+bool SyncConfig::getUseProxy() const { return syncPropUseProxy.getPropertyValue(*getNode(syncPropUseProxy)); }
+void SyncConfig::setUseProxy(bool value, bool temporarily) { syncPropUseProxy.setProperty(*getNode(syncPropUseProxy), value, temporarily); }
+const char *SyncConfig::getProxyHost() const { return m_stringCache.getProperty(*getNode(syncPropProxyHost), syncPropProxyHost); }
+void SyncConfig::setProxyHost(const string &value, bool temporarily) { syncPropProxyHost.setProperty(*getNode(syncPropProxyHost), value, temporarily); }
+const char *SyncConfig::getProxyUsername() const { return m_stringCache.getProperty(*getNode(syncPropProxyUsername), syncPropProxyUsername); }
+void SyncConfig::setProxyUsername(const string &value, bool temporarily) { syncPropProxyUsername.setProperty(*getNode(syncPropProxyUsername), value, temporarily); }
 const char *SyncConfig::getProxyPassword() const {
-    string password = syncPropProxyPassword.getCachedProperty(*m_configNode, m_cachedProxyPassword);
+    string password = syncPropProxyPassword.getCachedProperty(*getNode(syncPropProxyPassword), m_cachedProxyPassword);
     return m_stringCache.storeString(syncPropProxyPassword.getName(), password);
 }
 void SyncConfig::checkProxyPassword(ConfigUserInterface &ui) {
-    syncPropProxyPassword.checkPassword(ui, m_server, *m_configNode, "", boost::shared_ptr<FilterConfigNode>());
+    syncPropProxyPassword.checkPassword(ui, m_peer, *getNode(syncPropProxyPassword), "", boost::shared_ptr<FilterConfigNode>());
 }
 void SyncConfig::saveProxyPassword(ConfigUserInterface &ui) {
-    syncPropProxyPassword.savePassword(ui, m_server, *m_configNode, "", boost::shared_ptr<FilterConfigNode>());
+    syncPropProxyPassword.savePassword(ui, m_peer, *getNode(syncPropProxyPassword), "", boost::shared_ptr<FilterConfigNode>());
 }
-void SyncConfig::setProxyPassword(const string &value, bool temporarily) { m_cachedProxyPassword = ""; syncPropProxyPassword.setProperty(*m_configNode, value, temporarily); }
-const char *SyncConfig::getSyncURL() const { return m_stringCache.getProperty(*m_configNode, syncPropSyncURL); }
-void SyncConfig::setSyncURL(const string &value, bool temporarily) { syncPropSyncURL.setProperty(*m_configNode, value, temporarily); }
-const char *SyncConfig::getClientAuthType() const { return m_stringCache.getProperty(*m_configNode, syncPropClientAuthType); }
-void SyncConfig::setClientAuthType(const string &value, bool temporarily) { syncPropClientAuthType.setProperty(*m_configNode, value, temporarily); }
-unsigned long  SyncConfig::getMaxMsgSize() const { return syncPropMaxMsgSize.getProperty(*m_configNode); }
-void SyncConfig::setMaxMsgSize(unsigned long value, bool temporarily) { syncPropMaxMsgSize.setProperty(*m_configNode, value, temporarily); }
-unsigned int  SyncConfig::getMaxObjSize() const { return syncPropMaxObjSize.getProperty(*m_configNode); }
-void SyncConfig::setMaxObjSize(unsigned int value, bool temporarily) { syncPropMaxObjSize.setProperty(*m_configNode, value, temporarily); }
-bool SyncConfig::getCompression() const { return syncPropCompression.getProperty(*m_configNode); }
-void SyncConfig::setCompression(bool value, bool temporarily) { syncPropCompression.setProperty(*m_configNode, value, temporarily); }
-const char *SyncConfig::getDevID() const { return m_stringCache.getProperty(*m_configNode, syncPropDevID); }
-void SyncConfig::setDevID(const string &value, bool temporarily) { syncPropDevID.setProperty(*m_configNode, value, temporarily); }
-bool SyncConfig::getWBXML() const { return syncPropWBXML.getProperty(*m_configNode); }
-void SyncConfig::setWBXML(bool value, bool temporarily) { syncPropWBXML.setProperty(*m_configNode, value, temporarily); }
-const char *SyncConfig::getLogDir() const { return m_stringCache.getProperty(*m_configNode, syncPropLogDir); }
-void SyncConfig::setLogDir(const string &value, bool temporarily) { syncPropLogDir.setProperty(*m_configNode, value, temporarily); }
-int SyncConfig::getMaxLogDirs() const { return syncPropMaxLogDirs.getProperty(*m_configNode); }
-void SyncConfig::setMaxLogDirs(int value, bool temporarily) { syncPropMaxLogDirs.setProperty(*m_configNode, value, temporarily); }
-int SyncConfig::getLogLevel() const { return syncPropLogLevel.getProperty(*m_configNode); }
-void SyncConfig::setLogLevel(int value, bool temporarily) { syncPropLogLevel.setProperty(*m_configNode, value, temporarily); }
-int SyncConfig::getRetryDuration() const {return syncPropRetryDuration.getProperty(*m_configNode);}
-void SyncConfig::setRetryDuration(int value, bool temporarily) {syncPropRetryDuration.setProperty(*m_configNode, value, temporarily);}
-int SyncConfig::getRetryInterval() const {return syncPropRetryInterval.getProperty(*m_configNode);}
-void SyncConfig::setRetryInterval(int value, bool temporarily) {return syncPropRetryInterval.setProperty(*m_configNode,value,temporarily);}
-bool SyncConfig::getPrintChanges() const { return syncPropPrintChanges.getProperty(*m_configNode); }
-void SyncConfig::setPrintChanges(bool value, bool temporarily) { syncPropPrintChanges.setProperty(*m_configNode, value, temporarily); }
-std::string SyncConfig::getWebURL() const { return syncPropWebURL.getProperty(*m_configNode); }
-void SyncConfig::setWebURL(const std::string &url, bool temporarily) { syncPropWebURL.setProperty(*m_configNode, url, temporarily); }
-std::string SyncConfig::getIconURI() const { return syncPropIconURI.getProperty(*m_configNode); }
-bool SyncConfig::getConsumerReady() const { return syncPropConsumerReady.getProperty(*m_configNode); }
-void SyncConfig::setConsumerReady(bool ready) { return syncPropConsumerReady.setProperty(*m_configNode, ready); }
-void SyncConfig::setIconURI(const std::string &uri, bool temporarily) { syncPropIconURI.setProperty(*m_configNode, uri, temporarily); }
-unsigned long SyncConfig::getHashCode() const { return syncPropHashCode.getProperty(*m_hiddenNode); }
-void SyncConfig::setHashCode(unsigned long code) { syncPropHashCode.setProperty(*m_hiddenNode, code); }
-std::string SyncConfig::getConfigDate() const { return syncPropConfigDate.getProperty(*m_hiddenNode); }
+void SyncConfig::setProxyPassword(const string &value, bool temporarily) { m_cachedProxyPassword = ""; syncPropProxyPassword.setProperty(*getNode(syncPropProxyPassword), value, temporarily); }
+const char *SyncConfig::getSyncURL() const { return m_stringCache.getProperty(*getNode(syncPropSyncURL), syncPropSyncURL); }
+void SyncConfig::setSyncURL(const string &value, bool temporarily) { syncPropSyncURL.setProperty(*getNode(syncPropSyncURL), value, temporarily); }
+const char *SyncConfig::getClientAuthType() const { return m_stringCache.getProperty(*getNode(syncPropClientAuthType), syncPropClientAuthType); }
+void SyncConfig::setClientAuthType(const string &value, bool temporarily) { syncPropClientAuthType.setProperty(*getNode(syncPropClientAuthType), value, temporarily); }
+unsigned long  SyncConfig::getMaxMsgSize() const { return syncPropMaxMsgSize.getPropertyValue(*getNode(syncPropMaxMsgSize)); }
+void SyncConfig::setMaxMsgSize(unsigned long value, bool temporarily) { syncPropMaxMsgSize.setProperty(*getNode(syncPropMaxMsgSize), value, temporarily); }
+unsigned int  SyncConfig::getMaxObjSize() const { return syncPropMaxObjSize.getPropertyValue(*getNode(syncPropMaxObjSize)); }
+void SyncConfig::setMaxObjSize(unsigned int value, bool temporarily) { syncPropMaxObjSize.setProperty(*getNode(syncPropMaxObjSize), value, temporarily); }
+bool SyncConfig::getCompression() const { return syncPropCompression.getPropertyValue(*getNode(syncPropCompression)); }
+void SyncConfig::setCompression(bool value, bool temporarily) { syncPropCompression.setProperty(*getNode(syncPropCompression), value, temporarily); }
+const char *SyncConfig::getDevID() const { return m_stringCache.getProperty(*getNode(syncPropDevID), syncPropDevID); }
+void SyncConfig::setDevID(const string &value, bool temporarily) { syncPropDevID.setProperty(*getNode(syncPropDevID), value, temporarily); }
+bool SyncConfig::getWBXML() const { return syncPropWBXML.getPropertyValue(*getNode(syncPropWBXML)); }
+void SyncConfig::setWBXML(bool value, bool temporarily) { syncPropWBXML.setProperty(*getNode(syncPropWBXML), value, temporarily); }
+const char *SyncConfig::getLogDir() const { return m_stringCache.getProperty(*getNode(syncPropLogDir), syncPropLogDir); }
+void SyncConfig::setLogDir(const string &value, bool temporarily) { syncPropLogDir.setProperty(*getNode(syncPropLogDir), value, temporarily); }
+int SyncConfig::getMaxLogDirs() const { return syncPropMaxLogDirs.getPropertyValue(*getNode(syncPropMaxLogDirs)); }
+void SyncConfig::setMaxLogDirs(int value, bool temporarily) { syncPropMaxLogDirs.setProperty(*getNode(syncPropMaxLogDirs), value, temporarily); }
+int SyncConfig::getLogLevel() const { return syncPropLogLevel.getPropertyValue(*getNode(syncPropLogLevel)); }
+void SyncConfig::setLogLevel(int value, bool temporarily) { syncPropLogLevel.setProperty(*getNode(syncPropLogLevel), value, temporarily); }
+int SyncConfig::getRetryDuration() const {return syncPropRetryDuration.getPropertyValue(*getNode(syncPropRetryDuration));}
+void SyncConfig::setRetryDuration(int value, bool temporarily) { syncPropRetryDuration.setProperty(*getNode(syncPropRetryDuration), value, temporarily); }
+int SyncConfig::getRetryInterval() const { return syncPropRetryInterval.getPropertyValue(*getNode(syncPropRetryInterval)); }
+void SyncConfig::setRetryInterval(int value, bool temporarily) { return syncPropRetryInterval.setProperty(*getNode(syncPropRetryInterval),value,temporarily); }
+
+/* used by Server Alerted Sync */
+const char* SyncConfig::getRemoteIdentifier() const {return m_stringCache.getProperty (*getNode(syncPropRemoteIdentifier), syncPropRemoteIdentifier);}
+void SyncConfig::setRemoteIdentifier (const string &value, bool temporarily) { return syncPropRemoteIdentifier.setProperty (*getNode(syncPropRemoteIdentifier), value, temporarily); }
+
+bool SyncConfig::getPeerIsClient() const { return syncPropPeerIsClient.getPropertyValue(*getNode(syncPropPeerIsClient)); }
+void SyncConfig::setPeerIsClient(bool value, bool temporarily) { syncPropPeerIsClient.setProperty(*getNode(syncPropPeerIsClient), value, temporarily); }
+
+bool SyncConfig::getPrintChanges() const { return syncPropPrintChanges.getPropertyValue(*getNode(syncPropPrintChanges)); }
+void SyncConfig::setPrintChanges(bool value, bool temporarily) { syncPropPrintChanges.setProperty(*getNode(syncPropPrintChanges), value, temporarily); }
+std::string SyncConfig::getWebURL() const { return syncPropWebURL.getProperty(*getNode(syncPropWebURL)); }
+void SyncConfig::setWebURL(const std::string &url, bool temporarily) { syncPropWebURL.setProperty(*getNode(syncPropWebURL), url, temporarily); }
+std::string SyncConfig::getIconURI() const { return syncPropIconURI.getProperty(*getNode(syncPropIconURI)); }
+bool SyncConfig::getConsumerReady() const { return syncPropConsumerReady.getPropertyValue(*getNode(syncPropConsumerReady)); }
+void SyncConfig::setConsumerReady(bool ready) { return syncPropConsumerReady.setProperty(*getNode(syncPropConsumerReady), ready); }
+void SyncConfig::setIconURI(const std::string &uri, bool temporarily) { syncPropIconURI.setProperty(*getNode(syncPropIconURI), uri, temporarily); }
+unsigned long SyncConfig::getHashCode() const { return syncPropHashCode.getPropertyValue(*getNode(syncPropHashCode)); }
+void SyncConfig::setHashCode(unsigned long code) { syncPropHashCode.setProperty(*getNode(syncPropHashCode), code); }
+std::string SyncConfig::getConfigDate() const { return syncPropConfigDate.getProperty(*getNode(syncPropConfigDate)); }
 void SyncConfig::setConfigDate() { 
     /* Set current timestamp as configdate */
     char buffer[17]; 
     time_t ts = time(NULL);
     strftime(buffer, sizeof(buffer), "%Y%m%dT%H%M%SZ", gmtime(&ts));
     const std::string date(buffer);
-    syncPropConfigDate.setProperty(*m_hiddenNode, date);
+    syncPropConfigDate.setProperty(*getNode(syncPropConfigDate), date);
+}
+
+const char* SyncConfig::getSSLServerCertificates() const { return m_stringCache.getProperty(*getNode(syncPropSSLServerCertificates), syncPropSSLServerCertificates); }
+void SyncConfig::setSSLServerCertificates(const string &value, bool temporarily) { syncPropSSLServerCertificates.setProperty(*getNode(syncPropSSLServerCertificates), value, temporarily); }
+bool SyncConfig::getSSLVerifyServer() const { return syncPropSSLVerifyServer.getPropertyValue(*getNode(syncPropSSLVerifyServer)); }
+void SyncConfig::setSSLVerifyServer(bool value, bool temporarily) { syncPropSSLVerifyServer.setProperty(*getNode(syncPropSSLVerifyServer), value, temporarily); }
+bool SyncConfig::getSSLVerifyHost() const { return syncPropSSLVerifyHost.getPropertyValue(*getNode(syncPropSSLVerifyHost)); }
+void SyncConfig::setSSLVerifyHost(bool value, bool temporarily) { syncPropSSLVerifyHost.setProperty(*getNode(syncPropSSLVerifyHost), value, temporarily); }
+string SyncConfig::getRemoteDevID() const { return syncPropRemoteDevID.getProperty(*getNode(syncPropRemoteDevID)); }
+void SyncConfig::setRemoteDevID(const string &value) { syncPropRemoteDevID.setProperty(*getNode(syncPropRemoteDevID), value); }
+string SyncConfig::getNonce() const { return syncPropNonce.getProperty(*getNode(syncPropNonce)); }
+void SyncConfig::setNonce(const string &value) { syncPropNonce.setProperty(*getNode(syncPropNonce), value); }
+string SyncConfig::getDeviceData() const { return syncPropDeviceData.getProperty(*getNode(syncPropDeviceData)); }
+void SyncConfig::setDeviceData(const string &value) { syncPropDeviceData.setProperty(*getNode(syncPropDeviceData), value); }
+string SyncConfig::getDefaultPeer() const { return syncPropDefaultPeer.getProperty(*getNode(syncPropDefaultPeer)); }
+void SyncConfig::setDefaultPeer(const string &value) { syncPropDefaultPeer.setProperty(*getNode(syncPropDefaultPeer), value); }
+
+std::string SyncConfig::findSSLServerCertificate()
+{
+    std::string paths = getSSLServerCertificates();
+    std::vector< std::string > files;
+    boost::split(files, paths, boost::is_any_of(":"));
+    BOOST_FOREACH(std::string file, files) {
+        if (!file.empty() && !access(file.c_str(), R_OK)) {
+            return file;
+        }
+    }
+
+    return "";
+}
+
+void SyncConfig::setConfigFilter(bool sync,
+                                 const std::string &source,
+                                 const FilterConfigNode::ConfigFilter &filter)
+{
+    if (sync) {
+        m_peerNode->setFilter(filter);
+        if (m_peerNode != m_contextNode) {
+            m_contextNode->setFilter(filter);
+        }
+        if (m_globalNode != m_contextNode) {
+            m_globalNode->setFilter(filter);
+        }
+    } else if (source.empty()) {
+        m_sourceFilter = filter;
+    } else {
+        m_sourceFilters[source] = filter;
+    }
+}
+
+boost::shared_ptr<FilterConfigNode>
+SyncConfig::getNode(const ConfigProperty &prop)
+{
+    switch (prop.getSharing()) {
+    case ConfigProperty::GLOBAL_SHARING:
+        if (prop.isHidden()) {
+            boost::shared_ptr<FilterConfigNode>(new FilterConfigNode(boost::shared_ptr<ConfigNode>(new DevNullConfigNode("no hidden global properties"))));
+        } else {
+            return m_globalNode;
+        }
+        break;
+    case ConfigProperty::SOURCE_SET_SHARING:
+        if (prop.isHidden()) {
+            return boost::shared_ptr<FilterConfigNode>(new FilterConfigNode(m_contextHiddenNode));
+        } else {
+            return m_contextNode;
+        }
+        break;
+    case ConfigProperty::NO_SHARING:
+        if (prop.isHidden()) {
+            return boost::shared_ptr<FilterConfigNode>(new FilterConfigNode(m_hiddenPeerNode));
+        } else {
+            return m_peerNode;
+        }
+        break;
+    }
+    // should not be reached
+    return boost::shared_ptr<FilterConfigNode>(new FilterConfigNode(boost::shared_ptr<ConfigNode>(new DevNullConfigNode("unknown sharing state of property"))));
 }
-const char* SyncConfig::getSSLServerCertificates() const { return m_stringCache.getProperty(*m_configNode, syncPropSSLServerCertificates); }
-void SyncConfig::setSSLServerCertificates(const string &value, bool temporarily) { syncPropSSLServerCertificates.setProperty(*m_configNode, value, temporarily); }
-bool SyncConfig::getSSLVerifyServer() const { return syncPropSSLVerifyServer.getProperty(*m_configNode); }
-void SyncConfig::setSSLVerifyServer(bool value, bool temporarily) { syncPropSSLVerifyServer.setProperty(*m_configNode, value, temporarily); }
-bool SyncConfig::getSSLVerifyHost() const { return syncPropSSLVerifyHost.getProperty(*m_configNode); }
-void SyncConfig::setSSLVerifyHost(bool value, bool temporarily) { syncPropSSLVerifyHost.setProperty(*m_configNode, value, temporarily); }
 
 static void setDefaultProps(const ConfigPropertyRegistry &registry,
                             boost::shared_ptr<FilterConfigNode> node,
-                            bool force)
+                            bool force,
+                            bool unshared,
+                            bool useObligatory = true)
 {
     BOOST_FOREACH(const ConfigProperty *prop, registry) {
         bool isDefault;
         prop->getProperty(*node, &isDefault);
         
         if (!prop->isHidden() &&
+            (unshared || prop->getSharing() != ConfigProperty::NO_SHARING) &&
             (force || isDefault)) {
-            prop->setDefaultProperty(*node, prop->isObligatory());
+            if (useObligatory) {
+                prop->setDefaultProperty(*node, prop->isObligatory());
+            } else {
+                prop->setDefaultProperty(*node, false);
+            }
         }
-    }    
+    }
 }
 
 void SyncConfig::setDefaults(bool force)
 {
-    setDefaultProps(getRegistry(), m_configNode, force);
+    setDefaultProps(getRegistry(), getProperties(),
+                    force,
+                    !m_peerPath.empty());
 }
 
 void SyncConfig::setSourceDefaults(const string &name, bool force)
 {
     SyncSourceNodes nodes = getSyncSourceNodes(name);
     setDefaultProps(SyncSourceConfig::getRegistry(),
-                    nodes.m_configNode, force);
+                    nodes.getProperties(),
+                    force,
+                    !m_peerPath.empty());
+}
+
+void SyncConfig::removeSyncSource(const string &name)
+{
+    string lower = name;
+    boost::to_lower(lower);
+    string pathName;
+
+    if (m_layout == SHARED_LAYOUT) {
+        if (m_peerPath.empty()) {
+            // removed shared source properties...
+            pathName = m_contextPath + "/sources/" + lower;
+            m_tree->remove(pathName);
+            // ... and the peer-specific ones of *all* peers
+            BOOST_FOREACH(const std::string peer,
+                          m_tree->getChildren("peers")) {
+                m_tree->remove(string("peers/") + peer + "/sources/" + lower);
+            }
+        } else {
+            // remove only inside the selected peer
+            m_tree->remove(m_peerPath + "/sources/" + lower);
+        }
+    } else {
+        // remove the peer-specific ones
+        pathName = m_peerPath +
+            (m_layout == SYNC4J_LAYOUT ? "spds/sources/" : "sources/") +
+            lower;
+        m_tree->remove(pathName);
+    }
+}
+
+void SyncConfig::clearSyncSourceProperties(const string &name)
+{
+    SyncSourceNodes nodes = getSyncSourceNodes(name);
+    setDefaultProps(SyncSourceConfig::getRegistry(),
+                    nodes.getProperties(),
+                    true,
+                    !m_peerPath.empty(),
+                    false);
+}
+
+void SyncConfig::clearSyncProperties()
+{
+    setDefaultProps(getRegistry(), getProperties(),
+                    true,
+                    !m_peerPath.empty(),
+                    false);
 }
 
 static void copyProperties(const ConfigNode &fromProps,
                            ConfigNode &toProps,
                            bool hidden,
+                           bool unshared,
                            const ConfigPropertyRegistry &allProps)
 {
     BOOST_FOREACH(const ConfigProperty *prop, allProps) {
-        if (prop->isHidden() == hidden) {
+        if (prop->isHidden() == hidden &&
+            (unshared || prop->getSharing() != ConfigProperty::NO_SHARING)) {
             string name = prop->getName();
             bool isDefault;
             string value = prop->getProperty(fromProps, &isDefault);
@@ -954,22 +1462,22 @@ static void copyProperties(const ConfigNode &fromProps,
 static void copyProperties(const ConfigNode &fromProps,
                            ConfigNode &toProps)
 {
-    map<string, string> props;
+    ConfigProps props;
     fromProps.readProperties(props);
-
-    BOOST_FOREACH(const StringPair &prop, props) {
-        toProps.setProperty(prop.first, prop.second);
-    }
+    toProps.writeProperties(props);
 }
 
 void SyncConfig::copy(const SyncConfig &other,
                                const set<string> *sourceFilter)
 {
-    static const bool visibility[2] = { false, true };
     for (int i = 0; i < 2; i++ ) {
-        boost::shared_ptr<const FilterConfigNode> fromSyncProps(other.getProperties(visibility[i]));
-        boost::shared_ptr<FilterConfigNode> toSyncProps(this->getProperties(visibility[i]));
-        copyProperties(*fromSyncProps, *toSyncProps, visibility[i], other.getRegistry());
+        boost::shared_ptr<const FilterConfigNode> fromSyncProps(other.getProperties(i));
+        boost::shared_ptr<FilterConfigNode> toSyncProps(this->getProperties(i));
+        copyProperties(*fromSyncProps,
+                       *toSyncProps,
+                       i,
+                       !m_peerPath.empty(),
+                       SyncConfig::getRegistry());
     }
 
     list<string> sources = other.getSyncSources();
@@ -978,9 +1486,18 @@ void SyncConfig::copy(const SyncConfig &other,
             sourceFilter->find(sourceName) != sourceFilter->end()) {
             ConstSyncSourceNodes fromNodes = other.getSyncSourceNodes(sourceName);
             SyncSourceNodes toNodes = this->getSyncSourceNodes(sourceName);
-            copyProperties(*fromNodes.m_configNode, *toNodes.m_configNode, false, SyncSourceConfig::getRegistry());
-            copyProperties(*fromNodes.m_hiddenNode, *toNodes.m_hiddenNode, true, SyncSourceConfig::getRegistry());
-            copyProperties(*fromNodes.m_trackingNode, *toNodes.m_trackingNode);
+
+            for (int i = 0; i < 2; i++ ) {
+                copyProperties(*fromNodes.getProperties(i),
+                               *toNodes.getProperties(i),
+                               i,
+                               !m_peerPath.empty(),
+                               SyncSourceConfig::getRegistry());
+            }
+            copyProperties(*fromNodes.getTrackingNode(),
+                           *toNodes.getTrackingNode());
+            copyProperties(*fromNodes.getServerNode(),
+                           *toNodes.getServerNode());
         }
     }
 }
@@ -1016,6 +1533,11 @@ StringConfigProperty SyncSourceConfig::m_sourcePropSync("sync",
                                            (Aliases("one-way-from-client") + "one-way-client") +
                                            (Aliases("one-way-from-server") + "one-way-server" + "one-way") +
                                            (Aliases("disabled") + "none"));
+static bool SourcePropSyncIsSet(boost::shared_ptr<SyncSourceConfig> source)
+{
+    return source->isSet(SyncSourceConfig::m_sourcePropSync);
+}
+
 
 static class SourceTypeConfigProperty : public StringConfigProperty {
 public:
@@ -1028,14 +1550,31 @@ public:
                              "automatically unless specified differently.\n"
                              "Sometimes the format must be specified.\n"
                              "\n"
+                             "A special 'virtual' backend combines several other\n"
+                             "data sources and presents them as one set of items\n"
+                             "to the peer. For example, Nokia phones typically\n"
+                             "exchange tasks and events as part of one set of\n"
+                             "calendar items.\n"
+                             "\n"
+                             "Right now such a virtual backend is limited to\n"
+                             "combining one calendar source with events and one\n"
+                             "task source. They have to be specified in the\n"
+                             "'evolutionsource' property, typically like this:\n"
+                             "  calendar,todo\n"
+                             "\n"
                              "In all cases the format of this configuration is\n"
                              "  <backend>[:format]\n"
                              "\n"
+                             "Different sources combined in one virtual source must\n"
+                             "have a common representation. As with other backends,\n"
+                             "the preferred format can be influenced via the 'format'\n"
+                             "attribute.\n"
                              "Here are some valid examples:\n"
                              "  contacts - synchronize address book with default vCard 2.1 format\n"
                              "  contacts:text/vcard - address book with vCard 3.0 format\n"
                              "  calendar - synchronize events in iCalendar 2.0 format\n"
-                             "  calendar:text/x-calendar - prefer legacy vCalendar 1.0 format\n"
+                             "  calendar:text/x-vcalendar - prefer legacy vCalendar 1.0 format\n"
+                             "  virtual:text/x-vcalendar - a virtual backend using vCalendar 1.0 format\n"
                              "\n"
                              "Sending and receiving items in the same format as used by the server for\n"
                              "the uri selected below is essential. Normally, SyncEvolution and the server\n"
@@ -1056,6 +1595,7 @@ public:
                              "select backend",
                              "",
                              Values() +
+                             (Aliases("virtual")) +
                              (Aliases("calendar") + "events") +
                              (Aliases("calendar:text/calendar") + "text/calendar") +
                              (Aliases("calendar:text/x-vcalendar") + "text/x-vcalendar") +
@@ -1128,6 +1668,13 @@ static ConfigProperty sourcePropDatabaseID("evolutionsource",
                                            "like for example the system address book.\n"
                                            "Not setting this property selects that default\n"
                                            "data source.\n"
+                                           "If the backend is a virtual data source,\n"
+                                           "this field must contain comma seperated list of\n"
+                                           "sub datasources actually used to store data.\n"
+                                           "If your sub datastore has a comma in name, you\n"
+                                           "must prevent taht comma from being mistaken as the\n"
+                                           "separator by preceding it with a backslash, like this:\n"
+                                           "  evolutionsource=Source1PartA\\,PartB,Source2\\\\Backslash\n"
                                            "\n"
                                            "To get a full list of available data sources,\n"
                                            "run syncevolution without parameters. The name\n"
@@ -1153,8 +1700,8 @@ static ConfigProperty sourcePropUser("evolutionuser",
                                      "can cause the Evolution backend to hang.");
 static EvolutionPasswordConfigProperty sourcePropPassword("evolutionpassword", "","", "backend");
 
-static ULongConfigProperty sourcePropLast("last",
-                                          "used by the SyncML library internally; do not modify");
+static ConfigProperty sourcePropAdminData(SourceAdminDataName,
+                                          "used by the Synthesis library internally; do not modify");
 
 ConfigPropertyRegistry &SyncSourceConfig::getRegistry()
 {
@@ -1163,46 +1710,112 @@ ConfigPropertyRegistry &SyncSourceConfig::getRegistry()
 
     if (!initialized) {
         registry.push_back(&SyncSourceConfig::m_sourcePropSync);
-        SyncSourceConfig::m_sourcePropSync.setObligatory(true);
         registry.push_back(&sourcePropSourceType);
         registry.push_back(&sourcePropDatabaseID);
         registry.push_back(&sourcePropURI);
         registry.push_back(&sourcePropUser);
         registry.push_back(&sourcePropPassword);
-        registry.push_back(&sourcePropLast);
-        sourcePropLast.setHidden(true);
+        registry.push_back(&sourcePropAdminData);
+
+        // obligatory source properties
+        SyncSourceConfig::m_sourcePropSync.setObligatory(true);
+
+        // hidden source properties - only possible for
+        // non-shared properties (other hidden nodes don't
+        // exist at the moment)
+        sourcePropAdminData.setHidden(true);
+
+        // No global source properties. Does not make sense
+        // conceptually.
+
+        // peer independent source properties
+        sourcePropDatabaseID.setSharing(ConfigProperty::SOURCE_SET_SHARING);
+        sourcePropUser.setSharing(ConfigProperty::SOURCE_SET_SHARING);
+        sourcePropPassword.setSharing(ConfigProperty::SOURCE_SET_SHARING);
+
+        // Save "type" also in the shared nodes, so that the backend
+        // can be selected independently from a specific peer.
+        sourcePropSourceType.setFlags(ConfigProperty::SHARED_AND_UNSHARED);
+
         initialized = true;
     }
 
     return registry;
 }
 
-const char *SyncSourceConfig::getDatabaseID() const { return m_stringCache.getProperty(*m_nodes.m_configNode, sourcePropDatabaseID); }
-void SyncSourceConfig::setDatabaseID(const string &value, bool temporarily) { sourcePropDatabaseID.setProperty(*m_nodes.m_configNode, value, temporarily); }
-const char *SyncSourceConfig::getUser() const { return m_stringCache.getProperty(*m_nodes.m_configNode, sourcePropUser); }
-void SyncSourceConfig::setUser(const string &value, bool temporarily) { sourcePropUser.setProperty(*m_nodes.m_configNode, value, temporarily); }
+SyncSourceNodes::SyncSourceNodes(const boost::shared_ptr<FilterConfigNode> &sharedNode,
+                                 const boost::shared_ptr<FilterConfigNode> &peerNode,
+                                 const boost::shared_ptr<ConfigNode> &hiddenPeerNode,
+                                 const boost::shared_ptr<ConfigNode> &trackingNode,
+                                 const boost::shared_ptr<ConfigNode> &serverNode) :
+    m_sharedNode(sharedNode),
+    m_peerNode(peerNode),
+    m_hiddenPeerNode(hiddenPeerNode),
+    m_trackingNode(trackingNode),
+    m_serverNode(serverNode)
+{
+    boost::shared_ptr<MultiplexConfigNode> mnode;
+    mnode.reset(new MultiplexConfigNode(m_peerNode->getName(),
+                                        SyncSourceConfig::getRegistry(),
+                                        false));
+    m_props[false] = mnode;
+    mnode->setNode(false, ConfigProperty::SOURCE_SET_SHARING,
+                   m_sharedNode);
+    mnode->setNode(false, ConfigProperty::NO_SHARING,
+                   m_peerNode);
+    // no multiplexing necessary for hidden peer properties yet
+    m_props[true].reset(new FilterConfigNode(m_hiddenPeerNode));
+}
+
+
+boost::shared_ptr<FilterConfigNode>
+SyncSourceNodes::getNode(const ConfigProperty &prop) const
+{
+    switch (prop.getSharing()) {
+    case ConfigProperty::GLOBAL_SHARING:
+        return boost::shared_ptr<FilterConfigNode>(new FilterConfigNode(boost::shared_ptr<ConfigNode>(new DevNullConfigNode("no global source properties"))));
+        break;
+    case ConfigProperty::SOURCE_SET_SHARING:
+        if (prop.isHidden()) {
+            return boost::shared_ptr<FilterConfigNode>(new FilterConfigNode(boost::shared_ptr<ConfigNode>(new DevNullConfigNode("no hidden source set properties"))));
+        } else {
+            return m_sharedNode;
+        }
+        break;
+    case ConfigProperty::NO_SHARING:
+        if (prop.isHidden()) {
+            return boost::shared_ptr<FilterConfigNode>(new FilterConfigNode(m_hiddenPeerNode));
+        } else {
+            return m_peerNode;
+        }
+    }
+    return boost::shared_ptr<FilterConfigNode>();
+}
+
+const char *SyncSourceConfig::getDatabaseID() const { return m_stringCache.getProperty(*getNode(sourcePropDatabaseID), sourcePropDatabaseID); }
+void SyncSourceConfig::setDatabaseID(const string &value, bool temporarily) { sourcePropDatabaseID.setProperty(*getNode(sourcePropDatabaseID), value, temporarily); }
+const char *SyncSourceConfig::getUser() const { return m_stringCache.getProperty(*getNode(sourcePropUser), sourcePropUser); }
+void SyncSourceConfig::setUser(const string &value, bool temporarily) { sourcePropUser.setProperty(*getNode(sourcePropUser), value, temporarily); }
 const char *SyncSourceConfig::getPassword() const {
-    string password = sourcePropPassword.getCachedProperty(*m_nodes.m_configNode, m_cachedPassword);
+    string password = sourcePropPassword.getCachedProperty(*getNode(sourcePropPassword), m_cachedPassword);
     return m_stringCache.storeString(sourcePropPassword.getName(), password);
 }
 void SyncSourceConfig::checkPassword(ConfigUserInterface &ui, 
                                      const string &serverName, 
                                      FilterConfigNode& globalConfigNode) {
-    sourcePropPassword.checkPassword(ui, serverName, globalConfigNode, m_name, m_nodes.m_configNode);
+    sourcePropPassword.checkPassword(ui, serverName, globalConfigNode, m_name, getNode(sourcePropPassword));
 }
 void SyncSourceConfig::savePassword(ConfigUserInterface &ui, 
                                     const string &serverName, 
                                     FilterConfigNode& globalConfigNode) {
-    sourcePropPassword.savePassword(ui, serverName, globalConfigNode, m_name, m_nodes.m_configNode);
+    sourcePropPassword.savePassword(ui, serverName, globalConfigNode, m_name, getNode(sourcePropPassword));
 }
-void SyncSourceConfig::setPassword(const string &value, bool temporarily) { m_cachedPassword = ""; sourcePropPassword.setProperty(*m_nodes.m_configNode, value, temporarily); }
-const char *SyncSourceConfig::getURI() const { return m_stringCache.getProperty(*m_nodes.m_configNode, sourcePropURI); }
-void SyncSourceConfig::setURI(const string &value, bool temporarily) { sourcePropURI.setProperty(*m_nodes.m_configNode, value, temporarily); }
-const char *SyncSourceConfig::getSync() const { return m_stringCache.getProperty(*m_nodes.m_configNode, m_sourcePropSync); }
-void SyncSourceConfig::setSync(const string &value, bool temporarily) { m_sourcePropSync.setProperty(*m_nodes.m_configNode, value, temporarily); }
-unsigned long SyncSourceConfig::getLast() const { return sourcePropLast.getProperty(*m_nodes.m_hiddenNode); }
-void SyncSourceConfig::setLast(unsigned long timestamp) { sourcePropLast.setProperty(*m_nodes.m_hiddenNode, timestamp); }
-string SyncSourceConfig::getSourceTypeString(const SyncSourceNodes &nodes) { return sourcePropSourceType.getProperty(*nodes.m_configNode); }
+void SyncSourceConfig::setPassword(const string &value, bool temporarily) { m_cachedPassword = ""; sourcePropPassword.setProperty(*getNode(sourcePropPassword), value, temporarily); }
+const char *SyncSourceConfig::getURI() const { return m_stringCache.getProperty(*getNode(sourcePropURI), sourcePropURI); }
+void SyncSourceConfig::setURI(const string &value, bool temporarily) { sourcePropURI.setProperty(*getNode(sourcePropURI), value, temporarily); }
+const char *SyncSourceConfig::getSync() const { return m_stringCache.getProperty(*getNode(m_sourcePropSync), m_sourcePropSync); }
+void SyncSourceConfig::setSync(const string &value, bool temporarily) { m_sourcePropSync.setProperty(*getNode(m_sourcePropSync), value, temporarily); }
+string SyncSourceConfig::getSourceTypeString(const SyncSourceNodes &nodes) { return sourcePropSourceType.getProperty(*nodes.getNode(sourcePropSourceType)); }
 SourceType SyncSourceConfig::getSourceType(const SyncSourceNodes &nodes) {
     string type = getSourceTypeString(nodes);
     SourceType sourceType;
@@ -1225,7 +1838,7 @@ SourceType SyncSourceConfig::getSourceType(const SyncSourceNodes &nodes) {
     return sourceType;
 }
 SourceType SyncSourceConfig::getSourceType() const { return getSourceType(m_nodes); }
-void SyncSourceConfig::setSourceType(const string &value, bool temporarily) { sourcePropSourceType.setProperty(*m_nodes.m_configNode, value, temporarily); }
+void SyncSourceConfig::setSourceType(const string &value, bool temporarily) { sourcePropSourceType.setProperty(*getNode(sourcePropSourceType), value, temporarily); }
 
 ConfigPasswordKey EvolutionPasswordConfigProperty::getPasswordKey(const string &descr,
                                                                   const string &serverName,
index 8c80250..5eb45f0 100644 (file)
@@ -21,6 +21,7 @@
 # define INCL_SYNC_EVOLUTION_CONFIG
 
 #include <syncevo/FilterConfigNode.h>
+#include <syncevo/SafeConfigNode.h>
 
 #include <boost/shared_ptr.hpp>
 #include <boost/algorithm/string/predicate.hpp>
@@ -48,8 +49,11 @@ class SyncSourceConfig;
 class PersistentSyncSourceConfig;
 class ConfigTree;
 class ConfigUserInterface;
-struct SyncSourceNodes;
-struct ConstSyncSourceNodes;
+class SyncSourceNodes;
+class ConstSyncSourceNodes;
+
+/** name of the per-source admin data property */
+extern const char *const SourceAdminDataName;
 
 /**
  * A property has a name and a comment. Derived classes might have
@@ -63,6 +67,33 @@ struct ConstSyncSourceNodes;
  * trigger an exception. Setting invalid values does not because
  * it is not known where the value comes from - the caller should
  * check it himself.
+ *
+ * Properties are either registered as source properties or
+ * source-independent sync properties. In each of these two sets of
+ * properties, the names must be unique.
+ *
+ * Properties can be either user-visible (and editable) or
+ * internal. Internal properties are used to cache some information
+ * and may get lost when copying configurations. Therefore it
+ * must be possible to recreate them somehow, if necessary with
+ * an expensive operation like a slow sync.
+ *
+ * Starting with SyncEvolution 1.0, the internal storage of
+ * property values was reorganized so that some properties
+ * can be shared between peers. The concept of two property
+ * sets (source and sync properties) was preserved because of
+ * the simplicity that it brings to the APIs. Now this concept
+ * is implemented by mapping properties into "views" that
+ * contain the properties relevant for a particular peer.
+ * Setting a shared value in one view updates the value in
+ * another. For details, see:
+ * http://syncevolution.org/development/configuration-handling
+ *
+ * As in the migration from the Sync4j config layout (internal and
+ * user-visible properties in the same file), the code is written so
+ * that properties are mapped to config nodes according to the most
+ * recent layout. Older layouts are accessed by using the same config
+ * node instance multiple times.
  */
 class ConfigProperty {
  public:
@@ -70,6 +101,8 @@ class ConfigProperty {
                    const string &def = string(""), const string &descr = string("")) :
         m_obligatory(false),
         m_hidden(false),
+        m_sharing(NO_SHARING),
+        m_flags(0),
         m_name(name),
         m_comment(boost::trim_right_copy(comment)),
             m_defValue(def),
@@ -133,12 +166,41 @@ class ConfigProperty {
     /** split \n separated comment into lines without \n, appending them to commentLines */
     static void splitComment(const string &comment, list<string> &commentLines);
 
+    /** internal property? */
     bool isHidden() const { return m_hidden; }
     void setHidden(bool hidden) { m_hidden = hidden; }
 
+    /** config is invalid without setting this property? */
     bool isObligatory() const { return m_obligatory; }
     void setObligatory(bool obligatory) { m_obligatory = obligatory; }
 
+    /**
+     * determines how a property is shared between different views
+     */
+    enum Sharing {
+        GLOBAL_SHARING,         /**< shared between all views,
+                                   for example the "default peer" property */
+        SOURCE_SET_SHARING,     /**< shared between all peers accessing
+                                   the same source set, for example the
+                                   logdir property */
+        NO_SHARING              /**< each peer has his own values */
+    };
+    Sharing getSharing() const { return m_sharing; }
+    void setSharing(Sharing sharing) { m_sharing = sharing; }
+
+    /**
+     * special hacks for certain properties
+     */
+    enum Flags {
+        SHARED_AND_UNSHARED = 1<<0   /**< value is stored with
+                                        SOURCE_SET_SHARING and
+                                        NO_SHARING, the later taking
+                                        precedency when reading
+                                        ("type"!) */
+    };
+    void setFlags(int flags) { m_flags = flags; }
+    int getFlags(void) const { return m_flags; }
+
     /** set value unconditionally, even if it is not valid */
     void setProperty(ConfigNode &node, const string &value) const { node.setProperty(getName(), value, getComment()); }
     void setProperty(FilterConfigNode &node, const string &value, bool temporarily = false) const {
@@ -156,6 +218,10 @@ class ConfigProperty {
     }
 
     /**
+     * String representation of property value. getPropertyValue() in
+     * some derived classes returns the value in some other, class specific
+     * representation.
+     *
      * @retval isDefault    return true if the node had no value set and
      *                      the default was returned instead
      */
@@ -180,7 +246,7 @@ class ConfigProperty {
     }
 
     // true if property is set to non-empty value
-    virtual bool isSet(const ConfigNode &node) const {
+    bool isSet(const ConfigNode &node) const {
         string name = getName();
         string value = node.readProperty(name);
         return !value.empty();
@@ -192,6 +258,8 @@ class ConfigProperty {
  private:
     bool m_obligatory;
     bool m_hidden;
+    Sharing m_sharing;
+    int m_flags;
     const string m_name, m_comment, m_defValue, m_descr;
 };
 
@@ -347,7 +415,7 @@ template<class T> class TypedConfigProperty : public ConfigProperty {
         }
     }
 
-    T getProperty(ConfigNode &node, bool *isDefault = NULL) {
+    T getPropertyValue(const ConfigNode &node, bool *isDefault = NULL) const {
         string name = getName();
         string value = node.readProperty(name);
         istringstream in(value);
@@ -477,6 +545,7 @@ struct ConfigPasswordKey {
     /** the network port */
     unsigned int port;
 };
+
 /**
  * This interface has to be provided by the user of the config
  * to let the config code interact with the user.
@@ -524,8 +593,9 @@ class PasswordConfigProperty : public ConfigProperty {
     virtual void checkPassword(ConfigUserInterface &ui,
                                const string &serverName,
                                FilterConfigNode &globalConfigNode,
-                               const string &sourceName,
-                               const boost::shared_ptr<FilterConfigNode> &sourceConfigNode) const;
+                               const string &sourceName = "",
+                               const boost::shared_ptr<FilterConfigNode> &sourceConfigNode =
+                               boost::shared_ptr<FilterConfigNode>()) const;
 
     /**
      * It firstly check password and then invoke ui's savePassword
@@ -534,8 +604,9 @@ class PasswordConfigProperty : public ConfigProperty {
     virtual void savePassword(ConfigUserInterface &ui,
                               const string &serverName,
                               FilterConfigNode &globalConfigNode,
-                              const string &sourceName,
-                              const boost::shared_ptr<FilterConfigNode> &sourceConfigNode) const;
+                              const string &sourceName = "",
+                              const boost::shared_ptr<FilterConfigNode> &sourceConfigNode =
+                              boost::shared_ptr<FilterConfigNode>()) const;
 
     /**
      * Get password key for storing or retrieving passwords
@@ -548,12 +619,13 @@ class PasswordConfigProperty : public ConfigProperty {
                                              const string &serverName,
                                              FilterConfigNode &globalConfigNode,
                                              const string &sourceName = string(),
-                                             const boost::shared_ptr<FilterConfigNode> &sourceConfigNode=boost::shared_ptr<FilterConfigNode>()) const; 
+                                             const boost::shared_ptr<FilterConfigNode> &sourceConfigNode =
+                                             boost::shared_ptr<FilterConfigNode>()) const; 
 
     /**
      * return the cached value if necessary and possible
      */
-    virtual string getCachedProperty(ConfigNode &node,
+    virtual string getCachedProperty(const ConfigNode &node,
                                      const string &cachedPassword);
 };
 
@@ -625,7 +697,7 @@ class BoolConfigProperty : public StringConfigProperty {
     void setProperty(FilterConfigNode &node, bool value, bool temporarily = false) {
         StringConfigProperty::setProperty(node, value ? "1" : "0", temporarily);
     }
-    int getProperty(ConfigNode &node, bool *isDefault = NULL) {
+    int getPropertyValue(const ConfigNode &node, bool *isDefault = NULL) const {
         string res = ConfigProperty::getProperty(node, isDefault);
 
         return boost::iequals(res, "T") ||
@@ -635,6 +707,25 @@ class BoolConfigProperty : public StringConfigProperty {
 };
 
 /**
+ * A property for arbitrary strings.
+ */
+class SafeConfigProperty : public ConfigProperty {
+ public:
+    SafeConfigProperty(const string &name, const string &comment) :
+    ConfigProperty(name, comment)
+    {}
+
+    void setProperty(ConfigNode &node, const string &value) {
+        ConfigProperty::setProperty(node, SafeConfigNode::escape(value, true, false));
+    }
+    virtual string getProperty(const ConfigNode &node, bool *isDefault = NULL) const {
+        string res = ConfigProperty::getProperty(node, isDefault);
+        res = SafeConfigNode::unescape(res);
+        return res;
+    }
+};
+
+/**
  * A registry for all properties which might be saved in the same ConfigNode.
  * Currently the same as a simple list. Someone else owns the instances.
  */
@@ -717,13 +808,24 @@ class SyncConfig {
      * places. Will succeed even if config does not
      * yet exist: flushing such a config creates it.
      *
+     * @param peer   string that identifies the peer,
+     *               matching regex (.*)(@([^@]*))? 
+     *               where the $1 (the first part) is 
+     *               the peer name and the optional $2
+     *               (the part after the last @) is the
+     *               context, "default" if not given.
+     *               For example "scheduleworld" =
+     *               "ScheduleWorld" =
+     *               "scheduleworld@default", but not the same as
+     *               "scheduleworld@other_context"
+     *
      * @param tree   if non-NULL, then this is used
      *               as configuration tree instead of
      *               searching for it; always uses the
      *               current layout in that tree
      */
-    SyncConfig(const string &server,
-                        boost::shared_ptr<ConfigTree> tree = boost::shared_ptr<ConfigTree>());
+    SyncConfig(const string &peer,
+               boost::shared_ptr<ConfigTree> tree = boost::shared_ptr<ConfigTree>());
 
     /**
      * Creates a temporary configuration.
@@ -753,9 +855,10 @@ class SyncConfig {
      * 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)
      * @return NULL if no such template
      */
-    static boost::shared_ptr<SyncConfig> createServerTemplate(const string &server);
+    static boost::shared_ptr<SyncConfig> createServerTemplate(const string &peer);
 
     /** true if the main configuration file already exists */
     bool exists() const;
@@ -770,14 +873,16 @@ class SyncConfig {
     void flush();
 
     /**
-     * Remove the configuration. The config object itself is still
-     * valid afterwards, but empty and cannot be flushed.
+     * Remove the configuration. Config directories are removed if
+     * empty.
+     *
+     * When the configuration is peer-specific, only the peer's
+     * properties and config nodes are removed. Otherwise the complete
+     * configuration is removed, including all peers.
      *
      * Does *not* remove logs associated with the configuration.
      * For that use the logdir handling in SyncContext
      * before removing the configuration.
-     *
-     * The config directory is removed if it is empty.
      */
     void remove();
 
@@ -787,34 +892,63 @@ class SyncConfig {
     static ConfigPropertyRegistry &getRegistry();
 
     /**
+     * Normalize a config string:
+     * - lower case
+     * - @default stripped
+     * - empty string replaced with "@default"
+     */
+    static string normalizeConfigString(const string &config);
+
+    /**
+     * Normalize and in addition, set original context.
+     *
+     * @param config      one of the various ways of selecting a configuration
+     *                    (@default, scheduleworld, scheduleworld@foo, ...)
+     * @retval normal     normalized form of config string       
+     * @retval context    empty if no specified, otherwise normalized value
+     */
+    static void normalizeConfigString(const string &config, string &normal, string &context);
+
+    /**
+     * Split a config string (normalized or not) into the peer part
+     * (before final @) and the context (after that @, not including
+     * it), return "default" as context if not specified otherwise.
+     */
+    static void splitConfigString(const string &config, string &peer, string &context);
+
+    /**
      * Replaces the property filter of either the sync properties or
      * all sources. This can be used to e.g. temporarily override
      * the active sync mode.
+     *
+     * @param sync     true if the filter applies to sync properties,
+     *                 false if it applies to sources
+     * @param source   empty string if filter applies to all sources,
+     *                 otherwise the source name to which it applies
+     * @param filter   key (case insensitive)/value pairs of properties
+     *                 which are to be overridden
      */
-    virtual void setConfigFilter(bool sync, const FilterConfigNode::ConfigFilter &filter) {
-        if (sync) {
-            m_configNode->setFilter(filter);
-        } else {
-            m_sourceFilter = filter;
-        }
-    }
-
-    
+    void setConfigFilter(bool sync,
+                         const std::string &source,
+                         const FilterConfigNode::ConfigFilter &filter);
 
     /**
      * Read-write access to all configurable properties of the server.
      * The visible properties are passed through the config filter,
      * which can be modified.
      */
-    virtual boost::shared_ptr<FilterConfigNode> getProperties(bool hidden = false) {
-        if (hidden) {
-            return boost::shared_ptr<FilterConfigNode>(new FilterConfigNode(m_hiddenNode));
-        } else {
-            return m_configNode;
-        }
-    }
-    virtual boost::shared_ptr<const FilterConfigNode> getProperties(bool hidden = false) const { return const_cast<SyncConfig *>(this)->getProperties(hidden); }
+    boost::shared_ptr<FilterConfigNode> getProperties(bool hidden = false) { return m_props[hidden]; }
+    boost::shared_ptr<const FilterConfigNode> getProperties(bool hidden = false) const { return const_cast<SyncConfig *>(this)->getProperties(hidden); }
 
+    /**
+     * Returns the right config node for a certain property,
+     * depending on visibility and sharing.
+     */
+    boost::shared_ptr<FilterConfigNode> getNode(const ConfigProperty &prop);
+    boost::shared_ptr<const FilterConfigNode> getNode(const ConfigProperty &prop) const 
+    {
+        return const_cast<SyncConfig *>(this)->getNode(prop);
+    }
 
     /**
      * Returns a wrapper around all properties of the given source
@@ -862,6 +996,30 @@ class SyncConfig {
     void setSourceDefaults(const string &name, bool force = true);
 
     /**
+     * Remove sync source configuration. And remove the directory
+     * if it has no other files.
+     *
+     * When the configuration is peer-specific, only the peer's
+     * properties are removed. Otherwise the complete source
+     * configuration is removed, including properties stored
+     * for in any of the peers.
+     */
+    void removeSyncSource(const string &name);
+
+    /**
+     * clear existing visible source properties selected by the
+     * configuration: with or without peer-specific properties,
+     * depending on the current view
+     */
+    void clearSyncSourceProperties(const string &name);
+
+    /**
+     * clear all global sync properties, with or without
+     * peer-specific properties, depending on the current view
+     */
+    void clearSyncProperties();
+
+    /**
      * Copy all registered properties (hidden and visible) and the
      * tracking node into the current config. This is done by reading
      * all properties from the source config, which implies the unset
@@ -887,6 +1045,9 @@ class SyncConfig {
      */
     /**@{*/
 
+    virtual string getDefaultPeer() const;
+    virtual void setDefaultPeer(const string &value);
+
     virtual const char *getLogDir() const;
     virtual void setLogDir(const string &value, bool temporarily = false);
 
@@ -973,6 +1134,14 @@ class SyncConfig {
     virtual void setMaxObjSize(unsigned int value, bool temporarily = false);
     virtual unsigned long getReadBufferSize() const { return 0; }
     virtual const char* getSSLServerCertificates() const;
+
+    /**
+     * iterate over files mentioned in getSSLServerCertificates()
+     * and return name of first one which is found, empty string
+     * if none
+     */
+    std::string findSSLServerCertificate();
+
     virtual void setSSLServerCertificates(const string &value, bool temporarily = false);
     virtual bool getSSLVerifyServer() const;
     virtual void setSSLVerifyServer(bool value, bool temporarily = false);
@@ -988,6 +1157,33 @@ class SyncConfig {
     virtual const char*  getDevID() const;
     virtual void setDevID(const string &value, bool temporarily = false);
 
+    /*Used for Server Alerted Sync*/
+    virtual const char*  getRemoteIdentifier() const;
+    virtual void setRemoteIdentifier (const string &value, bool temporaritly = false);
+    virtual bool getPeerIsClient () const;
+    virtual void setPeerIsClient (bool value, bool temporarily = false);
+    /**
+     * The Device ID of our peer. Typically only relevant when the
+     * peer is a client. Servers don't have a Device ID, just some
+     * unique way of contacting them.
+     */
+    virtual string getRemoteDevID() const;
+    virtual void setRemoteDevID(const string &value);
+
+    /**
+     * The opaque nonce value stored for a peer, required for MD5
+     * authentication. Only used when acting as server.
+     */
+    virtual string getNonce() const;
+    virtual void setNonce(const string &value);
+
+    /**
+     * The opaque per-peer admin data managed by the Synthesis
+     * engine. Only used when acting as server.
+     */
+    virtual string getDeviceData() const;
+    virtual void setDeviceData(const string &value);
+
     /**
      * Specifies whether WBXML is to be used (default).
      * Otherwise XML is used.
@@ -1002,27 +1198,88 @@ class SyncConfig {
     virtual const char*  getHwv() const { return "unknown"; }
     virtual const char*  getSwv() const;
     virtual const char*  getDevType() const;
-
-    FilterConfigNode& getConfigNode() { return *m_configNode; }
-
     /**@}*/
 
 private:
-    string m_server;
-    bool m_oldLayout;
+    enum Layout {
+        SYNC4J_LAYOUT,        /**< .syncj4/evolution/<server>, SyncEvolution <= 0.7.x */
+        HTTP_SERVER_LAYOUT,   /**< .config/syncevolution/<server> with sources
+                                 underneath, SyncEvolution <= 0.9.x */
+        SHARED_LAYOUT         /**< .config/syncevolution/<context> containing sources 
+                                 and peers, with source settings shared by peers,
+                                 SyncEvolution >= 1.0 */
+    };
+
+    /**
+     * scans for peer configurations
+     * @param root         absolute directory path
+     * @param configname   expected name of config files (config.ini or config.txt)
+     * @retval res         filled with new peer configurations found
+     */
+    static void addPeers(const string &root,
+                         const std::string &configname,
+                         SyncConfig::ServerList &res);
+
+    /**
+     * set tree and nodes to VolatileConfigTree/Node
+     */
+    void makeVolatile();
+
+    /**
+     * String that identifies the peer, see constructor.
+     * This is a normalized string (normalizePeerString()).
+     */
+    string m_peer;
+
+    /**
+     * Lower case path to peer configuration,
+     * relative to configuration tree root.
+     * For example "scheduleworld" for "ScheduleWorld" when
+     * using the old config layouts, "default/peers/scheduleworld"
+     * in the new layout.
+     *
+     * Empty if configuration view has no peer-specific properties.
+     */
+    string m_peerPath;
+
+    /**
+     * lower case path to source set properties,
+     * unused for old layouts, else something like
+     * "default" or "other_context"
+     */
+    string m_contextPath;
+
+    Layout m_layout;
     string m_cachedPassword;
     string m_cachedProxyPassword;
 
     /** holds all config nodes relative to the root that we found */
     boost::shared_ptr<ConfigTree> m_tree;
 
-    /** access to global sync properties */
-    boost::shared_ptr<FilterConfigNode> m_configNode;
-    boost::shared_ptr<ConfigNode> m_hiddenNode;
+    /** access to global sync properties, independent of
+        the context (for example, "defaultPeer") */
+    boost::shared_ptr<FilterConfigNode> m_globalNode;
+        
+    /** access to properties shared between peers */
+    boost::shared_ptr<FilterConfigNode> m_contextNode;
+    boost::shared_ptr<ConfigNode> m_contextHiddenNode;
+
+    /** access to properties specific to a peer */
+    boost::shared_ptr<FilterConfigNode> m_peerNode;
+    boost::shared_ptr<ConfigNode> m_hiddenPeerNode;
+
+    /** multiplexer for the other config nodes */
+    boost::shared_ptr<FilterConfigNode> m_props[2];
 
-    /** temporary overrides for sync or sync source settings */
+    /**
+     * temporary override for all sync source settings
+     */
     FilterConfigNode::ConfigFilter m_sourceFilter;
 
+    /** temporary override for settings of specific sources */
+    typedef std::map<std::string, FilterConfigNode::ConfigFilter> SourceFilters_t;
+    SourceFilters_t m_sourceFilters;
+
     mutable ConfigStringCache m_stringCache;
 
     static string getOldRoot() {
@@ -1038,47 +1295,80 @@ private:
 
 /**
  * This set of config nodes is to be used by SyncSourceConfig
- * to accesss properties.
+ * to accesss properties. Note that "const SyncSourceNodes"
+ * only implies that the nodes cannot be changed; the properties
+ * are still read- and writable. ConstSyncSourceNodes grants
+ * only read access to properties.
  */
-struct SyncSourceNodes {
-    /**
-     * @param configNode    node for user-visible properties
-     * @param hiddenNode    node for internal properties (may be the same as
-     *                      configNode in old config layouts!)
-     * @param trackingNode  node for tracking changes (always different than the
-     *                      other two nodes)
-     */
-    SyncSourceNodes(const boost::shared_ptr<FilterConfigNode> &configNode,
-                    const boost::shared_ptr<ConfigNode> &hiddenNode,
-                    const boost::shared_ptr<ConfigNode> &trackingNode) : 
-    m_configNode(configNode),
-        m_hiddenNode(hiddenNode),
-        m_trackingNode(trackingNode)
-    {}
+class SyncSourceNodes {
+ public:
+    SyncSourceNodes() {}
 
-    const boost::shared_ptr<FilterConfigNode> m_configNode;
-    const boost::shared_ptr<ConfigNode> m_hiddenNode;
+    /**
+     * @param sharedNode      node for user-visible properties, shared between peers
+     * @param peerNode        node for user-visible, per-peer properties (the same
+     *                        as sharedNode in SYNC4J_LAYOUT and HTTP_SERVER_LAYOUT)
+     * @param hiddenPeerNode  node for internal, per-peer properties (the same as
+     *                        sharedNode in SYNC4J_LAYOUT)
+     * @param trackingNode    node for tracking changes (always different than the
+     *                        other nodes)
+     * @param serverNode      node for tracking items in a server (always different
+     *                        than the other nodes)
+     */
+    SyncSourceNodes(const boost::shared_ptr<FilterConfigNode> &sharedNode,
+                    const boost::shared_ptr<FilterConfigNode> &peerNode,
+                    const boost::shared_ptr<ConfigNode> &hiddenPeerNode,
+                    const boost::shared_ptr<ConfigNode> &trackingNode,
+                    const boost::shared_ptr<ConfigNode> &serverNode);
+
+    /** true if the peer-specific config node exists */
+    bool exists() const { return m_peerNode->exists(); }
+
+    /**
+     * Returns the right config node for a certain property,
+     * depending on visibility and sharing.
+     */
+    boost::shared_ptr<FilterConfigNode> getNode(const ConfigProperty &prop) const;
+
+    /**
+     * Read-write access to all configurable properties of the source.
+     * The visible properties are passed through the config filter,
+     * which can be modified.
+     */
+    boost::shared_ptr<FilterConfigNode> getProperties(bool hidden = false) const { return m_props[hidden]; }
+
+    /** read-write access to SyncML server specific config node */
+    boost::shared_ptr<ConfigNode> getServerNode() const { return m_serverNode; }
+
+    /** read-write access to backend specific tracking node */
+    boost::shared_ptr<ConfigNode> getTrackingNode() const { return m_trackingNode; }
+
+ protected:
+    const boost::shared_ptr<FilterConfigNode> m_sharedNode;
+    const boost::shared_ptr<FilterConfigNode> m_peerNode;
+    const boost::shared_ptr<ConfigNode> m_hiddenPeerNode;
     const boost::shared_ptr<ConfigNode> m_trackingNode;
-};
+    const boost::shared_ptr<ConfigNode> m_serverNode;
 
-struct ConstSyncSourceNodes {
-    ConstSyncSourceNodes(const boost::shared_ptr<const FilterConfigNode> &configNode,
-                         const boost::shared_ptr<const ConfigNode> &hiddenNode,
-                         const boost::shared_ptr<const ConfigNode> &trackingNode) : 
-    m_configNode(configNode),
-        m_hiddenNode(hiddenNode),
-        m_trackingNode(trackingNode)
-    {}
+    /** multiplexer for the other nodes */
+    boost::shared_ptr<FilterConfigNode> m_props[2];
+};
 
+/**
+ * same as SyncSourceNodes, but with only read access to properties
+ */
+class ConstSyncSourceNodes : private SyncSourceNodes
+{
+ public:
     ConstSyncSourceNodes(const SyncSourceNodes &other) :
-    m_configNode(other.m_configNode),
-        m_hiddenNode(other.m_hiddenNode),
-        m_trackingNode(other.m_trackingNode)
+       SyncSourceNodes(other)
     {}
 
-    const boost::shared_ptr<const FilterConfigNode> m_configNode;
-    const boost::shared_ptr<const ConfigNode> m_hiddenNode;
-    const boost::shared_ptr<const ConfigNode> m_trackingNode;
+    boost::shared_ptr<const FilterConfigNode> getProperties(bool hidden = false) const {
+        return const_cast<SyncSourceNodes *>(static_cast<const SyncSourceNodes *>(this))->getProperties(hidden);
+    }
+    boost::shared_ptr<const ConfigNode> getServerNode() const { return m_serverNode; }
+    boost::shared_ptr<const ConfigNode> getTrackingNode() const { return m_trackingNode; } 
 };
 
 struct SourceType {
@@ -1100,23 +1390,48 @@ class SyncSourceConfig {
 
     static ConfigPropertyRegistry &getRegistry();
 
+    /**
+     * Read-write access to all configurable properties of the source.
+     * The visible properties are passed through the config filter,
+     * which can be modified.
+     */
+    boost::shared_ptr<FilterConfigNode> getProperties(bool hidden = false) {
+        return m_nodes.getProperties(hidden);
+    }
+    boost::shared_ptr<const FilterConfigNode> getProperties(bool hidden = false) const { return const_cast<SyncSourceConfig *>(this)->getProperties(hidden); }
+
+    virtual const char*  getName() const { return m_name.c_str(); }
+
+    /**
+     * Returns the right config node for a certain property,
+     * depending on visibility and sharing.
+     */
+    boost::shared_ptr<FilterConfigNode> getNode(const ConfigProperty &prop) {
+        return m_nodes.getNode(prop);
+    }
+    boost::shared_ptr<const FilterConfigNode> getNode(const ConfigProperty &prop) const {
+        return m_nodes.getNode(prop);
+    }
+
+    /** access to SyncML server specific config node */
+    boost::shared_ptr<ConfigNode> getServerNode() { return m_nodes.getServerNode(); }
+    boost::shared_ptr<const ConfigNode> getServerNode() const { return m_nodes.getServerNode(); }
+
+    /** access to backend specific tracking node */
+    boost::shared_ptr<ConfigNode> getTrackingNode() { return m_nodes.getTrackingNode(); }
+    boost::shared_ptr<const ConfigNode> getTrackingNode() const { return m_nodes.getTrackingNode(); }
+
     /** sync mode for sync sources */
     static StringConfigProperty m_sourcePropSync;
 
-    bool exists() const { return m_nodes.m_configNode->exists(); }
+    /** true if the source config exists with view-specific properties (not just default or shared ones) */
+    bool exists() const { return m_nodes.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);
+        return prop.isSet(*getProperties(prop.isHidden()));
     }
 
-    /**
-     * @name Settings specific to SyncEvolution SyncSources
-     */
-    /**@{*/
-
     virtual const char *getUser() const;
     virtual void setUser(const string &value, bool temporarily = false);
 
@@ -1152,14 +1467,6 @@ class SyncSourceConfig {
     /** set the source type in <backend>[:format] style */
     virtual void setSourceType(const string &value, bool temporarily = false);
 
-
-    /**@}*/
-
-    /**
-     * @name Calls which usually do not have to be implemented by each SyncSource.
-     */
-    /**@{*/
-
     /**
      * Returns the SyncSource URI: used in SyncML to address the data
      * on the server.
@@ -1185,49 +1492,6 @@ class SyncSourceConfig {
      */
     virtual const char*  getSync() const;
     virtual void setSync(const string &value, bool temporarily = false);
-    
-    /**
-     * Sets the last sync timestamp. Called by the sync engine at
-     * the end of a sync. The client must save that modified
-     * value; it is needed to decide during the next sync whether
-     * an incremental sync is possible.
-     *
-     * SyncEvolution will reset this value when a SyncSource fails
-     * and thus force a slow sync during the next sync.
-     *
-     * @param timestamp the last sync timestamp
-     */
-    virtual unsigned long getLast() const;
-    virtual void setLast(unsigned long timestamp);
-
-    /**
-     * "des" enables an encryption mode which only the Funambol server
-     * understands. Not configurable in SyncEvolution unless a derived
-     * SyncSource decides otherwise.
-     */
-    virtual const char* getEncryption() const { return ""; }
-
-    /**
-     * Returns an array of CtCap with all the capabilities for this
-     * source.  The capabilities specify which parts of e.g. a vCard
-     * the sync source supports. Not specifying this in detail by
-     * returning an empty array implies that it supports all aspects.
-     * This is the default implementation of this call.
-     *
-     * @TODO: per-source capabilities
-     */
-    // virtual const ArrayList& getCtCaps() const { static const ArrayList dummy; return dummy; }
-
-    /**@}*/
-
-    /**
-     * @name Calls implemented by SyncEvolution.
-     */
-    /**@{*/
-    virtual const char*  getName() const { return m_name.c_str(); }
-
-    virtual SyncSourceNodes& getSyncSourceNodes() { return m_nodes; }
-    /**@}*/
 
  private:
     string m_name;
index 499f54b..71fe604 100644 (file)
@@ -34,6 +34,7 @@
 #include <syncevo/TransportAgent.h>
 #include <syncevo/CurlTransportAgent.h>
 #include <syncevo/SoupTransportAgent.h>
+#include <syncevo/ObexTransportAgent.h>
 
 #include <list>
 #include <memory>
@@ -63,54 +64,91 @@ using namespace std;
 
 #include <synthesis/enginemodulebridge.h>
 #include <synthesis/SDK_util.h>
+#include <synthesis/san.h>
 
 #include <syncevo/declarations.h>
 SE_BEGIN_CXX
 
 SourceList *SyncContext::m_sourceListPtr;
-
+SyncContext *SyncContext::m_activeContext;
 SuspendFlags SyncContext::s_flags;
 
-extern "C" void suspend_handler(int sig)
+static const char *LogfileBasename = "syncevolution-log";
+
+void SyncContext::handleSignal(int sig)
 {
-  time_t current;
-  time (&current);
-  SuspendFlags& s_flags = SyncContext::getSuspendFlags();
-  //first time suspend or already aborted
-  if (s_flags.state == SuspendFlags::CLIENT_NORMAL)
-  {
-      s_flags.state = SuspendFlags::CLIENT_SUSPEND;
-      s_flags.last_suspend = current;
-      SE_LOG_INFO(NULL, NULL,"Asking server to suspend...\nPress CTRL-C again quickly (within 2s) to stop sync immediately (can cause problems during next sync!)");
-      return;
-  }
-  else 
-  {
-      if (current - s_flags.last_suspend
-              < s_flags.ABORT_INTERVAL) 
-      {
-          s_flags.state = SuspendFlags::CLIENT_ABORT;
-          SE_LOG_INFO(NULL, NULL, "Aborting sync as requested via CTRL-C ...");
-      }
-      else
-      {
-          s_flags.last_suspend = current;
-          SE_LOG_INFO(NULL, NULL, "Suspend in progress...\nPress CTRL-C again quickly (within 2s) to stop sync immediately (can cause problems during next sync!)");
-      }
-  }
+    switch (sig) {
+    case SIGTERM:
+        switch (s_flags.state) {
+        case SuspendFlags::CLIENT_ABORT:
+            s_flags.message = "Already aborting sync as requested earlier ...";
+            break;
+        default:
+            s_flags.state = SuspendFlags::CLIENT_ABORT;
+            s_flags.message = "Aborting sync immediately via SIGTERM ...";
+            break;
+        }
+        break;
+    case SIGINT: {
+        time_t current;
+        time (&current);
+        switch (s_flags.state) {
+        case SuspendFlags::CLIENT_NORMAL:
+            // first time suspend or already aborted
+            s_flags.state = SuspendFlags::CLIENT_SUSPEND;
+            s_flags.message = "Asking server to suspend...\nPress CTRL-C again quickly (within 2s) to stop sync immediately (can cause problems during next sync!)";
+            s_flags.last_suspend = current;
+            break;
+        case SuspendFlags::CLIENT_SUSPEND:
+            // turn into abort?
+            if (current - s_flags.last_suspend
+                < s_flags.ABORT_INTERVAL) {
+                s_flags.state = SuspendFlags::CLIENT_ABORT;
+                s_flags.message = "Aborting sync as requested via CTRL-C ...";
+            } else {
+                s_flags.last_suspend = current;
+                s_flags.message = "Suspend in progress...\nPress CTRL-C again quickly (within 2s) to stop sync immediately (can cause problems during next sync!)";
+            }
+            break;
+        case SuspendFlags::CLIENT_ABORT:
+            s_flags.message = "Already aborting sync as requested earlier ...";
+            break;
+        case SuspendFlags::CLIENT_ILLEGAL:
+            break;
+        break;
+        }
+    }
+    }
 }
 
+void SyncContext::printSignals()
+{
+    if (s_flags.message) {
+        SE_LOG_INFO(NULL, NULL, "%s", s_flags.message);
+        s_flags.message = NULL;
+    }
+}
+
+SyncContext::SyncContext()
+{
+    init();
+}
 
 SyncContext::SyncContext(const string &server,
-                                         bool doLogging,
-                                         const set<string> &sources) :
+                         bool doLogging) :
     SyncConfig(server),
-    m_server(server),
-    m_sources(sources),
-    m_doLogging(doLogging),
-    m_quiet(false),
-    m_dryrun(false)
+    m_server(server)
 {
+    init();
+    m_doLogging = doLogging;
+}
+
+void SyncContext::init()
+{
+    m_doLogging = false;
+    m_quiet = false;
+    m_dryrun = false;
+    m_serverMode = false;
 }
 
 SyncContext::~SyncContext()
@@ -307,7 +345,7 @@ public:
                     SyncContext::throwError(m_path, errno);
                 }
             }
-            m_logfile = m_path + "/" + "sysynclib_linux.html";
+            m_logfile = m_path + "/" + LogfileBasename + ".html";
         }
 
         // update log level of default logger and our own replacement
@@ -507,7 +545,9 @@ private:
 
 // this class owns the sync sources and (together with
 // a logdir) handles writing of per-sync files as well
-// as the final report (
+// as the final report 
+// It also handles the virtual syncsources that is a combination of several
+// real syncsources.
 class SourceList : public vector<SyncSource *> {
 public:
     enum LogLevel {
@@ -516,6 +556,7 @@ public:
         LOGGING_FULL      /**< everything */
     };
 
+    std::vector<boost::shared_ptr<VirtualSyncSource> >m_virtualDS; /**All configured virtual datastores*/
 private:
     LogDir m_logdir;     /**< our logging directory */
     bool m_prepared;     /**< remember whether syncPrepare() dumped databases successfully */
@@ -803,15 +844,29 @@ string SyncContext::askPassword(const string &passwordName, const string &descr,
 
 boost::shared_ptr<TransportAgent> SyncContext::createTransportAgent()
 {
+    std::string url = getSyncURL();
+    if (boost::starts_with(url, "http://") ||
+        boost::starts_with(url, "https://")) {
 #ifdef ENABLE_LIBSOUP
-    boost::shared_ptr<SoupTransportAgent> agent(new SoupTransportAgent());
+        boost::shared_ptr<SoupTransportAgent> agent(new SoupTransportAgent());
+        agent->setConfig(*this);
+        return agent;
 #elif defined(ENABLE_LIBCURL)
-    boost::shared_ptr<CurlTransportAgent> agent(new CurlTransportAgent());
-#else
-    boost::shared_ptr<TransportAgent> agent;
-    throw std::string("libsyncevolution was compiled without default transport, client must implement SyncContext::createTransportAgent()");
+        boost::shared_ptr<CurlTransportAgent> agent(new CurlTransportAgent());
+        agent->setConfig(*this);
+        return agent;
+#endif
+    } else if (url.find("obex-bt://") ==0) {
+#ifdef ENABLE_BLUETOOTH
+        std::string btUrl = url.substr (strlen ("obex-bt://"), std::string::npos);
+        boost::shared_ptr<ObexTransportAgent> agent(new ObexTransportAgent(ObexTransportAgent::OBEX_BLUETOOTH));
+        agent->setURL (btUrl);
+        agent->connect();
+        return agent;
 #endif
-    return agent;
+    }
+
+    SE_THROW("unsupported transport type is specified in the configuration");
 }
 
 void SyncContext::displayServerMessage(const string &message)
@@ -833,7 +888,9 @@ void SyncContext::displaySourceProgress(sysync::TProgressEventEnum type,
     case sysync::PEV_PREPARING:
         /* preparing (e.g. preflight in some clients), extra1=progress, extra2=total */
         /* extra2 might be zero */
-        if (extra2) {
+        if (source.getFinalSyncMode() == SYNC_NONE) {
+            // not active, suppress output
+        } else if (extra2) {
             SE_LOG_INFO(NULL, NULL, "%s: preparing %d/%d",
                         source.getName(), extra1, extra2);
         } else {
@@ -910,7 +967,8 @@ void SyncContext::displaySourceProgress(sysync::TProgressEventEnum type,
     case sysync::PEV_ITEMRECEIVED:
         /* item received, extra1=current item count,
            extra2=number of expected changes (if >= 0) */
-        if (extra2 > 0) {
+        if (source.getFinalSyncMode() == SYNC_NONE) {
+        } else if (extra2 > 0) {
             SE_LOG_INFO(NULL, NULL, "%s: received %d/%d",
                         source.getName(), extra1, extra2);
         } else {
@@ -921,7 +979,8 @@ void SyncContext::displaySourceProgress(sysync::TProgressEventEnum type,
     case sysync::PEV_ITEMSENT:
         /* item sent,     extra1=current item count,
            extra2=number of expected items to be sent (if >=0) */
-        if (extra2 > 0) {
+        if (source.getFinalSyncMode() == SYNC_NONE) {
+        } else if (extra2 > 0) {
             SE_LOG_INFO(NULL, NULL, "%s: sent %d/%d",
                      source.getName(), extra1, extra2);
         } else {
@@ -933,21 +992,28 @@ void SyncContext::displaySourceProgress(sysync::TProgressEventEnum type,
         /* item locally processed,               extra1=# added, 
            extra2=# updated,
            extra3=# deleted */
-        SE_LOG_INFO(NULL, NULL, "%s: added %d, updated %d, removed %d",
-                 source.getName(), extra1, extra2, extra3);
+        if (source.getFinalSyncMode() == SYNC_NONE) {
+        } else if (source.getFinalSyncMode() != SYNC_NONE) {
+            SE_LOG_INFO(NULL, NULL, "%s: added %d, updated %d, removed %d",
+                        source.getName(), extra1, extra2, extra3);
+        }
         break;
     case sysync::PEV_SYNCEND:
         /* sync finished, probably with error in extra1 (0=ok),
            syncmode in extra2 (0=normal, 1=slow, 2=first time), 
            extra3=1 for resumed session) */
-        SE_LOG_INFO(NULL, NULL, "%s: %s%s sync done %s",
-                 source.getName(),
-                 extra3 ? "resumed " : "",
-                 extra2 == 0 ? "normal" :
-                 extra2 == 1 ? "slow" :
-                 extra2 == 2 ? "first time" :
-                 "unknown",
-                 extra1 ? "unsuccessfully" : "successfully");
+        if (source.getFinalSyncMode() == SYNC_NONE) {
+            SE_LOG_INFO(NULL, NULL, "%s: inactive", source.getName());
+        } else {
+            SE_LOG_INFO(NULL, NULL, "%s: %s%s sync done %s",
+                        source.getName(),
+                        extra3 ? "resumed " : "",
+                        extra2 == 0 ? "normal" :
+                        extra2 == 1 ? "slow" :
+                        extra2 == 2 ? "first time" :
+                        "unknown",
+                        extra1 ? "unsuccessfully" : "successfully");
+        }
         switch (extra1) {
         case 401:
             // TODO: reset cached password
@@ -1141,73 +1207,63 @@ SyncSource *SyncContext::findSource(const char *name)
     return m_sourceListPtr ? (*m_sourceListPtr)[name] : NULL;
 }
 
-void SyncContext::setConfigFilter(bool sync, const FilterConfigNode::ConfigFilter &filter)
+SyncContext *SyncContext::findContext(const char *sessionName)
 {
-    map<string, string>::const_iterator hasSync = filter.find(SyncSourceConfig::m_sourcePropSync.getName());
-
-    if (!sync && hasSync != filter.end()) {
-        m_overrideMode = hasSync->second;
-        FilterConfigNode::ConfigFilter strippedFilter = filter;
-        strippedFilter.erase(SyncSourceConfig::m_sourcePropSync.getName());
-        SyncConfig::setConfigFilter(sync, strippedFilter);
-    } else {
-        SyncConfig::setConfigFilter(sync, filter);
-    }
+    return m_activeContext;
 }
 
 void SyncContext::initSources(SourceList &sourceList)
 {
-    set<string> unmatchedSources = m_sources;
     list<string> configuredSources = getSyncSources();
     BOOST_FOREACH(const string &name, configuredSources) {
         boost::shared_ptr<PersistentSyncSourceConfig> sc(getSyncSourceConfig(name));
-        
+
+        SyncSourceNodes source = getSyncSourceNodes (name);
+        SourceType sourceType = SyncSource::getSourceType(source);
+
         // is the source enabled?
         string sync = sc->getSync();
         bool enabled = sync != "disabled";
-        string overrideMode = m_overrideMode;
-
-        // override state?
-        if (m_sources.size()) {
-            if (m_sources.find(sc->getName()) != m_sources.end()) {
-                if (!enabled) {
-                    if (overrideMode.empty()) {
-                        overrideMode = "two-way";
-                    }
-                    enabled = true;
-                }
-                unmatchedSources.erase(sc->getName());
-            } else {
-                enabled = false;
-            }
-        }
-        
         if (enabled) {
-            string url = getSyncURL();
-            boost::replace_first(url, "https://", "http://"); // do not distinguish between protocol in change tracking
-            string changeId = string("sync4jevolution:") + url + "/" + name;
-            SyncSourceParams params(name,
-                                    getSyncSourceNodes(name),
-                                    changeId);
-            // the sync mode has to be set before instantiating the source
-            // because the client library reads the preferredSyncMode at that time
-            if (!overrideMode.empty()) {
-                params.m_nodes.m_configNode->addFilter(SyncSourceConfig::m_sourcePropSync.getName(),
-                                                       overrideMode);
-            }
-            SyncSource *syncSource =
-                SyncSource::createSource(params);
-            if (!syncSource) {
-                throwError(name + ": type unknown" );
+            if (sourceType.m_backend == "virtual") {
+                //This is a virtual sync source 
+                SyncSourceParams params(name, source);
+                sourceList.m_virtualDS.push_back (
+                        boost::shared_ptr<VirtualSyncSource> (new VirtualSyncSource (params)));
+            } else {
+                string url = getSyncURL();
+                SyncSourceParams params(name,
+                        source);
+                SyncSource *syncSource =
+                    SyncSource::createSource(params);
+                if (!syncSource) {
+                    throwError(name + ": type unknown" );
+                }
+                sourceList.push_back(syncSource);
             }
-            sourceList.push_back(syncSource);
+        } else {
+            // the Synthesis engine is never going to see this source,
+            // therefore we have to mark it as 100% complete and
+            // "done"
+            class DummySyncSource source(name);
+            source.recordFinalSyncMode(SYNC_NONE);
+            displaySourceProgress(sysync::PEV_PREPARING,
+                                  source,
+                                  0, 0, 0);
+            displaySourceProgress(sysync::PEV_ITEMPROCESSED,
+                                  source,
+                                  0, 0, 0);
+            displaySourceProgress(sysync::PEV_ITEMRECEIVED,
+                                  source,
+                                  0, 0, 0);
+            displaySourceProgress(sysync::PEV_ITEMSENT,
+                                  source,
+                                  0, 0, 0);
+            displaySourceProgress(sysync::PEV_SYNCEND,
+                                  source,
+                                  0, 0, 0);
         }
     }
-
-    // check whether there were any sources specified which do not exist
-    if (unmatchedSources.size()) {
-        throwError(string("no such source(s): ") + boost::join(unmatchedSources, " "));
-    }
 }
 
 bool SyncContext::transport_cb (void *udata)
@@ -1217,6 +1273,10 @@ bool SyncContext::transport_cb (void *udata)
 
 bool SyncContext::processTransportCb()
 {
+    // TODO: distinguish between client and server. In the server
+    // we have to implement a much higher time out and then disconnect
+    // an unresponsive client.
+
     //Always return true to continue, we will detect the retry count at
     //the higher level together with transport error scenarios.
     SE_LOG_INFO(NULL, NULL, "Transport timeout after %d:%02dmin",
@@ -1310,6 +1370,48 @@ void SyncContext::getConfigXML(string &xml, string &configname)
     size_t index;
     unsigned long hash = 0;
 
+    substTag(xml,
+             "clientorserver",
+             m_serverMode ?
+             "  <server type='plugin'>\n"
+             "    <plugin_module>SyncEvolution</plugin_module>\n"
+             "    <plugin_sessionauth>yes</plugin_sessionauth>\n"
+             "    <plugin_deviceadmin>yes</plugin_deviceadmin>\n"
+             "\n"
+             "    <sessioninitscript><![CDATA[\n"
+             "      // these variables are possibly modified by rule scripts\n"
+             "      TIMESTAMP mindate; // earliest date remote party can handle\n"
+             "      INTEGER retransfer_body; // if set to true, body is re-sent to client when message is moved from outbox to sent\n"
+             "      mindate=EMPTY; // no limit by default\n"
+             "      retransfer_body=FALSE; // normally, do not retransfer email body (and attachments) when moving items to sent box\n"
+             "    ]]></sessioninitscript>\n"
+             "    <sessiontimeout>300</sessiontimeout>\n"
+             "\n"
+             "    <defaultauth/>\n"
+             "\n"
+             "    <datastore/>\n"
+             "\n"
+             "    <remoterules/>\n"
+             "  </server>\n"
+             :
+             "  <client type='plugin'>\n"
+             "    <binfilespath>$(binfilepath)</binfilespath>\n"
+             "    <defaultauth/>\n"
+             "\n"
+             // SyncEvolution has traditionally not folded long lines in
+             // vCard.  Testing showed that servers still have problems with
+             // it, so avoid it by default
+             "    <donotfoldcontent>yes</donotfoldcontent>\n"
+             "\n"
+             "    <fakedeviceid/>\n"
+             "\n"
+             "    <datastore/>\n"
+             "\n"
+             "    <remoterules/>\n"
+             "  </client>\n",
+             true
+             );
+
     tag = "<debug/>";
     index = xml.find(tag);
     if (index != xml.npos) {
@@ -1321,6 +1423,8 @@ void SyncContext::getConfigXML(string &xml, string &configname)
             "  <debug>\n"
             // logpath is a config variable set by SyncContext::doSync()
             "    <logpath>$(logpath)</logpath>\n"
+            "    <filename>" <<
+            LogfileBasename << "</filename>" <<
             "    <logflushmode>flush</logflushmode>\n"
             "    <logformat>html</logformat>\n"
             "    <folding>auto</folding>\n"
@@ -1379,6 +1483,59 @@ void SyncContext::getConfigXML(string &xml, string &configname)
                 fragment <<
                 "    </datastore>\n\n";
         }
+
+        /*If there is super datastore, add it here*/
+        //TODO generate specific superdatastore contents
+        //Now only works for synthesis built-in events+tasks 
+        BOOST_FOREACH (boost::shared_ptr<VirtualSyncSource> vSource, m_sourceListPtr->m_virtualDS) {
+            std::string evoSyncSource = vSource->getDatabaseID();
+            bool valid = true;
+            std::vector<std::string> mappedSources = unescapeJoinedString (evoSyncSource, ',');
+            BOOST_FOREACH (std::string source, mappedSources) {
+                //check whether the mapped source is really available
+                if (! (*m_sourceListPtr)[source]) {
+                    SE_LOG_ERROR (NULL, NULL, 
+                            "Virtual datasource %s referenced a non-existed datasource %s, check your configuration!",
+                            vSource->getName(), source.c_str());
+                    valid = false;
+                    break;
+                }
+                //TODO check the format. Must be the same for the superdatastore and all
+                //sub datastores. If not match, warn user.
+           }
+
+            if (!valid) {
+                continue;
+            }
+
+            if (mappedSources.size() !=2) {
+                vSource->throwError ("virtual data source now only supports events+tasks case");
+            } 
+
+            datastores << "    <superdatastore name= '" << vSource->getName() <<"'> \n";
+            datastores << "      <contains datastore = '" << mappedSources[0] <<"'>\n"
+                << "        <dispatchfilter>F.ISEVENT:=1</dispatchfilter>\n"
+                << "        <guidprefix>e</guidprefix>\n"
+                << "      </contains>\n"
+                <<"\n      <contains datastore = '" << mappedSources[1] <<"'>\n"
+                << "        <dispatchfilter>F.ISEVENT:=0</dispatchfilter>\n"
+                << "        <guidprefix>t</guidprefix>\n"
+                <<"      </contains>\n" ;
+
+            std::string typesupport;
+            typesupport = vSource->getDataTypeSupport();
+            if (typesupport.empty()) {
+                //TODO
+                //If the datatype is not set explictly by user, what should
+                //be do?
+                SE_THROW ("datatype format is not set in virtual datasource configuration");
+            } 
+            datastores << "      <typesupport>\n"
+                << typesupport 
+                << "      </typesupport>\n";
+            datastores <<"\n    </superdatastore>";
+        }
+
         if (datastores.str().empty()) {
             // Add dummy datastore, the engine needs it. sync()
             // checks that we have a valid configuration if it is
@@ -1399,9 +1556,16 @@ void SyncContext::getConfigXML(string &xml, string &configname)
     substTag(xml, "fieldlists", fragments.m_fieldlists.join(), true);
     substTag(xml, "profiles", fragments.m_profiles.join(), true);
     substTag(xml, "datatypes", fragments.m_datatypes.join(), true);
-    substTag(xml, "remoterules", fragments.m_remoterules.join(), true);
+    substTag(xml, "remoterules",
+             string("<remoterule name='EVOLUTION'><deviceid>none - this rule is activated via its name in MAKE/PARSETEXTWITHPROFILE() macro calls</deviceid></remoterule>\n") +
+             fragments.m_remoterules.join(),
+             true);
 
-    substTag(xml, "fakedeviceid", getDevID());
+    if (m_serverMode) {
+        // TODO: set the device ID for an OBEX server
+    } else {
+        substTag(xml, "fakedeviceid", getDevID());
+    }
     substTag(xml, "model", getMod());
     substTag(xml, "manufacturer", getMan());
     substTag(xml, "hardwareversion", getHwv());
@@ -1410,7 +1574,29 @@ void SyncContext::getConfigXML(string &xml, string &configname)
     substTag(xml, "devicetype", getDevType());
     substTag(xml, "maxmsgsize", std::max(getMaxMsgSize(), 10000ul));
     substTag(xml, "maxobjsize", std::max(getMaxObjSize(), 1024u));
-    substTag(xml, "defaultauth", getClientAuthType());
+    if (m_serverMode) {
+        const char *user = getUsername();
+        const char *password = getPassword();
+
+        if (user[0] || password[0]) {
+            // require authentication with the configured password
+            substTag(xml, "defaultauth",
+                     "<requestedauth>md5</requestedauth>\n"
+                     "<requiredauth>basic</requiredauth>\n"
+                     "<autononce>yes</autononce>\n",
+                     true);
+        } else {
+            // no authentication required
+            substTag(xml, "defaultauth",
+                     "<logininitscript>return TRUE</logininitscript>\n"
+                     "<requestedauth>none</requestedauth>\n"
+                     "<requiredauth>none</requiredauth>\n"
+                     "<autononce>yes</autononce>\n",
+                     true);
+        }
+    } else {
+        substTag(xml, "defaultauth", getClientAuthType());
+    }
 
     // if the hash code is changed, that means the content of the
     // config has changed, save the new hash and regen the configdate
@@ -1427,25 +1613,32 @@ SharedEngine SyncContext::createEngine()
 {
     SharedEngine engine(new sysync::TEngineModuleBridge);
 
-    // Use libsynthesis that we were linked against.  The name of a
-    // .so could be given here, too, to use that instead.  This
-    // instance of the engine is used outside of the sync session
-    // itself. doSync() then creates another engine for the sync
-    // itself. That is necessary because the engine shutdown depends
-    // on the context of the sync (in particular instantiated sync
-    // sources).
-    engine.Connect("[]", 0,
+    // This instance of the engine is used outside of the sync session
+    // itself for logging. doSync() then reinitializes it with a full
+    // datastore configuration.
+    engine.Connect(m_serverMode ?
+#ifdef ENABLE_SYNCML_LINKED
+                   // use Synthesis client or server engine that we were linked against
+                   "[server:]" : "[]",
+#else
+                   // load engine dynamically
+                   "server:libsynthesis.so.0" : "libsynthesis.so.0",
+#endif
+                   0,
                    sysync::DBG_PLUGIN_NONE|
                    sysync::DBG_PLUGIN_INT|
                    sysync::DBG_PLUGIN_DB|
                    sysync::DBG_PLUGIN_EXOT);
 
     SharedKey configvars = engine.OpenKeyByPath(SharedKey(), "/configvars");
-    string logdir = m_sourceListPtr->getLogdir();
+    string logdir;
+    if (m_sourceListPtr) {
+        logdir = m_sourceListPtr->getLogdir();
+    }
     engine.SetStrValue(configvars, "defout_path",
                        logdir.size() ? logdir : "/dev/null");
     engine.SetStrValue(configvars, "conferrpath", "console");
-    engine.SetStrValue(configvars, "binfilepath", getRootPath() + "/.synthesis");
+    engine.SetStrValue(configvars, "binfilepath", getSynthesisDatadir().c_str());
     configvars.reset();
 
     return engine;
@@ -1458,6 +1651,83 @@ namespace {
     }
 }
 
+void SyncContext::initServer(const std::string &sessionID,
+                             SharedBuffer data,
+                             const std::string &messageType)
+{
+    m_serverMode = true;
+    m_sessionID = sessionID;
+    m_initialMessage = data;
+    m_initialMessageType = messageType;
+    
+}
+
+struct SyncContext::SyncMLMessageInfo
+SyncContext::analyzeSyncMLMessage(const char *data, size_t len,
+                                  const std::string &messageType)
+{
+    SyncContext sync;
+    SwapContext syncSentinel(&sync);
+    SourceList sourceList(sync, false);
+    sourceList.setLogLevel(SourceList::LOGGING_SUMMARY);
+    m_sourceListPtr = &sourceList;
+    sync.initServer("", SharedBuffer(), "");
+    SwapEngine swapengine(sync);
+    sync.initEngine(false);
+
+    sysync::TEngineProgressInfo progressInfo;
+    sysync::uInt16 stepCmd = sysync::STEPCMD_GOTDATA;
+    SharedSession session = sync.m_engine.OpenSession(sync.m_sessionID);
+    SessionSentinel sessionSentinel(sync, session);
+
+    sync.m_engine.WriteSyncMLBuffer(session, data, len);
+    SharedKey sessionKey = sync.m_engine.OpenSessionKey(session);
+    sync.m_engine.SetStrValue(sessionKey,
+                              "contenttype",
+                              messageType);
+
+    // analyze main loop: runs until SessionStep() signals reply or error.
+    // Will call our SynthesisDBPlugin callbacks, most importantly
+    // SyncEvolution_Session_CheckDevice(), which records the device ID
+    // for us.
+    do {
+        sync.m_engine.SessionStep(session, stepCmd, &progressInfo);
+        switch (stepCmd) {
+        case sysync::STEPCMD_OK:
+        case sysync::STEPCMD_PROGRESS:
+            stepCmd = sysync::STEPCMD_STEP;
+            break;
+        default:
+            // whatever it is, cannot proceed
+            break;
+        }
+    } while (stepCmd == sysync::STEPCMD_STEP);
+
+    SyncMLMessageInfo info;
+    info.m_deviceID = sync.getSyncDeviceID();
+    return info;
+}
+
+void SyncContext::initEngine(bool logXML)
+{
+    string xml, configname;
+    getConfigXML(xml, configname);
+    try {
+        m_engine.InitEngineXML(xml.c_str());
+    } catch (const BadSynthesisResult &ex) {
+        SE_LOG_ERROR(NULL, NULL,
+                     "internal error, invalid XML configuration (%s):\n%s",
+                     m_sourceListPtr && !m_sourceListPtr->empty() ?
+                     "with datastores" :
+                     "without datastores",
+                     xml.c_str());
+        throw;
+    }
+    if (logXML) {
+        SE_LOG_DEV(NULL, NULL, "Full XML configuration:\n%s", xml.c_str());
+    }
+}
+
 SyncMLStatus SyncContext::sync(SyncReport *report)
 {
     SyncMLStatus status = STATUS_OK;
@@ -1472,27 +1742,29 @@ SyncMLStatus SyncContext::sync(SyncReport *report)
     sourceList.setLogLevel(m_quiet ? SourceList::LOGGING_QUIET :
                            getPrintChanges() ? SourceList::LOGGING_FULL :
                            SourceList::LOGGING_SUMMARY);
-    m_sourceListPtr = &sourceList;
 
-    if (getenv("SYNCEVOLUTION_GNUTLS_DEBUG")) {
-        // Enable libgnutls debugging without creating a hard dependency on it,
-        // because we don't call it directly and might not even be linked against
-        // it. Therefore check for the relevant symbols via dlsym().
-        void (*set_log_level)(int);
-        void (*set_log_function)(void (*func)(int level, const char *str));
+    SwapContext syncSentinel(this);
+    try {
+        m_sourceListPtr = &sourceList;
+
+        if (getenv("SYNCEVOLUTION_GNUTLS_DEBUG")) {
+            // Enable libgnutls debugging without creating a hard dependency on it,
+            // because we don't call it directly and might not even be linked against
+            // it. Therefore check for the relevant symbols via dlsym().
+            void (*set_log_level)(int);
+            void (*set_log_function)(void (*func)(int level, const char *str));
 
-        set_log_level = (typeof(set_log_level))dlsym(RTLD_DEFAULT, "gnutls_global_set_log_level");
-        set_log_function = (typeof(set_log_function))dlsym(RTLD_DEFAULT, "gnutls_global_set_log_function");
+            set_log_level = (typeof(set_log_level))dlsym(RTLD_DEFAULT, "gnutls_global_set_log_level");
+            set_log_function = (typeof(set_log_function))dlsym(RTLD_DEFAULT, "gnutls_global_set_log_function");
 
-        if (set_log_level && set_log_function) {
-            set_log_level(atoi(getenv("SYNCEVOLUTION_GNUTLS_DEBUG")));
-            set_log_function(GnutlsLogFunction);
-        } else {
-            SE_LOG_ERROR(NULL, NULL, "SYNCEVOLUTION_GNUTLS_DEBUG debugging not possible, log functions not found");
+            if (set_log_level && set_log_function) {
+                set_log_level(atoi(getenv("SYNCEVOLUTION_GNUTLS_DEBUG")));
+                set_log_function(GnutlsLogFunction);
+            } else {
+                SE_LOG_ERROR(NULL, NULL, "SYNCEVOLUTION_GNUTLS_DEBUG debugging not possible, log functions not found");
+            }
         }
-    }
 
-    try {
         SyncReport buffer;
         if (!report) {
             report = &buffer;
@@ -1509,12 +1781,18 @@ SyncMLStatus SyncContext::sync(SyncReport *report)
                                 report,
                                 "client");
 
+
+        /* Must detect server or client session before creating the
+         * underlying SynthesisEngine 
+         * */
+        if ( getPeerIsClient()) {
+            m_serverMode = true;
+        }
+
         // create a Synthesis engine, used purely for logging purposes
         // at this time
         SwapEngine swapengine(*this);
-        string xml, configname;
-        getConfigXML(xml, configname);
-        m_engine.InitEngineXML(xml.c_str());
+        initEngine(false);
 
         try {
             // dump some summary information at the beginning of the log
@@ -1547,28 +1825,32 @@ SyncMLStatus SyncContext::sync(SyncReport *report)
              */
             ConfigPropertyRegistry& registry = SyncConfig::getRegistry();
             BOOST_FOREACH(const ConfigProperty *prop, registry) {
-                prop->checkPassword(*this, m_server, getConfigNode());
+                prop->checkPassword(*this, m_server, *getProperties());
             }
             BOOST_FOREACH(SyncSource *source, sourceList) {
                 ConfigPropertyRegistry& registry = SyncSourceConfig::getRegistry();
                 BOOST_FOREACH(const ConfigProperty *prop, registry) {
-                    prop->checkPassword(*this, m_server, getConfigNode(),
-                                        source->getName(), source->getSyncSourceNodes().m_configNode);
+                    prop->checkPassword(*this, m_server, *getProperties(),
+                                        source->getName(), source->getProperties());
                 }
             }
 
             // open each source - failing now is still safe
             BOOST_FOREACH(SyncSource *source, sourceList) {
+                if (m_serverMode) {
+                    source->enableServerMode();
+                }
                 source->open();
             }
 
             // give derived class also a chance to update the configs
             prepare(sourceList);
 
+            // TODO: in server mode don't dump all databases. Wait until
+            // the client is logged in successfully and we know which
+            // sources it needs.
             // ready to go: dump initial databases and prepare for final report
             sourceList.syncPrepare();
-
-            // run sync session
             status = doSync();
         } catch (...) {
             // handle the exception here while the engine (and logging!) is still alive
@@ -1600,131 +1882,268 @@ SyncMLStatus SyncContext::sync(SyncReport *report)
     return status;
 }
 
+bool SyncContext::initSAN(int retries) 
+{
+    sysync::SanPackage san;
+    /* Should be nonce sent by the server in the preceeding sync session */
+    string nonce = "SyncEvolution";
+    /* SyncML Version 1.2 */
+    uint16_t protoVersion = 12;
+    string uauthb64 = san.B64_H (getUsername(), getPassword());
+    /* Client is expected to conduct the sync in the backgroud */
+    sysync::UI_Mode mode = sysync::UI_not_specified;
+
+    uint16_t sessionId = 0;
+    string serverId = getRemoteIdentifier();
+    if(serverId.empty()) {
+        serverId = getDevID();
+    }
+    san.PreparePackage( uauthb64, nonce, protoVersion, mode, 
+            sysync::Initiator_Server, sessionId, serverId);
+
+    san.CreateEmptyNotificationBody();
+    bool hasSource = false;
+    /* For each source to be notified do the following: */
+    BOOST_FOREACH (string name, m_sourceListPtr->getSources()) {
+        boost::shared_ptr<PersistentSyncSourceConfig> sc(getSyncSourceConfig(name));
+        string sync = sc->getSync();
+        int mode = StringToSyncMode (sync, true);
+        if (mode <SYNC_FIRST || mode >SYNC_LAST) {
+            SE_LOG_DEV (NULL, NULL, "Ignoring data source %s with an invalid sync mode", name.c_str());
+            continue;
+        }
+        hasSource = true;
+        string uri = sc->getURI();
+
+        SourceType sourceType = sc->getSourceType();
+        /*If the type is not set by user explictly, let's use backend default
+         * value*/
+        if(sourceType.m_format.empty()) {
+            sourceType.m_format = (*m_sourceListPtr)[name]->getPeerMimeType();
+        }
+        int contentTypeB = StringToContentType (sourceType.m_format);
+        if (contentTypeB == WSPCTC_UNKNOWN) {
+            contentTypeB = 0;
+            SE_LOG_DEBUG (NULL, NULL, "Unknown datasource mimetype, use 0 as default");
+        }
+        if ( san.AddSync(mode, (uInt32) contentTypeB, uri.c_str())) {
+            SE_LOG_ERROR(NULL, NULL, "SAN: adding server alerted sync element failed");
+        };
+    }
+
+    if (!hasSource) {
+        SE_THROW ("No source enabled for server alerted sync!");
+    }
+
+    /* Generate the SAN Package */
+    void *buffer;
+    size_t sanSize;
+    if (san.GetPackage(buffer, sanSize)){
+        SE_LOG_ERROR (NULL, NULL, "SAN package generating faield");
+        return false;
+    }
+
+    /* Create the transport agent */
+    try {
+        m_agent = createTransportAgent();
+        //register transport callback
+        if (m_retryInterval) {
+            m_agent->setCallback (transport_cb, this, m_retryInterval);
+        }
+        int retry = 0;
+        while (retry++ < retries) 
+        {
+            SE_LOG_INFO (NULL, NULL, "Server sending SAN %d", retry);
+            m_agent->setContentType (TransportAgent::m_contentTypeServerAlertedNotificationDS);
+            m_agent->send(reinterpret_cast <char *> (buffer), sanSize);
+            //change content type
+            m_agent->setContentType (getWBXML() ? TransportAgent::m_contentTypeSyncWBXML :
+                    TransportAgent::m_contentTypeSyncML);
+            if (m_agent->wait() == TransportAgent::GOT_REPLY){
+                const char *reply;
+                size_t replyLen;
+                string contentType;
+                m_agent->getReply (reply, replyLen, contentType);
+
+                //sanity check for the reply 
+                if (contentType.empty() || 
+                        contentType.find(TransportAgent::m_contentTypeSyncML) != contentType.npos ||
+                        contentType.find(TransportAgent::m_contentTypeSyncWBXML) != contentType.npos) {
+                    SharedBuffer request (reply, replyLen);
+                    //TODO should generate more reasonable sessionId here
+                    string sessionId ="";
+                    initServer (sessionId, request, contentType);
+                    return true;
+                }
+            }
+        }
+    } catch (TransportException e) {
+        SE_LOG_ERROR (NULL, NULL, "TransportException while sending SAN package");
+    }
+    return false;
+}
+
 SyncMLStatus SyncContext::doSync()
 {
+    // install signal handlers only if default behavior
+    // is currently active, restore when we return
     struct sigaction new_action, old_action;
-    new_action.sa_handler= suspend_handler;
-    sigemptyset (&new_action.sa_mask);
-    new_action.sa_flags = 0;
-    sigaction (SIGINT, &new_action, &old_action);
+    memset(&new_action, 0, sizeof(new_action));
+    new_action.sa_handler = handleSignal;
+    sigemptyset(&new_action.sa_mask);
+    sigaction(SIGINT, NULL, &old_action);
+    if (old_action.sa_handler == SIG_DFL) {
+        sigaction(SIGINT, &new_action, NULL);
+    }
+
+    struct sigaction old_term_action;
+    sigaction(SIGTERM, NULL, &old_term_action);
+    if (old_term_action.sa_handler == SIG_DFL) {
+        sigaction(SIGTERM, &new_action, NULL);
+    }   
+
     SyncMLStatus status = STATUS_OK;
     std::string s;
 
+    if (m_serverMode && !m_initialMessage.size()) {
+        //This is a server alerted sync !
+        if (! initSAN ()) {
+            // return a proper error code 
+            throwError ("Server Alerted Sync init failed");
+        }
+    }
+
     // re-init engine with all sources configured
     string xml, configname;
-    getConfigXML(xml, configname);
-    m_engine.InitEngineXML(xml.c_str());
-    SE_LOG_DEV(NULL, NULL, "Full XML configuration:\n%s", xml.c_str());
-
-    // check the settings status (MUST BE DONE TO MAKE SETTINGS READY)
-    SharedKey profiles = m_engine.OpenKeyByPath(SharedKey(), "/profiles");
-    m_engine.GetStrValue(profiles, "settingsstatus");
-    // allow creating new settings when existing settings are not up/downgradeable
-    m_engine.SetStrValue(profiles, "overwrite",  "1");
-    // check status again
-    m_engine.GetStrValue(profiles, "settingsstatus");
+    initEngine(true);
+
+    SharedKey targets;
+    SharedKey target;
+    if (m_serverMode) {
+        // Server engine has no profiles. All settings have be done
+        // via the XML configuration or function parameters (session ID
+        // in OpenSession()).
+    } else {
+        // check the settings status (MUST BE DONE TO MAKE SETTINGS READY)
+        SharedKey profiles = m_engine.OpenKeyByPath(SharedKey(), "/profiles");
+        m_engine.GetStrValue(profiles, "settingsstatus");
+        // allow creating new settings when existing settings are not up/downgradeable
+        m_engine.SetStrValue(profiles, "overwrite",  "1");
+        // check status again
+        m_engine.GetStrValue(profiles, "settingsstatus");
     
-    // open first profile
-    SharedKey profile;
-    try {
-        profile = m_engine.OpenSubkey(profiles, sysync::KEYVAL_ID_FIRST);
-    } catch (NoSuchKey error) {
-        // no profile exists  yet, create default profile
-        profile = m_engine.OpenSubkey(profiles, sysync::KEYVAL_ID_NEW_DEFAULT);
-    }
+        // open first profile
+        SharedKey profile;
+        try {
+            profile = m_engine.OpenSubkey(profiles, sysync::KEYVAL_ID_FIRST);
+        } catch (NoSuchKey error) {
+            // no profile exists  yet, create default profile
+            profile = m_engine.OpenSubkey(profiles, sysync::KEYVAL_ID_NEW_DEFAULT);
+        }
          
-    m_engine.SetStrValue(profile, "serverURI", getSyncURL());
-    m_engine.SetStrValue(profile, "serverUser", getUsername());
-    m_engine.SetStrValue(profile, "serverPassword", getPassword());
-    m_engine.SetInt32Value(profile, "encoding",
-                           getWBXML() ? 1 /* WBXML */ : 2 /* XML */);
-
-    // Iterate over all data stores in the XML config
-    // and match them with sync sources.
-    // TODO: let sync sources provide their own
-    // XML snippets (inside <client> and inside <datatypes>).
-    SharedKey targets = m_engine.OpenKeyByPath(profile, "targets");
-    SharedKey target;
+        m_engine.SetStrValue(profile, "serverURI", getSyncURL());
+        m_engine.SetStrValue(profile, "serverUser", getUsername());
+        m_engine.SetStrValue(profile, "serverPassword", getPassword());
+        m_engine.SetInt32Value(profile, "encoding",
+                               getWBXML() ? 1 /* WBXML */ : 2 /* XML */);
+
+        // Iterate over all data stores in the XML config
+        // and match them with sync sources.
+        // TODO: let sync sources provide their own
+        // XML snippets (inside <client> and inside <datatypes>).
+        targets = m_engine.OpenKeyByPath(profile, "targets");
 
-    try {
-        target = m_engine.OpenSubkey(targets, sysync::KEYVAL_ID_FIRST);
-        while (true) {
-            s = m_engine.GetStrValue(target, "dbname");
-            SyncSource *source = (*m_sourceListPtr)[s];
-            if (source) {
-                m_engine.SetInt32Value(target, "enabled", 1);
-                int slow = 0;
-                int direction = 0;
-                string mode = source->getSync();
-                if (!strcasecmp(mode.c_str(), "slow")) {
-                    slow = 1;
-                    direction = 0;
-                } else if (!strcasecmp(mode.c_str(), "two-way")) {
-                    slow = 0;
-                    direction = 0;
-                } else if (!strcasecmp(mode.c_str(), "refresh-from-server")) {
-                    slow = 1;
-                    direction = 1;
-                } else if (!strcasecmp(mode.c_str(), "refresh-from-client")) {
-                    slow = 1;
-                    direction = 2;
-                } else if (!strcasecmp(mode.c_str(), "one-way-from-server")) {
-                    slow = 0;
-                    direction = 1;
-                } else if (!strcasecmp(mode.c_str(), "one-way-from-client")) {
-                    slow = 0;
-                    direction = 2;
+        try {
+            target = m_engine.OpenSubkey(targets, sysync::KEYVAL_ID_FIRST);
+            while (true) {
+                s = m_engine.GetStrValue(target, "dbname");
+                SyncSource *source = (*m_sourceListPtr)[s];
+                if (source) {
+                    m_engine.SetInt32Value(target, "enabled", 1);
+                    int slow = 0;
+                    int direction = 0;
+                    string mode = source->getSync();
+                    if (!strcasecmp(mode.c_str(), "slow")) {
+                        slow = 1;
+                        direction = 0;
+                    } else if (!strcasecmp(mode.c_str(), "two-way")) {
+                        slow = 0;
+                        direction = 0;
+                    } else if (!strcasecmp(mode.c_str(), "refresh-from-server")) {
+                        slow = 1;
+                        direction = 1;
+                    } else if (!strcasecmp(mode.c_str(), "refresh-from-client")) {
+                        slow = 1;
+                        direction = 2;
+                    } else if (!strcasecmp(mode.c_str(), "one-way-from-server")) {
+                        slow = 0;
+                        direction = 1;
+                    } else if (!strcasecmp(mode.c_str(), "one-way-from-client")) {
+                        slow = 0;
+                        direction = 2;
+                    } else {
+                        source->throwError(string("invalid sync mode: ") + mode);
+                    }
+                    m_engine.SetInt32Value(target, "forceslow", slow);
+                    m_engine.SetInt32Value(target, "syncmode", direction);
+
+                    m_engine.SetStrValue(target, "remotepath", source->getURI());
                 } else {
-                    source->throwError(string("invalid sync mode: ") + mode);
+                    m_engine.SetInt32Value(target, "enabled", 0);
                 }
-                m_engine.SetInt32Value(target, "forceslow", slow);
-                m_engine.SetInt32Value(target, "syncmode", direction);
-
-                m_engine.SetStrValue(target, "remotepath", source->getURI());
-            } else {
-                m_engine.SetInt32Value(target, "enabled", 0);
+                target = m_engine.OpenSubkey(targets, sysync::KEYVAL_ID_NEXT);
             }
-            target = m_engine.OpenSubkey(targets, sysync::KEYVAL_ID_NEXT);
+        } catch (NoSuchKey error) {
         }
-    } catch (NoSuchKey error) {
+
+        // Close all keys so that engine can flush the modified config.
+        // Otherwise the session reads the unmodified values from the
+        // created files while the updated values are still in memory.
+        target.reset();
+        targets.reset();
+        profile.reset();
+        profiles.reset();
+
+        // reopen profile keys
+        profiles = m_engine.OpenKeyByPath(SharedKey(), "/profiles");
+        m_engine.GetStrValue(profiles, "settingsstatus");
+        profile = m_engine.OpenSubkey(profiles, sysync::KEYVAL_ID_FIRST);
+        targets = m_engine.OpenKeyByPath(profile, "targets");
     }
 
     m_retryInterval = getRetryInterval();
     m_retryDuration = getRetryDuration();
     m_retries = 0;
 
-    // run an HTTP client sync session
-    boost::shared_ptr<TransportAgent> agent(createTransportAgent());
-    if (getUseProxy()) {
-        agent->setProxy(getProxyHost());
-        agent->setProxyAuth(getProxyUsername(),
-                            getProxyPassword());
-    }
-    agent->setUserAgent(getUserAgent());
-    agent->setSSL(findSSLServerCertificate(),
-                  getSSLVerifyServer(),
-                  getSSLVerifyHost());
-
-    // Close all keys so that engine can flush the modified config.
-    // Otherwise the session reads the unmodified values from the
-    // created files while the updated values are still in memory.
-    target.reset();
-    targets.reset();
-    profile.reset();
-    profiles.reset();
-
-    // reopen profile keys
-    profiles = m_engine.OpenKeyByPath(SharedKey(), "/profiles");
-    m_engine.GetStrValue(profiles, "settingsstatus");
-    profile = m_engine.OpenSubkey(profiles, sysync::KEYVAL_ID_FIRST);
-    targets = m_engine.OpenKeyByPath(profile, "targets");
+    //Create the transport agent if not already created
+    if(!m_agent) {
+        m_agent = createTransportAgent();
+    }
 
     sysync::TEngineProgressInfo progressInfo;
-    sysync::uInt16 stepCmd = sysync::STEPCMD_CLIENTSTART; // first step
-    SharedSession session = m_engine.OpenSession();
+    sysync::uInt16 stepCmd = 
+        m_serverMode ?
+        sysync::STEPCMD_GOTDATA :
+        sysync::STEPCMD_CLIENTSTART;
+    SharedSession session = m_engine.OpenSession(m_sessionID);
     SharedBuffer sendBuffer;
     SessionSentinel sessionSentinel(*this, session);
 
+    if (m_serverMode) {
+        m_engine.WriteSyncMLBuffer(session,
+                                   m_initialMessage.get(),
+                                   m_initialMessage.size());
+        SharedKey sessionKey = m_engine.OpenSessionKey(session);
+        m_engine.SetStrValue(sessionKey,
+                             "contenttype",
+                             m_initialMessageType);
+        m_initialMessage.reset();
+
+        // TODO: set "sendrespuri" session key to control
+        // whether the generated messages contain a respURI
+        // (not needed for OBEX)
+    }
+
     // Sync main loop: runs until SessionStep() signals end or error.
     // Exceptions are caught and lead to a call of SessionStep() with
     // parameter STEPCMD_ABORT -> abort session as soon as possible.
@@ -1774,7 +2193,15 @@ SyncMLStatus SyncContext::doSync()
                 }
             }
 
-            m_engine.SessionStep(session, stepCmd, &progressInfo);
+            if (stepCmd == sysync::STEPCMD_NEEDDATA) {
+                // Engine already notified. Don't call it twice
+                // with this state, because it doesn't know how
+                // to handle this. Skip the SessionStep() call
+                // and wait for response.
+            } else {
+                m_engine.SessionStep(session, stepCmd, &progressInfo);
+            }
+
             //During suspention we actually insert a STEPCMD_SUSPEND cmd
             //Should restore to the original step here
             if(suspending == 1)
@@ -1808,21 +2235,23 @@ SyncMLStatus SyncContext::doSync()
                                             progressInfo.extra3);
                         break;
                     default:
-                        // specific for a certain sync source:
-                        // find it...
-                        target = m_engine.OpenSubkey(targets, progressInfo.targetID);
-                        s = m_engine.GetStrValue(target, "dbname");
-                        SyncSource *source = (*m_sourceListPtr)[s];
-                        if (source) {
-                            displaySourceProgress(sysync::TProgressEventEnum(progressInfo.eventtype),
-                                                  *source,
-                                                  progressInfo.extra1,
-                                                  progressInfo.extra2,
-                                                  progressInfo.extra3);
-                        } else {
-                            throwError(std::string("unknown target ") + s);
+                        if (!m_serverMode) {
+                            // specific for a certain sync source:
+                            // find it...
+                            target = m_engine.OpenSubkey(targets, progressInfo.targetID);
+                            s = m_engine.GetStrValue(target, "dbname");
+                            SyncSource *source = (*m_sourceListPtr)[s];
+                            if (source) {
+                                displaySourceProgress(sysync::TProgressEventEnum(progressInfo.eventtype),
+                                                      *source,
+                                                      progressInfo.extra1,
+                                                      progressInfo.extra2,
+                                                      progressInfo.extra3);
+                            } else {
+                                throwError(std::string("unknown target ") + s);
+                            }
+                            target.reset();
                         }
-                        target.reset();
                         break;
                     }
                 }
@@ -1842,27 +2271,31 @@ SyncMLStatus SyncContext::doSync()
             case sysync::STEPCMD_SENDDATA: {
                 // send data to remote
 
-                // use OpenSessionKey() and GetValue() to retrieve "connectURI"
-                // and "contenttype" to be used to send data to the server
                 SharedKey sessionKey = m_engine.OpenSessionKey(session);
-                s = m_engine.GetStrValue(sessionKey,
-                                         "connectURI");
-                agent->setURL(s);
+                if (m_serverMode) {
+                    m_agent->setURL("");
+                } else {
+                    // use OpenSessionKey() and GetValue() to retrieve "connectURI"
+                    // and "contenttype" to be used to send data to the server
+                    s = m_engine.GetStrValue(sessionKey,
+                                             "connectURI");
+                    m_agent->setURL(s);
+                }
                 s = m_engine.GetStrValue(sessionKey,
                                          "contenttype");
-                agent->setContentType(s);
+                m_agent->setContentType(s);
                 sessionKey.reset();
                 
                 sendStart = resendStart = time (NULL);
                 //register transport callback
                 if (m_retryInterval) {
-                    agent->setCallback (transport_cb, this, m_retryInterval);
+                    m_agent->setCallback (transport_cb, this, m_retryInterval);
                 }
                 // use GetSyncMLBuffer()/RetSyncMLBuffer() to access the data to be
                 // sent or have it copied into caller's buffer using
                 // ReadSyncMLBuffer(), then send it to the server
                 sendBuffer = m_engine.GetSyncMLBuffer(session, true);
-                agent->send(sendBuffer.get(), sendBuffer.size());
+                m_agent->send(sendBuffer.get(), sendBuffer.size());
                 stepCmd = sysync::STEPCMD_SENTDATA; // we have sent the data
                 break;
             }
@@ -1871,14 +2304,15 @@ SyncMLStatus SyncContext::doSync()
                 resendStart = time(NULL);
                 /* We are resending previous message, just read from the
                  * previous buffer */
-                agent->send(sendBuffer.get(), sendBuffer.size());
+                m_agent->send(sendBuffer.get(), sendBuffer.size());
                 stepCmd = sysync::STEPCMD_SENTDATA; // we have sent the data
                 break;
             }
             case sysync::STEPCMD_NEEDDATA:
-                switch (agent->wait()) {
+                switch (m_agent->wait()) {
                 case TransportAgent::ACTIVE:
-                    stepCmd = sysync::STEPCMD_SENTDATA; // still sending the data?!
+                    // Still sending the data?! Don't change anything,
+                    // skip SessionStep() above.
                     break;
                
                 case TransportAgent::TIME_OUT: {
@@ -1900,7 +2334,7 @@ SyncMLStatus SyncContext::doSync()
                     const char *reply;
                     size_t replylen;
                     string contentType;
-                    agent->getReply(reply, replylen, contentType);
+                    m_agent->getReply(reply, replylen, contentType);
 
                     // sanity check for reply: if known at all, it must be either XML or WBXML
                     if (contentType.empty() ||
@@ -1912,6 +2346,12 @@ SyncMLStatus SyncContext::doSync()
                         m_engine.WriteSyncMLBuffer(session,
                                                    reply,
                                                    replylen);
+                        if (m_serverMode) {
+                            SharedKey sessionKey = m_engine.OpenSessionKey(session);
+                            m_engine.SetStrValue(sessionKey,
+                                                 "contenttype",
+                                                 contentType);
+                        }
                         stepCmd = sysync::STEPCMD_GOTDATA; // we have received response data
                         break;
                     } else {
@@ -1994,10 +2434,32 @@ SyncMLStatus SyncContext::doSync()
         }
     } while (stepCmd != sysync::STEPCMD_DONE && stepCmd != sysync::STEPCMD_ERROR);
 
+    // If we get here without error, then close down connection normally.
+    // Otherwise destruct the agent without further communication.
+    if (!status && !checkForAbort()) {
+        try {
+            m_agent->shutdown();
+            // TODO: implement timeout for peers which fail to respond
+            while (!checkForAbort() &&
+                   m_agent->wait(true) == TransportAgent::ACTIVE) {
+                // TODO: allow aborting the sync here
+            }
+        } catch (...) {
+            status = handleException();
+        }
+    }
+
+    m_agent.reset();
     sigaction (SIGINT, &old_action, NULL);
+    sigaction (SIGTERM, &old_term_action, NULL);
     return status;
 }
 
+SyncMLStatus SyncContext::handleException()
+{
+    SyncMLStatus res = Exception::handle();
+    return res;
+}
 
 void SyncContext::status()
 {
@@ -2011,8 +2473,8 @@ void SyncContext::status()
     BOOST_FOREACH(SyncSource *source, sourceList) {
         ConfigPropertyRegistry& registry = SyncSourceConfig::getRegistry();
         BOOST_FOREACH(const ConfigProperty *prop, registry) {
-            prop->checkPassword(*this, m_server, getConfigNode(),
-                                source->getName(), source->getSyncSourceNodes().m_configNode);
+            prop->checkPassword(*this, m_server, *getProperties(),
+                                source->getName(), source->getProperties());
         }
     }
     BOOST_FOREACH(SyncSource *source, sourceList) {
@@ -2064,8 +2526,8 @@ void SyncContext::checkStatus(SyncReport &report)
     BOOST_FOREACH(SyncSource *source, sourceList) {
         ConfigPropertyRegistry& registry = SyncSourceConfig::getRegistry();
         BOOST_FOREACH(const ConfigProperty *prop, registry) {
-            prop->checkPassword(*this, m_server, getConfigNode(),
-                                source->getName(), source->getSyncSourceNodes().m_configNode);
+            prop->checkPassword(*this, m_server, *getProperties(),
+                                source->getName(), source->getProperties());
         }
     }
     BOOST_FOREACH(SyncSource *source, sourceList) {
@@ -2126,8 +2588,8 @@ void SyncContext::restore(const string &dirname, RestoreDatabase database)
     BOOST_FOREACH(SyncSource *source, sourceList) {
         ConfigPropertyRegistry& registry = SyncSourceConfig::getRegistry();
         BOOST_FOREACH(const ConfigProperty *prop, registry) {
-            prop->checkPassword(*this, m_server, getConfigNode(),
-                                source->getName(), source->getSyncSourceNodes().m_configNode);
+            prop->checkPassword(*this, m_server, *getProperties(),
+                                source->getName(), source->getProperties());
         }
     }
 
@@ -2185,18 +2647,4 @@ void SyncContext::readSessionInfo(const string &dir, SyncReport &report)
     logging.readReport(report);
 }
 
-std::string SyncContext::findSSLServerCertificate()
-{
-    std::string paths = getSSLServerCertificates();
-    std::vector< std::string > files;
-    boost::split(files, paths, boost::is_any_of(":"));
-    BOOST_FOREACH(std::string file, files) {
-        if (!file.empty() && !access(file.c_str(), R_OK)) {
-            return file;
-        }
-    }
-
-    return "";
-}
-
 SE_END_CXX
index 9e2da36..1ff6528 100644 (file)
@@ -43,6 +43,7 @@ class SyncSource;
 
 struct SuspendFlags
 {
+    /** SIGINT twice within this amount of seconds aborts the sync */
     static const time_t ABORT_INTERVAL = 2; 
     enum CLIENT_STATE
     {
@@ -53,7 +54,16 @@ struct SuspendFlags
     }state;
     time_t last_suspend;
 
-    SuspendFlags():state(CLIENT_NORMAL),last_suspend(0)
+    /**
+     * Simple string to print in SyncContext::printSignals().
+     * Set by SyncContext::handleSignal() when updating the
+     * global state. There's a slight race condition: if
+     * messages are set more quickly than they are printed,
+     * only the last message is printed.
+     */
+    const char *message;
+
+SuspendFlags():state(CLIENT_NORMAL),last_suspend(0),message(NULL)
     {}
 };
 
@@ -69,11 +79,18 @@ struct SuspendFlags
  */
 class SyncContext : public SyncConfig, public ConfigUserInterface {
     const string m_server;
-    const set<string> m_sources;
-    const bool m_doLogging;
+    bool m_doLogging;
     bool m_quiet;
     bool m_dryrun;
 
+    bool m_serverMode;
+    std::string m_sessionID;
+    SharedBuffer m_initialMessage;
+    string m_initialMessageType;
+    string m_syncDeviceID;
+
+    
+    boost::shared_ptr<TransportAgent> m_agent;
     /**
      * flags for suspend and abort
      */
@@ -86,6 +103,23 @@ class SyncContext : public SyncConfig, public ConfigUserInterface {
     static SourceList *m_sourceListPtr;
 
     /**
+     * a pointer to the active SyncContext instance if one exists;
+     * set by sync() and/or SwapContext
+     */
+    static SyncContext *m_activeContext;
+    class SwapContext {
+        SyncContext *m_oldContext;
+    public:
+        SwapContext(SyncContext *newContext) :
+            m_oldContext(SyncContext::m_activeContext) {
+            SyncContext::m_activeContext = newContext;
+        }
+        ~SwapContext() {
+            SyncContext::m_activeContext = m_oldContext;
+        }
+    };
+
+    /**
      * Connection to the Synthesis engine. Always valid in a
      * constructed SyncContext. Use getEngine() to reference
      * it.
@@ -115,23 +149,54 @@ class SyncContext : public SyncConfig, public ConfigUserInterface {
 
   public:
     /**
+     * SyncContext using a volatile config
+     * and no logging.
+     */
+    SyncContext();
+
+    /**
      * @param server     identifies the server config to be used
      * @param doLogging  write additional log and datatbase files about the sync
      */
     SyncContext(const string &server,
-                        bool doLogging = false,
-                        const set<string> &sources = set<string>());
+                bool doLogging = false);
     ~SyncContext();
 
-    using SyncConfig::savePassword;
-
     bool getQuiet() { return m_quiet; }
     void setQuiet(bool quiet) { m_quiet = quiet; }
 
     bool getDryRun() { return m_dryrun; }
     void setDryRun(bool dryrun) { m_dryrun = dryrun; }
 
-    static SuspendFlags& getSuspendFlags() {return s_flags;}
+    /** only for server: device ID of peer */
+    void setSyncDeviceID(const std::string &deviceID) { m_syncDeviceID = deviceID; }
+    std::string getSyncDeviceID() const { return m_syncDeviceID; }
+
+    /** read-only access to suspend and abort state */
+    static const SuspendFlags &getSuspendFlags() { return s_flags; }
+
+    /*
+     * Use initSAN as the first step is sync() if this is a server alerted sync.
+     * Prepare the san package and send the SAN request to the peer in retry
+     * times. Returns false if failed to get a valid client sync request
+     * otherwise put the client sync request into m_initialMessage which will
+     * be used to initalze the server via initServer(), then continue sync() to
+     * start the real sync serssion.
+     */
+    bool initSAN (int retry = 3);
+
+    /**
+     * Initializes the session so that it runs as SyncML server once
+     * sync() is called. For this to work the first client message
+     * must be available already.
+     *
+     * @param sessionID    session ID to be used by server
+     * @param data         content of initial message sent by the client
+     * @param messageType  content type set by the client
+     */
+    void initServer(const std::string &sessionID,
+                    SharedBuffer data,
+                    const std::string &messageType);
 
     /**
      * Executes the sync, throws an exception in case of failure.
@@ -142,6 +207,35 @@ class SyncContext : public SyncConfig, public ConfigUserInterface {
      */
     SyncMLStatus sync(SyncReport *report = NULL);
 
+    /** result of analyzeSyncMLMessage() */
+    struct SyncMLMessageInfo {
+        std::string m_deviceID;
+
+        /** a string representation of the whole structure for debugging */
+        std::string toString() { return std::string("deviceID ") + m_deviceID; }
+    };
+
+    /**
+     * Instead or executing a sync, analyze the initial message
+     * without changing any local data. Returns once the LocURI =
+     * device ID of the client is known.
+     *
+     * @return device ID, empty if not in data
+     */
+    static SyncMLMessageInfo
+        analyzeSyncMLMessage(const char *data, size_t len,
+                             const std::string &messageType);
+
+    /**
+     * Convenience function, to be called inside a catch() block of
+     * (or for) the sync.
+     *
+     * Rethrows the exception to determine what it is, then logs it
+     * as an error and returns a suitable error code (usually a general
+     * STATUS_DATASTORE_FAILURE).
+     */
+    SyncMLStatus handleException();
+
     /**
      * Determines the log directory of the previous sync (either in
      * temp or logdir) and shows changes since then.
@@ -249,14 +343,14 @@ class SyncContext : public SyncConfig, public ConfigUserInterface {
     static SyncSource *findSource(const char *name);
 
     /**
-     * intercept config filters
+     * Find the active sync context for the given session.
      *
-     * This call removes the "sync" source property and remembers
-     * it separately because it has to be applied to only the active
-     * sync sources; the generic config handling code would apply
-     * it to all sources.
+     * @param sessionName      chosen by SyncEvolution and passed to
+     *                         Synthesis engine, which calls us back
+     *                         with it in SyncEvolution_Session_CreateContext()
+     * @return context or NULL if not found
      */
-    virtual void setConfigFilter(bool sync, const FilterConfigNode::ConfigFilter &filter);
+    static SyncContext *findContext(const char *sessionName);
 
     SharedEngine getEngine() { return m_engine; }
     const SharedEngine getEngine() const { return m_engine; }
@@ -269,6 +363,25 @@ class SyncContext : public SyncConfig, public ConfigUserInterface {
      */
     SharedSession getSession() { return m_session; }
 
+    /**
+     * sync() installs signal handlers for SIGINT and SIGTERM if no
+     * handler was installed already. SIGINT will try to suspend.
+     * Sending the signal again quickly (typically done by pressing
+     * CTRL-C twice) will abort. SIGTERM will abort the running sync
+     * immediately.
+     *
+     * If a handler was installed already, the caller is responsible
+     * for calling this function if this kind of SIGINT/SIGTERM
+     * handling is desired.
+     */
+    static void handleSignal(int signal);
+
+    /**
+     * Once a signal was received, all future calls to sync() will
+     * react to it unless this function is called first.
+     */
+    static void resetSignals() { s_flags = SuspendFlags(); }
+
   protected:
     /** exchange active Synthesis engine */
     SharedEngine swapEngine(SharedEngine newengine) {
@@ -477,7 +590,10 @@ class SyncContext : public SyncConfig, public ConfigUserInterface {
      *
      * @return true if user wants to abort
      */
-    virtual bool checkForAbort() { return (s_flags.state == SuspendFlags::CLIENT_ABORT);}
+    virtual bool checkForAbort() {
+        printSignals();
+        return (s_flags.state == SuspendFlags::CLIENT_ABORT);
+    }
 
     /**
      * Called to find out whether user wants to suspend sync.
@@ -485,9 +601,20 @@ class SyncContext : public SyncConfig, public ConfigUserInterface {
      * Same as checkForAbort(), but the session is finished
      * gracefully so that it can be resumed.
      */
-    virtual bool checkForSuspend() { return (s_flags.state == SuspendFlags::CLIENT_SUSPEND);}
+    virtual bool checkForSuspend() {
+        printSignals();
+        return (s_flags.state == SuspendFlags::CLIENT_SUSPEND);
+    }
 
  private:
+    /** initialize members as part of constructors */
+    void init();
+
+    /**
+     * generate XML configuration and (re)initialize engine with it
+     */
+    void initEngine(bool logXML);
+
     /**
      * the code common to init() and status():
      * populate source list with active sources and open
@@ -506,16 +633,19 @@ class SyncContext : public SyncConfig, public ConfigUserInterface {
     SyncMLStatus doSync();
 
     /**
-     * iterate over files mentioned in getSSLServerCertificates()
-     * and return name of first one which is found, empty string
-     * if none
+     * directory for Synthesis client binfiles or
+     * Synthesis server textdb files, unique for each
+     * peer
      */
-    std::string findSSLServerCertificate();
+    string getSynthesisDatadir() { return getRootPath() + "/.synthesis"; }
 
     /**
-     * override sync mode of all active sync sources if set
+     * handleSignals() is called in a signal handler,
+     * which can only call reentrant functions. Our
+     * logging code is not reentrant and thus has
+     * to be called outside of the signal handler.
      */
-    string m_overrideMode;
+    static void printSignals();
 
     // total retry duration
     int m_retryDuration;
index 9000de6..bfdd9a9 100644 (file)
@@ -98,27 +98,6 @@ const char *SyncEvolutionXML =
 "      $VCALENDAR_10TO20_PRIORITY_CONVERSION;\n"
 "    ]]></macro>\n"
 "\n"
-"    <macro name=\"VCARD_INCOMING_NAMECHANGE_SCRIPT\"><![CDATA[\n"
-"      STRING tmp;\n"
-"      tmp=NORMALIZED(FN);\n"
-"      if (tmp==EMPTY){\n"
-"        tmp=N_FIRST;\n"
-"        if (N_MIDDLE != EMPTY) {\n"
-"          if (tmp != EMPTY) {\n"
-"            tmp = tmp + \" \";\n"
-"          }\n"
-"          tmp = tmp + N_MIDDLE;\n"
-"        }\n"
-"        if (N_LAST != EMPTY) {\n"
-"          if (tmp != EMPTY) {\n"
-"            tmp = tmp + \" \";\n"
-"          }\n"
-"          tmp = tmp + N_LAST;\n"
-"        }\n"
-"        FN = tmp;\n"
-"      }\n"
-"    ]]></macro>\n"
-"\n"
 "              <!-- define script macros for scripts that are used by both vCalendar 1.0 and iCalendar 2.0 -->\n"
 "\n"
 "    <macro name=\"VCALENDAR_INCOMING_SCRIPT\"><![CDATA[\n"
@@ -221,6 +200,7 @@ const char *SyncEvolutionXML =
 "      }\n"
 "    ]]></macro>\n"
 "\n"
+"\n"
 "    <macro name=\"VCALENDAR_OUTGOING_SCRIPT\"><![CDATA[\n"
 "      // set UTC time of generation for iCalendar 2.0 DTSTAMP\n"
 "      DGENERATED = NOW();\n"
@@ -285,8 +265,6 @@ const char *SyncEvolutionXML =
 "      <field name=\"FN\" type=\"string\" compare=\"conflict\" merge=\"fillempty\"/>\n"
 "      <field name=\"FILE-AS\" type=\"string\" compare=\"conflict\" merge=\"fillempty\"/>\n"
 "\n"
-"      <field name=\"GENDER\" type=\"string\" compare=\"conflict\" merge=\"fillempty\"/>\n"
-"\n"
 "      <!-- categories and classification -->\n"
 "      <field name=\"CATEGORIES\" array=\"yes\" type=\"string\" compare=\"conflict\"/>\n"
 "\n"
@@ -352,10 +330,6 @@ const char *SyncEvolutionXML =
 "      <field name=\"MSN_SLOT\"          array=\"yes\" type=\"string\" compare=\"conflict\"/>\n"
 "      <field name=\"YAHOO_HANDLE\"        array=\"yes\" type=\"string\" compare=\"conflict\"/>\n"
 "      <field name=\"YAHOO_SLOT\"          array=\"yes\" type=\"string\" compare=\"conflict\"/>\n"
-"      <field name=\"SKYPE_HANDLE\"      array=\"yes\" type=\"string\" compare=\"conflict\"/>\n"
-"      <field name=\"SKYPE_SLOT\"        array=\"yes\" type=\"string\" compare=\"conflict\"/>\n"
-"      <field name=\"SIP_HANDLE\"        array=\"yes\" type=\"string\" compare=\"conflict\"/>\n"
-"      <field name=\"SIP_SLOT\"          array=\"yes\" type=\"string\" compare=\"conflict\"/>\n"
 "\n"
 "      <!-- home address -->\n"
 "      <field name=\"ADR_STREET\"        array=\"yes\" type=\"multiline\" compare=\"conflict\"/>\n"
@@ -410,10 +384,6 @@ const char *SyncEvolutionXML =
 "          <value field=\"FILE-AS\"/>\n"
 "        </property>\n"
 "\n"
-"        <property name=\"X-GENDER\">\n"
-"          <value field=\"GENDER\"/>\n"
-"        </property>\n"
-"\n"
 "        <!-- onlyformode=\"standard\": not part of vCard 2.1, but some\n"
 "             peers (like the Funambol server) accept it anyway in\n"
 "             vCard 2.1 -->\n"
@@ -609,20 +579,6 @@ const char *SyncEvolutionXML =
 "          </parameter>\n"
 "        </property>\n"
 "\n"
-"        <property name=\"X-SKYPE\" suppressempty=\"yes\"> \n"
-"          <value field=\"SKYPE_HANDLE\"/>\n"
-"          <parameter name=\"X-EVOLUTION-UI-SLOT\" positional=\"no\" show=\"yes\">\n"
-"            <value field=\"SKYPE_SLOT\"/>\n"
-"          </parameter>\n"
-"        </property>\n"
-"\n"
-"        <property name=\"X-SIP\" suppressempty=\"yes\">\n"
-"          <value field=\"SIP_HANDLE\"/>\n"
-"          <parameter name=\"X-EVOLUTION-UI-SLOT\" positional=\"no\" show=\"yes\">\n"
-"            <value field=\"SIP_SLOT\"/>\n"
-"          </parameter>\n"
-"        </property>\n"
-"\n"
 "        <property name=\"ADR\" values=\"7\">\n"
 "          <value index=\"0\" field=\"ADR_POBOX\"/>\n"
 "          <value index=\"1\" field=\"ADR_ADDTL\"/>\n"
@@ -668,18 +624,12 @@ const char *SyncEvolutionXML =
 "    <datatype name=\"vCard21\" basetype=\"vcard\">\n"
 "      <version>2.1</version>\n"
 "      <use mimeprofile=\"vCard\"/>\n"
-"     <incomingscript><![CDATA[\n"
-"        $VCARD_INCOMING_NAMECHANGE_SCRIPT\n"
-"      ]]></incomingscript>\n"
 "    </datatype>\n"
 "\n"
 "    <!-- vCard 3.0 datatype, using vCard profile defined above -->\n"
 "    <datatype name=\"vCard30\" basetype=\"vcard\">\n"
 "      <version>3.0</version>\n"
 "      <use mimeprofile=\"vCard\"/>\n"
-"      <incomingscript><![CDATA[\n"
-"        $VCARD_INCOMING_NAMECHANGE_SCRIPT\n"
-"      ]]></incomingscript>\n"
 "    </datatype>\n"
 "\n"
 "\n"
@@ -1270,7 +1220,7 @@ const char *SyncEvolutionXML =
 "      <incomingscript><![CDATA[\n"
 "        $VCALENDAR_INCOMING_SCRIPT\n"
 "      ]]></incomingscript>\n"
-"      \n"
+"\n"
 "      <outgoingscript><![CDATA[\n"
 "        $VCALENDAR_OUTGOING_SCRIPT\n"
 "      ]]></outgoingscript>\n"
@@ -1287,7 +1237,6 @@ const char *SyncEvolutionXML =
 "        $VCALENDAR_INCOMING_SCRIPT\n"
 "      ]]></incomingscript>\n"
 "\n"
-"\n"
 "      <outgoingscript><![CDATA[\n"
 "        $VCALENDAR_OUTGOING_SCRIPT\n"
 "      ]]></outgoingscript>\n"
@@ -1398,25 +1347,15 @@ const char *SyncEvolutionXML =
 "    <datatypes/>\n"
 "  </datatypes>\n"
 "\n"
+"  <clientorserver/>\n"
 "\n"
 "  <client type=\"plugin\">\n"
-"    <binfilespath>$(binfilepath)</binfilespath>\n"
-"    <defaultauth/>\n"
-"\n"
-"    <!-- SyncEvolution has traditionally not folded long lines in\n"
-"         vCard.  Testing showed that servers still have problems with\n"
-"         it, so avoid it by default -->\n"
-"    <donotfoldcontent>yes</donotfoldcontent>\n"
-"\n"
-"    <fakedeviceid/>\n"
-"\n"
-"    <datastore/>\n"
-"\n"
-"    <remoterule name=\"EVOLUTION\">\n"
-"      <deviceid>none - this rule is activated via its name in MAKE/PARSETEXTWITHPROFILE() macro calls</deviceid>\n"
-"    </remoterule>\n"
-"\n"
-"    <remoterules/>\n"
+"      <remoterule name=\"ZYB\">\n"
+"          <manufacturer>ZYB</manufacturer>\n"
+"          <model>ZYB</model>\n"
+"          <!-- information to disable anchors checking -->\n"
+"          <lenientmode>yes</lenientmode>\n"
+"      </remoterule>\n"
 "  </client>\n"
 "\n"
 "</sysync_config>\n"
index 7e6a6d0..eb8b83a 100644 (file)
@@ -40,16 +40,21 @@ std::string PrettyPrintSyncMode(SyncMode mode, bool userVisible)
     case SYNC_NONE:
         return userVisible ? "disabled" : "SYNC_NONE";
     case SYNC_TWO_WAY:
+    case SA_SYNC_TWO_WAY:
         return userVisible ? "two-way" : "SYNC_TWO_WAY";
     case SYNC_SLOW:
         return userVisible ? "slow" : "SYNC_SLOW";
     case SYNC_ONE_WAY_FROM_CLIENT:
+    case SA_SYNC_ONE_WAY_FROM_CLIENT:
         return userVisible ? "one-way-from-client" : "SYNC_ONE_WAY_FROM_CLIENT";
     case SYNC_REFRESH_FROM_CLIENT:
+    case SA_SYNC_REFRESH_FROM_CLIENT:
         return userVisible ? "refresh-from-client" : "SYNC_REFRESH_FROM_CLIENT";
     case SYNC_ONE_WAY_FROM_SERVER:
+    case SA_SYNC_ONE_WAY_FROM_SERVER:
         return userVisible ? "one-way-from-server" : "SYNC_ONE_WAY_FROM_SERVER";
     case SYNC_REFRESH_FROM_SERVER:
+    case SA_SYNC_REFRESH_FROM_SERVER:
         return userVisible ? "refresh-from-server" : "SYNC_REFRESH_FROM_SERVER";
     default:
         std::stringstream res;
@@ -59,28 +64,49 @@ std::string PrettyPrintSyncMode(SyncMode mode, bool userVisible)
     }
 }
 
-SyncMode StringToSyncMode(const std::string &mode)
+SyncMode StringToSyncMode(const std::string &mode, bool serverAlerted)
 {
     if (boost::iequals(mode, "slow") || boost::iequals(mode, "SYNC_SLOW")) {
+        if (serverAlerted) {
+            //No server initiated slow sync, fallback to two way sync
+            return SA_SYNC_TWO_WAY;
+        }
         return SYNC_SLOW;
     } else if (boost::iequals(mode, "two-way") || boost::iequals(mode, "SYNC_TWO_WAY")) {
-        return SYNC_TWO_WAY;
+        return serverAlerted ?SA_SYNC_TWO_WAY: SYNC_TWO_WAY;
     } else if (boost::iequals(mode, "refresh-from-server") || boost::iequals(mode, "SYNC_REFRESH_FROM_SERVER")) {
-        return SYNC_REFRESH_FROM_SERVER;
+        return serverAlerted? SA_SYNC_REFRESH_FROM_SERVER: SYNC_REFRESH_FROM_SERVER;
     } else if (boost::iequals(mode, "refresh-from-client") || boost::iequals(mode, "SYNC_REFRESH_FROM_CLIENT")) {
-        return SYNC_REFRESH_FROM_CLIENT;
+        return serverAlerted? SA_SYNC_REFRESH_FROM_CLIENT: SYNC_REFRESH_FROM_CLIENT;
     } else if (boost::iequals(mode, "one-way-from-server") || boost::iequals(mode, "SYNC_ONE_WAY_FROM_SERVER")) {
-        return SYNC_REFRESH_FROM_SERVER;
+        return serverAlerted? SA_SYNC_ONE_WAY_FROM_SERVER: SYNC_ONE_WAY_FROM_SERVER;
     } else if (boost::iequals(mode, "one-way-from-client") || boost::iequals(mode, "SYNC_ONE_WAY_FROM_CLIENT")) {
-        return SYNC_REFRESH_FROM_CLIENT;
+        return serverAlerted? SA_SYNC_ONE_WAY_FROM_CLIENT: SYNC_ONE_WAY_FROM_CLIENT;
     } else if (boost::iequals(mode, "disabled") || boost::iequals(mode, "SYNC_NONE")) {
         return SYNC_NONE;
     } else {
-        return SYNC_MODE_MAX;
+        return SYNC_INVALID;
     }
 }
 
 
+ContentType StringToContentType(const std::string &type) {
+    if (boost::iequals (type, "text/x-vcard") || boost::iequals (type, "text/x-vcard:2.1")) {
+        return WSPCTC_XVCARD;
+    } else if (boost::iequals (type, "text/vcard") ||boost::iequals (type, "text/vcard:3.0")) {
+        return WSPCTC_VCARD;
+    } else if (boost::iequals (type, "text/x-vcalendar") ||boost::iequals (type, "text/x-vcalendar:1.0")
+              ||boost::iequals (type, "text/x-calendar") || boost::iequals (type, "text/x-calendar:1.0")) {
+        return WSPCTC_XVCALENDAR;
+    } else if (boost::iequals (type, "text/calendar") ||boost::iequals (type, "text/calendar:2.0")) {
+        return WSPCTC_ICALENDAR;
+    } else if (boost::iequals (type, "text/plain") ||boost::iequals (type, "text/plain:1.0")) {
+        return WSPCTC_TEXT_PLAIN;
+    } else {
+        return WSPCTC_UNKNOWN;
+    }
+}
+
 namespace {
     const char * const locNames[] = { "local", "remote", NULL };
     const char * const stateNames[] = { "added", "updated", "removed", "any", NULL };
index 6f8bc98..8a1fc60 100644 (file)
 #include <syncevo/declarations.h>
 SE_BEGIN_CXX
 
+/** alert Codes used at the synchronization initialization */
 enum SyncMode {
+    /** unset or disabled */
     SYNC_NONE,
-    SYNC_TWO_WAY,
-    SYNC_SLOW,
-    SYNC_ONE_WAY_FROM_CLIENT,
-    SYNC_REFRESH_FROM_CLIENT,
-    SYNC_ONE_WAY_FROM_SERVER,
-    SYNC_REFRESH_FROM_SERVER,
-    SYNC_MODE_MAX
+
+    SYNC_FIRST = 200,
+    SYNC_TWO_WAY = 200,
+    SYNC_SLOW = 201,
+    SYNC_ONE_WAY_FROM_CLIENT = 202,
+    SYNC_REFRESH_FROM_CLIENT = 203,
+    SYNC_ONE_WAY_FROM_SERVER = 204,
+    SYNC_REFRESH_FROM_SERVER = 205,
+
+    /** used by Server Alerted Sync **/
+    SA_SYNC_TWO_WAY = 206,
+    SA_SYNC_ONE_WAY_FROM_CLIENT = 207,
+    SA_SYNC_REFRESH_FROM_CLIENT = 208,
+    SA_SYNC_ONE_WAY_FROM_SERVER = 209,
+    SA_SYNC_REFRESH_FROM_SERVER = 210,
+    
+    SYNC_LAST = 220,
+    /** error situation (in contrast to SYNC_NONE) */
+    SYNC_INVALID = 255
+};
+
+/* According to OMNA WSP Content Type Numbers*/
+enum ContentType {
+    WSPCTC_TEXT_PLAIN = 0x03,
+    WSPCTC_XVCALENDAR = 0x06,
+    WSPCTC_XVCARD = 0x07,
+    WSPCTC_ICALENDAR = 0x0305,
+    WSPCTC_VCARD = 0x0309,
+    WSPCTC_UNKNOWN =0xFFFFFF
 };
 
 /**
@@ -50,7 +74,12 @@ std::string PrettyPrintSyncMode(SyncMode mode, bool userVisible = true);
 /**
  * Parse user-visible mode names.
  */
-SyncMode StringToSyncMode(const std::string &str);
+SyncMode StringToSyncMode(const std::string &str, bool serverAlerted = false);
+
+/*
+ * Parse string based content type to WSPCTC encoded binary code
+ */
+ContentType StringToContentType (const std::string &str);
 
 /**
  * result of SyncML operations, same codes as in HTTP and the Synthesis engine
index 90e3506..976bfaa 100644 (file)
@@ -26,6 +26,7 @@
 #include <syncevo/SyncSource.h>
 #include <syncevo/SyncContext.h>
 #include <syncevo/util.h>
+#include <syncevo/SafeConfigNode.h>
 
 #include <syncevo/SynthesisEngine.h>
 #include <synthesis/SDK_util.h>
@@ -33,6 +34,9 @@
 
 #include <boost/bind.hpp>
 #include <boost/algorithm/string/join.hpp>
+#include <boost/algorithm/string/split.hpp>
+#include <boost/algorithm/string/classification.hpp>
+#include <boost/algorithm/string/predicate.hpp>
 
 #include <ctype.h>
 #include <errno.h>
@@ -88,7 +92,10 @@ void SyncSourceBase::getDatastoreXML(string &xml, XMLConfigFragments &fragments)
 
     xmlstream <<
         "      <plugin_module>SyncEvolution</plugin_module>\n"
-        "      <plugin_datastoreadmin>no</plugin_datastoreadmin>\n"
+        "      <plugin_datastoreadmin>" <<
+        (serverModeEnabled() ? "yes" : "no") <<
+        "</plugin_datastoreadmin>\n"
+        "      <fromremoteonlysupport> yes </fromremoteonlysupport>\n"
         "\n"
         "      <!-- General datastore settings for all DB types -->\n"
         "\n"
@@ -336,7 +343,7 @@ SyncSource *SyncSource::createTestingSource(const string &name, const string &ty
 {
     SyncConfig config("testing");
     SyncSourceNodes nodes = config.getSyncSourceNodes(name);
-    SyncSourceParams params(name, nodes, "");
+    SyncSourceParams params(name, nodes);
     PersistentSyncSourceConfig sourceconfig(name, nodes);
     sourceconfig.setSourceType(type);
     if (prefix) {
@@ -440,7 +447,7 @@ void SyncSourceSerialize::getSynthesisInfo(SynthesisInfo &info,
         info.m_datatypes =
             "        <use datatype='vCard21' mode='rw'/>\n"
             "        <use datatype='vCard30' mode='rw' preferred='yes'/>\n";
-    } else if (type == "text/x-calendar") {
+    } else if (type == "text/x-calendar" || type == "text/x-vcalendar") {
         info.m_native = "vCalendar10";
         info.m_fieldlist = "calendar";
         info.m_profile = "\"vCalendar\", 1";
@@ -488,7 +495,8 @@ void SyncSourceSerialize::getSynthesisInfo(SynthesisInfo &info,
             info.m_datatypes +=
                 "        <use datatype='vCard21' mode='rw'/>\n";
         }
-    } else if (type == "text/x-vcalendar:1.0" || type == "text/x-vcalendar") {
+    } else if (type == "text/x-vcalendar:1.0" || type == "text/x-vcalendar"
+             || type == "text/x-calendar:1.0" || type == "text/x-calendar") {
         info.m_datatypes =
             "        <use datatype='vcalendar10' mode='rw' preferred='yes'/>\n";
         if (!sourceType.m_forceFormat) {
@@ -705,7 +713,7 @@ void SyncSourceRevisions::detectChanges(ConfigNode &trackingNode)
     }
 
     // clear information about all items that we recognized as deleted
-    map<string, string> props;
+    ConfigProps props;
     trackingNode.readProperties(props);
 
     BOOST_FOREACH(const StringPair &mapping, props) {
@@ -861,5 +869,167 @@ void SyncSourceLogging::init(const std::list<std::string> &fields,
                                    this, _1, ops.m_deleteItem);
 }
 
+sysync::TSyError SyncSourceAdmin::loadAdminData(const char *aLocDB,
+                                                const char *aRemDB,
+                                                char **adminData)
+{
+    std::string data = m_configNode->readProperty(m_adminPropertyName);
+    *adminData = StrAlloc(SafeConfigNode::unescape(data).c_str());
+    resetMap();
+    return sysync::LOCERR_OK;
+}
+
+sysync::TSyError SyncSourceAdmin::saveAdminData(const char *adminData)
+{
+    m_configNode->setProperty(m_adminPropertyName,
+                              SafeConfigNode::escape(adminData, false, false));
+
+    // Flush here, because some calls to saveAdminData() happend
+    // after SyncSourceAdmin::flush() (= session end).
+    m_configNode->flush();
+    return sysync::LOCERR_OK;
+}
+
+bool SyncSourceAdmin::readNextMapItem(sysync::MapID mID, bool aFirst)
+{
+    if (aFirst) {
+        resetMap();
+    }
+    if (m_mappingIterator != m_mapping.end()) {
+        entry2mapid(m_mappingIterator->first, m_mappingIterator->second, mID);
+        ++m_mappingIterator;
+        return true;
+    } else {
+        return false;
+    }
+}
+
+sysync::TSyError SyncSourceAdmin::insertMapItem(sysync::cMapID mID)
+{
+    string key, value;
+    mapid2entry(mID, key, value);
+
+#if 0
+    StringMap::iterator it = m_mapping.find(key);
+    if (it != m_mapping.end()) {
+        // error, exists already
+        return sysync::DB_Forbidden;
+    } else {
+        m_mapping[key] = value;
+        return sysync::LOCERR_OK;
+    }
+#else
+    m_mapping[key] = value;
+    m_mappingNode->clear();
+    m_mappingNode->writeProperties(m_mapping);
+    m_mappingNode->flush();
+    return sysync::LOCERR_OK;
+#endif
+}
+
+sysync::TSyError SyncSourceAdmin::updateMapItem(sysync::cMapID mID)
+{
+    string key, value;
+    mapid2entry(mID, key, value);
+
+    StringMap::iterator it = m_mapping.find(key);
+    if (it == m_mapping.end()) {
+        // error, does not exist
+        return sysync::DB_Forbidden;
+    } else {
+        m_mapping[key] = value;
+        m_mappingNode->clear();
+        m_mappingNode->writeProperties(m_mapping);
+        m_mappingNode->flush();
+        return sysync::LOCERR_OK;
+    }
+}
+
+sysync::TSyError SyncSourceAdmin::deleteMapItem(sysync::cMapID mID)
+{
+    string key, value;
+    mapid2entry(mID, key, value);
+
+    StringMap::iterator it = m_mapping.find(key);
+    if (it == m_mapping.end()) {
+        // error, does not exist
+        return sysync::DB_Forbidden;
+    } else {
+        m_mapping.erase(it);
+        m_mappingNode->clear();
+        m_mappingNode->writeProperties(m_mapping);
+        m_mappingNode->flush();
+        return sysync::LOCERR_OK;
+    }
+}
+
+void SyncSourceAdmin::flush()
+{
+    m_configNode->flush();
+    m_mappingNode->clear();
+    m_mappingNode->writeProperties(m_mapping);
+    m_mappingNode->flush();
+}
+
+void SyncSourceAdmin::resetMap()
+{
+    m_mapping.clear();
+    m_mappingNode->readProperties(m_mapping);
+    m_mappingIterator = m_mapping.begin();
+}
+
+
+void SyncSourceAdmin::mapid2entry(sysync::cMapID mID, string &key, string &value)
+{
+    key = SafeConfigNode::escape(mID->localID ? mID->localID : "", true, false);
+    value = StringPrintf("%s %x %x",
+                         SafeConfigNode::escape(mID->remoteID ? mID->remoteID : "", true, false).c_str(),
+                         mID->flags, mID->ident);
+}
+
+void SyncSourceAdmin::entry2mapid(const string &key, const string &value, sysync::MapID mID)
+{
+    mID->localID = StrAlloc(SafeConfigNode::unescape(key).c_str());
+    std::vector< std::string > tokens;
+    boost::split(tokens, value, boost::is_from_range(' ', ' '));
+    mID->remoteID = tokens.size() > 0 ? StrAlloc(tokens[0].c_str()) : NULL;
+    mID->flags = tokens.size() > 1 ? strtol(tokens[1].c_str(), NULL, 16) : 0;
+    mID->ident = tokens.size() > 2 ? strtol(tokens[2].c_str(), NULL, 16) : 0;
+}
+
+void SyncSourceAdmin::init(SyncSource::Operations &ops,
+                           const boost::shared_ptr<ConfigNode> &config,
+                           const std::string adminPropertyName,
+                           const boost::shared_ptr<ConfigNode> &mapping)
+{
+    m_configNode = config;
+    m_adminPropertyName = adminPropertyName;
+    m_mappingNode = mapping;
+
+    ops.m_loadAdminData = boost::bind(&SyncSourceAdmin::loadAdminData,
+                                      this, _1, _2, _3);
+    ops.m_saveAdminData = boost::bind(&SyncSourceAdmin::saveAdminData,
+                                      this, _1);
+    ops.m_readNextMapItem = boost::bind(&SyncSourceAdmin::readNextMapItem,
+                                        this, _1, _2);
+    ops.m_insertMapItem = boost::bind(&SyncSourceAdmin::insertMapItem,
+                                      this, _1);
+    ops.m_updateMapItem = boost::bind(&SyncSourceAdmin::updateMapItem,
+                                      this, _1);
+    ops.m_deleteMapItem = boost::bind(&SyncSourceAdmin::deleteMapItem,
+                                      this, _1);
+    ops.m_endSession.push_back(boost::bind(&SyncSourceAdmin::flush,
+                                           this));
+}
+
+void SyncSourceAdmin::init(SyncSource::Operations &ops,
+                           SyncSource *source)
+{
+    init(ops,
+         source->getProperties(true),
+         SourceAdminDataName,
+         source->getServerNode());
+}
 
 SE_END_CXX
+
index 8e97dd6..2819578 100644 (file)
@@ -44,40 +44,15 @@ struct SyncSourceParams {
     /**
      * @param    name        the name needed by SyncSource
      * @param    nodes       a set of config nodes to be used by this source
-     * @param    changeId    a unique string constructed from an ID for SyncEvolution
-     *                       and the URL/database we synchronize against; can be
-     *                       used to do change tracking for that combination of
-     *                       peers
      */
     SyncSourceParams(const string &name,
-                     const SyncSourceNodes &nodes,
-                     const string &changeId) :
-    m_name(name),
-        m_nodes(nodes),
-        m_changeId(stripChangeId(changeId))
+                     const SyncSourceNodes &nodes = SyncSourceNodes()) :
+        m_name(name),
+        m_nodes(nodes)
     {}
 
-    const string m_name;
-    const SyncSourceNodes m_nodes;
-    const string m_changeId;
-
-    /** remove special characters from change ID */
-    static string stripChangeId(const string changeId) {
-        string strippedChangeId = changeId;
-        size_t offset = 0;
-        while (offset < strippedChangeId.size()) {
-            switch (strippedChangeId[offset]) {
-            case ':':
-            case '/':
-            case '\\':
-                strippedChangeId.erase(offset, 1);
-                break;
-            default:
-                offset++;
-            }
-        }
-        return strippedChangeId;
-    }
+    string m_name;
+    SyncSourceNodes m_nodes;
 };
 
 /**
@@ -412,14 +387,12 @@ struct ClientTestConfig{
  * exchange format can register one configuration for each format, but
  * not registering any configuration is also okay.
  *
- * *Using* the registered tests depends on the CPPUnit test framework.
- * *Registering* does not. Therefore backends should always register *
- * *themselves for testing and leave it to the test runner
- * "client-test" whether tests are really executed.
- *
- * Unit tests are different. They create hard dependencies on CPPUnit
- * inside the code that contains them, and thus should be encapsulated
- * inside #ifdef ENABLE_UNIT_TESTS checks.
+ * This code depends on the C++ client library test framework and
+ * therefore CPPUnit. To avoid a hard dependency on that in the normal
+ * "syncevolution" binary, the actual usage of the test Config class
+ * is limited to the *Register.cpp files when compiling them for
+ * inclusion in the "client-test" binary, i.e., they are protected by
+ * #ifdef ENABLE_UNIT_TESTS.
  *
  * Sync sources have to work stand-alone without a full SyncClient
  * configuration for all local tests. The minimal configuration prepared
@@ -658,6 +631,12 @@ class SyncSourceBase : public Logger {
      */
     virtual SDKInterface *getSynthesisAPI() const = 0;
 
+    /**
+     * Prepare the sync source for usage inside a SyncML server.  To
+     * be called directly after creating the source, if at all.
+     */
+    virtual void enableServerMode() = 0;
+    virtual bool serverModeEnabled() const = 0;
 
  protected:
     struct SynthesisInfo {
@@ -864,6 +843,41 @@ class SyncSource : virtual public SyncSourceBase, public SyncSourceConfig, publi
         typedef sysync::TSyError (DeleteItem_t)(sysync::cItemID aID);
         boost::function<DeleteItem_t> m_deleteItem;
         /**@}*/
+
+
+        /**
+         * Synthesis administration callbacks. For documentation see the
+         * Synthesis API specification (PDF and/or sync_dbapi.h).
+         *
+         * Implementing this is *optional* in clients. In the Synthesis client
+         * engine, the "binfiles" module provides these calls without SyncEvolution
+         * doing anything.
+         *
+         * In the Synthesis server engine, the
+         * SyncSource::enableServerMode() call must install an
+         * implementation, like the one from SyncSourceAdmin.
+         */
+        /**@{*/
+        typedef sysync::TSyError (LoadAdminData_t)(const char *aLocDB,
+                                                   const char *aRemDB,
+                                                   char **adminData);
+        boost::function<LoadAdminData_t> m_loadAdminData;
+
+        typedef sysync::TSyError (SaveAdminData_t)(const char *adminData);
+        boost::function<SaveAdminData_t> m_saveAdminData;
+
+        typedef bool (ReadNextMapItem_t)(sysync::MapID mID, bool aFirst);
+        boost::function<ReadNextMapItem_t> m_readNextMapItem;
+
+        typedef sysync::TSyError (InsertMapItem_t)(sysync::cMapID mID);
+        boost::function<InsertMapItem_t> m_insertMapItem;
+
+        typedef sysync::TSyError (UpdateMapItem_t)(sysync::cMapID mID);
+        boost::function<UpdateMapItem_t> m_updateMapItem;
+
+        typedef sysync::TSyError (DeleteMapItem_t)(sysync::cMapID mID);
+        boost::function<DeleteMapItem_t> m_deleteMapItem;
+        /**@}*/
     };
     const Operations &getOperations() { return m_operations; }
         
@@ -932,6 +946,12 @@ class SyncSource : virtual public SyncSourceBase, public SyncSourceConfig, publi
      */
     static string backendsDebug();
 
+    /**
+     * Mime type a backend provides by default, this is used to alert the
+     * remote peer in SAN during server alerted sync.
+     */
+    virtual const char *getPeerMimeType() const =0;
+
     /* implementation of SyncSourceBase */
     virtual const char * getName() const { return SyncSourceConfig::getName(); }
     virtual long getNumDeleted() const { return m_numDeleted; }
@@ -962,6 +982,85 @@ class SyncSource : virtual public SyncSourceBase, public SyncSourceConfig, publi
 };
 
 /**
+ * A SyncSource with no pure virtual functions.
+ */
+class DummySyncSource : public SyncSource
+{
+ public:
+    DummySyncSource(const SyncSourceParams &params) :
+       SyncSource(params) {}
+
+    DummySyncSource(const std::string &name) :
+       SyncSource(SyncSourceParams(name)) {}
+
+    virtual Databases getDatabases() { return Databases(); }
+    virtual void open() {}
+    virtual void close() {}
+    virtual void getSynthesisInfo(SynthesisInfo &info,
+                                  XMLConfigFragments &fragments) {}
+    virtual void enableServerMode() {}
+    virtual bool serverModeEnabled() const { return false; }
+    virtual const char *getPeerMimeType() const {return "";} 
+};
+
+/**
+ * Virtual SyncSources
+ */
+class VirtualSyncSource : public DummySyncSource 
+{
+public:
+    VirtualSyncSource(const SyncSourceParams &params) :
+       DummySyncSource(params) {}
+
+    std::string getDataTypeSupport() {
+        string datatypes;
+        SourceType sourceType = getSourceType();
+        string type = sourceType.m_format;
+
+        if (type.empty()) {
+            return "";
+        } else if (type == "text/x-vcard:2.1" || type == "text/x-vcard") {
+            datatypes =
+                "        <use datatype='vCard21' mode='rw' preferred='yes'/>\n";
+            if (!sourceType.m_forceFormat) {
+                datatypes +=
+                    "        <use datatype='vCard30' mode='rw'/>\n";
+            }
+        } else if (type == "text/vcard:3.0" || type == "text/vcard") {
+            datatypes =
+                "        <use datatype='vCard30' mode='rw' preferred='yes'/>\n";
+            if (!sourceType.m_forceFormat) {
+                datatypes +=
+                    "        <use datatype='vCard21' mode='rw'/>\n";
+            }
+        } else if (type == "text/x-vcalendar:1.0" || type == "text/x-vcalendar" 
+                  || type == "text/x-calendar:1.0" || type == "text/x-calendar") {
+            datatypes =
+                "        <use datatype='vcalendar10' mode='rw' preferred='yes'/>\n";
+            if (!sourceType.m_forceFormat) {
+                datatypes +=
+                    "        <use datatype='icalendar20' mode='rw'/>\n";
+            }
+        } else if (type == "text/calendar:2.0" || type == "text/calendar") {
+            datatypes =
+                "        <use datatype='icalendar20' mode='rw' preferred='yes'/>\n";
+            if (!sourceType.m_forceFormat) {
+                datatypes +=
+                    "        <use datatype='vcalendar10' mode='rw'/>\n";
+            }
+        } else if (type == "text/plain:1.0" || type == "text/plain") {
+            // note10 are the same as note11, so ignore force format
+            datatypes =
+                "        <use datatype='note10' mode='rw' preferred='yes'/>\n"
+                "        <use datatype='note11' mode='rw'/>\n";
+        } else {
+            throwError(string("configured MIME type not supported: ") + type);
+        }
+        return datatypes;
+    }
+};
+
+/**
  * Hooks up the Synthesis DB Interface start sync (BeginDataRead) and
  * end sync (EndDataWrite) calls with virtual methods. Ensures that
  * sleepSinceModification() is called.
@@ -1406,6 +1505,47 @@ class SyncSourceLogging : public virtual SyncSourceBase
                                 const boost::function<SyncSource::Operations::DeleteItem_t> &parent);
 };
 
+/**
+ * Implements Load/SaveAdminData and MapItem handling in a SyncML
+ * server. Uses a single property for the admin data in the "internal"
+ * node and a complete node for the map items.
+ */
+class SyncSourceAdmin : public virtual SyncSourceBase
+{
+    boost::shared_ptr<ConfigNode> m_configNode;
+    std::string m_adminPropertyName;
+    boost::shared_ptr<ConfigNode> m_mappingNode;
+
+    ConfigProps m_mapping;
+    ConfigProps::const_iterator m_mappingIterator;
+
+    sysync::TSyError loadAdminData(const char *aLocDB,
+                                   const char *aRemDB,
+                                   char **adminData);
+    sysync::TSyError saveAdminData(const char *adminData);
+    bool readNextMapItem(sysync::MapID mID, bool aFirst);
+    sysync::TSyError insertMapItem(sysync::cMapID mID);
+    sysync::TSyError updateMapItem(sysync::cMapID mID);
+    sysync::TSyError deleteMapItem(sysync::cMapID mID);
+    void flush();
+
+    void resetMap();
+    void mapid2entry(sysync::cMapID mID, string &key, string &value);
+    void entry2mapid(const string &key, const string &value, sysync::MapID mID);
+
+ public:
+    /** flexible initialization */
+    void init(SyncSource::Operations &ops,
+              const boost::shared_ptr<ConfigNode> &config,
+              const std::string adminPropertyName,
+              const boost::shared_ptr<ConfigNode> &mapping);
+
+    /**
+     * simpler initialization, using the default placement of data
+     * inside the SyncSourceConfig base class
+     */
+    void init(SyncSource::Operations &ops, SyncSource *source);
+};
 
 /**
  * This is an interface definition that is expected by the client-test
index f487e6f..0f8b4c6 100644 (file)
@@ -52,7 +52,7 @@ static SyncSource *MoC(CContext mContext) { return (SyncSource *)mContext; }
 /**
  * looks up datasource and uses pointer to it as context
  *
- * @param mContextName   name of previously instantiated SyncSource
+ * @param mContextName   name of previously instantiated SyncSource, "" when used as session module
  * @retval mContext      the corresponding SyncSource
  */
 extern "C"
@@ -62,17 +62,20 @@ TSyError SyncEvolution_Module_CreateContext( CContext *mContext, cAppCharP   mod
                                              DB_Callback mCB )
 {
     TSyError err = LOCERR_WRONGUSAGE;
-    SyncSource *source = SyncContext::findSource(mContextName);
-    if (source) {
-        source->pushSynthesisAPI(mCB);
-        *mContext = (CContext)source;
+    if (!mContextName[0]) {
+        *mContext = NULL;
         err = LOCERR_OK;
+    } else {
+        SyncSource *source = SyncContext::findSource(mContextName);
+        if (source) {
+            source->pushSynthesisAPI(mCB);
+            *mContext = (CContext)source;
+            err = LOCERR_OK;
+        }
     }
 
-    DEBUG_DB(mCB, MyDB,  Mo_CC, "'%s%s%s' (%s) => %d",
-             moduleName, subName[0] ? "/" : "", subName, 
-             mContextName,
-             err);
+    SE_LOG_DEBUG(NULL, NULL, "CreateContext %s/%s/%s => %d",
+                 moduleName, subName, mContextName, err);
     return err;
 }
 
@@ -87,7 +90,7 @@ CVersion SyncEvolution_Module_Version(CContext mContext)
     CVersion v = Plugin_Version(BuildNumber);
   
     if (mContext) {
-        DEBUG_DB(MoC(mContext)->getSynthesisAPI(), MyDB,Mo_Ve, "%08X", v);
+        SE_LOG_DEBUG(NULL, NULL, "Module_Version = %08lx", (long)v);
     }
     return v;
 }
@@ -98,6 +101,8 @@ CVersion SyncEvolution_Module_Version(CContext mContext)
 extern "C"
 TSyError SyncEvolution_Module_Capabilities( CContext mContext, appCharP *mCapabilities )
 {
+    SyncSource *source  = MoC(mContext);
+
     std::stringstream s;
     s << MyPlatform() << "\n"
       << DLL_Info << "\n"
@@ -108,8 +113,13 @@ TSyError SyncEvolution_Module_Capabilities( CContext mContext, appCharP *mCapabi
       << Plugin_DS_Data_Key << ":yes\n"
       << CA_ItemAsKey << ":yes\n"
       << Plugin_DS_Blob << ":no\n";
+
+    if (source && source->getOperations().m_loadAdminData) {
+        s << Plugin_DS_Admin << ":yes\n";
+    }
+
     *mCapabilities= StrAlloc(s.str().c_str());
-    DEBUG_DB(MoC(mContext)->getSynthesisAPI(), MyDB, Mo_Ca, "'%s'", *mCapabilities);
+    SE_LOG_DEBUG(NULL, NULL, "Module_Capabilities:\n%s", *mCapabilities);
     return LOCERR_OK;
 } /* Module_Capabilities */
 
@@ -120,9 +130,8 @@ TSyError SyncEvolution_Module_PluginParams( CContext mContext,
                                             cAppCharP mConfigParams, CVersion engineVersion )
 {
     SyncSource *source  = MoC(mContext);
-    DEBUG_DB(source->getSynthesisAPI(), MyDB, Mo_PP, " Engine=%08X", engineVersion);
-    DEBUG_DB(source->getSynthesisAPI(), MyDB, Mo_PP, "'%s'",         mConfigParams );
-  
+    SE_LOG_DEBUG(source, NULL, "Module_PluginParams\n Engine=%08lX\n %s",
+                 (long)engineVersion, mConfigParams);
     /*return LOCERR_CFGPARSE;*/ /* if there are unsupported params */
     return LOCERR_OK;
 } /* Module_PluginParams */
@@ -133,8 +142,6 @@ TSyError SyncEvolution_Module_PluginParams( CContext mContext,
 extern "C"
 void SyncEvolution_Module_DisposeObj( CContext mContext, void* memory )
 {
-    DEBUG_Exotic_DB(MoC(mContext)->getSynthesisAPI(), MyDB, Mo_DO,
-                    "free at %08X '%s'", memory, memory);
     StrDispose(memory);
 }
 
@@ -142,51 +149,32 @@ extern "C"
 TSyError SyncEvolution_Module_DeleteContext( CContext mContext )
 {
     SyncSource  *source = MoC(mContext);
-    DEBUG_DB(source->getSynthesisAPI(), MyDB, Mo_DC, "'%s'", source->getName());
-    source->popSynthesisAPI();
+    SE_LOG_DEBUG(NULL, NULL, "Module_DeleteContext %s",
+                 source ? source->getName() : "'session'");
+    if (source) {
+        source->popSynthesisAPI();
+    }
     return LOCERR_OK;
 }
 
 
+/* <sContext> will be casted to the SyncContext* structure */
+static SyncContext* SeC( CContext sContext ) { return (SyncContext*)sContext; }
 
 
-/* ---------------------- session handling --------------------- */
-/* this is an example, how a context could be structured */
-class SessionContext {
-public:
-    SessionContext() { fCB= NULL; }
-    
-    int         fID; /* a reference number. */
-    DB_Callback fCB; /* callback structure  */
-    int      fPMode; /* The login password mode */
-};
-
-/* <sContext> will be casted to the SessionContext* structure */
-static SessionContext* SeC( CContext sContext ) { return (SessionContext*)sContext; }
 
-
-
-/* Create a context for a new session */ 
+/* Create a context for a new session. Maps to the existing SyncContext. */ 
 extern "C"
 TSyError SyncEvolution_Session_CreateContext( CContext *sContext, cAppCharP sessionName, DB_Callback sCB )
 { 
-  SessionContext* sc;
-  
-/*return DB_Error;*/ /* added for test */
-  
-  sc= new SessionContext;
-
-  if (sc==NULL) return DB_Full;
-
-  /**** CAN BE ADAPTED BY USER ****/
-            sc->fID= 333; /* as an example */
-            sc->fCB= sCB;
-            sc->fPMode= Password_ClrText_IN;        /* take this mode ... */
-         /* sc->fPMode= Password_ClrText_OUT; */    /* ... or this        */
-  DEBUG_DB( sc->fCB, MyDB,Se_CC, "%d '%s'", sc->fID,sessionName );
-  
-  *sContext= (CContext)sc; /* return the created context structure */
-  return LOCERR_OK;
+    *sContext = (CContext)SyncContext::findContext(sessionName);
+    SE_LOG_DEBUG(NULL, NULL, "Session_CreateContext '%s' %s", 
+                 sessionName, *sContext ? "found" : "not found");
+    if (*sContext) {
+        return LOCERR_OK;
+    } else {
+        return DB_NotFound;
+    }
 } /* Session_CreateContext */
 
 
@@ -198,11 +186,11 @@ TSyError SyncEvolution_Session_AdaptItem( CContext sContext, appCharP *sItemData
                                           appCharP *sLocalVars, 
                                           uInt32  sIdentifier ) 
 { 
-  /**** CAN BE ADAPTED BY USER ****/ 
-  SessionContext* sc= SeC( sContext );
-  DEBUG_DB      ( sc->fCB, MyDB,"Session_AdaptItem", "'%s' '%s' '%s' id=%d", 
-                                *sItemData1,*sItemData2,*sLocalVars, sIdentifier );
-  return LOCERR_OK;
+    /**** CAN BE ADAPTED BY USER ****/ 
+    // SyncContext* sc= SeC( sContext );
+    SE_LOG_DEBUG(NULL, NULL, "Session_AdaptItem '%s' '%s' '%s' id=%d", 
+                 *sItemData1,*sItemData2,*sLocalVars, sIdentifier);
+    return LOCERR_OK;
 } /* Session_AdaptItem */
 
 
@@ -213,13 +201,29 @@ TSyError SyncEvolution_Session_CheckDevice( CContext sContext,
                                             cAppCharP aDeviceID, appCharP *sDevKey,
                                             appCharP *nonce )
 {
-  /**** CAN BE ADAPTED BY USER ****/
-  SessionContext* sc= SeC( sContext );
-  
-  *sDevKey= StrAlloc( aDeviceID  );
-  *nonce  = StrAlloc( "xyz_last" );
-  DEBUG_DB( sc->fCB, MyDB,Se_CD, "%d dev='%s' nonce='%s'", sc->fID, *sDevKey,*nonce );
-  return LOCERR_OK;
+    SyncContext *sc = SeC(sContext);
+    if (!sc) {
+        return LOCERR_WRONGUSAGE;
+    }
+    TSyError res = LOCERR_OK;
+
+    sc->setSyncDeviceID(aDeviceID);
+    string id = sc->getRemoteDevID();
+    if (id.empty()) {
+        sc->setRemoteDevID(aDeviceID);
+        sc->flush();
+    } else if (id != aDeviceID) {
+        // We are using the wrong configuration?! Refuse to continue.
+        SE_LOG_ERROR(NULL, NULL, "remote device ID '%s' in config does not match the one from the peer '%s' - incorrect configuration?!",
+                     id.c_str(), aDeviceID);
+        res = DB_Forbidden;
+    }
+
+    *sDevKey= StrAlloc(aDeviceID);
+    *nonce = StrAlloc(sc->getNonce().c_str());
+    SE_LOG_DEBUG(NULL, NULL, "Session_CheckDevice dev='%s' nonce='%s' res=%d",
+                 *sDevKey, *nonce, res);
+    return res;
 } /* Session_CheckDevice */
 
 
@@ -230,11 +234,7 @@ TSyError SyncEvolution_Session_CheckDevice( CContext sContext,
 extern "C"
 TSyError SyncEvolution_Session_GetNonce( CContext sContext, appCharP *nonce )
 {
-  /**** CAN BE ADAPTED BY USER ****/
-  SessionContext* sc= SeC( sContext );
-  DEBUG_DB      ( sc->fCB, MyDB,Se_GN, "%d (not supported)", sc->fID );
-  *nonce= NULL;
-  return DB_NotFound;
+    return DB_NotFound;
 } /* Session_GetNonce */
 
  
@@ -245,10 +245,15 @@ TSyError SyncEvolution_Session_GetNonce( CContext sContext, appCharP *nonce )
 extern "C"
 TSyError SyncEvolution_Session_SaveNonce( CContext sContext, cAppCharP nonce )
 {
-  /**** CAN BE ADAPTED BY USER ****/
-  SessionContext* sc= SeC( sContext );
-  DEBUG_DB      ( sc->fCB, MyDB,Se_SN, "%d nonce='%s'", sc->fID, nonce );
-  return LOCERR_OK;
+    SyncContext *sc = SeC(sContext);
+    if (!sc) {
+        return LOCERR_WRONGUSAGE;
+    }
+    SE_LOG_DEBUG(NULL, NULL, "Session_SaveNonce nonce='%s'",
+                 nonce);
+    sc->setNonce(nonce);
+    sc->flush();
+    return LOCERR_OK;
 } /* Session_SaveNonce */
 
 
@@ -257,10 +262,15 @@ TSyError SyncEvolution_Session_SaveNonce( CContext sContext, cAppCharP nonce )
 extern "C"
 TSyError SyncEvolution_Session_SaveDeviceInfo( CContext sContext, cAppCharP aDeviceInfo )
 {
-  /**** CAN BE ADAPTED BY USER ****/
-  SessionContext* sc= SeC( sContext );
-  DEBUG_DB      ( sc->fCB, MyDB,Se_SD, "%d info='%s'", sc->fID, aDeviceInfo );
-  return LOCERR_OK;
+    SyncContext *sc = SeC(sContext);
+    if (!sc) {
+        return LOCERR_WRONGUSAGE;
+    }
+    SE_LOG_DEBUG(NULL, NULL, "Session_SaveDeviceInfo info='%s'",
+                 aDeviceInfo );
+    sc->setDeviceData(aDeviceInfo);
+    sc->flush();
+    return LOCERR_OK;
 } /* Session_SaveDeviceInfo */
 
 
@@ -269,11 +279,7 @@ TSyError SyncEvolution_Session_SaveDeviceInfo( CContext sContext, cAppCharP aDev
 extern "C"
 TSyError SyncEvolution_Session_GetDBTime( CContext sContext, appCharP *currentDBTime )
 { 
-  /**** CAN BE ADAPTED BY USER ****/
-  SessionContext* sc= SeC( sContext );
-  DEBUG_DB      ( sc->fCB, MyDB,Se_GT, "%d", sc->fID );
-  *currentDBTime= NULL;
-  return DB_NotFound;
+    return DB_NotFound;
 } /* Session_GetDBTime */
 
 
@@ -286,10 +292,7 @@ TSyError SyncEvolution_Session_GetDBTime( CContext sContext, appCharP *currentDB
 extern "C"
 sInt32 SyncEvolution_Session_PasswordMode( CContext sContext )
 {
-  /**** CAN BE ADAPTED BY USER ****/
-  SessionContext* sc= SeC( sContext );
-  DEBUG_DB      ( sc->fCB, MyDB,Se_PM, "%d mode=%d", sc->fID, sc->fPMode );
-  return          sc->fPMode;
+    return Password_ClrText_OUT;
 } /* Session_PasswordMode */
 
 
@@ -299,25 +302,25 @@ extern "C"
 TSyError SyncEvolution_Session_Login( CContext sContext, cAppCharP sUsername, appCharP *sPassword,
                                       appCharP *sUsrKey )
 { 
-  /**** CAN BE ADAPTED BY USER ****/
-  SessionContext* sc= SeC( sContext );
-  TSyError       err= DB_Forbidden; /* default */
-  
-  /* different modes, choose one for the plugin */
-  if (sc->fPMode==Password_ClrText_IN) {
-    if (strcmp(  sUsername,"super" )==0 &&
-        strcmp( *sPassword,"user"  )==0) { *sUsrKey  = StrAlloc( "1234" ); err= LOCERR_OK; }
-  }
-  else {       /* Password will be returned */
-    if (strcmp(  sUsername,"super" )==0) { *sPassword= StrAlloc( "user" );
-                                           *sUsrKey  = StrAlloc( "1234" ); err= LOCERR_OK; }
-  } /* if */
-
-  if (err) { DEBUG_DB( sc->fCB, MyDB,Se_LI, "%d usr='%s' err=%d",
-                                             sc->fID,sUsername, err ); }
-  else       DEBUG_DB( sc->fCB, MyDB,Se_LI, "%d usr='%s' pwd='%s' => key='%s'", 
-                                             sc->fID,sUsername,*sPassword, *sUsrKey );
-  return err;
+    SyncContext *sc = SeC(sContext);
+    if (!sc) {
+        return LOCERR_WRONGUSAGE;
+    }
+    TSyError res = DB_Forbidden;
+    string user = sc->getUsername();
+    string password = sc->getPassword();
+
+    if (user.empty() && password.empty()) {
+        // nothing to check, accept peer
+        res = LOCERR_OK;
+    } else if (user == sUsername) {
+        *sPassword=StrAlloc(password.c_str());
+        res = LOCERR_OK;
+    }
+
+    SE_LOG_DEBUG(NULL, NULL, "Session_Login usr='%s' expected user='%s' res=%d",
+                 sUsername, user.c_str(), res);
+    return res;
 } /* Session_Login */
 
 
@@ -326,10 +329,7 @@ TSyError SyncEvolution_Session_Login( CContext sContext, cAppCharP sUsername, ap
 extern "C"
 TSyError SyncEvolution_Session_Logout( CContext sContext )
 {
-  /**** CAN BE ADAPTED BY USER ****/ 
-  SessionContext* sc= SeC( sContext );
-  DEBUG_DB      ( sc->fCB, MyDB,Se_LO, "%d",sc->fID );
-  return LOCERR_OK;
+    return LOCERR_OK;
 } /* Session_Logout */
 
 
@@ -337,10 +337,6 @@ TSyError SyncEvolution_Session_Logout( CContext sContext )
 extern "C"
 void SyncEvolution_Session_DisposeObj( CContext sContext, void* memory )
 {
-  /**** CAN BE ADAPTED BY USER ****/ 
-  SessionContext*  sc= SeC( sContext );
-  DEBUG_Exotic_DB( sc->fCB, MyDB,Se_DO, "%d free at %08X '%s'",
-                   sc->fID, memory,memory );
   StrDispose              ( memory );
 } /* Session_DisposeObj */
 
@@ -350,9 +346,6 @@ void SyncEvolution_Session_DisposeObj( CContext sContext, void* memory )
 extern "C"
 void SyncEvolution_Session_ThreadMayChangeNow( CContext sContext )
 {
-  /**** CAN BE ADAPTED BY USER ****/ 
-  SessionContext*  sc= SeC( sContext );
-  DEBUG_Exotic_DB( sc->fCB, MyDB,Se_TC, "%d",sc->fID );
 } /* Session_ThreadMayChangeNow */
 
 
@@ -363,10 +356,6 @@ void SyncEvolution_Session_ThreadMayChangeNow( CContext sContext )
 extern "C"
 void SyncEvolution_Session_DispItems( CContext sContext, bool allFields, cAppCharP specificItem )
 {
-  /**** CAN BE ADAPTED BY USER ****/ 
-  SessionContext* sc= SeC( sContext );
-  DEBUG_DB      ( sc->fCB, MyDB,Se_DI, "%d %d '%s'",
-                  sc->fID, allFields,specificItem );
 } /* Session_DispItems */
 
 
@@ -375,13 +364,7 @@ void SyncEvolution_Session_DispItems( CContext sContext, bool allFields, cAppCha
 extern "C"
 TSyError SyncEvolution_Session_DeleteContext( CContext sContext ) 
 { 
-  /**** CAN BE ADAPTED BY USER ****/ 
-  SessionContext* sc= SeC( sContext );
-  DEBUG_DB      ( sc->fCB, MyDB,Se_DC, "%d",sc->fID );
-
-  delete sc;
-
-  return LOCERR_OK;
+    return LOCERR_OK;
 } /* Session_DeleteContext */
 
 
@@ -413,8 +396,8 @@ TSyError SyncEvolution_CreateContext( CContext *aContext, cAppCharP aContextName
         *aContext = (CContext)source;
         err = LOCERR_OK;
     }
-    DEBUG_DB( aCB, MyDB,Da_CC, "'%s' dev='%s' usr='%s'",
-              aContextName, sDevKey, sUsrKey ); 
+    SE_LOG_DEBUG(source, NULL, "'%s' dev='%s' usr='%s' err=%d",
+                 aContextName, sDevKey, sUsrKey, err);
     return err;
 }
 
@@ -424,7 +407,10 @@ extern "C"
 uInt32 SyncEvolution_ContextSupport( CContext aContext, cAppCharP aContextRules ) 
 {
     SyncSource *source = DBC( aContext );
-    DEBUG_DB( source->getSynthesisAPI(), MyDB,Da_CS, "%s '%s'", source->getName(),aContextRules );
+    if (!source) {
+        return LOCERR_WRONGUSAGE;
+    }
+    SE_LOG_DEBUG(source, NULL, "ContextSupport %s", aContextRules);
     return 0;
 }
 
@@ -435,7 +421,10 @@ uInt32 SyncEvolution_FilterSupport( CContext aContext, cAppCharP aFilterRules )
 {
   /**** CAN BE ADAPTED BY USER ****/ 
   SyncSource *source = DBC( aContext );
-  DEBUG_DB( source->getSynthesisAPI(), MyDB,Da_FS, "%s '%s'", source->getName(),aFilterRules );
+  if (!source) {
+      return LOCERR_WRONGUSAGE;
+  }
+  SE_LOG_DEBUG(source, NULL, "FilterSupport %s", aFilterRules);
   return 0;
 } /* FilterSupport */
 
@@ -446,12 +435,22 @@ extern "C"
 TSyError SyncEvolution_LoadAdminData( CContext aContext, cAppCharP aLocDB,
                                       cAppCharP aRemDB, appCharP *adminData )
 {
-  /**** CAN BE ADAPTED BY USER ****/ 
-  SyncSource *source = DBC( aContext );
-  DEBUG_DB( source->getSynthesisAPI(), MyDB,Da_LA, "%s '%s' '%s'",
-            source->getName(), aLocDB, aRemDB );
-  *adminData= NULL;
-  return DB_Forbidden; /* not yet implemented */
+    SyncSource *source = DBC( aContext );
+    if (!source) {
+        return LOCERR_WRONGUSAGE;
+    }
+    TSyError res = DB_Forbidden;
+    try {
+        if (source->getOperations().m_loadAdminData) {
+            res = source->getOperations().m_loadAdminData(aLocDB, aRemDB, adminData);
+        }
+    } catch (...) {
+        res = source->handleException();
+    }
+
+    SE_LOG_DEBUG(source, NULL, "LoadAdminData '%s' '%s', res=%d",
+                 aLocDB, aRemDB, res);
+    return res;
 } /* LoadAdminData */
 
 
@@ -459,10 +458,21 @@ TSyError SyncEvolution_LoadAdminData( CContext aContext, cAppCharP aLocDB,
 extern "C"
 TSyError SyncEvolution_SaveAdminData( CContext aContext, cAppCharP adminData )
 {
-  /**** CAN BE ADAPTED BY USER ****/ 
-  SyncSource *source = DBC( aContext );
-  DEBUG_DB( source->getSynthesisAPI(), MyDB,Da_SA, "%s '%s'", source->getName(), adminData );
-  return DB_Forbidden; /* not yet implemented */
+    SyncSource *source = DBC( aContext );
+    if (!source) {
+        return LOCERR_WRONGUSAGE;
+    }
+    TSyError res = DB_Forbidden;
+    try {
+        if (source->getOperations().m_saveAdminData) {
+            res = source->getOperations().m_saveAdminData(adminData);
+        }
+    } catch (...) {
+        res = source->handleException();
+    }
+
+    SE_LOG_DEBUG(source, NULL, "SaveAdminData '%s' res=%d", adminData, res);
+    return res;
 } /* SaveAdminData */
 
 
@@ -470,10 +480,22 @@ TSyError SyncEvolution_SaveAdminData( CContext aContext, cAppCharP adminData )
 extern "C"
 bool SyncEvolution_ReadNextMapItem( CContext aContext, MapID mID, bool aFirst )
 {
-  /**** CAN BE ADAPTED BY USER ****/ 
-  SyncSource *source = DBC( aContext );
-  DEBUG_DB( source->getSynthesisAPI(), MyDB,Da_RM, "%s %08X first=%d (EOF)", source->getName(), mID, aFirst );
-  return false; /* not yet implemented */
+    SyncSource *source = DBC( aContext );
+    if (!source) {
+        return LOCERR_WRONGUSAGE;
+    }
+    bool res = false;
+    try {
+        if (source->getOperations().m_readNextMapItem) {
+            res = source->getOperations().m_readNextMapItem(mID, aFirst);
+        }
+    } catch (...) {
+        res = source->handleException();
+    }
+
+    SE_LOG_DEBUG(source, NULL, "ReadNextMapItem %08lX first=%s res=%d",
+                 (long)mID, aFirst ? "yes" : "no", res);
+    return res;
 } /* ReadNextMapItem */
 
 
@@ -481,11 +503,22 @@ bool SyncEvolution_ReadNextMapItem( CContext aContext, MapID mID, bool aFirst )
 extern "C"
 TSyError SyncEvolution_InsertMapItem( CContext aContext, cMapID mID )
 {
-  /**** CAN BE ADAPTED BY USER ****/ 
-  SyncSource *source = DBC( aContext );
-  DEBUG_DB( source->getSynthesisAPI(), MyDB,Da_IM, "%s %08X: '%s' '%s' %04X %d", 
-                                  source->getName(), mID, mID->localID, mID->remoteID, mID->flags, mID->ident );
-  return DB_Forbidden; /* not yet implemented */
+    SyncSource *source = DBC( aContext );
+    if (!source) {
+        return LOCERR_WRONGUSAGE;
+    }
+    TSyError res = DB_Forbidden;
+    try {
+        if (source->getOperations().m_insertMapItem) {
+            res = source->getOperations().m_insertMapItem(mID);
+        }
+    } catch (...) {
+        res = source->handleException();
+    }
+
+    SE_LOG_DEBUG(source, NULL, "'%s' '%s' %04X %d, res=%d", 
+                 mID->localID, mID->remoteID, mID->flags, mID->ident, res);
+    return res;
 } /* InsertMapItem */
 
 
@@ -493,11 +526,23 @@ TSyError SyncEvolution_InsertMapItem( CContext aContext, cMapID mID )
 extern "C"
 TSyError SyncEvolution_UpdateMapItem( CContext aContext, cMapID mID )
 {
-  /**** CAN BE ADAPTED BY USER ****/ 
-  SyncSource *source = DBC( aContext );
-  DEBUG_DB( source->getSynthesisAPI(), MyDB,Da_UM, "%s %08X: '%s' '%s' %04X %d", 
-                                  source->getName(), mID, mID->localID, mID->remoteID, mID->flags, mID->ident );
-  return DB_Forbidden; /* not yet implemented */
+    SyncSource *source = DBC( aContext );
+    if (!source) {
+        return LOCERR_WRONGUSAGE;
+    }
+    TSyError res = DB_Forbidden;
+    try {
+        if (source->getOperations().m_updateMapItem) {
+            res = source->getOperations().m_updateMapItem(mID);
+        }
+    } catch (...) {
+        res = source->handleException();
+    }
+
+    SE_LOG_DEBUG(source, "UpdateMapItem '%s' '%s' %04X %d, res=%d", 
+                 mID->localID, mID->remoteID, mID->flags, mID->ident, res);
+
+    return res;
 } /* UpdateMapItem */
 
 
@@ -505,11 +550,22 @@ TSyError SyncEvolution_UpdateMapItem( CContext aContext, cMapID mID )
 extern "C"
 TSyError SyncEvolution_DeleteMapItem( CContext aContext, cMapID mID )
 {
-  /**** CAN BE ADAPTED BY USER ****/ 
-  SyncSource *source = DBC( aContext );
-  DEBUG_DB( source->getSynthesisAPI(), MyDB,Da_DM, "%s %08X: '%s' '%s' %04X %d",
-                                  source->getName(), mID, mID->localID, mID->remoteID, mID->flags, mID->ident );
-  return DB_Forbidden; /* not yet implemented */
+    SyncSource *source = DBC( aContext );
+    if (!source) {
+        return LOCERR_WRONGUSAGE;
+    }
+    TSyError res = DB_Forbidden;
+    try {
+        if (source->getOperations().m_deleteMapItem) {
+            res = source->getOperations().m_deleteMapItem(mID);
+        }
+    } catch (...) {
+        res = source->handleException();
+    }
+
+    SE_LOG_DEBUG(source, NULL, "DeleteMapItem '%s' '%s' %04X %d res=%d",
+                 mID->localID, mID->remoteID, mID->flags, mID->ident, res);
+    return res;
 } /* DeleteMapItem */
 
 
@@ -519,9 +575,6 @@ TSyError SyncEvolution_DeleteMapItem( CContext aContext, cMapID mID )
 extern "C"
 void SyncEvolution_DisposeObj( CContext aContext, void* memory )
 {
-  /**** CAN BE ADAPTED BY USER ****/ 
-  SyncSource *source = DBC( aContext );
-  DEBUG_Exotic_DB( source->getSynthesisAPI(), MyDB,Da_DO, "%s free at %08X", source->getName(),memory );
   free( memory );
 } /* DisposeObj */
 
@@ -530,10 +583,6 @@ void SyncEvolution_DisposeObj( CContext aContext, void* memory )
 extern "C"
 void SyncEvolution_ThreadMayChangeNow( CContext aContext )
 {
-  /**** CAN BE ADAPTED BY USER ****/ 
-  /* can be implemented empty, if no action is required */
-  SyncSource *source = DBC( aContext );
-  DEBUG_Exotic_DB( source->getSynthesisAPI(), MyDB,Da_TC, "%s", source->getName() );
 } /* ThreadMayChangeNow */
 
 
@@ -541,10 +590,6 @@ void SyncEvolution_ThreadMayChangeNow( CContext aContext )
 extern "C"
 void SyncEvolution_WriteLogData( CContext aContext, cAppCharP logData )
 {
-  /**** CAN BE ADAPTED BY USER ****/ 
-  SyncSource *source = DBC( aContext );
-  DEBUG_DB( source->getSynthesisAPI(), MyDB, Da_WL, "%s (BEGIN)\n%s", source->getName(), logData );
-  DEBUG_DB( source->getSynthesisAPI(), MyDB, Da_WL, "%s (END)",       source->getName() );
 } /* WriteLogData */
 
 
@@ -555,9 +600,6 @@ void SyncEvolution_WriteLogData( CContext aContext, cAppCharP logData )
 extern "C"
 void SyncEvolution_DispItems( CContext aContext, bool allFields, cAppCharP specificItem )
 {
-  /**** CAN BE ADAPTED BY USER ****/ 
-  SyncSource *source = DBC( aContext );
-  DEBUG_DB( source->getSynthesisAPI(), MyDB,Da_DI, "%s %d '%s'", source->getName(),allFields,specificItem );
 } /* DispItems */
 
 
@@ -571,8 +613,11 @@ TSyError SyncEvolution_AdaptItem( CContext aContext, appCharP *aItemData1,
 { 
   /**** CAN BE ADAPTED BY USER ****/ 
   SyncSource *source = DBC( aContext );
-  DEBUG_DB( source->getSynthesisAPI(), MyDB,"AdaptItem", "'%s' '%s' '%s' id=%d", 
-                          *aItemData1,*aItemData2,*aLocalVars, aIdentifier );
+  if (!source) {
+      return LOCERR_WRONGUSAGE;
+  }
+  SE_LOG_DEBUG(source, NULL, "AdaptItem '%s' '%s' '%s' id=%d", 
+               *aItemData1, *aItemData2, *aLocalVars, aIdentifier);
   return LOCERR_OK;
 } /* AdaptItem */
 
@@ -587,9 +632,9 @@ TSyError SyncEvolution_StartDataRead( CContext aContext, cAppCharP   lastToken,
                                       cAppCharP resumeToken )
 {
     SyncSource *source = DBC( aContext );
-    DEBUG_DB( source->getSynthesisAPI(), MyDB,Da_SR, "%s last='%s' resume='%s'",
-              source->getName(), lastToken,resumeToken );
-
+    if (!source) {
+        return LOCERR_WRONGUSAGE;
+    }
     TSyError res = LOCERR_OK;
     try {
         if (source->getOperations().m_startDataRead) {
@@ -603,6 +648,8 @@ TSyError SyncEvolution_StartDataRead( CContext aContext, cAppCharP   lastToken,
         res = source->handleException();
     }
 
+    SE_LOG_DEBUG(source, NULL, "StartDataRead last='%s' resume='%s' res=%d",
+                 lastToken, resumeToken, res);
     return res;
 }
 
@@ -613,7 +660,9 @@ TSyError SyncEvolution_ReadNextItemAsKey( CContext aContext, ItemID aID, KeyH aI
 {
     /**** CAN BE ADAPTED BY USER ****/
     SyncSource *source = DBC( aContext );
-
+    if (!source) {
+        return LOCERR_WRONGUSAGE;
+    }
     TSyError res = LOCERR_OK;
     *aStatus = 0;
     memset(aID, 0, sizeof(*aID));
@@ -625,8 +674,8 @@ TSyError SyncEvolution_ReadNextItemAsKey( CContext aContext, ItemID aID, KeyH aI
         }
     }
 
-    DEBUG_DB( source->getSynthesisAPI(), MyDB,Da_RNK, "%s aStatus=%d aItemKey=%08X aID=(%s,%s)",
-              source->getName(), *aStatus, aItemKey, aID->item, aID->parent );
+    SE_LOG_DEBUG(source, NULL, "ReadNextItemAsKey aStatus=%d aID=(%s,%s) res=%d",
+                 *aStatus, aID->item, aID->parent, res);
     return res;
 }
 
@@ -634,9 +683,9 @@ extern "C"
 TSyError SyncEvolution_ReadItemAsKey( CContext aContext, cItemID aID, KeyH aItemKey )
 {
     SyncSource *source = DBC( aContext );
-    DEBUG_DB( source->getSynthesisAPI(), MyDB,Da_RIK, "%s aItemKey=%08X aID=(%s,%s)",
-              source->getName(), aItemKey,  aID->item,aID->parent );
-
+    if (!source) {
+        return LOCERR_WRONGUSAGE;
+    }
     TSyError res = LOCERR_OK;
     if (source->getOperations().m_readItemAsKey) {
         try {
@@ -646,6 +695,8 @@ TSyError SyncEvolution_ReadItemAsKey( CContext aContext, cItemID aID, KeyH aItem
         }
     }
 
+    SE_LOG_DEBUG(source, NULL, "ReadItemAsKey aID=(%s,%s) res=%d",
+                 aID->item, aID->parent, res);
     return res;
 }
 
@@ -658,6 +709,10 @@ TSyError SyncEvolution_ReadBlob( CContext aContext, cItemID  aID,  cAppCharP  aB
 {
   /**** CAN BE ADAPTED BY USER ****/ 
   SyncSource *source = DBC( aContext );
+  if (!source) {
+      return LOCERR_WRONGUSAGE;
+  }
+  TSyError res = LOCERR_OK;
   const int sz= sizeof(int);
   
   int* ip = (int*)malloc( sz ); /* example BLOB structure for test (=4 bytes) */ 
@@ -667,12 +722,10 @@ TSyError SyncEvolution_ReadBlob( CContext aContext, cItemID  aID,  cAppCharP  aB
   *aTotSize= *aBlkSize;
   *aLast   = true;
 
-  DEBUG_DB( source->getSynthesisAPI(), MyDB,Da_RB, "%s aID=(%s,%s) aBlobID=(%s)",
-                                  source->getName(), aID->item,aID->parent, aBlobID );
-  DEBUG_DB( source->getSynthesisAPI(), MyDB,"",    "aBlkPtr=%08X aBlkSize=%d aTotSize=%d aFirst=%s aLast=%s", 
-                                 *aBlkPtr, *aBlkSize, *aTotSize,
-                                  aFirst?"true":"false", *aLast?"true":"false" );
-  return LOCERR_OK;
+  SE_LOG_DEBUG(source, NULL, "ReadBlob aID=(%s,%s) aBlobID=(%s) aBlkPtr=%08X aBlkSize=%d aTotSize=%d aFirst=%s aLast=%s res=%d",
+               aID->item,aID->parent, aBlobID, aBlkPtr, *aBlkSize, *aTotSize,
+               aFirst? "true" : "false", *aLast ? "true" : "false", res);
+  return res;
 } /* ReadBlob */
 #endif
 
@@ -681,8 +734,9 @@ extern "C"
 TSyError SyncEvolution_EndDataRead( CContext aContext )
 {
     SyncSource *source = DBC( aContext );
-    DEBUG_DB( source->getSynthesisAPI(), MyDB,Da_ER, "%s", source->getName() );
-
+    if (!source) {
+        return LOCERR_WRONGUSAGE;
+    }
     TSyError res = LOCERR_OK;
     if (source->getOperations().m_endDataRead) {
         try {
@@ -692,6 +746,7 @@ TSyError SyncEvolution_EndDataRead( CContext aContext )
         }
     }
 
+    SE_LOG_DEBUG(source, NULL, "EndDataRead res=%d", res);
     return res;
 }
 
@@ -703,7 +758,10 @@ extern "C"
 TSyError SyncEvolution_StartDataWrite( CContext aContext )
 {
     SyncSource *source = DBC( aContext );
-    DEBUG_DB( source->getSynthesisAPI(), MyDB,Da_SW, "%s", source->getName() );
+    if (!source) {
+        return LOCERR_WRONGUSAGE;
+    }
+    SE_LOG_DEBUG(source, NULL, "StartDataWrite");
     return LOCERR_OK;
 }
 
@@ -712,8 +770,9 @@ TSyError SyncEvolution_InsertItemAsKey( CContext aContext, KeyH aItemKey, ItemID
 {
     /**** CAN BE ADAPTED BY USER ****/
     SyncSource *source = DBC( aContext );
-    DEBUG_DB( source->getSynthesisAPI(), MyDB,Da_IIK, "%s %08X\n", source->getName(), aItemKey );
-
+    if (!source) {
+        return LOCERR_WRONGUSAGE;
+    }
     TSyError res = LOCERR_OK;
     if (source->getOperations().m_insertItemAsKey) {
         try {
@@ -723,6 +782,7 @@ TSyError SyncEvolution_InsertItemAsKey( CContext aContext, KeyH aItemKey, ItemID
         }
     }
 
+    SE_LOG_DEBUG(source, NULL, "InsertItemAsKey res=%d\n", res);
     return res;
 }
 
@@ -732,10 +792,9 @@ TSyError SyncEvolution_UpdateItemAsKey( CContext aContext, KeyH aItemKey, cItemI
                                         ItemID updID )
 {
     SyncSource *source = DBC( aContext );
-  
-    DEBUG_DB( source->getSynthesisAPI(), MyDB,Da_UI, "%s aID=(%s,%s)",
-              source->getName(), aID->item,aID->parent );
-
+    if (!source) {
+        return LOCERR_WRONGUSAGE;
+    }
     TSyError res = LOCERR_OK;
     if (source->getOperations().m_updateItemAsKey) {
         try {
@@ -745,6 +804,9 @@ TSyError SyncEvolution_UpdateItemAsKey( CContext aContext, KeyH aItemKey, cItemI
         }
     }
 
+  
+    SE_LOG_DEBUG(source, NULL, "aID=(%s,%s) res=%d",
+                 aID->item,aID->parent, res);
     return res;
 }
 
@@ -754,9 +816,11 @@ extern "C"
 TSyError SyncEvolution_MoveItem( CContext aContext, cItemID aID, cAppCharP newParID )
 {
     SyncSource *source = DBC( aContext );
-    DEBUG_DB( source->getSynthesisAPI(), MyDB,Da_MvI, "%s aID=(%s,%s) => (%s,%s)",
-              source->getName(), aID->item,aID->parent,
-              aID->item,newParID );
+    if (!source) {
+        return LOCERR_WRONGUSAGE;
+    }
+    SE_LOG_DEBUG(source, NULL, "MoveItem aID=(%s,%s) => (%s,%s)",
+                 aID->item,aID->parent, aID->item,newParID);
     return LOCERR_NOTIMP;
 }
 
@@ -766,8 +830,9 @@ extern "C"
 TSyError SyncEvolution_DeleteItem( CContext aContext, cItemID aID )
 {
     SyncSource *source = DBC( aContext );
-    DEBUG_DB( source->getSynthesisAPI(), MyDB,Da_DeI, "%s aID=(%s,%s)", source->getName(),aID->item,aID->parent );
-
+    if (!source) {
+        return LOCERR_WRONGUSAGE;
+    }
     TSyError res = LOCERR_OK;
     if (source->getOperations().m_deleteItem) {
         try {
@@ -777,6 +842,8 @@ TSyError SyncEvolution_DeleteItem( CContext aContext, cItemID aID )
         }
     }
 
+    SE_LOG_DEBUG(source, NULL, "DeleteItem aID=(%s,%s) res=%d",
+                 aID->item, aID->parent, res);
     return res;
 }
 
@@ -785,6 +852,11 @@ TSyError SyncEvolution_DeleteItem( CContext aContext, cItemID aID )
 extern "C"
 TSyError SyncEvolution_FinalizeLocalID( CContext aContext, cItemID aID, ItemID updID )
 {
+    SyncSource *source = DBC( aContext );
+    if (!source) {
+        return LOCERR_WRONGUSAGE;
+    }
+    SE_LOG_DEBUG(source, NULL, "FinalizeLocalID not implemented");
     return LOCERR_NOTIMP;
 }
 
@@ -793,6 +865,11 @@ TSyError SyncEvolution_FinalizeLocalID( CContext aContext, cItemID aID, ItemID u
 extern "C"
 TSyError SyncEvolution_DeleteSyncSet( CContext aContext )
 {
+    SyncSource *source = DBC( aContext );
+    if (!source) {
+        return LOCERR_WRONGUSAGE;
+    }
+    SE_LOG_DEBUG(source, NULL, "DeleteSyncSet not implemented");
     return LOCERR_NOTIMP;
 }
 
@@ -804,25 +881,31 @@ TSyError SyncEvolution_WriteBlob( CContext aContext, cItemID aID,  cAppCharP aBl
                                   uInt32 aTotSize,
                                   bool aFirst,    bool aLast )
 {
-  /**** CAN BE ADAPTED BY USER ****/ 
-  SyncSource *source = DBC( aContext );
-  DEBUG_DB( source->getSynthesisAPI(), MyDB,Da_WB, "%s aID=(%s,%s) aBlobID=(%s)",
-                                  source->getName(), aID->item,aID->parent, aBlobID );
-  DEBUG_DB( source->getSynthesisAPI(), MyDB,"",    "aBlkPtr=%08X aBlkSize=%d aTotSize=%d aFirst=%s aLast=%s", 
-                                  aBlkPtr, aBlkSize, aTotSize, 
-                                  aFirst?"true":"false", aLast ?"true":"false" );
-  return LOCERR_OK;
+    SyncSource *source = DBC( aContext );
+    if (!source) {
+        return LOCERR_WRONGUSAGE;
+    }
+    TSyError res = LOCERR_NOTIMP;
+  
+    SE_LOG_DEBUG(source, NULL, "WriteBlob aID=(%s,%s) aBlobID=(%s) aBlkPtr=%08X aBlkSize=%d aTotSize=%d aFirst=%s aLast=%s res=%d",
+                 aID->item,aID->parent, aBlobID, aBlkPtr, aBlkSize, aTotSize, 
+                 aFirst ? "true" : "false", aLast ? "true" : "false", res);
+    return res;
 } /* WriteBlob */
 
 
 extern "C"
 TSyError SyncEvolution_DeleteBlob( CContext aContext, cItemID aID, cAppCharP aBlobID )
 {
-  /**** CAN BE ADAPTED BY USER ****/ 
-  SyncSource *source = DBC( aContext );
-  DEBUG_DB( source->getSynthesisAPI(), MyDB,Da_DB, "%s aID=(%s,%s) aBlobID=(%s)",
-                                  source->getName(), aID->item,aID->parent, aBlobID );
-  return LOCERR_OK;
+    SyncSource *source = DBC( aContext );
+    if (!source) {
+        return LOCERR_WRONGUSAGE;
+    }
+    TSyError res = LOCERR_NOTIMP;
+
+    SE_LOG_DEBUG(source "DeleteBlob aID=(%s,%s) aBlobID=(%s) res=%d",
+                 aID->item,aID->parent, aBlobID, res);
+    return res;
 } /* DeleteBlob */
 
 #endif
@@ -832,6 +915,9 @@ extern "C"
 TSyError SyncEvolution_EndDataWrite( CContext aContext, bool success, appCharP *newToken )
 {
     SyncSource *source = DBC( aContext );
+    if (!source) {
+        return LOCERR_WRONGUSAGE;
+    }
     TSyError res = LOCERR_OK;
     try {
         BOOST_FOREACH(const SyncSource::Operations::CallbackFunctor_t &callback,
@@ -845,20 +931,21 @@ TSyError SyncEvolution_EndDataWrite( CContext aContext, bool success, appCharP *
         res = source->handleException();
     }
 
-    DEBUG_DB( source->getSynthesisAPI(), MyDB,Da_EW, "%s %s '%s'", 
-              source->getName(), success ? "COMMIT":"ROLLBACK", *newToken );
+    SE_LOG_DEBUG(source, NULL, "EndDataWrite %s '%s' res=%d", 
+                 success ? "COMMIT":"ROLLBACK", *newToken, res);
     return res;
 }
 
-
-
 /* ----------------------------------- */
 extern "C"
 TSyError SyncEvolution_DeleteContext( CContext aContext )
 {
   /**** CAN BE ADAPTED BY USER ****/ 
   SyncSource *source = DBC( aContext );
-  DEBUG_DB( source->getSynthesisAPI(), MyDB,Da_DC, "%s", source->getName() );
+  if (!source) {
+      return LOCERR_WRONGUSAGE;
+  }
+  SE_LOG_DEBUG(source, NULL, "DeleteContext");
   source->popSynthesisAPI();
   return LOCERR_OK;
 }
index 0293eec..e233062 100644 (file)
@@ -66,10 +66,11 @@ public:
 };
 
 
-SharedSession SharedEngine::OpenSession()
+SharedSession SharedEngine::OpenSession(const string &aSessionID)
 {
     sysync::SessionH sessionH = NULL;
-    sysync::TSyError err = m_engine->OpenSession(sessionH);
+    sysync::TSyError err = m_engine->OpenSession(sessionH, 0,
+                                                 aSessionID.empty() ? NULL : aSessionID.c_str());
     if (err) {
         throw BadSynthesisResult("opening session failed", static_cast<sysync::TSyErrorEnum>(err));
     }
index 7c85be6..b4a9670 100644 (file)
@@ -51,16 +51,24 @@ class SharedBuffer : public boost::shared_array<char>
         m_size(0)
         {}
 
+    /** transfers ownership */
     explicit SharedBuffer(char *p, size_t size):
     boost::shared_array<char>(p),
         m_size(size)
         {}
 
+    /** transfers ownership with custom destructor */
     template <class D> SharedBuffer(char *p, size_t size, const D &d) :
     boost::shared_array<char>(p, d),
         m_size(size)
         {}
 
+    /** copies memory */
+    explicit SharedBuffer(const char *p, size_t size):
+    boost::shared_array<char>(new char [size]),
+        m_size(size)
+        { memcpy(get(), p, size); }
+
     size_t size() { return m_size; }
 };
 
@@ -85,7 +93,7 @@ class SharedEngine {
     void Disconnect();
 
     void InitEngineXML(const string &aConfigXML);
-    SharedSession OpenSession();
+    SharedSession OpenSession(const string &aSessionID);
     SharedKey OpenSessionKey(SharedSession &aSessionH);
 
     void SessionStep(const SharedSession &aSessionH,
index d6a72e0..b4dfd3f 100644 (file)
@@ -31,20 +31,15 @@ TrackingSyncSource::TrackingSyncSource(const SyncSourceParams &params,
                                        int granularitySeconds) :
     TestingSyncSource(params),
     m_trackingNode(new PrefixConfigNode("item-",
-                                        boost::shared_ptr<ConfigNode>(new SafeConfigNode(params.m_nodes.m_trackingNode))))
+                                        boost::shared_ptr<ConfigNode>(new SafeConfigNode(params.m_nodes.getTrackingNode()))))
 {
-    m_operations.m_checkStatus = boost::bind(&TrackingSyncSource::checkStatus, this, _1);
+    m_operations.m_checkStatus = boost::bind(&TrackingSyncSource::checkStatus, this);
     SyncSourceRevisions::init(this, this, granularitySeconds, m_operations);
 }
 
-void TrackingSyncSource::checkStatus(SyncSourceReport &changes)
+void TrackingSyncSource::checkStatus()
 {
     detectChanges(*m_trackingNode);
-    // copy our item counts into the report
-    changes.setItemStat(ITEM_LOCAL, ITEM_ADDED, ITEM_TOTAL, getNewItems().size());
-    changes.setItemStat(ITEM_LOCAL, ITEM_UPDATED, ITEM_TOTAL, getUpdatedItems().size());
-    changes.setItemStat(ITEM_LOCAL, ITEM_REMOVED, ITEM_TOTAL, getDeletedItems().size());
-    changes.setItemStat(ITEM_LOCAL, ITEM_ANY, ITEM_TOTAL, getAllItems().size());
 }
 
 void TrackingSyncSource::beginSync(const std::string &lastToken, const std::string &resumeToken)
@@ -99,4 +94,19 @@ void TrackingSyncSource::deleteItem(const std::string &luid)
     deleteRevision(*m_trackingNode, luid);
 }
 
+void TrackingSyncSource::enableServerMode()
+{
+    SyncSourceAdmin::init(m_operations, this);
+}
+
+bool TrackingSyncSource::serverModeEnabled() const
+{
+    return m_operations.m_loadAdminData;
+}
+
+const char *TrackingSyncSource::getPeerMimeType() const
+{
+    return getMimeType();
+}
+
 SE_END_CXX
index 27d7301..ced3c56 100644 (file)
@@ -63,7 +63,9 @@ using namespace std;
  *   (beware, such a hash might change as the textual representation
  *    changes even though the item is unchanged)
  */
-class TrackingSyncSource : public TestingSyncSource, virtual public SyncSourceRevisions
+class TrackingSyncSource : public TestingSyncSource,
+    virtual public SyncSourceRevisions,
+    virtual public SyncSourceAdmin
 {
   public:
     /**
@@ -127,10 +129,7 @@ class TrackingSyncSource : public TestingSyncSource, virtual public SyncSourceRe
      *
      * @param luid     identifies the item to be modified, empty for creating
      * @param item     contains the new content of the item
-     * @param raw      item has internal format instead of engine format;
-     *                 testing and backup/restore might use such an internal format
-     *                 which may be different (more complete!) than the
-     *                 format when talking to the sync engine
+     * @param raw      item has internal format instead of engine format
      * @return the result of inserting the item
      */
     virtual InsertItemResult insertItem(const std::string &luid, const std::string &item, bool raw) = 0;
@@ -180,10 +179,16 @@ class TrackingSyncSource : public TestingSyncSource, virtual public SyncSourceRe
      */
     virtual const char *getMimeVersion() const = 0;
 
+    /**
+     * Mime type a backend provides by default, this is used to alert the
+     * remote peer in SAN during server alerted sync.
+     */
+    virtual const char *getPeerMimeType() const;
+
     using SyncSource::getName;
 
   private:
-    void checkStatus(SyncSourceReport &changes);
+    void checkStatus();
 
     /* implementations of SyncSource callbacks */
     virtual void beginSync(const std::string &lastToken, const std::string &resumeToken);
@@ -193,6 +198,8 @@ class TrackingSyncSource : public TestingSyncSource, virtual public SyncSourceRe
     virtual void readItem(const std::string &luid, std::string &item);
     virtual InsertItemResult insertItemRaw(const std::string &luid, const std::string &item);
     virtual void readItemRaw(const std::string &luid, std::string &item);
+    virtual void enableServerMode();
+    virtual bool serverModeEnabled() const;
 
     boost::shared_ptr<ConfigNode> m_trackingNode;
 };
diff --git a/src/syncevo/TransportAgent.cpp b/src/syncevo/TransportAgent.cpp
new file mode 100644 (file)
index 0000000..4579224
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2009 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) version 3.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301  USA
+ */
+
+#include <syncevo/TransportAgent.h>
+#include <syncevo/SyncConfig.h>
+
+#include <syncevo/declarations.h>
+SE_BEGIN_CXX
+
+const char * const TransportAgent::m_contentTypeSyncML = "application/vnd.syncml+xml";
+const char * const TransportAgent::m_contentTypeSyncWBXML = "application/vnd.syncml+wbxml";
+const char * const TransportAgent::m_contentTypeURLEncoded = "application/x-www-form-urlencoded";
+const char * const TransportAgent::m_contentTypeServerAlertedNotificationDS = "application/vnd.syncml.ds.notification";
+
+void HTTPTransportAgent::setConfig(SyncConfig &config)
+{
+    if (config.getUseProxy()) {
+        setProxy(config.getProxyHost());
+        setProxyAuth(config.getProxyUsername(),
+                     config.getProxyPassword());
+    }
+    setUserAgent(config.getUserAgent());
+    setSSL(config.findSSLServerCertificate(),
+           config.getSSLVerifyServer(),
+           config.getSSLVerifyHost());
+}
+
+SE_END_CXX
index 51a36bd..5fe79c8 100644 (file)
@@ -26,6 +26,7 @@
 #include <syncevo/declarations.h>
 SE_BEGIN_CXX
 
+class SyncConfig;
 
 /**
  * Abstract API for a message send/receive agent.
@@ -34,7 +35,9 @@ SE_BEGIN_CXX
  * - set parameters for next message
  * - start message send
  * - optional: cancel transmission
- * - wait for completion and reply
+ * - wait for completion and the optional reply
+ * - close
+ * - wait for completion of the shutdown
  *
  * Data to be sent is owned by caller. Data received as reply is
  * allocated and owned by agent. Errors are reported via
@@ -43,44 +46,28 @@ SE_BEGIN_CXX
 class TransportAgent
 {
  public:
-     typedef bool (*TransportCallback) (void *udata);
+    typedef bool (*TransportCallback) (void *udata);
+
     /**
      * set transport specific URL of next message
      */
     virtual void setURL(const std::string &url) = 0;
 
     /**
-     * set proxy for transport, in protocol://[user@]host[:port] format
-     */
-    virtual void setProxy(const std::string &proxy) = 0;
-
-    /**
-     * set proxy user name (if not specified in proxy string)
-     * and password
-     */
-    virtual void setProxyAuth(const std::string &user,
-                              const std::string &password) = 0;
-
-    /**
-     * control how SSL certificates are checked
-     *
-     * @param cacerts         path to a single CA certificate file
-     * @param verifyServer    enable server verification (should always be on)
-     * @param verifyHost      do strict hostname checking in the certificate
-     */
-    virtual void setSSL(const std::string &cacerts,
-                        bool verifyServer,
-                        bool verifyHost) = 0;
-
-    /**
      * define content type for post, see content type constants
      */
     virtual void setContentType(const std::string &type) = 0;
 
     /**
-     * override default user agent string
+     * Requests an normal shutdown of the transport. This can take a
+     * while, for example if communication is still pending.
+     * Therefore wait() has to be called to ensure that the
+     * shutdown is complete and that no error occurred.
+     *
+     * Simply deleting the transport is an *unnormal* shutdown that
+     * does not communicate with the peer.
      */
-    virtual void setUserAgent(const std::string &agent) = 0;
+    virtual void shutdown() = 0;
 
     /**
      * start sending message
@@ -103,13 +90,12 @@ class TransportAgent
 
     enum Status {
         /**
-         * message is being sent or reply received,
-         * check again with wait()
+         * operation is on-going, check again with wait()
          */
         ACTIVE,
         /**
          * received and buffered complete reply,
-         * get acces to it with getReponse()
+         * get access to it with getReponse()
          */
         GOT_REPLY,
         /**
@@ -122,6 +108,10 @@ class TransportAgent
          */
         FAILED,
         /**
+         * transport was closed normally without error
+         */
+        CLOSED,
+        /**
          * transport timeout
          */
         TIME_OUT,
@@ -132,11 +122,16 @@ class TransportAgent
     };
 
     /**
-     * wait for reply
+     * Wait for completion of an operation initiated earlier.
+     * The operation can be a send with optional reply or
+     * a close request.
      *
-     * Returns immediately if no transmission is pending.
+     * Returns immediately if no operations is pending.
+     *
+     * @param noReply    true if no reply is required for a running send;
+     *                   only relevant for transports used by a SyncML server
      */
-    virtual Status wait() = 0;
+    virtual Status wait(bool noReply = false) = 0;
 
     /**
      * The callback is called every interval seconds, with udata as the last
@@ -163,8 +158,49 @@ class TransportAgent
     /** normal HTTP URL encoded */
     static const char * const m_contentTypeURLEncoded;
 
+    /** binary Server Alerted Notification (SAN) for data sync */
+    static const char * const m_contentTypeServerAlertedNotificationDS;
+};
+
+class HTTPTransportAgent : public TransportAgent
+{
+ public:
+    /**
+     * set proxy for transport, in protocol://[user@]host[:port] format
+     */
+    virtual void setProxy(const std::string &proxy) = 0;
+
+    /**
+     * set proxy user name (if not specified in proxy string)
+     * and password
+     */
+    virtual void setProxyAuth(const std::string &user,
+                              const std::string &password) = 0;
+
+    /**
+     * control how SSL certificates are checked
+     *
+     * @param cacerts         path to a single CA certificate file
+     * @param verifyServer    enable server verification (should always be on)
+     * @param verifyHost      do strict hostname checking in the certificate
+     */
+    virtual void setSSL(const std::string &cacerts,
+                        bool verifyServer,
+                        bool verifyHost) = 0;
+
+    /**
+     * override default user agent string
+     */
+    virtual void setUserAgent(const std::string &agent) = 0;
+
+    /**
+     * convenience method which copies the HTTP settings from
+     * SyncConfig
+     */
+    void setConfig(SyncConfig &config);
 };
 
+
 class TransportException : public Exception
 {
  public:
@@ -176,6 +212,5 @@ class TransportException : public Exception
 };
 
 
-
 SE_END_CXX
 #endif // INCL_TRANSPORTAGENT
index c0dbb62..69ffe4d 100644 (file)
@@ -33,7 +33,7 @@ SE_BEGIN_CXX
 class VolatileConfigTree : public FileConfigTree {
  public:
  VolatileConfigTree() :
-    FileConfigTree("/dev/null", false)
+    FileConfigTree("/dev/null", "", false)
         {}
 
     virtual void flush() {}
index 249584d..146f546 100644 (file)
@@ -259,7 +259,6 @@ extern "C" void EDSAbiWrapperInit()
                 &EDSAbiWrapperSingleton.icalproperty_new_description, "icalproperty_new_description",
                 &EDSAbiWrapperSingleton.icalproperty_new_summary, "icalproperty_new_summary",
                 &EDSAbiWrapperSingleton.icalproperty_set_value_from_string, "icalproperty_set_value_from_string",
-                &EDSAbiWrapperSingleton.icalproperty_remove_parameter_by_kind, "icalproperty_remove_parameter_by_kind",
                 &EDSAbiWrapperSingleton.icaltime_as_ical_string, "icaltime_as_ical_string",
                 &EDSAbiWrapperSingleton.icaltimezone_free, "icaltimezone_free",
                 &EDSAbiWrapperSingleton.icaltimezone_get_builtin_timezone, "icaltimezone_get_builtin_timezone",
index 527f98f..a38eef9 100644 (file)
@@ -161,8 +161,6 @@ struct EDSAbiWrapper {
     icalproperty* (*icalproperty_new_description) (const char* v);
     icalproperty* (*icalproperty_new_summary) (const char* v);
     void (*icalproperty_set_value_from_string) (icalproperty* prop,const char* value, const char* kind);
-    void (*icalproperty_remove_parameter_by_kind)(icalproperty* prop,
-                                                  icalparameter_kind kind);
     const char* (*icaltime_as_ical_string) (const struct icaltimetype tt);
 
     void (*icaltimezone_free) (icaltimezone *zone, int free_struct);
@@ -268,7 +266,6 @@ extern struct EDSAbiWrapper EDSAbiWrapperSingleton;
 #   define icalproperty_new_description EDSAbiWrapperSingleton.icalproperty_new_description
 #   define icalproperty_new_summary EDSAbiWrapperSingleton.icalproperty_new_summary
 #   define icalproperty_set_value_from_string EDSAbiWrapperSingleton.icalproperty_set_value_from_string
-#   define icalproperty_remove_parameter_by_kind EDSAbiWrapperSingleton.icalproperty_remove_parameter_by_kind
 #   define icaltime_as_ical_string EDSAbiWrapperSingleton.icaltime_as_ical_string
 #   define icaltimezone_free EDSAbiWrapperSingleton.icaltimezone_free
 #   define icaltimezone_get_builtin_timezone EDSAbiWrapperSingleton.icaltimezone_get_builtin_timezone
index ce5025d..5f6c64a 100644 (file)
@@ -128,6 +128,32 @@ void rm_r(const string &path, boost::function<bool (const string &,
     }
 }
 
+void cp_r(const string &from, const string &to)
+{
+    if (isDir(from)) {
+        mkdir_p(to);
+        ReadDir dir(from);
+        BOOST_FOREACH(const string &entry, dir) {
+            cp_r(from + "/" + entry, to + "/" + entry);
+        }
+    } else {
+        ofstream out;
+        ifstream in;
+        out.open(to.c_str());
+        in.open(from.c_str());
+        char buf[8192];
+        do {
+            in.read(buf, sizeof(buf));
+            out.write(buf, in.gcount());
+        } while(in);
+        in.close();
+        out.close();
+        if (out.bad() || in.bad()) {
+            SE_THROW(string("failed copying ") + from + " to " + to);
+        }
+    }
+}
+
 bool isDir(const string &path)
 {
     DIR *dir = opendir(path.c_str());
@@ -351,4 +377,37 @@ std::string SubstEnvironment(const std::string &str)
     return res.str();
 }
 
+std::vector<std::string> unescapeJoinedString (const std::string& src, char sep)
+{
+    std::vector<std::string> splitStrings;
+    size_t pos1 = 0, pos2 = 0, pos3 = 0;
+    std::string s1, s2;
+    while (pos3 != src.npos) {
+        pos2 = src.find (sep, pos3);
+        s1 = src.substr (pos1, 
+                (pos2 == std::string::npos) ? std::string::npos : pos2-pos1);
+        size_t pos = s1.find_last_not_of ("\\");
+        pos3 = (pos2 == std::string::npos) ?pos2 : pos2+1;
+        // A matching delimiter is a comma with even trailing '\'
+        // characters
+        if (!((s1.length() - ((pos == s1.npos) ? 0: pos-1)) &1 )) {
+            s2="";
+            boost::trim (s1);
+            for (std::string::iterator i = s1.begin(); i != s1.end(); i++) {
+                //unescape characters
+                if (*i == '\\') {
+                    if(++i == s1.end()) {
+                        break;
+                    }
+                }
+                s2+=*i;
+            }
+            splitStrings.push_back (s2);
+            pos1 = pos3;
+        }
+    }
+    return splitStrings;
+}
+
+
 SE_END_CXX
index a307a92..da62a92 100644 (file)
@@ -55,6 +55,7 @@ public:
 
 /** shorthand, primarily useful for BOOST_FOREACH macro */
 typedef pair<string, string> StringPair;
+typedef map<string, string> StringMap;
 
 /**
  * remove multiple slashes in a row and dots directly after a slash if not followed by filename,
@@ -77,6 +78,22 @@ inline bool rm_r_all(const string &path, bool isDir) { return true; }
 void rm_r(const string &path, boost::function<bool (const string &,
                                                     bool)> filter = rm_r_all);
 
+/**
+ * copy complete directory hierarchy
+ *
+ * If the source is a directory, then the target
+ * also has to be a directory name. It will be
+ * created if necessary.
+ *
+ * Alternatively, both names may refer to files.
+ * In that case the directory which is going to
+ * contain the target file must exist.
+ *
+ * @param from     source directory or file
+ * @param to       target directory or file (must have same type as from)
+ */
+void cp_r(const string &from, const string &to);
+
 /** true if the path refers to a directory */
 bool isDir(const string &path);
 
@@ -217,6 +234,12 @@ inline string getHome() {
     return homestr ? homestr : ".";
 }
 
+/**
+ * Parse a separator splitted set of strings src, the separator itself is
+ * escaped by a backslash. Spaces around the separator is also stripped.
+ * */
+std::vector<std::string> unescapeJoinedString (const std::string &src, char separator);
+
 /** throw a normal SyncEvolution Exception, including source information */
 #define SE_THROW(_what) \
     SE_THROW_EXCEPTION(Exception, _what)
index 6f196af..d7bc87a 100644 (file)
@@ -79,7 +79,7 @@ class KeyringSyncCmdline : public Cmdline {
      * create a user implemented sync client.
      */
     SyncContext* createSyncClient() {
-        return new CmdlineSyncClient(m_server, true, m_sources, m_keyring);
+        return new CmdlineSyncClient(m_server, true, m_keyring);
     }
 };
 
index 8a1a275..121e7a1 100644 (file)
@@ -1,18 +1,30 @@
 # Generated by configure.  Do no edit.
-# git revision a29f5f37d3d13a46613c9eaf1867dcf08ed359f7
-# git tag libsynthesis_3.2.0.35+syncevolution-0-9-2
+# git revision d079c4831d44ef1d92989845b0a4556df342f87d
+# git tag libsynthesis_3.2.0.35+syncevolution-1-0-alpha-1-1-gd079c48
 
-2010-01-18  Ove Kaaven  <ovek@debian.org>
+2009-11-30  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * src/gen-makefile-am.sh:
+       * src/DB_interfaces/api_db/pluginapids.cpp:
+       * src/sysync/customimplds.cpp:
+       * src/sysync/debuglogger.cpp:
+       * src/sysync/localengineds.cpp:
+       * src/sysync/stdlogicds.cpp:
 
-       autotools: unnecessarily depends on too new findutils (MB #9112)
+       fixed GCC compiler warnings
 
-2009-12-10  Patrick Ohly  <patrick.ohly@intel.com>
+2009-11-30  Patrick Ohly  <patrick.ohly@intel.com>
 
-       * src/sysync/debuglogger.cpp:
+       * src/sysync/debuglogger.h:
+       * src/sysync/syncappbase.cpp:
+       * src/sysync/syncsession.cpp:
+
+       log file base name: configurable via "filename" config option
+
+2009-11-26  Zhu, Yongsheng  <yongsheng.zhu@intel.com>
+
+       * src/syncml_tk/src/sml/xlt/all/xltenc.c:
 
-       TDebugLoggerBase::DebugOpenBlock(): unused va_list
+       devinfo: increase memory size for encoding devinfo in WBXML
 
 2009-11-11  Patrick Ohly  <patrick.ohly@intel.com>
 
        autotools + old libical: crash when compiled without
        --enable-evolution-compatibility
 
+2009-11-09  Lukas Zeller  <luz@synthesis.ch>
+
+       * src/DB_interfaces/api_db/pluginapiagent.cpp:
+
+       anonymous login: improved passing anonymous login attempts to DB
+       Api
+
+2009-11-10  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/sysync/syncsession.cpp:
+
+       Revert "TSyncSession::checkCredentials(): <requiredauth>none =>
+       accept invalid credentials"
+
+2009-11-04  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/sysync/engineinterface.cpp:
+       * src/sysync/engineinterface.h:
+
+       TEngineInterface::debugPuts(): not active in server
+
+2009-11-03  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/sysync/syncsession.cpp:
+
+       TSyncSession::checkCredentials(): <requiredauth>none => accept
+       invalid credentials
+
+2009-10-29  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/sysync/engineinterface.cpp:
+       * src/sysync/engineinterface.h:
+
+       DebugPuts(): added to the unilib engine
+
+2009-10-29  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/sysync/syncappbase.cpp:
+
+       TSyncAppBase::encodingFromData(): detect Oracle Beehive XML
+       messages
+
+2009-10-23  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/Transport_interfaces/engine/enginesessiondispatch.cpp:
+
+       TServerEngineInterface::SessionStep(): removed obsolete label
+
+2009-10-23  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/Transport_interfaces/engine/enginesessiondispatch.cpp:
+
+       TServerEngineInterface::OpenSessionInternal(): printf format for
+       uInt64
+
+2009-10-23  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/Transport_interfaces/engine/enginesessiondispatch.cpp:
+
+       TEngineSessionDispatch::generateRespURI(): result of string::find
+       downcasted to sInt16
+
+2009-10-23  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/Targets/ReleasedProducts/combiEngine_opensource_linux/combiengine_opensource_linux_prefix.h:
+
+       Linux platform: need _GNU_SOURCE for vasprintf
+
+2009-10-23  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/DB_interfaces/api_db/pluginapids.cpp:
+
+       another unhandled enum
+
+2009-10-23  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/DB_interfaces/api_db/pluginapids.cpp:
+
+       another #warning
+
+2009-10-23  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/sysync/localengineds.cpp:
+
+       TLocalEngineDS::newDevInfDatastore(): fixed 64 biit issue
+
+2009-10-23  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/sysync/superdatastore.cpp:
+
+       superdatastore: add unhandled sop enum values
+
+2009-10-23  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/sysync/syncsession.cpp:
+
+       TSyncSession::initSync(): avoid #warning in gcc
+
+2009-10-23  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/sysync/stdlogicds.cpp:
+
+       TStdLogicDS::logicGenerateSyncCommandsAsServer: invalid logical
+       expression?!
+
+2009-10-23  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/sysync/stdlogicds.cpp:
+
+       TStdLogicDS::startDataAccessForServer(): fioxed signed/unsigned
+       comparison
+
+2009-10-23  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/sysync/customimplds.cpp:
+
+       TCustomImplDS::modifyMap(): added redundant parenthesis for gcc
+       -Wall
+
 2009-10-21  Patrick Ohly  <patrick.ohly@intel.com>
 
        * .gitignore:
        * src/gen-makefile-am.sh:
 
-       gen-makefile-am.sh + autotools: avoid GNU find -printf option
+       gen-makefile-am.sh + autotools: avoid GNU find --printf and shell
+       wildcards
 
 2009-10-17  Lukas Zeller  <luz@synthesis.ch>
 
-       * src/sysync/syncclient.cpp:
-       * src/sysync/syncclient.h:
+       * src/sysync/syncagent.cpp:
+       * src/sysync/syncagent.h:
        * src/sysync/synccommand.cpp:
        * src/sysync/synccommand.h:
        * src/sysync/syncsession.cpp:
        Alert 222 loop detector improved: do not trigger as long as valid
        status is received
 
+2009-10-16  Lukas Zeller  <luz@synthesis.ch>
+
+       * src/DB_interfaces/odbc_db/odbcapiagent.cpp:
+
+       ODBC STD servers and clients: did not work at all (connection
+       string always empty)
+
+2009-10-16  Lukas Zeller  <luz@synthesis.ch>
+
+       * src/sysync/engineinterface.cpp:
+       * src/sysync_SDK/Sources/sync_dbapidef.h:
+
+       comment cosmetics
+
+2009-10-15  Lukas Zeller  <luz@synthesis.ch>
+
+       * src/sysync/mimedirprofile.cpp:
+
+       vcard/vcal folding: Made sure folding does not occur within UTF-8
+       sequences
+
 2009-10-15  Lukas Zeller  <luz@synthesis.ch>
 
        * src/sysync/mimedirprofile.cpp:
        vcard/vcal B64 properties: added workaround to recognize
        improperly folded B64 properties
 
+2009-10-13  Lukas Zeller  <luz@synthesis.ch>
+
+       * src/DB_interfaces/api_db/pluginapids.cpp:
+       * src/sysync/localengineds.cpp:
+       * src/sysync/multifielditem.cpp:
+       * src/sysync/stdlogicds.cpp:
+       * src/sysync/syncagent.cpp:
+       * src/sysync/syncsession.cpp:
+
+       unilib: eliminated another bunch of printf argument warnings by
+       casting all %ld arguments to (long)
+
+2009-10-13  Lukas Zeller  <luz@synthesis.ch>
+
+       * src/sysync/engineinterface.cpp:
+
+       engineinterface: added missing return statement for
+       returnLineartime()
+
+2009-10-08  Beat Forster  <elisabethegli@beat-forsters-macbook-pro.local>
+
+       * src/sysync/customimplds.cpp:
+
+       stl_minimal has no != operator => use ==
+
+2009-10-08  Beat Forster  <elisabethegli@beat-forsters-macbook-pro.local>
+
+       * src/global_options.h:
+       * src/platform_adapters/linux/configfiles.cpp:
+
+       ANDROID strings added
+
+2009-10-08  Beat Forster  <elisabethegli@beat-forsters-macbook-pro.local>
+
+       * src/DB_interfaces/api_db/pluginapids.cpp:
+       * src/DB_interfaces/odbc_db/odbcapiagent.cpp:
+       * src/sysync/syncagent.cpp:
+       * src/sysync_SDK/Sources/stringutil.cpp:
+
+       unilib: several type adaptions for changes due to unilib
+
+2009-10-13  Lukas Zeller  <luz@synthesis.ch>
+
+
+       Merge remote branch 'moblin/unilib' into unilib
+
+2009-10-13  Lukas Zeller  <luz@synthesis.ch>
+
+       * src/sysync/syncclientbase.cpp:
+
+       unilib: make sure no half-constructed session is left over at
+       failed OpenSession()
+
+2009-10-08  Lukas Zeller  <luz@synthesis.ch>
+
+       * src/DB_interfaces/api_db/pluginapids.cpp:
+       * src/sysync/customimplagent.cpp:
+       * src/sysync/customimplds.cpp:
+       * src/sysync/syncsession.cpp:
+
+       unilib cleanup: fixed some build problems introduced through
+       unilib
+
+2009-10-08  Lukas Zeller  <luz@synthesis.ch>
+
+       * src/DB_interfaces/odbc_db/odbcapiagent.cpp:
+       * src/sysync/customimplagent.h:
+
+       unilib: fixed case for targets with no binfile compiled in at all
+
+2009-10-07  Lukas Zeller  <luz@synthesis.ch>
+
+       * src/sysync/syserial.h:
+
+       syserial product codes: added codes for Android client and server
+       libs, changed Win32 server code (was overlapping iPhone client
+       lib)
+
+2009-10-07  Beat Forster  <elisabethegli@beat-forsters-macbook-pro.local>
+
+       * src/sysync_SDK/Sources/SDK_util.c:
+       * src/sysync_SDK/Sources/sync_dbapidef.h:
+
+       SDK: version changed to V1.6.1
+
+2009-10-13  Lukas Zeller  <luz@synthesis.ch>
+
+       * src/sysync/engineinterface.cpp:
+       * src/sysync/engineinterface.h:
+       * src/sysync/syncagent.cpp:
+
+       engine: added "lastused" and "timeout" session keys for server
+       session timeout handling
+
+2009-10-12  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/gen-makefile-am.sh:
+
+       autotools build: only build SAN code as part of the SDK
+
+2009-10-08  Lukas Zeller  <luz@synthesis.ch>
+
+
+       Merge remote branch 'moblin/unilib' into unilib
+
+2009-10-08  Lukas Zeller  <luz@synthesis.ch>
+
+
+       Merge branch 'luz' into unilib
+
+2009-10-08  Lukas Zeller  <luz@synthesis.ch>
+
+
+       Merge remote branch 'moblin/san' into luz
+
+2009-10-07  Lukas Zeller  <luz@synthesis.ch>
+
+
+       Merge branch 'luz' into unilib
+
+2009-10-07  Beat Forster  <bfo@synthesis.ch>
+
+       * src/platform_adapters/linux/configfiles.cpp:
+       * src/platform_adapters/linux/platform_time.cpp:
+
+       platform adapters Linux: Android adaptions
+
+2009-10-07  Lukas Zeller  <luz@synthesis.ch>
+
+       * src/sysync/localengineds.cpp:
+
+       localengineds: avoid using != operator on strings because STLs
+       exist that only support == 
+
+2009-10-07  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * Makefile.am:
+       * configure.in:
+       * src/Makefile.am.in:
+       * src/gen-makefile-am.sh:
+       * src/sysync_SDK/Sources/enginestubs.c:
+       * synthesis-sdk.pc.in:
+       * synthesis.pc.in:
+
+       autotools + pkg-config: added synthesis-sdk.pc
+
 2009-10-02  Patrick Ohly  <patrick.ohly@intel.com>
 
        * src/Makefile.am.in:
 
        libsynthesis + autotools: must be linked against libz
 
+2009-10-07  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/sysync/syncappbase.cpp:
+
+       syncappbasse: turned extern "C" into static functions
+
+2009-10-02  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * configure.in:
+       * src/Makefile.am.in:
+       * src/gen-makefile-am.sh:
+       * src/synthesis-linker.map:
+       * src/sysync_SDK/Sources/UI_util.cpp:
+
+       autotools build: switched to new combi engine
+
+2009-10-07  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/sysync/dataconversion.cpp:
+
+       DataConversion(): adapted dummy engine to server API
+
+2009-09-24  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * configure.in:
+       * src/sysync/san.cpp:
+       * src/sysync/san.h:
+       * src/sysync/sysync_b64.cpp:
+       * src/sysync/sysync_b64.h:
+       * src/sysync/sysync_md5.cpp:
+       * src/sysync/sysync_md5.h:
+       * src/sysync_SDK/Sources/san.cpp:
+       * src/sysync_SDK/Sources/san.h:
+       * src/sysync_SDK/Sources/sysync_b64.cpp:
+       * src/sysync_SDK/Sources/sysync_b64.h:
+       * src/sysync_SDK/Sources/sysync_md5.cpp:
+       * src/sysync_SDK/Sources/sysync_md5.h:
+
+       SAN: moved to SDK, together with the corresponding utility
+       classes
+
+2009-10-03  Lukas Zeller  <luz@synthesis.ch>
+
+       * src/Targets/ReleasedProducts/combiEngine_opensource_linux/combiengine_opensource_linux_prefix.h:
+
+       unilib linux compile: corrected include (no separate combi-engine
+       include file exists here)
+
+2009-10-03  Lukas Zeller  <luz@synthesis.ch>
+
+       * src/client_engine_linux.mk:
+       * src/combi_engine_linux.mk:
+       * src/server_engine_linux.mk:
+
+       unilib: added plain makefile for combined client+server engine,
+       adapted client-only and server-only to use syncagent.h/.cpp
+
+2009-10-03  Lukas Zeller  <luz@synthesis.ch>
+
+       * src/sysync/syncclient.cpp:
+       * src/sysync/syncclient.h:
+       * src/sysync/syncserver.cpp:
+       * src/sysync/syncserver.h:
+
+       unilib: removed now obsolete syncclient/syncserver files
+
+2009-10-03  Lukas Zeller  <luz@synthesis.ch>
+
+
+       Merge branch 'luz' into unilib
+
+2009-10-03  Lukas Zeller  <luz@synthesis.ch>
+
+       * src/sysync_SDK/Sources/UI_util.cpp:
+
+       engine entry points: adjusted as per discussion (Patrick/bfo)
+
+2009-10-01  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/sysync_SDK/Sources/UI_util.cpp:
+       * src/sysync_SDK/Sources/UI_util.h:
+       * src/sysync_SDK/Sources/enginemodulebridge.cpp:
+       * src/sysync_SDK/Sources/enginemodulebridge.h:
+
+       SDK engine connect: allow choosing between client and server
+       engine
+
+2009-10-01  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/platform_adapters/linux/platform_DLL.cpp:
+
+       Linux platform_DLL: open shared library with name as requested
+
+2009-10-01  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/sysync/engineentry.h:
+       * src/sysync_SDK/Sources/sync_dbapidef.h:
+
+       use ENGINE_ENTRY_CXX to mark external C++ functions
+
+2009-10-01  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/sysync/dataobjtype.cpp:
+
+       added "namespace sysync"
+
+2009-09-27  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/Makefile.am.in:
+       * src/gen-makefile-am.sh:
+
+       autotools: added make rules for server engine
+       (libsynthesisserver.so)
+
+2009-10-03  Lukas Zeller  <luz@synthesis.ch>
+
+
+       Merge remote branch 'origin/bfo' into luz
+
+2009-09-27  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/sysync/syncsession.cpp:
+
+       TSyncSession: unitialized fEncoding
+
+2009-10-03  Lukas Zeller  <luz@synthesis.ch>
+
+
+       Merge remote branch 'moblin/master' into luz
+
+2009-10-03  Lukas Zeller  <luz@synthesis.ch>
+
+       * src/Targets/ReleasedProducts/combiEngine_opensource_linux/combiengine_demo++.pch:
+       * src/Targets/ReleasedProducts/combiEngine_opensource_linux/combiengine_demo.pch:
+       * src/Targets/ReleasedProducts/combiEngine_opensource_linux/combiengine_opensource_linux_prefix.h:
+       * src/Targets/ReleasedProducts/combiEngine_opensource_linux/define.h:
+       * src/Targets/ReleasedProducts/combiEngine_opensource_linux/target_options.h:
+
+       opensource linux combiengine: added new target files
+
+2009-10-02  Lukas Zeller  <luz@synthesis.ch>
+
+       * src/DB_interfaces/api_db/pluginapiagent.cpp:
+       * src/DB_interfaces/api_db/pluginapiagent.h:
+       * src/DB_interfaces/odbc_db/odbcapiagent.cpp:
+       * src/Transport_interfaces/engine/engineclientbase.cpp:
+       * src/Transport_interfaces/engine/engineclientbase.h:
+       * src/Transport_interfaces/engine/enginesessiondispatch.cpp:
+       * src/Transport_interfaces/engine/enginesessiondispatch.h:
+       * src/syncapps/serverEngine_custom/serverengine_custom_Base.cpp:
+       * src/sysync/localengineds.cpp:
+       * src/sysync/localengineds.h:
+       * src/sysync/stdlogicagent.h:
+       * src/sysync/stdlogicds.cpp:
+       * src/sysync/superdatastore.cpp:
+       * src/sysync/superdatastore.h:
+       * src/sysync/syncagent.cpp:
+       * src/sysync/syncagent.h:
+       * src/sysync/syncappbase.cpp:
+       * src/sysync/syncappbase.h:
+       * src/sysync/syncclientbase.cpp:
+       * src/sysync/synccommand.cpp:
+       * src/sysync/synccommand.h:
+       * src/sysync/syncdatastore.cpp:
+       * src/sysync/syncdatastore.h:
+       * src/sysync/syncitem.cpp:
+       * src/sysync/syncitem.h:
+       * src/sysync/syncsession.cpp:
+       * src/sysync/syncsessiondispatch.cpp:
+       * src/sysync/sysync_globs.h:
+
+       unilib: fixes needed to actually have both client&server enabled
+       in the same build
+
+2009-10-02  Lukas Zeller  <luz@synthesis.ch>
+
+       * src/syncapps/clientEngine_custom/product_options.h:
+       * src/syncapps/serverEngine_custom/combi_product_options.h:
+
+       unilib: "combiEngine" product options added
+
+2009-10-02  Lukas Zeller  <luz@synthesis.ch>
+
+       * src/DB_interfaces/odbc_db/odbcapiagent.cpp:
+       * src/DB_interfaces/odbc_db/odbcapids.cpp:
+       * src/Transport_interfaces/engine/enginesessiondispatch.cpp:
+       * src/platform_adapters/platform_thread.h:
+       * src/platform_adapters/unix_common/platform_thread.cpp:
+       * src/sysync/stdlogicds.cpp:
+       * src/sysync/stringutils.cpp:
+       * src/sysync/syncappbase.cpp:
+       * src/sysync/syncsessiondispatch.cpp:
+       * src/sysync/sysync_md5.cpp:
+       * src/sysync/sysync_md5.h:
+       * src/sysync_SDK/Sources/generic_types.h:
+
+       64 bit: adjusted generic_types.h to make sure uInt32/sInt32 IS
+       32bits
+
+2009-10-02  Lukas Zeller  <luz@synthesis.ch>
+
+       * src/syncapps/clientEngine_custom/clientengine_custom_Base.cpp:
+       * src/syncapps/clientEngine_custom/product_options.h:
+       * src/syncapps/serverEngine_custom/product_options.h:
+       * src/syncapps/serverEngine_custom/serverengine_custom_Base.cpp:
+       * src/sysync/binfileimplclient.cpp:
+       * src/sysync/customimplagent.cpp:
+       * src/sysync/engineinterface.cpp:
+       * src/sysync/engineinterface.h:
+       * src/sysync/syncagent.cpp:
+       * src/sysync/syncappbase.cpp:
+       * src/sysync/syncclientbase.cpp:
+       * src/sysync_SDK/Sources/enginemodulebase.h:
+       * src/sysync_SDK/Sources/sync_dbapidef.h:
+
+       unilib: prepared co-existence of server and client library
+       instance, added entry points
+
+2009-10-01  Lukas Zeller  <luz@synthesis.ch>
+
+       * src/DB_interfaces/api_db/pluginapiagent.cpp:
+       * src/DB_interfaces/api_db/pluginapiagent.h:
+       * src/DB_interfaces/api_db/pluginapids.cpp:
+       * src/DB_interfaces/api_db/pluginapids.h:
+       * src/DB_interfaces/odbc_db/odbcapiagent.cpp:
+       * src/DB_interfaces/odbc_db/odbcapiagent.h:
+       * src/DB_interfaces/odbc_db/odbcdb.h:
+       * src/global_options.h:
+       * src/sysync/binfileimplclient.cpp:
+       * src/sysync/binfileimplclient.h:
+       * src/sysync/binfileimplds.cpp:
+       * src/sysync/binfileimplds.h:
+       * src/sysync/customimplagent.cpp:
+       * src/sysync/customimplagent.h:
+       * src/sysync/customimplds.cpp:
+       * src/sysync/customimplds.h:
+       * src/sysync/stdlogicagent.cpp:
+       * src/sysync/stdlogicagent.h:
+       * src/sysync/syncagent.cpp:
+       * src/sysync/syncagent.h:
+       * src/sysync/sysync_precomp.h:
+
+       unilib: binfile/customimpl: Now binfile can be included but kept
+       inactive
+
+2009-10-01  Lukas Zeller  <luz@synthesis.ch>
+
+       * src/sysync/binfileimplclient.cpp:
+       * src/sysync/binfileimplclient.h:
+       * src/sysync/binfileimplds.cpp:
+       * src/sysync/binfileimplds.h:
+       * src/sysync/syncsession.h:
+
+       binfiles: made binfileimplclient/ds such that they can be
+       switched off (e.g. for unilib server)
+
+2009-10-01  Lukas Zeller  <luz@synthesis.ch>
+
+       * src/sysync/syncagent.cpp:
+       * src/sysync/syncagent.h:
+
+       unilib: unified TClientParamsKey and TServerParamsKey into
+       TAgentParamsKey
+
+2009-10-01  Lukas Zeller  <luz@synthesis.ch>
+
+       * src/Transport_interfaces/engine/engineclientbase.h:
+       * src/Transport_interfaces/engine/enginesessiondispatch.h:
+       * src/syncapps/sysytool/sysytool.cpp:
+       * src/sysync/binfileimplclient.h:
+       * src/sysync/localengineds.cpp:
+       * src/sysync/remotedatastore.cpp:
+       * src/sysync/stdlogicagent.h:
+       * src/sysync/syncagent.cpp:
+       * src/sysync/syncagent.h:
+       * src/sysync/syncappbase.h:
+       * src/sysync/syncclient.h:
+       * src/sysync/syncclientbase.cpp:
+       * src/sysync/syncclientbase.h:
+       * src/sysync/syncserver.h:
+       * src/sysync/syncsession.h:
+       * src/sysync/syncsessiondispatch.h:
+
+       unlib: including syncagent.h everywhere where we had syncclient.h
+       or syncserver.h
+
+2009-09-30  Lukas Zeller  <luz@synthesis.ch>
+
+       * src/DB_interfaces/api_db/pluginapiagent.cpp:
+       * src/DB_interfaces/api_db/pluginapiagent.h:
+       * src/DB_interfaces/odbc_db/odbcapiagent.cpp:
+       * src/DB_interfaces/odbc_db/odbcapiagent.h:
+       * src/Transport_interfaces/engine/enginesessiondispatch.cpp:
+       * src/Transport_interfaces/engine/enginesessiondispatch.h:
+       * src/sysync/binfileimplclient.cpp:
+       * src/sysync/binfileimplclient.h:
+       * src/sysync/customimplagent.cpp:
+       * src/sysync/customimplagent.h:
+       * src/sysync/localengineds.cpp:
+       * src/sysync/localengineds.h:
+       * src/sysync/mimedirprofile.cpp:
+       * src/sysync/remotedatastore.cpp:
+       * src/sysync/remotedatastore.h:
+       * src/sysync/stdlogicagent.cpp:
+       * src/sysync/stdlogicagent.h:
+       * src/sysync/syncagent.cpp:
+       * src/sysync/syncagent.h:
+       * src/sysync/syncappbase.cpp:
+       * src/sysync/syncappbase.h:
+       * src/sysync/syncclient.cpp:
+       * src/sysync/syncclient.h:
+       * src/sysync/syncclientbase.cpp:
+       * src/sysync/syncclientbase.h:
+       * src/sysync/synccommand.cpp:
+       * src/sysync/syncserver.cpp:
+       * src/sysync/syncserver.h:
+       * src/sysync/syncsession.cpp:
+       * src/sysync/syncsession.h:
+       * src/sysync/syncsessiondispatch.cpp:
+       * src/sysync/syncsessiondispatch.h:
+
+       unilib: united former syncserver/syncclient into syncagent.h/.cpp
+
+2009-09-29  Lukas Zeller  <luz@synthesis.ch>
+
+       * src/DB_interfaces/api_db/pluginapiagent.cpp:
+       * src/DB_interfaces/api_db/pluginapiagent.h:
+       * src/DB_interfaces/api_db/pluginapids.cpp:
+       * src/DB_interfaces/odbc_db/odbcapiagent.cpp:
+       * src/DB_interfaces/odbc_db/odbcapiagent.h:
+       * src/DB_interfaces/odbc_db/odbcapids.cpp:
+       * src/global_options.h:
+       * src/sysync/customimplds.cpp:
+       * src/sysync/customimplds.h:
+       * src/sysync/localengineds.cpp:
+       * src/sysync/localengineds.h:
+       * src/sysync/multifielditem.cpp:
+       * src/sysync/multifielditem.h:
+       * src/sysync/multifielditemtype.cpp:
+       * src/sysync/remotedatastore.cpp:
+       * src/sysync/stdlogicagent.cpp:
+       * src/sysync/stdlogicagent.h:
+       * src/sysync/stdlogicds.cpp:
+       * src/sysync/stdlogicds.h:
+       * src/sysync/superdatastore.cpp:
+       * src/sysync/superdatastore.h:
+       * src/sysync/syncappbase.cpp:
+       * src/sysync/syncclient.cpp:
+       * src/sysync/synccommand.cpp:
+       * src/sysync/synccommand.h:
+       * src/sysync/syncsession.cpp:
+       * src/sysync/sysync_globs.h:
+       * src/sysync/textprofile.cpp:
+
+       unilib started: engine version 3.3.0.0 to differentiate from
+       normal 3.2.x.x non-unified builds
+
+2009-09-28  Beat Forster  <elisabethegli@beat-forsters-macbook-pro.local>
+
+       * src/sysync_SDK/DB_Interfaces/text_db/sync_dbapi_text.cpp:
+
+       save changed nonce value (again)
+
+2009-09-09  Beat Forster  <elisabethegli@beat-forsters-macbook-pro.local>
+
+       * src/platform_adapters/linux/configfiles.cpp:
+       * src/platform_adapters/linux/platform_time.cpp:
+       * src/sysync_SDK/DB_Interfaces/text_db/sync_dbapi_text.cpp:
+
+       cleanup: appCharP type casting added, some updates for Android
+       port
+
+2009-09-25  Lukas Zeller  <luz@synthesis.ch>
+
+       * src/sysync/scriptcontext.cpp:
+
+       scripts: added TIMEONLY() function, enhanced POINTINTIME() not
+       only to convert duration, but also dateonly and timeonly to
+       timestamp
+
+2009-09-25  Lukas Zeller  <luz@synthesis.ch>
+
+       * src/sysync/customimplds.cpp:
+
+       debug log: wrapped finalizing item into block which shows localID
+
+2009-09-25  Lukas Zeller  <luz@synthesis.ch>
+
+       * src/DB_interfaces/odbc_db/odbcapids.cpp:
+
+       Debug output cosmetics (array map name is always "array", so do
+       not show it)
+
+2009-09-24  Lukas Zeller  <luz@synthesis.ch>
+
+       * src/sysync/syncclient.cpp:
+
+       client engine: when incoming data is not SyncML, this must abort
+       the session and dump the message
+
+2009-10-02  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/Makefile.am.in:
+
+       libsynthesis + autotools: must be linked against libz
+
+2009-09-30  Beat Forster  <bfo@synthesis.ch>
+
+       * src/sysync_SDK/DB_Interfaces/text_db/sync_dbapi_text.cpp:
+
+       SetNonce fChanged problem fixed; some type casting cAppChar
+
+2009-09-24  Lukas Zeller  <luz@synthesis.ch>
+
+
+       Merge remote branch 'moblin/master' into luz
+
+2009-09-24  Lukas Zeller  <luz@synthesis.ch>
+
+       * src/Transport_interfaces/engine/enginesessiondispatch.cpp:
+       * src/Transport_interfaces/engine/enginesessiondispatch.h:
+       * src/sysync/syncappbase.cpp:
+       * src/sysync/syncappbase.h:
+       * src/sysync/syncclient.cpp:
+       * src/sysync/syncserver.cpp:
+       * src/sysync/syncserver.h:
+       * src/sysync/syncsession.cpp:
+       * src/sysync/syncsession.h:
+
+       libsynthesis_srv: implementation complete - runs sync sessions ok
+       with textDB backend.
+
+2009-09-24  Lukas Zeller  <luz@synthesis.ch>
+
+       * src/sysync/localengineds.cpp:
+       * src/sysync/mimedirprofile.cpp:
+       * src/sysync/syncsession.cpp:
+
+       cleanup: eliminated some compiler warnings about shadowing local
+       declarations
+
+2009-09-24  Lukas Zeller  <luz@synthesis.ch>
+
+       * src/Targets/ReleasedProducts/serverEngine_opensource_linux/target_options.h:
+       * src/server_engine_linux.mk:
+       * src/syncapps/serverEngine_custom/product_options.h:
+
+       libsynthesis_srv configuration adjusted
+
+2009-09-24  Lukas Zeller  <luz@synthesis.ch>
+
+       * src/sysync_SDK/configs/syncserv_sample_config.xml:
+
+       libsynthesis_srv: added sample config for a TextDB based server
+
 2009-09-23  Patrick Ohly  <patrick.ohly@intel.com>
 
        * src/sysync_SDK/Sources/engine_defs.h:
 
 2009-09-22  Lukas Zeller  <luz@synthesis.ch>
 
+       * src/Targets/ReleasedProducts/serverEngine_opensource_linux/serverengine_demo++.pch:
+       * src/Targets/ReleasedProducts/serverEngine_opensource_linux/serverengine_demo.pch:
+       * src/Targets/ReleasedProducts/serverEngine_opensource_linux/serverengine_opensource++.pch:
+       * src/Targets/ReleasedProducts/serverEngine_opensource_linux/serverengine_opensource.pch:
+       * src/Transport_interfaces/engine/engine_server.h:
+       * src/Transport_interfaces/engine/engine_server_precomp.h:
+       * src/Transport_interfaces/engine/enginesessiondispatch.cpp:
+       * src/Transport_interfaces/engine/enginesessiondispatch.h:
+       * src/client_engine_linux.mk:
+       * src/server_engine_linux.mk:
+       * src/syncapps/serverEngine_custom/product_options.h:
+       * src/syncapps/serverEngine_custom/serverengine_custom.h:
+       * src/syncapps/serverEngine_custom/serverengine_custom_Base.cpp:
+       * src/syncapps/serverEngine_custom/serverengine_custom_Base.h:
+       * src/syncapps/serverEngine_custom/serverengine_custom_precomp.h:
+
+       libsynthesis_srv: added required files, traditional non-automake
+       works for server engine
+
+2009-09-22  Lukas Zeller  <luz@synthesis.ch>
+
        * src/sysync/localengineds.cpp:
 
        engine: statistics workaround for servers not sending status 201
index 15cdb3f..9ae6ac1 100644 (file)
@@ -11,4 +11,4 @@ MAINTAINERCLEANFILES = Makefile.in config.guess config.sub configure depcomp ins
 ACLOCAL_AMFLAGS = -I m4
 
 pkgconfigdir = $(libdir)/pkgconfig
-pkgconfig_DATA = synthesis.pc
+pkgconfig_DATA = synthesis.pc synthesis-sdk.pc
index b2636cd..0a77e04 100644 (file)
@@ -38,8 +38,9 @@ DIST_COMMON = README $(am__configure_deps) $(srcdir)/../../compile \
        $(srcdir)/../../install-sh $(srcdir)/../../ltmain.sh \
        $(srcdir)/../../missing $(srcdir)/../../mkinstalldirs \
        $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
-       $(srcdir)/config.h.in $(srcdir)/synthesis.pc.in \
-       $(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS
+       $(srcdir)/config.h.in $(srcdir)/synthesis-sdk.pc.in \
+       $(srcdir)/synthesis.pc.in $(top_srcdir)/configure AUTHORS \
+       COPYING ChangeLog INSTALL NEWS
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/configure.in
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
@@ -48,7 +49,7 @@ am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
  configure.lineno config.status.lineno
 mkinstalldirs = $(SHELL) $(top_srcdir)/../../mkinstalldirs
 CONFIG_HEADER = config.h
-CONFIG_CLEAN_FILES = synthesis.pc
+CONFIG_CLEAN_FILES = synthesis.pc synthesis-sdk.pc
 SOURCES =
 DIST_SOURCES =
 RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
@@ -211,7 +212,7 @@ EXTRA_DIST =
 MAINTAINERCLEANFILES = Makefile.in config.guess config.sub configure depcomp install-sh ltmain.sh missing mkinstalldirs
 ACLOCAL_AMFLAGS = -I m4
 pkgconfigdir = $(libdir)/pkgconfig
-pkgconfig_DATA = synthesis.pc
+pkgconfig_DATA = synthesis.pc synthesis-sdk.pc
 all: config.h
        $(MAKE) $(AM_MAKEFLAGS) all-recursive
 
@@ -268,6 +269,8 @@ distclean-hdr:
        -rm -f config.h stamp-h1
 synthesis.pc: $(top_builddir)/config.status $(srcdir)/synthesis.pc.in
        cd $(top_builddir) && $(SHELL) ./config.status $@
+synthesis-sdk.pc: $(top_builddir)/config.status $(srcdir)/synthesis-sdk.pc.in
+       cd $(top_builddir) && $(SHELL) ./config.status $@
 
 mostlyclean-libtool:
        -rm -f *.lo
index f9ec185..0346788 100644 (file)
@@ -1,8 +1,11 @@
 /* config.h.in.  Generated from configure.in by autoheader.  */
 
-/* libsynthesis.a linked statically */
+/* client engine linked statically */
 #undef DBAPI_LINKED
 
+/* server engine linked statically */
+#undef DBAPI_SRV_LINKED
+
 /* avoid hard dependency on Evolution shared objects */
 #undef EVOLUTION_COMPATIBILITY
 
@@ -80,3 +83,6 @@
 
 /* Version number of package */
 #undef VERSION
+
+/* support for Server Alerted Notifications according to SyncML 1.1 */
+#undef WITHOUT_SAN_1_1
index 48f22b1..6a3b96d 100755 (executable)
@@ -21158,8 +21158,7 @@ fi
 
 
 
-echo "enable dynamic $enable_shared"
-if test "$enable_shared" = "no"; then
+# the autotools SDK always assumes that it is linked against the engine
 
 cat >>confdefs.h <<\_ACEOF
 #define UIAPI_LINKED 1
@@ -21170,7 +21169,15 @@ cat >>confdefs.h <<\_ACEOF
 #define DBAPI_LINKED 1
 _ACEOF
 
-fi
+
+cat >>confdefs.h <<\_ACEOF
+#define DBAPI_SRV_LINKED 1
+_ACEOF
+
+
+# determines which object files are needed in the SDK:
+# if linking statically, some object files are shared with
+# libsynthesis.a
  if test "$enable_shared" = "no"; then
   COND_STATIC_TRUE=
   COND_STATIC_FALSE='#'
@@ -21180,7 +21187,15 @@ else
 fi
 
 
-ac_config_files="$ac_config_files Makefile src/Makefile synthesis.pc"
+# Disable unconditionally at the moment. Would add dependency of SDK
+# on SyncML Toolkit.
+
+cat >>confdefs.h <<\_ACEOF
+#define WITHOUT_SAN_1_1 1
+_ACEOF
+
+
+ac_config_files="$ac_config_files Makefile src/Makefile synthesis.pc synthesis-sdk.pc"
 
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
@@ -21785,6 +21800,7 @@ do
     "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
     "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
     "synthesis.pc") CONFIG_FILES="$CONFIG_FILES synthesis.pc" ;;
+    "synthesis-sdk.pc") CONFIG_FILES="$CONFIG_FILES synthesis-sdk.pc" ;;
 
   *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
 echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
index b7c015d..35a7653 100644 (file)
@@ -67,7 +67,7 @@ AC_ARG_WITH(expat,
 if test "$with_xmltok" = "no" && test "$with_expat" = "no"; then
    if test "$have_system_expat" = "yes"; then
       with_expat="yes"
-      XMLPARSE_LIBS="-lexpat" 
+      XMLPARSE_LIBS="-lexpat"
    elif test "$have_system_xmltok" = "yes"; then
       with_xmltok="yes"
       XMLPARSE_LIBS="-lxmlparse"
@@ -109,12 +109,20 @@ AM_CONDITIONAL([COND_XMLPARSE], [test "$with_xmltok" = "builtin"])
 
 AC_CHECK_HEADER(stdint.h)
 
-echo "enable dynamic $enable_shared"
-if test "$enable_shared" = "no"; then
-   AC_DEFINE(UIAPI_LINKED, 1, [libsynthesis.a linked statically])
-   AC_DEFINE(DBAPI_LINKED, 1, [libsynthesis.a linked statically])
-fi
+# the autotools SDK always assumes that it is linked against the engine
+AC_DEFINE(UIAPI_LINKED, 1, [libsynthesis.a linked statically])
+AC_DEFINE(DBAPI_LINKED, 1, [client engine linked statically])
+AC_DEFINE(DBAPI_SRV_LINKED, 1, [server engine linked statically])
+
+# determines which object files are needed in the SDK:
+# if linking statically, some object files are shared with
+# libsynthesis.a
 AM_CONDITIONAL([COND_STATIC], [test "$enable_shared" = "no"])
 
-AC_CONFIG_FILES(Makefile src/Makefile synthesis.pc)
+# Disable unconditionally at the moment. Would add dependency of SDK
+# on SyncML Toolkit.
+AC_DEFINE(WITHOUT_SAN_1_1, 1,
+          [support for Server Alerted Notifications according to SyncML 1.1])
+
+AC_CONFIG_FILES(Makefile src/Makefile synthesis.pc synthesis-sdk.pc)
 AC_OUTPUT
index c964b29..77f5b91 100755 (executable)
@@ -281,13 +281,8 @@ void TPluginAgentConfig::localResolve(bool aLastPass)
 // ===============
 
 
-#ifdef SYSYNC_CLIENT
-TPluginApiAgent::TPluginApiAgent(TSyncClientBase *aSyncClientBaseP, const char *aSessionID) :
-  inherited(aSyncClientBaseP, aSessionID),
-#else
-TPluginApiAgent::TPluginApiAgent(TSyncAppBase *aAppBaseP, TSyncSessionHandle *aSessionHandleP, const char *aSessionID) :
+TPluginApiAgent::TPluginApiAgent(TSyncAppBase *aAppBaseP, TSyncSessionHandle *aSessionHandleP, cAppCharP aSessionID) :
   inherited(aAppBaseP, aSessionHandleP, aSessionID),
-#endif
   fPluginAgentConfigP(NULL),
   fApiLocked(false)
 {
@@ -397,7 +392,7 @@ lineartime_t TPluginApiAgent::getDatabaseNowAs(timecontext_t aTimecontext)
 
 
 
-#ifndef SYSYNC_CLIENT
+#ifdef SYSYNC_SERVER
 
 // info about requested auth type
 TAuthTypes TPluginApiAgent::requestedAuthType(void)
@@ -405,7 +400,7 @@ TAuthTypes TPluginApiAgent::requestedAuthType(void)
   // if not checking via api, let inherited decide
   if (!fPluginAgentConfigP->fApiSessionAuth) return inherited::requestedAuthType();
   // get default
-  TAuthTypes auth = TSyncServer::requestedAuthType();
+  TAuthTypes auth = TSyncAgent::requestedAuthType();
   // depending on possibilities of used module, we need to enforce basic
   int pwmode=fDBApiSession.PasswordMode();
   if (pwmode==Password_ClrText_IN || (pwmode==Password_MD5_OUT && getSyncMLVersion()<syncml_vers_1_1)) {
@@ -466,7 +461,7 @@ void TPluginApiAgent::getNextNonce(const char *aDeviceID, string &aNextNonce)
 #endif // SYSYNC_CLIENT
 
 
-#ifndef BASED_ON_BINFILE_CLIENT
+#ifndef BINFILE_ALWAYS_ACTIVE
 
 
 // check device related stuff
@@ -492,10 +487,12 @@ void TPluginApiAgent::CheckDevice(const char *aDeviceID)
     TSyError sta = fDBApiSession.CheckDevice(aDeviceID,deviceKey,lastNonce);
     if (sta!=LOCERR_OK)
       SYSYNC_THROW(TSyncException("TPluginApiAgent: checkdevice failed",sta));
-    #ifndef SYSYNC_CLIENT
-    // save last nonce
-    fLastNonce = lastNonce.c_str();
-    #endif
+    #ifdef SYSYNC_SERVER
+    if (IS_SERVER) {
+      // save last nonce
+      fLastNonce = lastNonce.c_str();
+    }
+    #endif // SYSYNC_SERVER
     // device "key" is set to deviceID. Plugin internally maintains its key needed for storing Nonce or DevInf
     fDeviceKey = deviceKey.c_str();
   } // if device table implemented in ApiDB
@@ -590,9 +587,22 @@ bool TPluginApiAgent::CheckLogin(const char *aOriginalUserName, const char *aMod
   }
   // api auth required
   TDB_Api_Str userKey;
+  TDB_Api_Str dbSecret;
   int pwmode = fDBApiSession.PasswordMode();
+  // check anonymous login
+  if (aAuthStringType==sectyp_anonymous) {
+       if (pwmode==Password_ClrText_IN || pwmode==Password_MD5_Nonce_IN) {
+       // modes that pass in credential string - pass empty credential string to signal "anonymous"
+           authok = fDBApiSession.Login(aModifiedUserName,"",userKey)==LOCERR_OK;
+    }
+    else {
+       // modes that get credential string from API - check that API returns empty string to signal "anonymous" login is ok
+           authok = fDBApiSession.Login(aModifiedUserName,dbSecret,userKey)==LOCERR_OK;
+      authok = authok && dbSecret.empty(); // returned secret must be empty to allow anonymous login
+    }
+  }
   // check if we can auth at all
-  if (pwmode == Password_ClrText_IN) {
+  else if (pwmode == Password_ClrText_IN) {
     // we can auth only if we have a cleartext password from the remote
     if (aAuthStringType!=sectyp_clearpass) return false; // auth not possible
     // login with clear text password
@@ -604,23 +614,22 @@ bool TPluginApiAgent::CheckLogin(const char *aOriginalUserName, const char *aMod
     authok = fDBApiSession.Login(aModifiedUserName,aAuthString,userKey)==LOCERR_OK;
   }
   else {
-    TDB_Api_Str dbSecret;
     if (pwmode == Password_MD5_OUT) {
       // if the database has MD5, we can auth basic and SyncML 1.1 MD5, but not SyncML 1.0 MD5
       if (aAuthStringType==sectyp_md5_V10) return false; // auth with SyncML 1.0 MD5 not possible
     }
     // get Secret and preliminary authok (w/o password check yet) from database
-    authok= fDBApiSession.Login(aModifiedUserName,dbSecret,userKey)==LOCERR_OK;
+    authok = fDBApiSession.Login(aModifiedUserName,dbSecret,userKey)==LOCERR_OK;
     if (authok) {
       // check secret
       if (pwmode == Password_ClrText_OUT) {
         // we have the clear text password, check against what was transmitted from remote
-        authok=checkAuthPlain(aOriginalUserName,dbSecret.c_str(),nonce.c_str(),aAuthString,aAuthStringType);
+        authok = checkAuthPlain(aOriginalUserName,dbSecret.c_str(),nonce.c_str(),aAuthString,aAuthStringType);
       }
       else {
         // whe have the MD5 of user:password, check against what was transmitted from remote
         // Note: this can't work with non-V1.1 type creds
-        authok=checkAuthMD5(aOriginalUserName,dbSecret.c_str(),nonce.c_str(),aAuthString,aAuthStringType);
+        authok = checkAuthMD5(aOriginalUserName,dbSecret.c_str(),nonce.c_str(),aAuthString,aAuthStringType);
       }
     }
   }
@@ -645,7 +654,7 @@ bool TPluginApiAgent::CheckLogin(const char *aOriginalUserName, const char *aMod
   }
 } // TPluginApiAgent::CheckLogin
 
-#endif // not BASED_ON_BINFILE_CLIENT
+#endif // not BINFILE_ALWAYS_ACTIVE
 
 
 // - logout api
@@ -661,7 +670,7 @@ void TPluginApiAgent::LogoutApi(void)
 
 
 
-#ifndef SYSYNC_CLIENT
+#ifdef SYSYNC_SERVER
 
 void TPluginApiAgent::RequestEnded(bool &aHasData)
 {
@@ -685,16 +694,17 @@ void TPluginApiAgent::RequestEnded(bool &aHasData)
 
 #ifdef SYSYNC_CLIENT
 
-TSyncClient *TPluginAgentConfig::CreateClientSession(const char *aSessionID)
+TSyncAgent *TPluginAgentConfig::CreateClientSession(const char *aSessionID)
 {
   // return appropriate client session
-  MP_RETURN_NEW(TPluginApiAgent,DBG_HOT,"TPluginApiAgent",TPluginApiAgent(static_cast<TSyncClientBase *>(getSyncAppBase()),aSessionID));
+  MP_RETURN_NEW(TPluginApiAgent,DBG_HOT,"TPluginApiAgent",TPluginApiAgent(getSyncAppBase(),NULL,aSessionID));
 } // TPluginAgentConfig::CreateClientSession
 
+#endif
 
-#else
+#ifdef SYSYNC_SERVER
 
-TSyncServer *TPluginAgentConfig::CreateServerSession(TSyncSessionHandle *aSessionHandle, const char *aSessionID)
+TSyncAgent *TPluginAgentConfig::CreateServerSession(TSyncSessionHandle *aSessionHandle, const char *aSessionID)
 {
   // return XML2GO or ODBC-server session
   MP_RETURN_NEW(TPluginApiAgent,DBG_HOT,"TPluginApiAgent",TPluginApiAgent(getSyncAppBase(),aSessionHandle,aSessionID));
index 6e4cd4c..ead0eb4 100755 (executable)
@@ -110,10 +110,11 @@ protected:
 public:
   #ifdef SYSYNC_CLIENT
   // create appropriate session (=agent) for this client
-  virtual TSyncClient *CreateClientSession(const char *aSessionID);
-  #else
+  virtual TSyncAgent *CreateClientSession(const char *aSessionID);
+  #endif
+  #ifdef SYSYNC_SERVER
   // create appropriate session (=agent) for this server
-  virtual TSyncServer *CreateServerSession(TSyncSessionHandle *aSessionHandle, const char *aSessionID);
+  virtual TSyncAgent *CreateServerSession(TSyncSessionHandle *aSessionHandle, const char *aSessionID);
   #endif
 }; // TPluginAgentConfig
 
@@ -131,32 +132,28 @@ class TPluginApiAgent :
   typedef TCustomImplAgent inherited;
   #endif
 public:
-  #ifdef SYSYNC_CLIENT
-  TPluginApiAgent(TSyncClientBase *aSyncClientBaseP, const char *aSessionID);
-  #else
-  TPluginApiAgent(TSyncAppBase *aAppBaseP, TSyncSessionHandle *aSessionHandleP, const char *aSessionID);
-  #endif
+  TPluginApiAgent(TSyncAppBase *aAppBaseP, TSyncSessionHandle *aSessionHandleP, cAppCharP aSessionID);
   virtual ~TPluginApiAgent();
   virtual void TerminateSession(void); // Terminate session, like destructor, but without actually destructing object itself
   virtual void ResetSession(void); // Resets session (but unlike TerminateSession, session might be re-used)
   void InternalResetSession(void); // static implementation for calling through virtual destructor and virtual ResetSession();
   // user authentication
-  #ifndef SYSYNC_CLIENT
+  #ifdef SYSYNC_SERVER
   // - return auth type to be requested from remote
   virtual TAuthTypes requestedAuthType(void); // avoids MD5 when it cannot be checked
   // - get next nonce string top be sent to remote party for subsequent MD5 auth
   virtual void getNextNonce(const char *aDeviceID, string &aNextNonce);
   // - get nonce string, which is expected to be used by remote party for MD5 auth.
   virtual void getAuthNonce(const char *aDeviceID, string &aAuthNonce);
-  #endif
-  #ifndef BASED_ON_BINFILE_CLIENT
+  #endif // SYSYNC_SERVER
+  #ifndef BINFILE_ALWAYS_ACTIVE
   // - check device ID related stuff
   virtual void CheckDevice(const char *aDeviceID);
   // - remote device is analyzed, eventually save status
   virtual void remoteAnalyzed(void);
   // - check login for this session (everything else is done by CustomAgent's SessionLogin)
   virtual bool CheckLogin(const char *aOriginalUserName, const char *aModifiedUserName, const char *aAuthString, TAuthSecretTypes aAuthStringType, const char *aDeviceID);
-  #endif // not BASED_ON_BINFILE_CLIENT
+  #endif // not BINFILE_ALWAYS_ACTIVE
   // - logout
   void LogoutApi(void);
   // current database date & time
@@ -168,7 +165,7 @@ public:
   // get API session object
   TDB_Api_Session *getDBApiSession() { return &fDBApiSession; };
 protected:
-  #ifndef SYSYNC_CLIENT
+  #ifdef SYSYNC_SERVER
   // - request end, used to clean up
   virtual void RequestEnded(bool &aHasData);
   #endif
index 305c57c..5994345 100755 (executable)
@@ -240,12 +240,13 @@ void TPluginDSConfig::localResolve(bool aLastPass)
 TLocalEngineDS *TPluginDSConfig::newLocalDataStore(TSyncSession *aSessionP)
 {
   // Synccap defaults to normal set supported by the engine by default
-  TLocalEngineDS *ldsP =
-    #ifdef SYSYNC_CLIENT
-    new TPluginApiDS(this,aSessionP,getName(),aSessionP->getSyncCapMask() & ~(isOneWayFromRemoteSupported() ? 0 : SCAP_MASK_ONEWAY_SERVER));
-    #else
-    new TPluginApiDS(this,aSessionP,getName(),aSessionP->getSyncCapMask() & ~(isOneWayFromRemoteSupported() ? 0 : SCAP_MASK_ONEWAY_CLIENT));
-    #endif
+  TLocalEngineDS *ldsP;
+  if (IS_CLIENT) {
+    ldsP = new TPluginApiDS(this,aSessionP,getName(),aSessionP->getSyncCapMask() & ~(isOneWayFromRemoteSupported() ? 0 : SCAP_MASK_ONEWAY_SERVER));
+  }
+  else {
+    ldsP = new TPluginApiDS(this,aSessionP,getName(),aSessionP->getSyncCapMask() & ~(isOneWayFromRemoteSupported() ? 0 : SCAP_MASK_ONEWAY_CLIENT));
+  }
   // do common stuff
   addTypes(ldsP,aSessionP);
   // return
@@ -972,7 +973,7 @@ bool TPluginApiDS::dsOptionFilterFetchesFromDB(void)
   // %%% tbd:
   // - attachments inhibit
   // - size limit
-  #if !defined _MSC_VER || defined WINCE
+  #if (!defined _MSC_VER || defined WINCE) && !defined(__GNUC__)
   #warning "attachments and limit filters not yet supported"
   #endif
   // - let plugin know and check (we can filter at DBlevel if plugin understands both start/end)
@@ -1033,25 +1034,27 @@ localstatus TPluginApiDS::apiReadSyncSet(bool aNeedAll)
        TSyError dberr=LOCERR_OK;
 
   #ifdef BASED_ON_BINFILE_CLIENT
-  // we need to create the context for the data plugin here, as loadAdminData is not called in BASED_ON_BINFILE_CLIENT case.
-       dberr = connectDataPlugin();
-  if (dberr==LOCERR_OK) {
-    if (!fDBApi_Data.Created()) {
-      // - use datastore name as context name and link with session context
-      dberr = fDBApi_Data.CreateContext(
-        getName(), false,
-        &(fPluginDSConfigP->fDBApiConfig_Data),
-        "anydevice", // no real device key
-        "singleuser", // no real user key
-        NULL // no associated session level // fPluginAgentP->getDBApiSession()
-      );
+  if (binfileDSActive()) {
+    // we need to create the context for the data plugin here, as loadAdminData is not called in BASED_ON_BINFILE_CLIENT case.
+    dberr = connectDataPlugin();
+    if (dberr==LOCERR_OK) {
+      if (!fDBApi_Data.Created()) {
+        // - use datastore name as context name and link with session context
+        dberr = fDBApi_Data.CreateContext(
+          getName(), false,
+          &(fPluginDSConfigP->fDBApiConfig_Data),
+          "anydevice", // no real device key
+          "singleuser", // no real user key
+          NULL // no associated session level // fPluginAgentP->getDBApiSession()
+        );
+      }
     }
-  }
-  else if (dberr==LOCERR_NOTIMP)
-       dberr=LOCERR_OK; // we just don't have a data plugin, that's ok, inherited (SQL) will handle data
-  if (dberr!=LOCERR_OK)
-       return dberr;
-  #endif
+    else if (dberr==LOCERR_NOTIMP)
+      dberr=LOCERR_OK; // we just don't have a data plugin, that's ok, inherited (SQL) will handle data
+    if (dberr!=LOCERR_OK)
+      return dberr;
+  } // binfile active
+  #endif // BASED_ON_BINFILE_CLIENT
   #ifndef SDK_ONLY_SUPPORT
   // only handle here if we are in charge - otherwise let ancestor handle it
   if (!fDBApi_Data.Created()) return inherited::apiReadSyncSet(aNeedAll);
@@ -1414,40 +1417,6 @@ bool TPluginApiDS::dsFinalizeLocalID(string &aLocalID)
   }
   // no change - ID is ok as-is
   return false;
-
-  /*
-       // hacky implementation for now, as this routine is not yet in the DBApi.
-  // But as we need it for iPhone only so far, and iPhone only allows statically linked DB plugins, we can call
-  // it directly
-       #ifdef IPHONE_PLUGINS_STATIC
-  #warning "Ugly hack here"
-       char *finalizedID = NULL;
-  #ifdef HARDCODED_CONTACTS
-  if (fPluginDSConfigP->fLocalDBTypeID == 1001) {
-         sta = iPhone_addressbook::FinalizeLocalID(fDBApi_Data.fContext, aLocalID.c_str(), &finalizedID);
-  }
-  else
-  #endif // HARDCODED_CONTACTS
-  #ifdef HARDCODED_CALENDAR
-  if (fPluginDSConfigP->fLocalDBTypeID == 1002) {
-         sta = iPhone_calendar::FinalizeLocalID(fDBApi_Data.fContext, aLocalID.c_str(), &finalizedID);
-  }
-  else
-  #endif // HARDCODED_CALENDAR
-  {
-       return false; // no know datastore, no finalisation
-  }
-  // now get back translated ID
-  if (sta==LOCERR_OK && finalizedID) {
-               aLocalID = finalizedID;
-    free(finalizedID); // %%% should be StrDispose
-    return true; // final ID is different from temp one
-       }
-  #endif // IPHONE_PLUGINS_STATIC
-
-  // no change - ID is ok as-is
-  return false;
-  */
 } // TPluginApiDS::dsFinalizeLocalID
 
 #endif // SYSYNC_CLIENT
@@ -1506,10 +1475,10 @@ localstatus TPluginApiDS::apiUpdateItem(TMultiFieldItem &aItem)
   if (dberr==LOCERR_OK) {
     // check if ID has changed
     if (!updItemAndParentID.item.empty() && strcmp(updItemAndParentID.item.c_str(),aItem.getLocalID())!=0) {
-      #ifndef SYSYNC_CLIENT
-      // update item ID and Map
-      dsLocalIdHasChanged(aItem.getLocalID(),updItemAndParentID.item.c_str());
-      #endif
+       if (IS_SERVER) {
+        // update item ID and Map
+        dsLocalIdHasChanged(aItem.getLocalID(),updItemAndParentID.item.c_str());
+      }
       // - update in this item we have here as well
       aItem.setLocalID(updItemAndParentID.item.c_str());
       aItem.updateLocalIDDependencies();
@@ -1649,7 +1618,7 @@ void TPluginApiDS::dsThreadMayChangeNow(void)
 
 // - connect data handling part of plugin, Returns LOCERR_NOTIMPL when no data plugin is selected
 //   Note: this is either called as part of apiLoadAdminData (even if plugin is NOT responsible for data!)
-//         or directly before startDataRead (in BASED_ON_BINFILE_CLIENT case)
+//         or directly before startDataRead (in BASED_ON_BINFILE_CLIENT binfileDSActive() case)
 TSyError TPluginApiDS::connectDataPlugin(void)
 {
        TSyError err = LOCERR_NOTIMP;
@@ -1684,7 +1653,7 @@ TSyError TPluginApiDS::connectDataPlugin(void)
 } // connectDataPlugin
 
 
-#ifndef BASED_ON_BINFILE_CLIENT
+#ifndef BINFILE_ALWAYS_ACTIVE
 
 /// @brief save admin data
 ///   Must save the following items:
@@ -1747,14 +1716,14 @@ localstatus TPluginApiDS::apiSaveAdminData(bool aDataCommitted, bool aSessionFin
 
   // save the entire map list differentially
   pos=fMapTable.begin();
-  PDEBUGPRINTFX(DBG_ADMIN+DBG_EXOTIC,("apiSaveAdminData: internal map table has %ld entries (normal and others)",fMapTable.size()));
+  PDEBUGPRINTFX(DBG_ADMIN+DBG_EXOTIC,("apiSaveAdminData: internal map table has %lu entries (normal and others)",(unsigned long)fMapTable.size()));
   while (pos!=fMapTable.end()) {
     DEBUGPRINTFX(DBG_ADMIN+DBG_EXOTIC,(
       "apiSaveAdminData: entryType=%s, localid='%s', remoteID='%s', mapflags=0x%lX, changed=%d, deleted=%d, added=%d, markforresume=%d, savedmark=%d",
       MapEntryTypeNames[(*pos).entrytype],
       (*pos).localid.c_str(),
       (*pos).remoteid.c_str(),
-      (*pos).mapflags,
+      (long)(*pos).mapflags,
       (int)(*pos).changed,
       (int)(*pos).deleted,
       (int)(*pos).added,
@@ -1858,8 +1827,8 @@ localstatus TPluginApiDS::apiSaveAdminData(bool aDataCommitted, bool aSessionFin
   }
 
   /// For datastores that can resume in middle of a chunked item (fConfigP->fResumeItemSupport==true):
-  void* blPtr = fPIStoredDataP; // position
-  ulong blSize= fPIStoredSize;  // actualbytes
+  void*   blPtr = fPIStoredDataP; // position
+  memSize blSize= fPIStoredSize;  // actualbytes
 
   if (dsResumeChunkedSupportedInDB()) {
     ///   - fPartialItemState = state of partial item (TPartialItemState enum):
@@ -1885,11 +1854,11 @@ localstatus TPluginApiDS::apiSaveAdminData(bool aDataCommitted, bool aSessionFin
       // - fLastTargetURI    = item ID (string, if limited in length should be long enough for large IDs, >=64 chars recommended)
       adminData+="\r\nlasttargetURI:"; StrToCStrAppend( fLastTargetURI.c_str(), adminData,true );
       // - fPITotalSize      = uInt32, total item size
-      adminData+="\r\ntotalsize:"; StringObjAppendPrintf( adminData,"%hd", fPITotalSize );
+      adminData+="\r\ntotalsize:"; StringObjAppendPrintf( adminData,"%ld", (long)fPITotalSize );
       // - fPIUnconfirmedSize= uInt32, unconfirmed part of item size
-      adminData+="\r\nunconfirmedsize:"; StringObjAppendPrintf( adminData,"%hd", fPIUnconfirmedSize );
+      adminData+="\r\nunconfirmedsize:"; StringObjAppendPrintf( adminData,"%ld", (long)fPIUnconfirmedSize );
       // - fPIStoredSize     = uInt32, size of BLOB to store, store it as well to make ReadBlob easier (mallloc)
-      adminData+="\r\nstoredsize:"; StringObjAppendPrintf( adminData,"%hd", blSize );
+      adminData+="\r\nstoredsize:"; StringObjAppendPrintf( adminData,"%lu", (unsigned long)blSize );
       // - fPIStoredSize     = uInt32, size of BLOB to store, 0=none
       // - fPIStoredDataP    = void *, BLOB data, NULL if none
       adminData+="\r\nstored;BLOBID="; adminData+= PIStored;
@@ -1958,10 +1927,10 @@ localstatus TPluginApiDS::apiSaveAdminData(bool aDataCommitted, bool aSessionFin
 ///   - fLastRemoteAnchor = anchor string used by remote party for last session (and saved to DB then)
 ///   - fPreviousSyncTime = anchor (beginning of session) timestamp of last session.
 ///   - fPreviousToRemoteSyncCmpRef = Reference time to determine items modified since last time sending data to remote
-///                         (or last changelog update in case of BASED_ON_BINFILE_CLIENT)
+///                         (or last changelog update in case of BASED_ON_BINFILE_CLIENT && binfileDSActive())
 ///   - fPreviousToRemoteSyncIdentifier = string identifying last session that sent data to remote
-///                         (or last changelog update in case of BASED_ON_BINFILE_CLIENT). Needs only be saved
-///                         if derived datastore cannot work with timestamps and has its own identifier.
+///                         (or last changelog update in case of BASED_ON_BINFILE_CLIENT && binfileDSActive()). Needs
+///                         only be saved if derived datastore cannot work with timestamps and has its own identifier.
 ///   - fMapTable         = list<TMapEntry> containing map entries. The implementation must load all map entries
 ///                         related to the current sync target identified by the triple of (aDeviceID,aDatabaseID,aRemoteDBID)
 ///                         or by fTargetKey. The entries added to fMapTable must have "changed", "added" and "deleted" flags
@@ -2201,8 +2170,8 @@ localstatus TPluginApiDS::apiLoadAdminData(
                 if (err)
                   break;
 
-                ulong rema= b.fSize;
-                if (dp+rema > lim)
+                memSize rema= b.fSize;
+                if  (dp+rema > lim)
                   rema= lim-dp;    // avoid overflow
                 memcpy( dp, b.fPtr, rema ); dp+= rema;
                 fDBApi_Admin.DisposeBlk( b );         // we have now a copy => remove it
@@ -2258,7 +2227,7 @@ localstatus TPluginApiDS::apiLoadAdminData(
     mapEntry.remoteid=mapid.remoteID.c_str();
     mapEntry.mapflags=mapid.flags;
     // check for old API which did not support entry types
-    if (fPluginDSConfigP->fDBApiConfig_Admin.Version()<VE_InsertMapItem) {
+    if (fPluginDSConfigP->fDBApiConfig_Admin.Version()<sInt32(VE_InsertMapItem)) {
       mapEntry.entrytype = mapentry_normal; // DB has no entry types, treat all as normal entries
     }
     else {
@@ -2272,7 +2241,7 @@ localstatus TPluginApiDS::apiLoadAdminData(
       MapEntryTypeNames[mapEntry.entrytype],
       mapEntry.localid.c_str(),
       mapEntry.remoteid.c_str(),
-      mapEntry.mapflags
+      (long)mapEntry.mapflags
     ));
     // save entry in list
     mapEntry.changed=false; // not yet changed
@@ -2289,15 +2258,23 @@ localstatus TPluginApiDS::apiLoadAdminData(
     // Note: in the main map, these are marked deleted. Before the next saveAdminData, these will
     //       be re-added (=re-activated) from the extra lists if they still exist.
     switch (mapEntry.entrytype) {
-      #ifndef SYSYNC_CLIENT
+      #ifdef SYSYNC_SERVER 
       case mapentry_tempidmap:
-        fTempGUIDMap[mapEntry.remoteid]=mapEntry.localid; // tempGUIDs are accessed by remoteID=tempID
+       if (IS_SERVER)
+               fTempGUIDMap[mapEntry.remoteid]=mapEntry.localid; // tempGUIDs are accessed by remoteID=tempID
         break;
-      #else
+      #endif
+      #ifdef SYSYNC_CLIENT
       case mapentry_pendingmap:
-        fPendingAddMaps[mapEntry.localid]=mapEntry.remoteid;
+       if (IS_CLIENT)
+               fPendingAddMaps[mapEntry.localid]=mapEntry.remoteid;
         break;
       #endif
+    case mapentry_invalid:
+    case mapentry_normal:
+    case numMapEntryTypes:
+      // nothing to do or should not occur
+      break;
     }
     // next is not first entry any more
     firstEntry=false;
@@ -2306,7 +2283,7 @@ localstatus TPluginApiDS::apiLoadAdminData(
 } // TPluginApiDS::apiLoadAdminData
 
 
-#endif // not BASED_ON_BINFILE_CLIENT
+#endif // not BINFILE_ALWAYS_ACTIVE
 
 
 /// @brief log datastore sync result, called at end of sync with this datastore
@@ -2362,13 +2339,13 @@ void TPluginApiDS::dsLogSyncResult(void)
   logData.erase();
   logData+="lastsync:"; TimestampToISO8601Str(s,fCurrentSyncTime,TCTX_UTC); logData+=s.c_str();
   logData+="\r\ntargetkey:"; StrToCStrAppend(fTargetKey.c_str(),logData,true);
-  #ifndef BASED_ON_BINFILE_CLIENT
+  #ifndef BINFILE_ALWAYS_ACTIVE
   logData+="\r\nuserkey:"; StrToCStrAppend(fPluginAgentP->fUserKey.c_str(),logData,true);
   logData+="\r\ndevicekey:"; StrToCStrAppend(fPluginAgentP->fDeviceKey.c_str(),logData,true);
   #ifdef SCRIPT_SUPPORT
   logData+="\r\ndomain:"; StrToCStrAppend(fPluginAgentP->fDomainName.c_str(),logData,true);
   #endif
-  #endif
+  #endif // BINFILE_ALWAYS_ACTIVE
   logData+="\r\ndsname:"; StrToCStrAppend(getName(),logData,true);
   #ifndef MINIMAL_CODE
   logData+="\r\ndsremotepath:"; StrToCStrAppend(getRemoteDBPath(),logData,true);
@@ -2393,12 +2370,14 @@ void TPluginApiDS::dsLogSyncResult(void)
   logData+="\r\ndevicerejected:"; StringObjAppendPrintf(logData,"%ld",(long)fRemoteItemsError);
   logData+="\r\nlocalupdated:"; StringObjAppendPrintf(logData,"%ld",(long)fLocalItemsUpdated);
   logData+="\r\ndeviceupdated:"; StringObjAppendPrintf(logData,"%ld",(long)fRemoteItemsUpdated);
-  #ifndef SYSYNC_CLIENT
-  logData+="\r\nslowsyncmatches:"; StringObjAppendPrintf(logData,"%ld",fSlowSyncMatches);
-  logData+="\r\nserverwins:"; StringObjAppendPrintf(logData,"%ld",fConflictsServerWins);
-  logData+="\r\nclientwins:"; StringObjAppendPrintf(logData,"%ld",fConflictsClientWins);
-  logData+="\r\nduplicated:"; StringObjAppendPrintf(logData,"%ld",fConflictsDuplicated);
-  #endif
+  #ifdef SYSYNC_SERVER
+  if (IS_SERVER) {
+    logData+="\r\nslowsyncmatches:"; StringObjAppendPrintf(logData,"%ld",(long)fSlowSyncMatches);
+    logData+="\r\nserverwins:"; StringObjAppendPrintf(logData,"%ld",(long)fConflictsServerWins);
+    logData+="\r\nclientwins:"; StringObjAppendPrintf(logData,"%ld",(long)fConflictsClientWins);
+    logData+="\r\nduplicated:"; StringObjAppendPrintf(logData,"%ld",(long)fConflictsDuplicated);
+  } // server
+  #endif // SYSYNC_SERVER
   logData+="\r\nsessionbytesin:"; StringObjAppendPrintf(logData,"%ld",(long)fSessionP->getIncomingBytes());
   logData+="\r\nsessionbytesout:"; StringObjAppendPrintf(logData,"%ld",(long)fSessionP->getOutgoingBytes());
   logData+="\r\ndatabytesin:"; StringObjAppendPrintf(logData,"%ld",(long)fIncomingDataBytes);
index 4632094..c9422e0 100755 (executable)
@@ -169,7 +169,7 @@ public:
   virtual void dsResetDataStore(void) { InternalResetDataStore(); inherited::dsResetDataStore(); };
   virtual ~TPluginApiDS();
 
-  #ifndef BASED_ON_BINFILE_CLIENT
+  #ifndef BINFILE_ALWAYS_ACTIVE
   /// @name apiXXXX methods defining the interface from TCustomImplDS to TXXXApi actual API implementations
   /// @{
   //
@@ -249,7 +249,7 @@ public:
   ///   read items here already. Note that ReadSyncSet MAY read items here
   ///   even if aNeedAll is not set (if it is more efficient than reading
   ///   them separately afterwards).
-  #endif // not BASED_ON_BINFILE_CLIENT
+  #endif // not BINFILE_ALWAYS_ACTIVE
 
   virtual localstatus apiReadSyncSet(bool aNeedAll);
   /// Zap all data in syncset (note that everything outside the sync set will remain intact)
index 42911c8..4749245 100644 (file)
 #include "odbcapids.h"
 #include "odbcapiagent.h"
 
+#ifdef SYSYNC_TOOL
+#include "syncsessiondispatch.h"
+#endif
+
 namespace sysync {
 
 
@@ -39,7 +43,7 @@ int execSQL(int argc, const char *argv[])
   const char *sql = NULL;
 
   // show only one row by default
-  long maxrows=1;
+  sInt32 maxrows=1;
 
   // check for argument
   if (argc<1) {
@@ -567,14 +571,6 @@ public:
     #ifdef ODBCAPI_SUPPORT
     try {
       agentP->commitAndCloseScriptStatement();
-      /*
-      if (agentP->fScriptStatement!=SQL_NULL_HANDLE) {
-        // only commit if we have used a statement at all in scripts
-        SafeSQLFreeHandle(SQL_HANDLE_STMT,agentP->fScriptStatement);
-        agentP->fScriptStatement=SQL_NULL_HANDLE;
-        SafeSQLEndTran(SQL_HANDLE_DBC,agentP->getODBCConnectionHandle(),SQL_COMMIT);
-      }
-      */
     }
     catch (exception &e) {
       POBJDEBUGPRINTFX(aFuncContextP->getSession(),DBG_ERROR,(
@@ -817,14 +813,20 @@ void TOdbcAgentConfig::localResolve(bool aLastPass)
     #ifdef HAS_SQL_ADMIN
     if (fClearTextPw && fMD5UserPass)
       throw TConfigParseException("only one of 'cleartextpw' and 'md5userpass' can be set");
-    #ifndef SYSYNC_CLIENT
-    if (fAutoNonce && !fClearTextPw && !fMD5UserPass)
-      throw TConfigParseException("if 'autononce' is set, 'cleartextpw' or 'md5userpass' MUST be set as well");
-    #endif
+    #ifdef SYSYNC_SERVER
+    if (IS_SERVER) {
+      if (fAutoNonce && !fClearTextPw && !fMD5UserPass)
+        throw TConfigParseException("if 'autononce' is set, 'cleartextpw' or 'md5userpass' MUST be set as well");
+    }
+    #endif // SYSYNC_SERVER
     #ifdef SYSYNC_CLIENT
-    if (fNoLocalDBLogin && !fUserKeySQL.empty())
-      throw TConfigParseException("'nolocaldblogin' is not allowed when 'userkeysql' is defined");
-    #endif
+    if (IS_CLIENT) {
+      #ifndef NO_LOCAL_DBLOGIN
+      if (fNoLocalDBLogin && !fUserKeySQL.empty())
+        throw TConfigParseException("'nolocaldblogin' is not allowed when 'userkeysql' is defined");
+      #endif
+    }
+    #endif // SYSYNC_CLIENT
     #endif // HAS_SQL_ADMIN
     #endif // ODBCAPI_SUPPORT
   }
@@ -852,33 +854,29 @@ void TOdbcAgentConfig::ResolveAPIScripts(void)
 /* public TODBCApiAgent members */
 
 
-#ifdef SYSYNC_CLIENT
-TODBCApiAgent::TODBCApiAgent(TSyncClientBase *aSyncClientBaseP, const char *aSessionID) :
-  TCustomImplAgent(aSyncClientBaseP, aSessionID),
-#else
-TODBCApiAgent::TODBCApiAgent(TSyncAppBase *aAppBaseP, TSyncSessionHandle *aSessionHandleP, const char *aSessionID) :
-  TCustomImplAgent(aAppBaseP, aSessionHandleP, aSessionID),
-#endif
-  fConfigP(NULL)
+// private init routine for both client and server constructor
+TODBCApiAgent::TODBCApiAgent(TSyncAppBase *aAppBaseP, TSyncSessionHandle *aSessionHandleP, cAppCharP aSessionID) :
+  TCustomImplAgent(aAppBaseP, aSessionHandleP, aSessionID)
+{
+       // init basics
   #ifdef ODBCAPI_SUPPORT
-  ,fODBCConnectionHandle(SQL_NULL_HANDLE)
-  ,fODBCEnvironmentHandle(SQL_NULL_HANDLE)
+  fODBCConnectionHandle = SQL_NULL_HANDLE;
+  fODBCEnvironmentHandle = SQL_NULL_HANDLE;
   #ifdef SCRIPT_SUPPORT
-  ,fScriptStatement(SQL_NULL_HANDLE)
-  ,fAfterConnectContext(NULL)
+  fScriptStatement = SQL_NULL_HANDLE;
+  fAfterConnectContext = NULL;
   #endif
   #endif // ODBCAPI_SUPPORT
-{
   // get config for agent and save direct link to agent config for easy reference
   fConfigP = static_cast<TOdbcAgentConfig *>(getRootConfig()->fAgentConfigP);
   // Note: Datastores are already created from config
-  #ifdef SCRIPT_SUPPORT
   #ifdef ODBCAPI_SUPPORT
-  // - rebuild afterconnect script
-  TScriptContext::rebuildContext(getSyncAppBase(),fConfigP->fAfterConnectScript,fAfterConnectContext,this,true);
   // - assign default DB connection string and password
   fSessionDBConnStr = fConfigP->fDBConnStr;
   fSessionDBPassword = fConfigP->fPassword;
+  #ifdef SCRIPT_SUPPORT
+  // - rebuild afterconnect script
+  TScriptContext::rebuildContext(getSyncAppBase(),fConfigP->fAfterConnectScript,fAfterConnectContext,this,true);
   #endif
   #endif
 } // TODBCApiAgent::TODBCApiAgent
@@ -1708,16 +1706,18 @@ bool TODBCApiAgent::ParseParamSubst(
 // do generic substitutions
 void TODBCApiAgent::DoSQLSubstitutions(string &aSQL)
 {
-  #ifndef BASED_ON_BINFILE_CLIENT
-  // substitute: %u = userkey
-  StringSubst(aSQL,"%u",fUserKey,2,fConfigP->fDataCharSet,fConfigP->fDataLineEndMode,fConfigP->fQuotingMode);
-  // substitute: %d = devicekey
-  StringSubst(aSQL,"%d",fDeviceKey,2,fConfigP->fDataCharSet,fConfigP->fDataLineEndMode,fConfigP->fQuotingMode);
-  #ifdef SCRIPT_SUPPORT
-  // substitute: %C = domain name (such as company selector)
-  StringSubst(aSQL,"%C",fDomainName,2,fConfigP->fDataCharSet,fConfigP->fDataLineEndMode,fConfigP->fQuotingMode);
-  #endif
-  #endif
+  #ifndef BINFILE_ALWAYS_ACTIVE
+  if (!binfilesActive()) {
+    // substitute: %u = userkey
+    StringSubst(aSQL,"%u",fUserKey,2,fConfigP->fDataCharSet,fConfigP->fDataLineEndMode,fConfigP->fQuotingMode);
+    // substitute: %d = devicekey
+    StringSubst(aSQL,"%d",fDeviceKey,2,fConfigP->fDataCharSet,fConfigP->fDataLineEndMode,fConfigP->fQuotingMode);
+    #ifdef SCRIPT_SUPPORT
+    // substitute: %C = domain name (such as company selector)
+    StringSubst(aSQL,"%C",fDomainName,2,fConfigP->fDataCharSet,fConfigP->fDataLineEndMode,fConfigP->fQuotingMode);
+    #endif
+  }
+  #endif // not BINFILE_ALWAYS_ACTIVE
   #ifdef SCRIPT_SUPPORT
   // substitute %sv(sessionvarname) = session variable by name
   string::size_type i=0;
@@ -1958,7 +1958,7 @@ SQLHDBC TODBCApiAgent::getODBCConnectionHandle(void)
       throw;
     }
   }
-  PDEBUGPRINTFX(DBG_DBAPI+DBG_EXOTIC,("Session: using connection handle 0x%lX",(uInt32)fODBCConnectionHandle));
+  PDEBUGPRINTFX(DBG_DBAPI+DBG_EXOTIC,("Session: using connection handle 0x%lX",(uIntArch)fODBCConnectionHandle));
   return fODBCConnectionHandle;
 } // TODBCApiAgent::getODBCConnectionHandle
 
@@ -1971,13 +1971,6 @@ SQLHDBC TODBCApiAgent::pullODBCConnectionHandle(void)
   #ifdef SCRIPT_SUPPORT
   // make sure eventual script statement gets disposed, as connection is now owned by datastore
   commitAndCloseScriptStatement();
-  /*
-  if (fScriptStatement!=SQL_NULL_HANDLE) {
-    PDEBUGPRINTFX(DBG_DBAPI+DBG_EXOTIC,("Script statement exists, connection pulled into DS -> closing the script statement now"));
-    SafeSQLFreeHandle(SQL_HANDLE_STMT,fScriptStatement);
-    fScriptStatement=SQL_NULL_HANDLE;
-  }
-  */
   #endif
   return connhandle;
 } // TODBCApiAgent::pullODBCConnectionHandle
@@ -3420,12 +3413,12 @@ lineartime_t TODBCApiAgent::getDatabaseNowAs(timecontext_t aTimecontext)
 } // TODBCApiAgent::getDatabaseNowAs
 
 
-#ifndef SYSYNC_CLIENT
+#ifdef SYSYNC_SERVER
 
 // info about requested auth type
 TAuthTypes TODBCApiAgent::requestedAuthType(void)
 {
-  TAuthTypes auth = TSyncServer::requestedAuthType();
+  TAuthTypes auth = TSyncAgent::requestedAuthType();
 
   // make sure that we don't request MD5 if we cannot check it:
   // either we need plain text passwords in the DB or SyncML V1.1 MD5 schema
@@ -3513,7 +3506,7 @@ void TODBCApiAgent::getNextNonce(const char *aDeviceID, string &aNextNonce)
   }
 } // TODBCApiAgent::getNextNonce
 
-#endif // not SYSYNC_CLIENT
+#endif // SYSYNC_SERVER
 
 
 #ifdef HAS_SQL_ADMIN
@@ -3572,10 +3565,12 @@ void TODBCApiAgent::CheckDevice(const char *aDeviceID)
             throw TSyncException("Fatal: inserted device record cannot be found again");
           }
           PDEBUGPRINTFX(DBG_ADMIN,("Unknown device '%.30s', creating new record",aDeviceID));
-          #ifndef SYSYNC_CLIENT
-          // device does not exist yet
-          fLastNonce.erase();
-          #endif
+          if (IS_SERVER) {
+               #ifdef SYSYNC_SERVER
+            // device does not exist yet
+            fLastNonce.erase();
+            #endif
+          }
           // create new device
           SafeSQLCloseCursor(statement);
           // - get SQL
@@ -3609,18 +3604,23 @@ void TODBCApiAgent::CheckDevice(const char *aDeviceID)
           // - device key
           getColumnValueAsString(statement,1,fDeviceKey,chs_ascii);
           // - nonce
-          #ifdef SYSYNC_CLIENT
-          string dummy;
-          getColumnValueAsString(statement,2,dummy,chs_ascii);
-          #else
-          getColumnValueAsString(statement,2,fLastNonce,chs_ascii);
-          #endif
+          if (IS_CLIENT) {
+            string dummy;
+            getColumnValueAsString(statement,2,dummy,chs_ascii);
+          }
+          else {
+               #ifdef SYSYNC_SERVER
+                 getColumnValueAsString(statement,2,fLastNonce,chs_ascii);
+            #endif
+          }
           // - done for now
           SafeSQLCloseCursor(statement);
           PDEBUGPRINTFX(DBG_ADMIN,("Device '%.30s' found, fDeviceKey='%.30s'",aDeviceID,fDeviceKey.c_str()));
-          #ifndef SYSYNC_CLIENT
-          DEBUGPRINTFX(DBG_ADMIN,("Last nonce saved for device='%.30s'",fLastNonce.c_str()));
-          #endif
+          if (IS_SERVER) {
+            #ifdef SYSYNC_SERVER
+                 DEBUGPRINTFX(DBG_ADMIN,("Last nonce saved for device='%.30s'",fLastNonce.c_str()));
+                 #endif
+          }
           break;
         }
       } while (true); // do until device found or created new
@@ -3869,7 +3869,7 @@ void TODBCApiAgent::remoteAnalyzed(void)
 
 
 
-#ifndef SYSYNC_CLIENT
+#ifdef SYSYNC_SERVER
 
 void TODBCApiAgent::RequestEnded(bool &aHasData)
 {
@@ -3887,7 +3887,7 @@ void TODBCApiAgent::RequestEnded(bool &aHasData)
   #endif
 } // TODBCApiAgent::RequestEnded
 
-#endif
+#endif // SYSYNC_SERVER
 
 
 // factory methods of Agent config
@@ -3895,16 +3895,17 @@ void TODBCApiAgent::RequestEnded(bool &aHasData)
 
 #ifdef SYSYNC_CLIENT
 
-TSyncClient *TOdbcAgentConfig::CreateClientSession(const char *aSessionID)
+TSyncAgent *TOdbcAgentConfig::CreateClientSession(const char *aSessionID)
 {
   // return appropriate client session
-  MP_RETURN_NEW(TODBCApiAgent,DBG_HOT,"TODBCApiAgent",TODBCApiAgent(static_cast<TSyncClientBase *>(getSyncAppBase()),aSessionID));
+  MP_RETURN_NEW(TODBCApiAgent,DBG_HOT,"TODBCApiAgent",TODBCApiAgent(getSyncAppBase(),NULL,aSessionID));
 } // TOdbcAgentConfig::CreateClientSession
 
+#endif
 
-#else
+#ifdef SYSYNC_SERVER
 
-TSyncServer *TOdbcAgentConfig::CreateServerSession(TSyncSessionHandle *aSessionHandle, const char *aSessionID)
+TSyncAgent *TOdbcAgentConfig::CreateServerSession(TSyncSessionHandle *aSessionHandle, const char *aSessionID)
 {
   // return XML2GO or ODBC-server session
   MP_RETURN_NEW(TODBCApiAgent,DBG_HOT,"TODBCApiAgent",TODBCApiAgent(getSyncAppBase(),aSessionHandle,aSessionID));
index 6c77738..a353155 100755 (executable)
@@ -313,11 +313,12 @@ protected:
   #endif
   #ifdef SYSYNC_CLIENT
   // create appropriate session (=agent) for this client
-  virtual TSyncClient *CreateClientSession(const char *aSessionID);
-  #else
+  virtual TSyncAgent *CreateClientSession(const char *aSessionID);
+  #endif
 public:
+  #ifdef SYSYNC_SERVER
   // create appropriate session (=agent) for this server
-  virtual TSyncServer *CreateServerSession(TSyncSessionHandle *aSessionHandle, const char *aSessionID);
+  virtual TSyncAgent *CreateServerSession(TSyncSessionHandle *aSessionHandle, const char *aSessionID);
   #endif
 }; // TOdbcAgentConfig
 
@@ -330,11 +331,7 @@ class TODBCApiAgent: public TCustomImplAgent
   friend class TODBCAgentFuncs;
   typedef TCustomImplAgent inherited;
 public:
-  #ifdef SYSYNC_CLIENT
-  TODBCApiAgent(TSyncClientBase *aSyncClientBaseP, const char *aSessionID);
-  #else
-  TODBCApiAgent(TSyncAppBase *aAppBaseP, TSyncSessionHandle *aSessionHandleP, const char *aSessionID);
-  #endif
+  TODBCApiAgent(TSyncAppBase *aAppBaseP, TSyncSessionHandle *aSessionHandleP, cAppCharP aSessionID);
   virtual ~TODBCApiAgent();
   virtual void TerminateSession(void); // Terminate session, like destructor, but without actually destructing object itself
   virtual void ResetSession(void); // Resets session (but unlike TerminateSession, session might be re-used)
@@ -342,14 +339,14 @@ public:
   #ifdef HAS_SQL_ADMIN
   // Note: %%% for now, login is supported by ODBC only
   // user authentication
-  #ifndef SYSYNC_CLIENT
+  #ifdef SYSYNC_SERVER
   // - return auth type to be requested from remote
   virtual TAuthTypes requestedAuthType(void); // avoids MD5 when it cannot be checked
   // - get next nonce string top be sent to remote party for subsequent MD5 auth
   virtual void getNextNonce(const char *aDeviceID, string &aNextNonce);
   // - get nonce string, which is expected to be used by remote party for MD5 auth.
   virtual void getAuthNonce(const char *aDeviceID, string &aAuthNonce);
-  #endif // SYSYNC_CLIENT
+  #endif // SYSYNC_SERVER
   // - clean up after all login activity is over (including finishscript)
   virtual void LoginCleanUp(void);
   #endif // HAS_SQL_ADMIN
@@ -571,7 +568,7 @@ protected:
   // - remote device is analyzed, eventually save status
   virtual void remoteAnalyzed(void);
   #endif // HAS_SQL_ADMIN
-  #ifndef SYSYNC_CLIENT
+  #ifdef SYSYNC_SERVER
   // - request end, used to clean up
   virtual void RequestEnded(bool &aHasData);
   #endif
index 288f27d..7b4e764 100755 (executable)
@@ -603,12 +603,13 @@ void TOdbcDSConfig::apiResolveScripts(void)
 TLocalEngineDS *TOdbcDSConfig::newLocalDataStore(TSyncSession *aSessionP)
 {
   // Synccap defaults to normal set supported by the engine by default
-  TLocalEngineDS *ldsP =
-    #ifdef SYSYNC_CLIENT
-    new TODBCApiDS(this,aSessionP,getName(),aSessionP->getSyncCapMask() & ~(isOneWayFromRemoteSupported() ? 0 : SCAP_MASK_ONEWAY_SERVER));
-    #else
-    new TODBCApiDS(this,aSessionP,getName(),aSessionP->getSyncCapMask() & ~(isOneWayFromRemoteSupported() ? 0 : SCAP_MASK_ONEWAY_CLIENT));
-    #endif
+  TLocalEngineDS *ldsP;
+       if (IS_CLIENT) {
+    ldsP = new TODBCApiDS(this,aSessionP,getName(),aSessionP->getSyncCapMask() & ~(isOneWayFromRemoteSupported() ? 0 : SCAP_MASK_ONEWAY_SERVER));
+  }
+  else {
+    ldsP = new TODBCApiDS(this,aSessionP,getName(),aSessionP->getSyncCapMask() & ~(isOneWayFromRemoteSupported() ? 0 : SCAP_MASK_ONEWAY_CLIENT));
+  }
   // do common stuff
   addTypes(ldsP,aSessionP);
   // return
@@ -848,7 +849,7 @@ SQLHDBC TODBCApiDS::getODBCConnectionHandle(void)
     PDEBUGPRINTFX(DBG_DBAPI+DBG_EXOTIC,("Datastore %s does not own a DB connection yet -> pulling connection from session level",getName()));
     fODBCConnectionHandle = fAgentP->pullODBCConnectionHandle();
   }
-  PDEBUGPRINTFX(DBG_DBAPI+DBG_EXOTIC,("Datastore %s: using connection handle 0x%lX",getName(),(uInt32)fODBCConnectionHandle));
+  PDEBUGPRINTFX(DBG_DBAPI+DBG_EXOTIC,("Datastore %s: using connection handle 0x%lX",getName(),(uIntArch)fODBCConnectionHandle));
   return fODBCConnectionHandle;
 } // TODBCApiDS::getODBCConnectionHandle
 
@@ -1226,7 +1227,7 @@ void TODBCApiDS::writeArray(bool aDelete, bool aInsert, SQLHSTMT aStatement, TMu
   TODBCFieldMapArrayItem *fmaiP = dynamic_cast<TODBCFieldMapArrayItem *>(aMapItemP);
   PDEBUGPRINTFX(DBG_DATA+DBG_DBAPI+DBG_EXOTIC,("Writing Array, fmaiP=0x%lX",(long)fmaiP));
   if (!fmaiP) return; // do nothing
-  PDEBUGPRINTFX(DBG_DATA+DBG_DBAPI+DBG_EXOTIC,("Writing Array for field '%s'",fmaiP->getName()));
+  PDEBUGPRINTFX(DBG_DATA+DBG_DBAPI+DBG_EXOTIC,("Writing Array"));
   // Check initscript first. If it returns false, we do not insert anything
   bool doit;
   #ifdef SCRIPT_SUPPORT
@@ -4148,13 +4149,16 @@ localstatus TODBCApiDS::apiLoadAdminData(
             // Note: in the main map, these are marked deleted. Before the next saveAdminData, these will
             //       be re-added (=re-activated) from the extra lists if they still exist.
             switch (entry.entrytype) {
-              #ifndef SYSYNC_CLIENT
+              #ifdef SYSYNC_SERVER
               case mapentry_tempidmap:
-                fTempGUIDMap[entry.remoteid]=entry.localid; // tempGUIDs are accessed by remoteID=tempID
+               if (IS_SERVER)
+                       fTempGUIDMap[entry.remoteid]=entry.localid; // tempGUIDs are accessed by remoteID=tempID
                 break;
-              #else
+              #endif
+              #ifdef SYSYNC_CLIENT
               case mapentry_pendingmap:
-                fPendingAddMaps[entry.localid]=entry.remoteid;
+               if (IS_CLIENT)
+                       fPendingAddMaps[entry.localid]=entry.remoteid;
                 break;
               #endif
             }
index 0913caa..d260406 100755 (executable)
@@ -14,7 +14,7 @@
   #error "ODBC_SUPPORT no longer exists, is now called SQL_SUPPORT. ODBCAPI_SUPPORT exists."
 #endif
 // SQL based admin
-#if defined (SQL_SUPPORT) && defined(ODBCAPI_SUPPORT) && !defined(BASED_ON_BINFILE_CLIENT)
+#if defined (SQL_SUPPORT) && defined(ODBCAPI_SUPPORT) && !defined(BINFILE_ALWAYS_ACTIVE)
   #define HAS_SQL_ADMIN 1
 #endif
 
index 4f69db0..e0eb2ea 100644 (file)
@@ -1,3 +1,9 @@
+admindata.cpp
+admindata.h
+dbitem.cpp
+dbitem.h
+blobs.cpp
+blobs.h
 enginesessiondispatch.cpp
 syncserver.cpp
 binfile.cpp
@@ -10,5 +16,5 @@ syncclientbase.cpp
 clientprovisioning_inc.cpp
 .*_tables_inc.cpp
 syncsessiondispatch.cpp
+platform_thread.cpp
 enginestubs.c
-sysync/syncserver.cpp
index 4c81e8c..20c3317 100644 (file)
@@ -1,5 +1,5 @@
 clientprovisioning_inc.cpp
 .*_tables_inc.cpp
 syncsessiondispatch.cpp
+platform_thread.cpp
 enginestubs.c
-sysync/syncserver.cpp
index bd7580f..3d155b9 100644 (file)
@@ -9,34 +9,52 @@
 $(srcdir)/Makefile.am: $(srcdir)/Makefile.am.in $(srcdir)/gen-makefile-am.sh
        cd $(srcdir) && sh ./gen-makefile-am.sh
 
+# versioning for *all* libs
+#
+# CURRENT - most recent interface version
+# REVISION - minor version number of that interface implementation
+# AGE - number of previous interface versions supported in addition
+#       to the current one
+#
+# When adding to the interface, increment CURRENT and AGE and reset
+# REVISION to zero. When breaking the interface in a backwards
+# incompatible way, increment CURRENT and reset AGE and REVISION to
+# zero. When fixing something without interface change, increment
+# REVISION.
+ENGINE_CURRENT = 3
+ENGINE_REVISION = 0
+ENGINE_AGE = 3
+
 CLEANFILES =
 EXTRA_DIST =
 
-lib_LTLIBRARIES = libsmltk.la libsynthesis.la libsynthesissdk.la
-nobase_include_HEADERS = synthesis/enginemodulebridge.h synthesis/SDK_util.h synthesis/prefix_file.h synthesis/sync_dbapi.h synthesis/enginemodulebase.h synthesis/SDK_support.h synthesis/stringutil.h synthesis/sync_declarations.h synthesis/sync_dbapidef.h synthesis/generic_types.h synthesis/engine_defs.h synthesis/sync_include.h synthesis/timeutil.h synthesis/dbitem.h synthesis/blobs.h synthesis/sync_uiapi.h synthesis/admindata.h synthesis/dataconversion.h synthesis/syerror.h synthesis/UI_util.h synthesis/target_options.h
+lib_LTLIBRARIES = libsmltk.la libsynthesis.la libsynthesissdk.la libsynthesisstubs.la
+nobase_include_HEADERS = synthesis/sysync_b64.h synthesis/enginemodulebridge.h synthesis/SDK_util.h synthesis/prefix_file.h synthesis/sync_dbapi.h synthesis/enginemodulebase.h synthesis/SDK_support.h synthesis/stringutil.h synthesis/sync_declarations.h synthesis/sync_dbapidef.h synthesis/generic_types.h synthesis/engine_defs.h synthesis/sync_include.h synthesis/timeutil.h synthesis/dbitem.h synthesis/san.h synthesis/blobs.h synthesis/sync_uiapi.h synthesis/admindata.h synthesis/dataconversion.h synthesis/sysync_md5.h synthesis/syerror.h synthesis/UI_util.h synthesis/target_options.h
 
 # Configuration header files are searched in this order:
 # - Targets/ReleasedProducts/autotools: files only used when compiling with autotools
-# - Targets/ReleasedProducts/[clientEngine_opensource_linux|SDK]: files also used with Synthesis Linux makefile
+# - Targets/ReleasedProducts/[combiEngine_opensource_linux|serverEngine_opensource_linux|SDK]: files also used with Synthesis Linux makefile
 #
 # Always included first via -include:
 # - config.h: configure result (top directory)
-# - Targets/ReleasedProducts/clientEngine_opensource_linux/clientengine_demo_x86_linux_prefix.h
+# - Targets/ReleasedProducts/combiEngine_opensource_linux/clientengine_demo_x86_linux_prefix.h resp. Targets/ReleasedProducts/serverEngine_opensource_linux/serverengine_opensource_linux_prefix.h
 #
 # Included as needed:
 # - define.h: hard-coded SyncML Toolkit config (from search path above)
 
-libsynthesis_la_SOURCES = sysync/binfileimplclient.cpp sysync/syncclientbase.h sysync/sysync_b64.cpp sysync/sysync_md5.cpp sysync/sysync_b64.h sysync/syncml_globs.h sysync/stdlogicagent.cpp sysync/syncappbase.cpp sysync/customimplds.cpp sysync/syncsession.h sysync/syncclient.cpp sysync/syncitem.cpp sysync/textitemtype.cpp sysync/textitemtype.h sysync/localengineds.h sysync/syncexception.cpp sysync/clientprovisioning_inc.h sysync/global_progress.h sysync/textprofile.cpp sysync/stringutils.cpp sysync/customimplagent.cpp sysync/debuglogger.cpp sysync/vtimezone.cpp sysync/iso8601.h sysync/vcalendaritemtype.cpp sysync/scriptcontext.h sysync/syncitemtype.h sysync/smltk_precomp.h sysync/sysync_globs.h sysync/sysync_debug.h sysync/syncsessiondispatch.h sysync/san.cpp sysync/sysync_utils.cpp sysync/mimediritemtype.h sysync/dataobjtype.cpp sysync/multifielditem.cpp sysync/sysync_precomp_xpt.h sysync/iso8601.cpp sysync/syncclientbase.cpp sysync/itemfield.h sysync/syncserver.h sysync/remotedatastore.h sysync/engineentry.h sysync/itemfield.cpp sysync/stringutils.h sysync/lineartime.h sysync/syncml_tk.h sysync/mimediritemtype.cpp sysync/configelement.h sysync/clientautosync_inc.cpp sysync/binfilebase.cpp sysync/synccommand.cpp sysync/mimedirprofile.h sysync/tz_table.h sysync/binfileimplds.cpp sysync/sysync_crc16.cpp sysync/simpleitem.h sysync/timezones.h sysync/sysync_precomp.h sysync/sysync.h sysync/binfileimplclient.h sysync/syncitem.h sysync/localengineds.cpp sysync/dataobjtype.h sysync/customimplagent.h sysync/synccommand.h sysync/binfilebase.h sysync/textprofile.h sysync/vcarditemtype.h sysync/binfileimplds.h sysync/vcalendaritemtype.h sysync/syncexception.h sysync/san.h sysync/multifielditemtype.cpp sysync/lineartime.cpp sysync/clientautosync_inc.h sysync/debuglogger.h sysync/smltk_precomp_xpt.h sysync/syncsession.cpp sysync/multifielditemtype.h sysync/stdlogicds.h sysync/rrules.h sysync/remotedatastore.cpp sysync/engineentry.cpp sysync/simpleitem.cpp sysync/superdatastore.h sysync/uiapi.h sysync/vcarditemtype.cpp sysync/engineinterface.cpp sysync/syncappbase.h sysync/syncclient.h sysync/sysync_crc16.h sysync/syncdatastore.cpp sysync/multifielditem.h sysync/scriptcontext.cpp sysync/syncitemtype.cpp sysync/stdlogicds.cpp sysync/vtimezone.h sysync/uiapi.cpp sysync/dataconversion.cpp sysync/timezones.cpp sysync/engineinterface.h sysync/sysync_md5.h sysync/superdatastore.cpp sysync/sysync_utils.h sysync/customimplds.h sysync/rrules.cpp sysync/configelement.cpp sysync/syserial.h sysync/syncdatastore.h sysync/mimedirprofile.cpp sysync/stdlogicagent.h DB_interfaces/odbc_db/odbcapids.cpp DB_interfaces/odbc_db/odbcapiagent.h DB_interfaces/odbc_db/odbcapiagent.cpp DB_interfaces/odbc_db/odbcdb_precomp.h DB_interfaces/odbc_db/odbcapids.h DB_interfaces/odbc_db/odbcdb.h DB_interfaces/api_db/plugindb.h DB_interfaces/api_db/dbapi.h DB_interfaces/api_db/pluginapiagent.cpp DB_interfaces/api_db/dbapi_include.h DB_interfaces/api_db/sync_dbapiconnect.h DB_interfaces/api_db/pluginapiagent.h DB_interfaces/api_db/sync_dbapiconnect.cpp DB_interfaces/api_db/pluginapids.cpp DB_interfaces/api_db/plugindb_precomp.h DB_interfaces/api_db/dbapi.cpp DB_interfaces/api_db/DLL_interface.h DB_interfaces/api_db/DLL_interface.cpp DB_interfaces/api_db/pluginapids.h sysync_SDK/Sources/SDK_util.h sysync_SDK/Sources/prefix_file.h sysync_SDK/Sources/sync_dbapi.h sysync_SDK/Sources/enginemodulebase.h sysync_SDK/Sources/SDK_support.h sysync_SDK/Sources/sync_declarations.h sysync_SDK/Sources/sync_dbapidef.h sysync_SDK/Sources/generic_types.h sysync_SDK/Sources/engine_defs.h sysync_SDK/Sources/sync_include.h sysync_SDK/Sources/SDK_support.cpp sysync_SDK/Sources/SDK_util.c sysync_SDK/Sources/enginemodulebase.cpp sysync_SDK/Sources/sync_uiapi.h sysync_SDK/Sources/dataconversion.h sysync_SDK/Sources/syerror.h Transport_interfaces/engine/engine_client_precomp.h Transport_interfaces/engine/engineclientbase.cpp Transport_interfaces/engine/engineclientbase.h Transport_interfaces/engine/engine_client.h platform_adapters/sysync_glob_vars.h platform_adapters/configfiles.h platform_adapters/binfile.cpp platform_adapters/sysyncinit.cpp platform_adapters/profiling.h platform_adapters/linux/platform_DLL.cpp platform_adapters/linux/profiling.cpp platform_adapters/linux/platform_exec.h platform_adapters/linux/configfiles.cpp platform_adapters/linux/platform_time.cpp platform_adapters/linux/platform_exec.c platform_adapters/linux/platform_headers.h platform_adapters/linux/platform_timezones.cpp platform_adapters/linux/platform_time.h platform_adapters/binfile.h platform_adapters/platform_thread.h platform_adapters/platform_DLL.h platform_adapters/unix_common/platform_pipe.c platform_adapters/unix_common/platform_file.cpp platform_adapters/unix_common/platform_thread.cpp platform_adapters/unix_common/platform_pipe.h platform_adapters/unix_common/platform_mutex.cpp platform_adapters/platform_file.h platform_adapters/platform_headers.h platform_adapters/platform_mutex.h syncapps/clientEngine_custom/clientengine_custom_Base.h syncapps/clientEngine_custom/clientengine_custom_Base.cpp syncapps/clientEngine_custom/product_options.h syncapps/clientEngine_custom/clientengine_custom_precomp.h syncapps/clientEngine_custom/clientengine_custom.h
+libsynthesis_la_SOURCES = sysync/binfileimplclient.cpp sysync/syncclientbase.h sysync/syncagent.cpp sysync/syncml_globs.h sysync/stdlogicagent.cpp sysync/syncappbase.cpp sysync/customimplds.cpp sysync/syncsession.h sysync/syncitem.cpp sysync/textitemtype.cpp sysync/textitemtype.h sysync/localengineds.h sysync/syncexception.cpp sysync/clientprovisioning_inc.h sysync/global_progress.h sysync/textprofile.cpp sysync/stringutils.cpp sysync/customimplagent.cpp sysync/debuglogger.cpp sysync/vtimezone.cpp sysync/iso8601.h sysync/vcalendaritemtype.cpp sysync/scriptcontext.h sysync/syncitemtype.h sysync/smltk_precomp.h sysync/sysync_globs.h sysync/sysync_debug.h sysync/syncsessiondispatch.h sysync/sysync_utils.cpp sysync/mimediritemtype.h sysync/dataobjtype.cpp sysync/multifielditem.cpp sysync/sysync_precomp_xpt.h sysync/iso8601.cpp sysync/syncclientbase.cpp sysync/itemfield.h sysync/remotedatastore.h sysync/engineentry.h sysync/itemfield.cpp sysync/stringutils.h sysync/lineartime.h sysync/syncml_tk.h sysync/mimediritemtype.cpp sysync/configelement.h sysync/clientautosync_inc.cpp sysync/binfilebase.cpp sysync/synccommand.cpp sysync/mimedirprofile.h sysync/tz_table.h sysync/binfileimplds.cpp sysync/sysync_crc16.cpp sysync/simpleitem.h sysync/timezones.h sysync/sysync_precomp.h sysync/sysync.h sysync/binfileimplclient.h sysync/syncitem.h sysync/localengineds.cpp sysync/dataobjtype.h sysync/customimplagent.h sysync/synccommand.h sysync/binfilebase.h sysync/textprofile.h sysync/vcarditemtype.h sysync/binfileimplds.h sysync/vcalendaritemtype.h sysync/syncexception.h sysync/multifielditemtype.cpp sysync/lineartime.cpp sysync/clientautosync_inc.h sysync/debuglogger.h sysync/smltk_precomp_xpt.h sysync/syncsession.cpp sysync/multifielditemtype.h sysync/stdlogicds.h sysync/rrules.h sysync/remotedatastore.cpp sysync/engineentry.cpp sysync/simpleitem.cpp sysync/superdatastore.h sysync/uiapi.h sysync/vcarditemtype.cpp sysync/engineinterface.cpp sysync/syncappbase.h sysync/sysync_crc16.h sysync/syncdatastore.cpp sysync/multifielditem.h sysync/scriptcontext.cpp sysync/syncitemtype.cpp sysync/stdlogicds.cpp sysync/vtimezone.h sysync/uiapi.cpp sysync/syncagent.h sysync/dataconversion.cpp sysync/timezones.cpp sysync/engineinterface.h sysync/superdatastore.cpp sysync/sysync_utils.h sysync/customimplds.h sysync/rrules.cpp sysync/configelement.cpp sysync/syserial.h sysync/syncdatastore.h sysync/mimedirprofile.cpp sysync/stdlogicagent.h DB_interfaces/odbc_db/odbcapids.cpp DB_interfaces/odbc_db/odbcapiagent.h DB_interfaces/odbc_db/odbcapiagent.cpp DB_interfaces/odbc_db/odbcdb_precomp.h DB_interfaces/odbc_db/odbcapids.h DB_interfaces/odbc_db/odbcdb.h DB_interfaces/api_db/plugindb.h DB_interfaces/api_db/dbapi.h DB_interfaces/api_db/pluginapiagent.cpp DB_interfaces/api_db/dbapi_include.h DB_interfaces/api_db/sync_dbapiconnect.h DB_interfaces/api_db/pluginapiagent.h DB_interfaces/api_db/sync_dbapiconnect.cpp DB_interfaces/api_db/pluginapids.cpp DB_interfaces/api_db/plugindb_precomp.h DB_interfaces/api_db/dbapi.cpp DB_interfaces/api_db/DLL_interface.h DB_interfaces/api_db/DLL_interface.cpp DB_interfaces/api_db/pluginapids.h sysync_SDK/Sources/sysync_b64.cpp sysync_SDK/Sources/sysync_md5.cpp sysync_SDK/Sources/sysync_b64.h sysync_SDK/Sources/SDK_util.h sysync_SDK/Sources/prefix_file.h sysync_SDK/Sources/sync_dbapi.h sysync_SDK/Sources/enginemodulebase.h sysync_SDK/Sources/SDK_support.h sysync_SDK/Sources/sync_declarations.h sysync_SDK/Sources/sync_dbapidef.h sysync_SDK/Sources/generic_types.h sysync_SDK/Sources/engine_defs.h sysync_SDK/Sources/sync_include.h sysync_SDK/Sources/SDK_support.cpp sysync_SDK/Sources/SDK_util.c sysync_SDK/Sources/dbitem.h sysync_SDK/Sources/dbitem.cpp sysync_SDK/Sources/blobs.h sysync_SDK/Sources/enginemodulebase.cpp sysync_SDK/Sources/sync_uiapi.h sysync_SDK/Sources/admindata.h sysync_SDK/Sources/dataconversion.h sysync_SDK/Sources/admindata.cpp sysync_SDK/Sources/blobs.cpp sysync_SDK/Sources/sysync_md5.h sysync_SDK/Sources/syerror.h Transport_interfaces/engine/engine_client_precomp.h Transport_interfaces/engine/enginesessiondispatch.h Transport_interfaces/engine/engine_server_precomp.h Transport_interfaces/engine/enginesessiondispatch.cpp Transport_interfaces/engine/engine_server.h Transport_interfaces/engine/engineclientbase.cpp Transport_interfaces/engine/engineclientbase.h Transport_interfaces/engine/engine_client.h platform_adapters/sysync_glob_vars.h platform_adapters/configfiles.h platform_adapters/binfile.cpp platform_adapters/sysyncinit.cpp platform_adapters/profiling.h platform_adapters/linux/platform_DLL.cpp platform_adapters/linux/profiling.cpp platform_adapters/linux/platform_exec.h platform_adapters/linux/configfiles.cpp platform_adapters/linux/platform_time.cpp platform_adapters/linux/platform_exec.c platform_adapters/linux/platform_headers.h platform_adapters/linux/platform_timezones.cpp platform_adapters/linux/platform_time.h platform_adapters/binfile.h platform_adapters/platform_thread.h platform_adapters/platform_DLL.h platform_adapters/unix_common/platform_pipe.c platform_adapters/unix_common/platform_file.cpp platform_adapters/unix_common/platform_pipe.h platform_adapters/unix_common/platform_mutex.cpp platform_adapters/platform_file.h platform_adapters/platform_headers.h platform_adapters/platform_mutex.h syncapps/clientEngine_custom/clientengine_custom_Base.h syncapps/clientEngine_custom/clientengine_custom_Base.cpp syncapps/clientEngine_custom/product_options.h syncapps/clientEngine_custom/clientengine_custom_precomp.h syncapps/clientEngine_custom/clientengine_custom.h syncapps/serverEngine_custom/serverengine_custom.h syncapps/serverEngine_custom/serverengine_custom_Base.cpp syncapps/serverEngine_custom/serverengine_custom_Base.h syncapps/serverEngine_custom/combi_product_options.h syncapps/serverEngine_custom/product_options.h syncapps/serverEngine_custom/serverengine_custom_precomp.h sysync_SDK/DB_Interfaces/text_db/sync_dbapi_text.cpp \
+       $(XMLPARSE_SOURCES)
 libsynthesis_la_CPPFLAGS = -I$(srcdir)/sysync_SDK/Sources
-LIBSYNTHESIS_CFLAGS = \
+libsynthesis_la_CFLAGS = \
        -include $(top_builddir)/config.h \
-       -include $(srcdir)/Targets/ReleasedProducts/clientEngine_opensource_linux/clientengine_demo_x86_linux_prefix.h \
+       -include $(srcdir)/Targets/ReleasedProducts/combiEngine_opensource_linux/combiengine_opensource_linux_prefix.h \
        -I$(srcdir)/Targets/ReleasedProducts/clientEngine_autotools/ \
-       -I$(srcdir)/Targets/ReleasedProducts/clientEngine_opensource_linux/ \
+       -I$(srcdir)/Targets/ReleasedProducts/combiEngine_opensource_linux/ \
        -I$(srcdir)/platform_adapters/linux/ \
        -I$(srcdir)/platform_adapters/unix_common/ \
        -I$(srcdir)/platform_adapters/ \
        -I$(srcdir)/syncapps/clientEngine_custom/ \
+       -I$(srcdir)/syncapps/serverEngine_custom/ \
        -I$(srcdir)/sysync/ \
        -I$(srcdir)/Transport_interfaces/engine/ \
        -I$(srcdir)/ \
@@ -51,13 +69,22 @@ LIBSYNTHESIS_CFLAGS = \
        -I$(srcdir)/DB_interfaces/odbc_db/ \
        -I$(srcdir)/DB_interfaces/api_db/ \
        -I$(srcdir)/sysync_SDK/Sources/ \
-       $(PCRE_CFLAGS) $(SQLITE3_CFLAGS) $(ZLIB_CFLAGS) $(XMLPARSE_CFLAGS) $(LIBICAL_CFLAGS) $(LIBECAL_CFLAGS)
-libsynthesis_la_CFLAGS = $(LIBSYNTHESIS_CFLAGS)
-libsynthesis_la_CXXFLAGS = $(LIBSYNTHESIS_CFLAGS)
+       $(PCRE_CFLAGS) \
+       $(SQLITE3_CFLAGS) \
+       $(ZLIB_CFLAGS) \
+       $(XMLPARSE_CFLAGS) \
+       $(XMLPARSE_CFLAGS_BUILTIN) \
+       $(LIBICAL_CFLAGS) \
+       $(LIBECAL_CFLAGS)
+libsynthesis_la_CXXFLAGS = $(libsynthesis_la_CFLAGS)
 libsynthesis_la_LIBADD = $(PCRE_LIBS) $(SQLITE3_LIBS) $(XMLPARSE_LIBS) $(LIBICAL_LIBS) $(LIBECAL_LIBS) libsmltk.la -lz
+libsynthesis_la_LDFLAGS = -version-info $(ENGINE_CURRENT):$(ENGINE_REVISION):$(ENGINE_AGE) \
+       -Wl,--version-script=$(srcdir)/synthesis-linker.map
+libsynthesis_la_DEPENDENCIES = $(srcdir)/synthesis-linker.map libsmltk.la
+
 if COND_XMLPARSE
-LIBSYNTHESIS_CFLAGS += -I$(srcdir)/expat -I$(srcdir)/expat/xmltok -I$(srcdir)/expat/xmlparse
-libsynthesis_la_SOURCES += \
+XMLPARSE_CFLAGS_BUILTIN = -I$(srcdir)/expat -I$(srcdir)/expat/xmltok -I$(srcdir)/expat/xmlparse
+XMLPARSE_SOURCES = \
        expat/xmlparse/xmlparse.c \
        expat/xmlparse/xmlparse.h \
        expat/xmltok/ascii.h \
@@ -77,48 +104,33 @@ EXTRA_DIST += \
        expat/xmltok/xmltok_ns.c
 else
 # add path to xmlparse.h which includes the system's xmltok/xmlparse.h
-LIBSYNTHESIS_CFLAGS += -I$(srcdir)/Targets/ReleasedProducts/clientEngine_autotools/systemxml
+XMLPARSE_CFLAGS_BUILTIN = -I$(srcdir)/Targets/ReleasedProducts/clientEngine_autotools/systemxml
 endif
 
-# versioning:
-# CURRENT - most recent interface version
-# REVISION - minor version number of that interface implementation
-# AGE - number of previous interface versions supported in addition
-#       to the current one
-#
-# When adding to the interface, increment CURRENT and AGE and reset
-# REVISION to zero. When breaking the interface in a backwards
-# incompatible way, increment CURRENT and reset AGE and REVISION to
-# zero. When fixing something without interface change, increment
-# REVISION.
-ENGINE_CURRENT = 2
-ENGINE_REVISION = 0
-ENGINE_AGE = 2
-libsynthesis_la_LDFLAGS = -version-info $(ENGINE_CURRENT):$(ENGINE_REVISION):$(ENGINE_AGE) \
-       -Wl,--version-script=$(srcdir)/synthesis-linker.map
-libsynthesis_la_DEPENDENCIES = $(srcdir)/synthesis-linker.map libsmltk.la
-
-libsynthesissdk_la_LIBADD = libsynthesis.la
 libsynthesissdk_la_LDFLAGS = -static
-libsynthesissdk_la_SOURCES = synthesis/enginemodulebridge.h synthesis/SDK_util.h synthesis/prefix_file.h synthesis/sync_dbapi.h synthesis/enginemodulebase.h synthesis/SDK_support.h synthesis/stringutil.h synthesis/sync_declarations.h synthesis/sync_dbapidef.h synthesis/generic_types.h synthesis/engine_defs.h synthesis/sync_include.h synthesis/timeutil.h synthesis/dbitem.h synthesis/blobs.h synthesis/sync_uiapi.h synthesis/admindata.h synthesis/dataconversion.h synthesis/syerror.h synthesis/UI_util.h
+libsynthesissdk_la_SOURCES = synthesis/sysync_b64.h synthesis/enginemodulebridge.h synthesis/SDK_util.h synthesis/prefix_file.h synthesis/sync_dbapi.h synthesis/enginemodulebase.h synthesis/SDK_support.h synthesis/stringutil.h synthesis/sync_declarations.h synthesis/sync_dbapidef.h synthesis/generic_types.h synthesis/engine_defs.h synthesis/sync_include.h synthesis/timeutil.h synthesis/dbitem.h synthesis/san.h synthesis/blobs.h synthesis/sync_uiapi.h synthesis/admindata.h synthesis/dataconversion.h synthesis/sysync_md5.h synthesis/syerror.h synthesis/UI_util.h
 if COND_STATIC
-libsynthesissdk_la_SOURCES += sysync_SDK/Sources/timeutil.cpp sysync_SDK/Sources/enginemodulebridge.cpp sysync_SDK/Sources/dbitem.cpp sysync_SDK/Sources/UI_util.cpp sysync_SDK/Sources/stringutil.cpp sysync_SDK/Sources/admindata.cpp sysync_SDK/Sources/blobs.cpp
+libsynthesissdk_la_SOURCES += sysync_SDK/Sources/timeutil.cpp sysync_SDK/Sources/san.cpp sysync_SDK/Sources/enginemodulebridge.cpp sysync_SDK/Sources/UI_util.cpp sysync_SDK/Sources/stringutil.cpp
 else
-libsynthesissdk_la_SOURCES += sysync_SDK/Sources/timeutil.cpp sysync_SDK/Sources/enginemodulebridge.cpp sysync_SDK/Sources/SDK_support.cpp sysync_SDK/Sources/SDK_util.c sysync_SDK/Sources/dbitem.cpp sysync_SDK/Sources/UI_util.cpp sysync_SDK/Sources/enginemodulebase.cpp sysync_SDK/Sources/stringutil.cpp sysync_SDK/Sources/admindata.cpp sysync_SDK/Sources/blobs.cpp
+libsynthesissdk_la_SOURCES += sysync_SDK/Sources/sysync_b64.cpp sysync_SDK/Sources/timeutil.cpp sysync_SDK/Sources/sysync_md5.cpp sysync_SDK/Sources/san.cpp sysync_SDK/Sources/enginemodulebridge.cpp sysync_SDK/Sources/SDK_support.cpp sysync_SDK/Sources/SDK_util.c sysync_SDK/Sources/UI_util.cpp sysync_SDK/Sources/enginemodulebase.cpp sysync_SDK/Sources/stringutil.cpp
 endif
 libsynthesissdk_la_CPPFLAGS = \
        -D_GNU_SOURCE=1 \
        -I$(srcdir)/sysync_SDK/Sources \
        -I$(srcdir)/Targets/ReleasedProducts/SDK
 
+libsynthesisstubs_la_LDFLAGS = -static
+libsynthesisstubs_la_SOURCES = sysync_SDK/Sources/enginestubs.c
+libsynthesisstubs_la_CPPFLAGS = $(libsynthesissdk_la_CPPFLAGS)
+
 # All files needed by libsynthesissdk.a come from either
 # sysync_SDK/Sources (shared between engine and SDK) or
 # sysync_SDK/SDK (only in SDK). We patch the files so that
 # they include their own files via #include "synthesis/..."
-vpath %.cpp $(srcdir)/sysync_SDK/Sources $(srcdir)/sysync_SDK/SDK # $(srcdir)/Targets/ReleasedProducts/clientEngine_opensource_linux $(srcdir)/syncapps/clientEngine_custom $(srcdir)/sysync $(srcdir)/platform_adapters $(srcdir)
-vpath %.c $(srcdir)/sysync_SDK/Sources $(srcdir)/sysync_SDK/SDK # $(srcdir)/Targets/ReleasedProducts/clientEngine_opensource_linux $(srcdir)/syncapps/clientEngine_custom $(srcdir)/sysync $(srcdir)/platform_adapters $(srcdir)
-vpath %.h $(srcdir)/sysync_SDK/Sources $(srcdir)/sysync_SDK/SDK # $(srcdir)/Targets/ReleasedProducts/clientEngine_opensource_linux $(srcdir)/syncapps/clientEngine_custom $(srcdir)/sysync $(srcdir)/platform_adapters $(srcdir)
-synthesis/enginemodulebridge.h synthesis/SDK_util.h synthesis/prefix_file.h synthesis/sync_dbapi.h synthesis/enginemodulebase.h synthesis/SDK_support.h synthesis/stringutil.h synthesis/sync_declarations.h synthesis/sync_dbapidef.h synthesis/generic_types.h synthesis/engine_defs.h synthesis/sync_include.h synthesis/timeutil.h synthesis/dbitem.h synthesis/blobs.h synthesis/sync_uiapi.h synthesis/admindata.h synthesis/dataconversion.h synthesis/syerror.h synthesis/UI_util.h: synthesis/%: %
+vpath %.cpp $(srcdir)/sysync_SDK/Sources $(srcdir)/sysync_SDK/SDK
+vpath %.c $(srcdir)/sysync_SDK/Sources $(srcdir)/sysync_SDK/SDK
+vpath %.h $(srcdir)/sysync_SDK/Sources $(srcdir)/sysync_SDK/SDK
+synthesis/sysync_b64.h synthesis/enginemodulebridge.h synthesis/SDK_util.h synthesis/prefix_file.h synthesis/sync_dbapi.h synthesis/enginemodulebase.h synthesis/SDK_support.h synthesis/stringutil.h synthesis/sync_declarations.h synthesis/sync_dbapidef.h synthesis/generic_types.h synthesis/engine_defs.h synthesis/sync_include.h synthesis/timeutil.h synthesis/dbitem.h synthesis/san.h synthesis/blobs.h synthesis/sync_uiapi.h synthesis/admindata.h synthesis/dataconversion.h synthesis/sysync_md5.h synthesis/syerror.h synthesis/UI_util.h: synthesis/%: %
        mkdir -p synthesis
        sed -e 's;# *include  *";#include "synthesis/;' -e 's/defined(HAVE_STDINT_H)/1/' $< >$@
 
@@ -131,8 +143,8 @@ synthesis/target_options.h: $(srcdir)/Targets/ReleasedProducts/SDK/target_option
 
 # libsmltk: compiled just like libsynthesis
 libsmltk_la_SOURCES = syncml_tk/src/sml/inc/smlmetinfdtd.h syncml_tk/src/sml/inc/smldtd.h syncml_tk/src/sml/inc/smldef.h syncml_tk/src/sml/inc/smldevinfdtd.h syncml_tk/src/sml/inc/smlerr.h syncml_tk/src/sml/inc/sml.h syncml_tk/src/sml/lib/inc/libutil.h syncml_tk/src/sml/lib/inc/liblock.h syncml_tk/src/sml/lib/inc/libstr.h syncml_tk/src/sml/lib/inc/libmem.h syncml_tk/src/sml/lib/all/libutil.c syncml_tk/src/sml/lib/all/libstr.c syncml_tk/src/sml/lib/all/liblock.c syncml_tk/src/sml/lib/all/libmem.c syncml_tk/src/sml/wsm/inc/wsm.h syncml_tk/src/sml/wsm/inc/wsm_sm.h syncml_tk/src/sml/wsm/all/wsm.c syncml_tk/src/sml/mgr/inc/mgr.h syncml_tk/src/sml/mgr/inc/mgrutil.h syncml_tk/src/sml/mgr/all/mgr.c syncml_tk/src/sml/mgr/all/mgrutil.c syncml_tk/src/sml/mgr/all/mgrcmddispatcher.c syncml_tk/src/sml/mgr/all/mgrinstancelist.c syncml_tk/src/sml/mgr/all/mgrinstancemgr.c syncml_tk/src/sml/mgr/all/mgrcmdbuilder.c syncml_tk/src/sml/xlt/inc/xltdec.h syncml_tk/src/sml/xlt/inc/xltenc.h syncml_tk/src/sml/xlt/all/xltenccom.c syncml_tk/src/sml/xlt/all/xltmetinf.h syncml_tk/src/sml/xlt/all/xltmetinf.c syncml_tk/src/sml/xlt/all/xltenccom.h syncml_tk/src/sml/xlt/all/xltdeccom.h syncml_tk/src/sml/xlt/all/xltencwbxml.h syncml_tk/src/sml/xlt/all/xltutilstack.c syncml_tk/src/sml/xlt/all/xltenc.c syncml_tk/src/sml/xlt/all/xltencxml.h syncml_tk/src/sml/xlt/all/xltencwbxml.c syncml_tk/src/sml/xlt/all/xltdevinf.c syncml_tk/src/sml/xlt/all/xltdecwbxml.h syncml_tk/src/sml/xlt/all/xltdecwbxml.c syncml_tk/src/sml/xlt/all/xlttags.h syncml_tk/src/sml/xlt/all/xltdecxml.c syncml_tk/src/sml/xlt/all/xltutilstack.h syncml_tk/src/sml/xlt/all/xlttags.c syncml_tk/src/sml/xlt/all/xltencxml.c syncml_tk/src/sml/xlt/all/xlttagtbl.h syncml_tk/src/sml/xlt/all/xltdec.c syncml_tk/src/sml/xlt/all/xltdevinf.h
-libsmltk_la_CFLAGS = $(LIBSYNTHESIS_CFLAGS)
-libsmltk_la_CXXFLAGS = $(LIBSYNTHESIS_CFLAGS)
+libsmltk_la_CFLAGS = $(libsynthesis_la_CFLAGS)
+libsmltk_la_CXXFLAGS = $(libsmltk_la_CFLAGS)
 
 # versioning: same as of engine! changes in libsmltk are not tracked separately.
 libsmltk_la_LDFLAGS = -version-info $(ENGINE_CURRENT):$(ENGINE_REVISION):$(ENGINE_AGE) \
index 0db8b55..b02cf74 100644 (file)
@@ -9,34 +9,52 @@
 $(srcdir)/Makefile.am: $(srcdir)/Makefile.am.in $(srcdir)/gen-makefile-am.sh
        cd $(srcdir) && sh ./gen-makefile-am.sh
 
+# versioning for *all* libs
+#
+# CURRENT - most recent interface version
+# REVISION - minor version number of that interface implementation
+# AGE - number of previous interface versions supported in addition
+#       to the current one
+#
+# When adding to the interface, increment CURRENT and AGE and reset
+# REVISION to zero. When breaking the interface in a backwards
+# incompatible way, increment CURRENT and reset AGE and REVISION to
+# zero. When fixing something without interface change, increment
+# REVISION.
+ENGINE_CURRENT = 3
+ENGINE_REVISION = 0
+ENGINE_AGE = 3
+
 CLEANFILES =
 EXTRA_DIST =
 
-lib_LTLIBRARIES = libsmltk.la libsynthesis.la libsynthesissdk.la
+lib_LTLIBRARIES = libsmltk.la libsynthesis.la libsynthesissdk.la libsynthesisstubs.la
 nobase_include_HEADERS = @LIBSYNTHESISSDK_HEADERS@ synthesis/target_options.h
 
 # Configuration header files are searched in this order:
 # - Targets/ReleasedProducts/autotools: files only used when compiling with autotools
-# - Targets/ReleasedProducts/[clientEngine_opensource_linux|SDK]: files also used with Synthesis Linux makefile
+# - Targets/ReleasedProducts/[combiEngine_opensource_linux|serverEngine_opensource_linux|SDK]: files also used with Synthesis Linux makefile
 #
 # Always included first via -include:
 # - config.h: configure result (top directory)
-# - Targets/ReleasedProducts/clientEngine_opensource_linux/clientengine_demo_x86_linux_prefix.h
+# - Targets/ReleasedProducts/combiEngine_opensource_linux/clientengine_demo_x86_linux_prefix.h resp. Targets/ReleasedProducts/serverEngine_opensource_linux/serverengine_opensource_linux_prefix.h
 #
 # Included as needed:
 # - define.h: hard-coded SyncML Toolkit config (from search path above)
 
-libsynthesis_la_SOURCES = @LIBSYNTHESIS_SOURCES@
+libsynthesis_la_SOURCES = @LIBSYNTHESIS_SOURCES@ \
+       $(XMLPARSE_SOURCES)
 libsynthesis_la_CPPFLAGS = -I$(srcdir)/sysync_SDK/Sources
-LIBSYNTHESIS_CFLAGS = \
+libsynthesis_la_CFLAGS = \
        -include $(top_builddir)/config.h \
-       -include $(srcdir)/Targets/ReleasedProducts/clientEngine_opensource_linux/clientengine_demo_x86_linux_prefix.h \
+       -include $(srcdir)/Targets/ReleasedProducts/combiEngine_opensource_linux/combiengine_opensource_linux_prefix.h \
        -I$(srcdir)/Targets/ReleasedProducts/clientEngine_autotools/ \
-       -I$(srcdir)/Targets/ReleasedProducts/clientEngine_opensource_linux/ \
+       -I$(srcdir)/Targets/ReleasedProducts/combiEngine_opensource_linux/ \
        -I$(srcdir)/platform_adapters/linux/ \
        -I$(srcdir)/platform_adapters/unix_common/ \
        -I$(srcdir)/platform_adapters/ \
        -I$(srcdir)/syncapps/clientEngine_custom/ \
+       -I$(srcdir)/syncapps/serverEngine_custom/ \
        -I$(srcdir)/sysync/ \
        -I$(srcdir)/Transport_interfaces/engine/ \
        -I$(srcdir)/ \
@@ -51,13 +69,22 @@ LIBSYNTHESIS_CFLAGS = \
        -I$(srcdir)/DB_interfaces/odbc_db/ \
        -I$(srcdir)/DB_interfaces/api_db/ \
        -I$(srcdir)/sysync_SDK/Sources/ \
-       $(PCRE_CFLAGS) $(SQLITE3_CFLAGS) $(ZLIB_CFLAGS) $(XMLPARSE_CFLAGS) $(LIBICAL_CFLAGS) $(LIBECAL_CFLAGS)
-libsynthesis_la_CFLAGS = $(LIBSYNTHESIS_CFLAGS)
-libsynthesis_la_CXXFLAGS = $(LIBSYNTHESIS_CFLAGS)
+       $(PCRE_CFLAGS) \
+       $(SQLITE3_CFLAGS) \
+       $(ZLIB_CFLAGS) \
+       $(XMLPARSE_CFLAGS) \
+       $(XMLPARSE_CFLAGS_BUILTIN) \
+       $(LIBICAL_CFLAGS) \
+       $(LIBECAL_CFLAGS)
+libsynthesis_la_CXXFLAGS = $(libsynthesis_la_CFLAGS)
 libsynthesis_la_LIBADD = $(PCRE_LIBS) $(SQLITE3_LIBS) $(XMLPARSE_LIBS) $(LIBICAL_LIBS) $(LIBECAL_LIBS) libsmltk.la -lz
+libsynthesis_la_LDFLAGS = -version-info $(ENGINE_CURRENT):$(ENGINE_REVISION):$(ENGINE_AGE) \
+       -Wl,--version-script=$(srcdir)/synthesis-linker.map
+libsynthesis_la_DEPENDENCIES = $(srcdir)/synthesis-linker.map libsmltk.la
+
 if COND_XMLPARSE
-LIBSYNTHESIS_CFLAGS += -I$(srcdir)/expat -I$(srcdir)/expat/xmltok -I$(srcdir)/expat/xmlparse
-libsynthesis_la_SOURCES += \
+XMLPARSE_CFLAGS_BUILTIN = -I$(srcdir)/expat -I$(srcdir)/expat/xmltok -I$(srcdir)/expat/xmlparse
+XMLPARSE_SOURCES = \
        expat/xmlparse/xmlparse.c \
        expat/xmlparse/xmlparse.h \
        expat/xmltok/ascii.h \
@@ -77,28 +104,9 @@ EXTRA_DIST += \
        expat/xmltok/xmltok_ns.c
 else
 # add path to xmlparse.h which includes the system's xmltok/xmlparse.h
-LIBSYNTHESIS_CFLAGS += -I$(srcdir)/Targets/ReleasedProducts/clientEngine_autotools/systemxml
+XMLPARSE_CFLAGS_BUILTIN = -I$(srcdir)/Targets/ReleasedProducts/clientEngine_autotools/systemxml
 endif
 
-# versioning:
-# CURRENT - most recent interface version
-# REVISION - minor version number of that interface implementation
-# AGE - number of previous interface versions supported in addition
-#       to the current one
-#
-# When adding to the interface, increment CURRENT and AGE and reset
-# REVISION to zero. When breaking the interface in a backwards
-# incompatible way, increment CURRENT and reset AGE and REVISION to
-# zero. When fixing something without interface change, increment
-# REVISION.
-ENGINE_CURRENT = 2
-ENGINE_REVISION = 0
-ENGINE_AGE = 2
-libsynthesis_la_LDFLAGS = -version-info $(ENGINE_CURRENT):$(ENGINE_REVISION):$(ENGINE_AGE) \
-       -Wl,--version-script=$(srcdir)/synthesis-linker.map
-libsynthesis_la_DEPENDENCIES = $(srcdir)/synthesis-linker.map libsmltk.la
-
-libsynthesissdk_la_LIBADD = libsynthesis.la
 libsynthesissdk_la_LDFLAGS = -static
 libsynthesissdk_la_SOURCES = @LIBSYNTHESISSDK_HEADERS@
 if COND_STATIC
@@ -111,13 +119,17 @@ libsynthesissdk_la_CPPFLAGS = \
        -I$(srcdir)/sysync_SDK/Sources \
        -I$(srcdir)/Targets/ReleasedProducts/SDK
 
+libsynthesisstubs_la_LDFLAGS = -static
+libsynthesisstubs_la_SOURCES = sysync_SDK/Sources/enginestubs.c
+libsynthesisstubs_la_CPPFLAGS = $(libsynthesissdk_la_CPPFLAGS)
+
 # All files needed by libsynthesissdk.a come from either
 # sysync_SDK/Sources (shared between engine and SDK) or
 # sysync_SDK/SDK (only in SDK). We patch the files so that
 # they include their own files via #include "synthesis/..."
-vpath %.cpp $(srcdir)/sysync_SDK/Sources $(srcdir)/sysync_SDK/SDK # $(srcdir)/Targets/ReleasedProducts/clientEngine_opensource_linux $(srcdir)/syncapps/clientEngine_custom $(srcdir)/sysync $(srcdir)/platform_adapters $(srcdir)
-vpath %.c $(srcdir)/sysync_SDK/Sources $(srcdir)/sysync_SDK/SDK # $(srcdir)/Targets/ReleasedProducts/clientEngine_opensource_linux $(srcdir)/syncapps/clientEngine_custom $(srcdir)/sysync $(srcdir)/platform_adapters $(srcdir)
-vpath %.h $(srcdir)/sysync_SDK/Sources $(srcdir)/sysync_SDK/SDK # $(srcdir)/Targets/ReleasedProducts/clientEngine_opensource_linux $(srcdir)/syncapps/clientEngine_custom $(srcdir)/sysync $(srcdir)/platform_adapters $(srcdir)
+vpath %.cpp $(srcdir)/sysync_SDK/Sources $(srcdir)/sysync_SDK/SDK
+vpath %.c $(srcdir)/sysync_SDK/Sources $(srcdir)/sysync_SDK/SDK
+vpath %.h $(srcdir)/sysync_SDK/Sources $(srcdir)/sysync_SDK/SDK
 @LIBSYNTHESISSDK_HEADERS@: synthesis/%: %
        mkdir -p synthesis
        sed -e 's;# *include  *";#include "synthesis/;' -e 's/defined(HAVE_STDINT_H)/1/' $< >$@
@@ -131,8 +143,8 @@ synthesis/target_options.h: $(srcdir)/Targets/ReleasedProducts/SDK/target_option
 
 # libsmltk: compiled just like libsynthesis
 libsmltk_la_SOURCES = @LIBSMLTK_SOURCES@
-libsmltk_la_CFLAGS = $(LIBSYNTHESIS_CFLAGS)
-libsmltk_la_CXXFLAGS = $(LIBSYNTHESIS_CFLAGS)
+libsmltk_la_CFLAGS = $(libsynthesis_la_CFLAGS)
+libsmltk_la_CXXFLAGS = $(libsmltk_la_CFLAGS)
 
 # versioning: same as of engine! changes in libsmltk are not tracked separately.
 libsmltk_la_LDFLAGS = -version-info $(ENGINE_CURRENT):$(ENGINE_REVISION):$(ENGINE_AGE) \
index e1eb195..6e89e23 100644 (file)
@@ -33,31 +33,12 @@ PRE_UNINSTALL = :
 POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
-@COND_XMLPARSE_TRUE@am__append_1 = -I$(srcdir)/expat -I$(srcdir)/expat/xmltok -I$(srcdir)/expat/xmlparse
-@COND_XMLPARSE_TRUE@am__append_2 = \
-@COND_XMLPARSE_TRUE@   expat/xmlparse/xmlparse.c \
-@COND_XMLPARSE_TRUE@   expat/xmlparse/xmlparse.h \
-@COND_XMLPARSE_TRUE@   expat/xmltok/ascii.h \
-@COND_XMLPARSE_TRUE@   expat/xmltok/asciitab.h \
-@COND_XMLPARSE_TRUE@   expat/xmltok/iasciitab.h \
-@COND_XMLPARSE_TRUE@   expat/xmltok/latin1tab.h \
-@COND_XMLPARSE_TRUE@   expat/xmltok/nametab.h \
-@COND_XMLPARSE_TRUE@   expat/xmltok/utf8tab.h \
-@COND_XMLPARSE_TRUE@   expat/xmltok/xmldef.h \
-@COND_XMLPARSE_TRUE@   expat/xmltok/xmlrole.c \
-@COND_XMLPARSE_TRUE@   expat/xmltok/xmlrole.h \
-@COND_XMLPARSE_TRUE@   expat/xmltok/xmltok.c \
-@COND_XMLPARSE_TRUE@   expat/xmltok/xmltok.h \
-@COND_XMLPARSE_TRUE@   expat/xmltok/xmltok_impl.h
-
-@COND_XMLPARSE_TRUE@am__append_3 = \
+@COND_XMLPARSE_TRUE@am__append_1 = \
 @COND_XMLPARSE_TRUE@   expat/xmltok/xmltok_impl.c \
 @COND_XMLPARSE_TRUE@   expat/xmltok/xmltok_ns.c
 
-# add path to xmlparse.h which includes the system's xmltok/xmlparse.h
-@COND_XMLPARSE_FALSE@am__append_4 = -I$(srcdir)/Targets/ReleasedProducts/clientEngine_autotools/systemxml
-@COND_STATIC_TRUE@am__append_5 = sysync_SDK/Sources/timeutil.cpp sysync_SDK/Sources/enginemodulebridge.cpp sysync_SDK/Sources/dbitem.cpp sysync_SDK/Sources/UI_util.cpp sysync_SDK/Sources/stringutil.cpp sysync_SDK/Sources/admindata.cpp sysync_SDK/Sources/blobs.cpp
-@COND_STATIC_FALSE@am__append_6 = sysync_SDK/Sources/timeutil.cpp sysync_SDK/Sources/enginemodulebridge.cpp sysync_SDK/Sources/SDK_support.cpp sysync_SDK/Sources/SDK_util.c sysync_SDK/Sources/dbitem.cpp sysync_SDK/Sources/UI_util.cpp sysync_SDK/Sources/enginemodulebase.cpp sysync_SDK/Sources/stringutil.cpp sysync_SDK/Sources/admindata.cpp sysync_SDK/Sources/blobs.cpp
+@COND_STATIC_TRUE@am__append_2 = sysync_SDK/Sources/timeutil.cpp sysync_SDK/Sources/san.cpp sysync_SDK/Sources/enginemodulebridge.cpp sysync_SDK/Sources/UI_util.cpp sysync_SDK/Sources/stringutil.cpp
+@COND_STATIC_FALSE@am__append_3 = sysync_SDK/Sources/sysync_b64.cpp sysync_SDK/Sources/timeutil.cpp sysync_SDK/Sources/sysync_md5.cpp sysync_SDK/Sources/san.cpp sysync_SDK/Sources/enginemodulebridge.cpp sysync_SDK/Sources/SDK_support.cpp sysync_SDK/Sources/SDK_util.c sysync_SDK/Sources/UI_util.cpp sysync_SDK/Sources/enginemodulebase.cpp sysync_SDK/Sources/stringutil.cpp
 subdir = src
 DIST_COMMON = $(nobase_include_HEADERS) $(srcdir)/Makefile.am \
        $(srcdir)/Makefile.in
@@ -95,11 +76,10 @@ libsmltk_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
        $(CFLAGS) $(libsmltk_la_LDFLAGS) $(LDFLAGS) -o $@
 am__DEPENDENCIES_1 =
 am__libsynthesis_la_SOURCES_DIST = sysync/binfileimplclient.cpp \
-       sysync/syncclientbase.h sysync/sysync_b64.cpp \
-       sysync/sysync_md5.cpp sysync/sysync_b64.h \
+       sysync/syncclientbase.h sysync/syncagent.cpp \
        sysync/syncml_globs.h sysync/stdlogicagent.cpp \
        sysync/syncappbase.cpp sysync/customimplds.cpp \
-       sysync/syncsession.h sysync/syncclient.cpp sysync/syncitem.cpp \
+       sysync/syncsession.h sysync/syncitem.cpp \
        sysync/textitemtype.cpp sysync/textitemtype.h \
        sysync/localengineds.h sysync/syncexception.cpp \
        sysync/clientprovisioning_inc.h sysync/global_progress.h \
@@ -109,12 +89,11 @@ am__libsynthesis_la_SOURCES_DIST = sysync/binfileimplclient.cpp \
        sysync/vcalendaritemtype.cpp sysync/scriptcontext.h \
        sysync/syncitemtype.h sysync/smltk_precomp.h \
        sysync/sysync_globs.h sysync/sysync_debug.h \
-       sysync/syncsessiondispatch.h sysync/san.cpp \
-       sysync/sysync_utils.cpp sysync/mimediritemtype.h \
-       sysync/dataobjtype.cpp sysync/multifielditem.cpp \
-       sysync/sysync_precomp_xpt.h sysync/iso8601.cpp \
-       sysync/syncclientbase.cpp sysync/itemfield.h \
-       sysync/syncserver.h sysync/remotedatastore.h \
+       sysync/syncsessiondispatch.h sysync/sysync_utils.cpp \
+       sysync/mimediritemtype.h sysync/dataobjtype.cpp \
+       sysync/multifielditem.cpp sysync/sysync_precomp_xpt.h \
+       sysync/iso8601.cpp sysync/syncclientbase.cpp \
+       sysync/itemfield.h sysync/remotedatastore.h \
        sysync/engineentry.h sysync/itemfield.cpp sysync/stringutils.h \
        sysync/lineartime.h sysync/syncml_tk.h \
        sysync/mimediritemtype.cpp sysync/configelement.h \
@@ -128,7 +107,7 @@ am__libsynthesis_la_SOURCES_DIST = sysync/binfileimplclient.cpp \
        sysync/customimplagent.h sysync/synccommand.h \
        sysync/binfilebase.h sysync/textprofile.h \
        sysync/vcarditemtype.h sysync/binfileimplds.h \
-       sysync/vcalendaritemtype.h sysync/syncexception.h sysync/san.h \
+       sysync/vcalendaritemtype.h sysync/syncexception.h \
        sysync/multifielditemtype.cpp sysync/lineartime.cpp \
        sysync/clientautosync_inc.h sysync/debuglogger.h \
        sysync/smltk_precomp_xpt.h sysync/syncsession.cpp \
@@ -137,12 +116,12 @@ am__libsynthesis_la_SOURCES_DIST = sysync/binfileimplclient.cpp \
        sysync/engineentry.cpp sysync/simpleitem.cpp \
        sysync/superdatastore.h sysync/uiapi.h \
        sysync/vcarditemtype.cpp sysync/engineinterface.cpp \
-       sysync/syncappbase.h sysync/syncclient.h sysync/sysync_crc16.h \
+       sysync/syncappbase.h sysync/sysync_crc16.h \
        sysync/syncdatastore.cpp sysync/multifielditem.h \
        sysync/scriptcontext.cpp sysync/syncitemtype.cpp \
        sysync/stdlogicds.cpp sysync/vtimezone.h sysync/uiapi.cpp \
-       sysync/dataconversion.cpp sysync/timezones.cpp \
-       sysync/engineinterface.h sysync/sysync_md5.h \
+       sysync/syncagent.h sysync/dataconversion.cpp \
+       sysync/timezones.cpp sysync/engineinterface.h \
        sysync/superdatastore.cpp sysync/sysync_utils.h \
        sysync/customimplds.h sysync/rrules.cpp \
        sysync/configelement.cpp sysync/syserial.h \
@@ -165,7 +144,10 @@ am__libsynthesis_la_SOURCES_DIST = sysync/binfileimplclient.cpp \
        DB_interfaces/api_db/DLL_interface.h \
        DB_interfaces/api_db/DLL_interface.cpp \
        DB_interfaces/api_db/pluginapids.h \
-       sysync_SDK/Sources/SDK_util.h sysync_SDK/Sources/prefix_file.h \
+       sysync_SDK/Sources/sysync_b64.cpp \
+       sysync_SDK/Sources/sysync_md5.cpp \
+       sysync_SDK/Sources/sysync_b64.h sysync_SDK/Sources/SDK_util.h \
+       sysync_SDK/Sources/prefix_file.h \
        sysync_SDK/Sources/sync_dbapi.h \
        sysync_SDK/Sources/enginemodulebase.h \
        sysync_SDK/Sources/SDK_support.h \
@@ -175,12 +157,18 @@ am__libsynthesis_la_SOURCES_DIST = sysync/binfileimplclient.cpp \
        sysync_SDK/Sources/engine_defs.h \
        sysync_SDK/Sources/sync_include.h \
        sysync_SDK/Sources/SDK_support.cpp \
-       sysync_SDK/Sources/SDK_util.c \
+       sysync_SDK/Sources/SDK_util.c sysync_SDK/Sources/dbitem.h \
+       sysync_SDK/Sources/dbitem.cpp sysync_SDK/Sources/blobs.h \
        sysync_SDK/Sources/enginemodulebase.cpp \
-       sysync_SDK/Sources/sync_uiapi.h \
+       sysync_SDK/Sources/sync_uiapi.h sysync_SDK/Sources/admindata.h \
        sysync_SDK/Sources/dataconversion.h \
-       sysync_SDK/Sources/syerror.h \
+       sysync_SDK/Sources/admindata.cpp sysync_SDK/Sources/blobs.cpp \
+       sysync_SDK/Sources/sysync_md5.h sysync_SDK/Sources/syerror.h \
        Transport_interfaces/engine/engine_client_precomp.h \
+       Transport_interfaces/engine/enginesessiondispatch.h \
+       Transport_interfaces/engine/engine_server_precomp.h \
+       Transport_interfaces/engine/enginesessiondispatch.cpp \
+       Transport_interfaces/engine/engine_server.h \
        Transport_interfaces/engine/engineclientbase.cpp \
        Transport_interfaces/engine/engineclientbase.h \
        Transport_interfaces/engine/engine_client.h \
@@ -201,7 +189,6 @@ am__libsynthesis_la_SOURCES_DIST = sysync/binfileimplclient.cpp \
        platform_adapters/platform_DLL.h \
        platform_adapters/unix_common/platform_pipe.c \
        platform_adapters/unix_common/platform_file.cpp \
-       platform_adapters/unix_common/platform_thread.cpp \
        platform_adapters/unix_common/platform_pipe.h \
        platform_adapters/unix_common/platform_mutex.cpp \
        platform_adapters/platform_file.h \
@@ -212,6 +199,13 @@ am__libsynthesis_la_SOURCES_DIST = sysync/binfileimplclient.cpp \
        syncapps/clientEngine_custom/product_options.h \
        syncapps/clientEngine_custom/clientengine_custom_precomp.h \
        syncapps/clientEngine_custom/clientengine_custom.h \
+       syncapps/serverEngine_custom/serverengine_custom.h \
+       syncapps/serverEngine_custom/serverengine_custom_Base.cpp \
+       syncapps/serverEngine_custom/serverengine_custom_Base.h \
+       syncapps/serverEngine_custom/combi_product_options.h \
+       syncapps/serverEngine_custom/product_options.h \
+       syncapps/serverEngine_custom/serverengine_custom_precomp.h \
+       sysync_SDK/DB_Interfaces/text_db/sync_dbapi_text.cpp \
        expat/xmlparse/xmlparse.c expat/xmlparse/xmlparse.h \
        expat/xmltok/ascii.h expat/xmltok/asciitab.h \
        expat/xmltok/iasciitab.h expat/xmltok/latin1tab.h \
@@ -223,16 +217,14 @@ am__libsynthesis_la_SOURCES_DIST = sysync/binfileimplclient.cpp \
 @COND_XMLPARSE_TRUE@   libsynthesis_la-xmlrole.lo \
 @COND_XMLPARSE_TRUE@   libsynthesis_la-xmltok.lo
 am_libsynthesis_la_OBJECTS = libsynthesis_la-binfileimplclient.lo \
-       libsynthesis_la-sysync_b64.lo libsynthesis_la-sysync_md5.lo \
-       libsynthesis_la-stdlogicagent.lo \
+       libsynthesis_la-syncagent.lo libsynthesis_la-stdlogicagent.lo \
        libsynthesis_la-syncappbase.lo libsynthesis_la-customimplds.lo \
-       libsynthesis_la-syncclient.lo libsynthesis_la-syncitem.lo \
-       libsynthesis_la-textitemtype.lo \
+       libsynthesis_la-syncitem.lo libsynthesis_la-textitemtype.lo \
        libsynthesis_la-syncexception.lo \
        libsynthesis_la-textprofile.lo libsynthesis_la-stringutils.lo \
        libsynthesis_la-customimplagent.lo \
        libsynthesis_la-debuglogger.lo libsynthesis_la-vtimezone.lo \
-       libsynthesis_la-vcalendaritemtype.lo libsynthesis_la-san.lo \
+       libsynthesis_la-vcalendaritemtype.lo \
        libsynthesis_la-sysync_utils.lo libsynthesis_la-dataobjtype.lo \
        libsynthesis_la-multifielditem.lo libsynthesis_la-iso8601.lo \
        libsynthesis_la-syncclientbase.lo libsynthesis_la-itemfield.lo \
@@ -259,9 +251,12 @@ am_libsynthesis_la_OBJECTS = libsynthesis_la-binfileimplclient.lo \
        libsynthesis_la-pluginapiagent.lo \
        libsynthesis_la-sync_dbapiconnect.lo \
        libsynthesis_la-pluginapids.lo libsynthesis_la-dbapi.lo \
-       libsynthesis_la-DLL_interface.lo \
-       libsynthesis_la-SDK_support.lo libsynthesis_la-SDK_util.lo \
+       libsynthesis_la-DLL_interface.lo libsynthesis_la-sysync_b64.lo \
+       libsynthesis_la-sysync_md5.lo libsynthesis_la-SDK_support.lo \
+       libsynthesis_la-SDK_util.lo libsynthesis_la-dbitem.lo \
        libsynthesis_la-enginemodulebase.lo \
+       libsynthesis_la-admindata.lo libsynthesis_la-blobs.lo \
+       libsynthesis_la-enginesessiondispatch.lo \
        libsynthesis_la-engineclientbase.lo libsynthesis_la-binfile.lo \
        libsynthesis_la-sysyncinit.lo libsynthesis_la-platform_DLL.lo \
        libsynthesis_la-profiling.lo libsynthesis_la-configfiles.lo \
@@ -270,55 +265,62 @@ am_libsynthesis_la_OBJECTS = libsynthesis_la-binfileimplclient.lo \
        libsynthesis_la-platform_timezones.lo \
        libsynthesis_la-platform_pipe.lo \
        libsynthesis_la-platform_file.lo \
-       libsynthesis_la-platform_thread.lo \
        libsynthesis_la-platform_mutex.lo \
-       libsynthesis_la-clientengine_custom_Base.lo $(am__objects_1)
+       libsynthesis_la-clientengine_custom_Base.lo \
+       libsynthesis_la-serverengine_custom_Base.lo \
+       libsynthesis_la-sync_dbapi_text.lo $(am__objects_1)
 libsynthesis_la_OBJECTS = $(am_libsynthesis_la_OBJECTS)
 libsynthesis_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
        $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
        $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) \
        $(libsynthesis_la_LDFLAGS) $(LDFLAGS) -o $@
-libsynthesissdk_la_DEPENDENCIES = libsynthesis.la
-am__libsynthesissdk_la_SOURCES_DIST = synthesis/enginemodulebridge.h \
-       synthesis/SDK_util.h synthesis/prefix_file.h \
-       synthesis/sync_dbapi.h synthesis/enginemodulebase.h \
-       synthesis/SDK_support.h synthesis/stringutil.h \
-       synthesis/sync_declarations.h synthesis/sync_dbapidef.h \
-       synthesis/generic_types.h synthesis/engine_defs.h \
-       synthesis/sync_include.h synthesis/timeutil.h \
-       synthesis/dbitem.h synthesis/blobs.h synthesis/sync_uiapi.h \
-       synthesis/admindata.h synthesis/dataconversion.h \
+libsynthesissdk_la_LIBADD =
+am__libsynthesissdk_la_SOURCES_DIST = synthesis/sysync_b64.h \
+       synthesis/enginemodulebridge.h synthesis/SDK_util.h \
+       synthesis/prefix_file.h synthesis/sync_dbapi.h \
+       synthesis/enginemodulebase.h synthesis/SDK_support.h \
+       synthesis/stringutil.h synthesis/sync_declarations.h \
+       synthesis/sync_dbapidef.h synthesis/generic_types.h \
+       synthesis/engine_defs.h synthesis/sync_include.h \
+       synthesis/timeutil.h synthesis/dbitem.h synthesis/san.h \
+       synthesis/blobs.h synthesis/sync_uiapi.h synthesis/admindata.h \
+       synthesis/dataconversion.h synthesis/sysync_md5.h \
        synthesis/syerror.h synthesis/UI_util.h \
-       sysync_SDK/Sources/timeutil.cpp \
+       sysync_SDK/Sources/timeutil.cpp sysync_SDK/Sources/san.cpp \
        sysync_SDK/Sources/enginemodulebridge.cpp \
-       sysync_SDK/Sources/dbitem.cpp sysync_SDK/Sources/UI_util.cpp \
+       sysync_SDK/Sources/UI_util.cpp \
        sysync_SDK/Sources/stringutil.cpp \
-       sysync_SDK/Sources/admindata.cpp sysync_SDK/Sources/blobs.cpp \
+       sysync_SDK/Sources/sysync_b64.cpp \
+       sysync_SDK/Sources/sysync_md5.cpp \
        sysync_SDK/Sources/SDK_support.cpp \
        sysync_SDK/Sources/SDK_util.c \
        sysync_SDK/Sources/enginemodulebase.cpp
 @COND_STATIC_TRUE@am__objects_2 = libsynthesissdk_la-timeutil.lo \
+@COND_STATIC_TRUE@     libsynthesissdk_la-san.lo \
 @COND_STATIC_TRUE@     libsynthesissdk_la-enginemodulebridge.lo \
-@COND_STATIC_TRUE@     libsynthesissdk_la-dbitem.lo \
 @COND_STATIC_TRUE@     libsynthesissdk_la-UI_util.lo \
-@COND_STATIC_TRUE@     libsynthesissdk_la-stringutil.lo \
-@COND_STATIC_TRUE@     libsynthesissdk_la-admindata.lo \
-@COND_STATIC_TRUE@     libsynthesissdk_la-blobs.lo
-@COND_STATIC_FALSE@am__objects_3 = libsynthesissdk_la-timeutil.lo \
+@COND_STATIC_TRUE@     libsynthesissdk_la-stringutil.lo
+@COND_STATIC_FALSE@am__objects_3 = libsynthesissdk_la-sysync_b64.lo \
+@COND_STATIC_FALSE@    libsynthesissdk_la-timeutil.lo \
+@COND_STATIC_FALSE@    libsynthesissdk_la-sysync_md5.lo \
+@COND_STATIC_FALSE@    libsynthesissdk_la-san.lo \
 @COND_STATIC_FALSE@    libsynthesissdk_la-enginemodulebridge.lo \
 @COND_STATIC_FALSE@    libsynthesissdk_la-SDK_support.lo \
 @COND_STATIC_FALSE@    libsynthesissdk_la-SDK_util.lo \
-@COND_STATIC_FALSE@    libsynthesissdk_la-dbitem.lo \
 @COND_STATIC_FALSE@    libsynthesissdk_la-UI_util.lo \
 @COND_STATIC_FALSE@    libsynthesissdk_la-enginemodulebase.lo \
-@COND_STATIC_FALSE@    libsynthesissdk_la-stringutil.lo \
-@COND_STATIC_FALSE@    libsynthesissdk_la-admindata.lo \
-@COND_STATIC_FALSE@    libsynthesissdk_la-blobs.lo
+@COND_STATIC_FALSE@    libsynthesissdk_la-stringutil.lo
 am_libsynthesissdk_la_OBJECTS = $(am__objects_2) $(am__objects_3)
 libsynthesissdk_la_OBJECTS = $(am_libsynthesissdk_la_OBJECTS)
 libsynthesissdk_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
        $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
        $(CXXFLAGS) $(libsynthesissdk_la_LDFLAGS) $(LDFLAGS) -o $@
+libsynthesisstubs_la_LIBADD =
+am_libsynthesisstubs_la_OBJECTS = libsynthesisstubs_la-enginestubs.lo
+libsynthesisstubs_la_OBJECTS = $(am_libsynthesisstubs_la_OBJECTS)
+libsynthesisstubs_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(libsynthesisstubs_la_LDFLAGS) $(LDFLAGS) -o $@
 DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
 depcomp = $(SHELL) $(top_srcdir)/../../depcomp
 am__depfiles_maybe = depfiles
@@ -341,10 +343,11 @@ CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
        --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
        $(LDFLAGS) -o $@
 SOURCES = $(libsmltk_la_SOURCES) $(libsynthesis_la_SOURCES) \
-       $(libsynthesissdk_la_SOURCES)
+       $(libsynthesissdk_la_SOURCES) $(libsynthesisstubs_la_SOURCES)
 DIST_SOURCES = $(libsmltk_la_SOURCES) \
        $(am__libsynthesis_la_SOURCES_DIST) \
-       $(am__libsynthesissdk_la_SOURCES_DIST)
+       $(am__libsynthesissdk_la_SOURCES_DIST) \
+       $(libsynthesisstubs_la_SOURCES)
 nobase_includeHEADERS_INSTALL = $(install_sh_DATA)
 HEADERS = $(nobase_include_HEADERS)
 ETAGS = etags
@@ -469,150 +472,54 @@ sysconfdir = @sysconfdir@
 target_alias = @target_alias@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
+
+# versioning for *all* libs
+#
+# CURRENT - most recent interface version
+# REVISION - minor version number of that interface implementation
+# AGE - number of previous interface versions supported in addition
+#       to the current one
+#
+# When adding to the interface, increment CURRENT and AGE and reset
+# REVISION to zero. When breaking the interface in a backwards
+# incompatible way, increment CURRENT and reset AGE and REVISION to
+# zero. When fixing something without interface change, increment
+# REVISION.
+ENGINE_CURRENT = 3
+ENGINE_REVISION = 0
+ENGINE_AGE = 3
 CLEANFILES = 
-EXTRA_DIST = $(am__append_3)
-lib_LTLIBRARIES = libsmltk.la libsynthesis.la libsynthesissdk.la
-nobase_include_HEADERS = synthesis/enginemodulebridge.h synthesis/SDK_util.h synthesis/prefix_file.h synthesis/sync_dbapi.h synthesis/enginemodulebase.h synthesis/SDK_support.h synthesis/stringutil.h synthesis/sync_declarations.h synthesis/sync_dbapidef.h synthesis/generic_types.h synthesis/engine_defs.h synthesis/sync_include.h synthesis/timeutil.h synthesis/dbitem.h synthesis/blobs.h synthesis/sync_uiapi.h synthesis/admindata.h synthesis/dataconversion.h synthesis/syerror.h synthesis/UI_util.h synthesis/target_options.h
+EXTRA_DIST = $(am__append_1)
+lib_LTLIBRARIES = libsmltk.la libsynthesis.la libsynthesissdk.la libsynthesisstubs.la
+nobase_include_HEADERS = synthesis/sysync_b64.h synthesis/enginemodulebridge.h synthesis/SDK_util.h synthesis/prefix_file.h synthesis/sync_dbapi.h synthesis/enginemodulebase.h synthesis/SDK_support.h synthesis/stringutil.h synthesis/sync_declarations.h synthesis/sync_dbapidef.h synthesis/generic_types.h synthesis/engine_defs.h synthesis/sync_include.h synthesis/timeutil.h synthesis/dbitem.h synthesis/san.h synthesis/blobs.h synthesis/sync_uiapi.h synthesis/admindata.h synthesis/dataconversion.h synthesis/sysync_md5.h synthesis/syerror.h synthesis/UI_util.h synthesis/target_options.h
 
 # Configuration header files are searched in this order:
 # - Targets/ReleasedProducts/autotools: files only used when compiling with autotools
-# - Targets/ReleasedProducts/[clientEngine_opensource_linux|SDK]: files also used with Synthesis Linux makefile
+# - Targets/ReleasedProducts/[combiEngine_opensource_linux|serverEngine_opensource_linux|SDK]: files also used with Synthesis Linux makefile
 #
 # Always included first via -include:
 # - config.h: configure result (top directory)
-# - Targets/ReleasedProducts/clientEngine_opensource_linux/clientengine_demo_x86_linux_prefix.h
+# - Targets/ReleasedProducts/combiEngine_opensource_linux/clientengine_demo_x86_linux_prefix.h resp. Targets/ReleasedProducts/serverEngine_opensource_linux/serverengine_opensource_linux_prefix.h
 #
 # Included as needed:
 # - define.h: hard-coded SyncML Toolkit config (from search path above)
-libsynthesis_la_SOURCES = sysync/binfileimplclient.cpp \
-       sysync/syncclientbase.h sysync/sysync_b64.cpp \
-       sysync/sysync_md5.cpp sysync/sysync_b64.h \
-       sysync/syncml_globs.h sysync/stdlogicagent.cpp \
-       sysync/syncappbase.cpp sysync/customimplds.cpp \
-       sysync/syncsession.h sysync/syncclient.cpp sysync/syncitem.cpp \
-       sysync/textitemtype.cpp sysync/textitemtype.h \
-       sysync/localengineds.h sysync/syncexception.cpp \
-       sysync/clientprovisioning_inc.h sysync/global_progress.h \
-       sysync/textprofile.cpp sysync/stringutils.cpp \
-       sysync/customimplagent.cpp sysync/debuglogger.cpp \
-       sysync/vtimezone.cpp sysync/iso8601.h \
-       sysync/vcalendaritemtype.cpp sysync/scriptcontext.h \
-       sysync/syncitemtype.h sysync/smltk_precomp.h \
-       sysync/sysync_globs.h sysync/sysync_debug.h \
-       sysync/syncsessiondispatch.h sysync/san.cpp \
-       sysync/sysync_utils.cpp sysync/mimediritemtype.h \
-       sysync/dataobjtype.cpp sysync/multifielditem.cpp \
-       sysync/sysync_precomp_xpt.h sysync/iso8601.cpp \
-       sysync/syncclientbase.cpp sysync/itemfield.h \
-       sysync/syncserver.h sysync/remotedatastore.h \
-       sysync/engineentry.h sysync/itemfield.cpp sysync/stringutils.h \
-       sysync/lineartime.h sysync/syncml_tk.h \
-       sysync/mimediritemtype.cpp sysync/configelement.h \
-       sysync/clientautosync_inc.cpp sysync/binfilebase.cpp \
-       sysync/synccommand.cpp sysync/mimedirprofile.h \
-       sysync/tz_table.h sysync/binfileimplds.cpp \
-       sysync/sysync_crc16.cpp sysync/simpleitem.h sysync/timezones.h \
-       sysync/sysync_precomp.h sysync/sysync.h \
-       sysync/binfileimplclient.h sysync/syncitem.h \
-       sysync/localengineds.cpp sysync/dataobjtype.h \
-       sysync/customimplagent.h sysync/synccommand.h \
-       sysync/binfilebase.h sysync/textprofile.h \
-       sysync/vcarditemtype.h sysync/binfileimplds.h \
-       sysync/vcalendaritemtype.h sysync/syncexception.h sysync/san.h \
-       sysync/multifielditemtype.cpp sysync/lineartime.cpp \
-       sysync/clientautosync_inc.h sysync/debuglogger.h \
-       sysync/smltk_precomp_xpt.h sysync/syncsession.cpp \
-       sysync/multifielditemtype.h sysync/stdlogicds.h \
-       sysync/rrules.h sysync/remotedatastore.cpp \
-       sysync/engineentry.cpp sysync/simpleitem.cpp \
-       sysync/superdatastore.h sysync/uiapi.h \
-       sysync/vcarditemtype.cpp sysync/engineinterface.cpp \
-       sysync/syncappbase.h sysync/syncclient.h sysync/sysync_crc16.h \
-       sysync/syncdatastore.cpp sysync/multifielditem.h \
-       sysync/scriptcontext.cpp sysync/syncitemtype.cpp \
-       sysync/stdlogicds.cpp sysync/vtimezone.h sysync/uiapi.cpp \
-       sysync/dataconversion.cpp sysync/timezones.cpp \
-       sysync/engineinterface.h sysync/sysync_md5.h \
-       sysync/superdatastore.cpp sysync/sysync_utils.h \
-       sysync/customimplds.h sysync/rrules.cpp \
-       sysync/configelement.cpp sysync/syserial.h \
-       sysync/syncdatastore.h sysync/mimedirprofile.cpp \
-       sysync/stdlogicagent.h DB_interfaces/odbc_db/odbcapids.cpp \
-       DB_interfaces/odbc_db/odbcapiagent.h \
-       DB_interfaces/odbc_db/odbcapiagent.cpp \
-       DB_interfaces/odbc_db/odbcdb_precomp.h \
-       DB_interfaces/odbc_db/odbcapids.h \
-       DB_interfaces/odbc_db/odbcdb.h DB_interfaces/api_db/plugindb.h \
-       DB_interfaces/api_db/dbapi.h \
-       DB_interfaces/api_db/pluginapiagent.cpp \
-       DB_interfaces/api_db/dbapi_include.h \
-       DB_interfaces/api_db/sync_dbapiconnect.h \
-       DB_interfaces/api_db/pluginapiagent.h \
-       DB_interfaces/api_db/sync_dbapiconnect.cpp \
-       DB_interfaces/api_db/pluginapids.cpp \
-       DB_interfaces/api_db/plugindb_precomp.h \
-       DB_interfaces/api_db/dbapi.cpp \
-       DB_interfaces/api_db/DLL_interface.h \
-       DB_interfaces/api_db/DLL_interface.cpp \
-       DB_interfaces/api_db/pluginapids.h \
-       sysync_SDK/Sources/SDK_util.h sysync_SDK/Sources/prefix_file.h \
-       sysync_SDK/Sources/sync_dbapi.h \
-       sysync_SDK/Sources/enginemodulebase.h \
-       sysync_SDK/Sources/SDK_support.h \
-       sysync_SDK/Sources/sync_declarations.h \
-       sysync_SDK/Sources/sync_dbapidef.h \
-       sysync_SDK/Sources/generic_types.h \
-       sysync_SDK/Sources/engine_defs.h \
-       sysync_SDK/Sources/sync_include.h \
-       sysync_SDK/Sources/SDK_support.cpp \
-       sysync_SDK/Sources/SDK_util.c \
-       sysync_SDK/Sources/enginemodulebase.cpp \
-       sysync_SDK/Sources/sync_uiapi.h \
-       sysync_SDK/Sources/dataconversion.h \
-       sysync_SDK/Sources/syerror.h \
-       Transport_interfaces/engine/engine_client_precomp.h \
-       Transport_interfaces/engine/engineclientbase.cpp \
-       Transport_interfaces/engine/engineclientbase.h \
-       Transport_interfaces/engine/engine_client.h \
-       platform_adapters/sysync_glob_vars.h \
-       platform_adapters/configfiles.h platform_adapters/binfile.cpp \
-       platform_adapters/sysyncinit.cpp platform_adapters/profiling.h \
-       platform_adapters/linux/platform_DLL.cpp \
-       platform_adapters/linux/profiling.cpp \
-       platform_adapters/linux/platform_exec.h \
-       platform_adapters/linux/configfiles.cpp \
-       platform_adapters/linux/platform_time.cpp \
-       platform_adapters/linux/platform_exec.c \
-       platform_adapters/linux/platform_headers.h \
-       platform_adapters/linux/platform_timezones.cpp \
-       platform_adapters/linux/platform_time.h \
-       platform_adapters/binfile.h \
-       platform_adapters/platform_thread.h \
-       platform_adapters/platform_DLL.h \
-       platform_adapters/unix_common/platform_pipe.c \
-       platform_adapters/unix_common/platform_file.cpp \
-       platform_adapters/unix_common/platform_thread.cpp \
-       platform_adapters/unix_common/platform_pipe.h \
-       platform_adapters/unix_common/platform_mutex.cpp \
-       platform_adapters/platform_file.h \
-       platform_adapters/platform_headers.h \
-       platform_adapters/platform_mutex.h \
-       syncapps/clientEngine_custom/clientengine_custom_Base.h \
-       syncapps/clientEngine_custom/clientengine_custom_Base.cpp \
-       syncapps/clientEngine_custom/product_options.h \
-       syncapps/clientEngine_custom/clientengine_custom_precomp.h \
-       syncapps/clientEngine_custom/clientengine_custom.h \
-       $(am__append_2)
+libsynthesis_la_SOURCES = sysync/binfileimplclient.cpp sysync/syncclientbase.h sysync/syncagent.cpp sysync/syncml_globs.h sysync/stdlogicagent.cpp sysync/syncappbase.cpp sysync/customimplds.cpp sysync/syncsession.h sysync/syncitem.cpp sysync/textitemtype.cpp sysync/textitemtype.h sysync/localengineds.h sysync/syncexception.cpp sysync/clientprovisioning_inc.h sysync/global_progress.h sysync/textprofile.cpp sysync/stringutils.cpp sysync/customimplagent.cpp sysync/debuglogger.cpp sysync/vtimezone.cpp sysync/iso8601.h sysync/vcalendaritemtype.cpp sysync/scriptcontext.h sysync/syncitemtype.h sysync/smltk_precomp.h sysync/sysync_globs.h sysync/sysync_debug.h sysync/syncsessiondispatch.h sysync/sysync_utils.cpp sysync/mimediritemtype.h sysync/dataobjtype.cpp sysync/multifielditem.cpp sysync/sysync_precomp_xpt.h sysync/iso8601.cpp sysync/syncclientbase.cpp sysync/itemfield.h sysync/remotedatastore.h sysync/engineentry.h sysync/itemfield.cpp sysync/stringutils.h sysync/lineartime.h sysync/syncml_tk.h sysync/mimediritemtype.cpp sysync/configelement.h sysync/clientautosync_inc.cpp sysync/binfilebase.cpp sysync/synccommand.cpp sysync/mimedirprofile.h sysync/tz_table.h sysync/binfileimplds.cpp sysync/sysync_crc16.cpp sysync/simpleitem.h sysync/timezones.h sysync/sysync_precomp.h sysync/sysync.h sysync/binfileimplclient.h sysync/syncitem.h sysync/localengineds.cpp sysync/dataobjtype.h sysync/customimplagent.h sysync/synccommand.h sysync/binfilebase.h sysync/textprofile.h sysync/vcarditemtype.h sysync/binfileimplds.h sysync/vcalendaritemtype.h sysync/syncexception.h sysync/multifielditemtype.cpp sysync/lineartime.cpp sysync/clientautosync_inc.h sysync/debuglogger.h sysync/smltk_precomp_xpt.h sysync/syncsession.cpp sysync/multifielditemtype.h sysync/stdlogicds.h sysync/rrules.h sysync/remotedatastore.cpp sysync/engineentry.cpp sysync/simpleitem.cpp sysync/superdatastore.h sysync/uiapi.h sysync/vcarditemtype.cpp sysync/engineinterface.cpp sysync/syncappbase.h sysync/sysync_crc16.h sysync/syncdatastore.cpp sysync/multifielditem.h sysync/scriptcontext.cpp sysync/syncitemtype.cpp sysync/stdlogicds.cpp sysync/vtimezone.h sysync/uiapi.cpp sysync/syncagent.h sysync/dataconversion.cpp sysync/timezones.cpp sysync/engineinterface.h sysync/superdatastore.cpp sysync/sysync_utils.h sysync/customimplds.h sysync/rrules.cpp sysync/configelement.cpp sysync/syserial.h sysync/syncdatastore.h sysync/mimedirprofile.cpp sysync/stdlogicagent.h DB_interfaces/odbc_db/odbcapids.cpp DB_interfaces/odbc_db/odbcapiagent.h DB_interfaces/odbc_db/odbcapiagent.cpp DB_interfaces/odbc_db/odbcdb_precomp.h DB_interfaces/odbc_db/odbcapids.h DB_interfaces/odbc_db/odbcdb.h DB_interfaces/api_db/plugindb.h DB_interfaces/api_db/dbapi.h DB_interfaces/api_db/pluginapiagent.cpp DB_interfaces/api_db/dbapi_include.h DB_interfaces/api_db/sync_dbapiconnect.h DB_interfaces/api_db/pluginapiagent.h DB_interfaces/api_db/sync_dbapiconnect.cpp DB_interfaces/api_db/pluginapids.cpp DB_interfaces/api_db/plugindb_precomp.h DB_interfaces/api_db/dbapi.cpp DB_interfaces/api_db/DLL_interface.h DB_interfaces/api_db/DLL_interface.cpp DB_interfaces/api_db/pluginapids.h sysync_SDK/Sources/sysync_b64.cpp sysync_SDK/Sources/sysync_md5.cpp sysync_SDK/Sources/sysync_b64.h sysync_SDK/Sources/SDK_util.h sysync_SDK/Sources/prefix_file.h sysync_SDK/Sources/sync_dbapi.h sysync_SDK/Sources/enginemodulebase.h sysync_SDK/Sources/SDK_support.h sysync_SDK/Sources/sync_declarations.h sysync_SDK/Sources/sync_dbapidef.h sysync_SDK/Sources/generic_types.h sysync_SDK/Sources/engine_defs.h sysync_SDK/Sources/sync_include.h sysync_SDK/Sources/SDK_support.cpp sysync_SDK/Sources/SDK_util.c sysync_SDK/Sources/dbitem.h sysync_SDK/Sources/dbitem.cpp sysync_SDK/Sources/blobs.h sysync_SDK/Sources/enginemodulebase.cpp sysync_SDK/Sources/sync_uiapi.h sysync_SDK/Sources/admindata.h sysync_SDK/Sources/dataconversion.h sysync_SDK/Sources/admindata.cpp sysync_SDK/Sources/blobs.cpp sysync_SDK/Sources/sysync_md5.h sysync_SDK/Sources/syerror.h Transport_interfaces/engine/engine_client_precomp.h Transport_interfaces/engine/enginesessiondispatch.h Transport_interfaces/engine/engine_server_precomp.h Transport_interfaces/engine/enginesessiondispatch.cpp Transport_interfaces/engine/engine_server.h Transport_interfaces/engine/engineclientbase.cpp Transport_interfaces/engine/engineclientbase.h Transport_interfaces/engine/engine_client.h platform_adapters/sysync_glob_vars.h platform_adapters/configfiles.h platform_adapters/binfile.cpp platform_adapters/sysyncinit.cpp platform_adapters/profiling.h platform_adapters/linux/platform_DLL.cpp platform_adapters/linux/profiling.cpp platform_adapters/linux/platform_exec.h platform_adapters/linux/configfiles.cpp platform_adapters/linux/platform_time.cpp platform_adapters/linux/platform_exec.c platform_adapters/linux/platform_headers.h platform_adapters/linux/platform_timezones.cpp platform_adapters/linux/platform_time.h platform_adapters/binfile.h platform_adapters/platform_thread.h platform_adapters/platform_DLL.h platform_adapters/unix_common/platform_pipe.c platform_adapters/unix_common/platform_file.cpp platform_adapters/unix_common/platform_pipe.h platform_adapters/unix_common/platform_mutex.cpp platform_adapters/platform_file.h platform_adapters/platform_headers.h platform_adapters/platform_mutex.h syncapps/clientEngine_custom/clientengine_custom_Base.h syncapps/clientEngine_custom/clientengine_custom_Base.cpp syncapps/clientEngine_custom/product_options.h syncapps/clientEngine_custom/clientengine_custom_precomp.h syncapps/clientEngine_custom/clientengine_custom.h syncapps/serverEngine_custom/serverengine_custom.h syncapps/serverEngine_custom/serverengine_custom_Base.cpp syncapps/serverEngine_custom/serverengine_custom_Base.h syncapps/serverEngine_custom/combi_product_options.h syncapps/serverEngine_custom/product_options.h syncapps/serverEngine_custom/serverengine_custom_precomp.h sysync_SDK/DB_Interfaces/text_db/sync_dbapi_text.cpp \
+       $(XMLPARSE_SOURCES)
+
 libsynthesis_la_CPPFLAGS = -I$(srcdir)/sysync_SDK/Sources
-LIBSYNTHESIS_CFLAGS = -include $(top_builddir)/config.h -include \
-       $(srcdir)/Targets/ReleasedProducts/clientEngine_opensource_linux/clientengine_demo_x86_linux_prefix.h \
+libsynthesis_la_CFLAGS = \
+       -include $(top_builddir)/config.h \
+       -include $(srcdir)/Targets/ReleasedProducts/combiEngine_opensource_linux/combiengine_opensource_linux_prefix.h \
        -I$(srcdir)/Targets/ReleasedProducts/clientEngine_autotools/ \
-       -I$(srcdir)/Targets/ReleasedProducts/clientEngine_opensource_linux/ \
+       -I$(srcdir)/Targets/ReleasedProducts/combiEngine_opensource_linux/ \
        -I$(srcdir)/platform_adapters/linux/ \
        -I$(srcdir)/platform_adapters/unix_common/ \
        -I$(srcdir)/platform_adapters/ \
-       -I$(srcdir)/syncapps/clientEngine_custom/ -I$(srcdir)/sysync/ \
-       -I$(srcdir)/Transport_interfaces/engine/ -I$(srcdir)/ \
+       -I$(srcdir)/syncapps/clientEngine_custom/ \
+       -I$(srcdir)/syncapps/serverEngine_custom/ \
+       -I$(srcdir)/sysync/ \
+       -I$(srcdir)/Transport_interfaces/engine/ \
+       -I$(srcdir)/ \
        -I$(srcdir)/syncml_tk/src/sml/inc/ \
        -I$(srcdir)/syncml_tk/src/sml/lib/inc/ \
        -I$(srcdir)/syncml_tk/src/sml/lib/ \
@@ -623,50 +530,61 @@ LIBSYNTHESIS_CFLAGS = -include $(top_builddir)/config.h -include \
        -I$(srcdir)/syncml_tk/src/sml/xlt/all \
        -I$(srcdir)/DB_interfaces/odbc_db/ \
        -I$(srcdir)/DB_interfaces/api_db/ \
-       -I$(srcdir)/sysync_SDK/Sources/ $(PCRE_CFLAGS) \
-       $(SQLITE3_CFLAGS) $(ZLIB_CFLAGS) $(XMLPARSE_CFLAGS) \
-       $(LIBICAL_CFLAGS) $(LIBECAL_CFLAGS) $(am__append_1) \
-       $(am__append_4)
-libsynthesis_la_CFLAGS = $(LIBSYNTHESIS_CFLAGS)
-libsynthesis_la_CXXFLAGS = $(LIBSYNTHESIS_CFLAGS)
+       -I$(srcdir)/sysync_SDK/Sources/ \
+       $(PCRE_CFLAGS) \
+       $(SQLITE3_CFLAGS) \
+       $(ZLIB_CFLAGS) \
+       $(XMLPARSE_CFLAGS) \
+       $(XMLPARSE_CFLAGS_BUILTIN) \
+       $(LIBICAL_CFLAGS) \
+       $(LIBECAL_CFLAGS)
+
+libsynthesis_la_CXXFLAGS = $(libsynthesis_la_CFLAGS)
 libsynthesis_la_LIBADD = $(PCRE_LIBS) $(SQLITE3_LIBS) $(XMLPARSE_LIBS) $(LIBICAL_LIBS) $(LIBECAL_LIBS) libsmltk.la -lz
-
-# versioning:
-# CURRENT - most recent interface version
-# REVISION - minor version number of that interface implementation
-# AGE - number of previous interface versions supported in addition
-#       to the current one
-#
-# When adding to the interface, increment CURRENT and AGE and reset
-# REVISION to zero. When breaking the interface in a backwards
-# incompatible way, increment CURRENT and reset AGE and REVISION to
-# zero. When fixing something without interface change, increment
-# REVISION.
-ENGINE_CURRENT = 2
-ENGINE_REVISION = 0
-ENGINE_AGE = 2
 libsynthesis_la_LDFLAGS = -version-info $(ENGINE_CURRENT):$(ENGINE_REVISION):$(ENGINE_AGE) \
        -Wl,--version-script=$(srcdir)/synthesis-linker.map
 
 libsynthesis_la_DEPENDENCIES = $(srcdir)/synthesis-linker.map libsmltk.la
-libsynthesissdk_la_LIBADD = libsynthesis.la
+# add path to xmlparse.h which includes the system's xmltok/xmlparse.h
+@COND_XMLPARSE_FALSE@XMLPARSE_CFLAGS_BUILTIN = -I$(srcdir)/Targets/ReleasedProducts/clientEngine_autotools/systemxml
+@COND_XMLPARSE_TRUE@XMLPARSE_CFLAGS_BUILTIN = -I$(srcdir)/expat -I$(srcdir)/expat/xmltok -I$(srcdir)/expat/xmlparse
+@COND_XMLPARSE_TRUE@XMLPARSE_SOURCES = \
+@COND_XMLPARSE_TRUE@   expat/xmlparse/xmlparse.c \
+@COND_XMLPARSE_TRUE@   expat/xmlparse/xmlparse.h \
+@COND_XMLPARSE_TRUE@   expat/xmltok/ascii.h \
+@COND_XMLPARSE_TRUE@   expat/xmltok/asciitab.h \
+@COND_XMLPARSE_TRUE@   expat/xmltok/iasciitab.h \
+@COND_XMLPARSE_TRUE@   expat/xmltok/latin1tab.h \
+@COND_XMLPARSE_TRUE@   expat/xmltok/nametab.h \
+@COND_XMLPARSE_TRUE@   expat/xmltok/utf8tab.h \
+@COND_XMLPARSE_TRUE@   expat/xmltok/xmldef.h \
+@COND_XMLPARSE_TRUE@   expat/xmltok/xmlrole.c \
+@COND_XMLPARSE_TRUE@   expat/xmltok/xmlrole.h \
+@COND_XMLPARSE_TRUE@   expat/xmltok/xmltok.c \
+@COND_XMLPARSE_TRUE@   expat/xmltok/xmltok.h \
+@COND_XMLPARSE_TRUE@   expat/xmltok/xmltok_impl.h
+
 libsynthesissdk_la_LDFLAGS = -static
-libsynthesissdk_la_SOURCES = synthesis/enginemodulebridge.h \
-       synthesis/SDK_util.h synthesis/prefix_file.h \
-       synthesis/sync_dbapi.h synthesis/enginemodulebase.h \
-       synthesis/SDK_support.h synthesis/stringutil.h \
-       synthesis/sync_declarations.h synthesis/sync_dbapidef.h \
-       synthesis/generic_types.h synthesis/engine_defs.h \
-       synthesis/sync_include.h synthesis/timeutil.h \
-       synthesis/dbitem.h synthesis/blobs.h synthesis/sync_uiapi.h \
-       synthesis/admindata.h synthesis/dataconversion.h \
-       synthesis/syerror.h synthesis/UI_util.h $(am__append_5) \
-       $(am__append_6)
+libsynthesissdk_la_SOURCES = synthesis/sysync_b64.h \
+       synthesis/enginemodulebridge.h synthesis/SDK_util.h \
+       synthesis/prefix_file.h synthesis/sync_dbapi.h \
+       synthesis/enginemodulebase.h synthesis/SDK_support.h \
+       synthesis/stringutil.h synthesis/sync_declarations.h \
+       synthesis/sync_dbapidef.h synthesis/generic_types.h \
+       synthesis/engine_defs.h synthesis/sync_include.h \
+       synthesis/timeutil.h synthesis/dbitem.h synthesis/san.h \
+       synthesis/blobs.h synthesis/sync_uiapi.h synthesis/admindata.h \
+       synthesis/dataconversion.h synthesis/sysync_md5.h \
+       synthesis/syerror.h synthesis/UI_util.h $(am__append_2) \
+       $(am__append_3)
 libsynthesissdk_la_CPPFLAGS = \
        -D_GNU_SOURCE=1 \
        -I$(srcdir)/sysync_SDK/Sources \
        -I$(srcdir)/Targets/ReleasedProducts/SDK
 
+libsynthesisstubs_la_LDFLAGS = -static
+libsynthesisstubs_la_SOURCES = sysync_SDK/Sources/enginestubs.c
+libsynthesisstubs_la_CPPFLAGS = $(libsynthesissdk_la_CPPFLAGS)
 
 # libsmltk: compiled just like libsynthesis
 libsmltk_la_SOURCES = syncml_tk/src/sml/inc/smlmetinfdtd.h \
@@ -715,8 +633,8 @@ libsmltk_la_SOURCES = syncml_tk/src/sml/inc/smlmetinfdtd.h \
        syncml_tk/src/sml/xlt/all/xlttagtbl.h \
        syncml_tk/src/sml/xlt/all/xltdec.c \
        syncml_tk/src/sml/xlt/all/xltdevinf.h
-libsmltk_la_CFLAGS = $(LIBSYNTHESIS_CFLAGS)
-libsmltk_la_CXXFLAGS = $(LIBSYNTHESIS_CFLAGS)
+libsmltk_la_CFLAGS = $(libsynthesis_la_CFLAGS)
+libsmltk_la_CXXFLAGS = $(libsmltk_la_CFLAGS)
 
 # versioning: same as of engine! changes in libsmltk are not tracked separately.
 libsmltk_la_LDFLAGS = -version-info $(ENGINE_CURRENT):$(ENGINE_REVISION):$(ENGINE_AGE) \
@@ -789,6 +707,8 @@ libsynthesis.la: $(libsynthesis_la_OBJECTS) $(libsynthesis_la_DEPENDENCIES)
        $(libsynthesis_la_LINK) -rpath $(libdir) $(libsynthesis_la_OBJECTS) $(libsynthesis_la_LIBADD) $(LIBS)
 libsynthesissdk.la: $(libsynthesissdk_la_OBJECTS) $(libsynthesissdk_la_DEPENDENCIES) 
        $(libsynthesissdk_la_LINK) -rpath $(libdir) $(libsynthesissdk_la_OBJECTS) $(libsynthesissdk_la_LIBADD) $(LIBS)
+libsynthesisstubs.la: $(libsynthesisstubs_la_OBJECTS) $(libsynthesisstubs_la_DEPENDENCIES) 
+       $(libsynthesisstubs_la_LINK) -rpath $(libdir) $(libsynthesisstubs_la_OBJECTS) $(libsynthesisstubs_la_LIBADD) $(LIBS)
 
 mostlyclean-compile:
        -rm -f *.$(OBJEXT)
@@ -821,10 +741,12 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-DLL_interface.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-SDK_support.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-SDK_util.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-admindata.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-binfile.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-binfilebase.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-binfileimplclient.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-binfileimplds.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-blobs.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-clientautosync_inc.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-clientengine_custom_Base.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-configelement.Plo@am__quote@
@@ -834,11 +756,13 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-dataconversion.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-dataobjtype.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-dbapi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-dbitem.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-debuglogger.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-engineclientbase.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-engineentry.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-engineinterface.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-enginemodulebase.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-enginesessiondispatch.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-iso8601.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-itemfield.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-lineartime.Plo@am__quote@
@@ -854,7 +778,6 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-platform_file.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-platform_mutex.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-platform_pipe.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-platform_thread.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-platform_time.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-platform_timezones.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-pluginapiagent.Plo@am__quote@
@@ -862,16 +785,17 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-profiling.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-remotedatastore.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-rrules.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-san.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-scriptcontext.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-serverengine_custom_Base.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-simpleitem.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-stdlogicagent.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-stdlogicds.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-stringutils.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-superdatastore.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-sync_dbapi_text.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-sync_dbapiconnect.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-syncagent.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-syncappbase.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-syncclient.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-syncclientbase.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-synccommand.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesis_la-syncdatastore.Plo@am__quote@
@@ -897,13 +821,14 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesissdk_la-SDK_support.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesissdk_la-SDK_util.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesissdk_la-UI_util.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesissdk_la-admindata.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesissdk_la-blobs.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesissdk_la-dbitem.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesissdk_la-enginemodulebase.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesissdk_la-enginemodulebridge.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesissdk_la-san.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesissdk_la-stringutil.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesissdk_la-sysync_b64.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesissdk_la-sysync_md5.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesissdk_la-timeutil.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsynthesisstubs_la-enginestubs.Plo@am__quote@
 
 .c.o:
 @am__fastdepCC_TRUE@   $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@@ -1129,6 +1054,13 @@ libsynthesissdk_la-SDK_util.lo: sysync_SDK/Sources/SDK_util.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@  $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesissdk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsynthesissdk_la-SDK_util.lo `test -f 'sysync_SDK/Sources/SDK_util.c' || echo '$(srcdir)/'`sysync_SDK/Sources/SDK_util.c
 
+libsynthesisstubs_la-enginestubs.lo: sysync_SDK/Sources/enginestubs.c
+@am__fastdepCC_TRUE@   $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesisstubs_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsynthesisstubs_la-enginestubs.lo -MD -MP -MF $(DEPDIR)/libsynthesisstubs_la-enginestubs.Tpo -c -o libsynthesisstubs_la-enginestubs.lo `test -f 'sysync_SDK/Sources/enginestubs.c' || echo '$(srcdir)/'`sysync_SDK/Sources/enginestubs.c
+@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/libsynthesisstubs_la-enginestubs.Tpo $(DEPDIR)/libsynthesisstubs_la-enginestubs.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='sysync_SDK/Sources/enginestubs.c' object='libsynthesisstubs_la-enginestubs.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesisstubs_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsynthesisstubs_la-enginestubs.lo `test -f 'sysync_SDK/Sources/enginestubs.c' || echo '$(srcdir)/'`sysync_SDK/Sources/enginestubs.c
+
 .cpp.o:
 @am__fastdepCXX_TRUE@  $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
 @am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@@ -1157,19 +1089,12 @@ libsynthesis_la-binfileimplclient.lo: sysync/binfileimplclient.cpp
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -c -o libsynthesis_la-binfileimplclient.lo `test -f 'sysync/binfileimplclient.cpp' || echo '$(srcdir)/'`sysync/binfileimplclient.cpp
 
-libsynthesis_la-sysync_b64.lo: sysync/sysync_b64.cpp
-@am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -MT libsynthesis_la-sysync_b64.lo -MD -MP -MF $(DEPDIR)/libsynthesis_la-sysync_b64.Tpo -c -o libsynthesis_la-sysync_b64.lo `test -f 'sysync/sysync_b64.cpp' || echo '$(srcdir)/'`sysync/sysync_b64.cpp
-@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/libsynthesis_la-sysync_b64.Tpo $(DEPDIR)/libsynthesis_la-sysync_b64.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='sysync/sysync_b64.cpp' object='libsynthesis_la-sysync_b64.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -c -o libsynthesis_la-sysync_b64.lo `test -f 'sysync/sysync_b64.cpp' || echo '$(srcdir)/'`sysync/sysync_b64.cpp
-
-libsynthesis_la-sysync_md5.lo: sysync/sysync_md5.cpp
-@am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -MT libsynthesis_la-sysync_md5.lo -MD -MP -MF $(DEPDIR)/libsynthesis_la-sysync_md5.Tpo -c -o libsynthesis_la-sysync_md5.lo `test -f 'sysync/sysync_md5.cpp' || echo '$(srcdir)/'`sysync/sysync_md5.cpp
-@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/libsynthesis_la-sysync_md5.Tpo $(DEPDIR)/libsynthesis_la-sysync_md5.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='sysync/sysync_md5.cpp' object='libsynthesis_la-sysync_md5.lo' libtool=yes @AMDEPBACKSLASH@
+libsynthesis_la-syncagent.lo: sysync/syncagent.cpp
+@am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -MT libsynthesis_la-syncagent.lo -MD -MP -MF $(DEPDIR)/libsynthesis_la-syncagent.Tpo -c -o libsynthesis_la-syncagent.lo `test -f 'sysync/syncagent.cpp' || echo '$(srcdir)/'`sysync/syncagent.cpp
+@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/libsynthesis_la-syncagent.Tpo $(DEPDIR)/libsynthesis_la-syncagent.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='sysync/syncagent.cpp' object='libsynthesis_la-syncagent.lo' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -c -o libsynthesis_la-sysync_md5.lo `test -f 'sysync/sysync_md5.cpp' || echo '$(srcdir)/'`sysync/sysync_md5.cpp
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -c -o libsynthesis_la-syncagent.lo `test -f 'sysync/syncagent.cpp' || echo '$(srcdir)/'`sysync/syncagent.cpp
 
 libsynthesis_la-stdlogicagent.lo: sysync/stdlogicagent.cpp
 @am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -MT libsynthesis_la-stdlogicagent.lo -MD -MP -MF $(DEPDIR)/libsynthesis_la-stdlogicagent.Tpo -c -o libsynthesis_la-stdlogicagent.lo `test -f 'sysync/stdlogicagent.cpp' || echo '$(srcdir)/'`sysync/stdlogicagent.cpp
@@ -1192,13 +1117,6 @@ libsynthesis_la-customimplds.lo: sysync/customimplds.cpp
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -c -o libsynthesis_la-customimplds.lo `test -f 'sysync/customimplds.cpp' || echo '$(srcdir)/'`sysync/customimplds.cpp
 
-libsynthesis_la-syncclient.lo: sysync/syncclient.cpp
-@am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -MT libsynthesis_la-syncclient.lo -MD -MP -MF $(DEPDIR)/libsynthesis_la-syncclient.Tpo -c -o libsynthesis_la-syncclient.lo `test -f 'sysync/syncclient.cpp' || echo '$(srcdir)/'`sysync/syncclient.cpp
-@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/libsynthesis_la-syncclient.Tpo $(DEPDIR)/libsynthesis_la-syncclient.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='sysync/syncclient.cpp' object='libsynthesis_la-syncclient.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -c -o libsynthesis_la-syncclient.lo `test -f 'sysync/syncclient.cpp' || echo '$(srcdir)/'`sysync/syncclient.cpp
-
 libsynthesis_la-syncitem.lo: sysync/syncitem.cpp
 @am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -MT libsynthesis_la-syncitem.lo -MD -MP -MF $(DEPDIR)/libsynthesis_la-syncitem.Tpo -c -o libsynthesis_la-syncitem.lo `test -f 'sysync/syncitem.cpp' || echo '$(srcdir)/'`sysync/syncitem.cpp
 @am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/libsynthesis_la-syncitem.Tpo $(DEPDIR)/libsynthesis_la-syncitem.Plo
@@ -1262,13 +1180,6 @@ libsynthesis_la-vcalendaritemtype.lo: sysync/vcalendaritemtype.cpp
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -c -o libsynthesis_la-vcalendaritemtype.lo `test -f 'sysync/vcalendaritemtype.cpp' || echo '$(srcdir)/'`sysync/vcalendaritemtype.cpp
 
-libsynthesis_la-san.lo: sysync/san.cpp
-@am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -MT libsynthesis_la-san.lo -MD -MP -MF $(DEPDIR)/libsynthesis_la-san.Tpo -c -o libsynthesis_la-san.lo `test -f 'sysync/san.cpp' || echo '$(srcdir)/'`sysync/san.cpp
-@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/libsynthesis_la-san.Tpo $(DEPDIR)/libsynthesis_la-san.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='sysync/san.cpp' object='libsynthesis_la-san.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -c -o libsynthesis_la-san.lo `test -f 'sysync/san.cpp' || echo '$(srcdir)/'`sysync/san.cpp
-
 libsynthesis_la-sysync_utils.lo: sysync/sysync_utils.cpp
 @am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -MT libsynthesis_la-sysync_utils.lo -MD -MP -MF $(DEPDIR)/libsynthesis_la-sysync_utils.Tpo -c -o libsynthesis_la-sysync_utils.lo `test -f 'sysync/sysync_utils.cpp' || echo '$(srcdir)/'`sysync/sysync_utils.cpp
 @am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/libsynthesis_la-sysync_utils.Tpo $(DEPDIR)/libsynthesis_la-sysync_utils.Plo
@@ -1542,6 +1453,20 @@ libsynthesis_la-DLL_interface.lo: DB_interfaces/api_db/DLL_interface.cpp
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -c -o libsynthesis_la-DLL_interface.lo `test -f 'DB_interfaces/api_db/DLL_interface.cpp' || echo '$(srcdir)/'`DB_interfaces/api_db/DLL_interface.cpp
 
+libsynthesis_la-sysync_b64.lo: sysync_SDK/Sources/sysync_b64.cpp
+@am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -MT libsynthesis_la-sysync_b64.lo -MD -MP -MF $(DEPDIR)/libsynthesis_la-sysync_b64.Tpo -c -o libsynthesis_la-sysync_b64.lo `test -f 'sysync_SDK/Sources/sysync_b64.cpp' || echo '$(srcdir)/'`sysync_SDK/Sources/sysync_b64.cpp
+@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/libsynthesis_la-sysync_b64.Tpo $(DEPDIR)/libsynthesis_la-sysync_b64.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='sysync_SDK/Sources/sysync_b64.cpp' object='libsynthesis_la-sysync_b64.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -c -o libsynthesis_la-sysync_b64.lo `test -f 'sysync_SDK/Sources/sysync_b64.cpp' || echo '$(srcdir)/'`sysync_SDK/Sources/sysync_b64.cpp
+
+libsynthesis_la-sysync_md5.lo: sysync_SDK/Sources/sysync_md5.cpp
+@am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -MT libsynthesis_la-sysync_md5.lo -MD -MP -MF $(DEPDIR)/libsynthesis_la-sysync_md5.Tpo -c -o libsynthesis_la-sysync_md5.lo `test -f 'sysync_SDK/Sources/sysync_md5.cpp' || echo '$(srcdir)/'`sysync_SDK/Sources/sysync_md5.cpp
+@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/libsynthesis_la-sysync_md5.Tpo $(DEPDIR)/libsynthesis_la-sysync_md5.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='sysync_SDK/Sources/sysync_md5.cpp' object='libsynthesis_la-sysync_md5.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -c -o libsynthesis_la-sysync_md5.lo `test -f 'sysync_SDK/Sources/sysync_md5.cpp' || echo '$(srcdir)/'`sysync_SDK/Sources/sysync_md5.cpp
+
 libsynthesis_la-SDK_support.lo: sysync_SDK/Sources/SDK_support.cpp
 @am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -MT libsynthesis_la-SDK_support.lo -MD -MP -MF $(DEPDIR)/libsynthesis_la-SDK_support.Tpo -c -o libsynthesis_la-SDK_support.lo `test -f 'sysync_SDK/Sources/SDK_support.cpp' || echo '$(srcdir)/'`sysync_SDK/Sources/SDK_support.cpp
 @am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/libsynthesis_la-SDK_support.Tpo $(DEPDIR)/libsynthesis_la-SDK_support.Plo
@@ -1549,6 +1474,13 @@ libsynthesis_la-SDK_support.lo: sysync_SDK/Sources/SDK_support.cpp
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -c -o libsynthesis_la-SDK_support.lo `test -f 'sysync_SDK/Sources/SDK_support.cpp' || echo '$(srcdir)/'`sysync_SDK/Sources/SDK_support.cpp
 
+libsynthesis_la-dbitem.lo: sysync_SDK/Sources/dbitem.cpp
+@am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -MT libsynthesis_la-dbitem.lo -MD -MP -MF $(DEPDIR)/libsynthesis_la-dbitem.Tpo -c -o libsynthesis_la-dbitem.lo `test -f 'sysync_SDK/Sources/dbitem.cpp' || echo '$(srcdir)/'`sysync_SDK/Sources/dbitem.cpp
+@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/libsynthesis_la-dbitem.Tpo $(DEPDIR)/libsynthesis_la-dbitem.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='sysync_SDK/Sources/dbitem.cpp' object='libsynthesis_la-dbitem.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -c -o libsynthesis_la-dbitem.lo `test -f 'sysync_SDK/Sources/dbitem.cpp' || echo '$(srcdir)/'`sysync_SDK/Sources/dbitem.cpp
+
 libsynthesis_la-enginemodulebase.lo: sysync_SDK/Sources/enginemodulebase.cpp
 @am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -MT libsynthesis_la-enginemodulebase.lo -MD -MP -MF $(DEPDIR)/libsynthesis_la-enginemodulebase.Tpo -c -o libsynthesis_la-enginemodulebase.lo `test -f 'sysync_SDK/Sources/enginemodulebase.cpp' || echo '$(srcdir)/'`sysync_SDK/Sources/enginemodulebase.cpp
 @am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/libsynthesis_la-enginemodulebase.Tpo $(DEPDIR)/libsynthesis_la-enginemodulebase.Plo
@@ -1556,6 +1488,27 @@ libsynthesis_la-enginemodulebase.lo: sysync_SDK/Sources/enginemodulebase.cpp
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -c -o libsynthesis_la-enginemodulebase.lo `test -f 'sysync_SDK/Sources/enginemodulebase.cpp' || echo '$(srcdir)/'`sysync_SDK/Sources/enginemodulebase.cpp
 
+libsynthesis_la-admindata.lo: sysync_SDK/Sources/admindata.cpp
+@am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -MT libsynthesis_la-admindata.lo -MD -MP -MF $(DEPDIR)/libsynthesis_la-admindata.Tpo -c -o libsynthesis_la-admindata.lo `test -f 'sysync_SDK/Sources/admindata.cpp' || echo '$(srcdir)/'`sysync_SDK/Sources/admindata.cpp
+@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/libsynthesis_la-admindata.Tpo $(DEPDIR)/libsynthesis_la-admindata.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='sysync_SDK/Sources/admindata.cpp' object='libsynthesis_la-admindata.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -c -o libsynthesis_la-admindata.lo `test -f 'sysync_SDK/Sources/admindata.cpp' || echo '$(srcdir)/'`sysync_SDK/Sources/admindata.cpp
+
+libsynthesis_la-blobs.lo: sysync_SDK/Sources/blobs.cpp
+@am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -MT libsynthesis_la-blobs.lo -MD -MP -MF $(DEPDIR)/libsynthesis_la-blobs.Tpo -c -o libsynthesis_la-blobs.lo `test -f 'sysync_SDK/Sources/blobs.cpp' || echo '$(srcdir)/'`sysync_SDK/Sources/blobs.cpp
+@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/libsynthesis_la-blobs.Tpo $(DEPDIR)/libsynthesis_la-blobs.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='sysync_SDK/Sources/blobs.cpp' object='libsynthesis_la-blobs.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -c -o libsynthesis_la-blobs.lo `test -f 'sysync_SDK/Sources/blobs.cpp' || echo '$(srcdir)/'`sysync_SDK/Sources/blobs.cpp
+
+libsynthesis_la-enginesessiondispatch.lo: Transport_interfaces/engine/enginesessiondispatch.cpp
+@am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -MT libsynthesis_la-enginesessiondispatch.lo -MD -MP -MF $(DEPDIR)/libsynthesis_la-enginesessiondispatch.Tpo -c -o libsynthesis_la-enginesessiondispatch.lo `test -f 'Transport_interfaces/engine/enginesessiondispatch.cpp' || echo '$(srcdir)/'`Transport_interfaces/engine/enginesessiondispatch.cpp
+@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/libsynthesis_la-enginesessiondispatch.Tpo $(DEPDIR)/libsynthesis_la-enginesessiondispatch.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='Transport_interfaces/engine/enginesessiondispatch.cpp' object='libsynthesis_la-enginesessiondispatch.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -c -o libsynthesis_la-enginesessiondispatch.lo `test -f 'Transport_interfaces/engine/enginesessiondispatch.cpp' || echo '$(srcdir)/'`Transport_interfaces/engine/enginesessiondispatch.cpp
+
 libsynthesis_la-engineclientbase.lo: Transport_interfaces/engine/engineclientbase.cpp
 @am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -MT libsynthesis_la-engineclientbase.lo -MD -MP -MF $(DEPDIR)/libsynthesis_la-engineclientbase.Tpo -c -o libsynthesis_la-engineclientbase.lo `test -f 'Transport_interfaces/engine/engineclientbase.cpp' || echo '$(srcdir)/'`Transport_interfaces/engine/engineclientbase.cpp
 @am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/libsynthesis_la-engineclientbase.Tpo $(DEPDIR)/libsynthesis_la-engineclientbase.Plo
@@ -1619,13 +1572,6 @@ libsynthesis_la-platform_file.lo: platform_adapters/unix_common/platform_file.cp
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -c -o libsynthesis_la-platform_file.lo `test -f 'platform_adapters/unix_common/platform_file.cpp' || echo '$(srcdir)/'`platform_adapters/unix_common/platform_file.cpp
 
-libsynthesis_la-platform_thread.lo: platform_adapters/unix_common/platform_thread.cpp
-@am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -MT libsynthesis_la-platform_thread.lo -MD -MP -MF $(DEPDIR)/libsynthesis_la-platform_thread.Tpo -c -o libsynthesis_la-platform_thread.lo `test -f 'platform_adapters/unix_common/platform_thread.cpp' || echo '$(srcdir)/'`platform_adapters/unix_common/platform_thread.cpp
-@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/libsynthesis_la-platform_thread.Tpo $(DEPDIR)/libsynthesis_la-platform_thread.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='platform_adapters/unix_common/platform_thread.cpp' object='libsynthesis_la-platform_thread.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -c -o libsynthesis_la-platform_thread.lo `test -f 'platform_adapters/unix_common/platform_thread.cpp' || echo '$(srcdir)/'`platform_adapters/unix_common/platform_thread.cpp
-
 libsynthesis_la-platform_mutex.lo: platform_adapters/unix_common/platform_mutex.cpp
 @am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -MT libsynthesis_la-platform_mutex.lo -MD -MP -MF $(DEPDIR)/libsynthesis_la-platform_mutex.Tpo -c -o libsynthesis_la-platform_mutex.lo `test -f 'platform_adapters/unix_common/platform_mutex.cpp' || echo '$(srcdir)/'`platform_adapters/unix_common/platform_mutex.cpp
 @am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/libsynthesis_la-platform_mutex.Tpo $(DEPDIR)/libsynthesis_la-platform_mutex.Plo
@@ -1640,6 +1586,20 @@ libsynthesis_la-clientengine_custom_Base.lo: syncapps/clientEngine_custom/client
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -c -o libsynthesis_la-clientengine_custom_Base.lo `test -f 'syncapps/clientEngine_custom/clientengine_custom_Base.cpp' || echo '$(srcdir)/'`syncapps/clientEngine_custom/clientengine_custom_Base.cpp
 
+libsynthesis_la-serverengine_custom_Base.lo: syncapps/serverEngine_custom/serverengine_custom_Base.cpp
+@am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -MT libsynthesis_la-serverengine_custom_Base.lo -MD -MP -MF $(DEPDIR)/libsynthesis_la-serverengine_custom_Base.Tpo -c -o libsynthesis_la-serverengine_custom_Base.lo `test -f 'syncapps/serverEngine_custom/serverengine_custom_Base.cpp' || echo '$(srcdir)/'`syncapps/serverEngine_custom/serverengine_custom_Base.cpp
+@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/libsynthesis_la-serverengine_custom_Base.Tpo $(DEPDIR)/libsynthesis_la-serverengine_custom_Base.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='syncapps/serverEngine_custom/serverengine_custom_Base.cpp' object='libsynthesis_la-serverengine_custom_Base.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -c -o libsynthesis_la-serverengine_custom_Base.lo `test -f 'syncapps/serverEngine_custom/serverengine_custom_Base.cpp' || echo '$(srcdir)/'`syncapps/serverEngine_custom/serverengine_custom_Base.cpp
+
+libsynthesis_la-sync_dbapi_text.lo: sysync_SDK/DB_Interfaces/text_db/sync_dbapi_text.cpp
+@am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -MT libsynthesis_la-sync_dbapi_text.lo -MD -MP -MF $(DEPDIR)/libsynthesis_la-sync_dbapi_text.Tpo -c -o libsynthesis_la-sync_dbapi_text.lo `test -f 'sysync_SDK/DB_Interfaces/text_db/sync_dbapi_text.cpp' || echo '$(srcdir)/'`sysync_SDK/DB_Interfaces/text_db/sync_dbapi_text.cpp
+@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/libsynthesis_la-sync_dbapi_text.Tpo $(DEPDIR)/libsynthesis_la-sync_dbapi_text.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='sysync_SDK/DB_Interfaces/text_db/sync_dbapi_text.cpp' object='libsynthesis_la-sync_dbapi_text.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesis_la_CPPFLAGS) $(CPPFLAGS) $(libsynthesis_la_CXXFLAGS) $(CXXFLAGS) -c -o libsynthesis_la-sync_dbapi_text.lo `test -f 'sysync_SDK/DB_Interfaces/text_db/sync_dbapi_text.cpp' || echo '$(srcdir)/'`sysync_SDK/DB_Interfaces/text_db/sync_dbapi_text.cpp
+
 libsynthesissdk_la-timeutil.lo: sysync_SDK/Sources/timeutil.cpp
 @am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesissdk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libsynthesissdk_la-timeutil.lo -MD -MP -MF $(DEPDIR)/libsynthesissdk_la-timeutil.Tpo -c -o libsynthesissdk_la-timeutil.lo `test -f 'sysync_SDK/Sources/timeutil.cpp' || echo '$(srcdir)/'`sysync_SDK/Sources/timeutil.cpp
 @am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/libsynthesissdk_la-timeutil.Tpo $(DEPDIR)/libsynthesissdk_la-timeutil.Plo
@@ -1647,6 +1607,13 @@ libsynthesissdk_la-timeutil.lo: sysync_SDK/Sources/timeutil.cpp
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesissdk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libsynthesissdk_la-timeutil.lo `test -f 'sysync_SDK/Sources/timeutil.cpp' || echo '$(srcdir)/'`sysync_SDK/Sources/timeutil.cpp
 
+libsynthesissdk_la-san.lo: sysync_SDK/Sources/san.cpp
+@am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesissdk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libsynthesissdk_la-san.lo -MD -MP -MF $(DEPDIR)/libsynthesissdk_la-san.Tpo -c -o libsynthesissdk_la-san.lo `test -f 'sysync_SDK/Sources/san.cpp' || echo '$(srcdir)/'`sysync_SDK/Sources/san.cpp
+@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/libsynthesissdk_la-san.Tpo $(DEPDIR)/libsynthesissdk_la-san.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='sysync_SDK/Sources/san.cpp' object='libsynthesissdk_la-san.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesissdk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libsynthesissdk_la-san.lo `test -f 'sysync_SDK/Sources/san.cpp' || echo '$(srcdir)/'`sysync_SDK/Sources/san.cpp
+
 libsynthesissdk_la-enginemodulebridge.lo: sysync_SDK/Sources/enginemodulebridge.cpp
 @am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesissdk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libsynthesissdk_la-enginemodulebridge.lo -MD -MP -MF $(DEPDIR)/libsynthesissdk_la-enginemodulebridge.Tpo -c -o libsynthesissdk_la-enginemodulebridge.lo `test -f 'sysync_SDK/Sources/enginemodulebridge.cpp' || echo '$(srcdir)/'`sysync_SDK/Sources/enginemodulebridge.cpp
 @am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/libsynthesissdk_la-enginemodulebridge.Tpo $(DEPDIR)/libsynthesissdk_la-enginemodulebridge.Plo
@@ -1654,13 +1621,6 @@ libsynthesissdk_la-enginemodulebridge.lo: sysync_SDK/Sources/enginemodulebridge.
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesissdk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libsynthesissdk_la-enginemodulebridge.lo `test -f 'sysync_SDK/Sources/enginemodulebridge.cpp' || echo '$(srcdir)/'`sysync_SDK/Sources/enginemodulebridge.cpp
 
-libsynthesissdk_la-dbitem.lo: sysync_SDK/Sources/dbitem.cpp
-@am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesissdk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libsynthesissdk_la-dbitem.lo -MD -MP -MF $(DEPDIR)/libsynthesissdk_la-dbitem.Tpo -c -o libsynthesissdk_la-dbitem.lo `test -f 'sysync_SDK/Sources/dbitem.cpp' || echo '$(srcdir)/'`sysync_SDK/Sources/dbitem.cpp
-@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/libsynthesissdk_la-dbitem.Tpo $(DEPDIR)/libsynthesissdk_la-dbitem.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='sysync_SDK/Sources/dbitem.cpp' object='libsynthesissdk_la-dbitem.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesissdk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libsynthesissdk_la-dbitem.lo `test -f 'sysync_SDK/Sources/dbitem.cpp' || echo '$(srcdir)/'`sysync_SDK/Sources/dbitem.cpp
-
 libsynthesissdk_la-UI_util.lo: sysync_SDK/Sources/UI_util.cpp
 @am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesissdk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libsynthesissdk_la-UI_util.lo -MD -MP -MF $(DEPDIR)/libsynthesissdk_la-UI_util.Tpo -c -o libsynthesissdk_la-UI_util.lo `test -f 'sysync_SDK/Sources/UI_util.cpp' || echo '$(srcdir)/'`sysync_SDK/Sources/UI_util.cpp
 @am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/libsynthesissdk_la-UI_util.Tpo $(DEPDIR)/libsynthesissdk_la-UI_util.Plo
@@ -1675,19 +1635,19 @@ libsynthesissdk_la-stringutil.lo: sysync_SDK/Sources/stringutil.cpp
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesissdk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libsynthesissdk_la-stringutil.lo `test -f 'sysync_SDK/Sources/stringutil.cpp' || echo '$(srcdir)/'`sysync_SDK/Sources/stringutil.cpp
 
-libsynthesissdk_la-admindata.lo: sysync_SDK/Sources/admindata.cpp
-@am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesissdk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libsynthesissdk_la-admindata.lo -MD -MP -MF $(DEPDIR)/libsynthesissdk_la-admindata.Tpo -c -o libsynthesissdk_la-admindata.lo `test -f 'sysync_SDK/Sources/admindata.cpp' || echo '$(srcdir)/'`sysync_SDK/Sources/admindata.cpp
-@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/libsynthesissdk_la-admindata.Tpo $(DEPDIR)/libsynthesissdk_la-admindata.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='sysync_SDK/Sources/admindata.cpp' object='libsynthesissdk_la-admindata.lo' libtool=yes @AMDEPBACKSLASH@
+libsynthesissdk_la-sysync_b64.lo: sysync_SDK/Sources/sysync_b64.cpp
+@am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesissdk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libsynthesissdk_la-sysync_b64.lo -MD -MP -MF $(DEPDIR)/libsynthesissdk_la-sysync_b64.Tpo -c -o libsynthesissdk_la-sysync_b64.lo `test -f 'sysync_SDK/Sources/sysync_b64.cpp' || echo '$(srcdir)/'`sysync_SDK/Sources/sysync_b64.cpp
+@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/libsynthesissdk_la-sysync_b64.Tpo $(DEPDIR)/libsynthesissdk_la-sysync_b64.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='sysync_SDK/Sources/sysync_b64.cpp' object='libsynthesissdk_la-sysync_b64.lo' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesissdk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libsynthesissdk_la-admindata.lo `test -f 'sysync_SDK/Sources/admindata.cpp' || echo '$(srcdir)/'`sysync_SDK/Sources/admindata.cpp
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesissdk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libsynthesissdk_la-sysync_b64.lo `test -f 'sysync_SDK/Sources/sysync_b64.cpp' || echo '$(srcdir)/'`sysync_SDK/Sources/sysync_b64.cpp
 
-libsynthesissdk_la-blobs.lo: sysync_SDK/Sources/blobs.cpp
-@am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesissdk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libsynthesissdk_la-blobs.lo -MD -MP -MF $(DEPDIR)/libsynthesissdk_la-blobs.Tpo -c -o libsynthesissdk_la-blobs.lo `test -f 'sysync_SDK/Sources/blobs.cpp' || echo '$(srcdir)/'`sysync_SDK/Sources/blobs.cpp
-@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/libsynthesissdk_la-blobs.Tpo $(DEPDIR)/libsynthesissdk_la-blobs.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='sysync_SDK/Sources/blobs.cpp' object='libsynthesissdk_la-blobs.lo' libtool=yes @AMDEPBACKSLASH@
+libsynthesissdk_la-sysync_md5.lo: sysync_SDK/Sources/sysync_md5.cpp
+@am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesissdk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libsynthesissdk_la-sysync_md5.lo -MD -MP -MF $(DEPDIR)/libsynthesissdk_la-sysync_md5.Tpo -c -o libsynthesissdk_la-sysync_md5.lo `test -f 'sysync_SDK/Sources/sysync_md5.cpp' || echo '$(srcdir)/'`sysync_SDK/Sources/sysync_md5.cpp
+@am__fastdepCXX_TRUE@  mv -f $(DEPDIR)/libsynthesissdk_la-sysync_md5.Tpo $(DEPDIR)/libsynthesissdk_la-sysync_md5.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='sysync_SDK/Sources/sysync_md5.cpp' object='libsynthesissdk_la-sysync_md5.lo' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesissdk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libsynthesissdk_la-blobs.lo `test -f 'sysync_SDK/Sources/blobs.cpp' || echo '$(srcdir)/'`sysync_SDK/Sources/blobs.cpp
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesissdk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libsynthesissdk_la-sysync_md5.lo `test -f 'sysync_SDK/Sources/sysync_md5.cpp' || echo '$(srcdir)/'`sysync_SDK/Sources/sysync_md5.cpp
 
 libsynthesissdk_la-SDK_support.lo: sysync_SDK/Sources/SDK_support.cpp
 @am__fastdepCXX_TRUE@  $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsynthesissdk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libsynthesissdk_la-SDK_support.lo -MD -MP -MF $(DEPDIR)/libsynthesissdk_la-SDK_support.Tpo -c -o libsynthesissdk_la-SDK_support.lo `test -f 'sysync_SDK/Sources/SDK_support.cpp' || echo '$(srcdir)/'`sysync_SDK/Sources/SDK_support.cpp
@@ -1926,10 +1886,10 @@ $(srcdir)/Makefile.am: $(srcdir)/Makefile.am.in $(srcdir)/gen-makefile-am.sh
 # sysync_SDK/Sources (shared between engine and SDK) or
 # sysync_SDK/SDK (only in SDK). We patch the files so that
 # they include their own files via #include "synthesis/..."
-vpath %.cpp $(srcdir)/sysync_SDK/Sources $(srcdir)/sysync_SDK/SDK # $(srcdir)/Targets/ReleasedProducts/clientEngine_opensource_linux $(srcdir)/syncapps/clientEngine_custom $(srcdir)/sysync $(srcdir)/platform_adapters $(srcdir)
-vpath %.c $(srcdir)/sysync_SDK/Sources $(srcdir)/sysync_SDK/SDK # $(srcdir)/Targets/ReleasedProducts/clientEngine_opensource_linux $(srcdir)/syncapps/clientEngine_custom $(srcdir)/sysync $(srcdir)/platform_adapters $(srcdir)
-vpath %.h $(srcdir)/sysync_SDK/Sources $(srcdir)/sysync_SDK/SDK # $(srcdir)/Targets/ReleasedProducts/clientEngine_opensource_linux $(srcdir)/syncapps/clientEngine_custom $(srcdir)/sysync $(srcdir)/platform_adapters $(srcdir)
-synthesis/enginemodulebridge.h synthesis/SDK_util.h synthesis/prefix_file.h synthesis/sync_dbapi.h synthesis/enginemodulebase.h synthesis/SDK_support.h synthesis/stringutil.h synthesis/sync_declarations.h synthesis/sync_dbapidef.h synthesis/generic_types.h synthesis/engine_defs.h synthesis/sync_include.h synthesis/timeutil.h synthesis/dbitem.h synthesis/blobs.h synthesis/sync_uiapi.h synthesis/admindata.h synthesis/dataconversion.h synthesis/syerror.h synthesis/UI_util.h: synthesis/%: %
+vpath %.cpp $(srcdir)/sysync_SDK/Sources $(srcdir)/sysync_SDK/SDK
+vpath %.c $(srcdir)/sysync_SDK/Sources $(srcdir)/sysync_SDK/SDK
+vpath %.h $(srcdir)/sysync_SDK/Sources $(srcdir)/sysync_SDK/SDK
+synthesis/sysync_b64.h synthesis/enginemodulebridge.h synthesis/SDK_util.h synthesis/prefix_file.h synthesis/sync_dbapi.h synthesis/enginemodulebase.h synthesis/SDK_support.h synthesis/stringutil.h synthesis/sync_declarations.h synthesis/sync_dbapidef.h synthesis/generic_types.h synthesis/engine_defs.h synthesis/sync_include.h synthesis/timeutil.h synthesis/dbitem.h synthesis/san.h synthesis/blobs.h synthesis/sync_uiapi.h synthesis/admindata.h synthesis/dataconversion.h synthesis/sysync_md5.h synthesis/syerror.h synthesis/UI_util.h: synthesis/%: %
        mkdir -p synthesis
        sed -e 's;# *include  *";#include "synthesis/;' -e 's/defined(HAVE_STDINT_H)/1/' $< >$@
 
index eb5316e..0151e97 100644 (file)
@@ -3,13 +3,9 @@ enginemodulebridge.h
 stringutil.cpp
 stringutil.h
 target_options.h
+san.cpp
+san.h
 timeutil.cpp
 timeutil.h
 UI_util.cpp
 UI_util.h
-blobs.cpp
-blobs.h
-dbitem.cpp
-dbitem.h
-admindata.cpp
-admindata.h
index f3754df..be37fe0 100644 (file)
@@ -1,2 +1,8 @@
+admindata.cpp
+admindata.h
+dbitem.cpp
+dbitem.h
+blobs.cpp
+blobs.h
 enginesessiondispatch.cpp
 syncserver.cpp
diff --git a/src/synthesis/src/Targets/ReleasedProducts/combiEngine_opensource_linux/combiengine_demo++.pch b/src/synthesis/src/Targets/ReleasedProducts/combiEngine_opensource_linux/combiengine_demo++.pch
new file mode 100644 (file)
index 0000000..5ce5198
--- /dev/null
@@ -0,0 +1,21 @@
+/* precompiled headers source file
+ * ===============================
+ *
+ */
+
+// SySync is a C++ project, make sure precomp headers
+// are compiled as C++!
+#pragma cplusplus on
+
+// determine target file name
+#pragma precompile_target      "combiengine_opensource_linux++.mch"
+
+
+// include all headers that are suitable for precompiled use
+
+// - target options can incfluence everything
+#include "target_options.h"
+// - precompilable headers
+#include "combiengine_custom_precomp.h"
+
+// eof
diff --git a/src/synthesis/src/Targets/ReleasedProducts/combiEngine_opensource_linux/combiengine_demo.pch b/src/synthesis/src/Targets/ReleasedProducts/combiEngine_opensource_linux/combiengine_demo.pch
new file mode 100644 (file)
index 0000000..f6f9fad
--- /dev/null
@@ -0,0 +1,20 @@
+/* precompiled headers source file
+ * ===============================
+ *
+ */
+
+// C-version for SyncML toolkit files
+#pragma cplusplus off
+
+// determine target file name
+#pragma precompile_target "combiengine_opensource_linux.mch"
+
+// include all headers that are suitable for precompiled
+// C version use
+// - target options can incfluence everything
+#include "target_options.h"
+
+// standard SyncML TK stuff
+#include "smltk_precomp.h"
+
+// eof
diff --git a/src/synthesis/src/Targets/ReleasedProducts/combiEngine_opensource_linux/combiengine_opensource_linux_prefix.h b/src/synthesis/src/Targets/ReleasedProducts/combiEngine_opensource_linux/combiengine_opensource_linux_prefix.h
new file mode 100644 (file)
index 0000000..ee22a31
--- /dev/null
@@ -0,0 +1,43 @@
+/* prefix file
+ * ===========
+ *
+ */
+
+
+// override default in global_options.h:
+// always use SySync_ as prefix for external C functions
+// - client
+#define SYSYNC_EXTERNAL(_x) SySync_ ## _x
+#define SYSYNC_PREFIX "SySync_"
+// - server
+#define SYSYNC_EXTERNAL_SRV(_x) SySync_srv_ ## _x
+#define SYSYNC_PREFIX_SRV "SySync_srv_"
+
+
+// required before time.h to get tm_gmtoff in struct tm:
+// this is used to find standard and daylight saving offset
+// of the system, see timezones.cpp
+#define _BSD_SOURCE 1
+#define USE_TM_GMTOFF 1
+
+// required for vasprintf
+#define _GNU_SOURCE 1
+
+#ifdef __cplusplus
+  // include all headers that are suitable for precompiled use
+  // - target options can incfluence everything
+  #include "target_options.h"
+  // - platform specifics
+  #include "platform_headers.h"
+  // - precompilable headers (use those of server, but client is the same)
+  #include "serverengine_custom_precomp.h"
+#else
+  // include all headers that are suitable for precompiled
+  // C version use
+  // - target options can incfluence everything
+  #include "target_options.h"
+  // - platform specifics
+  #include "platform_headers.h"
+#endif
+
+/* eof */
diff --git a/src/synthesis/src/Targets/ReleasedProducts/combiEngine_opensource_linux/define.h b/src/synthesis/src/Targets/ReleasedProducts/combiEngine_opensource_linux/define.h
new file mode 100644 (file)
index 0000000..42b2247
--- /dev/null
@@ -0,0 +1,119 @@
+
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+// NOTE: this is a local copy for this specific target
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+
+
+/*************************************************************************/
+/* module:          Compiler Flag Definition File                        */
+/* file:            define.h                                             */
+/* target system:   win                                                  */
+/* target OS:       win                                                  */
+/*************************************************************************/
+
+/*
+ * Copyright Notice
+ * Copyright (c) Ericsson, IBM, Lotus, Matsushita Communication
+ * Industrial Co., Ltd., Motorola, Nokia, Openwave Systems, Inc.,
+ * Palm, Inc., Psion, Starfish Software, Symbian, Ltd. (2001).
+ * All Rights Reserved.
+ * Implementation of all or part of any Specification may require
+ * licenses under third party intellectual property rights,
+ * including without limitation, patent rights (such a third party
+ * may or may not be a Supporter). The Sponsors of the Specification
+ * are not responsible and shall not be held responsible in any
+ * manner for identifying or failing to identify any or all such
+ * third party intellectual property rights.
+ *
+ * THIS DOCUMENT AND THE INFORMATION CONTAINED HEREIN ARE PROVIDED
+ * ON AN "AS IS" BASIS WITHOUT WARRANTY OF ANY KIND AND ERICSSON, IBM,
+ * LOTUS, MATSUSHITA COMMUNICATION INDUSTRIAL CO. LTD, MOTOROLA,
+ * NOKIA, PALM INC., PSION, STARFISH SOFTWARE AND ALL OTHER SYNCML
+ * SPONSORS DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ * HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
+ * SHALL ERICSSON, IBM, LOTUS, MATSUSHITA COMMUNICATION INDUSTRIAL CO.,
+ * LTD, MOTOROLA, NOKIA, PALM INC., PSION, STARFISH SOFTWARE OR ANY
+ * OTHER SYNCML SPONSOR BE LIABLE TO ANY PARTY FOR ANY LOSS OF
+ * PROFITS, LOSS OF BUSINESS, LOSS OF USE OF DATA, INTERRUPTION OF
+ * BUSINESS, OR FOR DIRECT, INDIRECT, SPECIAL OR EXEMPLARY, INCIDENTAL,
+ * PUNITIVE OR CONSEQUENTIAL DAMAGES OF ANY KIND IN CONNECTION WITH
+ * THIS DOCUMENT OR THE INFORMATION CONTAINED HEREIN, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH LOSS OR DAMAGE.
+ *
+ * The above notice and this paragraph must be included on all copies
+ * of this document that are made.
+ *
+ */
+
+/**
+ * File for Windows Specific Compiler Flags
+ */
+
+#ifndef _DEFINE_H
+  #define _DEFINE_H
+#define __ANSI_C__
+
+
+/* thread safety (added by luz@synthesis.ch, 2001-10-29) */
+/* Note: moved define of this to target_options.h of every target */
+#undef __MAKE_THREADSAFE
+
+/* enable Alloc helpers */
+#define __USE_ALLOCFUNCS__
+
+/* do we need WBXML (binary XML) processing ? */
+#define __SML_WBXML__
+/* do we need the capability to decode plain text tokens in WBXML? */
+#define __SML_WBXML_TEXTTOKENS__
+/* do we need XML processing ? */
+#define __SML_XML__
+/* are we using a 'light' toolkit ? */
+//#define __SML_LITE__
+/* do we use Sub DTD extensions ? */
+#define __USE_EXTENSIONS__
+/* do we need Metainformation DTD parsing ? */
+#define __USE_METINF__
+/* do we use Device Info DTD ? */
+#define __USE_DEVINF__
+
+/* which of the following optional commands should be included ? */
+
+#define ADD_SEND
+//#define ATOMIC_SEND
+//#define ATOMIC_RECEIVE
+//#define COPY_SEND
+//#define COPY_RECEIVE
+//#define EXEC_SEND
+//#define EXEC_RECEIVE
+#define GET_SEND
+#define MAP_RECEIVE
+#define MAPITEM_RECEIVE
+#define RESULT_RECEIVE
+//#define SEARCH_SEND
+//#define SEARCH_RECEIVE
+//#define SEQUENCE_SEND
+//#define SEQUENCE_RECEIVE
+
+
+/* TK: to improve interoperability and handling we
+ * switched to using .def files instead of compiler
+ * specific per function definitions. As long as we only
+ * use C this is the easiest and cleanes way
+ */
+
+#define SML_API
+#define SML_API_DEF
+#define XPT_API
+#define XPT_API_DEF
+
+
+/* Multi segment macro for Palm OS */
+#define LIB_FUNC
+#define MGR_FUNC
+#define WSM_FUNC
+#define XLT_FUNC
+
+#endif
diff --git a/src/synthesis/src/Targets/ReleasedProducts/combiEngine_opensource_linux/target_options.h b/src/synthesis/src/Targets/ReleasedProducts/combiEngine_opensource_linux/target_options.h
new file mode 100644 (file)
index 0000000..3253c15
--- /dev/null
@@ -0,0 +1,193 @@
+/* Target options
+ * ==============
+ *
+ */
+
+// SYNCML SERVER ENGINE LIBRARY OPENSOURCE LINUX
+// #############################################
+
+// define platform
+#define LINUX
+
+// Release version status
+#define RELEASE_VERSION
+#define RELEASE_SYDEBUG 2 // extended DBG included
+//#define OPTIONAL_SYDEBUG 1
+
+// Eval limit options
+// ==================
+
+// OpenSource Library does not have any expiry mechanisms
+#define NEVER_EXPIRES_IS_OK 1 // to explicitly override check in SyncAppBase
+
+// now include platform independent product options (which include global_options.h)
+#include "combi_product_options.h"
+
+
+// Identification strings
+#define CUST_SYNC_MAN       SYSYNC_OEM  // manufactured by ourselves
+#define CUST_SYNC_MODEL     "SySync SyncML Library OpenSource Linux"
+#define CUST_SYNC_FIRMWARE  NULL  // no firmware
+#define CUST_SYNC_HARDWARE  NULL  // no hardware
+
+// String used to construct logfile names
+#define TARGETID "sysynclib_uni_linux"
+
+// Configuration
+// =============
+
+// Default profile
+#undef HARD_CODED_SERVER_URI
+#undef HARD_CODED_DBNAMES
+#define DEFAULT_SERVER_URI ""
+#define DEFAULT_LOCALDB_PROFILE ""
+#define DEFAULT_SERVER_USER ""
+#define DEFAULT_SERVER_PASSWD ""
+#define DEFAULT_ENCODING SML_WBXML
+#define DEFAULT_TRANSPORT_USER NULL
+#define DEFAULT_TRANSPORT_PASSWD NULL
+#define DEFAULT_SOCKS_HOST NULL
+#define DEFAULT_PROXY_HOST NULL
+#define DEFAULT_DATASTORES_ENABLED false
+#define DEFAULT_EVENTS_DAYSBEFORE 30
+#define DEFAULT_EVENTS_DAYSAFTER 90
+#define DEFAULT_EVENTS_LIMITED false
+#define DEFAULT_EMAILS_LIMITED true
+#define DEFAULT_EMAILS_HDRONLY true
+#define DEFAULT_EMAILS_MAXKB 2
+#define DEFAULT_EMAILS_ONLYLAST true
+#define DEFAULT_EMAILS_DAYSBEFORE 10
+
+
+// Note: Hard expiration date settings moved to product_options.h
+
+// This is the opensource Linux library, and needs no registration
+#undef SYSER_REGISTRATION
+#undef VERSION_COMMENTS
+#define VERSION_COMMENTS "Synthesis OpenSource"
+#undef EXPIRES_AFTER_DATE
+
+// - if defined, software will stop specified number of days after
+//   first use
+#undef EXPIRES_AFTER_DAYS // Engine does not have auto-demo
+
+// Identification for update check and demo period
+#define SYSER_VARIANT_CODE SYSER_VARIANT_PRO
+#define SYSER_PRODUCT_CODE SYSER_PRODCODE_SERVER_LIB_LINUX
+#define SYSER_EXTRA_ID SYSER_EXTRA_ID_NONE
+
+// - define allowed product codes
+#define SYSER_PRODUCT_CODE_MAIN SYSER_PRODCODE_SERVER_DEMO // a permanent DEMO license
+#define SYSER_PRODUCT_CODE_ALT1 SYSER_PRODCODE_SERVER_LIB_LINUX // ..or a library license for Linux
+#define SYSER_PRODUCT_CODE_ALT2 SYSER_PRODCODE_SERVER_LIB_ALL // ..or for all platforms
+#define SYSER_PRODUCT_CODE_ALT3 SYSER_PRODCODE_SERVER_LIB_DESK // ..or for desktop platforms
+#define SYSER_PRODUCT_CODE_ALT4 SYSER_PRODCODE_SERVER_ODBC_PRO_LINUX // ..or a PRO server for Linux
+// - define needed product flags
+//   only licenses that are release date limited (or explicitly NOT release date limited,
+//   or time limited) are allowed
+#define SYSER_NEEDED_PRODUCT_FLAGS SYSER_PRODFLAG_MAXRELDATE
+#define SYSER_FORBIDDEN_PRODUCT_FLAGS 0
+
+// for the opensource version, DLL plugins are always allowed
+// (even with licenses that do not have SYSER_PRODFLAG_SERVER_SDKAPI set)
+// because we do not use a license at all!
+#define DLL_PLUGINS_ALWAYS_ALLOWED 1
+
+
+// SySync options
+// ==============
+
+// - enhanced profile record
+#define ENHANCED_PROFILES_2004 1
+#define CLIENTFEATURES_2008 1
+
+// - NO support for automatic syncing (timed, IPP, server alerted...)
+#undef AUTOSYNC_SUPPORT
+// - support for intelligent push & poll (IPP)
+//#define IPP_SUPPORT 1
+//#define IPP_SUPPORT_ALWAYS 1 // regardless of license flags
+// - support for timed sync
+#undef TIMEDSYNC_SUPPORT
+// - support for WAP push alerted sync
+#undef SERVERALERT_SUPPORT
+
+// - support for Proxy
+#define PROXY_SUPPORT 1
+
+// - support for multiple profiles
+#define MULTI_PROFILE_SUPPORT 1
+
+// - show progress events
+#define PROGRESS_EVENTS 1
+
+// - we do not need to squeeze code
+#undef MINIMAL_CODE
+
+// - script with regex support
+#define SCRIPT_SUPPORT 1
+#define REGEX_SUPPORT 1
+
+// - server does support target options
+#define SYSYNC_TARGET_OPTIONS 1
+
+// - filters
+#define OBJECT_FILTERING 1
+
+// - server does need superdatastores
+#define SUPERDATASTORES 1
+
+
+// general options needed for email
+#define EMAIL_FORMAT_SUPPORT 1
+#define EMAIL_ATTACHMENT_SUPPORT 1
+#define ARRAYFIELD_SUPPORT 1
+
+// - if defined, stream field support will be included
+#define STREAMFIELD_SUPPORT 1
+
+// - if defined, semi-proprietary zipped-binary <data> for items (any type) can be used
+//   (enabled on a by type basis in the config)
+#define ZIPPED_BINDATA_SUPPORT 1
+
+
+// - where to save application data by default (if not otherwise configured)
+//   APPDATA_SUBDIR is a subdirectory of the user's "application data" dir.
+#define APPDATA_SUBDIR "synthesis.ch/SySyncLib_uni"
+
+// - if defined, code for incoming and outgoing SyncML dumping into (WB)XML logfiles is included
+#define MSGDUMP 1
+
+
+// Database support options
+// ========================
+
+// - link in customimplds on top of binfile
+#define BASED_ON_BINFILE_CLIENT 1
+// - SQL and API datastores have changedetection, so build binfile for that
+#define CHANGEDETECTION_AVAILABLE 1
+// - we need a separate changelog mechanism
+#define CHECKSUM_CHANGELOG 1
+// - string localIDs with sufficiently large size
+#define STRING_LOCALID_MAXLEN 256
+
+
+// - if defined, SQL support is included
+#define SQL_SUPPORT           1
+#undef ODBCAPI_SUPPORT
+#define SQLITE_SUPPORT        1
+// - if defined, ODBC DB mapping of arrays to aux tables is supported
+#define ARRAYDBTABLES_SUPPORT 1
+
+// - if defined, SDK support is included
+#define SDK_SUPPORT           1
+// - id defined, code allows calling of subsequent DLLs
+#define PLUGIN_DLL            1
+
+// - define what SDK modules are linked in
+//#define DBAPI_DEMO          1
+#define   DBAPI_TEXT          1
+//#define DBAPI_SILENT        1
+//#define DBAPI_EXAMPLE       1
+
+
+/* eof */
index 89cd701..d711a88 100644 (file)
 // - id defined, code allows calling of subsequent DLLs
 #define PLUGIN_DLL            1
 
+// - define what SDK modules are linked in
+//#define DBAPI_DEMO          1
+#define   DBAPI_TEXT          1
+//#define DBAPI_SILENT        1
+//#define DBAPI_EXAMPLE       1
 
 
 // SySync options
diff --git a/src/synthesis/src/Transport_interfaces/engine/engine_server.h b/src/synthesis/src/Transport_interfaces/engine/engine_server.h
new file mode 100644 (file)
index 0000000..b8f699d
--- /dev/null
@@ -0,0 +1,26 @@
+/* server engine (w/o internal transport) generic header file */
+
+#ifndef ENGINE_SERVER_H
+#define ENGINE_SERVER_H
+
+/* Headers that might be available in precompiled form
+ * (standard libraries, SyncML toolkit...)
+ */
+#include "engine_server_precomp.h"
+
+/* headers not suitable for / entirely included in precompilation */
+
+// sysync core
+#include "sysync.h"
+// platform utilities
+//#include "platform_utils.h"
+
+// classes
+#include "enginesessiondispatch.h"
+
+/* globals */
+
+
+#endif // ENGINE_SERVER_H
+
+/* eof */
diff --git a/src/synthesis/src/Transport_interfaces/engine/engine_server_precomp.h b/src/synthesis/src/Transport_interfaces/engine/engine_server_precomp.h
new file mode 100644 (file)
index 0000000..29c17f2
--- /dev/null
@@ -0,0 +1,34 @@
+/* Headers that might be available in precompiled form
+ * (standard libraries, SyncML toolkit...)
+ */
+
+#ifndef ENGINE_SERVER_PRECOMP_H
+#define ENGINE_SERVER_PRECOMP_H
+
+
+/* precompiled portion for SySync Core */
+#include "sysync_precomp.h"
+
+
+#ifdef __EPOC_OS__
+  // Symbian/EPOC: 
+#elif __INTEL__
+  // Windows32: nothing special
+#elif defined(__MC68K__)
+  // PalmOS: nothing special
+#elif defined(LINUX)
+  // Linux: nothing special
+#elif defined(MACOSX)
+  // MacOSX: nothing special
+#elif defined(WINCE)
+  // WinCE/PocketPC: nothing special
+#elif defined(_MSC_VER)
+  // Visual C++: nothing special
+#else
+  #error "Engine Client is Win32/PalmOS/MacOS/PocketPC/Linux only at this time"
+#endif
+
+
+#endif // ENGINE_SERVER_PRECOMP_H
+
+// eof
index 6e6067c..6d40f5b 100755 (executable)
@@ -18,6 +18,9 @@
 namespace sysync {
 
 
+#ifndef SYSYNC_SERVER
+// if there is also a server in the system, it will define AppConsolePuts so we don't need it here 
+
 // write to platform's "console", whatever that is
 void AppConsolePuts(const char *aText)
 {
@@ -25,41 +28,43 @@ void AppConsolePuts(const char *aText)
   PlatformConsolePuts(aText);
 } // AppConsolePuts
 
+#endif // no SYSYNC_SERVER included
 
-// TEngineCommConfig
-// =================
+
+// TEngineClientCommConfig
+// =======================
 // (dummy at this time)
 
 
 // config constructor
-TEngineCommConfig::TEngineCommConfig(TConfigElement *aParentElementP) :
+TEngineClientCommConfig::TEngineClientCommConfig(TConfigElement *aParentElementP) :
   TCommConfig("engineclient",aParentElementP)
 {
   // do not call clear(), because this is virtual!
-} // TEngineCommConfig::TXPTCommConfig
+} // TEngineClientCommConfig::TEngineClientCommConfig
 
 
 // config destructor
-TEngineCommConfig::~TEngineCommConfig()
+TEngineClientCommConfig::~TEngineClientCommConfig()
 {
   // nop by now
-} // TEngineCommConfig::~TXPTCommConfig
+} // TEngineClientCommConfig::~TEngineClientCommConfig
 
 
 // init defaults
-void TEngineCommConfig::clear(void)
+void TEngineClientCommConfig::clear(void)
 {
   // init defaults
   // %%% none for now
   // clear inherited
   inherited::clear();
-} // TEngineCommConfig::clear
+} // TEngineClientCommConfig::clear
 
 
 #ifndef HARDCODED_CONFIG
 
 // XPT transport config element parsing
-bool TEngineCommConfig::localStartElement(const char *aElementName, const char **aAttributes, sInt32 aLine)
+bool TEngineClientCommConfig::localStartElement(const char *aElementName, const char **aAttributes, sInt32 aLine)
 {
   // checking the elements
   /*
@@ -70,13 +75,13 @@ bool TEngineCommConfig::localStartElement(const char *aElementName, const char *
     return inherited::localStartElement(aElementName,aAttributes,aLine);
   // ok
   return true;
-} // TEngineCommConfig::localStartElement
+} // TEngineClientCommConfig::localStartElement
 
 #endif
 
 
 // resolve
-void TEngineCommConfig::localResolve(bool aLastPass)
+void TEngineClientCommConfig::localResolve(bool aLastPass)
 {
   if (aLastPass) {
     // check for required settings
@@ -84,7 +89,7 @@ void TEngineCommConfig::localResolve(bool aLastPass)
   }
   // resolve inherited
   inherited::localResolve(aLastPass);
-} // TEngineCommConfig::localResolve
+} // TEngineClientCommConfig::localResolve
 
 
 
@@ -118,7 +123,7 @@ TEngineClientBase::~TEngineClientBase()
 void TEngineClientRootConfig::installCommConfig(void)
 {
   // engine API needs no config at this time, commconfig is a NOP dummy for now
-  fCommConfigP=new TEngineCommConfig(this);
+  fCommConfigP=new TEngineClientCommConfig(this);
 } // TEngineClientRootConfig::installCommConfig
 
 
index 6bc71e8..0c62048 100755 (executable)
@@ -15,7 +15,7 @@
 // required headers
 #include "syncappbase.h"
 #include "syncclientbase.h"
-#include "syncclient.h"
+#include "syncagent.h"
 
 
 namespace sysync {
@@ -37,12 +37,12 @@ public:
 
 
 // engine client transport config
-class TEngineCommConfig: public TCommConfig
+class TEngineClientCommConfig: public TCommConfig
 {
   typedef TCommConfig inherited;
 public:
-  TEngineCommConfig(TConfigElement *aParentElementP);
-  virtual ~TEngineCommConfig();
+  TEngineClientCommConfig(TConfigElement *aParentElementP);
+  virtual ~TEngineClientCommConfig();
 protected:
   // check config elements
   #ifndef HARDCODED_CONFIG
diff --git a/src/synthesis/src/Transport_interfaces/engine/enginesessiondispatch.cpp b/src/synthesis/src/Transport_interfaces/engine/enginesessiondispatch.cpp
new file mode 100644 (file)
index 0000000..a11ed67
--- /dev/null
@@ -0,0 +1,484 @@
+/*
+ *  TEngineSessionDispatch
+ *    Server library specific descendant of TSyncSessionDispatch
+ *
+ *  Copyright (c) 2009-2009 by Synthesis AG (www.synthesis.ch)
+ *
+ *  2009-02-06 : luz : Created
+ *
+ */  
+
+#include "prefix_file.h"
+#include "engine_server.h"
+#include "enginesessiondispatch.h"
+
+
+namespace sysync {
+
+
+// write to platform's "console", whatever that is
+void AppConsolePuts(const char *aText)
+{
+  // Just print to platform's console
+  PlatformConsolePuts(aText);
+} // AppConsolePuts
+
+
+// TEngineServerCommConfig
+// =======================
+
+
+// config constructor
+TEngineServerCommConfig::TEngineServerCommConfig(TConfigElement *aParentElementP) :
+  TCommConfig("engineserver",aParentElementP)
+{
+  // do not call clear(), because this is virtual!
+} // TEngineServerCommConfig::TEngineServerCommConfig
+
+
+// config destructor
+TEngineServerCommConfig::~TEngineServerCommConfig()
+{
+  // nop by now
+} // TEngineServerCommConfig::~TEngineServerCommConfig
+
+
+// init defaults
+void TEngineServerCommConfig::clear(void)
+{
+  // init defaults
+  fSessionIDCGIPrefix = "sessionid=";
+  fSessionIDCGI = true;
+  // clear inherited  
+  inherited::clear();
+} // TEngineServerCommConfig::clear
+
+
+#ifndef HARDCODED_CONFIG
+
+// XPT transport config element parsing
+bool TEngineServerCommConfig::localStartElement(const char *aElementName, const char **aAttributes, sInt32 aLine)
+{
+  // checking the elements
+  if (strucmp(aElementName,"sessionidcgiprefix")==0)
+    expectString(fSessionIDCGIPrefix);
+  if (strucmp(aElementName,"sessionidcgi")==0)
+    expectBool(fSessionIDCGI);
+  else
+    return inherited::localStartElement(aElementName,aAttributes,aLine);
+  // ok
+  return true;
+} // TEngineServerCommConfig::localStartElement
+
+#endif
+
+
+// resolve
+void TEngineServerCommConfig::localResolve(bool aLastPass)
+{
+  if (aLastPass) {
+    // check for required settings
+    // NOP for now
+  }
+  // resolve inherited  
+  inherited::localResolve(aLastPass);
+} // TEngineServerCommConfig::localResolve
+
+
+
+// TEngineSessionDispatch
+// ======================
+
+
+// constructor
+TEngineSessionDispatch::TEngineSessionDispatch() :
+  TSyncAppBase()
+{
+  // this is a server engine
+  fIsServer = true;
+} // TEngineSessionDispatch::TEngineSessionDispatch
+
+
+// destructor
+TEngineSessionDispatch::~TEngineSessionDispatch()
+{
+  fDeleting=true; // flag deletion to block calling critical (virtual) methods
+  // clean up
+  // %%%
+} // TEngineSessionDispatch::~TEngineSessionDispatch
+
+
+// Called from SyncML toolkit when a new SyncML message arrives
+// - dispatches to session's StartMessage
+Ret_t TEngineSessionDispatch::StartMessage(
+  InstanceID_t aSmlWorkspaceID, // SyncML toolkit workspace instance ID
+  VoidPtr_t aUserData, // pointer to a TSyncAgent descendant
+  SmlSyncHdrPtr_t aContentP // SyncML tookit's decoded form of the <SyncHdr> element
+) {
+  TSyncSession *sessionP = static_cast<TSyncAgent *>(aUserData); // the server session
+  SYSYNC_TRY {
+    // let session handle details of StartMessage callback
+    return sessionP->StartMessage(aContentP);
+  }
+  SYSYNC_CATCH (exception &e)
+    return HandleDecodingException(sessionP,"StartMessage",&e);
+  SYSYNC_ENDCATCH
+  SYSYNC_CATCH (...)
+    return HandleDecodingException(sessionP,"StartMessage",NULL);
+  SYSYNC_ENDCATCH
+} // TEngineSessionDispatch::StartMessage
+
+
+// - combine URI and session ID to make a RespURI according to transport
+void TEngineSessionDispatch::generateRespURI(
+  string &aRespURI,
+  cAppCharP aLocalURI,
+  cAppCharP aSessionID
+)
+{
+  TEngineServerCommConfig *commCfgP = static_cast<TEngineServerCommConfig *>(getRootConfig()->fCommConfigP);
+  if (aLocalURI && aSessionID && commCfgP && commCfgP->fSessionIDCGI) {
+       // include session ID as CGI into RespURI
+    aRespURI=aLocalURI;
+    // see if there is already a sessionid in this localURI
+    string::size_type n=aRespURI.find(commCfgP->fSessionIDCGIPrefix);
+    if (n!=string::npos) {
+      n+=commCfgP->fSessionIDCGIPrefix.size(); // char after prefix
+      // is already there, replace value with new value
+      string::size_type m=aRespURI.find_first_of("&?\n\r",n);
+      if (m==string::npos)
+        aRespURI.replace(n,999,aSessionID);
+      else
+        aRespURI.replace(n,m-n,aSessionID);
+    }
+    else {
+      // no sessionID yet    
+      if (strchr(aLocalURI,'?')) {
+        // already has CGI param
+        aRespURI+="&amp;";
+      }
+      else {
+        // is first CGI param
+        aRespURI+='?';
+      }
+      // append session ID as CGI parameter
+      aRespURI+=commCfgP->fSessionIDCGIPrefix;
+      aRespURI+=aSessionID;
+    }
+  }
+} // TEngineSessionDispatch::generateRespURI
+
+
+
+// Handle exception happening while decoding commands for a session
+Ret_t TEngineSessionDispatch::HandleDecodingException(TSyncSession *aSessionP, const char *aRoutine, exception *aExceptionP)
+{
+  #ifdef SYDEBUG
+  // determine session name
+  const char *sname = "<unknown>";
+  try {
+    if (aSessionP) {
+      sname = aSessionP->getLocalSessionID();
+    }
+  }
+  catch (...) {
+    sname = "<BAD aSessionP, caused exception>";
+    aSessionP=NULL; // prevent attempt to write to session's log
+  }
+  // determine routine name
+  if (!aRoutine) aRoutine="<unspecified routine>";
+  // show details
+  if (aExceptionP) {
+    // known exception
+    // - show it in global log
+    PDEBUGPRINTFX(DBG_ERROR,(
+      "******** Exception in %s, sessionID=%s: %s",
+      aRoutine,
+      sname,
+      aExceptionP->what()
+    ));
+    // - and also in session log
+    #ifdef SYDEBUG
+    if (aSessionP) {
+      POBJDEBUGPRINTFX(aSessionP,DBG_ERROR,(
+        "******** Warning: Exception in %s: %s",
+        aRoutine,
+        aExceptionP->what()
+      ));
+    }
+    #endif
+  }
+  else {
+    // unknown exception
+    // - show it in global log
+    PDEBUGPRINTFX(DBG_ERROR,(
+      "******** Unknown Exception in %s, sessionID=%s",
+      aRoutine,
+      sname
+    ));
+    // - and also in session log
+    #ifdef SYDEBUG
+    if (aSessionP) {
+      POBJDEBUGPRINTFX(aSessionP,DBG_ERROR,(
+        "******** Warning: Unknown Exception in %s",
+        aRoutine
+      ));
+    }
+    #endif
+  }
+  #endif
+  // try to kill session
+  DEBUGPRINTFX(DBG_SESSION,("******** Exception aborts session"));
+  aSessionP->AbortSession(412,true); // incomplete command
+  // return error
+  DEBUGPRINTFX(DBG_SESSION,("******** Exception: returning SML_ERR_UNSPECIFIC to abort smlProcessData"));
+  return SML_ERR_UNSPECIFIC;
+} // TEngineSessionDispatch::HandleDecodingException
+
+
+
+// factory methods of Rootconfig
+// =============================
+
+
+// create default transport config
+void TEngineServerRootConfig::installCommConfig(void)
+{
+  // engine API needs no config at this time, commconfig is a NOP dummy for now
+  fCommConfigP=new TEngineServerCommConfig(this);
+} // TEngineServerRootConfig::installCommConfig
+
+
+#ifndef HARDCODED_CONFIG
+
+bool TEngineServerRootConfig::parseCommConfig(const char **aAttributes, sInt32 aLine)
+{
+  // engine API needs no config at this time
+  return false;
+} // TEngineServerRootConfig::parseCommConfig
+
+#endif  
+
+
+
+// TEngineServerSessionHandle
+// ==========================
+
+// Note: this is not a relative of TSyncSessionHandle, but only a container for TSyncAgent also
+//       holding some engine-related status. TSyncAgent is run with a NULL TSyncSessionHandle
+//       when called via engine, as all session dispatching is outside the engine.
+
+TEngineServerSessionHandle::TEngineServerSessionHandle(TServerEngineInterface *aServerEngineInterface)
+{
+       fServerSessionP = NULL;
+  fSmlInstanceID = 0;
+  fSessionStatus = LOCERR_WRONGUSAGE;
+  fServerEngineInterface = aServerEngineInterface;
+}
+
+TEngineServerSessionHandle::~TEngineServerSessionHandle()
+{
+       // remove the session if still existing
+       if (fServerSessionP) delete fServerSessionP;
+  fServerSessionP = NULL;
+  // also release the toolkit instance
+  fServerEngineInterface->getSyncAppBase()->freeSmlInstance(fSmlInstanceID);
+  fSmlInstanceID=NULL;  
+}
+
+
+// TServerEngineInterface
+// ======================
+
+/// @brief Open a session
+/// @param aNewSessionH[out] receives session handle for all session execution calls
+/// @param aSelector[in] selector, depending on session type.
+/// @param aSessionName[in] a text name/id to identify the session. If NULL, session gets a standard ID based on time and memory location
+/// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure
+TSyError TServerEngineInterface::OpenSessionInternal(SessionH &aNewSessionH, uInt32 aSelector, cAppCharP aSessionName)
+{
+  TEngineSessionDispatch *sessionDispatchP = static_cast<TEngineSessionDispatch *>(getSyncAppBase());
+
+  // check type of session
+  if (aSelector == SESSIONSEL_DBAPI_TUNNEL) {
+    // initiate a DBAPI tunnel session.
+    /* 
+    #ifdef DBAPI_TUNNEL_SUPPORT
+    #error "%%% tbi"
+    // Create a new session, sessionName selects datastore
+    fSessionStatus = sessionDispatchP->CreateTunnelSession(aSessionName);
+    if (fSessionStatus==LOCERR_OK) {
+      // return the session pointer as handle
+      %%%aNewSessionH=clientBaseP->fClientSessionP;
+    }
+    #else
+    return LOCERR_NOTIMP; // tunnel not implemented
+    #endif
+    */
+    // %%% for now: not implemented
+    return LOCERR_NOTIMP; // tunnel not implemented
+  }
+  else {
+               // create a new server session
+               TEngineServerSessionHandle *sessionHandleP = NULL;
+       TSyncAgent *sessionP=NULL;
+    SYSYNC_TRY {
+      // - create a handle
+      sessionHandleP = new TEngineServerSessionHandle(this);
+      // - create session ID if none passed
+      string SessionIDString;
+      if (aSessionName && *aSessionName) {
+        SessionIDString = aSessionName;
+      }
+      else {
+        // - create unique server-side session ID
+        //   format = aaaabbbbccccdddd
+        //   - aaaa = low word of time(NULL) >> 1 (to make sure MSB is cleared)
+        //   - dddd = high word of time(NULL)
+        //   - bbbbcccc = memory address of session handle
+        uInt64 sid =
+          time(NULL);
+        sid =
+          ((sid >> 16) & 0xFFFF) + ((sid << 47) & 0x7FFF000000000000LL) + // aaaa00000000dddd
+          ((((uIntPtr)sessionHandleP)&0xFFFFFFFF) << 16); // 0000bbbbcccc0000
+        // - make a string of it
+        StringObjPrintf(SessionIDString,"%llu",(long long unsigned)sid);
+      }
+      // - create session object
+      sessionP =
+        static_cast<TAgentConfig *>(sessionDispatchP->getRootConfig()->fAgentConfigP)
+          ->CreateServerSession(NULL,SessionIDString.c_str());
+      if (sessionP) {
+       // assign to handle
+        sessionHandleP->fServerSessionP = sessionP;
+        sessionHandleP->fSessionStatus = LOCERR_OK;
+        // also create a toolkit instance for the session (so we can start receiving data)
+        if (!getSyncAppBase()->newSmlInstance(
+          SML_XML,
+          sessionDispatchP->getRootConfig()->fLocalMaxMsgSize * 2, // twice the message size
+          sessionHandleP->fSmlInstanceID
+        )) {
+               // failed creating instance (must be memory problem)
+          delete sessionP;
+          return LOCERR_OUTOFMEM;
+        }
+        // link session with toolkit instance back and forth
+       getSyncAppBase()->setSmlInstanceUserData(sessionHandleP->fSmlInstanceID,sessionP); // toolkit must know session (as userData)
+       sessionP->setSmlWorkspaceID(sessionHandleP->fSmlInstanceID); // session must know toolkit workspace
+        // created session ok
+        aNewSessionH = (SessionH)sessionHandleP;        
+        return LOCERR_OK;
+      }
+    }
+    SYSYNC_CATCH (...)
+       // error creating session
+      if (sessionHandleP) delete sessionHandleP;
+      return LOCERR_EXCEPTION;
+    SYSYNC_ENDCATCH
+  }
+  return LOCERR_WRONGUSAGE;
+}
+
+
+/// @brief open session specific runtime parameter/settings key
+/// @note key handle obtained with this call must be closed BEFORE SESSION IS CLOSED!
+/// @param aNewKeyH[out] receives the opened key's handle on success
+/// @param aSessionH[in] session handle obtained with OpenSession
+/// @param aMode[in] the open mode
+/// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure
+TSyError TServerEngineInterface::OpenSessionKey(SessionH aSessionH, KeyH &aNewKeyH, uInt16 aMode)
+{
+       if (!aSessionH) return LOCERR_WRONGUSAGE;
+  TEngineServerSessionHandle *sessionHandleP = reinterpret_cast<TEngineServerSessionHandle *>(aSessionH);
+  // create settings key for the session
+  aNewKeyH = (KeyH)sessionHandleP->fServerSessionP->newSessionKey(this);
+  // done
+  return LOCERR_OK;
+}
+
+        
+/// @brief Close a session
+/// @note  terminates and destroys the session (if not already terminated)
+/// @param aSessionH[in] session handle obtained with OpenSession
+/// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure
+TSyError TServerEngineInterface::CloseSession(SessionH aSessionH)
+{
+       if (!aSessionH) return LOCERR_WRONGUSAGE;
+  TSyError sta = LOCERR_OK;
+  TEngineServerSessionHandle *sessionHandleP = reinterpret_cast<TEngineServerSessionHandle *>(aSessionH);
+  TSyncAgent *serverSessionP = sessionHandleP->fServerSessionP;
+  if (serverSessionP) {
+       // session still exists
+    if (!serverSessionP->isAborted()) {
+       // if not already aborted otherwise (e.g. by writing "abortstatus" in session key), let it be "timeout"
+       serverSessionP->AbortSession(408, true);
+    }
+    SYSYNC_TRY {
+      // - terminate (might hang a while until subthreads properly terminate)
+      serverSessionP->TerminateSession();
+      // - delete
+      sessionHandleP->fServerSessionP = NULL; // consider deleted, whatever happens
+      delete serverSessionP; // might hang until subthreads have terminated
+    }
+    SYSYNC_CATCH(...)
+      sessionHandleP->fServerSessionP = NULL; // consider deleted, even if failed
+      sta = LOCERR_EXCEPTION;
+    SYSYNC_ENDCATCH
+  }  
+  // forget session handle (and toolkit instance)
+  delete sessionHandleP;
+  // done
+  return LOCERR_OK;
+}
+       
+
+/// @brief Executes sync session or other sync related activity step by step
+/// @param aSessionH[in] session handle obtained with OpenSession
+/// @param aStepCmd[in/out] step command (STEPCMD_xxx):
+///        - tells caller to send or receive data or end the session etc.
+///        - instructs engine to suspend or abort the session etc.
+/// @param aInfoP[in] pointer to a TEngineProgressInfo structure, NULL if no progress info needed
+/// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure    
+TSyError TServerEngineInterface::SessionStep(SessionH aSessionH, uInt16 &aStepCmd,  TEngineProgressInfo *aInfoP)
+{
+       if (!aSessionH) return LOCERR_WRONGUSAGE;
+  TEngineServerSessionHandle *sessionHandleP = reinterpret_cast<TEngineServerSessionHandle *>(aSessionH);
+  TSyncAgent *serverSessionP = sessionHandleP->fServerSessionP;
+
+  // preprocess general step codes
+  switch (aStepCmd) {
+    case STEPCMD_TRANSPFAIL :
+      // directly abort
+      serverSessionP->AbortSession(LOCERR_TRANSPFAIL,true);
+      goto abort;
+    case STEPCMD_TIMEOUT :
+      // directly abort
+      serverSessionP->AbortSession(408,true);
+    abort:
+      aStepCmd = STEPCMD_STEP; // convert to normal step
+      break;
+  }
+  // let server session handle it
+  sessionHandleP->fSessionStatus = serverSessionP->SessionStep(aStepCmd, aInfoP);
+  // return step status
+  return sessionHandleP->fSessionStatus;
+} // TServerEngineInterface::SessionStep
+
+
+/// @brief returns the SML instance for a given session handle
+///   (internal helper to allow TEngineInterface to provide the access to the SyncML buffer)
+InstanceID_t TServerEngineInterface::getSmlInstanceOfSession(SessionH aSessionH)
+{
+       if (!aSessionH) return 0; // something wrong with session handle -> no SML instance
+  TEngineServerSessionHandle *sessionHandleP = reinterpret_cast<TEngineServerSessionHandle *>(aSessionH);
+  TSyncAgent *serverSessionP = sessionHandleP->fServerSessionP;
+  if (!serverSessionP) return 0; // something wrong with session handle -> no SML instance
+  // return SML instance associated with that session
+  return serverSessionP->getSmlWorkspaceID();
+} // TServerEngineInterface::getSmlInstanceOfSession
+
+
+} // namespace sysync
+
+// eof
diff --git a/src/synthesis/src/Transport_interfaces/engine/enginesessiondispatch.h b/src/synthesis/src/Transport_interfaces/engine/enginesessiondispatch.h
new file mode 100644 (file)
index 0000000..e2ed6cf
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ *  TEngineSessionDispatch
+ *    Server library specific descendant of TSyncSessionDispatch
+ *
+ *  Copyright (c) 2009-2009 by Synthesis AG (www.synthesis.ch)
+ *
+ *  2009-02-06 : luz : Created
+ *
+ */  
+#ifndef ENGINESESSIONDISPATCH_H
+#define ENGINESESSIONDISPATCH_H
+
+// required headers
+#include "syncappbase.h"
+#include "syncagent.h"
+
+
+namespace sysync {
+
+
+// Engine module class
+class TServerEngineInterface :
+  public TEngineInterface
+{
+  typedef TEngineInterface inherited;
+public:
+  // constructor
+  TServerEngineInterface() {};
+
+  // no appbase factory at this level (must be implemented in non-virtual descendants)
+  virtual TSyncAppBase *newSyncAppBase(void) = 0;
+
+  // Running a Server Sync Session
+  // -----------------------------
+
+  /// @brief Open a session
+  /// @param aNewSessionH[out] receives session handle for all session execution calls
+  /// @param aSelector[in] selector, depending on session type.
+  /// @param aSessionName[in] a text name/id to identify a session, useage depending on session type.
+  /// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure
+  virtual TSyError OpenSessionInternal(SessionH &aNewSessionH, uInt32 aSelector, cAppCharP aSessionName);
+
+  /// @brief open session specific runtime parameter/settings key
+  /// @note key handle obtained with this call must be closed BEFORE SESSION IS CLOSED!
+  /// @param aNewKeyH[out] receives the opened key's handle on success
+  /// @param aSessionH[in] session handle obtained with OpenSession
+  /// @param aMode[in] the open mode
+  /// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure
+  virtual TSyError OpenSessionKey(SessionH aSessionH, KeyH &aNewKeyH, uInt16 aMode);
+          
+  /// @brief Close a session
+  /// @note  It depends on session type if this also destroys the session or if it may persist and can be re-opened.
+  /// @param aSessionH[in] session handle obtained with OpenSession
+  /// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure
+  virtual TSyError CloseSession(SessionH aSessionH);
+
+  /// @brief Executes sync session or other sync related activity step by step
+  /// @param aSessionH[in] session handle obtained with OpenSession
+  /// @param aStepCmd[in/out] step command (STEPCMD_xxx):
+  ///        - tells caller to send or receive data or end the session etc.
+  ///        - instructs engine to suspend or abort the session etc.
+  /// @param aInfoP[in] pointer to a TEngineProgressInfo structure, NULL if no progress info needed
+  /// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure    
+  virtual TSyError SessionStep(SessionH aSessionH, uInt16 &aStepCmd,  TEngineProgressInfo *aInfoP = NULL);
+
+protected:
+
+  /// @brief returns the SML instance for a given session handle
+  virtual InstanceID_t getSmlInstanceOfSession(SessionH aSessionH);
+
+}; // TServerEngineInterface
+
+
+
+// engine client root config
+class TEngineServerRootConfig : public TRootConfig
+{
+  typedef TRootConfig inherited;
+public:
+  TEngineServerRootConfig(TSyncAppBase *aSyncAppBaseP) : inherited(aSyncAppBaseP) {};
+  // factory methods
+  virtual void installCommConfig(void);
+  // Config parsing
+  #ifndef HARDCODED_CONFIG
+  virtual bool parseCommConfig(const char **aAttributes, sInt32 aLine);
+  #endif    
+}; // TEngineClientRootConfig
+
+
+// engine server transport config
+class TEngineServerCommConfig: public TCommConfig
+{
+  typedef TCommConfig inherited;
+public:
+  TEngineServerCommConfig(TConfigElement *aParentElementP);
+  virtual ~TEngineServerCommConfig();
+  // config vars
+  bool fSessionIDCGI;
+  string fSessionIDCGIPrefix;
+protected:
+  // check config elements
+  #ifndef HARDCODED_CONFIG
+  virtual bool localStartElement(const char *aElementName, const char **aAttributes, sInt32 aLine);
+  #endif
+  virtual void clear();
+  virtual void localResolve(bool aLastPass);
+}; // TXPTCommConfig
+
+
+// forward declarations
+class TSyncAgent;
+class TSyncSession;
+
+
+
+// session handle for engine sessions
+// containing engine-specific session status
+class TEngineServerSessionHandle
+{
+public:
+       TEngineServerSessionHandle(TServerEngineInterface *aServerEngineInterface);
+  virtual ~TEngineServerSessionHandle();
+  // the server engine interface
+  TServerEngineInterface *fServerEngineInterface;
+  // the session itself
+       TSyncAgent *fServerSessionP;
+  // the toolkit instance used by the session
+  InstanceID_t fSmlInstanceID;
+  // status of the session
+  localstatus fSessionStatus;
+};
+
+
+// AppBase class for all server engines (libararies with API to build custom servers)
+// Note: unlike non-engine servers, the server library bypasses TSyncSessionDispatch
+//       completely. All actual session dispatch, thread locking, session timeout
+//       stuff must be implemented outside the library for engine-based servers.
+class TEngineSessionDispatch : public TSyncAppBase {
+  typedef TSyncAppBase inherited;
+public:
+  // constructors/destructors
+  TEngineSessionDispatch();
+  virtual ~TEngineSessionDispatch();
+  // handlers for SyncML toolkit callbacks
+  // - Start/End Message: identifies Session, and creates new or assigns existing session
+  Ret_t StartMessage(
+    InstanceID_t aSmlWorkspaceID, // SyncML toolkit workspace instance ID
+    VoidPtr_t aUserData, // pointer to a TSyncAgent descendant
+    SmlSyncHdrPtr_t aContentP // SyncML tookit's decoded form of the <SyncHdr> element
+  );
+  // - Handle exception happening while decoding commands for a session
+  virtual Ret_t HandleDecodingException(TSyncSession *aSessionP, const char *aRoutine, exception *aExceptionP);
+  // - combine URI and session ID to make a RespURI according to transport
+  virtual void generateRespURI(
+    string &aRespURI,
+    cAppCharP aLocalURI,
+    cAppCharP aSessionID
+  );
+}; // TEngineSessionDispatch
+
+} // namespace sysync
+
+#endif // ENGINESESSIONDISPATCH_H
+
+
+// eof
index 68e4aba..30d56d7 100644 (file)
@@ -16,7 +16,7 @@ SIZE="size"
 
 CFLAGS=  -m32 -Wall -O2 -c -MMD
 LDFLAGS= -m32
-MAKEFILE= "sysync_linux.mk"
+MAKEFILE= "client_engine_linux.mk"
 
 
 SYNCML_TK_SML=\
@@ -134,7 +134,7 @@ CLIENTENGINE=\
   sysync_SDK/Sources/enginemodulebase.cpp\
   sysync/engineentry.cpp\
   sysync/engineinterface.cpp\
-  sysync/syncclient.cpp\
+  sysync/syncagent.cpp\
   sysync/syncclientbase.cpp
 
 ODBC_DB=\
diff --git a/src/synthesis/src/combi_engine_linux.mk b/src/synthesis/src/combi_engine_linux.mk
new file mode 100644 (file)
index 0000000..049d282
--- /dev/null
@@ -0,0 +1,236 @@
+# Makefile generated by Metrowerks CodeWarrior IDE
+# adapted for standalone client library use 2009/02/05 by bfo@synthesis.ch
+# adapted for standalone server library use 2009/09/22 by luz@synthesis.ch
+# adapted for standalone combi (client+server) library use 2009/10/03 by luz@synthesis.ch
+
+all:         combiEngine
+clean: clean_combiEngine
+
+
+####### common definitions
+WD=$(shell echo `pwd`)
+WD_OBJS=$(WD)/../OBJS
+
+CC="gcc"
+LD="gcc"
+AR="ar -crs"
+SIZE="size"
+
+CFLAGS=  -m32 -Wall -O2 -c -MMD
+LDFLAGS= -m32
+MAKEFILE= "combi_engine_linux.mk"
+
+
+SYNCML_TK_SML=\
+  syncml_tk/src/sml/lib/all/liblock.c\
+  syncml_tk/src/sml/lib/all/libmem.c\
+  syncml_tk/src/sml/lib/all/libstr.c\
+  syncml_tk/src/sml/lib/all/libutil.c\
+  syncml_tk/src/sml/mgr/all/mgr.c\
+  syncml_tk/src/sml/mgr/all/mgrcmdbuilder.c\
+  syncml_tk/src/sml/mgr/all/mgrcmddispatcher.c\
+  syncml_tk/src/sml/mgr/all/mgrinstancelist.c\
+  syncml_tk/src/sml/mgr/all/mgrinstancemgr.c\
+  syncml_tk/src/sml/mgr/all/mgrutil.c\
+  syncml_tk/src/sml/xlt/all/xltdec.c\
+  syncml_tk/src/sml/xlt/all/xltdecwbxml.c\
+  syncml_tk/src/sml/xlt/all/xltdecxml.c\
+  syncml_tk/src/sml/xlt/all/xltdevinf.c\
+  syncml_tk/src/sml/xlt/all/xltenc.c\
+  syncml_tk/src/sml/xlt/all/xltenccom.c\
+  syncml_tk/src/sml/xlt/all/xltencwbxml.c\
+  syncml_tk/src/sml/xlt/all/xltencxml.c\
+  syncml_tk/src/sml/xlt/all/xltmetinf.c\
+  syncml_tk/src/sml/xlt/all/xlttags.c\
+  syncml_tk/src/sml/xlt/all/xltutilstack.c
+
+EXPAT=\
+  expat/xmltok/xmltok.c\
+  expat/xmltok/xmlrole.c\
+  expat/xmlparse/xmlparse.c
+
+ZLIB=\
+  zlib/adler32.c\
+  zlib/compress.c\
+  zlib/crc32.c\
+  zlib/deflate.c\
+  zlib/gzio.c\
+  zlib/infback.c\
+  zlib/inffast.c\
+  zlib/inflate.c\
+  zlib/inftrees.c\
+  zlib/trees.c\
+  zlib/uncompr.c\
+  zlib/zutil.c
+
+C_BASICS=\
+  $(SYNCML_TK_SML)\
+  $(EXPAT)\
+  platform_adapters/linux/platform_exec.c\
+  sysync_SDK/Sources/SDK_util.c
+
+PLATFORM=\
+  platform_adapters/linux/configfiles.cpp\
+  platform_adapters/linux/profiling.cpp\
+  platform_adapters/linux/platform_time.cpp\
+  platform_adapters/unix_common/platform_mutex.cpp\
+  platform_adapters/sysyncinit.cpp
+
+PLATFORM_EXT=\
+  $(PLATFORM)\
+  platform_adapters/linux/platform_DLL.cpp\
+  platform_adapters/unix_common/platform_thread.cpp\
+  platform_adapters/unix_common/platform_file.cpp
+
+SYSYNC=\
+  sysync/sysync_utils.cpp\
+  sysync/sysync_b64.cpp\
+  sysync/sysync_md5.cpp\
+  sysync/syncsession.cpp\
+  sysync/syncappbase.cpp\
+  sysync/lineartime.cpp\
+  sysync/iso8601.cpp\
+  sysync/stringutils.cpp\
+  sysync/superdatastore.cpp\
+  sysync/scriptcontext.cpp\
+  sysync/itemfield.cpp\
+  sysync/mimediritemtype.cpp\
+  sysync/mimedirprofile.cpp\
+  sysync/multifielditem.cpp\
+  sysync/multifielditemtype.cpp\
+  sysync/remotedatastore.cpp\
+  sysync/syncitem.cpp\
+  sysync/syncitemtype.cpp\
+  sysync/simpleitem.cpp\
+  sysync/synccommand.cpp\
+  sysync/syncdatastore.cpp\
+  sysync/textitemtype.cpp\
+  sysync/vcalendaritemtype.cpp\
+  sysync/vcarditemtype.cpp\
+  sysync/syncexception.cpp\
+  sysync/configelement.cpp\
+  sysync/sysync_crc16.cpp\
+  sysync/timezones.cpp\
+  sysync/rrules.cpp\
+  sysync/localengineds.cpp\
+  sysync/debuglogger.cpp\
+  sysync/textprofile.cpp\
+  sysync/dataobjtype.cpp\
+  sysync/stdlogicds.cpp\
+  sysync/stdlogicagent.cpp\
+  sysync/customimplagent.cpp\
+  sysync/customimplds.cpp\
+  sysync/vtimezone.cpp
+
+COMBIENGINE=\
+  $(SYSYNC)\
+  syncapps/serverEngine_custom/serverengine_custom_Base.cpp\
+  syncapps/clientEngine_custom/clientengine_custom_Base.cpp\
+  Transport_interfaces/engine/enginesessiondispatch.cpp\
+  Transport_interfaces/engine/engineclientbase.cpp\
+  sysync_SDK/Sources/enginemodulebase.cpp\
+  sysync/engineentry.cpp\
+  sysync/engineinterface.cpp\
+  sysync/syncclientbase.cpp\
+  sysync/syncagent.cpp
+
+
+ODBC_DB=\
+  DB_interfaces/odbc_db/odbcapiagent.cpp\
+  DB_interfaces/odbc_db/odbcapids.cpp
+
+API_DB=\
+  DB_interfaces/api_db/pluginapiagent.cpp\
+  DB_interfaces/api_db/pluginapids.cpp\
+  DB_interfaces/api_db/dbapi.cpp\
+  DB_interfaces/api_db/DLL_interface.cpp\
+  DB_interfaces/api_db/sync_dbapiconnect.cpp\
+  sysync_SDK/Sources/SDK_support.cpp\
+  sysync_SDK/DB_Interfaces/text_db/sync_dbapi_text.cpp\
+  sysync_SDK/Sources/admindata.cpp\
+  sysync_SDK/Sources/dbitem.cpp\
+  sysync_SDK/Sources/blobs.cpp
+
+
+# --------------------------------------------------------
+INCLUDE_PLATFORM=\
+  -I platform_adapters/linux/\
+  -I platform_adapters/unix_common/\
+  -I platform_adapters/
+
+INCLUDE_SYNCML_TK_SML=\
+  -I syncml_tk/src/sml/inc/\
+  -I syncml_tk/src/sml/lib/inc/\
+  -I syncml_tk/src/sml/lib/\
+  -I syncml_tk/src/sml/mgr/inc/\
+  -I syncml_tk/src/sml/mgr/\
+  -I syncml_tk/src/sml/wsm/inc/\
+  -I syncml_tk/src/sml/xlt/inc/\
+  -I syncml_tk/src/sml/xlt/all/
+
+INCLUDE_EXPAT=\
+  -I expat/xmltok/\
+  -I expat/xmlparse/
+
+INCLUDE_COMBIENGINE=\
+  -I syncapps/serverEngine_custom/\
+  -I syncapps/clientEngine_custom/\
+  -I Transport_interfaces/engine/\
+  -I sysync_SDK/Sources\
+  -I sysync/\
+  -I ./
+
+
+############################
+#######  TARGET: combiEngine
+############################
+WD_OBJS_combiEngine=$(WD_OBJS)/combiEngine
+
+c_SRC_combiEngine=\
+  $(C_BASICS) $(ZLIB)
+
+cpp_SRC_combiEngine=\
+  $(PLATFORM_EXT)\
+  $(COMBIENGINE)\
+  $(ODBC_DB)\
+  $(API_DB)
+
+OBJS_combiEngine+=  $(c_SRC_combiEngine:.c=.c.o)
+OBJS_combiEngine+=$(cpp_SRC_combiEngine:.cpp=.cpp.o)
+
+INCLUDE_combiEngine=\
+ -include Targets/ReleasedProducts/combiEngine_opensource_linux/combiengine_opensource_linux_prefix.h\
+ -I Targets/ReleasedProducts/combiEngine_opensource_linux/\
+ $(INCLUDE_PLATFORM)\
+ $(INCLUDE_SYNCML_TK_SML)\
+ $(INCLUDE_EXPAT)\
+ $(INCLUDE_COMBIENGINE)\
+ -I DB_interfaces/odbc_db/\
+ -I DB_interfaces/api_db/\
+ -I SQLite/\
+ -I zlib/\
+ -I /usr/include/
+
+combiEngine:
+       $(MAKE) -f $(MAKEFILE) sysync_combi_engine.so TARGET=sysync_combi_engine.so \
+  WDOP="$(WD_OBJS_combiEngine)"\
+  OBJS="$(addprefix $(WD_OBJS_combiEngine)/,$(OBJS_combiEngine))"\
+  LIBS="-L/usr/lib32 -L/usr/lib -lstdc++ -lpthread -lltdl -lpcre"\
+  INCL="$(INCLUDE_combiEngine)"
+
+sysync_combi_engine.so: $(OBJS)
+       $(LD) -shared -Xlinker -soname=sysync_combi_engine $(LDFLAGS) $(OBJS) $(LIBS) \
+       -o sysync_SDK/bin/Linux/sysync_combi_engine.so
+
+ifeq ($(TARGET), sysync_combi_engine.so)
+$(WDOP)/%.c.o:   $(WD)/%.c
+       mkdir -p $(dir $@)
+       $(CC) -fPIC $(CFLAGS) $(INCL) $< -o $@
+
+$(WDOP)/%.cpp.o: $(WD)/%.cpp
+       mkdir -p $(dir $@)
+       $(CC) -fPIC $(CFLAGS) $(INCL) $< -o $@
+endif
+
+clean_combiEngine:
+       rm -f -r $(WD_OBJS_combiEngine)
index 0ab7b1d..988819c 100755 (executable)
@@ -14,16 +14,12 @@ enginemodulebridge.h
 stringutil.cpp
 stringutil.h
 target_options.h
+san.cpp
+san.h
 timeutil.cpp
 timeutil.h
 UI_util.cpp
 UI_util.h
-blobs.cpp
-blobs.h
-dbitem.cpp
-dbitem.h
-admindata.cpp
-admindata.h
 EOF
 
 # The distinction between client and server files is not
@@ -44,6 +40,12 @@ EOF
 
 # files needed exclusively for the server engine
 cat > SERVER_FILES <<EOF
+admindata.cpp
+admindata.h
+dbitem.cpp
+dbitem.h
+blobs.cpp
+blobs.h
 enginesessiondispatch.cpp
 syncserver.cpp
 EOF
@@ -53,14 +55,16 @@ cat > EXTRA_FILES <<EOF
 clientprovisioning_inc.cpp
 .*_tables_inc.cpp
 syncsessiondispatch.cpp
+platform_thread.cpp
 enginestubs.c
-sysync/syncserver.cpp
 EOF
 
 # files to be included in libsynthesis
 cat EXTRA_FILES SDK_FILES > EXCLUDE_FILES
 LIBSYNTHESIS_SOURCES=`find ${ENGINE_SOURCES} \
      syncapps/clientEngine_custom \
+     syncapps/serverEngine_custom \
+     sysync_SDK/DB_Interfaces/text_db \
      \( -name '*.cpp' -o -name '*.[ch]' \) |
     grep -v -E -f EXCLUDE_FILES`
 LIBSYNTHESIS_SOURCES=`echo $LIBSYNTHESIS_SOURCES`
@@ -85,8 +89,8 @@ LIBSYNTHESISSDK_SOURCES_ONLY=`echo $LIBSYNTHESISSDK_SOURCES_ONLY`
 # files needed in libsmltk
 LIBSMLTK_SOURCES=`find syncml_tk \
      \( -name '*.cpp' -o -name '*.[ch]' \) \
-     \! \( -path syncml_tk/src/sml/\*/palm/\* -o \
-           -path syncml_tk/src/sml/\*/win/\* \)`
+     \! \( -wholename syncml_tk/src/sml/\*/palm/\* -o \
+           -wholename syncml_tk/src/sml/\*/win/\* \)`
 LIBSMLTK_SOURCES=`echo $LIBSMLTK_SOURCES`
 
 # header files required for using libsynthesissdk,
index 8d2b378..3ab8e73 100644 (file)
@@ -8,6 +8,22 @@
 #ifndef GLOBAL_OPTIONS_H
 #define GLOBAL_OPTIONS_H
 
+
+// the following should be defined BEFORE including this file
+// - SYSYNC_CLIENT : defined if client functionality should be included
+// - SYSYNC_SERVER : defined if server functionality should be included
+//   If not defined, and SYSYNC_CLIENT is also not defined, build
+//   defaults to SYSYNC_SERVER
+// - platform defines, like MACOSX, MOBOSX, LINUX, WINCE, _WIN32
+//   __PALM_OS__, __EPOC_OS__ etc.
+// - RELEASE_VERSION : define in targets that are real product releases
+//   not internal debug/test/experimental releases
+// - RELEASE_SYDEBUG : define the debug level for RELEASE_VERSION
+//   (0=no debug code at all, 1=basic debug, 2=extended, 3=developer only)
+//   Non-release versions (RELEASE_VERSION undefined) usually have
+//   a debug level of 2 or 3 (defined in target or product options).
+
+
 // signal that we are compiling with the SYSYNC engine
 #define SYSYNC_ENGINE 1
 
 #endif
 
 #ifndef SYSYNC_VERSION_MINOR
-#define SYSYNC_VERSION_MINOR        2
-#define SYSYNC_VERSION_MINOR_TXT   "2"
+#define SYSYNC_VERSION_MINOR        3
+#define SYSYNC_VERSION_MINOR_TXT   "3"
 #endif
 
 #ifndef SYSYNC_SUBVERSION
-#define SYSYNC_SUBVERSION           1
-#define SYSYNC_SUBVERSION_TXT      "1"
+#define SYSYNC_SUBVERSION           0
+#define SYSYNC_SUBVERSION_TXT      "0"
 #endif
 
 #ifndef SYSYNC_BUILDNUMBER
@@ -68,6 +84,8 @@
     #define SYSYNC_PLATFORM_NAME "iPhoneOS"
   #elif defined(MACOSX)
     #define SYSYNC_PLATFORM_NAME "MacOSX"
+  #elif defined(ANDROID)
+    #define SYSYNC_PLATFORM_NAME "Android"
   #elif defined(LINUX)
     #define SYSYNC_PLATFORM_NAME "Linux"
   #elif defined(__PALM_OS__)
 // ###################################################################
 
 
+// server or client macros
+// - make sure we have either SYSYNC_CLIENT, SYSYNC_SERVER or both
+// - if combined build, define SERVER_CLIENT_BUILD as well
+#if defined(SYSYNC_CLIENT) && defined(SYSYNC_SERVER)
+       #define SERVER_CLIENT_BUILD 1
+#elif !defined(SYSYNC_CLIENT)
+       #define SYSYNC_SERVER 1
+#endif
+// build differentiation macros
+#ifdef SERVER_CLIENT_BUILD
+       // dynamically switching between server and client
+  #define IS_CLIENT (!getSyncAppBase()->isServer())
+  #define IS_SERVER (getSyncAppBase()->isServer())
+#else
+       // static, built as either server or client
+  #ifdef SYSYNC_CLIENT
+       // client
+    #define IS_CLIENT 1
+    #define IS_SERVER 0
+  #else
+       // server
+    #define IS_CLIENT 0
+    #define IS_SERVER 1
+  #endif
+#endif
+
+
 // build type
 #ifdef ENGINE_LIBRARY
   // SySync engine with API
   #define DIRECT_APPBASE_GLOBALACCESS 1
 #endif
 
+// binfile layer specifics
+#if defined(BASED_ON_BINFILE_CLIENT) && !defined(SYSYNC_SERVER)
+       // client-only build with binfiles included -> binfile must be always active
+  // (and customimpl does not need a lot of stuff it would otherwise include)
+       #define BINFILE_ALWAYS_ACTIVE 1
+#endif
+
 
 // default datatype support
 #define MIMEDIR_SUPPORT 1
index 96bbf50..2eafc22 100755 (executable)
@@ -36,7 +36,11 @@ static bool getOSVersion(string &aOSVersion)
 static bool getHardwareName(string &aHardwareName)
 {
   // Obtain Device name
+  #ifdef ANDROID
+  aHardwareName="Android Device";
+  #else
   aHardwareName="Linux PC";
+  #endif
   return true;
 } // getHardwareName
 
@@ -101,7 +105,11 @@ bool getPlatformString(TPlatformStringID aStringID, string &aString)
       // My specific subdirectory for storing my app data/prefs
       userInfoP = getpwuid(getuid());
       aString = userInfoP->pw_dir; // user home dir
+      #ifdef ANDROID
+      aString += "/data/com.sysync/" APPDATA_SUBDIR; // application specific subdir for android
+      #else
       aString += "/.sysync/" APPDATA_SUBDIR; // application specific subdir
+      #endif
       break;
     #endif
     /*
@@ -127,7 +135,10 @@ bool getPlatformString(TPlatformStringID aStringID, string &aString)
 
 
 extern "C" {
+  #ifndef ANDROID
   #include <ctime>
+  #endif
+
   #include <sys/stat.h>
 }
 
@@ -232,7 +243,11 @@ bool getLocalDeviceID(string &aURI)
       hostName=szHostname; // just name of machine
   }
   // generate URI from name
+  #ifdef ANDROID
+  aURI="android:";
+  #else
   aURI="linux:"; // %%% SCTS does not like http:// here, so we take os:xxxx
+  #endif
   // add name of this machine (fully qualified if possible)
   aURI+=hostName;
   // this is more or less unique
index 3f5bb63..ebc80a0 100755 (executable)
@@ -63,6 +63,8 @@ public:
     string      aName= aDLLName;
 
     do {
+      aDLL = dlopen(aName.c_str(), RTLD_LAZY); if (!dlerror()) break;      
+
       aName+= DSuff;
       aDLL = dlopen(aName.c_str(), RTLD_LAZY); if (!dlerror()) break;
 
index 1a53c82..4da5cf1 100755 (executable)
 
 // Linux uses standard c time stuff
 //#warning "probably better use <cmath> here"
+#ifndef ANDROID
 #include <climits>
 #include <cstdarg>
 #include <cstdlib>
+#endif
+
 #include <cstdio>
 #include <cstring>
 // - Linux specific time stuff
 #include <sys/time.h>
 // - we need some library extras
 #define __USE_MISC 1
+#ifndef ANDROID
 #include <ctime>
+#endif
 
 namespace sysync {
 
index 26c6dde..487eaf0 100755 (executable)
@@ -34,9 +34,9 @@ namespace sysync {
 
 
 // get id of the running process
-uInt32 myProcessID();
+uIntArch myProcessID();
 // get id of the running thread
-uInt32 myThreadID();
+uIntArch myThreadID();
 
 
 class TThreadObject; // forward
@@ -55,12 +55,12 @@ public:
   // starts thread (or re-starts it again after termination)
   bool launch(
     TThreadFunc aThreadFunc=NULL, // the function to execute in the thread
-    uInt32 aThreadFuncParam=0, // a parameter to pass to the thread
+    uIntArch aThreadFuncParam=0, // a parameter to pass to the thread
     size_t aStackSize=0, // if 0, default stack size is used
     bool aAutoDispose=false // if true, the thread object will dispose itself when thread has finished running
   );
   // get thread ID
-  uInt32 getid(void);
+  uIntArch getid(void);
   // soft-terminates thread (sets a flag which requests execute() to terminate
   void terminate(void) { fTerminationRequested=true; };
   // hard (emergency) terminate (aborts processing on the OS level)
index fb915da..25829c1 100755 (executable)
 
 namespace sysync {
 
-
 //  get id of the running process
-uInt32 myProcessID() {
-  return (uInt32)getpid();
+uIntArch myProcessID() {
+  return (uIntArch)getpid();
 } // myProcessID
 
 
 // get id of the running thread
-uInt32 myThreadID() {
-  return (uInt32)pthread_self();
+uIntArch myThreadID() {
+  return (uIntArch)pthread_self();
 } // myThreadID
 
 
@@ -96,7 +95,7 @@ TThreadObject::~TThreadObject()
 // contain the platform error code for the failure to start the thread
 bool TThreadObject::launch(
   TThreadFunc aThreadFunc, // the function to execute in the thread
-  uInt32 aThreadFuncParam, // a parameter to pass to the thread
+  uIntArch aThreadFuncParam, // a parameter to pass to the thread
   size_t aStackSize,       // if 0, default stack size is used
   bool aAutoDispose        // if true, the thread object will dispose itself when thread has finished running
 )
@@ -135,8 +134,8 @@ bool TThreadObject::launch(
 } // TThreadObject::launch
 
 
-uInt32 TThreadObject::getid(void) {
-  return (uInt32)fPosixThread;
+uIntArch TThreadObject::getid(void) {
+  return (uIntArch)fPosixThread;
 } // TThreadObject::getid
 
 
diff --git a/src/synthesis/src/server_engine_linux.mk b/src/synthesis/src/server_engine_linux.mk
new file mode 100644 (file)
index 0000000..060a044
--- /dev/null
@@ -0,0 +1,230 @@
+# Makefile generated by Metrowerks CodeWarrior IDE
+# adapted for standalone client library use 09/02/05 by bfo@synthesis.ch
+# adapted for standalone server library use 09/09/22 by luz@synthesis.ch
+
+all:         serverEngine
+clean: clean_serverEngine
+
+
+####### common definitions
+WD=$(shell echo `pwd`)
+WD_OBJS=$(WD)/../OBJS
+
+CC="gcc"
+LD="gcc"
+AR="ar -crs"
+SIZE="size"
+
+CFLAGS=  -m32 -Wall -O2 -c -MMD
+LDFLAGS= -m32
+MAKEFILE= "server_engine_linux.mk"
+
+
+SYNCML_TK_SML=\
+  syncml_tk/src/sml/lib/all/liblock.c\
+  syncml_tk/src/sml/lib/all/libmem.c\
+  syncml_tk/src/sml/lib/all/libstr.c\
+  syncml_tk/src/sml/lib/all/libutil.c\
+  syncml_tk/src/sml/mgr/all/mgr.c\
+  syncml_tk/src/sml/mgr/all/mgrcmdbuilder.c\
+  syncml_tk/src/sml/mgr/all/mgrcmddispatcher.c\
+  syncml_tk/src/sml/mgr/all/mgrinstancelist.c\
+  syncml_tk/src/sml/mgr/all/mgrinstancemgr.c\
+  syncml_tk/src/sml/mgr/all/mgrutil.c\
+  syncml_tk/src/sml/xlt/all/xltdec.c\
+  syncml_tk/src/sml/xlt/all/xltdecwbxml.c\
+  syncml_tk/src/sml/xlt/all/xltdecxml.c\
+  syncml_tk/src/sml/xlt/all/xltdevinf.c\
+  syncml_tk/src/sml/xlt/all/xltenc.c\
+  syncml_tk/src/sml/xlt/all/xltenccom.c\
+  syncml_tk/src/sml/xlt/all/xltencwbxml.c\
+  syncml_tk/src/sml/xlt/all/xltencxml.c\
+  syncml_tk/src/sml/xlt/all/xltmetinf.c\
+  syncml_tk/src/sml/xlt/all/xlttags.c\
+  syncml_tk/src/sml/xlt/all/xltutilstack.c
+
+EXPAT=\
+  expat/xmltok/xmltok.c\
+  expat/xmltok/xmlrole.c\
+  expat/xmlparse/xmlparse.c
+
+ZLIB=\
+  zlib/adler32.c\
+  zlib/compress.c\
+  zlib/crc32.c\
+  zlib/deflate.c\
+  zlib/gzio.c\
+  zlib/infback.c\
+  zlib/inffast.c\
+  zlib/inflate.c\
+  zlib/inftrees.c\
+  zlib/trees.c\
+  zlib/uncompr.c\
+  zlib/zutil.c
+
+C_BASICS=\
+  $(SYNCML_TK_SML)\
+  $(EXPAT)\
+  platform_adapters/linux/platform_exec.c\
+  sysync_SDK/Sources/SDK_util.c
+
+PLATFORM=\
+  platform_adapters/linux/configfiles.cpp\
+  platform_adapters/linux/profiling.cpp\
+  platform_adapters/linux/platform_time.cpp\
+  platform_adapters/unix_common/platform_mutex.cpp\
+  platform_adapters/sysyncinit.cpp
+
+PLATFORM_EXT=\
+  $(PLATFORM)\
+  platform_adapters/linux/platform_DLL.cpp\
+  platform_adapters/unix_common/platform_thread.cpp\
+  platform_adapters/unix_common/platform_file.cpp
+
+SYSYNC=\
+  sysync/sysync_utils.cpp\
+  sysync/sysync_b64.cpp\
+  sysync/sysync_md5.cpp\
+  sysync/syncsession.cpp\
+  sysync/syncappbase.cpp\
+  sysync/lineartime.cpp\
+  sysync/iso8601.cpp\
+  sysync/stringutils.cpp\
+  sysync/superdatastore.cpp\
+  sysync/scriptcontext.cpp\
+  sysync/itemfield.cpp\
+  sysync/mimediritemtype.cpp\
+  sysync/mimedirprofile.cpp\
+  sysync/multifielditem.cpp\
+  sysync/multifielditemtype.cpp\
+  sysync/remotedatastore.cpp\
+  sysync/syncitem.cpp\
+  sysync/syncitemtype.cpp\
+  sysync/simpleitem.cpp\
+  sysync/synccommand.cpp\
+  sysync/syncdatastore.cpp\
+  sysync/textitemtype.cpp\
+  sysync/vcalendaritemtype.cpp\
+  sysync/vcarditemtype.cpp\
+  sysync/syncexception.cpp\
+  sysync/configelement.cpp\
+  sysync/sysync_crc16.cpp\
+  sysync/timezones.cpp\
+  sysync/rrules.cpp\
+  sysync/localengineds.cpp\
+  sysync/debuglogger.cpp\
+  sysync/textprofile.cpp\
+  sysync/dataobjtype.cpp\
+  sysync/stdlogicds.cpp\
+  sysync/stdlogicagent.cpp\
+  sysync/customimplagent.cpp\
+  sysync/customimplds.cpp\
+  sysync/vtimezone.cpp
+
+SERVERENGINE=\
+  $(SYSYNC)\
+  syncapps/serverEngine_custom/serverengine_custom_Base.cpp\
+  Transport_interfaces/engine/enginesessiondispatch.cpp\
+  sysync_SDK/Sources/enginemodulebase.cpp\
+  sysync/engineentry.cpp\
+  sysync/engineinterface.cpp\
+  sysync/syncagent.cpp
+
+ODBC_DB=\
+  DB_interfaces/odbc_db/odbcapiagent.cpp\
+  DB_interfaces/odbc_db/odbcapids.cpp
+
+API_DB=\
+  DB_interfaces/api_db/pluginapiagent.cpp\
+  DB_interfaces/api_db/pluginapids.cpp\
+  DB_interfaces/api_db/dbapi.cpp\
+  DB_interfaces/api_db/DLL_interface.cpp\
+  DB_interfaces/api_db/sync_dbapiconnect.cpp\
+  sysync_SDK/Sources/SDK_support.cpp\
+  sysync_SDK/DB_Interfaces/text_db/sync_dbapi_text.cpp\
+  sysync_SDK/Sources/admindata.cpp\
+  sysync_SDK/Sources/dbitem.cpp\
+  sysync_SDK/Sources/blobs.cpp
+
+
+# --------------------------------------------------------
+INCLUDE_PLATFORM=\
+  -I platform_adapters/linux/\
+  -I platform_adapters/unix_common/\
+  -I platform_adapters/
+
+INCLUDE_SYNCML_TK_SML=\
+  -I syncml_tk/src/sml/inc/\
+  -I syncml_tk/src/sml/lib/inc/\
+  -I syncml_tk/src/sml/lib/\
+  -I syncml_tk/src/sml/mgr/inc/\
+  -I syncml_tk/src/sml/mgr/\
+  -I syncml_tk/src/sml/wsm/inc/\
+  -I syncml_tk/src/sml/xlt/inc/\
+  -I syncml_tk/src/sml/xlt/all/
+
+INCLUDE_EXPAT=\
+  -I expat/xmltok/\
+  -I expat/xmlparse/
+
+INCLUDE_SERVERENGINE=\
+  -I syncapps/serverEngine_custom/\
+  -I Transport_interfaces/engine/\
+  -I sysync_SDK/Sources\
+  -I sysync/\
+  -I ./
+
+
+#############################
+#######  TARGET: serverEngine
+#############################
+WD_OBJS_serverEngine=$(WD_OBJS)/serverEngine
+
+c_SRC_serverEngine=\
+  $(C_BASICS) $(ZLIB)
+
+cpp_SRC_serverEngine=\
+  $(PLATFORM_EXT)\
+  $(SERVERENGINE)\
+  $(ODBC_DB)\
+  $(API_DB)
+
+OBJS_serverEngine+=  $(c_SRC_serverEngine:.c=.c.o)
+OBJS_serverEngine+=$(cpp_SRC_serverEngine:.cpp=.cpp.o)
+
+INCLUDE_serverEngine=\
+ -include Targets/ReleasedProducts/serverEngine_opensource_linux/serverengine_opensource_linux_prefix.h\
+ -I Targets/ReleasedProducts/serverEngine_opensource_linux/\
+ $(INCLUDE_PLATFORM)\
+ $(INCLUDE_SYNCML_TK_SML)\
+ $(INCLUDE_EXPAT)\
+ $(INCLUDE_SERVERENGINE)\
+ -I DB_interfaces/odbc_db/\
+ -I DB_interfaces/api_db/\
+ -I SQLite/\
+ -I zlib/\
+ -I /usr/include/
+
+serverEngine:
+       $(MAKE) -f $(MAKEFILE) sysync_server_engine.so TARGET=sysync_server_engine.so \
+  WDOP="$(WD_OBJS_serverEngine)"\
+  OBJS="$(addprefix $(WD_OBJS_serverEngine)/,$(OBJS_serverEngine))"\
+  LIBS="-L/usr/lib32 -L/usr/lib -lstdc++ -lpthread -lltdl -lpcre"\
+  INCL="$(INCLUDE_serverEngine)"
+
+sysync_server_engine.so: $(OBJS)
+       $(LD) -shared -Xlinker -soname=sysync_server_engine $(LDFLAGS) $(OBJS) $(LIBS) \
+       -o sysync_SDK/bin/Linux/sysync_server_engine.so
+
+ifeq ($(TARGET), sysync_server_engine.so)
+$(WDOP)/%.c.o:   $(WD)/%.c
+       mkdir -p $(dir $@)
+       $(CC) -fPIC $(CFLAGS) $(INCL) $< -o $@
+
+$(WDOP)/%.cpp.o: $(WD)/%.cpp
+       mkdir -p $(dir $@)
+       $(CC) -fPIC $(CFLAGS) $(INCL) $< -o $@
+endif
+
+clean_serverEngine:
+       rm -f -r $(WD_OBJS_serverEngine)
index 894c323..164d072 100644 (file)
@@ -21,10 +21,10 @@ namespace sysync {
 
 
 // factory function implementation - declared in TEngineInterface
-ENGINE_IF_CLASS *newEngine(void)
+ENGINE_IF_CLASS *newClientEngine(void)
 {
   return new TCustomClientEngineInterface;
-} // newEngine
+} // newClientEngine
 
 
 
index 0f338da..96ca8a6 100755 (executable)
@@ -33,6 +33,7 @@
 // Most hyperglobal definition, might even influence global_options.h:
 // - THIS IS A CLIENT
 #define SYSYNC_CLIENT 1
+
 // - is a engine library
 #define ENGINE_LIBRARY 1
 
@@ -77,7 +78,7 @@
 // separate files for outlook - different from old 1.0 client to make sure we don't import old problems
 #define SETTINGS_BFI_PREFIX "sysynclib_"
 
-// - if defined, local DB does not require any login
+// - if defined, local DB does not require any login in client mode
 #define NO_LOCAL_DBLOGIN 1
 
 // - if defined, config file might contain <syncrequest>s which will
@@ -90,7 +91,7 @@
 #undef HARDCODED_CONFIG
 
 // - if defined, remoterule mechanism is not included
-#define NO_REMOTE_RULES 1
+#undef NO_REMOTE_RULES
 
 // - if defined, support for hardcoded (predefined)
 //   type definitions will be included
diff --git a/src/synthesis/src/syncapps/serverEngine_custom/combi_product_options.h b/src/synthesis/src/syncapps/serverEngine_custom/combi_product_options.h
new file mode 100644 (file)
index 0000000..2813aa7
--- /dev/null
@@ -0,0 +1,127 @@
+/* Common Product options
+ * ======================
+ *
+ */
+
+// Custom Unified Server/Client Library Products
+// #############################################
+
+// Separate Version
+// ================
+
+// Note: for now, library has NO SEPARATE VERSION, but shows engine version
+
+/*
+#define SYSYNC_VERSION_MAJOR       1
+#define SYSYNC_VERSION_MAJOR_TXT   "1"
+
+#define SYSYNC_VERSION_MINOR       1
+#define SYSYNC_VERSION_MINOR_TXT   "1"
+
+#define SYSYNC_SUBVERSION       0
+#define SYSYNC_SUBVERSION_TXT   "0"
+
+#define SYSYNC_BUILDNUMBER      0
+#define SYSYNC_BUILDNUMBER_TXT  "0"
+*/
+
+
+// new major or minor gives a new demo period
+#define SYSER_VERSCHECK_MASK 0xFFFF0000
+
+
+// Most hyperglobal definition, might even influence global_options.h:
+// - THIS IS BOTH SERVER and CLIENT
+#define SYSYNC_SERVER 1
+#define SYSYNC_CLIENT 1
+
+// - is a engine library
+#define ENGINE_LIBRARY 1
+
+// - ...which is used in standalone apps
+#define STANDALONE_APP 1
+
+// global options
+#include "global_options.h"
+
+// Product (but not target) specific options
+// #########################################
+
+// Hard expiration date, software will stop working after defined date
+// if not registered
+#undef VERSION_COMMENTS
+#define VERSION_COMMENTS "Demo expires after " EXPIRY_DATE_STRING " if not registered"
+#define EXPIRES_AFTER_DATE 1
+
+// SySync options
+// ==============
+
+// - use precise time when possible
+#define NOW_WITH_MILLISECONDS 1
+
+
+// - if defined, debug code is included (not necessarily enabled, see gDebug)
+//   if 1, only "public" debugging is enabled, if >1, all debugging is enabled
+#ifdef RELEASE_VERSION
+  #if RELEASE_SYDEBUG
+    #define SYDEBUG RELEASE_SYDEBUG
+  #else
+    #undef SYDEBUG // absolutely no debug code for release!
+  #endif
+  #undef CONSOLEINFO
+#else
+  #define SYDEBUG 2 // 3=including XPT trace, 4=including memory leak detection
+  #undef CONSOLEINFO
+#endif
+
+// local Database options
+#define DESKTOP_CLIENT 1 // selects different binfile format (actually, will merge with mobile format at version 5)
+// separate files for outlook - different from old 1.0 client to make sure we don't import old problems
+#define SETTINGS_BFI_PREFIX "sysynclib_"
+
+// - if defined, local DB does not require any login in client mode
+#define NO_LOCAL_DBLOGIN 1
+
+// - if defined, config file might contain <syncrequest>s which will
+//   allow a client to run directly from config w/o additionally
+//   provided parameters.
+#undef PRECONFIGURED_SYNCREQUESTS
+
+// - if defined, XML config parsing is completely disabled,
+//   all config must be set programmatically
+#undef HARDCODED_CONFIG
+
+// - if defined, remoterule mechanism is not included
+#undef NO_REMOTE_RULES
+
+// - if defined, support for hardcoded (predefined)
+//   type definitions will be included
+#undef HARDCODED_TYPE_SUPPORT
+// - if defined, support for configurable types will be included
+#define CONFIGURABLE_TYPE_SUPPORT 1
+
+
+// do not modify remote IDs in any way while processing them
+#define DONT_STRIP_PATHPREFIX_FROM_REMOTEIDS 1
+
+// if defined, session continues after 401/407
+//#define AUTH_RETRY_USES_SAME_CLIENT_SESSION
+
+
+
+// SyncML Toolkit options
+// ======================
+
+// if defined, the entire complicated and thread-unsafe workspace manager
+// is completely bypassed
+#define NOWSM 1
+
+/* if defined, avoids using <![CDATA[ for opaque data except when really needed, i.e. contents would break XML */
+#define PCDATA_OPAQUE_AS_CDATA 1
+
+
+// we want the toolkit linked static
+#define __LINK_TOOLKIT_STATIC__ 1
+
+
+/* eof */
diff --git a/src/synthesis/src/syncapps/serverEngine_custom/product_options.h b/src/synthesis/src/syncapps/serverEngine_custom/product_options.h
new file mode 100644 (file)
index 0000000..1deee4c
--- /dev/null
@@ -0,0 +1,108 @@
+/* Common Product options
+ * ======================
+ *
+ */
+
+// Custom Server Library Products
+// ##############################
+
+// Separate Version
+// ================
+
+// Note: for now, server library has NO SEPARATE VERSION, but shows engine version
+
+/*
+#define SYSYNC_VERSION_MAJOR       1
+#define SYSYNC_VERSION_MAJOR_TXT   "1"
+
+#define SYSYNC_VERSION_MINOR       1
+#define SYSYNC_VERSION_MINOR_TXT   "1"
+
+#define SYSYNC_SUBVERSION       0
+#define SYSYNC_SUBVERSION_TXT   "0"
+
+#define SYSYNC_BUILDNUMBER      0
+#define SYSYNC_BUILDNUMBER_TXT  "0"
+*/
+
+
+// Most hyperglobal definition, might even influence global_options.h:
+// - THIS IS A SERVER
+#define SYSYNC_SERVER 1
+// - is a engine library
+#define ENGINE_LIBRARY 1
+
+// - ...which is used in standalone apps
+#define STANDALONE_APP 1
+
+// global options
+#include "global_options.h"
+
+// Product (but not target) specific options
+// #########################################
+
+// Hard expiration date, software will stop working after defined date
+// if not registered
+#undef VERSION_COMMENTS
+#define VERSION_COMMENTS "Demo expires after " EXPIRY_DATE_STRING " if not registered"
+#define EXPIRES_AFTER_DATE 1
+
+// SySync options
+// ==============
+
+// - use precise time when possible
+#define NOW_WITH_MILLISECONDS 1
+
+
+// - if defined, debug code is included (not necessarily enabled, see gDebug)
+//   if 1, only "public" debugging is enabled, if >1, all debugging is enabled
+#ifdef RELEASE_VERSION
+  #if RELEASE_SYDEBUG
+    #define SYDEBUG RELEASE_SYDEBUG
+  #else
+    #undef SYDEBUG // absolutely no debug code for release!
+  #endif
+  #undef CONSOLEINFO
+#else
+  #define SYDEBUG 2 // 3=including XPT trace, 4=including memory leak detection
+  #undef CONSOLEINFO
+#endif
+
+// - if defined, XML config parsing is completely disabled,
+//   all config must be set programmatically
+#undef HARDCODED_CONFIG
+
+// - if defined, remoterule mechanism is not included
+#undef NO_REMOTE_RULES
+
+// - if defined, support for hardcoded (predefined)
+//   type definitions will be included
+#undef HARDCODED_TYPE_SUPPORT
+// - if defined, support for configurable types will be included
+#define CONFIGURABLE_TYPE_SUPPORT 1
+
+
+// do not modify remote IDs in any way while processing them
+#define DONT_STRIP_PATHPREFIX_FROM_REMOTEIDS 1
+
+// if defined, session continues after 401/407
+//#define AUTH_RETRY_USES_SAME_CLIENT_SESSION
+
+
+
+// SyncML Toolkit options
+// ======================
+
+// if defined, the entire complicated and thread-unsafe workspace manager
+// is completely bypassed
+#define NOWSM 1
+
+/* if defined, avoids using <![CDATA[ for opaque data except when really needed, i.e. contents would break XML */
+#define PCDATA_OPAQUE_AS_CDATA 1
+
+
+// we want the toolkit linked static
+#define __LINK_TOOLKIT_STATIC__ 1
+
+
+/* eof */
diff --git a/src/synthesis/src/syncapps/serverEngine_custom/serverengine_custom.h b/src/synthesis/src/syncapps/serverEngine_custom/serverengine_custom.h
new file mode 100644 (file)
index 0000000..893ac4d
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef SERVERENGINE_CUSTOM_H
+#define SERVERENGINE_CUSTOM_H
+
+/* Headers that might be available in precompiled form
+ * (standard libraries, SyncML toolkit...)
+ */
+#include "serverengine_custom_precomp.h"
+
+/* headers not suitable for / entirely included in precompilation */
+
+// DB interface related includes
+#ifdef SQL_SUPPORT
+  #include "odbcdb.h"
+#endif
+#ifdef SDK_SUPPORT
+  #include "plugindb.h"
+#endif
+#ifdef OUTLOOK_SUPPORT
+  #include "outlookdb.h"
+#endif
+
+
+#endif // SERVERENGINE_CUSTOM_H
diff --git a/src/synthesis/src/syncapps/serverEngine_custom/serverengine_custom_Base.cpp b/src/synthesis/src/syncapps/serverEngine_custom/serverengine_custom_Base.cpp
new file mode 100644 (file)
index 0000000..85cf8cd
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ *  TCustomServerEngineBase, TCustomServerEngineInterface
+ *    SyncML client engine for custom server - base classes
+ *
+ *  Copyright (c) 2009-2009 by Synthesis AG (www.synthesis.ch)
+ *
+ *  2009-02-06 : luz : Created
+ *
+ */
+
+// includes
+#include "serverengine_custom.h"
+#include "serverengine_custom_Base.h"
+
+// common includes
+#include "enginesessiondispatch.h"
+
+
+namespace sysync {
+
+
+// factory function implementation - declared in TEngineInterface
+ENGINE_IF_CLASS *newServerEngine(void)
+{
+  return new TCustomServerEngineInterface;
+} // newServerEngine
+
+
+
+/*
+ * Implementation of TCustomServerEngineInterface
+ */
+
+
+/// @brief returns a new application base.
+TSyncAppBase *TCustomServerEngineInterface::newSyncAppBase(void)
+{
+  return new TCustomServerEngineBase;
+} // TCustomServerEngineInterface::newSyncAppBase
+
+
+
+/*
+ * Implementation of TCustomServerEngineBase
+ */
+
+
+TCustomServerEngineBase::TCustomServerEngineBase()
+{  
+  // create config root
+  fConfigP = new TEngineServerRootConfig(this);
+} // TCustomServerEngineBase::TCustomServerEngineBase
+
+
+TCustomServerEngineBase::~TCustomServerEngineBase()
+{
+  fDeleting=true; // flag deletion to block calling critical (virtual) methods
+} // TCustomServerEngineBase::~TCustomServerEngineBase
+
+
+} // namespace sysync
+
+// eof
\ No newline at end of file
diff --git a/src/synthesis/src/syncapps/serverEngine_custom/serverengine_custom_Base.h b/src/synthesis/src/syncapps/serverEngine_custom/serverengine_custom_Base.h
new file mode 100644 (file)
index 0000000..cdc246f
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ *  TCustomServerEngineBase, TCustomServerEngineInterface
+ *    SyncML client engine for custom server - base classes
+ *
+ *  Copyright (c) 2009-2009 by Synthesis AG (www.synthesis.ch)
+ *
+ *  2009-02-06 : luz : Created
+ *
+ */
+#ifndef SERVERENGINE_CUSTOM_BASE_H
+#define SERVERENGINE_CUSTOM_BASE_H
+
+// directly based on session dispatcher for engine servers
+#include "enginesessiondispatch.h"
+// using generic base for customizable builds
+#include "customimplagent.h"
+
+
+namespace sysync {
+
+// Appbase class
+class TCustomServerEngineBase: public TEngineSessionDispatch
+{
+  typedef TEngineSessionDispatch inherited;
+public:
+  TCustomServerEngineBase();
+  virtual ~TCustomServerEngineBase();
+}; // TCustomServerEngineBase
+
+
+// Engine interface class
+class TCustomServerEngineInterface:
+  public TServerEngineInterface
+{
+  typedef TServerEngineInterface inherited;
+public:
+  /// @brief returns a new application base.
+  virtual TSyncAppBase *newSyncAppBase(void);
+}; // TCustomServerEngineInterface
+
+}
+
+#endif  // SERVERENGINE_CUSTOM_BASE_H
+
+// eof
diff --git a/src/synthesis/src/syncapps/serverEngine_custom/serverengine_custom_precomp.h b/src/synthesis/src/syncapps/serverEngine_custom/serverengine_custom_precomp.h
new file mode 100644 (file)
index 0000000..3cc0120
--- /dev/null
@@ -0,0 +1,26 @@
+/* Headers that might be available in precompiled form
+ * (standard libraries, SyncML toolkit...)
+ *
+ */ 
+
+#ifndef SERVERENGINE_CUSTOM_PRECOMP_H
+#define SERVERENGINE_CUSTOM_PRECOMP_H
+
+// Needed for Engine 
+#include "sysync_precomp.h"
+
+// DB interface related includes
+#ifdef SQL_SUPPORT
+  #include "odbcdb_precomp.h"
+#endif
+#ifdef SDK_SUPPORT
+  #include "plugindb_precomp.h"
+#endif
+#ifdef OUTLOOK_SUPPORT
+  #include "outlookdb_precomp.h"
+#endif
+
+
+#endif // SERVERENGINE_CUSTOM_PRECOMP_H
+
+// eof
index bb6c464..3d7f5de 100755 (executable)
@@ -14,7 +14,7 @@
 
 // include files where commands are implemented
 #include "odbcapiagent.h"
-#include "syncserver.h"
+#include "syncagent.h"
 #include "sysync_utils.h"
 #include "rrules.h"
 
index 2bb98a9..35d8450 100755 (executable)
@@ -1454,7 +1454,10 @@ Ret_t subdtdEncWBXML(XltTagID_t tagId, XltRO_t reqOptFlag, const VoidPtr_t pCont
     Ret_t             _err         = SML_ERR_OK;
     #endif
 
-    Short_t           SubBufSize   = 12000; // for starters we use 12kB for each sub DTD to encode in WBXML
+    /* Double the size of SubBufSize for the memory is small for some complex
+     * content.
+     */ 
+    Short_t           SubBufSize   = 12000 * 2; // for starters we use 12kB for each sub DTD to encode in WBXML
     BufferMgmtPtr_t   pSubBufMgr   = NULL;
 
 
index 71aea67..2435aca 100644 (file)
@@ -1,8 +1,8 @@
 VER_1.0 {
     global:
-        SySync_ConnectEngine;
-        SySync_ConnectEngineS;
-        SySync_DisconnectEngine;
+        SySync_*ConnectEngine;
+        SySync_*ConnectEngineS;
+        SySync_*DisconnectEngine;
         extern "C++" {
                sysync::DataConversion*;
                sysync::SySyncDebugPuts*;
index 57a8e77..16c3e1e 100755 (executable)
@@ -34,7 +34,7 @@ namespace sysync {
   #error "this is here for Q&D testing with outlook client only"
 #endif
 // factory function implementation - declared in TEngineInterface
-ENGINE_IF_CLASS *newEngine(void)
+ENGINE_IF_CLASS *newClientEngine(void)
 {
   return new TBinfileEngineInterface;
 } // newEngine
@@ -56,7 +56,7 @@ TSyncAppBase *TBinfileEngineInterface::newSyncAppBase(void)
 // create appropriate root key
 TSettingsKeyImpl *TBinfileEngineInterface::newSettingsRootKey(void)
 {
-  return new TBinfileClientRootKey(this); // return base class which can return some engine infos
+  return new TBinfileAgentRootKey(this); // return base class which can return some engine infos
 } // TBinfileEngineInterface::newSettingsRootKey
 
 
@@ -1144,26 +1144,67 @@ TSyError TBinfileLogsKey::DeleteSubkey(sInt32 aID)
 } // TBinfileLogsKey::DeleteSubkey
 
 
+
+// Binfile Agent root key
+// ----------------------
+
+// Constructor
+TBinfileAgentRootKey::TBinfileAgentRootKey(TEngineInterface *aEngineInterfaceP) :
+  inherited(aEngineInterfaceP)
+{
+} // TBinfileAgentRootKey::TBinfileAgentRootKey
+
+
+// open subkey by name (not by path!)
+// - this is the actual implementation
+TSyError TBinfileAgentRootKey::OpenSubKeyByName(
+  TSettingsKeyImpl *&aSettingsKeyP,
+  cAppCharP aName, stringSize aNameSize,
+  uInt16 aMode
+) {
+  if (strucmp(aName,"profiles",aNameSize)==0) {
+    // allow accessing profiles only for active binfiles
+    if (
+      static_cast<TBinfileClientConfig *>(
+        fEngineInterfaceP->getSyncAppBase()->getRootConfig()->fAgentConfigP
+      )->fBinfilesActive
+    ) {
+      aSettingsKeyP = new TBinfileProfilesKey(fEngineInterfaceP);
+    }
+    else {
+      // cannot access profiles of inactive binfile layer
+      return LOCERR_WRONGUSAGE;
+    }
+  }
+  else if (strucmp(aName,"synclogs",aNameSize)==0)
+    aSettingsKeyP = new TBinfileLogsKey(fEngineInterfaceP);
+  else
+    return inherited::OpenSubKeyByName(aSettingsKeyP,aName,aNameSize,aMode);
+  // opened a key
+  return LOCERR_OK;
+} // TBinfileAgentRootKey::OpenSubKeyByName
+
+
 // Client runtime settings key
 // ---------------------------
 
 
 // Constructor
-TBinFileClientParamsKey::TBinFileClientParamsKey(TEngineInterface *aEngineInterfaceP, TSyncClient *aClientSessionP) :
+TBinFileAgentParamsKey::TBinFileAgentParamsKey(TEngineInterface *aEngineInterfaceP, TSyncAgent *aClientSessionP) :
   inherited(aEngineInterfaceP,aClientSessionP)
 {
-} // TBinFileClientParamsKey::TBinFileClientParamsKey
+} // TBinFileAgentParamsKey::TBinFileAgentParamsKey
 
 
 // open subkey by name (not by path!)
-TSyError TBinFileClientParamsKey::OpenSubKeyByName(
+TSyError TBinFileAgentParamsKey::OpenSubKeyByName(
   TSettingsKeyImpl *&aSettingsKeyP,
   cAppCharP aName, stringSize aNameSize,
   uInt16 aMode
 ) {
   if (strucmp(aName,"profile",aNameSize)==0) {
     // get binfileclient session pointer
-    TBinfileImplClient *bfclientP = static_cast<TBinfileImplClient *>(fClientSessionP);
+    TBinfileImplClient *bfclientP = static_cast<TBinfileImplClient *>(fAgentP);
     // opens current session's active profile
     aSettingsKeyP = new TBinfileProfileKey(
       fEngineInterfaceP,
@@ -1176,7 +1217,7 @@ TSyError TBinFileClientParamsKey::OpenSubKeyByName(
     return inherited::OpenSubKeyByName(aSettingsKeyP,aName,aNameSize,aMode);
   // opened a key
   return LOCERR_OK;
-} // TBinFileClientParamsKey::OpenSubKeyByName
+} // TBinFileAgentParamsKey::OpenSubKeyByName
 
 
 #endif // ENGINEINTERFACE_SUPPORT
@@ -1188,7 +1229,7 @@ TSyError TBinFileClientParamsKey::OpenSubKeyByName(
 // ======
 
 TBinfileClientConfig::TBinfileClientConfig(TConfigElement *aParentElement) :
-  TClientConfig("BinFileDBClient",aParentElement)
+  TAgentConfig("BinFileDBClient",aParentElement)
 {
 } // TBinfileClientConfig::TBinfileClientConfig
 
@@ -1202,6 +1243,8 @@ TBinfileClientConfig::~TBinfileClientConfig()
 // init defaults
 void TBinfileClientConfig::clear(void)
 {
+       // Only active in clients by default
+       fBinfilesActive = IS_CLIENT;
   #ifndef HARDCODED_CONFIG
   // init defaults
   fBinFilesPath.erase();
@@ -1223,6 +1266,8 @@ bool TBinfileClientConfig::localStartElement(const char *aElementName, const cha
     expectMacroString(fBinFilesPath);
   else if (strucmp(aElementName,"binfilelog")==0)
     expectBool(fBinFileLog);
+  else if (strucmp(aElementName,"binfilesactive")==0)
+    expectBool(fBinfilesActive);
   // - none known here
   else
     return inherited::localStartElement(aElementName,aAttributes,aLine);
@@ -1378,47 +1423,53 @@ void TBinfileClientConfig::getBinFilesPath(string &aPath)
 // open settings databases
 localstatus TBinfileClientConfig::openSettingsDatabases(bool aDoLoose)
 {
-  // safe for calling more than once
-  if (fProfileBinFile.isOpen() && fTargetsBinFile.isOpen())
-    return LOCERR_OK; // already open - ok
-  // open profile and targets databases
-  // - get base path
-  string basepath;
-  getBinFilesPath(basepath);
-  string usedpath;
-  bool newprofiles=false;
-  bferr err;
-  // - profiles
-  usedpath=basepath + PROFILE_DB_NAME;
-  fProfileBinFile.setFileInfo(usedpath.c_str(),PROFILE_DB_VERSION,PROFILE_DB_ID,sizeof(TBinfileDBSyncProfile));
-  err = fProfileBinFile.open(0,NULL,profileUpdateFunc);
-  if (err!=BFE_OK) {
-    // create new one or overwrite incompatible one if allowed
-    if (aDoLoose || err!=BFE_BADVERSION) {
-      err=fProfileBinFile.create(sizeof(TBinfileDBSyncProfile),0,NULL,true);
-      newprofiles=true;
-    }
-    else {
-      // would create new file due to bad (newer or non-upgradeable older) version
-      return LOCERR_CFGPARSE; // this is kind of a config parsing error
-    }
+       if (!fBinfilesActive) {
+       // databases can be opened only with active binfiles layer
+       return LOCERR_WRONGUSAGE;
   }
-  // - targets
-  usedpath=basepath + TARGETS_DB_NAME;
-  fTargetsBinFile.setFileInfo(usedpath.c_str(),TARGETS_DB_VERSION,TARGETS_DB_ID,sizeof(TBinfileDBSyncTarget));
-  err = fTargetsBinFile.open(0,NULL,targetUpdateFunc);
-  if (err!=BFE_OK || newprofiles) {
-    // create new one or overwrite incompatible one
-    // also ALWAYS create new targets if we HAVE created new profiles
-    if (aDoLoose || newprofiles || err!=BFE_BADVERSION) {
-      err=fTargetsBinFile.create(sizeof(TBinfileDBSyncTarget),0,NULL,true);
+  else {
+    // safe for calling more than once
+    if (fProfileBinFile.isOpen() && fTargetsBinFile.isOpen())
+      return LOCERR_OK; // already open - ok
+    // open profile and targets databases
+    // - get base path
+    string basepath;
+    getBinFilesPath(basepath);
+    string usedpath;
+    bool newprofiles=false;
+    bferr err;
+    // - profiles
+    usedpath=basepath + PROFILE_DB_NAME;
+    fProfileBinFile.setFileInfo(usedpath.c_str(),PROFILE_DB_VERSION,PROFILE_DB_ID,sizeof(TBinfileDBSyncProfile));
+    err = fProfileBinFile.open(0,NULL,profileUpdateFunc);
+    if (err!=BFE_OK) {
+      // create new one or overwrite incompatible one if allowed
+      if (aDoLoose || err!=BFE_BADVERSION) {
+        err=fProfileBinFile.create(sizeof(TBinfileDBSyncProfile),0,NULL,true);
+        newprofiles=true;
+      }
+      else {
+        // would create new file due to bad (newer or non-upgradeable older) version
+        return LOCERR_CFGPARSE; // this is kind of a config parsing error
+      }
     }
-    else {
-      // would create new file due to bad (newer or non-upgradeable older) version
-      return LOCERR_CFGPARSE; // this is kind of a config parsing error
+    // - targets
+    usedpath=basepath + TARGETS_DB_NAME;
+    fTargetsBinFile.setFileInfo(usedpath.c_str(),TARGETS_DB_VERSION,TARGETS_DB_ID,sizeof(TBinfileDBSyncTarget));
+    err = fTargetsBinFile.open(0,NULL,targetUpdateFunc);
+    if (err!=BFE_OK || newprofiles) {
+      // create new one or overwrite incompatible one
+      // also ALWAYS create new targets if we HAVE created new profiles
+      if (aDoLoose || newprofiles || err!=BFE_BADVERSION) {
+        err=fTargetsBinFile.create(sizeof(TBinfileDBSyncTarget),0,NULL,true);
+      }
+      else {
+        // would create new file due to bad (newer or non-upgradeable older) version
+        return LOCERR_CFGPARSE; // this is kind of a config parsing error
+      }
     }
+         return err;
   }
-  return err;
 } // TBinfileClientConfig::openSettingsDatabases
 
 
@@ -1448,9 +1499,11 @@ localstatus TBinfileClientConfig::loadVarConfig(bool aDoLoose)
 {
   // let inherited to it's stuff
   localstatus err=inherited::loadVarConfig(aDoLoose);
-  // now do my own stuf
-  if (err==LOCERR_OK) {
-    err=openSettingsDatabases(aDoLoose);
+  if (fBinfilesActive) {
+    // now do my own stuff
+    if (err==LOCERR_OK) {
+      err=openSettingsDatabases(aDoLoose);
+    }
   }
   // return status
   return err;
@@ -1461,10 +1514,12 @@ localstatus TBinfileClientConfig::loadVarConfig(bool aDoLoose)
 // save app state (such as settings in datastore configs etc.)
 void TBinfileClientConfig::saveAppState(void)
 {
-  // close and re-open the settings binfiles to make sure their
-  // contents is permanently saved
-  closeSettingsDatabases();
-  openSettingsDatabases(false);
+       if (fBinfilesActive) {
+    // close and re-open the settings binfiles to make sure their
+    // contents is permanently saved
+    closeSettingsDatabases();
+    openSettingsDatabases(false);
+  }
 } // TBinfileClientConfig::saveAppState
 
 
@@ -2267,12 +2322,12 @@ void TBinfileClientConfig::cleanChangeLogForDBname(cAppCharP aDBName)
 /* public TBinfileImplClient members */
 
 
-TBinfileImplClient::TBinfileImplClient(TSyncClientBase *aSyncClientBaseP, const char *aSessionID) :
-  TStdLogicAgent(aSyncClientBaseP, aSessionID),
+TBinfileImplClient::TBinfileImplClient(TSyncAppBase *aSyncAppBaseP, TSyncSessionHandle *aSyncSessionHandleP, cAppCharP aSessionID) :
+  TStdLogicAgent(aSyncAppBaseP, aSyncSessionHandleP, aSessionID),
   fConfigP(NULL)
 {
   // get config for agent
-  TRootConfig *rootcfgP = aSyncClientBaseP->getRootConfig();
+  TRootConfig *rootcfgP = aSyncAppBaseP->getRootConfig();
   // - save direct link to agent config for easy reference
   fConfigP = static_cast<TBinfileClientConfig *>(rootcfgP->fAgentConfigP);
   // - make profile invalid
@@ -2292,7 +2347,7 @@ TBinfileImplClient::~TBinfileImplClient()
 // Terminate session
 void TBinfileImplClient::TerminateSession()
 {
-  if (!fTerminated) {
+  if (!fTerminated && fConfigP->fBinfilesActive) {
     // save profile changes
     if (fProfileIndex>=0 && fProfileDirty) {
       fConfigP->fProfileBinFile.updateRecord(fProfileIndex,&fProfile);
@@ -2325,7 +2380,7 @@ void TBinfileImplClient::SetProfileSelector(uInt32 aProfileSelector)
 /// @brief Get new session key to access details of this session
 appPointer TBinfileImplClient::newSessionKey(TEngineInterface *aEngineInterfaceP)
 {
-  return new TBinFileClientParamsKey(aEngineInterfaceP,this);
+  return new TBinFileAgentParamsKey(aEngineInterfaceP,this);
 } // TBinfileImplClient::newSessionKey
 
 #endif // ENGINEINTERFACE_SUPPORT
@@ -2345,8 +2400,10 @@ void TBinfileImplClient::InternalResetSession(void)
 // Virtual version
 void TBinfileImplClient::ResetSession(void)
 {
-  // do my own stuff
-  InternalResetSession();
+       if (fConfigP->fBinfilesActive) {
+    // do my own stuff
+    InternalResetSession();
+  }
   // let ancestor do its stuff
   TStdLogicAgent::ResetSession();
 } // TBinfileImplClient::ResetSession
@@ -2357,8 +2414,8 @@ void TBinfileImplClient::ResetSession(void)
 //   last info here.
 void TBinfileImplClient::loadRemoteParams(void)
 {
-  if (fProfileIndex<0) {
-    // no profile loaded, let ancestor handle case
+  if (!fConfigP->fBinfilesActive || fProfileIndex<0) {
+    // not active or no profile loaded, let ancestor handle case
     TStdLogicAgent::loadRemoteParams();
   }
   else {
@@ -2387,7 +2444,7 @@ void TBinfileImplClient::loadRemoteParams(void)
 // - save remote connect params for use in next session (if descendant implements it)
 void TBinfileImplClient::saveRemoteParams(void)
 {
-  if (fProfileIndex>=0) {
+  if (fConfigP->fBinfilesActive && fProfileIndex>=0) {
     // save values to profile
     // - SyncML version (save it only if it is "better" than what we knew so far)
     if (fSyncMLVersion > fProfile.lastSyncMLVersion) {
@@ -2405,7 +2462,7 @@ void TBinfileImplClient::saveRemoteParams(void)
 // check remote devinf to detect special behaviour needed for some servers.
 localstatus TBinfileImplClient::checkRemoteSpecifics(SmlDevInfDevInfPtr_t aDevInfP)
 {
-  if (aDevInfP) {
+  if (fConfigP->fBinfilesActive && aDevInfP) {
     // check for some specific servers we KNOW they need special treatment
     uInt8 setFlags = 0;
     uInt8 clearFlags = 0;
@@ -2464,18 +2521,20 @@ localstatus TBinfileImplClient::checkRemoteSpecifics(SmlDevInfDevInfPtr_t aDevIn
 // generates custom PUT in case IPP/DMU is enabled to request settings
 void TBinfileImplClient::issueCustomGetPut(bool aGotDevInf, bool aSentDevInf)
 {
-  // get autosync PUT req string
-  string req;
-  fConfigP->autosync_get_putrequest(req);
-  // now create a PUT
-  if (!req.empty()) {
-    TPutCommand *putcommandP = new TPutCommand(this);
-    putcommandP->setMeta(newMetaType(IPP_PARAMS_ITEM_METATYPE));
-    SmlItemPtr_t putItemP = putcommandP->addSourceLocItem(IPP_PARAMS_LOCURI_REQ);
-    // - add data to item
-    putItemP->data = newPCDataString(req.c_str());
-    putcommandP->allowFailure(); // do not abort session in case server does not understand the command
-    ISSUE_COMMAND_ROOT(this,putcommandP);
+       if (fConfigP->fBinfilesActive) {
+    // get autosync PUT req string
+    string req;
+    fConfigP->autosync_get_putrequest(req);
+    // now create a PUT
+    if (!req.empty()) {
+      TPutCommand *putcommandP = new TPutCommand(this);
+      putcommandP->setMeta(newMetaType(IPP_PARAMS_ITEM_METATYPE));
+      SmlItemPtr_t putItemP = putcommandP->addSourceLocItem(IPP_PARAMS_LOCURI_REQ);
+      // - add data to item
+      putItemP->data = newPCDataString(req.c_str());
+      putcommandP->allowFailure(); // do not abort session in case server does not understand the command
+      ISSUE_COMMAND_ROOT(this,putcommandP);
+    }
   }
   // let ancestors issue their custom gets and puts, if any
   inherited::issueCustomGetPut(aGotDevInf, aSentDevInf);
@@ -2487,53 +2546,59 @@ void TBinfileImplClient::issueCustomGetPut(bool aGotDevInf, bool aSentDevInf)
 // handler of custom IPP/DMU put and result commands
 void TBinfileImplClient::processPutResultItem(bool aIsPut, const char *aLocUri, TSmlCommand *aPutResultsCommandP, SmlItemPtr_t aPutResultsItemP, TStatusCommand &aStatusCommand)
 {
-  #ifdef IPP_SUPPORT
-  // check for DMU specials
-  if (strucmp(relativeURI(aLocUri),relativeURI(IPP_PARAMS_LOCURI_CFG))==0) {
-    // get DMU string
-    const char *ippstring = smlItemDataToCharP(aPutResultsItemP);
-    PDEBUGPRINTFX(DBG_HOT,("received IPP config string: %s",ippstring));
-    // process it
-    string tag,value;
-    while (ippstring && *ippstring) {
-      ippstring=nextTag(ippstring,tag,value);
-      // set ipp params in current profile
-      fConfigP->ipp_setparam(tag.c_str(),value.c_str(),fProfile.ippSettings);
-      // make sure autosync profile copy gets updated as well
-      if (fConfigP->fAutosyncProfileLastidx==fProfileIndex) {
-        fConfigP->fAutosyncProfile = fProfile; // copy profile into autosync
-        fConfigP->autosync_condchanged(); // do immediately check settings at next autosync step
+       if (fConfigP->fBinfilesActive) {
+    #ifdef IPP_SUPPORT
+    // check for DMU specials
+    if (strucmp(relativeURI(aLocUri),relativeURI(IPP_PARAMS_LOCURI_CFG))==0) {
+      // get DMU string
+      const char *ippstring = smlItemDataToCharP(aPutResultsItemP);
+      PDEBUGPRINTFX(DBG_HOT,("received IPP config string: %s",ippstring));
+      // process it
+      string tag,value;
+      while (ippstring && *ippstring) {
+        ippstring=nextTag(ippstring,tag,value);
+        // set ipp params in current profile
+        fConfigP->ipp_setparam(tag.c_str(),value.c_str(),fProfile.ippSettings);
+        // make sure autosync profile copy gets updated as well
+        if (fConfigP->fAutosyncProfileLastidx==fProfileIndex) {
+          fConfigP->fAutosyncProfile = fProfile; // copy profile into autosync
+          fConfigP->autosync_condchanged(); // do immediately check settings at next autosync step
+        }
+        // make sure profile gets saved
+        fProfileDirty=true;
       }
-      // make sure profile gets saved
-      fProfileDirty=true;
+      // is ok
+      aStatusCommand.setStatusCode(200); // is ok
+      aStatusCommand.dontSend(); // ..but do not send it (%%% as session would then end with error 9999)
+    }
+    else
+    #endif
+    #ifdef SETTINGS_PROVISIONING_VIA_PUT
+    // check for provisioning strings arriving via PUT command
+    if (strucmp(relativeURI(aLocUri),relativeURI(SETTINGS_LOCURI_CFG))==0) {
+      // get provisioning string
+      const char *provstring = smlItemDataToCharP(aPutResultsItemP);
+      PDEBUGPRINTFX(DBG_HOT,("received settings provisioning string: %s",provstring));
+      // process it
+      // - but first save current profile
+      fConfigP->writeProfile(fProfileIndex,fProfile);
+      // - now modify profile (may include the current profile)
+      sInt32 activeprofile;
+      bool provok = fConfigP->executeProvisioningString(provstring, activeprofile);
+      // - reload current profile (eventually modified)
+      fConfigP->getProfile(fProfileIndex,fProfile);
+      // is ok
+      aStatusCommand.setStatusCode(provok ? 200 : 400); // ok or bad request
+      aStatusCommand.dontSend(); // ..but do not send it (%%% as session would then end with error 9999)
+    }
+    else
+    #endif
+    {
+      // let ancestors process it
+      inherited::processPutResultItem(aIsPut,aLocUri,aPutResultsCommandP,aPutResultsItemP,aStatusCommand);
     }
-    // is ok
-    aStatusCommand.setStatusCode(200); // is ok
-    aStatusCommand.dontSend(); // ..but do not send it (%%% as session would then end with error 9999)
-  }
-  else
-  #endif
-  #ifdef SETTINGS_PROVISIONING_VIA_PUT
-  // check for provisioning strings arriving via PUT command
-  if (strucmp(relativeURI(aLocUri),relativeURI(SETTINGS_LOCURI_CFG))==0) {
-    // get provisioning string
-    const char *provstring = smlItemDataToCharP(aPutResultsItemP);
-    PDEBUGPRINTFX(DBG_HOT,("received settings provisioning string: %s",provstring));
-    // process it
-    // - but first save current profile
-    fConfigP->writeProfile(fProfileIndex,fProfile);
-    // - now modify profile (may include the current profile)
-    sInt32 activeprofile;
-    bool provok = fConfigP->executeProvisioningString(provstring, activeprofile);
-    // - reload current profile (eventually modified)
-    fConfigP->getProfile(fProfileIndex,fProfile);
-    // is ok
-    aStatusCommand.setStatusCode(provok ? 200 : 400); // ok or bad request
-    aStatusCommand.dontSend(); // ..but do not send it (%%% as session would then end with error 9999)
   }
-  else
-  #endif
-  {
+  else {
     // let ancestors process it
     inherited::processPutResultItem(aIsPut,aLocUri,aPutResultsCommandP,aPutResultsItemP,aStatusCommand);
   }
@@ -2563,229 +2628,231 @@ const char * const Protocol_Names[num_transp_protos] = {
 localstatus TBinfileImplClient::SelectProfile(uInt32 aProfileSelector, bool aAutoSyncSession)
 {
   uInt32 recidx,maxidx;
-  
   // detect special tunnel session's selection
   bool tunnel = aProfileSelector==TUNNEL_PROFILE_ID;
-  if (tunnel) {
-       aProfileSelector=DEFAULT_PROFILE_ID;
-  }
-  // Note: profile database has already been opened in config resolve()
-  if (aProfileSelector==DEFAULT_PROFILE_ID) {
-    // default is first one
-    aProfileSelector=0;
-  }
-  // try to load profile
-  if (fConfigP->fProfileBinFile.readRecord(aProfileSelector,&fProfile)!=BFE_OK)
-    goto defaultprofile; // use default
-  // Now we have the profile
-  fProfileIndex=aProfileSelector;
-  fRemotepartyID=fProfile.profileID;
-  // Set session parameters
-  #ifdef SYNCML_ENCODING_OVERRIDE
-  fEncoding = SYNCML_ENCODING_OVERRIDE; // we use a globally defined encoding
-  #else
-  fEncoding = fProfile.encoding; // we use the profile's encoding
-  #endif
+       // select profile if active
+       if (fConfigP->fBinfilesActive) {  
+    if (tunnel) {
+      aProfileSelector=DEFAULT_PROFILE_ID;
+    }
+    // Note: profile database has already been opened in config resolve()
+    if (aProfileSelector==DEFAULT_PROFILE_ID) {
+      // default is first one
+      aProfileSelector=0;
+    }
+    // try to load profile
+    if (fConfigP->fProfileBinFile.readRecord(aProfileSelector,&fProfile)!=BFE_OK)
+      goto defaultprofile; // use default
+    // Now we have the profile
+    fProfileIndex=aProfileSelector;
+    fRemotepartyID=fProfile.profileID;
+    // Set session parameters
+    #ifdef SYNCML_ENCODING_OVERRIDE
+    fEncoding = SYNCML_ENCODING_OVERRIDE; // we use a globally defined encoding
+    #else
+    fEncoding = fProfile.encoding; // we use the profile's encoding
+    #endif
 
-  #ifdef HARD_CODED_SERVER_URI
-  // - Hard coded base URL of server
-  fRemoteURI=DEFAULT_SERVER_URI; // always use fixed URI
-  #else
-  // - configured URL
-  //   check config-level fixed URI first
-  if (!fConfigP->fServerURI.empty()) {
-    // override server URL from fixed value in config
-    fRemoteURI = fConfigP->fServerURI; // config
-    if (strucmp(fProfile.serverURI,fRemoteURI.c_str())!=0) {
-      PDEBUGPRINTFX(DBG_ERROR,("Warning - <serverurl> config overrides/overwrites server URL in profile"));
-      // re-adjust profile
-      AssignCString(fProfile.serverURI, fConfigP->fServerURI.c_str(), maxurisiz); // copy predefined URI back into profile
-      fProfile.readOnlyFlags |= rdonly_URI; // make it read-only
+    #ifdef HARD_CODED_SERVER_URI
+    // - Hard coded base URL of server
+    fRemoteURI=DEFAULT_SERVER_URI; // always use fixed URI
+    #else
+    // - configured URL
+    //   check config-level fixed URI first
+    if (!fConfigP->fServerURI.empty()) {
+      // override server URL from fixed value in config
+      fRemoteURI = fConfigP->fServerURI; // config
+      if (strucmp(fProfile.serverURI,fRemoteURI.c_str())!=0) {
+        PDEBUGPRINTFX(DBG_ERROR,("Warning - <serverurl> config overrides/overwrites server URL in profile"));
+        // re-adjust profile
+        AssignCString(fProfile.serverURI, fConfigP->fServerURI.c_str(), maxurisiz); // copy predefined URI back into profile
+        fProfile.readOnlyFlags |= rdonly_URI; // make it read-only
+      }
     }
-  }
-  else {
-    // use URL from profile
-    fRemoteURI=fProfile.serverURI;
-  }
-  #endif // not HARD_CODED_SERVER_URI
-  // check for URI that is a template and need inserts:
-  size_t n;
-  // - %%% check future other inserts here, \u should be last because if there's no \u, standard
-  //   CUSTOM_URI_SUFFIX mechanism may apply in else branch
-  // - \u for URIpath
-  n = fRemoteURI.find("\\u");
-  if (n!=string::npos) {
-       // URIPath may only not contain any special chars that might help to inject different server URLs
-    string up = fProfile.URIpath;
-    if (up.find_first_of(":/?.&=%,;")!=string::npos)
-       fRemoteURI.erase(n, 2); // no insert, invalid chars in URIpath
-    else
-               fRemoteURI.replace(n, 2, up); // insert URIPath instead of \u
-  }
-  #ifdef CUSTOM_URI_SUFFIX
-  else {
-       // Only if original URI is not a template
-    // - append custom URI suffix stored in serverURI field of profile (if one is set)
-    if (*(fProfile.URIpath))
-    {
-      // - append delimiter first if one defined (CUSTOM_URI_SUFFIX not NULL)
-      const char *p=CUSTOM_URI_SUFFIX;
-      if (p) fRemoteURI.append(p);
-      // - now append custom URI suffix
-      fRemoteURI.append(fProfile.URIpath);
+    else {
+      // use URL from profile
+      fRemoteURI=fProfile.serverURI;
     }
-  }
-  #endif // CUSTOM_URI_SUFFIX
-  #ifdef PROTOCOL_SELECTOR
-  fRemoteURI.insert(0,Protocol_Names[fProfile.protocol]);
-  fNoCRCPrefixLen=strlen(Protocol_Names[fProfile.protocol]);
-  #endif // PROTOCOL_SELECTOR
-  fServerUser=fProfile.serverUser;
-  getUnmangled(fServerPassword,fProfile.serverPassword,maxupwsiz);
-  // - HTTP auth
-  fTransportUser=fProfile.transportUser;
-  getUnmangled(fTransportPassword,fProfile.transportPassword,maxupwsiz);
-  // - proxy
-  fSocksHost.erase(); // default to none
-  fProxyHost.erase();
-  fProxyUser.erase();
-  fProxyPassword.erase();
-  #ifdef PROXY_SUPPORT
-  if (fProfile.useProxy)
-  {
-    fSocksHost=fProfile.socksHost;
-    fProxyHost=fProfile.proxyHost;
-    fProxyUser=fProfile.proxyUser;
-    getUnmangled(fProxyPassword,fProfile.proxyPassword,maxupwsiz);;
-    PDEBUGPRINTFX(DBG_TRANSP,("Sync Profile contains active proxy settings: http=%s, socks=%s, proxyuser=%s",fProxyHost.c_str(), fSocksHost.c_str(), fProxyUser.c_str()));
-  }
-  #endif // PROXY_SUPPORT
-  // check for forced legacy mode
-  fLegacyMode = fProfile.profileFlags & PROFILEFLAG_LEGACYMODE;
-  // check for lenient mode
-  fLenientMode = fProfile.profileFlags & PROFILEFLAG_LENIENTMODE;
-  // - get and increment session ID and save for next session
-  //   Note: as auth retries will increment the ID as well, we inc by 5
-  //         to avoid repeating the ID too soon
-  fProfile.sessionID+=5;
-  fProfileDirty=true;
-  fClientSessionNo=fProfile.sessionID;
-  // Note: loadRemoteParams will fetch the cached params from fProfile
-  // Reset session after profile change (especially fRemoteURI)
-  // and also remove any datastores we might have
-  ResetAndRemoveDatastores();
-  // in case of tunnel, don't touch datastores
-  if (tunnel) return LOCERR_OK;
-  // Now iterate trough associated target records and create datastores
-  maxidx=fConfigP->fTargetsBinFile.getNumRecords();
-  TBinfileDBSyncTarget target;
-  for (recidx=0; recidx<maxidx; recidx++) {
-    // - get record
-    if (fConfigP->fTargetsBinFile.readRecord(recidx,&target)==BFE_OK) {
-      // check if this one of my targets
-      if (target.remotepartyID == fRemotepartyID)
+    #endif // not HARD_CODED_SERVER_URI
+    // check for URI that is a template and need inserts:
+    size_t n;
+    // - %%% check future other inserts here, \u should be last because if there's no \u, standard
+    //   CUSTOM_URI_SUFFIX mechanism may apply in else branch
+    // - \u for URIpath
+    n = fRemoteURI.find("\\u");
+    if (n!=string::npos) {
+      // URIPath may only not contain any special chars that might help to inject different server URLs
+      string up = fProfile.URIpath;
+      if (up.find_first_of(":/?.&=%,;")!=string::npos)
+        fRemoteURI.erase(n, 2); // no insert, invalid chars in URIpath
+      else
+        fRemoteURI.replace(n, 2, up); // insert URIPath instead of \u
+    }
+    #ifdef CUSTOM_URI_SUFFIX
+    else {
+      // Only if original URI is not a template
+      // - append custom URI suffix stored in serverURI field of profile (if one is set)
+      if (*(fProfile.URIpath))
       {
-        // get datastore config
-        TBinfileDSConfig *binfiledscfgP = static_cast<TBinfileDSConfig *>(
-          getSessionConfig()->getLocalDS(target.dbname)
-        );
-        // check if we have config and if this DS is available now (profile.dsAvailFlags, DSFLAGS_ALWAYS_AVAILABLE, evtl. license...)
-        if (binfiledscfgP && binfiledscfgP->isAvailable(&fProfile)) {
-          // check if this DB must be synced
-          bool syncit=false;
-          #ifdef AUTOSYNC_SUPPORT
-          if (aAutoSyncSession) {
-            // target enable status is not relevant, but autosync alert is
-            syncit =
-              binfiledscfgP->fAutosyncForced ||
-              (binfiledscfgP->fAutosyncAlerted && target.enabled);
-          }
-          else {
-            // normal session
-            syncit = target.enabled && target.remoteDBpath[0]!=0; // and remote DB path specified
-            binfiledscfgP->fAutosyncAlerted=false; // this is NOT an autosync session
-            binfiledscfgP->fAutosyncForced=false;
-          }
-          #else
-          syncit = target.enabled && target.remoteDBpath[0]!=0; // and remote DB path specified
-          #endif
-          if (syncit)
-          {
-            TBinfileImplDS *binfiledsP=NULL;
-            if (binfiledscfgP) {
-              // create datastore
-              binfiledsP = static_cast<TBinfileImplDS *>(binfiledscfgP->newLocalDataStore(this));
+        // - append delimiter first if one defined (CUSTOM_URI_SUFFIX not NULL)
+        const char *p=CUSTOM_URI_SUFFIX;
+        if (p) fRemoteURI.append(p);
+        // - now append custom URI suffix
+        fRemoteURI.append(fProfile.URIpath);
+      }
+    }
+    #endif // CUSTOM_URI_SUFFIX
+    #ifdef PROTOCOL_SELECTOR
+    fRemoteURI.insert(0,Protocol_Names[fProfile.protocol]);
+    fNoCRCPrefixLen=strlen(Protocol_Names[fProfile.protocol]);
+    #endif // PROTOCOL_SELECTOR
+    fServerUser=fProfile.serverUser;
+    getUnmangled(fServerPassword,fProfile.serverPassword,maxupwsiz);
+    // - HTTP auth
+    fTransportUser=fProfile.transportUser;
+    getUnmangled(fTransportPassword,fProfile.transportPassword,maxupwsiz);
+    // - proxy
+    fSocksHost.erase(); // default to none
+    fProxyHost.erase();
+    fProxyUser.erase();
+    fProxyPassword.erase();
+    #ifdef PROXY_SUPPORT
+    if (fProfile.useProxy)
+    {
+      fSocksHost=fProfile.socksHost;
+      fProxyHost=fProfile.proxyHost;
+      fProxyUser=fProfile.proxyUser;
+      getUnmangled(fProxyPassword,fProfile.proxyPassword,maxupwsiz);;
+      PDEBUGPRINTFX(DBG_TRANSP,("Sync Profile contains active proxy settings: http=%s, socks=%s, proxyuser=%s",fProxyHost.c_str(), fSocksHost.c_str(), fProxyUser.c_str()));
+    }
+    #endif // PROXY_SUPPORT
+    // check for forced legacy mode
+    fLegacyMode = fProfile.profileFlags & PROFILEFLAG_LEGACYMODE;
+    // check for lenient mode
+    fLenientMode = fProfile.profileFlags & PROFILEFLAG_LENIENTMODE;
+    // - get and increment session ID and save for next session
+    //   Note: as auth retries will increment the ID as well, we inc by 5
+    //         to avoid repeating the ID too soon
+    fProfile.sessionID+=5;
+    fProfileDirty=true;
+    fClientSessionNo=fProfile.sessionID;
+    // Note: loadRemoteParams will fetch the cached params from fProfile
+    // Reset session after profile change (especially fRemoteURI)
+    // and also remove any datastores we might have
+    ResetAndRemoveDatastores();
+    // in case of tunnel, don't touch datastores
+    if (tunnel) return LOCERR_OK;
+    // Now iterate trough associated target records and create datastores
+    maxidx=fConfigP->fTargetsBinFile.getNumRecords();
+    TBinfileDBSyncTarget target;
+    for (recidx=0; recidx<maxidx; recidx++) {
+      // - get record
+      if (fConfigP->fTargetsBinFile.readRecord(recidx,&target)==BFE_OK) {
+        // check if this one of my targets
+        if (target.remotepartyID == fRemotepartyID)
+        {
+          // get datastore config
+          TBinfileDSConfig *binfiledscfgP = static_cast<TBinfileDSConfig *>(
+            getSessionConfig()->getLocalDS(target.dbname)
+          );
+          // check if we have config and if this DS is available now (profile.dsAvailFlags, DSFLAGS_ALWAYS_AVAILABLE, evtl. license...)
+          if (binfiledscfgP && binfiledscfgP->isAvailable(&fProfile)) {
+            // check if this DB must be synced
+            bool syncit=false;
+            #ifdef AUTOSYNC_SUPPORT
+            if (aAutoSyncSession) {
+              // target enable status is not relevant, but autosync alert is
+              syncit =
+                binfiledscfgP->fAutosyncForced ||
+                (binfiledscfgP->fAutosyncAlerted && target.enabled);
             }
-            if (binfiledsP) {
-              // copy target info to datastore for later access during sync
-              binfiledsP->fTargetIndex=recidx;
-              binfiledsP->fTarget=target;
-              // determine sync mode / flags to use
-              TSyncModes myMode;
-              bool mySlow;
-              #ifdef AUTOSYNC_SUPPORT
-              if (aAutoSyncSession && binfiledscfgP->fAutosyncAlertCode!=0) {
-                // syncmode provided from auto sync alert (e.g. SAN)
-                bool myIsSA;
-                TLocalEngineDS::getSyncModeFromAlertCode(
-                  binfiledscfgP->fAutosyncAlertCode,
+            else {
+              // normal session
+              syncit = target.enabled && target.remoteDBpath[0]!=0; // and remote DB path specified
+              binfiledscfgP->fAutosyncAlerted=false; // this is NOT an autosync session
+              binfiledscfgP->fAutosyncForced=false;
+            }
+            #else
+            syncit = target.enabled && target.remoteDBpath[0]!=0; // and remote DB path specified
+            #endif
+            if (syncit)
+            {
+              TBinfileImplDS *binfiledsP=NULL;
+              if (binfiledscfgP) {
+                // create datastore
+                binfiledsP = static_cast<TBinfileImplDS *>(binfiledscfgP->newLocalDataStore(this));
+              }
+              if (binfiledsP) {
+                // copy target info to datastore for later access during sync
+                binfiledsP->fTargetIndex=recidx;
+                binfiledsP->fTarget=target;
+                // determine sync mode / flags to use
+                TSyncModes myMode;
+                bool mySlow;
+                #ifdef AUTOSYNC_SUPPORT
+                if (aAutoSyncSession && binfiledscfgP->fAutosyncAlertCode!=0) {
+                  // syncmode provided from auto sync alert (e.g. SAN)
+                  bool myIsSA;
+                  TLocalEngineDS::getSyncModeFromAlertCode(
+                    binfiledscfgP->fAutosyncAlertCode,
+                    myMode,
+                    mySlow,
+                    myIsSA
+                  );
+                }
+                else
+                #endif
+                {
+                  // take it from config
+                  myMode = target.syncmode;
+                  mySlow = target.forceSlowSync;
+                }
+                // clean change logs if...
+                // ...this is the only profile
+                // ...this is NOT a resumable session (resumable not necessarily means that it WILL be resumed)
+                // ...we're about to slow sync
+                if (mySlow && target.resumeAlertCode==0 && fConfigP->fProfileBinFile.getNumRecords()==1) {
+                  fConfigP->cleanChangeLogForDBname(target.dbname);
+                }
+                // set non-BinFile specific parameters (note that this call might
+                // be to a derivate which uses additional info from fTarget to set sync params)
+                binfiledsP->dsSetClientSyncParams(
                   myMode,
                   mySlow,
-                  myIsSA
+                  target.remoteDBpath,
+                  NULL, // DB user
+                  NULL, // DB password
+                  NULL, // local path extension
+                  // %%% add filters here later!!!
+                  NULL, // filter query
+                  false // filter inclusive
                 );
+                // prepare local datastore (basic init can be done here) and check availability
+                if (binfiledsP->localDatastorePrep()) {
+                  // add to datastores for this sync
+                  fLocalDataStores.push_back(binfiledsP);
+                }
+                else {
+                  // silently discard (do not sync it)
+                  PDEBUGPRINTFX(DBG_ERROR,("Local Database for datastore '%s' prepares not ok -> not synced",binfiledsP->getName()));
+                  // show event (alerted for no database)
+                  OBJ_PROGRESS_EVENT(
+                    getSyncAppBase(),
+                    pev_error,
+                    binfiledscfgP,
+                    LOCERR_LOCDBNOTRDY,0,0
+                  );
+                  delete binfiledsP;
+                }
               }
-              else
-              #endif
-              {
-                // take it from config
-                myMode = target.syncmode;
-                mySlow = target.forceSlowSync;
-              }
-              // clean change logs if...
-              // ...this is the only profile
-              // ...this is NOT a resumable session (resumable not necessarily means that it WILL be resumed)
-              // ...we're about to slow sync
-              if (mySlow && target.resumeAlertCode==0 && fConfigP->fProfileBinFile.getNumRecords()==1) {
-                fConfigP->cleanChangeLogForDBname(target.dbname);
-              }
-              // set non-BinFile specific parameters (note that this call might
-              // be to a derivate which uses additional info from fTarget to set sync params)
-              binfiledsP->dsSetClientSyncParams(
-                myMode,
-                mySlow,
-                target.remoteDBpath,
-                NULL, // DB user
-                NULL, // DB password
-                NULL, // local path extension
-                // %%% add filters here later!!!
-                NULL, // filter query
-                false // filter inclusive
-              );
-              // prepare local datastore (basic init can be done here) and check availability
-              if (binfiledsP->localDatastorePrep()) {
-                // add to datastores for this sync
-                fLocalDataStores.push_back(binfiledsP);
-              }
-              else {
-                // silently discard (do not sync it)
-                PDEBUGPRINTFX(DBG_ERROR,("Local Database for datastore '%s' prepares not ok -> not synced",binfiledsP->getName()));
-                // show event (alerted for no database)
-                OBJ_PROGRESS_EVENT(
-                  getSyncAppBase(),
-                  pev_error,
-                  binfiledscfgP,
-                  LOCERR_LOCDBNOTRDY,0,0
-                );
-                delete binfiledsP;
-              }
-            }
-          } // if target DB enabled for sync
-        } // if we have a datastore config for this target
-      } // if target belongs to this profile
-    } // if we can read the target record
-  } // for all target records
-  // ok if at least one datastore enabled
-  return fLocalDataStores.size()>0 && fRemoteURI.size()>0 ? LOCERR_OK : LOCERR_NOCFG;
+            } // if target DB enabled for sync
+          } // if we have a datastore config for this target
+        } // if target belongs to this profile
+      } // if we can read the target record
+    } // for all target records
+    // ok if at least one datastore enabled
+    return fLocalDataStores.size()>0 && fRemoteURI.size()>0 ? LOCERR_OK : LOCERR_NOCFG;
+  } // active
 defaultprofile:
   return inherited::SelectProfile(aProfileSelector, aAutoSyncSession);
 } // TBinfileImplClient::SelectProfile
index f839310..5c3a7bc 100755 (executable)
 #include "stdlogicagent.h"
 #include "binfileimplds.h"
 #include "engineinterface.h"
+#include "syncclientbase.h"
 
 #ifndef SYSYNC_CLIENT
-  #error "binfileimplclient is CLIENT-ONLY!"
+  #error "binfileimplclient only makes sense with client datastores"
 #endif
 
 namespace sysync {
@@ -37,7 +38,7 @@ namespace sysync {
 #ifdef ENGINEINTERFACE_SUPPORT
 
 // forward
-class TBinfileClientRootKey;
+class TBinfileAgentRootKey;
 class TBinfileClientConfig;
 
 // Engine module class
@@ -333,33 +334,22 @@ private:
 
 
 // Binfile based client settings rootkey
-class TBinfileClientRootKey :
+class TBinfileAgentRootKey :
   public TSettingsRootKey
 {
   typedef TSettingsRootKey inherited;
 
 public:
-  TBinfileClientRootKey(TEngineInterface *aEngineInterfaceP) :
-    inherited(aEngineInterfaceP) {};
+  TBinfileAgentRootKey(TEngineInterface *aEngineInterfaceP);
 
 protected:
   // open subkey by name (not by path!)
-  // - this is the actual implementation
   virtual TSyError OpenSubKeyByName(
     TSettingsKeyImpl *&aSettingsKeyP,
     cAppCharP aName, stringSize aNameSize,
     uInt16 aMode
-  ) {
-    if (strucmp(aName,"profiles",aNameSize)==0)
-      aSettingsKeyP = new TBinfileProfilesKey(fEngineInterfaceP);
-    else if (strucmp(aName,"synclogs",aNameSize)==0)
-      aSettingsKeyP = new TBinfileLogsKey(fEngineInterfaceP);
-    else
-      return inherited::OpenSubKeyByName(aSettingsKeyP,aName,aNameSize,aMode);
-    // opened a key
-    return LOCERR_OK;
-  };
-}; // TBinfileClientRootKey
+  );
+}; // TBinfileAgentRootKey
 
 
 
@@ -370,9 +360,9 @@ protected:
 // ======
 
 class TBinfileClientConfig:
-  public TClientConfig
+  public TAgentConfig
 {
-  typedef TClientConfig inherited;
+  typedef TAgentConfig inherited;
 public:
   TBinfileClientConfig(TConfigElement *aParentElement);
   virtual ~TBinfileClientConfig();
@@ -468,6 +458,8 @@ public:
   );
   // - get path where to store binfiles
   void getBinFilesPath(string &aPath);
+  // activtion switch (for making it inactive e.g. in server case)
+  bool fBinfilesActive;
   #ifndef HARDCODED_CONFIG
   // - configurable path where to store binfiles
   string fBinFilesPath;
@@ -509,10 +501,12 @@ class TBinfileImplClient: public TStdLogicAgent
 {
   typedef TStdLogicAgent inherited;
   #ifdef ENGINEINTERFACE_SUPPORT
-  friend class TBinFileClientParamsKey;
+  friend class TBinFileAgentParamsKey;
   #endif
 public:
-  TBinfileImplClient(TSyncClientBase *aSyncClientBaseP, const char *aSessionID);
+  TBinfileImplClient(TSyncAppBase *aSyncAppBaseP, TSyncSessionHandle *aSyncSessionHandleP, cAppCharP aSessionID);
+  /// check if active derived classes (in particular: customImplDS that CAN derive binfiles, but does not necessarily so)
+  bool binfilesActive(void) { return fConfigP && fConfigP->fBinfilesActive; };
   // - selects a profile (returns false if profile not found)
   //   Note: This call must create and initialize all datastores that
   //         are to be synced with that profile.
@@ -566,24 +560,23 @@ private:
 // =========================================
 
 // client runtime parameters
-class TBinFileClientParamsKey :
-  public TClientParamsKey
+class TBinFileAgentParamsKey :
+  public TAgentParamsKey
 {
-  typedef TClientParamsKey inherited;
+  typedef TAgentParamsKey inherited;
 
 public:
-  TBinFileClientParamsKey(TEngineInterface *aEngineInterfaceP, TSyncClient *aClientSessionP);
-  virtual ~TBinFileClientParamsKey() {};
+  TBinFileAgentParamsKey(TEngineInterface *aEngineInterfaceP, TSyncAgent *aClientSessionP);
+  virtual ~TBinFileAgentParamsKey() {};
 
 protected:
   // open subkey by name (not by path!)
-  // - this is the actual implementation
   virtual TSyError OpenSubKeyByName(
     TSettingsKeyImpl *&aSettingsKeyP,
     cAppCharP aName, stringSize aNameSize,
     uInt16 aMode
   );
-}; // TBinFileClientParamsKey
+}; // TBinFileAgentParamsKey
 
 
 #endif // ENGINEINTERFACE_SUPPORT
index 7b8580b..77a32b9 100755 (executable)
 #include "binfileimplclient.h"
 #include "binfileimplds.h"
 
+#if defined(BINFILE_ALWAYS_ACTIVE) && defined(SYSYNC_SERVER)
+       #error "BINFILE_ALWAYS_ACTIVE is not compatible with server-enabled builds"
+#endif
+
 
 namespace sysync {
 
@@ -206,6 +210,8 @@ TBinfileDSConfig::~TBinfileDSConfig()
 // init defaults
 void TBinfileDSConfig::clear(void)
 {
+       // Only active in clients by default
+       fBinfileDSActive = IS_CLIENT;
   // init defaults
   fLocalDBPath.erase();
   fDSAvailFlag=0;
@@ -232,6 +238,8 @@ bool TBinfileDSConfig::localStartElement(const char *aElementName, const char **
     expectUInt16(fDSAvailFlag);
   else if (strucmp(aElementName,"cmptimestampatend")==0)
     expectBool(fCmpRefTimeStampAtEnd);
+  else if (strucmp(aElementName,"binfiledsactive")==0)
+    expectBool(fBinfileDSActive);
   // - none known here
   else
     return TLocalDSConfig::localStartElement(aElementName,aAttributes,aLine);
@@ -362,8 +370,10 @@ void TBinfileImplDS::dsResetDataStore(void)
   InternalResetDataStore();
   // Let ancestor initialize
   inherited::dsResetDataStore();
-  // And now force MaxGUIDSize to what this datastore can handle
-  fMaxGUIDSize=BINFILE_MAXGUIDSIZE;
+  if (binfileDSActive()) {
+    // And now force MaxGUIDSize to what this datastore can handle
+    fMaxGUIDSize=BINFILE_MAXGUIDSIZE;
+  }
 } // TBinfileImplDS::dsResetDataStore
 
 
@@ -426,20 +436,22 @@ bool TBinfileImplDS::dsSetClientSyncParams(
   bool aFilterInclusive
 )
 {
-  #ifdef AUTOSYNC_SUPPORT
-  string s;
-  bool cgi=false;
-  // add autosync options if this is an autosync
-  if (fConfigP->fAutosyncAlerted || fConfigP->fAutosyncForced) {
-    if (!fConfigP->fAutosyncPathCGI.empty()) {
-      s=aRemoteDBPath;
-      cgi = s.find('?')!=string::npos;
-      if (!cgi) { s+='?'; cgi=true; }
-      s += fConfigP->fAutosyncPathCGI;
-      aRemoteDBPath=s.c_str();
+       if (binfileDSActive()) {
+    #ifdef AUTOSYNC_SUPPORT
+    string s;
+    bool cgi=false;
+    // add autosync options if this is an autosync
+    if (fConfigP->fAutosyncAlerted || fConfigP->fAutosyncForced) {
+      if (!fConfigP->fAutosyncPathCGI.empty()) {
+        s=aRemoteDBPath;
+        cgi = s.find('?')!=string::npos;
+        if (!cgi) { s+='?'; cgi=true; }
+        s += fConfigP->fAutosyncPathCGI;
+        aRemoteDBPath=s.c_str();
+      }
     }
+    #endif
   }
-  #endif
   return inherited::dsSetClientSyncParams(aSyncMode,aSlowSync,aRemoteDBPath,aDBUser,aDBPassword,aLocalPathExtension,aRecordFilterQuery,aFilterInclusive);
 } // TBinfileImplDS::dsSetClientSyncParams
 
@@ -1045,6 +1057,8 @@ localstatus TBinfileImplDS::implMakeAdminReady(
   cAppCharP aRemoteDBID  // database ID of remote device
 )
 {
+       if (!binfileDSActive()) return LOCERR_WRONGUSAGE; // must be active when called at all
+
   localstatus sta=LOCERR_OK; // assume ok
 
   PDEBUGBLOCKDESCCOLL("implMakeAdminReady","Loading target info and pending maps");
@@ -1214,6 +1228,8 @@ localstatus TBinfileImplDS::implMakeAdminReady(
 
 localstatus TBinfileImplDS::implStartDataRead()
 {
+       if (!binfileDSActive()) return LOCERR_WRONGUSAGE; // must be active when called at all
+
   // init reading of all records
   /// @todo: check if there are other cases where we need all records even if not slow sync - probably with filters only
   fAllRecords=fSlowSync;
@@ -1223,6 +1239,8 @@ localstatus TBinfileImplDS::implStartDataRead()
 } // TBinfileImplDS::implStartDataRead
 
 
+/* %%% seems obsolete - never called from anywhere
+
 #ifdef OBJECT_FILTERING
 
 // Test Filters
@@ -1242,11 +1260,13 @@ bool TBinfileImplDS::testFilters(TMultiFieldItem *aItemP)
 
 #endif
 
+*/
 
 /// @brief called to have all non-yet-generated sync commands as "to-be-resumed"
 void TBinfileImplDS::implMarkOnlyUngeneratedForResume(void)
 {
-
+       if (!binfileDSActive()) return; // must be active when called at all
+  
   TChangeLogEntry *chglogP;
 
   // simply return aEof when just refreshing
@@ -1331,6 +1351,8 @@ void TBinfileImplDS::implMarkOnlyUngeneratedForResume(void)
 // as "to-be-resumed", by localID or remoteID (latter only in server case).
 void TBinfileImplDS::implMarkItemForResume(cAppCharP aLocalID, cAppCharP aRemoteID, bool aUnSent)
 {
+       if (!binfileDSActive()) return; // must be active when called at all
+
   // make sure we have the changelog in memory
   loadChangeLog();
   localid_out_t locID;
@@ -1364,6 +1386,8 @@ void TBinfileImplDS::implMarkItemForResume(cAppCharP aLocalID, cAppCharP aRemote
 // error status conditions, by localID or remoteID (latter only in server case).
 void TBinfileImplDS::implMarkItemForResend(cAppCharP aLocalID, cAppCharP aRemoteID)
 {
+       if (!binfileDSActive()) return; // must be active when called at all
+
   // make sure we have the changelog in memory
   loadChangeLog();
   localid_out_t locID;
@@ -1401,6 +1425,8 @@ localstatus TBinfileImplDS::implGetItem(
   TSyncItem* &aSyncItemP
 )
 {
+       if (!binfileDSActive()) return LOCERR_WRONGUSAGE; // must be active when called at all
+
   localstatus sta=LOCERR_OK;
   TSyncItem *myitemP=NULL;
   TChangeLogEntry *chglogP;
@@ -1597,6 +1623,8 @@ error:
 // end of read
 localstatus TBinfileImplDS::implEndDataRead(void)
 {
+       if (!binfileDSActive()) return LOCERR_WRONGUSAGE; // must be active when called at all
+
   // pass it on to the DB api (usually dummy for traditional binfile derivates, but
   // needed for customimplds)
   return apiEndDataRead();
@@ -1650,6 +1678,8 @@ void TBinfileImplDS::loadChangeLog(void)
 // start of write
 localstatus TBinfileImplDS::implStartDataWrite(void)
 {
+       if (!binfileDSActive()) return LOCERR_WRONGUSAGE; // must be active when called at all
+
   localstatus sta = LOCERR_OK;
 
   // latest chance to do preflight in case GetItem was never called
@@ -1725,6 +1755,7 @@ bool TBinfileImplDS::implRetrieveItemByID(
   TStatusCommand &aStatusCommand
 )
 {
+       if (!binfileDSActive()) return LOCERR_WRONGUSAGE; // must be active when called at all
   // %%% not so nice as we need to copy it once
   TSyncItem *itemP=NULL;
   // read item by local ID
@@ -1758,6 +1789,8 @@ bool TBinfileImplDS::implProcessItem(
   TStatusCommand &aStatusCommand
 )
 {
+       if (!binfileDSActive()) return LOCERR_WRONGUSAGE; // must be active when called at all
+
   localid_out_t newid;
   TSyError statuscode;
   localstatus sta;
@@ -1941,8 +1974,10 @@ done:
 // @note aSyncOp passed not necessarily reflects what was sent to remote, but what actually happened
 void TBinfileImplDS::dsConfirmItemOp(TSyncOperation aSyncOp, cAppCharP aLocalID, cAppCharP aRemoteID, bool aSuccess, localstatus aErrorStatus)
 {
-  // Nothing to do here, even successful deletes must not delete changelog entry (this will be done
-  // by changeLogPostFlight() for those enties that have been reported as deleted in all profiles!)
+       if (binfileDSActive()) {
+    // Nothing to do here, even successful deletes must not delete changelog entry (this will be done
+    // by changeLogPostFlight() for those enties that have been reported as deleted in all profiles!)
+  }
   // - let inherited know as well
   inherited::dsConfirmItemOp(aSyncOp, aLocalID, aRemoteID, aSuccess, aErrorStatus);
 } // TBinfileImplDS::confirmItemOp
@@ -1953,6 +1988,8 @@ void TBinfileImplDS::dsConfirmItemOp(TSyncOperation aSyncOp, cAppCharP aLocalID,
 //   (or, in case the session is really complete, make sure that no resume state is left)
 localstatus TBinfileImplDS::implSaveResumeMarks(void)
 {
+       if (!binfileDSActive()) return LOCERR_WRONGUSAGE; // must be active when called at all
+  
   // update modcount reference of last suspend
   fPreviousSuspendModCount = fCurrentModCount;
   // save admin data now
@@ -1965,6 +2002,7 @@ localstatus TBinfileImplDS::implSaveResumeMarks(void)
 // - Called at end of sync with this datastore
 void TBinfileImplDS::dsLogSyncResult(void)
 {
+       // Note: binfile logs can be active even if binfiles layer otherwise is not active
        TBinfileClientConfig *clientCfgP = static_cast<TBinfileClientConfig *>(fSessionP->getSessionConfig());
        if (clientCfgP->fBinFileLog) {
        // writing binfile logs enabled
@@ -2015,6 +2053,8 @@ void TBinfileImplDS::dsLogSyncResult(void)
 // be called by the derivate after doing customimpl specific stuff.
 localstatus TBinfileImplDS::implSaveEndOfSession(bool aUpdateAnchors)
 {
+       if (!binfileDSActive()) return LOCERR_WRONGUSAGE; // must be active when called at all
+
   // update TCustomImplDS dsSavedAdmin variables (other levels have already updated their variables
   if (aUpdateAnchors) {
     if (!fRefreshOnly || fSlowSync) {
@@ -2062,6 +2102,8 @@ localstatus TBinfileImplDS::implSaveEndOfSession(bool aUpdateAnchors)
 // - end write with commit
 bool TBinfileImplDS::implEndDataWrite(void)
 {
+       if (!binfileDSActive()) return LOCERR_WRONGUSAGE; // must be active when called at all
+
   // Call apiEndDataWrite variant which is possibly implemented in
   // datastores which were designed as direct derivates of binfileds.
   // Note that in BASED_ON_BINFILE_CLIENT case, implEndDataWrite() is
index d9fb6f7..f0c0141 100755 (executable)
@@ -636,6 +636,8 @@ public:
   TBinfileDSConfig(const char* aName, TConfigElement *aParentElement);
   virtual ~TBinfileDSConfig();
   // properties
+  // - activtion switch (for making it inactive e.g. in server case)
+  bool fBinfileDSActive;
   // - identifies local Database related to this datastore
   string fLocalDBPath;
   // - flag that corresponds with profile.dsAvailFlags / dsavail_xxx
@@ -854,15 +856,15 @@ protected:
   /// get next item from the sync set. Caller obtains ownership if aItemP is not NULL after return
   /// @return false if no item found
   virtual bool getNextItem(TSyncItem *&aItemP) = 0;
-  #endif
-  #else
+  #endif // RECORDHASH_FROM_DBAPI
+  #else // CHANGEDETECTION_AVAILABLE
   /// get first item's ID and modification status from the sync set
   /// @return false if no item found
   virtual bool getFirstItemInfo(localid_out_t &aLocalID, bool &aItemHasChanged) = 0;
   /// get next item's ID and modification status from the sync set.
   /// @return false if no item found
   virtual bool getNextItemInfo(localid_out_t &aLocalID, bool &aItemHasChanged) = 0;
-  #endif
+  #endif // not CHANGEDETECTION_AVAILABLE
   /// get item by local ID from the sync set. Caller obtains ownership if aItemP is not NULL after return
   /// @return != LOCERR_OK  if item with specified ID is not found.
   virtual localstatus getItemByID(localid_t aLocalID, TSyncItem *&aItemP) = 0;
@@ -870,7 +872,7 @@ protected:
   /// get specified item's CRC as calculated by DB
   /// @return != LOCERR_OK  if item with specified ID is not found.
   virtual localstatus getItemCRCByID(localid_t aLocalID, uInt16 &aItemCRC) = 0;
-  #endif
+  #endif // RECORDHASH_FROM_DBAPI
   /// end of syncset reading phase (especially for customimplds on top of binfileds)
   virtual localstatus apiEndDataRead(void) { return LOCERR_OK; };
   /// signal start of data write phase
@@ -908,6 +910,8 @@ protected:
   /// zaps changelog. Should be called if datastore as a entiety was replaced
   /// by another datatstore (or created new)
   void zapChangeLog(void);
+  /// check if active derived classes (in particular: customImplDS that CAN derive binfiles, but does not necessarily so)
+  bool binfileDSActive(void) { return fConfigP && fConfigP->fBinfileDSActive; };
 private:
   /// load changelog into memory for quick access
   void loadChangeLog(void);
@@ -917,11 +921,13 @@ private:
   localstatus SaveAdminData(bool aSessionFinished, bool aSuccessful);
   /// load target record for this datastore
        localstatus loadTarget(bool aCreateIfMissing, cAppCharP aRemoteDBID=NULL);
+  /* %%% seems obsolete - never called from anywhere
   // private utils
   #ifdef OBJECT_FILTERING
   // - Test Filters
   bool testFilters(TMultiFieldItem *aItemP);
   #endif
+  */
   // sync anchor, time and changelog cursor (modcount)
   #ifdef CHECKSUM_CHANGELOG
   /// change log
@@ -940,7 +946,7 @@ private:
   // - entire change log, loaded into memory for quick reference during write phase
   TChangeLogEntry *fLoadedChangeLog;
   uInt32 fLoadedChangeLogEntries;
-  #endif
+  #endif // CHECKSUM_CHANGELOG
   /// pending maps for Resume
   TBinFile fPendingMaps; ///< pending map binfile
   TPendingMapHeader fPendingMapHeader; ///< pending map header
index 940600b..65f4af4 100755 (executable)
@@ -135,10 +135,8 @@ sInt64 lineartimeToDbInt(lineartime_t aLinearTime, TDBFieldType aDbfty)
 TCustomAgentConfig::TCustomAgentConfig(TConfigElement *aParentElement) :
   #ifdef BASED_ON_BINFILE_CLIENT
   TBinfileClientConfig(aParentElement)
-  #elif defined(SYSYNC_CLIENT)
-  TClientConfig("CustomClient",aParentElement)
   #else
-  TServerConfig("CustomServer",aParentElement)
+  TAgentConfig("CustomAgent",aParentElement)
   #endif
   #ifdef SCRIPT_SUPPORT
   , fResolverContext(NULL)
@@ -163,7 +161,7 @@ void TCustomAgentConfig::clear(void)
   fDataCharSet=chs_ansi; // assume ANSI, is probable for ODBC connection
   fDataLineEndMode=lem_dos; // default to CRLF, as this seems to be safest assumption
   // resolver context
-  #ifndef BASED_ON_BINFILE_CLIENT
+  #ifndef BINFILE_ALWAYS_ACTIVE
   #ifdef SCRIPT_SUPPORT
   fLoginInitScript.erase();
   fLoginCheckScript.erase();
@@ -173,7 +171,7 @@ void TCustomAgentConfig::clear(void)
     fResolverContext=NULL;
   }
   #endif
-  #endif
+  #endif // BINFILE_ALWAYS_ACTIVE
   // clear inherited
   inherited::clear();
 } // TCustomAgentConfig::clear
@@ -189,7 +187,7 @@ void TCustomAgentConfig::clear(void)
 class TCustomAgentFuncs {
 public:
 
-  #ifndef BASED_ON_BINFILE_CLIENT
+  #ifndef BINFILE_ALWAYS_ACTIVE
   // Login context functions
 
   // integer CHECKAUTH(string user, string secret, integer secretismd5)
@@ -354,7 +352,7 @@ public:
     );
   }; // func_SetDeviceKey
 
-  #endif // not BASED_ON_BINFILE_CLIENT
+  #endif // not BINFILE_ALWAYS_ACTIVE
 
 
   // timestamp DBINTTOTIMESTAMP(integer dbint,string dbfieldtype)
@@ -434,7 +432,7 @@ const uInt8 param_oneInteger[] = { VAL(fty_integer) };
 const uInt8 param_variant[] = { VAL(fty_none) };
 
 
-#ifndef BASED_ON_BINFILE_CLIENT
+#ifndef BINFILE_ALWAYS_ACTIVE
 
 // builtin function table for login context
 const TBuiltInFuncDef CustomAgentFuncDefs[numCustomAgentFuncs] = {
@@ -451,12 +449,12 @@ const TBuiltInFuncDef CustomAgentFuncDefs[numCustomAgentFuncs] = {
   { "SETDEVICEKEY", TCustomAgentFuncs::func_SetDeviceKey, fty_none, 1, param_variant },
 };
 
-#endif // not BASED_ON_BINFILE_CLIENT
+#endif // not BINFILE_ALWAYS_ACTIVE
 
 
 // builtin function defs for customImpl database and login contexts
 const TBuiltInFuncDef CustomAgentAndDSFuncDefs[numCustomAgentAndDSFuncs] = {
-  #ifndef BASED_ON_BINFILE_CLIENT
+  #ifndef BINFILE_ALWAYS_ACTIVE
   { "DEVICEKEY", TCustomAgentFuncs::func_DeviceKey, fty_string, 0, NULL },
   { "USERKEY", TCustomAgentFuncs::func_UserKey, fty_string, 0, NULL },
   #endif
@@ -466,7 +464,7 @@ const TBuiltInFuncDef CustomAgentAndDSFuncDefs[numCustomAgentAndDSFuncs] = {
 };
 
 
-#ifndef BASED_ON_BINFILE_CLIENT
+#ifndef BINFILE_ALWAYS_ACTIVE
 
 // function table which is chained from login-context function table
 const TFuncTable CustomAgentFuncTable2 = {
@@ -493,7 +491,7 @@ const TFuncTable CustomAgentFuncTable = {
   CustomAgentChainFunc // chain to general agent funcs.
 };
 
-#endif // not BASED_ON_BINFILE_CLIENT
+#endif // not BINFILE_ALWAYS_ACTIVE
 
 
 // chain from agent funcs to custom datastore funcs (when chained via CustomDSFuncTable1
@@ -524,7 +522,7 @@ const TFuncTable CustomDSFuncTable1 = {
 bool TCustomAgentConfig::localStartElement(const char *aElementName, const char **aAttributes, sInt32 aLine)
 {
   // checking the elements
-  #ifndef BASED_ON_BINFILE_CLIENT
+  #ifndef BINFILE_ALWAYS_ACTIVE
   #ifdef SCRIPT_SUPPORT
   if (strucmp(aElementName,"logininitscript")==0)
     expectScript(fLoginInitScript,aLine,getAgentFuncTableP());
@@ -534,7 +532,7 @@ bool TCustomAgentConfig::localStartElement(const char *aElementName, const char
     expectScript(fLoginFinishScript,aLine,getAgentFuncTableP());
   else
   #endif // SCRIPT_SUPPORT
-  #endif // BASED_ON_BINFILE_CLIENT
+  #endif // BINFILE_ALWAYS_ACTIVE
   // - session level Date/Time info
   if (
     strucmp(aElementName,"timestamputc")==0 || // old 2.1 compatible
@@ -567,7 +565,7 @@ void TCustomAgentConfig::localResolve(bool aLastPass)
     fCurrentDateTimeZone = TCTX_UTC;
   // Scripts etc.
   if (aLastPass) {
-    #ifndef BASED_ON_BINFILE_CLIENT
+    #ifndef BINFILE_ALWAYS_ACTIVE
     #ifdef SCRIPT_SUPPORT
     // login scripting
     TScriptContext::resolveScript(getSyncAppBase(),fLoginInitScript,fResolverContext,NULL);
@@ -579,7 +577,7 @@ void TCustomAgentConfig::localResolve(bool aLastPass)
     if (fResolverContext) delete fResolverContext;
     fResolverContext=NULL;
     #endif
-    #endif // not BASED_ON_BINFILE_CLIENT
+    #endif // not BINFILE_ALWAYS_ACTIVE
   }
   // resolve inherited
   inherited::localResolve(aLastPass);
@@ -591,13 +589,8 @@ void TCustomAgentConfig::localResolve(bool aLastPass)
 /* public TCustomImplAgent members */
 
 
-#ifdef SYSYNC_CLIENT
-TCustomImplAgent::TCustomImplAgent(TSyncClientBase *aSyncClientBaseP, const char *aSessionID) :
-  inherited(aSyncClientBaseP, aSessionID),
-#else
-TCustomImplAgent::TCustomImplAgent(TSyncAppBase *aAppBaseP, TSyncSessionHandle *aSessionHandleP, const char *aSessionID) :
+TCustomImplAgent::TCustomImplAgent(TSyncAppBase *aAppBaseP, TSyncSessionHandle *aSessionHandleP, cAppCharP aSessionID) :
   inherited(aAppBaseP, aSessionHandleP, aSessionID),
-#endif
   fConfigP(NULL)
   #ifdef SCRIPT_SUPPORT
   ,fScriptContextDatastore(NULL)
@@ -611,7 +604,7 @@ TCustomImplAgent::TCustomImplAgent(TSyncAppBase *aAppBaseP, TSyncSessionHandle *
 {
   // get config for agent and save direct link to agent config for easy reference
   fConfigP = static_cast<TCustomAgentConfig *>(getRootConfig()->fAgentConfigP);
-  #ifndef BASED_ON_BINFILE_CLIENT
+  #ifndef BINFILE_ALWAYS_ACTIVE
   #ifdef SCRIPT_SUPPORT
   // create login script context if there are scripts
   // Note: derivates might already have initialized fAgentContext here, that's why we
@@ -621,7 +614,7 @@ TCustomImplAgent::TCustomImplAgent(TSyncAppBase *aAppBaseP, TSyncSessionHandle *
   TScriptContext::rebuildContext(getSyncAppBase(),fConfigP->fLoginFinishScript,fAgentContext,this,true); // now build vars
   // Note: derivates will rebuild NOW, AFTER our rebuilds, in the derived constructor
   #endif
-  #endif
+  #endif // BINFILE_ALWAYS_ACTIVE
   // Note: Datastores are already created from config
 } // TCustomImplAgent::TCustomImplAgent
 
@@ -714,13 +707,7 @@ TLocalEngineDS *TCustomImplAgent::getTunnelDS()
 
 
 
-
-
-
-
-
-
-#ifndef BASED_ON_BINFILE_CLIENT
+#ifndef BINFILE_ALWAYS_ACTIVE
 
 // check credential string
 // Note: if authentication is successful, odbcDBServer session
@@ -728,27 +715,35 @@ TLocalEngineDS *TCustomImplAgent::getTunnelDS()
 //       DB accesses.
 bool TCustomImplAgent::SessionLogin(const char *aUserName, const char *aAuthString, TAuthSecretTypes aAuthStringType, const char *aDeviceID)
 {
+       #ifdef BASED_ON_BINFILE_CLIENT
+       // let binfile handle it if it is active
+  if (binfilesActive()) {
+       return inherited::SessionLogin(aUserName, aAuthString, aAuthStringType, aDeviceID);
+  }
+  #endif // BASED_ON_BINFILE_CLIENT
+  
   bool authok = false;
   string nonce;
-  bool neednonce = aAuthStringType==sectyp_md5_V10 || aAuthStringType==sectyp_md5_V11;
 
   if (!fConfigP) return false; // no config -> fail early (no need for cleanup)
 
   #ifdef SYSYNC_CLIENT
-  #ifndef NO_LOCAL_DBLOGIN
-  // check for eventual client without need for local DB login
-  if (fNoLocalDBLogin) {
-    // just use local DB login name as user key (userkey is probably not needed anyway)
-    fUserKey=fLocalDBUser;
-    // accept as auth ok
-    return true; // return early, no need for cleanup
+  if (IS_CLIENT) {
+    #ifndef NO_LOCAL_DBLOGIN
+    // check for eventual client without need for local DB login
+    if (fNoLocalDBLogin) {
+      // just use local DB login name as user key (userkey is probably not needed anyway)
+      fUserKey=fLocalDBUser;
+      // accept as auth ok
+      return true; // return early, no need for cleanup
+    }
+    #else
+    // client without need for local login
+    return true;
+    //#warning "we could probably eliminate much more code here"
+    #endif
   }
-  #else
-  // client without need for local login
-  return true;
-  #warning "we could probably eliminate much more code here"
-  #endif
-  #endif
+  #endif // SYSYNC_CLIENT
   // first step: set defaults
   fUserKey=aUserName; // user key is equal to user name
   fDeviceKey=aDeviceID; // device key is equal to device name
@@ -841,7 +836,7 @@ cleanup:
   return authok;
 } // TCustomImplAgent::SessionLogin
 
-#endif // BASED_ON_BINFILE_CLIENT
+#endif // BINFILE_ALWAYS_ACTIVE
 
 
 } // namespace sysync
index 47cba5b..e3c63b0 100755 (executable)
@@ -39,7 +39,7 @@ extern const TFuncTable CustomDSFuncTable1;
 // - define count here as derivates will access the funcdefs table directly
 const int numCustomAgentFuncs=14;
 extern const TBuiltInFuncDef CustomAgentFuncDefs[numCustomAgentFuncs];
-#ifndef BASED_ON_BINFILE_CLIENT
+#ifndef BINFILE_ALWAYS_ACTIVE
   const int numCustomAgentAndDSFuncs=5;
 #else
   const int numCustomAgentAndDSFuncs=3;
@@ -95,18 +95,14 @@ class TScriptContext;
 class TCustomAgentConfig:
   #ifdef BASED_ON_BINFILE_CLIENT
   public TBinfileClientConfig
-  #elif defined(SYSYNC_CLIENT)
-  public TClientConfig
   #else
-  public TServerConfig
+  public TAgentConfig
   #endif
 {
   #ifdef BASED_ON_BINFILE_CLIENT
   typedef TBinfileClientConfig inherited;
-  #elif defined(SYSYNC_CLIENT)
-  typedef TClientConfig inherited;
   #else
-  typedef TServerConfig inherited;
+  typedef TAgentConfig inherited;
   #endif
 public:
   TCustomAgentConfig(TConfigElement *aParentElement);
@@ -164,11 +160,7 @@ class TCustomImplAgent:
   typedef TStdLogicAgent inherited;
   #endif
 public:
-  #ifdef SYSYNC_CLIENT
-  TCustomImplAgent(TSyncClientBase *aSyncClientBaseP, const char *aSessionID);
-  #else
-  TCustomImplAgent(TSyncAppBase *aAppBaseP, TSyncSessionHandle *aSessionHandleP, const char *aSessionID);
-  #endif
+  TCustomImplAgent(TSyncAppBase *aAppBaseP, TSyncSessionHandle *aSessionHandleP, cAppCharP aSessionID);
   virtual ~TCustomImplAgent();
   virtual void TerminateSession(void); // Terminate session, like destructor, but without actually destructing object itself
   virtual void ResetSession(void); // Resets session (but unlike TerminateSession, session might be re-used)
@@ -184,8 +176,12 @@ public:
   virtual localstatus InitializeTunnelSession(cAppCharP aDatastoreName);
   virtual TLocalEngineDS *getTunnelDS();
   #endif
-  // Login and device management only if not based on binfile client
   #ifndef BASED_ON_BINFILE_CLIENT
+  // if binfiles are not compiled in, they are always inactive (otherwise binfileclient parent defines this method)
+  bool binfilesActive(void) { return false; };  
+  #endif
+  // Login and device management only if not exclusively based on binfile client
+  #ifndef BINFILE_ALWAYS_ACTIVE
   // - login for this session
   virtual bool SessionLogin(const char *aUserName, const char *aAuthString, TAuthSecretTypes aAuthStringType, const char *aDeviceID);
   // - clean up after all login activity is over (including finishscript)
@@ -214,7 +210,7 @@ protected:
   // - remote device is analyzed, eventually save status
   virtual void remoteAnalyzed(void) { /* NOP at this level */ };
   // script contexts
-  #endif // BASED_ON_BINFILE_CLIENT
+  #endif // BINFILE_ALWAYS_ACTIVE
   #ifdef SCRIPT_SUPPORT
   TScriptContext *fAgentContext;
   #endif // SCRIPT_SUPPORT
index 15d635c..9290c9b 100755 (executable)
@@ -27,7 +27,7 @@
 
 namespace sysync {
 
-#ifndef BASED_ON_BINFILE_CLIENT
+#ifndef BINFILE_ALWAYS_ACTIVE
 #ifdef SYDEBUG
 const char * const MapEntryTypeNames[numMapEntryTypes] = {
   "invalid",
@@ -36,7 +36,7 @@ const char * const MapEntryTypeNames[numMapEntryTypes] = {
   "pendingmap"
 };
 #endif
-#endif // not BASED_ON_BINFILE_CLIENTs
+#endif // not BINFILE_ALWAYS_ACTIVE
 
 
 #ifdef SCRIPT_SUPPORT
@@ -212,14 +212,14 @@ void TCustomDSConfig::clear(void)
   fDataIsUTC=false; // compatibility flag only, will set fDataTimeZone to TCTX_UTC at Resolve if set
   fDataTimeZone=TCTX_SYSTEM; // default to local system time
   fUserZoneOutput=true; // by default, non-floating timestamps are moved to user zone after reading from DB. Only if zone context for timestamp fields is really retrieved from the DB on a per record level, this can be switched off
-  #ifndef BASED_ON_BINFILE_CLIENT
+  #ifndef BINFILE_ALWAYS_ACTIVE
   // - flag indicating that admin tables have DS 1.2 support (map entrytype, map flags, fResumeAlertCode, fLastSuspend, fLastSuspendIdentifier
   fResumeSupport=false;
   fResumeItemSupport=false; // no item resume as well
   // - admin capability info
   fSyncTimeStampAtEnd=false; // if set, time point of sync is taken AFTER last write to DB (for single-user DBs like FMPro). Note that target table layout is different in this case!
   fOneWayFromRemoteSupported=false; // compatible with old layout of target tables, no support
-  #endif // not BASED_ON_BINFILE_CLIENT
+  #endif // not BINFILE_ALWAYS_ACTIVE
   fStoreSyncIdentifiers=false; // compatible with old layout of target tables, no support
   // clear embedded
   fFieldMappings.clear();
@@ -263,7 +263,7 @@ bool TCustomDSConfig::localStartElement(const char *aElementName, const char **a
     expectTimezone(fDataTimeZone);
   else if (strucmp(aElementName,"userzoneoutput")==0)
     expectBool(fUserZoneOutput);
-  #ifndef BASED_ON_BINFILE_CLIENT
+  #ifndef BINFILE_ALWAYS_ACTIVE
   // - admin capability info
   else if (strucmp(aElementName,"synctimestampatend")==0)
     expectBool(fSyncTimeStampAtEnd);
@@ -273,7 +273,7 @@ bool TCustomDSConfig::localStartElement(const char *aElementName, const char **a
     expectBool(fResumeSupport);
   else if (strucmp(aElementName,"resumeitemsupport")==0)
     expectBool(fResumeItemSupport);
-  #endif
+  #endif // BINFILE_ALWAYS_ACTIVE
   else if (
     strucmp(aElementName,"storelastsyncidentifier")==0 ||
     strucmp(aElementName,"storesyncidentifiers")==0
@@ -961,14 +961,15 @@ void TCustomImplDS::InternalResetDataStore(void)
   for (pos=fFinalisationQueue.begin();pos!=fFinalisationQueue.end();pos++)
        delete (*pos); // delete the item
   fFinalisationQueue.clear();
-  #ifndef BASED_ON_BINFILE_CLIENT
+  #ifndef SCRIPT_SUPPORT
   fGetPhase=gph_done; // must be initialized first by startDataRead
   fGetPhasePrepared=false;
   // Clear map table and sync set lists
   fMapTable.clear();
-  #else // not BASED_ON_BINFILE_CLIENT
+  #endif // not SCRIPT_SUPPORT
+  #ifdef BASED_ON_BINFILE_CLIENT
   fSyncSetLoaded=false;
-  #endif // BASED_ON_BINFILE_CLIENT
+  #endif // SCRIPT_SUPPORT
   fNoSingleItemRead=false; // assume we can read single items
   if (fAgentP) {
     // forget script context
@@ -1046,10 +1047,12 @@ localstatus TCustomImplDS::dsBeforeStateChange(TLocalEngineDSState aOldState,TLo
        while (fFinalisationQueue.size()>0) {
         // process finalisation script
         TMultiFieldItem *itemP = *(fFinalisationQueue.begin());
+               PDEBUGBLOCKFMTCOLL(("Finalizing","Finalizing item","LocalID=%s",itemP->getLocalID()));
         TScriptContext::execute(
                fScriptContextP,fConfigP->fFieldMappings.fFinalisationScript,fConfigP->getDSFuncTableP(),fAgentP,
           itemP,true // pass the item from the queue, is writable (mainly to allow fields to be passed as by-ref params)
         );
+             PDEBUGENDBLOCK("Finalizing");
         // no longer needed
         delete itemP;
         // remove from queue
@@ -1088,7 +1091,7 @@ localstatus TCustomImplDS::dsAfterStateChange(TLocalEngineDSState aOldState,TLoc
 } // TCustomImplDS::dsAfterStateChange
 
 
-#ifndef BASED_ON_BINFILE_CLIENT
+#ifndef BINFILE_ALWAYS_ACTIVE
 
 // mark all map entries as deleted
 bool TCustomImplDS::deleteAllMaps(void)
@@ -1100,7 +1103,7 @@ bool TCustomImplDS::deleteAllMaps(void)
   for (pos=fMapTable.begin();pos!=fMapTable.end();pos++) {
     (*pos).deleted=true; // deleted
   }
-  PDEBUGPRINTFX(DBG_ADMIN+DBG_EXOTIC,("deleteAllMaps: all existing map entries (%ld) now marked deleted=1",fMapTable.size()));
+  PDEBUGPRINTFX(DBG_ADMIN+DBG_EXOTIC,("deleteAllMaps: all existing map entries (%lu) now marked deleted=1",(unsigned long)fMapTable.size()));
   return allok;
 } // TCustomImplDS::deleteAllMaps
 
@@ -1143,7 +1146,7 @@ TMapContainer::iterator TCustomImplDS::findMapByRemoteID(const char *aRemoteID)
 } // TCustomImplDS::findMapByRemoteID
 
 
-#ifndef SYSYNC_CLIENT
+#ifdef SYSYNC_SERVER
 
 // - called when a item in the sync set changes its localID (due to local DB internals)
 //   Datastore must make sure that eventually cached items get updated
@@ -1188,7 +1191,7 @@ void TCustomImplDS::modifyMap(TMapEntryType aEntryType, const char *aLocalID, co
     MapEntryTypeNames[aEntryType],
     aLocalID && *aLocalID ? aLocalID : "<none>",
     aRemoteID ? (*aRemoteID ? aRemoteID : "<set none>") : "<do not change>",
-    aMapFlags,
+    (long)aMapFlags,
     (int)aDelete
   ));
   // - if there is a localID, search map entry (even if it is deleted)
@@ -1202,7 +1205,7 @@ void TCustomImplDS::modifyMap(TMapEntryType aEntryType, const char *aLocalID, co
           "- found entry by entrytype/localID='%s' - remoteid='%s', mapflags=0x%lX, changed=%d, deleted=%d, added=%d, markforresume=%d, savedmark=%d",
           aLocalID,
           (*pos).remoteid.c_str(),
-          (*pos).mapflags,
+          (long)(*pos).mapflags,
           (int)(*pos).changed,
           (int)(*pos).deleted,
           (int)(*pos).added,
@@ -1227,7 +1230,7 @@ void TCustomImplDS::modifyMap(TMapEntryType aEntryType, const char *aLocalID, co
           "- found entry by remoteID='%s' - localid='%s', mapflags=0x%lX, changed=%d, deleted=%d, added=%d, markforresume=%d, savedmark=%d",
           aRemoteID,
           (*pos).localid.c_str(),
-          (*pos).mapflags,
+          (long)(*pos).mapflags,
           (int)(*pos).changed,
           (int)(*pos).deleted,
           (int)(*pos).added,
@@ -1283,7 +1286,7 @@ void TCustomImplDS::modifyMap(TMapEntryType aEntryType, const char *aLocalID, co
       // check if contents change, update if so
       if (
         (((*pos).mapflags & ~mapflag_useforresume) != aMapFlags) || // flags different (useForResume not tested!)
-        (aRemoteID && (*pos).remoteid!=aRemoteID) // remoteID different
+        (aRemoteID && !((*pos).remoteid==aRemoteID)) // remoteID different
       ) {
         // new RemoteID (but not NULL = keep existing) or different mapflags were passed -> this is a real change
         if (aRemoteID)
@@ -1294,7 +1297,7 @@ void TCustomImplDS::modifyMap(TMapEntryType aEntryType, const char *aLocalID, co
     // now item exists, set details
     (*pos).deleted=false; // in case we had it deleted before, but not yet saved
     // clear those flags shown in aClearFlags (by default: all) and set those in aMapFlags
-    (*pos).mapflags = (*pos).mapflags & ~aClearFlags | aMapFlags;
+    (*pos).mapflags = ((*pos).mapflags & ~aClearFlags) | aMapFlags;
     // now remove all other items with same remoteID (except if we have no or empty remoteID)
     if (aEntryType==mapentry_normal && aRemoteID && *aRemoteID) {
       // %%% note: this is strictly necessary only for add, but cleans up for update
@@ -1305,7 +1308,7 @@ void TCustomImplDS::modifyMap(TMapEntryType aEntryType, const char *aLocalID, co
           PDEBUGPRINTFX(DBG_ADMIN+DBG_EXOTIC,(
             "- cleanup: removing same remoteID from other entry with localid='%s', mapflags=0x%lX, changed=%d, deleted=%d, added=%d, markforresume=%d, savedmark=%d",
             (*pos2).localid.c_str(),
-            (*pos2).mapflags,
+            (long)(*pos2).mapflags,
             (int)(*pos2).changed,
             (int)(*pos2).deleted,
             (int)(*pos2).added,
@@ -1322,7 +1325,7 @@ void TCustomImplDS::modifyMap(TMapEntryType aEntryType, const char *aLocalID, co
 } // TCustomImplDS::modifyMap
 
 
-#endif // not BASED_ON_BINFILE_CLIENT
+#endif // not BINFILE_ALWAYS_ACTIVE
 
 
 // delete syncset
@@ -1471,7 +1474,7 @@ localstatus TCustomImplDS::implMakeAdminReady(
   fCurrentSyncCmpRef=0;
   fCurrentSyncIdentifier.erase();
 
-  #ifndef BASED_ON_BINFILE_CLIENT
+  #ifndef BINFILE_ALWAYS_ACTIVE
   fMapTable.clear(); // map is empty to begin with
   #endif
   // now get admin data
@@ -1518,17 +1521,22 @@ localstatus TCustomImplDS::implMakeAdminReady(
     }
     #endif
     #ifdef BASED_ON_BINFILE_CLIENT
-    // binfile's implLoadAdminData will do the job
-    sta = inherited::implMakeAdminReady(aDeviceID, aDatabaseID, aRemoteDBID);
-
-    #else
-    // Load admin data from TXXXApiDS (ODBC, text or derived class' special implementation)
-    sta = apiLoadAdminData(
-      aDeviceID,    // remote device URI (device ID)
-      aDatabaseID,  // database ID
-      aRemoteDBID   // database ID of remote device
-    );
-    #endif
+    if (binfileDSActive()) {
+      // binfile's implMakeAdminReady will do the job
+      sta = inherited::implMakeAdminReady(aDeviceID, aDatabaseID, aRemoteDBID);
+    }
+               else
+    #endif // BASED_ON_BINFILE_CLIENT
+    {
+       #ifndef BINFILE_ALWAYS_ACTIVE
+      // Load admin data from TXXXApiDS (ODBC, text or derived class' special implementation)
+      sta = apiLoadAdminData(
+        aDeviceID,    // remote device URI (device ID)
+        aDatabaseID,  // database ID
+        aRemoteDBID   // database ID of remote device
+      );
+      #endif
+    }
     // set error if one occurred during load
     if (sta==LOCERR_OK) {
       // extra check: if we get empty remote anchor, this is a first-time sync even if DB claims the opposite
@@ -1589,55 +1597,61 @@ localstatus TCustomImplDS::implStartDataRead()
     #endif
   }
   #ifdef BASED_ON_BINFILE_CLIENT
-  // further preparation is in binfileds
-  sta = inherited::implStartDataRead();
-  if (sta==LOCERR_OK) {
-    // now make sure the syncset is loaded
-    if (!makeSyncSetLoaded(
-      fSlowSync
-      #ifdef OBJECT_FILTERING
-      || fFilteringNeededForAll
-      #endif
-    ))
-      sta = 510; // error
-  }
-  #else
-  // kill all map entries if slow sync (but not if resuming!!)
-  if (fSlowSync && !isResuming()) {
-    // mark all map entries as deleted
-    deleteAllMaps();
+  if (binfileDSActive()) {
+    // further preparation is in binfileds
+    sta = inherited::implStartDataRead();
+    if (sta==LOCERR_OK) {
+      // now make sure the syncset is loaded
+      if (!makeSyncSetLoaded(
+        fSlowSync
+        #ifdef OBJECT_FILTERING
+        || fFilteringNeededForAll
+        #endif
+      ))
+        sta = 510; // error
+    }
   }
-  // - count entire read as database read
-  TP_DEFIDX(li);
-  TP_SWITCH(li,fSessionP->fTPInfo,TP_database);
-  PDEBUGBLOCKFMTCOLL(("ReadSyncSet","Reading Sync Set from Database","datastore=%s",getName()));
-  SYSYNC_TRY {
-    // read sync set (maybe from derived non-odbc data source)
-    // - in slow sync, we need all items (so allow ReadSyncSet to read them all here)
-    // - if all items must be filtered, we also need all data
-    // Note: ReadSyncSet will decide if it actually needs to load the syncset or not (depends on refresh, slowsync and needs of apiZapSyncSet())
-    sta = apiReadSyncSet(
-      fSlowSync
-      #ifdef OBJECT_FILTERING
-      || fFilteringNeededForAll
-      #endif
-    );
-    // determine how GetItem will start
-    fGetPhase = fSlowSync ? gph_added_changed : gph_deleted; // just report added (not-in-map, map is cleared already) for slowsync
-    // phase not yet prepared
-    fGetPhasePrepared = false;
-    // end of DB read
-    PDEBUGENDBLOCK("ReadSyncSet");
-    TP_START(fSessionP->fTPInfo,li);
+  else
+  #endif // BASED_ON_BINFILE_CLIENT
+  {
+    #ifndef BINFILE_ALWAYS_ACTIVE
+    // kill all map entries if slow sync (but not if resuming!!)
+    if (fSlowSync && !isResuming()) {
+      // mark all map entries as deleted
+      deleteAllMaps();
+    }
+    // - count entire read as database read
+    TP_DEFIDX(li);
+    TP_SWITCH(li,fSessionP->fTPInfo,TP_database);
+    PDEBUGBLOCKFMTCOLL(("ReadSyncSet","Reading Sync Set from Database","datastore=%s",getName()));
+    SYSYNC_TRY {
+      // read sync set (maybe from derived non-odbc data source)
+      // - in slow sync, we need all items (so allow ReadSyncSet to read them all here)
+      // - if all items must be filtered, we also need all data
+      // Note: ReadSyncSet will decide if it actually needs to load the syncset or not (depends on refresh, slowsync and needs of apiZapSyncSet())
+      sta = apiReadSyncSet(
+        fSlowSync
+        #ifdef OBJECT_FILTERING
+        || fFilteringNeededForAll
+        #endif
+      );
+      // determine how GetItem will start
+      fGetPhase = fSlowSync ? gph_added_changed : gph_deleted; // just report added (not-in-map, map is cleared already) for slowsync
+      // phase not yet prepared
+      fGetPhasePrepared = false;
+      // end of DB read
+      PDEBUGENDBLOCK("ReadSyncSet");
+      TP_START(fSessionP->fTPInfo,li);
+    }
+    SYSYNC_CATCH(exception &e)
+      PDEBUGPRINTFX(DBG_ERROR,("StartDataRead exception: %s",e.what()));
+      sta=510;
+      // end of DB read
+      PDEBUGENDBLOCK("ReadSyncSet");
+      TP_START(fSessionP->fTPInfo,li);
+    SYSYNC_ENDCATCH
+    #endif // BINFILE_ALWAYS_ACTIVE
   }
-  SYSYNC_CATCH(exception &e)
-    PDEBUGPRINTFX(DBG_ERROR,("StartDataRead exception: %s",e.what()));
-    sta=510;
-    // end of DB read
-    PDEBUGENDBLOCK("ReadSyncSet");
-    TP_START(fSessionP->fTPInfo,li);
-  SYSYNC_ENDCATCH
-  #endif // not BASED_ON_BINFILE_CLIENT
   return sta;
 } // TCustomImplDS::implStartDataRead
 
@@ -1687,11 +1701,20 @@ void TCustomImplDS::queueForFinalisation(TMultiFieldItem *aItemP)
 
 
 
-#ifndef BASED_ON_BINFILE_CLIENT
+#ifndef BINFILE_ALWAYS_ACTIVE
+
 
 /// @brief called to have all non-yet-generated sync commands as "to-be-resumed"
 void TCustomImplDS::implMarkOnlyUngeneratedForResume(void)
 {
+       #ifdef BASED_ON_BINFILE_CLIENT
+       // let binfile handle it if it is active
+  if (binfileDSActive()) {
+       inherited::implMarkOnlyUngeneratedForResume();
+    return;
+  }
+  #endif // BASED_ON_BINFILE_CLIENT
+
   // Note: all "markforresume" flags (but NOT the actual mapflag_useforresume!) are cleared
   //       after loading or saving admin, so we can start adding resume marks BEFORE
   //       implMarkOnlyUngeneratedForResume is called (needed to re-add items that got
@@ -1738,23 +1761,24 @@ void TCustomImplDS::implMarkOnlyUngeneratedForResume(void)
       bool needMark=false;
       pos=findMapByLocalID((*syncsetpos)->localid.c_str(),mapentry_normal,true); // find deleted ones as well
       if (fSlowSync) {
-        #ifdef SYSYNC_CLIENT
-        // for client, there are no reference-only: mark all leftovers in a slow sync
-        needMark=true;
-        #else
-        // for server, make sure not to mark reference-only.
-        if (!isResuming() || pos==fMapTable.end()) {
-          // if not resuming, or we have no map for this one at all - we'll need it again for resume
-          needMark=true;
+       if (IS_CLIENT) {
+               // for client, there are no reference-only: mark all leftovers in a slow sync
+             needMark=true;
         }
         else {
-          // for slowsync resume which have already a map:
-          // - items that are not marked for resume, but already have a remoteID mapped
-          //   are reference-only and must NOT be marked
-          if (((*pos).mapflags & mapflag_useforresume) || (*pos).remoteid.empty())
+          // for server, make sure not to mark reference-only.
+          if (!isResuming() || pos==fMapTable.end()) {
+            // if not resuming, or we have no map for this one at all - we'll need it again for resume
             needMark=true;
+          }
+          else {
+            // for slowsync resume which have already a map:
+            // - items that are not marked for resume, but already have a remoteID mapped
+            //   are reference-only and must NOT be marked
+            if (((*pos).mapflags & mapflag_useforresume) || (*pos).remoteid.empty())
+              needMark=true;
+          }
         }
-        #endif
       }
       else if (!isRefreshOnly()) {
         // not slow sync, and not refresh from remote only - mark those that are actually are involved
@@ -1807,6 +1831,14 @@ void TCustomImplDS::implMarkOnlyUngeneratedForResume(void)
 // @note aSyncOp passed not necessarily reflects what was sent to remote, but what actually happened
 void TCustomImplDS::dsConfirmItemOp(TSyncOperation aSyncOp, cAppCharP aLocalID, cAppCharP aRemoteID, bool aSuccess, localstatus aErrorStatus)
 {
+       #ifdef BASED_ON_BINFILE_CLIENT
+       // let binfile handle it if it is active
+  if (binfileDSActive()) {
+       inherited::dsConfirmItemOp(aSyncOp, aLocalID, aRemoteID, aSuccess, aErrorStatus);
+    return;
+  }
+  #endif // BASED_ON_BINFILE_CLIENT
+
   if (aSyncOp==sop_delete || aSyncOp==sop_archive_delete) {
     // a confirmed delete causes the entire map entry to be removed (item no longer exists (or is visible) locally or remotely)
     if (aSuccess) {
@@ -1816,35 +1848,36 @@ void TCustomImplDS::dsConfirmItemOp(TSyncOperation aSyncOp, cAppCharP aLocalID,
   }
   else {
     TMapContainer::iterator pos;
-    #ifdef SYSYNC_CLIENT
-    // for client, always find by localid
-    pos=findMapByLocalID(aLocalID,mapentry_normal);
-    #else
-    // for server, only add can be found by localid
-    if (aSyncOp==sop_add)
+    if (IS_CLIENT) {
+      // for client, always find by localid
       pos=findMapByLocalID(aLocalID,mapentry_normal);
-    else
-      pos=findMapByRemoteID(aRemoteID);
-    #endif
+    }
+    else {
+      // for server, only add can be found by localid
+      if (aSyncOp==sop_add)
+        pos=findMapByLocalID(aLocalID,mapentry_normal);
+      else
+        pos=findMapByRemoteID(aRemoteID);
+    }
     if (pos!=fMapTable.end()) {
       // Anyway, clear the status pending flag
       // Note: we do not set the "changed" bit here because we don't really need to make this persistent between sessions
       (*pos).mapflags &= ~mapflag_pendingStatus;
-      #ifdef SYSYNC_CLIENT
-      if (aSuccess) {
-        // Note: we do not check for sop here - any successfully statused sop will clear the pending add status
-        //       (e.g. in slow sync, items reported as add to engine are actually sent as replaces, but still
-        //       seeing a ok status means that they are not any longer pending as adds)
-        // Note: the same functionality formerly was in TStdLogicDS::startDataWrite() - making sure that a
-        //       add sent to the server is not repeated. As every item reported by implGetItem now already
-        //       has a map entry (adds get one with mapflag_pendingAddConfirm set), we just need to clear
-        //       the flag here now that we know the add has reached the server.
-        // Note: For the server, we can clear the mapflag_pendingAddConfirm not before we have received a <Map> item for it!
-        PDEBUGPRINTFX(DBG_ADMIN+DBG_EXOTIC,("successful status for non-delete received -> clear mapflag_pendingAddConfirm"));
-        (*pos).mapflags &= ~mapflag_pendingAddConfirm;
-        (*pos).changed = true; // this MUST be made persistent!
-      }
-      #endif
+      if (IS_CLIENT) {
+        if (aSuccess) {
+          // Note: we do not check for sop here - any successfully statused sop will clear the pending add status
+          //       (e.g. in slow sync, items reported as add to engine are actually sent as replaces, but still
+          //       seeing a ok status means that they are not any longer pending as adds)
+          // Note: the same functionality formerly was in TStdLogicDS::startDataWrite() - making sure that a
+          //       add sent to the server is not repeated. As every item reported by implGetItem now already
+          //       has a map entry (adds get one with mapflag_pendingAddConfirm set), we just need to clear
+          //       the flag here now that we know the add has reached the server.
+          // Note: For the server, we can clear the mapflag_pendingAddConfirm not before we have received a <Map> item for it!
+          PDEBUGPRINTFX(DBG_ADMIN+DBG_EXOTIC,("successful status for non-delete received -> clear mapflag_pendingAddConfirm"));
+          (*pos).mapflags &= ~mapflag_pendingAddConfirm;
+          (*pos).changed = true; // this MUST be made persistent!
+        }
+      } // if client
     }
     else {
       PDEBUGPRINTFX(DBG_ERROR+DBG_EXOTIC,("dsConfirmItemOp - INTERNAL ERROR: no map entry exists for item"));
@@ -1859,6 +1892,14 @@ void TCustomImplDS::dsConfirmItemOp(TSyncOperation aSyncOp, cAppCharP aLocalID,
 // error status conditions, by localID or remoteID (latter only in server case).
 void TCustomImplDS::implMarkItemForResend(cAppCharP aLocalID, cAppCharP aRemoteID)
 {
+       #ifdef BASED_ON_BINFILE_CLIENT
+       // let binfile handle it if it is active
+  if (binfileDSActive()) {
+       inherited::implMarkItemForResend(aLocalID, aRemoteID);
+    return;
+  }
+  #endif // BASED_ON_BINFILE_CLIENT
+
   // Note: this is only relevant for replaces and some adds:
   //       - some adds will not have a map entry yet
   //       - deletes will not have their map entry deleted until they are confirmed
@@ -1887,7 +1928,7 @@ void TCustomImplDS::implMarkItemForResend(cAppCharP aLocalID, cAppCharP aRemoteI
   PDEBUGPRINTFX(DBG_ADMIN+DBG_EXOTIC+DBG_HOT,(
     "localID='%s' marked for resending by setting mapflag_resend (AND mark for eventual resume!), flags now=0x%lX",
     (*pos).localid.c_str(),
-    (*pos).mapflags
+    (long)(*pos).mapflags
   ));
 } // TCustomImplDS::implMarkItemForResend
 
@@ -1896,6 +1937,14 @@ void TCustomImplDS::implMarkItemForResend(cAppCharP aLocalID, cAppCharP aRemoteI
 // as "to-be-resumed", by localID or remoteID (latter only in server case).
 void TCustomImplDS::implMarkItemForResume(cAppCharP aLocalID, cAppCharP aRemoteID, bool aUnSent)
 {
+       #ifdef BASED_ON_BINFILE_CLIENT
+       // let binfile handle it if it is active
+  if (binfileDSActive()) {
+       inherited::implMarkItemForResume(aLocalID, aRemoteID, aUnSent);
+    return;
+  }
+  #endif // BASED_ON_BINFILE_CLIENT
+
   TMapContainer::iterator pos;
   if (aLocalID && *aLocalID)
     pos=findMapByLocalID(aLocalID,mapentry_normal,true); // also find deleted ones
@@ -1922,8 +1971,8 @@ void TCustomImplDS::implMarkItemForResume(cAppCharP aLocalID, cAppCharP aRemoteI
     //   resume ONLY if we can rely on early maps or if they are completely unsent.
     //   Sent adds will just keep their mapflag_pendingAddConfirm until they receive their map
     // For Client: all items will be marked for resume
-    #ifndef SYSYNC_CLIENT
     if (
+       IS_SERVER &&
       ((*pos).mapflags & mapflag_pendingAddConfirm) && // is an add...
       !aUnSent && // ...and already sent out
       !fSessionP->getSessionConfig()->fRelyOnEarlyMaps // and we can't rely on the client sending the maps before
@@ -1932,19 +1981,17 @@ void TCustomImplDS::implMarkItemForResume(cAppCharP aLocalID, cAppCharP aRemoteI
       PDEBUGPRINTFX(DBG_ADMIN+DBG_EXOTIC,(
         "implMarkItemForResume: localID='%s', has mapFlags=0x%lX and was probably executed at remote -> NOT marked for resume",
         (*pos).localid.c_str(),
-        (*pos).mapflags
+        (long)(*pos).mapflags
       ));
       (*pos).markforresume=false;
     }
-    else
-    #endif
-    {
+    else {
       // for client: everything may be repeated and therefore marked for resume
       // for server: unsent adds will also be marked, or all if we can rely on early maps (which is the default)
       PDEBUGPRINTFX(DBG_ADMIN+DBG_EXOTIC,(
         "implMarkItemForResume: localID='%s', has mapFlags=0x%lX and was %s executed at remote%s -> mark for resume",
         (*pos).localid.c_str(),
-        (*pos).mapflags,
+        (long)(*pos).mapflags,
         aUnSent ? "NOT" : "probably",
         fSessionP->getSessionConfig()->fRelyOnEarlyMaps ? " (relying on early maps)" : ""
       ));
@@ -1983,8 +2030,14 @@ localstatus TCustomImplDS::implGetItem(
   TSyncItem* &aSyncItemP
 )
 {
-  localstatus sta = LOCERR_OK;
+       #ifdef BASED_ON_BINFILE_CLIENT
+       // let binfile handle it if it is active
+  if (binfileDSActive()) {
+       return inherited::implGetItem(aEof, aChanged, aSyncItemP);
+  }
+  #endif // BASED_ON_BINFILE_CLIENT
 
+  localstatus sta = LOCERR_OK;
   bool reportChangedOnly = aChanged; // save initial state, as we might repeat...
   bool rep=true; // to start-up lower part
   TSyncOperation sop=sop_none;
@@ -2098,7 +2151,7 @@ localstatus TCustomImplDS::implGetItem(
               "Item localID='%s' already has map entry: remoteid='%s', mapflags=0x%lX, changed=%d, deleted=%d, added=%d, markforresume=%d, savedmark=%d",
               syncsetitemP->localid.c_str(),
               (*pos).remoteid.c_str(),
-              (*pos).mapflags,
+              (long)(*pos).mapflags,
               (int)(*pos).changed,
               (int)(*pos).deleted,
               (int)(*pos).added,
@@ -2123,16 +2176,13 @@ localstatus TCustomImplDS::implGetItem(
           }
           else {
             if (pos!=fMapTable.end()) {
-              #ifndef SYSYNC_CLIENT
               // for slowsync resume - items that are not marked for resume, but already have a remoteID mapped
               // must be presented for re-match with sop_reference_only
-              if (fSlowSync && isResuming() && !((*pos).mapflags & mapflag_useforresume) && !(*pos).remoteid.empty()) {
+              if (IS_SERVER && fSlowSync && isResuming() && !((*pos).mapflags & mapflag_useforresume) && !(*pos).remoteid.empty()) {
                 // this item apparently was already slow-sync-matched before the suspend - still show it for reference to avoid re-adding it
                 sop=sop_reference_only;
               }
-              else
-              #endif
-              if (!isRefreshOnly()) {
+              else if (!isRefreshOnly()) {
                 // item is already in map: check if this is an already detected, but unfinished add
                 if (!((*pos).mapflags & mapflag_pendingAddConfirm)) {
                   // is a replace (not an add): changed if mod date newer or resend flagged (AND updates enabled)
@@ -2191,28 +2241,27 @@ localstatus TCustomImplDS::implGetItem(
                     }
                   }
                   else {
-                    #ifdef SYSYNC_CLIENT
-                    // for client - repeating an add does not harm (but helps if it did not reach the server in the previous attempt
-                    PDEBUGPRINTFX(DBG_ADMIN+DBG_EXOTIC,("Non-resume sync found item with mapflag_pendingAddConfirm -> send it again"));
-                    sop=sop_wants_add;
-                    #else
-                    // for server - repeating an add potentially DOES harm (duplicate if client already got the add, but didn't send a map yet)
-                    // but it's ok if it's flagged as an explicit resend (this happens only if we have got error status from remote)
-                    if ((*pos).mapflags & mapflag_resend) {
-                      PDEBUGPRINTFX(DBG_ADMIN+DBG_EXOTIC,("Item with mapflag_pendingAddConfirm (add) also has mapflag_resend -> we can safely resend"));
+                       if (IS_CLIENT) {
+                      // for client - repeating an add does not harm (but helps if it did not reach the server in the previous attempt
+                      PDEBUGPRINTFX(DBG_ADMIN+DBG_EXOTIC,("Non-resume sync found item with mapflag_pendingAddConfirm -> send it again"));
                       sop=sop_wants_add;
-                      // - reset resend flag here
-                      (*pos).mapflags &= ~mapflag_resend;
-                      (*pos).changed = true;
-                    }
+                    } // client
                     else {
-                      PDEBUGPRINTFX(DBG_ADMIN+DBG_EXOTIC,("Non-resume sync found item with mapflag_pendingAddConfirm (add) -> ignore until map is found"));
-                    }
-                    #endif
+                      // for server - repeating an add potentially DOES harm (duplicate if client already got the add, but didn't send a map yet)
+                      // but it's ok if it's flagged as an explicit resend (this happens only if we have got error status from remote)
+                      if ((*pos).mapflags & mapflag_resend) {
+                        PDEBUGPRINTFX(DBG_ADMIN+DBG_EXOTIC,("Item with mapflag_pendingAddConfirm (add) also has mapflag_resend -> we can safely resend"));
+                        sop=sop_wants_add;
+                        // - reset resend flag here
+                        (*pos).mapflags &= ~mapflag_resend;
+                        (*pos).changed = true;
+                      }
+                      else {
+                        PDEBUGPRINTFX(DBG_ADMIN+DBG_EXOTIC,("Non-resume sync found item with mapflag_pendingAddConfirm (add) -> ignore until map is found"));
+                      }
+                    } // server
                   }
                 }
-
-
               } // if not refreshonly
             } // a map entry already exists
             else {
@@ -2326,36 +2375,6 @@ localstatus TCustomImplDS::implGetItem(
                 }
               } // else: fetch from DB needed
               if (fetched) {
-                /* %%% moved map adjustments to implReviewReadItem, as maps must not be created
-                 * for items that get filtered out of the syncset (which happens later after
-                 * calling this routine)!
-                 *
-                // if we don't have a map entry here, this MUST be a potential add
-                // NOTE: Don't touch map if this is a for-reference-only (meaning that the map is
-                //   already ok, and it is included here ONLY to find eventual slowsync matches)!
-                if (sop!=sop_reference_only) {
-                  if (pos==fMapTable.end()) {
-                    // this MUST be an add - create new map entry
-                    modifyMap(mapentry_normal,myitemP->getLocalID(),NULL,mapflag_pendingAddConfirm+mapflag_pendingStatus,false);
-                  }
-                  else {
-                    // only adjust map flags
-                    if (fSlowSync || sop==sop_add || sop==sop_wants_add) {
-                      // for slowsync, all items are kind of "adds", that is, not yet mapped (server case)
-                      //   or not yet statused (client case)
-                      // for normal sync, make sure adds get mapflag_pendingAddConfirm set
-                      (*pos).mapflags &= ~mapflag_pendingDeleteStatus;
-                      (*pos).mapflags |= mapflag_pendingAddConfirm+mapflag_pendingStatus;
-                      (*pos).changed=true;
-                    }
-                    else {
-                      // not add (and never a delete here) -> is replace. Set status pending flag (which doesn't need to be saved to DB)
-                      (*pos).mapflags &= ~(mapflag_pendingAddConfirm+mapflag_pendingDeleteStatus);
-                      (*pos).mapflags |= mapflag_pendingStatus;
-                    }
-                  }
-                }
-                */
                 // set item to return to caller
                 aSyncItemP = myitemP;
                 aEof=false; // report something
@@ -2407,18 +2426,20 @@ localstatus TCustomImplDS::implGetItem(
   return sta;
 } // TCustomImplDS::implGetItem
 
-#endif
+#endif // not BINFILE_ALWAYS_ACTIVE
 
 
 // end of read
 localstatus TCustomImplDS::implEndDataRead(void)
 {
-  #ifdef BASED_ON_BINFILE_CLIENT
-  // let binfile handle it
-  return inherited::implEndDataRead();
-  #else
+       #ifdef BASED_ON_BINFILE_CLIENT
+       // let binfile handle it if it is active
+  if (binfileDSActive()) {
+         return inherited::implEndDataRead();
+  }
+  #endif // BASED_ON_BINFILE_CLIENT
+  // let API handle it directly
   return apiEndDataRead();
-  #endif
 } // TCustomImplDS::implEndDataRead
 
 
@@ -2427,50 +2448,56 @@ localstatus TCustomImplDS::implStartDataWrite()
 {
   localstatus sta = LOCERR_OK;
 
-  #ifdef BASED_ON_BINFILE_CLIENT
-  // let binfile handle it
-  sta = inherited::implStartDataWrite();
-  #else
-  SYSYNC_TRY {
-    // let actual data implementation prepare
-    sta = apiStartDataWrite();
-    if (sta==LOCERR_OK) {
-      // Notes:
-      // - transaction starts implicitly when first INSERT / UPDATE / DELETE occurs
-      // - resumed slow refreshes must NOT zap the sync set again!
-      // - prevent zapping when datastore is in readonly mode!
-      if (fRefreshOnly && fSlowSync && !isResuming() && !fReadOnly) {
-        // now, we need to zap the DB first
-        PDEBUGBLOCKFMTCOLL(("ZapSyncSet","Zapping sync set in database","datastore=%s",getName()));
-        SYSYNC_TRY {
-          sta=apiZapSyncSet();
-          PDEBUGENDBLOCK("ZapSyncSet");
-        }
-        SYSYNC_CATCH(exception &e)
-          PDEBUGPRINTFX(DBG_ERROR,("ZapSyncSet exception: %s",e.what()));
-          sta=510;
-          // end of DB read
-          PDEBUGENDBLOCK("ZapSyncSet");
-        SYSYNC_ENDCATCH
-        if (sta!=LOCERR_OK) {
-          PDEBUGPRINTFX(DBG_ERROR,("implStartDataWrite: cannot zap data for refresh, status=%hd",sta));
+       #ifdef BASED_ON_BINFILE_CLIENT
+       // let binfile handle it if it is active
+  if (binfileDSActive()) {
+         sta = inherited::implStartDataWrite();
+  }
+  else
+  #endif // BASED_ON_BINFILE_CLIENT
+       {
+       #ifndef BINFILE_ALWAYS_ACTIVE
+    SYSYNC_TRY {
+      // let actual data implementation prepare
+      sta = apiStartDataWrite();
+      if (sta==LOCERR_OK) {
+        // Notes:
+        // - transaction starts implicitly when first INSERT / UPDATE / DELETE occurs
+        // - resumed slow refreshes must NOT zap the sync set again!
+        // - prevent zapping when datastore is in readonly mode!
+        if (fRefreshOnly && fSlowSync && !isResuming() && !fReadOnly) {
+          // now, we need to zap the DB first
+          PDEBUGBLOCKFMTCOLL(("ZapSyncSet","Zapping sync set in database","datastore=%s",getName()));
+          SYSYNC_TRY {
+            sta=apiZapSyncSet();
+            PDEBUGENDBLOCK("ZapSyncSet");
+          }
+          SYSYNC_CATCH(exception &e)
+            PDEBUGPRINTFX(DBG_ERROR,("ZapSyncSet exception: %s",e.what()));
+            sta=510;
+            // end of DB read
+            PDEBUGENDBLOCK("ZapSyncSet");
+          SYSYNC_ENDCATCH
+          if (sta!=LOCERR_OK) {
+            PDEBUGPRINTFX(DBG_ERROR,("implStartDataWrite: cannot zap data for refresh, status=%hd",sta));
+          }
+          // ok, now that the old data is zapped, we MUST forget the former sync set, it is now for sure invalid
+          DeleteSyncSet(false);
         }
-        // ok, now that the old data is zapped, we MUST forget the former sync set, it is now for sure invalid
-        DeleteSyncSet(false);
       }
     }
+    SYSYNC_CATCH(exception &e)
+      PDEBUGPRINTFX(DBG_ERROR,("implStartDataWrite exception: %s",e.what()));
+      sta=510;
+    SYSYNC_ENDCATCH
+    #endif
   }
-  SYSYNC_CATCH(exception &e)
-    PDEBUGPRINTFX(DBG_ERROR,("implStartDataWrite exception: %s",e.what()));
-    sta=510;
-  SYSYNC_ENDCATCH
-  #endif
   // done
   return sta;
 } // TCustomImplDS::implStartDataWrite
 
 
-#ifndef BASED_ON_BINFILE_CLIENT
+#ifndef BINFILE_ALWAYS_ACTIVE
 
 // review reported entry (allows post-processing such as map deleting)
 // MUST be called after StartDataWrite, before any actual writing,
@@ -2479,6 +2506,13 @@ localstatus TCustomImplDS::implReviewReadItem(
   TSyncItem &aItem         // the item
 )
 {
+       #ifdef BASED_ON_BINFILE_CLIENT
+       // let binfile handle it if it is active
+  if (binfileDSActive()) {
+       return inherited::implReviewReadItem(aItem);
+  }
+  #endif // BASED_ON_BINFILE_CLIENT
+  
   // get the operation
   TSyncOperation sop = aItem.getSyncOp();
   // NOTE: Don't touch map if this is a for-reference-only (meaning that the map is
@@ -2512,34 +2546,41 @@ bool TCustomImplDS::implRetrieveItemByID(
   TStatusCommand &aStatusCommand
 )
 {
+       #ifdef BASED_ON_BINFILE_CLIENT
+       // let binfile handle it if it is active
+  if (binfileDSActive()) {
+       return inherited::implRetrieveItemByID(aItem, aStatusCommand);
+  }
+  #endif // BASED_ON_BINFILE_CLIENT
+  
   bool ok=true;
-
   // determine item's local ID
   if (!aItem.hasLocalID()) {
-    #ifdef SYSYNC_CLIENT
-    // client case: MUST have local ID
-    aStatusCommand.setStatusCode(400); // bad request (no address)
-    return false;
-    #else
-    // no local ID specified directly, address by remote ID
-    if (!aItem.hasRemoteID()) {
+       if (IS_CLIENT) {
+      // client case: MUST have local ID
       aStatusCommand.setStatusCode(400); // bad request (no address)
       return false;
     }
-    // lookup remote ID in map
-    TMapContainer::iterator mappos = findMapByRemoteID(aItem.getRemoteID());
-    if (mappos==fMapTable.end()) {
-      aStatusCommand.setStatusCode(404); // not found
-      return false;
-    }
-    // set local ID
-    aItem.setLocalID(mappos->localid.c_str());
-    // check if we have a local ID now
-    if (!aItem.hasLocalID()) {
-      aStatusCommand.setStatusCode(400); // bad request (no address)
-      return false;
+    else {
+      // no local ID specified directly, address by remote ID
+      if (!aItem.hasRemoteID()) {
+        aStatusCommand.setStatusCode(400); // bad request (no address)
+        return false;
+      }
+      // lookup remote ID in map
+      TMapContainer::iterator mappos = findMapByRemoteID(aItem.getRemoteID());
+      if (mappos==fMapTable.end()) {
+        aStatusCommand.setStatusCode(404); // not found
+        return false;
+      }
+      // set local ID
+      aItem.setLocalID(mappos->localid.c_str());
+      // check if we have a local ID now
+      if (!aItem.hasLocalID()) {
+        aStatusCommand.setStatusCode(400); // bad request (no address)
+        return false;
+      }
     }
-    #endif
   }
   TP_DEFIDX(li);
   TP_SWITCH(li,fSessionP->fTPInfo,TP_database);
@@ -2624,6 +2665,13 @@ bool TCustomImplDS::implProcessItem(
   TSyncItem *aItemP,         // the item
   TStatusCommand &aStatusCommand
 ) {
+       #ifdef BASED_ON_BINFILE_CLIENT
+       // let binfile handle it if it is active
+  if (binfileDSActive()) {
+       return inherited::implProcessItem(aItemP, aStatusCommand);
+  }
+  #endif // BASED_ON_BINFILE_CLIENT
+  
   bool ok=true;
   localstatus sta=LOCERR_OK;
   string localID;
@@ -2634,35 +2682,34 @@ bool TCustomImplDS::implProcessItem(
 
   TP_DEFIDX(li);
   TP_SWITCH(li,fSessionP->fTPInfo,TP_database);
-  // get field map list
-  TFieldMapList &fml = fConfigP->fFieldMappings.fFieldMapList;
   SYSYNC_TRY {
     // get casted item pointer
     TMultiFieldItem *myitemP = (TMultiFieldItem *)aItemP;
     // - get op
     sop = myitemP->getSyncOp();
     // - check IDs
-    #ifdef SYSYNC_CLIENT
-    // Client case: we always get the local ID, except for add
-    localID=myitemP->getLocalID();
-    remoteID=myitemP->getRemoteID();
-    if (!localID.empty() && sop!=sop_add && sop!=sop_wants_add)
-      mappos=findMapByLocalID(localID.c_str(),mapentry_normal); // for all but sop == sop_add
-    else
-      mappos=fMapTable.end(); // if there is no localid or it is an add, we have no map entry yet
-    #else
-    // Server case: we only know the remote ID
-    // - get remoteID
-    remoteID=myitemP->getRemoteID();
-    // first see if we have a map entry for this remote ID
-    localID.erase(); // none yet
-    // Note: even items detected for deletion still have a map item until deletion is confirmed by the remote party,
-    //       so we'll be able to update already "deleted" items (in case they are not really gone, but only invisible in the sync set)
-    mappos=findMapByRemoteID(remoteID); // search for it
-    if (mappos!=fMapTable.end()) {
-      localID = (*mappos).localid; // assign it if we have it
+    if (IS_CLIENT) {
+      // Client case: we always get the local ID, except for add
+      localID=myitemP->getLocalID();
+      remoteID=myitemP->getRemoteID();
+      if (!localID.empty() && sop!=sop_add && sop!=sop_wants_add)
+        mappos=findMapByLocalID(localID.c_str(),mapentry_normal); // for all but sop == sop_add
+      else
+        mappos=fMapTable.end(); // if there is no localid or it is an add, we have no map entry yet
+       }
+    else {
+      // Server case: we only know the remote ID
+      // - get remoteID
+      remoteID=myitemP->getRemoteID();
+      // first see if we have a map entry for this remote ID
+      localID.erase(); // none yet
+      // Note: even items detected for deletion still have a map item until deletion is confirmed by the remote party,
+      //       so we'll be able to update already "deleted" items (in case they are not really gone, but only invisible in the sync set)
+      mappos=findMapByRemoteID(remoteID); // search for it
+      if (mappos!=fMapTable.end()) {
+        localID = (*mappos).localid; // assign it if we have it
+      }
     }
-    #endif
     // - now perform op
     aStatusCommand.setStatusCode(510); // default DB error
     switch (sop) {
@@ -2671,17 +2718,19 @@ bool TCustomImplDS::implProcessItem(
       case sop_add :
         // add item and retrieve new localID for it
         sta = apiAddItem(*myitemP,localID);
-        #ifndef SYSYNC_CLIENT
-        if (sta==DB_DataMerged) {
-               // while adding, data was merged with pre-existing data (external from the sync set)
-          // so we should retrieve the full data and send an update back to the client
-          // - this is like forcing a conflict, i.e. this loads the item by local/remoteid and adds it to
-          //   the to-be-sent list of the server.
-                                       PDEBUGPRINTFX(DBG_DATA,("Database adapter indicates that added item was merged with pre-existing data (status 207), so update client with merged item"));
-          forceConflict(myitemP);
-          sta = LOCERR_OK; // otherwise, treat as ok
-        }
-        #endif
+        if (IS_SERVER) {
+               #ifdef SYSYNC_SERVER
+          if (sta==DB_DataMerged) {
+            // while adding, data was merged with pre-existing data (external from the sync set)
+            // so we should retrieve the full data and send an update back to the client
+            // - this is like forcing a conflict, i.e. this loads the item by local/remoteid and adds it to
+            //   the to-be-sent list of the server.
+            PDEBUGPRINTFX(DBG_DATA,("Database adapter indicates that added item was merged with pre-existing data (status 207), so update client with merged item"));
+            forceConflict(myitemP);
+            sta = LOCERR_OK; // otherwise, treat as ok
+          }
+          #endif
+        } // server
         if (sta!=LOCERR_OK) {
           aStatusCommand.setStatusCode(sta);
           ok=false;
@@ -2814,12 +2863,11 @@ localstatus TCustomImplDS::SaveAdminData(bool aSessionFinished, bool aSuccessful
     else if (!(*pos).deleted) {
       // in case of map table without flags, we must get rid of all non-real maps
       if (!dsResumeSupportedInDB() && aSessionFinished) {
-        #ifndef SYSYNC_CLIENT
         // For client, remoteid is irrelevant and can well be empty
         //   Map entries exist for those items that are not newly added on the client
         // For server, maps w/o remoteid are not really mapped and must not be saved when
         //   we have no flags to mark this special conditon (mapflag_pendingAddConfirm)
-        if ((*pos).remoteid.empty()) {
+        if (IS_SERVER && (*pos).remoteid.empty()) {
           // no remoteid -> this is not a real map, we cannot represent it w/o resume support (=flags) in map table
           DEBUGPRINTFX(DBG_ADMIN+DBG_EXOTIC,("LocalID='%s' has no remoteID - cannot be stored in non-DS-1.2 Map DB -> removed map",(*pos).localid.c_str()));
           if ((*pos).added) {
@@ -2833,9 +2881,7 @@ localstatus TCustomImplDS::SaveAdminData(bool aSessionFinished, bool aSuccessful
             (*pos).deleted=true;
           }
         }
-        else
-        #endif
-        {
+        else {
           // clear all specials
           (*pos).mapflags=0;
           (*pos).savedmark=false;
@@ -2848,9 +2894,8 @@ localstatus TCustomImplDS::SaveAdminData(bool aSessionFinished, bool aSuccessful
         ((*pos).mapflags & mapflag_pendingAddConfirm)
       ) {
         // successful end of session - we can forget pending add confirmations (as the add commands apparently never reached the remote at all)
-        #ifndef SYSYNC_CLIENT
         // Note: for clients, maps can well have an empty remoteid (because it does not need to be saved)
-        if ((*pos).remoteid.empty()) {
+        if (IS_SERVER && (*pos).remoteid.empty()) {
           PDEBUGPRINTFX(DBG_ADMIN+DBG_EXOTIC,("Successful end of session but localID='%s' has no remoteID and pendingAddConfirm still set -> removed map",(*pos).localid.c_str()));
           // if not mapped, this will be a re-add in the next session, so forget it for now
           if ((*pos).added) {
@@ -2864,9 +2909,7 @@ localstatus TCustomImplDS::SaveAdminData(bool aSessionFinished, bool aSuccessful
             (*pos).deleted=true;
           }
         }
-        else
-        #endif
-        {
+        else {
           // For server: is mapped, which means that it now exists in the client - just clean mapflag_pendingAddConfirm
           // For client: just clean the pendingAddConfirm
           // Note: maps like this should not exist at this time - as at end of a successful session all items should
@@ -2885,26 +2928,31 @@ localstatus TCustomImplDS::SaveAdminData(bool aSessionFinished, bool aSuccessful
     // Note: these entries are already in the global map table, but with the deleted flag set.
     //       Here those that still exist now will be re-activated (without saving them again if not needed)
     TStringToStringMap::iterator spos;
-    #ifdef SYSYNC_CLIENT
-    // - now pending maps (unsent ones)
-    PDEBUGPRINTFX(DBG_ADMIN+DBG_EXOTIC,("SaveAdminData: adding %ld entries from fPendingAddMap as mapentry_pendingmap",fPendingAddMaps.size()));
-    for (spos=fPendingAddMaps.begin();spos!=fPendingAddMaps.end();spos++) {
-       string locID = (*spos).first;
-      dsFinalizeLocalID(locID); // make sure we have the permanent version in case datastore implementation did deliver temp IDs
-      modifyMap(mapentry_pendingmap, locID.c_str(), (*spos).second.c_str(), 0, false);
-    }
-    // - now pending maps (sent, but not seen status yet)
-    PDEBUGPRINTFX(DBG_ADMIN+DBG_EXOTIC,("SaveAdminData: adding %ld entries from fUnconfirmedMaps as mapentry_pendingmap/mapflag_pendingMapStatus",fUnconfirmedMaps.size()));
-    for (spos=fUnconfirmedMaps.begin();spos!=fUnconfirmedMaps.end();spos++) {
-      modifyMap(mapentry_pendingmap, (*spos).first.c_str(), (*spos).second.c_str(), mapflag_pendingMapStatus, false);
+    if (IS_CLIENT) {
+       #ifdef SYSYNC_CLIENT
+      // - now pending maps (unsent ones)
+      PDEBUGPRINTFX(DBG_ADMIN+DBG_EXOTIC,("SaveAdminData: adding %lu entries from fPendingAddMap as mapentry_pendingmap",(unsigned long)fPendingAddMaps.size()));
+      for (spos=fPendingAddMaps.begin();spos!=fPendingAddMaps.end();spos++) {
+        string locID = (*spos).first;
+        dsFinalizeLocalID(locID); // make sure we have the permanent version in case datastore implementation did deliver temp IDs
+        modifyMap(mapentry_pendingmap, locID.c_str(), (*spos).second.c_str(), 0, false);
+      }
+      // - now pending maps (sent, but not seen status yet)
+      PDEBUGPRINTFX(DBG_ADMIN+DBG_EXOTIC,("SaveAdminData: adding %lu entries from fUnconfirmedMaps as mapentry_pendingmap/mapflag_pendingMapStatus",(long unsigned)fUnconfirmedMaps.size()));
+      for (spos=fUnconfirmedMaps.begin();spos!=fUnconfirmedMaps.end();spos++) {
+        modifyMap(mapentry_pendingmap, (*spos).first.c_str(), (*spos).second.c_str(), mapflag_pendingMapStatus, false);
+      }
+      #endif
     }
-    #else
-    // - the tempguid maps
-    PDEBUGPRINTFX(DBG_ADMIN+DBG_EXOTIC,("SaveAdminData: adding %ld entries from fTempGUIDMap as mapentry_tempidmap",fTempGUIDMap.size()));
-    for (spos=fTempGUIDMap.begin();spos!=fTempGUIDMap.end();spos++) {
-      modifyMap(mapentry_tempidmap, (*spos).second.c_str(), (*spos).first.c_str(), 0, false);
+    else {
+       #ifdef SYSYNC_SERVER
+      // - the tempguid maps
+      PDEBUGPRINTFX(DBG_ADMIN+DBG_EXOTIC,("SaveAdminData: adding %lu entries from fTempGUIDMap as mapentry_tempidmap",(unsigned long)fTempGUIDMap.size()));
+      for (spos=fTempGUIDMap.begin();spos!=fTempGUIDMap.end();spos++) {
+        modifyMap(mapentry_tempidmap, (*spos).second.c_str(), (*spos).first.c_str(), 0, false);
+      }
+      #endif
     }
-    #endif
   }
   sta=apiSaveAdminData(aSessionFinished,aSuccessful);
   if (sta!=LOCERR_OK) {
@@ -2913,7 +2961,7 @@ localstatus TCustomImplDS::SaveAdminData(bool aSessionFinished, bool aSuccessful
   return sta;
 } // TCustomImplDS::SaveAdminData
 
-#endif // not BASED_ON_BINFILE_CLIENT
+#endif // not BINFILE_ALWAYS_ACTIVE
 
 
 // save end of session state
@@ -2926,20 +2974,25 @@ localstatus TCustomImplDS::implSaveEndOfSession(bool aUpdateAnchors)
     if (!fRefreshOnly || fSlowSync) {
       // This was really a two-way sync or we implicitly know that
       // we are now in sync with remote (like after one-way-from-remote refresh = reload local)
-      #ifndef BASED_ON_BINFILE_CLIENT
-      // Note: in case of BASED_ON_BINFILE_CLIENT, these updates will be done by binfileds
-      //       (also note that fPreviousToRemoteSyncCmpRef has different semantics in BASED_ON_BINFILE_CLIENT,
-      //       as it serves as a last-changelog-update reference then)
-      // But here, fPreviousToRemoteSyncCmpRef is what it seems - the timestamp corresponding to last sync to remote
-      if (fConfigP->fSyncTimeStampAtEnd) {
-        // if datastore cannot explicitly set modification timestamps, best time to save is current time
-        fPreviousToRemoteSyncCmpRef = fAgentP->getDatabaseNowAs(TCTX_UTC);
-      }
-      else {
-        // if datastore can set modification timestamps, best time to save is start of sync
-        fPreviousToRemoteSyncCmpRef = fCurrentSyncTime;
+      #ifdef BASED_ON_BINFILE_CLIENT
+      if (!binfileDSActive())
+      #endif // BASED_ON_BINFILE_CLIENT
+                       {
+       #ifndef BINFILE_ALWAYS_ACTIVE
+        // Note: in case of BASED_ON_BINFILE_CLIENT, these updates will be done by binfileds
+        //       (also note that fPreviousToRemoteSyncCmpRef has different semantics in BASED_ON_BINFILE_CLIENT,
+        //       as it serves as a last-changelog-update reference then)
+        // But here, fPreviousToRemoteSyncCmpRef is what it seems - the timestamp corresponding to last sync to remote
+        if (fConfigP->fSyncTimeStampAtEnd) {
+          // if datastore cannot explicitly set modification timestamps, best time to save is current time
+          fPreviousToRemoteSyncCmpRef = fAgentP->getDatabaseNowAs(TCTX_UTC);
+        }
+        else {
+          // if datastore can set modification timestamps, best time to save is start of sync
+          fPreviousToRemoteSyncCmpRef = fCurrentSyncTime;
+        }
+        #endif
       }
-      #endif
       // also update opaque reference string eventually needed in DS API implementations
       fPreviousToRemoteSyncIdentifier = fCurrentSyncIdentifier;
     }
@@ -2948,15 +3001,19 @@ localstatus TCustomImplDS::implSaveEndOfSession(bool aUpdateAnchors)
     fPreviousSuspendIdentifier.erase();
   }
   #ifdef BASED_ON_BINFILE_CLIENT
-  // if we sit on top of binfile, let binfile do the actual end-if-session work
-  // (updates of cmprefs etc. are done at binfile level again).
-  sta = inherited::implSaveEndOfSession(aUpdateAnchors);
-  #else
-  // save admin data now
-  sta=SaveAdminData(true,aUpdateAnchors); // end of session
-  // we can foget the maps now
-  fMapTable.clear();
-  #endif
+  if (binfileDSActive()) {
+    // if we sit on top of activated binfile, let binfile do the actual end-if-session work
+    // (updates of cmprefs etc. are done at binfile level again).
+    sta = inherited::implSaveEndOfSession(aUpdateAnchors);
+  }
+  else
+  #endif // BASED_ON_BINFILE_CLIENT
+  {
+    // save admin data myself now
+    sta=SaveAdminData(true,aUpdateAnchors); // end of session
+    // we can foget the maps now
+    fMapTable.clear();
+  }
   PDEBUGENDBLOCK("SaveEndOfSession");
   return sta;
 } // TCustomImplDS::implSaveEndOfSession
@@ -2979,8 +3036,10 @@ bool TCustomImplDS::implEndDataWrite(void)
   SYSYNC_ENDCATCH
   TP_START(fSessionP->fTPInfo,li);
   #ifdef BASED_ON_BINFILE_CLIENT
-  // binfile level must be called as well
-  sta = inherited::implEndDataWrite();
+  if (binfileDSActive()) {
+    // binfile level must be called as well
+    sta = inherited::implEndDataWrite();
+  }
   #endif
   return sta;
 } // TCustomImplDS::implEndDataWrite
@@ -3012,13 +3071,20 @@ localstatus TCustomImplDS::zapSyncSet(void)
 } // TCustomImplDS::zapSyncSet
 
 
-#ifndef BASED_ON_BINFILE_CLIENT
+#ifndef BINFILE_ALWAYS_ACTIVE
 
 // - save status information required to eventually perform a resume (as passed to datastore with
 //   implMarkOnlyUngeneratedForResume() and implMarkItemForResume())
 //   (or, in case the session is really complete, make sure that no resume state is left)
 localstatus TCustomImplDS::implSaveResumeMarks(void)
 {
+       #ifdef BASED_ON_BINFILE_CLIENT
+       // let binfile handle it if it is active
+  if (binfileDSActive()) {
+       return inherited::implSaveResumeMarks();
+  }
+  #endif // BASED_ON_BINFILE_CLIENT
+
   PDEBUGBLOCKCOLL("SaveResumeMarks");
   // update anchoring info for resume
   if (fConfigP->fSyncTimeStampAtEnd) {
@@ -3038,12 +3104,18 @@ localstatus TCustomImplDS::implSaveResumeMarks(void)
 } // TCustomImplDS::implSaveResumeMarks
 
 
-#else // not BASED_ON_BINFILE_CLIENT
+#endif // not BINFILE_ALWAYS_ACTIVE
+
 
+#ifdef BASED_ON_BINFILE_CLIENT
 
 // Connecting methods when CustomImplDS is used on top of BinFileImplDS
 
+// Note: these are defined by BinFileImplDS and are ONLY CALLED IF BinFileImplDS is
+//       active. In setups where we can switch off the intermediate binfile layer,
+//       these routines are never called and can't harm
 
+// private helper
 bool TCustomImplDS::makeSyncSetLoaded(bool aNeedAll)
 {
   localstatus sta = LOCERR_OK;
@@ -3143,24 +3215,6 @@ localstatus TCustomImplDS::getItemByID(localid_t aLocalID, TSyncItem *&aItemP)
 } // TCustomImplDS::getItemByID
 
 
-/* no need to implement this here, calling API level directly from binfile is enough
-/// signal start of data write phase
-localstatus TCustomImplDS::apiStartDataWrite(void);
-*/
-
-/* must not be implemented here, as TCustomImplDS also derives
-   implEndDataWrite() which makes sure apiEndDataWrite(cmpRef) is called
-   at the right time
-/// signal end of data write phase
-localstatus TCustomImplDS::apiEndDataWrite(void)
-{
-  // call customImplDS branch's version of apiEndDataWrite
-  string thisSyncIdentifier;
-  return apiEndDataWrite(thisSyncIdentifier);
-} // TCustomImplDS::apiEndDataWrite
-*/
-
-
 /// update item by local ID in the sync set. Caller retains ownership of aItemP
 /// @return != LOCERR_OK  if item with specified ID is not found.
 localstatus TCustomImplDS::updateItemByID(localid_t aLocalID, TSyncItem *aItemP)
@@ -3256,7 +3310,7 @@ uInt32 TCustomImplDS::lastDBError(void)
 } // TCustomImplDS::lastDBError
 
 
-#endif // BASED_ON_BINFILE_CLIENT
+#endif // BASED_ON_BINFILE_CLIENT connecting methods
 
 
 #ifdef DBAPI_TEXTITEMS
index 2d003da..4e749fd 100755 (executable)
 
 #ifdef BASED_ON_BINFILE_CLIENT
   #include "binfileimplds.h"
+#else
+       #ifdef BINFILE_ALWAYS_ACTIVE
+       #error "BINFILE_ALWAYS_ACTIVE is only possible when BASED_ON_BINFILE_CLIENT"
+  #endif
 #endif
 
+
 using namespace sysync;
 
 namespace sysync {
@@ -214,14 +219,14 @@ public:
   bool fUserZoneOutput; // if set, all non-floating timestamps are moved to user time zone (probably from datatimezone)
   // - admin capability info
   bool fStoreSyncIdentifiers; // if set, database separately stores "last sync with data sent to remote" and "last suspend" identifiers (stored as string, not necessarily a date)
-  #ifndef BASED_ON_BINFILE_CLIENT
+  #ifndef BINFILE_ALWAYS_ACTIVE
   bool fSyncTimeStampAtEnd; // if set, time point of sync is taken AFTER last write to DB (for single-user DBs like FMPro)
   bool fOneWayFromRemoteSupported; // if set, database has a separate "last sync with data sent to remote" timestamp
   bool fResumeSupport; // if set, admin tables have DS 1.2 support needed for resume (map entrytype, map flags, fResumeAlertCode, fLastSuspend, fLastSuspendIdentifier
   bool fResumeItemSupport; // if set, admin tables have support for storing data to resume a partially transferred item
   // - one-way support is always given for binfile based DS
   virtual bool isOneWayFromRemoteSupported() { return fOneWayFromRemoteSupported; }
-  #endif // not BASED_ON_BINFILE_CLIENT
+  #endif // not BINFILE_ALWAYS_ACTIVE
   // - Database field to item field mappings
   TFieldMappings fFieldMappings;
   #ifdef SCRIPT_SUPPORT
@@ -255,7 +260,7 @@ protected:
 }; // TCustomDSConfig
 
 
-#ifndef BASED_ON_BINFILE_CLIENT
+#ifndef BINFILE_ALWAYS_ACTIVE
 
 // getitem phase
 typedef enum {
@@ -305,7 +310,7 @@ typedef struct {
 // container for map entries
 typedef list<TMapEntry> TMapContainer;
 
-#endif // BASED_ON_BINFILE_CLIENT
+#endif // BINFILE_ALWAYS_ACTIVE
 
 
 // local SyncSet entry
@@ -358,6 +363,7 @@ protected:
   /// @note normally==fPreviousSyncTime, but can be end of sync for datastore that can't write modified timestamps at will
   #ifndef BASED_ON_BINFILE_CLIENT
   /// @note for BASED_ON_BINFILE_CLIENT case, these already exist at the binfile level, so we MUST NOT have them here again!!
+  /// @note if binfile is there, but disabled, we still dont need these member vars.
   lineartime_t fPreviousToRemoteSyncCmpRef;
   /// Reference string used by database API level to determine modifications since last to-remote-sync
   string fPreviousToRemoteSyncIdentifier;
@@ -395,7 +401,7 @@ public:
   /// @{
   //
 
-  #ifndef BASED_ON_BINFILE_CLIENT
+  #ifndef BINFILE_ALWAYS_ACTIVE
   /// @brief Load admin data from database
   /// @param aDeviceID[in]       remote device URI (device ID)
   /// @param aDatabaseID[in]     local database ID
@@ -467,12 +473,7 @@ public:
   ///   - fTempGUIDMap      = map<string,string>. The implementation must save all entries as temporary LUID to GUID mappings
   ///                         (server only)
   virtual localstatus apiSaveAdminData(bool aSessionFinished, bool aSuccessful) = 0;
-  /* %%% luz 2008-04-01: no, this is NOT needed
-  #else // not BASED_ON_BINFILE_CLIENT
-  // when based on binfile, we need this apiEndDataWrite signature as glue
-  virtual localstatus apiEndDataWrite(void);
-  */
-  #endif // BASED_ON_BINFILE_CLIENT
+  #endif // BINFILE_ALWAYS_ACTIVE
 
   /// read sync set IDs and mod dates.
   /// @param[in] if set, all data fields are needed, so ReadSyncSet MAY
@@ -544,11 +545,11 @@ public:
   virtual localstatus dsBeforeStateChange(TLocalEngineDSState aOldState,TLocalEngineDSState aNewState);
   /// inform logic of happened state change
   virtual localstatus dsAfterStateChange(TLocalEngineDSState aOldState,TLocalEngineDSState aNewState);
-  #ifndef BASED_ON_BINFILE_CLIENT
+  #ifndef BINFILE_ALWAYS_ACTIVE
   /// called to confirm a sync operation's completion (ok status from remote received)
   /// @note aSyncOp passed not necessarily reflects what was sent to remote, but what actually happened
   virtual void dsConfirmItemOp(TSyncOperation aSyncOp, cAppCharP aLocalID, cAppCharP aRemoteID, bool aSuccess, localstatus aErrorStatus=0);
-  #endif
+  #endif // BINFILE_ALWAYS_ACTIVE
 
   /// @}
 
@@ -590,6 +591,7 @@ protected:
   // - returns true if database implementation can only update all fields of a record at once
   virtual bool dsReplaceWritesAllDBFields(void);
   #ifndef BASED_ON_BINFILE_CLIENT
+  // Note: these are identically in binfile client, so we need them only if there is no binfile layer
   // - returns true if DB implementation supports resume (saving of resume marks, alert code, pending maps, tempGUIDs)
   virtual bool dsResumeSupportedInDB(void) { return fConfigP && fConfigP->fResumeSupport; };
   /// returns true if DB implementation supports resuming in midst of a chunked item (can save fPIxxx.. and related admin data)
@@ -640,10 +642,15 @@ protected:
   ///       inhertited binfile version.
   virtual bool implEndDataWrite(void);
 
-  #ifndef BASED_ON_BINFILE_CLIENT
-
-  /// when based on binfile client, we don't need the syncset loaded to be able to retrieve items
+  #ifdef BASED_ON_BINFILE_CLIENT
+  /// when based on binfile client, we need the syncset loaded when binfile is active
+  bool implNeedSyncSetToRetrieve(void) { return binfileDSActive(); };
+  #else
   bool implNeedSyncSetToRetrieve(void) { return false; };
+  #endif
+  
+
+  #ifndef BINFILE_ALWAYS_ACTIVE
   /// get item from DB
   virtual localstatus implGetItem(
     bool &aEof,
@@ -686,15 +693,15 @@ protected:
   virtual localstatus implSaveResumeMarks(void);
 
   /// @}
-  #else // not BASED_ON_BINFILE_CLIENT
+  #endif // not BINFILE_ALWAYS_ACTIVE
+  
+  #ifdef BASED_ON_BINFILE_CLIENT
   /// @name methods used when based on BinfileImplDS
   /// @{
 
   #ifndef CHANGEDETECTION_AVAILABLE
     #error "CustomImplDS can be built only on BinFileImplDS with CHANGEDETECTION_AVAILABLE"
   #endif
-  /// when based on binfile client, we need the syncset loaded to be able to retrieve items
-  bool implNeedSyncSetToRetrieve(void) { return true; };
   /// get first item's ID and modification status from the sync set
   /// @return false if no item found
   virtual bool getFirstItemInfo(localid_out_t &aLocalID, bool &aItemHasChanged);
@@ -758,19 +765,19 @@ public:
   // - find entry in sync set by localid
   TSyncSetList::iterator findInSyncSet(const char *aLocalID);
 protected:
-  #ifndef BASED_ON_BINFILE_CLIENT
+  #ifndef BINFILE_ALWAYS_ACTIVE
   // - find non-deleted map entry by local ID / entry type
   TMapContainer::iterator findMapByLocalID(const char *aLocalID,TMapEntryType aEntryType, bool aDeletedAsWell=false);
   // - find map entry by remote ID
   TMapContainer::iterator findMapByRemoteID(const char *aRemoteID);
   // - modify map, if remoteID or localID is NULL or empty, map item will be deleted (if it exists at all)
   void modifyMap(TMapEntryType aEntryType, const char *aLocalID, const char *aRemoteID, uInt32 aMapFlags, bool aDelete, uInt32 aClearFlags=0xFFFFFFFF);
-  #endif // not BASED_ON_BINFILE_CLIENT
-  #ifndef SYSYNC_CLIENT
+  #endif // not BINFILE_ALWAYS_ACTIVE
+  #ifdef SYSYNC_SERVER
   // - called when a item in the sync set changes its localID (due to local DB internals)
   //   Datastore must make sure that eventually cached items get updated
   virtual void dsLocalIdHasChanged(const char *aOldID, const char *aNewID);
-  #endif
+  #endif // SYSYNC_SERVER
   // - target key (if needed by descendant)
   string fTargetKey;
   // - folder key (key value for subselecting in datastore, determined at implMakeAdminReady())
@@ -781,7 +788,7 @@ protected:
   TSyncSetList::iterator fSyncSetPos;
   // - list of items that must be processed in finalisation at end of sync
   TMultiFieldItemList fFinalisationQueue;
-  #ifndef BASED_ON_BINFILE_CLIENT
+  #ifndef BINFILE_ALWAYS_ACTIVE
   // local map list
   TMapContainer fMapTable;
   // - iterator for reporting deleted items in GetItem
@@ -789,7 +796,8 @@ protected:
   bool fReportDeleted;
   TGetPhases fGetPhase; // phase of get
   bool fGetPhasePrepared; // set if phase is prepared (select or list iterator init)
-  #else // not BASED_ON_BINFILE_CLIENT
+  #endif // BINFILE_ALWAYS_ACTIVE
+  #ifdef BASED_ON_BINFILE_CLIENT
   bool fSyncSetLoaded; // set if sync set is currently loaded
   bool makeSyncSetLoaded(bool aNeedAll);
   #endif // BASED_ON_BINFILE_CLIENT
@@ -798,7 +806,7 @@ protected:
   #ifdef SCRIPT_SUPPORT
   bool fOptionFilterTested;
   bool fOptionFilterWorksOnDBLevel; // set if option filters can be executed by DB
-  #endif
+  #endif // SCRIPT_SUPPORT
 
        #ifdef DBAPI_TUNNEL_SUPPORT
   // Tunnel DB access support
index 028d76e..a307f8f 100644 (file)
@@ -20,10 +20,23 @@ public:
   {}
   virtual bool logicProcessRemoteItem(TSyncItem*, TStatusCommand&, bool&, std::string*) { return false; }
   virtual bool logicRetrieveItemByID(TSyncItem&, TStatusCommand&) { return false; }
+#ifdef SYSYNC_CLIENT
   virtual bool logicGenerateSyncCommandsAsClient(TSmlCommandPContainer&, TSmlCommand*&, const char*) { return false; }
+#endif
+#ifdef SYSYNC_SERVER
+  virtual bool logicGenerateSyncCommandsAsServer(TSmlCommandPContainer &, TSmlCommand * &,
+    const char *) { return false; }
+#endif
   virtual void logicMarkOnlyUngeneratedForResume() {}
   virtual void logicMarkItemForResume(const char*, const char*, bool) {}
   virtual void logicMarkItemForResend(const char*, const char*) {}
+#ifdef SYSYNC_SERVER
+  virtual TSyncItem *getConflictingItemByRemoteID(TSyncItem *syncitemP) { return NULL; }
+  virtual TSyncItem *getMatchingItem(TSyncItem *syncitemP, TEqualityMode aEqMode) { return NULL; }
+  virtual void dontSendItemAsServer(TSyncItem *syncitemP) {}
+  virtual void SendItemAsServer(TSyncItem *aSyncitemP) {}
+  virtual localstatus logicProcessMap(cAppCharP aRemoteID, cAppCharP aLocalID) { return 0; }
+#endif
 };
 
 bool DataConversion(SessionH aSession,
index 1deafa5..1273901 100755 (executable)
@@ -22,6 +22,7 @@
 
 using namespace sysync;
 
+namespace sysync {
 
 const char* BeginCDATA=          "<![CDATA[";
 const char*   EndCDATA= "]]>";
@@ -966,7 +967,7 @@ bool TDataObjType::copyCTCapInfoFrom(TSyncItemType &aSourceItem)
 } // TDataObjType::copyCTCapInfoFrom
 
 
-
+} // namespace sysync
 
 /* end of TDataObjType implementation */
 // eof
index 7ee77f2..8f2f2d6 100755 (executable)
@@ -603,7 +603,8 @@ void TDebugLoggerBase::DebugOpenBlock(cAppCharP aBlockName, cAppCharP aBlockTitl
 {
   // we need a format and debug not completely off
   if (getMask() && aBlockName) {
-    static va_list va;
+    va_list va;
+    memset(&va, 0, sizeof(va));
     DebugVOpenBlock(aBlockName,aBlockTitle,aCollapsed,NULL,va);
   }
 } // TDebugLoggerBase::DebugOpenBlock
index e938c77..d780886 100755 (executable)
@@ -78,6 +78,7 @@ public:
   string fIndentString; ///< indent string
   string fCustomPrefix; ///< custom prefix (different xml header or html with different styles for example)
   string fCustomSuffix; ///< custom suffix (should match prefix)
+  string fBasename; ///< the initial part of the log file name, can override the hard-coded TARGETID (empty if unset)
   bool fSeparateMsgs; ///< separate message lines (needed especially in XML to avoid unformatted PCDATA block)
   bool fTimestampStructure; ///< include timestamp for structure elements (blocks)
   bool fTimestampForAll; ///< include timestamp information for every message
index 8d79b77..5802a12 100755 (executable)
@@ -24,89 +24,89 @@ using namespace std;
 namespace sysync {
 
 
-ENGINE_ENTRY void     DebugDB          ( void* aCB,    cAppCharP  aParams )   ENTRY_ATTR;
-ENGINE_ENTRY void     DebugExotic      ( void* aCB,    cAppCharP  aParams )   ENTRY_ATTR;
-ENGINE_ENTRY void     DebugBlock       ( void* aCB,    cAppCharP  aTag,
-                                                       cAppCharP  aDesc,
-                                                       cAppCharP  aAttrText ) ENTRY_ATTR;
-ENGINE_ENTRY void     DebugEndBlock    ( void* aCB,    cAppCharP  aTag )      ENTRY_ATTR;
-ENGINE_ENTRY void     DebugEndThread   ( void* aCB )                          ENTRY_ATTR;
+ENGINE_ENTRY_CXX void     DebugDB          ( void* aCB,    cAppCharP  aParams )   ENTRY_ATTR;
+ENGINE_ENTRY_CXX void     DebugExotic      ( void* aCB,    cAppCharP  aParams )   ENTRY_ATTR;
+ENGINE_ENTRY_CXX void     DebugBlock       ( void* aCB,    cAppCharP  aTag,
+                                             cAppCharP  aDesc,
+                                             cAppCharP  aAttrText ) ENTRY_ATTR;
+ENGINE_ENTRY_CXX void     DebugEndBlock    ( void* aCB,    cAppCharP  aTag )      ENTRY_ATTR;
+ENGINE_ENTRY_CXX void     DebugEndThread   ( void* aCB )                          ENTRY_ATTR;
 
 // ----------------------------------------------------------------------------------------
-ENGINE_ENTRY TSyError SetStringMode    ( void* aCB,       uInt16  aCharSet,
-                                                          uInt16  aLineEndMode,    bool aBigEndian ) ENTRY_ATTR;
-ENGINE_ENTRY TSyError InitEngineXML    ( void* aCB,    cAppCharP  aConfigXML )                       ENTRY_ATTR;
-ENGINE_ENTRY TSyError InitEngineFile   ( void* aCB,    cAppCharP  aConfigFilePath )                  ENTRY_ATTR;
-ENGINE_ENTRY TSyError InitEngineCB     ( void* aCB, TXMLConfigReadFunc aReaderFunc, void* aContext ) ENTRY_ATTR;
-
-
-ENGINE_ENTRY TSyError OpenSession      ( void* aCB,   SessionH *aSessionH, uInt32  aSelector,
-                                         cAppCharP  aSessionName )                ENTRY_ATTR;
-ENGINE_ENTRY TSyError OpenSessionKey   ( void* aCB,   SessionH aSessionH,
-                                         KeyH *aKeyH,     uInt16  aMode    ) ENTRY_ATTR;
-ENGINE_ENTRY TSyError SessionStep      ( void* aCB,   SessionH  aSessionH, uInt16 *aStepCmd,
-                                         TEngineProgressInfo *aInfoP   ) ENTRY_ATTR;
-ENGINE_ENTRY TSyError GetSyncMLBuffer  ( void* aCB,   SessionH aSessionH,   bool  aForSend,
-                                         appPointer *aBuffer,  memSize *aBufSize ) ENTRY_ATTR;
-ENGINE_ENTRY TSyError RetSyncMLBuffer  ( void* aCB,   SessionH aSessionH,   bool  aForSend,
-                                                                            memSize  aRetSize ) ENTRY_ATTR;
-ENGINE_ENTRY TSyError ReadSyncMLBuffer ( void* aCB,   SessionH  aSessionH,
-                                         appPointer  aBuffer,  memSize  aBufSize,
-                                                                            memSize *aValSize ) ENTRY_ATTR;
-ENGINE_ENTRY TSyError WriteSyncMLBuffer( void* aCB,   SessionH aSessionH,
-                                         appPointer  aBuffer,  memSize  aValSize ) ENTRY_ATTR;
-ENGINE_ENTRY TSyError CloseSession     ( void* aCB,   SessionH  aSessionH )                   ENTRY_ATTR;
-
-
-ENGINE_ENTRY TSyError OpenKeyByPath    ( void* aCB,   KeyH *aKeyH,
-                                         KeyH  aParentKeyH, cAppCharP aPath, uInt16 aMode )   ENTRY_ATTR;
-ENGINE_ENTRY TSyError OpenSubkey       ( void* aCB,   KeyH *aKeyH,
-                                         KeyH aParentKeyH, sInt32  aID,     uInt16 aMode )   ENTRY_ATTR;
-ENGINE_ENTRY TSyError DeleteSubkey     ( void* aCB,   KeyH  aParentKeyH, sInt32  aID )                     ENTRY_ATTR;
-ENGINE_ENTRY TSyError GetKeyID         ( void* aCB,   KeyH  aKeyH,       sInt32 *aID )                     ENTRY_ATTR;
-ENGINE_ENTRY TSyError SetTextMode      ( void* aCB,   KeyH  aKeyH,       uInt16  aCharSet,
-                                         uInt16  aLineEndMode,  bool  aBigEndian )              ENTRY_ATTR;
-ENGINE_ENTRY TSyError SetTimeMode      ( void* aCB,   KeyH aKeyH,       uInt16  aTimeMode )               ENTRY_ATTR;
-ENGINE_ENTRY TSyError CloseKey         ( void* aCB,   KeyH aKeyH )                                        ENTRY_ATTR;
-
-ENGINE_ENTRY TSyError GetValue         ( void* aCB,   KeyH aKeyH, cAppCharP aValName,  uInt16  aValType,
-                                         appPointer  aBuffer, memSize aBufSize, memSize *aValSize ) ENTRY_ATTR;
-ENGINE_ENTRY TSyError GetValueByID     ( void* aCB,   KeyH aKeyH,    sInt32 aID,       sInt32  arrIndex,
-                                                                                              uInt16  aValType,
-                                         appPointer  aBuffer, memSize aBufSize, memSize *aValSize ) ENTRY_ATTR;
-ENGINE_ENTRY sInt32   GetValueID       ( void* aCB,   KeyH aKeyH, cAppCharP aName )                       ENTRY_ATTR;
-ENGINE_ENTRY TSyError SetValue         ( void* aCB,   KeyH aKeyH, cAppCharP aValName,  uInt16  aValType,
-                                         cAppPointer  aBuffer, memSize aValSize )                    ENTRY_ATTR;
-ENGINE_ENTRY TSyError SetValueByID     ( void* aCB,   KeyH  aKeyH,    sInt32 aID,       sInt32  arrIndex,
-                                         uInt16  aValType,
-                                         cAppPointer  aBuffer, memSize aValSize )                    ENTRY_ATTR;
+ENGINE_ENTRY_CXX TSyError SetStringMode    ( void* aCB,       uInt16  aCharSet,
+                                             uInt16  aLineEndMode,    bool aBigEndian ) ENTRY_ATTR;
+ENGINE_ENTRY_CXX TSyError InitEngineXML    ( void* aCB,    cAppCharP  aConfigXML )                       ENTRY_ATTR;
+ENGINE_ENTRY_CXX TSyError InitEngineFile   ( void* aCB,    cAppCharP  aConfigFilePath )                  ENTRY_ATTR;
+ENGINE_ENTRY_CXX TSyError InitEngineCB     ( void* aCB, TXMLConfigReadFunc aReaderFunc, void* aContext ) ENTRY_ATTR;
+
+
+ENGINE_ENTRY_CXX TSyError OpenSession      ( void* aCB,   SessionH *aSessionH, uInt32  aSelector,
+                                             cAppCharP  aSessionName )                ENTRY_ATTR;
+ENGINE_ENTRY_CXX TSyError OpenSessionKey   ( void* aCB,   SessionH aSessionH,
+                                             KeyH *aKeyH,     uInt16  aMode    ) ENTRY_ATTR;
+ENGINE_ENTRY_CXX TSyError SessionStep      ( void* aCB,   SessionH  aSessionH, uInt16 *aStepCmd,
+                                             TEngineProgressInfo *aInfoP   ) ENTRY_ATTR;
+ENGINE_ENTRY_CXX TSyError GetSyncMLBuffer  ( void* aCB,   SessionH aSessionH,   bool  aForSend,
+                                             appPointer *aBuffer,  memSize *aBufSize ) ENTRY_ATTR;
+ENGINE_ENTRY_CXX TSyError RetSyncMLBuffer  ( void* aCB,   SessionH aSessionH,   bool  aForSend,
+                                             memSize  aRetSize ) ENTRY_ATTR;
+ENGINE_ENTRY_CXX TSyError ReadSyncMLBuffer ( void* aCB,   SessionH  aSessionH,
+                                             appPointer  aBuffer,  memSize  aBufSize,
+                                             memSize *aValSize ) ENTRY_ATTR;
+ENGINE_ENTRY_CXX TSyError WriteSyncMLBuffer( void* aCB,   SessionH aSessionH,
+                                             appPointer  aBuffer,  memSize  aValSize ) ENTRY_ATTR;
+ENGINE_ENTRY_CXX TSyError CloseSession     ( void* aCB,   SessionH  aSessionH )                   ENTRY_ATTR;
+
+
+ENGINE_ENTRY_CXX TSyError OpenKeyByPath    ( void* aCB,   KeyH *aKeyH,
+                                             KeyH  aParentKeyH, cAppCharP aPath, uInt16 aMode )   ENTRY_ATTR;
+ENGINE_ENTRY_CXX TSyError OpenSubkey       ( void* aCB,   KeyH *aKeyH,
+                                             KeyH aParentKeyH, sInt32  aID,     uInt16 aMode )   ENTRY_ATTR;
+ENGINE_ENTRY_CXX TSyError DeleteSubkey     ( void* aCB,   KeyH  aParentKeyH, sInt32  aID )                     ENTRY_ATTR;
+ENGINE_ENTRY_CXX TSyError GetKeyID         ( void* aCB,   KeyH  aKeyH,       sInt32 *aID )                     ENTRY_ATTR;
+ENGINE_ENTRY_CXX TSyError SetTextMode      ( void* aCB,   KeyH  aKeyH,       uInt16  aCharSet,
+                                             uInt16  aLineEndMode,  bool  aBigEndian )              ENTRY_ATTR;
+ENGINE_ENTRY_CXX TSyError SetTimeMode      ( void* aCB,   KeyH aKeyH,       uInt16  aTimeMode )               ENTRY_ATTR;
+ENGINE_ENTRY_CXX TSyError CloseKey         ( void* aCB,   KeyH aKeyH )                                        ENTRY_ATTR;
+
+ENGINE_ENTRY_CXX TSyError GetValue         ( void* aCB,   KeyH aKeyH, cAppCharP aValName,  uInt16  aValType,
+                                             appPointer  aBuffer, memSize aBufSize, memSize *aValSize ) ENTRY_ATTR;
+ENGINE_ENTRY_CXX TSyError GetValueByID     ( void* aCB,   KeyH aKeyH,    sInt32 aID,       sInt32  arrIndex,
+                                             uInt16  aValType,
+                                             appPointer  aBuffer, memSize aBufSize, memSize *aValSize ) ENTRY_ATTR;
+ENGINE_ENTRY_CXX sInt32   GetValueID       ( void* aCB,   KeyH aKeyH, cAppCharP aName )                       ENTRY_ATTR;
+ENGINE_ENTRY_CXX TSyError SetValue         ( void* aCB,   KeyH aKeyH, cAppCharP aValName,  uInt16  aValType,
+                                             cAppPointer  aBuffer, memSize aValSize )                    ENTRY_ATTR;
+ENGINE_ENTRY_CXX TSyError SetValueByID     ( void* aCB,   KeyH  aKeyH,    sInt32 aID,       sInt32  arrIndex,
+                                             uInt16  aValType,
+                                             cAppPointer  aBuffer, memSize aValSize )                    ENTRY_ATTR;
 
 
 // ---- tunnel --------------------------------------------------------------------------------------------------------
-ENGINE_ENTRY TSyError StartDataRead    ( CContext ac,  cAppCharP  lastToken, cAppCharP  resumeToken )       ENTRY_ATTR;
-ENGINE_ENTRY TSyError ReadNextItem     ( CContext ac,     ItemID  aID,        appCharP *aItemData,
-                                                          sInt32 *aStatus,        bool  aFirst )            ENTRY_ATTR;
-ENGINE_ENTRY TSyError ReadItem         ( CContext ac,    cItemID  aID,        appCharP *aItemData )         ENTRY_ATTR;
-ENGINE_ENTRY TSyError EndDataRead      ( CContext ac )                                                      ENTRY_ATTR;
-ENGINE_ENTRY TSyError StartDataWrite   ( CContext ac )                                                      ENTRY_ATTR;
-ENGINE_ENTRY TSyError InsertItem       ( CContext ac,  cAppCharP  aItemData,    ItemID  aID )               ENTRY_ATTR;
-ENGINE_ENTRY TSyError UpdateItem       ( CContext ac,  cAppCharP  aItemData,   cItemID  aID, ItemID updID ) ENTRY_ATTR;
-ENGINE_ENTRY TSyError MoveItem         ( CContext ac,    cItemID  aID,       cAppCharP           newParID ) ENTRY_ATTR;
-ENGINE_ENTRY TSyError DeleteItem       ( CContext ac,    cItemID  aID )                                     ENTRY_ATTR;
-ENGINE_ENTRY TSyError EndDataWrite     ( CContext ac,       bool  success,    appCharP *newToken )          ENTRY_ATTR;
-ENGINE_ENTRY void     DisposeObj       ( CContext ac,      void*  memory )                                  ENTRY_ATTR;
+ENGINE_ENTRY_CXX TSyError StartDataRead    ( CContext ac,  cAppCharP  lastToken, cAppCharP  resumeToken )       ENTRY_ATTR;
+ENGINE_ENTRY_CXX TSyError ReadNextItem     ( CContext ac,     ItemID  aID,        appCharP *aItemData,
+                                             sInt32 *aStatus,        bool  aFirst )            ENTRY_ATTR;
+ENGINE_ENTRY_CXX TSyError ReadItem         ( CContext ac,    cItemID  aID,        appCharP *aItemData )         ENTRY_ATTR;
+ENGINE_ENTRY_CXX TSyError EndDataRead      ( CContext ac )                                                      ENTRY_ATTR;
+ENGINE_ENTRY_CXX TSyError StartDataWrite   ( CContext ac )                                                      ENTRY_ATTR;
+ENGINE_ENTRY_CXX TSyError InsertItem       ( CContext ac,  cAppCharP  aItemData,    ItemID  aID )               ENTRY_ATTR;
+ENGINE_ENTRY_CXX TSyError UpdateItem       ( CContext ac,  cAppCharP  aItemData,   cItemID  aID, ItemID updID ) ENTRY_ATTR;
+ENGINE_ENTRY_CXX TSyError MoveItem         ( CContext ac,    cItemID  aID,       cAppCharP           newParID ) ENTRY_ATTR;
+ENGINE_ENTRY_CXX TSyError DeleteItem       ( CContext ac,    cItemID  aID )                                     ENTRY_ATTR;
+ENGINE_ENTRY_CXX TSyError EndDataWrite     ( CContext ac,       bool  success,    appCharP *newToken )          ENTRY_ATTR;
+ENGINE_ENTRY_CXX void     DisposeObj       ( CContext ac,      void*  memory )                                  ENTRY_ATTR;
 
 // ---- asKey ----
-ENGINE_ENTRY TSyError ReadNextItemAsKey( CContext ac,     ItemID  aID,            KeyH  aItemKey,
-                                                          sInt32 *aStatus,        bool  aFirst )            ENTRY_ATTR;
-ENGINE_ENTRY TSyError ReadItemAsKey    ( CContext ac,    cItemID  aID,            KeyH  aItemKey )          ENTRY_ATTR;
-ENGINE_ENTRY TSyError InsertItemAsKey  ( CContext ac,       KeyH  aItemKey,     ItemID  aID )               ENTRY_ATTR;
-ENGINE_ENTRY TSyError UpdateItemAsKey  ( CContext ac,       KeyH  aItemKey,    cItemID  aID, ItemID updID ) ENTRY_ATTR;
+ENGINE_ENTRY_CXX TSyError ReadNextItemAsKey( CContext ac,     ItemID  aID,            KeyH  aItemKey,
+                                             sInt32 *aStatus,        bool  aFirst )            ENTRY_ATTR;
+ENGINE_ENTRY_CXX TSyError ReadItemAsKey    ( CContext ac,    cItemID  aID,            KeyH  aItemKey )          ENTRY_ATTR;
+ENGINE_ENTRY_CXX TSyError InsertItemAsKey  ( CContext ac,       KeyH  aItemKey,     ItemID  aID )               ENTRY_ATTR;
+ENGINE_ENTRY_CXX TSyError UpdateItemAsKey  ( CContext ac,       KeyH  aItemKey,    cItemID  aID, ItemID updID ) ENTRY_ATTR;
 
 
 
 // ----------------------------------------------------------------------------------------
-ENGINE_ENTRY void CB_Connect( void* aCB ) ENTRY_ATTR;
+ENGINE_ENTRY_CXX void CB_Connect( void* aCB ) ENTRY_ATTR;
 
 // engine local helper, used e.g. from PluginDS/Agent
 void CB_Connect_KeyAccess   ( void* aCB );
index 0bec67d..51ec65f 100644 (file)
@@ -741,6 +741,17 @@ TSyError TStructFieldsKey::returnInt(sInt32 aInt, memSize aIntSize, appPointer a
 } // returnInt
 
 
+TSyError TStructFieldsKey::returnLineartime(lineartime_t aTime, appPointer aBuffer, memSize aBufSize, memSize &aValSize)
+{
+       aValSize=sizeof(lineartime_t);
+  if (aBufSize==0) return LOCERR_OK; // measuring size
+  if (aBufSize<aValSize) return LOCERR_BUFTOOSMALL;
+  *((lineartime_t *)aBuffer) = aTime;
+  return LOCERR_OK;
+}
+
+
+
 
 // get value's ID (e.g. internal index)
 sInt32 TStructFieldsKey::GetValueID(cAppCharP aName)
@@ -1771,12 +1782,77 @@ TSyError TEngineInterface::UpdateItemAsKey(SessionH aSessionH, KeyH aItemKey, cI
 
 #endif // DBAPI_TUNNEL_SUPPORT
 
+TSyError TEngineInterface::debugPuts(cAppCharP aFile, int aLine, cAppCharP aFunction,
+                                     int aDbgLevel, cAppCharP aPrefix,
+                                     cAppCharP aText)
+{
+  #if defined(SYDEBUG)
+  getSyncAppBase()->getDbgLogger()->DebugPuts(/* aFile, aLine, aFunction, aPrefix */
+                                              aDbgLevel, aText);
+  return 0;
+  #else
+  return LOCERR_NOTIMP;
+  #endif
+} // debugPuts
 
+#ifdef ENGINE_LIBRARY
 #ifndef SIMPLE_LINKING
 
 // Callback "factory" function implementation
 
-// Main entry point
+static TSyError internal_ConnectEngine(
+       bool aIsServer,
+  UI_Call_In *aCIP,
+  uInt16 aCallbackVersion, // if==0, engine creates new aCI
+  CVersion *aEngVersionP,
+  CVersion aPrgVersion,
+  uInt16 aDebugFlags
+)  
+{
+  // create new engine
+  TEngineModuleBase *engine = NULL;
+  TSyError err = LOCERR_OK;
+  if (aIsServer) {
+       #ifdef SYSYNC_SERVER
+    engine = newServerEngine();
+    #else
+    err = LOCERR_WRONGUSAGE;
+    #endif
+  }
+  else {
+       #ifdef SYSYNC_CLIENT
+    engine = newClientEngine();
+    #else
+    err = LOCERR_WRONGUSAGE;
+    #endif
+  }
+  if (err==LOCERR_OK) {
+    // connect the engine
+    if (aCallbackVersion!=0) {
+      // valid aCIP passed in
+      // - flag static
+      engine->fCIisStatic= true;
+      // - prepare callback and pass to engine
+      (*aCIP)->callbackVersion = aCallbackVersion;
+      engine->fCI = *aCIP;
+      // - connect the engine
+      err = engine->Connect("", aPrgVersion, aDebugFlags);
+    }
+    else {
+       // no aCIP passed, let engine create one
+      // - connect engine
+                 err = engine->Connect("", aPrgVersion, aDebugFlags);
+      // - get CI from engine
+                       *aCIP = engine->fCI;
+    }
+    // - get the version
+    if (aEngVersionP) *aEngVersionP = Plugin_Version(0);
+  }
+  return   err;        
+} // internal_ConnectEngine
+
+
+// Client engine main entry point
 TSyError SYSYNC_EXTERNAL(ConnectEngine)(
   UI_Call_In *aCI,
   CVersion   *aEngVersion,
@@ -1784,13 +1860,7 @@ TSyError SYSYNC_EXTERNAL(ConnectEngine)(
   uInt16      aDebugFlags
 )
 {
-  // create new engine
-  TEngineModuleBase *engine = newEngine();
-  // connect callback
-  TSyError err= engine->Connect("", aPrgVersion, aDebugFlags);
-  *aCI        = engine->fCI;
-  *aEngVersion= Plugin_Version(0);
-  return   err;
+       return internal_ConnectEngine(false, aCI, 0, aEngVersion, aPrgVersion, aDebugFlags);
 } // ConnectEngine
 
 
@@ -1803,21 +1873,38 @@ TSyError SYSYNC_EXTERNAL(ConnectEngineS)(
   uInt16      aDebugFlags
 )
 {
-  // create new engine
-  TEngineModuleBase *engine = newEngine();
-  engine->fCIisStatic= true;
-
-  // connect callback
-                aCI->callbackVersion= aCallbackVersion;
-  engine->fCI = aCI;
-  TSyError err= engine->Connect( "", aPrgVersion, aDebugFlags );
-  *aEngVersion= Plugin_Version(0);
-  return   err;
+       return internal_ConnectEngine(false, &aCI, aCallbackVersion, aEngVersion, aPrgVersion, aDebugFlags);
 } // ConnectEngineS
 
 
-/* Entry point to disconnect engine */
-TSyError SYSYNC_EXTERNAL(DisconnectEngine)( UI_Call_In aCI )
+// Server engine main entry point
+TSyError SYSYNC_EXTERNAL_SRV(ConnectEngine)(
+  UI_Call_In *aCI,
+  CVersion   *aEngVersion,
+  CVersion    aPrgVersion,
+  uInt16      aDebugFlags
+)
+{
+       return internal_ConnectEngine(true, aCI, 0, aEngVersion, aPrgVersion, aDebugFlags);
+} // ConnectEngine
+
+
+// The same, but coming in with a valid <aCI> */
+TSyError SYSYNC_EXTERNAL_SRV(ConnectEngineS)(
+  UI_Call_In  aCI,
+  uInt16      aCallbackVersion,
+  CVersion   *aEngVersion,
+  CVersion    aPrgVersion,
+  uInt16      aDebugFlags
+)
+{
+       return internal_ConnectEngine(true, &aCI, aCallbackVersion, aEngVersion, aPrgVersion, aDebugFlags);
+} // ConnectEngineS
+
+
+
+
+static TSyError internal_DisconnectEngine(UI_Call_In aCI)
 {
   TSyError err= LOCERR_OK;
 
@@ -1826,7 +1913,6 @@ TSyError SYSYNC_EXTERNAL(DisconnectEngine)( UI_Call_In aCI )
     TEngineModuleBase *engine = static_cast<TEngineModuleBase *>(aCI->thisBase);
     err= engine->Disconnect();
     aCI->thisBase= NULL; // no longer valid
-
     // delete the engine (this also deletes the callback!)
     SYSYNC_TRY {
       delete engine;
@@ -1836,13 +1922,26 @@ TSyError SYSYNC_EXTERNAL(DisconnectEngine)( UI_Call_In aCI )
     SYSYNC_ENDCATCH
     // done
   } // if
-
   return err;
-} // DisconnectEngine
+} // internal_DisconnectEngine
+
+
+/* Entry point to disconnect client engine */
+TSyError SYSYNC_EXTERNAL(DisconnectEngine)(UI_Call_In aCI)
+{
+       return internal_DisconnectEngine(aCI);
+}
+
 
+/* Entry point to disconnect server engine */
+TSyError SYSYNC_EXTERNAL_SRV(DisconnectEngine)(UI_Call_In aCI)
+{
+       return internal_DisconnectEngine(aCI);
+}
 
 
 #endif // not SIMPLE_LINKING
+#endif // ENGINE_LIBRARY
 
 
 } // namespace sysync
index 6937272..5fe08c9 100755 (executable)
@@ -55,12 +55,17 @@ class TSyncAppBase;
 
 #ifdef SIMPLE_LINKING
   // for using the engineInterface without EngineModuleBase, engine base class
-  // for the newEngine() function is TEngineInterface
+  // for the newXXXXEngine() functions is TEngineInterface
   #define ENGINE_IF_CLASS TEngineInterface
-  // factory function declaration is here, as we have no EngineModuleBase
-  ENGINE_IF_CLASS *newEngine(void);
+  // factory function declarations are here, as we have no EngineModuleBase
+  #ifdef SYSYNC_CLIENT
+  ENGINE_IF_CLASS *newClientEngine(void);
+  #endif
+  #ifdef SYSYNC_SERVER
+  ENGINE_IF_CLASS *newServerEngine(void);
+  #endif
 #else
-  // with EngineModuleBase, use it as base class. newEngine is declared in
+  // with EngineModuleBase, use it as base class. newXXXXXEngine are declared in
   // enginemodulebase.h
   #define ENGINE_IF_CLASS TEngineModuleBase
 #endif
@@ -322,6 +327,7 @@ public:
   // - static helper for procedural string readers
   static TSyError returnString(cAppCharP aReturnString, appPointer aBuffer, memSize aBufSize, memSize &aValSize);
   static TSyError returnInt(sInt32 aInt, memSize aIntSize, appPointer aBuffer, memSize aBufSize, memSize &aValSize);
+  static TSyError returnLineartime(lineartime_t aTime, appPointer aBuffer, memSize aBufSize, memSize &aValSize);
 
 protected:
 
@@ -749,6 +755,10 @@ public:
     EMBVIRTUAL TSyError InsertItemAsKey  ( SessionH aSessionH, KeyH aItemKey,  ItemID aID ) TUNNEL_IMPL;
     EMBVIRTUAL TSyError UpdateItemAsKey  ( SessionH aSessionH, KeyH aItemKey, cItemID aID, ItemID updID ) TUNNEL_IMPL;
     
+    EMBVIRTUAL TSyError debugPuts(cAppCharP aFile, int aLine, cAppCharP aFunction,
+                                  int aDbgLevel, cAppCharP aLinePrefix,
+                                  cAppCharP aText);
+
     /// @}
 
     /// @brief returns the current application base object
index 797e7ff..472a32e 100644 (file)
 // includes
 #include "prefix_file.h"
 #include "sysync.h"
-#include "syncappbase.h"
 #include "localengineds.h"
+#include "syncappbase.h"
 #include "scriptcontext.h"
 #include "superdatastore.h"
-
-#ifdef SYSYNC_CLIENT
-#include "syncclient.h"
-#endif
+#include "syncagent.h"
 
 
 using namespace sysync;
@@ -475,7 +472,7 @@ public:
     int daysbefore = aFuncContextP->getLocalVar(0)->getAsInteger();
     int daysafter = aFuncContextP->getLocalVar(1)->getAsInteger();
     // depending on SyncML version, create a SINCE/BEFORE filter or use the /dr(x,y) syntax
-    if (dsP->getSession()->getSyncMLVersion()>=syncml_vers_1_2 && static_cast<TSyncClient *>(dsP->getSession())->fServerHasSINCEBEFORE) {
+    if (dsP->getSession()->getSyncMLVersion()>=syncml_vers_1_2 && static_cast<TSyncAgent *>(dsP->getSession())->fServerHasSINCEBEFORE) {
       // use the SINCE/BEFORE syntax
       // BEFORE&EQ;20070808T000000Z&AND;SINCE&EQ;20070807T000000Z
       lineartime_t now = getSystemNowAs(TCTX_UTC,aFuncContextP->getSessionZones());
@@ -767,7 +764,7 @@ bool TTypeSupportConfig::localStartElement(const char *aElementName, const char
         }
                                else
                return fail("bad value for 'preferred'");
-      }      
+      }
     }
     // now add datatype
     if (preferred) {
@@ -866,7 +863,7 @@ void TLocalDSConfig::clear(void)
   fReportUpdates=true;
   fDeleteWins=false; // replace wins over delete by default
   fResendFailing=true; // resend failing items in next session by default
-  #ifndef SYSYNC_CLIENT
+  #ifdef SYSYNC_SERVER
   fTryUpdateDeleted=false; // no attempt to update already deleted items (assuming they are invisible only)
   fAlwaysSendLocalID=false; // off as it used to be not SCTS conformant (but would give clients chances to remap IDs)
   #endif
@@ -924,7 +921,7 @@ bool TLocalDSConfig::localStartElement(const char *aElementName, const char **aA
     expectBool(fDeleteWins);
   else if (strucmp(aElementName,"resendfailing")==0)
     expectBool(fResendFailing);
-  #ifndef SYSYNC_CLIENT
+  #ifdef SYSYNC_SERVER
   else if (strucmp(aElementName,"tryupdatedeleted")==0)
     expectBool(fTryUpdateDeleted);
   else if (strucmp(aElementName,"alwayssendlocalid")==0)
@@ -1155,14 +1152,15 @@ void TLocalEngineDS::InternalResetDataStore(void)
   fPendingAddMaps.clear();
   fUnconfirmedMaps.clear();
   fLastSessionMaps.clear();
-  #else
+  #endif
+  #ifdef SYSYNC_SERVER
   fTempGUIDMap.clear();
   #endif
 
        /// Init type negotiation
   /// - for sending data
   fLocalSendToRemoteTypeP = NULL;
-  fRemoteReceiveFromLocalTypeP = NULL;  
+  fRemoteReceiveFromLocalTypeP = NULL;
   /// - for receiving data
   fLocalReceiveFromRemoteTypeP = NULL;
   fRemoteSendToLocalTypeP = NULL;
@@ -1237,7 +1235,7 @@ void TLocalEngineDS::InternalResetDataStore(void)
   fRemoteItemsUpdated=0;
   fRemoteItemsDeleted=0;
   fRemoteItemsError=0;
-  #ifndef SYSYNC_CLIENT
+  #ifdef SYSYNC_SERVER
   // - conflicts
   fConflictsServerWins=0;
   fConflictsClientWins=0;
@@ -1421,21 +1419,23 @@ TTypeVariantDescriptor TLocalEngineDS::getVariantDescForType(TSyncItemType *aIte
 // - called when a item in the sync set changes its localID (due to local DB internals)
 void TLocalEngineDS::dsLocalIdHasChanged(const char *aOldID, const char *aNewID)
 {
-  #ifndef SYSYNC_CLIENT
-  // make sure remapped localIDs get updated as well
-  TStringToStringMap::iterator pos;
-  for (pos=fTempGUIDMap.begin(); pos!=fTempGUIDMap.end(); pos++) {
-    if (pos->second == aOldID) {
-      // update ID
-      pos->second = aNewID;
-      break;
+  #ifdef SYSYNC_SERVER
+  if (IS_SERVER) {
+    // make sure remapped localIDs get updated as well
+    TStringToStringMap::iterator pos;
+    for (pos=fTempGUIDMap.begin(); pos!=fTempGUIDMap.end(); pos++) {
+      if (pos->second == aOldID) {
+        // update ID
+        pos->second = aNewID;
+        break;
+      }
     }
   }
-  #endif
+  #endif // SYSYNC_SERVER
 } // TLocalEngineDS::dsLocalIdHasChanged
 
 
-#ifndef SYSYNC_CLIENT
+#ifdef SYSYNC_SERVER
 
 // for received GUIDs (Map command), obtain real GUID (might be temp GUID due to maxguidsize restrictions)
 void TLocalEngineDS::obtainRealLocalID(string &aLocalID)
@@ -1467,7 +1467,7 @@ void TLocalEngineDS::adjustLocalIDforSize(string &aLocalID, sInt32 maxguidsize,
     if (aLocalID.length()+prefixsize>(uInt32)maxguidsize) { //BCPPB needed unsigned cast
       // real GUID is too long, we need to create a temp
       string tempguid;
-      StringObjPrintf(tempguid,"#%ld",fTempGUIDMap.size()+1); // as list only grows, we have unique tempuids for sure
+      StringObjPrintf(tempguid,"#%lu",(unsigned long)fTempGUIDMap.size()+1); // as list only grows, we have unique tempuids for sure
       fTempGUIDMap[tempguid]=aLocalID;
       PDEBUGPRINTFX(DBG_DATA,(
         "translated realLocalID='%s' to tempLocalID='%s'",
@@ -1479,7 +1479,7 @@ void TLocalEngineDS::adjustLocalIDforSize(string &aLocalID, sInt32 maxguidsize,
   }
 } // TLocalEngineDS::adjustLocalIDforSize
 
-#endif
+#endif // SYSYNC_SERVER
 
 
 // set Sync types needed for sending local data to remote DB
@@ -1890,7 +1890,6 @@ const char *TLocalEngineDS::parseOption(
   #ifdef OBJECT_FILTERING
   if (strucmp(aOptName,"fi")==0) {
     if (!aArguments) return NULL;
-    bool filterok=false; // assume invalid
     // make sync set filter expression
     string f;
     aArguments=parseFilterCGI(aArguments,fLocalSendToRemoteTypeP,f); // if type being used for sending to remote is known here, use it
@@ -1904,7 +1903,6 @@ const char *TLocalEngineDS::parseOption(
   #ifdef SYNCML_TAF_SUPPORT
   else if (strucmp(aOptName,"tf")==0) {
     if (!aArguments) return NULL;
-    bool filterok=false; // assume invalid
     // make temporary filter (or TAF) expression
     aArguments=parseFilterCGI(aArguments,fLocalSendToRemoteTypeP,fTargetAddressFilter); // if type being used for sending to remote is known here, use it
     // Note: TAF filters are always evaluated internally as we need all SyncSet records
@@ -1957,15 +1955,15 @@ const char *TLocalEngineDS::parseOption(
   }
   else
   #endif
-  #ifndef SYSYNC_CLIENT
-  if (!aArguments && strucmp(aOptName,"slow")==0) {
+  #ifdef SYSYNC_SERVER
+  if (IS_SERVER && !aArguments && strucmp(aOptName,"slow")==0) {
     // force a slow sync
     PDEBUGPRINTFX(DBG_HOT,("Slowsync forced by CGI-option in db path"));
     fForceSlowSync=true;
     return (const char *)1; // non-zero
   }
   else
-  #endif
+  #endif // SYSYNC_SERVER
   if (aArguments && strucmp(aOptName,"o")==0) {
     // datastore options
     // - find end of arguments
@@ -2230,7 +2228,7 @@ TAlertCommand *TLocalEngineDS::engProcessSyncAlert(
     // NOTE for client case:
     //   ALL instantiated datastores have already sent an Alert to the server by now here
 
-    // check DS 1.2 filter
+    // check DS 1.2 <filter>
     sta = engProcessDS12Filter(aTargetFilter);
     if (sta != LOCERR_OK) {
       aStatusCommand.setStatusCode(sta);
@@ -2249,10 +2247,10 @@ TAlertCommand *TLocalEngineDS::engProcessSyncAlert(
         return NULL; // error in options
       }
     }
-    #ifndef SYSYNC_CLIENT
-    // server case: initially we are not in refresh only mode. Alert code or alert script could change this
-    fRefreshOnly=false;
-    #endif
+    if (IS_SERVER) {
+      // server case: initially we are not in refresh only mode. Alert code or alert script could change this
+      fRefreshOnly=false;
+    }
 
     // save it for suspend and reference in scripts
     fAlertCode=aAlertCode;
@@ -2267,52 +2265,59 @@ TAlertCommand *TLocalEngineDS::engProcessSyncAlert(
     aAlertCode=fAlertCode; // get eventually modified version back (SETALERTCODE)
     #endif
     // if we process a sync alert now, we haven't started sync or map generation
-    #ifndef SYSYNC_CLIENT
-    // server case: forget Temp GUID mapping
-    fTempGUIDMap.clear(); // forget all previous temp GUID mappings
+    #ifdef SYSYNC_SERVER
+    if (IS_SERVER) {
+      // server case: forget Temp GUID mapping
+      fTempGUIDMap.clear(); // forget all previous temp GUID mappings
+    }
     #endif
     // save remote's next anchor for saving at end of session
     fNextRemoteAnchor = aNextRemoteAnchor;
     // get target info in case we are server
-    #ifndef SYSYNC_CLIENT
-    // now get anchor info out of database
-    // - make sure other anchor variables are set
-    sta = engInitSyncAnchors(
-      aIdentifyingTargetURI, // use processed form, not as sent by remote
-      aSourceURI
-    );
-    if (sta!=LOCERR_OK) {
-      // error getting anchors
-      aStatusCommand.setStatusCode(syncmlError(sta));
-      PDEBUGPRINTFX(DBG_ERROR,("Could not get Sync Anchor info, status=%hd",sta));
-      return NULL; // no alert to send back
+    #ifdef SYSYNC_SERVER
+    if (IS_SERVER) {
+      // now get anchor info out of database
+      // - make sure other anchor variables are set
+      sta = engInitSyncAnchors(
+        aIdentifyingTargetURI, // use processed form, not as sent by remote
+        aSourceURI
+      );
+      if (sta!=LOCERR_OK) {
+        // error getting anchors
+        aStatusCommand.setStatusCode(syncmlError(sta));
+        PDEBUGPRINTFX(DBG_ERROR,("Could not get Sync Anchor info, status=%hd",sta));
+        return NULL; // no alert to send back
+      }
+      // Server ok until here
+      PDEBUGPRINTFX(DBG_PROTO,(
+        "Saved Last Remote Client Anchor='%s', received <last> Remote Client Anchor='%s' (must match for normal sync)",
+        fLastRemoteAnchor.c_str(),
+        aLastRemoteAnchor
+      ));
+      PDEBUGPRINTFX(DBG_PROTO,(
+        "Received <next> Remote Client Anchor='%s' (to be compared with <last> in NEXT session)",
+        fNextRemoteAnchor.c_str()
+      ));
+      PDEBUGPRINTFX(DBG_PROTO,(
+        "(Saved) Last Local Server Anchor='%s', (generated) Next Local Server Anchor='%s' (sent to client as <last>/<next> in <alert>)",
+        fLastLocalAnchor.c_str(),
+        fNextLocalAnchor.c_str()
+      ));
+    }
+    #endif
+    #ifdef SYSYNC_CLIENT
+    if (IS_CLIENT) {
+      // Client ok until here
+      PDEBUGPRINTFX(DBG_PROTO,(
+        "Saved Last Remote Server Anchor='%s', received <last> Remote Server Anchor='%s' (must match for normal sync)",
+        fLastRemoteAnchor.c_str(),
+        aLastRemoteAnchor
+      ));
+      PDEBUGPRINTFX(DBG_PROTO,(
+        "Received <next> Remote Server Anchor='%s' (to be compared with <last> in NEXT session)",
+        fNextRemoteAnchor.c_str()
+      ));
     }
-    // Server ok until here
-    PDEBUGPRINTFX(DBG_PROTO,(
-      "Saved Last Remote Client Anchor='%s', received <last> Remote Client Anchor='%s' (must match for normal sync)",
-      fLastRemoteAnchor.c_str(),
-      aLastRemoteAnchor
-    ));
-    PDEBUGPRINTFX(DBG_PROTO,(
-      "Received <next> Remote Client Anchor='%s' (to be compared with <last> in NEXT session)",
-      fNextRemoteAnchor.c_str()
-    ));
-    PDEBUGPRINTFX(DBG_PROTO,(
-      "(Saved) Last Local Server Anchor='%s', (generated) Next Local Server Anchor='%s' (sent to client as <last>/<next> in <alert>)",
-      fLastLocalAnchor.c_str(),
-      fNextLocalAnchor.c_str()
-    ));
-    #else
-    // Client ok until here
-    PDEBUGPRINTFX(DBG_PROTO,(
-      "Saved Last Remote Server Anchor='%s', received <last> Remote Server Anchor='%s' (must match for normal sync)",
-      fLastRemoteAnchor.c_str(),
-      aLastRemoteAnchor
-    ));
-    PDEBUGPRINTFX(DBG_PROTO,(
-      "Received <next> Remote Server Anchor='%s' (to be compared with <last> in NEXT session)",
-      fNextRemoteAnchor.c_str()
-    ));
     #endif
     PDEBUGPRINTFX(DBG_PROTO,(
       "(Saved) fResumeAlertCode = %hd (valid for >DS 1.2 only)",
@@ -2321,29 +2326,31 @@ TAlertCommand *TLocalEngineDS::engProcessSyncAlert(
     // Now check for resume
     // - default to what was actually alerted
     uInt16 effectiveAlertCode=aAlertCode;
-    #ifndef SYSYNC_CLIENT
-    // - check if resuming server session
-    fResuming=false;
-    if (aAlertCode==225) {
-      if (fSessionP->getSyncMLVersion()<syncml_vers_1_2) {
-        aStatusCommand.setStatusCode(406);
-        ADDDEBUGITEM(aStatusCommand,"Resume not supported in SyncML prior to 1.2");
-        PDEBUGPRINTFX(DBG_ERROR,("Resume not supported in SyncML prior to 1.2"));
-        return NULL;
-      }
-      // Resume requested
-      if (fResumeAlertCode==0 || !dsResumeSupportedInDB()) {
-        // cannot resume, suggest a normal sync (in case anchors do not match, this will become a 508 below)
-        aStatusCommand.setStatusCode(509); // cannot resume, override
-        effectiveAlertCode=200; // suggest normal sync
-        ADDDEBUGITEM(aStatusCommand,"Cannot resume, suggesting a normal sync");
-        PDEBUGPRINTFX(DBG_ERROR,("Cannot resume, suggesting a normal sync"));
-      }
-      else {
-        // we can resume, use the saved alert code
-        effectiveAlertCode=fResumeAlertCode;
-        PDEBUGPRINTFX(DBG_HOT,("Alerted to resume previous session, Switching to alert Code = %hd",fResumeAlertCode));
-        fResuming=true;
+    #ifdef SYSYNC_SERVER
+    if (IS_SERVER) {
+      // - check if resuming server session
+      fResuming=false;
+      if (aAlertCode==225) {
+        if (fSessionP->getSyncMLVersion()<syncml_vers_1_2) {
+          aStatusCommand.setStatusCode(406);
+          ADDDEBUGITEM(aStatusCommand,"Resume not supported in SyncML prior to 1.2");
+          PDEBUGPRINTFX(DBG_ERROR,("Resume not supported in SyncML prior to 1.2"));
+          return NULL;
+        }
+        // Resume requested
+        if (fResumeAlertCode==0 || !dsResumeSupportedInDB()) {
+          // cannot resume, suggest a normal sync (in case anchors do not match, this will become a 508 below)
+          aStatusCommand.setStatusCode(509); // cannot resume, override
+          effectiveAlertCode=200; // suggest normal sync
+          ADDDEBUGITEM(aStatusCommand,"Cannot resume, suggesting a normal sync");
+          PDEBUGPRINTFX(DBG_ERROR,("Cannot resume, suggesting a normal sync"));
+        }
+        else {
+          // we can resume, use the saved alert code
+          effectiveAlertCode=fResumeAlertCode;
+          PDEBUGPRINTFX(DBG_HOT,("Alerted to resume previous session, Switching to alert Code = %hd",fResumeAlertCode));
+          fResuming=true;
+        }
       }
     }
     #endif
@@ -2356,30 +2363,30 @@ TAlertCommand *TLocalEngineDS::engProcessSyncAlert(
       //       changes to two-way, as it might be that we have sent the server
       //       a two-way alert even if we want fromserver due to compatibility with
       //       servers that cannot do fromserver.
-      #ifndef SYSYNC_CLIENT
-      // - Server always obeys what client requests (that is, if alertscript does not modify it)
-      sta = setSyncModeFromAlertCode(effectiveAlertCode,false); // as server
-      #else
-      // - for client, check that server can't switch to a client writing mode
-      //   (we had a case when mobical did that for a user and erased all his data)
-      TSyncModes prevMode = fSyncMode; // remember previous mode
-      sta = setSyncModeFromAlertCode(effectiveAlertCode,true); // as client
-      if (prevMode==smo_fromclient && fSyncMode!=smo_fromclient) {
-        // server tries to switch to a mode that could be writing data to the client
-        // - forbidden
-        sta=403;
-        aStatusCommand.setStatusCode(syncmlError(sta));
-        ADDDEBUGITEM(aStatusCommand,"Server may not write to client");
-        PDEBUGPRINTFX(DBG_ERROR,("From-Client only: Server may not alert mode that writes client data (%hd) - blocked",effectiveAlertCode));
-        // - also abort sync of this datastore without chance to resume, as this problem might
-        //   originate from a resume attempt, which the server
-        //   tried to convert to a normal or slow sync. With cancelling the resume here, we make sure
-        //   next sync will start over and sending the desired (one-way) sync mode again.
-        engAbortDataStoreSync(sta, false, false); // remote problem, not resumable
-      }
-      else
-      #endif
-      {
+      if (IS_SERVER) {
+        // - Server always obeys what client requests (that is, if alertscript does not modify it)
+        sta = setSyncModeFromAlertCode(effectiveAlertCode,false); // as server
+      } // server
+      else {
+        // - for client, check that server can't switch to a client writing mode
+        //   (we had a case when mobical did that for a user and erased all his data)
+        TSyncModes prevMode = fSyncMode; // remember previous mode
+        sta = setSyncModeFromAlertCode(effectiveAlertCode,true); // as client
+        if (prevMode==smo_fromclient && fSyncMode!=smo_fromclient) {
+          // server tries to switch to a mode that could be writing data to the client
+          // - forbidden
+          sta=403;
+          aStatusCommand.setStatusCode(syncmlError(sta));
+          ADDDEBUGITEM(aStatusCommand,"Server may not write to client");
+          PDEBUGPRINTFX(DBG_ERROR,("From-Client only: Server may not alert mode that writes client data (%hd) - blocked",effectiveAlertCode));
+          // - also abort sync of this datastore without chance to resume, as this problem might
+          //   originate from a resume attempt, which the server
+          //   tried to convert to a normal or slow sync. With cancelling the resume here, we make sure
+          //   next sync will start over and sending the desired (one-way) sync mode again.
+          engAbortDataStoreSync(sta, false, false); // remote problem, not resumable
+        }
+      } // client
+      if (!isAborted()) {
         if (sta!=LOCERR_OK) {
           // Sync type not supported
           // - go back to idle
@@ -2393,11 +2400,12 @@ TAlertCommand *TLocalEngineDS::engProcessSyncAlert(
     if (sta==LOCERR_OK) {
       // Sync type supported
       // - set new state to alerted
-      #ifdef SYSYNC_CLIENT
-      changeState(dssta_clientalerted,true); // force it
-      #else
-      changeState(dssta_serveralerted,true); // force it
-      #endif
+      if (IS_CLIENT) {
+             changeState(dssta_clientalerted,true); // force it
+      }
+      else {
+             changeState(dssta_serveralerted,true); // force it
+      }
       // - datastore state is now dss_alerted
       PDEBUGPRINTFX(DBG_HOT,(
         "Alerted (code=%hd) for %s%s %s%s%s ",
@@ -2424,10 +2432,10 @@ TAlertCommand *TLocalEngineDS::engProcessSyncAlert(
       if (
         (
           (
-            (!fLastRemoteAnchor.empty() && 
+            (!fLastRemoteAnchor.empty() &&
                ( (fLastRemoteAnchor==aLastRemoteAnchor)
                 #ifdef SYSYNC_CLIENT
-                || (fSessionP->fLenientMode)
+                || (fSessionP->fLenientMode && IS_CLIENT)
                 #endif
               )
             ) || // either anchors must match (or lenient mode for client)...
@@ -2437,18 +2445,20 @@ TAlertCommand *TLocalEngineDS::engProcessSyncAlert(
         )
         || fSlowSync // if slow sync is requested by the remote anyway, we don't need to be in sync anyway, so just go on
       ) {
-       if (fLastRemoteAnchor!=aLastRemoteAnchor && fSessionP->fLenientMode) {
+       if (!(fLastRemoteAnchor==aLastRemoteAnchor) && fSessionP->fLenientMode) {
                PDEBUGPRINTFX(DBG_ERROR,("Warning - remote anchor mismatch but tolerated in lenient mode"));
         }
         // sync state ok or Slow sync requested anyway:
-        #ifndef SYSYNC_CLIENT
-        // we can generate Alert with same code as sent
-        // %%% Note: this is not entirely clear, as SCTS sends
-        //     corresponding SERVER ALERTED code back.
-        //     Specs suggest that we send the code back unmodified
-        uInt16 alertCode = getSyncStateAlertCode(fServerAlerted);
-        alertcmdP = new TAlertCommand(fSessionP,this,alertCode);
-        fAlertCode=alertCode; // save it for reference in scripts and for suspend/resume
+        #ifdef SYSYNC_SERVER
+        if (IS_SERVER) {
+          // we can generate Alert with same code as sent
+          // %%% Note: this is not entirely clear, as SCTS sends
+          //     corresponding SERVER ALERTED code back.
+          //     Specs suggest that we send the code back unmodified
+          uInt16 alertCode = getSyncStateAlertCode(fServerAlerted);
+          alertcmdP = new TAlertCommand(fSessionP,this,alertCode);
+          fAlertCode=alertCode; // save it for reference in scripts and for suspend/resume
+        }
         #endif
       }
       else {
@@ -2464,84 +2474,89 @@ TAlertCommand *TLocalEngineDS::engProcessSyncAlert(
         // NOTE: if client detected slow-sync not before here, status 508 alone
         //       (without another Alert 201 sent to the server) is sufficient for
         //       server to switch to slow sync.
-        #ifndef SYSYNC_CLIENT
-        // generate Alert for Slow sync
-        alertcmdP = new TAlertCommand(fSessionP,this,alertCode);
-        #endif
+        if (IS_SERVER) {
+          // generate Alert for Slow sync
+          alertcmdP = new TAlertCommand(fSessionP,this,alertCode);
+        }
       }
       // Now we are alerted for a sync
       // - reset item counters
       fItemsSent = 0;
       fItemsReceived = 0;
-      #ifndef SYSYNC_CLIENT
-      // Server case
-      // - show info
-      PDEBUGPRINTFX(DBG_HOT,(
-        "ALERTED from client for %s%s%s Sync",
-        fResuming ? "resumed " : "",
-        fSlowSync ? "slow" : "normal",
-        fFirstTimeSync ? " first time" : ""
-      ));
-      // server: add Item with Anchors and URIs
-      SmlItemPtr_t itemP = newItem();
-      // - anchors
-      itemP->meta=newMetaAnchor(fNextLocalAnchor.c_str(),fLastLocalAnchor.c_str());
-      // - MaxObjSize here again to make SCTS happy
-      if (
-        (fSessionP->getRootConfig()->fLocalMaxObjSize>0) &&
-        (fSessionP->getSyncMLVersion()>=syncml_vers_1_1)
-      ) {
-        // SyncML 1.1 has object size and we need to put it here for SCTS
-        smlPCDataToMetInfP(itemP->meta)->maxobjsize=newPCDataLong(
-          fSessionP->getRootConfig()->fLocalMaxObjSize
+      #ifdef SYSYNC_SERVER
+      if (IS_SERVER) {
+        // Server case
+        // - show info
+        PDEBUGPRINTFX(DBG_HOT,(
+          "ALERTED from client for %s%s%s Sync",
+          fResuming ? "resumed " : "",
+          fSlowSync ? "slow" : "normal",
+          fFirstTimeSync ? " first time" : ""
+        ));
+        // server: add Item with Anchors and URIs
+        SmlItemPtr_t itemP = newItem();
+        // - anchors
+        itemP->meta=newMetaAnchor(fNextLocalAnchor.c_str(),fLastLocalAnchor.c_str());
+        // - MaxObjSize here again to make SCTS happy
+        if (
+          (fSessionP->getRootConfig()->fLocalMaxObjSize>0) &&
+          (fSessionP->getSyncMLVersion()>=syncml_vers_1_1)
+        ) {
+          // SyncML 1.1 has object size and we need to put it here for SCTS
+          smlPCDataToMetInfP(itemP->meta)->maxobjsize=newPCDataLong(
+            fSessionP->getRootConfig()->fLocalMaxObjSize
+          );
+        }
+        // - URIs (reversed from what was received in Alert)
+        itemP->source=newLocation(aTargetURI); // use unprocessed form as sent by remote
+        itemP->target=newLocation(aSourceURI);
+        // - add to alert command
+        alertcmdP->addItem(itemP);
+        // - set new state, alert now answered
+        changeState(dssta_serveransweredalert,true); // force it
+      } // server case
+      #endif // SYSYNC_SERVER
+      #ifdef SYSYNC_CLIENT
+      if (IS_CLIENT) {
+        // Client case
+        // - now sync mode is stable (late switch to slowsync has now occurred if any)
+        changeState(dssta_syncmodestable,true);
+        // - show info
+        PDEBUGPRINTFX(DBG_HOT,(
+          "ALERTED from server for %s%s%s Sync",
+          fResuming ? "resumed " : "",
+          fSlowSync ? "slow" : "normal",
+          fFirstTimeSync ? " first time" : ""
+        ));
+        #ifdef PROGRESS_EVENTS
+        // - progress event
+        OBJ_PROGRESS_EVENT(
+          fSessionP->getSyncAppBase(),
+          pev_alerted,
+          fDSConfigP,
+          fSlowSync ? (fFirstTimeSync ? 2 : 1) : 0,
+          fResuming ? 1 : 0,
+          fSyncMode
         );
-      }
-      // - URIs (reversed from what was received in Alert)
-      itemP->source=newLocation(aTargetURI); // use unprocessed form as sent by remote
-      itemP->target=newLocation(aSourceURI);
-      // - add to alert command
-      alertcmdP->addItem(itemP);
-      // - set new state, alert now answered
-      changeState(dssta_serveransweredalert,true); // force it
-      #else
-      // Client case
-      // - now sync mode is stable (late switch to slowsync has now occurred if any)
-      changeState(dssta_syncmodestable,true);
-      // - show info
-      PDEBUGPRINTFX(DBG_HOT,(
-        "ALERTED from server for %s%s%s Sync",
-        fResuming ? "resumed " : "",
-        fSlowSync ? "slow" : "normal",
-        fFirstTimeSync ? " first time" : ""
-      ));
-      #ifdef PROGRESS_EVENTS
-      // - progress event
-      OBJ_PROGRESS_EVENT(
-        fSessionP->getSyncAppBase(),
-        pev_alerted,
-        fDSConfigP,
-        fSlowSync ? (fFirstTimeSync ? 2 : 1) : 0,
-        fResuming ? 1 : 0,
-        fSyncMode
-      );
-      #endif // PROGRESS_EVENTS
-      //%%% To make client-side filtering work, determining send/receive types must be done
-       //    before loading the sync set.
-      //               Therefore these two init steps are now in the new engInitForClientSync() routine, which is now called
-      //    in syncclient.cpp immediately before starting to generate sync commands.
-      //    (Alternatively, engInitForSyncOps() could be placed here before switching to dssta_dataaccessstarted.
-      //    Tried that, works, but has the disadvantage that in case server sends devInf after answering alerts,
-      //    type resolution would fail or be forced to blind flight)
-      /*
-      // - prepare engine for sync (determining types)
-      // - let local datastore (derived DB-specific class) prepare for sync
-      sta = changeState(dssta_dataaccessstarted);
-      if (sta==LOCERR_OK && isStarted(false)) {
-        // already started now, change state
-        sta = changeState(dssta_syncsetready);
-      }
-      */
-      #endif // client Case
+        #endif // PROGRESS_EVENTS
+        //%%% To make client-side filtering work, determining send/receive types must be done
+        //    before loading the sync set.
+        //             Therefore these two init steps are now in the new engInitForClientSync() routine, which is now called
+        //    in syncclient.cpp immediately before starting to generate sync commands.
+        //    (Alternatively, engInitForSyncOps() could be placed here before switching to dssta_dataaccessstarted.
+        //    Tried that, works, but has the disadvantage that in case server sends devInf after answering alerts,
+        //    type resolution would fail or be forced to blind flight)
+        /*
+        // - prepare engine for sync (determining types)
+        // - let local datastore (derived DB-specific class) prepare for sync
+        sta = changeState(dssta_dataaccessstarted);
+        if (sta==LOCERR_OK && isStarted(false)) {
+          // already started now, change state
+          sta = changeState(dssta_syncsetready);
+        }
+        */
+      } // client Case
+      #endif // SYSYNC_CLIENT
     }
     // clear partial item if we definitely know we are not resuming
     if (!fResuming) {
@@ -2557,9 +2572,9 @@ TAlertCommand *TLocalEngineDS::engProcessSyncAlert(
     // save name how remote adresses local database
     // (for sending same URI back in own Sync)
     fRemoteViewOfLocalURI = aTargetURI; // save it
-    #ifndef SYSYNC_CLIENT
-    fRemoteDBPath = aSourceURI;
-    #endif
+    if (IS_SERVER) {
+           fRemoteDBPath = aSourceURI;
+    }
     if (sta!=LOCERR_OK) {
       // no alert command
       if (alertcmdP) delete alertcmdP;
@@ -2582,26 +2597,27 @@ TAlertCommand *TLocalEngineDS::engProcessSyncAlert(
 bool TLocalEngineDS::engHandleAlertStatus(TSyError aStatusCode)
 {
   bool handled=false;
-  #ifdef SYSYNC_CLIENT
-  // for client, make sure we have just sent the alert
-  if (!testState(dssta_clientsentalert,true)) return false; // cannot switch if server not alerted
-  // anyway, we have seen the status
-  changeState(dssta_clientalertstatused,true); // force it
-  #else
-  // for server, check if client did combined init&sync
-  if (fLocalDSState>=dssta_syncmodestable) {
-    // must be combined init&sync
-    if (aStatusCode!=200) {
-      // everything except ok is not allowed here
-      PDEBUGPRINTFX(DBG_ERROR,("In combined init&sync, Alert status must be ok (but is %hd)",aStatusCode));
-      dsAbortDatastoreSync(400,false); // remote problem
+  if (IS_CLIENT) {
+    // for client, make sure we have just sent the alert
+    if (!testState(dssta_clientsentalert,true)) return false; // cannot switch if server not alerted
+    // anyway, we have seen the status
+    changeState(dssta_clientalertstatused,true); // force it
+       }
+  else {
+    // for server, check if client did combined init&sync
+    if (fLocalDSState>=dssta_syncmodestable) {
+      // must be combined init&sync
+      if (aStatusCode!=200) {
+        // everything except ok is not allowed here
+        PDEBUGPRINTFX(DBG_ERROR,("In combined init&sync, Alert status must be ok (but is %hd)",aStatusCode));
+        dsAbortDatastoreSync(400,false); // remote problem
+      }
+      // aborted or not, status is handled
+      return true;
     }
-    // aborted or not, status is handled
-    return true;
-  }
-  // normal case with separate init: we need to have answered the alert here
-  if (!testState(dssta_serveransweredalert,true)) return false; // cannot switch if server not alerted
-  #endif
+    // normal case with separate init: we need to have answered the alert here
+    if (!testState(dssta_serveransweredalert,true)) return false; // cannot switch if server not alerted
+  } // server case
   // now check status code
   if (aStatusCode==508) {
     // remote party needs slow sync
@@ -2618,31 +2634,27 @@ bool TLocalEngineDS::engHandleAlertStatus(TSyError aStatusCode)
   else if (aStatusCode==200) {
     handled=true;
   }
-  #ifdef SYSYNC_CLIENT
-  // check for resume override by server
-  if (!handled && fResuming) {
-    // we have requested resume
-    if (aStatusCode==509) {
-      // resume not accepted by server, but overridden by another sync type
-      fResuming=false;
-      PDEBUGPRINTFX(DBG_ERROR,("engHandleAlertStatus: Server rejected Resume"));
-      handled=true;
+  if (IS_CLIENT) {
+    // check for resume override by server
+    if (!handled && fResuming) {
+      // we have requested resume
+      if (aStatusCode==509) {
+        // resume not accepted by server, but overridden by another sync type
+        fResuming=false;
+        PDEBUGPRINTFX(DBG_ERROR,("engHandleAlertStatus: Server rejected Resume"));
+        handled=true;
+      }
     }
   }
-  #else
-  // if we have handled it here, sync mode is now stable
-  if (handled) {
-    // if we get that far, sync mode for server is now stable AND we can receive cached maps
-    changeState(dssta_syncmodestable,true); // force it, sync mode is now stable, no further changes are possible
+  else {
+    // if we have handled it here, sync mode is now stable
+    if (handled) {
+      // if we get that far, sync mode for server is now stable AND we can receive cached maps
+      changeState(dssta_syncmodestable,true); // force it, sync mode is now stable, no further changes are possible
+    }
   }
-  #endif
   // no other status codes are supported at the datastore level
   if (!handled && aStatusCode>=400) {
-    /** @deprecated no longer needed because we are never dssta_idle here
-    #ifdef SYSYNC_CLIENT
-    fState=dss_alerted; // normally, we are still dss_idle here. But we want an explicit abort, so pretend we were alerted
-    #endif
-    */
     engAbortDataStoreSync(aStatusCode, false); // remote problem
     handled=true;
   }
@@ -2721,12 +2733,12 @@ localstatus TLocalEngineDS::engInitForSyncOps(
         LocalReceiveFromRemoteTypeP = LocalSendToRemoteTypeP;
       }
       else {
-       // no specific "blind" preference, use my own normally preferred types 
+       // no specific "blind" preference, use my own normally preferred types
              LocalSendToRemoteTypeP = getPreferredTxItemType(); // send in preferred tx type of local datastore
              LocalReceiveFromRemoteTypeP = getPreferredRxItemType(); // receive in preferred rx type of local datastore
       }
                        // same type on both end (as only local type exists)
-      RemoteReceiveFromLocalTypeP = LocalSendToRemoteTypeP; // same on both end       
+      RemoteReceiveFromLocalTypeP = LocalSendToRemoteTypeP; // same on both end
       RemoteSendToLocalTypeP = LocalReceiveFromRemoteTypeP; // same on both end (as only local type exists)
       // create "remote" datastore with matching properties to local one
       PDEBUGPRINTFX(DBG_ERROR,("Warning: No DevInf for remote datastore, running blind sync attempt"));
@@ -2872,24 +2884,27 @@ bool TLocalEngineDS::engGenerateSyncCommands(
   PDEBUGBLOCKFMT(("SyncGen","Now generating sync commands","datastore=%s",getName()));
   bool finished=false;
   #ifdef SYSYNC_CLIENT
-  finished = logicGenerateSyncCommandsAsClient(aNextMessageCommands, aInterruptedCommandP, aLocalIDPrefix);
-  #else
-  finished = logicGenerateSyncCommandsAsServer(aNextMessageCommands, aInterruptedCommandP, aLocalIDPrefix);
+  if (IS_CLIENT)
+         finished = logicGenerateSyncCommandsAsClient(aNextMessageCommands, aInterruptedCommandP, aLocalIDPrefix);
+  #endif
+  #ifdef SYSYNC_SERVER
+  if (IS_SERVER)
+         finished = logicGenerateSyncCommandsAsServer(aNextMessageCommands, aInterruptedCommandP, aLocalIDPrefix);
   #endif
   // change state when finished
   if (finished) {
     changeState(dssta_syncgendone,true);
-    #ifdef SYSYNC_CLIENT
-    // from client only skips to clientmapssent without any server communication
-    // (except if we are in old synthesis-compatible mode which runs from-client-only
-    // with empty sync-from-server and map phases.
-    if (getSyncMode()==smo_fromclient && !fSessionP->fCompleteFromClientOnly) {
-      // data access ends with all sync commands generated in from-client-only
-      PDEBUGPRINTFX(DBG_PROTO,("From-Client-Only sync: skipping directly to end of map phase now"));
-      changeState(dssta_dataaccessdone,true);
-      changeState(dssta_clientmapssent,true);
+    if (IS_CLIENT) {
+      // from client only skips to clientmapssent without any server communication
+      // (except if we are in old synthesis-compatible mode which runs from-client-only
+      // with empty sync-from-server and map phases.
+      if (getSyncMode()==smo_fromclient && !fSessionP->fCompleteFromClientOnly) {
+        // data access ends with all sync commands generated in from-client-only
+        PDEBUGPRINTFX(DBG_PROTO,("From-Client-Only sync: skipping directly to end of map phase now"));
+        changeState(dssta_dataaccessdone,true);
+        changeState(dssta_clientmapssent,true);
+      }
     }
-    #endif
   }
   PDEBUGPRINTFX(DBG_DATA,(
     "engGenerateSyncCommands ended, state='%s', sync generation %sdone",
@@ -2933,7 +2948,7 @@ bool TLocalEngineDS::engHandleSyncOpStatus(TStatusCommand *aStatusCmdP,TSyncOpCo
   // just need to look at the first item's target and source
   const char *localID = aSyncOpCmdP->getSourceLocalID();
   const char *remoteID = aSyncOpCmdP->getTargetRemoteID();
-  #ifndef SYSYNC_CLIENT
+  #ifdef SYSYNC_SERVER
   string realLocID;
   #endif
   if (localID) {
@@ -2944,11 +2959,13 @@ bool TLocalEngineDS::engHandleSyncOpStatus(TStatusCommand *aStatusCmdP,TSyncOpCo
       localID = fAsSubDatastoreOf->removeSubDSPrefix(localID,this);
     }
     #endif
-    #ifndef SYSYNC_CLIENT
-    // for server only: convert to internal representation
-    realLocID=localID;
-    obtainRealLocalID(realLocID);
-    localID=realLocID.c_str();
+    #ifdef SYSYNC_SERVER
+    if (IS_SERVER) {
+      // for server only: convert to internal representation
+      realLocID=localID;
+      obtainRealLocalID(realLocID);
+      localID=realLocID.c_str();
+    }
     #endif
   }
   // handle special cases for Add/Replace/Delete
@@ -2967,9 +2984,7 @@ bool TLocalEngineDS::engHandleSyncOpStatus(TStatusCommand *aStatusCmdP,TSyncOpCo
       else if (
         statuscode==418 &&
         (isResuming()
-        #ifdef SYSYNC_CLIENT
-        || isSlowSync()
-        #endif
+        || (isSlowSync() && IS_CLIENT)
         )
       ) {
         // "Already exists"/418 is acceptable...
@@ -2999,8 +3014,8 @@ bool TLocalEngineDS::engHandleSyncOpStatus(TStatusCommand *aStatusCmdP,TSyncOpCo
     // case sop_copy: break;
     case sop_wants_replace:
     case sop_replace:
-      #ifndef SYSYNC_CLIENT
-      if (statuscode==404 || statuscode==410) {
+      #ifdef SYSYNC_SERVER
+      if (IS_SERVER && (statuscode==404 || statuscode==410)) {
         // obviously, remote item that we wanted to change does not exist any more.
         // Instead of aborting the session we'll just remove the map item for that
         // server item, such that it will be re-added in the next sync session
@@ -3028,7 +3043,7 @@ bool TLocalEngineDS::engHandleSyncOpStatus(TStatusCommand *aStatusCmdP,TSyncOpCo
         dsConfirmItemOp(sop_replace,localID,remoteID,true); // ok as replace
       }
       #ifdef SYSYNC_CLIENT
-      else if (isSlowSync() && statuscode==418) {
+      else if (IS_CLIENT && (isSlowSync() && statuscode==418)) {
         // "Already exists"/418 is acceptable as client in slow sync because some
         // servers use it instead of 200/419 for slow sync match
         PDEBUGPRINTFX(DBG_ERROR,("Warning: received 418 for for replace during slow sync - treat it as ok (200), but don't count as update"));
@@ -3559,14 +3574,14 @@ SmlDevInfDatastorePtr_t TLocalEngineDS::newDevInfDatastore(bool aAsServer, bool
   //   (this is to allow /dsname/foldername with clients that expect the
   //   devInf to contain exactly the same full path as name, like newer Nokias)
   string dotname;
-  #ifndef SYSYNC_CLIENT
-  if (testState(dssta_serveralerted,false) && fSessionP->fDSPathInDevInf) {
+  #ifdef SYSYNC_SERVER
+  if (IS_SERVER && testState(dssta_serveralerted,false) && fSessionP->fDSPathInDevInf) {
     // server and already alerted - use datastore spec as sent from remote, minus CGI, as relative spec
     dotname = URI_RELPREFIX;
     dotname += fSessionP->SessionRelativeURI(fRemoteViewOfLocalURI.c_str());
     if (!fSessionP->fDSCgiInDevInf) {
       // remove CGI
-      int n=dotname.find("?");
+      string::size_type n=dotname.find("?");
       if (n!=string::npos)
         dotname.resize(n); // remove CGI
     }
@@ -3621,8 +3636,8 @@ SmlDevInfDatastorePtr_t TLocalEngineDS::newDevInfDatastore(bool aAsServer, bool
   // - SyncML DS 1.2 filters
   datastoreP->filterrx=NULL;
   datastoreP->filtercap=NULL;
-  #if defined(OBJECT_FILTERING) && !defined(SYSYNC_CLIENT)
-  if (fDSConfigP->fDS12FilterSupport && fSessionP->getSyncMLVersion()>=syncml_vers_1_2) {
+  #ifdef OBJECT_FILTERING
+  if (IS_SERVER && fDSConfigP->fDS12FilterSupport && fSessionP->getSyncMLVersion()>=syncml_vers_1_2) {
     // Show Filter info in 1.2 devInf if this is not a client
     // - FilterRx constant
     datastoreP->filterrx = SML_NEW(SmlDevInfXmitList_t);
@@ -3649,7 +3664,7 @@ SmlDevInfDatastorePtr_t TLocalEngineDS::newDevInfDatastore(bool aAsServer, bool
       datastoreP->filtercap->data->propname=filterprops;
     }
   }
-  #endif
+  #endif // OBJECT_FILTERING
   // - Sync capabilities of this datastore
   datastoreP->synccap=newDevInfSyncCap(getSyncCapMask());
   // return it
@@ -3709,15 +3724,17 @@ bool TLocalEngineDS::engProcessSyncCmd(
     // all alert and alert status must be done by now, sync mode must be stable
     CONSOLEPRINTF(("- Starting Sync with Datastore '%s', %s sync",fRemoteViewOfLocalURI.c_str(),fSlowSync ? "slow" : "normal"));
     startingNow = true; // initiating start now
-    #ifndef SYSYNC_CLIENT
-    // - let local datastore (derived DB-specific class) prepare for sync
-    localstatus sta = changeState(dssta_dataaccessstarted);
-    if (sta!=LOCERR_OK) {
-      // abort session (old comment: %%% aborting datastore only does not work, will loop, why? %%%)
-      aStatusCommand.setStatusCode(syncmlError(sta));
-      PDEBUGPRINTFX(DBG_ERROR,("TLocalEngineDS::engProcessSyncCmd: could not change state to dsssta_dataaccessstarted -> abort"));
-      engAbortDataStoreSync(sta,true); // local problem
-      return false;
+    #ifdef SYSYNC_SERVER
+    if (IS_SERVER) {
+      // - let local datastore (derived DB-specific class) prepare for sync
+      localstatus sta = changeState(dssta_dataaccessstarted);
+      if (sta!=LOCERR_OK) {
+        // abort session (old comment: %%% aborting datastore only does not work, will loop, why? %%%)
+        aStatusCommand.setStatusCode(syncmlError(sta));
+        PDEBUGPRINTFX(DBG_ERROR,("TLocalEngineDS::engProcessSyncCmd: could not change state to dsssta_dataaccessstarted -> abort"));
+        engAbortDataStoreSync(sta,true); // local problem
+        return false;
+      }
     }
     #endif
   }
@@ -3727,19 +3744,20 @@ bool TLocalEngineDS::engProcessSyncCmd(
     // queue <sync> command if datastore is not yet started already
     if (engIsStarted(!startingNow)) { // wait only if start was already initiated
       // - is now initialized
-      #ifndef SYSYNC_CLIENT
-      // - for server, make the sync set ready now (as engine is now started)
-      changeState(dssta_syncsetready,true); // force it
-      #else
-      // - for client, we need at least dssta_syncgendone (sync set has been ready long ago, we've already sent changes to server!)
-      if (!testState(dssta_syncgendone)) {
-        // bad sequence of commands (<sync> from server too early!)
-        aStatusCommand.setStatusCode(400);
-        PDEBUGPRINTFX(DBG_ERROR,("TLocalEngineDS::engProcessSyncCmd: client received SYNC before sending SYNC complete"));
-        engAbortDataStoreSync(400,false,false); // remote problem, not resumable
-        return false;
+      if (IS_SERVER) {
+        // - for server, make the sync set ready now (as engine is now started)
+        changeState(dssta_syncsetready,true); // force it
+      }
+      else {
+        // - for client, we need at least dssta_syncgendone (sync set has been ready long ago, we've already sent changes to server!)
+        if (!testState(dssta_syncgendone)) {
+          // bad sequence of commands (<sync> from server too early!)
+          aStatusCommand.setStatusCode(400);
+          PDEBUGPRINTFX(DBG_ERROR,("TLocalEngineDS::engProcessSyncCmd: client received SYNC before sending SYNC complete"));
+          engAbortDataStoreSync(400,false,false); // remote problem, not resumable
+          return false;
+        }
       }
-      #endif
       PDEBUGPRINTFX(DBG_HOT,(
         "- Started %s Sync (first <sync> command)",
         fSlowSync ? "slow" : "normal"
@@ -3786,7 +3804,7 @@ bool TLocalEngineDS::engProcessSyncCmdEnd(bool &aQueueForLater)
 } // TLocalEngineDS::engProcessSyncCmdEnd
 
 
-#ifndef SYSYNC_CLIENT
+#ifdef SYSYNC_SERVER
 
 // server case: called whenever outgoing Message of Sync Package starts
 void TLocalEngineDS::engServerStartOfSyncMessage(void)
@@ -3845,26 +3863,29 @@ void TLocalEngineDS::engEndOfSyncFromRemote(bool aEndOfAllSyncCommands)
   if (testState(dssta_syncsetready)) {
     if (aEndOfAllSyncCommands) {
       // we are at end of sync-data-from-remote for THIS datastore
-      #ifdef SYSYNC_CLIENT
-      // - we are done with <Sync> from server, that is, data access is done now
-      changeState(dssta_dataaccessdone,true); // force it
-      #else
-      // - server has seen all client modifications now
-      // Note: in case of the simulated-empty-sync-hack in action, we
-      //       allow that we are already in server_sync_gen_started and
-      //       won't try to force down to dssta_serverseenclientmods
-      if (!fSessionP->fFakeFinalFlag || getDSState()<dssta_serverseenclientmods) {
-        // under normal circumstances, wee need dssta_serverseenclientmods here
-        changeState(dssta_serverseenclientmods,true); // force it
+      if (IS_CLIENT) {
+        // - we are done with <Sync> from server, that is, data access is done now
+        changeState(dssta_dataaccessdone,true); // force it
       }
       else {
-        // hack exception
-        PDEBUGPRINTFX(DBG_ERROR,("Warning: simulated </final> active - allowing state>server_seen_client_mods"));
+        // - server has seen all client modifications now
+        // Note: in case of the simulated-empty-sync-hack in action, we
+        //       allow that we are already in server_sync_gen_started and
+        //       won't try to force down to dssta_serverseenclientmods
+        if (!fSessionP->fFakeFinalFlag || getDSState()<dssta_serverseenclientmods) {
+          // under normal circumstances, wee need dssta_serverseenclientmods here
+          changeState(dssta_serverseenclientmods,true); // force it
+        }
+        else {
+          // hack exception
+          PDEBUGPRINTFX(DBG_ERROR,("Warning: simulated </final> active - allowing state>server_seen_client_mods"));
+        }
       }
-      #endif
     }
-    #ifndef SYSYNC_CLIENT
-    engServerStartOfSyncMessage();
+    #ifdef SYSYNC_SERVER
+    if (IS_SERVER) {
+           engServerStartOfSyncMessage();
+    }
     #endif
     // now do final things
     if (testState(dssta_dataaccessdone,true)) {
@@ -4091,19 +4112,21 @@ void TLocalEngineDS::DoLogSubstitutions(string &aLog,bool aPlaintext)
   StringSubst(aLog,"%leI",fLocalItemsError,4);
   // %leI remotely not accepted Items (got error from remote, local will resend them later)
   StringSubst(aLog,"%reI",fRemoteItemsError,4);
-  #ifndef SYSYNC_CLIENT
-  // %smI Slowsync matched Items
-  StringSubst(aLog,"%smI",fSlowSyncMatches,4);
-  // %scI Server won Conflicts
-  StringSubst(aLog,"%scI",fConflictsServerWins,4);
-  // %ccI Client won Conflicts
-  StringSubst(aLog,"%ccI",fConflictsClientWins,4);
-  // %dcI Conflicts with duplications
-  StringSubst(aLog,"%dcI",fConflictsDuplicated,4);
-  // %tiB total incoming bytes
-  StringSubst(aLog,"%tiB",fSessionP->getIncomingBytes(),4);
-  // %toB total outgoing bytes
-  StringSubst(aLog,"%toB",fSessionP->getOutgoingBytes(),4);
+  #ifdef SYSYNC_SERVER
+  if (IS_SERVER) {
+    // %smI Slowsync matched Items
+    StringSubst(aLog,"%smI",fSlowSyncMatches,4);
+    // %scI Server won Conflicts
+    StringSubst(aLog,"%scI",fConflictsServerWins,4);
+    // %ccI Client won Conflicts
+    StringSubst(aLog,"%ccI",fConflictsClientWins,4);
+    // %dcI Conflicts with duplications
+    StringSubst(aLog,"%dcI",fConflictsDuplicated,4);
+    // %tiB total incoming bytes
+    StringSubst(aLog,"%tiB",fSessionP->getIncomingBytes(),4);
+    // %toB total outgoing bytes
+    StringSubst(aLog,"%toB",fSessionP->getOutgoingBytes(),4);
+  }
   #endif
   // %niB net incoming data bytes for this datastore
   StringSubst(aLog,"%diB",fIncomingDataBytes,4);
@@ -4268,20 +4291,23 @@ void TLocalEngineDS::showStatistics(void)
   else {
     // successful: show statistics on console
     CONSOLEPRINTF(("  =================================================="));
-    #ifndef SYSYNC_CLIENT
-    CONSOLEPRINTF(("                               on Server   on Client"));
-    #else
-    CONSOLEPRINTF(("                               on Client   on Server"));
-    #endif
+    if (IS_SERVER) {
+           CONSOLEPRINTF(("                               on Server   on Client"));
+    }
+    else {
+           CONSOLEPRINTF(("                               on Client   on Server"));
+    }
     CONSOLEPRINTF(("  Added:                       %9ld   %9ld",fLocalItemsAdded,fRemoteItemsAdded));
     CONSOLEPRINTF(("  Deleted:                     %9ld   %9ld",fLocalItemsDeleted,fRemoteItemsDeleted));
     CONSOLEPRINTF(("  Updated:                     %9ld   %9ld",fLocalItemsUpdated,fRemoteItemsUpdated));
     CONSOLEPRINTF(("  Rejected with error:         %9ld   %9ld",fLocalItemsError,fRemoteItemsError));
-    #ifndef SYSYNC_CLIENT
-    CONSOLEPRINTF(("  SlowSync Matches:            %9ld",fSlowSyncMatches));
-    CONSOLEPRINTF(("  Server won Conflicts:        %9ld",fConflictsServerWins));
-    CONSOLEPRINTF(("  Client won Conflicts:        %9ld",fConflictsClientWins));
-    CONSOLEPRINTF(("  Conflicts with Duplication:  %9ld",fConflictsDuplicated));
+    #ifdef SYSYNC_SERVER
+    if (IS_SERVER) {
+      CONSOLEPRINTF(("  SlowSync Matches:            %9ld",fSlowSyncMatches));
+      CONSOLEPRINTF(("  Server won Conflicts:        %9ld",fConflictsServerWins));
+      CONSOLEPRINTF(("  Client won Conflicts:        %9ld",fConflictsClientWins));
+      CONSOLEPRINTF(("  Conflicts with Duplication:  %9ld",fConflictsDuplicated));
+    }
     #endif
   }
   CONSOLEPRINTF((""));
@@ -4289,9 +4315,11 @@ void TLocalEngineDS::showStatistics(void)
   OBJ_PROGRESS_EVENT(fSessionP->getSyncAppBase(),pev_dsstats_l,fDSConfigP,fLocalItemsAdded,fLocalItemsUpdated,fLocalItemsDeleted);
   OBJ_PROGRESS_EVENT(fSessionP->getSyncAppBase(),pev_dsstats_r,fDSConfigP,fRemoteItemsAdded,fRemoteItemsUpdated,fRemoteItemsDeleted);
   OBJ_PROGRESS_EVENT(fSessionP->getSyncAppBase(),pev_dsstats_e,fDSConfigP,fLocalItemsError,fRemoteItemsError,0);
-  #ifndef SYSYNC_CLIENT
-  OBJ_PROGRESS_EVENT(fSessionP->getSyncAppBase(),pev_dsstats_s,fDSConfigP,fSlowSyncMatches,0,0);
-  OBJ_PROGRESS_EVENT(fSessionP->getSyncAppBase(),pev_dsstats_c,fDSConfigP,fConflictsServerWins,fConflictsClientWins,fConflictsDuplicated);
+  #ifdef SYSYNC_SERVER
+  if (IS_SERVER) {
+    OBJ_PROGRESS_EVENT(fSessionP->getSyncAppBase(),pev_dsstats_s,fDSConfigP,fSlowSyncMatches,0,0);
+    OBJ_PROGRESS_EVENT(fSessionP->getSyncAppBase(),pev_dsstats_c,fDSConfigP,fConflictsServerWins,fConflictsClientWins,fConflictsDuplicated);
+  }
   #endif
   // NOTE: pev_dsstats_d should remain the last log data event sent (as it terminates collecting data in some GUIs)
   OBJ_PROGRESS_EVENT(fSessionP->getSyncAppBase(),pev_dsstats_d,fDSConfigP,fOutgoingDataBytes,fIncomingDataBytes,fRemoteItemsError);
@@ -4305,20 +4333,23 @@ void TLocalEngineDS::showStatistics(void)
   if (PDEBUGTEST(DBG_HOT)) {
     string stats =
              "==================================================\n";
-    #ifndef SYSYNC_CLIENT
-    stats += "                             on Server   on Client\n";
-    #else
-    stats += "                             on Client   on Server\n";
-    #endif
+    if (IS_SERVER) {
+           stats += "                             on Server   on Client\n";
+    }
+    else {
+           stats += "                             on Client   on Server\n";
+    }
     StringObjAppendPrintf(stats,"Added:                       %9ld   %9ld\n",(long)fLocalItemsAdded,(long)fRemoteItemsAdded);
     StringObjAppendPrintf(stats,"Deleted:                     %9ld   %9ld\n",(long)fLocalItemsDeleted,(long)fRemoteItemsDeleted);
     StringObjAppendPrintf(stats,"Updated:                     %9ld   %9ld\n",(long)fLocalItemsUpdated,(long)fRemoteItemsUpdated);
     StringObjAppendPrintf(stats,"Rejected with error:         %9ld   %9ld\n\n",(long)fLocalItemsError,(long)fRemoteItemsError);
-    #ifndef SYSYNC_CLIENT
-    StringObjAppendPrintf(stats,"SlowSync Matches:            %9ld\n",fSlowSyncMatches);
-    StringObjAppendPrintf(stats,"Server won Conflicts:        %9ld\n",fConflictsServerWins);
-    StringObjAppendPrintf(stats,"Client won Conflicts:        %9ld\n",fConflictsClientWins);
-    StringObjAppendPrintf(stats,"Conflicts with Duplication:  %9ld\n\n",fConflictsDuplicated);
+    #ifdef SYSYNC_SERVER
+    if (IS_SERVER) {
+      StringObjAppendPrintf(stats,"SlowSync Matches:            %9ld\n",(long)fSlowSyncMatches);
+      StringObjAppendPrintf(stats,"Server won Conflicts:        %9ld\n",(long)fConflictsServerWins);
+      StringObjAppendPrintf(stats,"Client won Conflicts:        %9ld\n",(long)fConflictsClientWins);
+      StringObjAppendPrintf(stats,"Conflicts with Duplication:  %9ld\n\n",(long)fConflictsDuplicated);
+    }
     #endif
     StringObjAppendPrintf(stats,"Content Data Bytes sent:     %9ld\n",(long)fOutgoingDataBytes);
     StringObjAppendPrintf(stats,"Content Data Bytes received: %9ld\n\n",(long)fIncomingDataBytes);
@@ -4349,20 +4380,23 @@ TSyncOpCommand *TLocalEngineDS::newSyncOpCommand(
   // make sure item does not have stuff it is not allowed to have
   // %%% SCTS does not like SourceURI in Replace and Delete commands sent to Client
   // there are the only ones allowed to carry a GUID
-  #ifndef SYSYNC_CLIENT
-  // Server: commands only have remote IDs, except add which only has target ID
-  if (syncop==sop_add || syncop==sop_wants_add)
-    aSyncItemP->clearRemoteID(); // no remote ID
-  else {
-    if (!fDSConfigP->fAlwaysSendLocalID) {
-      // only if localID may not be included in all syncops
-      aSyncItemP->clearLocalID(); // no local ID
+  if (IS_SERVER) {
+       #ifdef SYSYNC_SERVER
+    // Server: commands only have remote IDs, except add which only has target ID
+    if (syncop==sop_add || syncop==sop_wants_add)
+      aSyncItemP->clearRemoteID(); // no remote ID
+    else {
+      if (!fDSConfigP->fAlwaysSendLocalID) {
+        // only if localID may not be included in all syncops
+        aSyncItemP->clearLocalID(); // no local ID
+      }
     }
+    #endif
+  }
+  else {
+    // Client: all commands only have local IDs
+    aSyncItemP->clearRemoteID(); // no remote ID
   }
-  #else
-  // Client: all commands only have local IDs
-  aSyncItemP->clearRemoteID(); // no remote ID
-  #endif
   #ifdef SYSYNC_TARGET_OPTIONS
   // init item generation variables
   fItemSizeLimit=fSizeLimit;
@@ -4627,10 +4661,15 @@ bool TLocalEngineDS::engProcessRemoteItem(
 )
 {
   #ifdef SYSYNC_CLIENT
-  return engProcessRemoteItemAsClient(syncitemP,aStatusCommand); // status, must be set to correct status code (ok / error)
-  #else
-  return engProcessRemoteItemAsServer(syncitemP,aStatusCommand); // status, must be set to correct status code (ok / error)
+  if (IS_CLIENT)
+         return engProcessRemoteItemAsClient(syncitemP,aStatusCommand); // status, must be set to correct status code (ok / error)
+  #endif
+  #ifdef SYSYNC_SERVER
+  if (IS_SERVER)
+         return engProcessRemoteItemAsServer(syncitemP,aStatusCommand); // status, must be set to correct status code (ok / error)
   #endif
+  // neither
+  return false;
 } // TLocalEngineDS::engProcessRemoteItem
 
 
@@ -4837,7 +4876,7 @@ bool TLocalEngineDS::engProcessSyncOpItem(
 } // TLocalEngineDS::engProcessSyncOpItem
 
 
-#ifndef SYSYNC_CLIENT
+#ifdef SYSYNC_SERVER
 
 
 // Server Case
@@ -5779,9 +5818,11 @@ void TLocalEngineDS::engRequestEnded(void)
   }
 } // TLocalEngineDS::engRequestEnded
 
+#endif // SYSYNC_SERVER
 
 
-#else
+
+#ifdef SYSYNC_CLIENT
 
 // Client Case
 // ===========
@@ -6177,7 +6218,7 @@ bool TLocalEngineDS::isAddFromLastSession(cAppCharP aRemoteID)
 // - called to generate Map items
 //   Returns true if now finished for this datastore
 //   also sets fState to dss_done when finished
-bool TLocalEngineDS::engGenerateMapItems(TMapCommand *aMapCommandP)
+bool TLocalEngineDS::engGenerateMapItems(TMapCommand *aMapCommandP, cAppCharP aLocalIDPrefix)
 {
   #ifdef USE_SML_EVALUATION
   sInt32 leavefree = fSessionP->getNotUsableBufferBytes();
@@ -6193,6 +6234,10 @@ bool TLocalEngineDS::engGenerateMapItems(TMapCommand *aMapCommandP)
     // add item
     string locID = (*pos).first;
     dsFinalizeLocalID(locID); // make sure we have the permanent version in case datastore implementation did deliver temp IDs
+    // add local ID prefix, if any
+    if (aLocalIDPrefix && *aLocalIDPrefix)
+      locID.insert(0,aLocalIDPrefix);
+    // add it to map command
     aMapCommandP->addMapItem(locID.c_str(),(*pos).second.c_str());
     // check if we could send this command
     #ifdef USE_SML_EVALUATION
@@ -6250,7 +6295,9 @@ bool TLocalEngineDS::engGenerateMapItems(TMapCommand *aMapCommandP)
 } // TLocalEngineDS::engGenerateMapItems
 
 
-#endif // SYSYNC_CLIENT
+#endif // SYSYNC_SERVER
+
+
 
 // - called to mark an already generated (but probably not sent or not yet statused) item
 //   as "to-be-resumed", by localID or remoteID (latter only in server case).
@@ -6265,9 +6312,9 @@ void TLocalEngineDS::engMarkItemForResume(cAppCharP aLocalID, cAppCharP aRemoteI
     aLocalID = fAsSubDatastoreOf->removeSubDSPrefix(aLocalID, this);
   }
   #endif
-  #ifndef SYSYNC_CLIENT
+  #ifdef SYSYNC_SERVER
   // Now mark for resume
-  if (aLocalID && *aLocalID) {
+  if (IS_SERVER && aLocalID && *aLocalID) {
     // localID can be a translated localid at this point (for adds), so check for it
     string localid=aLocalID;
     obtainRealLocalID(localid);
@@ -6298,8 +6345,8 @@ void TLocalEngineDS::engMarkItemForResend(cAppCharP aLocalID, cAppCharP aRemoteI
   // maxobjsize restrictions.
   fRemoteItemsError++;
   // now mark for resend
-  #ifndef SYSYNC_CLIENT
-  if (aLocalID && *aLocalID) {
+  #ifdef SYSYNC_SERVER
+  if (IS_SERVER && aLocalID && *aLocalID) {
     // localID can be a translated localid at this point (for adds), so check for it
     string localid=aLocalID;
     obtainRealLocalID(localid);
index c652423..305e09c 100755 (executable)
@@ -140,10 +140,10 @@ public:
   bool fReportUpdates;     // if set(normal case), updates of server items will be sent to client (can be set to false for example for emails)
   bool fResendFailing;     // if set, items that receive a failure status from the remote will be resent in the next session (if DS 1.2 suspend marks supported by the DB)
   bool fDeleteWins;        // if set, in a replace/delete conflict the delete wins (also see DELETEWINS())
-  #ifndef SYSYNC_CLIENT
+  #ifdef SYSYNC_SERVER
   bool fTryUpdateDeleted;  // if set, in a client update with server delete conflict, server tries to update the already deleted item (in case it is just invisible)
   bool fAlwaysSendLocalID; // always send localID to clients (which gives them opportunity to remap IDs on Replace)
-  #endif
+  #endif // SYSYNC_SERVER
   uInt32 fMaxItemsPerMessage; // if >0, limits the number of items sent per SyncML message (useful in case of slow datastores where collecting data might exceed client timeout)
   #ifdef OBJECT_FILTERING
   // filtering
@@ -295,11 +295,7 @@ class TLocalEngineDS: public TSyncDataStore
   friend class TSyncOpCommand;
   friend class TMultiFieldItemType;
   friend class TTextProfileHandler;
-  #ifndef SYSYNC_CLIENT
-  friend class TSyncServer;
-  #else
-  friend class TSyncClient;
-  #endif
+  friend class TSyncAgent;
   #ifdef SUPERDATASTORES
   friend class TSuperDataStore;
   #endif
@@ -349,9 +345,10 @@ protected:
   // - other state info
   bool fFirstTimeSync;          ///< set to true if this is the first sync
   // - item ID lists (maps)
-  #ifndef SYSYNC_CLIENT
+  #ifdef SYSYNC_SERVER
   TStringToStringMap fTempGUIDMap;      ///< container for temp GUID to real GUID mapping
-  #else
+  #endif
+  #ifdef SYSYNC_CLIENT
   TStringToStringMap fPendingAddMaps;   ///< container for map items to be sent to server: fPendingAddMaps[localid]=remoteid; Note: might contain temporary localIDs that must be converted to final ones before using in <map> or saving with dsFinalizeLocalID()
   TStringToStringMap fUnconfirmedMaps;  ///< container for map items already sent to server, but not yet confirmed: fUnconfirmedMaps[localid]=remoteid;
   TStringToStringMap fLastSessionMaps;  ///< container for map items already confirmed, but still needed for duplicate checking:: fLastSessionMaps[localid]=remoteid;
@@ -469,7 +466,7 @@ protected:
   sInt32 fRemoteItemsDeleted;
   sInt32 fRemoteItemsError; // items that had a remote error (and will be resent later)
   /// }@
-  #ifndef SYSYNC_CLIENT
+  #ifdef SYSYNC_SERVER
   // @{ conflicts
   sInt32 fConflictsServerWins;
   sInt32 fConflictsClientWins;
@@ -493,16 +490,12 @@ private:
   // - local
   string fLocalDBPath;              ///< client, entire path to the local database, which might include subpaths/CGI to subselect records in the local DB
   // - remote
-  string fRemoteDBPath;             ///< client, path of remote DB, including all CGI params etc.
   string fDBUser;                   ///< client, DB layer user name
   string fDBPassword;               ///< client, DB layer password
   string fRemoteRecordFilterQuery;  ///< client, record level filter query
   bool fRemoteFilterInclusive;      ///< client, inclusive filter flag
-  #else
-  #ifndef MINIMAL_CODE
-  string fRemoteDBPath;             ///< server, path of remote DB, for documentary purposes
-  #endif
-  #endif
+  #endif // SYSYNC_CLIENT
+  string fRemoteDBPath;             ///< server and client, path of remote DB, for documentary purposes
   /// remote datastore involved, valid after processSyncCmdAsServer()
   TRemoteDataStore *fRemoteDatastoreP;
   /// Remote view if local URI
@@ -590,10 +583,8 @@ public:
   TSyncItemType *getLocalReceiveType(void) { return fLocalReceiveFromRemoteTypeP; };    ///< type used by local to receive from remote
   TSyncItemType *getRemoteSendType(void) { return fRemoteSendToLocalTypeP; };           ///< type used by remote to send to local
   TSyncItemType *getRemoteReceiveType(void) { return fRemoteReceiveFromLocalTypeP; };   ///< type used by remote to receive from local
-  #if defined(SYSYNC_CLIENT) || !defined(MINIMAL_CODE)
   /// get remote DB path
   cAppCharP getRemoteDBPath(void) { return fRemoteDBPath.c_str(); };
-  #endif
   #ifdef SYSYNC_CLIENT
   /// get local DB path
   cAppCharP getLocalDBPath(void) { return fLocalDBPath.c_str(); };
@@ -727,20 +718,17 @@ public:
   /// @param[in] aNotYetInMapPackage set if we are still in sync-from-server package
   /// @note usually, client starts sending maps while still receiving syncops from server
   void engClientStartOfMapMessage(bool aNotYetInMapPackage);
-  /// called to generate Map items
-  /// @note Returns true if now finished for this datastore
-  /// @note also sets fState to dss_done when finished
-  SUPERDS_VIRTUAL bool generateMapItems(TMapCommand *aMapCommandP);
   /// Client only: returns number of unsent map items
   SUPERDS_VIRTUAL sInt32 numUnsentMaps(void);
-  #else
+  #endif // SYSYNC_CLIENT
+  #ifdef SYSYNC_SERVER
   /// server only: called whenever we should start a sync command for all alerted datastores
   /// if not already started
   void engServerStartOfSyncMessage(void);
   /// called to process map commands from client to server
   /// @note aLocalID or aRemoteID can be NULL - which signifies deletion of a map entry
   SUPERDS_VIRTUAL localstatus engProcessMap(cAppCharP aRemoteID, cAppCharP aLocalID);
-  #endif
+  #endif // SYSYNC_SERVER
   /// check is datastore is completely started.
   /// @param[in] aWait if set, call will not return until either started state is reached
   ///   or cannot be reached within the maximally allowed request processing time left.
@@ -782,7 +770,8 @@ public:
     TSyncItem *aSyncItemP, ///< the item to be processed
     TStatusCommand &aStatusCommand ///< status, must be set to correct status code (ok / error)
   );
-  #else
+  #endif
+  #ifdef SYSYNC_SERVER
   bool engProcessRemoteItemAsServer(
     TSyncItem *aSyncItemP, ///< the item to be processed
     TStatusCommand &aStatusCommand ///< status, must be set to correct status code (ok / error)
@@ -797,10 +786,10 @@ public:
   /// called to mark maps confirmed, that is, we have received ok status for them
   #ifdef SYSYNC_CLIENT
   SUPERDS_VIRTUAL void engMarkMapConfirmed(cAppCharP aLocalID, cAppCharP aRemoteID);
-  /// Client only: called to generate Map items
-  /// - Returns true if now finished for this datastore
-  /// - also sets fState to dss_done when finished
-  SUPERDS_VIRTUAL bool engGenerateMapItems(TMapCommand *aMapCommandP);
+  /// called to generate Map items
+  /// @note Returns true if now finished for this datastore
+  /// @note also sets fState to done when finished
+  SUPERDS_VIRTUAL bool engGenerateMapItems(TMapCommand *aMapCommandP, cAppCharP aLocalIDPrefix);
   /// Client only: Check if the remoteid was used by an add command not
   /// fully mapped&confirmed in the previous session
   bool isAddFromLastSession(cAppCharP aRemoteID);
@@ -879,7 +868,7 @@ public:
   #endif
   // get usage variant for a specified type usage
   virtual TTypeVariantDescriptor getVariantDescForType(TSyncItemType *aItemTypeP);
-  #ifndef SYSYNC_CLIENT
+  #ifdef SYSYNC_SERVER
   /// called at end of request processing in server (derived only by superdatastore)
   SUPERDS_VIRTUAL void engRequestEnded(void);
   /// end map operation (derived class might want to rollback)
@@ -938,7 +927,7 @@ public:
     const char *aRecordFilterQuery = NULL,
     bool aFilterInclusive = false
   );
-  #endif
+  #endif // SYSYNC_CLIENT
 protected:
   /// reset datastore to a re-usable, like new-created state.
   virtual void dsResetDataStore(void) {};
@@ -1001,7 +990,7 @@ protected:
 
   /// get conflict resolution strategy.
   virtual TConflictResolution getConflictStrategy(bool aForSlowSync, bool aForFirstTime=false);
-  #ifndef SYSYNC_CLIENT
+  #ifdef SYSYNC_SERVER
   /// called to check if conflicting replace command from server exists
   virtual TSyncItem *getConflictingItemByRemoteID(TSyncItem *syncitemP) = 0;
   /// called to check if content-matching item from server exists
@@ -1038,7 +1027,8 @@ protected:
     TSmlCommand * &aInterruptedCommandP,
     const char *aLocalIDPrefix=NULL
   ) = 0;
-  #else
+  #endif
+  #ifdef SYSYNC_SERVER
   /// server: called to generate sync sub-commands to be sent to client
   /// Returns true if now finished for this datastore
   /// also sets fState to dss_syncdone(server)/dss_syncready(client) when finished
@@ -1104,14 +1094,14 @@ private:
   TRuleMatchTypesContainer fRuleMatchItemTypes; // contains rule match item types
   #endif
 protected:
-  #ifndef SYSYNC_CLIENT
+  #ifdef SYSYNC_SERVER
   /// for sending GUIDs (Add command), generate temp GUID which conforms to maxguidsize of remote datastore if needed
   void adjustLocalIDforSize(string &aLocalID, sInt32 maxguidsize, sInt32 prefixsize);
   /// for received GUIDs (Map command), obtain real GUID (might be temp GUID due to maxguidsize restrictions)
   void obtainRealLocalID(string &aLocalID);
   /// helper to force a conflict (i.e. have a particular item in the sync set)
   TSyncItem *forceConflict(TSyncItem *aSyncItemP);
-  #endif
+  #endif // SYSYNC_SERVER
   /// helper to save resume state either at end of request or explicitly at reception of a "suspend"
   SUPERDS_VIRTUAL localstatus engSaveSuspendState(bool aAnyway);
   /// Returns true if type information is sufficient to create items to be sent to remote party
index 8590ea5..3cafba5 100644 (file)
@@ -21,6 +21,8 @@
 #include "mimedirprofile.h"
 #include "mimediritemtype.h"
 
+#include "syncagent.h"
+
 
 using namespace sysync;
 
@@ -384,7 +386,6 @@ bool TMIMEProfileConfig::localStartElement(const char *aElementName, const char
       val = getAttr(aAttributes,"value");
       // - get mode
       TEnumMode mode=enm_translate; // default to translate
-      sInt16 m;
       const char *mod=getAttr(aAttributes,"mode");
       if (mod) {
         if (!StrToEnum(EnumModeNames,numEnumModes,m,mod))
@@ -509,7 +510,6 @@ bool TMIMEProfileConfig::localStartElement(const char *aElementName, const char
         return fail("'subprofile' must have 'name' attribute");
       // - get profile mode
       TProfileModes mode = profm_custom;
-      sInt16 m;
       cAppCharP pfmode = getAttr(aAttributes,"mode");
       if (pfmode) {
         if (!StrToEnum(ProfileModeNames,numProfileModes,m,pfmode))
@@ -668,7 +668,7 @@ bool TMIMEProfileConfig::localStartElement(const char *aElementName, const char
 
 #ifndef NO_REMOTE_RULES
 // resolve remote rule dependencies in profile (recursive)
-static void resolveRemoteRuleDeps(TProfileDefinition *aProfileP, TSessionConfig *aSessionConfigP)
+static void resolveRemoteRuleDeps(TProfileDefinition *aProfileP, TAgentConfig *aSessionConfigP)
 {
   TProfileDefinition *profileP = aProfileP;
   while (profileP) {
@@ -717,7 +717,7 @@ void TMIMEProfileConfig::localResolve(bool aLastPass)
     // recursively resolve remote rule dependencies in all properties
     resolveRemoteRuleDeps(
       fRootProfileP,
-      static_cast<TSessionConfig *>(static_cast<TRootConfig *>(getRootElement())->fAgentConfigP)
+      static_cast<TAgentConfig *>(static_cast<TRootConfig *>(getRootElement())->fAgentConfigP)
     );
     #endif
   }
@@ -1390,7 +1390,7 @@ bool TMimeDirProfileHandler::fieldToMIMEString(
         // remote cannot handle UTC or time is floating (eventually dateonly or duration)
         if (tsFldP->isFloating()) {
           // floating, show as-is
-          lineartime_t ts = tsFldP->getTimestampAs(TCTX_UNKNOWN);
+          ts = tsFldP->getTimestampAs(TCTX_UNKNOWN);
           if (ts==noLinearTime)
             aString.erase();
           else {
@@ -1999,13 +1999,24 @@ static void finalizeProperty(
   ssize_t n=0,llen=0;
   ssize_t lastlwsp=-1; // no linear white space found so far
   bool explf;
-  const char *firstunwritten=proptext; // none written yet
+  cAppCharP firstunwritten=proptext; // none written yet
   while (proptext && (c=*proptext)!=0) {
     // remember position of last lwsp (space or TAB)
     if (c==' ' || c==0x09) lastlwsp=n;
-    // next char
-    n++;
-    proptext++;
+    // next (UTF8) char
+    // Note: we prevent folding within UTF8 sequences as result string would become inconvertible e.g. into UTF16
+    uInt32 uc;
+    cAppCharP nP = UTF8toUCS4(proptext, uc);
+    if (uc!=0) {
+       // UTF-8 compliant byte (or byte sequence), skip as an entiety
+      n += nP-proptext;
+      proptext = nP;
+    }
+    else {
+       // Not UTF-8 compliant, simply one byte
+      n++;
+      proptext++;
+    }
     // check for optional break indicator
     if (c=='\b') {
       aString.append(firstunwritten,n-1); // copy what we have up to that '\b'
@@ -2195,7 +2206,7 @@ sInt16 TMimeDirProfileHandler::generateValue(
                   val.erase(); // ignore -> make value empty as empty values are never stored
                 else if (enumP->enummode==enm_prefix) {
                   // replace value prefix by text prefix
-                  size_t n=TCFG_SIZE(enumP->enumval);
+                  n=TCFG_SIZE(enumP->enumval);
                   val.replace(0,n,TCFG_CSTR(enumP->enumtext)); // replace val prefix by text prefix
                 }
                 else {
@@ -3099,10 +3110,10 @@ bool TMimeDirProfileHandler::MIMEStringToField(
         // combine mode
         if (!fldP->isEmpty()) {
           // not empty, append with separator
-          char s[2];
-          s[0]=aConvDefP->combineSep;
-          s[1]=0;
-          fldP->appendString(s);
+          char cs[2];
+          cs[0]=aConvDefP->combineSep;
+          cs[1]=0;
+          fldP->appendString(cs);
         }
         fldP->appendString(aText);
       }
@@ -3968,8 +3979,8 @@ bool TMimeDirProfileHandler::parseLevels(
   bool aRootLevel
 )
 {
-  char c;
-  const char *p,*propname;
+  appChar c;
+  cAppCharP p, propname;
   sInt32 n;
   sInt16 foundmandatory=0;
   const sInt16 maxreps = 50;
@@ -4064,7 +4075,7 @@ bool TMimeDirProfileHandler::parseLevels(
                 string s2;
                 string s = "END:";
                 s.append(subprofileP->levelName);
-                size_t n = s.size(); // size of lead-out
+                n = s.size(); // size of lead-out
                 cAppCharP e = strstr(p,s.c_str());
                 if (e==NULL) return false; // unterminated vTimeZone sublevel
                 s.assign(p,e-p); // everything between lead-in and lead-out
@@ -4266,7 +4277,6 @@ bool TMimeDirProfileHandler::parseLevels(
     // p is now end of parsed part
     // - skip rest up to EOLN (=any ctrl char)
     //   Note: we need to check if this is quoted-printable, otherwise we might NOT cancel soft breaks
-               char c;
     bool isqp = false;
     while ((c=*p)!=0) {
        if (isEndOfLineOrText(c)) break; // end of line or string
@@ -4288,7 +4298,7 @@ bool TMimeDirProfileHandler::parseLevels(
     // process delayed properties only after entire record is parsed (i.e. when we are at root level here)
     TDelayedParsingPropsList::iterator pos;
     for (pos=fDelayedProps.begin(); pos!=fDelayedProps.end(); pos++) {
-      const char *p = (*pos).start; // where to start parsing
+      p = (*pos).start; // where to start parsing
       PDEBUGPRINTFX(DBG_PARSE+DBG_EXOTIC,(
         "parseMimeDir: now parsing delayed property rank=%hd: %" FMT_LENGTH(".30") "s",
         (*pos).delaylevel,
index 7db0191..d180b6d 100755 (executable)
@@ -869,11 +869,10 @@ bool TMultiFieldItem::processFilter(bool aMakePass, const char *&aPos, const cha
     if (str=="LUID") {
       // this is SyncML-TAF Standard
       // it is also produced by DS 1.2 &LUID; pseudo-identifier
-      #ifdef SYSYNC_CLIENT
-      idfield.setAsString(getLocalID());
-      #else
-      idfield.setAsString(getRemoteID());
-      #endif
+      if (IS_CLIENT)
+             idfield.setAsString(getLocalID());
+      else
+             idfield.setAsString(getRemoteID());
       fldP=&idfield;
     }
     else if (str=="LOCALID") {
@@ -881,18 +880,18 @@ bool TMultiFieldItem::processFilter(bool aMakePass, const char *&aPos, const cha
       idfield.setAsString(getLocalID());
       fldP=&idfield;
     }
-    #ifndef SYSYNC_CLIENT
-    else if (str=="GUID") {
+    #ifdef SYSYNC_SERVER
+    else if (IS_SERVER && str=="GUID") {
       // this is a Synthesis extension, added for symmetry to LUID
       idfield.setAsString(getLocalID());
       fldP=&idfield;
     }
-    else if (str=="REMOTEID") {
+    else if (IS_SERVER && str=="REMOTEID") {
       // this is a Synthesis extension
       idfield.setAsString(getRemoteID());
       fldP=&idfield;
     }
-    #endif
+    #endif // SYSYNC_SERVER
     else {
       // must be a field
       if (fItemTypeP)
@@ -1045,7 +1044,7 @@ bool TMultiFieldItem::processFilter(bool aMakePass, const char *&aPos, const cha
 
 #endif
 
-#ifndef SYSYNC_CLIENT
+#ifdef SYSYNC_SERVER
 
 // compare function, returns 0 if equal, 1 if this > aItem, -1 if this < aItem
 sInt16 TMultiFieldItem::compareWith(
@@ -1169,11 +1168,11 @@ sInt16 TMultiFieldItem::standardCompareWith(
             PDEBUGPRINTFX(DBG_DATA+DBG_MATCH,("- not equal because fid=%hd not same in both items:",i));
             getField(i)->getAsString(ds);
             PDEBUGPRINTFX(DBG_DATA+DBG_MATCH+DBG_USERDATA,(
-              "- this item  : '%-0.1000s'",ds.c_str()
+              "- this item  : '%-.1000s'",ds.c_str()
             ));
             aItem.getField(i)->getAsString(ds);
             PDEBUGPRINTFX(DBG_DATA+DBG_MATCH+DBG_USERDATA,(
-              "- other item : '%-0.1000s'",ds.c_str()
+              "- other item : '%-.1000s'",ds.c_str()
             ));
             PDEBUGPRINTFX(DBG_DATA+DBG_MATCH,(
               "- thisItem.CompareWith(otherItem) = %hd",
@@ -1195,7 +1194,7 @@ sInt16 TMultiFieldItem::standardCompareWith(
             if (aDebugShow) {
               PDEBUGPRINTFX(DBG_DATA+DBG_MATCH,(
                 "- Cutoff detected, field considered equal, maxsize(thisitem)=%ld, maxsize(otheritem)=%ld",
-                s1,s2
+                (long)s1,(long)s2
               ));
             }
             #endif
@@ -1325,7 +1324,7 @@ bool TMultiFieldItem::checkItem(TLocalEngineDS *aDatastoreP)
 } // TMultiFieldItem::checkItem
 
 
-#ifndef SYSYNC_CLIENT
+#ifdef SYSYNC_SERVER
 
 // merge this item with specified item.
 // Notes:
@@ -1401,7 +1400,7 @@ void TMultiFieldItem::standardMergeWith(TMultiFieldItem &aItem, bool &aChangedTh
           string ds;
           getFieldRef(i).getAsString(ds);
           PDEBUGPRINTFX(DBG_DATA+DBG_CONFLICT+DBG_USERDATA,(
-            "- assigned value '%" FMT_LENGTH("0.40") "s' to winning (which had nothing assigned here)",
+            "- assigned value '%" FMT_LENGTH(".40") "s' to winning (which had nothing assigned here)",
             FMT_LENGTH_LIMITED(40,ds.c_str())
           ));
           #endif
@@ -1421,7 +1420,7 @@ void TMultiFieldItem::standardMergeWith(TMultiFieldItem &aItem, bool &aChangedTh
               string ds;
               winningField.getAsString(ds);
               PDEBUGPRINTFX(DBG_DATA+DBG_CONFLICT+DBG_USERDATA,(
-                "- copied value '%" FMT_LENGTH("0.40") "s' from loosing to empty winning",
+                "- copied value '%" FMT_LENGTH(".40") "s' from loosing to empty winning",
                 FMT_LENGTH_LIMITED(40,ds.c_str())
               ));
               #endif
@@ -1435,7 +1434,7 @@ void TMultiFieldItem::standardMergeWith(TMultiFieldItem &aItem, bool &aChangedTh
             winningField.getAsString(ds1);
             loosingField.getAsString(ds2);
             PDEBUGPRINTFX(DBG_DATA+DBG_CONFLICT+DBG_USERDATA,(
-              "- try merging winning value '%" FMT_LENGTH("0.40") "s' with loosing value '%" FMT_LENGTH("0.40") "s'",
+              "- try merging winning value '%" FMT_LENGTH(".40") "s' with loosing value '%" FMT_LENGTH(".40") "s'",
               FMT_LENGTH_LIMITED(40,ds1.c_str()),
               FMT_LENGTH_LIMITED(40,ds2.c_str())
             ));
@@ -1445,7 +1444,7 @@ void TMultiFieldItem::standardMergeWith(TMultiFieldItem &aItem, bool &aChangedTh
             #ifdef SYDEBUG
             winningField.getAsString(ds1);
             PDEBUGPRINTFX(DBG_DATA+DBG_CONFLICT+DBG_USERDATA,(
-              "  merged %sthing, winning value is '%" FMT_LENGTH("0.40") "s'",
+              "  merged %sthing, winning value is '%" FMT_LENGTH(".40") "s'",
               aChangedThis ? "some" : "no",
               FMT_LENGTH_LIMITED(40,ds1.c_str())
             ));
@@ -1470,7 +1469,7 @@ void TMultiFieldItem::standardMergeWith(TMultiFieldItem &aItem, bool &aChangedTh
         winningField.getAsString(wfv);
         loosingField.getAsString(lfv);
         PDEBUGPRINTFX(DBG_DATA+DBG_CONFLICT+DBG_USERDATA,(
-          "Winning and loosing Field '%s' not equal: '%" FMT_LENGTH("0.30") "s' <> '%" FMT_LENGTH("0.30") "s'",
+          "Winning and loosing Field '%s' not equal: '%" FMT_LENGTH(".30") "s' <> '%" FMT_LENGTH(".30") "s'",
           fFieldDefinitionsP->fFields[i].TCFG_CSTR(fieldname),
           FMT_LENGTH_LIMITED(30,wfv.c_str()),FMT_LENGTH_LIMITED(30,lfv.c_str())
         ));
@@ -1491,7 +1490,7 @@ void TMultiFieldItem::standardMergeWith(TMultiFieldItem &aItem, bool &aChangedTh
         string ds;
         winningField.getAsString(ds);
         PDEBUGPRINTFX(DBG_DATA+DBG_CONFLICT+DBG_USERDATA,(
-          "- updated fields such that both have same value '%" FMT_LENGTH("0.40") "s'",
+          "- updated fields such that both have same value '%" FMT_LENGTH(".40") "s'",
           FMT_LENGTH_LIMITED(40,ds.c_str())
         ));
         #endif
index 62e7945..2008c3c 100755 (executable)
@@ -311,7 +311,7 @@ public:
   virtual bool replaceDataFrom(TSyncItem &aItem, bool aAvailableOnly=false, bool aDetectCutoffs=false, bool aAssignedOnly=false, bool aTransferUnassigned=false);
   // check item before processing it
   virtual bool checkItem(TLocalEngineDS *aDatastoreP);
-  #ifndef SYSYNC_CLIENT
+  #ifdef SYSYNC_SERVER
   // merge this item with specified item.
   // Notes:
   // - specified item is treated as loosing item, this item is winning item
index c585d2b..2d583fd 100755 (executable)
@@ -51,7 +51,7 @@ void TMultiFieldTypeConfig::clear(void)
   fOutgoingScript.erase();
   fFilterInitScript.erase();
   fPostFetchFilterScript.erase();
-  #ifndef SYSYNC_CLIENT
+  #ifdef SYSYNC_SERVER
   fCompareScript.erase();
   fMergeScript.erase();
   #endif
@@ -104,7 +104,7 @@ public:
 
 
 
-  #ifndef SYSYNC_CLIENT
+  #ifdef SYSYNC_SERVER
 
   // void ECHOITEM(string syncop)
   // creates a duplicate of the processed item to be sent back to sender with the specified syncop
@@ -312,7 +312,7 @@ const TBuiltInFuncDef DataTypeFuncDefs[] = {
   { "SIZELIMIT", TMFTypeFuncs::func_Limit, fty_integer, 0, NULL },
   { "SETSIZELIMIT", TMFTypeFuncs::func_SetLimit, fty_none, 1, param_IntArg },
   #endif
-  #ifndef SYSYNC_CLIENT
+  #ifdef SYSYNC_SERVER
   { "ECHOITEM", TMFTypeFuncs::func_EchoItem, fty_none, 1, param_StrArg },
   { "CONFLICTSTRATEGY", TMFTypeFuncs::func_ConflictStrategy, fty_none, 1, param_StrArg },
   { "FORCECONFLICT", TMFTypeFuncs::func_ForceConflict, fty_none, 0, NULL },
@@ -394,7 +394,7 @@ bool TMultiFieldTypeConfig::localStartElement(const char *aElementName, const ch
     expectScript(fFilterInitScript,aLine,&DataTypeFuncTable);
   else if (strucmp(aElementName,"filterscript")==0)
     expectScript(fPostFetchFilterScript,aLine,&DataTypeFuncTable);
-  #ifndef SYSYNC_CLIENT
+  #ifdef SYSYNC_SERVER
   else if (strucmp(aElementName,"comparescript")==0)
     expectScript(fCompareScript,aLine,&DataTypeFuncTable);
   else if (strucmp(aElementName,"mergescript")==0)
@@ -431,7 +431,7 @@ void TMultiFieldTypeConfig::localResolve(bool aLastPass)
       TScriptContext::resolveScript(getSyncAppBase(),fFilterInitScript,sccP,fFieldListP);
       TScriptContext::resolveScript(getSyncAppBase(),fPostFetchFilterScript,sccP,fFieldListP);
       // - compare and merge scripts
-      #ifndef SYSYNC_CLIENT
+      #ifdef SYSYNC_SERVER
       TScriptContext::resolveScript(getSyncAppBase(),fCompareScript,sccP,fFieldListP);
       TScriptContext::resolveScript(getSyncAppBase(),fMergeScript,sccP,fFieldListP);
       #endif
@@ -572,7 +572,7 @@ void TMultiFieldItemType::initDataTypeUse(TLocalEngineDS *aDatastoreP, bool aFor
   TScriptContext::rebuildContext(cfgP->getSyncAppBase(),cfgP->fFilterInitScript,*ctxPP,fSessionP);
   TScriptContext::rebuildContext(cfgP->getSyncAppBase(),cfgP->fPostFetchFilterScript,*ctxPP,fSessionP);
   // - compare and merge scripts
-  #ifndef SYSYNC_CLIENT
+  #ifdef SYSYNC_SERVER
   TScriptContext::rebuildContext(cfgP->getSyncAppBase(),cfgP->fCompareScript,*ctxPP,fSessionP);
   TScriptContext::rebuildContext(cfgP->getSyncAppBase(),cfgP->fMergeScript,*ctxPP,fSessionP);
   #endif
@@ -688,7 +688,7 @@ bool TMultiFieldItemType::checkItem(TMultiFieldItem &aItem, TLocalEngineDS *aDat
 } // TMultiFieldItemType::checkItem
 
 
-#ifndef SYSYNC_CLIENT
+#ifdef SYSYNC_SERVER
 
 // compare two items
 sInt16 TMultiFieldItemType::compareItems(
@@ -796,7 +796,7 @@ void TMultiFieldItemType::mergeItems(
   #endif
 } // TMultiFieldItemType::mergeItems
 
-#endif // server only
+#endif // SYSYNC_SERVER
 
 
 // helper to create same-typed instance via base class
index f5c7d91..ed86862 100755 (executable)
 // includes
 #include "prefix_file.h"
 #include "sysync.h"
-#include "syncsession.h"
+#include "syncagent.h"
 #include "remotedatastore.h"
 
-#ifndef SYSYNC_CLIENT
-#include "syncserver.h"
-#endif
 
 using namespace sysync;
 
@@ -40,8 +37,10 @@ void TRemoteDataStore::init(void)
 void TRemoteDataStore::InternalResetDataStore(void)
 {
   // for server, get default GUID size (in case remote devInf does not send one)
-  #ifndef SYSYNC_CLIENT
-  fMaxGUIDSize = static_cast<TServerConfig *>(getSession()->getSessionConfig())->fMaxGUIDSizeSent;
+  #ifdef SYSYNC_SERVER
+  if (IS_SERVER) {
+         fMaxGUIDSize = static_cast<TAgentConfig *>(getSession()->getSessionConfig())->fMaxGUIDSizeSent;
+  }
   #endif
 } // TRemoteDataStore::InternalResetDataStore
 
index efd4887..2f4787b 100755 (executable)
@@ -27,7 +27,7 @@ namespace sysync {
 class TRemoteDataStore: public TSyncDataStore
 {
   typedef TSyncDataStore inherited;
-  friend class TSyncServer;
+  friend class TSyncAgent;
 private:
   void init(void); // internal init
   void InternalResetDataStore(void); // reset for re-use without re-creation
index 48a1855..4dbe01d 100755 (executable)
@@ -497,6 +497,23 @@ public:
   }; // func_DateOnly
 
 
+  // timestamp TIMEONLY(timestamp atime)
+  // returns a floating(!) time-only of the given timestamp
+  static void func_TimeOnly(TItemField *&aTermP, TScriptContext *aFuncContextP)
+  {
+    TTimestampField *tsP = static_cast<TTimestampField *>(aFuncContextP->getLocalVar(0));
+
+    // get timestamp as dateonly
+    timecontext_t tctx;
+    lineartime_t ts;
+    ts = tsP->getTimestampAs(TCTX_UNKNOWN | TCTX_TIMEONLY, &tctx);
+    // assign it to result (but do NOT pass in tctx, as it might contain a zone
+    // but we need it as floating to make dates comparable
+    static_cast<TTimestampField *>(aTermP)->setTimestampAndContext(ts,TCTX_TIMEONLY|TCTX_UNKNOWN);
+  }; // func_TimeOnly
+
+
+
   // integer ISDURATION(timestamp atime)
   // returns true if given timestamp is a duration value
   static void func_IsDuration(TItemField *&aTermP, TScriptContext *aFuncContextP)
@@ -522,7 +539,7 @@ public:
 
 
   // timestamp POINTINTIME(timestamp atime)
-  // returns the timestamp as a point in time (i.e. not duration)
+  // returns the timestamp as a point in time (i.e. not duration and not dateonly/timeonly)
   static void func_PointInTime(TItemField *&aTermP, TScriptContext *aFuncContextP)
   {
     TTimestampField *tsP = static_cast<TTimestampField *>(aFuncContextP->getLocalVar(0));
@@ -531,8 +548,8 @@ public:
     timecontext_t tctx;
     lineartime_t ts;
     ts = tsP->getTimestampAs(TCTX_UNKNOWN, &tctx);
-    // assign it to result with duration flag cleared
-    static_cast<TTimestampField *>(aTermP)->setTimestampAndContext(ts,tctx & (~TCTX_DURATION));
+    // assign it to result with duration and dateonly flag cleared
+    static_cast<TTimestampField *>(aTermP)->setTimestampAndContext(ts,tctx & (~(TCTX_DURATION+TCTX_DATEONLY+TCTX_TIMEONLY)));
   }; // func_PointInTime
 
 
@@ -2157,6 +2174,7 @@ const TBuiltInFuncDef BuiltInFuncDefs[] = {
   { "SETUSERTIMEZONE", TBuiltinStdFuncs::func_SetUserTimezone, fty_none, 1, param_oneVariant },
   { "ISDATEONLY", TBuiltinStdFuncs::func_IsDateOnly, fty_integer, 1, param_oneTimestamp },
   { "DATEONLY", TBuiltinStdFuncs::func_DateOnly, fty_timestamp, 1, param_oneTimestamp },
+  { "TIMEONLY", TBuiltinStdFuncs::func_TimeOnly, fty_timestamp, 1, param_oneTimestamp },
   { "ISDURATION", TBuiltinStdFuncs::func_IsDuration, fty_integer, 1, param_oneTimestamp },
   { "DURATION", TBuiltinStdFuncs::func_Duration, fty_timestamp, 1, param_oneTimestamp },
   { "POINTINTIME", TBuiltinStdFuncs::func_PointInTime, fty_timestamp, 1, param_oneTimestamp },
index 0aa19fc..14d438b 100755 (executable)
 
 /* public TStdLogicAgent members */
 
-#ifdef SYSYNC_CLIENT
-
-TStdLogicAgent::TStdLogicAgent(TSyncClientBase *aClientBaseP, const char *aSessionID) :
-  TSyncClient(aClientBaseP,aSessionID)
-{
-  // nop
-} // TStdLogicAgent::TStdLogicAgent
-
-#else
-
-TStdLogicAgent::TStdLogicAgent(TSyncAppBase *aAppBaseP, TSyncSessionHandle *aSessionHandleP, const char *aSessionID) :
-  TSyncServer(aAppBaseP, aSessionHandleP, aSessionID)
+TStdLogicAgent::TStdLogicAgent(TSyncAppBase *aAppBaseP, TSyncSessionHandle *aSessionHandleP, cAppCharP aSessionID) :
+  inherited(aAppBaseP, aSessionHandleP, aSessionID)
 {
-  // nop
-  InternalResetSession();
+       if (IS_SERVER) {
+               #ifdef SYSYNC_SERVER
+         InternalResetSession();
+    #endif
+  }
 } // TStdLogicAgent::TStdLogicAgent
 
-#endif
-
 
 // destructor
 TStdLogicAgent::~TStdLogicAgent()
index 80a21c3..9f21a93 100755 (executable)
 
 // includes
 #include "sysync.h"
-#ifdef SYSYNC_CLIENT
-#include "syncclient.h"
-#else
-#include "syncserver.h"
-#endif
+#include "syncagent.h"
 #include "localengineds.h"
 
 
@@ -32,33 +28,21 @@ namespace sysync {
 
 
 class TStdLogicAgent:
-  #ifdef SYSYNC_CLIENT
-  public TSyncClient
-  #else
-  public TSyncServer
-  #endif
+  public TSyncAgent
 {
-  #ifdef SYSYNC_CLIENT
-  typedef TSyncClient inherited;
-  #else
-  typedef TSyncServer inherited;
-  #endif
+  typedef TSyncAgent inherited;
 public:
-  #ifdef SYSYNC_CLIENT
-  TStdLogicAgent(TSyncClientBase *aClientBaseP, const char *aSessionID);
-  #else
-  TStdLogicAgent(TSyncAppBase *aAppBaseP, TSyncSessionHandle *aSessionHandleP, const char *aSessionID);
-  #endif
+  TStdLogicAgent(TSyncAppBase *aAppBaseP, TSyncSessionHandle *aSessionHandleP, cAppCharP aSessionID);
   virtual ~TStdLogicAgent();
   virtual void TerminateSession(void); // Terminate session, like destructor, but without actually destructing object itself
   virtual void ResetSession(void); // Resets session (but unlike TerminateSession, session might be re-used)
   void InternalResetSession(void); // static implementation for calling through virtual destructor and virtual ResetSession();
   // user authentication
   #ifndef SYSYNC_CLIENT
-  // - server should implement it, so we make it abstract here again (altough there is
+  // - server-only build should implement it, so we make it abstract here again (altough there is
   //   an implementation for simpleauth in session.
   virtual bool SessionLogin(const char *aUserName, const char *aAuthString, TAuthSecretTypes aAuthStringType, const char *aDeviceID) = 0;
-  #endif
+  #endif // not SYSYNC_CLIENT
 }; // TStdLogicAgent
 
 
index cbfafe2..df137e8 100755 (executable)
@@ -80,17 +80,21 @@ void TStdLogicDS::InternalResetDataStore(void)
   fInitializing=false;
   // no start init request yet
   fStartInit=false;
-  #if !defined(SYSYNC_CLIENT) || defined(CLIENT_USES_SERVER_DB)
-  // remove all items
-  TSyncItemPContainer::iterator pos;
-  for (pos=fItems.begin(); pos!=fItems.end(); ++pos) {
-    delete *pos;
+  if(HAS_SERVER_DB) {
+       #ifdef USES_SERVER_DB
+    // remove all items
+    TSyncItemPContainer::iterator pos;
+    for (pos=fItems.begin(); pos!=fItems.end(); ++pos) {
+      delete *pos;
+    }
+    fItems.clear(); // clear list
+    #endif
+  }
+  if (IS_SERVER) {
+       #ifdef SYSYNC_SERVER
+         fNumRefOnlyItems=0;
+    #endif
   }
-  fItems.clear(); // clear list
-  #endif
-  #ifndef SYSYNC_CLIENT
-  fNumRefOnlyItems=0;
-  #endif
 } // TStdLogicDS::InternalResetDataStore
 
 
@@ -150,21 +154,25 @@ localstatus TStdLogicDS::startDataWrite()
   if (!fWriteStarted) {
     sta=implStartDataWrite();
     fWriteStarted = sta==LOCERR_OK; // must be here to prevent recursion as startDataWrite might be called implicitly below
-    #if !defined(SYSYNC_CLIENT) || defined(CLIENT_USES_SERVER_DB)
-    // server-type DB needs post-processing to update map entries (client and server case)
-    TSyncItemPContainer::iterator pos;
-    if (sta==LOCERR_OK) {
-      // Now allow post-processing of all reported items
-      for (pos=fItems.begin(); pos!=fItems.end(); ++pos) {
-        localstatus sta2 = implReviewReadItem(**pos);
-        if (sta2!=LOCERR_OK) sta=sta2;
+    if (HAS_SERVER_DB) {
+       #ifdef USES_SERVER_DB
+      // server-type DB needs post-processing to update map entries (client and server case)
+      TSyncItemPContainer::iterator pos;
+      if (sta==LOCERR_OK) {
+        // Now allow post-processing of all reported items
+        for (pos=fItems.begin(); pos!=fItems.end(); ++pos) {
+          localstatus sta2 = implReviewReadItem(**pos);
+          if (sta2!=LOCERR_OK) sta=sta2;
+        }
       }
+      #endif
+    }
+    if (IS_CLIENT && HAS_SERVER_DB) {
+       #ifdef USES_SERVER_DB
+      /// @todo we don't need the items to remain that long at all - not even for CLIENT_USES_SERVER_DB case
+      fItems.clear(); // empty list
+      #endif
     }
-    #endif
-    #if defined(SYSYNC_CLIENT) && defined(CLIENT_USES_SERVER_DB)
-    /// @todo we don't need the items to remain that long at all - not even for CLIENT_USES_SERVER_DB case
-    fItems.clear(); // empty list
-    #endif // client using server DB
   }
   DEBUGPRINTFX(DBG_DATA,("startDataWrite called, status=%hd", sta));
   return sta;
@@ -207,12 +215,14 @@ bool TStdLogicDS::logicRetrieveItemByID(
 ///   or cannot be reached within the maximally allowed request processing time left.
 bool TStdLogicDS::isStarted(bool aWait)
 {
-  #ifndef SYSYNC_CLIENT
-  // only server has threaded datastores so far
-  if (aWait && fInitializing) {
-    localstatus sta = startDataAccessForServer();
-    if (sta!=LOCERR_OK) {
-      SYSYNC_THROW(TSyncException("startDataAccessForServer failed (when called from isStarted)", sta));
+       #ifdef SYSYNC_SERVER
+  if (IS_SERVER) {
+    // only server has threaded datastores so far
+    if (aWait && fInitializing) {
+      localstatus sta = startDataAccessForServer();
+      if (sta!=LOCERR_OK) {
+        SYSYNC_THROW(TSyncException("startDataAccessForServer failed (when called from isStarted)", sta));
+      }
     }
   }
   #endif
@@ -241,7 +251,7 @@ void TStdLogicDS::logicMarkItemForResend(cAppCharP aLocalID, cAppCharP aRemoteID
 
 
 
-#ifndef SYSYNC_CLIENT
+#ifdef SYSYNC_SERVER
 
 // Server case
 // ===========
@@ -351,7 +361,7 @@ localstatus TStdLogicDS::performStartSync(void)
     // end reading
     sta=implEndDataRead();
     // show items
-    PDEBUGPRINTFX(DBG_HOT,("%s: number of local items involved in %ssync = %ld",getName(), fSlowSync ? "slow " : "",fItems.size()));
+    PDEBUGPRINTFX(DBG_HOT,("%s: number of local items involved in %ssync = %lu",getName(), fSlowSync ? "slow " : "",(unsigned long)fItems.size()));
     CONSOLEPRINTF(("  %ld local items are new/changed/deleted for this sync",fItems.size()));
     if (PDEBUGTEST(DBG_DATA+DBG_DETAILS)) {
       PDEBUGBLOCKFMTCOLL(("SyncSet","Items involved in Sync","datastore=%s",getName()));
@@ -414,7 +424,7 @@ bool TStdLogicDS::threadedStartSync(void)
   // Note: ThreadMayChangeNow() has been posted already by startingThread()
   PDEBUGPRINTFX(DBG_HOT,("******* starting background thread for reading sync set..."));
   fStartSyncStatus.setStatusCode(200); // assume ok
-  if (!fStartSyncThread.launch(StartSyncThreadFunc,(uInt32)this)) { // pass datastoreP as param
+  if (!fStartSyncThread.launch(StartSyncThreadFunc,(uIntArch)this)) { // pass datastoreP as param
     // starting thread failed
     PDEBUGPRINTFX(DBG_ERROR,("******* Failed starting background thread for reading sync set"));
     return false;
@@ -440,7 +450,7 @@ bool TStdLogicDS::shouldExitStartSync(void)
   return fMultiThread && fStartSyncThread.terminationRequested();
 } // TStdLogicDS::shouldExitStartSync
 
-#else
+#else // MULTI_THREAD_DATASTORE
 
 // can be called to check if performStartSync() should be terminated
 bool TStdLogicDS::shouldExitStartSync(void)
@@ -449,7 +459,7 @@ bool TStdLogicDS::shouldExitStartSync(void)
   return false;
 } // TStdLogicDS::shouldExitStartSync
 
-#endif
+#endif // MULTI_THREAD_DATASTORE
 
 
 // called by dsBeforeStateChange to dssta_dataaccessstarted to make sure datastore is
@@ -465,7 +475,7 @@ localstatus TStdLogicDS::startDataAccessForServer(void)
     // - start initialisation now
     fWriteStarted=false;
     // - read all records from DB right now if server data is used at all
-    DEBUGPRINTFX(DBG_DATA,("- number of items in list before StartDataRead = %ld",fItems.size()));
+    DEBUGPRINTFX(DBG_DATA,("- number of items in list before StartDataRead = %lu",(unsigned long)fItems.size()));
     // now we can initialize the conflict resolution mode for this session
     /// @todo move this to localengineds, at point where we get dssta_syncmodestable
     fSessionConflictStrategy=getConflictStrategy(fSlowSync,fFirstTimeSync);
@@ -529,7 +539,7 @@ localstatus TStdLogicDS::startDataAccessForServer(void)
     if (sta==LOCERR_OK) {
       // quick test: if number of items is > than allowed maxid of remote datatstore,
       // sync is unlikely to succeed
-      if (getRemoteDatastore()->getMaxID()<fItems.size()) {
+      if (getRemoteDatastore()->getMaxID()<(long)fItems.size()) {
         // this will not work, warn (but no longer abort session, as Siemens S55 guys don't like that)
         CONSOLEPRINTF((
           "Warning: Synchronisation involves more items (%ld) than client can possibly manage (%ld",
@@ -538,8 +548,8 @@ localstatus TStdLogicDS::startDataAccessForServer(void)
         ));
         PDEBUGPRINTFX(DBG_ERROR,(
           "Warning: Synchronisation involves more items (%ld) than client can possibly manage (%ld)",
-          (sInt32)fItems.size(),
-          (sInt32)getRemoteDatastore()->getMaxID()
+          (long)fItems.size(),
+          (long)getRemoteDatastore()->getMaxID()
         ));
       }
     }
@@ -699,24 +709,6 @@ sInt32 TStdLogicDS::getNumberOfChanges(void)
 } // TStdLogicDS::getNumberOfChanges
 
 
-/// @brief called to have all non-yet-generated sync commands as "to-be-resumed"
-void TStdLogicDS::logicMarkOnlyUngeneratedForResume(void)
-{
-  // we do not maintain the map/bookmark list at this level, so
-  // derived class (ODBC, BinFile etc.) must make sure that their list is
-  // clean (no marks from previous sessions) before calling this inherited version
-  implMarkOnlyUngeneratedForResume();
-  // Now add those that we have already received from the implementation
-  TSyncItemPContainer::iterator pos;
-  for (pos = fItems.begin(); pos != fItems.end(); ++pos) {
-    // let datastore mark these unprocessed
-    TSyncItem *syncitemP = (*pos);
-    // mark it for resume by ID
-    logicMarkItemForResume(syncitemP->getLocalID(),syncitemP->getRemoteID(),true); // these are unsent
-  }
-} // TStdLogicDS::logicMarkOnlyUngeneratedForResume
-
-
 
 // - called to let server generate sync commands for client
 //   Returns true if now finished (or aborted) for this datastore
@@ -740,14 +732,14 @@ bool TStdLogicDS::logicGenerateSyncCommandsAsServer(
   if (fMaxItemCount> 0) {
     PDEBUGPRINTFX(DBG_DATA+DBG_HOT,(
       "Info: Max number of items to be sent in this session is limited to %ld (already sent by now=%ld)",
-      fMaxItemCount,
-      fItemsSent
+      (long)fMaxItemCount,
+      (long)fItemsSent
     ));
   }
   #endif
   while (
     !isAborted() && // not aborted
-    (getDSConfig()->fMaxItemsPerMessage==0 || itemcount<getDSConfig()->fMaxItemsPerMessage==0) && // max item count per message not reached or not active
+    (getDSConfig()->fMaxItemsPerMessage==0 || itemcount<getDSConfig()->fMaxItemsPerMessage) && // max item count per message not reached or not active
     !fSessionP->outgoingMessageFull() && // message not full
     aNextMessageCommands.size()==0 // no commands already queued for next message
   ) {
@@ -871,8 +863,11 @@ localstatus TStdLogicDS::logicProcessMap(cAppCharP aRemoteID, cAppCharP aLocalID
 } // TStdLogicDS::logicProcessMap
 
 
+#endif // SYSYNC_SERVER
+
 
-#else
+
+#ifdef SYSYNC_CLIENT
 
 // Client Case
 // ===========
@@ -902,19 +897,6 @@ localstatus TStdLogicDS::startDataAccessForClient(void)
 } // TStdLogicDS::startDataAccessForClient
 
 
-/// @brief called to have all non-yet-generated sync commands as "to-be-resumed"
-void TStdLogicDS::logicMarkOnlyUngeneratedForResume(void)
-{
-  // we do not maintain the map/bookmark list at this level, so
-  // derived class (ODBC, BinFile etc.) must make sure that their list is
-  // clean (no marks from previous sessions) before calling this inherited version
-  implMarkOnlyUngeneratedForResume();
-  // in client case, fItems does not contain ungenerated/unprocessed items
-  // so we don't have anything more do here for now
-} // TStdLogicDS::logicMarkOnlyUngeneratedForResume
-
-
-
 // called to generate sync sub-commands as client for remote server
 // @return true if now finished for this datastore
 bool TStdLogicDS::logicGenerateSyncCommandsAsClient(
@@ -1022,7 +1004,40 @@ bool TStdLogicDS::logicGenerateSyncCommandsAsClient(
 } // TStdLogicDS::logicGenerateSyncCommandsAsClient
 
 
-#endif // client case
+#endif // SYSYNC_CLIENT
+
+
+/// @brief called to have all non-yet-generated sync commands as "to-be-resumed"
+void TStdLogicDS::logicMarkOnlyUngeneratedForResume(void)
+{
+       if (IS_SERVER) {
+       #ifdef SYSYNC_SERVER
+    // we do not maintain the map/bookmark list at this level, so
+    // derived class (ODBC, BinFile etc.) must make sure that their list is
+    // clean (no marks from previous sessions) before calling this inherited version
+    implMarkOnlyUngeneratedForResume();
+    // Now add those that we have already received from the implementation
+    TSyncItemPContainer::iterator pos;
+    for (pos = fItems.begin(); pos != fItems.end(); ++pos) {
+      // let datastore mark these unprocessed
+      TSyncItem *syncitemP = (*pos);
+      // mark it for resume by ID
+      logicMarkItemForResume(syncitemP->getLocalID(),syncitemP->getRemoteID(),true); // these are unsent
+    }
+    #endif // SYSYNC_SERVER
+  }
+  else {
+       #ifdef SYSYNC_CLIENT
+    // we do not maintain the map/bookmark list at this level, so
+    // derived class (ODBC, BinFile etc.) must make sure that their list is
+    // clean (no marks from previous sessions) before calling this inherited version
+    implMarkOnlyUngeneratedForResume();
+    // in client case, fItems does not contain ungenerated/unprocessed items
+    // so we don't have anything more do here for now
+    #endif // SYSYNC_CLIENT
+  }
+} // TStdLogicDS::logicMarkOnlyUngeneratedForResume
+
 
 
 // called to process incoming item operation
@@ -1089,15 +1104,16 @@ bool TStdLogicDS::logicProcessRemoteItem(
           // - create new empty TMultiFieldItem
           TMultiFieldItem *refitemP =
             (TMultiFieldItem *) newItemForRemote(ity_multifield);
-          #ifdef SYSYNC_CLIENT
-          // Client: retrieve by local ID
-          refitemP->clearRemoteID(); // not known
-          refitemP->setLocalID(syncitemP->getLocalID()); // make sure we retrieve by local ID
-          #else
-          // Server: retrieve by remote ID
-          refitemP->clearLocalID(); // make sure we retrieve by remote ID
-          refitemP->setRemoteID(syncitemP->getRemoteID()); // make sure we retrieve by remote ID
-          #endif
+          if (IS_CLIENT) {
+            // Client: retrieve by local ID
+            refitemP->clearRemoteID(); // not known
+            refitemP->setLocalID(syncitemP->getLocalID()); // make sure we retrieve by local ID
+          }
+          else {
+            // Server: retrieve by remote ID
+            refitemP->clearLocalID(); // make sure we retrieve by remote ID
+            refitemP->setRemoteID(syncitemP->getRemoteID()); // make sure we retrieve by remote ID
+          }
           refitemP->setSyncOp(sop_replace);
           #ifdef OBJECT_FILTERING
           PDEBUGPRINTFX(DBG_DATA,(
@@ -1168,14 +1184,11 @@ bool TStdLogicDS::logicProcessRemoteItem(
             if (sta==404 || sta==410) {
               // this is an irregularity for a client (but it's perfectly
               // normal case for server, as client may use replace for adds+replaces)
-              #ifdef SYSYNC_CLIENT
-              if (!syncitemP->hasRemoteID()) {
+              if (IS_CLIENT && !syncitemP->hasRemoteID()) {
                 // - we cannot handle this properly, we have no remoteID, so report error to server
                 PDEBUGPRINTFX(DBG_ERROR,("TStdLogicDS: Item not found, but cannot switch to add because no RemoteID is known, Status=%hd",aStatusCommand.getStatusCode()));
               }
-              else
-              #endif
-              {
+              else {
                 if (fPreventAdd) {
                   // prevent implicit add -> return sta as is
                 }
@@ -1183,14 +1196,16 @@ bool TStdLogicDS::logicProcessRemoteItem(
                   // - switch to add if remote sent remoteID along so we can properly map
                   syncitemP->setSyncOp(sop_add);
                   PDEBUGPRINTFX(DBG_DATA,("TStdLogicDS: RetrieveItem: not found (Status=%hd) --> adding instead",sta));
-                  #ifndef SYSYNC_CLIENT
-                  // - make sure we delete the old item from the map table (as we *know* the item is gone - should it reappear under a different localID, it'll be re-added)
-                  implProcessMap(syncitemP->getRemoteID(),NULL);
-                  #endif
-                  // we can handle it, as we know the remoteID
-                  #ifdef SYSYNC_CLIENT
-                  irregular=true; // irregular only for client
-                  #endif
+                  if (IS_SERVER) {
+                       #ifdef SYSYNC_SERVER
+                    // server: make sure we delete the old item from the map table (as we *know* the item is gone - should it reappear under a different localID, it'll be re-added)
+                    implProcessMap(syncitemP->getRemoteID(),NULL);
+                    #endif
+                  }
+                  else {
+                    // client: we can handle it, as we know the remoteID
+                    irregular=true; // irregular only for client
+                  }
                   sta=LOCERR_OK; // ok for further processing, anyway
                 }
               }
@@ -1250,28 +1265,27 @@ bool TStdLogicDS::logicProcessRemoteItem(
             if (sta==404 || sta==410) {
               // this is an irregularity for a client (but it's perfectly
               // normal case for server, as client may use replace for adds+replaces)
-              #ifdef SYSYNC_CLIENT
-              if (!syncitemP->hasRemoteID()) {
+              if (IS_CLIENT && !syncitemP->hasRemoteID()) {
                 // - we cannot handle this properly, we have no remoteID, so report error to server
                 PDEBUGPRINTFX(DBG_ERROR,("to-be-replaced item not found, but cannot switch to add because no RemoteID is known, Status=%hd",sta));
               }
-              else
-              #endif
-              {
+              else {
                 if (fPreventAdd) {
                   // prevent implicit add -> return status as is
                 }
                 else {
                   // - switch to add if remote sent remoteID along so we can properly map
                   syncitemP->setSyncOp(sop_add);
-                  #ifndef SYSYNC_CLIENT
-                  // - make sure we delete the old item from the map table (as we *know* the item is gone - should it reappear under a different localID, it'll be re-added)
-                  implProcessMap(syncitemP->getRemoteID(),NULL);
-                  #endif
-                  // we can handle it, as we know the remoteID
-                  #ifdef SYSYNC_CLIENT
-                  irregular=true;
-                  #endif
+                  if (IS_SERVER) {
+                       #ifdef SYSYNC_SERVER                  
+                    // - make sure we delete the old item from the map table (as we *know* the item is gone - should it reappear under a different localID, it'll be re-added)
+                    implProcessMap(syncitemP->getRemoteID(),NULL);
+                    #endif
+                  }
+                  else {
+                    // we can handle it, as we know the remoteID
+                    irregular=true;
+                       }
                   PDEBUGPRINTFX(DBG_DATA,("to-be-replaced item not found (Status=%hd) --> adding instead",sta));
                   // - process again (note that we are re-using the status command that might
                   //   already have a text item with an OS errir if something failed before)
@@ -1358,18 +1372,23 @@ localstatus TStdLogicDS::dsBeforeStateChange(TLocalEngineDSState aOldState,TLoca
 
   if (aNewState==dssta_dataaccessstarted) {
     // start data access
-    #ifdef SYSYNC_CLIENT
-    sta = startDataAccessForClient();
-    #else
-    sta = startDataAccessForServer();
-    #endif
-  }
-  #ifdef SYSYNC_CLIENT
-  if (aNewState==dssta_syncgendone) {
-    // when client has done sync gen, start writing
-    sta = startDataWrite();
+    if (IS_CLIENT) {
+       #ifdef SYSYNC_CLIENT
+           sta = startDataAccessForClient();
+      #endif
+    }
+    else {
+      #ifdef SYSYNC_SERVER
+           sta = startDataAccessForServer();
+      #endif
+    }
   }
-  #endif
+  if (IS_CLIENT) {
+    if (aNewState==dssta_syncgendone) {
+      // when client has done sync gen, start writing
+      sta = startDataWrite();
+    }
+  } // client
   if (aNewState==dssta_completed && !isAborted()) {
     // finish writing data now anyway
     endDataWrite();
index 5271e7e..9f2df50 100755 (executable)
 #include "platform_thread.h"
 #endif
 
+#if defined(CLIENT_USES_SERVER_DB)
+       #define USES_SERVER_DB 1
+       #define HAS_SERVER_DB 1
+#else
+       #ifdef SERVER_SUPPORT
+       #define USES_SERVER_DB 1
+  #endif
+       #define HAS_SERVER_DB IS_SERVER
+#endif
+
 using namespace sysync;
 
 namespace sysync {
@@ -49,7 +59,8 @@ private:
   #ifdef CLIENT_USES_SERVER_DB
   TSyncItemPContainer fItems; ///< list of data items, used to simulate maps in server DB
   #endif
-  #else
+  #endif
+  #ifdef SYSYNC_SERVER
   TSyncItemPContainer fItems; ///< list of data items
   uInt32 fNumRefOnlyItems;
   #endif
@@ -117,7 +128,7 @@ protected:
   virtual localstatus dsBeforeStateChange(TLocalEngineDSState aOldState,TLocalEngineDSState aNewState);
   /// inform logic of happened state change
   virtual localstatus dsAfterStateChange(TLocalEngineDSState aOldState,TLocalEngineDSState aNewState);
-  #ifndef SYSYNC_CLIENT
+  #ifdef SYSYNC_SERVER
   // - called when a item in the sync set changes its localID (due to local DB internals)
   //   Datastore must make sure that eventually cached items get updated
   virtual void dsLocalIdHasChanged(const char *aOldID, const char *aNewID);
@@ -222,7 +233,7 @@ protected:
        virtual localstatus implReviewReadItem(
          TSyncItem &aItem         // the item
        ) = 0;
-       #ifndef SYSYNC_CLIENT
+       #ifdef SYSYNC_SERVER
   /// called to set maps.
   /// @note aLocalID or aRemoteID can be NULL - which signifies deletion of a map entry
   /// @note that this might be needed for clients accessing a server-style database as well
@@ -252,7 +263,8 @@ private:
   #ifdef SYSYNC_CLIENT
   /// called by dsBeforeStateChange to dssta_dataaccessstarted to make sure datastore is ready for being accessed.
   virtual localstatus startDataAccessForClient(void);
-  #else
+  #endif
+  #ifdef SYSYNC_SERVER
   /// called by dsBeforeStateChange to dssta_dataaccessstarted to make sure datastore is ready for being accessed.
   virtual localstatus startDataAccessForServer(void);
   #endif
@@ -261,7 +273,7 @@ private:
 
 
 
-  #ifndef SYSYNC_CLIENT
+  #ifdef SYSYNC_SERVER
   // - called to check if conflicting replace or delete command from server exists
   virtual TSyncItem *getConflictingItemByRemoteID(TSyncItem *syncitemP);
   // - called to check if content-matching item from server exists
@@ -292,7 +304,9 @@ private:
   /// called for servers when receiving map from client
   /// @note aLocalID or aRemoteID can be NULL - which signifies deletion of a map entry
   virtual localstatus logicProcessMap(cAppCharP aLocalID, cAppCharP aRemoteID);
-  #else
+  #endif // SYSYNC_SERVER
+  
+  #ifdef SYSYNC_CLIENT
   /// called to generate sync sub-commands as server for remote client
   /// @return true if now finished for this datastore
   virtual bool logicGenerateSyncCommandsAsClient(
@@ -300,13 +314,8 @@ private:
     TSmlCommand * &aInterruptedCommandP,
     const char *aLocalIDPrefix
   );
-  #endif
-  /** @deprecated obsolete, replaced by stuff in dsBeforeStateChange()
-  // - called at very end of sync session, when everything is done
-  //   Note: is also called before deleting a datastore (so aborted sessions
-  //     can do cleanup and/or statistics display as well)
-  virtual void endOfSync(bool aRegular);
-  */
+  #endif // SYSYNC_CLIENT
+  
   // - determine if this is a first time sync situation
   virtual bool isFirstTimeSync(void) { return fFirstTimeSync; };
 
index d3cc1a6..e8dee1c 100755 (executable)
@@ -544,7 +544,10 @@ sInt16 HexStrToUIntPtr(const char *aStr, uIntPtr &aIntPtr, sInt16 aMaxDigits)
 #if __WORDSIZE == 64
   return HexStrToULongLong(aStr, aIntPtr, aMaxDigits);
 #else
-  return HexStrToULong(aStr, aIntPtr, aMaxDigits);
+       uInt32 l;
+  sInt16 n = HexStrToULong(aStr, l, aMaxDigits);
+  aIntPtr = (uIntPtr)l;
+  return n;
 #endif
 } // HexStrToUIntPtr
 
index c3ec689..c624e7a 100755 (executable)
@@ -471,7 +471,7 @@ bool TSuperDataStore::engProcessSyncCmdEnd(bool &aQueueForLater)
 } // TSuperDataStore::engProcessSyncCmdEnd
 
 
-#ifndef SYSYNC_CLIENT
+#ifdef SYSYNC_SERVER
 
 // process map
 localstatus TSuperDataStore::engProcessMap(cAppCharP aRemoteID, cAppCharP aLocalID)
@@ -494,7 +494,7 @@ done:
   return sta;
 } // TSuperDataStore::engProcessMap
 
-#endif
+#endif // SYSYNC_SERVER
 
 
 // called to process incoming item operation
@@ -512,7 +512,7 @@ bool TSuperDataStore::engProcessRemoteItem(
 {
   bool regular=true;
   string datatext;
-  #ifndef SYSYNC_CLIENT
+  #ifdef SYSYNC_SERVER
   TSyncItem *itemcopyP;
   #endif
 
@@ -530,163 +530,180 @@ bool TSuperDataStore::engProcessRemoteItem(
   TSyncOperation sop=syncitemP->getSyncOp();
   string remid;
   TSubDSLinkList::iterator pos;
-  switch (sop) {
-    #ifndef SYSYNC_CLIENT
-    // Server case
-    case sop_wants_replace:
-    case sop_replace:
-    case sop_wants_add:
-    case sop_add:
-      // item has no local ID, we need to apply filters to item data
-      PDEBUGPRINTFX(DBG_DATA,("Checkin subdatastore filters to find where it belongs"));
-      linkP = findSubLinkByData(*syncitemP);
-      if (!linkP) goto nods;
-      PDEBUGPRINTFX(DBG_DATA,(
-        "Found item belongs to subdatastore '%s'",
-        linkP->fDatastoreLinkP->getName()
-      ));
-      // make sure item does not have a local ID (which would be wrong because of prefixes anyway)
-      syncitemP->clearLocalID();
-      // remembert because we might need it below for move-replace
-      remid=syncitemP->getRemoteID();
-      // let subdatastore process
-      regular=linkP->fDatastoreLinkP->engProcessRemoteItem(syncitemP,aStatusCommand);
-      // now check if replace was treated as add, if yes, this indicates
-      // that this might be a move between subdatastores
-      if (
-        (sop==sop_replace || sop==sop_wants_replace) &&
-        !fSlowSync && aStatusCommand.getStatusCode()==201
-      ) {
-        // this is probably a move from another datastore by changing an attribute
-        // that dispatches datastores (such as a vEvent changed to a vToDo)
-        // - so we delete all items with this remote ID in all other datastores
-        PDEBUGPRINTFX(DBG_DATA,("Replace could be a move between subdatastores, trying to delete all items with same remoteID in other subdatastores"));
-        TSubDSLinkList::iterator pos;
-        TStatusCommand substatus(fSessionP);
-        for (pos=fSubDSLinks.begin();pos!=fSubDSLinks.end();pos++) {
-          if (&(*pos) != linkP) {
-            // all but original datastore
-            substatus.setStatusCode(200);
-            itemcopyP = new TSyncItem();
-            // - only remote ID and syncop are relevant, leave everything else empty
-            itemcopyP->setRemoteID(remid.c_str());
-            itemcopyP->setSyncOp(sop_delete);
-            // - now try to delete. This might fail if replace above wasn't a move
-            //   itemcopyP is consumed
-            PDEBUGPRINTFX(DBG_DATA+DBG_DETAILS,(
-              "Trying to delete item with remoteID='%s' from subdatastore '%s'",
-              itemcopyP->getRemoteID(),
-              linkP->fDatastoreLinkP->getName()
-            ));
-            regular=pos->fDatastoreLinkP->engProcessRemoteItem(itemcopyP,substatus);
-            #ifdef SYDEBUG
-            if (regular) {
-              // deleted ok
-              PDEBUGPRINTFX(DBG_DATA,(
-                "Found item in '%s', deleted here (and moved to '%s')",
-                pos->fDatastoreLinkP->getName(),
+  #ifdef SYSYNC_SERVER
+  if (IS_SERVER) {
+    switch (sop) {
+      // Server case
+      case sop_wants_replace:
+      case sop_replace:
+      case sop_wants_add:
+      case sop_add:
+        // item has no local ID, we need to apply filters to item data
+        PDEBUGPRINTFX(DBG_DATA,("Checkin subdatastore filters to find where it belongs"));
+        linkP = findSubLinkByData(*syncitemP);
+        if (!linkP) goto nods;
+        PDEBUGPRINTFX(DBG_DATA,(
+          "Found item belongs to subdatastore '%s'",
+          linkP->fDatastoreLinkP->getName()
+        ));
+        // make sure item does not have a local ID (which would be wrong because of prefixes anyway)
+        syncitemP->clearLocalID();
+        // remembert because we might need it below for move-replace
+        remid=syncitemP->getRemoteID();
+        // let subdatastore process
+        regular=linkP->fDatastoreLinkP->engProcessRemoteItem(syncitemP,aStatusCommand);
+        // now check if replace was treated as add, if yes, this indicates
+        // that this might be a move between subdatastores
+        if (
+          (sop==sop_replace || sop==sop_wants_replace) &&
+          !fSlowSync && aStatusCommand.getStatusCode()==201
+        ) {
+          // this is probably a move from another datastore by changing an attribute
+          // that dispatches datastores (such as a vEvent changed to a vToDo)
+          // - so we delete all items with this remote ID in all other datastores
+          PDEBUGPRINTFX(DBG_DATA,("Replace could be a move between subdatastores, trying to delete all items with same remoteID in other subdatastores"));
+          TStatusCommand substatus(fSessionP);
+          for (pos=fSubDSLinks.begin();pos!=fSubDSLinks.end();pos++) {
+            if (&(*pos) != linkP) {
+              // all but original datastore
+              substatus.setStatusCode(200);
+              itemcopyP = new TSyncItem();
+              // - only remote ID and syncop are relevant, leave everything else empty
+              itemcopyP->setRemoteID(remid.c_str());
+              itemcopyP->setSyncOp(sop_delete);
+              // - now try to delete. This might fail if replace above wasn't a move
+              //   itemcopyP is consumed
+              PDEBUGPRINTFX(DBG_DATA+DBG_DETAILS,(
+                "Trying to delete item with remoteID='%s' from subdatastore '%s'",
+                itemcopyP->getRemoteID(),
                 linkP->fDatastoreLinkP->getName()
               ));
+              regular=pos->fDatastoreLinkP->engProcessRemoteItem(itemcopyP,substatus);
+              #ifdef SYDEBUG
+              if (regular) {
+                // deleted ok
+                PDEBUGPRINTFX(DBG_DATA,(
+                  "Found item in '%s', deleted here (and moved to '%s')",
+                  pos->fDatastoreLinkP->getName(),
+                  linkP->fDatastoreLinkP->getName()
+                ));
+              }
+              #endif
             }
-            #endif
           }
+          PDEBUGPRINTFX(DBG_DATA,("End of (possible) move-replace between subdatastores"));
+          regular=true; // fully ok, no matter if delete above has succeeded or not
         }
-        PDEBUGPRINTFX(DBG_DATA,("End of (possible) move-replace between subdatastores"));
-        regular=true; // fully ok, no matter if delete above has succeeded or not
-      }
-      goto done;
-    case sop_archive_delete:
-    case sop_soft_delete:
-    case sop_delete:
-    case sop_copy:
-      // item has no local ID AND no data, only a remoteID:
-      // we must try to read item from all subdatastores by remoteID until
-      // one is found
-      // get an empty item of correct type to call logicRetrieveItemByID
-      itemcopyP = getLocalReceiveType()->newSyncItem(getRemoteSendType(),this);
-      // - only remote ID is relevant, leave everything else empty
-      itemcopyP->setRemoteID(syncitemP->getRemoteID());
-      // try to read item from all subdatastores
-      for (pos=fSubDSLinks.begin();pos!=fSubDSLinks.end();pos++) {
-        linkP = &(*pos);
-        // always start with 200
-        aStatusCommand.setStatusCode(200);
-        // now try to read
-        PDEBUGPRINTFX(DBG_DATA+DBG_DETAILS,(
-          "Trying to read item by remoteID='%s' from subdatastore '%s' to see if it is there",
-          itemcopyP->getRemoteID(),
-          linkP->fDatastoreLinkP->getName()
-        ));
-        regular=linkP->fDatastoreLinkP->logicRetrieveItemByID(*itemcopyP,aStatusCommand);
-        // must be ok AND not 404 (item not found)
-        if (regular && aStatusCommand.getStatusCode()!=404) {
-          PDEBUGPRINTFX(DBG_DATA,(
-            "Item found in subdatastore '%s', deleting it there",
+        goto done;
+      case sop_archive_delete:
+      case sop_soft_delete:
+      case sop_delete:
+      case sop_copy:
+        // item has no local ID AND no data, only a remoteID:
+        // we must try to read item from all subdatastores by remoteID until
+        // one is found
+        // get an empty item of correct type to call logicRetrieveItemByID
+        itemcopyP = getLocalReceiveType()->newSyncItem(getRemoteSendType(),this);
+        // - only remote ID is relevant, leave everything else empty
+        itemcopyP->setRemoteID(syncitemP->getRemoteID());
+        // try to read item from all subdatastores
+        for (pos=fSubDSLinks.begin();pos!=fSubDSLinks.end();pos++) {
+          linkP = &(*pos);
+          // always start with 200
+          aStatusCommand.setStatusCode(200);
+          // now try to read
+          PDEBUGPRINTFX(DBG_DATA+DBG_DETAILS,(
+            "Trying to read item by remoteID='%s' from subdatastore '%s' to see if it is there",
+            itemcopyP->getRemoteID(),
             linkP->fDatastoreLinkP->getName()
           ));
-          // now we can delete or copy, consuming original item
-          regular=linkP->fDatastoreLinkP->engProcessRemoteItem(syncitemP,aStatusCommand);
-          // delete duplicated item as well
-          delete itemcopyP;
-          // done
-          regular=true;
-          goto done;
+          regular=linkP->fDatastoreLinkP->logicRetrieveItemByID(*itemcopyP,aStatusCommand);
+          // must be ok AND not 404 (item not found)
+          if (regular && aStatusCommand.getStatusCode()!=404) {
+            PDEBUGPRINTFX(DBG_DATA,(
+              "Item found in subdatastore '%s', deleting it there",
+              linkP->fDatastoreLinkP->getName()
+            ));
+            // now we can delete or copy, consuming original item
+            regular=linkP->fDatastoreLinkP->engProcessRemoteItem(syncitemP,aStatusCommand);
+            // delete duplicated item as well
+            delete itemcopyP;
+            // done
+            regular=true;
+            goto done;
+          }
         }
-      }
-      // none of the datastores could process this item --> error
-      // - delete duplicated item
-      delete itemcopyP;
-      // - make sure delete reports 200 for incomplete-rollback-datastores
-      if (aStatusCommand.getStatusCode()==404 && sop!=sop_copy) {
-        // not finding an item for delete might be ok for remote...
-        if (fSessionP->getSessionConfig()->fDeletingGoneOK) {
-          // 404/410: item not found, could be because previous aborted session has
-          // already committed deletion of that item -> behave as if delete was ok
-          PDEBUGPRINTFX(DBG_DATA,("to-be-deleted item was not found, but do NOT report %hd",aStatusCommand.getStatusCode()));
-          aStatusCommand.setStatusCode(200);
+        // none of the datastores could process this item --> error
+        // - delete duplicated item
+        delete itemcopyP;
+        // - make sure delete reports 200 for incomplete-rollback-datastores
+        if (aStatusCommand.getStatusCode()==404 && sop!=sop_copy) {
+          // not finding an item for delete might be ok for remote...
+          if (fSessionP->getSessionConfig()->fDeletingGoneOK) {
+            // 404/410: item not found, could be because previous aborted session has
+            // already committed deletion of that item -> behave as if delete was ok
+            PDEBUGPRINTFX(DBG_DATA,("to-be-deleted item was not found, but do NOT report %hd",aStatusCommand.getStatusCode()));
+            aStatusCommand.setStatusCode(200);
+          }
+          // ...but it is a internal irregularity, fall thru to return false
         }
-        // ...but it is a internal irregularity, fall thru to return false
-      }
-      // is an internal irregularity
-      regular=false;
-      goto done;
-    #else
-    // Client case
-    case sop_wants_replace:
-    case sop_replace:
-    case sop_archive_delete:
-    case sop_soft_delete:
-    case sop_delete:
-    case sop_copy:
-      // item has local ID, we can find datastore by prefix
-      linkP = findSubLinkByLocalID(syncitemP->getLocalID());
-      if (!linkP) goto nods;
-      // remove prefix before letting subdatastore process it
-      syncitemP->fLocalID.erase(0,linkP->fDSLinkConfigP->fGUIDPrefix.size());
-      // now let subdatastore process
-      regular=linkP->fDatastoreLinkP->engProcessRemoteItem(syncitemP,aStatusCommand);
-      goto done;
-    case sop_wants_add:
-    case sop_add:
-      // item has no local ID, we need to apply filters to item data
-      linkP = findSubLinkByData(*syncitemP);
-      if (!linkP) goto nods;
-      // make sure item does not have a local ID (which would be wrong because of prefixes anyway)
-      syncitemP->clearLocalID();
-      // let subdatastore process
-      regular=linkP->fDatastoreLinkP->engProcessRemoteItem(syncitemP,aStatusCommand);
-      goto done;
-    #endif
-    default:
-    nods:
-      // no datastore or unknown command, general DB error
-      aStatusCommand.setStatusCode(510);
-      PDEBUGPRINTFX(DBG_ERROR,("TSuperDataStore::processRemoteItem Fatal: Item cannot be processed by any subdatastore"));
-      // consume item
-      delete syncitemP;
-      regular=false;
-      goto done;
-  } // switch
+        // is an internal irregularity
+        regular=false;
+        goto done;
+    case sop_reference_only:
+    case sop_move:
+    case sop_none:
+    case numSyncOperations:
+      // nothing to do or shouldn't happen
+      break;
+    } // switch
+  } // server
+  #endif // SYSYNC_SERVER
+  #ifdef SYSYNC_CLIENT
+  if (IS_CLIENT) {
+    switch (sop) {
+      // Client case
+      case sop_wants_replace:
+      case sop_replace:
+      case sop_archive_delete:
+      case sop_soft_delete:
+      case sop_delete:
+      case sop_copy:
+        // item has local ID, we can find datastore by prefix
+        linkP = findSubLinkByLocalID(syncitemP->getLocalID());
+        if (!linkP) goto nods;
+        // remove prefix before letting subdatastore process it
+        syncitemP->fLocalID.erase(0,linkP->fDSLinkConfigP->fGUIDPrefix.size());
+        // now let subdatastore process
+        regular=linkP->fDatastoreLinkP->engProcessRemoteItem(syncitemP,aStatusCommand);
+        goto done;
+      case sop_wants_add:
+      case sop_add:
+        // item has no local ID, we need to apply filters to item data
+        linkP = findSubLinkByData(*syncitemP);
+        if (!linkP) goto nods;
+        // make sure item does not have a local ID (which would be wrong because of prefixes anyway)
+        syncitemP->clearLocalID();
+        // let subdatastore process
+        regular=linkP->fDatastoreLinkP->engProcessRemoteItem(syncitemP,aStatusCommand);
+        goto done;
+    case sop_reference_only:
+    case sop_move:
+    case sop_none:
+    case numSyncOperations:
+      // nothing to do or shouldn't happen
+      break;
+    } // switch
+  } // client
+  #endif // SYSYNC_CLIENT
+nods:
+  // no datastore or unknown command, general DB error
+  aStatusCommand.setStatusCode(510);
+  PDEBUGPRINTFX(DBG_ERROR,("TSuperDataStore::processRemoteItem Fatal: Item cannot be processed by any subdatastore"));
+  // consume item
+  delete syncitemP;
+  regular=false;
+  goto done;
 done:
   PDEBUGENDBLOCK("SuperProcessItem");
   return regular;
@@ -1063,7 +1080,7 @@ localstatus TSuperDataStore::engSaveSuspendState(bool aAnyway)
 } // TSuperDataStore::engSaveSuspendState
 
 
-#ifndef SYSYNC_CLIENT
+#ifdef SYSYNC_SERVER
 
 /// @brief called at end of request processing, should be used to save suspend state
 /// @note subdatastores don't do anything themselves, to make sure superds can make things happen in correct order
@@ -1142,27 +1159,6 @@ bool TSuperDataStore::engGenerateSyncCommands(
 
 #ifdef SYSYNC_CLIENT
 
-/* %%% not required - engClientStartOfSyncMessage() will be called for all local DS anyway,
-   and superDS will ALWAYS be called after contained subDS, as the superDS's definition
-   is always AFTER the contained subDS's definition in the config
-// called whenever outgoing Message of Sync Package starts
-// - Client will start Sync generation now, which means that subdatastores
-//   just set fSyncGenerationStarted=true (without actually creating a <sync>,
-//   and superdatastore creates a <sync> which will contain all add/delete/replace
-//   from all subdatastores (as generated by generateSyncCommands)
-void TSuperDataStore::engClientStartOfSyncMessage(void)
-{
-  // signal sync start to all subdatastores
-  TSubDSLinkList::iterator pos;
-  for (pos=fSubDSLinks.begin();pos!=fSubDSLinks.end();pos++) {
-    pos->fDatastoreLinkP->engClientStartOfSyncMessage();
-  }
-  // signal it to myself
-  TLocalEngineDS::engClientStartOfSyncMessage();
-} // TSuperDataStore::engClientStartOfSyncMessage
-
-*/
-
 // Client only: returns number of unsent map items
 sInt32 TSuperDataStore::numUnsentMaps(void)
 {
@@ -1183,7 +1179,7 @@ void TSuperDataStore::engMarkMapConfirmed(cAppCharP aLocalID, cAppCharP aRemoteI
   TSubDatastoreLink *linkP = findSubLinkByLocalID(aLocalID);
   if (linkP) {
     // pass to subdatastore with prefix removed
-    linkP->engMarkMapConfirmed(aLocalID+linkP->fDSLinkConfigP->fGUIDPrefix.size(),aRemoteID);
+    linkP->fDatastoreLinkP->engMarkMapConfirmed(aLocalID+linkP->fDSLinkConfigP->fGUIDPrefix.size(),aRemoteID);
   }
 } // TSuperDataStore::engMarkMapConfirmed
 
@@ -1191,10 +1187,7 @@ void TSuperDataStore::engMarkMapConfirmed(cAppCharP aLocalID, cAppCharP aRemoteI
 // - client only: called to generate Map items
 //   Returns true if now finished for this datastore
 //   also sets fState to dss_done when finished
-bool TSuperDataStore::engGenerateMapItems(
-  TMapCommand *aMapCommandP,
-  const char *aLocalIDPrefix
-)
+bool TSuperDataStore::engGenerateMapItems(TMapCommand *aMapCommandP, cAppCharP aLocalIDPrefix)
 {
   TSubDSLinkList::iterator pos=fSubDSLinks.begin();
   bool ok;
@@ -1208,7 +1201,7 @@ bool TSuperDataStore::engGenerateMapItems(
     AssignString(prefix,aLocalIDPrefix);
     prefix.append(fCurrentGenDSPos->fDSLinkConfigP->fGUIDPrefix);
     // generate Map items
-    ok=pos->fDatastoreLinkP->engGenerateMapItems(TMapCommand *aMapCommandP,prefix.c_str());
+    ok=pos->fDatastoreLinkP->engGenerateMapItems(aMapCommandP,prefix.c_str());
     // exit if not yet finished with generating map items for this datastore
     if (!ok) {
       PDEBUGENDBLOCK("MapGenerate");
@@ -1219,22 +1212,26 @@ bool TSuperDataStore::engGenerateMapItems(
   } while(true);
   // done
   // we are done if state is syncdone (no more sync commands will occur)
-  if (fState==dss_syncsend) {
-    PDEBUGPRINTFX(DBG_PROTO,("TSuperDataStore: Finished sending chached Map items from previous session"))
-  }
-  else if (fState==dss_syncdone) {
-    fState=dss_done;
+  if (testState(dssta_dataaccessdone)) {
+    changeState(dssta_clientmapssent,true);
     PDEBUGPRINTFX(DBG_PROTO,("TSuperDataStore: Finished generating Map items, server has finished <sync>, we are done now"))
   }
+  #ifdef SYDEBUG
+  // else if we are not yet dssta_syncgendone -> this is the end of a early pending map send
+  else if (!dbgTestState(dssta_syncgendone)) {
+    PDEBUGPRINTFX(DBG_PROTO,("TSuperDataStore: Finished sending cached Map items from last session"))
+  }
+  // otherwise, we are not really finished with the maps yet (but with the current map command)
   else {
     PDEBUGPRINTFX(DBG_PROTO,("TSuperDataStore: Finished generating Map items for now, but server still sending <Sync>"))
   }
+  #endif
   PDEBUGENDBLOCK("MapGenerate");
   return true;
 } // TSuperDataStore::engGenerateMapItems
 
 
-#endif
+#endif // SYSYNC_CLIENT
 
 
 /* end of TSuperDataStore implementation */
index 6d1716c..f93e00c 100755 (executable)
@@ -151,7 +151,7 @@ public:
     TSyncItem *syncitemP,
     TStatusCommand &aStatusCommand
   );
-  #ifndef SYSYNC_CLIENT
+  #ifdef SYSYNC_SERVER
   // - called to process map commands from client to server
   virtual localstatus engProcessMap(cAppCharP aRemoteID, cAppCharP aLocalID);
   #endif
@@ -217,22 +217,12 @@ protected:
   // - returns true if DB implementation supports resume (saving of resume marks, alert code, pending maps, tempGUIDs)
   virtual bool dsResumeSupportedInDB(void);
   #ifdef SYSYNC_CLIENT
-  /* %%% not required - these will be called for all local DS anyway,
-     and superDS will ALWAYS be called after contained subDS, as the superDS's definition
-     is always AFTER the contained subDS's definition in the config
-  // client only: called whenever outgoing Message of Sync Package starts
-  // - should start a sync command for all alerted datastores
-  virtual void engClientStartOfSyncMessage(void);
-  // called whenever outgoing Message of Map Package starts
-  virtual void engClientStartOfMapMessage(bool aNotYetInMapPackage);
-  */
   // Client only: called to generate Map items
   // - Returns true if now finished for this datastore
   // - also sets fState to dss_done when finished
-  virtual bool engGenerateMapItems(TMapCommand *aMapCommandP);
+  virtual bool engGenerateMapItems(TMapCommand *aMapCommandP, cAppCharP aLocalIDPrefix);
   // Client only: returns number of unsent map items
   virtual sInt32 numUnsentMaps(void);
-  #ifdef SYSYNC_CLIENT
   /// client: called to generate sync sub-commands to be sent to server
   /// Returns true if now finished for this datastore
   /// also sets fState to dss_syncdone(server)/dss_syncready(client) when finished
@@ -243,8 +233,8 @@ protected:
   ) { return LOCERR_NOTIMP; };
   // Client only: called to mark maps confirmed, that is, we have received ok status for them
   virtual void engMarkMapConfirmed(cAppCharP aLocalID, cAppCharP aRemoteID);
-  #endif
-  #else
+  #endif // SYSYNC_CLIENT
+  #ifdef SYSYNC_SERVER
   // Server only:
   /// server: called to generate sync sub-commands to be sent to client
   /// Returns true if now finished for this datastore
@@ -272,7 +262,7 @@ protected:
   virtual void dsLocalIdHasChanged(const char *aOldID, const char *aNewID) {};
   // - called to have additional item sent to remote (DB takes ownership of item)
   virtual void SendItemAsServer(TSyncItem *aSyncitemP) {};
-  #endif
+  #endif // SYSYNC_SERVER
   /// called to have all non-yet-generated sync commands as "to-be-resumed"
   virtual void logicMarkOnlyUngeneratedForResume(void) {};
   /// called to mark an already generated (but probably not sent or not yet statused) item
diff --git a/src/synthesis/src/sysync/syncagent.cpp b/src/synthesis/src/sysync/syncagent.cpp
new file mode 100755 (executable)
index 0000000..73c3dd9
--- /dev/null
@@ -0,0 +1,3667 @@
+/*
+ *  File:         syncagent.cpp
+ *
+ *  Author:                      Lukas Zeller (luz@synthesis.ch)
+ *
+ *  TSyncAgent:   Provides functionality to run client or server
+ *                sessions.
+ *                Unifies former TSyncClient and TSyncServer
+ *
+ *  Copyright (c) 2002-2009 by Synthesis AG (www.synthesis.ch)
+ *
+ *  2009-09-30 : luz : created from syncclient.cpp and syncserver.cpp
+ *
+ */
+
+
+// includes
+#include "prefix_file.h"
+#include "sysync.h"
+#include "syncagent.h"
+#include "syncappbase.h"
+
+#ifdef HARD_CODED_SERVER_URI
+  #include "syserial.h"
+#endif
+
+// includes that can't be in .h due to circular references
+#ifdef SYSYNC_SERVER
+#include "syncsessiondispatch.h"
+#endif
+#ifdef SYSYNC_CLIENT
+#include "syncclientbase.h"
+#endif
+
+#ifdef SYSYNC_TOOL
+#include <errno.h>
+#endif
+
+
+namespace sysync {
+
+
+#ifdef SYSYNC_TOOL
+
+// Support for SySync Diagnostic Tool
+// ==================================
+
+
+// test login into database
+int testLogin(int argc, const char *argv[])
+{
+  if (argc<0) {
+    // help requested
+    CONSOLEPRINTF(("  login [<username> <password>] [<deviceid>]"));
+    CONSOLEPRINTF(("    test login to database with syncml user/password and optional deviceid"));
+    return EXIT_SUCCESS;
+  }
+
+  TSyncSession *sessionP = NULL;
+  const char *username = NULL;
+  const char *password = NULL;
+  const char *deviceid = "sysytool_test";
+
+  // check for argument
+  if (argc<2) {
+    // no user/password, test anonymous login
+       if (argc>0) deviceid = argv[0];
+  }
+  else {
+    // login with user/password
+    username = argv[0];
+    password = argv[1];
+    if (argc>2) {
+      // explicit device ID
+      deviceid = argv[2];
+    }
+  }
+    
+  // get session to work with
+  sessionP =
+    static_cast<TSyncSessionDispatch *>(getSyncAppBase())->getSySyToolSession();
+
+  bool authok = false;
+  
+  // try login
+  if (username) {
+    // real login with user and password
+    authok = sessionP->SessionLogin(username, password, sectyp_clearpass, deviceid);
+  }
+  else {
+    // anonymous - do a "login" with empty credentials
+    authok = sessionP->SessionLogin("anonymous", NULL, sectyp_anonymous, deviceid);
+  }
+  
+  if (authok) {
+    CONSOLEPRINTF(("+++++ Successfully authorized"));
+  }
+  else {
+    CONSOLEPRINTF(("----- Authorisation failed"));
+  }
+  
+  return authok;
+} // testLogin
+
+
+// convert user data into internal format and back
+int convertData(int argc, const char *argv[])
+{
+  if (argc<0) {
+    // help requested
+    CONSOLEPRINTF(("  convert <datastore name> <data file, vcard or vcalendar etc.> [<explicit input type>] [<output type>]"));
+    CONSOLEPRINTF(("    Convert data to internal format of specified datastore and back"));
+    return EXIT_SUCCESS;
+  }
+
+  TSyncSession *sessionP = NULL;
+  const char *datastore = NULL;
+  const char *rawfilename = NULL;
+  const char *inputtype = NULL;
+  const char *outputtype = NULL;
+
+  // check for argument
+  if (argc<2) {
+       CONSOLEPRINTF(("required datatype name and raw file name arguments"));
+       return EXIT_FAILURE;
+  }
+  datastore = argv[0];
+  rawfilename = argv[1];
+  if (argc>=3) {
+    // third arg is explicit input type
+    inputtype=argv[2];
+  }
+  outputtype=inputtype; // default to input type
+  if (argc>=4) {
+    // fourth arg is explicit output type
+    outputtype=argv[3];
+  }
+  
+  // get session to work with
+  sessionP =
+    static_cast<TSyncSessionDispatch *>(getSyncAppBase())->getSySyToolSession();
+  // configure session
+  sessionP->fRemoteCanHandleUTC = true; // run generator and parser in UTC enabled mode
+  
+  
+  // switch mimimal debugging on
+  sessionP->getDbgLogger()->setMask(sessionP->getDbgLogger()->getMask() | (DBG_PARSE+DBG_GEN));
+    
+  // find datastore
+  TLocalEngineDS *datastoreP = sessionP->findLocalDataStore(datastore);
+  TSyncItemType *inputtypeP = NULL;
+  TSyncItemType *outputtypeP = NULL;
+  if (!datastoreP) {
+       CONSOLEPRINTF(("datastore type '%s' not found",datastore));
+       return EXIT_FAILURE;
+  }
+
+  // find input type
+  if (inputtype) {
+    // search in datastore
+    inputtypeP=datastoreP->getReceiveType(inputtype,NULL);
+  }
+  else {
+    // use preferred rx type
+    inputtypeP=datastoreP->getPreferredRxItemType();
+  }
+  if (!inputtypeP) {
+       CONSOLEPRINTF(("input type not found"));
+       return EXIT_FAILURE;
+  }
+  // find output type
+  if (outputtype) {
+    // search in datastore
+    outputtypeP=datastoreP->getSendType(outputtype,NULL);
+  }
+  else {
+    // use preferred rx type
+    outputtypeP=datastoreP->getPreferredTxItemType();
+  }
+  if (!outputtypeP) {
+       CONSOLEPRINTF(("output type not found"));
+       return EXIT_FAILURE;
+  }
+  // prepare type usage
+  if (inputtypeP==outputtypeP)
+    inputtypeP->initDataTypeUse(datastoreP, true, true);
+  else {
+    inputtypeP->initDataTypeUse(datastoreP, false, true);
+    outputtypeP->initDataTypeUse(datastoreP, true, false);
+  }    
+
+  // now open file and read data item
+  FILE *infile;
+  size_t insize=0;
+  uInt8 *databuffer;
+  
+  infile = fopen(rawfilename,"rb");
+  if (!infile) {
+       CONSOLEPRINTF(("Cannot open input file '%s' (%d)",rawfilename,errno));
+       return EXIT_FAILURE;    
+  }
+  // - get size of file
+  fseek(infile,0,SEEK_END);
+  insize=ftell(infile);
+  fseek(infile,0,SEEK_SET);
+  // - create buffer of appropriate size
+  databuffer = new uInt8[insize];
+  if (!databuffer) {
+       CONSOLEPRINTF(("Not enough memory to read input file '%s' (%d)",rawfilename,errno));
+       return EXIT_FAILURE;    
+  }  
+  // - read data
+  if (fread(databuffer,1,insize,infile)<insize) {
+       CONSOLEPRINTF(("Error reading input file '%s' (%d)",rawfilename,errno));
+       return EXIT_FAILURE;    
+  }
+  CONSOLEPRINTF(("\nNow converting into internal field representation\n"));
+  // create a sml item
+  TStatusCommand statusCmd(sessionP);
+  SmlItemPtr_t smlitemP = newItem();
+  smlitemP->data=newPCDataStringX(databuffer,true,insize);
+  delete[] databuffer;
+  // create and fill a Sync item
+  TSyncItem *syncitemP = inputtypeP->newSyncItem(
+    smlitemP, // SyncML toolkit item Data to be converted into SyncItem
+    sop_replace, // the operation to be performed with this item
+    fmt_chr,    // assume default (char) format
+    inputtypeP, // target myself
+    datastoreP, // local datastore
+    statusCmd // status command that might be modified in case of error
+  );
+  // forget SyncML version
+  smlFreeItemPtr(smlitemP);
+  if (!syncitemP) {
+       CONSOLEPRINTF(("Error converting input file to internal format (SyncML status code=%hd)",statusCmd.getStatusCode()));
+       return EXIT_FAILURE;
+  }
+
+  CONSOLEPRINTF(("\nNow copying item and convert back to transport format\n"));
+
+  // make new for output type
+  TSyncItem *outsyncitemP = outputtypeP->newSyncItem(
+    outputtypeP, // target myself
+    datastoreP  // local datastore
+  );
+  // copy data
+  outsyncitemP->replaceDataFrom(*syncitemP);
+  delete syncitemP;
+  // convert back
+  smlitemP=outputtypeP->newSmlItem(
+    outsyncitemP,   // the syncitem to be represented as SyncML
+    datastoreP // local datastore
+  );
+  if (!syncitemP) {
+       CONSOLEPRINTF(("Could not convert back item data"));
+       return EXIT_FAILURE;
+  }
+  
+  // forget converted back item
+  smlFreeItemPtr(smlitemP);
+  
+  return EXIT_SUCCESS;
+} // convertData
+
+#endif // SYSYNC_TOOL
+
+
+
+
+#ifdef PRECONFIGURED_SYNCREQUESTS
+
+// Implementation of TSyncReqConfig
+// ================================
+
+// config for databases to sync with
+TSyncReqConfig::TSyncReqConfig(TLocalDSConfig *aLocalDSCfg, TConfigElement *aParentElement) :
+  TConfigElement("syncrequest",aParentElement),
+  fLocalDSConfig(aLocalDSCfg)
+{
+  clear();
+} // TSyncReqConfig::TSyncReqConfig
+
+
+TSyncReqConfig::~TSyncReqConfig()
+{
+  // nop so far
+} // TSyncReqConfig::~TSyncReqConfig
+
+
+// init defaults
+void TSyncReqConfig::clear(void)
+{
+  // init defaults
+  // - local client datatstore subselection path or CGI (such as "test" in "contact/test")
+  fLocalPathExtension.erase();
+  // - remote server DB layer auth
+  fDBUser.erase();
+  fDBPassword.erase();
+  // - remote server datastore path
+  fServerDBPath.erase();
+  // - sync mode
+  fSyncMode=smo_twoway;
+  fSlowSync=false; // default to non-slow
+  // - DS 1.2 filtering parameters
+  fRecordFilterQuery.erase();
+  fFilterInclusive=false;
+  // clear inherited
+  inherited::clear();
+} // TSyncReqConfig::clear
+
+
+// config element parsing
+bool TSyncReqConfig::localStartElement(const char *aElementName, const char **aAttributes, sInt32 aLine)
+{
+  // checking the elements
+  if (strucmp(aElementName,"localpathextension")==0)
+    expectString(fLocalPathExtension);
+  else if (strucmp(aElementName,"dbuser")==0)
+    expectString(fDBUser);
+  else if (strucmp(aElementName,"dbpassword")==0)
+    expectString(fDBPassword);
+  else if (strucmp(aElementName,"dbpath")==0)
+    expectString(fServerDBPath);
+  else if (strucmp(aElementName,"syncmode")==0)
+    expectEnum(sizeof(fSyncMode),&fSyncMode,SyncModeNames,numSyncModes);
+  else if (strucmp(aElementName,"slowsync")==0)
+    expectBool(fSlowSync);
+  else if (strucmp(aElementName,"recordfilter")==0)
+    expectString(fRecordFilterQuery);
+  else if (strucmp(aElementName,"filterinclusive")==0)
+    expectBool(fFilterInclusive);
+
+  // - none known here
+  else
+    return inherited::localStartElement(aElementName,aAttributes,aLine);
+  // ok
+  return true;
+} // TSyncReqConfig::localStartElement
+
+
+// resolve
+void TSyncReqConfig::localResolve(bool aLastPass)
+{
+  if (aLastPass) {
+    // check for required settings
+    // %%% tbd
+  }
+  // resolve inherited
+  inherited::localResolve(aLastPass);
+} // TSyncReqConfig::localResolve
+
+
+// create appropriate type of local datastore from config and init sync parameters
+TLocalEngineDS *TSyncReqConfig::initNewLocalDataStore(TSyncSession *aSessionP)
+{
+  // - create appropriate type of localdsP
+  TLocalEngineDS *localdsP = fLocalDSConfig->newLocalDataStore(aSessionP);
+  // - set parameters
+  localdsP->dsSetClientSyncParams(
+    fSyncMode,
+    fSlowSync,
+    fServerDBPath.c_str(),
+    fDBUser.c_str(),
+    fDBPassword.c_str(),
+    fLocalPathExtension.c_str(),
+    fRecordFilterQuery.c_str(),
+    fFilterInclusive
+  );
+  return localdsP;
+} // TSyncReqConfig::initNewLocalDataStore
+
+#endif // PRECONFIGURED_SYNCREQUESTS
+
+
+// Implementation of TAgentConfig
+// ==============================
+
+
+TAgentConfig::TAgentConfig(const char* aName, TConfigElement *aParentElement) :
+  inherited(aName,aParentElement)
+{
+  clear();
+} // TAgentConfig::TAgentConfig
+
+
+TAgentConfig::~TAgentConfig()
+{
+  clear();
+} // TAgentConfig::~TAgentConfig
+
+
+// init defaults
+void TAgentConfig::clear(void)
+{
+  // clear inherited  
+  inherited::clear();
+       // Note: we always clear both client and server fields - even if we'll only use one set later
+       #ifdef SYSYNC_CLIENT
+  // init client auth defaults (note that these MUST correspond with the defaults set by loadRemoteParams() !!!
+  fAssumedServerAuth=auth_none; // start with no auth
+  fAssumedServerAuthEnc=fmt_chr; // start with char encoding
+  fAssumedNonce.erase(); // start with no nonce
+  // auth retry options (mainly for stupid servers like SCTS)
+  #ifdef SCTS_COMPATIBILITY_HACKS
+  fNewSessionForAuthRetry=false;
+  fNoRespURIForAuthRetry=false;
+  #else
+  fNewSessionForAuthRetry=true; // all production Synthesis clients had it hardcoded (ifdeffed) this way until 2.9.8.7
+  fNoRespURIForAuthRetry=true; // all production Synthesis clients had it hardcoded (ifdeffed) this way until 2.9.8.7
+  #endif
+  fSmartAuthRetry=true; // try to be smart and try different auth retry (different from fNewSessionForAuthRetry/fNoRespURIForAuthRetry) if first attempts fail
+  // other defaults
+  fPutDevInfAtSlowSync=true; // smartner server needs it, and it does not harm so we have it on by default
+  #ifndef NO_LOCAL_DBLOGIN
+  fLocalDBUser.erase();
+  fLocalDBPassword.erase();
+  fNoLocalDBLogin=false;
+  #endif
+  #ifdef PRECONFIGURED_SYNCREQUESTS
+  fEncoding=SML_XML; // default to more readable XML
+  fServerUser.erase();
+  fServerPassword.erase();
+  fServerURI.erase();
+  fTransportUser.erase();
+  fTransportPassword.erase();
+  fSocksHost.erase();
+  fProxyHost.erase();
+  fProxyUser.erase();
+  fProxyPassword.erase();
+  // remove sync db specifications
+  TSyncReqList::iterator pos;
+  for(pos=fSyncRequests.begin();pos!=fSyncRequests.end();pos++)
+    delete *pos;
+  fSyncRequests.clear();
+  #endif
+  // clear inherited
+  inherited::clear();
+  // modify timeout after inherited sets it
+  fSessionTimeout=DEFAULT_CLIENTSESSIONTIMEOUT;
+  // SyncML version support
+  fAssumedServerVersion=MAX_SYNCML_VERSION; // try with highest version we support
+  fMaxSyncMLVersionSupported=MAX_SYNCML_VERSION; // support what we request (overrides session default)
+  #endif
+  #ifdef SYSYNC_SERVER
+  // init server defaults
+  fRequestedAuth = auth_md5;
+  fRequiredAuth = auth_md5;
+  fAutoNonce = true;
+  fConstantNonce.erase();
+  fExternalURL.erase();
+  fMaxGUIDSizeSent = 32; // reasonable size, but prevent braindamaged Exchange-size IDs to be sent
+  fUseRespURI = true;
+  fRespURIOnlyWhenDifferent = true;
+  // modify timeout after inherited sets it
+  fSessionTimeout=DEFAULT_SERVERSESSIONTIMEOUT;
+  #endif
+} // TAgentConfig::clear
+
+
+#ifndef HARDCODED_CONFIG
+
+// config element parsing
+bool TAgentConfig::localStartElement(const char *aElementName, const char **aAttributes, sInt32 aLine)
+{
+  if (IS_CLIENT) {
+         // check the client elements
+       #ifdef SYSYNC_CLIENT
+    // - defaults for starting a session
+    if (strucmp(aElementName,"defaultsyncmlversion")==0)
+      expectEnum(sizeof(fAssumedServerVersion),&fAssumedServerVersion,SyncMLVersionNames,numSyncMLVersions);
+    else if (strucmp(aElementName,"defaultauth")==0)
+      expectEnum(sizeof(fAssumedServerAuth),&fAssumedServerAuth,authTypeNames,numAuthTypes);
+    else if (strucmp(aElementName,"defaultauthencoding")==0)
+      expectEnum(sizeof(fAssumedServerAuthEnc),&fAssumedServerAuthEnc,encodingFmtSyncMLNames,numFmtTypes);
+    else if (strucmp(aElementName,"defaultauthnonce")==0)
+      expectString(fAssumedNonce);
+    else if (strucmp(aElementName,"newsessionforretry")==0)
+      expectBool(fNewSessionForAuthRetry);
+    else if (strucmp(aElementName,"originaluriforretry")==0)
+      expectBool(fNoRespURIForAuthRetry);
+    else if (strucmp(aElementName,"smartauthretry")==0)
+      expectBool(fSmartAuthRetry);
+    // - other options
+    else if (strucmp(aElementName,"putdevinfatslowsync")==0)
+      expectBool(fPutDevInfAtSlowSync);
+    else if (strucmp(aElementName,"fakedeviceid")==0)
+      expectString(fFakeDeviceID);
+    else
+    #ifndef NO_LOCAL_DBLOGIN
+    if (strucmp(aElementName,"localdbuser")==0)
+      expectString(fLocalDBUser);
+    else if (strucmp(aElementName,"localdbpassword")==0)
+      expectString(fLocalDBPassword);
+    else if (strucmp(aElementName,"nolocaldblogin")==0)
+      expectBool(fNoLocalDBLogin);
+    else
+    #endif
+    // serverURL is always available to allow define fixed URL in config that can't be overridden in profiles
+    if (strucmp(aElementName,"serverurl")==0)
+      expectString(fServerURI);
+    else
+    #ifdef PRECONFIGURED_SYNCREQUESTS
+    if (strucmp(aElementName,"syncmlencoding")==0)
+      expectEnum(sizeof(fEncoding),&fEncoding,SyncMLEncodingNames,numSyncMLEncodings);
+    else if (strucmp(aElementName,"serveruser")==0)
+      expectString(fServerUser);
+    else if (strucmp(aElementName,"serverpassword")==0)
+      expectString(fServerPassword);
+    else if (strucmp(aElementName,"sockshost")==0)
+      expectString(fSocksHost);
+    else if (strucmp(aElementName,"proxyhost")==0)
+      expectString(fProxyHost);
+    else if (strucmp(aElementName,"proxyuser")==0)
+      expectString(fProxyUser);
+    else if (strucmp(aElementName,"proxypassword")==0)
+      expectString(fProxyPassword);
+    else if (strucmp(aElementName,"transportuser")==0)
+      expectString(fTransportUser);
+    else if (strucmp(aElementName,"transportpassword")==0)
+      expectString(fTransportPassword);
+    // - Sync DB specification
+    else if (strucmp(aElementName,"syncrequest")==0) {
+      // definition of a new datastore
+      const char* nam = getAttr(aAttributes,"datastore");
+      if (!nam) {
+        ReportError(true,"syncrequest missing 'datastore' attribute");
+      }
+      else {
+        // search datastore
+        TLocalDSConfig *localDSCfgP = getLocalDS(nam);
+        if (!localDSCfgP)
+          return fail("unknown local datastore '%s' specified",nam);
+        // create new syncDB config linked to that datastore
+        TSyncReqConfig *syncreqcfgP = new TSyncReqConfig(localDSCfgP,this);
+        // - save in list
+        fSyncRequests.push_back(syncreqcfgP);
+        // - let element handle parsing
+        expectChildParsing(*syncreqcfgP);
+      }
+    }
+    else
+    #endif
+       // - none known here
+      return inherited::localStartElement(aElementName,aAttributes,aLine);
+    #endif // SYSYNC_CLIENT
+  }
+  else {
+       #ifdef SYSYNC_SERVER
+    // check the server elements
+    if (strucmp(aElementName,"requestedauth")==0)
+      expectEnum(sizeof(fRequestedAuth),&fRequestedAuth,authTypeNames,numAuthTypes);
+    else if (strucmp(aElementName,"requiredauth")==0)
+      expectEnum(sizeof(fRequiredAuth),&fRequiredAuth,authTypeNames,numAuthTypes);
+    // here to maintain compatibility with old pre 1.0.5.3 config files
+    else if (strucmp(aElementName,"reqiredauth")==0)
+      expectEnum(sizeof(fRequiredAuth),&fRequiredAuth,authTypeNames,numAuthTypes);
+    else if (strucmp(aElementName,"autononce")==0)
+      expectBool(fAutoNonce);
+    else if (strucmp(aElementName,"constantnonce")==0)
+      expectString(fConstantNonce);
+    else if (strucmp(aElementName,"externalurl")==0)
+      expectString(fExternalURL);
+    else if (strucmp(aElementName,"maxguidsizesent")==0)
+      expectUInt16(fMaxGUIDSizeSent);
+    else if (strucmp(aElementName,"sendrespuri")==0)
+      expectBool(fUseRespURI);
+    else if (strucmp(aElementName,"respurionlywhendifferent")==0)
+      expectBool(fRespURIOnlyWhenDifferent);
+    // - none known here
+    else
+      return inherited::localStartElement(aElementName,aAttributes,aLine);
+       #endif // SYSYNC_SERVER
+  }
+  // ok
+  return true;
+} // TAgentConfig::localStartElement
+
+#endif // HARDCODED_CONFIG
+
+
+// resolve
+void TAgentConfig::localResolve(bool aLastPass)
+{
+  if (aLastPass) {
+       if (IS_CLIENT) {
+      #ifdef SYSYNC_CLIENT
+      #ifdef PRECONFIGURED_SYNCREQUESTS
+      // - resolve requests
+      TSyncReqList::iterator pos;
+      for(pos=fSyncRequests.begin();pos!=fSyncRequests.end();pos++)
+        (*pos)->Resolve(aLastPass);
+      #endif
+      #endif // SYSYNC_CLIENT
+    }
+    else {
+      #ifdef SYSYNC_SERVER
+      if (!fAutoNonce && fConstantNonce.empty())
+        ReportError(false,"Warning: 'constantnonce' should be defined when 'autononce' is not set");
+      #endif // SYSYNC_SERVER
+    }
+  }
+  // resolve inherited
+  inherited::localResolve(aLastPass);
+} // TAgentConfig::localResolve
+
+
+
+// Implementation of TSyncAgent
+// =============================
+
+
+// constructor
+TSyncAgent::TSyncAgent(
+  TSyncAppBase *aAppBaseP,
+  TSyncSessionHandle *aSessionHandleP,
+  const char *aSessionID // a session ID
+) :
+  TSyncSession(aAppBaseP,aSessionID)  
+{
+       if (IS_CLIENT) {
+               #ifdef SYSYNC_CLIENT
+    #ifdef HARD_CODED_SERVER_URI
+    fNoCRCPrefixLen=0;
+    #endif
+         #ifdef ENGINE_LIBRARY
+               // engine
+       fClientEngineState = ces_idle;
+    #endif
+    // reset session now to get correct initial state
+    InternalResetSession();
+    // restart with session numbering at 1 (incremented before use)
+    fClientSessionNo=0;  
+               #endif // SYSYNC_CLIENT
+  }
+  else {
+               #ifdef SYSYNC_SERVER
+    // init answer buffer
+    fBufferedAnswer = NULL;
+    fBufferedAnswerSize = 0;
+    // reset data counts
+    fIncomingBytes = 0;
+    fOutgoingBytes = 0;
+         #ifdef ENGINE_LIBRARY
+    // engine
+    fServerEngineState = ses_needdata;
+    fRequestSize = 0;
+    #endif
+    // init own stuff
+    InternalResetSession();
+    // save session handle
+    fSessionHandleP = aSessionHandleP; // link to handle
+    // get config defaults
+    TAgentConfig *configP = static_cast<TAgentConfig *>(aAppBaseP->getRootConfig()->fAgentConfigP);
+    fUseRespURI = configP->fUseRespURI;
+    // create all locally available datastores from config
+    TLocalDSList::iterator pos;
+    for (pos=configP->fDatastores.begin(); pos!=configP->fDatastores.end(); pos++) {
+      // create the datastore
+      addLocalDataStore(*pos);
+    }
+    #endif // SYSYNC_SERVER
+  }
+} // TSyncAgent::TSyncAgent
+
+
+// destructor
+TSyncAgent::~TSyncAgent()
+{
+       if (IS_CLIENT) {
+    // make sure everything is terminated BEFORE destruction of hierarchy begins
+    TerminateSession();
+  }
+  else {
+       #ifdef SYSYNC_SERVER
+    // forget any buffered answers
+    bufferAnswer(NULL,0);
+    // reset session
+    InternalResetSession();
+    // show session data transfer
+    PDEBUGPRINTFX(DBG_HOT,(
+      "Session data transfer statistics: incoming bytes=%ld, outgoing bytes=%ld",
+      (long)fIncomingBytes,
+      (long)fOutgoingBytes
+    ));
+    // DO NOT remove session from dispatcher here,
+    //   this is the task of the dispatcher itself!
+    CONSOLEPRINTF(("Terminated SyncML session (server id=%s)\n",getLocalSessionID()));
+    // show end of session in global level
+    POBJDEBUGPRINTFX(getSyncAppBase(),DBG_HOT,(
+      "TSyncAgent::~TSyncAgent: Deleted SyncML session (local session id=%s)",
+      getLocalSessionID()
+    ));
+               #endif // SYSYNC_SERVER
+  }
+} // TSyncAgent::~TSyncAgent
+
+
+// Terminate session
+void TSyncAgent::TerminateSession()
+{
+  #ifdef SYSYNC_CLIENT
+  if (IS_CLIENT && !fTerminated) {
+    InternalResetSession();
+    #ifdef ENGINE_LIBRARY
+    // switch state to done to prevent any further activity via SessionStep()
+    fClientEngineState = ces_done;
+    #endif
+  }
+  #endif // SYSYNC_CLIENT
+  inherited::TerminateSession();
+} // TSyncAgent::TerminateSession
+
+
+
+
+void TSyncAgent::InternalResetSession(void)
+{
+       if (IS_CLIENT) {
+       #ifdef SYSYNC_CLIENT
+    // use remote URI as specified to start a session
+    fRespondURI = fRemoteURI;
+    #ifdef HARD_CODED_SERVER_URI
+    #if defined(CUSTOM_URI_SUFFIX) && !defined(HARD_CODED_SERVER_URI_LEN)
+    #error "HARD_CODED_SERVER_URI_LEN must be defined when using CUSTOM_URI_SUFFIX"
+    #endif
+    #ifdef HARD_CODED_SERVER_URI_LEN
+    // only part of URL must match (max HARD_CODED_SERVER_URI_LEN chars will be added, less if URI is shorter)
+    fServerURICRC = addNameToCRC(SYSER_CRC32_SEED, fRemoteURI.c_str()+fNoCRCPrefixLen, false, HARD_CODED_SERVER_URI_LEN);
+    #else
+    // entire URL (except prefix) must match
+    fServerURICRC = addNameToCRC(SYSER_CRC32_SEED, fRemoteURI.c_str()+fNoCRCPrefixLen, false);
+    #endif
+    #endif
+    // set SyncML version
+    // Note: will be overridden with call to loadRemoteParams()
+    fSyncMLVersion = syncml_vers_unknown; // unknown
+    // will be cleared to suppress automatic use of DS 1.2 SINCE/BEFORE filters
+    // (e.g. for date range in func_SetDaysRange())
+    fServerHasSINCEBEFORE = true;
+    // no outgoing alert 222 sent so far
+    fOutgoingAlert222Count = 0;
+    #endif
+  }
+  else {
+               #ifdef SYSYNC_SERVER
+    // %%% remove this as soon as Server is 1.1 compliant
+    //fSyncMLVersion=syncml_vers_1_0; // only accepts 1.0 for now %%%%
+    #endif  
+  }
+} // TSyncAgent::InternalResetSession
+
+
+// Virtual version
+void TSyncAgent::ResetSession(void)
+{
+  // let ancestor do its stuff
+  TSyncSession::ResetSession();
+  // do my own stuff (and probably modify settings of ancestor!)
+  InternalResetSession();
+} // TSyncAgent::ResetSession
+
+
+bool TSyncAgent::MessageStarted(SmlSyncHdrPtr_t aContentP, TStatusCommand &aStatusCommand, bool aBad)
+{
+       if (IS_CLIENT) {
+               #ifdef SYSYNC_CLIENT
+    return ClientMessageStarted(aContentP,aStatusCommand,aBad);
+               #endif // SYSYNC_CLIENT
+  }
+  else {
+    #ifdef SYSYNC_SERVER
+    return ServerMessageStarted(aContentP,aStatusCommand,aBad);
+    #endif // SYSYNC_SERVER
+  }
+}
+
+void TSyncAgent::MessageEnded(bool aIncomingFinal)
+{
+       if (IS_CLIENT) {
+               #ifdef SYSYNC_CLIENT
+    ClientMessageEnded(aIncomingFinal);
+               #endif // SYSYNC_CLIENT
+  }
+  else {
+    #ifdef SYSYNC_SERVER
+    ServerMessageEnded(aIncomingFinal);
+    #endif // SYSYNC_SERVER
+  }
+}
+
+
+// starting with engine version 2.0.8.7 a client's device ID (in devinf) is no longer
+// a constant string, but the device's unique ID
+string TSyncAgent::getDeviceID(void)
+{
+  if (fLocalURI.empty()) {
+       if (IS_SERVER)
+           return SYSYNC_SERVER_DEVID; // return default ID
+       else    
+           return SYSYNC_CLIENT_DEVID; // return default ID
+  }
+  else
+    return fLocalURI;
+} // TSyncAgent::getDeviceID
+
+
+// ask syncappbase for device type
+string TSyncAgent::getDeviceType(void)
+{
+  // taken from configuration or default for engine type (client/server)
+  return getSyncAppBase()->getDevTyp();
+} // TSyncAgent::getDeviceType
+
+
+#ifdef SYSYNC_CLIENT
+
+// initialize the client session and link it with the SML toolkit
+localstatus TSyncAgent::InitializeSession(uInt32 aProfileSelector, bool aAutoSyncSession)
+{
+  localstatus sta;
+
+  // Select profile now (before creating instance, as encoding is dependent on profile)
+  sta=SelectProfile(aProfileSelector, aAutoSyncSession);
+  if (sta) return sta;
+  // Start a SyncML toolkit instance now and set the encoding from config
+  InstanceID_t myInstance;
+  if (!getSyncAppBase()->newSmlInstance(
+    getEncoding(),
+    getRootConfig()->fLocalMaxMsgSize * 2, // twice the message size
+    myInstance
+  )) {
+    return LOCERR_SMLFATAL;
+  }
+  // let toolkit know the session pointer
+  if (getSyncAppBase()->setSmlInstanceUserData(myInstance,this)!=SML_ERR_OK) // toolkit must know session (as userData)
+    return LOCERR_SMLFATAL;
+  // remember the instance myself
+  setSmlWorkspaceID(myInstance); // session must know toolkit workspace
+  // done
+  return LOCERR_OK;
+} // TSyncAgent::InitializeSession
+
+
+
+// select a profile (returns false if profile not found)
+// Note: base class just tries to retrieve information from
+//       config
+localstatus TSyncAgent::SelectProfile(uInt32 aProfileSelector, bool aAutoSyncSession)
+{
+  #ifndef PRECONFIGURED_SYNCREQUESTS
+  // no profile settings in config -> error
+  return LOCERR_NOCFG;
+  #else
+  // get profile settings from config
+  TAgentConfig *configP = static_cast<TAgentConfig *>(getRootConfig()->fAgentConfigP);
+  // - get encoding
+  fEncoding=configP->fEncoding; // SyncML encoding
+  // - set server access details
+  fRemoteURI=configP->fServerURI; // Remote URI = Server URI
+  fTransportUser=configP->fTransportUser; // transport layer user (e.g. HTTP auth)
+  fTransportPassword=configP->fTransportPassword; // transport layer password (e.g. HTTP auth)
+  fServerUser=configP->fServerUser; // Server layer authentification user name
+  fServerPassword=configP->fServerPassword; // Server layer authentification password
+  #ifndef NO_LOCAL_DBLOGIN
+  fLocalDBUser=configP->fLocalDBUser; // Local DB authentification user name (empty if local DB is single user)
+  fNoLocalDBLogin=configP->fNoLocalDBLogin; // if set, no local DB auth takes place, but fLocalDBUser is used as userkey (depending on DB implementation)
+  fLocalDBPassword=configP->fLocalDBPassword; // Local DB authentification password
+  #endif
+  fProxyHost=configP->fProxyHost; // Proxy host
+  fSocksHost=configP->fSocksHost; // Socks host
+  fProxyUser=configP->fProxyUser;
+  fProxyPassword=configP->fProxyPassword;
+  // Reset session after profile change
+  // and also remove any datastores we might have
+  ResetAndRemoveDatastores();
+  // if tunnel, that's all for now
+  if (aProfileSelector==TUNNEL_PROFILE_ID) return LOCERR_OK;
+  // - create and init datastores needed for this session from config
+  //   Note: probably config has no sync requests, but they are created later
+  //         programmatically
+  TSyncReqList::iterator pos;
+  for (pos=configP->fSyncRequests.begin(); pos!=configP->fSyncRequests.end(); pos++) {
+    // create and init the datastore
+    fLocalDataStores.push_back(
+      (*pos)->initNewLocalDataStore(this)
+    );
+  }
+  // create "new" session ID (derivates will do this better)
+  fClientSessionNo++;
+  return LOCERR_OK;
+  #endif
+} // TSyncAgent::SelectProfile
+
+
+// make sure we are logged in to local datastore
+localstatus TSyncAgent::LocalLogin(void)
+{
+  #ifndef NO_LOCAL_DBLOGIN
+  if (!fNoLocalDBLogin && !fLocalDBUser.empty()) {
+    // check authorisation (login to correct user) in local DB
+    if (!SessionLogin(fLocalDBUser.c_str(),fLocalDBPassword.c_str(),sectyp_clearpass,fRemoteURI.c_str())) {
+      return localError(401); // done & error
+    }
+  }
+  #endif
+  return LOCERR_OK;
+} // TSyncAgent::LocalLogin
+
+
+
+// process message in the instance buffer
+localstatus TSyncAgent::processAnswer(void)
+{
+  InstanceID_t myInstance = getSmlWorkspaceID();
+  Ret_t err;
+
+  // now process data
+  DEBUGPRINTF(("===> now calling smlProcessData"));
+  #ifdef SYDEBUG
+  MemPtr_t data = NULL;
+  MemSize_t datasize;
+  smlPeekMessageBuffer(getSmlWorkspaceID(), false, &data, &datasize);
+  #endif  
+  fIgnoreMsgErrs=false;
+  err=smlProcessData(
+    myInstance,
+    SML_ALL_COMMANDS
+  );
+  if (err) {
+    // dump the message that failed to process
+    #ifdef SYDEBUG
+    if (data) DumpSyncMLBuffer(data,datasize,false,err);
+    #endif    
+       if (!fIgnoreMsgErrs) {
+      PDEBUGPRINTFX(DBG_ERROR,("===> smlProcessData failed, returned 0x%hX",(sInt16)err));
+      // other problem or already using SyncML 1.0 --> error
+      return LOCERR_PROCESSMSG;
+    }
+  }
+  // now check if this is a session restart
+  if (isStarting()) {
+    // this is still the beginning of a session
+    return LOCERR_SESSIONRST;
+  }
+  return LOCERR_OK;
+} // TSyncAgentBase::processAnswer
+
+
+
+// let session produce (or finish producing) next message into
+// SML workspace
+// - returns aDone if no answer needs to be sent (=end of session)
+// - returns 0 if successful
+// - returns SyncML status code if unsucessfully aborted session
+localstatus TSyncAgent::NextMessage(bool &aDone)
+{
+  TLocalDataStorePContainer::iterator pos;
+  TSyError status;
+
+  TP_START(fTPInfo,TP_general); // could be new thread
+  // default to not continuing
+  aDone=true;
+  #ifdef PROGRESS_EVENTS
+  // check for user suspend
+  if (!getSyncAppBase()->NotifyProgressEvent(pev_suspendcheck)) {
+    SuspendSession(LOCERR_USERSUSPEND);
+  }
+  #endif
+  // done if session was aborted by last received commands
+  if (isAborted()) return getAbortReasonStatus(); // done & error
+  // check package state
+  if (fOutgoingState==psta_idle) {
+    // if suspended here, we'll just stop - nothing has happened yet
+    if (isSuspending()) {
+      AbortSession(fAbortReasonStatus,true);
+      return getAbortReasonStatus();
+    }
+    // start of an entirely new client session
+    #ifdef HARD_CODED_SERVER_URI
+    // extra check to limit hacking
+    if (fServerURICRC != SERVER_URI_CRC) {
+      // someone has tried to change the URI
+      DEBUGPRINTFX(DBG_ERROR,("hardcoded Server URI CRC mismatch"));
+      return LOCERR_LIMITED; // user will not know what this means, but we will
+    }
+    #endif
+    // - check if we have client requests
+    if (fLocalDataStores.size()<1) {
+      PDEBUGPRINTFX(DBG_ERROR,("No datastores defined to sync with"));
+      return LOCERR_NOCFG;
+    }
+    // %%% later, we could probably load cached info about
+    //     server requested auth, devinf etc. here
+    // use remote URI as specified to start a session
+    fRespondURI=fRemoteURI;
+    // get default params for sending first message to remote
+    // Note: may include remote flag settings that influence creation of my own ID below, that's why we do it now here
+    loadRemoteParams();
+    // get info about my own URI, whatever that is
+    #ifndef HARDCODED_CONFIG
+    if (!static_cast<TAgentConfig *>(getRootConfig()->fAgentConfigP)->fFakeDeviceID.empty()) {
+      // return fake Device ID if we have one defined in the config file (useful for testing)
+      fLocalURI = static_cast<TAgentConfig *>(getRootConfig()->fAgentConfigP)->fFakeDeviceID;
+    }
+    else
+    #endif
+    {
+      if (!getLocalDeviceID(fLocalURI) || devidWithUserHash()) {
+        // Device ID is not really unique, make a hash including user name to make it pseudo-unique
+        // create MD5 hash from non-unique ID and user name
+        // Note: when compiled with GUARANTEED_UNIQUE_DEVICID, devidWithUserHash() is always false.
+        md5::SYSYNC_MD5_CTX context;
+        uInt8 digest[16]; // for MD5 digest
+        md5::Init (&context);
+        // - add what we got for ID
+        md5::Update (&context, (uInt8 *)fLocalURI.c_str(), fLocalURI.size());
+        // - add user name, if any
+        if (fLocalURI.size()>0) md5::Update (&context, (uInt8 *)fServerUser.c_str(), fServerUser.size());
+        // - done
+        md5::Final (digest, &context);
+        // now make hex string of that
+        fLocalURI = devidWithUserHash() ? 'x' : 'X'; // start with X to document this special case (lowercase = forced by remoteFlag)
+        for (int n=0; n<16; n++) {
+          AppendHexByte(fLocalURI,digest[n]);
+        }
+      }
+    }
+    // get my own name (if any)
+    getPlatformString(pfs_device_name,fLocalName);
+    // override some of these if not set by loadRemoteParams()
+    if (fSyncMLVersion==syncml_vers_unknown)
+      fSyncMLVersion=static_cast<TAgentConfig *>(getRootConfig()->fAgentConfigP)->fAssumedServerVersion;
+    if (fRemoteRequestedAuth==auth_none)
+      fRemoteRequestedAuth=static_cast<TAgentConfig *>(getRootConfig()->fAgentConfigP)->fAssumedServerAuth;
+    if (fRemoteRequestedAuthEnc==fmt_chr)
+      fRemoteRequestedAuthEnc=static_cast<TAgentConfig *>(getRootConfig()->fAgentConfigP)->fAssumedServerAuthEnc;
+    if (fRemoteNonce.empty())
+      fRemoteNonce=static_cast<TAgentConfig *>(getRootConfig()->fAgentConfigP)->fAssumedNonce;
+
+    // we are not yet authenticated for the entire session
+    fNeedAuth=true;
+    // now ready for init
+    fOutgoingState=psta_init; // %%%% could also set psta_initsync for combined init/sync
+    fIncomingState=psta_idle; // remains idle until first answer SyncHdr with OK status is received
+    fInProgress=true; // assume in progress
+    // set session ID string
+    StringObjPrintf(fSynchdrSessionID,"%hd",(sInt16)fClientSessionNo);
+    // now we have a session id, can now display debug stuff
+    #ifdef SYDEBUG
+    string t;
+    StringObjTimestamp(t,getSystemNowAs(TCTX_SYSTEM));
+    PDEBUGPRINTFX(DBG_HOT,("\n[%s] =================> Starting new client session",t.c_str()));
+    #endif
+    // - make sure we are logged into the local database (if needed)
+    status=LocalLogin();
+    if (status!=LOCERR_OK) return status;
+    // create header for first message no noResp
+    issueHeader(false);
+  }
+  else {
+    // check for proper end of session (caused by MessageEnded analysis)
+    if (!fInProgress) {
+      // give an opportunity to let make outgoing message end and flush xml end message 
+      FinishMessage(true, false);  
+      // end sync in all datastores (save anchors etc.)
+      PDEBUGPRINTFX(DBG_PROTO,("Successful end of session -> calling engFinishDataStoreSync() for datastores now"));
+      for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos)
+        (*pos)->engFinishDataStoreSync(); // successful end
+      PDEBUGPRINTFX(DBG_PROTO,("Session not any more in progress: NextMessage() returns OK status=0"));
+      return LOCERR_OK; // done & ok
+    }
+  }
+  // check expired case
+  #ifdef APP_CAN_EXPIRE
+  if (getClientBase()->fAppExpiryStatus!=LOCERR_OK) {
+    PDEBUGPRINTFX(DBG_ERROR,("Evaluation Version expired - Please contact Synthesis AG for release version"));
+    return getClientBase()->fAppExpiryStatus; // payment required, done & error
+  }
+  #endif
+  if (fOutgoingState==psta_init || fOutgoingState==psta_initsync) {
+    // - if suspended in init, nothing substantial has happened already, so just exit
+    if (isSuspending() && fOutgoingState==psta_init) {
+      AbortSession(fAbortReasonStatus,true);
+      return getAbortReasonStatus();
+    }
+    // - prepare Alert(s) for databases to sync
+    bool anyfirstsyncs=false;
+    bool anyslowsyncs=false;
+    TLocalEngineDS *localDS;
+    for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
+      // prepare alert
+      localDS = *pos;
+      status=localDS->engPrepareClientSyncAlert(NULL); // not as superdatastore
+      if (status!=LOCERR_OK) {
+        // local database error
+        return localError(status); // not found
+      }
+      if (localDS->fFirstTimeSync) anyfirstsyncs=true;
+      if (localDS->fSlowSync) anyslowsyncs=true;
+    }
+    // send devinf in Put command right away with init message if either...
+    // - mustSendDevInf() returns true signalling an external condition that suggests sending devInf (like changed config)
+    // - any datastore is doing first time sync
+    // - fPutDevInfAtSlowSync is true and any datastore is doing slow sync
+    if (
+       mustSendDevInf() ||
+      anyfirstsyncs ||
+      (anyslowsyncs && static_cast<TAgentConfig *>(getRootConfig()->fAgentConfigP)->fPutDevInfAtSlowSync)
+    ) {
+      TDevInfPutCommand *putcmdP = new TDevInfPutCommand(this);
+      issueRootPtr(putcmdP);
+    }
+    // try to load devinf from cache (only if we don't know it already)
+    if (!fRemoteDataStoresKnown || !fRemoteDataTypesKnown) {
+      SmlDevInfDevInfPtr_t devinfP;
+      if (loadRemoteDevInf(getRemoteURI(),devinfP)) {
+        // we have cached devinf, analyze it now
+        analyzeRemoteDevInf(devinfP);
+      }
+    }
+    // GET the server's info if server didn't send it and we haven't cached at least the datastores
+    if (!fRemoteDataStoresKnown) {
+      // if we know datastores here, but not types, this means that remote does not have
+      // CTCap, so it makes no sense to issue a GET again.
+      #ifndef NO_DEVINF_GET
+      PDEBUGPRINTFX(DBG_REMOTEINFO,("Nothing known about server, request DevInf using GET command"));
+      TGetCommand *getcommandP = new TGetCommand(this);
+      getcommandP->addTargetLocItem(SyncMLDevInfNames[fSyncMLVersion]);
+      string devinftype=SYNCML_DEVINF_META_TYPE;
+      addEncoding(devinftype);
+      getcommandP->setMeta(newMetaType(devinftype.c_str()));
+      ISSUE_COMMAND_ROOT(this,getcommandP);
+      #endif
+    }
+    // - create Alert(s) for databases to sync
+    for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
+      // create alert for non-subdatastores
+      localDS = *pos;
+      if (!localDS->isSubDatastore()) {
+        TAlertCommand *alertcmdP;
+        status=localDS->engGenerateClientSyncAlert(alertcmdP);
+        if (status!=0) {
+          // local database error
+          return status; // not found
+        }
+        ///%%%% unneeded (probably got here by copy&paste accidentally): if (localDS->fFirstTimeSync) anyfirstsyncs=true;
+        // issue alert
+        issueRootPtr(alertcmdP);
+      }
+    }
+    // append sync phase if we have combined init/sync
+    if (fOutgoingState==psta_initsync) fOutgoingState=psta_sync;
+  }
+  // process sync/syncop/map generating phases after init
+  if (!isSuspending()) {
+    // normal, session continues
+    if (fOutgoingState==psta_sync) {
+      // hold back sync until server has finished first package (init or initsync)
+      if (fIncomingState==psta_sync || fIncomingState==psta_initsync) {
+        // start sync for alerted datastores
+        for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
+          // Note: some datastores might be aborted due to unsuccessful alert.
+          if ((*pos)->isActive()) {
+               // prepare engine for sync (%%% new routine in 3.2.0.3, summarizing engInitForSyncOps() and
+            // switching to dssta_dataaccessstarted, i.e. loading sync set), but do in only once
+            if (!((*pos)->testState(dssta_syncsetready))) {
+               // not yet started
+                       status = (*pos)->engInitForClientSync();
+                   if (status!=LOCERR_OK) {
+                // failed
+                AbortSession(status,true);
+                return getAbortReasonStatus();
+              }
+            }
+            // start or continue (which is largely nop, as continuing works via unfinished sync command)
+            // generating sync items
+            (*pos)->engClientStartOfSyncMessage();
+          }
+        }
+      }
+    }
+    else if (fOutgoingState==psta_map) {
+      // hold back map until server has started sync at least (incominstate >=psta_sync)
+      // NOTE: This is according to the specs, which says that client can begin
+      //   with Map/update status package BEFORE sync package from server is
+      //   completely received.
+      // NOTE: Starfish server expects this and generates a few 222 alerts
+      //   if we wait here, but then goes to map as well
+      //   (so (fIncomingState==psta_map)-version works as well here!
+      // %%%% other version: wait until server has started map phase as well
+      // %%%% if (fIncomingState==psta_map) {
+      if (fIncomingState>=psta_sync) {
+        // start map for synced datastores
+        for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
+          // Note: some datastores might be aborted due to unsuccessful alert.
+          if ((*pos)->isActive()) {
+            // now call datastore to generate map command if not already done
+            (*pos)->engClientStartOfMapMessage(fIncomingState<psta_map);
+          }
+        }
+      }
+    }
+    else if (fOutgoingState==psta_supplement) {
+       // we are waiting for the server to complete a pending phase altough we are already done
+      // with everything we want to send.
+      // -> just generate a Alert 222 and wait for server to complete
+      PDEBUGPRINTFX(DBG_PROTO+DBG_HOT,("Client finished so far, but needs to wait in supplement outgoing state until server finishes phase"));
+    }
+    else if (fOutgoingState!=psta_init) {
+      // NOTE: can be psta_init because "if" begins again after psta_init checking
+      //       to allow psta_init appending psta_sync for combined init/sync
+      // no known state
+      return 9999; // %%%%%
+    }
+  } // if not suspended
+
+  // security only: exit here if session got aborted in between
+  if (isAborted())
+    return getAbortReasonStatus(); // done & error
+  if (!fInProgress)
+    return 9999; // that's fine with us
+  // now, we know that we will (most probably) send a message, so default for aDone is false from now on
+  aDone=false;
+  bool outgoingfinal;
+
+  // check for suspend
+  if (isSuspending()) {
+    // make sure we send a Suspend Alert
+    TAlertCommand *alertCmdP = new TAlertCommand(this,NULL,(uInt16)224);
+    // - we just put local and remote URIs here
+    SmlItemPtr_t itemP = newItem();
+    itemP->target = newLocation(fRemoteURI.c_str());
+    itemP->source = newLocation(fLocalURI.c_str());
+    alertCmdP->addItem(itemP);
+    ISSUE_COMMAND_ROOT(this,alertCmdP);
+    // outgoing message is final, regardless of any session state
+    outgoingfinal=true;
+    MarkSuspendAlertSent(true);
+  }
+  else {
+    // Determine if package can be final and if we need an 222 Alert
+    // NOTE: if any commands were interruped or not sent due to outgoing message
+    //       size limits, FinishMessage() will prevent final anyway, so no
+    //       separate checking for enOfSync or endOfMap is needed.
+    // - can finalize message when server has at least started answering current package
+    //   OR if this is the first message (probably repeatedly) sent
+    outgoingfinal = fIncomingState >= fOutgoingState || fIncomingState==psta_idle;
+    if (outgoingfinal) {
+      // allow early success here in case of nothing to respond, and nothing pending
+      // StarFish server does need this...
+      if (!fNeedToAnswer) {
+        if (hasPendingCommands()) {
+          // we have pending commands, cannot be final message
+          outgoingfinal=false;
+        }
+        else {
+          // no pending commands -> we're done now
+          PDEBUGPRINTFX(DBG_PROTO,("Early end of session (nothing to send to server any more) -> calling engFinishDataStoreSync() for datastores now"));
+          // - end sync in all datastores (save anchors etc.)
+          for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos)
+            (*pos)->engFinishDataStoreSync(); // successful end
+          PDEBUGPRINTFX(DBG_PROTO,("Session not any more in progress: NextMessage() returns OK status=0"));
+          // done & ok
+          aDone=true;
+          return LOCERR_OK;
+        }
+      }
+    }
+  }
+  /* A dummy alert indicates this is a message with only alert222 request*/
+  bool dummyAlert = false;
+  if (!outgoingfinal) {
+    // - send Alert 222 if we need to continue package but have nothing to send
+    //   (or ALWAYS_CONTINUE222 defined)
+    #ifndef ALWAYS_CONTINUE222
+    if (!fNeedToAnswer)
+    #endif
+    {
+      /* End-less loop detection
+       * Some servers will never end and triggers client sends
+       * ALERT222 forever. Detect this scenario and abort the session if
+       * detected.
+       * It is still valid for the server to use ALERT222 to "keep-alive" the
+       * connection.
+       * Therefore the loop detection criteria is:
+       * - Nothing to send except the 222 Alert (!fNeedToAnswer)
+       * - 5 adjacent 222 alerts within 20 seconds
+       * - no status for an actual sync op command received (fOutgoingAlert222Count will be reset by those)
+       *   because a server sending pending status in small chunks could also trigger the detector otherwise
+       */
+      if (!fNeedToAnswer) {
+        dummyAlert = true;
+        if (fOutgoingAlert222Count++ == 0) {
+               // start of 222 loop detection time
+          fLastOutgoingAlert222 = getSystemNowAs(TCTX_UTC);
+        } else if (fOutgoingAlert222Count > 5) {
+          lineartime_t curTime = getSystemNowAs(TCTX_UTC);
+          if (curTime - fLastOutgoingAlert222 < 20*secondToLinearTimeFactor) {
+            PDEBUGPRINTFX(DBG_ERROR,(
+              "Warning: More than 5 consecutive Alert 222 within 20 seconds- "
+              "looks like endless loop, abort session"
+            ));
+            AbortSession(400, false);
+            return getAbortReasonStatus();
+          } else {
+            fOutgoingAlert222Count = 0;
+          }
+        }
+      }
+      // not final, and nothing to answer otherwise: create alert-Command to request more info
+      TAlertCommand *alertCmdP = new TAlertCommand(this,NULL,(uInt16)222);
+      // %%% not clear from spec what has to be in item for 222 alert code
+      //     but there MUST be an Item for the Alert command according to SyncML TK
+      // - we just put local and remote URIs here
+      SmlItemPtr_t itemP = newItem();
+      itemP->target = newLocation(fRemoteURI.c_str());
+      itemP->source = newLocation(fLocalURI.c_str());
+      alertCmdP->addItem(itemP);
+      ISSUE_COMMAND_ROOT(this,alertCmdP);
+    }
+  }
+  // We send a response with no dummy alert, so reset the alert detector
+  if (!dummyAlert) {
+    fOutgoingAlert222Count = 0;
+  }
+
+  // send custom end-of session puts
+  if (!isSuspending() && outgoingfinal && fOutgoingState==psta_map) {
+    // End of outgoing map package; let custom PUTs which may transmit some session statistics etc. happen now
+    issueCustomEndPut();
+  }
+  // message complete, now finish it
+  FinishMessage(
+    outgoingfinal, // allowed if possible
+    false // final not prevented
+  );
+  // Note, now fNewOutgoingPackage is set (by FinishMessage())
+  // if next message will be responded to with a new package
+
+  // debug info
+  #ifdef SYDEBUG
+  if (PDEBUGMASK & DBG_SESSION) {
+    PDEBUGPRINTFX(DBG_SESSION,(
+      "---> NextMessage, outgoing state='%s', incoming state='%s'",
+      PackageStateNames[fOutgoingState],
+      PackageStateNames[fIncomingState]
+    ));
+    for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
+      // Show state of local datastores
+      PDEBUGPRINTFX(DBG_SESSION,(
+        "Local Datastore '%s': %sState=%s, %s%s sync, %s%s",
+        (*pos)->getName(),
+        (*pos)->isAborted() ? "ABORTED - " : "",
+        (*pos)->getDSStateName(),
+        (*pos)->isResuming() ? "RESUMED " : "",
+        (*pos)->fSlowSync ? "SLOW" : "normal",
+        SyncModeDescriptions[(*pos)->fSyncMode],
+        (*pos)->fServerAlerted ? ", Server-Alerted" : ""
+      ));
+    }
+  }
+  PDEBUGENDBLOCK("SyncML_Outgoing");
+  if (getLastIncomingMsgID()>0) {
+    // we have already received an incoming message, so we have started an "SyncML_Incoming" blocks sometime
+    PDEBUGENDBLOCK("SyncML_Incoming"); // terminate debug block of previous incoming message as well
+  }
+  #endif
+  // ok
+  return LOCERR_OK; // ok
+} // TSyncAgent::NextMessage
+
+
+// called after successful decoding of an incoming message
+bool TSyncAgent::ClientMessageStarted(SmlSyncHdrPtr_t aContentP, TStatusCommand &aStatusCommand, bool aBad)
+{
+  // message not authorized by default
+  fMessageAuthorized=false;
+
+  // Check information from SyncHdr
+  if (
+    aBad ||
+    (!(fSynchdrSessionID==smlPCDataToCharP(aContentP->sessionID))) ||
+    (!(fLocalURI==smlSrcTargLocURIToCharP(aContentP->target)))
+  ) {
+    // bad response
+    PDEBUGPRINTFX(DBG_ERROR,(
+      "Bad SyncHeader from Server. Syntax %s, SessionID (rcvd/correct) = '%s' / '%s', LocalURI (rcvd/correct) = '%s' / '%s'",
+      aBad ? "ok" : "BAD",
+      smlPCDataToCharP(aContentP->sessionID),
+      fSynchdrSessionID.c_str(),
+      smlSrcTargLocURIToCharP(aContentP->target),
+      fLocalURI.c_str()
+    ));
+    aStatusCommand.setStatusCode(400); // bad response/request
+    AbortSession(400,true);
+    return false;
+  }
+  // check for suspend: if we are suspended at this point, this means that we have sent the Suspend Alert already
+  // in the previous message (due to user suspend request), so we can now terminate the session
+  if (isSuspending() && isSuspendAlertSent()) {
+    AbortSession(514,true,LOCERR_USERSUSPEND);
+    return false;
+  }
+  // - RespURI (remote URI to respond to)
+  if (aContentP->respURI) {
+    fRespondURI=smlPCDataToCharP(aContentP->respURI);
+    DEBUGPRINTFX(DBG_PROTO,("RespURI set to = '%s'",fRespondURI.c_str()));
+  }
+  // authorization check
+  // Note: next message will be started not before status for last one
+  //       has been processed. Commands issued before will automatically
+  //       be queued by issuePtr()
+  // %%% none for now
+  fSessionAuthorized=true;
+  fMessageAuthorized=true;
+  // returns false on BAD header (but true on wrong/bad/missing cred)
+  return true;
+} // TSyncAgent::ClientMessageStarted
+
+
+// determines new package states and sets fInProgress
+void TSyncAgent::ClientMessageEnded(bool aIncomingFinal)
+{
+  TLocalDataStorePContainer::iterator pos;
+
+  // show status before processing
+  PDEBUGPRINTFX(DBG_SESSION,(
+    "MessageEnded starts   : old outgoing state='%s', old incoming state='%s', %sNeedToAnswer",
+    PackageStateNames[fOutgoingState],
+    PackageStateNames[fIncomingState],
+    fNeedToAnswer ? "" : "NO "
+  ));
+  bool allFromClientOnly=false;
+  // process exceptions
+  if (fAborted) {
+    PDEBUGPRINTFX(DBG_ERROR,("***** Session is flagged 'aborted' -> MessageEnded ends package and session"));
+    fOutgoingState=psta_idle;
+    fIncomingState=psta_idle;
+    fInProgress=false;
+  } // if aborted
+  else if (!fMessageAuthorized) {
+    // not authorized messages will just be ignored, so
+    // nothing changes in states
+    // %%% this will probably not really work, as we would need to repeat the last
+    //     message in this (unlikely) case that fMessageAuthorized is not set for
+    //     a non-first message (first message case is handled in handleHeaderStatus)
+    DEBUGPRINTFX(DBG_ERROR,("***** received Message not authorized, ignore and DONT end package"));
+    fInProgress=true;
+  }
+  else {
+    fInProgress=true; // assume we need to continue
+    // Note: the map phase will not take place, if all datastores are in
+    //       send-to-server-only mode and we are not in non-conformant old
+    //       synthesis-compatible fCompleteFromClientOnly mode.
+    if (!fCompleteFromClientOnly) {
+      // let all local datastores know that message has ended
+      allFromClientOnly=true;
+      for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
+        // check sync modes
+        if ((*pos)->isActive() && (*pos)->getSyncMode()!=smo_fromclient) {
+          allFromClientOnly=false;
+          break;
+        }
+      }
+    }
+    // new outgoing state is determined by the incomingState of this message
+    // (which is the answer to the <final/> message of the previous outgoing package)
+    if (fNewOutgoingPackage && fIncomingState!=psta_idle) {
+      // last message sent was an end-of-package, so next will be a new package
+      if (fIncomingState==psta_init) {
+        // server has responded (or is still responding) to our finished init,
+        // so client enters sync state now (but holds back sync until server
+        // has finished init)
+        fOutgoingState=psta_sync;
+      }
+      else if (fIncomingState==psta_sync || fIncomingState==psta_initsync) {
+        // server has started (or already finished) sending statuses for our
+        // <sync> or its own <sync>
+        // client can enter map state (but holds back maps until server
+        // has finished sync/initsync). In case of allFromClientOnly, we skip the map phase
+        // but only if there is no need to answer.
+        // Otherwise, this is most probably an old (pre 2.9.8.2) Synthesis server that has
+        // sent an empty <sync> (and the status for it has set fNeedToAnswer), so we still
+        // go to map phase.
+        if (allFromClientOnly && !fNeedToAnswer) {
+          fOutgoingState=psta_supplement; // all datastores are from-client-only, skip map phase
+          PDEBUGPRINTFX(DBG_PROTO+DBG_HOT,("All datastores in from-client-only mode, and no need to answer: skip map phase"));
+        }
+        else {
+          fOutgoingState=psta_map; // Some datastores do from-server-only or twoway, so we need a map phase
+          allFromClientOnly=false; // do not skip map phase
+        }
+      }
+      else {
+        // map is finished as well, we might need extra packages just to
+        // finish getting results for map commands
+        fOutgoingState=psta_supplement;
+      }
+    }
+    // New incoming state is simply derived from the incoming state of
+    // this message
+    if (aIncomingFinal && fIncomingState!=psta_idle) {
+      if (fIncomingState==psta_init) {
+        // switch to sync
+        fIncomingState=psta_sync;
+      }
+      else if (fIncomingState==psta_sync || fIncomingState==psta_initsync) {
+        // check what to do
+        if (allFromClientOnly) {
+          // no need to answer and allFromClientOnly -> this is the end of the session
+          fIncomingState=psta_supplement;
+          fInProgress=false; // normally, at end of map answer, we are done
+        }
+        else {
+          fIncomingState=psta_map;
+        }
+      }
+      else {
+        // end of a map phase - end of session (if no fNeedToAnswer)
+        fIncomingState=psta_supplement;
+        // this only ALLOWS ending the session, but it will continue as long
+        // as more than OK for SyncHdr (fNeedToAnswer) must be sent
+        fInProgress=false; // normally, at end of map answer, we are done
+      }
+    }
+    // continue anyway as long as we need to answer
+    if (fNeedToAnswer) fInProgress=true;
+  }
+  // show states
+  PDEBUGPRINTFX(DBG_HOT,(
+    "MessageEnded finishes : new outgoing state='%s', new incoming state='%s', %sNeedToAnswer",
+    PackageStateNames[fOutgoingState],
+    PackageStateNames[fIncomingState],
+    fNeedToAnswer ? "" : "NO "
+  ));
+  // let all local datastores know that message has ended
+  for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
+    // let them know
+    (*pos)->engEndOfMessage();
+    // Show state of local datastores
+    PDEBUGPRINTFX(DBG_HOT,(
+      "Local Datastore '%s': %sState=%s, %s%s sync, %s%s",
+      (*pos)->getName(),
+      (*pos)->isAborted() ? "ABORTED - " : "",
+      (*pos)->getDSStateName(),
+      (*pos)->isResuming() ? "RESUMED " : "",
+      (*pos)->isSlowSync() ? "SLOW" : "normal",
+      SyncModeDescriptions[(*pos)->getSyncMode()],
+      (*pos)->fServerAlerted ? ", Server-Alerted" : ""
+    ));
+  }
+  // thread might end here, so stop profiling
+  TP_STOP(fTPInfo);
+} // TSyncAgent::ClientMessageEnded
+
+
+// get credentials/username to authenticate with remote party, NULL if none
+SmlCredPtr_t TSyncAgent::newCredentialsForRemote(void)
+{
+  if (fNeedAuth) {
+    // generate cretentials from username/password
+    PDEBUGPRINTFX(DBG_PROTO+DBG_USERDATA,("Authenticating with server as user '%s'", fServerUser.c_str()));
+    PDEBUGPRINTFX(DBG_PROTO+DBG_USERDATA+DBG_EXOTIC,("- using nonce '%s'", fRemoteNonce.c_str()));
+    // NOTE: can be NULL when fServerRequestedAuth is auth_none
+    return newCredentials(
+      fServerUser.c_str(),
+      fServerPassword.c_str()
+    );
+  }
+  else {
+    // already authorized, no auth needed
+    return NULL;
+  }
+} // TSyncAgent::newCredentialsForRemote
+
+
+// get client base
+TSyncClientBase *TSyncAgent::getClientBase(void)
+{
+  return static_cast<TSyncClientBase *>(getSyncAppBase());
+} // TSyncAgent::getClientBase
+
+
+// retry older protocol, returns false if no older protocol to try
+bool TSyncAgent::retryOlderProtocol(bool aSameVersionRetry, bool aOldMessageInBuffer)
+{
+  if (fIncomingState==psta_idle) {
+    // if we have not started a session yet and not using oldest protocol already,
+    // we want to retry with next older SyncML version
+    if (aSameVersionRetry) {
+      // just retry same version
+      PDEBUGPRINTFX(DBG_PROTO,("Retrying session start with %s",SyncMLVerProtoNames[fSyncMLVersion]));
+    }
+    else if (fSyncMLVersion>getSessionConfig()->fMinSyncMLVersionSupported) {
+      // next lower
+      fSyncMLVersion=(TSyncMLVersions)(((uInt16)fSyncMLVersion)-1);
+      PDEBUGPRINTFX(DBG_PROTO,("Server does not support our SyncML version, trying with %s",SyncMLVerProtoNames[fSyncMLVersion]));
+    }
+    else {
+      // cannot retry
+      return false;
+    }
+    // retry
+    retryClientSessionStart(aOldMessageInBuffer);
+    return true;
+  }
+  // session already started or no older protocol to try
+  return false;
+} // TSyncAgent::retryOlderProtocol
+
+
+// prepares client session such that it will do a retry to start a session
+// (but keeping already received auth/nonce/syncML-Version state)
+void TSyncAgent::retryClientSessionStart(bool aOldMessageInBuffer)
+{
+  TAgentConfig *configP = static_cast<TAgentConfig *>(getRootConfig()->fAgentConfigP);
+
+  // now restarting
+  PDEBUGPRINTFX(DBG_HOT,("=================> Retrying Client Session Start"));
+  bool newSessionForAuthRetry = configP->fNewSessionForAuthRetry;
+  bool noRespURIForAuthRetry = configP->fNoRespURIForAuthRetry;
+       // check if we should use modified behaviour (smart retries)
+  if (configP->fSmartAuthRetry && fAuthRetries>MAX_NORMAL_AUTH_RETRIES) {
+       if (newSessionForAuthRetry) {
+       // if we had new session for retry, switch to in-session retry now
+      newSessionForAuthRetry = false;
+      noRespURIForAuthRetry = false;
+    }
+    else {
+       // if we had in-session retry, try new session retry now
+      newSessionForAuthRetry = true;
+      noRespURIForAuthRetry = true;    
+    }
+    PDEBUGPRINTFX(DBG_PROTO,("Smart retry with modified behaviour: newSessionForAuthRetry=%d, noRespURIForAuthRetry=%d",newSessionForAuthRetry,noRespURIForAuthRetry));
+  }
+  // now retry
+  if (newSessionForAuthRetry) {
+    // Notes:
+    // - must apparently be disabled for SCTS 3.1.2 and eventually Mightyphone
+    // - must be enabled e.g for for Magically Server
+    // Create new session ID
+    StringObjPrintf(fSynchdrSessionID,"%hd",(sInt16)++fClientSessionNo);
+    // restart message counting at 1
+    fIncomingMsgID=0;
+    fOutgoingMsgID=0;
+    // we must terminate the block here when we reset fIncomingMsgID, as NextMessage
+    // only closes the incoming block when fIncomingMsgID>0
+    PDEBUGENDBLOCK("SyncML_Incoming");
+  }
+  if (noRespURIForAuthRetry) {
+    // Notes:
+    // - must apparently be switched on for Starfish.
+    // - must apparently be switched off for SCTS 3.1.2.
+    // make sure we send next msg to the original URL
+    fRespondURI=fRemoteURI;
+  }
+  // - make sure status for SyncHdr will not be generated!
+  forgetHeaderWaitCommands();
+  // check if we have already started next outgoing message
+  if (!fOutgoingStarted) {
+    if (aOldMessageInBuffer) {
+      // make sure we start with a fresh output buffer
+      // Note: This usually only occur when we are not currently parsing
+      //       part of the buffer. If we are parsing, the remaining incoming
+      //       message gets cleared as well.
+      getClientBase()->clrUnreadSmlBufferdata();
+    }
+    // start a new message
+    issueHeader(false);
+  }
+  else {
+    if (aOldMessageInBuffer) {
+      PDEBUGPRINTFX(DBG_ERROR,("Warning - restarting session with old message in output buffer"));
+    }
+  }
+  // - make sure subsequent commands (most probably statuses for Alerts)
+  //   don't get processed
+  AbortCommandProcessing(0); // silently discard all further commands
+  // - make sure eventual processing errors do not abort the session
+  fIgnoreMsgErrs = true;
+} // TSyncAgent::retryClientSessionStart
+
+
+#endif // SYSYNC_CLIENT
+
+#ifdef SYSYNC_SERVER
+
+// undefine these only for tests. Introduced to find problem with T68i
+#define RESPURI_ONLY_WHEN_NEEDED
+
+// create a RespURI string. If none needed, return NULL
+SmlPcdataPtr_t TSyncAgent::newResponseURIForRemote(void)
+{
+  // do it in a transport-independent way, therefore let dispatcher do it
+  string respURI; // empty string
+  if (fUseRespURI) {  
+    getSyncAppBase()->generateRespURI(
+      respURI,  // remains unaffected if no RespURI could be calculated
+      fInitialLocalURI.c_str(), // initial URI used by remote to send first message
+      fLocalSessionID.c_str()  // server generated unique session ID
+    );
+    // Omit RespURI if local URI as seen by client is identical
+    if (getServerConfig()->fRespURIOnlyWhenDifferent) {
+      // create RespURI only if different from original URI
+      if (respURI==fLocalURI) {
+        respURI.erase();
+        DEBUGPRINTFX(DBG_SESSION,(
+          "Generated RespURI and sourceLocURI are equal (%s)-> RespURI omitted",
+          fLocalURI.c_str()
+        ));
+      }
+    }
+  }
+  // Note: returns NULL if respURI is empty string
+  return newPCDataOptString(respURI.c_str());
+} // newResponseURIForRemote
+
+
+// called after successful decoding of an incoming message
+bool TSyncAgent::ServerMessageStarted(SmlSyncHdrPtr_t aContentP, TStatusCommand &aStatusCommand, bool aBad)
+{
+  // message not authorized by default
+  fMessageAuthorized=false;
+  
+  // Get information from SyncHdr which is needed for answers
+  // - session ID to be used for responses
+  fSynchdrSessionID=smlPCDataToCharP(aContentP->sessionID);
+  // - local URI (as seen by remote client)
+  fLocalURI=smlSrcTargLocURIToCharP(aContentP->target);
+  fLocalName=smlSrcTargLocNameToCharP(aContentP->target);
+  // - also remember URI to which first message was sent
+  // %%% note: incoming ID is not a criteria, because it might be >1 due to
+  //     client retrying something which it thinks is for the same session
+  //if (fIncomingMsgID==1) {
+  if (fOutgoingMsgID==0) {
+    // this is the first message, remember first URI used to contact server
+    // (or set preconfigured string from <externalurl>)
+    if (getServerConfig()->fExternalURL.empty())
+      fInitialLocalURI=fLocalURI; // use what client sends to us
+    else
+      fInitialLocalURI=getServerConfig()->fExternalURL; // use preconfigured URL
+    // Many clients, including SCTS send the second login attempt with a MsgID>1,
+    // and depending on how they handle RespURI, they might get a new session for that
+    // -> so, just handle the case that a new session does not start with MsgID=1
+    if (fIncomingMsgID>1) {
+      PDEBUGPRINTFX(DBG_ERROR,(
+        "New session gets first message with MsgID=%ld (should be 1). Might be due to retries, adjusting OutgoingID as well",
+        (long)fIncomingMsgID
+      ));
+      fOutgoingMsgID=fIncomingMsgID-1; // to make it match what client expects
+    }
+  }
+  // - remote URI
+  fRemoteURI=smlSrcTargLocURIToCharP(aContentP->source);
+  fRemoteName=smlSrcTargLocNameToCharP(aContentP->source);
+  // - RespURI (remote URI to respond to, if different from source)
+  fRespondURI.erase();
+  if (aContentP->respURI) {
+    fRespondURI=smlPCDataToCharP(aContentP->respURI);
+    DEBUGPRINTFX(DBG_PROTO,("RespURI specified = '%s'",fRespondURI.c_str()));
+  }
+  if (fRespondURI==fRemoteURI) fRespondURI.erase(); // if specified but equal to remote: act as if not specified
+  // More checking if header was ok
+  if (aBad) {
+    // bad header, only do what is needed to get a status back to client
+    fSessionAuthorized=false;
+    fIncomingState=psta_init;
+    fOutgoingState=psta_init;
+    fNewOutgoingPackage=true;
+    // issue header to make sure status can be sent back to client
+    if (!fMsgNoResp)
+      issueHeader(false); // issue header, do not prevent responses
+  }
+  else {  
+    // check busy (or expired) case
+    if (serverBusy()) {
+      #ifdef APP_CAN_EXPIRE
+       if (getSyncAppBase()->fAppExpiryStatus!=LOCERR_OK) {
+               aStatusCommand.setStatusCode(511); // server failure (expired)
+               aStatusCommand.addItemString("License expired or invalid");
+        PDEBUGPRINTFX(DBG_ERROR,("License expired or invalid - Please contact Synthesis AG to obtain license"));
+      }
+       else
+       #endif
+       {
+       aStatusCommand.setStatusCode(101); // busy
+      }
+      issueHeader(false); // issue header, do not prevent responses
+      AbortSession(0,true); // silently discard rest of commands
+      return false; // header not ok
+    }  
+    // now check what state we are in
+    if (fIncomingState==psta_idle) {  
+      // Initialize
+      // - session-wide authorization not yet there
+      fSessionAuthorized=false;
+      fMapSeen=false;
+      // - session has started, we are processing first incoming
+      //   package and generating first outgoing package
+      //   (init, eventually changed to combined init/sync by <sync> in this package)
+      fIncomingState=psta_init;
+      fOutgoingState=psta_init;
+      fNewOutgoingPackage=true;
+    }
+    // authorization check
+    if (fIncomingState>=psta_init) {
+      // now check authorization
+      if (!fSessionAuthorized) {    
+        // started, but not yet permanently authorized
+        fMessageAuthorized=checkCredentials(
+          smlSrcTargLocNameToCharP(aContentP->source), // user name in clear text according to SyncML 1.0.1
+          aContentP->cred, // actual credentials
+          aStatusCommand
+        );
+        // NOTE: aStatusCommand has now the appropriate status and chal (set by checkCredentials())
+        // if credentials do not match, stop processing commands (but stay with the session)
+        if (!fMessageAuthorized) {
+          AbortCommandProcessing(aStatusCommand.getStatusCode());  
+          PDEBUGPRINTFX(DBG_PROTO,("Authorization failed with status %hd, stop command processing",aStatusCommand.getStatusCode()));
+        }
+        // now determine if authorization is permanent or not
+        if (fMessageAuthorized) {
+          fAuthFailures=0; // reset count
+          if (messageAuthRequired()) {
+            // each message needs autorisation again (or no auth at all)
+            // - 200 ok, next message needs authorization again (or again: none)
+            fSessionAuthorized=false; // no permanent authorization
+            aStatusCommand.setStatusCode(200);
+            // - add challenge for next auth (different nonce)
+            aStatusCommand.setChallenge(newSessionChallenge());
+            PDEBUGPRINTFX(DBG_PROTO,("Authorization ok, but required again for subsequent messages: 200 + chal"));
+          }
+          else {
+            // entire session is authorized
+            fSessionAuthorized=true; // permanent authorization
+            // - 212 authentication accepted (or 200 if none is reqired at all)          
+            aStatusCommand.setStatusCode(requestedAuthType()==auth_none ? 200 : 212);
+            // - add challenge for next auth (in next session, but as we support carry
+            //   forward via using sessionID, we need to send one here as well)
+            aStatusCommand.setChallenge(newSessionChallenge());
+            PDEBUGPRINTFX(DBG_PROTO,("Authorization accepted: 212"));
+          }
+        }
+      } // authorisation check
+      else {
+        // already authorized from previous message
+        PDEBUGPRINTFX(DBG_PROTO,("Authorization ok from previous request: 200"));
+        fMessageAuthorized=true;
+      }
+      // Start response message AFTER auth check, to allow issueHeader
+      // to check auth state and customize the header accordingly (no
+      // RespURI for failed auth for example)
+      if (!fMsgNoResp) {
+        issueHeader(false); // issue header, do not prevent responses
+      }
+    } // if started at least
+  } // if not aBad
+  // return startmessage status
+  // debug info
+  #ifdef SYDEBUG
+  if (PDEBUGMASK & DBG_SESSION) {
+    PDEBUGPRINTFX(DBG_SESSION,(
+      "---> MessageStarted, Message %sauthorized, incoming state='%s', outgoing state='%s'",
+      fMessageAuthorized ? "" : "NOT ",
+      PackageStateNames[fIncomingState],
+      PackageStateNames[fOutgoingState]
+    ));
+       TLocalDataStorePContainer::iterator pos;
+    for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
+      // Show state of local datastores
+      PDEBUGPRINTFX(DBG_SESSION,(
+        "Local Datastore '%s': State=%s, %s%s sync, %s%s",
+        (*pos)->getName(),
+        (*pos)->getDSStateName(),
+        (*pos)->isResuming() ? "RESUMED " : "",
+        (*pos)->fSlowSync ? "SLOW" : "normal",
+        SyncModeDescriptions[(*pos)->fSyncMode],
+        (*pos)->fServerAlerted ? ", Server-Alerted" : ""
+      ));
+    }
+  }
+  #endif
+  // final check for too many auth failures
+  if (!fMessageAuthorized) {
+    #ifdef NO_NONCE_OLD_BEAHVIOUR
+    AbortSession(aStatusCommand.getStatusCode(),true); // local error
+    // avoid special treatment of non-authorized message, we have aborted, this is enough
+    fMessageAuthorized=true;
+    #else
+    // Unsuccessful auth, count this
+    fAuthFailures++;
+    PDEBUGPRINTFX(DBG_ERROR,(
+      "Authorization failed %hd. time, (any reason), sending status %hd",
+      fAuthFailures,
+      aStatusCommand.getStatusCode()
+    ));
+    // - abort session after too many auth failures
+    if (fAuthFailures>=MAX_AUTH_ATTEMPTS) {
+      PDEBUGPRINTFX(DBG_ERROR,("Too many (>=%hd) failures, aborting session",MAX_AUTH_ATTEMPTS));
+      AbortSession(400,true);
+    }
+    #endif        
+  }  
+  // returns false on BAD header (but true on wrong/bad/missing cred)
+  return true;
+} // TSyncAgent::ServerMessageStarted
+
+
+void TSyncAgent::ServerMessageEnded(bool aIncomingFinal)
+{
+  bool alldone;
+  TPackageStates newoutgoingstate,newincomingstate;
+  TLocalDataStorePContainer::iterator pos;
+  bool allFromClientOnly=false;
+  
+  // Incoming message ends here - what is following are commands initiated by the server
+  // not directly related to a incoming command.
+  PDEBUGENDBLOCK("SyncML_Incoming");
+  // assume that outgoing package is NOT finished, so outgoing state does not change
+  newoutgoingstate=fOutgoingState;
+  // new incoming state depends on whether this message is final or not
+  if ((aIncomingFinal || (fIncomingState==psta_supplement)) && fMessageAuthorized) {
+    // Note: in supplement state, incoming final is not relevant (may or may not be present, there is
+    //       no next phase anyway 
+    // find out if this is a shortened session (no map phase) due to
+    // from-client-only in all datastores
+    if (!fCompleteFromClientOnly) {
+      allFromClientOnly=true;
+      for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
+        // check sync modes
+        if ((*pos)->isActive() && (*pos)->getSyncMode()!=smo_fromclient) {
+          allFromClientOnly=false;
+          break;
+        }
+      }
+    }
+    // determine what package comes next
+    switch (fIncomingState) {
+      case psta_init :
+        newincomingstate=psta_sync;
+        break;
+      case psta_sync :
+      case psta_initsync :
+        // end of sync phase means end of session if all datastores are in from-client-only mode
+        if (allFromClientOnly) {
+          PDEBUGPRINTFX(DBG_PROTO+DBG_HOT,("All datastores in from-client-only mode: don't expect map phase from client"));
+          newincomingstate=psta_supplement;
+        }
+        else {
+          newincomingstate=psta_map;
+        }
+        break;
+      case psta_map :
+      case psta_supplement : // supplement state does not exit automatically
+        // after map, eventually some supplement status/alert 222 messages are needed from client
+        newincomingstate=psta_supplement;
+        break;
+      default:
+        // by default, back to idle
+        newincomingstate=psta_idle;
+        break;
+    } // switch
+  }
+  else {
+    // not final or not authorized: no change in state
+    newincomingstate=fIncomingState;
+  }
+  // show status before processing
+  PDEBUGPRINTFX(DBG_SESSION,(
+    "---> MessageEnded starts   : old incoming state='%s', old outgoing state='%s', %sNeedToAnswer",
+    PackageStateNames[fIncomingState],
+    PackageStateNames[fOutgoingState],
+    fNeedToAnswer ? "" : "NO "
+  ));
+  // process
+  if (isAborted()) {
+    // actual aborting has already taken place
+    PDEBUGPRINTFX(DBG_ERROR,("***** Session is flagged 'aborted' -> MessageEnded ends package and session"));
+    newoutgoingstate=psta_idle;
+    newincomingstate=psta_idle;
+    fInProgress=false;
+  } // if aborted
+  else if (isSuspending()) {
+    // only flagged for suspend - but datastores are not yet aborted, do it now
+    AbortSession(514,true,getAbortReasonStatus());
+    PDEBUGPRINTFX(DBG_ERROR,("***** Session is flagged 'suspended' -> MessageEnded ends package and session"));
+    newoutgoingstate=psta_idle;
+    newincomingstate=psta_idle;
+    fInProgress=false;
+  }
+  else if (!fMessageAuthorized) {
+    // not authorized messages will just be ignored, no matter if final or not,
+    // so outgoing will NEVER be final on non-authorized messages
+    // %%% before 1.0.4.9, this was fInProgress=true
+    //  DEBUGPRINTFX(DBG_ERROR,("***** Message not authorized, ignore and DONT end package, session continues"));
+    //  fInProgress=true; 
+    PDEBUGPRINTFX(DBG_ERROR,("***** Message not authorized, ignore msg and terminate session"));
+    fInProgress=false; 
+  }
+  else {
+    // determine if session continues living or not
+    // - if in other than idle state, session will continue
+    fInProgress =
+      (newincomingstate!=psta_idle) || // if not idle, we'll continue
+      !fMessageAuthorized; // if not authorized, we'll continue as well (retrying auth)   
+    // Check if we need to send an Alert 222 to get more messages of this package
+    if (!aIncomingFinal) {
+      // not end of incoming package
+      #ifndef ALWAYS_CONTINUE222
+      if (!fNeedToAnswer)
+      #endif
+      {
+        #ifdef COMBINE_SYNCANDMAP
+        // %%% make sure session gets to an end in case combined sync/map was used
+        if (fMapSeen && fIncomingState==psta_map && fOutgoingState==psta_map) {
+          DEBUGPRINTFX(DBG_HOT,("********** Incoming, non-final message in (combined)map state needs no answer -> force end of outgoing package"));          
+          newoutgoingstate=psta_idle;
+        }
+        else
+        #endif
+        {
+          // detected 222-loop on init here: when we have nothing to answer in init
+          // and nothing is alerted -> break session
+          // %%% not sure if this is always ok
+          if (fIncomingState<=psta_init) {
+            PDEBUGPRINTFX(DBG_ERROR,("############## Looks like if we were looping in an init-repeat loop -> force final"));
+            fInProgress=false;
+            fOutgoingState=psta_idle;
+          }
+          else {
+            // not final, and nothing to answer otherwise: create alert-Command to request more info
+            TAlertCommand *alertCmdP = new TAlertCommand(this,NULL,(uInt16)222);
+            // %%% not clear from spec what has to be in item for 222 alert code
+            //     but there MUST be an Item for the Alert command according to SyncML TK
+            // - we just put local and remote URIs here 
+            SmlItemPtr_t itemP = newItem();
+            itemP->target = newLocation(fRemoteURI.c_str());
+            itemP->source = newLocation(fLocalURI.c_str());
+            alertCmdP->addItem(itemP);
+            ISSUE_COMMAND_ROOT(this,alertCmdP);
+          }
+        }
+      }
+    }
+    else {
+      // end of package, finish processing package
+      if (fIncomingState==psta_init) {
+        // - try to load devinf from cache (only if we don't have both datastores and type info already)
+        if (!fRemoteDataStoresKnown || !fRemoteDataTypesKnown) {
+          SmlDevInfDevInfPtr_t devinfP;
+          TStatusCommand dummystatus(this);  
+          if (loadRemoteDevInf(getRemoteURI(),devinfP)) {
+            // we have cached devinf, analyze it now
+            localstatus sta = analyzeRemoteDevInf(devinfP);
+            PDEBUGPRINTFX(DBG_ERROR,("devInf from Cache could not be analyzed: error=%hd",sta));
+          }
+        }
+        // - if no DevInf for remote datastores cached or received yet,
+        //   issue GET for it now
+        if (!fRemoteDataStoresKnown) {
+          // if we know datastores here, but not types, this means that remote does not have
+          // CTCap, so it makes no sense to issue a GET again.
+          #ifndef NO_DEVINF_GET
+          // end of initialisation package, but datastores not known yet
+          // (=no DevInf Put received) --> ask for devinf now
+          PDEBUGPRINTFX(DBG_REMOTEINFO,("No DevInf received or cached, request DevInf using GET command"));
+          TGetCommand *getcommandP = new TGetCommand(this);
+          getcommandP->addTargetLocItem(SyncMLDevInfNames[fSyncMLVersion]);
+          string devinftype=SYNCML_DEVINF_META_TYPE;
+          addEncoding(devinftype);
+          getcommandP->setMeta(newMetaType(devinftype.c_str()));
+          ISSUE_COMMAND_ROOT(this,getcommandP);
+          #endif
+        }
+      }
+    }
+    // make sure syncing local datastores get informed of end-of-<Sync>-message
+    if (fIncomingState==psta_sync || fIncomingState==psta_initsync) {
+      // end of an incoming message of the Sync Package
+      // - let all local datastores know, this is now the time to generate
+      //   <sync> commands, if needed
+      // Note: if there are SyncEnd commands delayed, this means that this is
+      //       not yet the time to start <sync> commands. Instead, when all
+      //       queued SyncEnd commands are executed later, engEndOfSyncFromRemote()
+      //       will be called with the endOfAllSyncCommands flag true instead
+      //       of now. 
+      for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
+        (*pos)->engEndOfSyncFromRemote(aIncomingFinal && !delayedSyncEndsPending());
+      }
+    }
+    // Detect outgoing package state transitions
+    // - init to sync
+    if (fOutgoingState==psta_init && newincomingstate>psta_init) {
+      // new outgoing state is sync.
+      // Note: In combined init&sync mode, sync command received in init state
+      //       will set outgoing state from init to init-sync while processing message,
+      //       so no transition needs to be detected here
+      newoutgoingstate=psta_sync;
+    }
+    // - sync to map
+    else if (
+      (fOutgoingState==psta_sync || fOutgoingState==psta_initsync) && // outgoing is sync..
+      (newincomingstate>=psta_initsync) && // ..and incoming has finished sync
+      !allFromClientOnly // ..and this is not a session with all datastores doing from-client-only
+    ) {
+      // outgoing message belongs to Sync package
+      // - ask all local datastores if they are finished with sync command generation
+      alldone=true;
+      for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
+        alldone = alldone && (*pos)->isSyncDone();
+      }
+      if (alldone) {
+        // outgoing state changes to map (or supplement if all datastores are from-client-only
+        PDEBUGPRINTFX(DBG_HOT,("All datastores are done with generating <Sync>"));
+        newoutgoingstate=psta_map;
+        #ifdef COMBINE_SYNCANDMAP
+        // %%% it seems as if 9210 needs combined Sync/Map package and 
+        if (fMapSeen) {
+          // prevent FINAL to be sent at end of message
+          DEBUGPRINTFX(DBG_HOT,("********** Combining outgoing sync and map-response packages into one"));
+          fOutgoingState=psta_map;
+        }
+        #endif
+      }
+    }
+    // - map (or from-client-only sync) to idle
+    else if (
+      (fOutgoingState==psta_map && newincomingstate==psta_supplement) ||
+      (allFromClientOnly && (fOutgoingState==psta_sync || fOutgoingState==psta_initsync))
+    ) {
+      // we are going back to idle now
+      newoutgoingstate=psta_idle;
+      // session ends if it doesn't need to continue for session-level reasons
+      if (!sessionMustContinue()) {
+        PDEBUGPRINTFX(DBG_HOT,("Session completed, now let datastores terminate all sync operations"));
+        for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
+          // finished with Map: end of sync
+          (*pos)->engFinishDataStoreSync(); // successful
+        }
+        // session ends now
+        fInProgress=false;
+        // let custom PUTs which may transmit some session statistics etc. happen now
+        issueCustomEndPut();
+      }
+    }
+    // - if no need to answer (e.g. nothing to send back except OK status for SyncHdr),
+    //   session is over now (as well)
+    if (!fNeedToAnswer) fInProgress=false;
+  } // else 
+  // Now finish outgoing message
+  #ifdef DONT_FINAL_BAD_AUTH_ATTEMPTS
+  // - PREVENT final flag after failed auth attempts
+  if(FinishMessage(
+    fOutgoingState!=newoutgoingstate || fOutgoingState==psta_idle, // final when state changed or idle
+    !fMessageAuthorized || serverBusy() // busy or unauthorized prevent final flag at any rate
+  ))
+  #else
+  // - DO set final flag after failed auth attempts
+  if(FinishMessage(
+    !fMessageAuthorized || fOutgoingState!=newoutgoingstate || fOutgoingState==psta_idle, // final when state changed or idle
+    serverBusy() // busy prevents final flag at any rate
+  ))  
+  #endif
+  {
+    // outgoing state HAS changed
+    fOutgoingState=newoutgoingstate;
+  }
+  // Now update incoming state
+  fIncomingState=newincomingstate;
+  // show states
+  PDEBUGPRINTFX(DBG_HOT,(
+    "---> MessageEnded finishes : new incoming state='%s', new outgoing state='%s', %sNeedToAnswer",
+    PackageStateNames[fIncomingState],
+    PackageStateNames[fOutgoingState],
+    fNeedToAnswer ? "" : "NO "
+  ));
+  // let all local datastores know that message has ended
+  for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
+    // let them know
+    (*pos)->engEndOfMessage();
+    // Show state of local datastores
+    PDEBUGPRINTFX(DBG_HOT,(
+      "Local Datastore '%s': State=%s, %s%s sync, %s%s",
+      (*pos)->getName(),
+      (*pos)->getDSStateName(),
+      (*pos)->isResuming() ? "RESUMED " : "",
+      (*pos)->fSlowSync ? "SLOW" : "normal",
+      SyncModeDescriptions[(*pos)->fSyncMode],
+      (*pos)->fServerAlerted ? ", Server-Alerted" : ""
+    ));
+  }
+  // End of outgoing message
+  PDEBUGPRINTFX(DBG_HOT,(
+    "=================> Finished generating outgoing message #%ld, request=%ld",
+    (long)fOutgoingMsgID,
+    (long)getSyncAppBase()->requestCount()
+  ));
+  PDEBUGENDBLOCK("SyncML_Outgoing");
+} // TSyncAgent::ServerMessageEnded
+
+
+void TSyncAgent::RequestEnded(bool &aHasData)
+{
+  // to make sure, finish any unfinished message
+  FinishMessage(true); // final allowed, as this is an out-of-normal-order case anyway  
+  // if we need to answer, we have data
+  // - SyncML specs 1.0.1 says that server must always respond, even if message
+  //   contains of a Status for the SyncHdr only 
+  aHasData=true;
+  // %%% first drafts of 1.0.1 said that SyncHdr Status only messages must not be sent...
+  // aHasData=fNeedToAnswer; // %%%
+  
+  // now let all datastores know that request processing ends here (so they might
+  // prepare for a thread switch)
+  // terminate sync with all datastores
+  TLocalDataStorePContainer::iterator pos;
+  for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
+    // now let them know that request has ended
+    (*pos)->engRequestEnded();
+  }
+} // TSyncAgent::RequestEnded
+
+
+// Called at end of Request, returns true if session must be deleted
+// returns flag if data to be returned. If response URI was specified
+// different, it is returned in aRespURI, otherwise aRespURI is empty.
+bool TSyncAgent::EndRequest(bool &aHasData, string &aRespURI, uInt32 aReqBytes)
+{
+  // count incoming data
+  fIncomingBytes+=aReqBytes;
+  // let client or server do what is needed
+  if (fMessageRetried) {
+    // Message processing cancelled
+    CancelMessageProcessing();
+    // Nothing happened 
+         // - but count bytes 
+    fOutgoingBytes+=fBufferedAnswerSize;
+    PDEBUGPRINTFX(DBG_HOT,(
+           "========= Finished retried request with re-sending buffered answer (session %sin progress), incoming bytes=%ld, outgoing bytes=%ld",
+           fInProgress ? "" : "NOT ",
+           (long)aReqBytes,
+           (long)fBufferedAnswerSize
+         ));
+         aHasData=false; // we do not have data in the sml instance (but we have/had some in the retry re-send buffer)
+  }
+  else {
+    // end request
+         RequestEnded(aHasData);
+         // count bytes
+    fOutgoingBytes+=getOutgoingMessageSize();
+         PDEBUGPRINTFX(DBG_HOT,(
+           "========= Finished request (session %sin progress), processing time=%ld msec, incoming bytes=%ld, outgoing bytes=%ld",
+           fInProgress ? "" : "NOT ",
+           (long)((getSystemNowAs(TCTX_UTC)-getLastRequestStarted()) * nanosecondsPerLinearTime / 1000000),
+           (long)aReqBytes,
+      (long)getOutgoingMessageSize()
+         ));     
+         // return RespURI (is empty if none specified or equal to message source URI)
+         aRespURI = fRespondURI;
+  }
+  if (!fInProgress) {
+    // terminate datastores here already in case we are not in progress any more
+    // here. If any of the datastores are in progress at this point, this is a
+    // protocol violation, and therefore we return a 400.
+    // Note: resetting the session later will also call TerminateDatastores, but then
+    //       with a 408 (which is misleading when the session ends here due to protocol
+    //       problem.
+    TerminateDatastores(400);
+  }
+  //%%% moved to happen before end of SyncML_Outgoing 
+  //PDEBUGENDBLOCK("SyncML_Incoming");
+  if (fRequestMinTime>0) {
+    // make sure we spent enough time with this request, if not, artificially extend time
+    // - get number of seconds already spent
+    sInt32 t =
+      (sInt32)((getSystemNowAs(TCTX_UTC)-getLastRequestStarted()) / (lineartime_t)secondToLinearTimeFactor);
+    // - delay if needed
+    if (t<fRequestMinTime) {
+         PDEBUGPRINTFX(DBG_HOT,(
+           "requestmintime is set to %ld seconds, we have spent only %ld seconds so far -> sleeping %ld seconds",
+           (long)fRequestMinTime,
+           (long)t,
+           (long)fRequestMinTime-t
+         ));
+      CONSOLEPRINTF(("  ...delaying response by %ld seconds because requestmintime is set to %ld",fRequestMinTime,fRequestMinTime-t));
+         sleepLineartime((lineartime_t)(fRequestMinTime-t)*secondToLinearTimeFactor);
+    }
+  }
+  // thread might end here, so stop profiling
+  TP_STOP(fTPInfo);
+  #ifdef SYDEBUG
+  // we are not the main thread any longer
+  getDbgLogger()->DebugThreadOutputDone();
+  #endif
+  // return true if session is not in progress any more
+  return(!fInProgress);
+} // TSyncAgent::EndRequest
+
+
+// buffer answer in the session's buffer if transport allows it
+Ret_t TSyncAgent::bufferAnswer(MemPtr_t aAnswer, MemSize_t aAnswerSize)
+{
+  // get rid of previous buffered answer
+  if (fBufferedAnswer)
+    delete[] fBufferedAnswer;
+  fBufferedAnswer=NULL;
+  fBufferedAnswerSize=0;
+  // save new answer (if not empty)
+  if (aAnswer && aAnswerSize) {
+    // allocate buffer
+    fBufferedAnswer = new unsigned char[aAnswerSize];
+    // copy data
+    if (!fBufferedAnswer) return SML_ERR_NOT_ENOUGH_SPACE;
+    memcpy(fBufferedAnswer,aAnswer,aAnswerSize);
+    // save size
+    fBufferedAnswerSize=aAnswerSize;
+  }
+  return SML_ERR_OK;
+} // TSyncAgent::bufferAnswer
+
+
+// get buffered answer from the session's buffer if there is any
+void TSyncAgent::getBufferedAnswer(MemPtr_t &aAnswer, MemSize_t &aAnswerSize)
+{
+  aAnswer=fBufferedAnswer;
+  aAnswerSize=fBufferedAnswerSize;  
+  PDEBUGPRINTFX(DBG_HOT,(
+    "Buffered answer read from session: %ld bytes",
+    fBufferedAnswerSize
+  ));
+} // TSyncAgent::getBufferedAnswer
+
+
+// returns remaining time for request processing [seconds]
+sInt32 TSyncAgent::RemainingRequestTime(void)
+{
+  // if no request timeout specified, use session timeout
+  sInt32 t = fRequestMaxTime ? fRequestMaxTime : getSessionConfig()->fSessionTimeout;
+  // calculate number of remaining seconds
+  return
+    t==0 ?
+      0x7FFFFFFF : // "infinite"
+      t - (sInt32)((getSystemNowAs(TCTX_UTC)-getLastRequestStarted()) / (lineartime_t)secondToLinearTimeFactor);
+} // TSyncAgent::RemainingRequestTime
+
+
+
+
+
+// process a Map command in context of server session
+bool TSyncAgent::processMapCommand(
+  SmlMapPtr_t aMapCommandP,      // the map command contents
+  TStatusCommand &aStatusCommand, // pre-set 200 status, can be modified in case of errors
+  bool &aQueueForLater
+)
+{
+  bool allok=false; // assume not ok
+  localstatus sta;
+
+  // remember that this session has seen a map command already
+  fMapSeen=true;
+  // Detecting a map command in supplement incomin state indicates a
+  // client like funambol that send to many <final/> in pre-map phases
+  // (such as in 222-Alert messages). So we reset the session state back
+  // to incoming/outgoing map to correct this client bug
+  if (fIncomingState==psta_supplement) {
+    // back to map phase, as client apparently IS still in map phase, despite too many
+    // <final/> sent
+    PDEBUGPRINTFX(DBG_ERROR,(
+      "Warning: detected <Map> command after end of Map phase - buggy client sent too many <final/>. Re-entering map phase to compensate"
+    ));
+    fIncomingState=psta_map;
+    fOutgoingState=psta_map;
+  }
+  // find database(s)
+  // - get relative URI of requested database
+  const char *targetdburi = smlSrcTargLocURIToCharP(aMapCommandP->target);
+  TLocalEngineDS *datastoreP = findLocalDataStoreByURI(targetdburi);
+  if (!datastoreP) {
+    // no such local datastore
+    aStatusCommand.setStatusCode(404); // not found
+  }
+  else {
+    // local datastore found
+    // - maps can be processed when we are at least ready for early (chached by client from previous session) maps
+    if (datastoreP->testState(dssta_syncmodestable)) {
+      // datastore is ready 
+      PDEBUGBLOCKFMT(("ProcessMap", "Processing items from Map command", "datastore=%s", targetdburi));
+      allok=true; // assume all ok
+      SmlMapItemListPtr_t nextnode = aMapCommandP->mapItemList;
+      while (nextnode) {
+        POINTERTEST(nextnode->mapItem,("MapItemList node w/o MapItem"));
+        PDEBUGPRINTFX(DBG_HOT,(
+          "Mapping remoteID='%s' to localID='%s'",
+          smlSrcTargLocURIToCharP(nextnode->mapItem->source),
+          smlSrcTargLocURIToCharP(nextnode->mapItem->target)
+        ));
+        sta = datastoreP->engProcessMap(
+          #ifdef DONT_STRIP_PATHPREFIX_FROM_REMOTEIDS
+          smlSrcTargLocURIToCharP(nextnode->mapItem->source),
+          #else 
+          relativeURI(smlSrcTargLocURIToCharP(nextnode->mapItem->source)),
+          #endif
+          relativeURI(smlSrcTargLocURIToCharP(nextnode->mapItem->target))
+        );
+        if (sta!=LOCERR_OK) {
+          PDEBUGPRINTFX(DBG_ERROR,("    Mapping FAILED!"));
+          aStatusCommand.setStatusCode(sta);
+          allok=false;
+          break;
+        }
+        // next mapitem
+        nextnode=nextnode->next;
+      } // while more mapitems
+      // terminate Map command
+      allok=datastoreP->MapFinishAsServer(allok,aStatusCommand);
+      PDEBUGENDBLOCK("ProcessMap");
+    }
+    else {
+      // we must queue the command for later execution
+      aQueueForLater=true;
+      allok=true; // ok for now, we'll re-execute this later
+    }
+  } // database found
+  return allok;
+} // TSyncAgent::processMapCommand
+    
+
+// get next nonce string top be sent to remote party for subsequent MD5 auth
+void TSyncAgent::getNextNonce(const char *aDeviceID, string &aNextNonce)
+{
+  fLastNonce.erase();
+  if (getServerConfig()->fAutoNonce) {
+    // generate nonce out of source ref and session ID
+    // This scheme can provide nonce carrying forward between 
+    // sessions by initializing lastNonce with the srcRef/sessionid-1
+    // assuming client to use nonce from last session.
+    sInt32 sid;
+    // use current day as nonce varying number
+    sid = time(NULL) / 3600 / 24; 
+    generateNonce(fLastNonce,aDeviceID,sid);
+  }
+  else {
+    // get constant nonce (if empty, this is NO nonce)
+    fLastNonce=getServerConfig()->fConstantNonce;
+  }
+  // return new nonce
+  DEBUGPRINTFX(DBG_PROTO,("getNextNonce: created nonce='%s'",fLastNonce.c_str()));
+  aNextNonce=fLastNonce;
+} // TSyncAgent::getNextNonce
+
+
+// - get nonce string for specified deviceID
+void TSyncAgent::getAuthNonce(const char *aDeviceID, string &aAuthNonce)
+{
+  // if no device ID, use session default nonce
+  if (!aDeviceID) {
+    TSyncSession::getAuthNonce(aDeviceID,fLastNonce);
+  }
+  else {
+    // Basic nonce mechanism needing no per-device storage:
+    // - we have no stored last nonce, but we can re-create nonce used
+    //   for last session with this device by the used algorithm
+    if (getServerConfig()->fAutoNonce) {
+      if (fLastNonce.empty()) {
+        // none available, produce new one
+        sInt32 sid;
+        // use current day as nonce varying number
+        sid = time(NULL) / 3600 / 24; 
+        generateNonce(fLastNonce,aDeviceID,sid);
+      }
+    }
+    else {
+      // return constant nonce
+      fLastNonce=getServerConfig()->fConstantNonce;
+    }
+  }
+  DEBUGPRINTFX(DBG_PROTO,("getAuthNonce: current auth nonce='%s'",fLastNonce.c_str()));
+  aAuthNonce=fLastNonce;
+} // TSyncAgent::getAuthNonce
+
+
+
+// info about server status
+bool TSyncAgent::serverBusy(void)
+{
+       // return flag (which might have been set by some connection
+       // limit code in sessiondispatch).
+       // When app is expired, all server sessions are busy anyway
+       #ifdef APP_CAN_EXPIRE
+       return fSessionIsBusy || (getSyncAppBase()->fAppExpiryStatus!=LOCERR_OK);
+       #else
+       return fSessionIsBusy;
+       #endif
+} // TSyncAgent::serverBusy
+
+
+// access to config
+TAgentConfig *TSyncAgent::getServerConfig(void)
+{
+  TAgentConfig *scP;
+  GET_CASTED_PTR(scP,TAgentConfig,getSyncAppBase()->getRootConfig()->fAgentConfigP,DEBUGTEXT("no TAgentConfig","ss1"));
+  return scP;
+} // TSyncAgent::getServerConfig
+
+
+#endif // SYSYNC_SERVER
+
+
+// info about requested auth type
+TAuthTypes TSyncAgent::requestedAuthType(void)
+{
+       if (IS_SERVER) {
+       #ifdef SYSYNC_SERVER
+         return getServerConfig()->fRequestedAuth;
+    #endif
+  }
+  else {
+       return auth_none; // client does not require auth
+  }
+} // TSyncAgent::requestedAuthType
+
+
+// check if auth type is allowed
+bool TSyncAgent::isAuthTypeAllowed(TAuthTypes aAuthType)
+{
+       if (IS_SERVER) {
+       #ifdef SYSYNC_SERVER
+         return aAuthType>=getServerConfig()->fRequiredAuth;
+    #endif
+  }
+  else {
+       return true; // client accepts any auth
+  }
+} // TSyncAgent::isAuthTypeAllowed
+
+
+// called when incoming SyncHdr fails to execute
+bool TSyncAgent::syncHdrFailure(bool aTryAgain)
+{
+       if (IS_CLIENT) {
+    // do not try to re-execute the header, just let message processing fail;
+    // this will cause the client's main loop to try using an older protocol
+    return false;
+  }
+  else {
+       #ifdef SYSYNC_SERVER
+    if (!aTryAgain) {
+      // not already retried executing
+      // special case: header failed to execute, this means that session must be reset
+      // - Reset session (aborts all DB transactions etc.)
+      ResetSession();
+      PDEBUGPRINTFX(DBG_ERROR,("Trying to recover SyncHdr failure: =========== Session restarted ====================="));
+      // - now all session infos are gone except this command which is owned by
+      //   this function alone. Execute it again.
+      aTryAgain=true;
+    }
+    else {
+      // special special case: header failed to execute the second time
+      DEBUGPRINTFX(DBG_ERROR,("Fatal internal problem, SyncHdr execution failed twice"));
+      aTryAgain=false; // just to make sure
+      SYSYNC_THROW((TSyncException("SyncHdr fatal execution problem")));
+    }
+    return aTryAgain;    
+    #endif
+  }
+} // TSyncAgent::syncHdrFailure
+
+
+// handle status received for SyncHdr, returns false if not handled
+bool TSyncAgent::handleHeaderStatus(TStatusCommand *aStatusCmdP)
+{
+       if (IS_CLIENT) {
+       #ifdef SYSYNC_CLIENT
+    TAgentConfig *configP = static_cast<TAgentConfig *>(getRootConfig()->fAgentConfigP);
+    bool handled=true;
+    const char *txt;
+    SmlMetInfMetInfPtr_t chalmetaP=NULL;
+    SmlChalPtr_t chalP;
+
+    // first evaluate eventual challenge in header status
+    chalP = aStatusCmdP->getStatusElement()->chal;
+    if (chalP) {
+      chalmetaP = smlPCDataToMetInfP(chalP->meta);
+      if (chalmetaP) {
+        sInt16 ty;
+        // - get auth type
+        if (!chalmetaP->type) AbortSession(401,true); // missing auth, but no type
+        txt = smlPCDataToCharP(chalmetaP->type);
+        PDEBUGPRINTFX(DBG_PROTO,("Remote requests auth type='%s'",txt));
+        if (StrToEnum(authTypeSyncMLNames,numAuthTypes,ty,txt))
+          fRemoteRequestedAuth=(TAuthTypes)ty;
+        else {
+          AbortSession(406,true); // unknown auth type, not supported
+          goto donewithstatus;
+        }
+        // - get auth format
+        if (!smlPCDataToFormat(chalmetaP->format, fRemoteRequestedAuthEnc)) {
+          AbortSession(406,true); // unknown auth format, not supported
+          goto donewithstatus;
+        }
+        // - get next nonce
+        if (chalmetaP->nextnonce) {
+          // decode B64
+          uInt32 l;
+          uInt8 *nonce = b64::decode(smlPCDataToCharP(chalmetaP->nextnonce), 0, &l);
+          fRemoteNonce.assign((char *)nonce,l);
+          sysync_free(nonce);
+        }
+        // - show
+        PDEBUGPRINTFX(DBG_PROTO,(
+          "Next Cred will have type='%s' and format='%s' and use nonce='%s'",
+          authTypeNames[fRemoteRequestedAuth],
+          encodingFmtNames[fRemoteRequestedAuthEnc],
+          fRemoteNonce.c_str()
+        ));
+      }
+      /* %%% do not save here already, we don't know if SyncML version is ok
+             moved to those status code cases below that signal
+      // let descendant eventually save auth params
+      saveRemoteParams();
+      */
+    }
+    // now evaluate status code
+    switch (aStatusCmdP->getStatusCode()) {
+      case 101: // Busy
+        // Abort
+        AbortSession(101,false);
+        break;
+      case 212: // authentication accepted for entire session
+        fNeedAuth=false; // no need for further auth
+        PDEBUGPRINTFX(DBG_PROTO,("Remote accepted authentication for entire session"));
+      case 200: // authentication accepted for this message
+        // if this is the first authorized message we get an OK for the synchdr, this is
+        // also the first incoming message that is really processed as init message
+        if (fIncomingState==psta_idle && fMessageAuthorized) {
+          // first incoming is expected to be same as first outgoing (init or initsync)
+          fIncomingState=fOutgoingState;
+          PDEBUGPRINTFX(DBG_PROTO,("Authenticated successfully with remote server"));
+        }
+        else {
+          PDEBUGPRINTFX(DBG_PROTO,("Authentication with server ok for this message"));
+        }
+        // let descendant eventually save auth params
+        saveRemoteParams();
+        break;
+      case 501: // handle a "command not implemented" for the SyncHdr like 513 (indication that server does not like our header)
+      case 400: // ..and 400 as well (sync4j case, as it seems)
+      case 513: // bad protocol version
+      case 505: // bad DTD version (NextHaus/DeskNow case)
+        // try with next lower protocol
+        PDEBUGENDBLOCK("processStatus"); // done processing status
+        if (!retryOlderProtocol()) {
+          // no older SyncML protocol we can try --> abort
+          AbortSession(513,false); // server does not know any of our SyncML versions
+        }
+        break;
+      case 401: // bad authentication
+        // Bad authorisation
+        if (fAuthRetries==0)
+          // if first attempt is rejected with "bad", we conclude that the
+          // last attempt was carrying auth data and was not a attempt to get challenge
+          // from server. Therefore we count this as two tries (one get chal, one really failing)
+          fAuthRetries=2;
+        else
+          fAuthRetries++; // just count attempt to auth
+        /* %%% no longer required, is tested below at authfail:
+        if (fAuthRetries>MAX_AUTH_RETRIES) {
+          AbortSession(401,false); // abort session, too many retries
+          break;
+        }
+        */
+        // Treat no nonce like empty nonce to make sure that a server (like SySync old versions...)
+        // that does not send a nonce at all does not get auth with some old, invalid nonce string included.
+        if (chalmetaP && chalmetaP->nextnonce==NULL) fRemoteNonce.erase();
+        // otherwise treat like 407
+        goto authfail;
+      case 407: // authentication required
+        // new since 2.0.4.6: count this as well (normally this happens once when sending
+        // no auth to the server to force it to send us auth chal first).
+        fAuthRetries++;
+      authfail:
+        PDEBUGPRINTFX(DBG_ERROR,("Authentication failed (status=%hd) with remote server",aStatusCmdP->getStatusCode()));
+        // Auth fail after we have received a valid response for the init message indicates protocol messed up
+        if (fIncomingState!=psta_idle) {
+          AbortSession(400,true); // error in protocol handling from remote
+          break;
+        }
+        // Check if smart retries (with modified in-session vs out-of-session behaviour) are enabled
+        if (!configP->fSmartAuthRetry && fAuthRetries>MAX_NORMAL_AUTH_RETRIES) {
+          fAuthRetries = MAX_SMART_AUTH_RETRIES+1; // skip additional smart retries
+        }
+        // Missing or bad authorisation, evaluate chal
+        if (!chalmetaP || fAuthRetries>MAX_SMART_AUTH_RETRIES) {
+          #ifdef SYDEBUG
+          if (!chalmetaP) {
+            PDEBUGPRINTFX(DBG_ERROR,("Bad auth but no challenge in response status -> can't work - no retry"));
+          }
+          #endif
+          AbortSession(aStatusCmdP->getStatusCode(),false); // retries exhausted or no retry possible (no chal) -> stop session
+          break;
+        }
+        // let descendant eventually save auth params
+        saveRemoteParams();
+        // modify session for re-start
+        PDEBUGENDBLOCK("processStatus"); // done processing status
+        retryClientSessionStart(false); // no previously sent message in the buffer
+        break;
+      default:
+        handled=false; // could not handle status
+    } // switch
+  donewithstatus:
+    // Anyway, reception of status for header enables generation of next message header
+    // (plus already generated commands such as status for response header)
+    if (!fMsgNoResp && !isAborted()) {
+      // issue header now if not already issued above
+      if (!fOutgoingStarted) {
+        // interrupt status processing block here as issueHeader will do a start-of-message PDEBUGBLOCK
+        PDEBUGENDBLOCK("processStatus");
+        issueHeader(false);
+        PDEBUGBLOCKDESC("processStatus","finishing processing incoming SyncHdr Status");
+      }
+    }
+    // return handled status
+    return handled;
+    #endif // SYSYNC_SERVER
+  }
+  else {
+       // nothing special
+    return inherited::handleHeaderStatus(aStatusCmdP);
+  }
+} // TSyncAgent::handleHeaderStatus
+
+
+// - start sync group (called in client or server roles)
+bool TSyncAgent::processSyncStart(
+  SmlSyncPtr_t aSyncP,           // the Sync element
+  TStatusCommand &aStatusCommand, // pre-set 200 status, can be modified in case of errors
+  bool &aQueueForLater // will be set if command must be queued for later (re-)execution
+)
+{
+       if (IS_CLIENT) {
+       #ifdef SYSYNC_CLIENT
+    if (fIncomingState!=psta_sync && fIncomingState!=psta_initsync) {
+      aStatusCommand.setStatusCode(403); // forbidden in this context
+      PDEBUGPRINTFX(DBG_ERROR,("Sync command not allowed outside of sync phase (-> 403)"));
+      AbortSession(400,true);
+      return false;
+    }
+    // just find appropriate database, must be already initialized for sync!
+    // determine local database to sync with (target)
+    TLocalEngineDS *datastoreP = findLocalDataStoreByURI(smlSrcTargLocURIToCharP(aSyncP->target));
+    if (!datastoreP) {
+      // no such local datastore
+      PDEBUGPRINTFX(DBG_ERROR,("Sync command for unknown DS locURI '%s' (-> 404)",smlSrcTargLocURIToCharP(aSyncP->target)));
+      aStatusCommand.setStatusCode(404); // not found
+      return false;
+    }
+    else {
+      // save the pointer, will e.g. be used to route subsequent server commands
+      fLocalSyncDatastoreP=datastoreP;
+      // let local datastore know
+      return fLocalSyncDatastoreP->engProcessSyncCmd(aSyncP,aStatusCommand,aQueueForLater);
+    }
+    return true;
+               #endif // SYSYNC_CLIENT
+  }
+  else {
+    #ifdef SYSYNC_SERVER
+    // Init datastores for sync
+    localstatus sta = initSync(
+      smlSrcTargLocURIToCharP(aSyncP->target),  // local datastore
+      smlSrcTargLocURIToCharP(aSyncP->source)  // remote datastore
+    );
+    if (sta!=LOCERR_OK) {
+      aStatusCommand.setStatusCode(sta);
+      return false;
+    }
+    // let local datastore prepare for sync as server
+    // - let local process sync command
+    bool ok=fLocalSyncDatastoreP->engProcessSyncCmd(aSyncP,aStatusCommand,aQueueForLater);
+    // Note: ok means that the sync command is addressing existing datastores. However,
+    //       it does not mean that the actual processing is already executed; aQueueForLater
+    //       could be set!
+    // if ok and not queued: update package states
+    if (ok) {
+      if (fIncomingState==psta_init || fIncomingState==psta_initsync) {
+        // detected sync command in init package -> this is combined init/sync
+        #ifdef SYDEBUG
+        if (fIncomingState==psta_init)
+          DEBUGPRINTFX(DBG_HOT,("<Sync> started init package -> switching to combined init/sync"));
+        #endif
+        // - set new incoming state
+        fIncomingState=psta_initsync;
+        // - also update outgoing state, if it is in init package
+        if (fOutgoingState==psta_init)
+          fOutgoingState=psta_initsync;
+      }
+      else if (fCmdIncomingState!=psta_sync) {
+        DEBUGPRINTFX(DBG_ERROR,(
+          "<Sync> found in wrong incoming package state '%s' -> aborting session",
+          PackageStateNames[fCmdIncomingState]
+        ));
+        aStatusCommand.setStatusCode(403); // forbidden
+        fLocalSyncDatastoreP->engAbortDataStoreSync(403,true); // abort, local problem
+        ok=false;
+      }
+      else {
+        // - show sync start    
+        DEBUGPRINTFX(DBG_HOT,(
+          "<Sync> started, cmd-incoming state='%s', incoming state='%s', outgoing state='%s'",
+          PackageStateNames[fCmdIncomingState],
+          PackageStateNames[fIncomingState],
+          PackageStateNames[fOutgoingState]
+        ));
+      }
+    }
+    return ok;
+    #endif // SYSYNC_SERVER
+  }
+} // TSyncAgent::processSyncStart
+
+
+
+
+#ifdef ENGINEINTERFACE_SUPPORT
+
+// Support for EngineModule common interface
+// =========================================
+
+
+/// @brief Get new session key to access details of this session
+appPointer TSyncAgent::newSessionKey(TEngineInterface *aEngineInterfaceP)
+{
+       return new TAgentParamsKey(aEngineInterfaceP,this);
+} // TSyncAgent::newSessionKey
+
+
+#ifdef ENGINE_LIBRARY
+
+TSyError TSyncAgent::SessionStep(uInt16 &aStepCmd, TEngineProgressInfo *aInfoP)
+{
+       if (IS_CLIENT) {
+               #ifdef SYSYNC_CLIENT
+    return ClientSessionStep(aStepCmd,aInfoP);
+               #endif // SYSYNC_CLIENT
+  }
+  else {
+    #ifdef SYSYNC_SERVER
+    return ServerSessionStep(aStepCmd,aInfoP);
+    #endif // SYSYNC_SERVER
+  }
+} // TSyncAgent::SessionStep
+
+#endif // ENGINE_LIBRARY
+
+
+#ifdef SYSYNC_SERVER
+
+// Server implementation
+// ---------------------
+
+#ifndef ENGINE_LIBRARY
+
+// dummy server engine support to allow AsKey from plugins
+
+#warning "using ENGINEINTERFACE_SUPPORT in old-style appbase-rooted environment. Should be converted to real engine usage later"
+
+// Engine factory function for non-Library case
+ENGINE_IF_CLASS *newServerEngine(void)
+{
+  // For real engine based targets, newServerEngine must create a target-specific derivate
+  // of the server engine, which then has a suitable newSyncAppBase() method to create the
+  // appBase. For old-style environment, a generic TServerEngineInterface is ok, as this
+  // in turn calls the global newSyncAppBase() which then returns the appropriate
+  // target specific appBase. Here we just return a dummy server engine base.
+  return new TDummyServerEngineInterface;
+} // newServerEngine
+
+/// @brief returns a new application base.
+TSyncAppBase *TDummyServerEngineInterface::newSyncAppBase(void)
+{
+  // For not really engine based targets, the appbase factory function is
+  // a global routine (for real engine targets, it is a true virtual of
+  // the engineInterface, implemented in the target's leaf engineInterface derivate.
+  // - for now, use the global appBase creator routine
+  return sysync::newSyncAppBase(); // use global factory function 
+} // TDummyServerEngineInterface::newSyncAppBase
+
+#else // old style
+
+// Real server engine support
+
+/// @brief Executes next step of the session
+/// @param aStepCmd[in/out] step command (STEPCMD_xxx):
+///        - tells caller to send or receive data or end the session etc.
+///        - instructs engine to abort or time out the session etc.
+/// @param aInfoP[in] pointer to a TEngineProgressInfo structure, NULL if no progress info needed
+/// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure
+TSyError TSyncAgent::ServerSessionStep(uInt16 &aStepCmd, TEngineProgressInfo *aInfoP)
+{
+  uInt16 stepCmdIn = aStepCmd;
+  localstatus sta = LOCERR_WRONGUSAGE;
+
+  // init default response
+  aStepCmd = STEPCMD_ERROR; // error
+  if (aInfoP) {
+    aInfoP->eventtype=PEV_NOP;
+    aInfoP->targetID=0;
+    aInfoP->extra1=0;
+    aInfoP->extra2=0;
+    aInfoP->extra3=0;
+  }
+
+  // if session is already aborted, no more steps are required
+  if (isAborted()) {
+       fServerEngineState = ses_done; // we are done
+  }
+
+  // handle pre-processed step command according to current engine state
+  switch (fServerEngineState) {
+
+    // Done state
+    case ses_done :
+      // session done, nothing happens any more
+      aStepCmd = STEPCMD_DONE;
+      sta = LOCERR_OK;
+      break;
+
+    // Waiting for SyncML request data
+    case ses_needdata:
+      switch (stepCmdIn) {
+        case STEPCMD_GOTDATA : {
+               // got data, check content type
+          MemPtr_t data = NULL;
+          smlPeekMessageBuffer(getSmlWorkspaceID(), false, &data, &fRequestSize); // get request size      
+          SmlEncoding_t enc = TSyncAppBase::encodingFromData(data, fRequestSize);
+                                       if (getEncoding()==SML_UNDEF) {
+               // no encoding known so far - use what we found from looking at data
+            PDEBUGPRINTFX(DBG_ERROR,(
+               "Incoming data had no or invalid content type, Determined encoding by looking at data: %s",
+              SyncMLEncodingNames[enc]
+            ));
+            setEncoding(enc);
+          }
+          else if (getEncoding()!=enc) {
+               // already known encoding does not match actual encoding
+            PDEBUGPRINTFX(DBG_ERROR,(
+               "Warning: Incoming data encoding mismatch: expected=%s, found=%s",
+              SyncMLEncodingNames[getEncoding()],
+              SyncMLEncodingNames[enc]
+            ));
+          }
+          if (getEncoding()==SML_UNDEF) {
+               // if session encoding is still unknown at this point, reject data as non-SyncML
+            PDEBUGPRINTFX(DBG_ERROR,("Incoming data is not SyncML"));
+            sta = LOCERR_BADCONTENT; // bad content type
+                                   aStepCmd = STEPCMD_ERROR;
+            // Note: we do not abort the session here - app could have a retry strategy and re-enter
+            //       this step with better data
+            break;            
+          }
+          // content type ok - switch to processing mode
+          fServerEngineState = ses_processing;
+          aStepCmd = STEPCMD_OK;
+          sta = LOCERR_OK;
+          break;
+        }
+      } // switch stepCmdIn for ces_processing
+      break;
+
+    // Waiting until SyncML answer data is sent
+    // (only when session needs to continue, otherwise we are in ses_done)
+    case ses_dataready:
+      switch (stepCmdIn) {
+        case STEPCMD_SENTDATA :
+          // sent data, now wait for next request
+          fServerEngineState = ses_needdata;
+          aStepCmd = STEPCMD_NEEDDATA;
+          sta = LOCERR_OK;
+          break;
+      } // switch stepCmdIn for ces_processing
+      break;
+
+
+    // Ready for generation steps
+    case ses_generating:
+      switch (stepCmdIn) {
+        case STEPCMD_STEP :
+          sta = ServerGeneratingStep(aStepCmd,aInfoP);
+          break;
+      } // switch stepCmdIn for ces_generating
+      break;
+
+    // Ready for processing steps
+    case ses_processing:
+      switch (stepCmdIn) {
+        case STEPCMD_STEP :
+          sta = ServerProcessingStep(aStepCmd,aInfoP);
+          break;
+      } // switch stepCmdIn for ces_processing
+      break;
+
+  case numServerEngineStates:
+      // invalid
+      break;
+
+  } // switch fServerEngineState
+
+  // done
+  return sta;
+} // TSyncAgent::ServerSessionStep
+
+
+
+
+// Step that processes SyncML request data
+TSyError TSyncAgent::ServerProcessingStep(uInt16 &aStepCmd, TEngineProgressInfo *aInfoP)
+{
+  localstatus sta = LOCERR_WRONGUSAGE;
+  InstanceID_t myInstance = getSmlWorkspaceID();
+  Ret_t rc;
+
+  // now process next command
+  PDEBUGPRINTFX(DBG_EXOTIC,("Calling smlProcessData(NEXT_COMMAND)"));
+  #ifdef SYDEBUG
+  MemPtr_t data = NULL;
+  MemSize_t datasize;
+  smlPeekMessageBuffer(getSmlWorkspaceID(), false, &data, &datasize);
+  #endif  
+  rc=smlProcessData(
+    myInstance,
+    SML_NEXT_COMMAND
+  );
+  if (rc==SML_ERR_CONTINUE) {
+    // processed ok, but message not completely processed yet
+    // - engine state remains as is
+    aStepCmd = STEPCMD_OK; // ok w/o progress %%% for now, progress is delivered via queue in next step
+    sta = LOCERR_OK;
+  }
+  else if (rc==SML_ERR_OK) {
+    // message completely processed
+    // - switch engine state to generating answer message (if any)
+    aStepCmd = STEPCMD_OK;
+    fServerEngineState = ses_generating;
+    sta = LOCERR_OK;
+  }
+  else {
+    // processing failed
+    PDEBUGPRINTFX(DBG_ERROR,("===> smlProcessData failed, returned 0x%hX",(sInt16)rc));
+    // dump the message that failed to process
+    #ifdef SYDEBUG
+    if (data) DumpSyncMLBuffer(data,datasize,false,rc);
+    #endif    
+    // abort the session (causing proper error events to be generated and reported back)
+    AbortSession(LOCERR_PROCESSMSG, true);
+    // session is now done
+    fServerEngineState = ses_done;
+    // step by itself is ok - let app continue stepping (to restart session or complete abort)
+    aStepCmd = STEPCMD_OK;
+    sta = LOCERR_OK;
+  }
+  // done
+  return sta;
+} // TSyncAgent::ServerProcessingStep
+
+
+
+// Step that generates (rest of) SyncML answer data at end of request
+TSyError TSyncAgent::ServerGeneratingStep(uInt16 &aStepCmd, TEngineProgressInfo *aInfoP)
+{
+  bool done, hasdata;
+  string respURI;
+
+       // finish request
+       done = EndRequest(hasdata, respURI, fRequestSize);
+  // check different exit points
+  if (hasdata) {
+       // there is data to be sent
+    aStepCmd = STEPCMD_SENDDATA;
+    fServerEngineState = ses_dataready;
+  }
+  else {
+       // no more data to send
+       aStepCmd = STEPCMD_OK; // need one more step to finish
+  }
+  // in any case, if done, all susequent steps will return STEPCMD_DONE
+  if (done) {
+       // Session is done
+       TerminateSession();
+    // subsequent steps will all return STEPCMD_DONE
+       fServerEngineState = ses_done;
+  }
+  // request reset
+  fRequestSize = 0;
+  // return status
+  return LOCERR_OK;
+} // TSyncAgent::ServerGeneratingStep
+
+#endif // ENGINE_LIBRARY
+
+#endif // SYSYNC_SERVER
+
+
+#ifdef SYSYNC_CLIENT
+
+#ifdef ENGINE_LIBRARY
+
+// Client implementation
+// ---------------------
+
+/// @brief Executes next step of the session
+/// @param aStepCmd[in/out] step command (STEPCMD_xxx):
+///        - tells caller to send or receive data or end the session etc.
+///        - instructs engine to suspend or abort the session etc.
+/// @param aInfoP[in] pointer to a TEngineProgressInfo structure, NULL if no progress info needed
+/// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure
+TSyError TSyncAgent::ClientSessionStep(uInt16 &aStepCmd, TEngineProgressInfo *aInfoP)
+{
+  uInt16 stepCmdIn = aStepCmd;
+  localstatus sta = LOCERR_WRONGUSAGE;
+
+  // init default response
+  aStepCmd = STEPCMD_ERROR; // error
+  if (aInfoP) {
+    aInfoP->eventtype=PEV_NOP;
+    aInfoP->targetID=0;
+    aInfoP->extra1=0;
+    aInfoP->extra2=0;
+    aInfoP->extra3=0;
+  }
+
+  // if session is already aborted, no more steps are required
+  if (isAborted()) {
+       fClientEngineState = ces_done; // we are done
+  }
+
+  // handle pre-processed step command according to current engine state
+  switch (fClientEngineState) {
+
+    // Idle state
+    case ces_done : {
+      // session done, nothing happens any more
+      aStepCmd = STEPCMD_DONE;
+      sta = LOCERR_OK;
+      break;
+    }
+
+    case ces_idle : {
+      // in idle, we can only start a session
+      switch (stepCmdIn) {
+        case STEPCMD_CLIENTSTART:
+        case STEPCMD_CLIENTAUTOSTART:
+          // initialize a new session
+          sta = InitializeSession(fProfileSelectorInternal,stepCmdIn==STEPCMD_CLIENTAUTOSTART);
+          if (sta!=LOCERR_OK) break;
+          // engine is now ready, start generating first request
+          fClientEngineState = ces_generating;
+          // ok with no status
+          aStepCmd = STEPCMD_OK;
+          break;
+      } // switch stepCmdIn for ces_idle
+      break;
+    }
+
+    // Ready for generation steps
+    case ces_generating: {
+      switch (stepCmdIn) {
+        case STEPCMD_STEP :
+          sta = ClientGeneratingStep(aStepCmd,aInfoP);
+          break;
+      } // switch stepCmdIn for ces_generating
+      break;
+    }
+
+    // Ready for processing steps
+    case ces_processing: {
+      switch (stepCmdIn) {
+        case STEPCMD_STEP :
+          sta = ClientProcessingStep(aStepCmd,aInfoP);
+          break;
+      } // switch stepCmdIn for ces_processing
+      break;
+    }
+
+    // Waiting for SyncML data
+    case ces_needdata: {
+      switch (stepCmdIn) {
+        case STEPCMD_GOTDATA : {
+          // got data, now start processing it
+          OBJ_PROGRESS_EVENT(getSyncAppBase(),pev_recvend,NULL,0,0,0);
+          // check content type now
+          MemPtr_t data = NULL;
+          MemSize_t datasize;
+          smlPeekMessageBuffer(getSmlWorkspaceID(), false, &data, &datasize);
+          // check content type
+          SmlEncoding_t enc = TSyncAppBase::encodingFromData(data, datasize);
+          if (enc!=getEncoding()) {
+            PDEBUGPRINTFX(DBG_ERROR,("Incoming data is not SyncML"));
+            sta = LOCERR_BADCONTENT; // bad content type
+            #ifdef SYDEBUG
+            if (data) DumpSyncMLBuffer(data,datasize,false,SML_ERR_UNSPECIFIC);
+            #endif    
+            // abort the session (causing proper error events to be generated and reported back)
+            AbortSession(sta, true);
+            // session is now done
+            fClientEngineState = ces_done;
+                                   aStepCmd = STEPCMD_ERROR;
+            break;
+          }
+          // content type ok - switch to processing mode
+          fIgnoreMsgErrs=false; // do not ignore errors by default
+          fClientEngineState = ces_processing;
+          aStepCmd = STEPCMD_OK;
+          sta = LOCERR_OK;
+          break;
+        }
+        case STEPCMD_RESENDDATA :
+               // instead of having received new data, the network layer has found it needs to re-send the data.
+          // performing the STEPCMD_RESENDDATA just generates a new send start event, but otherwise no engine action
+          fClientEngineState = ces_resending;
+          aStepCmd = STEPCMD_RESENDDATA; // return the same step command, to differentiate it from STEPCMD_SENDDATA
+          OBJ_PROGRESS_EVENT(getSyncAppBase(),pev_sendstart,NULL,0,0,0);
+          sta = LOCERR_OK;
+          break;
+      } // switch stepCmdIn for ces_needdata
+      break;
+    }
+
+    // Waiting until SyncML data is sent
+    case ces_dataready:
+    case ces_resending: {
+      switch (stepCmdIn) {
+        case STEPCMD_SENTDATA :
+               // allowed in dataready or resending state
+          // sent (or re-sent) data, now request answer data
+          OBJ_PROGRESS_EVENT(getSyncAppBase(),pev_sendend,NULL,0,0,0);
+          fClientEngineState = ces_needdata;
+          aStepCmd = STEPCMD_NEEDDATA;
+          sta = LOCERR_OK;
+          break;
+      } // switch stepCmdIn for ces_dataready
+      break;
+    }
+
+       case numClientEngineStates: {
+      // invalid
+      break;
+    }
+
+  } // switch fClientEngineState
+
+  // done
+  return sta;
+} // TSyncAgent::ClientSessionStep
+
+
+
+// Step that generates SyncML data
+TSyError TSyncAgent::ClientGeneratingStep(uInt16 &aStepCmd, TEngineProgressInfo *aInfoP)
+{
+  localstatus sta = LOCERR_WRONGUSAGE;
+  bool done;
+
+  //%%% at this time, generate next message in one step
+  sta = NextMessage(done);
+  if (done) {
+    // done with session, with or without error
+    fClientEngineState = ces_done; // blocks any further activity with the session
+    aStepCmd = STEPCMD_DONE;
+    // terminate session to provoke all end-of-session progress events
+    TerminateSession();
+  }
+  else if (sta==LOCERR_OK) {
+       // finished generating outgoing message
+    // - make sure read pointer is set (advanced in case incoming
+    //   message had trailing garbage) to beginning of generated
+    //   answer. With incoming message being clean SyncML without
+    //   garbage, this call is not needed, however with garbage
+    //   it is important because otherwise outgoing message
+    //   would have that garbage inserted before actual message
+    //   start.
+    smlReadOutgoingAgain(getSmlWorkspaceID());
+    // next is sending request to server
+    fClientEngineState = ces_dataready;
+    aStepCmd = STEPCMD_SENDDATA;
+    OBJ_PROGRESS_EVENT(getSyncAppBase(),pev_sendstart,NULL,0,0,0);
+  }
+  // return status
+  return sta;
+} // TSyncAgent::ClientGeneratingStep
+
+
+
+// Step that processes SyncML data
+TSyError TSyncAgent::ClientProcessingStep(uInt16 &aStepCmd, TEngineProgressInfo *aInfoP)
+{
+  InstanceID_t myInstance = getSmlWorkspaceID();
+  Ret_t rc;
+  localstatus sta = LOCERR_WRONGUSAGE;
+
+  // now process next command
+  PDEBUGPRINTFX(DBG_EXOTIC,("Calling smlProcessData(NEXT_COMMAND)"));
+  #ifdef SYDEBUG
+  MemPtr_t data = NULL;
+  MemSize_t datasize;
+  smlPeekMessageBuffer(getSmlWorkspaceID(), false, &data, &datasize);
+  #endif  
+  rc=smlProcessData(
+    myInstance,
+    SML_NEXT_COMMAND
+  );
+  if (rc==SML_ERR_CONTINUE) {
+    // processed ok, but message not completely processed yet
+    // - engine state remains as is
+    aStepCmd = STEPCMD_OK; // ok w/o progress %%% for now, progress is delivered via queue in next step
+    sta = LOCERR_OK;
+  }
+  else if (rc==SML_ERR_OK) {
+    // message completely processed
+    // - switch engine state to generating next message (if any)
+    aStepCmd = STEPCMD_OK;
+    fClientEngineState = ces_generating;
+    sta = LOCERR_OK;
+  }
+  else {
+    // processing failed
+    PDEBUGPRINTFX(DBG_ERROR,("===> smlProcessData failed, returned 0x%hX",(sInt16)rc));
+    // dump the message that failed to process
+    #ifdef SYDEBUG
+    if (data) DumpSyncMLBuffer(data,datasize,false,rc);
+    #endif    
+    if (!fIgnoreMsgErrs) {
+           // abort the session (causing proper error events to be generated and reported back)
+       AbortSession(LOCERR_PROCESSMSG, true);
+      // session is now done
+      fClientEngineState = ces_done;
+    }
+    else {
+       // we must ignore errors e.g. because of session restart and go back to generate next message
+      fClientEngineState = ces_generating;
+    }
+    // anyway, step by itself is ok - let app continue stepping (to restart session or complete abort)
+    aStepCmd = STEPCMD_OK;
+    sta = LOCERR_OK;
+  }
+  // now check if this is a session restart
+  if (sta==LOCERR_OK && isStarting()) {
+    // this is still the beginning of a session, which means
+    // that we are restarting the session and caller should close
+    // eventually open communication with the server before sending the next message
+    aStepCmd = STEPCMD_RESTART;
+  }
+  // done
+  return sta;
+} // TSyncAgent::ClientProcessingStep
+
+#endif // ENGINE_LIBRARY
+
+#endif // SYSYNC_CLIENT
+
+
+
+// Session runtime settings key
+// ---------------------------
+
+// Constructor
+TAgentParamsKey::TAgentParamsKey(TEngineInterface *aEngineInterfaceP, TSyncAgent *aAgentP) :
+  inherited(aEngineInterfaceP,aAgentP),
+  fAgentP(aAgentP)
+{
+} // TAgentParamsKey::TAgentParamsKey
+
+
+
+// - read local session ID
+static TSyError readLocalSessionID(
+  TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
+  appPointer aBuffer, memSize aBufSize, memSize &aValSize
+)
+{
+  TAgentParamsKey *mykeyP = static_cast<TAgentParamsKey *>(aStructFieldsKeyP);
+  return TStructFieldsKey::returnString(
+    mykeyP->fAgentP->getLocalSessionID(),
+    aBuffer,aBufSize,aValSize
+  );
+} // readLocalSessionID
+
+
+// - read initial local URI
+static TSyError readInitialLocalURI(
+  TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
+  appPointer aBuffer, memSize aBufSize, memSize &aValSize
+)
+{
+  TAgentParamsKey *mykeyP = static_cast<TAgentParamsKey *>(aStructFieldsKeyP);
+  return TStructFieldsKey::returnString(
+    mykeyP->fAgentP->getInitialLocalURI(),
+    aBuffer,aBufSize,aValSize
+  );
+} // readInitialLocalURI
+
+
+// - read abort status
+static TSyError readAbortStatus(
+  TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
+  appPointer aBuffer, memSize aBufSize, memSize &aValSize
+)
+{
+  TAgentParamsKey *mykeyP = static_cast<TAgentParamsKey *>(aStructFieldsKeyP);
+  return TStructFieldsKey::returnInt(
+       mykeyP->fAgentP->getAbortReasonStatus(),
+    sizeof(TSyError),
+    aBuffer,aBufSize,aValSize
+  );
+} // readAbortStatus
+
+
+
+// - write abort status, which means aborting a session
+TSyError writeAbortStatus(
+  TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
+  cAppPointer aBuffer, memSize aValSize
+)
+{
+  TAgentParamsKey *mykeyP = static_cast<TAgentParamsKey *>(aStructFieldsKeyP);
+  // abort the session
+  TSyError sta = *((TSyError *)aBuffer);
+       mykeyP->fAgentP->AbortSession(sta, true);
+  return LOCERR_OK;
+} // writeAbortStatus
+
+
+
+// - read content type string
+static TSyError readContentType(
+  TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
+  appPointer aBuffer, memSize aBufSize, memSize &aValSize
+)
+{
+  TAgentParamsKey *mykeyP = static_cast<TAgentParamsKey *>(aStructFieldsKeyP);
+  string contentType = SYNCML_MIME_TYPE;
+  mykeyP->fAgentP->addEncoding(contentType);
+  return TStructFieldsKey::returnString(
+    contentType.c_str(),
+    aBuffer,aBufSize,aValSize
+  );
+} // readContentType
+
+
+// - write content type string
+static TSyError writeContentType(
+  TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
+  cAppPointer aBuffer, memSize aValSize
+)
+{
+  string contentType((cAppCharP)aBuffer,aValSize);
+  TAgentParamsKey *mykeyP = static_cast<TAgentParamsKey *>(aStructFieldsKeyP);
+  mykeyP->fAgentP->setEncoding(TSyncAppBase::encodingFromContentType(contentType.c_str()));
+  return LOCERR_OK;
+} // writeContentType
+
+
+// - read connection URL
+static TSyError readConnectURI(
+  TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
+  appPointer aBuffer, memSize aBufSize, memSize &aValSize
+)
+{
+  TAgentParamsKey *mykeyP = static_cast<TAgentParamsKey *>(aStructFieldsKeyP);
+  return TStructFieldsKey::returnString(
+    mykeyP->fAgentP->getSendURI(),
+    aBuffer,aBufSize,aValSize
+  );
+} // readConnectURI
+
+
+// - read host part of connection URL
+static TSyError readConnectHost(
+  TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
+  appPointer aBuffer, memSize aBufSize, memSize &aValSize
+)
+{
+  TAgentParamsKey *mykeyP = static_cast<TAgentParamsKey *>(aStructFieldsKeyP);
+  string host;
+  splitURL(mykeyP->fAgentP->getSendURI(),NULL,&host,NULL,NULL,NULL);
+  return TStructFieldsKey::returnString(
+    host.c_str(),
+    aBuffer,aBufSize,aValSize
+  );
+} // readConnectHost
+
+
+// - read document part of connection URL
+static TSyError readConnectDoc(
+  TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
+  appPointer aBuffer, memSize aBufSize, memSize &aValSize
+)
+{
+  TAgentParamsKey *mykeyP = static_cast<TAgentParamsKey *>(aStructFieldsKeyP);
+  string doc;
+  splitURL(mykeyP->fAgentP->getSendURI(),NULL,NULL,&doc,NULL,NULL);
+  return TStructFieldsKey::returnString(
+    doc.c_str(),
+    aBuffer,aBufSize,aValSize
+  );
+} // readConnectDoc
+
+
+// - time when session was last used
+static TSyError readLastUsed(
+  TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
+  appPointer aBuffer, memSize aBufSize, memSize &aValSize
+)
+{
+  TAgentParamsKey *mykeyP = static_cast<TAgentParamsKey *>(aStructFieldsKeyP);
+  // return it
+  return TStructFieldsKey::returnLineartime(mykeyP->fAgentP->getSessionLastUsed(), aBuffer, aBufSize, aValSize);
+} // readLastUsed
+
+
+// - server only: check session timeout
+static TSyError readTimedOut(
+  TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
+  appPointer aBuffer, memSize aBufSize, memSize &aValSize
+)
+{
+  TAgentParamsKey *mykeyP = static_cast<TAgentParamsKey *>(aStructFieldsKeyP);
+       // check if session has timed out
+  bool timedout = mykeyP->fAgentP->getSessionLastUsed()+mykeyP->fAgentP->getSessionConfig()->getSessionTimeout() < mykeyP->fAgentP->getSystemNowAs(TCTX_UTC);
+  // return it
+  return TStructFieldsKey::returnInt(timedout, sizeof(bool), aBuffer, aBufSize, aValSize);
+} // readTimedOut
+
+
+#ifdef SYSYNC_SERVER
+
+// - server only: read respURI enable flag
+static TSyError readSendRespURI(
+  TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
+  appPointer aBuffer, memSize aBufSize, memSize &aValSize
+)
+{
+  TAgentParamsKey *mykeyP = static_cast<TAgentParamsKey *>(aStructFieldsKeyP);
+  return TStructFieldsKey::returnInt(mykeyP->fAgentP->fUseRespURI, sizeof(bool), aBuffer, aBufSize, aValSize);
+} // readSendRespURI
+
+
+// - write respURI enable flag
+static TSyError writeSendRespURI(
+  TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
+  cAppPointer aBuffer, memSize aValSize
+)
+{
+  TAgentParamsKey *mykeyP = static_cast<TAgentParamsKey *>(aStructFieldsKeyP);
+       mykeyP->fAgentP->fUseRespURI = *((uInt8P)aBuffer);
+  return LOCERR_OK;
+} // writeSendRespURI
+
+
+#endif // SYSYNC_SERVER
+
+
+#ifdef SYSYNC_CLIENT
+
+// - write (volatile, write-only) password for running this session
+// (for cases where we don't want to rely on binfile storage for sensitive password data)
+TSyError writeSessionPassword(
+  TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
+  cAppPointer aBuffer, memSize aValSize
+)
+{
+  TAgentParamsKey *mykeyP = static_cast<TAgentParamsKey *>(aStructFieldsKeyP);
+       mykeyP->fAgentP->setServerPassword((cAppCharP)aBuffer, aValSize);
+  return LOCERR_OK;
+} // writeSessionPassword
+
+
+#ifdef ENGINE_LIBRARY
+// - read display alert
+static TSyError readDisplayAlert(
+  TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
+  appPointer aBuffer, memSize aBufSize, memSize &aValSize
+)
+{
+  TClientEngineInterface *clientEngineP =
+    static_cast<TClientEngineInterface *>(aStructFieldsKeyP->getEngineInterface());
+  return TStructFieldsKey::returnString(
+    clientEngineP->fAlertMessage.c_str(),
+    aBuffer,aBufSize,aValSize
+  );
+} // readDisplayAlert
+#endif
+
+#endif // SYSYNC_CLIENT
+
+
+// accessor table for server session key
+static const TStructFieldInfo ServerParamFieldInfos[] =
+{  
+  // valName, valType, writable, fieldOffs, valSiz
+  { "localSessionID", VALTYPE_TEXT, false, 0, 0, &readLocalSessionID, NULL },
+  { "initialLocalURI", VALTYPE_TEXT, false, 0, 0, &readInitialLocalURI, NULL },
+  { "abortStatus", VALTYPE_INT16, true, 0, 0, &readAbortStatus, &writeAbortStatus },
+  { "contenttype", VALTYPE_TEXT, true, 0, 0, &readContentType, &writeContentType },
+  { "connectURI", VALTYPE_TEXT, false, 0, 0, &readConnectURI, NULL },
+  { "connectHost", VALTYPE_TEXT, false, 0, 0, &readConnectHost, NULL },
+  { "connectDoc", VALTYPE_TEXT, false, 0, 0, &readConnectDoc, NULL },
+  { "timedout", VALTYPE_INT8, false, 0, 0, &readTimedOut, NULL },
+  { "lastused", VALTYPE_TIME64, false, 0, 0, &readLastUsed, NULL },
+  #ifdef SYSYNC_SERVER
+  { "sendrespuri", VALTYPE_INT8, true, 0, 0, &readSendRespURI, &writeSendRespURI },
+  #endif
+  #ifdef SYSYNC_CLIENT
+  { "sessionPassword", VALTYPE_TEXT, true, 0, 0, NULL, &writeSessionPassword },
+  #ifdef ENGINE_LIBRARY
+  { "displayalert", VALTYPE_TEXT, false, 0, 0, &readDisplayAlert, NULL },
+  #endif
+  #endif
+};
+
+// get table describing the fields in the struct
+const TStructFieldInfo *TAgentParamsKey::getFieldsTable(void)
+{
+  return ServerParamFieldInfos;
+} // TAgentParamsKey::getFieldsTable
+
+sInt32 TAgentParamsKey::numFields(void)
+{
+  return sizeof(ServerParamFieldInfos)/sizeof(TStructFieldInfo);
+} // TAgentParamsKey::numFields
+
+// get actual struct base address
+uInt8P TAgentParamsKey::getStructAddr(void)
+{
+  // prepared for accessing fields in server session object
+  return (uInt8P)fAgentP;
+} // TAgentParamsKey::getStructAddr
+
+
+// open subkey by name (not by path!)
+TSyError TAgentParamsKey::OpenSubKeyByName(
+  TSettingsKeyImpl *&aSettingsKeyP,
+  cAppCharP aName, stringSize aNameSize,
+  uInt16 aMode
+) {
+  #ifdef DBAPI_TUNNEL_SUPPORT
+  if (strucmp(aName,"tunnel",aNameSize)==0) {
+    // get tunnel datastore pointer
+    TLocalEngineDS *ds = fAgentP->getTunnelDS();
+    if (!ds) return LOCERR_WRONGUSAGE;
+    // opens current session's tunnel key
+    aSettingsKeyP = ds->newTunnelKey(fEngineInterfaceP);
+  }
+  else
+  #endif
+    return inherited::OpenSubKeyByName(aSettingsKeyP,aName,aNameSize,aMode);
+  // opened a key
+  return LOCERR_OK;
+} // TAgentParamsKey::OpenSubKeyByName
+
+
+#endif // ENGINEINTERFACE_SUPPORT
+
+} // namespace sysync
+
+// eof
similarity index 60%
rename from src/synthesis/src/sysync/syncclient.h
rename to src/synthesis/src/sysync/syncagent.h
index 16c73ea..8a11522 100755 (executable)
@@ -1,24 +1,22 @@
 /*
- *  File:         SyncClient.h
+ *  File:         SyncAgent.h
  *
  *  Author:                      Lukas Zeller (luz@synthesis.ch)
  *
- *  TSyncClient
- *    Provides functionality required for a Synchronisation
- *    client.
+ *  TSyncAgent:   Provides functionality to run client or server
+ *                sessions.
+ *                Unifies former TSyncClient and TSyncServer
  *
  *  Copyright (c) 2002-2009 by Synthesis AG (www.synthesis.ch)
  *
- *  2002-05-06 : luz : created from old SyncClient.h (which was a
- *                     intermediate class between server and session,
- *                     as initially we considered a client-server
- *                     combined class. Now both SyncClient and
- *                     SyncServer are directly derived from SyncSession
+ *  2009-09-30 : luz : created from syncclient.h and syncserver.h
  *
  */
 
-#ifndef SyncClient_H
-#define SyncClient_H
+#ifndef SYNC_AGENT_H
+#define SYNC_AGENT_H
+
+#include "engine_defs.h"
 
 //%%% we still need this at this time
 #define NON_FULLY_GRANULAR_ENGINE 1
@@ -31,11 +29,9 @@ namespace sysync {
 #endif
 
 
-
-// includes
 #include "syncsession.h"
-#include "syncclientbase.h"
 #include "localengineds.h"
+#include "remotedatastore.h"
 
 #include "engineinterface.h"
 
@@ -46,6 +42,30 @@ using namespace sysync;
 namespace sysync {
 
 
+#ifndef SYSYNC_SERVER
+// dummy session handle type for client-only case to allow unified constructor
+class TSyncSessionHandle {
+};
+#endif
+
+// Support for SySync Diagnostic Tool
+#ifdef SYSYNC_TOOL
+int testLogin(int argc, const char *argv[]);
+int convertData(int argc, const char *argv[]);
+#endif
+
+
+/// @brief server engine state
+typedef enum {
+  ses_needdata,     ///< need SyncML request data, waiting for STEPCMD_GOTDATA
+  ses_processing,   ///< ready to perform next STEPCMD_STEP to process SyncML messages
+  ses_generating,   ///< ready to perform next STEPCMD_STEP to generate SyncML messages
+  ses_dataready,    ///< data is ready to be sent, waiting for STEPCMD_SENTDATA  
+  ses_done,         ///< session done
+  numServerEngineStates
+} TServerEngineState;
+
+
 /// @brief client engine state
 typedef enum {
   ces_idle,         ///< client engine is idle and can be initialized with STEPCMD_CLIENTSTART
@@ -55,7 +75,6 @@ typedef enum {
   ces_needdata,     ///< need response data, waiting for STEPCMD_GOTDATA
   ces_processing,   ///< ready to perform next STEPCMD_STEP to process SyncML messages
   ces_done,         ///< session done
-
   numClientEngineStates
 } TClientEngineState;
 
@@ -107,17 +126,25 @@ typedef std::list<TSyncReqConfig *> TSyncReqList;
 
 #endif
 
+
 // forward
-class TSyncClient;
+class TSyncAgent;
+#ifdef SYSYNC_SERVER
+class TSyncSessionHandle;
+#endif
+#ifdef SYSYNC_CLIENT
+class TSyncClientBase;
+#endif
 
-// client config
-class TClientConfig: public TSessionConfig
+// agent (client or server) config
+class TAgentConfig: public TSessionConfig
 {
   typedef TSessionConfig inherited;
 public:
-  TClientConfig(const char *aElementName, TConfigElement *aParentElementP);
-  virtual ~TClientConfig();
-  // Local config
+  TAgentConfig(const char *aElementName, TConfigElement *aParentElementP);
+  virtual ~TAgentConfig();
+  #ifdef SYSYNC_CLIENT
+  // Local client config
   // - syncml version
   TSyncMLVersions fAssumedServerVersion; // we use this version for first connect attempt
   // - PUT devinf at every slow sync?? (smartner server needs this)
@@ -159,54 +186,102 @@ public:
   // - for debug only - used to fake a devID in the config file (useful when testing)
   string fFakeDeviceID;
   #endif
-protected:
+  #endif // SYSYNC_CLIENT
+  #ifdef SYSYNC_SERVER
+  // General server settings
+  // - requested auth type (Auth requested in Chal sent to client)
+  TAuthTypes fRequestedAuth;
+  // - minimally required auth type (lowest auth type that is allowed)
+  TAuthTypes fRequiredAuth;
+  // - use automatic nonce generation for MD5 auth (empty nonce if false)
+  bool fAutoNonce;
+  // - constant nonce string to be used if autononce is off. If empty, no nonce is used
+  string fConstantNonce;
+  // - constant external URL, if set, it is used to generate RespURI (instead of Target LocURI sent by client)
+  string fExternalURL;
+  // - max size of GUID sent if client does not specify a MaxGUIDSize in devInf. 0=unlimited
+  uInt16 fMaxGUIDSizeSent;
+  // - respURI
+  bool fUseRespURI;
+  bool fRespURIOnlyWhenDifferent;  
+  #endif // SYSYNC_SERVER
   // check config elements
   #ifndef HARDCODED_CONFIG
   virtual bool localStartElement(const char *aElementName, const char **aAttributes, sInt32 aLine);
   #endif
   virtual void clear();
   virtual void localResolve(bool aLastPass);
-public:
+       #ifdef SYSYNC_SERVER
+  // create appropriate session (=agent) for this server
+  virtual TSyncAgent *CreateServerSession(TSyncSessionHandle *aSessionHandle, const char *aSessionID)=0;
+  #endif
+  #ifdef SYSYNC_CLIENT
   // create appropriate session (=agent) for this client
-  virtual TSyncClient *CreateClientSession(cAppCharP aSessionID) = 0;
-}; // TClientConfig
-
+  virtual TSyncAgent *CreateClientSession(cAppCharP aSessionID) = 0;
+  #endif
+}; // TAgentConfig
 
 
-class TSyncClientBase;
-
 // default profile ID
 #define DEFAULT_PROFILE_ID 0xFFFFFFFF
 #define TUNNEL_PROFILE_ID 0xFFFFFFFE
 
-class TSyncClient: public TSyncSession
+class TSyncAgent: public TSyncSession
 {
   typedef TSyncSession inherited;
 public:
-  TSyncClient(
-    TSyncClientBase *aSyncClientBaseP,
+  TSyncAgent(
+    TSyncAppBase *aAppBaseP,
+    TSyncSessionHandle *aSessionHandleP,
     cAppCharP aSessionID // a session ID
-  );
-  virtual ~TSyncClient();
+  );  
+  virtual ~TSyncAgent();
   virtual void TerminateSession(void); // Terminate session, like destructor, but without actually destructing object itself
   virtual void ResetSession(void); // Resets session (but unlike TerminateSession, session might be re-used)
   void InternalResetSession(void); // static implementation for calling through virtual destructor and virtual ResetSession();
+
   #ifdef ENGINEINTERFACE_SUPPORT
-  // set profileID to client session before doing first SessionStep
-  virtual void SetProfileSelector(uInt32 aProfileSelector) { fProfileSelectorInternal = aProfileSelector; /* default is just passing it on */ };
+  #ifdef ENGINE_LIBRARY
   // Support for EngineModule common interface
   /// @brief Executes next step of the session
   /// @param aStepCmd[in/out] step command (STEPCMD_xxx):
   ///        - tells caller to send or receive data or end the session etc.
-  ///        - instructs engine to suspend or abort the session etc.
+  ///        - instructs engine to abort or time out the session etc.
   /// @param aInfoP[in] pointer to a TEngineProgressInfo structure, NULL if no progress info needed
   /// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure
   TSyError SessionStep(uInt16 &aStepCmd, TEngineProgressInfo *aInfoP);
+  #endif
   /// @brief Get new session key to access details of this session
   virtual appPointer newSessionKey(TEngineInterface *aEngineInterfaceP);
   #endif // ENGINEINTERFACE_SUPPORT
 
+       // Server & Client common:
+       // - message start and end
+  virtual bool MessageStarted(SmlSyncHdrPtr_t aContentP, TStatusCommand &aStatusCommand, bool aBad=false);
+  virtual void MessageEnded(bool aIncomingFinal);
+  // - handle status received for SyncHdr, returns false if not handled
+  virtual bool handleHeaderStatus(TStatusCommand *aStatusCmdP);
+  // - start <sync> command group
+  virtual bool processSyncStart(
+    SmlSyncPtr_t aSyncP,           // the Sync element
+    TStatusCommand &aStatusCommand, // pre-set 200 status, can be modified in case of errors
+    bool &aQueueForLater // will be set if command must be queued for later (re-)execution
+  );
+  // - info about needed auth type
+  virtual TAuthTypes requestedAuthType(void);
+  virtual bool isAuthTypeAllowed(TAuthTypes aAuthType);
+  // - called when incoming SyncHdr fails to execute
+  virtual bool syncHdrFailure(bool aTryAgain);
+  // device info (uses defaults in this base class, override to customize)
+  virtual string getDeviceType(void);
+  virtual string getDeviceID(void);
+
 
+       #ifdef SYSYNC_CLIENT
+  #ifdef ENGINE_LIBRARY
+  // set profileID to client session before doing first SessionStep
+  virtual void SetProfileSelector(uInt32 aProfileSelector) { fProfileSelectorInternal = aProfileSelector; /* default is just passing it on */ };
+  #endif // ENGINE_LIBRARY
   // session set-up
   // - initialize the client session, select the profile and link session with SML instance
   //   for the correct encoding
@@ -218,8 +293,6 @@ public:
   // - Prepares connection-related stuff. Will be called after all
   //   session init is done, but before first request is sent
   virtual localstatus PrepareConnect(void) { return LOCERR_OK; };
-  // called when incoming SyncHdr fails to execute
-  virtual bool syncHdrFailure(bool aTryAgain);
   // retry older protocol, returns false if no older protocol to try
   bool retryOlderProtocol(bool aSameVersionRetry=false, bool aOldMessageInBuffer=false);
   // prepares client session such that it will do a retry to start a session
@@ -237,8 +310,6 @@ public:
   //   returns aDone if no answer needs to be sent (=end of session)
   //   returns <>0 SyncML error status on error (no SyncML answer could be generated)
   localstatus NextMessage(bool &aDone);
-  // info about session
-  virtual bool IsServerSession(void) { return false; }; // is client
   // URI to send outgoing message to
   virtual cAppCharP getSendURI(void) { return fRespondURI.c_str(); }; // use respondURI
   // login
@@ -253,26 +324,37 @@ public:
   cAppCharP getProxyHost(void) { return fProxyHost.c_str(); };
   cAppCharP getProxyUser(void) { return fProxyUser.c_str(); };
   cAppCharP getProxyPassword(void) { return fProxyPassword.c_str(); };
-  // info about needed auth type
-  virtual TAuthTypes requestedAuthType(void) { return auth_none; }; // client does not require auth by default
-  virtual bool isAuthTypeAllowed(TAuthTypes /* aAuthType */) { return true; }; // client accepts any auth by default
   // special behaviour
   virtual bool devidWithUserHash(void) { return false; }; // do not include user name to make a hash-based pseudo-device ID by default
   // session handling
   // - get client base
   TSyncClientBase *getClientBase(void);
-  // Session level command handling
-  // - handle status received for SyncHdr, returns false if not handled
-  virtual bool handleHeaderStatus(TStatusCommand *aStatusCmdP);
-  // Sync processing (command group)
-  // - start sync group
-  virtual bool processSyncStart(
-    SmlSyncPtr_t aSyncP,           // the Sync element
-    TStatusCommand &aStatusCommand, // pre-set 200 status, can be modified in case of errors
-    bool &aQueueForLater // will be set if command must be queued for later (re-)execution
-  );
-protected:
+  #endif // SYSYNC_CLIENT
+
+  #ifdef SYSYNC_SERVER
+  virtual SmlPcdataPtr_t newResponseURIForRemote(void); // response URI
+  // Request processing
+  // - end of request (to make sure even incomplete SyncML messages get cleaned up properly)
+  bool EndRequest(bool &aHasData, string &aRespURI, uInt32 aReqBytes); // returns true if session must be deleted
+  // - buffer answer in the session's buffer if transport allows it
+  Ret_t bufferAnswer(MemPtr_t aAnswer, MemSize_t aAnswerSize);
+  // - get buffered answer from the session's buffer if there is any
+  void getBufferedAnswer(MemPtr_t &aAnswer, MemSize_t &aAnswerSize);
+  // - get byte statistics
+  virtual uInt32 getIncomingBytes(void) { return fIncomingBytes; };
+  virtual uInt32 getOutgoingBytes(void) { return fOutgoingBytes; };
+  // session handling
+  // - get session Handle pointer
+  TSyncSessionHandle *getSessionHandle(void) { return fSessionHandleP; }
+  // returns remaining time for request processing [seconds]
+  virtual sInt32 RemainingRequestTime(void);
+  // info about server status
+  virtual bool serverBusy(void); // return busy status (set by connection limit or app expiry)
+  #endif // SYSYNC_SERVER
+    
+       #ifdef SYSYNC_CLIENT
   // variables
+protected:
   // - socks and proxy hosts if any
   string fSocksHost;
   string fProxyHost;
@@ -296,11 +378,8 @@ protected:
   virtual cAppCharP  getUsernameForRemote(void) { return fServerUser.c_str(); }; // specified user name
   // internal processing events
   // - message start and end
-  virtual bool MessageStarted(SmlSyncHdrPtr_t aContentP, TStatusCommand &aStatusCommand, bool aBad=false);
-  virtual void MessageEnded(bool aIncomingFinal);
-  // device info (uses defaults in this base class, override to customize)
-  virtual string getDeviceType(void);
-  virtual string getDeviceID(void);
+  virtual bool ClientMessageStarted(SmlSyncHdrPtr_t aContentP, TStatusCommand &aStatusCommand, bool aBad=false);
+  virtual void ClientMessageEnded(bool aIncomingFinal);
   // if set, SML processing errors will not be reported
   // (in case session wants to re-try something)
   bool fIgnoreMsgErrs;
@@ -310,18 +389,20 @@ protected:
   uInt32 fServerURICRC;
   uInt8 fNoCRCPrefixLen;
   #endif
-  #ifdef ENGINEINTERFACE_SUPPORT
+  #ifdef ENGINE_LIBRARY
   // Engine interface
+  // - process step
+  TSyError ClientSessionStep(uInt16 &aStepCmd, TEngineProgressInfo *aInfoP);
   // - Step that generates SyncML data
-  TSyError generatingStep(uInt16 &aStepCmd, TEngineProgressInfo *aInfoP);
+  TSyError ClientGeneratingStep(uInt16 &aStepCmd, TEngineProgressInfo *aInfoP);
   // - Step that processes SyncML data
-  TSyError processingStep(uInt16 &aStepCmd, TEngineProgressInfo *aInfoP);
+  TSyError ClientProcessingStep(uInt16 &aStepCmd, TEngineProgressInfo *aInfoP);
   // - internal profile selector (can be ID or index) determined with
   //   SetProfileSelector(), to be used with SelectProfile()
   uInt32 fProfileSelectorInternal;
   // - Client engine state
-  TClientEngineState fEngineState;
-  #endif // ENGINEINTERFACE_SUPPORT
+  TClientEngineState fClientEngineState;
+  #endif // ENGINE_LIBRARY
   // - client side consecutive Alert 222, used to detect endless loop
   uInt32 fOutgoingAlert222Count;
   // Loop detecting time frame to avoid wrong detection of "keep-alive" message
@@ -333,7 +414,62 @@ public:
   // - can be cleared to suppress automatic use of DS 1.2 SINCE/BEFORE filters
   //   (e.g. for date range in func_SetDaysRange())
   bool fServerHasSINCEBEFORE;
-}; // TSyncClient
+  #endif // SYSYNC_CLIENT
+
+  #ifdef SYSYNC_SERVER
+public:
+  // respuri
+  bool fUseRespURI;
+protected:
+  // access to config
+  TAgentConfig *getServerConfig(void);
+  // internal processing events
+  // - message start and end
+  virtual bool ServerMessageStarted(SmlSyncHdrPtr_t aContentP, TStatusCommand &aStatusCommand, bool aBad=false);
+  virtual void ServerMessageEnded(bool aIncomingFinal);
+  // - request end, called by EndRequest, virtual for descendants
+  virtual void RequestEnded(bool &aHasData);
+  // - map operation
+  virtual bool processMapCommand(
+    SmlMapPtr_t aMapCommandP,       // the map command contents
+    TStatusCommand &aStatusCommand, // pre-set 200 status, can be modified in case of errors
+    bool &aQueueForLater
+  );
+  // Session level auth
+  // - get next nonce string top be sent to remote party for subsequent MD5 auth
+  virtual void getNextNonce(const char *aDeviceID, string &aNextNonce);
+  // - get nonce string, which is expected to be used by remote party for MD5 auth.
+  virtual void getAuthNonce(const char *aDeviceID, string &aAuthNonce);
+  #ifdef ENGINE_LIBRARY
+  // Engine interface
+  // - process step
+  TSyError ServerSessionStep(uInt16 &aStepCmd, TEngineProgressInfo *aInfoP);
+  // - Step that generates SyncML data
+  TSyError ServerGeneratingStep(uInt16 &aStepCmd, TEngineProgressInfo *aInfoP);
+  // - Step that processes SyncML data
+  TSyError ServerProcessingStep(uInt16 &aStepCmd, TEngineProgressInfo *aInfoP);
+  // - Server engine state
+  TServerEngineState fServerEngineState;
+  // - request size
+  MemSize_t fRequestSize;
+  #endif // ENGINE_LIBRARY
+  // set if map command received in this session
+  bool fMapSeen;
+  // standard nonce generation (without persistent device info)
+  // %%% note: move this to session when we start supporting client auth checking
+  string fLastNonce; // last nonce, will be returned at getAuthNonce()
+  // busy status
+  bool fServerIsBusy;
+  // buffered answer
+  MemPtr_t fBufferedAnswer;
+  MemSize_t fBufferedAnswerSize;
+  // data transfer statistics
+  uInt32 fIncomingBytes;
+  uInt32 fOutgoingBytes;
+  // server session handle
+  TSyncSessionHandle *fSessionHandleP; // the session "handle" (wrapper, containing server specific locking etc.)  
+  #endif // SYSYNC_SERVER
+}; // TSyncAgent
 
 
 #ifdef ENGINEINTERFACE_SUPPORT
@@ -341,15 +477,37 @@ public:
 // Support for EngineModule common interface
 // =========================================
 
-// client runtime parameters
-class TClientParamsKey :
+#if defined(SYSYNC_SERVER) && !defined(ENGINE_LIBRARY)
+
+#warning "using ENGINEINTERFACE_SUPPORT in old-style appbase-rooted environment. Should be converted to real engine usage later"
+
+// Define dummy server engine class - no implementation of actual server engine routines,
+// defaults from TEngineInterface (returning error codes) will be used.
+class TDummyServerEngineInterface :
+  public TEngineInterface
+{
+  typedef TEngineInterface inherited;
+public:
+  // constructor
+  TDummyServerEngineInterface() {};
+
+  // appbase factory
+  virtual TSyncAppBase *newSyncAppBase(void);
+
+}; // TDummyServerEngineInterface
+
+#endif // SYSYNC_SERVER and not ENGINE_LIBRARY
+
+
+// session runtime parameters
+class TAgentParamsKey :
   public TSessionKey
 {
   typedef TSessionKey inherited;
 
 public:
-  TClientParamsKey(TEngineInterface *aEngineInterfaceP, TSyncClient *aClientSessionP);
-  virtual ~TClientParamsKey() {};
+  TAgentParamsKey(TEngineInterface *aEngineInterfaceP, TSyncAgent *aAgentP);
+  virtual ~TAgentParamsKey() {};
   // open subkey by name (not by path!)
   virtual TSyError OpenSubKeyByName(
     TSettingsKeyImpl *&aSettingsKeyP,
@@ -363,14 +521,15 @@ protected:
   // get actual struct base address
   virtual uInt8P getStructAddr(void);
 public:
-  // the associated client session
-  TSyncClient *fClientSessionP;
-}; // TClientParamsKey
+  // the associated server session
+  TSyncAgent *fAgentP;
+}; // TAgentParamsKey
+
 
 #endif // ENGINEINTERFACE_SUPPORT
 
 }      // namespace sysync
 
-#endif // SyncClient_H
+#endif // SYNC_AGENT_H
 
 // eof
index d856552..5aa2c0d 100755 (executable)
@@ -15,6 +15,7 @@
 #include "syncappbase.h"
 #include "scriptcontext.h"
 #include "iso8601.h"
+#include "syncagent.h"
 #include "multifielditem.h" // in case we have no scripts...
 
 #ifdef SYSER_REGISTRATION
@@ -124,7 +125,11 @@ const char * const PlatformStringNames[numPlatformStrings] = {
     TSyncAppBase *appBase = getExistingSyncAppBase();
     if (appBase) return appBase;
     // no appBase yet, we must create and anchor the TEngineInterface
-    ENGINE_IF_CLASS *engine = sysync::newEngine();
+    #ifdef SYSYNC_CLIENT
+    ENGINE_IF_CLASS *engine = sysync::newClientEngine();
+    #else
+    ENGINE_IF_CLASS *engine = sysync::newServerEngine();
+    #endif
     // we must init the engine to trigger creation of the appbase!
     if (engine) engine->Init();
     return GET_SYNCAPPBASE;
@@ -433,12 +438,10 @@ bool TRootConfig::localStartElement(const char *aElementName, const char **aAttr
   #endif
   else
   // Agent: Server or client
-  #ifdef SYSYNC_CLIENT
-  if (strucmp(aElementName,"client")==0)
-  #else
-  if (strucmp(aElementName,"server")==0)
-  #endif
-  {
+  if (
+       (IS_CLIENT && strucmp(aElementName,"client")==0) ||
+               (IS_SERVER && strucmp(aElementName,"server")==0)
+  ) {
     // Agent config
     if (!fAgentConfigP) return false;
     return parseAgentConfig(aAttributes, aLine);
@@ -733,11 +736,11 @@ void TDebugConfig::localResolve(bool aLastPass)
         fGlobalDbgLoggerOptions.fSubThreadMode=dbgsubthread_separate; // separate per thread
         fGlobalDbgLoggerOptions.fTimestampForAll=true; // timestamp for every message
       #else
-        #ifndef SYSYNC_CLIENT
+       if (IS_SERVER) {
           // - global log for ISAPI/XPT *Servers* is always in openclose mode (possibly multiple processes accessing it)
           fGlobalDbgLoggerOptions.fFlushMode=dbgflush_openclose; // open and close for every log line
-        #endif
-          fGlobalDbgLoggerOptions.fSubThreadMode=dbgsubthread_linemix; // mix in one file
+        }
+        fGlobalDbgLoggerOptions.fSubThreadMode=dbgsubthread_linemix; // mix in one file
         #ifdef MULTI_THREAD_SUPPORT
           fGlobalDbgLoggerOptions.fThreadIDForAll=true; // thread ID for each message
         #endif
@@ -751,7 +754,9 @@ void TDebugConfig::localResolve(bool aLastPass)
     if (!getSyncAppBase()->fAppLogger.outputEstablished()) {
       getSyncAppBase()->fAppLogger.installOutput(getSyncAppBase()->newDbgOutputter(true)); // install the output object (and pass ownership!)
       getSyncAppBase()->fAppLogger.setDebugPath(fDebugInfoPath.c_str()); // global log all in one file
-      getSyncAppBase()->fAppLogger.appendToDebugPath(TARGETID);
+      getSyncAppBase()->fAppLogger.appendToDebugPath(fGlobalDbgLoggerOptions.fBasename.empty() ?
+                                                     TARGETID :
+                                                     fGlobalDbgLoggerOptions.fBasename.c_str());
       if (fSingleGlobLog) {
         // One single log - in this case, we MUST append to current log
         fGlobalDbgLoggerOptions.fAppend=true;
@@ -921,6 +926,8 @@ bool TDebugConfig::localStartElement(const char *aElementName, const char **aAtt
     expectRawString(fSessionDbgLoggerOptions.fCustomPrefix);
   else if (strucmp(aElementName,"filesuffix")==0)
     expectRawString(fSessionDbgLoggerOptions.fCustomSuffix);
+  else if (strucmp(aElementName,"filename")==0)
+    expectRawString(fSessionDbgLoggerOptions.fBasename);
   else if (strucmp(aElementName,"logflushmode")==0)
     expectEnum(sizeof(fSessionDbgLoggerOptions.fFlushMode),&fSessionDbgLoggerOptions.fFlushMode,DbgFlushModeNames,numDbgFlushModes);
   else if (strucmp(aElementName,"appendtoexisting")==0)
@@ -1100,47 +1107,47 @@ void ConsolePuts(const char *text)
 
 extern "C" {
   /* message callbacks */
-  Ret_t smlStartMessageCallback(InstanceID_t id, VoidPtr_t userData, SmlSyncHdrPtr_t pContent);
-  Ret_t smlEndMessageCallback(InstanceID_t id, VoidPtr_t userData, Boolean_t final);
+  static Ret_t smlStartMessageCallback(InstanceID_t id, VoidPtr_t userData, SmlSyncHdrPtr_t pContent);
+  static Ret_t smlEndMessageCallback(InstanceID_t id, VoidPtr_t userData, Boolean_t final);
   /* grouping commands */
-  Ret_t smlStartSyncCallback(InstanceID_t id, VoidPtr_t userData, SmlSyncPtr_t pContent);
-  Ret_t smlEndSyncCallback(InstanceID_t id, VoidPtr_t userData);
+  static Ret_t smlStartSyncCallback(InstanceID_t id, VoidPtr_t userData, SmlSyncPtr_t pContent);
+  static Ret_t smlEndSyncCallback(InstanceID_t id, VoidPtr_t userData);
   #ifdef ATOMIC_RECEIVE  /* these callbacks are NOT included in the Toolkit lite version */
-    Ret_t smlStartAtomicCallback(InstanceID_t id, VoidPtr_t userData, SmlAtomicPtr_t pContent);
-    Ret_t smlEndAtomicCallback(InstanceID_t id, VoidPtr_t userData);
+    static Ret_t smlStartAtomicCallback(InstanceID_t id, VoidPtr_t userData, SmlAtomicPtr_t pContent);
+    static Ret_t smlEndAtomicCallback(InstanceID_t id, VoidPtr_t userData);
   #endif
   #ifdef SEQUENCE_RECEIVE
-    Ret_t smlStartSequenceCallback(InstanceID_t id, VoidPtr_t userData, SmlSequencePtr_t pContent);
-    Ret_t smlEndSequenceCallback(InstanceID_t id, VoidPtr_t userData);
+    static Ret_t smlStartSequenceCallback(InstanceID_t id, VoidPtr_t userData, SmlSequencePtr_t pContent);
+    static Ret_t smlEndSequenceCallback(InstanceID_t id, VoidPtr_t userData);
   #endif
   /* Sync Commands */
-  Ret_t smlAddCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlAddPtr_t pContent);
-  Ret_t smlAlertCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlAlertPtr_t pContent);
-  Ret_t smlDeleteCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlDeletePtr_t pContent);
-  Ret_t smlGetCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlGetPtr_t pContent);
-  Ret_t smlPutCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlPutPtr_t pContent);
+  static Ret_t smlAddCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlAddPtr_t pContent);
+  static Ret_t smlAlertCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlAlertPtr_t pContent);
+  static Ret_t smlDeleteCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlDeletePtr_t pContent);
+  static Ret_t smlGetCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlGetPtr_t pContent);
+  static Ret_t smlPutCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlPutPtr_t pContent);
   #ifdef MAP_RECEIVE
-    Ret_t smlMapCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlMapPtr_t pContent);
+    static Ret_t smlMapCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlMapPtr_t pContent);
   #endif
   #ifdef RESULT_RECEIVE
-    Ret_t smlResultsCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlResultsPtr_t pContent);
+    static Ret_t smlResultsCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlResultsPtr_t pContent);
   #endif
-  Ret_t smlStatusCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlStatusPtr_t pContent);
-  Ret_t smlReplaceCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlReplacePtr_t pContent);
+  static Ret_t smlStatusCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlStatusPtr_t pContent);
+  static Ret_t smlReplaceCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlReplacePtr_t pContent);
   /* othe commands */
   #ifdef COPY_RECEIVE  /* these callbacks are NOT included in the Toolkit lite version */
-    Ret_t smlCopyCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlCopyPtr_t param);
+    static Ret_t smlCopyCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlCopyPtr_t param);
   #endif
-  Ret_t smlMoveCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlMovePtr_t param);
+  static Ret_t smlMoveCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlMovePtr_t param);
   #ifdef EXEC_RECEIVE
-    Ret_t smlExecCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlExecPtr_t pContent);
+    static Ret_t smlExecCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlExecPtr_t pContent);
   #endif
   #ifdef SEARCH_RECEIVE
-    Ret_t smlSearchCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlSearchPtr_t pContent);
+    static Ret_t smlSearchCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlSearchPtr_t pContent);
   #endif
   /* Other Callbacks */
-  Ret_t smlHandleErrorCallback(InstanceID_t id, VoidPtr_t userData);
-  Ret_t smlTransmitChunkCallback(InstanceID_t id, VoidPtr_t userData);
+  static Ret_t smlHandleErrorCallback(InstanceID_t id, VoidPtr_t userData);
+  static Ret_t smlTransmitChunkCallback(InstanceID_t id, VoidPtr_t userData);
 
   /* print callback */
   void smlPrintCallback(String_t outputString);
@@ -1149,6 +1156,7 @@ extern "C" {
 
 // constructor
 TSyncAppBase::TSyncAppBase() :
+  fIsServer(false),
   fDeleting(false),
   fConfigP(NULL),
   fRequestCount(0),
@@ -1179,6 +1187,9 @@ TSyncAppBase::TSyncAppBase() :
     #endif
     sysync_glob_setanchor(this);
   #endif
+  #ifdef MD5_TEST_FUNCS
+  md5::dotest();
+  #endif
   // init profiling
   TP_INIT(fTPInfo);
   TP_START(fTPInfo,TP_general);
@@ -1508,10 +1519,11 @@ typedef struct {
 
 
 // prototypes
-extern "C" void startElement(void *userData, const char *name, const char **atts);
-extern "C" void charData(void *userData, const XML_Char *s, int len);
-extern "C" void endElement(void *userData, const char *name);
-
+extern "C" {
+  static void startElement(void *userData, const char *name, const char **atts);
+  static void charData(void *userData, const XML_Char *s, int len);
+  static void endElement(void *userData, const char *name);
+}
 
 static localstatus checkErrors(TRootConfigElement *aRootConfigP,XML_Parser aParser)
 {
@@ -1532,7 +1544,7 @@ static localstatus checkErrors(TRootConfigElement *aRootConfigP,XML_Parser aPars
 
 
 // callback for expat
-extern "C" void startElement(void *userData, const char *name, const char **atts)
+static void startElement(void *userData, const char *name, const char **atts)
 {
   TRootConfigElement *cfgP = static_cast<TXMLUserData *>(userData)->rootconfig;
   XML_Parser parser = static_cast<TXMLUserData *>(userData)->parser;
@@ -1548,7 +1560,7 @@ extern "C" void startElement(void *userData, const char *name, const char **atts
 
 
 // callback for expat
-extern "C" void charData(void *userData, const XML_Char *s, int len)
+static void charData(void *userData, const XML_Char *s, int len)
 {
   TRootConfigElement *cfgP = static_cast<TXMLUserData *>(userData)->rootconfig;
   XML_Parser parser = static_cast<TXMLUserData *>(userData)->parser;
@@ -1565,7 +1577,7 @@ extern "C" void charData(void *userData, const XML_Char *s, int len)
 
 
 // callback for expat
-extern "C" void endElement(void *userData, const char *name)
+static void endElement(void *userData, const char *name)
 {
   TRootConfigElement *cfgP = static_cast<TXMLUserData *>(userData)->rootconfig;
   XML_Parser parser = static_cast<TXMLUserData *>(userData)->parser;
@@ -2349,47 +2361,47 @@ typedef struct {
 #define GET_USERDATA(x) (((TSmlContextDataRec *)x)->userDataP)
 
 /* message callbacks */
-Ret_t smlStartMessageCallback(InstanceID_t id, VoidPtr_t userData, SmlSyncHdrPtr_t pContent) { return GET_APPBASE(userData)->StartMessage(id,GET_USERDATA(userData),pContent); }
-Ret_t smlEndMessageCallback(InstanceID_t id, VoidPtr_t userData, Boolean_t final) { return GET_APPBASE(userData)->EndMessage(GET_USERDATA(userData),final); }
+static Ret_t smlStartMessageCallback(InstanceID_t id, VoidPtr_t userData, SmlSyncHdrPtr_t pContent) { return GET_APPBASE(userData)->StartMessage(id,GET_USERDATA(userData),pContent); }
+static Ret_t smlEndMessageCallback(InstanceID_t id, VoidPtr_t userData, Boolean_t final) { return GET_APPBASE(userData)->EndMessage(GET_USERDATA(userData),final); }
 /* grouping commands */
-Ret_t smlStartSyncCallback(InstanceID_t id, VoidPtr_t userData, SmlSyncPtr_t pContent) { return GET_APPBASE(userData)->StartSync(GET_USERDATA(userData),pContent); }
-Ret_t smlEndSyncCallback(InstanceID_t id, VoidPtr_t userData) { return GET_APPBASE(userData)->EndSync(GET_USERDATA(userData)); }
+static Ret_t smlStartSyncCallback(InstanceID_t id, VoidPtr_t userData, SmlSyncPtr_t pContent) { return GET_APPBASE(userData)->StartSync(GET_USERDATA(userData),pContent); }
+static Ret_t smlEndSyncCallback(InstanceID_t id, VoidPtr_t userData) { return GET_APPBASE(userData)->EndSync(GET_USERDATA(userData)); }
 #ifdef ATOMIC_RECEIVE  /* these callbacks are NOT included in the Toolkit lite version */
-  Ret_t smlStartAtomicCallback(InstanceID_t id, VoidPtr_t userData, SmlAtomicPtr_t pContent) { return GET_APPBASE(userData)->StartAtomic(GET_USERDATA(userData),pContent); }
-  Ret_t smlEndAtomicCallback(InstanceID_t id, VoidPtr_t userData) { return GET_APPBASE(userData)->EndAtomic(GET_USERDATA(userData)); }
+  static Ret_t smlStartAtomicCallback(InstanceID_t id, VoidPtr_t userData, SmlAtomicPtr_t pContent) { return GET_APPBASE(userData)->StartAtomic(GET_USERDATA(userData),pContent); }
+  static Ret_t smlEndAtomicCallback(InstanceID_t id, VoidPtr_t userData) { return GET_APPBASE(userData)->EndAtomic(GET_USERDATA(userData)); }
 #endif
 #ifdef SEQUENCE_RECEIVE
-  Ret_t smlStartSequenceCallback(InstanceID_t id, VoidPtr_t userData, SmlSequencePtr_t pContent) { return GET_APPBASE(userData)->StartSequence(GET_USERDATA(userData),pContent); }
-  Ret_t smlEndSequenceCallback(InstanceID_t id, VoidPtr_t userData) { return GET_APPBASE(userData)->EndSequence(GET_USERDATA(userData)); }
+  static Ret_t smlStartSequenceCallback(InstanceID_t id, VoidPtr_t userData, SmlSequencePtr_t pContent) { return GET_APPBASE(userData)->StartSequence(GET_USERDATA(userData),pContent); }
+  static Ret_t smlEndSequenceCallback(InstanceID_t id, VoidPtr_t userData) { return GET_APPBASE(userData)->EndSequence(GET_USERDATA(userData)); }
 #endif
 /* Sync Commands */
-Ret_t smlAddCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlAddPtr_t pContent) { return GET_APPBASE(userData)->AddCmd(GET_USERDATA(userData),pContent); }
-Ret_t smlAlertCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlAlertPtr_t pContent) { return GET_APPBASE(userData)->AlertCmd(GET_USERDATA(userData),pContent); }
-Ret_t smlDeleteCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlDeletePtr_t pContent) { return GET_APPBASE(userData)->DeleteCmd(GET_USERDATA(userData),pContent); }
-Ret_t smlGetCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlGetPtr_t pContent) { return GET_APPBASE(userData)->GetCmd(GET_USERDATA(userData),pContent); }
-Ret_t smlPutCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlPutPtr_t pContent) { return GET_APPBASE(userData)->PutCmd(GET_USERDATA(userData),pContent); }
+static Ret_t smlAddCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlAddPtr_t pContent) { return GET_APPBASE(userData)->AddCmd(GET_USERDATA(userData),pContent); }
+static Ret_t smlAlertCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlAlertPtr_t pContent) { return GET_APPBASE(userData)->AlertCmd(GET_USERDATA(userData),pContent); }
+static Ret_t smlDeleteCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlDeletePtr_t pContent) { return GET_APPBASE(userData)->DeleteCmd(GET_USERDATA(userData),pContent); }
+static Ret_t smlGetCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlGetPtr_t pContent) { return GET_APPBASE(userData)->GetCmd(GET_USERDATA(userData),pContent); }
+static Ret_t smlPutCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlPutPtr_t pContent) { return GET_APPBASE(userData)->PutCmd(GET_USERDATA(userData),pContent); }
 #ifdef MAP_RECEIVE
-  Ret_t smlMapCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlMapPtr_t pContent) { return GET_APPBASE(userData)->MapCmd(GET_USERDATA(userData),pContent); }
+  static Ret_t smlMapCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlMapPtr_t pContent) { return GET_APPBASE(userData)->MapCmd(GET_USERDATA(userData),pContent); }
 #endif
 #ifdef RESULT_RECEIVE
-  Ret_t smlResultsCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlResultsPtr_t pContent) { return GET_APPBASE(userData)->ResultsCmd(GET_USERDATA(userData),pContent); }
+  static Ret_t smlResultsCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlResultsPtr_t pContent) { return GET_APPBASE(userData)->ResultsCmd(GET_USERDATA(userData),pContent); }
 #endif
-Ret_t smlStatusCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlStatusPtr_t pContent) { return GET_APPBASE(userData)->StatusCmd(GET_USERDATA(userData),pContent); }
-Ret_t smlReplaceCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlReplacePtr_t pContent) { return GET_APPBASE(userData)->ReplaceCmd(GET_USERDATA(userData),pContent); }
+static Ret_t smlStatusCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlStatusPtr_t pContent) { return GET_APPBASE(userData)->StatusCmd(GET_USERDATA(userData),pContent); }
+static Ret_t smlReplaceCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlReplacePtr_t pContent) { return GET_APPBASE(userData)->ReplaceCmd(GET_USERDATA(userData),pContent); }
 /* other commands */
 #ifdef COPY_RECEIVE  /* these callbacks are NOT included in the Toolkit lite version */
-  Ret_t smlCopyCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlCopyPtr_t pContent) { return GET_APPBASE(userData)->CopyCmd(GET_USERDATA(userData),pContent); }
+  static Ret_t smlCopyCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlCopyPtr_t pContent) { return GET_APPBASE(userData)->CopyCmd(GET_USERDATA(userData),pContent); }
 #endif
-Ret_t smlMoveCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlMovePtr_t pContent) { return GET_APPBASE(userData)->MoveCmd(GET_USERDATA(userData),pContent); }
+static Ret_t smlMoveCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlMovePtr_t pContent) { return GET_APPBASE(userData)->MoveCmd(GET_USERDATA(userData),pContent); }
 #ifdef EXEC_RECEIVE
-  Ret_t smlExecCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlExecPtr_t pContent) { /*%%%tbd return GET_APPBASE(userData)->ExecCmd(GET_USERDATA(userData),pContent); */ return SML_ERR_INVALID_OPTIONS; }
+  static Ret_t smlExecCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlExecPtr_t pContent) { /*%%%tbd return GET_APPBASE(userData)->ExecCmd(GET_USERDATA(userData),pContent); */ return SML_ERR_INVALID_OPTIONS; }
 #endif
 #ifdef SEARCH_RECEIVE
-  Ret_t smlSearchCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlSearchPtr_t pContent) { /*%%%tbd return GET_APPBASE(userData)->SearchCmd(GET_USERDATA(userData),pContent); */ return SML_ERR_INVALID_OPTIONS; }
+  static Ret_t smlSearchCmdCallback(InstanceID_t id, VoidPtr_t userData, SmlSearchPtr_t pContent) { /*%%%tbd return GET_APPBASE(userData)->SearchCmd(GET_USERDATA(userData),pContent); */ return SML_ERR_INVALID_OPTIONS; }
 #endif
 /* Other Callbacks */
-Ret_t smlHandleErrorCallback(InstanceID_t id, VoidPtr_t userData) { return GET_APPBASE(userData)->DummyHandler(GET_USERDATA(userData),"ErrorCallback"); }
-Ret_t smlTransmitChunkCallback(InstanceID_t id, VoidPtr_t userData) { /*%%%tdb return GET_APPBASE(userData)->TransmitChunk(GET_USERDATA(userData),pContent); */ return SML_ERR_INVALID_OPTIONS; }
+static Ret_t smlHandleErrorCallback(InstanceID_t id, VoidPtr_t userData) { return GET_APPBASE(userData)->DummyHandler(GET_USERDATA(userData),"ErrorCallback"); }
+static Ret_t smlTransmitChunkCallback(InstanceID_t id, VoidPtr_t userData) { /*%%%tdb return GET_APPBASE(userData)->TransmitChunk(GET_USERDATA(userData),pContent); */ return SML_ERR_INVALID_OPTIONS; }
 
 
 /* end callback implementations */
@@ -2496,6 +2508,54 @@ void TSyncAppBase::freeSmlInstance(InstanceID_t aInstance)
 } // TSyncAppBase::freeSmlInstance
 
 
+// determine encoding from beginning of SyncML message data
+SmlEncoding_t TSyncAppBase::encodingFromData(cAppPointer aData, memSize aDataSize)
+{
+       SmlEncoding_t enc = SML_UNDEF;
+  if (aData && aDataSize>=5) {
+       // check for WBXML intro sequences
+    if (
+      (memcmp((cAppCharP)aData,"\x02\x00\x00",3)==0) || // WBXML V2 + Public identifier as string
+      (memcmp((cAppCharP)aData,"\x02\xA4\x01",3)==0) || // WBXML V2 + Public identifier 0x1201 for SyncML 1.2
+      (memcmp((cAppCharP)aData,"\x02\x9F\x53",3)==0) || // WBXML V2 + Public identifier 0x0FD3 for SyncML 1.1
+      (memcmp((cAppCharP)aData,"\x02\x9F\x51",3)==0)    // WBXML V2 + Public identifier 0x0FD1 for SyncML 1.0
+    )
+      enc=SML_WBXML;
+    else {
+       // could be XML
+      // - skip UTF-8 BOM if there is one
+      cUInt8P p = (cUInt8P)aData;
+      if (p[0]==0xEF && p[1]==0xBB && p[2]==0xBF)
+       p+=3; // skip the BOM
+      // now check for XML
+           if (strnncmp((cAppCharP)p,"<?xml",5)==0 ||
+                strnncmp((cAppCharP)p,"<SyncML",7)==0)
+                enc=SML_XML;
+       }
+  }
+  return enc;
+} // TSyncAppBase::encodingFromData
+
+
+// determine encoding from Content-Type: header value
+SmlEncoding_t TSyncAppBase::encodingFromContentType(cAppCharP aTypeString)
+{
+       sInt16 enc = SML_UNDEF;
+  if (aTypeString) {
+    stringSize l=strlen(SYNCML_MIME_TYPE SYNCML_ENCODING_SEPARATOR);
+    if (strucmp(aTypeString,SYNCML_MIME_TYPE SYNCML_ENCODING_SEPARATOR,l)==0) {
+      // is SyncML, check encoding
+      cAppCharP p = strchr(aTypeString,';');
+      sInt16 cl = p ? p-aTypeString-l : 0; // length of encoding string (charset could be appended here)  
+      StrToEnum(SyncMLEncodingMIMENames,numSyncMLEncodings,enc,aTypeString+l,cl);
+    }
+  }
+  return static_cast<SmlEncoding_t>(enc);
+} // TSyncAppBase::encodingFromContentType
+
+
+
+
 // save app state (such as settings in datastore configs etc.)
 void TSyncAppBase::saveAppState(void)
 {
@@ -2525,6 +2585,7 @@ string TSyncAppBase::getModel(void) {
        return CUST_SYNC_MODEL;
 } // TSyncAppBase::getModel
 
+
 // hardware version
 string TSyncAppBase::getHardwareVersion(void) {
   #ifdef ENGINEINTERFACE_SUPPORT
@@ -2538,6 +2599,7 @@ string TSyncAppBase::getHardwareVersion(void) {
   return s;
 } // TSyncAppBase::getHardwareVersion
 
+
 // firmware version (depends a lot on the context - OS version?)
 string TSyncAppBase::getFirmwareVersion(void) {
   #ifdef ENGINEINTERFACE_SUPPORT
@@ -2551,6 +2613,7 @@ string TSyncAppBase::getFirmwareVersion(void) {
   return s;
 } // TSyncAppBase::getHardwareVersion
 
+
 // hardware type (PDA, PC, ...)
 string TSyncAppBase::getDevTyp() {
   #ifdef ENGINEINTERFACE_SUPPORT
@@ -2559,9 +2622,13 @@ string TSyncAppBase::getDevTyp() {
   }
   #endif
   // if no string configured, return default
-  return SYNCML_CLIENT_DEVTYP;
+  if (isServer())
+       return SYNCML_SERVER_DEVTYP;
+  else
+    return SYNCML_CLIENT_DEVTYP;
 } // TSyncAppBase::getDevTyp
 
+
 #ifdef APP_CAN_EXPIRE
 
 void TSyncAppBase::updateAppExpiry(void)
index db34ffe..1b4eee8 100755 (executable)
@@ -175,6 +175,8 @@ public:
 }; // TCommConfig
 
 
+/* %%% this was a useless intermediate class. We now call the unilib config TAgentConfig
+       (union of TClientConfig and TServerConfig)
 // agent configuration (an agent is a server or a client)
 class TAgentConfig : public TConfigElement
 {
@@ -186,9 +188,9 @@ public:
   //   such as binfile profiles. If aDoLoose==false, situations, where existing config
   //   is detected but cannot be re-used will return an error. With aDoLoose==true, config
   //   files etc. are created even if it means a loss of data.
-  virtual localstatus loadVarConfig(bool aDoLoose=false) { return LOCERR_OK; /* NOP and ok by default */ }
+  virtual localstatus loadVarConfig(bool aDoLoose=false) { return LOCERR_OK; }
 }; // TAgentConfig
-
+*/
 
 
 // single data type configuration abstract class
@@ -304,6 +306,7 @@ private:
 #endif
 
 class TProfileConfig; // forward
+class TAgentConfig; // forward
 
 // root Config element
 class TRootConfig : public TRootConfigElement
@@ -359,7 +362,7 @@ public:
   bool fNeverPutDevinf;
   // transport/environment config
   TCommConfig *fCommConfigP;
-  // Server or Client config
+  // Agent (Server or Client session) config
   TAgentConfig *fAgentConfigP;
   // datatypes config
   TDatatypesConfig *fDatatypesConfigP;
@@ -486,6 +489,10 @@ public:
   Ret_t getSmlInstanceUserData(InstanceID_t aInstanceID, void **aUserDataPP);
   Ret_t setSmlInstanceUserData(InstanceID_t aInstanceID, void *aUserDataP);
   void freeSmlInstance(InstanceID_t aInstance);
+       // determine encoding from beginning of SyncML message data
+       static SmlEncoding_t encodingFromData(cAppPointer aData, memSize aDataSize);
+       // determine encoding from Content-Type: header value
+       static SmlEncoding_t encodingFromContentType(cAppCharP aTypeString);
   // virtual handlers for SyncML toolkit callbacks, must be separately derived for server/client cases
   // - Start/End Message: derived method in server case actually creates session
   virtual Ret_t StartMessage(
@@ -533,6 +540,8 @@ public:
   // convenience version for getting time
   lineartime_t getSystemNowAs(timecontext_t aContext) { return sysync::getSystemNowAs(aContext,getAppZones()); };
 protected:
+       // Server or client
+  bool fIsServer;
   // Application custom time zones
   GZones fAppZones;
   // Destruction flag
@@ -546,6 +555,8 @@ protected:
   // request count
   sInt32 fRequestCount; // count of requests
 public:
+       // this is called to control behaviour for builds that can be client OR server
+  bool isServer(void) { return fIsServer; };
   #ifdef SYSER_REGISTRATION
   // somewhat scattered within object to make reverse engineering harder
   bool fRegOK; // updated by checkRegInfo, used to disable hard-coded-expiry
@@ -655,7 +666,6 @@ private:
 
 } // namespace sysync
 
-
 #endif // SYNCAPPBASE_H
 
 
diff --git a/src/synthesis/src/sysync/syncclient.cpp b/src/synthesis/src/sysync/syncclient.cpp
deleted file mode 100755 (executable)
index 04d04e3..0000000
+++ /dev/null
@@ -1,1918 +0,0 @@
-/*
- *  File:         SyncClient.cpp
- *
- *  Author:       Lukas Zeller (luz@synthesis.ch)
- *
- *  TSyncClient
- *    Provides functionality required for a Synchronisation
- *    client.
- *
- *  Copyright (c) 2002-2009 by Synthesis AG (www.synthesis.ch)
- *
- *  2002-05-06 : luz : created from old SyncClient.h (which was a
- *                     intermediate class between server and session,
- *                     as initially we considered a client-server
- *                     combined class. Now both SyncClient and
- *                     SyncServer are directly derived from SyncSession
- *
- */
-
-
-// includes
-#include "prefix_file.h"
-#include "sysync.h"
-#include "syncclient.h"
-#include "syncappbase.h"
-
-#ifdef HARD_CODED_SERVER_URI
-  #include "syserial.h"
-#endif
-
-#ifndef SYSYNC_CLIENT
-  #error "SYSYNC_CLIENT must be defined when compiling syncclient.cpp"
-#endif
-
-namespace sysync {
-
-
-#ifdef PRECONFIGURED_SYNCREQUESTS
-
-// Implementation of TSyncReqConfig
-// ================================
-
-// config for databases to sync with
-TSyncReqConfig::TSyncReqConfig(TLocalDSConfig *aLocalDSCfg, TConfigElement *aParentElement) :
-  TConfigElement("syncrequest",aParentElement),
-  fLocalDSConfig(aLocalDSCfg)
-{
-  clear();
-} // TSyncReqConfig::TSyncReqConfig
-
-
-TSyncReqConfig::~TSyncReqConfig()
-{
-  // nop so far
-} // TSyncReqConfig::~TSyncReqConfig
-
-
-// init defaults
-void TSyncReqConfig::clear(void)
-{
-  // init defaults
-  // - local client datatstore subselection path or CGI (such as "test" in "contact/test")
-  fLocalPathExtension.erase();
-  // - remote server DB layer auth
-  fDBUser.erase();
-  fDBPassword.erase();
-  // - remote server datastore path
-  fServerDBPath.erase();
-  // - sync mode
-  fSyncMode=smo_twoway;
-  fSlowSync=false; // default to non-slow
-  // - DS 1.2 filtering parameters
-  fRecordFilterQuery.erase();
-  fFilterInclusive=false;
-  // clear inherited
-  inherited::clear();
-} // TSyncReqConfig::clear
-
-
-// config element parsing
-bool TSyncReqConfig::localStartElement(const char *aElementName, const char **aAttributes, sInt32 aLine)
-{
-  // checking the elements
-  if (strucmp(aElementName,"localpathextension")==0)
-    expectString(fLocalPathExtension);
-  else if (strucmp(aElementName,"dbuser")==0)
-    expectString(fDBUser);
-  else if (strucmp(aElementName,"dbpassword")==0)
-    expectString(fDBPassword);
-  else if (strucmp(aElementName,"dbpath")==0)
-    expectString(fServerDBPath);
-  else if (strucmp(aElementName,"syncmode")==0)
-    expectEnum(sizeof(fSyncMode),&fSyncMode,SyncModeNames,numSyncModes);
-  else if (strucmp(aElementName,"slowsync")==0)
-    expectBool(fSlowSync);
-  else if (strucmp(aElementName,"recordfilter")==0)
-    expectString(fRecordFilterQuery);
-  else if (strucmp(aElementName,"filterinclusive")==0)
-    expectBool(fFilterInclusive);
-
-  // - none known here
-  else
-    return inherited::localStartElement(aElementName,aAttributes,aLine);
-  // ok
-  return true;
-} // TSyncReqConfig::localStartElement
-
-
-// resolve
-void TSyncReqConfig::localResolve(bool aLastPass)
-{
-  if (aLastPass) {
-    // check for required settings
-    // %%% tbd
-  }
-  // resolve inherited
-  inherited::localResolve(aLastPass);
-} // TSyncReqConfig::localResolve
-
-
-// create appropriate type of local datastore from config and init sync parameters
-TLocalEngineDS *TSyncReqConfig::initNewLocalDataStore(TSyncSession *aSessionP)
-{
-  // - create appropriate type of localdsP
-  TLocalEngineDS *localdsP = fLocalDSConfig->newLocalDataStore(aSessionP);
-  // - set parameters
-  localdsP->dsSetClientSyncParams(
-    fSyncMode,
-    fSlowSync,
-    fServerDBPath.c_str(),
-    fDBUser.c_str(),
-    fDBPassword.c_str(),
-    fLocalPathExtension.c_str(),
-    fRecordFilterQuery.c_str(),
-    fFilterInclusive
-  );
-  return localdsP;
-} // TSyncReqConfig::initNewLocalDataStore
-
-#endif // PRECONFIGURED_SYNCREQUESTS
-
-
-// Implementation of TClientConfig
-// ===============================
-
-
-TClientConfig::TClientConfig(const char* aName, TConfigElement *aParentElement) :
-  TSessionConfig(aName,aParentElement)
-{
-  clear();
-} // TClientConfig::TClientConfig
-
-
-TClientConfig::~TClientConfig()
-{
-  clear();
-} // TClientConfig::~TClientConfig
-
-
-// init defaults
-void TClientConfig::clear(void)
-{
-  // init auth defaults (note that these MUST correspond with the defaults set by loadRemoteParams() !!!
-  fAssumedServerAuth=auth_none; // start with no auth
-  fAssumedServerAuthEnc=fmt_chr; // start with char encoding
-  fAssumedNonce.erase(); // start with no nonce
-  // auth retry options (mainly for stupid servers like SCTS)
-  #ifdef SCTS_COMPATIBILITY_HACKS
-  fNewSessionForAuthRetry=false;
-  fNoRespURIForAuthRetry=false;
-  #else
-  fNewSessionForAuthRetry=true; // all production Synthesis clients had it hardcoded (ifdeffed) this way until 2.9.8.7
-  fNoRespURIForAuthRetry=true; // all production Synthesis clients had it hardcoded (ifdeffed) this way until 2.9.8.7
-  #endif
-  fSmartAuthRetry=true; // try to be smart and try different auth retry (different from fNewSessionForAuthRetry/fNoRespURIForAuthRetry) if first attempts fail
-  // other defaults
-  fPutDevInfAtSlowSync=true; // smartner server needs it, and it does not harm so we have it on by default
-  #ifndef NO_LOCAL_DBLOGIN
-  fLocalDBUser.erase();
-  fLocalDBPassword.erase();
-  fNoLocalDBLogin=false;
-  #endif
-  #ifdef PRECONFIGURED_SYNCREQUESTS
-  fEncoding=SML_XML; // default to more readable XML
-  fServerUser.erase();
-  fServerPassword.erase();
-  fServerURI.erase();
-  fTransportUser.erase();
-  fTransportPassword.erase();
-  fSocksHost.erase();
-  fProxyHost.erase();
-  fProxyUser.erase();
-  fProxyPassword.erase();
-  // remove sync db specifications
-  TSyncReqList::iterator pos;
-  for(pos=fSyncRequests.begin();pos!=fSyncRequests.end();pos++)
-    delete *pos;
-  fSyncRequests.clear();
-  #endif
-  // clear inherited
-  TSessionConfig::clear();
-  // modify timeout after inherited sets it
-  fSessionTimeout=DEFAULT_CLIENTSESSIONTIMEOUT;
-  // SyncML version support
-  fAssumedServerVersion=MAX_SYNCML_VERSION; // try with highest version we support
-  fMaxSyncMLVersionSupported=MAX_SYNCML_VERSION; // support what we request (overrides session default)
-} // TClientConfig::clear
-
-
-#ifndef HARDCODED_CONFIG
-
-// config element parsing
-bool TClientConfig::localStartElement(const char *aElementName, const char **aAttributes, sInt32 aLine)
-{
-  // checking the elements
-  // - defaults for starting a session
-  if (strucmp(aElementName,"defaultsyncmlversion")==0)
-    expectEnum(sizeof(fAssumedServerVersion),&fAssumedServerVersion,SyncMLVersionNames,numSyncMLVersions);
-  else if (strucmp(aElementName,"defaultauth")==0)
-    expectEnum(sizeof(fAssumedServerAuth),&fAssumedServerAuth,authTypeNames,numAuthTypes);
-  else if (strucmp(aElementName,"defaultauthencoding")==0)
-    expectEnum(sizeof(fAssumedServerAuthEnc),&fAssumedServerAuthEnc,encodingFmtSyncMLNames,numFmtTypes);
-  else if (strucmp(aElementName,"defaultauthnonce")==0)
-    expectString(fAssumedNonce);
-  else if (strucmp(aElementName,"newsessionforretry")==0)
-    expectBool(fNewSessionForAuthRetry);
-  else if (strucmp(aElementName,"originaluriforretry")==0)
-    expectBool(fNoRespURIForAuthRetry);
-  else if (strucmp(aElementName,"smartauthretry")==0)
-    expectBool(fSmartAuthRetry);
-  // - other options
-  else if (strucmp(aElementName,"putdevinfatslowsync")==0)
-    expectBool(fPutDevInfAtSlowSync);
-  else if (strucmp(aElementName,"fakedeviceid")==0)
-    expectString(fFakeDeviceID);
-  else
-  #ifndef NO_LOCAL_DBLOGIN
-  if (strucmp(aElementName,"localdbuser")==0)
-    expectString(fLocalDBUser);
-  else if (strucmp(aElementName,"localdbpassword")==0)
-    expectString(fLocalDBPassword);
-  else if (strucmp(aElementName,"nolocaldblogin")==0)
-    expectBool(fNoLocalDBLogin);
-  else
-  #endif
-  // serverURL is always available to allow define fixed URL in config that can't be overridden in profiles
-  if (strucmp(aElementName,"serverurl")==0)
-    expectString(fServerURI);
-  else
-  #ifdef PRECONFIGURED_SYNCREQUESTS
-  if (strucmp(aElementName,"syncmlencoding")==0)
-    expectEnum(sizeof(fEncoding),&fEncoding,SyncMLEncodingNames,numSyncMLEncodings);
-  else if (strucmp(aElementName,"serveruser")==0)
-    expectString(fServerUser);
-  else if (strucmp(aElementName,"serverpassword")==0)
-    expectString(fServerPassword);
-  else if (strucmp(aElementName,"sockshost")==0)
-    expectString(fSocksHost);
-  else if (strucmp(aElementName,"proxyhost")==0)
-    expectString(fProxyHost);
-  else if (strucmp(aElementName,"proxyuser")==0)
-    expectString(fProxyUser);
-  else if (strucmp(aElementName,"proxypassword")==0)
-    expectString(fProxyPassword);
-  else if (strucmp(aElementName,"transportuser")==0)
-    expectString(fTransportUser);
-  else if (strucmp(aElementName,"transportpassword")==0)
-    expectString(fTransportPassword);
-  // - Sync DB specification
-  else if (strucmp(aElementName,"syncrequest")==0) {
-    // definition of a new datastore
-    const char* nam = getAttr(aAttributes,"datastore");
-    if (!nam) {
-      ReportError(true,"syncrequest missing 'datastore' attribute");
-    }
-    else {
-      // search datastore
-      TLocalDSConfig *localDSCfgP = getLocalDS(nam);
-      if (!localDSCfgP)
-        return fail("unknown local datastore '%s' specified",nam);
-      // create new syncDB config linked to that datastore
-      TSyncReqConfig *syncreqcfgP = new TSyncReqConfig(localDSCfgP,this);
-      // - save in list
-      fSyncRequests.push_back(syncreqcfgP);
-      // - let element handle parsing
-      expectChildParsing(*syncreqcfgP);
-    }
-  }
-  else
-  #endif
-  // - none known here
-    return TSessionConfig::localStartElement(aElementName,aAttributes,aLine);
-  // ok
-  return true;
-} // TClientConfig::localStartElement
-
-#endif
-
-// resolve
-void TClientConfig::localResolve(bool aLastPass)
-{
-  if (aLastPass) {
-    #ifdef PRECONFIGURED_SYNCREQUESTS
-    // - resolve requests
-    TSyncReqList::iterator pos;
-    for(pos=fSyncRequests.begin();pos!=fSyncRequests.end();pos++)
-      (*pos)->Resolve(aLastPass);
-    #endif
-  }
-  // resolve inherited
-  inherited::localResolve(aLastPass);
-} // TClientConfig::localResolve
-
-
-
-// Implementation of TSyncClient
-// =============================
-
-
-// constructor
-TSyncClient::TSyncClient(
-  TSyncClientBase *aSyncClientBaseP,
-  cAppCharP aSessionID // a session ID
-) :
-  TSyncSession(aSyncClientBaseP,aSessionID)
-  #ifdef ENGINEINTERFACE_SUPPORT
-  ,fEngineState(ces_idle)
-  #endif
-{
-  #ifdef HARD_CODED_SERVER_URI
-  fNoCRCPrefixLen=0;
-  #endif
-  // reset session now to get correct initial state
-  InternalResetSession();
-  // restart with session numbering at 1 (incremented before use)
-  fClientSessionNo=0;
-} // TSyncClient::TSyncClient
-
-
-// destructor
-TSyncClient::~TSyncClient()
-{
-  // make sure everything is terminated BEFORE destruction of hierarchy begins
-  TerminateSession();
-} // TSyncClient::~TSyncClient
-
-
-// Terminate session
-void TSyncClient::TerminateSession()
-{
-  if (!fTerminated) {
-    InternalResetSession();
-    #ifdef ENGINEINTERFACE_SUPPORT
-    // switch state to done to prevent any further activity via SessionStep()
-    fEngineState = ces_done;
-    #endif
-  }
-  inherited::TerminateSession();
-} // TSyncClient::TerminateSession
-
-
-
-#ifdef ENGINEINTERFACE_SUPPORT
-
-// Support for EngineModule common interface
-// -----------------------------------------
-
-
-/// @brief Executes next step of the session
-/// @param aStepCmd[in/out] step command (STEPCMD_xxx):
-///        - tells caller to send or receive data or end the session etc.
-///        - instructs engine to suspend or abort the session etc.
-/// @param aInfoP[in] pointer to a TEngineProgressInfo structure, NULL if no progress info needed
-/// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure
-TSyError TSyncClient::SessionStep(uInt16 &aStepCmd, TEngineProgressInfo *aInfoP)
-{
-  uInt16 stepCmdIn = aStepCmd;
-  localstatus sta = LOCERR_WRONGUSAGE;
-
-  // init default response
-  aStepCmd = STEPCMD_ERROR; // error
-  if (aInfoP) {
-    aInfoP->eventtype=PEV_NOP;
-    aInfoP->targetID=0;
-    aInfoP->extra1=0;
-    aInfoP->extra2=0;
-    aInfoP->extra3=0;
-  }
-
-  // if session is already aborted, no more steps are required
-  if (isAborted()) {
-       fEngineState = ces_done; // we are done
-  }
-
-  // handle pre-processed step command according to current engine state
-  switch (fEngineState) {
-
-    // Idle state
-    case ces_done :
-      // session done, nothing happens any more
-      aStepCmd = STEPCMD_DONE;
-      sta = LOCERR_OK;
-      break;
-
-    case ces_idle :
-      // in idle, we can only start a session
-      switch (stepCmdIn) {
-        case STEPCMD_CLIENTSTART:
-        case STEPCMD_CLIENTAUTOSTART:
-          // initialize a new session
-          sta = InitializeSession(fProfileSelectorInternal,stepCmdIn==STEPCMD_CLIENTAUTOSTART);
-          if (sta!=LOCERR_OK) break;
-          // engine is now ready, start generating first request
-          fEngineState = ces_generating;
-          // ok with no status
-          aStepCmd = STEPCMD_OK;
-          break;
-      } // switch stepCmdIn for ces_idle
-      break;
-
-    // Ready for generation steps
-    case ces_generating:
-      switch (stepCmdIn) {
-        case STEPCMD_STEP :
-          sta = generatingStep(aStepCmd,aInfoP);
-          break;
-      } // switch stepCmdIn for ces_generating
-      break;
-
-    // Ready for processing steps
-    case ces_processing:
-      switch (stepCmdIn) {
-        case STEPCMD_STEP :
-          sta = processingStep(aStepCmd,aInfoP);
-          break;
-      } // switch stepCmdIn for ces_processing
-      break;
-
-    // Waiting for SyncML data
-    case ces_needdata:
-      switch (stepCmdIn) {
-        case STEPCMD_GOTDATA :
-          // got data, now start processing it
-          OBJ_PROGRESS_EVENT(getSyncAppBase(),pev_recvend,NULL,0,0,0);
-          fIgnoreMsgErrs=false; // do not ignore errors by default
-          fEngineState = ces_processing;
-          aStepCmd = STEPCMD_OK;
-          sta = LOCERR_OK;
-          break;
-        case STEPCMD_RESENDDATA :
-               // instead of having received new data, the network layer has found it needs to re-send the data.
-          // performing the STEPCMD_RESENDDATA just generates a new send start event, but otherwise no engine action
-          fEngineState = ces_resending;
-          aStepCmd = STEPCMD_RESENDDATA; // return the same step command, to differentiate it from STEPCMD_SENDDATA
-          OBJ_PROGRESS_EVENT(getSyncAppBase(),pev_sendstart,NULL,0,0,0);
-          sta = LOCERR_OK;
-          break;
-      } // switch stepCmdIn for ces_needdata
-      break;
-
-    // Waiting until SyncML data is sent
-    case ces_dataready:
-    case ces_resending:
-      switch (stepCmdIn) {
-        case STEPCMD_SENTDATA :
-               // allowed in dataready or resending state
-          // sent (or re-sent) data, now request answer data
-          OBJ_PROGRESS_EVENT(getSyncAppBase(),pev_sendend,NULL,0,0,0);
-          fEngineState = ces_needdata;
-          aStepCmd = STEPCMD_NEEDDATA;
-          sta = LOCERR_OK;
-          break;
-      } // switch stepCmdIn for ces_dataready
-      break;
-
-  case numClientEngineStates:
-      // invalid
-      break;
-
-  } // switch fEngineState
-
-  // done
-  return sta;
-} // TSyncClient::SessionStep
-
-
-
-// Step that generates SyncML data
-TSyError TSyncClient::generatingStep(uInt16 &aStepCmd, TEngineProgressInfo *aInfoP)
-{
-  localstatus sta = LOCERR_WRONGUSAGE;
-  bool done;
-
-  //%%% at this time, generate next message in one step
-  sta = NextMessage(done);
-  if (done) {
-    // done with session, with or without error
-    fEngineState = ces_done; // blocks any further activity with the session
-    aStepCmd = STEPCMD_DONE;
-    // terminate session to provoke all end-of-session progress events
-    TerminateSession();
-  }
-  else if (sta==LOCERR_OK) {
-       // finished generating outgoing message
-    // - make sure read pointer is set (advanced in case incoming
-    //   message had trailing garbage) to beginning of generated
-    //   answer. With incoming message being clean SyncML without
-    //   garbage, this call is not needed, however with garbage
-    //   it is important because otherwise outgoing message
-    //   would have that garbage inserted before actual message
-    //   start.
-    smlReadOutgoingAgain(getSmlWorkspaceID());
-    // next is sending request to server
-    fEngineState = ces_dataready;
-    aStepCmd = STEPCMD_SENDDATA;
-    OBJ_PROGRESS_EVENT(getSyncAppBase(),pev_sendstart,NULL,0,0,0);
-  }
-  // return status
-  return sta;
-} // TSyncClient::generatingStep
-
-
-
-// Step that processes SyncML data
-TSyError TSyncClient::processingStep(uInt16 &aStepCmd, TEngineProgressInfo *aInfoP)
-{
-  InstanceID_t myInstance = getSmlWorkspaceID();
-  Ret_t rc;
-  localstatus sta = LOCERR_WRONGUSAGE;
-
-  // now process next command
-  PDEBUGPRINTFX(DBG_EXOTIC,("Calling smlProcessData(NEXT_COMMAND)"));
-  #ifdef SYDEBUG
-  MemPtr_t data = NULL;
-  MemSize_t datasize;
-  smlPeekMessageBuffer(getSmlWorkspaceID(), false, &data, &datasize);
-  #endif  
-  rc=smlProcessData(
-    myInstance,
-    SML_NEXT_COMMAND
-  );
-  if (rc==SML_ERR_CONTINUE) {
-    // processed ok, but message not completely processed yet
-    // - engine state remains as is
-    aStepCmd = STEPCMD_OK; // ok w/o progress %%% for now, progress is delivered via queue in next step
-    sta = LOCERR_OK;
-  }
-  else if (rc==SML_ERR_OK) {
-    // message completely processed
-    // - switch engine state to generating next message (if any)
-    aStepCmd = STEPCMD_OK;
-    fEngineState = ces_generating;
-    sta = LOCERR_OK;
-  }
-  else {
-    // processing failed
-    PDEBUGPRINTFX(DBG_ERROR,("===> smlProcessData failed, returned 0x%hX",(sInt16)rc));
-    // dump the message that failed to process
-    #ifdef SYDEBUG
-    if (data) DumpSyncMLBuffer(data,datasize,false,rc);
-    #endif    
-    if (!fIgnoreMsgErrs) {
-           // abort the session (causing proper error events to be generated and reported back)
-       AbortSession(LOCERR_PROCESSMSG, true);
-      // session is now done
-      fEngineState = ces_done;
-    }
-    else {
-       // we must ignore errors e.g. because of session restart and go back to generate next message
-      fEngineState = ces_generating;
-    }
-    // anyway, step by itself is ok - let app continue stepping (to restart session or complete abort)
-    aStepCmd = STEPCMD_OK;
-    sta = LOCERR_OK;
-  }
-  // now check if this is a session restart
-  if (sta==LOCERR_OK && isStarting()) {
-    // this is still the beginning of a session, which means
-    // that we are restarting the session and caller should close
-    // eventually open communication with the server before sending the next message
-    aStepCmd = STEPCMD_RESTART;
-  }
-  // done
-  return sta;
-} // TSyncClient::processingStep
-
-#endif // ENGINEINTERFACE_SUPPORT
-
-
-
-
-void TSyncClient::InternalResetSession(void)
-{
-  // use remote URI as specified to start a session
-  fRespondURI = fRemoteURI;
-  #ifdef HARD_CODED_SERVER_URI
-  #if defined(CUSTOM_URI_SUFFIX) && !defined(HARD_CODED_SERVER_URI_LEN)
-  #error "HARD_CODED_SERVER_URI_LEN must be defined when using CUSTOM_URI_SUFFIX"
-  #endif
-  #ifdef HARD_CODED_SERVER_URI_LEN
-  // only part of URL must match (max HARD_CODED_SERVER_URI_LEN chars will be added, less if URI is shorter)
-  fServerURICRC = addNameToCRC(SYSER_CRC32_SEED, fRemoteURI.c_str()+fNoCRCPrefixLen, false, HARD_CODED_SERVER_URI_LEN);
-  #else
-  // entire URL (except prefix) must match
-  fServerURICRC = addNameToCRC(SYSER_CRC32_SEED, fRemoteURI.c_str()+fNoCRCPrefixLen, false);
-  #endif
-  #endif
-  // set SyncML version
-  // Note: will be overridden with call to loadRemoteParams()
-  fSyncMLVersion = syncml_vers_unknown; // unknown
-  // will be cleared to suppress automatic use of DS 1.2 SINCE/BEFORE filters
-  // (e.g. for date range in func_SetDaysRange())
-  fServerHasSINCEBEFORE = true;
-  // no outgoing alert 222 sent so far
-  fOutgoingAlert222Count = 0;
-} // TSyncClient::InternalResetSession
-
-
-// Virtual version
-void TSyncClient::ResetSession(void)
-{
-  // let ancestor do its stuff
-  TSyncSession::ResetSession();
-  // do my own stuff (and probably modify settings of ancestor!)
-  InternalResetSession();
-} // TSyncClient::ResetSession
-
-
-
-// initialize the client session and link it with the SML toolkit
-localstatus TSyncClient::InitializeSession(uInt32 aProfileSelector, bool aAutoSyncSession)
-{
-  localstatus sta;
-
-  // Select profile now (before creating instance, as encoding is dependent on profile)
-  sta=SelectProfile(aProfileSelector, aAutoSyncSession);
-  if (sta) return sta;
-  // Start a SyncML toolkit instance now and set the encoding from config
-  InstanceID_t myInstance;
-  if (!getSyncAppBase()->newSmlInstance(
-    getEncoding(),
-    getRootConfig()->fLocalMaxMsgSize * 2, // twice the message size
-    myInstance
-  )) {
-    return LOCERR_SMLFATAL;
-  }
-  // let toolkit know the session pointer
-  if (getSyncAppBase()->setSmlInstanceUserData(myInstance,this)!=SML_ERR_OK) // toolkit must know session (as userData)
-    return LOCERR_SMLFATAL;
-  // remember the instance myself
-  setSmlWorkspaceID(myInstance); // session must know toolkit workspace
-  // done
-  return LOCERR_OK;
-} // TSyncClient::InitializeSession
-
-
-
-// select a profile (returns false if profile not found)
-// Note: base class just tries to retrieve information from
-//       config
-localstatus TSyncClient::SelectProfile(uInt32 aProfileSelector, bool aAutoSyncSession)
-{
-  #ifndef PRECONFIGURED_SYNCREQUESTS
-  // no profile settings in config -> error
-  return LOCERR_NOCFG;
-  #else
-  // get profile settings from config
-  TClientConfig *configP = static_cast<TClientConfig *>(getRootConfig()->fAgentConfigP);
-  // - get encoding
-  fEncoding=configP->fEncoding; // SyncML encoding
-  // - set server access details
-  fRemoteURI=configP->fServerURI; // Remote URI = Server URI
-  fTransportUser=configP->fTransportUser; // transport layer user (e.g. HTTP auth)
-  fTransportPassword=configP->fTransportPassword; // transport layer password (e.g. HTTP auth)
-  fServerUser=configP->fServerUser; // Server layer authentification user name
-  fServerPassword=configP->fServerPassword; // Server layer authentification password
-  #ifndef NO_LOCAL_DBLOGIN
-  fLocalDBUser=configP->fLocalDBUser; // Local DB authentification user name (empty if local DB is single user)
-  fNoLocalDBLogin=configP->fNoLocalDBLogin; // if set, no local DB auth takes place, but fLocalDBUser is used as userkey (depending on DB implementation)
-  fLocalDBPassword=configP->fLocalDBPassword; // Local DB authentification password
-  #endif
-  fProxyHost=configP->fProxyHost; // Proxy host
-  fSocksHost=configP->fSocksHost; // Socks host
-  fProxyUser=configP->fProxyUser;
-  fProxyPassword=configP->fProxyPassword;
-  // Reset session after profile change
-  // and also remove any datastores we might have
-  ResetAndRemoveDatastores();
-  // if tunnel, that's all for now
-  if (aProfileSelector==TUNNEL_PROFILE_ID) return LOCERR_OK;
-  // - create and init datastores needed for this session from config
-  //   Note: probably config has no sync requests, but they are created later
-  //         programmatically
-  TSyncReqList::iterator pos;
-  for (pos=configP->fSyncRequests.begin(); pos!=configP->fSyncRequests.end(); pos++) {
-    // create and init the datastore
-    fLocalDataStores.push_back(
-      (*pos)->initNewLocalDataStore(this)
-    );
-  }
-  // create "new" session ID (derivates will do this better)
-  fClientSessionNo++;
-  return LOCERR_OK;
-  #endif
-} // TSyncClient::SelectProfile
-
-
-// make sure we are logged in to local datastore
-localstatus TSyncClient::LocalLogin(void)
-{
-  #ifndef NO_LOCAL_DBLOGIN
-  if (!fNoLocalDBLogin && !fLocalDBUser.empty()) {
-    // check authorisation (login to correct user) in local DB
-    if (!SessionLogin(fLocalDBUser.c_str(),fLocalDBPassword.c_str(),sectyp_clearpass,fRemoteURI.c_str())) {
-      return localError(401); // done & error
-    }
-  }
-  #endif
-  return LOCERR_OK;
-} // TSyncClient::LocalLogin
-
-
-// starting with engine version 2.0.8.7 a client's device ID (in devinf) is no longer
-// a constant string, but the device's unique ID
-string TSyncClient::getDeviceID(void)
-{
-  if (fLocalURI.empty())
-    return SYSYNC_CLIENT_DEVID; // return default ID
-  else
-    return fLocalURI;
-} // TSyncClient::getDeviceID
-
-string TSyncClient::getDeviceType(void)
-{
-  // taken from configuration or SYSYNC_CLIENT_DEVTYP
-  return getSyncAppBase()->getDevTyp();
-}
-
-
-
-// process message in the instance buffer
-localstatus TSyncClient::processAnswer(void)
-{
-  InstanceID_t myInstance = getSmlWorkspaceID();
-  Ret_t err;
-
-  // now process data
-  DEBUGPRINTF(("===> now calling smlProcessData"));
-  #ifdef SYDEBUG
-  MemPtr_t data = NULL;
-  MemSize_t datasize;
-  smlPeekMessageBuffer(getSmlWorkspaceID(), false, &data, &datasize);
-  #endif  
-  fIgnoreMsgErrs=false;
-  err=smlProcessData(
-    myInstance,
-    SML_ALL_COMMANDS
-  );
-  if (err) {
-    // dump the message that failed to process
-    #ifdef SYDEBUG
-    if (data) DumpSyncMLBuffer(data,datasize,false,err);
-    #endif    
-       if (!fIgnoreMsgErrs) {
-      PDEBUGPRINTFX(DBG_ERROR,("===> smlProcessData failed, returned 0x%hX",(sInt16)err));
-      // other problem or already using SyncML 1.0 --> error
-      return LOCERR_PROCESSMSG;
-    }
-  }
-  // now check if this is a session restart
-  if (isStarting()) {
-    // this is still the beginning of a session
-    return LOCERR_SESSIONRST;
-  }
-  return LOCERR_OK;
-} // TSyncClientBase::processAnswer
-
-
-
-// let session produce (or finish producing) next message into
-// SML workspace
-// - returns aDone if no answer needs to be sent (=end of session)
-// - returns 0 if successful
-// - returns SyncML status code if unsucessfully aborted session
-localstatus TSyncClient::NextMessage(bool &aDone)
-{
-  TLocalDataStorePContainer::iterator pos;
-  TSyError status;
-
-  TP_START(fTPInfo,TP_general); // could be new thread
-  // default to not continuing
-  aDone=true;
-  #ifdef PROGRESS_EVENTS
-  // check for user suspend
-  if (!getSyncAppBase()->NotifyProgressEvent(pev_suspendcheck)) {
-    SuspendSession(LOCERR_USERSUSPEND);
-  }
-  #endif
-  // done if session was aborted by last received commands
-  if (isAborted()) return getAbortReasonStatus(); // done & error
-  // check package state
-  if (fOutgoingState==psta_idle) {
-    // if suspended here, we'll just stop - nothing has happened yet
-    if (isSuspending()) {
-      AbortSession(fAbortReasonStatus,true);
-      return getAbortReasonStatus();
-    }
-    // start of an entirely new client session
-    #ifdef HARD_CODED_SERVER_URI
-    // extra check to limit hacking
-    if (fServerURICRC != SERVER_URI_CRC) {
-      // someone has tried to change the URI
-      DEBUGPRINTFX(DBG_ERROR,("hardcoded Server URI CRC mismatch"));
-      return LOCERR_LIMITED; // user will not know what this means, but we will
-    }
-    #endif
-    // - check if we have client requests
-    if (fLocalDataStores.size()<1) {
-      PDEBUGPRINTFX(DBG_ERROR,("No datastores defined to sync with"));
-      return LOCERR_NOCFG;
-    }
-    // %%% later, we could probably load cached info about
-    //     server requested auth, devinf etc. here
-    // use remote URI as specified to start a session
-    fRespondURI=fRemoteURI;
-    // get default params for sending first message to remote
-    // Note: may include remote flag settings that influence creation of my own ID below, that's why we do it now here
-    loadRemoteParams();
-    // get info about my own URI, whatever that is
-    #ifndef HARDCODED_CONFIG
-    if (!static_cast<TClientConfig *>(getRootConfig()->fAgentConfigP)->fFakeDeviceID.empty()) {
-      // return fake Device ID if we have one defined in the config file (useful for testing)
-      fLocalURI = static_cast<TClientConfig *>(getRootConfig()->fAgentConfigP)->fFakeDeviceID;
-    }
-    else
-    #endif
-    {
-      if (!getLocalDeviceID(fLocalURI) || devidWithUserHash()) {
-        // Device ID is not really unique, make a hash including user name to make it pseudo-unique
-        // create MD5 hash from non-unique ID and user name
-        // Note: when compiled with GUARANTEED_UNIQUE_DEVICID, devidWithUserHash() is always false.
-        md5::SYSYNC_MD5_CTX context;
-        uInt8 digest[16]; // for MD5 digest
-        md5::Init (&context);
-        // - add what we got for ID
-        md5::Update (&context, (uInt8 *)fLocalURI.c_str(), fLocalURI.size());
-        // - add user name, if any
-        if (fLocalURI.size()>0) md5::Update (&context, (uInt8 *)fServerUser.c_str(), fServerUser.size());
-        // - done
-        md5::Final (digest, &context);
-        // now make hex string of that
-        fLocalURI = devidWithUserHash() ? 'x' : 'X'; // start with X to document this special case (lowercase = forced by remoteFlag)
-        for (int n=0; n<16; n++) {
-          AppendHexByte(fLocalURI,digest[n]);
-        }
-      }
-    }
-    // get my own name (if any)
-    getPlatformString(pfs_device_name,fLocalName);
-    // override some of these if not set by loadRemoteParams()
-    if (fSyncMLVersion==syncml_vers_unknown)
-      fSyncMLVersion=static_cast<TClientConfig *>(getRootConfig()->fAgentConfigP)->fAssumedServerVersion;
-    if (fRemoteRequestedAuth==auth_none)
-      fRemoteRequestedAuth=static_cast<TClientConfig *>(getRootConfig()->fAgentConfigP)->fAssumedServerAuth;
-    if (fRemoteRequestedAuthEnc==fmt_chr)
-      fRemoteRequestedAuthEnc=static_cast<TClientConfig *>(getRootConfig()->fAgentConfigP)->fAssumedServerAuthEnc;
-    if (fRemoteNonce.empty())
-      fRemoteNonce=static_cast<TClientConfig *>(getRootConfig()->fAgentConfigP)->fAssumedNonce;
-
-    // we are not yet authenticated for the entire session
-    fNeedAuth=true;
-    // now ready for init
-    fOutgoingState=psta_init; // %%%% could also set psta_initsync for combined init/sync
-    fIncomingState=psta_idle; // remains idle until first answer SyncHdr with OK status is received
-    fInProgress=true; // assume in progress
-    // set session ID string
-    StringObjPrintf(fSynchdrSessionID,"%hd",(sInt16)fClientSessionNo);
-    // now we have a session id, can now display debug stuff
-    #ifdef SYDEBUG
-    string t;
-    StringObjTimestamp(t,getSystemNowAs(TCTX_SYSTEM));
-    PDEBUGPRINTFX(DBG_HOT,("\n[%s] =================> Starting new client session",t.c_str()));
-    #endif
-    // - make sure we are logged into the local database (if needed)
-    status=LocalLogin();
-    if (status!=LOCERR_OK) return status;
-    // create header for first message no noResp
-    issueHeader(false);
-  }
-  else {
-    // check for proper end of session (caused by MessageEnded analysis)
-    if (!fInProgress) {
-      // give an opportunity to let make outgoing message end and flush xml end message 
-      FinishMessage(true, false);  
-      // end sync in all datastores (save anchors etc.)
-      PDEBUGPRINTFX(DBG_PROTO,("Successful end of session -> calling engFinishDataStoreSync() for datastores now"));
-      for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos)
-        (*pos)->engFinishDataStoreSync(); // successful end
-      PDEBUGPRINTFX(DBG_PROTO,("Session not any more in progress: NextMessage() returns OK status=0"));
-      return LOCERR_OK; // done & ok
-    }
-  }
-  // check expired case
-  #ifdef APP_CAN_EXPIRE
-  if (getClientBase()->fAppExpiryStatus!=LOCERR_OK) {
-    PDEBUGPRINTFX(DBG_ERROR,("Evaluation Version expired - Please contact Synthesis AG for release version"));
-    return getClientBase()->fAppExpiryStatus; // payment required, done & error
-  }
-  #endif
-  if (fOutgoingState==psta_init || fOutgoingState==psta_initsync) {
-    // - if suspended in init, nothing substantial has happened already, so just exit
-    if (isSuspending() && fOutgoingState==psta_init) {
-      AbortSession(fAbortReasonStatus,true);
-      return getAbortReasonStatus();
-    }
-    // - prepare Alert(s) for databases to sync
-    bool anyfirstsyncs=false;
-    bool anyslowsyncs=false;
-    TLocalEngineDS *localDS;
-    for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
-      // prepare alert
-      localDS = *pos;
-      status=localDS->engPrepareClientSyncAlert(NULL); // not as superdatastore
-      if (status!=LOCERR_OK) {
-        // local database error
-        return localError(status); // not found
-      }
-      if (localDS->fFirstTimeSync) anyfirstsyncs=true;
-      if (localDS->fSlowSync) anyslowsyncs=true;
-    }
-    // send devinf in Put command right away with init message if either...
-    // - mustSendDevInf() returns true signalling an external condition that suggests sending devInf (like changed config)
-    // - any datastore is doing first time sync
-    // - fPutDevInfAtSlowSync is true and any datastore is doing slow sync
-    if (
-       mustSendDevInf() ||
-      anyfirstsyncs ||
-      (anyslowsyncs && static_cast<TClientConfig *>(getRootConfig()->fAgentConfigP)->fPutDevInfAtSlowSync)
-    ) {
-      TDevInfPutCommand *putcmdP = new TDevInfPutCommand(this);
-      issueRootPtr(putcmdP);
-    }
-    // try to load devinf from cache (only if we don't know it already)
-    if (!fRemoteDataStoresKnown || !fRemoteDataTypesKnown) {
-      SmlDevInfDevInfPtr_t devinfP;
-      if (loadRemoteDevInf(getRemoteURI(),devinfP)) {
-        // we have cached devinf, analyze it now
-        analyzeRemoteDevInf(devinfP);
-      }
-    }
-    // GET the server's info if server didn't send it and we haven't cached at least the datastores
-    if (!fRemoteDataStoresKnown) {
-      // if we know datastores here, but not types, this means that remote does not have
-      // CTCap, so it makes no sense to issue a GET again.
-      #ifndef NO_DEVINF_GET
-      PDEBUGPRINTFX(DBG_REMOTEINFO,("Nothing known about server, request DevInf using GET command"));
-      TGetCommand *getcommandP = new TGetCommand(this);
-      getcommandP->addTargetLocItem(SyncMLDevInfNames[fSyncMLVersion]);
-      string devinftype=SYNCML_DEVINF_META_TYPE;
-      addEncoding(devinftype);
-      getcommandP->setMeta(newMetaType(devinftype.c_str()));
-      ISSUE_COMMAND_ROOT(this,getcommandP);
-      #endif
-    }
-    // - create Alert(s) for databases to sync
-    for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
-      // create alert for non-subdatastores
-      localDS = *pos;
-      if (!localDS->isSubDatastore()) {
-        TAlertCommand *alertcmdP;
-        status=localDS->engGenerateClientSyncAlert(alertcmdP);
-        if (status!=0) {
-          // local database error
-          return status; // not found
-        }
-        ///%%%% unneeded (probably got here by copy&paste accidentally): if (localDS->fFirstTimeSync) anyfirstsyncs=true;
-        // issue alert
-        issueRootPtr(alertcmdP);
-      }
-    }
-    // append sync phase if we have combined init/sync
-    if (fOutgoingState==psta_initsync) fOutgoingState=psta_sync;
-  }
-  // process sync/syncop/map generating phases after init
-  if (!isSuspending()) {
-    // normal, session continues
-    if (fOutgoingState==psta_sync) {
-      // hold back sync until server has finished first package (init or initsync)
-      if (fIncomingState==psta_sync || fIncomingState==psta_initsync) {
-        // start sync for alerted datastores
-        for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
-          // Note: some datastores might be aborted due to unsuccessful alert.
-          if ((*pos)->isActive()) {
-               // prepare engine for sync (%%% new routine in 3.2.0.3, summarizing engInitForSyncOps() and
-            // switching to dssta_dataaccessstarted, i.e. loading sync set), but do in only once
-            if (!((*pos)->testState(dssta_syncsetready))) {
-               // not yet started
-                       status = (*pos)->engInitForClientSync();
-                   if (status!=LOCERR_OK) {
-                // failed
-                AbortSession(status,true);
-                return getAbortReasonStatus();
-              }
-            }
-               /* %%% old code: engInitForSyncOps was here, but switching to dssta_dataaccessstarted
-                   was done earlier when handling alert from server. This caused that types
-                   were not ready when loading the sync set, making client-side filtering impossible
-            // initialize datastore for sync
-            TStatusCommand dummystatus(this);
-            status = (*pos)->engInitForSyncOps((*pos)->getRemoteDBPath());
-            if (status!=LOCERR_OK) {
-              // failed
-              AbortSession(status,true);
-              return status;
-            }
-            // init prepared, we can now call datastore to generate sync command
-            */
-            // start or continue (which is largely nop, as continuing works via unfinished sync command)
-            // generating sync items
-            (*pos)->engClientStartOfSyncMessage();
-          }
-        }
-      }
-    }
-    else if (fOutgoingState==psta_map) {
-      // hold back map until server has started sync at least (incominstate >=psta_sync)
-      // NOTE: This is according to the specs, which says that client can begin
-      //   with Map/update status package BEFORE sync package from server is
-      //   completely received.
-      // NOTE: Starfish server expects this and generates a few 222 alerts
-      //   if we wait here, but then goes to map as well
-      //   (so (fIncomingState==psta_map)-version works as well here!
-      // %%%% other version: wait until server has started map phase as well
-      // %%%% if (fIncomingState==psta_map) {
-      if (fIncomingState>=psta_sync) {
-        // start map for synced datastores
-        for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
-          // Note: some datastores might be aborted due to unsuccessful alert.
-          if ((*pos)->isActive()) {
-            // now call datastore to generate map command if not already done
-            (*pos)->engClientStartOfMapMessage(fIncomingState<psta_map);
-          }
-        }
-      }
-    }
-    else if (fOutgoingState==psta_supplement) {
-       // we are waiting for the server to complete a pending phase altough we are already done
-      // with everything we want to send.
-      // -> just generate a Alert 222 and wait for server to complete
-      PDEBUGPRINTFX(DBG_PROTO+DBG_HOT,("Client finished so far, but needs to wait in supplement outgoing state until server finishes phase"));
-    }
-    else if (fOutgoingState!=psta_init) {
-      // NOTE: can be psta_init because "if" begins again after psta_init checking
-      //       to allow psta_init appending psta_sync for combined init/sync
-      // no known state
-      return 9999; // %%%%%
-    }
-  } // if not suspended
-
-  // security only: exit here if session got aborted in between
-  if (isAborted())
-    return getAbortReasonStatus(); // done & error
-  if (!fInProgress)
-    return 9999; // that's fine with us
-  // now, we know that we will (most probably) send a message, so default for aDone is false from now on
-  aDone=false;
-  bool outgoingfinal;
-
-  // check for suspend
-  if (isSuspending()) {
-    // make sure we send a Suspend Alert
-    TAlertCommand *alertCmdP = new TAlertCommand(this,NULL,(uInt16)224);
-    // - we just put local and remote URIs here
-    SmlItemPtr_t itemP = newItem();
-    itemP->target = newLocation(fRemoteURI.c_str());
-    itemP->source = newLocation(fLocalURI.c_str());
-    alertCmdP->addItem(itemP);
-    ISSUE_COMMAND_ROOT(this,alertCmdP);
-    // outgoing message is final, regardless of any session state
-    outgoingfinal=true;
-    MarkSuspendAlertSent(true);
-  }
-  else {
-    // Determine if package can be final and if we need an 222 Alert
-    // NOTE: if any commands were interruped or not sent due to outgoing message
-    //       size limits, FinishMessage() will prevent final anyway, so no
-    //       separate checking for enOfSync or endOfMap is needed.
-    // - can finalize message when server has at least started answering current package
-    //   OR if this is the first message (probably repeatedly) sent
-    outgoingfinal = fIncomingState >= fOutgoingState || fIncomingState==psta_idle;
-    if (outgoingfinal) {
-      // allow early success here in case of nothing to respond, and nothing pending
-      // StarFish server does need this...
-      if (!fNeedToAnswer) {
-        if (hasPendingCommands()) {
-          // we have pending commands, cannot be final message
-          outgoingfinal=false;
-        }
-        else {
-          // no pending commands -> we're done now
-          PDEBUGPRINTFX(DBG_PROTO,("Early end of session (nothing to send to server any more) -> calling engFinishDataStoreSync() for datastores now"));
-          // - end sync in all datastores (save anchors etc.)
-          for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos)
-            (*pos)->engFinishDataStoreSync(); // successful end
-          PDEBUGPRINTFX(DBG_PROTO,("Session not any more in progress: NextMessage() returns OK status=0"));
-          // done & ok
-          aDone=true;
-          return LOCERR_OK;
-        }
-      }
-    }
-  }
-  /* A dummy alert indicates this is a message with only alert222 request*/
-  bool dummyAlert = false;
-  if (!outgoingfinal) {
-    // - send Alert 222 if we need to continue package but have nothing to send
-    //   (or ALWAYS_CONTINUE222 defined)
-    #ifndef ALWAYS_CONTINUE222
-    if (!fNeedToAnswer)
-    #endif
-    {
-      /* End-less loop detection
-       * Some servers will never end and triggers client sends
-       * ALERT222 forever. Detect this scenario and abort the session if
-       * detected.
-       * It is still valid for the server to use ALERT222 to "keep-alive" the
-       * connection.
-       * Therefore the loop detection criteria is:
-       * - Nothing to send except the 222 Alert (!fNeedToAnswer)
-       * - 5 adjacent 222 alerts within 20 seconds
-       * - no status for an actual sync op command received (fOutgoingAlert222Count will be reset by those)
-       *   because a server sending pending status in small chunks could also trigger the detector otherwise
-       */
-      if (!fNeedToAnswer) {
-        dummyAlert = true;
-        if (fOutgoingAlert222Count++ == 0) {
-               // start of 222 loop detection time
-          fLastOutgoingAlert222 = getSystemNowAs(TCTX_UTC);
-        } else if (fOutgoingAlert222Count > 5) {
-          lineartime_t curTime = getSystemNowAs(TCTX_UTC);
-          if (curTime - fLastOutgoingAlert222 < 20*secondToLinearTimeFactor) {
-            PDEBUGPRINTFX(DBG_ERROR,(
-              "Warning: More than 5 consecutive Alert 222 within 20 seconds- "
-              "looks like endless loop, abort session"
-            ));
-            AbortSession(400, false);
-            return getAbortReasonStatus();
-          } else {
-            fOutgoingAlert222Count = 0;
-          }
-        }
-      }
-      // not final, and nothing to answer otherwise: create alert-Command to request more info
-      TAlertCommand *alertCmdP = new TAlertCommand(this,NULL,(uInt16)222);
-      // %%% not clear from spec what has to be in item for 222 alert code
-      //     but there MUST be an Item for the Alert command according to SyncML TK
-      // - we just put local and remote URIs here
-      SmlItemPtr_t itemP = newItem();
-      itemP->target = newLocation(fRemoteURI.c_str());
-      itemP->source = newLocation(fLocalURI.c_str());
-      alertCmdP->addItem(itemP);
-      ISSUE_COMMAND_ROOT(this,alertCmdP);
-    }
-  }
-  // We send a response with no dummy alert, so reset the alert detector
-  if (!dummyAlert) {
-    fOutgoingAlert222Count = 0;
-  }
-
-  // send custom end-of session puts
-  if (!isSuspending() && outgoingfinal && fOutgoingState==psta_map) {
-    // End of outgoing map package; let custom PUTs which may transmit some session statistics etc. happen now
-    issueCustomEndPut();
-  }
-  // message complete, now finish it
-  FinishMessage(
-    outgoingfinal, // allowed if possible
-    false // final not prevented
-  );
-  // Note, now fNewOutgoingPackage is set (by FinishMessage())
-  // if next message will be responded to with a new package
-
-  // debug info
-  #ifdef SYDEBUG
-  if (PDEBUGMASK & DBG_SESSION) {
-    PDEBUGPRINTFX(DBG_SESSION,(
-      "---> NextMessage, outgoing state='%s', incoming state='%s'",
-      PackageStateNames[fOutgoingState],
-      PackageStateNames[fIncomingState]
-    ));
-    TLocalDataStorePContainer::iterator pos;
-    for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
-      // Show state of local datastores
-      PDEBUGPRINTFX(DBG_SESSION,(
-        "Local Datastore '%s': %sState=%s, %s%s sync, %s%s",
-        (*pos)->getName(),
-        (*pos)->isAborted() ? "ABORTED - " : "",
-        (*pos)->getDSStateName(),
-        (*pos)->isResuming() ? "RESUMED " : "",
-        (*pos)->fSlowSync ? "SLOW" : "normal",
-        SyncModeDescriptions[(*pos)->fSyncMode],
-        (*pos)->fServerAlerted ? ", Server-Alerted" : ""
-      ));
-    }
-  }
-  PDEBUGENDBLOCK("SyncML_Outgoing");
-  if (getLastIncomingMsgID()>0) {
-    // we have already received an incoming message, so we have started an "SyncML_Incoming" blocks sometime
-    PDEBUGENDBLOCK("SyncML_Incoming"); // terminate debug block of previous incoming message as well
-  }
-  #endif
-  // ok
-  return LOCERR_OK; // ok
-} // TSyncClient::NextMessage
-
-
-
-// called after successful decoding of an incoming message
-bool TSyncClient::MessageStarted(SmlSyncHdrPtr_t aContentP, TStatusCommand &aStatusCommand, bool aBad)
-{
-  // message not authorized by default
-  fMessageAuthorized=false;
-
-  // Check information from SyncHdr
-  if (
-    aBad ||
-    (!(fSynchdrSessionID==smlPCDataToCharP(aContentP->sessionID))) ||
-    (!(fLocalURI==smlSrcTargLocURIToCharP(aContentP->target)))
-  ) {
-    // bad response
-    PDEBUGPRINTFX(DBG_ERROR,(
-      "Bad SyncHeader from Server. Syntax %s, SessionID (rcvd/correct) = '%s' / '%s', LocalURI (rcvd/correct) = '%s' / '%s'",
-      aBad ? "ok" : "BAD",
-      smlPCDataToCharP(aContentP->sessionID),
-      fSynchdrSessionID.c_str(),
-      smlSrcTargLocURIToCharP(aContentP->target),
-      fLocalURI.c_str()
-    ));
-    aStatusCommand.setStatusCode(400); // bad response/request
-    AbortSession(400,true);
-    return false;
-  }
-  // check for suspend: if we are suspended at this point, this means that we have sent the Suspend Alert already
-  // in the previous message (due to user suspend request), so we can now terminate the session
-  if (isSuspending() && isSuspendAlertSent()) {
-    AbortSession(514,true,LOCERR_USERSUSPEND);
-    return false;
-  }
-  // - RespURI (remote URI to respond to)
-  if (aContentP->respURI) {
-    fRespondURI=smlPCDataToCharP(aContentP->respURI);
-    DEBUGPRINTFX(DBG_PROTO,("RespURI set to = '%s'",fRespondURI.c_str()));
-  }
-  // authorization check
-  // Note: next message will be started not before status for last one
-  //       has been processed. Commands issued before will automatically
-  //       be queued by issuePtr()
-  // %%% none for now
-  fSessionAuthorized=true;
-  fMessageAuthorized=true;
-  // returns false on BAD header (but true on wrong/bad/missing cred)
-  return true;
-} // TSyncClient::MessageStarted
-
-
-// determines new package states and sets fInProgress
-void TSyncClient::MessageEnded(bool aIncomingFinal)
-{
-  TLocalDataStorePContainer::iterator pos;
-
-  // show status before processing
-  PDEBUGPRINTFX(DBG_SESSION,(
-    "MessageEnded starts   : old outgoing state='%s', old incoming state='%s', %sNeedToAnswer",
-    PackageStateNames[fOutgoingState],
-    PackageStateNames[fIncomingState],
-    fNeedToAnswer ? "" : "NO "
-  ));
-  bool allFromClientOnly=false;
-  // process exceptions
-  if (fAborted) {
-    PDEBUGPRINTFX(DBG_ERROR,("***** Session is flagged 'aborted' -> MessageEnded ends package and session"));
-    fOutgoingState=psta_idle;
-    fIncomingState=psta_idle;
-    fInProgress=false;
-  } // if aborted
-  else if (!fMessageAuthorized) {
-    // not authorized messages will just be ignored, so
-    // nothing changes in states
-    // %%% this will probably not really work, as we would need to repeat the last
-    //     message in this (unlikely) case that fMessageAuthorized is not set for
-    //     a non-first message (first message case is handled in handleHeaderStatus)
-    DEBUGPRINTFX(DBG_ERROR,("***** received Message not authorized, ignore and DONT end package"));
-    fInProgress=true;
-  }
-  else {
-    fInProgress=true; // assume we need to continue
-    // Note: the map phase will not take place, if all datastores are in
-    //       send-to-server-only mode and we are not in non-conformant old
-    //       synthesis-compatible fCompleteFromClientOnly mode.
-    if (!fCompleteFromClientOnly) {
-      // let all local datastores know that message has ended
-      allFromClientOnly=true;
-      for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
-        // check sync modes
-        if ((*pos)->isActive() && (*pos)->getSyncMode()!=smo_fromclient) {
-          allFromClientOnly=false;
-          break;
-        }
-      }
-    }
-    // new outgoing state is determined by the incomingState of this message
-    // (which is the answer to the <final/> message of the previous outgoing package)
-    if (fNewOutgoingPackage && fIncomingState!=psta_idle) {
-      // last message sent was an end-of-package, so next will be a new package
-      if (fIncomingState==psta_init) {
-        // server has responded (or is still responding) to our finished init,
-        // so client enters sync state now (but holds back sync until server
-        // has finished init)
-        fOutgoingState=psta_sync;
-      }
-      else if (fIncomingState==psta_sync || fIncomingState==psta_initsync) {
-        // server has started (or already finished) sending statuses for our
-        // <sync> or its own <sync>
-        // client can enter map state (but holds back maps until server
-        // has finished sync/initsync). In case of allFromClientOnly, we skip the map phase
-        // but only if there is no need to answer.
-        // Otherwise, this is most probably an old (pre 2.9.8.2) Synthesis server that has
-        // sent an empty <sync> (and the status for it has set fNeedToAnswer), so we still
-        // go to map phase.
-        if (allFromClientOnly && !fNeedToAnswer) {
-          fOutgoingState=psta_supplement; // all datastores are from-client-only, skip map phase
-          PDEBUGPRINTFX(DBG_PROTO+DBG_HOT,("All datastores in from-client-only mode, and no need to answer: skip map phase"));
-        }
-        else {
-          fOutgoingState=psta_map; // Some datastores do from-server-only or twoway, so we need a map phase
-          allFromClientOnly=false; // do not skip map phase
-        }
-      }
-      else {
-        // map is finished as well, we might need extra packages just to
-        // finish getting results for map commands
-        fOutgoingState=psta_supplement;
-      }
-    }
-    // New incoming state is simply derived from the incoming state of
-    // this message
-    if (aIncomingFinal && fIncomingState!=psta_idle) {
-      if (fIncomingState==psta_init) {
-        // switch to sync
-        fIncomingState=psta_sync;
-      }
-      else if (fIncomingState==psta_sync || fIncomingState==psta_initsync) {
-        // check what to do
-        if (allFromClientOnly) {
-          // no need to answer and allFromClientOnly -> this is the end of the session
-          fIncomingState=psta_supplement;
-          fInProgress=false; // normally, at end of map answer, we are done
-        }
-        else {
-          fIncomingState=psta_map;
-        }
-      }
-      else {
-        // end of a map phase - end of session (if no fNeedToAnswer)
-        fIncomingState=psta_supplement;
-        // this only ALLOWS ending the session, but it will continue as long
-        // as more than OK for SyncHdr (fNeedToAnswer) must be sent
-        fInProgress=false; // normally, at end of map answer, we are done
-      }
-    }
-    // continue anyway as long as we need to answer
-    if (fNeedToAnswer) fInProgress=true;
-  }
-  // show states
-  PDEBUGPRINTFX(DBG_HOT,(
-    "MessageEnded finishes : new outgoing state='%s', new incoming state='%s', %sNeedToAnswer",
-    PackageStateNames[fOutgoingState],
-    PackageStateNames[fIncomingState],
-    fNeedToAnswer ? "" : "NO "
-  ));
-  // let all local datastores know that message has ended
-  for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
-    // let them know
-    (*pos)->engEndOfMessage();
-    // Show state of local datastores
-    PDEBUGPRINTFX(DBG_HOT,(
-      "Local Datastore '%s': %sState=%s, %s%s sync, %s%s",
-      (*pos)->getName(),
-      (*pos)->isAborted() ? "ABORTED - " : "",
-      (*pos)->getDSStateName(),
-      (*pos)->isResuming() ? "RESUMED " : "",
-      (*pos)->isSlowSync() ? "SLOW" : "normal",
-      SyncModeDescriptions[(*pos)->getSyncMode()],
-      (*pos)->fServerAlerted ? ", Server-Alerted" : ""
-    ));
-  }
-  // thread might end here, so stop profiling
-  TP_STOP(fTPInfo);
-} // TSyncClient::MessageEnded
-
-
-// get credentials/username to authenticate with remote party, NULL if none
-SmlCredPtr_t TSyncClient::newCredentialsForRemote(void)
-{
-  if (fNeedAuth) {
-    // generate cretentials from username/password
-    PDEBUGPRINTFX(DBG_PROTO+DBG_USERDATA,("Authenticating with server as user '%s'",fServerUser.c_str()));
-    // NOTE: can be NULL when fServerRequestedAuth is auth_none
-    return newCredentials(
-      fServerUser.c_str(),
-      fServerPassword.c_str()
-    );
-  }
-  else {
-    // already authorized, no auth needed
-    return NULL;
-  }
-} // TSyncClient::newCredentialsForRemote
-
-
-// get client base
-TSyncClientBase *TSyncClient::getClientBase(void)
-{
-  return static_cast<TSyncClientBase *>(getSyncAppBase());
-} // TSyncClient::getClientBase
-
-
-// called when incoming SyncHdr fails to execute
-bool TSyncClient::syncHdrFailure(bool aTryAgain)
-{
-  // do not try to re-execute the header, just let message processing fail;
-  // this will cause the client's main loop to try using an older protocol
-  return false;
-} // TSyncClient::syncHdrFailure
-
-
-// retry older protocol, returns false if no older protocol to try
-bool TSyncClient::retryOlderProtocol(bool aSameVersionRetry, bool aOldMessageInBuffer)
-{
-  if (fIncomingState==psta_idle) {
-    // if we have not started a session yet and not using oldest protocol already,
-    // we want to retry with next older SyncML version
-    if (aSameVersionRetry) {
-      // just retry same version
-      PDEBUGPRINTFX(DBG_PROTO,("Retrying session start with %s",SyncMLVerProtoNames[fSyncMLVersion]));
-    }
-    else if (fSyncMLVersion>getSessionConfig()->fMinSyncMLVersionSupported) {
-      // next lower
-      fSyncMLVersion=(TSyncMLVersions)(((uInt16)fSyncMLVersion)-1);
-      PDEBUGPRINTFX(DBG_PROTO,("Server does not support our SyncML version, trying with %s",SyncMLVerProtoNames[fSyncMLVersion]));
-    }
-    else {
-      // cannot retry
-      return false;
-    }
-    // retry
-    retryClientSessionStart(aOldMessageInBuffer);
-    return true;
-  }
-  // session already started or no older protocol to try
-  return false;
-} // TSyncClient::retryOlderProtocol
-
-
-// prepares client session such that it will do a retry to start a session
-// (but keeping already received auth/nonce/syncML-Version state)
-void TSyncClient::retryClientSessionStart(bool aOldMessageInBuffer)
-{
-  TClientConfig *configP = static_cast<TClientConfig *>(getRootConfig()->fAgentConfigP);
-
-  // now restarting
-  PDEBUGPRINTFX(DBG_HOT,("=================> Retrying Client Session Start"));
-  bool newSessionForAuthRetry = configP->fNewSessionForAuthRetry;
-  bool noRespURIForAuthRetry = configP->fNoRespURIForAuthRetry;
-       // check if we should use modified behaviour (smart retries)
-  if (configP->fSmartAuthRetry && fAuthRetries>MAX_NORMAL_AUTH_RETRIES) {
-       if (newSessionForAuthRetry) {
-       // if we had new session for retry, switch to in-session retry now
-      newSessionForAuthRetry = false;
-      noRespURIForAuthRetry = false;
-    }
-    else {
-       // if we had in-session retry, try new session retry now
-      newSessionForAuthRetry = true;
-      noRespURIForAuthRetry = true;    
-    }
-    PDEBUGPRINTFX(DBG_PROTO,("Smart retry with modified behaviour: newSessionForAuthRetry=%d, noRespURIForAuthRetry=%d",newSessionForAuthRetry,noRespURIForAuthRetry));
-  }
-  // now retry
-  if (newSessionForAuthRetry) {
-    // Notes:
-    // - must apparently be disabled for SCTS 3.1.2 and eventually Mightyphone
-    // - must be enabled e.g for for Magically Server
-    // Create new session ID
-    StringObjPrintf(fSynchdrSessionID,"%hd",(sInt16)++fClientSessionNo);
-    // restart message counting at 1
-    fIncomingMsgID=0;
-    fOutgoingMsgID=0;
-    // we must terminate the block here when we reset fIncomingMsgID, as NextMessage
-    // only closes the incoming block when fIncomingMsgID>0
-    PDEBUGENDBLOCK("SyncML_Incoming");
-  }
-  if (noRespURIForAuthRetry) {
-    // Notes:
-    // - must apparently be switched on for Starfish.
-    // - must apparently be switched off for SCTS 3.1.2.
-    // make sure we send next msg to the original URL
-    fRespondURI=fRemoteURI;
-  }
-  // - make sure status for SyncHdr will not be generated!
-  forgetHeaderWaitCommands();
-  // check if we have already started next outgoing message
-  if (!fOutgoingStarted) {
-    if (aOldMessageInBuffer) {
-      // make sure we start with a fresh output buffer
-      // Note: This usually only occur when we are not currently parsing
-      //       part of the buffer. If we are parsing, the remaining incoming
-      //       message gets cleared as well.
-      getClientBase()->clrUnreadSmlBufferdata();
-    }
-    // start a new message
-    issueHeader(false);
-  }
-  else {
-    if (aOldMessageInBuffer) {
-      PDEBUGPRINTFX(DBG_ERROR,("Warning - restarting session with old message in output buffer"));
-    }
-  }
-  // - make sure subsequent commands (most probably statuses for Alerts)
-  //   don't get processed
-  AbortCommandProcessing(0); // silently discard all further commands
-  // - make sure eventual processing errors do not abort the session
-  fIgnoreMsgErrs = true;
-} // TSyncClient::retryClientSessionStart
-
-
-// handle status received for SyncHdr, returns false if not handled
-bool TSyncClient::handleHeaderStatus(TStatusCommand *aStatusCmdP)
-{
-  TClientConfig *configP = static_cast<TClientConfig *>(getRootConfig()->fAgentConfigP);
-  bool handled=true;
-  const char *txt;
-  SmlMetInfMetInfPtr_t chalmetaP=NULL;
-  SmlChalPtr_t chalP;
-
-  // first evaluate eventual challenge in header status
-  chalP = aStatusCmdP->getStatusElement()->chal;
-  if (chalP) {
-    chalmetaP = smlPCDataToMetInfP(chalP->meta);
-    if (chalmetaP) {
-      sInt16 ty;
-      // - get auth type
-      if (!chalmetaP->type) AbortSession(401,true); // missing auth, but no type
-      txt = smlPCDataToCharP(chalmetaP->type);
-      PDEBUGPRINTFX(DBG_PROTO,("Remote requests auth type='%s'",txt));
-      if (StrToEnum(authTypeSyncMLNames,numAuthTypes,ty,txt))
-        fRemoteRequestedAuth=(TAuthTypes)ty;
-      else {
-        AbortSession(406,true); // unknown auth type, not supported
-        goto donewithstatus;
-      }
-      // - get auth format
-      if (!smlPCDataToFormat(chalmetaP->format, fRemoteRequestedAuthEnc)) {
-        AbortSession(406,true); // unknown auth format, not supported
-        goto donewithstatus;
-      }
-      // - get next nonce
-      if (chalmetaP->nextnonce) {
-        // decode B64
-        uInt32 l;
-        uInt8 *nonce = b64::decode(smlPCDataToCharP(chalmetaP->nextnonce), 0, &l);
-        fRemoteNonce.assign((char *)nonce,l);
-        sysync_free(nonce);
-      }
-      // - show
-      PDEBUGPRINTFX(DBG_PROTO,(
-        "Next Cred will have type='%s' and format='%s' and use nonce='%s'",
-        authTypeNames[fRemoteRequestedAuth],
-        encodingFmtNames[fRemoteRequestedAuthEnc],
-        fRemoteNonce.c_str()
-      ));
-    }
-    /* %%% do not save here already, we don't know if SyncML version is ok
-           moved to those status code cases below that signal
-    // let descendant eventually save auth params
-    saveRemoteParams();
-    */
-  }
-  // now evaluate status code
-  switch (aStatusCmdP->getStatusCode()) {
-    case 101: // Busy
-      // Abort
-      AbortSession(101,false);
-      break;
-    case 212: // authentication accepted for entire session
-      fNeedAuth=false; // no need for further auth
-      PDEBUGPRINTFX(DBG_PROTO,("Remote accepted authentication for entire session"));
-    case 200: // authentication accepted for this message
-      // if this is the first authorized message we get an OK for the synchdr, this is
-      // also the first incoming message that is really processed as init message
-      if (fIncomingState==psta_idle && fMessageAuthorized) {
-        // first incoming is expected to be same as first outgoing (init or initsync)
-        fIncomingState=fOutgoingState;
-        PDEBUGPRINTFX(DBG_PROTO,("Authenticated successfully with remote server"));
-      }
-      else {
-        PDEBUGPRINTFX(DBG_PROTO,("Authentication with server ok for this message"));
-      }
-      // let descendant eventually save auth params
-      saveRemoteParams();
-      break;
-    case 501: // handle a "command not implemented" for the SyncHdr like 513 (indication that server does not like our header)
-    case 400: // ..and 400 as well (sync4j case, as it seems)
-    case 513: // bad protocol version
-    case 505: // bad DTD version (NextHaus/DeskNow case)
-      // try with next lower protocol
-      PDEBUGENDBLOCK("processStatus"); // done processing status
-      if (!retryOlderProtocol()) {
-        // no older SyncML protocol we can try --> abort
-        AbortSession(513,false); // server does not know any of our SyncML versions
-      }
-      break;
-    case 401: // bad authentication
-      // Bad authorisation
-      if (fAuthRetries==0)
-        // if first attempt is rejected with "bad", we conclude that the
-        // last attempt was carrying auth data and was not a attempt to get challenge
-        // from server. Therefore we count this as two tries (one get chal, one really failing)
-        fAuthRetries=2;
-      else
-        fAuthRetries++; // just count attempt to auth
-      /* %%% no longer required, is tested below at authfail:
-      if (fAuthRetries>MAX_AUTH_RETRIES) {
-        AbortSession(401,false); // abort session, too many retries
-        break;
-      }
-      */
-      // Treat no nonce like empty nonce to make sure that a server (like SySync old versions...)
-      // that does not send a nonce at all does not get auth with some old, invalid nonce string included.
-      if (chalmetaP && chalmetaP->nextnonce==NULL) fRemoteNonce.erase();
-      // otherwise treat like 407
-      goto authfail;
-    case 407: // authentication required
-      // new since 2.0.4.6: count this as well (normally this happens once when sending
-      // no auth to the server to force it to send us auth chal first).
-      fAuthRetries++;
-    authfail:
-      PDEBUGPRINTFX(DBG_ERROR,("Authentication failed (status=%hd) with remote server",aStatusCmdP->getStatusCode()));
-      // Auth fail after we have received a valid response for the init message indicates protocol messed up
-      if (fIncomingState!=psta_idle) {
-        AbortSession(400,true); // error in protocol handling from remote
-        break;
-      }
-      // Check if smart retries (with modified in-session vs out-of-session behaviour) are enabled
-      if (!configP->fSmartAuthRetry && fAuthRetries>MAX_NORMAL_AUTH_RETRIES) {
-       fAuthRetries = MAX_SMART_AUTH_RETRIES+1; // skip additional smart retries
-      }
-      // Missing or bad authorisation, evaluate chal
-      if (!chalmetaP || fAuthRetries>MAX_SMART_AUTH_RETRIES) {
-       #ifdef SYDEBUG
-       if (!chalmetaP) {
-                     PDEBUGPRINTFX(DBG_ERROR,("Bad auth but no challenge in response status -> can't work - no retry"));
-        }
-        #endif
-        AbortSession(aStatusCmdP->getStatusCode(),false); // retries exhausted or no retry possible (no chal) -> stop session
-        break;
-      }
-      // let descendant eventually save auth params
-      saveRemoteParams();
-      // modify session for re-start
-      PDEBUGENDBLOCK("processStatus"); // done processing status
-      retryClientSessionStart(false); // no previously sent message in the buffer
-      break;
-    default:
-      handled=false; // could not handle status
-  } // switch
-donewithstatus:
-  // Anyway, reception of status for header enables generation of next message header
-  // (plus already generated commands such as status for response header)
-  if (!fMsgNoResp && !isAborted()) {
-    // issue header now if not already issued above
-    if (!fOutgoingStarted) {
-      // interrupt status processing block here as issueHeader will do a start-of-message PDEBUGBLOCK
-      PDEBUGENDBLOCK("processStatus");
-      issueHeader(false);
-      PDEBUGBLOCKDESC("processStatus","finishing processing incoming SyncHdr Status");
-    }
-  }
-  // return handled status
-  return handled;
-} // TSyncClient::handleHeaderStatus
-
-
-// - start sync group (called in client or server roles)
-bool TSyncClient::processSyncStart(
-  SmlSyncPtr_t aSyncP,           // the Sync element
-  TStatusCommand &aStatusCommand, // pre-set 200 status, can be modified in case of errors
-  bool &aQueueForLater // will be set if command must be queued for later (re-)execution
-)
-{
-  if (fIncomingState!=psta_sync && fIncomingState!=psta_initsync) {
-    aStatusCommand.setStatusCode(403); // forbidden in this context
-    PDEBUGPRINTFX(DBG_ERROR,("Sync command not allowed outside of sync phase (-> 403)"));
-    AbortSession(400,true);
-    return false;
-  }
-  // just find appropriate database, must be already initialized for sync!
-  // determine local database to sync with (target)
-  TLocalEngineDS *datastoreP = findLocalDataStoreByURI(smlSrcTargLocURIToCharP(aSyncP->target));
-  if (!datastoreP) {
-    // no such local datastore
-    PDEBUGPRINTFX(DBG_ERROR,("Sync command for unknown DS locURI '%s' (-> 404)",smlSrcTargLocURIToCharP(aSyncP->target)));
-    aStatusCommand.setStatusCode(404); // not found
-    return false;
-  }
-  else {
-    // save the pointer, will e.g. be used to route subsequent server commands
-    fLocalSyncDatastoreP=datastoreP;
-    // let local datastore know (in server case, this is done in TSyncServer)
-    return fLocalSyncDatastoreP->engProcessSyncCmd(aSyncP,aStatusCommand,aQueueForLater);
-  }
-  return true;
-} // TSyncClient::processSyncStart
-
-
-
-#ifdef ENGINEINTERFACE_SUPPORT
-
-
-// Support for EngineModule common interface
-// =========================================
-
-
-/// @brief Get new session key to access details of this session
-appPointer TSyncClient::newSessionKey(TEngineInterface *aEngineInterfaceP)
-{
-  return new TClientParamsKey(aEngineInterfaceP,this);
-} // TSyncClient::newSessionKey
-
-
-// Client runtime settings key
-// ---------------------------
-
-// Constructor
-TClientParamsKey::TClientParamsKey(TEngineInterface *aEngineInterfaceP, TSyncClient *aClientSessionP) :
-  inherited(aEngineInterfaceP,aClientSessionP),
-  fClientSessionP(aClientSessionP)
-{
-} // TClientParamsKey::TClientParamsKey
-
-
-// - read connection URL
-static TSyError readConnectURI(
-  TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
-  appPointer aBuffer, memSize aBufSize, memSize &aValSize
-)
-{
-  TClientParamsKey *mykeyP = static_cast<TClientParamsKey *>(aStructFieldsKeyP);
-  return TStructFieldsKey::returnString(
-    mykeyP->fClientSessionP->getSendURI(),
-    aBuffer,aBufSize,aValSize
-  );
-} // readConnectURI
-
-
-// - read host part of connection URL
-static TSyError readConnectHost(
-  TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
-  appPointer aBuffer, memSize aBufSize, memSize &aValSize
-)
-{
-  TClientParamsKey *mykeyP = static_cast<TClientParamsKey *>(aStructFieldsKeyP);
-  string host;
-  splitURL(mykeyP->fClientSessionP->getSendURI(),NULL,&host,NULL,NULL,NULL);
-  return TStructFieldsKey::returnString(
-    host.c_str(),
-    aBuffer,aBufSize,aValSize
-  );
-} // readConnectHost
-
-
-// - read document part of connection URL
-static TSyError readConnectDoc(
-  TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
-  appPointer aBuffer, memSize aBufSize, memSize &aValSize
-)
-{
-  TClientParamsKey *mykeyP = static_cast<TClientParamsKey *>(aStructFieldsKeyP);
-  string doc;
-  splitURL(mykeyP->fClientSessionP->getSendURI(),NULL,NULL,&doc,NULL,NULL);
-  return TStructFieldsKey::returnString(
-    doc.c_str(),
-    aBuffer,aBufSize,aValSize
-  );
-} // readConnectDoc
-
-
-// - read content type string
-static TSyError readContentType(
-  TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
-  appPointer aBuffer, memSize aBufSize, memSize &aValSize
-)
-{
-  TClientParamsKey *mykeyP = static_cast<TClientParamsKey *>(aStructFieldsKeyP);
-  string contentType = SYNCML_MIME_TYPE;
-  mykeyP->fClientSessionP->addEncoding(contentType);
-  return TStructFieldsKey::returnString(
-    contentType.c_str(),
-    aBuffer,aBufSize,aValSize
-  );
-} // readContentType
-
-
-// - read local session ID
-static TSyError readLocalSessionID(
-  TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
-  appPointer aBuffer, memSize aBufSize, memSize &aValSize
-)
-{
-  TClientParamsKey *mykeyP = static_cast<TClientParamsKey *>(aStructFieldsKeyP);
-  return TStructFieldsKey::returnString(
-    mykeyP->fClientSessionP->getLocalSessionID(),
-    aBuffer,aBufSize,aValSize
-  );
-} // readLocalSessionID
-
-
-// - write (volatile, write-only) password for running this session
-// (for cases where we don't want to rely on binfile storage for sensitive password data)
-TSyError writeSessionPassword(
-  TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
-  cAppPointer aBuffer, memSize aValSize
-)
-{
-  TClientParamsKey *mykeyP = static_cast<TClientParamsKey *>(aStructFieldsKeyP);
-       mykeyP->fClientSessionP->setServerPassword((cAppCharP)aBuffer, aValSize);
-  return LOCERR_OK;
-} // writeSessionPassword
-
-
-#ifdef ENGINE_LIBRARY
-// - read display alert
-static TSyError readDisplayAlert(
-  TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
-  appPointer aBuffer, memSize aBufSize, memSize &aValSize
-)
-{
-  TClientEngineInterface *clientEngineP =
-    static_cast<TClientEngineInterface *>(aStructFieldsKeyP->getEngineInterface());
-  return TStructFieldsKey::returnString(
-    clientEngineP->fAlertMessage.c_str(),
-    aBuffer,aBufSize,aValSize
-  );
-} // readDisplayAlert
-#endif
-
-
-// accessor table for client params
-static const TStructFieldInfo ClientParamFieldInfos[] =
-{
-  // valName, valType, writable, fieldOffs, valSiz
-  { "connectURI", VALTYPE_TEXT, false, 0, 0, &readConnectURI, NULL },
-  { "connectHost", VALTYPE_TEXT, false, 0, 0, &readConnectHost, NULL },
-  { "connectDoc", VALTYPE_TEXT, false, 0, 0, &readConnectDoc, NULL },
-  { "contenttype", VALTYPE_TEXT, false, 0, 0, &readContentType, NULL },
-  { "localSessionID", VALTYPE_TEXT, false, 0, 0, &readLocalSessionID, NULL },
-  { "sessionPassword", VALTYPE_TEXT, true, 0, 0, NULL, &writeSessionPassword },
-  #ifdef ENGINE_LIBRARY
-  { "displayalert", VALTYPE_TEXT, false, 0, 0, &readDisplayAlert, NULL },
-  #endif
-};
-
-// get table describing the fields in the struct
-const TStructFieldInfo *TClientParamsKey::getFieldsTable(void)
-{
-  return ClientParamFieldInfos;
-} // TClientParamsKey::getFieldsTable
-
-sInt32 TClientParamsKey::numFields(void)
-{
-  return sizeof(ClientParamFieldInfos)/sizeof(TStructFieldInfo);
-} // TClientParamsKey::numFields
-
-// get actual struct base address
-uInt8P TClientParamsKey::getStructAddr(void)
-{
-  // prepared for accessing fields in client session object
-  return (uInt8P)fClientSessionP;
-} // TClientParamsKey::getStructAddr
-
-
-// open subkey by name (not by path!)
-TSyError TClientParamsKey::OpenSubKeyByName(
-  TSettingsKeyImpl *&aSettingsKeyP,
-  cAppCharP aName, stringSize aNameSize,
-  uInt16 aMode
-) {
-  #ifdef DBAPI_TUNNEL_SUPPORT
-  if (strucmp(aName,"tunnel",aNameSize)==0) {
-    // get tunnel datastore pointer
-    TLocalEngineDS *ds = fClientSessionP->getTunnelDS();
-    if (!ds) return LOCERR_WRONGUSAGE;
-    // opens current session's tunnel key
-    aSettingsKeyP = ds->newTunnelKey(fEngineInterfaceP);
-  }
-  else
-  #endif
-    return inherited::OpenSubKeyByName(aSettingsKeyP,aName,aNameSize,aMode);
-  // opened a key
-  return LOCERR_OK;
-} // TBinFileClientParamsKey::OpenSubKeyByName
-
-
-#endif // ENGINEINTERFACE_SUPPORT
-
-} // namespace sysync
-
-// eof
index 3cd67fe..e2ede1d 100755 (executable)
@@ -10,7 +10,7 @@
 
 #include "sysync.h"
 #include "syncclientbase.h"
-#include "syncclient.h"
+#include "syncagent.h"
 
 namespace sysync {
 
@@ -24,15 +24,15 @@ namespace sysync {
 #warning "using ENGINEINTERFACE_SUPPORT in old-style appbase-rooted environment. Should be converted to real engine usage later"
 
 // Engine factory function for non-Library case
-ENGINE_IF_CLASS *newEngine(void)
+ENGINE_IF_CLASS *newClientEngine(void)
 {
-  // For real engine based targets, newEngine must create a target-specific derivate
-  // of the engine, which then has a suitable newSyncAppBase() method to create the
+  // For real engine based targets, newClientEngine must create a target-specific derivate
+  // of the client engine, which then has a suitable newSyncAppBase() method to create the
   // appBase. For old-style environment, a generic TClientEngineInterface is ok, as this
   // in turn calls the global newSyncAppBase() which then returns the appropriate
   // target specific appBase.
   return new TClientEngineInterface;
-} // newEngine
+} // newClientEngine
 
 /// @brief returns a new application base.
 TSyncAppBase *TClientEngineInterface::newSyncAppBase(void)
@@ -113,6 +113,13 @@ TSyError TClientEngineInterface::OpenSessionInternal(SessionH &aNewSessionH, uIn
       // return the session pointer as handle
       aNewSessionH=(SessionH)clientBaseP->fClientSessionP;
     }
+    else {
+       // error: make sure it is deleted in case it was half-constructed
+       if (clientBaseP->fClientSessionP) {
+       delete clientBaseP->fClientSessionP;
+        clientBaseP->fClientSessionP = NULL;
+      }
+    }
     #else
     return LOCERR_NOTIMP; // tunnel not implemented
     #endif
@@ -167,7 +174,7 @@ TSyError TClientEngineInterface::OpenSessionKey(SessionH aSessionH, KeyH &aNewKe
   if (aSessionH != (SessionH)static_cast<TSyncClientBase *>(getSyncAppBase())->fClientSessionP)
     return LOCERR_WRONGUSAGE; // something wrong with that handle
   // get client session pointer
-  TSyncClient *clientSessionP = static_cast<TSyncClient *>((void *)aSessionH);
+  TSyncAgent *clientSessionP = static_cast<TSyncAgent *>((void *)aSessionH);
   // create settings key for the session
   aNewKeyH = (KeyH)clientSessionP->newSessionKey(this);
   // done
@@ -217,7 +224,7 @@ TSyError TClientEngineInterface::SessionStep(SessionH aSessionH, uInt16 &aStepCm
   if (aSessionH != (SessionH)clientBaseP->fClientSessionP)
     return LOCERR_WRONGUSAGE; // something wrong with that handle
   // get client session pointer
-  TSyncClient *clientSessionP = static_cast<TSyncClient *>((void *)aSessionH);
+  TSyncAgent *clientSessionP = static_cast<TSyncAgent *>((void *)aSessionH);
   #ifdef NON_FULLY_GRANULAR_ENGINE
   // pre-process setp command and generate pseudo-steps to empty progress event queue
   // preprocess general step codes
@@ -301,7 +308,7 @@ InstanceID_t TClientEngineInterface::getSmlInstanceOfSession(SessionH aSessionH)
   if (aSessionH != (SessionH)clientBaseP->fClientSessionP)
     return 0; // something wrong with session handle -> no SML instance
   // get client session pointer
-  TSyncClient *clientSessionP = static_cast<TSyncClient *>((void *)aSessionH);
+  TSyncAgent *clientSessionP = static_cast<TSyncAgent *>((void *)aSessionH);
   // return SML instance associated with that session
   return clientSessionP->getSmlWorkspaceID();
 } // TClientEngineInterface::getSmlInstanceOfSession
@@ -344,7 +351,8 @@ TSyncClientBase::TSyncClientBase() :
   TSyncAppBase(),
   fClientSessionP(NULL)
 {
-  // nop so far
+  // this is a client engine
+  fIsServer = false;
 } // TSyncClientBase::TSyncClientBase
 
 
@@ -367,10 +375,10 @@ TSyncClientBase::~TSyncClientBase()
 // - dispatches to session's StartMessage
 Ret_t TSyncClientBase::StartMessage(
   InstanceID_t aSmlWorkspaceID, // SyncML toolkit workspace instance ID
-  VoidPtr_t aUserData, // pointer to a TSyncClient descendant
+  VoidPtr_t aUserData, // pointer to a TSyncAgent descendant
   SmlSyncHdrPtr_t aContentP // SyncML tookit's decoded form of the <SyncHdr> element
 ) {
-  TSyncSession *sessionP = static_cast<TSyncClient *>(aUserData); // the client session
+  TSyncSession *sessionP = static_cast<TSyncAgent *>(aUserData); // the client session
   SYSYNC_TRY {
     // let session handle details of StartMessage callback
     return sessionP->StartMessage(aContentP);
@@ -412,12 +420,12 @@ localstatus TSyncClientBase::CreateSession(void)
   // remove any eventually existing old session first
   KillClientSession();
   // get config
-  //TClientConfig *configP = static_cast<TClientConfig *>(getSyncAppBase()->getRootConfig()->fAgentConfigP);
+  //TAgentConfig *configP = static_cast<TAgentConfig *>(getSyncAppBase()->getRootConfig()->fAgentConfigP);
   // create a new client session of appropriate type
   // - use current time as session ID (only for logging purposes)
   string s;
   LONGLONGTOSTR(s,(long long)(getSystemNowAs(TCTX_UTC)));
-  fClientSessionP = static_cast<TClientConfig *>(fConfigP->fAgentConfigP)->CreateClientSession(s.c_str());
+  fClientSessionP = static_cast<TAgentConfig *>(fConfigP->fAgentConfigP)->CreateClientSession(s.c_str());
   if (!fClientSessionP) return LOCERR_UNDEFINED;
   // check expiry here
   return appEnableStatus();
@@ -494,7 +502,7 @@ void TSyncClientBase::KillClientSession(localstatus aStatusCode)
     freeSmlInstance(fClientSessionP->getSmlWorkspaceID());
     fClientSessionP->setSmlWorkspaceID(0); // make sure it isn't set any more
     // delete session itself
-    TSyncClient *clientP = fClientSessionP;
+    TSyncAgent *clientP = fClientSessionP;
     fClientSessionP=NULL;
     delete clientP;
   }
index 52af01f..38d1165 100644 (file)
@@ -12,7 +12,7 @@
 // general includes (SyncML tookit, windows, Clib)
 #include "sysync.h"
 #include "syncappbase.h"
-#include "syncclient.h"
+#include "syncagent.h"
 
 
 
@@ -20,7 +20,7 @@ namespace sysync {
 
 // forward declarations
 class TSyncSession;
-class TSyncClient;
+class TSyncAgent;
 class TSyncClientBase;
 
 #ifdef ENGINEINTERFACE_SUPPORT
@@ -158,14 +158,14 @@ public:
   // - process message in the instance buffer
   localstatus processAnswer(void);
   // - get current session
-  TSyncClient *getClientSession(void) { return fClientSessionP; };
+  TSyncAgent *getClientSession(void) { return fClientSessionP; };
   // - remove and kill current session
   void KillClientSession(localstatus aStatusCode=0);
   // handlers for SyncML toolkit callbacks
   // - Start/End Message: identifies Session, and creates new or assigns existing session
   Ret_t StartMessage(
     InstanceID_t aSmlWorkspaceID, // SyncML toolkit workspace instance ID
-    VoidPtr_t aUserData, // pointer to a TSyncClient descendant
+    VoidPtr_t aUserData, // pointer to a TSyncAgent descendant
     SmlSyncHdrPtr_t aContentP // SyncML tookit's decoded form of the <SyncHdr> element
   );
   // Session handling
@@ -181,7 +181,7 @@ protected:
   virtual Ret_t HandleDecodingException(TSyncSession * /* aSessionP */, const char * /* aRoutine */, exception * /* aExceptionP */=NULL) { return SML_ERR_UNSPECIFIC; /* %%%% nop so far */ };
 private:
   // the current session
-  TSyncClient *fClientSessionP;
+  TSyncAgent *fClientSessionP;
 }; // TSyncClientBase
 
 
index d8ccee2..25f93f2 100755 (executable)
@@ -117,6 +117,13 @@ uInt32 TSmlCommand::getDbgMask(void)
 } // TSmlCommand::getDbgMask
 #endif
 
+
+TSyncAppBase *TSmlCommand::getSyncAppBase(void)
+{
+       return fSessionP ? fSessionP->getSyncAppBase() : NULL;  
+} // TSmlCommand::getSyncAppBase
+
+
 // get name of certain command
 const char *TSmlCommand::getNameOf(TSmlCommandTypes aCmdType)
 {
@@ -541,7 +548,7 @@ bool TSyncHeader::execute(void)
           // known version found
           // - set it only for server, client keeps preset version (will change it when
           //   a 513 is detected)
-          if (fSessionP->IsServerSession()) fSessionP->fSyncMLVersion=(TSyncMLVersions)ver;
+          if (IS_SERVER) fSessionP->fSyncMLVersion=(TSyncMLVersions)ver;
           break;
         }
       }
@@ -552,7 +559,7 @@ bool TSyncHeader::execute(void)
         ver<minver ||
         ver>=numSyncMLVersions ||
         ver>maxver ||
-        (fSessionP->IsServerSession() && fSessionP->fSyncMLVersion!=syncml_vers_unknown && fSessionP->fSyncMLVersion!=ver)
+        (IS_SERVER && fSessionP->fSyncMLVersion!=syncml_vers_unknown && fSessionP->fSyncMLVersion!=ver)
       ) {
         // unsupported protocol version (or different than in first message): Status 513
         // - Make sure we have a valid SyncML version
@@ -2827,7 +2834,7 @@ TMapCommand::TMapCommand(
 } // TMapCommand::TMapCommand
 
 
-#ifndef SYSYNC_CLIENT
+#ifdef SYSYNC_SERVER
 // Server only receives Maps
 
 // analyze command (but do not yet execute)
@@ -2888,8 +2895,10 @@ bool TMapCommand::execute(void)
   return !queueforlater;
 } // TMapCommand::execute
 
+#endif
+
+#ifdef SYSYNC_CLIENT
 
-#else
 // Client only sends maps
 
 // constructor for sending MAP Command
@@ -3032,7 +3041,7 @@ void TMapCommand::generateMapItems(void)
 {
   // let datastore add Map items (eventually none)
   fInProgress = !(
-    fLocalDataStoreP->engGenerateMapItems(this)
+    fLocalDataStoreP->engGenerateMapItems(this,NULL)
   );
 } // TMapCommand::generateMapItems
 
@@ -4281,7 +4290,7 @@ TDevInfPutCommand::TDevInfPutCommand(
   fPutElementP->meta=newMetaType(metatype.c_str());
   // - add local DevInf item to result
   //   Note: PUT of server only returns alerted datastore's devInf
-  addItem(fSessionP->getLocalDevInfItem(fSessionP->IsServerSession(),false));
+  addItem(fSessionP->getLocalDevInfItem(IS_SERVER,false));
 } // TDevInfPutCommand::TDevInfPutCommand
 
 
index b67be4f..578cc15 100755 (executable)
@@ -63,6 +63,7 @@ typedef enum {
 // forward
 class TStatusCommand;
 class TSyncSession;
+class TSyncAppBase;
 
 
 // abstract base command class
@@ -82,6 +83,8 @@ public:
   TDebugLogger *getDbgLogger(void);
   uInt32 getDbgMask(void);
   #endif
+  // - get session owner (dispatcher/clientbase)
+  TSyncAppBase *getSyncAppBase(void);  
   #ifndef USE_SML_EVALUATION
   // - get (approximated) message size required for sending it
   virtual uInt32 messageSize(void);
@@ -496,11 +499,12 @@ public:
     uInt32 aMsgID,                    // the Message ID of the command
     SmlMapPtr_t aMapElementP        // associated syncml protocol element
   );
-  #ifndef SYSYNC_CLIENT
+  #ifdef SYSYNC_SERVER
   // Server implementation
   virtual bool analyze(TPackageStates aPackageState);
   virtual bool execute(void);
-  #else
+  #endif // SYSYNC_SERVER
+  #ifdef SYSYNC_CLIENT
   // Client implementation
   // - constructor for sending MAP
   TMapCommand(
@@ -525,7 +529,7 @@ public:
   // - handle status received for previously issued command
   //   returns true if done, false if command must be kept in the status queue
   virtual bool handleStatus(TStatusCommand *aStatusCmdP);
-  #endif
+  #endif // SYSYNC_CLIENT
 protected:
   virtual void FreeSmlElement(void);
   SmlMapPtr_t fMapElementP;
index 50fd999..36eed9e 100755 (executable)
@@ -130,6 +130,13 @@ uInt32 TSyncDataStore::getDbgMask(void)
 #endif
 
 
+TSyncAppBase *TSyncDataStore::getSyncAppBase(void)
+{
+       return fSessionP ? fSessionP->getSyncAppBase() : NULL;  
+} // TSyncDataStore::getSyncAppBase
+
+
+
 // check if this datastore is accessible with given URI
 // NOTE: URI might include path elements or CGI params that are
 // access options to the database; derived classes might
index d39fc8c..b009d39 100755 (executable)
@@ -23,6 +23,7 @@ namespace sysync {
 // forward
 class TSyncItemType;
 class TSyncSession;
+class TSyncAppBase;
 
 
 class TSyncDataStore
@@ -90,10 +91,13 @@ public:
   GZones *getSessionZones(void);
   // - return pure relative (item) URI (removes absolute part or ./ prefix)
   virtual const char *DatastoreRelativeURI(const char *aURI) = 0;
+  // - get debug mask/logger
   #ifdef SYDEBUG
   TDebugLogger *getDbgLogger(void);
   uInt32 getDbgMask(void);
   #endif
+  // - get session owner (dispatcher/clientbase)
+  TSyncAppBase *getSyncAppBase(void);  
 protected:
   // obtain new datastore info, returns NULL if none available
   virtual SmlDevInfDatastorePtr_t newDevInfDatastore(bool /* aAsServer */, bool /* aWithoutCTCapProps */) { return NULL; } // no description in base class
@@ -119,10 +123,6 @@ public:
   TSyncItemType *fTxPrefItemTypeP;
   TSyncItemTypePContainer fTxItemTypes;
 protected:
-  /*
-  // devInf <DataStore> representation
-  SmlDevInfDatastorePtr_t fDataStoreDevInfP;
-  */
   // session
   TSyncSession *fSessionP;
   // common (session) Sync capabilities
index c3ef1d1..36d57c2 100755 (executable)
@@ -93,6 +93,13 @@ uInt32 TSyncItem::getDbgMask(void)
 } // TSyncItem::getDbgMask
 #endif
 
+
+TSyncAppBase *TSyncItem::getSyncAppBase(void)
+{
+       return getSession() ? getSession()->getSyncAppBase() : NULL;    
+} // TSyncItem::getSyncAppBase
+
+
 /* end of TSyncItem implementation */
 
 // eof
index a8d359b..6a30213 100755 (executable)
@@ -54,6 +54,7 @@ extern const char * const compareRelevanceNames[numEQmodes];
 
 // forward
 class TLocalEngineDS;
+class TSyncAppBase;
 
 class TSyncItem
 {
@@ -147,6 +148,8 @@ public:
   TDebugLogger *getDbgLogger(void);
   uInt32 getDbgMask(void);
   #endif
+  // - get session owner (dispatcher/clientbase)
+  TSyncAppBase *getSyncAppBase(void);  
 protected:
   // operation to be performed with this item at its destination
   TSyncOperation fSyncOp;
diff --git a/src/synthesis/src/sysync/syncserver.cpp b/src/synthesis/src/sysync/syncserver.cpp
deleted file mode 100755 (executable)
index 5cf6c98..0000000
+++ /dev/null
@@ -1,1679 +0,0 @@
-/* 
- *  File:         SyncServer.cpp
- *
- *  Author:                      Lukas Zeller (luz@synthesis.ch)
- *
- *  TSyncServer
- *    <describe here>
- *
- *  Copyright (c) 2001-2009 by Synthesis AG (www.synthesis.ch)
- *
- *  2001-05-07 : luz : Created
- *
- */
-
-// includes
-#include <errno.h>
-#include "prefix_file.h"
-
-#include "sysync.h"
-#include "syncserver.h"
-
-#ifdef SYSYNC_CLIENT
-  #error "SYSYNC_CLIENT must NOT be defined when compiling syncserver.cpp"
-#endif
-
-
-// %%% define to prevent GET command sent to Client when
-//     package #1 did not contain DEVINF
-//#define NO_DEVINF_GET 1
-
-// %%% define to combine SYNC and MAP as one response package
-// %%%%%%% probably useless and totally wrong, but trying to
-// %%%%%%% get 9210 to work.
-//#define COMBINE_SYNCANDMAP
-
-// define to include a 222 alert in every response to a message
-// that does not include the <Final/> flag (otherwise, 222 Alert
-// will only be generated when no other command is to be sent back)
-//#define ALWAYS_CONTINUE222 1
-
-using namespace sysync; 
-
-
-namespace sysync {
-
-// Support for SySync Diagnostic Tool
-#ifdef SYSYNC_TOOL
-
-
-// test login into database
-int testLogin(int argc, const char *argv[])
-{
-  if (argc<0) {
-    // help requested
-    CONSOLEPRINTF(("  login [<username> <password>] [<deviceid>]"));
-    CONSOLEPRINTF(("    test login to database with syncml user/password and optional deviceid"));
-    return EXIT_SUCCESS;
-  }
-
-  TSyncSession *sessionP = NULL;
-  const char *username = NULL;
-  const char *password = NULL;
-  const char *deviceid = "sysytool_test";
-
-  // check for argument
-  if (argc<2) {
-    // no user/password, test anonymous login
-       if (argc>0) deviceid = argv[0];
-  }
-  else {
-    // login with user/password
-    username = argv[0];
-    password = argv[1];
-    if (argc>2) {
-      // explicit device ID
-      deviceid = argv[2];
-    }
-  }
-    
-  // get session to work with
-  sessionP =
-    static_cast<TSyncSessionDispatch *>(getSyncAppBase())->getSySyToolSession();
-
-  bool authok = false;
-  
-  // try login
-  if (username) {
-    // real login with user and password
-    authok = sessionP->SessionLogin(username, password, sectyp_clearpass, deviceid);
-  }
-  else {
-    // anonymous - do a "login" with empty credentials
-    authok = sessionP->SessionLogin("anonymous", NULL, sectyp_anonymous, deviceid);
-  }
-  
-  if (authok) {
-    CONSOLEPRINTF(("+++++ Successfully authorized"));
-  }
-  else {
-    CONSOLEPRINTF(("----- Authorisation failed"));
-  }
-  
-  return authok;
-} // testLogin
-
-
-// convert user data into internal format and back
-int convertData(int argc, const char *argv[])
-{
-  if (argc<0) {
-    // help requested
-    CONSOLEPRINTF(("  convert <datastore name> <data file, vcard or vcalendar etc.> [<explicit input type>] [<output type>]"));
-    CONSOLEPRINTF(("    Convert data to internal format of specified datastore and back"));
-    return EXIT_SUCCESS;
-  }
-
-  TSyncSession *sessionP = NULL;
-  const char *datastore = NULL;
-  const char *rawfilename = NULL;
-  const char *inputtype = NULL;
-  const char *outputtype = NULL;
-
-  // check for argument
-  if (argc<2) {
-       CONSOLEPRINTF(("required datatype name and raw file name arguments"));
-       return EXIT_FAILURE;
-  }
-  datastore = argv[0];
-  rawfilename = argv[1];
-  if (argc>=3) {
-    // third arg is explicit input type
-    inputtype=argv[2];
-  }
-  outputtype=inputtype; // default to input type
-  if (argc>=4) {
-    // fourth arg is explicit output type
-    outputtype=argv[3];
-  }
-  
-  // get session to work with
-  sessionP =
-    static_cast<TSyncSessionDispatch *>(getSyncAppBase())->getSySyToolSession();
-  // configure session
-  sessionP->fRemoteCanHandleUTC = true; // run generator and parser in UTC enabled mode
-  
-  
-  // switch mimimal debugging on
-  sessionP->getDbgLogger()->setMask(sessionP->getDbgLogger()->getMask() | (DBG_PARSE+DBG_GEN));
-    
-  // find datastore
-  TLocalEngineDS *datastoreP = sessionP->findLocalDataStore(datastore);
-  TSyncItemType *inputtypeP = NULL;
-  TSyncItemType *outputtypeP = NULL;
-  if (!datastoreP) {
-       CONSOLEPRINTF(("datastore type '%s' not found",datastore));
-       return EXIT_FAILURE;
-  }
-
-  // find input type
-  if (inputtype) {
-    // search in datastore
-    inputtypeP=datastoreP->getReceiveType(inputtype,NULL);
-  }
-  else {
-    // use preferred rx type
-    inputtypeP=datastoreP->getPreferredRxItemType();
-  }
-  if (!inputtypeP) {
-       CONSOLEPRINTF(("input type not found"));
-       return EXIT_FAILURE;
-  }
-  // find output type
-  if (outputtype) {
-    // search in datastore
-    outputtypeP=datastoreP->getSendType(outputtype,NULL);
-  }
-  else {
-    // use preferred rx type
-    outputtypeP=datastoreP->getPreferredTxItemType();
-  }
-  if (!outputtypeP) {
-       CONSOLEPRINTF(("output type not found"));
-       return EXIT_FAILURE;
-  }
-  // prepare type usage
-  if (inputtypeP==outputtypeP)
-    inputtypeP->initDataTypeUse(datastoreP, true, true);
-  else {
-    inputtypeP->initDataTypeUse(datastoreP, false, true);
-    outputtypeP->initDataTypeUse(datastoreP, true, false);
-  }    
-
-  // now open file and read data item
-  FILE *infile;
-  size_t insize=0;
-  uInt8 *databuffer;
-  
-  infile = fopen(rawfilename,"rb");
-  if (!infile) {
-       CONSOLEPRINTF(("Cannot open input file '%s' (%d)",rawfilename,errno));
-       return EXIT_FAILURE;    
-  }
-  // - get size of file
-  fseek(infile,0,SEEK_END);
-  insize=ftell(infile);
-  fseek(infile,0,SEEK_SET);
-  // - create buffer of appropriate size
-  databuffer = new uInt8[insize];
-  if (!databuffer) {
-       CONSOLEPRINTF(("Not enough memory to read input file '%s' (%d)",rawfilename,errno));
-       return EXIT_FAILURE;    
-  }  
-  // - read data
-  if (fread(databuffer,1,insize,infile)<insize) {
-       CONSOLEPRINTF(("Error reading input file '%s' (%d)",rawfilename,errno));
-       return EXIT_FAILURE;    
-  }
-  CONSOLEPRINTF(("\nNow converting into internal field representation\n"));
-  // create a sml item
-  TStatusCommand statusCmd(sessionP);
-  SmlItemPtr_t smlitemP = newItem();
-  smlitemP->data=newPCDataStringX(databuffer,true,insize);
-  delete[] databuffer;
-  // create and fill a Sync item
-  TSyncItem *syncitemP = inputtypeP->newSyncItem(
-    smlitemP, // SyncML toolkit item Data to be converted into SyncItem
-    sop_replace, // the operation to be performed with this item
-    fmt_chr,    // assume default (char) format
-    inputtypeP, // target myself
-    datastoreP, // local datastore
-    statusCmd // status command that might be modified in case of error
-  );
-  // forget SyncML version
-  smlFreeItemPtr(smlitemP);
-  if (!syncitemP) {
-       CONSOLEPRINTF(("Error converting input file to internal format (SyncML status code=%hd)",statusCmd.getStatusCode()));
-       return EXIT_FAILURE;
-  }
-
-  CONSOLEPRINTF(("\nNow copying item and convert back to transport format\n"));
-
-  // make new for output type
-  TSyncItem *outsyncitemP = outputtypeP->newSyncItem(
-    outputtypeP, // target myself
-    datastoreP  // local datastore
-  );
-  // copy data
-  outsyncitemP->replaceDataFrom(*syncitemP);
-  delete syncitemP;
-  // convert back
-  smlitemP=outputtypeP->newSmlItem(
-    outsyncitemP,   // the syncitem to be represented as SyncML
-    datastoreP // local datastore
-  );
-  if (!syncitemP) {
-       CONSOLEPRINTF(("Could not convert back item data"));
-       return EXIT_FAILURE;
-  }
-  
-  // forget converted back item
-  smlFreeItemPtr(smlitemP);
-  
-  return EXIT_SUCCESS;
-} // convertData
-
-#endif // SYSYNC_TOOL
-
-
-
-/*
- * Implementation of TServerConfig
- */
-
-// config constructor
-TServerConfig::TServerConfig(const char *aElementName, TConfigElement *aParentElementP) :
-  TSessionConfig(aElementName,aParentElementP)
-{
-  clear();
-} // TServerConfig::TServerConfig
-
-
-// config destructor
-TServerConfig::~TServerConfig()
-{
-} // TServerConfig::~TServerConfig
-
-
-// init defaults
-void TServerConfig::clear(void)
-{
-  // init defaults
-  fRequestedAuth=auth_md5;
-  fRequiredAuth=auth_md5;
-  fAutoNonce=true;
-  fConstantNonce.erase();
-  fExternalURL.erase();
-  fMaxGUIDSizeSent=32; // reasonable size, but prevent braindamaged Exchange-size IDs to be sent
-  // clear inherited  
-  inherited::clear();
-  // modify timeout after inherited sets it
-  fSessionTimeout=DEFAULT_SERVERSESSIONTIMEOUT;
-} // TServerConfig::clear
-
-
-// server config element parsing
-bool TServerConfig::localStartElement(const char *aElementName, const char **aAttributes, sInt32 aLine)
-{
-  // checking the elements
-  if (strucmp(aElementName,"requestedauth")==0)
-               expectEnum(sizeof(fRequestedAuth),&fRequestedAuth,authTypeNames,numAuthTypes);
-  else if (strucmp(aElementName,"requiredauth")==0)
-               expectEnum(sizeof(fRequiredAuth),&fRequiredAuth,authTypeNames,numAuthTypes);
-  // here to maintain compatibility with old pre 1.0.5.3 config files
-  else if (strucmp(aElementName,"reqiredauth")==0)
-               expectEnum(sizeof(fRequiredAuth),&fRequiredAuth,authTypeNames,numAuthTypes);
-  else if (strucmp(aElementName,"autononce")==0)
-               expectBool(fAutoNonce);
-  else if (strucmp(aElementName,"constantnonce")==0)
-               expectString(fConstantNonce);
-  else if (strucmp(aElementName,"externalurl")==0)
-               expectString(fExternalURL);
-  else if (strucmp(aElementName,"maxguidsizesent")==0)
-    expectUInt16(fMaxGUIDSizeSent);
-  // - none known here
-  else
-    return inherited::localStartElement(aElementName,aAttributes,aLine);
-  // ok
-  return true;
-} // TServerConfig::localStartElement
-
-
-// resolve
-void TServerConfig::localResolve(bool aLastPass)
-{
-  // check
-  if (aLastPass) {
-    if (!fAutoNonce && fConstantNonce.empty())
-      ReportError(false,"Warning: 'constantnonce' should be defined when 'autononce' is not set");
-  }
-  // resolve inherited  
-  inherited::localResolve(aLastPass);
-} // TServerConfig::localResolve
-
-
-/*
- * Implementation of TSyncServer
- */
-
-
-TSyncServer::TSyncServer(
-  TSyncAppBase *aAppBaseP,
-  TSyncSessionHandle *aSessionHandleP,
-  const char *aSessionID // a session ID
-) :
-  TSyncSession(aAppBaseP,aSessionID)  
-  #ifdef ENGINEINTERFACE_SUPPORT
-  ,fEngineState(ses_needdata)
-  #endif
-{
-  // init answer buffer
-  fBufferedAnswer=NULL;
-  fBufferedAnswerSize=0;  
-  // reset data counts
-  fIncomingBytes=0;
-  fOutgoingBytes=0;
-  // init own stuff
-  InternalResetSession();
-  // save session handle
-  fSessionHandleP = aSessionHandleP; // link to handle
-  // create all locally available datastores from config
-  TServerConfig *configP = static_cast<TServerConfig *>(aAppBaseP->getRootConfig()->fAgentConfigP);
-  TLocalDSList::iterator pos;
-  for (pos=configP->fDatastores.begin(); pos!=configP->fDatastores.end(); pos++) {
-    // create the datastore
-    addLocalDataStore(*pos);
-  }   
-} // TSyncServer::TSyncServer
-
-
-TSyncServer::~TSyncServer()
-{
-  // forget any buffered answers
-  bufferAnswer(NULL,0);
-  // reset session
-  InternalResetSession();
-  // show session data transfer
-  PDEBUGPRINTFX(DBG_HOT,(
-    "Session data transfer statistics: incoming bytes=%ld, outgoing bytes=%ld",
-    fIncomingBytes,
-    fOutgoingBytes
-  ));
-  // DO NOT remove session from dispatcher here,
-  //   this is the task of the dispatcher itself!
-  CONSOLEPRINTF(("Terminated SyncML session (server id=%s)\n",getLocalSessionID()));
-  // show end of session in global level
-  POBJDEBUGPRINTFX(getSyncAppBase(),DBG_HOT,(
-    "TSyncServer::~TSyncServer: Deleted SyncML session (local session id=%s)",
-    getLocalSessionID()
-  ));
-} // TSyncServer::~TSyncServer
-
-
-// Reset session
-void TSyncServer::InternalResetSession(void)
-{
-  // %%% remove this as soon as Server is 1.1 compliant
-  //fSyncMLVersion=syncml_vers_1_0; // only accepts 1.0 for now %%%%
-} // TSyncServer::InternalResetSession
-
-
-// Virtual version
-void TSyncServer::ResetSession(void)
-{
-  // let ancestor do its stuff
-  TSyncSession::ResetSession();
-  // do my own stuff
-  InternalResetSession();
-} // TSyncServer::ResetSession
-
-
-// called when incoming SyncHdr fails to execute
-bool TSyncServer::syncHdrFailure(bool aTryAgain)
-{
-  if (!aTryAgain) {
-    // not already retried executing
-    // special case: header failed to execute, this means that session must be reset
-    // - Reset session (aborts all DB transactions etc.)
-    ResetSession();
-    PDEBUGPRINTFX(DBG_ERROR,("Trying to recover SyncHdr failure: =========== Session restarted ====================="));
-    // - now all session infos are gone except this command which is owned by
-    //   this function alone. Execute it again.
-    aTryAgain=true;
-  }
-  else {
-    // special special case: header failed to execute the second time
-    DEBUGPRINTFX(DBG_ERROR,("Fatal internal problem, SyncHdr execution failed twice"));
-    aTryAgain=false; // just to make sure
-    SYSYNC_THROW((TSyncException("SyncHdr fatal execution problem")));
-  }
-  return aTryAgain;
-} // TSyncServer::syncHdrFailure
-
-
-// undefine these only for tests. Introduced to find problem with T68i
-#define USE_RESPURI
-#define RESPURI_ONLY_WHEN_NEEDED
-
-// create a RespURI string. If none needed, return NULL
-SmlPcdataPtr_t TSyncServer::newResponseURIForRemote(void)
-{
-  // do it in a transport-independent way, therefore let dispatcher do it
-  string respURI; // empty string
-  #ifdef USE_RESPURI
-  getSyncAppBase()->generateRespURI(
-    respURI,  // remains unaffected if no RespURI could be calculated
-    fInitialLocalURI.c_str(), // initial URI used by remote to send first message
-    fLocalSessionID.c_str()  // server generated unique session ID
-  );
-  // Omit RespURI if local URI as seen by client is identical
-  #ifdef RESPURI_ONLY_WHEN_NEEDED
-  // %%% attempt to make T68i work
-  if (respURI==fLocalURI) {
-    respURI.erase();
-    DEBUGPRINTFX(DBG_SESSION,(
-      "Generated RespURI and sourceLocURI are equal (%s)-> RespURI omitted",
-      fLocalURI.c_str()
-    ));
-  }
-  #endif
-  #endif
-  // Note: returns NULL if respURI is empty string
-  return newPCDataOptString(respURI.c_str());
-} // newResponseURIForRemote
-
-
-// called after successful decoding of an incoming message
-bool TSyncServer::MessageStarted(SmlSyncHdrPtr_t aContentP, TStatusCommand &aStatusCommand, bool aBad)
-{
-  Ret_t err=SML_ERR_OK;
-
-  // message not authorized by default
-  fMessageAuthorized=false;
-  
-  // Get information from SyncHdr which is needed for answers
-  // - session ID to be used for responses
-  fSynchdrSessionID=smlPCDataToCharP(aContentP->sessionID);
-  // - local URI (as seen by remote client)
-  fLocalURI=smlSrcTargLocURIToCharP(aContentP->target);
-  fLocalName=smlSrcTargLocNameToCharP(aContentP->target);
-  // - also remember URI to which first message was sent
-  // %%% note: incoming ID is not a criteria, because it might be >1 due to
-  //     client retrying something which it thinks is for the same session
-  //if (fIncomingMsgID==1) {
-  if (fOutgoingMsgID==0) {
-    // this is the first message, remember first URI used to contact server
-    // (or set preconfigured string from <externalurl>)
-    if (getServerConfig()->fExternalURL.empty())
-      fInitialLocalURI=fLocalURI; // use what client sends to us
-    else
-      fInitialLocalURI=getServerConfig()->fExternalURL; // use preconfigured URL
-    // Many clients, including SCTS send the second login attempt with a MsgID>1,
-    // and depending on how they handle RespURI, they might get a new session for that
-    // -> so, just handle the case that a new session does not start with MsgID=1
-    if (fIncomingMsgID>1) {
-      PDEBUGPRINTFX(DBG_ERROR,(
-        "New session gets first message with MsgID=%ld (should be 1). Might be due to retries, adjusting OutgoingID as well",
-        fIncomingMsgID
-      ));
-      fOutgoingMsgID=fIncomingMsgID-1; // to make it match what client expects
-    }
-  }
-  // - remote URI
-  fRemoteURI=smlSrcTargLocURIToCharP(aContentP->source);
-  fRemoteName=smlSrcTargLocNameToCharP(aContentP->source);
-  // - RespURI (remote URI to respond to, if different from source)
-  fRespondURI.erase();
-  if (aContentP->respURI) {
-    fRespondURI=smlPCDataToCharP(aContentP->respURI);
-    DEBUGPRINTFX(DBG_PROTO,("RespURI specified = '%s'",fRespondURI.c_str()));
-  }
-  if (fRespondURI==fRemoteURI) fRespondURI.erase(); // if specified but equal to remote: act as if not specified
-  // More checking if header was ok
-  if (aBad) {
-    // bad header, only do what is needed to get a status back to client
-    fSessionAuthorized=false;
-    fIncomingState=psta_init;
-    fOutgoingState=psta_init;
-    fNewOutgoingPackage=true;
-    // issue header to make sure status can be sent back to client
-    if (!fMsgNoResp)
-      issueHeader(false); // issue header, do not prevent responses
-  }
-  else {  
-    // check busy (or expired) case
-    if (serverBusy()) {
-      #ifdef APP_CAN_EXPIRE
-       if (getSyncAppBase()->fAppExpiryStatus!=LOCERR_OK) {
-               aStatusCommand.setStatusCode(511); // server failure (expired)
-               aStatusCommand.addItemString("License expired or invalid");
-        PDEBUGPRINTFX(DBG_ERROR,("License expired or invalid - Please contact Synthesis AG to obtain license"));
-      }
-       else
-       #endif
-       {
-       aStatusCommand.setStatusCode(101); // busy
-      }
-      issueHeader(false); // issue header, do not prevent responses
-      AbortSession(0,true); // silently discard rest of commands
-      return false; // header not ok
-    }  
-    // now check what state we are in
-    if (fIncomingState==psta_idle) {  
-      // Initialize
-      // - session-wide authorization not yet there
-      fSessionAuthorized=false;
-      fMapSeen=false;
-      // - session has started, we are processing first incoming
-      //   package and generating first outgoing package
-      //   (init, eventually changed to combined init/sync by <sync> in this package)
-      fIncomingState=psta_init;
-      fOutgoingState=psta_init;
-      fNewOutgoingPackage=true;
-    }
-    // authorization check
-    if (fIncomingState>=psta_init) {
-      // now check authorization
-      if (!fSessionAuthorized) {    
-        // started, but not yet permanently authorized
-        fMessageAuthorized=checkCredentials(
-          smlSrcTargLocNameToCharP(aContentP->source), // user name in clear text according to SyncML 1.0.1
-          aContentP->cred, // actual credentials
-          aStatusCommand
-        );
-        // NOTE: aStatusCommand has now the appropriate status and chal (set by checkCredentials())
-        // if credentials do not match, stop processing commands (but stay with the session)
-        if (!fMessageAuthorized) {
-          AbortCommandProcessing(aStatusCommand.getStatusCode());  
-          PDEBUGPRINTFX(DBG_PROTO,("Authorization failed with status %hd, stop command processing",aStatusCommand.getStatusCode()));
-        }
-        // now determine if authorization is permanent or not
-        if (fMessageAuthorized) {
-          fAuthFailures=0; // reset count
-          if (messageAuthRequired()) {
-            // each message needs autorisation again (or no auth at all)
-            // - 200 ok, next message needs authorization again (or again: none)
-            fSessionAuthorized=false; // no permanent authorization
-            aStatusCommand.setStatusCode(200);
-            // - add challenge for next auth (different nonce)
-            aStatusCommand.setChallenge(newSessionChallenge());
-            PDEBUGPRINTFX(DBG_PROTO,("Authorization ok, but required again for subsequent messages: 200 + chal"));
-          }
-          else {
-            // entire session is authorized
-            fSessionAuthorized=true; // permanent authorization
-            // - 212 authentication accepted (or 200 if none is reqired at all)          
-            aStatusCommand.setStatusCode(requestedAuthType()==auth_none ? 200 : 212);
-            // - add challenge for next auth (in next session, but as we support carry
-            //   forward via using sessionID, we need to send one here as well)
-            aStatusCommand.setChallenge(newSessionChallenge());
-            PDEBUGPRINTFX(DBG_PROTO,("Authorization accepted: 212"));
-          }
-        }
-      } // authorisation check
-      else {
-        // already authorized from previous message
-        PDEBUGPRINTFX(DBG_PROTO,("Authorization ok from previous request: 200"));
-        fMessageAuthorized=true;
-      }
-      // Start response message AFTER auth check, to allow issueHeader
-      // to check auth state and customize the header accordingly (no
-      // RespURI for failed auth for example)
-      if (!fMsgNoResp) {
-        issueHeader(false); // issue header, do not prevent responses
-      }
-    } // if started at least
-  } // if not aBad
-  // return startmessage status
-  // debug info
-  #ifdef SYDEBUG
-  if (PDEBUGMASK & DBG_SESSION) {
-    PDEBUGPRINTFX(DBG_SESSION,(
-      "---> MessageStarted, Message %sauthorized, incoming state='%s', outgoing state='%s'",
-      fMessageAuthorized ? "" : "NOT ",
-      PackageStateNames[fIncomingState],
-      PackageStateNames[fOutgoingState]
-    ));
-       TLocalDataStorePContainer::iterator pos;
-    for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
-      // Show state of local datastores
-      PDEBUGPRINTFX(DBG_SESSION,(
-        "Local Datastore '%s': State=%s, %s%s sync, %s%s",
-        (*pos)->getName(),
-        (*pos)->getDSStateName(),
-        (*pos)->isResuming() ? "RESUMED " : "",
-        (*pos)->fSlowSync ? "SLOW" : "normal",
-        SyncModeDescriptions[(*pos)->fSyncMode],
-        (*pos)->fServerAlerted ? ", Server-Alerted" : ""
-      ));
-    }
-  }
-  #endif
-  // final check for too many auth failures
-  if (!fMessageAuthorized) {
-    #ifdef NO_NONCE_OLD_BEAHVIOUR
-    AbortSession(aStatusCommand.getStatusCode(),true); // local error
-    // avoid special treatment of non-authorized message, we have aborted, this is enough
-    fMessageAuthorized=true;
-    #else
-    // Unsuccessful auth, count this
-    fAuthFailures++;
-    PDEBUGPRINTFX(DBG_ERROR,(
-      "Authorization failed %hd. time, (any reason), sending status %hd",
-      fAuthFailures,
-      aStatusCommand.getStatusCode()
-    ));
-    // - abort session after too many auth failures
-    if (fAuthFailures>=MAX_AUTH_ATTEMPTS) {
-      PDEBUGPRINTFX(DBG_ERROR,("Too many (>=%hd) failures, aborting session",MAX_AUTH_ATTEMPTS));
-      AbortSession(400,true);
-    }
-    #endif        
-  }  
-  // returns false on BAD header (but true on wrong/bad/missing cred)
-  return true;
-} // TSyncServer::MessageStarted
-
-
-void TSyncServer::MessageEnded(bool aIncomingFinal)
-{
-  bool alldone;
-  TPackageStates newoutgoingstate,newincomingstate;
-  TLocalDataStorePContainer::iterator pos;
-  bool allFromClientOnly=false;
-  
-  // Incoming message ends here - what is following are commands initiated by the server
-  // not directly related to a incoming command.
-  PDEBUGENDBLOCK("SyncML_Incoming");
-  // assume that outgoing package is NOT finished, so outgoing state does not change
-  newoutgoingstate=fOutgoingState;
-  // new incoming state depends on whether this message is final or not
-  if ((aIncomingFinal || (fIncomingState==psta_supplement)) && fMessageAuthorized) {
-    // Note: in supplement state, incoming final is not relevant (may or may not be present, there is
-    //       no next phase anyway 
-    // find out if this is a shortened session (no map phase) due to
-    // from-client-only in all datastores
-    if (!fCompleteFromClientOnly) {
-      allFromClientOnly=true;
-      for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
-        // check sync modes
-        if ((*pos)->isActive() && (*pos)->getSyncMode()!=smo_fromclient) {
-          allFromClientOnly=false;
-          break;
-        }
-      }
-    }
-    // determine what package comes next
-    switch (fIncomingState) {
-      case psta_init :
-        newincomingstate=psta_sync;
-        break;
-      case psta_sync :
-      case psta_initsync :
-        // end of sync phase means end of session if all datastores are in from-client-only mode
-        if (allFromClientOnly) {
-          PDEBUGPRINTFX(DBG_PROTO+DBG_HOT,("All datastores in from-client-only mode: don't expect map phase from client"));
-          newincomingstate=psta_supplement;
-        }
-        else {
-          newincomingstate=psta_map;
-        }
-        break;
-      case psta_map :
-      case psta_supplement : // supplement state does not exit automatically
-        // after map, eventually some supplement status/alert 222 messages are needed from client
-        newincomingstate=psta_supplement;
-        break;
-      default:
-        // by default, back to idle
-        newincomingstate=psta_idle;
-        break;
-    } // switch
-  }
-  else {
-    // not final or not authorized: no change in state
-    newincomingstate=fIncomingState;
-  }
-  // show status before processing
-  PDEBUGPRINTFX(DBG_SESSION,(
-    "---> MessageEnded starts   : old incoming state='%s', old outgoing state='%s', %sNeedToAnswer",
-    PackageStateNames[fIncomingState],
-    PackageStateNames[fOutgoingState],
-    fNeedToAnswer ? "" : "NO "
-  ));
-  // process
-  if (isAborted()) {
-    // actual aborting has already taken place
-    PDEBUGPRINTFX(DBG_ERROR,("***** Session is flagged 'aborted' -> MessageEnded ends package and session"));
-    newoutgoingstate=psta_idle;
-    newincomingstate=psta_idle;
-    fInProgress=false;
-  } // if aborted
-  else if (isSuspending()) {
-    // only flagged for suspend - but datastores are not yet aborted, do it now
-    AbortSession(514,true,getAbortReasonStatus());
-    PDEBUGPRINTFX(DBG_ERROR,("***** Session is flagged 'suspended' -> MessageEnded ends package and session"));
-    newoutgoingstate=psta_idle;
-    newincomingstate=psta_idle;
-    fInProgress=false;
-  }
-  else if (!fMessageAuthorized) {
-    // not authorized messages will just be ignored, no matter if final or not,
-    // so outgoing will NEVER be final on non-authorized messages
-    // %%% before 1.0.4.9, this was fInProgress=true
-    //  DEBUGPRINTFX(DBG_ERROR,("***** Message not authorized, ignore and DONT end package, session continues"));
-    //  fInProgress=true; 
-    PDEBUGPRINTFX(DBG_ERROR,("***** Message not authorized, ignore msg and terminate session"));
-    fInProgress=false; 
-  }
-  else {
-    // determine if session continues living or not
-    // - if in other than idle state, session will continue
-    fInProgress =
-      (newincomingstate!=psta_idle) || // if not idle, we'll continue
-      !fMessageAuthorized; // if not authorized, we'll continue as well (retrying auth)   
-    // Check if we need to send an Alert 222 to get more messages of this package
-    if (!aIncomingFinal) {
-      // not end of incoming package
-      #ifndef ALWAYS_CONTINUE222
-      if (!fNeedToAnswer)
-      #endif
-      {
-        #ifdef COMBINE_SYNCANDMAP
-        // %%% make sure session gets to an end in case combined sync/map was used
-        if (fMapSeen && fIncomingState==psta_map && fOutgoingState==psta_map) {
-          DEBUGPRINTFX(DBG_HOT,("********** Incoming, non-final message in (combined)map state needs no answer -> force end of outgoing package"));          
-          newoutgoingstate=psta_idle;
-        }
-        else
-        #endif
-        {
-          // detected 222-loop on init here: when we have nothing to answer in init
-          // and nothing is alerted -> break session
-          // %%% not sure if this is always ok
-          if (fIncomingState<=psta_init) {
-            PDEBUGPRINTFX(DBG_ERROR,("############## Looks like if we were looping in an init-repeat loop -> force final"));
-            fInProgress=false;
-            fOutgoingState=psta_idle;
-          }
-          else {
-            // not final, and nothing to answer otherwise: create alert-Command to request more info
-            TAlertCommand *alertCmdP = new TAlertCommand(this,NULL,(uInt16)222);
-            // %%% not clear from spec what has to be in item for 222 alert code
-            //     but there MUST be an Item for the Alert command according to SyncML TK
-            // - we just put local and remote URIs here 
-            SmlItemPtr_t itemP = newItem();
-            itemP->target = newLocation(fRemoteURI.c_str());
-            itemP->source = newLocation(fLocalURI.c_str());
-            alertCmdP->addItem(itemP);
-            ISSUE_COMMAND_ROOT(this,alertCmdP);
-          }
-        }
-      }
-    }
-    else {
-      // end of package, finish processing package
-      if (fIncomingState==psta_init) {
-        // - try to load devinf from cache (only if we don't have both datastores and type info already)
-        if (!fRemoteDataStoresKnown || !fRemoteDataTypesKnown) {
-          SmlDevInfDevInfPtr_t devinfP;
-          TStatusCommand dummystatus(this);  
-          if (loadRemoteDevInf(getRemoteURI(),devinfP)) {
-            // we have cached devinf, analyze it now
-            localstatus sta = analyzeRemoteDevInf(devinfP);
-            PDEBUGPRINTFX(DBG_ERROR,("devInf from Cache could not be analyzed: error=%hd",sta));
-          }
-        }
-        // - if no DevInf for remote datastores cached or received yet,
-        //   issue GET for it now
-        if (!fRemoteDataStoresKnown) {
-          // if we know datastores here, but not types, this means that remote does not have
-          // CTCap, so it makes no sense to issue a GET again.
-          #ifndef NO_DEVINF_GET
-          // end of initialisation package, but datastores not known yet
-          // (=no DevInf Put received) --> ask for devinf now
-          PDEBUGPRINTFX(DBG_REMOTEINFO,("No DevInf received or cached, request DevInf using GET command"));
-          TGetCommand *getcommandP = new TGetCommand(this);
-          getcommandP->addTargetLocItem(SyncMLDevInfNames[fSyncMLVersion]);
-          string devinftype=SYNCML_DEVINF_META_TYPE;
-          addEncoding(devinftype);
-          getcommandP->setMeta(newMetaType(devinftype.c_str()));
-          ISSUE_COMMAND_ROOT(this,getcommandP);
-          #endif
-        }
-      }
-    }
-    // make sure syncing local datastores get informed of end-of-<Sync>-message
-    if (fIncomingState==psta_sync || fIncomingState==psta_initsync) {
-      // end of an incoming message of the Sync Package
-      // - let all local datastores know, this is now the time to generate
-      //   <sync> commands, if needed
-      // Note: if there are SyncEnd commands delayed, this means that this is
-      //       not yet the time to start <sync> commands. Instead, when all
-      //       queued SyncEnd commands are executed later, engEndOfSyncFromRemote()
-      //       will be called with the endOfAllSyncCommands flag true instead
-      //       of now. 
-      for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
-        (*pos)->engEndOfSyncFromRemote(aIncomingFinal && !delayedSyncEndsPending());
-      }
-    }
-    // Detect outgoing package state transitions
-    // - init to sync
-    if (fOutgoingState==psta_init && newincomingstate>psta_init) {
-      // new outgoing state is sync.
-      // Note: In combined init&sync mode, sync command received in init state
-      //       will set outgoing state from init to init-sync while processing message,
-      //       so no transition needs to be detected here
-      newoutgoingstate=psta_sync;
-    }
-    // - sync to map
-    else if (
-      (fOutgoingState==psta_sync || fOutgoingState==psta_initsync) && // outgoing is sync..
-      (newincomingstate>=psta_initsync) && // ..and incoming has finished sync
-      !allFromClientOnly // ..and this is not a session with all datastores doing from-client-only
-    ) {
-      // outgoing message belongs to Sync package
-      // - ask all local datastores if they are finished with sync command generation
-      alldone=true;
-      for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
-        alldone = alldone && (*pos)->isSyncDone();
-      }
-      if (alldone) {
-        // outgoing state changes to map (or supplement if all datastores are from-client-only
-        PDEBUGPRINTFX(DBG_HOT,("All datastores are done with generating <Sync>"));
-        newoutgoingstate=psta_map;
-        #ifdef COMBINE_SYNCANDMAP
-        // %%% it seems as if 9210 needs combined Sync/Map package and 
-        if (fMapSeen) {
-          // prevent FINAL to be sent at end of message
-          DEBUGPRINTFX(DBG_HOT,("********** Combining outgoing sync and map-response packages into one"));
-          fOutgoingState=psta_map;
-        }
-        #endif
-      }
-    }
-    // - map (or from-client-only sync) to idle
-    else if (
-      (fOutgoingState==psta_map && newincomingstate==psta_supplement) ||
-      (allFromClientOnly && (fOutgoingState==psta_sync || fOutgoingState==psta_initsync))
-    ) {
-      // we are going back to idle now
-      newoutgoingstate=psta_idle;
-      // session ends if it doesn't need to continue for session-level reasons
-      if (!sessionMustContinue()) {
-        PDEBUGPRINTFX(DBG_HOT,("Session completed, now let datastores terminate all sync operations"));
-        for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
-          // finished with Map: end of sync
-          (*pos)->engFinishDataStoreSync(); // successful
-        }
-        // session ends now
-        fInProgress=false;
-        // let custom PUTs which may transmit some session statistics etc. happen now
-        issueCustomEndPut();
-      }
-    }
-    // - if no need to answer (e.g. nothing to send back except OK status for SyncHdr),
-    //   session is over now (as well)
-    if (!fNeedToAnswer) fInProgress=false;
-  } // else 
-  // Now finish outgoing message
-  #ifdef DONT_FINAL_BAD_AUTH_ATTEMPTS
-  // - PREVENT final flag after failed auth attempts
-  if(FinishMessage(
-    fOutgoingState!=newoutgoingstate || fOutgoingState==psta_idle, // final when state changed or idle
-    !fMessageAuthorized || serverBusy() // busy or unauthorized prevent final flag at any rate
-  ))
-  #else
-  // - DO set final flag after failed auth attempts
-  if(FinishMessage(
-    !fMessageAuthorized || fOutgoingState!=newoutgoingstate || fOutgoingState==psta_idle, // final when state changed or idle
-    serverBusy() // busy prevents final flag at any rate
-  ))  
-  #endif
-  {
-    // outgoing state HAS changed
-    fOutgoingState=newoutgoingstate;
-  }
-  // Now update incoming state
-  fIncomingState=newincomingstate;
-  // show states
-  PDEBUGPRINTFX(DBG_HOT,(
-    "---> MessageEnded finishes : new incoming state='%s', new outgoing state='%s', %sNeedToAnswer",
-    PackageStateNames[fIncomingState],
-    PackageStateNames[fOutgoingState],
-    fNeedToAnswer ? "" : "NO "
-  ));
-  // let all local datastores know that message has ended
-  for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
-    // let them know
-    (*pos)->engEndOfMessage();
-    // Show state of local datastores
-    PDEBUGPRINTFX(DBG_HOT,(
-      "Local Datastore '%s': State=%s, %s%s sync, %s%s",
-      (*pos)->getName(),
-      (*pos)->getDSStateName(),
-      (*pos)->isResuming() ? "RESUMED " : "",
-      (*pos)->fSlowSync ? "SLOW" : "normal",
-      SyncModeDescriptions[(*pos)->fSyncMode],
-      (*pos)->fServerAlerted ? ", Server-Alerted" : ""
-    ));
-  }
-  // End of outgoing message
-  PDEBUGPRINTFX(DBG_HOT,(
-    "=================> Finished generating outgoing message #%ld, request=%ld",
-    fOutgoingMsgID,
-    getSyncAppBase()->requestCount()
-  ));
-  PDEBUGENDBLOCK("SyncML_Outgoing");
-} // TSyncServer::MessageEnded
-
-
-void TSyncServer::RequestEnded(bool &aHasData)
-{
-  // to make sure, finish any unfinished message
-  FinishMessage(true); // final allowed, as this is an out-of-normal-order case anyway  
-  // if we need to answer, we have data
-  // - SyncML specs 1.0.1 says that server must always respond, even if message
-  //   contains of a Status for the SyncHdr only 
-  aHasData=true;
-  // %%% first drafts of 1.0.1 said that SyncHdr Status only messages must not be sent...
-  // aHasData=fNeedToAnswer; // %%%
-  
-  // now let all datastores know that request processing ends here (so they might
-  // prepare for a thread switch)
-  // terminate sync with all datastores
-  TLocalDataStorePContainer::iterator pos;
-  for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
-    // now let them know that request has ended
-    (*pos)->engRequestEnded();
-  }
-} // TSyncServer::RequestEnded
-
-
-// Called at end of Request, returns true if session must be deleted
-// returns flag if data to be returned. If response URI was specified
-// different, it is returned in aRespURI, otherwise aRespURI is empty.
-bool TSyncServer::EndRequest(bool &aHasData, string &aRespURI, uInt32 aReqBytes)
-{
-  // count incoming data
-  fIncomingBytes+=aReqBytes;
-  // let client or server do what is needed
-  if (fMessageRetried) {
-    // Message processing cancelled
-    CancelMessageProcessing();
-    // Nothing happened 
-         // - but count bytes 
-    fOutgoingBytes+=fBufferedAnswerSize;
-    PDEBUGPRINTFX(DBG_HOT,(
-           "========= Finished retried request with re-sending buffered answer (session %sin progress), incoming bytes=%ld, outgoing bytes=%ld",
-           fInProgress ? "" : "NOT ",
-           aReqBytes,
-           fBufferedAnswerSize
-         ));
-         aHasData=false; // we do not have data in the sml instance (but we have/had some in the retry re-send buffer)
-  }
-  else {
-    // end request
-         RequestEnded(aHasData);
-         // count bytes
-    fOutgoingBytes+=getOutgoingMessageSize();
-         PDEBUGPRINTFX(DBG_HOT,(
-           "========= Finished request (session %sin progress), processing time=%ld msec, incoming bytes=%ld, outgoing bytes=%ld",
-           fInProgress ? "" : "NOT ",
-           (sInt32)((getSystemNowAs(TCTX_UTC)-getLastRequestStarted()) * nanosecondsPerLinearTime / 1000000),
-           aReqBytes,
-      getOutgoingMessageSize()
-         ));     
-         // return RespURI (is empty if none specified or equal to message source URI)
-         aRespURI = fRespondURI;
-  }
-  if (!fInProgress) {
-    // terminate datastores here already in case we are not in progress any more
-    // here. If any of the datastores are in progress at this point, this is a
-    // protocol violation, and therefore we return a 400.
-    // Note: resetting the session later will also call TerminateDatastores, but then
-    //       with a 408 (which is misleading when the session ends here due to protocol
-    //       problem.
-    TerminateDatastores(400);
-  }
-  //%%% moved to happen before end of SyncML_Outgoing 
-  //PDEBUGENDBLOCK("SyncML_Incoming");
-  if (fRequestMinTime>0) {
-    // make sure we spent enough time with this request, if not, artificially extend time
-    // - get number of seconds already spent
-    sInt32 t =
-      (sInt32)((getSystemNowAs(TCTX_UTC)-getLastRequestStarted()) / (lineartime_t)secondToLinearTimeFactor);
-    // - delay if needed
-    if (t<fRequestMinTime) {
-         PDEBUGPRINTFX(DBG_HOT,(
-           "requestmintime is set to %ld seconds, we have spent only %ld seconds so far -> sleeping %ld seconds",
-           fRequestMinTime,
-           t,
-           fRequestMinTime-t
-         ));
-      CONSOLEPRINTF(("  ...delaying response by %ld seconds because requestmintime is set to %ld",fRequestMinTime,fRequestMinTime-t));
-         sleepLineartime((lineartime_t)(fRequestMinTime-t)*secondToLinearTimeFactor);
-    }
-  }
-  // thread might end here, so stop profiling
-  TP_STOP(fTPInfo);
-  #ifdef SYDEBUG
-  // we are not the main thread any longer
-  getDbgLogger()->DebugThreadOutputDone();
-  #endif
-  // return true if session is not in progress any more
-  return(!fInProgress);
-} // TSyncServer::EndRequest
-
-
-// buffer answer in the session's buffer if transport allows it
-Ret_t TSyncServer::bufferAnswer(MemPtr_t aAnswer, MemSize_t aAnswerSize)
-{
-  // get rid of previous buffered answer
-  if (fBufferedAnswer)
-    delete[] fBufferedAnswer;
-  fBufferedAnswer=NULL;
-  fBufferedAnswerSize=0;
-  // save new answer (if not empty)
-  if (aAnswer && aAnswerSize) {
-    // allocate buffer
-    fBufferedAnswer = new unsigned char[aAnswerSize];
-    // copy data
-    if (!fBufferedAnswer) return SML_ERR_NOT_ENOUGH_SPACE;
-    memcpy(fBufferedAnswer,aAnswer,aAnswerSize);
-    // save size
-    fBufferedAnswerSize=aAnswerSize;
-  }
-  return SML_ERR_OK;
-} // TSyncServer::bufferAnswer
-
-
-// get buffered answer from the session's buffer if there is any
-void TSyncServer::getBufferedAnswer(MemPtr_t &aAnswer, MemSize_t &aAnswerSize)
-{
-  aAnswer=fBufferedAnswer;
-  aAnswerSize=fBufferedAnswerSize;  
-  PDEBUGPRINTFX(DBG_HOT,(
-    "Buffered answer read from session: %ld bytes",
-    fBufferedAnswerSize
-  ));
-} // TSyncServer::getBufferedAnswer
-
-
-// returns remaining time for request processing [seconds]
-sInt32 TSyncServer::RemainingRequestTime(void)
-{
-  // if no request timeout specified, use session timeout
-  sInt32 t = fRequestMaxTime ? fRequestMaxTime : getSessionConfig()->fSessionTimeout;
-  // calculate number of remaining seconds
-  return
-    t==0 ?
-      0x7FFFFFFF : // "infinite"
-      t - (sInt32)((getSystemNowAs(TCTX_UTC)-getLastRequestStarted()) / (lineartime_t)secondToLinearTimeFactor);
-} // TSyncServer::RemainingRequestTime
-
-
-
-
-
-// process a Map command in context of server session
-bool TSyncServer::processMapCommand(
-  SmlMapPtr_t aMapCommandP,      // the map command contents
-  TStatusCommand &aStatusCommand, // pre-set 200 status, can be modified in case of errors
-  bool &aQueueForLater
-)
-{
-  bool allok=false; // assume not ok
-  localstatus sta;
-
-  // remember that this session has seen a map command already
-  fMapSeen=true;
-  // Detecting a map command in supplement incomin state indicates a
-  // client like funambol that send to many <final/> in pre-map phases
-  // (such as in 222-Alert messages). So we reset the session state back
-  // to incoming/outgoing map to correct this client bug
-  if (fIncomingState==psta_supplement) {
-    // back to map phase, as client apparently IS still in map phase, despite too many
-    // <final/> sent
-    PDEBUGPRINTFX(DBG_ERROR,(
-      "Warning: detected <Map> command after end of Map phase - buggy client sent too many <final/>. Re-entering map phase to compensate"
-    ));
-    fIncomingState=psta_map;
-    fOutgoingState=psta_map;
-  }
-  // find database(s)
-  // - get relative URI of requested database
-  const char *targetdburi = smlSrcTargLocURIToCharP(aMapCommandP->target);
-  TLocalEngineDS *datastoreP = findLocalDataStoreByURI(targetdburi);
-  if (!datastoreP) {
-    // no such local datastore
-    aStatusCommand.setStatusCode(404); // not found
-  }
-  else {
-    // local datastore found
-    // - maps can be processed when we are at least ready for early (chached by client from previous session) maps
-    if (datastoreP->testState(dssta_syncmodestable)) {
-      // datastore is ready 
-      PDEBUGBLOCKFMT(("ProcessMap", "Processing items from Map command", "datastore=%s", targetdburi));
-      allok=true; // assume all ok
-      SmlMapItemListPtr_t nextnode = aMapCommandP->mapItemList;
-      while (nextnode) {
-        POINTERTEST(nextnode->mapItem,("MapItemList node w/o MapItem"));
-        PDEBUGPRINTFX(DBG_HOT,(
-          "Mapping remoteID='%s' to localID='%s'",
-          smlSrcTargLocURIToCharP(nextnode->mapItem->source),
-          smlSrcTargLocURIToCharP(nextnode->mapItem->target)
-        ));
-        sta = datastoreP->engProcessMap(
-          #ifdef DONT_STRIP_PATHPREFIX_FROM_REMOTEIDS
-          smlSrcTargLocURIToCharP(nextnode->mapItem->source),
-          #else 
-          relativeURI(smlSrcTargLocURIToCharP(nextnode->mapItem->source)),
-          #endif
-          relativeURI(smlSrcTargLocURIToCharP(nextnode->mapItem->target))
-        );
-        if (sta!=LOCERR_OK) {
-          PDEBUGPRINTFX(DBG_ERROR,("    Mapping FAILED!"));
-          aStatusCommand.setStatusCode(sta);
-          allok=false;
-          break;
-        }
-        // next mapitem
-        nextnode=nextnode->next;
-      } // while more mapitems
-      // terminate Map command
-      allok=datastoreP->MapFinishAsServer(allok,aStatusCommand);
-      PDEBUGENDBLOCK("ProcessMap");
-    }
-    else {
-      // we must queue the command for later execution
-      aQueueForLater=true;
-      allok=true; // ok for now, we'll re-execute this later
-    }
-  } // database found
-  return allok;
-} // TSyncServer::processMapCommand
-    
-
-// - start sync group
-bool TSyncServer::processSyncStart(
-  SmlSyncPtr_t aSyncP,            // the Sync element
-  TStatusCommand &aStatusCommand, // pre-set 200 status, can be modified in case of errors
-  bool &aQueueForLater // will be set if command must be queued for later (re-)execution
-)
-{
-  // Init datastores for sync
-  localstatus sta = initSync(
-    smlSrcTargLocURIToCharP(aSyncP->target),  // local datastore
-    smlSrcTargLocURIToCharP(aSyncP->source)  // remote datastore
-  );
-  if (sta!=LOCERR_OK) {
-    aStatusCommand.setStatusCode(sta);
-    return false;
-  }
-  // let local datastore prepare for sync as server
-  // - let local process sync command
-  bool ok=fLocalSyncDatastoreP->engProcessSyncCmd(aSyncP,aStatusCommand,aQueueForLater);
-  // Note: ok means that the sync command is addressing existing datastores. However,
-  //       it does not mean that the actual processing is already executed; aQueueForLater
-  //       could be set!
-  // if ok and not queued: update package states
-  if (ok) {
-    if (fIncomingState==psta_init || fIncomingState==psta_initsync) {
-      // detected sync command in init package -> this is combined init/sync
-      #ifdef SYDEBUG
-      if (fIncomingState==psta_init)
-        DEBUGPRINTFX(DBG_HOT,("<Sync> started init package -> switching to combined init/sync"));
-      #endif
-      // - set new incoming state
-      fIncomingState=psta_initsync;
-      // - also update outgoing state, if it is in init package
-      if (fOutgoingState==psta_init)
-        fOutgoingState=psta_initsync;
-    }
-    else if (fCmdIncomingState!=psta_sync) {
-      DEBUGPRINTFX(DBG_ERROR,(
-        "<Sync> found in wrong incoming package state '%s' -> aborting session",
-        PackageStateNames[fCmdIncomingState]
-      ));
-      aStatusCommand.setStatusCode(403); // forbidden
-      fLocalSyncDatastoreP->engAbortDataStoreSync(403,true); // abort, local problem
-      ok=false;
-    }
-    else {
-      // - show sync start    
-      DEBUGPRINTFX(DBG_HOT,(
-        "<Sync> started, cmd-incoming state='%s', incoming state='%s', outgoing state='%s'",
-        PackageStateNames[fCmdIncomingState],
-        PackageStateNames[fIncomingState],
-        PackageStateNames[fOutgoingState]
-      ));
-    }
-  }
-  return ok;
-} // TSyncServer::processSyncStart
-
-
-
-// get next nonce string top be sent to remote party for subsequent MD5 auth
-void TSyncServer::getNextNonce(const char *aDeviceID, string &aNextNonce)
-{
-  fLastNonce.erase();
-  if (getServerConfig()->fAutoNonce) {
-    // generate nonce out of source ref and session ID
-    // This scheme can provide nonce carrying forward between 
-    // sessions by initializing lastNonce with the srcRef/sessionid-1
-    // assuming client to use nonce from last session.
-    sInt32 sid;
-    // use current day as nonce varying number
-    sid = time(NULL) / 3600 / 24; 
-    generateNonce(fLastNonce,aDeviceID,sid);
-  }
-  else {
-    // get constant nonce (if empty, this is NO nonce)
-    fLastNonce=getServerConfig()->fConstantNonce;
-  }
-  // return new nonce
-  DEBUGPRINTFX(DBG_PROTO,("getNextNonce: created nonce='%s'",fLastNonce.c_str()));
-  aNextNonce=fLastNonce;
-} // TSyncServer::getNextNonce
-
-
-// - get nonce string for specified deviceID
-void TSyncServer::getAuthNonce(const char *aDeviceID, string &aAuthNonce)
-{
-  // if no device ID, use session default nonce
-  if (!aDeviceID) {
-    TSyncSession::getAuthNonce(aDeviceID,fLastNonce);
-  }
-  else {
-    // Basic nonce mechanism needing no per-device storage:
-    // - we have no stored last nonce, but we can re-create nonce used
-    //   for last session with this device by the used algorithm
-    if (getServerConfig()->fAutoNonce) {
-      if (fLastNonce.empty()) {
-        // none available, produce new one
-        sInt32 sid;
-        // use current day as nonce varying number
-        sid = time(NULL) / 3600 / 24; 
-        generateNonce(fLastNonce,aDeviceID,sid);
-      }
-    }
-    else {
-      // return constant nonce
-      fLastNonce=getServerConfig()->fConstantNonce;
-    }
-  }
-  DEBUGPRINTFX(DBG_PROTO,("getAuthNonce: current auth nonce='%s'",fLastNonce.c_str()));
-  aAuthNonce=fLastNonce;
-} // TSyncServer::getAuthNonce
-
-
-
-// info about server status
-bool TSyncServer::serverBusy(void)
-{
-       // return flag (which might have been set by some connection
-       // limit code in sessiondispatch).
-       // When app is expired, all server sessions are busy anyway
-       #ifdef APP_CAN_EXPIRE
-       return fSessionIsBusy || (getSyncAppBase()->fAppExpiryStatus!=LOCERR_OK);
-       #else
-       return fSessionIsBusy;
-       #endif
-} // TSyncServer::serverBusy
-
-
-// access to config
-TServerConfig *TSyncServer::getServerConfig(void)
-{
-  TServerConfig *scP;
-  GET_CASTED_PTR(scP,TServerConfig,getSyncAppBase()->getRootConfig()->fAgentConfigP,DEBUGTEXT("no TServerConfig","ss1"));
-  return scP;
-} // TSyncServer::getServerConfig
-
-
-// info about requested auth type
-TAuthTypes TSyncServer::requestedAuthType(void)
-{
-  return getServerConfig()->fRequestedAuth;
-} // TSyncServer::requestedAuthType
-
-
-// check if auth type is allowed
-bool TSyncServer::isAuthTypeAllowed(TAuthTypes aAuthType)
-{
-  return aAuthType>=getServerConfig()->fRequiredAuth;
-} // TSyncServer::isAuthTypeAllowed
-
-
-#ifdef ENGINEINTERFACE_SUPPORT
-
-// Support for EngineModule common interface
-// -----------------------------------------
-
-
-#ifndef ENGINE_LIBRARY
-
-// dummy server engine support to allow AsKey from plugins
-
-#warning "using ENGINEINTERFACE_SUPPORT in old-style appbase-rooted environment. Should be converted to real engine usage later"
-
-// Engine factory function for non-Library case
-ENGINE_IF_CLASS *newEngine(void)
-{
-  // For real engine based targets, newEngine must create a target-specific derivate
-  // of the engine, which then has a suitable newSyncAppBase() method to create the
-  // appBase. For old-style environment, a generic TServerEngineInterface is ok, as this
-  // in turn calls the global newSyncAppBase() which then returns the appropriate
-  // target specific appBase. Here we just return a dummy server engine base. 
-  return new TDummyServerEngineInterface;
-} // newEngine
-
-/// @brief returns a new application base.
-TSyncAppBase *TDummyServerEngineInterface::newSyncAppBase(void)
-{
-  // For not really engine based targets, the appbase factory function is
-  // a global routine (for real engine targets, it is a true virtual of
-  // the engineInterface, implemented in the target's leaf engineInterface derivate.
-  // - for now, use the global appBase creator routine
-  return sysync::newSyncAppBase(); // use global factory function 
-} // TDummyServerEngineInterface::newSyncAppBase
-
-
-#else
-
-// Real server engine support
-
-/// @brief Executes next step of the session
-/// @param aStepCmd[in/out] step command (STEPCMD_xxx):
-///        - tells caller to send or receive data or end the session etc.
-///        - instructs engine to abort or time out the session etc.
-/// @param aInfoP[in] pointer to a TEngineProgressInfo structure, NULL if no progress info needed
-/// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure
-TSyError TSyncServer::SessionStep(uInt16 &aStepCmd, TEngineProgressInfo *aInfoP)
-{
-  uInt16 stepCmdIn = aStepCmd;
-  localstatus sta = LOCERR_WRONGUSAGE;
-
-  // init default response
-  aStepCmd = STEPCMD_ERROR; // error
-  if (aInfoP) {
-    aInfoP->eventtype=PEV_NOP;
-    aInfoP->targetID=0;
-    aInfoP->extra1=0;
-    aInfoP->extra2=0;
-    aInfoP->extra3=0;
-  }
-
-  // if session is already aborted, no more steps are required
-  if (isAborted()) {
-       fEngineState = ses_done; // we are done
-  }
-
-  // handle pre-processed step command according to current engine state
-  switch (fEngineState) {
-
-    // Done state
-    case ses_done :
-      // session done, nothing happens any more
-      aStepCmd = STEPCMD_DONE;
-      sta = LOCERR_OK;
-      break;
-
-    // Waiting for SyncML request data
-    case ses_needdata:
-      switch (stepCmdIn) {
-        case STEPCMD_GOTDATA :
-          // got data, now start processing it
-          fEngineState = ses_processing;
-          aStepCmd = STEPCMD_OK;
-          sta = LOCERR_OK;
-          break;
-      } // switch stepCmdIn for ces_processing
-      break;
-
-    // Waiting until SyncML answer data is sent
-    case ses_dataready:
-      switch (stepCmdIn) {
-        case STEPCMD_SENTDATA :
-          // sent data, now wait for next request
-          fEngineState = ses_needdata;
-          aStepCmd = STEPCMD_NEEDDATA;
-          sta = LOCERR_OK;
-          break;
-      } // switch stepCmdIn for ces_processing
-      break;
-
-
-    // Ready for generation steps
-    case ses_generating:
-      switch (stepCmdIn) {
-        case STEPCMD_STEP :
-          sta = generatingStep(aStepCmd,aInfoP);
-          break;
-      } // switch stepCmdIn for ces_generating
-      break;
-
-    // Ready for processing steps
-    case ses_processing:
-      switch (stepCmdIn) {
-        case STEPCMD_STEP :
-          sta = processingStep(aStepCmd,aInfoP);
-          break;
-      } // switch stepCmdIn for ces_processing
-      break;
-
-  case numServerEngineStates:
-      // invalid
-      break;
-
-  } // switch fEngineState
-
-  // done
-  return sta;
-} // TSyncServer::SessionStep
-
-
-
-
-// Step that processes SyncML request data
-TSyError TSyncServer::processingStep(uInt16 &aStepCmd, TEngineProgressInfo *aInfoP)
-{
-  localstatus sta = LOCERR_WRONGUSAGE;
-  InstanceID_t myInstance = getSmlWorkspaceID();
-  Ret_t rc;
-  
-  // %%% non-functional at this time
-  sta = LOCERR_NOTIMP;
-  /*
-  #error "%%% figure out encoding if we are starting a new session here"
-
-  // now process next command
-  PDEBUGPRINTFX(DBG_EXOTIC,("Calling smlProcessData(NEXT_COMMAND)"));
-  #ifdef SYDEBUG
-  MemPtr_t data = NULL;
-  MemSize_t datasize;
-  smlPeekMessageBuffer(getSmlWorkspaceID(), false, &data, &datasize);
-  #endif  
-  rc=smlProcessData(
-    myInstance,
-    SML_NEXT_COMMAND
-  );
-  if (rc==SML_ERR_CONTINUE) {
-    // processed ok, but message not completely processed yet
-    // - engine state remains as is
-    aStepCmd = STEPCMD_OK; // ok w/o progress %%% for now, progress is delivered via queue in next step
-    sta = LOCERR_OK;
-  }
-  else if (rc==SML_ERR_OK) {
-    // message completely processed
-    // - switch engine state to generating answer message (if any)
-    aStepCmd = STEPCMD_OK;
-    fEngineState = ses_generating;
-    sta = LOCERR_OK;
-  }
-  else {
-    // processing failed
-    PDEBUGPRINTFX(DBG_ERROR,("===> smlProcessData failed, returned 0x%hX",(sInt16)rc));
-    // dump the message that failed to process
-    #ifdef SYDEBUG
-    if (data) DumpSyncMLBuffer(data,datasize,false,rc);
-    #endif    
-    // abort the session (causing proper error events to be generated and reported back)
-    AbortSession(LOCERR_PROCESSMSG, true);
-    // session is now done
-    fEngineState = ses_done;
-    // step by itself is ok - let app continue stepping (to restart session or complete abort)
-    aStepCmd = STEPCMD_OK;
-    sta = LOCERR_OK;
-  }
-  */
-  // done
-  return sta;
-} // TSyncServer::processingStep
-
-
-
-// Step that generates SyncML answer data
-TSyError TSyncServer::generatingStep(uInt16 &aStepCmd, TEngineProgressInfo *aInfoP)
-{
-  localstatus sta = LOCERR_WRONGUSAGE;
-  bool done;
-
-  // %%% non-functional at this time
-  sta = LOCERR_NOTIMP;
-  /*
-  #error "%%% figure out encoding if we are starting a new session here"
-
-  //%%% at this time, generate next message in one step
-  sta = NextMessage(done);
-  if (done) {
-    // done with session, with or without error
-    fEngineState = ces_done; // blocks any further activity with the session
-    aStepCmd = STEPCMD_DONE;
-    // terminate session to provoke all end-of-session progress events
-    TerminateSession();
-  }
-  else if (sta==LOCERR_OK) {
-    // next is sending request to server
-    fEngineState = ces_dataready;
-    aStepCmd = STEPCMD_SENDDATA;
-    OBJ_PROGRESS_EVENT(getSyncAppBase(),pev_sendstart,NULL,0,0,0);
-  }
-  */
-  // return status
-  return sta;
-} // TSyncServer::generatingStep
-
-
-#endif // ENGINE_LIBRARY
-
-
-
-/// @brief Get new session key to access details of this session
-appPointer TSyncServer::newSessionKey(TEngineInterface *aEngineInterfaceP)
-{
-  return new TServerParamsKey(aEngineInterfaceP,this);
-} // TSyncServer::newSessionKey
-
-
-
-
-// Server runtime settings key
-// ---------------------------
-
-// Constructor
-TServerParamsKey::TServerParamsKey(TEngineInterface *aEngineInterfaceP, TSyncServer *aServerSessionP) :
-  inherited(aEngineInterfaceP,aServerSessionP),
-  fServerSessionP(aServerSessionP)
-{
-} // TServerParamsKey::TServerParamsKey
-
-
-// - read local session ID
-static TSyError readLocalSessionID(
-  TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
-  appPointer aBuffer, memSize aBufSize, memSize &aValSize
-)
-{
-  TServerParamsKey *mykeyP = static_cast<TServerParamsKey *>(aStructFieldsKeyP);
-  return TStructFieldsKey::returnString(
-    mykeyP->fServerSessionP->getLocalSessionID(),
-    aBuffer,aBufSize,aValSize
-  );
-} // readLocalSessionID
-
-
-// - read initial local URI
-static TSyError readInitialLocalURI(
-  TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
-  appPointer aBuffer, memSize aBufSize, memSize &aValSize
-)
-{
-  TServerParamsKey *mykeyP = static_cast<TServerParamsKey *>(aStructFieldsKeyP);
-  return TStructFieldsKey::returnString(
-    mykeyP->fServerSessionP->getInitialLocalURI(),
-    aBuffer,aBufSize,aValSize
-  );
-} // readInitialLocalURI
-
-
-// - read abort status
-static TSyError readAbortStatus(
-  TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
-  appPointer aBuffer, memSize aBufSize, memSize &aValSize
-)
-{
-  TServerParamsKey *mykeyP = static_cast<TServerParamsKey *>(aStructFieldsKeyP);
-  return TStructFieldsKey::returnInt(
-       mykeyP->fServerSessionP->getAbortReasonStatus(),
-    sizeof(TSyError),
-    aBuffer,aBufSize,aValSize
-  );
-} // readAbortStatus
-
-
-
-// - write abort status, which means aborting a session
-TSyError writeAbortStatus(
-  TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
-  cAppPointer aBuffer, memSize aValSize
-)
-{
-  TServerParamsKey *mykeyP = static_cast<TServerParamsKey *>(aStructFieldsKeyP);
-  // abort the session
-  TSyError sta = *((TSyError *)aBuffer);
-       mykeyP->fServerSessionP->AbortSession(sta, true);
-  return LOCERR_OK;
-} // writeAbortStatus
-
-
-
-// accessor table for server session key
-static const TStructFieldInfo ServerParamFieldInfos[] =
-{  
-  // valName, valType, writable, fieldOffs, valSiz
-  { "localSessionID", VALTYPE_TEXT, false, 0, 0, &readLocalSessionID, NULL },
-  { "initialLocalURI", VALTYPE_TEXT, false, 0, 0, &readInitialLocalURI, NULL },
-  { "abortStatus", VALTYPE_INT16, true, 0, 0, &readAbortStatus, &writeAbortStatus },
-};
-
-// get table describing the fields in the struct
-const TStructFieldInfo *TServerParamsKey::getFieldsTable(void)
-{
-  return ServerParamFieldInfos;
-} // TServerParamsKey::getFieldsTable
-
-sInt32 TServerParamsKey::numFields(void)
-{
-  return sizeof(ServerParamFieldInfos)/sizeof(TStructFieldInfo);
-} // TServerParamsKey::numFields
-
-// get actual struct base address
-uInt8P TServerParamsKey::getStructAddr(void)
-{
-  // prepared for accessing fields in server session object
-  return (uInt8P)fServerSessionP;
-} // TServerParamsKey::getStructAddr
-
-
-#endif // ENGINEINTERFACE_SUPPORT
-
-
-} // namespace sysync
-
-/* end of TSyncServer implementation */
-
-// eof
diff --git a/src/synthesis/src/sysync/syncserver.h b/src/synthesis/src/sysync/syncserver.h
deleted file mode 100755 (executable)
index abab580..0000000
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- *  File:         SyncServer.h
- *
- *  Author:                      Lukas Zeller (luz@synthesis.ch)
- *
- *  TSyncServer
- *    <describe here>
- *
- *  Copyright (c) 2001-2009 by Synthesis AG (www.synthesis.ch)
- *
- *  2001-05-07 : luz : Created
- *
- */
-
-#ifndef SyncServer_H
-#define SyncServer_H
-
-// includes
-#include "syncsessiondispatch.h"
-#include "syncsession.h"
-#include "syncdatastore.h"
-#include "remotedatastore.h"
-
-
-using namespace sysync;
-
-
-namespace sysync {
-
-
-// Support for SySync Diagnostic Tool
-#ifdef SYSYNC_TOOL
-int testLogin(int argc, const char *argv[]);
-int convertData(int argc, const char *argv[]);
-#endif
-
-
-/// @brief server engine state
-typedef enum {
-  ses_needdata,     ///< need SyncML request data, waiting for STEPCMD_GOTDATA
-  ses_processing,   ///< ready to perform next STEPCMD_STEP to process SyncML messages
-  ses_generating,   ///< ready to perform next STEPCMD_STEP to generate SyncML messages
-  ses_dataready,    ///< data is ready to be sent, waiting for STEPCMD_SENTDATA  
-  ses_done,         ///< session done
-  numServerEngineStates
-} TServerEngineState;
-
-
-
-// forward
-class TSyncSessionHandle;
-class TSyncServer;
-
-
-// server config
-class TServerConfig: public TSessionConfig
-{
-  typedef TSessionConfig inherited;
-public:
-  TServerConfig(const char *aElementName, TConfigElement *aParentElementP);
-  virtual ~TServerConfig();
-  // General server settings
-  // - requested auth type (Auth requested in Chal sent to client)
-  TAuthTypes fRequestedAuth;
-  // - minimally required auth type (lowest auth type that is allowed)
-  TAuthTypes fRequiredAuth;
-  // - use automatic nonce generation for MD5 auth (empty nonce if false)
-  bool fAutoNonce;
-  // - constant nonce string to be used if autononce is off. If empty, no nonce is used
-  string fConstantNonce;
-  // - constant external URL, if set, it is used to generate RespURI (instead of Target LocURI sent by client)
-  string fExternalURL;
-  // - max size of GUID sent if client does not specify a MaxGUIDSize in devInf. 0=unlimited
-  uInt16 fMaxGUIDSizeSent;
-protected:
-  // check config elements
-  #ifndef HARDCODED_CONFIG
-  virtual bool localStartElement(const char *aElementName, const char **aAttributes, sInt32 aLine);
-  #endif
-  virtual void clear();
-  virtual void localResolve(bool aLastPass);
-public:
-  // create appropriate session (=agent) for this server
-  virtual TSyncServer *CreateServerSession(TSyncSessionHandle *aSessionHandle, const char *aSessionID)=0;
-}; // TServerConfig
-
-
-// server session
-class TSyncServer: public TSyncSession
-{
-  typedef TSyncSession inherited;
-public:
-  TSyncServer(
-    TSyncAppBase *aAppBaseP,
-    TSyncSessionHandle *aSessionHandleP,
-    const char *aSessionID // a session ID
-  );
-  virtual ~TSyncServer();
-  virtual void ResetSession(void); // like destructor, but without destructing object itself
-  void InternalResetSession(void); // static implementation for calling through virtual destructor and virtual ResetSession();
-  virtual SmlPcdataPtr_t newResponseURIForRemote(void); // response URI
-  // info about session
-  virtual bool IsServerSession(void) { return true; }; // is server
-  // info about needed auth type
-  virtual TAuthTypes requestedAuthType(void);
-  virtual bool isAuthTypeAllowed(TAuthTypes aAuthType);
-  // Request processing
-  // - called when incoming SyncHdr fails to execute
-  virtual bool syncHdrFailure(bool aTryAgain);
-  // - end of request (to make sure even incomplete SyncML messages get cleaned up properly)
-  bool EndRequest(bool &aHasData, string &aRespURI, uInt32 aReqBytes); // returns true if session must be deleted
-  // - buffer answer in the session's buffer if transport allows it
-  Ret_t bufferAnswer(MemPtr_t aAnswer, MemSize_t aAnswerSize);
-  // - get buffered answer from the session's buffer if there is any
-  void getBufferedAnswer(MemPtr_t &aAnswer, MemSize_t &aAnswerSize);
-  // - get byte statistics
-  virtual uInt32 getIncomingBytes(void) { return fIncomingBytes; };
-  virtual uInt32 getOutgoingBytes(void) { return fOutgoingBytes; };
-  // session handling
-  // - get session Handle pointer
-  TSyncSessionHandle *getSessionHandle(void) { return fSessionHandleP; }
-  // returns remaining time for request processing [seconds]
-  virtual sInt32 RemainingRequestTime(void);
-  // info about server status
-  virtual bool serverBusy(void); // return busy status (set by connection limit or app expiry)
-  // Sync processing (command group)
-  // - start sync group
-  virtual bool processSyncStart(
-    SmlSyncPtr_t aSyncP,           // the Sync element
-    TStatusCommand &aStatusCommand, // pre-set 200 status, can be modified in case of errors
-    bool &aQueueForLater // will be set if command must be queued for later (re-)execution
-  );
-  #ifdef ENGINE_LIBRARY
-  // Support for EngineModule common interface
-  /// @brief Executes next step of the session
-  /// @param aStepCmd[in/out] step command (STEPCMD_xxx):
-  ///        - tells caller to send or receive data or end the session etc.
-  ///        - instructs engine to abort or time out the session etc.
-  /// @param aInfoP[in] pointer to a TEngineProgressInfo structure, NULL if no progress info needed
-  /// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure
-  TSyError SessionStep(uInt16 &aStepCmd, TEngineProgressInfo *aInfoP);
-  #endif // ENGINE_LIBRARY
-  #ifdef ENGINEINTERFACE_SUPPORT
-  /// @brief Get new session key to access details of this session
-  virtual appPointer newSessionKey(TEngineInterface *aEngineInterfaceP);
-  #endif // ENGINEINTERFACE_SUPPORT
-protected:
-  // access to config
-  TServerConfig *getServerConfig(void);
-  // internal processing events
-  // - message start and end
-  virtual bool MessageStarted(SmlSyncHdrPtr_t aContentP, TStatusCommand &aStatusCommand, bool aBad=false);
-  virtual void MessageEnded(bool aIncomingFinal);
-  // - request end, called by EndRequest, virtual for descendants
-  virtual void RequestEnded(bool &aHasData);
-  // - map operation
-  virtual bool processMapCommand(
-    SmlMapPtr_t aMapCommandP,       // the map command contents
-    TStatusCommand &aStatusCommand, // pre-set 200 status, can be modified in case of errors
-    bool &aQueueForLater
-  );
-  // Session level auth
-  // - get next nonce string top be sent to remote party for subsequent MD5 auth
-  virtual void getNextNonce(const char *aDeviceID, string &aNextNonce);
-  // - get nonce string, which is expected to be used by remote party for MD5 auth.
-  virtual void getAuthNonce(const char *aDeviceID, string &aAuthNonce);
-  // device info (uses defaults for server, override to customize)
-  virtual string getDeviceID(void) { return SYSYNC_SERVER_DEVID; }
-  virtual string getDeviceType(void) { return SYNCML_SERVER_DEVTYP; }
-  #ifdef ENGINEINTERFACE_SUPPORT
-  // Engine interface
-  // - Step that generates SyncML data
-  TSyError generatingStep(uInt16 &aStepCmd, TEngineProgressInfo *aInfoP);
-  // - Step that processes SyncML data
-  TSyError processingStep(uInt16 &aStepCmd, TEngineProgressInfo *aInfoP);
-  // - Server engine state
-  TServerEngineState fEngineState;
-  #endif // ENGINEINTERFACE_SUPPORT
-  // set if map command received in this session
-  bool fMapSeen;
-  // standard nonce generation (without persistent device info)
-  // %%% note: move this to session when we start supporting client auth checking
-  string fLastNonce; // last nonce, will be returned at getAuthNonce()
-  // busy status
-  bool fServerIsBusy;
-  // buffered answer
-  MemPtr_t fBufferedAnswer;
-  MemSize_t fBufferedAnswerSize;
-  // data transfer statistics
-  uInt32 fIncomingBytes;
-  uInt32 fOutgoingBytes;
-  // server session handle
-  TSyncSessionHandle *fSessionHandleP; // the session "handle" (wrapper, containing server specific locking etc.)
-}; // TSyncServer
-
-
-#ifdef ENGINEINTERFACE_SUPPORT
-
-// Support for EngineModule common interface
-// =========================================
-
-
-#ifndef ENGINE_LIBRARY
-
-#warning "using ENGINEINTERFACE_SUPPORT in old-style appbase-rooted environment. Should be converted to real engine usage later"
-
-// Define dummy server engine class - no implementation of actual server engine routines,
-// defaults from TEngineInterface (returning error codes) will be used.
-class TDummyServerEngineInterface :
-  public TEngineInterface
-{
-  typedef TEngineInterface inherited;
-public:
-  // constructor
-  TDummyServerEngineInterface() {};
-
-  // appbase factory
-  virtual TSyncAppBase *newSyncAppBase(void);
-
-}; // TDummyServerEngineInterface
-
-#endif // not ENGINE_LIBRARY
-
-
-
-// server runtime parameters
-class TServerParamsKey :
-  public TSessionKey
-{
-  typedef TSessionKey inherited;
-
-public:
-  TServerParamsKey(TEngineInterface *aEngineInterfaceP, TSyncServer *aServerSessionP);
-
-  virtual ~TServerParamsKey() {};
-
-protected:
-  // get table describing the fields in the struct
-  virtual const TStructFieldInfo *getFieldsTable(void);
-  virtual sInt32 numFields(void);
-  // get actual struct base address
-  virtual uInt8P getStructAddr(void);
-public:
-  // the associated server session
-  TSyncServer *fServerSessionP;
-}; // TServerParamsKey
-
-#endif // ENGINEINTERFACE_SUPPORT
-
-
-}      // namespace sysync
-
-#endif // SyncServer_H
-
-// eof
-
index 1395b3c..6fd97e5 100644 (file)
@@ -15,6 +15,7 @@
 
 #include "sysync.h"
 #include "syncsession.h"
+#include "syncagent.h"
 #ifdef SUPERDATASTORES
   #include "superdatastore.h"
 #endif
@@ -538,7 +539,7 @@ bool TRemoteRuleConfig::localStartElement(const char *aElementName, const char *
 
 // config constructor
 TSessionConfig::TSessionConfig(const char *aElementName, TConfigElement *aParentElementP) :
-  TAgentConfig(aElementName,aParentElementP)
+  inherited(aElementName,aParentElementP)
 {
   clear();
 } // TSessionConfig::TSessionConfig
@@ -589,15 +590,16 @@ void TSessionConfig::clear(void)
   fShowCTCapProps=true;
   // - default value for flag to send type/size in CTCap for SyncML 1.0 (disable as old clients like S55 crash on this)
   fShowTypeSzInCTCap10=false;
-  #ifdef SYSYNC_CLIENT
-  // - Synthesis clients always behaved like that (sending 23:59:59), so we'll keep it as a default
-       fVCal10EnddatesSameDay = true;
-  #else
-  // - Many modern clients need the exclusive format (start of next day) to detect all-day events properly.
-  //   Synthesis clients detect these fine as well, so not using 23:59:59 style by default is more
-  //   compatible in general for a server.
-       fVCal10EnddatesSameDay = false;
-  #endif
+  if (IS_CLIENT) {
+    // - Synthesis clients always behaved like that (sending 23:59:59), so we'll keep it as a default
+    fVCal10EnddatesSameDay = true;
+  }
+  else {
+    // - Many modern clients need the exclusive format (start of next day) to detect all-day events properly.
+    //   Synthesis clients detect these fine as well, so not using 23:59:59 style by default is more
+    //   compatible in general for a server.
+    fVCal10EnddatesSameDay = false;
+  }
   // traditionally Synthesis has folded content
   fDoNotFoldContent = false;
   // - default value for flag is "default" (depends on SyncML version)
@@ -642,8 +644,14 @@ void TSessionConfig::clear(void)
   #ifndef MINIMAL_CODE
   // - logfile
   fLogFileName.erase();
-  fLogFileFormat.assign(DEFAULT_LOG_FORMAT);
-  fLogFileLabels.assign(DEFAULT_LOG_LABELS);
+  if (IS_SERVER) {
+    fLogFileFormat.assign(DEFAULT_LOG_FORMAT_SERVER);
+    fLogFileLabels.assign(DEFAULT_LOG_LABELS_SERVER);
+  }
+  else {
+    fLogFileFormat.assign(DEFAULT_LOG_FORMAT_CLIENT);
+    fLogFileLabels.assign(DEFAULT_LOG_LABELS_CLIENT);  
+  }
   fLogEnabled=true;
   fDebugChunkMaxSize=0; // disabled
   #endif
@@ -807,7 +815,7 @@ bool TSessionConfig::localStartElement(const char *aElementName, const char **aA
   #endif
   // - none known here
   else
-    return TAgentConfig::localStartElement(aElementName,aAttributes,aLine);
+    return inherited::localStartElement(aElementName,aAttributes,aLine);
   // ok
   return true;
 } // TSessionConfig::localStartElement
@@ -894,6 +902,7 @@ TSyncSession::TSyncSession(
   TP_START(fTPInfo,TP_general);
   DEBUGPRINTFX(DBG_EXOTIC,("TSyncSession::TSyncSession: Profiling initialized"));
   // set fields
+  fEncoding = SML_UNDEF;
   fLocalAbortReason = true; // unless set otherwise 
   fAbortReasonStatus = 0;
   fSessionIsBusy = false; // not busy by default
@@ -936,7 +945,10 @@ TSyncSession::TSyncSession(
        // use separate output for session logs  
     fSessionLogger.installOutput(getSyncAppBase()->newDbgOutputter(false)); // install the output object (and pass ownership!)
     fSessionLogger.setDebugPath(getRootConfig()->fDebugConfig.fDebugInfoPath.c_str()); // base path
-    fSessionLogger.appendToDebugPath(TARGETID);
+    const string &name = getRootConfig()->fDebugConfig.fSessionDbgLoggerOptions.fBasename;
+    fSessionLogger.appendToDebugPath(name.empty() ?
+                                     TARGETID :
+                                     name.c_str());
     if (getRootConfig()->fDebugConfig.fSingleSessionLog) {
       getRootConfig()->fDebugConfig.fSessionDbgLoggerOptions.fAppend=true; // One single log - in this case, we MUST append to current log
       fSessionLogger.appendToDebugPath("_session"); // only single session log, always with the same name
@@ -972,8 +984,18 @@ TSyncSession::TSyncSession(
   if (PDEBUGTEST(DBG_HOT)) {
     // Show Session Start
     PDEBUGPRINTFX(DBG_HOT,(
-      "==== Session started with SyncML Engine Version %d.%d.%d.%d",
-      SYSYNC_VERSION_MAJOR,
+      "==== %s Session started with SyncML (%s) Engine Version %d.%d.%d.%d",
+      IS_SERVER ? "Server" : "Client",
+      #ifdef SYSYNC_SERVER
+      "Server"
+      #endif
+      #if defined(SYSYNC_SERVER) && defined(SYSYNC_CLIENT)
+      "+"
+      #endif
+      #ifdef SYSYNC_CLIENT
+      "Client"
+      #endif
+      , SYSYNC_VERSION_MAJOR,
       SYSYNC_VERSION_MINOR,
       SYSYNC_SUBVERSION,
       SYSYNC_BUILDNUMBER
@@ -2213,7 +2235,7 @@ void TSyncSession::ContinuePackage(
     pos=aNextMessageCommands.begin();
     if (pos==aNextMessageCommands.end()) break; // done
     // take command out of the list
-    TSmlCommand *cmdP=(*pos);
+    cmdP=(*pos);
     aNextMessageCommands.erase(pos);
     // issue it (without luck, might land in the queue again --> %%% endless retry??)
     if (!issuePtr(cmdP,aNextMessageCommands,aInterruptedCommandP)) break;
@@ -2229,16 +2251,18 @@ void TSyncSession::issueHeader(bool aNoResp)
   // Start output translation before issuing outgoing header
   XMLTranslationOutgoingStart();
   #endif
-  #if defined(SYDEBUG) && defined(SYSYNC_CLIENT)
-  // for client, document exchange starts with outgoing message
-  // but for server, SyncML_Outgoing is started before SyncML_Incoming, as SyncML_Incoming ends first
-  PDEBUGBLOCKDESC("SyncML_Outgoing","start of new outgoing message");
-  PDEBUGPRINTFX(DBG_HOT,("=================> Started new outgoing message"));
-  #endif
-  #if defined(EXPIRES_AFTER_DATE) && defined(SYSYNC_CLIENT)
-  // set 1/4 of the date here
-  fCopyOfScrambledNow=((getSyncAppBase()->fScrambledNow)<<2)+503; // scramble again a little
-  #endif
+  if (IS_CLIENT) {
+         #ifdef SYDEBUG
+    // for client, document exchange starts with outgoing message
+    // but for server, SyncML_Outgoing is started before SyncML_Incoming, as SyncML_Incoming ends first
+    PDEBUGBLOCKDESC("SyncML_Outgoing","start of new outgoing message");
+    PDEBUGPRINTFX(DBG_HOT,("=================> Started new outgoing message"));
+    #endif
+    #ifdef EXPIRES_AFTER_DATE
+    // set 1/4 of the date here
+    fCopyOfScrambledNow=((getSyncAppBase()->fScrambledNow)<<2)+503; // scramble again a little
+    #endif
+  }
   // create and send response header
   TSyncHeader *syncheaderP;
   MP_NEW(syncheaderP,DBG_OBJINST,"TSyncHeader",TSyncHeader(this,aNoResp));
@@ -2510,9 +2534,9 @@ Ret_t TSyncSession::processHeader(TSyncHeader *aSyncHdrP)
                 // there was at least one queued syncend executed AFTER end of incoming sync package
                 // This means that we must finalize the sync-from-remote phase for the datastores here
                 // (as it was suppressed when the incoming sync package had ended)
-                TLocalDataStorePContainer::iterator pos;
-                for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
-                  (*pos)->engEndOfSyncFromRemote(true);
+                TLocalDataStorePContainer::iterator dspos;
+                for (dspos=fLocalDataStores.begin(); dspos!=fLocalDataStores.end(); ++dspos) {
+                  (*dspos)->engEndOfSyncFromRemote(true);
                 }
               }
               else {
@@ -2521,10 +2545,10 @@ Ret_t TSyncSession::processHeader(TSyncHeader *aSyncHdrP)
               // now issue next package commands if any
               if (fNewOutgoingPackage) {
                 PDEBUGPRINTFX(DBG_SESSION,("New package: Sending %ld commands that were generated earlier for this package",(long)fNextPackageCommands.size()));
-                TSmlCommandPContainer::iterator pos;
-                for (pos=fNextPackageCommands.begin(); pos!=fNextPackageCommands.end(); pos++) {
+                TSmlCommandPContainer::iterator nppos;
+                for (nppos=fNextPackageCommands.begin(); nppos!=fNextPackageCommands.end(); nppos++) {
                   // issue it (might land in NextMessageCommands)
-                  issueRootPtr((*pos));
+                  issueRootPtr((*nppos));
                 }
                 // done sending next package commands
                 fNextPackageCommands.clear(); // clear list
@@ -2845,60 +2869,61 @@ void TSyncSession::nextMessageRequest(void)
 {
   // count the request
   fNextMessageRequests++;
-  #ifndef SYSYNC_CLIENT
-  // check if we have seen many requests but could not fulfil them
-  if (fNextMessageRequests>3) {
-    // check for resume that does not send us an empty Sync (Symbian client at TestFest 16)
-    PDEBUGPRINTFX(DBG_ERROR,("Warning: More than 3 consecutive Alert 222 - looks like endless loop, check if we need to work around client implementation issues"));
-    // - check datastores
-    TLocalDataStorePContainer::iterator pos;
-    for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
-      // see if it is currently resuming
-      TLocalEngineDS *ldsP = (*pos);
-      if (ldsP->isResuming() && ldsP->getDSState()<dssta_serverseenclientmods) {
-        // fake empty <sync> from client to get things going again
-        // - create it
-        SmlSyncPtr_t fakeSyncCmdP = (SmlSyncPtr_t)smlLibMalloc(sizeof(SmlSync_t));
-        fakeSyncCmdP->elementType = SML_PE_SYNC_START;
-        fakeSyncCmdP->cmdID=NULL; // none needed here
-        fakeSyncCmdP->flags=0; // none
-        fakeSyncCmdP->cred=NULL;
-        fakeSyncCmdP->target=newLocation(ldsP->getName()); // client would target myself
-        fakeSyncCmdP->source=newLocation(ldsP->getRemoteDBPath()); // client would target myself
-        fakeSyncCmdP->meta=NULL; // no meta
-        fakeSyncCmdP->noc=NULL; // no NOC
-        // - have it processed like it was a real command
-        PDEBUGPRINTFX(DBG_HOT+DBG_PROTO,("Probably client expects resume to continue without sending an empty <Sync> -> simulate one"));
-        PDEBUGBLOCKFMT((
-          "Resume_Sim_Sync","Simulated empty sync to get resume going",
-          "datastore=%s",
-          ldsP->getName()
-        ));
-        TStatusCommand *fakeStatusCmdP = new TStatusCommand(this);
-        bool queueforlater=false;
-        bool ok=processSyncStart(
-          fakeSyncCmdP,
-          *fakeStatusCmdP,
-          queueforlater // will be set if command must be queued for later re-execution
-        );
-        if (!queueforlater) {
-          fNextMessageRequests=0; // reset that counter
-          // and make sure we advance the sync session state
-          // - now the real ugly hacking starts - we have to fake receiving a <final/>
-          fFakeFinalFlag=true;
-        }
-        else {
-          PDEBUGPRINTFX(DBG_ERROR,("simulated <Sync> can't be processed now, we'll try again later"));
+  if (IS_SERVER) {
+    // check if we have seen many requests but could not fulfil them
+    if (fNextMessageRequests>3) {
+      // check for resume that does not send us an empty Sync (Symbian client at TestFest 16)
+      PDEBUGPRINTFX(DBG_ERROR,("Warning: More than 3 consecutive Alert 222 - looks like endless loop, check if we need to work around client implementation issues"));
+      // - check datastores
+      TLocalDataStorePContainer::iterator pos;
+      for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
+        // see if it is currently resuming
+        TLocalEngineDS *ldsP = (*pos);
+        if (ldsP->isResuming() && ldsP->getDSState()<dssta_serverseenclientmods) {
+          // fake empty <sync> from client to get things going again
+          // - create it
+          SmlSyncPtr_t fakeSyncCmdP = (SmlSyncPtr_t)smlLibMalloc(sizeof(SmlSync_t));
+          fakeSyncCmdP->elementType = SML_PE_SYNC_START;
+          fakeSyncCmdP->cmdID=NULL; // none needed here
+          fakeSyncCmdP->flags=0; // none
+          fakeSyncCmdP->cred=NULL;
+          fakeSyncCmdP->target=newLocation(ldsP->getName()); // client would target myself
+          fakeSyncCmdP->source=newLocation(ldsP->getRemoteDBPath()); // client would target myself
+          fakeSyncCmdP->meta=NULL; // no meta
+          fakeSyncCmdP->noc=NULL; // no NOC
+          // - have it processed like it was a real command
+          PDEBUGPRINTFX(DBG_HOT+DBG_PROTO,("Probably client expects resume to continue without sending an empty <Sync> -> simulate one"));
+          PDEBUGBLOCKFMT((
+            "Resume_Sim_Sync","Simulated empty sync to get resume going",
+            "datastore=%s",
+            ldsP->getName()
+          ));
+          TStatusCommand *fakeStatusCmdP = new TStatusCommand(this);
+          bool queueforlater=false;
+          /* bool ok= */
+          processSyncStart(
+            fakeSyncCmdP,
+            *fakeStatusCmdP,
+            queueforlater // will be set if command must be queued for later re-execution
+          );
+          if (!queueforlater) {
+            fNextMessageRequests=0; // reset that counter
+            // and make sure we advance the sync session state
+            // - now the real ugly hacking starts - we have to fake receiving a <final/>
+            fFakeFinalFlag=true;
+          }
+          else {
+            PDEBUGPRINTFX(DBG_ERROR,("simulated <Sync> can't be processed now, we'll try again later"));
+          }
+          // now just simulate a </sync>
+          processSyncEnd(queueforlater);
+          // now let this particular datastore "know" that sync-from-client is over now
+          (*pos)->engEndOfSyncFromRemote(true); // fake "final"
+          PDEBUGENDBLOCK("Resume_Sim_Sync");
         }
-        // now just simulate a </sync>
-        processSyncEnd(queueforlater);
-        // now let this particular datastore "know" that sync-from-client is over now
-        (*pos)->engEndOfSyncFromRemote(true); // fake "final"
-        PDEBUGENDBLOCK("Resume_Sim_Sync");
       }
     }
-  }
-  #endif // SYSYNC_CLIENT
+  } // server
 } // TSyncSession::nextMessageRequest
 
 
@@ -3033,6 +3058,16 @@ void TSyncSession::addEncoding(string &aString)
 } // TSyncSession::addEncoding
 
 
+// set encoding for session
+void TSyncSession::setEncoding(SmlEncoding_t aEncoding)
+{
+  Ret_t err=smlSetEncoding(fSmlWorkspaceID,aEncoding);
+  if (err==SML_ERR_OK) {
+       fEncoding = aEncoding;
+  }
+} // TSyncSession::setEncoding
+
+
 // find remote datastore by (remote party specified) URI
 TRemoteDataStore *TSyncSession::findRemoteDataStore(const char *aDatastoreURI)
 {
@@ -3172,7 +3207,7 @@ SmlDevInfDatastoreListPtr_t TSyncSession::newDevInfDataStoreList(bool aAlertedOn
         continue; // not alerted, do not show this one
     }
     // see if we have info at all
-    datastoreP = (*pos1)->getDatastoreDevinf(IsServerSession(), aWithoutCTCapProps);
+    datastoreP = (*pos1)->getDatastoreDevinf(IS_SERVER, aWithoutCTCapProps);
     if (datastoreP) {
       // create new list item
       (*insertpos) = SML_NEW(SmlDevInfDatastoreList_t);
@@ -3502,7 +3537,7 @@ done:
 } // TSyncSession::analyzeRemoteDevInf
 
 
-#ifndef SYSYNC_CLIENT
+#ifdef SYSYNC_SERVER
 
 // Initialize Sync: set up datastores and types for server sync session
 localstatus TSyncSession::initSync(
@@ -3534,9 +3569,9 @@ localstatus TSyncSession::initSync(
   #endif
   #ifdef OBJECT_FILTERING
   if (sta==LOCERR_OK) {
-    // %%% parse DS 1.2 <filter>
-    #if !defined _MSC_VER || defined WINCE
-    #warning "tbd%%%:  parse <filter>"
+    // %%% check for DS 1.2 <filter> in <Sync> command as well (we do parse <filter> in <Alert> already)
+    #if (!defined _MSC_VER || defined WINCE) && !defined(__GNUC__)
+    #warning "tbd %%%: check for DS 1.2 <filter> in <Sync> command as well (we do parse <filter> in <Alert> already)"
     #endif
   }
   #endif
@@ -3560,7 +3595,7 @@ localstatus TSyncSession::initSync(
   return sta;
 } // TSyncSession::initSync
 
-#endif // not SYSYNC_CLIENT
+#endif // SYSYNC_SERVER
 
 
 
@@ -3976,13 +4011,13 @@ bool TSyncSession::checkCredentials(const char *aUserName, const SmlCredPtr_t aC
     SYSYNC_SUBVERSION,
     SYSYNC_BUILDNUMBER
   ));
-  #ifndef SYSYNC_CLIENT
-  PDEBUGPRINTFX(DBG_HOT,(
-    "==== SyncML URL used = '%s', username as sent by remote = '%s'",
-    fInitialLocalURI.c_str(),
-    fSyncUserName.c_str()
-  ));
-  #endif
+  if (IS_SERVER) {
+    PDEBUGPRINTFX(DBG_HOT,(
+      "==== SyncML URL used = '%s', username as sent by remote = '%s'",
+      fInitialLocalURI.c_str(),
+      fSyncUserName.c_str()
+    ));
+  } // server
   // return result
   return authok;
 } // TSyncSession::checkCredentials(SmlCredPtr_t...)
@@ -4374,14 +4409,15 @@ localstatus TSyncSession::checkRemoteSpecifics(SmlDevInfDevInfPtr_t aDevInfP)
       fRemoteDescName += " (no devInf)";
       // switch on legacy behaviour (conservative preferred types)
       fLegacyMode = true;
-      #ifdef SYSYNC_CLIENT
-      // Client case
-      fRemoteCanHandleUTC = true; // Assume server can handle UTC (it is very improbable a server can't)
-      #else
-      // Server case
-      fRemoteCanHandleUTC = fSyncMLVersion==syncml_vers_1_0 ? true : false; // Assume client cannot handle UTC (it is likely a client can't, or at least can't properly, so localtime is safer)
-      fLimitedRemoteFieldLengths = true; // assume limited client field length (almost all clients have limited length)
-      #endif
+      if (IS_CLIENT) {
+        // Client case
+        fRemoteCanHandleUTC = true; // Assume server can handle UTC (it is very improbable a server can't)
+      }
+      else {
+        // Server case
+        fRemoteCanHandleUTC = fSyncMLVersion==syncml_vers_1_0 ? true : false; // Assume client cannot handle UTC (it is likely a client can't, or at least can't properly, so localtime is safer)
+        fLimitedRemoteFieldLengths = true; // assume limited client field length (almost all clients have limited length)
+      }
     }
   }
   // show summary
@@ -4698,10 +4734,10 @@ TSmlCommand *TSyncSession::processAlertItem(
         );
         // echo next anchor sent with item back in status
         // %%% specs say that only next anchor must be echoed, SCTS echoes both
-        SmlItemPtr_t aItemP = newItem(); // empty item
+        SmlItemPtr_t itemP = newItem(); // empty item
         // NOTE: anchor is MetInf, but is echoed in DATA part of item, not META!
-        aItemP->data = newMetaAnchor(nextRemoteAnchor,NULL); // only next (like specs)
-        aStatusCommand.addItem(aItemP); // add it to status
+        itemP->data = newMetaAnchor(nextRemoteAnchor,NULL); // only next (like specs)
+        aStatusCommand.addItem(itemP); // add it to status
       }
       break;
     case 224 :
@@ -5029,21 +5065,23 @@ Ret_t TSyncSession::StartMessage(SmlSyncHdrPtr_t aContentP)
   fMessageRetried = false; // we assume no message retry
   MP_SHOWCURRENT(DBG_PROFILE,"Start of incoming Message");
   TP_START(fTPInfo,TP_general); // could be new thread
-  #if defined(EXPIRES_AFTER_DATE) && !defined(SYSYNC_CLIENT)
-  // set 1/4 of the date here
-  fCopyOfScrambledNow=((getSyncAppBase()->fScrambledNow)<<2)+503; // scramble again a little
-  #endif
+  #ifdef EXPIRES_AFTER_DATE
+  if (IS_SERVER) {
+    // set 1/4 of the date here
+    fCopyOfScrambledNow=((getSyncAppBase()->fScrambledNow)<<2)+503; // scramble again a little
+  }
+  #endif // EXPIRES_AFTER_DATE
   // dump it if configured
   // Note: this must happen here before answer writing to the instance buffer starts, as otherwise
   //       the already consumed part of the buffer might get overwritten (the SyncML message header in this case).
   #ifdef SYDEBUG
   DumpSyncMLMessage(false); // incoming
   #endif
-  #ifndef SYSYNC_CLIENT
-  // for server, SyncML_Outgoing is started here, as SyncML_Incoming ends before SyncML_Outgoing
-  // but for client, document exchange starts with outgoing message
-  PDEBUGBLOCKDESC("SyncML_Outgoing","preparing for response before starting to analyze new incoming message");
-  #endif
+  if (IS_SERVER) {
+    // for server, SyncML_Outgoing is started here, as SyncML_Incoming ends before SyncML_Outgoing
+    // but for client, document exchange starts with outgoing message
+    PDEBUGBLOCKDESC("SyncML_Outgoing","preparing for response before starting to analyze new incoming message");
+  }
   PDEBUGBLOCKFMT(("SyncML_Incoming","Starting to analyze incoming message",
     "RequestNo=%ld|SySyncVers=%d.%d.%d.%d",(long)fSyncAppBaseP->requestCount(),
     SYSYNC_VERSION_MAJOR,
index 65960f2..1858e70 100755 (executable)
@@ -75,6 +75,7 @@ class TRootConfig;
 
 
 #ifdef SCRIPT_SUPPORT
+
 // publish as derivates might need it
 extern const TFuncTable ErrorFuncTable;
 
@@ -94,7 +95,9 @@ typedef struct {
   string itemData;
   string metaType;
 } TGetPutResultFuncContext;
-#endif
+
+#endif // SCRIPT_SUPPORT
+
 
 #ifndef NO_REMOTE_RULES
 
@@ -160,12 +163,12 @@ protected:
 
 typedef std::list<TRemoteRuleConfig *> TRemoteRulesList;
 
-#endif
+#endif // NO_REMOTE_RULES
 
 // session config
-class TSessionConfig: public TAgentConfig
+class TSessionConfig: public TConfigElement
 {
-  typedef TAgentConfig inherited;
+  typedef TConfigElement inherited;
 public:
   TSessionConfig(const char *aElementName, TConfigElement *aParentElementP);
   virtual ~TSessionConfig();
@@ -245,6 +248,11 @@ public:
   // public methods
   TLocalDSConfig *getLocalDS(const char *aName, uInt32 aDBTypeID=0);
   lineartime_t getSessionTimeout(void) { return fSessionTimeout * secondToLinearTimeFactor; };
+  // - MUST be called after creating config to load (or pre-load) variable parts of config
+  //   such as binfile profiles. If aDoLoose==false, situations, where existing config
+  //   is detected but cannot be re-used will return an error. With aDoLoose==true, config
+  //   files etc. are created even if it means a loss of data.
+  virtual localstatus loadVarConfig(bool aDoLoose=false) { return LOCERR_OK; }
 protected:
   // check config elements
   #ifndef HARDCODED_CONFIG
@@ -325,6 +333,7 @@ public:
   InstanceID_t getSmlWorkspaceID(void) { return fSmlWorkspaceID; };
   const char *getEncodingName(void); // encoding suffix in MIME type
   SmlEncoding_t getEncoding(void) { return fEncoding; }; // current encoding
+  void setEncoding(SmlEncoding_t aEncoding); // set encoding for session
   void addEncoding(string &aString); // add current encoding spec to given (type-)string
   sInt32 getSmlWorkspaceFreeBytes(void) { return ((sInt32) smlGetFreeBuffer(fSmlWorkspaceID)); };
   #ifdef ENGINEINTERFACE_SUPPORT
@@ -367,8 +376,6 @@ public:
   void setSessionBusy(bool aBusy) { fSessionIsBusy=aBusy; }; // make session behave busy generally
   bool getReadOnly(void) { return fReadOnly; }; // read-only option
   void setReadOnly(bool aReadOnly) { fReadOnly=aReadOnly; }; // read-only option
-  // info about session
-  virtual bool IsServerSession(void) = 0;
   // - check if we can handle UTC time (devices without time zone might override this)
   virtual bool canHandleUTC(void) { return true; }; // assume yes
   // helpers
@@ -755,8 +762,6 @@ protected:
   virtual string getDeviceType(void)=0; // abstract, must be client or server
   // - get new response URI to be sent to remote party for subsequent messages TO local party
   virtual SmlPcdataPtr_t newResponseURIForRemote(void) { return NULL; }; // no RespURI by default
-  // - URI to send outgoing message to
-  virtual const char *getSendURI(void) { return ""; }; // none by default (and server)
   // Authorisation
   // - required authentication type and mode
   virtual TAuthTypes requestedAuthType(void) = 0; // get preferred authentication type for authentication of remote party
@@ -768,6 +773,8 @@ protected:
   // - generate credentials (based on fRemoteNonce, fRemoteRequestedAuth, fRemoteRequestedAuthEnc)
   SmlCredPtr_t newCredentials(const char *aUser, const char *aPassword);
 public:
+  // - URI to send outgoing message to
+  virtual const char *getSendURI(void) { return ""; }; // none by default (and server)
   // - get common sync capabilities mask of this session (datastores might modify it)
   virtual uInt32 getSyncCapMask(void);
   // - check credentials, login to server
index b0204f7..7efc1e1 100755 (executable)
@@ -93,9 +93,9 @@ bool TSyncSessionHandle::TerminateSession(uInt16 aStatusCode)
 #ifdef SYSYNC_TOOL
 
 // get or create a session for use with the diagnostic tool
-TSyncServer *TSyncSessionDispatch::getSySyToolSession(void)
+TSyncAgent *TSyncSessionDispatch::getSySyToolSession(void)
 {
-  TSyncServer *sessionP=NULL; // the session (new or existing found in fSessions)
+  TSyncAgent *sessionP=NULL; // the session (new or existing found in fSessions)
 
   if (fToolSessionHP) {
     sessionP = fToolSessionHP->fSessionP;
@@ -103,7 +103,7 @@ TSyncServer *TSyncSessionDispatch::getSySyToolSession(void)
   else {
     // - create session object with given ID
     fToolSessionHP = CreateSessionHandle();
-    sessionP = static_cast<TServerConfig *>(fConfigP->fAgentConfigP)->CreateServerSession(fToolSessionHP,"SySyTool");
+    sessionP = static_cast<TAgentConfig *>(fConfigP->fAgentConfigP)->CreateServerSession(fToolSessionHP,"SySyTool");
     fToolSessionHP->fSessionP=sessionP;
   }
   return sessionP;
@@ -117,6 +117,9 @@ TSyncServer *TSyncSessionDispatch::getSySyToolSession(void)
 TSyncSessionDispatch::TSyncSessionDispatch() :
   TSyncAppBase()
 {
+  // this is a server engine
+  fIsServer = true;
+  // other init
   #ifdef SYSYNC_TOOL
   fToolSessionHP=NULL; // no tool session yet
   #endif
@@ -177,7 +180,7 @@ Ret_t TSyncSessionDispatch::StartMessage(
   VoidPtr_t aUserData, // user data, contains NULL or char* to transport-layer supported session ID
   SmlSyncHdrPtr_t aContentP // SyncML tookit's decoded form of the <SyncHdr> element
 ) {
-  TSyncServer *sessionP=NULL; // the session (new or existing found in fSessions)
+  TSyncAgent *sessionP=NULL; // the session (new or existing found in fSessions)
   TSyncSessionHandle *sessionHP=NULL;
   Ret_t err;
 
@@ -347,12 +350,12 @@ Ret_t TSyncSessionDispatch::StartMessage(
 /// @note session list must be locked before call!
 void TSyncSessionDispatch::collectTimedOutSessions(TSyncSessionHandlePList &aDeletableSessions)
 {
-  TSyncServer *sessionP=NULL; // the session (new or existing found in fSessions)
+  TSyncAgent *sessionP=NULL; // the session (new or existing found in fSessions)
   TSyncSessionHandle *sessionHP=NULL;
-  TServerConfig *serverconfigP=NULL;
+  TAgentConfig *serverconfigP=NULL;
 
   // get agent config
-  GET_CASTED_PTR(serverconfigP,TServerConfig,fConfigP->fAgentConfigP,"missing agent (server) config");
+  GET_CASTED_PTR(serverconfigP,TAgentConfig,fConfigP->fAgentConfigP,"missing agent (server) config");
   // - find timed-out sessions and count sessions not belonging to this client
   TSyncSessionHandlePContainer::iterator pos;
   for (pos=fSessions.begin();pos!=fSessions.end();pos++) {
@@ -393,12 +396,12 @@ void TSyncSessionDispatch::collectTimedOutSessions(TSyncSessionHandlePList &aDel
 /// - intended for implementations without a session thread (XPT, ISAPI, not pipe)
 void TSyncSessionDispatch::deleteListedSessions(TSyncSessionHandlePList &aDelSessionList)
 {
-  TSyncServer *sessionP=NULL;
+  TSyncAgent *sessionP=NULL;
   TSyncSessionHandle *sessionHP=NULL;
-  TServerConfig *serverconfigP=NULL;
+  TAgentConfig *serverconfigP=NULL;
 
   // get agent config
-  GET_CASTED_PTR(serverconfigP,TServerConfig,fConfigP->fAgentConfigP,"missing agent (server) config");
+  GET_CASTED_PTR(serverconfigP,TAgentConfig,fConfigP->fAgentConfigP,"missing agent (server) config");
 
   TSyncSessionHandlePList::iterator delpos;
   for (delpos=aDelSessionList.begin();delpos!=aDelSessionList.end();delpos++) {
@@ -460,9 +463,9 @@ void TSyncSessionDispatch::deleteListedSessions(TSyncSessionHandlePList &aDelSes
 /// @param aPredefinedSessionID : predefined sessionID, if NULL, internal ID will be generated
 TSyncSessionHandle *TSyncSessionDispatch::CreateAndEnterServerSession(cAppCharP aPredefinedSessionID)
 {
-  TSyncServer *sessionP=NULL; // the session (new or existing found in fSessions)
+  TSyncAgent *sessionP=NULL; // the session (new or existing found in fSessions)
   TSyncSessionHandle *sessionHP=NULL;
-  TServerConfig *serverconfigP=NULL;
+  TAgentConfig *serverconfigP=NULL;
 
   // - create new session instance
   //   NOTE: session list is unlocked here already
@@ -517,7 +520,7 @@ TSyncSessionHandle *TSyncSessionDispatch::CreateAndEnterServerSession(cAppCharP
           time(NULL);
         sid =
           ((sid >> 16) & 0xFFFF) + ((sid << 47) & 0x7FFF000000000000LL) + // aaaa00000000dddd
-          (((uInt32)sessionHP) << 16); // 0000bbbbcccc0000
+          ((((uIntPtr)sessionHP)&0xFFFFFFFF) << 16); // 0000bbbbcccc0000
         // - make a string of it
         StringObjPrintf(SessionIDString,"%lld",sid);
       }
@@ -532,7 +535,7 @@ TSyncSessionHandle *TSyncSessionDispatch::CreateAndEnterServerSession(cAppCharP
       #endif
       #endif
       // - create session object with given ID
-      sessionP = static_cast<TServerConfig *>(fConfigP->fAgentConfigP)->CreateServerSession(sessionHP,SessionIDString.c_str());
+      sessionP = static_cast<TAgentConfig *>(fConfigP->fAgentConfigP)->CreateServerSession(sessionHP,SessionIDString.c_str());
       sessionHP->fSessionP=sessionP;
       // debug
       PDEBUGPRINTFX(DBG_HOT,(
@@ -576,7 +579,7 @@ TSyncSessionHandle *TSyncSessionDispatch::CreateAndEnterServerSession(cAppCharP
 // cleaning up the session if needed
 Ret_t TSyncSessionDispatch::EndRequest(InstanceID_t aSmlWorkspaceID, bool &aHasData, string &aRespURI, bool &aEOSession, uInt32 aReqBytes)
 {
-  TSyncServer *serverSessionP=NULL; // the session
+  TSyncAgent *serverSessionP=NULL; // the session
   Ret_t err;
 
   // In case of a totally wrong request, this method may be
@@ -588,10 +591,10 @@ Ret_t TSyncSessionDispatch::EndRequest(InstanceID_t aSmlWorkspaceID, bool &aHasD
       // Important: instance and session must remain attached until session either continues
       //            running or is deleted.
       // Normal case: there IS a session attached
-      DEBUGPRINTFX(DBG_SESSION,("Request ended with session attached, calling TSyncServer::EndRequest"));
+      DEBUGPRINTFX(DBG_SESSION,("Request ended with session attached, calling TSyncAgent::EndRequest"));
       if (serverSessionP->EndRequest(aHasData,aRespURI,aReqBytes)) {
         // TSyncSession::EndRequest returns true when session is done and must be removed
-        PDEBUGPRINTFX(DBG_SESSION,("TSyncServer::EndRequest returned true -> terminating and deleting session now"));
+        PDEBUGPRINTFX(DBG_SESSION,("TSyncAgent::EndRequest returned true -> terminating and deleting session now"));
         // - take session out of session list
         LockSessions();
         TSyncSessionHandle *sessionHP = RemoveSession(serverSessionP);
@@ -617,7 +620,7 @@ Ret_t TSyncSessionDispatch::EndRequest(InstanceID_t aSmlWorkspaceID, bool &aHasD
       }
       else {
         // session is not finished, just leave lock as next message might come from another thread
-        PDEBUGPRINTFX(DBG_SESSION,("TSyncServer::EndRequest returned false -> just leave session"));
+        PDEBUGPRINTFX(DBG_SESSION,("TSyncAgent::EndRequest returned false -> just leave session"));
         serverSessionP->getSessionHandle()->LeaveSession();
         aEOSession=false; // session does not end
         // remove session's reference to this workspace as next request might be decoded in a different workspace
@@ -694,7 +697,7 @@ void TSyncSessionDispatch::dbgListSessions(void)
 // buffer answer in the session's buffer if instance still has a session attached at all
 Ret_t TSyncSessionDispatch::bufferAnswer(InstanceID_t aSmlWorkspaceID, MemPtr_t aAnswer, MemSize_t aAnswerSize)
 {
-  TSyncServer *serverSessionP=NULL; // the session
+  TSyncAgent *serverSessionP=NULL; // the session
   Ret_t err;
 
   err=getSmlInstanceUserData(aSmlWorkspaceID,(void **)&serverSessionP);
@@ -709,7 +712,7 @@ Ret_t TSyncSessionDispatch::bufferAnswer(InstanceID_t aSmlWorkspaceID, MemPtr_t
 // get buffered answer from the session's buffer if there is any
 void TSyncSessionDispatch::getBufferedAnswer(InstanceID_t aSmlWorkspaceID, MemPtr_t &aAnswer, MemSize_t &aAnswerSize)
 {
-  TSyncServer *serverSessionP=NULL; // the session
+  TSyncAgent *serverSessionP=NULL; // the session
   Ret_t err;
 
   err=getSmlInstanceUserData(aSmlWorkspaceID,(void **)&serverSessionP);
@@ -732,7 +735,7 @@ void TSyncSessionDispatch::getBufferedAnswer(InstanceID_t aSmlWorkspaceID, MemPt
 // Note: may not be called when session list is already locked
 void TSyncSessionDispatch::KillSessionByInstance(InstanceID_t aSmlWorkspaceID, uInt16 aStatusCode, const char *aMsg, uInt32 aErrorCode)
 {
-  TSyncServer *sessionP;
+  TSyncAgent *sessionP;
 
   // In case of a totally bad request, this method may be
   // called when no session is attached to the smlWorkspace
@@ -750,7 +753,7 @@ void TSyncSessionDispatch::KillSessionByInstance(InstanceID_t aSmlWorkspaceID, u
 
 // remove and kill session
 // Note: may not be called when session list is already locked
-void TSyncSessionDispatch::KillServerSession(TSyncServer *aSessionP, uInt16 aStatusCode, const char *aMsg, uInt32 aErrorCode)
+void TSyncSessionDispatch::KillServerSession(TSyncAgent *aSessionP, uInt16 aStatusCode, const char *aMsg, uInt32 aErrorCode)
 {
   if (aSessionP) {
     LockSessions();
@@ -849,7 +852,7 @@ Ret_t TSyncSessionDispatch::HandleDecodingException(TSyncSession *aSessionP, con
   #endif
   // try to kill session
   DEBUGPRINTFX(DBG_SESSION,("******** Exception aborts session: calling KillServerSession"));
-  KillServerSession(static_cast<TSyncServer *>(aSessionP),412,"Decoding Exception");
+  KillServerSession(static_cast<TSyncAgent *>(aSessionP),412,"Decoding Exception");
   // return error
   DEBUGPRINTFX(DBG_SESSION,("******** Exception: returning SML_ERR_UNSPECIFIC to abort smlProcessData"));
   return SML_ERR_UNSPECIFIC;
index 303e753..5565371 100755 (executable)
@@ -14,7 +14,7 @@
 // general includes (SyncML tookit, windows, Clib)
 #include "sysync.h"
 #include "syncappbase.h"
-#include "syncserver.h"
+#include "syncagent.h"
 
 
 
@@ -22,7 +22,7 @@ namespace sysync {
 
 // forward declarations
 class TSyncSession;
-class TSyncServer;
+class TSyncAgent;
 class TSyncSessionDispatch;
 
 
@@ -31,7 +31,7 @@ class TSyncSessionDispatch;
 class TSyncSessionHandle {
 public:
   // the session
-  TSyncServer * fSessionP;
+  TSyncAgent * fSessionP;
   // the app base
   TSyncAppBase * fAppBaseP;
   // - used for counting session for session limiting
@@ -114,7 +114,7 @@ public:
   sInt32 numSessions(void) { return fSessions.size(); };
   #ifdef SYSYNC_TOOL
   // get or create a session for use with the diagnostic tool
-  TSyncServer *getSySyToolSession(void);
+  TSyncAgent *getSySyToolSession(void);
   #endif
 protected:
   // must be implemented in derived class to make access to
@@ -126,7 +126,7 @@ protected:
   TSyncSessionHandle *RemoveSession(TSyncSession *aSessionP) throw();
   // remove and kill session
   // Note: may not be called when session list is already locked
-  void KillServerSession(TSyncServer *aSessionP, uInt16 aStatusCode, const char *aMsg=NULL, uInt32 aErrorCode=0); // by pointer
+  void KillServerSession(TSyncAgent *aSessionP, uInt16 aStatusCode, const char *aMsg=NULL, uInt32 aErrorCode=0); // by pointer
   void KillSessionByInstance(InstanceID_t aSmlWorkspaceID, uInt16 aStatusCode, const char *aMsg=NULL, uInt32 aErrorCode=0); // by SyncML toolkit instance ID
   // Handle exception happening while decoding commands for a session
   virtual Ret_t HandleDecodingException(TSyncSession *aSessionP, const char *aRoutine, exception *aExceptionP=NULL);
index 467e544..b31f6c0 100644 (file)
@@ -92,6 +92,7 @@ namespace sysync {
 #define SYSER_PRODCODE_CLIENT_LIB_WM           22 // for Windows Mobile
 #define SYSER_PRODCODE_CLIENT_LIB_PALM         23 // for PALMOS
 #define SYSER_PRODCODE_CLIENT_LIB_IPHONEOS  28 // iPhone OS
+#define SYSER_PRODCODE_CLIENT_LIB_ANDROID   40 // Android
 
 
 #define SYSER_PRODCODE_CLIENT_LIB_ALL          24 // ALL Platforms
@@ -108,13 +109,14 @@ namespace sysync {
 // Servers
 
 // - Server Libraries
-#define SYSER_PRODCODE_SERVER_LIB_WIN32        28 // Win32 ODBC PRO
+#define SYSER_PRODCODE_SERVER_LIB_WIN32        39 // Win32 ODBC PRO
 #define SYSER_PRODCODE_SERVER_LIB_MACOSX       29 // for Mac OS X
 #define SYSER_PRODCODE_SERVER_LIB_LINUX        30 // for Linux
 #define SYSER_PRODCODE_SERVER_LIB_SYMBIAN      31 // for Symbian
 #define SYSER_PRODCODE_SERVER_LIB_WM           32 // for Windows Mobile
 #define SYSER_PRODCODE_SERVER_LIB_PALM         33 // for PALMOS
 #define SYSER_PRODCODE_SERVER_LIB_IPHONEOS  38 // iPhone OS
+#define SYSER_PRODCODE_SERVER_LIB_ANDROID   41 // Android
 
 
 #define SYSER_PRODCODE_SERVER_LIB_ALL          34 // ALL Platforms
index d98fa1b..184a47f 100755 (executable)
@@ -49,13 +49,12 @@ typedef TSyError localstatus;
 #define DEFAULT_CLIENTSESSIONTIMEOUT 20 // 20 seconds
 
 // - log file format: datastore
-#ifdef SYSYNC_CLIENT
-  #define DEFAULT_LOG_LABELS "SyncEndTime\tUser\tSyncMLVers\tStatus\tSynctype\tSessionID\tRemote ID\tRemote Name\tRemote VersInfo\tDatastore\tLocAdded\tLocUpdated\tLocDeleted\tLocErrors\tRemAdded\tRemUpdated\tRemDeleted\tRemErrors\tBytesOut\tBytesIn\n\n"
-  #define DEFAULT_LOG_FORMAT "%seT\t%U\t%syV\t%sS\t%tS\t%iS\t%iR\t%nR\t%vR\t%nD\t%laI\t%luI\t%ldI\t%leI\t%raI\t%ruI\t%rdI\t%reI\t%doB\t%diB\n"
-#else
-  #define DEFAULT_LOG_LABELS "SyncEndTime\tUser\tSyncMLVers\tStatus\tSynctype\tSessionID\tRemote ID\tRemote Name\tRemote VersInfo\tDatastore\tLocAdded\tLocUpdated\tLocDeleted\tLocErrors\tRemAdded\tRemUpdated\tRemDeleted\tRemErrors\tSlowSyncMatches\tServerWon\tClientWon\tDuplicated\tBytesOut\tBytesIn\tSessionBytesOut\tSessionBytesIn\n\n"
-  #define DEFAULT_LOG_FORMAT "%seT\t%U\t%syV\t%sS\t%tS\t%iS\t%iR\t%nR\t%vR\t%nD\t%laI\t%luI\t%ldI\t%leI\t%raI\t%ruI\t%rdI\t%reI\t%smI\t%scI\t%ccI\t%dcI\t%doB\t%diB\t%toB\t%tiB\n"
-#endif
+//   - client
+#define DEFAULT_LOG_LABELS_CLIENT "SyncEndTime\tUser\tSyncMLVers\tStatus\tSynctype\tSessionID\tRemote ID\tRemote Name\tRemote VersInfo\tDatastore\tLocAdded\tLocUpdated\tLocDeleted\tLocErrors\tRemAdded\tRemUpdated\tRemDeleted\tRemErrors\tBytesOut\tBytesIn\n\n"
+#define DEFAULT_LOG_FORMAT_CLIENT "%seT\t%U\t%syV\t%sS\t%tS\t%iS\t%iR\t%nR\t%vR\t%nD\t%laI\t%luI\t%ldI\t%leI\t%raI\t%ruI\t%rdI\t%reI\t%doB\t%diB\n"
+//   - server
+#define DEFAULT_LOG_LABELS_SERVER "SyncEndTime\tUser\tSyncMLVers\tStatus\tSynctype\tSessionID\tRemote ID\tRemote Name\tRemote VersInfo\tDatastore\tLocAdded\tLocUpdated\tLocDeleted\tLocErrors\tRemAdded\tRemUpdated\tRemDeleted\tRemErrors\tSlowSyncMatches\tServerWon\tClientWon\tDuplicated\tBytesOut\tBytesIn\tSessionBytesOut\tSessionBytesIn\n\n"
+#define DEFAULT_LOG_FORMAT_SERVER "%seT\t%U\t%syV\t%sS\t%tS\t%iS\t%iR\t%nR\t%vR\t%nD\t%laI\t%luI\t%ldI\t%leI\t%raI\t%ruI\t%rdI\t%reI\t%smI\t%scI\t%ccI\t%dcI\t%doB\t%diB\t%toB\t%tiB\n"
 
 // - defines debug mask that is active by default
 #define DEFAULT_DEBUG DBG_NORMAL
@@ -130,44 +129,13 @@ typedef TSyError localstatus;
 #define CONFIG_READ_BUFSIZ 3048 // size of buffer for XML config reading
 
 
-/*
-// - maximum size of SyncML toolkit memory usage
-#ifndef SML_WORKSPACEMEM
-  // if not specified in target_options, use defaults
-  // NOTE: most clients and servers use the defaults, so be careful when changing here!
-  #ifdef SYSYNC_CLIENT
-    // client
-    //#define SML_MAXTOOLKITMEM 1000000 // 1 Megs for now
-    #define SML_WORKSPACEMEM 40000 // 40k now for DS 1.2 (we had 20k before 3.x)
-  #else
-    // server
-    //#define SML_MAXTOOLKITMEM 0 // unlimited for now
-    #define SML_WORKSPACEMEM 100000 // 100k workspace per default
-  #endif
-#endif
-
-// message size and object size constraints (0 for none)
-#ifndef SYNCML_MAXMSGSIZE
-  #define SYNCML_MAXMSGSIZE (SML_WORKSPACEMEM/2) // half of workspace size
-#endif
-#ifndef SYNCML_MAXOBJSIZE
-  #define SYNCML_MAXOBJSIZE 4000000 // 4MB should be enough
-#endif
-#if SYNCML_MAXOBJSIZE<SML_WORKSPACEMEM*2/3
-  #warning "SYNCML_MAXOBJSIZE probably too small (smaller than 2/3 of message)"
-#endif
-#if (SYNCML_MAXMSGSIZE>=SML_WORKSPACEMEM*3/4) && (SML_WORKSPACEMEM-SYNCML_MAXMSGSIZE<10000)
-  #warning "SYNCML_MAXMSGSIZE probably too big"
-#endif
-*/
-
 // Max message size
 #ifndef DEFAULT_MAXMSGSIZE
-  #ifdef SYSYNC_CLIENT
-    // client
+  #ifndef SYSYNC_SERVER
+    // only client
     #define DEFAULT_MAXMSGSIZE 20000 // 20k now for DS 1.2 (we had 10k before 3.x)
   #else
-    // server
+    // server (or server and client)
     #define DEFAULT_MAXMSGSIZE 50000 // 50k should be enough
   #endif
 #endif
@@ -183,10 +151,10 @@ typedef TSyError localstatus;
 #define SYSYNC_SERVER_DEVID "SySync Server"
 #define SYSYNC_CLIENT_DEVID "SySync Client"
 #ifndef SYNCML_SERVER_DEVTYP
-  #define SYNCML_SERVER_DEVTYP "server"; // could also be "workstation"
+  #define SYNCML_SERVER_DEVTYP "server" // could also be "workstation"
 #endif
 #ifndef SYNCML_CLIENT_DEVTYP
-  #define SYNCML_CLIENT_DEVTYP "workstation"; // general case, could also be "handheld" or "pda"...
+  #define SYNCML_CLIENT_DEVTYP "workstation" // general case, could also be "handheld" or "pda"...
 #endif
 
 // SyncML SyncCap mask bits
index 9e94740..7a32c49 100755 (executable)
@@ -8,17 +8,6 @@
 /* global includes */
 #include "target_options.h"
 
-/* compiler specifics */
-/* %%% probably obsolete
-#ifdef __BORLANDC__
-typedef __int64 longlong;
-typedef __uint64 ulonglong;
-#else if defined(_MSC_VER)
-typedef __int64 longlong;
-typedef unsigned __int64 ulonglong;
-#endif
-*/
-
 /* standard C includes */
 #ifdef __PALM_OS__
   // don't use the *.h versions! they don't work any more with CW Palm v9
index 37421c9..105db51 100755 (executable)
@@ -1185,7 +1185,6 @@ bool TTextProfileHandler::generateContent(TMultiFieldItem &aItem, TLineMapDefini
             aString+="\x0D\x0A";
             // - simply append string
             if (attfldP) {
-              string s;
               attfldP->getAsString(s);
               appendUTF8ToString(
                 s.c_str(),
index 4f9f40f..912cb9a 100644 (file)
@@ -493,6 +493,7 @@ TSyError Session_SaveNonce( CContext sContext, cAppCharP nonce )
   DEBUG_DB      ( sc->fCB, MyDB, Se_SN, "%d '%s'", sc,nonce );
 
   if (sc->fDev) { sc->fDev->fToken= nonce;
+                  sc->fDevList.fChanged= true;
     err=          sc->fDevList.SaveDB( true, sc->fCB ); // save it
   } // if
 
@@ -1127,13 +1128,13 @@ TSyError InsertItem( CContext aContext, cAppCharP aItemData, ItemID newID )
   string   newItemID;
   TDBItem* act;
 
-  ItemID_Struct a; a.item  = "";
-                   a.parent= newID->parent; if (!a.parent) a.parent= "";
+  ItemID_Struct a; a.item  = (appCharP)"";
+                   a.parent= newID->parent; if (!a.parent) a.parent= (appCharP)"";
 
   TSyError err= ac->fItemList.CreateEmptyItem( &a, newItemID, act, ac->fNewID );
 
-  if (err) a.item= "???"; // undefined
-  else     a.item= (char*)newItemID.c_str();
+  if (err) a.item= (appCharP)"???"; // undefined
+  else     a.item= (appCharP)newItemID.c_str();
   string   s= ItemID_Info( &a );
 
   DEBUG_DB( ac->fCB, MyDB,Da_II, "%s '%s' err=%d", s.c_str(), aItemData, err );
index 3bf3b07..3932e92 100755 (executable)
@@ -44,9 +44,9 @@ CVersion Plugin_Version( short buildNumber )
   #define P 256
   long    v;
 
-  #define SDK_VERSION_MAJOR 1 /* Release: V1.6.0, change this if you need troubles */
+  #define SDK_VERSION_MAJOR 1 /* Release: V1.6.1, change this if you need troubles */
   #define SDK_VERSION_MINOR 6
-  #define SDK_SUBVERSION    0
+  #define SDK_SUBVERSION    1
 
   /* allowed range for the local build number */
   if (buildNumber<  0) buildNumber=   0;
index 8adad13..b07e70d 100644 (file)
@@ -10,6 +10,9 @@
  *
  */
 
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
 
 #include "prefix_file.h"
 #include  "UI_util.h"
@@ -96,7 +99,8 @@ static bool IsLib( cAppCharP name )
 
 
 // Connect SyncML engine
-TSyError UI_Connect( UI_Call_In &aCI, appPointer &aDLL, cAppCharP aEngineName,
+TSyError UI_Connect( UI_Call_In &aCI, appPointer &aDLL, bool &aIsServer,
+                                                        cAppCharP aEngineName,
                                                         CVersion  aPrgVersion,
                                                         uInt16    aDebugFlags )
 {
@@ -115,6 +119,7 @@ TSyError UI_Connect( UI_Call_In &aCI, appPointer &aDLL, cAppCharP aEngineName,
                                                   uInt16    aDebugFlags );
   GetCEProc fConnectEngine= NULL;
 
+  aIsServer = false;
   do {
     aCI = NULL; // no such structure available at the beginning
     aDLL= NULL;
@@ -129,19 +134,37 @@ TSyError UI_Connect( UI_Call_In &aCI, appPointer &aDLL, cAppCharP aEngineName,
     } // if
 
     if (IsLib( name.c_str() )) {
-      #ifdef DBAPI_LINKED
+      if (name == "[]") {
+#ifdef DBAPI_LINKED
         fConnectEngine= SYSYNC_EXTERNAL(ConnectEngine);
-      #endif
+#endif
+      } else if (name == "[server:]") {
+        aIsServer=true;
+#ifdef DBAPI_SRV_LINKED
+        fConnectEngine= SySync_srv_ConnectEngine;
+#endif
+      }
 
       break;
     } // if
-                         name+= DLL_Suffix;
-        err= ConnectDLL( name.c_str(), aDLL ); // try with suffix first
+
+    cAppCharP prefix = "server:";
+    size_t prefixlen = strlen(prefix);
+    if (name.size() > prefixlen &&
+        !name.compare(0, prefixlen, prefix)) {
+      // ignore prefix and if we find the lib, look for different entry points
+      aIsServer=true;
+      name = name.substr(prefixlen);
+      SyFName= "SySync_srv_ConnectEngine";
+      FName=        "srv_ConnectEngine";
+    }
+
+    err= ConnectDLL( name.c_str(), aDLL ); // try with name directly
     if (dbg) printf( "modu='%s' err=%d\n", name.c_str(), err );
 
     if (err) {
-                         name= aEngineName;
-        err= ConnectDLL( name.c_str(), aDLL ); // then try directly
+                         name+= DLL_Suffix;
+        err= ConnectDLL( name.c_str(), aDLL ); // try with suffix next
     } // if
 
     if (dbg) printf( "modu='%s' err=%d\n", name.c_str(), err );
@@ -171,7 +194,7 @@ TSyError UI_Connect( UI_Call_In &aCI, appPointer &aDLL, cAppCharP aEngineName,
 } // UI_Connect
 
 
-TSyError UI_Disconnect( UI_Call_In aCI, appPointer aDLL )
+TSyError UI_Disconnect( UI_Call_In aCI, appPointer aDLL, bool aIsServer )
 {
   // Always search for BOTH names, independently of environment
   cAppCharP SyFName= "SySync_DisconnectEngine";
@@ -184,13 +207,24 @@ TSyError UI_Disconnect( UI_Call_In aCI, appPointer aDLL )
 
   do {
     if (aDLL==NULL) {
-      #ifdef DBAPI_LINKED
+      if (aIsServer) {
+#ifdef DBAPI_LINKED
         fDisconnectEngine= SYSYNC_EXTERNAL(DisconnectEngine);
-      #endif
+#endif
+      } else {
+#ifdef DBAPI_SRV_LINKED
+        fDisconnectEngine= SySync_srv_DisconnectEngine;
+#endif
+      }
 
       break;
     } // if
 
+    if (aIsServer) {
+      SyFName = "SySync_srv_DisconnectEngine";
+      FName = "srv_DisconnectEngine";
+    }
+
     cAppCharP                 fN= SyFName;
     err=      DLL_Func( aDLL, fN,   fFunc );
     fDisconnectEngine=   (GetDEProc)fFunc;
@@ -226,7 +260,8 @@ TSyError UI_CreateContext( CContext &uContext, cAppCharP aEngineName,
 {
   TSyError err;
   UIContext*           uc= new UIContext;
-  err=     UI_Connect( uc->uCI, uc->uDLL, aEngineName, aPrgVersion, aDebugFlags );
+  bool isServer;
+  err=     UI_Connect( uc->uCI, uc->uDLL, isServer, aEngineName, aPrgVersion, aDebugFlags );
                        uc->uName=         aEngineName;
   DEBUG_DB           ( uc->uCI, MyMod,"UI_CreateContext", "'%s'", uc->uName.c_str() );
   uContext=  (CContext)uc;
index f55aea7..82ea4b1 100644 (file)
@@ -31,11 +31,13 @@ UIContext* UiC( CContext uContext );
 
 /* Function definitions */
 TSyError UI_Connect    ( UI_Call_In &aCI, 
-                         appPointer &aDLL,     cAppCharP aEngineName,
+                         appPointer &aDLL,
+                         bool &aIsServer,      cAppCharP aEngineName,
                                                CVersion  aPrgVersion,
                                                uInt16    aDebugFlags );
 TSyError UI_Disconnect ( UI_Call_In  aCI, 
-                         appPointer  aDLL );
+                         appPointer  aDLL,
+                         bool aIsServer );
 
 
 TSyError UI_CreateContext( CContext &uContext, cAppCharP aEngineName,
index 4f9379f..83ff0db 100755 (executable)
@@ -402,8 +402,13 @@ void SySyncDebugPuts(void* aCB,
                      cAppCharP aText);
 
 
-// factory function declaration - must be implemented in the source file of the leaf derivate of TEngineInterface
-TEngineModuleBase *newEngine(void);
+// factory function declarations - must be implemented in the source file of the leaf derivates of TEngineInterface
+#ifdef SYSYNC_CLIENT
+TEngineModuleBase *newClientEngine(void);
+#endif
+#ifdef SYSYNC_SERVER
+TEngineModuleBase *newServerEngine(void);
+#endif
 
 } // namespace sysync
 #endif // ENGINEMODULEBASE_H
index 379d3c8..eeaa0de 100644 (file)
@@ -28,6 +28,7 @@ namespace sysync {
 // --------------------------------------------------------------
 TEngineModuleBridge::TEngineModuleBridge() {
   fDLL= NULL;
+  fIsServer= false;
 } // constructor
 
 
@@ -40,7 +41,7 @@ TEngineModuleBridge::~TEngineModuleBridge() {
 // --------------------------------------------------------------
 TSyError TEngineModuleBridge::Init()
 {
-  TSyError err= UI_Connect( fCI, fDLL, fEngineName.c_str(), fPrgVersion, fDebugFlags );
+  TSyError err= UI_Connect( fCI, fDLL, fIsServer, fEngineName.c_str(), fPrgVersion, fDebugFlags );
   return   err;
 } // Init
 
@@ -48,7 +49,7 @@ TSyError TEngineModuleBridge::Init()
 TSyError TEngineModuleBridge::Term()
 {
   TSyError   err= LOCERR_OK;
-  if (fCI) { err= UI_Disconnect( fCI, fDLL ); fCI= NULL; }
+  if (fCI) { err= UI_Disconnect( fCI, fDLL, fIsServer ); fCI= NULL; }
   return     err;
 } // Term
 
index 7d133d3..58c232d 100644 (file)
@@ -31,6 +31,7 @@ class TEngineModuleBridge : public TEngineModuleBase
     virtual ~TEngineModuleBridge();
 
     appPointer fDLL;
+    bool       fIsServer;
 
     virtual TSyError Init();
     virtual TSyError Term();
diff --git a/src/synthesis/src/sysync_SDK/Sources/enginestubs.c b/src/synthesis/src/sysync_SDK/Sources/enginestubs.c
new file mode 100644 (file)
index 0000000..ebeff9a
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ *  File:         enginestubs.c
+ *
+ *  Author:       Patrick Ohly
+ *
+ *  Dummy implementations of the engine entry points
+ *  for client and server, to be linked statically against
+ *  SDK instead of the real engine. The engine then has
+ *  to be opened as module.
+ *
+ *  Copyright (c) 2009 by Synthesis AG (www.synthesis.ch)
+ *
+ */
+
+#include "sync_dbapi.h"
+
+ENGINE_ENTRY TSyError
+SYSYNC_EXTERNAL(ConnectEngine)
+    (UI_Call_In *aCI,
+     CVersion   *aEngVersion,
+     CVersion    aPrgVersion,
+     uInt16      aDebugFlags
+     ) ENTRY_ATTR
+{
+  return 404;
+}
+
+ENGINE_ENTRY TSyError
+SYSYNC_EXTERNAL(DisconnectEngine)
+    (UI_Call_In aCI) ENTRY_ATTR
+{
+  return 404;
+}
+
+ENGINE_ENTRY TSyError
+SYSYNC_EXTERNAL_SRV(ConnectEngine)
+   (UI_Call_In *aCI,
+    CVersion   *aEngVersion,
+    CVersion    aPrgVersion,
+    uInt16      aDebugFlags
+    ) ENTRY_ATTR
+{
+  return 404;
+}
+
+ENGINE_ENTRY TSyError
+SYSYNC_EXTERNAL_SRV(DisconnectEngine)
+    (UI_Call_In aCI) ENTRY_ATTR
+{
+  return 404;
+}
index ebc4439..f5d4518 100755 (executable)
 # include <stdint.h>
 #endif
 
+#ifndef __WORDSIZE
+/* 64 platforms should have this defined, so assume that */
+/* platforms without the define are 32 bit. */
+# define __WORDSIZE 32
+#endif
+
+
 #ifdef __cplusplus
   namespace sysync {
 #endif
@@ -51,17 +58,27 @@ typedef unsigned long long uInt64;
 typedef signed long long sInt64;
 #endif
 
-/*
-#ifdef __PALM_OS__
-*/
+/* machine size integer, at least 32 bits */
+typedef unsigned long uIntArch;
+typedef signed long sIntArch;
+
+
+/* TODO, FIXME %%%% for now, we need uInt32 to be 64bit actually */
+//#define UINT32_HAS_64BITS_ON_ARCH64 1
+
+
+#if defined(UINT32_HAS_64BITS_ON_ARCH64) || defined(__PALM_OS__) || (__WORDSIZE < 32)
+/* must use long to get a 32bit int (but gets 64bit in 64-bit architectures) */
 typedef  unsigned long uInt32;
 typedef  signed   long sInt32;
-/*
+#ifdef UINT32_HAS_64BITS_ON_ARCH64
+       #warning "%%% UINT32_HAS_64BITS_ON_ARCH64 - which means that uInt32 is really 64bit: UGLY & DANGEROUS, please be careful"
+#endif
 #else
-  typedef unsigned int uInt32; // according to the ILP32/LP64 std for all other platforms
-  typedef signed   int sInt32; // %%%% requires some type cast fixing first %%%%
+/* according to the ILP32/LP64 std for all other platforms, int is 32bit (and long is 64bit) */
+typedef unsigned int uInt32; 
+typedef signed   int sInt32;
 #endif
-*/
 
 typedef unsigned short uInt16;
 typedef signed short sInt16;
@@ -77,18 +94,13 @@ typedef signed long sIntPtr;
 #endif
 
 /* - application integers */
-typedef uInt32 bufferIndex; /* index into app buffers (small platforms may have 16bit here) */
-typedef uInt32 stringIndex; /* index into string (small platforms may have 16bit here) */
-typedef uInt32 stringSize;  /* size of a string object */
-typedef uInt32 memSize;     /* size of a memory buffer */
+typedef uIntArch bufferIndex; /* index into app buffers (small platforms may have 16bit here) */
+typedef uIntArch stringIndex; /* index into string (small platforms may have 16bit here) */
+typedef uIntArch stringSize;  /* size of a string object */
+typedef uIntArch memSize;     /* size of a memory buffer */
 
 #endif /* HAVE_STDINT_H */
 
-#ifndef __WORDSIZE
-/* 64 platforms should have this defined, so assume that */
-/* platforms without the define are 32 bit. */
-# define __WORDSIZE 32
-#endif
 
 /* undefined size types */
 /* - application chars & pointers */
similarity index 99%
rename from src/synthesis/src/sysync/san.cpp
rename to src/synthesis/src/sysync_SDK/Sources/san.cpp
index a2e083a..e9fce70 100755 (executable)
@@ -59,12 +59,17 @@ digest= H(B64(H(server-identifier:password)):nonce:B64(H(notification)))
 */
 
 
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
 #include "prefix_file.h"
+#include "sync_include.h"
 #include "san.h"
 #include "sysync_md5.h"
 #include "sysync_b64.h"
 
-#ifndef PUSHALERTER
+#ifndef WITHOUT_SAN_1_1
 #include "sysync_utils.h"
 #endif
 
@@ -352,8 +357,7 @@ void SanPackage::ReleaseNotificationBody()
 } // ReleaseNotificationBody
 
 
-// not available for pushalerter tool
-#ifndef PUSHALERTER
+#ifndef WITHOUT_SAN_1_1
 // general callback entry for all others
 static Ret_t univ( ... )
 {
@@ -503,7 +507,7 @@ TSyError SanPackage::Check_11( void* san, size_t sanSize )
 
   return err;
 } // Check_11
-#endif
+#endif // WITHOUT_SAN_1_1
 
 
 TSyError SanPackage::PassSan( void* san, size_t sanSize )
@@ -514,7 +518,7 @@ TSyError SanPackage::PassSan( void* san, size_t sanSize )
   ReleasePackage();
 //printf( "here we will have the potential 1.1 -> 1.2 conversion\n" );
 
-  #ifndef PUSHALERTER
+  #ifndef WITHOUT_SAN_1_1
                err= Check_11  ( san,sanSize );
     if (!err)  err= GetPackage( san,sanSize );
   //use_as_12= err==SML_ERR_XLT_INCOMP_WBXML_VERS;
index 6cd9959..6f1df58 100644 (file)
@@ -231,7 +231,11 @@ sInt16 HexStrToUIntPtr( cAppCharP aStr, uIntPtr &aIntPtr, sInt16 aMaxDigits )
   #if __WORDSIZE == 64
     return HexStrToULongLong( aStr, aIntPtr, aMaxDigits );
   #else
-    return HexStrToULong    ( aStr, aIntPtr, aMaxDigits );
+    uInt32                            v= (uInt32)aIntPtr;
+    sInt16 rslt= HexStrToULong( aStr, v, aMaxDigits );
+    aIntPtr=                 (uIntPtr)v;
+    
+    return rslt;
   #endif
 } // HexStrToUIntPtr
 
index 6521ecc..7f89b5e 100755 (executable)
@@ -46,6 +46,7 @@
 
 #if defined MACOSX
        #define ENGINE_ENTRY ENTRY_C
+       #define ENGINE_ENTRY_CXX
        
        #ifdef __GNUC__
          #define ENTRY_ATTR __attribute__((visibility("default")))
   /* Visual Studio 2005 requires a specific entry point definition */
   /* This definition is empty for all other platforms */
   #define ENGINE_ENTRY ENTRY_C _declspec(dllexport)
+  #define ENGINE_ENTRY_CXX ENGINE_ENTRY
   #define ENTRY_ATTR
 #else
        #define ENGINE_ENTRY ENTRY_C
+       #define ENGINE_ENTRY_CXX
        #define ENTRY_ATTR
 #endif
 
 /* compose name of external symbols with C binding:
- * by default use parameter as-is (backwards compatibility),
+ * by default use parameter as-is (backwards compatibility) for client,
+ * and use "SySync_srv_" prefix for server.
+ * Newer builds usually use "SySync_" as prefix for client entry points.
  * can be changed in any file that is included before
  * this file
  */
 # define SYSYNC_EXTERNAL(_x) _x
 # define SYSYNC_PREFIX ""
 #endif
+#ifndef SYSYNC_EXTERNAL_SRV
+# define SYSYNC_EXTERNAL_SRV(_x) SySync_srv_ ## _x
+# define SYSYNC_PREFIX_SRV "SySync_srv_"
+#endif
 
 #ifdef __cplusplus
   namespace sysync {
@@ -152,8 +161,8 @@ enum Version {
   VP_CB_Version11        = 0x01050200,
   /** V1.6.0.X : Tunnel support                                  */
   VP_Tunnel              = 0x01060000,
-  /** V1.6.0.X : Current version, use 'Plugin_Version()'         */
-  VP_CurrentVersion      = 0x01060000,
+  /** V1.6.1.X : Current version, use 'Plugin_Version()'         */
+  VP_CurrentVersion      = 0x01060100,
 
   /** -------- : Bad/undefined version                           */
   VP_BadVersion          = 0xffffffff,
@@ -633,7 +642,7 @@ typedef TSyError (*DisconnectEngine_Func)   ( UI_Call_In  aCI );
 
 
 
-/* Entry point for connecting the SyncML engine from outside */
+/* Entry point for connecting the SyncML engine as client from outside */
  ENGINE_ENTRY TSyError SYSYNC_EXTERNAL(ConnectEngine)
                                           ( UI_Call_In *aCI,
                                             CVersion   *aEngVersion,
@@ -647,10 +656,30 @@ typedef TSyError (*DisconnectEngine_Func) ( UI_Call_In  aCI );
                                             CVersion    aPrgVersion,
                                             uInt16      aDebugFlags ) ENTRY_ATTR;
 
-/* Entry point for disconnecting the engine at the end */
+/* Entry point for connecting the SyncML engine as server from outside */
+ ENGINE_ENTRY TSyError SYSYNC_EXTERNAL_SRV(ConnectEngine)
+                                          ( UI_Call_In *aCI,
+                                            CVersion   *aEngVersion,
+                                            CVersion    aPrgVersion,
+                                            uInt16      aDebugFlags ) ENTRY_ATTR;
+
+ ENGINE_ENTRY TSyError SYSYNC_EXTERNAL_SRV(ConnectEngineS)
+                                          ( UI_Call_In  aCI,
+                                            uInt16      aCallbackVersion,
+                                            CVersion   *aEngVersion,
+                                            CVersion    aPrgVersion,
+                                            uInt16      aDebugFlags ) ENTRY_ATTR;
+
+
+/* Entry point for disconnecting the client engine at the end */
  ENGINE_ENTRY TSyError SYSYNC_EXTERNAL(DisconnectEngine)
                                           ( UI_Call_In  aCI         ) ENTRY_ATTR;
 
+/* Entry point for disconnecting the client engine at the end */
+ ENGINE_ENTRY TSyError SYSYNC_EXTERNAL_SRV(DisconnectEngine)
+                                          ( UI_Call_In  aCI         ) ENTRY_ATTR;
+
+
 
 #ifdef __cplusplus
   } // namespace
similarity index 97%
rename from src/synthesis/src/sysync/sysync_b64.cpp
rename to src/synthesis/src/sysync_SDK/Sources/sysync_b64.cpp
index eed6fb2..e1635ad 100755 (executable)
@@ -6,7 +6,7 @@
 #include <string.h>
 
 #include "sysync_b64.h"
-#include "profiling.h"
+#include "sync_include.h"
 
 using namespace b64;
 
@@ -55,7 +55,7 @@ char *b64::encode (const uInt8 *instr, uInt32 len, uInt32 *outlenP, sInt16 maxLi
       (outlen/maxLineLen+1) << (crLineEnd ? 0 : 1);
   }
 
-  outstr = (char *)sysync_malloc(outlen*sizeof(char));
+  outstr = (char *)malloc(outlen*sizeof(char));
   memset(outstr,0,outlen);
 
   linechars=0;
@@ -146,7 +146,7 @@ uInt8 *b64::decode(const char *instr, uInt32 len, uInt32 *outlenP)
 
   // this should always be more than enough len:
   // 3 times number of quads touched plus one for NUL terminator
-  outstr = (uInt8 *)sysync_malloc(((3*(len/4+1))+1) * sizeof(char));
+  outstr = (uInt8 *)malloc(((3*(len/4+1))+1) * sizeof(char));
   if (!outstr) return NULL;
   q=outstr;
 
@@ -237,7 +237,7 @@ uInt8 *b64::decode(const char *instr, uInt32 len, uInt32 *outlenP)
   // this should always be more than enough len
   outlen = (3*(quads+1))+1;
 
-  outstr = (uInt8 *)sysync_malloc(outlen * sizeof(char));
+  outstr = (uInt8 *)malloc(outlen * sizeof(char));
   memset(outstr,0,outlen);
   for (i = 0; i < quads; i++) {
 
similarity index 97%
rename from src/synthesis/src/sysync/sysync_md5.cpp
rename to src/synthesis/src/sysync_SDK/Sources/sysync_md5.cpp
index ab65b34..7655e1b 100755 (executable)
@@ -104,14 +104,6 @@ void md5::Init (SYSYNC_MD5_CTX *context)
   /* initialize the padding space, don't know if this is necessary */
   MD5_memset ((SYSYNC_POINTER)context->PADDING, 0, 64);
   context->PADDING[0]=0x80;
-  // note: this does the same thing as the original:
-  /* moved to SYSYNC_MD5_CTX as statics are not allowed in some environments
-  static uInt8 PADDING[64] = {
-    0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-  };
-  */
 }
 
 /* MD5 block update operation. Continues an MD5 message-digest
similarity index 89%
rename from src/synthesis/src/sysync/sysync_md5.h
rename to src/synthesis/src/sysync_SDK/Sources/sysync_md5.h
index 5bf2fb6..f438996 100755 (executable)
@@ -50,7 +50,12 @@ typedef uInt8 *SYSYNC_POINTER;
 typedef uInt16 SYSYNC_UINT2;
 
 /* UINT4 defines a four byte word */
-typedef uInt32 SYSYNC_UINT4;
+/* Note: "typedef uInt32 SYSYNC_UINT4;" is unreliable as uInt32 was 64bit in some weird builds */
+#if !defined(__WORDSIZE) || (__WORDSIZE < 32)
+typedef unsigned long SYSYNC_UINT4;
+#else
+typedef unsigned int SYSYNC_UINT4;
+#endif 
 
 /* MD5 context. */
 typedef struct {
@@ -69,6 +74,7 @@ void Final (uInt8 [16], SYSYNC_MD5_CTX *);
 /* for test */
 void String (const char *aString, char *s);
 void Print (uInt8 *digest, char * &s);
+void dotest(void);
 #endif
 
 } // end namespace md5
diff --git a/src/synthesis/src/sysync_SDK/configs/syncserv_sample_config.xml b/src/synthesis/src/sysync_SDK/configs/syncserv_sample_config.xml
new file mode 100755 (executable)
index 0000000..6746b1e
--- /dev/null
@@ -0,0 +1,2887 @@
+<?xml version="1.0"?>
+<!-- SYNTHESIS SYNC SERVER Version 3.2 Configuration file -->
+
+<sysync_config version="1.0">
+
+  <!-- this string is output to every session debug logfile to identify the config in use -->
+  <configidstring>Synthesis SyncML Server Engine 3.2 sample config</configidstring>
+
+  <debug>
+    <!-- path where logfiles are stored -->
+    <!-- <logpath platform="linux">/your/log/directory</logpath> -->
+    <logflushmode>buffered</logflushmode> <!-- buffered is fastest mode, but may loose data on process abort. Other options: "flush" (after every line) or "openclose" (safest, slowest, like in 2.x server) -->
+    <!-- per session log -->
+    <sessionlogs>yes</sessionlogs> <!-- by default, create a session log file for every sync session (might be disabled for special users/devices in scripts) -->
+    <!-- debug format options -->
+    <logformat>html</logformat> <!-- html is nicely colored and easily viewable with a web browser. Other options: "xml", "text" -->
+    <folding>auto</folding> <!-- dynamic folding of blocks enabled, automatically expanded or collapsed default. Other options: "none", "expanded", "collapsed" -->
+    <timestamp>yes</timestamp> <!-- show timestamps for structure elements in log -->
+    <timestampall>no</timestampall> <!-- don't show timestamp for every log line -->
+    <timedsessionlognames>yes</timedsessionlognames> <!-- session logs also have the session start timestamp in the filename - makes them more easily sortable -->
+    <!-- thread logging mode -->
+    <subthreadmode>separate</subthreadmode> <!-- write log info from subthreads into separate log files. Other options: "suppress" -->
+    <!-- basic debug level selection -->
+    <enable option="extended"/> <!-- "extended" is a good choice for start testing. For production, use "normal" or "minimal" -->
+    <!-- <enable option="normal"/> --> <!-- "normal" provides rich debug info, but still in reasonable size  -->
+    <!-- <enable option="minimal"/> --> <!-- "minimal" just shows basic flow and error. Not suitable for debugging -->
+    <!-- <enable option="maximal"/> --> <!-- "maximal" can create VERY LARGE logs and cause HEAVY SLOWDOWN. Only for detail debugging  -->
+    <!-- <enable option="all"/> --> <!-- "all" shows EVERYTHING possible, and way too much for any normal situation. For hardcore debugging ONLY! -->
+    <!-- additional debug info switches -->
+    <enable option="userdata"/> <!-- Make this <disable ...> if you don't want user data in the logs -->
+    <disable option="scripts"/> <!-- Make this <enable ...> to show script execution in logs  -->
+    <disable option="match"/> <!-- Make this <enable ...> to show slow sync matching. CAN PRODUCE ENORMOUS LOGS and HEAVILY IMPACT PERFORMANCE for large slow syncs - use with care!  -->
+    <disable option="exotic"/> <!-- Make this <enable ...> to include very in-detail info. CAN PRODUCE ENORMOUS LOGS and HEAVILY IMPACT PERFORMANCE for large slow syncs - use with care!  -->
+    <!-- see manual for more debug info switches -->
+    <!-- global log options -->
+    <globallogs>no</globallogs> <!-- by default, do not log global session dispatching, creation etc. (not useful in multi-user operation) -->
+    <singlegloballog>no</singlegloballog> <!-- a new global log will be started for every start of the server/application -->
+    <!-- SyncML message dumping options -->
+    <msgdump>no</msgdump> <!-- do not dump syncml traffic 1:1 to files -->
+    <xmltranslate>no</xmltranslate> <!-- do not try to translate syncml traffic into XML (DO NOT SET THIS OPTION IN PRODUCTIVE SERVERS!) -->
+  </debug>
+
+
+  <scripting>
+    <!-- Global script function definitions -->
+
+    <function><![CDATA[
+      // create a UID
+      string newuid() {
+        return "syuid" + NUMFORMAT(RANDOM(1000000),6,"0") + "." + (string)MILLISECONDS(NOW());
+      }
+    ]]></function>
+
+
+       <!-- define script macros for scripts that are used by both vCalendar 1.0 and iCalendar 2.0 -->
+
+    <macro name="VCALENDAR_INCOMING_SCRIPT"><![CDATA[
+      STRING MATCHES[];
+      STRING CAT,CN,EM;
+      INTEGER i;
+      // make sure we have all trailing and leading spaces eliminated
+      DESCRIPTION=NORMALIZED(DESCRIPTION);
+      SUMMARY=NORMALIZED(SUMMARY);
+      // eliminate description that is the same as summary
+      if (DESCRIPTION==SUMMARY) DESCRIPTION=EMPTY;
+      // calendar or todo
+      if (ISEVENT) {
+        // VEVENT
+        // - handle duration cases
+        if (ISDURATION(DURATION)) {
+          if (DTEND==EMPTY) DTEND = DTSTART + DURATION;
+          if (DTSTART==EMPTY) DTSTART = DTEND - DURATION;
+        }
+        // - detect alldays in vCalendar 1.0 (0:00-0:00 or 23:59 localtime)
+        i = ALLDAYCOUNT(DTSTART,DTEND,TRUE);
+        if (ITEMDATATYPE()=="vtodoz10" && i>0) {
+          // DTSTART and DTEND represent allday event, make them date-only values
+          // - convert start to user zone (or floating) so it represents midnight
+          DTSTART = CONVERTTOUSERZONE(DTSTART);
+          MAKEALLDAY(DTSTART,DTEND,i);
+        }
+        // - shape attendees (and make sure ATTENDEES[] is assigned even for empty email addresses)
+        i=0;
+        while(i<SIZE(ATTENDEES) || i<SIZE(ATTENDEE_CNS)) {
+          PARSEEMAILSPEC(ATTENDEES[i], CN, EM);
+          ATTENDEES[i] = EM; // pure email address
+          // in case we have no specific common name, use the one extracted from the email
+          // This catches the vCalendar 1.0 case and eventually ill-formed iCalendar 2.0 as well
+          if (ATTENDEE_CNS[i]==EMPTY)
+            ATTENDEE_CNS[i]=CN;
+          // default participation status to needs-action
+          if (ATTENDEE_PARTSTATS[i]==EMPTY)
+            ATTENDEE_PARTSTATS[i]=1; // 1=needs action
+          i=i+1;
+        }
+        // - shape organizer
+        PARSEEMAILSPEC(ORGANIZER, CN, EM);
+        ORGANIZER = EM; // pure email address
+        if (ORGANIZER_CN==EMPTY)
+          ORGANIZER_CN=CN;
+      }
+      else {
+        // VTODO
+        // - make sure we have at least a summary
+        if (SUMMARY==EMPTY) SUMMARY=DESCRIPTION; // use description if we don't have a summary
+        if (SUMMARY==EMPTY) SUMMARY="unnamed"; // set dummy summary if we still don't have one
+        // due shaping for non-iCalendar 2.0
+        if (ITEMDATATYPE()=="vCalendar10" && ALLDAYCOUNT(DUE,DUE,TRUE,TRUE)>0) {
+               DUE = DATEONLY(DUE);
+        }
+      }
+      // Common alarm handling
+      // - handle relative alarm time (as possible with VALARM TRIGGER)
+      if (ISDURATION(ALARM_TIME)) {
+        if (ALARM_REL==2)
+          ALARM_TIME = DTEND+ALARM_TIME; // relative to end
+        else {
+          if (ISEVENT)
+            ALARM_TIME = DTSTART+ALARM_TIME; // relative to start for events
+          else
+            ALARM_TIME = DUE+ALARM_TIME; // relative to due for todos
+        }
+      }
+    ]]></macro>
+
+
+    <macro name="VCALENDAR_OUTGOING_SCRIPT"><![CDATA[
+      // set UTC time of generation for iCalendar 2.0 DTSTAMP
+      DGENERATED = NOW();
+      // make sure we have all trailing and leading spaces eliminated
+      DESCRIPTION=NORMALIZED(DESCRIPTION);
+      SUMMARY=NORMALIZED(SUMMARY);
+      if (ISEVENT) {
+        // VEVENT
+        // - combine attendee email address and common name into single string for vCalendar 1.0
+        if (ITEMDATATYPE()=="vCalendar10") {
+          i=0;
+          while(i<SIZE(ATTENDEES)) {
+            ATTENDEES[i] = MAKEEMAILSPEC(ATTENDEE_CNS[i], ATTENDEES[i]);
+            i=i+1;
+          }
+          ORGANIZER = MAKEEMAILSPEC(ORGANIZER_CN, ORGANIZER);
+        }
+      }
+      else {
+        // VTODO
+        // - Nothing special so far
+      }
+      // make sure we have at least a summary
+      if (SUMMARY==EMPTY) SUMMARY=SUBSTR(DESCRIPTION,0,32); // derive from description
+      if (SUMMARY==EMPTY) SUMMARY="unnamed"; // in case description is empty as well
+      // do NOT send duration (some servers crash when doing so)
+      DURATION = UNASSIGNED;
+      // shape alarm
+      if (ALARM_TIME!=EMPTY) {
+        if (ITEMDATATYPE()=="iCalendar20") {
+          if (ALARM_ACTION==EMPTY) ALARM_ACTION = "AUDIO";
+          ALARM_TIME = CONVERTTOUSERZONE(ALARM_TIME,TRUE); // unfloat into user (system) zone, in case it is floating
+          ALARM_TIME = CONVERTTOZONE(ALARM_TIME,"UTC"); // must always be UTC by iCalendar 2.0 specs
+          // send as duration if we have non-empty non-date DTSTART
+          if (DTSTART!=EMPTY && !ISDATEONLY(DTSTART)) {
+            // make a duration (unfloat DTSTART into system zone in case it is floating first!)
+            ALARM_TIME = ALARM_TIME-CONVERTTOZONE(CONVERTTOUSERZONE(DTSTART,TRUE),"UTC");
+            ALARM_REL = 1; // relative to start
+          }
+        }
+        else {
+          if (ALARM_MSG==EMPTY) ALARM_MSG="alarm";
+        }
+      }
+    ]]></macro>
+
+
+    <!-- The following email handling scripts are defined as script MACROS because they
+         are used in multiple <datatype> definitions below. This avoids duplicating these
+         script's source code in the config file -->
+
+    <macro name="EMAIL_INIT_SCRIPT"><![CDATA[
+      INTEGER ITEMLIMIT;
+      // default limit is limit of session
+      ITEMLIMIT = SIZELIMIT();
+    ]]></macro>
+
+
+    <macro name="EMAIL_PROCESSITEM_SCRIPT"><![CDATA[
+      // pre-process item
+      if (UPPERCASE(FOLDER)=="INBOX") {
+        // In any case, prevent adding to inbox (delete remote items instead)
+        PREVENTADD();
+        // server always wins for inbox
+        CONFLICTSTRATEGY("server-wins");
+        if (SLOWSYNC()) {
+          // also prevent modifications in server
+          IGNOREUPDATE();
+        }
+        else {
+          // normal sync items going to inbox from client need special treatment
+          if (SYNCOP()=="add" || SYNCOP()=="replace") {
+            // make sure that existing server item will conflict with this item
+            if (LIMIT!=EMPTY && (LIMIT<0 || LIMIT>SIZELIMIT())) {
+              // force conflict only if this is a reload
+              FORCECONFLICT();
+            }
+            // make sure we never overwrite a body in the inbox
+            BODY = UNASSIGNED;
+            // delete always wins over replace in inbox (to avoid adds to inbox)
+            DELETEWINS();
+          }
+        }
+      }
+      else if (UPPERCASE(FOLDER)=="OUTBOX") {
+        // never try to change something in outbox
+        IGNOREUPDATE();
+        if (SYNCOP()!="delete") {
+          // - date of mail is NOW, set it such that a correct date is written to the DB
+          MAILDATE = DBNOW();
+          // MAILDATE = (INTEGER)DBNOW() - TIMEUNITS(120); // %%% backdate it 2 mins to make sure it does not get retransmitted
+          // - echo item as replace (to force-move it to the sent folder)
+          ECHOITEM("replace");
+        }
+        CONFLICTSTRATEGY("client-wins");
+      }
+      else if (UPPERCASE(FOLDER)=="SENT") {
+        // never try to change something in sent folder
+        IGNOREUPDATE();
+        // Server has precedence in case of conflicts
+        CONFLICTSTRATEGY("server-wins");
+        // Implement reload capability for sent items as well
+        if (SLOWSYNC()) {
+          // do not add new sent items to the server in slowsync
+          PREVENTADD(); // causes extra sent items on the client to be deleted
+        }
+        else {
+          // make sure that existing server item will conflict with this item
+          if (SYNCOP()=="replace") {
+            if (LIMIT!=EMPTY && (LIMIT<0 || LIMIT>SIZELIMIT())) {
+              // force conflict only if this is a reload
+              FORCECONFLICT();
+              REJECTITEM(200); // but do not process the item further
+            }
+            else {
+              // silently ignore other types of changes
+              REJECTITEM(200);
+            }
+            // make sure we never overwrite a body in the sent folder
+            BODY = UNASSIGNED;
+          }
+        }
+      }
+      else {
+        // Other folder
+        // - silently discard incoming item for other folder than the above
+        //   except if it is a delete
+        if (SYNCOP()!="delete")
+          REJECTITEM(0);
+      }
+    ]]></macro>
+
+
+    <macro name="EMAIL_MERGE_SCRIPT"><![CDATA[
+      // pre-process item
+      if (UPPERCASE(LOOSING.FOLDER)!="OUTBOX") {
+        // non-outbox (especially inbox) needs special merge to accomplish reload feature
+        // - loosing item is client's, winning is server's
+        if (LOOSING.LIMIT!=EMPTY) {
+          // loosing (remote) item specifies a new limit, override winning's default
+          WINNING.LIMIT=LOOSING.LIMIT;
+          SETWINNINGCHANGED(TRUE);
+        }
+        // make sure winning has right folder
+        WINNING.FOLDER=LOOSING.FOLDER;
+        // make sure a set read-flag gets propagated to server
+        if (LOOSING.ISREAD=="true") WINNING.ISREAD="true";
+        // merge other fields normally
+        MERGEFIELDS();
+        // make sure body does not get re-written to local DB even if merge would cause local update
+        LOOSING.BODY=UNASSIGNED;
+      }
+      else {
+        // normal merging in other folders
+        MERGEFIELDS();
+      }
+    ]]></macro>
+
+    <macro name="EMAIL_OUTGOING_SCRIPT"><![CDATA[
+      // pre-process item
+      if (UPPERCASE(FOLDER)=="OUTBOX") {
+        // writing to outbox is always the ECHOITEM
+        // - cause item to move into "sent" folder
+        FOLDER = "sent";
+        if (!SESSIONVAR("retransfer_body")) {
+          // - prevent body retransfer, but not for dumb P800/P900/M600/P990 clients
+          BODY = UNASSIGNED; // prevent body transfer
+          ATT_COUNT = 0; // prevent attachment transfer
+          ATT_CONTENTS = UNASSIGNED;
+          // basically, this item is not limited (already complete on the client)
+          // even if contents are not sent
+          LIMIT = -1;
+          SETSIZELIMIT(-1);
+        }
+      }
+      else {
+        // outgoing item to any folder of of remote (inbox, sent...)
+        // - limit body to what is set in the LIMIT field
+        // %%% probably obsolete, as textitem will handle limit field automatically for >=V1.0.8.21
+        IF (LIMIT==EMPTY)
+          LIMIT = SIZELIMIT(); // if none set already, use default for this item (=default of datastore, if not SETSIZELIMIT() called before for this item generation)
+      }
+      // set limit for item generator
+      if (LIMIT!=EMPTY)
+        SETSIZELIMIT(LIMIT);
+    ]]></macro>
+
+
+    <macro name="EMAIL_FILTERINIT_SCRIPT"><![CDATA[
+      // check if we need to filter
+      INTEGER NEEDFILTER;
+
+      NEEDFILTER =
+        !DBHANDLESOPTS() && // only if DB cannot handle it
+        (STARTDATE()!=EMPTY); // and only if a start date is set (end date not needed as there are never future emails today)
+      SETFILTERALL(NEEDFILTER);
+      RETURN NEEDFILTER;
+    ]]></macro>
+
+
+    <macro name="EMAIL_FILTER_SCRIPT"><![CDATA[
+      INTEGER PASSES;
+
+      // check if item passes filter
+      PASSES=FALSE;
+      // Emails pass if they have a MAILDATE on or later than start date
+      PASSES = MAILDATE>=STARTDATE();
+      RETURN PASSES;
+    ]]></macro>
+
+  </scripting>
+
+
+  <datatypes>
+
+    <!-- list of internal fields representing vCard data -->
+    <fieldlist name="contacts">
+      <field name="SYNCLVL" type="integer" compare="never"/>
+      <field name="REV" type="timestamp" compare="never" age="yes"/>
+
+      <!-- Name elements -->
+      <field name="N_LAST" type="string" compare="always"/>
+      <field name="N_FIRST" type="string" compare="always"/>
+      <field name="N_MIDDLE" type="string" compare="always"/>
+      <field name="N_PREFIX" type="string" compare="conflict"/>
+      <field name="N_SUFFIX" type="string" compare="conflict"/>
+      <field name="NICKNAME" type="string" compare="conflict"/>
+      <field name="TITLE" type="string" compare="conflict" merge="fillempty"/>
+
+      <field name="FN" type="string" compare="conflict" merge="fillempty"/>
+
+      <!-- categories and classification -->
+      <field name="CATEGORIES" array="yes" type="string" compare="conflict"/>
+
+      <!-- organisation -->
+      <field name="ORG_NAME" type="string" compare="slowsync" merge="fillempty"/>
+      <field name="ORG_DIVISION" type="string" compare="conflict" merge="fillempty"/>
+
+      <!-- birthday -->
+      <field name="BDAY" type="date" compare="conflict" merge="fillempty"/>
+
+      <!-- telephone numbers -->
+      <field name="TEL"         array="yes" type="telephone" compare="conflict"/>
+      <field name="TEL_FLAGS"   array="yes" type="integer"   compare="conflict"/> <!-- offset 0 -->
+      <field name="TEL_LABEL"   array="yes" type="string"    compare="conflict"/> <!-- offset 1 -->
+      <field name="TEL_ID"      array="yes" type="integer"   compare="conflict"/> <!-- offset 2 -->
+
+      <!-- emails -->
+      <field name="EMAIL"       array="yes" type="multiline" compare="conflict"/>
+      <field name="EMAIL_FLAGS" array="yes" type="integer"   compare="conflict"/> <!-- offset 0 -->
+      <field name="EMAIL_LABEL" array="yes" type="string"    compare="conflict"/> <!-- offset 1 -->
+      <field name="EMAIL_ID"    array="yes" type="integer"   compare="conflict"/> <!-- offset 2 -->
+
+      <!-- web addresses -->
+      <field name="WEB"         array="yes" type="url" compare="conflict"/>
+      <field name="WEB_FLAGS"   array="yes" type="integer"   compare="conflict"/> <!-- offset 0 -->
+      <field name="WEB_LABEL"   array="yes" type="string"    compare="conflict"/> <!-- offset 1 -->
+      <field name="WEB_ID"      array="yes" type="integer"   compare="conflict"/> <!-- offset 2 -->
+
+      <!-- home address -->
+      <field name="ADR_STREET"        array="yes" type="multiline" compare="conflict"/>
+      <field name="ADR_ADDTL"         array="yes" type="multiline" compare="conflict"/>
+      <field name="ADR_STREET_FLAGS"  array="yes" type="integer"   compare="conflict"/> <!-- offset 0 (from ADR_STREET_FLAGS) -->
+      <field name="ADR_STREET_LABEL"  array="yes" type="string"    compare="conflict"/> <!-- offset 1 -->
+      <field name="ADR_STREET_ID"     array="yes" type="integer"   compare="conflict"/> <!-- offset 2 -->
+      <field name="ADR_POBOX"         array="yes" type="multiline" compare="conflict"/>
+      <field name="ADR_CITY"          array="yes" type="multiline" compare="conflict"/>
+      <field name="ADR_REG"           array="yes" type="multiline" compare="conflict"/>
+      <field name="ADR_ZIP"           array="yes" type="multiline" compare="conflict"/>
+      <field name="ADR_COUNTRY"       array="yes" type="multiline" compare="conflict"/>
+
+      <!-- Note -->
+      <field name="NOTE" type="multiline" compare="conflict" merge="lines"/>
+
+      <!-- Photo -->
+      <field name="PHOTO" type="blob" compare="never" merge="fillempty"/>
+      <field name="PHOTO_TYPE" type="integer" compare="never" merge="fillempty"/>
+
+    </fieldlist>
+
+    <!-- vCard profile -->
+    <mimeprofile name="vCard" fieldlist="contacts">
+
+      <profile name="VCARD" nummandatory="0"> <!-- we allow records without "N" as Address book can store them -->
+        <property name="VERSION">
+          <value conversion="version"/>
+        </property>
+
+        <property onlyformode="standard" name="PRODID" mandatory="no">
+          <value conversion="prodid"/>
+        </property>
+
+        <property name="REV">
+          <value field="REV"/>
+        </property>
+
+        <property name="N" values="5" mandatory="yes"> <!-- Note: makes N parse and generate even if not in remote's CTCap -->
+          <value index="0" field="N_LAST"/>
+          <value index="1" field="N_FIRST"/>
+          <value index="2" field="N_MIDDLE"/>
+          <value index="3" field="N_PREFIX"/>
+          <value index="4" field="N_SUFFIX"/>
+        </property>
+
+        <property name="FN">
+          <value field="FN"/>
+        </property>
+
+        <property name="NICKNAME" onlyformode="standard">
+          <value field="NICKNAME"/>
+        </property>
+
+        <property name="TITLE">
+          <value field="TITLE"/>
+        </property>
+
+        <property name="CATEGORIES" values="list" valueseparator="," altvalueseparator=";" > <!-- non-standard, but 1:1 as in vCard 3.0 (NOT like in vCalendar 1.0, where separator is ";") -->
+          <value field="CATEGORIES"/>
+          <position field="CATEGORIES" repeat="array" increment="1" minshow="0"/>
+        </property>
+
+        <property name="ORG" values="2">
+          <value index="0" field="ORG_NAME"/>
+          <value index="1" field="ORG_DIVISION"/>
+        </property>
+
+        <property name="TEL">
+          <value field="TEL"/>
+          <position field="TEL" repeat="array" increment="1" minshow="1"/>
+          <parameter name="TYPE" default="yes" positional="no" show="yes">
+            <value field="TEL_FLAGS" conversion="multimix" combine=",">
+              <enum name="HOME"     value="B0"/>
+              <enum name="WORK"     value="B1"/>
+              <enum mode="ignore"   value="B2"/> <!-- OTHER -->
+              <enum name="VOICE"    value="B3"/>
+              <enum name="CELL"     value="B4"/>
+              <enum name="FAX"      value="B5"/>
+              <enum name="PAGER"    value="B6"/>
+              <enum name="PREF"     value="B7"/>
+
+              <enum mode="prefix" name="X-CustomLabel-" value="1.L"/>
+              <enum mode="prefix" name="X-Synthesis-Ref" value="2.L"/>
+            </value>
+          </parameter>
+        </property>
+
+        <property name="EMAIL">
+          <value field="EMAIL"/>
+          <position field="EMAIL" repeat="array" increment="1" minshow="1"/>
+          <parameter name="TYPE" default="yes" positional="no" show="yes">
+            <value field="EMAIL_FLAGS" conversion="multimix" combine=",">
+              <enum name="HOME"     value="B0"/>
+              <enum name="WORK"     value="B1"/>
+              <enum mode="ignore"   value="B2"/> <!-- OTHER -->
+              <enum name="INTERNET" value="B3"/>
+
+              <enum mode="prefix" name="X-CustomLabel-" value="1.L"/>
+              <enum mode="prefix" name="X-Synthesis-Ref" value="2.L"/>
+            </value>
+          </parameter>
+        </property>
+
+        <property name="URL">
+          <value field="WEB"/>
+          <position field="WEB" repeat="array" increment="1" minshow="1"/>
+          <parameter name="TYPE" default="yes" positional="no" show="yes">
+            <value field="WEB_FLAGS" conversion="multimix" combine=",">
+              <enum name="HOME"     value="B0"/>
+              <enum name="WORK"     value="B1"/>
+              <enum mode="ignore"   value="B2"/> <!-- OTHER -->
+              <enum name="PREF"     value="B3"/>
+
+              <enum mode="prefix" name="X-CustomLabel-" value="1.L"/>
+              <enum mode="prefix" name="X-Synthesis-Ref" value="2.L"/>
+            </value>
+          </parameter>
+        </property>
+
+        <property name="ADR" values="7">
+          <value index="0" field="ADR_POBOX"/>
+          <value index="1" field="ADR_ADDTL"/>
+          <value index="2" field="ADR_STREET"/>
+          <value index="3" field="ADR_CITY"/>
+          <value index="4" field="ADR_REG"/>
+          <value index="5" field="ADR_ZIP"/>
+          <value index="6" field="ADR_COUNTRY"/>
+          <position field="ADR_POBOX" repeat="array" increment="1" minshow="1"/>
+          <parameter name="TYPE" default="yes" positional="no" show="yes">
+            <value field="ADR_STREET_FLAGS" conversion="multimix" combine=",">
+              <enum name="HOME"     value="B0"/>
+              <enum name="WORK"     value="B1"/>
+              <enum mode="ignore"   value="B2"/> <!-- OTHER -->
+
+              <enum mode="prefix" name="X-CustomLabel-" value="1.L"/>
+              <enum mode="prefix" name="X-Synthesis-Ref" value="2.L"/>
+            </value>
+          </parameter>
+        </property>
+
+        <property name="BDAY">
+          <value field="BDAY"/>
+        </property>
+
+        <property name="NOTE" filter="no">
+          <value field="NOTE"/>
+        </property>
+
+        <property name="PHOTO" filter="no">
+          <value field="PHOTO" conversion="BLOB_B64"/>
+          <parameter name="TYPE" default="no" show="yes">
+            <value field="PHOTO_TYPE">
+              <enum name="JPEG" value="0"/>
+            </value>
+          </parameter>
+        </property>
+
+      </profile>
+    </mimeprofile>
+
+    <!-- vCard 2.1 datatype, using vCard profile defined above -->
+    <datatype name="vCard21" basetype="vcard">
+      <version>2.1</version>
+      <use mimeprofile="vCard"/>
+    </datatype>
+
+    <!-- vCard 3.0 datatype, using vCard profile defined above -->
+    <datatype name="vCard30" basetype="vcard">
+      <version>3.0</version>
+      <use mimeprofile="vCard"/>
+    </datatype>
+
+
+    <!-- common field list for events and todos (both represented by vCalendar/iCalendar) -->
+    <fieldlist name="calendar">
+      <field name="SYNCLVL" type="integer" compare="never"/>
+      <field name="ISEVENT" type="integer" compare="always"/>
+
+      <field name="DMODIFIED" type="timestamp" compare="never" age="yes"/>
+      <field name="DCREATED" type="timestamp" compare="never"/>
+
+      <field name="DGENERATED" type="timestamp" compare="never"/>
+
+      <field name="UID" type="string" compare="never"/>
+
+      <field name="CATEGORIES" array="yes" type="string" compare="conflict" merge="fillempty"/>
+      <field name="CLASS" type="integer" compare="conflict" merge="fillempty"/>
+      <field name="TRANSP" type="integer" compare="conflict" merge="fillempty"/>
+
+      <field name="SUMMARY" type="multiline" compare="always"/>
+      <field name="DESCRIPTION" type="multiline" compare="slowsync" merge="lines"/>
+      <field name="LOCATION" type="multiline" compare="slowsync" merge="lines"/>
+
+      <!-- recurrence rule block, fields must be in that order, including
+           DTSTART as last field !! -->
+      <field name="RR_FREQ" type="string" compare="conflict"/>
+      <field name="RR_INTERVAL" type="integer" compare="conflict"/>
+      <field name="RR_FMASK" type="integer" compare="conflict"/>
+      <field name="RR_LMASK" type="integer" compare="conflict"/>
+      <field name="RR_END" type="timestamp" compare="conflict"/>
+
+      <!-- Note: DTSTART/DTEND are compared in the <comparescript>,
+                 therefore compare is set no "never" here -->
+      <field name="DTSTART" type="timestamp" compare="never"/>
+      <field name="DTEND" type="timestamp" compare="never"/>
+      <field name="DURATION" type="timestamp" compare="never"/>
+      <field name="COMPLETED" type="timestamp" compare="never"/>
+      <field name="DUE" type="timestamp" compare="never"/>
+
+      <field name="GEO_LAT" type="string" compare="never"/>
+      <field name="GEO_LONG" type="string" compare="never"/>
+
+      <field name="PRIORITY" type="integer" compare="conflict"/>
+      <field name="STATUS" type="integer" compare="conflict" merge="fillempty"/>
+
+      <field name="ALARM_TIME" type="timestamp" compare="conflict"/>
+      <field name="ALARM_SNOOZE" type="string" compare="conflict"/>
+      <field name="ALARM_REPEAT" type="string" compare="conflict"/>
+      <field name="ALARM_MSG" type="string" compare="conflict"/>
+      <field name="ALARM_ACTION" type="string" compare="conflict"/>
+      <field name="ALARM_REL" type="integer" compare="never"/>
+
+      <!-- non-standard -->
+      <field name="PARENT_UID" type="string" compare="never"/>
+
+      <!-- for events -->
+      <field name="EXDATES" array="yes" type="timestamp" compare="never"/>
+
+      <field name="ORIGSTART" array="no" type="timestamp" compare="never"/>
+      <field name="SEQNO" array="no" type="integer" compare="never"/>
+
+      <field name="ATTENDEES" array="yes" type="string" compare="never"/>
+      <field name="ATTENDEE_CNS" array="yes" type="string" compare="never"/>
+      <field name="ATTENDEE_PARTSTATS" array="yes" type="integer" compare="never"/>
+      <field name="ORGANIZER" array="no" type="string" compare="never"/>
+      <field name="ORGANIZER_CN" array="no" type="string" compare="never"/>
+
+    </fieldlist>
+
+
+    <!-- vCalendar with VTODO and VEVENT variants -->
+    <mimeprofile name="vCalendar" fieldlist="calendar">
+
+      <vtimezonegenmode>current</vtimezonegenmode>
+      <tzidgenmode>olson</tzidgenmode>
+
+      <profile name="VCALENDAR" nummandatory="1">
+
+        <property name="VERSION" mandatory="yes">
+          <value conversion="version"/>
+        </property>
+
+        <property onlyformode="standard" name="PRODID" mandatory="no">
+          <value conversion="prodid"/>
+        </property>
+
+        <property onlyformode="old" name="TZ" filter="false" suppressempty="yes">
+          <value field="DTSTART" conversion="tz"/>
+        </property>
+
+        <property onlyformode="old" name="DAYLIGHT" mode="daylight" filter="false" suppressempty="yes">
+          <value field="DTSTART" conversion="daylight"/>
+        </property>
+
+        <property name="GEO" values="2" suppressempty="yes" onlyformode="old" valueseparator=",">
+          <!-- LON,LAT in vCalendar 1.0 -->
+          <value index="0" field="GEO_LAT"/>
+          <value index="1" field="GEO_LONG"/>
+        </property>
+
+        <subprofile onlyformode="standard" name="VTIMEZONE" mode="vtimezones"/>
+
+        <!-- sub-profile for todoz -->
+        <subprofile name="VTODO" nummandatory="1" showifselectedonly="yes" field="ISEVENT" value="0">
+
+          <property name="LAST-MODIFIED">
+            <value field="DMODIFIED"/>
+          </property>
+
+          <property name="DTSTAMP" suppressempty="yes" onlyformode="standard">
+            <value field="DGENERATED"/>
+          </property>
+
+          <property name="DCREATED" suppressempty="yes" onlyformode="old">
+            <value field="DCREATED"/>
+          </property>
+          <property name="CREATED" suppressempty="yes" onlyformode="standard">
+            <value field="DCREATED"/>
+          </property>
+
+          <property name="UID" suppressempty="yes">
+            <value field="UID"/>
+          </property>
+
+          <property name="SEQUENCE" suppressempty="yes">
+            <value field="SEQNO"/>
+          </property>
+
+          <property name="GEO" values="2" suppressempty="yes" onlyformode="standard" valueseparator=";">
+            <!-- LAT;LON in iCalendar 2.0 -->
+            <value index="0" field="GEO_LONG"/>
+            <value index="1" field="GEO_LAT"/>
+          </property>
+
+          <property onlyformode="standard" name="CATEGORIES" values="list" valueseparator="," suppressempty="yes">
+            <value field="CATEGORIES" />
+            <position field="CATEGORIES" repeat="array" minshow="0"/>
+          </property>
+
+          <property onlyformode="old" name="CATEGORIES" values="list" valueseparator=";" altvalueseparator="," suppressempty="yes">
+            <value field="CATEGORIES" />
+            <position field="CATEGORIES" repeat="array" minshow="0"/>
+          </property>
+
+          <property name="CLASS" suppressempty="yes">
+            <value field="CLASS">
+              <enum name="PUBLIC"       value="0"/>
+              <enum name="PRIVATE"      value="1"/>
+              <enum name="CONFIDENTIAL" value="2"/>
+            </value>
+          </property>
+
+          <property name="SUMMARY" mandatory="yes">
+            <value field="SUMMARY"/>
+          </property>
+
+          <property name="DESCRIPTION" mandatory="yes">
+            <value field="DESCRIPTION"/>
+          </property>
+
+          <property name="LOCATION" mandatory="no">
+            <value field="LOCATION"/>
+          </property>
+
+          <property name="DTSTART" suppressempty="yes" delayedparsing="1">
+            <value field="DTSTART" conversion="autodate"/>
+            <parameter onlyformode="standard" name="TZID" default="no" show="yes">
+              <value field="DTSTART" conversion="TZID"/>
+            </parameter>
+            <parameter onlyformode="standard" name="VALUE" default="no" show="yes">
+              <value field="DTSTART" conversion="VALUETYPE"/>
+            </parameter>
+          </property>
+
+          <property name="COMPLETED" suppressempty="yes" delayedparsing="1">
+            <value field="COMPLETED" conversion="autoenddate"/>
+            <parameter onlyformode="standard" name="TZID" default="no" show="yes">
+              <value field="COMPLETED" conversion="TZID"/>
+            </parameter>
+            <parameter onlyformode="standard" name="VALUE" default="no" show="yes">
+              <value field="COMPLETED" conversion="VALUETYPE"/>
+            </parameter>
+          </property>
+
+          <property name="DUE" suppressempty="yes" delayedparsing="1">
+            <value field="DUE" conversion="autodate"/>
+            <parameter onlyformode="standard" name="TZID" default="no" show="yes">
+              <value field="DUE" conversion="TZID"/>
+            </parameter>
+            <parameter onlyformode="standard" name="VALUE" default="no" show="yes">
+              <value field="DUE" conversion="VALUETYPE"/>
+            </parameter>
+          </property>
+
+          <property name="PRIORITY" suppressempty="yes">
+            <value field="PRIORITY"/>
+          </property>
+
+          <property name="STATUS" onlyformode="standard" suppressempty="yes">
+            <value field="STATUS" conversion="emptyonly">
+              <enum name="COMPLETED"      value="0"/>
+              <enum name="NEEDS-ACTION"   value="1"/>
+              <enum name="IN-PROCESS"     value="2"/>
+              <enum name="CANCELLED"      value="3"/>
+              <enum name="ACCEPTED"       value="4"/>
+              <enum name="TENTATIVE"      value="5"/>
+              <enum name="DELEGATED"      value="6"/>
+              <enum name="DECLINED"       value="7"/>
+              <enum name="SENT"           value="8"/>
+              <enum name="CONFIRMED"      value="9"/>
+              <enum name="DRAFT"          value="10"/>
+              <enum name="FINAL"          value="11"/>
+            </value>
+          </property>
+
+          <property name="STATUS" onlyformode="old" suppressempty="yes">
+            <value field="STATUS" conversion="emptyonly">
+              <enum name="COMPLETED"      value="0"/>
+              <enum name="NEEDS ACTION"   value="1"/>
+              <enum mode="defaultvalue"   value="1"/> <!-- catch unknown, but also non-conformant NEEDS_ACTION -->
+              <enum name="IN PROCESS"     value="2"/>
+              <enum name="CANCELLED"      value="3"/>
+              <enum name="ACCEPTED"       value="4"/>
+              <enum name="TENTATIVE"      value="5"/>
+              <enum name="DELEGATED"      value="6"/>
+              <enum name="DECLINED"       value="7"/>
+              <enum name="SENT"           value="8"/>
+              <enum name="CONFIRMED"      value="9"/>
+              <enum name="DRAFT"          value="10"/>
+              <enum name="FINAL"          value="11"/>
+            </value>
+          </property>
+
+
+          <!-- AALARM and DALARM both use the same fields -->
+          <property name="AALARM" onlyformode="old" values="4" suppressempty="yes">
+            <value index="0" field="ALARM_TIME" conversion="emptyonly"/>
+            <value index="1" field="ALARM_SNOOZE" conversion="emptyonly"/>
+            <value index="2" field="ALARM_REPEAT" conversion="emptyonly"/>
+            <value index="3" field="ALARM_MSG" conversion="emptyonly"/>
+          </property>
+          <property name="DALARM" onlyformode="old" values="4" suppressempty="yes">
+            <value index="0" field="ALARM_TIME" conversion="emptyonly"/>
+            <value index="1" field="ALARM_SNOOZE" conversion="emptyonly"/>
+            <value index="2" field="ALARM_REPEAT" conversion="emptyonly"/>
+            <value index="3" field="ALARM_MSG" conversion="emptyonly"/>
+          </property>
+
+          <subprofile onlyformode="standard" name="VALARM" nummandatory="1" field="ALARM_TIME">
+            <property name="TRIGGER" suppressempty="no" mandatory="yes">
+              <value field="ALARM_TIME"/>
+              <parameter name="VALUE" default="no" show="yes">
+                <value field="ALARM_TIME" conversion="FULLVALUETYPE"/>
+              </parameter>
+              <parameter name="RELATED" default="no" show="yes">
+                <value field="ALARM_REL">
+                  <enum mode="ignore" value="0"/>
+                  <enum name="START" value="1"/>
+                  <enum name="END"   value="2"/>
+                </value>
+              </parameter>
+            </property>
+            <property name="ACTION" suppressempty="yes" mandatory="yes">
+              <value field="ALARM_ACTION"/>
+            </property>
+            <property name="DESCRIPTION" suppressempty="yes">
+              <value field="ALARM_MSG"/>
+            </property>
+            <property name="REPEAT" suppressempty="yes">
+              <value field="ALARM_REPEAT"/>
+            </property>
+          </subprofile>
+
+          <property onlyformode="old" name="RELATED-TO" suppressempty="yes">
+            <value field="PARENT_UID"/>
+          </property>
+
+          <property onlyformode="standard" name="RELATED-TO" suppressempty="yes">
+            <value field="PARENT_UID"/>
+            <parameter onlyformode="standard" name="RELTYPE" default="no" positional="yes" show="yes">
+              <value>
+                <enum name="PARENT"/>
+                <enum mode="defaultvalue" name="other"/>
+              </value>
+              <position hasnot="other" shows="PARENT" field="PARENT_UID"/>
+            </parameter>
+          </property>
+
+        </subprofile>
+
+        <!-- sub-profile for event -->
+        <subprofile name="VEVENT" nummandatory="1" showifselectedonly="yes" field="ISEVENT" value="1">
+
+          <property name="LAST-MODIFIED">
+            <value field="DMODIFIED"/>
+          </property>
+
+          <property name="DTSTAMP" suppressempty="yes" onlyformode="standard">
+            <value field="DGENERATED"/>
+          </property>
+
+          <property name="DCREATED" suppressempty="yes" onlyformode="old">
+            <value field="DCREATED"/>
+          </property>
+          <property name="CREATED" suppressempty="yes" onlyformode="standard">
+            <value field="DCREATED"/>
+          </property>
+
+
+          <property name="UID" suppressempty="yes">
+            <value field="UID"/>
+          </property>
+
+          <property name="SEQUENCE" suppressempty="yes">
+            <value field="SEQNO"/>
+          </property>
+
+          <property name="GEO" values="2" suppressempty="yes" onlyformode="standard" valueseparator=";">
+            <!-- LAT;LON in iCalendar 2.0 -->
+            <value index="0" field="GEO_LONG"/>
+            <value index="1" field="GEO_LAT"/>
+          </property>
+
+          <property onlyformode="standard" name="CATEGORIES" values="list" valueseparator="," suppressempty="yes">
+            <value field="CATEGORIES" />
+            <position field="CATEGORIES" repeat="array" minshow="0"/>
+          </property>
+
+          <property onlyformode="old" name="CATEGORIES" values="list" valueseparator=";" altvalueseparator="," suppressempty="yes">
+            <value field="CATEGORIES" />
+            <position field="CATEGORIES" repeat="array" minshow="0"/>
+          </property>
+
+          <property name="CLASS" suppressempty="yes">
+            <value field="CLASS">
+              <enum name="PUBLIC"       value="0"/>
+              <enum name="PRIVATE"      value="1"/>
+              <enum name="CONFIDENTIAL" value="2"/>
+            </value>
+          </property>
+
+
+          <property name="TRANSP" suppressempty="yes" onlyformode="standard">
+            <value field="TRANSP">
+              <enum name="OPAQUE"       value="0"/>
+              <enum name="TRANSPARENT"  value="1"/>
+              <enum name="TENTATIVE"     value="2"/> <!-- according to Oracle de facto usage in vCalendar 1.0 -->
+              <enum name="OUT_OF_OFFICE" value="3"/> <!-- according to Oracle de facto usage in vCalendar 1.0 -->
+              <enum mode="defaultvalue" value="0"/>
+            </value>
+          </property>
+          <property name="TRANSP" suppressempty="yes" onlyformode="old">
+            <value field="TRANSP"/> <!-- directly numeric in vCalendar 1.0 -->
+          </property>
+
+
+          <property name="PRIORITY" suppressempty="yes">
+            <value field="PRIORITY"/>
+          </property>
+
+          <property name="SUMMARY" mandatory="yes">
+            <value field="SUMMARY"/>
+          </property>
+
+          <property name="DESCRIPTION" mandatory="yes">
+            <value field="DESCRIPTION"/>
+          </property>
+
+          <property name="LOCATION" mandatory="no">
+            <value field="LOCATION"/>
+          </property>
+
+          <property name="DTSTART" suppressempty="yes" delayedparsing="1">
+            <value field="DTSTART" conversion="autodate"/>
+            <parameter onlyformode="standard" name="TZID" default="no" show="yes">
+              <value field="DTSTART" conversion="TZID"/>
+            </parameter>
+            <parameter onlyformode="standard" name="VALUE" default="no" show="yes">
+              <value field="DTSTART" conversion="VALUETYPE"/>
+            </parameter>
+          </property>
+
+          <!-- recurrence rule (with delayed parsing, as it is dependent on DTSTART) -->
+          <property name="RRULE" suppressempty="yes" delayedparsing="2">
+            <!-- Note: RR_FREQ is the beginning of a block of fields
+                 suitable for the "rrule" conversion mode -->
+            <value field="RR_FREQ" conversion="rrule"/>
+          </property>
+
+          <!-- Symbian uses this, so it might make the client work with symbian-prepared servers better -->
+          <property name="X-RECURRENCE-ID" suppressempty="yes" onlyformode="old">
+            <value field="ORIGSTART" conversion="autodate"/>
+          </property>
+
+          <property name="RECURRENCE-ID" suppressempty="yes" onlyformode="standard" delayedparsing="1">
+            <value field="ORIGSTART" conversion="autodate"/>
+            <parameter name="TZID" default="no" show="yes">
+              <value field="ORIGSTART" conversion="TZID"/>
+            </parameter>
+            <parameter name="VALUE" default="no" show="yes">
+              <value field="ORIGSTART" conversion="VALUETYPE"/>
+            </parameter>
+          </property>
+
+          <property name="EXDATE" values="list" suppressempty="yes" onlyformode="standard" delayedparsing="1" valueseparator="," altvalueseparator=";">
+            <value field="EXDATES"/>
+            <position field="EXDATES" repeat="array" increment="1" minshow="0"/>
+            <parameter name="TZID" default="no" show="yes">
+              <value field="EXDATES" conversion="TZID"/>
+            </parameter>
+          </property>
+
+          <property name="EXDATE" values="list" suppressempty="yes" onlyformode="old" delayedparsing="1" valueseparator=";" altvalueseparator=",">
+            <value field="EXDATES"/>
+            <position field="EXDATES" repeat="array" increment="1" minshow="0"/>
+          </property>
+
+
+          <property name="DTEND" suppressempty="yes" delayedparsing="1">
+            <value field="DTEND" conversion="autoenddate"/>
+            <parameter onlyformode="standard" name="TZID" default="no" show="yes">
+              <value field="DTEND" conversion="TZID"/>
+            </parameter>
+            <parameter onlyformode="standard" name="VALUE" default="no" show="yes">
+              <value field="DTEND" conversion="VALUETYPE"/>
+            </parameter>
+          </property>
+
+          <property name="DURATION" suppressempty="yes" delayedparsing="1" onlyformode="standard">
+            <value field="DURATION"/>
+            <parameter onlyformode="standard" name="VALUE" default="no" show="no">
+              <value field="DURATION" conversion="VALUETYPE"/>
+            </parameter>
+          </property>
+
+          <property name="ATTENDEE" suppressempty="yes" onlyformode="old">
+            <value field="ATTENDEES"/>
+            <parameter name="ROLE" default="no" positional="yes" show="yes">
+              <value>
+                <enum name="ORGANIZER"/>
+              </value>
+              <position has="ORGANIZER" field="ORGANIZER" overwriteempty="yes"/>
+              <position hasnot="ORGANIZER" field="ATTENDEES" repeat="array" increment="1" overwriteempty="yes"/>
+            </parameter>
+            <parameter name="STATUS" default="no" show="yes">
+              <value field="ATTENDEE_PARTSTATS">
+                <enum name="NEEDS ACTION"   value="1"/>
+                <enum mode="defaultvalue"   value="1"/> <!-- catch unknown, but also non-conformant NEEDS_ACTION -->
+                <enum name="ACCEPTED"       value="4"/>
+                <enum name="DECLINED"       value="7"/>
+                <enum name="TENTATIVE"      value="5"/>
+                <enum name="DELEGATED"      value="6"/>
+              </value>
+            </parameter>
+          </property>
+
+          <property name="ATTENDEE" suppressempty="yes" onlyformode="standard">
+            <value field="ATTENDEES" conversion="mailto"/>
+            <position field="ATTENDEES" repeat="array" increment="1" minshow="0"/>
+            <parameter name="CN" default="no" show="yes" shownonempty="yes">
+              <value field="ATTENDEE_CNS"/>
+            </parameter>
+            <parameter name="PARTSTAT" default="no" show="yes">
+              <value field="ATTENDEE_PARTSTATS">
+                <enum name="NEEDS-ACTION"   value="1"/>
+                <enum mode="defaultvalue"   value="1"/> <!-- catch unknown, but also non-conformant NEEDS_ACTION -->
+                <enum name="ACCEPTED"       value="4"/>
+                <enum name="DECLINED"       value="7"/>
+                <enum name="TENTATIVE"      value="5"/>
+                <enum name="DELEGATED"      value="6"/>
+              </value>
+            </parameter>
+          </property>
+
+          <property name="ORGANIZER" suppressempty="yes" onlyformode="standard">
+            <value field="ORGANIZER" conversion="mailto"/>
+            <parameter name="CN" default="no" show="yes">
+              <value field="ORGANIZER_CN"/>
+            </parameter>
+          </property>
+
+
+          <!-- AALARM and DALARM both use the same fields -->
+          <property name="AALARM" onlyformode="old" values="4" suppressempty="yes">
+            <value index="0" field="ALARM_TIME" conversion="emptyonly"/>
+            <value index="1" field="ALARM_SNOOZE" conversion="emptyonly"/>
+            <value index="2" field="ALARM_REPEAT" conversion="emptyonly"/>
+            <value index="3" field="ALARM_MSG" conversion="emptyonly"/>
+          </property>
+          <property name="DALARM" onlyformode="old" values="4" suppressempty="yes">
+            <value index="0" field="ALARM_TIME" conversion="emptyonly"/>
+            <value index="1" field="ALARM_SNOOZE" conversion="emptyonly"/>
+            <value index="2" field="ALARM_REPEAT" conversion="emptyonly"/>
+            <value index="3" field="ALARM_MSG" conversion="emptyonly"/>
+          </property>
+
+          <subprofile onlyformode="standard" name="VALARM" nummandatory="1" field="ALARM_TIME">
+            <property name="TRIGGER" suppressempty="no" mandatory="yes">
+              <value field="ALARM_TIME"/>
+              <parameter name="VALUE" default="no" show="yes">
+                <value field="ALARM_TIME" conversion="FULLVALUETYPE"/>
+              </parameter>
+              <parameter name="RELATED" default="no" show="yes">
+                <value field="ALARM_REL">
+                  <enum mode="ignore" value="0"/>
+                  <enum name="START" value="1"/>
+                  <enum name="END"   value="2"/>
+                </value>
+              </parameter>
+            </property>
+            <property name="ACTION" suppressempty="yes" mandatory="yes">
+              <value field="ALARM_ACTION"/>
+            </property>
+            <property name="DESCRIPTION" suppressempty="yes">
+              <value field="ALARM_MSG"/>
+            </property>
+            <property name="REPEAT" suppressempty="yes">
+              <value field="ALARM_REPEAT"/>
+            </property>
+          </subprofile>
+
+        </subprofile>
+
+      </profile>
+    </mimeprofile>
+
+
+    <!-- vCalendar 1.0 datatype, using vCalendar profile defined above -->
+    <datatype name="vCalendar10" basetype="vcalendar">
+      <version>1.0</version>
+      <use mimeprofile="vCalendar"/>
+
+      <incomingscript><![CDATA[
+        $VCALENDAR_INCOMING_SCRIPT
+      ]]></incomingscript>
+
+      <outgoingscript><![CDATA[
+        $VCALENDAR_OUTGOING_SCRIPT
+      ]]></outgoingscript>
+
+    </datatype>
+
+
+    <!-- iCalendar 2.0 datatype, using vCalendar profile defined above -->
+    <datatype name="iCalendar20" basetype="vcalendar">
+      <version>2.0</version>
+      <use mimeprofile="vCalendar"/>
+
+      <incomingscript><![CDATA[
+        $VCALENDAR_INCOMING_SCRIPT
+      ]]></incomingscript>
+
+      <outgoingscript><![CDATA[
+        $VCALENDAR_OUTGOING_SCRIPT
+      ]]></outgoingscript>
+
+    </datatype>
+
+
+    <!-- list of internal fields representing plain text note data -->
+    <fieldlist name="Note">
+      <field name="SYNCLVL" type="integer" compare="never"/>
+      <field name="SUBJECT" type="multiline" compare="always"/>
+      <field name="TEXT" type="multiline" compare="conflict" merge="lines"/>
+    </fieldlist>
+
+    <textprofile name="Note" fieldlist="Note">
+      <linemap field="SUBJECT">
+        <numlines>1</numlines>
+        <inheader>false</inheader>
+        <allowempty>true</allowempty>
+        <filterkeyword>SUBJECT</filterkeyword>
+      </linemap>
+      <linemap field="TEXT">
+        <numlines>0</numlines>
+        <inheader>false</inheader>
+        <allowempty>true</allowempty>
+      </linemap>
+    </textprofile>
+
+    <datatype name="note" basetype="text">
+      <use profile="Note"/>
+      <typestring>text/plain</typestring>
+      <versionstring>1.0</versionstring>
+    </datatype>
+
+    <datatype name="note11" basetype="text">
+      <use profile="Note"/>
+      <typestring>text/plain</typestring>
+      <versionstring>1.1</versionstring>
+    </datatype>
+
+
+    <!-- list of internal fields representing vBookmark data -->
+    <fieldlist name="bookmarks">
+      <field name="REV" type="timestamp" compare="never" age="yes"/>
+      <field name="SYNCLVL" type="integer" compare="never"/>
+
+      <!-- Name -->
+      <field name="TITLE" type="string" compare="always"/>
+
+      <!-- categories and classification -->
+      <field name="CATEGORIES" type="string" compare="conflict" merge="fillempty"/>
+      <field name="CLASS" type="string" compare="conflict" merge="fillempty"/>
+
+      <!-- web addresses -->
+      <field name="URL" type="url" compare="slowsync" merge="fillempty"/>
+
+      <!-- Note -->
+      <field name="NOTE" type="multiline" compare="conflict" merge="lines"/>
+
+    </fieldlist>
+
+    <!-- vBookmark profile -->
+    <mimeprofile name="vbookmark" fieldlist="bookmarks">
+
+      <profile name="VBKM" nummandatory="0">
+        <property name="VERSION">
+          <value conversion="version"/>
+        </property>
+
+        <property name="X-LAST-MODIFIED">
+          <value field="REV"/>
+        </property>
+
+        <property name="TITLE">
+          <value field="TITLE"/>
+        </property>
+
+        <property name="URL">
+          <value field="URL"/>
+        </property>
+
+        <!-- non-standard properties -->
+
+        <!-- inherit CATEGORIES from vCard 3.0, i.e. comma separated -->
+        <property name="CATEGORIES" values="list" valueseparator="," altvalueseparator=";">
+          <value field="CATEGORIES" combine=","/>
+        </property>
+
+        <property name="CLASS" suppressempty="yes">
+          <value field="CLASS"/>
+        </property>
+
+        <property name="NOTE" filter="no">
+          <value field="NOTE"/>
+        </property>
+
+      </profile>
+    </mimeprofile>
+
+    <!-- vBookmark datatype, using vBookmark profile defined above -->
+    <datatype name="vbookmark" basetype="mimedir">
+      <typestring>text/x-vbookmark</typestring>
+      <versionstring>1.0</versionstring>
+      <use profile="vbookmark"/>
+    </datatype>
+
+
+
+    <!-- list of internal fields representing email data -->
+    <fieldlist name="email">
+      <field name="SYNCLVL" type="integer" compare="never"/>
+      <field name="MODIFIED" type="timestamp" compare="never" age="yes"/>
+      <field name="SENDER" type="multiline" compare="always"/>
+      <field name="RECEIVER" type="multiline" compare="always"/>
+      <field name="CARBONCOPY" type="multiline" compare="always"/>
+      <field name="BLINDCARBONCOPY" type="multiline" compare="always"/>
+      <field name="REPLY_TO" type="multiline" compare="never"/>
+      <field name="SUBJECT" type="multiline" compare="always"/>
+      <field name="PRIORITY" type="integer" compare="never"/>
+      <field name="MAILDATE" type="timestamp" compare="never"/>
+      <field name="STATUS" type="string" compare="never"/>
+      <field name="FOLDER" type="string" compare="conflict"/>
+      <field name="ISREAD" type="string" compare="never"/>
+      <field name="LIMIT" type="integer" compare="never"/>
+      <field name="BODY" type="multiline" compare="never"/>
+      <field name="ATT_COUNT" type="integer" compare="never"/>
+      <field name="ATT_NAMES" array="yes" type="string" compare="never"/>
+      <field name="ATT_MIMETYPES" array="yes" type="string" compare="never"/>
+      <field name="ATT_SIZES" array="yes" type="integer" compare="never"/>
+      <field name="ATT_CONTENTS" array="yes" type="blob" compare="never"/>
+    </fieldlist>
+
+
+    <!-- this is the text profile used to generate and decode RFC2822/MIME-Multipart
+         email messages. -->
+    <textprofile name="rfc2822_email" fieldlist="email">
+
+      <mimemail>true</mimemail>
+      <!-- attachment configuration -->
+      <maxattachments>100</maxattachments>
+      <attachmentcountfield>ATT_COUNT</attachmentcountfield>
+      <attachmentmimetypesfield>ATT_MIMETYPES</attachmentmimetypesfield>
+      <attachmentsfield>ATT_CONTENTS</attachmentsfield>
+      <attachmentsizesfield>ATT_SIZES</attachmentsizesfield>
+      <attachmentnamesfield>ATT_NAMES</attachmentnamesfield>
+      <sizelimitfield>LIMIT</sizelimitfield>
+
+
+      <linemap field="SENDER">
+        <headertag>From:</headertag>
+        <valuetype>rfc2047</valuetype>
+        <inheader>true</inheader>
+        <filterkeyword>FROM</filterkeyword>
+      </linemap>
+
+      <linemap field="RECEIVER">
+        <headertag>To:</headertag>
+        <valuetype>rfc2047</valuetype>
+        <inheader>true</inheader>
+        <filterkeyword>TO</filterkeyword>
+      </linemap>
+
+      <linemap field="CARBONCOPY">
+        <headertag>Cc:</headertag>
+        <valuetype>rfc2047</valuetype>
+        <inheader>true</inheader>
+        <filterkeyword>CC</filterkeyword>
+      </linemap>
+
+      <linemap field="BLINDCARBONCOPY">
+        <headertag>Bcc:</headertag>
+        <valuetype>rfc2047</valuetype>
+        <inheader>true</inheader>
+        <filterkeyword>BCC</filterkeyword>
+      </linemap>
+
+      <linemap field="REPLY_TO">
+        <headertag>Reply-To:</headertag>
+        <valuetype>rfc2047</valuetype>
+        <inheader>true</inheader>
+      </linemap>
+
+      <linemap field="SUBJECT">
+        <headertag>Subject:</headertag>
+        <valuetype>rfc2047</valuetype>
+        <inheader>true</inheader>
+        <filterkeyword>SUBJECT</filterkeyword>
+      </linemap>
+
+      <linemap field="PRIORITY">
+        <headertag>X-Priority:</headertag>
+        <inheader>true</inheader>
+      </linemap>
+
+      <linemap field="MAILDATE">
+        <valuetype>date</valuetype>
+        <headertag>Date:</headertag>
+        <inheader>true</inheader>
+      </linemap>
+
+      <linemap field="STATUS">
+        <headertag>Status:</headertag>
+        <inheader>true</inheader>
+      </linemap>
+
+      <linemap field="FOLDER">
+        <headertag>X-Sync-Parent-Folder:</headertag>
+        <inheader>true</inheader>
+      </linemap>
+
+      <linemap field="ISREAD">
+        <headertag>X-Sync-Message-Read:</headertag>
+        <inheader>true</inheader>
+      </linemap>
+
+      <linemap field="MODIFIED">
+        <!-- note that this is a ISO8601 date -->
+        <headertag>X-Sync-Lastmodified:</headertag>
+        <inheader>true</inheader>
+      </linemap>
+
+      <linemap field="BODY">
+        <valuetype>body</valuetype>
+        <numlines>0</numlines>
+        <inheader>false</inheader>
+        <allowempty>true</allowempty>
+      </linemap>
+    </textprofile>
+
+
+    <datatype name="email" basetype="text">
+      <use profile="rfc2822_email"/>
+      <typestring>text/message</typestring> <!-- this is P800-like -->
+      <versionstring>1.0</versionstring>
+
+      <initscript><![CDATA[
+        $EMAIL_INIT_SCRIPT
+      ]]></initscript>
+
+      <processitemscript><![CDATA[
+        $EMAIL_PROCESSITEM_SCRIPT
+      ]]></processitemscript>
+
+
+      <mergescript><![CDATA[
+        $EMAIL_MERGE_SCRIPT
+      ]]></mergescript>
+
+
+      <outgoingscript><![CDATA[
+        $EMAIL_OUTGOING_SCRIPT
+      ]]></outgoingscript>
+
+      <filterinitscript><![CDATA[
+        $EMAIL_FILTERINIT_SCRIPT
+      ]]></filterinitscript>
+
+
+      <filterscript><![CDATA[
+        $EMAIL_FILTER_SCRIPT
+      ]]></filterscript>
+
+    </datatype>
+
+
+    <!-- Note: This is a proprietary extension datatype for Synthesis AG Windows Mobile SyncML clients.
+         This format is a compressed form of the standard RFC2822 format. For one, the entire data
+         is compressed using the zip algorithm (<zippedbindata>), and secondly attachments are included
+         in binary form in the RFC2822 data stream rather than bandwidth wasting B64, adding a
+         "Content-Length:" header for each MIME part (<binaryparts>). -->
+
+    <datatype name="email_zipbin" basetype="text">
+      <use profile="rfc2822_email"/>
+      <typestring>application/x-zip-message</typestring> <!-- our own private zipped binary optimized format -->
+      <versionstring>1.1</versionstring>
+      <binaryparts>yes</binaryparts>
+      <zippedbindata>yes</zippedbindata>
+      <zipcompressionlevel>9</zipcompressionlevel> <!-- -1=default, 0=no compression, 1=fast & least effective ... 9=slow and most effective -->
+
+      <initscript><![CDATA[
+        $EMAIL_INIT_SCRIPT
+      ]]></initscript>
+
+      <processitemscript><![CDATA[
+        $EMAIL_PROCESSITEM_SCRIPT
+      ]]></processitemscript>
+
+
+      <mergescript><![CDATA[
+        $EMAIL_MERGE_SCRIPT
+      ]]></mergescript>
+
+
+      <outgoingscript><![CDATA[
+        $EMAIL_OUTGOING_SCRIPT
+      ]]></outgoingscript>
+
+      <filterinitscript><![CDATA[
+        $EMAIL_FILTERINIT_SCRIPT
+      ]]></filterinitscript>
+
+
+      <filterscript><![CDATA[
+        $EMAIL_FILTER_SCRIPT
+      ]]></filterscript>
+
+    </datatype>
+
+
+
+    <datatype name="email_sonyericsson" basetype="text">
+      <use profile="rfc2822_email"/>
+      <typestring>message/rfc822</typestring> <!-- this is M600i/P990-like -->
+      <versionstring>1.0</versionstring>
+
+      <initscript><![CDATA[
+        $EMAIL_INIT_SCRIPT
+      ]]></initscript>
+
+      <processitemscript><![CDATA[
+        $EMAIL_PROCESSITEM_SCRIPT
+      ]]></processitemscript>
+
+
+      <mergescript><![CDATA[
+        $EMAIL_MERGE_SCRIPT
+      ]]></mergescript>
+
+
+      <outgoingscript><![CDATA[
+        $EMAIL_OUTGOING_SCRIPT
+      ]]></outgoingscript>
+
+      <filterinitscript><![CDATA[
+        $EMAIL_FILTERINIT_SCRIPT
+      ]]></filterinitscript>
+
+
+      <filterscript><![CDATA[
+        $EMAIL_FILTER_SCRIPT
+      ]]></filterscript>
+
+    </datatype>
+
+
+    <datatype name="email_nokia9500" basetype="text">
+      <use profile="rfc2822_email"/>
+      <typestring>message/x-rfc822</typestring> <!-- this is Nokia 9500/9300-like -->
+      <versionstring>1.0</versionstring>
+
+      <initscript><![CDATA[
+        INTEGER ITEMLIMIT;
+        // default limit is limit of session
+        ITEMLIMIT = SIZELIMIT();
+      ]]></initscript>
+
+      <processitemscript><![CDATA[
+        INTEGER n;
+
+        // For Nokia Email, we must derive folder ID from source LocURI
+        // which has form "./somestrangenumber/folder/itemid"
+        // where folder can be "Inbox" or "Outbox"
+        if (FIND(REMOTEID(),"Inbox",0)!=UNASSIGNED) {
+          FOLDER="INBOX";
+        }
+        else if (FIND(REMOTEID(),"Outbox",0)!=UNASSIGNED) {
+          FOLDER="OUTBOX";
+        }
+        // pre-process item
+        if (UPPERCASE(FOLDER)=="INBOX") {
+          // In any case, prevent adding to inbox (delete remote items instead)
+          PREVENTADD();
+          // server always wins for inbox
+          CONFLICTSTRATEGY("server-wins");
+          if (SLOWSYNC()) {
+            // also prevent modifications in server
+            IGNOREUPDATE();
+          }
+          else {
+            // normal sync items going to inbox from client need special treatment
+            if (SYNCOP()=="add" || SYNCOP()=="replace") {
+              // make sure that existing server item will conflict with this item
+              if (LIMIT!=EMPTY && (LIMIT<0 || LIMIT>SIZELIMIT())) {
+                // force conflict only if this is a reload
+                FORCECONFLICT();
+              }
+              // make sure we never overwrite a body in the inbox
+              BODY = UNASSIGNED;
+              // delete always wins over replace in inbox (to avoid adds to inbox)
+              DELETEWINS();
+            }
+          }
+        }
+        else if (UPPERCASE(FOLDER)=="OUTBOX") {
+          // never try to change something in outbox
+          IGNOREUPDATE();
+          if (SYNCOP()!="delete") {
+            // - date of mail is NOW, set it such that a correct date is written to the DB
+            MAILDATE = DBNOW();
+            // MAILDATE = (INTEGER)DBNOW() - TIMEUNITS(120); // %%% backdate it 2 mins to make sure it does not get retransmitted
+            // - echo item as delete (this causes that it is moved to the "sent" folder in the 9500)
+            ECHOITEM("delete");
+          }
+          CONFLICTSTRATEGY("client-wins");
+        }
+        else {
+          // Other folder
+          // - silently discard incoming item for other folder than the above
+          //   except if it is a delete
+          if (SYNCOP()!="delete")
+            REJECTITEM(0);
+        }
+      ]]></processitemscript>
+
+
+      <mergescript><![CDATA[
+        // pre-process item
+        if (UPPERCASE(LOOSING.FOLDER)!="OUTBOX") {
+          // non-outbox (especially inbox) needs special merge to accomplish reload feature
+          // - loosing item is client's, winning is server's
+          if (LOOSING.LIMIT!=EMPTY) {
+            // loosing (remote) item specifies a new limit, override winning's default
+            WINNING.LIMIT=LOOSING.LIMIT;
+            SETWINNINGCHANGED(TRUE);
+          }
+          // make sure winning has right folder
+          WINNING.FOLDER=LOOSING.FOLDER;
+          // make sure a set read-flag gets propagated to server
+          if (LOOSING.ISREAD=="true") WINNING.ISREAD="true";
+          // merge other fields normally
+          MERGEFIELDS();
+          // make sure body does not get re-written to local DB even if merge would cause local update
+          LOOSING.BODY=UNASSIGNED;
+        }
+        else {
+          // normal merging in other folders
+          MERGEFIELDS();
+        }
+      ]]></mergescript>
+
+
+      <outgoingscript><![CDATA[
+        // we can only send to inbox or outbox
+        // - If we have no remote ID (=add command) prepare special Target item ID
+        //   containing target folder.
+        if (REMOTEID()==EMPTY) {
+        if (UPPERCASE(FOLDER)=="INBOX") {
+            SETREMOTEID(REMOTEDBNAME()+"/Inbox/");
+        }
+        else if (UPPERCASE(FOLDER)=="OUTBOX") {
+            SETREMOTEID(REMOTEDBNAME()+"/Outbox/");
+          }
+        }
+      ]]></outgoingscript>
+
+      <filterinitscript><![CDATA[
+        // check if we need to filter
+        INTEGER NEEDFILTER;
+
+        NEEDFILTER =
+          !DBHANDLESOPTS() && // only if DB cannot handle it
+          (STARTDATE()!=EMPTY); // and only if a start date is set (end date not needed as there are never future emails today)
+        SETFILTERALL(NEEDFILTER);
+        RETURN NEEDFILTER;
+      ]]></filterinitscript>
+
+
+      <filterscript><![CDATA[
+        INTEGER PASSES;
+
+        // check if item passes filter
+        PASSES=FALSE;
+        // Filter out anything not for Inbox or Outbox
+        if (UPPERCASE(FOLDER)!="INBOX" && UPPERCASE(FOLDER)!="OUTBOX") RETURN FALSE;
+        // Emails pass if they have a MAILDATE on or later than start date
+        PASSES = MAILDATE>=STARTDATE();
+        RETURN PASSES;
+      ]]></filterscript>
+
+    </datatype>
+
+  </datatypes>
+
+
+  <server type="plugin">
+
+    <!-- Uncomment the following for Linux if you are sure properly working pthread implementation is available
+         For Windows and Mac OS X, multithreading is enabled by default -->
+    <!--<multithread>yes</multithread>-->
+
+
+    <!-- plugin module which handles the session level, i.e. login and device tracking -->
+    <plugin_module>[SDK_textdb]</plugin_module>
+    <plugin_sessionauth>yes</plugin_sessionauth>
+    <plugin_deviceadmin>yes</plugin_deviceadmin>
+
+    <plugin_params>
+      <!-- plugin params can contain any number of plugin-specific parameters
+           that will be passed to the plugin implementation for processing -->
+
+      <!-- For TextDB: text file locations: -->
+      <!-- Uncomment the following tags if you want
+           to specifiy locations for the text files generated by the
+           server. If you leave it commented, all text files will be in the
+           application directory -->
+      <!--
+      <mapfilepath>C:\sync\auxfiles</mapfilepath>
+      <datafilepath>C:\sync\datafiles</datafilepath>
+      -->
+
+      <ultimate_answer>42</ultimate_answer> <!-- just as an example -->
+    </plugin_params>
+
+    <!-- un-comment or change the following directive if you want the server only accept
+         SyncML 1.1 or 1.0 connections - not recommended normally, but
+         eventually useful for testing. By default, the server accepts
+         all 1.2, 1.1 and 1.0 connections -->
+    <!-- <maxsyncmlversion>1.1</maxsyncmlversion> -->
+
+    <!-- IMPORTANT: Note that the following charset, lineend and quoting settings are relevant for session-level data access only.
+         Most data access takes place in individual <datastores>, which each has the same three settings
+         again locally (see below in the <datastore> sections). -->
+
+    <!-- text db plugin is designed for UTF-8, make sure data is passed as UTF-8 (and not the ISO-8859-1 default) -->
+    <datacharset>UTF-8</datacharset>
+    <!-- use C-language (unix style) linefeeds (\n, 0x0A) -->
+    <datalineends>unix</datalineends>
+
+
+    <!-- If you want a text logfile, specify its full path here: -->
+    <!-- <logfile platform="win32">D:\your\log\directory\yourlogfile.txt</logfile> -->
+    <!-- <logfile platform="linux">/your/log/directory/yourlogfile.txt</logfile> -->
+    <!-- <logfile platform="macosx">/your/log/directory/yourlogfile.txt</logfile> -->
+
+    <logenabled>yes</logenabled> <!-- log enabled by default (session login scripts might disable it for special users/devices) -->
+
+    <!-- the logfile format can be customized with <loglabels> and <logformat>
+         but if these are not specified, a default format will be used
+    -->
+    <!-- This sample produces a simplified logfile:
+    <loglabels>SyncEndTime\tUser\tStatus\tSynctype\tRemoteName\tDatabase\tLocAdded\tLocUpdated\tLocDeleted\n\n</loglabels>
+    <logformat>%seT\t%U\t%sS\t%tS\t%nR\t%lD\t%laI\t%luI\t%ldI\n</logformat>
+    -->
+
+
+    <sessioninitscript><![CDATA[
+      // these variables are possibly modified by rule scripts
+      TIMESTAMP mindate; // earliest date remote party can handle
+      INTEGER retransfer_body; // if set to true, body is re-sent to client when message is moved from outbox to sent
+      mindate=EMPTY; // no limit by default
+      retransfer_body=FALSE; // normally, do not retransfer email body (and attachments) when moving items to sent box
+    ]]></sessioninitscript>
+
+    <!-- timeout for unfinished sessions in seconds -->
+    <sessiontimeout>300</sessiontimeout>
+
+    <!-- defines how clients must authenticate with the server
+         To allow simple authentication (unencrypted passwords will
+         be transferred over the net, so be careful)
+         set <requiredauth> to "basic" instead of "md5"
+    -->
+    <requestedauth>md5</requestedauth>
+    <requiredauth>md5</requiredauth>
+    <autononce>yes</autononce>
+
+    <!-- you can comment out <simpleauthuser> and <simpleauthpw>
+         to have the plugin check user authentification.
+         Note that the built-in textdb plugin has a hard-wired test/test
+         user only -->
+    <simpleauthuser>test</simpleauthuser>
+    <simpleauthpw>test</simpleauthpw>
+
+
+
+    <datastore name="contacts" type="plugin">
+
+      <plugin_module>[SDK_textdb]</plugin_module>
+      <plugin_datastoreadmin>yes</plugin_datastoreadmin>
+      <plugin_params>
+        <!-- specify plugin-specific parameters here, they will be
+             passed to the plugin implementation for processing -->
+        <ultimate_answer>42</ultimate_answer> <!-- just as an example -->
+      </plugin_params>
+
+
+      <!-- General datastore settings for all DB types -->
+
+      <!-- if this is set to "yes", SyncML clients can only read
+           from the server database, but make no modifications -->
+      <readonly>no</readonly>
+
+      <!-- conflict strategy: Newer item wins
+           You can set "server-wins" or "client-wins" as well
+           if you want to give one side precedence
+      -->
+      <conflictstrategy>newer-wins</conflictstrategy>
+
+      <!-- on slowsync: duplicate items that are not fully equal
+           You can set this to "newer-wins" as well to avoid
+           duplicates as much as possible
+      -->
+      <slowsyncstrategy>duplicate</slowsyncstrategy>
+
+      <!-- Visibility control: Server items that have the SYNCLVL
+           field set to 0 will be invisible to SyncML clients.
+           Using CGI-filtering in database names (such as
+           ./contacts?SYNCLVL:>=5) smaller clients can
+           sync a reduced set of server items -->
+      <makepassfilter>F.SYNCLVL:=10</makepassfilter>
+      <invisiblefilter>F.SYNCLVL:=0|F.SYNCLVL*=E</invisiblefilter>
+      <makevisiblefilter>F.SYNCLVL:=10</makevisiblefilter>
+
+
+      <!-- text db plugin is designed for UTF-8, make sure data is passed as UTF-8 (and not the ISO-8859-1 default) -->
+      <datacharset>UTF-8</datacharset>
+      <!-- use C-language (unix style) linefeeds (\n, 0x0A) -->
+      <datalineends>unix</datalineends>
+
+      <!-- set this to "UTC" if time values should be stored in UTC into the database
+           rather than local time. "SYSTEM" denotes local server time zone. -->
+      <datatimezone>SYSTEM</datatimezone>
+
+      <!-- plugin DB may have its own identifiers to determine the point in time of changes, so
+           we must make sure this identifier is stored (and not only the sync time) -->
+      <storesyncidentifiers>yes</storesyncidentifiers>
+
+      <!-- TextDB plugin supports resume and resuming partial items, so enable these here -->
+      <resumesupport>yes</resumesupport>
+      <resumeitemsupport>yes</resumeitemsupport>
+
+
+
+      <!-- Mapping of the fields to the fieldlist "contacts" -->
+      <fieldmap fieldlist="contacts">
+        <automap indexasname="true"/>
+      </fieldmap>
+
+      <!-- datatypes supported by this datastore -->
+      <typesupport>
+        <use datatype="vCard30" mode="rw" preferred="yes"/>
+        <use datatype="vCard21" mode="rw" preferred="legacy"/>
+      </typesupport>
+
+    </datastore>
+
+
+
+    <datastore name="events" type="plugin">
+
+      <plugin_module>[SDK_textdb]</plugin_module>
+      <plugin_datastoreadmin>yes</plugin_datastoreadmin>
+      <plugin_params>
+        <!-- specify plugin-specific parameters here, they will be
+             passed to the plugin implementation for processing -->
+        <ultimate_answer>42</ultimate_answer> <!-- just as an example -->
+      </plugin_params>
+
+
+      <!-- General datastore settings for all DB types -->
+
+      <!-- if this is set to "yes", SyncML clients can only read
+           from the server database, but make no modifications -->
+      <readonly>no</readonly>
+
+      <!-- conflict strategy: Newer item wins
+           You can set "server-wins" or "client-wins" as well
+           if you want to give one side precedence
+      -->
+      <conflictstrategy>newer-wins</conflictstrategy>
+
+      <!-- on slowsync: duplicate items that are not fully equal
+           You can set this to "newer-wins" as well to avoid
+           duplicates as much as possible
+      -->
+      <slowsyncstrategy>duplicate</slowsyncstrategy>
+
+      <!-- Visibility control: Server items that have the SYNCLVL
+           field set to 0 will be invisible to SyncML clients.
+           Using CGI-filtering in database names (such as
+           ./contacts?SYNCLVL:>=5) smaller clients can
+           sync a reduced set of server items -->
+      <makepassfilter>F.SYNCLVL:=10</makepassfilter>
+      <invisiblefilter>F.SYNCLVL:=0|F.SYNCLVL*=E</invisiblefilter>
+      <makevisiblefilter>F.SYNCLVL:=10</makevisiblefilter>
+
+
+      <!-- text db plugin is designed for UTF-8, make sure data is passed as UTF-8 (and not the ISO-8859-1 default) -->
+      <datacharset>UTF-8</datacharset>
+      <!-- use C-language (unix style) linefeeds (\n, 0x0A) -->
+      <datalineends>unix</datalineends>
+
+      <!-- set this to "UTC" if time values should be stored in UTC into the database
+           rather than local time. "SYSTEM" denotes local server time zone. -->
+      <datatimezone>SYSTEM</datatimezone>
+
+      <!-- plugin DB may have its own identifiers to determine the point in time of changes, so
+           we must make sure this identifier is stored (and not only the sync time) -->
+      <storesyncidentifiers>yes</storesyncidentifiers>
+
+      <!-- TextDB plugin supports resume and resuming partial items, so enable these here -->
+      <resumesupport>yes</resumesupport>
+      <resumeitemsupport>yes</resumeitemsupport>
+
+
+
+      <!-- Mapping of the fields to the fieldlist "calendar" -->
+      <fieldmap fieldlist="calendar">
+        <automap indexasname="true"/>
+      </fieldmap>
+
+      <!-- datatypes supported by this datastore -->
+      <typesupport>
+        <use datatype="iCalendar20" mode="rw" variant="VEVENT" preferred="yes"/>
+        <use datatype="vCalendar10" mode="rw" variant="VEVENT" preferred="legacy"/>
+      </typesupport>
+
+    </datastore>
+
+
+    <datastore name="tasks" type="plugin">
+
+      <plugin_module>[SDK_textdb]</plugin_module>
+      <plugin_datastoreadmin>yes</plugin_datastoreadmin>
+      <plugin_params>
+        <!-- specify plugin-specific parameters here, they will be
+             passed to the plugin implementation for processing -->
+        <ultimate_answer>42</ultimate_answer> <!-- just as an example -->
+      </plugin_params>
+
+
+      <!-- General datastore settings for all DB types -->
+
+      <!-- if this is set to "yes", SyncML clients can only read
+           from the server database, but make no modifications -->
+      <readonly>no</readonly>
+
+      <!-- conflict strategy: Newer item wins
+           You can set "server-wins" or "client-wins" as well
+           if you want to give one side precedence
+      -->
+      <conflictstrategy>newer-wins</conflictstrategy>
+
+      <!-- on slowsync: duplicate items that are not fully equal
+           You can set this to "newer-wins" as well to avoid
+           duplicates as much as possible
+      -->
+      <slowsyncstrategy>duplicate</slowsyncstrategy>
+
+      <!-- Visibility control: Server items that have the SYNCLVL
+           field set to 0 will be invisible to SyncML clients.
+           Using CGI-filtering in database names (such as
+           ./contacts?SYNCLVL:>=5) smaller clients can
+           sync a reduced set of server items -->
+      <makepassfilter>F.SYNCLVL:=10</makepassfilter>
+      <invisiblefilter>F.SYNCLVL:=0|F.SYNCLVL*=E</invisiblefilter>
+      <makevisiblefilter>F.SYNCLVL:=10</makevisiblefilter>
+
+
+      <!-- text db plugin is designed for UTF-8, make sure data is passed as UTF-8 (and not the ISO-8859-1 default) -->
+      <datacharset>UTF-8</datacharset>
+      <!-- use C-language (unix style) linefeeds (\n, 0x0A) -->
+      <datalineends>unix</datalineends>
+
+      <!-- set this to "UTC" if time values should be stored in UTC into the database
+           rather than local time. "SYSTEM" denotes local server time zone. -->
+      <datatimezone>SYSTEM</datatimezone>
+
+      <!-- plugin DB may have its own identifiers to determine the point in time of changes, so
+           we must make sure this identifier is stored (and not only the sync time) -->
+      <storesyncidentifiers>yes</storesyncidentifiers>
+
+      <!-- TextDB plugin supports resume and resuming partial items, so enable these here -->
+      <resumesupport>yes</resumesupport>
+      <resumeitemsupport>yes</resumeitemsupport>
+
+
+
+      <!-- Mapping of the fields to the fieldlist "calendar" -->
+      <fieldmap fieldlist="calendar">
+        <automap indexasname="true"/>
+      </fieldmap>
+
+      <!-- datatypes supported by this datastore -->
+      <typesupport>
+        <use datatype="iCalendar20" mode="rw" variant="VTODO" preferred="yes"/>
+        <use datatype="vCalendar10" mode="rw" variant="VTODO" preferred="legacy"/>
+      </typesupport>
+
+    </datastore>
+
+
+    <!-- this "superdatastore" makes the two individual
+         "events" and "tasks" datastores accessible as one
+         datastore. This is required for example for
+         older Symbian clients -->
+    <superdatastore name="calendar">
+
+      <!-- sub-datastores contained in this superdatastore -->
+
+      <!-- if set, SyncML DS 1.2 filtering is possible and will be indicated in server devInf -->
+      <ds12filters>yes</ds12filters>
+
+      <!-- if set, datastore supports filtering by a date range specification (SINCE,BEFORE or /dr())
+           Note: if this is set to yes, actual range filtering must be implemented in the datatype
+           and/or the subdatastores contained in this superdatastore -->
+      <daterangesupport>yes</daterangesupport>
+
+      <contains datastore="events">
+        <dispatchfilter>F.KIND:=EVENT</dispatchfilter>
+        <guidprefix>e</guidprefix>
+      </contains>
+
+      <contains datastore="tasks">
+        <dispatchfilter>F.KIND:=TODO</dispatchfilter>
+        <guidprefix>t</guidprefix>
+      </contains>
+
+      <!-- datatypes supported by this datastore -->
+      <typesupport>
+        <use datatype="vcalendar10" mode="rw" preferred="yes"/>
+      </typesupport>
+
+    </superdatastore>
+
+
+    <datastore name="notes" type="plugin">
+
+      <plugin_module>[SDK_textdb]</plugin_module>
+      <plugin_datastoreadmin>yes</plugin_datastoreadmin>
+      <plugin_params>
+        <!-- specify plugin-specific parameters here, they will be
+             passed to the plugin implementation for processing -->
+        <ultimate_answer>42</ultimate_answer> <!-- just as an example -->
+      </plugin_params>
+
+
+      <!-- General datastore settings for all DB types -->
+
+      <!-- if this is set to "yes", SyncML clients can only read
+           from the server database, but make no modifications -->
+      <readonly>no</readonly>
+
+      <!-- conflict strategy: Newer item wins
+           You can set "server-wins" or "client-wins" as well
+           if you want to give one side precedence
+      -->
+      <conflictstrategy>newer-wins</conflictstrategy>
+
+      <!-- on slowsync: duplicate items that are not fully equal
+           You can set this to "newer-wins" as well to avoid
+           duplicates as much as possible
+      -->
+      <slowsyncstrategy>duplicate</slowsyncstrategy>
+
+      <!-- Visibility control: Server items that have the SYNCLVL
+           field set to 0 will be invisible to SyncML clients.
+           Using CGI-filtering in database names (such as
+           ./contacts?SYNCLVL:>=5) smaller clients can
+           sync a reduced set of server items -->
+      <makepassfilter>F.SYNCLVL:=10</makepassfilter>
+      <invisiblefilter>F.SYNCLVL:=0|F.SYNCLVL*=E</invisiblefilter>
+      <makevisiblefilter>F.SYNCLVL:=10</makevisiblefilter>
+
+
+      <!-- text db plugin is designed for UTF-8, make sure data is passed as UTF-8 (and not the ISO-8859-1 default) -->
+      <datacharset>UTF-8</datacharset>
+      <!-- use C-language (unix style) linefeeds (\n, 0x0A) -->
+      <datalineends>unix</datalineends>
+
+      <!-- set this to "UTC" if time values should be stored in UTC into the database
+           rather than local time. "SYSTEM" denotes local server time zone. -->
+      <datatimezone>SYSTEM</datatimezone>
+
+      <!-- plugin DB may have its own identifiers to determine the point in time of changes, so
+           we must make sure this identifier is stored (and not only the sync time) -->
+      <storesyncidentifiers>yes</storesyncidentifiers>
+
+      <!-- TextDB plugin supports resume and resuming partial items, so enable these here -->
+      <resumesupport>yes</resumesupport>
+      <resumeitemsupport>yes</resumeitemsupport>
+
+
+
+      <!-- Mapping of the fields to the fieldlist "notes" -->
+      <fieldmap fieldlist="Note">
+        <automap indexasname="true"/>
+      </fieldmap>
+
+      <typesupport>
+        <use datatype="note" mode="rw" preferred="yes"/>
+        <use datatype="note11" mode="rw"/>
+      </typesupport>
+
+    </datastore>
+
+
+    <datastore name="bookmarks" type="plugin">
+
+      <plugin_module>[SDK_textdb]</plugin_module>
+      <plugin_datastoreadmin>yes</plugin_datastoreadmin>
+      <plugin_params>
+        <!-- specify plugin-specific parameters here, they will be
+             passed to the plugin implementation for processing -->
+        <ultimate_answer>42</ultimate_answer> <!-- just as an example -->
+      </plugin_params>
+
+
+      <!-- General datastore settings for all DB types -->
+
+      <!-- if this is set to "yes", SyncML clients can only read
+           from the server database, but make no modifications -->
+      <readonly>no</readonly>
+
+      <!-- conflict strategy: Newer item wins
+           You can set "server-wins" or "client-wins" as well
+           if you want to give one side precedence
+      -->
+      <conflictstrategy>newer-wins</conflictstrategy>
+
+      <!-- on slowsync: duplicate items that are not fully equal
+           You can set this to "newer-wins" as well to avoid
+           duplicates as much as possible
+      -->
+      <slowsyncstrategy>duplicate</slowsyncstrategy>
+
+      <!-- Visibility control: Server items that have the SYNCLVL
+           field set to 0 will be invisible to SyncML clients.
+           Using CGI-filtering in database names (such as
+           ./contacts?SYNCLVL:>=5) smaller clients can
+           sync a reduced set of server items -->
+      <makepassfilter>F.SYNCLVL:=10</makepassfilter>
+      <invisiblefilter>F.SYNCLVL:=0|F.SYNCLVL*=E</invisiblefilter>
+      <makevisiblefilter>F.SYNCLVL:=10</makevisiblefilter>
+
+
+      <!-- text db plugin is designed for UTF-8, make sure data is passed as UTF-8 (and not the ISO-8859-1 default) -->
+      <datacharset>UTF-8</datacharset>
+      <!-- use C-language (unix style) linefeeds (\n, 0x0A) -->
+      <datalineends>unix</datalineends>
+
+      <!-- set this to "UTC" if time values should be stored in UTC into the database
+           rather than local time. "SYSTEM" denotes local server time zone. -->
+      <datatimezone>SYSTEM</datatimezone>
+
+      <!-- plugin DB may have its own identifiers to determine the point in time of changes, so
+           we must make sure this identifier is stored (and not only the sync time) -->
+      <storesyncidentifiers>yes</storesyncidentifiers>
+
+      <!-- TextDB plugin supports resume and resuming partial items, so enable these here -->
+      <resumesupport>yes</resumesupport>
+      <resumeitemsupport>yes</resumeitemsupport>
+
+
+
+      <!-- Mapping of the fields to the fieldlist "bookmarks" -->
+      <fieldmap fieldlist="bookmarks">
+        <automap indexasname="true"/>
+      </fieldmap>
+
+      <!-- datatypes supported by this datastore -->
+      <typesupport>
+        <use datatype="vbookmark" mode="rw" preferred="yes"/>
+      </typesupport>
+
+    </datastore>
+
+
+    <datastore name="emails" type="plugin">
+
+      <plugin_module>[SDK_textdb]</plugin_module>
+      <plugin_datastoreadmin>yes</plugin_datastoreadmin>
+      <plugin_params>
+        <!-- specify plugin-specific parameters here, they will be
+             passed to the plugin implementation for processing -->
+        <ultimate_answer>42</ultimate_answer> <!-- just as an example -->
+      </plugin_params>
+
+
+      <!-- General datastore settings for all DB types -->
+
+      <!-- if this is set to "yes", SyncML clients can only read
+           from the server database, but make no modifications -->
+      <readonly>no</readonly>
+
+      <!-- conflict strategy: Newer item wins
+           You can set "server-wins" or "client-wins" as well
+           if you want to give one side precedence
+      -->
+      <conflictstrategy>newer-wins</conflictstrategy>
+
+      <!-- on slowsync: duplicate items that are not fully equal
+           You can set this to "newer-wins" as well to avoid
+           duplicates as much as possible
+      -->
+      <slowsyncstrategy>duplicate</slowsyncstrategy>
+
+      <!-- Visibility control: Server items that have the SYNCLVL
+           field set to 0 will be invisible to SyncML clients.
+           Using CGI-filtering in database names (such as
+           ./contacts?SYNCLVL:>=5) smaller clients can
+           sync a reduced set of server items -->
+      <makepassfilter>F.SYNCLVL:=10</makepassfilter>
+      <invisiblefilter>F.SYNCLVL:=0|F.SYNCLVL*=E</invisiblefilter>
+      <makevisiblefilter>F.SYNCLVL:=10</makevisiblefilter>
+
+
+      <!-- text db plugin is designed for UTF-8, make sure data is passed as UTF-8 (and not the ISO-8859-1 default) -->
+      <datacharset>UTF-8</datacharset>
+      <!-- use C-language (unix style) linefeeds (\n, 0x0A) -->
+      <datalineends>unix</datalineends>
+
+      <!-- set this to "UTC" if time values should be stored in UTC into the database
+           rather than local time. "SYSTEM" denotes local server time zone. -->
+      <datatimezone>SYSTEM</datatimezone>
+
+      <!-- plugin DB may have its own identifiers to determine the point in time of changes, so
+           we must make sure this identifier is stored (and not only the sync time) -->
+      <storesyncidentifiers>yes</storesyncidentifiers>
+
+      <!-- TextDB plugin supports resume and resuming partial items, so enable these here -->
+      <resumesupport>yes</resumesupport>
+      <resumeitemsupport>yes</resumeitemsupport>
+
+
+
+      <!-- Mapping of the fields to the fieldlist "notes" -->
+      <fieldmap fieldlist="email">
+        <automap indexasname="true"/>
+      </fieldmap>
+
+      <typesupport>
+        <!-- Note: the compressed Synthesis specific "email_zipbin" format is made the preferred format
+             here to make sure clients supporting that format will actually use it. -->
+        <use datatype="email_zipbin" mode="rw" preferred="yes"/>
+        <use datatype="email" mode="rw" preferred="no"/>
+        <use datatype="email_nokia9500" mode="rw" preferred="no"/>
+        <use datatype="email_sonyericsson" mode="rw" preferred="no"/>
+      </typesupport>
+
+    </datastore>
+
+
+    <!-- Remote Rules list
+         =================
+         Note: the <remoterule> tags specify options and exceptions needed for correct handling of
+               certain devices. Synthesis AG provides this list including all currently know
+               exceptions in this config file and also publishes regular updates for the list
+               of remote rules on its web site at http://www.synthesis.ch
+    -->
+
+
+    <remoterule name="t39m">
+      <!-- Rule for Ericsson T39m client -->
+      <manufacturer>Ericsson</manufacturer>
+      <software>R1A</software>
+
+      <limitedfieldlengths>yes</limitedfieldlengths>
+      <descriptivename>Ericsson T39m</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="t68">
+      <!-- Rule for Ericsson T68 client -->
+      <manufacturer>Ericsson</manufacturer>
+      <software>R1B</software>
+
+      <limitedfieldlengths>yes</limitedfieldlengths>
+      <descriptivename>Ericsson T68</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="V3">
+      <!-- Rule for Motorola V3 -->
+      <manufacturer>Motorola*</manufacturer>
+      <model>V3</model>
+
+      <limitedfieldlengths>yes</limitedfieldlengths>
+      <quote8bitcontent>yes</quote8bitcontent>
+      <nocontentfolding>yes</nocontentfolding>
+      <outputcharset>ANSI</outputcharset>
+      <descriptivename>Motorola V3</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="V3i">
+      <!-- Rule for Motorola V3i -->
+      <manufacturer>Motorola*</manufacturer>
+      <model>V3i</model>
+
+      <limitedfieldlengths>yes</limitedfieldlengths>
+      <quote8bitcontent>yes</quote8bitcontent>
+      <nocontentfolding>yes</nocontentfolding>
+      <outputcharset>ANSI</outputcharset>
+      <descriptivename>Motorola V3i</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="6230">
+      <manufacturer>NOKIA</manufacturer>
+      <model>6230</model>
+
+      <limitedfieldlengths>yes</limitedfieldlengths>
+      <forcelocaltime>yes</forcelocaltime>
+      <descriptivename>Nokia 6230</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="9210">
+      <manufacturer>NOKIA</manufacturer>
+      <model>9210</model>
+
+      <rulescript><![CDATA[
+        // no dates before 1980
+        mindate=(TIMESTAMP)"19800101T000000Z";
+      ]]></rulescript>
+
+      <forcelocaltime>yes</forcelocaltime>
+      <descriptivename>Nokia 9210</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="9210i">
+      <manufacturer>NOKIA</manufacturer>
+      <model>9210i</model>
+
+      <rulescript><![CDATA[
+        // no dates before 1980
+        mindate=(TIMESTAMP)"19800101T000000Z";
+      ]]></rulescript>
+
+      <forcelocaltime>yes</forcelocaltime>
+      <descriptivename>Nokia 9210</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="3220">
+      <manufacturer>NOKIA</manufacturer>
+      <model>3220</model>
+
+      <rulescript><![CDATA[
+        // no dates before 1980
+        mindate=(TIMESTAMP)"19800101T000000Z";
+      ]]></rulescript>
+
+      <limitedfieldlengths>yes</limitedfieldlengths>
+      <forcelocaltime>yes</forcelocaltime>
+      <descriptivename>Nokia 3220</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="3230">
+      <manufacturer>NOKIA</manufacturer>
+      <model>3230</model>
+
+      <rulescript><![CDATA[
+        // no dates before 1980
+        mindate=(TIMESTAMP)"19800101T000000Z";
+      ]]></rulescript>
+
+      <limitedfieldlengths>yes</limitedfieldlengths>
+      <forcelocaltime>yes</forcelocaltime>
+      <descriptivename>Nokia 3230</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="3600">
+      <manufacturer>NOKIA</manufacturer>
+      <model>3600</model>
+
+      <rulescript><![CDATA[
+        // no dates before 1980
+        mindate=(TIMESTAMP)"19800101T000000Z";
+      ]]></rulescript>
+
+      <limitedfieldlengths>yes</limitedfieldlengths>
+      <forcelocaltime>yes</forcelocaltime>
+      <descriptivename>Nokia 3600</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="3620">
+      <manufacturer>NOKIA</manufacturer>
+      <model>3620</model>
+
+      <rulescript><![CDATA[
+        // no dates before 1980
+        mindate=(TIMESTAMP)"19800101T000000Z";
+      ]]></rulescript>
+
+      <limitedfieldlengths>yes</limitedfieldlengths>
+      <forcelocaltime>yes</forcelocaltime>
+      <descriptivename>Nokia 3620</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="3650">
+      <manufacturer>NOKIA</manufacturer>
+      <model>3650</model>
+
+      <rulescript><![CDATA[
+        // no dates before 1980
+        mindate=(TIMESTAMP)"19800101T000000Z";
+      ]]></rulescript>
+
+      <limitedfieldlengths>yes</limitedfieldlengths>
+      <forcelocaltime>yes</forcelocaltime>
+      <descriptivename>Nokia 3650</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="3660">
+      <manufacturer>NOKIA</manufacturer>
+      <model>3660</model>
+
+      <rulescript><![CDATA[
+        // no dates before 1980
+        mindate=(TIMESTAMP)"19800101T000000Z";
+      ]]></rulescript>
+
+      <limitedfieldlengths>yes</limitedfieldlengths>
+      <forcelocaltime>yes</forcelocaltime>
+      <descriptivename>Nokia 3660</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="6260">
+      <manufacturer>NOKIA</manufacturer>
+      <model>6260</model>
+
+      <rulescript><![CDATA[
+        // no dates before 1980
+        mindate=(TIMESTAMP)"19800101T000000Z";
+      ]]></rulescript>
+
+      <limitedfieldlengths>yes</limitedfieldlengths>
+      <forcelocaltime>yes</forcelocaltime>
+      <descriptivename>Nokia 6260</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="6600">
+      <manufacturer>NOKIA</manufacturer>
+      <model>6600</model>
+
+      <rulescript><![CDATA[
+        // no dates before 1980
+        mindate=(TIMESTAMP)"19800101T000000Z";
+      ]]></rulescript>
+
+      <limitedfieldlengths>yes</limitedfieldlengths>
+      <forcelocaltime>yes</forcelocaltime>
+      <descriptivename>Nokia 6600</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="6620">
+      <manufacturer>NOKIA</manufacturer>
+      <model>6620</model>
+
+      <rulescript><![CDATA[
+        // no dates before 1980
+        mindate=(TIMESTAMP)"19800101T000000Z";
+      ]]></rulescript>
+
+      <limitedfieldlengths>yes</limitedfieldlengths>
+      <forcelocaltime>yes</forcelocaltime>
+      <descriptivename>Nokia 6620</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="6630">
+      <manufacturer>NOKIA</manufacturer>
+      <model>6630</model>
+
+      <rulescript><![CDATA[
+        // no dates before 1980
+        mindate=(TIMESTAMP)"19800101T000000Z";
+      ]]></rulescript>
+
+      <limitedfieldlengths>yes</limitedfieldlengths>
+      <forcelocaltime>yes</forcelocaltime>
+      <descriptivename>Nokia 6630</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="6670">
+      <manufacturer>NOKIA</manufacturer>
+      <model>6670</model>
+
+      <rulescript><![CDATA[
+        // no dates before 1980
+        mindate=(TIMESTAMP)"19800101T000000Z";
+      ]]></rulescript>
+
+      <limitedfieldlengths>yes</limitedfieldlengths>
+      <forcelocaltime>yes</forcelocaltime>
+      <descriptivename>Nokia 6670</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="7250">
+      <manufacturer>NOKIA</manufacturer>
+      <model>7250</model>
+
+      <rulescript><![CDATA[
+        // no dates before 1980
+        mindate=(TIMESTAMP)"19800101T000000Z";
+      ]]></rulescript>
+
+      <limitedfieldlengths>yes</limitedfieldlengths>
+      <forcelocaltime>yes</forcelocaltime>
+      <descriptivename>Nokia 7250</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="7250i">
+      <manufacturer>NOKIA</manufacturer>
+      <model>7250i</model>
+
+      <rulescript><![CDATA[
+        // no dates before 1980
+        mindate=(TIMESTAMP)"19800101T000000Z";
+      ]]></rulescript>
+
+      <limitedfieldlengths>yes</limitedfieldlengths>
+      <forcelocaltime>yes</forcelocaltime>
+      <descriptivename>Nokia 7250i</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="7260">
+      <manufacturer>NOKIA</manufacturer>
+      <model>7260</model>
+
+      <rulescript><![CDATA[
+        // no dates before 1980
+        mindate=(TIMESTAMP)"19800101T000000Z";
+      ]]></rulescript>
+
+      <limitedfieldlengths>yes</limitedfieldlengths>
+      <forcelocaltime>yes</forcelocaltime>
+      <descriptivename>Nokia 7260</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="7610">
+      <manufacturer>NOKIA</manufacturer>
+      <model>7610</model>
+
+      <rulescript><![CDATA[
+        // no dates before 1980
+        mindate=(TIMESTAMP)"19800101T000000Z";
+      ]]></rulescript>
+
+      <limitedfieldlengths>yes</limitedfieldlengths>
+      <forcelocaltime>yes</forcelocaltime>
+      <descriptivename>Nokia 7610</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="7650">
+      <manufacturer>NOKIA</manufacturer>
+      <model>7650</model>
+
+      <rulescript><![CDATA[
+        // no dates before 1980
+        mindate=(TIMESTAMP)"19800101T000000Z";
+      ]]></rulescript>
+
+      <limitedfieldlengths>yes</limitedfieldlengths>
+      <forcelocaltime>yes</forcelocaltime>
+      <descriptivename>Nokia 7650</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="N-Gage">
+      <manufacturer>NOKIA</manufacturer>
+      <model>N-Gage</model>
+
+      <rulescript><![CDATA[
+        // no dates before 1980
+        mindate=(TIMESTAMP)"19800101T000000Z";
+      ]]></rulescript>
+
+      <limitedfieldlengths>yes</limitedfieldlengths>
+      <forcelocaltime>yes</forcelocaltime>
+      <descriptivename>Nokia N-Gage</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="N-Gage QD">
+      <manufacturer>NOKIA</manufacturer>
+      <model>N-Gage QD</model>
+
+      <rulescript><![CDATA[
+        // no dates before 1980
+        mindate=(TIMESTAMP)"19800101T000000Z";
+      ]]></rulescript>
+
+      <limitedfieldlengths>yes</limitedfieldlengths>
+      <forcelocaltime>yes</forcelocaltime>
+      <descriptivename>Nokia N-Gage QD</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="9300">
+      <manufacturer>NOKIA</manufacturer>
+      <model>9300</model>
+
+      <rulescript><![CDATA[
+        // no dates before 1980
+        mindate=(TIMESTAMP)"19800101T000000Z";
+      ]]></rulescript>
+
+      <limitedfieldlengths>yes</limitedfieldlengths>
+      <treatasutc>yes</treatasutc> <!-- needs 2.1.1 or later server -->
+      <descriptivename>Nokia 9300</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="9500">
+      <manufacturer>NOKIA</manufacturer>
+      <model>9500</model>
+
+      <rulescript><![CDATA[
+        // no dates before 1980
+        mindate=(TIMESTAMP)"19800101T000000Z";
+      ]]></rulescript>
+
+      <limitedfieldlengths>yes</limitedfieldlengths>
+      <treatasutc>yes</treatasutc> <!-- needs 2.1.1 or later server -->
+      <descriptivename>Nokia 9500</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="E90">
+      <manufacturer>NOKIA</manufacturer>
+      <model>E90</model>
+
+      <rulescript><![CDATA[
+        // no dates before 1980
+        mindate=(TIMESTAMP)"19800101T000000Z";
+      ]]></rulescript>
+
+      <ignoredevinfmaxsize>yes</ignoredevinfmaxsize>
+      <descriptivename>Nokia E90</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="X">
+      <manufacturer>Sendo</manufacturer>
+      <model>X</model>
+
+      <rulescript><![CDATA[
+        // no dates before 1980
+        mindate=(TIMESTAMP)"19800101T000000Z";
+      ]]></rulescript>
+
+      <limitedfieldlengths>yes</limitedfieldlengths>
+      <forcelocaltime>yes</forcelocaltime>
+      <descriptivename>Sendo X</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="SX1">
+      <manufacturer>SIEMENS</manufacturer>
+      <model>SX1</model>
+
+      <rulescript><![CDATA[
+        // no dates before 1980
+        mindate=(TIMESTAMP)"19800101T000000Z";
+      ]]></rulescript>
+
+      <limitedfieldlengths>yes</limitedfieldlengths>
+      <forcelocaltime>yes</forcelocaltime>
+      <!-- Note: SX1 crashes on contacts with empty properties -->
+      <noemptyproperties>yes</noemptyproperties>
+      <descriptivename>Siemens SX1</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="M55">
+      <manufacturer>SIEMENS</manufacturer>
+      <model>M55</model>
+
+      <forcelocaltime>yes</forcelocaltime>
+      <limitedfieldlengths>yes</limitedfieldlengths>
+      <descriptivename>Siemens M55</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="SL55">
+      <manufacturer>SIEMENS</manufacturer>
+      <model>SL55</model>
+
+      <forcelocaltime>yes</forcelocaltime>
+      <limitedfieldlengths>yes</limitedfieldlengths>
+      <descriptivename>Siemens SL55</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="S55">
+      <manufacturer>SIEMENS</manufacturer>
+      <model>S55</model>
+
+      <forcelocaltime>yes</forcelocaltime>
+      <limitedfieldlengths>yes</limitedfieldlengths>
+      <descriptivename>Siemens S55</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="S65">
+      <manufacturer>SIEMENS</manufacturer>
+      <model>S65</model>
+
+      <forcelocaltime>yes</forcelocaltime>
+      <limitedfieldlengths>yes</limitedfieldlengths>
+      <descriptivename>Siemens S65</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="SL65">
+      <manufacturer>SIEMENS</manufacturer>
+      <model>SL65</model>
+
+      <forcelocaltime>yes</forcelocaltime>
+      <limitedfieldlengths>yes</limitedfieldlengths>
+      <descriptivename>Siemens SL65</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="K700">
+      <!-- Rule for SonyEricsson K700 (aka SEMC Phone) client -->
+      <manufacturer>SonyEricsson</manufacturer>
+      <model>SEMC Phone</model>
+      <software>R3B</software>
+
+      <!-- is a 1.1 client and claims UTC support, but it seems not to work ok
+      <forcelocaltime>yes</forcelocaltime>
+      -->
+      <limitedfieldlengths>yes</limitedfieldlengths>
+      <descriptivename>SonyEricsson K700</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="T610/T630">
+      <!-- Rule for SonyEricsson T610/T630 client -->
+      <manufacturer>SonyEricsson</manufacturer>
+      <software>R2B</software>
+
+      <limitedfieldlengths>yes</limitedfieldlengths>
+      <descriptivename>SonyEricsson T610/T630</descriptivename>
+    </remoterule>
+
+
+    <!-- Due to a problem in M600i vCalendar implementation,
+         the device does not calculate time zones correctly
+         in all cases.
+         If your M600i is brand new, you need to specify
+         "calendar?/o(Z)" as database path instead of just
+         "calendar". If your M600i has already been synced
+         at least once via the cradle and the software
+         delivered with the device, you must omit the
+         "?/o(Z)" appendix and specify just "calendar" instead.
+         Please also note that the o(Z) option for never-synced
+         M600i devices only works if your server's config is
+         derived from a recent version of our sample config.
+         Otherwise, just make sure the M600i is synced once
+         in the cradle before using SyncML.
+    -->
+    <remoterule name="M600i">
+      <manufacturer>Sony Ericsson</manufacturer>
+      <model>M600i</model>
+
+      <rulescript><![CDATA[
+        // no dates before 1980
+        mindate=(TIMESTAMP)"19800101T000000Z";
+        // retransfer body when items are moved to sent box
+        retransfer_body=TRUE;
+      ]]></rulescript>
+
+      <treataslocaltime>no</treataslocaltime> <!-- can be set to yes to have /o(Z) mode (see comment above) as default, otherwise /o(z) is default -->
+      <forcelocaltime>yes</forcelocaltime>
+      <descriptivename>SonyEricsson M600i</descriptivename>
+    </remoterule>
+
+
+    <!-- Due to a problem in P800 vCalendar implementation,
+         the device does not calculate time zones correctly
+         in all cases.
+         If your P800 is brand new, you need to specify
+         "calendar?/o(Z)" as database path instead of just
+         "calendar". If your P800 has already been synced
+         at least once via the cradle and the software
+         delivered with the device, you must omit the
+         "?/o(Z)" appendix and specify just "calendar" instead.
+         Please also note that the o(Z) option for never-synced
+         P800 devices only works if your server's config is
+         derived from a recent version of our sample config.
+         Otherwise, just make sure the P800 is synced once
+         in the cradle before using SyncML.
+    -->
+    <remoterule name="P800">
+      <manufacturer>Sony Ericsson</manufacturer>
+      <model>P800</model>
+
+      <rulescript><![CDATA[
+        // no dates before 1980
+        mindate=(TIMESTAMP)"19800101T000000Z";
+        // retransfer body when items are moved to sent box
+        retransfer_body=TRUE;
+      ]]></rulescript>
+
+      <treataslocaltime>no</treataslocaltime> <!-- can be set to yes to have /o(Z) mode (see comment above) as default, otherwise /o(z) is default -->
+      <forcelocaltime>yes</forcelocaltime>
+      <descriptivename>SonyEricsson P800</descriptivename>
+    </remoterule>
+
+
+    <!-- Due to a problem in P900 vCalendar implementation,
+         the device does not calculate time zones correctly
+         in all cases.
+         If your P900 is brand new, you need to specify
+         "calendar?/o(Z)" as database path instead of just
+         "calendar". If your P900 has already been synced
+         at least once via the cradle and the software
+         delivered with the device, you must omit the
+         "?/o(Z)" appendix and specify just "calendar" instead.
+         Please also note that the o(Z) option for never-synced
+         P900 devices only works if your server's config is
+         derived from a recent version of our sample config.
+         Otherwise, just make sure the P900 is synced once
+         in the cradle before using SyncML.
+    -->
+    <remoterule name="P900">
+      <manufacturer>Sony Ericsson</manufacturer>
+      <model>P900</model>
+
+      <rulescript><![CDATA[
+        // no dates before 1980
+        mindate=(TIMESTAMP)"19800101T000000Z";
+        // retransfer body when items are moved to sent box
+        retransfer_body=TRUE;
+      ]]></rulescript>
+
+      <treataslocaltime>no</treataslocaltime> <!-- can be set to yes to have /o(Z) mode (see comment above) as default, otherwise /o(z) is default -->
+      <forcelocaltime>yes</forcelocaltime>
+      <descriptivename>SonyEricsson P900</descriptivename>
+    </remoterule>
+
+
+    <!-- Due to a problem in P910 vCalendar implementation,
+         the device does not calculate time zones correctly
+         in all cases.
+         If your P910 is brand new, you need to specify
+         "calendar?/o(Z)" as database path instead of just
+         "calendar". If your P910 has already been synced
+         at least once via the cradle and the software
+         delivered with the device, you must omit the
+         "?/o(Z)" appendix and specify just "calendar" instead.
+         Please also note that the o(Z) option for never-synced
+         P910 devices only works if your server's config is
+         derived from a recent version of our sample config.
+         Otherwise, just make sure the P910 is synced once
+         in the cradle before using SyncML.
+    -->
+    <remoterule name="P910">
+      <manufacturer>Sony Ericsson</manufacturer>
+      <model>P910</model>
+
+      <rulescript><![CDATA[
+        // no dates before 1980
+        mindate=(TIMESTAMP)"19800101T000000Z";
+        // retransfer body when items are moved to sent box
+        retransfer_body=TRUE;
+      ]]></rulescript>
+
+      <treataslocaltime>no</treataslocaltime> <!-- can be set to yes to have /o(Z) mode (see comment above) as default, otherwise /o(z) is default -->
+      <forcelocaltime>yes</forcelocaltime>
+      <descriptivename>SonyEricsson P910</descriptivename>
+    </remoterule>
+
+
+    <!-- Due to a problem in P910i vCalendar implementation,
+         the device does not calculate time zones correctly
+         in all cases.
+         If your P910i is brand new, you need to specify
+         "calendar?/o(Z)" as database path instead of just
+         "calendar". If your P910i has already been synced
+         at least once via the cradle and the software
+         delivered with the device, you must omit the
+         "?/o(Z)" appendix and specify just "calendar" instead.
+         Please also note that the o(Z) option for never-synced
+         P910i devices only works if your server's config is
+         derived from a recent version of our sample config.
+         Otherwise, just make sure the P910i is synced once
+         in the cradle before using SyncML.
+    -->
+    <remoterule name="P910i">
+      <manufacturer>Sony Ericsson</manufacturer>
+      <model>P910i</model>
+
+      <rulescript><![CDATA[
+        // no dates before 1980
+        mindate=(TIMESTAMP)"19800101T000000Z";
+        // retransfer body when items are moved to sent box
+        retransfer_body=TRUE;
+      ]]></rulescript>
+
+      <treataslocaltime>no</treataslocaltime> <!-- can be set to yes to have /o(Z) mode (see comment above) as default, otherwise /o(z) is default -->
+      <forcelocaltime>yes</forcelocaltime>
+      <descriptivename>SonyEricsson P910i</descriptivename>
+    </remoterule>
+
+
+    <!-- Due to a problem in P990i vCalendar implementation,
+         the device does not calculate time zones correctly
+         in all cases.
+         If your P990i is brand new, you need to specify
+         "calendar?/o(Z)" as database path instead of just
+         "calendar". If your P990i has already been synced
+         at least once via the cradle and the software
+         delivered with the device, you must omit the
+         "?/o(Z)" appendix and specify just "calendar" instead.
+         Please also note that the o(Z) option for never-synced
+         P990i devices only works if your server's config is
+         derived from a recent version of our sample config.
+         Otherwise, just make sure the P990i is synced once
+         in the cradle before using SyncML.
+    -->
+    <remoterule name="P990i">
+      <manufacturer>Sony Ericsson</manufacturer>
+      <model>P990i</model>
+
+      <rulescript><![CDATA[
+        // no dates before 1980
+        mindate=(TIMESTAMP)"19800101T000000Z";
+        // retransfer body when items are moved to sent box
+        retransfer_body=TRUE;
+      ]]></rulescript>
+
+      <treataslocaltime>no</treataslocaltime> <!-- can be set to yes to have /o(Z) mode (see comment above) as default, otherwise /o(z) is default -->
+      <forcelocaltime>yes</forcelocaltime>
+      <descriptivename>SonyEricsson P990i</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="t68i">
+      <!-- Rule for SonyEricsson T68i client -->
+      <manufacturer>SonyEricsson</manufacturer>
+      <software>R2A</software>
+
+      <limitedfieldlengths>yes</limitedfieldlengths>
+      <descriptivename>SonyEricsson T68i</descriptivename>
+    </remoterule>
+
+
+    <remoterule name="Funambol_Outlook">
+      <!-- Rule for Funambol Outlook Sync Client -->
+      <model>Funambol Outlook Sync Client</model>
+
+      <lenientmode>yes</lenientmode> <!-- some status messages are missing at end of session -->
+      <descriptivename>Funambol Outlook Sync Client</descriptivename>
+    </remoterule>
+
+
+ÊÊ  <remoterule name="SyncJe_Outlook">
+ÊÊÊÊ  <!-- Rule for NextHaus SyncJe Outlook Edition -->
+ÊÊÊÊ  <model>SyncJe Outlook Edition</model>
+
+ÊÊÊÊ  <ignorectcap>yes</ignorectcap> <!-- can do contact photo sync, but is missing in CTCap -->
+      <descriptivename>NextHaus SyncJe Outlook Client</descriptivename>
+ÊÊ  </remoterule>
+
+
+    <!-- End of remote rule list. -->
+
+  </server>
+
+</sysync_config>
diff --git a/src/synthesis/synthesis-sdk.pc.in b/src/synthesis/synthesis-sdk.pc.in
new file mode 100644 (file)
index 0000000..98f360a
--- /dev/null
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: synthesis
+Description: Synthesis SyncML SDK
+Version: @VERSION@
+Libs: -L${libdir} -lsynthesissdk -lsynthesisstubs
+Cflags: -I${includedir}
index c5a6136..03a93e7 100644 (file)
@@ -4,7 +4,7 @@ libdir=@libdir@
 includedir=@includedir@
 
 Name: synthesis
-Description: Synthesis SyncML Engine
+Description: Synthesis SyncML SDK, Client and Server Engine
 Version: @VERSION@
 Libs: -L${libdir} -lsynthesissdk -lsynthesis
 Cflags: -I${includedir}
diff --git a/src/testcases/vcard30.vcf.zyb.tem b/src/testcases/vcard30.vcf.zyb.tem
new file mode 100644 (file)
index 0000000..1cf00a5
--- /dev/null
@@ -0,0 +1,428 @@
+BEGIN:VCARD\r
+VERSION:3.0\r
+NICKNAME:user17\r
+NOTE:triggers parser bug in Funambol 3.0: trailing = is mistaken for soft line break=\r
+FN:parserbug=\r
+N:parserbug=\r
+X-EVOLUTION-FILE-AS:parserbug=\r
+END:VCARD\r
+\r
+BEGIN:VCARD\r
+VERSION:3.0\r
+NICKNAME:user16\r
+NOTE:test case with empty email\r
+FN:incomplete\r
+N:incomplete\r
+EMAIL:\r
+X-EVOLUTION-FILE-AS:incomplete\r
+END:VCARD\r
+\r
+BEGIN:VCARD\r
+VERSION:3.0\r
+NICKNAME:user11\r
+NOTE:This is a long line without any special characters. This is a simpler \r
+ example that should require folding in vcards. Does folding insert a crlf\r
+  before a space or does it insert crlf _plus_ a space? vCard 2.1 inserts \r
+ before a space\, 3.0 inserts line break plus space.\r
+FN:long line\r
+N:line;long;;;\r
+X-EVOLUTION-FILE-AS:line\, long\r
+END:VCARD\r
+\r
+BEGIN:VCARD\r
+VERSION:3.0\r
+NICKNAME:user12\r
+NOTE:ampersand entity & less-than entity >\r
+FN:xml entities\r
+N:xml;entities;;;\r
+X-EVOLUTION-FILE-AS:xml\, entities\r
+END:VCARD\r
+\r
+BEGIN:VCARD\r
+VERSION:3.0\r
+NICKNAME:user13\r
+NOTE:a colon is not a special character so here it comes : and not quoting necessary\r
+FN:colon\r
+N:colon;unquoted;;;\r
+X-EVOLUTION-FILE-AS:colon\, unquoted\r
+END:VCARD\r
+\r
+BEGIN:VCARD\r
+VERSION:3.0\r
+NICKNAME:user14\r
+NOTE:here are some quotation marks: single ' double " back ` - none of them is special\r
+FN:quotation marks\r
+N:marks;quotation;;;\r
+X-EVOLUTION-FILE-AS:marks\, quotation\r
+END:VCARD\r
+\r
+BEGIN:VCARD\r
+VERSION:3.0\r
+NICKNAME:user15\r
+NOTE:Spouse's Name: foobar\r
+FN:spouse name\r
+N:name;spouse;;;\r
+X-EVOLUTION-FILE-AS:spouse\, name\r
+END:VCARD\r
+\r
+BEGIN:VCARD\r
+VERSION:3.0\r
+NICKNAME:user9\r
+NOTE;CHARSET="UTF-8":Tests charset specification with quotation marks.\r
+FN:charset\r
+N:set;char;;;\r
+X-EVOLUTION-FILE-AS:set\, char\r
+END:VCARD\r
+\r
+BEGIN:VCARD\r
+VERSION:3.0\r
+URL:\r
+TITLE:\r
+ROLE:\r
+X-EVOLUTION-MANAGER:\r
+X-EVOLUTION-ASSISTANT:\r
+NICKNAME:user2\r
+X-EVOLUTION-SPOUSE:\r
+NOTE:This user tests some of the advanced aspects of vcards:\n- non-ASCII c\r
+ haracters (with umlauts in the name)\n- line break (in this note and the\r
+  mailing address)\n- long lines (in this note)\n- special characters (in\r
+  this note)\n- tabs (in this note)\n\nVery long line\, very very long th\r
+ is time... still not finished... blah blah blah blah blah 1 2 3 4 5 6 7 \r
+ 8 9 10 11 12 13 14 15 16\n\ncomma \,\ncolon :\nsemicolon \;\nbackslash \r
+ \\\n\nThe same\, in the middle of a line:\ncomma \, comma\ncolon : col\r
+ on\nsemicolon \; semicolon\nbackslash \\ backslash\n\nA tab   tab done\n      \r
+ line starts with tab\r
+FN:Umlaut Ã„ Ã– Ãœ ÃŸ\r
+N:Ü;Ä;Ö;Umlaut;ß\r
+X-EVOLUTION-FILE-AS:Ãœ\, Ã„\r
+CATEGORIES:Business\r
+X-EVOLUTION-BLOG-URL:\r
+CALURI:\r
+FBURL:\r
+X-EVOLUTION-VIDEO-URL:\r
+X-MOZILLA-HTML:FALSE\r
+ADR;TYPE=HOME:test 5;Line 2;Umlaut Ã„ in Line 1;test 1;test 3;test 2;test 4\r
+LABEL;TYPE=HOME:Umlaut Ã„ in Line 1\nLine 2\n\ntest 1\, test 3\ntest 2\ntest 5\ntest 4\r
+UID:pas-id-43C0EF0A00000002\r
+END:VCARD\r
+\r
+BEGIN:VCARD\r
+VERSION:3.0\r
+URL:\r
+TITLE:\r
+ROLE:\r
+X-EVOLUTION-MANAGER:\r
+X-EVOLUTION-ASSISTANT:\r
+NICKNAME:user8\r
+X-EVOLUTION-SPOUSE:\r
+NOTE:Here are some special characters: comma \, colon : semicolon \;\r
+FN:special characters\r
+N:characters;special;;;\r
+X-EVOLUTION-FILE-AS:characters\, special\r
+X-EVOLUTION-BLOG-URL:\r
+CALURI:\r
+FBURL:\r
+X-EVOLUTION-VIDEO-URL:\r
+X-MOZILLA-HTML:FALSE\r
+UID:pas-id-43C15E84000001AC\r
+END:VCARD\r
+\r
+BEGIN:VCARD\r
+VERSION:3.0\r
+URL:\r
+TITLE:\r
+ROLE:\r
+X-EVOLUTION-MANAGER:\r
+X-EVOLUTION-ASSISTANT:\r
+NICKNAME:user7\r
+X-EVOLUTION-SPOUSE:\r
+NOTE:This test case uses line breaks. This is line 1.\nLine 2.\n\nLine brea\r
+ ks in vcard 2.1 are encoded as =0D=0A.\nThat means the = has to be encod\r
+ ed itself...\r
+FN:line breaks\r
+N:breaks;line;;;\r
+X-EVOLUTION-FILE-AS:breaks\, line\r
+X-EVOLUTION-BLOG-URL:\r
+CALURI:\r
+FBURL:\r
+X-EVOLUTION-VIDEO-URL:\r
+X-MOZILLA-HTML:FALSE\r
+ADR;TYPE=HOME:;Address Line 2\nAddress Line 3;Address Line 1;;;;\r
+LABEL;TYPE=HOME:Address Line 1\nAddress Line 2\nAddress Line 3\r
+UID:pas-id-43C15DFB000001AB\r
+END:VCARD\r
+\r
+BEGIN:VCARD\r
+VERSION:3.0\r
+URL:http://john.doe.com\r
+TITLE:Senior Tester\r
+ORG:Test Inc.;Testing;test#1\r
+ROLE:professional test case\r
+X-EVOLUTION-MANAGER:John Doe Senior\r
+X-EVOLUTION-ASSISTANT:John Doe Junior\r
+NICKNAME:user1\r
+BDAY:2006-01-08\r
+X-EVOLUTION-ANNIVERSARY:2006-01-09\r
+X-EVOLUTION-SPOUSE:Joan Doe\r
+NOTE:This is a test case which uses almost all Evolution fields.\r
+FN:John Doe\r
+N:Doe;John;;;\r
+X-EVOLUTION-FILE-AS:Doe\, John\r
+CATEGORIES:TEST\r
+X-EVOLUTION-BLOG-URL:web log\r
+CALURI:calender\r
+FBURL:free/busy\r
+X-EVOLUTION-VIDEO-URL:chat\r
+X-MOZILLA-HTML:TRUE\r
+ADR;TYPE=WORK:Test Box #2;;Test Drive 2;Test Town;Upper Test County;12346;O\r
+ ld\r
+LABEL;TYPE=WORK:Test Drive 2\nTest Town\, Upper Test County\n12346\nTest Bo\r
+ x #2\nOld Testovia\r
+ADR;TYPE=HOME:Test Box #1;;Test Drive 1;Test Village;Lower Test County;1234\r
+ 5;Te\r
+LABEL;TYPE=HOME:Test Drive 1\nTest Village\, Lower Test County\n12345\nTest\r
+  Box #1\nTestovia\r
+ADR:Test Box #3;;Test Drive 3;Test Megacity;Test County;12347;New Testonia\r
+LABEL;TYPE=OTHER:Test Drive 3\nTest Megacity\, Test County\n12347\nTest Box\r
+  #3\nNew Testonia\r
+UID:pas-id-43C0ED3900000001\r
+EMAIL;TYPE=WORK;X-EVOLUTION-UI-SLOT=1:john.doe@work.com\r
+EMAIL;TYPE=HOME;X-EVOLUTION-UI-SLOT=2:john.doe@home.priv\r
+EMAIL;TYPE=OTHER;X-EVOLUTION-UI-SLOT=3:john.doe@other.world\r
+EMAIL;TYPE=OTHER;X-EVOLUTION-UI-SLOT=4:john.doe@yet.another.world\r
+TEL;TYPE=work;TYPE=Voice;X-EVOLUTION-UI-SLOT=1:business 1\r
+TEL;TYPE=homE;TYPE=VOICE;X-EVOLUTION-UI-SLOT=2:home 2\r
+TEL;TYPE=CELL;X-EVOLUTION-UI-SLOT=3:mobile 3\r
+TEL;TYPE=WORK;TYPE=FAX;X-EVOLUTION-UI-SLOT=4:businessfax 4\r
+TEL;TYPE=HOME;TYPE=FAX;X-EVOLUTION-UI-SLOT=5:homefax 5\r
+TEL;TYPE=PAGER;X-EVOLUTION-UI-SLOT=6:pager 6\r
+TEL;TYPE=CAR;X-EVOLUTION-UI-SLOT=7:car 7\r
+TEL;TYPE=PREF;X-EVOLUTION-UI-SLOT=8:primary 8\r
+X-AIM;TYPE=HOME;X-EVOLUTION-UI-SLOT=1:AIM JOHN\r
+X-YAHOO;TYPE=HOME;X-EVOLUTION-UI-SLOT=2:YAHOO JDOE\r
+X-ICQ;TYPE=HOME;X-EVOLUTION-UI-SLOT=3:ICQ JD\r
+X-GROUPWISE;TYPE=HOME;X-EVOLUTION-UI-SLOT=4:GROUPWISE DOE\r
+END:VCARD\r
+\r
+BEGIN:VCARD\r
+VERSION:3.0\r
+URL:\r
+TITLE:\r
+ROLE:\r
+X-EVOLUTION-MANAGER:\r
+X-EVOLUTION-ASSISTANT:\r
+NICKNAME:user5\r
+X-EVOLUTION-SPOUSE:\r
+NOTE:image in JPG format\r
+FN:Ms. JPG\r
+N:;JPG;;Ms.;\r
+X-EVOLUTION-FILE-AS:JPG\r
+X-EVOLUTION-BLOG-URL:\r
+CALURI:\r
+FBURL:\r
+X-EVOLUTION-VIDEO-URL:\r
+X-MOZILLA-HTML:FALSE\r
+PHOTO;ENCODING=b;TYPE=JPEG:/9j/4AAQSkZJRgABAQEASABIAAD/4QAWRXhpZgAATU0AKgAA\r
+ AAgAAAAAAAD//gAXQ3JlYXRlZCB3aXRoIFRoZSBHSU1Q/9sAQwAFAwQEBAMFBAQEBQUFBgcM\r
+ CAcHBwcPCwsJDBEPEhIRDxERExYcFxMUGhURERghGBodHR8fHxMXIiQiHiQcHh8e/9sAQwEF\r
+ BQUHBgcOCAgOHhQRFB4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4e\r
+ Hh4eHh4eHh4e/8AAEQgAFwAkAwEiAAIRAQMRAf/EABkAAQADAQEAAAAAAAAAAAAAAAAGBwgE\r
+ Bf/EADIQAAECBQMCAwQLAAAAAAAAAAECBAADBQYRBxIhEzEUFSIIFjNBGCRHUVZ3lqXD0+P/\r
+ xAAUAQEAAAAAAAAAAAAAAAAAAAAA/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMR\r
+ AD8AuX6UehP45/aXv9MTPTLVKxNSvMPcqu+a+XdLxf1SfJ6fU37PioTnOxfbOMc/KIZ7U/2V\r
+ fmTR/wCaKlu6+blu/Ui72zxWtUmmUOrTaWwkWDT09FPR4K587OVrUfVsIwElPPPAbAjxr2um\r
+ hWXbDu5rmfeApLPZ4hx0lzNm9aUJ9KAVHKlJHAPf7ozPLqWt9y6Z0EPGmoLNjTq48a1iaybJ\r
+ YV52yEtCms5KJmAT61JXtJyUdyQTEc1WlMql7N1/oZ6jagVZVFfUyZPpFy5lvWcxU7Z03BUk\r
+ GZLWJqVhPYLkIIPBEBtSEUyNAsjI1q1m/VP+UICwL/sqlXp7v+aOHsnyGttq218MtKd8+Ru2\r
+ JXuScoO45Awe2CIi96aKW1cVyubkYVy6rTqz0J8a5t2qqZl0UjAMwYKScfPAJ+cIQHHP0Dth\r
+ VFaMWt0XwxetnM50Ks2rsxL6ZMnJlJmb5hBBBEiVxjA28dznqo+hdksbQuS3Hs6tVtNzdM1Z\r
+ /VH5nO3Bl/CJmYHKDynjv3zCEB5rLQNo0bIbydWNWxKljbLQLoWkISOAkBKAABCEID//2Q==\r
+UID:pas-id-43C0F0B500000005\r
+END:VCARD\r
+\r
+BEGIN:VCARD\r
+VERSION:3.0\r
+URL:\r
+TITLE:\r
+ROLE:\r
+X-EVOLUTION-MANAGER:\r
+X-EVOLUTION-ASSISTANT:\r
+NICKNAME:user4\r
+X-EVOLUTION-SPOUSE:\r
+NOTE:image in PNG format\r
+FN:Mrs. PNG\r
+N:;PNG;;Mrs.;\r
+X-EVOLUTION-FILE-AS:PNG\r
+X-EVOLUTION-BLOG-URL:\r
+CALURI:\r
+FBURL:\r
+X-EVOLUTION-VIDEO-URL:\r
+X-MOZILLA-HTML:FALSE\r
+PHOTO;ENCODING=b;TYPE=PNG:iVBORw0KGgoAAAANSUhEUgAAACQAAAAXCAYAAABj7u2bAAAAB\r
+ mJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1gEICjgdiWkBO\r
+ QAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJTVDvZCVuAAABaElEQVRIx+3Wu\r
+ 0tcURAG8F98gRKTYGORRqwksJV/QOqFFIFgKgsRYbHV1larDQQCKQxpUscyhUmXJuCSNpYWP\r
+ sAU6wPxHW6aWbgsu+ve3RUs7geHc+fON3O+M4c5HHLkyHG/eISkg5heIGmUr++hVWigyY6TH\r
+ lejbWSt0Bv8QBXX2MF7jKU4IyjjJ45xg31sYKZuw7Xv9Gh6vvXO9QbBtbGNJ8Ert+AlTURkF\r
+ jQX9g5e4ykGUcBm+FaDexx2MUQOYhIL2Lpj09oV9CvsQgPuePj+hP037BL6M6yRSdDZHWVOc\r
+ BHcEv7FvyN8xxqmeynovA1Baf4UVvANhyn/Uq8E/Q57ssNufhvx1QZrDHfS9p9i3sQsnscdN\r
+ owXWEQlOBXMYyI4j3EavqFUzpOYl4OTqUJ9+NzmkbXyb6Ryfumm7Wso4it2cYXL6K6PeBmcV\r
+ 8E5iEvxPDjv8CyVaxQfsIfbqGIlf17k6Bb/Ae0cnahfg6KuAAAAAElFTkSuQmCC\r
+UID:pas-id-43C0F07900000004\r
+END:VCARD\r
+\r
+BEGIN:VCARD\r
+VERSION:3.0\r
+URL:\r
+TITLE:\r
+ROLE:\r
+X-EVOLUTION-MANAGER:\r
+X-EVOLUTION-ASSISTANT:\r
+NICKNAME:user6\r
+X-EVOLUTION-SPOUSE:\r
+NOTE:The first name is "First \; special \;".\r
+FN:Mr. First \; special \; middle Last\r
+N:Last;First special ;middle;Mr.;\r
+X-EVOLUTION-FILE-AS:Last\, First \; special \;\r
+X-EVOLUTION-BLOG-URL:\r
+CALURI:\r
+FBURL:\r
+X-EVOLUTION-VIDEO-URL:\r
+X-MOZILLA-HTML:FALSE\r
+UID:pas-id-43C15D55000001AA\r
+END:VCARD\r
+\r
+BEGIN:VCARD\r
+VERSION:3.0\r
+URL:\r
+TITLE:\r
+ROLE:\r
+X-EVOLUTION-MANAGER:\r
+X-EVOLUTION-ASSISTANT:\r
+NICKNAME:user3\r
+X-EVOLUTION-SPOUSE:\r
+NOTE:image in GIF format\r
+FN:Mr. GIF\r
+N:;GIF;;Mr.;\r
+X-EVOLUTION-FILE-AS:GIF\r
+X-EVOLUTION-BLOG-URL:\r
+CALURI:\r
+FBURL:\r
+X-EVOLUTION-VIDEO-URL:\r
+X-MOZILLA-HTML:FALSE\r
+PHOTO;ENCODING=b;TYPE=GIF:R0lGODlhJAAXAIABAAAAAP///yH+FUNyZWF0ZWQgd2l0aCBUa\r
+ GUgR0lNUAAh+QQBCgABACwAAAAAJAAXAAACVYyPqcvtD6OctNqLFdi8b/sd3giAJRNmqXaKH\r
+ TIaZJKSpx3McLtyeSuTAWm34e+4WBGFuJ/P1QjZek9ksjiRGqFCTW5pZblmzdiO+GJWncqM+\r
+ w2PwwsAOw==\r
+UID:pas-id-43C0F04B00000003\r
+END:VCARD\r
+\r
+BEGIN:VCARD\r
+VERSION:3.0\r
+NICKNAME:user10\r
+X-EVOLUTION-SPOUSE:\r
+NOTE:large vcard with plenty of special chars < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+  & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & < & <\r
+FN:large vcard\r
+N:;vcard;;large;\r
+X-EVOLUTION-FILE-AS:large\r
+END:VCARD\r
index 7088bdf..0769582 100644 (file)
@@ -2391,7 +2391,9 @@ void SyncTests::testManyItems() {
     doSync("send",
            SyncOptions(SYNC_TWO_WAY,
                        CheckSyncReport(0,0,0, num_items,0,0, true, SYNC_TWO_WAY),
-                       64 * 1024, 64 * 1024, true));
+                       SyncOptions::DEFAULT_MAX_MSG_SIZE,
+                       SyncOptions::DEFAULT_MAX_OBJ_SIZE, 
+                       true));
 
     // ensure that client has the same data, ignoring data conversion
     // issues (those are covered by testItems())
@@ -2404,7 +2406,9 @@ void SyncTests::testManyItems() {
     doSync("twinning",
            SyncOptions(SYNC_SLOW,
                        CheckSyncReport(-1,-1,-1, -1,-1,-1, true, SYNC_SLOW),
-                       64 * 1024, 64 * 1024, true));
+                       SyncOptions::DEFAULT_MAX_MSG_SIZE,
+                       SyncOptions::DEFAULT_MAX_OBJ_SIZE, 
+                       true));
 
     // compare
     compareDatabases();
@@ -2567,8 +2571,8 @@ void SyncTests::doVarSizes(bool withMaxMsgSize,
     doSync("send",
            SyncOptions(SYNC_TWO_WAY,
                        CheckSyncReport(0,0,0, -1,0,0, true, SYNC_TWO_WAY), // number of items sent to server depends on source
-                       withMaxMsgSize ? maxMsgSize : 0,
-                       withMaxMsgSize ? maxMsgSize * 100 : 0,
+                       withMaxMsgSize ? SyncOptions::DEFAULT_MAX_MSG_SIZE: 0,
+                       withMaxMsgSize ? SyncOptions::DEFAULT_MAX_OBJ_SIZE : 0,
                        withLargeObject));
 
     // copy to second client
@@ -2845,7 +2849,6 @@ void SyncTests::doInterruptResume(int changes,
         // by overloading the delete operator.
         int wasInterrupted;
         {
-            wrapper->reset();
             wrapper->setInterruptAtMessage(interruptAtMessage);
             accessClientB->doSync("changesFromB",
                                   SyncOptions(SYNC_TWO_WAY,
@@ -2853,6 +2856,7 @@ void SyncTests::doInterruptResume(int changes,
                                                   -1, -1, false)).setTransportAgent(wrapper));
             wasInterrupted = interruptAtMessage != -1 &&
                 wrapper->getMessageCount() <= interruptAtMessage;
+            wrapper->rewind();
         }
 
         if (interruptAtMessage != -1) {
index 608efe1..4722fa4 100644 (file)
@@ -94,6 +94,10 @@ class CheckSyncReport {
  * parameters for running a sync
  */
 struct SyncOptions {
+    /** default maximum message size */
+    static const long DEFAULT_MAX_MSG_SIZE = 128 * 1024;
+    /** default maximum object size */
+    static const long DEFAULT_MAX_OBJ_SIZE = 1024 * 1024 * 1024;
     /** sync mode chosen by client */
     SyncMode m_syncMode;
     /**
@@ -129,8 +133,8 @@ struct SyncOptions {
 
     SyncOptions(SyncMode syncMode = SYNC_NONE,
                 const CheckSyncReport &checkReport = CheckSyncReport(),
-                long maxMsgSize = 128 * 1024, // 128KB = large enough that normal tests should run with a minimal number of messages
-                long maxObjSize = 1 * 1024 * 1024 * 1024, // 1GB = basically unlimited...
+                long maxMsgSize = DEFAULT_MAX_MSG_SIZE, // 128KB = large enough that normal tests should run with a minimal number of messages
+                long maxObjSize = DEFAULT_MAX_OBJ_SIZE, // 1GB = basically unlimited...
                 bool loSupport = false,
                 bool isWBXML = defaultWBXML(),
                 Callback_t startCallback = EmptyCallback,
@@ -739,25 +743,21 @@ public:
     virtual int getMessageCount() { return m_messageCount; }
 
     virtual void setURL(const std::string &url) { m_wrappedAgent->setURL(url); }
-    virtual void setProxy(const std::string &proxy) { m_wrappedAgent->setProxy(proxy); }
-    virtual void setProxyAuth(const std::string &user,
-                              const std::string &password) { m_wrappedAgent->setProxyAuth(user, password); }
-    virtual void setSSL(const std::string &cacerts,
-                        bool verifyServer,
-                        bool verifyHost) { m_wrappedAgent->setSSL(cacerts, verifyServer, verifyHost); }
     virtual void setContentType(const std::string &type) { m_wrappedAgent->setContentType(type); }
-    virtual void setUserAgent(const::string &agent) { m_wrappedAgent->setUserAgent(agent); }
     virtual void setAgent(boost::shared_ptr<TransportAgent> agent) {m_wrappedAgent = agent;}
     virtual void setSyncOptions(SyncOptions *options) {m_options = options;}
     virtual void setInterruptAtMessage (int interrupt) {m_interruptAtMessage = interrupt;}
     virtual void cancel() { m_wrappedAgent->cancel(); }
-    virtual void reset() {
+    virtual void shutdown() { m_wrappedAgent->shutdown(); }
+
+    virtual void rewind() {
         m_messageCount = 0;
         m_interruptAtMessage = -1;
         m_status = INACTIVE;
         m_options = NULL;
+        m_wrappedAgent.reset();
     }
-    virtual Status wait() { return m_status; }
+    virtual Status wait(bool noReply = false) { return m_status; }
     virtual void setCallback (TransportCallback cb, void *udata, int interval) 
     { return m_wrappedAgent->setCallback(cb, udata, interval);}
 };
index c7a99f8..7402071 100644 (file)
@@ -56,6 +56,8 @@ AUTOMAKE = @AUTOMAKE@
 AWK = @AWK@
 BACKEND_CPPFLAGS = @BACKEND_CPPFLAGS@
 BACKEND_DEFINES = @BACKEND_DEFINES@
+BLUEZ_CFLAGS = @BLUEZ_CFLAGS@
+BLUEZ_LIBS = @BLUEZ_LIBS@
 BOOST_CPPFLAGS = @BOOST_CPPFLAGS@
 BOOST_LDFLAGS = @BOOST_LDFLAGS@
 CATALOGS = @CATALOGS@
@@ -63,7 +65,6 @@ CATOBJEXT = @CATOBJEXT@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
-CLEAN_CLIENT_SRC = @CLEAN_CLIENT_SRC@
 CORE_LDADD_DEP = @CORE_LDADD_DEP@
 CPP = @CPP@
 CPPFLAGS = @CPPFLAGS@
@@ -76,8 +77,10 @@ CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
 DATADIRNAME = @DATADIRNAME@
 DBUS_BINDING_TOOL = @DBUS_BINDING_TOOL@
+DBUS_CFLAGS = @DBUS_CFLAGS@
 DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@
 DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@
+DBUS_LIBS = @DBUS_LIBS@
 DBUS_SERVICES_DIR = @DBUS_SERVICES_DIR@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
@@ -104,11 +107,7 @@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
 GLIB_LIBS = @GLIB_LIBS@
 GMOFILES = @GMOFILES@
 GMSGFMT = @GMSGFMT@
-GOBJECT_CFLAGS = @GOBJECT_CFLAGS@
-GOBJECT_LIBS = @GOBJECT_LIBS@
 GREP = @GREP@
-GTHREAD_CFLAGS = @GTHREAD_CFLAGS@
-GTHREAD_LIBS = @GTHREAD_LIBS@
 GTK_BUILDER_CONV = @GTK_BUILDER_CONV@
 GUI_CFLAGS = @GUI_CFLAGS@
 GUI_DESKTOP_FILES = @GUI_DESKTOP_FILES@
@@ -132,6 +131,8 @@ KEYRING_LIBS = @KEYRING_LIBS@
 LDFLAGS = @LDFLAGS@
 LIBEXECDIR = @LIBEXECDIR@
 LIBOBJS = @LIBOBJS@
+LIBOPENOBEX_CFLAGS = @LIBOPENOBEX_CFLAGS@
+LIBOPENOBEX_LIBS = @LIBOPENOBEX_LIBS@
 LIBS = @LIBS@
 LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@
 LIBSOUP_LIBS = @LIBSOUP_LIBS@
@@ -139,8 +140,6 @@ LIBTOOL = @LIBTOOL@
 LN_S = @LN_S@
 LTLIBOBJS = @LTLIBOBJS@
 MAKEINFO = @MAKEINFO@
-MCALB_CFLAGS = @MCALB_CFLAGS@
-MCALB_LIBS = @MCALB_LIBS@
 MKDIR_P = @MKDIR_P@
 MKINSTALLDIRS = @MKINSTALLDIRS@
 MODIFY_SYNCCOMPARE = @MODIFY_SYNCCOMPARE@
@@ -176,6 +175,7 @@ SYNTHESIS = @SYNTHESIS@
 SYNTHESISSRC = @SYNTHESISSRC@
 SYNTHESIS_CFLAGS = @SYNTHESIS_CFLAGS@
 SYNTHESIS_DEP = @SYNTHESIS_DEP@
+SYNTHESIS_ENGINE = @SYNTHESIS_ENGINE@
 SYNTHESIS_LIB = @SYNTHESIS_LIB@
 SYNTHESIS_LIBS = @SYNTHESIS_LIBS@
 SYNTHESIS_SRC = @SYNTHESIS_SRC@
@@ -187,8 +187,6 @@ UNIQUE_LIBS = @UNIQUE_LIBS@
 USE_NLS = @USE_NLS@
 VERSION = @VERSION@
 XGETTEXT = @XGETTEXT@
-XMLRPC_CFLAGS = @XMLRPC_CFLAGS@
-XMLRPC_LIBS = @XMLRPC_LIBS@
 XSLT = @XSLT@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
index 69c141a..87a8caa 100644 (file)
@@ -31,6 +31,7 @@ http://bugzilla.moblin.org/show_bug.cgi?id=3009
   Client::Sync::vcard21::testDelete,                                        \
   Client::Sync::vcard21::testItemsXML,                                      \
   Client::Sync::vcard21::testOneWayFromServer,                              \
+  Client::Sync::vcard21::testOneWayFromClient,                              \
   Client::Sync::vcard21::Retry,Client::Sync::vcard21::Suspend,              \
   Client::Sync::ical20::testRefreshFromClientSync,                          \
   Client::Sync::ical20::testSlowSyncSemantic,                               \
@@ -38,6 +39,7 @@ http://bugzilla.moblin.org/show_bug.cgi?id=3009
   Client::Sync::ical20::testDelete,                                         \
   Client::Sync::ical20::testItemsXML,                                       \
   Client::Sync::ical20::testOneWayFromServer,                               \
+  Client::Sync::ical20::testOneWayFromClient,                               \
   Client::Sync::ical20::Retry,Client::Sync::ical20::Suspend,                \
   Client::Sync::itodo20::testRefreshFromClientSync,                         \
   Client::Sync::itodo20::testSlowSyncSemantic,                              \
@@ -45,6 +47,7 @@ http://bugzilla.moblin.org/show_bug.cgi?id=3009
   Client::Sync::itodo20::testDelete,                                        \
   Client::Sync::itodo20::testItemsXML,                                      \
   Client::Sync::itodo20::testOneWayFromServer,                              \
+  Client::Sync::itodo20::testOneWayFromClient,                              \
   Client::Sync::itodo20::Retry,Client::Sync::itodo20::Suspend,              \
   Client::Sync::text::testRefreshFromClientSync,                            \
   Client::Sync::text::testSlowSyncSemantic,                                 \
@@ -52,6 +55,7 @@ http://bugzilla.moblin.org/show_bug.cgi?id=3009
   Client::Sync::text::testDelete,                                           \
   Client::Sync::text::testItemsXML,                                         \
   Client::Sync::text::testOneWayFromServer,                                 \
+  Client::Sync::text::testOneWayFromClient,                                 \
   Client::Sync::text::Retry,Client::Sync::text::Suspend,                    \
   
  
@@ -70,6 +74,8 @@ All
      testOneWayFromServer,testRefreshFromClientSync.
   -- It fails in xml mode due to devinfo wrapped with cdata type
      This causes failure of testItemsXML.
+  -- Server initiates a slow-sync when one client syncs with server in one-way-from-client mode 
+     from the second time.
 vCard21
   -- Below properties are not supported:
      CALURI, CATEGORIES, FBURL, NICKNAME, X-MOZILLA-HTML, X-EVOLUTION-FILE-AS, X-AIM, 
diff --git a/test/README.zyb b/test/README.zyb
new file mode 100644 (file)
index 0000000..87b6186
--- /dev/null
@@ -0,0 +1,29 @@
+This document is used to show interoperability test information with zyb server.
+http://bugzilla.moblin.org/show_bug.cgi?id=2424
+
+* The zyb Server's device information 
+  ZYB HTTP SyncML Server
+  Version:3.9.18
+  Build:3.9.18b572
+
+* Test Environment Variables Settings
+  CLIENT_TEST_SERVER=zyb CLIENT_TEST_EVOLUTION_PREFIX=file:///tmp/test/
+* Test Profiles Settings
+  -- N/A
+
+* Data formats we need to test:
+  -- Client::Sync::vcard21
+
+* Know Limitations in ZYB server:
+VCard21
+  -- Only below properties are accepted:
+     FN, N, PHOTO, BDAY, ADR, LABEL, TEL, EMAIL, TZ, GEO, TITLE, ROLE, LOGO, ORG, NOTE, REV, SOUND, URL 
+  -- The property 'N' parser error: treat "\;" as the delimiter
+  -- The property 'ADR': if it is long, three extra chars '\r', '\n' and ' 'will be added in the property value.
+  -- Server does escaped text processing, e.g, "&lt\;" is converted to "<"
+  -- Server sends mismatch anchors between two sync even if there is no failure. 
+
+* Known test failures:
+  -- NONE
+
index d72615d..deaf62c 100644 (file)
@@ -57,7 +57,7 @@ my $server = $ENV{CLIENT_TEST_SERVER};
 my $client = $ENV{CLIENT_TEST_CLIENT} || "evolution";
 my $scheduleworld = $server =~ /scheduleworld/;
 my $synthesis = $server =~ /synthesis/;
-#my $zyb = $server =~ /zyb/;
+my $zyb = $server =~ /zyb/;
 my $mobical = $server =~ /mobical/;
 my $memotoo = $server =~ /memotoo/;
 
@@ -404,6 +404,10 @@ sub Normalize {
       }
     }
 
+    if ($zyb) {
+        s/^(CALURI|CATEGORIES|FBURL|NICKNAME|X-MOZILLA-HTML|PHOTO|X-EVOLUTION-FILE-AS|X-ANNIVERSARY|X-ASSISTANT|X-EVOLUTION-BLOG-URL|X-EVOLUTION-VIDEO-URL|X-GROUPWISE|X-ICQ|X-MANAGER|X-SPOUSE|X-YAHOO|X-AIM)(;[^:;\n]*)*:.*\r?\n?//gm;
+    }
+
     # treat X-MOZILLA-HTML=FALSE as if the property didn't exist
     s/^X-MOZILLA-HTML:FALSE\r?\n?//gm;