Imported Upstream version 1.3.99.5_20131030_SE_05e5911_SYSYNC_69de386 upstream/1.3.99.5_20131030_SE_05e5911_SYSYNC_69de386
authorroot <root@pohly-mobl1.fritz.box>
Wed, 20 Nov 2013 15:20:38 +0000 (15:20 +0000)
committerroot <root@pohly-mobl1.fritz.box>
Wed, 20 Nov 2013 15:20:38 +0000 (15:20 +0000)
62 files changed:
Makefile.am
Makefile.in
NEWS
README
config.h.in
configure
configure.ac
src/backends/activesync/configure-sub.in
src/backends/evolution/EvolutionContactSource.cpp
src/backends/evolution/EvolutionSyncSource.cpp
src/backends/evolution/configure-sub.in
src/dbus/server/localed-listener.cpp [new file with mode: 0644]
src/dbus/server/localed-listener.h [new file with mode: 0644]
src/dbus/server/main.cpp
src/dbus/server/org.syncevolution.service.in
src/dbus/server/pim/README
src/dbus/server/pim/folks.cpp
src/dbus/server/pim/folks.h
src/dbus/server/pim/full-view.cpp
src/dbus/server/pim/full-view.h
src/dbus/server/pim/locale-factory-boost.cpp
src/dbus/server/pim/locale-factory.cpp
src/dbus/server/pim/locale-factory.h
src/dbus/server/pim/manager.cpp
src/dbus/server/pim/manager.h
src/dbus/server/pim/org._01.pim.contacts.service.in
src/dbus/server/pim/testpim.py
src/dbus/server/presence-status.h
src/dbus/server/server.am
src/dbus/server/session-helper.cpp
src/dbus/server/session-helper.h
src/dbus/server/session.cpp
src/dbus/server/sync-helper.cpp
src/dbus/server/syncevo-dbus-server-startup.sh.in
src/syncevo/EDSClient.cpp
src/syncevo/EDSClient.h
src/syncevo/GLibSupport.h
src/syncevo/LocalTransportAgent.cpp
src/syncevo/LogDLT.cpp [new file with mode: 0644]
src/syncevo/LogDLT.h [new file with mode: 0644]
src/syncevo/LogRedirect.cpp
src/syncevo/LogStdout.cpp
src/syncevo/Logging.cpp
src/syncevo/Logging.h
src/syncevo/SyncContext.cpp
src/syncevo/SyncSource.cpp
src/syncevo/eds_abi_wrapper.cpp
src/syncevo/eds_abi_wrapper.h
src/syncevo/syncevo.am
src/synthesis-includes/Makefile.in
src/synthesis/ChangeLog
src/synthesis/Makefile.in
src/synthesis/README.DLT [new file with mode: 0644]
src/synthesis/config.h.in
src/synthesis/configure
src/synthesis/configure.in
src/synthesis/src/Makefile.am
src/synthesis/src/Makefile.am.in
src/synthesis/src/Makefile.in
src/synthesis/src/platform_adapters/linux/configfiles.cpp
src/synthesis/src/sysync/debuglogger.cpp
src/synthesis/src/sysync/debuglogger.h

index 9be9aec..ed83c92 100644 (file)
@@ -68,6 +68,13 @@ DEV_FILE_PATTERN = $(1)$(2)/include $(1)$(2)/lib/*.so $(1)$(2)/lib/*.a $(1)$(2)/
 # be packaged separately.
 DEV_FILE_PATTERN += $(1)$(2)/lib/syncevolution/backends/syncactivesync.so
 
+# It is possible to have additional .so backend files included in the
+# binary archives. The additional backend files must be named in the
+# EXTRA_BACKENDS env or make variable with their full file paths,
+# separated by spaces. They will be renamed to <basename>-2.so. See
+# also ScannedBackends in SyncSource.cpp.
+ADD_EXTRA_BACKENDS = set -e; for i in $(EXTRA_BACKENDS); do cp $$i $(1)/$(BACKENDS_DIRECTORY)/`basename $$i .so`-2.so; done
+
 # binary distribution as .tar.gz
 if COND_DBUS
 # when building with D-Bus, we have no choice: the service has to go into /usr
@@ -83,6 +90,7 @@ distbin : $(distbin_docs) INSTALL-tar-gz all
        mkdir -p $(distdir)/usr/share/doc/syncevolution
        cp $(srcdir)/INSTALL-tar-gz $(distdir)/INSTALL
        cp $(filter-out all, $+) $(distdir)/usr/share/doc/syncevolution
+       $(call ADD_EXTRA_BACKENDS, $(distdir))
        tar zcf $(distdir)-$(BINSUFFIX).tar.gz $(distdir)
        rm -rf $(distdir)
 else
@@ -96,6 +104,7 @@ distbin : $(distbin_docs) all
        rm -rf $(call DEV_FILE_PATTERN,$(distdir),/)
        for i in `find $(distdir) -type d | sort -r`; do rmdir $$i 2>/dev/null || true; done
        cp $(filter-out all, $+) $(distdir)
+       $(call ADD_EXTRA_BACKENDS, $(distdir))
        tar zcf $(distdir)-$(BINSUFFIX).tar.gz $(distdir)
        rm -rf $(distdir)
 endif
@@ -250,6 +259,7 @@ checkinstall/dist/$(distdir): all
        rm -rf $@
        $(MAKE) install DESTDIR=`pwd`/$@
        $(MAKE) installcheck DESTDIR=`pwd`/$@
+       $(call ADD_EXTRA_BACKENDS, $@)
        rm -rf $(call DEV_FILE_PATTERN,$@,/usr)
 clean-local: clean_dist
 clean_dist:
@@ -298,10 +308,12 @@ if ENABLE_EVOLUTION_COMPATIBILITY
 # (relevant in that case and for static builds) for dependencies on
 # problematic libraries and symbols
 #
+# Exclude *-2.so, these are EXTRA_BACKENDS for which other rules apply.
+#
 # ical_strdup is an exception because it is in SyncEvolution.
 all_local_installchecks += toplevel_so_check
 toplevel_so_check:
-       for i in `find $(DESTDIR)/$(libdir)/syncevolution $(DESTDIR)/$(libdir)/libsyncevo* $(DESTDIR)/$(libdir)/libsynthesis* -name *.so` $(DESTDIR)/$(bindir)/syncevolution; \
+       for i in `find $(DESTDIR)/$(libdir)/syncevolution $(DESTDIR)/$(libdir)/libsyncevo* $(DESTDIR)/$(libdir)/libsynthesis* -name *.so | grep -v -2.so` $(DESTDIR)/$(bindir)/syncevolution; \
        do \
          if objdump -T -C $$i | grep -v :: | grep '\*UND\*' | sort | grep -v -w ical_strdup | grep -e ical -e " e_"; then \
            echo "$$i should not depend on EDS, libical or libbluetooth"; \
@@ -406,8 +418,15 @@ dist-hook: $(all_dist_hooks)
 # Force sequential installation. This is a workaround for relinking failures
 # during concurrent distcheck (a backend was relinked against not yet installed
 # libsyncevolution.la).
+#
+# Also used to add additional backends.
 install-am: all-am
        @$(MAKE) $(AM_MAKEFLAGS) install-exec-am
        @$(MAKE) $(AM_MAKEFLAGS) install-data-am
+       for i in $(EXTRA_BACKENDS); do $(INSTALL) $$i $(DESTDIR)/$(BACKENDS_DIRECTORY)/`basename $$i .so`-2.so; done
+
+# Necessary for "make distcheck": must not leave files behind.
+uninstall-local:
+       rm -f $(DESTDIR)/$(BACKENDS_DIRECTORY)/*-2.so
 
 .DELETE_ON_ERROR:
index 1ef31b3..2fab6cd 100644 (file)
@@ -372,7 +372,7 @@ EXTRA_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
 
 @COND_DBUS_PIM_TRUE@@COND_DBUS_TRUE@am__append_66 = $(DBUS_PIM_PLUGIN_LDFLAGS)
 @COND_DBUS_PIM_TRUE@@COND_DBUS_TRUE@am__append_67 = $(FOLKS_LIBS) $(DBUS_PIM_PLUGIN_LIBS) $(PHONENUMBERS_LIBS)
-@COND_DBUS_PIM_TRUE@@COND_DBUS_TRUE@am__append_68 = $(FOLKS_CFLAGS) $(DBUS_PIM_PLUGIN_CFLAGS) $(PHONENUMBERS_CFLAGS)
+@COND_DBUS_PIM_TRUE@@COND_DBUS_TRUE@am__append_68 = $(FOLKS_CFLAGS) $(DBUS_PIM_PLUGIN_CFLAGS) $(PHONENUMBERS_CFLAGS) $(DLT_CFLAGS)
 
 # Need to list all plugins here and not include the active one in the regular
 # source list above, because "make dist" would only include the configured one.
@@ -508,6 +508,8 @@ EXTRA_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
 # (relevant in that case and for static builds) for dependencies on
 # problematic libraries and symbols
 #
+# Exclude *-2.so, these are EXTRA_BACKENDS for which other rules apply.
+#
 # ical_strdup is an exception because it is in SyncEvolution.
 @ENABLE_EVOLUTION_COMPATIBILITY_TRUE@am__append_106 = toplevel_so_check
 # libneon is intentionally not linked against, to choose between
@@ -1060,7 +1062,8 @@ am__src_dbus_server_libsyncevodbusserver_la_SOURCES_DIST =  \
        src/dbus/server/connection.h src/dbus/server/connman-client.h \
        src/dbus/server/dbus-callbacks.h \
        src/dbus/server/dbus-user-interface.h \
-       src/dbus/server/exceptions.h src/dbus/server/info-req.h \
+       src/dbus/server/exceptions.h \
+       src/dbus/server/localed-listener.h src/dbus/server/info-req.h \
        src/dbus/server/network-manager-client.h \
        src/dbus/server/presence-status.h \
        src/dbus/server/progress-data.h \
@@ -1092,7 +1095,9 @@ am__src_dbus_server_libsyncevodbusserver_la_SOURCES_DIST =  \
        src/dbus/server/connman-client.cpp \
        src/dbus/server/dbus-callbacks.cpp \
        src/dbus/server/dbus-user-interface.cpp \
-       src/dbus/server/exceptions.cpp src/dbus/server/info-req.cpp \
+       src/dbus/server/exceptions.cpp \
+       src/dbus/server/localed-listener.cpp \
+       src/dbus/server/info-req.cpp \
        src/dbus/server/network-manager-client.cpp \
        src/dbus/server/presence-status.cpp \
        src/dbus/server/progress-data.cpp \
@@ -1128,6 +1133,7 @@ am__src_dbus_server_libsyncevodbusserver_la_SOURCES_DIST =  \
 @COND_DBUS_TRUE@       src/dbus/server/src_dbus_server_libsyncevodbusserver_la-dbus-callbacks.lo \
 @COND_DBUS_TRUE@       src/dbus/server/src_dbus_server_libsyncevodbusserver_la-dbus-user-interface.lo \
 @COND_DBUS_TRUE@       src/dbus/server/src_dbus_server_libsyncevodbusserver_la-exceptions.lo \
+@COND_DBUS_TRUE@       src/dbus/server/src_dbus_server_libsyncevodbusserver_la-localed-listener.lo \
 @COND_DBUS_TRUE@       src/dbus/server/src_dbus_server_libsyncevodbusserver_la-info-req.lo \
 @COND_DBUS_TRUE@       src/dbus/server/src_dbus_server_libsyncevodbusserver_la-network-manager-client.lo \
 @COND_DBUS_TRUE@       src/dbus/server/src_dbus_server_libsyncevodbusserver_la-presence-status.lo \
@@ -1228,7 +1234,8 @@ am__src_syncevo_libsyncevolution_la_SOURCES_DIST =  \
        src/syncevo/ThreadSupport.h src/syncevo/SyncML.h \
        src/syncevo/SyncML.cpp src/syncevo/SynthesisEngine.h \
        src/syncevo/SynthesisEngine.cpp src/syncevo/Logging.h \
-       src/syncevo/Logging.cpp src/syncevo/LogStdout.h \
+       src/syncevo/Logging.cpp src/syncevo/LogDLT.h \
+       src/syncevo/LogDLT.cpp src/syncevo/LogStdout.h \
        src/syncevo/LogStdout.cpp src/syncevo/LogRedirect.h \
        src/syncevo/LogRedirect.cpp src/syncevo/LogSyslog.h \
        src/syncevo/LogSyslog.cpp src/syncevo/TransportAgent.h \
@@ -1281,6 +1288,7 @@ am__src_syncevo_libsyncevolution_la_SOURCES_DIST =  \
 @COND_CORE_TRUE@       src/syncevo/src_syncevo_libsyncevolution_la-SyncML.lo \
 @COND_CORE_TRUE@       src/syncevo/src_syncevo_libsyncevolution_la-SynthesisEngine.lo \
 @COND_CORE_TRUE@       src/syncevo/src_syncevo_libsyncevolution_la-Logging.lo \
+@COND_CORE_TRUE@       src/syncevo/src_syncevo_libsyncevolution_la-LogDLT.lo \
 @COND_CORE_TRUE@       src/syncevo/src_syncevo_libsyncevolution_la-LogStdout.lo \
 @COND_CORE_TRUE@       src/syncevo/src_syncevo_libsyncevolution_la-LogRedirect.lo \
 @COND_CORE_TRUE@       src/syncevo/src_syncevo_libsyncevolution_la-LogSyslog.lo \
@@ -2224,13 +2232,13 @@ DBUS_SERVICES_DIR = @DBUS_SERVICES_DIR@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
 DLLTOOL = @DLLTOOL@
+DLT_CFLAGS = @DLT_CFLAGS@
+DLT_LIBS = @DLT_LIBS@
 DSYMUTIL = @DSYMUTIL@
 DUMPBIN = @DUMPBIN@
 EASCLIENT_CFLAGS = @EASCLIENT_CFLAGS@
 EASCLIENT_DEPENDENCIES = @EASCLIENT_DEPENDENCIES@
 EASCLIENT_LIBS = @EASCLIENT_LIBS@
-EBOOKCONTACTS_CFLAGS = @EBOOKCONTACTS_CFLAGS@
-EBOOKCONTACTS_LIBS = @EBOOKCONTACTS_LIBS@
 EBOOK_CFLAGS = @EBOOK_CFLAGS@
 EBOOK_LIBS = @EBOOK_LIBS@
 EBOOK_VERSION_CFLAGS = @EBOOK_VERSION_CFLAGS@
@@ -2405,6 +2413,7 @@ SYNCEVOLUTION_CXXFLAGS = @SYNCEVOLUTION_CXXFLAGS@
 SYNCEVOLUTION_LDADD = @SYNCEVOLUTION_LDADD@ $(am__append_83)
 SYNCEVOLUTION_LIBS = @SYNCEVOLUTION_LIBS@
 SYNCEVOLUTION_LOCALEDIR = @SYNCEVOLUTION_LOCALEDIR@
+SYNCEVO_DBUS_SERVER_ARGS = @SYNCEVO_DBUS_SERVER_ARGS@
 SYNCEVO_WFLAGS = @SYNCEVO_WFLAGS@
 SYNCSOURCES = @SYNCSOURCES@
 SYNTHESIS = @SYNTHESIS@
@@ -2751,6 +2760,7 @@ src_cppflags = -I$(top_srcdir)/src $(am__append_3) $(am__append_8) \
 @COND_CORE_TRUE@       src/syncevo/SynthesisEngine.h \
 @COND_CORE_TRUE@       src/syncevo/SynthesisEngine.cpp \
 @COND_CORE_TRUE@       src/syncevo/Logging.h src/syncevo/Logging.cpp \
+@COND_CORE_TRUE@       src/syncevo/LogDLT.h src/syncevo/LogDLT.cpp \
 @COND_CORE_TRUE@       src/syncevo/LogStdout.h \
 @COND_CORE_TRUE@       src/syncevo/LogStdout.cpp \
 @COND_CORE_TRUE@       src/syncevo/LogRedirect.h \
@@ -2851,7 +2861,8 @@ src_cppflags = -I$(top_srcdir)/src $(am__append_3) $(am__append_8) \
 @COND_CORE_TRUE@       @EPACKAGE_LIBS@ @GIO_LIBS@ @GTHREAD_LIBS@ \
 @COND_CORE_TRUE@       @GLIB_LIBS@ $(SYNTHESIS_LIBS) $(PCRECPP_LIBS) \
 @COND_CORE_TRUE@       $(TRANSPORT_LIBS) @LIBS@ $(src_syncevo_ldadd) \
-@COND_CORE_TRUE@       $(DBUS_LIBS) $(NSS_LIBS) $(am__append_27)
+@COND_CORE_TRUE@       $(DLT_LIBS) $(DBUS_LIBS) $(NSS_LIBS) \
+@COND_CORE_TRUE@       $(am__append_27)
 @COND_CORE_TRUE@src_syncevo_libsyncevolution_la_CXXFLAGS = \
 @COND_CORE_TRUE@  $(PCRECPP_CFLAGS) \
 @COND_CORE_TRUE@  $(TRANSPORT_CFLAGS) \
@@ -2865,13 +2876,14 @@ src_cppflags = -I$(top_srcdir)/src $(am__append_3) $(am__append_8) \
 
 @COND_CORE_TRUE@src_syncevo_libsyncevolution_la_CPPFLAGS = \
 @COND_CORE_TRUE@  $(src_syncevo_cppflags) \
+@COND_CORE_TRUE@  $(DLT_CFLAGS) \
 @COND_CORE_TRUE@  $(DBUS_CFLAGS) \
 @COND_CORE_TRUE@  -DDATA_DIR=\""$(pkgdatadir)"\" \
 @COND_CORE_TRUE@  -DXML_CONFIG_DIR=\""$(datadir)/syncevolution/xml"\" \
 @COND_CORE_TRUE@  -DTEMPLATE_DIR=\""$(datadir)/syncevolution/templates"\" \
 @COND_CORE_TRUE@  -DLIBDIR=\""$(libdir)"\"
 
-@COND_CORE_TRUE@src_syncevo_libsyncevolution_la_DEPENDENCIES = $(SYNTHESIS_DEP) $(src_syncevo_ldadd)
+@COND_CORE_TRUE@src_syncevo_libsyncevolution_la_DEPENDENCIES = $(SYNTHESIS_DEP) $(filter %.la, $(src_syncevo_ldadd))
 @COND_CORE_TRUE@@ENABLE_MODULES_FALSE@src_syncevo_libsyncevolution_la_LDFLAGS = -static
 @COND_CORE_TRUE@@ENABLE_MODULES_TRUE@src_syncevo_libsyncevolution_la_LDFLAGS = 
 
@@ -3286,6 +3298,7 @@ src_cppflags = -I$(top_srcdir)/src $(am__append_3) $(am__append_8) \
 @COND_DBUS_TRUE@       src/dbus/server/dbus-callbacks.cpp \
 @COND_DBUS_TRUE@       src/dbus/server/dbus-user-interface.cpp \
 @COND_DBUS_TRUE@       src/dbus/server/exceptions.cpp \
+@COND_DBUS_TRUE@       src/dbus/server/localed-listener.cpp \
 @COND_DBUS_TRUE@       src/dbus/server/info-req.cpp \
 @COND_DBUS_TRUE@       src/dbus/server/network-manager-client.cpp \
 @COND_DBUS_TRUE@       src/dbus/server/presence-status.cpp \
@@ -3636,6 +3649,13 @@ TEST_README_FILES = $(wildcard $(top_srcdir)/test/README.*)
 DEV_FILE_PATTERN = $(1)$(2)/include $(1)$(2)/lib/*.so $(1)$(2)/lib/*.a \
        $(1)$(2)/lib/*.la $(1)$(2)/lib/*/*.la $(1)$(2)/lib/pkgconfig \
        $(1)$(2)/lib/syncevolution/backends/syncactivesync.so
+
+# It is possible to have additional .so backend files included in the
+# binary archives. The additional backend files must be named in the
+# EXTRA_BACKENDS env or make variable with their full file paths,
+# separated by spaces. They will be renamed to <basename>-2.so. See
+# also ScannedBackends in SyncSource.cpp.
+ADD_EXTRA_BACKENDS = set -e; for i in $(EXTRA_BACKENDS); do cp $$i $(1)/$(BACKENDS_DIRECTORY)/`basename $$i .so`-2.so; done
 IPHONE_FILENAME = syncevolution-$(VERSION)-iphone.zip
 TYPE_deb = -D
 TYPE_rpm = -R
@@ -4696,6 +4716,9 @@ src/dbus/server/src_dbus_server_libsyncevodbusserver_la-dbus-user-interface.lo:
 src/dbus/server/src_dbus_server_libsyncevodbusserver_la-exceptions.lo:  \
        src/dbus/server/$(am__dirstamp) \
        src/dbus/server/$(DEPDIR)/$(am__dirstamp)
+src/dbus/server/src_dbus_server_libsyncevodbusserver_la-localed-listener.lo:  \
+       src/dbus/server/$(am__dirstamp) \
+       src/dbus/server/$(DEPDIR)/$(am__dirstamp)
 src/dbus/server/src_dbus_server_libsyncevodbusserver_la-info-req.lo:  \
        src/dbus/server/$(am__dirstamp) \
        src/dbus/server/$(DEPDIR)/$(am__dirstamp)
@@ -4831,6 +4854,9 @@ src/syncevo/src_syncevo_libsyncevolution_la-SynthesisEngine.lo:  \
 src/syncevo/src_syncevo_libsyncevolution_la-Logging.lo:  \
        src/syncevo/$(am__dirstamp) \
        src/syncevo/$(DEPDIR)/$(am__dirstamp)
+src/syncevo/src_syncevo_libsyncevolution_la-LogDLT.lo:  \
+       src/syncevo/$(am__dirstamp) \
+       src/syncevo/$(DEPDIR)/$(am__dirstamp)
 src/syncevo/src_syncevo_libsyncevolution_la-LogStdout.lo:  \
        src/syncevo/$(am__dirstamp) \
        src/syncevo/$(DEPDIR)/$(am__dirstamp)
@@ -5872,6 +5898,8 @@ mostlyclean-compile:
        -rm -f src/dbus/server/src_dbus_server_libsyncevodbusserver_la-exceptions.lo
        -rm -f src/dbus/server/src_dbus_server_libsyncevodbusserver_la-info-req.$(OBJEXT)
        -rm -f src/dbus/server/src_dbus_server_libsyncevodbusserver_la-info-req.lo
+       -rm -f src/dbus/server/src_dbus_server_libsyncevodbusserver_la-localed-listener.$(OBJEXT)
+       -rm -f src/dbus/server/src_dbus_server_libsyncevodbusserver_la-localed-listener.lo
        -rm -f src/dbus/server/src_dbus_server_libsyncevodbusserver_la-main.$(OBJEXT)
        -rm -f src/dbus/server/src_dbus_server_libsyncevodbusserver_la-main.lo
        -rm -f src/dbus/server/src_dbus_server_libsyncevodbusserver_la-network-manager-client.$(OBJEXT)
@@ -5974,6 +6002,8 @@ mostlyclean-compile:
        -rm -f src/syncevo/src_syncevo_libsyncevolution_la-IniConfigNode.lo
        -rm -f src/syncevo/src_syncevo_libsyncevolution_la-LocalTransportAgent.$(OBJEXT)
        -rm -f src/syncevo/src_syncevo_libsyncevolution_la-LocalTransportAgent.lo
+       -rm -f src/syncevo/src_syncevo_libsyncevolution_la-LogDLT.$(OBJEXT)
+       -rm -f src/syncevo/src_syncevo_libsyncevolution_la-LogDLT.lo
        -rm -f src/syncevo/src_syncevo_libsyncevolution_la-LogRedirect.$(OBJEXT)
        -rm -f src/syncevo/src_syncevo_libsyncevolution_la-LogRedirect.lo
        -rm -f src/syncevo/src_syncevo_libsyncevolution_la-LogStdout.$(OBJEXT)
@@ -6192,6 +6222,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@src/dbus/server/$(DEPDIR)/src_dbus_server_libsyncevodbusserver_la-dbus-user-interface.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/dbus/server/$(DEPDIR)/src_dbus_server_libsyncevodbusserver_la-exceptions.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/dbus/server/$(DEPDIR)/src_dbus_server_libsyncevodbusserver_la-info-req.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/dbus/server/$(DEPDIR)/src_dbus_server_libsyncevodbusserver_la-localed-listener.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/dbus/server/$(DEPDIR)/src_dbus_server_libsyncevodbusserver_la-main.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/dbus/server/$(DEPDIR)/src_dbus_server_libsyncevodbusserver_la-network-manager-client.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/dbus/server/$(DEPDIR)/src_dbus_server_libsyncevodbusserver_la-notification-backend-libnotify.Plo@am__quote@
@@ -6269,6 +6300,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@src/syncevo/$(DEPDIR)/src_syncevo_libsyncevolution_la-IdentityProvider.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/syncevo/$(DEPDIR)/src_syncevo_libsyncevolution_la-IniConfigNode.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/syncevo/$(DEPDIR)/src_syncevo_libsyncevolution_la-LocalTransportAgent.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/syncevo/$(DEPDIR)/src_syncevo_libsyncevolution_la-LogDLT.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/syncevo/$(DEPDIR)/src_syncevo_libsyncevolution_la-LogRedirect.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/syncevo/$(DEPDIR)/src_syncevo_libsyncevolution_la-LogStdout.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/syncevo/$(DEPDIR)/src_syncevo_libsyncevolution_la-LogSyslog.Plo@am__quote@
@@ -7302,6 +7334,13 @@ src/dbus/server/src_dbus_server_libsyncevodbusserver_la-exceptions.lo: src/dbus/
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_dbus_server_libsyncevodbusserver_la_CPPFLAGS) $(CPPFLAGS) $(src_dbus_server_libsyncevodbusserver_la_CXXFLAGS) $(CXXFLAGS) -c -o src/dbus/server/src_dbus_server_libsyncevodbusserver_la-exceptions.lo `test -f 'src/dbus/server/exceptions.cpp' || echo '$(srcdir)/'`src/dbus/server/exceptions.cpp
 
+src/dbus/server/src_dbus_server_libsyncevodbusserver_la-localed-listener.lo: src/dbus/server/localed-listener.cpp
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_dbus_server_libsyncevodbusserver_la_CPPFLAGS) $(CPPFLAGS) $(src_dbus_server_libsyncevodbusserver_la_CXXFLAGS) $(CXXFLAGS) -MT src/dbus/server/src_dbus_server_libsyncevodbusserver_la-localed-listener.lo -MD -MP -MF src/dbus/server/$(DEPDIR)/src_dbus_server_libsyncevodbusserver_la-localed-listener.Tpo -c -o src/dbus/server/src_dbus_server_libsyncevodbusserver_la-localed-listener.lo `test -f 'src/dbus/server/localed-listener.cpp' || echo '$(srcdir)/'`src/dbus/server/localed-listener.cpp
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) src/dbus/server/$(DEPDIR)/src_dbus_server_libsyncevodbusserver_la-localed-listener.Tpo src/dbus/server/$(DEPDIR)/src_dbus_server_libsyncevodbusserver_la-localed-listener.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='src/dbus/server/localed-listener.cpp' object='src/dbus/server/src_dbus_server_libsyncevodbusserver_la-localed-listener.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_dbus_server_libsyncevodbusserver_la_CPPFLAGS) $(CPPFLAGS) $(src_dbus_server_libsyncevodbusserver_la_CXXFLAGS) $(CXXFLAGS) -c -o src/dbus/server/src_dbus_server_libsyncevodbusserver_la-localed-listener.lo `test -f 'src/dbus/server/localed-listener.cpp' || echo '$(srcdir)/'`src/dbus/server/localed-listener.cpp
+
 src/dbus/server/src_dbus_server_libsyncevodbusserver_la-info-req.lo: src/dbus/server/info-req.cpp
 @am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_dbus_server_libsyncevodbusserver_la_CPPFLAGS) $(CPPFLAGS) $(src_dbus_server_libsyncevodbusserver_la_CXXFLAGS) $(CXXFLAGS) -MT src/dbus/server/src_dbus_server_libsyncevodbusserver_la-info-req.lo -MD -MP -MF src/dbus/server/$(DEPDIR)/src_dbus_server_libsyncevodbusserver_la-info-req.Tpo -c -o src/dbus/server/src_dbus_server_libsyncevodbusserver_la-info-req.lo `test -f 'src/dbus/server/info-req.cpp' || echo '$(srcdir)/'`src/dbus/server/info-req.cpp
 @am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) src/dbus/server/$(DEPDIR)/src_dbus_server_libsyncevodbusserver_la-info-req.Tpo src/dbus/server/$(DEPDIR)/src_dbus_server_libsyncevodbusserver_la-info-req.Plo
@@ -7505,6 +7544,13 @@ src/syncevo/src_syncevo_libsyncevolution_la-Logging.lo: src/syncevo/Logging.cpp
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_syncevo_libsyncevolution_la_CPPFLAGS) $(CPPFLAGS) $(src_syncevo_libsyncevolution_la_CXXFLAGS) $(CXXFLAGS) -c -o src/syncevo/src_syncevo_libsyncevolution_la-Logging.lo `test -f 'src/syncevo/Logging.cpp' || echo '$(srcdir)/'`src/syncevo/Logging.cpp
 
+src/syncevo/src_syncevo_libsyncevolution_la-LogDLT.lo: src/syncevo/LogDLT.cpp
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_syncevo_libsyncevolution_la_CPPFLAGS) $(CPPFLAGS) $(src_syncevo_libsyncevolution_la_CXXFLAGS) $(CXXFLAGS) -MT src/syncevo/src_syncevo_libsyncevolution_la-LogDLT.lo -MD -MP -MF src/syncevo/$(DEPDIR)/src_syncevo_libsyncevolution_la-LogDLT.Tpo -c -o src/syncevo/src_syncevo_libsyncevolution_la-LogDLT.lo `test -f 'src/syncevo/LogDLT.cpp' || echo '$(srcdir)/'`src/syncevo/LogDLT.cpp
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) src/syncevo/$(DEPDIR)/src_syncevo_libsyncevolution_la-LogDLT.Tpo src/syncevo/$(DEPDIR)/src_syncevo_libsyncevolution_la-LogDLT.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='src/syncevo/LogDLT.cpp' object='src/syncevo/src_syncevo_libsyncevolution_la-LogDLT.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_syncevo_libsyncevolution_la_CPPFLAGS) $(CPPFLAGS) $(src_syncevo_libsyncevolution_la_CXXFLAGS) $(CXXFLAGS) -c -o src/syncevo/src_syncevo_libsyncevolution_la-LogDLT.lo `test -f 'src/syncevo/LogDLT.cpp' || echo '$(srcdir)/'`src/syncevo/LogDLT.cpp
+
 src/syncevo/src_syncevo_libsyncevolution_la-LogStdout.lo: src/syncevo/LogStdout.cpp
 @am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_syncevo_libsyncevolution_la_CPPFLAGS) $(CPPFLAGS) $(src_syncevo_libsyncevolution_la_CXXFLAGS) $(CXXFLAGS) -MT src/syncevo/src_syncevo_libsyncevolution_la-LogStdout.lo -MD -MP -MF src/syncevo/$(DEPDIR)/src_syncevo_libsyncevolution_la-LogStdout.Tpo -c -o src/syncevo/src_syncevo_libsyncevolution_la-LogStdout.lo `test -f 'src/syncevo/LogStdout.cpp' || echo '$(srcdir)/'`src/syncevo/LogStdout.cpp
 @am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) src/syncevo/$(DEPDIR)/src_syncevo_libsyncevolution_la-LogStdout.Tpo src/syncevo/$(DEPDIR)/src_syncevo_libsyncevolution_la-LogStdout.Plo
@@ -10741,7 +10787,8 @@ uninstall-am: uninstall-binPROGRAMS uninstall-binSCRIPTS \
        uninstall-dist_src_testcases_templates_clients_phone_nokia_s40DATA \
        uninstall-docDATA uninstall-libLTLIBRARIES \
        uninstall-libexecPROGRAMS uninstall-libexecSCRIPTS \
-       uninstall-man uninstall-nodist_accounts_providersDATA \
+       uninstall-local uninstall-man \
+       uninstall-nodist_accounts_providersDATA \
        uninstall-nodist_accounts_servicesDATA \
        uninstall-nodist_binSCRIPTS \
        uninstall-nodist_src_dbus_qt_libsyncevolution_qt_dbus_includeHEADERS \
@@ -10900,7 +10947,7 @@ uninstall-man: uninstall-man1
        uninstall-dist_src_testcases_templates_clients_phone_nokia_s40DATA \
        uninstall-docDATA uninstall-libLTLIBRARIES \
        uninstall-libexecPROGRAMS uninstall-libexecSCRIPTS \
-       uninstall-man uninstall-man1 \
+       uninstall-local uninstall-man uninstall-man1 \
        uninstall-nodist_accounts_providersDATA \
        uninstall-nodist_accounts_servicesDATA \
        uninstall-nodist_binSCRIPTS \
@@ -11159,11 +11206,11 @@ src/dbus/interfaces/%.xml: src/dbus/interfaces/%-full.xml src/dbus/interfaces/.s
 @ENABLE_QT_DBUS_TRUE@  && perl -pi -e 's/SYNCEVO-(\w*)-FULL_H/SYNCEVO_$$1_FULL_H/' src/dbus/qt/syncevo-$*-full.* \
 @ENABLE_QT_DBUS_TRUE@  && echo 'timestamp' >$@
 @COND_DBUS_TRUE@$(src_dbus_server_script): $(src_dbus_server_script_in)
-@COND_DBUS_TRUE@       @sed -e "s|\@libexecdir\@|$(libexecdir)|" $< >$@
+@COND_DBUS_TRUE@       @sed -e "s|\@libexecdir\@|$(libexecdir)|" -e "s|\@SYNCEVO_DBUS_SERVER_ARGS\@|$(SYNCEVO_DBUS_SERVER_ARGS)|" $< >$@
 @COND_DBUS_TRUE@$(src_dbus_server_desktop): $(src_dbus_server_desktop_in)
 @COND_DBUS_TRUE@       @sed -e "s|\@libexecdir\@|$(libexecdir)|" $< >$@
 @COND_DBUS_TRUE@src/dbus/server/%.service: src/dbus/server/%.service.in
-@COND_DBUS_TRUE@       @sed -e "s|\@libexecdir\@|$(libexecdir)|" $< >$@
+@COND_DBUS_TRUE@       @sed -e "s|\@libexecdir\@|$(libexecdir)|" -e "s|\@SYNCEVO_DBUS_SERVER_ARGS\@|$(SYNCEVO_DBUS_SERVER_ARGS)|" $< >$@
 
 # if this will pose a problem then see the link below, probably the solution
 # here will need to be used.
@@ -11329,6 +11376,7 @@ src/test: src/client-test
 @COND_DBUS_TRUE@       mkdir -p $(distdir)/usr/share/doc/syncevolution
 @COND_DBUS_TRUE@       cp $(srcdir)/INSTALL-tar-gz $(distdir)/INSTALL
 @COND_DBUS_TRUE@       cp $(filter-out all, $+) $(distdir)/usr/share/doc/syncevolution
+@COND_DBUS_TRUE@       $(call ADD_EXTRA_BACKENDS, $(distdir))
 @COND_DBUS_TRUE@       tar zcf $(distdir)-$(BINSUFFIX).tar.gz $(distdir)
 @COND_DBUS_TRUE@       rm -rf $(distdir)
 # without D-Bus, we can simply create an archive with a bin directory
@@ -11341,6 +11389,7 @@ src/test: src/client-test
 @COND_DBUS_FALSE@      rm -rf $(call DEV_FILE_PATTERN,$(distdir),/)
 @COND_DBUS_FALSE@      for i in `find $(distdir) -type d | sort -r`; do rmdir $$i 2>/dev/null || true; done
 @COND_DBUS_FALSE@      cp $(filter-out all, $+) $(distdir)
+@COND_DBUS_FALSE@      $(call ADD_EXTRA_BACKENDS, $(distdir))
 @COND_DBUS_FALSE@      tar zcf $(distdir)-$(BINSUFFIX).tar.gz $(distdir)
 @COND_DBUS_FALSE@      rm -rf $(distdir)
 
@@ -11425,6 +11474,7 @@ checkinstall/dist/$(distdir): all
        rm -rf $@
        $(MAKE) install DESTDIR=`pwd`/$@
        $(MAKE) installcheck DESTDIR=`pwd`/$@
+       $(call ADD_EXTRA_BACKENDS, $@)
        rm -rf $(call DEV_FILE_PATTERN,$@,/usr)
 clean-local: clean_dist
 clean_dist:
@@ -11461,7 +11511,7 @@ dot_dist_hook:
          echo 'A git checkout is required to generate a ChangeLog.' >&2; \
        fi
 @ENABLE_EVOLUTION_COMPATIBILITY_TRUE@toplevel_so_check:
-@ENABLE_EVOLUTION_COMPATIBILITY_TRUE@  for i in `find $(DESTDIR)/$(libdir)/syncevolution $(DESTDIR)/$(libdir)/libsyncevo* $(DESTDIR)/$(libdir)/libsynthesis* -name *.so` $(DESTDIR)/$(bindir)/syncevolution; \
+@ENABLE_EVOLUTION_COMPATIBILITY_TRUE@  for i in `find $(DESTDIR)/$(libdir)/syncevolution $(DESTDIR)/$(libdir)/libsyncevo* $(DESTDIR)/$(libdir)/libsynthesis* -name *.so | grep -v -2.so` $(DESTDIR)/$(bindir)/syncevolution; \
 @ENABLE_EVOLUTION_COMPATIBILITY_TRUE@  do \
 @ENABLE_EVOLUTION_COMPATIBILITY_TRUE@    if objdump -T -C $$i | grep -v :: | grep '\*UND\*' | sort | grep -v -w ical_strdup | grep -e ical -e " e_"; then \
 @ENABLE_EVOLUTION_COMPATIBILITY_TRUE@      echo "$$i should not depend on EDS, libical or libbluetooth"; \
@@ -11533,9 +11583,16 @@ dist-hook: $(all_dist_hooks)
 # Force sequential installation. This is a workaround for relinking failures
 # during concurrent distcheck (a backend was relinked against not yet installed
 # libsyncevolution.la).
+#
+# Also used to add additional backends.
 install-am: all-am
        @$(MAKE) $(AM_MAKEFLAGS) install-exec-am
        @$(MAKE) $(AM_MAKEFLAGS) install-data-am
+       for i in $(EXTRA_BACKENDS); do $(INSTALL) $$i $(DESTDIR)/$(BACKENDS_DIRECTORY)/`basename $$i .so`-2.so; done
+
+# Necessary for "make distcheck": must not leave files behind.
+uninstall-local:
+       rm -f $(DESTDIR)/$(BACKENDS_DIRECTORY)/*-2.so
 
 .DELETE_ON_ERROR:
 
diff --git a/NEWS b/NEWS
index cc4f0ae..225fe37 100644 (file)
--- a/NEWS
+++ b/NEWS
+SyncEvolution 1.3.99.6, xxxxxxxxxx
+==================================
+
+This update focuses on SyncEvolution in IVI again. It adds support for
+GENIVI Diagnostic Log and Trace (DLT) and enhances searching in the
+unified address book.
+
+Binaries on syncevolution.org now work with EDS < 3.6 *and* >= 3.6.
+
+Details:
+
+* libsynthesis: avoid redundant (and sometimes slow) getaddrbyname() (FDO #70771)
+
+  The network lookup of the hostname can be slow (10 second delay when
+  not connected) and shouldn't be necessary anyway, so disable it.
+
+* PIM Manager: case-insensitive and transliterated search (FDO #56524)
+
+* PIM: accent-insensitive and transliterated search (FDO #56524)
+
+  Accent-insensitive search ignores accents, using the same code as in
+  EDS.  Transliterated search ignores foreign scripts by transliterating
+  search term and contact properties to Latin first. That one is using
+  ICU directly in the same way as EDS, but doesn't use the EDS
+  ETransliterator class to avoid extra string copying.
+
+  This commit changes the default behavior such that searching is by
+  default most permissive (case- and accent-insensitive, does
+  transliteration). Flags exist to restore more restrictive matching.
+
+* PIM: relax phone number matching
+
+  Previously, the current default country was used to turn phone numbers
+  without an explicit country code into full E164 numbers, which then
+  had to match the search term when doing a caller ID lookup.
+
+  This was inconsistent with EDS, where a weaker
+  EQUALS_NATIONAL_PHONE_NUMBER was done. The difference is that a
+  comparison between a number with country code matches one without if
+  the national number of the same, regardless of the current default
+  country. This is better because it reduces the influence of the hard
+  to guess default country on matching.
+
+  Another advantage of this change is the lower memory consumption and
+  faster comparison, because strings are now stored in 4 + 8 byte
+  numbers instead of strings of varying length.
+
+* PIM: fix incorrect write into pim-manager.ini (FDO #70772)
+
+  Removing a peer accidentally wrote the updated list of active
+  address books into the "sort" property of pim-manager.ini, which
+  then prevented starting the PIM Manager.
+
+* PIM: ignore broken sort order in config (FDO #70772)
+
+  Failure to set the sort order from pim-manager.ini should not
+  prevent the startup of the PIM Manager because the client cannot
+  really diagnose and fix the problem. It is better to try again with
+  the default sort order.
+
+* PIM: adapt to locale changes at runtime (FDO #66618)
+
+  Listen to signals from localed D-Bus system service and update all
+  internal state which depends on the current locale. This state includes:
+  - pre-computed data in all loaded contacts
+  - filtering (for example, case sensitivity is locale dependent)
+  - the sort order
+
+  This feature can be controlled by setting the SYNCEVOLUTION_LOCALED
+  env variable:
+  - "session" - use a localed instance on the D-Bus session bus instead
+    of the system instance. This was originally meant for
+    testing, but might also be useful for per-user setting changes.
+  - "none" - disables the feature
+
+* D-Bus server: support DLT (FDO #66769)
+
+  Diagnostic Log and Trace (DLT) manages a sequence of log messages,
+  with remote controllable level of detail. SyncEvolution optionally
+  (can be chosen at compile time and again at runtime) uses DLT
+  instead of its own syncevolution-log.html files. See README-DLT.rst
+  for more information.
+
+  To use the feature, configure SyncEvolution with
+  "--enable-dbus-server=--dlt --no-syslog"
+
+* EDS: enhanced compatibility mode
+
+  SyncEvolution compiled for EDS < 3.6 can now also load EDS backends
+  compiled for EDS >= 3.6. The packaging for syncevolution.org uses
+  that to bundle EDS backends compiled on different distros in the
+  same package.
+
+* EDS: SYNCEVOLUTION_EBOOK_QUERY env variable
+
+  Setting the SYNCEVOLUTION_EBOOK_QUERY env variable to a valid EBook
+  query string limits the results to contacts matching that
+  query. Useful only in combination with --print-items or
+  --export. Only implemented for EDS >= 3.6.
+
+* EDS: fix compile problem with boost and EDS > 3.36
+
+  This fixes the following problem, seen with Boost 1.53.0 on altlinux
+  when compiling for EDS >= 3.6:
+
+    /usr/include/boost/smart_ptr/shared_ptr.hpp: In instantiation of 'typename boost::detail::sp_array_access<T>::type boost::shared_ptr<T>::operator[](std::ptrdiff_t) const [with T = char*; typename boost::detail::sp_array_access<T>::type = void; std::ptrdiff_t = long int]':
+    src/backends/evolution/EvolutionSyncSource.cpp:163:38: required from here
+    /usr/include/boost/smart_ptr/shared_ptr.hpp:663:22: error: return-statement with a value, in function returning 'void' [-fpermissive]
+    make[2]: *** [src/backends/evolution/src_backends_evolution_syncecal_la-EvolutionSyncSource.lo]
+
+
 SyncEvolution 1.3.99.5, 01.10.2013
 ==================================
 
 SyncEvolution now supports Google CalDAV/CardDAV with OAuth2
-authentication. These are the open protocol that Google currently and
-thus the recommended way of syncing with Google, replacing ActiveSync
-and SyncML (both no longer available to all Google customers).
+authentication. These are the open protocol that Google currently
+supports and thus the recommended way of syncing with Google,
+replacing ActiveSync and SyncML (both no longer available to all
+Google customers).
 
 Support for Google CardDAV is new. Because of a vCard encoding issue
 on the server side, spaces in long notes may get removed. Like
diff --git a/README b/README
index db77cb3..6c79129 100644 (file)
--- a/README
+++ b/README
@@ -7,8 +7,8 @@ synchronize personal information management data
 ------------------------------------------------
 
 :Manual section: 1
-:Version: 1.3.99.5
-:Date: 2013-10-01
+:Version: 1.3.99.5+20131030+SE+05e5911+SYSYNC+69de386
+:Date: 2013-10-30
 
 
 SYNOPSIS
index 835f3dc..690c556 100644 (file)
@@ -9,6 +9,15 @@
 /* "SyncML DevInf DevType" */
 #undef DEVICE_TYPE
 
+/* "DLT app ID for syncevo-dbus-helper" */
+#undef DLT_SYNCEVO_DBUS_HELPER_ID
+
+/* "DLT app ID for syncevo-dbus-server" */
+#undef DLT_SYNCEVO_DBUS_SERVER_ID
+
+/* "DLT app ID for syncevo-local-helper" */
+#undef DLT_SYNCEVO_LOCAL_HELPER_ID
+
 /* ActiveSync available */
 #undef ENABLE_ACTIVESYNC
 
 /* "using Synthesis engine" */
 #undef SYNTHESIS
 
+/* "optionally use GENIVI Diagnostic Log and Trace for logging" */
+#undef USE_DLT
+
 /* use e_book/cal_client_* calls */
 #undef USE_EDS_CLIENT
 
index 035aca7..60dceb5 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.69 for syncevolution 1.3.99.5.
+# Generated by GNU Autoconf 2.69 for syncevolution 1.3.99.5+20131030+SE+05e5911+SYSYNC+69de386.
 #
 #
 # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -587,8 +587,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='syncevolution'
 PACKAGE_TARNAME='syncevolution'
-PACKAGE_VERSION='1.3.99.5'
-PACKAGE_STRING='syncevolution 1.3.99.5'
+PACKAGE_VERSION='1.3.99.5+20131030+SE+05e5911+SYSYNC+69de386'
+PACKAGE_STRING='syncevolution 1.3.99.5+20131030+SE+05e5911+SYSYNC+69de386'
 PACKAGE_BUGREPORT=''
 PACKAGE_URL=''
 
@@ -717,8 +717,6 @@ KEYRING_LIBS
 KEYRING_CFLAGS
 FILE_LIBS
 FILE_CFLAGS
-EBOOKCONTACTS_LIBS
-EBOOKCONTACTS_CFLAGS
 EDS_VERSION_LIBS
 EDS_VERSION_CFLAGS
 ENABLE_ECAL_FALSE
@@ -862,6 +860,7 @@ DBUS_LIBS
 DBUS_CFLAGS
 COND_GIO_GDBUS_FALSE
 COND_GIO_GDBUS_TRUE
+SYNCEVO_DBUS_SERVER_ARGS
 COND_DBUS_FALSE
 COND_DBUS_TRUE
 COND_CORE_FALSE
@@ -877,6 +876,8 @@ ENABLE_BLUETOOTH_FALSE
 ENABLE_BLUETOOTH_TRUE
 ENABLE_OBEX_FALSE
 ENABLE_OBEX_TRUE
+DLT_LIBS
+DLT_CFLAGS
 BLUEZ_LIBS
 BLUEZ_CFLAGS
 LIBOPENOBEX_LIBS
@@ -1051,6 +1052,8 @@ enable_maemo
 with_ca_certificates
 enable_libcurl
 enable_libsoup
+enable_dlt
+with_dlt_syncevolution
 enable_bluetooth
 enable_ssl_certificate_check
 enable_gtk
@@ -1119,6 +1122,8 @@ LIBOPENOBEX_CFLAGS
 LIBOPENOBEX_LIBS
 BLUEZ_CFLAGS
 BLUEZ_LIBS
+DLT_CFLAGS
+DLT_LIBS
 DBUS_CFLAGS
 DBUS_LIBS
 LIBNOTIFY_CFLAGS
@@ -1159,8 +1164,6 @@ EBOOK_VERSION_CFLAGS
 EBOOK_VERSION_LIBS
 EDS_VERSION_CFLAGS
 EDS_VERSION_LIBS
-EBOOKCONTACTS_CFLAGS
-EBOOKCONTACTS_LIBS
 KEYRING_CFLAGS
 KEYRING_LIBS
 KCALEXTENDED_CFLAGS
@@ -1734,7 +1737,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 1.3.99.5 to adapt to many kinds of systems.
+\`configure' configures syncevolution 1.3.99.5+20131030+SE+05e5911+SYSYNC+69de386 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1804,7 +1807,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of syncevolution 1.3.99.5:";;
+     short | recursive ) echo "Configuration of syncevolution 1.3.99.5+20131030+SE+05e5911+SYSYNC+69de386:";;
    esac
   cat <<\_ACEOF
 
@@ -1852,6 +1855,8 @@ Optional Features:
                           the Maemo 2.0 until at least 3.0 EDS-Dbus
   --enable-libcurl        enable libcurl as transport layer
   --enable-libsoup        enable libsoup as transport layer
+  --enable-dlt            enable logging via GENIVI Diagnostic Log and Trace
+                          (DLT)
   --enable-bluetooth      enable bluetooth transport support
   --disable-ssl-certificate-check
                           Disable SSL certificate checking in all server
@@ -1873,9 +1878,14 @@ Optional Features:
                           built when --enable-gui is not used.
   --enable-core           enables building the core SyncEvolution (library,
                           backends)
-  --enable-dbus-service   enables building the dbus service executable and all
+  --enable-dbus-service=args
+                          Enables building the dbus service executable and all
                           related features (the DBus wrapper library, command
-                          line usage of server, etc).
+                          line usage of server, etc). The optional arguments
+                          are syncevo-dbus-server command line arguments that
+                          are used when auto-starting via D-Bus or .desktop
+                          file. By default, the daemon logs to syslog. This
+                          can be changed via command line arguments.
   --enable-notify         send notifications for automatic sync events, using
                           libnotify
   --enable-notify-compatibility
@@ -1990,6 +2000,10 @@ Optional Packages:
                           using libcurl (because it has its own default), a
                           list of paths known to work for Debian and Red Hat
                           otherwise.
+  --with-dlt-syncevolution=SYNS,SYNH,SYNL
+                          controls the application IDs used by
+                          syncevo-dbus-server, syncevo-dbus-helper and
+                          syncevo-local-sync
   --with-gio-gdbus        enables use of GIO's GDBus instead of the in-tree,
                           Bluez gdbus.
   --with-boost-locale[=special-lib]
@@ -2051,6 +2065,8 @@ Some influential environment variables:
   BLUEZ_CFLAGS
               C compiler flags for BLUEZ, overriding pkg-config
   BLUEZ_LIBS  linker flags for BLUEZ, overriding pkg-config
+  DLT_CFLAGS  C compiler flags for DLT, overriding pkg-config
+  DLT_LIBS    linker flags for DLT, overriding pkg-config
   DBUS_CFLAGS C compiler flags for DBUS, overriding pkg-config
   DBUS_LIBS   linker flags for DBUS, overriding pkg-config
   LIBNOTIFY_CFLAGS
@@ -2119,10 +2135,6 @@ Some influential environment variables:
               C compiler flags for EDS_VERSION, overriding pkg-config
   EDS_VERSION_LIBS
               linker flags for EDS_VERSION, overriding pkg-config
-  EBOOKCONTACTS_CFLAGS
-              C compiler flags for EBOOKCONTACTS, overriding pkg-config
-  EBOOKCONTACTS_LIBS
-              linker flags for EBOOKCONTACTS, overriding pkg-config
   KEYRING_CFLAGS
               C compiler flags for KEYRING, overriding pkg-config
   KEYRING_LIBS
@@ -2239,7 +2251,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-syncevolution configure 1.3.99.5
+syncevolution configure 1.3.99.5+20131030+SE+05e5911+SYSYNC+69de386
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2879,7 +2891,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 1.3.99.5, which was
+It was created by syncevolution $as_me 1.3.99.5+20131030+SE+05e5911+SYSYNC+69de386, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -3267,6 +3279,10 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
 
+
+
+
+
 # Minimum version of libsynthesis as defined in its
 # configure script and thus .pc files:
 
@@ -3794,7 +3810,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='syncevolution'
- VERSION='1.3.99.5'
+ VERSION='1.3.99.5+20131030+SE+05e5911+SYSYNC+69de386'
 
 
 cat >>confdefs.h <<_ACEOF
 
 
 
-test "x$CPPUNIT_CONFIG" != 'xno' || as_fn_error $? "\"cppunit-config not found.\"" "$LINENO" 5
-
 # cppunit needed?
-#if test "x$enable_unit_tests" = 'xyes' || test "x$enable_integration_tests" = 'xyes'
-#then
+if test "x$enable_unit_tests" = 'xyes' || test "x$enable_integration_tests" = 'xyes'; then
+  test "x$CPPUNIT_CONFIG" != 'xno' || as_fn_error $? "\"cppunit-config not found.\"" "$LINENO" 5
+fi
+if test "x$CPPUNIT_CONFIG" != 'xno'; then
+  # Export the flags if available, even if not enabled. This allows
+  # "make src/client-test" in cases where "make all" would not build
+  # client-test.
   CPPUNIT_CXXFLAGS=`$CPPUNIT_CONFIG --cflags`
   CPPUNIT_LDFLAGS=`$CPPUNIT_CONFIG --libs`
-#fi
+fi
 
 
 
 # SoupTransportAgent depends on glib
 case "$TRANSPORT" in *libsoup*) need_glib=yes;; esac
 
+# Check whether --enable-dlt was given.
+if test "${enable_dlt+set}" = set; then :
+  enableval=$enable_dlt; enable_dlt=$enableval
+               test $enable_dlt = "yes" || test $enable_dlt = "no" || as_fn_error $? "invalid value of --enable-dlt: $enableval" "$LINENO" 5
+else
+  enable_dlt="no"
+fi
+
+if test "$enable_dlt" = "yes"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for DLT" >&5
+$as_echo_n "checking for DLT... " >&6; }
+
+if test -n "$DLT_CFLAGS"; then
+    pkg_cv_DLT_CFLAGS="$DLT_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"automotive-dlt\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "automotive-dlt") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_DLT_CFLAGS=`$PKG_CONFIG --cflags "automotive-dlt" 2>/dev/null`
+                     test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$DLT_LIBS"; then
+    pkg_cv_DLT_LIBS="$DLT_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"automotive-dlt\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "automotive-dlt") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_DLT_LIBS=`$PKG_CONFIG --libs "automotive-dlt" 2>/dev/null`
+                     test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+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
+               DLT_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "automotive-dlt" 2>&1`
+        else
+               DLT_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "automotive-dlt" 2>&1`
+        fi
+       # Put the nasty error message in config.log where it belongs
+       echo "$DLT_PKG_ERRORS" >&5
+
+       as_fn_error $? "dlt not found, required for --enable-dlt" "$LINENO" 5
+elif test $pkg_failed = untried; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+       as_fn_error $? "dlt not found, required for --enable-dlt" "$LINENO" 5
+else
+       DLT_CFLAGS=$pkg_cv_DLT_CFLAGS
+       DLT_LIBS=$pkg_cv_DLT_LIBS
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+       USE_DLT=1
+fi
+
+$as_echo "#define USE_DLT 1" >>confdefs.h
+
+
+# Check whether --with-dlt-syncevolution was given.
+if test "${with_dlt_syncevolution+set}" = set; then :
+  withval=$with_dlt_syncevolution; with_dlt_ids="$withval"
+else
+  with_dlt_ids="SYNS,SYNH,SYNL"
+fi
+
+    syns=`echo $with_dlt_ids | cut -d , -f 1`
+    synh=`echo $with_dlt_ids | cut -d , -f 2`
+    synl=`echo $with_dlt_ids | cut -d , -f 3`
+
+cat >>confdefs.h <<_ACEOF
+#define DLT_SYNCEVO_DBUS_SERVER_ID "$syns"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define DLT_SYNCEVO_DBUS_HELPER_ID "$synh"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define DLT_SYNCEVO_LOCAL_HELPER_ID "$synl"
+_ACEOF
+
+fi
+
 bluetooth_disabled=no
 # Check whether --enable-bluetooth was given.
 if test "${enable_bluetooth+set}" = set; then :
@@ -17675,7 +17805,7 @@ else
                fi
 fi
 
- if test "$enable_dbus_service" = "yes"; then
+ if test "$enable_dbus_service" != "no"; then
   COND_DBUS_TRUE=
   COND_DBUS_FALSE='#'
 else
@@ -17683,6 +17813,10 @@ else
   COND_DBUS_FALSE=
 fi
 
+if test "$enable_dbus_service" != "no" && test "$enable_dbus_service" != "yes"; then
+   SYNCEVO_DBUS_SERVER_ARGS="$enable_dbus_service"
+fi
+
 
 
 # Check whether --with-gio-gdbus was given.
@@ -17933,7 +18067,7 @@ fi
 
 fi
 
-if test $enable_dbus_service = "yes"; then
+if test "$enable_dbus_service" != "no"; then
     if test -z "$XSLT"; then
        as_fn_error $? "xsltproc not found, is required for D-Bus service" "$LINENO" 5
     fi
@@ -18709,7 +18843,7 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
-if test $enable_gui != "no" || test $enable_dbus_service = "yes"; then
+if test "$enable_gui" != "no" || test "$enable_dbus_service" != "no"; then
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether NLS is requested" >&5
 $as_echo_n "checking whether NLS is requested... " >&6; }
@@ -20532,7 +20666,7 @@ $as_echo "yes" >&6; }
 
 fi
 
-elif test "$enable_dbus_service" = "yes"; then
+elif test "$enable_dbus_service" != "no"; then
     # syncevo-dbus-server needs localization
     :
 else
@@ -21071,12 +21205,12 @@ if test -n "$SYNTHESIS_CFLAGS"; then
     pkg_cv_SYNTHESIS_CFLAGS="$SYNTHESIS_CFLAGS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"synthesis >= 3.4.0.16.10\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "synthesis >= 3.4.0.16.10") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"synthesis >= 3.4.0.16.11\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "synthesis >= 3.4.0.16.11") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_SYNTHESIS_CFLAGS=`$PKG_CONFIG --cflags "synthesis >= 3.4.0.16.10" 2>/dev/null`
+  pkg_cv_SYNTHESIS_CFLAGS=`$PKG_CONFIG --cflags "synthesis >= 3.4.0.16.11" 2>/dev/null`
                      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
@@ -21088,12 +21222,12 @@ if test -n "$SYNTHESIS_LIBS"; then
     pkg_cv_SYNTHESIS_LIBS="$SYNTHESIS_LIBS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"synthesis >= 3.4.0.16.10\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "synthesis >= 3.4.0.16.10") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"synthesis >= 3.4.0.16.11\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "synthesis >= 3.4.0.16.11") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_SYNTHESIS_LIBS=`$PKG_CONFIG --libs "synthesis >= 3.4.0.16.10" 2>/dev/null`
+  pkg_cv_SYNTHESIS_LIBS=`$PKG_CONFIG --libs "synthesis >= 3.4.0.16.11" 2>/dev/null`
                      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
@@ -21114,14 +21248,14 @@ else
         _pkg_short_errors_supported=no
 fi
         if test $_pkg_short_errors_supported = yes; then
-               SYNTHESIS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "synthesis >= 3.4.0.16.10" 2>&1`
+               SYNTHESIS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "synthesis >= 3.4.0.16.11" 2>&1`
         else
-               SYNTHESIS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "synthesis >= 3.4.0.16.10" 2>&1`
+               SYNTHESIS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "synthesis >= 3.4.0.16.11" 2>&1`
         fi
        # Put the nasty error message in config.log where it belongs
        echo "$SYNTHESIS_PKG_ERRORS" >&5
 
-       as_fn_error $? "Package requirements (synthesis >= 3.4.0.16.10) were not met:
+       as_fn_error $? "Package requirements (synthesis >= 3.4.0.16.11) were not met:
 
 $SYNTHESIS_PKG_ERRORS
 
@@ -21208,12 +21342,12 @@ if test -n "$WITH_SYNTHESIS_SRC_CFLAGS"; then
     pkg_cv_WITH_SYNTHESIS_SRC_CFLAGS="$WITH_SYNTHESIS_SRC_CFLAGS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"synthesis >= 3.4.0.16.10\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "synthesis >= 3.4.0.16.10") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"synthesis >= 3.4.0.16.11\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "synthesis >= 3.4.0.16.11") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_WITH_SYNTHESIS_SRC_CFLAGS=`$PKG_CONFIG --cflags "synthesis >= 3.4.0.16.10" 2>/dev/null`
+  pkg_cv_WITH_SYNTHESIS_SRC_CFLAGS=`$PKG_CONFIG --cflags "synthesis >= 3.4.0.16.11" 2>/dev/null`
                      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
@@ -21225,12 +21359,12 @@ if test -n "$WITH_SYNTHESIS_SRC_LIBS"; then
     pkg_cv_WITH_SYNTHESIS_SRC_LIBS="$WITH_SYNTHESIS_SRC_LIBS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"synthesis >= 3.4.0.16.10\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "synthesis >= 3.4.0.16.10") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"synthesis >= 3.4.0.16.11\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "synthesis >= 3.4.0.16.11") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_WITH_SYNTHESIS_SRC_LIBS=`$PKG_CONFIG --libs "synthesis >= 3.4.0.16.10" 2>/dev/null`
+  pkg_cv_WITH_SYNTHESIS_SRC_LIBS=`$PKG_CONFIG --libs "synthesis >= 3.4.0.16.11" 2>/dev/null`
                      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
@@ -21251,18 +21385,18 @@ else
         _pkg_short_errors_supported=no
 fi
         if test $_pkg_short_errors_supported = yes; then
-               WITH_SYNTHESIS_SRC_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "synthesis >= 3.4.0.16.10" 2>&1`
+               WITH_SYNTHESIS_SRC_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "synthesis >= 3.4.0.16.11" 2>&1`
         else
-               WITH_SYNTHESIS_SRC_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "synthesis >= 3.4.0.16.10" 2>&1`
+               WITH_SYNTHESIS_SRC_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "synthesis >= 3.4.0.16.11" 2>&1`
         fi
        # Put the nasty error message in config.log where it belongs
        echo "$WITH_SYNTHESIS_SRC_PKG_ERRORS" >&5
 
-       as_fn_error $? "need at least libsynthesis >= 3.4.0.16.10; the latest libsynthesis for SyncEvolution is the one from http://cgit.freedesktop.org/SyncEvolution/" "$LINENO" 5
+       as_fn_error $? "need at least libsynthesis >= 3.4.0.16.11; the latest libsynthesis for SyncEvolution is the one from http://cgit.freedesktop.org/SyncEvolution/" "$LINENO" 5
 elif test $pkg_failed = untried; then
        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-       as_fn_error $? "need at least libsynthesis >= 3.4.0.16.10; the latest libsynthesis for SyncEvolution is the one from http://cgit.freedesktop.org/SyncEvolution/" "$LINENO" 5
+       as_fn_error $? "need at least libsynthesis >= 3.4.0.16.11; the latest libsynthesis for SyncEvolution is the one from http://cgit.freedesktop.org/SyncEvolution/" "$LINENO" 5
 else
        WITH_SYNTHESIS_SRC_CFLAGS=$pkg_cv_WITH_SYNTHESIS_SRC_CFLAGS
        WITH_SYNTHESIS_SRC_LIBS=$pkg_cv_WITH_SYNTHESIS_SRC_LIBS
@@ -21453,7 +21587,7 @@ if test "$enable_activesync" = "yes"; then
                 { $as_echo "$as_me:${as_lineno-$LINENO}: configuring activesyncd using the $ACTIVESYNCDSRC source code" >&5
 $as_echo "$as_me: configuring activesyncd using the $ACTIVESYNCDSRC source code" >&6;}
                 ( set -x; cd src/backends/activesync/activesyncd/build &&
-                  $ACTIVESYNCDSRC/configure --disable-eplugin --disable-camel-backend --prefix=`pwd`/../install) ||
+                  $ACTIVESYNCDSRC/configure --disable-eplugin --disable-camel-backend --disable-qtconfig --prefix=`pwd`/../install) ||
                 as_fn_error $? "configuring activesyncd failed" "$LINENO" 5
 
                 # hard-coded replacement for pkg-config: necessary because
@@ -22228,99 +22362,9 @@ $as_echo "yes" >&6; }
 
 $as_echo "#define USE_EDS_CLIENT 1" >>confdefs.h
 
-                           # When using it, then we also need libebook-contacts-1.2
-                           # for the ESourceBackendSummary extension.
-
-pkg_failed=no
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for EBOOKCONTACTS" >&5
-$as_echo_n "checking for EBOOKCONTACTS... " >&6; }
-
-if test -n "$EBOOKCONTACTS_CFLAGS"; then
-    pkg_cv_EBOOKCONTACTS_CFLAGS="$EBOOKCONTACTS_CFLAGS"
- elif test -n "$PKG_CONFIG"; then
-    if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libebook-contacts-1.2\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "libebook-contacts-1.2") 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }; then
-  pkg_cv_EBOOKCONTACTS_CFLAGS=`$PKG_CONFIG --cflags "libebook-contacts-1.2" 2>/dev/null`
-                     test "x$?" != "x0" && pkg_failed=yes
-else
-  pkg_failed=yes
-fi
- else
-    pkg_failed=untried
-fi
-if test -n "$EBOOKCONTACTS_LIBS"; then
-    pkg_cv_EBOOKCONTACTS_LIBS="$EBOOKCONTACTS_LIBS"
- elif test -n "$PKG_CONFIG"; then
-    if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libebook-contacts-1.2\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "libebook-contacts-1.2") 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }; then
-  pkg_cv_EBOOKCONTACTS_LIBS=`$PKG_CONFIG --libs "libebook-contacts-1.2" 2>/dev/null`
-                     test "x$?" != "x0" && pkg_failed=yes
-else
-  pkg_failed=yes
-fi
- else
-    pkg_failed=untried
-fi
-
-
-
-if test $pkg_failed = yes; then
-       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-
-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
-               EBOOKCONTACTS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libebook-contacts-1.2" 2>&1`
-        else
-               EBOOKCONTACTS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libebook-contacts-1.2" 2>&1`
-        fi
-       # Put the nasty error message in config.log where it belongs
-       echo "$EBOOKCONTACTS_PKG_ERRORS" >&5
-
-       as_fn_error $? "Package requirements (libebook-contacts-1.2) were not met:
-
-$EBOOKCONTACTS_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 EBOOKCONTACTS_CFLAGS
-and EBOOKCONTACTS_LIBS to avoid the need to call pkg-config.
-See the pkg-config man page for more details." "$LINENO" 5
-elif test $pkg_failed = untried; then
-       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-       { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_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 EBOOKCONTACTS_CFLAGS
-and EBOOKCONTACTS_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" "$LINENO" 5; }
-else
-       EBOOKCONTACTS_CFLAGS=$pkg_cv_EBOOKCONTACTS_CFLAGS
-       EBOOKCONTACTS_LIBS=$pkg_cv_EBOOKCONTACTS_LIBS
-        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-
-fi
+                           # Was used for a while (ESourceBackendSummarySetup), but not anymore.
+                           # Don't depend on it, it wasn't in 3.6 yet.
+                           # PKG_CHECK_MODULES(EBOOKCONTACTS, libebook-contacts-1.2)
                            { $as_echo "$as_me:${as_lineno-$LINENO}: checking for e_book_client_new_direct in -lebook-1.2" >&5
 $as_echo_n "checking for e_book_client_new_direct in -lebook-1.2... " >&6; }
 if ${ac_cv_lib_ebook_1_2_e_book_client_new_direct+:} false; then :
@@ -26033,7 +26077,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=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 1.3.99.5, which was
+This file was extended by syncevolution $as_me 1.3.99.5+20131030+SE+05e5911+SYSYNC+69de386, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -26099,7 +26143,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-syncevolution config.status 1.3.99.5
+syncevolution config.status 1.3.99.5+20131030+SE+05e5911+SYSYNC+69de386
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
index 3acbd07..a0893b4 100644 (file)
@@ -25,7 +25,7 @@ SE_CHECK_FOR_STABLE_RELEASE
 
 # Minimum version of libsynthesis as defined in its
 # configure script and thus .pc files:
-define([SYNTHESIS_MIN_VERSION], [3.4.0.16.10])
+define([SYNTHESIS_MIN_VERSION], [3.4.0.16.11])
 
 # Line above is patched by gen-autotools.sh. Handle
 # both "yes" and "no".
@@ -166,14 +166,17 @@ AC_CHECK_HEADERS(signal.h dlfcn.h)
 # cppunit-config is used even when both unit tests and integration tests are disabled.
 AC_PATH_PROG([CPPUNIT_CONFIG], [cppunit-config], [no])
 
-test "x$CPPUNIT_CONFIG" != 'xno' || AC_MSG_ERROR("cppunit-config not found.")
-
 # cppunit needed?
-#if test "x$enable_unit_tests" = 'xyes' || test "x$enable_integration_tests" = 'xyes'
-#then
+if test "x$enable_unit_tests" = 'xyes' || test "x$enable_integration_tests" = 'xyes'; then
+  test "x$CPPUNIT_CONFIG" != 'xno' || AC_MSG_ERROR("cppunit-config not found.")
+fi
+if test "x$CPPUNIT_CONFIG" != 'xno'; then
+  # Export the flags if available, even if not enabled. This allows
+  # "make src/client-test" in cases where "make all" would not build
+  # client-test.
   CPPUNIT_CXXFLAGS=`$CPPUNIT_CONFIG --cflags`
   CPPUNIT_LDFLAGS=`$CPPUNIT_CONFIG --libs`
-#fi
+fi
 AC_SUBST(CPPUNIT_CXXFLAGS)
 AC_SUBST(CPPUNIT_LDFLAGS)
 
@@ -287,6 +290,30 @@ AC_ARG_ENABLE(libsoup,
 # SoupTransportAgent depends on glib
 case "$TRANSPORT" in *libsoup*) need_glib=yes;; esac
 
+AC_ARG_ENABLE(dlt,
+              AS_HELP_STRING([--enable-dlt],
+                             [enable logging via GENIVI Diagnostic Log and Trace (DLT)]),
+              [enable_dlt=$enableval
+               test $enable_dlt = "yes" || test $enable_dlt = "no" || AC_ERROR([invalid value of --enable-dlt: $enableval])],
+              [enable_dlt="no"])
+if test "$enable_dlt" = "yes"; then
+    PKG_CHECK_MODULES(DLT, automotive-dlt,
+                      [USE_DLT=1],
+                      [AC_ERROR([dlt not found, required for --enable-dlt])])
+    AC_DEFINE(USE_DLT, 1, "optionally use GENIVI Diagnostic Log and Trace for logging")
+    AC_ARG_WITH([dlt-syncevolution],
+                AS_HELP_STRING([--with-dlt-syncevolution=SYNS,SYNH,SYNL],
+                               [controls the application IDs used by syncevo-dbus-server, syncevo-dbus-helper and syncevo-local-sync]),
+                [with_dlt_ids="$withval"],
+                [with_dlt_ids="SYNS,SYNH,SYNL"])
+    syns=`echo $with_dlt_ids | cut -d , -f 1`
+    synh=`echo $with_dlt_ids | cut -d , -f 2`
+    synl=`echo $with_dlt_ids | cut -d , -f 3`
+    AC_DEFINE_UNQUOTED(DLT_SYNCEVO_DBUS_SERVER_ID, "$syns", "DLT app ID for syncevo-dbus-server")
+    AC_DEFINE_UNQUOTED(DLT_SYNCEVO_DBUS_HELPER_ID, "$synh", "DLT app ID for syncevo-dbus-helper")
+    AC_DEFINE_UNQUOTED(DLT_SYNCEVO_LOCAL_HELPER_ID, "$synl", "DLT app ID for syncevo-local-helper")
+fi
+
 bluetooth_disabled=no
 AC_ARG_ENABLE(bluetooth,
               AS_HELP_STRING([--enable-bluetooth],
@@ -438,16 +465,24 @@ AC_ARG_ENABLE(core,
 AM_CONDITIONAL([COND_CORE], [test "$enable_core" = "yes"])
 
 AC_ARG_ENABLE(dbus-service,
-              AS_HELP_STRING([--enable-dbus-service],
-                             [enables building the dbus service executable and all related features
-                             (the DBus wrapper library, command line usage of server, etc).]),
+              AS_HELP_STRING([--enable-dbus-service=args],
+                             [Enables building the dbus service executable and all related features
+                             (the DBus wrapper library, command line usage of server, etc).
+                             The optional arguments are syncevo-dbus-server command line arguments
+                             that are used when auto-starting via D-Bus or .desktop file. By default,
+                             the daemon logs to syslog. This can be changed via command line arguments.
+                             ]),
               enable_dbus_service="$enableval",
               [if test $enable_gui = "no"; then
                   enable_dbus_service="no"
                else
                   enable_dbus_service="yes"
                fi])
-AM_CONDITIONAL([COND_DBUS], [test "$enable_dbus_service" = "yes"])
+AM_CONDITIONAL([COND_DBUS], [test "$enable_dbus_service" != "no"])
+if test "$enable_dbus_service" != "no" && test "$enable_dbus_service" != "yes"; then
+   SYNCEVO_DBUS_SERVER_ARGS="$enable_dbus_service"
+fi
+AC_SUBST(SYNCEVO_DBUS_SERVER_ARGS)
 
 AC_ARG_WITH([gio-gdbus],
             AS_HELP_STRING([--with-gio-gdbus],
@@ -477,7 +512,7 @@ AS_IF([test "x$with_gio_gdbus" = "xyes"],
                     AC_DEFINE(NEED_DBUS_WATCH_GET_UNIX_FD, 1,
                     [Define to 1 if you need the dbus_watch_get_unix_fd() function.]))])
 
-if test $enable_dbus_service = "yes"; then
+if test "$enable_dbus_service" != "no"; then
     if test -z "$XSLT"; then
        AC_MSG_ERROR([xsltproc not found, is required for D-Bus service])
     fi
@@ -600,7 +635,7 @@ DBUS_SERVICES_DIR="${datadir}/dbus-1/services"
 AC_SUBST(DBUS_SERVICES_DIR)
 AC_DEFINE_UNQUOTED(DBUS_SERVICES_DIR, "$DBUS_SERVICES_DIR", [Location of D-Bus services directory])
 
-if test $enable_gui != "no" || test $enable_dbus_service = "yes"; then
+if test "$enable_gui" != "no" || test "$enable_dbus_service" != "no"; then
     IT_PROG_INTLTOOL([0.37.1])
     GETTEXT_PACKAGE=syncevolution
     AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", [The gettext package name])
@@ -664,7 +699,7 @@ if test $enable_gui != "no"; then
 
     PKG_CHECK_MODULES(GUI, $gui_modules)
 
-elif test "$enable_dbus_service" = "yes"; then
+elif test "$enable_dbus_service" != "no"; then
     # syncevo-dbus-server needs localization
     :
 else
index 701b538..47f3d38 100644 (file)
@@ -24,7 +24,7 @@ if test "$enable_activesync" = "yes"; then
                 mkdir -p src/backends/activesync/activesyncd/build
                 AC_MSG_NOTICE([configuring activesyncd using the $ACTIVESYNCDSRC source code])
                 ( set -x; cd src/backends/activesync/activesyncd/build &&
-                  $ACTIVESYNCDSRC/configure --disable-eplugin --disable-camel-backend --prefix=`pwd`/../install) ||
+                  $ACTIVESYNCDSRC/configure --disable-eplugin --disable-camel-backend --disable-qtconfig --prefix=`pwd`/../install) ||
                 AC_MSG_ERROR([configuring activesyncd failed])
 
                 # hard-coded replacement for pkg-config: necessary because
index e6ff652..545a1d0 100644 (file)
@@ -380,7 +380,13 @@ void EvolutionContactSource::listAllItems(RevisionMap_t &revisions)
     EBookClientView *view;
 
     EBookQueryCXX allItemsQuery(e_book_query_any_field_contains(""), TRANSFER_REF);
-    PlainGStr sexp(e_book_query_to_string (allItemsQuery.get()));
+    PlainGStr buffer(e_book_query_to_string (allItemsQuery.get()));
+    const char *sexp = getenv("SYNCEVOLUTION_EBOOK_QUERY");
+    if (sexp) {
+        SE_LOG_INFO(NULL, "restricting item set to items matching %s", sexp);
+    } else {
+        sexp = buffer;
+    }
 
     if (!e_book_client_get_view_sync(m_addressbook, sexp, &view, NULL, gerror)) {
         throwError( "getting the view" , gerror);
index 1f8bbee..127eef1 100644 (file)
@@ -160,7 +160,7 @@ SyncSource::Database EvolutionSyncSource::createDatabase(const Database &databas
         gerror.throwError("listing keys in main section");
     }
     for (int i = 0; keys.at(i); i++) {
-        if (boost::starts_with(keys[i], "DisplayName[")) {
+        if (boost::starts_with(keys.at(i), "DisplayName[")) {
             if (!g_key_file_remove_key(keyfile, mainSection, keys.at(i), gerror)) {
                 gerror.throwError("remove key");
             }
index 940f2b1..e8ce189 100644 (file)
@@ -68,9 +68,9 @@ if test "$enable_evo" = "yes"; then
         # Only the EClient code supports the API in EDS 3.5.x.
         PKG_CHECK_MODULES(EDS_VERSION, [libedataserver-1.2 >= 3.5],
                           [AC_DEFINE(USE_EDS_CLIENT, 1, [use e_book/cal_client_* calls])
-                           # When using it, then we also need libebook-contacts-1.2
-                           # for the ESourceBackendSummary extension.
-                           PKG_CHECK_MODULES(EBOOKCONTACTS, libebook-contacts-1.2)
+                           # Was used for a while (ESourceBackendSummarySetup), but not anymore.
+                           # Don't depend on it, it wasn't in 3.6 yet.
+                           PKG_CHECK_MODULES(EBOOKCONTACTS, libebook-contacts-1.2)
                            AC_CHECK_LIB(ebook-1.2, e_book_client_new_direct,
                                         [AC_DEFINE(HAVE_E_BOOK_CLIENT_NEW_DIRECT, 1, [use e_book_client_new_direct])],
                                         [true],
diff --git a/src/dbus/server/localed-listener.cpp b/src/dbus/server/localed-listener.cpp
new file mode 100644 (file)
index 0000000..a0cb500
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2013 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 "localed-listener.h"
+#include <syncevo/BoostHelper.h>
+#include <syncevo/Logging.h>
+#include <syncevo/util.h>
+
+#include <boost/foreach.hpp>
+#include <boost/algorithm/string/join.hpp>
+#include <boost/algorithm/string/predicate.hpp>
+#include <algorithm>
+
+SE_BEGIN_CXX
+
+static const char LOCALED_PATH[] = "/org/freedesktop/locale1";
+static const char LOCALED_INTERFACE[] = "org.freedesktop.locale1";
+static const char LOCALED_DESTINATION[] = "org.freedesktop.locale1";
+static const char LOCALED_LOCALE_PROPERTY[] = "Locale";
+
+/**
+ * Must be a complete list, because we need to know which variables
+ * we have to unset if not set remotely.
+ *
+ * Localed intentionally does not support LC_ALL. As localed.c says:
+ * "We don't list LC_ALL here on purpose. People should be using LANG instead."
+ */
+static const char * const LOCALED_ENV_VARS[] = {
+    "LANG",
+    "LC_CTYPE",
+    "LC_NUMERIC",
+    "LC_TIME",
+    "LC_COLLATE",
+    "LC_MONETARY",
+    "LC_MESSAGES",
+    "LC_PAPER",
+    "LC_NAME",
+    "LC_ADDRESS",
+    "LC_TELEPHONE",
+    "LC_MEASUREMENT",
+    "LC_IDENTIFICATION"
+};
+
+static const char PROPERTIES_INTERFACE[] = "org.freedesktop.DBus.Properties";
+static const char PROPERTIES_CHANGED_SIGNAL[] = "PropertiesChanged";
+static const char PROPERTIES_GET[] = "Get";
+
+LocaledListener::LocaledListener():
+    GDBusCXX::DBusRemoteObject(!strcmp(getEnv("SYNCEVOLUTION_LOCALED", ""), "none") ?
+                               NULL : /* simulate missing localed */
+                               GDBusCXX::dbus_get_bus_connection(!strcmp(getEnv("SYNCEVOLUTION_LOCALED", ""), "session") ?
+                                                                 "SESSION" : /* use our own localed stub */
+                                                                 "SYSTEM" /* use real localed */,
+                                                                 NULL, false, NULL),
+                               LOCALED_PATH,
+                               PROPERTIES_INTERFACE,
+                               LOCALED_DESTINATION),
+    m_propertiesChanged(*this, PROPERTIES_CHANGED_SIGNAL),
+    m_propertiesGet(*this, PROPERTIES_GET)
+{
+    if (getConnection()) {
+        m_propertiesChanged.activate(boost::bind(&LocaledListener::onPropertiesChange, this, _1, _2, _3));
+    } else {
+        SE_LOG_DEBUG(NULL, "localed: not activating, no connection");
+    }
+};
+
+
+boost::shared_ptr<LocaledListener> LocaledListener::create()
+{
+    static boost::weak_ptr<LocaledListener> singleton;
+    boost::shared_ptr<LocaledListener> self = singleton.lock();
+    if (!self) {
+        self.reset(new LocaledListener());
+        self->m_self = self;
+        singleton = self;
+    }
+    return self;
+};
+
+void LocaledListener::onPropertiesChange(const std::string &interface,
+                                         const Properties &properties,
+                                         const Invalidated &invalidated)
+{
+    if (interface == LOCALED_INTERFACE) {
+        boost::function<void (const LocaleEnv &env)> result(boost::bind(&LocaledListener::emitLocaleEnv, m_self, _1));
+        BOOST_FOREACH (const Properties::value_type &entry, properties) {
+            if (entry.first == LOCALED_LOCALE_PROPERTY) {
+                const LocaleEnv *locale = boost::get<LocaleEnv>(&entry.second);
+                if (locale) {
+                    SE_LOG_DEBUG(NULL, "localed: got new Locale");
+                    processLocaleProperty(*locale, "", false, result);
+                } else {
+                    SE_LOG_DEBUG(NULL, "localed: got new Locale of invalid type?! Ignore.");
+                }
+                return;
+            }
+        }
+        if (std::find(invalidated.begin(),
+                      invalidated.end(),
+                      LOCALED_LOCALE_PROPERTY) != invalidated.end()) {
+            SE_LOG_DEBUG(NULL, "localed: Locale changed, need to get new value");
+            m_propertiesGet.start(std::string(LOCALED_INTERFACE),
+                                  std::string(LOCALED_LOCALE_PROPERTY),
+                                  boost::bind(&LocaledListener::processLocaleProperty, m_self,
+                                              _1, _2, false,
+                                              result));
+        }
+        SE_LOG_DEBUG(NULL, "localed: ignoring irrelevant property change");
+    }
+}
+
+void LocaledListener::processLocaleProperty(const LocaleVariant &variant,
+                                            const std::string &error,
+                                            bool mustCall,
+                                            const ProcessLocalePropCB_t &result)
+{
+    SE_LOG_DEBUG(NULL, "localed: got Locale property: %s", error.empty() ? "<<successfully>>" : error.c_str());
+    const LocaleEnv *locale =
+        error.empty() ?
+        boost::get<LocaleEnv>(&variant) :
+        NULL;
+    LocaleEnv current;
+    if (!locale && mustCall) {
+        SE_LOG_DEBUG(NULL, "localed: using current environment as fallback");
+        BOOST_FOREACH (const char *name, LOCALED_ENV_VARS) {
+            const char *value = getenv(name);
+            if (value) {
+                current.push_back(StringPrintf("%s=%s", name, value));
+            }
+        }
+        locale = &current;
+    }
+    if (locale) {
+        result(*locale);
+    }
+}
+
+void LocaledListener::emitLocaleEnv(const LocaleEnv &env)
+{
+    SE_LOG_DEBUG(NULL, "localed: got environment: %s",
+                 boost::join(env, " ").c_str());
+    m_localeValues(env);
+}
+
+void LocaledListener::check(const boost::function<void (const LocaleEnv &env)> &result)
+{
+    if (getConnection()) {
+        SE_LOG_DEBUG(NULL, "localed: get current Locale property");
+        m_propertiesGet.start(std::string(LOCALED_INTERFACE),
+                              std::string(LOCALED_LOCALE_PROPERTY),
+                              boost::bind(&LocaledListener::processLocaleProperty, m_self, _1, _2, true, result));
+    } else {
+        processLocaleProperty(LocaleVariant(), "no D-Bus connection", true, result);
+    }
+}
+
+void LocaledListener::setLocale(const LocaleEnv &locale)
+{
+    bool modified = false;
+    BOOST_FOREACH (const char *name, LOCALED_ENV_VARS) {
+        const char *value = getenv(name);
+        std::string assignment = StringPrintf("%s=", name);
+        LocaleEnv::const_iterator instance = std::find_if(locale.begin(), locale.end(),
+                                                          boost::bind(boost::starts_with<std::string, std::string>, _1, name));
+        const char *newvalue = instance != locale.end() ? instance->c_str() + assignment.size() : NULL;
+        if ((value && newvalue && strcmp(value, newvalue)) ||
+            (!value && newvalue)) {
+            modified = true;
+            setenv(name, newvalue, true);
+            SE_LOG_DEBUG(NULL, "localed: %s = %s -> %s", name, value ? value : "<none>", newvalue);
+        } else if (value && !newvalue) {
+            modified = true;
+            unsetenv(name);
+            SE_LOG_DEBUG(NULL, "localed: %s = %s -> <none>", name, value);
+        }
+    }
+    SE_LOG_DEBUG(NULL, "localed: environment %s", modified ? "changed" : "unchanged");
+    if (modified) {
+        m_localeChanged();
+    }
+}
+
+SE_END_CXX
diff --git a/src/dbus/server/localed-listener.h b/src/dbus/server/localed-listener.h
new file mode 100644 (file)
index 0000000..8e54907
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2013 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_LOCALED_LISTENER
+#define INCL_LOCALED_LISTENER
+
+#include <gdbus-cxx-bridge.h>
+#include <boost/signals2.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+#include <syncevo/declarations.h>
+SE_BEGIN_CXX
+
+/**
+ * The D-Bus binding for http://www.freedesktop.org/wiki/Software/systemd/localed/
+ */
+class LocaledListener : public GDBusCXX::DBusRemoteObject
+{
+ public:
+    /**
+     * Singleton - at most one instance of LocaledListener will exist.
+     * It lives as long as one of the create() callers keeps the reference.
+     */
+    static boost::shared_ptr<LocaledListener> create();
+
+    /**
+     * array of var=value, for example LANG, LC_NUMERIC, etc.
+     */
+    typedef std::vector<std::string> LocaleEnv;
+
+    /**
+     * Emitted for each new set of env variables from localed.
+     * May or may not be different from what we have already.
+     */
+    boost::signals2::signal<void (const LocaleEnv &env)> m_localeValues;
+
+    /**
+     * The result callback is guaranteed to be invoked once,
+     * either with the current settings from localed or, if
+     * retrieving those fails, with the current environment.
+     */
+    void check(const boost::function<void (const LocaleEnv &env)> &result);
+
+    /**
+     * Updates current environment to match the one in the parameter.
+     * Emits m_localeChanged if and only if something really changed.
+     *
+     * Not called by default. To ensure that the current environment
+     * matches localed, do:
+     * - use current settings
+     * - m_localeValues -> setLocale
+     * - check -> setLocale
+     *
+     * Alternatively, one could wait until check() completes and only
+     * then use the current settings.
+     */
+    void setLocale(const LocaleEnv &locale);
+
+    typedef boost::signals2::signal<void ()> LocaleChangedSignal;
+    /**
+     * Emitted by setLocale() only if something really changed in the
+     * local environment.
+     */
+    LocaleChangedSignal m_localeChanged;
+
+ private:
+    boost::weak_ptr<LocaledListener> m_self;
+    typedef boost::variant<LocaleEnv> LocaleVariant;
+    typedef std::map<std::string, LocaleVariant> Properties;
+    typedef std::vector<std::string> Invalidated;
+    GDBusCXX::SignalWatch3<std::string, Properties, Invalidated> m_propertiesChanged;
+    GDBusCXX::DBusClientCall1<LocaleVariant> m_propertiesGet;
+
+    LocaledListener();
+    void onPropertiesChange(const std::string &interface,
+                            const Properties &properties,
+                            const Invalidated &invalidated);
+    typedef boost::function<void (const LocaleEnv &env)> ProcessLocalePropCB_t;
+    void processLocaleProperty(const LocaleVariant &locale,
+                               const std::string &error,
+                               bool mustCall,
+                               const ProcessLocalePropCB_t &result);
+    void emitLocaleEnv(const LocaleEnv &env);
+};
+
+SE_END_CXX
+
+#endif // INCL_LOCALED_LISTENER
index a8d8c6d..63c757b 100644 (file)
 #include <syncevo/SuspendFlags.h>
 #include <syncevo/LogRedirect.h>
 #include <syncevo/LogSyslog.h>
+#include <syncevo/LogDLT.h>
 #include <syncevo/GLibSupport.h>
 
+#ifdef USE_DLT
+# include <dlt.h>
+#endif
+
 using namespace SyncEvo;
 using namespace GDBusCXX;
 
@@ -100,6 +105,9 @@ int main(int argc, char **argv, char **envp)
         int logLevelDBus = 2;
         gboolean stdoutEnabled = false;
         gboolean syslogEnabled = true;
+#ifdef USE_DLT
+        gboolean dltEnabled = false;
+#endif
 #ifdef ENABLE_DBUS_PIM
         gboolean startPIM = false;
 #endif
@@ -115,6 +123,9 @@ int main(int argc, char **argv, char **envp)
               "Enable printing to stdout (result of operations) and stderr (errors/info/debug).",
               NULL },
             { "no-syslog", 's', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &syslogEnabled, "Disable printing to syslog.", NULL },
+#ifdef USE_DLT
+            { "dlt", 0, 0, G_OPTION_ARG_NONE, &dltEnabled, "Enable logging via GENIVI Diagnostic Log and Trace.", NULL },
+#endif
 #ifdef ENABLE_DBUS_PIM
             { "start-pim", 'p', 0, G_OPTION_ARG_NONE, &startPIM,
               "Activate the PIM Manager (= unified address book) immediately.",
@@ -154,6 +165,20 @@ int main(int argc, char **argv, char **envp)
         // Redirect output and optionally log to syslog.
         PushLogger<LogRedirect> redirect(new LogRedirect(LogRedirect::STDERR_AND_STDOUT));
         redirect->setLevel(stdoutEnabled ? level : Logger::NONE);
+#ifdef USE_DLT
+        PushLogger<LoggerDLT> loggerdlt;
+        if (dltEnabled) {
+            // DLT logging with default log level DLT_LOG_WARN.  This
+            // default was chosen because DLT's own default,
+            // DLT_LOG_INFO, leads to too much output given that a lot
+            // of the standard messages in SyncEvolution and
+            // libsynthesis are labelled informational.
+            setenv("SYNCEVOLUTION_USE_DLT", StringPrintf("%d", DLT_LOG_WARN).c_str(), true);
+            loggerdlt.reset(new LoggerDLT(DLT_SYNCEVO_DBUS_SERVER_ID, "SyncEvolution D-Bus server"));
+        } else {
+            unsetenv("SYNCEVOLUTION_USE_DLT");
+        }
+#endif
         PushLogger<LoggerSyslog> syslogger;
         if (syslogEnabled && level > Logger::NONE) {
             syslogger.reset(new LoggerSyslog(execName));
index db8a0b4..edc6376 100644 (file)
@@ -1,3 +1,3 @@
 [D-BUS Service]
 Name=org.syncevolution
-Exec=@libexecdir@/syncevo-dbus-server
+Exec=@libexecdir@/syncevo-dbus-server @SYNCEVO_DBUS_SERVER_ARGS@
index 9620594..a83fe52 100644 (file)
@@ -187,12 +187,26 @@ Supported searches:
 
     Except for 'phones/value', all values are treated as text values.
     For text values, the default search without explicit flags is
-    case-insensitive and accent-sensitive. Spaces between words
-    matter. This behavior can be modified by giving additional,
+    very tolerant, meaning that it ignores quite a few differences
+    between search term and value. The default search:
+    - transliterates any foreign script in search term and values
+      to Latin before comparison, thus finding 江 when searching
+      for Jiang and vice-versa
+    - is case-insensitive
+    - is accent-insensitive
+
+    Case and accent differences get removed after the optional
+    transliteration. Spaces between words always matter.
+
+    This behavior can be modified by giving additional,
     optional flags after the search value:
     'case-insensitive' - force case-insensitive search (available for the sake
     of consistency and just in case, should the default ever change)
     'case-sensitive' - force case-sensitive search
+    'accent-insensitive', 'accent-sensitive' - same for accents
+    'transliteration' - force transliteration, i.e. explicitly choose the
+    current default
+    'no-transliteration' - disable transliteration
 
     For telephone numbers, only digits are compared. Latin alphabetic
     characters are treated as aliases for digits as they typically
index 6fd4dba..9af83e7 100644 (file)
@@ -90,18 +90,20 @@ boost::shared_ptr<IndividualCompare> IndividualCompare::defaultCompare()
     return compare;
 }
 
-void IndividualData::init(const IndividualCompare *compare,
+bool IndividualData::init(const IndividualCompare *compare,
                           const LocaleFactory *locale,
                           FolksIndividual *individual)
 {
+    bool precomputedModified = false;
     m_individual = FolksIndividualCXX(individual, ADD_REF);
     if (compare) {
         m_criteria.clear();
         compare->createCriteria(individual, m_criteria);
     }
     if (locale) {
-        locale->precompute(individual, m_precomputed);
+        precomputedModified = locale->precompute(individual, m_precomputed);
     }
+    return precomputedModified;
 }
 
 bool IndividualCompare::compare(const Criteria_t &a, const Criteria_t &b) const
@@ -275,6 +277,16 @@ void IndividualAggregator::setCompare(const boost::shared_ptr<IndividualCompare>
     }
 }
 
+void IndividualAggregator::setLocale(const boost::shared_ptr<LocaleFactory> &locale)
+{
+    m_locale = locale;
+
+    if (m_view) {
+        m_view->setLocale(m_locale);
+    }
+}
+
+
 void IndividualAggregator::start()
 {
     if (!m_view) {
index 853240b..0f6d86f 100644 (file)
@@ -116,8 +116,10 @@ struct IndividualData
      * Sets all members to match the given individual, using the
      * compare instance to compute values. Both compare and locale may
      * be NULL.
+     *
+     * Returns true if the precomputed values changed.
      */
-    void init(const IndividualCompare *compare,
+    bool init(const IndividualCompare *compare,
               const LocaleFactory *locale,
               FolksIndividual *individual);
 
@@ -315,6 +317,12 @@ class IndividualAggregator
     void setCompare(const boost::shared_ptr<IndividualCompare> &compare);
 
     /**
+     * Change current locale. Must be followed by setCompare() to update
+     * any pre-computed data.
+     */
+    void setLocale(const boost::shared_ptr<LocaleFactory> &locale);
+
+    /**
      * Starts pulling and sorting of contacts.
      * Creates m_view and starts populating it.
      * Can be called multiple times.
index b0d5d7a..bc9fbe1 100644 (file)
@@ -21,6 +21,8 @@
 
 #include <syncevo/BoostHelper.h>
 
+#include <boost/dynamic_bitset.hpp>
+
 #include <syncevo/declarations.h>
 SE_BEGIN_CXX
 
@@ -28,6 +30,7 @@ FullView::FullView(const FolksIndividualAggregatorCXX &folks,
                    const boost::shared_ptr<LocaleFactory> &locale) :
     m_folks(folks),
     m_locale(locale),
+    m_localeChanged(false), // set only after explicit setLocale()
     m_isQuiescent(false),
     // Ensure that there is a sort criteria.
     m_compare(IndividualCompare::defaultCompare())
@@ -104,6 +107,16 @@ boost::shared_ptr<FullView> FullView::create(const FolksIndividualAggregatorCXX
     return view;
 }
 
+
+void FullView::setLocale(const boost::shared_ptr<LocaleFactory> &locale)
+{
+    m_locale = locale;
+    m_localeChanged = true;
+
+    // Don't recompute all IndividualData content. That will be done
+    // as part of setCompare(), which must be called later.
+}
+
 void FullView::individualsChanged(GeeSet *added,
                                   GeeSet *removed,
                                   gchar *message,
@@ -297,8 +310,17 @@ void FullView::setCompare(const boost::shared_ptr<IndividualCompare> &compare)
     memcpy(old.get(), m_entries.c_array(), sizeof(IndividualData *) * m_entries.size());
 
     // Change sort criteria and sort.
-    BOOST_FOREACH (IndividualData &data, m_entries) {
-        data.init(m_compare.get(), NULL, data.m_individual);
+    // Optionally also re-compute locale-dependent values, if
+    // the locale changed (see setLocale()).
+    LocaleFactory *locale = m_localeChanged ? m_locale.get() : NULL;
+    m_localeChanged = false;
+    boost::dynamic_bitset<size_t> modified(locale ? m_entries.size() : 0);
+    for (size_t i = 0; i < m_entries.size(); i++ ) {
+        IndividualData &data = m_entries[i];
+        bool preComputedModified = data.init(m_compare.get(), locale, data.m_individual);
+        if (locale && preComputedModified) {
+            modified.set(i);
+        }
     }
     m_entries.sort(IndividualDataCompare(m_compare));
 
@@ -306,7 +328,8 @@ void FullView::setCompare(const boost::shared_ptr<IndividualCompare> &compare)
     for (size_t index = 0; index < m_entries.size(); index++) {
         IndividualData &previous = *old[index],
             &current = m_entries[index];
-        if (previous.m_individual != current.m_individual) {
+        if (previous.m_individual != current.m_individual ||
+            (locale && modified[index])) {
             // Contact at the index changed. Don't try to find out
             // where it came from now. The effect is that temporarily
             // the same contact might be shown at two different
index 3035fa5..40531fb 100644 (file)
@@ -33,6 +33,7 @@ class FullView : public IndividualView
 {
     FolksIndividualAggregatorCXX m_folks;
     boost::shared_ptr<LocaleFactory> m_locale;
+    bool m_localeChanged;
     bool m_isQuiescent;
     boost::weak_ptr<FullView> m_self;
     Timeout m_waitForIdle;
@@ -78,6 +79,12 @@ class FullView : public IndividualView
     static boost::shared_ptr<FullView> create(const FolksIndividualAggregatorCXX &folks,
                                               const boost::shared_ptr<LocaleFactory> &locale);
 
+    /**
+     * Change locale. Updating pre-computed data must be triggered by
+     * calling setCompare() later.
+     */
+    void setLocale(const boost::shared_ptr<LocaleFactory> &locale);
+
     /** FolksIndividualAggregator "individuals-changed" slot */
     void individualsChanged(GeeSet *added,
                             GeeSet *removed,
index 4cf2951..583602b 100644 (file)
 #include <phonenumbers/phonenumberutil.h>
 #include <phonenumbers/logger.h>
 #include <boost/locale.hpp>
+#include <boost/lexical_cast.hpp>
 
 #include <unicode/unistr.h>
 #include <unicode/translit.h>
 #include <unicode/bytestream.h>
+#include <unicode/locid.h>
 
 SE_GLIB_TYPE(EBookQuery, e_book_query)
 
@@ -110,6 +112,8 @@ std::string CompareBoost::transform(const char *string) const
 
 std::string CompareBoost::transform(const std::string &string) const
 {
+    // TODO: use e_collator_generate_key
+
     if (m_trans.get()) {
         // std::string result;
         // m_trans->transliterate(icu::StringPiece(string), icu::StringByteSink<std::string>(&result));
@@ -205,32 +209,63 @@ class AnyContainsBoost : public IndividualFilter
 {
 public:
     enum Mode {
-        CASE_SENSITIVE,
-        CASE_INSENSITIVE
+        EXACT = 0,
+        CASE_INSENSITIVE = 1<<0,
+        ACCENT_INSENSITIVE = 1<<1,
+        TRANSLITERATE = 1<<2,
+        ALL =
+        CASE_INSENSITIVE|
+        ACCENT_INSENSITIVE|
+        TRANSLITERATE|
+        0
     };
 
     AnyContainsBoost(const std::locale &locale,
                      const std::string &searchValue,
-                     Mode mode) :
+                     int mode) :
         m_locale(locale),
+        // For performance reasons we use ICU directly and thus need
+        // an ICU::Locale.
+        //         m_ICULocale(std::use_facet<boost::locale::info>(m_locale).language().c_str(),
+        //            std::use_facet<boost::locale::info>(m_locale).country().c_str(),
+        //            std::use_facet<boost::locale::info>(m_locale).variant().c_str()),
         // m_collator(std::use_facet<boost::locale::collator>(locale)),
         m_searchValue(searchValue),
         m_mode(mode)
     {
+        if (mode & TRANSLITERATE) {
+            UErrorCode status = U_ZERO_ERROR;
+            m_transliterator.reset(Transliterator::createInstance ("Any-Latin", UTRANS_FORWARD, status));
+            if (!m_transliterator ||
+                U_FAILURE(status)) {
+                SE_LOG_WARNING(NULL, "creating ICU Any-Latin Transliterator failed, error code %s; falling back to not transliterating", u_errorName(status));
+                m_transliterator.reset();
+                mode ^= TRANSLITERATE;
+                m_mode = mode;
+            }
+        }
+
         switch (mode) {
-        case CASE_SENSITIVE:
-            // Search directly, no preprocessing.
+        case EXACT:
             break;
-        case CASE_INSENSITIVE:
-            // Locale-aware conversion to fold case (= case
-            // independent) representation before search.
-            m_searchValueTransformed = boost::locale::fold_case(m_searchValue, m_locale);
+        default:
+            m_searchValueTransformed = transform(m_searchValue);
             break;
         }
         m_searchValueTel = normalizePhoneText(m_searchValue.c_str());
     }
 
     /**
+     * Turn filter arguments into bit field.
+     */
+    static int getFilterMode(const std::vector<LocaleFactory::Filter_t> &terms,
+                             size_t start);
+
+    /** simplify according to mode */
+    std::string transform(const char *in) const;
+    std::string transform(const std::string &in) const { return transform(in.c_str()); }
+
+    /**
      * The search text is not necessarily a full phone number,
      * therefore we cannot parse it with libphonenumber. Instead
      * do a sub-string search after telephone specific normalization,
@@ -271,12 +306,12 @@ public:
             return false;
         }
         switch (m_mode) {
-        case CASE_SENSITIVE:
+        case EXACT:
             return boost::contains(text, m_searchValue);
             break;
-        case CASE_INSENSITIVE: {
-            std::string lower(boost::locale::fold_case(text, m_locale));
-            return boost::contains(lower, m_searchValueTransformed);
+        default: {
+            std::string transformed = transform(text);
+            return boost::contains(transformed, m_searchValueTransformed);
             break;
         }
         }
@@ -296,12 +331,12 @@ public:
             return false;
         }
         switch (m_mode) {
-        case CASE_SENSITIVE:
+        case EXACT:
             return boost::equals(text, m_searchValue);
             break;
-        case CASE_INSENSITIVE: {
-            std::string lower(boost::locale::fold_case(text, m_locale));
-            return boost::equals(lower, m_searchValueTransformed);
+        default: {
+            std::string transformed = transform(text);
+            return boost::equals(transformed, m_searchValueTransformed);
             break;
         }
         }
@@ -321,12 +356,12 @@ public:
             return false;
         }
         switch (m_mode) {
-        case CASE_SENSITIVE:
+        case EXACT:
             return boost::starts_with(text, m_searchValue);
             break;
-        case CASE_INSENSITIVE: {
-            std::string lower(boost::locale::fold_case(text, m_locale));
-            return boost::starts_with(lower, m_searchValueTransformed);
+        default:  {
+            std::string transformed = transform(text);
+            return boost::starts_with(transformed, m_searchValueTransformed);
             break;
         }
         }
@@ -346,12 +381,12 @@ public:
             return false;
         }
         switch (m_mode) {
-        case CASE_SENSITIVE:
+        case EXACT:
             return boost::ends_with(text, m_searchValue);
             break;
-        case CASE_INSENSITIVE: {
-            std::string lower(boost::locale::fold_case(text, m_locale));
-            return boost::ends_with(lower, m_searchValueTransformed);
+        default: {
+            std::string transformed = transform(text);
+            return boost::ends_with(transformed, m_searchValueTransformed);
             break;
         }
         }
@@ -416,13 +451,62 @@ public:
 
 private:
     std::locale m_locale;
+    // icu::Locale m_ICULocale;
+    boost::shared_ptr<icu::Transliterator> m_transliterator;
     std::string m_searchValue;
     std::string m_searchValueTransformed;
     std::string m_searchValueTel;
-    Mode m_mode;
+    int m_mode;
     // const bool (*m_contains)(const std::string &, const std::string &, const std::locale &);
 };
 
+std::string AnyContainsBoost::transform(const char *in) const
+{
+    icu::UnicodeString unicode = icu::UnicodeString::fromUTF8(in);
+    if (m_mode & TRANSLITERATE) {
+        m_transliterator->transliterate(unicode);
+    }
+    if (m_mode & CASE_INSENSITIVE) {
+        unicode.foldCase();
+    }
+    std::string utf8;
+    unicode.toUTF8String(utf8);
+    if (m_mode & ACCENT_INSENSITIVE) {
+        // Haven't found an easy way to do this with ICU.
+        // Use e_util_utf8_remove_accents(), which also ensures
+        // consistency with EDS.
+        PlainGStr res = e_util_utf8_remove_accents(utf8.c_str());
+        return std::string(res);
+    } else {
+        return utf8;
+    }
+}
+
+int AnyContainsBoost::getFilterMode(const std::vector<LocaleFactory::Filter_t> &terms,
+                                    size_t start)
+{
+    int mode = ALL;
+    for (size_t i = start; i < terms.size(); i++) {
+        const std::string flag = LocaleFactory::getFilterString(terms[i], "any-contains flag");
+        if (flag == "case-sensitive") {
+            mode &= ~CASE_INSENSITIVE;
+        } else if (flag == "case-insensitive") {
+            mode |= CASE_INSENSITIVE;
+        } else if (flag == "accent-sensitive") {
+            mode &= ~ACCENT_INSENSITIVE;
+        } else if (flag == "accent-insensitive") {
+            mode |= ACCENT_INSENSITIVE;
+        } else if (flag == "no-transliteration") {
+            mode &= ~TRANSLITERATE;
+        } else if (flag == "transliteration") {
+            mode |= TRANSLITERATE;
+        } else {
+            SE_THROW("unsupported filter flag: " + flag);
+        }
+    }
+    return mode;
+}
+
 class FilterFullName : public AnyContainsBoost
 {
     bool (AnyContainsBoost::*m_operation)(const char *text) const;
@@ -430,7 +514,7 @@ class FilterFullName : public AnyContainsBoost
 public:
     FilterFullName(const std::locale &locale,
                    const std::string &searchValue,
-                   Mode mode,
+                   int mode,
                    bool (AnyContainsBoost::*operation)(const char *text) const) :
         AnyContainsBoost(locale, searchValue, mode),
         m_operation(operation)
@@ -453,7 +537,7 @@ class FilterNickname : public AnyContainsBoost
 public:
     FilterNickname(const std::locale &locale,
                    const std::string &searchValue,
-                   Mode mode,
+                   int mode,
                    bool (AnyContainsBoost::*operation)(const char *text) const) :
         AnyContainsBoost(locale, searchValue, mode),
         m_operation(operation)
@@ -476,7 +560,7 @@ class FilterFamilyName : public AnyContainsBoost
 public:
     FilterFamilyName(const std::locale &locale,
                      const std::string &searchValue,
-                     Mode mode,
+                     int mode,
                      bool (AnyContainsBoost::*operation)(const char *text) const) :
         AnyContainsBoost(locale, searchValue, mode),
         m_operation(operation)
@@ -504,7 +588,7 @@ class FilterGivenName : public AnyContainsBoost
 public:
     FilterGivenName(const std::locale &locale,
                     const std::string &searchValue,
-                    Mode mode,
+                    int mode,
                     bool (AnyContainsBoost::*operation)(const char *text) const) :
         AnyContainsBoost(locale, searchValue, mode),
         m_operation(operation)
@@ -532,7 +616,7 @@ class FilterAdditionalName : public AnyContainsBoost
 public:
     FilterAdditionalName(const std::locale &locale,
                          const std::string &searchValue,
-                         Mode mode,
+                         int mode,
                          bool (AnyContainsBoost::*operation)(const char *text) const) :
         AnyContainsBoost(locale, searchValue, mode),
         m_operation(operation)
@@ -560,7 +644,7 @@ class FilterEmails : public AnyContainsBoost
 public:
     FilterEmails(const std::locale &locale,
                  const std::string &searchValue,
-                 Mode mode,
+                 int mode,
                  bool (AnyContainsBoost::*operation)(const char *text) const) :
         AnyContainsBoost(locale, searchValue, mode),
         m_operation(operation)
@@ -591,7 +675,7 @@ public:
     FilterTel(const std::locale &locale,
               const std::string &searchValue,
               bool (AnyContainsBoost::*operation)(const char *text) const) :
-        AnyContainsBoost(locale, searchValue, CASE_SENSITIVE /* doesn't matter */),
+        AnyContainsBoost(locale, searchValue, 0 /* doesn't matter */),
         m_operation(operation)
     {
     }
@@ -620,7 +704,7 @@ protected:
 public:
     FilterAddr(const std::locale &locale,
                const std::string &searchValue,
-               Mode mode,
+               int mode,
                bool (AnyContainsBoost::*operation)(const char *text) const) :
         AnyContainsBoost(locale, searchValue, mode),
         m_operation(operation)
@@ -650,7 +734,7 @@ class FilterAddrPOBox : public FilterAddr
 public:
     FilterAddrPOBox(const std::locale &locale,
                     const std::string &searchValue,
-                    Mode mode,
+                    int mode,
                     bool (AnyContainsBoost::*operation)(const char *text) const) :
         FilterAddr(locale, searchValue, mode, operation)
     {
@@ -668,7 +752,7 @@ class FilterAddrExtension : public FilterAddr
 public:
     FilterAddrExtension(const std::locale &locale,
                         const std::string &searchValue,
-                        Mode mode,
+                        int mode,
                         bool (AnyContainsBoost::*operation)(const char *text) const) :
         FilterAddr(locale, searchValue, mode, operation)
     {
@@ -686,7 +770,7 @@ class FilterAddrStreet : public FilterAddr
 public:
     FilterAddrStreet(const std::locale &locale,
                      const std::string &searchValue,
-                     Mode mode,
+                     int mode,
                      bool (AnyContainsBoost::*operation)(const char *text) const) :
         FilterAddr(locale, searchValue, mode, operation)
     {
@@ -704,7 +788,7 @@ class FilterAddrLocality : public FilterAddr
 public:
     FilterAddrLocality(const std::locale &locale,
                        const std::string &searchValue,
-                       Mode mode,
+                       int mode,
                        bool (AnyContainsBoost::*operation)(const char *text) const) :
         FilterAddr(locale, searchValue, mode, operation)
     {
@@ -722,7 +806,7 @@ class FilterAddrRegion : public FilterAddr
 public:
     FilterAddrRegion(const std::locale &locale,
                      const std::string &searchValue,
-                     Mode mode,
+                     int mode,
                      bool (AnyContainsBoost::*operation)(const char *text) const) :
         FilterAddr(locale, searchValue, mode, operation)
     {
@@ -740,7 +824,7 @@ class FilterAddrPostalCode : public FilterAddr
 public:
     FilterAddrPostalCode(const std::locale &locale,
                          const std::string &searchValue,
-                         Mode mode,
+                         int mode,
                          bool (AnyContainsBoost::*operation)(const char *text) const) :
         FilterAddr(locale, searchValue, mode, operation)
     {
@@ -758,7 +842,7 @@ class FilterAddrCountry : public FilterAddr
 public:
     FilterAddrCountry(const std::locale &locale,
                       const std::string &searchValue,
-                      Mode mode,
+                      int mode,
                       bool (AnyContainsBoost::*operation)(const char *text) const) :
         FilterAddr(locale, searchValue, mode, operation)
     {
@@ -775,10 +859,16 @@ public:
 
 
 /**
- * Search value must be a valid caller ID. The telephone numbers
- * in the contacts may or may not be valid; only valid ones
- * will match. The user is expected to clean up that data to get
- * exact matches for the others.
+ * Search value must be a valid caller ID (with or without a country
+ * code). The telephone numbers in the contacts may or may not be
+ * valid; only valid ones will match. The user is expected to clean up
+ * that data to get exact matches for the others.
+ *
+ * The matching uses the same semantic as EQUALS_NATIONAL_PHONE_NUMBER:
+ * - If both numbers have an explicit country code, that code must be
+ *   the same for a match.
+ * - If one or both numbers have no country code, matching the national
+ *   part is enough for a match.
  */
 class PhoneStartsWith : public IndividualFilter
 {
@@ -811,19 +901,19 @@ public:
             break;
         }
 
-        // Search based on full internal format, without formatting.
-        // For example: +41446681800
-        //
-        // A prefix match is good enough. That way a caller ID
-        // with suppressed extension still matches a contact with
-        // extension.
-        m_phoneNumberUtil.Format(number, i18n::phonenumbers::PhoneNumberUtil::E164, &m_tel);
+        m_number.m_countryCode = number.country_code();
+        m_number.m_nationalNumber = number.national_number();
     }
 
     virtual bool matches(const IndividualData &data) const
     {
-        BOOST_FOREACH(const std::string &tel, data.m_precomputed.m_phoneNumbers) {
-            if (boost::starts_with(tel, m_tel)) {
+        BOOST_FOREACH(const SimpleE164 &number, data.m_precomputed.m_phoneNumbers) {
+            // National part must always match, country code only if
+            // set explicitly in both (NSN_MATCH in libphonenumber,
+            // EQUALS_NATIONAL_PHONE_NUMBER in EDS).
+            if (number.m_nationalNumber == m_number.m_nationalNumber &&
+                (!number.m_countryCode || !m_number.m_countryCode ||
+                 number.m_countryCode == m_number.m_countryCode)) {
                 return true;
             }
         }
@@ -832,12 +922,13 @@ public:
 
     virtual std::string getEBookFilter() const
     {
-        size_t len = std::min((size_t)4, m_tel.size());
+        std::string tel = m_number.toString();
+        size_t len = std::min((size_t)4, tel.size());
         EBookQueryCXX query(m_simpleEDSSearch ?
                             // A suffix match with a limited number of digits is most
                             // likely to find the right contacts.
                             e_book_query_field_test(E_CONTACT_TEL, E_BOOK_QUERY_ENDS_WITH,
-                                                    m_tel.substr(m_tel.size() - len, len).c_str()) :
+                                                    tel.substr(tel.size() - len, len).c_str()) :
                             // We use EQUALS_NATIONAL_PHONE_NUMBER
                             // instead of EQUALS_PHONE_NUMBER here,
                             // because it will also match contacts
@@ -851,19 +942,19 @@ public:
                             // check that and not return a false match
                             // if the country code is different.
                             //
-                            // At the moment, we pass the E164
-                            // formatted search term with a country
-                            // code here. The country code is the
-                            // current default one.  We could think
-                            // about passing the original search term
-                            // instead, to allow matches where contact
-                            // and search term have no country code,
-                            // but it is uncertain whether EDS
-                            // currently works that way. It looks like
-                            // it always adds the default country code
-                            // to the search term.
+                            // We try to pass the E164 string here. If
+                            // the search term had no country code,
+                            // that's a bit difficult because we can't
+                            // just add the default country code.
+                            // That would break the
+                            // NATIONAL_PHONE_NUMBER semantic because
+                            // EDS wouldn't know that the search term
+                            // had no country code. We resort to the
+                            // format of SimpleE164.toString(), which
+                            // is passing the national number
+                            // formatted as string.
                             e_book_query_field_test(E_CONTACT_TEL, E_BOOK_QUERY_EQUALS_NATIONAL_PHONE_NUMBER,
-                                                    m_tel.c_str()),
+                                                    tel.c_str()),
                             TRANSFER_REF);
         PlainGStr filter(e_book_query_to_string(query.get()));
         return filter.get();
@@ -873,7 +964,7 @@ private:
     const i18n::phonenumbers::PhoneNumberUtil &m_phoneNumberUtil;
     bool m_simpleEDSSearch;
     std::string m_country;
-    std::string m_tel;
+    SimpleE164 m_number;
 };
 
 class PhoneNumberLogger : public i18n::phonenumbers::Logger
@@ -911,23 +1002,6 @@ public:
     }
 };
 
-static AnyContainsBoost::Mode getFilterMode(const std::vector<LocaleFactory::Filter_t> &terms,
-                                            size_t start)
-{
-    AnyContainsBoost::Mode mode = AnyContainsBoost::CASE_INSENSITIVE;
-    for (size_t i = start; i < terms.size(); i++) {
-        const std::string flag = LocaleFactory::getFilterString(terms[i], "any-contains flag");
-        if (flag == "case-sensitive") {
-            mode = AnyContainsBoost::CASE_SENSITIVE;
-        } else if (flag == "case-insensitive") {
-            mode = AnyContainsBoost::CASE_INSENSITIVE;
-        } else {
-            SE_THROW("unsupported filter flag: " + flag);
-        }
-    }
-    return mode;
-}
-
 class LocaleFactoryBoost : public LocaleFactory
 {
     const i18n::phonenumbers::PhoneNumberUtil &m_phoneNumberUtil;
@@ -940,7 +1014,7 @@ class LocaleFactoryBoost : public LocaleFactory
 public:
     LocaleFactoryBoost() :
         m_phoneNumberUtil(*i18n::phonenumbers::PhoneNumberUtil::GetInstance()),
-        m_edsSupportsPhoneNumbers(e_phone_number_is_supported()),
+        m_edsSupportsPhoneNumbers(e_phone_number_is_supported() && !getenv("SYNCEVOLUTION_PIM_EDS_NO_E164")),
         m_locale(genLocale()),
         m_country(std::use_facet<boost::locale::info>(m_locale).country()),
         m_defaultCountryCode(StringPrintf("+%d", m_phoneNumberUtil.GetCountryCodeForRegion(m_country)))
@@ -1048,7 +1122,7 @@ public:
                                                 func == &AnyContainsBoost::endsWithSearchText ? &AnyContainsBoost::endsWithSearchTel :
                                                 func));
                     } else {
-                        AnyContainsBoost::Mode mode = getFilterMode(terms, 3);
+                        int mode = AnyContainsBoost::getFilterMode(terms, 3);
                         if (field == "full-name") {
                             res.reset(new FilterFullName(m_locale, value, mode, func));
                         } else if (field == "nickname") {
@@ -1084,7 +1158,7 @@ public:
                         SE_THROW("missing search value");
                     }
                     const std::string &value = getFilterString(terms[1], "search string");
-                    AnyContainsBoost::Mode mode = getFilterMode(terms, 2);
+                    int mode = AnyContainsBoost::getFilterMode(terms, 2);
                     res.reset(new AnyContainsBoost(m_locale, value, mode));
                 } else if (operation == "phone") {
                     if (terms.size() != 2) {
@@ -1104,9 +1178,10 @@ public:
         return res ? res : LocaleFactory::createFilter(filter, level);
     }
 
-    virtual void precompute(FolksIndividual *individual, Precomputed &precomputed) const
+    virtual bool precompute(FolksIndividual *individual, Precomputed &precomputed) const
     {
-        precomputed.m_phoneNumbers.clear();
+        LocaleFactory::Precomputed old;
+        std::swap(old, precomputed);
 
         FolksPhoneDetails *phoneDetails = FOLKS_PHONE_DETAILS(individual);
         GeeSet *phones = folks_phone_details_get_phone_numbers(phoneDetails);
@@ -1116,7 +1191,8 @@ public:
                 reinterpret_cast<const gchar *>(folks_abstract_field_details_get_value(phone));
             if (value) {
                 if (m_edsSupportsPhoneNumbers) {
-                    // TODO: check X-EVOLUTION-E164 (made lowercase by folks!).
+                    // Check X-EVOLUTION-E164 (made lowercase by folks!).
+                    //
                     // It has the format <local number>,<country code>,
                     // where <country code> happens to be in quotation marks.
                     // This ends up being split into individual values which
@@ -1133,21 +1209,32 @@ public:
                         components.reserve(2);
                         BOOST_FOREACH (const gchar *component, GeeStringCollection(coll)) {
                             // Empty component represents an unset
-                            // country code. Replace with the current
-                            // country code to form the full number.
-                            // Note that it is not certain whether we
-                            // get to see the empty component. At the
-                            // moment (EDS 3.7, folks 0.9.1), someone
-                            // swallows it.
-                            components.push_back(component[0] ? component : m_defaultCountryCode);
+                            // country code. Note that it is not
+                            // certain whether we get to see the empty
+                            // component. At the moment (EDS 3.7,
+                            // folks 0.9.1), someone swallows it.
+                            components.push_back(component);
                         }
-                        // Only one component? We must still miss the country code.
-                        if (components.size() == 1) {
-                            components.push_back(m_defaultCountryCode);
+                        if (!components.empty()) {
+                            // Only one component? We must still miss the country code.
+                            if (components.size() == 1) {
+                                components.push_back("");
+                            }
+                            std::sort(components.begin(), components.end());
+                            try {
+                                SimpleE164 number;
+                                number.m_countryCode = components[0].empty() ?
+                                    0 :
+                                    boost::lexical_cast<SimpleE164::CountryCode_t>(components[0]);
+                                number.m_nationalNumber = components[1].empty() ?
+                                    0 :
+                                    boost::lexical_cast<SimpleE164::NationalNumber_t>(components[1]);
+                                precomputed.m_phoneNumbers.push_back(number);
+                            } catch (const boost::bad_lexical_cast &ex) {
+                                SE_LOG_WARNING(NULL, "ignoring malformed X-EVOLUTION-E164 (sorted): %s",
+                                               boost::join(components, ", ").c_str());
+                            }
                         }
-                        std::sort(components.begin(), components.end());
-                        std::string normal = boost::join(components, "");
-                        precomputed.m_phoneNumbers.push_back(normal);
                     }
                     // Either EDS had a normalized value or there is none because
                     // the value is not a phone number. No need to try parsing again.
@@ -1158,12 +1245,16 @@ public:
                 i18n::phonenumbers::PhoneNumberUtil::ErrorType error =
                     m_phoneNumberUtil.Parse(value, m_country, &number);
                 if (error == i18n::phonenumbers::PhoneNumberUtil::NO_PARSING_ERROR) {
-                    std::string tel;
-                    m_phoneNumberUtil.Format(number, i18n::phonenumbers::PhoneNumberUtil::E164, &tel);
-                    precomputed.m_phoneNumbers.push_back(tel);
+                    SimpleE164 e164;
+                    e164.m_countryCode = number.country_code();
+                    e164.m_nationalNumber = number.national_number();
+                    precomputed.m_phoneNumbers.push_back(e164);
                 }
             }
         }
+
+        // Now check if any phone number changed.
+        return old != precomputed;
     }
 };
 
index f30cf41..3b5b960 100644 (file)
 
 SE_BEGIN_CXX
 
+std::string SimpleE164::toString() const
+{
+    std::ostringstream out;
+    if (m_countryCode) {
+        out << "+" << m_countryCode;
+    }
+    if (m_nationalNumber) {
+        out << m_nationalNumber;
+    }
+    return out.str();
+}
+
+bool LocaleFactory::Precomputed::operator == (const LocaleFactory::Precomputed &other) const
+{
+    if (other.m_phoneNumbers.size() != m_phoneNumbers.size()) {
+        return false;
+    }
+    PhoneNumbers::const_iterator ita = other.m_phoneNumbers.begin();
+    PhoneNumbers::const_iterator itb = m_phoneNumbers.begin();
+    while (ita != other.m_phoneNumbers.end()) {
+        if (*ita != *itb) {
+            return false;
+        }
+        ++ita;
+        ++itb;
+    }
+    return true;
+}
+
 class Filter2StringVisitor : public boost::static_visitor<void>
 {
     std::ostringstream m_out;
index 48aee19..9a043ac 100644 (file)
@@ -39,6 +39,46 @@ SE_BEGIN_CXX
 class IndividualCompare;
 class IndividualFilter;
 
+/**
+ * Normalized phone numbers (E164). A subset of the full
+ * i18n::phonenumbers::PhoneNumber data.
+ */
+class SimpleE164
+{
+ public:
+    SimpleE164() : m_countryCode(0), m_nationalNumber(0) {}
+
+    typedef int32_t CountryCode_t;
+    typedef uint64_t NationalNumber_t;
+
+    /**
+     * Country code (for example, 49 for the +49 prefix of Germany),
+     * 0 if unknown/unset.
+     */
+    CountryCode_t m_countryCode;
+
+    /**
+     * Phone number after the country code as it would appear in E.164
+     * after the +<country> prefix, again given as binary value,
+     * 0 if unknown/unset.
+     */
+    NationalNumber_t m_nationalNumber;
+
+    /**
+     * +<country><national> if country code and national number are set,
+     * +<country> if only country code is set,
+     * <national> if only national number is set,
+     * empty string if both are unset.
+     */
+    std::string toString() const;
+
+    bool operator == (const SimpleE164 &other) const 
+    {
+        return m_countryCode == other.m_countryCode &&
+        m_nationalNumber == other.m_nationalNumber;
+    }
+    bool operator != (const SimpleE164 &other) const { return !(*this == other); }
+};
 
 /**
  * Factory for everything related to the current locale: sorting and
@@ -114,17 +154,16 @@ class LocaleFactory
      */
     struct Precomputed
     {
-        /**
-         * Normalized phone numbers (E164). Contains only + and digits.
-         * TODO (?): store in more compact format.
-         */
-        std::vector<std::string> m_phoneNumbers;
+        typedef std::vector<SimpleE164> PhoneNumbers;
+        PhoneNumbers m_phoneNumbers;
+        bool operator == (const Precomputed &other) const;
+        bool operator != (const Precomputed &other) const { return !(*this == other); }
     };
 
     /**
      * (Re)set pre-computed data for an individual.
      */
-    virtual void precompute(FolksIndividual *individual, Precomputed &precomputed) const = 0;
+    virtual bool precompute(FolksIndividual *individual, Precomputed &precomputed) const = 0;
 };
 
 SE_END_CXX
index 7bc626d..5183284 100644 (file)
@@ -27,6 +27,7 @@
 #include "../resource.h"
 #include "../client.h"
 #include "../session.h"
+#include "../localed-listener.h"
 
 #include <syncevo/IniConfigNode.h>
 #include <syncevo/BoostHelper.h>
@@ -81,8 +82,15 @@ Manager::Manager(const boost::shared_ptr<Server> &server) :
     m_mainThread(g_thread_self()),
     m_server(server),
     m_locale(LocaleFactory::createFactory()),
+    m_localedListener(LocaledListener::create()),
     emitSyncProgress(*this, "SyncProgress")
 {
+    // Update our own environment and sorting on each locale change.
+    m_localedListener->m_localeValues.connect(boost::bind(&LocaledListener::setLocale, m_localedListener.get(), _1));
+    m_localedListener->m_localeChanged.connect(boost::bind(&Manager::localeChanged, this));
+
+    // Get the environment once from localed, just to be sure.
+    m_localedListener->check(boost::bind(&LocaledListener::setLocale, boost::weak_ptr<LocaledListener>(m_localedListener), _1));
 }
 
 Manager::~Manager()
@@ -116,7 +124,6 @@ void Manager::init()
         "last/first";
     InitStateString active = m_configNode->readProperty(MANAGER_CONFIG_ACTIVE_ADDRESS_BOOKS_PROPERTY);
     m_enabledEBooks.clear();
-    typedef boost::split_iterator<string::iterator> string_split_iterator;
     BOOST_FOREACH(const std::string &entry,
                   boost::tokenizer< boost::char_separator<char> >(active, boost::char_separator<char>(", \t"))) {
         if (!entry.empty()) {
@@ -124,7 +131,16 @@ void Manager::init()
         }
     }
     initFolks();
-    initSorting(m_sortOrder);
+    try {
+        initSorting(m_sortOrder);
+    } catch (...) {
+        std::string explanation;
+        Exception::handle(explanation, HANDLE_EXCEPTION_NO_ERROR);
+        SE_LOG_WARNING(NULL, "Restoring sort order from config failed, falling back to default: %s",
+                       explanation.c_str());
+        m_sortOrder = "last/first";
+        initSorting(m_sortOrder);
+    }
     initDatabases();
 
     add(this, &Manager::start, "Start");
@@ -257,6 +273,23 @@ void Manager::initSorting(const std::string &order)
     m_folks->setCompare(compare);
 }
 
+void Manager::localeChanged()
+{
+    // First update locale.
+    m_locale = LocaleFactory::createFactory();
+    // Change sorting. First install new locale in
+    // IndividualAggregator and through it in FullView.
+    if (m_folks) {
+        m_folks->setLocale(m_locale);
+    }
+    // Then update IndividualData of all loaded individuals by
+    // changing the sort order.
+    initSorting(m_sortOrder);
+
+    // Now update views.
+    m_localeChanged(m_locale);
+}
+
 boost::shared_ptr<Manager> Manager::create(const boost::shared_ptr<Server> &server)
 {
     boost::shared_ptr<Manager> manager(new Manager(server));
@@ -366,6 +399,7 @@ class ViewResource : public Resource, public GDBusCXX::DBusObjectHelper
     boost::shared_ptr<IndividualView> m_view;
     boost::shared_ptr<LocaleFactory> m_locale;
     boost::weak_ptr<Client> m_owner;
+    LocaleFactory::Filter_t m_filter;
     struct Change {
         Change() : m_start(0), m_call(NULL) {}
 
@@ -381,6 +415,7 @@ class ViewResource : public Resource, public GDBusCXX::DBusObjectHelper
     ViewResource(const boost::shared_ptr<IndividualView> view,
                  const boost::shared_ptr<LocaleFactory> &locale,
                  const boost::shared_ptr<Client> &owner,
+                 const LocaleFactory::Filter_t &filter,
                  GDBusCXX::connection_type *connection,
                  const GDBusCXX::Caller_t &ID,
                  const GDBusCXX::DBusObject_t &agentPath) :
@@ -394,6 +429,7 @@ class ViewResource : public Resource, public GDBusCXX::DBusObjectHelper
         m_view(view),
         m_locale(locale),
         m_owner(owner),
+        m_filter(filter),
 
         // use ViewAgent interface
         m_quiescent(m_viewAgent, "Quiescent"),
@@ -707,6 +743,7 @@ public:
     static boost::shared_ptr<ViewResource> create(const boost::shared_ptr<IndividualView> &view,
                                                   const boost::shared_ptr<LocaleFactory> &locale,
                                                   const boost::shared_ptr<Client> &owner,
+                                                  const LocaleFactory::Filter_t &filter,
                                                   GDBusCXX::connection_type *connection,
                                                   const GDBusCXX::Caller_t &ID,
                                                   const GDBusCXX::DBusObject_t &agentPath)
@@ -714,6 +751,7 @@ public:
         boost::shared_ptr<ViewResource> viewResource(new ViewResource(view,
                                                                       locale,
                                                                       owner,
+                                                                      filter,
                                                                       connection,
                                                                       ID,
                                                                       agentPath));
@@ -770,10 +808,32 @@ public:
     void replaceSearch(const std::vector<LocaleFactory::Filter_t> &filterArray, bool refine)
     {
         // Same as in Search().
-        LocaleFactory::Filter_t filter = filterArray;
-        boost::shared_ptr<IndividualFilter> individualFilter = m_locale->createFilter(filter, 0);
+        m_filter = filterArray;
+        redoSearch(refine);
+    }
+
+    /**
+     * Start filtering again, using the current environment. To be
+     * called after a locale change or when m_filter changed.
+     *
+     * @param refine   true only if it is known to the caller that the new result set is
+     *                 a subset of the current one, false if uncertain
+     */
+    void redoSearch(bool refine)
+    {
+        boost::shared_ptr<IndividualFilter> individualFilter = m_locale->createFilter(m_filter, 0);
         m_view->replaceFilter(individualFilter, refine);
     }
+
+    /**
+     * Change locale, then refilter because the filter may have changed.
+     */
+    void setLocale(const boost::shared_ptr<LocaleFactory> &locale)
+    {
+        m_locale = locale;
+        redoSearch(true);
+    }
+
 };
 unsigned int ViewResource::m_counter;
 
@@ -897,11 +957,15 @@ void Manager::doSearch(const ESourceRegistryCXX &registry,
     boost::shared_ptr<ViewResource> viewResource(ViewResource::create(view,
                                                                       m_locale,
                                                                       client,
+                                                                      filter,
                                                                       getConnection(),
                                                                       ID,
                                                                       agentPath));
     client->attach(boost::shared_ptr<Resource>(viewResource));
 
+    // Redo search when locale changes.
+    m_localeChanged.connect(LocaleChangedSignal::slot_type(&ViewResource::setLocale, viewResource.get(), _1).track(viewResource));
+
     // created local resource
     result->done(viewResource->getPath());
 }
@@ -1272,7 +1336,7 @@ void Manager::doRemovePeer(const boost::shared_ptr<Session> &session,
     // doing so doesn't hurt.
     m_enabledEBooks.erase(localDatabaseName);
     initDatabases();
-    m_configNode->writeProperty(MANAGER_CONFIG_SORT_PROPERTY,
+    m_configNode->writeProperty(MANAGER_CONFIG_ACTIVE_ADDRESS_BOOKS_PROPERTY,
                                 InitStateString(boost::join(m_enabledEBooks, " "), true));
     m_configNode->flush();
 
index d43a523..e9fee00 100644 (file)
@@ -34,6 +34,8 @@
 #include <syncevo/declarations.h>
 SE_BEGIN_CXX
 
+class LocaledListener;
+
 /**
  * Implementation of org._01.pim.contacts.Manager.
  */
@@ -44,6 +46,7 @@ class Manager : public GDBusCXX::DBusObjectHelper
     boost::shared_ptr<Server> m_server;
     boost::shared_ptr<IndividualAggregator> m_folks;
     boost::shared_ptr<LocaleFactory> m_locale;
+    boost::shared_ptr<LocaledListener> m_localedListener;
     /** Stores "sort" property in XDG ~/.config/syncevolution/pim-manager.ini'. */
     boost::shared_ptr<ConfigNode> m_configNode;
     std::string m_sortOrder;
@@ -64,6 +67,10 @@ class Manager : public GDBusCXX::DBusObjectHelper
     void initFolks();
     void initDatabases();
     void initSorting(const std::string &order);
+    void localeChanged();
+
+    typedef boost::signals2::signal<void (const boost::shared_ptr<LocaleFactory> &locale)> LocaleChangedSignal;
+    LocaleChangedSignal m_localeChanged;
 
  public:
     /** Manager.Start() */
index 54b1dfe..e892372 100644 (file)
@@ -1,3 +1,3 @@
 [D-BUS Service]
 Name=org._01.pim.contacts
-Exec=@libexecdir@/syncevo-dbus-server
+Exec=@libexecdir@/syncevo-dbus-server @SYNCEVO_DBUS_SERVER_ARGS@
index 7328ba5..a2e1f71 100755 (executable)
@@ -45,6 +45,8 @@ import codecs
 import pprint
 import shutil
 
+import localed
+
 # Update path so that testdbus.py can be found.
 pimFolder = os.path.realpath(os.path.abspath(os.path.split(inspect.getfile(inspect.currentframe()))[0]))
 if pimFolder not in sys.path:
@@ -600,6 +602,16 @@ VERSION:3.0\r?
         return set([os.path.splitext(x)[0] for x in (os.path.exists(self.sourcedir) and os.listdir(self.sourcedir) or [])])
 
 
+    def readManagerIni(self):
+         '''returns content of manager.ini file, split into lines and sorted, None if not found'''
+         filename = os.path.join(xdg_root, "config", "syncevolution", "pim-manager.ini")
+         if os.path.exists(filename):
+              lines = open(filename, "r").readlines()
+              lines.sort()
+              return lines
+         else:
+              return None
+
 
 class TestContacts(TestPIMUtil, unittest.TestCase):
     """Tests for org._01.pim.contacts API.
@@ -634,6 +646,18 @@ XDG root.
         expected.add(self.managerPrefix + uid)
         self.assertEqual(peers, self.manager.GetAllPeers())
         self.assertEqual(expected, self.currentSources())
+        self.assertEqual(['sort =\n'],
+                         self.readManagerIni())
+
+        # Check effect of SetActiveAddressBooks() on pim-manager.ini.
+        self.manager.SetActiveAddressBooks(['peer-' + uid])
+        self.assertEqual(['active = pim-manager-' + uid + '\n',
+                          'sort =\n'],
+                         self.readManagerIni())
+        self.manager.SetActiveAddressBooks([])
+        self.assertEqual(['active = \n',
+                          'sort =\n'],
+                         self.readManagerIni())
 
         # PIM Manager must not allow overwriting an existing config.
         # Uses the new name for SetPeer().
@@ -659,14 +683,21 @@ XDG root.
         self.manager.RemovePeer(uid)
         self.assertEqual(peers, self.manager.GetAllPeers())
         self.assertEqual(expected, self.currentSources())
+        self.assertEqual(['active = \n',
+                          'sort =\n'],
+                         self.readManagerIni())
 
-        # add and remove foo again
+        # add and remove foo again, this time while its address book is active
         uid = self.uidPrefix + 'foo4' # work around EDS bug with reusing UID
         peers[uid] = {'protocol': 'PBAP',
                       'address': 'xxx'}
         self.manager.SetPeer(uid,
                              peers[uid])
         expected.add(self.managerPrefix + uid)
+        self.manager.SetActiveAddressBooks(['peer-' + uid])
+        self.assertEqual(['active = pim-manager-' + uid + '\n',
+                          'sort =\n'],
+                         self.readManagerIni())
         self.assertEqual(peers, self.manager.GetAllPeers())
         self.assertEqual(expected, self.currentSources())
         time.sleep(2)
@@ -675,9 +706,14 @@ XDG root.
         self.manager.RemovePeer(uid)
         self.assertEqual(peers, self.manager.GetAllPeers())
         self.assertEqual(expected, self.currentSources())
+        self.assertEqual(['active = \n',
+                          'sort =\n'],
+                         self.readManagerIni())
 
         # add foo, bar, xyz
+        addressbooks = []
         uid = self.uidPrefix + 'foo2'
+        addressbooks.append('peer-' + uid)
         peers[uid] = {'protocol': 'PBAP',
                       'address': 'xxx'}
         self.manager.SetPeer(uid,
@@ -685,8 +721,12 @@ XDG root.
         expected.add(self.managerPrefix + uid)
         self.assertEqual(peers, self.manager.GetAllPeers())
         self.assertEqual(expected, self.currentSources())
+        self.assertEqual(['active = \n',
+                          'sort =\n'],
+                         self.readManagerIni())
 
         uid = self.uidPrefix + 'bar'
+        addressbooks.append('peer-' + uid)
         peers[uid] = {'protocol': 'PBAP',
                       'address': 'yyy'}
         self.manager.SetPeer(uid,
@@ -696,6 +736,7 @@ XDG root.
         self.assertEqual(expected, self.currentSources())
 
         uid = self.uidPrefix + 'xyz'
+        addressbooks.append('peer-' + uid)
         peers[uid] = {'protocol': 'PBAP',
                       'address': 'zzz'}
         self.manager.SetPeer(uid,
@@ -703,6 +744,15 @@ XDG root.
         expected.add(self.managerPrefix + uid)
         self.assertEqual(peers, self.manager.GetAllPeers())
         self.assertEqual(expected, self.currentSources())
+        self.assertEqual(['active = \n',
+                          'sort =\n'],
+                         self.readManagerIni())
+
+        self.manager.SetActiveAddressBooks(addressbooks)
+        addressbooks.sort()
+        self.assertEqual(['active = ' + ' '.join([x.replace('peer-', 'pim-manager-') for x in addressbooks]) + '\n',
+                          'sort =\n'],
+                         self.readManagerIni())
 
         # EDS workaround
         time.sleep(2)
@@ -710,9 +760,13 @@ XDG root.
         # remove yxz, bar, foo
         expected.remove(self.managerPrefix + uid)
         del peers[uid]
+        addressbooks.remove('peer-' + uid)
         self.manager.RemovePeer(uid)
         self.assertEqual(peers, self.manager.GetAllPeers())
         self.assertEqual(expected, self.currentSources())
+        self.assertEqual(['active = ' + ' '.join([x.replace('peer-', 'pim-manager-') for x in addressbooks]) + '\n',
+                          'sort =\n'],
+                         self.readManagerIni())
 
         # EDS workaround
         time.sleep(2)
@@ -720,9 +774,13 @@ XDG root.
         uid = self.uidPrefix + 'bar'
         expected.remove(self.managerPrefix + uid)
         del peers[uid]
+        addressbooks.remove('peer-' + uid)
         self.manager.RemovePeer(uid)
         self.assertEqual(peers, self.manager.GetAllPeers())
         self.assertEqual(expected, self.currentSources())
+        self.assertEqual(['active = ' + ' '.join([x.replace('peer-', 'pim-manager-') for x in addressbooks]) + '\n',
+                          'sort =\n'],
+                         self.readManagerIni())
 
         # EDS workaround
         time.sleep(2)
@@ -730,13 +788,23 @@ XDG root.
         uid = self.uidPrefix + 'foo2'
         expected.remove(self.managerPrefix + uid)
         del peers[uid]
+        addressbooks.remove('peer-' + uid)
         self.manager.RemovePeer(uid)
         self.assertEqual(peers, self.manager.GetAllPeers())
         self.assertEqual(expected, self.currentSources())
+        self.assertEqual(['active = ' + ' '.join([x.replace('peer-', 'pim-manager-') for x in addressbooks]) + '\n',
+                          'sort =\n'],
+                         self.readManagerIni())
 
         # EDS workaround
         time.sleep(2)
 
+    @property("snapshot", "broken-config")
+    def testBrokenConfig(self):
+        '''TestContacts.testBrokenConfig - start with broken pim-manager.ini'''
+        self.manager.Start()
+        self.assertEqual("last/first", self.manager.GetSortOrder())
+
     @timeout(os.environ.get('TESTPIM_TEST_SYNC_TESTCASES', False) and 300000 or 300)
     @property("snapshot", "simple-sort")
     def testSync(self):
@@ -1534,8 +1602,7 @@ END:VCARD''']):
         # Check that order was adapted and stored permanently.
         self.assertEqual("last/first", self.manager.GetSortOrder())
         self.assertIn("sort = last/first\n",
-                      open(os.path.join(xdg_root, "config", "syncevolution", "pim-manager.ini"),
-                           "r").readlines())
+                      self.readManagerIni())
 
         # Contact in the middle may or may not become invalidated.
         self.runUntil('reordered',
@@ -1984,8 +2051,7 @@ END:VCARD'''
         # assuming that the PIM Manager preserves that order (not really guaranteed
         # by the API, but is how it is implemented).
         self.assertIn('active = pim-manager-' + self.uidPrefix + 'a pim-manager-' + self.uidPrefix + 'b pim-manager-' + self.uidPrefix + 'c system-address-book\n',
-                      open(os.path.join(xdg_root, "config", "syncevolution", "pim-manager.ini"),
-                           "r").readlines())
+                      self.readManagerIni())
 
         for peer in active:
              for index in range(0, contactsPerPeer):
@@ -2397,26 +2463,40 @@ END:VCARD''']):
 
         # Find Abraham via caller ID for 089/7888-99 (country is Germany).
         view = ContactsView(self.manager)
-        view.search([['phone', '+49897888']])
-        self.runUntil('"+49897888" search results',
+        view.search([['phone', '+4989788899']])
+        self.runUntil('"+4989788899" search results',
                       check=lambda: self.assertEqual([], view.errors),
                       until=lambda: view.quiescentCount > 0)
         self.assertEqual(1, len(view.contacts))
         view.read(0, 1)
-        self.runUntil('+49897888 data',
+        self.runUntil('+4989788899 data',
+                      check=lambda: self.assertEqual([], view.errors),
+                      until=lambda: view.haveData(0))
+        self.assertEqual(u'Abraham', view.contacts[0]['structured-name']['given'])
+
+        # Find Abraham via caller ID for +44 89 7888-99 (Abraham has no country code
+        # set and matches, whereas Benjamin has +1 as country code and does not match).
+        view = ContactsView(self.manager)
+        view.search([['phone', '+4489788899']])
+        self.runUntil('"+4489788899" search results',
+                      check=lambda: self.assertEqual([], view.errors),
+                      until=lambda: view.quiescentCount > 0)
+        self.assertEqual(1, len(view.contacts))
+        view.read(0, 1)
+        self.runUntil('+4489788899 data',
                       check=lambda: self.assertEqual([], view.errors),
                       until=lambda: view.haveData(0))
         self.assertEqual(u'Abraham', view.contacts[0]['structured-name']['given'])
 
         # Find Abraham via 089/7888-99 (not a full caller ID, but at least a valid phone number).
         view = ContactsView(self.manager)
-        view.search([['phone', '0897888']])
-        self.runUntil('"0897888" search results',
+        view.search([['phone', '089788899']])
+        self.runUntil('"089788899" search results',
                       check=lambda: self.assertEqual([], view.errors),
                       until=lambda: view.quiescentCount > 0)
         self.assertEqual(1, len(view.contacts))
         view.read(0, 1)
-        self.runUntil('0897888 data',
+        self.runUntil('089788899 data',
                       check=lambda: self.assertEqual([], view.errors),
                       until=lambda: view.haveData(0))
         self.assertEqual(u'Abraham', view.contacts[0]['structured-name']['given'])
@@ -2433,6 +2513,7 @@ END:VCARD''']):
         self.setUpView()
 
         msg = None
+        view = None
         try:
              # Insert new contacts and calculate their family names.
              names = []
@@ -2503,6 +2584,7 @@ END:VCARD
                   raise Exception('%s:\n%s' % (msg, repr(ex))), None, info[2]
              else:
                   raise
+        return view
 
     @timeout(60)
     @property("ENV", "LC_TYPE=ja_JP.UTF-8 LC_ALL=ja_JP.UTF-8 LANG=ja_JP.UTF-8")
@@ -2521,13 +2603,19 @@ END:VCARD
          self.doFilter(# Names of all contacts, sorted as expected.
                        # 江 = jiāng = Jiang when using Pinyin and thus after Jeffries and before Meadows.
                        # 鳥 = niǎo before 女性 = nǚ xìng (see FDO #66618)
-                       ('Adams', 'Jeffries', u'江', 'Meadows', u'鳥', u'女性' ),
-                       # 'J' not expected to find Jiang; searching
-                       # is meant to use Chinese letters.
-                       (([['any-contains', 'J']], ('Jeffries',)),
-                        ([['any-contains', u'江']], (u'江',)),
-                        ([['any-contains', u'jiāng']], ()),
-                        ([['any-contains', u'Jiang']], ()),
+                       ('Adams', 'Jeffries', u'江', 'jiang', 'Meadows', u'鳥', u'女性' ),
+                       # 'J' may or may not match Jiang; by default, it matches.
+                       (([['any-contains', 'J']], ('Jeffries', u'江', 'jiang')),
+                        ([['any-contains', 'J', 'no-transliteration']], ('Jeffries', 'jiang')),
+                        ([['any-contains', 'J', 'no-transliteration', 'case-sensitive']], ('Jeffries',)),
+                        ([['any-contains', u'江']], (u'江', 'jiang')),
+                        ([['any-contains', u'jiang']], (u'江', 'jiang')),
+                        ([['any-contains', u'jiāng']], (u'江', 'jiang')),
+                        ([['any-contains', u'jiāng', 'no-transliteration']], ('jiang',)),
+                        ([['any-contains', u'jiāng', 'accent-sensitive']], (u'江',)),
+                        ([['any-contains', u'jiāng', 'accent-sensitive', 'case-sensitive']], (u'江',)),
+                        ([['any-contains', u'Jiāng', 'accent-sensitive', 'case-sensitive']], ()),
+                        ([['any-contains', u'Jiang']], (u'江', 'jiang')),
                         ),
                        )
 
@@ -2542,6 +2630,100 @@ END:VCARD
                        (),
                        )
 
+    @timeout(60)
+    @property("ENV", "LC_TYPE=zh_CN.UTF-8 LANG=zh_CN.UTF-8")
+    def testLocaled(self):
+         # Use mixed Chinese/Western names, because then the locale really matters.
+         namespinyin = ('Adams', 'Jeffries', u'江', 'Meadows', u'鳥', u'女性' )
+         namesgerman = ('Adams', 'Jeffries', 'Meadows', u'女性', u'江', u'鳥' )
+         numtestcases = len(namespinyin)
+         self.doFilter(namespinyin, ())
+
+         daemon = localed.Localed()
+         msg = None
+         try:
+              # Broadcast Locale value together with PropertiesChanged signal.
+              self.view.quiescentCount = 0
+              daemon.SetLocale(['LC_TYPE=de_DE.UTF-8', 'LANG=de_DE.UTF-8'], False)
+              logging.log('reading contacts, German')
+              self.runUntil('German sorting',
+                            check=lambda: self.assertEqual([], self.view.errors),
+                            until=lambda: self.view.quiescentCount > 1)
+              self.view.read(0, numtestcases)
+              self.runUntil('German contacts',
+                            check=lambda: self.assertEqual([], self.view.errors),
+                            until=lambda: self.view.haveData(0, numtestcases))
+              for i, name in enumerate(namesgerman):
+                   msg = u'contact #%d with name %s in\n%s' % (i, name, pprint.pformat(self.stripDBus(self.view.contacts, sortLists=False)))
+                   self.assertEqual(name, self.view.contacts[i]['full-name'])
+
+              # Switch back to Pinyin without including the new value.
+              self.view.quiescentCount = 0
+              daemon.SetLocale(['LC_TYPE=zh_CN.UTF-8', 'LANG=zh_CN.UTF-8'], True)
+              logging.log('reading contacts, Pinyin')
+              self.runUntil('Pinyin sorting',
+                            check=lambda: self.assertEqual([], self.view.errors),
+                            until=lambda: self.view.quiescentCount > 1)
+              self.view.read(0, numtestcases)
+              self.runUntil('Pinyin contacts',
+                            check=lambda: self.assertEqual([], self.view.errors),
+                            until=lambda: self.view.haveData(0, numtestcases))
+              for i, name in enumerate(namespinyin):
+                   msg = u'contact #%d with name %s in\n%s' % (i, name, pprint.pformat(self.stripDBus(self.view.contacts, sortLists=False)))
+                   self.assertEqual(name, self.view.contacts[i]['full-name'])
+         except Exception, ex:
+             if msg:
+                  info = sys.exc_info()
+                  raise Exception('%s:\n%s' % (msg, repr(ex))), None, info[2]
+             else:
+                  raise
+
+    @timeout(60)
+    # Must disable usage of pre-computed phone numbers from EDS, because we can't tell EDS
+    # when locale is meant to change.
+    @property("ENV", "LANG=en_US.UTF-8 SYNCEVOLUTION_PIM_EDS_NO_E164=1")
+    def testLocaledPhone(self):
+         # Parsing of 1234-5 depends on locale: US drops the 1 from 1234
+         # Germany (and other countries) don't. Use that to match (or not match)
+         # a contact.
+         testcases = (('Doe', '''BEGIN:VCARD
+VERSION:3.0
+FN:Doe
+N:Doe;;;;
+TEL:12 34-5
+END:VCARD
+'''),)
+         names = ('Doe')
+         numtestcases = len(testcases)
+         view = self.doFilter(testcases,
+                              (([['phone', '+12345']], ('Doe',)),))
+
+         daemon = localed.Localed()
+         msg = None
+         try:
+              # Contact no longer matched because it's phone number normalization
+              # becomes different.
+              view.quiescentCount = 0
+              daemon.SetLocale(['LANG=de_DE.UTF-8'], True)
+              self.runUntil('German locale',
+                            check=lambda: self.assertEqual([], view.errors),
+                            until=lambda: view.quiescentCount > 1)
+              self.assertEqual(len(view.contacts), 0)
+
+              # Switch back to US.
+              view.quiescentCount = 0
+              daemon.SetLocale(['LANG=en_US.UTF-8'], True)
+              self.runUntil('US locale',
+                            check=lambda: self.assertEqual([], view.errors),
+                            until=lambda: view.quiescentCount > 1)
+              self.assertEqual(len(view.contacts), 1)
+         except Exception, ex:
+             if msg:
+                  info = sys.exc_info()
+                  raise Exception('%s:\n%s' % (msg, repr(ex))), None, info[2]
+             else:
+                  raise
+
     # Not supported correctly by ICU?
     # See icu-support "Subject: Austrian phone book sorting"
     # @timeout(60)
index ddff6f1..3f6869e 100644 (file)
@@ -22,7 +22,7 @@
 
 #include "read-operations.h"
 
-#include <boost/signals.hpp>
+#include <boost/signals2.hpp>
 
 SE_BEGIN_CXX
 
index ab01679..cd82028 100644 (file)
@@ -25,6 +25,7 @@ src_dbus_server_server_cpp_files = \
   src/dbus/server/dbus-callbacks.cpp \
   src/dbus/server/dbus-user-interface.cpp \
   src/dbus/server/exceptions.cpp \
+  src/dbus/server/localed-listener.cpp \
   src/dbus/server/info-req.cpp \
   src/dbus/server/network-manager-client.cpp \
   src/dbus/server/presence-status.cpp \
@@ -82,7 +83,7 @@ nodist_src_dbus_server_libsyncevodbusserver_la_SOURCES += \
 
 src_dbus_server_libsyncevodbusserver_la_LDFLAGS += $(DBUS_PIM_PLUGIN_LDFLAGS)
 src_dbus_server_libsyncevodbusserver_la_LIBADD += $(FOLKS_LIBS) $(DBUS_PIM_PLUGIN_LIBS) $(PHONENUMBERS_LIBS)
-src_dbus_server_libsyncevodbusserver_la_CXXFLAGS += $(FOLKS_CFLAGS) $(DBUS_PIM_PLUGIN_CFLAGS) $(PHONENUMBERS_CFLAGS)
+src_dbus_server_libsyncevodbusserver_la_CXXFLAGS += $(FOLKS_CFLAGS) $(DBUS_PIM_PLUGIN_CFLAGS) $(PHONENUMBERS_CFLAGS) $(DLT_CFLAGS)
 endif
 
 # Need to list all plugins here and not include the active one in the regular
@@ -128,7 +129,7 @@ src_dbus_server_autostart_DATA = $(src_dbus_server_desktop)
 
 libexec_SCRIPTS += $(src_dbus_server_script)
 $(src_dbus_server_script): $(src_dbus_server_script_in)
-       @sed -e "s|\@libexecdir\@|$(libexecdir)|" $< >$@
+       @sed -e "s|\@libexecdir\@|$(libexecdir)|" -e "s|\@SYNCEVO_DBUS_SERVER_ARGS\@|$(SYNCEVO_DBUS_SERVER_ARGS)|" $< >$@
 $(src_dbus_server_desktop): $(src_dbus_server_desktop_in)
        @sed -e "s|\@libexecdir\@|$(libexecdir)|" $< >$@
 
@@ -137,7 +138,7 @@ src_dbus_server_service_files = $(src_dbus_server_service_files_in:.service.in=.
 src_dbus_server_servicedir = $(DBUS_SERVICES_DIR)
 src_dbus_server_service_DATA = $(src_dbus_server_service_files)
 src/dbus/server/%.service: src/dbus/server/%.service.in
-       @sed -e "s|\@libexecdir\@|$(libexecdir)|" $< >$@
+       @sed -e "s|\@libexecdir\@|$(libexecdir)|" -e "s|\@SYNCEVO_DBUS_SERVER_ARGS\@|$(SYNCEVO_DBUS_SERVER_ARGS)|" $< >$@
 
 if COND_DBUS_PIM
 src_dbus_server_service_files_in += \
index 7d23396..19776ea 100644 (file)
@@ -42,14 +42,13 @@ static void dumpString(const std::string &output)
  */
 class SessionHelperLogger : public Logger
 {
-    boost::shared_ptr<LogRedirect> m_parentLogger;
+    Handle m_parentLogger;
     boost::shared_ptr<SessionHelper> m_helper;
     Level m_dbusLogLevel;
 
 public:
-    SessionHelperLogger(const boost::shared_ptr<LogRedirect> &parentLogger,
-                        const boost::shared_ptr<SessionHelper> &helper):
-        m_parentLogger(parentLogger),
+    SessionHelperLogger(const boost::shared_ptr<SessionHelper> &helper):
+        m_parentLogger(Logger::instance()),
         m_helper(helper),
         m_dbusLogLevel(DEBUG)
     {
@@ -84,7 +83,7 @@ public:
             va_list argsCopy;
             va_copy(argsCopy, args);
             if (m_parentLogger) {
-                m_parentLogger->messagev(options, format, argsCopy);
+                m_parentLogger.messagev(options, format, argsCopy);
             } else {
                 formatLines(options.m_level, DEBUG,
                             options.m_processName,
@@ -94,10 +93,16 @@ public:
             }
             va_end(argsCopy);
         } else if (m_parentLogger) {
-            // Only flush parent logger, to capture output sent to
-            // stdout/stderr by some library and send it via D-Bus
-            // (recursively!)  before printing out own, new output.
-            m_parentLogger->flush();
+            // Pass through to parent, but marked in such a way that
+            // only the DLT and syslog logger will react to it, but
+            // not LogStdout. That's necessary because
+            // syncevo-dbus-server handles stdout for us.
+            va_list argsCopy;
+            va_copy(argsCopy, args);
+            MessageOptions buffer(options);
+            buffer.m_flags |= MessageOptions::ONLY_GLOBAL_LOG;
+            m_parentLogger.messagev(buffer, format, argsCopy);
+            va_end(argsCopy);
         }
 
         if (m_helper &&
@@ -117,8 +122,7 @@ public:
 
 SessionHelper::SessionHelper(GMainLoop *loop,
                              const GDBusCXX::DBusConnectionPtr &conn,
-                             const boost::shared_ptr<ForkExecChild> &forkexec,
-                             const boost::shared_ptr<LogRedirect> &parentLogger) :
+                             const boost::shared_ptr<ForkExecChild> &forkexec) :
     GDBusCXX::DBusObjectHelper(conn,
                                std::string(SessionCommon::HELPER_PATH) + "/" + forkexec->getInstance(),
                                SessionCommon::HELPER_IFACE,
@@ -127,7 +131,7 @@ SessionHelper::SessionHelper(GMainLoop *loop,
     m_loop(loop),
     m_conn(conn),
     m_forkexec(forkexec),
-    m_logger(new SessionHelperLogger(parentLogger, boost::shared_ptr<SessionHelper>(this, NopDestructor()))),
+    m_logger(new SessionHelperLogger(boost::shared_ptr<SessionHelper>(this, NopDestructor()))),
     emitLogOutput(*this, "LogOutput"),
     emitSyncProgress(*this, "SyncProgress"),
     emitSourceProgress(*this, "SourceProgress"),
index 3c38000..6f9dc0e 100644 (file)
@@ -85,8 +85,7 @@ class SessionHelper : public GDBusCXX::DBusObjectHelper,
  public:
     SessionHelper(GMainLoop *loop,
                   const GDBusCXX::DBusConnectionPtr &conn,
-                  const boost::shared_ptr<ForkExecChild> &forkexec,
-                  const boost::shared_ptr<LogRedirect> &parentLogger);
+                  const boost::shared_ptr<ForkExecChild> &forkexec);
     ~SessionHelper();
 
     void setDBusLogLevel(Logger::Level level);
index 12b5bb7..03c4ee1 100644 (file)
 #include <syncevo/SyncContext.h>
 #include <syncevo/BoostHelper.h>
 
+#ifdef USE_DLT
+#include <syncevo/LogDLT.h>
+#endif
+
 #include <memory>
 
 #include <boost/foreach.hpp>
@@ -793,6 +797,11 @@ void Session::useHelperAsync(const SimpleResult &result)
             args.push_back("--dbus-verbosity");
             args.push_back(StringPrintf("%d", m_server.getDBusLogLevel()));
             m_forkExecParent = SyncEvo::ForkExecParent::create("syncevo-dbus-helper", args);
+#ifdef USE_DLT
+            if (getenv("SYNCEVOLUTION_USE_DLT")) {
+                m_forkExecParent->addEnvVar("SYNCEVOLUTION_USE_DLT", StringPrintf("%d", LoggerDLT::getCurrentDLTLogLevel()));
+            }
+#endif
             // We own m_forkExecParent, so the "this" pointer for
             // onConnect will live longer than the signal in
             // m_forkExecParent -> no need for resource
@@ -884,6 +893,7 @@ static void Logging2Server(Server &server,
         // there is considered an error.
         Logger::MessageOptions options(Logger::strToLevel(strLevel.c_str()));
         options.m_processName = &procname;
+        options.m_flags = Logger::MessageOptions::ALREADY_LOGGED;
         Logging2ServerAndStdout(server, path, options, "%s", explanation.c_str());
     }
 }
index a564e9a..8fefb3c 100644 (file)
@@ -28,6 +28,7 @@
 #include <syncevo/SuspendFlags.h>
 #include <syncevo/SyncContext.h>
 #include <syncevo/LogRedirect.h>
+#include <syncevo/LogDLT.h>
 
 using namespace SyncEvo;
 using namespace GDBusCXX;
@@ -45,11 +46,10 @@ namespace {
     }
 
     void onConnect(const DBusConnectionPtr &conn,
-                   const boost::shared_ptr<LogRedirect> &parentLogger,
                    const boost::shared_ptr<ForkExecChild> &forkexec,
                    boost::shared_ptr<SessionHelper> &helper)
     {
-        helper.reset(new SessionHelper(loop, conn, forkexec, parentLogger));
+        helper.reset(new SessionHelper(loop, conn, forkexec));
         helper->activate();
         helper->setDBusLogLevel(Logger::Level(logLevelDBus));
     }
@@ -107,6 +107,14 @@ int main(int argc, char **argv, char **envp)
         redirect.reset(new LogRedirect(LogRedirect::STDERR_AND_STDOUT));
         pushRedirect.reset(redirect);
     }
+#ifdef USE_DLT
+    // Set by syncevo-dbus-server for us.
+    bool useDLT = getenv("SYNCEVOLUTION_USE_DLT") != NULL;
+    PushLogger<LoggerDLT> loggerdlt;
+    if (useDLT) {
+        loggerdlt.reset(new LoggerDLT(DLT_SYNCEVO_DBUS_HELPER_ID, "SyncEvolution local sync helper"));
+    }
+#endif
     setvbuf(stderr, NULL, _IONBF, 0);
     setvbuf(stdout, NULL, _IONBF, 0);
 
@@ -140,7 +148,7 @@ int main(int argc, char **argv, char **envp)
 
         boost::shared_ptr<SessionHelper> helper;
         bool failed = false;
-        forkexec->m_onConnect.connect(boost::bind(onConnect, _1, redirect,
+        forkexec->m_onConnect.connect(boost::bind(onConnect, _1,
                                                   boost::cref(forkexec),
                                                   boost::ref(helper)));
         forkexec->m_onFailure.connect(boost::bind(onFailure, _2, boost::ref(failed)));
index 8d19cf7..6f9d7ba 100755 (executable)
@@ -1,3 +1,3 @@
 #! /bin/sh
 sleep 120
-exec @libexecdir@/syncevo-dbus-server 2>/dev/null 1>&1
+exec @libexecdir@/syncevo-dbus-server @SYNCEVO_DBUS_SERVER_ARGS@ 2>/dev/null 1>&1
index ad140c8..0325934 100644 (file)
 
 #include <config.h>
 
-#if defined(HAVE_EDS) && defined(USE_EDS_CLIENT)
-
-#include <boost/bind.hpp>
-
 #include <syncevo/declarations.h>
 SE_BEGIN_CXX
 
-EDSRegistryLoader &EDSRegistryLoader::singleton()
-{
-    static EDSRegistryLoader self;
-    return self;
-}
-
-void EDSRegistryLoader::getESourceRegistryAsync(const Callback_t &cb)
-{
-    singleton().async(cb);
-}
-
-void EDSRegistryLoader::async(const Callback_t &cb)
-{
-    if (m_registry || m_gerror) {
-        cb(m_registry, m_gerror);
-    } else {
-        m_pending.push_back(cb);
-        m_loading = true;
-        SYNCEVO_GLIB_CALL_ASYNC(e_source_registry_new,
-                                boost::bind(&EDSRegistryLoader::created,
-                                            this,
-                                            _1, _2),
-                                NULL);
-    }
-}
-
-ESourceRegistryCXX EDSRegistryLoader::getESourceRegistry()
-{
-    return singleton().sync();
-}
-
-ESourceRegistryCXX EDSRegistryLoader::sync()
-{
-    if (!m_loading) {
-        m_loading = true;
-        SYNCEVO_GLIB_CALL_ASYNC(e_source_registry_new,
-                                boost::bind(&EDSRegistryLoader::created,
-                                            this,
-                                            _1, _2),
-                                NULL);
-    }
-
-    while (true) {
-        if (m_registry) {
-            return m_registry;
-        }
-        if (m_gerror) {
-            m_gerror.throwError("creating source registry");
-        }
-        // Only master thread can drive the event processing.
-       if (g_main_context_is_owner(g_main_context_default())) {
-            g_main_context_iteration(NULL, true);
-        } else {
-            Sleep(0.1);
-        }
-    }
-}
-
-void EDSRegistryLoader::created(ESourceRegistry *registry, const GError *gerror) throw ()
+EDSRegistryLoader &EDSRegistryLoaderSingleton(const boost::shared_ptr<EDSRegistryLoader> &loader)
 {
-    try {
-        m_registry = ESourceRegistryCXX::steal(registry);
-        m_gerror = gerror;
-        BOOST_FOREACH (const Callback_t &cb, m_pending) {
-            cb(m_registry, m_gerror);
-        }
-    } catch (...) {
-        Exception::handle(HANDLE_EXCEPTION_FATAL);
+    static boost::shared_ptr<EDSRegistryLoader> singleton;
+    if (!singleton) {
+        singleton = loader;
     }
+    return *singleton;
 }
 
 SE_END_CXX
 
-#endif // HAVE_EDS && USE_EDS_CLIENT
index b7431c9..dd855a8 100644 (file)
@@ -22,6 +22,8 @@
 
 #include <config.h>
 
+#include <boost/shared_ptr.hpp>
+
 #if defined(HAVE_EDS) && defined(USE_EDS_CLIENT)
 
 #include <syncevo/GLibSupport.h>
@@ -29,6 +31,8 @@
 #include <libedataserver/libedataserver.h>
 #include <boost/function.hpp>
 #include <boost/utility.hpp>
+#include <boost/bind.hpp>
+#include <boost/lambda/core.hpp>
 #include <list>
 
 typedef SyncEvo::GListCXX<ESource, GList, SyncEvo::GObjectDestructor> ESourceListCXX;
@@ -36,9 +40,25 @@ SE_GOBJECT_TYPE(ESourceRegistry)
 SE_GOBJECT_TYPE(ESource)
 SE_GOBJECT_TYPE(EClient)
 
+#endif // HAVE_EDS && USE_EDS_CLIENT
+
 #include <syncevo/declarations.h>
 SE_BEGIN_CXX
 
+// This code must always be compiled into libsyncevolution.
+// It may get used by backends which were compiled against
+// EDS >= 3.6 even when the libsyncevolution itself wasn't.
+class EDSRegistryLoader;
+EDSRegistryLoader &EDSRegistryLoaderSingleton(const boost::shared_ptr<EDSRegistryLoader> &loader);
+
+// The following code implements EDSRegistryLoader.
+// For the sake of simplicity, its all in the header file,
+// so all users of it end up with a copy of the code and
+// then they can activate that code when instantiating the object
+// and passing it to EDSRegistryLoaderSingleton().
+
+#if defined(HAVE_EDS) && defined(USE_EDS_CLIENT)
+
 /**
  * Creates ESourceRegistry on demand and shares it inside
  * SyncEvolution. It's never freed once used.
@@ -53,12 +73,18 @@ class EDSRegistryLoader : private boost::noncopyable
      * Callback gets invoked exactly once. If the registry pointer is empty,
      * then the error will explain why.
      */
-    static void getESourceRegistryAsync(const Callback_t &cb);
+    static void getESourceRegistryAsync(const Callback_t &cb)
+    {
+        EDSRegistryLoaderSingleton(boost::shared_ptr<EDSRegistryLoader>(new EDSRegistryLoader)).async(cb);
+    }
 
     /**
      * Returns shared ESourceRegistry, throws error if creation failed.
      */
-    static ESourceRegistryCXX getESourceRegistry();
+    static ESourceRegistryCXX getESourceRegistry()
+    {
+        return EDSRegistryLoaderSingleton(boost::shared_ptr<EDSRegistryLoader>(new EDSRegistryLoader)).sync();
+    }
 
  private:
     Bool m_loading;
@@ -66,13 +92,76 @@ class EDSRegistryLoader : private boost::noncopyable
     GErrorCXX m_gerror;
     std::list<Callback_t> m_pending;
 
-    static EDSRegistryLoader &singleton();
-    void async(const Callback_t &cb);
-    ESourceRegistryCXX sync();
-    void created(ESourceRegistry *registry, const GError *gerror) throw ();
+    void async(const Callback_t &cb)
+    {
+        if (m_registry || m_gerror) {
+            cb(m_registry, m_gerror);
+        } else {
+            m_pending.push_back(cb);
+#if 0
+            m_loading = true;
+            SYNCEVO_GLIB_CALL_ASYNC(e_source_registry_new,
+                                    boost::bind(&EDSRegistryLoader::created,
+                                                this,
+                                                _1, _2),
+                                    NULL);
+#else
+           ESourceRegistry *registry;
+           GErrorCXX gerror;
+           registry = e_source_registry_new_sync(NULL, gerror);
+           created(registry, gerror);
+#endif
+        }
+    }
+
+    ESourceRegistryCXX sync()
+    {
+#if 0
+        if (!m_loading) {
+            m_loading = true;
+            SYNCEVO_GLIB_CALL_ASYNC(e_source_registry_new,
+                                    boost::bind(&EDSRegistryLoader::created,
+                                                this,
+                                                _1, _2),
+                                    NULL);
+        }
+
+        GRunWhile(!boost::lambda::var(m_registry) && !boost::lambda::var(m_gerror));
+#else
+        if (!m_registry) {
+            ESourceRegistry *registry;
+            GErrorCXX gerror;
+            registry = e_source_registry_new_sync(NULL, gerror);
+            created(registry, gerror);
+        }
+#endif
+
+        if (m_registry) {
+            return m_registry;
+        }
+        if (m_gerror) {
+            m_gerror.throwError("creating source registry");
+        }
+        return m_registry;
+    }
+
+
+    void created(ESourceRegistry *registry, const GError *gerror) throw ()
+    {
+        try {
+            m_registry = ESourceRegistryCXX::steal(registry);
+            m_gerror = gerror;
+            BOOST_FOREACH (const Callback_t &cb, m_pending) {
+                cb(m_registry, m_gerror);
+            }
+        } catch (...) {
+            Exception::handle(HANDLE_EXCEPTION_FATAL);
+        }
+    }
 };
 
+#endif // HAVE_EDS && USE_EDS_CLIENT
+
 SE_END_CXX
 
-#endif // HAVE_EDS && USE_EDS_CLIENT
 #endif // INCL_SYNCEVO_EDS_CLIENT
index 1b3a8a5..11d0fb8 100644 (file)
@@ -636,6 +636,11 @@ class PlainGStrArray : public boost::shared_ptr<gchar *>
         PlainGStrArray(const PlainGStrArray &other) : boost::shared_ptr<char *>(other) {}
         operator gchar * const *() const { return &**this; }
         gchar * &at(size_t index) { return get()[index]; }
+ private:
+        // Hide this operator because boost::shared_ptr has problems with it,
+        // probably because of missing traits for a pointer type. Instead use
+        // at().
+        gchar * operator[] (size_t index);
 };
 
 // empty template, need specialization based on parameter and return types
index 3b0ce03..d348878 100644 (file)
@@ -27,6 +27,7 @@
 #include <syncevo/DBusTraits.h>
 #include <syncevo/SuspendFlags.h>
 #include <syncevo/LogRedirect.h>
+#include <syncevo/LogDLT.h>
 #include <syncevo/BoostHelper.h>
 
 #include <synthesis/syerror.h>
@@ -100,6 +101,11 @@ void LocalTransportAgent::start()
     }
     m_status = ACTIVE;
     m_forkexec = ForkExecParent::create("syncevo-local-sync");
+#ifdef USE_DLT
+    if (getenv("SYNCEVOLUTION_USE_DLT")) {
+        m_forkexec->addEnvVar("SYNCEVOLUTION_USE_DLT", StringPrintf("%d", LoggerDLT::getCurrentDLTLogLevel()));
+    }
+#endif
     m_forkexec->m_onConnect.connect(boost::bind(&LocalTransportAgent::onChildConnect, this, _1));
     // fatal problems, including quitting child with non-zero status
     m_forkexec->m_onFailure.connect(boost::bind(&LocalTransportAgent::onFailure, this, _2));
@@ -177,6 +183,9 @@ void LocalTransportAgent::logChildOutput(const std::string &level, const std::st
 {
     Logger::MessageOptions options(Logger::strToLevel(level.c_str()));
     options.m_processName = &m_clientContext;
+    // Child should have written this into its own log file and/or syslog/dlt already.
+    // Only pass it on to a user of the command line interface.
+    options.m_flags = Logger::MessageOptions::ALREADY_LOGGED;
     SyncEvo::Logger::instance().messageWithOptions(options, "%s", message.c_str());
 }
 
@@ -1146,6 +1155,16 @@ int LocalTransportMain(int argc, char **argv)
             Logger::Handle handle(child->createLogger());
             logger.reset(handle);
         }
+
+#ifdef USE_DLT
+        // Set by syncevo-dbus-server for us.
+        bool useDLT = getenv("SYNCEVOLUTION_USE_DLT") != NULL;
+        PushLogger<LoggerDLT> loggerdlt;
+        if (useDLT) {
+            loggerdlt.reset(new LoggerDLT(DLT_SYNCEVO_LOCAL_HELPER_ID, "SyncEvolution local sync helper"));
+        }
+#endif
+
         child->run();
         int ret = child->getReturnCode();
         logger.reset();
diff --git a/src/syncevo/LogDLT.cpp b/src/syncevo/LogDLT.cpp
new file mode 100644 (file)
index 0000000..fd80859
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2012 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/LogDLT.h>
+
+#ifdef USE_DLT
+
+#include <dlt.h>
+
+#include <syncevo/declarations.h>
+SE_BEGIN_CXX
+
+static DltLogLevelType SyncEvoLevel2DLTLevel(Logger::Level level)
+{
+    switch (level) {
+    case Logger::NONE: return DLT_LOG_OFF;
+    case Logger::ERROR: return DLT_LOG_ERROR;
+    case Logger::WARNING: return DLT_LOG_WARN;
+    case Logger::SHOW:
+    case Logger::INFO: return DLT_LOG_INFO;
+    case Logger::DEV:
+    case Logger::DEBUG: return DLT_LOG_DEBUG;
+    }
+    return DLT_LOG_OFF;
+}
+
+static LoggerDLT *LoggerDLTInstance;
+
+LoggerDLT::LoggerDLT(const char *appid, const char *description) :
+    m_parentLogger(Logger::instance()),
+    m_dltContext(calloc(1, sizeof(DltContext)))
+{
+    DLT_REGISTER_APP(appid, description);
+    int level = atoi(getEnv("SYNCEVOLUTION_USE_DLT", "-1"));
+    if (level > 0) {
+        DLT_REGISTER_CONTEXT_LL_TS(*(DltContext *)m_dltContext, "SYNC", "SyncEvolution messages",
+                                   (DltLogLevelType)level, DLT_TRACE_STATUS_OFF);
+    } else {
+        DLT_REGISTER_CONTEXT(*(DltContext *)m_dltContext, "SYNC", "SyncEvolution messages");
+    }
+    LoggerDLTInstance = this;
+}
+
+LoggerDLT::~LoggerDLT()
+{
+    DLT_UNREGISTER_CONTEXT(*(DltContext *)m_dltContext);
+    DLT_UNREGISTER_APP();
+    LoggerDLTInstance = NULL;
+}
+
+void LoggerDLT::messagev(const MessageOptions &options,
+                         const char *format,
+                         va_list args)
+{
+    // always to parent first (usually stdout):
+    // if the parent is a LogRedirect instance, then
+    // it'll flush its own output first, which ensures
+    // that the new output comes later (as desired)
+    {
+        va_list argscopy;
+        va_copy(argscopy, args);
+        m_parentLogger.messagev(options, format, argscopy);
+        va_end(argscopy);
+    }
+
+    DltContextData log;
+    if (!(options.m_flags & MessageOptions::ALREADY_LOGGED) &&
+        dlt_user_log_write_start((DltContext *)m_dltContext, &log, SyncEvoLevel2DLTLevel(options.m_level)) > 0) {
+        std::string buffer = StringPrintfV(format, args);
+        // Avoid almost empty messages. They are triggered by
+        // SyncEvolution to format the INFO output and don't add any
+        // valuable information to the DLT log.
+        if (!buffer.empty() &&
+            buffer != "\n") {
+            dlt_user_log_write_string(&log, buffer.c_str());
+            dlt_user_log_write_finish(&log);
+        }
+    }
+}
+
+int LoggerDLT::getCurrentDLTLogLevel()
+{
+    if (LoggerDLTInstance) {
+        for (int level = DLT_LOG_VERBOSE;
+             level > DLT_LOG_DEFAULT;
+             --level) {
+            DltContextData log;
+            // Emulates DLT_LOG(): logging active if dlt_user_log_write_start() returns something > 0.
+            // Otherwise discard the DltContextData without doing anything.
+            if (dlt_user_log_write_start((DltContext *)LoggerDLTInstance->m_dltContext, &log, (DltLogLevelType)level) > 0) {
+                return level;
+            }
+        }
+    }
+    return DLT_LOG_DEFAULT;
+}
+
+SE_END_CXX
+
+#endif // USE_DLT
diff --git a/src/syncevo/LogDLT.h b/src/syncevo/LogDLT.h
new file mode 100644 (file)
index 0000000..f93e1dc
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2012 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_LOGDLT
+#define INCL_LOGDLT
+
+#include <config.h>
+
+#ifdef USE_DLT
+
+#include <syncevo/Logging.h>
+#include <syncevo/util.h>
+
+#include <syncevo/declarations.h>
+SE_BEGIN_CXX
+
+/**
+ * A logger which writes to DLT and passes log messages
+ * through to its parent.
+ */
+class LoggerDLT : public Logger
+{
+    Handle m_parentLogger;
+    // avoid dependency on dlt.h here
+    void *m_dltContext;
+
+public:
+    LoggerDLT(const char *appid, const char *description);
+    ~LoggerDLT();
+
+    virtual void messagev(const MessageOptions &options,
+                          const char *format,
+                          va_list args);
+
+    /**
+     * Extracts current log level from the LoggerDLT which was
+     * pushed onto the stack, DLT_LOG_DEFAULT if none active.
+     */
+    static int getCurrentDLTLogLevel();
+};
+
+SE_END_CXX
+
+#endif // USE_DLT
+#endif // INCL_LOGSYSLOG
index ca7666c..45640cc 100644 (file)
@@ -247,16 +247,18 @@ void LogRedirect::messagev(const MessageOptions &options,
 
     // check for other output first
     process();
-    // Choose output channel: SHOW goes to original stdout,
-    // everything else to stderr.
-    LoggerStdout::write(options.m_level == SHOW ?
-                        (m_out ? m_out : stdout) :
-                        (m_err ? m_err : stderr),
-                        options.m_level, getLevel(),
-                        options.m_prefix,
-                        options.m_processName,
-                        format,
-                        args);
+    if (!(options.m_flags & MessageOptions::ONLY_GLOBAL_LOG)) {
+        // Choose output channel: SHOW goes to original stdout,
+        // everything else to stderr.
+        LoggerStdout::write(options.m_level == SHOW ?
+                            (m_out ? m_out : stdout) :
+                            (m_err ? m_err : stderr),
+                            options.m_level, getLevel(),
+                            options.m_prefix,
+                            options.m_processName,
+                            format,
+                            args);
+    }
 }
 
 void LogRedirect::redirect(int original, FDs &fds) throw()
index f78ff9d..a2014e2 100644 (file)
@@ -84,10 +84,12 @@ void LoggerStdout::messagev(const MessageOptions &options,
                             const char *format,
                             va_list args)
 {
-    write(m_file, options.m_level, getLevel(),
-          options.m_prefix,
-          options.m_processName,
-          format, args);
+    if (!(options.m_flags & MessageOptions::ONLY_GLOBAL_LOG)) {
+        write(m_file, options.m_level, getLevel(),
+              options.m_prefix,
+              options.m_processName,
+              format, args);
+    }
 }
 
 SE_END_CXX
index 0e80947..837c882 100644 (file)
@@ -255,13 +255,15 @@ Logger::MessageOptions::MessageOptions(Level level,
                                        const std::string *prefix,
                                        const char *file,
                                        int line,
-                                       const char *function) :
+                                       const char *function,
+                                       int flags) :
     m_level(level),
     m_prefix(prefix),
     m_file(file),
     m_line(line),
     m_function(function),
-    m_processName(NULL)
+    m_processName(NULL),
+    m_flags(flags)
 {
 }
 
index dde9e32..ce9a249 100644 (file)
@@ -199,13 +199,29 @@ class Logger
         const char *m_function;
         /** name of the process which originally created the message, if different from current one */
         const std::string *m_processName;
+        /** additional flags */
+        int m_flags;
+
+        enum {
+            /**
+             * The message was written into a global log (syslog, dlt, ...)
+             * already. Such a message must not be logged again.
+             */
+            ALREADY_LOGGED = 1<<0,
+            /**
+             * The message must be written into a global log,
+             * but not to stdout.
+             */
+            ONLY_GLOBAL_LOG = 1<<1
+        };
 
         MessageOptions(Level level);
         MessageOptions(Level level,
                        const std::string *prefix,
                        const char *file,
                        int line,
-                       const char *function);
+                       const char *function,
+                       int flags = 0);
     };
 
     /**
index d157a19..13b0aaa 100644 (file)
@@ -73,6 +73,10 @@ using namespace std;
 #include <synthesis/SDK_util.h>
 #include <synthesis/san.h>
 
+#ifdef USE_DLT
+# include <dlt.h>
+#endif
+
 #include "test.h"
 
 #include <syncevo/declarations.h>
@@ -279,6 +283,9 @@ class LogDirLogger : public Logger
 {
     Logger::Handle m_parentLogger;     /**< the logger which was active before we started to intercept messages */
     boost::weak_ptr<LogDir> m_logdir;  /**< grants access to report and Synthesis engine */
+#ifdef USE_DLT
+    bool m_useDLT;                     /**< SyncEvolution and libsynthesis are logging to DLT */
+#endif
 
 public:
     LogDirLogger(const boost::weak_ptr<LogDir> &logdir);
@@ -930,6 +937,9 @@ private:
 LogDirLogger::LogDirLogger(const boost::weak_ptr<LogDir> &logdir) :
     m_parentLogger(Logger::instance()),
     m_logdir(logdir)
+#ifdef USE_DLT
+    , m_useDLT(getenv("SYNCEVOLUTION_USE_DLT") != NULL)
+#endif
 {
 }
 
@@ -958,8 +968,16 @@ void LogDirLogger::messagev(const MessageOptions &options,
     m_parentLogger.messagev(options, format, argscopy);
     va_end(argscopy);
 
-    boost::shared_ptr<LogDir> logdir = m_logdir.lock();
-    if (logdir) {
+    // Special handling of our own messages: include in sync report
+    // (always, because that is how we did it traditionally) and write
+    // to our own syncevolution-log.html (if not already logged).
+    //
+    // The TestLocalSync.testServerFailure and some others check that
+    // we record the child's error message in our sync report. If we
+    // don't then it shows up later marked as an "error on the target
+    // side", which is probably not what we want.
+    boost::shared_ptr<LogDir> logdir;
+    if ((bool)(logdir = m_logdir.lock())) {
         if (logdir->m_report &&
             options.m_level <= ERROR &&
             logdir->m_report->getError().empty()) {
@@ -971,7 +989,14 @@ void LogDirLogger::messagev(const MessageOptions &options,
             logdir->m_report->setError(error);
         }
 
-        if (logdir->m_client.getEngine().get()) {
+        if (!(options.m_flags & MessageOptions::ALREADY_LOGGED) &&
+#ifdef USE_DLT
+            // Don't send to  libsynthesis if using DLT,
+            // because then it would end up getting logged
+            // in DLT twice.
+            !m_useDLT &&
+#endif
+            logdir->m_client.getEngine().get()) {
             va_list argscopy;
             va_copy(argscopy, args);
             // Once to Synthesis log, with full debugging.
@@ -2646,23 +2671,77 @@ void SyncContext::getConfigXML(string &xml, string &configname)
         stringstream debug;
         bool logging = !m_sourceListPtr->getLogdir().empty();
         int loglevel = getLogLevel();
+#ifdef USE_DLT
+        const char *useDLT = getenv("SYNCEVOLUTION_USE_DLT");
+#else
+        static const char *useDLT = NULL;
+#endif
 
         debug <<
             "  <debug>\n"
             // logpath is a config variable set by SyncContext::doSync()
             "    <logpath>$(logpath)</logpath>\n"
-            "    <filename>" <<
-            LogfileBasename << "</filename>" <<
+            "    <filename>" << (useDLT ? "" : LogfileBasename) << "</filename>" <<
             "    <logflushmode>flush</logflushmode>\n"
-            "    <logformat>html</logformat>\n"
-            "    <folding>auto</folding>\n"
-            "    <timestamp>yes</timestamp>\n"
-            "    <timestampall>yes</timestampall>\n"
+            "    <logformat>" << (useDLT ? "dlt" : "html") << "</logformat>\n"
+            "    <folding>auto</folding>\n" <<
+            (useDLT ?
+             "    <timestamp>no</timestamp>\n"
+             "    <timestampall>no</timestampall>\n" :
+             "    <timestamp>yes</timestamp>\n"
+             "    <timestampall>yes</timestampall>\n") <<
             "    <timedsessionlognames>no</timedsessionlognames>\n"
             "    <subthreadmode>separate</subthreadmode>\n"
             "    <logsessionstoglobal>yes</logsessionstoglobal>\n"
             "    <singlegloballog>yes</singlegloballog>\n";
-        if (logging) {
+#ifdef USE_DLT
+        if (useDLT) {
+            const char *contexts[] = {
+                "PROT",
+                "SESS",
+                "ADMN",
+                "DATA",
+                "REMI",
+                "PARS",
+                "GEN",
+                "TRNS",
+                "SMLT",
+                "SYS"
+            };
+            BOOST_FOREACH (const char *context, contexts) {
+                // Help libsynthesis debuglogger.cpp set default log levels,
+                // based on our own one.
+                SE_LOG_DEBUG(NULL, "default libsynthesis DLT logging of %s = %s",
+                             context, useDLT);
+                setenv((std::string("LIBSYNTHESIS_") + context).c_str(),
+                       useDLT,
+                       false);
+            }
+
+            debug <<
+                // We have to enable all logging inside libsynthesis.
+                // The actual filtering then takes place inside DLT.
+                // Message logging is not supported.
+                "    <enable option=\"all\"/>\n"
+                // Allow logging outside of sessions.
+                "    <globallogs>yes</globallogs>\n"
+                // Don't try per-session logging, it all goes to DLT anyway.
+                "    <sessionlogs>yes</sessionlogs>\n"
+                ;
+
+            // Be extra verbose if currently enabled. Cannot be changed later on.
+            if (atoi(useDLT) > DLT_LOG_DEBUG) {
+                debug <<
+                    "    <enable option=\"userdata\"/>\n"
+                    "    <enable option=\"scripts\"/>\n";
+            }
+            if (atoi(useDLT) > DLT_LOG_DEBUG) {
+                debug <<
+                    "    <enable option=\"exotic\"/>\n";
+            }
+        } else
+#endif // USE_DLT
+            if (logging) {
             debug <<
                 "    <sessionlogs>yes</sessionlogs>\n"
                 "    <globallogs>yes</globallogs>\n";
index 04cb95d..391cc1d 100644 (file)
@@ -295,11 +295,13 @@ public:
         }
         boost::shared_ptr<ReadDir> dir (new ReadDir (backend_dir, false));
         string dirpath (backend_dir);
+        // Base name (= no dir, no .so suffix) mapping to full file
+        // name (including .so).
+        std::map<std::string, std::string> candidates;
         // scan directories for matching module names
         do {
             debug<<"Scanning backend libraries in " <<dirpath <<endl;
             BOOST_FOREACH (const string &entry, *dir) {
-                void *dlhandle;
                 if (isDir (dirpath + '/' + entry)) {
                     /* This is a 2-level dir, this corresponds to loading
                      * backends from current building directory. The library
@@ -311,25 +313,10 @@ public:
                     }
                     continue;
                 }
-                if (entry.rfind(".so") == entry.length()-3){
-
-                    // Open the shared object so that backend can register
-                    // itself. We keep that pointer, so never close the
-                    // module!
+                if (boost::ends_with(entry, ".so")) {
                     string fullpath = dirpath + '/' + entry;
                     fullpath = normalizePath(fullpath);
-                    // RTLD_LAZY is needed for the WebDAV backend, which
-                    // needs to do an explicit dlopen() of libneon in compatibility
-                    // mode before any of the neon functions can be resolved.
-                    dlhandle = dlopen(fullpath.c_str(), RTLD_LAZY|RTLD_GLOBAL);
-                    // remember which modules were found and which were not
-                    if (dlhandle) {
-                        debug<<"Loading backend library "<<entry<<endl;
-                        info<<"Loading backend library "<<fullpath<<endl;
-                        m_available.push_back(entry);
-                    } else {
-                        debug<<"Loading backend library "<<entry<<"failed "<< dlerror()<<endl;
-                    }
+                    candidates[entry.substr(0, entry.size() - 3)] = fullpath;
                 }
             }
             if (!dirs.empty()){
@@ -340,6 +327,53 @@ public:
                 break;
             }
         } while (true);
+
+        // Look at foo-<version> before foo. If there is more than
+        // one version and the version sorts lexically, the "highest"
+        // one will be checked first, too.
+        //
+        // The intention is to try loading syncebook-2 (with explicit
+        // library dependencies) first, then skip syncebook if loading
+        // of syncebook-2 succeeded. If loading of syncebook-2 fails
+        // due to missing libraries, we proceed to use syncebook.
+        BOOST_REVERSE_FOREACH (const StringPair &entry, candidates) {
+            const std::string &basename = entry.first;
+            const std::string &fullpath = entry.second;
+            std::string replacement;
+            std::string modname;
+            size_t offset = basename.rfind('-');
+            if (offset != basename.npos) {
+                modname = basename.substr(offset);
+            } else {
+                modname = basename;
+            }
+            BOOST_FOREACH (const std::string &l, m_available) {
+                if (boost::starts_with(l, modname)) {
+                    replacement = l;
+                    break;
+                }
+            }
+            if (!replacement.empty()) {
+                debug << "Skipping " << basename << " = " << fullpath << " because a more recent version of it was already loaded: " << replacement;
+                continue;
+            }
+
+            // Open the shared object so that backend can register
+            // itself. We keep that pointer, so never close the
+            // module!
+            // RTLD_LAZY is needed for the WebDAV backend, which
+            // needs to do an explicit dlopen() of libneon in compatibility
+            // mode before any of the neon functions can be resolved.
+            void *dlhandle = dlopen(fullpath.c_str(), RTLD_LAZY|RTLD_GLOBAL);
+            // remember which modules were found and which were not
+            if (dlhandle) {
+                debug<<"Loading backend library "<<basename<<endl;
+                info<<"Loading backend library "<<fullpath<<endl;
+                m_available.push_back(basename);
+            } else {
+                debug<<"Loading backend library "<<basename<<"failed "<< dlerror()<<endl;
+            }
+        }
 #endif
     }
     list<string> m_available;
index 57da24b..0f4628c 100644 (file)
@@ -163,8 +163,6 @@ void *findSymbols(const char *libname, int minver, int maxver,
 
 }
 
-#endif // EVOLUTION_COMPATIBILITY
-
 int EDSAbiHaveEbook, EDSAbiHaveEcal, EDSAbiHaveEdataserver;
 int EDSAbiHaveIcal;
 int SyncEvoHaveLibbluetooth;
@@ -179,7 +177,6 @@ extern "C" void EDSAbiWrapperInit()
         initialized = true;
     }
 
-#ifdef EVOLUTION_COMPATIBILITY
 # ifdef HAVE_EDS
     edshandle =
     findSymbols("libedataserver-1.2.so", 7, 16,
@@ -412,24 +409,8 @@ extern "C" void EDSAbiWrapperInit()
     }
     SyncEvoHaveLibbluetooth = EDSAbiWrapperSingleton.sdp_connect != 0;
 # endif
-#else // EVOLUTION_COMPATIBILITY
-# ifdef HAVE_EDS
-    EDSAbiHaveEdataserver = true;
-# endif
-# ifdef ENABLE_EBOOK
-    EDSAbiHaveEbook = true;
-# endif
-# ifdef ENABLE_ECAL
-    EDSAbiHaveEcal = true;
-# endif
-# ifdef ENABLE_ICAL
-    EDSAbiHaveIcal = true;
-# endif
-# ifdef ENABLE_BLUETOOTH
-    SyncEvoHaveLibbluetooth = true;
-# endif
-#endif // EVOLUTION_COMPATIBILITY
 }
+#endif // EVOLUTION_COMPATIBILITY
 
 extern "C" const char *EDSAbiWrapperInfo() { EDSAbiWrapperInit(); return lookupInfo.c_str(); }
 extern "C" const char *EDSAbiWrapperDebug() { EDSAbiWrapperInit(); return lookupDebug.c_str(); }
index 186fab2..bdf1595 100644 (file)
@@ -93,6 +93,8 @@
 extern "C" {
 #endif
 
+#ifdef EVOLUTION_COMPATIBILITY
+
 /** libebook, libecal, libedataserver available (currently checks for e_book_new/e_cal_new/e_source_group_peek_sources) */
 extern int EDSAbiHaveEbook, EDSAbiHaveEcal, EDSAbiHaveEdataserver;
 extern int EDSAbiHaveIcal;
@@ -100,7 +102,8 @@ extern int EDSAbiHaveIcal;
 /** libbluetooth available (checks sdp_connect()) */
 extern int SyncEvoHaveLibbluetooth;
 
-#ifdef EVOLUTION_COMPATIBILITY
+/** initialize pointers to EDS functions, if necessary; can be called multiple times */
+void EDSAbiWrapperInit();
 
 /**
  * This is a struct instead of a namespace because that allows
@@ -444,6 +447,23 @@ extern struct EDSAbiWrapper EDSAbiWrapperSingleton;
 
 #else /* EVOLUTION_COMPATIBILITY */
 
+// This is necessary because in C++, 1 && 1 triggers
+// a warning with some gcc versions.
+#ifdef __cplusplus
+# define EDS_ABI_HACK_TRUE true
+#else
+# define EDS_ABI_HACK_TRUE 1
+#endif
+
+# define EDSAbiHaveEbook EDS_ABI_HACK_TRUE
+# define EDSAbiHaveEcal EDS_ABI_HACK_TRUE
+# define EDSAbiHaveEdataserver EDS_ABI_HACK_TRUE
+# define EDSAbiHaveIcal EDS_ABI_HACK_TRUE
+# define SyncEvoHaveLibbluetooth EDS_ABI_HACK_TRUE
+
+
+# define EDSAbiWrapperInit()
+
 # if !defined(EDS_ABI_WRAPPER_NO_REDEFINE) && defined(HAVE_LIBICAL_R)
 #  ifdef ENABLE_ICAL
 #   ifndef LIBICAL_MEMFIXES
@@ -457,9 +477,6 @@ extern struct EDSAbiWrapper EDSAbiWrapperSingleton;
 # endif /* EDS_ABI_WRAPPER_NO_REDEFINE */
 #endif /* EVOLUTION_COMPATIBILITY */
 
-/** initialize pointers to EDS functions, if necessary; can be called multiple times */
-void EDSAbiWrapperInit();
-
 const char *EDSAbiWrapperInfo();
 const char *EDSAbiWrapperDebug();
 
index f5bd6a8..1794017 100644 (file)
@@ -49,6 +49,8 @@ src_syncevo_sources = \
   \
   src/syncevo/Logging.h \
   src/syncevo/Logging.cpp \
+  src/syncevo/LogDLT.h \
+  src/syncevo/LogDLT.cpp \
   src/syncevo/LogStdout.h \
   src/syncevo/LogStdout.cpp \
   src/syncevo/LogRedirect.h \
@@ -212,6 +214,7 @@ src_syncevo_libsyncevolution_la_LIBADD = \
   $(TRANSPORT_LIBS) \
   @LIBS@ \
   $(src_syncevo_ldadd) \
+  $(DLT_LIBS) \
   $(DBUS_LIBS) \
   $(NSS_LIBS)
 if ENABLE_MODULES
@@ -228,12 +231,13 @@ src_syncevo_libsyncevolution_la_CFLAGS = \
   $(SYNCEVO_WFLAGS)
 src_syncevo_libsyncevolution_la_CPPFLAGS = \
   $(src_syncevo_cppflags) \
+  $(DLT_CFLAGS) \
   $(DBUS_CFLAGS) \
   -DDATA_DIR=\""$(pkgdatadir)"\" \
   -DXML_CONFIG_DIR=\""$(datadir)/syncevolution/xml"\" \
   -DTEMPLATE_DIR=\""$(datadir)/syncevolution/templates"\" \
   -DLIBDIR=\""$(libdir)"\"
-src_syncevo_libsyncevolution_la_DEPENDENCIES = $(SYNTHESIS_DEP) $(src_syncevo_ldadd)
+src_syncevo_libsyncevolution_la_DEPENDENCIES = $(SYNTHESIS_DEP) $(filter %.la, $(src_syncevo_ldadd))
 
 # rule which is only relevant when compiling Synthesis in subdirectory
 src/build-synthesis/libsynthesissdk.la: $(SYNTHESIS_SUBDIR)/all
index 4f26bbb..e073aca 100644 (file)
@@ -140,13 +140,13 @@ DBUS_SERVICES_DIR = @DBUS_SERVICES_DIR@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
 DLLTOOL = @DLLTOOL@
+DLT_CFLAGS = @DLT_CFLAGS@
+DLT_LIBS = @DLT_LIBS@
 DSYMUTIL = @DSYMUTIL@
 DUMPBIN = @DUMPBIN@
 EASCLIENT_CFLAGS = @EASCLIENT_CFLAGS@
 EASCLIENT_DEPENDENCIES = @EASCLIENT_DEPENDENCIES@
 EASCLIENT_LIBS = @EASCLIENT_LIBS@
-EBOOKCONTACTS_CFLAGS = @EBOOKCONTACTS_CFLAGS@
-EBOOKCONTACTS_LIBS = @EBOOKCONTACTS_LIBS@
 EBOOK_CFLAGS = @EBOOK_CFLAGS@
 EBOOK_LIBS = @EBOOK_LIBS@
 EBOOK_VERSION_CFLAGS = @EBOOK_VERSION_CFLAGS@
@@ -321,6 +321,7 @@ SYNCEVOLUTION_CXXFLAGS = @SYNCEVOLUTION_CXXFLAGS@
 SYNCEVOLUTION_LDADD = @SYNCEVOLUTION_LDADD@
 SYNCEVOLUTION_LIBS = @SYNCEVOLUTION_LIBS@
 SYNCEVOLUTION_LOCALEDIR = @SYNCEVOLUTION_LOCALEDIR@
+SYNCEVO_DBUS_SERVER_ARGS = @SYNCEVO_DBUS_SERVER_ARGS@
 SYNCEVO_WFLAGS = @SYNCEVO_WFLAGS@
 SYNCSOURCES = @SYNCSOURCES@
 SYNTHESIS = @SYNTHESIS@
index 67e8026..678e359 100644 (file)
@@ -1,6 +1,28 @@
 # Generated by configure.  Do not edit.
-# git revision 5cd3c49d8e51eb76be24049234c64922bcc3654e
-# git tag libsynthesis_3.4.0.47+syncevolution-1-3-99-4
+# git revision 69de3861f0d3b98e0f5791baea7254cdb2e7bce5
+# git tag libsynthesis_3.4.0.47+syncevolution-1-3-99-6
+
+2013-10-29  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * configure.in:
+
+       autotools: bump Linux/SyncEvolution sub-version for DLT support
+
+2013-10-27  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/platform_adapters/linux/configfiles.cpp:
+
+       Linux: avoid expensive network hostname lookup (FDO #70771)
+
+2013-10-22  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * README.DLT:
+       * configure.in:
+       * src/Makefile.am.in:
+       * src/sysync/debuglogger.cpp:
+       * src/sysync/debuglogger.h:
+
+       logging: support DLT
 
 2013-07-11  Patrick Ohly  <patrick.ohly@intel.com>
 
        Initial Commit by Synthesis AG for Open Source libsynthesis
        3.2.0.25 and libsmltk
 
-hly@intel.com>
+:
+
+       CalDAV: fixed Google 404 workaround
+
+2012-03-09  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * Makefile.am:
+       * description:
+
+       packaging: added evolution and kde meta .deb packages
+
+2012-03-09  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/backends/kde/KDEPlatform.cpp:
+
+       KDE: use up-to-date version number in appinfo
+
+2012-03-08  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/SyncContext.cpp:
+       * test/test-dbus.py:
+
+       D-Bus test: interactive password request in local sync
+
+2012-03-06  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/CmdlineSyncClient.cpp:
+       * src/CmdlineSyncClient.h:
+       * src/backends/gnome/GNOMEPlatformRegister.cpp:
+       * src/backends/kde/KDEPlatformRegister.cpp:
+       * src/dbus/server/dbus-sync.cpp:
+       * src/dbus/server/dbus-sync.h:
+       * src/dbus/server/dbus-user-interface.cpp:
+       * src/dbus/server/dbus-user-interface.h:
+       * src/dbus/server/read-operations.cpp:
+       * src/dbus/server/read-operations.h:
+       * src/dbus/server/session.cpp:
+       * src/syncevo/Cmdline.cpp:
+       * src/syncevo/LocalTransportAgent.cpp:
+       * src/syncevo/SyncConfig.cpp:
+       * src/syncevo/SyncConfig.h:
+       * src/syncevo/SyncContext.cpp:
+       * src/syncevo/SyncContext.h:
+       * src/syncevo/UserInterface.cpp:
+       * src/syncevo/UserInterface.h:
+       * src/syncevo/syncevo.am:
+       * src/syncevo/util.h:
+
+       SyncContext + ConfigUserInterface: code refactoring
+
+2012-03-08  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/backends/activesync/ActiveSyncSourceRegister.cpp:
+       * src/backends/addressbook/AddressBookSourceRegister.cpp:
+       * src/backends/akonadi/AkonadiSyncSourceRegister.cpp:
+       * src/backends/evolution/EvolutionCalendarSourceRegister.cpp:
+       * src/backends/evolution/EvolutionContactSourceRegister.cpp:
+       * src/backends/file/FileSyncSourceRegister.cpp:
+       * src/backends/kcalextended/KCalExtendedSourceRegister.cpp:
+       * src/backends/maemo/MaemoCalendarSourceRegister.cpp:
+       * src/backends/qtcontacts/QtContactsSourceRegister.cpp:
+       * src/backends/sqlite/SQLiteContactSourceRegister.cpp:
+       * src/backends/webdav/WebDAVSourceRegister.cpp:
+       * src/backends/xmlrpc/XMLRPCSyncSourceRegister.cpp:
+       * src/dbus/server/read-operations.cpp:
+       * src/syncevo/Cmdline.cpp:
+       * src/syncevo/SyncSource.cpp:
+       * src/syncevo/SyncSource.h:
+
+       SyncSource: remove special RegisterSyncSource::InactiveSource
+       pointer
+
+2012-03-06  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * configure.ac:
+       * src/CmdlineSyncClient.cpp:
+       * src/backends/gnome/GNOMEPlatform.cpp:
+       * src/backends/gnome/GNOMEPlatform.h:
+       * src/backends/gnome/GNOMEPlatformRegister.cpp:
+       * src/backends/gnome/configure-sub.in:
+       * src/backends/gnome/gnome.am:
+       * src/backends/kde/KDEPlatform.cpp:
+       * src/backends/kde/KDEPlatform.h:
+       * src/backends/kde/KDEPlatformRegister.cpp:
+       * src/backends/kde/configure-sub.in:
+       * src/backends/kde/kde.am:
+       * src/dbus/server/dbus-user-interface.cpp:
+       * src/dbus/server/server.am:
+       * src/src.am:
+       * src/syncevo/Cmdline.cpp:
+       * src/syncevo/SyncConfig.cpp:
+       * src/syncevo/SyncConfig.h:
+       * src/syncevo/SyncContext.cpp:
+       * src/syncevo/SyncContext.h:
+       * src/syncevo/syncevo.am:
+       * test/sys.supp:
+
+       KDE + GNOME: moved keyring/kwallet and KDE init into modules
+
+2012-03-08  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/SyncConfig.h:
+       * src/syncevo/SyncContext.h:
+
+       SyncContext+SyncConfig: virtual destructor
+
+2012-03-07  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/sys.supp:
+
+       testing: valgrind suppressions for Debian Testing, part II
+
+2012-03-06  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/evo.supp:
+
+       evo.supp: ignore genuine leak in EDS
+
+2012-03-06  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/sys.supp:
+
+       sys.supp: ignore cond valgrind warning in libdb
+
+2012-03-07  Patrick Ohly  <patrick.ohly@intel.com>
+
+
+       Merge branch 'master' into pbap
+
+2012-03-06  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/syncevo/configs/scripting/04vcard-photo-inlining.xml:
+
+       sync: fixed inlining of EDS 3.4 PHOTO data
+
+2012-03-02  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/evo.supp:
+
+       Revert "testing: ignore real leak in libecal 3.2"
+
+2012-03-02  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/backends/evolution/EvolutionContactSource.cpp:
+       * src/backends/evolution/configure-sub.in:
+       * src/syncevo/eds_abi_wrapper.cpp:
+       * src/syncevo/eds_abi_wrapper.h:
+
+       EDS: added support for inlining local photo data in backup and
+       --export
+
+2012-03-02  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/dbus-session.sh:
+
+       dbus-session: updated auto-starting of EDS daemons
+
+2012-03-02  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/synccompare.pl:
+
+       synccompare: shorter data dump of PHOTO
+
+2012-03-02  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * src/backends/activesync/configure-sub.in:
+
+       ActiveSync: don't compile camel backend and eplugin
+
+2012-03-01  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/ClientTest.cpp:
+       * test/testcases/eds_event.ics.radicale.tem.patch:
+
+       Revert "testing: ignore Radicale detached recurrence issue"
+
+2012-03-02  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/resultchecker.py:
+
+       testing: fixed result checking for restart tests
+
+2012-03-02  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/runtests.py:
+
+       runtests.py: test combined contact/event sync with syncevohttp
+
+2012-02-13  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/ClientTest.cpp:
+       * test/ClientTest.h:
+       * test/runtests.py:
+
+       client-test: add Client::Sync::*::testTwoWayRestart
+
+2012-02-13  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/ClientTest.cpp:
+       * test/ClientTest.h:
+
+       CheckSyncReport: refactor check()
+
+2012-02-13  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/ClientTest.h:
+
+       SyncOptions: added comment to m_startCallback
+
+2012-02-13  Patrick Ohly  <patrick.ohly@intel.com>
+
+       * test/ClientTest.cpp:
+       * test/ClientTest.h:
+
+       ClientTest: refactored code for inserting and deleting items in
+       source test
+
+2012-02-13  Patrick Ohly  <patrick.ohly@intel.com>
 
        * src/syncevo/SyncContext.cpp:
        * src/syncevo/SyncContext.h:
index 63ea2e5..a7a5eba 100644 (file)
@@ -149,6 +149,8 @@ CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
+DLT_CFLAGS = @DLT_CFLAGS@
+DLT_LIBS = @DLT_LIBS@
 DSYMUTIL = @DSYMUTIL@
 DUMPBIN = @DUMPBIN@
 ECHO_C = @ECHO_C@
diff --git a/src/synthesis/README.DLT b/src/synthesis/README.DLT
new file mode 100644 (file)
index 0000000..2fc36fc
--- /dev/null
@@ -0,0 +1,90 @@
+GENIVI Diagnostic Log and Trace (DLT) support
+=============================================
+
+DLT is a logging mechanism defined by GENIVI. It supports the context
+of log message contexts (arbitrary groups, defined by the app or
+library) and levels (off, fatal, error, warning, information, debug,
+verbose). The log level can be set per context, using mechanisms
+provided by DLT (for example, interactively via DLT client connected
+to a system running the DLT daemon and apps using that daemon).
+
+If DLT support is enabled during compilation of libsynthesis (use
+--enable-dlt on Linux) and in the configuration (use "dlt" as
+"logformat" and ignore all other logging options), then libsynthesis
+uses DLT for logging instead of writing its own files.
+
+libsynthesis has no concept of a strictly ordered log level. Instead
+major categories are combined with minor ones, which allows enabling
+"more verbose" logging for some aspects of a major category while
+leaving "less verbose" ones disabled. When using DLT, a hard-coded
+mapping between minor categories and log level is used, so some
+flexibility is lost.
+
+The mapping is as follows:
+
+Context ID = Synthesis debug topic: description (from SySync_config_reference.pdf)
+
+PROT = "proto": SyncML protocol related information.
+SESS = "session": Session management related information.
+ADMN = "admin": Everything that has to do with administrative data (anchors,
+targets, map table).
+DATA = "data": Everything that has to do with handling user data (data objects).
+Actual user data will however be shown only if loglevel >= debug.
+REMI = "remoteinfo": This shows information delivered in the remote party's
+device information, such as manufacturer name, datatypes supported, fields supported
+etc.
+PARS = "parse": This shows information related to parsing and processing incoming
+data from the remote party. Actual user data will however be shown only if loglevel >=
+debug.
+GEN  = "generate": This shows information related to generating outgoing data for the remote
+party. Actual user data will however be shown only if loglevel >= debug.
+TRNS = "transp": Shows transport (http and TCP communication) related information.
+SMLT = "syncml_rtk": Messages generated by the SyncML Toolkit code.
+SYSY = "rest": Any other debug log message that does not fit in any of the above
+contexts.
+
+The default log level of each context can be set via env variables
+called LIBSYNTHESIS_<context ID>, with values from 0 (off) to 6
+(verbose).
+
+The log level of a message is derived from the other Synthesis debug topics:
+
+"error" => ERROR: error messages.
+
+"hot"=> INFO: most important information (of all topics). This should never
+be switched of (except when switching off debug logging completely).
+
+"userdata" => DEBUG: Anything that is user data. To create anonymized
+logs that do not show user's data, use a log level less than debug
+(and, depending on the database interface, "dbapi" as well, as it
+might show SQL commands revealing user data as well).
+
+"dbapi" => VERBOSE: Information related to accessing the database. For
+ODBC, this enables showing SQL statements issued to the database, for
+plugin datastores, this includes all communication with the plugins
+and also messages generated by the plugin itself (see "plugin" below).
+
+"plugin" => DEBUG: Messages generated by database adapter plugins.
+
+"scripts" => VERBOSE: This is useful to debug scripts, and shows each
+line of executed scripts (but only for enabled debug topics!). Switching
+this on can generate huge log files, so it should normally be switched
+off in productive environments.
+
+"expressions" => VERBOSE: Together with "scripts" this causes detailed
+step-by-step logging of script expression evaluation.
+
+"filter" => DEBUG. Information about data item filtering.
+
+"match" => VERBOSE: Information about matching data in slow sync. Note
+that together with "exotic" this can produce extremely large logs as
+matching is an O(N^2) operation, so use with care.
+
+"conflict" => DEBUG: Information about conflict resolution and data merging.
+
+"details" => increases log level by one. Enabling this option adds
+generally some more detail to the debug output.
+
+"exotic" => VERBOSE: Enabling this adds the highest level of exotic detail possible.
+This is usually only required to track down device interoperability issues or
+bugs in the server/config.
index f784e7e..2030561 100644 (file)
@@ -97,5 +97,8 @@
 /* libsynthesis.a linked statically */
 #undef UIAPI_LINKED
 
+/* "optionally use GENIVI Diagnostic Log and Trace for logging" */
+#undef USE_DLT
+
 /* Version number of package */
 #undef VERSION
index ce25b3f..3a43f1a 100755 (executable)
@@ -754,6 +754,8 @@ LIBECAL_LIBS
 LIBECAL_CFLAGS
 LIBICAL_LIBS
 LIBICAL_CFLAGS
+DLT_LIBS
+DLT_CFLAGS
 PCRE_LIBS
 PCRE_CFLAGS
 SQLITE3_LIBS
@@ -891,6 +893,7 @@ enable_warnings
 enable_debug_logs
 enable_sqlite
 enable_regex
+enable_dlt
 enable_libical
 enable_evolution_compatibility
 with_xmltok
@@ -916,6 +919,8 @@ SQLITE3_CFLAGS
 SQLITE3_LIBS
 PCRE_CFLAGS
 PCRE_LIBS
+DLT_CFLAGS
+DLT_LIBS
 LIBICAL_CFLAGS
 LIBICAL_LIBS
 LIBECAL_CFLAGS
@@ -1553,6 +1558,8 @@ Optional Features:
                           libsqlite3, enabled by default
   --enable-regex          enable regular expression support in scripts,
                           depends on libpcre, enabled by default
+  --enable-dlt            enable logging mode "dlt" = GENIVI Diagnostic Log
+                          and Trace
   --enable-libical        use libical (if necessary, the one in libecal) to
                           improve time zone support, enabled by default if
                           necessary libs are found
@@ -1604,6 +1611,8 @@ Some influential environment variables:
               linker flags for SQLITE3, overriding pkg-config
   PCRE_CFLAGS C compiler flags for PCRE, overriding pkg-config
   PCRE_LIBS   linker flags for PCRE, overriding pkg-config
+  DLT_CFLAGS  C compiler flags for DLT, overriding pkg-config
+  DLT_LIBS    linker flags for DLT, overriding pkg-config
   LIBICAL_CFLAGS
               C compiler flags for LIBICAL, overriding pkg-config
   LIBICAL_LIBS
@@ -2976,7 +2985,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE=synthesis
- VERSION=3.4.0.16.10
+ VERSION=3.4.0.16.11
 
 
 cat >>confdefs.h <<_ACEOF
@@ -5067,13 +5076,13 @@ if test "${lt_cv_nm_interface+set}" = set; then :
 else
   lt_cv_nm_interface="BSD nm"
   echo "int some_variable = 0;" > conftest.$ac_ext
-  (eval echo "\"\$as_me:5070: $ac_compile\"" >&5)
+  (eval echo "\"\$as_me:5079: $ac_compile\"" >&5)
   (eval "$ac_compile" 2>conftest.err)
   cat conftest.err >&5
-  (eval echo "\"\$as_me:5073: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+  (eval echo "\"\$as_me:5082: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
   (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
   cat conftest.err >&5
-  (eval echo "\"\$as_me:5076: output\"" >&5)
+  (eval echo "\"\$as_me:5085: output\"" >&5)
   cat conftest.out >&5
   if $GREP 'External.*some_variable' conftest.out > /dev/null; then
     lt_cv_nm_interface="MS dumpbin"
@@ -6279,7 +6288,7 @@ ia64-*-hpux*)
   ;;
 *-*-irix6*)
   # Find out which ABI we are using.
-  echo '#line 6282 "configure"' > conftest.$ac_ext
+  echo '#line 6291 "configure"' > conftest.$ac_ext
   if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -8334,11 +8343,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:8337: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:8346: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:8341: \$? = $ac_status" >&5
+   echo "$as_me:8350: \$? = $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.
@@ -8673,11 +8682,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:8676: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:8685: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:8680: \$? = $ac_status" >&5
+   echo "$as_me:8689: \$? = $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.
@@ -8778,11 +8787,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:8781: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:8790: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:8785: \$? = $ac_status" >&5
+   echo "$as_me:8794: \$? = $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
@@ -8833,11 +8842,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:8836: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:8845: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:8840: \$? = $ac_status" >&5
+   echo "$as_me:8849: \$? = $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
@@ -11217,7 +11226,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11220 "configure"
+#line 11229 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11313,7 +11322,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11316 "configure"
+#line 11325 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -13269,11 +13278,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:13272: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:13281: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:13276: \$? = $ac_status" >&5
+   echo "$as_me:13285: \$? = $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.
@@ -13368,11 +13377,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:13371: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:13380: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:13375: \$? = $ac_status" >&5
+   echo "$as_me:13384: \$? = $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
@@ -13420,11 +13429,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:13423: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:13432: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:13427: \$? = $ac_status" >&5
+   echo "$as_me:13436: \$? = $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
@@ -15039,6 +15048,91 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
+# Check whether --enable-dlt was given.
+if test "${enable_dlt+set}" = set; then :
+  enableval=$enable_dlt; enable_dlt=$enableval
+               test $enable_dlt = "yes" || test $enable_dlt = "no" || as_fn_error "invalid value of --enable-dlt: $enableval" "$LINENO" 5
+else
+  enable_dlt="no"
+fi
+
+if test "$enable_dlt" = "yes"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for DLT" >&5
+$as_echo_n "checking for DLT... " >&6; }
+
+if test -n "$PKG_CONFIG"; then
+    if test -n "$DLT_CFLAGS"; then
+        pkg_cv_DLT_CFLAGS="$DLT_CFLAGS"
+    else
+        if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"automotive-dlt\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "automotive-dlt") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_DLT_CFLAGS=`$PKG_CONFIG --cflags "automotive-dlt" 2>/dev/null`
+else
+  pkg_failed=yes
+fi
+    fi
+else
+       pkg_failed=untried
+fi
+if test -n "$PKG_CONFIG"; then
+    if test -n "$DLT_LIBS"; then
+        pkg_cv_DLT_LIBS="$DLT_LIBS"
+    else
+        if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"automotive-dlt\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "automotive-dlt") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_DLT_LIBS=`$PKG_CONFIG --libs "automotive-dlt" 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
+               DLT_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "automotive-dlt"`
+        else
+               DLT_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "automotive-dlt"`
+        fi
+       # Put the nasty error message in config.log where it belongs
+       echo "$DLT_PKG_ERRORS" >&5
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+                as_fn_error "dlt not found, required for --enable-dlt" "$LINENO" 5
+elif test $pkg_failed = untried; then
+       as_fn_error "dlt not found, required for --enable-dlt" "$LINENO" 5
+else
+       DLT_CFLAGS=$pkg_cv_DLT_CFLAGS
+       DLT_LIBS=$pkg_cv_DLT_LIBS
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+       USE_DLT=1
+fi
+
+$as_echo "#define USE_DLT 1" >>confdefs.h
+
+fi
+
 ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default"
 if test "x$ac_cv_header_zlib_h" = x""yes; then :
 
index 2827e51..cf6a488 100644 (file)
@@ -4,7 +4,7 @@ AC_INIT(src/sysync/engineinterface.cpp)
 AC_CONFIG_MACRO_DIR([m4])
 # four digit upstream version, one additional digit for
 # Linux/SyncEvolution specific extensions:
-AM_INIT_AUTOMAKE(synthesis, 3.4.0.16.10)
+AM_INIT_AUTOMAKE(synthesis, 3.4.0.16.11)
 AM_CONFIG_HEADER(config.h)
 AC_LIBTOOL_DLOPEN
 
@@ -72,6 +72,19 @@ else
 fi
 AC_DEFINE_UNQUOTED(ONOFF_REGEX_SUPPORT, $HAVE_PCRE, "regular expressions in scripts")
 
+AC_ARG_ENABLE(dlt,
+              AS_HELP_STRING([--enable-dlt],
+                             [enable logging mode "dlt" = GENIVI Diagnostic Log and Trace]),
+              [enable_dlt=$enableval
+               test $enable_dlt = "yes" || test $enable_dlt = "no" || AC_ERROR([invalid value of --enable-dlt: $enableval])],
+              [enable_dlt="no"])
+if test "$enable_dlt" = "yes"; then
+    PKG_CHECK_MODULES(DLT, automotive-dlt,
+                      [USE_DLT=1],
+                      [AC_ERROR([dlt not found, required for --enable-dlt])])
+    AC_DEFINE(USE_DLT, 1, "optionally use GENIVI Diagnostic Log and Trace for logging")
+fi
+
 AC_CHECK_HEADER(zlib.h, , [AC_ERROR(zlib.h not found.)])
 AC_CHECK_HEADER(xmltok/xmlparse.h, have_system_xmltok="yes")
 AC_CHECK_HEADER(expat.h, have_system_expat="yes")
index c401c1a..0d4f256 100644 (file)
@@ -71,6 +71,7 @@ libsynthesis_la_CFLAGS = \
        -I$(srcdir)/DB_interfaces/api_db/ \
        -I$(srcdir)/sysync_SDK/Sources/ \
        $(PCRE_CFLAGS) \
+       $(DLT_CFLAGS) \
        $(SQLITE3_CFLAGS) \
        $(ZLIB_CFLAGS) \
        $(XMLPARSE_CFLAGS) \
@@ -78,7 +79,7 @@ libsynthesis_la_CFLAGS = \
        $(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 -ldl -lpthread
+libsynthesis_la_LIBADD = $(PCRE_LIBS) $(DLT_LIBS) $(SQLITE3_LIBS) $(XMLPARSE_LIBS) $(LIBICAL_LIBS) $(LIBECAL_LIBS) libsmltk.la -lz -ldl -lpthread
 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
index df2f34a..347dbe3 100644 (file)
@@ -71,6 +71,7 @@ libsynthesis_la_CFLAGS = \
        -I$(srcdir)/DB_interfaces/api_db/ \
        -I$(srcdir)/sysync_SDK/Sources/ \
        $(PCRE_CFLAGS) \
+       $(DLT_CFLAGS) \
        $(SQLITE3_CFLAGS) \
        $(ZLIB_CFLAGS) \
        $(XMLPARSE_CFLAGS) \
@@ -78,7 +79,7 @@ libsynthesis_la_CFLAGS = \
        $(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 -ldl -lpthread
+libsynthesis_la_LIBADD = $(PCRE_LIBS) $(DLT_LIBS) $(SQLITE3_LIBS) $(XMLPARSE_LIBS) $(LIBICAL_LIBS) $(LIBECAL_LIBS) libsmltk.la -lz -ldl -lpthread
 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
index 8d4bbf8..9980f84 100644 (file)
@@ -412,6 +412,8 @@ CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
+DLT_CFLAGS = @DLT_CFLAGS@
+DLT_LIBS = @DLT_LIBS@
 DSYMUTIL = @DSYMUTIL@
 DUMPBIN = @DUMPBIN@
 ECHO_C = @ECHO_C@
@@ -585,6 +587,7 @@ libsynthesis_la_CFLAGS = \
        -I$(srcdir)/DB_interfaces/api_db/ \
        -I$(srcdir)/sysync_SDK/Sources/ \
        $(PCRE_CFLAGS) \
+       $(DLT_CFLAGS) \
        $(SQLITE3_CFLAGS) \
        $(ZLIB_CFLAGS) \
        $(XMLPARSE_CFLAGS) \
@@ -593,7 +596,7 @@ libsynthesis_la_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 -ldl -lpthread
+libsynthesis_la_LIBADD = $(PCRE_LIBS) $(DLT_LIBS) $(SQLITE3_LIBS) $(XMLPARSE_LIBS) $(LIBICAL_LIBS) $(LIBECAL_LIBS) libsmltk.la -lz -ldl -lpthread
 libsynthesis_la_LDFLAGS = -version-info $(ENGINE_CURRENT):$(ENGINE_REVISION):$(ENGINE_AGE) \
        -Wl,--version-script=$(srcdir)/synthesis-linker.map
 
index ca2bd26..67e9de2 100755 (executable)
@@ -231,7 +231,6 @@ lineartime_t getFileModificationDate(const char *aFileName)
 bool getLocalDeviceID(string &aURI)
 {
   char     szHostname[100];
-  struct hostent *pHostEnt=NULL;
   string hostName;
 
   // get name of own machine
@@ -239,12 +238,25 @@ bool getLocalDeviceID(string &aURI)
     hostName="_unknown_";
   }
   else {
+    // A network lookup of the domain name is not likely
+    // to yield any good result on most Linux consumer
+    // devices. It just causes a slowdown, in particular
+    // when the device is not currently connected (which
+    // does not necessarily prevent syncing, for example
+    // when using Bluetooth); 10 second delays have
+    // been observed while the network stack waits for
+    // a timeout (FDO #70771).
+    //
+    // To avoid that timeout, disable this code unconditionally.
+#if 0
+    struct hostent *pHostEnt=NULL;
     // get host entry
     pHostEnt = gethostbyname(szHostname);
     // return fully qualified name of machine as ID
     if (pHostEnt)
       hostName=pHostEnt->h_name; // DNS name of machine
     else
+#endif
       hostName=szHostname; // just name of machine
   }
   // generate URI from name
index be685d2..8f976d1 100755 (executable)
 #include "platform_thread.h"
 #endif
 
+#ifdef USE_DLT
+#include <dlt.h>
+#endif
+
 namespace sysync {
 
+#ifdef USE_DLT
+static bool DbgDLTInitialized;
+static DltContext DbgProtoContext;
+static DltContext DbgSessionContext;
+static DltContext DbgAdminContext;
+static DltContext DbgDataContext;
+static DltContext DbgRemoteInfoContext;
+static DltContext DbgParseContext;
+static DltContext DbgGenerateContext;
+static DltContext DbgTranspContext;
+static DltContext DbgSyncMLTKContext;
+static DltContext DbgDefaultContext;
+#endif
+
+
 #ifndef HARDCODED_CONFIG
 
 // debug format modes
@@ -32,6 +51,13 @@ cAppCharP const DbgOutFormatNames[numDbgOutFormats] = {
   "text",       // plain text format (but can be indented)
   "xml",        // XML format
   "html"        // HTML format
+#ifdef USE_DLT
+  // If DLT support is not enabled, then trying to uses it in a config
+  // will lead to a generic parse error. Might be good enough, although
+  // a dedicated error message about "DLT being disabled in this build"
+  // would be nicer.
+  , "dlt"         // GENIVI Diagnostic Log and Trace
+#endif
 };
 
 
@@ -733,6 +759,39 @@ string TDebugLoggerBase::dbg2Link(const TDbgLocation &aTDbgLoc, const string &aT
 
 #endif // SYDEBUG_LOCATION
 
+#ifdef USE_DLT
+static void DbgText2PlainText(const char *in, size_t len, std::string &out)
+{
+  const char *q=in;
+  const char *s=q;
+  const char *end=in + len;
+
+  while (q<end) {
+    if (*q=='&') {
+      if (end-q>=6 && strucmp(q,"&html;",6)==0) {
+        if (q>s) out.append(s,q-s);
+        // everything until next &html; must be filtered out
+        // - search next &html;
+        s=q=q+6;
+        while(q+6<=end && strucmp(q,"&html;",6)!=0) q++;
+        s=q=q+6;
+      }
+      else if (end-q>=4 && strucmp(q,"&sp;",4)==0) {
+        if (q>s) out.append(s,q-s);
+        s=q=q+4;
+        out += ' '; // convert to plain space
+      }
+      else
+        q++;
+    }
+    else {
+      q++;
+    }
+  }
+  if (q>s) out.append(s,q-s);
+}
+#endif // USE_DLT
+
 
 // output text to debug channel
 void TDebugLoggerBase::DebugPuts(TDBG_LOCATION_PROTO uInt32 aDbgMask, cAppCharP aText, stringSize aTextSize, bool aPreFormatted)
@@ -759,6 +818,72 @@ void TDebugLoggerBase::DebugPuts(TDBG_LOCATION_PROTO uInt32 aDbgMask, cAppCharP
         return; // stop all efforts here
       }
     }
+
+#ifdef USE_DLT
+    // DLT logging logs everything in one chunk
+    if (fDbgOptionsP->fOutputFormat == dbgfmt_dlt) {
+      DltContext *context = &DbgDefaultContext;
+      if (aDbgMask & DBG_PROTO) {
+        context = &DbgProtoContext;
+      }
+      else if (aDbgMask & DBG_SESSION) {
+        context = &DbgSessionContext;
+      }
+      else if (aDbgMask & DBG_ADMIN) {
+        context = &DbgAdminContext;
+      }
+      else if (aDbgMask & DBG_DATA) {
+        context = &DbgDataContext;
+      }
+      else if (aDbgMask & DBG_REMOTEINFO) {
+        context = &DbgRemoteInfoContext;
+      }
+      else if (aDbgMask & DBG_PARSE) {
+        context = &DbgParseContext;
+      }
+      else if (aDbgMask & DBG_GEN) {
+        context = &DbgGenerateContext;
+      }
+      else if (aDbgMask & DBG_TRANSP) {
+        context = &DbgTranspContext;
+      }
+      else if (aDbgMask & (DBG_RTK_SML|DBG_RTK_XPT)) {
+        context = &DbgSyncMLTKContext;
+      }
+
+      DltLogLevelType level = DLT_LOG_VERBOSE;
+      if (level > DLT_LOG_INFO &&
+          (aDbgMask & DBG_HOT)) {
+        level = DLT_LOG_INFO;
+      }
+      if (level > DLT_LOG_ERROR &&
+          (aDbgMask & DBG_ERROR)) {
+        level = DLT_LOG_ERROR;
+      }
+      if (level > DLT_LOG_DEBUG &&
+          (aDbgMask & (DBG_USERDATA|DBG_PLUGIN|DBG_FILTER|DBG_CONFLICT))) {
+        level = DLT_LOG_DEBUG;
+      }
+      if (level < DLT_LOG_VERBOSE &&
+          (aDbgMask & DBG_DETAILS)) {
+        level = (DltLogLevelType)((int)level + 1);
+      }
+      if ((aTextSize > 0 && strlen(aText) > aTextSize) ||
+          strstr(aText, "&html;") ||
+          strstr(aText, "&sp;")) {
+            // Must make a copy and potentially filter out html markup.
+        string buffer;
+        buffer.reserve(aTextSize);
+        DbgText2PlainText(aText, aTextSize ? aTextSize : strlen(aText), buffer);
+        DLT_LOG(*context, level, DLT_STRING(buffer.c_str()));
+      } else {
+        // Fast path: log directly.
+        DLT_LOG(*context, level, DLT_STRING(aText));
+      }
+      return;
+    }
+#endif // USE_DLT
+
     // dissect into lines
     cAppCharP end=aTextSize ? aText+aTextSize : NULL;
     bool firstLine=true;
@@ -1325,11 +1450,47 @@ void TDebugLoggerBase::internalCloseBlocks(TDBG_LOCATION_PROTO cAppCharP aBlockN
   }
 } // TDebugLoggerBase::internalCloseBlocks
 
+#ifdef USE_DLT
+static void RegisterContext(DltContext *aHandle, const char *aContextID, const char *aDescription)
+{
+  std::string envName = "LIBSYNTHESIS_";
+  envName += aContextID;
+  const char *value = getenv(envName.c_str());
+  if (value) {
+    // Explicit level.
+    DltLogLevelType level = (DltLogLevelType)atoi(value);
+    dlt_register_context_ll_ts(aHandle, aContextID, aDescription, level, DLT_TRACE_STATUS_OFF);
+  } else {
+    // Default level.
+    dlt_register_context(aHandle, aContextID, aDescription);
+  }
+}
+#endif // USE_DLT
 
 // start debugging output if needed and sets fOutStarted
 bool TDebugLoggerBase::DebugStartOutput(void)
 {
   if (!fOutStarted) {
+#ifdef USE_DLT
+    if (fDbgOptionsP && fDbgOptionsP->fOutputFormat==dbgfmt_dlt) {
+      // Register our logging contexts.
+      if (!DbgDLTInitialized) {
+        RegisterContext(&DbgProtoContext, "PROT", "SyncML protocol related information");
+        RegisterContext(&DbgSessionContext, "SESS", "session management related information");
+        RegisterContext(&DbgAdminContext, "ADMN", "verything that has to do with administrative data (anchors, targets, map table)");
+        RegisterContext(&DbgDataContext, "DATA", "Everything that has to do with handling user data (data objects). Actual user data will however be shown only if loglevel >= debug.");
+        RegisterContext(&DbgRemoteInfoContext, "REMI", "This shows information delivered in the remote party's device information, such as manufacturer name, datatypes supported, fields supported etc.");
+        RegisterContext(&DbgParseContext, "PARS", "This shows information related to parsing and processing incoming data from the remote party. Actual user data will however be shown only if loglevel >= debug.");
+        RegisterContext(&DbgGenerateContext, "GEN", "This shows information related to generating outgoing data for the remote party. Actual user data will however be shown only if loglevel >= debug.");
+        RegisterContext(&DbgTranspContext, "TRNS", "shows transport (http and TCP communication) related information");
+        RegisterContext(&DbgSyncMLTKContext, "SMLT", "messages generated by the SyncML Toolkit code");
+        RegisterContext(&DbgDefaultContext, "SYS", "any other libsynthesis debug log message that does not fit in any of the other contexts");
+        DbgDLTInitialized = true;
+      }
+      fOutStarted = true;
+    }
+    else
+#endif // USE_DLT
     if (fOutputLoggerP) {
       // using another logger, call it to start output
       fOutStarted = fOutputLoggerP->DebugStartOutput();
@@ -1396,6 +1557,23 @@ void TDebugLoggerBase::DebugFinalizeOutput(void)
 // Output single line to debug channel (includes indenting and other prefixing, but no further formatting)
 void TDebugLoggerBase::DebugPutLine(TDBG_LOCATION_PROTO cAppCharP aText, stringSize aTextSize, bool aPre)
 {
+#ifdef USE_DLT
+  if (fDbgOptionsP && fDbgOptionsP->fOutputFormat==dbgfmt_dlt) {
+    // One example where this gets called is DebugVOpen/CloseBlock()
+    // with lines prepared as if we are printing plain text. Use
+    // a fairly neutral log level here.
+    if (aText) {
+      if (aTextSize > 0 && aTextSize < strlen(aText)) {
+        string buffer(aText, aTextSize);
+        DLT_LOG(DbgDefaultContext, DLT_LOG_INFO, DLT_STRING(buffer.c_str()));
+      } else {
+        DLT_LOG(DbgDefaultContext, DLT_LOG_INFO, DLT_STRING(aText));
+      }
+    }
+    return;
+  }
+#endif // USE_DLT
+
   if (!aText || (!fDbgOutP && !fOutputLoggerP)) return;
   if (*aText) {
     // not an empty line
index a583365..3cc234e 100755 (executable)
@@ -30,6 +30,9 @@ typedef enum {
   dbgfmt_text,        ///< plain text format (but can be indented)
   dbgfmt_xml,         ///< XML format
   dbgfmt_html,        ///< HTML format
+#ifdef USE_DLT
+  dbgfmt_dlt,         ///< GENIVI Diagnostic Log and Trace
+#endif
   numDbgOutFormats
 } TDbgOutFormats;